@01.software/sdk 0.4.3 → 0.5.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.
Files changed (40) hide show
  1. package/README.md +13 -13
  2. package/dist/auth.d.cts +1 -1
  3. package/dist/auth.d.ts +1 -1
  4. package/dist/{const-C3GC2SxR.d.cts → const-BO4SPN7f.d.ts} +2 -2
  5. package/dist/{const-ikSyKVND.d.ts → const-hqVXNZoy.d.cts} +2 -2
  6. package/dist/index.cjs +9 -7
  7. package/dist/index.cjs.map +1 -1
  8. package/dist/index.d.cts +27 -18
  9. package/dist/index.d.ts +27 -18
  10. package/dist/index.js +9 -7
  11. package/dist/index.js.map +1 -1
  12. package/dist/{payload-types-DPka7hJu.d.cts → payload-types-mZpmjJBz.d.cts} +102 -4
  13. package/dist/{payload-types-DPka7hJu.d.ts → payload-types-mZpmjJBz.d.ts} +102 -4
  14. package/dist/realtime.cjs.map +1 -1
  15. package/dist/realtime.d.cts +2 -2
  16. package/dist/realtime.d.ts +2 -2
  17. package/dist/realtime.js.map +1 -1
  18. package/dist/server-B80o7igg.d.cts +242 -0
  19. package/dist/server-B80o7igg.d.ts +242 -0
  20. package/dist/ui/flow/server.cjs +233 -0
  21. package/dist/ui/flow/server.cjs.map +1 -0
  22. package/dist/ui/flow/server.d.cts +3 -0
  23. package/dist/ui/flow/server.d.ts +3 -0
  24. package/dist/ui/flow/server.js +213 -0
  25. package/dist/ui/flow/server.js.map +1 -0
  26. package/dist/ui/flow.cjs +540 -127
  27. package/dist/ui/flow.cjs.map +1 -1
  28. package/dist/ui/flow.d.cts +39 -189
  29. package/dist/ui/flow.d.ts +39 -189
  30. package/dist/ui/flow.js +544 -135
  31. package/dist/ui/flow.js.map +1 -1
  32. package/dist/ui/form.d.cts +1 -1
  33. package/dist/ui/form.d.ts +1 -1
  34. package/dist/ui/video.d.cts +1 -1
  35. package/dist/ui/video.d.ts +1 -1
  36. package/dist/{webhook-CvNTdBWV.d.ts → webhook-CMi4JRCp.d.ts} +3 -3
  37. package/dist/{webhook-B8BfJ_Ka.d.cts → webhook-D65mzWt2.d.cts} +3 -3
  38. package/dist/webhook.d.cts +3 -3
  39. package/dist/webhook.d.ts +3 -3
  40. package/package.json +19 -14
package/dist/ui/flow.js CHANGED
@@ -39,18 +39,6 @@ var __async = (__this, __arguments, generator) => {
39
39
  });
40
40
  };
41
41
 
42
- // src/ui/Flow/index.tsx
43
- import React from "react";
44
- import {
45
- ReactFlow,
46
- ReactFlowProvider,
47
- Background,
48
- Controls,
49
- MiniMap,
50
- MarkerType,
51
- useReactFlow
52
- } from "@xyflow/react";
53
-
54
42
  // src/ui/Flow/types.ts
