@01.software/sdk 0.43.0 → 0.45.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +375 -2
- package/MIGRATION.md +89 -10
- package/README.md +451 -109
- package/dist/{server-nXOezi4b.d.cts → catalog-mappers-sIshKNb3.d.cts} +14 -3
- package/dist/{server-nXOezi4b.d.ts → catalog-mappers-sIshKNb3.d.ts} +14 -3
- package/dist/client.cjs +2680 -345
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +10 -7
- package/dist/client.d.ts +10 -7
- package/dist/client.js +2680 -345
- package/dist/client.js.map +1 -1
- package/dist/{collection-client-U70KizLf.d.cts → collection-client-BSo7VXQE.d.cts} +8 -5
- package/dist/{collection-client-gWsA7BVP.d.ts → collection-client-Ckfusuee.d.ts} +8 -5
- package/dist/{const-_WWHU-gX.d.ts → const-BAG0MH0u.d.cts} +13 -10
- package/dist/{const-BBynifk0.d.cts → const-CaPq2AE4.d.ts} +13 -10
- package/dist/errors.cjs +74 -1
- package/dist/errors.cjs.map +1 -1
- package/dist/errors.d.cts +38 -1
- package/dist/errors.d.ts +38 -1
- package/dist/errors.js +74 -1
- package/dist/errors.js.map +1 -1
- package/dist/{index-DPi5NWU8.d.ts → index-BNICJxBL.d.ts} +4 -4
- package/dist/{index-Dg4Y6Aq7.d.cts → index-YGrZrxNn.d.cts} +4 -4
- package/dist/index.cjs +2741 -368
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +18 -19
- package/dist/index.d.ts +18 -19
- package/dist/index.js +2741 -368
- package/dist/index.js.map +1 -1
- package/dist/{payload-types-DLxkB7Mv.d.cts → payload-types-CJZuXcgF.d.cts} +6873 -4208
- package/dist/{payload-types-DLxkB7Mv.d.ts → payload-types-CJZuXcgF.d.ts} +6873 -4208
- package/dist/query.cjs +550 -101
- package/dist/query.cjs.map +1 -1
- package/dist/query.d.cts +43 -45
- package/dist/query.d.ts +43 -45
- package/dist/query.js +550 -101
- package/dist/query.js.map +1 -1
- package/dist/realtime.cjs.map +1 -1
- package/dist/realtime.d.cts +2 -2
- package/dist/realtime.d.ts +2 -2
- package/dist/realtime.js.map +1 -1
- package/dist/server.cjs +2252 -444
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +11 -10
- package/dist/server.d.ts +11 -10
- package/dist/server.js +2252 -444
- package/dist/server.js.map +1 -1
- package/dist/storefront-cache.cjs +65 -1
- package/dist/storefront-cache.cjs.map +1 -1
- package/dist/storefront-cache.js +65 -1
- package/dist/storefront-cache.js.map +1 -1
- package/dist/types-BC6rVmJa.d.ts +47 -0
- package/dist/{types-B9lGhZlB.d.ts → types-BlOvjoTX.d.ts} +1095 -504
- package/dist/{types-Bpx5sYKo.d.cts → types-C4WuJfw7.d.cts} +1095 -504
- package/dist/types-D5p7-m1l.d.cts +47 -0
- package/dist/ui/canvas/server.cjs +244 -2
- package/dist/ui/canvas/server.cjs.map +1 -1
- package/dist/ui/canvas/server.d.cts +27 -1
- package/dist/ui/canvas/server.d.ts +27 -1
- package/dist/ui/canvas/server.js +244 -2
- package/dist/ui/canvas/server.js.map +1 -1
- package/dist/ui/canvas.cjs +419 -103
- package/dist/ui/canvas.cjs.map +1 -1
- package/dist/ui/canvas.d.cts +19 -7
- package/dist/ui/canvas.d.ts +19 -7
- package/dist/ui/canvas.js +419 -103
- package/dist/ui/canvas.js.map +1 -1
- package/dist/ui/form.d.cts +1 -1
- package/dist/ui/form.d.ts +1 -1
- package/dist/ui/video.d.cts +1 -1
- package/dist/ui/video.d.ts +1 -1
- package/dist/webhook.cjs +2 -1
- package/dist/webhook.cjs.map +1 -1
- package/dist/webhook.d.cts +4 -4
- package/dist/webhook.d.ts +4 -4
- package/dist/webhook.js +2 -1
- package/dist/webhook.js.map +1 -1
- package/package.json +12 -11
- package/dist/types-B1ngKbWI.d.cts +0 -33
- package/dist/types-BiKNBwRA.d.ts +0 -33
package/dist/ui/canvas.cjs
CHANGED
|
@@ -31,8 +31,10 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
31
31
|
// src/ui/Canvas/index.tsx
|
|
32
32
|
var Canvas_exports = {};
|
|
33
33
|
__export(Canvas_exports, {
|
|
34
|
+
CANVAS_SHAPE_TYPES: () => CANVAS_SHAPE_TYPES,
|
|
34
35
|
CanvasFrame: () => CanvasFrame,
|
|
35
36
|
CanvasRenderer: () => CanvasRenderer,
|
|
37
|
+
DefaultShapeNode: () => DefaultShapeNode,
|
|
36
38
|
clearTemplateCache: () => clearTemplateCache,
|
|
37
39
|
compileTemplate: () => compileTemplate,
|
|
38
40
|
getBooleanField: () => getBooleanField,
|
|
@@ -44,6 +46,7 @@ __export(Canvas_exports, {
|
|
|
44
46
|
getTextField: () => getTextField,
|
|
45
47
|
isDynamicNode: () => isDynamicNode,
|
|
46
48
|
isFrameNode: () => isFrameNode,
|
|
49
|
+
isShapeNode: () => isShapeNode,
|
|
47
50
|
prefetchCanvas: () => prefetchCanvas,
|
|
48
51
|
renderFieldValue: () => renderFieldValue,
|
|
49
52
|
sanitizeCSS: () => sanitizeCSS,
|
|
@@ -57,12 +60,22 @@ __export(Canvas_exports, {
|
|
|
57
60
|
module.exports = __toCommonJS(Canvas_exports);
|
|
58
61
|
|
|
59
62
|
// src/ui/Canvas/types.ts
|
|
63
|
+
var CANVAS_SHAPE_TYPES = [
|
|
64
|
+
"terminator",
|
|
65
|
+
"process",
|
|
66
|
+
"decision",
|
|
67
|
+
"io",
|
|
68
|
+
"subprocess"
|
|
69
|
+
];
|
|
60
70
|
function isDynamicNode(node) {
|
|
61
71
|
return node.type === "dynamic";
|
|
62
72
|
}
|
|
63
73
|
function isFrameNode(node) {
|
|
64
74
|
return node.type === "frame";
|
|
65
75
|
}
|
|
76
|
+
function isShapeNode(node) {
|
|
77
|
+
return node.type === "shape";
|
|
78
|
+
}
|
|
66
79
|
|
|
67
80
|
// src/ui/Canvas/useCanvas.ts
|
|
68
81
|
var import_react_query = require("@tanstack/react-query");
|
|
@@ -86,10 +99,13 @@ function collectionKeys(collection) {
|
|
|
86
99
|
}
|
|
87
100
|
|
|
88
101
|
// src/ui/Canvas/query-options.ts
|
|
102
|
+
var CANVAS_STALE_TIME_MS = 6e4;
|
|
103
|
+
var CANVAS_CATALOG_STALE_TIME_MS = 5 * 6e4;
|
|
89
104
|
function canvasQueryOptions(client, slug, id) {
|
|
90
105
|
const identifier = id ?? slug ?? "";
|
|
91
106
|
return {
|
|
92
107
|
queryKey: collectionKeys("canvases").detail(identifier),
|
|
108
|
+
staleTime: CANVAS_STALE_TIME_MS,
|
|
93
109
|
queryFn: async () => {
|
|
94
110
|
if (id) return client.collections.from("canvases").findById(id);
|
|
95
111
|
const result = await client.collections.from("canvases").find({
|
|
@@ -105,8 +121,9 @@ function canvasQueryOptions(client, slug, id) {
|
|
|
105
121
|
function nodeTypesQueryOptions(client) {
|
|
106
122
|
return {
|
|
107
123
|
queryKey: collectionKeys("canvas-node-types").lists(),
|
|
124
|
+
staleTime: CANVAS_CATALOG_STALE_TIME_MS,
|
|
108
125
|
queryFn: async () => {
|
|
109
|
-
const result = await client.collections.from("canvas-node-types").find({ limit:
|
|
126
|
+
const result = await client.collections.from("canvas-node-types").find({ limit: 100 });
|
|
110
127
|
return result.docs;
|
|
111
128
|
}
|
|
112
129
|
};
|
|
@@ -114,8 +131,9 @@ function nodeTypesQueryOptions(client) {
|
|
|
114
131
|
function edgeTypesQueryOptions(client) {
|
|
115
132
|
return {
|
|
116
133
|
queryKey: collectionKeys("canvas-edge-types").lists(),
|
|
134
|
+
staleTime: CANVAS_CATALOG_STALE_TIME_MS,
|
|
117
135
|
queryFn: async () => {
|
|
118
|
-
const result = await client.collections.from("canvas-edge-types").find({ limit:
|
|
136
|
+
const result = await client.collections.from("canvas-edge-types").find({ limit: 100 });
|
|
119
137
|
return result.docs;
|
|
120
138
|
}
|
|
121
139
|
};
|
|
@@ -384,10 +402,9 @@ function getFrameData(data, frameId) {
|
|
|
384
402
|
// src/ui/Canvas/template-compiler.ts
|
|
385
403
|
var import_react4 = __toESM(require("react"), 1);
|
|
386
404
|
var import_sucrase = require("sucrase");
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
var
|
|
390
|
-
var ALLOWED_ELEMENTS = /* @__PURE__ */ new Set([
|
|
405
|
+
|
|
406
|
+
// src/ui/Canvas/template-security.ts
|
|
407
|
+
var ALLOWED_TEMPLATE_ELEMENTS = [
|
|
391
408
|
"div",
|
|
392
409
|
"span",
|
|
393
410
|
"p",
|
|
@@ -421,33 +438,188 @@ var ALLOWED_ELEMENTS = /* @__PURE__ */ new Set([
|
|
|
421
438
|
"g",
|
|
422
439
|
"circle",
|
|
423
440
|
"rect"
|
|
424
|
-
]);
|
|
425
|
-
var BLOCKED_PATTERNS = [
|
|
426
|
-
/\bdocument\s*\./,
|
|
427
|
-
/\bwindow\s*\./,
|
|
428
|
-
/\bwindow\s*\[/,
|
|
429
|
-
/\bglobalThis\s*\./,
|
|
430
|
-
/\bfetch\s*\(/,
|
|
431
|
-
/\bXMLHttpRequest/,
|
|
432
|
-
/\beval\s*\(/,
|
|
433
|
-
/\bFunction\s*\(/,
|
|
434
|
-
/\bimport\s*\(/,
|
|
435
|
-
/\blocalStorage/,
|
|
436
|
-
/\bsessionStorage/,
|
|
437
|
-
/\bcookie/,
|
|
438
|
-
/\bpostMessage\s*\(/,
|
|
439
|
-
/\blocation\s*[.=]/,
|
|
440
|
-
/\bnavigator\s*\./,
|
|
441
|
-
/\bsetTimeout\s*\(/,
|
|
442
|
-
/\bsetInterval\s*\(/,
|
|
443
|
-
/\bsetImmediate\s*\(/,
|
|
444
|
-
/\brequire\s*\(/,
|
|
445
|
-
/\bself\b/,
|
|
446
|
-
/\bconstructor\s*\.\s*constructor/,
|
|
447
|
-
/\bReflect\b/,
|
|
448
|
-
/\bProxy\b/,
|
|
449
|
-
/\b__proto__\b/
|
|
450
441
|
];
|
|
442
|
+
var ALLOWED_TEMPLATE_ELEMENT_SET = new Set(ALLOWED_TEMPLATE_ELEMENTS);
|
|
443
|
+
function isAllowedTemplateElement(value) {
|
|
444
|
+
return ALLOWED_TEMPLATE_ELEMENT_SET.has(value.toLowerCase());
|
|
445
|
+
}
|
|
446
|
+
var TEMPLATE_BLOCKED_PATTERNS = [
|
|
447
|
+
{ pattern: /\bdocument\s*\./, hint: "document API" },
|
|
448
|
+
{ pattern: /\bwindow\s*\./, hint: "window API" },
|
|
449
|
+
{ pattern: /\bwindow\s*\[/, hint: "window indexer" },
|
|
450
|
+
{ pattern: /\bglobalThis\s*\./, hint: "globalThis" },
|
|
451
|
+
{ pattern: /\bfetch\s*\(/, hint: "fetch()" },
|
|
452
|
+
{ pattern: /\bXMLHttpRequest/, hint: "XMLHttpRequest" },
|
|
453
|
+
{ pattern: /\beval\s*\(/, hint: "eval()" },
|
|
454
|
+
{ pattern: /\bFunction\s*\(/, hint: "Function constructor" },
|
|
455
|
+
{ pattern: /\bimport\s*\(/, hint: "dynamic import()" },
|
|
456
|
+
{ pattern: /\blocalStorage/, hint: "localStorage" },
|
|
457
|
+
{ pattern: /\bsessionStorage/, hint: "sessionStorage" },
|
|
458
|
+
{ pattern: /\bcookie/, hint: "cookie access" },
|
|
459
|
+
{ pattern: /\bpostMessage\s*\(/, hint: "postMessage()" },
|
|
460
|
+
{ pattern: /\blocation\s*[.=]/, hint: "location API" },
|
|
461
|
+
{ pattern: /\bnavigator\s*\./, hint: "navigator API" },
|
|
462
|
+
{ pattern: /\bsetTimeout\s*\(/, hint: "setTimeout()" },
|
|
463
|
+
{ pattern: /\bsetInterval\s*\(/, hint: "setInterval()" },
|
|
464
|
+
{ pattern: /\bsetImmediate\s*\(/, hint: "setImmediate()" },
|
|
465
|
+
{ pattern: /\brequire\s*\(/, hint: "require()" },
|
|
466
|
+
{ pattern: /\bself\b/, hint: "self alias" },
|
|
467
|
+
{
|
|
468
|
+
pattern: /\bconstructor\s*\.\s*constructor/,
|
|
469
|
+
hint: "constructor.constructor escape"
|
|
470
|
+
},
|
|
471
|
+
{ pattern: /\bReflect\b/, hint: "Reflect" },
|
|
472
|
+
{ pattern: /\bProxy\b/, hint: "Proxy" },
|
|
473
|
+
{ pattern: /\b__proto__\b/, hint: "__proto__" }
|
|
474
|
+
];
|
|
475
|
+
function findBlockedTemplatePattern(code) {
|
|
476
|
+
for (const { pattern, hint } of TEMPLATE_BLOCKED_PATTERNS) {
|
|
477
|
+
if (pattern.test(code)) return { hint };
|
|
478
|
+
}
|
|
479
|
+
return null;
|
|
480
|
+
}
|
|
481
|
+
var SAFE_DATA_URI_PREFIXES = [
|
|
482
|
+
"data:image/png;",
|
|
483
|
+
"data:image/jpeg;",
|
|
484
|
+
"data:image/gif;",
|
|
485
|
+
"data:image/webp;",
|
|
486
|
+
"data:image/avif;"
|
|
487
|
+
];
|
|
488
|
+
function isSafeTemplateUrl(value) {
|
|
489
|
+
if (typeof value !== "string") return false;
|
|
490
|
+
if (value.startsWith("/") || value.startsWith("./") || value.startsWith("../") || value.startsWith("#")) {
|
|
491
|
+
return true;
|
|
492
|
+
}
|
|
493
|
+
if (SAFE_DATA_URI_PREFIXES.some((prefix) => value.startsWith(prefix))) {
|
|
494
|
+
return true;
|
|
495
|
+
}
|
|
496
|
+
try {
|
|
497
|
+
const url = new URL(value);
|
|
498
|
+
return url.protocol === "http:" || url.protocol === "https:";
|
|
499
|
+
} catch {
|
|
500
|
+
return false;
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
var URL_PROPS = /* @__PURE__ */ new Set([
|
|
504
|
+
"src",
|
|
505
|
+
"href",
|
|
506
|
+
"xlinkhref",
|
|
507
|
+
"xlink:href",
|
|
508
|
+
// Obsolete but still implemented URL-bearing attributes on allowed elements.
|
|
509
|
+
"background",
|
|
510
|
+
"longdesc",
|
|
511
|
+
"usemap"
|
|
512
|
+
]);
|
|
513
|
+
function isTemplateUrlProp(name) {
|
|
514
|
+
return URL_PROPS.has(name.toLowerCase());
|
|
515
|
+
}
|
|
516
|
+
var SRCSET_PROPS = /* @__PURE__ */ new Set([
|
|
517
|
+
"srcset",
|
|
518
|
+
// React spells the preload attribute `imageSrcSet`; keep it guarded if the
|
|
519
|
+
// element allowlist ever expands to include `link`.
|
|
520
|
+
"imagesrcset"
|
|
521
|
+
]);
|
|
522
|
+
function isTemplateSrcSetProp(name) {
|
|
523
|
+
return SRCSET_PROPS.has(name.toLowerCase());
|
|
524
|
+
}
|
|
525
|
+
function isSafeTemplateSrcSet(value) {
|
|
526
|
+
if (typeof value !== "string" || value.trim() === "") return false;
|
|
527
|
+
return value.split(",").every((candidate) => {
|
|
528
|
+
const parts = candidate.trim().split(/\s+/);
|
|
529
|
+
if (parts.length === 0 || parts.length > 2 || !isSafeTemplateUrl(parts[0])) {
|
|
530
|
+
return false;
|
|
531
|
+
}
|
|
532
|
+
const descriptor = parts[1];
|
|
533
|
+
if (descriptor === void 0) return true;
|
|
534
|
+
if (/^[1-9]\d*w$/.test(descriptor)) return true;
|
|
535
|
+
if (/^(?:\d+(?:\.\d+)?|\.\d+)x$/.test(descriptor)) {
|
|
536
|
+
return Number.parseFloat(descriptor) > 0;
|
|
537
|
+
}
|
|
538
|
+
return false;
|
|
539
|
+
});
|
|
540
|
+
}
|
|
541
|
+
var URL_FUNCTION_PATTERN = /url\s*\(/i;
|
|
542
|
+
var SVG_URL_FUNCTION_PROPS = /* @__PURE__ */ new Set([
|
|
543
|
+
"clip-path",
|
|
544
|
+
"clippath",
|
|
545
|
+
"color-profile",
|
|
546
|
+
"colorprofile",
|
|
547
|
+
"cursor",
|
|
548
|
+
"fill",
|
|
549
|
+
"filter",
|
|
550
|
+
"marker",
|
|
551
|
+
"marker-end",
|
|
552
|
+
"marker-mid",
|
|
553
|
+
"marker-start",
|
|
554
|
+
"markerend",
|
|
555
|
+
"markermid",
|
|
556
|
+
"markerstart",
|
|
557
|
+
"mask",
|
|
558
|
+
"stroke"
|
|
559
|
+
]);
|
|
560
|
+
function isTemplatePaintProp(name) {
|
|
561
|
+
return SVG_URL_FUNCTION_PROPS.has(name.toLowerCase());
|
|
562
|
+
}
|
|
563
|
+
function isSafeTemplatePaintValue(value) {
|
|
564
|
+
if (typeof value === "string") return !URL_FUNCTION_PATTERN.test(value);
|
|
565
|
+
if (!Array.isArray(value) || value.length === 0) return false;
|
|
566
|
+
return value.every(
|
|
567
|
+
(candidate) => typeof candidate === "string" && !URL_FUNCTION_PATTERN.test(candidate)
|
|
568
|
+
);
|
|
569
|
+
}
|
|
570
|
+
var BLOCKED_STYLE_PROPS = /* @__PURE__ */ new Set([
|
|
571
|
+
"backgroundImage",
|
|
572
|
+
"background",
|
|
573
|
+
"listStyleImage",
|
|
574
|
+
"content",
|
|
575
|
+
"borderImage",
|
|
576
|
+
"borderImageSource",
|
|
577
|
+
"maskImage",
|
|
578
|
+
"mask",
|
|
579
|
+
"filter",
|
|
580
|
+
"cursor"
|
|
581
|
+
]);
|
|
582
|
+
function sanitizeTemplateStyle(style) {
|
|
583
|
+
if (!style || typeof style !== "object" || Array.isArray(style)) return {};
|
|
584
|
+
const safe = {};
|
|
585
|
+
for (const [key, value] of Object.entries(style)) {
|
|
586
|
+
if (BLOCKED_STYLE_PROPS.has(key)) continue;
|
|
587
|
+
if (typeof value === "string" && URL_FUNCTION_PATTERN.test(value)) continue;
|
|
588
|
+
if (key === "position" && typeof value === "string" && /fixed|sticky/i.test(value)) {
|
|
589
|
+
continue;
|
|
590
|
+
}
|
|
591
|
+
if (key === "zIndex") {
|
|
592
|
+
const numericValue = typeof value === "number" ? value : parseInt(String(value), 10);
|
|
593
|
+
if (isNaN(numericValue) || numericValue > 9998) continue;
|
|
594
|
+
}
|
|
595
|
+
safe[key] = value;
|
|
596
|
+
}
|
|
597
|
+
return safe;
|
|
598
|
+
}
|
|
599
|
+
function sanitizeTemplateProps(props) {
|
|
600
|
+
const safeProps = {};
|
|
601
|
+
for (const [key, value] of Object.entries(props)) {
|
|
602
|
+
const normalizedKey = key.toLowerCase();
|
|
603
|
+
if (normalizedKey.startsWith("on")) continue;
|
|
604
|
+
if (key === "dangerouslySetInnerHTML" || key === "ref") continue;
|
|
605
|
+
if (isTemplateUrlProp(key) && !isSafeTemplateUrl(value)) continue;
|
|
606
|
+
if (isTemplateSrcSetProp(key) && !isSafeTemplateSrcSet(value)) continue;
|
|
607
|
+
if (isTemplatePaintProp(key) && !isSafeTemplatePaintValue(value)) {
|
|
608
|
+
continue;
|
|
609
|
+
}
|
|
610
|
+
if (normalizedKey === "style") {
|
|
611
|
+
safeProps.style = sanitizeTemplateStyle(value);
|
|
612
|
+
continue;
|
|
613
|
+
}
|
|
614
|
+
safeProps[key] = value;
|
|
615
|
+
}
|
|
616
|
+
return safeProps;
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
// src/ui/Canvas/template-compiler.ts
|
|
620
|
+
var WIRE_FORMAT_VERSION = 1;
|
|
621
|
+
var MAX_CACHE_SIZE = 100;
|
|
622
|
+
var MAX_MATERIALIZE_DEPTH = 20;
|
|
451
623
|
var VM_SETUP = `
|
|
452
624
|
var React = {
|
|
453
625
|
createElement: function(type, props) {
|
|
@@ -484,52 +656,7 @@ function hashCode(str) {
|
|
|
484
656
|
return hash.toString(36);
|
|
485
657
|
}
|
|
486
658
|
function validateTemplateCode(code) {
|
|
487
|
-
return
|
|
488
|
-
}
|
|
489
|
-
var SAFE_DATA_URI_PREFIXES = [
|
|
490
|
-
"data:image/png;",
|
|
491
|
-
"data:image/jpeg;",
|
|
492
|
-
"data:image/gif;",
|
|
493
|
-
"data:image/webp;",
|
|
494
|
-
"data:image/avif;"
|
|
495
|
-
];
|
|
496
|
-
function isSafeUrl(value) {
|
|
497
|
-
if (typeof value !== "string") return false;
|
|
498
|
-
if (value.startsWith("/") || value.startsWith("./") || value.startsWith("../")) return true;
|
|
499
|
-
if (SAFE_DATA_URI_PREFIXES.some((p) => value.startsWith(p))) return true;
|
|
500
|
-
try {
|
|
501
|
-
const url = new URL(value);
|
|
502
|
-
return url.protocol === "http:" || url.protocol === "https:";
|
|
503
|
-
} catch {
|
|
504
|
-
return false;
|
|
505
|
-
}
|
|
506
|
-
}
|
|
507
|
-
var BLOCKED_STYLE_PROPS = /* @__PURE__ */ new Set([
|
|
508
|
-
"backgroundImage",
|
|
509
|
-
"background",
|
|
510
|
-
"listStyleImage",
|
|
511
|
-
"content",
|
|
512
|
-
"borderImage",
|
|
513
|
-
"borderImageSource",
|
|
514
|
-
"maskImage",
|
|
515
|
-
"mask",
|
|
516
|
-
"filter",
|
|
517
|
-
"cursor"
|
|
518
|
-
]);
|
|
519
|
-
function sanitizeStyle(style) {
|
|
520
|
-
if (!style || typeof style !== "object" || Array.isArray(style)) return {};
|
|
521
|
-
const safe = {};
|
|
522
|
-
for (const [k, v] of Object.entries(style)) {
|
|
523
|
-
if (BLOCKED_STYLE_PROPS.has(k)) continue;
|
|
524
|
-
if (typeof v === "string" && /url\s*\(/i.test(v)) continue;
|
|
525
|
-
if (k === "position" && typeof v === "string" && /fixed|sticky/i.test(v)) continue;
|
|
526
|
-
if (k === "zIndex") {
|
|
527
|
-
const n = typeof v === "number" ? v : parseInt(String(v), 10);
|
|
528
|
-
if (isNaN(n) || n > 9998) continue;
|
|
529
|
-
}
|
|
530
|
-
safe[k] = v;
|
|
531
|
-
}
|
|
532
|
-
return safe;
|
|
659
|
+
return findBlockedTemplatePattern(code) === null;
|
|
533
660
|
}
|
|
534
661
|
function materialize(node, depth = 0) {
|
|
535
662
|
if (depth > MAX_MATERIALIZE_DEPTH) return null;
|
|
@@ -557,18 +684,8 @@ function materialize(node, depth = 0) {
|
|
|
557
684
|
const type = String(d.type ?? "");
|
|
558
685
|
const props = d.props && typeof d.props === "object" ? d.props : {};
|
|
559
686
|
const ch = Array.isArray(d.ch) ? d.ch : [];
|
|
560
|
-
if (!
|
|
561
|
-
const safeProps =
|
|
562
|
-
for (const [k, v] of Object.entries(props)) {
|
|
563
|
-
if (k.startsWith("on")) continue;
|
|
564
|
-
if (k === "dangerouslySetInnerHTML" || k === "ref") continue;
|
|
565
|
-
if ((k === "src" || k === "href") && !isSafeUrl(v)) continue;
|
|
566
|
-
if (k === "style") {
|
|
567
|
-
safeProps[k] = sanitizeStyle(v);
|
|
568
|
-
continue;
|
|
569
|
-
}
|
|
570
|
-
safeProps[k] = v;
|
|
571
|
-
}
|
|
687
|
+
if (!isAllowedTemplateElement(type)) return null;
|
|
688
|
+
const safeProps = sanitizeTemplateProps(props);
|
|
572
689
|
const children = ch.map((c) => materialize(c, depth + 1));
|
|
573
690
|
return import_react4.default.createElement(type, safeProps, ...children);
|
|
574
691
|
}
|
|
@@ -852,19 +969,22 @@ function sanitizeImageData(image, safeUrl) {
|
|
|
852
969
|
) : image.sizes
|
|
853
970
|
};
|
|
854
971
|
}
|
|
855
|
-
function renderFieldValue(key, val, fieldDef) {
|
|
972
|
+
function renderFieldValue(key, val, fieldDef, imageAlt) {
|
|
856
973
|
if (val == null || val === "") return null;
|
|
857
974
|
const fieldType = fieldDef?.fieldType;
|
|
858
975
|
if (fieldType === "image" || typeof val === "object" && val !== null && "url" in val) {
|
|
859
976
|
const imgUrl = typeof val === "string" ? val : val?.url;
|
|
860
977
|
const safeUrl = sanitizeUrl(imgUrl);
|
|
861
978
|
if (!safeUrl) return null;
|
|
979
|
+
const embeddedAlt = typeof val === "object" && val !== null && "alt" in val && typeof val.alt === "string" ? val.alt : void 0;
|
|
980
|
+
const alt = imageAlt?.authored !== void 0 ? imageAlt.authored : embeddedAlt !== void 0 ? embeddedAlt : imageAlt?.fallback ?? "";
|
|
862
981
|
if (fieldType === "image" && typeof val === "object" && val !== null) {
|
|
863
982
|
return /* @__PURE__ */ import_react6.default.createElement(
|
|
864
983
|
Image,
|
|
865
984
|
{
|
|
866
985
|
key,
|
|
867
986
|
image: sanitizeImageData(val, safeUrl),
|
|
987
|
+
alt,
|
|
868
988
|
fill: true,
|
|
869
989
|
objectFit: "contain",
|
|
870
990
|
style: { flex: 1, minHeight: 0, width: "100%" }
|
|
@@ -876,7 +996,7 @@ function renderFieldValue(key, val, fieldDef) {
|
|
|
876
996
|
{
|
|
877
997
|
key,
|
|
878
998
|
src: safeUrl,
|
|
879
|
-
alt
|
|
999
|
+
alt,
|
|
880
1000
|
draggable: false,
|
|
881
1001
|
style: { flex: 1, minHeight: 0, width: "100%", objectFit: "contain" }
|
|
882
1002
|
}
|
|
@@ -899,6 +1019,7 @@ function renderFieldValue(key, val, fieldDef) {
|
|
|
899
1019
|
}
|
|
900
1020
|
function DefaultDynamicNode({ data }) {
|
|
901
1021
|
const d = data;
|
|
1022
|
+
const authoredImageAlt = typeof d.fields?.alt === "string" ? d.fields.alt : void 0;
|
|
902
1023
|
return /* @__PURE__ */ import_react6.default.createElement(
|
|
903
1024
|
"div",
|
|
904
1025
|
{
|
|
@@ -909,7 +1030,12 @@ function DefaultDynamicNode({ data }) {
|
|
|
909
1030
|
flexDirection: "column"
|
|
910
1031
|
}
|
|
911
1032
|
},
|
|
912
|
-
d.fields && Object.entries(d.fields).filter(([, v]) => v != null && v !== "").map(
|
|
1033
|
+
d.fields && Object.entries(d.fields).filter(([, v]) => v != null && v !== "").map(
|
|
1034
|
+
([key, val]) => renderFieldValue(key, val, void 0, {
|
|
1035
|
+
authored: authoredImageAlt,
|
|
1036
|
+
fallback: d.label
|
|
1037
|
+
})
|
|
1038
|
+
)
|
|
913
1039
|
);
|
|
914
1040
|
}
|
|
915
1041
|
var TemplateErrorBoundary = class extends import_react6.default.Component {
|
|
@@ -939,13 +1065,14 @@ function EnhancedDynamicNode({
|
|
|
939
1065
|
height
|
|
940
1066
|
}) {
|
|
941
1067
|
useQuickJS();
|
|
1068
|
+
const authoredImageAlt = typeof data.fields?.alt === "string" ? data.fields.alt : void 0;
|
|
942
1069
|
if (typeDef.template) {
|
|
943
1070
|
const Component = compileTemplate(typeDef.template, typeDef.slug);
|
|
944
1071
|
if (Component) {
|
|
945
1072
|
return /* @__PURE__ */ import_react6.default.createElement(
|
|
946
1073
|
"div",
|
|
947
1074
|
{
|
|
948
|
-
className: `flow-node flow-node--${typeDef.slug}${typeDef.transparentBackground ? "
|
|
1075
|
+
className: `flow-node flow-node--${typeDef.slug}${typeDef.transparentBackground ? "flow-node--transparent-bg" : ""}`,
|
|
949
1076
|
style: { width: "100%", height: "100%" }
|
|
950
1077
|
},
|
|
951
1078
|
/* @__PURE__ */ import_react6.default.createElement(TemplateErrorBoundary, { resetKey: typeDef.template }, /* @__PURE__ */ import_react6.default.createElement(
|
|
@@ -976,7 +1103,10 @@ function EnhancedDynamicNode({
|
|
|
976
1103
|
typeDef.fields.map((f) => {
|
|
977
1104
|
const val = data.fields[f.name];
|
|
978
1105
|
if (val == null || val === "") return null;
|
|
979
|
-
return renderFieldValue(f.name, val, f
|
|
1106
|
+
return renderFieldValue(f.name, val, f, {
|
|
1107
|
+
authored: authoredImageAlt,
|
|
1108
|
+
fallback: data.label
|
|
1109
|
+
});
|
|
980
1110
|
})
|
|
981
1111
|
);
|
|
982
1112
|
}
|
|
@@ -1022,6 +1152,90 @@ function DefaultFrameNode({ data }) {
|
|
|
1022
1152
|
)
|
|
1023
1153
|
);
|
|
1024
1154
|
}
|
|
1155
|
+
var DEFAULT_SHAPE_COLOR = "#dbeafe";
|
|
1156
|
+
var SHAPE_STROKE = "#334155";
|
|
1157
|
+
function ShapeGeometry({ shape, color }) {
|
|
1158
|
+
const common = {
|
|
1159
|
+
fill: color,
|
|
1160
|
+
stroke: SHAPE_STROKE,
|
|
1161
|
+
strokeWidth: 2,
|
|
1162
|
+
vectorEffect: "non-scaling-stroke"
|
|
1163
|
+
};
|
|
1164
|
+
switch (shape) {
|
|
1165
|
+
case "terminator":
|
|
1166
|
+
return /* @__PURE__ */ import_react6.default.createElement("rect", { x: "1", y: "1", width: "198", height: "98", rx: "49", ...common });
|
|
1167
|
+
case "decision":
|
|
1168
|
+
return /* @__PURE__ */ import_react6.default.createElement("polygon", { points: "100,1 199,50 100,99 1,50", ...common });
|
|
1169
|
+
case "io":
|
|
1170
|
+
return /* @__PURE__ */ import_react6.default.createElement("polygon", { points: "25,1 199,1 175,99 1,99", ...common });
|
|
1171
|
+
case "subprocess":
|
|
1172
|
+
return /* @__PURE__ */ import_react6.default.createElement("g", null, /* @__PURE__ */ import_react6.default.createElement("rect", { x: "1", y: "1", width: "198", height: "98", rx: "3", ...common }), /* @__PURE__ */ import_react6.default.createElement(
|
|
1173
|
+
"path",
|
|
1174
|
+
{
|
|
1175
|
+
d: "M20 1V99M180 1V99",
|
|
1176
|
+
fill: "none",
|
|
1177
|
+
stroke: SHAPE_STROKE,
|
|
1178
|
+
strokeWidth: "2",
|
|
1179
|
+
vectorEffect: "non-scaling-stroke"
|
|
1180
|
+
}
|
|
1181
|
+
));
|
|
1182
|
+
case "process":
|
|
1183
|
+
default:
|
|
1184
|
+
return /* @__PURE__ */ import_react6.default.createElement("rect", { x: "1", y: "1", width: "198", height: "98", rx: "3", ...common });
|
|
1185
|
+
}
|
|
1186
|
+
}
|
|
1187
|
+
function DefaultShapeNode({ data }) {
|
|
1188
|
+
const shapeData = data;
|
|
1189
|
+
return /* @__PURE__ */ import_react6.default.createElement(
|
|
1190
|
+
"div",
|
|
1191
|
+
{
|
|
1192
|
+
className: `flow-node flow-node--shape flow-node--shape-${shapeData.shape}`,
|
|
1193
|
+
style: { width: "100%", height: "100%", position: "relative" },
|
|
1194
|
+
"data-shape": shapeData.shape
|
|
1195
|
+
},
|
|
1196
|
+
/* @__PURE__ */ import_react6.default.createElement(
|
|
1197
|
+
"svg",
|
|
1198
|
+
{
|
|
1199
|
+
"aria-hidden": "true",
|
|
1200
|
+
focusable: "false",
|
|
1201
|
+
viewBox: "0 0 200 100",
|
|
1202
|
+
preserveAspectRatio: "none",
|
|
1203
|
+
style: {
|
|
1204
|
+
position: "absolute",
|
|
1205
|
+
inset: 0,
|
|
1206
|
+
width: "100%",
|
|
1207
|
+
height: "100%"
|
|
1208
|
+
}
|
|
1209
|
+
},
|
|
1210
|
+
/* @__PURE__ */ import_react6.default.createElement(
|
|
1211
|
+
ShapeGeometry,
|
|
1212
|
+
{
|
|
1213
|
+
shape: shapeData.shape,
|
|
1214
|
+
color: shapeData.color ?? DEFAULT_SHAPE_COLOR
|
|
1215
|
+
}
|
|
1216
|
+
)
|
|
1217
|
+
),
|
|
1218
|
+
/* @__PURE__ */ import_react6.default.createElement(
|
|
1219
|
+
"div",
|
|
1220
|
+
{
|
|
1221
|
+
style: {
|
|
1222
|
+
position: "absolute",
|
|
1223
|
+
inset: "12%",
|
|
1224
|
+
display: "flex",
|
|
1225
|
+
alignItems: "center",
|
|
1226
|
+
justifyContent: "center",
|
|
1227
|
+
overflow: "hidden",
|
|
1228
|
+
color: "#0f172a",
|
|
1229
|
+
fontSize: 12,
|
|
1230
|
+
fontWeight: 600,
|
|
1231
|
+
textAlign: "center",
|
|
1232
|
+
wordBreak: "break-word"
|
|
1233
|
+
}
|
|
1234
|
+
},
|
|
1235
|
+
shapeData.label
|
|
1236
|
+
)
|
|
1237
|
+
);
|
|
1238
|
+
}
|
|
1025
1239
|
|
|
1026
1240
|
// src/ui/Canvas/field-helpers.ts
|
|
1027
1241
|
function getImageField(fields, name) {
|
|
@@ -1234,9 +1448,12 @@ var import_react12 = require("@xyflow/react");
|
|
|
1234
1448
|
|
|
1235
1449
|
// src/ui/Canvas/node-types-factory.tsx
|
|
1236
1450
|
var import_react7 = __toESM(require("react"), 1);
|
|
1451
|
+
function areNodePropsEqual(prev, next) {
|
|
1452
|
+
return prev.id === next.id && prev.data === next.data && prev.selected === next.selected && prev.dragging === next.dragging && prev.width === next.width && prev.height === next.height;
|
|
1453
|
+
}
|
|
1237
1454
|
function createNodeTypes(nodeRenderers, nodeTypeDefsMap, frameRenderer, nodeWrapper, renderNode) {
|
|
1238
1455
|
const types = {};
|
|
1239
|
-
|
|
1456
|
+
const DynamicNode = (props) => {
|
|
1240
1457
|
const d = props.data;
|
|
1241
1458
|
const typeDef = nodeTypeDefsMap?.get(d.nodeTypeSlug);
|
|
1242
1459
|
const CustomRenderer = nodeRenderers?.[d.nodeTypeSlug];
|
|
@@ -1285,8 +1502,12 @@ function createNodeTypes(nodeRenderers, nodeTypeDefsMap, frameRenderer, nodeWrap
|
|
|
1285
1502
|
);
|
|
1286
1503
|
}
|
|
1287
1504
|
return content;
|
|
1288
|
-
}
|
|
1289
|
-
types.
|
|
1505
|
+
};
|
|
1506
|
+
types.dynamic = import_react7.default.memo(
|
|
1507
|
+
DynamicNode,
|
|
1508
|
+
areNodePropsEqual
|
|
1509
|
+
);
|
|
1510
|
+
const FrameNode = frameRenderer ? (props) => {
|
|
1290
1511
|
const d = props.data;
|
|
1291
1512
|
const Renderer = frameRenderer;
|
|
1292
1513
|
return /* @__PURE__ */ import_react7.default.createElement(
|
|
@@ -1302,7 +1523,10 @@ function createNodeTypes(nodeRenderers, nodeTypeDefsMap, frameRenderer, nodeWrap
|
|
|
1302
1523
|
height: props.height
|
|
1303
1524
|
}
|
|
1304
1525
|
);
|
|
1305
|
-
}
|
|
1526
|
+
} : DefaultFrameNode;
|
|
1527
|
+
types.frame = import_react7.default.memo(FrameNode, areNodePropsEqual);
|
|
1528
|
+
const ShapeNode = (props) => /* @__PURE__ */ import_react7.default.createElement(DefaultShapeNode, { ...props });
|
|
1529
|
+
types.shape = import_react7.default.memo(ShapeNode, areNodePropsEqual);
|
|
1306
1530
|
return types;
|
|
1307
1531
|
}
|
|
1308
1532
|
function createEdgeTypes(edgeRenderers, edgeTypeDefsMap) {
|
|
@@ -1512,18 +1736,82 @@ function FocusHandler({
|
|
|
1512
1736
|
);
|
|
1513
1737
|
}
|
|
1514
1738
|
|
|
1739
|
+
// src/ui/Canvas/accessibility.ts
|
|
1740
|
+
var CANVAS_ACCESSIBILITY_LABELS = {
|
|
1741
|
+
ko: {
|
|
1742
|
+
canvas: "\uCE94\uBC84\uC2A4 \uB2E4\uC774\uC5B4\uADF8\uB7A8",
|
|
1743
|
+
node: "\uB178\uB4DC",
|
|
1744
|
+
frame: "\uD504\uB808\uC784",
|
|
1745
|
+
ariaLabelConfig: {
|
|
1746
|
+
"node.a11yDescription.default": "\uCE94\uBC84\uC2A4 \uB2E4\uC774\uC5B4\uADF8\uB7A8\uC758 \uB178\uB4DC\uC785\uB2C8\uB2E4.",
|
|
1747
|
+
"node.a11yDescription.keyboardDisabled": "\uCE94\uBC84\uC2A4 \uB2E4\uC774\uC5B4\uADF8\uB7A8\uC758 \uB178\uB4DC\uC785\uB2C8\uB2E4.",
|
|
1748
|
+
"edge.a11yDescription.default": "\uCE94\uBC84\uC2A4 \uB2E4\uC774\uC5B4\uADF8\uB7A8\uC758 \uC5F0\uACB0\uC120\uC785\uB2C8\uB2E4.",
|
|
1749
|
+
"controls.ariaLabel": "\uCE94\uBC84\uC2A4 \uC81C\uC5B4\uD310",
|
|
1750
|
+
"controls.zoomIn.ariaLabel": "\uD655\uB300",
|
|
1751
|
+
"controls.zoomOut.ariaLabel": "\uCD95\uC18C",
|
|
1752
|
+
"controls.fitView.ariaLabel": "\uD654\uBA74\uC5D0 \uB9DE\uCD94\uAE30",
|
|
1753
|
+
"controls.interactive.ariaLabel": "\uC0C1\uD638\uC791\uC6A9 \uC804\uD658",
|
|
1754
|
+
"minimap.ariaLabel": "\uBBF8\uB2C8\uB9F5",
|
|
1755
|
+
"handle.ariaLabel": "\uC5F0\uACB0\uC810"
|
|
1756
|
+
}
|
|
1757
|
+
},
|
|
1758
|
+
en: {
|
|
1759
|
+
canvas: "Canvas diagram",
|
|
1760
|
+
node: "Node",
|
|
1761
|
+
frame: "Frame",
|
|
1762
|
+
ariaLabelConfig: {
|
|
1763
|
+
"node.a11yDescription.default": "A node in the canvas diagram.",
|
|
1764
|
+
"node.a11yDescription.keyboardDisabled": "A node in the canvas diagram.",
|
|
1765
|
+
"edge.a11yDescription.default": "A connection in the canvas diagram.",
|
|
1766
|
+
"controls.ariaLabel": "Canvas controls",
|
|
1767
|
+
"controls.zoomIn.ariaLabel": "Zoom in",
|
|
1768
|
+
"controls.zoomOut.ariaLabel": "Zoom out",
|
|
1769
|
+
"controls.fitView.ariaLabel": "Fit view",
|
|
1770
|
+
"controls.interactive.ariaLabel": "Toggle interactivity",
|
|
1771
|
+
"minimap.ariaLabel": "Mini map",
|
|
1772
|
+
"handle.ariaLabel": "Handle"
|
|
1773
|
+
}
|
|
1774
|
+
}
|
|
1775
|
+
};
|
|
1776
|
+
function nodeAriaLabel(node, labels) {
|
|
1777
|
+
const explicitLabel = typeof node.ariaLabel === "string" ? node.ariaLabel.trim() : "";
|
|
1778
|
+
if (explicitLabel) return explicitLabel;
|
|
1779
|
+
const isFrame = node.type === "frame";
|
|
1780
|
+
const label = node.data?.label?.trim();
|
|
1781
|
+
if (!label) return isFrame ? labels.frame : labels.node;
|
|
1782
|
+
return isFrame ? `${label} (${labels.frame})` : label;
|
|
1783
|
+
}
|
|
1784
|
+
|
|
1515
1785
|
// src/ui/Canvas/CanvasRenderer.tsx
|
|
1786
|
+
function usePrefersReducedMotion() {
|
|
1787
|
+
const query = "(prefers-reduced-motion: reduce)";
|
|
1788
|
+
const [prefersReducedMotion, setPrefersReducedMotion] = import_react11.default.useState(
|
|
1789
|
+
() => typeof window !== "undefined" && window.matchMedia?.(query).matches
|
|
1790
|
+
);
|
|
1791
|
+
import_react11.default.useEffect(() => {
|
|
1792
|
+
if (typeof window === "undefined" || !window.matchMedia) return;
|
|
1793
|
+
const mediaQuery = window.matchMedia(query);
|
|
1794
|
+
const handleChange = (event) => setPrefersReducedMotion(event.matches);
|
|
1795
|
+
setPrefersReducedMotion(mediaQuery.matches);
|
|
1796
|
+
mediaQuery.addEventListener("change", handleChange);
|
|
1797
|
+
return () => mediaQuery.removeEventListener("change", handleChange);
|
|
1798
|
+
}, []);
|
|
1799
|
+
return prefersReducedMotion;
|
|
1800
|
+
}
|
|
1516
1801
|
var NullFrameRenderer = () => null;
|
|
1517
1802
|
function CanvasRenderer({
|
|
1518
1803
|
data,
|
|
1519
1804
|
className,
|
|
1520
1805
|
style,
|
|
1806
|
+
ariaLabel,
|
|
1807
|
+
locale = "en",
|
|
1521
1808
|
nodeRenderers,
|
|
1522
1809
|
nodeTypeDefs,
|
|
1523
1810
|
edgeTypeDefs,
|
|
1524
1811
|
background = false,
|
|
1525
1812
|
interactive = false,
|
|
1526
1813
|
fitView = true,
|
|
1814
|
+
onlyRenderVisibleElements = true,
|
|
1527
1815
|
onNodeClick,
|
|
1528
1816
|
onNodeDoubleClick,
|
|
1529
1817
|
onNodeContextMenu,
|
|
@@ -1551,6 +1839,8 @@ function CanvasRenderer({
|
|
|
1551
1839
|
minZoom: minZoomProp,
|
|
1552
1840
|
maxZoom: maxZoomProp
|
|
1553
1841
|
}) {
|
|
1842
|
+
const prefersReducedMotion = usePrefersReducedMotion();
|
|
1843
|
+
const accessibilityLabels = CANVAS_ACCESSIBILITY_LABELS[locale];
|
|
1554
1844
|
const resolvedFrameRenderer = hideFrames ? NullFrameRenderer : frameRenderer;
|
|
1555
1845
|
const nodeTypeDefsMap = import_react11.default.useMemo(() => {
|
|
1556
1846
|
if (!nodeTypeDefs?.length) return void 0;
|
|
@@ -1568,7 +1858,13 @@ function CanvasRenderer({
|
|
|
1568
1858
|
nodeWrapper,
|
|
1569
1859
|
renderNode
|
|
1570
1860
|
),
|
|
1571
|
-
[
|
|
1861
|
+
[
|
|
1862
|
+
nodeRenderers,
|
|
1863
|
+
nodeTypeDefsMap,
|
|
1864
|
+
resolvedFrameRenderer,
|
|
1865
|
+
nodeWrapper,
|
|
1866
|
+
renderNode
|
|
1867
|
+
]
|
|
1572
1868
|
);
|
|
1573
1869
|
const customEdgeTypes = import_react11.default.useMemo(
|
|
1574
1870
|
() => createEdgeTypes(edgeRenderers, edgeTypeDefsMap),
|
|
@@ -1591,6 +1887,21 @@ function CanvasRenderer({
|
|
|
1591
1887
|
}
|
|
1592
1888
|
return edges;
|
|
1593
1889
|
}, [data?.edges, edgeTypeDefsMap, edgeRenderers]);
|
|
1890
|
+
const accessibleNodes = import_react11.default.useMemo(
|
|
1891
|
+
() => (data?.nodes ?? []).map((node) => ({
|
|
1892
|
+
...node,
|
|
1893
|
+
...node.type === "shape" ? {
|
|
1894
|
+
style: {
|
|
1895
|
+
...node.style,
|
|
1896
|
+
background: "transparent",
|
|
1897
|
+
border: "none",
|
|
1898
|
+
padding: 0
|
|
1899
|
+
}
|
|
1900
|
+
} : {},
|
|
1901
|
+
ariaLabel: nodeAriaLabel(node, accessibilityLabels)
|
|
1902
|
+
})),
|
|
1903
|
+
[data?.nodes, accessibilityLabels]
|
|
1904
|
+
);
|
|
1594
1905
|
const translateExtent = import_react11.default.useMemo(() => {
|
|
1595
1906
|
if (translateExtentProp) return translateExtentProp;
|
|
1596
1907
|
const es = clampBounds ?? bounds;
|
|
@@ -1625,6 +1936,8 @@ function CanvasRenderer({
|
|
|
1625
1936
|
return /* @__PURE__ */ import_react11.default.createElement(import_react12.ReactFlowProvider, null, /* @__PURE__ */ import_react11.default.createElement(
|
|
1626
1937
|
"div",
|
|
1627
1938
|
{
|
|
1939
|
+
role: "region",
|
|
1940
|
+
"aria-label": ariaLabel ?? accessibilityLabels.canvas,
|
|
1628
1941
|
className,
|
|
1629
1942
|
style: {
|
|
1630
1943
|
width: "100%",
|
|
@@ -1636,12 +1949,13 @@ function CanvasRenderer({
|
|
|
1636
1949
|
/* @__PURE__ */ import_react11.default.createElement(
|
|
1637
1950
|
import_react12.ReactFlow,
|
|
1638
1951
|
{
|
|
1639
|
-
nodes:
|
|
1952
|
+
nodes: accessibleNodes,
|
|
1640
1953
|
edges: styledEdges,
|
|
1641
1954
|
nodeTypes,
|
|
1642
1955
|
edgeTypes: customEdgeTypes,
|
|
1643
1956
|
defaultViewport: resolvedDefaultViewport,
|
|
1644
1957
|
fitView: bounds ? false : fitView,
|
|
1958
|
+
onlyRenderVisibleElements,
|
|
1645
1959
|
translateExtent: activeExtent,
|
|
1646
1960
|
onNodeClick,
|
|
1647
1961
|
onNodeDoubleClick,
|
|
@@ -1655,13 +1969,15 @@ function CanvasRenderer({
|
|
|
1655
1969
|
nodesDraggable: interactive,
|
|
1656
1970
|
nodesConnectable: false,
|
|
1657
1971
|
elementsSelectable: interactive || !!onNodeClick || !!onNodeDoubleClick || !!onEdgeClick,
|
|
1972
|
+
autoPanOnSelection: false,
|
|
1658
1973
|
panOnDrag: interactive,
|
|
1659
1974
|
zoomOnScroll: interactive,
|
|
1660
1975
|
zoomOnPinch: interactive,
|
|
1661
1976
|
zoomOnDoubleClick: false,
|
|
1662
1977
|
minZoom: minZoomProp,
|
|
1663
1978
|
maxZoom: maxZoomProp,
|
|
1664
|
-
proOptions: { hideAttribution: true }
|
|
1979
|
+
proOptions: { hideAttribution: true },
|
|
1980
|
+
ariaLabelConfig: accessibilityLabels.ariaLabelConfig
|
|
1665
1981
|
},
|
|
1666
1982
|
mergedCSS && /* @__PURE__ */ import_react11.default.createElement("style", { dangerouslySetInnerHTML: { __html: mergedCSS } }),
|
|
1667
1983
|
background && /* @__PURE__ */ import_react11.default.createElement(import_react12.Background, null),
|
|
@@ -1677,7 +1993,7 @@ function CanvasRenderer({
|
|
|
1677
1993
|
{
|
|
1678
1994
|
bounds,
|
|
1679
1995
|
padding: focusPadding ?? 0.1,
|
|
1680
|
-
animation: focusAnimation ?? true,
|
|
1996
|
+
animation: prefersReducedMotion ? false : focusAnimation ?? true,
|
|
1681
1997
|
mode: focusMode,
|
|
1682
1998
|
responsive: responsiveFit ?? true,
|
|
1683
1999
|
extent: translateExtent,
|