@01.software/sdk 0.4.3-dev.1774336698898 → 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
@@ -650,39 +650,28 @@ function createNodeTypes(nodeRenderers, nodeTypeDefsMap, frameRenderer, nodeWrap
650
650
  const d = props.data;
651
651
  const typeDef = nodeTypeDefsMap == null ? void 0 : nodeTypeDefsMap.get(d.nodeTypeSlug);
652
652
  const CustomRenderer = nodeRenderers == null ? void 0 : nodeRenderers[d.nodeTypeSlug];
653
- let content;
654
- if (CustomRenderer) {
655
- content = /* @__PURE__ */ import_react4.default.createElement(
656
- CustomRenderer,
657
- {
658
- id: props.id,
659
- nodeTypeSlug: d.nodeTypeSlug,
660
- label: d.label,
661
- fields: d.fields,
662
- nodeTypeDef: typeDef
663
- }
664
- );
665
- } else if (typeDef) {
666
- content = /* @__PURE__ */ import_react4.default.createElement(
667
- EnhancedDynamicNode,
668
- {
669
- data: d,
670
- typeDef,
671
- width: props.width,
672
- height: props.height
673
- }
674
- );
675
- } else {
676
- content = /* @__PURE__ */ import_react4.default.createElement(DefaultDynamicNode, __spreadValues({}, props));
677
- }
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;
678
674
  if (renderNode) {
679
- const slotProps = {
680
- id: props.id,
681
- nodeTypeSlug: d.nodeTypeSlug,
682
- label: d.label,
683
- fields: d.fields,
684
- nodeTypeDef: typeDef
685
- };
686
675
  const result = renderNode(slotProps, content);
687
676
  if (result !== null) content = result;
688
677
  }
@@ -713,7 +702,9 @@ function createNodeTypes(nodeRenderers, nodeTypeDefsMap, frameRenderer, nodeWrap
713
702
  color: d.color,
714
703
  padding: d.padding,
715
704
  borderStyle: d.borderStyle,
716
- opacity: d.opacity
705
+ opacity: d.opacity,
706
+ width: props.width,
707
+ height: props.height
717
708
  }
718
709
  );
719
710
  }) : DefaultFrameNode;
