@snowcone-app/canvas 0.23.0 → 0.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/ERROR_CONTRACT.md +638 -0
  2. package/README.md +2 -1
  3. package/STYLING_CONTRACT.md +59 -8
  4. package/dist/{CanvasRenderer-6_HhR4-q.js → CanvasRenderer-yszzrDfo.js} +4 -4
  5. package/dist/{CanvasRenderer-6_HhR4-q.js.map → CanvasRenderer-yszzrDfo.js.map} +1 -1
  6. package/dist/{CanvasStateV1-DmZ1Qvvn.js → CanvasStateV1-BTbCD_xC.js} +3 -3
  7. package/dist/{CanvasStateV1-DmZ1Qvvn.js.map → CanvasStateV1-BTbCD_xC.js.map} +1 -1
  8. package/dist/{ContextualToolbars-BDEt9ND0.js → ContextualToolbars-BHjYsril.js} +6 -6
  9. package/dist/{ContextualToolbars-BDEt9ND0.js.map → ContextualToolbars-BHjYsril.js.map} +1 -1
  10. package/dist/{EditorCanvasImpl-Ckg7WO2j.js → EditorCanvasImpl-Ui8Ceb-h.js} +8 -8
  11. package/dist/{EditorCanvasImpl-Ckg7WO2j.js.map → EditorCanvasImpl-Ui8Ceb-h.js.map} +1 -1
  12. package/dist/{ExportManager-DoU4VK6h.js → ExportManager-BTcyj4cf.js} +2 -2
  13. package/dist/{ExportManager-DoU4VK6h.js.map → ExportManager-BTcyj4cf.js.map} +1 -1
  14. package/dist/{FontAnalyzer-CwIpgTGd.js → FontAnalyzer-EF3gLPr8.js} +30 -20
  15. package/dist/{FontAnalyzer-CwIpgTGd.js.map → FontAnalyzer-EF3gLPr8.js.map} +1 -1
  16. package/dist/{ImagePanel-BwqFDKvW.js → ImagePanel-CIk6z41z.js} +6 -6
  17. package/dist/{ImagePanel-BwqFDKvW.js.map → ImagePanel-CIk6z41z.js.map} +1 -1
  18. package/dist/{SnowconeCanvas-D1sLcIja.js → SnowconeCanvas-DuWALOAt.js} +10 -10
  19. package/dist/{SnowconeCanvas-D1sLcIja.js.map → SnowconeCanvas-DuWALOAt.js.map} +1 -1
  20. package/dist/{UnifiedFontService-CC3CSmH5.js → UnifiedFontService-CHVYDBDW.js} +869 -836
  21. package/dist/{UnifiedFontService-CC3CSmH5.js.map → UnifiedFontService-CHVYDBDW.js.map} +1 -1
  22. package/dist/advanced.mjs +14 -14
  23. package/dist/api/embed.d.ts +6 -2
  24. package/dist/components/editor/EditorLoadingOverlay.d.ts +12 -0
  25. package/dist/components/editor/EditorPlacements.d.ts +14 -0
  26. package/dist/components/editor/EditorPreview.d.ts +32 -8
  27. package/dist/components/editor/EditorRoot.d.ts +12 -0
  28. package/dist/components/editor/PreviewPrismOverlay.d.ts +23 -0
  29. package/dist/components/editor/RootInternals.d.ts +31 -0
  30. package/dist/components/editor/editorAudit.d.ts +66 -0
  31. package/dist/components/editor/index.d.ts +14 -0
  32. package/dist/components/editor/usePlacements.d.ts +14 -0
  33. package/dist/components/embed-realtime/context.d.ts +11 -2
  34. package/dist/components/embed-realtime/validateEmbed.d.ts +20 -1
  35. package/dist/contexts/EditorContext.d.ts +34 -0
  36. package/dist/core/HybridHistoryManager.d.ts +7 -0
  37. package/dist/core/elementGuards.d.ts +19 -0
  38. package/dist/{custom-icons-BW6hqmkL.js → custom-icons-CcLMyybv.js} +7 -7
  39. package/dist/{custom-icons-BW6hqmkL.js.map → custom-icons-CcLMyybv.js.map} +1 -1
  40. package/dist/design/design-builder.d.ts +41 -3
  41. package/dist/design/product-config.d.ts +10 -0
  42. package/dist/{design-builder-2VUjfmdt.js → design-builder-cZY958Rw.js} +109 -61
  43. package/dist/design-builder-cZY958Rw.js.map +1 -0
  44. package/dist/editorErrors-BhrZ_nwj.js +1219 -0
  45. package/dist/editorErrors-BhrZ_nwj.js.map +1 -0
  46. package/dist/embed-CJswRZte.js +1586 -0
  47. package/dist/embed-CJswRZte.js.map +1 -0
  48. package/dist/embed.mjs +42 -34
  49. package/dist/errors/editorError.d.ts +29 -1
  50. package/dist/{guards-8rkFAMBs.js → guards-DIX8aXWM.js} +2 -2
  51. package/dist/{guards-8rkFAMBs.js.map → guards-DIX8aXWM.js.map} +1 -1
  52. package/dist/hooks/elementPatch.d.ts +96 -0
  53. package/dist/hooks/useCommands.d.ts +20 -0
  54. package/dist/index.mjs +8 -8
  55. package/dist/internals.mjs +9 -9
  56. package/dist/style.css +1 -1
  57. package/dist/template-fields-BXl29sgh.js +716 -0
  58. package/dist/template-fields-BXl29sgh.js.map +1 -0
  59. package/dist/testing.mjs +4 -4
  60. package/dist/{usePieceGuideBundle-CbJJg66S.js → usePieceGuideBundle-DE21DQGZ.js} +2 -2
  61. package/dist/{usePieceGuideBundle-CbJJg66S.js.map → usePieceGuideBundle-DE21DQGZ.js.map} +1 -1
  62. package/dist/{validation-C9Fe9ahK.js → validation-DGXAQmUC.js} +11 -11
  63. package/dist/{validation-C9Fe9ahK.js.map → validation-DGXAQmUC.js.map} +1 -1
  64. package/example/package.json +1 -1
  65. package/llms.txt +3 -0
  66. package/package.json +7 -4
  67. package/dist/design-builder-2VUjfmdt.js.map +0 -1
  68. package/dist/editorErrors-B2mb1sVN.js +0 -1208
  69. package/dist/editorErrors-B2mb1sVN.js.map +0 -1
  70. package/dist/embed-DxsaqZJF.js +0 -1226
  71. package/dist/embed-DxsaqZJF.js.map +0 -1
  72. package/dist/template-fields-CQ6n2P4V.js +0 -548
  73. package/dist/template-fields-CQ6n2P4V.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"custom-icons-BW6hqmkL.js","sources":["../src/vendor/ui/primitives/input.tsx","../src/vendor/ui/primitives/label.tsx","../src/vendor/ui/primitives/tabs.tsx","../src/vendor/ui/primitives/text-field.tsx","../src/components/ui/custom-icons.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { cn } from '../lib/utils';\nimport { useSurface } from './surface';\n\nexport interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {\n /** Whether the input is in an invalid state */\n isInvalid?: boolean;\n /** Content to display at the start of the input */\n startContent?: React.ReactNode;\n /** Content to display at the end of the input */\n endContent?: React.ReactNode;\n /**\n * Visual variant - auto-detected from Surface context, or can be set explicitly\n * - `default`: Standard field styling for forms (bg-field)\n * - `filled`: Field on elevated surface (bg-field-on-surface)\n * - `subtle`: Blends with buttons/tabs in toolbars (bg-default)\n */\n variant?: 'default' | 'filled' | 'subtle';\n}\n\nconst Input = React.forwardRef<HTMLInputElement, InputProps>(\n (\n {\n className,\n type,\n isInvalid,\n startContent,\n endContent,\n disabled,\n readOnly,\n required,\n variant,\n ...props\n },\n ref\n ) => {\n // Auto-detect variant from Surface context\n const surface = useSurface();\n const isOnSurface = surface.variant === 'default' || surface.variant === 'secondary';\n const effectiveVariant = variant ?? (isOnSurface ? 'filled' : 'default');\n\n const inputElement = (\n <input\n type={type}\n className={cn(\n 'sc:flex sc:h-10 sc:w-full sc:rounded-input sc:px-2.5 sc:py-1.5 sc:text-sm sc:appearance-none',\n 'sc:text-foreground sc:border-none',\n 'sc:file:border-0 sc:file:bg-transparent sc:file:text-sm sc:file:font-medium sc:file:text-foreground',\n 'sc:placeholder:text-foreground/50',\n 'sc:transition-shadow sc:duration-200 sc:ease-out sc:focus-visible:outline-none sc:focus:ring-2 sc:focus:ring-focus sc:focus:ring-offset-1 sc:focus:ring-offset-background',\n 'sc:disabled:cursor-not-allowed sc:disabled:opacity-50',\n // Variant styles - semantic: field on page vs field on surface vs toolbar\n effectiveVariant === 'default' && 'sc:bg-field sc:shadow-soft sc:dark:shadow-none',\n effectiveVariant === 'filled' && 'sc:bg-[var(--color-field-on-surface)]',\n effectiveVariant === 'subtle' && 'sc:bg-default sc:dark:bg-[var(--color-default-on-surface)]',\n isInvalid && 'sc:ring-2 sc:ring-danger sc:focus-visible:ring-danger',\n startContent && 'sc:pl-10',\n endContent && 'sc:pr-10',\n className\n )}\n ref={ref}\n disabled={disabled}\n readOnly={readOnly}\n required={required}\n aria-invalid={isInvalid}\n {...props}\n />\n );\n\n if (startContent || endContent) {\n return (\n <div className=\"sc:relative\">\n {startContent && (\n <div className=\"sc:absolute sc:left-3 sc:top-1/2 sc:-translate-y-1/2 sc:text-foreground sc:opacity-40\">{startContent}</div>\n )}\n {inputElement}\n {endContent && (\n <div className=\"sc:absolute sc:right-3 sc:top-1/2 sc:-translate-y-1/2 sc:text-foreground sc:opacity-40\">{endContent}</div>\n )}\n </div>\n );\n }\n\n return inputElement;\n }\n);\nInput.displayName = 'Input';\n\nexport { Input };\n","'use client';\n\nimport * as React from 'react';\nimport * as LabelPrimitive from '@radix-ui/react-label';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { cn } from '../lib/utils';\n\nconst labelVariants = cva(\n 'sc:block sc:text-sm sc:leading-none sc:text-foreground sc:peer-disabled:cursor-not-allowed sc:peer-disabled:opacity-70 sc:font-label'\n);\n\nconst Label = React.forwardRef<\n React.ElementRef<typeof LabelPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> & VariantProps<typeof labelVariants>\n>(({ className, ...props }, ref) => (\n <LabelPrimitive.Root ref={ref} className={cn(labelVariants(), className)} {...props} />\n));\nLabel.displayName = LabelPrimitive.Root.displayName;\n\nexport { Label };\n","\"use client\";\n\n'use client';\n\nimport * as React from 'react';\nimport * as TabsPrimitive from '@radix-ui/react-tabs';\nimport { cn } from '../lib/utils';\nimport { useSurface } from './surface';\n\ninterface TabsProps\n extends Omit<React.ComponentPropsWithoutRef<typeof TabsPrimitive.Root>, 'value' | 'onValueChange'> {\n value?: string;\n onValueChange?: (value: string) => void;\n}\n\nconst TabsRoot = React.forwardRef<React.ElementRef<typeof TabsPrimitive.Root>, TabsProps>(\n ({ value, onValueChange, ...props }, ref) => (\n <TabsPrimitive.Root ref={ref} value={value} onValueChange={onValueChange} {...props} />\n )\n);\nTabsRoot.displayName = 'Tabs';\n\nconst TabsList = React.forwardRef<\n React.ElementRef<typeof TabsPrimitive.List>,\n React.ComponentPropsWithoutRef<typeof TabsPrimitive.List>\n>(({ className, children, ...props }, ref) => {\n const listRef = React.useRef<HTMLDivElement>(null);\n const [indicatorStyle, setIndicatorStyle] = React.useState<React.CSSProperties>({\n opacity: 0,\n });\n\n // Update indicator position when active tab changes\n React.useEffect(() => {\n const listElement = listRef.current;\n if (!listElement) return;\n\n const updateIndicator = () => {\n const activeTab = listElement.querySelector('[data-state=\"active\"]') as HTMLElement;\n if (activeTab) {\n const listRect = listElement.getBoundingClientRect();\n const tabRect = activeTab.getBoundingClientRect();\n\n setIndicatorStyle({\n width: tabRect.width,\n height: tabRect.height,\n left: tabRect.left - listRect.left,\n opacity: 1,\n });\n }\n };\n\n // Initial position\n updateIndicator();\n\n // Use MutationObserver to detect when active tab changes\n const observer = new MutationObserver((mutations) => {\n for (const mutation of mutations) {\n if (mutation.type === 'attributes' && mutation.attributeName === 'data-state') {\n updateIndicator();\n break;\n }\n }\n });\n\n // Observe all trigger elements for data-state changes\n const triggers = listElement.querySelectorAll('[role=\"tab\"]');\n triggers.forEach((trigger) => {\n observer.observe(trigger, { attributes: true, attributeFilter: ['data-state'] });\n });\n\n // Also update on resize\n const resizeObserver = new ResizeObserver(updateIndicator);\n resizeObserver.observe(listElement);\n\n return () => {\n observer.disconnect();\n resizeObserver.disconnect();\n };\n }, [children]);\n\n return (\n <TabsPrimitive.List\n ref={(node) => {\n // Handle both refs\n (listRef as React.MutableRefObject<HTMLDivElement | null>).current = node;\n if (typeof ref === 'function') {\n ref(node);\n } else if (ref) {\n ref.current = node;\n }\n }}\n className={cn(\n 'sc:relative sc:inline-flex sc:h-10 sc:items-center sc:justify-center sc:rounded-full sc:px-1 sc:text-muted-foreground',\n // Consistent bg-default matches Button secondary variant for toolbar harmony\n 'sc:bg-default sc:dark:bg-[var(--color-default-on-surface)]',\n className\n )}\n {...props}\n >\n {/* Animated sliding indicator. In dark mode the previous `bg-muted`\n value resolved to the same color as `bg-default` on the container,\n so the active tab was invisible without relying purely on\n shadow-md. `bg-popover` lands ~0.08 lightness above `bg-default`\n in dark mode for a clearly visible elevation. */}\n <span\n className=\"sc:absolute sc:top-1/2 sc:-translate-y-1/2 sc:rounded-full sc:bg-surface sc:dark:bg-popover sc:shadow-md sc:transition-[left,width,opacity]\"\n style={{\n ...indicatorStyle,\n transitionDuration: '350ms',\n transitionTimingFunction: 'cubic-bezier(0.22, 1, 0.36, 1)',\n }}\n aria-hidden=\"true\"\n />\n {children}\n </TabsPrimitive.List>\n );\n});\nTabsList.displayName = TabsPrimitive.List.displayName;\n\ninterface TabsTriggerProps extends Omit<React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>, 'value'> {\n // HeroUI uses 'id' for tab identification, Radix uses 'value'\n // At least one must be provided\n id?: string;\n value?: string;\n}\n\nconst TabsTrigger = React.forwardRef<React.ElementRef<typeof TabsPrimitive.Trigger>, TabsTriggerProps>(\n ({ className, id, value, ...props }, ref) => {\n const { variant: surfaceVariant } = useSurface();\n const isOnSurface = surfaceVariant === 'default' || surfaceVariant === 'secondary';\n\n return (\n <TabsPrimitive.Trigger\n ref={ref}\n value={id ?? value ?? ''}\n className={cn(\n 'sc:relative sc:z-10 sc:inline-flex sc:h-8 sc:items-center sc:justify-center sc:gap-2 sc:whitespace-nowrap sc:rounded-full sc:px-4 sc:text-sm sc:font-label',\n 'sc:transition-[color,opacity]',\n 'sc:focus-visible:outline-none sc:focus-visible:ring-2 sc:focus-visible:ring-focus sc:focus-visible:ring-offset-2',\n 'sc:disabled:pointer-events-none sc:disabled:opacity-50',\n 'sc:data-[state=active]:text-foreground sc:data-[state=active]:opacity-100',\n // Inactive tabs use element opacity (not color opacity) to avoid SVG path overlap issues\n isOnSurface\n ? 'sc:data-[state=inactive]:text-foreground sc:data-[state=inactive]:opacity-30 sc:data-[state=inactive]:hover:opacity-50'\n : 'sc:data-[state=inactive]:text-foreground sc:data-[state=inactive]:opacity-50 sc:data-[state=inactive]:hover:opacity-70',\n className\n )}\n {...props}\n />\n );\n }\n);\nTabsTrigger.displayName = TabsPrimitive.Trigger.displayName;\n\ninterface TabsContentProps extends Omit<React.ComponentPropsWithoutRef<typeof TabsPrimitive.Content>, 'value'> {\n // HeroUI uses 'id' for panel identification, Radix uses 'value'\n // At least one must be provided\n id?: string;\n value?: string;\n}\n\nconst TabsContent = React.forwardRef<React.ElementRef<typeof TabsPrimitive.Content>, TabsContentProps>(\n ({ className, id, value, ...props }, ref) => (\n <TabsPrimitive.Content\n ref={ref}\n value={id ?? value ?? ''}\n className={cn(\n 'sc:mt-2 sc:ring-offset-background sc:focus-visible:outline-none sc:focus-visible:ring-2 sc:focus-visible:ring-focus sc:focus-visible:ring-offset-2',\n className\n )}\n {...props}\n />\n )\n);\nTabsContent.displayName = TabsPrimitive.Content.displayName;\n\n// HeroUI ListContainer - wrapper for the tabs list (passthrough div)\nconst TabsListContainer = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n ({ className, ...props }, ref) => <div ref={ref} className={className} {...props} />\n);\nTabsListContainer.displayName = 'TabsListContainer';\n\n// HeroUI Tab - alias for TabsTrigger\nconst TabsTab = TabsTrigger;\n\n// HeroUI Panel - alias for TabsContent\nconst TabsPanel = TabsContent;\n\n// HeroUI Indicator - now rendered automatically by TabsList, this is a no-op\nconst TabsIndicator = () => null;\n\n// Create compound component with all aliases\nconst TabsBase = TabsRoot;\n\n// HeroUI-compatible compound component\nconst Tabs = Object.assign(TabsBase, {\n List: TabsList,\n ListContainer: TabsListContainer,\n Tab: TabsTab,\n Trigger: TabsTrigger,\n Panel: TabsPanel,\n Content: TabsContent,\n Indicator: TabsIndicator,\n});\n\nexport { Tabs, TabsList, TabsTrigger, TabsContent, TabsRoot };\n","'use client';\n\nimport * as React from 'react';\nimport { cn } from '../lib/utils';\n\nexport interface TextFieldProps extends React.HTMLAttributes<HTMLDivElement> {\n /**\n * Accessible label for the input.\n * If not provided via children, use aria-label on the div.\n */\n 'aria-label'?: string;\n /**\n * Error state - applies error styling to children inputs\n */\n isInvalid?: boolean;\n /**\n * Disabled state - disables all children inputs\n */\n disabled?: boolean;\n /**\n * Required state - marks all children inputs as required\n */\n required?: boolean;\n}\n\n/**\n * TextField - A wrapper component that groups Label and Input together.\n *\n * Groups Label and Input with a convenient wrapper that can propagate\n * disabled, required, and invalid states to child inputs.\n *\n * @example\n * ```tsx\n * <TextField>\n * <Label>Email</Label>\n * <Input type=\"email\" placeholder=\"Enter email...\" />\n * </TextField>\n * ```\n */\nconst TextField = React.forwardRef<HTMLDivElement, TextFieldProps>(\n ({ className, children, isInvalid, disabled, required, ...props }, ref) => {\n // Clone children to pass through state props to Input/Textarea children\n const enhancedChildren = React.Children.map(children, (child) => {\n if (!React.isValidElement(child)) return child;\n\n // Get the display name or type name to check if it's an input component\n const childType = child.type;\n const displayName =\n typeof childType === 'function'\n ? (childType as React.ComponentType).displayName || childType.name\n : typeof childType === 'string'\n ? childType\n : '';\n\n // Check if this is an input-like element that should receive state props\n const isInputElement =\n displayName === 'Input' ||\n displayName === 'Textarea' ||\n displayName === 'TextArea' ||\n displayName === 'input' ||\n displayName === 'textarea';\n\n if (isInputElement) {\n const childProps = child.props as Record<string, unknown>;\n return React.cloneElement(child as React.ReactElement<Record<string, unknown>>, {\n isInvalid: (childProps.isInvalid as boolean) ?? isInvalid,\n disabled: (childProps.disabled as boolean) ?? disabled,\n required: (childProps.required as boolean) ?? required,\n });\n }\n\n return child;\n });\n\n return (\n <div ref={ref} className={cn('sc:flex sc:flex-col sc:gap-1.5', className)} {...props}>\n {enhancedChildren}\n </div>\n );\n }\n);\nTextField.displayName = 'TextField';\n\nexport { TextField };\n","/**\n * Custom Icons - Centered versions of icons from various sets\n *\n * These are copies of icons with adjusted viewBox to center properly.\n * Use these instead of the original iconify versions for consistent alignment.\n */\n\nimport React from 'react';\nimport { cn } from '../../lib/utils';\n\ninterface IconProps {\n className?: string;\n size?: number | string;\n}\n\n/**\n * Rotate Left icon (lucide-style stroked version)\n */\nexport const RotateLeftIcon: React.FC<IconProps> = ({ className, size = 24 }) => (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n width={size}\n height={size}\n className={cn('sc:inline-block iconify', className)}\n >\n <path d=\"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8\" />\n <path d=\"M3 3v5h5\" />\n </svg>\n);\n\n/**\n * Rotate Right icon (lucide-style stroked version)\n */\nexport const RotateRightIcon: React.FC<IconProps> = ({ className, size = 24 }) => (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n width={size}\n height={size}\n className={cn('sc:inline-block iconify', className)}\n >\n <path d=\"M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8\" />\n <path d=\"M21 3v5h-5\" />\n </svg>\n);\n\n/**\n * Sparkles icon (based on gravity-ui:sparkles)\n * Two sparkle shapes - main 4-point star and smaller accent\n */\nexport const SparklesIcon: React.FC<IconProps> = ({ className, size = 24 }) => (\n <svg\n viewBox=\"0 0 28 28\"\n fill=\"currentColor\"\n width={size}\n height={size}\n className={cn('sc:inline-block', className)}\n >\n <path d=\"M10.06 18.701a1.628 1.628 0 0 0 2.43-.676l.77-2.34a3.82 3.82 0 0 1 2.416-2.418l2.238-.727a1.6 1.6 0 0 0 .786-.595a1.62 1.62 0 0 0-.849-2.489l-2.215-.72a3.82 3.82 0 0 1-2.42-2.414l-.727-2.237a1.62 1.62 0 0 0-.594-.785a1.655 1.655 0 0 0-1.879 0a1.63 1.63 0 0 0-.6.8L8.68 6.365a3.82 3.82 0 0 1-2.359 2.37l-2.24.726a1.626 1.626 0 0 0 .02 3.073l2.216.72a3.86 3.86 0 0 1 1.816 1.286c.266.343.471.728.606 1.14l.728 2.234c.112.318.32.593.595.787m-3.273-6.873l-2.22-.72s-.085-.038-.085-.108a.14.14 0 0 1 .084-.115L6.8 10.16a5.34 5.34 0 0 0 3.32-3.375l.721-2.219s.043-.084.114-.084s.113.084.113.084l.723 2.223a5.32 5.32 0 0 0 3.377 3.372l2.27.735a.13.13 0 0 1 .078.11a.15.15 0 0 1-.083.113l-2.225.722a5.32 5.32 0 0 0-3.374 3.374l-.715 2.2a.11.11 0 0 1-.115.093c-.104 0-.118-.075-.118-.075l-.723-2.22a5.32 5.32 0 0 0-3.376-3.385m13.017 12.954A1.2 1.2 0 0 0 20.5 25a1.2 1.2 0 0 0 .692-.216a1.2 1.2 0 0 0 .446-.6l.372-1.143a1.61 1.61 0 0 1 1.017-1.02l1.166-.378A1.21 1.21 0 0 0 25 20.505a1.2 1.2 0 0 0-.844-1.146l-1.144-.37a1.61 1.61 0 0 1-1.02-1.018l-.38-1.163a1.2 1.2 0 0 0-2.274.016l-.374 1.146a1.61 1.61 0 0 1-.993 1.017l-1.166.378a1.21 1.21 0 0 0-.807 1.139a1.2 1.2 0 0 0 .823 1.138l1.144.372a1.6 1.6 0 0 1 1.02 1.023l.379 1.163a1.2 1.2 0 0 0 .44.582m-1.371-4.194l-.27-.088l.283-.096a3.12 3.12 0 0 0 1.943-1.974l.088-.27l.089.272a3.11 3.11 0 0 0 1.974 1.975l.293.1l-.271.087a3.12 3.12 0 0 0-1.974 1.977l-.088.27l-.088-.272a3.12 3.12 0 0 0-1.98-1.98\" />\n </svg>\n);\n\n// Map of icon names to components for easy lookup\nexport const CustomIcons = {\n 'rotate-left': RotateLeftIcon,\n 'rotate-right': RotateRightIcon,\n 'sparkles': SparklesIcon,\n} as const;\n\nexport type CustomIconName = keyof typeof CustomIcons;\n"],"names":["Input","React","className","type","isInvalid","startContent","endContent","disabled","readOnly","required","variant","props","ref","surface","useSurface","isOnSurface","effectiveVariant","inputElement","jsx","cn","jsxs","labelVariants","cva","Label","LabelPrimitive","TabsRoot","value","onValueChange","TabsPrimitive","TabsList","children","listRef","indicatorStyle","setIndicatorStyle","listElement","updateIndicator","activeTab","listRect","tabRect","observer","mutations","mutation","trigger","resizeObserver","node","TabsTrigger","id","surfaceVariant","TabsContent","TabsListContainer","TabsTab","TabsPanel","TabsIndicator","TabsBase","Tabs","TextField","enhancedChildren","child","childType","displayName","childProps","RotateLeftIcon","size","SparklesIcon"],"mappings":"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"}
