@01.software/sdk 0.12.1 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/README.md +102 -57
  2. package/dist/analytics.cjs +207 -0
  3. package/dist/analytics.cjs.map +1 -0
  4. package/dist/analytics.d.cts +20 -0
  5. package/dist/analytics.d.ts +20 -0
  6. package/dist/analytics.js +184 -0
  7. package/dist/analytics.js.map +1 -0
  8. package/dist/{const-CRjjFJ3o.d.ts → const-CigSm8e_.d.ts} +1 -1
  9. package/dist/{const-CZOY2tsf.d.cts → const-CxpAy8X_.d.cts} +1 -1
  10. package/dist/index.cjs +946 -485
  11. package/dist/index.cjs.map +1 -1
  12. package/dist/index.d.cts +640 -439
  13. package/dist/index.d.ts +640 -439
  14. package/dist/index.js +946 -485
  15. package/dist/index.js.map +1 -1
  16. package/dist/{payload-types-D4IWd3ZB.d.cts → payload-types-DH1fKdM3.d.cts} +94 -1
  17. package/dist/{payload-types-D4IWd3ZB.d.ts → payload-types-DH1fKdM3.d.ts} +94 -1
  18. package/dist/realtime.cjs.map +1 -1
  19. package/dist/realtime.d.cts +2 -2
  20. package/dist/realtime.d.ts +2 -2
  21. package/dist/realtime.js.map +1 -1
  22. package/dist/{server-JR9TvKZ5.d.cts → server-DLdbWJVv.d.cts} +5 -3
  23. package/dist/{server-JR9TvKZ5.d.ts → server-DLdbWJVv.d.ts} +5 -3
  24. package/dist/ui/canvas/server.cjs +4 -4
  25. package/dist/ui/canvas/server.cjs.map +1 -1
  26. package/dist/ui/canvas/server.d.cts +1 -1
  27. package/dist/ui/canvas/server.d.ts +1 -1
  28. package/dist/ui/canvas/server.js +4 -4
  29. package/dist/ui/canvas/server.js.map +1 -1
  30. package/dist/ui/canvas.cjs +4 -4
  31. package/dist/ui/canvas.cjs.map +1 -1
  32. package/dist/ui/canvas.d.cts +2 -2
  33. package/dist/ui/canvas.d.ts +2 -2
  34. package/dist/ui/canvas.js +4 -4
  35. package/dist/ui/canvas.js.map +1 -1
  36. package/dist/ui/form.d.cts +1 -1
  37. package/dist/ui/form.d.ts +1 -1
  38. package/dist/ui/video.d.cts +1 -1
  39. package/dist/ui/video.d.ts +1 -1
  40. package/dist/{webhook-D_7bYIKj.d.ts → webhook-CmJWfLjs.d.ts} +2 -2
  41. package/dist/{webhook-C1q3iC6W.d.cts → webhook-IX2MGQj2.d.cts} +2 -2
  42. package/dist/webhook.d.cts +3 -3
  43. package/dist/webhook.d.ts +3 -3
  44. package/package.json +11 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/ui/Canvas/server.ts","../../../src/core/query/query-keys.ts","../../../src/ui/Canvas/query-options.ts","../../../src/ui/Canvas/prefetchCanvas.ts","../../../src/ui/Canvas/utils.ts","../../../src/ui/Canvas/types.ts","../../../src/ui/Canvas/built-in-node-types.ts","../../../src/ui/Canvas/built-in-edge-types.ts"],"sourcesContent":["// Server-safe exports (no 'use client' directive).\n// Use `@01.software/sdk/ui/canvas/server` for server components and route loaders.\n\nexport { prefetchCanvas } from './prefetchCanvas'\nexport type { PrefetchCanvasOptions } from './prefetchCanvas'\nexport { getNodeBounds, getFrames, getFrameData } from './utils'\nexport type { FrameData } from './utils'\nexport type {\n CanvasData,\n CanvasNode,\n CanvasEdge,\n CanvasViewport,\n CanvasNodePosition,\n CanvasNodeData,\n DynamicNodeData,\n FrameNodeData,\n CanvasBounds,\n NodeTypeDef,\n NodeTypeFieldDef,\n EdgeTypeDef,\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'\n","import type { PublicCollection, ApiQueryOptions } from '../client/types'\nimport type { ProductListingGroupsQueryOptions } from './query-hooks'\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\nexport const productKeys = {\n listingGroups: (options?: ProductListingGroupsQueryOptions) =>\n ['products', 'listing-groups', 'list', options] as const,\n listingGroupsInfinite: (\n options?: Omit<ProductListingGroupsQueryOptions, 'page' | 'limit'>,\n ) =>\n ['products', 'listing-groups', 'infinite', options] as const,\n}\n","import { collectionKeys } from '../../core/query/query-keys'\nimport type { SDKClient } from './useCanvas'\n\nexport function canvasQueryOptions(\n client: SDKClient,\n slug?: string,\n id?: string,\n) {\n const identifier = id ?? slug ?? ''\n return {\n queryKey: collectionKeys('canvases').detail(identifier),\n queryFn: async () => {\n if (id) return client.from('canvases').findById(id)\n const result = await client.from('canvases').find({\n where: { slug: { equals: slug } },\n limit: 1,\n })\n const doc = result.docs[0]\n if (!doc) throw new Error(`Canvas not found: ${slug}`)\n return doc\n },\n }\n}\n\nexport function nodeTypesQueryOptions(client: SDKClient) {\n return {\n queryKey: collectionKeys('canvas-node-types').lists(),\n queryFn: async () => {\n // limit: 0 = fetch all documents (Payload CMS convention, disables pagination)\n const result = await client.from('canvas-node-types').find({ limit: 0 })\n return result.docs\n },\n }\n}\n\nexport function edgeTypesQueryOptions(client: SDKClient) {\n return {\n queryKey: collectionKeys('canvas-edge-types').lists(),\n queryFn: async () => {\n const result = await client.from('canvas-edge-types').find({ limit: 0 })\n return result.docs\n },\n }\n}\n","import type { SDKClient } from './useCanvas'\nimport {\n canvasQueryOptions,\n nodeTypesQueryOptions,\n edgeTypesQueryOptions,\n} from './query-options'\n\nexport interface PrefetchCanvasOptions {\n /** SDK client instance (Client or ServerClient) */\n client: SDKClient\n /** Canvas slug (URL-friendly identifier) */\n slug?: string\n /** Canvas document ID (UUID) */\n id?: string\n}\n\n/**\n * Prefetch canvas data into the query cache.\n * Call in route loaders or server components to eliminate loading states on mount.\n *\n * ```ts\n * // React Router loader / Server Component\n * await prefetchCanvas({ client, slug: 'Home' })\n * ```\n */\nexport async function prefetchCanvas(\n options: PrefetchCanvasOptions,\n): Promise<void> {\n const { client, slug, id } = options\n\n if (!slug && !id) {\n throw new Error('prefetchCanvas requires either slug or id')\n }\n\n await Promise.all([\n client.queryClient.prefetchQuery(canvasQueryOptions(client, slug, id)),\n client.queryClient.prefetchQuery(nodeTypesQueryOptions(client)),\n client.queryClient.prefetchQuery(edgeTypesQueryOptions(client)),\n ])\n}\n","import type { CanvasNode, CanvasEdge, CanvasBounds, CanvasData } from './types'\n\n// ── Shared helpers ──\n\nfunction getNodeSize(node: CanvasNode): { 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: CanvasNode,\n nodeMap: Map<string, CanvasNode>,\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 using a pre-built parent→children map (O(N)). */\nfunction collectDescendants(\n nodes: CanvasNode[],\n rootId: string,\n): Set<string> {\n // Build parent → children lookup in O(N)\n const childrenMap = new Map<string, string[]>()\n for (const n of nodes) {\n if (n.parentId) {\n let siblings = childrenMap.get(n.parentId)\n if (!siblings) {\n siblings = []\n childrenMap.set(n.parentId, siblings)\n }\n siblings.push(n.id)\n }\n }\n\n // BFS over children map in O(descendants)\n const result = new Set<string>([rootId])\n const queue = [rootId]\n let i = 0\n while (i < queue.length) {\n const children = childrenMap.get(queue[i++]!)\n if (children) {\n for (const childId of children) {\n if (!result.has(childId)) {\n result.add(childId)\n queue.push(childId)\n }\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: CanvasNode[],\n nodeIds: string[],\n): CanvasBounds | 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: CanvasNode[],\n): Array<{ id: string; label: string; bounds: CanvasBounds }> {\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: CanvasBounds\n /** Bounding box of the frame itself — use for panning/zoom restriction (clamp). */\n clampBounds: CanvasBounds\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: CanvasEdge) => 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: CanvasBounds = 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 }\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 CanvasNodeData = (DynamicNodeData | FrameNodeData) &\n Record<string, unknown>\n\n// ── Canvas types (mirrors @xyflow/react but standalone) ──\n\nexport interface CanvasNodePosition {\n x: number\n y: number\n}\n\nexport interface CanvasNode {\n id: string\n type?: string\n position: CanvasNodePosition\n data: CanvasNodeData\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 CanvasEdge {\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 CanvasViewport {\n x: number\n y: number\n zoom: number\n}\n\nexport interface CanvasData {\n nodes: CanvasNode[]\n edges: CanvasEdge[]\n viewport: CanvasViewport\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: CanvasNode,\n): node is CanvasNode & { data: DynamicNodeData } {\n return node.type === 'dynamic'\n}\n\nexport function isFrameNode(\n node: CanvasNode,\n): node is CanvasNode & { 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 CanvasBounds {\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"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/ui/Canvas/server.ts","../../../src/core/query/query-keys.ts","../../../src/ui/Canvas/query-options.ts","../../../src/ui/Canvas/prefetchCanvas.ts","../../../src/ui/Canvas/utils.ts","../../../src/ui/Canvas/types.ts","../../../src/ui/Canvas/built-in-node-types.ts","../../../src/ui/Canvas/built-in-edge-types.ts"],"sourcesContent":["// Server-safe exports (no 'use client' directive).\n// Use `@01.software/sdk/ui/canvas/server` for server components and route loaders.\n\nexport { prefetchCanvas } from './prefetchCanvas'\nexport type { PrefetchCanvasOptions } from './prefetchCanvas'\nexport { getNodeBounds, getFrames, getFrameData } from './utils'\nexport type { FrameData } from './utils'\nexport type {\n CanvasData,\n CanvasNode,\n CanvasEdge,\n CanvasViewport,\n CanvasNodePosition,\n CanvasNodeData,\n DynamicNodeData,\n FrameNodeData,\n CanvasBounds,\n NodeTypeDef,\n NodeTypeFieldDef,\n EdgeTypeDef,\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'\n","import type { PublicCollection, ApiQueryOptions } from '../client/types'\nimport type { ProductListingGroupsQueryOptions } from './query-hooks'\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\nexport const productKeys = {\n listingGroups: (options?: ProductListingGroupsQueryOptions) =>\n ['products', 'listing-groups', 'list', options] as const,\n listingGroupsInfinite: (\n options?: Omit<ProductListingGroupsQueryOptions, 'page' | 'limit'>,\n ) =>\n ['products', 'listing-groups', 'infinite', options] as const,\n}\n","import { collectionKeys } from '../../core/query/query-keys'\nimport type { SDKClient } from './useCanvas'\n\nexport function canvasQueryOptions(\n client: SDKClient,\n slug?: string,\n id?: string,\n) {\n const identifier = id ?? slug ?? ''\n return {\n queryKey: collectionKeys('canvases').detail(identifier),\n queryFn: async () => {\n if (id) return client.collections.from('canvases').findById(id)\n const result = await client.collections.from('canvases').find({\n where: { slug: { equals: slug } },\n limit: 1,\n })\n const doc = result.docs[0]\n if (!doc) throw new Error(`Canvas not found: ${slug}`)\n return doc\n },\n }\n}\n\nexport function nodeTypesQueryOptions(client: SDKClient) {\n return {\n queryKey: collectionKeys('canvas-node-types').lists(),\n queryFn: async () => {\n // limit: 0 = fetch all documents (Payload CMS convention, disables pagination)\n const result = await client.collections.from('canvas-node-types').find({ limit: 0 })\n return result.docs\n },\n }\n}\n\nexport function edgeTypesQueryOptions(client: SDKClient) {\n return {\n queryKey: collectionKeys('canvas-edge-types').lists(),\n queryFn: async () => {\n const result = await client.collections.from('canvas-edge-types').find({ limit: 0 })\n return result.docs\n },\n }\n}\n","import type { SDKClient } from './useCanvas'\nimport {\n canvasQueryOptions,\n nodeTypesQueryOptions,\n edgeTypesQueryOptions,\n} from './query-options'\n\nexport interface PrefetchCanvasOptions {\n /** SDK client instance (Client or ServerClient) */\n client: SDKClient\n /** Canvas slug (URL-friendly identifier) */\n slug?: string\n /** Canvas document ID (UUID) */\n id?: string\n}\n\n/**\n * Prefetch canvas data into the query cache.\n * Call in route loaders or server components to eliminate loading states on mount.\n *\n * ```ts\n * // React Router loader / Server Component\n * await prefetchCanvas({ client, slug: 'Home' })\n * ```\n */\nexport async function prefetchCanvas(\n options: PrefetchCanvasOptions,\n): Promise<void> {\n const { client, slug, id } = options\n\n if (!slug && !id) {\n throw new Error('prefetchCanvas requires either slug or id')\n }\n\n await Promise.all([\n client.queryClient.prefetchQuery(canvasQueryOptions(client, slug, id)),\n client.queryClient.prefetchQuery(nodeTypesQueryOptions(client)),\n client.queryClient.prefetchQuery(edgeTypesQueryOptions(client)),\n ])\n}\n","import type { CanvasNode, CanvasEdge, CanvasBounds, CanvasData } from './types'\n\n// ── Shared helpers ──\n\nfunction getNodeSize(node: CanvasNode): { 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: CanvasNode,\n nodeMap: Map<string, CanvasNode>,\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 using a pre-built parent→children map (O(N)). */\nfunction collectDescendants(\n nodes: CanvasNode[],\n rootId: string,\n): Set<string> {\n // Build parent → children lookup in O(N)\n const childrenMap = new Map<string, string[]>()\n for (const n of nodes) {\n if (n.parentId) {\n let siblings = childrenMap.get(n.parentId)\n if (!siblings) {\n siblings = []\n childrenMap.set(n.parentId, siblings)\n }\n siblings.push(n.id)\n }\n }\n\n // BFS over children map in O(descendants)\n const result = new Set<string>([rootId])\n const queue = [rootId]\n let i = 0\n while (i < queue.length) {\n const children = childrenMap.get(queue[i++]!)\n if (children) {\n for (const childId of children) {\n if (!result.has(childId)) {\n result.add(childId)\n queue.push(childId)\n }\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: CanvasNode[],\n nodeIds: string[],\n): CanvasBounds | 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: CanvasNode[],\n): Array<{ id: string; label: string; bounds: CanvasBounds }> {\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: CanvasBounds\n /** Bounding box of the frame itself — use for panning/zoom restriction (clamp). */\n clampBounds: CanvasBounds\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: CanvasEdge) => 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: CanvasBounds = 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 }\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 CanvasNodeData = (DynamicNodeData | FrameNodeData) &\n Record<string, unknown>\n\n// ── Canvas types (mirrors @xyflow/react but standalone) ──\n\nexport interface CanvasNodePosition {\n x: number\n y: number\n}\n\nexport interface CanvasNode {\n id: string\n type?: string\n position: CanvasNodePosition\n data: CanvasNodeData\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 CanvasEdge {\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 CanvasViewport {\n x: number\n y: number\n zoom: number\n}\n\nexport interface CanvasData {\n nodes: CanvasNode[]\n edges: CanvasEdge[]\n viewport: CanvasViewport\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: CanvasNode,\n): node is CanvasNode & { data: DynamicNodeData } {\n return node.type === 'dynamic'\n}\n\nexport function isFrameNode(\n node: CanvasNode,\n): node is CanvasNode & { 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 CanvasBounds {\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"],"mappings":"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","names":[]}
