@01.software/sdk 0.32.0 → 0.34.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/README.md +253 -38
- package/dist/analytics/react.cjs.map +1 -1
- package/dist/analytics/react.js.map +1 -1
- package/dist/analytics.cjs.map +1 -1
- package/dist/analytics.js.map +1 -1
- package/dist/client.cjs +368 -24
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +7 -6
- package/dist/client.d.ts +7 -6
- package/dist/client.js +368 -24
- package/dist/client.js.map +1 -1
- package/dist/{collection-client-CORhppPb.d.cts → collection-client-CR2B8c1v.d.cts} +7 -3
- package/dist/{collection-client-DPGXnhoF.d.ts → collection-client-DkREjhQ9.d.ts} +7 -3
- package/dist/{const-DcY2_z9O.d.ts → const-BTvdrXtY.d.cts} +5 -5
- package/dist/{const-Brk2Ff0q.d.cts → const-CdqCauHQ.d.ts} +5 -5
- package/dist/index-CjA3U6X3.d.cts +186 -0
- package/dist/index-DK8_NXkh.d.ts +186 -0
- package/dist/index.cjs +1651 -260
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +74 -9
- package/dist/index.d.ts +74 -9
- package/dist/index.js +1651 -260
- package/dist/index.js.map +1 -1
- package/dist/{payload-types-DVK1QCeU.d.cts → payload-types-C7tb7Xbs.d.cts} +2115 -1833
- package/dist/{payload-types-DVK1QCeU.d.ts → payload-types-C7tb7Xbs.d.ts} +2115 -1833
- package/dist/query.cjs +194 -35
- package/dist/query.cjs.map +1 -1
- package/dist/query.d.cts +45 -18
- package/dist/query.d.ts +45 -18
- package/dist/query.js +194 -35
- package/dist/query.js.map +1 -1
- package/dist/realtime.cjs.map +1 -1
- package/dist/realtime.d.cts +2 -2
- package/dist/realtime.d.ts +2 -2
- package/dist/realtime.js.map +1 -1
- package/dist/{server-CrsPyqEc.d.cts → server-nXOezi4b.d.cts} +22 -6
- package/dist/{server-CrsPyqEc.d.ts → server-nXOezi4b.d.ts} +22 -6
- package/dist/server.cjs +474 -36
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +11 -179
- package/dist/server.d.ts +11 -179
- package/dist/server.js +474 -36
- package/dist/server.js.map +1 -1
- package/dist/{types-DUPC7Xn6.d.ts → types-1ylMrCuW.d.ts} +1 -1
- package/dist/{types-ByMrR_Z_.d.cts → types-Bx558PU6.d.cts} +1 -1
- package/dist/{types-CYMSBkJC.d.ts → types-Byo_Rty4.d.ts} +728 -75
- package/dist/{types-CAkWqIr6.d.cts → types-DDhtZI6E.d.cts} +728 -75
- package/dist/ui/canvas/server.cjs +231 -38
- package/dist/ui/canvas/server.cjs.map +1 -1
- package/dist/ui/canvas/server.d.cts +1 -1
- package/dist/ui/canvas/server.d.ts +1 -1
- package/dist/ui/canvas/server.js +221 -38
- package/dist/ui/canvas/server.js.map +1 -1
- package/dist/ui/canvas.cjs +320 -257
- package/dist/ui/canvas.cjs.map +1 -1
- package/dist/ui/canvas.d.cts +5 -19
- package/dist/ui/canvas.d.ts +5 -19
- package/dist/ui/canvas.js +323 -260
- package/dist/ui/canvas.js.map +1 -1
- package/dist/ui/form.d.cts +1 -1
- package/dist/ui/form.d.ts +1 -1
- package/dist/ui/video.d.cts +1 -1
- package/dist/ui/video.d.ts +1 -1
- package/dist/webhook.cjs +95 -0
- package/dist/webhook.cjs.map +1 -1
- package/dist/webhook.d.cts +20 -104
- package/dist/webhook.d.ts +20 -104
- package/dist/webhook.js +95 -0
- package/dist/webhook.js.map +1 -1
- package/package.json +4 -5
package/dist/ui/canvas.js
CHANGED
|
@@ -8,44 +8,6 @@ function isFrameNode(node) {
|
|
|
8
8
|
return node.type === "frame";
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
// src/ui/Canvas/built-in-node-types.ts
|
|
12
|
-
var BUILT_IN_NODE_TYPES = [
|
|
13
|
-
{
|
|
14
|
-
slug: "text",
|
|
15
|
-
name: "Text",
|
|
16
|
-
color: "#e5e7eb",
|
|
17
|
-
defaultSize: { width: 200, height: 200 },
|
|
18
|
-
fields: [{ name: "body", label: "Body", fieldType: "textarea" }]
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
slug: "image",
|
|
22
|
-
name: "Image",
|
|
23
|
-
color: "#e5e7eb",
|
|
24
|
-
transparentBackground: true,
|
|
25
|
-
defaultSize: { width: 200, height: 200 },
|
|
26
|
-
fields: [
|
|
27
|
-
{ name: "image", label: "Image", fieldType: "image" },
|
|
28
|
-
{ name: "alt", label: "Alt Text", fieldType: "text" },
|
|
29
|
-
{ name: "caption", label: "Caption", fieldType: "text" }
|
|
30
|
-
]
|
|
31
|
-
}
|
|
32
|
-
];
|
|
33
|
-
|
|
34
|
-
// src/ui/Canvas/built-in-edge-types.ts
|
|
35
|
-
var BUILT_IN_EDGE_TYPES = [
|
|
36
|
-
{
|
|
37
|
-
slug: "default",
|
|
38
|
-
name: "Default",
|
|
39
|
-
color: "",
|
|
40
|
-
strokeWidth: 2,
|
|
41
|
-
animated: false,
|
|
42
|
-
lineStyle: "default",
|
|
43
|
-
markerStart: "none",
|
|
44
|
-
markerEnd: "arrow",
|
|
45
|
-
fields: []
|
|
46
|
-
}
|
|
47
|
-
];
|
|
48
|
-
|
|
49
11
|
// src/ui/Canvas/useCanvas.ts
|
|
50
12
|
import { useQuery } from "@tanstack/react-query";
|
|
51
13
|
import { useMemo } from "react";
|
|
@@ -99,7 +61,7 @@ function edgeTypesQueryOptions(client) {
|
|
|
99
61
|
};
|
|
100
62
|
}
|
|
101
63
|
|
|
102
|
-
// src/ui/Canvas/
|
|
64
|
+
// src/ui/Canvas/catalog-mappers.ts
|
|
103
65
|
function toNodeTypeDef(doc) {
|
|
104
66
|
return {
|
|
105
67
|
slug: String(doc.slug ?? ""),
|
|
@@ -110,7 +72,10 @@ function toNodeTypeDef(doc) {
|
|
|
110
72
|
height: 200
|
|
111
73
|
},
|
|
112
74
|
fields: Array.isArray(doc.fields) ? doc.fields : [],
|
|
113
|
-
|
|
75
|
+
editorIntent: doc.editorIntent === "text" || doc.editorIntent === "image" ? doc.editorIntent : void 0,
|
|
76
|
+
transparentBackground: Boolean(
|
|
77
|
+
doc.hasTransparentBackground ?? doc.transparentBackground
|
|
78
|
+
),
|
|
114
79
|
template: doc.template ?? null,
|
|
115
80
|
customCSS: doc.customCSS ?? null
|
|
116
81
|
};
|
|
@@ -121,13 +86,16 @@ function toEdgeTypeDef(doc) {
|
|
|
121
86
|
name: String(doc.title ?? ""),
|
|
122
87
|
color: String(doc.color ?? ""),
|
|
123
88
|
strokeWidth: doc.strokeWidth ?? 2,
|
|
124
|
-
animated: doc.animated ?? false,
|
|
89
|
+
animated: doc.isAnimated ?? doc.animated ?? false,
|
|
125
90
|
lineStyle: String(doc.lineStyle ?? "default"),
|
|
126
91
|
markerStart: String(doc.markerStart ?? "none"),
|
|
127
92
|
markerEnd: String(doc.markerEnd ?? "arrow"),
|
|
128
|
-
fields: Array.isArray(doc.fields) ? doc.fields : []
|
|
93
|
+
fields: Array.isArray(doc.fields) ? doc.fields : [],
|
|
94
|
+
isDefaultEdge: Boolean(doc.isDefaultEdge)
|
|
129
95
|
};
|
|
130
96
|
}
|
|
97
|
+
|
|
98
|
+
// src/ui/Canvas/useCanvas.ts
|
|
131
99
|
function useCanvas(options) {
|
|
132
100
|
const { client, queryClient, slug, id, enabled = true } = options;
|
|
133
101
|
const hasIdentifier = !!(slug || id);
|
|
@@ -153,16 +121,10 @@ function useCanvas(options) {
|
|
|
153
121
|
queryClient
|
|
154
122
|
);
|
|
155
123
|
const nodeTypeDefs = useMemo(() => {
|
|
156
|
-
|
|
157
|
-
const builtInSlugs = new Set(BUILT_IN_NODE_TYPES.map((t) => t.slug));
|
|
158
|
-
const customDefs = apiDefs.filter((d) => !builtInSlugs.has(d.slug));
|
|
159
|
-
return [...BUILT_IN_NODE_TYPES, ...customDefs];
|
|
124
|
+
return (nodeTypesQuery.data ?? []).map(toNodeTypeDef);
|
|
160
125
|
}, [nodeTypesQuery.data]);
|
|
161
126
|
const edgeTypeDefs = useMemo(() => {
|
|
162
|
-
|
|
163
|
-
const builtInSlugs = new Set(BUILT_IN_EDGE_TYPES.map((t) => t.slug));
|
|
164
|
-
const customDefs = apiDefs.filter((d) => !builtInSlugs.has(d.slug));
|
|
165
|
-
return [...BUILT_IN_EDGE_TYPES, ...customDefs];
|
|
127
|
+
return (edgeTypesQuery.data ?? []).map(toEdgeTypeDef);
|
|
166
128
|
}, [edgeTypesQuery.data]);
|
|
167
129
|
const canvasDoc = canvasQuery.data;
|
|
168
130
|
const canvasData = canvasDoc?.canvas;
|
|
@@ -194,11 +156,11 @@ import { useMemo as useMemo2 } from "react";
|
|
|
194
156
|
function useCanvasData(options) {
|
|
195
157
|
const { data, nodeTypeDefs: inputNodeDefs, edgeTypeDefs: inputEdgeDefs } = options;
|
|
196
158
|
const nodeTypeDefsMap = useMemo2(() => {
|
|
197
|
-
const allDefs = inputNodeDefs ??
|
|
159
|
+
const allDefs = inputNodeDefs ?? [];
|
|
198
160
|
return new Map(allDefs.map((d) => [d.slug, d]));
|
|
199
161
|
}, [inputNodeDefs]);
|
|
200
162
|
const edgeTypeDefsMap = useMemo2(() => {
|
|
201
|
-
const allDefs = inputEdgeDefs ??
|
|
163
|
+
const allDefs = inputEdgeDefs ?? [];
|
|
202
164
|
return new Map(allDefs.map((d) => [d.slug, d]));
|
|
203
165
|
}, [inputEdgeDefs]);
|
|
204
166
|
const nodes = useMemo2(() => data?.nodes ?? [], [data?.nodes]);
|
|
@@ -630,9 +592,176 @@ function clearTemplateCache() {
|
|
|
630
592
|
}
|
|
631
593
|
|
|
632
594
|
// src/ui/Canvas/node-renderers.tsx
|
|
633
|
-
import
|
|
595
|
+
import React3 from "react";
|
|
596
|
+
|
|
597
|
+
// src/ui/Image/index.tsx
|
|
598
|
+
import React2, { useCallback, useRef, useState } from "react";
|
|
599
|
+
|
|
600
|
+
// src/utils/image.ts
|
|
601
|
+
var IMAGE_SIZES = [384, 768, 1536];
|
|
602
|
+
function getImageSrcSet(image) {
|
|
603
|
+
const parts = [];
|
|
604
|
+
const sizes = image.sizes;
|
|
605
|
+
if (sizes) {
|
|
606
|
+
for (const size of IMAGE_SIZES) {
|
|
607
|
+
const entry = sizes[String(size)];
|
|
608
|
+
if (entry?.url && entry.width) {
|
|
609
|
+
parts.push(`${entry.url} ${entry.width}w`);
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
if (image.url && image.width) {
|
|
614
|
+
parts.push(`${image.url} ${image.width}w`);
|
|
615
|
+
}
|
|
616
|
+
return parts.join(", ");
|
|
617
|
+
}
|
|
618
|
+
function getImagePlaceholderStyle(image, options) {
|
|
619
|
+
const type = options?.type ?? "blur";
|
|
620
|
+
const paletteColor = options?.paletteColor ?? "muted";
|
|
621
|
+
if (type === "none") return {};
|
|
622
|
+
const color = image.palette?.[paletteColor];
|
|
623
|
+
if (type === "blur") {
|
|
624
|
+
const lqip = image.lqip;
|
|
625
|
+
if (lqip) {
|
|
626
|
+
return {
|
|
627
|
+
backgroundImage: `url(${lqip})`,
|
|
628
|
+
backgroundSize: "cover",
|
|
629
|
+
backgroundPosition: "center"
|
|
630
|
+
};
|
|
631
|
+
}
|
|
632
|
+
if (color) {
|
|
633
|
+
return { backgroundColor: color };
|
|
634
|
+
}
|
|
635
|
+
return {};
|
|
636
|
+
}
|
|
637
|
+
if (color) {
|
|
638
|
+
return { backgroundColor: color };
|
|
639
|
+
}
|
|
640
|
+
return {};
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
// src/ui/Image/index.tsx
|
|
644
|
+
function Image({
|
|
645
|
+
image,
|
|
646
|
+
width,
|
|
647
|
+
dpr = 1,
|
|
648
|
+
placeholder: placeholderProp,
|
|
649
|
+
className,
|
|
650
|
+
style,
|
|
651
|
+
imgClassName,
|
|
652
|
+
imgStyle,
|
|
653
|
+
sizes,
|
|
654
|
+
loading: loadingProp,
|
|
655
|
+
onLoad,
|
|
656
|
+
objectFit = "cover",
|
|
657
|
+
priority = false,
|
|
658
|
+
fill = false,
|
|
659
|
+
imageRendering,
|
|
660
|
+
alt: altProp
|
|
661
|
+
}) {
|
|
662
|
+
const [loaded, setLoaded] = useState(false);
|
|
663
|
+
const firedRef = useRef(false);
|
|
664
|
+
const isPixelRendering = imageRendering === "pixelated" || imageRendering === "crisp-edges";
|
|
665
|
+
const placeholder = placeholderProp ?? (isPixelRendering ? "none" : "blur");
|
|
666
|
+
const loading = priority ? "eager" : loadingProp ?? "lazy";
|
|
667
|
+
const aspectRatio = !fill && image.width && image.height ? `${image.width} / ${image.height}` : void 0;
|
|
668
|
+
const srcSet = getImageSrcSet(image);
|
|
669
|
+
const src = image.url ?? void 0;
|
|
670
|
+
const hasLqip = placeholder === "blur" && !!image.lqip;
|
|
671
|
+
const placeholderStyle = getImagePlaceholderStyle(image, {
|
|
672
|
+
type: placeholder
|
|
673
|
+
});
|
|
674
|
+
const placeholderColor = !hasLqip && "backgroundColor" in placeholderStyle ? placeholderStyle.backgroundColor : void 0;
|
|
675
|
+
const fireLoad = useCallback(() => {
|
|
676
|
+
if (firedRef.current) return;
|
|
677
|
+
firedRef.current = true;
|
|
678
|
+
setLoaded(true);
|
|
679
|
+
onLoad?.();
|
|
680
|
+
}, [onLoad]);
|
|
681
|
+
const imgRef = useCallback(
|
|
682
|
+
(node) => {
|
|
683
|
+
if (node && node.complete && node.naturalWidth > 0) {
|
|
684
|
+
fireLoad();
|
|
685
|
+
}
|
|
686
|
+
},
|
|
687
|
+
[fireLoad]
|
|
688
|
+
);
|
|
689
|
+
const containerStyle = {
|
|
690
|
+
position: "relative",
|
|
691
|
+
overflow: "hidden",
|
|
692
|
+
...fill ? { width: "100%", height: "100%" } : {},
|
|
693
|
+
...aspectRatio ? { aspectRatio } : {},
|
|
694
|
+
...style
|
|
695
|
+
};
|
|
696
|
+
const overlayBase = {
|
|
697
|
+
position: "absolute",
|
|
698
|
+
top: 0,
|
|
699
|
+
left: 0,
|
|
700
|
+
width: "100%",
|
|
701
|
+
height: "100%",
|
|
702
|
+
opacity: loaded ? 0 : 1,
|
|
703
|
+
transition: "opacity 0.3s ease",
|
|
704
|
+
pointerEvents: "none"
|
|
705
|
+
};
|
|
706
|
+
const mainImgStyle = {
|
|
707
|
+
display: "block",
|
|
708
|
+
width: "100%",
|
|
709
|
+
height: "100%",
|
|
710
|
+
objectFit,
|
|
711
|
+
...imageRendering ? { imageRendering } : {},
|
|
712
|
+
opacity: loaded ? 1 : 0,
|
|
713
|
+
transition: "opacity 0.3s ease",
|
|
714
|
+
...imgStyle
|
|
715
|
+
};
|
|
716
|
+
return /* @__PURE__ */ React2.createElement("div", { className, style: containerStyle }, hasLqip && /* @__PURE__ */ React2.createElement(
|
|
717
|
+
"img",
|
|
718
|
+
{
|
|
719
|
+
"aria-hidden": true,
|
|
720
|
+
alt: "",
|
|
721
|
+
src: image.lqip,
|
|
722
|
+
style: {
|
|
723
|
+
...overlayBase,
|
|
724
|
+
display: "block",
|
|
725
|
+
objectFit,
|
|
726
|
+
filter: "blur(20px)",
|
|
727
|
+
transform: "scale(1.1)"
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
), placeholderColor && /* @__PURE__ */ React2.createElement(
|
|
731
|
+
"div",
|
|
732
|
+
{
|
|
733
|
+
"aria-hidden": true,
|
|
734
|
+
style: {
|
|
735
|
+
...overlayBase,
|
|
736
|
+
backgroundColor: placeholderColor
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
), /* @__PURE__ */ React2.createElement(
|
|
740
|
+
"img",
|
|
741
|
+
{
|
|
742
|
+
ref: imgRef,
|
|
743
|
+
alt: altProp ?? image.alt ?? "",
|
|
744
|
+
src,
|
|
745
|
+
srcSet: srcSet || void 0,
|
|
746
|
+
sizes,
|
|
747
|
+
width: width ? width * dpr : void 0,
|
|
748
|
+
loading,
|
|
749
|
+
decoding: "async",
|
|
750
|
+
fetchPriority: priority ? "high" : void 0,
|
|
751
|
+
onLoad: fireLoad,
|
|
752
|
+
className: imgClassName,
|
|
753
|
+
style: mainImgStyle
|
|
754
|
+
}
|
|
755
|
+
));
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
// src/ui/Canvas/node-renderers.tsx
|
|
634
759
|
function sanitizeUrl(url) {
|
|
635
760
|
if (!url) return url;
|
|
761
|
+
if (url !== url.trim()) return void 0;
|
|
762
|
+
if (url.startsWith("/") && !url.startsWith("//") || url.startsWith("./")) {
|
|
763
|
+
return url;
|
|
764
|
+
}
|
|
636
765
|
try {
|
|
637
766
|
const parsed = new URL(url);
|
|
638
767
|
if (parsed.protocol === "http:" || parsed.protocol === "https:") return url;
|
|
@@ -641,6 +770,18 @@ function sanitizeUrl(url) {
|
|
|
641
770
|
return void 0;
|
|
642
771
|
}
|
|
643
772
|
}
|
|
773
|
+
function sanitizeImageData(image, safeUrl) {
|
|
774
|
+
return {
|
|
775
|
+
...image,
|
|
776
|
+
url: safeUrl,
|
|
777
|
+
sizes: image.sizes ? Object.fromEntries(
|
|
778
|
+
Object.entries(image.sizes).map(([name, size]) => [
|
|
779
|
+
name,
|
|
780
|
+
size ? { ...size, url: sanitizeUrl(size.url ?? void 0) } : size
|
|
781
|
+
])
|
|
782
|
+
) : image.sizes
|
|
783
|
+
};
|
|
784
|
+
}
|
|
644
785
|
function renderFieldValue(key, val, fieldDef) {
|
|
645
786
|
if (val == null || val === "") return null;
|
|
646
787
|
const fieldType = fieldDef?.fieldType;
|
|
@@ -648,7 +789,19 @@ function renderFieldValue(key, val, fieldDef) {
|
|
|
648
789
|
const imgUrl = typeof val === "string" ? val : val?.url;
|
|
649
790
|
const safeUrl = sanitizeUrl(imgUrl);
|
|
650
791
|
if (!safeUrl) return null;
|
|
651
|
-
|
|
792
|
+
if (fieldType === "image" && typeof val === "object" && val !== null) {
|
|
793
|
+
return /* @__PURE__ */ React3.createElement(
|
|
794
|
+
Image,
|
|
795
|
+
{
|
|
796
|
+
key,
|
|
797
|
+
image: sanitizeImageData(val, safeUrl),
|
|
798
|
+
fill: true,
|
|
799
|
+
objectFit: "contain",
|
|
800
|
+
style: { flex: 1, minHeight: 0, width: "100%" }
|
|
801
|
+
}
|
|
802
|
+
);
|
|
803
|
+
}
|
|
804
|
+
return /* @__PURE__ */ React3.createElement(
|
|
652
805
|
"img",
|
|
653
806
|
{
|
|
654
807
|
key,
|
|
@@ -659,7 +812,7 @@ function renderFieldValue(key, val, fieldDef) {
|
|
|
659
812
|
}
|
|
660
813
|
);
|
|
661
814
|
}
|
|
662
|
-
return /* @__PURE__ */
|
|
815
|
+
return /* @__PURE__ */ React3.createElement(
|
|
663
816
|
"div",
|
|
664
817
|
{
|
|
665
818
|
key,
|
|
@@ -676,7 +829,7 @@ function renderFieldValue(key, val, fieldDef) {
|
|
|
676
829
|
}
|
|
677
830
|
function DefaultDynamicNode({ data }) {
|
|
678
831
|
const d = data;
|
|
679
|
-
return /* @__PURE__ */
|
|
832
|
+
return /* @__PURE__ */ React3.createElement(
|
|
680
833
|
"div",
|
|
681
834
|
{
|
|
682
835
|
style: {
|
|
@@ -689,7 +842,7 @@ function DefaultDynamicNode({ data }) {
|
|
|
689
842
|
d.fields && Object.entries(d.fields).filter(([, v]) => v != null && v !== "").map(([key, val]) => renderFieldValue(key, val))
|
|
690
843
|
);
|
|
691
844
|
}
|
|
692
|
-
var TemplateErrorBoundary = class extends
|
|
845
|
+
var TemplateErrorBoundary = class extends React3.Component {
|
|
693
846
|
constructor() {
|
|
694
847
|
super(...arguments);
|
|
695
848
|
this.state = { error: null };
|
|
@@ -704,7 +857,7 @@ var TemplateErrorBoundary = class extends React2.Component {
|
|
|
704
857
|
}
|
|
705
858
|
render() {
|
|
706
859
|
if (this.state.error) {
|
|
707
|
-
return /* @__PURE__ */
|
|
860
|
+
return /* @__PURE__ */ React3.createElement("div", { style: { padding: 8, fontSize: 11, color: "#ef4444" } }, /* @__PURE__ */ React3.createElement("strong", null, "Render error"), /* @__PURE__ */ React3.createElement("pre", { style: { fontSize: 10, whiteSpace: "pre-wrap" } }, process.env.NODE_ENV === "development" ? this.state.error.message : "Template render failed"));
|
|
708
861
|
}
|
|
709
862
|
return this.props.children;
|
|
710
863
|
}
|
|
@@ -719,13 +872,13 @@ function EnhancedDynamicNode({
|
|
|
719
872
|
if (typeDef.template) {
|
|
720
873
|
const Component = compileTemplate(typeDef.template, typeDef.slug);
|
|
721
874
|
if (Component) {
|
|
722
|
-
return /* @__PURE__ */
|
|
875
|
+
return /* @__PURE__ */ React3.createElement(
|
|
723
876
|
"div",
|
|
724
877
|
{
|
|
725
878
|
className: `flow-node flow-node--${typeDef.slug}${typeDef.transparentBackground ? " flow-node--transparent-bg" : ""}`,
|
|
726
879
|
style: { width: "100%", height: "100%" }
|
|
727
880
|
},
|
|
728
|
-
/* @__PURE__ */
|
|
881
|
+
/* @__PURE__ */ React3.createElement(TemplateErrorBoundary, { resetKey: typeDef.template }, /* @__PURE__ */ React3.createElement(
|
|
729
882
|
Component,
|
|
730
883
|
{
|
|
731
884
|
fields: data.fields,
|
|
@@ -739,7 +892,7 @@ function EnhancedDynamicNode({
|
|
|
739
892
|
);
|
|
740
893
|
}
|
|
741
894
|
}
|
|
742
|
-
return /* @__PURE__ */
|
|
895
|
+
return /* @__PURE__ */ React3.createElement(
|
|
743
896
|
"div",
|
|
744
897
|
{
|
|
745
898
|
className: `flow-node flow-node--${typeDef.slug}`,
|
|
@@ -767,12 +920,14 @@ function DefaultFrameNode({ data }) {
|
|
|
767
920
|
const m = baseColor.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/);
|
|
768
921
|
if (m) return `rgba(${m[1]},${m[2]},${m[3]},${opacity})`;
|
|
769
922
|
const h6 = baseColor.match(/^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i);
|
|
770
|
-
if (h6)
|
|
923
|
+
if (h6)
|
|
924
|
+
return `rgba(${parseInt(h6[1], 16)},${parseInt(h6[2], 16)},${parseInt(h6[3], 16)},${opacity})`;
|
|
771
925
|
const h3 = baseColor.match(/^#([0-9a-f])([0-9a-f])([0-9a-f])$/i);
|
|
772
|
-
if (h3)
|
|
926
|
+
if (h3)
|
|
927
|
+
return `rgba(${parseInt(h3[1] + h3[1], 16)},${parseInt(h3[2] + h3[2], 16)},${parseInt(h3[3] + h3[3], 16)},${opacity})`;
|
|
773
928
|
return baseColor;
|
|
774
929
|
})();
|
|
775
|
-
return /* @__PURE__ */
|
|
930
|
+
return /* @__PURE__ */ React3.createElement(
|
|
776
931
|
"div",
|
|
777
932
|
{
|
|
778
933
|
style: {
|
|
@@ -783,7 +938,7 @@ function DefaultFrameNode({ data }) {
|
|
|
783
938
|
border: borderStyle === "none" ? "none" : `2px ${borderStyle} rgba(128,128,128,0.3)`
|
|
784
939
|
}
|
|
785
940
|
},
|
|
786
|
-
/* @__PURE__ */
|
|
941
|
+
/* @__PURE__ */ React3.createElement(
|
|
787
942
|
"div",
|
|
788
943
|
{
|
|
789
944
|
style: {
|
|
@@ -820,21 +975,64 @@ function getBooleanField(fields, name) {
|
|
|
820
975
|
|
|
821
976
|
// src/ui/Canvas/css-sanitizer.ts
|
|
822
977
|
import postcss from "postcss";
|
|
823
|
-
var ALLOWED_AT_RULES = /* @__PURE__ */ new Set([
|
|
824
|
-
|
|
978
|
+
var ALLOWED_AT_RULES = /* @__PURE__ */ new Set([
|
|
979
|
+
"keyframes",
|
|
980
|
+
"media",
|
|
981
|
+
"supports",
|
|
982
|
+
"container",
|
|
983
|
+
"layer"
|
|
984
|
+
]);
|
|
985
|
+
var BLOCKED_VALUE_PATTERNS = [
|
|
986
|
+
/url\s*\(/i,
|
|
987
|
+
/expression\s*\(/i,
|
|
988
|
+
/paint\s*\(/i,
|
|
989
|
+
/-moz-binding/i
|
|
990
|
+
];
|
|
825
991
|
var DANGEROUS_SELECTOR = /(?:^|[\s,])(?::root|html|body)\b/;
|
|
826
992
|
var BLOCKED_PROPERTY_VALUES = {
|
|
827
993
|
// absolute is allowed — contained by nearest positioned ancestor (node wrapper)
|
|
828
994
|
position: /fixed|sticky/i
|
|
829
995
|
};
|
|
996
|
+
var TENANT_CSS_BLOCKED_PATTERNS = [
|
|
997
|
+
{ pattern: /<\/style/i, label: "</style" },
|
|
998
|
+
{ pattern: /<script/i, label: "<script" },
|
|
999
|
+
{ pattern: /@import/i, label: "@import" },
|
|
1000
|
+
{ pattern: /url\s*\(/i, label: "url(" }
|
|
1001
|
+
];
|
|
830
1002
|
var Z_INDEX_MAX = 9998;
|
|
1003
|
+
function normalizeCSSEscapes(value) {
|
|
1004
|
+
return value.replace(
|
|
1005
|
+
/\\(?:([0-9a-fA-F]{1,6})(?:\r\n|[ \t\r\n\f])?|([^\r\n\f]))/g,
|
|
1006
|
+
(match, hex, escaped) => {
|
|
1007
|
+
if (hex) {
|
|
1008
|
+
const cp = parseInt(hex, 16);
|
|
1009
|
+
if (Number.isNaN(cp) || cp > 1114111) return match;
|
|
1010
|
+
try {
|
|
1011
|
+
return String.fromCodePoint(cp);
|
|
1012
|
+
} catch {
|
|
1013
|
+
return match;
|
|
1014
|
+
}
|
|
1015
|
+
}
|
|
1016
|
+
return escaped ?? match;
|
|
1017
|
+
}
|
|
1018
|
+
);
|
|
1019
|
+
}
|
|
831
1020
|
function sanitizeCSS(css, scopeClass) {
|
|
1021
|
+
return sanitizeCSSWithStats(css, scopeClass).css;
|
|
1022
|
+
}
|
|
1023
|
+
function sanitizeCSSWithStats(css, scopeClass) {
|
|
832
1024
|
let root;
|
|
833
1025
|
try {
|
|
834
1026
|
root = postcss.parse(css);
|
|
835
1027
|
} catch {
|
|
836
|
-
return "";
|
|
1028
|
+
return { css: "", removedRules: 0, removedDecls: 0, removedAtRules: 0 };
|
|
837
1029
|
}
|
|
1030
|
+
const stats = {
|
|
1031
|
+
css: "",
|
|
1032
|
+
removedRules: 0,
|
|
1033
|
+
removedDecls: 0,
|
|
1034
|
+
removedAtRules: 0
|
|
1035
|
+
};
|
|
838
1036
|
const safeScopeClass = scopeClass ? scopeClass.replace(/[{}()[\];,'"\\<>\s]/g, "") : "";
|
|
839
1037
|
const keyframeNameMap = /* @__PURE__ */ new Map();
|
|
840
1038
|
if (safeScopeClass) {
|
|
@@ -847,7 +1045,13 @@ function sanitizeCSS(css, scopeClass) {
|
|
|
847
1045
|
});
|
|
848
1046
|
}
|
|
849
1047
|
if (safeScopeClass && keyframeNameMap.size > 0) {
|
|
850
|
-
const ANIM_KEYWORDS = /* @__PURE__ */ new Set([
|
|
1048
|
+
const ANIM_KEYWORDS = /* @__PURE__ */ new Set([
|
|
1049
|
+
"none",
|
|
1050
|
+
"initial",
|
|
1051
|
+
"inherit",
|
|
1052
|
+
"unset",
|
|
1053
|
+
"revert"
|
|
1054
|
+
]);
|
|
851
1055
|
const replaceAnimName = (token) => {
|
|
852
1056
|
const t = token.trim().replace(/^['"]|['"]$/g, "");
|
|
853
1057
|
return ANIM_KEYWORDS.has(t) ? token : keyframeNameMap.get(t) ?? token;
|
|
@@ -863,23 +1067,24 @@ function sanitizeCSS(css, scopeClass) {
|
|
|
863
1067
|
}
|
|
864
1068
|
root.walkAtRules((node) => {
|
|
865
1069
|
if (!ALLOWED_AT_RULES.has(node.name.toLowerCase())) {
|
|
1070
|
+
stats.removedAtRules++;
|
|
866
1071
|
node.remove();
|
|
867
1072
|
}
|
|
868
1073
|
});
|
|
869
1074
|
root.walkDecls((node) => {
|
|
870
|
-
const normalizedValue =
|
|
1075
|
+
const normalizedValue = normalizeCSSEscapes(
|
|
1076
|
+
node.value.replace(/\/\*[\s\S]*?\*\//g, "")
|
|
1077
|
+
);
|
|
871
1078
|
if (BLOCKED_VALUE_PATTERNS.some((p) => p.test(normalizedValue))) {
|
|
1079
|
+
stats.removedDecls++;
|
|
872
1080
|
node.remove();
|
|
873
1081
|
return;
|
|
874
1082
|
}
|
|
875
1083
|
const propLower = node.prop.toLowerCase();
|
|
876
1084
|
const blockedValuePattern = BLOCKED_PROPERTY_VALUES[propLower];
|
|
877
1085
|
if (blockedValuePattern) {
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
(_, hex) => String.fromCodePoint(parseInt(hex, 16))
|
|
881
|
-
);
|
|
882
|
-
if (blockedValuePattern.test(deescaped)) {
|
|
1086
|
+
if (blockedValuePattern.test(normalizedValue)) {
|
|
1087
|
+
stats.removedDecls++;
|
|
883
1088
|
node.remove();
|
|
884
1089
|
return;
|
|
885
1090
|
}
|
|
@@ -890,6 +1095,7 @@ function sanitizeCSS(css, scopeClass) {
|
|
|
890
1095
|
} else {
|
|
891
1096
|
const val = parseInt(zv, 10);
|
|
892
1097
|
if (isNaN(val) || String(val) !== zv || val > Z_INDEX_MAX) {
|
|
1098
|
+
stats.removedDecls++;
|
|
893
1099
|
node.remove();
|
|
894
1100
|
return;
|
|
895
1101
|
}
|
|
@@ -897,13 +1103,21 @@ function sanitizeCSS(css, scopeClass) {
|
|
|
897
1103
|
}
|
|
898
1104
|
});
|
|
899
1105
|
root.walkRules((rule) => {
|
|
900
|
-
|
|
901
|
-
|
|
1106
|
+
const safeSelectors = rule.selectors.filter(
|
|
1107
|
+
(s) => s.trim() && !DANGEROUS_SELECTOR.test(s)
|
|
1108
|
+
);
|
|
1109
|
+
if (!safeSelectors.length) {
|
|
1110
|
+
stats.removedRules++;
|
|
902
1111
|
rule.remove();
|
|
903
1112
|
return;
|
|
904
1113
|
}
|
|
1114
|
+
if (safeSelectors.length !== rule.selectors.length) {
|
|
1115
|
+
stats.removedRules++;
|
|
1116
|
+
}
|
|
1117
|
+
rule.selectors = safeSelectors;
|
|
905
1118
|
if (scopeClass) {
|
|
906
1119
|
if (!safeScopeClass) {
|
|
1120
|
+
stats.removedRules++;
|
|
907
1121
|
rule.remove();
|
|
908
1122
|
return;
|
|
909
1123
|
}
|
|
@@ -914,7 +1128,34 @@ function sanitizeCSS(css, scopeClass) {
|
|
|
914
1128
|
rule.selectors = rule.selectors.map((sel) => `.${safeScopeClass} ${sel}`);
|
|
915
1129
|
}
|
|
916
1130
|
});
|
|
917
|
-
|
|
1131
|
+
stats.css = root.toString().replace(/<\/style/gi, "<\\/style");
|
|
1132
|
+
return stats;
|
|
1133
|
+
}
|
|
1134
|
+
function validateTenantCSS(css) {
|
|
1135
|
+
const trimmed = css.trim();
|
|
1136
|
+
if (!trimmed) return null;
|
|
1137
|
+
const deescapedCSS = normalizeCSSEscapes(css);
|
|
1138
|
+
for (const { pattern, label } of TENANT_CSS_BLOCKED_PATTERNS) {
|
|
1139
|
+
if (pattern.test(deescapedCSS)) {
|
|
1140
|
+
return `CSS contains blocked pattern: ${label}`;
|
|
1141
|
+
}
|
|
1142
|
+
}
|
|
1143
|
+
try {
|
|
1144
|
+
postcss.parse(css);
|
|
1145
|
+
} catch {
|
|
1146
|
+
return "CSS parse error";
|
|
1147
|
+
}
|
|
1148
|
+
const sanitized = sanitizeCSSWithStats(
|
|
1149
|
+
css,
|
|
1150
|
+
"flow-node--tenant-css-validation"
|
|
1151
|
+
);
|
|
1152
|
+
if (!sanitized.css.trim()) {
|
|
1153
|
+
return "CSS must contain safe rules";
|
|
1154
|
+
}
|
|
1155
|
+
if (sanitized.removedRules > 0 || sanitized.removedDecls > 0 || sanitized.removedAtRules > 0) {
|
|
1156
|
+
return "CSS contains unsafe rules or selectors";
|
|
1157
|
+
}
|
|
1158
|
+
return null;
|
|
918
1159
|
}
|
|
919
1160
|
|
|
920
1161
|
// src/ui/Canvas/CanvasRenderer.tsx
|
|
@@ -929,169 +1170,6 @@ import {
|
|
|
929
1170
|
|
|
930
1171
|
// src/ui/Canvas/node-types-factory.tsx
|
|
931
1172
|
import React4 from "react";
|
|
932
|
-
|
|
933
|
-
// src/ui/Image/index.tsx
|
|
934
|
-
import React3, { useCallback, useRef, useState } from "react";
|
|
935
|
-
|
|
936
|
-
// src/utils/image.ts
|
|
937
|
-
var IMAGE_SIZES = [384, 768, 1536];
|
|
938
|
-
function getImageSrcSet(image) {
|
|
939
|
-
const parts = [];
|
|
940
|
-
const sizes = image.sizes;
|
|
941
|
-
if (sizes) {
|
|
942
|
-
for (const size of IMAGE_SIZES) {
|
|
943
|
-
const entry = sizes[String(size)];
|
|
944
|
-
if (entry?.url && entry.width) {
|
|
945
|
-
parts.push(`${entry.url} ${entry.width}w`);
|
|
946
|
-
}
|
|
947
|
-
}
|
|
948
|
-
}
|
|
949
|
-
if (image.url && image.width) {
|
|
950
|
-
parts.push(`${image.url} ${image.width}w`);
|
|
951
|
-
}
|
|
952
|
-
return parts.join(", ");
|
|
953
|
-
}
|
|
954
|
-
function getImagePlaceholderStyle(image, options) {
|
|
955
|
-
const type = options?.type ?? "blur";
|
|
956
|
-
const paletteColor = options?.paletteColor ?? "muted";
|
|
957
|
-
if (type === "none") return {};
|
|
958
|
-
const color = image.palette?.[paletteColor];
|
|
959
|
-
if (type === "blur") {
|
|
960
|
-
const lqip = image.lqip;
|
|
961
|
-
if (lqip) {
|
|
962
|
-
return {
|
|
963
|
-
backgroundImage: `url(${lqip})`,
|
|
964
|
-
backgroundSize: "cover",
|
|
965
|
-
backgroundPosition: "center"
|
|
966
|
-
};
|
|
967
|
-
}
|
|
968
|
-
if (color) {
|
|
969
|
-
return { backgroundColor: color };
|
|
970
|
-
}
|
|
971
|
-
return {};
|
|
972
|
-
}
|
|
973
|
-
if (color) {
|
|
974
|
-
return { backgroundColor: color };
|
|
975
|
-
}
|
|
976
|
-
return {};
|
|
977
|
-
}
|
|
978
|
-
|
|
979
|
-
// src/ui/Image/index.tsx
|
|
980
|
-
function Image({
|
|
981
|
-
image,
|
|
982
|
-
width,
|
|
983
|
-
dpr = 1,
|
|
984
|
-
placeholder: placeholderProp,
|
|
985
|
-
className,
|
|
986
|
-
style,
|
|
987
|
-
imgClassName,
|
|
988
|
-
imgStyle,
|
|
989
|
-
sizes,
|
|
990
|
-
loading: loadingProp,
|
|
991
|
-
onLoad,
|
|
992
|
-
objectFit = "cover",
|
|
993
|
-
priority = false,
|
|
994
|
-
fill = false,
|
|
995
|
-
imageRendering,
|
|
996
|
-
alt: altProp
|
|
997
|
-
}) {
|
|
998
|
-
const [loaded, setLoaded] = useState(false);
|
|
999
|
-
const firedRef = useRef(false);
|
|
1000
|
-
const isPixelRendering = imageRendering === "pixelated" || imageRendering === "crisp-edges";
|
|
1001
|
-
const placeholder = placeholderProp ?? (isPixelRendering ? "none" : "blur");
|
|
1002
|
-
const loading = priority ? "eager" : loadingProp ?? "lazy";
|
|
1003
|
-
const aspectRatio = !fill && image.width && image.height ? `${image.width} / ${image.height}` : void 0;
|
|
1004
|
-
const srcSet = getImageSrcSet(image);
|
|
1005
|
-
const src = image.url ?? void 0;
|
|
1006
|
-
const hasLqip = placeholder === "blur" && !!image.lqip;
|
|
1007
|
-
const placeholderStyle = getImagePlaceholderStyle(image, {
|
|
1008
|
-
type: placeholder
|
|
1009
|
-
});
|
|
1010
|
-
const placeholderColor = !hasLqip && "backgroundColor" in placeholderStyle ? placeholderStyle.backgroundColor : void 0;
|
|
1011
|
-
const fireLoad = useCallback(() => {
|
|
1012
|
-
if (firedRef.current) return;
|
|
1013
|
-
firedRef.current = true;
|
|
1014
|
-
setLoaded(true);
|
|
1015
|
-
onLoad?.();
|
|
1016
|
-
}, [onLoad]);
|
|
1017
|
-
const imgRef = useCallback(
|
|
1018
|
-
(node) => {
|
|
1019
|
-
if (node && node.complete && node.naturalWidth > 0) {
|
|
1020
|
-
fireLoad();
|
|
1021
|
-
}
|
|
1022
|
-
},
|
|
1023
|
-
[fireLoad]
|
|
1024
|
-
);
|
|
1025
|
-
const containerStyle = {
|
|
1026
|
-
position: "relative",
|
|
1027
|
-
overflow: "hidden",
|
|
1028
|
-
...fill ? { width: "100%", height: "100%" } : {},
|
|
1029
|
-
...aspectRatio ? { aspectRatio } : {},
|
|
1030
|
-
...style
|
|
1031
|
-
};
|
|
1032
|
-
const overlayBase = {
|
|
1033
|
-
position: "absolute",
|
|
1034
|
-
top: 0,
|
|
1035
|
-
left: 0,
|
|
1036
|
-
width: "100%",
|
|
1037
|
-
height: "100%",
|
|
1038
|
-
opacity: loaded ? 0 : 1,
|
|
1039
|
-
transition: "opacity 0.3s ease",
|
|
1040
|
-
pointerEvents: "none"
|
|
1041
|
-
};
|
|
1042
|
-
const mainImgStyle = {
|
|
1043
|
-
display: "block",
|
|
1044
|
-
width: "100%",
|
|
1045
|
-
height: "100%",
|
|
1046
|
-
objectFit,
|
|
1047
|
-
...imageRendering ? { imageRendering } : {},
|
|
1048
|
-
opacity: loaded ? 1 : 0,
|
|
1049
|
-
transition: "opacity 0.3s ease",
|
|
1050
|
-
...imgStyle
|
|
1051
|
-
};
|
|
1052
|
-
return /* @__PURE__ */ React3.createElement("div", { className, style: containerStyle }, hasLqip && /* @__PURE__ */ React3.createElement(
|
|
1053
|
-
"img",
|
|
1054
|
-
{
|
|
1055
|
-
"aria-hidden": true,
|
|
1056
|
-
alt: "",
|
|
1057
|
-
src: image.lqip,
|
|
1058
|
-
style: {
|
|
1059
|
-
...overlayBase,
|
|
1060
|
-
display: "block",
|
|
1061
|
-
objectFit,
|
|
1062
|
-
filter: "blur(20px)",
|
|
1063
|
-
transform: "scale(1.1)"
|
|
1064
|
-
}
|
|
1065
|
-
}
|
|
1066
|
-
), placeholderColor && /* @__PURE__ */ React3.createElement(
|
|
1067
|
-
"div",
|
|
1068
|
-
{
|
|
1069
|
-
"aria-hidden": true,
|
|
1070
|
-
style: {
|
|
1071
|
-
...overlayBase,
|
|
1072
|
-
backgroundColor: placeholderColor
|
|
1073
|
-
}
|
|
1074
|
-
}
|
|
1075
|
-
), /* @__PURE__ */ React3.createElement(
|
|
1076
|
-
"img",
|
|
1077
|
-
{
|
|
1078
|
-
ref: imgRef,
|
|
1079
|
-
alt: altProp ?? image.alt ?? "",
|
|
1080
|
-
src,
|
|
1081
|
-
srcSet: srcSet || void 0,
|
|
1082
|
-
sizes,
|
|
1083
|
-
width: width ? width * dpr : void 0,
|
|
1084
|
-
loading,
|
|
1085
|
-
decoding: "async",
|
|
1086
|
-
fetchPriority: priority ? "high" : void 0,
|
|
1087
|
-
onLoad: fireLoad,
|
|
1088
|
-
className: imgClassName,
|
|
1089
|
-
style: mainImgStyle
|
|
1090
|
-
}
|
|
1091
|
-
));
|
|
1092
|
-
}
|
|
1093
|
-
|
|
1094
|
-
// src/ui/Canvas/node-types-factory.tsx
|
|
1095
1173
|
function createNodeTypes(nodeRenderers, nodeTypeDefsMap, frameRenderer, nodeWrapper, renderNode) {
|
|
1096
1174
|
const types = {};
|
|
1097
1175
|
types.dynamic = ((props) => {
|
|
@@ -1121,22 +1199,6 @@ function createNodeTypes(nodeRenderers, nodeTypeDefsMap, frameRenderer, nodeWrap
|
|
|
1121
1199
|
let content;
|
|
1122
1200
|
if (CustomRenderer) {
|
|
1123
1201
|
content = /* @__PURE__ */ React4.createElement(CustomRenderer, { ...slotProps });
|
|
1124
|
-
} else if (d.nodeTypeSlug === "image") {
|
|
1125
|
-
const imageVal = d.fields?.image;
|
|
1126
|
-
if (imageVal && typeof imageVal === "object" && "url" in imageVal) {
|
|
1127
|
-
content = /* @__PURE__ */ React4.createElement(
|
|
1128
|
-
Image,
|
|
1129
|
-
{
|
|
1130
|
-
image: imageVal,
|
|
1131
|
-
width: props.width,
|
|
1132
|
-
fill: true,
|
|
1133
|
-
priority: true,
|
|
1134
|
-
objectFit: "contain"
|
|
1135
|
-
}
|
|
1136
|
-
);
|
|
1137
|
-
} else {
|
|
1138
|
-
content = defaultRender;
|
|
1139
|
-
}
|
|
1140
1202
|
} else {
|
|
1141
1203
|
content = defaultRender;
|
|
1142
1204
|
}
|
|
@@ -1621,8 +1683,6 @@ function CanvasFrame({
|
|
|
1621
1683
|
);
|
|
1622
1684
|
}
|
|
1623
1685
|
export {
|
|
1624
|
-
BUILT_IN_EDGE_TYPES,
|
|
1625
|
-
BUILT_IN_NODE_TYPES,
|
|
1626
1686
|
CanvasFrame,
|
|
1627
1687
|
CanvasRenderer,
|
|
1628
1688
|
clearTemplateCache,
|
|
@@ -1639,8 +1699,11 @@ export {
|
|
|
1639
1699
|
prefetchCanvas,
|
|
1640
1700
|
renderFieldValue,
|
|
1641
1701
|
sanitizeCSS,
|
|
1702
|
+
toEdgeTypeDef,
|
|
1703
|
+
toNodeTypeDef,
|
|
1642
1704
|
useCanvas,
|
|
1643
1705
|
useCanvasData,
|
|
1644
|
-
useQuickJS
|
|
1706
|
+
useQuickJS,
|
|
1707
|
+
validateTenantCSS
|
|
1645
1708
|
};
|
|
1646
1709
|
//# sourceMappingURL=canvas.js.map
|