@redvars/peacock 3.6.2 → 3.6.3

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.
Files changed (75) hide show
  1. package/dist/assets/components.css.map +1 -1
  2. package/dist/assets/styles.css.map +1 -1
  3. package/dist/{button-colors-AvGh22Zn.js → button-colors-Cg6oxiz-.js} +126 -116
  4. package/dist/{button-colors-AvGh22Zn.js.map → button-colors-Cg6oxiz-.js.map} +1 -1
  5. package/dist/button-group.js +2 -2
  6. package/dist/button.js +17 -14
  7. package/dist/button.js.map +1 -1
  8. package/dist/canvas.js +126 -107
  9. package/dist/canvas.js.map +1 -1
  10. package/dist/custom-elements-jsdocs.json +665 -162
  11. package/dist/custom-elements.json +859 -326
  12. package/dist/{flow-designer-node-BWrPuxAR.js → flow-designer-node-9Bqyn6qx.js} +2 -1
  13. package/dist/flow-designer-node-9Bqyn6qx.js.map +1 -0
  14. package/dist/flow-designer-node.js +1 -1
  15. package/dist/flow-designer.js +3 -3
  16. package/dist/{icon-button-ohxHhy4t.js → icon-button-AdJBEoNy.js} +34 -30
  17. package/dist/icon-button-AdJBEoNy.js.map +1 -0
  18. package/dist/index.js +4 -4
  19. package/dist/{navigation-rail-CD7IrqbN.js → navigation-rail-DAUuJ_Yp.js} +735 -370
  20. package/dist/navigation-rail-DAUuJ_Yp.js.map +1 -0
  21. package/dist/peacock-loader.js +6 -3
  22. package/dist/peacock-loader.js.map +1 -1
  23. package/dist/popover-content.js +1 -1
  24. package/dist/popover-content.js.map +1 -1
  25. package/dist/search.js +11 -14
  26. package/dist/search.js.map +1 -1
  27. package/dist/src/canvas/canvas.d.ts +3 -3
  28. package/dist/src/field/field.d.ts +1 -0
  29. package/dist/src/flow-designer/flow-designer-node.d.ts +1 -0
  30. package/dist/src/image/image.d.ts +2 -2
  31. package/dist/src/index.d.ts +1 -0
  32. package/dist/src/input/input.d.ts +1 -3
  33. package/dist/src/item/index.d.ts +1 -0
  34. package/dist/src/item/item.d.ts +48 -0
  35. package/dist/src/menu/menu-item/menu-item.d.ts +8 -9
  36. package/dist/src/menu/sub-menu/sub-menu.d.ts +1 -0
  37. package/dist/src/navigation-rail/navigation-rail.d.ts +2 -6
  38. package/dist/src/popover/popover-content.d.ts +1 -1
  39. package/dist/src/search/search.d.ts +2 -6
  40. package/dist/test/item.test.d.ts +1 -0
  41. package/dist/tsconfig.tsbuildinfo +1 -1
  42. package/package.json +1 -1
  43. package/scss/mixin.scss +23 -0
  44. package/src/button/button/button-sizes.scss +11 -11
  45. package/src/button/button/button.scss +96 -122
  46. package/src/button/button/button.ts +37 -34
  47. package/src/button/icon-button/icon-button-sizes.scss +8 -8
  48. package/src/button/icon-button/icon-button.ts +23 -20
  49. package/src/canvas/canvas.scss +18 -6
  50. package/src/canvas/canvas.ts +125 -103
  51. package/src/chip/chip/chip.scss +1 -1
  52. package/src/empty-state/empty-state.scss +1 -0
  53. package/src/field/field.ts +6 -0
  54. package/src/flow-designer/flow-designer-node.ts +1 -0
  55. package/src/image/image.scss +21 -16
  56. package/src/image/image.ts +13 -14
  57. package/src/index.ts +1 -0
  58. package/src/input/input.ts +16 -25
  59. package/src/item/index.ts +1 -0
  60. package/src/item/item.scss +184 -0
  61. package/src/item/item.ts +340 -0
  62. package/src/menu/menu/menu.ts +5 -9
  63. package/src/menu/menu-item/menu-item.scss +30 -108
  64. package/src/menu/menu-item/menu-item.ts +89 -129
  65. package/src/menu/sub-menu/sub-menu.ts +6 -2
  66. package/src/navigation-rail/navigation-rail.ts +2 -6
  67. package/src/peacock-loader.ts +4 -0
  68. package/src/popover/popover-content.ts +1 -1
  69. package/src/search/search.ts +11 -16
  70. package/src/select/option.ts +1 -1
  71. package/src/select/select.scss +1 -10
  72. package/src/select/select.ts +2 -0
  73. package/dist/flow-designer-node-BWrPuxAR.js.map +0 -1
  74. package/dist/icon-button-ohxHhy4t.js.map +0 -1
  75. package/dist/navigation-rail-CD7IrqbN.js.map +0 -1