@@ -1,3 +1,3 @@
1
- export { o as BUILT_IN_EDGE_TYPES, B as BUILT_IN_NODE_TYPES, g as CanvasBounds, C as CanvasData, c as CanvasEdge, a as CanvasNode, j as CanvasNodeData, i as CanvasNodePosition, f as CanvasViewport, k as DynamicNodeData, E as EdgeTypeDef, h as FrameData, l as FrameNodeData, N as NodeTypeDef, b as NodeTypeFieldDef, P as PrefetchCanvasOptions, t as getFrameData, s as getFrames, r as getNodeBounds, m as isDynamicNode, n as isFrameNode, q as prefetchCanvas } from '../../server-JR9TvKZ5.cjs';
1
+ export { o as BUILT_IN_EDGE_TYPES, B as BUILT_IN_NODE_TYPES, g as CanvasBounds, C as CanvasData, c as CanvasEdge, a as CanvasNode, j as CanvasNodeData, i as CanvasNodePosition, f as CanvasViewport, k as DynamicNodeData, E as EdgeTypeDef, h as FrameData, l as FrameNodeData, N as NodeTypeDef, b as NodeTypeFieldDef, P as PrefetchCanvasOptions, t as getFrameData, s as getFrames, r as getNodeBounds, m as isDynamicNode, n as isFrameNode, q as prefetchCanvas } from '../../server-DLdbWJVv.cjs';
2
2
  import '@tanstack/react-query';
