stickyflow 0.5.0 → 0.6.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 (58) hide show
  1. package/CHANGELOG.md +16 -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-IEHE6WVN.js → chunk-4G2R7PEL.js} +319 -45
  7. package/dist/chunk-4G2R7PEL.js.map +1 -0
  8. package/dist/{chunk-L3VJXZFD.cjs → chunk-4LENHH6C.cjs} +15 -15
  9. package/dist/{chunk-L3VJXZFD.cjs.map → chunk-4LENHH6C.cjs.map} +1 -1
  10. package/dist/{chunk-LTGF5OHP.js → chunk-FVHVOJS2.js} +395 -89
  11. package/dist/chunk-FVHVOJS2.js.map +1 -0
  12. package/dist/{chunk-TWDLOXRM.cjs → chunk-JIJMZMGY.cjs} +18 -18
  13. package/dist/{chunk-TWDLOXRM.cjs.map → chunk-JIJMZMGY.cjs.map} +1 -1
  14. package/dist/{chunk-VK3T6O5Z.cjs → chunk-KTNCDNDB.cjs} +33 -33
  15. package/dist/{chunk-VK3T6O5Z.cjs.map → chunk-KTNCDNDB.cjs.map} +1 -1
  16. package/dist/{chunk-BODZN3ZI.js → chunk-MFNUJA26.js} +4 -4
  17. package/dist/{chunk-BODZN3ZI.js.map → chunk-MFNUJA26.js.map} +1 -1
  18. package/dist/{chunk-7VW2XKVB.js → chunk-ULQZ6CZW.js} +3 -3
  19. package/dist/{chunk-7VW2XKVB.js.map → chunk-ULQZ6CZW.js.map} +1 -1
  20. package/dist/{chunk-ZMLQIMJK.cjs → chunk-WQRT5PVT.cjs} +993 -687
  21. package/dist/chunk-WQRT5PVT.cjs.map +1 -0
  22. package/dist/{chunk-G7NRK5AG.js → chunk-WRDVNMFS.js} +5 -5
  23. package/dist/{chunk-G7NRK5AG.js.map → chunk-WRDVNMFS.js.map} +1 -1
  24. package/dist/{chunk-XY2GZUHC.cjs → chunk-XJ4W6TW4.cjs} +326 -44
  25. package/dist/chunk-XJ4W6TW4.cjs.map +1 -0
  26. package/dist/index.cjs +49 -29
  27. package/dist/index.d.cts +52 -7
  28. package/dist/index.d.ts +52 -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-Db0eSz_s.d.cts} +36 -15
  37. package/dist/{render-CgX_y15a.d.cts → render-Db0eSz_s.d.ts} +36 -15
  38. package/dist/{runtime-reWgr7MP.d.cts → runtime-BhivvBeL.d.cts} +2 -2
  39. package/dist/{runtime-DnUxca3Y.d.ts → runtime-n2yG-_j-.d.ts} +2 -2
  40. package/dist/{runtimeTypes-D60w6nyF.d.cts → runtimeTypes-CrkMHvVi.d.cts} +2 -2
  41. package/dist/{runtimeTypes-CEBGueYM.d.ts → runtimeTypes-DnI7mRF5.d.ts} +2 -2
  42. package/dist/stickyflow-diagram.global.js +35 -35
  43. package/dist/stickyflow-diagram.global.js.map +1 -1
  44. package/dist/{types-DvhMpqrL.d.cts → types-BHfUKT4s.d.cts} +1 -1
  45. package/dist/{types-DYLC_lsk.d.ts → types-D4cH4f1a.d.ts} +1 -1
  46. package/dist/viewer/index.cjs +9 -9
  47. package/dist/viewer/index.d.cts +4 -4
  48. package/dist/viewer/index.d.ts +4 -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-IEHE6WVN.js.map +0 -1
  56. package/dist/chunk-LTGF5OHP.js.map +0 -1
  57. package/dist/chunk-XY2GZUHC.cjs.map +0 -1
  58. 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-4G2R7PEL.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),
