stickyflow 0.5.0 → 0.7.0

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 (62) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/dist/binding/index.cjs +9 -9
  3. package/dist/binding/index.d.cts +4 -4
  4. package/dist/binding/index.d.ts +4 -4
  5. package/dist/binding/index.js +3 -3
  6. package/dist/{chunk-ZMLQIMJK.cjs → chunk-A73UJ5AQ.cjs} +1537 -738
  7. package/dist/chunk-A73UJ5AQ.cjs.map +1 -0
  8. package/dist/{chunk-VK3T6O5Z.cjs → chunk-BUOWM3LC.cjs} +745 -62
  9. package/dist/chunk-BUOWM3LC.cjs.map +1 -0
  10. package/dist/{chunk-L3VJXZFD.cjs → chunk-EKAWJFJQ.cjs} +15 -15
  11. package/dist/{chunk-L3VJXZFD.cjs.map → chunk-EKAWJFJQ.cjs.map} +1 -1
  12. package/dist/{chunk-BODZN3ZI.js → chunk-JCRPLPKV.js} +156 -23
  13. package/dist/chunk-JCRPLPKV.js.map +1 -0
  14. package/dist/{chunk-IEHE6WVN.js → chunk-JQK4IGXJ.js} +489 -51
  15. package/dist/chunk-JQK4IGXJ.js.map +1 -0
  16. package/dist/{chunk-XY2GZUHC.cjs → chunk-KXYSO6GC.cjs} +498 -50
  17. package/dist/chunk-KXYSO6GC.cjs.map +1 -0
  18. package/dist/{chunk-G7NRK5AG.js → chunk-MUKIGLR5.js} +717 -34
  19. package/dist/chunk-MUKIGLR5.js.map +1 -0
  20. package/dist/{chunk-TWDLOXRM.cjs → chunk-OWNVXKXN.cjs} +170 -37
  21. package/dist/chunk-OWNVXKXN.cjs.map +1 -0
  22. package/dist/{chunk-LTGF5OHP.js → chunk-SDMQRSRW.js} +941 -143
  23. package/dist/chunk-SDMQRSRW.js.map +1 -0
  24. package/dist/{chunk-7VW2XKVB.js → chunk-ZNHYW47T.js} +3 -3
  25. package/dist/{chunk-7VW2XKVB.js.map → chunk-ZNHYW47T.js.map} +1 -1
  26. package/dist/index.cjs +57 -29
  27. package/dist/index.d.cts +80 -7
  28. package/dist/index.d.ts +80 -7
  29. package/dist/index.js +5 -5
  30. package/dist/interaction/index.cjs +245 -235
  31. package/dist/interaction/index.cjs.map +1 -1
  32. package/dist/interaction/index.d.cts +3 -2
  33. package/dist/interaction/index.d.ts +3 -2
  34. package/dist/interaction/index.js +17 -7
  35. package/dist/interaction/index.js.map +1 -1
  36. package/dist/{render-CgX_y15a.d.ts → render-BU2uYzjG.d.cts} +40 -16
  37. package/dist/{render-CgX_y15a.d.cts → render-BU2uYzjG.d.ts} +40 -16
  38. package/dist/{runtime-reWgr7MP.d.cts → runtime-B7KiTmn8.d.cts} +2 -2
  39. package/dist/{runtime-DnUxca3Y.d.ts → runtime-BPzyD-Nd.d.ts} +2 -2
  40. package/dist/{runtimeTypes-D60w6nyF.d.cts → runtimeTypes-BIP70z72.d.cts} +3 -2
  41. package/dist/{runtimeTypes-CEBGueYM.d.ts → runtimeTypes-DalvhScn.d.ts} +3 -2
  42. package/dist/stickyflow-diagram.global.js +387 -36
  43. package/dist/stickyflow-diagram.global.js.map +1 -1
  44. package/dist/{types-DYLC_lsk.d.ts → types-DMWs27Hn.d.ts} +1 -1
  45. package/dist/{types-DvhMpqrL.d.cts → types-D_2NZ6lL.d.cts} +1 -1
  46. package/dist/viewer/index.cjs +9 -9
  47. package/dist/viewer/index.d.cts +5 -4
  48. package/dist/viewer/index.d.ts +5 -4
  49. package/dist/viewer/index.js +4 -4
  50. package/dist/web-component/index.cjs +6 -6
  51. package/dist/web-component/index.d.cts +2 -2
  52. package/dist/web-component/index.d.ts +2 -2
  53. package/dist/web-component/index.js +4 -4
  54. package/package.json +1 -1
  55. package/dist/chunk-BODZN3ZI.js.map +0 -1
  56. package/dist/chunk-G7NRK5AG.js.map +0 -1
  57. package/dist/chunk-IEHE6WVN.js.map +0 -1
  58. package/dist/chunk-LTGF5OHP.js.map +0 -1
  59. package/dist/chunk-TWDLOXRM.cjs.map +0 -1
  60. package/dist/chunk-VK3T6O5Z.cjs.map +0 -1
  61. package/dist/chunk-XY2GZUHC.cjs.map +0 -1
  62. package/dist/chunk-ZMLQIMJK.cjs.map +0 -1
@@ -1,4 +1,4 @@
1
- import { componentRegistryVersion, isIsometricObject, sflToCanvasState, registerComponentDescriptor, isBuiltInComponentType, getComponentDescriptor, tag, EMPTY_BOUNDS, DOM_CONTRACT_VERSION, edgePointToward, elementCenter, VISIBLE_ISOMETRIC_FACES, isometricFaceCenter, finite, freeformPathData, rotatedBounds, DEFAULT_FONT, isGenericComponent, isometricFaces, roundedPolygonPath, pointAtNormalizedPort, boxBounds, cornersRoundedRectPath, calculateLinkRoute, labelGapDash, getLineMidpoint, personLabelArea, wrapText, heuristicRichMeasure, isometricBounds, deriveFaceFills, stackSequence, stackRank, topRoundedRectPath, rightRoundedRectPath, leftRoundedRectPath, bottomRoundedRectPath, isHorizontalBar, paint, CHART_TITLE_PROP, chartText, chartTicks, mapChartValue, roundedOrthogonalPathData, localShapePath, pillCornerRadius, isometricTopFaceCenter, resolveChartShadow, CHART_COLORS, angleForAxisValue, horizontalRows, rowTop, categoryProp, ISOMETRIC_SIZE_ATTR, CORNER_RADIUS_ATTR, ISOMETRIC_LABEL_OFFSET_ATTR, PATH_POINTS_ATTR, PATH_TENSION_ATTR, PATH_CLOSED_ATTR, SYMBOL_BOUNDS_ATTR, SYMBOL_POINTS_ATTR, SYMBOL_TENSION_ATTR, SQUARE_CORNER_ATTR, resolvePieRadii, radarCategoryCount, radarRadius, createPieGeometry, DEFAULT_HEX_RADIUS, DEFAULT_HEATMAP_ZONES, axisBands, DEFAULT_ZONE_FILL, representativeColor, computeBoxplotStats, barCategoryCount, ruleAtProp, ruleTextProp, seriesLabelProp, axisLabelProp, seriesColorProp, seriesValueProp, radarSeriesPath, radarRadiusForValue, createPieSlicePath, clipSegmentToRect, formatFieldValue, renderPieLabels, interpolateHexColorStops, contrastTextColor, sameHueTint, isLightColor, barShapePath, linePathData, colorWithAlpha, estimateTextWidth, segmentedBarPath, roundedBarPath, radarPointAt, gapInsetAngle, pieUsesInnerArc, maxPieCornerRadius, pieApexRadius, maxApexCornerRadius, pieArcPoint, sameHueContrastColor, zoneColorAtValue, ellipsizeToWidth, barPath, seriesValueColorProp, stackedSegment, errorBarRange, createVerticalErrorWhiskerNode, formatBarLabel, barLabelSize, CATEGORY_LABEL_ROW, BAR_LABEL, pillPath, resolveRollingNumberStyle, formatRollingNumber } from './chunk-IEHE6WVN.js';
1
+ import { componentRegistryVersion, isDimensionObject, isIsometricObject, sflToCanvasState, registerComponentDescriptor, isBuiltInComponentType, getComponentDescriptor, tag, EMPTY_BOUNDS, DOM_CONTRACT_VERSION, edgePointToward, elementCenter, VISIBLE_ISOMETRIC_FACES, isometricFaceCenter, finite, freeformPathData, rotatedBounds, DEFAULT_FONT, isGenericComponent, cleanFootprint, pointAtNormalizedPort, boxBounds, cornersRoundedRectPath, calculateLinkRoute, labelGapDash, getLineMidpoint, personLabelArea, wrapText, heuristicRichMeasure, shadeFill, extrudeFootprint, isometricFaces, roundedPolygonPath, stackSequence, stackRank, topRoundedRectPath, rightRoundedRectPath, leftRoundedRectPath, bottomRoundedRectPath, isHorizontalBar, paint, CHART_TITLE_PROP, chartText, chartTicks, mapChartValue, roundedOrthogonalPathData, localShapePath, pillCornerRadius, isometricBounds, AXIS_SIN, deriveFaceFills, resolveChartShadow, CHART_COLORS, angleForAxisValue, horizontalRows, rowTop, categoryProp, isometricTopFaceCenter, ISOMETRIC_SIZE_ATTR, CORNER_RADIUS_ATTR, ISOMETRIC_LABEL_OFFSET_ATTR, PATH_POINTS_ATTR, PATH_TENSION_ATTR, PATH_CLOSED_ATTR, SYMBOL_BOUNDS_ATTR, SYMBOL_POINTS_ATTR, SYMBOL_TENSION_ATTR, SQUARE_CORNER_ATTR, resolvePieRadii, radarCategoryCount, radarRadius, createPieGeometry, DEFAULT_HEX_RADIUS, DEFAULT_HEATMAP_ZONES, axisBands, DEFAULT_ZONE_FILL, representativeColor, computeBoxplotStats, barCategoryCount, ruleAtProp, ruleTextProp, seriesLabelProp, axisLabelProp, seriesColorProp, seriesValueProp, radarSeriesPath, radarRadiusForValue, createPieSlicePath, clipSegmentToRect, formatFieldValue, renderPieLabels, interpolateHexColorStops, contrastTextColor, sameHueTint, isLightColor, barShapePath, linePathData, colorWithAlpha, estimateTextWidth, segmentedBarPath, roundedBarPath, radarPointAt, gapInsetAngle, pieUsesInnerArc, maxPieCornerRadius, pieApexRadius, maxApexCornerRadius, pieArcPoint, sameHueContrastColor, zoneColorAtValue, ellipsizeToWidth, barPath, seriesValueColorProp, stackedSegment, errorBarRange, createVerticalErrorWhiskerNode, formatBarLabel, barLabelSize, CATEGORY_LABEL_ROW, BAR_LABEL, pillPath, resolveRollingNumberStyle, formatRollingNumber } from './chunk-JQK4IGXJ.js';
2
2
 
