@01.software/sdk 0.4.3-dev.1774331521107 → 0.4.3-dev.1774338319418

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.cjs CHANGED
@@ -573,7 +573,8 @@ function EnhancedDynamicNode({
573
573
  return /* @__PURE__ */ import_react4.default.createElement(
574
574
  "div",
575
575
  {
576
- className: `flow-node flow-node--${typeDef.slug}${typeDef.transparentBackground ? " flow-node--transparent-bg" : ""}`
576
+ className: `flow-node flow-node--${typeDef.slug}${typeDef.transparentBackground ? " flow-node--transparent-bg" : ""}`,
577
+ style: { width: "100%", height: "100%" }
577
578
  },
578
579
  /* @__PURE__ */ import_react4.default.createElement(TemplateErrorBoundary, { resetKey: typeDef.template }, /* @__PURE__ */ import_react4.default.createElement(
579
580
  Component,
@@ -609,7 +610,7 @@ function EnhancedDynamicNode({
609
610
  function DefaultFrameNode({ data }) {
610
611
  var _a, _b, _c, _d;
611
612
  const d = data;
612
- const baseColor = (_a = d.color) != null ? _a : "rgba(128,128,128,0.15)";
613
+ const baseColor = (_a = d.color) != null ? _a : "rgb(128,128,128)";
613
614
  const padding = (_b = d.padding) != null ? _b : 20;
614
615
  const borderStyle = (_c = d.borderStyle) != null ? _c : "dashed";
615
616
  const opacity = (_d = d.opacity) != null ? _d : 0.15;
@@ -649,39 +650,28 @@ function createNodeTypes(nodeRenderers, nodeTypeDefsMap, frameRenderer, nodeWrap
649
650
  const d = props.data;
650
651
  const typeDef = nodeTypeDefsMap == null ? void 0 : nodeTypeDefsMap.get(d.nodeTypeSlug);
651
652
  const CustomRenderer = nodeRenderers == null ? void 0 : nodeRenderers[d.nodeTypeSlug];
652
- let content;
653
- if (CustomRenderer) {
654
- content = /* @__PURE__ */ import_react4.default.createElement(
655
- CustomRenderer,
656
- {
657
- id: props.id,
658
- nodeTypeSlug: d.nodeTypeSlug,
659
- label: d.label,
660
- fields: d.fields,
661
- nodeTypeDef: typeDef
662
- }
663
- );
664
- } else if (typeDef) {
665
- content = /* @__PURE__ */ import_react4.default.createElement(
666
- EnhancedDynamicNode,
667
- {
668
- data: d,
669
- typeDef,
670
- width: props.width,
671
- height: props.height
672
- }
673
- );
674
- } else {
675
- content = /* @__PURE__ */ import_react4.default.createElement(DefaultDynamicNode, __spreadValues({}, props));
676
- }
653
+ const defaultRender = typeDef ? /* @__PURE__ */ import_react4.default.createElement(
654
+ EnhancedDynamicNode,
655
+ {
656
+ data: d,
657
+ typeDef,
658
+ width: props.width,
659
+ height: props.height
660
+ }
661
+ ) : /* @__PURE__ */ import_react4.default.createElement(DefaultDynamicNode, __spreadValues({}, props));
662
+ const slotProps = {
663
+ id: props.id,
664
+ nodeTypeSlug: d.nodeTypeSlug,
665
+ label: d.label,
666
+ fields: d.fields,
667
+ nodeTypeDef: typeDef,
668
+ selected: props.selected,
669
+ width: props.width,
670
+ height: props.height,
671
+ defaultRender
672
+ };
673
+ let content = CustomRenderer ? /* @__PURE__ */ import_react4.default.createElement(CustomRenderer, __spreadValues({}, slotProps)) : defaultRender;
677
674
  if (renderNode) {
678
- const slotProps = {
679
- id: props.id,
680
- nodeTypeSlug: d.nodeTypeSlug,
681
- label: d.label,
682
- fields: d.fields,
683
- nodeTypeDef: typeDef
684
- };
685
675
  const result = renderNode(slotProps, content);
686
676
  if (result !== null) content = result;
687
677
  }
@@ -712,7 +702,9 @@ function createNodeTypes(nodeRenderers, nodeTypeDefsMap, frameRenderer, nodeWrap
712
702
  color: d.color,
713
703
  padding: d.padding,
714
704
  borderStyle: d.borderStyle,
715
- opacity: d.opacity
705
+ opacity: d.opacity,
706
+ width: props.width,
707
+ height: props.height
716
708
  }
717
709
  );
718
710
  }) : DefaultFrameNode;
@@ -763,9 +755,12 @@ function FocusHandler({
763
755
  animation,
764
756
  mode,
765
757
  responsive,
766
- extent
758
+ extent,
759
+ clampBounds,
760
+ minZoomProp
767
761
  }) {
768
762
  const { setViewport } = (0, import_react5.useReactFlow)();
763
+ const store = (0, import_react5.useStoreApi)();
769
764
  const containerRef = import_react4.default.useRef(null);
770
765
  const boundsKey = `${bounds.x},${bounds.y},${bounds.width},${bounds.height}`;
771
766
  const boundsRef = import_react4.default.useRef(bounds);
@@ -797,17 +792,27 @@ function FocusHandler({
797
792
  if (isResizeOnly && !responsive) return;
798
793
  const duration = isInitial || isBoundsChange ? animation === true ? 300 : typeof animation === "number" ? animation : 0 : 0;
799
794
  const b = boundsRef.current;
800
- const padX = padding * b.width;
801
- const padY = padding * b.height;
802
- const bw = b.width + padX * 2;
803
- const bh = b.height + padY * 2;
795
+ const zoomTarget = mode === "cover" && clampBounds ? clampBounds : b;
796
+ const padX = padding * zoomTarget.width;
797
+ const padY = padding * zoomTarget.height;
798
+ const bw = zoomTarget.width + padX * 2;
799
+ const bh = zoomTarget.height + padY * 2;
804
800
  if (bw === 0 || bh === 0) return;
805
801
  const zoomFn = mode === "cover" ? Math.max : Math.min;
806
802
  const zoom = zoomFn(containerSize.w / bw, containerSize.h / bh);
807
- const cx = b.x + b.width / 2;
808
- const cy = b.y + b.height / 2;
803
+ const cx = zoomTarget.x + zoomTarget.width / 2;
804
+ const cy = zoomTarget.y + zoomTarget.height / 2;
809
805
  const x = containerSize.w / 2 - cx * zoom;
810
806
  const y = containerSize.h / 2 - cy * zoom;
807
+ if (clampBounds) {
808
+ const coverZoom = Math.max(
809
+ containerSize.w / clampBounds.width,
810
+ containerSize.h / clampBounds.height
811
+ );
812
+ store.getState().setMinZoom(Math.max(coverZoom, minZoomProp != null ? minZoomProp : 0));
813
+ } else {
814
+ store.getState().setMinZoom(minZoomProp != null ? minZoomProp : 0.5);
815
+ }
811
816
  let vp = { x, y, zoom };
812
817
  if (extent) {
813
818
  vp = clampViewport(vp, containerSize.w, containerSize.h, extent);
@@ -822,7 +827,10 @@ function FocusHandler({
822
827
  containerSize.w,
823
828
  containerSize.h,
824
829
  extent,
825
- setViewport
830
+ setViewport,
831
+ clampBounds,
832
+ minZoomProp,
833
+ store
826
834
  ]);
827
835
  return /* @__PURE__ */ import_react4.default.createElement(
828
836
  "div",
@@ -908,7 +916,9 @@ function FlowRenderer({
908
916
  focusAnimation,
909
917
  focusMode = "contain",
910
918
  responsiveFit,
911
- translateExtent: translateExtentProp
919
+ translateExtent: translateExtentProp,
920
+ minZoom: minZoomProp,
921
+ maxZoom: maxZoomProp
912
922
  }) {
913
923
  var _a;
914
924
  const nodeTypeDefsMap = import_react4.default.useMemo(() => {
@@ -999,6 +1009,8 @@ function FlowRenderer({
999
1009
  zoomOnScroll: interactive,
1000
1010
  zoomOnPinch: interactive,
1001
1011
  zoomOnDoubleClick: false,
1012
+ minZoom: minZoomProp,
1013
+ maxZoom: maxZoomProp,
1002
1014
  proOptions: { hideAttribution: true }
1003
1015
  },
1004
1016
  mergedCSS && /* @__PURE__ */ import_react4.default.createElement("style", { dangerouslySetInnerHTML: { __html: mergedCSS } }),
@@ -1018,7 +1030,9 @@ function FlowRenderer({
1018
1030
  animation: focusAnimation != null ? focusAnimation : true,
1019
1031
  mode: focusMode,
1020
1032
  responsive: responsiveFit != null ? responsiveFit : true,
1021
- extent: translateExtent
1033
+ extent: translateExtent,
1034
+ clampBounds,
1035
+ minZoomProp
1022
1036
  }
1023
1037
  ),
1024
1038
  children
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/ui/Flow/index.tsx","../../src/ui/Flow/types.ts","../../src/ui/Flow/built-in-node-types.ts","../../src/ui/Flow/built-in-edge-types.ts","../../src/ui/Flow/useFlow.ts","../../src/core/query/query-keys.ts","../../src/ui/Flow/useFlowData.ts","../../src/ui/Flow/utils.ts","../../src/ui/Flow/template-compiler.ts"],"sourcesContent":["'use client'\n\nimport React from 'react'\nimport {\n ReactFlow,\n ReactFlowProvider,\n Background,\n Controls,\n MiniMap,\n MarkerType,\n useReactFlow,\n type NodeTypes,\n type NodeProps,\n type Edge,\n} from '@xyflow/react'\nimport type {\n CanvasData,\n DynamicNodeData,\n DynamicNodeSlotProps,\n EdgeSlotProps,\n EdgeTypeDef,\n FlowBounds,\n FlowEdge,\n FlowNode,\n FlowViewport,\n FrameNodeData,\n FrameNodeSlotProps,\n NodeTypeDef,\n NodeTypeFieldDef,\n NodeWrapperSlotProps,\n} from './types'\n\nexport type {\n CanvasData,\n DynamicNodeSlotProps,\n FlowNode,\n FlowEdge,\n FlowViewport,\n FlowNodePosition,\n FlowNodeData,\n DynamicNodeData,\n FrameNodeData,\n NodeTypeDef,\n NodeTypeFieldDef,\n EdgeTypeDef,\n FrameNodeSlotProps,\n EdgeSlotProps,\n NodeWrapperSlotProps,\n FlowBounds,\n} from './types'\nexport { isDynamicNode, isFrameNode } from './types'\nexport { BUILT_IN_NODE_TYPES } from './built-in-node-types'\nexport { BUILT_IN_EDGE_TYPES } from './built-in-edge-types'\nexport { useFlow } from './useFlow'\nexport type { SDKClient, UseFlowOptions, UseFlowResult } from './useFlow'\nexport { useFlowData } from './useFlowData'\nexport type { UseFlowDataOptions, UseFlowDataResult } from './useFlowData'\nexport { getNodeBounds, getFrames, getFrameData } from './utils'\nexport type { FrameData } from './utils'\nexport { compileTemplate, clearTemplateCache } from './template-compiler'\nexport type { CodeComponentProps } from './template-compiler'\n\nimport { compileTemplate } from './template-compiler'\n\n// ── Helpers ──\n\nfunction sanitizeUrl(url: string | undefined): string | undefined {\n if (!url) return url\n try {\n const parsed = new URL(url)\n if (parsed.protocol === 'http:' || parsed.protocol === 'https:') return url\n return undefined\n } catch {\n return undefined\n }\n}\n\nfunction toMarkerType(value: string): MarkerType | undefined {\n if (value === 'arrow') return MarkerType.Arrow\n if (value === 'arrowclosed') return MarkerType.ArrowClosed\n return undefined\n}\n\n// ── Field renderer (type-aware, matching console style) ──\n\nfunction renderFieldValue(\n key: string,\n val: unknown,\n fieldDef?: NodeTypeFieldDef,\n): React.ReactNode {\n if (val == null || val === '') return null\n\n const fieldType = fieldDef?.fieldType\n\n // Image field — image only, no decoration\n if (\n fieldType === 'image' ||\n (typeof val === 'object' && val !== null && 'url' in val)\n ) {\n const imgUrl =\n typeof val === 'string' ? val : (val as { url?: string })?.url\n const safeUrl = sanitizeUrl(imgUrl)\n if (!safeUrl) return null\n return (\n <img\n key={key}\n src={safeUrl}\n alt=\"\"\n draggable={false}\n style={{ flex: 1, minHeight: 0, width: '100%', objectFit: 'contain' }}\n />\n )\n }\n\n // All other fields — text only\n return (\n <div\n key={key}\n style={{\n fontSize: 11,\n whiteSpace: 'pre-wrap',\n wordBreak: 'break-word',\n overflow: 'hidden',\n flexShrink: 0,\n }}\n >\n {String(val)}\n </div>\n )\n}\n\n// ── Default dynamic node renderer (no typeDef) ──\n\nfunction DefaultDynamicNode({ data }: NodeProps) {\n const d = data as unknown as DynamicNodeData\n return (\n <div\n style={{\n width: '100%',\n height: '100%',\n display: 'flex',\n flexDirection: 'column',\n }}\n >\n {d.fields &&\n Object.entries(d.fields)\n .filter(([, v]) => v != null && v !== '')\n .map(([key, val]) => renderFieldValue(key, val))}\n </div>\n )\n}\n\n// ── Template error boundary ──\n\nclass TemplateErrorBoundary extends React.Component<\n { resetKey?: string; children: React.ReactNode },\n { error: Error | null }\n> {\n state: { error: Error | null } = { error: null }\n static getDerivedStateFromError(error: Error) {\n return { error }\n }\n componentDidUpdate(prevProps: { resetKey?: string }) {\n if (prevProps.resetKey !== this.props.resetKey && this.state.error) {\n this.setState({ error: null })\n }\n }\n render() {\n if (this.state.error) {\n return (\n <div style={{ padding: 8, fontSize: 11, color: '#ef4444' }}>\n <strong>Render error</strong>\n <pre style={{ fontSize: 10, whiteSpace: 'pre-wrap' }}>\n {this.state.error.message}\n </pre>\n </div>\n )\n }\n return this.props.children\n }\n}\n\n// ── Enhanced dynamic node renderer (with NodeTypeDef) ──\n\nfunction EnhancedDynamicNode({\n data,\n typeDef,\n width,\n height,\n}: {\n data: DynamicNodeData\n typeDef: NodeTypeDef\n width?: number\n height?: number\n}) {\n // Tier 2: Custom template rendering\n if (typeDef.template) {\n const Component = compileTemplate(typeDef.template, typeDef.slug)\n if (Component) {\n return (\n <div\n className={`flow-node flow-node--${typeDef.slug}${typeDef.transparentBackground ? ' flow-node--transparent-bg' : ''}`}\n >\n <TemplateErrorBoundary resetKey={typeDef.template}>\n <Component\n fields={data.fields}\n label={data.label}\n color={typeDef.color}\n nodeTypeSlug={typeDef.slug}\n width={width || typeDef.defaultSize.width}\n height={height || typeDef.defaultSize.height}\n />\n </TemplateErrorBoundary>\n </div>\n )\n }\n }\n\n // Tier 1: Default field rendering\n return (\n <div\n style={{\n width: '100%',\n height: '100%',\n display: 'flex',\n flexDirection: 'column',\n }}\n >\n {typeDef.fields.map((f) => {\n const val = data.fields[f.name]\n if (val == null || val === '') return null\n return renderFieldValue(f.name, val, f)\n })}\n </div>\n )\n}\n\n// ── Default frame node renderer ──\n\nfunction DefaultFrameNode({ data }: NodeProps) {\n const d = data as unknown as FrameNodeData\n const baseColor = d.color ?? 'rgba(128,128,128,0.15)'\n const padding = d.padding ?? 20\n const borderStyle = d.borderStyle ?? 'dashed'\n const opacity = d.opacity ?? 0.15\n\n // Apply opacity to rgba colors\n const bgColor = (() => {\n const m = baseColor.match(/rgba?\\((\\d+),\\s*(\\d+),\\s*(\\d+)/)\n if (m) return `rgba(${m[1]},${m[2]},${m[3]},${opacity})`\n return baseColor\n })()\n\n return (\n <div\n style={{\n backgroundColor: bgColor,\n padding,\n width: '100%',\n height: '100%',\n border:\n borderStyle === 'none'\n ? 'none'\n : `2px ${borderStyle} rgba(128,128,128,0.3)`,\n }}\n >\n <div\n style={{\n fontSize: 11,\n fontWeight: 600,\n color: 'rgba(128,128,128,0.6)',\n userSelect: 'none',\n }}\n >\n {d.label}\n </div>\n </div>\n )\n}\n\n// ── Node types builder ──\n\nfunction createNodeTypes(\n nodeRenderers?: Record<string, React.ComponentType<DynamicNodeSlotProps>>,\n nodeTypeDefsMap?: Map<string, NodeTypeDef>,\n frameRenderer?: React.ComponentType<FrameNodeSlotProps>,\n nodeWrapper?: React.ComponentType<NodeWrapperSlotProps>,\n renderNode?: (\n props: DynamicNodeSlotProps,\n defaultRender: React.ReactElement,\n ) => React.ReactElement | null,\n): NodeTypes {\n const types: NodeTypes = {} as NodeTypes\n\n // Dynamic node type\n types.dynamic = ((props: NodeProps) => {\n const d = props.data as unknown as DynamicNodeData\n const typeDef = nodeTypeDefsMap?.get(d.nodeTypeSlug)\n const CustomRenderer = nodeRenderers?.[d.nodeTypeSlug]\n\n let content: React.ReactElement\n if (CustomRenderer) {\n content = (\n <CustomRenderer\n id={props.id}\n nodeTypeSlug={d.nodeTypeSlug}\n label={d.label}\n fields={d.fields}\n nodeTypeDef={typeDef}\n />\n )\n } else if (typeDef) {\n content = (\n <EnhancedDynamicNode\n data={d}\n typeDef={typeDef}\n width={props.width}\n height={props.height}\n />\n )\n } else {\n content = <DefaultDynamicNode {...props} />\n }\n\n // S5: renderNode global callback\n if (renderNode) {\n const slotProps: DynamicNodeSlotProps = {\n id: props.id,\n nodeTypeSlug: d.nodeTypeSlug,\n label: d.label,\n fields: d.fields,\n nodeTypeDef: typeDef,\n }\n const result = renderNode(slotProps, content)\n if (result !== null) content = result\n }\n\n // S3: nodeWrapper\n if (nodeWrapper) {\n const Wrapper = nodeWrapper\n content = (\n <Wrapper\n id={props.id}\n nodeTypeSlug={d.nodeTypeSlug}\n label={d.label}\n selected={props.selected}\n nodeTypeDef={typeDef}\n >\n {content}\n </Wrapper>\n )\n }\n\n return content\n }) as NodeTypes[string]\n\n // S1: Frame node type — custom or default\n types.frame = frameRenderer\n ? (((props: NodeProps) => {\n const d = props.data as unknown as FrameNodeData\n const Renderer = frameRenderer\n return (\n <Renderer\n id={props.id}\n label={d.label}\n color={d.color}\n padding={d.padding}\n borderStyle={d.borderStyle}\n opacity={d.opacity}\n />\n )\n }) as NodeTypes[string])\n : (DefaultFrameNode as NodeTypes[string])\n\n return types\n}\n\n// S2: Edge types builder\n\nfunction createEdgeTypes(\n edgeRenderers?: Record<string, React.ComponentType<EdgeSlotProps>>,\n edgeTypeDefsMap?: Map<string, EdgeTypeDef>,\n): Record<string, React.ComponentType<EdgeSlotProps>> | undefined {\n if (!edgeRenderers || Object.keys(edgeRenderers).length === 0)\n return undefined\n const types: Record<string, React.ComponentType<EdgeSlotProps>> = {}\n for (const [slug, Renderer] of Object.entries(edgeRenderers)) {\n types[slug] = ((props: Record<string, unknown>) => {\n const def = edgeTypeDefsMap?.get(slug)\n return (\n <Renderer\n id={props.id as string}\n edgeTypeSlug={slug}\n source={props.source as string}\n target={props.target as string}\n label={props.label as string | undefined}\n fields={\n (props.data as Record<string, unknown> | undefined)?.fields as\n | Record<string, unknown>\n | undefined\n }\n edgeTypeDef={def}\n style={props.style as React.CSSProperties | undefined}\n />\n )\n }) as unknown as React.ComponentType<EdgeSlotProps>\n }\n return types\n}\n\n// S8: FocusHandler — must be inside ReactFlowProvider\n\n// Match d3-zoom's translateExtent clamping so the initial viewport\n// is identical to what the user sees after the first drag.\nfunction clampViewport(\n vp: { x: number; y: number; zoom: number },\n cw: number,\n ch: number,\n extent: [[number, number], [number, number]],\n): { x: number; y: number; zoom: number } {\n const left = -vp.x / vp.zoom\n const right = (cw - vp.x) / vp.zoom\n const top = -vp.y / vp.zoom\n const bottom = (ch - vp.y) / vp.zoom\n\n const dx0 = left - extent[0][0]\n const dx1 = right - extent[1][0]\n const dy0 = top - extent[0][1]\n const dy1 = bottom - extent[1][1]\n\n const cx =\n dx1 > dx0 ? (dx0 + dx1) / 2 : Math.min(0, dx0) || Math.max(0, dx1)\n const cy =\n dy1 > dy0 ? (dy0 + dy1) / 2 : Math.min(0, dy0) || Math.max(0, dy1)\n\n if (cx === 0 && cy === 0) return vp\n return { x: vp.x + cx * vp.zoom, y: vp.y + cy * vp.zoom, zoom: vp.zoom }\n}\n\nfunction FocusHandler({\n bounds,\n padding,\n animation,\n mode,\n responsive,\n extent,\n}: {\n bounds: FlowBounds\n padding: number\n animation: boolean | number\n mode: 'contain' | 'cover'\n responsive: boolean\n extent?: [[number, number], [number, number]]\n}) {\n const { setViewport } = useReactFlow()\n const containerRef = React.useRef<HTMLDivElement>(null)\n const boundsKey = `${bounds.x},${bounds.y},${bounds.width},${bounds.height}`\n const boundsRef = React.useRef(bounds)\n boundsRef.current = bounds\n const [containerSize, setContainerSize] = React.useState({ w: 0, h: 0 })\n const prevBoundsKeyRef = React.useRef<string | null>(null)\n const prevSizeRef = React.useRef({ w: 0, h: 0 })\n\n // Track container size via ResizeObserver\n React.useEffect(() => {\n const el = containerRef.current\n if (!el) return\n const observer = new ResizeObserver((entries) => {\n const entry = entries[0]\n if (!entry) return\n const { width, height } = entry.contentRect\n setContainerSize({ w: width, h: height })\n })\n observer.observe(el)\n return () => observer.disconnect()\n }, [])\n\n React.useEffect(() => {\n if (containerSize.w === 0 || containerSize.h === 0) return\n\n const prevKey = prevBoundsKeyRef.current\n const prevSize = prevSizeRef.current\n prevBoundsKeyRef.current = boundsKey\n prevSizeRef.current = { w: containerSize.w, h: containerSize.h }\n\n // Determine trigger: bounds change vs resize-only\n const isBoundsChange = prevKey !== boundsKey\n const isResizeOnly =\n !isBoundsChange &&\n (prevSize.w !== containerSize.w || prevSize.h !== containerSize.h)\n const isInitial = prevKey === null\n\n // Skip resize-triggered re-fit if responsiveFit is disabled\n if (isResizeOnly && !responsive) return\n\n // Animate on initial + bounds change; instant on resize\n const duration =\n isInitial || isBoundsChange\n ? animation === true\n ? 300\n : typeof animation === 'number'\n ? animation\n : 0\n : 0\n\n const b = boundsRef.current\n const padX = padding * b.width\n const padY = padding * b.height\n const bw = b.width + padX * 2\n const bh = b.height + padY * 2\n\n if (bw === 0 || bh === 0) return\n\n // contain: fit inside viewport, cover: fill viewport (may crop)\n const zoomFn = mode === 'cover' ? Math.max : Math.min\n const zoom = zoomFn(containerSize.w / bw, containerSize.h / bh)\n const cx = b.x + b.width / 2\n const cy = b.y + b.height / 2\n const x = containerSize.w / 2 - cx * zoom\n const y = containerSize.h / 2 - cy * zoom\n\n let vp = { x, y, zoom }\n if (extent) {\n vp = clampViewport(vp, containerSize.w, containerSize.h, extent)\n }\n setViewport(vp, { duration })\n }, [\n boundsKey,\n padding,\n animation,\n mode,\n responsive,\n containerSize.w,\n containerSize.h,\n extent,\n setViewport,\n ])\n\n // Measurement div — always rendered to track container size\n return (\n <div\n ref={containerRef}\n style={{\n position: 'absolute',\n inset: 0,\n pointerEvents: 'none',\n visibility: 'hidden',\n }}\n />\n )\n}\n\n// ── Edge style resolver ──\n\nconst EDGE_TYPE_MAP: Record<string, string> = {\n step: 'step',\n smoothstep: 'smoothstep',\n bezier: 'default',\n default: 'default',\n}\n\nfunction applyEdgeStyles(\n edges: FlowEdge[],\n edgeTypeDefsMap?: Map<string, EdgeTypeDef>,\n): Edge[] {\n if (!edgeTypeDefsMap?.size) return edges as unknown as Edge[]\n\n return edges.map((edge) => {\n const slug = edge.edgeTypeSlug\n if (!slug) return edge as unknown as Edge\n\n const def = edgeTypeDefsMap.get(slug)\n if (!def) return edge as unknown as Edge\n\n const styled: Edge = { ...(edge as unknown as Edge) }\n\n // Edge type (line style) — canvas value takes precedence\n if (!styled.type && def.lineStyle) {\n styled.type = EDGE_TYPE_MAP[def.lineStyle] ?? 'default'\n }\n\n // Visual style — canvas style merged with def as fallback\n styled.style = {\n ...(def.color ? { stroke: def.color } : undefined),\n ...(def.strokeWidth ? { strokeWidth: def.strokeWidth } : undefined),\n ...edge.style,\n }\n\n // Animation — canvas value takes precedence\n if (styled.animated == null && def.animated) styled.animated = true\n\n // Markers — canvas value takes precedence over def\n if (!styled.markerStart) {\n const startType = toMarkerType(def.markerStart)\n if (startType) {\n styled.markerStart = {\n type: startType,\n ...(def.color ? { color: def.color } : undefined),\n }\n }\n }\n if (!styled.markerEnd) {\n const endType = toMarkerType(def.markerEnd)\n if (endType) {\n styled.markerEnd = {\n type: endType,\n ...(def.color ? { color: def.color } : undefined),\n }\n }\n }\n\n return styled\n })\n}\n\n// ── FlowRenderer ──\n\n/**\n * Renders a Flow canvas in read-only mode.\n *\n * Requires `@xyflow/react` peer dependency and its CSS:\n * ```ts\n * import '@xyflow/react/dist/style.css'\n * ```\n */\nexport interface FlowRendererProps {\n /** Canvas data from Flow document's `canvas` field */\n data: CanvasData\n /** Container className */\n className?: string\n /** Container style */\n style?: React.CSSProperties\n /** Custom renderers by node type slug (e.g., `{ 'product-card': MyProductCard }`) */\n nodeRenderers?: Record<string, React.ComponentType<DynamicNodeSlotProps>>\n /** Node type definitions for enhanced rendering (field-type-aware display) */\n nodeTypeDefs?: NodeTypeDef[]\n /** Edge type definitions for styled edges (color, stroke, markers, animation) */\n edgeTypeDefs?: EdgeTypeDef[]\n /** Show background pattern (default: false) */\n background?: boolean\n /** Allow user interaction - pan, zoom (default: false for read-only display) */\n interactive?: boolean\n /** Fit view on mount (default: true) */\n fitView?: boolean\n /** Called when a node is clicked */\n onNodeClick?: (event: React.MouseEvent, node: FlowNode) => void\n /** Called when a node is double-clicked */\n onNodeDoubleClick?: (event: React.MouseEvent, node: FlowNode) => void\n /** Called on node right-click / context menu */\n onNodeContextMenu?: (event: React.MouseEvent, node: FlowNode) => void\n /** Called when mouse enters a node */\n onNodeMouseEnter?: (event: React.MouseEvent, node: FlowNode) => void\n /** Called when mouse leaves a node */\n onNodeMouseLeave?: (event: React.MouseEvent, node: FlowNode) => void\n /** Called when an edge is clicked */\n onEdgeClick?: (event: React.MouseEvent, edge: FlowEdge) => void\n /** S1: Custom frame node renderer. Should be a stable reference (memoize or define outside render). */\n frameRenderer?: React.ComponentType<FrameNodeSlotProps>\n /** S2: Custom edge renderers by edge type slug. Should be a stable reference (memoize or define outside render). */\n edgeRenderers?: Record<string, React.ComponentType<EdgeSlotProps>>\n /** S3: Wraps every dynamic node's rendered content. Should be a stable reference (memoize or define outside render). */\n nodeWrapper?: React.ComponentType<NodeWrapperSlotProps>\n /** S4: Show controls (default: false) */\n controls?: boolean\n /** S4: Show minimap (default: false) */\n minimap?: boolean\n /** S4: Custom minimap node color function */\n minimapNodeColor?: (node: FlowNode) => string\n /** S4: Additional children rendered inside ReactFlow */\n children?: React.ReactNode\n /** S5: Global override for all dynamic nodes. Should be a stable reference (memoize or define outside render). */\n renderNode?: (\n props: DynamicNodeSlotProps,\n defaultRender: React.ReactElement,\n ) => React.ReactElement | null\n /** S6: Called when viewport changes (pan/zoom) */\n onViewportChange?: (viewport: FlowViewport) => void\n /** S6: Default viewport (used when fitView is false) */\n defaultViewport?: FlowViewport\n /** S8: Focus on specific bounds (used for initial viewport fit). */\n bounds?: FlowBounds\n /** S8: Separate bounds for panning/zoom restriction. When set, overrides bounds-based translateExtent. Useful when fitBounds (content) differs from clampBounds (frame area). */\n clampBounds?: FlowBounds\n /** S8: Padding for focus bounds (default: 0.1) */\n focusPadding?: number\n /** S8: Animate focus transition (true=300ms, number=custom ms, false=instant) */\n focusAnimation?: boolean | number\n /** S8: Focus mode — \"contain\" fits entire bounds (may have margins), \"cover\" fills viewport (may crop). Default: \"contain\" */\n focusMode?: 'contain' | 'cover'\n /** Re-fit viewport on container resize (default: true when bounds is set) */\n responsiveFit?: boolean\n /** Override translateExtent directly. When set, overrides the automatic bounds-based panning restriction. */\n translateExtent?: [[number, number], [number, number]]\n}\n\nexport function FlowRenderer({\n data,\n className,\n style,\n nodeRenderers,\n nodeTypeDefs,\n edgeTypeDefs,\n background = false,\n interactive = false,\n fitView = true,\n onNodeClick,\n onNodeDoubleClick,\n onNodeContextMenu,\n onNodeMouseEnter,\n onNodeMouseLeave,\n onEdgeClick,\n frameRenderer,\n edgeRenderers,\n nodeWrapper,\n controls,\n minimap,\n minimapNodeColor,\n children,\n renderNode,\n onViewportChange,\n defaultViewport: defaultViewportProp,\n bounds,\n clampBounds,\n focusPadding,\n focusAnimation,\n focusMode = 'contain',\n responsiveFit,\n translateExtent: translateExtentProp,\n}: FlowRendererProps) {\n const nodeTypeDefsMap = React.useMemo(() => {\n if (!nodeTypeDefs?.length) return undefined\n return new Map(nodeTypeDefs.map((d) => [d.slug, d]))\n }, [nodeTypeDefs])\n\n const edgeTypeDefsMap = React.useMemo(() => {\n if (!edgeTypeDefs?.length) return undefined\n return new Map(edgeTypeDefs.map((d) => [d.slug, d]))\n }, [edgeTypeDefs])\n\n const nodeTypes = React.useMemo(\n () =>\n createNodeTypes(\n nodeRenderers,\n nodeTypeDefsMap,\n frameRenderer,\n nodeWrapper,\n renderNode,\n ),\n [nodeRenderers, nodeTypeDefsMap, frameRenderer, nodeWrapper, renderNode],\n )\n\n // S2: Custom edge types\n const customEdgeTypes = React.useMemo(\n () => createEdgeTypes(edgeRenderers, edgeTypeDefsMap),\n [edgeRenderers, edgeTypeDefsMap],\n )\n\n // Merge all customCSS from node type definitions\n const mergedCSS = React.useMemo(() => {\n if (!nodeTypeDefs?.length) return ''\n return nodeTypeDefs\n .filter((d) => d.customCSS)\n .map((d) => d.customCSS)\n .join('\\n')\n }, [nodeTypeDefs])\n\n const styledEdges = React.useMemo(() => {\n let edges = applyEdgeStyles(data?.edges ?? [], edgeTypeDefsMap)\n // When custom edge renderers exist, set edge type to slug for matching\n if (edgeRenderers) {\n edges = edges.map((edge) => {\n const slug = (edge as unknown as FlowEdge).edgeTypeSlug\n if (slug && edgeRenderers[slug]) {\n return { ...edge, type: slug }\n }\n return edge\n })\n }\n return edges\n }, [data?.edges, edgeTypeDefsMap, edgeRenderers])\n\n // Panning restriction: explicit prop > clampBounds (no padding) > bounds (with padding)\n const translateExtent = React.useMemo(() => {\n if (translateExtentProp) return translateExtentProp\n const es = clampBounds ?? bounds\n if (!es) return undefined\n const ep = clampBounds ? 0 : (focusPadding ?? 0.1)\n return [\n [es.x - ep * es.width, es.y - ep * es.height],\n [es.x + es.width * (1 + ep), es.y + es.height * (1 + ep)],\n ] as [[number, number], [number, number]]\n }, [translateExtentProp, clampBounds, bounds, focusPadding])\n\n if (!data) return null\n\n const resolvedDefaultViewport =\n defaultViewportProp ??\n (!fitView && data.viewport ? data.viewport : undefined)\n\n return (\n <ReactFlowProvider>\n <div\n className={className}\n style={{\n width: '100%',\n height: '100%',\n background: 'transparent',\n ...style,\n }}\n >\n <ReactFlow\n nodes={\n (data.nodes ?? []) as unknown as Parameters<\n typeof ReactFlow\n >[0]['nodes']\n }\n edges={styledEdges}\n nodeTypes={nodeTypes}\n edgeTypes={\n customEdgeTypes as Parameters<typeof ReactFlow>[0]['edgeTypes']\n }\n defaultViewport={resolvedDefaultViewport}\n fitView={bounds ? false : fitView}\n translateExtent={translateExtent}\n onNodeClick={\n onNodeClick as Parameters<typeof ReactFlow>[0]['onNodeClick']\n }\n onNodeDoubleClick={\n onNodeDoubleClick as Parameters<\n typeof ReactFlow\n >[0]['onNodeDoubleClick']\n }\n onNodeContextMenu={\n onNodeContextMenu as Parameters<\n typeof ReactFlow\n >[0]['onNodeContextMenu']\n }\n onNodeMouseEnter={\n onNodeMouseEnter as Parameters<\n typeof ReactFlow\n >[0]['onNodeMouseEnter']\n }\n onNodeMouseLeave={\n onNodeMouseLeave as Parameters<\n typeof ReactFlow\n >[0]['onNodeMouseLeave']\n }\n onEdgeClick={\n onEdgeClick as Parameters<typeof ReactFlow>[0]['onEdgeClick']\n }\n onMoveEnd={\n onViewportChange\n ? (((_: unknown, vp: { x: number; y: number; zoom: number }) => {\n onViewportChange(vp)\n }) as Parameters<typeof ReactFlow>[0]['onMoveEnd'])\n : undefined\n }\n nodesDraggable={interactive}\n nodesConnectable={false}\n elementsSelectable={\n interactive ||\n !!onNodeClick ||\n !!onNodeDoubleClick ||\n !!onEdgeClick\n }\n panOnDrag={interactive}\n zoomOnScroll={interactive}\n zoomOnPinch={interactive}\n zoomOnDoubleClick={false}\n proOptions={{ hideAttribution: true }}\n >\n {mergedCSS && (\n <style dangerouslySetInnerHTML={{ __html: mergedCSS }} />\n )}\n {background && <Background />}\n {controls && <Controls />}\n {minimap && (\n <MiniMap\n nodeColor={\n minimapNodeColor as Parameters<typeof MiniMap>[0]['nodeColor']\n }\n />\n )}\n {bounds && (\n <FocusHandler\n bounds={bounds}\n padding={focusPadding ?? 0.1}\n animation={focusAnimation ?? true}\n mode={focusMode}\n responsive={responsiveFit ?? true}\n extent={translateExtent}\n />\n )}\n {children}\n </ReactFlow>\n </div>\n </ReactFlowProvider>\n )\n}\n","import type React from 'react'\n\n// ── Dynamic node data ──\n\nexport interface DynamicNodeData {\n nodeTypeSlug: string\n label: string\n fields: Record<string, unknown>\n}\n\nexport type FlowNodeData = (DynamicNodeData | FrameNodeData) &\n Record<string, unknown>\n\n// ── Canvas types (mirrors @xyflow/react but standalone) ──\n\nexport interface FlowNodePosition {\n x: number\n y: number\n}\n\nexport interface FlowNode {\n id: string\n type?: string\n position: FlowNodePosition\n data: FlowNodeData\n parentId?: string\n style?: React.CSSProperties\n width?: number\n height?: number\n measured?: { width?: number; height?: number }\n draggable?: boolean\n selectable?: boolean\n [key: string]: unknown\n}\n\nexport interface FlowEdge {\n id: string\n source: string\n target: string\n sourceHandle?: string | null\n targetHandle?: string | null\n type?: string\n style?: React.CSSProperties\n animated?: boolean\n markerStart?: unknown\n markerEnd?: unknown\n edgeTypeSlug?: string\n fields?: Record<string, unknown>\n [key: string]: unknown\n}\n\nexport interface FlowViewport {\n x: number\n y: number\n zoom: number\n}\n\nexport interface CanvasData {\n nodes: FlowNode[]\n edges: FlowEdge[]\n viewport: FlowViewport\n}\n\n// ── Node type definitions (mirrors console's NodeTypeDef) ──\n\nexport interface NodeTypeFieldDef {\n name: string\n label: string\n fieldType:\n | 'text'\n | 'textarea'\n | 'number'\n | 'url'\n | 'color'\n | 'image'\n | 'select'\n | 'toggle'\n options?: { label: string; value: string }[]\n defaultValue?: string\n required?: boolean\n}\n\nexport interface NodeTypeDef {\n slug: string\n name: string\n color: string\n defaultSize: { width: number; height: number }\n fields: NodeTypeFieldDef[]\n transparentBackground?: boolean\n template?: string | null\n customCSS?: string | null\n}\n\n// ── Edge type definitions (mirrors console's EdgeTypeDef) ──\n\nexport interface EdgeTypeDef {\n slug: string\n name: string\n color: string\n strokeWidth: number\n animated: boolean\n lineStyle: string\n markerStart: string\n markerEnd: string\n fields: NodeTypeFieldDef[]\n}\n\n// ── Type guards ──\n\nexport function isDynamicNode(\n node: FlowNode,\n): node is FlowNode & { data: DynamicNodeData } {\n return node.type === 'dynamic'\n}\n\nexport function isFrameNode(\n node: FlowNode,\n): node is FlowNode & { data: FrameNodeData } {\n return node.type === 'frame'\n}\n\n// ── Component slot props ──\n\nexport interface DynamicNodeSlotProps {\n id: string\n nodeTypeSlug: string\n label: string\n fields: Record<string, unknown>\n nodeTypeDef?: NodeTypeDef\n}\n\n// ── Frame node data ──\n\nexport interface FrameNodeData {\n label: string\n color?: string\n padding?: number\n borderStyle?: 'dashed' | 'solid' | 'none'\n opacity?: number\n}\n\n// S1: Frame renderer slot\nexport interface FrameNodeSlotProps {\n id: string\n label: string\n color?: string\n padding?: number\n borderStyle?: 'dashed' | 'solid' | 'none'\n opacity?: number\n children?: React.ReactNode\n}\n\n// S2: Edge renderer slot\nexport interface EdgeSlotProps {\n id: string\n edgeTypeSlug?: string\n source: string\n target: string\n label?: string\n fields?: Record<string, unknown>\n edgeTypeDef?: EdgeTypeDef\n style?: React.CSSProperties\n}\n\n// S3: Node wrapper slot\nexport interface NodeWrapperSlotProps {\n id: string\n nodeTypeSlug: string\n label: string\n selected?: boolean\n nodeTypeDef?: NodeTypeDef\n children: React.ReactNode\n}\n\n// S8: Viewport focus\nexport interface FlowBounds {\n x: number\n y: number\n width: number\n height: number\n}\n","import type { NodeTypeDef } from './types'\n\nexport const BUILT_IN_NODE_TYPES: NodeTypeDef[] = [\n {\n slug: 'text',\n name: 'Text',\n color: '#e5e7eb',\n defaultSize: { width: 200, height: 200 },\n fields: [{ name: 'body', label: 'Body', fieldType: 'textarea' }],\n },\n {\n slug: 'image',\n name: 'Image',\n color: '#e5e7eb',\n transparentBackground: true,\n defaultSize: { width: 200, height: 200 },\n fields: [\n { name: 'image', label: 'Image', fieldType: 'image' },\n { name: 'alt', label: 'Alt Text', fieldType: 'text' },\n { name: 'caption', label: 'Caption', fieldType: 'text' },\n ],\n },\n]\n","import type { EdgeTypeDef } from './types'\n\nexport const BUILT_IN_EDGE_TYPES: EdgeTypeDef[] = [\n {\n slug: 'default',\n name: 'Default',\n color: '',\n strokeWidth: 2,\n animated: false,\n lineStyle: 'default',\n markerStart: 'none',\n markerEnd: 'arrow',\n fields: [],\n },\n]\n","'use client'\n\nimport { useQuery, type QueryClient } from '@tanstack/react-query'\nimport { useMemo } from 'react'\nimport type { CanvasData, NodeTypeDef, EdgeTypeDef } from './types'\nimport { BUILT_IN_NODE_TYPES } from './built-in-node-types'\nimport { BUILT_IN_EDGE_TYPES } from './built-in-edge-types'\nimport { collectionKeys } from '../../core/query/query-keys'\n\n// ── Client interface ──\n// Structurally compatible with both BrowserClient and ServerClient.\n// Lists only the collections useFlow actually queries so the generic\n// `from<T extends PublicCollection>` on the real clients satisfies this.\n\ntype FlowCollection = 'flows' | 'flow-node-types' | 'flow-edge-types'\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype AnyFn = (...args: any[]) => any\n\nexport interface SDKClient {\n from(collection: FlowCollection): {\n find: AnyFn\n findById: AnyFn\n }\n queryClient: QueryClient\n}\n\n// ── Options & Result ──\n\nexport interface UseFlowOptions {\n /** SDK client instance (BrowserClient or ServerClient) */\n client: SDKClient\n /** Flow slug (URL-friendly identifier) */\n slug?: string\n /** Flow document ID (UUID) */\n id?: string\n /** Enable/disable data fetching (default: true) */\n enabled?: boolean\n}\n\nexport interface UseFlowResult {\n data: CanvasData | undefined\n nodeTypeDefs: NodeTypeDef[]\n edgeTypeDefs: EdgeTypeDef[]\n flow: Record<string, unknown> | undefined\n isLoading: boolean\n error: Error | null\n}\n\n// ── Helpers ──\n\nfunction toNodeTypeDef(doc: Record<string, unknown>): NodeTypeDef {\n return {\n slug: String(doc.slug ?? ''),\n name: String(doc.title ?? ''),\n color: String(doc.color ?? '#e5e7eb'),\n defaultSize: (doc.defaultSize as NodeTypeDef['defaultSize']) ?? {\n width: 200,\n height: 200,\n },\n fields: Array.isArray(doc.fields)\n ? (doc.fields as NodeTypeDef['fields'])\n : [],\n transparentBackground: Boolean(doc.transparentBackground),\n template: (doc.template as string) ?? null,\n customCSS: (doc.customCSS as string) ?? null,\n }\n}\n\nfunction toEdgeTypeDef(doc: Record<string, unknown>): EdgeTypeDef {\n return {\n slug: String(doc.slug ?? ''),\n name: String(doc.title ?? ''),\n color: String(doc.color ?? ''),\n strokeWidth: (doc.strokeWidth as number) ?? 2,\n animated: (doc.animated as boolean) ?? false,\n lineStyle: String(doc.lineStyle ?? 'default'),\n markerStart: String(doc.markerStart ?? 'none'),\n markerEnd: String(doc.markerEnd ?? 'arrow'),\n fields: Array.isArray(doc.fields)\n ? (doc.fields as EdgeTypeDef['fields'])\n : [],\n }\n}\n\n// ── Hook ──\n\nexport function useFlow(options: UseFlowOptions): UseFlowResult {\n const { client, slug, id, enabled = true } = options\n const hasIdentifier = !!(slug || id)\n const identifier = id ?? slug ?? ''\n\n // Fetch flow document\n const flowQuery = useQuery<Record<string, unknown>>(\n {\n queryKey: collectionKeys('flows').detail(identifier),\n queryFn: async () => {\n if (id) {\n return client.from('flows').findById(id)\n }\n const result = await client.from('flows').find({\n where: { slug: { equals: slug } },\n limit: 1,\n })\n const doc = result.docs[0]\n if (!doc) throw new Error(`Flow not found: ${slug}`)\n return doc\n },\n enabled: enabled && hasIdentifier,\n },\n client.queryClient,\n )\n\n // Fetch tenant's custom node types\n const nodeTypesQuery = useQuery<Record<string, unknown>[]>(\n {\n queryKey: collectionKeys('flow-node-types').lists(),\n queryFn: async () => {\n const result = await client.from('flow-node-types').find({ limit: 100 })\n return result.docs\n },\n enabled,\n },\n client.queryClient,\n )\n\n // Fetch tenant's custom edge types\n const edgeTypesQuery = useQuery<Record<string, unknown>[]>(\n {\n queryKey: collectionKeys('flow-edge-types').lists(),\n queryFn: async () => {\n const result = await client.from('flow-edge-types').find({ limit: 100 })\n return result.docs\n },\n enabled,\n },\n client.queryClient,\n )\n\n // Merge built-in + API node types\n const nodeTypeDefs = useMemo<NodeTypeDef[]>(() => {\n const apiDefs = (nodeTypesQuery.data ?? []).map(toNodeTypeDef)\n const builtInSlugs = new Set(BUILT_IN_NODE_TYPES.map((t) => t.slug))\n const customDefs = apiDefs.filter((d) => !builtInSlugs.has(d.slug))\n return [...BUILT_IN_NODE_TYPES, ...customDefs]\n }, [nodeTypesQuery.data])\n\n // Merge built-in + API edge types\n const edgeTypeDefs = useMemo<EdgeTypeDef[]>(() => {\n const apiDefs = (edgeTypesQuery.data ?? []).map(toEdgeTypeDef)\n const builtInSlugs = new Set(BUILT_IN_EDGE_TYPES.map((t) => t.slug))\n const customDefs = apiDefs.filter((d) => !builtInSlugs.has(d.slug))\n return [...BUILT_IN_EDGE_TYPES, ...customDefs]\n }, [edgeTypesQuery.data])\n\n const flow = flowQuery.data\n const canvas = flow?.canvas as CanvasData | undefined\n\n return {\n data: canvas,\n nodeTypeDefs,\n edgeTypeDefs,\n flow,\n isLoading:\n flowQuery.isLoading ||\n nodeTypesQuery.isLoading ||\n edgeTypesQuery.isLoading,\n error:\n (flowQuery.error as Error | null) ??\n (nodeTypesQuery.error as Error | null) ??\n (edgeTypesQuery.error as Error | null),\n }\n}\n","import type { PublicCollection, ApiQueryOptions } from '../client/types'\n\nexport function collectionKeys<T extends PublicCollection>(collection: T) {\n return {\n all: [collection] as const,\n lists: () => [collection, 'list'] as const,\n list: (options?: ApiQueryOptions) => [collection, 'list', options] as const,\n details: () => [collection, 'detail'] as const,\n detail: (id: string, options?: ApiQueryOptions) =>\n [collection, 'detail', id, options] as const,\n infinites: () => [collection, 'infinite'] as const,\n infinite: (options?: Omit<ApiQueryOptions, 'page'>) =>\n [collection, 'infinite', options] as const,\n }\n}\n\nexport const customerKeys = {\n all: ['customer'] as const,\n me: () => ['customer', 'me'] as const,\n}\n","import { useMemo } from 'react'\nimport type { CanvasData, FlowNode, NodeTypeDef, EdgeTypeDef } from './types'\nimport type { Edge } from '@xyflow/react'\nimport { BUILT_IN_NODE_TYPES } from './built-in-node-types'\nimport { BUILT_IN_EDGE_TYPES } from './built-in-edge-types'\n\n// ── Options & Result ──\n\nexport interface UseFlowDataOptions {\n /** Canvas data from Flow document's `canvas` field */\n data: CanvasData | undefined\n /** Node type definitions (defaults to built-in types) */\n nodeTypeDefs?: NodeTypeDef[]\n /** Edge type definitions (defaults to built-in types) */\n edgeTypeDefs?: EdgeTypeDef[]\n}\n\nexport interface UseFlowDataResult {\n /** Nodes from canvas data */\n nodes: FlowNode[]\n /** Edges from canvas data (typed for @xyflow/react) */\n edges: Edge[]\n /** Map of node type slug to definition */\n nodeTypeDefsMap: Map<string, NodeTypeDef>\n /** Map of edge type slug to definition */\n edgeTypeDefsMap: Map<string, EdgeTypeDef>\n}\n\n/**\n * Pure data transformation hook — extracts nodes, edges, and type definition\n * maps from canvas data without any rendering. Useful for headless usage\n * (custom layouts, analytics, server-side processing).\n */\nexport function useFlowData(options: UseFlowDataOptions): UseFlowDataResult {\n const { data, nodeTypeDefs: inputNodeDefs, edgeTypeDefs: inputEdgeDefs } =\n options\n\n const nodeTypeDefsMap = useMemo(() => {\n const allDefs = inputNodeDefs ?? BUILT_IN_NODE_TYPES\n return new Map(allDefs.map((d) => [d.slug, d]))\n }, [inputNodeDefs])\n\n const edgeTypeDefsMap = useMemo(() => {\n const allDefs = inputEdgeDefs ?? BUILT_IN_EDGE_TYPES\n return new Map(allDefs.map((d) => [d.slug, d]))\n }, [inputEdgeDefs])\n\n const nodes = useMemo(() => data?.nodes ?? [], [data?.nodes])\n const edges = useMemo(() => (data?.edges ?? []) as unknown as Edge[], [data?.edges])\n\n return {\n nodes,\n edges,\n nodeTypeDefsMap,\n edgeTypeDefsMap,\n }\n}\n","import type { FlowNode, FlowEdge, FlowBounds, CanvasData } from './types'\n\n// ── Shared helpers ──\n\nfunction getNodeSize(node: FlowNode): { width: number; height: number } {\n return {\n width:\n (node.style?.width as number) ??\n node.measured?.width ??\n node.width ??\n 200,\n height:\n (node.style?.height as number) ??\n node.measured?.height ??\n node.height ??\n 200,\n }\n}\n\nfunction getAbsolutePosition(\n node: FlowNode,\n nodeMap: Map<string, FlowNode>,\n): { x: number; y: number } {\n let x = node.position.x\n let y = node.position.y\n let current = node\n const visited = new Set<string>([node.id])\n while (current.parentId) {\n const parentId = current.parentId\n if (visited.has(parentId)) break\n const parent = nodeMap.get(parentId)\n if (!parent) break\n visited.add(parent.id)\n x += parent.position.x\n y += parent.position.y\n current = parent\n }\n return { x, y }\n}\n\n/** Collect a node and all its descendants (BFS with index pointer to avoid O(Q²) shift). */\nfunction collectDescendants(\n nodes: FlowNode[],\n rootId: string,\n): Set<string> {\n const result = new Set<string>([rootId])\n const queue = [rootId]\n let i = 0\n while (i < queue.length) {\n const current = queue[i++]\n for (const n of nodes) {\n if (n.parentId === current && !result.has(n.id)) {\n result.add(n.id)\n queue.push(n.id)\n }\n }\n }\n return result\n}\n\n// ── Public utilities ──\n\n/**\n * Calculate bounding box for given node IDs.\n * Pure function — usable in SSR, server components, or outside React.\n */\nexport function getNodeBounds(\n nodes: FlowNode[],\n nodeIds: string[],\n): FlowBounds | undefined {\n const idSet = new Set(nodeIds)\n const targetNodes = nodes.filter((n) => idSet.has(n.id))\n if (targetNodes.length === 0) return undefined\n\n const nodeMap = new Map(nodes.map((n) => [n.id, n]))\n\n let minX = Infinity\n let minY = Infinity\n let maxX = -Infinity\n let maxY = -Infinity\n\n for (const node of targetNodes) {\n const abs = getAbsolutePosition(node, nodeMap)\n const { width: w, height: h } = getNodeSize(node)\n minX = Math.min(minX, abs.x)\n minY = Math.min(minY, abs.y)\n maxX = Math.max(maxX, abs.x + w)\n maxY = Math.max(maxY, abs.y + h)\n }\n\n return { x: minX, y: minY, width: maxX - minX, height: maxY - minY }\n}\n\n/**\n * Get all frame nodes with their bounds.\n * Sorted by position (top-left to bottom-right).\n */\nexport function getFrames(\n nodes: FlowNode[],\n): Array<{ id: string; label: string; bounds: FlowBounds }> {\n const frames = nodes.filter((n) => n.type === 'frame')\n if (frames.length === 0) return []\n\n const nodeMap = new Map(nodes.map((n) => [n.id, n]))\n\n return frames\n .map((f) => {\n const data = f.data as { label?: string }\n const abs = getAbsolutePosition(f, nodeMap)\n const { width: w, height: h } = getNodeSize(f)\n return {\n id: f.id,\n label: data.label ?? '',\n bounds: { x: abs.x, y: abs.y, width: w, height: h },\n }\n })\n .sort((a, b) => a.bounds.y - b.bounds.y || a.bounds.x - b.bounds.x)\n}\n\n/** Result of getFrameData — contains filtered canvas + dual bounds. */\nexport interface FrameData {\n /** Canvas data containing only the frame's descendants (nodes have draggable: false). */\n data: CanvasData\n /** Bounding box of child content nodes — use for initial viewport fit (centering). */\n fitBounds: FlowBounds\n /** Bounding box of the frame itself — use for panning/zoom restriction (clamp). */\n clampBounds: FlowBounds\n /** @deprecated Use fitBounds instead. Alias for clampBounds for backward compatibility. */\n bounds: FlowBounds\n}\n\n/**\n * Extract a frame's descendants and related edges from canvas data.\n * Recursively collects all nested children (supports nested frames).\n * Returns undefined if frameId is not found or is not a frame node.\n *\n * Child nodes are marked `draggable: false` to prevent interfering with canvas panning.\n * The frame node itself is included (use `frameRenderer={() => null}` to hide it).\n *\n * Returns dual bounds:\n * - `fitBounds`: child content bounding box (for centering the viewport)\n * - `clampBounds`: frame area bounding box (for panning restriction)\n */\nexport function getFrameData(\n data: CanvasData,\n frameId: string,\n): FrameData | undefined {\n const frame = data.nodes.find((n) => n.id === frameId)\n if (!frame || frame.type !== 'frame') return undefined\n\n // Recursively collect frame + all descendants\n const descendantIds = collectDescendants(data.nodes, frameId)\n const childNodes = data.nodes\n .filter((n) => descendantIds.has(n.id))\n .map((n) => ({ ...n, draggable: false }))\n\n // Keep only edges where both source and target are within the frame\n const childEdges = data.edges.filter(\n (e: FlowEdge) => descendantIds.has(e.source) && descendantIds.has(e.target),\n )\n\n // clampBounds: frame's own bounding box (for panning restriction)\n const frameBounds = getNodeBounds(data.nodes, [frameId])\n const { width: w, height: h } = getNodeSize(frame)\n const clampBounds: FlowBounds = frameBounds ?? {\n x: frame.position.x,\n y: frame.position.y,\n width: w,\n height: h,\n }\n\n // fitBounds: child content bounding box (for centering)\n const contentNodeIds = childNodes\n .filter((n) => n.id !== frameId)\n .map((n) => n.id)\n const contentBounds = contentNodeIds.length > 0\n ? getNodeBounds(data.nodes, contentNodeIds)\n : undefined\n const fitBounds = contentBounds ?? clampBounds\n\n return {\n data: {\n nodes: childNodes,\n edges: childEdges,\n viewport: data.viewport,\n },\n fitBounds,\n clampBounds,\n bounds: clampBounds,\n }\n}\n","'use client'\n\nimport React from 'react'\nimport { transform } from 'sucrase'\n\nexport interface CodeComponentProps {\n fields: Record<string, unknown>\n label: string\n color: string\n nodeTypeSlug: string\n width: number\n height: number\n}\n\nconst MAX_CACHE_SIZE = 100\nconst componentCache = new Map<string, React.FC<CodeComponentProps>>()\n\nfunction hashCode(str: string): string {\n let hash = 0\n for (let i = 0; i < str.length; i++) {\n const char = str.charCodeAt(i)\n hash = ((hash << 5) - hash + char) | 0\n }\n return hash.toString(36)\n}\n\nconst BLOCKED_PATTERNS = [\n /\\bdocument\\s*\\./,\n /\\bwindow\\s*\\./,\n /\\bwindow\\s*\\[/,\n /\\bglobalThis\\s*\\./,\n /\\bfetch\\s*\\(/,\n /\\bXMLHttpRequest/,\n /\\beval\\s*\\(/,\n /\\bFunction\\s*\\(/,\n /\\bimport\\s*\\(/,\n /\\blocalStorage/,\n /\\bsessionStorage/,\n /\\bcookie/,\n /\\bpostMessage\\s*\\(/,\n /\\blocation\\s*[.=]/,\n /\\bnavigator\\s*\\./,\n /\\bsetTimeout\\s*\\(/,\n /\\bsetInterval\\s*\\(/,\n /\\bsetImmediate\\s*\\(/,\n /\\brequire\\s*\\(/,\n]\n\nfunction validateTemplateCode(code: string): boolean {\n return !BLOCKED_PATTERNS.some((pattern) => pattern.test(code))\n}\n\nexport function compileTemplate(\n code: string,\n slug: string,\n): React.FC<CodeComponentProps> | null {\n const cacheKey = `${slug}:${hashCode(code)}`\n\n if (componentCache.has(cacheKey)) {\n const cached = componentCache.get(cacheKey)!\n componentCache.delete(cacheKey)\n componentCache.set(cacheKey, cached)\n return cached\n }\n\n if (!validateTemplateCode(code)) {\n console.warn(`[flow] Template \"${slug}\" contains blocked patterns`)\n return null\n }\n\n try {\n const { code: jsCode } = transform(code, {\n transforms: ['typescript', 'jsx', 'imports'],\n jsxRuntime: 'classic',\n jsxPragma: 'React.createElement',\n jsxFragmentPragma: 'React.Fragment',\n })\n\n // Shadow dangerous globals to neutralize blocklist bypasses\n const factory = new Function(\n 'React',\n `\n var window = undefined;\n var document = undefined;\n var globalThis = undefined;\n var setTimeout = undefined;\n var setInterval = undefined;\n var setImmediate = undefined;\n var fetch = undefined;\n var XMLHttpRequest = undefined;\n var navigator = undefined;\n var location = undefined;\n var exports = {};\n var module = { exports: exports };\n ${jsCode}\n return module.exports.default || module.exports;\n `,\n )\n\n const Component = factory(React)\n if (typeof Component !== 'function') return null\n\n if (componentCache.size >= MAX_CACHE_SIZE) {\n const oldestKey = componentCache.keys().next().value\n if (oldestKey) componentCache.delete(oldestKey)\n }\n\n componentCache.set(cacheKey, Component)\n return Component\n } catch (e) {\n console.warn(`[flow] Failed to compile template for \"${slug}\":`, e)\n return null\n }\n}\n\nexport function clearTemplateCache(): void {\n componentCache.clear()\n}\n"],"mappings":"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","names":["import_react","_a","import_react","import_react","React","React","_a"]}
1
+ {"version":3,"sources":["../../src/ui/Flow/index.tsx","../../src/ui/Flow/types.ts","../../src/ui/Flow/built-in-node-types.ts","../../src/ui/Flow/built-in-edge-types.ts","../../src/ui/Flow/useFlow.ts","../../src/core/query/query-keys.ts","../../src/ui/Flow/useFlowData.ts","../../src/ui/Flow/utils.ts","../../src/ui/Flow/template-compiler.ts"],"sourcesContent":["'use client'\n\nimport React from 'react'\nimport {\n ReactFlow,\n ReactFlowProvider,\n Background,\n Controls,\n MiniMap,\n MarkerType,\n useReactFlow,\n useStoreApi,\n type NodeTypes,\n type NodeProps,\n type Edge,\n} from '@xyflow/react'\nimport type {\n CanvasData,\n DynamicNodeData,\n DynamicNodeSlotProps,\n EdgeSlotProps,\n EdgeTypeDef,\n FlowBounds,\n FlowEdge,\n FlowNode,\n FlowViewport,\n FrameNodeData,\n FrameNodeSlotProps,\n NodeTypeDef,\n NodeTypeFieldDef,\n NodeWrapperSlotProps,\n} from './types'\n\nexport type {\n CanvasData,\n DynamicNodeSlotProps,\n FlowNode,\n FlowEdge,\n FlowViewport,\n FlowNodePosition,\n FlowNodeData,\n DynamicNodeData,\n FrameNodeData,\n NodeTypeDef,\n NodeTypeFieldDef,\n EdgeTypeDef,\n FrameNodeSlotProps,\n EdgeSlotProps,\n NodeWrapperSlotProps,\n FlowBounds,\n} from './types'\nexport { isDynamicNode, isFrameNode } from './types'\nexport { BUILT_IN_NODE_TYPES } from './built-in-node-types'\nexport { BUILT_IN_EDGE_TYPES } from './built-in-edge-types'\nexport { useFlow } from './useFlow'\nexport type { SDKClient, UseFlowOptions, UseFlowResult } from './useFlow'\nexport { useFlowData } from './useFlowData'\nexport type { UseFlowDataOptions, UseFlowDataResult } from './useFlowData'\nexport { getNodeBounds, getFrames, getFrameData } from './utils'\nexport type { FrameData } from './utils'\nexport { compileTemplate, clearTemplateCache } from './template-compiler'\nexport type { CodeComponentProps } from './template-compiler'\n\nimport { compileTemplate } from './template-compiler'\n\n// ── Helpers ──\n\nfunction sanitizeUrl(url: string | undefined): string | undefined {\n if (!url) return url\n try {\n const parsed = new URL(url)\n if (parsed.protocol === 'http:' || parsed.protocol === 'https:') return url\n return undefined\n } catch {\n return undefined\n }\n}\n\nfunction toMarkerType(value: string): MarkerType | undefined {\n if (value === 'arrow') return MarkerType.Arrow\n if (value === 'arrowclosed') return MarkerType.ArrowClosed\n return undefined\n}\n\n// ── Field renderer (type-aware, matching console style) ──\n\nfunction renderFieldValue(\n key: string,\n val: unknown,\n fieldDef?: NodeTypeFieldDef,\n): React.ReactNode {\n if (val == null || val === '') return null\n\n const fieldType = fieldDef?.fieldType\n\n // Image field — image only, no decoration\n if (\n fieldType === 'image' ||\n (typeof val === 'object' && val !== null && 'url' in val)\n ) {\n const imgUrl =\n typeof val === 'string' ? val : (val as { url?: string })?.url\n const safeUrl = sanitizeUrl(imgUrl)\n if (!safeUrl) return null\n return (\n <img\n key={key}\n src={safeUrl}\n alt=\"\"\n draggable={false}\n style={{ flex: 1, minHeight: 0, width: '100%', objectFit: 'contain' }}\n />\n )\n }\n\n // All other fields — text only\n return (\n <div\n key={key}\n style={{\n fontSize: 11,\n whiteSpace: 'pre-wrap',\n wordBreak: 'break-word',\n overflow: 'hidden',\n flexShrink: 0,\n }}\n >\n {String(val)}\n </div>\n )\n}\n\n// ── Default dynamic node renderer (no typeDef) ──\n\nfunction DefaultDynamicNode({ data }: NodeProps) {\n const d = data as unknown as DynamicNodeData\n return (\n <div\n style={{\n width: '100%',\n height: '100%',\n display: 'flex',\n flexDirection: 'column',\n }}\n >\n {d.fields &&\n Object.entries(d.fields)\n .filter(([, v]) => v != null && v !== '')\n .map(([key, val]) => renderFieldValue(key, val))}\n </div>\n )\n}\n\n// ── Template error boundary ──\n\nclass TemplateErrorBoundary extends React.Component<\n { resetKey?: string; children: React.ReactNode },\n { error: Error | null }\n> {\n state: { error: Error | null } = { error: null }\n static getDerivedStateFromError(error: Error) {\n return { error }\n }\n componentDidUpdate(prevProps: { resetKey?: string }) {\n if (prevProps.resetKey !== this.props.resetKey && this.state.error) {\n this.setState({ error: null })\n }\n }\n render() {\n if (this.state.error) {\n return (\n <div style={{ padding: 8, fontSize: 11, color: '#ef4444' }}>\n <strong>Render error</strong>\n <pre style={{ fontSize: 10, whiteSpace: 'pre-wrap' }}>\n {this.state.error.message}\n </pre>\n </div>\n )\n }\n return this.props.children\n }\n}\n\n// ── Enhanced dynamic node renderer (with NodeTypeDef) ──\n\nfunction EnhancedDynamicNode({\n data,\n typeDef,\n width,\n height,\n}: {\n data: DynamicNodeData\n typeDef: NodeTypeDef\n width?: number\n height?: number\n}) {\n // Tier 2: Custom template rendering\n if (typeDef.template) {\n const Component = compileTemplate(typeDef.template, typeDef.slug)\n if (Component) {\n return (\n <div\n className={`flow-node flow-node--${typeDef.slug}${typeDef.transparentBackground ? ' flow-node--transparent-bg' : ''}`}\n style={{ width: '100%', height: '100%' }}\n >\n <TemplateErrorBoundary resetKey={typeDef.template}>\n <Component\n fields={data.fields}\n label={data.label}\n color={typeDef.color}\n nodeTypeSlug={typeDef.slug}\n width={width || typeDef.defaultSize.width}\n height={height || typeDef.defaultSize.height}\n />\n </TemplateErrorBoundary>\n </div>\n )\n }\n }\n\n // Tier 1: Default field rendering\n return (\n <div\n style={{\n width: '100%',\n height: '100%',\n display: 'flex',\n flexDirection: 'column',\n }}\n >\n {typeDef.fields.map((f) => {\n const val = data.fields[f.name]\n if (val == null || val === '') return null\n return renderFieldValue(f.name, val, f)\n })}\n </div>\n )\n}\n\n// ── Default frame node renderer ──\n\nfunction DefaultFrameNode({ data }: NodeProps) {\n const d = data as unknown as FrameNodeData\n const baseColor = d.color ?? 'rgb(128,128,128)'\n const padding = d.padding ?? 20\n const borderStyle = d.borderStyle ?? 'dashed'\n const opacity = d.opacity ?? 0.15\n\n // Apply opacity to color at render time\n const bgColor = (() => {\n const m = baseColor.match(/rgba?\\((\\d+),\\s*(\\d+),\\s*(\\d+)/)\n if (m) return `rgba(${m[1]},${m[2]},${m[3]},${opacity})`\n return baseColor\n })()\n\n return (\n <div\n style={{\n backgroundColor: bgColor,\n padding,\n width: '100%',\n height: '100%',\n border:\n borderStyle === 'none'\n ? 'none'\n : `2px ${borderStyle} rgba(128,128,128,0.3)`,\n }}\n >\n <div\n style={{\n fontSize: 11,\n fontWeight: 600,\n color: 'rgba(128,128,128,0.6)',\n userSelect: 'none',\n }}\n >\n {d.label}\n </div>\n </div>\n )\n}\n\n// ── Node types builder ──\n\nfunction createNodeTypes(\n nodeRenderers?: Record<string, React.ComponentType<DynamicNodeSlotProps>>,\n nodeTypeDefsMap?: Map<string, NodeTypeDef>,\n frameRenderer?: React.ComponentType<FrameNodeSlotProps>,\n nodeWrapper?: React.ComponentType<NodeWrapperSlotProps>,\n renderNode?: (\n props: DynamicNodeSlotProps,\n content: React.ReactElement,\n ) => React.ReactElement | null,\n): NodeTypes {\n const types: NodeTypes = {} as NodeTypes\n\n // Dynamic node type\n types.dynamic = ((props: NodeProps) => {\n const d = props.data as unknown as DynamicNodeData\n const typeDef = nodeTypeDefsMap?.get(d.nodeTypeSlug)\n const CustomRenderer = nodeRenderers?.[d.nodeTypeSlug]\n\n // Compute default rendering (template or field-based)\n const defaultRender: React.ReactElement = typeDef ? (\n <EnhancedDynamicNode\n data={d}\n typeDef={typeDef}\n width={props.width}\n height={props.height}\n />\n ) : (\n <DefaultDynamicNode {...props} />\n )\n\n const slotProps: DynamicNodeSlotProps = {\n id: props.id,\n nodeTypeSlug: d.nodeTypeSlug,\n label: d.label,\n fields: d.fields,\n nodeTypeDef: typeDef,\n selected: props.selected,\n width: props.width,\n height: props.height,\n defaultRender,\n }\n\n let content: React.ReactElement = CustomRenderer ? (\n <CustomRenderer {...slotProps} />\n ) : (\n defaultRender\n )\n\n // S5: renderNode global callback\n if (renderNode) {\n const result = renderNode(slotProps, content)\n if (result !== null) content = result\n }\n\n // S3: nodeWrapper\n if (nodeWrapper) {\n const Wrapper = nodeWrapper\n content = (\n <Wrapper\n id={props.id}\n nodeTypeSlug={d.nodeTypeSlug}\n label={d.label}\n selected={props.selected}\n nodeTypeDef={typeDef}\n >\n {content}\n </Wrapper>\n )\n }\n\n return content\n }) as NodeTypes[string]\n\n // S1: Frame node type — custom or default\n types.frame = frameRenderer\n ? (((props: NodeProps) => {\n const d = props.data as unknown as FrameNodeData\n const Renderer = frameRenderer\n return (\n <Renderer\n id={props.id}\n label={d.label}\n color={d.color}\n padding={d.padding}\n borderStyle={d.borderStyle}\n opacity={d.opacity}\n width={props.width}\n height={props.height}\n />\n )\n }) as NodeTypes[string])\n : (DefaultFrameNode as NodeTypes[string])\n\n return types\n}\n\n// S2: Edge types builder\n\nfunction createEdgeTypes(\n edgeRenderers?: Record<string, React.ComponentType<EdgeSlotProps>>,\n edgeTypeDefsMap?: Map<string, EdgeTypeDef>,\n): Record<string, React.ComponentType<EdgeSlotProps>> | undefined {\n if (!edgeRenderers || Object.keys(edgeRenderers).length === 0)\n return undefined\n const types: Record<string, React.ComponentType<EdgeSlotProps>> = {}\n for (const [slug, Renderer] of Object.entries(edgeRenderers)) {\n types[slug] = ((props: Record<string, unknown>) => {\n const def = edgeTypeDefsMap?.get(slug)\n return (\n <Renderer\n id={props.id as string}\n edgeTypeSlug={slug}\n source={props.source as string}\n target={props.target as string}\n label={props.label as string | undefined}\n fields={\n (props.data as Record<string, unknown> | undefined)?.fields as\n | Record<string, unknown>\n | undefined\n }\n edgeTypeDef={def}\n style={props.style as React.CSSProperties | undefined}\n />\n )\n }) as unknown as React.ComponentType<EdgeSlotProps>\n }\n return types\n}\n\n// S8: FocusHandler — must be inside ReactFlowProvider\n\n// Match d3-zoom's translateExtent clamping so the initial viewport\n// is identical to what the user sees after the first drag.\nfunction clampViewport(\n vp: { x: number; y: number; zoom: number },\n cw: number,\n ch: number,\n extent: [[number, number], [number, number]],\n): { x: number; y: number; zoom: number } {\n const left = -vp.x / vp.zoom\n const right = (cw - vp.x) / vp.zoom\n const top = -vp.y / vp.zoom\n const bottom = (ch - vp.y) / vp.zoom\n\n const dx0 = left - extent[0][0]\n const dx1 = right - extent[1][0]\n const dy0 = top - extent[0][1]\n const dy1 = bottom - extent[1][1]\n\n const cx =\n dx1 > dx0 ? (dx0 + dx1) / 2 : Math.min(0, dx0) || Math.max(0, dx1)\n const cy =\n dy1 > dy0 ? (dy0 + dy1) / 2 : Math.min(0, dy0) || Math.max(0, dy1)\n\n if (cx === 0 && cy === 0) return vp\n return { x: vp.x + cx * vp.zoom, y: vp.y + cy * vp.zoom, zoom: vp.zoom }\n}\n\nfunction FocusHandler({\n bounds,\n padding,\n animation,\n mode,\n responsive,\n extent,\n clampBounds,\n minZoomProp,\n}: {\n bounds: FlowBounds\n padding: number\n animation: boolean | number\n mode: 'contain' | 'cover'\n responsive: boolean\n extent?: [[number, number], [number, number]]\n /** When set, cover zoom of these bounds is enforced as minZoom via store API. */\n clampBounds?: FlowBounds\n /** User-specified minZoom prop, used with Math.max against coverZoom. */\n minZoomProp?: number\n}) {\n const { setViewport } = useReactFlow()\n const store = useStoreApi()\n const containerRef = React.useRef<HTMLDivElement>(null)\n const boundsKey = `${bounds.x},${bounds.y},${bounds.width},${bounds.height}`\n const boundsRef = React.useRef(bounds)\n boundsRef.current = bounds\n const [containerSize, setContainerSize] = React.useState({ w: 0, h: 0 })\n const prevBoundsKeyRef = React.useRef<string | null>(null)\n const prevSizeRef = React.useRef({ w: 0, h: 0 })\n\n // Track container size via ResizeObserver\n React.useEffect(() => {\n const el = containerRef.current\n if (!el) return\n const observer = new ResizeObserver((entries) => {\n const entry = entries[0]\n if (!entry) return\n const { width, height } = entry.contentRect\n setContainerSize({ w: width, h: height })\n })\n observer.observe(el)\n return () => observer.disconnect()\n }, [])\n\n React.useEffect(() => {\n if (containerSize.w === 0 || containerSize.h === 0) return\n\n const prevKey = prevBoundsKeyRef.current\n const prevSize = prevSizeRef.current\n prevBoundsKeyRef.current = boundsKey\n prevSizeRef.current = { w: containerSize.w, h: containerSize.h }\n\n // Determine trigger: bounds change vs resize-only\n const isBoundsChange = prevKey !== boundsKey\n const isResizeOnly =\n !isBoundsChange &&\n (prevSize.w !== containerSize.w || prevSize.h !== containerSize.h)\n const isInitial = prevKey === null\n\n // Skip resize-triggered re-fit if responsiveFit is disabled\n if (isResizeOnly && !responsive) return\n\n // Animate on initial + bounds change; instant on resize\n const duration =\n isInitial || isBoundsChange\n ? animation === true\n ? 300\n : typeof animation === 'number'\n ? animation\n : 0\n : 0\n\n const b = boundsRef.current\n // In cover mode with clampBounds, use clampBounds for zoom & centering\n // to prevent asymmetric gap when content is offset within frame\n const zoomTarget = mode === 'cover' && clampBounds ? clampBounds : b\n const padX = padding * zoomTarget.width\n const padY = padding * zoomTarget.height\n const bw = zoomTarget.width + padX * 2\n const bh = zoomTarget.height + padY * 2\n\n if (bw === 0 || bh === 0) return\n\n // contain: fit inside viewport, cover: fill viewport (may crop)\n const zoomFn = mode === 'cover' ? Math.max : Math.min\n const zoom = zoomFn(containerSize.w / bw, containerSize.h / bh)\n const cx = zoomTarget.x + zoomTarget.width / 2\n const cy = zoomTarget.y + zoomTarget.height / 2\n const x = containerSize.w / 2 - cx * zoom\n const y = containerSize.h / 2 - cy * zoom\n\n // Enforce minZoom from clampBounds so user cannot zoom out beyond the frame\n if (clampBounds) {\n const coverZoom = Math.max(\n containerSize.w / clampBounds.width,\n containerSize.h / clampBounds.height,\n )\n store.getState().setMinZoom(Math.max(coverZoom, minZoomProp ?? 0))\n } else {\n store.getState().setMinZoom(minZoomProp ?? 0.5)\n }\n\n let vp = { x, y, zoom }\n if (extent) {\n vp = clampViewport(vp, containerSize.w, containerSize.h, extent)\n }\n setViewport(vp, { duration })\n }, [\n boundsKey,\n padding,\n animation,\n mode,\n responsive,\n containerSize.w,\n containerSize.h,\n extent,\n setViewport,\n clampBounds,\n minZoomProp,\n store,\n ])\n\n // Measurement div — always rendered to track container size\n return (\n <div\n ref={containerRef}\n style={{\n position: 'absolute',\n inset: 0,\n pointerEvents: 'none',\n visibility: 'hidden',\n }}\n />\n )\n}\n\n// ── Edge style resolver ──\n\nconst EDGE_TYPE_MAP: Record<string, string> = {\n step: 'step',\n smoothstep: 'smoothstep',\n bezier: 'default',\n default: 'default',\n}\n\nfunction applyEdgeStyles(\n edges: FlowEdge[],\n edgeTypeDefsMap?: Map<string, EdgeTypeDef>,\n): Edge[] {\n if (!edgeTypeDefsMap?.size) return edges as unknown as Edge[]\n\n return edges.map((edge) => {\n const slug = edge.edgeTypeSlug\n if (!slug) return edge as unknown as Edge\n\n const def = edgeTypeDefsMap.get(slug)\n if (!def) return edge as unknown as Edge\n\n const styled: Edge = { ...(edge as unknown as Edge) }\n\n // Edge type (line style) — canvas value takes precedence\n if (!styled.type && def.lineStyle) {\n styled.type = EDGE_TYPE_MAP[def.lineStyle] ?? 'default'\n }\n\n // Visual style — canvas style merged with def as fallback\n styled.style = {\n ...(def.color ? { stroke: def.color } : undefined),\n ...(def.strokeWidth ? { strokeWidth: def.strokeWidth } : undefined),\n ...edge.style,\n }\n\n // Animation — canvas value takes precedence\n if (styled.animated == null && def.animated) styled.animated = true\n\n // Markers — canvas value takes precedence over def\n if (!styled.markerStart) {\n const startType = toMarkerType(def.markerStart)\n if (startType) {\n styled.markerStart = {\n type: startType,\n ...(def.color ? { color: def.color } : undefined),\n }\n }\n }\n if (!styled.markerEnd) {\n const endType = toMarkerType(def.markerEnd)\n if (endType) {\n styled.markerEnd = {\n type: endType,\n ...(def.color ? { color: def.color } : undefined),\n }\n }\n }\n\n return styled\n })\n}\n\n// ── FlowRenderer ──\n\n/**\n * Renders a Flow canvas in read-only mode.\n *\n * Requires `@xyflow/react` peer dependency and its CSS:\n * ```ts\n * import '@xyflow/react/dist/style.css'\n * ```\n */\nexport interface FlowRendererProps {\n /** Canvas data from Flow document's `canvas` field */\n data: CanvasData\n /** Container className */\n className?: string\n /** Container style */\n style?: React.CSSProperties\n /** Custom renderers by node type slug (e.g., `{ 'product-card': MyProductCard }`) */\n nodeRenderers?: Record<string, React.ComponentType<DynamicNodeSlotProps>>\n /** Node type definitions for enhanced rendering (field-type-aware display) */\n nodeTypeDefs?: NodeTypeDef[]\n /** Edge type definitions for styled edges (color, stroke, markers, animation) */\n edgeTypeDefs?: EdgeTypeDef[]\n /** Show background pattern (default: false) */\n background?: boolean\n /** Allow user interaction - pan, zoom (default: false for read-only display) */\n interactive?: boolean\n /** Fit view on mount (default: true) */\n fitView?: boolean\n /** Called when a node is clicked */\n onNodeClick?: (event: React.MouseEvent, node: FlowNode) => void\n /** Called when a node is double-clicked */\n onNodeDoubleClick?: (event: React.MouseEvent, node: FlowNode) => void\n /** Called on node right-click / context menu */\n onNodeContextMenu?: (event: React.MouseEvent, node: FlowNode) => void\n /** Called when mouse enters a node */\n onNodeMouseEnter?: (event: React.MouseEvent, node: FlowNode) => void\n /** Called when mouse leaves a node */\n onNodeMouseLeave?: (event: React.MouseEvent, node: FlowNode) => void\n /** Called when an edge is clicked */\n onEdgeClick?: (event: React.MouseEvent, edge: FlowEdge) => void\n /** S1: Custom frame node renderer. Should be a stable reference (memoize or define outside render). */\n frameRenderer?: React.ComponentType<FrameNodeSlotProps>\n /** S2: Custom edge renderers by edge type slug. Should be a stable reference (memoize or define outside render). */\n edgeRenderers?: Record<string, React.ComponentType<EdgeSlotProps>>\n /** S3: Wraps every dynamic node's rendered content. Should be a stable reference (memoize or define outside render). */\n nodeWrapper?: React.ComponentType<NodeWrapperSlotProps>\n /** S4: Show controls (default: false) */\n controls?: boolean\n /** S4: Show minimap (default: false) */\n minimap?: boolean\n /** S4: Custom minimap node color function */\n minimapNodeColor?: (node: FlowNode) => string\n /** S4: Additional children rendered inside ReactFlow */\n children?: React.ReactNode\n /** S5: Global override for all dynamic nodes. `content` is the resolved rendering (custom renderer output or default). `props.defaultRender` contains the original template/field-based rendering. */\n renderNode?: (\n props: DynamicNodeSlotProps,\n content: React.ReactElement,\n ) => React.ReactElement | null\n /** S6: Called when viewport changes (pan/zoom) */\n onViewportChange?: (viewport: FlowViewport) => void\n /** S6: Default viewport (used when fitView is false) */\n defaultViewport?: FlowViewport\n /** S8: Focus on specific bounds (used for initial viewport fit). */\n bounds?: FlowBounds\n /** S8: Separate bounds for panning/zoom restriction. When set, overrides bounds-based translateExtent. Useful when fitBounds (content) differs from clampBounds (frame area). */\n clampBounds?: FlowBounds\n /** S8: Padding for focus bounds (default: 0.1) */\n focusPadding?: number\n /** S8: Animate focus transition (true=300ms, number=custom ms, false=instant) */\n focusAnimation?: boolean | number\n /** S8: Focus mode — \"contain\" fits entire bounds (may have margins), \"cover\" fills viewport (may crop). Default: \"contain\" */\n focusMode?: 'contain' | 'cover'\n /** Re-fit viewport on container resize (default: true when bounds is set) */\n responsiveFit?: boolean\n /** Override translateExtent directly. When set, overrides the automatic bounds-based panning restriction. */\n translateExtent?: [[number, number], [number, number]]\n /** Minimum zoom level. When clampBounds is set, automatically enforced as cover zoom (user cannot zoom out beyond the frame). */\n minZoom?: number\n /** Maximum zoom level */\n maxZoom?: number\n}\n\nexport function FlowRenderer({\n data,\n className,\n style,\n nodeRenderers,\n nodeTypeDefs,\n edgeTypeDefs,\n background = false,\n interactive = false,\n fitView = true,\n onNodeClick,\n onNodeDoubleClick,\n onNodeContextMenu,\n onNodeMouseEnter,\n onNodeMouseLeave,\n onEdgeClick,\n frameRenderer,\n edgeRenderers,\n nodeWrapper,\n controls,\n minimap,\n minimapNodeColor,\n children,\n renderNode,\n onViewportChange,\n defaultViewport: defaultViewportProp,\n bounds,\n clampBounds,\n focusPadding,\n focusAnimation,\n focusMode = 'contain',\n responsiveFit,\n translateExtent: translateExtentProp,\n minZoom: minZoomProp,\n maxZoom: maxZoomProp,\n}: FlowRendererProps) {\n const nodeTypeDefsMap = React.useMemo(() => {\n if (!nodeTypeDefs?.length) return undefined\n return new Map(nodeTypeDefs.map((d) => [d.slug, d]))\n }, [nodeTypeDefs])\n\n const edgeTypeDefsMap = React.useMemo(() => {\n if (!edgeTypeDefs?.length) return undefined\n return new Map(edgeTypeDefs.map((d) => [d.slug, d]))\n }, [edgeTypeDefs])\n\n const nodeTypes = React.useMemo(\n () =>\n createNodeTypes(\n nodeRenderers,\n nodeTypeDefsMap,\n frameRenderer,\n nodeWrapper,\n renderNode,\n ),\n [nodeRenderers, nodeTypeDefsMap, frameRenderer, nodeWrapper, renderNode],\n )\n\n // S2: Custom edge types\n const customEdgeTypes = React.useMemo(\n () => createEdgeTypes(edgeRenderers, edgeTypeDefsMap),\n [edgeRenderers, edgeTypeDefsMap],\n )\n\n // Merge all customCSS from node type definitions\n const mergedCSS = React.useMemo(() => {\n if (!nodeTypeDefs?.length) return ''\n return nodeTypeDefs\n .filter((d) => d.customCSS)\n .map((d) => d.customCSS)\n .join('\\n')\n }, [nodeTypeDefs])\n\n const styledEdges = React.useMemo(() => {\n let edges = applyEdgeStyles(data?.edges ?? [], edgeTypeDefsMap)\n // When custom edge renderers exist, set edge type to slug for matching\n if (edgeRenderers) {\n edges = edges.map((edge) => {\n const slug = (edge as unknown as FlowEdge).edgeTypeSlug\n if (slug && edgeRenderers[slug]) {\n return { ...edge, type: slug }\n }\n return edge\n })\n }\n return edges\n }, [data?.edges, edgeTypeDefsMap, edgeRenderers])\n\n // Panning restriction: explicit prop > clampBounds (no padding, hard boundary) > bounds (with padding)\n const translateExtent = React.useMemo(() => {\n if (translateExtentProp) return translateExtentProp\n const es = clampBounds ?? bounds\n if (!es) return undefined\n const ep = clampBounds ? 0 : (focusPadding ?? 0.1)\n return [\n [es.x - ep * es.width, es.y - ep * es.height],\n [es.x + es.width * (1 + ep), es.y + es.height * (1 + ep)],\n ] as [[number, number], [number, number]]\n }, [translateExtentProp, clampBounds, bounds, focusPadding])\n\n if (!data) return null\n\n const resolvedDefaultViewport =\n defaultViewportProp ??\n (!fitView && data.viewport ? data.viewport : undefined)\n\n return (\n <ReactFlowProvider>\n <div\n className={className}\n style={{\n width: '100%',\n height: '100%',\n background: 'transparent',\n ...style,\n }}\n >\n <ReactFlow\n nodes={\n (data.nodes ?? []) as unknown as Parameters<\n typeof ReactFlow\n >[0]['nodes']\n }\n edges={styledEdges}\n nodeTypes={nodeTypes}\n edgeTypes={\n customEdgeTypes as Parameters<typeof ReactFlow>[0]['edgeTypes']\n }\n defaultViewport={resolvedDefaultViewport}\n fitView={bounds ? false : fitView}\n translateExtent={translateExtent}\n onNodeClick={\n onNodeClick as Parameters<typeof ReactFlow>[0]['onNodeClick']\n }\n onNodeDoubleClick={\n onNodeDoubleClick as Parameters<\n typeof ReactFlow\n >[0]['onNodeDoubleClick']\n }\n onNodeContextMenu={\n onNodeContextMenu as Parameters<\n typeof ReactFlow\n >[0]['onNodeContextMenu']\n }\n onNodeMouseEnter={\n onNodeMouseEnter as Parameters<\n typeof ReactFlow\n >[0]['onNodeMouseEnter']\n }\n onNodeMouseLeave={\n onNodeMouseLeave as Parameters<\n typeof ReactFlow\n >[0]['onNodeMouseLeave']\n }\n onEdgeClick={\n onEdgeClick as Parameters<typeof ReactFlow>[0]['onEdgeClick']\n }\n onMoveEnd={\n onViewportChange\n ? (((_: unknown, vp: { x: number; y: number; zoom: number }) => {\n onViewportChange(vp)\n }) as Parameters<typeof ReactFlow>[0]['onMoveEnd'])\n : undefined\n }\n nodesDraggable={interactive}\n nodesConnectable={false}\n elementsSelectable={\n interactive ||\n !!onNodeClick ||\n !!onNodeDoubleClick ||\n !!onEdgeClick\n }\n panOnDrag={interactive}\n zoomOnScroll={interactive}\n zoomOnPinch={interactive}\n zoomOnDoubleClick={false}\n minZoom={minZoomProp}\n maxZoom={maxZoomProp}\n proOptions={{ hideAttribution: true }}\n >\n {mergedCSS && (\n <style dangerouslySetInnerHTML={{ __html: mergedCSS }} />\n )}\n {background && <Background />}\n {controls && <Controls />}\n {minimap && (\n <MiniMap\n nodeColor={\n minimapNodeColor as Parameters<typeof MiniMap>[0]['nodeColor']\n }\n />\n )}\n {bounds && (\n <FocusHandler\n bounds={bounds}\n padding={focusPadding ?? 0.1}\n animation={focusAnimation ?? true}\n mode={focusMode}\n responsive={responsiveFit ?? true}\n extent={translateExtent}\n clampBounds={clampBounds}\n minZoomProp={minZoomProp}\n />\n )}\n {children}\n </ReactFlow>\n </div>\n </ReactFlowProvider>\n )\n}\n","import type React from 'react'\n\n// ── Dynamic node data ──\n\nexport interface DynamicNodeData {\n nodeTypeSlug: string\n label: string\n fields: Record<string, unknown>\n}\n\nexport type FlowNodeData = (DynamicNodeData | FrameNodeData) &\n Record<string, unknown>\n\n// ── Canvas types (mirrors @xyflow/react but standalone) ──\n\nexport interface FlowNodePosition {\n x: number\n y: number\n}\n\nexport interface FlowNode {\n id: string\n type?: string\n position: FlowNodePosition\n data: FlowNodeData\n parentId?: string\n style?: React.CSSProperties\n width?: number\n height?: number\n measured?: { width?: number; height?: number }\n draggable?: boolean\n selectable?: boolean\n [key: string]: unknown\n}\n\nexport interface FlowEdge {\n id: string\n source: string\n target: string\n sourceHandle?: string | null\n targetHandle?: string | null\n type?: string\n style?: React.CSSProperties\n animated?: boolean\n markerStart?: unknown\n markerEnd?: unknown\n edgeTypeSlug?: string\n fields?: Record<string, unknown>\n [key: string]: unknown\n}\n\nexport interface FlowViewport {\n x: number\n y: number\n zoom: number\n}\n\nexport interface CanvasData {\n nodes: FlowNode[]\n edges: FlowEdge[]\n viewport: FlowViewport\n}\n\n// ── Node type definitions (mirrors console's NodeTypeDef) ──\n\nexport interface NodeTypeFieldDef {\n name: string\n label: string\n fieldType:\n | 'text'\n | 'textarea'\n | 'number'\n | 'url'\n | 'color'\n | 'image'\n | 'select'\n | 'toggle'\n options?: { label: string; value: string }[]\n defaultValue?: string\n required?: boolean\n}\n\nexport interface NodeTypeDef {\n slug: string\n name: string\n color: string\n defaultSize: { width: number; height: number }\n fields: NodeTypeFieldDef[]\n transparentBackground?: boolean\n template?: string | null\n customCSS?: string | null\n}\n\n// ── Edge type definitions (mirrors console's EdgeTypeDef) ──\n\nexport interface EdgeTypeDef {\n slug: string\n name: string\n color: string\n strokeWidth: number\n animated: boolean\n lineStyle: string\n markerStart: string\n markerEnd: string\n fields: NodeTypeFieldDef[]\n}\n\n// ── Type guards ──\n\nexport function isDynamicNode(\n node: FlowNode,\n): node is FlowNode & { data: DynamicNodeData } {\n return node.type === 'dynamic'\n}\n\nexport function isFrameNode(\n node: FlowNode,\n): node is FlowNode & { data: FrameNodeData } {\n return node.type === 'frame'\n}\n\n// ── Component slot props ──\n\nexport interface DynamicNodeSlotProps {\n id: string\n nodeTypeSlug: string\n label: string\n fields: Record<string, unknown>\n nodeTypeDef?: NodeTypeDef\n /** Whether this node is currently selected */\n selected?: boolean\n /** Measured node width (undefined before first measurement) */\n width?: number\n /** Measured node height (undefined before first measurement) */\n height?: number\n /** The default rendering (template or field-based). Allows custom renderers to wrap/extend instead of replacing entirely. */\n defaultRender?: React.ReactElement\n}\n\n// ── Frame node data ──\n\nexport interface FrameNodeData {\n label: string\n color?: string\n padding?: number\n borderStyle?: 'dashed' | 'solid' | 'none'\n opacity?: number\n}\n\n// S1: Frame renderer slot\nexport interface FrameNodeSlotProps {\n id: string\n label: string\n color?: string\n padding?: number\n borderStyle?: 'dashed' | 'solid' | 'none'\n opacity?: number\n width?: number\n height?: number\n children?: React.ReactNode\n}\n\n// S2: Edge renderer slot\nexport interface EdgeSlotProps {\n id: string\n edgeTypeSlug?: string\n source: string\n target: string\n label?: string\n fields?: Record<string, unknown>\n edgeTypeDef?: EdgeTypeDef\n style?: React.CSSProperties\n}\n\n// S3: Node wrapper slot\nexport interface NodeWrapperSlotProps {\n id: string\n nodeTypeSlug: string\n label: string\n selected?: boolean\n nodeTypeDef?: NodeTypeDef\n children: React.ReactNode\n}\n\n// S8: Viewport focus\nexport interface FlowBounds {\n x: number\n y: number\n width: number\n height: number\n}\n","import type { NodeTypeDef } from './types'\n\nexport const BUILT_IN_NODE_TYPES: NodeTypeDef[] = [\n {\n slug: 'text',\n name: 'Text',\n color: '#e5e7eb',\n defaultSize: { width: 200, height: 200 },\n fields: [{ name: 'body', label: 'Body', fieldType: 'textarea' }],\n },\n {\n slug: 'image',\n name: 'Image',\n color: '#e5e7eb',\n transparentBackground: true,\n defaultSize: { width: 200, height: 200 },\n fields: [\n { name: 'image', label: 'Image', fieldType: 'image' },\n { name: 'alt', label: 'Alt Text', fieldType: 'text' },\n { name: 'caption', label: 'Caption', fieldType: 'text' },\n ],\n },\n]\n","import type { EdgeTypeDef } from './types'\n\nexport const BUILT_IN_EDGE_TYPES: EdgeTypeDef[] = [\n {\n slug: 'default',\n name: 'Default',\n color: '',\n strokeWidth: 2,\n animated: false,\n lineStyle: 'default',\n markerStart: 'none',\n markerEnd: 'arrow',\n fields: [],\n },\n]\n","'use client'\n\nimport { useQuery, type QueryClient } from '@tanstack/react-query'\nimport { useMemo } from 'react'\nimport type { CanvasData, NodeTypeDef, EdgeTypeDef } from './types'\nimport { BUILT_IN_NODE_TYPES } from './built-in-node-types'\nimport { BUILT_IN_EDGE_TYPES } from './built-in-edge-types'\nimport { collectionKeys } from '../../core/query/query-keys'\n\n// ── Client interface ──\n// Structurally compatible with both BrowserClient and ServerClient.\n// Lists only the collections useFlow actually queries so the generic\n// `from<T extends PublicCollection>` on the real clients satisfies this.\n\ntype FlowCollection = 'flows' | 'flow-node-types' | 'flow-edge-types'\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype AnyFn = (...args: any[]) => any\n\nexport interface SDKClient {\n from(collection: FlowCollection): {\n find: AnyFn\n findById: AnyFn\n }\n queryClient: QueryClient\n}\n\n// ── Options & Result ──\n\nexport interface UseFlowOptions {\n /** SDK client instance (BrowserClient or ServerClient) */\n client: SDKClient\n /** Flow slug (URL-friendly identifier) */\n slug?: string\n /** Flow document ID (UUID) */\n id?: string\n /** Enable/disable data fetching (default: true) */\n enabled?: boolean\n}\n\nexport interface UseFlowResult {\n data: CanvasData | undefined\n nodeTypeDefs: NodeTypeDef[]\n edgeTypeDefs: EdgeTypeDef[]\n flow: Record<string, unknown> | undefined\n isLoading: boolean\n error: Error | null\n}\n\n// ── Helpers ──\n\nfunction toNodeTypeDef(doc: Record<string, unknown>): NodeTypeDef {\n return {\n slug: String(doc.slug ?? ''),\n name: String(doc.title ?? ''),\n color: String(doc.color ?? '#e5e7eb'),\n defaultSize: (doc.defaultSize as NodeTypeDef['defaultSize']) ?? {\n width: 200,\n height: 200,\n },\n fields: Array.isArray(doc.fields)\n ? (doc.fields as NodeTypeDef['fields'])\n : [],\n transparentBackground: Boolean(doc.transparentBackground),\n template: (doc.template as string) ?? null,\n customCSS: (doc.customCSS as string) ?? null,\n }\n}\n\nfunction toEdgeTypeDef(doc: Record<string, unknown>): EdgeTypeDef {\n return {\n slug: String(doc.slug ?? ''),\n name: String(doc.title ?? ''),\n color: String(doc.color ?? ''),\n strokeWidth: (doc.strokeWidth as number) ?? 2,\n animated: (doc.animated as boolean) ?? false,\n lineStyle: String(doc.lineStyle ?? 'default'),\n markerStart: String(doc.markerStart ?? 'none'),\n markerEnd: String(doc.markerEnd ?? 'arrow'),\n fields: Array.isArray(doc.fields)\n ? (doc.fields as EdgeTypeDef['fields'])\n : [],\n }\n}\n\n// ── Hook ──\n\nexport function useFlow(options: UseFlowOptions): UseFlowResult {\n const { client, slug, id, enabled = true } = options\n const hasIdentifier = !!(slug || id)\n const identifier = id ?? slug ?? ''\n\n // Fetch flow document\n const flowQuery = useQuery<Record<string, unknown>>(\n {\n queryKey: collectionKeys('flows').detail(identifier),\n queryFn: async () => {\n if (id) {\n return client.from('flows').findById(id)\n }\n const result = await client.from('flows').find({\n where: { slug: { equals: slug } },\n limit: 1,\n })\n const doc = result.docs[0]\n if (!doc) throw new Error(`Flow not found: ${slug}`)\n return doc\n },\n enabled: enabled && hasIdentifier,\n },\n client.queryClient,\n )\n\n // Fetch tenant's custom node types\n const nodeTypesQuery = useQuery<Record<string, unknown>[]>(\n {\n queryKey: collectionKeys('flow-node-types').lists(),\n queryFn: async () => {\n const result = await client.from('flow-node-types').find({ limit: 100 })\n return result.docs\n },\n enabled,\n },\n client.queryClient,\n )\n\n // Fetch tenant's custom edge types\n const edgeTypesQuery = useQuery<Record<string, unknown>[]>(\n {\n queryKey: collectionKeys('flow-edge-types').lists(),\n queryFn: async () => {\n const result = await client.from('flow-edge-types').find({ limit: 100 })\n return result.docs\n },\n enabled,\n },\n client.queryClient,\n )\n\n // Merge built-in + API node types\n const nodeTypeDefs = useMemo<NodeTypeDef[]>(() => {\n const apiDefs = (nodeTypesQuery.data ?? []).map(toNodeTypeDef)\n const builtInSlugs = new Set(BUILT_IN_NODE_TYPES.map((t) => t.slug))\n const customDefs = apiDefs.filter((d) => !builtInSlugs.has(d.slug))\n return [...BUILT_IN_NODE_TYPES, ...customDefs]\n }, [nodeTypesQuery.data])\n\n // Merge built-in + API edge types\n const edgeTypeDefs = useMemo<EdgeTypeDef[]>(() => {\n const apiDefs = (edgeTypesQuery.data ?? []).map(toEdgeTypeDef)\n const builtInSlugs = new Set(BUILT_IN_EDGE_TYPES.map((t) => t.slug))\n const customDefs = apiDefs.filter((d) => !builtInSlugs.has(d.slug))\n return [...BUILT_IN_EDGE_TYPES, ...customDefs]\n }, [edgeTypesQuery.data])\n\n const flow = flowQuery.data\n const canvas = flow?.canvas as CanvasData | undefined\n\n return {\n data: canvas,\n nodeTypeDefs,\n edgeTypeDefs,\n flow,\n isLoading:\n flowQuery.isLoading ||\n nodeTypesQuery.isLoading ||\n edgeTypesQuery.isLoading,\n error:\n (flowQuery.error as Error | null) ??\n (nodeTypesQuery.error as Error | null) ??\n (edgeTypesQuery.error as Error | null),\n }\n}\n","import type { PublicCollection, ApiQueryOptions } from '../client/types'\n\nexport function collectionKeys<T extends PublicCollection>(collection: T) {\n return {\n all: [collection] as const,\n lists: () => [collection, 'list'] as const,\n list: (options?: ApiQueryOptions) => [collection, 'list', options] as const,\n details: () => [collection, 'detail'] as const,\n detail: (id: string, options?: ApiQueryOptions) =>\n [collection, 'detail', id, options] as const,\n infinites: () => [collection, 'infinite'] as const,\n infinite: (options?: Omit<ApiQueryOptions, 'page'>) =>\n [collection, 'infinite', options] as const,\n }\n}\n\nexport const customerKeys = {\n all: ['customer'] as const,\n me: () => ['customer', 'me'] as const,\n}\n","import { useMemo } from 'react'\nimport type { CanvasData, FlowNode, NodeTypeDef, EdgeTypeDef } from './types'\nimport type { Edge } from '@xyflow/react'\nimport { BUILT_IN_NODE_TYPES } from './built-in-node-types'\nimport { BUILT_IN_EDGE_TYPES } from './built-in-edge-types'\n\n// ── Options & Result ──\n\nexport interface UseFlowDataOptions {\n /** Canvas data from Flow document's `canvas` field */\n data: CanvasData | undefined\n /** Node type definitions (defaults to built-in types) */\n nodeTypeDefs?: NodeTypeDef[]\n /** Edge type definitions (defaults to built-in types) */\n edgeTypeDefs?: EdgeTypeDef[]\n}\n\nexport interface UseFlowDataResult {\n /** Nodes from canvas data */\n nodes: FlowNode[]\n /** Edges from canvas data (typed for @xyflow/react) */\n edges: Edge[]\n /** Map of node type slug to definition */\n nodeTypeDefsMap: Map<string, NodeTypeDef>\n /** Map of edge type slug to definition */\n edgeTypeDefsMap: Map<string, EdgeTypeDef>\n}\n\n/**\n * Pure data transformation hook — extracts nodes, edges, and type definition\n * maps from canvas data without any rendering. Useful for headless usage\n * (custom layouts, analytics, server-side processing).\n */\nexport function useFlowData(options: UseFlowDataOptions): UseFlowDataResult {\n const { data, nodeTypeDefs: inputNodeDefs, edgeTypeDefs: inputEdgeDefs } =\n options\n\n const nodeTypeDefsMap = useMemo(() => {\n const allDefs = inputNodeDefs ?? BUILT_IN_NODE_TYPES\n return new Map(allDefs.map((d) => [d.slug, d]))\n }, [inputNodeDefs])\n\n const edgeTypeDefsMap = useMemo(() => {\n const allDefs = inputEdgeDefs ?? BUILT_IN_EDGE_TYPES\n return new Map(allDefs.map((d) => [d.slug, d]))\n }, [inputEdgeDefs])\n\n const nodes = useMemo(() => data?.nodes ?? [], [data?.nodes])\n const edges = useMemo(() => (data?.edges ?? []) as unknown as Edge[], [data?.edges])\n\n return {\n nodes,\n edges,\n nodeTypeDefsMap,\n edgeTypeDefsMap,\n }\n}\n","import type { FlowNode, FlowEdge, FlowBounds, CanvasData } from './types'\n\n// ── Shared helpers ──\n\nfunction getNodeSize(node: FlowNode): { width: number; height: number } {\n return {\n width:\n (node.style?.width as number) ??\n node.measured?.width ??\n node.width ??\n 200,\n height:\n (node.style?.height as number) ??\n node.measured?.height ??\n node.height ??\n 200,\n }\n}\n\nfunction getAbsolutePosition(\n node: FlowNode,\n nodeMap: Map<string, FlowNode>,\n): { x: number; y: number } {\n let x = node.position.x\n let y = node.position.y\n let current = node\n const visited = new Set<string>([node.id])\n while (current.parentId) {\n const parentId = current.parentId\n if (visited.has(parentId)) break\n const parent = nodeMap.get(parentId)\n if (!parent) break\n visited.add(parent.id)\n x += parent.position.x\n y += parent.position.y\n current = parent\n }\n return { x, y }\n}\n\n/** Collect a node and all its descendants (BFS with index pointer to avoid O(Q²) shift). */\nfunction collectDescendants(\n nodes: FlowNode[],\n rootId: string,\n): Set<string> {\n const result = new Set<string>([rootId])\n const queue = [rootId]\n let i = 0\n while (i < queue.length) {\n const current = queue[i++]\n for (const n of nodes) {\n if (n.parentId === current && !result.has(n.id)) {\n result.add(n.id)\n queue.push(n.id)\n }\n }\n }\n return result\n}\n\n// ── Public utilities ──\n\n/**\n * Calculate bounding box for given node IDs.\n * Pure function — usable in SSR, server components, or outside React.\n */\nexport function getNodeBounds(\n nodes: FlowNode[],\n nodeIds: string[],\n): FlowBounds | undefined {\n const idSet = new Set(nodeIds)\n const targetNodes = nodes.filter((n) => idSet.has(n.id))\n if (targetNodes.length === 0) return undefined\n\n const nodeMap = new Map(nodes.map((n) => [n.id, n]))\n\n let minX = Infinity\n let minY = Infinity\n let maxX = -Infinity\n let maxY = -Infinity\n\n for (const node of targetNodes) {\n const abs = getAbsolutePosition(node, nodeMap)\n const { width: w, height: h } = getNodeSize(node)\n minX = Math.min(minX, abs.x)\n minY = Math.min(minY, abs.y)\n maxX = Math.max(maxX, abs.x + w)\n maxY = Math.max(maxY, abs.y + h)\n }\n\n return { x: minX, y: minY, width: maxX - minX, height: maxY - minY }\n}\n\n/**\n * Get all frame nodes with their bounds.\n * Sorted by position (top-left to bottom-right).\n */\nexport function getFrames(\n nodes: FlowNode[],\n): Array<{ id: string; label: string; bounds: FlowBounds }> {\n const frames = nodes.filter((n) => n.type === 'frame')\n if (frames.length === 0) return []\n\n const nodeMap = new Map(nodes.map((n) => [n.id, n]))\n\n return frames\n .map((f) => {\n const data = f.data as { label?: string }\n const abs = getAbsolutePosition(f, nodeMap)\n const { width: w, height: h } = getNodeSize(f)\n return {\n id: f.id,\n label: data.label ?? '',\n bounds: { x: abs.x, y: abs.y, width: w, height: h },\n }\n })\n .sort((a, b) => a.bounds.y - b.bounds.y || a.bounds.x - b.bounds.x)\n}\n\n/** Result of getFrameData — contains filtered canvas + dual bounds. */\nexport interface FrameData {\n /** Canvas data containing only the frame's descendants (nodes have draggable: false). */\n data: CanvasData\n /** Bounding box of child content nodes — use for initial viewport fit (centering). */\n fitBounds: FlowBounds\n /** Bounding box of the frame itself — use for panning/zoom restriction (clamp). */\n clampBounds: FlowBounds\n /** @deprecated Use fitBounds instead. Alias for clampBounds for backward compatibility. */\n bounds: FlowBounds\n}\n\n/**\n * Extract a frame's descendants and related edges from canvas data.\n * Recursively collects all nested children (supports nested frames).\n * Returns undefined if frameId is not found or is not a frame node.\n *\n * Child nodes are marked `draggable: false` to prevent interfering with canvas panning.\n * The frame node itself is included (use `frameRenderer={() => null}` to hide it).\n *\n * Returns dual bounds:\n * - `fitBounds`: child content bounding box (for centering the viewport)\n * - `clampBounds`: frame area bounding box (for panning restriction)\n */\nexport function getFrameData(\n data: CanvasData,\n frameId: string,\n): FrameData | undefined {\n const frame = data.nodes.find((n) => n.id === frameId)\n if (!frame || frame.type !== 'frame') return undefined\n\n // Recursively collect frame + all descendants\n const descendantIds = collectDescendants(data.nodes, frameId)\n const childNodes = data.nodes\n .filter((n) => descendantIds.has(n.id))\n .map((n) => ({ ...n, draggable: false }))\n\n // Keep only edges where both source and target are within the frame\n const childEdges = data.edges.filter(\n (e: FlowEdge) => descendantIds.has(e.source) && descendantIds.has(e.target),\n )\n\n // clampBounds: frame's own bounding box (for panning restriction)\n const frameBounds = getNodeBounds(data.nodes, [frameId])\n const { width: w, height: h } = getNodeSize(frame)\n const clampBounds: FlowBounds = frameBounds ?? {\n x: frame.position.x,\n y: frame.position.y,\n width: w,\n height: h,\n }\n\n // fitBounds: child content bounding box (for centering)\n const contentNodeIds = childNodes\n .filter((n) => n.id !== frameId)\n .map((n) => n.id)\n const contentBounds = contentNodeIds.length > 0\n ? getNodeBounds(data.nodes, contentNodeIds)\n : undefined\n const fitBounds = contentBounds ?? clampBounds\n\n return {\n data: {\n nodes: childNodes,\n edges: childEdges,\n viewport: data.viewport,\n },\n fitBounds,\n clampBounds,\n bounds: clampBounds,\n }\n}\n","'use client'\n\nimport React from 'react'\nimport { transform } from 'sucrase'\n\nexport interface CodeComponentProps {\n fields: Record<string, unknown>\n label: string\n color: string\n nodeTypeSlug: string\n width: number\n height: number\n}\n\nconst MAX_CACHE_SIZE = 100\nconst componentCache = new Map<string, React.FC<CodeComponentProps>>()\n\nfunction hashCode(str: string): string {\n let hash = 0\n for (let i = 0; i < str.length; i++) {\n const char = str.charCodeAt(i)\n hash = ((hash << 5) - hash + char) | 0\n }\n return hash.toString(36)\n}\n\nconst BLOCKED_PATTERNS = [\n /\\bdocument\\s*\\./,\n /\\bwindow\\s*\\./,\n /\\bwindow\\s*\\[/,\n /\\bglobalThis\\s*\\./,\n /\\bfetch\\s*\\(/,\n /\\bXMLHttpRequest/,\n /\\beval\\s*\\(/,\n /\\bFunction\\s*\\(/,\n /\\bimport\\s*\\(/,\n /\\blocalStorage/,\n /\\bsessionStorage/,\n /\\bcookie/,\n /\\bpostMessage\\s*\\(/,\n /\\blocation\\s*[.=]/,\n /\\bnavigator\\s*\\./,\n /\\bsetTimeout\\s*\\(/,\n /\\bsetInterval\\s*\\(/,\n /\\bsetImmediate\\s*\\(/,\n /\\brequire\\s*\\(/,\n]\n\nfunction validateTemplateCode(code: string): boolean {\n return !BLOCKED_PATTERNS.some((pattern) => pattern.test(code))\n}\n\nexport function compileTemplate(\n code: string,\n slug: string,\n): React.FC<CodeComponentProps> | null {\n const cacheKey = `${slug}:${hashCode(code)}`\n\n if (componentCache.has(cacheKey)) {\n const cached = componentCache.get(cacheKey)!\n componentCache.delete(cacheKey)\n componentCache.set(cacheKey, cached)\n return cached\n }\n\n if (!validateTemplateCode(code)) {\n console.warn(`[flow] Template \"${slug}\" contains blocked patterns`)\n return null\n }\n\n try {\n const { code: jsCode } = transform(code, {\n transforms: ['typescript', 'jsx', 'imports'],\n jsxRuntime: 'classic',\n jsxPragma: 'React.createElement',\n jsxFragmentPragma: 'React.Fragment',\n })\n\n // Shadow dangerous globals to neutralize blocklist bypasses\n const factory = new Function(\n 'React',\n `\n var window = undefined;\n var document = undefined;\n var globalThis = undefined;\n var setTimeout = undefined;\n var setInterval = undefined;\n var setImmediate = undefined;\n var fetch = undefined;\n var XMLHttpRequest = undefined;\n var navigator = undefined;\n var location = undefined;\n var exports = {};\n var module = { exports: exports };\n ${jsCode}\n return module.exports.default || module.exports;\n `,\n )\n\n const Component = factory(React)\n if (typeof Component !== 'function') return null\n\n if (componentCache.size >= MAX_CACHE_SIZE) {\n const oldestKey = componentCache.keys().next().value\n if (oldestKey) componentCache.delete(oldestKey)\n }\n\n componentCache.set(cacheKey, Component)\n return Component\n } catch (e) {\n console.warn(`[flow] Failed to compile template for \"${slug}\":`, e)\n return null\n }\n}\n\nexport function clearTemplateCache(): void {\n componentCache.clear()\n}\n"],"mappings":"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","names":["import_react","_a","import_react","import_react","React","React","_a"]}
@@ -101,6 +101,14 @@ interface DynamicNodeSlotProps {
101
101
  label: string;
102
102
  fields: Record<string, unknown>;
103
103
  nodeTypeDef?: NodeTypeDef;
104
+ /** Whether this node is currently selected */
105
+ selected?: boolean;
106
+ /** Measured node width (undefined before first measurement) */
107
+ width?: number;
108
+ /** Measured node height (undefined before first measurement) */
109
+ height?: number;
110
+ /** The default rendering (template or field-based). Allows custom renderers to wrap/extend instead of replacing entirely. */
111
+ defaultRender?: React.ReactElement;
104
112
  }
105
113
  interface FrameNodeData {
106
114
  label: string;
@@ -116,6 +124,8 @@ interface FrameNodeSlotProps {
116
124
  padding?: number;
117
125
  borderStyle?: 'dashed' | 'solid' | 'none';
118
126
  opacity?: number;
127
+ width?: number;
128
+ height?: number;
119
129
  children?: React.ReactNode;
120
130
  }
121
131
  interface EdgeSlotProps {
@@ -304,8 +314,8 @@ interface FlowRendererProps {
304
314
  minimapNodeColor?: (node: FlowNode) => string;
305
315
  /** S4: Additional children rendered inside ReactFlow */
306
316
  children?: React.ReactNode;
307
- /** S5: Global override for all dynamic nodes. Should be a stable reference (memoize or define outside render). */
308
- renderNode?: (props: DynamicNodeSlotProps, defaultRender: React.ReactElement) => React.ReactElement | null;
317
+ /** S5: Global override for all dynamic nodes. `content` is the resolved rendering (custom renderer output or default). `props.defaultRender` contains the original template/field-based rendering. */
318
+ renderNode?: (props: DynamicNodeSlotProps, content: React.ReactElement) => React.ReactElement | null;
309
319
  /** S6: Called when viewport changes (pan/zoom) */
310
320
  onViewportChange?: (viewport: FlowViewport) => void;
311
321
  /** S6: Default viewport (used when fitView is false) */
@@ -324,7 +334,11 @@ interface FlowRendererProps {
324
334
  responsiveFit?: boolean;
325
335
  /** Override translateExtent directly. When set, overrides the automatic bounds-based panning restriction. */
326
336
  translateExtent?: [[number, number], [number, number]];
337
+ /** Minimum zoom level. When clampBounds is set, automatically enforced as cover zoom (user cannot zoom out beyond the frame). */
338
+ minZoom?: number;
339
+ /** Maximum zoom level */
340
+ maxZoom?: number;
327
341
  }
328
- declare function FlowRenderer({ data, className, style, nodeRenderers, nodeTypeDefs, edgeTypeDefs, background, interactive, fitView, onNodeClick, onNodeDoubleClick, onNodeContextMenu, onNodeMouseEnter, onNodeMouseLeave, onEdgeClick, frameRenderer, edgeRenderers, nodeWrapper, controls, minimap, minimapNodeColor, children, renderNode, onViewportChange, defaultViewport: defaultViewportProp, bounds, clampBounds, focusPadding, focusAnimation, focusMode, responsiveFit, translateExtent: translateExtentProp, }: FlowRendererProps): React.JSX.Element | null;
342
+ declare function FlowRenderer({ data, className, style, nodeRenderers, nodeTypeDefs, edgeTypeDefs, background, interactive, fitView, onNodeClick, onNodeDoubleClick, onNodeContextMenu, onNodeMouseEnter, onNodeMouseLeave, onEdgeClick, frameRenderer, edgeRenderers, nodeWrapper, controls, minimap, minimapNodeColor, children, renderNode, onViewportChange, defaultViewport: defaultViewportProp, bounds, clampBounds, focusPadding, focusAnimation, focusMode, responsiveFit, translateExtent: translateExtentProp, minZoom: minZoomProp, maxZoom: maxZoomProp, }: FlowRendererProps): React.JSX.Element | null;
329
343
 
330
344
  export { BUILT_IN_EDGE_TYPES, BUILT_IN_NODE_TYPES, type CanvasData, type CodeComponentProps, type DynamicNodeData, type DynamicNodeSlotProps, type EdgeSlotProps, type EdgeTypeDef, type FlowBounds, type FlowEdge, type FlowNode, type FlowNodeData, type FlowNodePosition, FlowRenderer, type FlowRendererProps, type FlowViewport, type FrameData, type FrameNodeData, type FrameNodeSlotProps, type NodeTypeDef, type NodeTypeFieldDef, type NodeWrapperSlotProps, type SDKClient, type UseFlowDataOptions, type UseFlowDataResult, type UseFlowOptions, type UseFlowResult, clearTemplateCache, compileTemplate, getFrameData, getFrames, getNodeBounds, isDynamicNode, isFrameNode, useFlow, useFlowData };
package/dist/ui/flow.d.ts CHANGED
@@ -101,6 +101,14 @@ interface DynamicNodeSlotProps {
101
101
  label: string;
102
102
  fields: Record<string, unknown>;
103
103
  nodeTypeDef?: NodeTypeDef;
104
+ /** Whether this node is currently selected */
105
+ selected?: boolean;
106
+ /** Measured node width (undefined before first measurement) */
107
+ width?: number;
108
+ /** Measured node height (undefined before first measurement) */
109
+ height?: number;
110
+ /** The default rendering (template or field-based). Allows custom renderers to wrap/extend instead of replacing entirely. */
111
+ defaultRender?: React.ReactElement;
104
112
  }
105
113
  interface FrameNodeData {
106
114
  label: string;
@@ -116,6 +124,8 @@ interface FrameNodeSlotProps {
116
124
  padding?: number;
117
125
  borderStyle?: 'dashed' | 'solid' | 'none';
118
126
  opacity?: number;
127
+ width?: number;
128
+ height?: number;
119
129
  children?: React.ReactNode;
120
130
  }
121
131
  interface EdgeSlotProps {
@@ -304,8 +314,8 @@ interface FlowRendererProps {
304
314
  minimapNodeColor?: (node: FlowNode) => string;
305
315
  /** S4: Additional children rendered inside ReactFlow */
306
316
  children?: React.ReactNode;
307
- /** S5: Global override for all dynamic nodes. Should be a stable reference (memoize or define outside render). */
308
- renderNode?: (props: DynamicNodeSlotProps, defaultRender: React.ReactElement) => React.ReactElement | null;
317
+ /** S5: Global override for all dynamic nodes. `content` is the resolved rendering (custom renderer output or default). `props.defaultRender` contains the original template/field-based rendering. */
318
+ renderNode?: (props: DynamicNodeSlotProps, content: React.ReactElement) => React.ReactElement | null;
309
319
  /** S6: Called when viewport changes (pan/zoom) */
310
320
  onViewportChange?: (viewport: FlowViewport) => void;
311
321
  /** S6: Default viewport (used when fitView is false) */
@@ -324,7 +334,11 @@ interface FlowRendererProps {
324
334
  responsiveFit?: boolean;
325
335
  /** Override translateExtent directly. When set, overrides the automatic bounds-based panning restriction. */
326
336
  translateExtent?: [[number, number], [number, number]];
337
+ /** Minimum zoom level. When clampBounds is set, automatically enforced as cover zoom (user cannot zoom out beyond the frame). */
338
+ minZoom?: number;
339
+ /** Maximum zoom level */
340
+ maxZoom?: number;
327
341
  }
328
- declare function FlowRenderer({ data, className, style, nodeRenderers, nodeTypeDefs, edgeTypeDefs, background, interactive, fitView, onNodeClick, onNodeDoubleClick, onNodeContextMenu, onNodeMouseEnter, onNodeMouseLeave, onEdgeClick, frameRenderer, edgeRenderers, nodeWrapper, controls, minimap, minimapNodeColor, children, renderNode, onViewportChange, defaultViewport: defaultViewportProp, bounds, clampBounds, focusPadding, focusAnimation, focusMode, responsiveFit, translateExtent: translateExtentProp, }: FlowRendererProps): React.JSX.Element | null;
342
+ declare function FlowRenderer({ data, className, style, nodeRenderers, nodeTypeDefs, edgeTypeDefs, background, interactive, fitView, onNodeClick, onNodeDoubleClick, onNodeContextMenu, onNodeMouseEnter, onNodeMouseLeave, onEdgeClick, frameRenderer, edgeRenderers, nodeWrapper, controls, minimap, minimapNodeColor, children, renderNode, onViewportChange, defaultViewport: defaultViewportProp, bounds, clampBounds, focusPadding, focusAnimation, focusMode, responsiveFit, translateExtent: translateExtentProp, minZoom: minZoomProp, maxZoom: maxZoomProp, }: FlowRendererProps): React.JSX.Element | null;
329
343
 
330
344
  export { BUILT_IN_EDGE_TYPES, BUILT_IN_NODE_TYPES, type CanvasData, type CodeComponentProps, type DynamicNodeData, type DynamicNodeSlotProps, type EdgeSlotProps, type EdgeTypeDef, type FlowBounds, type FlowEdge, type FlowNode, type FlowNodeData, type FlowNodePosition, FlowRenderer, type FlowRendererProps, type FlowViewport, type FrameData, type FrameNodeData, type FrameNodeSlotProps, type NodeTypeDef, type NodeTypeFieldDef, type NodeWrapperSlotProps, type SDKClient, type UseFlowDataOptions, type UseFlowDataResult, type UseFlowOptions, type UseFlowResult, clearTemplateCache, compileTemplate, getFrameData, getFrames, getNodeBounds, isDynamicNode, isFrameNode, useFlow, useFlowData };
package/dist/ui/flow.js CHANGED
@@ -48,7 +48,8 @@ import {
48
48
  Controls,
49
49
  MiniMap,
50
50
  MarkerType,
51
- useReactFlow
51
+ useReactFlow,
52
+ useStoreApi
52
53
  } from "@xyflow/react";
53
54
 
54
55
  // src/ui/Flow/types.ts
@@ -539,7 +540,8 @@ function EnhancedDynamicNode({
539
540
  return /* @__PURE__ */ React2.createElement(
540
541
  "div",
541
542
  {
542
- className: `flow-node flow-node--${typeDef.slug}${typeDef.transparentBackground ? " flow-node--transparent-bg" : ""}`
543
+ className: `flow-node flow-node--${typeDef.slug}${typeDef.transparentBackground ? " flow-node--transparent-bg" : ""}`,
544
+ style: { width: "100%", height: "100%" }
543
545
  },
544
546
  /* @__PURE__ */ React2.createElement(TemplateErrorBoundary, { resetKey: typeDef.template }, /* @__PURE__ */ React2.createElement(
545
547
  Component,
@@ -575,7 +577,7 @@ function EnhancedDynamicNode({
575
577
  function DefaultFrameNode({ data }) {
576
578
  var _a, _b, _c, _d;
577
579
  const d = data;
578
- const baseColor = (_a = d.color) != null ? _a : "rgba(128,128,128,0.15)";
580
+ const baseColor = (_a = d.color) != null ? _a : "rgb(128,128,128)";
579
581
  const padding = (_b = d.padding) != null ? _b : 20;
580
582
  const borderStyle = (_c = d.borderStyle) != null ? _c : "dashed";
581
583
  const opacity = (_d = d.opacity) != null ? _d : 0.15;
@@ -615,39 +617,28 @@ function createNodeTypes(nodeRenderers, nodeTypeDefsMap, frameRenderer, nodeWrap
615
617
  const d = props.data;
616
618
  const typeDef = nodeTypeDefsMap == null ? void 0 : nodeTypeDefsMap.get(d.nodeTypeSlug);
617
619
  const CustomRenderer = nodeRenderers == null ? void 0 : nodeRenderers[d.nodeTypeSlug];
618
- let content;
619
- if (CustomRenderer) {
620
- content = /* @__PURE__ */ React2.createElement(
621
- CustomRenderer,
622
- {
623
- id: props.id,
624
- nodeTypeSlug: d.nodeTypeSlug,
625
- label: d.label,
626
- fields: d.fields,
627
- nodeTypeDef: typeDef
628
- }
629
- );
630
- } else if (typeDef) {
631
- content = /* @__PURE__ */ React2.createElement(
632
- EnhancedDynamicNode,
633
- {
634
- data: d,
635
- typeDef,
636
- width: props.width,
637
- height: props.height
638
- }
639
- );
640
- } else {
641
- content = /* @__PURE__ */ React2.createElement(DefaultDynamicNode, __spreadValues({}, props));
642
- }
620
+ const defaultRender = typeDef ? /* @__PURE__ */ React2.createElement(
621
+ EnhancedDynamicNode,
622
+ {
623
+ data: d,
624
+ typeDef,
625
+ width: props.width,
626
+ height: props.height
627
+ }
628
+ ) : /* @__PURE__ */ React2.createElement(DefaultDynamicNode, __spreadValues({}, props));
629
+ const slotProps = {
630
+ id: props.id,
631
+ nodeTypeSlug: d.nodeTypeSlug,
632
+ label: d.label,
633
+ fields: d.fields,
634
+ nodeTypeDef: typeDef,
635
+ selected: props.selected,
636
+ width: props.width,
637
+ height: props.height,
638
+ defaultRender
639
+ };
640
+ let content = CustomRenderer ? /* @__PURE__ */ React2.createElement(CustomRenderer, __spreadValues({}, slotProps)) : defaultRender;
643
641
  if (renderNode) {
644
- const slotProps = {
645
- id: props.id,
646
- nodeTypeSlug: d.nodeTypeSlug,
647
- label: d.label,
648
- fields: d.fields,
649
- nodeTypeDef: typeDef
650
- };
651
642
  const result = renderNode(slotProps, content);
652
643
  if (result !== null) content = result;
653
644
  }
@@ -678,7 +669,9 @@ function createNodeTypes(nodeRenderers, nodeTypeDefsMap, frameRenderer, nodeWrap
678
669
  color: d.color,
679
670
  padding: d.padding,
680
671
  borderStyle: d.borderStyle,
681
- opacity: d.opacity
672
+ opacity: d.opacity,
673
+ width: props.width,
674
+ height: props.height
682
675
  }
683
676
  );
684
677
  }) : DefaultFrameNode;
@@ -729,9 +722,12 @@ function FocusHandler({
729
722
  animation,
730
723
  mode,
731
724
  responsive,
732
- extent
725
+ extent,
726
+ clampBounds,
727
+ minZoomProp
733
728
  }) {
734
729
  const { setViewport } = useReactFlow();
730
+ const store = useStoreApi();
735
731
  const containerRef = React2.useRef(null);
736
732
  const boundsKey = `${bounds.x},${bounds.y},${bounds.width},${bounds.height}`;
737
733
  const boundsRef = React2.useRef(bounds);
@@ -763,17 +759,27 @@ function FocusHandler({
763
759
  if (isResizeOnly && !responsive) return;
764
760
  const duration = isInitial || isBoundsChange ? animation === true ? 300 : typeof animation === "number" ? animation : 0 : 0;
765
761
  const b = boundsRef.current;
766
- const padX = padding * b.width;
767
- const padY = padding * b.height;
768
- const bw = b.width + padX * 2;
769
- const bh = b.height + padY * 2;
762
+ const zoomTarget = mode === "cover" && clampBounds ? clampBounds : b;
763
+ const padX = padding * zoomTarget.width;
764
+ const padY = padding * zoomTarget.height;
765
+ const bw = zoomTarget.width + padX * 2;
766
+ const bh = zoomTarget.height + padY * 2;
770
767
  if (bw === 0 || bh === 0) return;
771
768
  const zoomFn = mode === "cover" ? Math.max : Math.min;
772
769
  const zoom = zoomFn(containerSize.w / bw, containerSize.h / bh);
773
- const cx = b.x + b.width / 2;
774
- const cy = b.y + b.height / 2;
770
+ const cx = zoomTarget.x + zoomTarget.width / 2;
771
+ const cy = zoomTarget.y + zoomTarget.height / 2;
775
772
  const x = containerSize.w / 2 - cx * zoom;
776
773
  const y = containerSize.h / 2 - cy * zoom;
774
+ if (clampBounds) {
775
+ const coverZoom = Math.max(
776
+ containerSize.w / clampBounds.width,
777
+ containerSize.h / clampBounds.height
778
+ );
779
+ store.getState().setMinZoom(Math.max(coverZoom, minZoomProp != null ? minZoomProp : 0));
780
+ } else {
781
+ store.getState().setMinZoom(minZoomProp != null ? minZoomProp : 0.5);
782
+ }
777
783
  let vp = { x, y, zoom };
778
784
  if (extent) {
779
785
  vp = clampViewport(vp, containerSize.w, containerSize.h, extent);
@@ -788,7 +794,10 @@ function FocusHandler({
788
794
  containerSize.w,
789
795
  containerSize.h,
790
796
  extent,
791
- setViewport
797
+ setViewport,
798
+ clampBounds,
799
+ minZoomProp,
800
+ store
792
801
  ]);
793
802
  return /* @__PURE__ */ React2.createElement(
794
803
  "div",
@@ -874,7 +883,9 @@ function FlowRenderer({
874
883
  focusAnimation,
875
884
  focusMode = "contain",
876
885
  responsiveFit,
877
- translateExtent: translateExtentProp
886
+ translateExtent: translateExtentProp,
887
+ minZoom: minZoomProp,
888
+ maxZoom: maxZoomProp
878
889
  }) {
879
890
  var _a;
880
891
  const nodeTypeDefsMap = React2.useMemo(() => {
@@ -965,6 +976,8 @@ function FlowRenderer({
965
976
  zoomOnScroll: interactive,
966
977
  zoomOnPinch: interactive,
967
978
  zoomOnDoubleClick: false,
979
+ minZoom: minZoomProp,
980
+ maxZoom: maxZoomProp,
968
981
  proOptions: { hideAttribution: true }
969
982
  },
970
983
  mergedCSS && /* @__PURE__ */ React2.createElement("style", { dangerouslySetInnerHTML: { __html: mergedCSS } }),
@@ -984,7 +997,9 @@ function FlowRenderer({
984
997
  animation: focusAnimation != null ? focusAnimation : true,
985
998
  mode: focusMode,
986
999
  responsive: responsiveFit != null ? responsiveFit : true,
987
- extent: translateExtent
1000
+ extent: translateExtent,
1001
+ clampBounds,
1002
+ minZoomProp
988
1003
  }
989
1004
  ),
990
1005
  children
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/ui/Flow/index.tsx","../../src/ui/Flow/types.ts","../../src/ui/Flow/built-in-node-types.ts","../../src/ui/Flow/built-in-edge-types.ts","../../src/ui/Flow/useFlow.ts","../../src/core/query/query-keys.ts","../../src/ui/Flow/useFlowData.ts","../../src/ui/Flow/utils.ts","../../src/ui/Flow/template-compiler.ts"],"sourcesContent":["'use client'\n\nimport React from 'react'\nimport {\n ReactFlow,\n ReactFlowProvider,\n Background,\n Controls,\n MiniMap,\n MarkerType,\n useReactFlow,\n type NodeTypes,\n type NodeProps,\n type Edge,\n} from '@xyflow/react'\nimport type {\n CanvasData,\n DynamicNodeData,\n DynamicNodeSlotProps,\n EdgeSlotProps,\n EdgeTypeDef,\n FlowBounds,\n FlowEdge,\n FlowNode,\n FlowViewport,\n FrameNodeData,\n FrameNodeSlotProps,\n NodeTypeDef,\n NodeTypeFieldDef,\n NodeWrapperSlotProps,\n} from './types'\n\nexport type {\n CanvasData,\n DynamicNodeSlotProps,\n FlowNode,\n FlowEdge,\n FlowViewport,\n FlowNodePosition,\n FlowNodeData,\n DynamicNodeData,\n FrameNodeData,\n NodeTypeDef,\n NodeTypeFieldDef,\n EdgeTypeDef,\n FrameNodeSlotProps,\n EdgeSlotProps,\n NodeWrapperSlotProps,\n FlowBounds,\n} from './types'\nexport { isDynamicNode, isFrameNode } from './types'\nexport { BUILT_IN_NODE_TYPES } from './built-in-node-types'\nexport { BUILT_IN_EDGE_TYPES } from './built-in-edge-types'\nexport { useFlow } from './useFlow'\nexport type { SDKClient, UseFlowOptions, UseFlowResult } from './useFlow'\nexport { useFlowData } from './useFlowData'\nexport type { UseFlowDataOptions, UseFlowDataResult } from './useFlowData'\nexport { getNodeBounds, getFrames, getFrameData } from './utils'\nexport type { FrameData } from './utils'\nexport { compileTemplate, clearTemplateCache } from './template-compiler'\nexport type { CodeComponentProps } from './template-compiler'\n\nimport { compileTemplate } from './template-compiler'\n\n// ── Helpers ──\n\nfunction sanitizeUrl(url: string | undefined): string | undefined {\n if (!url) return url\n try {\n const parsed = new URL(url)\n if (parsed.protocol === 'http:' || parsed.protocol === 'https:') return url\n return undefined\n } catch {\n return undefined\n }\n}\n\nfunction toMarkerType(value: string): MarkerType | undefined {\n if (value === 'arrow') return MarkerType.Arrow\n if (value === 'arrowclosed') return MarkerType.ArrowClosed\n return undefined\n}\n\n// ── Field renderer (type-aware, matching console style) ──\n\nfunction renderFieldValue(\n key: string,\n val: unknown,\n fieldDef?: NodeTypeFieldDef,\n): React.ReactNode {\n if (val == null || val === '') return null\n\n const fieldType = fieldDef?.fieldType\n\n // Image field — image only, no decoration\n if (\n fieldType === 'image' ||\n (typeof val === 'object' && val !== null && 'url' in val)\n ) {\n const imgUrl =\n typeof val === 'string' ? val : (val as { url?: string })?.url\n const safeUrl = sanitizeUrl(imgUrl)\n if (!safeUrl) return null\n return (\n <img\n key={key}\n src={safeUrl}\n alt=\"\"\n draggable={false}\n style={{ flex: 1, minHeight: 0, width: '100%', objectFit: 'contain' }}\n />\n )\n }\n\n // All other fields — text only\n return (\n <div\n key={key}\n style={{\n fontSize: 11,\n whiteSpace: 'pre-wrap',\n wordBreak: 'break-word',\n overflow: 'hidden',\n flexShrink: 0,\n }}\n >\n {String(val)}\n </div>\n )\n}\n\n// ── Default dynamic node renderer (no typeDef) ──\n\nfunction DefaultDynamicNode({ data }: NodeProps) {\n const d = data as unknown as DynamicNodeData\n return (\n <div\n style={{\n width: '100%',\n height: '100%',\n display: 'flex',\n flexDirection: 'column',\n }}\n >\n {d.fields &&\n Object.entries(d.fields)\n .filter(([, v]) => v != null && v !== '')\n .map(([key, val]) => renderFieldValue(key, val))}\n </div>\n )\n}\n\n// ── Template error boundary ──\n\nclass TemplateErrorBoundary extends React.Component<\n { resetKey?: string; children: React.ReactNode },\n { error: Error | null }\n> {\n state: { error: Error | null } = { error: null }\n static getDerivedStateFromError(error: Error) {\n return { error }\n }\n componentDidUpdate(prevProps: { resetKey?: string }) {\n if (prevProps.resetKey !== this.props.resetKey && this.state.error) {\n this.setState({ error: null })\n }\n }\n render() {\n if (this.state.error) {\n return (\n <div style={{ padding: 8, fontSize: 11, color: '#ef4444' }}>\n <strong>Render error</strong>\n <pre style={{ fontSize: 10, whiteSpace: 'pre-wrap' }}>\n {this.state.error.message}\n </pre>\n </div>\n )\n }\n return this.props.children\n }\n}\n\n// ── Enhanced dynamic node renderer (with NodeTypeDef) ──\n\nfunction EnhancedDynamicNode({\n data,\n typeDef,\n width,\n height,\n}: {\n data: DynamicNodeData\n typeDef: NodeTypeDef\n width?: number\n height?: number\n}) {\n // Tier 2: Custom template rendering\n if (typeDef.template) {\n const Component = compileTemplate(typeDef.template, typeDef.slug)\n if (Component) {\n return (\n <div\n className={`flow-node flow-node--${typeDef.slug}${typeDef.transparentBackground ? ' flow-node--transparent-bg' : ''}`}\n >\n <TemplateErrorBoundary resetKey={typeDef.template}>\n <Component\n fields={data.fields}\n label={data.label}\n color={typeDef.color}\n nodeTypeSlug={typeDef.slug}\n width={width || typeDef.defaultSize.width}\n height={height || typeDef.defaultSize.height}\n />\n </TemplateErrorBoundary>\n </div>\n )\n }\n }\n\n // Tier 1: Default field rendering\n return (\n <div\n style={{\n width: '100%',\n height: '100%',\n display: 'flex',\n flexDirection: 'column',\n }}\n >\n {typeDef.fields.map((f) => {\n const val = data.fields[f.name]\n if (val == null || val === '') return null\n return renderFieldValue(f.name, val, f)\n })}\n </div>\n )\n}\n\n// ── Default frame node renderer ──\n\nfunction DefaultFrameNode({ data }: NodeProps) {\n const d = data as unknown as FrameNodeData\n const baseColor = d.color ?? 'rgba(128,128,128,0.15)'\n const padding = d.padding ?? 20\n const borderStyle = d.borderStyle ?? 'dashed'\n const opacity = d.opacity ?? 0.15\n\n // Apply opacity to rgba colors\n const bgColor = (() => {\n const m = baseColor.match(/rgba?\\((\\d+),\\s*(\\d+),\\s*(\\d+)/)\n if (m) return `rgba(${m[1]},${m[2]},${m[3]},${opacity})`\n return baseColor\n })()\n\n return (\n <div\n style={{\n backgroundColor: bgColor,\n padding,\n width: '100%',\n height: '100%',\n border:\n borderStyle === 'none'\n ? 'none'\n : `2px ${borderStyle} rgba(128,128,128,0.3)`,\n }}\n >\n <div\n style={{\n fontSize: 11,\n fontWeight: 600,\n color: 'rgba(128,128,128,0.6)',\n userSelect: 'none',\n }}\n >\n {d.label}\n </div>\n </div>\n )\n}\n\n// ── Node types builder ──\n\nfunction createNodeTypes(\n nodeRenderers?: Record<string, React.ComponentType<DynamicNodeSlotProps>>,\n nodeTypeDefsMap?: Map<string, NodeTypeDef>,\n frameRenderer?: React.ComponentType<FrameNodeSlotProps>,\n nodeWrapper?: React.ComponentType<NodeWrapperSlotProps>,\n renderNode?: (\n props: DynamicNodeSlotProps,\n defaultRender: React.ReactElement,\n ) => React.ReactElement | null,\n): NodeTypes {\n const types: NodeTypes = {} as NodeTypes\n\n // Dynamic node type\n types.dynamic = ((props: NodeProps) => {\n const d = props.data as unknown as DynamicNodeData\n const typeDef = nodeTypeDefsMap?.get(d.nodeTypeSlug)\n const CustomRenderer = nodeRenderers?.[d.nodeTypeSlug]\n\n let content: React.ReactElement\n if (CustomRenderer) {\n content = (\n <CustomRenderer\n id={props.id}\n nodeTypeSlug={d.nodeTypeSlug}\n label={d.label}\n fields={d.fields}\n nodeTypeDef={typeDef}\n />\n )\n } else if (typeDef) {\n content = (\n <EnhancedDynamicNode\n data={d}\n typeDef={typeDef}\n width={props.width}\n height={props.height}\n />\n )\n } else {\n content = <DefaultDynamicNode {...props} />\n }\n\n // S5: renderNode global callback\n if (renderNode) {\n const slotProps: DynamicNodeSlotProps = {\n id: props.id,\n nodeTypeSlug: d.nodeTypeSlug,\n label: d.label,\n fields: d.fields,\n nodeTypeDef: typeDef,\n }\n const result = renderNode(slotProps, content)\n if (result !== null) content = result\n }\n\n // S3: nodeWrapper\n if (nodeWrapper) {\n const Wrapper = nodeWrapper\n content = (\n <Wrapper\n id={props.id}\n nodeTypeSlug={d.nodeTypeSlug}\n label={d.label}\n selected={props.selected}\n nodeTypeDef={typeDef}\n >\n {content}\n </Wrapper>\n )\n }\n\n return content\n }) as NodeTypes[string]\n\n // S1: Frame node type — custom or default\n types.frame = frameRenderer\n ? (((props: NodeProps) => {\n const d = props.data as unknown as FrameNodeData\n const Renderer = frameRenderer\n return (\n <Renderer\n id={props.id}\n label={d.label}\n color={d.color}\n padding={d.padding}\n borderStyle={d.borderStyle}\n opacity={d.opacity}\n />\n )\n }) as NodeTypes[string])\n : (DefaultFrameNode as NodeTypes[string])\n\n return types\n}\n\n// S2: Edge types builder\n\nfunction createEdgeTypes(\n edgeRenderers?: Record<string, React.ComponentType<EdgeSlotProps>>,\n edgeTypeDefsMap?: Map<string, EdgeTypeDef>,\n): Record<string, React.ComponentType<EdgeSlotProps>> | undefined {\n if (!edgeRenderers || Object.keys(edgeRenderers).length === 0)\n return undefined\n const types: Record<string, React.ComponentType<EdgeSlotProps>> = {}\n for (const [slug, Renderer] of Object.entries(edgeRenderers)) {\n types[slug] = ((props: Record<string, unknown>) => {\n const def = edgeTypeDefsMap?.get(slug)\n return (\n <Renderer\n id={props.id as string}\n edgeTypeSlug={slug}\n source={props.source as string}\n target={props.target as string}\n label={props.label as string | undefined}\n fields={\n (props.data as Record<string, unknown> | undefined)?.fields as\n | Record<string, unknown>\n | undefined\n }\n edgeTypeDef={def}\n style={props.style as React.CSSProperties | undefined}\n />\n )\n }) as unknown as React.ComponentType<EdgeSlotProps>\n }\n return types\n}\n\n// S8: FocusHandler — must be inside ReactFlowProvider\n\n// Match d3-zoom's translateExtent clamping so the initial viewport\n// is identical to what the user sees after the first drag.\nfunction clampViewport(\n vp: { x: number; y: number; zoom: number },\n cw: number,\n ch: number,\n extent: [[number, number], [number, number]],\n): { x: number; y: number; zoom: number } {\n const left = -vp.x / vp.zoom\n const right = (cw - vp.x) / vp.zoom\n const top = -vp.y / vp.zoom\n const bottom = (ch - vp.y) / vp.zoom\n\n const dx0 = left - extent[0][0]\n const dx1 = right - extent[1][0]\n const dy0 = top - extent[0][1]\n const dy1 = bottom - extent[1][1]\n\n const cx =\n dx1 > dx0 ? (dx0 + dx1) / 2 : Math.min(0, dx0) || Math.max(0, dx1)\n const cy =\n dy1 > dy0 ? (dy0 + dy1) / 2 : Math.min(0, dy0) || Math.max(0, dy1)\n\n if (cx === 0 && cy === 0) return vp\n return { x: vp.x + cx * vp.zoom, y: vp.y + cy * vp.zoom, zoom: vp.zoom }\n}\n\nfunction FocusHandler({\n bounds,\n padding,\n animation,\n mode,\n responsive,\n extent,\n}: {\n bounds: FlowBounds\n padding: number\n animation: boolean | number\n mode: 'contain' | 'cover'\n responsive: boolean\n extent?: [[number, number], [number, number]]\n}) {\n const { setViewport } = useReactFlow()\n const containerRef = React.useRef<HTMLDivElement>(null)\n const boundsKey = `${bounds.x},${bounds.y},${bounds.width},${bounds.height}`\n const boundsRef = React.useRef(bounds)\n boundsRef.current = bounds\n const [containerSize, setContainerSize] = React.useState({ w: 0, h: 0 })\n const prevBoundsKeyRef = React.useRef<string | null>(null)\n const prevSizeRef = React.useRef({ w: 0, h: 0 })\n\n // Track container size via ResizeObserver\n React.useEffect(() => {\n const el = containerRef.current\n if (!el) return\n const observer = new ResizeObserver((entries) => {\n const entry = entries[0]\n if (!entry) return\n const { width, height } = entry.contentRect\n setContainerSize({ w: width, h: height })\n })\n observer.observe(el)\n return () => observer.disconnect()\n }, [])\n\n React.useEffect(() => {\n if (containerSize.w === 0 || containerSize.h === 0) return\n\n const prevKey = prevBoundsKeyRef.current\n const prevSize = prevSizeRef.current\n prevBoundsKeyRef.current = boundsKey\n prevSizeRef.current = { w: containerSize.w, h: containerSize.h }\n\n // Determine trigger: bounds change vs resize-only\n const isBoundsChange = prevKey !== boundsKey\n const isResizeOnly =\n !isBoundsChange &&\n (prevSize.w !== containerSize.w || prevSize.h !== containerSize.h)\n const isInitial = prevKey === null\n\n // Skip resize-triggered re-fit if responsiveFit is disabled\n if (isResizeOnly && !responsive) return\n\n // Animate on initial + bounds change; instant on resize\n const duration =\n isInitial || isBoundsChange\n ? animation === true\n ? 300\n : typeof animation === 'number'\n ? animation\n : 0\n : 0\n\n const b = boundsRef.current\n const padX = padding * b.width\n const padY = padding * b.height\n const bw = b.width + padX * 2\n const bh = b.height + padY * 2\n\n if (bw === 0 || bh === 0) return\n\n // contain: fit inside viewport, cover: fill viewport (may crop)\n const zoomFn = mode === 'cover' ? Math.max : Math.min\n const zoom = zoomFn(containerSize.w / bw, containerSize.h / bh)\n const cx = b.x + b.width / 2\n const cy = b.y + b.height / 2\n const x = containerSize.w / 2 - cx * zoom\n const y = containerSize.h / 2 - cy * zoom\n\n let vp = { x, y, zoom }\n if (extent) {\n vp = clampViewport(vp, containerSize.w, containerSize.h, extent)\n }\n setViewport(vp, { duration })\n }, [\n boundsKey,\n padding,\n animation,\n mode,\n responsive,\n containerSize.w,\n containerSize.h,\n extent,\n setViewport,\n ])\n\n // Measurement div — always rendered to track container size\n return (\n <div\n ref={containerRef}\n style={{\n position: 'absolute',\n inset: 0,\n pointerEvents: 'none',\n visibility: 'hidden',\n }}\n />\n )\n}\n\n// ── Edge style resolver ──\n\nconst EDGE_TYPE_MAP: Record<string, string> = {\n step: 'step',\n smoothstep: 'smoothstep',\n bezier: 'default',\n default: 'default',\n}\n\nfunction applyEdgeStyles(\n edges: FlowEdge[],\n edgeTypeDefsMap?: Map<string, EdgeTypeDef>,\n): Edge[] {\n if (!edgeTypeDefsMap?.size) return edges as unknown as Edge[]\n\n return edges.map((edge) => {\n const slug = edge.edgeTypeSlug\n if (!slug) return edge as unknown as Edge\n\n const def = edgeTypeDefsMap.get(slug)\n if (!def) return edge as unknown as Edge\n\n const styled: Edge = { ...(edge as unknown as Edge) }\n\n // Edge type (line style) — canvas value takes precedence\n if (!styled.type && def.lineStyle) {\n styled.type = EDGE_TYPE_MAP[def.lineStyle] ?? 'default'\n }\n\n // Visual style — canvas style merged with def as fallback\n styled.style = {\n ...(def.color ? { stroke: def.color } : undefined),\n ...(def.strokeWidth ? { strokeWidth: def.strokeWidth } : undefined),\n ...edge.style,\n }\n\n // Animation — canvas value takes precedence\n if (styled.animated == null && def.animated) styled.animated = true\n\n // Markers — canvas value takes precedence over def\n if (!styled.markerStart) {\n const startType = toMarkerType(def.markerStart)\n if (startType) {\n styled.markerStart = {\n type: startType,\n ...(def.color ? { color: def.color } : undefined),\n }\n }\n }\n if (!styled.markerEnd) {\n const endType = toMarkerType(def.markerEnd)\n if (endType) {\n styled.markerEnd = {\n type: endType,\n ...(def.color ? { color: def.color } : undefined),\n }\n }\n }\n\n return styled\n })\n}\n\n// ── FlowRenderer ──\n\n/**\n * Renders a Flow canvas in read-only mode.\n *\n * Requires `@xyflow/react` peer dependency and its CSS:\n * ```ts\n * import '@xyflow/react/dist/style.css'\n * ```\n */\nexport interface FlowRendererProps {\n /** Canvas data from Flow document's `canvas` field */\n data: CanvasData\n /** Container className */\n className?: string\n /** Container style */\n style?: React.CSSProperties\n /** Custom renderers by node type slug (e.g., `{ 'product-card': MyProductCard }`) */\n nodeRenderers?: Record<string, React.ComponentType<DynamicNodeSlotProps>>\n /** Node type definitions for enhanced rendering (field-type-aware display) */\n nodeTypeDefs?: NodeTypeDef[]\n /** Edge type definitions for styled edges (color, stroke, markers, animation) */\n edgeTypeDefs?: EdgeTypeDef[]\n /** Show background pattern (default: false) */\n background?: boolean\n /** Allow user interaction - pan, zoom (default: false for read-only display) */\n interactive?: boolean\n /** Fit view on mount (default: true) */\n fitView?: boolean\n /** Called when a node is clicked */\n onNodeClick?: (event: React.MouseEvent, node: FlowNode) => void\n /** Called when a node is double-clicked */\n onNodeDoubleClick?: (event: React.MouseEvent, node: FlowNode) => void\n /** Called on node right-click / context menu */\n onNodeContextMenu?: (event: React.MouseEvent, node: FlowNode) => void\n /** Called when mouse enters a node */\n onNodeMouseEnter?: (event: React.MouseEvent, node: FlowNode) => void\n /** Called when mouse leaves a node */\n onNodeMouseLeave?: (event: React.MouseEvent, node: FlowNode) => void\n /** Called when an edge is clicked */\n onEdgeClick?: (event: React.MouseEvent, edge: FlowEdge) => void\n /** S1: Custom frame node renderer. Should be a stable reference (memoize or define outside render). */\n frameRenderer?: React.ComponentType<FrameNodeSlotProps>\n /** S2: Custom edge renderers by edge type slug. Should be a stable reference (memoize or define outside render). */\n edgeRenderers?: Record<string, React.ComponentType<EdgeSlotProps>>\n /** S3: Wraps every dynamic node's rendered content. Should be a stable reference (memoize or define outside render). */\n nodeWrapper?: React.ComponentType<NodeWrapperSlotProps>\n /** S4: Show controls (default: false) */\n controls?: boolean\n /** S4: Show minimap (default: false) */\n minimap?: boolean\n /** S4: Custom minimap node color function */\n minimapNodeColor?: (node: FlowNode) => string\n /** S4: Additional children rendered inside ReactFlow */\n children?: React.ReactNode\n /** S5: Global override for all dynamic nodes. Should be a stable reference (memoize or define outside render). */\n renderNode?: (\n props: DynamicNodeSlotProps,\n defaultRender: React.ReactElement,\n ) => React.ReactElement | null\n /** S6: Called when viewport changes (pan/zoom) */\n onViewportChange?: (viewport: FlowViewport) => void\n /** S6: Default viewport (used when fitView is false) */\n defaultViewport?: FlowViewport\n /** S8: Focus on specific bounds (used for initial viewport fit). */\n bounds?: FlowBounds\n /** S8: Separate bounds for panning/zoom restriction. When set, overrides bounds-based translateExtent. Useful when fitBounds (content) differs from clampBounds (frame area). */\n clampBounds?: FlowBounds\n /** S8: Padding for focus bounds (default: 0.1) */\n focusPadding?: number\n /** S8: Animate focus transition (true=300ms, number=custom ms, false=instant) */\n focusAnimation?: boolean | number\n /** S8: Focus mode — \"contain\" fits entire bounds (may have margins), \"cover\" fills viewport (may crop). Default: \"contain\" */\n focusMode?: 'contain' | 'cover'\n /** Re-fit viewport on container resize (default: true when bounds is set) */\n responsiveFit?: boolean\n /** Override translateExtent directly. When set, overrides the automatic bounds-based panning restriction. */\n translateExtent?: [[number, number], [number, number]]\n}\n\nexport function FlowRenderer({\n data,\n className,\n style,\n nodeRenderers,\n nodeTypeDefs,\n edgeTypeDefs,\n background = false,\n interactive = false,\n fitView = true,\n onNodeClick,\n onNodeDoubleClick,\n onNodeContextMenu,\n onNodeMouseEnter,\n onNodeMouseLeave,\n onEdgeClick,\n frameRenderer,\n edgeRenderers,\n nodeWrapper,\n controls,\n minimap,\n minimapNodeColor,\n children,\n renderNode,\n onViewportChange,\n defaultViewport: defaultViewportProp,\n bounds,\n clampBounds,\n focusPadding,\n focusAnimation,\n focusMode = 'contain',\n responsiveFit,\n translateExtent: translateExtentProp,\n}: FlowRendererProps) {\n const nodeTypeDefsMap = React.useMemo(() => {\n if (!nodeTypeDefs?.length) return undefined\n return new Map(nodeTypeDefs.map((d) => [d.slug, d]))\n }, [nodeTypeDefs])\n\n const edgeTypeDefsMap = React.useMemo(() => {\n if (!edgeTypeDefs?.length) return undefined\n return new Map(edgeTypeDefs.map((d) => [d.slug, d]))\n }, [edgeTypeDefs])\n\n const nodeTypes = React.useMemo(\n () =>\n createNodeTypes(\n nodeRenderers,\n nodeTypeDefsMap,\n frameRenderer,\n nodeWrapper,\n renderNode,\n ),\n [nodeRenderers, nodeTypeDefsMap, frameRenderer, nodeWrapper, renderNode],\n )\n\n // S2: Custom edge types\n const customEdgeTypes = React.useMemo(\n () => createEdgeTypes(edgeRenderers, edgeTypeDefsMap),\n [edgeRenderers, edgeTypeDefsMap],\n )\n\n // Merge all customCSS from node type definitions\n const mergedCSS = React.useMemo(() => {\n if (!nodeTypeDefs?.length) return ''\n return nodeTypeDefs\n .filter((d) => d.customCSS)\n .map((d) => d.customCSS)\n .join('\\n')\n }, [nodeTypeDefs])\n\n const styledEdges = React.useMemo(() => {\n let edges = applyEdgeStyles(data?.edges ?? [], edgeTypeDefsMap)\n // When custom edge renderers exist, set edge type to slug for matching\n if (edgeRenderers) {\n edges = edges.map((edge) => {\n const slug = (edge as unknown as FlowEdge).edgeTypeSlug\n if (slug && edgeRenderers[slug]) {\n return { ...edge, type: slug }\n }\n return edge\n })\n }\n return edges\n }, [data?.edges, edgeTypeDefsMap, edgeRenderers])\n\n // Panning restriction: explicit prop > clampBounds (no padding) > bounds (with padding)\n const translateExtent = React.useMemo(() => {\n if (translateExtentProp) return translateExtentProp\n const es = clampBounds ?? bounds\n if (!es) return undefined\n const ep = clampBounds ? 0 : (focusPadding ?? 0.1)\n return [\n [es.x - ep * es.width, es.y - ep * es.height],\n [es.x + es.width * (1 + ep), es.y + es.height * (1 + ep)],\n ] as [[number, number], [number, number]]\n }, [translateExtentProp, clampBounds, bounds, focusPadding])\n\n if (!data) return null\n\n const resolvedDefaultViewport =\n defaultViewportProp ??\n (!fitView && data.viewport ? data.viewport : undefined)\n\n return (\n <ReactFlowProvider>\n <div\n className={className}\n style={{\n width: '100%',\n height: '100%',\n background: 'transparent',\n ...style,\n }}\n >\n <ReactFlow\n nodes={\n (data.nodes ?? []) as unknown as Parameters<\n typeof ReactFlow\n >[0]['nodes']\n }\n edges={styledEdges}\n nodeTypes={nodeTypes}\n edgeTypes={\n customEdgeTypes as Parameters<typeof ReactFlow>[0]['edgeTypes']\n }\n defaultViewport={resolvedDefaultViewport}\n fitView={bounds ? false : fitView}\n translateExtent={translateExtent}\n onNodeClick={\n onNodeClick as Parameters<typeof ReactFlow>[0]['onNodeClick']\n }\n onNodeDoubleClick={\n onNodeDoubleClick as Parameters<\n typeof ReactFlow\n >[0]['onNodeDoubleClick']\n }\n onNodeContextMenu={\n onNodeContextMenu as Parameters<\n typeof ReactFlow\n >[0]['onNodeContextMenu']\n }\n onNodeMouseEnter={\n onNodeMouseEnter as Parameters<\n typeof ReactFlow\n >[0]['onNodeMouseEnter']\n }\n onNodeMouseLeave={\n onNodeMouseLeave as Parameters<\n typeof ReactFlow\n >[0]['onNodeMouseLeave']\n }\n onEdgeClick={\n onEdgeClick as Parameters<typeof ReactFlow>[0]['onEdgeClick']\n }\n onMoveEnd={\n onViewportChange\n ? (((_: unknown, vp: { x: number; y: number; zoom: number }) => {\n onViewportChange(vp)\n }) as Parameters<typeof ReactFlow>[0]['onMoveEnd'])\n : undefined\n }\n nodesDraggable={interactive}\n nodesConnectable={false}\n elementsSelectable={\n interactive ||\n !!onNodeClick ||\n !!onNodeDoubleClick ||\n !!onEdgeClick\n }\n panOnDrag={interactive}\n zoomOnScroll={interactive}\n zoomOnPinch={interactive}\n zoomOnDoubleClick={false}\n proOptions={{ hideAttribution: true }}\n >\n {mergedCSS && (\n <style dangerouslySetInnerHTML={{ __html: mergedCSS }} />\n )}\n {background && <Background />}\n {controls && <Controls />}\n {minimap && (\n <MiniMap\n nodeColor={\n minimapNodeColor as Parameters<typeof MiniMap>[0]['nodeColor']\n }\n />\n )}\n {bounds && (\n <FocusHandler\n bounds={bounds}\n padding={focusPadding ?? 0.1}\n animation={focusAnimation ?? true}\n mode={focusMode}\n responsive={responsiveFit ?? true}\n extent={translateExtent}\n />\n )}\n {children}\n </ReactFlow>\n </div>\n </ReactFlowProvider>\n )\n}\n","import type React from 'react'\n\n// ── Dynamic node data ──\n\nexport interface DynamicNodeData {\n nodeTypeSlug: string\n label: string\n fields: Record<string, unknown>\n}\n\nexport type FlowNodeData = (DynamicNodeData | FrameNodeData) &\n Record<string, unknown>\n\n// ── Canvas types (mirrors @xyflow/react but standalone) ──\n\nexport interface FlowNodePosition {\n x: number\n y: number\n}\n\nexport interface FlowNode {\n id: string\n type?: string\n position: FlowNodePosition\n data: FlowNodeData\n parentId?: string\n style?: React.CSSProperties\n width?: number\n height?: number\n measured?: { width?: number; height?: number }\n draggable?: boolean\n selectable?: boolean\n [key: string]: unknown\n}\n\nexport interface FlowEdge {\n id: string\n source: string\n target: string\n sourceHandle?: string | null\n targetHandle?: string | null\n type?: string\n style?: React.CSSProperties\n animated?: boolean\n markerStart?: unknown\n markerEnd?: unknown\n edgeTypeSlug?: string\n fields?: Record<string, unknown>\n [key: string]: unknown\n}\n\nexport interface FlowViewport {\n x: number\n y: number\n zoom: number\n}\n\nexport interface CanvasData {\n nodes: FlowNode[]\n edges: FlowEdge[]\n viewport: FlowViewport\n}\n\n// ── Node type definitions (mirrors console's NodeTypeDef) ──\n\nexport interface NodeTypeFieldDef {\n name: string\n label: string\n fieldType:\n | 'text'\n | 'textarea'\n | 'number'\n | 'url'\n | 'color'\n | 'image'\n | 'select'\n | 'toggle'\n options?: { label: string; value: string }[]\n defaultValue?: string\n required?: boolean\n}\n\nexport interface NodeTypeDef {\n slug: string\n name: string\n color: string\n defaultSize: { width: number; height: number }\n fields: NodeTypeFieldDef[]\n transparentBackground?: boolean\n template?: string | null\n customCSS?: string | null\n}\n\n// ── Edge type definitions (mirrors console's EdgeTypeDef) ──\n\nexport interface EdgeTypeDef {\n slug: string\n name: string\n color: string\n strokeWidth: number\n animated: boolean\n lineStyle: string\n markerStart: string\n markerEnd: string\n fields: NodeTypeFieldDef[]\n}\n\n// ── Type guards ──\n\nexport function isDynamicNode(\n node: FlowNode,\n): node is FlowNode & { data: DynamicNodeData } {\n return node.type === 'dynamic'\n}\n\nexport function isFrameNode(\n node: FlowNode,\n): node is FlowNode & { data: FrameNodeData } {\n return node.type === 'frame'\n}\n\n// ── Component slot props ──\n\nexport interface DynamicNodeSlotProps {\n id: string\n nodeTypeSlug: string\n label: string\n fields: Record<string, unknown>\n nodeTypeDef?: NodeTypeDef\n}\n\n// ── Frame node data ──\n\nexport interface FrameNodeData {\n label: string\n color?: string\n padding?: number\n borderStyle?: 'dashed' | 'solid' | 'none'\n opacity?: number\n}\n\n// S1: Frame renderer slot\nexport interface FrameNodeSlotProps {\n id: string\n label: string\n color?: string\n padding?: number\n borderStyle?: 'dashed' | 'solid' | 'none'\n opacity?: number\n children?: React.ReactNode\n}\n\n// S2: Edge renderer slot\nexport interface EdgeSlotProps {\n id: string\n edgeTypeSlug?: string\n source: string\n target: string\n label?: string\n fields?: Record<string, unknown>\n edgeTypeDef?: EdgeTypeDef\n style?: React.CSSProperties\n}\n\n// S3: Node wrapper slot\nexport interface NodeWrapperSlotProps {\n id: string\n nodeTypeSlug: string\n label: string\n selected?: boolean\n nodeTypeDef?: NodeTypeDef\n children: React.ReactNode\n}\n\n// S8: Viewport focus\nexport interface FlowBounds {\n x: number\n y: number\n width: number\n height: number\n}\n","import type { NodeTypeDef } from './types'\n\nexport const BUILT_IN_NODE_TYPES: NodeTypeDef[] = [\n {\n slug: 'text',\n name: 'Text',\n color: '#e5e7eb',\n defaultSize: { width: 200, height: 200 },\n fields: [{ name: 'body', label: 'Body', fieldType: 'textarea' }],\n },\n {\n slug: 'image',\n name: 'Image',\n color: '#e5e7eb',\n transparentBackground: true,\n defaultSize: { width: 200, height: 200 },\n fields: [\n { name: 'image', label: 'Image', fieldType: 'image' },\n { name: 'alt', label: 'Alt Text', fieldType: 'text' },\n { name: 'caption', label: 'Caption', fieldType: 'text' },\n ],\n },\n]\n","import type { EdgeTypeDef } from './types'\n\nexport const BUILT_IN_EDGE_TYPES: EdgeTypeDef[] = [\n {\n slug: 'default',\n name: 'Default',\n color: '',\n strokeWidth: 2,\n animated: false,\n lineStyle: 'default',\n markerStart: 'none',\n markerEnd: 'arrow',\n fields: [],\n },\n]\n","'use client'\n\nimport { useQuery, type QueryClient } from '@tanstack/react-query'\nimport { useMemo } from 'react'\nimport type { CanvasData, NodeTypeDef, EdgeTypeDef } from './types'\nimport { BUILT_IN_NODE_TYPES } from './built-in-node-types'\nimport { BUILT_IN_EDGE_TYPES } from './built-in-edge-types'\nimport { collectionKeys } from '../../core/query/query-keys'\n\n// ── Client interface ──\n// Structurally compatible with both BrowserClient and ServerClient.\n// Lists only the collections useFlow actually queries so the generic\n// `from<T extends PublicCollection>` on the real clients satisfies this.\n\ntype FlowCollection = 'flows' | 'flow-node-types' | 'flow-edge-types'\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype AnyFn = (...args: any[]) => any\n\nexport interface SDKClient {\n from(collection: FlowCollection): {\n find: AnyFn\n findById: AnyFn\n }\n queryClient: QueryClient\n}\n\n// ── Options & Result ──\n\nexport interface UseFlowOptions {\n /** SDK client instance (BrowserClient or ServerClient) */\n client: SDKClient\n /** Flow slug (URL-friendly identifier) */\n slug?: string\n /** Flow document ID (UUID) */\n id?: string\n /** Enable/disable data fetching (default: true) */\n enabled?: boolean\n}\n\nexport interface UseFlowResult {\n data: CanvasData | undefined\n nodeTypeDefs: NodeTypeDef[]\n edgeTypeDefs: EdgeTypeDef[]\n flow: Record<string, unknown> | undefined\n isLoading: boolean\n error: Error | null\n}\n\n// ── Helpers ──\n\nfunction toNodeTypeDef(doc: Record<string, unknown>): NodeTypeDef {\n return {\n slug: String(doc.slug ?? ''),\n name: String(doc.title ?? ''),\n color: String(doc.color ?? '#e5e7eb'),\n defaultSize: (doc.defaultSize as NodeTypeDef['defaultSize']) ?? {\n width: 200,\n height: 200,\n },\n fields: Array.isArray(doc.fields)\n ? (doc.fields as NodeTypeDef['fields'])\n : [],\n transparentBackground: Boolean(doc.transparentBackground),\n template: (doc.template as string) ?? null,\n customCSS: (doc.customCSS as string) ?? null,\n }\n}\n\nfunction toEdgeTypeDef(doc: Record<string, unknown>): EdgeTypeDef {\n return {\n slug: String(doc.slug ?? ''),\n name: String(doc.title ?? ''),\n color: String(doc.color ?? ''),\n strokeWidth: (doc.strokeWidth as number) ?? 2,\n animated: (doc.animated as boolean) ?? false,\n lineStyle: String(doc.lineStyle ?? 'default'),\n markerStart: String(doc.markerStart ?? 'none'),\n markerEnd: String(doc.markerEnd ?? 'arrow'),\n fields: Array.isArray(doc.fields)\n ? (doc.fields as EdgeTypeDef['fields'])\n : [],\n }\n}\n\n// ── Hook ──\n\nexport function useFlow(options: UseFlowOptions): UseFlowResult {\n const { client, slug, id, enabled = true } = options\n const hasIdentifier = !!(slug || id)\n const identifier = id ?? slug ?? ''\n\n // Fetch flow document\n const flowQuery = useQuery<Record<string, unknown>>(\n {\n queryKey: collectionKeys('flows').detail(identifier),\n queryFn: async () => {\n if (id) {\n return client.from('flows').findById(id)\n }\n const result = await client.from('flows').find({\n where: { slug: { equals: slug } },\n limit: 1,\n })\n const doc = result.docs[0]\n if (!doc) throw new Error(`Flow not found: ${slug}`)\n return doc\n },\n enabled: enabled && hasIdentifier,\n },\n client.queryClient,\n )\n\n // Fetch tenant's custom node types\n const nodeTypesQuery = useQuery<Record<string, unknown>[]>(\n {\n queryKey: collectionKeys('flow-node-types').lists(),\n queryFn: async () => {\n const result = await client.from('flow-node-types').find({ limit: 100 })\n return result.docs\n },\n enabled,\n },\n client.queryClient,\n )\n\n // Fetch tenant's custom edge types\n const edgeTypesQuery = useQuery<Record<string, unknown>[]>(\n {\n queryKey: collectionKeys('flow-edge-types').lists(),\n queryFn: async () => {\n const result = await client.from('flow-edge-types').find({ limit: 100 })\n return result.docs\n },\n enabled,\n },\n client.queryClient,\n )\n\n // Merge built-in + API node types\n const nodeTypeDefs = useMemo<NodeTypeDef[]>(() => {\n const apiDefs = (nodeTypesQuery.data ?? []).map(toNodeTypeDef)\n const builtInSlugs = new Set(BUILT_IN_NODE_TYPES.map((t) => t.slug))\n const customDefs = apiDefs.filter((d) => !builtInSlugs.has(d.slug))\n return [...BUILT_IN_NODE_TYPES, ...customDefs]\n }, [nodeTypesQuery.data])\n\n // Merge built-in + API edge types\n const edgeTypeDefs = useMemo<EdgeTypeDef[]>(() => {\n const apiDefs = (edgeTypesQuery.data ?? []).map(toEdgeTypeDef)\n const builtInSlugs = new Set(BUILT_IN_EDGE_TYPES.map((t) => t.slug))\n const customDefs = apiDefs.filter((d) => !builtInSlugs.has(d.slug))\n return [...BUILT_IN_EDGE_TYPES, ...customDefs]\n }, [edgeTypesQuery.data])\n\n const flow = flowQuery.data\n const canvas = flow?.canvas as CanvasData | undefined\n\n return {\n data: canvas,\n nodeTypeDefs,\n edgeTypeDefs,\n flow,\n isLoading:\n flowQuery.isLoading ||\n nodeTypesQuery.isLoading ||\n edgeTypesQuery.isLoading,\n error:\n (flowQuery.error as Error | null) ??\n (nodeTypesQuery.error as Error | null) ??\n (edgeTypesQuery.error as Error | null),\n }\n}\n","import type { PublicCollection, ApiQueryOptions } from '../client/types'\n\nexport function collectionKeys<T extends PublicCollection>(collection: T) {\n return {\n all: [collection] as const,\n lists: () => [collection, 'list'] as const,\n list: (options?: ApiQueryOptions) => [collection, 'list', options] as const,\n details: () => [collection, 'detail'] as const,\n detail: (id: string, options?: ApiQueryOptions) =>\n [collection, 'detail', id, options] as const,\n infinites: () => [collection, 'infinite'] as const,\n infinite: (options?: Omit<ApiQueryOptions, 'page'>) =>\n [collection, 'infinite', options] as const,\n }\n}\n\nexport const customerKeys = {\n all: ['customer'] as const,\n me: () => ['customer', 'me'] as const,\n}\n","import { useMemo } from 'react'\nimport type { CanvasData, FlowNode, NodeTypeDef, EdgeTypeDef } from './types'\nimport type { Edge } from '@xyflow/react'\nimport { BUILT_IN_NODE_TYPES } from './built-in-node-types'\nimport { BUILT_IN_EDGE_TYPES } from './built-in-edge-types'\n\n// ── Options & Result ──\n\nexport interface UseFlowDataOptions {\n /** Canvas data from Flow document's `canvas` field */\n data: CanvasData | undefined\n /** Node type definitions (defaults to built-in types) */\n nodeTypeDefs?: NodeTypeDef[]\n /** Edge type definitions (defaults to built-in types) */\n edgeTypeDefs?: EdgeTypeDef[]\n}\n\nexport interface UseFlowDataResult {\n /** Nodes from canvas data */\n nodes: FlowNode[]\n /** Edges from canvas data (typed for @xyflow/react) */\n edges: Edge[]\n /** Map of node type slug to definition */\n nodeTypeDefsMap: Map<string, NodeTypeDef>\n /** Map of edge type slug to definition */\n edgeTypeDefsMap: Map<string, EdgeTypeDef>\n}\n\n/**\n * Pure data transformation hook — extracts nodes, edges, and type definition\n * maps from canvas data without any rendering. Useful for headless usage\n * (custom layouts, analytics, server-side processing).\n */\nexport function useFlowData(options: UseFlowDataOptions): UseFlowDataResult {\n const { data, nodeTypeDefs: inputNodeDefs, edgeTypeDefs: inputEdgeDefs } =\n options\n\n const nodeTypeDefsMap = useMemo(() => {\n const allDefs = inputNodeDefs ?? BUILT_IN_NODE_TYPES\n return new Map(allDefs.map((d) => [d.slug, d]))\n }, [inputNodeDefs])\n\n const edgeTypeDefsMap = useMemo(() => {\n const allDefs = inputEdgeDefs ?? BUILT_IN_EDGE_TYPES\n return new Map(allDefs.map((d) => [d.slug, d]))\n }, [inputEdgeDefs])\n\n const nodes = useMemo(() => data?.nodes ?? [], [data?.nodes])\n const edges = useMemo(() => (data?.edges ?? []) as unknown as Edge[], [data?.edges])\n\n return {\n nodes,\n edges,\n nodeTypeDefsMap,\n edgeTypeDefsMap,\n }\n}\n","import type { FlowNode, FlowEdge, FlowBounds, CanvasData } from './types'\n\n// ── Shared helpers ──\n\nfunction getNodeSize(node: FlowNode): { width: number; height: number } {\n return {\n width:\n (node.style?.width as number) ??\n node.measured?.width ??\n node.width ??\n 200,\n height:\n (node.style?.height as number) ??\n node.measured?.height ??\n node.height ??\n 200,\n }\n}\n\nfunction getAbsolutePosition(\n node: FlowNode,\n nodeMap: Map<string, FlowNode>,\n): { x: number; y: number } {\n let x = node.position.x\n let y = node.position.y\n let current = node\n const visited = new Set<string>([node.id])\n while (current.parentId) {\n const parentId = current.parentId\n if (visited.has(parentId)) break\n const parent = nodeMap.get(parentId)\n if (!parent) break\n visited.add(parent.id)\n x += parent.position.x\n y += parent.position.y\n current = parent\n }\n return { x, y }\n}\n\n/** Collect a node and all its descendants (BFS with index pointer to avoid O(Q²) shift). */\nfunction collectDescendants(\n nodes: FlowNode[],\n rootId: string,\n): Set<string> {\n const result = new Set<string>([rootId])\n const queue = [rootId]\n let i = 0\n while (i < queue.length) {\n const current = queue[i++]\n for (const n of nodes) {\n if (n.parentId === current && !result.has(n.id)) {\n result.add(n.id)\n queue.push(n.id)\n }\n }\n }\n return result\n}\n\n// ── Public utilities ──\n\n/**\n * Calculate bounding box for given node IDs.\n * Pure function — usable in SSR, server components, or outside React.\n */\nexport function getNodeBounds(\n nodes: FlowNode[],\n nodeIds: string[],\n): FlowBounds | undefined {\n const idSet = new Set(nodeIds)\n const targetNodes = nodes.filter((n) => idSet.has(n.id))\n if (targetNodes.length === 0) return undefined\n\n const nodeMap = new Map(nodes.map((n) => [n.id, n]))\n\n let minX = Infinity\n let minY = Infinity\n let maxX = -Infinity\n let maxY = -Infinity\n\n for (const node of targetNodes) {\n const abs = getAbsolutePosition(node, nodeMap)\n const { width: w, height: h } = getNodeSize(node)\n minX = Math.min(minX, abs.x)\n minY = Math.min(minY, abs.y)\n maxX = Math.max(maxX, abs.x + w)\n maxY = Math.max(maxY, abs.y + h)\n }\n\n return { x: minX, y: minY, width: maxX - minX, height: maxY - minY }\n}\n\n/**\n * Get all frame nodes with their bounds.\n * Sorted by position (top-left to bottom-right).\n */\nexport function getFrames(\n nodes: FlowNode[],\n): Array<{ id: string; label: string; bounds: FlowBounds }> {\n const frames = nodes.filter((n) => n.type === 'frame')\n if (frames.length === 0) return []\n\n const nodeMap = new Map(nodes.map((n) => [n.id, n]))\n\n return frames\n .map((f) => {\n const data = f.data as { label?: string }\n const abs = getAbsolutePosition(f, nodeMap)\n const { width: w, height: h } = getNodeSize(f)\n return {\n id: f.id,\n label: data.label ?? '',\n bounds: { x: abs.x, y: abs.y, width: w, height: h },\n }\n })\n .sort((a, b) => a.bounds.y - b.bounds.y || a.bounds.x - b.bounds.x)\n}\n\n/** Result of getFrameData — contains filtered canvas + dual bounds. */\nexport interface FrameData {\n /** Canvas data containing only the frame's descendants (nodes have draggable: false). */\n data: CanvasData\n /** Bounding box of child content nodes — use for initial viewport fit (centering). */\n fitBounds: FlowBounds\n /** Bounding box of the frame itself — use for panning/zoom restriction (clamp). */\n clampBounds: FlowBounds\n /** @deprecated Use fitBounds instead. Alias for clampBounds for backward compatibility. */\n bounds: FlowBounds\n}\n\n/**\n * Extract a frame's descendants and related edges from canvas data.\n * Recursively collects all nested children (supports nested frames).\n * Returns undefined if frameId is not found or is not a frame node.\n *\n * Child nodes are marked `draggable: false` to prevent interfering with canvas panning.\n * The frame node itself is included (use `frameRenderer={() => null}` to hide it).\n *\n * Returns dual bounds:\n * - `fitBounds`: child content bounding box (for centering the viewport)\n * - `clampBounds`: frame area bounding box (for panning restriction)\n */\nexport function getFrameData(\n data: CanvasData,\n frameId: string,\n): FrameData | undefined {\n const frame = data.nodes.find((n) => n.id === frameId)\n if (!frame || frame.type !== 'frame') return undefined\n\n // Recursively collect frame + all descendants\n const descendantIds = collectDescendants(data.nodes, frameId)\n const childNodes = data.nodes\n .filter((n) => descendantIds.has(n.id))\n .map((n) => ({ ...n, draggable: false }))\n\n // Keep only edges where both source and target are within the frame\n const childEdges = data.edges.filter(\n (e: FlowEdge) => descendantIds.has(e.source) && descendantIds.has(e.target),\n )\n\n // clampBounds: frame's own bounding box (for panning restriction)\n const frameBounds = getNodeBounds(data.nodes, [frameId])\n const { width: w, height: h } = getNodeSize(frame)\n const clampBounds: FlowBounds = frameBounds ?? {\n x: frame.position.x,\n y: frame.position.y,\n width: w,\n height: h,\n }\n\n // fitBounds: child content bounding box (for centering)\n const contentNodeIds = childNodes\n .filter((n) => n.id !== frameId)\n .map((n) => n.id)\n const contentBounds = contentNodeIds.length > 0\n ? getNodeBounds(data.nodes, contentNodeIds)\n : undefined\n const fitBounds = contentBounds ?? clampBounds\n\n return {\n data: {\n nodes: childNodes,\n edges: childEdges,\n viewport: data.viewport,\n },\n fitBounds,\n clampBounds,\n bounds: clampBounds,\n }\n}\n","'use client'\n\nimport React from 'react'\nimport { transform } from 'sucrase'\n\nexport interface CodeComponentProps {\n fields: Record<string, unknown>\n label: string\n color: string\n nodeTypeSlug: string\n width: number\n height: number\n}\n\nconst MAX_CACHE_SIZE = 100\nconst componentCache = new Map<string, React.FC<CodeComponentProps>>()\n\nfunction hashCode(str: string): string {\n let hash = 0\n for (let i = 0; i < str.length; i++) {\n const char = str.charCodeAt(i)\n hash = ((hash << 5) - hash + char) | 0\n }\n return hash.toString(36)\n}\n\nconst BLOCKED_PATTERNS = [\n /\\bdocument\\s*\\./,\n /\\bwindow\\s*\\./,\n /\\bwindow\\s*\\[/,\n /\\bglobalThis\\s*\\./,\n /\\bfetch\\s*\\(/,\n /\\bXMLHttpRequest/,\n /\\beval\\s*\\(/,\n /\\bFunction\\s*\\(/,\n /\\bimport\\s*\\(/,\n /\\blocalStorage/,\n /\\bsessionStorage/,\n /\\bcookie/,\n /\\bpostMessage\\s*\\(/,\n /\\blocation\\s*[.=]/,\n /\\bnavigator\\s*\\./,\n /\\bsetTimeout\\s*\\(/,\n /\\bsetInterval\\s*\\(/,\n /\\bsetImmediate\\s*\\(/,\n /\\brequire\\s*\\(/,\n]\n\nfunction validateTemplateCode(code: string): boolean {\n return !BLOCKED_PATTERNS.some((pattern) => pattern.test(code))\n}\n\nexport function compileTemplate(\n code: string,\n slug: string,\n): React.FC<CodeComponentProps> | null {\n const cacheKey = `${slug}:${hashCode(code)}`\n\n if (componentCache.has(cacheKey)) {\n const cached = componentCache.get(cacheKey)!\n componentCache.delete(cacheKey)\n componentCache.set(cacheKey, cached)\n return cached\n }\n\n if (!validateTemplateCode(code)) {\n console.warn(`[flow] Template \"${slug}\" contains blocked patterns`)\n return null\n }\n\n try {\n const { code: jsCode } = transform(code, {\n transforms: ['typescript', 'jsx', 'imports'],\n jsxRuntime: 'classic',\n jsxPragma: 'React.createElement',\n jsxFragmentPragma: 'React.Fragment',\n })\n\n // Shadow dangerous globals to neutralize blocklist bypasses\n const factory = new Function(\n 'React',\n `\n var window = undefined;\n var document = undefined;\n var globalThis = undefined;\n var setTimeout = undefined;\n var setInterval = undefined;\n var setImmediate = undefined;\n var fetch = undefined;\n var XMLHttpRequest = undefined;\n var navigator = undefined;\n var location = undefined;\n var exports = {};\n var module = { exports: exports };\n ${jsCode}\n return module.exports.default || module.exports;\n `,\n )\n\n const Component = factory(React)\n if (typeof Component !== 'function') return null\n\n if (componentCache.size >= MAX_CACHE_SIZE) {\n const oldestKey = componentCache.keys().next().value\n if (oldestKey) componentCache.delete(oldestKey)\n }\n\n componentCache.set(cacheKey, Component)\n return Component\n } catch (e) {\n console.warn(`[flow] Failed to compile template for \"${slug}\":`, e)\n return null\n }\n}\n\nexport function clearTemplateCache(): void {\n componentCache.clear()\n}\n"],"mappings":"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","names":["React","_a","useMemo","useMemo","React","_a"]}
1
+ {"version":3,"sources":["../../src/ui/Flow/index.tsx","../../src/ui/Flow/types.ts","../../src/ui/Flow/built-in-node-types.ts","../../src/ui/Flow/built-in-edge-types.ts","../../src/ui/Flow/useFlow.ts","../../src/core/query/query-keys.ts","../../src/ui/Flow/useFlowData.ts","../../src/ui/Flow/utils.ts","../../src/ui/Flow/template-compiler.ts"],"sourcesContent":["'use client'\n\nimport React from 'react'\nimport {\n ReactFlow,\n ReactFlowProvider,\n Background,\n Controls,\n MiniMap,\n MarkerType,\n useReactFlow,\n useStoreApi,\n type NodeTypes,\n type NodeProps,\n type Edge,\n} from '@xyflow/react'\nimport type {\n CanvasData,\n DynamicNodeData,\n DynamicNodeSlotProps,\n EdgeSlotProps,\n EdgeTypeDef,\n FlowBounds,\n FlowEdge,\n FlowNode,\n FlowViewport,\n FrameNodeData,\n FrameNodeSlotProps,\n NodeTypeDef,\n NodeTypeFieldDef,\n NodeWrapperSlotProps,\n} from './types'\n\nexport type {\n CanvasData,\n DynamicNodeSlotProps,\n FlowNode,\n FlowEdge,\n FlowViewport,\n FlowNodePosition,\n FlowNodeData,\n DynamicNodeData,\n FrameNodeData,\n NodeTypeDef,\n NodeTypeFieldDef,\n EdgeTypeDef,\n FrameNodeSlotProps,\n EdgeSlotProps,\n NodeWrapperSlotProps,\n FlowBounds,\n} from './types'\nexport { isDynamicNode, isFrameNode } from './types'\nexport { BUILT_IN_NODE_TYPES } from './built-in-node-types'\nexport { BUILT_IN_EDGE_TYPES } from './built-in-edge-types'\nexport { useFlow } from './useFlow'\nexport type { SDKClient, UseFlowOptions, UseFlowResult } from './useFlow'\nexport { useFlowData } from './useFlowData'\nexport type { UseFlowDataOptions, UseFlowDataResult } from './useFlowData'\nexport { getNodeBounds, getFrames, getFrameData } from './utils'\nexport type { FrameData } from './utils'\nexport { compileTemplate, clearTemplateCache } from './template-compiler'\nexport type { CodeComponentProps } from './template-compiler'\n\nimport { compileTemplate } from './template-compiler'\n\n// ── Helpers ──\n\nfunction sanitizeUrl(url: string | undefined): string | undefined {\n if (!url) return url\n try {\n const parsed = new URL(url)\n if (parsed.protocol === 'http:' || parsed.protocol === 'https:') return url\n return undefined\n } catch {\n return undefined\n }\n}\n\nfunction toMarkerType(value: string): MarkerType | undefined {\n if (value === 'arrow') return MarkerType.Arrow\n if (value === 'arrowclosed') return MarkerType.ArrowClosed\n return undefined\n}\n\n// ── Field renderer (type-aware, matching console style) ──\n\nfunction renderFieldValue(\n key: string,\n val: unknown,\n fieldDef?: NodeTypeFieldDef,\n): React.ReactNode {\n if (val == null || val === '') return null\n\n const fieldType = fieldDef?.fieldType\n\n // Image field — image only, no decoration\n if (\n fieldType === 'image' ||\n (typeof val === 'object' && val !== null && 'url' in val)\n ) {\n const imgUrl =\n typeof val === 'string' ? val : (val as { url?: string })?.url\n const safeUrl = sanitizeUrl(imgUrl)\n if (!safeUrl) return null\n return (\n <img\n key={key}\n src={safeUrl}\n alt=\"\"\n draggable={false}\n style={{ flex: 1, minHeight: 0, width: '100%', objectFit: 'contain' }}\n />\n )\n }\n\n // All other fields — text only\n return (\n <div\n key={key}\n style={{\n fontSize: 11,\n whiteSpace: 'pre-wrap',\n wordBreak: 'break-word',\n overflow: 'hidden',\n flexShrink: 0,\n }}\n >\n {String(val)}\n </div>\n )\n}\n\n// ── Default dynamic node renderer (no typeDef) ──\n\nfunction DefaultDynamicNode({ data }: NodeProps) {\n const d = data as unknown as DynamicNodeData\n return (\n <div\n style={{\n width: '100%',\n height: '100%',\n display: 'flex',\n flexDirection: 'column',\n }}\n >\n {d.fields &&\n Object.entries(d.fields)\n .filter(([, v]) => v != null && v !== '')\n .map(([key, val]) => renderFieldValue(key, val))}\n </div>\n )\n}\n\n// ── Template error boundary ──\n\nclass TemplateErrorBoundary extends React.Component<\n { resetKey?: string; children: React.ReactNode },\n { error: Error | null }\n> {\n state: { error: Error | null } = { error: null }\n static getDerivedStateFromError(error: Error) {\n return { error }\n }\n componentDidUpdate(prevProps: { resetKey?: string }) {\n if (prevProps.resetKey !== this.props.resetKey && this.state.error) {\n this.setState({ error: null })\n }\n }\n render() {\n if (this.state.error) {\n return (\n <div style={{ padding: 8, fontSize: 11, color: '#ef4444' }}>\n <strong>Render error</strong>\n <pre style={{ fontSize: 10, whiteSpace: 'pre-wrap' }}>\n {this.state.error.message}\n </pre>\n </div>\n )\n }\n return this.props.children\n }\n}\n\n// ── Enhanced dynamic node renderer (with NodeTypeDef) ──\n\nfunction EnhancedDynamicNode({\n data,\n typeDef,\n width,\n height,\n}: {\n data: DynamicNodeData\n typeDef: NodeTypeDef\n width?: number\n height?: number\n}) {\n // Tier 2: Custom template rendering\n if (typeDef.template) {\n const Component = compileTemplate(typeDef.template, typeDef.slug)\n if (Component) {\n return (\n <div\n className={`flow-node flow-node--${typeDef.slug}${typeDef.transparentBackground ? ' flow-node--transparent-bg' : ''}`}\n style={{ width: '100%', height: '100%' }}\n >\n <TemplateErrorBoundary resetKey={typeDef.template}>\n <Component\n fields={data.fields}\n label={data.label}\n color={typeDef.color}\n nodeTypeSlug={typeDef.slug}\n width={width || typeDef.defaultSize.width}\n height={height || typeDef.defaultSize.height}\n />\n </TemplateErrorBoundary>\n </div>\n )\n }\n }\n\n // Tier 1: Default field rendering\n return (\n <div\n style={{\n width: '100%',\n height: '100%',\n display: 'flex',\n flexDirection: 'column',\n }}\n >\n {typeDef.fields.map((f) => {\n const val = data.fields[f.name]\n if (val == null || val === '') return null\n return renderFieldValue(f.name, val, f)\n })}\n </div>\n )\n}\n\n// ── Default frame node renderer ──\n\nfunction DefaultFrameNode({ data }: NodeProps) {\n const d = data as unknown as FrameNodeData\n const baseColor = d.color ?? 'rgb(128,128,128)'\n const padding = d.padding ?? 20\n const borderStyle = d.borderStyle ?? 'dashed'\n const opacity = d.opacity ?? 0.15\n\n // Apply opacity to color at render time\n const bgColor = (() => {\n const m = baseColor.match(/rgba?\\((\\d+),\\s*(\\d+),\\s*(\\d+)/)\n if (m) return `rgba(${m[1]},${m[2]},${m[3]},${opacity})`\n return baseColor\n })()\n\n return (\n <div\n style={{\n backgroundColor: bgColor,\n padding,\n width: '100%',\n height: '100%',\n border:\n borderStyle === 'none'\n ? 'none'\n : `2px ${borderStyle} rgba(128,128,128,0.3)`,\n }}\n >\n <div\n style={{\n fontSize: 11,\n fontWeight: 600,\n color: 'rgba(128,128,128,0.6)',\n userSelect: 'none',\n }}\n >\n {d.label}\n </div>\n </div>\n )\n}\n\n// ── Node types builder ──\n\nfunction createNodeTypes(\n nodeRenderers?: Record<string, React.ComponentType<DynamicNodeSlotProps>>,\n nodeTypeDefsMap?: Map<string, NodeTypeDef>,\n frameRenderer?: React.ComponentType<FrameNodeSlotProps>,\n nodeWrapper?: React.ComponentType<NodeWrapperSlotProps>,\n renderNode?: (\n props: DynamicNodeSlotProps,\n content: React.ReactElement,\n ) => React.ReactElement | null,\n): NodeTypes {\n const types: NodeTypes = {} as NodeTypes\n\n // Dynamic node type\n types.dynamic = ((props: NodeProps) => {\n const d = props.data as unknown as DynamicNodeData\n const typeDef = nodeTypeDefsMap?.get(d.nodeTypeSlug)\n const CustomRenderer = nodeRenderers?.[d.nodeTypeSlug]\n\n // Compute default rendering (template or field-based)\n const defaultRender: React.ReactElement = typeDef ? (\n <EnhancedDynamicNode\n data={d}\n typeDef={typeDef}\n width={props.width}\n height={props.height}\n />\n ) : (\n <DefaultDynamicNode {...props} />\n )\n\n const slotProps: DynamicNodeSlotProps = {\n id: props.id,\n nodeTypeSlug: d.nodeTypeSlug,\n label: d.label,\n fields: d.fields,\n nodeTypeDef: typeDef,\n selected: props.selected,\n width: props.width,\n height: props.height,\n defaultRender,\n }\n\n let content: React.ReactElement = CustomRenderer ? (\n <CustomRenderer {...slotProps} />\n ) : (\n defaultRender\n )\n\n // S5: renderNode global callback\n if (renderNode) {\n const result = renderNode(slotProps, content)\n if (result !== null) content = result\n }\n\n // S3: nodeWrapper\n if (nodeWrapper) {\n const Wrapper = nodeWrapper\n content = (\n <Wrapper\n id={props.id}\n nodeTypeSlug={d.nodeTypeSlug}\n label={d.label}\n selected={props.selected}\n nodeTypeDef={typeDef}\n >\n {content}\n </Wrapper>\n )\n }\n\n return content\n }) as NodeTypes[string]\n\n // S1: Frame node type — custom or default\n types.frame = frameRenderer\n ? (((props: NodeProps) => {\n const d = props.data as unknown as FrameNodeData\n const Renderer = frameRenderer\n return (\n <Renderer\n id={props.id}\n label={d.label}\n color={d.color}\n padding={d.padding}\n borderStyle={d.borderStyle}\n opacity={d.opacity}\n width={props.width}\n height={props.height}\n />\n )\n }) as NodeTypes[string])\n : (DefaultFrameNode as NodeTypes[string])\n\n return types\n}\n\n// S2: Edge types builder\n\nfunction createEdgeTypes(\n edgeRenderers?: Record<string, React.ComponentType<EdgeSlotProps>>,\n edgeTypeDefsMap?: Map<string, EdgeTypeDef>,\n): Record<string, React.ComponentType<EdgeSlotProps>> | undefined {\n if (!edgeRenderers || Object.keys(edgeRenderers).length === 0)\n return undefined\n const types: Record<string, React.ComponentType<EdgeSlotProps>> = {}\n for (const [slug, Renderer] of Object.entries(edgeRenderers)) {\n types[slug] = ((props: Record<string, unknown>) => {\n const def = edgeTypeDefsMap?.get(slug)\n return (\n <Renderer\n id={props.id as string}\n edgeTypeSlug={slug}\n source={props.source as string}\n target={props.target as string}\n label={props.label as string | undefined}\n fields={\n (props.data as Record<string, unknown> | undefined)?.fields as\n | Record<string, unknown>\n | undefined\n }\n edgeTypeDef={def}\n style={props.style as React.CSSProperties | undefined}\n />\n )\n }) as unknown as React.ComponentType<EdgeSlotProps>\n }\n return types\n}\n\n// S8: FocusHandler — must be inside ReactFlowProvider\n\n// Match d3-zoom's translateExtent clamping so the initial viewport\n// is identical to what the user sees after the first drag.\nfunction clampViewport(\n vp: { x: number; y: number; zoom: number },\n cw: number,\n ch: number,\n extent: [[number, number], [number, number]],\n): { x: number; y: number; zoom: number } {\n const left = -vp.x / vp.zoom\n const right = (cw - vp.x) / vp.zoom\n const top = -vp.y / vp.zoom\n const bottom = (ch - vp.y) / vp.zoom\n\n const dx0 = left - extent[0][0]\n const dx1 = right - extent[1][0]\n const dy0 = top - extent[0][1]\n const dy1 = bottom - extent[1][1]\n\n const cx =\n dx1 > dx0 ? (dx0 + dx1) / 2 : Math.min(0, dx0) || Math.max(0, dx1)\n const cy =\n dy1 > dy0 ? (dy0 + dy1) / 2 : Math.min(0, dy0) || Math.max(0, dy1)\n\n if (cx === 0 && cy === 0) return vp\n return { x: vp.x + cx * vp.zoom, y: vp.y + cy * vp.zoom, zoom: vp.zoom }\n}\n\nfunction FocusHandler({\n bounds,\n padding,\n animation,\n mode,\n responsive,\n extent,\n clampBounds,\n minZoomProp,\n}: {\n bounds: FlowBounds\n padding: number\n animation: boolean | number\n mode: 'contain' | 'cover'\n responsive: boolean\n extent?: [[number, number], [number, number]]\n /** When set, cover zoom of these bounds is enforced as minZoom via store API. */\n clampBounds?: FlowBounds\n /** User-specified minZoom prop, used with Math.max against coverZoom. */\n minZoomProp?: number\n}) {\n const { setViewport } = useReactFlow()\n const store = useStoreApi()\n const containerRef = React.useRef<HTMLDivElement>(null)\n const boundsKey = `${bounds.x},${bounds.y},${bounds.width},${bounds.height}`\n const boundsRef = React.useRef(bounds)\n boundsRef.current = bounds\n const [containerSize, setContainerSize] = React.useState({ w: 0, h: 0 })\n const prevBoundsKeyRef = React.useRef<string | null>(null)\n const prevSizeRef = React.useRef({ w: 0, h: 0 })\n\n // Track container size via ResizeObserver\n React.useEffect(() => {\n const el = containerRef.current\n if (!el) return\n const observer = new ResizeObserver((entries) => {\n const entry = entries[0]\n if (!entry) return\n const { width, height } = entry.contentRect\n setContainerSize({ w: width, h: height })\n })\n observer.observe(el)\n return () => observer.disconnect()\n }, [])\n\n React.useEffect(() => {\n if (containerSize.w === 0 || containerSize.h === 0) return\n\n const prevKey = prevBoundsKeyRef.current\n const prevSize = prevSizeRef.current\n prevBoundsKeyRef.current = boundsKey\n prevSizeRef.current = { w: containerSize.w, h: containerSize.h }\n\n // Determine trigger: bounds change vs resize-only\n const isBoundsChange = prevKey !== boundsKey\n const isResizeOnly =\n !isBoundsChange &&\n (prevSize.w !== containerSize.w || prevSize.h !== containerSize.h)\n const isInitial = prevKey === null\n\n // Skip resize-triggered re-fit if responsiveFit is disabled\n if (isResizeOnly && !responsive) return\n\n // Animate on initial + bounds change; instant on resize\n const duration =\n isInitial || isBoundsChange\n ? animation === true\n ? 300\n : typeof animation === 'number'\n ? animation\n : 0\n : 0\n\n const b = boundsRef.current\n // In cover mode with clampBounds, use clampBounds for zoom & centering\n // to prevent asymmetric gap when content is offset within frame\n const zoomTarget = mode === 'cover' && clampBounds ? clampBounds : b\n const padX = padding * zoomTarget.width\n const padY = padding * zoomTarget.height\n const bw = zoomTarget.width + padX * 2\n const bh = zoomTarget.height + padY * 2\n\n if (bw === 0 || bh === 0) return\n\n // contain: fit inside viewport, cover: fill viewport (may crop)\n const zoomFn = mode === 'cover' ? Math.max : Math.min\n const zoom = zoomFn(containerSize.w / bw, containerSize.h / bh)\n const cx = zoomTarget.x + zoomTarget.width / 2\n const cy = zoomTarget.y + zoomTarget.height / 2\n const x = containerSize.w / 2 - cx * zoom\n const y = containerSize.h / 2 - cy * zoom\n\n // Enforce minZoom from clampBounds so user cannot zoom out beyond the frame\n if (clampBounds) {\n const coverZoom = Math.max(\n containerSize.w / clampBounds.width,\n containerSize.h / clampBounds.height,\n )\n store.getState().setMinZoom(Math.max(coverZoom, minZoomProp ?? 0))\n } else {\n store.getState().setMinZoom(minZoomProp ?? 0.5)\n }\n\n let vp = { x, y, zoom }\n if (extent) {\n vp = clampViewport(vp, containerSize.w, containerSize.h, extent)\n }\n setViewport(vp, { duration })\n }, [\n boundsKey,\n padding,\n animation,\n mode,\n responsive,\n containerSize.w,\n containerSize.h,\n extent,\n setViewport,\n clampBounds,\n minZoomProp,\n store,\n ])\n\n // Measurement div — always rendered to track container size\n return (\n <div\n ref={containerRef}\n style={{\n position: 'absolute',\n inset: 0,\n pointerEvents: 'none',\n visibility: 'hidden',\n }}\n />\n )\n}\n\n// ── Edge style resolver ──\n\nconst EDGE_TYPE_MAP: Record<string, string> = {\n step: 'step',\n smoothstep: 'smoothstep',\n bezier: 'default',\n default: 'default',\n}\n\nfunction applyEdgeStyles(\n edges: FlowEdge[],\n edgeTypeDefsMap?: Map<string, EdgeTypeDef>,\n): Edge[] {\n if (!edgeTypeDefsMap?.size) return edges as unknown as Edge[]\n\n return edges.map((edge) => {\n const slug = edge.edgeTypeSlug\n if (!slug) return edge as unknown as Edge\n\n const def = edgeTypeDefsMap.get(slug)\n if (!def) return edge as unknown as Edge\n\n const styled: Edge = { ...(edge as unknown as Edge) }\n\n // Edge type (line style) — canvas value takes precedence\n if (!styled.type && def.lineStyle) {\n styled.type = EDGE_TYPE_MAP[def.lineStyle] ?? 'default'\n }\n\n // Visual style — canvas style merged with def as fallback\n styled.style = {\n ...(def.color ? { stroke: def.color } : undefined),\n ...(def.strokeWidth ? { strokeWidth: def.strokeWidth } : undefined),\n ...edge.style,\n }\n\n // Animation — canvas value takes precedence\n if (styled.animated == null && def.animated) styled.animated = true\n\n // Markers — canvas value takes precedence over def\n if (!styled.markerStart) {\n const startType = toMarkerType(def.markerStart)\n if (startType) {\n styled.markerStart = {\n type: startType,\n ...(def.color ? { color: def.color } : undefined),\n }\n }\n }\n if (!styled.markerEnd) {\n const endType = toMarkerType(def.markerEnd)\n if (endType) {\n styled.markerEnd = {\n type: endType,\n ...(def.color ? { color: def.color } : undefined),\n }\n }\n }\n\n return styled\n })\n}\n\n// ── FlowRenderer ──\n\n/**\n * Renders a Flow canvas in read-only mode.\n *\n * Requires `@xyflow/react` peer dependency and its CSS:\n * ```ts\n * import '@xyflow/react/dist/style.css'\n * ```\n */\nexport interface FlowRendererProps {\n /** Canvas data from Flow document's `canvas` field */\n data: CanvasData\n /** Container className */\n className?: string\n /** Container style */\n style?: React.CSSProperties\n /** Custom renderers by node type slug (e.g., `{ 'product-card': MyProductCard }`) */\n nodeRenderers?: Record<string, React.ComponentType<DynamicNodeSlotProps>>\n /** Node type definitions for enhanced rendering (field-type-aware display) */\n nodeTypeDefs?: NodeTypeDef[]\n /** Edge type definitions for styled edges (color, stroke, markers, animation) */\n edgeTypeDefs?: EdgeTypeDef[]\n /** Show background pattern (default: false) */\n background?: boolean\n /** Allow user interaction - pan, zoom (default: false for read-only display) */\n interactive?: boolean\n /** Fit view on mount (default: true) */\n fitView?: boolean\n /** Called when a node is clicked */\n onNodeClick?: (event: React.MouseEvent, node: FlowNode) => void\n /** Called when a node is double-clicked */\n onNodeDoubleClick?: (event: React.MouseEvent, node: FlowNode) => void\n /** Called on node right-click / context menu */\n onNodeContextMenu?: (event: React.MouseEvent, node: FlowNode) => void\n /** Called when mouse enters a node */\n onNodeMouseEnter?: (event: React.MouseEvent, node: FlowNode) => void\n /** Called when mouse leaves a node */\n onNodeMouseLeave?: (event: React.MouseEvent, node: FlowNode) => void\n /** Called when an edge is clicked */\n onEdgeClick?: (event: React.MouseEvent, edge: FlowEdge) => void\n /** S1: Custom frame node renderer. Should be a stable reference (memoize or define outside render). */\n frameRenderer?: React.ComponentType<FrameNodeSlotProps>\n /** S2: Custom edge renderers by edge type slug. Should be a stable reference (memoize or define outside render). */\n edgeRenderers?: Record<string, React.ComponentType<EdgeSlotProps>>\n /** S3: Wraps every dynamic node's rendered content. Should be a stable reference (memoize or define outside render). */\n nodeWrapper?: React.ComponentType<NodeWrapperSlotProps>\n /** S4: Show controls (default: false) */\n controls?: boolean\n /** S4: Show minimap (default: false) */\n minimap?: boolean\n /** S4: Custom minimap node color function */\n minimapNodeColor?: (node: FlowNode) => string\n /** S4: Additional children rendered inside ReactFlow */\n children?: React.ReactNode\n /** S5: Global override for all dynamic nodes. `content` is the resolved rendering (custom renderer output or default). `props.defaultRender` contains the original template/field-based rendering. */\n renderNode?: (\n props: DynamicNodeSlotProps,\n content: React.ReactElement,\n ) => React.ReactElement | null\n /** S6: Called when viewport changes (pan/zoom) */\n onViewportChange?: (viewport: FlowViewport) => void\n /** S6: Default viewport (used when fitView is false) */\n defaultViewport?: FlowViewport\n /** S8: Focus on specific bounds (used for initial viewport fit). */\n bounds?: FlowBounds\n /** S8: Separate bounds for panning/zoom restriction. When set, overrides bounds-based translateExtent. Useful when fitBounds (content) differs from clampBounds (frame area). */\n clampBounds?: FlowBounds\n /** S8: Padding for focus bounds (default: 0.1) */\n focusPadding?: number\n /** S8: Animate focus transition (true=300ms, number=custom ms, false=instant) */\n focusAnimation?: boolean | number\n /** S8: Focus mode — \"contain\" fits entire bounds (may have margins), \"cover\" fills viewport (may crop). Default: \"contain\" */\n focusMode?: 'contain' | 'cover'\n /** Re-fit viewport on container resize (default: true when bounds is set) */\n responsiveFit?: boolean\n /** Override translateExtent directly. When set, overrides the automatic bounds-based panning restriction. */\n translateExtent?: [[number, number], [number, number]]\n /** Minimum zoom level. When clampBounds is set, automatically enforced as cover zoom (user cannot zoom out beyond the frame). */\n minZoom?: number\n /** Maximum zoom level */\n maxZoom?: number\n}\n\nexport function FlowRenderer({\n data,\n className,\n style,\n nodeRenderers,\n nodeTypeDefs,\n edgeTypeDefs,\n background = false,\n interactive = false,\n fitView = true,\n onNodeClick,\n onNodeDoubleClick,\n onNodeContextMenu,\n onNodeMouseEnter,\n onNodeMouseLeave,\n onEdgeClick,\n frameRenderer,\n edgeRenderers,\n nodeWrapper,\n controls,\n minimap,\n minimapNodeColor,\n children,\n renderNode,\n onViewportChange,\n defaultViewport: defaultViewportProp,\n bounds,\n clampBounds,\n focusPadding,\n focusAnimation,\n focusMode = 'contain',\n responsiveFit,\n translateExtent: translateExtentProp,\n minZoom: minZoomProp,\n maxZoom: maxZoomProp,\n}: FlowRendererProps) {\n const nodeTypeDefsMap = React.useMemo(() => {\n if (!nodeTypeDefs?.length) return undefined\n return new Map(nodeTypeDefs.map((d) => [d.slug, d]))\n }, [nodeTypeDefs])\n\n const edgeTypeDefsMap = React.useMemo(() => {\n if (!edgeTypeDefs?.length) return undefined\n return new Map(edgeTypeDefs.map((d) => [d.slug, d]))\n }, [edgeTypeDefs])\n\n const nodeTypes = React.useMemo(\n () =>\n createNodeTypes(\n nodeRenderers,\n nodeTypeDefsMap,\n frameRenderer,\n nodeWrapper,\n renderNode,\n ),\n [nodeRenderers, nodeTypeDefsMap, frameRenderer, nodeWrapper, renderNode],\n )\n\n // S2: Custom edge types\n const customEdgeTypes = React.useMemo(\n () => createEdgeTypes(edgeRenderers, edgeTypeDefsMap),\n [edgeRenderers, edgeTypeDefsMap],\n )\n\n // Merge all customCSS from node type definitions\n const mergedCSS = React.useMemo(() => {\n if (!nodeTypeDefs?.length) return ''\n return nodeTypeDefs\n .filter((d) => d.customCSS)\n .map((d) => d.customCSS)\n .join('\\n')\n }, [nodeTypeDefs])\n\n const styledEdges = React.useMemo(() => {\n let edges = applyEdgeStyles(data?.edges ?? [], edgeTypeDefsMap)\n // When custom edge renderers exist, set edge type to slug for matching\n if (edgeRenderers) {\n edges = edges.map((edge) => {\n const slug = (edge as unknown as FlowEdge).edgeTypeSlug\n if (slug && edgeRenderers[slug]) {\n return { ...edge, type: slug }\n }\n return edge\n })\n }\n return edges\n }, [data?.edges, edgeTypeDefsMap, edgeRenderers])\n\n // Panning restriction: explicit prop > clampBounds (no padding, hard boundary) > bounds (with padding)\n const translateExtent = React.useMemo(() => {\n if (translateExtentProp) return translateExtentProp\n const es = clampBounds ?? bounds\n if (!es) return undefined\n const ep = clampBounds ? 0 : (focusPadding ?? 0.1)\n return [\n [es.x - ep * es.width, es.y - ep * es.height],\n [es.x + es.width * (1 + ep), es.y + es.height * (1 + ep)],\n ] as [[number, number], [number, number]]\n }, [translateExtentProp, clampBounds, bounds, focusPadding])\n\n if (!data) return null\n\n const resolvedDefaultViewport =\n defaultViewportProp ??\n (!fitView && data.viewport ? data.viewport : undefined)\n\n return (\n <ReactFlowProvider>\n <div\n className={className}\n style={{\n width: '100%',\n height: '100%',\n background: 'transparent',\n ...style,\n }}\n >\n <ReactFlow\n nodes={\n (data.nodes ?? []) as unknown as Parameters<\n typeof ReactFlow\n >[0]['nodes']\n }\n edges={styledEdges}\n nodeTypes={nodeTypes}\n edgeTypes={\n customEdgeTypes as Parameters<typeof ReactFlow>[0]['edgeTypes']\n }\n defaultViewport={resolvedDefaultViewport}\n fitView={bounds ? false : fitView}\n translateExtent={translateExtent}\n onNodeClick={\n onNodeClick as Parameters<typeof ReactFlow>[0]['onNodeClick']\n }\n onNodeDoubleClick={\n onNodeDoubleClick as Parameters<\n typeof ReactFlow\n >[0]['onNodeDoubleClick']\n }\n onNodeContextMenu={\n onNodeContextMenu as Parameters<\n typeof ReactFlow\n >[0]['onNodeContextMenu']\n }\n onNodeMouseEnter={\n onNodeMouseEnter as Parameters<\n typeof ReactFlow\n >[0]['onNodeMouseEnter']\n }\n onNodeMouseLeave={\n onNodeMouseLeave as Parameters<\n typeof ReactFlow\n >[0]['onNodeMouseLeave']\n }\n onEdgeClick={\n onEdgeClick as Parameters<typeof ReactFlow>[0]['onEdgeClick']\n }\n onMoveEnd={\n onViewportChange\n ? (((_: unknown, vp: { x: number; y: number; zoom: number }) => {\n onViewportChange(vp)\n }) as Parameters<typeof ReactFlow>[0]['onMoveEnd'])\n : undefined\n }\n nodesDraggable={interactive}\n nodesConnectable={false}\n elementsSelectable={\n interactive ||\n !!onNodeClick ||\n !!onNodeDoubleClick ||\n !!onEdgeClick\n }\n panOnDrag={interactive}\n zoomOnScroll={interactive}\n zoomOnPinch={interactive}\n zoomOnDoubleClick={false}\n minZoom={minZoomProp}\n maxZoom={maxZoomProp}\n proOptions={{ hideAttribution: true }}\n >\n {mergedCSS && (\n <style dangerouslySetInnerHTML={{ __html: mergedCSS }} />\n )}\n {background && <Background />}\n {controls && <Controls />}\n {minimap && (\n <MiniMap\n nodeColor={\n minimapNodeColor as Parameters<typeof MiniMap>[0]['nodeColor']\n }\n />\n )}\n {bounds && (\n <FocusHandler\n bounds={bounds}\n padding={focusPadding ?? 0.1}\n animation={focusAnimation ?? true}\n mode={focusMode}\n responsive={responsiveFit ?? true}\n extent={translateExtent}\n clampBounds={clampBounds}\n minZoomProp={minZoomProp}\n />\n )}\n {children}\n </ReactFlow>\n </div>\n </ReactFlowProvider>\n )\n}\n","import type React from 'react'\n\n// ── Dynamic node data ──\n\nexport interface DynamicNodeData {\n nodeTypeSlug: string\n label: string\n fields: Record<string, unknown>\n}\n\nexport type FlowNodeData = (DynamicNodeData | FrameNodeData) &\n Record<string, unknown>\n\n// ── Canvas types (mirrors @xyflow/react but standalone) ──\n\nexport interface FlowNodePosition {\n x: number\n y: number\n}\n\nexport interface FlowNode {\n id: string\n type?: string\n position: FlowNodePosition\n data: FlowNodeData\n parentId?: string\n style?: React.CSSProperties\n width?: number\n height?: number\n measured?: { width?: number; height?: number }\n draggable?: boolean\n selectable?: boolean\n [key: string]: unknown\n}\n\nexport interface FlowEdge {\n id: string\n source: string\n target: string\n sourceHandle?: string | null\n targetHandle?: string | null\n type?: string\n style?: React.CSSProperties\n animated?: boolean\n markerStart?: unknown\n markerEnd?: unknown\n edgeTypeSlug?: string\n fields?: Record<string, unknown>\n [key: string]: unknown\n}\n\nexport interface FlowViewport {\n x: number\n y: number\n zoom: number\n}\n\nexport interface CanvasData {\n nodes: FlowNode[]\n edges: FlowEdge[]\n viewport: FlowViewport\n}\n\n// ── Node type definitions (mirrors console's NodeTypeDef) ──\n\nexport interface NodeTypeFieldDef {\n name: string\n label: string\n fieldType:\n | 'text'\n | 'textarea'\n | 'number'\n | 'url'\n | 'color'\n | 'image'\n | 'select'\n | 'toggle'\n options?: { label: string; value: string }[]\n defaultValue?: string\n required?: boolean\n}\n\nexport interface NodeTypeDef {\n slug: string\n name: string\n color: string\n defaultSize: { width: number; height: number }\n fields: NodeTypeFieldDef[]\n transparentBackground?: boolean\n template?: string | null\n customCSS?: string | null\n}\n\n// ── Edge type definitions (mirrors console's EdgeTypeDef) ──\n\nexport interface EdgeTypeDef {\n slug: string\n name: string\n color: string\n strokeWidth: number\n animated: boolean\n lineStyle: string\n markerStart: string\n markerEnd: string\n fields: NodeTypeFieldDef[]\n}\n\n// ── Type guards ──\n\nexport function isDynamicNode(\n node: FlowNode,\n): node is FlowNode & { data: DynamicNodeData } {\n return node.type === 'dynamic'\n}\n\nexport function isFrameNode(\n node: FlowNode,\n): node is FlowNode & { data: FrameNodeData } {\n return node.type === 'frame'\n}\n\n// ── Component slot props ──\n\nexport interface DynamicNodeSlotProps {\n id: string\n nodeTypeSlug: string\n label: string\n fields: Record<string, unknown>\n nodeTypeDef?: NodeTypeDef\n /** Whether this node is currently selected */\n selected?: boolean\n /** Measured node width (undefined before first measurement) */\n width?: number\n /** Measured node height (undefined before first measurement) */\n height?: number\n /** The default rendering (template or field-based). Allows custom renderers to wrap/extend instead of replacing entirely. */\n defaultRender?: React.ReactElement\n}\n\n// ── Frame node data ──\n\nexport interface FrameNodeData {\n label: string\n color?: string\n padding?: number\n borderStyle?: 'dashed' | 'solid' | 'none'\n opacity?: number\n}\n\n// S1: Frame renderer slot\nexport interface FrameNodeSlotProps {\n id: string\n label: string\n color?: string\n padding?: number\n borderStyle?: 'dashed' | 'solid' | 'none'\n opacity?: number\n width?: number\n height?: number\n children?: React.ReactNode\n}\n\n// S2: Edge renderer slot\nexport interface EdgeSlotProps {\n id: string\n edgeTypeSlug?: string\n source: string\n target: string\n label?: string\n fields?: Record<string, unknown>\n edgeTypeDef?: EdgeTypeDef\n style?: React.CSSProperties\n}\n\n// S3: Node wrapper slot\nexport interface NodeWrapperSlotProps {\n id: string\n nodeTypeSlug: string\n label: string\n selected?: boolean\n nodeTypeDef?: NodeTypeDef\n children: React.ReactNode\n}\n\n// S8: Viewport focus\nexport interface FlowBounds {\n x: number\n y: number\n width: number\n height: number\n}\n","import type { NodeTypeDef } from './types'\n\nexport const BUILT_IN_NODE_TYPES: NodeTypeDef[] = [\n {\n slug: 'text',\n name: 'Text',\n color: '#e5e7eb',\n defaultSize: { width: 200, height: 200 },\n fields: [{ name: 'body', label: 'Body', fieldType: 'textarea' }],\n },\n {\n slug: 'image',\n name: 'Image',\n color: '#e5e7eb',\n transparentBackground: true,\n defaultSize: { width: 200, height: 200 },\n fields: [\n { name: 'image', label: 'Image', fieldType: 'image' },\n { name: 'alt', label: 'Alt Text', fieldType: 'text' },\n { name: 'caption', label: 'Caption', fieldType: 'text' },\n ],\n },\n]\n","import type { EdgeTypeDef } from './types'\n\nexport const BUILT_IN_EDGE_TYPES: EdgeTypeDef[] = [\n {\n slug: 'default',\n name: 'Default',\n color: '',\n strokeWidth: 2,\n animated: false,\n lineStyle: 'default',\n markerStart: 'none',\n markerEnd: 'arrow',\n fields: [],\n },\n]\n","'use client'\n\nimport { useQuery, type QueryClient } from '@tanstack/react-query'\nimport { useMemo } from 'react'\nimport type { CanvasData, NodeTypeDef, EdgeTypeDef } from './types'\nimport { BUILT_IN_NODE_TYPES } from './built-in-node-types'\nimport { BUILT_IN_EDGE_TYPES } from './built-in-edge-types'\nimport { collectionKeys } from '../../core/query/query-keys'\n\n// ── Client interface ──\n// Structurally compatible with both BrowserClient and ServerClient.\n// Lists only the collections useFlow actually queries so the generic\n// `from<T extends PublicCollection>` on the real clients satisfies this.\n\ntype FlowCollection = 'flows' | 'flow-node-types' | 'flow-edge-types'\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype AnyFn = (...args: any[]) => any\n\nexport interface SDKClient {\n from(collection: FlowCollection): {\n find: AnyFn\n findById: AnyFn\n }\n queryClient: QueryClient\n}\n\n// ── Options & Result ──\n\nexport interface UseFlowOptions {\n /** SDK client instance (BrowserClient or ServerClient) */\n client: SDKClient\n /** Flow slug (URL-friendly identifier) */\n slug?: string\n /** Flow document ID (UUID) */\n id?: string\n /** Enable/disable data fetching (default: true) */\n enabled?: boolean\n}\n\nexport interface UseFlowResult {\n data: CanvasData | undefined\n nodeTypeDefs: NodeTypeDef[]\n edgeTypeDefs: EdgeTypeDef[]\n flow: Record<string, unknown> | undefined\n isLoading: boolean\n error: Error | null\n}\n\n// ── Helpers ──\n\nfunction toNodeTypeDef(doc: Record<string, unknown>): NodeTypeDef {\n return {\n slug: String(doc.slug ?? ''),\n name: String(doc.title ?? ''),\n color: String(doc.color ?? '#e5e7eb'),\n defaultSize: (doc.defaultSize as NodeTypeDef['defaultSize']) ?? {\n width: 200,\n height: 200,\n },\n fields: Array.isArray(doc.fields)\n ? (doc.fields as NodeTypeDef['fields'])\n : [],\n transparentBackground: Boolean(doc.transparentBackground),\n template: (doc.template as string) ?? null,\n customCSS: (doc.customCSS as string) ?? null,\n }\n}\n\nfunction toEdgeTypeDef(doc: Record<string, unknown>): EdgeTypeDef {\n return {\n slug: String(doc.slug ?? ''),\n name: String(doc.title ?? ''),\n color: String(doc.color ?? ''),\n strokeWidth: (doc.strokeWidth as number) ?? 2,\n animated: (doc.animated as boolean) ?? false,\n lineStyle: String(doc.lineStyle ?? 'default'),\n markerStart: String(doc.markerStart ?? 'none'),\n markerEnd: String(doc.markerEnd ?? 'arrow'),\n fields: Array.isArray(doc.fields)\n ? (doc.fields as EdgeTypeDef['fields'])\n : [],\n }\n}\n\n// ── Hook ──\n\nexport function useFlow(options: UseFlowOptions): UseFlowResult {\n const { client, slug, id, enabled = true } = options\n const hasIdentifier = !!(slug || id)\n const identifier = id ?? slug ?? ''\n\n // Fetch flow document\n const flowQuery = useQuery<Record<string, unknown>>(\n {\n queryKey: collectionKeys('flows').detail(identifier),\n queryFn: async () => {\n if (id) {\n return client.from('flows').findById(id)\n }\n const result = await client.from('flows').find({\n where: { slug: { equals: slug } },\n limit: 1,\n })\n const doc = result.docs[0]\n if (!doc) throw new Error(`Flow not found: ${slug}`)\n return doc\n },\n enabled: enabled && hasIdentifier,\n },\n client.queryClient,\n )\n\n // Fetch tenant's custom node types\n const nodeTypesQuery = useQuery<Record<string, unknown>[]>(\n {\n queryKey: collectionKeys('flow-node-types').lists(),\n queryFn: async () => {\n const result = await client.from('flow-node-types').find({ limit: 100 })\n return result.docs\n },\n enabled,\n },\n client.queryClient,\n )\n\n // Fetch tenant's custom edge types\n const edgeTypesQuery = useQuery<Record<string, unknown>[]>(\n {\n queryKey: collectionKeys('flow-edge-types').lists(),\n queryFn: async () => {\n const result = await client.from('flow-edge-types').find({ limit: 100 })\n return result.docs\n },\n enabled,\n },\n client.queryClient,\n )\n\n // Merge built-in + API node types\n const nodeTypeDefs = useMemo<NodeTypeDef[]>(() => {\n const apiDefs = (nodeTypesQuery.data ?? []).map(toNodeTypeDef)\n const builtInSlugs = new Set(BUILT_IN_NODE_TYPES.map((t) => t.slug))\n const customDefs = apiDefs.filter((d) => !builtInSlugs.has(d.slug))\n return [...BUILT_IN_NODE_TYPES, ...customDefs]\n }, [nodeTypesQuery.data])\n\n // Merge built-in + API edge types\n const edgeTypeDefs = useMemo<EdgeTypeDef[]>(() => {\n const apiDefs = (edgeTypesQuery.data ?? []).map(toEdgeTypeDef)\n const builtInSlugs = new Set(BUILT_IN_EDGE_TYPES.map((t) => t.slug))\n const customDefs = apiDefs.filter((d) => !builtInSlugs.has(d.slug))\n return [...BUILT_IN_EDGE_TYPES, ...customDefs]\n }, [edgeTypesQuery.data])\n\n const flow = flowQuery.data\n const canvas = flow?.canvas as CanvasData | undefined\n\n return {\n data: canvas,\n nodeTypeDefs,\n edgeTypeDefs,\n flow,\n isLoading:\n flowQuery.isLoading ||\n nodeTypesQuery.isLoading ||\n edgeTypesQuery.isLoading,\n error:\n (flowQuery.error as Error | null) ??\n (nodeTypesQuery.error as Error | null) ??\n (edgeTypesQuery.error as Error | null),\n }\n}\n","import type { PublicCollection, ApiQueryOptions } from '../client/types'\n\nexport function collectionKeys<T extends PublicCollection>(collection: T) {\n return {\n all: [collection] as const,\n lists: () => [collection, 'list'] as const,\n list: (options?: ApiQueryOptions) => [collection, 'list', options] as const,\n details: () => [collection, 'detail'] as const,\n detail: (id: string, options?: ApiQueryOptions) =>\n [collection, 'detail', id, options] as const,\n infinites: () => [collection, 'infinite'] as const,\n infinite: (options?: Omit<ApiQueryOptions, 'page'>) =>\n [collection, 'infinite', options] as const,\n }\n}\n\nexport const customerKeys = {\n all: ['customer'] as const,\n me: () => ['customer', 'me'] as const,\n}\n","import { useMemo } from 'react'\nimport type { CanvasData, FlowNode, NodeTypeDef, EdgeTypeDef } from './types'\nimport type { Edge } from '@xyflow/react'\nimport { BUILT_IN_NODE_TYPES } from './built-in-node-types'\nimport { BUILT_IN_EDGE_TYPES } from './built-in-edge-types'\n\n// ── Options & Result ──\n\nexport interface UseFlowDataOptions {\n /** Canvas data from Flow document's `canvas` field */\n data: CanvasData | undefined\n /** Node type definitions (defaults to built-in types) */\n nodeTypeDefs?: NodeTypeDef[]\n /** Edge type definitions (defaults to built-in types) */\n edgeTypeDefs?: EdgeTypeDef[]\n}\n\nexport interface UseFlowDataResult {\n /** Nodes from canvas data */\n nodes: FlowNode[]\n /** Edges from canvas data (typed for @xyflow/react) */\n edges: Edge[]\n /** Map of node type slug to definition */\n nodeTypeDefsMap: Map<string, NodeTypeDef>\n /** Map of edge type slug to definition */\n edgeTypeDefsMap: Map<string, EdgeTypeDef>\n}\n\n/**\n * Pure data transformation hook — extracts nodes, edges, and type definition\n * maps from canvas data without any rendering. Useful for headless usage\n * (custom layouts, analytics, server-side processing).\n */\nexport function useFlowData(options: UseFlowDataOptions): UseFlowDataResult {\n const { data, nodeTypeDefs: inputNodeDefs, edgeTypeDefs: inputEdgeDefs } =\n options\n\n const nodeTypeDefsMap = useMemo(() => {\n const allDefs = inputNodeDefs ?? BUILT_IN_NODE_TYPES\n return new Map(allDefs.map((d) => [d.slug, d]))\n }, [inputNodeDefs])\n\n const edgeTypeDefsMap = useMemo(() => {\n const allDefs = inputEdgeDefs ?? BUILT_IN_EDGE_TYPES\n return new Map(allDefs.map((d) => [d.slug, d]))\n }, [inputEdgeDefs])\n\n const nodes = useMemo(() => data?.nodes ?? [], [data?.nodes])\n const edges = useMemo(() => (data?.edges ?? []) as unknown as Edge[], [data?.edges])\n\n return {\n nodes,\n edges,\n nodeTypeDefsMap,\n edgeTypeDefsMap,\n }\n}\n","import type { FlowNode, FlowEdge, FlowBounds, CanvasData } from './types'\n\n// ── Shared helpers ──\n\nfunction getNodeSize(node: FlowNode): { width: number; height: number } {\n return {\n width:\n (node.style?.width as number) ??\n node.measured?.width ??\n node.width ??\n 200,\n height:\n (node.style?.height as number) ??\n node.measured?.height ??\n node.height ??\n 200,\n }\n}\n\nfunction getAbsolutePosition(\n node: FlowNode,\n nodeMap: Map<string, FlowNode>,\n): { x: number; y: number } {\n let x = node.position.x\n let y = node.position.y\n let current = node\n const visited = new Set<string>([node.id])\n while (current.parentId) {\n const parentId = current.parentId\n if (visited.has(parentId)) break\n const parent = nodeMap.get(parentId)\n if (!parent) break\n visited.add(parent.id)\n x += parent.position.x\n y += parent.position.y\n current = parent\n }\n return { x, y }\n}\n\n/** Collect a node and all its descendants (BFS with index pointer to avoid O(Q²) shift). */\nfunction collectDescendants(\n nodes: FlowNode[],\n rootId: string,\n): Set<string> {\n const result = new Set<string>([rootId])\n const queue = [rootId]\n let i = 0\n while (i < queue.length) {\n const current = queue[i++]\n for (const n of nodes) {\n if (n.parentId === current && !result.has(n.id)) {\n result.add(n.id)\n queue.push(n.id)\n }\n }\n }\n return result\n}\n\n// ── Public utilities ──\n\n/**\n * Calculate bounding box for given node IDs.\n * Pure function — usable in SSR, server components, or outside React.\n */\nexport function getNodeBounds(\n nodes: FlowNode[],\n nodeIds: string[],\n): FlowBounds | undefined {\n const idSet = new Set(nodeIds)\n const targetNodes = nodes.filter((n) => idSet.has(n.id))\n if (targetNodes.length === 0) return undefined\n\n const nodeMap = new Map(nodes.map((n) => [n.id, n]))\n\n let minX = Infinity\n let minY = Infinity\n let maxX = -Infinity\n let maxY = -Infinity\n\n for (const node of targetNodes) {\n const abs = getAbsolutePosition(node, nodeMap)\n const { width: w, height: h } = getNodeSize(node)\n minX = Math.min(minX, abs.x)\n minY = Math.min(minY, abs.y)\n maxX = Math.max(maxX, abs.x + w)\n maxY = Math.max(maxY, abs.y + h)\n }\n\n return { x: minX, y: minY, width: maxX - minX, height: maxY - minY }\n}\n\n/**\n * Get all frame nodes with their bounds.\n * Sorted by position (top-left to bottom-right).\n */\nexport function getFrames(\n nodes: FlowNode[],\n): Array<{ id: string; label: string; bounds: FlowBounds }> {\n const frames = nodes.filter((n) => n.type === 'frame')\n if (frames.length === 0) return []\n\n const nodeMap = new Map(nodes.map((n) => [n.id, n]))\n\n return frames\n .map((f) => {\n const data = f.data as { label?: string }\n const abs = getAbsolutePosition(f, nodeMap)\n const { width: w, height: h } = getNodeSize(f)\n return {\n id: f.id,\n label: data.label ?? '',\n bounds: { x: abs.x, y: abs.y, width: w, height: h },\n }\n })\n .sort((a, b) => a.bounds.y - b.bounds.y || a.bounds.x - b.bounds.x)\n}\n\n/** Result of getFrameData — contains filtered canvas + dual bounds. */\nexport interface FrameData {\n /** Canvas data containing only the frame's descendants (nodes have draggable: false). */\n data: CanvasData\n /** Bounding box of child content nodes — use for initial viewport fit (centering). */\n fitBounds: FlowBounds\n /** Bounding box of the frame itself — use for panning/zoom restriction (clamp). */\n clampBounds: FlowBounds\n /** @deprecated Use fitBounds instead. Alias for clampBounds for backward compatibility. */\n bounds: FlowBounds\n}\n\n/**\n * Extract a frame's descendants and related edges from canvas data.\n * Recursively collects all nested children (supports nested frames).\n * Returns undefined if frameId is not found or is not a frame node.\n *\n * Child nodes are marked `draggable: false` to prevent interfering with canvas panning.\n * The frame node itself is included (use `frameRenderer={() => null}` to hide it).\n *\n * Returns dual bounds:\n * - `fitBounds`: child content bounding box (for centering the viewport)\n * - `clampBounds`: frame area bounding box (for panning restriction)\n */\nexport function getFrameData(\n data: CanvasData,\n frameId: string,\n): FrameData | undefined {\n const frame = data.nodes.find((n) => n.id === frameId)\n if (!frame || frame.type !== 'frame') return undefined\n\n // Recursively collect frame + all descendants\n const descendantIds = collectDescendants(data.nodes, frameId)\n const childNodes = data.nodes\n .filter((n) => descendantIds.has(n.id))\n .map((n) => ({ ...n, draggable: false }))\n\n // Keep only edges where both source and target are within the frame\n const childEdges = data.edges.filter(\n (e: FlowEdge) => descendantIds.has(e.source) && descendantIds.has(e.target),\n )\n\n // clampBounds: frame's own bounding box (for panning restriction)\n const frameBounds = getNodeBounds(data.nodes, [frameId])\n const { width: w, height: h } = getNodeSize(frame)\n const clampBounds: FlowBounds = frameBounds ?? {\n x: frame.position.x,\n y: frame.position.y,\n width: w,\n height: h,\n }\n\n // fitBounds: child content bounding box (for centering)\n const contentNodeIds = childNodes\n .filter((n) => n.id !== frameId)\n .map((n) => n.id)\n const contentBounds = contentNodeIds.length > 0\n ? getNodeBounds(data.nodes, contentNodeIds)\n : undefined\n const fitBounds = contentBounds ?? clampBounds\n\n return {\n data: {\n nodes: childNodes,\n edges: childEdges,\n viewport: data.viewport,\n },\n fitBounds,\n clampBounds,\n bounds: clampBounds,\n }\n}\n","'use client'\n\nimport React from 'react'\nimport { transform } from 'sucrase'\n\nexport interface CodeComponentProps {\n fields: Record<string, unknown>\n label: string\n color: string\n nodeTypeSlug: string\n width: number\n height: number\n}\n\nconst MAX_CACHE_SIZE = 100\nconst componentCache = new Map<string, React.FC<CodeComponentProps>>()\n\nfunction hashCode(str: string): string {\n let hash = 0\n for (let i = 0; i < str.length; i++) {\n const char = str.charCodeAt(i)\n hash = ((hash << 5) - hash + char) | 0\n }\n return hash.toString(36)\n}\n\nconst BLOCKED_PATTERNS = [\n /\\bdocument\\s*\\./,\n /\\bwindow\\s*\\./,\n /\\bwindow\\s*\\[/,\n /\\bglobalThis\\s*\\./,\n /\\bfetch\\s*\\(/,\n /\\bXMLHttpRequest/,\n /\\beval\\s*\\(/,\n /\\bFunction\\s*\\(/,\n /\\bimport\\s*\\(/,\n /\\blocalStorage/,\n /\\bsessionStorage/,\n /\\bcookie/,\n /\\bpostMessage\\s*\\(/,\n /\\blocation\\s*[.=]/,\n /\\bnavigator\\s*\\./,\n /\\bsetTimeout\\s*\\(/,\n /\\bsetInterval\\s*\\(/,\n /\\bsetImmediate\\s*\\(/,\n /\\brequire\\s*\\(/,\n]\n\nfunction validateTemplateCode(code: string): boolean {\n return !BLOCKED_PATTERNS.some((pattern) => pattern.test(code))\n}\n\nexport function compileTemplate(\n code: string,\n slug: string,\n): React.FC<CodeComponentProps> | null {\n const cacheKey = `${slug}:${hashCode(code)}`\n\n if (componentCache.has(cacheKey)) {\n const cached = componentCache.get(cacheKey)!\n componentCache.delete(cacheKey)\n componentCache.set(cacheKey, cached)\n return cached\n }\n\n if (!validateTemplateCode(code)) {\n console.warn(`[flow] Template \"${slug}\" contains blocked patterns`)\n return null\n }\n\n try {\n const { code: jsCode } = transform(code, {\n transforms: ['typescript', 'jsx', 'imports'],\n jsxRuntime: 'classic',\n jsxPragma: 'React.createElement',\n jsxFragmentPragma: 'React.Fragment',\n })\n\n // Shadow dangerous globals to neutralize blocklist bypasses\n const factory = new Function(\n 'React',\n `\n var window = undefined;\n var document = undefined;\n var globalThis = undefined;\n var setTimeout = undefined;\n var setInterval = undefined;\n var setImmediate = undefined;\n var fetch = undefined;\n var XMLHttpRequest = undefined;\n var navigator = undefined;\n var location = undefined;\n var exports = {};\n var module = { exports: exports };\n ${jsCode}\n return module.exports.default || module.exports;\n `,\n )\n\n const Component = factory(React)\n if (typeof Component !== 'function') return null\n\n if (componentCache.size >= MAX_CACHE_SIZE) {\n const oldestKey = componentCache.keys().next().value\n if (oldestKey) componentCache.delete(oldestKey)\n }\n\n componentCache.set(cacheKey, Component)\n return Component\n } catch (e) {\n console.warn(`[flow] Failed to compile template for \"${slug}\":`, e)\n return null\n }\n}\n\nexport function clearTemplateCache(): void {\n componentCache.clear()\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEA,OAAOA,YAAW;AAClB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAIK;;;AC8FA,SAAS,cACd,MAC8C;AAC9C,SAAO,KAAK,SAAS;AACvB;AAEO,SAAS,YACd,MAC4C;AAC5C,SAAO,KAAK,SAAS;AACvB;;;ACrHO,IAAM,sBAAqC;AAAA,EAChD;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AAAA,IACN,OAAO;AAAA,IACP,aAAa,EAAE,OAAO,KAAK,QAAQ,IAAI;AAAA,IACvC,QAAQ,CAAC,EAAE,MAAM,QAAQ,OAAO,QAAQ,WAAW,WAAW,CAAC;AAAA,EACjE;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AAAA,IACN,OAAO;AAAA,IACP,uBAAuB;AAAA,IACvB,aAAa,EAAE,OAAO,KAAK,QAAQ,IAAI;AAAA,IACvC,QAAQ;AAAA,MACN,EAAE,MAAM,SAAS,OAAO,SAAS,WAAW,QAAQ;AAAA,MACpD,EAAE,MAAM,OAAO,OAAO,YAAY,WAAW,OAAO;AAAA,MACpD,EAAE,MAAM,WAAW,OAAO,WAAW,WAAW,OAAO;AAAA,IACzD;AAAA,EACF;AACF;;;ACpBO,IAAM,sBAAqC;AAAA,EAChD;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AAAA,IACN,OAAO;AAAA,IACP,aAAa;AAAA,IACb,UAAU;AAAA,IACV,WAAW;AAAA,IACX,aAAa;AAAA,IACb,WAAW;AAAA,IACX,QAAQ,CAAC;AAAA,EACX;AACF;;;ACZA,SAAS,gBAAkC;AAC3C,SAAS,eAAe;;;ACDjB,SAAS,eAA2C,YAAe;AACxE,SAAO;AAAA,IACL,KAAK,CAAC,UAAU;AAAA,IAChB,OAAO,MAAM,CAAC,YAAY,MAAM;AAAA,IAChC,MAAM,CAAC,YAA8B,CAAC,YAAY,QAAQ,OAAO;AAAA,IACjE,SAAS,MAAM,CAAC,YAAY,QAAQ;AAAA,IACpC,QAAQ,CAAC,IAAY,YACnB,CAAC,YAAY,UAAU,IAAI,OAAO;AAAA,IACpC,WAAW,MAAM,CAAC,YAAY,UAAU;AAAA,IACxC,UAAU,CAAC,YACT,CAAC,YAAY,YAAY,OAAO;AAAA,EACpC;AACF;;;ADqCA,SAAS,cAAc,KAA2C;AAnDlE;AAoDE,SAAO;AAAA,IACL,MAAM,QAAO,SAAI,SAAJ,YAAY,EAAE;AAAA,IAC3B,MAAM,QAAO,SAAI,UAAJ,YAAa,EAAE;AAAA,IAC5B,OAAO,QAAO,SAAI,UAAJ,YAAa,SAAS;AAAA,IACpC,cAAc,SAAI,gBAAJ,YAAkD;AAAA,MAC9D,OAAO;AAAA,MACP,QAAQ;AAAA,IACV;AAAA,IACA,QAAQ,MAAM,QAAQ,IAAI,MAAM,IAC3B,IAAI,SACL,CAAC;AAAA,IACL,uBAAuB,QAAQ,IAAI,qBAAqB;AAAA,IACxD,WAAW,SAAI,aAAJ,YAA2B;AAAA,IACtC,YAAY,SAAI,cAAJ,YAA4B;AAAA,EAC1C;AACF;AAEA,SAAS,cAAc,KAA2C;AArElE;AAsEE,SAAO;AAAA,IACL,MAAM,QAAO,SAAI,SAAJ,YAAY,EAAE;AAAA,IAC3B,MAAM,QAAO,SAAI,UAAJ,YAAa,EAAE;AAAA,IAC5B,OAAO,QAAO,SAAI,UAAJ,YAAa,EAAE;AAAA,IAC7B,cAAc,SAAI,gBAAJ,YAA8B;AAAA,IAC5C,WAAW,SAAI,aAAJ,YAA4B;AAAA,IACvC,WAAW,QAAO,SAAI,cAAJ,YAAiB,SAAS;AAAA,IAC5C,aAAa,QAAO,SAAI,gBAAJ,YAAmB,MAAM;AAAA,IAC7C,WAAW,QAAO,SAAI,cAAJ,YAAiB,OAAO;AAAA,IAC1C,QAAQ,MAAM,QAAQ,IAAI,MAAM,IAC3B,IAAI,SACL,CAAC;AAAA,EACP;AACF;AAIO,SAAS,QAAQ,SAAwC;AAvFhE;AAwFE,QAAM,EAAE,QAAQ,MAAM,IAAI,UAAU,KAAK,IAAI;AAC7C,QAAM,gBAAgB,CAAC,EAAE,QAAQ;AACjC,QAAM,cAAa,uBAAM,SAAN,YAAc;AAGjC,QAAM,YAAY;AAAA,IAChB;AAAA,MACE,UAAU,eAAe,OAAO,EAAE,OAAO,UAAU;AAAA,MACnD,SAAS,MAAY;AACnB,YAAI,IAAI;AACN,iBAAO,OAAO,KAAK,OAAO,EAAE,SAAS,EAAE;AAAA,QACzC;AACA,cAAM,SAAS,MAAM,OAAO,KAAK,OAAO,EAAE,KAAK;AAAA,UAC7C,OAAO,EAAE,MAAM,EAAE,QAAQ,KAAK,EAAE;AAAA,UAChC,OAAO;AAAA,QACT,CAAC;AACD,cAAM,MAAM,OAAO,KAAK,CAAC;AACzB,YAAI,CAAC,IAAK,OAAM,IAAI,MAAM,mBAAmB,IAAI,EAAE;AACnD,eAAO;AAAA,MACT;AAAA,MACA,SAAS,WAAW;AAAA,IACtB;AAAA,IACA,OAAO;AAAA,EACT;AAGA,QAAM,iBAAiB;AAAA,IACrB;AAAA,MACE,UAAU,eAAe,iBAAiB,EAAE,MAAM;AAAA,MAClD,SAAS,MAAY;AACnB,cAAM,SAAS,MAAM,OAAO,KAAK,iBAAiB,EAAE,KAAK,EAAE,OAAO,IAAI,CAAC;AACvE,eAAO,OAAO;AAAA,MAChB;AAAA,MACA;AAAA,IACF;AAAA,IACA,OAAO;AAAA,EACT;AAGA,QAAM,iBAAiB;AAAA,IACrB;AAAA,MACE,UAAU,eAAe,iBAAiB,EAAE,MAAM;AAAA,MAClD,SAAS,MAAY;AACnB,cAAM,SAAS,MAAM,OAAO,KAAK,iBAAiB,EAAE,KAAK,EAAE,OAAO,IAAI,CAAC;AACvE,eAAO,OAAO;AAAA,MAChB;AAAA,MACA;AAAA,IACF;AAAA,IACA,OAAO;AAAA,EACT;AAGA,QAAM,eAAe,QAAuB,MAAM;AA5IpD,QAAAC;AA6II,UAAM,YAAWA,MAAA,eAAe,SAAf,OAAAA,MAAuB,CAAC,GAAG,IAAI,aAAa;AAC7D,UAAM,eAAe,IAAI,IAAI,oBAAoB,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC;AACnE,UAAM,aAAa,QAAQ,OAAO,CAAC,MAAM,CAAC,aAAa,IAAI,EAAE,IAAI,CAAC;AAClE,WAAO,CAAC,GAAG,qBAAqB,GAAG,UAAU;AAAA,EAC/C,GAAG,CAAC,eAAe,IAAI,CAAC;AAGxB,QAAM,eAAe,QAAuB,MAAM;AApJpD,QAAAA;AAqJI,UAAM,YAAWA,MAAA,eAAe,SAAf,OAAAA,MAAuB,CAAC,GAAG,IAAI,aAAa;AAC7D,UAAM,eAAe,IAAI,IAAI,oBAAoB,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC;AACnE,UAAM,aAAa,QAAQ,OAAO,CAAC,MAAM,CAAC,aAAa,IAAI,EAAE,IAAI,CAAC;AAClE,WAAO,CAAC,GAAG,qBAAqB,GAAG,UAAU;AAAA,EAC/C,GAAG,CAAC,eAAe,IAAI,CAAC;AAExB,QAAM,OAAO,UAAU;AACvB,QAAM,SAAS,6BAAM;AAErB,SAAO;AAAA,IACL,MAAM;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,IACA,WACE,UAAU,aACV,eAAe,aACf,eAAe;AAAA,IACjB,QACG,qBAAU,UAAV,YACA,eAAe,UADf,YAEA,eAAe;AAAA,EACpB;AACF;;;AE5KA,SAAS,WAAAC,gBAAe;AAiCjB,SAAS,YAAY,SAAgD;AAC1E,QAAM,EAAE,MAAM,cAAc,eAAe,cAAc,cAAc,IACrE;AAEF,QAAM,kBAAkBC,SAAQ,MAAM;AACpC,UAAM,UAAU,wCAAiB;AACjC,WAAO,IAAI,IAAI,QAAQ,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;AAAA,EAChD,GAAG,CAAC,aAAa,CAAC;AAElB,QAAM,kBAAkBA,SAAQ,MAAM;AACpC,UAAM,UAAU,wCAAiB;AACjC,WAAO,IAAI,IAAI,QAAQ,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;AAAA,EAChD,GAAG,CAAC,aAAa,CAAC;AAElB,QAAM,QAAQA,SAAQ,MAAG;AA/C3B;AA+C8B,8CAAM,UAAN,YAAe,CAAC;AAAA,KAAG,CAAC,6BAAM,KAAK,CAAC;AAC5D,QAAM,QAAQA,SAAQ,MAAG;AAhD3B;AAgD+B,8CAAM,UAAN,YAAe,CAAC;AAAA,KAAyB,CAAC,6BAAM,KAAK,CAAC;AAEnF,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;ACpDA,SAAS,YAAY,MAAmD;AAJxE;AAKE,SAAO;AAAA,IACL,QACG,4BAAK,UAAL,mBAAY,UAAZ,aACD,UAAK,aAAL,mBAAe,UADd,YAED,KAAK,UAFJ,YAGD;AAAA,IACF,SACG,4BAAK,UAAL,mBAAY,WAAZ,aACD,UAAK,aAAL,mBAAe,WADd,YAED,KAAK,WAFJ,YAGD;AAAA,EACJ;AACF;AAEA,SAAS,oBACP,MACA,SAC0B;AAC1B,MAAI,IAAI,KAAK,SAAS;AACtB,MAAI,IAAI,KAAK,SAAS;AACtB,MAAI,UAAU;AACd,QAAM,UAAU,oBAAI,IAAY,CAAC,KAAK,EAAE,CAAC;AACzC,SAAO,QAAQ,UAAU;AACvB,UAAM,WAAW,QAAQ;AACzB,QAAI,QAAQ,IAAI,QAAQ,EAAG;AAC3B,UAAM,SAAS,QAAQ,IAAI,QAAQ;AACnC,QAAI,CAAC,OAAQ;AACb,YAAQ,IAAI,OAAO,EAAE;AACrB,SAAK,OAAO,SAAS;AACrB,SAAK,OAAO,SAAS;AACrB,cAAU;AAAA,EACZ;AACA,SAAO,EAAE,GAAG,EAAE;AAChB;AAGA,SAAS,mBACP,OACA,QACa;AACb,QAAM,SAAS,oBAAI,IAAY,CAAC,MAAM,CAAC;AACvC,QAAM,QAAQ,CAAC,MAAM;AACrB,MAAI,IAAI;AACR,SAAO,IAAI,MAAM,QAAQ;AACvB,UAAM,UAAU,MAAM,GAAG;AACzB,eAAW,KAAK,OAAO;AACrB,UAAI,EAAE,aAAa,WAAW,CAAC,OAAO,IAAI,EAAE,EAAE,GAAG;AAC/C,eAAO,IAAI,EAAE,EAAE;AACf,cAAM,KAAK,EAAE,EAAE;AAAA,MACjB;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAQO,SAAS,cACd,OACA,SACwB;AACxB,QAAM,QAAQ,IAAI,IAAI,OAAO;AAC7B,QAAM,cAAc,MAAM,OAAO,CAAC,MAAM,MAAM,IAAI,EAAE,EAAE,CAAC;AACvD,MAAI,YAAY,WAAW,EAAG,QAAO;AAErC,QAAM,UAAU,IAAI,IAAI,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;AAEnD,MAAI,OAAO;AACX,MAAI,OAAO;AACX,MAAI,OAAO;AACX,MAAI,OAAO;AAEX,aAAW,QAAQ,aAAa;AAC9B,UAAM,MAAM,oBAAoB,MAAM,OAAO;AAC7C,UAAM,EAAE,OAAO,GAAG,QAAQ,EAAE,IAAI,YAAY,IAAI;AAChD,WAAO,KAAK,IAAI,MAAM,IAAI,CAAC;AAC3B,WAAO,KAAK,IAAI,MAAM,IAAI,CAAC;AAC3B,WAAO,KAAK,IAAI,MAAM,IAAI,IAAI,CAAC;AAC/B,WAAO,KAAK,IAAI,MAAM,IAAI,IAAI,CAAC;AAAA,EACjC;AAEA,SAAO,EAAE,GAAG,MAAM,GAAG,MAAM,OAAO,OAAO,MAAM,QAAQ,OAAO,KAAK;AACrE;AAMO,SAAS,UACd,OAC0D;AAC1D,QAAM,SAAS,MAAM,OAAO,CAAC,MAAM,EAAE,SAAS,OAAO;AACrD,MAAI,OAAO,WAAW,EAAG,QAAO,CAAC;AAEjC,QAAM,UAAU,IAAI,IAAI,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;AAEnD,SAAO,OACJ,IAAI,CAAC,MAAM;AA1GhB;AA2GM,UAAM,OAAO,EAAE;AACf,UAAM,MAAM,oBAAoB,GAAG,OAAO;AAC1C,UAAM,EAAE,OAAO,GAAG,QAAQ,EAAE,IAAI,YAAY,CAAC;AAC7C,WAAO;AAAA,MACL,IAAI,EAAE;AAAA,MACN,QAAO,UAAK,UAAL,YAAc;AAAA,MACrB,QAAQ,EAAE,GAAG,IAAI,GAAG,GAAG,IAAI,GAAG,OAAO,GAAG,QAAQ,EAAE;AAAA,IACpD;AAAA,EACF,CAAC,EACA,KAAK,CAAC,GAAG,MAAM,EAAE,OAAO,IAAI,EAAE,OAAO,KAAK,EAAE,OAAO,IAAI,EAAE,OAAO,CAAC;AACtE;AA0BO,SAAS,aACd,MACA,SACuB;AACvB,QAAM,QAAQ,KAAK,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,OAAO;AACrD,MAAI,CAAC,SAAS,MAAM,SAAS,QAAS,QAAO;AAG7C,QAAM,gBAAgB,mBAAmB,KAAK,OAAO,OAAO;AAC5D,QAAM,aAAa,KAAK,MACrB,OAAO,CAAC,MAAM,cAAc,IAAI,EAAE,EAAE,CAAC,EACrC,IAAI,CAAC,MAAO,iCAAK,IAAL,EAAQ,WAAW,MAAM,EAAE;AAG1C,QAAM,aAAa,KAAK,MAAM;AAAA,IAC5B,CAAC,MAAgB,cAAc,IAAI,EAAE,MAAM,KAAK,cAAc,IAAI,EAAE,MAAM;AAAA,EAC5E;AAGA,QAAM,cAAc,cAAc,KAAK,OAAO,CAAC,OAAO,CAAC;AACvD,QAAM,EAAE,OAAO,GAAG,QAAQ,EAAE,IAAI,YAAY,KAAK;AACjD,QAAM,cAA0B,oCAAe;AAAA,IAC7C,GAAG,MAAM,SAAS;AAAA,IAClB,GAAG,MAAM,SAAS;AAAA,IAClB,OAAO;AAAA,IACP,QAAQ;AAAA,EACV;AAGA,QAAM,iBAAiB,WACpB,OAAO,CAAC,MAAM,EAAE,OAAO,OAAO,EAC9B,IAAI,CAAC,MAAM,EAAE,EAAE;AAClB,QAAM,gBAAgB,eAAe,SAAS,IAC1C,cAAc,KAAK,OAAO,cAAc,IACxC;AACJ,QAAM,YAAY,wCAAiB;AAEnC,SAAO;AAAA,IACL,MAAM;AAAA,MACJ,OAAO;AAAA,MACP,OAAO;AAAA,MACP,UAAU,KAAK;AAAA,IACjB;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,EACV;AACF;;;AC5LA,OAAO,WAAW;AAClB,SAAS,iBAAiB;AAW1B,IAAM,iBAAiB;AACvB,IAAM,iBAAiB,oBAAI,IAA0C;AAErE,SAAS,SAAS,KAAqB;AACrC,MAAI,OAAO;AACX,WAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,KAAK;AACnC,UAAM,OAAO,IAAI,WAAW,CAAC;AAC7B,YAAS,QAAQ,KAAK,OAAO,OAAQ;AAAA,EACvC;AACA,SAAO,KAAK,SAAS,EAAE;AACzB;AAEA,IAAM,mBAAmB;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,SAAS,qBAAqB,MAAuB;AACnD,SAAO,CAAC,iBAAiB,KAAK,CAAC,YAAY,QAAQ,KAAK,IAAI,CAAC;AAC/D;AAEO,SAAS,gBACd,MACA,MACqC;AACrC,QAAM,WAAW,GAAG,IAAI,IAAI,SAAS,IAAI,CAAC;AAE1C,MAAI,eAAe,IAAI,QAAQ,GAAG;AAChC,UAAM,SAAS,eAAe,IAAI,QAAQ;AAC1C,mBAAe,OAAO,QAAQ;AAC9B,mBAAe,IAAI,UAAU,MAAM;AACnC,WAAO;AAAA,EACT;AAEA,MAAI,CAAC,qBAAqB,IAAI,GAAG;AAC/B,YAAQ,KAAK,oBAAoB,IAAI,6BAA6B;AAClE,WAAO;AAAA,EACT;AAEA,MAAI;AACF,UAAM,EAAE,MAAM,OAAO,IAAI,UAAU,MAAM;AAAA,MACvC,YAAY,CAAC,cAAc,OAAO,SAAS;AAAA,MAC3C,YAAY;AAAA,MACZ,WAAW;AAAA,MACX,mBAAmB;AAAA,IACrB,CAAC;AAGD,UAAM,UAAU,IAAI;AAAA,MAClB;AAAA,MACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAaE,MAAM;AAAA;AAAA;AAAA,IAGV;AAEA,UAAM,YAAY,QAAQ,KAAK;AAC/B,QAAI,OAAO,cAAc,WAAY,QAAO;AAE5C,QAAI,eAAe,QAAQ,gBAAgB;AACzC,YAAM,YAAY,eAAe,KAAK,EAAE,KAAK,EAAE;AAC/C,UAAI,UAAW,gBAAe,OAAO,SAAS;AAAA,IAChD;AAEA,mBAAe,IAAI,UAAU,SAAS;AACtC,WAAO;AAAA,EACT,SAAS,GAAG;AACV,YAAQ,KAAK,0CAA0C,IAAI,MAAM,CAAC;AAClE,WAAO;AAAA,EACT;AACF;AAEO,SAAS,qBAA2B;AACzC,iBAAe,MAAM;AACvB;;;ARlDA,SAAS,YAAY,KAA6C;AAChE,MAAI,CAAC,IAAK,QAAO;AACjB,MAAI;AACF,UAAM,SAAS,IAAI,IAAI,GAAG;AAC1B,QAAI,OAAO,aAAa,WAAW,OAAO,aAAa,SAAU,QAAO;AACxE,WAAO;AAAA,EACT,SAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,aAAa,OAAuC;AAC3D,MAAI,UAAU,QAAS,QAAO,WAAW;AACzC,MAAI,UAAU,cAAe,QAAO,WAAW;AAC/C,SAAO;AACT;AAIA,SAAS,iBACP,KACA,KACA,UACiB;AACjB,MAAI,OAAO,QAAQ,QAAQ,GAAI,QAAO;AAEtC,QAAM,YAAY,qCAAU;AAG5B,MACE,cAAc,WACb,OAAO,QAAQ,YAAY,QAAQ,QAAQ,SAAS,KACrD;AACA,UAAM,SACJ,OAAO,QAAQ,WAAW,MAAO,2BAA0B;AAC7D,UAAM,UAAU,YAAY,MAAM;AAClC,QAAI,CAAC,QAAS,QAAO;AACrB,WACE,gBAAAC,OAAA;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,KAAK;AAAA,QACL,KAAI;AAAA,QACJ,WAAW;AAAA,QACX,OAAO,EAAE,MAAM,GAAG,WAAW,GAAG,OAAO,QAAQ,WAAW,UAAU;AAAA;AAAA,IACtE;AAAA,EAEJ;AAGA,SACE,gBAAAA,OAAA;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,OAAO;AAAA,QACL,UAAU;AAAA,QACV,YAAY;AAAA,QACZ,WAAW;AAAA,QACX,UAAU;AAAA,QACV,YAAY;AAAA,MACd;AAAA;AAAA,IAEC,OAAO,GAAG;AAAA,EACb;AAEJ;AAIA,SAAS,mBAAmB,EAAE,KAAK,GAAc;AAC/C,QAAM,IAAI;AACV,SACE,gBAAAA,OAAA;AAAA,IAAC;AAAA;AAAA,MACC,OAAO;AAAA,QACL,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,SAAS;AAAA,QACT,eAAe;AAAA,MACjB;AAAA;AAAA,IAEC,EAAE,UACD,OAAO,QAAQ,EAAE,MAAM,EACpB,OAAO,CAAC,CAAC,EAAE,CAAC,MAAM,KAAK,QAAQ,MAAM,EAAE,EACvC,IAAI,CAAC,CAAC,KAAK,GAAG,MAAM,iBAAiB,KAAK,GAAG,CAAC;AAAA,EACrD;AAEJ;AAIA,IAAM,wBAAN,cAAoCA,OAAM,UAGxC;AAAA,EAHF;AAAA;AAIE,iBAAiC,EAAE,OAAO,KAAK;AAAA;AAAA,EAC/C,OAAO,yBAAyB,OAAc;AAC5C,WAAO,EAAE,MAAM;AAAA,EACjB;AAAA,EACA,mBAAmB,WAAkC;AACnD,QAAI,UAAU,aAAa,KAAK,MAAM,YAAY,KAAK,MAAM,OAAO;AAClE,WAAK,SAAS,EAAE,OAAO,KAAK,CAAC;AAAA,IAC/B;AAAA,EACF;AAAA,EACA,SAAS;AACP,QAAI,KAAK,MAAM,OAAO;AACpB,aACE,gBAAAA,OAAA,cAAC,SAAI,OAAO,EAAE,SAAS,GAAG,UAAU,IAAI,OAAO,UAAU,KACvD,gBAAAA,OAAA,cAAC,gBAAO,cAAY,GACpB,gBAAAA,OAAA,cAAC,SAAI,OAAO,EAAE,UAAU,IAAI,YAAY,WAAW,KAChD,KAAK,MAAM,MAAM,OACpB,CACF;AAAA,IAEJ;AACA,WAAO,KAAK,MAAM;AAAA,EACpB;AACF;AAIA,SAAS,oBAAoB;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAKG;AAED,MAAI,QAAQ,UAAU;AACpB,UAAM,YAAY,gBAAgB,QAAQ,UAAU,QAAQ,IAAI;AAChE,QAAI,WAAW;AACb,aACE,gBAAAA,OAAA;AAAA,QAAC;AAAA;AAAA,UACC,WAAW,wBAAwB,QAAQ,IAAI,GAAG,QAAQ,wBAAwB,+BAA+B,EAAE;AAAA,UACnH,OAAO,EAAE,OAAO,QAAQ,QAAQ,OAAO;AAAA;AAAA,QAEvC,gBAAAA,OAAA,cAAC,yBAAsB,UAAU,QAAQ,YACvC,gBAAAA,OAAA;AAAA,UAAC;AAAA;AAAA,YACC,QAAQ,KAAK;AAAA,YACb,OAAO,KAAK;AAAA,YACZ,OAAO,QAAQ;AAAA,YACf,cAAc,QAAQ;AAAA,YACtB,OAAO,SAAS,QAAQ,YAAY;AAAA,YACpC,QAAQ,UAAU,QAAQ,YAAY;AAAA;AAAA,QACxC,CACF;AAAA,MACF;AAAA,IAEJ;AAAA,EACF;AAGA,SACE,gBAAAA,OAAA;AAAA,IAAC;AAAA;AAAA,MACC,OAAO;AAAA,QACL,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,SAAS;AAAA,QACT,eAAe;AAAA,MACjB;AAAA;AAAA,IAEC,QAAQ,OAAO,IAAI,CAAC,MAAM;AACzB,YAAM,MAAM,KAAK,OAAO,EAAE,IAAI;AAC9B,UAAI,OAAO,QAAQ,QAAQ,GAAI,QAAO;AACtC,aAAO,iBAAiB,EAAE,MAAM,KAAK,CAAC;AAAA,IACxC,CAAC;AAAA,EACH;AAEJ;AAIA,SAAS,iBAAiB,EAAE,KAAK,GAAc;AAjP/C;AAkPE,QAAM,IAAI;AACV,QAAM,aAAY,OAAE,UAAF,YAAW;AAC7B,QAAM,WAAU,OAAE,YAAF,YAAa;AAC7B,QAAM,eAAc,OAAE,gBAAF,YAAiB;AACrC,QAAM,WAAU,OAAE,YAAF,YAAa;AAG7B,QAAM,WAAW,MAAM;AACrB,UAAM,IAAI,UAAU,MAAM,gCAAgC;AAC1D,QAAI,EAAG,QAAO,QAAQ,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,OAAO;AACrD,WAAO;AAAA,EACT,GAAG;AAEH,SACE,gBAAAA,OAAA;AAAA,IAAC;AAAA;AAAA,MACC,OAAO;AAAA,QACL,iBAAiB;AAAA,QACjB;AAAA,QACA,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,QACE,gBAAgB,SACZ,SACA,OAAO,WAAW;AAAA,MAC1B;AAAA;AAAA,IAEA,gBAAAA,OAAA;AAAA,MAAC;AAAA;AAAA,QACC,OAAO;AAAA,UACL,UAAU;AAAA,UACV,YAAY;AAAA,UACZ,OAAO;AAAA,UACP,YAAY;AAAA,QACd;AAAA;AAAA,MAEC,EAAE;AAAA,IACL;AAAA,EACF;AAEJ;AAIA,SAAS,gBACP,eACA,iBACA,eACA,aACA,YAIW;AACX,QAAM,QAAmB,CAAC;AAG1B,QAAM,WAAW,CAAC,UAAqB;AACrC,UAAM,IAAI,MAAM;AAChB,UAAM,UAAU,mDAAiB,IAAI,EAAE;AACvC,UAAM,iBAAiB,+CAAgB,EAAE;AAGzC,UAAM,gBAAoC,UACxC,gBAAAA,OAAA;AAAA,MAAC;AAAA;AAAA,QACC,MAAM;AAAA,QACN;AAAA,QACA,OAAO,MAAM;AAAA,QACb,QAAQ,MAAM;AAAA;AAAA,IAChB,IAEA,gBAAAA,OAAA,cAAC,uCAAuB,MAAO;AAGjC,UAAM,YAAkC;AAAA,MACtC,IAAI,MAAM;AAAA,MACV,cAAc,EAAE;AAAA,MAChB,OAAO,EAAE;AAAA,MACT,QAAQ,EAAE;AAAA,MACV,aAAa;AAAA,MACb,UAAU,MAAM;AAAA,MAChB,OAAO,MAAM;AAAA,MACb,QAAQ,MAAM;AAAA,MACd;AAAA,IACF;AAEA,QAAI,UAA8B,iBAChC,gBAAAA,OAAA,cAAC,mCAAmB,UAAW,IAE/B;AAIF,QAAI,YAAY;AACd,YAAM,SAAS,WAAW,WAAW,OAAO;AAC5C,UAAI,WAAW,KAAM,WAAU;AAAA,IACjC;AAGA,QAAI,aAAa;AACf,YAAM,UAAU;AAChB,gBACE,gBAAAA,OAAA;AAAA,QAAC;AAAA;AAAA,UACC,IAAI,MAAM;AAAA,UACV,cAAc,EAAE;AAAA,UAChB,OAAO,EAAE;AAAA,UACT,UAAU,MAAM;AAAA,UAChB,aAAa;AAAA;AAAA,QAEZ;AAAA,MACH;AAAA,IAEJ;AAEA,WAAO;AAAA,EACT;AAGA,QAAM,QAAQ,iBACR,CAAC,UAAqB;AACtB,UAAM,IAAI,MAAM;AAChB,UAAM,WAAW;AACjB,WACE,gBAAAA,OAAA;AAAA,MAAC;AAAA;AAAA,QACC,IAAI,MAAM;AAAA,QACV,OAAO,EAAE;AAAA,QACT,OAAO,EAAE;AAAA,QACT,SAAS,EAAE;AAAA,QACX,aAAa,EAAE;AAAA,QACf,SAAS,EAAE;AAAA,QACX,OAAO,MAAM;AAAA,QACb,QAAQ,MAAM;AAAA;AAAA,IAChB;AAAA,EAEJ,KACC;AAEL,SAAO;AACT;AAIA,SAAS,gBACP,eACA,iBACgE;AAChE,MAAI,CAAC,iBAAiB,OAAO,KAAK,aAAa,EAAE,WAAW;AAC1D,WAAO;AACT,QAAM,QAA4D,CAAC;AACnE,aAAW,CAAC,MAAM,QAAQ,KAAK,OAAO,QAAQ,aAAa,GAAG;AAC5D,UAAM,IAAI,KAAK,CAAC,UAAmC;AAtYvD;AAuYM,YAAM,MAAM,mDAAiB,IAAI;AACjC,aACE,gBAAAA,OAAA;AAAA,QAAC;AAAA;AAAA,UACC,IAAI,MAAM;AAAA,UACV,cAAc;AAAA,UACd,QAAQ,MAAM;AAAA,UACd,QAAQ,MAAM;AAAA,UACd,OAAO,MAAM;AAAA,UACb,SACG,WAAM,SAAN,mBAAoD;AAAA,UAIvD,aAAa;AAAA,UACb,OAAO,MAAM;AAAA;AAAA,MACf;AAAA,IAEJ;AAAA,EACF;AACA,SAAO;AACT;AAMA,SAAS,cACP,IACA,IACA,IACA,QACwC;AACxC,QAAM,OAAO,CAAC,GAAG,IAAI,GAAG;AACxB,QAAM,SAAS,KAAK,GAAG,KAAK,GAAG;AAC/B,QAAM,MAAM,CAAC,GAAG,IAAI,GAAG;AACvB,QAAM,UAAU,KAAK,GAAG,KAAK,GAAG;AAEhC,QAAM,MAAM,OAAO,OAAO,CAAC,EAAE,CAAC;AAC9B,QAAM,MAAM,QAAQ,OAAO,CAAC,EAAE,CAAC;AAC/B,QAAM,MAAM,MAAM,OAAO,CAAC,EAAE,CAAC;AAC7B,QAAM,MAAM,SAAS,OAAO,CAAC,EAAE,CAAC;AAEhC,QAAM,KACJ,MAAM,OAAO,MAAM,OAAO,IAAI,KAAK,IAAI,GAAG,GAAG,KAAK,KAAK,IAAI,GAAG,GAAG;AACnE,QAAM,KACJ,MAAM,OAAO,MAAM,OAAO,IAAI,KAAK,IAAI,GAAG,GAAG,KAAK,KAAK,IAAI,GAAG,GAAG;AAEnE,MAAI,OAAO,KAAK,OAAO,EAAG,QAAO;AACjC,SAAO,EAAE,GAAG,GAAG,IAAI,KAAK,GAAG,MAAM,GAAG,GAAG,IAAI,KAAK,GAAG,MAAM,MAAM,GAAG,KAAK;AACzE;AAEA,SAAS,aAAa;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAWG;AACD,QAAM,EAAE,YAAY,IAAI,aAAa;AACrC,QAAM,QAAQ,YAAY;AAC1B,QAAM,eAAeA,OAAM,OAAuB,IAAI;AACtD,QAAM,YAAY,GAAG,OAAO,CAAC,IAAI,OAAO,CAAC,IAAI,OAAO,KAAK,IAAI,OAAO,MAAM;AAC1E,QAAM,YAAYA,OAAM,OAAO,MAAM;AACrC,YAAU,UAAU;AACpB,QAAM,CAAC,eAAe,gBAAgB,IAAIA,OAAM,SAAS,EAAE,GAAG,GAAG,GAAG,EAAE,CAAC;AACvE,QAAM,mBAAmBA,OAAM,OAAsB,IAAI;AACzD,QAAM,cAAcA,OAAM,OAAO,EAAE,GAAG,GAAG,GAAG,EAAE,CAAC;AAG/C,EAAAA,OAAM,UAAU,MAAM;AACpB,UAAM,KAAK,aAAa;AACxB,QAAI,CAAC,GAAI;AACT,UAAM,WAAW,IAAI,eAAe,CAAC,YAAY;AAC/C,YAAM,QAAQ,QAAQ,CAAC;AACvB,UAAI,CAAC,MAAO;AACZ,YAAM,EAAE,OAAO,OAAO,IAAI,MAAM;AAChC,uBAAiB,EAAE,GAAG,OAAO,GAAG,OAAO,CAAC;AAAA,IAC1C,CAAC;AACD,aAAS,QAAQ,EAAE;AACnB,WAAO,MAAM,SAAS,WAAW;AAAA,EACnC,GAAG,CAAC,CAAC;AAEL,EAAAA,OAAM,UAAU,MAAM;AACpB,QAAI,cAAc,MAAM,KAAK,cAAc,MAAM,EAAG;AAEpD,UAAM,UAAU,iBAAiB;AACjC,UAAM,WAAW,YAAY;AAC7B,qBAAiB,UAAU;AAC3B,gBAAY,UAAU,EAAE,GAAG,cAAc,GAAG,GAAG,cAAc,EAAE;AAG/D,UAAM,iBAAiB,YAAY;AACnC,UAAM,eACJ,CAAC,mBACA,SAAS,MAAM,cAAc,KAAK,SAAS,MAAM,cAAc;AAClE,UAAM,YAAY,YAAY;AAG9B,QAAI,gBAAgB,CAAC,WAAY;AAGjC,UAAM,WACJ,aAAa,iBACT,cAAc,OACZ,MACA,OAAO,cAAc,WACnB,YACA,IACJ;AAEN,UAAM,IAAI,UAAU;AAGpB,UAAM,aAAa,SAAS,WAAW,cAAc,cAAc;AACnE,UAAM,OAAO,UAAU,WAAW;AAClC,UAAM,OAAO,UAAU,WAAW;AAClC,UAAM,KAAK,WAAW,QAAQ,OAAO;AACrC,UAAM,KAAK,WAAW,SAAS,OAAO;AAEtC,QAAI,OAAO,KAAK,OAAO,EAAG;AAG1B,UAAM,SAAS,SAAS,UAAU,KAAK,MAAM,KAAK;AAClD,UAAM,OAAO,OAAO,cAAc,IAAI,IAAI,cAAc,IAAI,EAAE;AAC9D,UAAM,KAAK,WAAW,IAAI,WAAW,QAAQ;AAC7C,UAAM,KAAK,WAAW,IAAI,WAAW,SAAS;AAC9C,UAAM,IAAI,cAAc,IAAI,IAAI,KAAK;AACrC,UAAM,IAAI,cAAc,IAAI,IAAI,KAAK;AAGrC,QAAI,aAAa;AACf,YAAM,YAAY,KAAK;AAAA,QACrB,cAAc,IAAI,YAAY;AAAA,QAC9B,cAAc,IAAI,YAAY;AAAA,MAChC;AACA,YAAM,SAAS,EAAE,WAAW,KAAK,IAAI,WAAW,oCAAe,CAAC,CAAC;AAAA,IACnE,OAAO;AACL,YAAM,SAAS,EAAE,WAAW,oCAAe,GAAG;AAAA,IAChD;AAEA,QAAI,KAAK,EAAE,GAAG,GAAG,KAAK;AACtB,QAAI,QAAQ;AACV,WAAK,cAAc,IAAI,cAAc,GAAG,cAAc,GAAG,MAAM;AAAA,IACjE;AACA,gBAAY,IAAI,EAAE,SAAS,CAAC;AAAA,EAC9B,GAAG;AAAA,IACD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,cAAc;AAAA,IACd,cAAc;AAAA,IACd;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAGD,SACE,gBAAAA,OAAA;AAAA,IAAC;AAAA;AAAA,MACC,KAAK;AAAA,MACL,OAAO;AAAA,QACL,UAAU;AAAA,QACV,OAAO;AAAA,QACP,eAAe;AAAA,QACf,YAAY;AAAA,MACd;AAAA;AAAA,EACF;AAEJ;AAIA,IAAM,gBAAwC;AAAA,EAC5C,MAAM;AAAA,EACN,YAAY;AAAA,EACZ,QAAQ;AAAA,EACR,SAAS;AACX;AAEA,SAAS,gBACP,OACA,iBACQ;AACR,MAAI,EAAC,mDAAiB,MAAM,QAAO;AAEnC,SAAO,MAAM,IAAI,CAAC,SAAS;AAllB7B;AAmlBI,UAAM,OAAO,KAAK;AAClB,QAAI,CAAC,KAAM,QAAO;AAElB,UAAM,MAAM,gBAAgB,IAAI,IAAI;AACpC,QAAI,CAAC,IAAK,QAAO;AAEjB,UAAM,SAAe,mBAAM;AAG3B,QAAI,CAAC,OAAO,QAAQ,IAAI,WAAW;AACjC,aAAO,QAAO,mBAAc,IAAI,SAAS,MAA3B,YAAgC;AAAA,IAChD;AAGA,WAAO,QAAQ,iDACT,IAAI,QAAQ,EAAE,QAAQ,IAAI,MAAM,IAAI,SACpC,IAAI,cAAc,EAAE,aAAa,IAAI,YAAY,IAAI,SACtD,KAAK;AAIV,QAAI,OAAO,YAAY,QAAQ,IAAI,SAAU,QAAO,WAAW;AAG/D,QAAI,CAAC,OAAO,aAAa;AACvB,YAAM,YAAY,aAAa,IAAI,WAAW;AAC9C,UAAI,WAAW;AACb,eAAO,cAAc;AAAA,UACnB,MAAM;AAAA,WACF,IAAI,QAAQ,EAAE,OAAO,IAAI,MAAM,IAAI;AAAA,MAE3C;AAAA,IACF;AACA,QAAI,CAAC,OAAO,WAAW;AACrB,YAAM,UAAU,aAAa,IAAI,SAAS;AAC1C,UAAI,SAAS;AACX,eAAO,YAAY;AAAA,UACjB,MAAM;AAAA,WACF,IAAI,QAAQ,EAAE,OAAO,IAAI,MAAM,IAAI;AAAA,MAE3C;AAAA,IACF;AAEA,WAAO;AAAA,EACT,CAAC;AACH;AAsFO,SAAS,aAAa;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,aAAa;AAAA,EACb,cAAc;AAAA,EACd,UAAU;AAAA,EACV;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,iBAAiB;AAAA,EACjB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ;AAAA,EACA,iBAAiB;AAAA,EACjB,SAAS;AAAA,EACT,SAAS;AACX,GAAsB;AAzvBtB;AA0vBE,QAAM,kBAAkBA,OAAM,QAAQ,MAAM;AAC1C,QAAI,EAAC,6CAAc,QAAQ,QAAO;AAClC,WAAO,IAAI,IAAI,aAAa,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;AAAA,EACrD,GAAG,CAAC,YAAY,CAAC;AAEjB,QAAM,kBAAkBA,OAAM,QAAQ,MAAM;AAC1C,QAAI,EAAC,6CAAc,QAAQ,QAAO;AAClC,WAAO,IAAI,IAAI,aAAa,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;AAAA,EACrD,GAAG,CAAC,YAAY,CAAC;AAEjB,QAAM,YAAYA,OAAM;AAAA,IACtB,MACE;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACF,CAAC,eAAe,iBAAiB,eAAe,aAAa,UAAU;AAAA,EACzE;AAGA,QAAM,kBAAkBA,OAAM;AAAA,IAC5B,MAAM,gBAAgB,eAAe,eAAe;AAAA,IACpD,CAAC,eAAe,eAAe;AAAA,EACjC;AAGA,QAAM,YAAYA,OAAM,QAAQ,MAAM;AACpC,QAAI,EAAC,6CAAc,QAAQ,QAAO;AAClC,WAAO,aACJ,OAAO,CAAC,MAAM,EAAE,SAAS,EACzB,IAAI,CAAC,MAAM,EAAE,SAAS,EACtB,KAAK,IAAI;AAAA,EACd,GAAG,CAAC,YAAY,CAAC;AAEjB,QAAM,cAAcA,OAAM,QAAQ,MAAM;AA/xB1C,QAAAC;AAgyBI,QAAI,QAAQ,iBAAgBA,MAAA,6BAAM,UAAN,OAAAA,MAAe,CAAC,GAAG,eAAe;AAE9D,QAAI,eAAe;AACjB,cAAQ,MAAM,IAAI,CAAC,SAAS;AAC1B,cAAM,OAAQ,KAA6B;AAC3C,YAAI,QAAQ,cAAc,IAAI,GAAG;AAC/B,iBAAO,iCAAK,OAAL,EAAW,MAAM,KAAK;AAAA,QAC/B;AACA,eAAO;AAAA,MACT,CAAC;AAAA,IACH;AACA,WAAO;AAAA,EACT,GAAG,CAAC,6BAAM,OAAO,iBAAiB,aAAa,CAAC;AAGhD,QAAM,kBAAkBD,OAAM,QAAQ,MAAM;AAC1C,QAAI,oBAAqB,QAAO;AAChC,UAAM,KAAK,oCAAe;AAC1B,QAAI,CAAC,GAAI,QAAO;AAChB,UAAM,KAAK,cAAc,IAAK,sCAAgB;AAC9C,WAAO;AAAA,MACL,CAAC,GAAG,IAAI,KAAK,GAAG,OAAO,GAAG,IAAI,KAAK,GAAG,MAAM;AAAA,MAC5C,CAAC,GAAG,IAAI,GAAG,SAAS,IAAI,KAAK,GAAG,IAAI,GAAG,UAAU,IAAI,GAAG;AAAA,IAC1D;AAAA,EACF,GAAG,CAAC,qBAAqB,aAAa,QAAQ,YAAY,CAAC;AAE3D,MAAI,CAAC,KAAM,QAAO;AAElB,QAAM,0BACJ,oDACC,CAAC,WAAW,KAAK,WAAW,KAAK,WAAW;AAE/C,SACE,gBAAAA,OAAA,cAAC,yBACC,gBAAAA,OAAA;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,OAAO;AAAA,QACL,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,YAAY;AAAA,SACT;AAAA;AAAA,IAGL,gBAAAA,OAAA;AAAA,MAAC;AAAA;AAAA,QACC,QACG,UAAK,UAAL,YAAc,CAAC;AAAA,QAIlB,OAAO;AAAA,QACP;AAAA,QACA,WACE;AAAA,QAEF,iBAAiB;AAAA,QACjB,SAAS,SAAS,QAAQ;AAAA,QAC1B;AAAA,QACA;AAAA,QAGA;AAAA,QAKA;AAAA,QAKA;AAAA,QAKA;AAAA,QAKA;AAAA,QAGA,WACE,oBACM,CAAC,GAAY,OAA+C;AAC5D,2BAAiB,EAAE;AAAA,QACrB,KACA;AAAA,QAEN,gBAAgB;AAAA,QAChB,kBAAkB;AAAA,QAClB,oBACE,eACA,CAAC,CAAC,eACF,CAAC,CAAC,qBACF,CAAC,CAAC;AAAA,QAEJ,WAAW;AAAA,QACX,cAAc;AAAA,QACd,aAAa;AAAA,QACb,mBAAmB;AAAA,QACnB,SAAS;AAAA,QACT,SAAS;AAAA,QACT,YAAY,EAAE,iBAAiB,KAAK;AAAA;AAAA,MAEnC,aACC,gBAAAA,OAAA,cAAC,WAAM,yBAAyB,EAAE,QAAQ,UAAU,GAAG;AAAA,MAExD,cAAc,gBAAAA,OAAA,cAAC,gBAAW;AAAA,MAC1B,YAAY,gBAAAA,OAAA,cAAC,cAAS;AAAA,MACtB,WACC,gBAAAA,OAAA;AAAA,QAAC;AAAA;AAAA,UACC,WACE;AAAA;AAAA,MAEJ;AAAA,MAED,UACC,gBAAAA,OAAA;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA,SAAS,sCAAgB;AAAA,UACzB,WAAW,0CAAkB;AAAA,UAC7B,MAAM;AAAA,UACN,YAAY,wCAAiB;AAAA,UAC7B,QAAQ;AAAA,UACR;AAAA,UACA;AAAA;AAAA,MACF;AAAA,MAED;AAAA,IACH;AAAA,EACF,CACF;AAEJ;","names":["React","_a","useMemo","useMemo","React","_a"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@01.software/sdk",
3
- "version": "0.4.3-dev.1774331521107",
3
+ "version": "0.4.3-dev.1774338319418",
4
4
  "description": "01.software SDK",
5
5
  "author": "<office@01.works>",
6
6
  "keywords": [],