@01.software/sdk 0.5.2 → 0.5.4
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/dist/auth.d.cts +1 -1
- package/dist/auth.d.ts +1 -1
- package/dist/{const-Cy_NaRCl.d.cts → const-C9I6r5Wa.d.cts} +1 -1
- package/dist/{const-C6vryj3j.d.ts → const-JbuUTzeh.d.ts} +1 -1
- package/dist/index.d.cts +6 -6
- package/dist/index.d.ts +6 -6
- package/dist/{payload-types-JCbsSVeL.d.cts → payload-types-D8fN_vZR.d.cts} +5 -1
- package/dist/{payload-types-JCbsSVeL.d.ts → payload-types-D8fN_vZR.d.ts} +5 -1
- package/dist/realtime.d.cts +2 -2
- package/dist/realtime.d.ts +2 -2
- package/dist/{server-B80o7igg.d.cts → server-StNHlSjW.d.cts} +5 -1
- package/dist/{server-B80o7igg.d.ts → server-StNHlSjW.d.ts} +5 -1
- package/dist/ui/code-block.cjs +5 -1
- package/dist/ui/code-block.cjs.map +1 -1
- package/dist/ui/code-block.js +5 -1
- package/dist/ui/code-block.js.map +1 -1
- package/dist/ui/flow/server.cjs +101 -34
- package/dist/ui/flow/server.cjs.map +1 -1
- package/dist/ui/flow/server.d.cts +1 -1
- package/dist/ui/flow/server.d.ts +1 -1
- package/dist/ui/flow/server.js +101 -34
- package/dist/ui/flow/server.js.map +1 -1
- package/dist/ui/flow.cjs +780 -180
- package/dist/ui/flow.cjs.map +1 -1
- package/dist/ui/flow.d.cts +77 -11
- package/dist/ui/flow.d.ts +77 -11
- package/dist/ui/flow.js +767 -167
- package/dist/ui/flow.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-Dd_7Qgaa.d.ts → webhook-BkwMrrL1.d.ts} +2 -2
- package/dist/{webhook-CDu_s44-.d.cts → webhook-Dbx-pRib.d.cts} +2 -2
- package/dist/webhook.d.cts +3 -3
- package/dist/webhook.d.ts +3 -3
- package/package.json +3 -1
package/dist/ui/flow.js
CHANGED
|
@@ -18,6 +18,18 @@ var __spreadValues = (a, b) => {
|
|
|
18
18
|
return a;
|
|
19
19
|
};
|
|
20
20
|
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
21
|
+
var __objRest = (source, exclude) => {
|
|
22
|
+
var target = {};
|
|
23
|
+
for (var prop in source)
|
|
24
|
+
if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
|
|
25
|
+
target[prop] = source[prop];
|
|
26
|
+
if (source != null && __getOwnPropSymbols)
|
|
27
|
+
for (var prop of __getOwnPropSymbols(source)) {
|
|
28
|
+
if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
|
|
29
|
+
target[prop] = source[prop];
|
|
30
|
+
}
|
|
31
|
+
return target;
|
|
32
|
+
};
|
|
21
33
|
var __async = (__this, __arguments, generator) => {
|
|
22
34
|
return new Promise((resolve, reject) => {
|
|
23
35
|
var fulfilled = (value) => {
|
|
@@ -102,6 +114,43 @@ function collectionKeys(collection) {
|
|
|
102
114
|
};
|
|
103
115
|
}
|
|
104
116
|
|
|
117
|
+
// src/ui/Flow/query-options.ts
|
|
118
|
+
function flowQueryOptions(client, slug, id) {
|
|
119
|
+
var _a;
|
|
120
|
+
const identifier = (_a = id != null ? id : slug) != null ? _a : "";
|
|
121
|
+
return {
|
|
122
|
+
queryKey: collectionKeys("flows").detail(identifier),
|
|
123
|
+
queryFn: () => __async(null, null, function* () {
|
|
124
|
+
if (id) return client.from("flows").findById(id);
|
|
125
|
+
const result = yield client.from("flows").find({
|
|
126
|
+
where: { slug: { equals: slug } },
|
|
127
|
+
limit: 1
|
|
128
|
+
});
|
|
129
|
+
const doc = result.docs[0];
|
|
130
|
+
if (!doc) throw new Error(`Flow not found: ${slug}`);
|
|
131
|
+
return doc;
|
|
132
|
+
})
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
function nodeTypesQueryOptions(client) {
|
|
136
|
+
return {
|
|
137
|
+
queryKey: collectionKeys("flow-node-types").lists(),
|
|
138
|
+
queryFn: () => __async(null, null, function* () {
|
|
139
|
+
const result = yield client.from("flow-node-types").find({ limit: 0 });
|
|
140
|
+
return result.docs;
|
|
141
|
+
})
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
function edgeTypesQueryOptions(client) {
|
|
145
|
+
return {
|
|
146
|
+
queryKey: collectionKeys("flow-edge-types").lists(),
|
|
147
|
+
queryFn: () => __async(null, null, function* () {
|
|
148
|
+
const result = yield client.from("flow-edge-types").find({ limit: 0 });
|
|
149
|
+
return result.docs;
|
|
150
|
+
})
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
|
|
105
154
|
// src/ui/Flow/useFlow.ts
|
|
106
155
|
function toNodeTypeDef(doc) {
|
|
107
156
|
var _a, _b, _c, _d, _e, _f;
|
|
@@ -134,49 +183,25 @@ function toEdgeTypeDef(doc) {
|
|
|
134
183
|
};
|
|
135
184
|
}
|
|
136
185
|
function useFlow(options) {
|
|
137
|
-
var _a, _b
|
|
186
|
+
var _a, _b;
|
|
138
187
|
const { client, slug, id, enabled = true } = options;
|
|
139
188
|
const hasIdentifier = !!(slug || id);
|
|
140
|
-
const identifier = (_a = id != null ? id : slug) != null ? _a : "";
|
|
141
189
|
const flowQuery = useQuery(
|
|
142
|
-
{
|
|
143
|
-
queryKey: collectionKeys("flows").detail(identifier),
|
|
144
|
-
queryFn: () => __async(null, null, function* () {
|
|
145
|
-
if (id) {
|
|
146
|
-
return client.from("flows").findById(id);
|
|
147
|
-
}
|
|
148
|
-
const result = yield client.from("flows").find({
|
|
149
|
-
where: { slug: { equals: slug } },
|
|
150
|
-
limit: 1
|
|
151
|
-
});
|
|
152
|
-
const doc = result.docs[0];
|
|
153
|
-
if (!doc) throw new Error(`Flow not found: ${slug}`);
|
|
154
|
-
return doc;
|
|
155
|
-
}),
|
|
190
|
+
__spreadProps(__spreadValues({}, flowQueryOptions(client, slug, id)), {
|
|
156
191
|
enabled: enabled && hasIdentifier
|
|
157
|
-
},
|
|
192
|
+
}),
|
|
158
193
|
client.queryClient
|
|
159
194
|
);
|
|
160
195
|
const nodeTypesQuery = useQuery(
|
|
161
|
-
{
|
|
162
|
-
queryKey: collectionKeys("flow-node-types").lists(),
|
|
163
|
-
queryFn: () => __async(null, null, function* () {
|
|
164
|
-
const result = yield client.from("flow-node-types").find({ limit: 100 });
|
|
165
|
-
return result.docs;
|
|
166
|
-
}),
|
|
196
|
+
__spreadProps(__spreadValues({}, nodeTypesQueryOptions(client)), {
|
|
167
197
|
enabled
|
|
168
|
-
},
|
|
198
|
+
}),
|
|
169
199
|
client.queryClient
|
|
170
200
|
);
|
|
171
201
|
const edgeTypesQuery = useQuery(
|
|
172
|
-
{
|
|
173
|
-
queryKey: collectionKeys("flow-edge-types").lists(),
|
|
174
|
-
queryFn: () => __async(null, null, function* () {
|
|
175
|
-
const result = yield client.from("flow-edge-types").find({ limit: 100 });
|
|
176
|
-
return result.docs;
|
|
177
|
-
}),
|
|
202
|
+
__spreadProps(__spreadValues({}, edgeTypesQueryOptions(client)), {
|
|
178
203
|
enabled
|
|
179
|
-
},
|
|
204
|
+
}),
|
|
180
205
|
client.queryClient
|
|
181
206
|
);
|
|
182
207
|
const nodeTypeDefs = useMemo(() => {
|
|
@@ -201,44 +226,21 @@ function useFlow(options) {
|
|
|
201
226
|
edgeTypeDefs,
|
|
202
227
|
flow,
|
|
203
228
|
isLoading: flowQuery.isLoading || nodeTypesQuery.isLoading || edgeTypesQuery.isLoading,
|
|
204
|
-
error: (
|
|
229
|
+
error: (_b = (_a = flowQuery.error) != null ? _a : nodeTypesQuery.error) != null ? _b : edgeTypesQuery.error
|
|
205
230
|
};
|
|
206
231
|
}
|
|
207
232
|
|
|
208
233
|
// src/ui/Flow/prefetchFlow.ts
|
|
209
234
|
function prefetchFlow(options) {
|
|
210
235
|
return __async(this, null, function* () {
|
|
211
|
-
var _a;
|
|
212
236
|
const { client, slug, id } = options;
|
|
213
|
-
|
|
237
|
+
if (!slug && !id) {
|
|
238
|
+
throw new Error("prefetchFlow requires either slug or id");
|
|
239
|
+
}
|
|
214
240
|
yield Promise.all([
|
|
215
|
-
client.queryClient.prefetchQuery(
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
if (id) return client.from("flows").findById(id);
|
|
219
|
-
const result = yield client.from("flows").find({
|
|
220
|
-
where: { slug: { equals: slug } },
|
|
221
|
-
limit: 1
|
|
222
|
-
});
|
|
223
|
-
const doc = result.docs[0];
|
|
224
|
-
if (!doc) throw new Error(`Flow not found: ${slug}`);
|
|
225
|
-
return doc;
|
|
226
|
-
})
|
|
227
|
-
}),
|
|
228
|
-
client.queryClient.prefetchQuery({
|
|
229
|
-
queryKey: collectionKeys("flow-node-types").lists(),
|
|
230
|
-
queryFn: () => __async(null, null, function* () {
|
|
231
|
-
const result = yield client.from("flow-node-types").find({ limit: 100 });
|
|
232
|
-
return result.docs;
|
|
233
|
-
})
|
|
234
|
-
}),
|
|
235
|
-
client.queryClient.prefetchQuery({
|
|
236
|
-
queryKey: collectionKeys("flow-edge-types").lists(),
|
|
237
|
-
queryFn: () => __async(null, null, function* () {
|
|
238
|
-
const result = yield client.from("flow-edge-types").find({ limit: 100 });
|
|
239
|
-
return result.docs;
|
|
240
|
-
})
|
|
241
|
-
})
|
|
241
|
+
client.queryClient.prefetchQuery(flowQueryOptions(client, slug, id)),
|
|
242
|
+
client.queryClient.prefetchQuery(nodeTypesQueryOptions(client)),
|
|
243
|
+
client.queryClient.prefetchQuery(edgeTypesQueryOptions(client))
|
|
242
244
|
]);
|
|
243
245
|
});
|
|
244
246
|
}
|
|
@@ -297,15 +299,28 @@ function getAbsolutePosition(node, nodeMap) {
|
|
|
297
299
|
return { x, y };
|
|
298
300
|
}
|
|
299
301
|
function collectDescendants(nodes, rootId) {
|
|
302
|
+
const childrenMap = /* @__PURE__ */ new Map();
|
|
303
|
+
for (const n of nodes) {
|
|
304
|
+
if (n.parentId) {
|
|
305
|
+
let siblings = childrenMap.get(n.parentId);
|
|
306
|
+
if (!siblings) {
|
|
307
|
+
siblings = [];
|
|
308
|
+
childrenMap.set(n.parentId, siblings);
|
|
309
|
+
}
|
|
310
|
+
siblings.push(n.id);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
300
313
|
const result = /* @__PURE__ */ new Set([rootId]);
|
|
301
314
|
const queue = [rootId];
|
|
302
315
|
let i = 0;
|
|
303
316
|
while (i < queue.length) {
|
|
304
|
-
const
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
result.
|
|
308
|
-
|
|
317
|
+
const children = childrenMap.get(queue[i++]);
|
|
318
|
+
if (children) {
|
|
319
|
+
for (const childId of children) {
|
|
320
|
+
if (!result.has(childId)) {
|
|
321
|
+
result.add(childId);
|
|
322
|
+
queue.push(childId);
|
|
323
|
+
}
|
|
309
324
|
}
|
|
310
325
|
}
|
|
311
326
|
}
|
|
@@ -380,16 +395,76 @@ function getFrameData(data, frameId) {
|
|
|
380
395
|
// src/ui/Flow/template-compiler.ts
|
|
381
396
|
import React from "react";
|
|
382
397
|
import { transform } from "sucrase";
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
}
|
|
391
|
-
return hash.toString(36);
|
|
398
|
+
|
|
399
|
+
// src/ui/Flow/quickjs-loader.ts
|
|
400
|
+
import { useSyncExternalStore } from "react";
|
|
401
|
+
var _state = { status: "idle", module: null };
|
|
402
|
+
var _listeners = /* @__PURE__ */ new Set();
|
|
403
|
+
function _notify() {
|
|
404
|
+
_listeners.forEach((fn) => fn());
|
|
392
405
|
}
|
|
406
|
+
function subscribeQuickJS(cb) {
|
|
407
|
+
_listeners.add(cb);
|
|
408
|
+
return () => _listeners.delete(cb);
|
|
409
|
+
}
|
|
410
|
+
function getQuickJSSnapshot() {
|
|
411
|
+
return _state.module;
|
|
412
|
+
}
|
|
413
|
+
function ensureQuickJSLoaded() {
|
|
414
|
+
if (_state.status !== "idle") return;
|
|
415
|
+
_state = { status: "loading", module: null };
|
|
416
|
+
import("quickjs-emscripten").then(
|
|
417
|
+
(mod) => mod.getQuickJS()
|
|
418
|
+
).then((module) => {
|
|
419
|
+
_state = { status: "ready", module };
|
|
420
|
+
_notify();
|
|
421
|
+
}).catch(() => {
|
|
422
|
+
_state = { status: "failed", module: null };
|
|
423
|
+
_notify();
|
|
424
|
+
});
|
|
425
|
+
}
|
|
426
|
+
function useQuickJS() {
|
|
427
|
+
return useSyncExternalStore(subscribeQuickJS, getQuickJSSnapshot, () => null);
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
// src/ui/Flow/template-compiler.ts
|
|
431
|
+
var MAX_CACHE_SIZE = 100;
|
|
432
|
+
var MAX_MATERIALIZE_DEPTH = 20;
|
|
433
|
+
var ALLOWED_ELEMENTS = /* @__PURE__ */ new Set([
|
|
434
|
+
"div",
|
|
435
|
+
"span",
|
|
436
|
+
"p",
|
|
437
|
+
"h1",
|
|
438
|
+
"h2",
|
|
439
|
+
"h3",
|
|
440
|
+
"h4",
|
|
441
|
+
"h5",
|
|
442
|
+
"h6",
|
|
443
|
+
"ul",
|
|
444
|
+
"ol",
|
|
445
|
+
"li",
|
|
446
|
+
"strong",
|
|
447
|
+
"em",
|
|
448
|
+
"b",
|
|
449
|
+
"i",
|
|
450
|
+
"br",
|
|
451
|
+
"img",
|
|
452
|
+
"figure",
|
|
453
|
+
"section",
|
|
454
|
+
"table",
|
|
455
|
+
"thead",
|
|
456
|
+
"tbody",
|
|
457
|
+
"tr",
|
|
458
|
+
"th",
|
|
459
|
+
"td",
|
|
460
|
+
"pre",
|
|
461
|
+
"code",
|
|
462
|
+
"svg",
|
|
463
|
+
"path",
|
|
464
|
+
"g",
|
|
465
|
+
"circle",
|
|
466
|
+
"rect"
|
|
467
|
+
]);
|
|
393
468
|
var BLOCKED_PATTERNS = [
|
|
394
469
|
/\bdocument\s*\./,
|
|
395
470
|
/\bwindow\s*\./,
|
|
@@ -409,79 +484,217 @@ var BLOCKED_PATTERNS = [
|
|
|
409
484
|
/\bsetTimeout\s*\(/,
|
|
410
485
|
/\bsetInterval\s*\(/,
|
|
411
486
|
/\bsetImmediate\s*\(/,
|
|
412
|
-
/\brequire\s*\(
|
|
487
|
+
/\brequire\s*\(/,
|
|
488
|
+
/\bself\b/,
|
|
489
|
+
/\bconstructor\s*\.\s*constructor/,
|
|
490
|
+
/\bReflect\b/,
|
|
491
|
+
/\bProxy\b/,
|
|
492
|
+
/\b__proto__\b/
|
|
413
493
|
];
|
|
494
|
+
var VM_SETUP = `
|
|
495
|
+
var React = {
|
|
496
|
+
createElement: function(type, props) {
|
|
497
|
+
var args = Array.prototype.slice.call(arguments, 2);
|
|
498
|
+
return { $$t: 'el', type: String(type), props: props || {}, ch: args };
|
|
499
|
+
},
|
|
500
|
+
Fragment: '__frag__'
|
|
501
|
+
};
|
|
502
|
+
var exports = {};
|
|
503
|
+
var module = { exports: exports };
|
|
504
|
+
var window = undefined;
|
|
505
|
+
var document = undefined;
|
|
506
|
+
var globalThis = undefined;
|
|
507
|
+
var self = undefined;
|
|
508
|
+
var setTimeout = undefined;
|
|
509
|
+
var setInterval = undefined;
|
|
510
|
+
var setImmediate = undefined;
|
|
511
|
+
var fetch = undefined;
|
|
512
|
+
var XMLHttpRequest = undefined;
|
|
513
|
+
var navigator = undefined;
|
|
514
|
+
var location = undefined;
|
|
515
|
+
var localStorage = undefined;
|
|
516
|
+
var sessionStorage = undefined;
|
|
517
|
+
var cookie = undefined;
|
|
518
|
+
var postMessage = undefined;
|
|
519
|
+
`;
|
|
520
|
+
var rendererCache = /* @__PURE__ */ new Map();
|
|
521
|
+
function hashCode(str) {
|
|
522
|
+
let hash = 0;
|
|
523
|
+
for (let i = 0; i < str.length; i++) {
|
|
524
|
+
const char = str.charCodeAt(i);
|
|
525
|
+
hash = (hash << 5) - hash + char | 0;
|
|
526
|
+
}
|
|
527
|
+
return hash.toString(36);
|
|
528
|
+
}
|
|
414
529
|
function validateTemplateCode(code) {
|
|
415
530
|
return !BLOCKED_PATTERNS.some((pattern) => pattern.test(code));
|
|
416
531
|
}
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
532
|
+
var SAFE_DATA_URI_PREFIXES = [
|
|
533
|
+
"data:image/png;",
|
|
534
|
+
"data:image/jpeg;",
|
|
535
|
+
"data:image/gif;",
|
|
536
|
+
"data:image/webp;",
|
|
537
|
+
"data:image/avif;"
|
|
538
|
+
];
|
|
539
|
+
function isSafeUrl(value) {
|
|
540
|
+
if (typeof value !== "string") return false;
|
|
541
|
+
if (value.startsWith("/") || value.startsWith("./") || value.startsWith("../")) return true;
|
|
542
|
+
if (SAFE_DATA_URI_PREFIXES.some((p) => value.startsWith(p))) return true;
|
|
543
|
+
try {
|
|
544
|
+
const url = new URL(value);
|
|
545
|
+
return url.protocol === "http:" || url.protocol === "https:";
|
|
546
|
+
} catch (e) {
|
|
547
|
+
return false;
|
|
424
548
|
}
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
549
|
+
}
|
|
550
|
+
var BLOCKED_STYLE_PROPS = /* @__PURE__ */ new Set([
|
|
551
|
+
"backgroundImage",
|
|
552
|
+
"background",
|
|
553
|
+
"listStyleImage",
|
|
554
|
+
"content",
|
|
555
|
+
"borderImage",
|
|
556
|
+
"borderImageSource",
|
|
557
|
+
"maskImage",
|
|
558
|
+
"mask",
|
|
559
|
+
"filter",
|
|
560
|
+
"cursor"
|
|
561
|
+
]);
|
|
562
|
+
function sanitizeStyle(style) {
|
|
563
|
+
if (!style || typeof style !== "object" || Array.isArray(style)) return {};
|
|
564
|
+
const safe = {};
|
|
565
|
+
for (const [k, v] of Object.entries(style)) {
|
|
566
|
+
if (BLOCKED_STYLE_PROPS.has(k)) continue;
|
|
567
|
+
if (typeof v === "string" && /url\s*\(/i.test(v)) continue;
|
|
568
|
+
if (k === "position" && typeof v === "string" && /fixed|sticky/i.test(v)) continue;
|
|
569
|
+
if (k === "zIndex") {
|
|
570
|
+
const n = typeof v === "number" ? v : parseInt(String(v), 10);
|
|
571
|
+
if (isNaN(n) || n > 9998) continue;
|
|
572
|
+
}
|
|
573
|
+
safe[k] = v;
|
|
574
|
+
}
|
|
575
|
+
return safe;
|
|
576
|
+
}
|
|
577
|
+
function materialize(node, depth = 0) {
|
|
578
|
+
var _a;
|
|
579
|
+
if (depth > MAX_MATERIALIZE_DEPTH) return null;
|
|
580
|
+
if (node == null) return null;
|
|
581
|
+
if (typeof node === "string" || typeof node === "number") return node;
|
|
582
|
+
if (Array.isArray(node)) {
|
|
583
|
+
return React.createElement(
|
|
584
|
+
React.Fragment,
|
|
585
|
+
null,
|
|
586
|
+
...node.map((c) => materialize(c, depth + 1))
|
|
587
|
+
);
|
|
588
|
+
}
|
|
589
|
+
if (typeof node !== "object") return null;
|
|
590
|
+
const d = node;
|
|
591
|
+
if (d.$$t === "frag") {
|
|
592
|
+
const ch = Array.isArray(d.ch) ? d.ch : [];
|
|
593
|
+
return React.createElement(
|
|
594
|
+
React.Fragment,
|
|
595
|
+
null,
|
|
596
|
+
...ch.map((c) => materialize(c, depth + 1))
|
|
597
|
+
);
|
|
598
|
+
}
|
|
599
|
+
if (d.$$t === "el") {
|
|
600
|
+
const type = String((_a = d.type) != null ? _a : "");
|
|
601
|
+
const props = d.props && typeof d.props === "object" ? d.props : {};
|
|
602
|
+
const ch = Array.isArray(d.ch) ? d.ch : [];
|
|
603
|
+
if (!ALLOWED_ELEMENTS.has(type.toLowerCase())) return null;
|
|
604
|
+
const safeProps = {};
|
|
605
|
+
for (const [k, v] of Object.entries(props)) {
|
|
606
|
+
if (k.startsWith("on")) continue;
|
|
607
|
+
if (k === "dangerouslySetInnerHTML" || k === "ref") continue;
|
|
608
|
+
if ((k === "src" || k === "href") && !isSafeUrl(v)) continue;
|
|
609
|
+
if (k === "style") {
|
|
610
|
+
safeProps[k] = sanitizeStyle(v);
|
|
611
|
+
continue;
|
|
612
|
+
}
|
|
613
|
+
safeProps[k] = v;
|
|
614
|
+
}
|
|
615
|
+
const children = ch.map((c) => materialize(c, depth + 1));
|
|
616
|
+
return React.createElement(type, safeProps, ...children);
|
|
617
|
+
}
|
|
618
|
+
return null;
|
|
619
|
+
}
|
|
620
|
+
function evalInContext(vm, code) {
|
|
621
|
+
const result = vm.evalCode(code);
|
|
622
|
+
if (result.error) {
|
|
623
|
+
result.error.dispose();
|
|
624
|
+
return { ok: false };
|
|
428
625
|
}
|
|
626
|
+
return { ok: true, handle: result.value };
|
|
627
|
+
}
|
|
628
|
+
var MAX_VM_CYCLES = 2e5;
|
|
629
|
+
function makeRenderer(jsCode) {
|
|
630
|
+
return function runInQuickJS(qjs, props) {
|
|
631
|
+
const vm = qjs.newContext();
|
|
632
|
+
let cycles = 0;
|
|
633
|
+
vm.runtime.setInterruptHandler(() => {
|
|
634
|
+
cycles++;
|
|
635
|
+
return cycles > MAX_VM_CYCLES;
|
|
636
|
+
});
|
|
637
|
+
try {
|
|
638
|
+
const setupResult = evalInContext(vm, VM_SETUP + jsCode);
|
|
639
|
+
if (!setupResult.ok) return null;
|
|
640
|
+
setupResult.handle.dispose();
|
|
641
|
+
const propsJson = JSON.stringify(props);
|
|
642
|
+
const callCode = `(function(){var __c=module.exports.default||module.exports;return JSON.stringify(__c(${propsJson}));})();`;
|
|
643
|
+
const callResult = evalInContext(vm, callCode);
|
|
644
|
+
if (!callResult.ok) return null;
|
|
645
|
+
const raw = vm.dump(callResult.handle);
|
|
646
|
+
callResult.handle.dispose();
|
|
647
|
+
return materialize(JSON.parse(String(raw)));
|
|
648
|
+
} catch (e) {
|
|
649
|
+
return null;
|
|
650
|
+
} finally {
|
|
651
|
+
vm.dispose();
|
|
652
|
+
}
|
|
653
|
+
};
|
|
654
|
+
}
|
|
655
|
+
function makeReactFC(renderer, qjs) {
|
|
656
|
+
return function QuickJSTemplateComponent(props) {
|
|
657
|
+
var _a;
|
|
658
|
+
return (_a = renderer(qjs, props)) != null ? _a : null;
|
|
659
|
+
};
|
|
660
|
+
}
|
|
661
|
+
function compileTemplate(code, slug) {
|
|
662
|
+
ensureQuickJSLoaded();
|
|
663
|
+
if (!validateTemplateCode(code)) return null;
|
|
664
|
+
const qjs = getQuickJSSnapshot();
|
|
665
|
+
if (!qjs) return null;
|
|
666
|
+
const cacheKey = `${slug}:${code.length}:${hashCode(code)}`;
|
|
667
|
+
if (rendererCache.has(cacheKey)) {
|
|
668
|
+
const entry = rendererCache.get(cacheKey);
|
|
669
|
+
rendererCache.delete(cacheKey);
|
|
670
|
+
rendererCache.set(cacheKey, entry);
|
|
671
|
+
return entry.fc;
|
|
672
|
+
}
|
|
673
|
+
let jsCode;
|
|
429
674
|
try {
|
|
430
|
-
const
|
|
675
|
+
const result = transform(code, {
|
|
431
676
|
transforms: ["typescript", "jsx", "imports"],
|
|
432
677
|
jsxRuntime: "classic",
|
|
433
678
|
jsxPragma: "React.createElement",
|
|
434
679
|
jsxFragmentPragma: "React.Fragment"
|
|
435
680
|
});
|
|
436
|
-
|
|
437
|
-
"React",
|
|
438
|
-
`
|
|
439
|
-
var window = undefined;
|
|
440
|
-
var document = undefined;
|
|
441
|
-
var globalThis = undefined;
|
|
442
|
-
var setTimeout = undefined;
|
|
443
|
-
var setInterval = undefined;
|
|
444
|
-
var setImmediate = undefined;
|
|
445
|
-
var fetch = undefined;
|
|
446
|
-
var XMLHttpRequest = undefined;
|
|
447
|
-
var navigator = undefined;
|
|
448
|
-
var location = undefined;
|
|
449
|
-
var exports = {};
|
|
450
|
-
var module = { exports: exports };
|
|
451
|
-
${jsCode}
|
|
452
|
-
return module.exports.default || module.exports;
|
|
453
|
-
`
|
|
454
|
-
);
|
|
455
|
-
const Component = factory(React);
|
|
456
|
-
if (typeof Component !== "function") return null;
|
|
457
|
-
if (componentCache.size >= MAX_CACHE_SIZE) {
|
|
458
|
-
const oldestKey = componentCache.keys().next().value;
|
|
459
|
-
if (oldestKey) componentCache.delete(oldestKey);
|
|
460
|
-
}
|
|
461
|
-
componentCache.set(cacheKey, Component);
|
|
462
|
-
return Component;
|
|
681
|
+
jsCode = result.code;
|
|
463
682
|
} catch (e) {
|
|
464
|
-
console.warn(`[flow] Failed to compile template for "${slug}":`, e);
|
|
465
683
|
return null;
|
|
466
684
|
}
|
|
685
|
+
const renderer = makeRenderer(jsCode);
|
|
686
|
+
const fc = makeReactFC(renderer, qjs);
|
|
687
|
+
if (rendererCache.size >= MAX_CACHE_SIZE) {
|
|
688
|
+
const oldest = rendererCache.keys().next().value;
|
|
689
|
+
if (oldest) rendererCache.delete(oldest);
|
|
690
|
+
}
|
|
691
|
+
rendererCache.set(cacheKey, { renderer, fc });
|
|
692
|
+
return fc;
|
|
467
693
|
}
|
|
468
694
|
function clearTemplateCache() {
|
|
469
|
-
|
|
695
|
+
rendererCache.clear();
|
|
470
696
|
}
|
|
471
697
|
|
|
472
|
-
// src/ui/Flow/FlowRenderer.tsx
|
|
473
|
-
import React5 from "react";
|
|
474
|
-
import {
|
|
475
|
-
ReactFlow,
|
|
476
|
-
ReactFlowProvider,
|
|
477
|
-
Background,
|
|
478
|
-
Controls,
|
|
479
|
-
MiniMap
|
|
480
|
-
} from "@xyflow/react";
|
|
481
|
-
|
|
482
|
-
// src/ui/Flow/node-types-factory.tsx
|
|
483
|
-
import React3 from "react";
|
|
484
|
-
|
|
485
698
|
// src/ui/Flow/node-renderers.tsx
|
|
486
699
|
import React2 from "react";
|
|
487
700
|
function sanitizeUrl(url) {
|
|
@@ -557,7 +770,7 @@ var TemplateErrorBoundary = class extends React2.Component {
|
|
|
557
770
|
}
|
|
558
771
|
render() {
|
|
559
772
|
if (this.state.error) {
|
|
560
|
-
return /* @__PURE__ */ React2.createElement("div", { style: { padding: 8, fontSize: 11, color: "#ef4444" } }, /* @__PURE__ */ React2.createElement("strong", null, "Render error"), /* @__PURE__ */ React2.createElement("pre", { style: { fontSize: 10, whiteSpace: "pre-wrap" } }, this.state.error.message));
|
|
773
|
+
return /* @__PURE__ */ React2.createElement("div", { style: { padding: 8, fontSize: 11, color: "#ef4444" } }, /* @__PURE__ */ React2.createElement("strong", null, "Render error"), /* @__PURE__ */ React2.createElement("pre", { style: { fontSize: 10, whiteSpace: "pre-wrap" } }, process.env.NODE_ENV === "development" ? this.state.error.message : "Template render failed"));
|
|
561
774
|
}
|
|
562
775
|
return this.props.children;
|
|
563
776
|
}
|
|
@@ -568,6 +781,7 @@ function EnhancedDynamicNode({
|
|
|
568
781
|
width,
|
|
569
782
|
height
|
|
570
783
|
}) {
|
|
784
|
+
useQuickJS();
|
|
571
785
|
if (typeDef.template) {
|
|
572
786
|
const Component = compileTemplate(typeDef.template, typeDef.slug);
|
|
573
787
|
if (Component) {
|
|
@@ -594,6 +808,7 @@ function EnhancedDynamicNode({
|
|
|
594
808
|
return /* @__PURE__ */ React2.createElement(
|
|
595
809
|
"div",
|
|
596
810
|
{
|
|
811
|
+
className: `flow-node flow-node--${typeDef.slug}`,
|
|
597
812
|
style: {
|
|
598
813
|
width: "100%",
|
|
599
814
|
height: "100%",
|
|
@@ -646,14 +861,304 @@ function DefaultFrameNode({ data }) {
|
|
|
646
861
|
);
|
|
647
862
|
}
|
|
648
863
|
|
|
864
|
+
// src/ui/Flow/field-helpers.ts
|
|
865
|
+
function getImageField(fields, name) {
|
|
866
|
+
const val = fields == null ? void 0 : fields[name];
|
|
867
|
+
if (val && typeof val === "object" && val !== null && "url" in val)
|
|
868
|
+
return val;
|
|
869
|
+
return void 0;
|
|
870
|
+
}
|
|
871
|
+
function getTextField(fields, name) {
|
|
872
|
+
const val = fields == null ? void 0 : fields[name];
|
|
873
|
+
return typeof val === "string" ? val : void 0;
|
|
874
|
+
}
|
|
875
|
+
function getNumberField(fields, name) {
|
|
876
|
+
const val = fields == null ? void 0 : fields[name];
|
|
877
|
+
return typeof val === "number" ? val : void 0;
|
|
878
|
+
}
|
|
879
|
+
function getBooleanField(fields, name) {
|
|
880
|
+
const val = fields == null ? void 0 : fields[name];
|
|
881
|
+
return typeof val === "boolean" ? val : void 0;
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
// src/ui/Flow/css-sanitizer.ts
|
|
885
|
+
import postcss from "postcss";
|
|
886
|
+
var ALLOWED_AT_RULES = /* @__PURE__ */ new Set(["keyframes", "media", "supports", "container", "layer"]);
|
|
887
|
+
var BLOCKED_VALUE_PATTERNS = [/url\s*\(/i, /expression\s*\(/i, /paint\s*\(/i, /-moz-binding/i];
|
|
888
|
+
var DANGEROUS_SELECTOR = /(?:^|[\s,])(?::root|html|body)\b/;
|
|
889
|
+
var BLOCKED_PROPERTY_VALUES = {
|
|
890
|
+
// absolute is allowed — contained by nearest positioned ancestor (node wrapper)
|
|
891
|
+
position: /fixed|sticky/i
|
|
892
|
+
};
|
|
893
|
+
var Z_INDEX_MAX = 9998;
|
|
894
|
+
function sanitizeCSS(css, scopeClass) {
|
|
895
|
+
let root;
|
|
896
|
+
try {
|
|
897
|
+
root = postcss.parse(css);
|
|
898
|
+
} catch (e) {
|
|
899
|
+
return "";
|
|
900
|
+
}
|
|
901
|
+
const safeScopeClass = scopeClass ? scopeClass.replace(/[{}()[\];,'"\\<>\s]/g, "") : "";
|
|
902
|
+
const keyframeNameMap = /* @__PURE__ */ new Map();
|
|
903
|
+
if (safeScopeClass) {
|
|
904
|
+
root.walkAtRules(/^keyframes$/i, (node) => {
|
|
905
|
+
const rawName = node.params.trim().replace(/^['"]|['"]$/g, "");
|
|
906
|
+
const originalName = rawName;
|
|
907
|
+
const scopedName = `${safeScopeClass}__${rawName.replace(/\s+/g, "_")}`;
|
|
908
|
+
keyframeNameMap.set(originalName, scopedName);
|
|
909
|
+
node.params = scopedName;
|
|
910
|
+
});
|
|
911
|
+
}
|
|
912
|
+
if (safeScopeClass && keyframeNameMap.size > 0) {
|
|
913
|
+
const ANIM_KEYWORDS = /* @__PURE__ */ new Set(["none", "initial", "inherit", "unset", "revert"]);
|
|
914
|
+
const replaceAnimName = (token) => {
|
|
915
|
+
var _a;
|
|
916
|
+
const t = token.trim().replace(/^['"]|['"]$/g, "");
|
|
917
|
+
return ANIM_KEYWORDS.has(t) ? token : (_a = keyframeNameMap.get(t)) != null ? _a : token;
|
|
918
|
+
};
|
|
919
|
+
root.walkDecls(/^animation-name$/i, (node) => {
|
|
920
|
+
node.value = node.value.split(",").map(replaceAnimName).join(", ");
|
|
921
|
+
});
|
|
922
|
+
root.walkDecls(/^animation$/i, (node) => {
|
|
923
|
+
node.value = node.value.split(",").map(
|
|
924
|
+
(anim) => anim.split(/(\s+)/).map((token) => /\s/.test(token) ? token : replaceAnimName(token)).join("")
|
|
925
|
+
).join(",");
|
|
926
|
+
});
|
|
927
|
+
}
|
|
928
|
+
root.walkAtRules((node) => {
|
|
929
|
+
if (!ALLOWED_AT_RULES.has(node.name.toLowerCase())) {
|
|
930
|
+
node.remove();
|
|
931
|
+
}
|
|
932
|
+
});
|
|
933
|
+
root.walkDecls((node) => {
|
|
934
|
+
const normalizedValue = node.value.replace(/\/\*[\s\S]*?\*\//g, "");
|
|
935
|
+
if (BLOCKED_VALUE_PATTERNS.some((p) => p.test(normalizedValue))) {
|
|
936
|
+
node.remove();
|
|
937
|
+
return;
|
|
938
|
+
}
|
|
939
|
+
const propLower = node.prop.toLowerCase();
|
|
940
|
+
const blockedValuePattern = BLOCKED_PROPERTY_VALUES[propLower];
|
|
941
|
+
if (blockedValuePattern) {
|
|
942
|
+
const deescaped = normalizedValue.replace(
|
|
943
|
+
/\\([0-9a-fA-F]{1,6})\s?/g,
|
|
944
|
+
(_, hex) => String.fromCodePoint(parseInt(hex, 16))
|
|
945
|
+
);
|
|
946
|
+
if (blockedValuePattern.test(deescaped)) {
|
|
947
|
+
node.remove();
|
|
948
|
+
return;
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
if (propLower === "z-index") {
|
|
952
|
+
const zv = node.value.trim();
|
|
953
|
+
if (zv === "auto" || zv === "initial" || zv === "inherit" || zv === "unset" || zv === "revert") {
|
|
954
|
+
} else {
|
|
955
|
+
const val = parseInt(zv, 10);
|
|
956
|
+
if (isNaN(val) || String(val) !== zv || val > Z_INDEX_MAX) {
|
|
957
|
+
node.remove();
|
|
958
|
+
return;
|
|
959
|
+
}
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
});
|
|
963
|
+
root.walkRules((rule) => {
|
|
964
|
+
rule.selectors = rule.selectors.filter((s) => !DANGEROUS_SELECTOR.test(s));
|
|
965
|
+
if (!rule.selectors.length) {
|
|
966
|
+
rule.remove();
|
|
967
|
+
return;
|
|
968
|
+
}
|
|
969
|
+
if (scopeClass) {
|
|
970
|
+
if (!safeScopeClass) {
|
|
971
|
+
rule.remove();
|
|
972
|
+
return;
|
|
973
|
+
}
|
|
974
|
+
const parent = rule.parent;
|
|
975
|
+
if ((parent == null ? void 0 : parent.type) === "atrule" && parent.name.toLowerCase() === "keyframes") {
|
|
976
|
+
return;
|
|
977
|
+
}
|
|
978
|
+
rule.selectors = rule.selectors.map((sel) => `.${safeScopeClass} ${sel}`);
|
|
979
|
+
}
|
|
980
|
+
});
|
|
981
|
+
return root.toString().replace(/<\/style/gi, "<\\/style");
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
// src/ui/Flow/FlowRenderer.tsx
|
|
985
|
+
import React6 from "react";
|
|
986
|
+
import {
|
|
987
|
+
ReactFlow,
|
|
988
|
+
ReactFlowProvider,
|
|
989
|
+
Background,
|
|
990
|
+
Controls,
|
|
991
|
+
MiniMap
|
|
992
|
+
} from "@xyflow/react";
|
|
993
|
+
|
|
994
|
+
// src/ui/Flow/node-types-factory.tsx
|
|
995
|
+
import React4 from "react";
|
|
996
|
+
|
|
997
|
+
// src/ui/Image/index.tsx
|
|
998
|
+
import React3, { useCallback, useRef, useState } from "react";
|
|
999
|
+
|
|
1000
|
+
// src/utils/image.ts
|
|
1001
|
+
var IMAGE_SIZES = [384, 768, 1536];
|
|
1002
|
+
function getImageSrcSet(image) {
|
|
1003
|
+
const parts = [];
|
|
1004
|
+
const sizes = image.sizes;
|
|
1005
|
+
if (sizes) {
|
|
1006
|
+
for (const size of IMAGE_SIZES) {
|
|
1007
|
+
const entry = sizes[String(size)];
|
|
1008
|
+
if ((entry == null ? void 0 : entry.url) && entry.width) {
|
|
1009
|
+
parts.push(`${entry.url} ${entry.width}w`);
|
|
1010
|
+
}
|
|
1011
|
+
}
|
|
1012
|
+
}
|
|
1013
|
+
if (image.url && image.width) {
|
|
1014
|
+
parts.push(`${image.url} ${image.width}w`);
|
|
1015
|
+
}
|
|
1016
|
+
return parts.join(", ");
|
|
1017
|
+
}
|
|
1018
|
+
function getImagePlaceholderStyle(image, options) {
|
|
1019
|
+
var _a, _b, _c;
|
|
1020
|
+
const type = (_a = options == null ? void 0 : options.type) != null ? _a : "blur";
|
|
1021
|
+
const paletteColor = (_b = options == null ? void 0 : options.paletteColor) != null ? _b : "muted";
|
|
1022
|
+
if (type === "none") return {};
|
|
1023
|
+
const color = (_c = image.palette) == null ? void 0 : _c[paletteColor];
|
|
1024
|
+
if (type === "blur") {
|
|
1025
|
+
const lqip = image.lqip;
|
|
1026
|
+
if (lqip) {
|
|
1027
|
+
return {
|
|
1028
|
+
backgroundImage: `url(${lqip})`,
|
|
1029
|
+
backgroundSize: "cover",
|
|
1030
|
+
backgroundPosition: "center"
|
|
1031
|
+
};
|
|
1032
|
+
}
|
|
1033
|
+
if (color) {
|
|
1034
|
+
return { backgroundColor: color };
|
|
1035
|
+
}
|
|
1036
|
+
return {};
|
|
1037
|
+
}
|
|
1038
|
+
if (color) {
|
|
1039
|
+
return { backgroundColor: color };
|
|
1040
|
+
}
|
|
1041
|
+
return {};
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
// src/ui/Image/index.tsx
|
|
1045
|
+
function Image({
|
|
1046
|
+
image,
|
|
1047
|
+
width,
|
|
1048
|
+
dpr = 1,
|
|
1049
|
+
placeholder: placeholderProp,
|
|
1050
|
+
className,
|
|
1051
|
+
style,
|
|
1052
|
+
imgClassName,
|
|
1053
|
+
imgStyle,
|
|
1054
|
+
sizes,
|
|
1055
|
+
loading: loadingProp,
|
|
1056
|
+
onLoad,
|
|
1057
|
+
objectFit = "cover",
|
|
1058
|
+
priority = false,
|
|
1059
|
+
fill = false,
|
|
1060
|
+
imageRendering
|
|
1061
|
+
}) {
|
|
1062
|
+
var _a, _b;
|
|
1063
|
+
const [loaded, setLoaded] = useState(false);
|
|
1064
|
+
const firedRef = useRef(false);
|
|
1065
|
+
const isPixelRendering = imageRendering === "pixelated" || imageRendering === "crisp-edges";
|
|
1066
|
+
const placeholder = placeholderProp != null ? placeholderProp : isPixelRendering ? "none" : "blur";
|
|
1067
|
+
const loading = priority ? "eager" : loadingProp != null ? loadingProp : "lazy";
|
|
1068
|
+
const aspectRatio = !fill && image.width && image.height ? `${image.width} / ${image.height}` : void 0;
|
|
1069
|
+
const srcSet = getImageSrcSet(image);
|
|
1070
|
+
const src = (_a = image.url) != null ? _a : void 0;
|
|
1071
|
+
const hasLqip = placeholder === "blur" && !!image.lqip;
|
|
1072
|
+
const placeholderStyle = getImagePlaceholderStyle(image, {
|
|
1073
|
+
type: placeholder
|
|
1074
|
+
});
|
|
1075
|
+
const placeholderColor = !hasLqip && "backgroundColor" in placeholderStyle ? placeholderStyle.backgroundColor : void 0;
|
|
1076
|
+
const fireLoad = useCallback(() => {
|
|
1077
|
+
if (firedRef.current) return;
|
|
1078
|
+
firedRef.current = true;
|
|
1079
|
+
setLoaded(true);
|
|
1080
|
+
onLoad == null ? void 0 : onLoad();
|
|
1081
|
+
}, [onLoad]);
|
|
1082
|
+
const imgRef = useCallback(
|
|
1083
|
+
(node) => {
|
|
1084
|
+
if (node && node.complete && node.naturalWidth > 0) {
|
|
1085
|
+
fireLoad();
|
|
1086
|
+
}
|
|
1087
|
+
},
|
|
1088
|
+
[fireLoad]
|
|
1089
|
+
);
|
|
1090
|
+
const containerStyle = __spreadValues(__spreadValues(__spreadValues({
|
|
1091
|
+
position: "relative",
|
|
1092
|
+
overflow: "hidden"
|
|
1093
|
+
}, fill ? { width: "100%", height: "100%" } : {}), aspectRatio ? { aspectRatio } : {}), style);
|
|
1094
|
+
const overlayBase = {
|
|
1095
|
+
position: "absolute",
|
|
1096
|
+
top: 0,
|
|
1097
|
+
left: 0,
|
|
1098
|
+
width: "100%",
|
|
1099
|
+
height: "100%",
|
|
1100
|
+
opacity: loaded ? 0 : 1,
|
|
1101
|
+
transition: "opacity 0.3s ease",
|
|
1102
|
+
pointerEvents: "none"
|
|
1103
|
+
};
|
|
1104
|
+
const mainImgStyle = __spreadValues(__spreadProps(__spreadValues({
|
|
1105
|
+
display: "block",
|
|
1106
|
+
width: "100%",
|
|
1107
|
+
height: "100%",
|
|
1108
|
+
objectFit
|
|
1109
|
+
}, imageRendering ? { imageRendering } : {}), {
|
|
1110
|
+
opacity: loaded ? 1 : 0,
|
|
1111
|
+
transition: "opacity 0.3s ease"
|
|
1112
|
+
}), imgStyle);
|
|
1113
|
+
return /* @__PURE__ */ React3.createElement("div", { className, style: containerStyle }, hasLqip && /* @__PURE__ */ React3.createElement(
|
|
1114
|
+
"img",
|
|
1115
|
+
{
|
|
1116
|
+
"aria-hidden": true,
|
|
1117
|
+
alt: "",
|
|
1118
|
+
src: image.lqip,
|
|
1119
|
+
style: __spreadProps(__spreadValues({}, overlayBase), {
|
|
1120
|
+
display: "block",
|
|
1121
|
+
objectFit,
|
|
1122
|
+
filter: "blur(20px)",
|
|
1123
|
+
transform: "scale(1.1)"
|
|
1124
|
+
})
|
|
1125
|
+
}
|
|
1126
|
+
), placeholderColor && /* @__PURE__ */ React3.createElement(
|
|
1127
|
+
"div",
|
|
1128
|
+
{
|
|
1129
|
+
"aria-hidden": true,
|
|
1130
|
+
style: __spreadProps(__spreadValues({}, overlayBase), {
|
|
1131
|
+
backgroundColor: placeholderColor
|
|
1132
|
+
})
|
|
1133
|
+
}
|
|
1134
|
+
), /* @__PURE__ */ React3.createElement(
|
|
1135
|
+
"img",
|
|
1136
|
+
{
|
|
1137
|
+
ref: imgRef,
|
|
1138
|
+
alt: (_b = image.alt) != null ? _b : "",
|
|
1139
|
+
src,
|
|
1140
|
+
srcSet: srcSet || void 0,
|
|
1141
|
+
sizes,
|
|
1142
|
+
width: width ? width * dpr : void 0,
|
|
1143
|
+
loading,
|
|
1144
|
+
decoding: "async",
|
|
1145
|
+
fetchPriority: priority ? "high" : void 0,
|
|
1146
|
+
onLoad: fireLoad,
|
|
1147
|
+
className: imgClassName,
|
|
1148
|
+
style: mainImgStyle
|
|
1149
|
+
}
|
|
1150
|
+
));
|
|
1151
|
+
}
|
|
1152
|
+
|
|
649
1153
|
// src/ui/Flow/node-types-factory.tsx
|
|
650
1154
|
function createNodeTypes(nodeRenderers, nodeTypeDefsMap, frameRenderer, nodeWrapper, renderNode) {
|
|
651
1155
|
const types = {};
|
|
652
1156
|
types.dynamic = ((props) => {
|
|
1157
|
+
var _a;
|
|
653
1158
|
const d = props.data;
|
|
654
1159
|
const typeDef = nodeTypeDefsMap == null ? void 0 : nodeTypeDefsMap.get(d.nodeTypeSlug);
|
|
655
1160
|
const CustomRenderer = nodeRenderers == null ? void 0 : nodeRenderers[d.nodeTypeSlug];
|
|
656
|
-
const defaultRender = typeDef ? /* @__PURE__ */
|
|
1161
|
+
const defaultRender = typeDef ? /* @__PURE__ */ React4.createElement(
|
|
657
1162
|
EnhancedDynamicNode,
|
|
658
1163
|
{
|
|
659
1164
|
data: d,
|
|
@@ -661,7 +1166,7 @@ function createNodeTypes(nodeRenderers, nodeTypeDefsMap, frameRenderer, nodeWrap
|
|
|
661
1166
|
width: props.width,
|
|
662
1167
|
height: props.height
|
|
663
1168
|
}
|
|
664
|
-
) : /* @__PURE__ */
|
|
1169
|
+
) : /* @__PURE__ */ React4.createElement(DefaultDynamicNode, __spreadValues({}, props));
|
|
665
1170
|
const slotProps = {
|
|
666
1171
|
id: props.id,
|
|
667
1172
|
nodeTypeSlug: d.nodeTypeSlug,
|
|
@@ -673,14 +1178,35 @@ function createNodeTypes(nodeRenderers, nodeTypeDefsMap, frameRenderer, nodeWrap
|
|
|
673
1178
|
height: props.height,
|
|
674
1179
|
defaultRender
|
|
675
1180
|
};
|
|
676
|
-
let content
|
|
1181
|
+
let content;
|
|
1182
|
+
if (CustomRenderer) {
|
|
1183
|
+
content = /* @__PURE__ */ React4.createElement(CustomRenderer, __spreadValues({}, slotProps));
|
|
1184
|
+
} else if (d.nodeTypeSlug === "image") {
|
|
1185
|
+
const imageVal = (_a = d.fields) == null ? void 0 : _a.image;
|
|
1186
|
+
if (imageVal && typeof imageVal === "object" && "url" in imageVal) {
|
|
1187
|
+
content = /* @__PURE__ */ React4.createElement(
|
|
1188
|
+
Image,
|
|
1189
|
+
{
|
|
1190
|
+
image: imageVal,
|
|
1191
|
+
width: props.width,
|
|
1192
|
+
fill: true,
|
|
1193
|
+
priority: true,
|
|
1194
|
+
objectFit: "contain"
|
|
1195
|
+
}
|
|
1196
|
+
);
|
|
1197
|
+
} else {
|
|
1198
|
+
content = defaultRender;
|
|
1199
|
+
}
|
|
1200
|
+
} else {
|
|
1201
|
+
content = defaultRender;
|
|
1202
|
+
}
|
|
677
1203
|
if (renderNode) {
|
|
678
1204
|
const result = renderNode(slotProps, content);
|
|
679
1205
|
if (result !== null) content = result;
|
|
680
1206
|
}
|
|
681
1207
|
if (nodeWrapper) {
|
|
682
1208
|
const Wrapper = nodeWrapper;
|
|
683
|
-
content = /* @__PURE__ */
|
|
1209
|
+
content = /* @__PURE__ */ React4.createElement(
|
|
684
1210
|
Wrapper,
|
|
685
1211
|
{
|
|
686
1212
|
id: props.id,
|
|
@@ -697,7 +1223,7 @@ function createNodeTypes(nodeRenderers, nodeTypeDefsMap, frameRenderer, nodeWrap
|
|
|
697
1223
|
types.frame = frameRenderer ? ((props) => {
|
|
698
1224
|
const d = props.data;
|
|
699
1225
|
const Renderer = frameRenderer;
|
|
700
|
-
return /* @__PURE__ */
|
|
1226
|
+
return /* @__PURE__ */ React4.createElement(
|
|
701
1227
|
Renderer,
|
|
702
1228
|
{
|
|
703
1229
|
id: props.id,
|
|
@@ -721,7 +1247,7 @@ function createEdgeTypes(edgeRenderers, edgeTypeDefsMap) {
|
|
|
721
1247
|
types[slug] = ((props) => {
|
|
722
1248
|
var _a;
|
|
723
1249
|
const def = edgeTypeDefsMap == null ? void 0 : edgeTypeDefsMap.get(slug);
|
|
724
|
-
return /* @__PURE__ */
|
|
1250
|
+
return /* @__PURE__ */ React4.createElement(
|
|
725
1251
|
Renderer,
|
|
726
1252
|
{
|
|
727
1253
|
id: props.id,
|
|
@@ -787,7 +1313,7 @@ function applyEdgeStyles(edges, edgeTypeDefsMap) {
|
|
|
787
1313
|
}
|
|
788
1314
|
|
|
789
1315
|
// src/ui/Flow/focus-handler.tsx
|
|
790
|
-
import
|
|
1316
|
+
import React5 from "react";
|
|
791
1317
|
import { useReactFlow, useStoreApi } from "@xyflow/react";
|
|
792
1318
|
function clampViewport(vp, cw, ch, extent) {
|
|
793
1319
|
const left = -vp.x / vp.zoom;
|
|
@@ -816,14 +1342,14 @@ function FocusHandler({
|
|
|
816
1342
|
}) {
|
|
817
1343
|
const { setViewport } = useReactFlow();
|
|
818
1344
|
const store = useStoreApi();
|
|
819
|
-
const containerRef =
|
|
1345
|
+
const containerRef = React5.useRef(null);
|
|
820
1346
|
const boundsKey = `${bounds.x},${bounds.y},${bounds.width},${bounds.height}`;
|
|
821
|
-
const boundsRef =
|
|
1347
|
+
const boundsRef = React5.useRef(bounds);
|
|
822
1348
|
boundsRef.current = bounds;
|
|
823
|
-
const [containerSize, setContainerSize] =
|
|
824
|
-
const prevBoundsKeyRef =
|
|
825
|
-
const prevSizeRef =
|
|
826
|
-
|
|
1349
|
+
const [containerSize, setContainerSize] = React5.useState({ w: 0, h: 0 });
|
|
1350
|
+
const prevBoundsKeyRef = React5.useRef(null);
|
|
1351
|
+
const prevSizeRef = React5.useRef({ w: 0, h: 0 });
|
|
1352
|
+
React5.useEffect(() => {
|
|
827
1353
|
const el = containerRef.current;
|
|
828
1354
|
if (!el) return;
|
|
829
1355
|
const observer = new ResizeObserver((entries) => {
|
|
@@ -835,7 +1361,7 @@ function FocusHandler({
|
|
|
835
1361
|
observer.observe(el);
|
|
836
1362
|
return () => observer.disconnect();
|
|
837
1363
|
}, []);
|
|
838
|
-
|
|
1364
|
+
React5.useEffect(() => {
|
|
839
1365
|
if (containerSize.w === 0 || containerSize.h === 0) return;
|
|
840
1366
|
const prevKey = prevBoundsKeyRef.current;
|
|
841
1367
|
const prevSize = prevSizeRef.current;
|
|
@@ -902,7 +1428,7 @@ function FocusHandler({
|
|
|
902
1428
|
store,
|
|
903
1429
|
onInitialFit
|
|
904
1430
|
]);
|
|
905
|
-
return /* @__PURE__ */
|
|
1431
|
+
return /* @__PURE__ */ React5.createElement(
|
|
906
1432
|
"div",
|
|
907
1433
|
{
|
|
908
1434
|
ref: containerRef,
|
|
@@ -917,6 +1443,7 @@ function FocusHandler({
|
|
|
917
1443
|
}
|
|
918
1444
|
|
|
919
1445
|
// src/ui/Flow/FlowRenderer.tsx
|
|
1446
|
+
var NullFrameRenderer = () => null;
|
|
920
1447
|
function FlowRenderer({
|
|
921
1448
|
data,
|
|
922
1449
|
className,
|
|
@@ -934,6 +1461,7 @@ function FlowRenderer({
|
|
|
934
1461
|
onNodeMouseLeave,
|
|
935
1462
|
onEdgeClick,
|
|
936
1463
|
frameRenderer,
|
|
1464
|
+
hideFrames = false,
|
|
937
1465
|
edgeRenderers,
|
|
938
1466
|
nodeWrapper,
|
|
939
1467
|
controls,
|
|
@@ -954,33 +1482,34 @@ function FlowRenderer({
|
|
|
954
1482
|
maxZoom: maxZoomProp
|
|
955
1483
|
}) {
|
|
956
1484
|
var _a, _b;
|
|
957
|
-
const
|
|
1485
|
+
const resolvedFrameRenderer = hideFrames ? NullFrameRenderer : frameRenderer;
|
|
1486
|
+
const nodeTypeDefsMap = React6.useMemo(() => {
|
|
958
1487
|
if (!(nodeTypeDefs == null ? void 0 : nodeTypeDefs.length)) return void 0;
|
|
959
1488
|
return new Map(nodeTypeDefs.map((d) => [d.slug, d]));
|
|
960
1489
|
}, [nodeTypeDefs]);
|
|
961
|
-
const edgeTypeDefsMap =
|
|
1490
|
+
const edgeTypeDefsMap = React6.useMemo(() => {
|
|
962
1491
|
if (!(edgeTypeDefs == null ? void 0 : edgeTypeDefs.length)) return void 0;
|
|
963
1492
|
return new Map(edgeTypeDefs.map((d) => [d.slug, d]));
|
|
964
1493
|
}, [edgeTypeDefs]);
|
|
965
|
-
const nodeTypes =
|
|
1494
|
+
const nodeTypes = React6.useMemo(
|
|
966
1495
|
() => createNodeTypes(
|
|
967
1496
|
nodeRenderers,
|
|
968
1497
|
nodeTypeDefsMap,
|
|
969
|
-
|
|
1498
|
+
resolvedFrameRenderer,
|
|
970
1499
|
nodeWrapper,
|
|
971
1500
|
renderNode
|
|
972
1501
|
),
|
|
973
|
-
[nodeRenderers, nodeTypeDefsMap,
|
|
1502
|
+
[nodeRenderers, nodeTypeDefsMap, resolvedFrameRenderer, nodeWrapper, renderNode]
|
|
974
1503
|
);
|
|
975
|
-
const customEdgeTypes =
|
|
1504
|
+
const customEdgeTypes = React6.useMemo(
|
|
976
1505
|
() => createEdgeTypes(edgeRenderers, edgeTypeDefsMap),
|
|
977
1506
|
[edgeRenderers, edgeTypeDefsMap]
|
|
978
1507
|
);
|
|
979
|
-
const mergedCSS =
|
|
1508
|
+
const mergedCSS = React6.useMemo(() => {
|
|
980
1509
|
if (!(nodeTypeDefs == null ? void 0 : nodeTypeDefs.length)) return "";
|
|
981
|
-
return nodeTypeDefs.filter((d) => d.customCSS).map((d) => d.customCSS).join("\n");
|
|
1510
|
+
return nodeTypeDefs.filter((d) => d.customCSS).map((d) => sanitizeCSS(d.customCSS, `flow-node--${d.slug}`)).join("\n");
|
|
982
1511
|
}, [nodeTypeDefs]);
|
|
983
|
-
const styledEdges =
|
|
1512
|
+
const styledEdges = React6.useMemo(() => {
|
|
984
1513
|
var _a2;
|
|
985
1514
|
let edges = applyEdgeStyles((_a2 = data == null ? void 0 : data.edges) != null ? _a2 : [], edgeTypeDefsMap);
|
|
986
1515
|
if (edgeRenderers) {
|
|
@@ -994,7 +1523,7 @@ function FlowRenderer({
|
|
|
994
1523
|
}
|
|
995
1524
|
return edges;
|
|
996
1525
|
}, [data == null ? void 0 : data.edges, edgeTypeDefsMap, edgeRenderers]);
|
|
997
|
-
const translateExtent =
|
|
1526
|
+
const translateExtent = React6.useMemo(() => {
|
|
998
1527
|
if (translateExtentProp) return translateExtentProp;
|
|
999
1528
|
const es = clampBounds != null ? clampBounds : bounds;
|
|
1000
1529
|
if (!es) return void 0;
|
|
@@ -1005,16 +1534,16 @@ function FlowRenderer({
|
|
|
1005
1534
|
];
|
|
1006
1535
|
}, [translateExtentProp, clampBounds, bounds, focusPadding]);
|
|
1007
1536
|
const boundsKey = bounds ? `${bounds.x},${bounds.y},${bounds.width},${bounds.height}` : "";
|
|
1008
|
-
const extentReadyRef =
|
|
1009
|
-
const expandedExtentRef =
|
|
1010
|
-
const prevBoundsKeyRef =
|
|
1537
|
+
const extentReadyRef = React6.useRef(false);
|
|
1538
|
+
const expandedExtentRef = React6.useRef(void 0);
|
|
1539
|
+
const prevBoundsKeyRef = React6.useRef(boundsKey);
|
|
1011
1540
|
if (prevBoundsKeyRef.current !== boundsKey) {
|
|
1012
1541
|
prevBoundsKeyRef.current = boundsKey;
|
|
1013
1542
|
extentReadyRef.current = false;
|
|
1014
1543
|
expandedExtentRef.current = void 0;
|
|
1015
1544
|
}
|
|
1016
|
-
const [, rerender] =
|
|
1017
|
-
const handleInitialFit =
|
|
1545
|
+
const [, rerender] = React6.useReducer((x) => x + 1, 0);
|
|
1546
|
+
const handleInitialFit = React6.useCallback(
|
|
1018
1547
|
(expandedExtent) => {
|
|
1019
1548
|
extentReadyRef.current = true;
|
|
1020
1549
|
expandedExtentRef.current = expandedExtent;
|
|
@@ -1025,7 +1554,7 @@ function FlowRenderer({
|
|
|
1025
1554
|
const activeExtent = !bounds || extentReadyRef.current ? (_a = expandedExtentRef.current) != null ? _a : translateExtent : void 0;
|
|
1026
1555
|
if (!data) return null;
|
|
1027
1556
|
const resolvedDefaultViewport = defaultViewportProp != null ? defaultViewportProp : !fitView && data.viewport ? data.viewport : void 0;
|
|
1028
|
-
return /* @__PURE__ */
|
|
1557
|
+
return /* @__PURE__ */ React6.createElement(ReactFlowProvider, null, /* @__PURE__ */ React6.createElement(
|
|
1029
1558
|
"div",
|
|
1030
1559
|
{
|
|
1031
1560
|
className,
|
|
@@ -1035,7 +1564,7 @@ function FlowRenderer({
|
|
|
1035
1564
|
background: "transparent"
|
|
1036
1565
|
}, style)
|
|
1037
1566
|
},
|
|
1038
|
-
/* @__PURE__ */
|
|
1567
|
+
/* @__PURE__ */ React6.createElement(
|
|
1039
1568
|
ReactFlow,
|
|
1040
1569
|
{
|
|
1041
1570
|
nodes: (_b = data.nodes) != null ? _b : [],
|
|
@@ -1065,16 +1594,16 @@ function FlowRenderer({
|
|
|
1065
1594
|
maxZoom: maxZoomProp,
|
|
1066
1595
|
proOptions: { hideAttribution: true }
|
|
1067
1596
|
},
|
|
1068
|
-
mergedCSS && /* @__PURE__ */
|
|
1069
|
-
background && /* @__PURE__ */
|
|
1070
|
-
controls && /* @__PURE__ */
|
|
1071
|
-
minimap && /* @__PURE__ */
|
|
1597
|
+
mergedCSS && /* @__PURE__ */ React6.createElement("style", { dangerouslySetInnerHTML: { __html: mergedCSS } }),
|
|
1598
|
+
background && /* @__PURE__ */ React6.createElement(Background, null),
|
|
1599
|
+
controls && /* @__PURE__ */ React6.createElement(Controls, null),
|
|
1600
|
+
minimap && /* @__PURE__ */ React6.createElement(
|
|
1072
1601
|
MiniMap,
|
|
1073
1602
|
{
|
|
1074
1603
|
nodeColor: minimapNodeColor
|
|
1075
1604
|
}
|
|
1076
1605
|
),
|
|
1077
|
-
bounds && /* @__PURE__ */
|
|
1606
|
+
bounds && /* @__PURE__ */ React6.createElement(
|
|
1078
1607
|
FocusHandler,
|
|
1079
1608
|
{
|
|
1080
1609
|
bounds,
|
|
@@ -1092,18 +1621,89 @@ function FlowRenderer({
|
|
|
1092
1621
|
)
|
|
1093
1622
|
));
|
|
1094
1623
|
}
|
|
1624
|
+
|
|
1625
|
+
// src/ui/Flow/FlowFrame.tsx
|
|
1626
|
+
import React7, { useMemo as useMemo3, useEffect, useRef as useRef2 } from "react";
|
|
1627
|
+
function FlowFrame(_a) {
|
|
1628
|
+
var _b = _a, {
|
|
1629
|
+
client,
|
|
1630
|
+
slug,
|
|
1631
|
+
id,
|
|
1632
|
+
frameId,
|
|
1633
|
+
loading = null,
|
|
1634
|
+
error: renderError,
|
|
1635
|
+
onDataReady
|
|
1636
|
+
} = _b, rendererProps = __objRest(_b, [
|
|
1637
|
+
"client",
|
|
1638
|
+
"slug",
|
|
1639
|
+
"id",
|
|
1640
|
+
"frameId",
|
|
1641
|
+
"loading",
|
|
1642
|
+
"error",
|
|
1643
|
+
"onDataReady"
|
|
1644
|
+
]);
|
|
1645
|
+
const { data, nodeTypeDefs, edgeTypeDefs, flow, isLoading, error } = useFlow({
|
|
1646
|
+
client,
|
|
1647
|
+
slug,
|
|
1648
|
+
id
|
|
1649
|
+
});
|
|
1650
|
+
const frameData = useMemo3(
|
|
1651
|
+
() => data ? getFrameData(data, frameId) : void 0,
|
|
1652
|
+
[data, frameId]
|
|
1653
|
+
);
|
|
1654
|
+
const onDataReadyRef = useRef2(onDataReady);
|
|
1655
|
+
onDataReadyRef.current = onDataReady;
|
|
1656
|
+
useEffect(() => {
|
|
1657
|
+
var _a2;
|
|
1658
|
+
if (frameData && flow) {
|
|
1659
|
+
(_a2 = onDataReadyRef.current) == null ? void 0 : _a2.call(onDataReadyRef, frameData, flow);
|
|
1660
|
+
}
|
|
1661
|
+
}, [frameData, flow]);
|
|
1662
|
+
if (process.env.NODE_ENV !== "production" && !slug && !id) {
|
|
1663
|
+
console.warn('[FlowFrame] Either "slug" or "id" must be provided.');
|
|
1664
|
+
}
|
|
1665
|
+
if (isLoading) return /* @__PURE__ */ React7.createElement(React7.Fragment, null, loading);
|
|
1666
|
+
if (error) return renderError ? /* @__PURE__ */ React7.createElement(React7.Fragment, null, renderError(error)) : null;
|
|
1667
|
+
if (!frameData) {
|
|
1668
|
+
if (process.env.NODE_ENV !== "production" && data) {
|
|
1669
|
+
const frames = data.nodes.filter(isFrameNode).map((n) => n.id);
|
|
1670
|
+
console.warn(
|
|
1671
|
+
`[FlowFrame] Frame "${frameId}" not found. Available frames: ${frames.join(", ") || "(none)"}`
|
|
1672
|
+
);
|
|
1673
|
+
}
|
|
1674
|
+
return null;
|
|
1675
|
+
}
|
|
1676
|
+
return /* @__PURE__ */ React7.createElement(
|
|
1677
|
+
FlowRenderer,
|
|
1678
|
+
__spreadProps(__spreadValues({}, rendererProps), {
|
|
1679
|
+
data: frameData.data,
|
|
1680
|
+
nodeTypeDefs,
|
|
1681
|
+
edgeTypeDefs,
|
|
1682
|
+
bounds: frameData.fitBounds,
|
|
1683
|
+
clampBounds: frameData.clampBounds,
|
|
1684
|
+
hideFrames: true
|
|
1685
|
+
})
|
|
1686
|
+
);
|
|
1687
|
+
}
|
|
1095
1688
|
export {
|
|
1096
1689
|
BUILT_IN_EDGE_TYPES,
|
|
1097
1690
|
BUILT_IN_NODE_TYPES,
|
|
1691
|
+
FlowFrame,
|
|
1098
1692
|
FlowRenderer,
|
|
1099
1693
|
clearTemplateCache,
|
|
1100
1694
|
compileTemplate,
|
|
1695
|
+
getBooleanField,
|
|
1101
1696
|
getFrameData,
|
|
1102
1697
|
getFrames,
|
|
1698
|
+
getImageField,
|
|
1103
1699
|
getNodeBounds,
|
|
1700
|
+
getNumberField,
|
|
1701
|
+
getTextField,
|
|
1104
1702
|
isDynamicNode,
|
|
1105
1703
|
isFrameNode,
|
|
1106
1704
|
prefetchFlow,
|
|
1705
|
+
renderFieldValue,
|
|
1706
|
+
sanitizeCSS,
|
|
1107
1707
|
useFlow,
|
|
1108
1708
|
useFlowData
|
|
1109
1709
|
};
|