stickyflow 0.4.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.
- package/CHANGELOG.md +43 -0
- package/README.md +51 -5
- package/dist/binding/index.cjs +34 -0
- package/dist/binding/index.cjs.map +1 -0
- package/dist/binding/index.d.cts +11 -0
- package/dist/binding/index.d.ts +11 -0
- package/dist/binding/index.js +5 -0
- package/dist/binding/index.js.map +1 -0
- package/dist/{chunk-BYMIYXP5.js → chunk-4G2R7PEL.js} +513 -61
- package/dist/chunk-4G2R7PEL.js.map +1 -0
- package/dist/{chunk-HFOGKSNU.cjs → chunk-4LENHH6C.cjs} +15 -15
- package/dist/{chunk-HFOGKSNU.cjs.map → chunk-4LENHH6C.cjs.map} +1 -1
- package/dist/{chunk-65IVT4GK.js → chunk-FVHVOJS2.js} +1333 -650
- package/dist/chunk-FVHVOJS2.js.map +1 -0
- package/dist/chunk-JIJMZMGY.cjs +1189 -0
- package/dist/chunk-JIJMZMGY.cjs.map +1 -0
- package/dist/{chunk-UXDWH2JC.cjs → chunk-KTNCDNDB.cjs} +1165 -1118
- package/dist/chunk-KTNCDNDB.cjs.map +1 -0
- package/dist/chunk-MFNUJA26.js +1182 -0
- package/dist/chunk-MFNUJA26.js.map +1 -0
- package/dist/{chunk-XEN5QIIJ.js → chunk-ULQZ6CZW.js} +3 -3
- package/dist/{chunk-XEN5QIIJ.js.map → chunk-ULQZ6CZW.js.map} +1 -1
- package/dist/{chunk-DDCTNLLD.cjs → chunk-WQRT5PVT.cjs} +1837 -1155
- package/dist/chunk-WQRT5PVT.cjs.map +1 -0
- package/dist/{chunk-CSXQD3ON.js → chunk-WRDVNMFS.js} +1128 -1081
- package/dist/chunk-WRDVNMFS.js.map +1 -0
- package/dist/{chunk-CXL254BT.cjs → chunk-XJ4W6TW4.cjs} +528 -60
- package/dist/chunk-XJ4W6TW4.cjs.map +1 -0
- package/dist/index.cjs +73 -1013
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +67 -14
- package/dist/index.d.ts +67 -14
- package/dist/index.js +6 -993
- package/dist/index.js.map +1 -1
- package/dist/interaction/index.cjs +246 -236
- 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 +18 -8
- package/dist/interaction/index.js.map +1 -1
- package/dist/{render-C5X74hds.d.cts → render-Db0eSz_s.d.cts} +216 -118
- package/dist/{render-C5X74hds.d.ts → render-Db0eSz_s.d.ts} +216 -118
- package/dist/runtime-BhivvBeL.d.cts +10 -0
- package/dist/runtime-n2yG-_j-.d.ts +10 -0
- package/dist/{runtimeTypes-yTSAvtCn.d.cts → runtimeTypes-CrkMHvVi.d.cts} +10 -5
- package/dist/{runtimeTypes-D8hPZ62T.d.ts → runtimeTypes-DnI7mRF5.d.ts} +10 -5
- package/dist/stickyflow-diagram.global.js +35 -35
- package/dist/stickyflow-diagram.global.js.map +1 -1
- package/dist/{types-CdgGdtoD.d.ts → types-BHfUKT4s.d.cts} +3 -2
- package/dist/{types-BDKDf4zr.d.cts → types-D4cH4f1a.d.ts} +3 -2
- package/dist/viewer/index.cjs +9 -9
- package/dist/viewer/index.d.cts +4 -4
- package/dist/viewer/index.d.ts +4 -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 +6 -1
- package/dist/chunk-65IVT4GK.js.map +0 -1
- package/dist/chunk-BYMIYXP5.js.map +0 -1
- package/dist/chunk-CSXQD3ON.js.map +0 -1
- package/dist/chunk-CXL254BT.cjs.map +0 -1
- package/dist/chunk-DDCTNLLD.cjs.map +0 -1
- package/dist/chunk-UXDWH2JC.cjs.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isIsometricObject, sflToCanvasState, tag, EMPTY_BOUNDS, DOM_CONTRACT_VERSION, edgePointToward, elementCenter, VISIBLE_ISOMETRIC_FACES, isometricFaceCenter, finite, freeformPathData, rotatedBounds,
|
|
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-]*`;
|
|
@@ -124,6 +124,10 @@ function solidColor(value) {
|
|
|
124
124
|
const decoded = decodeColor(value);
|
|
125
125
|
return typeof decoded === "string" ? decoded : void 0;
|
|
126
126
|
}
|
|
127
|
+
var CSS_COLOR = /^(?:#[0-9a-f]{3,8}|rgba?\([\d.,%\s]+\)|[a-z][\w-]*)$/i;
|
|
128
|
+
function cssColor(value) {
|
|
129
|
+
return value && CSS_COLOR.test(value) ? value : void 0;
|
|
130
|
+
}
|
|
127
131
|
function oneOf(value, allowed, fallback) {
|
|
128
132
|
return allowed.includes(value) ? value : fallback;
|
|
129
133
|
}
|
|
@@ -583,6 +587,242 @@ function typedChart(base, chartType, config) {
|
|
|
583
587
|
return { ...base, chartType, config };
|
|
584
588
|
}
|
|
585
589
|
|
|
590
|
+
// src/renderInput/fromSfl/canvasObjects/genericComponent.ts
|
|
591
|
+
function numberProperty(descriptor, raw) {
|
|
592
|
+
const value = Number(raw);
|
|
593
|
+
if (raw === void 0 || raw === "" || !Number.isFinite(value)) {
|
|
594
|
+
return descriptor.default;
|
|
595
|
+
}
|
|
596
|
+
const atLeast = descriptor.min === void 0 ? value : Math.max(descriptor.min, value);
|
|
597
|
+
return descriptor.max === void 0 ? atLeast : Math.min(descriptor.max, atLeast);
|
|
598
|
+
}
|
|
599
|
+
function readProperty(descriptor, raw) {
|
|
600
|
+
switch (descriptor.type) {
|
|
601
|
+
case "number":
|
|
602
|
+
return numberProperty(descriptor, raw);
|
|
603
|
+
case "boolean":
|
|
604
|
+
return raw === void 0 ? descriptor.default : raw === "true";
|
|
605
|
+
case "color":
|
|
606
|
+
return cssColor(raw) ?? descriptor.default;
|
|
607
|
+
case "enum":
|
|
608
|
+
return raw !== void 0 && descriptor.options.includes(raw) ? raw : descriptor.default;
|
|
609
|
+
case "string":
|
|
610
|
+
return raw ?? descriptor.default;
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
function readComponentProperties(descriptor, props) {
|
|
614
|
+
const properties = {};
|
|
615
|
+
for (const [key, property] of Object.entries(descriptor?.properties ?? {})) {
|
|
616
|
+
properties[key] = readProperty(property, props[key]);
|
|
617
|
+
}
|
|
618
|
+
return properties;
|
|
619
|
+
}
|
|
620
|
+
function readComponentValue(descriptor, raw) {
|
|
621
|
+
if (!descriptor) {
|
|
622
|
+
return "";
|
|
623
|
+
}
|
|
624
|
+
if (descriptor.type === "boolean") {
|
|
625
|
+
return raw === "true";
|
|
626
|
+
}
|
|
627
|
+
if (descriptor.type === "number") {
|
|
628
|
+
const value = Number(raw);
|
|
629
|
+
return Number.isFinite(value) ? value : descriptor.default;
|
|
630
|
+
}
|
|
631
|
+
return raw;
|
|
632
|
+
}
|
|
633
|
+
function genericComponentObject(canvasObject) {
|
|
634
|
+
const descriptor = getComponentDescriptor(canvasObject.component.type);
|
|
635
|
+
return {
|
|
636
|
+
id: canvasObject.id,
|
|
637
|
+
type: canvasObject.component.type,
|
|
638
|
+
value: descriptor ? readComponentValue(descriptor.value, canvasObject.component.value) : canvasObject.component.value,
|
|
639
|
+
disabled: canvasObject.props.disabled === "true",
|
|
640
|
+
label: canvasObject.component.label,
|
|
641
|
+
x: canvasObject.x,
|
|
642
|
+
y: canvasObject.y,
|
|
643
|
+
width: canvasObject.width,
|
|
644
|
+
height: canvasObject.height,
|
|
645
|
+
rotation: canvasObject.rotation,
|
|
646
|
+
order: canvasObject.order,
|
|
647
|
+
sourceIndex: canvasObject.sourceIndex,
|
|
648
|
+
parentFrameId: canvasObject.parentFrameId,
|
|
649
|
+
properties: readComponentProperties(descriptor, canvasObject.props)
|
|
650
|
+
};
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
// src/renderInput/fromSfl/canvasObjects/component.ts
|
|
654
|
+
var CSS_FONT_FAMILY = /^[\w\s,'"-]+$/;
|
|
655
|
+
function fontFamily(value) {
|
|
656
|
+
return value && CSS_FONT_FAMILY.test(value) ? value : void 0;
|
|
657
|
+
}
|
|
658
|
+
var FONT_WEIGHT = /^(?:[1-9]00|normal|bold)$/;
|
|
659
|
+
function variant(value) {
|
|
660
|
+
return value === "plain" || value === "flip" ? value : void 0;
|
|
661
|
+
}
|
|
662
|
+
function motion(value) {
|
|
663
|
+
return value === "roll" || value === "fade" ? value : void 0;
|
|
664
|
+
}
|
|
665
|
+
function positiveNumber(value) {
|
|
666
|
+
const number = Number(value);
|
|
667
|
+
return value !== void 0 && Number.isFinite(number) && number > 0 ? number : void 0;
|
|
668
|
+
}
|
|
669
|
+
function fontWeight(value) {
|
|
670
|
+
return value && FONT_WEIGHT.test(value) ? value : void 0;
|
|
671
|
+
}
|
|
672
|
+
var TICK_SCALE_NUMBERS = [
|
|
673
|
+
"ticks",
|
|
674
|
+
"major",
|
|
675
|
+
"radius",
|
|
676
|
+
"length",
|
|
677
|
+
"thickness",
|
|
678
|
+
"round",
|
|
679
|
+
"start",
|
|
680
|
+
"sweep",
|
|
681
|
+
"intensity"
|
|
682
|
+
];
|
|
683
|
+
var TICK_SCALE_COLORS = ["color", "accent"];
|
|
684
|
+
function tickScaleObject(canvasObject) {
|
|
685
|
+
const properties = canvasObject.props;
|
|
686
|
+
const parameters = {};
|
|
687
|
+
for (const key of TICK_SCALE_NUMBERS) {
|
|
688
|
+
const value = Number(properties[key]);
|
|
689
|
+
if (properties[key] !== void 0 && Number.isFinite(value)) {
|
|
690
|
+
parameters[key] = value;
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
for (const key of TICK_SCALE_COLORS) {
|
|
694
|
+
const value = cssColor(properties[key]);
|
|
695
|
+
if (value) {
|
|
696
|
+
parameters[key] = value;
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
return {
|
|
700
|
+
id: canvasObject.id,
|
|
701
|
+
type: "tickScale",
|
|
702
|
+
value: canvasObject.component.value,
|
|
703
|
+
max: canvasObject.component.max,
|
|
704
|
+
label: canvasObject.component.label,
|
|
705
|
+
x: canvasObject.x,
|
|
706
|
+
y: canvasObject.y,
|
|
707
|
+
width: canvasObject.width,
|
|
708
|
+
height: canvasObject.height,
|
|
709
|
+
rotation: canvasObject.rotation,
|
|
710
|
+
order: canvasObject.order,
|
|
711
|
+
sourceIndex: canvasObject.sourceIndex,
|
|
712
|
+
parentFrameId: canvasObject.parentFrameId,
|
|
713
|
+
parameters,
|
|
714
|
+
labels: properties.labels === "true" ? {
|
|
715
|
+
size: Number.isFinite(Number(properties.labelSize)) && properties.labelSize !== void 0 ? Number(properties.labelSize) : void 0,
|
|
716
|
+
color: cssColor(properties.labelColor),
|
|
717
|
+
offset: Number.isFinite(Number(properties.labelOffset)) && properties.labelOffset !== void 0 ? Number(properties.labelOffset) : void 0,
|
|
718
|
+
weight: fontWeight(properties.labelWeight),
|
|
719
|
+
fontFamily: fontFamily(properties.labelFont)
|
|
720
|
+
} : void 0
|
|
721
|
+
};
|
|
722
|
+
}
|
|
723
|
+
var RULER_NUMBERS = [
|
|
724
|
+
"ticks",
|
|
725
|
+
"major",
|
|
726
|
+
"length",
|
|
727
|
+
"thickness",
|
|
728
|
+
"round",
|
|
729
|
+
"dent",
|
|
730
|
+
"spread",
|
|
731
|
+
"inset",
|
|
732
|
+
"line",
|
|
733
|
+
"gap",
|
|
734
|
+
"intensity"
|
|
735
|
+
];
|
|
736
|
+
var RULER_COLORS = ["color", "accent", "glow"];
|
|
737
|
+
var RULER_DEFAULTS = { color: "#8f95c4", accent: "#d9f270", glow: "#3ddc84" };
|
|
738
|
+
var RULER_OPTIONAL_COLORS = ["core", "peak"];
|
|
739
|
+
function rulerObject(canvasObject) {
|
|
740
|
+
const properties = canvasObject.props;
|
|
741
|
+
const parameters = {};
|
|
742
|
+
for (const key of RULER_NUMBERS) {
|
|
743
|
+
const value = Number(properties[key]);
|
|
744
|
+
if (properties[key] !== void 0 && Number.isFinite(value)) {
|
|
745
|
+
parameters[key] = value;
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
for (const key of RULER_COLORS) {
|
|
749
|
+
parameters[key] = cssColor(properties[key]) ?? RULER_DEFAULTS[key];
|
|
750
|
+
}
|
|
751
|
+
for (const key of RULER_OPTIONAL_COLORS) {
|
|
752
|
+
const value = cssColor(properties[key]);
|
|
753
|
+
if (value) {
|
|
754
|
+
parameters[key] = value;
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
parameters.axis = properties.axis === "horizontal" ? "horizontal" : "vertical";
|
|
758
|
+
if (properties.knob) {
|
|
759
|
+
parameters.knob = properties.knob;
|
|
760
|
+
}
|
|
761
|
+
return {
|
|
762
|
+
id: canvasObject.id,
|
|
763
|
+
type: "ruler",
|
|
764
|
+
value: canvasObject.component.value,
|
|
765
|
+
min: canvasObject.component.min,
|
|
766
|
+
max: canvasObject.component.max,
|
|
767
|
+
label: canvasObject.component.label,
|
|
768
|
+
x: canvasObject.x,
|
|
769
|
+
y: canvasObject.y,
|
|
770
|
+
width: canvasObject.width,
|
|
771
|
+
height: canvasObject.height,
|
|
772
|
+
rotation: canvasObject.rotation,
|
|
773
|
+
order: canvasObject.order,
|
|
774
|
+
sourceIndex: canvasObject.sourceIndex,
|
|
775
|
+
parentFrameId: canvasObject.parentFrameId,
|
|
776
|
+
parameters,
|
|
777
|
+
labels: properties.labels === "true" ? {
|
|
778
|
+
size: Number.isFinite(Number(properties.labelSize)) && properties.labelSize !== void 0 ? Number(properties.labelSize) : void 0,
|
|
779
|
+
color: cssColor(properties.labelColor),
|
|
780
|
+
offset: Number.isFinite(Number(properties.labelOffset)) && properties.labelOffset !== void 0 ? Number(properties.labelOffset) : void 0,
|
|
781
|
+
weight: fontWeight(properties.labelWeight),
|
|
782
|
+
fontFamily: fontFamily(properties.labelFont)
|
|
783
|
+
} : void 0
|
|
784
|
+
};
|
|
785
|
+
}
|
|
786
|
+
function rollingNumberObject(canvasObject) {
|
|
787
|
+
const properties = canvasObject.props;
|
|
788
|
+
return {
|
|
789
|
+
id: canvasObject.id,
|
|
790
|
+
type: "rollingNumber",
|
|
791
|
+
value: canvasObject.component.value,
|
|
792
|
+
digits: canvasObject.component.digits,
|
|
793
|
+
duration: canvasObject.component.duration,
|
|
794
|
+
label: canvasObject.component.label,
|
|
795
|
+
x: canvasObject.x,
|
|
796
|
+
y: canvasObject.y,
|
|
797
|
+
width: canvasObject.width,
|
|
798
|
+
height: canvasObject.height,
|
|
799
|
+
rotation: canvasObject.rotation,
|
|
800
|
+
order: canvasObject.order,
|
|
801
|
+
sourceIndex: canvasObject.sourceIndex,
|
|
802
|
+
parentFrameId: canvasObject.parentFrameId,
|
|
803
|
+
style: {
|
|
804
|
+
color: cssColor(properties.color),
|
|
805
|
+
surface: cssColor(properties.surface),
|
|
806
|
+
divider: cssColor(properties.divider),
|
|
807
|
+
labelColor: cssColor(properties.labelColor),
|
|
808
|
+
fontFamily: fontFamily(properties.fontFamily),
|
|
809
|
+
variant: variant(properties.variant),
|
|
810
|
+
motion: motion(properties.motion),
|
|
811
|
+
fontWeight: fontWeight(properties.fontWeight),
|
|
812
|
+
fontSize: positiveNumber(properties.fontSize)
|
|
813
|
+
}
|
|
814
|
+
};
|
|
815
|
+
}
|
|
816
|
+
var BUILT_IN_OBJECTS = {
|
|
817
|
+
rollingNumber: rollingNumberObject,
|
|
818
|
+
tickScale: tickScaleObject,
|
|
819
|
+
ruler: rulerObject
|
|
820
|
+
};
|
|
821
|
+
function componentObject(canvasObject) {
|
|
822
|
+
const type = canvasObject.component.type;
|
|
823
|
+
return isBuiltInComponentType(type) ? BUILT_IN_OBJECTS[type](canvasObject) : genericComponentObject(canvasObject);
|
|
824
|
+
}
|
|
825
|
+
|
|
586
826
|
// src/renderInput/fromSfl/canvasObjects/connection.ts
|
|
587
827
|
function connectionObject(c) {
|
|
588
828
|
const p = c.props;
|
|
@@ -604,6 +844,26 @@ function connectionObject(c) {
|
|
|
604
844
|
};
|
|
605
845
|
}
|
|
606
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
|
+
|
|
607
867
|
// src/renderInput/fromSfl/canvasObjects/frame.ts
|
|
608
868
|
function frameObject(e) {
|
|
609
869
|
const p = e.props;
|
|
@@ -642,6 +902,8 @@ function isometricObject(canvasObject) {
|
|
|
642
902
|
width: canvasObject.width,
|
|
643
903
|
height: canvasObject.height,
|
|
644
904
|
depth: canvasObject.isometric.depth,
|
|
905
|
+
footprint: canvasObject.isometric.footprint,
|
|
906
|
+
form: canvasObject.isometric.form,
|
|
645
907
|
rotation: canvasObject.rotation,
|
|
646
908
|
order: canvasObject.order,
|
|
647
909
|
sourceIndex: canvasObject.sourceIndex,
|
|
@@ -650,7 +912,7 @@ function isometricObject(canvasObject) {
|
|
|
650
912
|
fill: solidColor(presentation.fill) ?? "#f8fafc",
|
|
651
913
|
strokeColor: solidColor(presentation.stroke) ?? "#111827",
|
|
652
914
|
strokeWidth: numOf(presentation.strokeWidth) ?? 1,
|
|
653
|
-
cornerRadius: numOf(presentation.cornerRadius) ?? 8,
|
|
915
|
+
cornerRadius: numOf(presentation.cornerRadius) ?? (canvasObject.isometric.footprint ? 0 : 8),
|
|
654
916
|
hasShadow: shadowStyle?.enabled ?? false,
|
|
655
917
|
shadowStyle,
|
|
656
918
|
labelOffsetX: numOf(presentation.labelOffsetX) ?? 0,
|
|
@@ -790,248 +1052,75 @@ function swimlaneObject(e) {
|
|
|
790
1052
|
};
|
|
791
1053
|
}
|
|
792
1054
|
|
|
793
|
-
// src/renderInput/fromSfl/canvasObjects/
|
|
794
|
-
var
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
1055
|
+
// src/renderInput/fromSfl/canvasObjects/collect.ts
|
|
1056
|
+
var byOrder = (items) => [...items].sort((a, b) => (a.order ?? 0) - (b.order ?? 0));
|
|
1057
|
+
function collectCanvasObjects(state) {
|
|
1058
|
+
const canvasObjects = byOrder(state.canvasObjects);
|
|
1059
|
+
const shaders = new Map((state.shaders ?? []).map((shader) => [shader.name, shader]));
|
|
1060
|
+
return {
|
|
1061
|
+
shapes: canvasObjects.filter((canvasObject) => canvasObject.objectType === "shape").map((shape) => shapeObject(shape, shaders)),
|
|
1062
|
+
frames: canvasObjects.filter((canvasObject) => canvasObject.objectType === "frame").map(frameObject),
|
|
1063
|
+
swimlanes: canvasObjects.filter((canvasObject) => canvasObject.objectType === "swimlane").map(swimlaneObject),
|
|
1064
|
+
isometricObjects: canvasObjects.filter(isIsometricObject).map(isometricObject),
|
|
1065
|
+
paths: canvasObjects.filter((canvasObject) => canvasObject.objectType === "path").map(pathObject),
|
|
1066
|
+
dimensions: canvasObjects.filter(isDimensionObject).map(dimensionObject),
|
|
1067
|
+
charts: canvasObjects.filter((canvasObject) => canvasObject.objectType === "chart").map(chartObject),
|
|
1068
|
+
components: canvasObjects.filter(
|
|
1069
|
+
(canvasObject) => canvasObject.objectType === "component" && canvasObject.component !== void 0
|
|
1070
|
+
).map(componentObject),
|
|
1071
|
+
links: byOrder(state.links).map(linkObject),
|
|
1072
|
+
connections: byOrder(state.connections).map(connectionObject)
|
|
1073
|
+
};
|
|
798
1074
|
}
|
|
799
|
-
|
|
800
|
-
|
|
1075
|
+
|
|
1076
|
+
// src/renderInput/fromSfl/endpoint.ts
|
|
1077
|
+
function sidePoint(canvasObject, endpoint) {
|
|
1078
|
+
const offset = endpoint.offset ?? 0.5;
|
|
1079
|
+
switch (endpoint.side) {
|
|
1080
|
+
case "top":
|
|
1081
|
+
return { x: canvasObject.x + canvasObject.width * offset, y: canvasObject.y };
|
|
1082
|
+
case "right":
|
|
1083
|
+
return { x: canvasObject.x + canvasObject.width, y: canvasObject.y + canvasObject.height * offset };
|
|
1084
|
+
case "bottom":
|
|
1085
|
+
return { x: canvasObject.x + canvasObject.width * offset, y: canvasObject.y + canvasObject.height };
|
|
1086
|
+
case "left":
|
|
1087
|
+
return { x: canvasObject.x, y: canvasObject.y + canvasObject.height * offset };
|
|
1088
|
+
}
|
|
801
1089
|
}
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
1090
|
+
function namedPortPoint(canvasObject, endpoint) {
|
|
1091
|
+
const port = canvasObject.symbol?.ports?.find((candidate) => candidate.name === endpoint.port);
|
|
1092
|
+
if (!port) {
|
|
1093
|
+
return elementCenter(canvasObject);
|
|
1094
|
+
}
|
|
1095
|
+
return pointAtNormalizedPort(
|
|
1096
|
+
{
|
|
1097
|
+
x: canvasObject.x,
|
|
1098
|
+
y: canvasObject.y,
|
|
1099
|
+
width: canvasObject.width,
|
|
1100
|
+
height: canvasObject.height,
|
|
1101
|
+
rotation: canvasObject.rotation ?? void 0
|
|
1102
|
+
},
|
|
1103
|
+
port.at
|
|
1104
|
+
);
|
|
805
1105
|
}
|
|
806
|
-
function
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
}
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
"sweep",
|
|
825
|
-
"intensity"
|
|
826
|
-
];
|
|
827
|
-
var TICK_SCALE_COLORS = ["color", "accent"];
|
|
828
|
-
function tickScaleObject(canvasObject) {
|
|
829
|
-
const properties = canvasObject.props;
|
|
830
|
-
const parameters = {};
|
|
831
|
-
for (const key of TICK_SCALE_NUMBERS) {
|
|
832
|
-
const value = Number(properties[key]);
|
|
833
|
-
if (properties[key] !== void 0 && Number.isFinite(value)) {
|
|
834
|
-
parameters[key] = value;
|
|
835
|
-
}
|
|
836
|
-
}
|
|
837
|
-
for (const key of TICK_SCALE_COLORS) {
|
|
838
|
-
const value = color(properties[key]);
|
|
839
|
-
if (value) {
|
|
840
|
-
parameters[key] = value;
|
|
841
|
-
}
|
|
842
|
-
}
|
|
843
|
-
return {
|
|
844
|
-
id: canvasObject.id,
|
|
845
|
-
type: "tickScale",
|
|
846
|
-
value: canvasObject.widget.value,
|
|
847
|
-
max: canvasObject.widget.max,
|
|
848
|
-
label: canvasObject.widget.label,
|
|
849
|
-
x: canvasObject.x,
|
|
850
|
-
y: canvasObject.y,
|
|
851
|
-
width: canvasObject.width,
|
|
852
|
-
height: canvasObject.height,
|
|
853
|
-
rotation: canvasObject.rotation,
|
|
854
|
-
order: canvasObject.order,
|
|
855
|
-
sourceIndex: canvasObject.sourceIndex,
|
|
856
|
-
parentFrameId: canvasObject.parentFrameId,
|
|
857
|
-
parameters,
|
|
858
|
-
labels: properties.labels === "true" ? {
|
|
859
|
-
size: Number.isFinite(Number(properties.labelSize)) && properties.labelSize !== void 0 ? Number(properties.labelSize) : void 0,
|
|
860
|
-
color: color(properties.labelColor),
|
|
861
|
-
offset: Number.isFinite(Number(properties.labelOffset)) && properties.labelOffset !== void 0 ? Number(properties.labelOffset) : void 0,
|
|
862
|
-
weight: fontWeight(properties.labelWeight),
|
|
863
|
-
fontFamily: fontFamily(properties.labelFont)
|
|
864
|
-
} : void 0
|
|
865
|
-
};
|
|
866
|
-
}
|
|
867
|
-
var RULER_NUMBERS = [
|
|
868
|
-
"ticks",
|
|
869
|
-
"major",
|
|
870
|
-
"length",
|
|
871
|
-
"thickness",
|
|
872
|
-
"round",
|
|
873
|
-
"dent",
|
|
874
|
-
"spread",
|
|
875
|
-
"inset",
|
|
876
|
-
"line",
|
|
877
|
-
"gap",
|
|
878
|
-
"intensity"
|
|
879
|
-
];
|
|
880
|
-
var RULER_COLORS = ["color", "accent", "glow"];
|
|
881
|
-
var RULER_DEFAULTS = { color: "#8f95c4", accent: "#d9f270", glow: "#3ddc84" };
|
|
882
|
-
var RULER_OPTIONAL_COLORS = ["core", "peak"];
|
|
883
|
-
function rulerObject(canvasObject) {
|
|
884
|
-
const properties = canvasObject.props;
|
|
885
|
-
const parameters = {};
|
|
886
|
-
for (const key of RULER_NUMBERS) {
|
|
887
|
-
const value = Number(properties[key]);
|
|
888
|
-
if (properties[key] !== void 0 && Number.isFinite(value)) {
|
|
889
|
-
parameters[key] = value;
|
|
890
|
-
}
|
|
891
|
-
}
|
|
892
|
-
for (const key of RULER_COLORS) {
|
|
893
|
-
parameters[key] = color(properties[key]) ?? RULER_DEFAULTS[key];
|
|
894
|
-
}
|
|
895
|
-
for (const key of RULER_OPTIONAL_COLORS) {
|
|
896
|
-
const value = color(properties[key]);
|
|
897
|
-
if (value) {
|
|
898
|
-
parameters[key] = value;
|
|
899
|
-
}
|
|
900
|
-
}
|
|
901
|
-
parameters.axis = properties.axis === "horizontal" ? "horizontal" : "vertical";
|
|
902
|
-
if (properties.knob) {
|
|
903
|
-
parameters.knob = properties.knob;
|
|
904
|
-
}
|
|
905
|
-
return {
|
|
906
|
-
id: canvasObject.id,
|
|
907
|
-
type: "ruler",
|
|
908
|
-
value: canvasObject.widget.value,
|
|
909
|
-
min: canvasObject.widget.min,
|
|
910
|
-
max: canvasObject.widget.max,
|
|
911
|
-
label: canvasObject.widget.label,
|
|
912
|
-
x: canvasObject.x,
|
|
913
|
-
y: canvasObject.y,
|
|
914
|
-
width: canvasObject.width,
|
|
915
|
-
height: canvasObject.height,
|
|
916
|
-
rotation: canvasObject.rotation,
|
|
917
|
-
order: canvasObject.order,
|
|
918
|
-
sourceIndex: canvasObject.sourceIndex,
|
|
919
|
-
parentFrameId: canvasObject.parentFrameId,
|
|
920
|
-
parameters,
|
|
921
|
-
labels: properties.labels === "true" ? {
|
|
922
|
-
size: Number.isFinite(Number(properties.labelSize)) && properties.labelSize !== void 0 ? Number(properties.labelSize) : void 0,
|
|
923
|
-
color: color(properties.labelColor),
|
|
924
|
-
offset: Number.isFinite(Number(properties.labelOffset)) && properties.labelOffset !== void 0 ? Number(properties.labelOffset) : void 0,
|
|
925
|
-
weight: fontWeight(properties.labelWeight),
|
|
926
|
-
fontFamily: fontFamily(properties.labelFont)
|
|
927
|
-
} : void 0
|
|
928
|
-
};
|
|
929
|
-
}
|
|
930
|
-
function widgetObject(canvasObject) {
|
|
931
|
-
if (canvasObject.widget.type === "tickScale") {
|
|
932
|
-
return tickScaleObject(canvasObject);
|
|
933
|
-
}
|
|
934
|
-
if (canvasObject.widget.type === "ruler") {
|
|
935
|
-
return rulerObject(canvasObject);
|
|
936
|
-
}
|
|
937
|
-
const properties = canvasObject.props;
|
|
938
|
-
return {
|
|
939
|
-
id: canvasObject.id,
|
|
940
|
-
type: "rollingNumber",
|
|
941
|
-
value: canvasObject.widget.value,
|
|
942
|
-
digits: canvasObject.widget.digits,
|
|
943
|
-
duration: canvasObject.widget.duration,
|
|
944
|
-
label: canvasObject.widget.label,
|
|
945
|
-
x: canvasObject.x,
|
|
946
|
-
y: canvasObject.y,
|
|
947
|
-
width: canvasObject.width,
|
|
948
|
-
height: canvasObject.height,
|
|
949
|
-
rotation: canvasObject.rotation,
|
|
950
|
-
order: canvasObject.order,
|
|
951
|
-
sourceIndex: canvasObject.sourceIndex,
|
|
952
|
-
parentFrameId: canvasObject.parentFrameId,
|
|
953
|
-
style: {
|
|
954
|
-
color: color(properties.color),
|
|
955
|
-
surface: color(properties.surface),
|
|
956
|
-
divider: color(properties.divider),
|
|
957
|
-
labelColor: color(properties.labelColor),
|
|
958
|
-
fontFamily: fontFamily(properties.fontFamily),
|
|
959
|
-
variant: variant(properties.variant),
|
|
960
|
-
motion: motion(properties.motion),
|
|
961
|
-
fontWeight: fontWeight(properties.fontWeight),
|
|
962
|
-
fontSize: positiveNumber(properties.fontSize)
|
|
963
|
-
}
|
|
964
|
-
};
|
|
965
|
-
}
|
|
966
|
-
|
|
967
|
-
// src/renderInput/fromSfl/canvasObjects/collect.ts
|
|
968
|
-
var byOrder = (items) => [...items].sort((a, b) => (a.order ?? 0) - (b.order ?? 0));
|
|
969
|
-
function collectCanvasObjects(state) {
|
|
970
|
-
const canvasObjects = byOrder(state.canvasObjects);
|
|
971
|
-
const shaders = new Map((state.shaders ?? []).map((shader) => [shader.name, shader]));
|
|
972
|
-
return {
|
|
973
|
-
shapes: canvasObjects.filter((canvasObject) => canvasObject.objectType === "shape").map((shape) => shapeObject(shape, shaders)),
|
|
974
|
-
frames: canvasObjects.filter((canvasObject) => canvasObject.objectType === "frame").map(frameObject),
|
|
975
|
-
swimlanes: canvasObjects.filter((canvasObject) => canvasObject.objectType === "swimlane").map(swimlaneObject),
|
|
976
|
-
isometricObjects: canvasObjects.filter(isIsometricObject).map(isometricObject),
|
|
977
|
-
paths: canvasObjects.filter((canvasObject) => canvasObject.objectType === "path").map(pathObject),
|
|
978
|
-
charts: canvasObjects.filter((canvasObject) => canvasObject.objectType === "chart").map(chartObject),
|
|
979
|
-
widgets: canvasObjects.filter(
|
|
980
|
-
(canvasObject) => canvasObject.objectType === "widget" && ["rollingNumber", "tickScale", "ruler"].includes(canvasObject.widget?.type ?? "")
|
|
981
|
-
).map(widgetObject),
|
|
982
|
-
links: byOrder(state.links).map(linkObject),
|
|
983
|
-
connections: byOrder(state.connections).map(connectionObject)
|
|
984
|
-
};
|
|
985
|
-
}
|
|
986
|
-
|
|
987
|
-
// src/renderInput/fromSfl/endpoint.ts
|
|
988
|
-
function sidePoint(canvasObject, endpoint) {
|
|
989
|
-
const offset = endpoint.offset ?? 0.5;
|
|
990
|
-
switch (endpoint.side) {
|
|
991
|
-
case "top":
|
|
992
|
-
return { x: canvasObject.x + canvasObject.width * offset, y: canvasObject.y };
|
|
993
|
-
case "right":
|
|
994
|
-
return { x: canvasObject.x + canvasObject.width, y: canvasObject.y + canvasObject.height * offset };
|
|
995
|
-
case "bottom":
|
|
996
|
-
return { x: canvasObject.x + canvasObject.width * offset, y: canvasObject.y + canvasObject.height };
|
|
997
|
-
case "left":
|
|
998
|
-
return { x: canvasObject.x, y: canvasObject.y + canvasObject.height * offset };
|
|
999
|
-
}
|
|
1000
|
-
}
|
|
1001
|
-
function namedPortPoint(canvasObject, endpoint) {
|
|
1002
|
-
const port = canvasObject.symbol?.ports?.find((candidate) => candidate.name === endpoint.port);
|
|
1003
|
-
if (!port) {
|
|
1004
|
-
return elementCenter(canvasObject);
|
|
1005
|
-
}
|
|
1006
|
-
return pointAtNormalizedPort(
|
|
1007
|
-
{
|
|
1008
|
-
x: canvasObject.x,
|
|
1009
|
-
y: canvasObject.y,
|
|
1010
|
-
width: canvasObject.width,
|
|
1011
|
-
height: canvasObject.height,
|
|
1012
|
-
rotation: canvasObject.rotation ?? void 0
|
|
1013
|
-
},
|
|
1014
|
-
port.at
|
|
1015
|
-
);
|
|
1016
|
-
}
|
|
1017
|
-
function resolveLinkEndpoint(link, end, canvasObjects) {
|
|
1018
|
-
const selected = selectLinkEndpoint(link, end);
|
|
1019
|
-
const absolutePoint = explicitAbsolutePoint(selected.explicit);
|
|
1020
|
-
if (absolutePoint) {
|
|
1021
|
-
return absolutePoint;
|
|
1022
|
-
}
|
|
1023
|
-
const canvasObject = findPositionedCanvasObject(canvasObjects, selected.canvasObjectId);
|
|
1024
|
-
if (!canvasObject) {
|
|
1025
|
-
return { x: 0, y: 0 };
|
|
1026
|
-
}
|
|
1027
|
-
const anchoredPoint = explicitAnchorPoint(canvasObject, selected.explicit);
|
|
1028
|
-
if (anchoredPoint) {
|
|
1029
|
-
return anchoredPoint;
|
|
1030
|
-
}
|
|
1031
|
-
return automaticEndpointPoint(
|
|
1032
|
-
canvasObject,
|
|
1033
|
-
findPositionedCanvasObject(canvasObjects, selected.oppositeCanvasObjectId)
|
|
1034
|
-
);
|
|
1106
|
+
function resolveLinkEndpoint(link, end, canvasObjects) {
|
|
1107
|
+
const selected = selectLinkEndpoint(link, end);
|
|
1108
|
+
const absolutePoint = explicitAbsolutePoint(selected.explicit);
|
|
1109
|
+
if (absolutePoint) {
|
|
1110
|
+
return absolutePoint;
|
|
1111
|
+
}
|
|
1112
|
+
const canvasObject = findPositionedCanvasObject(canvasObjects, selected.canvasObjectId);
|
|
1113
|
+
if (!canvasObject) {
|
|
1114
|
+
return { x: 0, y: 0 };
|
|
1115
|
+
}
|
|
1116
|
+
const anchoredPoint = explicitAnchorPoint(canvasObject, selected.explicit);
|
|
1117
|
+
if (anchoredPoint) {
|
|
1118
|
+
return anchoredPoint;
|
|
1119
|
+
}
|
|
1120
|
+
return automaticEndpointPoint(
|
|
1121
|
+
canvasObject,
|
|
1122
|
+
findPositionedCanvasObject(canvasObjects, selected.oppositeCanvasObjectId)
|
|
1123
|
+
);
|
|
1035
1124
|
}
|
|
1036
1125
|
function selectLinkEndpoint(link, end) {
|
|
1037
1126
|
return end === "from" ? { canvasObjectId: link.fromId, oppositeCanvasObjectId: link.toId, explicit: link.fromPoint } : { canvasObjectId: link.toId, oppositeCanvasObjectId: link.fromId, explicit: link.toPoint };
|
|
@@ -1133,13 +1222,502 @@ function sflToRenderInput(sfl) {
|
|
|
1133
1222
|
swimlanes: canvasObjects.swimlanes,
|
|
1134
1223
|
isometricObjects: canvasObjects.isometricObjects,
|
|
1135
1224
|
paths: canvasObjects.paths,
|
|
1225
|
+
dimensions: canvasObjects.dimensions,
|
|
1136
1226
|
charts: canvasObjects.charts,
|
|
1137
|
-
|
|
1227
|
+
components: canvasObjects.components,
|
|
1138
1228
|
links: createRenderInputLinks(canvasObjects),
|
|
1139
1229
|
diagnostics: state.diagnostics
|
|
1140
1230
|
};
|
|
1141
1231
|
}
|
|
1142
1232
|
|
|
1233
|
+
// src/renderScene/artifacts/component/placeholder.ts
|
|
1234
|
+
var STROKE = "#94a3b8";
|
|
1235
|
+
function buildPlaceholder(component, index) {
|
|
1236
|
+
const x = finite(component.x, 0);
|
|
1237
|
+
const y = finite(component.y, 0);
|
|
1238
|
+
const width = Math.max(0, finite(component.width, 120));
|
|
1239
|
+
const height = Math.max(0, finite(component.height, 60));
|
|
1240
|
+
const rotation = finite(component.rotation, 0);
|
|
1241
|
+
const order = 1e4 + index;
|
|
1242
|
+
const bounds = rotatedBounds({ x, y, width, height }, rotation, 2);
|
|
1243
|
+
return [
|
|
1244
|
+
{
|
|
1245
|
+
id: `widget-${component.id}`,
|
|
1246
|
+
type: "rect",
|
|
1247
|
+
order,
|
|
1248
|
+
bounds,
|
|
1249
|
+
x,
|
|
1250
|
+
y,
|
|
1251
|
+
width,
|
|
1252
|
+
height,
|
|
1253
|
+
rx: 6,
|
|
1254
|
+
rotation,
|
|
1255
|
+
style: { fill: { kind: "none" }, stroke: { kind: "solid", color: STROKE }, strokeWidth: 1, dash: [4, 3] }
|
|
1256
|
+
},
|
|
1257
|
+
{
|
|
1258
|
+
id: `widget-${component.id}-label`,
|
|
1259
|
+
type: "text",
|
|
1260
|
+
order: order + 0.1,
|
|
1261
|
+
bounds,
|
|
1262
|
+
x,
|
|
1263
|
+
y,
|
|
1264
|
+
width,
|
|
1265
|
+
height,
|
|
1266
|
+
lines: [component.type],
|
|
1267
|
+
fontFamily: DEFAULT_FONT,
|
|
1268
|
+
fontSize: 12,
|
|
1269
|
+
fontWeight: "normal",
|
|
1270
|
+
color: STROKE,
|
|
1271
|
+
align: "center",
|
|
1272
|
+
verticalAlign: "middle",
|
|
1273
|
+
lineHeight: 1.3,
|
|
1274
|
+
rotation
|
|
1275
|
+
}
|
|
1276
|
+
];
|
|
1277
|
+
}
|
|
1278
|
+
|
|
1279
|
+
// src/renderScene/artifacts/component/builtIn.ts
|
|
1280
|
+
function buildRollingNumber(component, index) {
|
|
1281
|
+
const x = finite(component.x, 0);
|
|
1282
|
+
const y = finite(component.y, 0);
|
|
1283
|
+
const width = Math.max(0, finite(component.width, 160));
|
|
1284
|
+
const height = Math.max(0, finite(component.height, 90));
|
|
1285
|
+
const rotation = finite(component.rotation, 0);
|
|
1286
|
+
return [
|
|
1287
|
+
{
|
|
1288
|
+
id: `widget-${component.id}`,
|
|
1289
|
+
type: "rolling-number",
|
|
1290
|
+
order: 1e4 + index,
|
|
1291
|
+
bounds: rotatedBounds({ x, y, width, height }, rotation, 2),
|
|
1292
|
+
x,
|
|
1293
|
+
y,
|
|
1294
|
+
width,
|
|
1295
|
+
height,
|
|
1296
|
+
rotation,
|
|
1297
|
+
value: formatRollingNumber(component.value, component.digits),
|
|
1298
|
+
digits: component.digits,
|
|
1299
|
+
duration: Math.max(0, finite(component.duration, 420)),
|
|
1300
|
+
label: component.label,
|
|
1301
|
+
componentStyle: resolveRollingNumberStyle(component.style)
|
|
1302
|
+
}
|
|
1303
|
+
];
|
|
1304
|
+
}
|
|
1305
|
+
function buildTickScale(component, index) {
|
|
1306
|
+
const x = finite(component.x, 0);
|
|
1307
|
+
const y = finite(component.y, 0);
|
|
1308
|
+
const width = Math.max(0, finite(component.width, 200));
|
|
1309
|
+
const height = Math.max(0, finite(component.height, 200));
|
|
1310
|
+
const rotation = finite(component.rotation, 0);
|
|
1311
|
+
const max = finite(component.max, 100) || 100;
|
|
1312
|
+
const progress = Math.min(1, Math.max(0, finite(Number(component.value), 0) / max));
|
|
1313
|
+
const nodes = [
|
|
1314
|
+
{
|
|
1315
|
+
id: `widget-${component.id}`,
|
|
1316
|
+
type: "shader-surface",
|
|
1317
|
+
order: 1e4 + index,
|
|
1318
|
+
bounds: rotatedBounds({ x, y, width, height }, rotation, 2),
|
|
1319
|
+
x,
|
|
1320
|
+
y,
|
|
1321
|
+
width,
|
|
1322
|
+
height,
|
|
1323
|
+
rotation,
|
|
1324
|
+
shader: { name: component.id, program: "tickScale", parameters: { ...component.parameters, progress, max } },
|
|
1325
|
+
mask: "ellipse"
|
|
1326
|
+
}
|
|
1327
|
+
];
|
|
1328
|
+
if (component.labels) {
|
|
1329
|
+
nodes.push(...buildTickLabels(component, { x, y, width, height, max, order: 1e4 + index }));
|
|
1330
|
+
}
|
|
1331
|
+
return nodes;
|
|
1332
|
+
}
|
|
1333
|
+
function buildTickLabels(component, box) {
|
|
1334
|
+
const labels = component.labels ?? {};
|
|
1335
|
+
const ticks = Math.max(1, finite(Number(component.parameters.ticks), 48));
|
|
1336
|
+
const major = Math.max(1, finite(Number(component.parameters.major), 5));
|
|
1337
|
+
const start = finite(Number(component.parameters.start), 225) * Math.PI / 180;
|
|
1338
|
+
const sweep = finite(Number(component.parameters.sweep), 270) * Math.PI / 180;
|
|
1339
|
+
const radius = finite(Number(component.parameters.radius), 0.9) + finite(labels.offset, 0.08);
|
|
1340
|
+
const fontSize = finite(labels.size, 12);
|
|
1341
|
+
const centerX = box.x + box.width / 2;
|
|
1342
|
+
const centerY = box.y + box.height / 2;
|
|
1343
|
+
const count = Math.floor(ticks / major);
|
|
1344
|
+
const nodes = [];
|
|
1345
|
+
for (let step = 0; step <= count; step += 1) {
|
|
1346
|
+
const fraction = step * major / ticks;
|
|
1347
|
+
const angle = start - fraction * sweep;
|
|
1348
|
+
const labelX2 = centerX + Math.cos(angle) * radius * (box.width / 2);
|
|
1349
|
+
const labelY = centerY - Math.sin(angle) * radius * (box.height / 2);
|
|
1350
|
+
const labelBox = { x: labelX2 - 24, y: labelY - fontSize, width: 48, height: fontSize * 2 };
|
|
1351
|
+
nodes.push({
|
|
1352
|
+
id: `widget-${component.id}-label-${step}`,
|
|
1353
|
+
type: "text",
|
|
1354
|
+
order: box.order + 0.1,
|
|
1355
|
+
bounds: rotatedBounds(labelBox, 0, 2),
|
|
1356
|
+
...labelBox,
|
|
1357
|
+
lines: [String(Math.round(box.max * fraction * 10) / 10)],
|
|
1358
|
+
fontFamily: labels.fontFamily || DEFAULT_FONT,
|
|
1359
|
+
fontSize,
|
|
1360
|
+
fontWeight: labels.weight ?? "normal",
|
|
1361
|
+
color: labels.color || "#8f95c4",
|
|
1362
|
+
align: "center",
|
|
1363
|
+
verticalAlign: "middle",
|
|
1364
|
+
lineHeight: 1.3
|
|
1365
|
+
});
|
|
1366
|
+
}
|
|
1367
|
+
return nodes;
|
|
1368
|
+
}
|
|
1369
|
+
function buildRuler(component, index) {
|
|
1370
|
+
const x = finite(component.x, 0);
|
|
1371
|
+
const y = finite(component.y, 0);
|
|
1372
|
+
const width = Math.max(0, finite(component.width, 120));
|
|
1373
|
+
const height = Math.max(0, finite(component.height, 360));
|
|
1374
|
+
const rotation = finite(component.rotation, 0);
|
|
1375
|
+
const min = finite(component.min, 0);
|
|
1376
|
+
const max = finite(component.max, 100);
|
|
1377
|
+
const progress = max === min ? 0 : Math.min(1, Math.max(0, (finite(Number(component.value), min) - min) / (max - min)));
|
|
1378
|
+
const nodes = [
|
|
1379
|
+
{
|
|
1380
|
+
id: `widget-${component.id}`,
|
|
1381
|
+
type: "shader-surface",
|
|
1382
|
+
order: 1e4 + index,
|
|
1383
|
+
bounds: rotatedBounds({ x, y, width, height }, rotation, 2),
|
|
1384
|
+
x,
|
|
1385
|
+
y,
|
|
1386
|
+
width,
|
|
1387
|
+
height,
|
|
1388
|
+
rotation,
|
|
1389
|
+
shader: { name: component.id, program: "ruler", parameters: { ...component.parameters, progress, min, max } },
|
|
1390
|
+
mask: "rect"
|
|
1391
|
+
}
|
|
1392
|
+
];
|
|
1393
|
+
if (component.labels) {
|
|
1394
|
+
nodes.push(...buildRulerLabels(component, { x, y, width, height, min, max, order: 1e4 + index }));
|
|
1395
|
+
}
|
|
1396
|
+
return nodes;
|
|
1397
|
+
}
|
|
1398
|
+
function buildRulerLabels(component, box) {
|
|
1399
|
+
const labels = component.labels ?? {};
|
|
1400
|
+
const horizontal = component.parameters.axis === "horizontal";
|
|
1401
|
+
const ticks = Math.max(1, finite(Number(component.parameters.ticks), 50));
|
|
1402
|
+
const major = Math.max(1, finite(Number(component.parameters.major), 5));
|
|
1403
|
+
const inset = finite(Number(component.parameters.inset), 0.05) > 0 ? finite(Number(component.parameters.inset), 0.05) : 0.05;
|
|
1404
|
+
const line = finite(Number(component.parameters.line), 0.7) > 0 ? finite(Number(component.parameters.line), 0.7) : 0.7;
|
|
1405
|
+
const across = horizontal ? box.height : box.width;
|
|
1406
|
+
const tickLength = (finite(Number(component.parameters.length), 0.1) > 0 ? finite(Number(component.parameters.length), 0.1) : 0.1) * across * 1.9;
|
|
1407
|
+
const edge = line * across - 0.12 * across - tickLength - finite(labels.offset, 0.04) * across;
|
|
1408
|
+
const fontSize = finite(labels.size, 12);
|
|
1409
|
+
const count = Math.floor(ticks / major);
|
|
1410
|
+
const nodes = [];
|
|
1411
|
+
for (let step = 0; step <= count; step += 1) {
|
|
1412
|
+
const fraction = step * major / ticks;
|
|
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 };
|
|
1415
|
+
nodes.push({
|
|
1416
|
+
id: `widget-${component.id}-label-${step}`,
|
|
1417
|
+
type: "text",
|
|
1418
|
+
order: box.order + 0.1,
|
|
1419
|
+
bounds: rotatedBounds(labelBox, 0, 2),
|
|
1420
|
+
...labelBox,
|
|
1421
|
+
lines: [String(Math.round((box.min + (box.max - box.min) * fraction) * 10) / 10)],
|
|
1422
|
+
fontFamily: labels.fontFamily || DEFAULT_FONT,
|
|
1423
|
+
fontSize,
|
|
1424
|
+
fontWeight: labels.weight ?? "normal",
|
|
1425
|
+
color: labels.color || "#8f95c4",
|
|
1426
|
+
align: horizontal ? "center" : "right",
|
|
1427
|
+
verticalAlign: "middle",
|
|
1428
|
+
lineHeight: 1.3
|
|
1429
|
+
});
|
|
1430
|
+
}
|
|
1431
|
+
return nodes;
|
|
1432
|
+
}
|
|
1433
|
+
|
|
1434
|
+
// src/renderScene/artifacts/component/controlParts.ts
|
|
1435
|
+
var DISABLED_INK = "#94a3b8";
|
|
1436
|
+
function controlBox(component, index, fallback) {
|
|
1437
|
+
return {
|
|
1438
|
+
x: finite(component.x, 0),
|
|
1439
|
+
y: finite(component.y, 0),
|
|
1440
|
+
width: Math.max(1, finite(component.width, fallback.width)),
|
|
1441
|
+
height: Math.max(1, finite(component.height, fallback.height)),
|
|
1442
|
+
order: 1e4 + index
|
|
1443
|
+
};
|
|
1444
|
+
}
|
|
1445
|
+
var textProperty = (component, key) => String(component.properties[key] ?? "");
|
|
1446
|
+
var numberProperty2 = (component, key) => Number(component.properties[key] ?? 0);
|
|
1447
|
+
var solid = (color) => ({ kind: "solid", color });
|
|
1448
|
+
var ink = (component, color) => component.disabled ? DISABLED_INK : color;
|
|
1449
|
+
function fade(component, style) {
|
|
1450
|
+
return component.disabled ? { ...style, opacity: 0.4 } : style;
|
|
1451
|
+
}
|
|
1452
|
+
function hitArea(component, box) {
|
|
1453
|
+
return {
|
|
1454
|
+
id: `widget-${component.id}`,
|
|
1455
|
+
type: "rect",
|
|
1456
|
+
order: box.order,
|
|
1457
|
+
bounds: rotatedBounds(box, 0, 0),
|
|
1458
|
+
x: box.x,
|
|
1459
|
+
y: box.y,
|
|
1460
|
+
width: box.width,
|
|
1461
|
+
height: box.height,
|
|
1462
|
+
style: { fill: { kind: "none" }, stroke: { kind: "none" }, pointerEvents: "all" }
|
|
1463
|
+
};
|
|
1464
|
+
}
|
|
1465
|
+
function labelText(component, part, area, label, order) {
|
|
1466
|
+
return {
|
|
1467
|
+
id: `widget-${component.id}-${part}`,
|
|
1468
|
+
type: "text",
|
|
1469
|
+
order,
|
|
1470
|
+
bounds: rotatedBounds(area, 0, 0),
|
|
1471
|
+
x: area.x,
|
|
1472
|
+
y: area.y,
|
|
1473
|
+
width: area.width,
|
|
1474
|
+
height: area.height,
|
|
1475
|
+
lines: [label.text],
|
|
1476
|
+
fontFamily: DEFAULT_FONT,
|
|
1477
|
+
fontSize: label.fontSize,
|
|
1478
|
+
fontWeight: "600",
|
|
1479
|
+
color: label.color,
|
|
1480
|
+
align: label.align,
|
|
1481
|
+
verticalAlign: "middle",
|
|
1482
|
+
lineHeight: 1.3
|
|
1483
|
+
};
|
|
1484
|
+
}
|
|
1485
|
+
|
|
1486
|
+
// src/renderScene/artifacts/component/button.ts
|
|
1487
|
+
function buildButton(component, index) {
|
|
1488
|
+
const box = controlBox(component, index, { width: 120, height: 40 });
|
|
1489
|
+
const nodes = [
|
|
1490
|
+
hitArea(component, box),
|
|
1491
|
+
{
|
|
1492
|
+
id: `widget-${component.id}-face`,
|
|
1493
|
+
type: "rect",
|
|
1494
|
+
order: box.order + 0.1,
|
|
1495
|
+
bounds: rotatedBounds(box, 0, 0),
|
|
1496
|
+
x: box.x,
|
|
1497
|
+
y: box.y,
|
|
1498
|
+
width: box.width,
|
|
1499
|
+
height: box.height,
|
|
1500
|
+
rx: Math.min(numberProperty2(component, "radius"), box.height / 2),
|
|
1501
|
+
style: fade(component, { fill: solid(textProperty(component, "accent")), stroke: { kind: "none" } })
|
|
1502
|
+
}
|
|
1503
|
+
];
|
|
1504
|
+
if (component.label) {
|
|
1505
|
+
const label = {
|
|
1506
|
+
text: component.label,
|
|
1507
|
+
color: ink(component, textProperty(component, "textColor")),
|
|
1508
|
+
fontSize: numberProperty2(component, "fontSize"),
|
|
1509
|
+
align: "center"
|
|
1510
|
+
};
|
|
1511
|
+
nodes.push(labelText(component, "label", box, label, box.order + 0.2));
|
|
1512
|
+
}
|
|
1513
|
+
return nodes;
|
|
1514
|
+
}
|
|
1515
|
+
|
|
1516
|
+
// src/renderScene/artifacts/component/checkbox.ts
|
|
1517
|
+
var CORNER_RATIO = 0.22;
|
|
1518
|
+
var LABEL_GAP_RATIO = 0.5;
|
|
1519
|
+
var CHECK_MARK = [
|
|
1520
|
+
[0.24, 0.52],
|
|
1521
|
+
[0.43, 0.72],
|
|
1522
|
+
[0.78, 0.3]
|
|
1523
|
+
];
|
|
1524
|
+
function checkPath(square) {
|
|
1525
|
+
const [first, ...rest] = CHECK_MARK.map(([u, v]) => `${square.x + u * square.width} ${square.y + v * square.width}`);
|
|
1526
|
+
return `M ${first} ${rest.map((point) => `L ${point}`).join(" ")}`;
|
|
1527
|
+
}
|
|
1528
|
+
function boxNode(component, box, square) {
|
|
1529
|
+
const on = component.value === true;
|
|
1530
|
+
return {
|
|
1531
|
+
id: `widget-${component.id}-box`,
|
|
1532
|
+
type: "rect",
|
|
1533
|
+
order: box.order + 0.1,
|
|
1534
|
+
bounds: rotatedBounds(square, 0, 2),
|
|
1535
|
+
...square,
|
|
1536
|
+
rx: square.width * CORNER_RATIO,
|
|
1537
|
+
style: fade(component, {
|
|
1538
|
+
fill: on ? solid(textProperty(component, "accent")) : { kind: "none" },
|
|
1539
|
+
stroke: solid(on ? textProperty(component, "accent") : textProperty(component, "stroke")),
|
|
1540
|
+
strokeWidth: 1.5
|
|
1541
|
+
})
|
|
1542
|
+
};
|
|
1543
|
+
}
|
|
1544
|
+
function checkNode(component, box, square) {
|
|
1545
|
+
return {
|
|
1546
|
+
id: `widget-${component.id}-check`,
|
|
1547
|
+
type: "path",
|
|
1548
|
+
order: box.order + 0.2,
|
|
1549
|
+
bounds: rotatedBounds(square, 0, 0),
|
|
1550
|
+
d: checkPath(square),
|
|
1551
|
+
style: fade(component, {
|
|
1552
|
+
fill: { kind: "none" },
|
|
1553
|
+
stroke: solid(textProperty(component, "check")),
|
|
1554
|
+
strokeWidth: Math.max(1.5, square.width * 0.12),
|
|
1555
|
+
lineCap: "round",
|
|
1556
|
+
lineJoin: "round"
|
|
1557
|
+
})
|
|
1558
|
+
};
|
|
1559
|
+
}
|
|
1560
|
+
function labelNode(component, box, side, text) {
|
|
1561
|
+
const gap = side * LABEL_GAP_RATIO;
|
|
1562
|
+
const area = { x: box.x + side + gap, y: box.y, width: Math.max(0, box.width - side - gap), height: box.height };
|
|
1563
|
+
const label = {
|
|
1564
|
+
text,
|
|
1565
|
+
color: ink(component, textProperty(component, "textColor")),
|
|
1566
|
+
fontSize: numberProperty2(component, "fontSize"),
|
|
1567
|
+
align: "left"
|
|
1568
|
+
};
|
|
1569
|
+
return labelText(component, "label", area, label, box.order + 0.3);
|
|
1570
|
+
}
|
|
1571
|
+
function buildCheckbox(component, index) {
|
|
1572
|
+
const box = controlBox(component, index, { width: 160, height: 24 });
|
|
1573
|
+
const side = Math.min(box.height, box.width);
|
|
1574
|
+
const square = { x: box.x, y: box.y + (box.height - side) / 2, width: side, height: side };
|
|
1575
|
+
return [
|
|
1576
|
+
hitArea(component, box),
|
|
1577
|
+
boxNode(component, box, square),
|
|
1578
|
+
...component.value === true ? [checkNode(component, box, square)] : [],
|
|
1579
|
+
...component.label ? [labelNode(component, box, side, component.label)] : []
|
|
1580
|
+
];
|
|
1581
|
+
}
|
|
1582
|
+
|
|
1583
|
+
// src/renderScene/artifacts/component/switch.ts
|
|
1584
|
+
var PADDING_RATIO = 0.12;
|
|
1585
|
+
function buildSwitch(component, index) {
|
|
1586
|
+
const box = controlBox(component, index, { width: 52, height: 30 });
|
|
1587
|
+
const on = component.value === true;
|
|
1588
|
+
const padding = box.height * PADDING_RATIO;
|
|
1589
|
+
const radius = box.height / 2 - padding;
|
|
1590
|
+
const centerX = on ? box.x + box.width - box.height / 2 : box.x + box.height / 2;
|
|
1591
|
+
const thumb = { x: centerX - radius, y: box.y + padding, width: radius * 2, height: radius * 2 };
|
|
1592
|
+
return [
|
|
1593
|
+
hitArea(component, box),
|
|
1594
|
+
{
|
|
1595
|
+
id: `widget-${component.id}-track`,
|
|
1596
|
+
type: "rect",
|
|
1597
|
+
order: box.order + 0.1,
|
|
1598
|
+
bounds: rotatedBounds(box, 0, 0),
|
|
1599
|
+
x: box.x,
|
|
1600
|
+
y: box.y,
|
|
1601
|
+
width: box.width,
|
|
1602
|
+
height: box.height,
|
|
1603
|
+
rx: box.height / 2,
|
|
1604
|
+
style: fade(component, {
|
|
1605
|
+
fill: solid(textProperty(component, on ? "accent" : "track")),
|
|
1606
|
+
stroke: { kind: "none" }
|
|
1607
|
+
})
|
|
1608
|
+
},
|
|
1609
|
+
{
|
|
1610
|
+
id: `widget-${component.id}-thumb`,
|
|
1611
|
+
type: "ellipse",
|
|
1612
|
+
order: box.order + 0.2,
|
|
1613
|
+
bounds: rotatedBounds(thumb, 0, 0),
|
|
1614
|
+
cx: centerX,
|
|
1615
|
+
cy: box.y + box.height / 2,
|
|
1616
|
+
rx: radius,
|
|
1617
|
+
ry: radius,
|
|
1618
|
+
style: fade(component, {
|
|
1619
|
+
fill: solid(textProperty(component, "thumb")),
|
|
1620
|
+
stroke: { kind: "none" },
|
|
1621
|
+
shadow: { color: "#000000", opacity: 0.25, blur: 2, dx: 0, dy: 1 }
|
|
1622
|
+
})
|
|
1623
|
+
}
|
|
1624
|
+
];
|
|
1625
|
+
}
|
|
1626
|
+
|
|
1627
|
+
// src/renderScene/artifacts/component/toggleButton.ts
|
|
1628
|
+
function buildToggleButton(component, index) {
|
|
1629
|
+
const box = controlBox(component, index, { width: 120, height: 40 });
|
|
1630
|
+
const on = component.value === true;
|
|
1631
|
+
const nodes = [
|
|
1632
|
+
hitArea(component, box),
|
|
1633
|
+
{
|
|
1634
|
+
id: `widget-${component.id}-face`,
|
|
1635
|
+
type: "rect",
|
|
1636
|
+
order: box.order + 0.1,
|
|
1637
|
+
bounds: rotatedBounds(box, 0, 2),
|
|
1638
|
+
x: box.x,
|
|
1639
|
+
y: box.y,
|
|
1640
|
+
width: box.width,
|
|
1641
|
+
height: box.height,
|
|
1642
|
+
rx: box.height / 2,
|
|
1643
|
+
style: fade(component, {
|
|
1644
|
+
fill: on ? solid(textProperty(component, "accent")) : { kind: "none" },
|
|
1645
|
+
stroke: solid(on ? textProperty(component, "accent") : textProperty(component, "stroke")),
|
|
1646
|
+
strokeWidth: 1.5
|
|
1647
|
+
})
|
|
1648
|
+
}
|
|
1649
|
+
];
|
|
1650
|
+
if (component.label) {
|
|
1651
|
+
const label = {
|
|
1652
|
+
text: component.label,
|
|
1653
|
+
color: ink(component, textProperty(component, on ? "onTextColor" : "textColor")),
|
|
1654
|
+
fontSize: numberProperty2(component, "fontSize"),
|
|
1655
|
+
align: "center"
|
|
1656
|
+
};
|
|
1657
|
+
nodes.push(labelText(component, "label", box, label, box.order + 0.2));
|
|
1658
|
+
}
|
|
1659
|
+
return nodes;
|
|
1660
|
+
}
|
|
1661
|
+
|
|
1662
|
+
// src/renderScene/artifacts/component/registry.ts
|
|
1663
|
+
var asComponentBuilder = (build) => (component, index) => build(component, index);
|
|
1664
|
+
var builders = /* @__PURE__ */ new Map([
|
|
1665
|
+
["rollingNumber", asComponentBuilder(buildRollingNumber)],
|
|
1666
|
+
["tickScale", asComponentBuilder(buildTickScale)],
|
|
1667
|
+
["ruler", asComponentBuilder(buildRuler)],
|
|
1668
|
+
["switch", asComponentBuilder(buildSwitch)],
|
|
1669
|
+
["checkbox", asComponentBuilder(buildCheckbox)],
|
|
1670
|
+
["toggleButton", asComponentBuilder(buildToggleButton)],
|
|
1671
|
+
["button", asComponentBuilder(buildButton)]
|
|
1672
|
+
]);
|
|
1673
|
+
function registerComponentBuilder(type, builder) {
|
|
1674
|
+
builders.set(type, builder);
|
|
1675
|
+
return () => {
|
|
1676
|
+
if (builders.get(type) === builder) {
|
|
1677
|
+
builders.delete(type);
|
|
1678
|
+
}
|
|
1679
|
+
};
|
|
1680
|
+
}
|
|
1681
|
+
function getComponentBuilder(type) {
|
|
1682
|
+
return builders.get(type);
|
|
1683
|
+
}
|
|
1684
|
+
|
|
1685
|
+
// src/renderScene/artifacts/component/build.ts
|
|
1686
|
+
function ariaOf(component) {
|
|
1687
|
+
const role = getComponentDescriptor(component.type)?.role;
|
|
1688
|
+
if (!role || !isGenericComponent(component)) {
|
|
1689
|
+
return void 0;
|
|
1690
|
+
}
|
|
1691
|
+
const flag = typeof component.value === "boolean" ? component.value : void 0;
|
|
1692
|
+
return {
|
|
1693
|
+
role,
|
|
1694
|
+
...flag === void 0 ? {} : role === "button" ? { pressed: flag } : { checked: flag },
|
|
1695
|
+
...component.disabled ? { disabled: true } : {}
|
|
1696
|
+
};
|
|
1697
|
+
}
|
|
1698
|
+
function labelOf(component) {
|
|
1699
|
+
return component.label ?? (isGenericComponent(component) ? component.id : String(component.value));
|
|
1700
|
+
}
|
|
1701
|
+
function buildComponents(components) {
|
|
1702
|
+
return components.flatMap((component, index) => {
|
|
1703
|
+
const build = getComponentBuilder(component.type) ?? buildPlaceholder;
|
|
1704
|
+
const nodes = tag(
|
|
1705
|
+
build(component, index),
|
|
1706
|
+
"widget",
|
|
1707
|
+
component.id,
|
|
1708
|
+
component.type,
|
|
1709
|
+
labelOf(component),
|
|
1710
|
+
component.parentFrameId
|
|
1711
|
+
);
|
|
1712
|
+
const aria = ariaOf(component);
|
|
1713
|
+
const primary = nodes.find((node) => node.identity?.primary);
|
|
1714
|
+
if (aria && primary?.identity) {
|
|
1715
|
+
primary.identity.aria = aria;
|
|
1716
|
+
}
|
|
1717
|
+
return nodes;
|
|
1718
|
+
});
|
|
1719
|
+
}
|
|
1720
|
+
|
|
1143
1721
|
// src/renderScene/artifacts/container/style.ts
|
|
1144
1722
|
function simpleContainerStyle(fill2, stroke, strokeWidth, dash) {
|
|
1145
1723
|
return {
|
|
@@ -1504,7 +2082,130 @@ function buildContainers(input) {
|
|
|
1504
2082
|
];
|
|
1505
2083
|
}
|
|
1506
2084
|
|
|
1507
|
-
// src/
|
|
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 };
|
|
1508
2209
|
function isometricContext(object, index) {
|
|
1509
2210
|
const strokeWidth = Math.max(0, finite(object.strokeWidth, 1));
|
|
1510
2211
|
const rotation = finite(object.rotation, 0);
|
|
@@ -1529,85 +2230,22 @@ function isometricContext(object, index) {
|
|
|
1529
2230
|
lineJoin: "round"
|
|
1530
2231
|
}
|
|
1531
2232
|
}
|
|
1532
|
-
};
|
|
1533
|
-
}
|
|
1534
|
-
function groundShadowNode(context, faces) {
|
|
1535
|
-
const { object, index, rotation, rotationCenter } = context;
|
|
1536
|
-
if (!object.hasShadow) {
|
|
1537
|
-
return void 0;
|
|
1538
|
-
}
|
|
1539
|
-
const height = Math.max(0, object.height);
|
|
1540
|
-
const heightFactor = 0.6 + Math.min(1, height / 150) * 0.7;
|
|
1541
|
-
const shadowDrop = height + finite(object.shadowStyle?.distance, 0);
|
|
1542
|
-
const contactFootprint = faces.top.map((point) => ({ x: point.x, y: point.y + shadowDrop }));
|
|
1543
|
-
const footprintCenter = {
|
|
1544
|
-
x: contactFootprint.reduce((sum, point) => sum + point.x, 0) / contactFootprint.length,
|
|
1545
|
-
y: contactFootprint.reduce((sum, point) => sum + point.y, 0) / contactFootprint.length
|
|
1546
|
-
};
|
|
1547
|
-
const shadowSpread = 1.3;
|
|
1548
|
-
const footprint = contactFootprint.map((point) => ({
|
|
1549
|
-
x: footprintCenter.x + (point.x - footprintCenter.x) * shadowSpread,
|
|
1550
|
-
y: footprintCenter.y + (point.y - footprintCenter.y) * shadowSpread
|
|
1551
|
-
}));
|
|
1552
|
-
const footprintXs = footprint.map((point) => point.x);
|
|
1553
|
-
const footprintYs = footprint.map((point) => point.y);
|
|
1554
|
-
return {
|
|
1555
|
-
type: "path",
|
|
1556
|
-
id: `isometric-${object.id}-ground-shadow`,
|
|
1557
|
-
order: 14e3 + index,
|
|
1558
|
-
bounds: {
|
|
1559
|
-
minX: Math.min(...footprintXs),
|
|
1560
|
-
minY: Math.min(...footprintYs),
|
|
1561
|
-
maxX: Math.max(...footprintXs),
|
|
1562
|
-
maxY: Math.max(...footprintYs)
|
|
1563
|
-
},
|
|
1564
|
-
d: roundedPolygonPath(footprint, 0),
|
|
1565
|
-
rotation,
|
|
1566
|
-
rotationCenter,
|
|
1567
|
-
style: {
|
|
1568
|
-
fill: { kind: "solid", color: object.shadowStyle?.color ?? "#000000" },
|
|
1569
|
-
stroke: { kind: "none" },
|
|
1570
|
-
opacity: Math.min(1, (object.shadowStyle?.opacity ?? 0.18) * heightFactor),
|
|
1571
|
-
blur: finite(object.shadowStyle?.blur, 8),
|
|
1572
|
-
pointerEvents: "none"
|
|
1573
|
-
}
|
|
1574
|
-
};
|
|
1575
|
-
}
|
|
1576
|
-
function faceNodes(context, faces, hullClip) {
|
|
1577
|
-
const { object, order, common } = context;
|
|
1578
|
-
const noStroke = { ...common.style, stroke: { kind: "none" } };
|
|
1579
|
-
const faceFills = deriveFaceFills(object.fill ?? "#f8fafc");
|
|
1580
|
-
const colorProp = { prop: "style.fill", propKind: "color", propSolidOnly: true };
|
|
1581
|
-
const face = (name, offset, points, color2) => ({
|
|
1582
|
-
...common,
|
|
1583
|
-
id: `isometric-${object.id}-${name}`,
|
|
1584
|
-
order: order + offset,
|
|
1585
|
-
d: roundedPolygonPath(points, 0),
|
|
1586
|
-
style: { ...noStroke, fill: { kind: "solid", color: color2 }, clip: hullClip },
|
|
1587
|
-
...colorProp
|
|
1588
|
-
});
|
|
1589
|
-
return [
|
|
1590
|
-
face("top", 0, faces.top, faceFills.topFill),
|
|
1591
|
-
face("front", 0.1, faces.front, faceFills.frontFill),
|
|
1592
|
-
face("side", 0.2, faces.right, faceFills.sideFill)
|
|
1593
|
-
];
|
|
2233
|
+
};
|
|
1594
2234
|
}
|
|
1595
|
-
function
|
|
1596
|
-
const { object, order, common, strokeWidth } = context;
|
|
2235
|
+
function faceNode(context, name, offset, points, style) {
|
|
1597
2236
|
return {
|
|
1598
|
-
...common,
|
|
1599
|
-
id: `isometric-${object.id}
|
|
1600
|
-
order: order +
|
|
1601
|
-
d:
|
|
1602
|
-
style
|
|
1603
|
-
|
|
1604
|
-
fill: { kind: "none" },
|
|
1605
|
-
stroke: { kind: "solid", color: "#cbd5e1" },
|
|
1606
|
-
strokeWidth: Math.min(strokeWidth, 1),
|
|
1607
|
-
clip: hullClip
|
|
1608
|
-
}
|
|
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
|
|
1609
2243
|
};
|
|
1610
2244
|
}
|
|
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]];
|
|
2248
|
+
}
|
|
1611
2249
|
function hullNode(context, hullPath, cornerRadius) {
|
|
1612
2250
|
const { object, order, common, box } = context;
|
|
1613
2251
|
return {
|
|
@@ -1628,6 +2266,14 @@ function hullNode(context, hullPath, cornerRadius) {
|
|
|
1628
2266
|
style: { ...common.style, fill: { kind: "none" } }
|
|
1629
2267
|
};
|
|
1630
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
|
|
1631
2277
|
var LABEL_HEIGHT = 20;
|
|
1632
2278
|
var LABEL_GAP = 12;
|
|
1633
2279
|
var LABEL_PADDING_X = 6;
|
|
@@ -1723,20 +2369,232 @@ function labelNodes(context, text) {
|
|
|
1723
2369
|
}
|
|
1724
2370
|
return [guide, labelBackgroundNode(context, placement, text, background), label];
|
|
1725
2371
|
}
|
|
1726
|
-
|
|
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) {
|
|
1727
2480
|
const context = isometricContext(object, index);
|
|
1728
2481
|
const faces = isometricFaces(object);
|
|
1729
2482
|
const cornerRadius = Math.max(0, finite(object.cornerRadius, 8));
|
|
1730
|
-
const
|
|
1731
|
-
const hullPath = roundedPolygonPath(silhouette, cornerRadius);
|
|
2483
|
+
const hullPath = roundedPolygonPath(silhouette(object), cornerRadius);
|
|
1732
2484
|
const hullClip = { type: "path", d: hullPath };
|
|
1733
|
-
const groundShadow = groundShadowNode(context, faces);
|
|
2485
|
+
const groundShadow = groundShadowNode(context, faces.top);
|
|
1734
2486
|
const seams = seamsNode(context, faces, hullClip);
|
|
1735
2487
|
const hull = hullNode(context, hullPath, cornerRadius);
|
|
1736
2488
|
const facesNodes = faceNodes(context, faces, hullClip);
|
|
1737
2489
|
const objectNodes = groundShadow ? [hull, ...facesNodes, groundShadow, seams] : [hull, ...facesNodes, seams];
|
|
1738
2490
|
return object.text ? [...objectNodes, ...labelNodes(context, object.text)] : objectNodes;
|
|
1739
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
|
+
}
|
|
1740
2598
|
function buildIsometricObjects(objects) {
|
|
1741
2599
|
return objects.flatMap(
|
|
1742
2600
|
(object, index) => tag(
|
|
@@ -1872,13 +2730,13 @@ function labelLayout(link, measureText) {
|
|
|
1872
2730
|
const lines = visible ? wrapText(link.text ?? "", width, fontSize, metrics) : [];
|
|
1873
2731
|
return { visible, fontSize, width, height: lines.length * fontSize * 1.4, lines };
|
|
1874
2732
|
}
|
|
1875
|
-
function linkStyle(item, strokeWidth,
|
|
2733
|
+
function linkStyle(item, strokeWidth, color, dash) {
|
|
1876
2734
|
const link = item.link;
|
|
1877
2735
|
const stroke = typeof link.style?.color === "object" && link.style.color.type === "gradient" ? {
|
|
1878
2736
|
kind: "linear-gradient",
|
|
1879
2737
|
angle: 0,
|
|
1880
2738
|
stops: link.style.color.stops.map((stop) => ({ offset: stop.position, color: stop.color }))
|
|
1881
|
-
} : { kind: "solid", color
|
|
2739
|
+
} : { kind: "solid", color };
|
|
1882
2740
|
return {
|
|
1883
2741
|
fill: { kind: "none" },
|
|
1884
2742
|
stroke,
|
|
@@ -1895,7 +2753,7 @@ function createLinkRenderContext(item, index, measureText) {
|
|
|
1895
2753
|
const pathType = link.style?.pathType ?? "orthogonal";
|
|
1896
2754
|
const { points, segments } = calculateLinkRoute(link, from, to, pathType);
|
|
1897
2755
|
const strokeWidth = finite(link.style?.strokeWidth, 2);
|
|
1898
|
-
const
|
|
2756
|
+
const color = getLinkStrokeColor(link.style?.color) || "#64748b";
|
|
1899
2757
|
const label = labelLayout(link, measureText);
|
|
1900
2758
|
const contentDash = getDashArray(strokeWidth, link.style?.strokeStyle ?? "solid");
|
|
1901
2759
|
const gap = label.visible && !contentDash ? labelGapDash(points, pathType, label.width, label.height) : null;
|
|
@@ -1908,9 +2766,9 @@ function createLinkRenderContext(item, index, measureText) {
|
|
|
1908
2766
|
midpoint: getLineMidpoint(points, pathType, from, to),
|
|
1909
2767
|
strokeWidth,
|
|
1910
2768
|
bounds: linkBounds(points, strokeWidth + 14),
|
|
1911
|
-
color
|
|
2769
|
+
color,
|
|
1912
2770
|
order: 2e4 + index,
|
|
1913
|
-
style: linkStyle(item, strokeWidth,
|
|
2771
|
+
style: linkStyle(item, strokeWidth, color, dash),
|
|
1914
2772
|
label,
|
|
1915
2773
|
hasLabelGap: Boolean(gap)
|
|
1916
2774
|
};
|
|
@@ -1943,7 +2801,7 @@ function polylinePathData(points) {
|
|
|
1943
2801
|
}
|
|
1944
2802
|
return path;
|
|
1945
2803
|
}
|
|
1946
|
-
function
|
|
2804
|
+
function pathData2(points, pathType, segments, strokeWidth) {
|
|
1947
2805
|
if (points.length < 4) {
|
|
1948
2806
|
return "";
|
|
1949
2807
|
}
|
|
@@ -1977,7 +2835,7 @@ function renderLinkPath(context) {
|
|
|
1977
2835
|
id: `link-${link.id}`,
|
|
1978
2836
|
order: context.order,
|
|
1979
2837
|
bounds: context.bounds,
|
|
1980
|
-
d:
|
|
2838
|
+
d: pathData2(context.points, context.pathType, context.segments, context.strokeWidth),
|
|
1981
2839
|
style: context.style,
|
|
1982
2840
|
markerStart: markerForEnd(link, "start"),
|
|
1983
2841
|
markerEnd: markerForEnd(link, "end"),
|
|
@@ -2510,211 +3368,6 @@ function buildShapes(shapes, diagnostics, measureText) {
|
|
|
2510
3368
|
);
|
|
2511
3369
|
}
|
|
2512
3370
|
|
|
2513
|
-
// src/model/widget/format.ts
|
|
2514
|
-
function formatRollingNumber(value, digits) {
|
|
2515
|
-
const text = String(value);
|
|
2516
|
-
if (digits === void 0) {
|
|
2517
|
-
return text;
|
|
2518
|
-
}
|
|
2519
|
-
if (!Number.isInteger(digits) || digits < 1) {
|
|
2520
|
-
return text;
|
|
2521
|
-
}
|
|
2522
|
-
return text.padStart(digits, "0");
|
|
2523
|
-
}
|
|
2524
|
-
|
|
2525
|
-
// src/model/widget/theme.ts
|
|
2526
|
-
var DEFAULT_ROLLING_NUMBER_STYLE = {
|
|
2527
|
-
color: "#000000",
|
|
2528
|
-
surface: "rgba(255, 255, 255, 0.28)",
|
|
2529
|
-
divider: "rgba(0, 0, 0, 0.2)",
|
|
2530
|
-
labelColor: "rgba(0, 0, 0, 0.62)",
|
|
2531
|
-
fontFamily: "'Roboto Mono', 'SFMono-Regular', Consolas, monospace",
|
|
2532
|
-
variant: "flip",
|
|
2533
|
-
motion: "roll",
|
|
2534
|
-
fontWeight: "300",
|
|
2535
|
-
fontSize: 0
|
|
2536
|
-
};
|
|
2537
|
-
function resolveRollingNumberStyle(style) {
|
|
2538
|
-
return {
|
|
2539
|
-
color: style.color ?? DEFAULT_ROLLING_NUMBER_STYLE.color,
|
|
2540
|
-
surface: style.surface ?? DEFAULT_ROLLING_NUMBER_STYLE.surface,
|
|
2541
|
-
divider: style.divider ?? DEFAULT_ROLLING_NUMBER_STYLE.divider,
|
|
2542
|
-
labelColor: style.labelColor ?? DEFAULT_ROLLING_NUMBER_STYLE.labelColor,
|
|
2543
|
-
fontFamily: style.fontFamily ?? DEFAULT_ROLLING_NUMBER_STYLE.fontFamily,
|
|
2544
|
-
variant: style.variant ?? DEFAULT_ROLLING_NUMBER_STYLE.variant,
|
|
2545
|
-
motion: style.motion ?? DEFAULT_ROLLING_NUMBER_STYLE.motion,
|
|
2546
|
-
fontWeight: style.fontWeight ?? DEFAULT_ROLLING_NUMBER_STYLE.fontWeight,
|
|
2547
|
-
fontSize: style.fontSize ?? DEFAULT_ROLLING_NUMBER_STYLE.fontSize
|
|
2548
|
-
};
|
|
2549
|
-
}
|
|
2550
|
-
|
|
2551
|
-
// src/renderScene/artifacts/widget.ts
|
|
2552
|
-
function buildRollingNumber(widget, index) {
|
|
2553
|
-
const x = finite(widget.x, 0);
|
|
2554
|
-
const y = finite(widget.y, 0);
|
|
2555
|
-
const width = Math.max(0, finite(widget.width, 160));
|
|
2556
|
-
const height = Math.max(0, finite(widget.height, 90));
|
|
2557
|
-
const rotation = finite(widget.rotation, 0);
|
|
2558
|
-
return [
|
|
2559
|
-
{
|
|
2560
|
-
id: `widget-${widget.id}`,
|
|
2561
|
-
type: "rolling-number",
|
|
2562
|
-
order: 1e4 + index,
|
|
2563
|
-
bounds: rotatedBounds({ x, y, width, height }, rotation, 2),
|
|
2564
|
-
x,
|
|
2565
|
-
y,
|
|
2566
|
-
width,
|
|
2567
|
-
height,
|
|
2568
|
-
rotation,
|
|
2569
|
-
value: formatRollingNumber(widget.value, widget.digits),
|
|
2570
|
-
digits: widget.digits,
|
|
2571
|
-
duration: Math.max(0, finite(widget.duration, 420)),
|
|
2572
|
-
label: widget.label,
|
|
2573
|
-
widgetStyle: resolveRollingNumberStyle(widget.style)
|
|
2574
|
-
}
|
|
2575
|
-
];
|
|
2576
|
-
}
|
|
2577
|
-
function buildTickScale(widget, index) {
|
|
2578
|
-
const x = finite(widget.x, 0);
|
|
2579
|
-
const y = finite(widget.y, 0);
|
|
2580
|
-
const width = Math.max(0, finite(widget.width, 200));
|
|
2581
|
-
const height = Math.max(0, finite(widget.height, 200));
|
|
2582
|
-
const rotation = finite(widget.rotation, 0);
|
|
2583
|
-
const max = finite(widget.max, 100) || 100;
|
|
2584
|
-
const progress = Math.min(1, Math.max(0, finite(Number(widget.value), 0) / max));
|
|
2585
|
-
const nodes = [
|
|
2586
|
-
{
|
|
2587
|
-
id: `widget-${widget.id}`,
|
|
2588
|
-
type: "shader-surface",
|
|
2589
|
-
order: 1e4 + index,
|
|
2590
|
-
bounds: rotatedBounds({ x, y, width, height }, rotation, 2),
|
|
2591
|
-
x,
|
|
2592
|
-
y,
|
|
2593
|
-
width,
|
|
2594
|
-
height,
|
|
2595
|
-
rotation,
|
|
2596
|
-
shader: { name: widget.id, program: "tickScale", parameters: { ...widget.parameters, progress, max } },
|
|
2597
|
-
mask: "ellipse"
|
|
2598
|
-
}
|
|
2599
|
-
];
|
|
2600
|
-
if (widget.labels) {
|
|
2601
|
-
nodes.push(...buildTickLabels(widget, { x, y, width, height, max, order: 1e4 + index }));
|
|
2602
|
-
}
|
|
2603
|
-
return nodes;
|
|
2604
|
-
}
|
|
2605
|
-
function buildTickLabels(widget, box) {
|
|
2606
|
-
const labels = widget.labels ?? {};
|
|
2607
|
-
const ticks = Math.max(1, finite(Number(widget.parameters.ticks), 48));
|
|
2608
|
-
const major = Math.max(1, finite(Number(widget.parameters.major), 5));
|
|
2609
|
-
const start = finite(Number(widget.parameters.start), 225) * Math.PI / 180;
|
|
2610
|
-
const sweep = finite(Number(widget.parameters.sweep), 270) * Math.PI / 180;
|
|
2611
|
-
const radius = finite(Number(widget.parameters.radius), 0.9) + finite(labels.offset, 0.08);
|
|
2612
|
-
const fontSize = finite(labels.size, 12);
|
|
2613
|
-
const centerX = box.x + box.width / 2;
|
|
2614
|
-
const centerY = box.y + box.height / 2;
|
|
2615
|
-
const count = Math.floor(ticks / major);
|
|
2616
|
-
const nodes = [];
|
|
2617
|
-
for (let step = 0; step <= count; step += 1) {
|
|
2618
|
-
const fraction = step * major / ticks;
|
|
2619
|
-
const angle = start - fraction * sweep;
|
|
2620
|
-
const labelX2 = centerX + Math.cos(angle) * radius * (box.width / 2);
|
|
2621
|
-
const labelY = centerY - Math.sin(angle) * radius * (box.height / 2);
|
|
2622
|
-
const labelBox = { x: labelX2 - 24, y: labelY - fontSize, width: 48, height: fontSize * 2 };
|
|
2623
|
-
nodes.push({
|
|
2624
|
-
id: `widget-${widget.id}-label-${step}`,
|
|
2625
|
-
type: "text",
|
|
2626
|
-
order: box.order + 0.1,
|
|
2627
|
-
bounds: rotatedBounds(labelBox, 0, 2),
|
|
2628
|
-
...labelBox,
|
|
2629
|
-
lines: [String(Math.round(box.max * fraction * 10) / 10)],
|
|
2630
|
-
fontFamily: labels.fontFamily || DEFAULT_FONT,
|
|
2631
|
-
fontSize,
|
|
2632
|
-
fontWeight: labels.weight ?? "normal",
|
|
2633
|
-
color: labels.color || "#8f95c4",
|
|
2634
|
-
align: "center",
|
|
2635
|
-
verticalAlign: "middle",
|
|
2636
|
-
lineHeight: 1.3
|
|
2637
|
-
});
|
|
2638
|
-
}
|
|
2639
|
-
return nodes;
|
|
2640
|
-
}
|
|
2641
|
-
function buildRuler(widget, index) {
|
|
2642
|
-
const x = finite(widget.x, 0);
|
|
2643
|
-
const y = finite(widget.y, 0);
|
|
2644
|
-
const width = Math.max(0, finite(widget.width, 120));
|
|
2645
|
-
const height = Math.max(0, finite(widget.height, 360));
|
|
2646
|
-
const rotation = finite(widget.rotation, 0);
|
|
2647
|
-
const min = finite(widget.min, 0);
|
|
2648
|
-
const max = finite(widget.max, 100);
|
|
2649
|
-
const progress = max === min ? 0 : Math.min(1, Math.max(0, (finite(Number(widget.value), min) - min) / (max - min)));
|
|
2650
|
-
const nodes = [
|
|
2651
|
-
{
|
|
2652
|
-
id: `widget-${widget.id}`,
|
|
2653
|
-
type: "shader-surface",
|
|
2654
|
-
order: 1e4 + index,
|
|
2655
|
-
bounds: rotatedBounds({ x, y, width, height }, rotation, 2),
|
|
2656
|
-
x,
|
|
2657
|
-
y,
|
|
2658
|
-
width,
|
|
2659
|
-
height,
|
|
2660
|
-
rotation,
|
|
2661
|
-
shader: { name: widget.id, program: "ruler", parameters: { ...widget.parameters, progress, min, max } },
|
|
2662
|
-
mask: "rect"
|
|
2663
|
-
}
|
|
2664
|
-
];
|
|
2665
|
-
if (widget.labels) {
|
|
2666
|
-
nodes.push(...buildRulerLabels(widget, { x, y, width, height, min, max, order: 1e4 + index }));
|
|
2667
|
-
}
|
|
2668
|
-
return nodes;
|
|
2669
|
-
}
|
|
2670
|
-
function buildRulerLabels(widget, box) {
|
|
2671
|
-
const labels = widget.labels ?? {};
|
|
2672
|
-
const horizontal = widget.parameters.axis === "horizontal";
|
|
2673
|
-
const ticks = Math.max(1, finite(Number(widget.parameters.ticks), 50));
|
|
2674
|
-
const major = Math.max(1, finite(Number(widget.parameters.major), 5));
|
|
2675
|
-
const inset = finite(Number(widget.parameters.inset), 0.05) > 0 ? finite(Number(widget.parameters.inset), 0.05) : 0.05;
|
|
2676
|
-
const line = finite(Number(widget.parameters.line), 0.7) > 0 ? finite(Number(widget.parameters.line), 0.7) : 0.7;
|
|
2677
|
-
const across = horizontal ? box.height : box.width;
|
|
2678
|
-
const tickLength = (finite(Number(widget.parameters.length), 0.1) > 0 ? finite(Number(widget.parameters.length), 0.1) : 0.1) * across * 1.9;
|
|
2679
|
-
const edge = line * across - 0.12 * across - tickLength - finite(labels.offset, 0.04) * across;
|
|
2680
|
-
const fontSize = finite(labels.size, 12);
|
|
2681
|
-
const count = Math.floor(ticks / major);
|
|
2682
|
-
const nodes = [];
|
|
2683
|
-
for (let step = 0; step <= count; step += 1) {
|
|
2684
|
-
const fraction = step * major / ticks;
|
|
2685
|
-
const along = inset + (1 - 2 * inset) * fraction;
|
|
2686
|
-
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 };
|
|
2687
|
-
nodes.push({
|
|
2688
|
-
id: `widget-${widget.id}-label-${step}`,
|
|
2689
|
-
type: "text",
|
|
2690
|
-
order: box.order + 0.1,
|
|
2691
|
-
bounds: rotatedBounds(labelBox, 0, 2),
|
|
2692
|
-
...labelBox,
|
|
2693
|
-
lines: [String(Math.round((box.min + (box.max - box.min) * fraction) * 10) / 10)],
|
|
2694
|
-
fontFamily: labels.fontFamily || DEFAULT_FONT,
|
|
2695
|
-
fontSize,
|
|
2696
|
-
fontWeight: labels.weight ?? "normal",
|
|
2697
|
-
color: labels.color || "#8f95c4",
|
|
2698
|
-
align: horizontal ? "center" : "right",
|
|
2699
|
-
verticalAlign: "middle",
|
|
2700
|
-
lineHeight: 1.3
|
|
2701
|
-
});
|
|
2702
|
-
}
|
|
2703
|
-
return nodes;
|
|
2704
|
-
}
|
|
2705
|
-
function buildWidgets(widgets) {
|
|
2706
|
-
return widgets.flatMap(
|
|
2707
|
-
(widget, index) => tag(
|
|
2708
|
-
widget.type === "tickScale" ? buildTickScale(widget, index) : widget.type === "ruler" ? buildRuler(widget, index) : buildRollingNumber(widget, index),
|
|
2709
|
-
"widget",
|
|
2710
|
-
widget.id,
|
|
2711
|
-
widget.type,
|
|
2712
|
-
widget.label ?? widget.value,
|
|
2713
|
-
widget.parentFrameId
|
|
2714
|
-
)
|
|
2715
|
-
);
|
|
2716
|
-
}
|
|
2717
|
-
|
|
2718
3371
|
// src/renderScene/charts/decorations/axisLabels.ts
|
|
2719
3372
|
function buildXAxisLabel(chart, layout, order) {
|
|
2720
3373
|
if (!chart.axisX.label) {
|
|
@@ -2869,7 +3522,7 @@ function createLegendSwatch(render2, item) {
|
|
|
2869
3522
|
const { chart, bounds, diagnostics } = render2;
|
|
2870
3523
|
const fallback = CHART_COLORS[item.seriesIndex % CHART_COLORS.length];
|
|
2871
3524
|
const solidOnly = chart.chartType === "line";
|
|
2872
|
-
const
|
|
3525
|
+
const color = solidOnly ? representativeColor(item.series.color, fallback) : item.series.color ?? fallback;
|
|
2873
3526
|
return {
|
|
2874
3527
|
type: "rect",
|
|
2875
3528
|
id: `chart-legend-swatch-${chart.id}-${item.series.id}`,
|
|
@@ -2883,7 +3536,7 @@ function createLegendSwatch(render2, item) {
|
|
|
2883
3536
|
prop: seriesColorProp(item.series.id),
|
|
2884
3537
|
propKind: "color",
|
|
2885
3538
|
propSolidOnly: solidOnly,
|
|
2886
|
-
style: { fill: paint(
|
|
3539
|
+
style: { fill: paint(color, diagnostics, chart.id) }
|
|
2887
3540
|
};
|
|
2888
3541
|
}
|
|
2889
3542
|
function createLegendLabel(render2, item) {
|
|
@@ -3614,7 +4267,7 @@ function createGlassBackdropNodes(context, id, d) {
|
|
|
3614
4267
|
}
|
|
3615
4268
|
|
|
3616
4269
|
// src/renderScene/charts/renderers/bar/glow.ts
|
|
3617
|
-
function createBarGlowNode(context, id, d,
|
|
4270
|
+
function createBarGlowNode(context, id, d, color, glow, bounds = context.bounds) {
|
|
3618
4271
|
const { chart, diagnostics, nextOrder } = context;
|
|
3619
4272
|
return {
|
|
3620
4273
|
type: "path",
|
|
@@ -3623,8 +4276,8 @@ function createBarGlowNode(context, id, d, color2, glow, bounds = context.bounds
|
|
|
3623
4276
|
bounds,
|
|
3624
4277
|
d,
|
|
3625
4278
|
style: {
|
|
3626
|
-
fill: paint(
|
|
3627
|
-
shadow: { color: representativeColor(
|
|
4279
|
+
fill: paint(color, diagnostics, chart.id),
|
|
4280
|
+
shadow: { color: representativeColor(color, "#ffffff"), opacity: 0.9, blur: glow, dx: 0, dy: 0 },
|
|
3628
4281
|
pointerEvents: "none"
|
|
3629
4282
|
}
|
|
3630
4283
|
};
|
|
@@ -3644,7 +4297,7 @@ function labelTop(placement, frame, height) {
|
|
|
3644
4297
|
}
|
|
3645
4298
|
return placement === "inside" ? frame.y + BAR_LABEL.gap : frame.y + frame.height / 2 - height / 2;
|
|
3646
4299
|
}
|
|
3647
|
-
function createPillNode(context, id, box,
|
|
4300
|
+
function createPillNode(context, id, box, color) {
|
|
3648
4301
|
const { chart, bounds, diagnostics, nextOrder } = context;
|
|
3649
4302
|
const config = chart.config;
|
|
3650
4303
|
return {
|
|
@@ -3655,13 +4308,13 @@ function createPillNode(context, id, box, color2) {
|
|
|
3655
4308
|
d: pillPath(box.left, box.top, box.width, box.height),
|
|
3656
4309
|
style: {
|
|
3657
4310
|
fill: config?.barLabelPillColor ? paint(config.barLabelPillColor, diagnostics, chart.id) : { kind: "none" },
|
|
3658
|
-
stroke: paint(config?.barLabelBorderColor ??
|
|
4311
|
+
stroke: paint(config?.barLabelBorderColor ?? color, diagnostics, chart.id),
|
|
3659
4312
|
strokeWidth: finite(config?.barLabelBorderWidth, 1),
|
|
3660
4313
|
pointerEvents: "none"
|
|
3661
4314
|
}
|
|
3662
4315
|
};
|
|
3663
4316
|
}
|
|
3664
|
-
function createTextNode(context, id, box, text, placement, fontSize,
|
|
4317
|
+
function createTextNode(context, id, box, text, placement, fontSize, color) {
|
|
3665
4318
|
const { chart, bounds, nextOrder } = context;
|
|
3666
4319
|
const config = chart.config;
|
|
3667
4320
|
return {
|
|
@@ -3675,7 +4328,7 @@ function createTextNode(context, id, box, text, placement, fontSize, color2) {
|
|
|
3675
4328
|
align: "center"
|
|
3676
4329
|
}),
|
|
3677
4330
|
mark: `bar-label|${placement}|${config?.barLabelFormat ?? ""}`,
|
|
3678
|
-
color
|
|
4331
|
+
color,
|
|
3679
4332
|
fontSize,
|
|
3680
4333
|
fontFamily: config?.barLabelFontFamily ?? chart.fontFamily ?? "Inter, sans-serif",
|
|
3681
4334
|
fontWeight: config?.barLabelFontWeight ?? "normal"
|
|
@@ -3733,12 +4386,12 @@ function createBarLabelNodes(context, target) {
|
|
|
3733
4386
|
left: target.frame.x + target.frame.width / 2 - size.width / 2,
|
|
3734
4387
|
top: labelTop(placement, target.frame, size.height)
|
|
3735
4388
|
};
|
|
3736
|
-
const
|
|
4389
|
+
const color = config?.barLabelColor ?? chart.textColor ?? "#0f172a";
|
|
3737
4390
|
const nodes = [];
|
|
3738
4391
|
if (pill) {
|
|
3739
|
-
nodes.push(createPillNode(context, target.id, box,
|
|
4392
|
+
nodes.push(createPillNode(context, target.id, box, color));
|
|
3740
4393
|
}
|
|
3741
|
-
nodes.push(createTextNode(context, target.id, box, text, placement, fontSize,
|
|
4394
|
+
nodes.push(createTextNode(context, target.id, box, text, placement, fontSize, color));
|
|
3742
4395
|
return nodes;
|
|
3743
4396
|
}
|
|
3744
4397
|
|
|
@@ -4474,12 +5127,12 @@ function renderBoxplotSeries(context, layout, series, seriesIndex) {
|
|
|
4474
5127
|
return [];
|
|
4475
5128
|
}
|
|
4476
5129
|
const geometry = createBoxplotGeometry(context, layout, seriesIndex, stats);
|
|
4477
|
-
const
|
|
5130
|
+
const color = series.color ?? CHART_COLORS[seriesIndex % CHART_COLORS.length];
|
|
4478
5131
|
const mark = {
|
|
4479
5132
|
id: `${context.chart.id}-${series.id}`,
|
|
4480
5133
|
series,
|
|
4481
5134
|
seriesIndex,
|
|
4482
|
-
color
|
|
5135
|
+
color,
|
|
4483
5136
|
geometry
|
|
4484
5137
|
};
|
|
4485
5138
|
const nodes = renderBoxAndWhiskers(context, layout, mark);
|
|
@@ -4541,9 +5194,9 @@ function customPointPosition(context, value) {
|
|
|
4541
5194
|
};
|
|
4542
5195
|
}
|
|
4543
5196
|
function customSeriesStyle(context, series, seriesIndex) {
|
|
4544
|
-
const
|
|
5197
|
+
const color = series.color ?? CHART_COLORS[seriesIndex % CHART_COLORS.length];
|
|
4545
5198
|
return {
|
|
4546
|
-
fill: paint(
|
|
5199
|
+
fill: paint(color, context.diagnostics, context.chart.id),
|
|
4547
5200
|
stroke: series.stroke ? { kind: "solid", color: series.stroke } : void 0,
|
|
4548
5201
|
strokeWidth: series.stroke ? finite(series.strokeWidth, 1) : void 0
|
|
4549
5202
|
};
|
|
@@ -4642,7 +5295,7 @@ function connectorDash(text) {
|
|
|
4642
5295
|
const parts = (text ?? "").split(/[ ,]+/).map(Number).filter((part) => Number.isFinite(part) && part > 0);
|
|
4643
5296
|
return parts.length > 0 ? parts : void 0;
|
|
4644
5297
|
}
|
|
4645
|
-
function createConnectorLine(context, index, from, to,
|
|
5298
|
+
function createConnectorLine(context, index, from, to, color) {
|
|
4646
5299
|
const { chart } = context;
|
|
4647
5300
|
return {
|
|
4648
5301
|
type: "path",
|
|
@@ -4652,7 +5305,7 @@ function createConnectorLine(context, index, from, to, color2) {
|
|
|
4652
5305
|
d: `M ${from.x} ${from.y} L ${to.x} ${to.y}`,
|
|
4653
5306
|
style: {
|
|
4654
5307
|
fill: { kind: "none" },
|
|
4655
|
-
stroke: { kind: "solid", color
|
|
5308
|
+
stroke: { kind: "solid", color },
|
|
4656
5309
|
strokeWidth: finite(chart.config?.customConnectorWidth, 2),
|
|
4657
5310
|
opacity: chart.config?.customConnectorOpacity,
|
|
4658
5311
|
dash: connectorDash(chart.config?.customConnectorDash)
|
|
@@ -4956,7 +5609,7 @@ function createFieldCell(context, grid, row, column) {
|
|
|
4956
5609
|
const { chart, plot, bounds, nextOrder } = context;
|
|
4957
5610
|
const centerX = plot.x + plot.width * (column / (grid.columns - 1));
|
|
4958
5611
|
const centerY = plot.y + plot.height * (row / (grid.rows - 1));
|
|
4959
|
-
const
|
|
5612
|
+
const color = colorAtRamp(chart.config?.scale, grid.values[row * grid.columns + column]);
|
|
4960
5613
|
return {
|
|
4961
5614
|
type: "rect",
|
|
4962
5615
|
id: `chart-field-cell-${chart.id}-${row}-${column}`,
|
|
@@ -4966,7 +5619,7 @@ function createFieldCell(context, grid, row, column) {
|
|
|
4966
5619
|
y: centerY - grid.cellHeight / 2,
|
|
4967
5620
|
width: grid.cellWidth,
|
|
4968
5621
|
height: grid.cellHeight,
|
|
4969
|
-
style: { fill: { kind: "solid", color
|
|
5622
|
+
style: { fill: { kind: "solid", color }, clip: fieldSurfaceClip(chart, plot) }
|
|
4970
5623
|
};
|
|
4971
5624
|
}
|
|
4972
5625
|
function renderIsolines(context, grid) {
|
|
@@ -5020,14 +5673,14 @@ function createIsoline(context, grid, threshold, thresholdIndex) {
|
|
|
5020
5673
|
function renderVectorField(context, seriesList) {
|
|
5021
5674
|
const nodes = [];
|
|
5022
5675
|
seriesList.forEach((series, seriesIndex) => {
|
|
5023
|
-
const
|
|
5676
|
+
const color = series.color ?? CHART_COLORS[seriesIndex % CHART_COLORS.length];
|
|
5024
5677
|
series.values.forEach((vector, vectorIndex) => {
|
|
5025
|
-
nodes.push(createVectorNode(context, series.id, vector, vectorIndex,
|
|
5678
|
+
nodes.push(createVectorNode(context, series.id, vector, vectorIndex, color));
|
|
5026
5679
|
});
|
|
5027
5680
|
});
|
|
5028
5681
|
return nodes;
|
|
5029
5682
|
}
|
|
5030
|
-
function createVectorNode(context, seriesId, vector, vectorIndex,
|
|
5683
|
+
function createVectorNode(context, seriesId, vector, vectorIndex, color) {
|
|
5031
5684
|
const { chart, plot, bounds, diagnostics, nextOrder } = context;
|
|
5032
5685
|
const [x, y, angle, magnitude] = vector;
|
|
5033
5686
|
const startX = plot.x + mapChartValue(x, chart.axisX, plot.width);
|
|
@@ -5043,7 +5696,7 @@ function createVectorNode(context, seriesId, vector, vectorIndex, color2) {
|
|
|
5043
5696
|
markerEnd: "filled_arrow",
|
|
5044
5697
|
style: {
|
|
5045
5698
|
fill: { kind: "none" },
|
|
5046
|
-
stroke: paint(
|
|
5699
|
+
stroke: paint(color, diagnostics, chart.id),
|
|
5047
5700
|
strokeWidth: 2
|
|
5048
5701
|
}
|
|
5049
5702
|
};
|
|
@@ -5697,11 +6350,11 @@ function renderHexbin(context) {
|
|
|
5697
6350
|
}));
|
|
5698
6351
|
const bins = computeHexBins(pixelPoints2, hexRadius);
|
|
5699
6352
|
const maxCount = Math.max(1, ...bins.map((bin) => bin.count));
|
|
5700
|
-
const
|
|
6353
|
+
const color = series.color ?? CHART_COLORS[seriesIndex % CHART_COLORS.length];
|
|
5701
6354
|
const ramp = config?.scale;
|
|
5702
6355
|
bins.forEach((bin, i) => {
|
|
5703
6356
|
const share = bin.count / maxCount;
|
|
5704
|
-
const fill2 = ramp ? colorAtRamp(ramp, share) :
|
|
6357
|
+
const fill2 = ramp ? colorAtRamp(ramp, share) : color;
|
|
5705
6358
|
nodes.push({
|
|
5706
6359
|
type: "path",
|
|
5707
6360
|
id: `chart-hexbin-${chart.id}-${series.id}-${i}`,
|
|
@@ -5738,7 +6391,7 @@ function pixelPoints(context, pairs) {
|
|
|
5738
6391
|
}
|
|
5739
6392
|
|
|
5740
6393
|
// src/renderScene/charts/renderers/line/area.ts
|
|
5741
|
-
function createLineAreaFill(context, series, points,
|
|
6394
|
+
function createLineAreaFill(context, series, points, color, tension, areaOpacity) {
|
|
5742
6395
|
const { chart, plot, nextOrder } = context;
|
|
5743
6396
|
const baselineY = plot.y + plot.height;
|
|
5744
6397
|
const first = points[0];
|
|
@@ -5765,8 +6418,8 @@ function createLineAreaFill(context, series, points, color2, tension, areaOpacit
|
|
|
5765
6418
|
kind: "linear-gradient",
|
|
5766
6419
|
angle: 90,
|
|
5767
6420
|
stops: [
|
|
5768
|
-
{ offset: 0, color: colorWithAlpha(
|
|
5769
|
-
{ offset: 100, color: colorWithAlpha(
|
|
6421
|
+
{ offset: 0, color: colorWithAlpha(color, areaOpacity) },
|
|
6422
|
+
{ offset: 100, color: colorWithAlpha(color, 0) }
|
|
5770
6423
|
]
|
|
5771
6424
|
},
|
|
5772
6425
|
stroke: { kind: "none" },
|
|
@@ -5816,7 +6469,7 @@ function dotNode(context, mark) {
|
|
|
5816
6469
|
}
|
|
5817
6470
|
};
|
|
5818
6471
|
}
|
|
5819
|
-
function
|
|
6472
|
+
function labelNode3(context, mark, value) {
|
|
5820
6473
|
const { chart, bounds, nextOrder } = context;
|
|
5821
6474
|
const config = chart.config;
|
|
5822
6475
|
const fontSize = Math.max(9, chart.fontSize ?? 12);
|
|
@@ -5841,7 +6494,7 @@ function labelNode(context, mark, value) {
|
|
|
5841
6494
|
fontWeight: "bold"
|
|
5842
6495
|
};
|
|
5843
6496
|
}
|
|
5844
|
-
function renderLineHighlights(context, series,
|
|
6497
|
+
function renderLineHighlights(context, series, color) {
|
|
5845
6498
|
const { chart } = context;
|
|
5846
6499
|
const config = chart.config;
|
|
5847
6500
|
const wanted = config?.highlightPoints;
|
|
@@ -5862,28 +6515,28 @@ function renderLineHighlights(context, series, color2) {
|
|
|
5862
6515
|
point,
|
|
5863
6516
|
index,
|
|
5864
6517
|
radius: config?.highlightSize ?? 6,
|
|
5865
|
-
color: config?.highlightColor ??
|
|
6518
|
+
color: config?.highlightColor ?? color
|
|
5866
6519
|
};
|
|
5867
6520
|
if (config?.highlightGuide) {
|
|
5868
6521
|
nodes.push(guideNode(context, mark));
|
|
5869
6522
|
}
|
|
5870
6523
|
nodes.push(dotNode(context, mark));
|
|
5871
6524
|
if (config?.highlightLabels) {
|
|
5872
|
-
nodes.push(
|
|
6525
|
+
nodes.push(labelNode3(context, mark, pairs[index][1]));
|
|
5873
6526
|
}
|
|
5874
6527
|
}
|
|
5875
6528
|
return nodes;
|
|
5876
6529
|
}
|
|
5877
6530
|
|
|
5878
6531
|
// src/renderScene/charts/renderers/line/marks.ts
|
|
5879
|
-
function createLinePointMarks(series, pairs, points,
|
|
6532
|
+
function createLinePointMarks(series, pairs, points, color) {
|
|
5880
6533
|
return points.map((position, valueIndex) => ({
|
|
5881
6534
|
seriesId: series.id,
|
|
5882
6535
|
valueIndex,
|
|
5883
6536
|
value: pairs[valueIndex][1],
|
|
5884
6537
|
error: series.error?.[valueIndex],
|
|
5885
6538
|
position,
|
|
5886
|
-
color
|
|
6539
|
+
color
|
|
5887
6540
|
}));
|
|
5888
6541
|
}
|
|
5889
6542
|
function renderLineMarks(context, marks) {
|
|
@@ -5944,7 +6597,7 @@ function createLinePoint(context, mark) {
|
|
|
5944
6597
|
}
|
|
5945
6598
|
|
|
5946
6599
|
// src/renderScene/charts/renderers/line/path.ts
|
|
5947
|
-
function createLinePath(context, series, points,
|
|
6600
|
+
function createLinePath(context, series, points, color, tension) {
|
|
5948
6601
|
const { chart, plot, bounds, diagnostics, nextOrder } = context;
|
|
5949
6602
|
const config = chart.config;
|
|
5950
6603
|
const source = series.color;
|
|
@@ -5959,12 +6612,12 @@ function createLinePath(context, series, points, color2, tension) {
|
|
|
5959
6612
|
d: linePathData(points, tension),
|
|
5960
6613
|
style: {
|
|
5961
6614
|
fill: { kind: "none" },
|
|
5962
|
-
stroke: paint(gradient ??
|
|
6615
|
+
stroke: paint(gradient ?? color, diagnostics, chart.id),
|
|
5963
6616
|
strokeWidth: series.strokeWidth ?? config?.lineWidth ?? 2,
|
|
5964
6617
|
dash: series.dash,
|
|
5965
6618
|
lineCap: config?.lineWidth === void 0 ? void 0 : "round",
|
|
5966
6619
|
lineJoin: "round",
|
|
5967
|
-
shadow: glow ? { color
|
|
6620
|
+
shadow: glow ? { color, opacity: 0.9, blur: glow, dx: 0, dy: 0 } : resolveChartShadow(chart.shadowStyle)
|
|
5968
6621
|
}
|
|
5969
6622
|
};
|
|
5970
6623
|
}
|
|
@@ -5978,23 +6631,23 @@ function renderLineSeriesArea(context, series, seriesIndex) {
|
|
|
5978
6631
|
if (areaOpacity === void 0 || areaOpacity <= 0) {
|
|
5979
6632
|
return [];
|
|
5980
6633
|
}
|
|
5981
|
-
const
|
|
6634
|
+
const color = seriesColor(series, seriesIndex);
|
|
5982
6635
|
const tension = context.chart.config?.lineTension ?? 0;
|
|
5983
6636
|
const points = pixelPoints(context, seriesValuePairs(context.chart, series));
|
|
5984
|
-
return points.length > 1 ? [createLineAreaFill(context, series, points,
|
|
6637
|
+
return points.length > 1 ? [createLineAreaFill(context, series, points, color, tension, areaOpacity)] : [];
|
|
5985
6638
|
}
|
|
5986
6639
|
function renderLineSeries(context, series, seriesIndex) {
|
|
5987
|
-
const
|
|
6640
|
+
const color = seriesColor(series, seriesIndex);
|
|
5988
6641
|
const tension = context.chart.config?.lineTension ?? 0;
|
|
5989
6642
|
const pairs = seriesValuePairs(context.chart, series);
|
|
5990
6643
|
const points = pixelPoints(context, pairs);
|
|
5991
6644
|
const nodes = [];
|
|
5992
6645
|
if (points.length) {
|
|
5993
|
-
nodes.push(createLinePath(context, series, points,
|
|
6646
|
+
nodes.push(createLinePath(context, series, points, color, tension));
|
|
5994
6647
|
}
|
|
5995
|
-
const marks = createLinePointMarks(series, pairs, points,
|
|
6648
|
+
const marks = createLinePointMarks(series, pairs, points, color);
|
|
5996
6649
|
nodes.push(...renderLineMarks(context, marks));
|
|
5997
|
-
nodes.push(...renderLineHighlights(context, series,
|
|
6650
|
+
nodes.push(...renderLineHighlights(context, series, color));
|
|
5998
6651
|
return nodes;
|
|
5999
6652
|
}
|
|
6000
6653
|
|
|
@@ -6203,13 +6856,13 @@ function calculateColumnSegments(seriesList, layout, columnIndex) {
|
|
|
6203
6856
|
const height = (column.total > 0 ? value / column.total : 0) * column.height;
|
|
6204
6857
|
const y = column.y + cumulativeHeight;
|
|
6205
6858
|
cumulativeHeight += height;
|
|
6206
|
-
const
|
|
6859
|
+
const color = series.color ?? CHART_COLORS[seriesIndex % CHART_COLORS.length];
|
|
6207
6860
|
segments.push({
|
|
6208
6861
|
columnIndex,
|
|
6209
6862
|
seriesId: series.id,
|
|
6210
6863
|
seriesLabel: series.label,
|
|
6211
6864
|
value,
|
|
6212
|
-
color
|
|
6865
|
+
color,
|
|
6213
6866
|
isTop: seriesIndex === 0,
|
|
6214
6867
|
frame: {
|
|
6215
6868
|
x: column.x,
|
|
@@ -6566,7 +7219,7 @@ function clampedCorner(layout, outerRadius, angles) {
|
|
|
6566
7219
|
function wedgeNodes(context, layout, series, angles, outerRadius, value, rawColor) {
|
|
6567
7220
|
const { chart, bounds, diagnostics, nextOrder } = context;
|
|
6568
7221
|
const { centerX, centerY, innerRadius, maxRadius, gapPx } = layout;
|
|
6569
|
-
const
|
|
7222
|
+
const color = paint(rawColor, diagnostics, chart.id);
|
|
6570
7223
|
const shadow = resolveChartShadow(chart.shadowStyle);
|
|
6571
7224
|
const trackPath = createPieSlicePath(
|
|
6572
7225
|
{ centerX, centerY, outerRadius: maxRadius, innerRadius },
|
|
@@ -6598,7 +7251,7 @@ function wedgeNodes(context, layout, series, angles, outerRadius, value, rawColo
|
|
|
6598
7251
|
order: nextOrder(),
|
|
6599
7252
|
bounds,
|
|
6600
7253
|
d: wedgePath,
|
|
6601
|
-
style: { fill:
|
|
7254
|
+
style: { fill: color, shadow, clip: { type: "path", d: trackPath } }
|
|
6602
7255
|
} : void 0;
|
|
6603
7256
|
const wedge = {
|
|
6604
7257
|
type: "path",
|
|
@@ -6616,7 +7269,7 @@ function wedgeNodes(context, layout, series, angles, outerRadius, value, rawColo
|
|
|
6616
7269
|
pieValue: value
|
|
6617
7270
|
},
|
|
6618
7271
|
prop: seriesValueProp(series.id, 0),
|
|
6619
|
-
style: { fill:
|
|
7272
|
+
style: { fill: color, innerShadow: shadow, ...wedgeStroke(context) }
|
|
6620
7273
|
};
|
|
6621
7274
|
return shadowCaster ? [track, shadowCaster, wedge] : [track, wedge];
|
|
6622
7275
|
}
|
|
@@ -6711,11 +7364,11 @@ function labelPlacement2(context, geometry, angles, series, fillColor) {
|
|
|
6711
7364
|
const outside = hasManualOffset || !fitsInline;
|
|
6712
7365
|
const tickStart = pieArcPoint(geometry, mid, geometry.outerRadius + LEADER_INSET);
|
|
6713
7366
|
const point = outside ? hasManualOffset ? addOffset(pieArcPoint(geometry, mid, geometry.outerRadius), labelOffsetX, labelOffsetY) : pieArcPoint(geometry, mid, geometry.outerRadius + OUTSIDE_GAP) : pieArcPoint(geometry, mid, geometry.innerRadius + ringThickness * LABEL_RADIUS_FRACTION);
|
|
6714
|
-
const
|
|
7367
|
+
const color = outside ? outsideLabels && context.chart.textColor ? context.chart.textColor : sameHueTint(representativeColor(fillColor, OUTSIDE_FALLBACK_COLOR), OUTSIDE_TINT_LIGHTNESS) ?? OUTSIDE_FALLBACK_COLOR : sameHueContrastColor(
|
|
6715
7368
|
representativeColor(fillColor, "#0f172a"),
|
|
6716
7369
|
contrastTextColor(representativeColor(fillColor, "#0f172a"))
|
|
6717
7370
|
);
|
|
6718
|
-
return { point, color
|
|
7371
|
+
return { point, color, outside, mid, tickStart };
|
|
6719
7372
|
}
|
|
6720
7373
|
function createWedgeLabel(context, geometry, angles, series, value, fillColor) {
|
|
6721
7374
|
const placement = labelPlacement2(context, geometry, angles, series, fillColor);
|
|
@@ -6723,7 +7376,7 @@ function createWedgeLabel(context, geometry, angles, series, value, fillColor) {
|
|
|
6723
7376
|
return [];
|
|
6724
7377
|
}
|
|
6725
7378
|
const { chart, bounds, nextOrder } = context;
|
|
6726
|
-
const { point, color
|
|
7379
|
+
const { point, color, outside, mid, tickStart } = placement;
|
|
6727
7380
|
const { nameSize, valueSize } = labelSizes(chart);
|
|
6728
7381
|
const lineHeight = Math.max(nameSize, valueSize) * 1.2;
|
|
6729
7382
|
const tickEnd = outside ? clipSegmentToRect(tickStart, point, LABEL_WIDTH / 2, lineHeight) : tickStart;
|
|
@@ -6734,7 +7387,7 @@ function createWedgeLabel(context, geometry, angles, series, value, fillColor) {
|
|
|
6734
7387
|
bounds,
|
|
6735
7388
|
d: `M ${tickStart.x} ${tickStart.y} L ${tickEnd.x} ${tickEnd.y}`,
|
|
6736
7389
|
detail: { of: "chartSeries", series: series.id, mark: "polar-area-label-tick" },
|
|
6737
|
-
style: outside ? { stroke: { kind: "solid", color
|
|
7390
|
+
style: outside ? { stroke: { kind: "solid", color }, strokeWidth: 1.5 } : { stroke: { kind: "none" } }
|
|
6738
7391
|
};
|
|
6739
7392
|
const detail = {
|
|
6740
7393
|
of: "chartSeries",
|
|
@@ -6752,7 +7405,7 @@ function createWedgeLabel(context, geometry, angles, series, value, fillColor) {
|
|
|
6752
7405
|
align: "center",
|
|
6753
7406
|
verticalAlign: "middle",
|
|
6754
7407
|
lineHeight: 1.2,
|
|
6755
|
-
color
|
|
7408
|
+
color
|
|
6756
7409
|
};
|
|
6757
7410
|
const valueFirst = chart.config?.polarValueFirst ?? false;
|
|
6758
7411
|
const nameHeight = nameSize * 1.2;
|
|
@@ -6953,13 +7606,13 @@ function renderRadarSeries(context, geometry) {
|
|
|
6953
7606
|
return nodes;
|
|
6954
7607
|
}
|
|
6955
7608
|
function renderSeries(context, geometry, series, seriesIndex) {
|
|
6956
|
-
const
|
|
7609
|
+
const color = series.color ?? CHART_COLORS[seriesIndex % CHART_COLORS.length];
|
|
6957
7610
|
const points = seriesPoints(series, context, geometry);
|
|
6958
7611
|
const path = radarSeriesPath(points, geometry.circular, geometry.tension);
|
|
6959
7612
|
return [
|
|
6960
|
-
createSeriesFill(context, geometry, series, path,
|
|
6961
|
-
...geometry.strokeWidth > 0 ? [createSeriesStroke(context, geometry, series, path,
|
|
6962
|
-
...geometry.pointSize > 0 ? createSeriesPoints(context, geometry, series, points,
|
|
7613
|
+
createSeriesFill(context, geometry, series, path, color),
|
|
7614
|
+
...geometry.strokeWidth > 0 ? [createSeriesStroke(context, geometry, series, path, color)] : [],
|
|
7615
|
+
...geometry.pointSize > 0 ? createSeriesPoints(context, geometry, series, points, color) : []
|
|
6963
7616
|
];
|
|
6964
7617
|
}
|
|
6965
7618
|
function seriesPoints(series, context, geometry) {
|
|
@@ -6968,7 +7621,7 @@ function seriesPoints(series, context, geometry) {
|
|
|
6968
7621
|
(_, categoryIndex) => geometry.pointAt(geometry.radiusForValue(values[categoryIndex] ?? context.chart.axisY.min), categoryIndex)
|
|
6969
7622
|
);
|
|
6970
7623
|
}
|
|
6971
|
-
function createSeriesFill(context, geometry, series, path,
|
|
7624
|
+
function createSeriesFill(context, geometry, series, path, color) {
|
|
6972
7625
|
const { chart, bounds, diagnostics, nextOrder } = context;
|
|
6973
7626
|
return {
|
|
6974
7627
|
type: "path",
|
|
@@ -6978,13 +7631,13 @@ function createSeriesFill(context, geometry, series, path, color2) {
|
|
|
6978
7631
|
d: path,
|
|
6979
7632
|
detail: { of: "chartSeries", series: series.id },
|
|
6980
7633
|
style: {
|
|
6981
|
-
fill: paint(
|
|
7634
|
+
fill: paint(color, diagnostics, chart.id),
|
|
6982
7635
|
stroke: { kind: "none" },
|
|
6983
7636
|
opacity: Math.max(0, Math.min(1, series.opacity ?? geometry.areaOpacity))
|
|
6984
7637
|
}
|
|
6985
7638
|
};
|
|
6986
7639
|
}
|
|
6987
|
-
function createSeriesStroke(context, geometry, series, path,
|
|
7640
|
+
function createSeriesStroke(context, geometry, series, path, color) {
|
|
6988
7641
|
const { chart, bounds, diagnostics, nextOrder } = context;
|
|
6989
7642
|
return {
|
|
6990
7643
|
type: "path",
|
|
@@ -6995,14 +7648,14 @@ function createSeriesStroke(context, geometry, series, path, color2) {
|
|
|
6995
7648
|
detail: { of: "chartSeries", series: series.id },
|
|
6996
7649
|
style: {
|
|
6997
7650
|
fill: { kind: "none" },
|
|
6998
|
-
stroke: paint(
|
|
7651
|
+
stroke: paint(color, diagnostics, chart.id),
|
|
6999
7652
|
strokeWidth: geometry.strokeWidth,
|
|
7000
7653
|
lineJoin: "round",
|
|
7001
7654
|
shadow: resolveChartShadow(chart.shadowStyle)
|
|
7002
7655
|
}
|
|
7003
7656
|
};
|
|
7004
7657
|
}
|
|
7005
|
-
function createSeriesPoints(context, geometry, series, points,
|
|
7658
|
+
function createSeriesPoints(context, geometry, series, points, color) {
|
|
7006
7659
|
const { chart, bounds, diagnostics, nextOrder } = context;
|
|
7007
7660
|
return points.map((point, pointIndex) => ({
|
|
7008
7661
|
type: "ellipse",
|
|
@@ -7015,7 +7668,7 @@ function createSeriesPoints(context, geometry, series, points, color2) {
|
|
|
7015
7668
|
ry: geometry.pointSize,
|
|
7016
7669
|
detail: { of: "chartValue", series: series.id, valueIndex: pointIndex, mark: "radar-vertex" },
|
|
7017
7670
|
prop: seriesValueProp(series.id, pointIndex),
|
|
7018
|
-
style: { fill: paint(
|
|
7671
|
+
style: { fill: paint(color, diagnostics, chart.id) }
|
|
7019
7672
|
}));
|
|
7020
7673
|
}
|
|
7021
7674
|
|
|
@@ -7084,7 +7737,7 @@ function layoutOf2(context) {
|
|
|
7084
7737
|
cap: chart.config?.ringCap ?? "round"
|
|
7085
7738
|
};
|
|
7086
7739
|
}
|
|
7087
|
-
function ringEndShadows(context, layout, series, radius, sweep,
|
|
7740
|
+
function ringEndShadows(context, layout, series, radius, sweep, color) {
|
|
7088
7741
|
const { chart, bounds, nextOrder } = context;
|
|
7089
7742
|
const { centerX, centerY, ringThickness, start } = layout;
|
|
7090
7743
|
const shadow = resolveChartShadow(chart.shadowStyle);
|
|
@@ -7106,7 +7759,7 @@ function ringEndShadows(context, layout, series, radius, sweep, color2) {
|
|
|
7106
7759
|
d: arcSegmentPath(centerX, centerY, radius, from, to),
|
|
7107
7760
|
style: {
|
|
7108
7761
|
fill: { kind: "none" },
|
|
7109
|
-
stroke:
|
|
7762
|
+
stroke: color,
|
|
7110
7763
|
strokeWidth: ringThickness,
|
|
7111
7764
|
lineCap: layout.cap,
|
|
7112
7765
|
shadow: clampedShadow,
|
|
@@ -7125,12 +7778,12 @@ function ringNodes2(context, layout, series, index) {
|
|
|
7125
7778
|
if (radius <= ringThickness / 2) {
|
|
7126
7779
|
return [];
|
|
7127
7780
|
}
|
|
7128
|
-
const
|
|
7781
|
+
const color = paint(series.color ?? CHART_COLORS[index % CHART_COLORS.length], diagnostics, chart.id);
|
|
7129
7782
|
const value = Math.max(0, finite(series.values[0], 0));
|
|
7130
7783
|
const fraction = range > 0 ? Math.min(1, Math.max(0, (value - axisMin) / range)) : 0;
|
|
7131
7784
|
const trackStyle = {
|
|
7132
7785
|
fill: { kind: "none" },
|
|
7133
|
-
stroke:
|
|
7786
|
+
stroke: color,
|
|
7134
7787
|
strokeWidth: ringThickness,
|
|
7135
7788
|
opacity: trackOpacity
|
|
7136
7789
|
};
|
|
@@ -7156,7 +7809,7 @@ function ringNodes2(context, layout, series, index) {
|
|
|
7156
7809
|
return [track];
|
|
7157
7810
|
}
|
|
7158
7811
|
const sweep = fraction * total;
|
|
7159
|
-
const casters = ringEndShadows(context, layout, series, radius, sweep,
|
|
7812
|
+
const casters = ringEndShadows(context, layout, series, radius, sweep, color);
|
|
7160
7813
|
const progress = {
|
|
7161
7814
|
type: "path",
|
|
7162
7815
|
id: `chart-radial-bar-ring-${chart.id}-${series.id}`,
|
|
@@ -7165,7 +7818,7 @@ function ringNodes2(context, layout, series, index) {
|
|
|
7165
7818
|
d: ringProgressPath(centerX, centerY, radius, sweep, start),
|
|
7166
7819
|
detail: { of: "chartValue", series: series.id, valueIndex: 0, mark: "radial-bar-ring" },
|
|
7167
7820
|
prop: seriesValueProp(series.id, 0),
|
|
7168
|
-
style: { fill: { kind: "none" }, stroke:
|
|
7821
|
+
style: { fill: { kind: "none" }, stroke: color, strokeWidth: ringThickness, lineCap: cap }
|
|
7169
7822
|
};
|
|
7170
7823
|
return [track, ...casters, progress];
|
|
7171
7824
|
}
|
|
@@ -7340,8 +7993,8 @@ function createNodeLabel(context, data, node) {
|
|
|
7340
7993
|
node.color,
|
|
7341
7994
|
isLightColor(fallback) ? OUTSIDE_LABEL_LIGHTNESS_ON_DARK_BG : OUTSIDE_LABEL_LIGHTNESS_ON_LIGHT_BG
|
|
7342
7995
|
) ?? fallback;
|
|
7343
|
-
const
|
|
7344
|
-
return { ...label, color
|
|
7996
|
+
const color = chart.config?.labelColor ?? defaultColor;
|
|
7997
|
+
return { ...label, color, detail: { of: "chartSeries", series: node.id, mark: "sankey-node-label" } };
|
|
7345
7998
|
}
|
|
7346
7999
|
function createOutsideLabel(context, data, node) {
|
|
7347
8000
|
const { chart, bounds, nextOrder } = context;
|
|
@@ -7471,15 +8124,15 @@ function renderScatter(context) {
|
|
|
7471
8124
|
const nodes = [];
|
|
7472
8125
|
const shadow = resolveChartShadow(context.chart.shadowStyle);
|
|
7473
8126
|
context.chart.series.forEach((series, seriesIndex) => {
|
|
7474
|
-
const
|
|
8127
|
+
const color = series.color ?? CHART_COLORS[seriesIndex % CHART_COLORS.length];
|
|
7475
8128
|
const points = pixelPoints(context, seriesValuePairs(context.chart, series));
|
|
7476
8129
|
points.forEach((point, pointIndex) => {
|
|
7477
|
-
nodes.push(createScatterPoint(context, series, point, pointIndex,
|
|
8130
|
+
nodes.push(createScatterPoint(context, series, point, pointIndex, color, shadow));
|
|
7478
8131
|
});
|
|
7479
8132
|
});
|
|
7480
8133
|
return nodes;
|
|
7481
8134
|
}
|
|
7482
|
-
function createScatterPoint(context, series, point, pointIndex,
|
|
8135
|
+
function createScatterPoint(context, series, point, pointIndex, color, shadow) {
|
|
7483
8136
|
const { chart, bounds, diagnostics, nextOrder } = context;
|
|
7484
8137
|
const config = chart.config;
|
|
7485
8138
|
const radius = config?.pointSize ?? DEFAULT_POINT_SIZE;
|
|
@@ -7495,8 +8148,8 @@ function createScatterPoint(context, series, point, pointIndex, color2, shadow)
|
|
|
7495
8148
|
ry: radius,
|
|
7496
8149
|
detail: { of: "chartValue", series: series.id, valueIndex: pointIndex },
|
|
7497
8150
|
style: {
|
|
7498
|
-
fill: paint(
|
|
7499
|
-
stroke: strokeWidth > 0 ? paint(config?.pointStrokeColor ??
|
|
8151
|
+
fill: paint(color, diagnostics, chart.id),
|
|
8152
|
+
stroke: strokeWidth > 0 ? paint(config?.pointStrokeColor ?? color, diagnostics, chart.id) : void 0,
|
|
7500
8153
|
strokeWidth: strokeWidth > 0 ? strokeWidth : void 0,
|
|
7501
8154
|
opacity: config?.pointOpacity,
|
|
7502
8155
|
shadow
|
|
@@ -7772,15 +8425,15 @@ function renderTreemapHeader(context, layout, header, index) {
|
|
|
7772
8425
|
return [background, label];
|
|
7773
8426
|
}
|
|
7774
8427
|
function renderTile(context, layout, tile, nextTile) {
|
|
7775
|
-
const
|
|
8428
|
+
const color = treemapLeafColor(tile.item.leaf, layout);
|
|
7776
8429
|
const nextColor = nextTile ? treemapLeafColor(nextTile.item.leaf, layout) : void 0;
|
|
7777
|
-
const nodes = [createTileNode(context, layout, tile,
|
|
8430
|
+
const nodes = [createTileNode(context, layout, tile, color, nextColor)];
|
|
7778
8431
|
if (context.showLabels && tile.width >= 34 && tile.height >= 18) {
|
|
7779
|
-
nodes.push(...createTileLabel(context, layout, tile,
|
|
8432
|
+
nodes.push(...createTileLabel(context, layout, tile, color));
|
|
7780
8433
|
}
|
|
7781
8434
|
return nodes;
|
|
7782
8435
|
}
|
|
7783
|
-
function createTileNode(context, layout, tile,
|
|
8436
|
+
function createTileNode(context, layout, tile, color, nextColor) {
|
|
7784
8437
|
const { chart, plot, bounds, diagnostics, nextOrder } = context;
|
|
7785
8438
|
const gap = layout.cellGap;
|
|
7786
8439
|
const shadow = resolveChartShadow(chart.shadowStyle);
|
|
@@ -7800,10 +8453,10 @@ function createTileNode(context, layout, tile, color2, nextColor) {
|
|
|
7800
8453
|
kind: "linear-gradient",
|
|
7801
8454
|
angle: 0,
|
|
7802
8455
|
stops: [
|
|
7803
|
-
{ offset: 0, color: representativeColor(
|
|
8456
|
+
{ offset: 0, color: representativeColor(color, fallback) },
|
|
7804
8457
|
{ offset: 100, color: representativeColor(nextColor, fallback) }
|
|
7805
8458
|
]
|
|
7806
|
-
} : paint(
|
|
8459
|
+
} : paint(color, diagnostics, chart.id);
|
|
7807
8460
|
return {
|
|
7808
8461
|
type: "rect",
|
|
7809
8462
|
id: `chart-treemap-tile-${chart.id}-${tile.item.leaf.id}`,
|
|
@@ -7823,7 +8476,7 @@ function createTileNode(context, layout, tile, color2, nextColor) {
|
|
|
7823
8476
|
}
|
|
7824
8477
|
};
|
|
7825
8478
|
}
|
|
7826
|
-
function createTileLabel(context, layout, tile,
|
|
8479
|
+
function createTileLabel(context, layout, tile, color) {
|
|
7827
8480
|
const { chart, plot, bounds, nextOrder } = context;
|
|
7828
8481
|
const { leaf, value } = tile.item;
|
|
7829
8482
|
const gap = layout.cellGap;
|
|
@@ -7832,7 +8485,7 @@ function createTileLabel(context, layout, tile, color2) {
|
|
|
7832
8485
|
const height = Math.max(1, tile.height - gap - pad * 1.5);
|
|
7833
8486
|
const x = plot.x + tile.x + gap / 2 + pad;
|
|
7834
8487
|
const y = plot.y + tile.y + gap / 2 + pad * 0.75;
|
|
7835
|
-
const textColor = chart.config?.tileTextColor ?? contrastTextColor(representativeColor(
|
|
8488
|
+
const textColor = chart.config?.tileTextColor ?? contrastTextColor(representativeColor(color, "#ffffff"));
|
|
7836
8489
|
const lineHeight = layout.labelSize * 1.2;
|
|
7837
8490
|
const maxLines = Math.max(1, Math.floor(height / lineHeight));
|
|
7838
8491
|
const labelLines = wrapText(leaf.label, width, layout.labelSize).slice(0, maxLines).map((line) => ellipsizeToWidth(line, width, layout.labelSize, true));
|
|
@@ -8154,7 +8807,7 @@ function stackingOf(input) {
|
|
|
8154
8807
|
add("frame", input.frames, 0);
|
|
8155
8808
|
add("swimlane", input.swimlanes, 5e3);
|
|
8156
8809
|
add("shape", input.shapes, 1e4);
|
|
8157
|
-
add("widget", input.widgets ?? [], 1e4);
|
|
8810
|
+
add("widget", input.components ?? input.widgets ?? [], 1e4);
|
|
8158
8811
|
add("isometric", input.isometricObjects ?? [], 15e3);
|
|
8159
8812
|
add(
|
|
8160
8813
|
"link",
|
|
@@ -8163,6 +8816,7 @@ function stackingOf(input) {
|
|
|
8163
8816
|
);
|
|
8164
8817
|
add("chart", input.charts ?? [], 2e4);
|
|
8165
8818
|
add("path", input.paths ?? [], 3e4);
|
|
8819
|
+
add("dimension", input.dimensions ?? [], 31e3);
|
|
8166
8820
|
return stacking;
|
|
8167
8821
|
}
|
|
8168
8822
|
function stampStacking(nodes, input) {
|
|
@@ -8182,8 +8836,9 @@ function buildRenderScene(input, options = {}) {
|
|
|
8182
8836
|
...buildCharts(input.charts ?? [], diagnostics),
|
|
8183
8837
|
...buildLinks(input.links, measureText),
|
|
8184
8838
|
...buildShapes(input.shapes, diagnostics, measureText),
|
|
8185
|
-
...
|
|
8186
|
-
...buildIsometricObjects(input.isometricObjects ?? [])
|
|
8839
|
+
...buildComponents(input.components ?? input.widgets ?? []),
|
|
8840
|
+
...buildIsometricObjects(input.isometricObjects ?? []),
|
|
8841
|
+
...buildDimensions(input.dimensions ?? [])
|
|
8187
8842
|
];
|
|
8188
8843
|
stampStacking(nodes, input);
|
|
8189
8844
|
nodes.sort(
|
|
@@ -8286,21 +8941,21 @@ function innerShadowPrimitives(shadow) {
|
|
|
8286
8941
|
}
|
|
8287
8942
|
|
|
8288
8943
|
// src/svg/markerBodies.ts
|
|
8289
|
-
function markerBody(type, size,
|
|
8944
|
+
function markerBody(type, size, color, strokeWidth) {
|
|
8290
8945
|
const bodies = {
|
|
8291
|
-
arrow: `<path d="M ${num(-size)} ${num(-size * 0.6)} L 0 0 L ${num(-size)} ${num(size * 0.6)}" fill="none" stroke="${
|
|
8292
|
-
filled_arrow: `<path d="M ${num(-size)} ${num(-size * 0.6)} L 0 0 L ${num(-size)} ${num(size * 0.6)} Z" fill="${
|
|
8293
|
-
circle: `<circle cx="0" cy="0" r="${num(size * 0.5)}" fill="white" stroke="${
|
|
8294
|
-
filled_circle: `<circle cx="0" cy="0" r="${num(size * 0.5)}" fill="${
|
|
8295
|
-
diamond: `<path d="M ${num(-size * 0.6)} 0 L 0 ${num(-size * 0.6)} L ${num(size * 0.6)} 0 L 0 ${num(size * 0.6)} Z" fill="white" stroke="${
|
|
8296
|
-
filled_diamond: `<path d="M ${num(-size * 0.6)} 0 L 0 ${num(-size * 0.6)} L ${num(size * 0.6)} 0 L 0 ${num(size * 0.6)} Z" fill="${
|
|
8297
|
-
bar: `<path d="M 0 ${num(-size * 0.6)} V ${num(size * 0.6)}" stroke="${
|
|
8298
|
-
triangle: `<path d="M ${num(-size)} ${num(-size * 0.72)} L 0 0 L ${num(-size)} ${num(size * 0.72)} Z" fill="white" stroke="${
|
|
8299
|
-
one: `<path d="M 0 ${num(-size * 0.62)} V ${num(size * 0.62)} M ${num(-size * 0.72)} ${num(-size * 0.62)} V ${num(size * 0.62)}" stroke="${
|
|
8300
|
-
zero_one: `<circle cx="${num(-size * 0.8)}" cy="0" r="${num(size * 0.38)}" fill="white" stroke="${
|
|
8301
|
-
many: `<path d="M ${num(-size)} ${num(-size * 0.72)} L 0 0 M ${num(-size)} 0 L 0 0 M ${num(-size)} ${num(size * 0.72)} L 0 0" stroke="${
|
|
8302
|
-
one_many: `<path d="M ${num(-size)} ${num(-size * 0.72)} L 0 0 M ${num(-size)} 0 L 0 0 M ${num(-size)} ${num(size * 0.72)} L 0 0 M ${num(-size * 1.45)} ${num(-size * 0.62)} V ${num(size * 0.62)}" stroke="${
|
|
8303
|
-
zero_many: `<circle cx="${num(-size * 1.45)}" cy="0" r="${num(size * 0.38)}" fill="white" stroke="${
|
|
8946
|
+
arrow: `<path d="M ${num(-size)} ${num(-size * 0.6)} L 0 0 L ${num(-size)} ${num(size * 0.6)}" fill="none" stroke="${color}" stroke-width="${num(strokeWidth)}" stroke-linecap="round" stroke-linejoin="round"/>`,
|
|
8947
|
+
filled_arrow: `<path d="M ${num(-size)} ${num(-size * 0.6)} L 0 0 L ${num(-size)} ${num(size * 0.6)} Z" fill="${color}" stroke="${color}" stroke-width="${num(strokeWidth * 0.5)}" stroke-linejoin="round"/>`,
|
|
8948
|
+
circle: `<circle cx="0" cy="0" r="${num(size * 0.5)}" fill="white" stroke="${color}" stroke-width="${num(strokeWidth)}"/>`,
|
|
8949
|
+
filled_circle: `<circle cx="0" cy="0" r="${num(size * 0.5)}" fill="${color}"/>`,
|
|
8950
|
+
diamond: `<path d="M ${num(-size * 0.6)} 0 L 0 ${num(-size * 0.6)} L ${num(size * 0.6)} 0 L 0 ${num(size * 0.6)} Z" fill="white" stroke="${color}" stroke-width="${num(strokeWidth)}"/>`,
|
|
8951
|
+
filled_diamond: `<path d="M ${num(-size * 0.6)} 0 L 0 ${num(-size * 0.6)} L ${num(size * 0.6)} 0 L 0 ${num(size * 0.6)} Z" fill="${color}" stroke="${color}" stroke-width="${num(strokeWidth * 0.5)}"/>`,
|
|
8952
|
+
bar: `<path d="M 0 ${num(-size * 0.6)} V ${num(size * 0.6)}" stroke="${color}" stroke-width="${num(strokeWidth)}" stroke-linecap="round"/>`,
|
|
8953
|
+
triangle: `<path d="M ${num(-size)} ${num(-size * 0.72)} L 0 0 L ${num(-size)} ${num(size * 0.72)} Z" fill="white" stroke="${color}" stroke-width="${num(strokeWidth)}" stroke-linejoin="round"/>`,
|
|
8954
|
+
one: `<path d="M 0 ${num(-size * 0.62)} V ${num(size * 0.62)} M ${num(-size * 0.72)} ${num(-size * 0.62)} V ${num(size * 0.62)}" stroke="${color}" stroke-width="${num(strokeWidth)}"/>`,
|
|
8955
|
+
zero_one: `<circle cx="${num(-size * 0.8)}" cy="0" r="${num(size * 0.38)}" fill="white" stroke="${color}" stroke-width="${num(strokeWidth)}"/><path d="M 0 ${num(-size * 0.62)} V ${num(size * 0.62)}" stroke="${color}" stroke-width="${num(strokeWidth)}"/>`,
|
|
8956
|
+
many: `<path d="M ${num(-size)} ${num(-size * 0.72)} L 0 0 M ${num(-size)} 0 L 0 0 M ${num(-size)} ${num(size * 0.72)} L 0 0" stroke="${color}" stroke-width="${num(strokeWidth)}" stroke-linecap="round"/>`,
|
|
8957
|
+
one_many: `<path d="M ${num(-size)} ${num(-size * 0.72)} L 0 0 M ${num(-size)} 0 L 0 0 M ${num(-size)} ${num(size * 0.72)} L 0 0 M ${num(-size * 1.45)} ${num(-size * 0.62)} V ${num(size * 0.62)}" stroke="${color}" stroke-width="${num(strokeWidth)}" stroke-linecap="round"/>`,
|
|
8958
|
+
zero_many: `<circle cx="${num(-size * 1.45)}" cy="0" r="${num(size * 0.38)}" fill="white" stroke="${color}" stroke-width="${num(strokeWidth)}"/><path d="M ${num(-size)} ${num(-size * 0.72)} L 0 0 M ${num(-size)} 0 L 0 0 M ${num(-size)} ${num(size * 0.72)} L 0 0" stroke="${color}" stroke-width="${num(strokeWidth)}" stroke-linecap="round"/>`
|
|
8304
8959
|
};
|
|
8305
8960
|
return bodies[type];
|
|
8306
8961
|
}
|
|
@@ -8321,11 +8976,11 @@ var SvgMarkerDefinitions = class {
|
|
|
8321
8976
|
addDefinition;
|
|
8322
8977
|
prefix;
|
|
8323
8978
|
ids = /* @__PURE__ */ new Map();
|
|
8324
|
-
marker(type,
|
|
8979
|
+
marker(type, color, strokeWidth) {
|
|
8325
8980
|
if (!type || type === "none") {
|
|
8326
8981
|
return void 0;
|
|
8327
8982
|
}
|
|
8328
|
-
const key = `${type}:${
|
|
8983
|
+
const key = `${type}:${color}:${strokeWidth}`;
|
|
8329
8984
|
let id = this.ids.get(key);
|
|
8330
8985
|
if (id) {
|
|
8331
8986
|
return id;
|
|
@@ -8335,7 +8990,7 @@ var SvgMarkerDefinitions = class {
|
|
|
8335
8990
|
const size = 12 + (strokeWidth - 2) * 3;
|
|
8336
8991
|
const extent = markerExtent(type, size, strokeWidth);
|
|
8337
8992
|
const attributes = markerAttributes(id, extent);
|
|
8338
|
-
this.addDefinition(`<marker ${attributes}>${markerBody(type, size, xml(
|
|
8993
|
+
this.addDefinition(`<marker ${attributes}>${markerBody(type, size, xml(color), strokeWidth)}</marker>`);
|
|
8339
8994
|
return id;
|
|
8340
8995
|
}
|
|
8341
8996
|
};
|
|
@@ -8415,8 +9070,8 @@ var SvgDefinitionRegistry = class {
|
|
|
8415
9070
|
filter(style, nodeId, size) {
|
|
8416
9071
|
return this.filters.filter(style, nodeId, size);
|
|
8417
9072
|
}
|
|
8418
|
-
marker(type,
|
|
8419
|
-
return this.markers.marker(type,
|
|
9073
|
+
marker(type, color, strokeWidth) {
|
|
9074
|
+
return this.markers.marker(type, color, strokeWidth);
|
|
8420
9075
|
}
|
|
8421
9076
|
clip(style) {
|
|
8422
9077
|
return this.clips.clip(style);
|
|
@@ -8546,13 +9201,22 @@ function imageAttrs(node, defs) {
|
|
|
8546
9201
|
function domRole(identity) {
|
|
8547
9202
|
return identity.role === "shape" ? "entity" : identity.role;
|
|
8548
9203
|
}
|
|
9204
|
+
function ariaAttrs(aria) {
|
|
9205
|
+
return [
|
|
9206
|
+
`role="${xml(aria.role)}"`,
|
|
9207
|
+
aria.checked === void 0 ? void 0 : `aria-checked="${aria.checked}"`,
|
|
9208
|
+
aria.pressed === void 0 ? void 0 : `aria-pressed="${aria.pressed}"`,
|
|
9209
|
+
aria.disabled ? 'aria-disabled="true"' : void 0
|
|
9210
|
+
];
|
|
9211
|
+
}
|
|
8549
9212
|
function identityAttrs(identity) {
|
|
8550
9213
|
return [
|
|
8551
9214
|
`data-sf-role="${domRole(identity)}"`,
|
|
8552
9215
|
`data-sf-id="${xml(identity.id)}"`,
|
|
8553
9216
|
identity.kind ? `data-sf-kind="${xml(identity.kind)}"` : void 0,
|
|
8554
9217
|
identity.primary ? 'data-sf-primary="true"' : void 0,
|
|
8555
|
-
identity.parentFrameId ? `data-sf-parent-frame="${xml(identity.parentFrameId)}"` : void 0
|
|
9218
|
+
identity.parentFrameId ? `data-sf-parent-frame="${xml(identity.parentFrameId)}"` : void 0,
|
|
9219
|
+
...identity.aria ? ariaAttrs(identity.aria) : []
|
|
8556
9220
|
];
|
|
8557
9221
|
}
|
|
8558
9222
|
function detailAttrs(detail) {
|
|
@@ -8737,7 +9401,7 @@ function shaderSurfaceSvg(node, defs) {
|
|
|
8737
9401
|
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>`;
|
|
8738
9402
|
}
|
|
8739
9403
|
function rollingDigitSvg(character, node) {
|
|
8740
|
-
const style = node.
|
|
9404
|
+
const style = node.componentStyle;
|
|
8741
9405
|
if (style.variant === "plain") {
|
|
8742
9406
|
return `<span xmlns="http://www.w3.org/1999/xhtml" data-sf-rolling-digit="true" style="position:relative;display:inline-block;width:.62em;height:1.1em;overflow:hidden"><span data-sf-rolling-current="true" style="position:absolute;inset:0;display:grid;place-items:center;color:${xml(style.color)};font-weight:${xml(style.fontWeight)};line-height:1">${xml(character)}</span></span>`;
|
|
8743
9407
|
}
|
|
@@ -8745,11 +9409,11 @@ function rollingDigitSvg(character, node) {
|
|
|
8745
9409
|
}
|
|
8746
9410
|
function rollingNumberSvg(node, defs) {
|
|
8747
9411
|
const rotation = transform(node.rotation, { x: node.x + node.width / 2, y: node.y + node.height / 2 });
|
|
8748
|
-
const fontSize = node.
|
|
8749
|
-
const label = node.label ? `<span xmlns="http://www.w3.org/1999/xhtml" style="margin-bottom:.14em;color:${xml(node.
|
|
9412
|
+
const fontSize = node.componentStyle.fontSize > 0 ? node.componentStyle.fontSize : Math.max(1, Math.min(node.width, node.height) * 0.28);
|
|
9413
|
+
const label = node.label ? `<span xmlns="http://www.w3.org/1999/xhtml" style="margin-bottom:.14em;color:${xml(node.componentStyle.labelColor)};font-size:.16em;font-weight:600;letter-spacing:.24em;line-height:1">${xml(node.label)}</span>` : "";
|
|
8750
9414
|
const digits = [...node.value].map((character) => rollingDigitSvg(character, node)).join("");
|
|
8751
|
-
const
|
|
8752
|
-
return `<foreignObject id="${defs.elementId(node.id)}"${contractAttrs(node)} data-sf-widget="rollingNumber" data-sf-widget-value="${xml(node.value)}" data-sf-widget-digits="${node.digits ?? ""}" data-sf-widget-duration="${num(node.duration)}" data-sf-widget-style="${
|
|
9415
|
+
const componentStyle = xml(JSON.stringify(node.componentStyle));
|
|
9416
|
+
return `<foreignObject id="${defs.elementId(node.id)}"${contractAttrs(node)} data-sf-widget="rollingNumber" data-sf-widget-value="${xml(node.value)}" data-sf-widget-digits="${node.digits ?? ""}" data-sf-widget-duration="${num(node.duration)}" data-sf-widget-style="${componentStyle}" x="${num(node.x)}" y="${num(node.y)}" width="${num(node.width)}" height="${num(node.height)}"${rotation}><div xmlns="http://www.w3.org/1999/xhtml" style="width:100%;height:100%;display:flex;flex-direction:column;align-items:center;justify-content:center;font-family:${xml(node.componentStyle.fontFamily)};font-size:${num(fontSize)}px">${label}<div data-sf-rolling-digits="true" aria-label="${xml(node.value)}" style="display:flex;gap:${node.componentStyle.variant === "plain" ? ".02em" : ".1em"};font-size:1em">${digits}</div></div></foreignObject>`;
|
|
8753
9417
|
}
|
|
8754
9418
|
function nodeSvg(node, defs) {
|
|
8755
9419
|
if (node.type === "text") {
|
|
@@ -8804,7 +9468,13 @@ function renderCanvas(input, options = {}) {
|
|
|
8804
9468
|
}
|
|
8805
9469
|
var SCENE_CACHE_LIMIT = 50;
|
|
8806
9470
|
var sceneCache = /* @__PURE__ */ new Map();
|
|
9471
|
+
var cachedForRegistry = componentRegistryVersion();
|
|
8807
9472
|
function cachedRenderScene(source) {
|
|
9473
|
+
const registry = componentRegistryVersion();
|
|
9474
|
+
if (registry !== cachedForRegistry) {
|
|
9475
|
+
sceneCache.clear();
|
|
9476
|
+
cachedForRegistry = registry;
|
|
9477
|
+
}
|
|
8808
9478
|
const cached = sceneCache.get(source);
|
|
8809
9479
|
if (cached) {
|
|
8810
9480
|
sceneCache.delete(source);
|
|
@@ -8829,7 +9499,20 @@ function render(source, options = {}) {
|
|
|
8829
9499
|
const { svg, width, height, diagnostics } = renderSceneToSvg(scene, options);
|
|
8830
9500
|
return { svg, width, height, diagnostics, scene };
|
|
8831
9501
|
}
|
|
9502
|
+
var SCENE_ORDER_BASE = 1e4;
|
|
9503
|
+
function defineComponent(definition) {
|
|
9504
|
+
const { scene, ...descriptor } = definition;
|
|
9505
|
+
const unregisterDescriptor = registerComponentDescriptor(descriptor);
|
|
9506
|
+
const unregisterBuilder = registerComponentBuilder(
|
|
9507
|
+
descriptor.type,
|
|
9508
|
+
(component, index) => scene(component, { order: SCENE_ORDER_BASE + index })
|
|
9509
|
+
);
|
|
9510
|
+
return () => {
|
|
9511
|
+
unregisterBuilder();
|
|
9512
|
+
unregisterDescriptor();
|
|
9513
|
+
};
|
|
9514
|
+
}
|
|
8832
9515
|
|
|
8833
|
-
export {
|
|
8834
|
-
//# sourceMappingURL=chunk-
|
|
8835
|
-
//# sourceMappingURL=chunk-
|
|
9516
|
+
export { collectCanvasObjects, decodeColor, decodeShadow, defineComponent, render, renderCanvas, sflToRenderInput };
|
|
9517
|
+
//# sourceMappingURL=chunk-FVHVOJS2.js.map
|
|
9518
|
+
//# sourceMappingURL=chunk-FVHVOJS2.js.map
|