@@ -149,6 +149,7 @@ export class IconButton extends BaseButton {
149
149
  };
150
150
 
151
151
  if (!isLink) {
152
+ cssClasses['native-button'] = true;
152
153
  return html`<button
153
154
  class=${classMap(cssClasses)}
154
155
  id="button"
@@ -167,27 +168,29 @@ export class IconButton extends BaseButton {
167
168
  ${this.renderButtonContent()}
168
169
  </button>
169
170
  ${this.__renderTooltip()}`;
170
- }
171
- return html`<a
172
- class=${classMap(cssClasses)}
173
- id="button"
174
- href=${this.href}
175
- target=${this.target}
176
- tabindex=${this.disabled ? '-1' : '0'}
177
- @click=${this.__dispatchClick}
178
- @mousedown=${this.__handlePress}
179
- @keydown=${this.__handlePress}
180
- @keyup=${this.__handlePress}
181
- role="button"
182
-
183
- aria-describedby=${ifDefined(this.softDisabled ? BaseButton.DISABLED_REASON_ID : undefined)}
184
- ?aria-disabled=${this.softDisabled}
171
+ } else {
172
+ cssClasses['native-link'] = true;
173
+ return html`<a
174
+ class=${classMap(cssClasses)}
175
+ id="button"
176
+ href=${this.href}
177
+ target=${this.target}
178
+ tabindex=${this.disabled ? '-1' : '0'}
179
+ @click=${this.__dispatchClick}
180
+ @mousedown=${this.__handlePress}
181
+ @keydown=${this.__handlePress}
182
+ @keyup=${this.__handlePress}
183
+ role="button"
184
+
185
+ aria-describedby=${ifDefined(this.softDisabled ? BaseButton.DISABLED_REASON_ID : undefined)}
186
+ ?aria-disabled=${this.softDisabled}
185
187
 
186
- ${spread(this.configAria)}
187
- >
188
- ${this.renderButtonContent()}
189
- </a>
190
- ${this.__renderTooltip()}`;
188
+ ${spread(this.configAria)}
189
+ >
190
+ ${this.renderButtonContent()}
191
+ </a>
192
+ ${this.__renderTooltip()}`;
193
+ }
191
194
  }
192
195
 
193
196
  renderButtonContent() {
@@ -12,8 +12,22 @@
12
12
  }
13
13
 
14
14
  .canvas-wrapper {
15
+ position: relative;
15
16
  background: var(--canvas-background);
16
- border-radius: var(--shape-corner-medium);
17
+ }
18
+
19
+ .canvas {
20
+ display: block;
21
+ }
22
+
23
+ .canvas-background,
24
+ .canvas-shapes {
25
+ position: absolute;
26
+ inset: 0;
27
+ }
28
+
29
+ .canvas-background {
30
+ pointer-events: none;
17
31
  }
18
32
 
19
33
  #canvas-background circle {
@@ -22,16 +36,14 @@
22
36
 
23
37
  #endarrow polyline {
24
38
  fill: none;
25
- stroke: var(--canvas-arrow-color);
39
+ stroke: context-stroke;
26
40
  vector-effect: non-scaling-stroke;
27
41
  stroke-width: 2;
42
+ stroke-linejoin: round;
43
+ stroke-linecap: round;
28
44
  }