3
3
  // src/renderInput/styleDecoding/colorToken.ts
4
4
  var COLOR_TOKEN_PATTERN = String.raw`rgba?\([^)]*\)|#[0-9a-fA-F]+|[a-zA-Z][\w-]*`;
@@ -844,6 +844,26 @@ function connectionObject(c) {
844
844
  };
845
845
  }
846
846
 
847
+ // src/renderInput/fromSfl/canvasObjects/dimension.ts
848
+ function dimensionObject(canvasObject) {
849
+ const presentation = canvasObject.props;
850
+ return {
851
+ id: canvasObject.id,
852
+ start: canvasObject.dimension.start,
853
+ end: canvasObject.dimension.end,
854
+ offset: canvasObject.dimension.offset,
855
+ text: canvasObject.text,
856
+ unit: canvasObject.dimension.unit,
857
+ strokeColor: solidColor(presentation.stroke),
858
+ strokeWidth: numOf(presentation.strokeWidth),
859
+ textColor: solidColor(presentation.textColor),
860
+ fontSize: numOf(presentation.fontSize),
861
+ order: canvasObject.order,
862
+ sourceIndex: canvasObject.sourceIndex,
863
+ parentFrameId: canvasObject.parentFrameId
864
+ };
865
+ }
866
+
847
867
  // src/renderInput/fromSfl/canvasObjects/frame.ts
