sketchmark 0.2.4 → 0.2.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -29,6 +29,7 @@ end
29
29
  - [DSL Reference](#dsl-reference)
30
30
  - [Diagram Header](#diagram-header)
31
31
  - [Node Shapes](#node-shapes)
32
+ - [Icons](#icon-shape)
32
33
  - [Edges](#edges)
33
34
  - [Groups](#groups)
34
35
  - [Bare Groups](#bare-groups)
@@ -37,6 +38,7 @@ end
37
38
  - [Charts](#charts)
38
39
  - [Markdown Blocks](#markdown-blocks)
39
40
  - [Themes](#themes)
41
+ - [Style Directive](#style-directive)
40
42
  - [Typography](#typography)
41
43
  - [Animation Steps](#animation-steps)
42
44
  - [Layout System](#layout-system)
@@ -127,11 +129,15 @@ end
127
129
  | Keyword | Example | Description |
128
130
  |---|---|---|
129
131
  | `title` | `title label="My Diagram"` | Title shown above the diagram |
132
+ | `description` | `description "A brief summary"` | Diagram description (metadata) |
130
133
  | `layout` | `layout row` | Root layout direction: `row`, `column`, `grid` |
131
134
  | `config gap` | `config gap=60` | Gap between root-level items (default: 80) |
132
135
  | `config margin` | `config margin=40` | Outer canvas margin (default: 60) |
133
136
  | `config theme` | `config theme=ocean` | Global palette (see [Theme Palettes](#theme-palettes)) |
134
137
  | `config font` | `config font=caveat` | Diagram-wide font (see [Font System](#font-system)) |
138
+ | `config title-color` | `config title-color=#333` | Title text color |
139
+ | `config title-size` | `config title-size=20` | Title font size in px |
140
+ | `config title-weight` | `config title-weight=700` | Title font weight |
135
141
 
136
142
  ---
137
143
 
@@ -147,6 +153,7 @@ cylinder id label="..."
147
153
  parallelogram id label="..."
148
154
  text id label="..."
149
155
  image id label="..." url="https://..."
156
+ icon id label="..." name="prefix:name"
150
157
  ```
151
158
 
152
159
  **Common properties:**
@@ -159,6 +166,9 @@ image id label="..." url="https://..."
159
166
  | `height` | `height=55` | Override auto-height in px |
160
167
  | `fill` | `fill="#e8f4ff"` | Background fill color |
161
168
  | `stroke` | `stroke="#0044cc"` | Border color |
169
+ | `stroke-width` | `stroke-width=2` | Border thickness in px |
170
+ | `stroke-dash` | `stroke-dash=5,3` | Dashed border pattern (dash, gap) |
171
+ | `opacity` | `opacity=0.5` | Element opacity (0 to 1) |
162
172
  | `color` | `color="#003399"` | Text color |
163
173
  | `font` | `font=caveat` | Font family or built-in name |
164
174
  | `font-size` | `font-size=12` | Label font size in px |
@@ -170,7 +180,9 @@ image id label="..." url="https://..."
170
180
 
171
181
  > **`text` shape:** No border or background. Long labels auto word-wrap. Use `width=` to control the wrap width.
172
182
 
173
- > **`image` shape:** Renders an image clipped to a rounded rect. Requires `url=` property.
183
+ > **`image` shape:** Renders an image clipped to a rounded rect. Requires `url=` property. Label and border only shown when explicitly set.
184
+
185
+ > **`icon` shape:** Renders an icon from [Iconify](https://iconify.design/) (200,000+ open source icons). Requires `name=` property in `prefix:name` format (e.g. `mdi:database`). Defaults to `mdi` prefix if omitted. Use `color=` to tint the icon. Label and border only shown when explicitly set. Default size: 48x48.
174
186
 
175
187
  **Example:**
176
188
  ```
@@ -178,11 +190,42 @@ box gateway label="API Gateway" theme=warning width=150 height=55
178
190
  circle user label="User" fill="#e8f4ff" stroke="#0044cc" color="#003399"
179
191
  cylinder db label="PostgreSQL" theme=success width=140 height=65
180
192
  image logo label="Logo" url="https://example.com/logo.png" width=80 height=80
193
+ icon db label="Database" name="mdi:database" color="#1976D2"
194
+ icon cloud name="mdi:cloud" width=64 height=64
181
195
  text caption label="This auto-wraps across multiple lines." width=300
182
196
  ```
183
197
 
184
198
  ---
185
199
 
200
+ ### Icon Shape
201
+
202
+ Render any of 200,000+ open source vector icons from [Iconify](https://iconify.design/).
203
+
204
+ ```
205
+ icon id [label="..."] name="prefix:name" [color="#hex"] [width=N] [height=N]
206
+ ```
207
+
208
+ | Property | Example | Description |
209
+ |---|---|---|
210
+ | `name` | `name="mdi:database"` | Icon identifier in `prefix:name` format. Defaults to `mdi` prefix if omitted |
211
+ | `color` | `color="#1976D2"` | Icon tint color |
212
+ | `stroke` | `stroke="#333"` | Optional border (not shown by default) |
213
+ | `label` | `label="DB"` | Optional label (not shown by default) |
214
+ | `width` | `width=64` | Icon width (default: 48) |
215
+ | `height` | `height=64` | Icon height (default: 48) |
216
+
217
+ Browse available icons at [icon-sets.iconify.design](https://icon-sets.iconify.design/). Common prefixes: `mdi` (Material Design), `lucide`, `heroicons`, `tabler`, `ph` (Phosphor), `ri` (Remix), `carbon`.
218
+
219
+ **Example:**
220
+ ```
221
+ icon db label="Database" name="mdi:database" color="#1976D2"
222
+ icon cloud label="Cloud" name="mdi:cloud-outline" color="#FF9800" width=64 height=64
223
+ icon lock name="mdi:lock" color="#E53935"
224
+ icon user name="lucide:user"
225
+ ```
226
+
227
+ ---
228
+
186
229
  ### Edges
187
230
 
188
231
  ```
@@ -483,6 +526,19 @@ Apply to any element: `box a theme=primary`, `group g theme=muted`, `note n them
483
526
 
484
527
  ---
485
528
 
529
+ ### Style Directive
530
+
531
+ Apply styles to any element after it's defined, by targeting its id:
532
+
533
+ ```
534
+ box a label="Hello"
535
+ style a fill="#ff0000" stroke="#cc0000" font-size=16
536
+ ```
537
+
538
+ This merges with any existing styles on the element. Useful for separating layout from styling.
539
+
540
+ ---
541
+
486
542
  ### Typography
487
543
 
488
544
  Typography properties work on all text-bearing elements.
@@ -540,6 +596,7 @@ All actions work on **all element types** — nodes, groups, tables, notes, char
540
596
  | Option | Description |
541
597
  |---|---|
542
598
  | `duration=600` | Animation duration in ms |
599
+ | `delay=100` | Delay before animation starts in ms |
543
600
  | `dx=100` | X offset for `move` |
544
601
  | `dy=-80` | Y offset for `move` |
545
602
  | `factor=1.5` | Scale multiplier |
@@ -1,4 +1,4 @@
1
- export type NodeShape = 'box' | 'circle' | 'diamond' | 'hexagon' | 'triangle' | 'cylinder' | 'parallelogram' | 'text' | 'image';
1
+ export type NodeShape = 'box' | 'circle' | 'diamond' | 'hexagon' | 'triangle' | 'cylinder' | 'parallelogram' | 'text' | 'image' | 'icon';
2
2
  export type EdgeConnector = '->' | '<-' | '<->' | '-->' | '<-->' | '---' | '--';
3
3
  export type LayoutType = 'row' | 'column' | 'grid';
4
4
  export type AlignItems = 'start' | 'center' | 'end';
@@ -66,6 +66,7 @@ export interface ASTNode {
66
66
  label: string;
67
67
  groupId?: string;
68
68
  imageUrl?: string;
69
+ iconName?: string;
69
70
  width?: number;
70
71
  height?: number;
71
72
  theme?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/ast/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/ast/types.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,SAAS,GACjB,KAAK,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,UAAU,GACrD,UAAU,GAAG,eAAe,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;AAE7D,MAAM,MAAM,aAAa,GACrB,IAAI,GAAG,IAAI,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,IAAI,CAAC;AAGxD,MAAM,MAAM,UAAU,GAAS,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;AACzD,MAAM,MAAM,UAAU,GAAS,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAC;AAC1D,MAAM,MAAM,cAAc,GAAK,OAAO,GAAG,QAAQ,GAAG,KAAK,GAAG,eAAe,GAAG,cAAc,CAAC;AAC7F,MAAM,MAAM,eAAe,GAAI,WAAW,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,QAAQ,CAAC;AACtJ,MAAM,MAAM,gBAAgB,GAAG,UAAU,CAAA;AAEzC,MAAM,WAAW,UAAU;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;IACxC,aAAa,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,QAAQ,CAAC;IAC5C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAGD,MAAM,MAAM,aAAa,GACrB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,GAC7B;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAC7B;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAC7B;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAC5B;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAC7B;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAA;AAGpC,MAAM,MAAM,WAAW,GACnB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,GAC7B;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAC7B;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAC7B;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAC5B;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAC7B;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAA;AAEpC,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAC1D,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IACvD,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,UAAU,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACnD;AAED,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IACnD,SAAS,EAAE,aAAa,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACzC,MAAM,CAAC,EAAE,OAAO,CAAC;IAAC,aAAa,CAAC,EAAE,OAAO,CAAC;IAC1C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,UAAU,CAAC;CACpB;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAO,OAAO,CAAC;IACnB,EAAE,EAAS,MAAM,CAAC;IAClB,KAAK,EAAM,MAAM,CAAC;IAClB,QAAQ,EAAG,aAAa,EAAE,CAAC;IAC3B,MAAM,CAAC,EAAI,UAAU,CAAC;IACtB,OAAO,CAAC,EAAG,MAAM,CAAC;IAClB,OAAO,CAAC,EAAG,MAAM,CAAC;IAClB,GAAG,CAAC,EAAO,MAAM,CAAC;IAClB,KAAK,CAAC,EAAK,UAAU,CAAC;IACtB,OAAO,CAAC,EAAG,cAAc,CAAC;IAC1B,KAAK,CAAC,EAAK,MAAM,CAAC;IAClB,KAAK,CAAC,EAAK,UAAU,CAAC;IACtB,KAAK,CAAC,EAAK,MAAM,CAAC;IAClB,MAAM,CAAC,EAAI,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,eAAe,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IACtD,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAC9E,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,YAAY;IAAG,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,IAAI,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,EAAE,CAAC;CAAE;AAEjF,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,OAAO,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAC1B,SAAS,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;IACjE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,YAAY,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACpE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,UAAU,CAAC;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAG,QAAQ,GAAG,MAAM,CAAC;IACzB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAI,OAAO,CAAC;IAChB,EAAE,EAAM,MAAM,CAAC;IACf,KAAK,EAAG,MAAM,CAAC;IACf,IAAI,EAAI,WAAW,EAAE,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,UAAU,CAAC;CACpB;AAED,MAAM,WAAW,OAAO;IACtB,IAAI,EAAI,MAAM,CAAC;IACf,EAAE,EAAM,MAAM,CAAC;IACf,KAAK,EAAG,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAK,UAAU,CAAC;IACpB,EAAE,EAAO,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAG,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAG,MAAM,CAAC;IAChB,KAAK,CAAC,EAAG,UAAU,CAAC;CACrB;AAGD,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,SAAS,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IACtD,MAAM,EAAE,UAAU,CAAC;IACnB,KAAK,EAAG,OAAO,EAAE,CAAC;IAClB,KAAK,EAAG,OAAO,EAAE,CAAC;IAClB,MAAM,EAAE,QAAQ,EAAE,CAAC;IACnB,MAAM,EAAE,QAAQ,EAAE,CAAC;IACnB,KAAK,EAAE,OAAO,EAAE,CAAC;IACjB,KAAK,EAAG,OAAO,EAAE,CAAC;IAClB,MAAM,EAAE,QAAQ,EAAE,CAAC;IACnB,SAAS,EAAE,WAAW,EAAE,CAAC;IACzB,MAAM,EAAK,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACtC,MAAM,EAAK,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACtC,MAAM,EAAK,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC;IACrD,SAAS,EAAE,WAAW,EAAE,CAAC;CAC1B"}
package/dist/index.cjs CHANGED
@@ -19,6 +19,7 @@ const KEYWORDS = new Set([
19
19
  "parallelogram",
20
20
  "text",
21
21
  "image",
22
+ "icon",
22
23
  "group",
23
24
  "style",
24
25
  "step",
@@ -232,6 +233,7 @@ const SHAPES = [
232
233
  "parallelogram",
233
234
  "text",
234
235
  "image",
236
+ "icon",
235
237
  ];
236
238
  const CHART_TYPES = [
237
239
  "bar-chart",
@@ -422,7 +424,7 @@ function parse(src) {
422
424
  kind: "node",
423
425
  id,
424
426
  shape,
425
- label: props.label || id,
427
+ label: props.label || (shape === "image" || shape === "icon" ? "" : id),
426
428
  ...(groupId ? { groupId } : {}),
427
429
  ...(props.width ? { width: parseFloat(props.width) } : {}),
428
430
  ...(props.height ? { height: parseFloat(props.height) } : {}),
@@ -431,6 +433,8 @@ function parse(src) {
431
433
  };
432
434
  if (props.url)
433
435
  node.imageUrl = props.url;
436
+ if (props.name)
437
+ node.iconName = props.name;
434
438
  return node;
435
439
  }
436
440
  function parseEdge(fromId, connector, rest) {
@@ -499,7 +503,7 @@ function parse(src) {
499
503
  j++;
500
504
  }
501
505
  // Support multiline via literal \n in label string
502
- const rawLabel = props.label ?? id;
506
+ const rawLabel = props.label ?? "";
503
507
  return {
504
508
  kind: "note",
505
509
  id,
@@ -1278,6 +1282,7 @@ function buildSceneGraph(ast) {
1278
1282
  height: n.height,
1279
1283
  meta: n.meta,
1280
1284
  imageUrl: n.imageUrl,
1285
+ iconName: n.iconName,
1281
1286
  x: 0,
1282
1287
  y: 0,
1283
1288
  w: 0,
@@ -1504,6 +1509,10 @@ function sizeNode(n) {
1504
1509
  }
1505
1510
  break;
1506
1511
  }
1512
+ case "icon":
1513
+ n.w = n.w || 48;
1514
+ n.h = n.h || (n.label !== n.id ? 64 : 48); // extra height for label
1515
+ break;
1507
1516
  default:
1508
1517
  n.w = n.w || Math.max(MIN_W, Math.min(MAX_W, labelW));
1509
1518
  n.h = n.h || 52;
@@ -5099,6 +5108,58 @@ function renderShape$1(rc, n, palette) {
5099
5108
  }
5100
5109
  case "text":
5101
5110
  return [];
5111
+ case "icon": {
5112
+ if (n.iconName) {
5113
+ const [prefix, name] = n.iconName.includes(":")
5114
+ ? n.iconName.split(":", 2)
5115
+ : ["mdi", n.iconName];
5116
+ const iconColor = s.color
5117
+ ? encodeURIComponent(String(s.color))
5118
+ : encodeURIComponent(String(palette.nodeStroke));
5119
+ const iconSize = Math.min(n.w, n.h) - 4;
5120
+ const iconUrl = `https://api.iconify.design/${prefix}/${name}.svg?color=${iconColor}&width=${iconSize}&height=${iconSize}`;
5121
+ const img = document.createElementNS(NS, "image");
5122
+ img.setAttribute("href", iconUrl);
5123
+ img.setAttribute("x", String(n.x + 1));
5124
+ img.setAttribute("y", String(n.y + 1));
5125
+ img.setAttribute("width", String(n.w - 2));
5126
+ img.setAttribute("height", String(n.h - 2));
5127
+ img.setAttribute("preserveAspectRatio", "xMidYMid meet");
5128
+ if (s.opacity != null)
5129
+ img.setAttribute("opacity", String(s.opacity));
5130
+ // clip-path for rounded corners (same as image)
5131
+ const clipId = `clip-${n.id}`;
5132
+ const defs = document.createElementNS(NS, "defs");
5133
+ const clip = document.createElementNS(NS, "clipPath");
5134
+ clip.setAttribute("id", clipId);
5135
+ const rect = document.createElementNS(NS, "rect");
5136
+ rect.setAttribute("x", String(n.x + 1));
5137
+ rect.setAttribute("y", String(n.y + 1));
5138
+ rect.setAttribute("width", String(n.w - 2));
5139
+ rect.setAttribute("height", String(n.h - 2));
5140
+ rect.setAttribute("rx", "6");
5141
+ clip.appendChild(rect);
5142
+ defs.appendChild(clip);
5143
+ img.setAttribute("clip-path", `url(#${clipId})`);
5144
+ // only draw border when stroke is explicitly set
5145
+ const els = [defs, img];
5146
+ if (s.stroke) {
5147
+ els.push(rc.rectangle(n.x + 1, n.y + 1, n.w - 2, n.h - 2, {
5148
+ ...opts,
5149
+ fill: "none",
5150
+ }));
5151
+ }
5152
+ return els;
5153
+ }
5154
+ // fallback: placeholder square
5155
+ return [
5156
+ rc.rectangle(n.x + 1, n.y + 1, n.w - 2, n.h - 2, {
5157
+ ...opts,
5158
+ fill: "#e0e0e0",
5159
+ stroke: "#999999",
5160
+ }),
5161
+ ];
5162
+ }
5102
5163
  case "image": {
5103
5164
  if (n.imageUrl) {
5104
5165
  const img = document.createElementNS(NS, "image");
@@ -5121,11 +5182,15 @@ function renderShape$1(rc, n, palette) {
5121
5182
  clip.appendChild(rect);
5122
5183
  defs.appendChild(clip);
5123
5184
  img.setAttribute("clip-path", `url(#${clipId})`);
5124
- const border = rc.rectangle(n.x + 1, n.y + 1, n.w - 2, n.h - 2, {
5125
- ...opts,
5126
- fill: "none",
5127
- });
5128
- return [defs, img, border];
5185
+ // only draw border when stroke is explicitly set
5186
+ const els = [defs, img];
5187
+ if (s.stroke) {
5188
+ els.push(rc.rectangle(n.x + 1, n.y + 1, n.w - 2, n.h - 2, {
5189
+ ...opts,
5190
+ fill: "none",
5191
+ }));
5192
+ }
5193
+ return els;
5129
5194
  }
5130
5195
  return [
5131
5196
  rc.rectangle(n.x + 1, n.y + 1, n.w - 2, n.h - 2, {
@@ -5369,9 +5434,11 @@ function renderToSVG(sg, container, options = {}) {
5369
5434
  : verticalAlign === "bottom"
5370
5435
  ? nodeBodyBottom - blockH / 2
5371
5436
  : nodeBodyMid;
5372
- ng.appendChild(lines.length > 1
5373
- ? mkMultilineText(lines, textX, textCY, fontSize, fontWeight, textColor, textAnchor, lineHeight, nodeFont, letterSpacing)
5374
- : mkText(n.label, textX, textCY, fontSize, fontWeight, textColor, textAnchor, nodeFont, letterSpacing));
5437
+ if (n.label) {
5438
+ ng.appendChild(lines.length > 1
5439
+ ? mkMultilineText(lines, textX, textCY, fontSize, fontWeight, textColor, textAnchor, lineHeight, nodeFont, letterSpacing)
5440
+ : mkText(n.label, textX, textCY, fontSize, fontWeight, textColor, textAnchor, nodeFont, letterSpacing));
5441
+ }
5375
5442
  if (options.interactive) {
5376
5443
  ng.style.cursor = "pointer";
5377
5444
  ng.addEventListener("click", () => options.onNodeClick?.(n.id));
@@ -6069,6 +6136,50 @@ function renderShape(rc, ctx, n, palette, R) {
6069
6136
  break;
6070
6137
  case 'text':
6071
6138
  break; // no shape drawn
6139
+ case 'icon': {
6140
+ if (n.iconName) {
6141
+ const [prefix, name] = n.iconName.includes(':')
6142
+ ? n.iconName.split(':', 2)
6143
+ : ['mdi', n.iconName];
6144
+ const iconColor = s.color
6145
+ ? encodeURIComponent(String(s.color))
6146
+ : encodeURIComponent(String(palette.nodeStroke));
6147
+ const iconSize = Math.min(n.w, n.h) - 4;
6148
+ const iconUrl = `https://api.iconify.design/${prefix}/${name}.svg?color=${iconColor}&width=${iconSize}&height=${iconSize}`;
6149
+ const img = new Image();
6150
+ img.crossOrigin = 'anonymous';
6151
+ img.onload = () => {
6152
+ ctx.save();
6153
+ if (s.opacity != null)
6154
+ ctx.globalAlpha = Number(s.opacity);
6155
+ // clip-path for rounded corners (same as image)
6156
+ ctx.beginPath();
6157
+ const r = 6;
6158
+ ctx.moveTo(n.x + r, n.y);
6159
+ ctx.lineTo(n.x + n.w - r, n.y);
6160
+ ctx.quadraticCurveTo(n.x + n.w, n.y, n.x + n.w, n.y + r);
6161
+ ctx.lineTo(n.x + n.w, n.y + n.h - r);
6162
+ ctx.quadraticCurveTo(n.x + n.w, n.y + n.h, n.x + n.w - r, n.y + n.h);
6163
+ ctx.lineTo(n.x + r, n.y + n.h);
6164
+ ctx.quadraticCurveTo(n.x, n.y + n.h, n.x, n.y + n.h - r);
6165
+ ctx.lineTo(n.x, n.y + r);
6166
+ ctx.quadraticCurveTo(n.x, n.y, n.x + r, n.y);
6167
+ ctx.closePath();
6168
+ ctx.clip();
6169
+ ctx.drawImage(img, n.x + 1, n.y + 1, n.w - 2, n.h - 2);
6170
+ ctx.restore();
6171
+ // only draw border when stroke is explicitly set
6172
+ if (s.stroke) {
6173
+ rc.rectangle(n.x + 1, n.y + 1, n.w - 2, n.h - 2, { ...opts, fill: 'none' });
6174
+ }
6175
+ };
6176
+ img.src = iconUrl;
6177
+ }
6178
+ else {
6179
+ rc.rectangle(n.x + 1, n.y + 1, n.w - 2, n.h - 2, { ...opts, fill: '#e0e0e0', stroke: '#999999' });
6180
+ }
6181
+ return;
6182
+ }
6072
6183
  case 'image': {
6073
6184
  if (n.imageUrl) {
6074
6185
  const img = new Image();
@@ -6090,7 +6201,10 @@ function renderShape(rc, ctx, n, palette, R) {
6090
6201
  ctx.clip();
6091
6202
  ctx.drawImage(img, n.x + 1, n.y + 1, n.w - 2, n.h - 2);
6092
6203
  ctx.restore();
6093
- rc.rectangle(n.x + 1, n.y + 1, n.w - 2, n.h - 2, { ...opts, fill: 'none' });
6204
+ // only draw border when stroke is explicitly set
6205
+ if (s.stroke) {
6206
+ rc.rectangle(n.x + 1, n.y + 1, n.w - 2, n.h - 2, { ...opts, fill: 'none' });
6207
+ }
6094
6208
  };
6095
6209
  img.src = n.imageUrl;
6096
6210
  }
@@ -6280,11 +6394,13 @@ function renderToCanvas(sg, canvas, options = {}) {
6280
6394
  const textCY = vertAlign === 'top' ? nodeBodyTop + blockH / 2
6281
6395
  : vertAlign === 'bottom' ? nodeBodyBottom - blockH / 2
6282
6396
  : n.y + n.h / 2; // middle (default)
6283
- if (lines.length > 1) {
6284
- drawMultilineText(ctx, lines, textX, textCY, fontSize, fontWeight, textColor, textAlign, lineHeight, nodeFont, letterSpacing);
6285
- }
6286
- else {
6287
- drawText(ctx, lines[0] ?? '', textX, textCY, fontSize, fontWeight, textColor, textAlign, nodeFont, letterSpacing);
6397
+ if (n.label) {
6398
+ if (lines.length > 1) {
6399
+ drawMultilineText(ctx, lines, textX, textCY, fontSize, fontWeight, textColor, textAlign, lineHeight, nodeFont, letterSpacing);
6400
+ }
6401
+ else {
6402
+ drawText(ctx, lines[0] ?? '', textX, textCY, fontSize, fontWeight, textColor, textAlign, nodeFont, letterSpacing);
6403
+ }
6288
6404
  }
6289
6405
  if (n.style?.opacity != null)
6290
6406
  ctx.globalAlpha = 1;