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.
- package/CHANGELOG.md +43 -0
- package/dist/binding/index.cjs +9 -9
- package/dist/binding/index.d.cts +4 -4
- package/dist/binding/index.d.ts +4 -4
- package/dist/binding/index.js +3 -3
- package/dist/{chunk-ZMLQIMJK.cjs → chunk-A73UJ5AQ.cjs} +1537 -738
- package/dist/chunk-A73UJ5AQ.cjs.map +1 -0
- package/dist/{chunk-VK3T6O5Z.cjs → chunk-BUOWM3LC.cjs} +745 -62
- package/dist/chunk-BUOWM3LC.cjs.map +1 -0
- package/dist/{chunk-L3VJXZFD.cjs → chunk-EKAWJFJQ.cjs} +15 -15
- package/dist/{chunk-L3VJXZFD.cjs.map → chunk-EKAWJFJQ.cjs.map} +1 -1
- package/dist/{chunk-BODZN3ZI.js → chunk-JCRPLPKV.js} +156 -23
- package/dist/chunk-JCRPLPKV.js.map +1 -0
- package/dist/{chunk-IEHE6WVN.js → chunk-JQK4IGXJ.js} +489 -51
- package/dist/chunk-JQK4IGXJ.js.map +1 -0
- package/dist/{chunk-XY2GZUHC.cjs → chunk-KXYSO6GC.cjs} +498 -50
- package/dist/chunk-KXYSO6GC.cjs.map +1 -0
- package/dist/{chunk-G7NRK5AG.js → chunk-MUKIGLR5.js} +717 -34
- package/dist/chunk-MUKIGLR5.js.map +1 -0
- package/dist/{chunk-TWDLOXRM.cjs → chunk-OWNVXKXN.cjs} +170 -37
- package/dist/chunk-OWNVXKXN.cjs.map +1 -0
- package/dist/{chunk-LTGF5OHP.js → chunk-SDMQRSRW.js} +941 -143
- package/dist/chunk-SDMQRSRW.js.map +1 -0
- package/dist/{chunk-7VW2XKVB.js → chunk-ZNHYW47T.js} +3 -3
- package/dist/{chunk-7VW2XKVB.js.map → chunk-ZNHYW47T.js.map} +1 -1
- package/dist/index.cjs +57 -29
- package/dist/index.d.cts +80 -7
- package/dist/index.d.ts +80 -7
- package/dist/index.js +5 -5
- package/dist/interaction/index.cjs +245 -235
- package/dist/interaction/index.cjs.map +1 -1
- package/dist/interaction/index.d.cts +3 -2
- package/dist/interaction/index.d.ts +3 -2
- package/dist/interaction/index.js +17 -7
- package/dist/interaction/index.js.map +1 -1
- package/dist/{render-CgX_y15a.d.ts → render-BU2uYzjG.d.cts} +40 -16
- package/dist/{render-CgX_y15a.d.cts → render-BU2uYzjG.d.ts} +40 -16
- package/dist/{runtime-reWgr7MP.d.cts → runtime-B7KiTmn8.d.cts} +2 -2
- package/dist/{runtime-DnUxca3Y.d.ts → runtime-BPzyD-Nd.d.ts} +2 -2
- package/dist/{runtimeTypes-D60w6nyF.d.cts → runtimeTypes-BIP70z72.d.cts} +3 -2
- package/dist/{runtimeTypes-CEBGueYM.d.ts → runtimeTypes-DalvhScn.d.ts} +3 -2
- package/dist/stickyflow-diagram.global.js +387 -36
- package/dist/stickyflow-diagram.global.js.map +1 -1
- package/dist/{types-DYLC_lsk.d.ts → types-DMWs27Hn.d.ts} +1 -1
- package/dist/{types-DvhMpqrL.d.cts → types-D_2NZ6lL.d.cts} +1 -1
- package/dist/viewer/index.cjs +9 -9
- package/dist/viewer/index.d.cts +5 -4
- package/dist/viewer/index.d.ts +5 -4
- package/dist/viewer/index.js +4 -4
- package/dist/web-component/index.cjs +6 -6
- package/dist/web-component/index.d.cts +2 -2
- package/dist/web-component/index.d.ts +2 -2
- package/dist/web-component/index.js +4 -4
- package/package.json +1 -1
- package/dist/chunk-BODZN3ZI.js.map +0 -1
- package/dist/chunk-G7NRK5AG.js.map +0 -1
- package/dist/chunk-IEHE6WVN.js.map +0 -1
- package/dist/chunk-LTGF5OHP.js.map +0 -1
- package/dist/chunk-TWDLOXRM.cjs.map +0 -1
- package/dist/chunk-VK3T6O5Z.cjs.map +0 -1
- package/dist/chunk-XY2GZUHC.cjs.map +0 -1
- 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,
|
|
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
|
|
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(
|
|
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 /
|
|
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
|
|
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(
|
|
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 /
|
|
1389
|
-
const
|
|
1390
|
-
const labelBox = horizontal ? { x: box.x + box.width *
|
|
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
|
-
|
|
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/
|
|
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
|
|
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
|
-
|
|
2110
|
-
id: `isometric-${object.id}
|
|
2111
|
-
order:
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
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
|
|
2131
|
-
const
|
|
2132
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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:
|
|
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 =
|
|
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
|
|
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:
|
|
3879
|
-
y:
|
|
3880
|
-
width:
|
|
3881
|
-
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", ...
|
|
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:
|
|
3893
|
-
y:
|
|
3894
|
-
width:
|
|
3895
|
-
height:
|
|
3896
|
-
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
|
|
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:
|
|
3918
|
-
y:
|
|
3919
|
-
width:
|
|
3920
|
-
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
|
|
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(
|
|
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
|
|
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
|
|
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 +
|
|
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 +
|
|
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, ...
|
|
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 -
|
|
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
|
|
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, ...
|
|
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-
|
|
9212
|
-
//# sourceMappingURL=chunk-
|
|
10008
|
+
export { collectCanvasObjects, decodeColor, decodeShadow, defineComponent, render, renderCanvas, sflToRenderInput, sliderReach };
|
|
10009
|
+
//# sourceMappingURL=chunk-SDMQRSRW.js.map
|
|
10010
|
+
//# sourceMappingURL=chunk-SDMQRSRW.js.map
|