29
45
 
30
46
  .line {
31
- &.no-color {
32
- stroke: var(--canvas-line-color);
33
- }
34
-
35
47
  &.variant-dashed {
36
48
  stroke-dasharray: 6 6;
37
49
  }
@@ -61,6 +61,9 @@ export type CanvasShape =
61
61
  | CanvasLineShape
62
62
  | CanvasConnectorShape;
63
63
 
64
+ const GRID_GAP = 10;
65
+ const GRID_DOT_RADIUS = 1;
66
+
64
67
  interface CanvasBounds {
65
68
  x: number;
66
69
  y: number;
@@ -68,6 +71,20 @@ interface CanvasBounds {
68
71
  height: number;
69
72
  }
70
73
 
74
+ interface CanvasExtents {
75
+ minX: number;
76
+ minY: number;
77
+ maxX: number;
78
+ maxY: number;
79
+ }
80
+
81
+ interface CanvasViewBox {
82
+ x: number;
83
+ y: number;
84
+ width: number;
85
+ height: number;
86
+ }
87
+
71
88
  /**
72
89
  * @label Canvas
73
90
  * @tag wc-canvas
@@ -118,10 +135,6 @@ export class Canvas extends LitElement {
118
135
  @property({ type: String })
119
136
  viewbox?: string;
120
137
 
121
- private unitSize: number = 1;
122
-
123
- private gap: number = this.unitSize * 10;
124
-
125
138
  private static getNextPoint(
126
139
  point: CanvasPoint,
127
140
  direction: CanvasDirection,
@@ -134,30 +147,33 @@ export class Canvas extends LitElement {
134
147
  return { x: point.x, y: point.y };
135
148
  }
136
149
 
137
- private static updateComputationArea(
138
- point: CanvasPoint,
139
- area: CanvasBounds,
140
- ): CanvasBounds {
141
- const nextArea = { ...area };
142
- if (point.x > nextArea.width) nextArea.width = point.x;
143
- else if (point.x < nextArea.x) nextArea.x = point.x;
144
- if (point.y > nextArea.height) nextArea.height = point.y;
145
- else if (point.y < nextArea.y) nextArea.y = point.y;
146
- return nextArea;
150
+ private static updateExtents(
151
+ extents: CanvasExtents,
152
+ x: number,
153
+ y: number,
154
+ ) {
155
+ if (x < extents.minX) extents.minX = x;
156
+ if (x > extents.maxX) extents.maxX = x;
157
+ if (y < extents.minY) extents.minY = y;
158
+ if (y > extents.maxY) extents.maxY = y;
147
159
  }
148
160
 
149
161
  private static getStrokeVariantClasses(variant?: CanvasStrokeVariant) {
150
162
  return {
151
163
  line: true,
152
- 'no-color': false,
153
164
  'variant-dashed': variant === 'dashed' || variant === 'animated-dashed',
154
165
  'variant-animated-dashed': variant === 'animated-dashed',
155
166
  };
156
167
  }
157
168
 
158
169
  private computeShapes(initialBounds: CanvasBounds) {
159
- const dotRadius = this.unitSize;
160
- let computedViewbox = { ...initialBounds };
170
+ // Track world-space bounds (grid units) as shapes are processed.
171
+ const extents: CanvasExtents = {
172
+ minX: initialBounds.x,
173
+ minY: initialBounds.y,
174
+ maxX: initialBounds.x + initialBounds.width,
175
+ maxY: initialBounds.y + initialBounds.height,
176
+ };
161
177
 
162
178
  const shapes = this.shapes.map(shape => {
163
179
  switch (shape.type) {
@@ -165,19 +181,14 @@ export class Canvas extends LitElement {
165
181
  const r = shape.radius || 1;
166
182
  const cx = shape.x || 0;
167
183
  const cy = shape.y || 0;
168
- if (cx + Math.ceil(r) > computedViewbox.width)
169
- computedViewbox.width = cx + Math.ceil(r);
170
- if (cx - Math.ceil(r) < computedViewbox.x)
171
- computedViewbox.x = cx - Math.ceil(r);
172
- if (cy + Math.ceil(r) > computedViewbox.height)
173
- computedViewbox.height = cy + Math.ceil(r);
174
- if (cy - Math.ceil(r) < computedViewbox.y)
175
- computedViewbox.y = cy - Math.ceil(r);
184
+ Canvas.updateExtents(extents, cx - r, cy - r);
185
+ Canvas.updateExtents(extents, cx + r, cy + r);
176
186
 
187
+ // Convert from grid units to SVG pixels using the fixed gap.
177
188
  return svg`<circle
178
- cx=${cx * this.gap + dotRadius}
179
- cy=${cy * this.gap + dotRadius}
180
- r=${r * this.gap}
189
+ cx=${cx * GRID_GAP + GRID_DOT_RADIUS}
190
+ cy=${cy * GRID_GAP + GRID_DOT_RADIUS}
191
+ r=${r * GRID_GAP}
181
192
  fill=${shape.color || 'var(--canvas-line-color, var(--color-on-surface))'}
182
193
  />`;
183
194
  }
@@ -186,27 +197,23 @@ export class Canvas extends LitElement {
186
197
  const h = shape.height || 1;
187
198
  const rx = shape.x || 0;
188
199
  const ry = shape.y || 0;
189
- if (rx + Math.ceil(w) > computedViewbox.width)
190
- computedViewbox.width = rx + Math.ceil(w);
191
- if (rx - Math.ceil(w) < computedViewbox.x)
192
- computedViewbox.x = rx - Math.ceil(w);
193
- if (ry + Math.ceil(h) > computedViewbox.height)
194
- computedViewbox.height = ry + Math.ceil(h);
195
- if (ry - Math.ceil(h) < computedViewbox.y)
196
- computedViewbox.y = ry - Math.ceil(h);
200
+ Canvas.updateExtents(extents, rx, ry);
201
+ Canvas.updateExtents(extents, rx + w, ry + h);
197
202
 
198
203
  return svg`<rect
199
- x=${rx * this.gap + dotRadius}
200
- y=${ry * this.gap}
201
- width=${w * this.gap + dotRadius}
202
- height=${h * this.gap + dotRadius}
204
+ x=${rx * GRID_GAP + GRID_DOT_RADIUS}
205
+ y=${ry * GRID_GAP}
206
+ width=${w * GRID_GAP + GRID_DOT_RADIUS}
207
+ height=${h * GRID_GAP + GRID_DOT_RADIUS}
203
208
  fill=${shape.color || 'var(--canvas-line-color, var(--color-on-surface))'}
204
209
  />`;
205
210
  }
206
211
  case 'line': {
207
212
  const start = shape.start || { x: 0, y: 0 };
208
213
  const end = shape.end || { x: 0, y: 0 };
209
- const pathString = `M${start.x * this.gap + dotRadius} ${start.y * this.gap + dotRadius} L${end.x * this.gap + dotRadius} ${end.y * this.gap + dotRadius}`;
214
+ Canvas.updateExtents(extents, start.x, start.y);
215
+ Canvas.updateExtents(extents, end.x, end.y);
216
+ const pathString = `M${start.x * GRID_GAP + GRID_DOT_RADIUS} ${start.y * GRID_GAP + GRID_DOT_RADIUS} L${end.x * GRID_GAP + GRID_DOT_RADIUS} ${end.y * GRID_GAP + GRID_DOT_RADIUS}`;
210
217
  const strokeColor =
211
218
  shape.color ||
212
219
  'var(--canvas-line-color, var(--color-on-surface))';
@@ -215,7 +222,6 @@ export class Canvas extends LitElement {
215
222
  class=${classMap({
216
223
  ...Canvas.getStrokeVariantClasses(shape.variant),
217
224
  clickable: !!shape.clickable,
218
- 'no-color': !shape.color,
219
225
  })}
220
226
  stroke-width="2"
221
227
  stroke-linecap="round"
@@ -229,19 +235,20 @@ export class Canvas extends LitElement {
229
235
  }
230
236
  case 'connector': {
231
237
  const start = shape.start || { x: 0, y: 0 };
232
- let pathString = `M${start.x * this.gap + dotRadius} ${start.y * this.gap + dotRadius}`;
238
+ let pathString = `M${start.x * GRID_GAP + GRID_DOT_RADIUS} ${start.y * GRID_GAP + GRID_DOT_RADIUS}`;
233
239
  let current = { ...start };
234
- computedViewbox = Canvas.updateComputationArea(current, computedViewbox);
240
+ Canvas.updateExtents(extents, current.x, current.y);
235
241
 
236
242
  const pathSegments = shape.path || [];
237
243
  for (let i = 0; i < pathSegments.length; i += 1) {
238
244
  const path = pathSegments[i];
239
245
 
240
246
  if (i === 0) {
247
+ // Move one unit first so curved corner joins don't overlap start.
241
248
  const point = Canvas.getNextPoint(current, path.direction, 1);
242
- pathString += ` L${point.x * this.gap + dotRadius} ${point.y * this.gap + dotRadius}`;
249
+ pathString += ` L${point.x * GRID_GAP + GRID_DOT_RADIUS} ${point.y * GRID_GAP + GRID_DOT_RADIUS}`;
243
250
  current = { ...point };
244
- computedViewbox = Canvas.updateComputationArea(current, computedViewbox);
251
+ Canvas.updateExtents(extents, current.x, current.y);
245
252
  }
246
253
 
247
254
  const point = Canvas.getNextPoint(
@@ -249,26 +256,28 @@ export class Canvas extends LitElement {
249
256
  path.direction,
250
257
  path.length - 2,
251
258
  );
252
- pathString += ` L${point.x * this.gap + dotRadius} ${point.y * this.gap + dotRadius}`;
259
+ pathString += ` L${point.x * GRID_GAP + GRID_DOT_RADIUS} ${point.y * GRID_GAP + GRID_DOT_RADIUS}`;
253
260
  current = { ...point };
254
- computedViewbox = Canvas.updateComputationArea(current, computedViewbox);
261
+ Canvas.updateExtents(extents, current.x, current.y);
255
262
 
256
263
  if (i === pathSegments.length - 1) {
257
264
  const endPoint = Canvas.getNextPoint(current, path.direction, 1);
258
- pathString += ` L${endPoint.x * this.gap + dotRadius} ${endPoint.y * this.gap + dotRadius}`;
265
+ pathString += ` L${endPoint.x * GRID_GAP + GRID_DOT_RADIUS} ${endPoint.y * GRID_GAP + GRID_DOT_RADIUS}`;
259
266
  current = { ...endPoint };
260
- computedViewbox = Canvas.updateComputationArea(current, computedViewbox);
267
+ Canvas.updateExtents(extents, current.x, current.y);
261
268
  } else {
262
269
  const nextPath = pathSegments[i + 1];
263
270
  const midPoint = Canvas.getNextPoint(current, path.direction, 1);
271
+ Canvas.updateExtents(extents, midPoint.x, midPoint.y);
264
272
  const nextPoint = Canvas.getNextPoint(
265
273
  midPoint,
266
274
  nextPath.direction,
267
275
  1,
268
276
  );
269
- pathString += ` Q ${midPoint.x * this.gap + dotRadius} ${midPoint.y * this.gap + dotRadius} ${nextPoint.x * this.gap + dotRadius} ${nextPoint.y * this.gap + dotRadius}`;
277
+ // Use a quadratic segment to round corners between directions.
278
+ pathString += ` Q ${midPoint.x * GRID_GAP + GRID_DOT_RADIUS} ${midPoint.y * GRID_GAP + GRID_DOT_RADIUS} ${nextPoint.x * GRID_GAP + GRID_DOT_RADIUS} ${nextPoint.y * GRID_GAP + GRID_DOT_RADIUS}`;
270
279
  current = { ...nextPoint };
271
- computedViewbox = Canvas.updateComputationArea(current, computedViewbox);
280
+ Canvas.updateExtents(extents, current.x, current.y);
272
281
  }
273
282
  }
274
283
 
@@ -280,7 +289,6 @@ export class Canvas extends LitElement {
280
289
  <path
281
290
  class=${classMap({
282
291
  ...Canvas.getStrokeVariantClasses(shape.variant),
283
- 'no-color': !shape.color,
284
292
  })}
285
293
  stroke-width="2"
286
294
  stroke-linecap="round"
@@ -306,19 +314,68 @@ export class Canvas extends LitElement {
306
314
  }
307
315
  });
308
316
 
309
- // Padding
310
- computedViewbox.x -= this.padding;
311
- computedViewbox.y -= this.padding;
312
- computedViewbox.width += this.padding;
313
- computedViewbox.height += this.padding;
314
- computedViewbox.width -= computedViewbox.x;
315
- computedViewbox.height -= computedViewbox.y;
317
+ // Expand bounds with padding so shapes are not flush to the edge.
318
+ const computedViewbox = {
319
+ x: extents.minX - this.padding,
320
+ y: extents.minY - this.padding,
321
+ width: Math.max(extents.maxX - extents.minX + this.padding * 2, 0),
322
+ height: Math.max(extents.maxY - extents.minY + this.padding * 2, 0),
323
+ };
316
324
 
317
325
  return { shapes, computedViewbox };
318
326
  }
319
327
 
328
+ private renderBackgroundSvg(computedViewBox: CanvasViewBox, svgViewBox: string) {
329
+ return html`
330
+ <svg
331
+ class="canvas canvas-background"
332
+ height="100%"
333
+ width="100%"
334
+ viewBox=${svgViewBox}
335
+ aria-hidden="true"
336
+ >
337
+ <defs>
338
+ <pattern
339
+ id="canvas-background"
340
+ patternUnits="userSpaceOnUse"
341
+ width=${GRID_GAP}
342
+ height=${GRID_GAP}
343
+ >
344
+ <circle cx="1" cy="1" r=${GRID_DOT_RADIUS} />
345
+ </pattern>
346
+ </defs>
347
+
348
+ <rect
349
+ x=${computedViewBox.x * GRID_GAP}
350
+ y=${computedViewBox.y * GRID_GAP}
351
+ width="100%"
352
+ height="100%"
353
+ fill="url(#canvas-background)"
354
+ />
355
+ </svg>
356
+ `;
357
+ }
358
+
359
+ private renderShapesSvg(shapes: unknown[], svgViewBox: string) {
360
+ return html`
361
+ <svg
362
+ class="canvas canvas-shapes"
363
+ height="100%"
364
+ width="100%"
365
+ viewBox=${svgViewBox}
366
+ >
367
+ <defs>
368
+ <marker id="endarrow" markerWidth="10" markerHeight="10" refX="5" refY="5" markerUnits="strokeWidth" orient="auto">
369
+ <polyline points="0 2, 5 5, 0 8"></polyline>
370
+ </marker>
371
+ </defs>
372
+
373
+ ${shapes}
374
+ </svg>
375
+ `;
376
+ }
377
+
320
378
  protected render() {
321
- const dotRadius = this.unitSize;
322
379
  let computedViewBox = { width: 0, height: 0, x: 0, y: 0 };
323
380
 
324
381
  const { shapes, computedViewbox } = this.computeShapes(computedViewBox);
@@ -334,57 +391,22 @@ export class Canvas extends LitElement {
334
391
  };
335
392
  }
336
393
 
394
+ // Zoom scales the outer viewport size while the SVG viewBox stays in world units.
337
395
  const wrapperWidth =
338
- (computedViewBox.width * this.gap + 2) * dotRadius * this.zoom;
396
+ (computedViewBox.width * GRID_GAP + 2) * GRID_DOT_RADIUS * this.zoom;
339
397
  const wrapperHeight =
340
- (computedViewBox.height * this.gap + 2) * dotRadius * this.zoom;
398
+ (computedViewBox.height * GRID_GAP + 2) * GRID_DOT_RADIUS * this.zoom;
341
399
 
342
- const svgViewBox = `${computedViewBox.x * this.gap} ${computedViewBox.y * this.gap} ${computedViewBox.width * this.gap + 2 * dotRadius} ${computedViewBox.height * this.gap + 2 * dotRadius}`;
400
+ // viewBox maps world-space extents into the internal SVG coordinate system.
401
+ const svgViewBox = `${computedViewBox.x * GRID_GAP} ${computedViewBox.y * GRID_GAP} ${computedViewBox.width * GRID_GAP + 2 * GRID_DOT_RADIUS} ${computedViewBox.height * GRID_GAP + 2 * GRID_DOT_RADIUS}`;
343
402
 
344
403
  return html`
345
404
  <div
346
405
  class="canvas-wrapper"
347
406
  style="width: ${wrapperWidth}px; height: ${wrapperHeight}px;"
348
407
  >
349
- <svg
350
- class="canvas"
351
- height="100%"
352
- width="100%"
353
- viewBox=${svgViewBox}
354
- >
355
- <defs>
356
- <pattern
357
- id="canvas-background"
358
- patternUnits="userSpaceOnUse"
359
- width=${this.gap}
360
- height=${this.gap}
361
- >
362
- <circle cx="1" cy="1" r=${dotRadius} />
363
- </pattern>
364
-
365
- <marker
366
- id="endarrow"
367
- markerWidth="15"
368
- markerHeight="22.5"
369
- refX="9"
370
- refY="15"
371
- markerUnits="userSpaceOnUse"
372
- orient="auto"
373
- >
374
- <polyline points="0 22.5, 7.5 15, 0 7.5"></polyline>
375
- </marker>
376
- </defs>
377
-
378
- <rect
379
- x=${computedViewBox.x * this.gap}
380
- y=${computedViewBox.y * this.gap}
381
- width="100%"
382
- height="100%"
383
- fill="url(#canvas-background)"
384
- />
385
-
386
- ${shapes}
387
- </svg>
408
+ ${this.renderBackgroundSvg(computedViewBox, svgViewBox)}
409
+ ${this.renderShapesSvg(shapes, svgViewBox)}
388
410
  </div>
389
411
  `;
390
412
  }
@@ -3,7 +3,7 @@
3
3
  @include mixin.base-styles;
4
4
 
5
5
  :host {
6
- display: inline-block;
6
+ display: inline-flex;
7
7
  --chip-container-color: var(--color-surface);
8
8
  --chip-label-text-color: var(--color-on-surface);
9
9
  --chip-outline-color: var(--color-outline-variant);
@@ -53,6 +53,7 @@
53
53
 
54
54
  :host(.content-center) .content {
55
55
  align-items: center;
56
+ text-align: center;
56
57
  }
57
58
 
58
59
  @container emptystate (min-width: 672px) {
@@ -24,6 +24,12 @@ import styles from './field.scss';
24
24
  * @tags form
25
25
  */
26
26
  export class Field extends LitElement {
27
+
28
+ static shadowRootOptions: ShadowRootInit = {
29
+ ...LitElement.shadowRootOptions,
30
+ delegatesFocus: true,
31
+ };
32
+
27
33
  static styles = [styles];
28
34
 
29
35
  @property({ type: String })
@@ -10,6 +10,7 @@ import type { WorkflowNode } from './types.js';
10
10
  *
11
11
  * @tag wc-flow-designer-node
12
12
  * @rawTag flow-designer-node
13
+ * @parentRawTag flow-designer
13
14
  * @wip true
14
15
  */
15
16
  @IndividualComponent
@@ -30,27 +30,32 @@ img.clickable {
30
30
  display: block;
31
31
  }
32
32
 
33
- /* Preview overlayrendered in light DOM via portal, but we keep
34
- a host-level overlay as a fallback when shadow DOM is used. */
35
- .preview-overlay {
36
- display: none;
37
- position: fixed;
38
- inset: 0;
39
- z-index: 9999;
40
- background: rgba(0, 0, 0, 0.85);
41
- align-items: center;
42
- justify-content: center;
33
+ /* Lightbox previewnative <dialog> renders in the top layer,
34
+ bypassing any stacking context on the host page. */
35
+ .preview-dialog {
36
+ background: transparent;
37
+ border: none;
43
38
  cursor: zoom-out;
39
+ max-height: 90dvh;
40
+ max-width: 90dvw;
41
+ padding: 0;
42
+
43
+ &[open] {
44
+ display: flex;
45
+ align-items: center;
46
+ justify-content: center;
47
+ }
48
+
49
+ &::backdrop {
50
+ background: color-mix(in srgb, var(--color-scrim), transparent 15%);
51
+ }
44
52
  }
45
53
 
46
- .preview-overlay.open {
47
- display: flex;
48
- }
49
-
50
- .preview-overlay img {
54
+ .preview-dialog img {
51
55
  max-width: 90vw;
52
56
  max-height: 90vh;
53
57
  object-fit: contain;
54
- box-shadow: 0 8px 40px rgba(0, 0, 0, 0.6);
58
+ box-shadow: 0 8px 40px color-mix(in srgb, var(--color-shadow), transparent 40%);
55
59
  border-radius: 4px;
60
+ cursor: auto;
56
61
  }
@@ -1,5 +1,5 @@
1
1
  import { LitElement, html } from 'lit';
2
- import { property, state } from 'lit/decorators.js';
2
+ import { property, query, state } from 'lit/decorators.js';
3
3
 
4
4
  import { isDarkMode } from '@/__utils/is-dark-mode.js';
5
5
  import { observeThemeChange } from '@/__utils/observe-theme-change.js';
@@ -37,7 +37,7 @@ export class Image extends LitElement {
37
37
 
38
38
  @state() private _loaded = false;
39
39
 
40
- @state() private _previewOpen = false;
40
+ @query('.preview-dialog') private _dialog?: HTMLDialogElement;
41
41
 
42
42
  private _intersectionObserver: IntersectionObserver | null = null;
43
43
 
@@ -90,13 +90,15 @@ export class Image extends LitElement {
90
90
 
91
91
  private _handleClick() {
92
92
  if (this.preview) {
93
- this._previewOpen = true;
93
+ this._dialog?.showModal();
94
94
  }
95
95
  }
96
96
 
97
- private _closePreview(e: Event) {
98
- e.stopPropagation();
99
- this._previewOpen = false;
97
+ private _handleDialogClick(e: MouseEvent) {
98
+ // Close when clicking the backdrop (target is the dialog itself, not the image)
99
+ if (e.target === e.currentTarget) {
100
+ (e.currentTarget as HTMLDialogElement).close();
101
+ }
100
102
  }
101
103
 
102
104
  render() {
@@ -112,17 +114,14 @@ export class Image extends LitElement {
112
114
  : html`<span class="placeholder" aria-hidden="true"></span>`}
113
115
  </div>
114
116
 
115
- <!-- Lightbox preview overlay (inside shadow root) -->
116
- <div
117
- class="preview-overlay ${this._previewOpen ? 'open' : ''}"
118
- role="dialog"
119
- aria-modal="true"
117
+ <!-- Lightbox preview dialog uses native top-layer to avoid stacking context issues -->
118
+ <dialog
119
+ class="preview-dialog"
120
120
  aria-label="Image preview"
121
- @click=${this._closePreview}
122
- @keydown=${(e: KeyboardEvent) => e.key === 'Escape' && this._closePreview(e)}
121
+ @click=${this._handleDialogClick}
123
122
  >
124
123
  <img src=${this._activeSrc} alt=${this.imageTitle} @click=${(e: Event) => e.stopPropagation()} />
125
- </div>
124
+ </dialog>
126
125
  `;
127
126
  }
128
127
  }
package/src/index.ts CHANGED
@@ -39,6 +39,7 @@ export { Popover, PopoverContent } from './popover/index.js';
39
39
  export { Breadcrumb, BreadcrumbItem } from './breadcrumb/index.js';
40
40
  export { Menu, MenuItem, SubMenu } from './menu/index.js';
41
41
  export { List, ListItem } from './list/index.js';
42
+ export { Item } from './item/index.js';
42
43
 
43
44
  export { CodeHighlighter } from './code-highlighter/index.js';
44
45
  export { CodeEditor } from './code-editor/index.js';