@01.software/sdk 0.5.1 → 0.5.3
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-CDpRB7XK.d.cts → const-C9I6r5Wa.d.cts} +1 -1
- package/dist/{const-DQIDvvB-.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-C-keX5go.d.cts → payload-types-D8fN_vZR.d.cts} +17 -1
- package/dist/{payload-types-C-keX5go.d.ts → payload-types-D8fN_vZR.d.ts} +17 -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 +718 -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 +705 -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-DseJdRFT.d.ts → webhook-BkwMrrL1.d.ts} +2 -2
- package/dist/{webhook-Dqe2_xMx.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 +5 -3
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,75 @@ 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
|
-
|
|
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());
|
|
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
|
+
});
|
|
424
|
+
}
|
|
425
|
+
function useQuickJS() {
|
|
426
|
+
return useSyncExternalStore(subscribeQuickJS, getQuickJSSnapshot, () => null);
|
|
392
427
|
}
|
|
428
|
+
|
|
429
|
+
// src/ui/Flow/template-compiler.ts
|
|
430
|
+
var MAX_CACHE_SIZE = 100;
|
|
431
|
+
var MAX_MATERIALIZE_DEPTH = 20;
|
|
432
|
+
var ALLOWED_ELEMENTS = /* @__PURE__ */ new Set([
|
|
433
|
+
"div",
|
|
434
|
+
"span",
|
|
435
|
+
"p",
|
|
436
|
+
"h1",
|
|
437
|
+
"h2",
|
|
438
|
+
"h3",
|
|
439
|
+
"h4",
|
|
440
|
+
"h5",
|
|
441
|
+
"h6",
|
|
442
|
+
"ul",
|
|
443
|
+
"ol",
|
|
444
|
+
"li",
|
|
445
|
+
"strong",
|
|
446
|
+
"em",
|
|
447
|
+
"b",
|
|
448
|
+
"i",
|
|
449
|
+
"br",
|
|
450
|
+
"img",
|
|
451
|
+
"figure",
|
|
452
|
+
"section",
|
|
453
|
+
"table",
|
|
454
|
+
"thead",
|
|
455
|
+
"tbody",
|
|
456
|
+
"tr",
|
|
457
|
+
"th",
|
|
458
|
+
"td",
|
|
459
|
+
"pre",
|
|
460
|
+
"code",
|
|
461
|
+
"svg",
|
|
462
|
+
"path",
|
|
463
|
+
"g",
|
|
464
|
+
"circle",
|
|
465
|
+
"rect"
|
|
466
|
+
]);
|
|
393
467
|
var BLOCKED_PATTERNS = [
|
|
394
468
|
/\bdocument\s*\./,
|
|
395
469
|
/\bwindow\s*\./,
|
|
@@ -409,79 +483,212 @@ var BLOCKED_PATTERNS = [
|
|
|
409
483
|
/\bsetTimeout\s*\(/,
|
|
410
484
|
/\bsetInterval\s*\(/,
|
|
411
485
|
/\bsetImmediate\s*\(/,
|
|
412
|
-
/\brequire\s*\(
|
|
486
|
+
/\brequire\s*\(/,
|
|
487
|
+
/\bself\b/,
|
|
488
|
+
/\bconstructor\s*\.\s*constructor/,
|
|
489
|
+
/\bReflect\b/,
|
|
490
|
+
/\bProxy\b/,
|
|
491
|
+
/\b__proto__\b/
|
|
413
492
|
];
|
|
493
|
+
var VM_SETUP = `
|
|
494
|
+
var React = {
|
|
495
|
+
createElement: function(type, props) {
|
|
496
|
+
var args = Array.prototype.slice.call(arguments, 2);
|
|
497
|
+
return { $$t: 'el', type: String(type), props: props || {}, ch: args };
|
|
498
|
+
},
|
|
499
|
+
Fragment: '__frag__'
|
|
500
|
+
};
|
|
501
|
+
var exports = {};
|
|
502
|
+
var module = { exports: exports };
|
|
503
|
+
var window = undefined;
|
|
504
|
+
var document = undefined;
|
|
505
|
+
var globalThis = undefined;
|
|
506
|
+
var self = undefined;
|
|
507
|
+
var setTimeout = undefined;
|
|
508
|
+
var setInterval = undefined;
|
|
509
|
+
var setImmediate = undefined;
|
|
510
|
+
var fetch = undefined;
|
|
511
|
+
var XMLHttpRequest = undefined;
|
|
512
|
+
var navigator = undefined;
|
|
513
|
+
var location = undefined;
|
|
514
|
+
var localStorage = undefined;
|
|
515
|
+
var sessionStorage = undefined;
|
|
516
|
+
var cookie = undefined;
|
|
517
|
+
var postMessage = undefined;
|
|
518
|
+
`;
|
|
519
|
+
var rendererCache = /* @__PURE__ */ new Map();
|
|
520
|
+
function hashCode(str) {
|
|
521
|
+
let hash = 0;
|
|
522
|
+
for (let i = 0; i < str.length; i++) {
|
|
523
|
+
const char = str.charCodeAt(i);
|
|
524
|
+
hash = (hash << 5) - hash + char | 0;
|
|
525
|
+
}
|
|
526
|
+
return hash.toString(36);
|
|
527
|
+
}
|
|
414
528
|
function validateTemplateCode(code) {
|
|
415
529
|
return !BLOCKED_PATTERNS.some((pattern) => pattern.test(code));
|
|
416
530
|
}
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
531
|
+
var SAFE_DATA_URI_PREFIXES = [
|
|
532
|
+
"data:image/png;",
|
|
533
|
+
"data:image/jpeg;",
|
|
534
|
+
"data:image/gif;",
|
|
535
|
+
"data:image/webp;",
|
|
536
|
+
"data:image/avif;"
|
|
537
|
+
];
|
|
538
|
+
function isSafeUrl(value) {
|
|
539
|
+
if (typeof value !== "string") return false;
|
|
540
|
+
if (value.startsWith("/") || value.startsWith("./") || value.startsWith("../")) return true;
|
|
541
|
+
if (SAFE_DATA_URI_PREFIXES.some((p) => value.startsWith(p))) return true;
|
|
542
|
+
try {
|
|
543
|
+
const url = new URL(value);
|
|
544
|
+
return url.protocol === "http:" || url.protocol === "https:";
|
|
545
|
+
} catch (e) {
|
|
546
|
+
return false;
|
|
424
547
|
}
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
548
|
+
}
|
|
549
|
+
var BLOCKED_STYLE_PROPS = /* @__PURE__ */ new Set([
|
|
550
|
+
"backgroundImage",
|
|
551
|
+
"background",
|
|
552
|
+
"listStyleImage",
|
|
553
|
+
"content",
|
|
554
|
+
"borderImage",
|
|
555
|
+
"borderImageSource",
|
|
556
|
+
"maskImage",
|
|
557
|
+
"mask",
|
|
558
|
+
"filter",
|
|
559
|
+
"cursor"
|
|
560
|
+
]);
|
|
561
|
+
function sanitizeStyle(style) {
|
|
562
|
+
if (!style || typeof style !== "object" || Array.isArray(style)) return {};
|
|
563
|
+
const safe = {};
|
|
564
|
+
for (const [k, v] of Object.entries(style)) {
|
|
565
|
+
if (BLOCKED_STYLE_PROPS.has(k)) continue;
|
|
566
|
+
if (typeof v === "string" && /url\s*\(/i.test(v)) continue;
|
|
567
|
+
if (k === "position" && typeof v === "string" && /fixed|absolute/i.test(v)) continue;
|
|
568
|
+
safe[k] = v;
|
|
569
|
+
}
|
|
570
|
+
return safe;
|
|
571
|
+
}
|
|
572
|
+
function materialize(node, depth = 0) {
|
|
573
|
+
var _a;
|
|
574
|
+
if (depth > MAX_MATERIALIZE_DEPTH) return null;
|
|
575
|
+
if (node == null) return null;
|
|
576
|
+
if (typeof node === "string" || typeof node === "number") return node;
|
|
577
|
+
if (Array.isArray(node)) {
|
|
578
|
+
return React.createElement(
|
|
579
|
+
React.Fragment,
|
|
580
|
+
null,
|
|
581
|
+
...node.map((c) => materialize(c, depth + 1))
|
|
582
|
+
);
|
|
583
|
+
}
|
|
584
|
+
if (typeof node !== "object") return null;
|
|
585
|
+
const d = node;
|
|
586
|
+
if (d.$$t === "frag") {
|
|
587
|
+
const ch = Array.isArray(d.ch) ? d.ch : [];
|
|
588
|
+
return React.createElement(
|
|
589
|
+
React.Fragment,
|
|
590
|
+
null,
|
|
591
|
+
...ch.map((c) => materialize(c, depth + 1))
|
|
592
|
+
);
|
|
428
593
|
}
|
|
594
|
+
if (d.$$t === "el") {
|
|
595
|
+
const type = String((_a = d.type) != null ? _a : "");
|
|
596
|
+
const props = d.props && typeof d.props === "object" ? d.props : {};
|
|
597
|
+
const ch = Array.isArray(d.ch) ? d.ch : [];
|
|
598
|
+
if (!ALLOWED_ELEMENTS.has(type.toLowerCase())) return null;
|
|
599
|
+
const safeProps = {};
|
|
600
|
+
for (const [k, v] of Object.entries(props)) {
|
|
601
|
+
if (k.startsWith("on")) continue;
|
|
602
|
+
if (k === "dangerouslySetInnerHTML" || k === "ref") continue;
|
|
603
|
+
if ((k === "src" || k === "href") && !isSafeUrl(v)) continue;
|
|
604
|
+
if (k === "style") {
|
|
605
|
+
safeProps[k] = sanitizeStyle(v);
|
|
606
|
+
continue;
|
|
607
|
+
}
|
|
608
|
+
safeProps[k] = v;
|
|
609
|
+
}
|
|
610
|
+
const children = ch.map((c) => materialize(c, depth + 1));
|
|
611
|
+
return React.createElement(type, safeProps, ...children);
|
|
612
|
+
}
|
|
613
|
+
return null;
|
|
614
|
+
}
|
|
615
|
+
function evalInContext(vm, code) {
|
|
616
|
+
const result = vm.evalCode(code);
|
|
617
|
+
if (result.error) {
|
|
618
|
+
result.error.dispose();
|
|
619
|
+
return { ok: false };
|
|
620
|
+
}
|
|
621
|
+
return { ok: true, handle: result.value };
|
|
622
|
+
}
|
|
623
|
+
var MAX_VM_CYCLES = 2e5;
|
|
624
|
+
function makeRenderer(jsCode) {
|
|
625
|
+
return function runInQuickJS(qjs, props) {
|
|
626
|
+
const vm = qjs.newContext();
|
|
627
|
+
let cycles = 0;
|
|
628
|
+
vm.runtime.setInterruptHandler(() => {
|
|
629
|
+
cycles++;
|
|
630
|
+
return cycles > MAX_VM_CYCLES;
|
|
631
|
+
});
|
|
632
|
+
try {
|
|
633
|
+
const setupResult = evalInContext(vm, VM_SETUP + jsCode);
|
|
634
|
+
if (!setupResult.ok) return null;
|
|
635
|
+
setupResult.handle.dispose();
|
|
636
|
+
const propsJson = JSON.stringify(props);
|
|
637
|
+
const callCode = `(function(){var __c=module.exports.default||module.exports;return JSON.stringify(__c(${propsJson}));})();`;
|
|
638
|
+
const callResult = evalInContext(vm, callCode);
|
|
639
|
+
if (!callResult.ok) return null;
|
|
640
|
+
const raw = vm.dump(callResult.handle);
|
|
641
|
+
callResult.handle.dispose();
|
|
642
|
+
return materialize(JSON.parse(String(raw)));
|
|
643
|
+
} catch (e) {
|
|
644
|
+
return null;
|
|
645
|
+
} finally {
|
|
646
|
+
vm.dispose();
|
|
647
|
+
}
|
|
648
|
+
};
|
|
649
|
+
}
|
|
650
|
+
function makeReactFC(renderer, qjs) {
|
|
651
|
+
return function QuickJSTemplateComponent(props) {
|
|
652
|
+
var _a;
|
|
653
|
+
return (_a = renderer(qjs, props)) != null ? _a : null;
|
|
654
|
+
};
|
|
655
|
+
}
|
|
656
|
+
function compileTemplate(code, slug) {
|
|
657
|
+
ensureQuickJSLoaded();
|
|
658
|
+
if (!validateTemplateCode(code)) return null;
|
|
659
|
+
const qjs = getQuickJSSnapshot();
|
|
660
|
+
if (!qjs) return null;
|
|
661
|
+
const cacheKey = `${slug}:${code.length}:${hashCode(code)}`;
|
|
662
|
+
if (rendererCache.has(cacheKey)) {
|
|
663
|
+
const renderer2 = rendererCache.get(cacheKey);
|
|
664
|
+
rendererCache.delete(cacheKey);
|
|
665
|
+
rendererCache.set(cacheKey, renderer2);
|
|
666
|
+
return makeReactFC(renderer2, qjs);
|
|
667
|
+
}
|
|
668
|
+
let jsCode;
|
|
429
669
|
try {
|
|
430
|
-
const
|
|
670
|
+
const result = transform(code, {
|
|
431
671
|
transforms: ["typescript", "jsx", "imports"],
|
|
432
672
|
jsxRuntime: "classic",
|
|
433
673
|
jsxPragma: "React.createElement",
|
|
434
674
|
jsxFragmentPragma: "React.Fragment"
|
|
435
675
|
});
|
|
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;
|
|
676
|
+
jsCode = result.code;
|
|
463
677
|
} catch (e) {
|
|
464
|
-
console.warn(`[flow] Failed to compile template for "${slug}":`, e);
|
|
465
678
|
return null;
|
|
466
679
|
}
|
|
680
|
+
const renderer = makeRenderer(jsCode);
|
|
681
|
+
if (rendererCache.size >= MAX_CACHE_SIZE) {
|
|
682
|
+
const oldest = rendererCache.keys().next().value;
|
|
683
|
+
if (oldest) rendererCache.delete(oldest);
|
|
684
|
+
}
|
|
685
|
+
rendererCache.set(cacheKey, renderer);
|
|
686
|
+
return makeReactFC(renderer, qjs);
|
|
467
687
|
}
|
|
468
688
|
function clearTemplateCache() {
|
|
469
|
-
|
|
689
|
+
rendererCache.clear();
|
|
470
690
|
}
|
|
471
691
|
|
|
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
692
|
// src/ui/Flow/node-renderers.tsx
|
|
486
693
|
import React2 from "react";
|
|
487
694
|
function sanitizeUrl(url) {
|
|
@@ -557,7 +764,7 @@ var TemplateErrorBoundary = class extends React2.Component {
|
|
|
557
764
|
}
|
|
558
765
|
render() {
|
|
559
766
|
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));
|
|
767
|
+
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
768
|
}
|
|
562
769
|
return this.props.children;
|
|
563
770
|
}
|
|
@@ -568,6 +775,7 @@ function EnhancedDynamicNode({
|
|
|
568
775
|
width,
|
|
569
776
|
height
|
|
570
777
|
}) {
|
|
778
|
+
useQuickJS();
|
|
571
779
|
if (typeDef.template) {
|
|
572
780
|
const Component = compileTemplate(typeDef.template, typeDef.slug);
|
|
573
781
|
if (Component) {
|
|
@@ -594,6 +802,7 @@ function EnhancedDynamicNode({
|
|
|
594
802
|
return /* @__PURE__ */ React2.createElement(
|
|
595
803
|
"div",
|
|
596
804
|
{
|
|
805
|
+
className: `flow-node flow-node--${typeDef.slug}`,
|
|
597
806
|
style: {
|
|
598
807
|
width: "100%",
|
|
599
808
|
height: "100%",
|
|
@@ -646,14 +855,248 @@ function DefaultFrameNode({ data }) {
|
|
|
646
855
|
);
|
|
647
856
|
}
|
|
648
857
|
|
|
858
|
+
// src/ui/Flow/field-helpers.ts
|
|
859
|
+
function getImageField(fields, name) {
|
|
860
|
+
const val = fields == null ? void 0 : fields[name];
|
|
861
|
+
if (val && typeof val === "object" && val !== null && "url" in val)
|
|
862
|
+
return val;
|
|
863
|
+
return void 0;
|
|
864
|
+
}
|
|
865
|
+
function getTextField(fields, name) {
|
|
866
|
+
const val = fields == null ? void 0 : fields[name];
|
|
867
|
+
return typeof val === "string" ? val : void 0;
|
|
868
|
+
}
|
|
869
|
+
function getNumberField(fields, name) {
|
|
870
|
+
const val = fields == null ? void 0 : fields[name];
|
|
871
|
+
return typeof val === "number" ? val : void 0;
|
|
872
|
+
}
|
|
873
|
+
function getBooleanField(fields, name) {
|
|
874
|
+
const val = fields == null ? void 0 : fields[name];
|
|
875
|
+
return typeof val === "boolean" ? val : void 0;
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
// src/ui/Flow/css-sanitizer.ts
|
|
879
|
+
import postcss from "postcss";
|
|
880
|
+
var ALLOWED_AT_RULES = /* @__PURE__ */ new Set(["keyframes", "media", "supports", "container", "layer"]);
|
|
881
|
+
var BLOCKED_VALUE_PATTERNS = [/url\s*\(/i, /expression\s*\(/i, /paint\s*\(/i, /-moz-binding/i];
|
|
882
|
+
var DANGEROUS_SELECTOR = /(?:^|[\s,])(?::root|html|body)\b/;
|
|
883
|
+
function sanitizeCSS(css, scopeClass) {
|
|
884
|
+
let root;
|
|
885
|
+
try {
|
|
886
|
+
root = postcss.parse(css);
|
|
887
|
+
} catch (e) {
|
|
888
|
+
return "";
|
|
889
|
+
}
|
|
890
|
+
root.walkAtRules((node) => {
|
|
891
|
+
if (!ALLOWED_AT_RULES.has(node.name.toLowerCase())) {
|
|
892
|
+
node.remove();
|
|
893
|
+
}
|
|
894
|
+
});
|
|
895
|
+
root.walkDecls((node) => {
|
|
896
|
+
if (BLOCKED_VALUE_PATTERNS.some((p) => p.test(node.value))) {
|
|
897
|
+
node.remove();
|
|
898
|
+
}
|
|
899
|
+
});
|
|
900
|
+
root.walkRules((rule) => {
|
|
901
|
+
rule.selectors = rule.selectors.filter((s) => !DANGEROUS_SELECTOR.test(s));
|
|
902
|
+
if (!rule.selectors.length) {
|
|
903
|
+
rule.remove();
|
|
904
|
+
return;
|
|
905
|
+
}
|
|
906
|
+
if (scopeClass) {
|
|
907
|
+
const safeScopeClass = scopeClass.replace(/[{}()[\];,'"\\<>]/g, "");
|
|
908
|
+
if (!safeScopeClass) {
|
|
909
|
+
rule.remove();
|
|
910
|
+
return;
|
|
911
|
+
}
|
|
912
|
+
const parent = rule.parent;
|
|
913
|
+
if ((parent == null ? void 0 : parent.type) === "atrule" && parent.name.toLowerCase() === "keyframes") {
|
|
914
|
+
return;
|
|
915
|
+
}
|
|
916
|
+
rule.selectors = rule.selectors.map((sel) => `.${safeScopeClass} ${sel}`);
|
|
917
|
+
}
|
|
918
|
+
});
|
|
919
|
+
return root.toString().replace(/<\/style/gi, "<\\/style");
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
// src/ui/Flow/FlowRenderer.tsx
|
|
923
|
+
import React6 from "react";
|
|
924
|
+
import {
|
|
925
|
+
ReactFlow,
|
|
926
|
+
ReactFlowProvider,
|
|
927
|
+
Background,
|
|
928
|
+
Controls,
|
|
929
|
+
MiniMap
|
|
930
|
+
} from "@xyflow/react";
|
|
931
|
+
|
|
932
|
+
// src/ui/Flow/node-types-factory.tsx
|
|
933
|
+
import React4 from "react";
|
|
934
|
+
|
|
935
|
+
// src/ui/Image/index.tsx
|
|
936
|
+
import React3, { useCallback, useRef, useState } from "react";
|
|
937
|
+
|
|
938
|
+
// src/utils/image.ts
|
|
939
|
+
var IMAGE_SIZES = [384, 768, 1536];
|
|
940
|
+
function getImageSrcSet(image) {
|
|
941
|
+
const parts = [];
|
|
942
|
+
const sizes = image.sizes;
|
|
943
|
+
if (sizes) {
|
|
944
|
+
for (const size of IMAGE_SIZES) {
|
|
945
|
+
const entry = sizes[String(size)];
|
|
946
|
+
if ((entry == null ? void 0 : entry.url) && entry.width) {
|
|
947
|
+
parts.push(`${entry.url} ${entry.width}w`);
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
if (image.url && image.width) {
|
|
952
|
+
parts.push(`${image.url} ${image.width}w`);
|
|
953
|
+
}
|
|
954
|
+
return parts.join(", ");
|
|
955
|
+
}
|
|
956
|
+
function getImagePlaceholderStyle(image, options) {
|
|
957
|
+
var _a, _b, _c;
|
|
958
|
+
const type = (_a = options == null ? void 0 : options.type) != null ? _a : "blur";
|
|
959
|
+
const paletteColor = (_b = options == null ? void 0 : options.paletteColor) != null ? _b : "muted";
|
|
960
|
+
if (type === "none") return {};
|
|
961
|
+
const color = (_c = image.palette) == null ? void 0 : _c[paletteColor];
|
|
962
|
+
if (type === "blur") {
|
|
963
|
+
const lqip = image.lqip;
|
|
964
|
+
if (lqip) {
|
|
965
|
+
return {
|
|
966
|
+
backgroundImage: `url(${lqip})`,
|
|
967
|
+
backgroundSize: "cover",
|
|
968
|
+
backgroundPosition: "center"
|
|
969
|
+
};
|
|
970
|
+
}
|
|
971
|
+
if (color) {
|
|
972
|
+
return { backgroundColor: color };
|
|
973
|
+
}
|
|
974
|
+
return {};
|
|
975
|
+
}
|
|
976
|
+
if (color) {
|
|
977
|
+
return { backgroundColor: color };
|
|
978
|
+
}
|
|
979
|
+
return {};
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
// src/ui/Image/index.tsx
|
|
983
|
+
function Image({
|
|
984
|
+
image,
|
|
985
|
+
width,
|
|
986
|
+
dpr = 1,
|
|
987
|
+
placeholder: placeholderProp,
|
|
988
|
+
className,
|
|
989
|
+
style,
|
|
990
|
+
imgClassName,
|
|
991
|
+
imgStyle,
|
|
992
|
+
sizes,
|
|
993
|
+
loading: loadingProp,
|
|
994
|
+
onLoad,
|
|
995
|
+
objectFit = "cover",
|
|
996
|
+
priority = false,
|
|
997
|
+
fill = false,
|
|
998
|
+
imageRendering
|
|
999
|
+
}) {
|
|
1000
|
+
var _a, _b;
|
|
1001
|
+
const [loaded, setLoaded] = useState(false);
|
|
1002
|
+
const firedRef = useRef(false);
|
|
1003
|
+
const isPixelRendering = imageRendering === "pixelated" || imageRendering === "crisp-edges";
|
|
1004
|
+
const placeholder = placeholderProp != null ? placeholderProp : isPixelRendering ? "none" : "blur";
|
|
1005
|
+
const loading = priority ? "eager" : loadingProp != null ? loadingProp : "lazy";
|
|
1006
|
+
const aspectRatio = !fill && image.width && image.height ? `${image.width} / ${image.height}` : void 0;
|
|
1007
|
+
const srcSet = getImageSrcSet(image);
|
|
1008
|
+
const src = (_a = image.url) != null ? _a : void 0;
|
|
1009
|
+
const hasLqip = placeholder === "blur" && !!image.lqip;
|
|
1010
|
+
const placeholderStyle = getImagePlaceholderStyle(image, {
|
|
1011
|
+
type: placeholder
|
|
1012
|
+
});
|
|
1013
|
+
const placeholderColor = !hasLqip && "backgroundColor" in placeholderStyle ? placeholderStyle.backgroundColor : void 0;
|
|
1014
|
+
const fireLoad = useCallback(() => {
|
|
1015
|
+
if (firedRef.current) return;
|
|
1016
|
+
firedRef.current = true;
|
|
1017
|
+
setLoaded(true);
|
|
1018
|
+
onLoad == null ? void 0 : onLoad();
|
|
1019
|
+
}, [onLoad]);
|
|
1020
|
+
const imgRef = useCallback(
|
|
1021
|
+
(node) => {
|
|
1022
|
+
if (node && node.complete && node.naturalWidth > 0) {
|
|
1023
|
+
fireLoad();
|
|
1024
|
+
}
|
|
1025
|
+
},
|
|
1026
|
+
[fireLoad]
|
|
1027
|
+
);
|
|
1028
|
+
const containerStyle = __spreadValues(__spreadValues(__spreadValues({
|
|
1029
|
+
position: "relative",
|
|
1030
|
+
overflow: "hidden"
|
|
1031
|
+
}, fill ? { width: "100%", height: "100%" } : {}), aspectRatio ? { aspectRatio } : {}), style);
|
|
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 = __spreadValues(__spreadProps(__spreadValues({
|
|
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
|
+
return /* @__PURE__ */ React3.createElement("div", { className, style: containerStyle }, hasLqip && /* @__PURE__ */ React3.createElement(
|
|
1052
|
+
"img",
|
|
1053
|
+
{
|
|
1054
|
+
"aria-hidden": true,
|
|
1055
|
+
alt: "",
|
|
1056
|
+
src: image.lqip,
|
|
1057
|
+
style: __spreadProps(__spreadValues({}, overlayBase), {
|
|
1058
|
+
display: "block",
|
|
1059
|
+
objectFit,
|
|
1060
|
+
filter: "blur(20px)",
|
|
1061
|
+
transform: "scale(1.1)"
|
|
1062
|
+
})
|
|
1063
|
+
}
|
|
1064
|
+
), placeholderColor && /* @__PURE__ */ React3.createElement(
|
|
1065
|
+
"div",
|
|
1066
|
+
{
|
|
1067
|
+
"aria-hidden": true,
|
|
1068
|
+
style: __spreadProps(__spreadValues({}, overlayBase), {
|
|
1069
|
+
backgroundColor: placeholderColor
|
|
1070
|
+
})
|
|
1071
|
+
}
|
|
1072
|
+
), /* @__PURE__ */ React3.createElement(
|
|
1073
|
+
"img",
|
|
1074
|
+
{
|
|
1075
|
+
ref: imgRef,
|
|
1076
|
+
alt: (_b = image.alt) != null ? _b : "",
|
|
1077
|
+
src,
|
|
1078
|
+
srcSet: srcSet || void 0,
|
|
1079
|
+
sizes,
|
|
1080
|
+
width: width ? width * dpr : void 0,
|
|
1081
|
+
loading,
|
|
1082
|
+
decoding: "async",
|
|
1083
|
+
fetchPriority: priority ? "high" : void 0,
|
|
1084
|
+
onLoad: fireLoad,
|
|
1085
|
+
className: imgClassName,
|
|
1086
|
+
style: mainImgStyle
|
|
1087
|
+
}
|
|
1088
|
+
));
|
|
1089
|
+
}
|
|
1090
|
+
|
|
649
1091
|
// src/ui/Flow/node-types-factory.tsx
|
|
650
1092
|
function createNodeTypes(nodeRenderers, nodeTypeDefsMap, frameRenderer, nodeWrapper, renderNode) {
|
|
651
1093
|
const types = {};
|
|
652
1094
|
types.dynamic = ((props) => {
|
|
1095
|
+
var _a;
|
|
653
1096
|
const d = props.data;
|
|
654
1097
|
const typeDef = nodeTypeDefsMap == null ? void 0 : nodeTypeDefsMap.get(d.nodeTypeSlug);
|
|
655
1098
|
const CustomRenderer = nodeRenderers == null ? void 0 : nodeRenderers[d.nodeTypeSlug];
|
|
656
|
-
const defaultRender = typeDef ? /* @__PURE__ */
|
|
1099
|
+
const defaultRender = typeDef ? /* @__PURE__ */ React4.createElement(
|
|
657
1100
|
EnhancedDynamicNode,
|
|
658
1101
|
{
|
|
659
1102
|
data: d,
|
|
@@ -661,7 +1104,7 @@ function createNodeTypes(nodeRenderers, nodeTypeDefsMap, frameRenderer, nodeWrap
|
|
|
661
1104
|
width: props.width,
|
|
662
1105
|
height: props.height
|
|
663
1106
|
}
|
|
664
|
-
) : /* @__PURE__ */
|
|
1107
|
+
) : /* @__PURE__ */ React4.createElement(DefaultDynamicNode, __spreadValues({}, props));
|
|
665
1108
|
const slotProps = {
|
|
666
1109
|
id: props.id,
|
|
667
1110
|
nodeTypeSlug: d.nodeTypeSlug,
|
|
@@ -673,14 +1116,35 @@ function createNodeTypes(nodeRenderers, nodeTypeDefsMap, frameRenderer, nodeWrap
|
|
|
673
1116
|
height: props.height,
|
|
674
1117
|
defaultRender
|
|
675
1118
|
};
|
|
676
|
-
let content
|
|
1119
|
+
let content;
|
|
1120
|
+
if (CustomRenderer) {
|
|
1121
|
+
content = /* @__PURE__ */ React4.createElement(CustomRenderer, __spreadValues({}, slotProps));
|
|
1122
|
+
} else if (d.nodeTypeSlug === "image") {
|
|
1123
|
+
const imageVal = (_a = d.fields) == null ? void 0 : _a.image;
|
|
1124
|
+
if (imageVal && typeof imageVal === "object" && "url" in imageVal) {
|
|
1125
|
+
content = /* @__PURE__ */ React4.createElement(
|
|
1126
|
+
Image,
|
|
1127
|
+
{
|
|
1128
|
+
image: imageVal,
|
|
1129
|
+
width: props.width,
|
|
1130
|
+
fill: true,
|
|
1131
|
+
priority: true,
|
|
1132
|
+
objectFit: "contain"
|
|
1133
|
+
}
|
|
1134
|
+
);
|
|
1135
|
+
} else {
|
|
1136
|
+
content = defaultRender;
|
|
1137
|
+
}
|
|
1138
|
+
} else {
|
|
1139
|
+
content = defaultRender;
|
|
1140
|
+
}
|
|
677
1141
|
if (renderNode) {
|
|
678
1142
|
const result = renderNode(slotProps, content);
|
|
679
1143
|
if (result !== null) content = result;
|
|
680
1144
|
}
|
|
681
1145
|
if (nodeWrapper) {
|
|
682
1146
|
const Wrapper = nodeWrapper;
|
|
683
|
-
content = /* @__PURE__ */
|
|
1147
|
+
content = /* @__PURE__ */ React4.createElement(
|
|
684
1148
|
Wrapper,
|
|
685
1149
|
{
|
|
686
1150
|
id: props.id,
|
|
@@ -697,7 +1161,7 @@ function createNodeTypes(nodeRenderers, nodeTypeDefsMap, frameRenderer, nodeWrap
|
|
|
697
1161
|
types.frame = frameRenderer ? ((props) => {
|
|
698
1162
|
const d = props.data;
|
|
699
1163
|
const Renderer = frameRenderer;
|
|
700
|
-
return /* @__PURE__ */
|
|
1164
|
+
return /* @__PURE__ */ React4.createElement(
|
|
701
1165
|
Renderer,
|
|
702
1166
|
{
|
|
703
1167
|
id: props.id,
|
|
@@ -721,7 +1185,7 @@ function createEdgeTypes(edgeRenderers, edgeTypeDefsMap) {
|
|
|
721
1185
|
types[slug] = ((props) => {
|
|
722
1186
|
var _a;
|
|
723
1187
|
const def = edgeTypeDefsMap == null ? void 0 : edgeTypeDefsMap.get(slug);
|
|
724
|
-
return /* @__PURE__ */
|
|
1188
|
+
return /* @__PURE__ */ React4.createElement(
|
|
725
1189
|
Renderer,
|
|
726
1190
|
{
|
|
727
1191
|
id: props.id,
|
|
@@ -787,7 +1251,7 @@ function applyEdgeStyles(edges, edgeTypeDefsMap) {
|
|
|
787
1251
|
}
|
|
788
1252
|
|
|
789
1253
|
// src/ui/Flow/focus-handler.tsx
|
|
790
|
-
import
|
|
1254
|
+
import React5 from "react";
|
|
791
1255
|
import { useReactFlow, useStoreApi } from "@xyflow/react";
|
|
792
1256
|
function clampViewport(vp, cw, ch, extent) {
|
|
793
1257
|
const left = -vp.x / vp.zoom;
|
|
@@ -816,14 +1280,14 @@ function FocusHandler({
|
|
|
816
1280
|
}) {
|
|
817
1281
|
const { setViewport } = useReactFlow();
|
|
818
1282
|
const store = useStoreApi();
|
|
819
|
-
const containerRef =
|
|
1283
|
+
const containerRef = React5.useRef(null);
|
|
820
1284
|
const boundsKey = `${bounds.x},${bounds.y},${bounds.width},${bounds.height}`;
|
|
821
|
-
const boundsRef =
|
|
1285
|
+
const boundsRef = React5.useRef(bounds);
|
|
822
1286
|
boundsRef.current = bounds;
|
|
823
|
-
const [containerSize, setContainerSize] =
|
|
824
|
-
const prevBoundsKeyRef =
|
|
825
|
-
const prevSizeRef =
|
|
826
|
-
|
|
1287
|
+
const [containerSize, setContainerSize] = React5.useState({ w: 0, h: 0 });
|
|
1288
|
+
const prevBoundsKeyRef = React5.useRef(null);
|
|
1289
|
+
const prevSizeRef = React5.useRef({ w: 0, h: 0 });
|
|
1290
|
+
React5.useEffect(() => {
|
|
827
1291
|
const el = containerRef.current;
|
|
828
1292
|
if (!el) return;
|
|
829
1293
|
const observer = new ResizeObserver((entries) => {
|
|
@@ -835,7 +1299,7 @@ function FocusHandler({
|
|
|
835
1299
|
observer.observe(el);
|
|
836
1300
|
return () => observer.disconnect();
|
|
837
1301
|
}, []);
|
|
838
|
-
|
|
1302
|
+
React5.useEffect(() => {
|
|
839
1303
|
if (containerSize.w === 0 || containerSize.h === 0) return;
|
|
840
1304
|
const prevKey = prevBoundsKeyRef.current;
|
|
841
1305
|
const prevSize = prevSizeRef.current;
|
|
@@ -902,7 +1366,7 @@ function FocusHandler({
|
|
|
902
1366
|
store,
|
|
903
1367
|
onInitialFit
|
|
904
1368
|
]);
|
|
905
|
-
return /* @__PURE__ */
|
|
1369
|
+
return /* @__PURE__ */ React5.createElement(
|
|
906
1370
|
"div",
|
|
907
1371
|
{
|
|
908
1372
|
ref: containerRef,
|
|
@@ -917,6 +1381,7 @@ function FocusHandler({
|
|
|
917
1381
|
}
|
|
918
1382
|
|
|
919
1383
|
// src/ui/Flow/FlowRenderer.tsx
|
|
1384
|
+
var NullFrameRenderer = () => null;
|
|
920
1385
|
function FlowRenderer({
|
|
921
1386
|
data,
|
|
922
1387
|
className,
|
|
@@ -934,6 +1399,7 @@ function FlowRenderer({
|
|
|
934
1399
|
onNodeMouseLeave,
|
|
935
1400
|
onEdgeClick,
|
|
936
1401
|
frameRenderer,
|
|
1402
|
+
hideFrames = false,
|
|
937
1403
|
edgeRenderers,
|
|
938
1404
|
nodeWrapper,
|
|
939
1405
|
controls,
|
|
@@ -954,33 +1420,34 @@ function FlowRenderer({
|
|
|
954
1420
|
maxZoom: maxZoomProp
|
|
955
1421
|
}) {
|
|
956
1422
|
var _a, _b;
|
|
957
|
-
const
|
|
1423
|
+
const resolvedFrameRenderer = hideFrames ? NullFrameRenderer : frameRenderer;
|
|
1424
|
+
const nodeTypeDefsMap = React6.useMemo(() => {
|
|
958
1425
|
if (!(nodeTypeDefs == null ? void 0 : nodeTypeDefs.length)) return void 0;
|
|
959
1426
|
return new Map(nodeTypeDefs.map((d) => [d.slug, d]));
|
|
960
1427
|
}, [nodeTypeDefs]);
|
|
961
|
-
const edgeTypeDefsMap =
|
|
1428
|
+
const edgeTypeDefsMap = React6.useMemo(() => {
|
|
962
1429
|
if (!(edgeTypeDefs == null ? void 0 : edgeTypeDefs.length)) return void 0;
|
|
963
1430
|
return new Map(edgeTypeDefs.map((d) => [d.slug, d]));
|
|
964
1431
|
}, [edgeTypeDefs]);
|
|
965
|
-
const nodeTypes =
|
|
1432
|
+
const nodeTypes = React6.useMemo(
|
|
966
1433
|
() => createNodeTypes(
|
|
967
1434
|
nodeRenderers,
|
|
968
1435
|
nodeTypeDefsMap,
|
|
969
|
-
|
|
1436
|
+
resolvedFrameRenderer,
|
|
970
1437
|
nodeWrapper,
|
|
971
1438
|
renderNode
|
|
972
1439
|
),
|
|
973
|
-
[nodeRenderers, nodeTypeDefsMap,
|
|
1440
|
+
[nodeRenderers, nodeTypeDefsMap, resolvedFrameRenderer, nodeWrapper, renderNode]
|
|
974
1441
|
);
|
|
975
|
-
const customEdgeTypes =
|
|
1442
|
+
const customEdgeTypes = React6.useMemo(
|
|
976
1443
|
() => createEdgeTypes(edgeRenderers, edgeTypeDefsMap),
|
|
977
1444
|
[edgeRenderers, edgeTypeDefsMap]
|
|
978
1445
|
);
|
|
979
|
-
const mergedCSS =
|
|
1446
|
+
const mergedCSS = React6.useMemo(() => {
|
|
980
1447
|
if (!(nodeTypeDefs == null ? void 0 : nodeTypeDefs.length)) return "";
|
|
981
|
-
return nodeTypeDefs.filter((d) => d.customCSS).map((d) => d.customCSS).join("\n");
|
|
1448
|
+
return nodeTypeDefs.filter((d) => d.customCSS).map((d) => sanitizeCSS(d.customCSS, `flow-node--${d.slug}`)).join("\n");
|
|
982
1449
|
}, [nodeTypeDefs]);
|
|
983
|
-
const styledEdges =
|
|
1450
|
+
const styledEdges = React6.useMemo(() => {
|
|
984
1451
|
var _a2;
|
|
985
1452
|
let edges = applyEdgeStyles((_a2 = data == null ? void 0 : data.edges) != null ? _a2 : [], edgeTypeDefsMap);
|
|
986
1453
|
if (edgeRenderers) {
|
|
@@ -994,7 +1461,7 @@ function FlowRenderer({
|
|
|
994
1461
|
}
|
|
995
1462
|
return edges;
|
|
996
1463
|
}, [data == null ? void 0 : data.edges, edgeTypeDefsMap, edgeRenderers]);
|
|
997
|
-
const translateExtent =
|
|
1464
|
+
const translateExtent = React6.useMemo(() => {
|
|
998
1465
|
if (translateExtentProp) return translateExtentProp;
|
|
999
1466
|
const es = clampBounds != null ? clampBounds : bounds;
|
|
1000
1467
|
if (!es) return void 0;
|
|
@@ -1005,16 +1472,16 @@ function FlowRenderer({
|
|
|
1005
1472
|
];
|
|
1006
1473
|
}, [translateExtentProp, clampBounds, bounds, focusPadding]);
|
|
1007
1474
|
const boundsKey = bounds ? `${bounds.x},${bounds.y},${bounds.width},${bounds.height}` : "";
|
|
1008
|
-
const extentReadyRef =
|
|
1009
|
-
const expandedExtentRef =
|
|
1010
|
-
const prevBoundsKeyRef =
|
|
1475
|
+
const extentReadyRef = React6.useRef(false);
|
|
1476
|
+
const expandedExtentRef = React6.useRef(void 0);
|
|
1477
|
+
const prevBoundsKeyRef = React6.useRef(boundsKey);
|
|
1011
1478
|
if (prevBoundsKeyRef.current !== boundsKey) {
|
|
1012
1479
|
prevBoundsKeyRef.current = boundsKey;
|
|
1013
1480
|
extentReadyRef.current = false;
|
|
1014
1481
|
expandedExtentRef.current = void 0;
|
|
1015
1482
|
}
|
|
1016
|
-
const [, rerender] =
|
|
1017
|
-
const handleInitialFit =
|
|
1483
|
+
const [, rerender] = React6.useReducer((x) => x + 1, 0);
|
|
1484
|
+
const handleInitialFit = React6.useCallback(
|
|
1018
1485
|
(expandedExtent) => {
|
|
1019
1486
|
extentReadyRef.current = true;
|
|
1020
1487
|
expandedExtentRef.current = expandedExtent;
|
|
@@ -1025,7 +1492,7 @@ function FlowRenderer({
|
|
|
1025
1492
|
const activeExtent = !bounds || extentReadyRef.current ? (_a = expandedExtentRef.current) != null ? _a : translateExtent : void 0;
|
|
1026
1493
|
if (!data) return null;
|
|
1027
1494
|
const resolvedDefaultViewport = defaultViewportProp != null ? defaultViewportProp : !fitView && data.viewport ? data.viewport : void 0;
|
|
1028
|
-
return /* @__PURE__ */
|
|
1495
|
+
return /* @__PURE__ */ React6.createElement(ReactFlowProvider, null, /* @__PURE__ */ React6.createElement(
|
|
1029
1496
|
"div",
|
|
1030
1497
|
{
|
|
1031
1498
|
className,
|
|
@@ -1035,7 +1502,7 @@ function FlowRenderer({
|
|
|
1035
1502
|
background: "transparent"
|
|
1036
1503
|
}, style)
|
|
1037
1504
|
},
|
|
1038
|
-
/* @__PURE__ */
|
|
1505
|
+
/* @__PURE__ */ React6.createElement(
|
|
1039
1506
|
ReactFlow,
|
|
1040
1507
|
{
|
|
1041
1508
|
nodes: (_b = data.nodes) != null ? _b : [],
|
|
@@ -1065,16 +1532,16 @@ function FlowRenderer({
|
|
|
1065
1532
|
maxZoom: maxZoomProp,
|
|
1066
1533
|
proOptions: { hideAttribution: true }
|
|
1067
1534
|
},
|
|
1068
|
-
mergedCSS && /* @__PURE__ */
|
|
1069
|
-
background && /* @__PURE__ */
|
|
1070
|
-
controls && /* @__PURE__ */
|
|
1071
|
-
minimap && /* @__PURE__ */
|
|
1535
|
+
mergedCSS && /* @__PURE__ */ React6.createElement("style", { dangerouslySetInnerHTML: { __html: mergedCSS } }),
|
|
1536
|
+
background && /* @__PURE__ */ React6.createElement(Background, null),
|
|
1537
|
+
controls && /* @__PURE__ */ React6.createElement(Controls, null),
|
|
1538
|
+
minimap && /* @__PURE__ */ React6.createElement(
|
|
1072
1539
|
MiniMap,
|
|
1073
1540
|
{
|
|
1074
1541
|
nodeColor: minimapNodeColor
|
|
1075
1542
|
}
|
|
1076
1543
|
),
|
|
1077
|
-
bounds && /* @__PURE__ */
|
|
1544
|
+
bounds && /* @__PURE__ */ React6.createElement(
|
|
1078
1545
|
FocusHandler,
|
|
1079
1546
|
{
|
|
1080
1547
|
bounds,
|
|
@@ -1092,18 +1559,89 @@ function FlowRenderer({
|
|
|
1092
1559
|
)
|
|
1093
1560
|
));
|
|
1094
1561
|
}
|
|
1562
|
+
|
|
1563
|
+
// src/ui/Flow/FlowFrame.tsx
|
|
1564
|
+
import React7, { useMemo as useMemo3, useEffect, useRef as useRef2 } from "react";
|
|
1565
|
+
function FlowFrame(_a) {
|
|
1566
|
+
var _b = _a, {
|
|
1567
|
+
client,
|
|
1568
|
+
slug,
|
|
1569
|
+
id,
|
|
1570
|
+
frameId,
|
|
1571
|
+
loading = null,
|
|
1572
|
+
error: renderError,
|
|
1573
|
+
onDataReady
|
|
1574
|
+
} = _b, rendererProps = __objRest(_b, [
|
|
1575
|
+
"client",
|
|
1576
|
+
"slug",
|
|
1577
|
+
"id",
|
|
1578
|
+
"frameId",
|
|
1579
|
+
"loading",
|
|
1580
|
+
"error",
|
|
1581
|
+
"onDataReady"
|
|
1582
|
+
]);
|
|
1583
|
+
const { data, nodeTypeDefs, edgeTypeDefs, flow, isLoading, error } = useFlow({
|
|
1584
|
+
client,
|
|
1585
|
+
slug,
|
|
1586
|
+
id
|
|
1587
|
+
});
|
|
1588
|
+
const frameData = useMemo3(
|
|
1589
|
+
() => data ? getFrameData(data, frameId) : void 0,
|
|
1590
|
+
[data, frameId]
|
|
1591
|
+
);
|
|
1592
|
+
const onDataReadyRef = useRef2(onDataReady);
|
|
1593
|
+
onDataReadyRef.current = onDataReady;
|
|
1594
|
+
useEffect(() => {
|
|
1595
|
+
var _a2;
|
|
1596
|
+
if (frameData && flow) {
|
|
1597
|
+
(_a2 = onDataReadyRef.current) == null ? void 0 : _a2.call(onDataReadyRef, frameData, flow);
|
|
1598
|
+
}
|
|
1599
|
+
}, [frameData, flow]);
|
|
1600
|
+
if (process.env.NODE_ENV !== "production" && !slug && !id) {
|
|
1601
|
+
console.warn('[FlowFrame] Either "slug" or "id" must be provided.');
|
|
1602
|
+
}
|
|
1603
|
+
if (isLoading) return /* @__PURE__ */ React7.createElement(React7.Fragment, null, loading);
|
|
1604
|
+
if (error) return renderError ? /* @__PURE__ */ React7.createElement(React7.Fragment, null, renderError(error)) : null;
|
|
1605
|
+
if (!frameData) {
|
|
1606
|
+
if (process.env.NODE_ENV !== "production" && data) {
|
|
1607
|
+
const frames = data.nodes.filter(isFrameNode).map((n) => n.id);
|
|
1608
|
+
console.warn(
|
|
1609
|
+
`[FlowFrame] Frame "${frameId}" not found. Available frames: ${frames.join(", ") || "(none)"}`
|
|
1610
|
+
);
|
|
1611
|
+
}
|
|
1612
|
+
return null;
|
|
1613
|
+
}
|
|
1614
|
+
return /* @__PURE__ */ React7.createElement(
|
|
1615
|
+
FlowRenderer,
|
|
1616
|
+
__spreadProps(__spreadValues({}, rendererProps), {
|
|
1617
|
+
data: frameData.data,
|
|
1618
|
+
nodeTypeDefs,
|
|
1619
|
+
edgeTypeDefs,
|
|
1620
|
+
bounds: frameData.fitBounds,
|
|
1621
|
+
clampBounds: frameData.clampBounds,
|
|
1622
|
+
hideFrames: true
|
|
1623
|
+
})
|
|
1624
|
+
);
|
|
1625
|
+
}
|
|
1095
1626
|
export {
|
|
1096
1627
|
BUILT_IN_EDGE_TYPES,
|
|
1097
1628
|
BUILT_IN_NODE_TYPES,
|
|
1629
|
+
FlowFrame,
|
|
1098
1630
|
FlowRenderer,
|
|
1099
1631
|
clearTemplateCache,
|
|
1100
1632
|
compileTemplate,
|
|
1633
|
+
getBooleanField,
|
|
1101
1634
|
getFrameData,
|
|
1102
1635
|
getFrames,
|
|
1636
|
+
getImageField,
|
|
1103
1637
|
getNodeBounds,
|
|
1638
|
+
getNumberField,
|
|
1639
|
+
getTextField,
|
|
1104
1640
|
isDynamicNode,
|
|
1105
1641
|
isFrameNode,
|
|
1106
1642
|
prefetchFlow,
|
|
1643
|
+
renderFieldValue,
|
|
1644
|
+
sanitizeCSS,
|
|
1107
1645
|
useFlow,
|
|
1108
1646
|
useFlowData
|
|
1109
1647
|
};
|