@@ -1386,8 +1410,8 @@ function buildRulerLabels(component, box) {
1386
1410
  const nodes = [];
1387
1411
  for (let step = 0; step <= count; step += 1) {
1388
1412
  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 };
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",
@@ -2058,7 +2082,130 @@ function buildContainers(input) {
2058
2082
  ];
2059
2083
  }
2060
2084
 
2061
- // src/renderScene/artifacts/isometric.ts
2085
+ // src/model/dimension/geometry.ts
2086
+ var GAP = 4;
2087
+ var OVERSHOOT = 6;
2088
+ var along = (origin, direction, distance) => ({
2089
+ x: origin.x + direction.x * distance,
2090
+ y: origin.y + direction.y * distance
2091
+ });
2092
+ function dimensionLength(dimension) {
2093
+ return Math.hypot(dimension.end.x - dimension.start.x, dimension.end.y - dimension.start.y);
2094
+ }
2095
+ function dimensionText(dimension) {
2096
+ if (dimension.text !== void 0) {
2097
+ return dimension.text;
2098
+ }
2099
+ const length = Math.round(dimensionLength(dimension) * 10) / 10;
2100
+ return `${length}${dimension.unit ? ` ${dimension.unit}` : ""}`;
2101
+ }
2102
+ function dimensionGeometry(dimension) {
2103
+ const length = dimensionLength(dimension);
2104
+ const direction = length === 0 ? { x: 1, y: 0 } : { x: (dimension.end.x - dimension.start.x) / length, y: (dimension.end.y - dimension.start.y) / length };
2105
+ const normal = { x: direction.y, y: -direction.x };
2106
+ const side = dimension.offset < 0 ? -1 : 1;
2107
+ const line = [
2108
+ along(dimension.start, normal, dimension.offset),
2109
+ along(dimension.end, normal, dimension.offset)
2110
+ ];
2111
+ const extensions = Math.abs(dimension.offset) <= GAP ? [] : [dimension.start, dimension.end].map((point) => [
2112
+ along(point, normal, GAP * side),
2113
+ along(point, normal, dimension.offset + OVERSHOOT * side)
2114
+ ]);
2115
+ const lift = ((dimension.fontSize ?? 11) * 0.75 + 2) * side;
2116
+ const middle = { x: (line[0].x + line[1].x) / 2, y: (line[0].y + line[1].y) / 2 };
2117
+ let angle = Math.atan2(direction.y, direction.x) * 180 / Math.PI;
2118
+ if (angle > 90) {
2119
+ angle -= 180;
2120
+ } else if (angle <= -90) {
2121
+ angle += 180;
2122
+ }
2123
+ return { length, line, extensions, label: { center: along(middle, normal, lift), angle } };
2124
+ }
2125
+
2126
+ // src/renderScene/artifacts/dimension.ts
2127
+ var DEFAULT_COLOR = "#475569";
2128
+ var CHAR_WIDTH = 0.6;
2129
+ var pathData = (segments) => segments.map(([from, to]) => `M ${from.x} ${from.y} L ${to.x} ${to.y}`).join(" ");
2130
+ function pathNode(dimension, name, order, segments) {
2131
+ const strokeWidth = Math.max(0, finite(dimension.strokeWidth, 1));
2132
+ const points = segments.flat();
2133
+ return {
2134
+ type: "path",
2135
+ id: `dimension-${dimension.id}-${name}`,
2136
+ order,
2137
+ bounds: {
2138
+ minX: Math.min(...points.map((point) => point.x)) - strokeWidth,
2139
+ minY: Math.min(...points.map((point) => point.y)) - strokeWidth,
2140
+ maxX: Math.max(...points.map((point) => point.x)) + strokeWidth,
2141
+ maxY: Math.max(...points.map((point) => point.y)) + strokeWidth
2142
+ },
2143
+ d: pathData(segments),
2144
+ style: {
2145
+ fill: { kind: "none" },
2146
+ stroke: { kind: "solid", color: dimension.strokeColor ?? DEFAULT_COLOR },
2147
+ strokeWidth,
2148
+ lineCap: "round"
2149
+ }
2150
+ };
2151
+ }
2152
+ function labelNode2(dimension, order, text, center, angle) {
2153
+ const fontSize = finite(dimension.fontSize, 11);
2154
+ const width = Math.max(24, text.length * fontSize * CHAR_WIDTH + 8);
2155
+ const height = fontSize * 1.3;
2156
+ return {
2157
+ type: "text",
2158
+ id: `dimension-${dimension.id}-label`,
2159
+ order,
2160
+ bounds: {
2161
+ minX: center.x - width / 2,
2162
+ minY: center.y - height / 2,
2163
+ maxX: center.x + width / 2,
2164
+ maxY: center.y + height / 2
2165
+ },
2166
+ x: center.x - width / 2,
2167
+ y: center.y - height / 2,
2168
+ width,
2169
+ height,
2170
+ lines: [text],
2171
+ fontFamily: DEFAULT_FONT,
2172
+ fontSize,
2173
+ fontWeight: "normal",
2174
+ color: dimension.textColor ?? dimension.strokeColor ?? DEFAULT_COLOR,
2175
+ align: "center",
2176
+ verticalAlign: "middle",
2177
+ lineHeight: 1.2,
2178
+ rotation: angle,
2179
+ rotationCenter: center
2180
+ };
2181
+ }
2182
+ function buildDimension(dimension, index) {
2183
+ const geometry = dimensionGeometry(dimension);
2184
+ const order = 31e3 + index;
2185
+ const line = {
2186
+ ...pathNode(dimension, "line", order + 0.1, [geometry.line]),
2187
+ markerStart: "filled_arrow",
2188
+ markerEnd: "filled_arrow"
2189
+ };
2190
+ const extensions = geometry.extensions.length > 0 ? [pathNode(dimension, "extensions", order, geometry.extensions)] : [];
2191
+ const text = dimensionText(dimension);
2192
+ return [...extensions, line, labelNode2(dimension, order + 0.2, text, geometry.label.center, geometry.label.angle)];
2193
+ }
2194
+ function buildDimensions(dimensions) {
2195
+ return dimensions.flatMap(
2196
+ (dimension, index) => tag(
2197
+ buildDimension(dimension, index),
2198
+ "dimension",
2199
+ dimension.id,
2200
+ "dimension",
2201
+ dimensionText(dimension),
2202
+ dimension.parentFrameId
2203
+ )
2204
+ );
2205
+ }
2206
+
2207
+ // src/renderScene/artifacts/isometric/context.ts
2208
+ var FILL_PROP = { prop: "style.fill", propKind: "color", propSolidOnly: true };
2062
2209
  function isometricContext(object, index) {
2063
2210
  const strokeWidth = Math.max(0, finite(object.strokeWidth, 1));
2064
2211
  const rotation = finite(object.rotation, 0);
@@ -2085,82 +2232,19 @@ function isometricContext(object, index) {
2085
2232
  }
2086
2233
  };