55
43
  function isDynamicNode(node) {
56
44
  return node.type === "dynamic";
@@ -116,7 +104,7 @@ function collectionKeys(collection) {
116
104
 
117
105
  // src/ui/Flow/useFlow.ts
118
106
  function toNodeTypeDef(doc) {
119
- var _a, _b, _c, _d;
107
+ var _a, _b, _c, _d, _e, _f;
120
108
  return {
121
109
  slug: String((_a = doc.slug) != null ? _a : ""),
122
110
  name: String((_b = doc.title) != null ? _b : ""),
@@ -126,7 +114,9 @@ function toNodeTypeDef(doc) {
126
114
  height: 200
127
115
  },
128
116
  fields: Array.isArray(doc.fields) ? doc.fields : [],
129
- transparentBackground: Boolean(doc.transparentBackground)
117
+ transparentBackground: Boolean(doc.transparentBackground),
118
+ template: (_e = doc.template) != null ? _e : null,
119
+ customCSS: (_f = doc.customCSS) != null ? _f : null
130
120
  };
131
121
  }
132
122
  function toEdgeTypeDef(doc) {
@@ -215,6 +205,44 @@ function useFlow(options) {
215
205
  };
216
206
  }
217
207
 
208
+ // src/ui/Flow/prefetchFlow.ts
209
+ function prefetchFlow(options) {
210
+ return __async(this, null, function* () {
211
+ var _a;
212
+ const { client, slug, id } = options;
213
+ const identifier = (_a = id != null ? id : slug) != null ? _a : "";
214
+ yield Promise.all([
215
+ client.queryClient.prefetchQuery({
216
+ queryKey: collectionKeys("flows").detail(identifier),
217
+ queryFn: () => __async(null, null, function* () {
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
+ })
242
+ ]);
243
+ });
244
+ }
245
+
218
246
  // src/ui/Flow/useFlowData.ts
219
247
  import { useMemo as useMemo2 } from "react";
220
248
  function useFlowData(options) {
@@ -244,37 +272,57 @@ function useFlowData(options) {
244
272
  }
245
273
 
246
274
  // src/ui/Flow/utils.ts
247
- function getNodeBounds(nodes, nodeIds) {
275
+ function getNodeSize(node) {
248
276
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
277
+ return {
278
+ width: (_e = (_d = (_c = (_a = node.style) == null ? void 0 : _a.width) != null ? _c : (_b = node.measured) == null ? void 0 : _b.width) != null ? _d : node.width) != null ? _e : 200,
279
+ height: (_j = (_i = (_h = (_f = node.style) == null ? void 0 : _f.height) != null ? _h : (_g = node.measured) == null ? void 0 : _g.height) != null ? _i : node.height) != null ? _j : 200
280
+ };
281
+ }
282
+ function getAbsolutePosition(node, nodeMap) {
283
+ let x = node.position.x;
284
+ let y = node.position.y;
285
+ let current = node;
286
+ const visited = /* @__PURE__ */ new Set([node.id]);
287
+ while (current.parentId) {
288
+ const parentId = current.parentId;
289
+ if (visited.has(parentId)) break;
290
+ const parent = nodeMap.get(parentId);
291
+ if (!parent) break;
292
+ visited.add(parent.id);
293
+ x += parent.position.x;
294
+ y += parent.position.y;
295
+ current = parent;
296
+ }
297
+ return { x, y };
298
+ }
299
+ function collectDescendants(nodes, rootId) {
300
+ const result = /* @__PURE__ */ new Set([rootId]);
301
+ const queue = [rootId];
302
+ let i = 0;
303
+ while (i < queue.length) {
304
+ const current = queue[i++];
305
+ for (const n of nodes) {
306
+ if (n.parentId === current && !result.has(n.id)) {
307
+ result.add(n.id);
308
+ queue.push(n.id);
309
+ }
310
+ }
311
+ }
312
+ return result;
313
+ }
314
+ function getNodeBounds(nodes, nodeIds) {
249
315
  const idSet = new Set(nodeIds);
250
316
  const targetNodes = nodes.filter((n) => idSet.has(n.id));
251
317
  if (targetNodes.length === 0) return void 0;
252
318
  const nodeMap = new Map(nodes.map((n) => [n.id, n]));
253
- function getAbsolutePosition(node) {
254
- let x = node.position.x;
255
- let y = node.position.y;
256
- let current = node;
257
- const visited = /* @__PURE__ */ new Set([node.id]);
258
- while (current.parentId) {
259
- const parentId = current.parentId;
260
- if (visited.has(parentId)) break;
261
- const parent = nodeMap.get(parentId);
262
- if (!parent) break;
263
- visited.add(parent.id);
264
- x += parent.position.x;
265
- y += parent.position.y;
266
- current = parent;
267
- }
268
- return { x, y };
269
- }
270
319
  let minX = Infinity;
271
320
  let minY = Infinity;
272
321
  let maxX = -Infinity;
273
322
  let maxY = -Infinity;
274
323
  for (const node of targetNodes) {
275
- const abs = getAbsolutePosition(node);
276
- const w = (_e = (_d = (_c = (_a = node.style) == null ? void 0 : _a.width) != null ? _c : (_b = node.measured) == null ? void 0 : _b.width) != null ? _d : node.width) != null ? _e : 200;
277
- const h = (_j = (_i = (_h = (_f = node.style) == null ? void 0 : _f.height) != null ? _h : (_g = node.measured) == null ? void 0 : _g.height) != null ? _i : node.height) != null ? _j : 200;
324
+ const abs = getAbsolutePosition(node, nodeMap);
325
+ const { width: w, height: h } = getNodeSize(node);
278
326
  minX = Math.min(minX, abs.x);
279
327
  minY = Math.min(minY, abs.y);
280
328
  maxX = Math.max(maxX, abs.x + w);
@@ -286,34 +334,156 @@ function getFrames(nodes) {
286
334
  const frames = nodes.filter((n) => n.type === "frame");
287
335
  if (frames.length === 0) return [];
288
336
  const nodeMap = new Map(nodes.map((n) => [n.id, n]));
289
- function getAbsolutePosition(node) {
290
- let x = node.position.x;
291
- let y = node.position.y;
292
- let current = node;
293
- const visited = /* @__PURE__ */ new Set([node.id]);
294
- while (current.parentId) {
295
- const parentId = current.parentId;
296
- if (visited.has(parentId)) break;
297
- const parent = nodeMap.get(parentId);
298
- if (!parent) break;
299
- visited.add(parent.id);
300
- x += parent.position.x;
301
- y += parent.position.y;
302
- current = parent;
303
- }
304
- return { x, y };
305
- }
306
337
  return frames.map((f) => {
307
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
338
+ var _a;
308
339
  const data = f.data;
309
- const abs = getAbsolutePosition(f);
310
- const w = (_e = (_d = (_c = (_a = f.style) == null ? void 0 : _a.width) != null ? _c : (_b = f.measured) == null ? void 0 : _b.width) != null ? _d : f.width) != null ? _e : 200;
311
- const h = (_j = (_i = (_h = (_f = f.style) == null ? void 0 : _f.height) != null ? _h : (_g = f.measured) == null ? void 0 : _g.height) != null ? _i : f.height) != null ? _j : 200;
312
- return { id: f.id, label: (_k = data.label) != null ? _k : "", bounds: { x: abs.x, y: abs.y, width: w, height: h } };
340
+ const abs = getAbsolutePosition(f, nodeMap);
341
+ const { width: w, height: h } = getNodeSize(f);
342
+ return {
343
+ id: f.id,
344
+ label: (_a = data.label) != null ? _a : "",
345
+ bounds: { x: abs.x, y: abs.y, width: w, height: h }
346
+ };
313
347
  }).sort((a, b) => a.bounds.y - b.bounds.y || a.bounds.x - b.bounds.x);
314
348
  }
349
+ function getFrameData(data, frameId) {
350
+ const frame = data.nodes.find((n) => n.id === frameId);
351
+ if (!frame || frame.type !== "frame") return void 0;
352
+ const descendantIds = collectDescendants(data.nodes, frameId);
353
+ const childNodes = data.nodes.filter((n) => descendantIds.has(n.id)).map((n) => __spreadProps(__spreadValues({}, n), { draggable: false }));
354
+ const childEdges = data.edges.filter(
355
+ (e) => descendantIds.has(e.source) && descendantIds.has(e.target)
356
+ );
357
+ const frameBounds = getNodeBounds(data.nodes, [frameId]);
358
+ const { width: w, height: h } = getNodeSize(frame);
359
+ const clampBounds = frameBounds != null ? frameBounds : {
360
+ x: frame.position.x,
361
+ y: frame.position.y,
362
+ width: w,
363
+ height: h
364
+ };
365
+ const contentNodeIds = childNodes.filter((n) => n.id !== frameId).map((n) => n.id);
366
+ const contentBounds = contentNodeIds.length > 0 ? getNodeBounds(data.nodes, contentNodeIds) : void 0;
367
+ const fitBounds = contentBounds != null ? contentBounds : clampBounds;
368
+ return {
369
+ data: {
370
+ nodes: childNodes,
371
+ edges: childEdges,
372
+ viewport: data.viewport
373
+ },
374
+ fitBounds,
375
+ clampBounds,
376
+ bounds: clampBounds
377
+ };
378
+ }
379
+
380
+ // src/ui/Flow/template-compiler.ts
381
+ import React from "react";
382
+ import { transform } from "sucrase";
383
+ var MAX_CACHE_SIZE = 100;
384
+ var componentCache = /* @__PURE__ */ new Map();
385
+ function hashCode(str) {
386
+ let hash = 0;
387
+ for (let i = 0; i < str.length; i++) {
388
+ const char = str.charCodeAt(i);
389
+ hash = (hash << 5) - hash + char | 0;
390
+ }
391
+ return hash.toString(36);
392
+ }
393
+ var BLOCKED_PATTERNS = [
394
+ /\bdocument\s*\./,
395
+ /\bwindow\s*\./,
396
+ /\bwindow\s*\[/,
397
+ /\bglobalThis\s*\./,
398
+ /\bfetch\s*\(/,
399
+ /\bXMLHttpRequest/,
400
+ /\beval\s*\(/,
401
+ /\bFunction\s*\(/,
402
+ /\bimport\s*\(/,
403
+ /\blocalStorage/,
404
+ /\bsessionStorage/,
405
+ /\bcookie/,
406
+ /\bpostMessage\s*\(/,
407
+ /\blocation\s*[.=]/,
408
+ /\bnavigator\s*\./,
409
+ /\bsetTimeout\s*\(/,
410
+ /\bsetInterval\s*\(/,
411
+ /\bsetImmediate\s*\(/,
412
+ /\brequire\s*\(/
413
+ ];
414
+ function validateTemplateCode(code) {
415
+ return !BLOCKED_PATTERNS.some((pattern) => pattern.test(code));
416
+ }
417
+ function compileTemplate(code, slug) {
418
+ const cacheKey = `${slug}:${hashCode(code)}`;
419
+ if (componentCache.has(cacheKey)) {
420
+ const cached = componentCache.get(cacheKey);
421
+ componentCache.delete(cacheKey);
422
+ componentCache.set(cacheKey, cached);
423
+ return cached;
424
+ }
425
+ if (!validateTemplateCode(code)) {
426
+ console.warn(`[flow] Template "${slug}" contains blocked patterns`);
427
+ return null;
428
+ }
429
+ try {
430
+ const { code: jsCode } = transform(code, {
431
+ transforms: ["typescript", "jsx", "imports"],
432
+ jsxRuntime: "classic",
433
+ jsxPragma: "React.createElement",
434
+ jsxFragmentPragma: "React.Fragment"
435
+ });
436
+ const factory = new Function(
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;
463
+ } catch (e) {
464
+ console.warn(`[flow] Failed to compile template for "${slug}":`, e);
465
+ return null;
466
+ }
467
+ }
468
+ function clearTemplateCache() {
469
+ componentCache.clear();
470
+ }
315
471
 
316
- // src/ui/Flow/index.tsx
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
+ // src/ui/Flow/node-renderers.tsx
486
+ import React2 from "react";
317
487
  function sanitizeUrl(url) {
318
488
  if (!url) return url;
319
489
  try {
@@ -324,11 +494,6 @@ function sanitizeUrl(url) {
324
494
  return void 0;
325
495
  }
326
496
  }
327
- function toMarkerType(value) {
328
- if (value === "arrow") return MarkerType.Arrow;
329
- if (value === "arrowclosed") return MarkerType.ArrowClosed;
330
- return void 0;
331
- }
332
497
  function renderFieldValue(key, val, fieldDef) {
333
498
  if (val == null || val === "") return null;
334
499
  const fieldType = fieldDef == null ? void 0 : fieldDef.fieldType;
@@ -336,7 +501,7 @@ function renderFieldValue(key, val, fieldDef) {
336
501
  const imgUrl = typeof val === "string" ? val : val == null ? void 0 : val.url;
337
502
  const safeUrl = sanitizeUrl(imgUrl);
338
503
  if (!safeUrl) return null;
339
- return /* @__PURE__ */ React.createElement(
504
+ return /* @__PURE__ */ React2.createElement(
340
505
  "img",
341
506
  {
342
507
  key,
@@ -347,7 +512,7 @@ function renderFieldValue(key, val, fieldDef) {
347
512
  }
348
513
  );
349
514
  }
350
- return /* @__PURE__ */ React.createElement(
515
+ return /* @__PURE__ */ React2.createElement(
351
516
  "div",
352
517
  {
353
518
  key,
@@ -364,7 +529,7 @@ function renderFieldValue(key, val, fieldDef) {
364
529
  }
365
530
  function DefaultDynamicNode({ data }) {
366
531
  const d = data;
367
- return /* @__PURE__ */ React.createElement(
532
+ return /* @__PURE__ */ React2.createElement(
368
533
  "div",
369
534
  {
370
535
  style: {
@@ -377,11 +542,56 @@ function DefaultDynamicNode({ data }) {
377
542
  d.fields && Object.entries(d.fields).filter(([, v]) => v != null && v !== "").map(([key, val]) => renderFieldValue(key, val))
378
543
  );
379
544
  }
545
+ var TemplateErrorBoundary = class extends React2.Component {
546
+ constructor() {
547
+ super(...arguments);
548
+ this.state = { error: null };
549
+ }
550
+ static getDerivedStateFromError(error) {
551
+ return { error };
552
+ }
553
+ componentDidUpdate(prevProps) {
554
+ if (prevProps.resetKey !== this.props.resetKey && this.state.error) {
555
+ this.setState({ error: null });
556
+ }
557
+ }
558
+ render() {
559
+ 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));
561
+ }
562
+ return this.props.children;
563
+ }
564
+ };
380
565
  function EnhancedDynamicNode({
381
566
  data,
382
- typeDef
567
+ typeDef,
568
+ width,
569
+ height
383
570
  }) {
384
- return /* @__PURE__ */ React.createElement(
571
+ if (typeDef.template) {
572
+ const Component = compileTemplate(typeDef.template, typeDef.slug);
573
+ if (Component) {
574
+ return /* @__PURE__ */ React2.createElement(
575
+ "div",
576
+ {
577
+ className: `flow-node flow-node--${typeDef.slug}${typeDef.transparentBackground ? " flow-node--transparent-bg" : ""}`,
578
+ style: { width: "100%", height: "100%" }
579
+ },
580
+ /* @__PURE__ */ React2.createElement(TemplateErrorBoundary, { resetKey: typeDef.template }, /* @__PURE__ */ React2.createElement(
581
+ Component,
582
+ {
583
+ fields: data.fields,
584
+ label: data.label,
585
+ color: typeDef.color,
586
+ nodeTypeSlug: typeDef.slug,
587
+ width: width || typeDef.defaultSize.width,
588
+ height: height || typeDef.defaultSize.height
589
+ }
590
+ ))
591
+ );
592
+ }
593
+ }
594
+ return /* @__PURE__ */ React2.createElement(
385
595
  "div",
386
596
  {
387
597
  style: {
@@ -401,7 +611,7 @@ function EnhancedDynamicNode({
401
611
  function DefaultFrameNode({ data }) {
402
612
  var _a, _b, _c, _d;
403
613
  const d = data;
404
- const baseColor = (_a = d.color) != null ? _a : "rgba(128,128,128,0.15)";
614
+ const baseColor = (_a = d.color) != null ? _a : "rgb(128,128,128)";
405
615
  const padding = (_b = d.padding) != null ? _b : 20;
406
616
  const borderStyle = (_c = d.borderStyle) != null ? _c : "dashed";
407
617
  const opacity = (_d = d.opacity) != null ? _d : 0.15;
@@ -410,7 +620,7 @@ function DefaultFrameNode({ data }) {
410
620
  if (m) return `rgba(${m[1]},${m[2]},${m[3]},${opacity})`;
411
621
  return baseColor;
412
622
  })();
413
- return /* @__PURE__ */ React.createElement(
623
+ return /* @__PURE__ */ React2.createElement(
414
624
  "div",
415
625
  {
416
626
  style: {
@@ -421,7 +631,7 @@ function DefaultFrameNode({ data }) {
421
631
  border: borderStyle === "none" ? "none" : `2px ${borderStyle} rgba(128,128,128,0.3)`
422
632
  }
423
633
  },
424
- /* @__PURE__ */ React.createElement(
634
+ /* @__PURE__ */ React2.createElement(
425
635
  "div",
426
636
  {
427
637
  style: {
@@ -435,43 +645,42 @@ function DefaultFrameNode({ data }) {
435
645
  )
436
646
  );
437
647
  }
648
+
649
+ // src/ui/Flow/node-types-factory.tsx
438
650
  function createNodeTypes(nodeRenderers, nodeTypeDefsMap, frameRenderer, nodeWrapper, renderNode) {
439
651
  const types = {};
440
652
  types.dynamic = ((props) => {
441
653
  const d = props.data;
442
654
  const typeDef = nodeTypeDefsMap == null ? void 0 : nodeTypeDefsMap.get(d.nodeTypeSlug);
443
655
  const CustomRenderer = nodeRenderers == null ? void 0 : nodeRenderers[d.nodeTypeSlug];
444
- let content;
445
- if (CustomRenderer) {
446
- content = /* @__PURE__ */ React.createElement(
447
- CustomRenderer,
448
- {
449
- id: props.id,
450
- nodeTypeSlug: d.nodeTypeSlug,
451
- label: d.label,
452
- fields: d.fields,
453
- nodeTypeDef: typeDef
454
- }
455
- );
456
- } else if (typeDef) {
457
- content = /* @__PURE__ */ React.createElement(EnhancedDynamicNode, { data: d, typeDef });
458
- } else {
459
- content = /* @__PURE__ */ React.createElement(DefaultDynamicNode, __spreadValues({}, props));
460
- }
656
+ const defaultRender = typeDef ? /* @__PURE__ */ React3.createElement(
657
+ EnhancedDynamicNode,
658
+ {
659
+ data: d,
660
+ typeDef,
661
+ width: props.width,
662
+ height: props.height
663
+ }
664
+ ) : /* @__PURE__ */ React3.createElement(DefaultDynamicNode, __spreadValues({}, props));
665
+ const slotProps = {
666
+ id: props.id,
667
+ nodeTypeSlug: d.nodeTypeSlug,
668
+ label: d.label,
669
+ fields: d.fields,
670
+ nodeTypeDef: typeDef,
671
+ selected: props.selected,
672
+ width: props.width,
673
+ height: props.height,
674
+ defaultRender
675
+ };
676
+ let content = CustomRenderer ? /* @__PURE__ */ React3.createElement(CustomRenderer, __spreadValues({}, slotProps)) : defaultRender;
461
677
  if (renderNode) {
462
- const slotProps = {
463
- id: props.id,
464
- nodeTypeSlug: d.nodeTypeSlug,
465
- label: d.label,
466
- fields: d.fields,
467
- nodeTypeDef: typeDef
468
- };
469
678
  const result = renderNode(slotProps, content);
470
679
  if (result !== null) content = result;
471
680
  }
472
681
  if (nodeWrapper) {
473
682
  const Wrapper = nodeWrapper;
474
- content = /* @__PURE__ */ React.createElement(
683
+ content = /* @__PURE__ */ React3.createElement(
475
684
  Wrapper,
476
685
  {
477
686
  id: props.id,
@@ -488,7 +697,7 @@ function createNodeTypes(nodeRenderers, nodeTypeDefsMap, frameRenderer, nodeWrap
488
697
  types.frame = frameRenderer ? ((props) => {
489
698
  const d = props.data;
490
699
  const Renderer = frameRenderer;
491
- return /* @__PURE__ */ React.createElement(
700
+ return /* @__PURE__ */ React3.createElement(
492
701
  Renderer,
493
702
  {
494
703
  id: props.id,
@@ -496,20 +705,23 @@ function createNodeTypes(nodeRenderers, nodeTypeDefsMap, frameRenderer, nodeWrap
496
705
  color: d.color,
497
706
  padding: d.padding,
498
707
  borderStyle: d.borderStyle,
499
- opacity: d.opacity
708
+ opacity: d.opacity,
709
+ width: props.width,
710
+ height: props.height
500
711
  }
501
712
  );
502
713
  }) : DefaultFrameNode;
503
714
  return types;
504
715
  }
505
716
  function createEdgeTypes(edgeRenderers, edgeTypeDefsMap) {
506
- if (!edgeRenderers || Object.keys(edgeRenderers).length === 0) return void 0;
717
+ if (!edgeRenderers || Object.keys(edgeRenderers).length === 0)
718
+ return void 0;
507
719
  const types = {};
508
720
  for (const [slug, Renderer] of Object.entries(edgeRenderers)) {
509
721
  types[slug] = ((props) => {
510
722
  var _a;
511
723
  const def = edgeTypeDefsMap == null ? void 0 : edgeTypeDefsMap.get(slug);
512
- return /* @__PURE__ */ React.createElement(
724
+ return /* @__PURE__ */ React3.createElement(
513
725
  Renderer,
514
726
  {
515
727
  id: props.id,
@@ -526,20 +738,13 @@ function createEdgeTypes(edgeRenderers, edgeTypeDefsMap) {
526
738
  }
527
739
  return types;
528
740
  }
529
- function FocusHandler({
530
- bounds,
531
- padding,
532
- animation
533
- }) {
534
- const { fitBounds } = useReactFlow();
535
- const boundsKey = `${bounds.x},${bounds.y},${bounds.width},${bounds.height}`;
536
- const boundsRef = React.useRef(bounds);
537
- boundsRef.current = bounds;
538
- React.useEffect(() => {
539
- const duration = animation === true ? 300 : typeof animation === "number" ? animation : 0;
540
- fitBounds(boundsRef.current, { padding, duration });
541
- }, [boundsKey, padding, animation, fitBounds]);
542
- return null;
741
+
742
+ // src/ui/Flow/edge-styles.ts
743
+ import { MarkerType } from "@xyflow/react";
744
+ function toMarkerType(value) {
745
+ if (value === "arrow") return MarkerType.Arrow;
746
+ if (value === "arrowclosed") return MarkerType.ArrowClosed;
747
+ return void 0;
543
748
  }
544
749
  var EDGE_TYPE_MAP = {
545
750
  step: "step",
@@ -580,6 +785,138 @@ function applyEdgeStyles(edges, edgeTypeDefsMap) {
580
785
  return styled;
581
786
  });
582
787
  }
788
+
789
+ // src/ui/Flow/focus-handler.tsx
790
+ import React4 from "react";
791
+ import { useReactFlow, useStoreApi } from "@xyflow/react";
792
+ function clampViewport(vp, cw, ch, extent) {
793
+ const left = -vp.x / vp.zoom;
794
+ const right = (cw - vp.x) / vp.zoom;
795
+ const top = -vp.y / vp.zoom;
796
+ const bottom = (ch - vp.y) / vp.zoom;
797
+ const dx0 = left - extent[0][0];
798
+ const dx1 = right - extent[1][0];
799
+ const dy0 = top - extent[0][1];
800
+ const dy1 = bottom - extent[1][1];
801
+ const cx = dx1 > dx0 ? (dx0 + dx1) / 2 : Math.min(0, dx0) || Math.max(0, dx1);
802
+ const cy = dy1 > dy0 ? (dy0 + dy1) / 2 : Math.min(0, dy0) || Math.max(0, dy1);
803
+ if (cx === 0 && cy === 0) return vp;
804
+ return { x: vp.x + cx * vp.zoom, y: vp.y + cy * vp.zoom, zoom: vp.zoom };
805
+ }
806
+ function FocusHandler({
807
+ bounds,
808
+ padding,
809
+ animation,
810
+ mode,
811
+ responsive,
812
+ extent,
813
+ clampBounds,
814
+ minZoomProp,
815
+ onInitialFit
816
+ }) {
817
+ const { setViewport } = useReactFlow();
818
+ const store = useStoreApi();
819
+ const containerRef = React4.useRef(null);
820
+ const boundsKey = `${bounds.x},${bounds.y},${bounds.width},${bounds.height}`;
821
+ const boundsRef = React4.useRef(bounds);
822
+ boundsRef.current = bounds;
823
+ const [containerSize, setContainerSize] = React4.useState({ w: 0, h: 0 });
824
+ const prevBoundsKeyRef = React4.useRef(null);
825
+ const prevSizeRef = React4.useRef({ w: 0, h: 0 });
826
+ React4.useEffect(() => {
827
+ const el = containerRef.current;
828
+ if (!el) return;
829
+ const observer = new ResizeObserver((entries) => {
830
+ const entry = entries[0];
831
+ if (!entry) return;
832
+ const { width, height } = entry.contentRect;
833
+ setContainerSize({ w: width, h: height });
834
+ });
835
+ observer.observe(el);
836
+ return () => observer.disconnect();
837
+ }, []);
838
+ React4.useEffect(() => {
839
+ if (containerSize.w === 0 || containerSize.h === 0) return;
840
+ const prevKey = prevBoundsKeyRef.current;
841
+ const prevSize = prevSizeRef.current;
842
+ prevBoundsKeyRef.current = boundsKey;
843
+ prevSizeRef.current = { w: containerSize.w, h: containerSize.h };
844
+ const isBoundsChange = prevKey !== boundsKey;
845
+ const isResizeOnly = !isBoundsChange && (prevSize.w !== containerSize.w || prevSize.h !== containerSize.h);
846
+ const isInitial = prevKey === null;
847
+ if (isResizeOnly && !responsive) return;
848
+ const duration = isInitial ? 0 : isBoundsChange ? animation === true ? 300 : typeof animation === "number" ? animation : 0 : 0;
849
+ const b = boundsRef.current;
850
+ const padX = padding * b.width;
851
+ const padY = padding * b.height;
852
+ const bw = b.width + padX * 2;
853
+ const bh = b.height + padY * 2;
854
+ if (bw === 0 || bh === 0) return;
855
+ const zoomFn = mode === "cover" ? Math.max : Math.min;
856
+ const zoom = zoomFn(containerSize.w / bw, containerSize.h / bh);
857
+ const centerTarget = clampBounds != null ? clampBounds : b;
858
+ const cx = centerTarget.x + centerTarget.width / 2;
859
+ const cy = centerTarget.y + centerTarget.height / 2;
860
+ const x = containerSize.w / 2 - cx * zoom;
861
+ const y = containerSize.h / 2 - cy * zoom;
862
+ if (clampBounds) {
863
+ const coverZoom = Math.max(
864
+ containerSize.w / clampBounds.width,
865
+ containerSize.h / clampBounds.height
866
+ );
867
+ store.getState().setMinZoom(Math.max(Math.min(coverZoom, zoom), minZoomProp != null ? minZoomProp : 0));
868
+ } else {
869
+ store.getState().setMinZoom(minZoomProp != null ? minZoomProp : 0.5);
870
+ }
871
+ let vp = { x, y, zoom };
872
+ if (isInitial || isBoundsChange) {
873
+ setViewport(vp, { duration: isInitial ? 0 : duration });
874
+ if (extent) {
875
+ const visW = containerSize.w / zoom;
876
+ const visH = containerSize.h / zoom;
877
+ onInitialFit == null ? void 0 : onInitialFit([
878
+ [Math.min(extent[0][0], cx - visW / 2), Math.min(extent[0][1], cy - visH / 2)],
879
+ [Math.max(extent[1][0], cx + visW / 2), Math.max(extent[1][1], cy + visH / 2)]
880
+ ]);
881
+ } else {
882
+ onInitialFit == null ? void 0 : onInitialFit();
883
+ }
884
+ } else {
885
+ if (extent) {
886
+ vp = clampViewport(vp, containerSize.w, containerSize.h, extent);
887
+ }
888
+ setViewport(vp, { duration });
889
+ }
890
+ }, [
891
+ boundsKey,
892
+ padding,
893
+ animation,
894
+ mode,
895
+ responsive,
896
+ containerSize.w,
897
+ containerSize.h,
898
+ extent,
899
+ setViewport,
900
+ clampBounds,
901
+ minZoomProp,
902
+ store,
903
+ onInitialFit
904
+ ]);
905
+ return /* @__PURE__ */ React4.createElement(
906
+ "div",
907
+ {
908
+ ref: containerRef,
909
+ style: {
910
+ position: "absolute",
911
+ inset: 0,
912
+ pointerEvents: "none",
913
+ visibility: "hidden"
914
+ }
915
+ }
916
+ );
917
+ }
918
+
919
+ // src/ui/Flow/FlowRenderer.tsx
583
920
  function FlowRenderer({
584
921
  data,
585
922
  className,
@@ -591,6 +928,10 @@ function FlowRenderer({
591
928
  interactive = false,
592
929
  fitView = true,
593
930
  onNodeClick,
931
+ onNodeDoubleClick,
932
+ onNodeContextMenu,
933
+ onNodeMouseEnter,
934
+ onNodeMouseLeave,
594
935
  onEdgeClick,
595
936
  frameRenderer,
596
937
  edgeRenderers,
@@ -603,27 +944,43 @@ function FlowRenderer({
603
944
  onViewportChange,
604
945
  defaultViewport: defaultViewportProp,
605
946
  bounds,
947
+ clampBounds,
606
948
  focusPadding,
607
- focusAnimation
949
+ focusAnimation,
950
+ focusMode = "contain",
951
+ responsiveFit,
952
+ translateExtent: translateExtentProp,
953
+ minZoom: minZoomProp,
954
+ maxZoom: maxZoomProp
608
955
  }) {
609
- var _a;
610
- const nodeTypeDefsMap = React.useMemo(() => {
956
+ var _a, _b;
957
+ const nodeTypeDefsMap = React5.useMemo(() => {
611
958
  if (!(nodeTypeDefs == null ? void 0 : nodeTypeDefs.length)) return void 0;
612
959
  return new Map(nodeTypeDefs.map((d) => [d.slug, d]));
613
960
  }, [nodeTypeDefs]);
614
- const edgeTypeDefsMap = React.useMemo(() => {
961
+ const edgeTypeDefsMap = React5.useMemo(() => {
615
962
  if (!(edgeTypeDefs == null ? void 0 : edgeTypeDefs.length)) return void 0;
616
963
  return new Map(edgeTypeDefs.map((d) => [d.slug, d]));
617
964
  }, [edgeTypeDefs]);
618
- const nodeTypes = React.useMemo(
619
- () => createNodeTypes(nodeRenderers, nodeTypeDefsMap, frameRenderer, nodeWrapper, renderNode),
965
+ const nodeTypes = React5.useMemo(
966
+ () => createNodeTypes(
967
+ nodeRenderers,
968
+ nodeTypeDefsMap,
969
+ frameRenderer,
970
+ nodeWrapper,
971
+ renderNode
972
+ ),
620
973
  [nodeRenderers, nodeTypeDefsMap, frameRenderer, nodeWrapper, renderNode]
621
974
  );
622
- const customEdgeTypes = React.useMemo(
975
+ const customEdgeTypes = React5.useMemo(
623
976
  () => createEdgeTypes(edgeRenderers, edgeTypeDefsMap),
624
977
  [edgeRenderers, edgeTypeDefsMap]
625
978
  );
626
- const styledEdges = React.useMemo(() => {
979
+ const mergedCSS = React5.useMemo(() => {
980
+ if (!(nodeTypeDefs == null ? void 0 : nodeTypeDefs.length)) return "";
981
+ return nodeTypeDefs.filter((d) => d.customCSS).map((d) => d.customCSS).join("\n");
982
+ }, [nodeTypeDefs]);
983
+ const styledEdges = React5.useMemo(() => {
627
984
  var _a2;
628
985
  let edges = applyEdgeStyles((_a2 = data == null ? void 0 : data.edges) != null ? _a2 : [], edgeTypeDefsMap);
629
986
  if (edgeRenderers) {
@@ -637,50 +994,98 @@ function FlowRenderer({
637
994
  }
638
995
  return edges;
639
996
  }, [data == null ? void 0 : data.edges, edgeTypeDefsMap, edgeRenderers]);
997
+ const translateExtent = React5.useMemo(() => {
998
+ if (translateExtentProp) return translateExtentProp;
999
+ const es = clampBounds != null ? clampBounds : bounds;
1000
+ if (!es) return void 0;
1001
+ const ep = clampBounds ? 0 : focusPadding != null ? focusPadding : 0.1;
1002
+ return [
1003
+ [es.x - ep * es.width, es.y - ep * es.height],
1004
+ [es.x + es.width * (1 + ep), es.y + es.height * (1 + ep)]
1005
+ ];
1006
+ }, [translateExtentProp, clampBounds, bounds, focusPadding]);
1007
+ const boundsKey = bounds ? `${bounds.x},${bounds.y},${bounds.width},${bounds.height}` : "";
1008
+ const extentReadyRef = React5.useRef(false);
1009
+ const expandedExtentRef = React5.useRef(void 0);
1010
+ const prevBoundsKeyRef = React5.useRef(boundsKey);
1011
+ if (prevBoundsKeyRef.current !== boundsKey) {
1012
+ prevBoundsKeyRef.current = boundsKey;
1013
+ extentReadyRef.current = false;
1014
+ expandedExtentRef.current = void 0;
1015
+ }
1016
+ const [, rerender] = React5.useReducer((x) => x + 1, 0);
1017
+ const handleInitialFit = React5.useCallback(
1018
+ (expandedExtent) => {
1019
+ extentReadyRef.current = true;
1020
+ expandedExtentRef.current = expandedExtent;
1021
+ rerender();
1022
+ },
1023
+ []
1024
+ );
1025
+ const activeExtent = !bounds || extentReadyRef.current ? (_a = expandedExtentRef.current) != null ? _a : translateExtent : void 0;
640
1026
  if (!data) return null;
641
1027
  const resolvedDefaultViewport = defaultViewportProp != null ? defaultViewportProp : !fitView && data.viewport ? data.viewport : void 0;
642
- return /* @__PURE__ */ React.createElement(ReactFlowProvider, null, /* @__PURE__ */ React.createElement(
1028
+ return /* @__PURE__ */ React5.createElement(ReactFlowProvider, null, /* @__PURE__ */ React5.createElement(
643
1029
  "div",
644
1030
  {
645
1031
  className,
646
- style: __spreadValues({ width: "100%", height: "100%" }, style)
1032
+ style: __spreadValues({
1033
+ width: "100%",
1034
+ height: "100%",
1035
+ background: "transparent"
1036
+ }, style)
647
1037
  },
648
- /* @__PURE__ */ React.createElement(
1038
+ /* @__PURE__ */ React5.createElement(
649
1039
  ReactFlow,
650
1040
  {
651
- nodes: (_a = data.nodes) != null ? _a : [],
1041
+ nodes: (_b = data.nodes) != null ? _b : [],
652
1042
  edges: styledEdges,
653
1043
  nodeTypes,
654
1044
  edgeTypes: customEdgeTypes,
655
1045
  defaultViewport: resolvedDefaultViewport,
656
- fitView,
1046
+ fitView: bounds ? false : fitView,
1047
+ translateExtent: activeExtent,
657
1048
  onNodeClick,
1049
+ onNodeDoubleClick,
1050
+ onNodeContextMenu,
1051
+ onNodeMouseEnter,
1052
+ onNodeMouseLeave,
658
1053
  onEdgeClick,
659
1054
  onMoveEnd: onViewportChange ? ((_, vp) => {
660
1055
  onViewportChange(vp);
661
1056
  }) : void 0,
662
- nodesDraggable: interactive ? void 0 : false,
1057
+ nodesDraggable: interactive,
663
1058
  nodesConnectable: false,
664
- elementsSelectable: interactive || !!onNodeClick || !!onEdgeClick,
1059
+ elementsSelectable: interactive || !!onNodeClick || !!onNodeDoubleClick || !!onEdgeClick,
665
1060
  panOnDrag: interactive,
666
1061
  zoomOnScroll: interactive,
667
1062
  zoomOnPinch: interactive,
668
- zoomOnDoubleClick: false
1063
+ zoomOnDoubleClick: false,
1064
+ minZoom: minZoomProp,
1065
+ maxZoom: maxZoomProp,
1066
+ proOptions: { hideAttribution: true }
669
1067
  },
670
- background && /* @__PURE__ */ React.createElement(Background, null),
671
- controls && /* @__PURE__ */ React.createElement(Controls, null),
672
- minimap && /* @__PURE__ */ React.createElement(
1068
+ mergedCSS && /* @__PURE__ */ React5.createElement("style", { dangerouslySetInnerHTML: { __html: mergedCSS } }),
1069
+ background && /* @__PURE__ */ React5.createElement(Background, null),
1070
+ controls && /* @__PURE__ */ React5.createElement(Controls, null),
1071
+ minimap && /* @__PURE__ */ React5.createElement(
673
1072
  MiniMap,
674
1073
  {
675
1074
  nodeColor: minimapNodeColor
676
1075
  }
677
1076
  ),
678
- bounds && /* @__PURE__ */ React.createElement(
1077
+ bounds && /* @__PURE__ */ React5.createElement(
679
1078
  FocusHandler,
680
1079
  {
681
1080
  bounds,
682
1081
  padding: focusPadding != null ? focusPadding : 0.1,
683
- animation: focusAnimation != null ? focusAnimation : true
1082
+ animation: focusAnimation != null ? focusAnimation : true,
1083
+ mode: focusMode,
1084
+ responsive: responsiveFit != null ? responsiveFit : true,
1085
+ extent: translateExtent,
1086
+ clampBounds,
1087
+ minZoomProp,
1088
+ onInitialFit: handleInitialFit
684
1089
  }
685
1090
  ),
686
1091
  children
@@ -691,10 +1096,14 @@ export {
691
1096
  BUILT_IN_EDGE_TYPES,
692
1097
  BUILT_IN_NODE_TYPES,
693
1098
  FlowRenderer,
1099
+ clearTemplateCache,
1100
+ compileTemplate,
1101
+ getFrameData,
694
1102
  getFrames,
695
1103
  getNodeBounds,
696
1104
  isDynamicNode,
697
1105
  isFrameNode,
1106
+ prefetchFlow,
698
1107
  useFlow,
699
1108
  useFlowData
700
1109
  };