task(F4): library providers - builtin catalogs (event/architecture/landscape 15 blocks each), user-library and global-library via LibraryProviderExtension, panel UI with existing Drop-Channel

This commit is contained in:
Agent Zero
2026-08-28 23:20:11 +02:00
parent ec7cb4043b
commit 2efbbf9bd2
11 changed files with 2093 additions and 1 deletions
@@ -0,0 +1,587 @@
{
"folderId": "cat-arch",
"label": "Architektur-Katalog",
"blocks": [
{
"id": "arch-1",
"name": "Tür 900",
"elements": [
{
"id": "a1a",
"type": "line",
"layerId": "layer-0",
"x": 0,
"y": 0,
"width": 0,
"height": 0,
"properties": {
"x1": 0,
"y1": 0,
"x2": 900,
"y2": 0
}
},
{
"id": "a1b",
"type": "arc",
"layerId": "layer-0",
"x": 0,
"y": 0,
"width": 1800,
"height": 1800,
"properties": {
"radius": 900,
"startAngle": 0,
"endAngle": 90
}
}
]
},
{
"id": "arch-2",
"name": "Doppel-Tür 1800",
"elements": [
{
"id": "a2a",
"type": "line",
"layerId": "layer-0",
"x": 0,
"y": 0,
"width": 0,
"height": 0,
"properties": {
"x1": -900,
"y1": 0,
"x2": -450,
"y2": 0
}
},
{
"id": "a2b",
"type": "arc",
"layerId": "layer-0",
"x": -900,
"y": 0,
"width": 900,
"height": 900,
"properties": {
"radius": 450,
"startAngle": 0,
"endAngle": 90
}
},
{
"id": "a2c",
"type": "line",
"layerId": "layer-0",
"x": 0,
"y": 0,
"width": 0,
"height": 0,
"properties": {
"x1": 450,
"y1": 0,
"x2": 900,
"y2": 0
}
},
{
"id": "a2d",
"type": "arc",
"layerId": "layer-0",
"x": 900,
"y": 0,
"width": 900,
"height": 900,
"properties": {
"radius": 450,
"startAngle": 90,
"endAngle": 180
}
}
]
},
{
"id": "arch-3",
"name": "Tür 1200",
"elements": [
{
"id": "a3a",
"type": "line",
"layerId": "layer-0",
"x": 0,
"y": 0,
"width": 0,
"height": 0,
"properties": {
"x1": 0,
"y1": 0,
"x2": 1200,
"y2": 0
}
},
{
"id": "a3b",
"type": "arc",
"layerId": "layer-0",
"x": 0,
"y": 0,
"width": 2400,
"height": 2400,
"properties": {
"radius": 1200,
"startAngle": 0,
"endAngle": 90
}
}
]
},
{
"id": "arch-4",
"name": "Fenster 1200",
"elements": [
{
"id": "a4a",
"type": "rect",
"layerId": "layer-0",
"x": 0,
"y": -30,
"width": 1200,
"height": 20,
"properties": {}
},
{
"id": "a4b",
"type": "rect",
"layerId": "layer-0",
"x": 0,
"y": 30,
"width": 1200,
"height": 20,
"properties": {}
}
]
},
{
"id": "arch-5",
"name": "Fenster 2400",
"elements": [
{
"id": "a5a",
"type": "rect",
"layerId": "layer-0",
"x": 0,
"y": -30,
"width": 2400,
"height": 20,
"properties": {}
},
{
"id": "a5b",
"type": "rect",
"layerId": "layer-0",
"x": 0,
"y": 30,
"width": 2400,
"height": 20,
"properties": {}
}
]
},
{
"id": "arch-6",
"name": "Wandstück 2m",
"elements": [
{
"id": "a6a",
"type": "rect",
"layerId": "layer-0",
"x": 0,
"y": 0,
"width": 2000,
"height": 240,
"properties": {
"fill": "#8a8f98"
}
}
]
},
{
"id": "arch-7",
"name": "Wandstück vertikal 2m",
"elements": [
{
"id": "a7a",
"type": "rect",
"layerId": "layer-0",
"x": 0,
"y": 0,
"width": 240,
"height": 2000,
"properties": {
"fill": "#8a8f98"
}
}
]
},
{
"id": "arch-8",
"name": "Treppe (8 Stufen)",
"elements": [
{
"id": "a8s0",
"type": "line",
"layerId": "layer-0",
"x": 0,
"y": 0,
"width": 0,
"height": 0,
"properties": {
"x1": -350,
"y1": 0,
"x2": -350,
"y2": 1200
}
},
{
"id": "a8s1",
"type": "line",
"layerId": "layer-0",
"x": 0,
"y": 0,
"width": 0,
"height": 0,
"properties": {
"x1": -250,
"y1": 0,
"x2": -250,
"y2": 1200
}
},
{
"id": "a8s2",
"type": "line",
"layerId": "layer-0",
"x": 0,
"y": 0,
"width": 0,
"height": 0,
"properties": {
"x1": -150,
"y1": 0,
"x2": -150,
"y2": 1200
}
},
{
"id": "a8s3",
"type": "line",
"layerId": "layer-0",
"x": 0,
"y": 0,
"width": 0,
"height": 0,
"properties": {
"x1": -50,
"y1": 0,
"x2": -50,
"y2": 1200
}
},
{
"id": "a8s4",
"type": "line",
"layerId": "layer-0",
"x": 0,
"y": 0,
"width": 0,
"height": 0,
"properties": {
"x1": 50,
"y1": 0,
"x2": 50,
"y2": 1200
}
},
{
"id": "a8s5",
"type": "line",
"layerId": "layer-0",
"x": 0,
"y": 0,
"width": 0,
"height": 0,
"properties": {
"x1": 150,
"y1": 0,
"x2": 150,
"y2": 1200
}
},
{
"id": "a8s6",
"type": "line",
"layerId": "layer-0",
"x": 0,
"y": 0,
"width": 0,
"height": 0,
"properties": {
"x1": 250,
"y1": 0,
"x2": 250,
"y2": 1200
}
},
{
"id": "a8s7",
"type": "line",
"layerId": "layer-0",
"x": 0,
"y": 0,
"width": 0,
"height": 0,
"properties": {
"x1": 350,
"y1": 0,
"x2": 350,
"y2": 1200
}
},
{
"id": "a8la",
"type": "line",
"layerId": "layer-0",
"x": 0,
"y": 0,
"width": 0,
"height": 0,
"properties": {
"x1": -450,
"y1": 0,
"x2": -450,
"y2": 1200
}
},
{
"id": "a8lb",
"type": "line",
"layerId": "layer-0",
"x": 0,
"y": 0,
"width": 0,
"height": 0,
"properties": {
"x1": 450,
"y1": 0,
"x2": 450,
"y2": 1200
}
}
]
},
{
"id": "arch-9",
"name": "Säule Ø50",
"elements": [
{
"id": "a9a",
"type": "circle",
"layerId": "layer-0",
"x": 0,
"y": 0,
"width": 500,
"height": 500,
"properties": {
"radius": 250,
"fill": "#9aa0a6"
}
}
]
},
{
"id": "arch-10",
"name": "Schreibtisch",
"elements": [
{
"id": "a10a",
"type": "rect",
"layerId": "layer-0",
"x": 0,
"y": 0,
"width": 1800,
"height": 800,
"properties": {
"fill": "#6b7280"
}
}
]
},
{
"id": "arch-11",
"name": "Bürostuhl",
"elements": [
{
"id": "a11a",
"type": "chair",
"layerId": "layer-0",
"x": 0,
"y": 0,
"width": 60,
"height": 60,
"properties": {
"fill": "#5a7d9a",
"outlineColor": "#2a5a99"
}
}
]
},
{
"id": "arch-12",
"name": "Sofa 3-Sitzer",
"elements": [
{
"id": "a12a",
"type": "rect",
"layerId": "layer-0",
"x": 0,
"y": 0,
"width": 2200,
"height": 900,
"properties": {
"fill": "#5a7d9a"
}
}
]
},
{
"id": "arch-13",
"name": "Einzelbett",
"elements": [
{
"id": "a13a",
"type": "rect",
"layerId": "layer-0",
"x": 0,
"y": 0,
"width": 900,
"height": 2000,
"properties": {
"fill": "#8fa3bf"
}
},
{
"id": "a13b",
"type": "rect",
"layerId": "layer-0",
"x": 0,
"y": -750,
"width": 700,
"height": 300,
"properties": {
"fill": "#d5dbdb"
}
}
]
},
{
"id": "arch-14",
"name": "Waschbecken",
"elements": [
{
"id": "a14a",
"type": "rect",
"layerId": "layer-0",
"x": 0,
"y": 0,
"width": 600,
"height": 450,
"properties": {}
},
{
"id": "a14b",
"type": "circle",
"layerId": "layer-0",
"x": 0,
"y": 0,
"width": 340,
"height": 340,
"properties": {
"radius": 170,
"fill": "#7f9db9"
}
}
]
},
{
"id": "arch-15",
"name": "Küchenzeile 2.4m",
"elements": [
{
"id": "a15a",
"type": "rect",
"layerId": "layer-0",
"x": 0,
"y": 0,
"width": 2400,
"height": 600,
"properties": {
"fill": "#3c4043"
}
},
{
"id": "a15p0",
"type": "circle",
"layerId": "layer-0",
"x": -1800,
"y": 0,
"width": 180,
"height": 180,
"properties": {
"radius": 90,
"fill": "#202124"
}
},
{
"id": "a15p1",
"type": "circle",
"layerId": "layer-0",
"x": -1320,
"y": 0,
"width": 180,
"height": 180,
"properties": {
"radius": 90,
"fill": "#202124"
}
},
{
"id": "a15p2",
"type": "circle",
"layerId": "layer-0",
"x": -840,
"y": 0,
"width": 180,
"height": 180,
"properties": {
"radius": 90,
"fill": "#202124"
}
},
{
"id": "a15p3",
"type": "circle",
"layerId": "layer-0",
"x": -360,
"y": 0,
"width": 180,
"height": 180,
"properties": {
"radius": 90,
"fill": "#202124"
}
}
]
}
]
}
@@ -0,0 +1,619 @@
{
"folderId": "cat-event",
"label": "Event-Katalog",
"blocks": [
{
"id": "evt-1",
"name": "Stuhl",
"elements": [
{
"id": "e1",
"type": "chair",
"layerId": "layer-0",
"x": 0,
"y": 0,
"width": 45,
"height": 45,
"properties": {
"fill": "#4a90d9",
"outlineColor": "#2a5a99"
}
}
]
},
{
"id": "evt-2",
"name": "Tisch rund 180cm",
"elements": [
{
"id": "e2a",
"type": "table",
"layerId": "layer-0",
"x": 0,
"y": 0,
"width": 1800,
"height": 1800,
"properties": {
"fill": "#8b7355"
}
}
]
},
{
"id": "evt-3",
"name": "Tisch rund 120cm",
"elements": [
{
"id": "e3a",
"type": "table",
"layerId": "layer-0",
"x": 0,
"y": 0,
"width": 1200,
"height": 1200,
"properties": {
"fill": "#8b7355"
}
}
]
},
{
"id": "evt-4",
"name": "Stehtisch 80cm",
"elements": [
{
"id": "e4a",
"type": "table",
"layerId": "layer-0",
"x": 0,
"y": 0,
"width": 800,
"height": 800,
"properties": {
"fill": "#a08f6a"
}
}
]
},
{
"id": "evt-5",
"name": "Bühne 3x2m",
"elements": [
{
"id": "e5a",
"type": "stage",
"layerId": "layer-0",
"x": 0,
"y": 0,
"width": 3000,
"height": 2000,
"properties": {}
}
]
},
{
"id": "evt-6",
"name": "Bühne 4x3m",
"elements": [
{
"id": "e6a",
"type": "stage",
"layerId": "layer-0",
"x": 0,
"y": 0,
"width": 4000,
"height": 3000,
"properties": {}
}
]
},
{
"id": "evt-7",
"name": "Podest 1x1m",
"elements": [
{
"id": "e7a",
"type": "stage",
"layerId": "layer-0",
"x": 0,
"y": 0,
"width": 1000,
"height": 1000,
"properties": {}
}
]
},
{
"id": "evt-8",
"name": "Sitzreihe (10 Stühle)",
"elements": [
{
"id": "e2",
"type": "chair",
"layerId": "layer-0",
"x": -405,
"y": 0,
"width": 45,
"height": 45,
"properties": {
"fill": "#4a90d9",
"outlineColor": "#2a5a99"
}
},
{
"id": "e3",
"type": "chair",
"layerId": "layer-0",
"x": -315,
"y": 0,
"width": 45,
"height": 45,
"properties": {
"fill": "#4a90d9",
"outlineColor": "#2a5a99"
}
},
{
"id": "e4",
"type": "chair",
"layerId": "layer-0",
"x": -225,
"y": 0,
"width": 45,
"height": 45,
"properties": {
"fill": "#4a90d9",
"outlineColor": "#2a5a99"
}
},
{
"id": "e5",
"type": "chair",
"layerId": "layer-0",
"x": -135,
"y": 0,
"width": 45,
"height": 45,
"properties": {
"fill": "#4a90d9",
"outlineColor": "#2a5a99"
}
},
{
"id": "e6",
"type": "chair",
"layerId": "layer-0",
"x": -45,
"y": 0,
"width": 45,
"height": 45,
"properties": {
"fill": "#4a90d9",
"outlineColor": "#2a5a99"
}
},
{
"id": "e7",
"type": "chair",
"layerId": "layer-0",
"x": 45,
"y": 0,
"width": 45,
"height": 45,
"properties": {
"fill": "#4a90d9",
"outlineColor": "#2a5a99"
}
},
{
"id": "e8",
"type": "chair",
"layerId": "layer-0",
"x": 135,
"y": 0,
"width": 45,
"height": 45,
"properties": {
"fill": "#4a90d9",
"outlineColor": "#2a5a99"
}
},
{
"id": "e9",
"type": "chair",
"layerId": "layer-0",
"x": 225,
"y": 0,
"width": 45,
"height": 45,
"properties": {
"fill": "#4a90d9",
"outlineColor": "#2a5a99"
}
},
{
"id": "e10",
"type": "chair",
"layerId": "layer-0",
"x": 315,
"y": 0,
"width": 45,
"height": 45,
"properties": {
"fill": "#4a90d9",
"outlineColor": "#2a5a99"
}
},
{
"id": "e11",
"type": "chair",
"layerId": "layer-0",
"x": 405,
"y": 0,
"width": 45,
"height": 45,
"properties": {
"fill": "#4a90d9",
"outlineColor": "#2a5a99"
}
}
]
},
{
"id": "evt-9",
"name": "Bankett-Rundtisch (8 Stühle)",
"elements": [
{
"id": "e9a",
"type": "circle",
"layerId": "layer-0",
"x": 0,
"y": 0,
"width": 1800,
"height": 1800,
"properties": {
"radius": 900,
"fill": "#8b7355"
}
},
{
"id": "e12",
"type": "chair",
"layerId": "layer-0",
"x": 1200,
"y": 0,
"width": 45,
"height": 45,
"properties": {
"fill": "#4a90d9",
"outlineColor": "#2a5a99"
}
},
{
"id": "e13",
"type": "chair",
"layerId": "layer-0",
"x": 848,
"y": 848,
"width": 45,
"height": 45,
"properties": {
"fill": "#4a90d9",
"outlineColor": "#2a5a99"
}
},
{
"id": "e14",
"type": "chair",
"layerId": "layer-0",
"x": 0,
"y": 1200,
"width": 45,
"height": 45,
"properties": {
"fill": "#4a90d9",
"outlineColor": "#2a5a99"
}
},
{
"id": "e15",
"type": "chair",
"layerId": "layer-0",
"x": -848,
"y": 848,
"width": 45,
"height": 45,
"properties": {
"fill": "#4a90d9",
"outlineColor": "#2a5a99"
}
},
{
"id": "e16",
"type": "chair",
"layerId": "layer-0",
"x": -1200,
"y": 0,
"width": 45,
"height": 45,
"properties": {
"fill": "#4a90d9",
"outlineColor": "#2a5a99"
}
},
{
"id": "e17",
"type": "chair",
"layerId": "layer-0",
"x": -848,
"y": -848,
"width": 45,
"height": 45,
"properties": {
"fill": "#4a90d9",
"outlineColor": "#2a5a99"
}
},
{
"id": "e18",
"type": "chair",
"layerId": "layer-0",
"x": 0,
"y": -1200,
"width": 45,
"height": 45,
"properties": {
"fill": "#4a90d9",
"outlineColor": "#2a5a99"
}
},
{
"id": "e19",
"type": "chair",
"layerId": "layer-0",
"x": 848,
"y": -848,
"width": 45,
"height": 45,
"properties": {
"fill": "#4a90d9",
"outlineColor": "#2a5a99"
}
}
]
},
{
"id": "evt-10",
"name": "Tischgruppe (4 Stühle)",
"elements": [
{
"id": "e10a",
"type": "rect",
"layerId": "layer-0",
"x": 0,
"y": 0,
"width": 1600,
"height": 800,
"properties": {
"fill": "#8b7355"
}
},
{
"id": "e20",
"type": "chair",
"layerId": "layer-0",
"x": -400,
"y": -580,
"width": 45,
"height": 45,
"properties": {
"fill": "#4a90d9",
"outlineColor": "#2a5a99"
}
},
{
"id": "e21",
"type": "chair",
"layerId": "layer-0",
"x": 400,
"y": -580,
"width": 45,
"height": 45,
"properties": {
"fill": "#4a90d9",
"outlineColor": "#2a5a99"
}
},
{
"id": "e22",
"type": "chair",
"layerId": "layer-0",
"x": -400,
"y": 580,
"width": 45,
"height": 45,
"properties": {
"fill": "#4a90d9",
"outlineColor": "#2a5a99"
}
},
{
"id": "e23",
"type": "chair",
"layerId": "layer-0",
"x": 400,
"y": 580,
"width": 45,
"height": 45,
"properties": {
"fill": "#4a90d9",
"outlineColor": "#2a5a99"
}
}
]
},
{
"id": "evt-11",
"name": "Flipchart",
"elements": [
{
"id": "e11a",
"type": "rect",
"layerId": "layer-0",
"x": 0,
"y": 0,
"width": 700,
"height": 500,
"properties": {
"fill": "#546b7a"
}
},
{
"id": "e11b",
"type": "line",
"layerId": "layer-0",
"x": 0,
"y": 0,
"width": 0,
"height": 0,
"properties": {
"x1": 0,
"y1": 250,
"x2": 0,
"y2": 500
}
}
]
},
{
"id": "evt-12",
"name": "Pinnwand 120cm",
"elements": [
{
"id": "e12a",
"type": "rect",
"layerId": "layer-0",
"x": 0,
"y": 0,
"width": 1200,
"height": 150,
"properties": {
"fill": "#7a6550"
}
}
]
},
{
"id": "evt-13",
"name": "Kaffeetafel 2m",
"elements": [
{
"id": "e13a",
"type": "rect",
"layerId": "layer-0",
"x": 0,
"y": 0,
"width": 2000,
"height": 600,
"properties": {
"fill": "#6b5340"
}
}
]
},
{
"id": "evt-14",
"name": "Garderobe 1m",
"elements": [
{
"id": "e14a",
"type": "rect",
"layerId": "layer-0",
"x": 0,
"y": 0,
"width": 1000,
"height": 300,
"properties": {}
},
{
"id": "e14h0",
"type": "circle",
"layerId": "layer-0",
"x": -300,
"y": 0,
"width": 180,
"height": 180,
"properties": {
"radius": 90
}
},
{
"id": "e14h1",
"type": "circle",
"layerId": "layer-0",
"x": -150,
"y": 0,
"width": 180,
"height": 180,
"properties": {
"radius": 90
}
},
{
"id": "e14h2",
"type": "circle",
"layerId": "layer-0",
"x": 0,
"y": 0,
"width": 180,
"height": 180,
"properties": {
"radius": 90
}
},
{
"id": "e14h3",
"type": "circle",
"layerId": "layer-0",
"x": 150,
"y": 0,
"width": 180,
"height": 180,
"properties": {
"radius": 90
}
},
{
"id": "e14h4",
"type": "circle",
"layerId": "layer-0",
"x": 300,
"y": 0,
"width": 180,
"height": 180,
"properties": {
"radius": 90
}
}
]
},
{
"id": "evt-15",
"name": "Teppichläufer 2m",
"elements": [
{
"id": "e15a",
"type": "rect",
"layerId": "layer-0",
"x": 0,
"y": 0,
"width": 2000,
"height": 200,
"properties": {
"fill": "#7a5230"
}
}
]
}
]
}
@@ -0,0 +1,406 @@
{
"folderId": "cat-land",
"label": "Landschafts-Katalog",
"blocks": [
{
"id": "land-1",
"name": "Baum (groß)",
"elements": [
{
"id": "l1a",
"type": "circle",
"layerId": "layer-0",
"x": 0,
"y": -200,
"width": 2200,
"height": 2200,
"properties": {
"radius": 1100,
"fill": "#6aa84f"
}
},
{
"id": "l1b",
"type": "rect",
"layerId": "layer-0",
"x": 0,
"y": 600,
"width": 200,
"height": 800,
"properties": {
"fill": "#8b5a2b"
}
}
]
},
{
"id": "land-2",
"name": "Baum (mittel)",
"elements": [
{
"id": "l2a",
"type": "circle",
"layerId": "layer-0",
"x": 0,
"y": -150,
"width": 1500,
"height": 1500,
"properties": {
"radius": 750,
"fill": "#6aa84f"
}
},
{
"id": "l2b",
"type": "rect",
"layerId": "layer-0",
"x": 0,
"y": 450,
"width": 150,
"height": 600,
"properties": {
"fill": "#8b5a2b"
}
}
]
},
{
"id": "land-3",
"name": "Strauch",
"elements": [
{
"id": "l3a",
"type": "circle",
"layerId": "layer-0",
"x": 0,
"y": 0,
"width": 1000,
"height": 1000,
"properties": {
"radius": 500,
"fill": "#85b75f"
}
}
]
},
{
"id": "land-4",
"name": "Hecke horizontal 4m",
"elements": [
{
"id": "l4a",
"type": "rect",
"layerId": "layer-0",
"x": 0,
"y": 0,
"width": 4000,
"height": 500,
"properties": {
"fill": "#4c7a3f"
}
}
]
},
{
"id": "land-5",
"name": "Hecke vertikal 4m",
"elements": [
{
"id": "l5a",
"type": "rect",
"layerId": "layer-0",
"x": 0,
"y": 0,
"width": 500,
"height": 4000,
"properties": {
"fill": "#4c7a3f"
}
}
]
},
{
"id": "land-6",
"name": "Blumenbeet",
"elements": [
{
"id": "l6a",
"type": "circle",
"layerId": "layer-0",
"x": 0,
"y": 0,
"width": 1600,
"height": 1600,
"properties": {
"radius": 800,
"fill": "#c76fb6"
}
},
{
"id": "l6b",
"type": "circle",
"layerId": "layer-0",
"x": 0,
"y": 0,
"width": 600,
"height": 600,
"properties": {
"radius": 300,
"fill": "#e6a23c"
}
}
]
},
{
"id": "land-7",
"name": "Teich",
"elements": [
{
"id": "l7a",
"type": "circle",
"layerId": "layer-0",
"x": 0,
"y": 0,
"width": 3000,
"height": 3000,
"properties": {
"radius": 1500,
"fill": "#4a90d9"
}
},
{
"id": "l7b",
"type": "circle",
"layerId": "layer-0",
"x": 0,
"y": 100,
"width": 2700,
"height": 2700,
"properties": {
"radius": 1350,
"fill": "#5fa8e0"
}
}
]
},
{
"id": "land-8",
"name": "Rasenfläche 5x3m",
"elements": [
{
"id": "l8a",
"type": "rect",
"layerId": "layer-0",
"x": 0,
"y": 0,
"width": 5000,
"height": 3000,
"properties": {
"fill": "#7cb342"
}
}
]
},
{
"id": "land-9",
"name": "Bodenplatte",
"elements": [
{
"id": "l9a",
"type": "rect",
"layerId": "layer-0",
"x": 0,
"y": 0,
"width": 1200,
"height": 1200,
"properties": {
"fill": "#b8a888"
}
}
]
},
{
"id": "land-10",
"name": "Weg (Gerade)",
"elements": [
{
"id": "l10a",
"type": "rect",
"layerId": "layer-0",
"x": 0,
"y": 0,
"width": 600,
"height": 4000,
"properties": {
"fill": "#b8a888"
}
}
]
},
{
"id": "land-11",
"name": "Sonnenliege",
"elements": [
{
"id": "l11a",
"type": "rect",
"layerId": "layer-0",
"x": 0,
"y": 0,
"width": 600,
"height": 2000,
"properties": {
"fill": "#d2b48c"
}
}
]
},
{
"id": "land-12",
"name": "Feuerschale",
"elements": [
{
"id": "l12a",
"type": "circle",
"layerId": "layer-0",
"x": 0,
"y": 0,
"width": 1200,
"height": 1200,
"properties": {
"radius": 600,
"fill": "#5a5a5a"
}
},
{
"id": "l12b",
"type": "circle",
"layerId": "layer-0",
"x": 0,
"y": 0,
"width": 600,
"height": 600,
"properties": {
"radius": 300,
"fill": "#cc4125"
}
}
]
},
{
"id": "land-13",
"name": "Zaun 3m",
"elements": [
{
"id": "l13a",
"type": "line",
"layerId": "layer-0",
"x": 0,
"y": 0,
"width": 0,
"height": 0,
"properties": {
"x1": -1500,
"y1": 0,
"x2": -1500,
"y2": 900
}
},
{
"id": "l13b",
"type": "line",
"layerId": "layer-0",
"x": 0,
"y": 0,
"width": 0,
"height": 0,
"properties": {
"x1": 1500,
"y1": 0,
"x2": 1500,
"y2": 900
}
},
{
"id": "l13c",
"type": "line",
"layerId": "layer-0",
"x": 0,
"y": 0,
"width": 0,
"height": 0,
"properties": {
"x1": -1500,
"y1": 450,
"x2": 1500,
"y2": 450
}
}
]
},
{
"id": "land-14",
"name": "Laterne",
"elements": [
{
"id": "l14a",
"type": "circle",
"layerId": "layer-0",
"x": 0,
"y": -1000,
"width": 400,
"height": 400,
"properties": {
"radius": 200,
"fill": "#f5d76e"
}
},
{
"id": "l14b",
"type": "line",
"layerId": "layer-0",
"x": 0,
"y": 0,
"width": 0,
"height": 0,
"properties": {
"x1": 0,
"y1": -800,
"x2": 0,
"y2": 1000
}
},
{
"id": "l14c",
"type": "rect",
"layerId": "layer-0",
"x": 0,
"y": 1100,
"width": 300,
"height": 200,
"properties": {
"fill": "#5a5a5a"
}
}
]
},
{
"id": "land-15",
"name": "Gartenbank",
"elements": [
{
"id": "l15a",
"type": "rect",
"layerId": "layer-0",
"x": 0,
"y": 0,
"width": 1500,
"height": 400,
"properties": {
"fill": "#8b5a2b"
}
}
]
}
]
}
@@ -0,0 +1,24 @@
/**
* Task F4 Builtin-Bibliotheks-Plugin.
*
* Registriert den builtin-Katalog-Provider über die Plugin-API v2. Die Provider
* für user-library (zeichnungsscoped) und global-library (API/Token) sind als
* Fabriken (makeUserLibraryProvider / makeGlobalLibraryProvider) umgesetzt und
* werden vom UI je Token/Zeichnung instanziert.
*/
import type { PluginV2 } from '../../types';
import { builtinCatalogProvider } from './providers';
export const builtinLibraryPlugin: PluginV2 = {
manifest: {
id: 'builtin-library',
name: 'Block-Bibliothek',
version: '1.0.0',
author: 'WebCAD Project',
description: 'Bibliothek: builtin-Kataloge (Event/Architektur/Landschaft) als LibraryProvider (Task F4).',
category: 'library',
enabledByDefault: true,
permissions: ['storage'],
},
libraryProviders: [builtinCatalogProvider],
};
@@ -0,0 +1,161 @@
/**
* Task F4 Bibliotheksquellen als LibraryProviderExtension.
*
* Drei Quellen:
* - builtinCatalogProvider: statische JSON-Startersets (event/architecture/landscape)
* - makeUserLibraryProvider: zeichnungsscoped Blockdefinitionen (Drawing-Blöcke)
* - makeGlobalLibraryProvider: persistente globale Blockbibliothek (global-blocks API)
*
* Payload-Konvention: String-Payload = JSON-Array von CADElementen — identisch zum
* 'text/global-block-data' Drop-Kanal von BlockLibraryTree (F2/F3), damit der
* Canvas-Drop-Pfad (CanvasArea) ohne Änderung funktioniert.
*/
import catalogEvent from './catalogs/event.json';
import catalogArch from './catalogs/architecture.json';
import catalogLand from './catalogs/landscape.json';
import { generateBlockSvg } from '../../../utils/blockThumbnail';
import type { CADElement } from '../../../types/cad.types';
import type { LibraryProviderExtension, LibBlock, LibFolder } from '../../types';
import { getGlobalFolders, getGlobalBlocks, type GlobalBlock } from '../../../services/api';
interface CatalogBlock { id: string; name: string; elements: CADElement[]; }
interface CatalogFile { folderId: string; label: string; blocks: CatalogBlock[]; }
const CATALOGS: CatalogFile[] = [catalogEvent, catalogArch, catalogLand].map(
(c) => c as unknown as CatalogFile,
);
const thumbCache = new Map<string, string>();
function toLibBlock(folderId: string, block: CatalogBlock): LibBlock {
let thumbnail = thumbCache.get(block.id);
if (!thumbnail) {
thumbnail = generateBlockSvg(block.elements);
thumbCache.set(block.id, thumbnail);
}
return {
id: block.id,
folderId,
name: block.name,
thumbnail,
payload: JSON.stringify(block.elements),
};
}
/** Statischer builtin-Katalog: Event / Architektur / Landschaft Startersets. */
export const builtinCatalogProvider: LibraryProviderExtension = {
id: 'builtin-catalog',
label: 'Builtin-Kataloge',
async listFolders(): Promise<LibFolder[]> {
return CATALOGS.map((c) => ({ id: c.folderId, label: c.label, parentId: null }));
},
async listBlocks(folderId: string): Promise<LibBlock[]> {
const cat = CATALOGS.find((c) => c.folderId === folderId);
return cat ? cat.blocks.map((b) => toLibBlock(folderId, b)) : [];
},
async getBlock(id: string): Promise<LibBlock> {
for (const cat of CATALOGS) {
const found = cat.blocks.find((b) => b.id === id);
if (found) return toLibBlock(cat.folderId, found);
}
throw new Error(`Block not found: ${id}`);
},
};
export interface UserBlockLike {
id: string;
name: string;
elements?: unknown;
elements_json?: string;
thumbnail?: string | null;
drawing_id?: string;
description?: string | null;
category?: string;
}
function extractElements(block: UserBlockLike): CADElement[] {
try {
if (Array.isArray(block.elements)) return block.elements as CADElement[];
if (typeof block.elements_json === 'string') {
const parsed: unknown = JSON.parse(block.elements_json);
if (Array.isArray(parsed)) return parsed as CADElement[];
const wrapped = parsed as { elements?: unknown } | null;
if (wrapped && Array.isArray(wrapped.elements)) return wrapped.elements as CADElement[];
}
} catch {
// invalider Inhalt → leerer Block wird beim Auflisten gefiltert
}
return [];
}
/** Zeichnungsscoped Blöcke (Drawing-Blöcke) als Bibliothek anbinden. */
export function makeUserLibraryProvider(userBlocks: readonly UserBlockLike[]): LibraryProviderExtension {
const folderId = 'user-blocks';
const toBlock = (block: UserBlockLike): LibBlock => {
const elements = extractElements(block);
return {
id: `user:${block.id}`,
folderId,
name: block.name,
thumbnail: elements.length ? generateBlockSvg(elements) : undefined,
payload: elements.length ? JSON.stringify(elements) : undefined,
};
};
return {
id: 'user-library',
label: 'Benutzer-Bibliothek',
async listFolders(): Promise<LibFolder[]> {
return [{ id: folderId, label: 'Zeichnungs-Blöcke', parentId: null }];
},
async listBlocks(id: string): Promise<LibBlock[]> {
return id === folderId
? userBlocks.filter((b) => extractElements(b).length > 0).map(toBlock)
: [];
},
async getBlock(id: string): Promise<LibBlock> {
const found = userBlocks.find((b) => `user:${b.id}` === id && extractElements(b).length > 0);
if (found) return toBlock(found);
throw new Error(`Block not found: ${id}`);
},
};
}
/** Persistente globale Blockbibliothek über die global-blocks API anbinden. */
export function makeGlobalLibraryProvider(token: string): LibraryProviderExtension {
const toBlock = (block: GlobalBlock): LibBlock => ({
id: `global:${block.id}`,
folderId: block.folder_id ?? 'global-root',
name: block.name,
thumbnail: block.svg_data ?? undefined,
payload: block.block_data,
});
const loadAll = async (): Promise<GlobalBlock[]> => {
try {
return await getGlobalBlocks(token);
} catch {
return [];
}
};
return {
id: 'global-library',
label: 'Globale Bibliothek',
async listFolders(): Promise<LibFolder[]> {
try {
const folders = await getGlobalFolders(token);
return folders.map((f) => ({ id: f.id, label: f.name, parentId: f.parent_id }));
} catch {
return [];
}
},
async listBlocks(folderId: string): Promise<LibBlock[]> {
const blocks = await loadAll();
return blocks.filter((b) => (b.folder_id ?? 'global-root') === folderId).map(toBlock);
},
async getBlock(id: string): Promise<LibBlock> {
const blocks = await loadAll();
const found = blocks.find((b) => `global:${b.id}` === id);
if (found) return toBlock(found);
throw new Error(`Block not found: ${id}`);
},
};
}