2087
2234
  }
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);
2235
+ function faceNode(context, name, offset, points, style) {
2108
2236
  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
- }
2237
+ ...context.common,
2238
+ id: `isometric-${context.object.id}-${name}`,
2239
+ order: context.order + offset,
2240
+ d: roundedPolygonPath([...points], 0),
2241
+ style,
2242
+ ...FILL_PROP
2128
2243
  };
2129
2244
  }
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
- };
2245
+ function silhouette(object) {
2246
+ const faces = isometricFaces(object);
2247
+ return [faces.top[0], faces.top[1], faces.right[2], faces.front[2], faces.front[3], faces.top[3]];
2164
2248
  }
2165
2249
  function hullNode(context, hullPath, cornerRadius) {
2166
2250
  const { object, order, common, box } = context;
@@ -2182,6 +2266,14 @@ function hullNode(context, hullPath, cornerRadius) {
2182
2266
  style: { ...common.style, fill: { kind: "none" } }
2183
2267
  };
2184
2268
  }
2269
+ function unseenHullNode(context) {
2270
+ return {
2271
+ ...hullNode(context, roundedPolygonPath(silhouette(context.object), 0), 0),
2272
+ style: { ...context.common.style, fill: { kind: "none" }, stroke: { kind: "none" } }
2273
+ };
2274
+ }
2275
+
2276
+ // src/renderScene/artifacts/isometric/label.ts
2185
2277
  var LABEL_HEIGHT = 20;