3
3
  import 'react';
@@ -1,3 +1,3 @@
1
- export { o as BUILT_IN_EDGE_TYPES, B as BUILT_IN_NODE_TYPES, g as CanvasBounds, C as CanvasData, c as CanvasEdge, a as CanvasNode, j as CanvasNodeData, i as CanvasNodePosition, f as CanvasViewport, k as DynamicNodeData, E as EdgeTypeDef, h as FrameData, l as FrameNodeData, N as NodeTypeDef, b as NodeTypeFieldDef, P as PrefetchCanvasOptions, t as getFrameData, s as getFrames, r as getNodeBounds, m as isDynamicNode, n as isFrameNode, q as prefetchCanvas } from '../../server-JR9TvKZ5.js';
1
+ export { o as BUILT_IN_EDGE_TYPES, B as BUILT_IN_NODE_TYPES, g as CanvasBounds, C as CanvasData, c as CanvasEdge, a as CanvasNode, j as CanvasNodeData, i as CanvasNodePosition, f as CanvasViewport, k as DynamicNodeData, E as EdgeTypeDef, h as FrameData, l as FrameNodeData, N as NodeTypeDef, b as NodeTypeFieldDef, P as PrefetchCanvasOptions, t as getFrameData, s as getFrames, r as getNodeBounds, m as isDynamicNode, n as isFrameNode, q as prefetchCanvas } from '../../server-DLdbWJVv.js';
2
2
  import '@tanstack/react-query';