1
+ {"version":3,"file":"custom-icons-CcLMyybv.js","sources":["../src/vendor/ui/primitives/input.tsx","../src/vendor/ui/primitives/label.tsx","../src/vendor/ui/primitives/tabs.tsx","../src/vendor/ui/primitives/text-field.tsx","../src/components/ui/custom-icons.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { cn } from '../lib/utils';\nimport { useSurface } from './surface';\n\nexport interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {\n /** Whether the input is in an invalid state */\n isInvalid?: boolean;\n /** Content to display at the start of the input */\n startContent?: React.ReactNode;\n /** Content to display at the end of the input */\n endContent?: React.ReactNode;\n /**\n * Visual variant - auto-detected from Surface context, or can be set explicitly\n * - `default`: Standard field styling for forms (bg-field)\n * - `filled`: Field on elevated surface (bg-field-on-surface)\n * - `subtle`: Blends with buttons/tabs in toolbars (bg-default)\n */\n variant?: 'default' | 'filled' | 'subtle';\n}\n\nconst Input = React.forwardRef<HTMLInputElement, InputProps>(\n (\n {\n className,\n type,\n isInvalid,\n startContent,\n endContent,\n disabled,\n readOnly,\n required,\n variant,\n ...props\n },\n ref\n ) => {\n // Auto-detect variant from Surface context\n const surface = useSurface();\n const isOnSurface = surface.variant === 'default' || surface.variant === 'secondary';\n const effectiveVariant = variant ?? (isOnSurface ? 'filled' : 'default');\n\n const inputElement = (\n <input\n type={type}\n className={cn(\n 'sc:flex sc:h-10 sc:w-full sc:rounded-input sc:px-2.5 sc:py-1.5 sc:text-sm sc:appearance-none',\n 'sc:text-foreground sc:border-none',\n 'sc:file:border-0 sc:file:bg-transparent sc:file:text-sm sc:file:font-medium sc:file:text-foreground',\n 'sc:placeholder:text-foreground/50',\n 'sc:transition-shadow sc:duration-200 sc:ease-out sc:focus-visible:outline-none sc:focus:ring-2 sc:focus:ring-focus sc:focus:ring-offset-1 sc:focus:ring-offset-background',\n 'sc:disabled:cursor-not-allowed sc:disabled:opacity-50',\n // Variant styles - semantic: field on page vs field on surface vs toolbar\n effectiveVariant === 'default' && 'sc:bg-field sc:shadow-soft sc:dark:shadow-none',\n effectiveVariant === 'filled' && 'sc:bg-[var(--color-field-on-surface)]',\n effectiveVariant === 'subtle' && 'sc:bg-default sc:dark:bg-[var(--color-default-on-surface)]',\n isInvalid && 'sc:ring-2 sc:ring-danger sc:focus-visible:ring-danger',\n startContent && 'sc:pl-10',\n endContent && 'sc:pr-10',\n className\n )}\n ref={ref}\n disabled={disabled}\n readOnly={readOnly}\n required={required}\n aria-invalid={isInvalid}\n {...props}\n />\n );\n\n if (startContent || endContent) {\n return (\n <div className=\"sc:relative\">\n {startContent && (\n <div className=\"sc:absolute sc:left-3 sc:top-1/2 sc:-translate-y-1/2 sc:text-foreground sc:opacity-40\">{startContent}</div>\n )}\n {inputElement}\n {endContent && (\n <div className=\"sc:absolute sc:right-3 sc:top-1/2 sc:-translate-y-1/2 sc:text-foreground sc:opacity-40\">{endContent}</div>\n )}\n </div>\n );\n }\n\n return inputElement;\n }\n);\nInput.displayName = 'Input';\n\nexport { Input };\n","'use client';\n\nimport * as React from 'react';\nimport * as LabelPrimitive from '@radix-ui/react-label';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { cn } from '../lib/utils';\n\nconst labelVariants = cva(\n 'sc:block sc:text-sm sc:leading-none sc:text-foreground sc:peer-disabled:cursor-not-allowed sc:peer-disabled:opacity-70 sc:font-label'\n);\n\nconst Label = React.forwardRef<\n React.ElementRef<typeof LabelPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> & VariantProps<typeof labelVariants>\n>(({ className, ...props }, ref) => (\n <LabelPrimitive.Root ref={ref} className={cn(labelVariants(), className)} {...props} />\n));\nLabel.displayName = LabelPrimitive.Root.displayName;\n\nexport { Label };\n","\"use client\";\n\n'use client';\n\nimport * as React from 'react';\nimport * as TabsPrimitive from '@radix-ui/react-tabs';\nimport { cn } from '../lib/utils';\nimport { useSurface } from './surface';\n\ninterface TabsProps\n extends Omit<React.ComponentPropsWithoutRef<typeof TabsPrimitive.Root>, 'value' | 'onValueChange'> {\n value?: string;\n onValueChange?: (value: string) => void;\n}\n\nconst TabsRoot = React.forwardRef<React.ElementRef<typeof TabsPrimitive.Root>, TabsProps>(\n ({ value, onValueChange, ...props }, ref) => (\n <TabsPrimitive.Root ref={ref} value={value} onValueChange={onValueChange} {...props} />\n )\n);\nTabsRoot.displayName = 'Tabs';\n\nconst TabsList = React.forwardRef<\n React.ElementRef<typeof TabsPrimitive.List>,\n React.ComponentPropsWithoutRef<typeof TabsPrimitive.List>\n>(({ className, children, ...props }, ref) => {\n const listRef = React.useRef<HTMLDivElement>(null);\n const [indicatorStyle, setIndicatorStyle] = React.useState<React.CSSProperties>({\n opacity: 0,\n });\n\n // Update indicator position when active tab changes\n React.useEffect(() => {\n const listElement = listRef.current;\n if (!listElement) return;\n\n const updateIndicator = () => {\n const activeTab = listElement.querySelector('[data-state=\"active\"]') as HTMLElement;\n if (activeTab) {\n const listRect = listElement.getBoundingClientRect();\n const tabRect = activeTab.getBoundingClientRect();\n\n setIndicatorStyle({\n width: tabRect.width,\n height: tabRect.height,\n left: tabRect.left - listRect.left,\n opacity: 1,\n });\n }\n };\n\n // Initial position\n updateIndicator();\n\n // Use MutationObserver to detect when active tab changes\n const observer = new MutationObserver((mutations) => {\n for (const mutation of mutations) {\n if (mutation.type === 'attributes' && mutation.attributeName === 'data-state') {\n updateIndicator();\n break;\n }\n }\n });\n\n // Observe all trigger elements for data-state changes\n const triggers = listElement.querySelectorAll('[role=\"tab\"]');\n triggers.forEach((trigger) => {\n observer.observe(trigger, { attributes: true, attributeFilter: ['data-state'] });\n });\n\n // Also update on resize\n const resizeObserver = new ResizeObserver(updateIndicator);\n resizeObserver.observe(listElement);\n\n return () => {\n observer.disconnect();\n resizeObserver.disconnect();\n };\n }, [children]);\n\n return (\n <TabsPrimitive.List\n ref={(node) => {\n // Handle both refs\n (listRef as React.MutableRefObject<HTMLDivElement | null>).current = node;\n if (typeof ref === 'function') {\n ref(node);\n } else if (ref) {\n ref.current = node;\n }\n }}\n className={cn(\n 'sc:relative sc:inline-flex sc:h-10 sc:items-center sc:justify-center sc:rounded-full sc:px-1 sc:text-muted-foreground',\n // Consistent bg-default matches Button secondary variant for toolbar harmony\n 'sc:bg-default sc:dark:bg-[var(--color-default-on-surface)]',\n className\n )}\n {...props}\n >\n {/* Animated sliding indicator. In dark mode the previous `bg-muted`\n value resolved to the same color as `bg-default` on the container,\n so the active tab was invisible without relying purely on\n shadow-md. `bg-popover` lands ~0.08 lightness above `bg-default`\n in dark mode for a clearly visible elevation. */}\n <span\n className=\"sc:absolute sc:top-1/2 sc:-translate-y-1/2 sc:rounded-full sc:bg-surface sc:dark:bg-popover sc:shadow-md sc:transition-[left,width,opacity]\"\n style={{\n ...indicatorStyle,\n transitionDuration: '350ms',\n transitionTimingFunction: 'cubic-bezier(0.22, 1, 0.36, 1)',\n }}\n aria-hidden=\"true\"\n />\n {children}\n </TabsPrimitive.List>\n );\n});\nTabsList.displayName = TabsPrimitive.List.displayName;\n\ninterface TabsTriggerProps extends Omit<React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>, 'value'> {\n // HeroUI uses 'id' for tab identification, Radix uses 'value'\n // At least one must be provided\n id?: string;\n value?: string;\n}\n\nconst TabsTrigger = React.forwardRef<React.ElementRef<typeof TabsPrimitive.Trigger>, TabsTriggerProps>(\n ({ className, id, value, ...props }, ref) => {\n const { variant: surfaceVariant } = useSurface();\n const isOnSurface = surfaceVariant === 'default' || surfaceVariant === 'secondary';\n\n return (\n <TabsPrimitive.Trigger\n ref={ref}\n value={id ?? value ?? ''}\n className={cn(\n 'sc:relative sc:z-10 sc:inline-flex sc:h-8 sc:items-center sc:justify-center sc:gap-2 sc:whitespace-nowrap sc:rounded-full sc:px-4 sc:text-sm sc:font-label',\n 'sc:transition-[color,opacity]',\n 'sc:focus-visible:outline-none sc:focus-visible:ring-2 sc:focus-visible:ring-focus sc:focus-visible:ring-offset-2',\n 'sc:disabled:pointer-events-none sc:disabled:opacity-50',\n 'sc:data-[state=active]:text-foreground sc:data-[state=active]:opacity-100',\n // Inactive tabs use element opacity (not color opacity) to avoid SVG path overlap issues\n isOnSurface\n ? 'sc:data-[state=inactive]:text-foreground sc:data-[state=inactive]:opacity-30 sc:data-[state=inactive]:hover:opacity-50'\n : 'sc:data-[state=inactive]:text-foreground sc:data-[state=inactive]:opacity-50 sc:data-[state=inactive]:hover:opacity-70',\n className\n )}\n {...props}\n />\n );\n }\n);\nTabsTrigger.displayName = TabsPrimitive.Trigger.displayName;\n\ninterface TabsContentProps extends Omit<React.ComponentPropsWithoutRef<typeof TabsPrimitive.Content>, 'value'> {\n // HeroUI uses 'id' for panel identification, Radix uses 'value'\n // At least one must be provided\n id?: string;\n value?: string;\n}\n\nconst TabsContent = React.forwardRef<React.ElementRef<typeof TabsPrimitive.Content>, TabsContentProps>(\n ({ className, id, value, ...props }, ref) => (\n <TabsPrimitive.Content\n ref={ref}\n value={id ?? value ?? ''}\n className={cn(\n 'sc:mt-2 sc:ring-offset-background sc:focus-visible:outline-none sc:focus-visible:ring-2 sc:focus-visible:ring-focus sc:focus-visible:ring-offset-2',\n className\n )}\n {...props}\n />\n )\n);\nTabsContent.displayName = TabsPrimitive.Content.displayName;\n\n// HeroUI ListContainer - wrapper for the tabs list (passthrough div)\nconst TabsListContainer = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n ({ className, ...props }, ref) => <div ref={ref} className={className} {...props} />\n);\nTabsListContainer.displayName = 'TabsListContainer';\n\n// HeroUI Tab - alias for TabsTrigger\nconst TabsTab = TabsTrigger;\n\n// HeroUI Panel - alias for TabsContent\nconst TabsPanel = TabsContent;\n\n// HeroUI Indicator - now rendered automatically by TabsList, this is a no-op\nconst TabsIndicator = () => null;\n\n// Create compound component with all aliases\nconst TabsBase = TabsRoot;\n\n// HeroUI-compatible compound component\nconst Tabs = Object.assign(TabsBase, {\n List: TabsList,\n ListContainer: TabsListContainer,\n Tab: TabsTab,\n Trigger: TabsTrigger,\n Panel: TabsPanel,\n Content: TabsContent,\n Indicator: TabsIndicator,\n});\n\nexport { Tabs, TabsList, TabsTrigger, TabsContent, TabsRoot };\n","'use client';\n\nimport * as React from 'react';\nimport { cn } from '../lib/utils';\n\nexport interface TextFieldProps extends React.HTMLAttributes<HTMLDivElement> {\n /**\n * Accessible label for the input.\n * If not provided via children, use aria-label on the div.\n */\n 'aria-label'?: string;\n /**\n * Error state - applies error styling to children inputs\n */\n isInvalid?: boolean;\n /**\n * Disabled state - disables all children inputs\n */\n disabled?: boolean;\n /**\n * Required state - marks all children inputs as required\n */\n required?: boolean;\n}\n\n/**\n * TextField - A wrapper component that groups Label and Input together.\n *\n * Groups Label and Input with a convenient wrapper that can propagate\n * disabled, required, and invalid states to child inputs.\n *\n * @example\n * ```tsx\n * <TextField>\n * <Label>Email</Label>\n * <Input type=\"email\" placeholder=\"Enter email...\" />\n * </TextField>\n * ```\n */\nconst TextField = React.forwardRef<HTMLDivElement, TextFieldProps>(\n ({ className, children, isInvalid, disabled, required, ...props }, ref) => {\n // Clone children to pass through state props to Input/Textarea children\n const enhancedChildren = React.Children.map(children, (child) => {\n if (!React.isValidElement(child)) return child;\n\n // Get the display name or type name to check if it's an input component\n const childType = child.type;\n const displayName =\n typeof childType === 'function'\n ? (childType as React.ComponentType).displayName || childType.name\n : typeof childType === 'string'\n ? childType\n : '';\n\n // Check if this is an input-like element that should receive state props\n const isInputElement =\n displayName === 'Input' ||\n displayName === 'Textarea' ||\n displayName === 'TextArea' ||\n displayName === 'input' ||\n displayName === 'textarea';\n\n if (isInputElement) {\n const childProps = child.props as Record<string, unknown>;\n return React.cloneElement(child as React.ReactElement<Record<string, unknown>>, {\n isInvalid: (childProps.isInvalid as boolean) ?? isInvalid,\n disabled: (childProps.disabled as boolean) ?? disabled,\n required: (childProps.required as boolean) ?? required,\n });\n }\n\n return child;\n });\n\n return (\n <div ref={ref} className={cn('sc:flex sc:flex-col sc:gap-1.5', className)} {...props}>\n {enhancedChildren}\n </div>\n );\n }\n);\nTextField.displayName = 'TextField';\n\nexport { TextField };\n","/**\n * Custom Icons - Centered versions of icons from various sets\n *\n * These are copies of icons with adjusted viewBox to center properly.\n * Use these instead of the original iconify versions for consistent alignment.\n */\n\nimport React from 'react';\nimport { cn } from '../../lib/utils';\n\ninterface IconProps {\n className?: string;\n size?: number | string;\n}\n\n/**\n * Rotate Left icon (lucide-style stroked version)\n */\nexport const RotateLeftIcon: React.FC<IconProps> = ({ className, size = 24 }) => (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n width={size}\n height={size}\n className={cn('sc:inline-block iconify', className)}\n >\n <path d=\"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8\" />\n <path d=\"M3 3v5h5\" />\n </svg>\n);\n\n/**\n * Rotate Right icon (lucide-style stroked version)\n */\nexport const RotateRightIcon: React.FC<IconProps> = ({ className, size = 24 }) => (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n width={size}\n height={size}\n className={cn('sc:inline-block iconify', className)}\n >\n <path d=\"M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8\" />\n <path d=\"M21 3v5h-5\" />\n </svg>\n);\n\n/**\n * Sparkles icon (based on gravity-ui:sparkles)\n * Two sparkle shapes - main 4-point star and smaller accent\n */\nexport const SparklesIcon: React.FC<IconProps> = ({ className, size = 24 }) => (\n <svg\n viewBox=\"0 0 28 28\"\n fill=\"currentColor\"\n width={size}\n height={size}\n className={cn('sc:inline-block', className)}\n >\n <path d=\"M10.06 18.701a1.628 1.628 0 0 0 2.43-.676l.77-2.34a3.82 3.82 0 0 1 2.416-2.418l2.238-.727a1.6 1.6 0 0 0 .786-.595a1.62 1.62 0 0 0-.849-2.489l-2.215-.72a3.82 3.82 0 0 1-2.42-2.414l-.727-2.237a1.62 1.62 0 0 0-.594-.785a1.655 1.655 0 0 0-1.879 0a1.63 1.63 0 0 0-.6.8L8.68 6.365a3.82 3.82 0 0 1-2.359 2.37l-2.24.726a1.626 1.626 0 0 0 .02 3.073l2.216.72a3.86 3.86 0 0 1 1.816 1.286c.266.343.471.728.606 1.14l.728 2.234c.112.318.32.593.595.787m-3.273-6.873l-2.22-.72s-.085-.038-.085-.108a.14.14 0 0 1 .084-.115L6.8 10.16a5.34 5.34 0 0 0 3.32-3.375l.721-2.219s.043-.084.114-.084s.113.084.113.084l.723 2.223a5.32 5.32 0 0 0 3.377 3.372l2.27.735a.13.13 0 0 1 .078.11a.15.15 0 0 1-.083.113l-2.225.722a5.32 5.32 0 0 0-3.374 3.374l-.715 2.2a.11.11 0 0 1-.115.093c-.104 0-.118-.075-.118-.075l-.723-2.22a5.32 5.32 0 0 0-3.376-3.385m13.017 12.954A1.2 1.2 0 0 0 20.5 25a1.2 1.2 0 0 0 .692-.216a1.2 1.2 0 0 0 .446-.6l.372-1.143a1.61 1.61 0 0 1 1.017-1.02l1.166-.378A1.21 1.21 0 0 0 25 20.505a1.2 1.2 0 0 0-.844-1.146l-1.144-.37a1.61 1.61 0 0 1-1.02-1.018l-.38-1.163a1.2 1.2 0 0 0-2.274.016l-.374 1.146a1.61 1.61 0 0 1-.993 1.017l-1.166.378a1.21 1.21 0 0 0-.807 1.139a1.2 1.2 0 0 0 .823 1.138l1.144.372a1.6 1.6 0 0 1 1.02 1.023l.379 1.163a1.2 1.2 0 0 0 .44.582m-1.371-4.194l-.27-.088l.283-.096a3.12 3.12 0 0 0 1.943-1.974l.088-.27l.089.272a3.11 3.11 0 0 0 1.974 1.975l.293.1l-.271.087a3.12 3.12 0 0 0-1.974 1.977l-.088.27l-.088-.272a3.12 3.12 0 0 0-1.98-1.98\" />\n </svg>\n);\n\n// Map of icon names to components for easy lookup\nexport const CustomIcons = {\n 'rotate-left': RotateLeftIcon,\n 'rotate-right': RotateRightIcon,\n 'sparkles': SparklesIcon,\n} as const;\n\nexport type CustomIconName = keyof typeof CustomIcons;\n"],"names":["Input","React","className","type","isInvalid","startContent","endContent","disabled","readOnly","required","variant","props","ref","surface","useSurface","isOnSurface","effectiveVariant","inputElement","jsx","cn","jsxs","labelVariants","cva","Label","LabelPrimitive","TabsRoot","value","onValueChange","TabsPrimitive","TabsList","children","listRef","indicatorStyle","setIndicatorStyle","listElement","updateIndicator","activeTab","listRect","tabRect","observer","mutations","mutation","trigger","resizeObserver","node","TabsTrigger","id","surfaceVariant","TabsContent","TabsListContainer","TabsTab","TabsPanel","TabsIndicator","TabsBase","Tabs","TextField","enhancedChildren","child","childType","displayName","childProps","RotateLeftIcon","size","SparklesIcon"],"mappings":"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"}
@@ -178,13 +178,20 @@ type InferKind<N extends string, TText extends string, TImage extends string> =
178
178
  * docs; never block the dynamic case).