2186
2278
  var LABEL_GAP = 12;
2187
2279
  var LABEL_PADDING_X = 6;
@@ -2277,20 +2369,232 @@ function labelNodes(context, text) {
2277
2369
  }
2278
2370
  return [guide, labelBackgroundNode(context, placement, text, background), label];
2279
2371
  }
2280
- function buildIsometricObject(object, index) {
2372
+
2373
+ // src/renderScene/artifacts/isometric/shadow.ts
2374
+ function groundShadowNode(context, topOutline) {
2375
+ const { object, index, rotation, rotationCenter } = context;
2376
+ if (!object.hasShadow) {
2377
+ return void 0;
2378
+ }
2379
+ const height = Math.max(0, object.height);
2380
+ const heightFactor = 0.6 + Math.min(1, height / 150) * 0.7;
2381
+ const shadowDrop = height + finite(object.shadowStyle?.distance, 0);
2382
+ const contactFootprint = topOutline.map((point) => ({ x: point.x, y: point.y + shadowDrop }));
2383
+ const footprintCenter = {
2384
+ x: contactFootprint.reduce((sum, point) => sum + point.x, 0) / contactFootprint.length,
2385
+ y: contactFootprint.reduce((sum, point) => sum + point.y, 0) / contactFootprint.length
2386
+ };
2387
+ const shadowSpread = 1.3;
2388
+ const footprint = contactFootprint.map((point) => ({
2389
+ x: footprintCenter.x + (point.x - footprintCenter.x) * shadowSpread,
2390
+ y: footprintCenter.y + (point.y - footprintCenter.y) * shadowSpread
2391
+ }));
2392
+ const footprintXs = footprint.map((point) => point.x);
2393
+ const footprintYs = footprint.map((point) => point.y);
2394
+ return {
2395
+ type: "path",
2396
+ id: `isometric-${object.id}-ground-shadow`,
2397
+ order: 14e3 + index,
2398
+ bounds: {
2399
+ minX: Math.min(...footprintXs),
2400
+ minY: Math.min(...footprintYs),
2401
+ maxX: Math.max(...footprintXs),
2402
+ maxY: Math.max(...footprintYs)
2403
+ },
2404
+ d: roundedPolygonPath(footprint, 0),
2405
+ rotation,
2406
+ rotationCenter,
2407
+ style: {
2408
+ fill: { kind: "solid", color: object.shadowStyle?.color ?? "#000000" },
2409
+ stroke: { kind: "none" },
2410
+ opacity: Math.min(1, (object.shadowStyle?.opacity ?? 0.18) * heightFactor),
2411
+ blur: finite(object.shadowStyle?.blur, 8),
2412
+ pointerEvents: "none"
2413
+ }
2414
+ };
2415
+ }
2416
+ function sphereShadowNode(context, radius) {
2417
+ const { object, index, box } = context;
2418
+ if (!object.hasShadow) {
2419
+ return void 0;
2420
+ }
2421
+ const width = Math.max(0, object.width);
2422
+ const depth = Math.max(0, object.depth);
2423
+ const center = {
2424
+ x: box.x + box.width / 2,
2425
+ y: object.y + Math.max(0, object.height) + (width + depth) * AXIS_SIN / 2
2426
+ };
2427
+ return {
2428
+ type: "ellipse",
2429
+ id: `isometric-${object.id}-ground-shadow`,
2430
+ order: 14e3 + index,
2431
+ bounds: {
2432
+ minX: center.x - radius * 1.1,
2433
+ minY: center.y - radius * 0.6,
2434
+ maxX: center.x + radius * 1.1,
2435
+ maxY: center.y + radius * 0.6
2436
+ },
2437
+ cx: center.x,
2438
+ cy: center.y,
2439
+ rx: radius * 1.05,
2440
+ ry: radius * 0.52,
2441
+ style: {
2442
+ fill: { kind: "solid", color: object.shadowStyle?.color ?? "#000000" },
2443
+ stroke: { kind: "none" },
2444
+ opacity: object.shadowStyle?.opacity ?? 0.2,
2445
+ blur: finite(object.shadowStyle?.blur, 8),
2446
+ pointerEvents: "none"
2447
+ }
2448
+ };
2449
+ }
2450
+
2451
+ // src/renderScene/artifacts/isometric/box.ts
2452
+ function faceNodes(context, faces, hullClip) {
2453
+ const { object, common } = context;
2454
+ const noStroke = { ...common.style, stroke: { kind: "none" } };
2455
+ const fills = deriveFaceFills(object.fill ?? "#f8fafc");
2456
+ const face = (name, offset, points, color) => faceNode(context, name, offset, points, { ...noStroke, fill: { kind: "solid", color }, clip: hullClip });
2457
+ return [
2458
+ face("top", 0, faces.top, fills.topFill),
2459
+ face("front", 0.1, faces.front, fills.frontFill),
2460
+ face("side", 0.2, faces.right, fills.sideFill)
2461
+ ];
2462
+ }
2463
+ function seamsNode(context, faces, hullClip) {
2464
+ const { object, order, common, strokeWidth } = context;
2465
+ return {
2466
+ ...common,
2467
+ id: `isometric-${object.id}-seams`,
2468
+ order: order + 0.22,
2469
+ 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}`,
2470
+ style: {
2471
+ ...common.style,
2472
+ fill: { kind: "none" },
2473
+ stroke: { kind: "solid", color: "#cbd5e1" },
2474
+ strokeWidth: Math.min(strokeWidth, 1),
2475
+ clip: hullClip
2476
+ }
2477
+ };
2478
+ }
2479
+ function buildBox(object, index) {
2281
2480
  const context = isometricContext(object, index);
2282
2481
  const faces = isometricFaces(object);
2283
2482
  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);
2483
+ const hullPath = roundedPolygonPath(silhouette(object), cornerRadius);
2286
2484
  const hullClip = { type: "path", d: hullPath };
2287
- const groundShadow = groundShadowNode(context, faces);
2485
+ const groundShadow = groundShadowNode(context, faces.top);
2288
2486
  const seams = seamsNode(context, faces, hullClip);
2289
2487
  const hull = hullNode(context, hullPath, cornerRadius);
2290
2488
  const facesNodes = faceNodes(context, faces, hullClip);
2291
2489
  const objectNodes = groundShadow ? [hull, ...facesNodes, groundShadow, seams] : [hull, ...facesNodes, seams];
2292
2490
  return object.text ? [...objectNodes, ...labelNodes(context, object.text)] : objectNodes;
2293
2491
  }
2492
+
2493
+ // src/renderScene/artifacts/isometric/extruded.ts
2494
+ function wallNode(context, side, index, fill2) {
2495
+ const color = shadeFill(fill2, side.light);
2496
+ return faceNode(context, `side-${index}`, 0.05 + index * 1e-3, side.points, {
2497
+ ...context.common.style,
2498
+ stroke: { kind: "solid", color },
2499
+ strokeWidth: 0.6,
2500
+ fill: { kind: "solid", color }
2501
+ });
2502
+ }
2503
+ function wallEdgesNode(context, side, index) {
2504
+ const [topFrom, topTo, bottomTo, bottomFrom] = side.points;
2505
+ const lines = [
2506
+ `M ${bottomFrom.x} ${bottomFrom.y} L ${bottomTo.x} ${bottomTo.y}`,
2507
+ ...side.smoothStart ? [] : [`M ${topFrom.x} ${topFrom.y} L ${bottomFrom.x} ${bottomFrom.y}`],
2508
+ ...side.smoothEnd ? [] : [`M ${topTo.x} ${topTo.y} L ${bottomTo.x} ${bottomTo.y}`]
2509
+ ];
2510
+ return {
2511
+ ...context.common,
2512
+ id: `isometric-${context.object.id}-side-${index}-edges`,
2513
+ order: context.order + 0.0505 + index * 1e-3,
2514
+ d: lines.join(" "),
2515
+ style: { ...context.common.style, fill: { kind: "none" } }
2516
+ };
2517
+ }
2518
+ function buildExtruded(object, index, footprint) {
2519
+ const context = isometricContext(object, index);
2520
+ const { top, sides } = extrudeFootprint(object, footprint, Math.max(0, finite(object.cornerRadius, 0)));
2521
+ const fill2 = object.fill ?? "#f8fafc";
2522
+ const groundShadow = groundShadowNode(context, top);
2523
+ const topFace = faceNode(context, "top", 0.2, top, { ...context.common.style, fill: { kind: "solid", color: fill2 } });
2524
+ const nodes = [
2525
+ unseenHullNode(context),
2526
+ ...groundShadow ? [groundShadow] : [],
2527
+ ...sides.flatMap((side, i) => [wallNode(context, side, i, fill2), wallEdgesNode(context, side, i)]),
2528
+ topFace
2529
+ ];
2530
+ return object.text ? [...nodes, ...labelNodes(context, object.text)] : nodes;
2531
+ }
2532
+
2533
+ // src/renderScene/artifacts/isometric/sphere.ts
2534
+ function buildSphere(object, index) {
2535
+ const context = isometricContext(object, index);
2536
+ const { order, common, box } = context;
2537
+ const radius = Math.max(0, Math.min(object.width, object.height, object.depth)) / 2;
2538
+ const cx = box.x + box.width / 2;
2539
+ const cy = box.y + box.height / 2;
2540
+ const fill2 = object.fill ?? "#f8fafc";
2541
+ const bounds = { minX: cx - radius, minY: cy - radius, maxX: cx + radius, maxY: cy + radius };
2542
+ const body = {
2543
+ type: "ellipse",
2544
+ id: `isometric-${object.id}-sphere`,
2545
+ order: order + 0.1,
2546
+ bounds,
2547
+ cx,
2548
+ cy,
2549
+ rx: radius,
2550
+ ry: radius,
2551
+ style: {
2552
+ ...common.style,
2553
+ fill: {
2554
+ kind: "linear-gradient",
2555
+ angle: 135,
2556
+ stops: [
2557
+ { offset: 0, color: shadeFill(fill2, 1.22) },
2558
+ { offset: 0.5, color: fill2 },
2559
+ { offset: 1, color: shadeFill(fill2, 0.82) }
2560
+ ]
2561
+ }
2562
+ },
2563
+ prop: "style.fill",
2564
+ propKind: "color",
2565
+ propSolidOnly: true
2566
+ };
2567
+ const highlight = {
2568
+ type: "ellipse",
2569
+ id: `isometric-${object.id}-highlight`,
2570
+ order: order + 0.2,
2571
+ bounds,
2572
+ cx: cx - radius * 0.32,
2573
+ cy: cy - radius * 0.38,
2574
+ rx: radius * 0.26,
2575
+ ry: radius * 0.18,
2576
+ rotation: -35,
2577
+ style: {
2578
+ fill: { kind: "solid", color: "#ffffff" },
2579
+ stroke: { kind: "none" },
2580
+ opacity: 0.45,
2581
+ blur: radius * 0.1,
2582
+ pointerEvents: "none"
2583
+ }
2584
+ };
2585
+ const shadow = sphereShadowNode(context, radius);
2586
+ const nodes = [unseenHullNode(context), ...shadow ? [shadow] : [], body, highlight];
2587
+ return object.text ? [...nodes, ...labelNodes(context, object.text)] : nodes;
2588
+ }
2589
+
2590
+ // src/renderScene/artifacts/isometric/index.ts
2591
+ function buildIsometricObject(object, index) {
2592
+ if (object.form === "sphere") {
2593
+ return buildSphere(object, index);
2594
+ }
2595
+ const footprint = cleanFootprint(object.footprint);
2596
+ return footprint.length > 0 ? buildExtruded(object, index, footprint) : buildBox(object, index);
2597
+ }
2294
2598
  function buildIsometricObjects(objects) {
2295
2599
  return objects.flatMap(
2296
2600
  (object, index) => tag(
@@ -2497,7 +2801,7 @@ function polylinePathData(points) {
2497
2801
  }
2498
2802
  return path;
2499
2803
  }
2500
- function pathData(points, pathType, segments, strokeWidth) {
2804
+ function pathData2(points, pathType, segments, strokeWidth) {
2501
2805
  if (points.length < 4) {
2502
2806
  return "";
2503
2807
  }
@@ -2531,7 +2835,7 @@ function renderLinkPath(context) {
2531
2835
  id: `link-${link.id}`,
2532
2836
  order: context.order,
2533
2837
  bounds: context.bounds,
2534
- d: pathData(context.points, context.pathType, context.segments, context.strokeWidth),
2838
+ d: pathData2(context.points, context.pathType, context.segments, context.strokeWidth),
2535
2839
  style: context.style,
2536
2840
  markerStart: markerForEnd(link, "start"),
2537
2841
  markerEnd: markerForEnd(link, "end"),
@@ -6165,7 +6469,7 @@ function dotNode(context, mark) {
6165
6469
  }
6166
6470
  };
6167
6471
  }
6168
- function labelNode2(context, mark, value) {
6472
+ function labelNode3(context, mark, value) {
6169
6473
  const { chart, bounds, nextOrder } = context;
6170
6474
  const config = chart.config;
6171
6475
  const fontSize = Math.max(9, chart.fontSize ?? 12);
@@ -6218,7 +6522,7 @@ function renderLineHighlights(context, series, color) {
6218
6522
  }
6219
6523
  nodes.push(dotNode(context, mark));
6220
6524
  if (config?.highlightLabels) {
6221
- nodes.push(labelNode2(context, mark, pairs[index][1]));
6525
+ nodes.push(labelNode3(context, mark, pairs[index][1]));
6222
6526
  }
6223
6527
  }
6224
6528
  return nodes;
@@ -8512,6 +8816,7 @@ function stackingOf(input) {
8512
8816
  );
8513
8817
  add("chart", input.charts ?? [], 2e4);
8514
8818
  add("path", input.paths ?? [], 3e4);
8819
+ add("dimension", input.dimensions ?? [], 31e3);
8515
8820
  return stacking;
8516
8821
  }
8517
8822
  function stampStacking(nodes, input) {
@@ -8532,7 +8837,8 @@ function buildRenderScene(input, options = {}) {
8532
8837
  ...buildLinks(input.links, measureText),
8533
8838
  ...buildShapes(input.shapes, diagnostics, measureText),
8534
8839
  ...buildComponents(input.components ?? input.widgets ?? []),
8535
- ...buildIsometricObjects(input.isometricObjects ?? [])
8840
+ ...buildIsometricObjects(input.isometricObjects ?? []),
8841
+ ...buildDimensions(input.dimensions ?? [])
8536
8842
  ];
8537
8843
  stampStacking(nodes, input);
8538
8844
  nodes.sort(
@@ -9208,5 +9514,5 @@ function defineComponent(definition) {
9208
9514
  }
9209
9515
 
9210
9516
  export { collectCanvasObjects, decodeColor, decodeShadow, defineComponent, render, renderCanvas, sflToRenderInput };
9211
- //# sourceMappingURL=chunk-LTGF5OHP.js.map
9212
- //# sourceMappingURL=chunk-LTGF5OHP.js.map
9517
+ //# sourceMappingURL=chunk-FVHVOJS2.js.map
9518
+ //# sourceMappingURL=chunk-FVHVOJS2.js.map