848
868
  function frameObject(e) {
849
869
  const p = e.props;
@@ -882,6 +902,8 @@ function isometricObject(canvasObject) {
882
902
  width: canvasObject.width,
883
903
  height: canvasObject.height,
884
904
  depth: canvasObject.isometric.depth,
905
+ footprint: canvasObject.isometric.footprint,
906
+ form: canvasObject.isometric.form,
885
907
  rotation: canvasObject.rotation,
886
908
  order: canvasObject.order,
887
909
  sourceIndex: canvasObject.sourceIndex,
@@ -890,7 +912,7 @@ function isometricObject(canvasObject) {
890
912
  fill: solidColor(presentation.fill) ?? "#f8fafc",
891
913
  strokeColor: solidColor(presentation.stroke) ?? "#111827",
892
914
  strokeWidth: numOf(presentation.strokeWidth) ?? 1,
893
- cornerRadius: numOf(presentation.cornerRadius) ?? 8,
915
+ cornerRadius: numOf(presentation.cornerRadius) ?? (canvasObject.isometric.footprint ? 0 : 8),
894
916
  hasShadow: shadowStyle?.enabled ?? false,
895
917
  shadowStyle,
896
918
  labelOffsetX: numOf(presentation.labelOffsetX) ?? 0,
@@ -1041,6 +1063,7 @@ function collectCanvasObjects(state) {
1041
1063
  swimlanes: canvasObjects.filter((canvasObject) => canvasObject.objectType === "swimlane").map(swimlaneObject),
1042
1064
  isometricObjects: canvasObjects.filter(isIsometricObject).map(isometricObject),
1043
1065
  paths: canvasObjects.filter((canvasObject) => canvasObject.objectType === "path").map(pathObject),
1066
+ dimensions: canvasObjects.filter(isDimensionObject).map(dimensionObject),
1044
1067
  charts: canvasObjects.filter((canvasObject) => canvasObject.objectType === "chart").map(chartObject),
1045
1068
  components: canvasObjects.filter(
1046
1069
  (canvasObject) => canvasObject.objectType === "component" && canvasObject.component !== void 0
@@ -1199,6 +1222,7 @@ function sflToRenderInput(sfl) {
1199
1222
  swimlanes: canvasObjects.swimlanes,
1200
1223
  isometricObjects: canvasObjects.isometricObjects,
1201
1224
  paths: canvasObjects.paths,
1225
+ dimensions: canvasObjects.dimensions,
1202
1226
  charts: canvasObjects.charts,
1203
1227
  components: canvasObjects.components,
1204
1228
  links: createRenderInputLinks(canvasObjects),
@@ -1308,7 +1332,7 @@ function buildTickScale(component, index) {
1308
1332
  }
1309
1333
  function buildTickLabels(component, box) {
1310
1334
  const labels = component.labels ?? {};
1311
- const ticks = Math.max(1, finite(Number(component.parameters.ticks), 48));
1335
+ const ticks2 = Math.max(1, finite(Number(component.parameters.ticks), 48));
1312
1336
  const major = Math.max(1, finite(Number(component.parameters.major), 5));
1313
1337
  const start = finite(Number(component.parameters.start), 225) * Math.PI / 180;
1314
1338
  const sweep = finite(Number(component.parameters.sweep), 270) * Math.PI / 180;
@@ -1316,10 +1340,10 @@ function buildTickLabels(component, box) {
1316
1340
  const fontSize = finite(labels.size, 12);
1317
1341
  const centerX = box.x + box.width / 2;
1318
1342
  const centerY = box.y + box.height / 2;
1319
- const count = Math.floor(ticks / major);
1343
+ const count = Math.floor(ticks2 / major);
1320
1344
  const nodes = [];
1321
1345
  for (let step = 0; step <= count; step += 1) {
1322
- const fraction = step * major / ticks;
1346
+ const fraction = step * major / ticks2;
1323
1347
  const angle = start - fraction * sweep;
1324
1348
  const labelX2 = centerX + Math.cos(angle) * radius * (box.width / 2);
1325
1349
  const labelY = centerY - Math.sin(angle) * radius * (box.height / 2);
@@ -1374,7 +1398,7 @@ function buildRuler(component, index) {
1374
1398
  function buildRulerLabels(component, box) {
1375
1399
  const labels = component.labels ?? {};
1376
1400
  const horizontal = component.parameters.axis === "horizontal";
1377
- const ticks = Math.max(1, finite(Number(component.parameters.ticks), 50));
1401
+ const ticks2 = Math.max(1, finite(Number(component.parameters.ticks), 50));
1378
1402
  const major = Math.max(1, finite(Number(component.parameters.major), 5));
1379
1403
  const inset = finite(Number(component.parameters.inset), 0.05) > 0 ? finite(Number(component.parameters.inset), 0.05) : 0.05;
1380
1404
  const line = finite(Number(component.parameters.line), 0.7) > 0 ? finite(Number(component.parameters.line), 0.7) : 0.7;
@@ -1382,12 +1406,12 @@ function buildRulerLabels(component, box) {
1382
1406
  const tickLength = (finite(Number(component.parameters.length), 0.1) > 0 ? finite(Number(component.parameters.length), 0.1) : 0.1) * across * 1.9;
1383
1407
  const edge = line * across - 0.12 * across - tickLength - finite(labels.offset, 0.04) * across;
1384
1408
  const fontSize = finite(labels.size, 12);
1385
- const count = Math.floor(ticks / major);
1409
+ const count = Math.floor(ticks2 / major);
1386
1410
  const nodes = [];
1387
1411
  for (let step = 0; step <= count; step += 1) {
1388
- const fraction = step * major / ticks;
1389
- const along = inset + (1 - 2 * inset) * fraction;
1390
- const labelBox = horizontal ? { x: box.x + box.width * along - 24, y: box.y + edge - fontSize * 2, width: 48, height: fontSize * 2 } : { x: box.x + edge - 48, y: box.y + box.height * (1 - along) - fontSize, width: 48, height: fontSize * 2 };
1412
+ const fraction = step * major / ticks2;
1413
+ const along2 = inset + (1 - 2 * inset) * fraction;
1414
+ const labelBox = horizontal ? { x: box.x + box.width * along2 - 24, y: box.y + edge - fontSize * 2, width: 48, height: fontSize * 2 } : { x: box.x + edge - 48, y: box.y + box.height * (1 - along2) - fontSize, width: 48, height: fontSize * 2 };
1391
1415
  nodes.push({
1392
1416
  id: `widget-${component.id}-label-${step}`,
1393
1417
  type: "text",
@@ -1423,7 +1447,9 @@ var numberProperty2 = (component, key) => Number(component.properties[key] ?? 0)
1423
1447
  var solid = (color) => ({ kind: "solid", color });
1424
1448
  var ink = (component, color) => component.disabled ? DISABLED_INK : color;
1425
1449
  function fade(component, style) {
1426
- return component.disabled ? { ...style, opacity: 0.4 } : style;
1450
+ const animate = Number(component.properties.animate ?? 0);
1451
+ const shown = component.disabled ? { ...style, opacity: 0.4 } : style;
1452
+ return animate > 0 ? { ...shown, transition: animate } : shown;
1427
1453
  }
1428
1454
  function hitArea(component, box) {
1429
1455
  return {
@@ -1556,6 +1582,463 @@ function buildCheckbox(component, index) {
1556
1582
  ];
1557
1583
  }
1558
1584
 
1585
+ // src/renderScene/artifacts/component/knob.ts
1586
+ var DOT_RATIO = 0.62;
1587
+ function decimals(step) {
1588
+ return step > 0 ? String(step).split(".")[1]?.length ?? 0 : 0;
1589
+ }
1590
+ function readout(component, fraction) {
1591
+ const display = textProperty(component, "display");
1592
+ if (display === "percent") {
1593
+ return `${Math.round(fraction * 100)}%`;
1594
+ }
1595
+ return display === "value" ? Number(component.value).toFixed(decimals(numberProperty2(component, "step"))) : "";
1596
+ }
1597
+ function buildKnob(component, index) {
1598
+ const box = controlBox(component, index, { width: 96, height: 96 });
1599
+ const min = numberProperty2(component, "min");
1600
+ const max = numberProperty2(component, "max");
1601
+ const fraction = Math.min(1, Math.max(0, (Number(component.value) - min) / (max - min || 1)));
1602
+ const start = numberProperty2(component, "start");
1603
+ const sweep = Math.min(360, Math.max(1, numberProperty2(component, "sweep")));
1604
+ const thickness = Math.min(numberProperty2(component, "thickness"), Math.min(box.width, box.height) / 3);
1605
+ const cx = box.x + box.width / 2;
1606
+ const cy = box.y + box.height / 2;
1607
+ const radius = Math.max(1, Math.min(box.width, box.height) / 2 - thickness / 2);
1608
+ const circumference = 2 * Math.PI * radius;
1609
+ const round2 = textProperty(component, "rounded") !== "false";
1610
+ const angle = (start - fraction * sweep) * Math.PI / 180;
1611
+ const arc = (part, order, color, length, extra = {}) => ({
1612
+ id: `widget-${component.id}-${part}`,
1613
+ type: "ellipse",
1614
+ order: box.order + order,
1615
+ bounds: rotatedBounds({ x: cx - radius, y: cy - radius, width: radius * 2, height: radius * 2 }, 0, thickness),
1616
+ cx,
1617
+ cy,
1618
+ rx: radius,
1619
+ ry: radius,
1620
+ rotation: -start,
1621
+ style: fade(component, {
1622
+ fill: { kind: "none" },
1623
+ stroke: solid(color),
1624
+ strokeWidth: thickness,
1625
+ dash: [Math.max(1e-3, length), circumference],
1626
+ lineCap: round2 ? "round" : "butt",
1627
+ ...extra
1628
+ })
1629
+ });
1630
+ const faceRadius = Math.max(1, radius - thickness / 2 - Math.max(2, thickness * 0.4));
1631
+ const dotRadius = thickness / 2 * DOT_RATIO + 1;
1632
+ const nodes = [
1633
+ hitArea(component, box),
1634
+ arc("track", 0.1, textProperty(component, "track"), sweep / 360 * circumference),
1635
+ arc("fill", 0.2, textProperty(component, "accent"), fraction * sweep / 360 * circumference, {
1636
+ opacity: fraction > 0 ? 1 : 0
1637
+ }),
1638
+ {
1639
+ id: `widget-${component.id}-face`,
1640
+ type: "ellipse",
1641
+ order: box.order + 0.3,
1642
+ bounds: rotatedBounds(
1643
+ { x: cx - faceRadius, y: cy - faceRadius, width: faceRadius * 2, height: faceRadius * 2 },
1644
+ 0,
1645
+ 0
1646
+ ),
1647
+ cx,
1648
+ cy,
1649
+ rx: faceRadius,
1650
+ ry: faceRadius,
1651
+ style: fade(component, { fill: solid(textProperty(component, "face")), stroke: { kind: "none" } })
1652
+ },
1653
+ {
1654
+ id: `widget-${component.id}-dot`,
1655
+ type: "ellipse",
1656
+ order: box.order + 0.4,
1657
+ bounds: rotatedBounds(
1658
+ {
1659
+ x: cx + radius * Math.cos(angle) - dotRadius,
1660
+ y: cy - radius * Math.sin(angle) - dotRadius,
1661
+ width: dotRadius * 2,
1662
+ height: dotRadius * 2
1663
+ },
1664
+ 0,
1665
+ 0
1666
+ ),
1667
+ cx: cx + radius * Math.cos(angle),
1668
+ cy: cy - radius * Math.sin(angle),
1669
+ rx: dotRadius,
1670
+ ry: dotRadius,
1671
+ style: fade(component, { fill: solid(textProperty(component, "dot")), stroke: { kind: "none" } })
1672
+ }
1673
+ ];
1674
+ const text = readout(component, fraction);
1675
+ if (text) {
1676
+ const label = {
1677
+ text,
1678
+ color: ink(component, textProperty(component, "textColor")),
1679
+ fontSize: numberProperty2(component, "fontSize"),
1680
+ align: "center"
1681
+ };
1682
+ nodes.push(
1683
+ labelText(
1684
+ component,
1685
+ "value",
1686
+ { x: cx - faceRadius, y: cy - faceRadius, width: faceRadius * 2, height: faceRadius * 2 },
1687
+ label,
1688
+ box.order + 0.5
1689
+ )
1690
+ );
1691
+ }
1692
+ return nodes;
1693
+ }
1694
+
1695
+ // src/renderScene/artifacts/component/progress.ts
1696
+ function readout2(component, fraction) {
1697
+ const display = textProperty(component, "display");
1698
+ if (display === "percent") {
1699
+ return `${Math.round(fraction * 100)}%`;
1700
+ }
1701
+ return display === "value" ? String(Number(component.value)) : "";
1702
+ }
1703
+ function buildProgress(component, index) {
1704
+ const box = controlBox(component, index, { width: 220, height: 12 });
1705
+ const min = numberProperty2(component, "min");
1706
+ const max = numberProperty2(component, "max");
1707
+ const fraction = Math.min(1, Math.max(0, (Number(component.value) - min) / (max - min || 1)));
1708
+ const round2 = textProperty(component, "rounded") !== "false";
1709
+ const nodes = [hitArea(component, box)];
1710
+ if (textProperty(component, "variant") === "ring") {
1711
+ const thickness = Math.min(numberProperty2(component, "thickness"), Math.min(box.width, box.height) / 2);
1712
+ const radius = Math.max(1, Math.min(box.width, box.height) / 2 - thickness / 2);
1713
+ const circumference = 2 * Math.PI * radius;
1714
+ const cx = box.x + box.width / 2;
1715
+ const cy = box.y + box.height / 2;
1716
+ const ring = (part, order, color, extra) => ({
1717
+ id: `widget-${component.id}-${part}`,
1718
+ type: "ellipse",
1719
+ order: box.order + order,
1720
+ bounds: rotatedBounds({ x: cx - radius, y: cy - radius, width: radius * 2, height: radius * 2 }, 0, thickness),
1721
+ cx,
1722
+ cy,
1723
+ rx: radius,
1724
+ ry: radius,
1725
+ rotation: -90,
1726
+ style: fade(component, { fill: { kind: "none" }, stroke: solid(color), strokeWidth: thickness, ...extra })
1727
+ });
1728
+ nodes.push(ring("track", 0.1, textProperty(component, "track"), {}));
1729
+ nodes.push(
1730
+ ring("fill", 0.2, textProperty(component, "accent"), {
1731
+ dash: [Math.max(1e-3, fraction * circumference), circumference],
1732
+ lineCap: round2 ? "round" : "butt",
1733
+ opacity: fraction > 0 ? 1 : 0
1734
+ })
1735
+ );
1736
+ } else {
1737
+ const vertical = textProperty(component, "direction") === "vertical";
1738
+ const radius = round2 ? (vertical ? box.width : box.height) / 2 : 0;
1739
+ const bar = (part, order, length, color, opacity) => {
1740
+ const shape = vertical ? { x: box.x, y: box.y + box.height - length, width: box.width, height: length } : { x: box.x, y: box.y, width: length, height: box.height };
1741
+ return {
1742
+ id: `widget-${component.id}-${part}`,
1743
+ type: "rect",
1744
+ order: box.order + order,
1745
+ bounds: rotatedBounds(shape, 0, 0),
1746
+ ...shape,
1747
+ rx: radius,
1748
+ style: fade(component, {
1749
+ fill: solid(color),
1750
+ stroke: { kind: "none" },
1751
+ ...opacity === void 0 ? {} : { opacity }
1752
+ })
1753
+ };
1754
+ };
1755
+ const full = vertical ? box.height : box.width;
1756
+ nodes.push(bar("track", 0.1, full, textProperty(component, "track")));
1757
+ nodes.push(bar("fill", 0.2, Math.max(0, fraction * full), textProperty(component, "accent"), fraction > 0 ? 1 : 0));
1758
+ }
1759
+ const text = readout2(component, fraction);
1760
+ if (text) {
1761
+ const label = {
1762
+ text,
1763
+ color: ink(component, textProperty(component, "textColor")),
1764
+ fontSize: numberProperty2(component, "fontSize"),
1765
+ align: "center"
1766
+ };
1767
+ nodes.push(labelText(component, "value", box, label, box.order + 0.3));
1768
+ }
1769
+ return nodes;
1770
+ }
1771
+
1772
+ // src/renderScene/artifacts/component/segmented.ts
1773
+ function buildSegmented(component, index) {
1774
+ const box = controlBox(component, index, { width: 300, height: 40 });
1775
+ const options = textProperty(component, "options").split(",").map((option) => option.trim()).filter(Boolean);
1776
+ const count = Math.max(1, options.length);
1777
+ const active = Math.min(count - 1, Math.max(0, Math.round(Number(component.value)) || 0));
1778
+ const inset = Math.min(numberProperty2(component, "inset"), box.height / 2);
1779
+ const radius = Math.min(numberProperty2(component, "radius"), box.height / 2);
1780
+ const cellWidth = (box.width - inset * 2) / count;
1781
+ const cell = { y: box.y + inset, height: box.height - inset * 2 };
1782
+ const nodes = [
1783
+ hitArea(component, box),
1784
+ {
1785
+ id: `widget-${component.id}-track`,
1786
+ type: "rect",
1787
+ order: box.order + 0.1,
1788
+ bounds: rotatedBounds(box, 0, 0),
1789
+ x: box.x,
1790
+ y: box.y,
1791
+ width: box.width,
1792
+ height: box.height,
1793
+ rx: radius,
1794
+ style: fade(component, { fill: solid(textProperty(component, "track")), stroke: { kind: "none" } })
1795
+ },
1796
+ {
1797
+ id: `widget-${component.id}-active`,
1798
+ type: "rect",
1799
+ order: box.order + 0.2,
1800
+ bounds: rotatedBounds({ x: box.x + inset + active * cellWidth, width: cellWidth, ...cell }, 0, 0),
1801
+ x: box.x + inset + active * cellWidth,
1802
+ y: cell.y,
1803
+ width: cellWidth,
1804
+ height: cell.height,
1805
+ rx: Math.max(0, radius - inset),
1806
+ style: fade(component, {
1807
+ fill: solid(textProperty(component, "accent")),
1808
+ stroke: { kind: "none" },
1809
+ shadow: { color: "#000000", opacity: 0.18, blur: 3, dx: 0, dy: 1 }
1810
+ })
1811
+ }
1812
+ ];
1813
+ options.forEach((option, position) => {
1814
+ const area = { x: box.x + inset + position * cellWidth, width: cellWidth, ...cell };
1815
+ const color = ink(component, textProperty(component, position === active ? "activeTextColor" : "textColor"));
1816
+ nodes.push(
1817
+ labelText(
1818
+ component,
1819
+ `option-${position}`,
1820
+ area,
1821
+ { text: option, color, fontSize: numberProperty2(component, "fontSize"), align: "center" },
1822
+ box.order + 0.3
1823
+ )
1824
+ );
1825
+ });
1826
+ return nodes;
1827
+ }
1828
+
1829
+ // src/model/component/sliderReach.ts
1830
+ function sliderReach(variant2, height) {
1831
+ return variant2 === "field" ? Math.min(8, height / 2) : height / 2;
1832
+ }
1833
+
1834
+ // src/renderScene/artifacts/component/slider.ts
1835
+ var HANDLE_WIDTH = 4;
1836
+ var TEXT_PADDING = 12;
1837
+ var TICK_LENGTH = 5;
1838
+ var TICK_THICKNESS = 1.5;
1839
+ function decimals2(step) {
1840
+ return step > 0 ? String(step).split(".")[1]?.length ?? 0 : 0;
1841
+ }
1842
+ function readout3(component, thumbs) {
1843
+ const display = textProperty(component, "display");
1844
+ const places = decimals2(numberProperty2(component, "step"));
1845
+ const parts = display === "percent" ? thumbs.two ? [thumbs.from, thumbs.to].map((fraction) => `${Math.round(fraction * 100)}%`) : [`${Math.round(thumbs.to * 100)}%`] : display === "value" ? thumbs.values.map((value) => value.toFixed(places)) : [];
1846
+ return parts.join(" \u2013 ");
1847
+ }
1848
+ var rect = (component, box, part, order, shape, color, extra = {}) => ({
1849
+ id: `widget-${component.id}-${part}`,
1850
+ type: "rect",
1851
+ order: box.order + order,
1852
+ bounds: rotatedBounds(shape, 0, 0),
1853
+ ...shape,
1854
+ style: fade(component, { fill: solid(color), stroke: { kind: "none" }, ...extra })
1855
+ });
1856
+ function ticks(component, box, vertical, reach, offset) {
1857
+ const count = Math.round(numberProperty2(component, "ticks"));
1858
+ const color = textProperty(component, "tickColor");
1859
+ return Array.from({ length: count >= 2 ? count : 0 }, (_, index) => {
1860
+ const t = index / (count - 1);
1861
+ const shape = vertical ? {
1862
+ x: box.x + offset,
1863
+ y: box.y + box.height - reach - t * (box.height - reach * 2) - TICK_THICKNESS / 2,
1864
+ width: TICK_LENGTH,
1865
+ height: TICK_THICKNESS,
1866
+ rx: TICK_THICKNESS / 2
1867
+ } : {
1868
+ x: box.x + reach + t * (box.width - reach * 2) - TICK_THICKNESS / 2,
1869
+ y: box.y + offset,
1870
+ width: TICK_THICKNESS,
1871
+ height: TICK_LENGTH,
1872
+ rx: TICK_THICKNESS / 2
1873
+ };
1874
+ return rect(component, box, `tick-${index}`, 0.15, shape, color);
1875
+ });
1876
+ }
1877
+ function buildLine(component, box, thumbs, vertical) {
1878
+ const reach = sliderReach("line", vertical ? box.width : box.height);
1879
+ const radius = reach * numberProperty2(component, "thumbSize") / 100;
1880
+ const thickness = Math.min(numberProperty2(component, "trackHeight"), vertical ? box.width : box.height);
1881
+ const mid = vertical ? box.x + box.width / 2 : box.y + box.height / 2;
1882
+ const along2 = (fraction) => vertical ? box.y + box.height - reach - fraction * (box.height - reach * 2) : box.x + reach + fraction * (box.width - reach * 2);
1883
+ const line = (start, end) => vertical ? {
1884
+ x: mid - thickness / 2,
1885
+ y: Math.min(start, end),
1886
+ width: thickness,
1887
+ height: Math.abs(end - start),
1888
+ rx: thickness / 2
1889
+ } : {
1890
+ x: Math.min(start, end),
1891
+ y: mid - thickness / 2,
1892
+ width: Math.abs(end - start),
1893
+ height: thickness,
1894
+ rx: thickness / 2
1895
+ };
1896
+ const whole = vertical ? line(box.y, box.y + box.height) : line(box.x, box.x + box.width);
1897
+ const filled = line(thumbs.two ? along2(thumbs.from) : vertical ? box.y + box.height : box.x, along2(thumbs.to));
1898
+ const thumb = (part, fraction, order) => {
1899
+ const cx = vertical ? mid : along2(fraction);
1900
+ const cy = vertical ? along2(fraction) : mid;
1901
+ return {
1902
+ id: `widget-${component.id}-${part}`,
1903
+ type: "ellipse",
1904
+ order: box.order + order,
1905
+ bounds: rotatedBounds({ x: cx - radius, y: cy - radius, width: radius * 2, height: radius * 2 }, 0, 0),
1906
+ cx,
1907
+ cy,
1908
+ rx: radius,
1909
+ ry: radius,
1910
+ style: fade(component, {
1911
+ fill: solid(textProperty(component, "thumb")),
1912
+ stroke: { kind: "none" },
1913
+ shadow: { color: "#000000", opacity: 0.25, blur: 3, dx: 0, dy: 1 }
1914
+ })
1915
+ };
1916
+ };
1917
+ return [
1918
+ rect(component, box, "track", 0.1, whole, textProperty(component, "track")),
1919
+ ...ticks(
1920
+ component,
1921
+ box,
1922
+ vertical,
1923
+ reach,
1924
+ vertical ? box.width / 2 + thickness / 2 + 5 : box.height / 2 + thickness / 2 + 5
1925
+ ),
1926
+ rect(component, box, "fill", 0.2, filled, textProperty(component, "accent")),
1927
+ ...thumbs.two ? [thumb("thumb-start", thumbs.from, 0.3)] : [],
1928
+ thumb(thumbs.two ? "thumb-end" : "thumb", thumbs.to, 0.31)
1929
+ ];
1930
+ }
1931
+ function buildField(component, box, thumbs, vertical) {
1932
+ const reach = sliderReach("field", vertical ? box.width : box.height);
1933
+ const radius = Math.min(numberProperty2(component, "radius"), Math.min(box.width, box.height) / 2);
1934
+ const whole = { x: box.x, y: box.y, width: box.width, height: box.height, rx: radius };
1935
+ const along2 = (fraction) => vertical ? box.y + box.height - reach - fraction * (box.height - reach * 2) : box.x + reach + fraction * (box.width - reach * 2);
1936
+ const start = thumbs.two ? along2(thumbs.from) : vertical ? box.y + box.height : box.x;
1937
+ const end = along2(thumbs.to);
1938
+ const first = Math.min(start, end) - (thumbs.two ? HANDLE_WIDTH / 2 : 0);
1939
+ const last = Math.max(start, end) + HANDLE_WIDTH / 2;
1940
+ const filled = vertical ? {
1941
+ ...whole,
1942
+ y: thumbs.two ? first : end - HANDLE_WIDTH / 2,
1943
+ height: thumbs.two ? last - first : Math.max(0, box.y + box.height - end + HANDLE_WIDTH / 2),
1944
+ rx: thumbs.two ? 0 : radius
1945
+ } : {
1946
+ ...whole,
1947
+ x: thumbs.two ? first : box.x,
1948
+ width: thumbs.two ? last - first : Math.max(0, end + HANDLE_WIDTH / 2 - box.x),
1949
+ rx: thumbs.two ? 0 : radius
1950
+ };
1951
+ const handleLength = (vertical ? box.width : box.height) * 0.5;
1952
+ const handle = (part, at) => {
1953
+ const shape = vertical ? {
1954
+ x: box.x + (box.width - handleLength) / 2,
1955
+ y: at - HANDLE_WIDTH / 2,
1956
+ width: handleLength,
1957
+ height: HANDLE_WIDTH,
1958
+ rx: HANDLE_WIDTH / 2
1959
+ } : {
1960
+ x: at - HANDLE_WIDTH / 2,
1961
+ y: box.y + (box.height - handleLength) / 2,
1962
+ width: HANDLE_WIDTH,
1963
+ height: handleLength,
1964
+ rx: HANDLE_WIDTH / 2
1965
+ };
1966
+ return rect(component, box, part, 0.3, shape, textProperty(component, "accent"));
1967
+ };
1968
+ const nodes = [
1969
+ rect(component, box, "track", 0.1, whole, textProperty(component, "surface")),
1970
+ rect(component, box, "fill", 0.2, filled, textProperty(component, "fill")),
1971
+ ...thumbs.two ? [handle("handle-start", start)] : [],
1972
+ handle(thumbs.two ? "handle-end" : "handle", end)
1973
+ ];
1974
+ const text = {
1975
+ color: ink(component, textProperty(component, "textColor")),
1976
+ fontSize: numberProperty2(component, "fontSize")
1977
+ };
1978
+ const value = readout3(component, thumbs);
1979
+ if (vertical) {
1980
+ if (value) {
1981
+ nodes.push(
1982
+ labelText(
1983
+ component,
1984
+ "value",
1985
+ { x: box.x, y: box.y + 6, width: box.width, height: 20 },
1986
+ { ...text, text: value, align: "center" },
1987
+ box.order + 0.4
1988
+ )
1989
+ );
1990
+ }
1991
+ return nodes;
1992
+ }
1993
+ const inner = { y: box.y, height: box.height, width: Math.max(0, box.width / 2 - TEXT_PADDING) };
1994
+ if (component.label) {
1995
+ nodes.push(
1996
+ labelText(
1997
+ component,
1998
+ "label",
1999
+ { x: box.x + TEXT_PADDING, ...inner },
2000
+ { ...text, text: component.label, align: "left" },
2001
+ box.order + 0.4
2002
+ )
2003
+ );
2004
+ }
2005
+ if (value) {
2006
+ nodes.push(
2007
+ labelText(
2008
+ component,
2009
+ "value",
2010
+ { x: box.x + box.width / 2, ...inner },
2011
+ { ...text, text: value, align: "right" },
2012
+ box.order + 0.4
2013
+ )
2014
+ );
2015
+ }
2016
+ nodes.push(...ticks(component, box, false, reach, box.height - TICK_LENGTH - 5));
2017
+ return nodes;
2018
+ }
2019
+ function buildSlider(component, index) {
2020
+ const field = textProperty(component, "variant") === "field";
2021
+ const vertical = textProperty(component, "direction") === "vertical";
2022
+ const fallback = vertical ? { width: field ? 56 : 28, height: 180 } : { width: 220, height: field ? 36 : 28 };
2023
+ const box = controlBox(component, index, fallback);
2024
+ const min = numberProperty2(component, "min");
2025
+ const max = numberProperty2(component, "max");
2026
+ const fractionOf = (value) => Math.min(1, Math.max(0, (value - min) / (max - min || 1)));
2027
+ const two = component.type === "range";
2028
+ const low = Number(component.value);
2029
+ const high = two ? Number(component.properties.valueEnd ?? max) : low;
2030
+ const thumbs = {
2031
+ from: fractionOf(two ? Math.min(low, high) : min),
2032
+ to: fractionOf(two ? Math.max(low, high) : low),
2033
+ values: two ? [Math.min(low, high), Math.max(low, high)] : [low],
2034
+ two
2035
+ };
2036
+ return [
2037
+ hitArea(component, box),
2038
+ ...field ? buildField(component, box, thumbs, vertical) : buildLine(component, box, thumbs, vertical)
2039
+ ];
2040
+ }
2041
+
1559
2042
  // src/renderScene/artifacts/component/switch.ts
1560
2043
  var PADDING_RATIO = 0.12;
1561
2044
  function buildSwitch(component, index) {
@@ -1644,7 +2127,12 @@ var builders = /* @__PURE__ */ new Map([
1644
2127
  ["switch", asComponentBuilder(buildSwitch)],
1645
2128
  ["checkbox", asComponentBuilder(buildCheckbox)],
1646
2129
  ["toggleButton", asComponentBuilder(buildToggleButton)],
1647
- ["button", asComponentBuilder(buildButton)]
2130
+ ["button", asComponentBuilder(buildButton)],
2131
+ ["slider", asComponentBuilder(buildSlider)],
2132
+ ["progress", asComponentBuilder(buildProgress)],
2133
+ ["segmented", asComponentBuilder(buildSegmented)],
2134
+ ["knob", asComponentBuilder(buildKnob)],
2135
+ ["range", asComponentBuilder(buildSlider)]
1648
2136
  ]);
1649
2137
  function registerComponentBuilder(type, builder) {
1650
2138
  builders.set(type, builder);
@@ -2058,7 +2546,130 @@ function buildContainers(input) {
2058
2546
  ];
2059
2547
  }
2060
2548
 
2061
- // src/renderScene/artifacts/isometric.ts
2549
+ // src/model/dimension/geometry.ts
2550
+ var GAP = 4;
2551
+ var OVERSHOOT = 6;
2552
+ var along = (origin, direction, distance) => ({
2553
+ x: origin.x + direction.x * distance,
2554
+ y: origin.y + direction.y * distance
2555
+ });
2556
+ function dimensionLength(dimension) {
2557
+ return Math.hypot(dimension.end.x - dimension.start.x, dimension.end.y - dimension.start.y);
2558
+ }
2559
+ function dimensionText(dimension) {
2560
+ if (dimension.text !== void 0) {
2561
+ return dimension.text;
2562
+ }
2563
+ const length = Math.round(dimensionLength(dimension) * 10) / 10;
2564
+ return `${length}${dimension.unit ? ` ${dimension.unit}` : ""}`;
2565
+ }
2566
+ function dimensionGeometry(dimension) {
2567
+ const length = dimensionLength(dimension);
2568
+ const direction = length === 0 ? { x: 1, y: 0 } : { x: (dimension.end.x - dimension.start.x) / length, y: (dimension.end.y - dimension.start.y) / length };
2569
+ const normal = { x: direction.y, y: -direction.x };
2570
+ const side = dimension.offset < 0 ? -1 : 1;
2571
+ const line = [
2572
+ along(dimension.start, normal, dimension.offset),
2573
+ along(dimension.end, normal, dimension.offset)
2574
+ ];
2575
+ const extensions = Math.abs(dimension.offset) <= GAP ? [] : [dimension.start, dimension.end].map((point) => [
2576
+ along(point, normal, GAP * side),
2577
+ along(point, normal, dimension.offset + OVERSHOOT * side)
2578
+ ]);
2579
+ const lift = ((dimension.fontSize ?? 11) * 0.75 + 2) * side;
2580
+ const middle = { x: (line[0].x + line[1].x) / 2, y: (line[0].y + line[1].y) / 2 };
2581
+ let angle = Math.atan2(direction.y, direction.x) * 180 / Math.PI;
2582
+ if (angle > 90) {
2583
+ angle -= 180;
2584
+ } else if (angle <= -90) {
2585
+ angle += 180;
2586
+ }
2587
+ return { length, line, extensions, label: { center: along(middle, normal, lift), angle } };
2588
+ }
2589
+
2590
+ // src/renderScene/artifacts/dimension.ts
2591
+ var DEFAULT_COLOR = "#475569";
2592
+ var CHAR_WIDTH = 0.6;
2593
+ var pathData = (segments) => segments.map(([from, to]) => `M ${from.x} ${from.y} L ${to.x} ${to.y}`).join(" ");
2594
+ function pathNode(dimension, name, order, segments) {
2595
+ const strokeWidth = Math.max(0, finite(dimension.strokeWidth, 1));
2596
+ const points = segments.flat();
2597
+ return {
2598
+ type: "path",
2599
+ id: `dimension-${dimension.id}-${name}`,
2600
+ order,
2601
+ bounds: {
2602
+ minX: Math.min(...points.map((point) => point.x)) - strokeWidth,
2603
+ minY: Math.min(...points.map((point) => point.y)) - strokeWidth,
2604
+ maxX: Math.max(...points.map((point) => point.x)) + strokeWidth,
2605
+ maxY: Math.max(...points.map((point) => point.y)) + strokeWidth
2606
+ },
2607
+ d: pathData(segments),
2608
+ style: {
2609
+ fill: { kind: "none" },
2610
+ stroke: { kind: "solid", color: dimension.strokeColor ?? DEFAULT_COLOR },
2611
+ strokeWidth,
2612
+ lineCap: "round"
2613
+ }
2614
+ };
2615
+ }
2616
+ function labelNode2(dimension, order, text, center, angle) {
2617
+ const fontSize = finite(dimension.fontSize, 11);
2618
+ const width = Math.max(24, text.length * fontSize * CHAR_WIDTH + 8);
2619
+ const height = fontSize * 1.3;
2620
+ return {
2621
+ type: "text",
2622
+ id: `dimension-${dimension.id}-label`,
2623
+ order,
2624
+ bounds: {
2625
+ minX: center.x - width / 2,
2626
+ minY: center.y - height / 2,
2627
+ maxX: center.x + width / 2,
2628
+ maxY: center.y + height / 2
2629
+ },
2630
+ x: center.x - width / 2,
2631
+ y: center.y - height / 2,
2632
+ width,
2633
+ height,
2634
+ lines: [text],
2635
+ fontFamily: DEFAULT_FONT,
2636
+ fontSize,
2637
+ fontWeight: "normal",
2638
+ color: dimension.textColor ?? dimension.strokeColor ?? DEFAULT_COLOR,
2639
+ align: "center",
2640
+ verticalAlign: "middle",
2641
+ lineHeight: 1.2,
2642
+ rotation: angle,
2643
+ rotationCenter: center
2644
+ };
2645
+ }
2646
+ function buildDimension(dimension, index) {
2647
+ const geometry = dimensionGeometry(dimension);
2648
+ const order = 31e3 + index;
2649
+ const line = {
2650
+ ...pathNode(dimension, "line", order + 0.1, [geometry.line]),
2651
+ markerStart: "filled_arrow",
2652
+ markerEnd: "filled_arrow"
2653
+ };
2654
+ const extensions = geometry.extensions.length > 0 ? [pathNode(dimension, "extensions", order, geometry.extensions)] : [];
2655
+ const text = dimensionText(dimension);
2656
+ return [...extensions, line, labelNode2(dimension, order + 0.2, text, geometry.label.center, geometry.label.angle)];
2657
+ }
2658
+ function buildDimensions(dimensions) {
2659
+ return dimensions.flatMap(
2660
+ (dimension, index) => tag(
2661
+ buildDimension(dimension, index),
2662
+ "dimension",
2663
+ dimension.id,
2664
+ "dimension",
2665
+ dimensionText(dimension),
2666
+ dimension.parentFrameId
2667
+ )
2668
+ );
2669
+ }
2670
+
2671
+ // src/renderScene/artifacts/isometric/context.ts
2672
+ var FILL_PROP = { prop: "style.fill", propKind: "color", propSolidOnly: true };
2062
2673
  function isometricContext(object, index) {
2063
2674
  const strokeWidth = Math.max(0, finite(object.strokeWidth, 1));
2064
2675
  const rotation = finite(object.rotation, 0);
@@ -2085,82 +2696,19 @@ function isometricContext(object, index) {
2085
2696
  }
2086
2697
  };
2087
2698
  }
2088
- function groundShadowNode(context, faces) {
2089
- const { object, index, rotation, rotationCenter } = context;
2090
- if (!object.hasShadow) {
2091
- return void 0;
2092
- }
2093
- const height = Math.max(0, object.height);
2094
- const heightFactor = 0.6 + Math.min(1, height / 150) * 0.7;
2095
- const shadowDrop = height + finite(object.shadowStyle?.distance, 0);
2096
- const contactFootprint = faces.top.map((point) => ({ x: point.x, y: point.y + shadowDrop }));
2097
- const footprintCenter = {
2098
- x: contactFootprint.reduce((sum, point) => sum + point.x, 0) / contactFootprint.length,
2099
- y: contactFootprint.reduce((sum, point) => sum + point.y, 0) / contactFootprint.length
2100
- };
2101
- const shadowSpread = 1.3;
2102
- const footprint = contactFootprint.map((point) => ({
2103
- x: footprintCenter.x + (point.x - footprintCenter.x) * shadowSpread,
2104
- y: footprintCenter.y + (point.y - footprintCenter.y) * shadowSpread
2105
- }));
2106
- const footprintXs = footprint.map((point) => point.x);
2107
- const footprintYs = footprint.map((point) => point.y);
2699
+ function faceNode(context, name, offset, points, style) {
2108
2700
  return {
2109
- type: "path",
2110
- id: `isometric-${object.id}-ground-shadow`,
2111
- order: 14e3 + index,
2112
- bounds: {
2113
- minX: Math.min(...footprintXs),
2114
- minY: Math.min(...footprintYs),
2115
- maxX: Math.max(...footprintXs),
2116
- maxY: Math.max(...footprintYs)
2117
- },
2118
- d: roundedPolygonPath(footprint, 0),
2119
- rotation,
2120
- rotationCenter,
2121
- style: {
2122
- fill: { kind: "solid", color: object.shadowStyle?.color ?? "#000000" },
2123
- stroke: { kind: "none" },
2124
- opacity: Math.min(1, (object.shadowStyle?.opacity ?? 0.18) * heightFactor),
2125
- blur: finite(object.shadowStyle?.blur, 8),
2126
- pointerEvents: "none"
2127
- }
2701
+ ...context.common,
2702
+ id: `isometric-${context.object.id}-${name}`,
2703
+ order: context.order + offset,
2704
+ d: roundedPolygonPath([...points], 0),
2705
+ style,
2706
+ ...FILL_PROP
2128
2707
  };
2129
2708
  }
2130
- function faceNodes(context, faces, hullClip) {
2131
- const { object, order, common } = context;
2132
- const noStroke = { ...common.style, stroke: { kind: "none" } };
2133
- const faceFills = deriveFaceFills(object.fill ?? "#f8fafc");
2134
- const colorProp = { prop: "style.fill", propKind: "color", propSolidOnly: true };
2135
- const face = (name, offset, points, color) => ({
2136
- ...common,
2137
- id: `isometric-${object.id}-${name}`,
2138
- order: order + offset,
2139
- d: roundedPolygonPath(points, 0),
2140
- style: { ...noStroke, fill: { kind: "solid", color }, clip: hullClip },
2141
- ...colorProp
2142
- });
2143
- return [
2144
- face("top", 0, faces.top, faceFills.topFill),
2145
- face("front", 0.1, faces.front, faceFills.frontFill),
2146
- face("side", 0.2, faces.right, faceFills.sideFill)
2147
- ];
2148
- }
2149
- function seamsNode(context, faces, hullClip) {
2150
- const { object, order, common, strokeWidth } = context;
2151
- return {
2152
- ...common,
2153
- id: `isometric-${object.id}-seams`,
2154
- order: order + 0.22,
2155
- d: `M ${faces.top[3].x} ${faces.top[3].y} L ${faces.top[2].x} ${faces.top[2].y} L ${faces.top[1].x} ${faces.top[1].y} M ${faces.top[2].x} ${faces.top[2].y} L ${faces.front[2].x} ${faces.front[2].y}`,
2156
- style: {
2157
- ...common.style,
2158
- fill: { kind: "none" },
2159
- stroke: { kind: "solid", color: "#cbd5e1" },
2160
- strokeWidth: Math.min(strokeWidth, 1),
2161
- clip: hullClip
2162
- }
2163
- };
2709
+ function silhouette(object) {
2710
+ const faces = isometricFaces(object);
2711
+ return [faces.top[0], faces.top[1], faces.right[2], faces.front[2], faces.front[3], faces.top[3]];
2164
2712
  }
2165
2713
  function hullNode(context, hullPath, cornerRadius) {
2166
2714
  const { object, order, common, box } = context;
@@ -2182,6 +2730,14 @@ function hullNode(context, hullPath, cornerRadius) {
2182
2730
  style: { ...common.style, fill: { kind: "none" } }
2183
2731
  };
2184
2732
  }
2733
+ function unseenHullNode(context) {
2734
+ return {
2735
+ ...hullNode(context, roundedPolygonPath(silhouette(context.object), 0), 0),
2736
+ style: { ...context.common.style, fill: { kind: "none" }, stroke: { kind: "none" } }
2737
+ };
2738
+ }
2739
+
2740
+ // src/renderScene/artifacts/isometric/label.ts
2185
2741
  var LABEL_HEIGHT = 20;
2186
2742
  var LABEL_GAP = 12;
2187
2743
  var LABEL_PADDING_X = 6;
@@ -2277,20 +2833,232 @@ function labelNodes(context, text) {
2277
2833
  }
2278
2834
  return [guide, labelBackgroundNode(context, placement, text, background), label];
2279
2835
  }
2280
- function buildIsometricObject(object, index) {
2836
+
2837
+ // src/renderScene/artifacts/isometric/shadow.ts
2838
+ function groundShadowNode(context, topOutline) {
2839
+ const { object, index, rotation, rotationCenter } = context;
2840
+ if (!object.hasShadow) {
2841
+ return void 0;
2842
+ }
2843
+ const height = Math.max(0, object.height);
2844
+ const heightFactor = 0.6 + Math.min(1, height / 150) * 0.7;
2845
+ const shadowDrop = height + finite(object.shadowStyle?.distance, 0);
2846
+ const contactFootprint = topOutline.map((point) => ({ x: point.x, y: point.y + shadowDrop }));
2847
+ const footprintCenter = {
2848
+ x: contactFootprint.reduce((sum, point) => sum + point.x, 0) / contactFootprint.length,
2849
+ y: contactFootprint.reduce((sum, point) => sum + point.y, 0) / contactFootprint.length
2850
+ };
2851
+ const shadowSpread = 1.3;
2852
+ const footprint = contactFootprint.map((point) => ({
2853
+ x: footprintCenter.x + (point.x - footprintCenter.x) * shadowSpread,
2854
+ y: footprintCenter.y + (point.y - footprintCenter.y) * shadowSpread
2855
+ }));
2856
+ const footprintXs = footprint.map((point) => point.x);
2857
+ const footprintYs = footprint.map((point) => point.y);
2858
+ return {
2859
+ type: "path",
2860
+ id: `isometric-${object.id}-ground-shadow`,
2861
+ order: 14e3 + index,
2862
+ bounds: {
2863
+ minX: Math.min(...footprintXs),
2864
+ minY: Math.min(...footprintYs),
2865
+ maxX: Math.max(...footprintXs),
2866
+ maxY: Math.max(...footprintYs)
2867
+ },
2868
+ d: roundedPolygonPath(footprint, 0),
2869
+ rotation,
2870
+ rotationCenter,
2871
+ style: {
2872
+ fill: { kind: "solid", color: object.shadowStyle?.color ?? "#000000" },
2873
+ stroke: { kind: "none" },
2874
+ opacity: Math.min(1, (object.shadowStyle?.opacity ?? 0.18) * heightFactor),
2875
+ blur: finite(object.shadowStyle?.blur, 8),
2876
+ pointerEvents: "none"
2877
+ }
2878
+ };
2879
+ }
2880
+ function sphereShadowNode(context, radius) {
2881
+ const { object, index, box } = context;
2882
+ if (!object.hasShadow) {
2883
+ return void 0;
2884
+ }
2885
+ const width = Math.max(0, object.width);
2886
+ const depth = Math.max(0, object.depth);
2887
+ const center = {
2888
+ x: box.x + box.width / 2,
2889
+ y: object.y + Math.max(0, object.height) + (width + depth) * AXIS_SIN / 2
2890
+ };
2891
+ return {
2892
+ type: "ellipse",
2893
+ id: `isometric-${object.id}-ground-shadow`,
2894
+ order: 14e3 + index,
2895
+ bounds: {
2896
+ minX: center.x - radius * 1.1,
2897
+ minY: center.y - radius * 0.6,
2898
+ maxX: center.x + radius * 1.1,
2899
+ maxY: center.y + radius * 0.6
2900
+ },
2901
+ cx: center.x,
2902
+ cy: center.y,
2903
+ rx: radius * 1.05,
2904
+ ry: radius * 0.52,
2905
+ style: {
2906
+ fill: { kind: "solid", color: object.shadowStyle?.color ?? "#000000" },
2907
+ stroke: { kind: "none" },
2908
+ opacity: object.shadowStyle?.opacity ?? 0.2,
2909
+ blur: finite(object.shadowStyle?.blur, 8),
2910
+ pointerEvents: "none"
2911
+ }
2912
+ };
2913
+ }
2914
+
2915
+ // src/renderScene/artifacts/isometric/box.ts
2916
+ function faceNodes(context, faces, hullClip) {
2917
+ const { object, common } = context;
2918
+ const noStroke = { ...common.style, stroke: { kind: "none" } };
2919
+ const fills = deriveFaceFills(object.fill ?? "#f8fafc");
2920
+ const face = (name, offset, points, color) => faceNode(context, name, offset, points, { ...noStroke, fill: { kind: "solid", color }, clip: hullClip });
2921
+ return [
2922
+ face("top", 0, faces.top, fills.topFill),
2923
+ face("front", 0.1, faces.front, fills.frontFill),
2924
+ face("side", 0.2, faces.right, fills.sideFill)
2925
+ ];
2926
+ }
2927
+ function seamsNode(context, faces, hullClip) {
2928
+ const { object, order, common, strokeWidth } = context;
2929
+ return {
2930
+ ...common,
2931
+ id: `isometric-${object.id}-seams`,
2932
+ order: order + 0.22,
2933
+ d: `M ${faces.top[3].x} ${faces.top[3].y} L ${faces.top[2].x} ${faces.top[2].y} L ${faces.top[1].x} ${faces.top[1].y} M ${faces.top[2].x} ${faces.top[2].y} L ${faces.front[2].x} ${faces.front[2].y}`,
2934
+ style: {
2935
+ ...common.style,
2936
+ fill: { kind: "none" },
2937
+ stroke: { kind: "solid", color: "#cbd5e1" },
2938
+ strokeWidth: Math.min(strokeWidth, 1),
2939
+ clip: hullClip
2940
+ }
2941
+ };
2942
+ }
2943
+ function buildBox(object, index) {
2281
2944
  const context = isometricContext(object, index);
2282
2945
  const faces = isometricFaces(object);
2283
2946
  const cornerRadius = Math.max(0, finite(object.cornerRadius, 8));
2284
- const silhouette = [faces.top[0], faces.top[1], faces.right[2], faces.front[2], faces.front[3], faces.top[3]];
2285
- const hullPath = roundedPolygonPath(silhouette, cornerRadius);
2947
+ const hullPath = roundedPolygonPath(silhouette(object), cornerRadius);
2286
2948
  const hullClip = { type: "path", d: hullPath };
2287
- const groundShadow = groundShadowNode(context, faces);
2949
+ const groundShadow = groundShadowNode(context, faces.top);
2288
2950
  const seams = seamsNode(context, faces, hullClip);
2289
2951
  const hull = hullNode(context, hullPath, cornerRadius);
2290
2952
  const facesNodes = faceNodes(context, faces, hullClip);
2291
2953
  const objectNodes = groundShadow ? [hull, ...facesNodes, groundShadow, seams] : [hull, ...facesNodes, seams];
2292
2954
  return object.text ? [...objectNodes, ...labelNodes(context, object.text)] : objectNodes;
2293
2955
  }
2956
+
2957
+ // src/renderScene/artifacts/isometric/extruded.ts
2958
+ function wallNode(context, side, index, fill2) {
2959
+ const color = shadeFill(fill2, side.light);
2960
+ return faceNode(context, `side-${index}`, 0.05 + index * 1e-3, side.points, {
2961
+ ...context.common.style,
2962
+ stroke: { kind: "solid", color },
2963
+ strokeWidth: 0.6,
2964
+ fill: { kind: "solid", color }
2965
+ });
2966
+ }
2967
+ function wallEdgesNode(context, side, index) {
2968
+ const [topFrom, topTo, bottomTo, bottomFrom] = side.points;
2969
+ const lines = [
2970
+ `M ${bottomFrom.x} ${bottomFrom.y} L ${bottomTo.x} ${bottomTo.y}`,
2971
+ ...side.smoothStart ? [] : [`M ${topFrom.x} ${topFrom.y} L ${bottomFrom.x} ${bottomFrom.y}`],
2972
+ ...side.smoothEnd ? [] : [`M ${topTo.x} ${topTo.y} L ${bottomTo.x} ${bottomTo.y}`]
2973
+ ];
2974
+ return {
2975
+ ...context.common,
2976
+ id: `isometric-${context.object.id}-side-${index}-edges`,
2977
+ order: context.order + 0.0505 + index * 1e-3,
2978
+ d: lines.join(" "),
2979
+ style: { ...context.common.style, fill: { kind: "none" } }
2980
+ };
2981
+ }
2982
+ function buildExtruded(object, index, footprint) {
2983
+ const context = isometricContext(object, index);
2984
+ const { top, sides } = extrudeFootprint(object, footprint, Math.max(0, finite(object.cornerRadius, 0)));
2985
+ const fill2 = object.fill ?? "#f8fafc";
2986
+ const groundShadow = groundShadowNode(context, top);
2987
+ const topFace = faceNode(context, "top", 0.2, top, { ...context.common.style, fill: { kind: "solid", color: fill2 } });
2988
+ const nodes = [
2989
+ unseenHullNode(context),
2990
+ ...groundShadow ? [groundShadow] : [],
2991
+ ...sides.flatMap((side, i) => [wallNode(context, side, i, fill2), wallEdgesNode(context, side, i)]),
2992
+ topFace
2993
+ ];
2994
+ return object.text ? [...nodes, ...labelNodes(context, object.text)] : nodes;
2995
+ }
2996
+
2997
+ // src/renderScene/artifacts/isometric/sphere.ts
2998
+ function buildSphere(object, index) {
2999
+ const context = isometricContext(object, index);
3000
+ const { order, common, box } = context;
3001
+ const radius = Math.max(0, Math.min(object.width, object.height, object.depth)) / 2;
3002
+ const cx = box.x + box.width / 2;
3003
+ const cy = box.y + box.height / 2;
3004
+ const fill2 = object.fill ?? "#f8fafc";
3005
+ const bounds = { minX: cx - radius, minY: cy - radius, maxX: cx + radius, maxY: cy + radius };
3006
+ const body = {
3007
+ type: "ellipse",
3008
+ id: `isometric-${object.id}-sphere`,
3009
+ order: order + 0.1,
3010
+ bounds,
3011
+ cx,
3012
+ cy,
3013
+ rx: radius,
3014
+ ry: radius,
3015
+ style: {
3016
+ ...common.style,
3017
+ fill: {
3018
+ kind: "linear-gradient",
3019
+ angle: 135,
3020
+ stops: [
3021
+ { offset: 0, color: shadeFill(fill2, 1.22) },
3022
+ { offset: 0.5, color: fill2 },
3023
+ { offset: 1, color: shadeFill(fill2, 0.82) }
3024
+ ]
3025
+ }
3026
+ },
3027
+ prop: "style.fill",
3028
+ propKind: "color",
3029
+ propSolidOnly: true
3030
+ };
3031
+ const highlight = {
3032
+ type: "ellipse",
3033
+ id: `isometric-${object.id}-highlight`,
3034
+ order: order + 0.2,
3035
+ bounds,
3036
+ cx: cx - radius * 0.32,
3037
+ cy: cy - radius * 0.38,
3038
+ rx: radius * 0.26,
3039
+ ry: radius * 0.18,
3040
+ rotation: -35,
3041
+ style: {
3042
+ fill: { kind: "solid", color: "#ffffff" },
3043
+ stroke: { kind: "none" },
3044
+ opacity: 0.45,
3045
+ blur: radius * 0.1,
3046
+ pointerEvents: "none"
3047
+ }
3048
+ };
3049
+ const shadow = sphereShadowNode(context, radius);
3050
+ const nodes = [unseenHullNode(context), ...shadow ? [shadow] : [], body, highlight];
3051
+ return object.text ? [...nodes, ...labelNodes(context, object.text)] : nodes;
3052
+ }
3053
+
3054
+ // src/renderScene/artifacts/isometric/index.ts
3055
+ function buildIsometricObject(object, index) {
3056
+ if (object.form === "sphere") {
3057
+ return buildSphere(object, index);
3058
+ }
3059
+ const footprint = cleanFootprint(object.footprint);
3060
+ return footprint.length > 0 ? buildExtruded(object, index, footprint) : buildBox(object, index);
3061
+ }
2294
3062
  function buildIsometricObjects(objects) {
2295
3063
  return objects.flatMap(
2296
3064
  (object, index) => tag(
@@ -2497,7 +3265,7 @@ function polylinePathData(points) {
2497
3265
  }
2498
3266
  return path;
2499
3267
  }
2500
- function pathData(points, pathType, segments, strokeWidth) {
3268
+ function pathData2(points, pathType, segments, strokeWidth) {
2501
3269
  if (points.length < 4) {
2502
3270
  return "";
2503
3271
  }
@@ -2531,7 +3299,7 @@ function renderLinkPath(context) {
2531
3299
  id: `link-${link.id}`,
2532
3300
  order: context.order,
2533
3301
  bounds: context.bounds,
2534
- d: pathData(context.points, context.pathType, context.segments, context.strokeWidth),
3302
+ d: pathData2(context.points, context.pathType, context.segments, context.strokeWidth),
2535
3303
  style: context.style,
2536
3304
  markerStart: markerForEnd(link, "start"),
2537
3305
  markerEnd: markerForEnd(link, "end"),
@@ -2769,6 +3537,46 @@ function renderShapeGeometry(context) {
2769
3537
  return renderer(context);
2770
3538
  }
2771
3539
 
3540
+ // src/renderScene/artifacts/shape/shaderSurface.ts
3541
+ var RECT_PROGRAMS = /* @__PURE__ */ new Set(["reactivePanel", "ledMatrix", "lightBand", "silkFolds"]);
3542
+ function shaderMask(context) {
3543
+ if (context.shape.shapeType === "circle" || context.shape.shapeType === "oval") {
3544
+ return "ellipse";
3545
+ }
3546
+ const rectangular = context.shape.shapeType === "rectangle" || context.shape.shapeType === "rounded_rectangle";
3547
+ if (rectangular && context.shape.shader && RECT_PROGRAMS.has(context.shape.shader.program)) {
3548
+ return "rect";
3549
+ }
3550
+ return void 0;
3551
+ }
3552
+ function renderShapeShaderSurface(context) {
3553
+ if (!context.shape.shader) {
3554
+ return void 0;
3555
+ }
3556
+ const mask = shaderMask(context);
3557
+ if (!mask) {
3558
+ return void 0;
3559
+ }
3560
+ const padding = mask === "rect" ? Math.max(0, context.shape.shader.surfacePadding ?? 0) : 0;
3561
+ const surfaceBounds = {
3562
+ x: context.x - padding,
3563
+ y: context.y - padding,
3564
+ width: context.width + padding * 2,
3565
+ height: context.height + padding * 2
3566
+ };
3567
+ return {
3568
+ id: `${context.id}-shader`,
3569
+ type: "shader-surface",
3570
+ order: context.order,
3571
+ bounds: rotatedBounds(surfaceBounds, context.rotation, 0),
3572
+ ...surfaceBounds,
3573
+ rotation: context.rotation,
3574
+ shader: context.shape.shader,
3575
+ mask,
3576
+ fillColor: context.style.fill?.kind === "solid" ? context.style.fill.color : void 0
3577
+ };
3578
+ }
3579
+
2772
3580
  // src/renderScene/artifacts/shape/style.ts
2773
3581
  var REMOVED_SHAPE_HINTS = {
2774
3582
  container_rectangle: " (use 'rectangle' with strokeStyle: dashed)"
@@ -3011,32 +3819,13 @@ function createRenderContext(shape, index, diagnostics) {
3011
3819
  }
3012
3820
  };
3013
3821
  }
3014
- function renderShaderSurface(context) {
3015
- if (!context.shape.shader || context.shape.shapeType !== "circle" && context.shape.shapeType !== "oval") {
3016
- return void 0;
3017
- }
3018
- return {
3019
- id: `${context.id}-shader`,
3020
- type: "shader-surface",
3021
- order: context.order,
3022
- bounds: context.bounds,
3023
- x: context.x,
3024
- y: context.y,
3025
- width: context.width,
3026
- height: context.height,
3027
- rotation: context.rotation,
3028
- shader: context.shape.shader,
3029
- mask: "ellipse",
3030
- fillColor: context.style.fill?.kind === "solid" ? context.style.fill.color : void 0
3031
- };
3032
- }
3033
3822
  function buildShape(shape, index, diagnostics, measureText) {
3034
3823
  if (shape.isVisible === false) {
3035
3824
  return [];
3036
3825
  }
3037
3826
  const { context, strokeWidth } = createRenderContext(shape, index, diagnostics);
3038
3827
  const nodes = shape.strokeStyle === "double" ? renderDoubleStroke(context, strokeWidth || 1) : renderShapeGeometry(context);
3039
- const shader = renderShaderSurface(context);
3828
+ const shader = renderShapeShaderSurface(context);
3040
3829
  if (shader) {
3041
3830
  for (const node of nodes) {
3042
3831
  if (node.type === "ellipse" || node.type === "path" || node.type === "rect") {
@@ -3868,19 +4657,19 @@ function buildChartBackdrop(chart, bounds, order) {
3868
4657
  if (!chart.fillImage) {
3869
4658
  return [];
3870
4659
  }
3871
- const rect = chartImageRect(chart);
4660
+ const rect2 = chartImageRect(chart);
3872
4661
  const nodes = [
3873
4662
  {
3874
4663
  type: "image",
3875
4664
  id: `chart-image-${chart.id}`,
3876
4665
  order: order.next(),
3877
4666
  bounds,
3878
- x: rect.x,
3879
- y: rect.y,
3880
- width: rect.width,
3881
- height: rect.height,
4667
+ x: rect2.x,
4668
+ y: rect2.y,
4669
+ width: rect2.width,
4670
+ height: rect2.height,
3882
4671
  href: chart.fillImage.url,
3883
- style: { clip: { type: "rect", ...rect }, pointerEvents: "none" }
4672
+ style: { clip: { type: "rect", ...rect2 }, pointerEvents: "none" }
3884
4673
  }
3885
4674
  ];
3886
4675
  if (chart.fillImage.overlay) {
@@ -3889,11 +4678,11 @@ function buildChartBackdrop(chart, bounds, order) {
3889
4678
  id: `chart-image-overlay-${chart.id}`,
3890
4679
  order: order.next(),
3891
4680
  bounds,
3892
- x: rect.x,
3893
- y: rect.y,
3894
- width: rect.width,
3895
- height: rect.height,
3896
- rx: rect.rx,
4681
+ x: rect2.x,
4682
+ y: rect2.y,
4683
+ width: rect2.width,
4684
+ height: rect2.height,
4685
+ rx: rect2.rx,
3897
4686
  style: { fill: { kind: "solid", color: chart.fillImage.overlay }, pointerEvents: "none" }
3898
4687
  });
3899
4688
  }
@@ -3907,17 +4696,17 @@ function createGlassBackdropNodes(context, id, d) {
3907
4696
  if (blur <= 0 || !chart.fillImage) {
3908
4697
  return [];
3909
4698
  }
3910
- const rect = chartImageRect(chart);
4699
+ const rect2 = chartImageRect(chart);
3911
4700
  const nodes = [
3912
4701
  {
3913
4702
  type: "image",
3914
4703
  id: `chart-bar-glass-${chart.id}-${id}`,
3915
4704
  order: nextOrder(),
3916
4705
  bounds,
3917
- x: rect.x,
3918
- y: rect.y,
3919
- width: rect.width,
3920
- height: rect.height,
4706
+ x: rect2.x,
4707
+ y: rect2.y,
4708
+ width: rect2.width,
4709
+ height: rect2.height,
3921
4710
  href: chart.fillImage.url,
3922
4711
  style: {
3923
4712
  blur,
@@ -6165,7 +6954,7 @@ function dotNode(context, mark) {
6165
6954
  }
6166
6955
  };
6167
6956
  }
6168
- function labelNode2(context, mark, value) {
6957
+ function labelNode3(context, mark, value) {
6169
6958
  const { chart, bounds, nextOrder } = context;
6170
6959
  const config = chart.config;
6171
6960
  const fontSize = Math.max(9, chart.fontSize ?? 12);
@@ -6218,7 +7007,7 @@ function renderLineHighlights(context, series, color) {
6218
7007
  }
6219
7008
  nodes.push(dotNode(context, mark));
6220
7009
  if (config?.highlightLabels) {
6221
- nodes.push(labelNode2(context, mark, pairs[index][1]));
7010
+ nodes.push(labelNode3(context, mark, pairs[index][1]));
6222
7011
  }
6223
7012
  }
6224
7013
  return nodes;
@@ -7887,7 +8676,7 @@ function treemapLeafColor(leaf, layout) {
7887
8676
 
7888
8677
  // src/renderScene/charts/renderers/treemap/legend.ts
7889
8678
  var BAR_THICKNESS = 10;
7890
- var TICK_LENGTH = 4;
8679
+ var TICK_LENGTH2 = 4;
7891
8680
  var ROW_GAP2 = 2;
7892
8681
  var CHART_GAP = 16;
7893
8682
  var LABEL_SIZE = 34;
@@ -7935,14 +8724,14 @@ function renderBottomLegend(context, layout) {
7935
8724
  strokeWidth: 1
7936
8725
  }
7937
8726
  };
7938
- const ticks = layout.bands.flatMap((value, index) => {
8727
+ const ticks2 = layout.bands.flatMap((value, index) => {
7939
8728
  const x = barX + bandRatio2(layout, value) * barWidth;
7940
8729
  const tick = {
7941
8730
  type: "path",
7942
8731
  id: `chart-treemap-legend-tick-${chart.id}-${index}`,
7943
8732
  order: nextOrder(),
7944
8733
  bounds,
7945
- d: `M ${x} ${barY + BAR_THICKNESS} L ${x} ${barY + BAR_THICKNESS + TICK_LENGTH}`,
8734
+ d: `M ${x} ${barY + BAR_THICKNESS} L ${x} ${barY + BAR_THICKNESS + TICK_LENGTH2}`,
7946
8735
  style: {
7947
8736
  fill: { kind: "none" },
7948
8737
  stroke: { kind: "solid", color: chart.gridColor ?? "#e2e8f0" },
@@ -7957,14 +8746,14 @@ function renderBottomLegend(context, layout) {
7957
8746
  id: `chart-treemap-legend-tick-label-${chart.id}-${index}`,
7958
8747
  order: nextOrder(),
7959
8748
  bounds,
7960
- frame: { x: frameX, y: barY + BAR_THICKNESS + TICK_LENGTH + ROW_GAP2, width: LABEL_SIZE, height: labelHeight },
8749
+ frame: { x: frameX, y: barY + BAR_THICKNESS + TICK_LENGTH2 + ROW_GAP2, width: LABEL_SIZE, height: labelHeight },
7961
8750
  text: formatFieldValue(value),
7962
8751
  chart,
7963
8752
  align
7964
8753
  });
7965
8754
  return [tick, label];
7966
8755
  });
7967
- return [bar, ...ticks];
8756
+ return [bar, ...ticks2];
7968
8757
  }
7969
8758
  function renderSideLegend(context, layout) {
7970
8759
  const { chart, plot, bounds, nextOrder } = context;
@@ -7992,9 +8781,9 @@ function renderSideLegend(context, layout) {
7992
8781
  }
7993
8782
  };
7994
8783
  const tickX = side === "left" ? barX : barX + BAR_THICKNESS;
7995
- const tickEndX = side === "left" ? tickX - TICK_LENGTH : tickX + TICK_LENGTH;
8784
+ const tickEndX = side === "left" ? tickX - TICK_LENGTH2 : tickX + TICK_LENGTH2;
7996
8785
  const labelX2 = side === "left" ? tickEndX - ROW_GAP2 - LABEL_SIZE : tickEndX + ROW_GAP2;
7997
- const ticks = layout.bands.flatMap((value, index) => {
8786
+ const ticks2 = layout.bands.flatMap((value, index) => {
7998
8787
  const y = barTop + (1 - bandRatio2(layout, value)) * barHeight;
7999
8788
  const tick = {
8000
8789
  type: "path",
@@ -8019,7 +8808,7 @@ function renderSideLegend(context, layout) {
8019
8808
  });
8020
8809
  return [tick, label];
8021
8810
  });
8022
- return [bar, ...ticks];
8811
+ return [bar, ...ticks2];
8023
8812
  }
8024
8813
 
8025
8814
  // src/renderScene/charts/renderers/treemap/tiles.ts
@@ -8512,6 +9301,7 @@ function stackingOf(input) {
8512
9301
  );
8513
9302
  add("chart", input.charts ?? [], 2e4);
8514
9303
  add("path", input.paths ?? [], 3e4);
9304
+ add("dimension", input.dimensions ?? [], 31e3);
8515
9305
  return stacking;
8516
9306
  }
8517
9307
  function stampStacking(nodes, input) {
@@ -8532,7 +9322,8 @@ function buildRenderScene(input, options = {}) {
8532
9322
  ...buildLinks(input.links, measureText),
8533
9323
  ...buildShapes(input.shapes, diagnostics, measureText),
8534
9324
  ...buildComponents(input.components ?? input.widgets ?? []),
8535
- ...buildIsometricObjects(input.isometricObjects ?? [])
9325
+ ...buildIsometricObjects(input.isometricObjects ?? []),
9326
+ ...buildDimensions(input.dimensions ?? [])
8536
9327
  ];
8537
9328
  stampStacking(nodes, input);
8538
9329
  nodes.sort(
@@ -8842,6 +9633,12 @@ function addStrokeAttrs(attrs, style) {
8842
9633
  if (style.pointerEvents) {
8843
9634
  attrs.push(`pointer-events="${style.pointerEvents}"`);
8844
9635
  }
9636
+ if (style.transition && style.transition > 0) {
9637
+ const time = `${num(style.transition)}ms ease`;
9638
+ attrs.push(
9639
+ `style="transition: x ${time}, y ${time}, width ${time}, height ${time}, cx ${time}, cy ${time}, rx ${time}, ry ${time}, fill ${time}, stroke ${time}, stroke-width ${time}, stroke-dasharray ${time}, opacity ${time}"`
9640
+ );
9641
+ }
8845
9642
  }
8846
9643
  function elementSize(node) {
8847
9644
  const shape = node;
@@ -9091,8 +9888,9 @@ function lineOffset(index, linePx) {
9091
9888
  function shaderSurfaceSvg(node, defs) {
9092
9889
  const rotation = transform(node.rotation, { x: node.x + node.width / 2, y: node.y + node.height / 2 });
9093
9890
  const parameters = xml(JSON.stringify(node.shader.parameters));
9891
+ const surfacePadding = node.shader.surfacePadding ?? 0;
9094
9892
  const fillColor = node.fillColor ? ` data-sf-shader-fill="${xml(node.fillColor)}"` : "";
9095
- return `<foreignObject id="${defs.elementId(node.id)}"${contractAttrs(node)} data-sf-shader="${xml(node.shader.program)}" data-sf-shader-name="${xml(node.shader.name)}" data-sf-shader-params="${parameters}" data-sf-shader-mask="${node.mask}"${fillColor} x="${num(node.x)}" y="${num(node.y)}" width="${num(node.width)}" height="${num(node.height)}"${rotation} pointer-events="${node.shader.program === "ruler" || node.identity?.role === "widget" ? "all" : "none"}"><canvas xmlns="http://www.w3.org/1999/xhtml" data-sf-shader-canvas="true" style="display:block;width:100%;height:100%;pointer-events:none"></canvas></foreignObject>`;
9893
+ return `<foreignObject id="${defs.elementId(node.id)}"${contractAttrs(node)} data-sf-shader="${xml(node.shader.program)}" data-sf-shader-name="${xml(node.shader.name)}" data-sf-shader-params="${parameters}" data-sf-shader-mask="${node.mask}" data-sf-shader-padding="${num(surfacePadding)}"${fillColor} x="${num(node.x)}" y="${num(node.y)}" width="${num(node.width)}" height="${num(node.height)}"${rotation} pointer-events="${node.shader.program === "ruler" || node.identity?.role === "widget" ? "all" : "none"}"><canvas xmlns="http://www.w3.org/1999/xhtml" data-sf-shader-canvas="true" style="display:block;width:100%;height:100%;pointer-events:none"></canvas></foreignObject>`;
9096
9894
  }
9097
9895
  function rollingDigitSvg(character, node) {
9098
9896
  const style = node.componentStyle;
@@ -9207,6 +10005,6 @@ function defineComponent(definition) {
9207
10005
  };
9208
10006
  }
9209
10007
 
9210
- export { collectCanvasObjects, decodeColor, decodeShadow, defineComponent, render, renderCanvas, sflToRenderInput };
9211
- //# sourceMappingURL=chunk-LTGF5OHP.js.map
9212
- //# sourceMappingURL=chunk-LTGF5OHP.js.map
10008
+ export { collectCanvasObjects, decodeColor, decodeShadow, defineComponent, render, renderCanvas, sflToRenderInput, sliderReach };
10009
+ //# sourceMappingURL=chunk-SDMQRSRW.js.map
10010
+ //# sourceMappingURL=chunk-SDMQRSRW.js.map