@@ -765,7 +756,8 @@ function FocusHandler({
765
756
  mode,
766
757
  responsive,
767
758
  extent,
768
- clampBounds
759
+ clampBounds,
760
+ minZoomProp
769
761
  }) {
770
762
  const { setViewport } = (0, import_react5.useReactFlow)();
771
763
  const store = (0, import_react5.useStoreApi)();
@@ -800,15 +792,16 @@ function FocusHandler({
800
792
  if (isResizeOnly && !responsive) return;
801
793
  const duration = isInitial || isBoundsChange ? animation === true ? 300 : typeof animation === "number" ? animation : 0 : 0;
802
794
  const b = boundsRef.current;
803
- const padX = padding * b.width;
804
- const padY = padding * b.height;
805
- const bw = b.width + padX * 2;
806
- 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;
807
800
  if (bw === 0 || bh === 0) return;
808
801
  const zoomFn = mode === "cover" ? Math.max : Math.min;
809
802
  const zoom = zoomFn(containerSize.w / bw, containerSize.h / bh);
810
- const cx = b.x + b.width / 2;
811
- const cy = b.y + b.height / 2;
803
+ const cx = zoomTarget.x + zoomTarget.width / 2;
804
+ const cy = zoomTarget.y + zoomTarget.height / 2;
812
805
  const x = containerSize.w / 2 - cx * zoom;
813
806
  const y = containerSize.h / 2 - cy * zoom;
814
807
  if (clampBounds) {
@@ -816,7 +809,9 @@ function FocusHandler({
816
809
  containerSize.w / clampBounds.width,
817
810
  containerSize.h / clampBounds.height
818
811
  );
819
- store.getState().setMinZoom(coverZoom);
812
+ store.getState().setMinZoom(Math.max(coverZoom, minZoomProp != null ? minZoomProp : 0));
813
+ } else {
814
+ store.getState().setMinZoom(minZoomProp != null ? minZoomProp : 0.5);
820
815
  }
821
816
  let vp = { x, y, zoom };
822
817
  if (extent) {
@@ -834,6 +829,7 @@ function FocusHandler({
834
829
  extent,
835
830
  setViewport,
836
831
  clampBounds,
832
+ minZoomProp,
837
833
  store
838
834
  ]);
839
835
  return /* @__PURE__ */ import_react4.default.createElement(
@@ -1035,7 +1031,8 @@ function FlowRenderer({
1035
1031
  mode: focusMode,
1036
1032
  responsive: responsiveFit != null ? responsiveFit : true,
1037
1033
  extent: translateExtent,
1038
- clampBounds
1034
+ clampBounds,
1035
+ minZoomProp
1039
1036
  }
1040
1037
  ),
1041
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 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 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 clampBounds,\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}) {\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 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 // 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(coverZoom)\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 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. 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 /** 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) > 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 />\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) */
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) */
package/dist/ui/flow.js CHANGED
@@ -617,39 +617,28 @@ function createNodeTypes(nodeRenderers, nodeTypeDefsMap, frameRenderer, nodeWrap
617
617
  const d = props.data;
618
618
  const typeDef = nodeTypeDefsMap == null ? void 0 : nodeTypeDefsMap.get(d.nodeTypeSlug);
619
619
  const CustomRenderer = nodeRenderers == null ? void 0 : nodeRenderers[d.nodeTypeSlug];
620
- let content;
621
- if (CustomRenderer) {
622
- content = /* @__PURE__ */ React2.createElement(
623
- CustomRenderer,
624
- {
625
- id: props.id,
626
- nodeTypeSlug: d.nodeTypeSlug,
627
- label: d.label,
628
- fields: d.fields,
629
- nodeTypeDef: typeDef
630
- }
631
- );
632
- } else if (typeDef) {
633
- content = /* @__PURE__ */ React2.createElement(
634
- EnhancedDynamicNode,
635
- {
636
- data: d,
637
- typeDef,
638
- width: props.width,
639
- height: props.height
640
- }
641
- );
642
- } else {
643
- content = /* @__PURE__ */ React2.createElement(DefaultDynamicNode, __spreadValues({}, props));
644
- }
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;
645
641
  if (renderNode) {
646
- const slotProps = {
647
- id: props.id,
648
- nodeTypeSlug: d.nodeTypeSlug,
649
- label: d.label,
650
- fields: d.fields,
651
- nodeTypeDef: typeDef
652
- };
653
642
  const result = renderNode(slotProps, content);
654
643
  if (result !== null) content = result;
655
644
  }
@@ -680,7 +669,9 @@ function createNodeTypes(nodeRenderers, nodeTypeDefsMap, frameRenderer, nodeWrap
680
669
  color: d.color,
681
670
  padding: d.padding,
682
671
  borderStyle: d.borderStyle,
683
- opacity: d.opacity
672
+ opacity: d.opacity,
673
+ width: props.width,
674
+ height: props.height
684
675
  }
685
676
  );
686
677
  }) : DefaultFrameNode;
@@ -732,7 +723,8 @@ function FocusHandler({
732
723
  mode,
733
724
  responsive,
734
725
  extent,
735
- clampBounds
726
+ clampBounds,
727
+ minZoomProp
736
728
  }) {
737
729
  const { setViewport } = useReactFlow();
738
730
  const store = useStoreApi();
@@ -767,15 +759,16 @@ function FocusHandler({
767
759
  if (isResizeOnly && !responsive) return;
768
760
  const duration = isInitial || isBoundsChange ? animation === true ? 300 : typeof animation === "number" ? animation : 0 : 0;
769
761
  const b = boundsRef.current;
770
- const padX = padding * b.width;
771
- const padY = padding * b.height;
772
- const bw = b.width + padX * 2;
773
- const bh = b.height + padY * 2;
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;
774
767
  if (bw === 0 || bh === 0) return;
775
768
  const zoomFn = mode === "cover" ? Math.max : Math.min;
776
769
  const zoom = zoomFn(containerSize.w / bw, containerSize.h / bh);
777
- const cx = b.x + b.width / 2;
778
- const cy = b.y + b.height / 2;
770
+ const cx = zoomTarget.x + zoomTarget.width / 2;
771
+ const cy = zoomTarget.y + zoomTarget.height / 2;
779
772
  const x = containerSize.w / 2 - cx * zoom;
780
773
  const y = containerSize.h / 2 - cy * zoom;
781
774
  if (clampBounds) {
@@ -783,7 +776,9 @@ function FocusHandler({
783
776
  containerSize.w / clampBounds.width,
784
777
  containerSize.h / clampBounds.height
785
778
  );
786
- store.getState().setMinZoom(coverZoom);
779
+ store.getState().setMinZoom(Math.max(coverZoom, minZoomProp != null ? minZoomProp : 0));
780
+ } else {
781
+ store.getState().setMinZoom(minZoomProp != null ? minZoomProp : 0.5);
787
782
  }
788
783
  let vp = { x, y, zoom };
789
784
  if (extent) {
@@ -801,6 +796,7 @@ function FocusHandler({
801
796
  extent,
802
797
  setViewport,
803
798
  clampBounds,
799
+ minZoomProp,
804
800
  store
805
801
  ]);
806
802
  return /* @__PURE__ */ React2.createElement(
@@ -1002,7 +998,8 @@ function FlowRenderer({
1002
998
  mode: focusMode,
1003
999
  responsive: responsiveFit != null ? responsiveFit : true,
1004
1000
  extent: translateExtent,
1005
- clampBounds
1001
+ clampBounds,
1002
+ minZoomProp
1006
1003
  }
1007
1004
  ),
1008
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 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 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 clampBounds,\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}) {\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 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 // 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(coverZoom)\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 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. 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 /** 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) > 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 />\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":"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","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.1774336698898",
3
+ "version": "0.4.3-dev.1774338319418",
4
4
  "description": "01.software SDK",
5
5
  "author": "<office@01.works>",
6
6
  "keywords": [],