179
179
  */
180
180
  export declare class DesignBuilder<out TText extends string = string, out TImage extends string = string, out TColor extends string = string> {
181
- private readonly artboard;
181
+ /** The CURRENT authoring artboard — anchor math and new elements target it.
182
+ * Reassigned by {@link DesignBuilder.artboard}; the initially-active
183
+ * placement stays {@link activeName}. */
184
+ private current;
185
+ /** The placement that is active when the design mounts — always the FIRST
186
+ * artboard (or the saved state's active one), never moved by `.artboard()`. */
187
+ private readonly activeName;
182
188
  private readonly els;
183
189
  /** Declared color roles, name → normalized uppercase `#RRGGBB`. */
184
190
  private readonly colorRoles;
185
191
  private idCounter;
186
- /** Every artboard of a multi-page state (fromState `{ artboards: 'all' }`);
187
- * unset for single-artboard builders. */
192
+ /** Every artboard of a multi-artboard design — set by `fromState({ artboards:
193
+ * 'all' })` or the first `.artboard()` call; unset for single-artboard
194
+ * builders. */
188
195
  private allArtboards?;
189
196
  constructor(artboard: DesignArtboard);
190
197
  /**
@@ -208,6 +215,37 @@ export declare class DesignBuilder<out TText extends string = string, out TImage
208
215
  activeArtboard: string;
209
216
  }, options?: FromStateOptions): DesignBuilder;
210
217
  private nextId;
218
+ /** A wire-shape snapshot of an authoring artboard, applying the same
219
+ * background-export rule everywhere (a design background is part of the
220
+ * design — exports and server renders paint it). */
221
+ private static snapshotArtboard;
222
+ /**
223
+ * Open a NEW artboard (placement) and make it the authoring context: layer
224
+ * calls after this target the new artboard — anchor math uses its
225
+ * dimensions, and the elements carry its membership tag (the public
226
+ * `artboard` field, PR #482). The FIRST artboard (from `design({ name })`)
227
+ * remains the initially-active placement when the design mounts; switch at
228
+ * runtime with `usePlacements()` / `<Editor.Placements/>` (ADR-0088).
229
+ *
230
+ * `label` must be the product's placement label (case-sensitive) — the same
231
+ * artboard-name-is-placement-label rule as `design({ name })`.
232
+ *
233
+ * ```ts
234
+ * const seed = design({ name: 'Front', width: 1480, height: 2328 })
235
+ * .text('YOUR NAME', { anchor: 'top', name: 'headline' })
236
+ * .artboard('Back', { width: 1480, height: 2328 })
237
+ * .text('EST. 2026', { anchor: 'center', name: 'backline' });
238
+ * ```
239
+ *
240
+ * @throws EditorError `E_DUPLICATE_ARTBOARD` — the design already has an
241
+ * artboard with this label.
242
+ */
243
+ artboard(label: string, dims: {
244
+ width: number;
245
+ height: number;
246
+ backgroundColor?: string | ColorToken;
247
+ role?: ArtboardRole;
248
+ }): this;
211
249
  /** Full-bleed background image (fills the whole artboard). Cover-fit (no
212
250
  * distortion) when `aspectRatio` is supplied. Inserted at the bottom of the
213
251
  * stack regardless of call order. The default layer name `'Background'`
@@ -23,6 +23,16 @@ export interface ProductRenderConfig {
23
23
  };
24
24
  /** Every editable (non-color) placement label — placement pickers. */
25
25
  placementLabels: string[];
26
+ /** Geometry of EVERY renderable image placement, in catalog order — seed a
27
+ * multi-placement design mechanically (ADR-0088):
28
+ * `config.placements.reduce((d, p) => d.artboard(p.label, p), …)`. The
29
+ * entry matching `placement` is the same object shape. */
30
+ placements: Array<{
31
+ label: string;
32
+ width: number;
33
+ height: number;
34
+ aspectRatio: number;
35
+ }>;
26
36
  /** First mockup scene that photographs the rendered variant — the default
27
37
  * `<Editor.Preview mockupId>`. */
28
38
  primaryMockupId: string;
@@ -1,5 +1,5 @@
1
- import { g as l } from "./editorErrors-B2mb1sVN.js";
2
- const k = 1;
1
+ import { g as l } from "./editorErrors-BhrZ_nwj.js";
2
+ const x = 1;
3
3
  function d(e) {
4
4
  return typeof e == "number" && Number.isFinite(e) ? Math.round(e * 100) / 100 : e;
5
5
  }
@@ -18,10 +18,10 @@ function O(e) {
18
18
  const t = (n = e.artboards) != null && n.length ? e.artboards : [{ name: "Front", width: 800, height: 800 }], r = t.map(() => []);
19
19
  for (const i of e.elements || []) {
20
20
  const o = i == null ? void 0 : i.artboard, s = typeof o == "string" ? t.findIndex((a) => (a.name || "Front") === o) : -1;
21
- r[s >= 0 ? s : 0].push(C(i));
21
+ r[s >= 0 ? s : 0].push(A(i));
22
22
  }
23
23
  return {
24
- schemaVersion: k,
24
+ schemaVersion: x,
25
25
  artboards: t.map((i, o) => ({
26
26
  id: `artboard-${o + 1}`,
27
27
  name: i.name || "Front",
@@ -41,7 +41,7 @@ function O(e) {
41
41
  }))
42
42
  };
43
43
  }
44
- function C(e) {
44
+ function A(e) {
45
45
  const t = e.type || e.transformType;
46
46
  if (t === "image")
47
47
  return N(e);
@@ -67,41 +67,41 @@ function N(e) {
67
67
  return !r && (t.cropX !== 0 || t.cropY !== 0 || t.cropWidth !== 1 || t.cropHeight !== 1) && (a.cropX = t.cropX, a.cropY = t.cropY, a.cropWidth = t.cropWidth, a.cropHeight = t.cropHeight, a.needsCropPixelConversion = !0), t.flipHorizontal && (a.flipHorizontal = t.flipHorizontal), t.flipVertical && (a.flipVertical = t.flipVertical), t.borderRadius && (a.borderRadius = t.borderRadius), e.opacity !== void 0 && (a.opacity = e.opacity), e.distressEffect && (a.distressEffect = e.distressEffect), ((c = e.masks) == null ? void 0 : c.length) > 0 && (a.masks = e.masks), e.blendMode && (a.blendMode = e.blendMode), e.knockoutParts && (a.knockoutParts = e.knockoutParts), e.stroke && (a.stroke = e.stroke), b(a);
68
68
  }
69
69
  const p = "center", y = Symbol.for("snowcone.canvas.layerToken");
70
- function $(e) {
70
+ function z(e) {
71
71
  return typeof e == "object" && e !== null && e[y] === !0 && typeof e.name == "string" && (e.kind === "text" || e.kind === "image");
72
72
  }
73
- function E(e, t) {
73
+ function C(e, t) {
74
74
  return Object.freeze({ kind: e, name: t, [y]: !0 });
75
75
  }
76
76
  const w = Symbol.for("snowcone.canvas.colorToken");
77
- function T(e) {
77
+ function E(e) {
78
78
  return typeof e == "object" && e !== null && e[w] === !0 && typeof e.name == "string" && typeof e.value == "string";
79
79
  }
80
- function A(e, t) {
80
+ function T(e, t) {
81
81
  return Object.freeze({ name: e, value: t, [w]: !0 });
82
82
  }
83
83
  function S(e) {
84
84
  let t = e.trim().toUpperCase();
85
85
  return /^#[0-9A-F]{3}$/.test(t) && (t = "#" + t[1] + t[1] + t[2] + t[2] + t[3] + t[3]), /^#[0-9A-F]{6}$/.test(t) ? t : null;
86
86
  }
87
- function f(e) {
88
- return T(e) ? e.value : e;
87
+ function m(e) {
88
+ return E(e) ? e.value : e;
89
89
  }
90
- function u(e) {
90
+ function g(e) {
91
91
  const t = e.transformType;
92
92
  return t === "image" ? "image" : t === "shape" || t === "group" || t === "path" ? null : "text";
93
93
  }
94
- function _(e) {
94
+ function v(e) {
95
95
  return e === "top-left" || e === "left" || e === "bottom-left" ? "left" : e === "top-right" || e === "right" || e === "bottom-right" ? "right" : "center";
96
96
  }
97
- function v(e) {
97
+ function _(e) {
98
98
  return e === "top-left" || e === "top" || e === "top-right" ? "top" : e === "bottom-left" || e === "bottom" || e === "bottom-right" ? "bottom" : "middle";
99
99
  }
100
- function m(e, t, r, n, i, o) {
101
- const s = _(e), a = v(e), h = s === "left" ? t / 2 + o : s === "right" ? n - t / 2 - o : n / 2, c = a === "top" ? r / 2 + o : a === "bottom" ? i - r / 2 - o : i / 2;
100
+ function u(e, t, r, n, i, o) {
101
+ const s = v(e), a = _(e), h = s === "left" ? t / 2 + o : s === "right" ? n - t / 2 - o : n / 2, c = a === "top" ? r / 2 + o : a === "bottom" ? i - r / 2 - o : i / 2;
102
102
  return { x: h, y: c };
103
103
  }
104
- function H(e, t, r) {
104
+ function $(e, t, r) {
105
105
  const n = t / r;
106
106
  if (e >= n) {
107
107
  const s = r * e, a = t / s;
@@ -124,7 +124,7 @@ function H(e, t, r) {
124
124
  cropHeight: o
125
125
  };
126
126
  }
127
- class g {
127
+ class f {
128
128
  constructor(t) {
129
129
  if (this.els = [], this.colorRoles = /* @__PURE__ */ new Map(), this.idCounter = 0, !(t.width > 0) || !(t.height > 0))
130
130
  throw new Error("design(): artboard width and height must be positive numbers");
@@ -145,13 +145,13 @@ class g {
145
145
  );
146
146
  this.colorRoles.set(r, i);
147
147
  }
148
- this.artboard = {
148
+ this.current = {
149
149
  name: t.name || "Front",
150
150
  width: t.width,
151
151
  height: t.height,
152
- backgroundColor: f(t.backgroundColor),
152
+ backgroundColor: m(t.backgroundColor),
153
153
  role: t.role
154
- };
154
+ }, this.activeName = this.current.name;
155
155
  }
156
156
  /**
157
157
  * Seed a builder from a previously saved canvas state — the editor shape
@@ -172,7 +172,7 @@ class g {
172
172
  const n = t.artboards.find((o) => o.name === t.activeArtboard) ?? t.artboards[0];
173
173
  if (!n)
174
174
  throw new Error("DesignBuilder.fromState(): state has no artboards");
175
- const i = new g({
175
+ const i = new f({
176
176
  name: n.name,
177
177
  width: n.width,
178
178
  height: n.height,
@@ -192,11 +192,66 @@ class g {
192
192
  nextId(t) {
193
193
  return `${t}-${++this.idCounter}`;
194
194
  }
195
+ /** A wire-shape snapshot of an authoring artboard, applying the same
196
+ * background-export rule everywhere (a design background is part of the
197
+ * design — exports and server renders paint it). */
198
+ static snapshotArtboard(t) {
199
+ return {
200
+ name: t.name,
201
+ width: t.width,
202
+ height: t.height,
203
+ ...t.backgroundColor ? {
204
+ backgroundColor: t.backgroundColor,
205
+ exportBackground: t.backgroundColor !== "transparent"
206
+ } : {},
207
+ ...t.role ? { role: t.role } : {}
208
+ };
209
+ }
210
+ /**
211
+ * Open a NEW artboard (placement) and make it the authoring context: layer
212
+ * calls after this target the new artboard — anchor math uses its
213
+ * dimensions, and the elements carry its membership tag (the public
214
+ * `artboard` field, PR #482). The FIRST artboard (from `design({ name })`)
215
+ * remains the initially-active placement when the design mounts; switch at
216
+ * runtime with `usePlacements()` / `<Editor.Placements/>` (ADR-0088).
217
+ *
218
+ * `label` must be the product's placement label (case-sensitive) — the same
219
+ * artboard-name-is-placement-label rule as `design({ name })`.
220
+ *
221
+ * ```ts
222
+ * const seed = design({ name: 'Front', width: 1480, height: 2328 })
223
+ * .text('YOUR NAME', { anchor: 'top', name: 'headline' })
224
+ * .artboard('Back', { width: 1480, height: 2328 })
225
+ * .text('EST. 2026', { anchor: 'center', name: 'backline' });
226
+ * ```
227
+ *
228
+ * @throws EditorError `E_DUPLICATE_ARTBOARD` — the design already has an
229
+ * artboard with this label.
230
+ */
231
+ artboard(t, r) {
232
+ if (!(r.width > 0) || !(r.height > 0))
233
+ throw new Error("design().artboard(): width and height must be positive numbers");
234
+ if (this.allArtboards || (this.allArtboards = [f.snapshotArtboard(this.current)]), this.allArtboards.some((n) => n.name === t))
235
+ throw new l(
236
+ "E_DUPLICATE_ARTBOARD",
237
+ `the design already has an artboard "${t}" — artboard names are placement labels and must be unique. Existing: ${JSON.stringify(this.allArtboards.map((n) => n.name))}.`,
238
+ { artboardName: t, validNames: this.allArtboards.map((n) => n.name), docSlug: "embed-mode" }
239
+ );
240
+ for (const n of this.els)
241
+ n.artboard || (n.artboard = this.current.name);
242
+ return this.current = {
243
+ name: t,
244
+ width: r.width,
245
+ height: r.height,
246
+ backgroundColor: m(r.backgroundColor),
247
+ role: r.role
248
+ }, this.allArtboards.push(f.snapshotArtboard(this.current)), this;
249
+ }
195
250
  background(t, r = {}) {
196
- const { width: n, height: i } = this.artboard;
251
+ const { width: n, height: i } = this.current;
197
252
  let o;
198
253
  if (r.aspectRatio && r.aspectRatio > 0) {
199
- const a = H(r.aspectRatio, n, i);
254
+ const a = $(r.aspectRatio, n, i);
200
255
  o = {
201
256
  type: "image",
202
257
  width: a.width,
@@ -237,7 +292,7 @@ class g {
237
292
  return this.els.unshift(s), this;
238
293
  }
239
294
  image(t, r = {}) {
240
- const { width: n, height: i } = this.artboard, o = r.width ?? Math.round(n / 3), s = r.height ?? (r.aspectRatio ? Math.round(o / r.aspectRatio) : o), { x: a, y: h } = m(r.anchor ?? p, o, s, n, i, r.padding ?? 0), c = {
295
+ const { width: n, height: i } = this.current, o = r.width ?? Math.round(n / 3), s = r.height ?? (r.aspectRatio ? Math.round(o / r.aspectRatio) : o), { x: a, y: h } = u(r.anchor ?? p, o, s, n, i, r.padding ?? 0), c = {
241
296
  id: this.nextId("img"),
242
297
  transformType: "image",
243
298
  x: a,
@@ -263,7 +318,7 @@ class g {
263
318
  return this.els.push(c), this;
264
319
  }
265
320
  text(t, r = {}) {
266
- const { width: n, height: i } = this.artboard, o = r.fontSize ?? Math.round(this.artboard.height / 12), { x: s, y: a } = m(r.anchor ?? "top", 0, o, n, i, r.padding ?? Math.round(i / 20)), h = {
321
+ const { width: n, height: i } = this.current, o = r.fontSize ?? Math.round(this.current.height / 12), { x: s, y: a } = u(r.anchor ?? "top", 0, o, n, i, r.padding ?? Math.round(i / 20)), h = {
267
322
  id: this.nextId("text"),
268
323
  transformType: "custom",
269
324
  x: s,
@@ -272,7 +327,7 @@ class g {
272
327
  text: t,
273
328
  fontSize: o,
274
329
  fontFamily: r.fontFamily ?? "Anton",
275
- color: f(r.color) ?? "#ffffff",
330
+ color: m(r.color) ?? "#ffffff",
276
331
  textAlign: r.textAlign ?? "center",
277
332
  bold: r.bold ?? !1,
278
333
  italic: r.italic ?? !1,
@@ -304,14 +359,14 @@ class g {
304
359
  { layerName: t, validNames: [...i, ...o], textNames: i, imageNames: o, docSlug: "embed-mode" }
305
360
  );
306
361
  }
307
- const n = u(r);
362
+ const n = g(r);
308
363
  if (!n)
309
364
  throw new l(
310
365
  "E_LAYER_WRONG_KIND",
311
366
  `layer "${t}" is a ${r.transformType} element — only text and image layers are bindable. Bindable layers: ${JSON.stringify([...this.layerNamesOfKind("text"), ...this.layerNamesOfKind("image")])}.`,
312
367
  { layerName: t, actualType: r.transformType, docSlug: "embed-mode" }
313
368
  );
314
- return E(n, t);
369
+ return C(n, t);
315
370
  }
316
371
  /**
317
372
  * Mint a {@link ColorToken} for a declared color role. Compile time: `name`
@@ -334,24 +389,24 @@ class g {
334
389
  `no color role "${t}" in this design. Declared roles: ${JSON.stringify([...this.colorRoles.keys()])}. Declare roles up front — design({ …, colors: { ${t}: '#FF2D8A' } }).`,
335
390
  { roleName: t, validNames: [...this.colorRoles.keys()], docSlug: "embed-mode" }
336
391
  );
337
- return A(t, r);
392
+ return T(t, r);
338
393
  }
339
394
  /** Names of bindable layers of one kind, in stack order. @internal */
340
395
  layerNamesOfKind(t) {
341
- return this.els.filter((r) => u(r) === t).map((r) => r.name).filter((r) => !!r);
396
+ return this.els.filter((r) => g(r) === t).map((r) => r.name).filter((r) => !!r);
342
397
  }
343
398
  /** An anchored vector shape. */
344
399
  shape(t, r = {}) {
345
- const { width: n, height: i } = this.artboard, o = r.size ?? Math.round(n / 6), s = typeof o == "number" ? o : o.width, a = typeof o == "number" ? o : o.height, { x: h, y: c } = m(r.anchor ?? p, s, a, n, i, r.padding ?? 0), R = {
400
+ const { width: n, height: i } = this.current, o = r.size ?? Math.round(n / 6), s = typeof o == "number" ? o : o.width, a = typeof o == "number" ? o : o.height, { x: h, y: c } = u(r.anchor ?? p, s, a, n, i, r.padding ?? 0), R = {
346
401
  type: "shape",
347
402
  shapeType: t,
348
403
  width: s,
349
404
  height: a,
350
- fillColor: f(r.fill) ?? "#000000",
405
+ fillColor: m(r.fill) ?? "#000000",
351
406
  fillOpacity: r.opacity ?? 1,
352
407
  ...r.points !== void 0 ? { points: r.points } : {},
353
408
  ...r.sides !== void 0 ? { sides: r.sides } : {}
354
- }, x = {
409
+ }, k = {
355
410
  id: this.nextId("shape"),
356
411
  transformType: "shape",
357
412
  x: h,
@@ -360,7 +415,7 @@ class g {
360
415
  transformData: R,
361
416
  ...r.name ? { name: r.name } : {}
362
417
  };
363
- return this.els.push(x), this;
418
+ return this.els.push(k), this;
364
419
  }
365
420
  /** The composed elements, in render order (background first). Editor shape. */
366
421
  get elements() {
@@ -372,30 +427,23 @@ class g {
372
427
  * page (artboard `role`s and element membership tags included). */
373
428
  toJSON() {
374
429
  return this.allArtboards ? {
375
- // Elements added via builder methods after fromState are untagged —
376
- // they belong to the builder's (active) artboard; stamp them so the
377
- // multi-artboard state groups them correctly.
430
+ // Elements added via builder methods since the last context switch are
431
+ // untagged — they belong to the CURRENT authoring artboard; stamp them
432
+ // so the multi-artboard state groups them correctly.
378
433
  elements: this.els.map(
379
- (t) => t.artboard ? { ...t } : { ...t, artboard: this.artboard.name }
434
+ (t) => t.artboard ? { ...t } : { ...t, artboard: this.current.name }
380
435
  ),
381
436
  artboards: this.allArtboards.map((t) => ({ ...t })),
382
- activeArtboard: this.artboard.name
437
+ // The initially-active placement (first artboard / saved state's
438
+ // active) — NOT the last `.artboard()` authoring context.
439
+ activeArtboard: this.activeName
383
440
  } : {
384
441
  elements: this.elements,
385
- artboards: [{
386
- name: this.artboard.name,
387
- width: this.artboard.width,
388
- height: this.artboard.height,
389
- // A background set on a design is part of the design: flag it
390
- // renderable so exports and server renders paint it, matching the
391
- // editor (the export worker skips it without `exportBackground`).
392
- ...this.artboard.backgroundColor ? {
393
- backgroundColor: this.artboard.backgroundColor,
394
- exportBackground: this.artboard.backgroundColor !== "transparent"
395
- } : {},
396
- ...this.artboard.role ? { role: this.artboard.role } : {}
397
- }],
398
- activeArtboard: this.artboard.name
442
+ // A background set on a design is part of the design: flag it renderable
443
+ // so exports and server renders paint it, matching the editor (the
444
+ // export worker skips it without `exportBackground`) — see snapshotArtboard.
445
+ artboards: [f.snapshotArtboard(this.current)],
446
+ activeArtboard: this.current.name
399
447
  };
400
448
  }
401
449
  /** Server-render payload for `RenderSession.renderState(placement, …)`.
@@ -405,18 +453,18 @@ class g {
405
453
  }
406
454
  }
407
455
  function L(e) {
408
- return new g(e);
456
+ return new f(e);
409
457
  }
410
458
  function F(e) {
411
- return u(e);
459
+ return g(e);
412
460
  }
413
461
  export {
414
- k as C,
415
- g as D,
416
- T as a,
462
+ x as C,
463
+ f as D,
464
+ E as a,
417
465
  L as d,
418
- $ as i,
466
+ z as i,
419
467
  F as l,
420
468
  O as s
421
469
  };
422
- //# sourceMappingURL=design-builder-2VUjfmdt.js.map
470
+ //# sourceMappingURL=design-builder-cZY958Rw.js.map