@01.software/sdk 0.4.2 → 0.4.3-dev.1774320860782

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/ui/flow.js CHANGED
@@ -40,7 +40,7 @@ var __async = (__this, __arguments, generator) => {
40
40
  };
41
41
 
42
42
  // src/ui/Flow/index.tsx
43
- import React from "react";
43
+ import React2 from "react";
44
44
  import {
45
45
  ReactFlow,
46
46
  ReactFlowProvider,
@@ -116,7 +116,7 @@ function collectionKeys(collection) {
116
116
 
117
117
  // src/ui/Flow/useFlow.ts
118
118
  function toNodeTypeDef(doc) {
119
- var _a, _b, _c, _d;
119
+ var _a, _b, _c, _d, _e, _f;
120
120
  return {
121
121
  slug: String((_a = doc.slug) != null ? _a : ""),
122
122
  name: String((_b = doc.title) != null ? _b : ""),
@@ -126,7 +126,9 @@ function toNodeTypeDef(doc) {
126
126
  height: 200
127
127
  },
128
128
  fields: Array.isArray(doc.fields) ? doc.fields : [],
129
- transparentBackground: Boolean(doc.transparentBackground)
129
+ transparentBackground: Boolean(doc.transparentBackground),
130
+ template: (_e = doc.template) != null ? _e : null,
131
+ customCSS: (_f = doc.customCSS) != null ? _f : null
130
132
  };
131
133
  }
132
134
  function toEdgeTypeDef(doc) {
@@ -244,37 +246,57 @@ function useFlowData(options) {
244
246
  }
245
247
 
246
248
  // src/ui/Flow/utils.ts
247
- function getNodeBounds(nodes, nodeIds) {
249
+ function getNodeSize(node) {
248
250
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
251
+ return {
252
+ 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,
253
+ 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
254
+ };
255
+ }
256
+ function getAbsolutePosition(node, nodeMap) {
257
+ let x = node.position.x;
258
+ let y = node.position.y;
259
+ let current = node;
260
+ const visited = /* @__PURE__ */ new Set([node.id]);
261
+ while (current.parentId) {
262
+ const parentId = current.parentId;
263
+ if (visited.has(parentId)) break;
264
+ const parent = nodeMap.get(parentId);
265
+ if (!parent) break;
266
+ visited.add(parent.id);
267
+ x += parent.position.x;
268
+ y += parent.position.y;
269
+ current = parent;
270
+ }
271
+ return { x, y };
272
+ }
273
+ function collectDescendants(nodes, rootId) {
274
+ const result = /* @__PURE__ */ new Set([rootId]);
275
+ const queue = [rootId];
276
+ let i = 0;
277
+ while (i < queue.length) {
278
+ const current = queue[i++];
279
+ for (const n of nodes) {
280
+ if (n.parentId === current && !result.has(n.id)) {
281
+ result.add(n.id);
282
+ queue.push(n.id);
283
+ }
284
+ }
285
+ }
286
+ return result;
287
+ }
288
+ function getNodeBounds(nodes, nodeIds) {
249
289
  const idSet = new Set(nodeIds);
250
290
  const targetNodes = nodes.filter((n) => idSet.has(n.id));
251
291
  if (targetNodes.length === 0) return void 0;
252
292
  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
293
  let minX = Infinity;
271
294
  let minY = Infinity;
272
295
  let maxX = -Infinity;
273
296
  let maxY = -Infinity;
274
297
  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;
298
+ const abs = getAbsolutePosition(node, nodeMap);
299
+ const { width: w, height: h } = getNodeSize(node);
278
300
  minX = Math.min(minX, abs.x);
279
301
  minY = Math.min(minY, abs.y);
280
302
  maxX = Math.max(maxX, abs.x + w);
@@ -286,32 +308,140 @@ function getFrames(nodes) {
286
308
  const frames = nodes.filter((n) => n.type === "frame");
287
309
  if (frames.length === 0) return [];
288
310
  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
311
  return frames.map((f) => {
307
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
312
+ var _a;
308
313
  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 } };
314
+ const abs = getAbsolutePosition(f, nodeMap);
315
+ const { width: w, height: h } = getNodeSize(f);
316
+ return {
317
+ id: f.id,
318
+ label: (_a = data.label) != null ? _a : "",
319
+ bounds: { x: abs.x, y: abs.y, width: w, height: h }
320
+ };
313
321
  }).sort((a, b) => a.bounds.y - b.bounds.y || a.bounds.x - b.bounds.x);
314
322
  }
323
+ function getFrameData(data, frameId) {
324
+ const frame = data.nodes.find((n) => n.id === frameId);
325
+ if (!frame || frame.type !== "frame") return void 0;
326
+ const descendantIds = collectDescendants(data.nodes, frameId);
327
+ const childNodes = data.nodes.filter((n) => descendantIds.has(n.id)).map((n) => __spreadProps(__spreadValues({}, n), { draggable: false }));
328
+ const childEdges = data.edges.filter(
329
+ (e) => descendantIds.has(e.source) && descendantIds.has(e.target)
330
+ );
331
+ const frameBounds = getNodeBounds(data.nodes, [frameId]);
332
+ const { width: w, height: h } = getNodeSize(frame);
333
+ const clampBounds = frameBounds != null ? frameBounds : {
334
+ x: frame.position.x,
335
+ y: frame.position.y,
336
+ width: w,
337
+ height: h
338
+ };
339
+ const contentNodeIds = childNodes.filter((n) => n.id !== frameId).map((n) => n.id);
340
+ const contentBounds = contentNodeIds.length > 0 ? getNodeBounds(data.nodes, contentNodeIds) : void 0;
341
+ const fitBounds = contentBounds != null ? contentBounds : clampBounds;
342
+ return {
343
+ data: {
344
+ nodes: childNodes,
345
+ edges: childEdges,
346
+ viewport: data.viewport
347
+ },
348
+ fitBounds,
349
+ clampBounds,
350
+ bounds: clampBounds
351
+ };
352
+ }
353
+
354
+ // src/ui/Flow/template-compiler.ts
355
+ import React from "react";
356
+ import { transform } from "sucrase";
357
+ var MAX_CACHE_SIZE = 100;
358
+ var componentCache = /* @__PURE__ */ new Map();
359
+ function hashCode(str) {
360
+ let hash = 0;
361
+ for (let i = 0; i < str.length; i++) {
362
+ const char = str.charCodeAt(i);
363
+ hash = (hash << 5) - hash + char | 0;
364
+ }
365
+ return hash.toString(36);
366
+ }
367
+ var BLOCKED_PATTERNS = [
368
+ /\bdocument\s*\./,
369
+ /\bwindow\s*\./,
370
+ /\bwindow\s*\[/,
371
+ /\bglobalThis\s*\./,
372
+ /\bfetch\s*\(/,
373
+ /\bXMLHttpRequest/,
374
+ /\beval\s*\(/,
375
+ /\bFunction\s*\(/,
376
+ /\bimport\s*\(/,
377
+ /\blocalStorage/,
378
+ /\bsessionStorage/,
379
+ /\bcookie/,
380
+ /\bpostMessage\s*\(/,
381
+ /\blocation\s*[.=]/,
382
+ /\bnavigator\s*\./,
383
+ /\bsetTimeout\s*\(/,
384
+ /\bsetInterval\s*\(/,
385
+ /\bsetImmediate\s*\(/,
386
+ /\brequire\s*\(/
387
+ ];
388
+ function validateTemplateCode(code) {
389
+ return !BLOCKED_PATTERNS.some((pattern) => pattern.test(code));
390
+ }
391
+ function compileTemplate(code, slug) {
392
+ const cacheKey = `${slug}:${hashCode(code)}`;
393
+ if (componentCache.has(cacheKey)) {
394
+ const cached = componentCache.get(cacheKey);
395
+ componentCache.delete(cacheKey);
396
+ componentCache.set(cacheKey, cached);
397
+ return cached;
398
+ }
399
+ if (!validateTemplateCode(code)) {
400
+ console.warn(`[flow] Template "${slug}" contains blocked patterns`);
401
+ return null;
402
+ }
403
+ try {
404
+ const { code: jsCode } = transform(code, {
405
+ transforms: ["typescript", "jsx", "imports"],
406
+ jsxRuntime: "classic",
407
+ jsxPragma: "React.createElement",
408
+ jsxFragmentPragma: "React.Fragment"
409
+ });
410
+ const factory = new Function(
411
+ "React",
412
+ `
413
+ var window = undefined;
414
+ var document = undefined;
415
+ var globalThis = undefined;
416
+ var setTimeout = undefined;
417
+ var setInterval = undefined;
418
+ var setImmediate = undefined;
419
+ var fetch = undefined;
420
+ var XMLHttpRequest = undefined;
421
+ var navigator = undefined;
422
+ var location = undefined;
423
+ var exports = {};
424
+ var module = { exports: exports };
425
+ ${jsCode}
426
+ return module.exports.default || module.exports;
427
+ `
428
+ );
429
+ const Component = factory(React);
430
+ if (typeof Component !== "function") return null;
431
+ if (componentCache.size >= MAX_CACHE_SIZE) {
432
+ const oldestKey = componentCache.keys().next().value;
433
+ if (oldestKey) componentCache.delete(oldestKey);
434
+ }
435
+ componentCache.set(cacheKey, Component);
436
+ return Component;
437
+ } catch (e) {
438
+ console.warn(`[flow] Failed to compile template for "${slug}":`, e);
439
+ return null;
440
+ }
441
+ }
442
+ function clearTemplateCache() {
443
+ componentCache.clear();
444
+ }
315
445
 
316
446
  // src/ui/Flow/index.tsx
317
447
  function sanitizeUrl(url) {
@@ -336,7 +466,7 @@ function renderFieldValue(key, val, fieldDef) {
336
466
  const imgUrl = typeof val === "string" ? val : val == null ? void 0 : val.url;
337
467
  const safeUrl = sanitizeUrl(imgUrl);
338
468
  if (!safeUrl) return null;
339
- return /* @__PURE__ */ React.createElement(
469
+ return /* @__PURE__ */ React2.createElement(
340
470
  "img",
341
471
  {
342
472
  key,
@@ -347,7 +477,7 @@ function renderFieldValue(key, val, fieldDef) {
347
477
  }
348
478
  );
349
479
  }
350
- return /* @__PURE__ */ React.createElement(
480
+ return /* @__PURE__ */ React2.createElement(
351
481
  "div",
352
482
  {
353
483
  key,
@@ -364,7 +494,7 @@ function renderFieldValue(key, val, fieldDef) {
364
494
  }
365
495
  function DefaultDynamicNode({ data }) {
366
496
  const d = data;
367
- return /* @__PURE__ */ React.createElement(
497
+ return /* @__PURE__ */ React2.createElement(
368
498
  "div",
369
499
  {
370
500
  style: {
@@ -377,11 +507,59 @@ function DefaultDynamicNode({ data }) {
377
507
  d.fields && Object.entries(d.fields).filter(([, v]) => v != null && v !== "").map(([key, val]) => renderFieldValue(key, val))
378
508
  );
379
509
  }
510
+ var TemplateErrorBoundary = class extends React2.Component {
511
+ constructor() {
512
+ super(...arguments);
513
+ this.state = { error: null };
514
+ }
515
+ static getDerivedStateFromError(error) {
516
+ return { error };
517
+ }
518
+ componentDidUpdate(prevProps) {
519
+ if (prevProps.resetKey !== this.props.resetKey && this.state.error) {
520
+ this.setState({ error: null });
521
+ }
522
+ }
523
+ render() {
524
+ if (this.state.error) {
525
+ 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));
526
+ }
527
+ return this.props.children;
528
+ }
529
+ };
380
530
  function EnhancedDynamicNode({
381
531
  data,
382
- typeDef
532
+ typeDef,
533
+ width,
534
+ height
383
535
  }) {
384
- return /* @__PURE__ */ React.createElement(
536
+ if (typeDef.template) {
537
+ const Component = compileTemplate(typeDef.template, typeDef.slug);
538
+ if (Component) {
539
+ return /* @__PURE__ */ React2.createElement(
540
+ "div",
541
+ {
542
+ className: `flow-node flow-node--${typeDef.slug}${typeDef.transparentBackground ? " flow-node--transparent-bg" : ""}`,
543
+ style: {
544
+ width: "100%",
545
+ height: "100%"
546
+ }
547
+ },
548
+ /* @__PURE__ */ React2.createElement(TemplateErrorBoundary, { resetKey: typeDef.template }, /* @__PURE__ */ React2.createElement(
549
+ Component,
550
+ {
551
+ fields: data.fields,
552
+ label: data.label,
553
+ color: typeDef.color,
554
+ nodeTypeSlug: typeDef.slug,
555
+ width: width != null ? width : typeDef.defaultSize.width,
556
+ height: height != null ? height : typeDef.defaultSize.height
557
+ }
558
+ ))
559
+ );
560
+ }
561
+ }
562
+ return /* @__PURE__ */ React2.createElement(
385
563
  "div",
386
564
  {
387
565
  style: {
@@ -410,7 +588,7 @@ function DefaultFrameNode({ data }) {
410
588
  if (m) return `rgba(${m[1]},${m[2]},${m[3]},${opacity})`;
411
589
  return baseColor;
412
590
  })();
413
- return /* @__PURE__ */ React.createElement(
591
+ return /* @__PURE__ */ React2.createElement(
414
592
  "div",
415
593
  {
416
594
  style: {
@@ -421,7 +599,7 @@ function DefaultFrameNode({ data }) {
421
599
  border: borderStyle === "none" ? "none" : `2px ${borderStyle} rgba(128,128,128,0.3)`
422
600
  }
423
601
  },
424
- /* @__PURE__ */ React.createElement(
602
+ /* @__PURE__ */ React2.createElement(
425
603
  "div",
426
604
  {
427
605
  style: {
@@ -443,7 +621,7 @@ function createNodeTypes(nodeRenderers, nodeTypeDefsMap, frameRenderer, nodeWrap
443
621
  const CustomRenderer = nodeRenderers == null ? void 0 : nodeRenderers[d.nodeTypeSlug];
444
622
  let content;
445
623
  if (CustomRenderer) {
446
- content = /* @__PURE__ */ React.createElement(
624
+ content = /* @__PURE__ */ React2.createElement(
447
625
  CustomRenderer,
448
626
  {
449
627
  id: props.id,
@@ -454,9 +632,17 @@ function createNodeTypes(nodeRenderers, nodeTypeDefsMap, frameRenderer, nodeWrap
454
632
  }
455
633
  );
456
634
  } else if (typeDef) {
457
- content = /* @__PURE__ */ React.createElement(EnhancedDynamicNode, { data: d, typeDef });
635
+ content = /* @__PURE__ */ React2.createElement(
636
+ EnhancedDynamicNode,
637
+ {
638
+ data: d,
639
+ typeDef,
640
+ width: props.width,
641
+ height: props.height
642
+ }
643
+ );
458
644
  } else {
459
- content = /* @__PURE__ */ React.createElement(DefaultDynamicNode, __spreadValues({}, props));
645
+ content = /* @__PURE__ */ React2.createElement(DefaultDynamicNode, __spreadValues({}, props));
460
646
  }
461
647
  if (renderNode) {
462
648
  const slotProps = {
@@ -471,7 +657,7 @@ function createNodeTypes(nodeRenderers, nodeTypeDefsMap, frameRenderer, nodeWrap
471
657
  }
472
658
  if (nodeWrapper) {
473
659
  const Wrapper = nodeWrapper;
474
- content = /* @__PURE__ */ React.createElement(
660
+ content = /* @__PURE__ */ React2.createElement(
475
661
  Wrapper,
476
662
  {
477
663
  id: props.id,
@@ -488,7 +674,7 @@ function createNodeTypes(nodeRenderers, nodeTypeDefsMap, frameRenderer, nodeWrap
488
674
  types.frame = frameRenderer ? ((props) => {
489
675
  const d = props.data;
490
676
  const Renderer = frameRenderer;
491
- return /* @__PURE__ */ React.createElement(
677
+ return /* @__PURE__ */ React2.createElement(
492
678
  Renderer,
493
679
  {
494
680
  id: props.id,
@@ -503,13 +689,14 @@ function createNodeTypes(nodeRenderers, nodeTypeDefsMap, frameRenderer, nodeWrap
503
689
  return types;
504
690
  }
505
691
  function createEdgeTypes(edgeRenderers, edgeTypeDefsMap) {
506
- if (!edgeRenderers || Object.keys(edgeRenderers).length === 0) return void 0;
692
+ if (!edgeRenderers || Object.keys(edgeRenderers).length === 0)
693
+ return void 0;
507
694
  const types = {};
508
695
  for (const [slug, Renderer] of Object.entries(edgeRenderers)) {
509
696
  types[slug] = ((props) => {
510
697
  var _a;
511
698
  const def = edgeTypeDefsMap == null ? void 0 : edgeTypeDefsMap.get(slug);
512
- return /* @__PURE__ */ React.createElement(
699
+ return /* @__PURE__ */ React2.createElement(
513
700
  Renderer,
514
701
  {
515
702
  id: props.id,
@@ -526,20 +713,99 @@ function createEdgeTypes(edgeRenderers, edgeTypeDefsMap) {
526
713
  }
527
714
  return types;
528
715
  }
716
+ function clampViewport(vp, cw, ch, extent) {
717
+ const left = -vp.x / vp.zoom;
718
+ const right = (cw - vp.x) / vp.zoom;
719
+ const top = -vp.y / vp.zoom;
720
+ const bottom = (ch - vp.y) / vp.zoom;
721
+ const dx0 = left - extent[0][0];
722
+ const dx1 = right - extent[1][0];
723
+ const dy0 = top - extent[0][1];
724
+ const dy1 = bottom - extent[1][1];
725
+ const cx = dx1 > dx0 ? (dx0 + dx1) / 2 : Math.min(0, dx0) || Math.max(0, dx1);
726
+ const cy = dy1 > dy0 ? (dy0 + dy1) / 2 : Math.min(0, dy0) || Math.max(0, dy1);
727
+ if (cx === 0 && cy === 0) return vp;
728
+ return { x: vp.x + cx * vp.zoom, y: vp.y + cy * vp.zoom, zoom: vp.zoom };
729
+ }
529
730
  function FocusHandler({
530
731
  bounds,
531
732
  padding,
532
- animation
733
+ animation,
734
+ mode,
735
+ responsive,
736
+ extent
533
737
  }) {
534
- const { fitBounds } = useReactFlow();
738
+ const { setViewport } = useReactFlow();
739
+ const containerRef = React2.useRef(null);
535
740
  const boundsKey = `${bounds.x},${bounds.y},${bounds.width},${bounds.height}`;
536
- const boundsRef = React.useRef(bounds);
741
+ const boundsRef = React2.useRef(bounds);
537
742
  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;
743
+ const [containerSize, setContainerSize] = React2.useState({ w: 0, h: 0 });
744
+ const prevBoundsKeyRef = React2.useRef(null);
745
+ const prevSizeRef = React2.useRef({ w: 0, h: 0 });
746
+ React2.useEffect(() => {
747
+ const el = containerRef.current;
748
+ if (!el) return;
749
+ const observer = new ResizeObserver((entries) => {
750
+ const entry = entries[0];
751
+ if (!entry) return;
752
+ const { width, height } = entry.contentRect;
753
+ setContainerSize({ w: width, h: height });
754
+ });
755
+ observer.observe(el);
756
+ return () => observer.disconnect();
757
+ }, []);
758
+ React2.useEffect(() => {
759
+ if (containerSize.w === 0 || containerSize.h === 0) return;
760
+ const prevKey = prevBoundsKeyRef.current;
761
+ const prevSize = prevSizeRef.current;
762
+ prevBoundsKeyRef.current = boundsKey;
763
+ prevSizeRef.current = { w: containerSize.w, h: containerSize.h };
764
+ const isBoundsChange = prevKey !== boundsKey;
765
+ const isResizeOnly = !isBoundsChange && (prevSize.w !== containerSize.w || prevSize.h !== containerSize.h);
766
+ const isInitial = prevKey === null;
767
+ if (isResizeOnly && !responsive) return;
768
+ const duration = isInitial || isBoundsChange ? animation === true ? 300 : typeof animation === "number" ? animation : 0 : 0;
769
+ const b = boundsRef.current;
770
+ const padX = padding * b.width;
771
+ const padY = padding * b.height;
772
+ const bw = b.width + padX * 2;
773
+ const bh = b.height + padY * 2;
774
+ if (bw === 0 || bh === 0) return;
775
+ const zoomFn = mode === "cover" ? Math.max : Math.min;
776
+ const zoom = zoomFn(containerSize.w / bw, containerSize.h / bh);
777
+ const cx = b.x + b.width / 2;
778
+ const cy = b.y + b.height / 2;
779
+ const x = containerSize.w / 2 - cx * zoom;
780
+ const y = containerSize.h / 2 - cy * zoom;
781
+ let vp = { x, y, zoom };
782
+ if (extent) {
783
+ vp = clampViewport(vp, containerSize.w, containerSize.h, extent);
784
+ }
785
+ setViewport(vp, { duration });
786
+ }, [
787
+ boundsKey,
788
+ padding,
789
+ animation,
790
+ mode,
791
+ responsive,
792
+ containerSize.w,
793
+ containerSize.h,
794
+ extent,
795
+ setViewport
796
+ ]);
797
+ return /* @__PURE__ */ React2.createElement(
798
+ "div",
799
+ {
800
+ ref: containerRef,
801
+ style: {
802
+ position: "absolute",
803
+ inset: 0,
804
+ pointerEvents: "none",
805
+ visibility: "hidden"
806
+ }
807
+ }
808
+ );
543
809
  }
544
810
  var EDGE_TYPE_MAP = {
545
811
  step: "step",
@@ -591,6 +857,10 @@ function FlowRenderer({
591
857
  interactive = false,
592
858
  fitView = true,
593
859
  onNodeClick,
860
+ onNodeDoubleClick,
861
+ onNodeContextMenu,
862
+ onNodeMouseEnter,
863
+ onNodeMouseLeave,
594
864
  onEdgeClick,
595
865
  frameRenderer,
596
866
  edgeRenderers,
@@ -603,27 +873,41 @@ function FlowRenderer({
603
873
  onViewportChange,
604
874
  defaultViewport: defaultViewportProp,
605
875
  bounds,
876
+ clampBounds,
606
877
  focusPadding,
607
- focusAnimation
878
+ focusAnimation,
879
+ focusMode = "contain",
880
+ responsiveFit,
881
+ translateExtent: translateExtentProp
608
882
  }) {
609
883
  var _a;
610
- const nodeTypeDefsMap = React.useMemo(() => {
884
+ const nodeTypeDefsMap = React2.useMemo(() => {
611
885
  if (!(nodeTypeDefs == null ? void 0 : nodeTypeDefs.length)) return void 0;
612
886
  return new Map(nodeTypeDefs.map((d) => [d.slug, d]));
613
887
  }, [nodeTypeDefs]);
614
- const edgeTypeDefsMap = React.useMemo(() => {
888
+ const edgeTypeDefsMap = React2.useMemo(() => {
615
889
  if (!(edgeTypeDefs == null ? void 0 : edgeTypeDefs.length)) return void 0;
616
890
  return new Map(edgeTypeDefs.map((d) => [d.slug, d]));
617
891
  }, [edgeTypeDefs]);
618
- const nodeTypes = React.useMemo(
619
- () => createNodeTypes(nodeRenderers, nodeTypeDefsMap, frameRenderer, nodeWrapper, renderNode),
892
+ const nodeTypes = React2.useMemo(
893
+ () => createNodeTypes(
894
+ nodeRenderers,
895
+ nodeTypeDefsMap,
896
+ frameRenderer,
897
+ nodeWrapper,
898
+ renderNode
899
+ ),
620
900
  [nodeRenderers, nodeTypeDefsMap, frameRenderer, nodeWrapper, renderNode]
621
901
  );
622
- const customEdgeTypes = React.useMemo(
902
+ const customEdgeTypes = React2.useMemo(
623
903
  () => createEdgeTypes(edgeRenderers, edgeTypeDefsMap),
624
904
  [edgeRenderers, edgeTypeDefsMap]
625
905
  );
626
- const styledEdges = React.useMemo(() => {
906
+ const mergedCSS = React2.useMemo(() => {
907
+ if (!(nodeTypeDefs == null ? void 0 : nodeTypeDefs.length)) return "";
908
+ return nodeTypeDefs.filter((d) => d.customCSS).map((d) => d.customCSS).join("\n");
909
+ }, [nodeTypeDefs]);
910
+ const styledEdges = React2.useMemo(() => {
627
911
  var _a2;
628
912
  let edges = applyEdgeStyles((_a2 = data == null ? void 0 : data.edges) != null ? _a2 : [], edgeTypeDefsMap);
629
913
  if (edgeRenderers) {
@@ -637,15 +921,29 @@ function FlowRenderer({
637
921
  }
638
922
  return edges;
639
923
  }, [data == null ? void 0 : data.edges, edgeTypeDefsMap, edgeRenderers]);
924
+ const translateExtent = React2.useMemo(() => {
925
+ if (translateExtentProp) return translateExtentProp;
926
+ const es = clampBounds != null ? clampBounds : bounds;
927
+ if (!es) return void 0;
928
+ const ep = clampBounds ? 0 : focusPadding != null ? focusPadding : 0.1;
929
+ return [
930
+ [es.x - ep * es.width, es.y - ep * es.height],
931
+ [es.x + es.width * (1 + ep), es.y + es.height * (1 + ep)]
932
+ ];
933
+ }, [translateExtentProp, clampBounds, bounds, focusPadding]);
640
934
  if (!data) return null;
641
935
  const resolvedDefaultViewport = defaultViewportProp != null ? defaultViewportProp : !fitView && data.viewport ? data.viewport : void 0;
642
- return /* @__PURE__ */ React.createElement(ReactFlowProvider, null, /* @__PURE__ */ React.createElement(
936
+ return /* @__PURE__ */ React2.createElement(ReactFlowProvider, null, /* @__PURE__ */ React2.createElement(
643
937
  "div",
644
938
  {
645
939
  className,
646
- style: __spreadValues({ width: "100%", height: "100%" }, style)
940
+ style: __spreadValues({
941
+ width: "100%",
942
+ height: "100%",
943
+ background: "transparent"
944
+ }, style)
647
945
  },
648
- /* @__PURE__ */ React.createElement(
946
+ /* @__PURE__ */ React2.createElement(
649
947
  ReactFlow,
650
948
  {
651
949
  nodes: (_a = data.nodes) != null ? _a : [],
@@ -653,34 +951,44 @@ function FlowRenderer({
653
951
  nodeTypes,
654
952
  edgeTypes: customEdgeTypes,
655
953
  defaultViewport: resolvedDefaultViewport,
656
- fitView,
954
+ fitView: bounds ? false : fitView,
955
+ translateExtent,
657
956
  onNodeClick,
957
+ onNodeDoubleClick,
958
+ onNodeContextMenu,
959
+ onNodeMouseEnter,
960
+ onNodeMouseLeave,
658
961
  onEdgeClick,
659
962
  onMoveEnd: onViewportChange ? ((_, vp) => {
660
963
  onViewportChange(vp);
661
964
  }) : void 0,
662
- nodesDraggable: interactive ? void 0 : false,
965
+ nodesDraggable: interactive,
663
966
  nodesConnectable: false,
664
- elementsSelectable: interactive || !!onNodeClick || !!onEdgeClick,
967
+ elementsSelectable: interactive || !!onNodeClick || !!onNodeDoubleClick || !!onEdgeClick,
665
968
  panOnDrag: interactive,
666
969
  zoomOnScroll: interactive,
667
970
  zoomOnPinch: interactive,
668
- zoomOnDoubleClick: false
971
+ zoomOnDoubleClick: false,
972
+ proOptions: { hideAttribution: true }
669
973
  },
670
- background && /* @__PURE__ */ React.createElement(Background, null),
671
- controls && /* @__PURE__ */ React.createElement(Controls, null),
672
- minimap && /* @__PURE__ */ React.createElement(
974
+ mergedCSS && /* @__PURE__ */ React2.createElement("style", { dangerouslySetInnerHTML: { __html: mergedCSS } }),
975
+ background && /* @__PURE__ */ React2.createElement(Background, null),
976
+ controls && /* @__PURE__ */ React2.createElement(Controls, null),
977
+ minimap && /* @__PURE__ */ React2.createElement(
673
978
  MiniMap,
674
979
  {
675
980
  nodeColor: minimapNodeColor
676
981
  }
677
982
  ),
678
- bounds && /* @__PURE__ */ React.createElement(
983
+ bounds && /* @__PURE__ */ React2.createElement(
679
984
  FocusHandler,
680
985
  {
681
986
  bounds,
682
987
  padding: focusPadding != null ? focusPadding : 0.1,
683
- animation: focusAnimation != null ? focusAnimation : true
988
+ animation: focusAnimation != null ? focusAnimation : true,
989
+ mode: focusMode,
990
+ responsive: responsiveFit != null ? responsiveFit : true,
991
+ extent: translateExtent
684
992
  }
685
993
  ),
686
994
  children
@@ -691,6 +999,9 @@ export {
691
999
  BUILT_IN_EDGE_TYPES,
692
1000
  BUILT_IN_NODE_TYPES,
693
1001
  FlowRenderer,
1002
+ clearTemplateCache,
1003
+ compileTemplate,
1004
+ getFrameData,
694
1005
  getFrames,
695
1006
  getNodeBounds,
696
1007
  isDynamicNode,