@octaviaflow/core 3.1.0-beta.73 → 3.1.0-beta.75

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 (41) hide show
  1. package/dist/chunk-2N74IQCL.js +5700 -0
  2. package/dist/chunk-2N74IQCL.js.map +1 -0
  3. package/dist/components/AuthScreen/AuthScreen.d.ts +29 -1
  4. package/dist/components/AuthScreen/AuthScreen.d.ts.map +1 -1
  5. package/dist/components/FlowSettingsDialog/FlowSettingsDialog.d.ts +37 -0
  6. package/dist/components/FlowSettingsDialog/FlowSettingsDialog.d.ts.map +1 -0
  7. package/dist/components/FlowSettingsDialog/index.d.ts +2 -0
  8. package/dist/components/FlowSettingsDialog/index.d.ts.map +1 -0
  9. package/dist/components/FlowToolbar/FlowToolbar.d.ts +26 -0
  10. package/dist/components/FlowToolbar/FlowToolbar.d.ts.map +1 -1
  11. package/dist/components/FlowToolbar/index.d.ts +1 -1
  12. package/dist/components/FlowToolbar/index.d.ts.map +1 -1
  13. package/dist/components/MembersSettings/MembersSettings.d.ts +35 -0
  14. package/dist/components/MembersSettings/MembersSettings.d.ts.map +1 -0
  15. package/dist/components/MembersSettings/index.d.ts +2 -0
  16. package/dist/components/MembersSettings/index.d.ts.map +1 -0
  17. package/dist/components/OrganizationSettings/OrganizationSettings.d.ts +41 -0
  18. package/dist/components/OrganizationSettings/OrganizationSettings.d.ts.map +1 -0
  19. package/dist/components/OrganizationSettings/index.d.ts +2 -0
  20. package/dist/components/OrganizationSettings/index.d.ts.map +1 -0
  21. package/dist/components/ProfileSettings/ProfileSettings.d.ts +46 -0
  22. package/dist/components/ProfileSettings/ProfileSettings.d.ts.map +1 -0
  23. package/dist/components/ProfileSettings/index.d.ts +2 -0
  24. package/dist/components/ProfileSettings/index.d.ts.map +1 -0
  25. package/dist/components/SettingsLayout/SettingsLayout.d.ts +26 -0
  26. package/dist/components/SettingsLayout/SettingsLayout.d.ts.map +1 -0
  27. package/dist/components/SettingsLayout/index.d.ts +2 -0
  28. package/dist/components/SettingsLayout/index.d.ts.map +1 -0
  29. package/dist/components/WorkflowHeader/WorkflowHeader.d.ts +1 -31
  30. package/dist/components/WorkflowHeader/WorkflowHeader.d.ts.map +1 -1
  31. package/dist/components/WorkflowHeader/WorkflowHeaderExpanded.d.ts +0 -23
  32. package/dist/components/WorkflowHeader/WorkflowHeaderExpanded.d.ts.map +1 -1
  33. package/dist/index.cjs +6509 -5378
  34. package/dist/index.cjs.map +1 -1
  35. package/dist/index.d.ts +5 -1
  36. package/dist/index.d.ts.map +1 -1
  37. package/dist/index.js +2913 -1784
  38. package/dist/index.js.map +1 -1
  39. package/dist/styles.css +1 -1
  40. package/dist/workflow.js +1 -1
  41. package/package.json +1 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/Badge/Badge.tsx","../src/components/Checkbox/Checkbox.tsx","../src/components/Banner/Banner.tsx","../src/hooks/usePasswordStrength.ts","../src/components/PasswordInput/PasswordInput.tsx","../src/components/CodeEditor/CodeEditor.tsx","../src/components/Combobox/Combobox.tsx","../src/components/KeyValueEditor/KeyValueEditor.tsx","../src/components/Disclosure/Disclosure.tsx","../src/components/InlineMessage/InlineMessage.tsx","../src/components/SegmentedControl/SegmentedControl.tsx","../src/components/JsonViewer/JsonViewer.tsx","../src/workflow/utils/paths.ts","../src/workflow/hooks/useFlow.ts","../src/workflow/utils/geometry.ts","../src/components/Switch/Switch.tsx","../src/workflow/store/selectors.ts","../src/workflow/store/context.ts","../src/components/NumberInput/NumberInput.tsx","../src/components/Tabs/Tabs.tsx","../src/workflow/store/changes.ts","../src/workflow/utils/parenting.ts","../src/workflow/components/FlowEdge/FlowEdge.tsx","../src/workflow/components/Handle/handleRegistry.ts","../src/workflow/components/FlowNode/FlowNodeContext.tsx","../src/workflow/components/FlowNode/FlowNode.tsx","../src/workflow/components/FlowCanvas/FlowCanvasContext.tsx","../src/workflow/components/FlowNode/nodeKinds.ts","../src/workflow/components/Handle/Handle.tsx","../src/workflow/components/NodeResizer/NodeResizer.tsx","../src/workflow/components/kinds/BaseNode.tsx","../src/workflow/components/kinds/index.tsx","../src/workflow/components/FlowCanvas/FlowCanvas.tsx","../src/workflow/store/createFlowStore.ts","../src/workflow/utils/collision.ts"],"sourcesContent":["\"use client\";\nimport {\n type ComponentPropsWithoutRef,\n type ElementType,\n forwardRef,\n type KeyboardEvent,\n type MouseEvent,\n type ReactNode,\n type Ref,\n} from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { Slot } from \"../../utils/Slot\";\n\n/* ---------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\nexport type BadgeVariant =\n | \"success\"\n | \"warning\"\n | \"error\"\n | \"info\"\n | \"neutral\"\n | \"accent\";\n\nexport type BadgeSize = \"sm\" | \"md\" | \"lg\";\n\nexport interface BadgeProps\n extends Omit<ComponentPropsWithoutRef<\"span\">, \"color\" | \"onClick\"> {\n variant?: BadgeVariant;\n size?: BadgeSize;\n\n /** Render a colored dot before the text. Mutually exclusive with `icon`. */\n dot?: boolean;\n /** Custom icon node rendered before the text. If both `icon` and `dot`\n * are passed, `icon` wins. */\n icon?: ReactNode;\n\n /** Render a `×` button to remove the badge. */\n closable?: boolean;\n /** @deprecated Use `closable`. Kept as an alias for back-compat. */\n closeable?: boolean;\n /** Fires when the user clicks (or activates via keyboard) the close\n * button. Receives the MouseEvent so callers can `stopPropagation` /\n * `preventDefault` as needed. */\n onClose?: (event: MouseEvent<HTMLButtonElement>) => void;\n /** Accessible label for the close button. Defaults to \"Remove\". Override\n * for localization or contextual reads (\"Remove tag 'cdc'\"). */\n closeLabel?: string;\n\n /** Thin outline + transparent background instead of the filled chip. */\n outlined?: boolean;\n\n /** Truncate long text with an ellipsis and surface the full content as a\n * `title` tooltip. `true` uses the design default (200 px); a number sets\n * an explicit max-width in px. */\n truncate?: boolean | number;\n\n /** Numeric badge convenience. Renders the value (or \"99+\" if > 99).\n * Ignored when `children` is also set. */\n count?: number;\n\n /** Click handler for the entire badge. Sets `role=\"button\"` and wires\n * Enter / Space keyboard activation. */\n onClick?: (event: MouseEvent<HTMLSpanElement>) => void;\n\n /** Render Badge's styling onto a custom child element (Radix-style Slot).\n * Useful for letting Badge own the chrome while a router link / tooltip\n * trigger / etc. owns the actual element semantics.\n *\n * Example:\n * <Badge asChild variant=\"accent\">\n * <NextLink href=\"/pricing\">Beta</NextLink>\n * </Badge>\n *\n * When `asChild` is true, Badge does NOT render its internal `dot`,\n * `icon`, or close-button slots — the consumer fully owns the content.\n * For chips with built-in slots, use the regular form without asChild. */\n asChild?: boolean;\n\n children?: ReactNode;\n}\n\n/* ---------------------------------------------------------------------------\n * Helpers\n * ------------------------------------------------------------------------- */\n\nfunction formatCount(value: number): string {\n if (!Number.isFinite(value)) return \"\";\n if (value < 0) return \"0\";\n if (value > 99) return \"99+\";\n return String(Math.floor(value));\n}\n\n/** Inline close glyph — kept self-contained so Badge has no runtime dep on\n * `@octaviaflow/icons` (Badge is imported by very low-level surfaces that\n * shouldn't pull the icon package). */\nfunction CloseGlyph() {\n return (\n <svg\n width=\"10\"\n height=\"10\"\n viewBox=\"0 0 10 10\"\n fill=\"none\"\n aria-hidden=\"true\"\n focusable=\"false\"\n >\n <path\n d=\"M2 2 L8 8 M8 2 L2 8\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n />\n </svg>\n );\n}\n\n/* ---------------------------------------------------------------------------\n * Component\n * ------------------------------------------------------------------------- */\n\nexport const Badge = forwardRef<HTMLSpanElement, BadgeProps>(function Badge(\n {\n variant = \"neutral\",\n size = \"md\",\n dot = false,\n icon,\n closable,\n closeable, // deprecated alias\n onClose,\n closeLabel = \"Remove\",\n outlined = false,\n truncate = false,\n count,\n onClick,\n asChild = false,\n className,\n children,\n style,\n ...rest\n },\n ref,\n) {\n // Back-compat: prefer `closable` when set; fall back to legacy `closeable`.\n const isClosable = closable ?? closeable ?? false;\n const isClickable = Boolean(onClick);\n\n // `count` is short-hand for numeric content. Real `children` always wins\n // — that's the spec for filter chips that happen to also carry a count.\n const displayChildren =\n children ?? (count !== undefined ? formatCount(count) : undefined);\n\n // Truncation: turn the bool/number into a concrete style on the text span.\n // We attach `title` on the root for the hover-tooltip when content is a\n // plain string (so AT and mouse users both get the full label).\n const maxWidth =\n truncate === true ? \"var(--ods-badge-max-width, 200px)\" : typeof truncate === \"number\" ? `${truncate}px` : undefined;\n const truncateTitle =\n truncate && typeof displayChildren === \"string\" ? displayChildren : undefined;\n\n const handleKeyDown = (e: KeyboardEvent<HTMLSpanElement>) => {\n if (!isClickable) return;\n if ((e.key === \"Enter\" || e.key === \" \") && !e.repeat) {\n e.preventDefault();\n onClick?.(e as unknown as MouseEvent<HTMLSpanElement>);\n }\n };\n\n const handleCloseClick = (e: MouseEvent<HTMLButtonElement>) => {\n // Stop propagation so a Badge nested inside a clickable surface (card,\n // row, tag-input) doesn't fire the parent's onClick when the user is\n // removing the chip. Callers can still observe the event via onClose.\n e.stopPropagation();\n onClose?.(e);\n };\n\n const rootClassName = cn(\n \"ods-badge\",\n `ods-badge--${variant}`,\n `ods-badge--${size}`,\n outlined && \"ods-badge--outlined\",\n isClickable && \"ods-badge--interactive\",\n truncate && \"ods-badge--truncate\",\n className,\n );\n\n // asChild mode: clone the consumer's element and apply Badge's styling /\n // accessibility surface onto it. Internal slots (dot, icon, close) are\n // not rendered — the consumer's element fully owns the content.\n if (asChild) {\n return (\n <Slot\n {...(rest as ComponentPropsWithoutRef<ElementType>)}\n ref={ref as Ref<HTMLElement>}\n className={rootClassName}\n style={style}\n role={isClickable ? \"button\" : rest.role}\n tabIndex={isClickable ? (rest.tabIndex ?? 0) : rest.tabIndex}\n onClick={onClick as ((e: MouseEvent<HTMLElement>) => void) | undefined}\n onKeyDown={isClickable ? handleKeyDown : rest.onKeyDown}\n title={truncateTitle ?? rest.title}\n >\n {children as React.ReactElement}\n </Slot>\n );\n }\n\n return (\n <span\n {...rest}\n ref={ref}\n className={rootClassName}\n style={style}\n // The whole badge becomes a button when onClick is set. Otherwise we\n // leave the role unset so it stays a plain inline element.\n role={isClickable ? \"button\" : rest.role}\n tabIndex={isClickable ? (rest.tabIndex ?? 0) : rest.tabIndex}\n onClick={onClick as MouseEvent<HTMLSpanElement> extends MouseEvent<HTMLSpanElement> ? typeof onClick : never}\n onKeyDown={isClickable ? handleKeyDown : rest.onKeyDown}\n title={truncateTitle ?? rest.title}\n >\n {icon ? (\n <span className=\"ods-badge__icon\" aria-hidden=\"true\">\n {icon}\n </span>\n ) : dot ? (\n <span className=\"ods-badge__dot\" aria-hidden=\"true\" />\n ) : null}\n <span\n className=\"ods-badge__text\"\n style={maxWidth ? { maxWidth } : undefined}\n >\n {displayChildren}\n </span>\n {isClosable && (\n <button\n type=\"button\"\n className=\"ods-badge__close\"\n onClick={handleCloseClick}\n aria-label={closeLabel}\n >\n <CloseGlyph />\n </button>\n )}\n </span>\n );\n});\n\nBadge.displayName = \"Badge\";\n","\"use client\";\nimport {\n type InputHTMLAttributes,\n type ReactNode,\n forwardRef,\n useId,\n useImperativeHandle,\n useRef,\n} from \"react\";\nimport { useCheckbox } from \"react-aria\";\nimport { useToggleState } from \"react-stately\";\nimport { resolveAccessibleName } from \"../../utils/a11y\";\nimport { cn } from \"../../utils/cn\";\n\n/* ---------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\nexport type CheckboxSize = \"sm\" | \"md\" | \"lg\";\n\nexport interface CheckboxProps\n extends Omit<InputHTMLAttributes<HTMLInputElement>, \"onChange\" | \"size\"> {\n /** Controlled checked state. */\n checked?: boolean;\n /** Uncontrolled initial state. */\n defaultChecked?: boolean;\n /** Fires with the new selection state. */\n onChange?: (isSelected: boolean) => void;\n /** Mixed-state checkbox (for \"select all\" with partial children). */\n indeterminate?: boolean;\n disabled?: boolean;\n /** Visible label. Pair with `description` for \"label + helper text\" stacks. */\n label?: ReactNode;\n /** Optional helper text below the label. Linked via `aria-describedby` so\n * AT users hear the description after the label. */\n description?: ReactNode;\n /** Mark the field as invalid. Adds the error tint + `aria-invalid`. */\n error?: boolean;\n /** Error message rendered under the description. */\n errorMessage?: ReactNode;\n size?: CheckboxSize;\n className?: string;\n}\n\n/* ---------------------------------------------------------------------------\n * Component\n * ------------------------------------------------------------------------- */\n\nexport const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(\n function Checkbox(\n {\n checked,\n defaultChecked,\n onChange,\n indeterminate = false,\n disabled = false,\n label,\n description,\n error = false,\n errorMessage,\n size = \"md\",\n required,\n className,\n ...props\n },\n forwardedRef,\n ) {\n const internalRef = useRef<HTMLInputElement>(null);\n useImperativeHandle(forwardedRef, () => internalRef.current as HTMLInputElement);\n\n const state = useToggleState({\n isSelected: checked,\n defaultSelected: defaultChecked,\n onChange,\n });\n\n // ─ Stable IDs for description / error message wiring ──────────────────\n const reactId = useId();\n const baseId = (props.id as string | undefined) ?? `ods-cb-${reactId}`;\n const descId = description ? `${baseId}-desc` : undefined;\n const errId = error && errorMessage ? `${baseId}-err` : undefined;\n const describedBy = [descId, errId].filter(Boolean).join(\" \") || undefined;\n\n // Resolve accessible name from {label, aria-label, aria-labelledby}.\n const ariaNameProps = resolveAccessibleName({\n label,\n ariaLabel: (props as any)[\"aria-label\"],\n ariaLabelledby: (props as any)[\"aria-labelledby\"],\n componentName: \"Checkbox\",\n });\n\n const { inputProps } = useCheckbox(\n {\n isSelected: state.isSelected,\n isIndeterminate: indeterminate,\n isDisabled: disabled,\n isRequired: required,\n isInvalid: error,\n onChange,\n // useCheckbox returns `name`/`value`/`form` in its `inputProps`. If\n // we let them fall through as `undefined`, the spread overwrites\n // the consumer's attrs. Pass them via the config so react-aria\n // emits real values.\n name: (props as { name?: string }).name,\n value: (props as { value?: string }).value,\n form: (props as { form?: string }).form,\n ...ariaNameProps,\n },\n state,\n internalRef,\n );\n\n const isChecked = state.isSelected;\n\n // React Aria owns the interactive event handlers. Strip those from the\n // caller's props so we don't double-bind, then let native form attrs\n // (name, value, form, required, autoFocus, etc.) flow to the DOM.\n const {\n onClick: _onClick,\n onKeyDown: _onKeyDown,\n onKeyUp: _onKeyUp,\n onFocus: _onFocus,\n onBlur: _onBlur,\n ...passthroughProps\n } = props as Record<string, unknown>;\n\n return (\n <label\n className={cn(\n \"ods-checkbox\",\n `ods-checkbox--${size}`,\n disabled && \"ods-checkbox--disabled\",\n error && \"ods-checkbox--error\",\n description && \"ods-checkbox--with-description\",\n className,\n )}\n >\n <input\n {...(passthroughProps as any)}\n {...inputProps}\n id={baseId}\n ref={internalRef}\n aria-describedby={describedBy}\n className=\"ods-checkbox__input\"\n />\n <span\n className={cn(\n \"ods-checkbox__box\",\n isChecked && !indeterminate && \"ods-checkbox__box--checked\",\n indeterminate && \"ods-checkbox__box--indeterminate\",\n )}\n aria-hidden=\"true\"\n >\n {indeterminate ? (\n <svg\n className=\"ods-checkbox__dash\"\n viewBox=\"0 0 12 12\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <line\n x1=\"2\"\n y1=\"6\"\n x2=\"10\"\n y2=\"6\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n />\n </svg>\n ) : (\n <svg\n className={cn(\n \"ods-checkbox__checkmark\",\n isChecked && \"ods-checkbox__checkmark--checked\",\n )}\n viewBox=\"0 0 12 12\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M2 6L5 9L10 3\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n )}\n </span>\n {(label || description || errorMessage) && (\n <span className=\"ods-checkbox__text\">\n {label && (\n <span className=\"ods-checkbox__label\">\n {label}\n {required && (\n <span className=\"ods-checkbox__required\" aria-hidden=\"true\">\n *\n </span>\n )}\n </span>\n )}\n {description && (\n <span id={descId} className=\"ods-checkbox__description\">\n {description}\n </span>\n )}\n {error && errorMessage && (\n <span\n id={errId}\n className=\"ods-checkbox__error-message\"\n role=\"alert\"\n >\n {errorMessage}\n </span>\n )}\n </span>\n )}\n </label>\n );\n },\n);\n\nCheckbox.displayName = \"Checkbox\";\n","\"use client\";\nimport { AnimatePresence, motion, useReducedMotion } from \"framer-motion\";\nimport {\n type ComponentPropsWithoutRef,\n type ElementType,\n forwardRef,\n type ReactElement,\n type ReactNode,\n type Ref,\n useEffect,\n useRef,\n} from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { Slot } from \"../../utils/Slot\";\n\n/* ---------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\nexport type BannerVariant = \"info\" | \"success\" | \"warning\" | \"error\" | \"promo\" | \"neutral\";\nexport type BannerSize = \"sm\" | \"md\" | \"lg\";\n\n/** Direction the banner slides in / out from. Default = `down` (enters\n * slightly above its final position, settles down + fades in). */\nexport type BannerAnimateFrom = \"top\" | \"bottom\" | \"left\" | \"right\" | \"none\";\nexport type BannerAppearance = \"filled\" | \"outlined\" | \"subtle\";\n\nexport interface BannerProps\n extends Omit<ComponentPropsWithoutRef<\"div\">, \"color\" | \"title\"> {\n /** Visual / semantic variant. `error` defaults to `role=\"alert\"`; the rest\n * default to `role=\"status\"` (polite live region). */\n variant?: BannerVariant;\n /** Size variant. */\n size?: BannerSize;\n /** Appearance treatment. `filled` (default) uses the variant's bg/border;\n * `outlined` keeps the border but drops the fill; `subtle` mutes both. */\n appearance?: BannerAppearance;\n\n /** Leading icon. If omitted, Banner renders a sensible default per\n * variant (info/success/warning/error/promo). Pass `null` explicitly to\n * suppress the default. */\n icon?: ReactNode | null;\n title?: ReactNode;\n description?: ReactNode;\n\n /** Trailing action slot (typically a Button). */\n action?: ReactNode;\n /** Renders a dismiss `×` button on the trailing edge. */\n dismissible?: boolean;\n /** Fires when the dismiss button is clicked. */\n onDismiss?: () => void;\n /** Accessible label for the dismiss button. Defaults to \"Dismiss\". */\n dismissLabel?: string;\n\n /** Override the inferred role. Pass explicitly for non-default\n * announcements (\"alert\", \"alertdialog\", \"region\", etc.). */\n role?: ComponentPropsWithoutRef<\"div\">[\"role\"];\n\n /** Auto-focus the banner when it first mounts. Useful for error banners\n * that should grab focus on appearance so AT users notice them. */\n autoFocus?: boolean;\n\n /** Controls whether the banner is mounted. Pair with `useBanner()` for\n * declarative show/hide state, or wire to your own state. When omitted,\n * the banner is always mounted (the regular, animation-free shape). */\n open?: boolean;\n /** Direction the enter/exit animation slides from. Defaults to `top`.\n * `none` disables the slide entirely (still fades). */\n animateFrom?: BannerAnimateFrom;\n /** Disable all enter/exit motion. Use when the banner is part of a\n * larger animation managed externally. */\n disableAnimation?: boolean;\n\n /** Render Banner's styling onto a custom child element (Radix-style Slot).\n *\n * Example — a clickable banner-as-link:\n * <Banner asChild variant=\"promo\">\n * <a href=\"/changelog\">New release! See what's new →</a>\n * </Banner>\n *\n * When `asChild` is true, Banner does NOT render its internal icon /\n * title / description / action / dismiss slots. The consumer's element\n * fully owns the content. */\n asChild?: boolean;\n\n children?: ReactNode;\n}\n\n/* ---------------------------------------------------------------------------\n * Default per-variant icons — self-contained SVGs so Banner has no runtime\n * dependency on @octaviaflow/icons. They inherit color via `currentColor`\n * so the variant's icon color applies.\n * ------------------------------------------------------------------------- */\n\nfunction InfoIcon() {\n return (\n <svg viewBox=\"0 0 18 18\" fill=\"none\" aria-hidden=\"true\" focusable=\"false\">\n <circle cx=\"9\" cy=\"9\" r=\"7.5\" stroke=\"currentColor\" strokeWidth=\"1.5\" />\n <path d=\"M9 8v4\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" />\n <circle cx=\"9\" cy=\"5.5\" r=\"0.9\" fill=\"currentColor\" />\n </svg>\n );\n}\nfunction SuccessIcon() {\n return (\n <svg viewBox=\"0 0 18 18\" fill=\"none\" aria-hidden=\"true\" focusable=\"false\">\n <circle cx=\"9\" cy=\"9\" r=\"7.5\" stroke=\"currentColor\" strokeWidth=\"1.5\" />\n <path d=\"M5.5 9.2 8 11.5 12.5 6.5\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n );\n}\nfunction WarningIcon() {\n return (\n <svg viewBox=\"0 0 18 18\" fill=\"none\" aria-hidden=\"true\" focusable=\"false\">\n <path d=\"M9 2 L16 15 H2 Z\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinejoin=\"round\" />\n <path d=\"M9 7v4\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" />\n <circle cx=\"9\" cy=\"13\" r=\"0.9\" fill=\"currentColor\" />\n </svg>\n );\n}\nfunction ErrorIcon() {\n return (\n <svg viewBox=\"0 0 18 18\" fill=\"none\" aria-hidden=\"true\" focusable=\"false\">\n <circle cx=\"9\" cy=\"9\" r=\"7.5\" stroke=\"currentColor\" strokeWidth=\"1.5\" />\n <path d=\"M6.5 6.5 11.5 11.5 M11.5 6.5 6.5 11.5\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" />\n </svg>\n );\n}\nfunction PromoIcon() {\n return (\n <svg viewBox=\"0 0 18 18\" fill=\"none\" aria-hidden=\"true\" focusable=\"false\">\n <path\n d=\"M9 1.5 L11 6.5 L16.5 7 L12.4 10.7 L13.7 16 L9 13 L4.3 16 L5.6 10.7 L1.5 7 L7 6.5 Z\"\n stroke=\"currentColor\"\n strokeWidth=\"1.4\"\n strokeLinejoin=\"round\"\n />\n </svg>\n );\n}\n\nconst DEFAULT_ICONS: Record<BannerVariant, () => ReactElement> = {\n info: InfoIcon,\n success: SuccessIcon,\n warning: WarningIcon,\n error: ErrorIcon,\n promo: PromoIcon,\n neutral: InfoIcon,\n};\n\nfunction DismissGlyph() {\n return (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" aria-hidden=\"true\" focusable=\"false\">\n <path\n d=\"M3.5 3.5 L10.5 10.5 M10.5 3.5 L3.5 10.5\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n />\n </svg>\n );\n}\n\n/* ---------------------------------------------------------------------------\n * Component\n * ------------------------------------------------------------------------- */\n\n/* ---------------------------------------------------------------------------\n * Enter/exit motion offsets per direction. Subtle by design — banners\n * shouldn't fly across the viewport on appear; ~8 px is enough to read as\n * \"arrived\" without distracting from the content. Under reduced-motion we\n * zero out the transform and just cross-fade.\n * ------------------------------------------------------------------------- */\nconst MOTION_OFFSETS: Record<BannerAnimateFrom, { x: number; y: number }> = {\n top: { x: 0, y: -8 },\n bottom: { x: 0, y: 8 },\n left: { x: -8, y: 0 },\n right: { x: 8, y: 0 },\n none: { x: 0, y: 0 },\n};\n\nexport const Banner = forwardRef<HTMLDivElement, BannerProps>(function Banner(\n {\n variant = \"info\",\n size = \"md\",\n appearance = \"filled\",\n icon,\n title,\n description,\n action,\n dismissible = false,\n onDismiss,\n dismissLabel = \"Dismiss\",\n role,\n autoFocus = false,\n asChild = false,\n open,\n animateFrom = \"top\",\n disableAnimation = false,\n className,\n children,\n ...rest\n },\n ref,\n) {\n // Variant → default ARIA role. `error` is announced as an alert so AT\n // interrupts; everything else is a polite live status region.\n const resolvedRole = role ?? (variant === \"error\" ? \"alert\" : \"status\");\n\n // Resolve the icon: explicit `null` → suppress; undefined → variant default;\n // anything else → as passed.\n const DefaultIconComponent = DEFAULT_ICONS[variant];\n const resolvedIcon =\n icon === null ? null : icon === undefined ? <DefaultIconComponent /> : icon;\n\n // Hooks must run unconditionally (rules of hooks). Compose them up here\n // even though some render paths below don't use them.\n const reducedMotion = useReducedMotion();\n const internalRef = useRef<HTMLDivElement | null>(null);\n const setRef = (node: HTMLDivElement | null) => {\n internalRef.current = node;\n if (typeof ref === \"function\") ref(node);\n else if (ref) (ref as { current: HTMLDivElement | null }).current = node;\n };\n\n useEffect(() => {\n if (autoFocus && internalRef.current) {\n // Banner is not normally focusable; ensure tabIndex=-1 so focus() is\n // programmatically valid without exposing the banner to Tab traversal.\n internalRef.current.focus({ preventScroll: false });\n }\n }, [autoFocus]);\n\n const rootClassName = cn(\n \"ods-banner\",\n `ods-banner--${variant}`,\n `ods-banner--${size}`,\n `ods-banner--${appearance}`,\n className,\n );\n\n // asChild mode — clone the consumer's element and project Banner's chrome\n // onto it. Internal slots aren't rendered.\n if (asChild) {\n return (\n <Slot\n {...(rest as ComponentPropsWithoutRef<ElementType>)}\n ref={ref as Ref<HTMLElement>}\n className={rootClassName}\n role={resolvedRole}\n >\n {children as ReactElement}\n </Slot>\n );\n }\n\n // Inner slots shared by every render path (plain / animated / static\n // closed). Pulled out so the animation wrapper doesn't duplicate JSX.\n const innerSlots = (\n <>\n {resolvedIcon && (\n <span className=\"ods-banner__icon\" aria-hidden=\"true\">\n {resolvedIcon}\n </span>\n )}\n <div className=\"ods-banner__body\">\n {title && <div className=\"ods-banner__title\">{title}</div>}\n {description && <div className=\"ods-banner__description\">{description}</div>}\n {children}\n </div>\n {action && <div className=\"ods-banner__action\">{action}</div>}\n {dismissible && (\n <button\n type=\"button\"\n className=\"ods-banner__dismiss\"\n onClick={onDismiss}\n aria-label={dismissLabel}\n >\n <DismissGlyph />\n </button>\n )}\n </>\n );\n\n // Uncontrolled mode (no `open` prop): always rendered, no animation.\n // Keeps the legacy / static shape working for consumers that don't need\n // mount/unmount behaviour.\n if (open === undefined) {\n return (\n <div\n {...rest}\n ref={setRef}\n className={rootClassName}\n role={resolvedRole}\n tabIndex={autoFocus ? -1 : rest.tabIndex}\n >\n {innerSlots}\n </div>\n );\n }\n\n // Controlled mode without animation — plain mount/unmount.\n if (disableAnimation) {\n if (!open) return null;\n return (\n <div\n {...rest}\n ref={setRef}\n className={rootClassName}\n role={resolvedRole}\n tabIndex={autoFocus ? -1 : rest.tabIndex}\n >\n {innerSlots}\n </div>\n );\n }\n\n // Controlled mode with animation: AnimatePresence drives enter/exit.\n // Under prefers-reduced-motion we zero out the transform and rely on the\n // opacity cross-fade only — which is well under perceptual thresholds.\n const offset = reducedMotion\n ? { x: 0, y: 0 }\n : MOTION_OFFSETS[animateFrom];\n\n return (\n <AnimatePresence initial={false}>\n {open && (\n <motion.div\n {...(rest as Omit<typeof rest, \"onDrag\" | \"onDragStart\" | \"onDragEnd\" | \"onAnimationStart\" | \"onAnimationEnd\">)}\n ref={setRef}\n className={rootClassName}\n role={resolvedRole}\n tabIndex={autoFocus ? -1 : rest.tabIndex}\n initial={{ opacity: 0, x: offset.x, y: offset.y }}\n animate={{ opacity: 1, x: 0, y: 0 }}\n exit={{ opacity: 0, x: offset.x, y: offset.y }}\n transition={{ duration: 0.18, ease: [0.16, 1, 0.3, 1] }}\n >\n {innerSlots}\n </motion.div>\n )}\n </AnimatePresence>\n );\n});\n\nBanner.displayName = \"Banner\";\n","\"use client\";\nimport { useMemo } from \"react\";\n\n/* ---------------------------------------------------------------------------\n * usePasswordStrength — declarative password-rule evaluation\n *\n * Evaluates a password value against an ordered list of rules and returns a\n * 0–4 score plus per-rule pass/fail metadata. The score is ratio-based so\n * it stays sensible regardless of how many rules the consumer configures\n * (a 4-of-4 rule set and an 8-of-8 rule set both top out at score 4).\n *\n * const { score, rules, passed, total, isValid } = usePasswordStrength(\n * value,\n * [\n * { id: \"len\", label: \"At least 8 chars\", test: /.{8,}/ },\n * { id: \"low\", label: \"A lower-case letter\", test: /[a-z]/ },\n * { id: \"up\", label: \"An upper-case letter\", test: /[A-Z]/ },\n * { id: \"num\", label: \"A digit\", test: /\\d/ },\n * ],\n * );\n *\n * Defaults: when `rules` is omitted, `DEFAULT_PASSWORD_RULES` is used\n * (4 rules: length-8, lower, upper, digit). Pass an empty array to\n * disable all rules (score will always be 0).\n * ------------------------------------------------------------------------- */\n\nexport interface PasswordRule {\n /** Stable id — keyed in the result for React rendering and useful for\n * driving per-rule a11y associations. */\n id: string;\n /** Human-readable description (\"At least 8 characters\"). Surfaced in\n * the PasswordInput requirements checklist. */\n label: string;\n /** Regex (preferred) or predicate function. Regexes are tested with\n * `.test(value)`; predicates receive the raw value. */\n test: RegExp | ((value: string) => boolean);\n}\n\nexport interface PasswordRuleResult {\n id: string;\n label: string;\n passed: boolean;\n}\n\nexport type PasswordStrengthScore = 0 | 1 | 2 | 3 | 4;\n\nexport interface PasswordStrengthResult {\n /** 0–4, derived from `passed / total` (ratio-scaled). 0 = very weak,\n * 4 = very strong. */\n score: PasswordStrengthScore;\n /** Per-rule pass/fail in the order rules were supplied. */\n rules: PasswordRuleResult[];\n /** Count of rules that passed. */\n passed: number;\n /** Total rules evaluated. */\n total: number;\n /** True iff every rule passed (or the rule set is empty — vacuously\n * satisfied; consumers should usually require a non-empty rule set). */\n isValid: boolean;\n}\n\n/* ---------------------------------------------------------------------------\n * Defaults\n * ------------------------------------------------------------------------- */\n\n/** Reasonable starter rule set — 8-char minimum + character-class diversity.\n * Consumers should override for any compliance regime (passphrases,\n * banking, etc.). */\nexport const DEFAULT_PASSWORD_RULES: PasswordRule[] = [\n { id: \"length-8\", label: \"At least 8 characters\", test: /.{8,}/ },\n { id: \"lowercase\", label: \"A lower-case letter\", test: /[a-z]/ },\n { id: \"uppercase\", label: \"An upper-case letter\", test: /[A-Z]/ },\n { id: \"digit\", label: \"A digit\", test: /\\d/ },\n];\n\n/* ---------------------------------------------------------------------------\n * Hook\n * ------------------------------------------------------------------------- */\n\nexport function usePasswordStrength(\n value: string,\n rules: PasswordRule[] = DEFAULT_PASSWORD_RULES,\n): PasswordStrengthResult {\n return useMemo(() => {\n const evaluated: PasswordRuleResult[] = rules.map((r) => ({\n id: r.id,\n label: r.label,\n passed: runRule(r.test, value),\n }));\n const passed = evaluated.filter((r) => r.passed).length;\n const total = evaluated.length;\n const score = computeScore(passed, total);\n return {\n score,\n rules: evaluated,\n passed,\n total,\n isValid: total === 0 || passed === total,\n };\n }, [value, rules]);\n}\n\n/* ---------------------------------------------------------------------------\n * Helpers\n * ------------------------------------------------------------------------- */\n\nfunction runRule(\n test: PasswordRule[\"test\"],\n value: string,\n): boolean {\n if (typeof test === \"function\") return test(value);\n // Regexes used as rule predicates can be stateful (the `g` and `y` flags\n // hold a `lastIndex` between calls). Re-running `.test` on a stale regex\n // returns wrong results — reset before testing.\n test.lastIndex = 0;\n return test.test(value);\n}\n\nfunction computeScore(passed: number, total: number): PasswordStrengthScore {\n if (total === 0) return 0;\n // Ratio-based: 0/total → 0, total/total → 4, evenly stepped between.\n // `floor(ratio * 5)` maps to {0,1,2,3,4,5} — clamp the perfect score\n // back to 4 so the meter caps at \"Very strong\".\n const ratio = passed / total;\n return Math.min(4, Math.floor(ratio * 5)) as PasswordStrengthScore;\n}\n","\"use client\";\nimport {\n type ChangeEvent,\n type ComponentPropsWithoutRef,\n forwardRef,\n type ReactNode,\n useId,\n useState,\n} from \"react\";\nimport { CheckmarkIcon, ViewIcon, ViewOffIcon } from \"@octaviaflow/icons\";\nimport {\n type PasswordRule,\n type PasswordStrengthScore,\n usePasswordStrength,\n} from \"../../hooks/usePasswordStrength\";\nimport { cn } from \"../../utils/cn\";\n\n/* ---------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\nexport type PasswordInputSize = \"sm\" | \"md\" | \"lg\";\n\ntype InputPropsBase = Omit<\n ComponentPropsWithoutRef<\"input\">,\n \"type\" | \"size\" | \"value\" | \"onChange\" | \"prefix\"\n>;\n\nexport interface PasswordInputProps extends InputPropsBase {\n label?: ReactNode;\n value: string;\n onChange?: (value: string) => void;\n size?: PasswordInputSize;\n error?: ReactNode;\n helperText?: ReactNode;\n /** 0–4 strength score. When set, renders the visual strength meter.\n * `strength` takes precedence over `strengthRules` so consumers can\n * always override what the rules computed (e.g. server-derived score). */\n strength?: PasswordStrengthScore;\n /** Rule set to evaluate the password against. When provided (and\n * `strength` is NOT), the component runs `usePasswordStrength`\n * internally and renders the meter from the derived score. */\n strengthRules?: PasswordRule[];\n /** Render the requirements checklist below the meter. Each rule shows\n * a met/unmet glyph + its label, and the list is wired via\n * `aria-describedby` so screen readers announce the state. */\n showRequirements?: boolean;\n /** Show the show/hide-password toggle. Default true. */\n showToggle?: boolean;\n leftIcon?: ReactNode;\n /** Extra class on the wrapper (NOT the input). */\n wrapperClassName?: string;\n}\n\nconst strengthLabels = [\n \"Very weak\",\n \"Weak\",\n \"Fair\",\n \"Strong\",\n \"Very strong\",\n] as const;\n\n/* ---------------------------------------------------------------------------\n * Component\n * ------------------------------------------------------------------------- */\n\nexport const PasswordInput = forwardRef<HTMLInputElement, PasswordInputProps>(\n function PasswordInput(\n {\n label,\n value,\n onChange,\n size = \"md\",\n error,\n helperText,\n strength,\n strengthRules,\n showRequirements = false,\n showToggle = true,\n leftIcon,\n disabled,\n id: providedId,\n className,\n wrapperClassName,\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledBy,\n \"aria-describedby\": consumerDescribedBy,\n ...rest\n },\n ref,\n ) {\n const reactId = useId();\n const inputId = providedId ?? `ods-pwd-${reactId}`;\n const labelId = label ? `${inputId}-label` : undefined;\n const hintId = error || helperText ? `${inputId}-hint` : undefined;\n // strengthId is rendered only when the meter is actually displayed.\n // We resolve `effectiveScore` below; the id is built upfront so the\n // memoization order stays stable, and we strip it from describedBy\n // when there's nothing to describe.\n\n const [shown, setShown] = useState(false);\n const handle = (e: ChangeEvent<HTMLInputElement>) =>\n onChange?.(e.target.value);\n\n // Hook ALWAYS runs — pass an empty rule list when the consumer didn't\n // configure one to keep the call cheap. Manual `strength` wins over\n // the derived score so server-side / app-side computations override\n // the local heuristic. The meter renders whenever EITHER the manual\n // score or a non-empty rule set is provided.\n const derived = usePasswordStrength(value, strengthRules ?? []);\n const ruleDriven = (strengthRules?.length ?? 0) > 0;\n const effectiveScore: PasswordStrengthScore | undefined =\n typeof strength === \"number\"\n ? strength\n : ruleDriven\n ? derived.score\n : undefined;\n const strengthId =\n typeof effectiveScore === \"number\" ? `${inputId}-strength` : undefined;\n const requirementsId =\n showRequirements && ruleDriven ? `${inputId}-requirements` : undefined;\n\n // Compose aria-describedby — consumer's value wins, then our hint id,\n // then the strength meter so AT users hear \"Weak / Strong / …\", then\n // the requirements checklist so they hear \"3 of 4 met\".\n const describedBy =\n [consumerDescribedBy, hintId, strengthId, requirementsId]\n .filter(Boolean)\n .join(\" \") || undefined;\n\n return (\n <div\n className={cn(\n \"ods-pwd\",\n `ods-pwd--${size}`,\n disabled && \"ods-pwd--disabled\",\n error && \"ods-pwd--error\",\n wrapperClassName,\n )}\n >\n {label && (\n <label\n id={labelId}\n htmlFor={inputId}\n className=\"ods-pwd__label\"\n >\n {label}\n </label>\n )}\n <div className=\"ods-pwd__field\">\n {leftIcon && (\n <span className=\"ods-pwd__icon\" aria-hidden=\"true\">\n {leftIcon}\n </span>\n )}\n <input\n {...rest}\n ref={ref}\n id={inputId}\n type={shown ? \"text\" : \"password\"}\n value={value}\n onChange={handle}\n disabled={disabled}\n className={cn(\"ods-pwd__input\", className)}\n aria-invalid={error ? true : undefined}\n aria-describedby={describedBy}\n aria-labelledby={ariaLabelledBy ?? labelId}\n aria-label={\n !labelId && !ariaLabelledBy ? ariaLabel : undefined\n }\n />\n {showToggle && (\n <button\n type=\"button\"\n className=\"ods-pwd__toggle\"\n onClick={() => setShown((s) => !s)}\n aria-label={shown ? \"Hide password\" : \"Show password\"}\n aria-pressed={shown}\n disabled={disabled}\n tabIndex={-1}\n >\n {shown ? <ViewOffIcon /> : <ViewIcon />}\n </button>\n )}\n </div>\n {typeof effectiveScore === \"number\" && (\n <div\n id={strengthId}\n className=\"ods-pwd__strength\"\n data-level={effectiveScore}\n >\n <span className=\"ods-pwd__meter\" aria-hidden=\"true\">\n <span\n className={cn(\n \"ods-pwd__bar\",\n `ods-pwd__bar--${effectiveScore}`,\n )}\n />\n </span>\n <span className=\"ods-pwd__strength-label\">\n {strengthLabels[effectiveScore]}\n </span>\n </div>\n )}\n {showRequirements && ruleDriven && (\n // The checklist is decorative for sighted users + announced via\n // `aria-describedby` for AT. Each <li>'s `aria-label` encodes\n // state inline so screen readers say \"At least 8 characters,\n // met\" without any visible SR-only span — bullet-proof across\n // CSS reset variations and stale build artifacts.\n <ul\n id={requirementsId}\n className=\"ods-pwd__requirements\"\n aria-label={`Password requirements (${derived.passed} of ${derived.total} met)`}\n >\n {derived.rules.map((r) => (\n <li\n key={r.id}\n className={cn(\n \"ods-pwd__requirement\",\n r.passed && \"ods-pwd__requirement--met\",\n )}\n aria-label={`${r.label}, ${r.passed ? \"met\" : \"not met\"}`}\n >\n {/* Custom dot+check morph — the dot is a CSS-drawn 14-px\n * circle so we don't fight an icon's intrinsic sizing,\n * and the check fades + scales in on state flip for a\n * crisp micro-interaction. `prefers-reduced-motion`\n * drops the transitions in SCSS. */}\n <span\n className=\"ods-pwd__requirement-dot\"\n aria-hidden=\"true\"\n >\n <CheckmarkIcon\n size=\"xs\"\n tone=\"inverse\"\n className=\"ods-pwd__requirement-check\"\n />\n </span>\n <span className=\"ods-pwd__requirement-label\">{r.label}</span>\n </li>\n ))}\n </ul>\n )}\n {error ? (\n <div\n id={hintId}\n className=\"ods-pwd__hint ods-pwd__hint--error\"\n role=\"alert\"\n >\n {error}\n </div>\n ) : helperText ? (\n <div id={hintId} className=\"ods-pwd__hint\">\n {helperText}\n </div>\n ) : null}\n </div>\n );\n },\n);\n\nPasswordInput.displayName = \"PasswordInput\";\n","\"use client\";\nimport {\n CheckmarkIcon,\n CopyIcon,\n MagicWandIcon,\n SearchIcon,\n TextWrapIcon,\n} from \"@octaviaflow/icons\";\nimport {\n forwardRef,\n type ReactNode,\n useEffect,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { cn } from \"../../utils/cn\";\n\nexport type CodeEditorLanguage = \"sql\" | \"json\" | \"javascript\" | \"typescript\" | \"yaml\" | \"plain\";\n\nexport interface CodeEditorProps {\n value: string;\n onChange?: (value: string) => void;\n language?: CodeEditorLanguage;\n /** Read-only mode. */\n readOnly?: boolean;\n /** Hide the gutter (line numbers). */\n showLineNumbers?: boolean;\n /** Highlight the active line. */\n highlightActiveLine?: boolean;\n /** Number of spaces a Tab inserts. */\n tabSize?: number;\n /** Minimum height in pixels. */\n minHeight?: number;\n /** Maximum height in pixels. */\n maxHeight?: number;\n placeholder?: string;\n ariaLabel?: string;\n /** Optional toolbar slot above the editor. */\n toolbar?: ReactNode;\n /** Status pill on the right side of the toolbar. */\n status?: ReactNode;\n className?: string;\n /** Show built-in Copy button. Default true. */\n showCopy?: boolean;\n /** Show built-in Format button (JSON only by default). */\n showFormat?: boolean;\n /** Word wrap (controlled). */\n wordWrap?: boolean;\n /** Show built-in word-wrap toggle. Default true (only when uncontrolled). */\n showWordWrapToggle?: boolean;\n /** Enable auto-pair brackets and quotes. Default true. */\n autoPair?: boolean;\n /** Show character/selection counter at bottom. Default true. */\n showCounter?: boolean;\n /** Enable Cmd+F search bar. Default true. */\n searchable?: boolean;\n\n /** Form integration — passes through to the underlying <textarea>. */\n name?: string;\n /** Form attribute (for buttons rendered outside their parent form). */\n form?: string;\n /** Mark as required for native form validation. */\n required?: boolean;\n /** Native id (replaces the auto-generated one if you need to pair a\n * <label htmlFor> with this editor). */\n id?: string;\n}\n\nconst COMMENT_PREFIX: Record<CodeEditorLanguage, string> = {\n sql: \"-- \",\n json: \"// \",\n javascript: \"// \",\n typescript: \"// \",\n yaml: \"# \",\n plain: \"// \",\n};\n\nconst OPEN_PAIRS: Record<string, string> = {\n \"{\": \"}\",\n \"[\": \"]\",\n \"(\": \")\",\n '\"': '\"',\n \"'\": \"'\",\n \"`\": \"`\",\n};\nconst CLOSE_PAIRS = new Set(Object.values(OPEN_PAIRS));\n\nfunction tryFormat(value: string, language: CodeEditorLanguage): string | null {\n if (language === \"json\") {\n try {\n return JSON.stringify(JSON.parse(value), null, 2);\n } catch {\n return null;\n }\n }\n return null;\n}\n\nexport const CodeEditor = forwardRef<HTMLTextAreaElement, CodeEditorProps>(\n function CodeEditor(\n {\n value,\n onChange,\n language = \"plain\",\n readOnly = false,\n showLineNumbers = true,\n highlightActiveLine = true,\n tabSize = 2,\n minHeight = 120,\n maxHeight,\n placeholder = \"Type code here…\",\n ariaLabel = \"Code editor\",\n toolbar,\n status,\n className,\n showCopy = true,\n showFormat,\n wordWrap: wordWrapProp,\n showWordWrapToggle = true,\n autoPair = true,\n showCounter = true,\n searchable = true,\n name,\n form,\n required,\n id,\n },\n forwardedRef,\n ) {\n const taRef = useRef<HTMLTextAreaElement>(null);\n // Bridge the local ref to the forwarded one so consumers can access the\n // underlying textarea (focus, select, scrollIntoView, etc.).\n useImperativeHandle(forwardedRef, () => taRef.current as HTMLTextAreaElement);\n const gutterRef = useRef<HTMLDivElement>(null);\n const [activeLine, setActiveLine] = useState(1);\n const [copied, setCopied] = useState(false);\n const [internalWrap, setInternalWrap] = useState<boolean>(wordWrapProp ?? false);\n const wordWrap = wordWrapProp ?? internalWrap;\n const [selectionLen, setSelectionLen] = useState(0);\n const [selectionLines, setSelectionLines] = useState(0);\n const [findOpen, setFindOpen] = useState(false);\n const [findQuery, setFindQuery] = useState(\"\");\n const [findIndex, setFindIndex] = useState(0);\n const findInputRef = useRef<HTMLInputElement>(null);\n\n const lines = value.split(\"\\n\");\n const lineCount = lines.length;\n\n const matches = useMemo(() => {\n if (!findQuery) return [] as Array<{ start: number; end: number }>;\n const out: Array<{ start: number; end: number }> = [];\n const lower = value.toLowerCase();\n const q = findQuery.toLowerCase();\n let i = 0;\n while (i <= lower.length - q.length) {\n const idx = lower.indexOf(q, i);\n if (idx < 0) break;\n out.push({ start: idx, end: idx + q.length });\n i = idx + Math.max(1, q.length);\n }\n return out;\n }, [findQuery, value]);\n\n useEffect(() => {\n const ta = taRef.current;\n const gut = gutterRef.current;\n if (!ta || !gut) return;\n const onScroll = () => {\n gut.scrollTop = ta.scrollTop;\n };\n ta.addEventListener(\"scroll\", onScroll);\n return () => ta.removeEventListener(\"scroll\", onScroll);\n }, []);\n\n const updateSelection = () => {\n const ta = taRef.current;\n if (!ta) return;\n const start = ta.selectionStart;\n const end = ta.selectionEnd;\n const upTo = ta.value.slice(0, start);\n setActiveLine(upTo.split(\"\\n\").length);\n const selLen = end - start;\n setSelectionLen(selLen);\n if (selLen > 0) {\n const slice = ta.value.slice(start, end);\n setSelectionLines(slice.split(\"\\n\").length);\n } else {\n setSelectionLines(0);\n }\n };\n\n const setCaret = (start: number, end?: number) => {\n requestAnimationFrame(() => {\n const ta = taRef.current;\n if (!ta) return;\n ta.selectionStart = start;\n ta.selectionEnd = end ?? start;\n updateSelection();\n });\n };\n\n const replaceRange = (start: number, end: number, replacement: string, caretAt?: number) => {\n const next = value.slice(0, start) + replacement + value.slice(end);\n onChange?.(next);\n setCaret(caretAt ?? start + replacement.length);\n };\n\n const lineBounds = (text: string, caret: number) => {\n const before = text.lastIndexOf(\"\\n\", caret - 1);\n const after = text.indexOf(\"\\n\", caret);\n return {\n lineStart: before === -1 ? 0 : before + 1,\n lineEnd: after === -1 ? text.length : after,\n };\n };\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n const ta = e.currentTarget;\n if (readOnly) return;\n const isMac = typeof navigator !== \"undefined\" && /Mac/.test(navigator.platform);\n const mod = isMac ? e.metaKey : e.ctrlKey;\n\n // Cmd+F → open find bar\n if (mod && (e.key === \"f\" || e.key === \"F\")) {\n if (!searchable) return;\n e.preventDefault();\n setFindOpen(true);\n requestAnimationFrame(() => findInputRef.current?.focus());\n return;\n }\n\n // Escape closes find\n if (e.key === \"Escape\" && findOpen) {\n e.preventDefault();\n setFindOpen(false);\n return;\n }\n\n // Cmd+/ → toggle comment for current line or selection\n if (mod && e.key === \"/\") {\n e.preventDefault();\n const prefix = COMMENT_PREFIX[language];\n const trimmedPrefix = prefix.trim();\n const start = ta.selectionStart;\n const end = ta.selectionEnd;\n const firstStart = lineBounds(value, start).lineStart;\n const lastEnd = lineBounds(value, end).lineEnd;\n const slice = value.slice(firstStart, lastEnd);\n const partLines = slice.split(\"\\n\");\n const allCommented = partLines.every(\n (l) => l.trim() === \"\" || l.trimStart().startsWith(trimmedPrefix),\n );\n const updated = partLines\n .map((l) => {\n if (l.trim() === \"\") return l;\n if (allCommented) {\n const idx = l.indexOf(trimmedPrefix);\n if (idx >= 0) return l.slice(0, idx) + l.slice(idx + prefix.length);\n return l;\n }\n const leading = l.match(/^\\s*/)?.[0] ?? \"\";\n return `${leading}${prefix}${l.slice(leading.length)}`;\n })\n .join(\"\\n\");\n const next = value.slice(0, firstStart) + updated + value.slice(lastEnd);\n onChange?.(next);\n const delta = updated.length - slice.length;\n setCaret(start + (allCommented ? -prefix.length : prefix.length), end + delta);\n return;\n }\n\n // Cmd+D → duplicate current line (or selection)\n if (mod && (e.key === \"d\" || e.key === \"D\")) {\n e.preventDefault();\n const start = ta.selectionStart;\n const end = ta.selectionEnd;\n if (start === end) {\n const { lineStart, lineEnd } = lineBounds(value, start);\n const line = value.slice(lineStart, lineEnd);\n const next = value.slice(0, lineEnd) + \"\\n\" + line + value.slice(lineEnd);\n onChange?.(next);\n setCaret(start + line.length + 1);\n } else {\n const slice = value.slice(start, end);\n const next = value.slice(0, end) + slice + value.slice(end);\n onChange?.(next);\n setCaret(end + slice.length);\n }\n return;\n }\n\n // Alt+ArrowUp/Down → move line up/down\n if (e.altKey && (e.key === \"ArrowUp\" || e.key === \"ArrowDown\")) {\n e.preventDefault();\n const direction = e.key === \"ArrowUp\" ? -1 : 1;\n const caret = ta.selectionStart;\n const linesArr = value.split(\"\\n\");\n let acc = 0;\n let lineIdx = 0;\n let lineStart = 0;\n for (let i = 0; i < linesArr.length; i++) {\n const lineLen = linesArr[i].length;\n if (caret <= acc + lineLen) {\n lineIdx = i;\n lineStart = acc;\n break;\n }\n acc += lineLen + 1;\n lineIdx = i;\n lineStart = acc;\n }\n const target = lineIdx + direction;\n if (target < 0 || target >= linesArr.length) return;\n const swap = linesArr[lineIdx];\n linesArr[lineIdx] = linesArr[target];\n linesArr[target] = swap;\n const next = linesArr.join(\"\\n\");\n onChange?.(next);\n let newStart = 0;\n for (let i = 0; i < target; i++) newStart += linesArr[i].length + 1;\n const col = caret - lineStart;\n setCaret(newStart + Math.min(col, linesArr[target].length));\n return;\n }\n\n // Tab → spaces (or indent block when multi-line selection)\n if (e.key === \"Tab\") {\n e.preventDefault();\n const start = ta.selectionStart;\n const end = ta.selectionEnd;\n if (start !== end && value.slice(start, end).includes(\"\\n\")) {\n const firstStart = lineBounds(value, start).lineStart;\n const lastEnd = lineBounds(value, end).lineEnd;\n const block = value.slice(firstStart, lastEnd);\n let updated: string;\n if (e.shiftKey) {\n updated = block\n .split(\"\\n\")\n .map((l) => l.replace(new RegExp(`^ {1,${tabSize}}`), \"\"))\n .join(\"\\n\");\n } else {\n const pad = \" \".repeat(tabSize);\n updated = block\n .split(\"\\n\")\n .map((l) => `${pad}${l}`)\n .join(\"\\n\");\n }\n const next = value.slice(0, firstStart) + updated + value.slice(lastEnd);\n onChange?.(next);\n setCaret(firstStart, firstStart + updated.length);\n return;\n }\n const spaces = \" \".repeat(tabSize);\n replaceRange(start, end, spaces);\n return;\n }\n\n // Enter → auto-indent (+ expanded block when between auto-pair)\n if (e.key === \"Enter\") {\n const start = ta.selectionStart;\n const before = value[start - 1];\n const after = value[start];\n const upTo = value.slice(0, start);\n const currentLine = upTo.split(\"\\n\").pop() ?? \"\";\n const indent = currentLine.match(/^\\s*/)?.[0] ?? \"\";\n\n if (autoPair && before && after && OPEN_PAIRS[before] === after) {\n e.preventDefault();\n const inner = `\\n${indent}${\" \".repeat(tabSize)}\\n${indent}`;\n const next = value.slice(0, start) + inner + value.slice(ta.selectionEnd);\n onChange?.(next);\n setCaret(start + 1 + indent.length + tabSize);\n return;\n }\n\n if (indent.length > 0) {\n e.preventDefault();\n const next = value.slice(0, start) + \"\\n\" + indent + value.slice(ta.selectionEnd);\n onChange?.(next);\n setCaret(start + 1 + indent.length);\n return;\n }\n }\n\n // Auto-pair: opening bracket/quote\n if (autoPair && !e.metaKey && !e.ctrlKey && !e.altKey && OPEN_PAIRS[e.key]) {\n const start = ta.selectionStart;\n const end = ta.selectionEnd;\n if (start !== end) {\n e.preventDefault();\n const selected = value.slice(start, end);\n const wrapped = `${e.key}${selected}${OPEN_PAIRS[e.key]}`;\n replaceRange(start, end, wrapped, end + 2);\n return;\n }\n const nextChar = value[start];\n // Skip pairing if we'd just stack identical quotes\n if ((e.key === '\"' || e.key === \"'\" || e.key === \"`\") && nextChar === e.key) {\n e.preventDefault();\n setCaret(start + 1);\n return;\n }\n e.preventDefault();\n const insert = `${e.key}${OPEN_PAIRS[e.key]}`;\n const next = value.slice(0, start) + insert + value.slice(start);\n onChange?.(next);\n setCaret(start + 1);\n return;\n }\n\n // Auto-skip closing bracket when next char already matches\n if (autoPair && CLOSE_PAIRS.has(e.key)) {\n const start = ta.selectionStart;\n if (start === ta.selectionEnd && value[start] === e.key) {\n e.preventDefault();\n setCaret(start + 1);\n return;\n }\n }\n\n // Backspace inside an empty pair → delete both\n if (autoPair && e.key === \"Backspace\") {\n const start = ta.selectionStart;\n if (start === ta.selectionEnd && start > 0) {\n const left = value[start - 1];\n const right = value[start];\n if (left && right && OPEN_PAIRS[left] === right) {\n e.preventDefault();\n const next = value.slice(0, start - 1) + value.slice(start + 1);\n onChange?.(next);\n setCaret(start - 1);\n return;\n }\n }\n }\n };\n\n const doFindNext = (dir: 1 | -1 = 1) => {\n if (matches.length === 0) return;\n const next = (findIndex + dir + matches.length) % matches.length;\n setFindIndex(next);\n const m = matches[next];\n setCaret(m.start, m.end);\n requestAnimationFrame(() => taRef.current?.focus());\n };\n\n const handleCopy = async () => {\n if (typeof navigator === \"undefined\") return;\n try {\n await navigator.clipboard.writeText(value);\n setCopied(true);\n setTimeout(() => setCopied(false), 1200);\n } catch {\n /* ignore */\n }\n };\n\n const handleFormat = () => {\n const formatted = tryFormat(value, language);\n if (formatted) onChange?.(formatted);\n };\n\n const showFormatBtn = (showFormat ?? language === \"json\") && !readOnly;\n const showWrapToggle = showWordWrapToggle && wordWrapProp === undefined;\n\n return (\n <div\n className={cn(\n \"ods-code-editor\",\n `ods-code-editor--${language}`,\n readOnly && \"ods-code-editor--readonly\",\n wordWrap && \"ods-code-editor--wrap\",\n className,\n )}\n >\n <div className=\"ods-code-editor__toolbar\">\n <div className=\"ods-code-editor__toolbar-left\">\n <span className=\"ods-code-editor__lang\">{language.toUpperCase()}</span>\n {toolbar}\n </div>\n <div className=\"ods-code-editor__toolbar-right\">\n <span className=\"ods-code-editor__lines\">\n {lineCount} line{lineCount === 1 ? \"\" : \"s\"}\n </span>\n {status && <span className=\"ods-code-editor__status\">{status}</span>}\n {showWrapToggle && (\n <button\n type=\"button\"\n className={cn(\"ods-code-editor__btn\", wordWrap && \"ods-code-editor__btn--active\")}\n onClick={() => setInternalWrap((w) => !w)}\n aria-pressed={wordWrap}\n aria-label=\"Toggle word wrap\"\n title=\"Word wrap\"\n >\n <TextWrapIcon aria-hidden=\"true\" />\n </button>\n )}\n {showFormatBtn && (\n <button\n type=\"button\"\n className=\"ods-code-editor__btn\"\n onClick={handleFormat}\n aria-label=\"Format\"\n title=\"Format (JSON)\"\n >\n <MagicWandIcon aria-hidden=\"true\" />\n </button>\n )}\n {showCopy && (\n <button\n type=\"button\"\n className={cn(\"ods-code-editor__btn\", copied && \"ods-code-editor__btn--success\")}\n onClick={handleCopy}\n aria-label=\"Copy\"\n title=\"Copy\"\n >\n {copied ? (\n <CheckmarkIcon aria-hidden=\"true\" />\n ) : (\n <CopyIcon aria-hidden=\"true\" />\n )}\n </button>\n )}\n </div>\n </div>\n\n {findOpen && (\n <div className=\"ods-code-editor__find\" role=\"search\">\n <SearchIcon aria-hidden=\"true\" />\n <input\n ref={findInputRef}\n className=\"ods-code-editor__find-input\"\n type=\"text\"\n placeholder=\"Find…\"\n value={findQuery}\n onChange={(e) => {\n setFindQuery(e.target.value);\n setFindIndex(0);\n }}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") {\n e.preventDefault();\n doFindNext(e.shiftKey ? -1 : 1);\n }\n if (e.key === \"Escape\") {\n e.preventDefault();\n setFindOpen(false);\n taRef.current?.focus();\n }\n }}\n />\n <span className=\"ods-code-editor__find-count\">\n {matches.length > 0 ? `${findIndex + 1} of ${matches.length}` : \"0\"}\n </span>\n <button\n type=\"button\"\n className=\"ods-code-editor__btn\"\n onClick={() => doFindNext(-1)}\n aria-label=\"Previous match\"\n disabled={matches.length === 0}\n >\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"none\" aria-hidden=\"true\">\n <path\n d=\"M3 6.5 5 4.5l2 2\"\n stroke=\"currentColor\"\n strokeWidth=\"1.4\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n </button>\n <button\n type=\"button\"\n className=\"ods-code-editor__btn\"\n onClick={() => doFindNext(1)}\n aria-label=\"Next match\"\n disabled={matches.length === 0}\n >\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"none\" aria-hidden=\"true\">\n <path\n d=\"M3 3.5 5 5.5l2-2\"\n stroke=\"currentColor\"\n strokeWidth=\"1.4\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n </button>\n <button\n type=\"button\"\n className=\"ods-code-editor__btn\"\n onClick={() => {\n setFindOpen(false);\n taRef.current?.focus();\n }}\n aria-label=\"Close find\"\n >\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"none\" aria-hidden=\"true\">\n <path\n d=\"m3 3 4 4M7 3l-4 4\"\n stroke=\"currentColor\"\n strokeWidth=\"1.4\"\n strokeLinecap=\"round\"\n />\n </svg>\n </button>\n </div>\n )}\n\n <div className=\"ods-code-editor__body\" style={{ minHeight, maxHeight }}>\n {showLineNumbers && (\n <div ref={gutterRef} className=\"ods-code-editor__gutter\" aria-hidden=\"true\">\n {lines.map((_, i) => (\n <span\n key={i}\n className={cn(\n \"ods-code-editor__line-no\",\n highlightActiveLine && activeLine === i + 1 && \"ods-code-editor__line-no--active\",\n )}\n >\n {i + 1}\n </span>\n ))}\n </div>\n )}\n <textarea\n ref={taRef}\n id={id}\n name={name}\n form={form}\n required={required}\n className=\"ods-code-editor__textarea\"\n value={value}\n onChange={(e) => onChange?.(e.target.value)}\n onKeyDown={handleKeyDown}\n onKeyUp={updateSelection}\n onClick={updateSelection}\n onSelect={updateSelection}\n placeholder={placeholder}\n readOnly={readOnly}\n spellCheck={false}\n aria-label={ariaLabel}\n aria-required={required || undefined}\n wrap={wordWrap ? \"soft\" : \"off\"}\n />\n </div>\n\n {showCounter && (\n <div className=\"ods-code-editor__footer\">\n <span className=\"ods-code-editor__pos\">\n Ln {activeLine}\n {selectionLen > 0 && (\n <>\n {\" \"}\n · {selectionLen} char{selectionLen === 1 ? \"\" : \"s\"}\n {selectionLines > 1 && ` · ${selectionLines} lines`}\n </>\n )}\n </span>\n <span className=\"ods-code-editor__shortcut-hint\">\n <kbd className=\"ods-code-editor__kbd\">⌘/</kbd> comment\n <span className=\"ods-code-editor__sep\">·</span>\n <kbd className=\"ods-code-editor__kbd\">⌘D</kbd> duplicate\n <span className=\"ods-code-editor__sep\">·</span>\n <kbd className=\"ods-code-editor__kbd\">⌥↑↓</kbd> move\n {searchable && (\n <>\n <span className=\"ods-code-editor__sep\">·</span>\n <kbd className=\"ods-code-editor__kbd\">⌘F</kbd> find\n </>\n )}\n </span>\n </div>\n )}\n </div>\n );\n },\n);\n\nCodeEditor.displayName = \"CodeEditor\";\n","\"use client\";\nimport { ChevronDownIcon } from \"@octaviaflow/icons\";\nimport {\n type KeyboardEvent,\n type ReactNode,\n useCallback,\n useEffect,\n useId,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { cn } from \"../../utils/cn\";\n\nexport interface ComboboxOption {\n value: string;\n label: string;\n /** Secondary line under the label (e.g. the underlying token/expression). */\n description?: string;\n /** Optional leading glyph. */\n icon?: ReactNode;\n disabled?: boolean;\n}\n\nexport interface ComboboxProps {\n /** Current text value. Free text is always allowed — options are suggestions. */\n value: string;\n onChange: (value: string) => void;\n options: ComboboxOption[];\n placeholder?: string;\n /** Accessible name when no visible `label` is rendered. */\n ariaLabel?: string;\n /** Optional visible label rendered above the field. */\n label?: ReactNode;\n helperText?: ReactNode;\n size?: \"sm\" | \"md\" | \"lg\";\n disabled?: boolean;\n /** Shows a loading row in the panel instead of options (async option fetch). */\n loading?: boolean;\n error?: boolean;\n errorMessage?: ReactNode;\n /**\n * When true, a typed value that isn't an exact option match surfaces a\n * leading \"Use «value»\" row so users see free entry is allowed. Free typing\n * works regardless; this is purely an affordance.\n */\n creatable?: boolean;\n /** Message shown when no options match the typed text. */\n emptyMessage?: ReactNode;\n /** Override the default substring match. Receives the option and typed query. */\n filter?: (option: ComboboxOption, query: string) => boolean;\n id?: string;\n name?: string;\n required?: boolean;\n className?: string;\n onBlur?: () => void;\n}\n\nconst defaultFilter = (option: ComboboxOption, query: string) => {\n const q = query.trim().toLowerCase();\n return (\n option.label.toLowerCase().includes(q) || option.value.toLowerCase().includes(q)\n );\n};\n\n/**\n * Editable combobox: a free-text input with an attached dropdown button. The\n * button (or ArrowDown) reveals the option list; picking an option fills the\n * input, and the user can also type any value not in the list. Options filter\n * by the typed text. The panel is portal-positioned so it escapes parent\n * `overflow: hidden` clipping (side panels, drawers, scrollable sections).\n *\n * Free-type-OR-pick is the core behaviour — use it wherever a field accepts\n * both known values and arbitrary input (dynamic tokens, custom identifiers).\n */\nexport function Combobox({\n value,\n onChange,\n options,\n placeholder = \"Select or type…\",\n ariaLabel,\n label,\n helperText,\n size = \"md\",\n disabled = false,\n loading = false,\n error = false,\n errorMessage,\n creatable = false,\n emptyMessage = \"Type a custom value\",\n filter = defaultFilter,\n id,\n name,\n required,\n className,\n onBlur,\n}: ComboboxProps) {\n const [open, setOpen] = useState(false);\n const [activeIdx, setActiveIdx] = useState(0);\n const wrapRef = useRef<HTMLDivElement>(null);\n const fieldRef = useRef<HTMLDivElement>(null);\n const inputRef = useRef<HTMLInputElement>(null);\n const panelRef = useRef<HTMLDivElement>(null);\n const reactId = useId();\n const inputId = id ?? `${reactId}-combobox`;\n const listboxId = `${reactId}-listbox`;\n const errorId = `${reactId}-err`;\n const helperId = `${reactId}-help`;\n\n const [panelPos, setPanelPos] = useState<{ top: number; left: number; width: number } | null>(\n null,\n );\n const updatePanelPos = useCallback(() => {\n if (!fieldRef.current) return;\n const r = fieldRef.current.getBoundingClientRect();\n setPanelPos({ top: r.bottom + 4, left: r.left, width: r.width });\n }, []);\n useLayoutEffect(() => {\n if (!open) return;\n updatePanelPos();\n window.addEventListener(\"scroll\", updatePanelPos, true);\n window.addEventListener(\"resize\", updatePanelPos);\n return () => {\n window.removeEventListener(\"scroll\", updatePanelPos, true);\n window.removeEventListener(\"resize\", updatePanelPos);\n };\n }, [open, updatePanelPos]);\n\n // When the value exactly matches a known option (i.e. a committed selection)\n // or is empty, show ALL options so reopening reveals the full list. Only when\n // the text diverges from any option do we treat it as a search query.\n const isExactMatch = useMemo(\n () => value !== \"\" && options.some((o) => o.value === value),\n [options, value],\n );\n const filtered = useMemo(() => {\n if (!value.trim() || isExactMatch) return options;\n return options.filter((o) => filter(o, value));\n }, [options, value, isExactMatch, filter]);\n\n // The optional \"Use «typed»\" creatable row precedes the filtered options.\n const showCreate = creatable && value.trim() !== \"\" && !isExactMatch;\n const rowCount = filtered.length + (showCreate ? 1 : 0);\n\n useEffect(() => {\n setActiveIdx(0);\n }, [value, open]);\n\n // Click outside closes.\n useEffect(() => {\n if (!open) return;\n const onDoc = (e: MouseEvent) => {\n const t = e.target as Node;\n if (!wrapRef.current?.contains(t) && !panelRef.current?.contains(t)) setOpen(false);\n };\n document.addEventListener(\"mousedown\", onDoc);\n return () => document.removeEventListener(\"mousedown\", onDoc);\n }, [open]);\n\n const commit = (v: string) => {\n onChange(v);\n setOpen(false);\n inputRef.current?.focus();\n };\n\n // ArrowDown/Up navigate the visible rows (create row is index 0 when present);\n // Enter commits the active row; Escape closes.\n const activeValueAt = (idx: number): string | undefined => {\n if (showCreate && idx === 0) return value;\n const optIdx = showCreate ? idx - 1 : idx;\n return filtered[optIdx]?.value;\n };\n\n const handleKey = (e: KeyboardEvent<HTMLInputElement>) => {\n if (disabled) return;\n if (e.key === \"ArrowDown\") {\n e.preventDefault();\n if (!open) {\n setOpen(true);\n return;\n }\n setActiveIdx((i) => Math.min(i + 1, Math.max(rowCount - 1, 0)));\n } else if (e.key === \"ArrowUp\") {\n if (!open) return;\n e.preventDefault();\n setActiveIdx((i) => Math.max(i - 1, 0));\n } else if (e.key === \"Enter\") {\n if (open && rowCount > 0) {\n const v = activeValueAt(activeIdx);\n if (v !== undefined) {\n e.preventDefault();\n commit(v);\n }\n }\n } else if (e.key === \"Escape\") {\n if (open) {\n e.preventDefault();\n setOpen(false);\n }\n }\n };\n\n const describedBy = error && errorMessage ? errorId : helperText ? helperId : undefined;\n const activeDescendant = open && rowCount > 0 ? `${listboxId}-opt-${activeIdx}` : undefined;\n\n return (\n <div\n ref={wrapRef}\n className={cn(\n \"ods-combobox\",\n `ods-combobox--${size}`,\n error && \"ods-combobox--error\",\n disabled && \"ods-combobox--disabled\",\n className,\n )}\n onBlur={(e) => {\n // Fire consumer onBlur only when focus leaves the whole widget.\n if (!wrapRef.current?.contains(e.relatedTarget as Node)) onBlur?.();\n }}\n >\n {label && (\n <label htmlFor={inputId} className=\"ods-combobox__label\">\n {label}\n {required && (\n <span className=\"ods-combobox__required\" aria-hidden=\"true\">\n *\n </span>\n )}\n </label>\n )}\n <div ref={fieldRef} className=\"ods-combobox__field\">\n <input\n ref={inputRef}\n id={inputId}\n name={name}\n type=\"text\"\n className=\"ods-combobox__input\"\n value={value}\n disabled={disabled}\n required={required}\n placeholder={placeholder}\n onChange={(e) => {\n onChange(e.target.value);\n if (!open) setOpen(true);\n }}\n onKeyDown={handleKey}\n onFocus={() => !disabled && setOpen(true)}\n role=\"combobox\"\n aria-expanded={open}\n aria-controls={open ? listboxId : undefined}\n aria-activedescendant={activeDescendant}\n aria-autocomplete=\"list\"\n aria-label={!label ? ariaLabel : undefined}\n aria-invalid={error || undefined}\n aria-required={required || undefined}\n aria-describedby={describedBy}\n />\n <button\n type=\"button\"\n className={cn(\"ods-combobox__toggle\", open && \"ods-combobox__toggle--open\")}\n onClick={() => {\n if (disabled) return;\n setOpen((o) => !o);\n inputRef.current?.focus();\n }}\n aria-label={`${ariaLabel ?? \"Options\"}`}\n aria-haspopup=\"listbox\"\n aria-expanded={open}\n disabled={disabled}\n tabIndex={-1}\n >\n <ChevronDownIcon aria-hidden=\"true\" className=\"ods-combobox__chev\" />\n </button>\n </div>\n\n {open && panelPos && typeof document !== \"undefined\" &&\n createPortal(\n <div\n ref={panelRef}\n className=\"ods-combobox__panel\"\n role=\"presentation\"\n style={{\n position: \"fixed\",\n top: panelPos.top,\n left: panelPos.left,\n minWidth: panelPos.width,\n }}\n >\n {loading ? (\n <div className=\"ods-combobox__status\" role=\"status\">\n <span className=\"ods-combobox__spinner\" aria-hidden=\"true\" />\n Loading…\n </div>\n ) : (\n <ul id={listboxId} role=\"listbox\" aria-label={ariaLabel} className=\"ods-combobox__list\">\n {showCreate && (\n <li>\n <button\n type=\"button\"\n id={`${listboxId}-opt-0`}\n role=\"option\"\n aria-selected={false}\n className={cn(\n \"ods-combobox__opt ods-combobox__opt--create\",\n activeIdx === 0 && \"ods-combobox__opt--active\",\n )}\n onClick={() => commit(value)}\n onMouseEnter={() => setActiveIdx(0)}\n >\n Use “<strong>{value}</strong>”\n </button>\n </li>\n )}\n {filtered.length === 0 && !showCreate && (\n <li className=\"ods-combobox__empty\">{emptyMessage}</li>\n )}\n {filtered.map((opt, i) => {\n const idx = showCreate ? i + 1 : i;\n return (\n <li key={opt.value}>\n <button\n type=\"button\"\n id={`${listboxId}-opt-${idx}`}\n role=\"option\"\n aria-selected={opt.value === value}\n disabled={opt.disabled}\n className={cn(\n \"ods-combobox__opt\",\n opt.value === value && \"ods-combobox__opt--selected\",\n idx === activeIdx && \"ods-combobox__opt--active\",\n opt.disabled && \"ods-combobox__opt--disabled\",\n )}\n onClick={() => !opt.disabled && commit(opt.value)}\n onMouseEnter={() => setActiveIdx(idx)}\n >\n {opt.icon && (\n <span className=\"ods-combobox__opt-icon\" aria-hidden=\"true\">\n {opt.icon}\n </span>\n )}\n <span className=\"ods-combobox__opt-body\">\n <span className=\"ods-combobox__opt-text\">{opt.label}</span>\n {opt.description && (\n <span className=\"ods-combobox__opt-desc\">{opt.description}</span>\n )}\n </span>\n </button>\n </li>\n );\n })}\n </ul>\n )}\n </div>,\n document.body,\n )}\n\n {error && errorMessage && (\n <div id={errorId} className=\"ods-combobox__error-message\" role=\"alert\">\n {errorMessage}\n </div>\n )}\n {!error && helperText && (\n <div id={helperId} className=\"ods-combobox__helper\">\n {helperText}\n </div>\n )}\n </div>\n );\n}\n\nCombobox.displayName = \"Combobox\";\n","\"use client\";\nimport { AddIcon, CloseIcon } from \"@octaviaflow/icons\";\nimport type { ReactNode } from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { Checkbox } from \"../Checkbox\";\nimport { Combobox, type ComboboxOption } from \"../Combobox\";\n\nexport interface KeyValuePair {\n key: string;\n value: string;\n /** Per-row enable flag. Only meaningful when `rowToggle` is set; a missing\n * value is treated as enabled (backward-compatible). */\n enabled?: boolean;\n /** Optional per-row description. Only rendered when `showDescription` is set. */\n description?: string;\n}\n\nexport interface KeyValueEditorProps {\n pairs: KeyValuePair[];\n onChange: (pairs: KeyValuePair[]) => void;\n label?: ReactNode;\n helperText?: ReactNode;\n keyPlaceholder?: string;\n valuePlaceholder?: string;\n descriptionPlaceholder?: string;\n addLabel?: ReactNode;\n /** When set, the key field is a Combobox of these suggestions (free-type still allowed). */\n keyOptions?: ComboboxOption[];\n /** When set, the value field is a Combobox of these suggestions (free-type still allowed). */\n valueOptions?: ComboboxOption[];\n /** Render a per-row enable Checkbox; disabled rows dim and their fields go\n * read-only (the toggle + remove stay active). New rows default to enabled. */\n rowToggle?: boolean;\n /** Render a third description column per row. */\n showDescription?: boolean;\n size?: \"sm\" | \"md\" | \"lg\";\n disabled?: boolean;\n error?: boolean;\n errorMessage?: ReactNode;\n /** Shown when there are no rows yet. */\n emptyLabel?: ReactNode;\n maxRows?: number;\n className?: string;\n}\n\n/** A row counts as enabled unless explicitly turned off (so legacy pairs with\n * no `enabled` field stay active). */\nconst isRowEnabled = (pair: KeyValuePair) => pair.enabled !== false;\n\n/**\n * KeyValueEditor — a list of key/value rows with add/remove. Drives field\n * defaults, request headers/params, and similar \"name → value\" maps. Either\n * field can become a Combobox (suggestions + free entry) by passing\n * `keyOptions` / `valueOptions`; otherwise both are plain text inputs.\n */\nexport function KeyValueEditor({\n pairs,\n onChange,\n label,\n helperText,\n keyPlaceholder = \"key\",\n valuePlaceholder = \"value\",\n descriptionPlaceholder = \"description\",\n addLabel = \"Add\",\n keyOptions,\n valueOptions,\n rowToggle = false,\n showDescription = false,\n size = \"md\",\n disabled = false,\n error = false,\n errorMessage,\n emptyLabel,\n maxRows,\n className,\n}: KeyValueEditorProps) {\n const setAt = (i: number, patch: Partial<KeyValuePair>) =>\n onChange(pairs.map((p, j) => (j === i ? { ...p, ...patch } : p)));\n const removeAt = (i: number) => onChange(pairs.filter((_, j) => j !== i));\n const add = () =>\n onChange([...pairs, { key: \"\", value: \"\", ...(rowToggle ? { enabled: true } : {}) }]);\n\n const canAdd = !disabled && (maxRows === undefined || pairs.length < maxRows);\n\n return (\n <div\n className={cn(\n \"ods-kv-editor\",\n `ods-kv-editor--${size}`,\n error && \"ods-kv-editor--error\",\n showDescription && \"ods-kv-editor--with-description\",\n className,\n )}\n >\n {label && <div className=\"ods-kv-editor__label\">{label}</div>}\n\n {pairs.length === 0 && emptyLabel && (\n <div className=\"ods-kv-editor__empty\">{emptyLabel}</div>\n )}\n\n {pairs.map((pair, i) => {\n // A row's fields are read-only when the editor is globally disabled OR\n // the row has been toggled off. The toggle + remove always stay active.\n const rowOff = rowToggle && !isRowEnabled(pair);\n const fieldsDisabled = disabled || rowOff;\n return (\n <div\n key={i}\n className={cn(\"ods-kv-editor__row\", rowOff && \"ods-kv-editor__row--disabled\")}\n >\n {rowToggle && (\n <Checkbox\n size={size === \"lg\" ? \"md\" : size}\n aria-label=\"Enable row\"\n checked={isRowEnabled(pair)}\n onChange={(on) => setAt(i, { enabled: on })}\n disabled={disabled}\n />\n )}\n {keyOptions ? (\n <Combobox\n ariaLabel=\"Key\"\n size={size}\n value={pair.key}\n options={keyOptions}\n onChange={(v) => setAt(i, { key: v })}\n placeholder={keyPlaceholder}\n disabled={fieldsDisabled}\n />\n ) : (\n <input\n className=\"ods-kv-editor__input\"\n aria-label=\"Key\"\n value={pair.key}\n onChange={(e) => setAt(i, { key: e.target.value })}\n placeholder={keyPlaceholder}\n disabled={fieldsDisabled}\n />\n )}\n {valueOptions ? (\n <Combobox\n ariaLabel=\"Value\"\n size={size}\n value={pair.value}\n options={valueOptions}\n onChange={(v) => setAt(i, { value: v })}\n placeholder={valuePlaceholder}\n disabled={fieldsDisabled}\n />\n ) : (\n <input\n className=\"ods-kv-editor__input\"\n aria-label=\"Value\"\n value={pair.value}\n onChange={(e) => setAt(i, { value: e.target.value })}\n placeholder={valuePlaceholder}\n disabled={fieldsDisabled}\n />\n )}\n {showDescription && (\n <input\n className=\"ods-kv-editor__input ods-kv-editor__input--description\"\n aria-label=\"Description\"\n value={pair.description ?? \"\"}\n onChange={(e) => setAt(i, { description: e.target.value })}\n placeholder={descriptionPlaceholder}\n disabled={fieldsDisabled}\n />\n )}\n <button\n type=\"button\"\n className=\"ods-kv-editor__remove\"\n aria-label=\"Remove row\"\n onClick={() => removeAt(i)}\n disabled={disabled}\n >\n <CloseIcon width={14} height={14} aria-hidden=\"true\" />\n </button>\n </div>\n );\n })}\n\n {canAdd && (\n <button type=\"button\" className=\"ods-kv-editor__add\" onClick={add}>\n <AddIcon width={14} height={14} aria-hidden=\"true\" />\n {addLabel}\n </button>\n )}\n\n {error && errorMessage && (\n <div className=\"ods-kv-editor__error-message\" role=\"alert\">\n {errorMessage}\n </div>\n )}\n {!error && helperText && <div className=\"ods-kv-editor__helper\">{helperText}</div>}\n </div>\n );\n}\n\nKeyValueEditor.displayName = \"KeyValueEditor\";\n","\"use client\";\nimport { ChevronRightIcon } from \"@octaviaflow/icons\";\nimport { type ReactNode, useId, useState } from \"react\";\nimport { cn } from \"../../utils/cn\";\n\nexport interface DisclosureProps {\n /** Header text (the clickable toggle). */\n title: ReactNode;\n children: ReactNode;\n /** Optional secondary line under the title. */\n description?: ReactNode;\n /** Optional leading icon in the header. */\n icon?: ReactNode;\n /** Optional trailing slot in the header (e.g. a count Badge). */\n trailing?: ReactNode;\n /** Uncontrolled initial open state. Default false. */\n defaultOpen?: boolean;\n /** Controlled open state. When set, `onOpenChange` drives changes. */\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n size?: \"sm\" | \"md\";\n disabled?: boolean;\n className?: string;\n}\n\n/**\n * Disclosure — a single collapsible section toggled by a button header. Use for\n * \"Advanced options\" / \"Properties\" reveals where a full Accordion (grouped\n * multi-section) is overkill. Controlled or uncontrolled. Keyboard + ARIA\n * disclosure semantics (button `aria-expanded` + `aria-controls` → region).\n */\nexport function Disclosure({\n title,\n children,\n description,\n icon,\n trailing,\n defaultOpen = false,\n open: controlledOpen,\n onOpenChange,\n size = \"md\",\n disabled = false,\n className,\n}: DisclosureProps) {\n const [uncontrolledOpen, setUncontrolledOpen] = useState(defaultOpen);\n const isControlled = controlledOpen !== undefined;\n const open = isControlled ? controlledOpen : uncontrolledOpen;\n const reactId = useId();\n const regionId = `${reactId}-region`;\n\n const toggle = () => {\n if (disabled) return;\n const next = !open;\n if (!isControlled) setUncontrolledOpen(next);\n onOpenChange?.(next);\n };\n\n return (\n <div\n className={cn(\n \"ods-disclosure\",\n `ods-disclosure--${size}`,\n open && \"ods-disclosure--open\",\n disabled && \"ods-disclosure--disabled\",\n className,\n )}\n >\n <button\n type=\"button\"\n className=\"ods-disclosure__trigger\"\n onClick={toggle}\n disabled={disabled}\n aria-expanded={open}\n aria-controls={regionId}\n >\n <ChevronRightIcon aria-hidden=\"true\" className=\"ods-disclosure__chev\" />\n {icon && (\n <span className=\"ods-disclosure__icon\" aria-hidden=\"true\">\n {icon}\n </span>\n )}\n <span className=\"ods-disclosure__head\">\n <span className=\"ods-disclosure__title\">{title}</span>\n {description && <span className=\"ods-disclosure__desc\">{description}</span>}\n </span>\n {trailing && <span className=\"ods-disclosure__trailing\">{trailing}</span>}\n </button>\n {open && (\n <div id={regionId} role=\"region\" className=\"ods-disclosure__content\">\n {children}\n </div>\n )}\n </div>\n );\n}\n\nDisclosure.displayName = \"Disclosure\";\n","\"use client\";\nimport {\n CheckmarkFilledIcon,\n ErrorFilledIcon,\n InformationFilledIcon,\n WarningFilledIcon,\n} from \"@octaviaflow/icons\";\nimport {\n type ComponentPropsWithoutRef,\n forwardRef,\n type ReactNode,\n} from \"react\";\nimport { cn } from \"../../utils/cn\";\n\n/* ---------------------------------------------------------------------------\n * InlineMessage — small, lightweight status text.\n *\n * The middle-weight between a heavy `Banner` / `Callout` (page-level\n * card-like surface with title + description + actions) and a plain\n * `<span>` of muted text. Used for:\n *\n * - Form field validation (\"Required\", \"Min 8 characters\")\n * - DataTable cell errors (\"Failed to sync · retry?\")\n * - Inline status hints (\"Last saved 4 min ago\")\n * - Connector-row warnings (\"Lag exceeds SLA\")\n *\n * Renders as inline-flex text + optional leading icon. No padding,\n * no background, no border by default — it's text, not a card.\n *\n * A11y: `aria-live` is wired via the `live` prop. Default `\"off\"` for\n * static helper text; set `\"polite\"` for validation messages so screen\n * readers announce the change when the message replaces / appears.\n * ------------------------------------------------------------------------- */\n\nexport type InlineMessageTone = \"info\" | \"success\" | \"warning\" | \"danger\";\n\nexport type InlineMessageSize = \"sm\" | \"md\";\n\nexport interface InlineMessageProps\n extends Omit<ComponentPropsWithoutRef<\"div\">, \"children\"> {\n /** Tone — drives text + icon color. Default `\"info\"`. */\n tone?: InlineMessageTone;\n /** Visual size. Default `\"md\"`. */\n size?: InlineMessageSize;\n /**\n * Leading icon. When omitted, a tone-appropriate filled icon is\n * used. Pass `false` to suppress the icon entirely (text-only).\n */\n icon?: ReactNode | false;\n /**\n * ARIA live-region politeness. Use `\"polite\"` for validation\n * messages, `\"assertive\"` for blocking errors. Default `\"off\"` —\n * static helper text that doesn't need to be announced.\n */\n live?: \"off\" | \"polite\" | \"assertive\";\n /** Message text. */\n children: ReactNode;\n}\n\n/* ---------------------------------------------------------------------------\n * Tone → default icon\n * ------------------------------------------------------------------------- */\n\nconst TONE_ICON: Record<InlineMessageTone, React.ElementType> = {\n info: InformationFilledIcon,\n success: CheckmarkFilledIcon,\n warning: WarningFilledIcon,\n danger: ErrorFilledIcon,\n};\n\n/* ---------------------------------------------------------------------------\n * Component\n * ------------------------------------------------------------------------- */\n\nexport const InlineMessage = forwardRef<HTMLDivElement, InlineMessageProps>(\n function InlineMessage(\n {\n tone = \"info\",\n size = \"md\",\n icon,\n live = \"off\",\n className,\n children,\n ...rest\n },\n ref,\n ) {\n const DefaultIcon = TONE_ICON[tone];\n const renderIcon = icon === false ? null : (icon ?? <DefaultIcon />);\n\n return (\n <div\n {...rest}\n ref={ref}\n className={cn(\n \"ods-inline-msg\",\n `ods-inline-msg--${tone}`,\n `ods-inline-msg--${size}`,\n className,\n )}\n // role + aria-live are paired so AT picks up the announcement\n // when the message appears / changes. When `live=\"off\"`,\n // neither attribute is set — the element reads as plain text.\n role={live !== \"off\" ? \"status\" : undefined}\n aria-live={live !== \"off\" ? live : undefined}\n >\n {renderIcon && (\n <span className=\"ods-inline-msg__icon\" aria-hidden=\"true\">\n {renderIcon}\n </span>\n )}\n <span className=\"ods-inline-msg__text\">{children}</span>\n </div>\n );\n },\n);\n\nInlineMessage.displayName = \"InlineMessage\";\n","\"use client\";\nimport { motion, useReducedMotion } from \"framer-motion\";\nimport {\n type ComponentPropsWithoutRef,\n forwardRef,\n type KeyboardEvent,\n type MouseEvent,\n type ReactNode,\n useCallback,\n useId,\n useState,\n} from \"react\";\nimport { cn } from \"../../utils/cn\";\n\n/* ---------------------------------------------------------------------------\n * SegmentedControl — small mutually-exclusive view-mode toggle.\n *\n * Common ETL UI uses:\n * - View toggle: Grid | List | Table\n * - Time range: Day | Week | Month | Year\n * - Mode flip: Edit | Preview\n * - Direction: Source | Destination\n *\n * Each segment is a button; the radiogroup pattern is the WAI-ARIA\n * recommended approach. Keyboard nav: ← → cycles, Home / End jump to\n * boundaries. A motion-backed \"indicator\" slides between segments on\n * change for a tactile feel (respects reduced-motion).\n *\n * Controlled OR uncontrolled — pass `value` for controlled, omit and\n * let the component own state with `defaultValue`.\n * ------------------------------------------------------------------------- */\n\nexport type SegmentedControlSize = \"sm\" | \"md\" | \"lg\";\n\nexport interface SegmentedControlOption<T extends string = string> {\n /** Stable value identifier. */\n value: T;\n /** Display label. */\n label: ReactNode;\n /** Optional leading icon. */\n icon?: ReactNode;\n /** Disable this segment. */\n disabled?: boolean;\n}\n\nexport interface SegmentedControlProps<T extends string = string>\n extends Omit<\n ComponentPropsWithoutRef<\"div\">,\n | \"onChange\"\n | \"defaultValue\"\n | \"children\"\n | \"onDrag\"\n | \"onDragStart\"\n | \"onDragEnd\"\n | \"onAnimationStart\"\n > {\n /** Available segments. */\n options: SegmentedControlOption<T>[];\n /** Controlled: currently-selected value. */\n value?: T;\n /** Uncontrolled fallback. Default = first non-disabled option. */\n defaultValue?: T;\n /** Fires on selection change. */\n onChange?: (value: T) => void;\n /** Visual size. Default `\"md\"`. */\n size?: SegmentedControlSize;\n /** Stretch to fill the container. Default `false`. */\n fullWidth?: boolean;\n /** Hide labels (icon-only segments). Default `false`. */\n iconOnly?: boolean;\n /** Disable the entire control. */\n disabled?: boolean;\n /** Accessible label for the group (required when no visible label). */\n \"aria-label\"?: string;\n /** id of an element that labels the group. */\n \"aria-labelledby\"?: string;\n}\n\n/* ---------------------------------------------------------------------------\n * Component\n * ------------------------------------------------------------------------- */\n\nfunction SegmentedControlInner<T extends string>(\n {\n options,\n value: controlledValue,\n defaultValue,\n onChange,\n size = \"md\",\n fullWidth = false,\n iconOnly = false,\n disabled = false,\n id: providedId,\n className,\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledBy,\n ...rest\n }: SegmentedControlProps<T>,\n ref: React.Ref<HTMLDivElement>,\n) {\n const reactId = useId();\n const baseId = providedId ?? `ods-segmented-${reactId}`;\n const reducedMotion = useReducedMotion();\n\n // Initial value: explicit defaultValue → first non-disabled option.\n const fallback =\n defaultValue ?? options.find((o) => !o.disabled)?.value ?? options[0]?.value;\n const [internalValue, setInternalValue] = useState<T | undefined>(\n fallback as T | undefined,\n );\n const isControlled = controlledValue !== undefined;\n const value = isControlled ? controlledValue : internalValue;\n\n const setValue = useCallback(\n (next: T) => {\n if (!isControlled) setInternalValue(next);\n onChange?.(next);\n },\n [isControlled, onChange],\n );\n\n const handleClick =\n (option: SegmentedControlOption<T>) =>\n (e: MouseEvent<HTMLButtonElement>) => {\n if (disabled || option.disabled) return;\n e.preventDefault();\n if (option.value !== value) setValue(option.value);\n };\n\n const handleKeyDown = (\n e: KeyboardEvent<HTMLButtonElement>,\n index: number,\n ) => {\n if (disabled) return;\n const enabled = options.filter((o) => !o.disabled);\n const currentEnabledIdx = enabled.findIndex((o) => o.value === value);\n let nextIdx = currentEnabledIdx;\n if (e.key === \"ArrowRight\" || e.key === \"ArrowDown\") {\n e.preventDefault();\n nextIdx = (currentEnabledIdx + 1) % enabled.length;\n } else if (e.key === \"ArrowLeft\" || e.key === \"ArrowUp\") {\n e.preventDefault();\n nextIdx =\n (currentEnabledIdx - 1 + enabled.length) % enabled.length;\n } else if (e.key === \"Home\") {\n e.preventDefault();\n nextIdx = 0;\n } else if (e.key === \"End\") {\n e.preventDefault();\n nextIdx = enabled.length - 1;\n } else {\n return;\n }\n const next = enabled[nextIdx];\n if (next) {\n setValue(next.value);\n const btn = document.getElementById(`${baseId}-seg-${next.value}`);\n (btn as HTMLButtonElement | null)?.focus();\n }\n // index is kept for future per-segment handling; currently unused\n void index;\n };\n\n return (\n <div\n {...rest}\n ref={ref}\n id={baseId}\n role=\"radiogroup\"\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n className={cn(\n \"ods-segmented\",\n `ods-segmented--${size}`,\n fullWidth && \"ods-segmented--full\",\n iconOnly && \"ods-segmented--icon-only\",\n disabled && \"ods-segmented--disabled\",\n className,\n )}\n >\n {options.map((opt, i) => {\n const selected = opt.value === value;\n return (\n <button\n key={opt.value}\n id={`${baseId}-seg-${opt.value}`}\n type=\"button\"\n role=\"radio\"\n aria-checked={selected}\n aria-label={iconOnly && typeof opt.label === \"string\" ? opt.label : undefined}\n tabIndex={selected ? 0 : -1}\n disabled={disabled || opt.disabled}\n className={cn(\n \"ods-segmented__segment\",\n selected && \"ods-segmented__segment--selected\",\n )}\n onClick={handleClick(opt)}\n onKeyDown={(e) => handleKeyDown(e, i)}\n >\n {selected && (\n <motion.span\n layoutId={`${baseId}-indicator`}\n className=\"ods-segmented__indicator\"\n aria-hidden=\"true\"\n transition={\n reducedMotion\n ? { duration: 0 }\n : { type: \"spring\", stiffness: 480, damping: 38 }\n }\n />\n )}\n {opt.icon && (\n <span\n className=\"ods-segmented__icon\"\n aria-hidden=\"true\"\n >\n {opt.icon}\n </span>\n )}\n {!iconOnly && (\n <span className=\"ods-segmented__label\">{opt.label}</span>\n )}\n </button>\n );\n })}\n </div>\n );\n}\n\nexport const SegmentedControl = forwardRef(SegmentedControlInner) as <\n T extends string = string,\n>(\n props: SegmentedControlProps<T> & { ref?: React.Ref<HTMLDivElement> },\n) => React.ReactElement;\n","\"use client\";\nimport { CheckmarkIcon, ChevronRightIcon, CopyIcon } from \"@octaviaflow/icons\";\nimport {\n type ComponentPropsWithoutRef,\n forwardRef,\n type ReactNode,\n useEffect,\n useMemo,\n useState,\n} from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { CodeEditor } from \"../CodeEditor\";\nimport { InlineMessage } from \"../InlineMessage\";\n\n/* ---------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/** Result reported through `onValidate` after each edit-mode keystroke. */\nexport interface JsonViewerValidationResult {\n /** True when the current editor text parses as valid JSON. */\n valid: boolean;\n /** Parse error details — only present when `valid` is false. */\n error?: {\n /** 1-indexed line number from the parser. */\n line: number;\n /** 1-indexed column number from the parser. */\n col: number;\n /** Human-readable error message from the JSON parser. */\n message: string;\n };\n}\n\nexport interface JsonViewerProps\n extends Omit<ComponentPropsWithoutRef<\"div\">, \"title\" | \"onChange\"> {\n data: unknown;\n /**\n * `view` (default) — read-only collapsible tree view of `data`.\n * `edit` — switches to a CodeEditor primed with the JSON text of `data`.\n * In edit mode `onChange` fires on every keystroke with the raw text;\n * `onValidate` reports parse success/failure (Monaco's built-in JSON\n * language service also renders inline red squiggles).\n */\n mode?: \"view\" | \"edit\";\n /** Fires on every keystroke in `mode='edit'` with the raw editor text.\n * Always fires — even when the text is currently invalid JSON. */\n onChange?: (rawText: string) => void;\n /** Fires after each parse attempt in `mode='edit'`. Consumers gate the\n * save button on `result.valid`. */\n onValidate?: (result: JsonViewerValidationResult) => void;\n /** Initially expand to N levels deep (view mode only). Default 2. */\n defaultExpandDepth?: number;\n /** Show array indexes (view mode only). Default true. */\n showIndexes?: boolean;\n /** Show a copy button on hover for each leaf value (view mode only). */\n copyable?: boolean;\n /** Optional title. */\n title?: ReactNode;\n /** Optional status pill next to title. */\n status?: ReactNode;\n /** Limit each string value display length (view mode only). */\n truncateAt?: number;\n /** Fixed body height — number → pixels, string → any CSS length.\n * The inner tree scrolls vertically when content exceeds the bound. */\n height?: number | string;\n /** Upper bound on body height. Same shape as `height`; lets the body\n * grow up to the cap before scrolling kicks in. Ignored when `height`\n * is set (height takes precedence). */\n maxHeight?: number | string;\n}\n\n/* ---------------------------------------------------------------------------\n * Component\n * ------------------------------------------------------------------------- */\n\n/**\n * JSON viewer with two modes:\n *\n * - `view` (default) — collapsible tree of `data` with type-tinted\n * values, mono font for keys, optional copy buttons on leaves.\n * - `edit` — CodeEditor primed with JSON-stringified `data`.\n * Monaco's built-in JSON language service renders inline parse-error\n * squiggles. Consumers wire `onChange` (raw text) + `onValidate`\n * (parse result) — typical pattern is `disabled={!isValid}` on a\n * save button driven by `onValidate`.\n */\nexport const JsonViewer = forwardRef<HTMLDivElement, JsonViewerProps>(\n function JsonViewer(\n {\n data,\n mode = \"view\",\n onChange,\n onValidate,\n defaultExpandDepth = 2,\n showIndexes = true,\n copyable = false,\n title,\n status,\n truncateAt = 200,\n height,\n maxHeight,\n className,\n ...rest\n },\n ref,\n ) {\n // Constrain the scrollable body. Numbers get the `px` unit; strings\n // pass through (so consumers can use vh / clamp() / etc.). `height`\n // is the hard size; `maxHeight` is the upper bound when content fits\n // naturally — either one switches the body to a real scroll surface.\n const bodyStyle: React.CSSProperties | undefined =\n height !== undefined\n ? { height: typeof height === \"number\" ? `${height}px` : height }\n : maxHeight !== undefined\n ? { maxHeight: typeof maxHeight === \"number\" ? `${maxHeight}px` : maxHeight }\n : undefined;\n\n return (\n <div {...rest} ref={ref} className={cn(\"ods-json-viewer\", className)} data-mode={mode}>\n {(title || status) && (\n <div className=\"ods-json-viewer__head\">\n {title && <span className=\"ods-json-viewer__title\">{title}</span>}\n {status && <span className=\"ods-json-viewer__status\">{status}</span>}\n </div>\n )}\n <div className=\"ods-json-viewer__body\" style={bodyStyle}>\n {mode === \"edit\" ? (\n <JsonEditBody data={data} onChange={onChange} onValidate={onValidate} />\n ) : (\n <JsonNode\n value={data}\n depth={0}\n defaultExpandDepth={defaultExpandDepth}\n showIndexes={showIndexes}\n copyable={copyable}\n truncateAt={truncateAt}\n />\n )}\n </div>\n </div>\n );\n },\n);\n\nJsonViewer.displayName = \"JsonViewer\";\n\n/* ---------------------------------------------------------------------------\n * Inner tree node — recursive\n * ------------------------------------------------------------------------- */\n\nfunction JsonNode({\n name,\n value,\n depth,\n defaultExpandDepth,\n showIndexes,\n copyable,\n truncateAt,\n isLast = true,\n}: {\n name?: string | number;\n value: unknown;\n depth: number;\n defaultExpandDepth: number;\n showIndexes: boolean;\n copyable: boolean;\n truncateAt: number;\n isLast?: boolean;\n}) {\n const [open, setOpen] = useState(depth < defaultExpandDepth);\n\n const isObject = value !== null && typeof value === \"object\" && !Array.isArray(value);\n const isArray = Array.isArray(value);\n const isContainer = isObject || isArray;\n\n const renderKey = useMemo(() => {\n if (name === undefined) return null;\n if (typeof name === \"number\") {\n return showIndexes ? (\n <span className=\"ods-json-viewer__key ods-json-viewer__key--index\">{name}</span>\n ) : null;\n }\n return <span className=\"ods-json-viewer__key\">{`\"${name}\"`}</span>;\n }, [name, showIndexes]);\n\n if (!isContainer) {\n return (\n <div className=\"ods-json-viewer__row\" style={{ paddingLeft: depth * 14 }}>\n <span className=\"ods-json-viewer__caret-spacer\" />\n {renderKey}\n {renderKey != null && <span className=\"ods-json-viewer__colon\">:</span>}\n <Leaf value={value} truncateAt={truncateAt} copyable={copyable} />\n {!isLast && <span className=\"ods-json-viewer__comma\">,</span>}\n </div>\n );\n }\n\n const entries = isArray\n ? (value as unknown[]).map((v, i) => [i, v] as const)\n : Object.entries(value as Record<string, unknown>);\n\n const openBracket = isArray ? \"[\" : \"{\";\n const closeBracket = isArray ? \"]\" : \"}\";\n\n return (\n <div>\n <div\n className=\"ods-json-viewer__row ods-json-viewer__row--container\"\n style={{ paddingLeft: depth * 14 }}\n onClick={() => setOpen((o) => !o)}\n >\n <button\n type=\"button\"\n className={cn(\"ods-json-viewer__caret\", open && \"ods-json-viewer__caret--open\")}\n aria-expanded={open}\n aria-label={open ? \"Collapse\" : \"Expand\"}\n onClick={(e) => {\n e.stopPropagation();\n setOpen((o) => !o);\n }}\n >\n <ChevronRightIcon aria-hidden=\"true\" />\n </button>\n {renderKey}\n {renderKey != null && <span className=\"ods-json-viewer__colon\">:</span>}\n <span className=\"ods-json-viewer__bracket\">{openBracket}</span>\n {!open && (\n <>\n <span className=\"ods-json-viewer__preview\">\n {isArray\n ? entries.length === 0\n ? \"\"\n : `${entries.length} item${entries.length === 1 ? \"\" : \"s\"}`\n : entries.length === 0\n ? \"\"\n : `${entries.length} key${entries.length === 1 ? \"\" : \"s\"}`}\n </span>\n <span className=\"ods-json-viewer__bracket\">{closeBracket}</span>\n </>\n )}\n {!isLast && !open && <span className=\"ods-json-viewer__comma\">,</span>}\n </div>\n {open && (\n <>\n {entries.map(([k, v], i) => (\n <JsonNode\n key={String(k)}\n name={isArray ? (k as number) : (k as string)}\n value={v}\n depth={depth + 1}\n defaultExpandDepth={defaultExpandDepth}\n showIndexes={showIndexes}\n copyable={copyable}\n truncateAt={truncateAt}\n isLast={i === entries.length - 1}\n />\n ))}\n <div\n className=\"ods-json-viewer__row ods-json-viewer__row--close\"\n style={{ paddingLeft: depth * 14 }}\n >\n <span className=\"ods-json-viewer__caret-spacer\" />\n <span className=\"ods-json-viewer__bracket\">{closeBracket}</span>\n {!isLast && <span className=\"ods-json-viewer__comma\">,</span>}\n </div>\n </>\n )}\n </div>\n );\n}\n\n/* ---------------------------------------------------------------------------\n * Leaf value — type-tinted span + optional copy button\n * ------------------------------------------------------------------------- */\n\nfunction Leaf({\n value,\n truncateAt,\n copyable,\n}: {\n value: unknown;\n truncateAt: number;\n copyable: boolean;\n}) {\n const [copied, setCopied] = useState(false);\n\n let display: string;\n let variant: \"string\" | \"number\" | \"boolean\" | \"null\";\n if (value === null) {\n display = \"null\";\n variant = \"null\";\n } else if (typeof value === \"string\") {\n const t = value.length > truncateAt ? `${value.slice(0, truncateAt)}…` : value;\n display = `\"${t}\"`;\n variant = \"string\";\n } else if (typeof value === \"number\") {\n display = String(value);\n variant = \"number\";\n } else if (typeof value === \"boolean\") {\n display = String(value);\n variant = \"boolean\";\n } else {\n display = String(value);\n variant = \"string\";\n }\n\n const handleCopy = async () => {\n if (!copyable || typeof navigator === \"undefined\") return;\n try {\n await navigator.clipboard.writeText(\n typeof value === \"string\" ? value : JSON.stringify(value),\n );\n setCopied(true);\n setTimeout(() => setCopied(false), 1200);\n } catch {\n /* clipboard write rejected (older browser, permission policy) */\n }\n };\n\n return (\n <span className={cn(\"ods-json-viewer__value\", `ods-json-viewer__value--${variant}`)}>\n <span>{display}</span>\n {copyable && (\n <button\n type=\"button\"\n className={cn(\n \"ods-json-viewer__copy\",\n copied && \"ods-json-viewer__copy--success\",\n )}\n onClick={(e) => {\n e.stopPropagation();\n handleCopy();\n }}\n aria-label={copied ? \"Copied\" : \"Copy value\"}\n >\n {copied ? (\n <CheckmarkIcon width={10} height={10} aria-hidden=\"true\" />\n ) : (\n <CopyIcon width={10} height={10} aria-hidden=\"true\" />\n )}\n </button>\n )}\n </span>\n );\n}\n\n/* ---------------------------------------------------------------------------\n * Edit-mode body — CodeEditor + JSON parse validation\n * ------------------------------------------------------------------------- */\n\n/** Extract `line` / `col` from a native `SyntaxError` thrown by `JSON.parse`.\n * The browser-reported message format varies — we look for common shapes\n * (\"at position N\", \"line N column M\", \"JSON.parse: …line N column M\") and\n * fall back to deriving line/col from the position offset when the raw\n * text is available.\n *\n * Returns `{ line: 1, col: 1 }` when no position info is recoverable —\n * consumers always get a usable location to highlight. */\nfunction extractJsonErrorPosition(\n err: unknown,\n text: string,\n): { line: number; col: number; message: string } {\n const message = err instanceof Error ? err.message : String(err);\n\n // Pattern 1: \"JSON.parse: ... at line N column M ...\"\n // Pattern 2: \"Unexpected token X in JSON at position N\"\n // Pattern 3: \"Expected … in JSON at position N (line N column M)\"\n const lineColMatch = message.match(/line (\\d+) column (\\d+)/i);\n if (lineColMatch) {\n return {\n line: Number(lineColMatch[1]),\n col: Number(lineColMatch[2]),\n message,\n };\n }\n\n const posMatch = message.match(/position (\\d+)/i);\n if (posMatch) {\n const pos = Number(posMatch[1]);\n // Walk the text to convert absolute offset → (line, col).\n let line = 1;\n let col = 1;\n for (let i = 0; i < pos && i < text.length; i++) {\n if (text[i] === \"\\n\") {\n line++;\n col = 1;\n } else {\n col++;\n }\n }\n return { line, col, message };\n }\n\n return { line: 1, col: 1, message };\n}\n\ninterface JsonEditBodyProps {\n data: unknown;\n onChange?: (rawText: string) => void;\n onValidate?: (result: JsonViewerValidationResult) => void;\n}\n\n/** Edit-mode shell — JSON-stringifies `data` once on mount, then owns the\n * text state internally. Parsing happens on every keystroke so consumers\n * get fast validation feedback through `onValidate`. */\nfunction JsonEditBody({ data, onChange, onValidate }: JsonEditBodyProps) {\n // Initial serialization — pretty-printed with 2-space indent so it\n // matches the view-mode tree's visual rhythm. We initialize from `data`\n // once; the editor then becomes the source of truth (changes through\n // `data` prop after mount are ignored to avoid stomping the user's\n // edits mid-typing).\n const initial = useMemo(() => {\n try {\n return JSON.stringify(data, null, 2);\n } catch {\n // Circular refs / non-serializable values — fall back to an empty\n // object so the editor isn't broken.\n return \"{}\";\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const [text, setText] = useState(initial);\n const [parseError, setParseError] = useState<{\n line: number;\n col: number;\n message: string;\n } | null>(null);\n\n // Parse + reporting — extracted so the initial-mount effect and the\n // per-keystroke handler share identical behaviour.\n const validate = (next: string) => {\n try {\n JSON.parse(next);\n setParseError(null);\n onValidate?.({ valid: true });\n } catch (err) {\n const pos = extractJsonErrorPosition(err, next);\n setParseError(pos);\n onValidate?.({ valid: false, error: pos });\n }\n };\n\n const handleChange = (next: string) => {\n setText(next);\n onChange?.(next);\n validate(next);\n };\n\n // Initial validation report — consumers can disable their save button\n // from mount if the seed data happens to be invalid (rare but possible\n // when `data` was already a string of bad JSON).\n useEffect(() => {\n validate(initial);\n // Run once on mount to seed the consumer's validity flag.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n return (\n <div className=\"ods-json-viewer__edit\">\n {parseError && (\n <InlineMessage\n tone=\"danger\"\n size=\"sm\"\n className=\"ods-json-viewer__parse-error\"\n title={`Line ${parseError.line}, column ${parseError.col}`}\n >\n Line {parseError.line}, col {parseError.col} · {parseError.message}\n </InlineMessage>\n )}\n <CodeEditor\n value={text}\n onChange={handleChange}\n language=\"json\"\n ariaLabel=\"JSON editor\"\n showFormat\n showCopy\n />\n </div>\n );\n}\n","// ════════════════════════════════════════════════════════════════════════\n// Edge-path builders — bezier, step, smoothstep, straight.\n// ════════════════════════════════════════════════════════════════════════\n// All builders take two oriented endpoints (a position + the side of the\n// node that the port faces) and return:\n// - `d` — the SVG path attribute\n// - `midX`, `midY` — analytic midpoint used by the label + delete chrome\n//\n// Path style is selected via `edge.routing`. The choice does NOT affect\n// the `edge.type` semantic (default/conditional/loop/error) which still\n// drives stroke colour and dash. They're orthogonal.\n\nimport type { HandlePosition, Position } from \"../editor\";\n\nexport type EdgeRouting = \"bezier\" | \"step\" | \"smoothstep\" | \"straight\";\n\nexport interface PathGeometry {\n d: string;\n midX: number;\n midY: number;\n /** Tangent angle (radians) at the midpoint — useful when callers want\n * to offset the label/delete chrome along or perpendicular to the path. */\n midAngle: number;\n}\n\n// ── Public dispatcher ──────────────────────────────────────────────────\nexport function buildEdgePath(\n routing: EdgeRouting,\n start: Position,\n startSide: HandlePosition,\n end: Position,\n endSide: HandlePosition,\n options: { borderRadius?: number; curvature?: number } = {},\n): PathGeometry {\n switch (routing) {\n case \"step\":\n return stepPath(start, startSide, end, endSide);\n case \"smoothstep\":\n return smoothStepPath(start, startSide, end, endSide, options.borderRadius ?? 8);\n case \"straight\":\n return straightPath(start, end);\n default:\n return bezierPath(start, startSide, end, endSide, options.curvature ?? 0.25);\n }\n}\n\n// ── Bezier — React-Flow-style control-offset algorithm ────────────────\n// `curvature` ∈ [0, 1]. Smaller = tighter; 0.25 is a comfortable default.\n// When the target is *in the port's forward direction*, offset is a linear\n// fraction of axis distance. When *behind* (target is in the opposite\n// direction from where the port faces), offset uses a square-root falloff\n// so the curve fans out without overshooting wildly.\nexport function bezierPath(\n start: Position,\n startSide: HandlePosition,\n end: Position,\n endSide: HandlePosition,\n curvature = 0.25,\n): PathGeometry {\n const sourceOffset = calcControlOffset(start, startSide, end, curvature);\n const targetOffset = calcControlOffset(end, endSide, start, curvature);\n const c1 = offsetAlongSide(start, startSide, sourceOffset);\n const c2 = offsetAlongSide(end, endSide, targetOffset);\n\n const d = `M ${start.x},${start.y} C ${c1.x},${c1.y} ${c2.x},${c2.y} ${end.x},${end.y}`;\n\n // Analytic midpoint of a cubic bezier at t=0.5.\n const midX = 0.125 * start.x + 0.375 * c1.x + 0.375 * c2.x + 0.125 * end.x;\n const midY = 0.125 * start.y + 0.375 * c1.y + 0.375 * c2.y + 0.125 * end.y;\n // Tangent at t=0.5 = 3 * ((c2 - c1) + 0.5 * ((c1 - start) - (end - c2))).\n // Simplified: derivative of the bezier polynomial at 0.5.\n const tx =\n 3 *\n ((1 - 0.5) ** 2 * (c1.x - start.x) +\n 2 * (1 - 0.5) * 0.5 * (c2.x - c1.x) +\n 0.5 ** 2 * (end.x - c2.x));\n const ty =\n 3 *\n ((1 - 0.5) ** 2 * (c1.y - start.y) +\n 2 * (1 - 0.5) * 0.5 * (c2.y - c1.y) +\n 0.5 ** 2 * (end.y - c2.y));\n const midAngle = Math.atan2(ty, tx);\n\n return { d, midX, midY, midAngle };\n}\n\n/**\n * Distance from `from` to `to` along the axis the `side` points in.\n * Positive = `to` is in front of the port; negative = behind.\n */\nfunction axisDistance(from: Position, side: HandlePosition, to: Position): number {\n switch (side) {\n case \"top\":\n return from.y - to.y;\n case \"bottom\":\n return to.y - from.y;\n case \"left\":\n return from.x - to.x;\n case \"right\":\n return to.x - from.x;\n }\n}\n\nfunction calcControlOffset(\n from: Position,\n side: HandlePosition,\n to: Position,\n curvature: number,\n): number {\n const distance = axisDistance(from, side, to);\n if (distance >= 0) {\n // Linear fraction of axis distance — produces gentle S-curves.\n return distance * 0.5 * (1 + curvature);\n }\n // Backward — square-root falloff so the curve fans wide without\n // shooting off into space at extreme distances. The 25-multiplier is\n // tuned to match React Flow's visual behaviour.\n return curvature * 25 * Math.sqrt(-distance);\n}\n\nfunction offsetAlongSide(p: Position, side: HandlePosition, magnitude: number): Position {\n switch (side) {\n case \"top\":\n return { x: p.x, y: p.y - magnitude };\n case \"bottom\":\n return { x: p.x, y: p.y + magnitude };\n case \"left\":\n return { x: p.x - magnitude, y: p.y };\n case \"right\":\n return { x: p.x + magnitude, y: p.y };\n }\n}\n\n// ── Step routing — orthogonal Z/U-bend ────────────────────────────────\n// For top/bottom ports: vertical-horizontal-vertical (Z). For left/right\n// ports: horizontal-vertical-horizontal. Mixed sides produce an L.\nexport function stepPath(\n start: Position,\n startSide: HandlePosition,\n end: Position,\n endSide: HandlePosition,\n): PathGeometry {\n const corners = computeStepCorners(start, startSide, end, endSide);\n const pts = [start, ...corners, end];\n const d = pts.map((p, i) => `${i === 0 ? \"M\" : \"L\"} ${p.x},${p.y}`).join(\" \");\n // Midpoint along the longest segment so label/delete don't overlap a corner.\n const { midX, midY, midAngle } = midpointOnPolyline(pts);\n return { d, midX, midY, midAngle };\n}\n\n// ── Smoothstep — step with rounded corners ────────────────────────────\nexport function smoothStepPath(\n start: Position,\n startSide: HandlePosition,\n end: Position,\n endSide: HandlePosition,\n borderRadius = 8,\n): PathGeometry {\n const corners = computeStepCorners(start, startSide, end, endSide);\n const pts = [start, ...corners, end];\n if (corners.length === 0) {\n return straightPath(start, end);\n }\n // Build SVG path with `Q` arcs at each interior corner.\n const segments: string[] = [`M ${pts[0].x},${pts[0].y}`];\n for (let i = 1; i < pts.length - 1; i++) {\n const prev = pts[i - 1];\n const here = pts[i];\n const next = pts[i + 1];\n // Cap the radius so it never exceeds half of the adjacent segments.\n const r = Math.min(borderRadius, distance(prev, here) / 2, distance(here, next) / 2);\n const enter = pointTowards(here, prev, r);\n const exit = pointTowards(here, next, r);\n segments.push(`L ${enter.x},${enter.y}`);\n segments.push(`Q ${here.x},${here.y} ${exit.x},${exit.y}`);\n }\n const last = pts[pts.length - 1];\n segments.push(`L ${last.x},${last.y}`);\n const d = segments.join(\" \");\n const { midX, midY, midAngle } = midpointOnPolyline(pts);\n return { d, midX, midY, midAngle };\n}\n\n// ── Straight ─────────────────────────────────────────────────────────\nexport function straightPath(start: Position, end: Position): PathGeometry {\n const d = `M ${start.x},${start.y} L ${end.x},${end.y}`;\n return {\n d,\n midX: (start.x + end.x) / 2,\n midY: (start.y + end.y) / 2,\n midAngle: Math.atan2(end.y - start.y, end.x - start.x),\n };\n}\n\n// ── Helpers ───────────────────────────────────────────────────────────\nfunction computeStepCorners(\n start: Position,\n startSide: HandlePosition,\n end: Position,\n endSide: HandlePosition,\n): Position[] {\n const sourceVertical = startSide === \"top\" || startSide === \"bottom\";\n const targetVertical = endSide === \"top\" || endSide === \"bottom\";\n\n if (sourceVertical && targetVertical) {\n // Z-shape: vertical → horizontal → vertical.\n const midY = (start.y + end.y) / 2;\n return [\n { x: start.x, y: midY },\n { x: end.x, y: midY },\n ];\n }\n if (!sourceVertical && !targetVertical) {\n // Same idea horizontally.\n const midX = (start.x + end.x) / 2;\n return [\n { x: midX, y: start.y },\n { x: midX, y: end.y },\n ];\n }\n // Mixed — L-shape (single corner at the intersection).\n if (sourceVertical) {\n return [{ x: end.x, y: start.y }];\n }\n return [{ x: start.x, y: end.y }];\n}\n\nfunction midpointOnPolyline(pts: Position[]): {\n midX: number;\n midY: number;\n midAngle: number;\n} {\n if (pts.length === 2) {\n return {\n midX: (pts[0].x + pts[1].x) / 2,\n midY: (pts[0].y + pts[1].y) / 2,\n midAngle: Math.atan2(pts[1].y - pts[0].y, pts[1].x - pts[0].x),\n };\n }\n // Walk segments accumulating length; pick the segment whose midpoint\n // is closest to the half-length mark. Anchoring the label to the\n // longest segment keeps it readable.\n let totalLen = 0;\n const lens: number[] = [];\n for (let i = 0; i < pts.length - 1; i++) {\n const l = distance(pts[i], pts[i + 1]);\n lens.push(l);\n totalLen += l;\n }\n const half = totalLen / 2;\n let acc = 0;\n for (let i = 0; i < lens.length; i++) {\n if (acc + lens[i] >= half) {\n const seg = lens[i];\n const remaining = half - acc;\n const t = seg === 0 ? 0 : remaining / seg;\n const a = pts[i];\n const b = pts[i + 1];\n return {\n midX: a.x + (b.x - a.x) * t,\n midY: a.y + (b.y - a.y) * t,\n midAngle: Math.atan2(b.y - a.y, b.x - a.x),\n };\n }\n acc += lens[i];\n }\n // Fallback — unreachable in practice.\n return { midX: pts[0].x, midY: pts[0].y, midAngle: 0 };\n}\n\nfunction distance(a: Position, b: Position): number {\n return Math.hypot(b.x - a.x, b.y - a.y);\n}\n\nfunction pointTowards(from: Position, to: Position, dist: number): Position {\n const d = distance(from, to);\n if (d === 0) return from;\n const t = dist / d;\n return { x: from.x + (to.x - from.x) * t, y: from.y + (to.y - from.y) * t };\n}\n","\"use client\";\n\n// ════════════════════════════════════════════════════════════════════════\n// useFlow — imperative instance for the workflow editor.\n// ════════════════════════════════════════════════════════════════════════\n// Consumers reach inside `<FlowCanvas>` via this hook to do things that\n// React's declarative API can't express cleanly:\n//\n// - convert between screen and flow coordinates (drag-from-palette\n// needs to know where the pointer landed in flow space)\n// - imperatively fit the viewport to a set of nodes (\"zoom to error\")\n// - query intersecting nodes for marquee select / dragover hits\n// - patch node data without round-tripping through the parent reducer\n// - request a delete that respects `onBeforeDelete` veto\n//\n// All methods read from the FlowStore via narrow selectors, so the hook\n// itself doesn't trigger re-renders when state changes. The instance\n// reference is stable for the lifetime of the canvas.\n\nimport { createContext, useContext } from \"react\";\nimport type {\n FitViewOptions,\n Position,\n Rect,\n Viewport,\n WorkflowEdge,\n WorkflowNode,\n} from \"../editor\";\n\nexport interface FlowInstance {\n // ── Viewport ───────────────────────────────────────────────────────\n getViewport(): Viewport;\n setViewport(viewport: Viewport, opts?: { duration?: number }): void;\n setCenter(x: number, y: number, opts?: { duration?: number; zoom?: number }): void;\n fitView(opts?: FitViewOptions): Promise<boolean>;\n zoomIn(opts?: { step?: number }): void;\n zoomOut(opts?: { step?: number }): void;\n zoomTo(level: number): void;\n\n // ── Coordinate transforms ──────────────────────────────────────────\n /** Convert a pointer position (relative to the canvas container) into\n * flow-space coordinates. */\n screenToFlowPosition(p: Position): Position;\n /** Inverse of `screenToFlowPosition`. */\n flowToScreenPosition(p: Position): Position;\n\n // ── Data access (snapshot reads) ───────────────────────────────────\n getNodes(): WorkflowNode[];\n getEdges(): WorkflowEdge[];\n getNode(id: string): WorkflowNode | undefined;\n getEdge(id: string): WorkflowEdge | undefined;\n /** Axis-aligned bounding box of the given nodes (or every node when omitted). */\n getNodesBounds(nodes?: { id: string }[]): Rect;\n /** Find every node whose bbox overlaps the given rect.\n * `partially=true` includes partial overlaps; `false` requires full containment. */\n getIntersectingNodes(area: Rect, partially?: boolean): WorkflowNode[];\n\n // ── Mutation (round-tripped through onNodesChange/onEdgesChange) ──\n addNodes(nodes: WorkflowNode | WorkflowNode[]): void;\n addEdges(edges: WorkflowEdge | WorkflowEdge[]): void;\n /** Merge a partial into the node's existing `data` field. Cheap shorthand\n * for the common case of editing a node's payload without rebuilding it. */\n updateNodeData<TData = unknown>(id: string, partial: Partial<TData>): void;\n /** Replace the node entirely (use sparingly — usually `updateNodeData` is enough). */\n updateNode(id: string, partial: Partial<WorkflowNode>): void;\n /** Imperatively remove nodes and/or edges. Returns false if the host's\n * `onBeforeDelete` vetoed; true otherwise. Synchronous for non-async\n * vetoes; awaits the promise when the host returns one. */\n deleteElements(params: { nodes?: { id: string }[]; edges?: { id: string }[] }): Promise<boolean>;\n}\n\nexport const FlowInstanceContext = createContext<FlowInstance | null>(null);\n\n/**\n * Imperative handle for `<FlowCanvas>`. Throws if called outside the\n * canvas — the instance is canvas-scoped (not a global singleton) so\n * multiple canvases on the same page each have their own.\n */\nexport function useFlow(): FlowInstance {\n const instance = useContext(FlowInstanceContext);\n if (!instance) {\n throw new Error(\"[@octaviaflow/core/workflow] useFlow() must be called inside <FlowCanvas>.\");\n }\n return instance;\n}\n","// ════════════════════════════════════════════════════════════════════════\n// Shared geometry helpers used by FlowNode, FlowEdge, and the connection\n// drag middleware. Pure functions — no state, no DOM.\n// ════════════════════════════════════════════════════════════════════════\n\nimport type { HandlePosition, Position, Viewport, WorkflowNode } from \"../editor\";\n\n// Default node footprint when the renderer hasn't yet measured a custom\n// node. Kept in lockstep with the BaseNode body width (368 px) so the\n// pre-measurement edge math anchors precisely on the handle dot. Height\n// stays 96 — the body min-height clamps the real measurement past that.\nexport const DEFAULT_NODE_WIDTH = 368;\nexport const DEFAULT_NODE_HEIGHT = 96;\n\n// Collapsed container heights — kept in lockstep with the values in\n// `kinds/index.tsx` (GroupNode renders `collapsed ? 36 : ...`,\n// ForEachNode renders `collapsed ? 40 : ...`). When a container is\n// collapsed its visual footprint shrinks to this header strip; edges to\n// the perimeter handles must use the same height or they'll terminate\n// hundreds of pixels below the visible node.\nexport const COLLAPSED_GROUP_HEIGHT = 36;\nexport const COLLAPSED_FOREACH_HEIGHT = 40;\n\n/**\n * The height the node *actually renders at* — accounts for collapsed\n * containers whose visual height differs from `node.height`. All edge\n * geometry should go through this helper instead of reading\n * `node.height` directly.\n */\nexport function effectiveHeight(node: WorkflowNode): number {\n const data = node.data as { collapsed?: boolean } | undefined;\n if (data?.collapsed) {\n if (node.type === \"group\") return COLLAPSED_GROUP_HEIGHT;\n if (node.type === \"forEach\") return COLLAPSED_FOREACH_HEIGHT;\n }\n return node.height ?? DEFAULT_NODE_HEIGHT;\n}\n\n/**\n * Compute the absolute (flow-space) centre of one of a node's handles.\n *\n * The handle's logical position (`top`/`right`/`bottom`/`left`) plus its\n * index among same-side handles determines a deterministic spread along\n * the relevant edge of the node bbox. We do NOT consult the DOM — the\n * source of truth is the node's measured (or default) dimensions.\n *\n * `total` is the count of handles on that side, `index` is this handle's\n * 0-based position among them. A single handle centres; multiple spread\n * evenly with equal margins.\n */\nexport function handleCentre(\n node: WorkflowNode,\n side: HandlePosition,\n index: number,\n total: number,\n): Position {\n const w = node.width ?? DEFAULT_NODE_WIDTH;\n // Use the EFFECTIVE rendered height — collapsed containers report a\n // tall `node.height` but visually render a 36-40px strip. Without this,\n // edges to a collapsed group's perimeter handle terminate hundreds of\n // pixels below the visible pill.\n const h = effectiveHeight(node);\n const x0 = node.position.x;\n const y0 = node.position.y;\n const denom = total + 1;\n const ratio = (index + 1) / denom;\n\n switch (side) {\n case \"top\":\n return { x: x0 + w * ratio, y: y0 };\n case \"bottom\":\n return { x: x0 + w * ratio, y: y0 + h };\n case \"left\":\n return { x: x0, y: y0 + h * ratio };\n case \"right\":\n return { x: x0 + w, y: y0 + h * ratio };\n }\n}\n\n/**\n * Cubic bezier path between two oriented points. The control points are\n * offset along each port's facing direction so the curve leaves and\n * enters along the port's axis (the same routing model as v1).\n */\nexport function bezierPath(\n start: Position,\n startSide: HandlePosition,\n end: Position,\n endSide: HandlePosition,\n): { d: string; midX: number; midY: number } {\n const distance = Math.hypot(end.x - start.x, end.y - start.y);\n const magnitude = Math.max(40, Math.min(160, distance * 0.45));\n const c1 = offsetBySide(start, startSide, magnitude);\n const c2 = offsetBySide(end, endSide, magnitude);\n const d = `M ${start.x},${start.y} C ${c1.x},${c1.y} ${c2.x},${c2.y} ${end.x},${end.y}`;\n // Analytic midpoint of a cubic bezier at t = 0.5.\n const midX = 0.125 * start.x + 0.375 * c1.x + 0.375 * c2.x + 0.125 * end.x;\n const midY = 0.125 * start.y + 0.375 * c1.y + 0.375 * c2.y + 0.125 * end.y;\n return { d, midX, midY };\n}\n\nfunction offsetBySide(p: Position, side: HandlePosition, m: number): Position {\n switch (side) {\n case \"top\":\n return { x: p.x, y: p.y - m };\n case \"bottom\":\n return { x: p.x, y: p.y + m };\n case \"left\":\n return { x: p.x - m, y: p.y };\n case \"right\":\n return { x: p.x + m, y: p.y };\n }\n}\n\n/**\n * Convert a screen-space point (pixels relative to the viewport\n * container's top-left) to flow-space coordinates, given the current\n * viewport.\n */\nexport function screenToFlow(p: Position, vp: Viewport): Position {\n return {\n x: (p.x - vp.x) / vp.zoom,\n y: (p.y - vp.y) / vp.zoom,\n };\n}\n\n/**\n * Inverse of `screenToFlow`.\n */\nexport function flowToScreen(p: Position, vp: Viewport): Position {\n return {\n x: p.x * vp.zoom + vp.x,\n y: p.y * vp.zoom + vp.y,\n };\n}\n","\"use client\";\nimport {\n type ComponentPropsWithoutRef,\n forwardRef,\n type ReactNode,\n useRef,\n} from \"react\";\nimport { useSwitch } from \"react-aria\";\nimport { useToggleState } from \"react-stately\";\nimport { getRenderableText, resolveAccessibleName } from \"../../utils/a11y\";\nimport { cn } from \"../../utils/cn\";\n\n/* ---------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\nexport type SwitchSize = \"sm\" | \"md\" | \"lg\";\n\ntype InputPropsBase = Omit<\n ComponentPropsWithoutRef<\"input\">,\n \"type\" | \"onChange\" | \"size\" | \"checked\" | \"defaultChecked\"\n>;\n\nexport interface SwitchProps extends InputPropsBase {\n checked?: boolean;\n defaultChecked?: boolean;\n onChange?: (isSelected: boolean) => void;\n disabled?: boolean;\n size?: SwitchSize;\n /** Visible label — accepts rich content. */\n label?: ReactNode;\n /** Optional sublabel rendered below the label. */\n description?: ReactNode;\n}\n\n/* ---------------------------------------------------------------------------\n * Component\n * ------------------------------------------------------------------------- */\n\nexport const Switch = forwardRef<HTMLInputElement, SwitchProps>(function Switch(\n {\n checked,\n defaultChecked,\n onChange,\n disabled = false,\n size = \"md\",\n label,\n description,\n className,\n ...props\n },\n forwardedRef,\n) {\n const innerRef = useRef<HTMLInputElement>(null);\n // Compose forwarded ref + internal ref so consumers can `.focus()`\n // while react-aria's plumbing still works.\n const setRef = (node: HTMLInputElement | null) => {\n (innerRef as { current: HTMLInputElement | null }).current = node;\n if (typeof forwardedRef === \"function\") forwardedRef(node);\n else if (forwardedRef)\n (forwardedRef as { current: HTMLInputElement | null }).current = node;\n };\n\n const state = useToggleState({\n isSelected: checked,\n defaultSelected: defaultChecked,\n onChange,\n });\n\n // Derive the accessible name from the label's TEXT — including a rich\n // ReactNode label (icon + text, custom JSX), not just a bare string. Without\n // this, a non-string `label` was dropped here and the switch tripped a false\n // \"no accessible name\" warning + a bogus aria-label=\"Unlabeled Switch\" that\n // overrode the real visible label. A genuinely nameless switch (no label,\n // no aria-*) still warns, which is correct.\n const labelText = getRenderableText(label).trim();\n const ariaNameProps = resolveAccessibleName({\n label: labelText || undefined,\n ariaLabel: (props as Record<string, unknown>)[\"aria-label\"] as\n | string\n | undefined,\n ariaLabelledby: (props as Record<string, unknown>)[\"aria-labelledby\"] as\n | string\n | undefined,\n componentName: \"Switch\",\n });\n\n const { inputProps } = useSwitch(\n {\n isSelected: state.isSelected,\n isDisabled: disabled,\n onChange,\n ...ariaNameProps,\n },\n state,\n innerRef,\n );\n\n const isOn = state.isSelected;\n\n // React Aria owns the interactive event handlers + aria-* on the\n // input. Strip them from the caller's props so we don't double-bind;\n // native form attrs (name/value/form/id/etc.) flow through.\n const {\n onClick: _onClick,\n onKeyDown: _onKeyDown,\n onKeyUp: _onKeyUp,\n onFocus: _onFocus,\n onBlur: _onBlur,\n ...passthroughProps\n } = props as Record<string, unknown>;\n\n return (\n <label\n className={cn(\n \"ods-switch\",\n `ods-switch--${size}`,\n disabled && \"ods-switch--disabled\",\n description && \"ods-switch--with-description\",\n className,\n )}\n >\n <input\n {...(passthroughProps as ComponentPropsWithoutRef<\"input\">)}\n {...inputProps}\n ref={setRef}\n className=\"ods-switch__input\"\n />\n <div\n className={cn(\"ods-switch__track\", isOn && \"ods-switch__track--on\")}\n aria-hidden=\"true\"\n >\n <div className=\"ods-switch__thumb\" />\n </div>\n {(label || description) && (\n <div className=\"ods-switch__text\">\n {label && <span className=\"ods-switch__label\">{label}</span>}\n {description && (\n <span className=\"ods-switch__description\">{description}</span>\n )}\n </div>\n )}\n </label>\n );\n});\n\nSwitch.displayName = \"Switch\";\n","// ════════════════════════════════════════════════════════════════════════\n// Narrow selector hooks — the only sanctioned way to read from the store.\n// Each hook does one thing and subscribes to the smallest possible slice\n// so re-renders are surgical.\n// ════════════════════════════════════════════════════════════════════════\n\nimport { useContext, useMemo, useSyncExternalStore } from \"react\";\nimport type {\n ConnectStartParams,\n FlowStoreSnapshot,\n Viewport,\n WorkflowEdge,\n WorkflowNode,\n} from \"../editor\";\nimport { FlowStoreContext, useFlowStore } from \"./context\";\n\n/**\n * Generic selector hook. Use for one-off reads in tests or rare cases.\n * Public hooks below cover the common paths.\n *\n * NB: `selector` must be stable (referentially equal across renders) or\n * memoised — otherwise it re-subscribes every render. We do NOT do this\n * automatically because it would mask the bug.\n */\nexport function useFlowSelector<T>(\n selector: (snapshot: FlowStoreSnapshot) => T,\n isEqual: (a: T, b: T) => boolean = Object.is,\n): T {\n // Note: useSyncExternalStore uses Object.is internally for change\n // detection. The `isEqual` arg is reserved for a future patch that adds\n // structural equality (e.g. for array selectors); reference it so the\n // arg isn't dead.\n void isEqual;\n const store = useFlowStore();\n return useSyncExternalStore(\n store.subscribe,\n () => selector(store.getSnapshot()),\n () => selector(store.getSnapshot()),\n );\n}\n\n// ── Reads ──────────────────────────────────────────────────────────────\n\nexport function useNodes(): WorkflowNode[] {\n return useFlowSelector((s) => s.nodes);\n}\n\nexport function useEdges(): WorkflowEdge[] {\n return useFlowSelector((s) => s.edges);\n}\n\nexport function useViewport(): Viewport {\n return useFlowSelector((s) => s.viewport);\n}\n\nconst VIEWPORT_OR_NULL_NO_STORE_SUBSCRIBE = (_cb: () => void) => () => {};\nconst VIEWPORT_OR_NULL_NO_STORE_SNAPSHOT = (): Viewport | null => null;\n\n/**\n * Like `useViewport()` but returns `null` when called outside a\n * `<FlowCanvas>`. Useful for shared chrome components (FlowToolbarZoom,\n * minimap previews) that want to auto-subscribe when mounted inside the\n * canvas, but still render correctly in isolation (Storybook, design\n * docs) when no store is present.\n *\n * The subscribe/getSnapshot pair is memoised so React subscribes once per\n * mounted `<FlowCanvas>` ancestor — flipping in/out is rare (only when a\n * canvas is unmounted around the consumer).\n */\nexport function useViewportOrNull(): Viewport | null {\n const store = useContext(FlowStoreContext);\n const { sub, snap } = useMemo(\n () =>\n store\n ? {\n sub: store.subscribe,\n snap: (): Viewport | null => store.getSnapshot().viewport,\n }\n : {\n sub: VIEWPORT_OR_NULL_NO_STORE_SUBSCRIBE,\n snap: VIEWPORT_OR_NULL_NO_STORE_SNAPSHOT,\n },\n [store],\n );\n return useSyncExternalStore(sub, snap, snap);\n}\n\nexport function useNodeById(id: string): WorkflowNode | undefined {\n return useFlowSelector((s) => s.nodes.find((n) => n.id === id));\n}\n\n/**\n * Subscribe to the `data` slice of a single node by id. Re-renders only\n * when this specific node's `data` reference changes — no cross-node\n * leakage. Pair with `FlowStateBag.updateNodeData(id, patch)` to write.\n *\n * Returns undefined when the node is not present; consumers should\n * branch on that. Typed via the generic so callers get their `TData`\n * shape back without casting.\n */\nexport function useNodeData<TData = unknown>(id: string): TData | undefined {\n return useFlowSelector(\n (s) => (s.nodes.find((n) => n.id === id)?.data as TData | undefined) ?? undefined,\n );\n}\n\nexport function useEdgeById(id: string): WorkflowEdge | undefined {\n return useFlowSelector((s) => s.edges.find((e) => e.id === id));\n}\n\nexport function useIsNodeSelected(id: string): boolean {\n return useFlowSelector((s) => s.selectedNodeIds.has(id));\n}\n\nexport function useIsEdgeSelected(id: string): boolean {\n return useFlowSelector((s) => s.selectedEdgeIds.has(id));\n}\n\nexport function useConnection(): ConnectStartParams | null {\n return useFlowSelector((s) => s.connection);\n}\n\nexport function useSelection(): { nodes: WorkflowNode[]; edges: WorkflowEdge[] } {\n // Subscribe to each underlying slice separately so useSyncExternalStore\n // sees stable references — building a fresh object inside the selector\n // would force a re-render every render (snapshot-cache violation).\n const nodes = useNodes();\n const edges = useEdges();\n const selectedNodeIds = useFlowSelector((s) => s.selectedNodeIds);\n const selectedEdgeIds = useFlowSelector((s) => s.selectedEdgeIds);\n return useMemo(\n () => ({\n nodes: nodes.filter((n) => selectedNodeIds.has(n.id)),\n edges: edges.filter((e) => selectedEdgeIds.has(e.id)),\n }),\n [nodes, edges, selectedNodeIds, selectedEdgeIds],\n );\n}\n","// ════════════════════════════════════════════════════════════════════════\n// FlowStoreContext — descendants reach the store through this React\n// context. The store itself is NOT a context value (that would tank\n// perf); only the store *handle* is. Consumers read state via the\n// selector hooks in `./selectors.ts`.\n// ════════════════════════════════════════════════════════════════════════\n\nimport { createContext, useContext } from \"react\";\nimport type { FlowStore } from \"./createFlowStore\";\n\nexport const FlowStoreContext = createContext<FlowStore | null>(null);\n\nexport function useFlowStore(): FlowStore {\n const store = useContext(FlowStoreContext);\n if (!store) {\n throw new Error(\n \"[@octaviaflow/core/workflow] useFlowStore must be called inside a <FlowCanvas>.\",\n );\n }\n return store;\n}\n","\"use client\";\nimport {\n type ChangeEvent,\n type ComponentPropsWithoutRef,\n forwardRef,\n type ReactNode,\n useCallback,\n useId,\n} from \"react\";\nimport { AddIcon, SubtractIcon } from \"@octaviaflow/icons\";\nimport { cn } from \"../../utils/cn\";\n\n/* ---------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\nexport type NumberInputSize = \"sm\" | \"md\" | \"lg\";\n\n/** Native `<input>` props minus the ones the component owns. We also drop\n * the native `size` attribute because we redefine `size` as the visual\n * variant (\"sm\" | \"md\" | \"lg\"). */\ntype InputPropsBase = Omit<\n ComponentPropsWithoutRef<\"input\">,\n | \"type\"\n | \"value\"\n | \"onChange\"\n | \"min\"\n | \"max\"\n | \"step\"\n | \"size\"\n | \"prefix\"\n>;\n\nexport interface NumberInputProps extends InputPropsBase {\n label?: ReactNode;\n value: number;\n onChange?: (value: number) => void;\n min?: number;\n max?: number;\n step?: number;\n prefix?: ReactNode;\n suffix?: ReactNode;\n size?: NumberInputSize;\n disabled?: boolean;\n error?: ReactNode;\n helperText?: ReactNode;\n /** Extra class on the wrapper (NOT the input — use `inputClassName` for\n * the underlying control's class). */\n wrapperClassName?: string;\n /** Hide the +/- stepper buttons — renders a plain numeric field. The\n * value can still be typed; native number-input arrow keys still work. */\n hideControls?: boolean;\n /** Horizontal alignment of the value. Defaults to \"center\" (the\n * stepper-flanked style); use \"left\" for a standard form-field look.\n * Implied when `hideControls` is set unless overridden. */\n align?: \"left\" | \"center\";\n}\n\n/* ---------------------------------------------------------------------------\n * Component\n * ------------------------------------------------------------------------- */\n\nexport const NumberInput = forwardRef<HTMLInputElement, NumberInputProps>(\n function NumberInput(\n {\n label,\n value,\n onChange,\n min,\n max,\n step = 1,\n prefix,\n suffix,\n size = \"md\",\n disabled = false,\n error,\n helperText,\n id: providedId,\n className,\n wrapperClassName,\n hideControls = false,\n align,\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledBy,\n \"aria-describedby\": consumerDescribedBy,\n ...rest\n },\n ref,\n ) {\n // When the steppers are hidden the field reads like a normal form\n // input, so default the value to left-aligned unless the consumer\n // explicitly asked for centre.\n const resolvedAlign = align ?? (hideControls ? \"left\" : \"center\");\n const reactId = useId();\n const inputId = providedId ?? `ods-num-${reactId}`;\n const labelId = label ? `${inputId}-label` : undefined;\n const hintId = error || helperText ? `${inputId}-hint` : undefined;\n\n const clamp = useCallback(\n (v: number) => {\n if (typeof min === \"number\") v = Math.max(min, v);\n if (typeof max === \"number\") v = Math.min(max, v);\n return v;\n },\n [min, max],\n );\n\n const dec = () => !disabled && onChange?.(clamp(value - step));\n const inc = () => !disabled && onChange?.(clamp(value + step));\n const handleInput = (e: ChangeEvent<HTMLInputElement>) => {\n // Empty string is a valid transient state while the user is typing\n // (e.g. erasing to retype) — preserve it via NaN so the caller can\n // decide whether to coerce. For a controlled component callers\n // typically just hold their last numeric value.\n const raw = e.target.value;\n if (raw === \"\") return;\n const num = Number(raw);\n if (!Number.isNaN(num)) onChange?.(clamp(num));\n };\n\n // Compose aria-describedby: consumer's value wins on conflict, then\n // our hint id is appended. Filter out empties to keep the attribute\n // tidy when nothing applies.\n const describedBy =\n [consumerDescribedBy, hintId].filter(Boolean).join(\" \") || undefined;\n\n return (\n <div\n className={cn(\n \"ods-num\",\n `ods-num--${size}`,\n disabled && \"ods-num--disabled\",\n error && \"ods-num--error\",\n hideControls && \"ods-num--no-controls\",\n resolvedAlign === \"left\" && \"ods-num--align-left\",\n wrapperClassName,\n )}\n >\n {label && (\n <label\n id={labelId}\n htmlFor={inputId}\n className=\"ods-num__label\"\n >\n {label}\n </label>\n )}\n <div className=\"ods-num__field\">\n {!hideControls && (\n <button\n type=\"button\"\n className=\"ods-num__step ods-num__step--dec\"\n onClick={dec}\n disabled={disabled || (typeof min === \"number\" && value <= min)}\n aria-label=\"Decrease\"\n tabIndex={-1}\n >\n <SubtractIcon />\n </button>\n )}\n {prefix && (\n <span className=\"ods-num__prefix\" aria-hidden=\"true\">\n {prefix}\n </span>\n )}\n <input\n {...rest}\n ref={ref}\n id={inputId}\n type=\"number\"\n className={cn(\"ods-num__input\", className)}\n value={Number.isFinite(value) ? value : \"\"}\n onChange={handleInput}\n disabled={disabled}\n min={min}\n max={max}\n step={step}\n aria-invalid={error ? true : undefined}\n aria-describedby={describedBy}\n // Accessible-name fallback chain: an explicit aria-labelledby\n // or aria-label always wins. Otherwise we fall back to the\n // visible <label> when one was rendered.\n aria-labelledby={ariaLabelledBy ?? labelId}\n aria-label={\n !labelId && !ariaLabelledBy ? ariaLabel : undefined\n }\n />\n {suffix && (\n <span className=\"ods-num__suffix\" aria-hidden=\"true\">\n {suffix}\n </span>\n )}\n {!hideControls && (\n <button\n type=\"button\"\n className=\"ods-num__step ods-num__step--inc\"\n onClick={inc}\n disabled={disabled || (typeof max === \"number\" && value >= max)}\n aria-label=\"Increase\"\n tabIndex={-1}\n >\n <AddIcon />\n </button>\n )}\n </div>\n {error ? (\n <div\n id={hintId}\n className=\"ods-num__hint ods-num__hint--error\"\n role=\"alert\"\n >\n {error}\n </div>\n ) : helperText ? (\n <div id={hintId} className=\"ods-num__hint\">\n {helperText}\n </div>\n ) : null}\n </div>\n );\n },\n);\n\nNumberInput.displayName = \"NumberInput\";\n","\"use client\";\nimport { motion } from \"framer-motion\";\nimport { type ReactNode, useCallback, useEffect, useId, useMemo, useRef, useState } from \"react\";\nimport { useTab, useTabList, useTabPanel } from \"react-aria\";\nimport { Item, type TabListStateOptions, useTabListState } from \"react-stately\";\nimport { cn } from \"../../utils/cn\";\n\nexport interface TabItem {\n value: string;\n label: string;\n icon?: ReactNode;\n disabled?: boolean;\n children?: ReactNode;\n}\n\nexport interface TabsProps {\n items: TabItem[];\n value?: string;\n defaultValue?: string;\n onChange?: (value: string) => void;\n orientation?: \"horizontal\" | \"vertical\";\n className?: string;\n}\n\n// Each Tabs instance gets its own layoutId via React's `useId()`. Without\n// the per-instance scope, multiple Tabs mounted on the same page share the\n// same shared layout group, which makes the indicator chase the most recent\n// re-mount (visually it \"disappears\" or jumps between tabs). The id is\n// forwarded into the indicator's `layoutId` so the animation is bounded.\nfunction TabButton({\n item,\n state,\n indicatorLayoutId,\n}: {\n item: any;\n state: any;\n indicatorLayoutId: string;\n}) {\n const ref = useRef<HTMLDivElement>(null);\n const { tabProps } = useTab({ key: item.key }, state, ref);\n const isSelected = state.selectedKey === item.key;\n const isDisabled = state.disabledKeys.has(item.key);\n\n // When a tab becomes selected (pointer OR keyboard), bring it fully into\n // view in the horizontally-scrollable strip — clicking a half-clipped or\n // last tab previously left it partly hidden behind the overflow edge.\n // `inline: \"nearest\"` no-ops when the tab is already fully visible, and\n // `block: \"nearest\"` keeps it from scrolling the surrounding page.\n useEffect(() => {\n // `scrollIntoView` is absent in jsdom (tests) — optional-chain the method\n // so the effect is a safe no-op there and in any non-DOM environment.\n if (isSelected) {\n ref.current?.scrollIntoView?.({ block: \"nearest\", inline: \"nearest\" });\n }\n }, [isSelected]);\n\n // Remove motion-conflicting props\n const { onDrag, onDragStart, onDragEnd, onAnimationStart, ...safeTabProps } = tabProps as any;\n\n return (\n <motion.div\n {...safeTabProps}\n ref={ref}\n className={cn(\n \"ods-tabs__tab\",\n isSelected && \"ods-tabs__tab--selected\",\n isDisabled && \"ods-tabs__tab--disabled\",\n )}\n >\n {item.rendered}\n {isSelected && (\n <motion.div\n className={\"ods-tabs__indicator\"}\n layoutId={indicatorLayoutId}\n transition={{ type: \"spring\", damping: 30, stiffness: 400 }}\n />\n )}\n </motion.div>\n );\n}\n\nfunction TabPanelContent({ state, panelContent, ...props }: any) {\n const ref = useRef<HTMLDivElement>(null);\n const { tabPanelProps } = useTabPanel(props, state, ref);\n return (\n <div {...tabPanelProps} ref={ref} className={\"ods-tabs__panel\"}>\n {panelContent}\n </div>\n );\n}\n\n// Threshold below which we consider the strip \"fully scrolled\" — covers\n// fractional pixel rounding so chevrons hide cleanly at the ends.\nconst SCROLL_EDGE_EPSILON = 1;\n// Step size for the chevron buttons. ~200 px clears two or three average\n// tabs without overshooting on narrow strips.\nconst SCROLL_STEP_PX = 200;\n\nexport function Tabs({\n items,\n value,\n defaultValue,\n onChange,\n orientation = \"horizontal\",\n className,\n}: TabsProps) {\n const reactId = useId();\n const indicatorLayoutId = `ods-tabs-indicator-${reactId}`;\n const [internalValue, setInternalValue] = useState(defaultValue || items[0]?.value);\n const selectedKey = value ?? internalValue;\n\n const handleSelectionChange = (key: any) => {\n const keyStr = String(key);\n if (!value) setInternalValue(keyStr);\n onChange?.(keyStr);\n };\n\n // Build a map of value -> panel content\n const panelContentMap = useMemo(() => {\n const map = new Map<string, ReactNode>();\n items.forEach((item) => {\n map.set(item.value, item.children);\n });\n return map;\n }, [items]);\n\n const stateProps: TabListStateOptions<any> = {\n children: items.map((item) => (\n <Item key={item.value} textValue={item.label}>\n {item.icon && <span className={\"ods-tabs__icon\"}>{item.icon}</span>}\n <span>{item.label}</span>\n </Item>\n )),\n selectedKey,\n onSelectionChange: handleSelectionChange,\n disabledKeys: items.filter((i) => i.disabled).map((i) => i.value),\n };\n\n const state = useTabListState(stateProps);\n const ref = useRef<HTMLDivElement>(null);\n const { tabListProps } = useTabList({ ...stateProps, orientation }, state, ref);\n\n // ── Horizontal-overflow scroll ────────────────────────────────────────\n // When the tab strip is wider than its viewport (typical when the host\n // pins it inside a narrow column), we surface left/right chevron\n // buttons that programmatically scroll the strip. The native scrollbar\n // is hidden via SCSS so the chevrons remain the only affordance.\n //\n // We only enable the overflow chrome for horizontal orientation; the\n // vertical layout already scrolls naturally via the parent overflow.\n const scrollContainerRef = useRef<HTMLDivElement>(null);\n const [canScrollLeft, setCanScrollLeft] = useState(false);\n const [canScrollRight, setCanScrollRight] = useState(false);\n\n const measureOverflow = useCallback(() => {\n const el = scrollContainerRef.current;\n if (!el || orientation !== \"horizontal\") {\n setCanScrollLeft(false);\n setCanScrollRight(false);\n return;\n }\n const max = el.scrollWidth - el.clientWidth;\n setCanScrollLeft(el.scrollLeft > SCROLL_EDGE_EPSILON);\n setCanScrollRight(el.scrollLeft < max - SCROLL_EDGE_EPSILON);\n }, [orientation]);\n\n // Recompute on mount + when items change. The ResizeObserver covers the\n // case where the container itself resizes (responsive parent layouts).\n useEffect(() => {\n measureOverflow();\n const el = scrollContainerRef.current;\n if (!el || typeof ResizeObserver === \"undefined\") return;\n const ro = new ResizeObserver(() => measureOverflow());\n ro.observe(el);\n return () => ro.disconnect();\n }, [items, measureOverflow]);\n\n const onScroll = () => measureOverflow();\n\n const scrollBy = (dir: -1 | 1) => {\n const el = scrollContainerRef.current;\n if (!el) return;\n el.scrollBy({ left: dir * SCROLL_STEP_PX, behavior: \"smooth\" });\n };\n\n const currentPanelContent = panelContentMap.get(String(selectedKey));\n\n return (\n <div className={cn(\"ods-tabs\", `ods-tabs--${orientation}`, className)}>\n <div className=\"ods-tabs__list-wrap\">\n {orientation === \"horizontal\" && canScrollLeft && (\n <button\n type=\"button\"\n className=\"ods-tabs__scroll-btn ods-tabs__scroll-btn--left\"\n onClick={() => scrollBy(-1)}\n aria-label=\"Scroll tabs left\"\n tabIndex={-1}\n >\n <ChevronSvg dir=\"left\" />\n </button>\n )}\n <div\n className=\"ods-tabs__scroller\"\n ref={scrollContainerRef}\n onScroll={orientation === \"horizontal\" ? onScroll : undefined}\n >\n <div {...tabListProps} ref={ref} className={\"ods-tabs__list\"}>\n {[...state.collection].map((item) => (\n <TabButton\n key={item.key}\n item={item}\n state={state}\n indicatorLayoutId={indicatorLayoutId}\n />\n ))}\n </div>\n </div>\n {orientation === \"horizontal\" && canScrollRight && (\n <button\n type=\"button\"\n className=\"ods-tabs__scroll-btn ods-tabs__scroll-btn--right\"\n onClick={() => scrollBy(1)}\n aria-label=\"Scroll tabs right\"\n tabIndex={-1}\n >\n <ChevronSvg dir=\"right\" />\n </button>\n )}\n </div>\n <TabPanelContent key={state.selectedKey} state={state} panelContent={currentPanelContent} />\n </div>\n );\n}\n\nfunction ChevronSvg({ dir }: { dir: \"left\" | \"right\" }) {\n // Inline chevron; rotates via CSS-friendly `d` so we don't need to ship\n // an icon dep just for the scroll chrome.\n const d = dir === \"left\" ? \"M11 4L5 10l6 6\" : \"M9 4l6 6-6 6\";\n return (\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 20 20\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.8\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d={d} />\n </svg>\n );\n}\n","// ════════════════════════════════════════════════════════════════════════\n// Change reducers — apply node/edge change arrays in one immutable pass.\n// ════════════════════════════════════════════════════════════════════════\n// Consumers in controlled mode write:\n//\n// <FlowCanvas\n// nodes={nodes}\n// edges={edges}\n// onNodesChange={(changes) => setNodes((ns) => applyNodeChanges(ns, changes))}\n// onEdgesChange={(changes) => setEdges((es) => applyEdgeChanges(es, changes))}\n// />\n//\n// The helpers run in O(n + m) where n is the existing list and m the\n// change count, with one shallow clone per touched item. Add / remove\n// short-circuit when the array is unchanged, so React's reconciler\n// happily reuses references.\n\nimport type { EdgeChange, NodeChange, WorkflowEdge, WorkflowNode } from \"../editor\";\n\n/**\n * Apply a batch of node changes to an existing node list. Returns a\n * **new array** if anything changed, the **same array** otherwise (so\n * React.memo'd children don't re-render unnecessarily).\n */\nexport function applyNodeChanges<TData = unknown>(\n nodes: WorkflowNode<TData>[],\n changes: NodeChange<TData>[],\n): WorkflowNode<TData>[] {\n if (changes.length === 0) return nodes;\n\n // Bucket changes by id for O(1) lookup during the single map pass.\n const byId = new Map<string, NodeChange<TData>[]>();\n const adds: WorkflowNode<TData>[] = [];\n const removes = new Set<string>();\n let touched = false;\n\n for (const change of changes) {\n switch (change.type) {\n case \"add\":\n adds.push(change.item);\n touched = true;\n break;\n case \"remove\":\n removes.add(change.id);\n touched = true;\n break;\n default: {\n const id = change.id;\n const arr = byId.get(id);\n if (arr) arr.push(change);\n else byId.set(id, [change]);\n touched = true;\n break;\n }\n }\n }\n\n if (!touched) return nodes;\n\n const next: WorkflowNode<TData>[] = [];\n for (const node of nodes) {\n if (removes.has(node.id)) continue;\n const patches = byId.get(node.id);\n if (!patches) {\n next.push(node);\n continue;\n }\n let n: WorkflowNode<TData> = node;\n for (const patch of patches) {\n switch (patch.type) {\n case \"position\":\n n = {\n ...n,\n position: patch.position,\n dragging: patch.dragging,\n };\n break;\n case \"dimensions\":\n n = {\n ...n,\n width: patch.dimensions.width,\n height: patch.dimensions.height,\n };\n break;\n case \"select\":\n // Skip if already in the target state — keeps reference stable.\n if (n.selected === patch.selected) break;\n n = { ...n, selected: patch.selected };\n break;\n case \"replace\":\n n = patch.item;\n break;\n }\n }\n next.push(n);\n }\n\n // Adds go to the end. Parents must precede children (caller's\n // responsibility; we don't reorder mid-application because that would\n // make `replace` unpredictable when a child already exists).\n for (const add of adds) next.push(add);\n\n return next;\n}\n\n/**\n * Apply a batch of edge changes. Same shape as `applyNodeChanges`.\n */\nexport function applyEdgeChanges<TData = unknown>(\n edges: WorkflowEdge<TData>[],\n changes: EdgeChange<TData>[],\n): WorkflowEdge<TData>[] {\n if (changes.length === 0) return edges;\n\n const byId = new Map<string, EdgeChange<TData>[]>();\n const adds: WorkflowEdge<TData>[] = [];\n const removes = new Set<string>();\n let touched = false;\n\n for (const change of changes) {\n switch (change.type) {\n case \"add\":\n adds.push(change.item);\n touched = true;\n break;\n case \"remove\":\n removes.add(change.id);\n touched = true;\n break;\n default: {\n const arr = byId.get(change.id);\n if (arr) arr.push(change);\n else byId.set(change.id, [change]);\n touched = true;\n break;\n }\n }\n }\n\n if (!touched) return edges;\n\n const next: WorkflowEdge<TData>[] = [];\n for (const edge of edges) {\n if (removes.has(edge.id)) continue;\n const patches = byId.get(edge.id);\n if (!patches) {\n next.push(edge);\n continue;\n }\n let e: WorkflowEdge<TData> = edge;\n for (const patch of patches) {\n switch (patch.type) {\n case \"select\":\n if (e.selected === patch.selected) break;\n e = { ...e, selected: patch.selected };\n break;\n case \"replace\":\n e = patch.item;\n break;\n }\n }\n next.push(e);\n }\n\n for (const add of adds) next.push(add);\n return next;\n}\n\n// ── Convenience builders ────────────────────────────────────────────────\n// Used by the store / hooks internally. Public consumers usually let the\n// canvas emit changes; these are handy for tests + custom interactions.\n\nexport const change = {\n node: {\n add<TData>(item: WorkflowNode<TData>): NodeChange<TData> {\n return { type: \"add\", item };\n },\n remove<TData>(id: string): NodeChange<TData> {\n return { type: \"remove\", id };\n },\n position<TData>(\n id: string,\n position: { x: number; y: number },\n dragging: boolean,\n ): NodeChange<TData> {\n return { type: \"position\", id, position, dragging };\n },\n dimensions<TData>(\n id: string,\n dimensions: { width: number; height: number },\n ): NodeChange<TData> {\n return { type: \"dimensions\", id, dimensions };\n },\n select<TData>(id: string, selected: boolean): NodeChange<TData> {\n return { type: \"select\", id, selected };\n },\n replace<TData>(id: string, item: WorkflowNode<TData>): NodeChange<TData> {\n return { type: \"replace\", id, item };\n },\n },\n edge: {\n add<TData>(item: WorkflowEdge<TData>): EdgeChange<TData> {\n return { type: \"add\", item };\n },\n remove<TData>(id: string): EdgeChange<TData> {\n return { type: \"remove\", id };\n },\n select<TData>(id: string, selected: boolean): EdgeChange<TData> {\n return { type: \"select\", id, selected };\n },\n replace<TData>(id: string, item: WorkflowEdge<TData>): EdgeChange<TData> {\n return { type: \"replace\", id, item };\n },\n },\n};\n","// ════════════════════════════════════════════════════════════════════════\n// Parenting helpers — descendant traversal, extent clamping, descendant\n// position recompute. Used by FlowCanvas's drag middleware to keep\n// subflow semantics consistent.\n// ════════════════════════════════════════════════════════════════════════\n\nimport type { NodeKind, Position, WorkflowNode } from \"../editor\";\nimport { DEFAULT_NODE_WIDTH, effectiveHeight } from \"./geometry\";\n\n/**\n * Node types that behave as containers — subflow frames whose children nest\n * via `parentId` and render inside the frame.\n *\n * `forEach` is intentionally NOT a container. The DS renders it as a SIMPLE\n * node (1 input on top, Each / Done outputs on the bottom) whose loop body is\n * wired by EDGES, not nested by `parentId` (see ForEachNode). Treating it as\n * a container let drag-to-reparent adopt nodes INTO a forEach; the host then\n * silently dropped those \"children\" on save because its wire contract has no\n * forEach-children concept — real data loss (DEV-200). Keep this list in sync\n * with the kinds that actually render a child-hosting frame.\n */\nexport const CONTAINER_NODE_TYPES: readonly NodeKind[] = [\"group\"];\n\n/** True when a node type hosts nested children via `parentId`. */\nexport function isContainerType(type: NodeKind | undefined): boolean {\n return type !== undefined && CONTAINER_NODE_TYPES.includes(type);\n}\n\n/**\n * Returns the transitive descendants of a node — i.e. every node whose\n * `parentId` chain ends at `nodeId`. Stable order (DFS). The root node\n * is NOT included.\n */\nexport function descendantsOf(nodeId: string, nodes: WorkflowNode[]): WorkflowNode[] {\n const childrenByParent = new Map<string, WorkflowNode[]>();\n for (const n of nodes) {\n if (!n.parentId) continue;\n const arr = childrenByParent.get(n.parentId);\n if (arr) arr.push(n);\n else childrenByParent.set(n.parentId, [n]);\n }\n const out: WorkflowNode[] = [];\n const stack = [nodeId];\n // Guard against malformed cycles (a → b → a) which can sneak in via\n // hand-crafted fixtures. Without this the walk is unbounded.\n const visited = new Set<string>([nodeId]);\n while (stack.length) {\n const cur = stack.pop();\n if (cur === undefined) break;\n const list = childrenByParent.get(cur);\n if (!list) continue;\n for (const c of list) {\n if (visited.has(c.id)) continue;\n visited.add(c.id);\n out.push(c);\n stack.push(c.id);\n }\n }\n return out;\n}\n\n/**\n * Walk up the parent chain. Returns the first ancestor that satisfies\n * `predicate`, or undefined.\n */\nexport function findAncestor(\n node: WorkflowNode,\n nodes: WorkflowNode[],\n predicate: (n: WorkflowNode) => boolean,\n): WorkflowNode | undefined {\n let cursor: WorkflowNode | undefined = node;\n const seen = new Set<string>();\n while (cursor?.parentId) {\n if (seen.has(cursor.parentId)) return undefined; // cycle guard\n seen.add(cursor.parentId);\n const parent = nodes.find((n) => n.id === cursor!.parentId);\n if (!parent) return undefined;\n if (predicate(parent)) return parent;\n cursor = parent;\n }\n return undefined;\n}\n\n/**\n * Clamp a proposed child position to its parent's bounding box. The\n * child is kept fully inside the parent — child's bottom-right corner\n * cannot exceed the parent's bottom-right.\n *\n * Returns the original position if the node has no parent or extent\n * isn't `'parent'`.\n */\nexport function clampToParentExtent(\n node: WorkflowNode,\n proposed: Position,\n nodes: WorkflowNode[],\n): Position {\n if (node.extent !== \"parent\" || !node.parentId) return proposed;\n const parent = nodes.find((n) => n.id === node.parentId);\n if (!parent) return proposed;\n const pw = parent.width ?? DEFAULT_NODE_WIDTH;\n const ph = effectiveHeight(parent);\n const w = node.width ?? DEFAULT_NODE_WIDTH;\n const h = effectiveHeight(node);\n const minX = parent.position.x;\n const minY = parent.position.y;\n const maxX = parent.position.x + pw - w;\n const maxY = parent.position.y + ph - h;\n return {\n x: Math.max(minX, Math.min(maxX, proposed.x)),\n y: Math.max(minY, Math.min(maxY, proposed.y)),\n };\n}\n\n/**\n * Hit-test which container node (if any) contains the given point. Used by\n * drag-to-reparent and drop-to-add to scope a node. Only `group` is a\n * container (see `isContainerType` — `forEach` is a simple node).\n *\n * When containers overlap or nest, the SMALLEST-area container under the\n * point wins. That's the most specific / deepest-nested frame, and it\n * matches the host's own drop hit-test (which picked the deepest container).\n * The previous \"last in array order\" rule disagreed with the host, so a drag\n * and a drop over the same nested groups could adopt into different parents\n * (DEV-200).\n */\nexport function findContainingGroup(\n point: Position,\n nodes: WorkflowNode[],\n exclude: string[] = [],\n): WorkflowNode | undefined {\n let best: WorkflowNode | undefined;\n let bestArea = Number.POSITIVE_INFINITY;\n for (const n of nodes) {\n if (exclude.includes(n.id)) continue;\n if (!isContainerType(n.type)) continue;\n if (n.data && typeof n.data === \"object\" && (n.data as { collapsed?: boolean }).collapsed) {\n continue;\n }\n const w = n.width ?? DEFAULT_NODE_WIDTH;\n const h = effectiveHeight(n);\n if (\n point.x >= n.position.x &&\n point.y >= n.position.y &&\n point.x <= n.position.x + w &&\n point.y <= n.position.y + h\n ) {\n const area = w * h;\n if (area < bestArea) {\n best = n;\n bestArea = area;\n }\n }\n }\n return best;\n}\n","\"use client\";\n\n// ════════════════════════════════════════════════════════════════════════\n// FlowEdge v2 — port-aware path, four routing modes, editable label.\n// ════════════════════════════════════════════════════════════════════════\n// Routing modes: bezier (default), step, smoothstep, straight.\n// Semantic types: default / conditional / loop / error — drive stroke\n// colour and dash pattern, orthogonal to routing.\n//\n// Label + delete chrome are stacked vertically at the midpoint so they\n// don't overlap. Double-clicking the label opens an inline editor;\n// changes commit via `onLabelChange`.\n\nimport {\n memo,\n type KeyboardEvent as ReactKeyboardEvent,\n useEffect,\n useId,\n useRef,\n useState,\n} from \"react\";\nimport { cn } from \"../../../utils/cn\";\nimport type { EdgeKind, WorkflowEdge as WorkflowEdgeType, WorkflowNode } from \"../../editor\";\nimport { handleCentre } from \"../../utils/geometry\";\nimport { buildEdgePath, type EdgeRouting } from \"../../utils/paths\";\nimport { useHandleRegistry } from \"../Handle/handleRegistry\";\n\nexport interface FlowEdgeProps {\n edge: WorkflowEdgeType;\n nodes: WorkflowNode[];\n onSelect?: (id: string) => void;\n onDelete?: (id: string) => void;\n /** Commit a label edit. When omitted, double-click is a no-op. */\n onLabelChange?: (id: string, label: string) => void;\n /** Show the X delete affordance at the midpoint on hover/select. */\n showDelete?: boolean;\n /** Curvature for bezier routing (0–1). Smaller = tighter. Default 0.25. */\n curvature?: number;\n /** Corner radius for smoothstep routing. Default 8 px. */\n borderRadius?: number;\n /**\n * Bust-cache token from FlowCanvas. Bumps whenever the handle registry\n * mutates so this edge re-renders against fresh handle descriptors —\n * fixes stale geometry after collapse/uncollapse of a subflow whose\n * children mount their Handles in a follow-up effect tick.\n */\n handleVersion?: number;\n}\n\nfunction FlowEdgeImpl({\n edge,\n nodes,\n onSelect,\n onDelete,\n onLabelChange,\n showDelete = true,\n curvature = 0.25,\n borderRadius = 8,\n}: FlowEdgeProps) {\n const uid = useId();\n const markerId = `ods-flow-edge-arrow-${uid.replace(/:/g, \"\")}`;\n const registry = useHandleRegistry();\n const [hovered, setHovered] = useState(false);\n const [editing, setEditing] = useState(false);\n const [draftLabel, setDraftLabel] = useState<string>(edge.label ?? \"\");\n const inputRef = useRef<HTMLInputElement>(null);\n\n // Sync the draft when the edge's label changes externally (e.g. after a\n // commit). The local state survives blur/Enter cleanly.\n useEffect(() => {\n if (!editing) setDraftLabel(edge.label ?? \"\");\n }, [edge.label, editing]);\n\n const sourceNode = nodes.find((n) => n.id === edge.source);\n const targetNode = nodes.find((n) => n.id === edge.target);\n\n if (!sourceNode || !targetNode) return null;\n\n // Compute on every render — handle registrations may arrive after the\n // first paint, and the math is cheap.\n const sourceHandleId = edge.sourceHandle ?? \"default\";\n const targetHandleId = edge.targetHandle ?? \"default\";\n const sourceDesc = registry.resolve(sourceNode.id, \"source\", sourceHandleId);\n const targetDesc = registry.resolve(targetNode.id, \"target\", targetHandleId);\n const sourceSide = sourceDesc?.side ?? sourceNode.sourcePosition ?? \"bottom\";\n const targetSide = targetDesc?.side ?? targetNode.targetPosition ?? \"top\";\n // The handle dot's physical edge (`side`) places the endpoint; the\n // `routeSide` decides which way the curve leaves/enters it. They differ\n // for a subflow's inner-facing ports — a dot on the frame's `top` edge\n // whose wire must curve `down` into the frame.\n const sourceRoute = sourceDesc?.routeSide ?? sourceSide;\n const targetRoute = targetDesc?.routeSide ?? targetSide;\n const sourceIndex = sourceDesc?.index ?? 0;\n const sourceTotal = sourceDesc?.total ?? 1;\n const targetIndex = targetDesc?.index ?? 0;\n const targetTotal = targetDesc?.total ?? 1;\n const rawStart = handleCentre(sourceNode, sourceSide, sourceIndex, sourceTotal);\n const rawEnd = handleCentre(targetNode, targetSide, targetIndex, targetTotal);\n // Pull the visible path back from each handle dot a few pixels so\n // the arrowhead lands ON the port circle (overlapping its centre)\n // rather than floating in space above it. The hitbox path still\n // uses the raw points so the click hit area extends right up to\n // the dot. Port circle is 12 px / radius 6; a 2 px pull-back puts\n // the arrow's visual tip at the port centre.\n const HANDLE_GAP = 2;\n const start = offsetAlongSide(rawStart, sourceRoute, HANDLE_GAP);\n const end = offsetAlongSide(rawEnd, targetRoute, HANDLE_GAP);\n const routing: EdgeRouting = edge.routing ?? \"bezier\";\n const { d, midX, midY } = buildEdgePath(routing, start, sourceRoute, end, targetRoute, {\n curvature,\n borderRadius,\n });\n const { d: hitD } = buildEdgePath(routing, rawStart, sourceRoute, rawEnd, targetRoute, {\n curvature,\n borderRadius,\n });\n\n const type: EdgeKind = edge.type ?? \"default\";\n const isHot = hovered || edge.selected;\n const stroke =\n type === \"error\"\n ? \"var(--ods-status-failed, #dc2626)\"\n : isHot\n ? \"var(--ods-accent, #4f46e5)\"\n : \"var(--ods-border-strong, #6b7280)\";\n // Explicit `edge.style.strokeDasharray` wins over the type's default —\n // this is what `collapseFor` uses to render boundary edges (sparse-dotted)\n // so the user sees they're a \"summary\" rather than a real connection.\n const typeDash = type === \"conditional\" ? \"6 4\" : type === \"loop\" ? \"4 4\" : undefined;\n const dash = edge.style?.strokeDasharray ?? typeDash;\n const strokeWidth = edge.style?.strokeWidth ?? (isHot ? 2 : 1.4);\n const animateDash = edge.animated === true;\n const label = edge.label;\n const hasDelete = showDelete && (isHot || edge.selected) && !!onDelete;\n\n // Lay label + delete affordance side by side at the midpoint:\n //\n // ┌─────────┐ ⓧ ← inline chrome, both on midY\n // │ label │\n // └─────────┘\n //\n // The foreignObject sits on the bezier's midpoint and holds a flex row\n // that centres its children horizontally. Either child may be absent;\n // remaining child stays centred.\n const showChrome = !!label || editing || hasDelete;\n\n const commitLabel = (next: string) => {\n setEditing(false);\n if (next !== edge.label) onLabelChange?.(edge.id, next);\n };\n\n const onLabelKey = (e: ReactKeyboardEvent<HTMLInputElement>) => {\n if (e.key === \"Enter\") {\n e.preventDefault();\n commitLabel(draftLabel);\n } else if (e.key === \"Escape\") {\n e.preventDefault();\n setEditing(false);\n setDraftLabel(edge.label ?? \"\");\n }\n };\n\n return (\n <g\n className={cn(\n \"ods-flow-edge-v2\",\n `ods-flow-edge-v2--${type}`,\n `ods-flow-edge-v2--routing-${routing}`,\n edge.selected && \"ods-flow-edge-v2--selected\",\n hovered && \"ods-flow-edge-v2--hovered\",\n edge.className,\n )}\n data-edge-id={edge.id}\n data-edge-routing={routing}\n onMouseEnter={() => setHovered(true)}\n onMouseLeave={() => setHovered(false)}\n onClick={(e) => {\n e.stopPropagation();\n onSelect?.(edge.id);\n }}\n onDoubleClick={(e) => {\n // Double-clicking anywhere on the edge opens the label editor —\n // this is the only way to ADD a description to an edge that\n // doesn't have one yet (the label chip only renders once a\n // label exists, so there'd otherwise be nothing to double-click).\n if (!onLabelChange) return;\n e.stopPropagation();\n setDraftLabel(edge.label ?? \"\");\n setEditing(true);\n }}\n >\n <defs>\n <marker\n id={markerId}\n viewBox=\"0 0 10 10\"\n refX=\"9\"\n refY=\"5\"\n markerWidth=\"7\"\n markerHeight=\"7\"\n orient=\"auto-start-reverse\"\n >\n <path d=\"M0 0L10 5L0 10z\" fill={stroke} />\n </marker>\n </defs>\n\n {/* Hitbox — wider stroke than the visible path so the edge is easy\n to click even when zoomed out or routed with sharp corners. Uses\n the un-shortened path so the click target reaches the port. */}\n <path d={hitD} stroke=\"transparent\" strokeWidth={20} fill=\"none\" />\n\n {/* Visible path. */}\n <path\n d={d}\n stroke={stroke}\n strokeWidth={strokeWidth}\n strokeDasharray={dash}\n fill=\"none\"\n markerEnd={`url(#${markerId})`}\n style={\n animateDash\n ? {\n strokeDasharray: dash ?? \"6 4\",\n animation: \"ods-flow-edge-flow 0.6s linear infinite\",\n }\n : undefined\n }\n />\n\n {showChrome && (\n <foreignObject\n x={midX - 140}\n y={midY - 16}\n width={280}\n height={32}\n style={{ overflow: \"visible\", pointerEvents: \"none\" }}\n >\n <div className=\"ods-flow-edge-v2__chrome\">\n {(label || editing) &&\n (editing ? (\n <input\n ref={inputRef}\n className=\"ods-flow-edge-v2__label-input\"\n value={draftLabel}\n autoFocus\n onChange={(e) => setDraftLabel(e.target.value)}\n onBlur={() => commitLabel(draftLabel)}\n onKeyDown={onLabelKey}\n onClick={(e) => e.stopPropagation()}\n onMouseDown={(e) => e.stopPropagation()}\n aria-label=\"Edit edge label\"\n />\n ) : (\n <button\n type=\"button\"\n className=\"ods-flow-edge-v2__label-chip\"\n onDoubleClick={(e) => {\n if (!onLabelChange) return;\n e.stopPropagation();\n setDraftLabel(edge.label ?? \"\");\n setEditing(true);\n }}\n onClick={(e) => {\n e.stopPropagation();\n onSelect?.(edge.id);\n }}\n title={onLabelChange ? \"Double-click to edit\" : undefined}\n tabIndex={onLabelChange ? 0 : -1}\n >\n <span>{label}</span>\n </button>\n ))}\n\n {hasDelete && (\n <button\n type=\"button\"\n className=\"ods-flow-edge-v2__delete-btn\"\n onClick={(e) => {\n e.stopPropagation();\n onDelete?.(edge.id);\n }}\n aria-label=\"Delete edge\"\n >\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" aria-hidden=\"true\">\n <path\n d=\"M2 2l6 6M8 2l-6 6\"\n stroke=\"currentColor\"\n strokeWidth={1.5}\n strokeLinecap=\"round\"\n />\n </svg>\n </button>\n )}\n </div>\n </foreignObject>\n )}\n </g>\n );\n}\n\n/**\n * Pull a handle anchor point inward by `gap` px along the side it sits\n * on. Used to leave space between the arrowhead and the open-circle\n * port — the path stops just outside the dot so the arrow stays visible.\n *\n * \"top\" → end is at the node's top edge, pull it UP (smaller y)\n * \"bottom\" → pull DOWN (larger y)\n * \"left\" → pull LEFT (smaller x)\n * \"right\" → pull RIGHT (larger x)\n */\nfunction offsetAlongSide(\n p: { x: number; y: number },\n side: \"top\" | \"right\" | \"bottom\" | \"left\",\n gap: number,\n): { x: number; y: number } {\n switch (side) {\n case \"top\":\n return { x: p.x, y: p.y - gap };\n case \"bottom\":\n return { x: p.x, y: p.y + gap };\n case \"left\":\n return { x: p.x - gap, y: p.y };\n case \"right\":\n return { x: p.x + gap, y: p.y };\n }\n}\n\nexport const FlowEdge = memo(FlowEdgeImpl, (prev, next) => {\n if (prev.edge !== next.edge) return false;\n if (prev.onSelect !== next.onSelect || prev.onDelete !== next.onDelete) return false;\n if (prev.onLabelChange !== next.onLabelChange) return false;\n if (prev.showDelete !== next.showDelete) return false;\n if (prev.curvature !== next.curvature || prev.borderRadius !== next.borderRadius) return false;\n // Bust the cache when the handle registry mutates — otherwise edges\n // referring to handles that mount in a follow-up effect tick (e.g.\n // children inside a subflow that just un-collapsed) freeze at the\n // first-render-with-stale-registry geometry.\n if (prev.handleVersion !== next.handleVersion) return false;\n const ps = prev.nodes.find((n) => n.id === prev.edge.source);\n const pt = prev.nodes.find((n) => n.id === prev.edge.target);\n const ns = next.nodes.find((n) => n.id === next.edge.source);\n const nt = next.nodes.find((n) => n.id === next.edge.target);\n if (ps !== ns || pt !== nt) return false;\n return true;\n});\n","// ════════════════════════════════════════════════════════════════════════\n// Per-canvas handle registry — Edge components look up handle positions\n// via this registry so they don't need to thread DOM refs around.\n// ════════════════════════════════════════════════════════════════════════\n// The Handle component registers itself on mount with its (nodeId,\n// handleId, type, side, index, total) tuple. FlowEdge derives the absolute\n// flow-space centre via `handleCentre()` using `node.position +\n// node.dimensions + side + index/total`.\n//\n// Keys are `(nodeId, type, handleId)` — note the `type`! Input and\n// output handles can legitimately share an id (the default is `\"default\"`\n// for both), and the type disambiguates. Without this, a node with one\n// input + one output (both with id `\"default\"`) would collide and edges\n// would resolve the wrong side.\n\nimport { createContext, useContext } from \"react\";\nimport type { HandlePosition, HandleType } from \"../../editor\";\n\nexport interface HandleDescriptor {\n nodeId: string;\n handleId: string;\n type: HandleType;\n /** Physical edge the handle dot sits on — drives placement + the\n * handle's flow-space centre. */\n side: HandlePosition;\n /**\n * Edge-routing direction. The bezier leaves/enters along THIS side,\n * which is normally the same as `side`. A subflow's inner-facing port\n * sits on the frame's outer edge (`side`) but must route INWARD — e.g.\n * a port physically on `top` whose wire should curve `down` into the\n * frame sets `routeSide: \"bottom\"`. Defaults to `side`.\n */\n routeSide: HandlePosition;\n /** 0-based position among same-(node, side, type) handles. */\n index: number;\n /** Total handles on the same (node, side, type). */\n total: number;\n /** May this handle START a connection? Defaults true. */\n canStart: boolean;\n /** May this handle END a connection? Defaults true. */\n canEnd: boolean;\n}\n\nexport interface HandleRegistry {\n register(d: HandleDescriptor): () => void;\n resolve(nodeId: string, type: HandleType, handleId: string): HandleDescriptor | undefined;\n /** Every currently-registered handle. Used by the connection drag to\n * resolve a drop target geometrically (nearest handle within snap\n * radius) rather than relying on DOM hit-testing, which is fragile\n * against z-index / pointer-events / overlapping subflow frames. */\n all(): HandleDescriptor[];\n /**\n * Subscribe to registry mutations. Fires after every register /\n * unregister so listeners (typically the EdgesLayer) can re-render\n * once the new handles are present. Without this, edges resolved\n * during the same React commit as a node remount fall back to default\n * positions because the Handle's `useEffect` hasn't yet written its\n * descriptor — which is what caused the post-collapse stale-edge bug\n * inside subflows.\n */\n subscribe(listener: () => void): () => void;\n}\n\nexport const HandleRegistryContext = createContext<HandleRegistry | null>(null);\n\nexport function useHandleRegistry(): HandleRegistry {\n const r = useContext(HandleRegistryContext);\n if (!r) {\n throw new Error(\"[@octaviaflow/core/workflow] Handle must be used inside <FlowCanvas>.\");\n }\n return r;\n}\n\n/**\n * Build a registry. One per FlowCanvas instance.\n */\nexport function createHandleRegistry(): HandleRegistry {\n const map = new Map<string, HandleDescriptor>();\n const key = (n: string, t: HandleType, h: string) => `${n}::${t}::${h}`;\n const listeners = new Set<() => void>();\n const notify = () => {\n for (const l of listeners) l();\n };\n return {\n register(d) {\n map.set(key(d.nodeId, d.type, d.handleId), d);\n notify();\n return () => {\n // Only delete if our descriptor is still the registered one — guards\n // against races when a node unmounts a Handle and immediately\n // remounts it with the same id during a quick re-render.\n const k = key(d.nodeId, d.type, d.handleId);\n if (map.get(k) === d) {\n map.delete(k);\n notify();\n }\n };\n },\n resolve(nodeId, type, handleId) {\n return map.get(key(nodeId, type, handleId));\n },\n all() {\n return Array.from(map.values());\n },\n subscribe(listener) {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n };\n}\n","\"use client\";\n\n// ════════════════════════════════════════════════════════════════════════\n// FlowNodeContext — descendants of a node (Handle, NodeToolbar, …) read\n// the node id and basic state through this context.\n// ════════════════════════════════════════════════════════════════════════\n\nimport { createContext, useContext } from \"react\";\nimport type { WorkflowNode } from \"../../editor\";\n\nexport interface FlowNodeContextValue {\n id: string;\n node: WorkflowNode;\n selected: boolean;\n}\n\nexport const FlowNodeContext = createContext<FlowNodeContextValue | null>(null);\n\nexport function useFlowNodeContext(): FlowNodeContextValue {\n const v = useContext(FlowNodeContext);\n if (!v) {\n throw new Error(\n \"[@octaviaflow/core/workflow] Handle / NodeToolbar must be inside a node renderer.\",\n );\n }\n return v;\n}\n","\"use client\";\n\n// ════════════════════════════════════════════════════════════════════════\n// FlowNode — wrapper for any node in the v2 editor.\n// ════════════════════════════════════════════════════════════════════════\n// Responsibilities:\n// 1. Position itself absolutely at `node.position` (in flow space).\n// 2. Provide FlowNodeContext so descendants (Handle, NodeToolbar) know\n// which node they live in.\n// 3. Begin drag on pointerdown (the canvas-level pointermove takes over).\n// 4. Begin selection on click.\n// 5. Dispatch to the kind component for the actual chrome.\n//\n// The wrapper does NOT subscribe to its own selected state via the store;\n// instead the parent NodesLayer passes the resolved `selected` flag down\n// — keeps re-render fan-out predictable.\n\nimport { type PointerEvent, useEffect, useMemo, useRef } from \"react\";\nimport { cn } from \"../../../utils/cn\";\nimport type { WorkflowNode } from \"../../editor\";\nimport { useFlowNodeBridge } from \"../FlowCanvas/FlowCanvasContext\";\nimport { FlowNodeContext, type FlowNodeContextValue } from \"./FlowNodeContext\";\nimport type { NodeKindComponent } from \"./nodeKinds\";\n\nexport interface FlowNodeProps {\n node: WorkflowNode;\n selected: boolean;\n dragging: boolean;\n isConnecting: boolean;\n Kind: NodeKindComponent;\n /** Optional fallback width for un-measured nodes — defaults to 240. */\n defaultWidth?: number;\n}\n\nexport function FlowNode({\n node,\n selected,\n dragging,\n isConnecting,\n Kind,\n // Match the BaseNode body's fixed 368 px width so the wrapper bbox and\n // the rendered card line up on the first paint — before the\n // ResizeObserver has had a chance to write back the measured size.\n // Container kinds (group / forEach) opt out by setting `node.width`.\n defaultWidth = 368,\n}: FlowNodeProps) {\n const bridge = useFlowNodeBridge();\n const wrapperRef = useRef<HTMLDivElement>(null);\n\n // ── ResizeObserver — feed real dimensions back through onNodesChange so\n // edges can compute endpoints against the actual rendered footprint.\n // Without this, every node looks 96px tall to the edge layer and arrows\n // land mid-air below tall nodes.\n //\n // Container kinds (`group`, `forEach`) are EXEMPT. Why: when a group is\n // collapsed its rendered height shrinks to 36px; if we measure that the\n // 36px gets written back into `node.height` and the group never restores\n // its expanded height on un-collapse. Container size is consumer-driven\n // (set explicitly via `node.width` / `node.height`) — no measurement.\n useEffect(() => {\n const el = wrapperRef.current;\n if (!el || typeof ResizeObserver === \"undefined\") return;\n if (node.type === \"group\" || node.type === \"forEach\") return;\n const ro = new ResizeObserver(() => {\n // `offsetWidth/Height` are un-affected by ancestor CSS transforms\n // (the canvas viewport applies `scale(zoom)`). `getBoundingClientRect`\n // would scale with zoom and give us wildly wrong values when zoomed\n // in/out.\n bridge.reportDimensions(node.id, el.offsetWidth, el.offsetHeight);\n });\n ro.observe(el);\n return () => ro.disconnect();\n }, [bridge, node.id, node.type]);\n\n const ctx = useMemo<FlowNodeContextValue>(\n () => ({ id: node.id, node, selected }),\n [node, selected],\n );\n\n // Track pointerdown coordinates so we can decide post-pointerup whether\n // this was a click or a drag. DOM fires `click` after a drag too, which\n // would otherwise re-open the config panel when the user only moved the\n // node. 5 px matches the platform's canvas `paneClickDistance` default.\n const downPosRef = useRef<{ x: number; y: number } | null>(null);\n const draggedRef = useRef(false);\n const CLICK_VS_DRAG_PX = 5;\n\n const handlePointerDown = (e: PointerEvent<HTMLDivElement>) => {\n // Only the primary (left) button starts a node drag. A right/middle\n // press must fall through to the context menu (and not stopPropagation),\n // so it can't begin a drag or collapse the selection (DEV-206).\n if (e.button !== 0) return;\n // Skip drag if the pointerdown originated on a handle — that gesture\n // is owned by the connect middleware.\n if ((e.target as HTMLElement).closest(\"[data-handle-id]\")) return;\n // Skip drag inside opt-out regions (allows form controls inside nodes).\n if ((e.target as HTMLElement).closest(\"[data-flow-no-drag='true']\")) return;\n e.stopPropagation();\n downPosRef.current = { x: e.clientX, y: e.clientY };\n draggedRef.current = false;\n // Pass through altKey — the canvas's drag middleware uses it for\n // Alt-detach (drop out of a parent group, or rebind into a new one).\n bridge.beginNodeDrag(node.id, e.pointerId, e.clientX, e.clientY, e.altKey);\n };\n\n const handlePointerMove = (e: PointerEvent<HTMLDivElement>) => {\n const start = downPosRef.current;\n if (!start || draggedRef.current) return;\n if (\n Math.abs(e.clientX - start.x) > CLICK_VS_DRAG_PX ||\n Math.abs(e.clientY - start.y) > CLICK_VS_DRAG_PX\n ) {\n draggedRef.current = true;\n }\n };\n\n const handleClick = (e: PointerEvent<HTMLDivElement>) => {\n if ((e.target as HTMLElement).closest(\"[data-handle-id]\")) return;\n e.stopPropagation();\n // Click that arrives after a drag is a synthetic side-effect — DO NOT\n // re-fire selection or notify the consumer (would re-open the panel\n // they were trying to keep on the original node).\n if (draggedRef.current) {\n draggedRef.current = false;\n downPosRef.current = null;\n return;\n }\n downPosRef.current = null;\n // Selection state was already updated at pointerdown by beginNodeDrag.\n // Here we re-assert it (handles meta-key toggle on already-selected\n // nodes) and ALSO notify the consumer of the click — which `selectNode`\n // intentionally no longer does on its own.\n bridge.selectNode(node.id, e.metaKey || e.ctrlKey || e.shiftKey);\n bridge.notifyNodeClick(node.id);\n };\n\n return (\n <div\n ref={wrapperRef}\n data-node-id={node.id}\n data-node-type={node.type}\n data-node-selected={selected ? \"true\" : \"false\"}\n className={cn(\n \"ods-flow-node-v2\",\n `ods-flow-node-v2--kind-${node.type}`,\n selected && \"ods-flow-node-v2--selected\",\n dragging && \"ods-flow-node-v2--dragging\",\n isConnecting && \"ods-flow-node-v2--connecting\",\n node.className,\n )}\n style={{\n position: \"absolute\",\n left: node.position.x,\n top: node.position.y,\n width: node.width ?? defaultWidth,\n // Z-stack (per architecture doc): groups (20) sit below normal\n // nodes (30) so children render visually on top of their parent\n // frame. Selection raises by 10. Consumer override wins.\n zIndex:\n node.zIndex ??\n (selected ? (node.type === \"group\" ? 35 : 40) : node.type === \"group\" ? 20 : 30),\n ...node.style,\n }}\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n onClick={handleClick}\n >\n <FlowNodeContext.Provider value={ctx}>\n <Kind node={node} selected={selected} dragging={dragging} isConnecting={isConnecting} />\n </FlowNodeContext.Provider>\n </div>\n );\n}\n","\"use client\";\n\n// ════════════════════════════════════════════════════════════════════════\n// FlowCanvasContext — imperative entry points used by Handle + FlowNode.\n// ════════════════════════════════════════════════════════════════════════\n// Each `<FlowCanvas>` creates a private context value containing the\n// callbacks needed by its descendants. We expose these via a \"dispatch\"\n// hook in the spirit of useReducer; the action payload is opaque to\n// descendants — they just know which method to call.\n\nimport { createContext, useContext } from \"react\";\n\nexport interface FlowDispatchAction {\n type: \"connection/start\";\n nodeId: string;\n handleId: string;\n handleType: \"source\" | \"target\";\n pointerId: number;\n clientX: number;\n clientY: number;\n}\n\nexport type FlowDispatch = (action: FlowDispatchAction) => void;\n\nexport const FlowDispatchContext = createContext<FlowDispatch | null>(null);\n\nexport function useFlowDispatch(): FlowDispatch {\n const dispatch = useContext(FlowDispatchContext);\n if (!dispatch) {\n throw new Error(\n \"[@octaviaflow/core/workflow] useFlowDispatch must be called inside <FlowCanvas>.\",\n );\n }\n return dispatch;\n}\n\n/**\n * Internal-only callbacks shared with FlowNode. Not part of the public\n * surface; node renderers use the `useFlowNodeContext` hook instead.\n */\nexport interface FlowNodeBridge {\n beginNodeDrag(\n nodeId: string,\n pointerId: number,\n clientX: number,\n clientY: number,\n altKey?: boolean,\n ): void;\n selectNode(nodeId: string, additive: boolean): void;\n /**\n * Fire the consumer's `onNodeClick` for this node. Split from\n * `selectNode` so drag-start (which selects the node so it carries the\n * selection style) does NOT also fire the click event — otherwise a\n * drag would re-open the config panel.\n */\n notifyNodeClick(nodeId: string): void;\n selectEdge(edgeId: string, additive: boolean): void;\n /**\n * Reports measured DOM dimensions back to the canvas. FlowNode observes\n * itself via ResizeObserver and calls this on size changes. The canvas\n * de-dupes (skips when w/h unchanged) and emits a `dimensions`\n * NodeChange so edges can recompute against the real footprint.\n */\n reportDimensions(nodeId: string, width: number, height: number): void;\n /** Removes a single node. Edges that reference it are dropped too. */\n deleteNode(nodeId: string): void;\n /**\n * Toggle the `data.collapsed` flag on a group / forEach container.\n * Used by the chevron in the GroupNode / ForEachNode header so the\n * user can expand/collapse the subflow without an external toolbar.\n * No-op for non-container kinds.\n */\n toggleNodeCollapse(nodeId: string): void;\n}\n\nexport const FlowNodeBridgeContext = createContext<FlowNodeBridge | null>(null);\n\nexport function useFlowNodeBridge(): FlowNodeBridge {\n const b = useContext(FlowNodeBridgeContext);\n if (!b) {\n throw new Error(\"[@octaviaflow/core/workflow] FlowNode must be a child of <FlowCanvas>.\");\n }\n return b;\n}\n","// ════════════════════════════════════════════════════════════════════════\n// Node-kind registry — maps a `node.type` string to a React component.\n// ════════════════════════════════════════════════════════════════════════\n// We deliberately avoid the \"pass a `nodeTypes` map prop and pray the\n// caller memoises it\" anti-pattern. The registry is a stable map managed\n// internally; consumers can extend it via `useRegisterNodeKind()` or by\n// passing an override prop that is *frozen* by the canvas the first time\n// it sees it.\n\nimport type { ComponentType } from \"react\";\nimport type { WorkflowNode } from \"../../editor\";\n\n/**\n * Props passed to every kind renderer. Matches the public `NodeProps`\n * shape we expose to consumers; we deliberately do NOT duplicate\n * coordinate fields (see ADR-003).\n */\nexport interface NodeKindProps<TData = unknown> {\n /** The full node — kinds read `data`, can mutate via `updateNodeData`. */\n node: WorkflowNode<TData>;\n /** True when this node is the focus of selection. */\n selected: boolean;\n /** True while a drag is in progress on this node. */\n dragging: boolean;\n /** True when any connection drag is in flight and could end here. */\n isConnecting: boolean;\n}\n\nexport type NodeKindComponent<TData = unknown> = ComponentType<NodeKindProps<TData>>;\n\nexport type NodeKindRegistry = Record<string, NodeKindComponent>;\n\n/**\n * Build a registry from a default set plus optional overrides. The result\n * is a frozen object so consumers can't mutate it post-hoc.\n */\nexport function buildNodeKindRegistry(\n defaults: NodeKindRegistry,\n overrides?: NodeKindRegistry,\n): NodeKindRegistry {\n return Object.freeze({ ...defaults, ...(overrides ?? {}) });\n}\n","\"use client\";\n\n// ════════════════════════════════════════════════════════════════════════\n// Handle — a port primitive that custom node renderers drop in.\n// ════════════════════════════════════════════════════════════════════════\n// Responsibilities:\n// 1. Register its descriptor (nodeId, handleId, type, side, index, total)\n// so edges can resolve its absolute centre.\n// 2. Render a visible dot at the configured side.\n// 3. Initiate connection drags via Pointer Events.\n//\n// The Handle does NOT own pointermove / pointerup — those live on the\n// FlowCanvas-level connect middleware, which sees the gesture all the\n// way through even if the pointer leaves the handle.\n\nimport { type CSSProperties, type PointerEvent, useEffect, useRef } from \"react\";\nimport { cn } from \"../../../utils/cn\";\nimport type { HandlePosition, HandleType } from \"../../editor\";\nimport { useFlowDispatch } from \"../FlowCanvas/FlowCanvasContext\";\nimport { useFlowNodeContext } from \"../FlowNode/FlowNodeContext\";\nimport { useHandleRegistry } from \"./handleRegistry\";\n\nexport interface HandleProps {\n /** `source` = connections start here; `target` = connections end here. */\n type: HandleType;\n /** Which side of the node the handle sits on. */\n position: HandlePosition;\n /**\n * Direction the edge should route from this handle. Defaults to\n * `position`. Override it when the handle dot sits on one edge but the\n * wire must leave/enter from another — e.g. a subflow's inner-facing\n * port lives on the frame's `top` edge yet its wire curves `down` into\n * the frame: `position=\"top\" routeSide=\"bottom\"`.\n */\n routeSide?: HandlePosition;\n /** Stable id within the node. Default `\"default\"`; required when >1 handle of same type. */\n id?: string;\n /** Defaults to true. Setting false disables both starting and ending here. */\n isConnectable?: boolean;\n /** Allow this handle to *start* a connection. Defaults to `isConnectable`. */\n isConnectableStart?: boolean;\n /** Allow this handle to *end* a connection. Defaults to `isConnectable`. */\n isConnectableEnd?: boolean;\n /** 0-based position among same-(node, side) handles. Defaults to 0. */\n index?: number;\n /** Total handles on the same (node, side). Defaults to 1. */\n total?: number;\n /** Optional caption rendered next to the dot (e.g. \"true\"/\"false\"). */\n label?: string;\n className?: string;\n style?: CSSProperties;\n}\n\nconst DEFAULT_HANDLE_ID = \"default\";\n\nexport function Handle({\n type,\n position,\n routeSide,\n id = DEFAULT_HANDLE_ID,\n isConnectable = true,\n isConnectableStart,\n isConnectableEnd,\n index = 0,\n total = 1,\n label,\n className,\n style,\n}: HandleProps) {\n const registry = useHandleRegistry();\n const node = useFlowNodeContext();\n const dispatch = useFlowDispatch();\n const ref = useRef<HTMLDivElement>(null);\n\n const canStart = isConnectableStart ?? isConnectable;\n const canEnd = isConnectableEnd ?? isConnectable;\n\n // Register on every render so changes to side/index/total are visible\n // immediately to edges. The registry de-dupes by (nodeId, handleId).\n useEffect(() => {\n const dispose = registry.register({\n nodeId: node.id,\n handleId: id,\n type,\n side: position,\n routeSide: routeSide ?? position,\n index,\n total,\n canStart,\n canEnd,\n });\n return dispose;\n }, [registry, node.id, id, type, position, routeSide, index, total, canStart, canEnd]);\n\n const handlePointerDown = (e: PointerEvent<HTMLDivElement>) => {\n if (!canStart) return;\n // Only the primary (left) button starts a connection drag (DEV-206).\n if (e.button !== 0) return;\n e.stopPropagation();\n e.preventDefault();\n dispatch({\n type: \"connection/start\",\n nodeId: node.id,\n handleId: id,\n handleType: type,\n pointerId: e.pointerId,\n clientX: e.clientX,\n clientY: e.clientY,\n });\n };\n\n // Pointerup on a Handle is the \"drop on this handle\" gesture. The\n // FlowCanvas-level pointerup also fires; the canvas resolves the target\n // handle by hit-testing `e.target.closest('[data-handle-id]')`.\n return (\n <div\n ref={ref}\n data-handle-id={id}\n data-handle-node-id={node.id}\n data-handle-type={type}\n data-handle-side={position}\n data-handle-connectable-end={canEnd ? \"true\" : \"false\"}\n className={cn(\n \"ods-flow-handle\",\n `ods-flow-handle--${type}`,\n `ods-flow-handle--side-${position}`,\n !isConnectable && \"ods-flow-handle--disabled\",\n className,\n )}\n style={{\n ...handleSideStyle(position, index, total),\n ...style,\n }}\n onPointerDown={handlePointerDown}\n >\n <div className=\"ods-flow-handle__dot\" />\n {label && <span className=\"ods-flow-handle__label\">{label}</span>}\n </div>\n );\n}\n\n// Position the handle along its side. The visual element is small\n// (12 px), so we offset by half its size so the dot's centre lands on\n// the node's edge. Index/total spread multiple handles evenly.\nfunction handleSideStyle(side: HandlePosition, index: number, total: number): CSSProperties {\n const ratio = ((index + 1) / (total + 1)) * 100;\n switch (side) {\n case \"top\":\n return { position: \"absolute\", top: -6, left: `${ratio}%`, transform: \"translateX(-50%)\" };\n case \"bottom\":\n return { position: \"absolute\", bottom: -6, left: `${ratio}%`, transform: \"translateX(-50%)\" };\n case \"left\":\n return { position: \"absolute\", left: -6, top: `${ratio}%`, transform: \"translateY(-50%)\" };\n case \"right\":\n return { position: \"absolute\", right: -6, top: `${ratio}%`, transform: \"translateY(-50%)\" };\n }\n}\n","\"use client\";\n\n// ════════════════════════════════════════════════════════════════════════\n// NodeResizer — drag-to-resize handles attached to a node.\n// ════════════════════════════════════════════════════════════════════════\n// Dropped inside a custom node renderer. Four corner handles each adjust\n// width/height (and, where appropriate, position so the OPPOSITE corner\n// stays pinned). Width/height changes flow back through the imperative\n// instance via `updateNode`.\n//\n// Visible by default only when the host node is selected. Min/max sizes\n// + aspect-ratio lock keep the resize sensible. We deliberately do NOT\n// ship a `shouldResize` veto (yet) — that's a follow-on.\n\nimport { type CSSProperties, type PointerEvent, useRef } from \"react\";\nimport { cn } from \"../../../utils/cn\";\nimport { useFlow } from \"../../hooks/useFlow\";\nimport { useViewport } from \"../../store/selectors\";\nimport { DEFAULT_NODE_HEIGHT, DEFAULT_NODE_WIDTH } from \"../../utils/geometry\";\nimport { useFlowNodeContext } from \"../FlowNode/FlowNodeContext\";\n\nexport interface NodeResizerProps {\n /** Force-visible. Default: visible iff the host node is selected. */\n isVisible?: boolean;\n /** Lower bound for the resize. Defaults to 80×60. */\n minWidth?: number;\n minHeight?: number;\n /** Upper bound for the resize. Defaults unbounded. */\n maxWidth?: number;\n maxHeight?: number;\n /** Lock width:height ratio at the value computed from the node's\n * current dimensions on resize-start. */\n keepAspectRatio?: boolean;\n /** Fired on every pointermove during resize. */\n onResize?: (size: { width: number; height: number }) => void;\n /** Fired on pointerup (the committed size). */\n onResizeEnd?: (size: { width: number; height: number }) => void;\n /** Override handle colour. */\n color?: string;\n}\n\ntype Corner = \"nw\" | \"ne\" | \"sw\" | \"se\";\n\ninterface DragState {\n pointerId: number;\n corner: Corner;\n startClientX: number;\n startClientY: number;\n startWidth: number;\n startHeight: number;\n startX: number;\n startY: number;\n aspect: number; // w / h\n}\n\nexport function NodeResizer({\n isVisible,\n minWidth = 80,\n minHeight = 60,\n maxWidth,\n maxHeight,\n keepAspectRatio = false,\n onResize,\n onResizeEnd,\n color,\n}: NodeResizerProps) {\n const { node, selected } = useFlowNodeContext();\n const viewport = useViewport();\n const flow = useFlow();\n const dragRef = useRef<DragState | null>(null);\n\n const show = isVisible ?? selected;\n if (!show) return null;\n\n const beginResize = (e: PointerEvent<HTMLDivElement>, corner: Corner) => {\n // Only the primary (left) button resizes — a right/middle press must not\n // start a resize gesture (DEV-206).\n if (e.button !== 0) return;\n e.preventDefault();\n e.stopPropagation();\n (e.target as HTMLElement).setPointerCapture(e.pointerId);\n const w = node.width ?? DEFAULT_NODE_WIDTH;\n const h = node.height ?? DEFAULT_NODE_HEIGHT;\n dragRef.current = {\n pointerId: e.pointerId,\n corner,\n startClientX: e.clientX,\n startClientY: e.clientY,\n startWidth: w,\n startHeight: h,\n startX: node.position.x,\n startY: node.position.y,\n aspect: w / Math.max(1, h),\n };\n };\n\n const onMove = (e: PointerEvent<HTMLDivElement>) => {\n const drag = dragRef.current;\n if (!drag || drag.pointerId !== e.pointerId) return;\n const dx = (e.clientX - drag.startClientX) / viewport.zoom;\n const dy = (e.clientY - drag.startClientY) / viewport.zoom;\n // The edges OPPOSITE the dragged corner are anchored — they must not\n // move. Capture them up front so we can re-derive the top-left from the\n // CLAMPED size below. Deriving position from the raw pointer delta made\n // the node slide across the canvas once a corner hit its min/max clamp:\n // the size stopped changing but the position kept tracking the pointer\n // (DEV-206).\n const fixedRight = drag.startX + drag.startWidth;\n const fixedBottom = drag.startY + drag.startHeight;\n let nextW = drag.startWidth;\n let nextH = drag.startHeight;\n switch (drag.corner) {\n case \"se\":\n nextW = drag.startWidth + dx;\n nextH = drag.startHeight + dy;\n break;\n case \"sw\":\n nextW = drag.startWidth - dx;\n nextH = drag.startHeight + dy;\n break;\n case \"ne\":\n nextW = drag.startWidth + dx;\n nextH = drag.startHeight - dy;\n break;\n case \"nw\":\n nextW = drag.startWidth - dx;\n nextH = drag.startHeight - dy;\n break;\n }\n if (keepAspectRatio) {\n // Maintain the original ratio — fit height to width.\n nextH = nextW / drag.aspect;\n }\n nextW = Math.max(minWidth, maxWidth ? Math.min(maxWidth, nextW) : nextW);\n nextH = Math.max(minHeight, maxHeight ? Math.min(maxHeight, nextH) : nextH);\n // Re-derive the top-left from the CLAMPED size so the anchored edges stay\n // put. `se` keeps the top-left fixed; the others anchor the opposite\n // right/bottom edge.\n let nextX = drag.startX;\n let nextY = drag.startY;\n switch (drag.corner) {\n case \"se\":\n break;\n case \"sw\":\n nextX = fixedRight - nextW;\n break;\n case \"ne\":\n nextY = fixedBottom - nextH;\n break;\n case \"nw\":\n nextX = fixedRight - nextW;\n nextY = fixedBottom - nextH;\n break;\n }\n flow.updateNode(node.id, {\n width: nextW,\n height: nextH,\n position: { x: nextX, y: nextY },\n });\n onResize?.({ width: nextW, height: nextH });\n };\n\n const onUp = (e: PointerEvent<HTMLDivElement>) => {\n if (dragRef.current?.pointerId === e.pointerId) {\n const cur = flow.getNode(node.id);\n if (cur) {\n onResizeEnd?.({\n width: cur.width ?? DEFAULT_NODE_WIDTH,\n height: cur.height ?? DEFAULT_NODE_HEIGHT,\n });\n }\n dragRef.current = null;\n }\n };\n\n const handleColor = color ?? \"var(--ods-accent)\";\n const handleStyle = (corner: Corner): CSSProperties => {\n const base: CSSProperties = {\n position: \"absolute\",\n width: 12,\n height: 12,\n background: \"var(--ods-surface-canvas)\",\n border: `2px solid ${handleColor}`,\n borderRadius: 2,\n cursor: cursorFor(corner),\n touchAction: \"none\",\n // Place each handle so its CENTRE sits on the corresponding corner.\n transform: \"translate(-50%, -50%)\",\n };\n switch (corner) {\n case \"nw\":\n return { ...base, top: 0, left: 0 };\n case \"ne\":\n return { ...base, top: 0, left: \"100%\" };\n case \"sw\":\n return { ...base, top: \"100%\", left: 0 };\n case \"se\":\n return { ...base, top: \"100%\", left: \"100%\" };\n }\n };\n\n return (\n <div className={cn(\"ods-node-resizer\")} data-flow-no-drag=\"true\">\n {([\"nw\", \"ne\", \"sw\", \"se\"] as Corner[]).map((corner) => (\n <div\n key={corner}\n style={handleStyle(corner)}\n onPointerDown={(e) => beginResize(e, corner)}\n onPointerMove={onMove}\n onPointerUp={onUp}\n onPointerCancel={onUp}\n aria-label={`Resize ${corner}`}\n />\n ))}\n </div>\n );\n}\n\nfunction cursorFor(corner: Corner): string {\n // Standard 8-direction resize cursors. We only ship corners for v1; the\n // edge handles (n/s/e/w) can come later.\n switch (corner) {\n case \"nw\":\n case \"se\":\n return \"nwse-resize\";\n case \"ne\":\n case \"sw\":\n return \"nesw-resize\";\n }\n}\n","\"use client\";\n\n// ════════════════════════════════════════════════════════════════════════\n// BaseNode — shared chrome for built-in kinds.\n// ════════════════════════════════════════════════════════════════════════\n// Visual structure (mirrors the finalised platform node):\n//\n// ┌─[ KIND ]──────────────────────────────────┐ ← external pill = node TYPE\n// │ ╭──╮ Title (node NAME) │\n// │ │● │ ▸ [CHIP] description-value │ ← chip + value (config-driven)\n// │ ╰──╯ │\n// │ [×] │ ← delete bottom-right\n// └──────────────────────────────────────────[●] ← status top-right\n//\n// The pill is the node TYPE label (e.g. \"HTTP\", \"WEBHOOK\", \"ACTION\") —\n// not the node name. The name lives in the body title. The body's info\n// line takes an optional `chip` (small inline badge) plus a value, which\n// is the canonical pattern for showing the most-relevant config value\n// (HTTP method + path, condition operator + expression, etc.).\n\nimport { TrashCanIcon } from \"@octaviaflow/icons\";\nimport { type ReactNode, useContext } from \"react\";\nimport { cn } from \"../../../utils/cn\";\nimport { FlowNodeBridgeContext } from \"../FlowCanvas/FlowCanvasContext\";\nimport { FlowNodeContext } from \"../FlowNode/FlowNodeContext\";\n\nexport type BaseNodeStatus = \"idle\" | \"running\" | \"success\" | \"error\" | \"warning\";\n\nexport interface BaseNodeProps {\n /** Pill label — the node TYPE/category (e.g. \"HTTP\", \"WEBHOOK\", \"ACTION\"). */\n kind: ReactNode;\n /** Optional small icon inside the pill, left of the kind label. */\n kindIcon?: ReactNode;\n /** Icon shown in the body bubble (32px circle). */\n icon?: ReactNode;\n /** Bold name shown in the body — this is the user-facing instance name. */\n title: ReactNode;\n /**\n * Optional chip rendered before the description text — used for\n * configuration values like HTTP method (\"GET\"), condition operator\n * (\"==\"), execution mode, etc. Inherits the accent colour.\n */\n chip?: ReactNode;\n /**\n * The body description / value — typically the most-relevant config\n * field (path, url, expression). Clamps to two lines.\n */\n description?: ReactNode;\n /**\n * Generic right-aligned chip slot. Renders inside the info row to the\n * right of the description (e.g. an `/v1/orders/:id` path chip next to\n * a `GET` method `chip`). Inherits the kind accent like `chip` does.\n */\n valueChip?: ReactNode;\n /** Per-kind accent — paints the pill background and the chip. */\n accent?: \"blue\" | \"violet\" | \"amber\" | \"green\" | \"red\" | \"slate\";\n /** Status dot in the top-right corner (config / runtime). */\n status?: BaseNodeStatus;\n /**\n * Delete button click — when set, the corner [×] button uses this. If\n * omitted, BaseNode auto-wires it through the FlowCanvas bridge so the\n * default behaviour is \"this button deletes me\". Pass `false` to hide.\n */\n onDelete?: (() => void) | false;\n /** Footer slot below the description (e.g. additional metadata). */\n footer?: ReactNode;\n className?: string;\n /** Handles + extras — positioned absolutely by the caller. */\n children?: ReactNode;\n}\n\nexport function BaseNode({\n kind,\n kindIcon,\n icon,\n title,\n chip,\n description,\n valueChip,\n accent = \"green\",\n status,\n onDelete,\n footer,\n className,\n children,\n}: BaseNodeProps) {\n // Auto-wire delete via the canvas bridge when the kind didn't pass an\n // explicit handler. `onDelete={false}` disables the button entirely.\n const ctx = useContext(FlowNodeContext);\n const bridge = useContext(FlowNodeBridgeContext);\n const deleteHandler: (() => void) | undefined =\n onDelete === false\n ? undefined\n : (onDelete ?? (ctx && bridge ? () => bridge.deleteNode(ctx.id) : undefined));\n return (\n <div\n className={cn(\n \"ods-flow-base-node\",\n `ods-flow-base-node--accent-${accent}`,\n status && `ods-flow-base-node--status-${status}`,\n className,\n )}\n >\n {/* External pill — the node TYPE label, not the name. */}\n <div className=\"ods-flow-base-node__pill\">\n {kindIcon && (\n <span className=\"ods-flow-base-node__pill-icon\" aria-hidden=\"true\">\n {kindIcon}\n </span>\n )}\n <span className=\"ods-flow-base-node__pill-label\">{kind}</span>\n </div>\n\n {/* Status indicator — top-right of the card. */}\n {status && status !== \"idle\" && (\n <span\n className={cn(\"ods-flow-base-node__status\", `ods-flow-base-node__status--${status}`)}\n aria-hidden=\"true\"\n />\n )}\n\n {/* Body */}\n <div className=\"ods-flow-base-node__body\">\n <div className=\"ods-flow-base-node__content\">\n <div className=\"ods-flow-base-node__bubble\" aria-hidden=\"true\">\n {icon}\n </div>\n <div className=\"ods-flow-base-node__content-text\">\n <div className=\"ods-flow-base-node__content-title\">{title}</div>\n {(chip !== undefined || description !== undefined || valueChip !== undefined) && (\n <div className=\"ods-flow-base-node__content-info\">\n {chip !== undefined && <span className=\"ods-flow-base-node__chip\">{chip}</span>}\n {description !== undefined && (\n <span className=\"ods-flow-base-node__description\">{description}</span>\n )}\n {valueChip !== undefined && (\n <span className=\"ods-flow-base-node__value-chip\">{valueChip}</span>\n )}\n </div>\n )}\n </div>\n </div>\n\n {footer && <div className=\"ods-flow-base-node__footer\">{footer}</div>}\n\n {deleteHandler && (\n <button\n type=\"button\"\n className=\"ods-flow-base-node__delete\"\n onClick={(e) => {\n e.stopPropagation();\n deleteHandler();\n }}\n aria-label=\"Delete node\"\n data-flow-no-drag=\"true\"\n title=\"Delete node\"\n >\n <TrashCanIcon size={16} aria-hidden />\n </button>\n )}\n </div>\n\n {/* Handles + extras slot. */}\n {children}\n </div>\n );\n}\n","\"use client\";\n\n// ════════════════════════════════════════════════════════════════════════\n// Built-in node kinds — Action / Trigger / Condition / Group.\n// ════════════════════════════════════════════════════════════════════════\n// Each kind is a small functional component that composes BaseNode and\n// adds its own Handle layout. Additional kinds (Loop, Parallel, Wait,\n// Output, Error, Sticky) will land in a follow-up pass.\n\nimport type { PointerEvent } from \"react\";\nimport { useFlowNodeBridge } from \"../FlowCanvas/FlowCanvasContext\";\nimport type { NodeKindComponent, NodeKindProps, NodeKindRegistry } from \"../FlowNode/nodeKinds\";\nimport { Handle } from \"../Handle/Handle\";\nimport { NodeResizer } from \"../NodeResizer/NodeResizer\";\nimport { BaseNode, type BaseNodeStatus } from \"./BaseNode\";\n\n// Common payload shape that built-in kinds expect. Consumers can extend\n// `data` with their own fields; the renderer just reads the named slots.\nexport interface BuiltInNodeData {\n /** Pill label override — defaults to the kind's canonical type label\n * (e.g. \"HTTP\", \"WEBHOOK\", \"ACTION\"). Rarely needed; mostly here so\n * consumers can rename \"HTTP\" → \"REST\" without forking the kind. */\n kind?: import(\"react\").ReactNode;\n /** Body name — the user-facing instance label (e.g. \"Fetch Order\"). */\n title?: string;\n /**\n * Optional chip rendered before the description value, used for\n * configuration metadata that should read at a glance — HTTP method,\n * condition operator, schedule frequency, etc. Renders as a coloured\n * inline badge that inherits the kind accent.\n */\n chip?: import(\"react\").ReactNode;\n /** Description / config value — the most-relevant config field (path,\n * url, expression). Clamped to two lines in the body. */\n description?: import(\"react\").ReactNode;\n /**\n * Generic right-aligned chip slot — used when a node has a secondary\n * config value to surface (e.g. the path `/v1/orders/:id` next to an\n * HTTP `GET` method chip). Inherits the kind accent.\n */\n valueChip?: import(\"react\").ReactNode;\n /** Legacy alias for `description` — older fixtures still pass this. */\n subtitle?: import(\"react\").ReactNode;\n /** Legacy alias for `chip` — older fixtures still pass this. */\n badge?: import(\"react\").ReactNode;\n /** Runtime status — drives the pulsing dot in the top-right corner. */\n status?: BaseNodeStatus;\n /** Body bubble icon (32px circle). */\n icon?: import(\"react\").ReactNode;\n // Condition-specific:\n branches?: { id: string; label: string }[];\n // Group-specific:\n collapsed?: boolean;\n /** Populated by `collapseFor()` — number of descendants hidden under\n * this collapsed group; the renderer shows it as a \"N steps\" badge. */\n hiddenCount?: number;\n /** Dim the container's frame to signal \"the engine will skip this\n * subflow + all descendants\". Visual only — semantics enforced by\n * the consumer's execution layer. */\n disabled?: boolean;\n // ForEach-specific:\n iterator?: string;\n // Wait-specific (not yet implemented; reserved):\n waitMs?: number;\n // Webhook / HttpRequest-specific helpers — populate `chip` + `description`\n // automatically when present.\n method?: string;\n path?: string;\n url?: string;\n}\n\n// ────────────────────────────────────────────────────────────────────────\n// ActionNode — generic action; 1 input on top + 1 output on bottom.\n// ────────────────────────────────────────────────────────────────────────\nexport const ActionNode: NodeKindComponent<BuiltInNodeData> = ({\n node,\n}: NodeKindProps<BuiltInNodeData>) => {\n const d = node.data ?? {};\n return (\n <BaseNode\n kind={d.kind ?? \"ACTION\"}\n icon={d.icon}\n title={d.title ?? \"Action\"}\n chip={d.chip ?? d.badge}\n description={d.description ?? d.subtitle}\n valueChip={d.valueChip}\n status={d.status}\n accent=\"green\"\n >\n <Handle type=\"target\" position=\"top\" />\n <Handle type=\"source\" position=\"bottom\" />\n </BaseNode>\n );\n};\n\n// ────────────────────────────────────────────────────────────────────────\n// TriggerNode — no input port; green accent matches the platform.\n// ────────────────────────────────────────────────────────────────────────\nexport const TriggerNode: NodeKindComponent<BuiltInNodeData> = ({\n node,\n}: NodeKindProps<BuiltInNodeData>) => {\n const d = node.data ?? {};\n return (\n <BaseNode\n kind={d.kind ?? \"TRIGGER\"}\n icon={d.icon}\n title={d.title ?? \"Trigger\"}\n chip={d.chip}\n description={d.description ?? \"Manually triggered\"}\n valueChip={d.valueChip}\n status={d.status}\n accent=\"green\"\n >\n <Handle type=\"source\" position=\"bottom\" />\n </BaseNode>\n );\n};\n\n// ────────────────────────────────────────────────────────────────────────\n// ConditionNode — single input on top; multiple labelled outputs along\n// the bottom edge. Default branches: true / false.\n// ────────────────────────────────────────────────────────────────────────\nexport const ConditionNode: NodeKindComponent<BuiltInNodeData> = ({\n node,\n}: NodeKindProps<BuiltInNodeData>) => {\n const d = node.data ?? {};\n const branches = d.branches ?? [\n { id: \"true\", label: \"true\" },\n { id: \"false\", label: \"false\" },\n ];\n return (\n <BaseNode\n kind={d.kind ?? \"CONDITION\"}\n icon={d.icon}\n title={d.title ?? \"Condition\"}\n chip={d.chip ?? d.badge}\n description={d.description ?? d.subtitle}\n valueChip={d.valueChip}\n status={d.status}\n accent=\"amber\"\n >\n <Handle type=\"target\" position=\"top\" />\n {branches.map((b, i) => (\n <Handle\n key={b.id}\n type=\"source\"\n position=\"bottom\"\n id={b.id}\n index={i}\n total={branches.length}\n label={b.label}\n />\n ))}\n </BaseNode>\n );\n};\n\n// ────────────────────────────────────────────────────────────────────────\n// GroupNode — frame container for sub-flows. Children render absolutely\n// positioned (per ADR-003) on top of the frame.\n//\n// When `data.collapsed === true`:\n// - Body collapses to the header strip.\n// - Two perimeter handles are registered (`__group_in` on top,\n// `__group_out` on bottom). The `collapseFor()` helper rewrites\n// edges that cross the boundary so they terminate at these handles\n// instead of dangling at hidden children.\n// - A count badge (\"N steps\") is rendered next to the title.\n// ────────────────────────────────────────────────────────────────────────\nexport const GroupNode: NodeKindComponent<BuiltInNodeData> = ({\n node,\n}: NodeKindProps<BuiltInNodeData>) => {\n const d = node.data ?? {};\n const collapsed = !!d.collapsed;\n const disabled = !!d.disabled;\n // The host (or `collapseFor`) reports the descendant count via\n // `node.data.hiddenCount`. We fall back to undefined → no badge.\n const hiddenCount = (d as { hiddenCount?: number }).hiddenCount;\n const bridge = useFlowNodeBridge();\n // The chevron is a button — clicking it (and only it) toggles collapse.\n // We stop propagation so the click doesn't also bubble up to the node\n // wrapper's selection / drag-start gestures. `data-flow-no-drag` keeps\n // pointerdown from starting a node drag.\n const onChevronClick = (e: PointerEvent<HTMLButtonElement>) => {\n e.stopPropagation();\n bridge.toggleNodeCollapse(node.id);\n };\n return (\n <div\n className=\"ods-flow-group\"\n data-collapsed={collapsed ? \"true\" : \"false\"}\n data-disabled={disabled ? \"true\" : undefined}\n style={{\n width: node.width ?? 360,\n height: collapsed ? 36 : (node.height ?? 200),\n }}\n >\n {/* Built-in corner-resize handles. Hidden when collapsed (resize\n a 36px-tall strip makes no sense). Visibility otherwise\n defaults to \"node is selected\" — driven by FlowNodeContext. */}\n {!collapsed && <NodeResizer minWidth={240} minHeight={120} />}\n\n <div className=\"ods-flow-group__header\" data-flow-no-drag=\"false\">\n <button\n type=\"button\"\n className=\"ods-flow-group__chevron\"\n data-flow-no-drag=\"true\"\n aria-label={collapsed ? \"Expand group\" : \"Collapse group\"}\n aria-expanded={!collapsed}\n onClick={onChevronClick}\n onPointerDown={(e) => e.stopPropagation()}\n >\n {collapsed ? \"▸\" : \"▾\"}\n </button>\n <span className=\"ods-flow-group__title\">{d.title ?? \"Group\"}</span>\n {d.subtitle && <span className=\"ods-flow-group__subtitle\">{d.subtitle}</span>}\n {disabled && (\n <span className=\"ods-flow-group__disabled-badge\" aria-label=\"Disabled subflow\">\n Disabled\n </span>\n )}\n {collapsed && hiddenCount !== undefined && hiddenCount > 0 && (\n <span className=\"ods-flow-group__count\" aria-label={`${hiddenCount} hidden steps`}>\n {hiddenCount} steps\n </span>\n )}\n </div>\n\n {/* Canonical perimeter handles — 1 input on top, 1 output on\n bottom. Visible primary interaction surface (was previously\n muted on expanded mode; now they ARE the user-facing ports).\n Ids stay stable for `collapseFor()` edge rewriting. */}\n <Handle type=\"target\" position=\"top\" id=\"__group_in\" />\n <Handle type=\"source\" position=\"bottom\" id=\"__group_out\" />\n </div>\n );\n};\n\n// ────────────────────────────────────────────────────────────────────────\n// ForEachNode — iteration step. A SIMPLE node (NOT a container), shaped\n// like ConditionNode: 1 input on top, 2 labelled outputs on the bottom:\n//\n// - \"Each\" — the loop body; the subgraph wired here runs once per item.\n// - \"Done\" — the post-iteration exit; runs after every item completes.\n//\n// Branch handle ids come from `data.branches` (the consumer's port ids,\n// e.g. `…_output_each` / `…_output_done`) so saved edges anchor exactly;\n// falls back to `each` / `done` when none are supplied. The engine\n// resolves the loop body by following edges from the `…_each` port — no\n// `parentId` nesting, so forEach is a plain node in the chain.\n// ────────────────────────────────────────────────────────────────────────\nexport const ForEachNode: NodeKindComponent<BuiltInNodeData> = ({\n node,\n}: NodeKindProps<BuiltInNodeData>) => {\n const d = node.data ?? {};\n const branches = d.branches ?? [\n { id: \"each\", label: \"Each\" },\n { id: \"done\", label: \"Done\" },\n ];\n return (\n <BaseNode\n kind={d.kind ?? \"FOR EACH\"}\n icon={d.icon}\n title={d.title ?? \"For each\"}\n chip={d.chip ?? d.badge}\n description={d.description ?? d.subtitle ?? d.iterator}\n valueChip={d.valueChip}\n status={d.status}\n accent=\"amber\"\n >\n <Handle type=\"target\" position=\"top\" />\n {branches.map((b, i) => (\n <Handle\n key={b.id}\n type=\"source\"\n position=\"bottom\"\n id={b.id}\n index={i}\n total={branches.length}\n label={b.label}\n />\n ))}\n </BaseNode>\n );\n};\n\n// ────────────────────────────────────────────────────────────────────────\n// OutputNode — terminal node; no output port. Pill reads \"OUTPUT\".\n// ────────────────────────────────────────────────────────────────────────\nexport const OutputNode: NodeKindComponent<BuiltInNodeData> = ({\n node,\n}: NodeKindProps<BuiltInNodeData>) => {\n const d = node.data ?? {};\n return (\n <BaseNode\n kind={d.kind ?? \"OUTPUT\"}\n icon={d.icon}\n title={d.title ?? \"Output\"}\n chip={d.chip ?? d.badge}\n description={d.description ?? d.subtitle}\n status={d.status}\n accent=\"green\"\n >\n <Handle type=\"target\" position=\"top\" />\n </BaseNode>\n );\n};\n\n// ────────────────────────────────────────────────────────────────────────\n// ErrorNode — failure handler; red accent.\n// ────────────────────────────────────────────────────────────────────────\nexport const ErrorNode: NodeKindComponent<BuiltInNodeData> = ({\n node,\n}: NodeKindProps<BuiltInNodeData>) => {\n const d = node.data ?? {};\n return (\n <BaseNode\n kind={d.kind ?? \"ERROR\"}\n icon={d.icon}\n title={d.title ?? \"On error\"}\n chip={d.chip ?? d.badge}\n description={d.description ?? d.subtitle}\n status={d.status ?? \"error\"}\n accent=\"red\"\n >\n <Handle type=\"target\" position=\"top\" />\n <Handle type=\"source\" position=\"bottom\" />\n </BaseNode>\n );\n};\n\n// ────────────────────────────────────────────────────────────────────────\n// WaitNode — pause execution. Chip surfaces the duration when provided.\n// ────────────────────────────────────────────────────────────────────────\nexport const WaitNode: NodeKindComponent<BuiltInNodeData> = ({\n node,\n}: NodeKindProps<BuiltInNodeData>) => {\n const d = node.data ?? {};\n const waitMs = (d as { waitMs?: number }).waitMs;\n const durationChip = waitMs ? `${Math.round(waitMs / 100) / 10}s` : undefined;\n return (\n <BaseNode\n kind={d.kind ?? \"WAIT\"}\n icon={d.icon}\n title={d.title ?? \"Wait\"}\n chip={d.chip ?? durationChip}\n description={d.description ?? (durationChip ? \"Pause execution\" : undefined)}\n status={d.status}\n accent=\"violet\"\n >\n <Handle type=\"target\" position=\"top\" />\n <Handle type=\"source\" position=\"bottom\" />\n </BaseNode>\n );\n};\n\n// ────────────────────────────────────────────────────────────────────────\n// ParallelNode — fan-out: one input, N parallel outputs.\n// ────────────────────────────────────────────────────────────────────────\nexport const ParallelNode: NodeKindComponent<BuiltInNodeData> = ({\n node,\n}: NodeKindProps<BuiltInNodeData>) => {\n const d = node.data ?? {};\n const branches = d.branches ?? [\n { id: \"a\", label: \"a\" },\n { id: \"b\", label: \"b\" },\n ];\n return (\n <BaseNode\n kind={d.kind ?? \"PARALLEL\"}\n icon={d.icon}\n title={d.title ?? \"Parallel\"}\n chip={d.chip ?? `${branches.length}×`}\n description={d.description ?? \"Fan-out branches\"}\n status={d.status}\n accent=\"blue\"\n >\n <Handle type=\"target\" position=\"top\" />\n {branches.map((b, i) => (\n <Handle\n key={b.id}\n type=\"source\"\n position=\"bottom\"\n id={b.id}\n index={i}\n total={branches.length}\n label={b.label}\n />\n ))}\n </BaseNode>\n );\n};\n\n// ────────────────────────────────────────────────────────────────────────\n// StickyNode — non-executing annotation. No ports. Renders behind nodes.\n// Multi-line `data.description` is the body.\n// ────────────────────────────────────────────────────────────────────────\nexport const StickyNode: NodeKindComponent<BuiltInNodeData> = ({\n node,\n}: NodeKindProps<BuiltInNodeData>) => {\n const d = node.data ?? {};\n return (\n <div\n className=\"ods-flow-sticky\"\n style={{\n width: node.width ?? 240,\n minHeight: node.height ?? 120,\n }}\n >\n {d.title && <div className=\"ods-flow-sticky__title\">{d.title}</div>}\n {d.description && <div className=\"ods-flow-sticky__body\">{d.description}</div>}\n </div>\n );\n};\n\n// ────────────────────────────────────────────────────────────────────────\n// WebhookNode — specialised Trigger. Pill = \"WEBHOOK\"; chip = HTTP\n// method; description = path (the most-relevant config value).\n// ────────────────────────────────────────────────────────────────────────\nexport const WebhookNode: NodeKindComponent<BuiltInNodeData> = ({\n node,\n}: NodeKindProps<BuiltInNodeData>) => {\n const d = node.data ?? {};\n return (\n <BaseNode\n kind={d.kind ?? \"WEBHOOK\"}\n icon={d.icon}\n title={d.title ?? \"Webhook\"}\n chip={d.chip ?? d.method ?? \"POST\"}\n description={d.description ?? d.path ?? \"/hooks/incoming\"}\n valueChip={d.valueChip}\n status={d.status}\n accent=\"blue\"\n >\n <Handle type=\"source\" position=\"bottom\" />\n </BaseNode>\n );\n};\n\n// ────────────────────────────────────────────────────────────────────────\n// HttpRequestNode — Action variant. Pill = \"HTTP\"; chip = HTTP method;\n// description = url (the most-relevant config value).\n// ────────────────────────────────────────────────────────────────────────\nexport const HttpRequestNode: NodeKindComponent<BuiltInNodeData> = ({\n node,\n}: NodeKindProps<BuiltInNodeData>) => {\n const d = node.data ?? {};\n return (\n <BaseNode\n kind={d.kind ?? \"HTTP\"}\n icon={d.icon}\n title={d.title ?? \"HTTP Request\"}\n chip={d.chip ?? d.method ?? \"GET\"}\n description={d.description ?? d.url ?? \"Call an API\"}\n valueChip={d.valueChip}\n status={d.status}\n accent=\"blue\"\n >\n <Handle type=\"target\" position=\"top\" />\n <Handle type=\"source\" position=\"bottom\" />\n </BaseNode>\n );\n};\n\n// ────────────────────────────────────────────────────────────────────────\n// Default registry — the canvas merges this with any consumer overrides.\n// ────────────────────────────────────────────────────────────────────────\nexport const DEFAULT_NODE_KINDS: NodeKindRegistry = {\n action: ActionNode as NodeKindComponent,\n trigger: TriggerNode as NodeKindComponent,\n condition: ConditionNode as NodeKindComponent,\n group: GroupNode as NodeKindComponent,\n forEach: ForEachNode as NodeKindComponent,\n output: OutputNode as NodeKindComponent,\n error: ErrorNode as NodeKindComponent,\n wait: WaitNode as NodeKindComponent,\n parallel: ParallelNode as NodeKindComponent,\n sticky: StickyNode as NodeKindComponent,\n webhook: WebhookNode as NodeKindComponent,\n httpRequest: HttpRequestNode as NodeKindComponent,\n};\n","\"use client\";\n\n// ════════════════════════════════════════════════════════════════════════\n// FlowCanvas v2 — the editor kernel.\n// ════════════════════════════════════════════════════════════════════════\n// Responsibilities:\n// 1. Mount the per-canvas store + handle registry; provide their contexts.\n// 2. Render the viewport (transform: translate(x,y) scale(zoom)).\n// 3. Own Pointer Events for pan, zoom, drag, and connect; route to the\n// right middleware via a single pointermove handler installed on the\n// window during an active gesture.\n// 4. Emit batched onNodesChange / onEdgesChange / onConnect / ...\n// 5. Mirror controlled `nodes` / `edges` props into the store each render\n// so descendants read fresh data via selectors.\n\nimport {\n type CSSProperties,\n memo,\n type PointerEvent,\n type ReactNode,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n type WheelEvent,\n} from \"react\";\nimport { cn } from \"../../../utils/cn\";\nimport type {\n ConnectEndState,\n Connection,\n ConnectStartParams,\n EdgeChange,\n NodeChange,\n Position,\n Viewport,\n WorkflowEdge,\n WorkflowNode,\n} from \"../../editor\";\nimport { type FlowInstance, FlowInstanceContext } from \"../../hooks/useFlow\";\nimport { change } from \"../../store/changes\";\nimport { FlowStoreContext } from \"../../store/context\";\nimport { createFlowStore } from \"../../store/createFlowStore\";\nimport { resolveNodeCollisions } from \"../../utils/collision\";\nimport {\n DEFAULT_NODE_HEIGHT,\n DEFAULT_NODE_WIDTH,\n effectiveHeight,\n flowToScreen,\n handleCentre,\n screenToFlow,\n} from \"../../utils/geometry\";\nimport {\n clampToParentExtent,\n descendantsOf,\n findContainingGroup,\n isContainerType,\n} from \"../../utils/parenting\";\nimport { FlowEdge } from \"../FlowEdge/FlowEdge\";\nimport { FlowNode } from \"../FlowNode/FlowNode\";\nimport { buildNodeKindRegistry, type NodeKindRegistry } from \"../FlowNode/nodeKinds\";\nimport {\n createHandleRegistry,\n type HandleDescriptor,\n HandleRegistryContext,\n} from \"../Handle/handleRegistry\";\nimport { type BuiltInNodeData, DEFAULT_NODE_KINDS } from \"../kinds\";\nimport {\n type FlowDispatch,\n type FlowDispatchAction,\n FlowDispatchContext,\n type FlowNodeBridge,\n FlowNodeBridgeContext,\n} from \"./FlowCanvasContext\";\n\nexport interface FlowCanvasProps {\n nodes: WorkflowNode[];\n edges: WorkflowEdge[];\n onNodesChange?: (changes: NodeChange[]) => void;\n onEdgesChange?: (changes: EdgeChange[]) => void;\n\n // Viewport\n viewport?: Viewport;\n defaultViewport?: Viewport;\n onViewportChange?: (viewport: Viewport) => void;\n minZoom?: number;\n maxZoom?: number;\n /**\n * Auto-frame the existing nodes on first mount so the canvas opens\n * centered on content rather than at the {0,0,1} origin. Defaults to\n * `true` when no explicit `viewport` or `defaultViewport` is supplied;\n * when the consumer pins either prop the canvas honours that and skips\n * the auto-fit. Pass `false` to opt out unconditionally. Pass\n * `{ padding, minZoom, maxZoom }` to tune the framing.\n */\n fitViewOnInit?: boolean | { padding?: number; minZoom?: number; maxZoom?: number };\n\n // Node kinds\n nodeKinds?: NodeKindRegistry;\n\n // Connection\n onConnect?: (connection: Connection) => void;\n onConnectStart?: (\n event: PointerEvent | globalThis.PointerEvent,\n params: ConnectStartParams,\n ) => void;\n onConnectEnd?: (event: PointerEvent | globalThis.PointerEvent, state: ConnectEndState) => void;\n isValidConnection?: (connection: Connection) => boolean;\n\n // Selection\n onSelectionChange?: (selection: { nodes: WorkflowNode[]; edges: WorkflowEdge[] }) => void;\n onPaneClick?: () => void;\n onNodeClick?: (node: WorkflowNode) => void;\n onEdgeClick?: (edge: WorkflowEdge) => void;\n /** Double-clicking an edge label opens an inline editor; commit fires\n * this callback. When omitted, labels are not editable. */\n onEdgeLabelChange?: (id: string, label: string) => void;\n /** Fires once when the canvas mounts. Hand-off for the imperative\n * instance — consumers store it to call `fitView`, `addNodes`, etc. */\n onInit?: (instance: FlowInstance) => void;\n /** Async veto for deletions. Return `false` (or a Promise resolving\n * false) to block. Fires from `instance.deleteElements`, Backspace,\n * and the edge X button. */\n onBeforeDelete?: (params: {\n nodes: WorkflowNode[];\n edges: WorkflowEdge[];\n }) => boolean | Promise<boolean>;\n /** Right-click on a node. Consumer must `preventDefault()` to suppress\n * the browser's native menu. */\n onNodeContextMenu?: (event: React.MouseEvent, node: WorkflowNode) => void;\n /** Right-click on an edge. */\n onEdgeContextMenu?: (event: React.MouseEvent, edge: WorkflowEdge) => void;\n /** Right-click on the empty pane. */\n onPaneContextMenu?: (event: React.MouseEvent) => void;\n\n // Policies\n nodesDraggable?: boolean;\n nodesConnectable?: boolean;\n panOnDrag?: boolean;\n zoomOnScroll?: boolean;\n /**\n * Trackpad / touch behaviour preset.\n *\n * - `\"mouse\"` (default): mouse-first. Drag the pane to pan;\n * wheel zooms; pinch zooms.\n * - `\"trackpad\"`: two-finger trackpad scroll pans; pinch zooms;\n * wheel-with-Ctrl zooms. Drag the pane is still pan (`panOnDrag`).\n * - `\"touch\"`: same as trackpad but with enlarged hit areas (44 px\n * on coarse pointers via `@media (pointer: coarse)`) and no pan\n * on plain drag — single-finger drag selects, two-finger pans.\n *\n * Override individual policies (`panOnDrag`, `zoomOnScroll`, etc.)\n * after picking a preset to fine-tune.\n */\n preset?: \"mouse\" | \"trackpad\" | \"touch\";\n /** Pixels of pointer travel during a pane-press before it stops counting\n * as a click (used to decide whether to clear selection on pointerup). */\n paneClickDistance?: number;\n /**\n * Whether a click on the empty canvas pane clears the current node /\n * edge selection. Defaults to `true` (the design-tool standard:\n * \"click background to deselect\"). Set to `false` when selection\n * should persist through pane clicks — e.g. when a side ConfigPanel\n * stays open until the user dismisses it explicitly.\n *\n * `onPaneClick` still fires regardless; this only controls whether\n * the canvas also clears its internal selection state.\n */\n paneClickClearsSelection?: boolean;\n\n // Visual canvas options\n /** Background grid style. Defaults to `\"dots\"`. */\n background?: \"dots\" | \"lines\" | \"cross\" | \"none\";\n /** Grid pitch in flow-space pixels. Defaults to 20. Also used for snap. */\n gridSize?: number;\n /** Snap node positions to the grid on drag-end. Defaults to false. */\n snapToGrid?: boolean;\n /**\n * Minimum gap (px) between sibling nodes during drag. When >= 0, a\n * dragged node is \"magnet snapped\" so it stays at least `nodeCollisionGap`\n * pixels from every other sibling — siblings share the same `parentId`\n * (or are both top-level). `0` means \"no overlap allowed, zero buffer.\"\n * Pass `-1` (the default) to disable collision avoidance entirely.\n */\n nodeCollisionGap?: number;\n /**\n * Same as `nodeCollisionGap` but applied to subflow containers\n * (`isContainerType` — i.e. `group`; `forEach` is a simple node). Lets you\n * keep groups visually separated without applying the rule to the action\n * nodes inside. Default falls back to `nodeCollisionGap`.\n */\n subflowCollisionGap?: number;\n\n /**\n * When `true`, dragging a node into another container's bbox sets\n * the dragged node's `parentId`; dragging out clears it — without\n * requiring the Alt modifier key. Default `false` preserves the\n * legacy Alt-drag-to-reparent behaviour for backward compatibility.\n *\n * Pairs with `autoResizeContainers` to deliver the full \"drop nodes\n * inside a group\" UX consumers usually want from a subflow editor.\n */\n reparentOnDrag?: boolean;\n\n /**\n * When `true`, container kinds (`group` / `forEach`) auto-resize at\n * drag-end so the frame encloses all current children plus padding.\n * The reposition + dimension update is folded into the same\n * `onNodesChange` call as the drag-end position change, so a child\n * dropped near the edge of a container can't miss the parent's\n * post-resize bbox in a follow-up render tick (the host-side race\n * the parented-on-drop UX would otherwise hit).\n *\n * Default `false`. Pair with `reparentOnDrag` for the full flow.\n */\n autoResizeContainers?: boolean;\n\n /**\n * Padding (in flow-space pixels) added around children's bbox when\n * `autoResizeContainers` recomputes a container's frame. Default 32.\n */\n containerAutoResizePadding?: number;\n\n /**\n * Floor size for `autoResizeContainers`. A container that fits its\n * children in less than this stops shrinking here — it never collapses\n * below the size a freshly-dropped (empty) container would have.\n * Defaults: 320 × 200.\n */\n containerMinWidth?: number;\n containerMinHeight?: number;\n\n // Layout\n height?: number | string;\n width?: number | string;\n className?: string;\n style?: CSSProperties;\n children?: ReactNode;\n emptyState?: ReactNode;\n}\n\nconst DEFAULT_VIEWPORT: Viewport = { x: 0, y: 0, zoom: 1 };\n\nexport function FlowCanvas(props: FlowCanvasProps) {\n // Capture whether the consumer explicitly handed us either viewport\n // prop. We can't tell from the destructured value alone (the default\n // assignment below would obscure an undefined explicit pass), and the\n // auto-fit fallback needs to know \"did the consumer pin the viewport,\n // or are we free to frame the nodes?\".\n const viewportPropProvided = props.viewport !== undefined || props.defaultViewport !== undefined;\n const {\n nodes,\n edges,\n onNodesChange,\n onEdgesChange,\n viewport: controlledViewport,\n defaultViewport = DEFAULT_VIEWPORT,\n onViewportChange,\n minZoom = 0.25,\n maxZoom = 2,\n fitViewOnInit,\n nodeKinds,\n onConnect,\n onConnectStart,\n onConnectEnd,\n isValidConnection,\n onSelectionChange,\n onPaneClick,\n onNodeClick,\n onEdgeClick,\n onEdgeLabelChange,\n onInit,\n onBeforeDelete,\n onNodeContextMenu,\n onEdgeContextMenu,\n onPaneContextMenu,\n nodesDraggable = true,\n nodesConnectable = true,\n panOnDrag: panOnDragProp,\n zoomOnScroll: zoomOnScrollProp,\n preset = \"mouse\",\n paneClickDistance = 4,\n paneClickClearsSelection = true,\n background = \"dots\",\n gridSize = 20,\n snapToGrid = false,\n nodeCollisionGap = -1,\n subflowCollisionGap,\n reparentOnDrag = false,\n autoResizeContainers = false,\n containerAutoResizePadding = 32,\n containerMinWidth = 320,\n containerMinHeight = 200,\n height = \"100%\",\n width = \"100%\",\n className,\n style,\n children,\n emptyState,\n } = props;\n // Resolve the preset defaults — individual props override. The presets\n // map to the documented interaction modes:\n // - mouse: pan-on-drag, wheel zoom\n // - trackpad: pan-on-drag still on (so users can grab the pane), but\n // two-finger trackpad scroll also pans (translated as wheel delta);\n // pinch zooms; wheel-zoom remains on for Ctrl+scroll.\n // - touch: drag the pane = box-select intent, no auto-pan\n // (single-finger drag is reserved for selection on touch surfaces).\n const presetDefaults = {\n mouse: { panOnDrag: true, zoomOnScroll: true },\n trackpad: { panOnDrag: true, zoomOnScroll: true },\n touch: { panOnDrag: false, zoomOnScroll: true },\n } as const;\n const panOnDrag = panOnDragProp ?? presetDefaults[preset].panOnDrag;\n const zoomOnScroll = zoomOnScrollProp ?? presetDefaults[preset].zoomOnScroll;\n\n // ── Singletons that live for the lifetime of this canvas ──\n const store = useState(() =>\n createFlowStore({\n initialNodes: nodes,\n initialEdges: edges,\n initialViewport: controlledViewport ?? defaultViewport,\n }),\n )[0];\n const handleRegistry = useState(() => createHandleRegistry())[0];\n\n // Subscribe to handle (un)registrations. Each Handle's `useEffect`\n // commits AFTER the surrounding render, so edges rendered in the same\n // commit as a node remount (typical for subflow collapse/uncollapse)\n // resolve against a stale registry and fall back to default ports.\n // Bumping this counter forces a follow-up render once the effects fire.\n const [handleVersion, setHandleVersion] = useState(0);\n useEffect(() => {\n const unsub = handleRegistry.subscribe(() => {\n setHandleVersion((v) => v + 1);\n });\n return unsub;\n }, [handleRegistry]);\n\n // Merge built-in kinds with consumer overrides. Frozen so consumers\n // can't mutate the registry mid-flight.\n const kinds = useMemo(() => buildNodeKindRegistry(DEFAULT_NODE_KINDS, nodeKinds), [nodeKinds]);\n\n const containerRef = useRef<HTMLDivElement>(null);\n\n // ── Mirror controlled props → store ───────────────────────────────────\n useEffect(() => store.setNodes(nodes), [store, nodes]);\n useEffect(() => store.setEdges(edges), [store, edges]);\n\n // ── Viewport (controlled or uncontrolled) ─────────────────────────────\n const [uncontrolledVp, setUncontrolledVp] = useState(controlledViewport ?? defaultViewport);\n const viewport = controlledViewport ?? uncontrolledVp;\n useEffect(() => store.setViewport(viewport), [store, viewport]);\n const setViewport = useCallback(\n (next: Viewport) => {\n if (controlledViewport === undefined) setUncontrolledVp(next);\n onViewportChange?.(next);\n },\n [controlledViewport, onViewportChange],\n );\n\n // ── Selection — derived from `node.selected` / `edge.selected` in props.\n // We do NOT keep a parallel ref because that would drift the moment a\n // consumer set a node.selected = true via their own state. The single\n // source of truth is the props.\n const selectedNodeIds = useMemo(() => {\n const s = new Set<string>();\n for (const n of nodes) if (n.selected) s.add(n.id);\n return s;\n }, [nodes]);\n const selectedEdgeIds = useMemo(() => {\n const s = new Set<string>();\n for (const e of edges) if (e.selected) s.add(e.id);\n return s;\n }, [edges]);\n\n // Sync resolved selection into the store so descendants can read it.\n useEffect(() => {\n store.setSelection(selectedNodeIds, selectedEdgeIds);\n if (onSelectionChange) {\n onSelectionChange({\n nodes: nodes.filter((n) => selectedNodeIds.has(n.id)),\n edges: edges.filter((e) => selectedEdgeIds.has(e.id)),\n });\n }\n }, [store, selectedNodeIds, selectedEdgeIds, nodes, edges, onSelectionChange]);\n\n // Selection state only — does NOT fire `onNodeClick`. The click event\n // is dispatched separately from the click path in FlowNode, so drag\n // starts (which need to select the node so it carries selection styles)\n // don't accidentally fire the consumer's click handler.\n const selectNode = useCallback(\n (id: string, additive: boolean) => {\n const next: NodeChange[] = [];\n const nextEdges: EdgeChange[] = [];\n if (!additive) {\n for (const n of nodes) {\n if (n.selected && n.id !== id) next.push(change.node.select(n.id, false));\n }\n for (const e of edges) {\n if (e.selected) nextEdges.push(change.edge.select(e.id, false));\n }\n }\n const isSelected = selectedNodeIds.has(id);\n if (additive && isSelected) {\n // Toggle off when meta-clicking an already-selected node.\n next.push(change.node.select(id, false));\n } else if (!isSelected) {\n next.push(change.node.select(id, true));\n }\n if (next.length) onNodesChange?.(next);\n if (nextEdges.length) onEdgesChange?.(nextEdges);\n },\n [nodes, edges, selectedNodeIds, onNodesChange, onEdgesChange],\n );\n\n // Click notification — fires the consumer's `onNodeClick`. FlowNode\n // calls this AFTER `selectNode` only when the gesture was a click,\n // not a drag. Separating the two lets drag-start update selection\n // without firing the click event.\n const notifyNodeClick = useCallback(\n (id: string) => {\n const node = nodes.find((n) => n.id === id);\n if (node) onNodeClick?.(node);\n },\n [nodes, onNodeClick],\n );\n\n const selectEdge = useCallback(\n (id: string, additive: boolean) => {\n const next: EdgeChange[] = [];\n const nextNodes: NodeChange[] = [];\n if (!additive) {\n for (const e of edges) {\n if (e.selected && e.id !== id) next.push(change.edge.select(e.id, false));\n }\n for (const n of nodes) {\n if (n.selected) nextNodes.push(change.node.select(n.id, false));\n }\n }\n const isSelected = selectedEdgeIds.has(id);\n if (additive && isSelected) {\n next.push(change.edge.select(id, false));\n } else if (!isSelected) {\n next.push(change.edge.select(id, true));\n }\n if (next.length) onEdgesChange?.(next);\n if (nextNodes.length) onNodesChange?.(nextNodes);\n const edge = edges.find((e) => e.id === id);\n if (edge) onEdgeClick?.(edge);\n },\n [nodes, edges, selectedEdgeIds, onEdgesChange, onNodesChange, onEdgeClick],\n );\n\n const clearSelection = useCallback(() => {\n const ns: NodeChange[] = [];\n const es: EdgeChange[] = [];\n for (const n of nodes) if (n.selected) ns.push(change.node.select(n.id, false));\n for (const e of edges) if (e.selected) es.push(change.edge.select(e.id, false));\n if (ns.length) onNodesChange?.(ns);\n if (es.length) onEdgesChange?.(es);\n }, [nodes, edges, onNodesChange, onEdgesChange]);\n\n // ── Node drag middleware ──────────────────────────────────────────────\n // Drag also moves transitive descendants (children of a parent move with\n // the parent), respects `extent: 'parent'` clamping, and supports\n // Alt-detach for re-parenting subflow children.\n type DragState = {\n pointerId: number;\n nodeId: string;\n startClientX: number;\n startClientY: number;\n startPosition: Position;\n /** Captured at drag-start so each pointermove can reposition all\n * descendants by the same delta without re-walking the tree. */\n descendants: { id: string; startPosition: Position }[];\n /** Skip the `extent: 'parent'` clamp for this drag. True only when\n * the node is genuinely free to leave its parent: an explicit\n * Alt-detach, or a top-level node (no parent) that `reparentOnDrag`\n * lets travel into a container. A parented child on a plain drag\n * stays clamped — that's what keeps a subflow child in its frame. */\n skipClamp: boolean;\n /** Hit-test for a new parent at drag-end (Alt held OR the consumer\n * opted into `reparentOnDrag`). */\n evaluateReparent: boolean;\n rafScheduled: boolean;\n nextDelta: { dx: number; dy: number } | null;\n };\n const dragRef = useRef<DragState | null>(null);\n const [draggingId, setDraggingId] = useState<string | null>(null);\n\n const beginNodeDrag = useCallback(\n (nodeId: string, pointerId: number, clientX: number, clientY: number, altKey = false) => {\n if (!nodesDraggable) return;\n const node = nodes.find((n) => n.id === nodeId);\n if (!node) return;\n const kids = descendantsOf(nodeId, nodes).map((d) => ({\n id: d.id,\n startPosition: d.position,\n }));\n // Reparenting is \"in play\" when the user held Alt OR the consumer\n // set `reparentOnDrag`. That decides whether we hit-test for a new\n // parent at drag-end.\n const evaluateReparent = altKey || reparentOnDragRef.current;\n // The extent clamp is short-circuited ONLY when the node is truly\n // free to leave its parent:\n // • Alt held → explicit detach gesture.\n // • reparentOnDrag + node has no parent → a top-level node that\n // should be able to travel INTO a container.\n // A parented child on a plain drag keeps its clamp even with\n // `reparentOnDrag` on, so subflow children can't slide out of the\n // frame by accident — detaching one is a deliberate Alt-drag.\n const hasParent = !!node.parentId;\n const skipClamp = altKey || (reparentOnDragRef.current && !hasParent);\n dragRef.current = {\n pointerId,\n nodeId,\n startClientX: clientX,\n startClientY: clientY,\n startPosition: node.position,\n descendants: kids,\n skipClamp,\n evaluateReparent,\n rafScheduled: false,\n nextDelta: null,\n };\n setDraggingId(nodeId);\n selectNode(nodeId, false);\n },\n [nodes, nodesDraggable, selectNode],\n );\n\n // ── Connection middleware ─────────────────────────────────────────────\n // `connection` is local state. The ghost-line component subscribes here\n // (via prop), the rest of the canvas does not — so a connection drag\n // does NOT re-render every node. Setting state inside the global\n // pointermove handler still triggers a re-render of FlowCanvas itself,\n // but that's just the SVG ghost; the node list and edges are memoised.\n const [conn, setConn] = useState<{\n pointerId: number;\n from: ConnectStartParams;\n start: Position;\n end: Position;\n } | null>(null);\n // We keep a ref mirror so the global pointermove handler can read the\n // latest value without re-attaching listeners on every state change.\n const connRef = useRef<typeof conn>(null);\n useEffect(() => {\n connRef.current = conn;\n }, [conn]);\n\n const beginConnection = useCallback(\n (\n nodeId: string,\n handleId: string,\n handleType: \"source\" | \"target\",\n pointerId: number,\n clientX: number,\n clientY: number,\n ) => {\n if (!nodesConnectable) return;\n const node = nodes.find((n) => n.id === nodeId);\n if (!node) return;\n // Compute the originating handle's flow-space centre so the ghost\n // line is visible from the very first frame (no flicker).\n const desc = handleRegistry.resolve(nodeId, handleType, handleId);\n const side = desc?.side ?? (handleType === \"source\" ? \"bottom\" : \"top\");\n const index = desc?.index ?? 0;\n const total = desc?.total ?? 1;\n const ratio = (index + 1) / (total + 1);\n // Default width matches the BaseNode body (368 px) so the ghost\n // line origin lands ON the handle dot even before the ResizeObserver\n // has reported the real measured width back through `onNodesChange`.\n const w = node.width ?? 368;\n // Use the effective height — collapsed containers render a tiny\n // strip; without this the ghost line would start far below the\n // visible group when dragging from a perimeter handle.\n const h = effectiveHeight(node);\n const start: Position = (() => {\n switch (side) {\n case \"top\":\n return { x: node.position.x + w * ratio, y: node.position.y };\n case \"bottom\":\n return { x: node.position.x + w * ratio, y: node.position.y + h };\n case \"left\":\n return { x: node.position.x, y: node.position.y + h * ratio };\n case \"right\":\n return { x: node.position.x + w, y: node.position.y + h * ratio };\n }\n })();\n const from: ConnectStartParams = { nodeId, handleId, handleType };\n const rect = containerRef.current?.getBoundingClientRect();\n const end = rect\n ? screenToFlow({ x: clientX - rect.left, y: clientY - rect.top }, viewport)\n : start;\n setConn({ pointerId, from, start, end });\n store.setConnection(from);\n onConnectStart?.({ clientX, clientY, pointerId } as unknown as globalThis.PointerEvent, from);\n },\n [nodes, nodesConnectable, handleRegistry, viewport, store, onConnectStart],\n );\n\n // ── Refs that the global pointer listeners read so they don't depend\n // ── on captured callback identity (avoids listener re-attach storms).\n const viewportRef = useRef(viewport);\n const nodesRef = useRef(nodes);\n const edgesRef = useRef(edges);\n const onNodesChangeRefForInstance = useRef(onNodesChange);\n const onEdgesChangeRefForInstance = useRef(onEdgesChange);\n const onBeforeDeleteRef = useRef(onBeforeDelete);\n const snapToGridRef = useRef(snapToGrid);\n const gridSizeRef = useRef(gridSize);\n const nodeCollisionGapRef = useRef(nodeCollisionGap);\n const subflowCollisionGapRef = useRef(subflowCollisionGap ?? nodeCollisionGap);\n const reparentOnDragRef = useRef(reparentOnDrag);\n const autoResizeContainersRef = useRef(autoResizeContainers);\n const containerAutoResizePaddingRef = useRef(containerAutoResizePadding);\n const containerMinWidthRef = useRef(containerMinWidth);\n const containerMinHeightRef = useRef(containerMinHeight);\n useEffect(() => {\n edgesRef.current = edges;\n }, [edges]);\n useEffect(() => {\n onNodesChangeRefForInstance.current = onNodesChange;\n }, [onNodesChange]);\n useEffect(() => {\n onEdgesChangeRefForInstance.current = onEdgesChange;\n }, [onEdgesChange]);\n useEffect(() => {\n onBeforeDeleteRef.current = onBeforeDelete;\n }, [onBeforeDelete]);\n useEffect(() => {\n snapToGridRef.current = snapToGrid;\n }, [snapToGrid]);\n useEffect(() => {\n gridSizeRef.current = gridSize;\n }, [gridSize]);\n useEffect(() => {\n nodeCollisionGapRef.current = nodeCollisionGap;\n }, [nodeCollisionGap]);\n useEffect(() => {\n subflowCollisionGapRef.current = subflowCollisionGap ?? nodeCollisionGap;\n }, [subflowCollisionGap, nodeCollisionGap]);\n useEffect(() => {\n reparentOnDragRef.current = reparentOnDrag;\n }, [reparentOnDrag]);\n useEffect(() => {\n autoResizeContainersRef.current = autoResizeContainers;\n }, [autoResizeContainers]);\n useEffect(() => {\n containerAutoResizePaddingRef.current = containerAutoResizePadding;\n }, [containerAutoResizePadding]);\n useEffect(() => {\n containerMinWidthRef.current = containerMinWidth;\n }, [containerMinWidth]);\n useEffect(() => {\n containerMinHeightRef.current = containerMinHeight;\n }, [containerMinHeight]);\n const onNodesChangeRef = useRef(onNodesChange);\n const onConnectRef = useRef(onConnect);\n const onConnectEndRef = useRef(onConnectEnd);\n const isValidConnectionRef = useRef(isValidConnection);\n useEffect(() => {\n viewportRef.current = viewport;\n }, [viewport]);\n useEffect(() => {\n nodesRef.current = nodes;\n }, [nodes]);\n useEffect(() => {\n onNodesChangeRef.current = onNodesChange;\n }, [onNodesChange]);\n useEffect(() => {\n onConnectRef.current = onConnect;\n }, [onConnect]);\n useEffect(() => {\n onConnectEndRef.current = onConnectEnd;\n }, [onConnectEnd]);\n useEffect(() => {\n isValidConnectionRef.current = isValidConnection;\n }, [isValidConnection]);\n\n // ── Pointer dispatch — single window-level listener installed ONCE.\n // All gesture deps come through refs, so this effect runs once per\n // mount and never re-attaches.\n useEffect(() => {\n const onPointerMove = (e: globalThis.PointerEvent) => {\n const vp = viewportRef.current;\n // Node drag\n const drag = dragRef.current;\n if (drag && drag.pointerId === e.pointerId) {\n const dx = (e.clientX - drag.startClientX) / vp.zoom;\n const dy = (e.clientY - drag.startClientY) / vp.zoom;\n drag.nextDelta = { dx, dy };\n if (!drag.rafScheduled) {\n drag.rafScheduled = true;\n requestAnimationFrame(() => {\n const d = dragRef.current;\n if (!d) return;\n d.rafScheduled = false;\n const delta = d.nextDelta;\n if (!delta) return;\n // Compute the proposed new position for the dragged node.\n const dragNode = nodesRef.current.find((n) => n.id === d.nodeId);\n if (!dragNode) return;\n const proposed = {\n x: d.startPosition.x + delta.dx,\n y: d.startPosition.y + delta.dy,\n };\n // Apply extent:'parent' clamping unless this drag is allowed\n // to leave the parent (Alt-detach, or a top-level node free\n // to roam). A clamped child can't be dragged out of frame.\n const clamped = d.skipClamp\n ? proposed\n : clampToParentExtent(dragNode, proposed, nodesRef.current);\n // Magnet collision — push out of any sibling we're overlapping\n // (or sitting closer than `gap` to). Subflow containers use\n // `subflowCollisionGap`; regular nodes use `nodeCollisionGap`.\n // Descendants of the dragged node never participate, so a\n // parent can move freely through the space its children occupy.\n const isContainer = isContainerType(dragNode.type);\n const gap = isContainer ? subflowCollisionGapRef.current : nodeCollisionGapRef.current;\n const excludeIds = new Set<string>([d.nodeId, ...d.descendants.map((kid) => kid.id)]);\n const finalPos = resolveNodeCollisions(dragNode, clamped, nodesRef.current, {\n gap,\n exclude: excludeIds,\n });\n // The realised delta may differ from the proposed delta after\n // clamping and collision — use it for shifting descendants so\n // they stay glued to the parent.\n const realDx = finalPos.x - d.startPosition.x;\n const realDy = finalPos.y - d.startPosition.y;\n const changes: NodeChange[] = [change.node.position(d.nodeId, finalPos, true)];\n for (const kid of d.descendants) {\n changes.push(\n change.node.position(\n kid.id,\n { x: kid.startPosition.x + realDx, y: kid.startPosition.y + realDy },\n true,\n ),\n );\n }\n onNodesChangeRef.current?.(changes);\n });\n }\n }\n\n // Connection drag — only this branch sets React state, so the\n // re-render is limited to FlowCanvas itself (nodes + edges memoised).\n const c = connRef.current;\n if (c && c.pointerId === e.pointerId) {\n const rect = containerRef.current?.getBoundingClientRect();\n if (rect) {\n const end = screenToFlow({ x: e.clientX - rect.left, y: e.clientY - rect.top }, vp);\n setConn({ ...c, end });\n }\n }\n };\n\n const onPointerUp = (e: globalThis.PointerEvent) => {\n const vp = viewportRef.current;\n const drag = dragRef.current;\n if (drag && drag.pointerId === e.pointerId) {\n const dx = (e.clientX - drag.startClientX) / vp.zoom;\n const dy = (e.clientY - drag.startClientY) / vp.zoom;\n const dragNode = nodesRef.current.find((n) => n.id === drag.nodeId);\n if (dragNode) {\n let proposed = {\n x: drag.startPosition.x + dx,\n y: drag.startPosition.y + dy,\n };\n // Snap to grid on commit only — during drag the node follows\n // the pointer freely, but releases land on the nearest grid\n // intersection. UX is \"smooth move, satisfying click.\"\n if (snapToGridRef.current) {\n const g = gridSizeRef.current;\n proposed = {\n x: Math.round(proposed.x / g) * g,\n y: Math.round(proposed.y / g) * g,\n };\n }\n const clamped = drag.skipClamp\n ? proposed\n : clampToParentExtent(dragNode, proposed, nodesRef.current);\n // Run collision once more on commit — guards against a fast\n // pointer-up that bypassed the last rAF tick.\n const isContainer = isContainerType(dragNode.type);\n const gap = isContainer ? subflowCollisionGapRef.current : nodeCollisionGapRef.current;\n const excludeIds = new Set<string>([\n drag.nodeId,\n ...drag.descendants.map((kid) => kid.id),\n ]);\n const finalPos = resolveNodeCollisions(dragNode, clamped, nodesRef.current, {\n gap,\n exclude: excludeIds,\n });\n const realDx = finalPos.x - drag.startPosition.x;\n const realDy = finalPos.y - drag.startPosition.y;\n\n // Build the final commit. Dragging now becomes false.\n const changes: NodeChange[] = [change.node.position(drag.nodeId, finalPos, false)];\n for (const kid of drag.descendants) {\n changes.push(\n change.node.position(\n kid.id,\n { x: kid.startPosition.x + realDx, y: kid.startPosition.y + realDy },\n false,\n ),\n );\n }\n\n // Reparent evaluation: when `evaluateReparent` is set (Alt-held\n // OR `reparentOnDrag` prop enabled), hit-test the drop point\n // against existing containers. Three outcomes:\n // • Was parented, dropped outside any container → detach.\n // • Was parented, dropped inside a different container → reparent.\n // • Was top-level, dropped inside a container → adopt.\n // The replace-change is appended to the same `onNodesChange`\n // batch as the position change, so the consumer sees one\n // atomic update — no parentId/position race.\n if (drag.evaluateReparent) {\n // Hit-test the child's CENTRE. Fall back to the default\n // footprint (not 0) for unmeasured nodes — `?? 0` made the\n // centre collapse onto the top-left corner, so a node dropped\n // squarely on a container could miss it (DEV-200).\n const dragW = dragNode.width ?? DEFAULT_NODE_WIDTH;\n const dragH = effectiveHeight(dragNode);\n const targetGroup = findContainingGroup(\n {\n x: finalPos.x + dragW / 2,\n y: finalPos.y + dragH / 2,\n },\n nodesRef.current,\n [drag.nodeId, ...drag.descendants.map((d) => d.id)],\n );\n const nextParentId = targetGroup?.id;\n // Only emit a replace if parentage actually changed —\n // dragging a child around inside its own parent should NOT\n // re-emit the whole node every frame.\n if (nextParentId !== dragNode.parentId) {\n const updated: WorkflowNode = {\n ...dragNode,\n position: finalPos,\n parentId: nextParentId,\n // Adopting into a container always pins the child with\n // `extent: 'parent'` so it's clamped from the next drag\n // on. Detaching clears it.\n extent: nextParentId ? \"parent\" : undefined,\n };\n changes.push(change.node.replace(drag.nodeId, updated));\n\n // Grow-only fit on ADOPT: make sure the target container is\n // at least large enough to show the freshly-adopted child in\n // full. Otherwise the child overhangs the frame and then\n // \"jumps\" inside on the next drag when `extent: 'parent'`\n // clamps it. We only GROW (never shrink or reposition) so a\n // manually-sized frame is preserved — full auto-fit remains\n // opt-in via `autoResizeContainers`. DEV-200.\n if (targetGroup) {\n const pad = containerAutoResizePaddingRef.current;\n const curW = targetGroup.width ?? DEFAULT_NODE_WIDTH;\n const curH = targetGroup.height ?? effectiveHeight(targetGroup);\n const needW = finalPos.x + dragW + pad - targetGroup.position.x;\n const needH = finalPos.y + dragH + pad - targetGroup.position.y;\n const grownW = Math.max(curW, needW);\n const grownH = Math.max(curH, needH);\n if (grownW !== curW || grownH !== curH) {\n changes.push(\n change.node.dimensions(targetGroup.id, { width: grownW, height: grownH }),\n );\n }\n }\n }\n }\n\n // Container auto-resize: recompute each container's bbox from\n // its (post-drag, post-reparent) children + padding. Folded\n // into the same change batch so the consumer can't see a\n // half-resized frame between renders.\n if (autoResizeContainersRef.current) {\n const containerChanges = computeContainerAutoResize(\n nodesRef.current,\n // Projected children: apply the position + reparent\n // changes we just built before measuring bboxes.\n changes,\n containerAutoResizePaddingRef.current,\n containerMinWidthRef.current,\n containerMinHeightRef.current,\n );\n for (const c of containerChanges) changes.push(c);\n }\n\n onNodesChangeRef.current?.(changes);\n }\n dragRef.current = null;\n setDraggingId(null);\n }\n\n const c = connRef.current;\n if (c && c.pointerId === e.pointerId) {\n // ── Geometric drop-target resolution ──────────────────────────\n // We do NOT hit-test the DOM (`e.target.closest` /\n // `elementsFromPoint`). Inside a subflow the container frame,\n // the child nodes and their ports overlap and stack in ways\n // that make DOM hit-testing miss the intended port entirely.\n // Instead we project the pointer into flow-space and pick the\n // nearest registered handle within a snap radius — the same\n // source of truth edges already use for their geometry. This\n // is immune to z-index, pointer-events and overlapping frames.\n const rect = containerRef.current?.getBoundingClientRect();\n const flowPos = rect\n ? screenToFlow({ x: e.clientX - rect.left, y: e.clientY - rect.top }, vp)\n : { x: 0, y: 0 };\n\n // Snap radius: ~26 on-screen px, converted to flow-space so the\n // tolerance feels constant regardless of zoom.\n const snapRadius = 26 / Math.max(0.1, vp.zoom);\n let bestDesc: HandleDescriptor | null = null;\n let bestDist = snapRadius;\n for (const desc of handleRegistry.all()) {\n // Can't end on the source node itself, and the target must be\n // the OPPOSITE role — a `source` connects to a `target`.\n if (desc.nodeId === c.from.nodeId) continue;\n if (desc.type === c.from.handleType) continue;\n if (!desc.canEnd) continue;\n const targetNode = nodesRef.current.find((n) => n.id === desc.nodeId);\n if (!targetNode || targetNode.hidden) continue;\n const centre = handleCentre(targetNode, desc.side, desc.index, desc.total);\n const dist = Math.hypot(centre.x - flowPos.x, centre.y - flowPos.y);\n if (dist < bestDist) {\n bestDist = dist;\n bestDesc = desc;\n }\n }\n\n let connection: Connection | null = null;\n let connectedTo: ConnectStartParams | undefined;\n if (bestDesc) {\n const source =\n c.from.handleType === \"source\"\n ? c.from\n : {\n nodeId: bestDesc.nodeId,\n handleId: bestDesc.handleId,\n handleType: \"source\" as const,\n };\n const target2 =\n c.from.handleType === \"target\"\n ? c.from\n : {\n nodeId: bestDesc.nodeId,\n handleId: bestDesc.handleId,\n handleType: \"target\" as const,\n };\n connection = {\n source: source.nodeId,\n sourceHandle: source.handleId,\n target: target2.nodeId,\n targetHandle: target2.handleId,\n };\n connectedTo = {\n nodeId: bestDesc.nodeId,\n handleId: bestDesc.handleId,\n handleType: bestDesc.type,\n };\n const validator = isValidConnectionRef.current;\n if (validator && !validator(connection)) {\n connection = null;\n connectedTo = undefined;\n }\n }\n const endState: ConnectEndState = {\n cancelled: !connection,\n position: { x: e.clientX, y: e.clientY },\n flowPosition: flowPos,\n from: c.from,\n to: connectedTo,\n };\n if (connection) onConnectRef.current?.(connection);\n onConnectEndRef.current?.(e, endState);\n setConn(null);\n store.setConnection(null);\n }\n };\n\n const onPointerCancel = () => {\n if (dragRef.current) {\n dragRef.current = null;\n setDraggingId(null);\n }\n if (connRef.current) {\n setConn(null);\n store.setConnection(null);\n }\n };\n\n window.addEventListener(\"pointermove\", onPointerMove);\n window.addEventListener(\"pointerup\", onPointerUp);\n window.addEventListener(\"pointercancel\", onPointerCancel);\n return () => {\n window.removeEventListener(\"pointermove\", onPointerMove);\n window.removeEventListener(\"pointerup\", onPointerUp);\n window.removeEventListener(\"pointercancel\", onPointerCancel);\n };\n }, [store]); // mount-only\n\n // ── Container auto-resize — catch-all ─────────────────────────────────\n // The drag-end commit resizes containers atomically for the drag case.\n // This effect covers every OTHER way a container's children change:\n // a node dropped in from an action drawer, a child deleted, a paste.\n // It's a no-op during an active drag (the commit path owns that) and\n // `computeContainerAutoResize` returns [] when nothing is dirty, so a\n // settled graph can't loop.\n useEffect(() => {\n if (!autoResizeContainers || draggingId) return;\n const resizeChanges = computeContainerAutoResize(\n nodes,\n [],\n containerAutoResizePadding,\n containerMinWidth,\n containerMinHeight,\n );\n if (resizeChanges.length > 0) onNodesChange?.(resizeChanges);\n }, [\n nodes,\n draggingId,\n autoResizeContainers,\n containerAutoResizePadding,\n containerMinWidth,\n containerMinHeight,\n onNodesChange,\n ]);\n\n // ── Pan (canvas drag) ─────────────────────────────────────────────────\n // We DON'T clear selection on pan-start (issue #4 from the audit). The\n // pointerup handler decides whether this was a click (no movement) and\n // only clears selection then.\n const panRef = useRef<{\n pointerId: number;\n startClientX: number;\n startClientY: number;\n startVp: Viewport;\n moved: boolean;\n } | null>(null);\n const onCanvasPointerDown = (e: PointerEvent<HTMLDivElement>) => {\n if (e.button !== 0) return;\n const t = e.target as HTMLElement;\n if (\n t.closest(\"[data-node-id]\") ||\n t.closest(\"[data-edge-id]\") ||\n t.closest(\"[data-handle-id]\")\n ) {\n return;\n }\n if (!panOnDrag) {\n // Even without pan, a click on the pane should clear selection.\n panRef.current = {\n pointerId: e.pointerId,\n startClientX: e.clientX,\n startClientY: e.clientY,\n startVp: viewport,\n moved: false,\n };\n return;\n }\n panRef.current = {\n pointerId: e.pointerId,\n startClientX: e.clientX,\n startClientY: e.clientY,\n startVp: viewport,\n moved: false,\n };\n };\n\n useEffect(() => {\n const onMove = (e: globalThis.PointerEvent) => {\n const pan = panRef.current;\n if (!pan || pan.pointerId !== e.pointerId) return;\n const dx = e.clientX - pan.startClientX;\n const dy = e.clientY - pan.startClientY;\n if (Math.abs(dx) > paneClickDistance || Math.abs(dy) > paneClickDistance) {\n if (!pan.moved) setPanGesture(true);\n pan.moved = true;\n }\n if (pan.moved && panOnDrag) {\n setViewport({ ...pan.startVp, x: pan.startVp.x + dx, y: pan.startVp.y + dy });\n }\n };\n const onUp = () => {\n const pan = panRef.current;\n if (!pan) return;\n // A genuine \"click\" on the pane (no significant movement) fires\n // onPaneClick. Selection is cleared only when the consumer opts in\n // — consumers that keep a side-panel open through pane clicks pass\n // `paneClickClearsSelection={false}`. A drag-pan does neither.\n if (!pan.moved) {\n onPaneClick?.();\n if (paneClickClearsSelection) clearSelection();\n }\n panRef.current = null;\n setPanGesture(false);\n };\n window.addEventListener(\"pointermove\", onMove);\n window.addEventListener(\"pointerup\", onUp);\n window.addEventListener(\"pointercancel\", onUp);\n return () => {\n window.removeEventListener(\"pointermove\", onMove);\n window.removeEventListener(\"pointerup\", onUp);\n window.removeEventListener(\"pointercancel\", onUp);\n };\n }, [\n setViewport,\n paneClickDistance,\n panOnDrag,\n onPaneClick,\n clearSelection,\n paneClickClearsSelection,\n ]);\n\n // ── Wheel-zoom ────────────────────────────────────────────────────────\n // Attached as a NON-PASSIVE native listener (see effect below) rather than\n // via React's `onWheel`. React registers wheel handlers as passive, so\n // `preventDefault()` inside a React onWheel is silently ignored — the\n // trackpad pinch (ctrl+wheel) then zoomed the whole browser page instead\n // of the canvas (DEV-206). A native listener with `{ passive: false }`\n // lets preventDefault actually take effect.\n const handleWheel = (e: globalThis.WheelEvent) => {\n if (!zoomOnScroll) return;\n e.preventDefault();\n const rect = containerRef.current?.getBoundingClientRect();\n if (!rect) return;\n const px = e.clientX - rect.left;\n const py = e.clientY - rect.top;\n const factor = Math.exp(-e.deltaY * 0.001);\n const nextZoom = Math.max(minZoom, Math.min(maxZoom, viewport.zoom * factor));\n const k = nextZoom / viewport.zoom;\n setViewport({\n zoom: nextZoom,\n x: px - (px - viewport.x) * k,\n y: py - (py - viewport.y) * k,\n });\n };\n // Keep the freshest handler in a ref so the native listener (attached once)\n // always sees the current viewport/zoom without re-binding every render.\n const handleWheelRef = useRef(handleWheel);\n handleWheelRef.current = handleWheel;\n useEffect(() => {\n const el = containerRef.current;\n if (!el) return;\n const listener = (e: globalThis.WheelEvent) => handleWheelRef.current(e);\n el.addEventListener(\"wheel\", listener, { passive: false });\n return () => el.removeEventListener(\"wheel\", listener);\n }, []);\n\n // Zoom around the VIEWPORT CENTRE (not the flow-space origin). The toolbar\n // zoom buttons keep `x`/`y` unchanged, which anchors the scale at flow\n // (0,0) — so the workflow flew toward/away from the top-left corner and\n // could shoot off-screen. Pin the flow point currently under the container\n // centre instead (DEV-206).\n const zoomAroundCentre = (nextZoom: number) => {\n const rect = containerRef.current?.getBoundingClientRect();\n const vp = viewportRef.current;\n const cx = rect ? rect.width / 2 : 0;\n const cy = rect ? rect.height / 2 : 0;\n const k = nextZoom / vp.zoom;\n setViewport({\n zoom: nextZoom,\n x: cx - (cx - vp.x) * k,\n y: cy - (cy - vp.y) * k,\n });\n };\n\n // ── Dispatch contract for Handle ──────────────────────────────────────\n const dispatch = useCallback<FlowDispatch>(\n (a: FlowDispatchAction) => {\n if (a.type === \"connection/start\") {\n beginConnection(a.nodeId, a.handleId, a.handleType, a.pointerId, a.clientX, a.clientY);\n }\n },\n [beginConnection],\n );\n\n // Dimensions reporter — FlowNode's ResizeObserver calls this on size\n // change. We compare against `nodes[]` (current props) and only emit a\n // change when the value actually differs, so we don't trigger an\n // infinite render loop (dimensions change → parent re-renders nodes →\n // ResizeObserver may fire again from style updates).\n const reportDimensions = useCallback(\n (nodeId: string, width: number, height: number) => {\n const node = nodes.find((n) => n.id === nodeId);\n if (!node) return;\n if (node.width === width && node.height === height) return;\n onNodesChange?.([change.node.dimensions(nodeId, { width, height })]);\n },\n [nodes, onNodesChange],\n );\n\n // Toggle data.collapsed on a container node. Exposed via the bridge so\n // the chevron rendered inside GroupNode / ForEachNode can flip the\n // subflow state from inside the kind component, no external toolbar\n // wiring needed.\n const toggleNodeCollapseImpl = useCallback(\n (nodeId: string) => {\n const node = nodes.find((n) => n.id === nodeId);\n if (!node) return;\n const prevData = (node.data ?? {}) as { collapsed?: boolean } & Record<string, unknown>;\n const nextNode = {\n ...node,\n data: { ...prevData, collapsed: !prevData.collapsed },\n } as WorkflowNode;\n onNodesChange?.([change.node.replace(nodeId, nextNode)]);\n },\n [nodes, onNodesChange],\n );\n\n // Delete one node + its incident edges. Exposed via the FlowNodeBridge\n // so a node-rendered delete button (BaseNode corner [×]) can fire\n // without going through the keyboard / context-menu path.\n const deleteNodeImpl = useCallback(\n (nodeId: string) => {\n const incidentEdgeIds = edgesRef.current\n .filter((e) => e.source === nodeId || e.target === nodeId)\n .map((e) => e.id);\n if (incidentEdgeIds.length > 0) {\n onEdgesChange?.(incidentEdgeIds.map((id) => change.edge.remove(id)));\n }\n onNodesChange?.([change.node.remove(nodeId)]);\n },\n [onNodesChange, onEdgesChange],\n );\n\n // ── Imperative instance — useFlow() and onInit ───────────────────────\n // Methods read through refs each call so they always see fresh state,\n // even though the instance itself is stable across renders. Mutating\n // methods round-trip through the consumer's onNodesChange/onEdgesChange\n // so the canonical state stays single-source-of-truth.\n const instance = useMemo<FlowInstance>(\n () => ({\n // viewport\n getViewport: () => viewportRef.current,\n setViewport: (vp) => setViewport(vp),\n setCenter: (x, y, opts) => {\n const z = opts?.zoom ?? viewportRef.current.zoom;\n const rect = containerRef.current?.getBoundingClientRect();\n if (!rect) return;\n setViewport({\n zoom: z,\n x: rect.width / 2 - x * z,\n y: rect.height / 2 - y * z,\n });\n },\n fitView: async (opts) => {\n const rect = containerRef.current?.getBoundingClientRect();\n if (!rect) return false;\n const padding = opts?.padding ?? 80;\n const targetNodes = opts?.nodes\n ? nodesRef.current.filter((n) => opts.nodes!.some((x) => x.id === n.id))\n : nodesRef.current.filter((n) => !n.hidden);\n if (targetNodes.length === 0) return false;\n let minX = Number.POSITIVE_INFINITY;\n let minY = Number.POSITIVE_INFINITY;\n let maxX = Number.NEGATIVE_INFINITY;\n let maxY = Number.NEGATIVE_INFINITY;\n for (const n of targetNodes) {\n const w = n.width ?? DEFAULT_NODE_WIDTH;\n const h = effectiveHeight(n);\n if (n.position.x < minX) minX = n.position.x;\n if (n.position.y < minY) minY = n.position.y;\n if (n.position.x + w > maxX) maxX = n.position.x + w;\n if (n.position.y + h > maxY) maxY = n.position.y + h;\n }\n const cw = maxX - minX;\n const ch = maxY - minY;\n const zx = (rect.width - padding * 2) / cw;\n const zy = (rect.height - padding * 2) / ch;\n const zoom = Math.max(\n opts?.minZoom ?? 0.25,\n Math.min(opts?.maxZoom ?? 1.5, Math.min(zx, zy)),\n );\n setViewport({\n zoom,\n x: rect.width / 2 - ((minX + maxX) / 2) * zoom,\n y: rect.height / 2 - ((minY + maxY) / 2) * zoom,\n });\n return true;\n },\n zoomIn: (opts) => {\n const step = opts?.step ?? 0.2;\n const next = Math.min(maxZoom, viewportRef.current.zoom * (1 + step));\n zoomAroundCentre(next);\n },\n zoomOut: (opts) => {\n const step = opts?.step ?? 0.2;\n const next = Math.max(minZoom, viewportRef.current.zoom / (1 + step));\n zoomAroundCentre(next);\n },\n zoomTo: (level) => {\n zoomAroundCentre(Math.max(minZoom, Math.min(maxZoom, level)));\n },\n\n // transforms\n screenToFlowPosition: (p) => screenToFlow(p, viewportRef.current),\n flowToScreenPosition: (p) => flowToScreen(p, viewportRef.current),\n\n // reads\n getNodes: () => nodesRef.current.slice(),\n getEdges: () => edgesRef.current.slice(),\n getNode: (id) => nodesRef.current.find((n) => n.id === id),\n getEdge: (id) => edgesRef.current.find((e) => e.id === id),\n getNodesBounds: (subset) => {\n const pool = subset\n ? nodesRef.current.filter((n) => subset.some((x) => x.id === n.id))\n : nodesRef.current.filter((n) => !n.hidden);\n if (pool.length === 0) return { x: 0, y: 0, width: 0, height: 0 };\n let minX = Number.POSITIVE_INFINITY;\n let minY = Number.POSITIVE_INFINITY;\n let maxX = Number.NEGATIVE_INFINITY;\n let maxY = Number.NEGATIVE_INFINITY;\n for (const n of pool) {\n const w = n.width ?? DEFAULT_NODE_WIDTH;\n const h = effectiveHeight(n);\n minX = Math.min(minX, n.position.x);\n minY = Math.min(minY, n.position.y);\n maxX = Math.max(maxX, n.position.x + w);\n maxY = Math.max(maxY, n.position.y + h);\n }\n return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };\n },\n getIntersectingNodes: (area, partially = true) => {\n return nodesRef.current.filter((n) => {\n if (n.hidden) return false;\n const w = n.width ?? DEFAULT_NODE_WIDTH;\n const h = effectiveHeight(n);\n if (partially) {\n // Any overlap counts.\n return (\n n.position.x < area.x + area.width &&\n n.position.x + w > area.x &&\n n.position.y < area.y + area.height &&\n n.position.y + h > area.y\n );\n }\n // Strict containment — node bbox sits entirely inside area.\n return (\n n.position.x >= area.x &&\n n.position.y >= area.y &&\n n.position.x + w <= area.x + area.width &&\n n.position.y + h <= area.y + area.height\n );\n });\n },\n\n // mutations\n addNodes: (nodes) => {\n const arr = Array.isArray(nodes) ? nodes : [nodes];\n onNodesChangeRefForInstance.current?.(arr.map((item) => change.node.add(item)));\n },\n addEdges: (edges) => {\n const arr = Array.isArray(edges) ? edges : [edges];\n onEdgesChangeRefForInstance.current?.(arr.map((item) => change.edge.add(item)));\n },\n updateNodeData: (id, partial) => {\n const cur = nodesRef.current.find((n) => n.id === id);\n if (!cur) return;\n // Merge partial into existing data; the consumer's reducer will\n // apply the resulting `replace` and emit fresh nodes.\n const nextData = { ...((cur.data ?? {}) as object), ...partial } as typeof cur.data;\n onNodesChangeRefForInstance.current?.([\n change.node.replace(id, { ...cur, data: nextData }),\n ]);\n },\n updateNode: (id, partial) => {\n const cur = nodesRef.current.find((n) => n.id === id);\n if (!cur) return;\n onNodesChangeRefForInstance.current?.([change.node.replace(id, { ...cur, ...partial })]);\n },\n deleteElements: async ({ nodes: ns, edges: es }) => {\n const nodesToDelete = (ns ?? [])\n .map((x) => nodesRef.current.find((n) => n.id === x.id))\n .filter((n): n is WorkflowNode => !!n);\n const edgesToDelete = (es ?? [])\n .map((x) => edgesRef.current.find((e) => e.id === x.id))\n .filter((e): e is WorkflowEdge => !!e);\n // Async veto — host can return a Promise<boolean> to confirm\n // (\"this node is referenced by a running execution; really delete?\").\n const before = onBeforeDeleteRef.current;\n if (before) {\n const ok = await before({ nodes: nodesToDelete, edges: edgesToDelete });\n if (!ok) return false;\n }\n if (nodesToDelete.length > 0) {\n onNodesChangeRefForInstance.current?.(nodesToDelete.map((n) => change.node.remove(n.id)));\n }\n if (edgesToDelete.length > 0) {\n onEdgesChangeRefForInstance.current?.(edgesToDelete.map((e) => change.edge.remove(e.id)));\n }\n return true;\n },\n }),\n [setViewport, minZoom, maxZoom],\n );\n\n // Hand the instance to the consumer once on mount. We don't refire on\n // every render because consumers typically stash the ref once. The\n // instance itself is stable (closures read fresh values via refs).\n const initFiredRef = useRef(false);\n useEffect(() => {\n if (initFiredRef.current) return;\n initFiredRef.current = true;\n onInit?.(instance);\n }, [instance, onInit]);\n\n // Auto-frame the existing nodes on first mount. Without this, a\n // canvas that opens with nodes at positions like (1200, 800) shows\n // an empty viewport at the {0,0,1} origin and the user has to pan to\n // find their workflow. The default kicks in only when the consumer\n // didn't pin a viewport themselves and didn't explicitly disable it.\n //\n // Fires on the first frame where `nodes.length > 0` AND the container\n // has measured dimensions (a 0×0 container would yield NaN bounds).\n // The bounding-box math falls back to DEFAULT_NODE_WIDTH / height for\n // un-measured nodes, so the framing is correct even before ResizeObservers\n // have reported real dimensions.\n const fitOnInitFiredRef = useRef(false);\n useEffect(() => {\n if (fitOnInitFiredRef.current) return;\n const opt = fitViewOnInit;\n const shouldFit = opt === false ? false : opt !== undefined ? true : !viewportPropProvided;\n if (!shouldFit) return;\n // Wait until the container has real dimensions — a 0×0 container yields\n // NaN bounds. We do NOT latch while unmeasured so the fit still fires\n // once the container lays out.\n const rect = containerRef.current?.getBoundingClientRect();\n if (!rect || rect.width === 0 || rect.height === 0) return;\n // Container is measured → this is our single initialization opportunity.\n // \"Fit on init\" means \"frame the content present at initialization\", NOT\n // \"fit whenever the first node ever appears\". If the canvas mounted empty\n // there is nothing to frame, but we still latch here so that a node the\n // user later drops onto the blank canvas is NOT mistaken for hydration\n // and does not recenter + reset zoom onto itself (DEV-203).\n if (nodes.length === 0) {\n fitOnInitFiredRef.current = true;\n return;\n }\n const fitOpts = typeof opt === \"object\" && opt !== null ? opt : undefined;\n // Defer one frame so any layout effects (e.g. ResizeObservers reporting\n // node dimensions) have settled before we compute bounds. Latch INSIDE\n // the rAF (not before scheduling it) so React StrictMode's\n // mount → cleanup → remount cycle — whose cleanup cancels the first\n // frame — cannot leave us permanently \"fired\" without ever fitting\n // (DEV-206). Each effect re-run cancels the prior frame via cleanup, so\n // there is no double-fit.\n const raf = requestAnimationFrame(() => {\n fitOnInitFiredRef.current = true;\n void instance.fitView(fitOpts);\n });\n return () => cancelAnimationFrame(raf);\n }, [fitViewOnInit, viewportPropProvided, nodes.length, instance]);\n\n // ── Keyboard: Backspace / Delete removes the current selection ────────\n // Goes through `instance.deleteElements` so `onBeforeDelete` veto, edge\n // re-routing, and the same change pipeline as the X button fire\n // consistently. We only act when focus is on the canvas (or its\n // children) — typing in a real input shouldn't delete the workflow.\n useEffect(() => {\n const onKey = (e: KeyboardEvent) => {\n if (e.key !== \"Backspace\" && e.key !== \"Delete\") return;\n const target = e.target as HTMLElement | null;\n // Don't hijack typing in form fields. `contentEditable` covers the\n // edge label inline editor.\n if (\n target &&\n (target.tagName === \"INPUT\" ||\n target.tagName === \"TEXTAREA\" ||\n target.tagName === \"SELECT\" ||\n target.isContentEditable)\n ) {\n return;\n }\n // Only fire when the canvas (or something inside it) currently\n // owns focus / pointer interaction. Bare `keydown` on document\n // would steal Backspace from other widgets on the page.\n if (!containerRef.current?.contains(target) && document.activeElement !== document.body) {\n return;\n }\n const sel = store.getSnapshot();\n if (sel.selectedNodeIds.size === 0 && sel.selectedEdgeIds.size === 0) return;\n e.preventDefault();\n void instance.deleteElements({\n nodes: Array.from(sel.selectedNodeIds, (id) => ({ id })),\n edges: Array.from(sel.selectedEdgeIds, (id) => ({ id })),\n });\n };\n window.addEventListener(\"keydown\", onKey);\n return () => window.removeEventListener(\"keydown\", onKey);\n }, [instance, store]);\n\n const bridge = useMemo<FlowNodeBridge>(\n () => ({\n beginNodeDrag,\n selectNode,\n notifyNodeClick,\n selectEdge,\n reportDimensions,\n deleteNode: deleteNodeImpl,\n toggleNodeCollapse: toggleNodeCollapseImpl,\n }),\n [\n beginNodeDrag,\n selectNode,\n notifyNodeClick,\n selectEdge,\n reportDimensions,\n deleteNodeImpl,\n toggleNodeCollapseImpl,\n ],\n );\n\n // ── Cursor feedback ───────────────────────────────────────────────────\n // The user gets immediate visual cues for which gesture they're in:\n // - idle on empty canvas → \"grab\" (or default if panOnDrag = false)\n // - dragging the pane → \"grabbing\"\n // - dragging a connection → \"crosshair\"\n // - dragging a node → handled by FlowNode CSS (\"grabbing\")\n // We use a state-driven class so the cursor flips synchronously with\n // the gesture (vs CSS :active which lags behind pointer-capture).\n const [panGesture, setPanGesture] = useState(false);\n\n // ── Render ────────────────────────────────────────────────────────────\n const isEmpty = nodes.length === 0 && edges.length === 0;\n const isConnecting = conn !== null;\n\n // Filter out hidden nodes + their incident edges. Hidden is a runtime\n // flag (e.g. set by a \"collapse group\" toggle). Edges that reference a\n // hidden node would otherwise dangle in space.\n const visibleNodes = useMemo(() => nodes.filter((n) => !n.hidden), [nodes]);\n const visibleEdges = useMemo(() => {\n if (visibleNodes.length === nodes.length) return edges;\n const visibleIds = new Set(visibleNodes.map((n) => n.id));\n return edges.filter((e) => visibleIds.has(e.source) && visibleIds.has(e.target));\n }, [edges, nodes, visibleNodes]);\n\n // Sort so containers render before their children (lower in DOM = under\n // children when zIndex ties). For NESTED containers (group inside group)\n // we order by depth — outermost first — so an inner group's children\n // can still draw on top of the outer group's frame. Non-container nodes\n // sort last in original-array order.\n //\n // Containers: `group` only (see `isContainerType`). `forEach` is a simple\n // node, not a child-hosting frame.\n const orderedNodes = useMemo(() => {\n const isContainer = (n: WorkflowNode) => isContainerType(n.type);\n // Cache parent chain depth for stable ordering. Cycles return Infinity.\n const depth = (n: WorkflowNode): number => {\n let d = 0;\n let cursor = n.parentId;\n const seen = new Set<string>();\n while (cursor) {\n if (seen.has(cursor)) return Number.POSITIVE_INFINITY;\n seen.add(cursor);\n d++;\n cursor = visibleNodes.find((x) => x.id === cursor)?.parentId;\n }\n return d;\n };\n const containers = visibleNodes.filter(isContainer);\n const others = visibleNodes.filter((n) => !isContainer(n));\n containers.sort((a, b) => depth(a) - depth(b));\n return [...containers, ...others];\n }, [visibleNodes]);\n\n return (\n <FlowStoreContext.Provider value={store}>\n <FlowInstanceContext.Provider value={instance}>\n <HandleRegistryContext.Provider value={handleRegistry}>\n <FlowDispatchContext.Provider value={dispatch}>\n <FlowNodeBridgeContext.Provider value={bridge}>\n <div\n ref={containerRef}\n className={cn(\n \"ods-flow-canvas-v2\",\n panGesture && \"ods-flow-canvas-v2--panning\",\n isConnecting && \"ods-flow-canvas-v2--connecting\",\n draggingId && \"ods-flow-canvas-v2--dragging\",\n className,\n )}\n style={{\n position: \"relative\",\n width,\n height,\n overflow: \"hidden\",\n userSelect: \"none\",\n touchAction: \"none\",\n // Cursor: state-driven so it flips instantly with the\n // gesture. CSS `:active` would lag behind pointer-capture.\n cursor: panGesture\n ? \"grabbing\"\n : isConnecting\n ? \"crosshair\"\n : panOnDrag\n ? \"grab\"\n : \"default\",\n ...style,\n }}\n onPointerDown={onCanvasPointerDown}\n onContextMenu={(e) => {\n // Route the right-click to the per-surface handler based on\n // where the pointer landed. Consumers `preventDefault()` to\n // suppress the browser's native menu; we don't do it for\n // them because some workflows prefer the OS menu on pane.\n const t = e.target as HTMLElement;\n const nodeEl = t.closest(\"[data-node-id]\") as HTMLElement | null;\n if (nodeEl && onNodeContextMenu) {\n const id = nodeEl.dataset.nodeId!;\n const node = nodes.find((n) => n.id === id);\n if (node) onNodeContextMenu(e, node);\n return;\n }\n const edgeEl = t.closest(\"[data-edge-id]\") as HTMLElement | null;\n if (edgeEl && onEdgeContextMenu) {\n const id = edgeEl.dataset.edgeId!;\n const edge = edges.find((x) => x.id === id);\n if (edge) onEdgeContextMenu(e, edge);\n return;\n }\n onPaneContextMenu?.(e);\n }}\n data-empty={isEmpty ? \"true\" : undefined}\n >\n {background !== \"none\" && (\n <div\n className={cn(\n \"ods-flow-canvas-v2__grid\",\n `ods-flow-canvas-v2__grid--${background}`,\n )}\n style={\n {\n // Custom property drives the four variants' SCSS.\n \"--ods-flow-grid-size\": `${gridSize * viewport.zoom}px`,\n backgroundPosition: `${viewport.x}px ${viewport.y}px`,\n } as CSSProperties\n }\n />\n )}\n\n <div\n className=\"ods-flow-canvas-v2__viewport\"\n style={{\n position: \"absolute\",\n inset: 0,\n transform: `translate(${viewport.x}px, ${viewport.y}px) scale(${viewport.zoom})`,\n transformOrigin: \"0 0\",\n }}\n >\n <EdgesLayer\n edges={visibleEdges}\n nodes={visibleNodes}\n onSelect={(id) => bridge.selectEdge(id, false)}\n onDelete={(id) => onEdgesChangeRef(id, onEdgesChange)}\n onLabelChange={onEdgeLabelChange}\n ghost={conn ? { start: conn.start, end: conn.end } : null}\n // Bust EdgesLayer's memo when the handle registry\n // changes, so edges recompute geometry against the\n // newly-mounted handles.\n handleVersion={handleVersion}\n />\n\n {orderedNodes.map((node) => {\n const Kind = kinds[node.type] ?? kinds.action;\n if (!Kind) return null;\n return (\n <FlowNode\n key={node.id}\n node={node}\n selected={selectedNodeIds.has(node.id)}\n dragging={draggingId === node.id}\n isConnecting={isConnecting}\n Kind={Kind}\n />\n );\n })}\n </div>\n\n {isEmpty && emptyState && (\n <div className=\"ods-flow-canvas-v2__empty\">{emptyState}</div>\n )}\n\n {children}\n </div>\n </FlowNodeBridgeContext.Provider>\n </FlowDispatchContext.Provider>\n </HandleRegistryContext.Provider>\n </FlowInstanceContext.Provider>\n </FlowStoreContext.Provider>\n );\n}\n\n// Tiny helper — keeps the JSX above clean.\nfunction onEdgesChangeRef(id: string, cb?: (changes: EdgeChange[]) => void) {\n cb?.([change.edge.remove(id)]);\n}\n\n/**\n * Compute auto-resize updates for every container in the graph so each\n * frame encloses its current children + padding.\n *\n * `pending` carries the position / replace changes the canvas is\n * about to dispatch — we PROJECT them onto the current node list\n * before measuring so a drag that just moved a child uses the new\n * position, not the stale committed one. That makes the auto-resize\n * atomic with the drag commit: a single `onNodesChange` call carries\n * both the child's new position AND the parent's new frame.\n *\n * Container frames track their children's bbox in BOTH directions —\n * they grow to fit and shrink when children are removed, floored at\n * `minWidth/minHeight` (the default empty-container size) so a frame\n * never collapses to nothing. A fixed `CONTAINER_DROP_HEADROOM` is\n * kept past the content so there's always room to drop ~2 more nodes\n * before the next grow. The frame also re-positions its top-left to\n * follow the children bbox so children stay visually inside.\n */\n// Spare room the auto-resize keeps PAST the children's bbox so a couple\n// more nodes can be dropped before the frame has to grow again. Sized to\n// roughly two default node rows tall and one node-width of slack wide —\n// the \"+2 nodes of drop room\" a subflow container should always offer.\nconst CONTAINER_DROP_HEADROOM_W = 220;\nconst CONTAINER_DROP_HEADROOM_H = 2 * 128;\n\nfunction computeContainerAutoResize(\n nodes: WorkflowNode[],\n pending: NodeChange[],\n padding: number,\n minWidth: number,\n minHeight: number,\n): NodeChange[] {\n // Apply pending changes to a transient view of the node list. We\n // care about: `position` (child moves), `replace` (reparent), and\n // `add` (newly-inserted nodes are projected too). Other change\n // types don't affect bbox math.\n const projected = new Map<string, WorkflowNode>();\n for (const n of nodes) projected.set(n.id, n);\n for (const c of pending) {\n if (c.type === \"position\" && c.position) {\n const cur = projected.get(c.id);\n if (cur) projected.set(c.id, { ...cur, position: c.position });\n } else if (c.type === \"replace\" && c.item) {\n projected.set(c.id, { ...projected.get(c.id), ...c.item } as WorkflowNode);\n } else if (c.type === \"add\" && c.item) {\n projected.set((c.item as WorkflowNode).id, c.item as WorkflowNode);\n }\n }\n\n const HEADER = 56; // breathing room above the first child\n const out: NodeChange[] = [];\n for (const parent of projected.values()) {\n if (!isContainerType(parent.type)) continue;\n const children: WorkflowNode[] = [];\n for (const n of projected.values()) {\n if (n.parentId === parent.id) children.push(n);\n }\n if (children.length === 0) {\n // Emptied container — collapse it back to the default floor size.\n // Position is left alone (no children to track).\n const curW = parent.width ?? 480;\n const curH = parent.height ?? 240;\n if (curW !== minWidth || curH !== minHeight) {\n out.push(change.node.dimensions(parent.id, { width: minWidth, height: minHeight }));\n }\n continue;\n }\n\n let minX = Number.POSITIVE_INFINITY;\n let minY = Number.POSITIVE_INFINITY;\n let maxX = Number.NEGATIVE_INFINITY;\n let maxY = Number.NEGATIVE_INFINITY;\n for (const c of children) {\n const cw = c.width ?? 240;\n const ch = c.height ?? 96;\n if (c.position.x < minX) minX = c.position.x;\n if (c.position.y < minY) minY = c.position.y;\n if (c.position.x + cw > maxX) maxX = c.position.x + cw;\n if (c.position.y + ch > maxY) maxY = c.position.y + ch;\n }\n const targetX = minX - padding;\n const targetY = minY - padding - HEADER;\n const curW = parent.width ?? 480;\n const curH = parent.height ?? 240;\n // Fit children + padding + drop headroom, floored at the container's\n // default size. This both GROWS and SHRINKS: a frame that's lost\n // children collapses back toward `minWidth/minHeight`, and one that's\n // gained them grows to keep ~2 nodes of empty drop room. The headroom\n // is what makes \"drop two more before it resizes\" hold.\n const fitW = maxX - minX + padding * 2 + CONTAINER_DROP_HEADROOM_W;\n const fitH = maxY - minY + padding * 2 + HEADER + CONTAINER_DROP_HEADROOM_H;\n const nextW = Math.max(minWidth, fitW);\n const nextH = Math.max(minHeight, fitH);\n const positionDirty = parent.position.x !== targetX || parent.position.y !== targetY;\n const sizeDirty = curW !== nextW || curH !== nextH;\n if (positionDirty) {\n out.push(change.node.position(parent.id, { x: targetX, y: targetY }, false));\n }\n if (sizeDirty) {\n out.push(change.node.dimensions(parent.id, { width: nextW, height: nextH }));\n }\n }\n return out;\n}\n\n// ────────────────────────────────────────────────────────────────────────\n// EdgesLayer — memoised. Re-renders only when edges/nodes arrays or ghost\n// position change. Edges within use memo on (edge, source/target position,\n// edge.selected/animated) so dragging one node only re-renders edges\n// connected to that node.\n// ────────────────────────────────────────────────────────────────────────\nconst EdgesLayer = memo(function EdgesLayer({\n edges,\n nodes,\n onSelect,\n onDelete,\n onLabelChange,\n ghost,\n handleVersion: _handleVersion,\n}: {\n edges: WorkflowEdge[];\n nodes: WorkflowNode[];\n onSelect: (id: string) => void;\n onDelete: (id: string) => void;\n onLabelChange?: (id: string, label: string) => void;\n ghost: { start: Position; end: Position } | null;\n /** Bust-cache token that flips whenever the handle registry mutates.\n * React.memo's default shallow compare picks up the change and re-\n * renders the layer; FlowEdge inside reads the now-up-to-date\n * registry on the re-render. */\n handleVersion: number;\n}) {\n return (\n <svg\n className=\"ods-flow-canvas-v2__edges\"\n style={{ position: \"absolute\", inset: 0, overflow: \"visible\", pointerEvents: \"none\" }}\n width=\"100%\"\n height=\"100%\"\n >\n <g style={{ pointerEvents: \"auto\" }}>\n {edges.map((edge) => (\n <FlowEdge\n key={edge.id}\n edge={edge}\n nodes={nodes}\n onSelect={onSelect}\n onDelete={onDelete}\n onLabelChange={onLabelChange}\n handleVersion={_handleVersion}\n />\n ))}\n </g>\n {ghost && (\n <path\n d={`M ${ghost.start.x} ${ghost.start.y} L ${ghost.end.x} ${ghost.end.y}`}\n stroke=\"var(--ods-accent, #4f46e5)\"\n strokeWidth={1.5}\n strokeDasharray=\"4 4\"\n fill=\"none\"\n />\n )}\n </svg>\n );\n});\n\n// Type re-export so consumers don't need to import from a deeper path.\nexport type { BuiltInNodeData };\n","// ════════════════════════════════════════════════════════════════════════\n// FlowStore — per-canvas state, exposed only via narrow selector hooks.\n// ════════════════════════════════════════════════════════════════════════\n// We deliberately do NOT export the store instance (see ADR-005). The\n// store lives behind a React context; descendants read via\n// `useFlowSelector(selector)` which under the hood is\n// `useSyncExternalStore` against a single `subscribe` channel.\n//\n// The store is the single source of truth for runtime state\n// (selection, viewport, in-flight connection). Node/edge data is mirrored\n// from the controlled props each render; the store keeps a frozen\n// snapshot so descendants don't have to thread `nodes` / `edges` through\n// component trees.\n\nimport type {\n ConnectStartParams,\n FlowStoreSnapshot,\n Viewport,\n WorkflowEdge,\n WorkflowNode,\n} from \"../editor\";\n\ntype Listener = () => void;\n\nexport interface FlowStore {\n /** React subscription hook contract — used by `useSyncExternalStore`. */\n subscribe(listener: Listener): () => void;\n /** Cheap snapshot getter — must return the same ref between mutations. */\n getSnapshot(): FlowStoreSnapshot;\n /** Imperative setters — called by the canvas internals, never by consumers. */\n setNodes(nodes: WorkflowNode[]): void;\n setEdges(edges: WorkflowEdge[]): void;\n setViewport(viewport: Viewport): void;\n setSelection(nodes: ReadonlySet<string>, edges: ReadonlySet<string>): void;\n setConnection(connection: ConnectStartParams | null): void;\n}\n\nexport interface CreateFlowStoreOptions {\n initialNodes?: WorkflowNode[];\n initialEdges?: WorkflowEdge[];\n initialViewport?: Viewport;\n}\n\nconst DEFAULT_VIEWPORT: Viewport = { x: 0, y: 0, zoom: 1 };\n\n/**\n * Build a FlowStore for one canvas instance. Designed to be created in\n * `useState(() => createFlowStore())` inside FlowCanvas so a single\n * `<FlowCanvas>` owns exactly one store and unmounting cleans it up.\n */\nexport function createFlowStore({\n initialNodes = [],\n initialEdges = [],\n initialViewport = DEFAULT_VIEWPORT,\n}: CreateFlowStoreOptions = {}): FlowStore {\n let snapshot: FlowStoreSnapshot = {\n nodes: initialNodes,\n edges: initialEdges,\n viewport: initialViewport,\n selectedNodeIds: EMPTY_SET,\n selectedEdgeIds: EMPTY_SET,\n connection: null,\n };\n\n const listeners = new Set<Listener>();\n const emit = () => {\n for (const l of listeners) l();\n };\n\n const subscribe = (listener: Listener) => {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n };\n\n // Replace the snapshot reference on every change so React's\n // `useSyncExternalStore` triggers a re-render. We never mutate in place.\n const replace = (patch: Partial<FlowStoreSnapshot>) => {\n snapshot = { ...snapshot, ...patch };\n emit();\n };\n\n return {\n subscribe,\n getSnapshot: () => snapshot,\n setNodes(nodes) {\n if (nodes === snapshot.nodes) return;\n replace({ nodes });\n },\n setEdges(edges) {\n if (edges === snapshot.edges) return;\n replace({ edges });\n },\n setViewport(viewport) {\n if (\n viewport.x === snapshot.viewport.x &&\n viewport.y === snapshot.viewport.y &&\n viewport.zoom === snapshot.viewport.zoom\n ) {\n return;\n }\n replace({ viewport });\n },\n setSelection(selectedNodeIds, selectedEdgeIds) {\n replace({ selectedNodeIds, selectedEdgeIds });\n },\n setConnection(connection) {\n if (connection === snapshot.connection) return;\n replace({ connection });\n },\n };\n}\n\nconst EMPTY_SET: ReadonlySet<string> = new Set();\n","// ════════════════════════════════════════════════════════════════════════\n// Collision avoidance — keep nodes from overlapping each other (or from\n// landing closer than a configurable minimum gap).\n// ════════════════════════════════════════════════════════════════════════\n//\n// The function below is a pure axis-aligned bounding-box (AABB) \"minimum\n// translation vector\" resolver. Given a proposed position for one node\n// and a set of other nodes, it shifts the proposed position along the\n// axis of *smallest* overlap correction until either (a) no node is\n// closer than `gap` pixels, or (b) the iteration cap is reached.\n//\n// Why MTV? It produces the smoothest \"magnet snap\" UX — when you nudge a\n// node toward a neighbour, it slides along the contact edge rather than\n// flinging away. The iteration cap (8 by default) handles cascading\n// resolutions where pushing out of one node lands in another.\n\nimport type { Position, WorkflowNode } from \"../editor\";\nimport { DEFAULT_NODE_WIDTH, effectiveHeight } from \"./geometry\";\n\nexport interface CollisionOptions {\n /** Minimum gap (px) the dragged node must keep from each other node.\n *\n * - `gap >= 0` — the resolver is **enabled**. `gap === 0` means\n * \"no overlap, zero buffer\" (strict no-overlap). `gap > 0` enforces\n * a buffer of that many pixels.\n * - `gap < 0` — the resolver is **disabled** (returns the proposed\n * position unchanged). This is the no-op sentinel used by\n * consumers that haven't opted into magnet behaviour. */\n gap: number;\n /** Cap iterative resolutions — prevents infinite loops in pathological\n * geometries (e.g. four nodes hugging a single corner). Default 8. */\n maxIterations?: number;\n /** Node ids that the resolver should ignore — typically the dragged\n * node itself plus its descendants (so a parent doesn't collide with\n * its own children) and its ancestors (so a child doesn't collide\n * with its containing group). */\n exclude?: Set<string>;\n /** When true, only consider nodes that share the same `parentId` as\n * the dragged node (i.e. its siblings). When false, all non-excluded\n * nodes participate. Defaults to true — this is the \"rooms\" model\n * where children of group A never collide with children of group B\n * even if their bboxes overlap in flow space. */\n scopeToSiblings?: boolean;\n}\n\n/**\n * Adjust a proposed (flow-space) position so the node's bbox stays at\n * least `gap` pixels away from every other (non-excluded) node's bbox.\n *\n * The function does NOT mutate the input nodes; it returns a new\n * `Position`. The caller is responsible for emitting the resulting\n * change via `onNodesChange` — collision resolution doesn't dispatch\n * anything on its own.\n */\nexport function resolveNodeCollisions(\n node: WorkflowNode,\n proposed: Position,\n others: WorkflowNode[],\n opts: CollisionOptions,\n): Position {\n const { gap, maxIterations = 8, exclude, scopeToSiblings = true } = opts;\n if (gap < 0 || others.length === 0) return proposed;\n\n const w = node.width ?? DEFAULT_NODE_WIDTH;\n const h = effectiveHeight(node);\n const parentId = node.parentId;\n\n // Pre-filter the candidate list once — keeps the per-iteration loop tight.\n const candidates = others.filter((o) => {\n if (o.id === node.id) return false;\n if (o.hidden) return false;\n if (exclude?.has(o.id)) return false;\n if (scopeToSiblings && (o.parentId ?? undefined) !== (parentId ?? undefined)) {\n return false;\n }\n return true;\n });\n if (candidates.length === 0) return proposed;\n\n let cur = proposed;\n\n for (let iter = 0; iter < maxIterations; iter++) {\n // Find the colliding pair with the SMALLEST overlap correction and\n // resolve that one this iteration. Doing one push per iteration keeps\n // the displacement minimal and lets cascading shifts settle naturally.\n let bestOverlap = Number.POSITIVE_INFINITY;\n let bestPushX = 0;\n let bestPushY = 0;\n let hit = false;\n\n // Inflate our rect by `gap` so any node within `gap` registers as\n // overlap. We add the full gap to one side (rather than gap/2 to\n // both sides) so the resulting min-distance matches user intuition:\n // \"at least `gap` pixels between the two visual edges.\"\n const aLeft = cur.x - gap;\n const aRight = cur.x + w + gap;\n const aTop = cur.y - gap;\n const aBottom = cur.y + h + gap;\n\n for (const o of candidates) {\n const ow = o.width ?? DEFAULT_NODE_WIDTH;\n const oh = effectiveHeight(o);\n const bLeft = o.position.x;\n const bRight = o.position.x + ow;\n const bTop = o.position.y;\n const bBottom = o.position.y + oh;\n\n const overlapX = Math.min(aRight, bRight) - Math.max(aLeft, bLeft);\n const overlapY = Math.min(aBottom, bBottom) - Math.max(aTop, bTop);\n if (overlapX <= 0 || overlapY <= 0) continue;\n\n // Pick the axis with the smaller overlap — that's the cheaper push.\n // Direction: if our centre is \"before\" their centre on that axis,\n // push backward; otherwise push forward.\n let pushX = 0;\n let pushY = 0;\n let overlap: number;\n if (overlapX < overlapY) {\n const aCx = cur.x + w / 2;\n const bCx = o.position.x + ow / 2;\n pushX = aCx < bCx ? -overlapX : overlapX;\n overlap = overlapX;\n } else {\n const aCy = cur.y + h / 2;\n const bCy = o.position.y + oh / 2;\n pushY = aCy < bCy ? -overlapY : overlapY;\n overlap = overlapY;\n }\n\n if (overlap < bestOverlap) {\n bestOverlap = overlap;\n bestPushX = pushX;\n bestPushY = pushY;\n hit = true;\n }\n }\n\n if (!hit) break;\n cur = { x: cur.x + bestPushX, y: cur.y + bestPushY };\n }\n\n return cur;\n}\n"],"mappings":"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","names":["Badge","forwardRef","jsx","jsxs","forwardRef","Checkbox","forwardRef","useRef","jsx","jsxs","forwardRef","Banner","useRef","forwardRef","useId","jsx","jsxs","forwardRef","PasswordInput","useId","CheckmarkIcon","forwardRef","useEffect","useImperativeHandle","useMemo","useRef","useState","Fragment","jsx","jsxs","forwardRef","CodeEditor","useRef","useImperativeHandle","useState","useMemo","useEffect","CheckmarkIcon","useEffect","useId","useMemo","useRef","useState","jsx","jsxs","useState","useRef","useId","useMemo","useEffect","jsx","jsxs","useId","useState","jsx","jsxs","useState","useId","forwardRef","jsx","jsxs","forwardRef","InlineMessage","motion","useReducedMotion","forwardRef","useCallback","useId","useState","jsx","jsxs","useId","useReducedMotion","useState","useCallback","motion","forwardRef","CheckmarkIcon","ChevronRightIcon","CopyIcon","forwardRef","useEffect","useMemo","useState","Fragment","jsx","jsxs","forwardRef","JsonViewer","useState","useMemo","ChevronRightIcon","CheckmarkIcon","CopyIcon","useEffect","distance","bezierPath","distance","forwardRef","useRef","jsx","jsxs","forwardRef","Switch","useRef","useContext","useMemo","createContext","useContext","useContext","useMemo","forwardRef","useCallback","useId","AddIcon","jsx","jsxs","forwardRef","NumberInput","useId","useCallback","AddIcon","motion","useCallback","useEffect","useId","useMemo","useRef","useState","jsx","jsxs","useRef","useEffect","motion","useId","useState","useMemo","useCallback","change","useEffect","useId","useRef","useState","createContext","useContext","jsx","jsxs","useId","useState","useRef","useEffect","offsetAlongSide","createContext","useContext","useEffect","useMemo","useRef","createContext","useContext","jsx","useRef","useEffect","useMemo","useEffect","useRef","jsx","jsxs","useRef","useEffect","useRef","jsx","useRef","useContext","jsx","jsxs","useContext","jsx","jsxs","memo","useCallback","useEffect","useMemo","useRef","useState","jsx","jsxs","DEFAULT_VIEWPORT","useState","useEffect","useMemo","useRef","useCallback","c","width","height","nodes","edges","curW","curH","memo","EdgesLayer"]}