3
3
  import 'react';
@@ -17,8 +17,8 @@ function canvasQueryOptions(client, slug, id) {
17
17
  return {
18
18
  queryKey: collectionKeys("canvases").detail(identifier),
19
19
  queryFn: async () => {
20
- if (id) return client.from("canvases").findById(id);
21
- const result = await client.from("canvases").find({
20
+ if (id) return client.collections.from("canvases").findById(id);
21
+ const result = await client.collections.from("canvases").find({
22
22
  where: { slug: { equals: slug } },
23
23
  limit: 1
24
24
  });
@@ -32,7 +32,7 @@ function nodeTypesQueryOptions(client) {
32
32
  return {
33
33
  queryKey: collectionKeys("canvas-node-types").lists(),
34
34
  queryFn: async () => {
35
- const result = await client.from("canvas-node-types").find({ limit: 0 });
35
+ const result = await client.collections.from("canvas-node-types").find({ limit: 0 });
36
36
  return result.docs;
37
37
  }
38
38
  };
@@ -41,7 +41,7 @@ function edgeTypesQueryOptions(client) {
41
41
  return {
42
42
  queryKey: collectionKeys("canvas-edge-types").lists(),
43
43
  queryFn: async () => {
44
- const result = await client.from("canvas-edge-types").find({ limit: 0 });
44
+ const result = await client.collections.from("canvas-edge-types").find({ limit: 0 });
45
45
  return result.docs;
46
46
  }
47
47
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/core/query/query-keys.ts","../../../src/ui/Canvas/query-options.ts","../../../src/ui/Canvas/prefetchCanvas.ts","../../../src/ui/Canvas/utils.ts","../../../src/ui/Canvas/types.ts","../../../src/ui/Canvas/built-in-node-types.ts","../../../src/ui/Canvas/built-in-edge-types.ts"],"sourcesContent":["import type { PublicCollection, ApiQueryOptions } from '../client/types'\nimport type { ProductListingGroupsQueryOptions } from './query-hooks'\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\nexport const productKeys = {\n listingGroups: (options?: ProductListingGroupsQueryOptions) =>\n ['products', 'listing-groups', 'list', options] as const,\n listingGroupsInfinite: (\n options?: Omit<ProductListingGroupsQueryOptions, 'page' | 'limit'>,\n ) =>\n ['products', 'listing-groups', 'infinite', options] as const,\n}\n","import { collectionKeys } from '../../core/query/query-keys'\nimport type { SDKClient } from './useCanvas'\n\nexport function canvasQueryOptions(\n client: SDKClient,\n slug?: string,\n id?: string,\n) {\n const identifier = id ?? slug ?? ''\n return {\n queryKey: collectionKeys('canvases').detail(identifier),\n queryFn: async () => {\n if (id) return client.from('canvases').findById(id)\n const result = await client.from('canvases').find({\n where: { slug: { equals: slug } },\n limit: 1,\n })\n const doc = result.docs[0]\n if (!doc) throw new Error(`Canvas not found: ${slug}`)\n return doc\n },\n }\n}\n\nexport function nodeTypesQueryOptions(client: SDKClient) {\n return {\n queryKey: collectionKeys('canvas-node-types').lists(),\n queryFn: async () => {\n // limit: 0 = fetch all documents (Payload CMS convention, disables pagination)\n const result = await client.from('canvas-node-types').find({ limit: 0 })\n return result.docs\n },\n }\n}\n\nexport function edgeTypesQueryOptions(client: SDKClient) {\n return {\n queryKey: collectionKeys('canvas-edge-types').lists(),\n queryFn: async () => {\n const result = await client.from('canvas-edge-types').find({ limit: 0 })\n return result.docs\n },\n }\n}\n","import type { SDKClient } from './useCanvas'\nimport {\n canvasQueryOptions,\n nodeTypesQueryOptions,\n edgeTypesQueryOptions,\n} from './query-options'\n\nexport interface PrefetchCanvasOptions {\n /** SDK client instance (Client or ServerClient) */\n client: SDKClient\n /** Canvas slug (URL-friendly identifier) */\n slug?: string\n /** Canvas document ID (UUID) */\n id?: string\n}\n\n/**\n * Prefetch canvas data into the query cache.\n * Call in route loaders or server components to eliminate loading states on mount.\n *\n * ```ts\n * // React Router loader / Server Component\n * await prefetchCanvas({ client, slug: 'Home' })\n * ```\n */\nexport async function prefetchCanvas(\n options: PrefetchCanvasOptions,\n): Promise<void> {\n const { client, slug, id } = options\n\n if (!slug && !id) {\n throw new Error('prefetchCanvas requires either slug or id')\n }\n\n await Promise.all([\n client.queryClient.prefetchQuery(canvasQueryOptions(client, slug, id)),\n client.queryClient.prefetchQuery(nodeTypesQueryOptions(client)),\n client.queryClient.prefetchQuery(edgeTypesQueryOptions(client)),\n ])\n}\n","import type { CanvasNode, CanvasEdge, CanvasBounds, CanvasData } from './types'\n\n// ── Shared helpers ──\n\nfunction getNodeSize(node: CanvasNode): { 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: CanvasNode,\n nodeMap: Map<string, CanvasNode>,\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 using a pre-built parent→children map (O(N)). */\nfunction collectDescendants(\n nodes: CanvasNode[],\n rootId: string,\n): Set<string> {\n // Build parent → children lookup in O(N)\n const childrenMap = new Map<string, string[]>()\n for (const n of nodes) {\n if (n.parentId) {\n let siblings = childrenMap.get(n.parentId)\n if (!siblings) {\n siblings = []\n childrenMap.set(n.parentId, siblings)\n }\n siblings.push(n.id)\n }\n }\n\n // BFS over children map in O(descendants)\n const result = new Set<string>([rootId])\n const queue = [rootId]\n let i = 0\n while (i < queue.length) {\n const children = childrenMap.get(queue[i++]!)\n if (children) {\n for (const childId of children) {\n if (!result.has(childId)) {\n result.add(childId)\n queue.push(childId)\n }\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: CanvasNode[],\n nodeIds: string[],\n): CanvasBounds | 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: CanvasNode[],\n): Array<{ id: string; label: string; bounds: CanvasBounds }> {\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: CanvasBounds\n /** Bounding box of the frame itself — use for panning/zoom restriction (clamp). */\n clampBounds: CanvasBounds\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: CanvasEdge) => 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: CanvasBounds = 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 }\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 CanvasNodeData = (DynamicNodeData | FrameNodeData) &\n Record<string, unknown>\n\n// ── Canvas types (mirrors @xyflow/react but standalone) ──\n\nexport interface CanvasNodePosition {\n x: number\n y: number\n}\n\nexport interface CanvasNode {\n id: string\n type?: string\n position: CanvasNodePosition\n data: CanvasNodeData\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 CanvasEdge {\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 CanvasViewport {\n x: number\n y: number\n zoom: number\n}\n\nexport interface CanvasData {\n nodes: CanvasNode[]\n edges: CanvasEdge[]\n viewport: CanvasViewport\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: CanvasNode,\n): node is CanvasNode & { data: DynamicNodeData } {\n return node.type === 'dynamic'\n}\n\nexport function isFrameNode(\n node: CanvasNode,\n): node is CanvasNode & { 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 CanvasBounds {\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"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/core/query/query-keys.ts","../../../src/ui/Canvas/query-options.ts","../../../src/ui/Canvas/prefetchCanvas.ts","../../../src/ui/Canvas/utils.ts","../../../src/ui/Canvas/types.ts","../../../src/ui/Canvas/built-in-node-types.ts","../../../src/ui/Canvas/built-in-edge-types.ts"],"sourcesContent":["import type { PublicCollection, ApiQueryOptions } from '../client/types'\nimport type { ProductListingGroupsQueryOptions } from './query-hooks'\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\nexport const productKeys = {\n listingGroups: (options?: ProductListingGroupsQueryOptions) =>\n ['products', 'listing-groups', 'list', options] as const,\n listingGroupsInfinite: (\n options?: Omit<ProductListingGroupsQueryOptions, 'page' | 'limit'>,\n ) =>\n ['products', 'listing-groups', 'infinite', options] as const,\n}\n","import { collectionKeys } from '../../core/query/query-keys'\nimport type { SDKClient } from './useCanvas'\n\nexport function canvasQueryOptions(\n client: SDKClient,\n slug?: string,\n id?: string,\n) {\n const identifier = id ?? slug ?? ''\n return {\n queryKey: collectionKeys('canvases').detail(identifier),\n queryFn: async () => {\n if (id) return client.collections.from('canvases').findById(id)\n const result = await client.collections.from('canvases').find({\n where: { slug: { equals: slug } },\n limit: 1,\n })\n const doc = result.docs[0]\n if (!doc) throw new Error(`Canvas not found: ${slug}`)\n return doc\n },\n }\n}\n\nexport function nodeTypesQueryOptions(client: SDKClient) {\n return {\n queryKey: collectionKeys('canvas-node-types').lists(),\n queryFn: async () => {\n // limit: 0 = fetch all documents (Payload CMS convention, disables pagination)\n const result = await client.collections.from('canvas-node-types').find({ limit: 0 })\n return result.docs\n },\n }\n}\n\nexport function edgeTypesQueryOptions(client: SDKClient) {\n return {\n queryKey: collectionKeys('canvas-edge-types').lists(),\n queryFn: async () => {\n const result = await client.collections.from('canvas-edge-types').find({ limit: 0 })\n return result.docs\n },\n }\n}\n","import type { SDKClient } from './useCanvas'\nimport {\n canvasQueryOptions,\n nodeTypesQueryOptions,\n edgeTypesQueryOptions,\n} from './query-options'\n\nexport interface PrefetchCanvasOptions {\n /** SDK client instance (Client or ServerClient) */\n client: SDKClient\n /** Canvas slug (URL-friendly identifier) */\n slug?: string\n /** Canvas document ID (UUID) */\n id?: string\n}\n\n/**\n * Prefetch canvas data into the query cache.\n * Call in route loaders or server components to eliminate loading states on mount.\n *\n * ```ts\n * // React Router loader / Server Component\n * await prefetchCanvas({ client, slug: 'Home' })\n * ```\n */\nexport async function prefetchCanvas(\n options: PrefetchCanvasOptions,\n): Promise<void> {\n const { client, slug, id } = options\n\n if (!slug && !id) {\n throw new Error('prefetchCanvas requires either slug or id')\n }\n\n await Promise.all([\n client.queryClient.prefetchQuery(canvasQueryOptions(client, slug, id)),\n client.queryClient.prefetchQuery(nodeTypesQueryOptions(client)),\n client.queryClient.prefetchQuery(edgeTypesQueryOptions(client)),\n ])\n}\n","import type { CanvasNode, CanvasEdge, CanvasBounds, CanvasData } from './types'\n\n// ── Shared helpers ──\n\nfunction getNodeSize(node: CanvasNode): { 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: CanvasNode,\n nodeMap: Map<string, CanvasNode>,\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 using a pre-built parent→children map (O(N)). */\nfunction collectDescendants(\n nodes: CanvasNode[],\n rootId: string,\n): Set<string> {\n // Build parent → children lookup in O(N)\n const childrenMap = new Map<string, string[]>()\n for (const n of nodes) {\n if (n.parentId) {\n let siblings = childrenMap.get(n.parentId)\n if (!siblings) {\n siblings = []\n childrenMap.set(n.parentId, siblings)\n }\n siblings.push(n.id)\n }\n }\n\n // BFS over children map in O(descendants)\n const result = new Set<string>([rootId])\n const queue = [rootId]\n let i = 0\n while (i < queue.length) {\n const children = childrenMap.get(queue[i++]!)\n if (children) {\n for (const childId of children) {\n if (!result.has(childId)) {\n result.add(childId)\n queue.push(childId)\n }\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: CanvasNode[],\n nodeIds: string[],\n): CanvasBounds | 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: CanvasNode[],\n): Array<{ id: string; label: string; bounds: CanvasBounds }> {\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: CanvasBounds\n /** Bounding box of the frame itself — use for panning/zoom restriction (clamp). */\n clampBounds: CanvasBounds\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: CanvasEdge) => 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: CanvasBounds = 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 }\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 CanvasNodeData = (DynamicNodeData | FrameNodeData) &\n Record<string, unknown>\n\n// ── Canvas types (mirrors @xyflow/react but standalone) ──\n\nexport interface CanvasNodePosition {\n x: number\n y: number\n}\n\nexport interface CanvasNode {\n id: string\n type?: string\n position: CanvasNodePosition\n data: CanvasNodeData\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 CanvasEdge {\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 CanvasViewport {\n x: number\n y: number\n zoom: number\n}\n\nexport interface CanvasData {\n nodes: CanvasNode[]\n edges: CanvasEdge[]\n viewport: CanvasViewport\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: CanvasNode,\n): node is CanvasNode & { data: DynamicNodeData } {\n return node.type === 'dynamic'\n}\n\nexport function isFrameNode(\n node: CanvasNode,\n): node is CanvasNode & { 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 CanvasBounds {\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"],"mappings":"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","names":[]}
@@ -123,8 +123,8 @@ function canvasQueryOptions(client, slug, id) {
123
123
  return {
124
124
  queryKey: collectionKeys("canvases").detail(identifier),
125
125
  queryFn: async () => {
126
- if (id) return client.from("canvases").findById(id);
127
- const result = await client.from("canvases").find({
126
+ if (id) return client.collections.from("canvases").findById(id);
127
+ const result = await client.collections.from("canvases").find({
128
128
  where: { slug: { equals: slug } },
129
129
  limit: 1
130
130
  });
@@ -138,7 +138,7 @@ function nodeTypesQueryOptions(client) {
138
138
  return {
139
139
  queryKey: collectionKeys("canvas-node-types").lists(),
140
140
  queryFn: async () => {
141
- const result = await client.from("canvas-node-types").find({ limit: 0 });
141
+ const result = await client.collections.from("canvas-node-types").find({ limit: 0 });
142
142
  return result.docs;
143
143
  }
144
144
  };
@@ -147,7 +147,7 @@ function edgeTypesQueryOptions(client) {
147
147
  return {
148
148
  queryKey: collectionKeys("canvas-edge-types").lists(),
149
149
  queryFn: async () => {
150
- const result = await client.from("canvas-edge-types").find({ limit: 0 });
150
+ const result = await client.collections.from("canvas-edge-types").find({ limit: 0 });
151
151
  return result.docs;
152
152
  }
153
153
  };