@texturehq/edges 2.1.0 → 2.1.2

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/Dialog/Dialog.tsx","../../src/hooks/useMediaQuery.ts","../../src/hooks/useVisualViewportHeight.ts","../../src/utils/classNames.ts","../../src/utils/typography.ts","../../src/utils/index.ts","../../src/utils/controlStyles.ts","../../src/components/Icon/customIcons/createTextureIcon.tsx","../../src/components/Icon/customIcons/registry.tsx","../../src/components/Icon/Icon.tsx","../../src/components/Button/Button.tsx","../../src/components/DialogFooter/DialogFooter.tsx","../../src/components/Heading/Heading.tsx","../../src/components/DialogHeader/DialogHeader.tsx","../../src/components/Skeleton/Skeleton.tsx","../../src/components/Card/Card.tsx","../../src/components/ErrorBoundary/ErrorBoundary.tsx","../../src/components/ModalBackdrop/ModalBackdrop.tsx","../../src/components/Tray/Tray.tsx","../../src/components/Form/Form.tsx","../../src/form/DialogForm.tsx","../../src/components/Drawer/Drawer.tsx","../../src/form/DrawerForm.tsx","../../src/form/FormActions.tsx","../../src/form/FormGrid.tsx","../../src/components/Field/Field.tsx","../../src/form/FormSection.tsx","../../src/form/FormStepper.tsx","../../src/form/SaveBar.tsx","../../src/form/UnsavedChangesPrompt.tsx","../../src/form/useWizard.tsx"],"names":["useMediaQuery","query","defaultValue","matches","setMatches","useState","useEffect","mediaQueryList","handleChange","event","useVisualViewportHeight","enabled","state","setState","vv","update","keyboardOffset","cx","classNames","typographyRole","typeRole","role","focusRing","showDefaultOutline","controlStyles","createTextureIcon","displayName","children","Component","forwardRef","size","color","className","mirrored","alt","rest","ref","hasAccessibleName","jsx","SwitchContactBase","jsxs","Fragment","OpenBlade","ClosedBlade","TextureRecloser","TextureFuse","TextureBreaker","TextureSource","TextureCapacitor","TextureRegulator","TextureSwitch","TextureSwitchClosed","TextureSectionalizerOpen","TextureSectionalizerClosed","TextureTransformer","PHASE_YS","solidLine","y","dashedLine","TextureSinglePhaseOverheadLine","TextureTwoPhaseOverheadLine","TextureThreePhaseOverheadLine","TextureSinglePhaseUndergroundLine","TextureTwoPhaseUndergroundLine","TextureThreePhaseUndergroundLine","TextureSupportStructure","CUSTOM_ICON_REGISTRY","customName","PhosphorIcons","sizePresets","Icon","memo","name","weight","ariaLabel","props","IconComponent","resolvedSize","iconClassName","twMerge","IconWithContainer","variant","shape","containerSize","containerClassName","iconSize","resolvedContainerSize","containerClasses","baseStyles","primaryButtonStyles","variantStyles","widthStyles","disabledStyles","enabledStyles","badgePositionStyles","badgeVariantStyles","normalizeVariant","getButtonStyles","isDisabled","fullWidth","isLoading","normalizedVariant","styles","focusRingColor","Button","icon","loadingText","loadingIndicator","iconPosition","iconWeight","href","badgeNumber","badgeVariant","badgePosition","style","target","rel","restProps","iconElement","content","loadingNode","hasBadge","composedClassName","linkProps","_onPress","_onPressStart","_onPressEnd","_onPressChange","_onPressUp","_onAuxClick","_onContextMenu","_onDoubleClick","safeRestProps","buttonOrLink","RACLink","renderProps","RACButton","ActionButton","action","defaultVariant","defaultSize","hasFormId","DialogFooter","primaryAction","secondaryAction","tertiaryAction","footerContent","hasActions","variantSizeMap","heightVariants","Heading","Tag","height","sizeClasses","heightClasses","DialogHeader","title","onClose","hideCloseIcon","titleAlign","hasBackArrow","onBack","headerContent","Skeleton","width","animation","gradient","flex","stack","responsive","delay","adjustAnimationSpeedBasedOnWidth","dataTestId","visible","setVisible","timer","baseClasses","animationSpeed","numWidth","animationClasses","shapeClasses","layoutClasses","responsiveStyles","breakpoint","value","lineWidth","index","cardVariantStyles","cardBaseStyles","aspectRatioStyles","footerAlignStyles","Card","layout","CardHeader","subtitle","actions","CardMedia","src","aspectRatio","CardContent","fill","defaultPadding","CardFooter","align","ErrorBoundary","__publicField","error","errorInfo","ModalBackdrop","transparent","ModalOverlay","composeRenderProps","SWIPE_DISMISS_THRESHOLD","SWIPE_VELOCITY_THRESHOLD","Tray","isOpen","isDismissable","transparentOverlay","maxHeight","maxWidth","contentPadding","showHandle","animationVariant","isHandleAnimating","setIsHandleAnimating","dragOffset","setDragOffset","isTransitioning","setIsTransitioning","viewport","viewportHeight","containerRef","useRef","scrollContentRef","transitionTimeoutRef","dragStateRef","scrollEl","focusScrollTimeout","handleFocusIn","e","handlePointerDown","useCallback","handlePointerMove","isDragging","startY","pointerId","deltaY","handlePointerEnd","startTime","elapsed","velocity","threshold","hasHeader","hasFooter","open","Modal","RACDialog","Dialog","minWidth","mobileMaxHeight","mobileHeight","isMobile","mobileDialogRef","handleMobileDialogScroll","dialogRef","mobileScrollContentRef","handleDialogScroll","isControlled","Form","RACForm","DialogForm","formId","onSubmit","primaryLabel","secondaryLabel","onCancel","primaryVariant","secondaryVariant","dialogProps","form","Drawer","slideInFrom","DrawerForm","drawerProps","FormActions","gapClass","colsToClass","cols","base","md","lg","FormGrid","gap","InputWrapper","React","Description","FormSection","description","showDivider","FormDivider","FormStepper","steps","currentStepId","onStepClick","currentIndex","s","step","isActive","isCompleted","isClickable","SaveBar","show","isSubmitting","UnsavedChangesPrompt","when","message","wt","handler","useWizard","initialStepId","canNavigate","setCurrentStepId","Nt","stepIndex","hasPrev","hasNext","goTo","id"],"mappings":"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","file":"index.js","sourcesContent":["\"use client\";\n\nimport React, { useCallback, useEffect, useRef } from \"react\";\nimport { Modal, Dialog as RACDialog } from \"react-aria-components\";\nimport { twMerge } from \"tailwind-merge\";\nimport { useMediaQuery } from \"../../hooks/useMediaQuery\";\nimport { useVisualViewportHeight } from \"../../hooks/useVisualViewportHeight\";\nimport { DialogFooter } from \"../DialogFooter\";\nimport { DialogHeader } from \"../DialogHeader\";\nimport { ErrorBoundary } from \"../ErrorBoundary\";\nimport { ModalBackdrop } from \"../ModalBackdrop\";\nimport { Tray } from \"../Tray\";\nimport type { DialogFooterConfig, DialogHeaderConfig } from \"./types\";\n\nexport interface DialogProps extends Omit<DialogHeaderConfig, \"onClose\">, DialogFooterConfig {\n /**\n * Whether the dialog is open (controlled mode)\n * When using DialogTrigger, leave this undefined for automatic state management\n * @default undefined\n */\n isOpen?: boolean;\n /**\n * Callback when the dialog is closed (controlled mode)\n * When using DialogTrigger, leave this undefined for automatic state management\n * @default undefined\n */\n onClose?: () => void;\n /**\n * Dialog content\n */\n children: React.ReactNode;\n /**\n * Whether to use a transparent backdrop\n * @default false\n */\n transparentOverlay?: boolean;\n /**\n * Maximum width of the dialog\n * @default \"600px\"\n */\n maxWidth?: string;\n /**\n * Minimum width of the dialog (desktop only, mobile uses full width)\n * @default \"400px\"\n */\n minWidth?: string;\n /**\n * Maximum height of the dialog on desktop\n * @default \"85vh\"\n */\n maxHeight?: string;\n /**\n * Explicit height of the dialog on desktop (overrides maxHeight if set)\n * Content will scroll within this fixed height\n * @default undefined\n */\n height?: string;\n /**\n * Maximum height of the dialog on mobile (tray version)\n * @default \"90vh\"\n */\n mobileMaxHeight?: string;\n /**\n * Explicit height of the dialog on mobile (overrides mobileMaxHeight if set)\n * Content will scroll within this fixed height\n * @default undefined\n */\n mobileHeight?: string;\n /**\n * Whether to include padding inside the content area\n * @default true\n */\n contentPadding?: boolean;\n /**\n * Additional CSS classes\n */\n className?: string;\n}\n\n/**\n * Dialog\n *\n * Responsive modal dialog component with backdrop.\n *\n * **Desktop (≥768px):** Centered modal with scale and fade animation\n * **Mobile (<768px):** Uses Tray component for native bottom sheet experience with drag handle\n *\n * Includes optional header with title/back button and footer with action buttons.\n *\n * ## Usage Patterns\n *\n * ### Uncontrolled with DialogTrigger (Recommended)\n * ```tsx\n * import { DialogTrigger, Dialog, Button } from \"@texturehq/edges\";\n *\n * <DialogTrigger>\n * <Button>Open Dialog</Button>\n * <Dialog title=\"My Dialog\">\n * <p>Dialog content</p>\n * </Dialog>\n * </DialogTrigger>\n * ```\n *\n * ### Controlled (Advanced)\n * ```tsx\n * const [isOpen, setIsOpen] = useState(false);\n *\n * <Dialog isOpen={isOpen} onClose={() => setIsOpen(false)} title=\"My Dialog\">\n * <p>Dialog content</p>\n * </Dialog>\n * ```\n */\nexport function Dialog({\n isOpen,\n onClose,\n title,\n headerContent,\n titleAlign = \"left\",\n hideCloseIcon = false,\n hasBackArrow = false,\n onBack,\n children,\n primaryAction,\n secondaryAction,\n tertiaryAction,\n footerContent,\n transparentOverlay = false,\n maxWidth = \"600px\",\n minWidth = \"400px\",\n maxHeight = \"85vh\",\n height,\n mobileMaxHeight = \"90vh\",\n mobileHeight,\n contentPadding = true,\n className,\n}: DialogProps) {\n // Check if we're on mobile - must be called before any early returns\n const isMobile = useMediaQuery(\"(max-width: 767px)\");\n\n // Track visual viewport height to handle iOS soft keyboard pushing the tray under the keyboard.\n // Only active on mobile in uncontrolled mode (isOpen===undefined). In controlled mode, Dialog\n // delegates to <Tray> which manages its own visualViewport subscription — enabling both would\n // create duplicate listeners and unnecessary re-renders.\n const viewport = useVisualViewportHeight(isMobile && isOpen === undefined);\n const viewportHeight = viewport?.height ?? null;\n const keyboardOffset = viewport?.keyboardOffset ?? 0;\n\n // Ref to prevent unwanted scroll on the dialog container (used for mobile uncontrolled mode)\n // When focus moves to an element inside the dialog, the browser may try to\n // scroll the dialog container itself (even with overflow:hidden) to bring\n // the focused element into view. This causes the entire dialog to shift up.\n const mobileDialogRef = useRef<HTMLElement>(null);\n\n // Reset any unwanted scroll on the mobile dialog container\n const handleMobileDialogScroll = useCallback(() => {\n if (mobileDialogRef.current && mobileDialogRef.current.scrollTop !== 0) {\n mobileDialogRef.current.scrollTop = 0;\n }\n }, []);\n\n // Ref to prevent unwanted scroll on the desktop dialog container\n const dialogRef = useRef<HTMLElement>(null);\n\n // Ref for the scrollable content area in the mobile uncontrolled path.\n const mobileScrollContentRef = useRef<HTMLDivElement>(null);\n\n // On iOS, focusing an input inside a non-body scroll container won't automatically\n // scroll it into view. Listen for focusin and manually scroll after the keyboard settles.\n useEffect(() => {\n const scrollEl = mobileScrollContentRef.current;\n if (!scrollEl || !isMobile) return;\n\n let focusScrollTimeout: ReturnType<typeof setTimeout> | null = null;\n\n const handleFocusIn = (e: FocusEvent) => {\n const target = e.target as HTMLElement | null;\n if (!target) return;\n if (![\"INPUT\", \"TEXTAREA\", \"SELECT\"].includes(target.tagName)) return;\n if (focusScrollTimeout) clearTimeout(focusScrollTimeout);\n focusScrollTimeout = setTimeout(() => {\n target.scrollIntoView({ block: \"nearest\", behavior: \"smooth\" });\n }, 320);\n };\n\n scrollEl.addEventListener(\"focusin\", handleFocusIn);\n return () => {\n scrollEl.removeEventListener(\"focusin\", handleFocusIn);\n if (focusScrollTimeout) clearTimeout(focusScrollTimeout);\n };\n }, [isMobile]);\n\n // Reset any unwanted scroll on the desktop dialog container\n const handleDialogScroll = useCallback(() => {\n if (dialogRef.current && dialogRef.current.scrollTop !== 0) {\n dialogRef.current.scrollTop = 0;\n }\n }, []);\n\n // In controlled mode, don't render if closed\n if (isOpen === false) return null;\n\n const hasHeader = title || headerContent;\n const hasFooter = primaryAction || secondaryAction || tertiaryAction || footerContent;\n\n // Determine if we're in controlled mode\n const isControlled = isOpen !== undefined;\n\n // On mobile, use Tray component\n if (isMobile) {\n // In uncontrolled mode (when used with DialogTrigger), we need to return the Tray\n // but let DialogTrigger handle the state. We can't use Tray directly in uncontrolled mode\n // because Tray requires isOpen prop. So we need to wrap it similarly to desktop.\n if (!isControlled) {\n // For uncontrolled mode, render nothing - DialogTrigger will handle rendering\n // This is a limitation: mobile will fall through to desktop rendering for uncontrolled mode\n return (\n <ErrorBoundary>\n <ModalBackdrop\n isDismissable\n transparent={transparentOverlay}\n style={{\n paddingBottom: keyboardOffset > 0 ? `${keyboardOffset}px` : undefined,\n transition: \"padding-bottom 0.25s ease-out\",\n }}\n className=\"flex items-end justify-center\"\n >\n <Modal className=\"w-full p-0 outline-none focus:outline-none focus-visible:outline-none ring-0 focus:ring-0 focus-visible:ring-0\">\n <RACDialog\n ref={mobileDialogRef}\n onScroll={handleMobileDialogScroll}\n className={twMerge(\n \"relative flex w-full flex-col\",\n \"bg-background-surface\",\n \"shadow-2xl shadow-black/20\",\n \"border-t border-x border-border-default/40\",\n \"rounded-t-xl\",\n \"overflow-hidden\",\n \"animate-in slide-in-from-bottom\",\n \"duration-300 ease-out\",\n \"data-[exiting]:animate-out data-[exiting]:slide-out-to-bottom\",\n \"data-[exiting]:duration-200 data-[exiting]:ease-in\",\n className\n )}\n style={{\n // Cap height to the visual viewport so the tray stays above the iOS keyboard.\n // dvh = dynamic viewport height (shrinks with iOS keyboard on Safari 15.4+).\n // visualViewport JS value = live tracking for older Safari / edge cases.\n ...(mobileHeight\n ? { height: mobileHeight }\n : {\n // CSS min() only accepts <length-percentage>, not keywords (e.g. \"none\",\n // \"max-content\"). If mobileMaxHeight is a bare keyword, pass it through;\n // otherwise compose with the live viewport clamp.\n maxHeight: /\\d/.test(mobileMaxHeight)\n ? viewportHeight !== null\n ? `min(${mobileMaxHeight}, ${Math.max(viewportHeight - 8, 0)}px, 100dvh)`\n : `min(${mobileMaxHeight}, 100dvh)`\n : mobileMaxHeight,\n }),\n }}\n >\n <div className=\"flex justify-center pt-2\">\n <div className=\"h-1.5 w-12 rounded-full bg-border-muted\" />\n </div>\n {hasHeader &&\n (hasBackArrow ? (\n <DialogHeader\n title={title}\n headerContent={headerContent}\n titleAlign={titleAlign}\n hideCloseIcon={hideCloseIcon || !onClose}\n hasBackArrow={true}\n onBack={onBack!}\n onClose={\n onClose ||\n (() => {\n /* no-op for uncontrolled mode */\n })\n }\n />\n ) : (\n <DialogHeader\n title={title}\n headerContent={headerContent}\n titleAlign={titleAlign}\n hideCloseIcon={hideCloseIcon || !onClose}\n onClose={\n onClose ||\n (() => {\n /* no-op for uncontrolled mode */\n })\n }\n />\n ))}\n <div\n ref={mobileScrollContentRef}\n className={twMerge(\n \"flex-1 min-h-0 overflow-y-auto overscroll-contain\",\n contentPadding ? \"px-6 py-6\" : \"p-0\"\n )}\n >\n {children}\n </div>\n {hasFooter && (\n <DialogFooter\n primaryAction={primaryAction}\n secondaryAction={secondaryAction}\n tertiaryAction={tertiaryAction}\n footerContent={footerContent}\n />\n )}\n </RACDialog>\n </Modal>\n </ModalBackdrop>\n </ErrorBoundary>\n );\n }\n\n // Controlled mode - use Tray\n return (\n <Tray\n isOpen={isOpen}\n onClose={onClose}\n title={title}\n headerContent={headerContent}\n titleAlign={titleAlign}\n hideCloseIcon={hideCloseIcon}\n hasBackArrow={hasBackArrow}\n onBack={onBack}\n primaryAction={primaryAction}\n secondaryAction={secondaryAction}\n footerContent={footerContent}\n transparentOverlay={transparentOverlay}\n maxHeight={mobileMaxHeight}\n height={mobileHeight}\n maxWidth={maxWidth}\n contentPadding={contentPadding}\n showHandle={true}\n animationVariant=\"scale\"\n className={className}\n >\n {children}\n </Tray>\n );\n }\n\n // On desktop, use centered modal\n return (\n <ErrorBoundary>\n <ModalBackdrop\n // Only pass isOpen/onOpenChange in controlled mode\n {...(isControlled\n ? {\n isOpen: isOpen,\n onOpenChange: (open) => {\n if (!open && onClose) onClose();\n },\n }\n : {})}\n isDismissable\n transparent={transparentOverlay}\n className=\"flex items-center justify-center\"\n >\n <Modal\n className=\"w-full p-4 outline-none focus:outline-none focus-visible:outline-none ring-0 focus:ring-0 focus-visible:ring-0\"\n style={{ maxWidth }}\n >\n <RACDialog\n ref={dialogRef}\n onScroll={handleDialogScroll}\n className={twMerge(\n // Base structure\n \"relative flex w-full flex-col\",\n // Visual styling\n \"bg-background-surface\",\n \"shadow-2xl shadow-black/20\",\n \"border border-border-default/50\",\n // Layout\n \"rounded-md\",\n \"overflow-hidden\",\n // Remove browser focus outline/ring on the dialog container\n \"outline-none focus:outline-none focus-visible:outline-none ring-0 focus:ring-0\",\n // Desktop: scale and fade animation\n \"animate-in fade-in zoom-in-96 slide-in-from-bottom-2\",\n \"duration-300 ease-out\",\n // Exit animations\n \"data-[exiting]:animate-out data-[exiting]:fade-out data-[exiting]:zoom-out-95\",\n \"data-[exiting]:duration-200 data-[exiting]:ease-in\",\n className\n )}\n style={{\n minWidth,\n ...(height ? { height } : { maxHeight }),\n }}\n >\n {hasHeader &&\n (hasBackArrow ? (\n <DialogHeader\n title={title}\n headerContent={headerContent}\n titleAlign={titleAlign}\n hideCloseIcon={hideCloseIcon || !onClose}\n hasBackArrow={true}\n onBack={onBack!}\n onClose={\n onClose ||\n (() => {\n /* no-op for uncontrolled mode */\n })\n }\n />\n ) : (\n <DialogHeader\n title={title}\n headerContent={headerContent}\n titleAlign={titleAlign}\n hideCloseIcon={hideCloseIcon || !onClose}\n onClose={\n onClose ||\n (() => {\n /* no-op for uncontrolled mode */\n })\n }\n />\n ))}\n <div className={twMerge(\"flex-1 min-h-0 overflow-y-auto\", contentPadding ? \"px-6 py-6\" : \"p-0\")}>\n {children}\n </div>\n {hasFooter && (\n <DialogFooter\n primaryAction={primaryAction}\n secondaryAction={secondaryAction}\n tertiaryAction={tertiaryAction}\n footerContent={footerContent}\n />\n )}\n </RACDialog>\n </Modal>\n </ModalBackdrop>\n </ErrorBoundary>\n );\n}\n\n// Export types\nexport type {\n DialogAction,\n DialogFooterConfig,\n DialogHeaderConfig,\n} from \"./types\";\n","import { useEffect, useState } from \"react\";\n\n/**\n * Hook to check if a media query matches the current viewport\n *\n * @param query - A CSS media query string (e.g., \"(min-width: 768px)\")\n * @param defaultValue - The default value to return during SSR or before the first render\n * @returns A boolean indicating whether the media query matches\n *\n * @example\n * ```tsx\n * const isMobile = useMediaQuery('(max-width: 767px)');\n * const prefersReducedMotion = useMediaQuery('(prefers-reduced-motion: reduce)');\n * const isLandscape = useMediaQuery('(orientation: landscape)');\n * ```\n */\nexport function useMediaQuery(query: string, defaultValue = false): boolean {\n const [matches, setMatches] = useState<boolean>(defaultValue);\n\n useEffect(() => {\n // Return early if window is not available (SSR)\n if (typeof window === \"undefined\") return;\n\n const mediaQueryList = window.matchMedia(query);\n\n // Set initial value\n setMatches(mediaQueryList.matches);\n\n // Handler for when the media query match state changes\n const handleChange = (event: MediaQueryListEvent) => {\n setMatches(event.matches);\n };\n\n // Listen for changes\n mediaQueryList.addEventListener(\"change\", handleChange);\n\n // Cleanup\n return () => {\n mediaQueryList.removeEventListener(\"change\", handleChange);\n };\n }, [query]);\n\n return matches;\n}\n","import { useEffect, useState } from \"react\";\n\nexport interface VisualViewportState {\n /** Current visual viewport height in px */\n height: number;\n /**\n * Pixels to shift a position:fixed element upward so it sits above the keyboard.\n * = window.innerHeight - visualViewport.height - visualViewport.offsetTop\n * Zero when no keyboard is open.\n */\n keyboardOffset: number;\n}\n\n/**\n * useVisualViewportHeight\n *\n * Tracks `window.visualViewport` to handle the iOS soft keyboard.\n *\n * On iOS Safari, `position: fixed` elements are anchored to the layout viewport\n * (full page size) and don't move when the keyboard opens. This hook returns:\n *\n * - `height`: the visible viewport height (shrinks when keyboard opens)\n * - `keyboardOffset`: how many px to translate a fixed element upward to clear the keyboard\n *\n * Returns `null` on SSR or in browsers that don't support `visualViewport`.\n */\nexport function useVisualViewportHeight(enabled = true): VisualViewportState | null {\n const [state, setState] = useState<VisualViewportState | null>(null);\n\n useEffect(() => {\n if (!enabled) {\n // Reset stale state so the next open doesn't briefly flash the old viewport height.\n setState(null);\n return;\n }\n\n const vv = typeof window !== \"undefined\" ? window.visualViewport : null;\n if (!vv) return;\n\n const update = () => {\n // keyboard offset = how far the visual viewport has been pushed up from the bottom\n // of the layout viewport by the keyboard.\n const keyboardOffset = Math.max(0, window.innerHeight - vv.height - (vv.offsetTop ?? 0));\n setState({ height: vv.height, keyboardOffset });\n };\n\n update();\n\n vv.addEventListener(\"resize\", update);\n vv.addEventListener(\"scroll\", update);\n return () => {\n vv.removeEventListener(\"resize\", update);\n vv.removeEventListener(\"scroll\", update);\n };\n }, [enabled]);\n\n return state;\n}\n","type ClassValue = string | false | null | undefined;\n\n/**\n * Small className joiner for generated semantic utilities that tailwind-merge\n * does not understand yet. Use when preserving both a typography role class\n * (`text-heading-md`) and a semantic color class (`text-text-primary`) matters.\n */\nexport function cx(...classNames: ClassValue[]): string {\n return classNames.filter(Boolean).join(\" \");\n}\n","import { cx } from \"./classNames\";\n\n/**\n * Semantic typography role classes generated by @texturehq/edges-tokens.\n *\n * These classes apply the full type role — family, size, line-height,\n * weight, and letter-spacing. Pair them with explicit semantic text-color\n * utilities at the callsite.\n */\nexport const typographyRole = {\n displayXl: \"text-display-xl\",\n displayLg: \"text-display-lg\",\n displayMd: \"text-display-md\",\n displaySm: \"text-display-sm\",\n headingXl: \"text-heading-xl\",\n headingLg: \"text-heading-lg\",\n headingMd: \"text-heading-md\",\n headingSm: \"text-heading-sm\",\n bodyLg: \"text-body-lg\",\n bodyMd: \"text-body-md\",\n bodySm: \"text-body-sm\",\n labelLg: \"text-label-lg\",\n labelMd: \"text-label-md\",\n labelSm: \"text-label-sm\",\n code: \"text-code\",\n agent: \"text-agent\",\n} as const;\n\nexport type TypographyRole = keyof typeof typographyRole;\n\n/**\n * Merge a semantic typography role with semantic color utilities and any\n * component-specific layout classes. This keeps components from hand-composing\n * `text-sm font-medium leading-*` whenever a role exists.\n */\nexport function typeRole(role: TypographyRole, ...classNames: Array<string | false | null | undefined>): string {\n return cx(typographyRole[role], ...classNames);\n}\n","import { composeRenderProps } from \"react-aria-components\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport type { BrandProviderProps, BrandVariables } from \"./BrandProvider\";\nexport { BrandProvider } from \"./BrandProvider\";\nexport { ColorModeProvider, useColorMode } from \"./ColorModeProvider\";\nexport { cx } from \"./classNames\";\n\n// Re-export formatting utilities from the new formatting module\nexport * from \"./formatting\";\n\n// Re-export time formatting utilities\nexport * from \"./timeFormat\";\n\n// Re-export semantic typography role helpers\nexport * from \"./typography\";\n\nexport function focusRing(showDefaultOutline: boolean = false) {\n // Use data-[focus-visible] instead of :focus-visible to work with React Aria's focus management\n const baseClasses = showDefaultOutline\n ? \"outline outline-1 outline-border-input data-[focus-visible]:outline-2 data-[focus-visible]:outline-action-default data-[focus-visible]:outline-offset-0 invalid:outline-2 invalid:outline-feedback-error-border group-invalid:outline-2 group-invalid:outline-feedback-error-border forced-colors:focus:outline-[Highlight] forced-colors:focus:outline-2 forced-colors:focus:outline-offset-2\"\n : \"outline-none data-[focus-visible]:outline data-[focus-visible]:outline-2 data-[focus-visible]:outline-action-default data-[focus-visible]:outline-offset-0 invalid:outline-2 invalid:outline-feedback-error-border group-invalid:outline-2 group-invalid:outline-feedback-error-border forced-colors:focus:outline-[Highlight] forced-colors:focus:outline-2 forced-colors:focus:outline-offset-2\";\n return `${baseClasses}`;\n}\n\nexport function composeTailwindRenderProps<T>(\n className: string | ((v: T) => string) | undefined,\n tw: string\n): string | ((v: T) => string) {\n return composeRenderProps(className, (className) => twMerge(tw, className));\n}\n","/**\n * Control-specific style utilities for form elements and interactive components.\n * These styles use CSS variables defined in the theme for consistent sizing\n * and spacing across all control elements.\n *\n * Text sizes follow the relationships defined in theme.css:\n * sm: --control-text-sm (maps to --text-xs)\n * md: --control-text-md (maps to --text-sm)\n * lg: --control-text-lg (maps to --text-base)\n * xl: --control-text-xl (maps to --text-lg)\n */\n\nexport type Size = \"sm\" | \"md\" | \"lg\" | \"xl\";\n\nexport const controlStyles = {\n sm: {\n text: \"text-[length:var(--control-text-sm)]\",\n height: \"h-[var(--control-sm-height)]\",\n padding: \"px-[var(--control-padding-sm)]\",\n paddingY: \"py-[var(--control-gap-sm)]\",\n gap: \"gap-[var(--control-gap-sm)]\",\n },\n md: {\n text: \"text-[length:var(--control-text-md)]\",\n height: \"h-[var(--control-md-height)]\",\n padding: \"px-[var(--control-padding-md)]\",\n paddingY: \"py-[var(--control-gap-md)]\",\n gap: \"gap-[var(--control-gap-md)]\",\n },\n lg: {\n text: \"text-[length:var(--control-text-lg)]\",\n height: \"h-[var(--control-lg-height)]\",\n padding: \"px-[var(--control-padding-lg)]\",\n paddingY: \"py-[var(--control-gap-lg)]\",\n gap: \"gap-[var(--control-gap-lg)]\",\n },\n xl: {\n text: \"text-[length:var(--control-text-xl)]\",\n height: \"h-[var(--control-xl-height)]\",\n padding: \"px-[var(--control-padding-xl)]\",\n paddingY: \"py-[var(--control-gap-xl)]\",\n gap: \"gap-[var(--control-gap-xl)]\",\n },\n} as const;\n","\"use client\";\nimport type { IconProps, Icon as PhosphorIcon } from \"@phosphor-icons/react\";\nimport { forwardRef, type ReactNode } from \"react\";\n\n/**\n * Factory for Texture-authored icons that are NOT available in Phosphor but\n * must plug into the Edges `<Icon name=\"…\" />` component with the exact same\n * API (size / color / weight / className / mirrored / aria-*).\n *\n * Each custom icon is authored as a Phosphor-compatible component:\n * - 256×256 viewBox (matches Phosphor's optical grid so custom + stock icons\n * sit at the same scale)\n * - `fill={color}` defaulting to `currentColor` (inherits text color like Phosphor)\n * - `size` drives both width and height\n *\n * `weight` is accepted for API parity but is a no-op for single-weight custom\n * glyphs. Author the `children` against the 256×256 grid.\n *\n * @example\n * ```tsx\n * export const TextureRecloserIcon = createTextureIcon(\n * \"TextureRecloser\",\n * <path d=\"M48 128 ...\" />,\n * );\n * ```\n */\nexport function createTextureIcon(displayName: string, children: ReactNode): PhosphorIcon {\n const Component = forwardRef<SVGSVGElement, IconProps>(\n ({ size = 24, color = \"currentColor\", className, mirrored, alt, ...rest }, ref) => {\n // The Edges `Icon` wrapper always layers on an accessible name via\n // `aria-label` (spread through `rest`). Treat the glyph as decorative\n // ONLY when neither an explicit `alt` nor an inherited `aria-label`\n // is present — otherwise a hard-coded `aria-hidden` would silence the\n // very label the wrapper just set, hiding custom glyphs from SR users.\n const hasAccessibleName = Boolean(alt) || \"aria-label\" in rest;\n return (\n <svg\n ref={ref}\n xmlns=\"http://www.w3.org/2000/svg\"\n width={size}\n height={size}\n viewBox=\"0 0 256 256\"\n fill={color}\n className={className}\n transform={mirrored ? \"scale(-1, 1)\" : undefined}\n aria-hidden={hasAccessibleName ? undefined : true}\n role={hasAccessibleName ? \"img\" : undefined}\n aria-label={alt}\n {...rest}\n >\n {children}\n </svg>\n );\n }\n );\n\n Component.displayName = displayName;\n // Custom icons are single-weight; the cast aligns the factory output with the\n // Phosphor `Icon` component type so both resolve uniformly in the registry.\n return Component as unknown as PhosphorIcon;\n}\n","\"use client\";\nimport type { Icon as PhosphorIcon } from \"@phosphor-icons/react\";\nimport { createTextureIcon } from \"./createTextureIcon\";\n\n/**\n * Texture-authored custom icons.\n *\n * These glyphs are NOT in @phosphor-icons/react but plug into the Edges\n * `<Icon name=\"…\" />` component with the same API. Each is authored via\n * `createTextureIcon` (256×256 viewBox, currentColor fill) so it resolves\n * uniformly alongside Phosphor icons.\n *\n * NAMING: every custom icon MUST be prefixed `Texture*`. Phosphor ships ~1,500\n * names and adds more each release; the prefix guarantees a future Phosphor\n * release can never silently shadow a custom icon, and makes it obvious in\n * call sites (e.g. ENTITY_CONFIG) which icons are bespoke. The disjoint-keyset\n * assertion in Icon.tsx enforces this in development.\n *\n * NOTE: the paths below are PLACEHOLDER glyphs (simple, legible stand-ins) so\n * the pattern is wired end-to-end. Replace the `children` with the real\n * Texture-designed SVG paths when they're ready — no other code changes needed.\n */\n\n/**\n * Shared switching-device geometry (256 grid, centered on y=128).\n *\n * The switching family — Switch, Breaker, Recloser, Motor Switch, Sectionalizer\n * — all share one SPST contact base (two terminal poles + leads). Each device\n * swings a blade UP (open) or near-flat across the poles (closed), giving every\n * switchable element a real open/closed geometry, and rides a distinguishing\n * marker on the blade midpoint:\n * • Switch — no marker\n * • Breaker — outlined square (the ANSI breaker box)\n * • Recloser — outlined circle (auto-reclose)\n * • Motor Switch — outlined diamond\n * • Sectionalizer — fuse cartridge (fuse-switch combo)\n *\n * STATE = geometry (open vs closed), so the variants are distinct glyphs wired\n * via EntityConfig.states. STATUS COLOR stays a render-layer overlay\n * (GRID_STATE_COLORS) — never baked into these glyphs.\n *\n * Blade midpoints: open ≈ (127,95), closed ≈ (127,125).\n */\nconst SwitchContactBase = () => (\n <>\n <path d=\"M12 128h44M200 128h44\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"16\" strokeLinecap=\"round\" />\n <circle cx=\"76\" cy=\"128\" r=\"20\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"16\" />\n <circle cx=\"180\" cy=\"128\" r=\"20\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"16\" />\n </>\n);\nconst OpenBlade = () => (\n <path d=\"M166 120 88 70\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"16\" strokeLinecap=\"round\" />\n);\nconst ClosedBlade = () => (\n <path d=\"M162 122 92 128\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"16\" strokeLinecap=\"round\" />\n);\n\n/**\n * Recloser — a bold \"R\" inside a square. The letter is a real typeface glyph\n * (SVG <text>) so it reads cleanly at any size. State (open/closed) is NOT\n * expressed geometrically here — the letter-badge is a stable identity mark;\n * live open/closed status is conveyed by the render-layer color overlay.\n */\nconst TextureRecloser = createTextureIcon(\n \"TextureRecloser\",\n <>\n <rect x=\"36\" y=\"36\" width=\"184\" height=\"184\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"16\" />\n <text\n x=\"128\"\n y=\"126\"\n textAnchor=\"middle\"\n dominantBaseline=\"central\"\n fontFamily=\"ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif\"\n fontSize=\"140\"\n fontWeight=\"700\"\n fill=\"currentColor\"\n stroke=\"none\"\n >\n R\n </text>\n </>\n);\n\n/**\n * Fuse — a single stroked sine cycle (one up/down bump) on a horizontal lead,\n * extending flat to both edges. Starts from Phosphor's WaveSine motif but is a\n * thin stroked line (not the filled glyph) with leads, matching the schematic\n * fuse symbol. Authored on the 256 grid, centered on y=128.\n */\nconst TextureFuse = createTextureIcon(\n \"TextureFuse\",\n <path\n d=\"M20 128h72q18 -84 36 0q18 84 36 0h72\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"16\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n);\n\n/**\n * Breaker — a bold \"B\" inside a square. The letter is a real typeface glyph\n * (SVG <text>) so it reads cleanly at any size. State (open/closed) is NOT\n * expressed geometrically here — the letter-badge is a stable identity mark;\n * live open/closed status is conveyed by the render-layer color overlay.\n */\nconst TextureBreaker = createTextureIcon(\n \"TextureBreaker\",\n <>\n <rect x=\"36\" y=\"36\" width=\"184\" height=\"184\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"16\" />\n <text\n x=\"128\"\n y=\"126\"\n textAnchor=\"middle\"\n dominantBaseline=\"central\"\n fontFamily=\"ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif\"\n fontSize=\"140\"\n fontWeight=\"700\"\n fill=\"currentColor\"\n stroke=\"none\"\n >\n B\n </text>\n </>\n);\n\n/**\n * Source — the standard AC source symbol: a single stroked sine cycle (matching\n * the Fuse wave, minus the leads) centered inside a circle, with short\n * horizontal leads extending to each side.\n */\nconst TextureSource = createTextureIcon(\n \"TextureSource\",\n <>\n <path d=\"M4 128h40M212 128h40\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"16\" strokeLinecap=\"round\" />\n <circle cx=\"128\" cy=\"128\" r=\"84\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"16\" />\n <path\n d=\"M92 128q18 -84 36 0q18 84 36 0\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"16\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </>\n);\n\n/**\n * Capacitor — the standard schematic symbol: two parallel vertical plates in\n * the center with horizontal leads extending to each side.\n */\nconst TextureCapacitor = createTextureIcon(\n \"TextureCapacitor\",\n <>\n <path\n d=\"M4 128h106M146 128h106M110 72v112M146 72v112\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"16\"\n strokeLinecap=\"round\"\n />\n </>\n);\n\n/**\n * Regulator — a bold \"V\" inside a circle (mirrors the Recloser treatment, which\n * is an \"R\" in a square). The letter is a real typeface glyph (SVG <text>) so it\n * reads cleanly at any size.\n */\nconst TextureRegulator = createTextureIcon(\n \"TextureRegulator\",\n <>\n <circle cx=\"128\" cy=\"128\" r=\"92\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"16\" />\n <text\n x=\"128\"\n y=\"126\"\n textAnchor=\"middle\"\n dominantBaseline=\"central\"\n fontFamily=\"ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif\"\n fontSize=\"128\"\n fontWeight=\"700\"\n fill=\"currentColor\"\n stroke=\"none\"\n >\n V\n </text>\n </>\n);\n\n/**\n * Switch — SPST contact, no marker. Open swings the blade up; closed lays it\n * near-flat across the poles. Centered on y=128 via the shared base.\n */\nconst TextureSwitch = createTextureIcon(\n \"TextureSwitch\",\n <>\n <SwitchContactBase />\n <OpenBlade />\n </>\n);\n\nconst TextureSwitchClosed = createTextureIcon(\n \"TextureSwitchClosed\",\n <>\n <SwitchContactBase />\n <ClosedBlade />\n </>\n);\n\n/**\n * Sectionalizer — fuse-switch combo: the contact base with a fuse cartridge\n * (outlined rounded rect, IEC fuse motif) on the blade. Open and closed\n * variants swing the blade; the cartridge rides its midpoint, rotated to match.\n */\nconst TextureSectionalizerOpen = createTextureIcon(\n \"TextureSectionalizerOpen\",\n <>\n <SwitchContactBase />\n <OpenBlade />\n <rect\n x=\"97\"\n y=\"79\"\n width=\"60\"\n height=\"32\"\n rx=\"8\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"12\"\n transform=\"rotate(-32.6 127 95)\"\n />\n </>\n);\nconst TextureSectionalizerClosed = createTextureIcon(\n \"TextureSectionalizerClosed\",\n <>\n <SwitchContactBase />\n <ClosedBlade />\n <rect\n x=\"97\"\n y=\"109\"\n width=\"60\"\n height=\"32\"\n rx=\"8\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"12\"\n transform=\"rotate(-4.9 127 125)\"\n />\n </>\n);\n\n/**\n * Transformer — the standard schematic symbol: two facing windings (coils),\n * each drawn as a vertical stack of three semicircular bumps with horizontal\n * leads at top and bottom. Left coil bulges right, right coil bulges left, so\n * the two windings face each other across the core gap. Authored on the 256\n * grid; coils span y=64→196 (3 bumps, r=22).\n */\nconst TextureTransformer = createTextureIcon(\n \"TextureTransformer\",\n <>\n {/* left winding — bumps bulge right, leads exit left */}\n <path\n d=\"M40 64H88A22 22 0 0 1 88 108A22 22 0 0 1 88 152A22 22 0 0 1 88 196H40\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"16\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n {/* right winding — bumps bulge left, leads exit right */}\n <path\n d=\"M216 64H168A22 22 0 0 0 168 108A22 22 0 0 0 168 152A22 22 0 0 0 168 196H216\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"16\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </>\n);\n\n/**\n * Phase × medium line matrix. Lines are drawn as N parallel horizontal\n * conductors (1/2/3 = single/two/three-phase), SOLID for overhead and DASHED\n * for underground (buried / not visible). Authored on the 256 grid; the\n * conductor stack is vertically centered on y=128 with 36u spacing. The dash\n * uses pathLength=100 + \"20 20\" so it tiles evenly with no clipped end dash.\n */\nconst PHASE_YS = { 1: [128], 2: [110, 146], 3: [92, 128, 164] } as const;\n\nconst solidLine = (y: number) => (\n <path key={y} d={`M24 ${y}h208`} fill=\"none\" stroke=\"currentColor\" strokeWidth=\"16\" strokeLinecap=\"round\" />\n);\nconst dashedLine = (y: number) => (\n <path\n key={y}\n d={`M24 ${y}h208`}\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"16\"\n strokeLinecap=\"round\"\n pathLength={100}\n strokeDasharray=\"20 20\"\n />\n);\n\nconst TextureSinglePhaseOverheadLine = createTextureIcon(\n \"TextureSinglePhaseOverheadLine\",\n <>{PHASE_YS[1].map(solidLine)}</>\n);\nconst TextureTwoPhaseOverheadLine = createTextureIcon(\"TextureTwoPhaseOverheadLine\", <>{PHASE_YS[2].map(solidLine)}</>);\nconst TextureThreePhaseOverheadLine = createTextureIcon(\n \"TextureThreePhaseOverheadLine\",\n <>{PHASE_YS[3].map(solidLine)}</>\n);\nconst TextureSinglePhaseUndergroundLine = createTextureIcon(\n \"TextureSinglePhaseUndergroundLine\",\n <>{PHASE_YS[1].map(dashedLine)}</>\n);\nconst TextureTwoPhaseUndergroundLine = createTextureIcon(\n \"TextureTwoPhaseUndergroundLine\",\n <>{PHASE_YS[2].map(dashedLine)}</>\n);\nconst TextureThreePhaseUndergroundLine = createTextureIcon(\n \"TextureThreePhaseUndergroundLine\",\n <>{PHASE_YS[3].map(dashedLine)}</>\n);\n\n/**\n * Support Structure — a single bold filled dot, larger than Phosphor's Dot, to\n * mark a pole / support point on the network. Centered on the 256 grid.\n */\nconst TextureSupportStructure = createTextureIcon(\n \"TextureSupportStructure\",\n <circle cx=\"128\" cy=\"128\" r=\"40\" fill=\"currentColor\" stroke=\"none\" />\n);\n\n/**\n * Registry of all custom icons, keyed by name. The Edges `Icon` resolver checks\n * this map first, then falls back to Phosphor. `as const satisfies` keeps the\n * keys as a literal union (drives `CustomIconName` + autocomplete) while\n * type-checking each value is a Phosphor-compatible component.\n */\nexport const CUSTOM_ICON_REGISTRY = {\n TextureRecloser,\n TextureFuse,\n TextureBreaker,\n TextureSource,\n TextureCapacitor,\n TextureRegulator,\n TextureSwitch,\n TextureSwitchClosed,\n TextureSectionalizerOpen,\n TextureSectionalizerClosed,\n TextureTransformer,\n TextureSinglePhaseOverheadLine,\n TextureTwoPhaseOverheadLine,\n TextureThreePhaseOverheadLine,\n TextureSinglePhaseUndergroundLine,\n TextureTwoPhaseUndergroundLine,\n TextureThreePhaseUndergroundLine,\n TextureSupportStructure,\n} as const satisfies Record<string, PhosphorIcon>;\n\n/** Union of all custom icon names. Folded into `IconName`. */\nexport type CustomIconName = keyof typeof CUSTOM_ICON_REGISTRY;\n","\"use client\";\nimport type { IconProps as PhosphorIconProps } from \"@phosphor-icons/react\";\nimport * as PhosphorIcons from \"@phosphor-icons/react\";\nimport { memo } from \"react\";\nimport { twMerge } from \"tailwind-merge\";\nimport { CUSTOM_ICON_REGISTRY, type CustomIconName } from \"./customIcons\";\n\n// Type for any Phosphor icon component\ntype PhosphorIconComponent = typeof PhosphorIcons.House;\n\n// Extract all icon names from the Phosphor package\nexport type PhosphorIconName = keyof typeof PhosphorIcons;\n\n// Re-export custom icon names so consumers can reference the union directly.\nexport type { CustomIconName } from \"./customIcons\";\n\n/**\n * All icon names accepted by `<Icon name=\"…\" />` — every Phosphor icon plus\n * Texture's custom icons (see `customIcons/registry.tsx`). Custom names are\n * prefixed `Texture*` and resolve through `CUSTOM_ICON_REGISTRY` first, then\n * Phosphor.\n */\nexport type IconName = PhosphorIconName | CustomIconName;\n\n// Dev-time guard: a custom icon name must never collide with a Phosphor name,\n// otherwise a future Phosphor release could silently shadow (or be shadowed by)\n// a custom glyph. The `Texture*` prefix convention prevents this; this assert\n// makes a violation loud during development instead of a silent wrong-icon.\nif (process.env.NODE_ENV === \"development\") {\n for (const customName of Object.keys(CUSTOM_ICON_REGISTRY)) {\n if (customName in PhosphorIcons) {\n console.error(\n `Custom icon \"${customName}\" collides with a Phosphor icon of the same name. ` +\n `Rename it (use the \"Texture\" prefix) to keep the icon namespace unambiguous.`\n );\n }\n }\n}\n\n// Standard size presets for the design system\nconst sizePresets = {\n xs: 16,\n sm: 20,\n md: 24,\n lg: 32,\n xl: 40,\n \"2xl\": 48,\n} as const;\n\ntype SizePreset = keyof typeof sizePresets;\n\ninterface IconProps extends Omit<PhosphorIconProps, \"size\"> {\n /**\n * The name of the icon to render — any valid icon from @phosphor-icons/react,\n * or a Texture custom icon (see customIcons/registry.tsx).\n */\n name: IconName;\n\n /**\n * Size of the icon - can be a preset or custom number\n */\n size?: SizePreset | number;\n\n /**\n * Accessibility label (maps to aria-label)\n */\n ariaLabel?: string;\n}\n\n/**\n * Icon\n *\n * Icon wrapper component with standardized sizing and styling. Provides access\n * to the full Phosphor icon library PLUS Texture's custom icons through one\n * unified `name` API, with tree-shaking support and design system presets.\n * - TypeScript autocomplete for all icon names (Phosphor + custom)\n *\n * Custom icons resolve through `CUSTOM_ICON_REGISTRY` first, then fall back to\n * Phosphor — so `<Icon name=\"TextureRecloser\" />` works exactly like\n * `<Icon name=\"House\" />`.\n *\n * Usage:\n * ```tsx\n * <Icon name=\"House\" size=\"md\" />\n * <Icon name=\"TextureRecloser\" size={32} className=\"text-brand\" />\n * ```\n */\nexport const Icon = memo(\n ({ name, size = \"md\", color, weight = \"regular\", className, ariaLabel, ...props }: IconProps) => {\n // Resolve the icon: custom registry takes precedence, then Phosphor.\n const IconComponent =\n (CUSTOM_ICON_REGISTRY[name as CustomIconName] as PhosphorIconComponent | undefined) ??\n (PhosphorIcons[name as PhosphorIconName] as PhosphorIconComponent | undefined);\n\n if (!IconComponent) {\n if (process.env.NODE_ENV === \"development\") {\n console.error(`Icon \"${name}\" not found in @phosphor-icons/react or the custom icon registry`);\n }\n return null;\n }\n\n // Resolve size to pixel value\n const resolvedSize = typeof size === \"string\" && size in sizePresets ? sizePresets[size as SizePreset] : size;\n\n // Build className with design system defaults\n const iconClassName = twMerge(\n // Default styles\n \"inline-block flex-shrink-0\",\n // Allow color inheritance from parent\n !color && \"text-current\",\n // Custom classes\n className\n );\n\n return (\n <IconComponent\n {...props}\n size={resolvedSize as number}\n color={color}\n weight={weight}\n className={iconClassName}\n aria-label={ariaLabel || `${name} icon`}\n data-testid={`icon-${name}`}\n />\n );\n }\n);\n\nIcon.displayName = \"Icon\";\n\n/**\n * Helper component for icons with containers\n */\ninterface IconWithContainerProps extends IconProps {\n /**\n * Container variant\n */\n variant?: \"subtle\" | \"solid\" | \"outline\";\n\n /**\n * Container shape\n */\n shape?: \"square\" | \"circle\";\n\n /**\n * Container size (adds padding around icon)\n */\n containerSize?: SizePreset | number;\n\n /**\n * Container background color\n */\n containerClassName?: string;\n}\n\nexport const IconWithContainer = memo(\n ({\n variant = \"subtle\",\n shape = \"square\",\n containerSize,\n containerClassName,\n size = \"md\",\n className,\n name,\n color,\n weight,\n ariaLabel,\n ref,\n ...props\n }: IconWithContainerProps & { ref?: React.Ref<HTMLDivElement> }) => {\n // Calculate container size if not specified\n const iconSize = typeof size === \"string\" && size in sizePresets ? sizePresets[size as SizePreset] : size;\n const resolvedContainerSize = containerSize\n ? typeof containerSize === \"string\" && containerSize in sizePresets\n ? sizePresets[containerSize as SizePreset]\n : containerSize\n : (iconSize as number) * 1.75; // Default to 1.75x icon size\n\n const containerClasses = twMerge(\n // Base styles\n \"inline-flex items-center justify-center flex-shrink-0\",\n\n // Shape\n shape === \"circle\" ? \"rounded-full\" : \"rounded-lg\",\n\n // Variant styles using Tailwind 4 CSS variables\n variant === \"subtle\" && \"bg-background-muted\",\n variant === \"solid\" && \"bg-action-brand text-[color:var(--color-action-brand-text)]\",\n variant === \"outline\" && \"border-2 border-current\",\n\n // Container className for overrides\n containerClassName\n );\n\n return (\n <div\n className={containerClasses}\n style={{\n width: resolvedContainerSize,\n height: resolvedContainerSize,\n }}\n >\n <Icon\n {...props}\n name={name}\n size={size}\n color={color}\n weight={weight}\n className={className}\n ariaLabel={ariaLabel}\n />\n </div>\n );\n }\n);\n\nIconWithContainer.displayName = \"IconWithContainer\";\n","import type { ComponentProps, ReactNode } from \"react\";\nimport {\n ButtonRenderProps,\n LinkRenderProps,\n Button as RACButton,\n ButtonProps as RACButtonProps,\n Link as RACLink,\n LinkProps as RACLinkProps,\n} from \"react-aria-components\";\nimport { twMerge } from \"tailwind-merge\";\nimport { focusRing } from \"../../utils\";\nimport type { Size } from \"../../utils/controlStyles\";\nimport { controlStyles } from \"../../utils/controlStyles\";\nimport { Icon } from \"../Icon\";\n\ntype IconName = ComponentProps<typeof Icon>[\"name\"];\n\ntype BaseButtonProps = Omit<RACButtonProps, \"className\">;\n\n/**\n * Button\n *\n * A versatile action component that supports multiple visual variants, sizes,\n * optional icons, a loading state, and badge indicators. Follows the Edges\n * design system tokens and composes `react-aria-components` under the hood.\n *\n * Example usage:\n * ```tsx\n * <Button variant=\"primary\" size=\"md\" icon=\"Check\">Save</Button>\n * ```\n */\ntype ButtonVariant = \"primary\" | \"secondary\" | \"destructive\" | \"icon\" | \"link\" | \"unstyled\" | \"ghost\";\ntype LegacyButtonVariant = \"default\" | \"brand\";\n\nexport interface ButtonProps extends BaseButtonProps {\n /**\n * Visual treatment. Use `primary` for the main action and `secondary` for\n * lower-emphasis actions. `default` and `brand` are deprecated aliases for\n * `primary` during the primary/secondary migration.\n */\n variant?: ButtonVariant | LegacyButtonVariant;\n size?: Size;\n badgeNumber?: number;\n badgeVariant?: \"primary\" | \"destructive\";\n badgePosition?: \"top-right\" | \"top-left\" | \"bottom-right\" | \"bottom-left\";\n fullWidth?: boolean;\n icon?: IconName;\n iconWeight?: \"thin\" | \"light\" | \"regular\" | \"bold\" | \"fill\" | \"duotone\";\n iconPosition?: \"left\" | \"right\";\n isLoading?: boolean;\n loadingText?: string;\n loadingIndicator?: React.ReactNode;\n className?: string;\n href?: string;\n target?: string;\n rel?: string;\n style?: React.CSSProperties;\n}\n\nconst baseStyles =\n \"flex font-medium justify-center items-center gap-2 text-center transition rounded-[var(--control-border-radius)] whitespace-nowrap box-border\";\n\nconst primaryButtonStyles =\n \"bg-action-primary text-[color:var(--color-action-primary-text)] hover:bg-action-primary-hover forced-colors:bg-[ButtonText] forced-colors:text-[ButtonFace] border-2 border-transparent\";\n\nconst variantStyles = {\n primary: primaryButtonStyles,\n secondary:\n \"bg-action-secondary text-[color:var(--color-action-secondary-text)] border-2 border-border-muted hover:bg-action-secondary-hover forced-colors:border-[ButtonBorder] forced-colors:bg-[ButtonFace] forced-colors:text-[ButtonText]\",\n ghost:\n \"border-none text-text-primary hover:bg-text-primary/5 forced-colors:text-[ButtonText] forced-colors:hover:bg-[ButtonFace]\",\n destructive:\n \"bg-transparent text-feedback-error-text border-2 border-border-muted hover:bg-feedback-error-background/50 forced-colors:border-[ButtonBorder] forced-colors:bg-[ButtonFace] forced-colors:text-[Mark]\",\n link: \"!text-action-primary hover:text-action-primary/90 hover:underline hover:decoration-2 hover:underline-offset-4\",\n icon: \"border-none text-text-primary hover:bg-background-hover hover:text-text-primary forced-colors:text-[ButtonText] forced-colors:hover:bg-[ButtonFace] p-1 flex-shrink-0 rounded-[var(--control-border-radius)]\",\n unstyled: \"bg-transparent\",\n} as const;\n\nconst widthStyles = {\n full: \"w-full\",\n default: \"w-fit\",\n};\n\nconst disabledStyles = \"opacity-50 cursor-not-allowed pointer-events-none\";\nconst enabledStyles = \"opacity-100 cursor-pointer\";\n\nconst badgePositionStyles = {\n \"top-right\": \"-right-2 -top-2\",\n \"top-left\": \"-left-2 -top-2\",\n \"bottom-right\": \"-right-2 -bottom-2\",\n \"bottom-left\": \"-left-2 -bottom-2\",\n} as const;\n\nconst badgeVariantStyles = {\n primary: \"bg-action-primary text-[color:var(--color-action-primary-text)]\",\n destructive: \"bg-feedback-error-border text-text-inverse\",\n} as const;\n\nfunction normalizeVariant(variant: ButtonProps[\"variant\"]): ButtonVariant {\n if (!variant || variant === \"default\" || variant === \"brand\") {\n return \"primary\";\n }\n\n return variant;\n}\n\nfunction getButtonStyles(props: ButtonProps) {\n const { variant = \"primary\", size = \"md\", isDisabled, fullWidth = false, isLoading = false } = props;\n\n const normalizedVariant = normalizeVariant(variant);\n\n let styles = normalizedVariant === \"unstyled\" ? \"\" : `${baseStyles} ${variantStyles[normalizedVariant]}`;\n\n // Add size styles using controlStyles\n if (normalizedVariant !== \"unstyled\") {\n styles += ` ${controlStyles[size].text} ${controlStyles[size].height} ${controlStyles[size].padding} ${controlStyles[size].gap}`;\n }\n\n if (isDisabled || isLoading) {\n styles += ` ${disabledStyles}`;\n } else {\n styles += ` ${enabledStyles}`;\n }\n\n if (fullWidth) {\n styles += ` ${widthStyles.full}`;\n } else {\n styles += ` ${widthStyles.default}`;\n }\n\n const focusRingColor = normalizedVariant === \"primary\" ? \"focus-visible:outline-action-primary\" : undefined;\n\n return [styles, focusRing(), focusRingColor].filter(Boolean).join(\" \");\n}\n\n/**\n * Renders an Edges Button. When `href` is provided, renders a link-styled\n * button using the same visual system.\n */\nexport function Button(props: ButtonProps) {\n const {\n icon,\n children,\n isLoading = false,\n loadingText,\n loadingIndicator,\n size = \"md\",\n iconPosition = \"left\",\n iconWeight,\n href,\n className,\n badgeNumber,\n badgeVariant = \"primary\",\n badgePosition = \"top-right\",\n style,\n target,\n rel,\n ...restProps\n } = props;\n\n // Shared icon logic\n const iconElement = icon ? <Icon name={icon} size={size} weight={iconWeight} /> : null;\n\n // Shared content logic\n const content = (\n <>\n {iconPosition === \"left\" && iconElement}\n {typeof children === \"function\" ? null : children}\n {iconPosition === \"right\" && iconElement}\n </>\n );\n\n // Loading state\n const loadingNode = (\n <div className=\"relative inline-flex items-center justify-center\">\n <div className=\"absolute inset-0 flex items-center justify-center\">\n {loadingIndicator || <Icon name=\"CircleNotch\" size={size} className=\"animate-spin\" aria-hidden=\"true\" />}\n </div>\n <div className=\"invisible\" aria-hidden=\"true\">\n {content}\n </div>\n {loadingText && (\n <span className=\"sr-only\" role=\"status\" aria-live=\"polite\">\n {loadingText}\n </span>\n )}\n </div>\n );\n\n // Compose className using twMerge to properly handle Tailwind class conflicts\n const hasBadge = (badgeNumber ?? 0) > 0;\n const composedClassName = twMerge(getButtonStyles(props), className);\n\n // Create link-specific props by filtering out button-specific props\n const linkProps: Partial<RACLinkProps> = href\n ? {\n href,\n target,\n rel,\n // Only include props that are valid for both Button and Link\n ...(restProps as Record<string, unknown>),\n }\n : {};\n\n // Remove button-specific event handlers that don't apply to links\n if (href) {\n const {\n onPress: _onPress,\n onPressStart: _onPressStart,\n onPressEnd: _onPressEnd,\n onPressChange: _onPressChange,\n onPressUp: _onPressUp,\n onAuxClick: _onAuxClick,\n onContextMenu: _onContextMenu,\n onDoubleClick: _onDoubleClick,\n ...safeRestProps\n } = restProps as Record<string, unknown>;\n Object.assign(linkProps, safeRestProps);\n }\n\n // Compose the button or link element\n const buttonOrLink = href ? (\n <RACLink\n {...linkProps}\n {...(isLoading && { \"aria-busy\": true })}\n style={hasBadge ? undefined : style}\n className={composedClassName}\n >\n {isLoading\n ? loadingNode\n : typeof children === \"function\"\n ? (function (renderProps: LinkRenderProps & { defaultChildren: ReactNode }) {\n return (\n <>\n {iconPosition === \"left\" && iconElement}\n {children(\n renderProps as unknown as ButtonRenderProps & {\n defaultChildren: ReactNode;\n }\n )}\n {iconPosition === \"right\" && iconElement}\n </>\n );\n } as (props: LinkRenderProps & { defaultChildren: ReactNode }) => ReactNode)\n : content}\n </RACLink>\n ) : (\n <RACButton\n {...restProps}\n {...(isLoading && { \"aria-busy\": true })}\n style={hasBadge ? undefined : style}\n className={composedClassName}\n >\n {isLoading\n ? loadingNode\n : typeof children === \"function\"\n ? (function (renderProps: ButtonRenderProps & { defaultChildren: ReactNode }) {\n return (\n <>\n {iconPosition === \"left\" && iconElement}\n {children(renderProps)}\n {iconPosition === \"right\" && iconElement}\n </>\n );\n } as (props: ButtonRenderProps & { defaultChildren: ReactNode }) => ReactNode)\n : content}\n </RACButton>\n );\n\n // Render badge if badgeNumber is provided and > 0\n if (hasBadge) {\n return (\n <div className={twMerge(\"relative flex\", className)} style={style}>\n {buttonOrLink}\n <span\n className={`absolute ${badgePositionStyles[badgePosition]} flex h-5 w-5 items-center justify-center rounded-full ${badgeVariantStyles[badgeVariant]} text-xs font-medium`}\n aria-label={`${badgeNumber} items`}\n >\n {badgeNumber}\n </span>\n </div>\n );\n }\n\n return buttonOrLink;\n}\n","import React from \"react\";\nimport { Button } from \"../Button\";\nimport type { DialogAction } from \"../Dialog/types\";\n\nexport interface DialogFooterProps {\n /**\n * Primary action button configuration\n */\n primaryAction?: DialogAction;\n /**\n * Secondary action button configuration\n */\n secondaryAction?: DialogAction;\n /**\n * Tertiary action button configuration (typically left-aligned destructive action)\n */\n tertiaryAction?: DialogAction;\n /**\n * Custom footer content above the action buttons\n */\n footerContent?: React.ReactNode;\n}\n\n/**\n * Renders an action button, optionally as a form submit button\n */\nfunction ActionButton({\n action,\n defaultVariant,\n defaultSize = \"lg\",\n}: {\n action: DialogAction;\n defaultVariant: DialogAction[\"variant\"];\n defaultSize?: DialogAction[\"size\"];\n}) {\n const hasFormId = !!action.formId;\n\n return (\n <Button\n type={hasFormId ? \"submit\" : \"button\"}\n form={hasFormId ? action.formId : undefined}\n size={action.size || defaultSize}\n variant={action.variant || defaultVariant}\n onPress={hasFormId ? undefined : action.onPress}\n isLoading={action.isLoading}\n isDisabled={action.isDisabled}\n >\n {action.label}\n </Button>\n );\n}\n\n/**\n * DialogFooter\n *\n * Shared footer component for Dialog and Drawer.\n * Renders action buttons with consistent styling.\n *\n * Supports form integration via the `formId` prop on actions:\n * - When `formId` is set, the button becomes a submit button for that form\n * - Use `isDisabled` to control button state based on form validation\n */\nexport function DialogFooter({ primaryAction, secondaryAction, tertiaryAction, footerContent }: DialogFooterProps) {\n const hasActions = primaryAction || secondaryAction || tertiaryAction;\n\n if (!hasActions && !footerContent) {\n return null;\n }\n\n return (\n <div className={`flex w-full flex-col items-center justify-center border-t p-4 ${footerContent ? \"h-28\" : \"\"}`}>\n {footerContent && <div className=\"flex h-10 justify-center\">{footerContent}</div>}\n {hasActions && (\n <div className=\"flex w-full items-center justify-between gap-3\">\n {/* Left-aligned tertiary action (typically destructive) */}\n <div>{tertiaryAction && <ActionButton action={tertiaryAction} defaultVariant=\"destructive\" />}</div>\n\n {/* Right-aligned primary and secondary actions */}\n <div className=\"flex items-center gap-3\">\n {secondaryAction && <ActionButton action={secondaryAction} defaultVariant=\"secondary\" />}\n {primaryAction && <ActionButton action={primaryAction} defaultVariant=\"primary\" />}\n </div>\n </div>\n )}\n </div>\n );\n}\n","import React from \"react\";\nimport { cx } from \"../../utils/classNames\";\nimport { typographyRole } from \"../../utils/typography\";\n\nconst variantSizeMap = {\n heading: {\n sm: typographyRole.headingSm,\n md: typographyRole.headingMd,\n lg: typographyRole.headingLg,\n xl: typographyRole.headingXl,\n },\n display: {\n sm: typographyRole.displaySm,\n md: typographyRole.displayMd,\n lg: typographyRole.displayLg,\n xl: typographyRole.displayXl,\n },\n} as const;\n\nconst heightVariants = {\n page: \"h-16 leading-[62px]\",\n} as const;\n\nexport type HeadingVariant = keyof typeof variantSizeMap;\nexport type HeadingSize = keyof (typeof variantSizeMap)[\"heading\"] | \"xs\";\nexport type HeadingHeight = keyof typeof heightVariants;\n\n/**\n * Heading\n *\n * Typography component for page/section headings.\n *\n * - `variant=\"heading\"` (default) uses the Inter heading scale — for page titles,\n * section titles, card titles, and other product chrome.\n * - `variant=\"display\"` uses the display scale — reserved for brand moments\n * (signup, marketing surfaces) and big-number KPIs.\n *\n * Both variants share the same `sm` / `md` / `lg` / `xl` size scale.\n */\nexport interface HeadingProps {\n tag?: React.ElementType;\n /** Type scale to render in. Defaults to \"heading\". */\n variant?: HeadingVariant;\n /** Size within the chosen variant's scale. */\n size?: HeadingSize;\n height?: HeadingHeight;\n className?: string;\n children?: React.ReactNode;\n}\n\nexport function Heading({\n tag: Tag = \"h1\",\n variant = \"heading\",\n size = \"lg\",\n height,\n className = \"\",\n children,\n}: HeadingProps) {\n const resolvedSize = size === \"xs\" ? \"sm\" : size;\n const sizeClasses = variantSizeMap[variant][resolvedSize];\n const heightClasses = height ? heightVariants[height] : \"\";\n\n return <Tag className={cx(sizeClasses, \"text-text-primary\", heightClasses, className)}>{children}</Tag>;\n}\n","import React from \"react\";\nimport { twMerge } from \"tailwind-merge\";\nimport { Button } from \"../Button\";\nimport { Heading } from \"../Heading\";\nimport { Icon } from \"../Icon\";\n\ntype BaseDialogHeaderProps = {\n title?: string;\n onClose?: () => void;\n hideCloseIcon?: boolean;\n titleAlign?: \"left\" | \"center\";\n headerContent?: React.ReactNode;\n};\n\ntype WithBackArrow = BaseDialogHeaderProps & {\n hasBackArrow: true;\n onBack: () => void;\n};\n\ntype WithoutBackArrow = BaseDialogHeaderProps & {\n hasBackArrow?: false;\n onBack?: never;\n};\n\n/**\n * DialogHeader\n *\n * Header area for dialogs with optional back arrow.\n */\nexport type DialogHeaderProps = WithBackArrow | WithoutBackArrow;\n\nexport const DialogHeader: React.FC<DialogHeaderProps> = ({\n title,\n onClose,\n hideCloseIcon = false,\n titleAlign = \"left\",\n hasBackArrow = false,\n onBack,\n headerContent,\n}) => {\n return (\n <div\n className={twMerge(\n \"relative flex h-16 w-full flex-shrink-0 items-center justify-between border-b px-6\",\n title && \"border-b\",\n titleAlign === \"center\" ? \"justify-center\" : \"\"\n )}\n >\n {hasBackArrow && (\n <Button variant=\"icon\" onPress={onBack} className=\"absolute left-6\" aria-label=\"Go back\">\n <Icon name=\"CaretLeft\" data-testid=\"back-arrow\" />\n </Button>\n )}\n {headerContent || (\n <>\n {title && <Heading size=\"xs\">{title}</Heading>}\n {onClose && !hideCloseIcon && (\n <Button variant=\"icon\" onPress={onClose} aria-label=\"Close dialog\">\n <Icon name=\"X\" data-testid=\"close-button\" />\n </Button>\n )}\n </>\n )}\n </div>\n );\n};\n","\"use client\";\n\nimport React, { useEffect, useState } from \"react\";\nimport { twMerge } from \"tailwind-merge\";\n\ninterface SkeletonProps {\n width?: number | string;\n height?: number | string;\n variant?: \"text\" | \"rect\" | \"circle\";\n animation?: \"pulse\" | \"wave\" | \"none\";\n gradient?: boolean;\n flex?: boolean;\n stack?: (number | string)[]; // Array of widths for stacked skeletons\n responsive?: Record<string, string | number>;\n delay?: number;\n adjustAnimationSpeedBasedOnWidth?: boolean;\n ariaLabel?: string;\n className?: string;\n \"data-testid\"?: string;\n}\n\n/**\n * Skeleton\n *\n * Loading placeholder component that mimics content structure.\n * Supports various shapes, animations, and responsive configurations for skeleton screens.\n */\nexport const Skeleton: React.FC<SkeletonProps> = ({\n width,\n height,\n variant = \"rect\",\n animation = \"pulse\",\n gradient = false,\n flex = false,\n stack,\n responsive,\n delay = 0,\n adjustAnimationSpeedBasedOnWidth = false,\n ariaLabel,\n className,\n \"data-testid\": dataTestId,\n}) => {\n const [visible, setVisible] = useState(delay === 0);\n\n useEffect(() => {\n if (delay > 0) {\n const timer = setTimeout(() => setVisible(true), delay);\n return () => clearTimeout(timer);\n }\n }, [delay]);\n\n if (!visible) return null;\n\n // Base styles\n const baseClasses = gradient\n ? \"bg-gradient-to-r from-[var(--color-skeleton-base)] via-[var(--color-skeleton-highlight)] to-[var(--color-skeleton-base)]\"\n : \"bg-[var(--color-skeleton-base)]\";\n\n // Adjust animation speed dynamically based on width\n const animationSpeed =\n adjustAnimationSpeedBasedOnWidth && width\n ? (() => {\n const numWidth = typeof width === \"number\" ? width : parseFloat(String(width));\n return !isNaN(numWidth) ? `animation-duration-[${Math.max(0.8, numWidth / 100)}s]` : \"\";\n })()\n : \"\";\n\n // Animation styles\n const animationClasses =\n animation === \"pulse\"\n ? `animate-pulse ${animationSpeed}`\n : animation === \"wave\"\n ? `relative overflow-hidden before:absolute before:inset-0 before:bg-gradient-to-r before:from-transparent before:via-[var(--color-skeleton-wave)] before:to-transparent before:animate-wave ${animationSpeed}`\n : \"\";\n\n // Shape-specific styles\n let shapeClasses = \"rounded-sm\";\n if (variant === \"circle\") shapeClasses = \"rounded-full\";\n if (variant === \"text\") shapeClasses = \"h-4 w-full rounded-sm\";\n\n // Dynamic layout handling\n const layoutClasses = flex ? \"flex-1 min-w-0\" : \"\";\n\n // Responsive styles\n const responsiveStyles = responsive\n ? Object.entries(responsive)\n .map(([breakpoint, value]) => `${breakpoint}:w-[${value}]`)\n .join(\" \")\n : \"\";\n\n // Stacking Multiple Skeletons\n if (stack) {\n return (\n <div className=\"space-y-2\" data-testid={dataTestId}>\n {stack.map((lineWidth, index) => (\n <div\n key={index}\n className={twMerge(baseClasses, animationClasses, shapeClasses, layoutClasses, responsiveStyles, className)}\n style={{\n width: lineWidth,\n height,\n }}\n />\n ))}\n </div>\n );\n }\n\n return (\n <div\n className={twMerge(baseClasses, animationClasses, shapeClasses, layoutClasses, responsiveStyles, className)}\n style={{\n width,\n height,\n }}\n role=\"presentation\"\n aria-hidden={!ariaLabel}\n aria-label={ariaLabel ?? undefined}\n data-testid={dataTestId}\n />\n );\n};\n\ninterface SkeletonGroupProps {\n count?: number;\n children: React.ReactNode;\n className?: string;\n \"data-testid\"?: string;\n}\n\nexport const SkeletonGroup: React.FC<SkeletonGroupProps> = ({\n count = 1,\n children,\n className,\n \"data-testid\": dataTestId,\n}) => {\n return (\n <div className={className} data-testid={dataTestId}>\n {Array.from({ length: count }).map((_, index) => (\n <div key={index}>{children}</div>\n ))}\n </div>\n );\n};\n","import React from \"react\";\nimport { twMerge } from \"tailwind-merge\";\nimport { typeRole } from \"../../utils/typography\";\nimport { Heading } from \"../Heading\";\nimport { Skeleton } from \"../Skeleton\";\n\n/**\n * Card - Enterprise surface container component\n *\n * A flexible, composable card component following enterprise design system best practices.\n * Supports modular content sections with consistent styling and accessibility.\n *\n * Usage:\n * ```tsx\n * <Card variant=\"outlined\" size=\"md\">\n * <Card.Header\n * title=\"Card Title\"\n * subtitle=\"Optional subtitle\"\n * actions={<Button variant=\"ghost\" icon=\"MoreHorizontal\" />}\n * />\n * <Card.Media src=\"image.jpg\" alt=\"Description\" />\n * <Card.Content>\n * <p>Main content goes here</p>\n * </Card.Content>\n * <Card.Footer>\n * <Button variant=\"primary\">Action</Button>\n * </Card.Footer>\n * </Card>\n * ```\n */\n\n// ——————————————————————————————————————————\n// Types\n// ——————————————————————————————————————————\n\nexport type CardVariant = \"outlined\" | \"elevated\" | \"filled\" | \"ghost\";\nexport interface CardProps {\n variant?: CardVariant;\n className?: string;\n children?: React.ReactNode;\n isLoading?: boolean;\n /** Enable flex column layout so children can expand to fill space */\n layout?: \"default\" | \"flex\";\n}\n\nexport interface CardHeaderProps {\n title?: React.ReactNode;\n subtitle?: React.ReactNode;\n actions?: React.ReactNode;\n className?: string;\n isLoading?: boolean;\n}\n\nexport interface CardMediaProps {\n src?: string;\n alt?: string;\n aspectRatio?: \"square\" | \"video\" | \"wide\" | \"auto\";\n className?: string;\n children?: React.ReactNode;\n isLoading?: boolean;\n}\n\nexport interface CardContentProps {\n className?: string;\n children?: React.ReactNode;\n isLoading?: boolean;\n /** When true and parent Card has layout=\"flex\", content expands to fill available space */\n fill?: boolean;\n}\n\nexport interface CardFooterProps {\n className?: string;\n children?: React.ReactNode;\n align?: \"start\" | \"end\" | \"center\" | \"between\";\n isLoading?: boolean;\n}\n\n// ——————————————————————————————————————————\n// Styles\n// ——————————————————————————————————————————\n\nconst cardVariantStyles: Record<CardVariant, string> = {\n outlined: \"bg-background-surface border border-border-default\",\n elevated: \"bg-background-surface border-0 shadow-md\",\n filled: \"bg-background-muted border-0\",\n ghost: \"bg-transparent border-0 shadow-none\",\n};\n\nconst cardBaseStyles = \"rounded-lg\";\n\nconst aspectRatioStyles = {\n square: \"aspect-square\",\n video: \"aspect-video\",\n wide: \"aspect-[2/1]\",\n auto: \"\",\n};\n\nconst footerAlignStyles = {\n start: \"justify-start\",\n end: \"justify-end\",\n center: \"justify-center\",\n between: \"justify-between\",\n};\n\n// ——————————————————————————————————————————\n// Main Card Component\n// ——————————————————————————————————————————\n\nexport function Card({ variant = \"outlined\", className, children, isLoading = false, layout = \"default\" }: CardProps) {\n return (\n <div\n className={twMerge(\n \"w-full overflow-hidden\",\n cardVariantStyles[variant],\n cardBaseStyles,\n layout === \"flex\" && \"flex flex-col\",\n className\n )}\n data-testid=\"card\"\n >\n {isLoading ? (\n // Skeleton fills the card completely - respects height set on card\n <Skeleton width=\"100%\" height=\"100%\" className=\"rounded-none\" />\n ) : (\n children\n )}\n </div>\n );\n}\n\n// ——————————————————————————————————————————\n// Card Header\n// ——————————————————————————————————————————\n\nexport function CardHeader({ title, subtitle, actions, className, isLoading = false }: CardHeaderProps) {\n if (isLoading) {\n return (\n <div className={twMerge(\"p-6 pb-4\", className)}>\n <div className=\"flex justify-between items-start mb-1\">\n <Skeleton width={120} height={20} />\n <Skeleton width={24} height={24} />\n </div>\n {subtitle && <Skeleton width={200} height={16} />}\n </div>\n );\n }\n\n if (!title && !subtitle && !actions) {\n return null;\n }\n\n return (\n <div className={twMerge(\"p-6 pb-4\", className)}>\n <div className=\"flex justify-between items-start gap-4\">\n <div className=\"min-w-0 flex-1\">\n {title && (\n <div className=\"mb-1\">\n {typeof title === \"string\" ? (\n <Heading tag=\"h3\" size=\"sm\" className=\"text-text-primary\">\n {title}\n </Heading>\n ) : (\n title\n )}\n </div>\n )}\n {subtitle && <div className={typeRole(\"bodySm\", \"text-text-secondary\")}>{subtitle}</div>}\n </div>\n {actions && <div className=\"flex-shrink-0\">{actions}</div>}\n </div>\n </div>\n );\n}\n\n// ——————————————————————————————————————————\n// Card Media\n// ——————————————————————————————————————————\n\nexport function CardMedia({ src, alt, aspectRatio = \"auto\", className, children, isLoading = false }: CardMediaProps) {\n if (isLoading) {\n return (\n <div className={twMerge(\"bg-background-muted\", aspectRatioStyles[aspectRatio], className)}>\n <Skeleton width=\"100%\" height=\"100%\" />\n </div>\n );\n }\n\n if (children) {\n return <div className={twMerge(\"overflow-hidden\", aspectRatioStyles[aspectRatio], className)}>{children}</div>;\n }\n\n if (!src) {\n return null;\n }\n\n return (\n <div className={twMerge(\"overflow-hidden\", aspectRatioStyles[aspectRatio], className)}>\n <img src={src} alt={alt || \"\"} className=\"w-full h-full object-cover\" loading=\"lazy\" />\n </div>\n );\n}\n\n// ——————————————————————————————————————————\n// Card Content\n// ——————————————————————————————————————————\n\nexport function CardContent({ className, children, isLoading = false, fill = false }: CardContentProps) {\n // Extract padding classes from className - if any padding class is set, respect it\n const hasPadding = className?.match(/p(?:t|b|l|r|x|y)?-(?:\\d+(?:\\.\\d+)?|px|\\[.+?\\])/);\n const defaultPadding = hasPadding ? \"\" : \"px-6 py-4\";\n\n if (isLoading) {\n return (\n <div className={twMerge(defaultPadding, fill && \"flex-1 flex flex-col min-h-0\", className)}>\n <div className=\"space-y-2\">\n <Skeleton width=\"100%\" height={16} />\n <Skeleton width=\"80%\" height={16} />\n <Skeleton width=\"60%\" height={16} />\n </div>\n </div>\n );\n }\n\n if (!children) {\n return null;\n }\n\n return (\n <div className={twMerge(\"px-6 py-4 text-text-primary\", fill && \"flex-1 flex flex-col min-h-0\", className)}>\n {children}\n </div>\n );\n}\n\n// ——————————————————————————————————————————\n// Card Footer\n// ——————————————————————————————————————————\n\nexport function CardFooter({ className, children, align = \"end\", isLoading = false }: CardFooterProps) {\n if (isLoading) {\n return (\n <div className={twMerge(\"px-6 py-4 flex gap-2 justify-end\", className)}>\n <Skeleton width={80} height={32} />\n <Skeleton width={60} height={32} />\n </div>\n );\n }\n\n if (!children) {\n return null;\n }\n\n return (\n <div className={twMerge(\"px-6 py-4 flex items-center gap-2\", footerAlignStyles[align], className)}>{children}</div>\n );\n}\n\n// ——————————————————————————————————————————\n// Compound Component API\n// ——————————————————————————————————————————\n\nCard.Header = CardHeader;\nCard.Media = CardMedia;\nCard.Content = CardContent;\nCard.Footer = CardFooter;\n","import { Component, ErrorInfo, ReactNode } from \"react\";\nimport { Card } from \"../Card\";\n\ninterface Props {\n children: ReactNode;\n fallback?: ReactNode;\n title?: string;\n}\n\ninterface State {\n hasError: boolean;\n error?: Error;\n}\n\n/**\n * ErrorBoundary\n *\n * React error boundary component for graceful error handling.\n * Catches JavaScript errors in child components and displays a fallback UI with retry option.\n */\nexport class ErrorBoundary extends Component<Props, State> {\n public state: State = {\n hasError: false,\n };\n\n public static getDerivedStateFromError(error: Error): State {\n return { hasError: true, error };\n }\n\n public componentDidCatch(error: Error, errorInfo: ErrorInfo) {\n console.error(\"Error Boundary caught an error:\", error, errorInfo);\n }\n\n private handleRetry = () => {\n this.setState({ hasError: false, error: undefined });\n if (typeof window !== \"undefined\") {\n window.location.reload();\n }\n };\n\n public render() {\n if (this.state.hasError) {\n if (this.props.fallback) {\n return this.props.fallback;\n }\n\n return (\n <Card>\n {this.props.title && <Card.Header title={this.props.title} />}\n <Card.Content>\n <div className=\"flex flex-col items-center justify-center gap-4\" data-testid=\"error-boundary\">\n <p className=\"text-feedback-error-text\">{this.state.error?.message || \"Something went wrong\"}</p>\n <button\n className=\"rounded bg-action-default px-4 py-2 text-[color:var(--color-action-default-text)] hover:bg-action-default-hover\"\n onClick={this.handleRetry}\n >\n Retry\n </button>\n </div>\n </Card.Content>\n </Card>\n );\n }\n\n return this.props.children;\n }\n}\n","import { composeRenderProps, ModalOverlay, ModalOverlayProps } from \"react-aria-components\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport interface ModalBackdropProps extends ModalOverlayProps {\n /**\n * Whether to use a transparent backdrop instead of dark overlay\n * @default false\n */\n transparent?: boolean;\n /**\n * Additional CSS classes for the backdrop\n */\n className?: string;\n}\n\n/**\n * ModalBackdrop\n *\n * Shared backdrop/overlay component used by Dialog and Drawer.\n * Wraps React Aria's ModalOverlay with consistent styling and smooth animations.\n */\nexport function ModalBackdrop({ transparent = false, className, children, ...props }: ModalBackdropProps) {\n return (\n <ModalOverlay\n {...props}\n className={composeRenderProps(className, (className, renderProps) => {\n return twMerge(\n // Base positioning and layering\n \"fixed inset-0 z-50\",\n // Remove focus outlines from modal overlay\n \"outline-none focus:outline-none focus-visible:outline-none ring-0 focus:ring-0 focus-visible:ring-0\",\n // Backdrop styling - subtle gradient for depth\n transparent\n ? \"bg-transparent\"\n : [\n \"bg-gradient-to-br from-background-modal/20 via-background-modal/15 to-background-modal/20\",\n \"backdrop-blur-[2px]\",\n \"supports-[backdrop-filter]:bg-background-modal/15\",\n ].join(\" \"),\n // Smooth animations\n renderProps.isEntering && [\"animate-in fade-in\", \"duration-300 ease-out\"].join(\" \"),\n renderProps.isExiting && [\"animate-out fade-out\", \"duration-200 ease-in\"].join(\" \"),\n className\n );\n })}\n >\n {children}\n </ModalOverlay>\n );\n}\n","import React, { useCallback, useEffect, useRef, useState } from \"react\";\nimport { Modal, Dialog as RACDialog } from \"react-aria-components\";\nimport { twMerge } from \"tailwind-merge\";\nimport { useVisualViewportHeight } from \"../../hooks/useVisualViewportHeight\";\nimport type { DialogFooterConfig, DialogHeaderConfig } from \"../Dialog/types\";\nimport { DialogFooter } from \"../DialogFooter\";\nimport { DialogHeader } from \"../DialogHeader\";\nimport { ErrorBoundary } from \"../ErrorBoundary\";\nimport { ModalBackdrop } from \"../ModalBackdrop\";\n\nconst SWIPE_DISMISS_THRESHOLD = 0.3;\nconst SWIPE_VELOCITY_THRESHOLD = 0.5;\n\nexport interface TrayProps extends DialogHeaderConfig, DialogFooterConfig {\n /**\n * Tray content\n */\n children?: React.ReactNode;\n /**\n * Controls whether the tray is visible\n */\n isOpen: boolean;\n /**\n * Called when the tray should close\n */\n onClose?: () => void;\n /**\n * Whether clicking the backdrop should dismiss the tray\n * @default true\n */\n isDismissable?: boolean;\n /**\n * Whether to use a transparent overlay behind the tray\n * @default false\n */\n transparentOverlay?: boolean;\n /**\n * Maximum height for the tray content area\n * @default \"80vh\"\n */\n maxHeight?: string;\n /**\n * Explicit height for the tray (overrides maxHeight if set)\n * Content will scroll within this fixed height\n * @default undefined\n */\n height?: string;\n /**\n * Maximum width of the tray\n * @default \"640px\"\n */\n maxWidth?: string;\n /**\n * Whether to include padding around tray content\n * @default true\n */\n contentPadding?: boolean;\n /**\n * Whether to show the drag handle indicator on mobile\n * @default true\n */\n showHandle?: boolean;\n /**\n * Animation variant for the tray entrance/exit\n * @default \"scale\" - Slide with subtle scale effect for depth\n * \"slide\" - Simple slide up/down\n */\n animationVariant?: \"slide\" | \"scale\";\n /**\n * Additional CSS classes for the tray container\n */\n className?: string;\n}\n\n/**\n * Tray\n *\n * Bottom anchored overlay optimized for mobile experiences.\n * Provides optional header/footer slots that align with Dialog & Drawer APIs.\n */\nexport function Tray({\n children,\n title,\n headerContent,\n titleAlign = \"left\",\n hideCloseIcon = false,\n hasBackArrow = false,\n onBack,\n isOpen,\n onClose,\n isDismissable = true,\n transparentOverlay = false,\n primaryAction,\n secondaryAction,\n footerContent,\n maxHeight = \"80vh\",\n height,\n maxWidth = \"640px\",\n contentPadding = true,\n showHandle = true,\n animationVariant = \"scale\",\n className,\n}: TrayProps) {\n const [isHandleAnimating, setIsHandleAnimating] = useState(false);\n const [dragOffset, setDragOffset] = useState(0);\n const [isTransitioning, setIsTransitioning] = useState(false);\n // Track the available visual viewport height so the tray resizes and repositions\n // when the iOS soft keyboard pushes up the viewport.\n const viewport = useVisualViewportHeight(isOpen);\n const viewportHeight = viewport?.height ?? null;\n const keyboardOffset = viewport?.keyboardOffset ?? 0;\n const containerRef = useRef<HTMLDivElement>(null);\n // Ref for the scrollable content area — used to scroll focused inputs into view on iOS.\n const scrollContentRef = useRef<HTMLDivElement>(null);\n const transitionTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const dragStateRef = useRef<{\n isDragging: boolean;\n startY: number;\n startTime: number;\n pointerId: number | null;\n }>({\n isDragging: false,\n startY: 0,\n startTime: 0,\n pointerId: null,\n });\n\n // Trigger a subtle handle animation when tray opens\n useEffect(() => {\n if (isOpen) {\n const timer = setTimeout(() => {\n setIsHandleAnimating(true);\n setTimeout(() => setIsHandleAnimating(false), 600);\n }, 400);\n return () => clearTimeout(timer);\n }\n }, [isOpen]);\n\n // Reset drag state when tray closes\n useEffect(() => {\n if (!isOpen) {\n setDragOffset(0);\n setIsTransitioning(false);\n dragStateRef.current = {\n isDragging: false,\n startY: 0,\n startTime: 0,\n pointerId: null,\n };\n }\n }, [isOpen]);\n\n // On iOS, focusing an input inside a non-body scroll container won't automatically\n // scroll that container to bring the input into view — the browser scrolls the page\n // body instead (which is locked by the modal). We listen for focusin on the scroll\n // container and manually scroll the focused element into view after the keyboard has\n // had a chance to open (small timeout lets visualViewport settle first).\n useEffect(() => {\n const scrollEl = scrollContentRef.current;\n if (!scrollEl || !isOpen) return;\n\n let focusScrollTimeout: ReturnType<typeof setTimeout> | null = null;\n\n const handleFocusIn = (e: FocusEvent) => {\n const target = e.target as HTMLElement | null;\n if (!target) return;\n\n // Only act on actual form inputs\n if (![\"INPUT\", \"TEXTAREA\", \"SELECT\"].includes(target.tagName)) return;\n\n // Delay so the keyboard has time to open and visualViewport to update\n if (focusScrollTimeout) clearTimeout(focusScrollTimeout);\n focusScrollTimeout = setTimeout(() => {\n target.scrollIntoView({ block: \"nearest\", behavior: \"smooth\" });\n }, 320);\n };\n\n scrollEl.addEventListener(\"focusin\", handleFocusIn);\n return () => {\n scrollEl.removeEventListener(\"focusin\", handleFocusIn);\n if (focusScrollTimeout) clearTimeout(focusScrollTimeout);\n };\n }, [isOpen]);\n\n const handlePointerDown = useCallback(\n (e: React.PointerEvent) => {\n if (!isDismissable) return;\n if (e.pointerType !== \"touch\" && e.pointerType !== \"pen\") return;\n\n // Clear any pending transition timeout from previous gesture\n if (transitionTimeoutRef.current) {\n clearTimeout(transitionTimeoutRef.current);\n transitionTimeoutRef.current = null;\n }\n\n dragStateRef.current = {\n isDragging: true,\n startY: e.clientY,\n startTime: Date.now(),\n pointerId: e.pointerId,\n };\n setIsTransitioning(false);\n e.currentTarget.setPointerCapture(e.pointerId);\n },\n [isDismissable]\n );\n\n const handlePointerMove = useCallback((e: React.PointerEvent) => {\n const { isDragging, startY, pointerId } = dragStateRef.current;\n if (!isDragging || e.pointerId !== pointerId) return;\n\n const deltaY = e.clientY - startY;\n setDragOffset(Math.max(0, deltaY));\n }, []);\n\n const handlePointerEnd = useCallback(\n (e: React.PointerEvent) => {\n const { isDragging, startY, startTime, pointerId } = dragStateRef.current;\n if (!isDragging || e.pointerId !== pointerId) return;\n\n const deltaY = e.clientY - startY;\n const elapsed = Date.now() - startTime;\n const velocity = deltaY / elapsed;\n\n dragStateRef.current = {\n isDragging: false,\n startY: 0,\n startTime: 0,\n pointerId: null,\n };\n\n const containerHeight = containerRef.current?.getBoundingClientRect().height ?? 0;\n const threshold = containerHeight * SWIPE_DISMISS_THRESHOLD;\n const shouldDismiss = deltaY > threshold || (velocity > SWIPE_VELOCITY_THRESHOLD && deltaY > 50);\n\n if (shouldDismiss && isDismissable) {\n onClose?.();\n setDragOffset(0);\n } else {\n setIsTransitioning(true);\n setDragOffset(0);\n transitionTimeoutRef.current = setTimeout(() => {\n setIsTransitioning(false);\n transitionTimeoutRef.current = null;\n }, 200);\n }\n },\n [isDismissable, onClose]\n );\n\n if (!isOpen) return null;\n\n const hasHeader = title || headerContent;\n const hasFooter = primaryAction || secondaryAction || footerContent;\n\n return (\n <ErrorBoundary>\n <ModalBackdrop\n isOpen={isOpen}\n onOpenChange={(open) => {\n if (!open) onClose?.();\n }}\n isDismissable={isDismissable}\n transparent={transparentOverlay}\n // On iOS Safari, position:fixed overlays are anchored to the layout viewport\n // and don't shift when the soft keyboard opens. We apply bottom padding equal\n // to the keyboard height so the tray — which is flex-end aligned — gets pushed\n // up above the keyboard. Transition matches the iOS keyboard animation curve.\n style={{\n paddingBottom: keyboardOffset > 0 ? `${keyboardOffset}px` : undefined,\n transition: \"padding-bottom 0.25s ease-out\",\n }}\n className=\"flex items-end justify-center p-0 sm:p-4\"\n >\n <Modal\n className=\"w-full max-w-full p-0 sm:p-2 outline-none focus:outline-none focus-visible:outline-none ring-0 focus:ring-0 focus-visible:ring-0\"\n isDismissable={isDismissable}\n >\n <div\n ref={containerRef}\n className={twMerge(\"w-full\", isTransitioning && \"transition-transform duration-200\")}\n style={{\n transform: dragOffset > 0 ? `translateY(${dragOffset}px)` : undefined,\n }}\n >\n <RACDialog\n className={twMerge(\n // Base structure\n \"relative flex w-full flex-col overflow-hidden\",\n // Background and borders with elevation\n \"bg-background-surface\",\n \"shadow-2xl shadow-black/30 dark:shadow-black/60\",\n \"border-t border-x border-border-default/40\",\n // Suppress browser focus outline/rings on the dialog container itself\n // This is safe: React Aria manages focus on interactive elements inside the dialog.\n // The container doesn't need a focus indicator as it's not directly interactive.\n \"outline-none focus:outline-none focus-visible:outline-none ring-0 focus:ring-0 focus-visible:ring-0 focus:shadow-none\",\n // Transform origin for scale animation\n \"origin-bottom\",\n // Entrance animations using combined keyframes with enterprise-grade timing\n animationVariant === \"scale\"\n ? \"animate-[tray-enter-scale_400ms_cubic-bezier(0.32,0.72,0,1)]\"\n : \"animate-[tray-enter_400ms_cubic-bezier(0.32,0.72,0,1)]\",\n // Exit animations using data-[exiting] state - snappier for responsiveness\n animationVariant === \"scale\"\n ? \"data-[exiting]:animate-[tray-exit-scale_250ms_cubic-bezier(0.32,0,0.67,0)]\"\n : \"data-[exiting]:animate-[tray-exit_250ms_cubic-bezier(0.32,0,0.67,0)]\",\n className\n )}\n style={{\n maxWidth,\n // When the iOS soft keyboard is open, window.visualViewport.height\n // is smaller than the full window height. We use that value (minus a\n // small top offset so the tray doesn't touch the status bar) as the\n // ceiling, which keeps the tray — including its footer — fully visible\n // above the keyboard. Falls back to the prop value when visualViewport\n // is unavailable or hasn't been measured yet.\n ...(height\n ? { height }\n : {\n // Use the smaller of:\n // 1. The prop maxHeight (e.g. \"80vh\") — designer-controlled ceiling\n // 2. The live visual viewport height (JS, tracks keyboard in real-time)\n // 3. 100dvh — CSS-native dynamic viewport height, shrinks with iOS keyboard on Safari 15.4+\n // The dvh fallback ensures we never exceed the visible area even before\n // visualViewport fires its first event (e.g. on initial mount or slow paint).\n // CSS min() only accepts <length-percentage>, not keywords (e.g. \"none\",\n // \"max-content\"). If maxHeight is a bare keyword, pass it through;\n // otherwise compose with the live viewport clamp.\n maxHeight: /\\d/.test(maxHeight)\n ? viewportHeight !== null\n ? `min(${maxHeight}, ${Math.max(viewportHeight - 8, 0)}px, 100dvh)`\n : `min(${maxHeight}, 100dvh)`\n : maxHeight,\n }),\n }}\n >\n {showHandle && (\n <div\n className=\"absolute top-0 left-0 right-0 h-8 z-10 flex justify-center items-start pt-2 touch-none cursor-grab active:cursor-grabbing\"\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n onPointerUp={handlePointerEnd}\n onPointerCancel={handlePointerEnd}\n >\n <div\n className={twMerge(\n \"h-1 w-12 rounded-full bg-border-muted transition-all duration-300\",\n \"hover:bg-border-default hover:w-16\",\n isHandleAnimating && \"animate-[handle-wiggle_0.6s_ease-in-out]\"\n )}\n />\n </div>\n )}\n {hasHeader &&\n (hasBackArrow ? (\n <DialogHeader\n title={title}\n headerContent={headerContent}\n titleAlign={titleAlign}\n hideCloseIcon={hideCloseIcon || !onClose}\n hasBackArrow={true}\n onBack={\n onBack ??\n (() => {\n /* no-op */\n })\n }\n onClose={\n onClose ||\n (() => {\n /* Default handler */\n })\n }\n />\n ) : (\n <DialogHeader\n title={title}\n headerContent={headerContent}\n titleAlign={titleAlign}\n hideCloseIcon={hideCloseIcon || !onClose}\n onClose={\n onClose ||\n (() => {\n /* Default handler */\n })\n }\n />\n ))}\n <div\n ref={scrollContentRef}\n className={twMerge(\"flex-1 min-h-0 overflow-y-auto overscroll-contain\", contentPadding ? \"p-4\" : \"p-0\")}\n >\n {children}\n </div>\n {hasFooter && (\n <DialogFooter\n primaryAction={primaryAction}\n secondaryAction={secondaryAction}\n footerContent={footerContent}\n />\n )}\n </RACDialog>\n </div>\n </Modal>\n </ModalBackdrop>\n </ErrorBoundary>\n );\n}\n\nTray.displayName = \"Tray\";\n\n// Export types\nexport type { DialogAction } from \"../Dialog/types\";\n","import { FormProps, Form as RACForm } from \"react-aria-components\";\nimport { twMerge } from \"tailwind-merge\";\n\n/**\n * Form\n *\n * Accessibility-first form wrapper with consistent spacing.\n * Defaults to ARIA validation to use custom error styling instead of native browser tooltips.\n */\nexport function Form(props: FormProps) {\n return <RACForm validationBehavior=\"aria\" {...props} className={twMerge(\"flex flex-col gap-6\", props.className)} />;\n}\n","import * as React from \"react\";\nimport { Dialog, type DialogProps } from \"@/components/Dialog\";\nimport { Form } from \"@/components/Form\";\n\nexport interface DialogFormProps extends Omit<DialogProps, \"children\" | \"footerContent\"> {\n formId?: string;\n onSubmit?: React.FormEventHandler<HTMLFormElement>;\n primaryLabel?: string;\n secondaryLabel?: string;\n onCancel?: () => void;\n primaryVariant?: \"primary\" | \"secondary\" | \"destructive\" | \"icon\" | \"link\" | \"unstyled\" | \"ghost\";\n secondaryVariant?: \"primary\" | \"secondary\" | \"destructive\" | \"icon\" | \"link\" | \"unstyled\" | \"ghost\";\n children?: React.ReactNode;\n}\n\nexport function DialogForm({\n formId = \"dialog-form\",\n onSubmit,\n primaryLabel = \"Save\",\n secondaryLabel = \"Cancel\",\n onCancel,\n primaryVariant,\n secondaryVariant = \"secondary\",\n children,\n title,\n ...dialogProps\n}: DialogFormProps) {\n const handleFormSubmit = () => {\n // The form element itself will handle the submit event\n const form = document.getElementById(formId) as HTMLFormElement;\n if (form) {\n form.requestSubmit();\n }\n };\n\n return (\n <Dialog\n title={title}\n primaryAction={{\n label: primaryLabel,\n onPress: handleFormSubmit,\n variant: primaryVariant,\n }}\n secondaryAction={\n onCancel\n ? {\n label: secondaryLabel,\n onPress: onCancel,\n variant: secondaryVariant,\n }\n : undefined\n }\n {...dialogProps}\n >\n <Form id={formId} onSubmit={onSubmit}>\n {children}\n </Form>\n </Dialog>\n );\n}\n","import type React from \"react\";\nimport { Modal, Dialog as RACDialog } from \"react-aria-components\";\nimport { twMerge } from \"tailwind-merge\";\nimport type { DialogFooterConfig, DialogHeaderConfig } from \"../Dialog/types\";\nimport { DialogFooter } from \"../DialogFooter\";\nimport { DialogHeader } from \"../DialogHeader\";\nimport { ErrorBoundary } from \"../ErrorBoundary\";\nimport { ModalBackdrop } from \"../ModalBackdrop\";\n\nexport interface DrawerProps extends DialogHeaderConfig, DialogFooterConfig {\n /**\n * Drawer content\n */\n children?: React.ReactNode;\n /**\n * Whether the drawer is open\n */\n isOpen: boolean;\n /**\n * Side to slide in from\n * @default \"right\"\n */\n slideInFrom?: \"left\" | \"right\";\n /**\n * Whether to use a transparent backdrop\n * @default false\n */\n transparentOverlay?: boolean;\n /**\n * Callback when the drawer is closed\n */\n onClose?: () => void;\n /**\n * Additional CSS classes\n */\n className?: string;\n /**\n * Whether to include padding inside the content area\n * @default true\n */\n contentPadding?: boolean;\n /**\n * Maximum width of the drawer\n * @default \"400px\"\n */\n maxWidth?: string;\n}\n\n/**\n * Drawer\n *\n * Sliding panel that anchors to screen edges.\n */\nexport function Drawer({\n children,\n title,\n headerContent,\n titleAlign = \"left\",\n hideCloseIcon = false,\n hasBackArrow = false,\n onBack,\n isOpen,\n slideInFrom = \"right\",\n transparentOverlay = false,\n onClose,\n className,\n primaryAction,\n secondaryAction,\n tertiaryAction,\n footerContent,\n contentPadding = true,\n maxWidth = \"400px\",\n}: DrawerProps) {\n if (!isOpen) return null;\n\n const hasHeader = title || headerContent;\n const hasFooter = primaryAction || secondaryAction || tertiaryAction || footerContent;\n\n return (\n <ErrorBoundary>\n <ModalBackdrop\n isOpen={isOpen}\n onOpenChange={(open) => !open && onClose?.()}\n isDismissable\n transparent={transparentOverlay}\n >\n <Modal className=\"outline-none focus:outline-none focus-visible:outline-none ring-0 focus:ring-0 focus-visible:ring-0\">\n <RACDialog\n className={twMerge(\n \"fixed top-0 bottom-0 flex flex-col bg-background-surface shadow-xl overflow-hidden\",\n slideInFrom === \"right\" ? \"right-0\" : \"left-0\",\n slideInFrom === \"right\"\n ? \"animate-in slide-in-from-right duration-300 ease-out\"\n : \"animate-in slide-in-from-left duration-300 ease-out\",\n \"data-[exiting]:animate-out\",\n slideInFrom === \"right\" ? \"data-[exiting]:slide-out-to-right\" : \"data-[exiting]:slide-out-to-left\",\n \"data-[exiting]:duration-200 data-[exiting]:ease-in\",\n \"outline-none focus-visible:outline focus-visible:outline-2 focus-visible:outline-action-default focus-visible:outline-offset-0\",\n className\n )}\n style={{\n maxWidth: maxWidth,\n width: \"100%\",\n }}\n >\n {hasHeader &&\n (hasBackArrow && onBack ? (\n <DialogHeader\n title={title}\n headerContent={headerContent}\n titleAlign={titleAlign}\n hideCloseIcon={hideCloseIcon}\n hasBackArrow={true}\n onBack={onBack}\n onClose={onClose}\n />\n ) : (\n <DialogHeader\n title={title}\n headerContent={headerContent}\n titleAlign={titleAlign}\n hideCloseIcon={hideCloseIcon}\n onClose={onClose}\n />\n ))}\n <div className={twMerge(\"flex-1 overflow-y-auto overscroll-contain\", contentPadding ? \"px-6 py-6\" : \"p-0\")}>\n {children}\n </div>\n {hasFooter && (\n <DialogFooter\n primaryAction={primaryAction}\n secondaryAction={secondaryAction}\n tertiaryAction={tertiaryAction}\n footerContent={footerContent}\n />\n )}\n </RACDialog>\n </Modal>\n </ModalBackdrop>\n </ErrorBoundary>\n );\n}\n\nDrawer.displayName = \"Drawer\";\n\n// Export types\nexport type { DialogAction } from \"../Dialog/types\";\n","import * as React from \"react\";\nimport { Drawer, type DrawerProps } from \"@/components/Drawer\";\nimport { Form } from \"@/components/Form\";\n\nexport interface DrawerFormProps extends Omit<DrawerProps, \"children\" | \"footerContent\"> {\n formId?: string;\n onSubmit?: React.FormEventHandler<HTMLFormElement>;\n primaryLabel?: string;\n secondaryLabel?: string;\n onCancel?: () => void;\n primaryVariant?: \"primary\" | \"secondary\" | \"destructive\" | \"icon\" | \"link\" | \"unstyled\" | \"ghost\";\n secondaryVariant?: \"primary\" | \"secondary\" | \"destructive\" | \"icon\" | \"link\" | \"unstyled\" | \"ghost\";\n children?: React.ReactNode;\n}\n\nexport function DrawerForm({\n formId = \"drawer-form\",\n onSubmit,\n primaryLabel = \"Save\",\n secondaryLabel = \"Cancel\",\n onCancel,\n primaryVariant,\n secondaryVariant = \"secondary\",\n children,\n ...drawerProps\n}: DrawerFormProps) {\n const handleFormSubmit = () => {\n const form = document.getElementById(formId) as HTMLFormElement;\n if (form) {\n form.requestSubmit();\n }\n };\n\n return (\n <Drawer\n primaryAction={{\n label: primaryLabel,\n onPress: handleFormSubmit,\n variant: primaryVariant,\n }}\n secondaryAction={\n onCancel\n ? {\n label: secondaryLabel,\n onPress: onCancel,\n variant: secondaryVariant,\n }\n : undefined\n }\n {...drawerProps}\n >\n <Form id={formId} onSubmit={onSubmit} className=\"mt-2\">\n {children}\n </Form>\n </Drawer>\n );\n}\n","import * as React from \"react\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport interface FormActionsProps extends React.HTMLAttributes<HTMLDivElement> {\n align?: \"start\" | \"end\" | \"between\";\n}\n\nexport function FormActions({ align = \"end\", className, ...rest }: FormActionsProps) {\n const justify = align === \"start\" ? \"justify-start\" : align === \"between\" ? \"justify-between\" : \"justify-end\";\n return <div {...rest} className={twMerge(\"flex gap-2\", justify, className)} />;\n}\n","import * as React from \"react\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport interface FormGridProps extends React.HTMLAttributes<HTMLDivElement> {\n cols?: { base?: 1 | 2 | 3 | 4; md?: 1 | 2 | 3 | 4; lg?: 1 | 2 | 3 | 4 };\n gap?: \"sm\" | \"md\" | \"lg\";\n}\n\nconst gapClass = {\n sm: \"gap-2\",\n md: \"gap-4\",\n lg: \"gap-6\",\n} as const;\n\nfunction colsToClass(cols?: FormGridProps[\"cols\"]) {\n if (!cols) return \"\";\n const base = cols.base ? `grid-cols-${cols.base}` : \"\";\n const md = cols.md ? `md:grid-cols-${cols.md}` : \"\";\n const lg = cols.lg ? `lg:grid-cols-${cols.lg}` : \"\";\n return [base, md, lg].filter(Boolean).join(\" \");\n}\n\nexport function FormGrid({ cols = { base: 1 }, gap = \"lg\", className, ...rest }: FormGridProps) {\n return <div {...rest} className={twMerge(\"grid\", colsToClass(cols), gapClass[gap], className)} />;\n}\n","\"use client\";\n/**\n * Field Component System\n *\n * A comprehensive system for building form fields and input components with consistent\n * styling, accessibility, and behavior. This module provides both base components and\n * styling utilities that can be composed to create complex form controls.\n *\n * Key Features:\n * - Consistent styling across all form elements\n * - Built-in state handling (invalid, disabled, focused)\n * - Accessibility support out of the box\n * - Flexible composition through style utilities\n *\n * @example Basic Usage\n * ```tsx\n * <Label htmlFor=\"name\">Name</Label>\n * <Input id=\"name\" size=\"md\" />\n * ```\n *\n * @example Complex Field with All Components\n * ```tsx\n * <div>\n * <Label htmlFor=\"email\" tooltip=\"Enter your work email\">Email</Label>\n * <Input\n * id=\"email\"\n * type=\"email\"\n * isInvalid={hasError}\n * isDisabled={isSubmitting}\n * />\n * <Description>We'll never share your email</Description>\n * {hasError && <FieldError>Please enter a valid email</FieldError>}\n * </div>\n * ```\n */\n\nimport React from \"react\";\nimport type { TextProps } from \"react-aria-components\";\nimport { twMerge } from \"tailwind-merge\";\nimport { controlStyles, type Size } from \"../../utils/controlStyles\";\nimport { Icon } from \"../Icon/Icon\";\nimport { Tooltip } from \"../Tooltip/Tooltip\";\n\n// Base style props interface for all input-like components\nexport interface InputStyleProps {\n /** Whether the input is in an invalid state */\n isInvalid?: boolean;\n /** Whether the input is disabled */\n isDisabled?: boolean;\n /** Whether the input should have a transparent background */\n transparent?: boolean;\n /** The size variant of the input */\n size?: Size;\n /** Whether the input is currently focused */\n isFocused?: boolean;\n /** Additional CSS classes to apply */\n className?: string;\n}\n\n// Common interfaces\nexport interface BaseProps {\n /** The size variant of the component */\n size?: Size;\n /** Additional CSS classes to apply */\n className?: string;\n}\n\nexport type DescriptionPlacement = \"below\" | \"tooltip\" | \"inline\" | \"hidden\";\n\nexport interface BaseInputProps extends BaseProps {\n /** Whether the input should have a transparent background */\n transparent?: boolean;\n /** Whether to show a clear button when the input has a value */\n isClearable?: boolean;\n /** Callback when the clear button is clicked */\n onClear?: () => void;\n /** Whether to show a search icon */\n showSearchIcon?: boolean;\n /**\n * Whether to reserve space for error messages to prevent layout shift\n * @default true\n */\n reserveErrorSpace?: boolean;\n /**\n * Where to display the description text\n * - \"below\": Show below the field (default)\n * - \"tooltip\": Show as a tooltip on the label icon\n * - \"inline\": Show inline with the label\n * - \"hidden\": Don't display the description\n * @default \"below\"\n */\n descriptionPlacement?: DescriptionPlacement;\n}\n\nexport interface LabelProps extends BaseProps {\n /** The label content */\n children: React.ReactNode;\n /** Optional tooltip text to show next to the label */\n tooltip?: string;\n /** Optional description to show as tooltip or inline */\n description?: string;\n /** Where to display the description (only used if description is provided) */\n descriptionPlacement?: DescriptionPlacement;\n /** Whether to show a required field indicator (*) */\n isRequired?: boolean;\n /** The ID of the input this label is associated with */\n htmlFor?: string;\n}\n\nexport interface FieldErrorProps extends BaseProps {\n /** The error message to display */\n children: React.ReactNode;\n}\n\nexport interface InputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, \"size\">, InputStyleProps {\n /** The size variant of the input */\n size?: Size;\n}\n\nexport interface DescriptionProps extends Omit<TextProps, \"className\">, BaseProps {\n /** The description content */\n children: React.ReactNode;\n}\n\nexport interface FieldGroupProps extends Omit<React.HTMLAttributes<HTMLDivElement>, \"children\">, InputStyleProps {\n /** Whether any child of the group is focused */\n isFocusWithin?: boolean;\n /** Children can be either a ReactNode or a render function */\n children?: React.ReactNode | ((props: InputStyleProps) => React.ReactNode);\n}\n\n/**\n * Hook for managing input focus state\n */\nexport function useInputFocus() {\n const [isFocused, setIsFocused] = React.useState(false);\n\n const handleFocus = React.useCallback(\n (e: React.FocusEvent<HTMLInputElement>, onFocus?: (e: React.FocusEvent<HTMLInputElement>) => void) => {\n setIsFocused(true);\n onFocus?.(e);\n },\n []\n );\n\n const handleBlur = React.useCallback(\n (e: React.FocusEvent<HTMLInputElement>, onBlur?: (e: React.FocusEvent<HTMLInputElement>) => void) => {\n setIsFocused(false);\n onBlur?.(e);\n },\n []\n );\n\n return { isFocused, handleFocus, handleBlur };\n}\n\n/**\n * Wrapper component for input containers\n */\nexport const InputWrapper = React.forwardRef<\n HTMLDivElement,\n {\n children: React.ReactNode;\n className?: string;\n }\n>(({ children, className }, ref) => {\n return (\n <div ref={ref} className={twMerge(\"relative w-full\", className)}>\n {children}\n </div>\n );\n});\n\nInputWrapper.displayName = \"InputWrapper\";\n\n/**\n * Clear button component for inputs\n */\nexport function ClearButton({\n onClick,\n size = \"md\",\n className,\n}: {\n onClick: () => void;\n size?: Size;\n className?: string;\n}) {\n return (\n <button\n type=\"button\"\n onClick={(e) => {\n e.preventDefault();\n e.stopPropagation();\n onClick();\n }}\n className={twMerge(\n \"absolute right-2 top-[48%] -translate-y-1/2 transform text-text-secondary hover:text-text-primary cursor-pointer\",\n className\n )}\n aria-label=\"Clear input\"\n onMouseDown={(e) => {\n e.preventDefault();\n e.stopPropagation();\n }}\n >\n <Icon name=\"X\" size={size === \"sm\" ? 16 : 20} />\n </button>\n );\n}\n\n/**\n * Generates state-specific styles for inputs based on their current state\n * (invalid, disabled, focused).\n *\n * State Priority:\n * 1. Disabled (overrides all other states)\n * 2. Invalid + Focused\n * 3. Invalid\n * 4. Focused\n * 5. Default\n *\n * @example\n * ```tsx\n * const styles = getInputStateStyles({ isInvalid: true, isFocused: true });\n * ```\n */\nexport function getInputStateStyles(props: { isInvalid?: boolean; isDisabled?: boolean; isFocused?: boolean }) {\n const { isInvalid, isDisabled, isFocused } = props;\n const baseStyles = \"border rounded-[var(--control-border-radius)] !outline-none \";\n\n // Disabled state overrides all others\n if (isDisabled) {\n return `${baseStyles} border-border-muted`;\n }\n\n // Handle combinations of invalid and focus states\n if (isInvalid && isFocused) {\n return `${baseStyles} border-feedback-error-border shadow-[inset_0_0_0_1px_var(--color-feedback-error-border)]`;\n }\n\n if (isInvalid) {\n return `${baseStyles} border-feedback-error-border`;\n }\n\n if (isFocused) {\n return `${baseStyles} border-border-focus shadow-[inset_0_0_0_1px_var(--color-border-focus)]`;\n }\n\n // Default state - explicitly set border color\n return `${baseStyles} border-border-input`;\n}\n\n/**\n * Generates background styles based on the transparent and disabled props.\n * Uses Tailwind classes for consistent styling across light/dark modes.\n */\nexport function getInputBackgroundStyles(props: { transparent?: boolean; isDisabled?: boolean }) {\n if (props.isDisabled) {\n return \"bg-background-muted\";\n }\n return props.transparent ? \"bg-transparent\" : \"bg-background-input\";\n}\n\n/**\n * Returns the mobile font-size override class for input components.\n * iOS Safari zooms in on inputs with font-size < 16px when focused.\n * This ensures inputs use at least 16px on mobile to prevent auto-zoom,\n * while preserving the original size on desktop (768px+).\n *\n * Uses Tailwind responsive classes for proper handling by twMerge.\n */\nfunction getInputMobileFontClass(size: Size): string {\n // Only sm and md sizes need the override (they're < 16px)\n // lg and xl are already >= 16px\n // Use text-base (16px) on mobile, restore original size on md: breakpoint\n if (size === \"sm\") {\n return \"!text-base md:!text-[length:var(--control-text-sm)]\";\n }\n if (size === \"md\") {\n return \"!text-base md:!text-[length:var(--control-text-md)]\";\n }\n return \"\";\n}\n\n/**\n * Generates the complete set of base styles for input components.\n * This includes state styles, background, sizing, and custom classes.\n *\n * @example\n * ```tsx\n * const styles = getInputBaseStyles({\n * isInvalid: formState.hasError,\n * isDisabled: isLoading,\n * size: \"md\"\n * });\n * ```\n */\nexport function getInputBaseStyles(props: InputStyleProps) {\n const { isInvalid, isDisabled, isFocused, transparent, size = \"md\", className } = props;\n\n return twMerge(\n \"w-full\",\n getInputStateStyles({ isInvalid, isDisabled, isFocused }),\n getInputBackgroundStyles({ transparent, isDisabled }),\n controlStyles[size].text,\n controlStyles[size].height,\n controlStyles[size].padding,\n getInputMobileFontClass(size),\n className\n );\n}\n\n/**\n * Generates styles for grouped form elements (like input with buttons)\n *\n * @example\n * ```tsx\n * <div className={getFieldGroupStyles({ size: \"md\" })}>\n * <Input />\n * <Button>Submit</Button>\n * </div>\n * ```\n */\nexport function getFieldGroupStyles(props: FieldGroupProps) {\n const { size = \"md\", isFocusWithin, isInvalid, isDisabled, transparent, className } = props;\n\n return twMerge(\n \"group flex items-center rounded-[var(--control-border-radius)] overflow-hidden\",\n getInputBackgroundStyles({ transparent, isDisabled }),\n controlStyles[size].height,\n getInputStateStyles({ isFocused: isFocusWithin, isInvalid, isDisabled }),\n className\n );\n}\n\n// Components\n\n/**\n * Label component for form fields. Supports tooltips and required field indicators.\n *\n * @example\n * ```tsx\n * <Label\n * htmlFor=\"email\"\n * tooltip=\"Enter your work email\"\n * isRequired\n * >\n * Email Address\n * </Label>\n * ```\n */\nexport function Label({\n children,\n size = \"md\",\n tooltip,\n description,\n descriptionPlacement = \"below\",\n isRequired,\n className,\n htmlFor,\n}: LabelProps) {\n const showTooltip = tooltip || (description && descriptionPlacement === \"tooltip\");\n const tooltipContent = tooltip || description;\n const showInlineDescription = description && descriptionPlacement === \"inline\";\n\n const labelContent = (\n <label\n htmlFor={htmlFor}\n className={twMerge(controlStyles[size].text, \"!text-text-label font-semibold flex items-center gap-1\", className)}\n >\n {children}\n {isRequired && <span>*</span>}\n {showTooltip && (\n <span className=\"inline-flex items-center text-text-secondary\">\n <Icon name=\"Info\" size={size === \"sm\" ? 16 : 20} />\n </span>\n )}\n {showInlineDescription && <span className=\"text-text-secondary font-normal ml-1\">{description}</span>}\n </label>\n );\n\n if (showTooltip && tooltipContent) {\n return <Tooltip content={tooltipContent}>{labelContent}</Tooltip>;\n }\n\n return labelContent;\n}\n\n/**\n * Description component for providing additional context about a form field.\n *\n * @example\n * ```tsx\n * <Description>Must be at least 8 characters</Description>\n * ```\n */\nexport function Description({ size = \"md\", className, children, ...props }: DescriptionProps) {\n return (\n <div {...props} className={twMerge(\"leading-[2.25] text-text-secondary\", controlStyles[size].text, className)}>\n {children}\n </div>\n );\n}\n\n/**\n * Error message component for form fields. Automatically handles\n * accessibility attributes for screen readers.\n *\n * @example\n * ```tsx\n * {hasError && <FieldError>This field is required</FieldError>}\n * ```\n */\nexport function FieldError({ children, size = \"md\", className }: FieldErrorProps) {\n return (\n <div role=\"alert\" className={twMerge(controlStyles[size].text, \"text-feedback-error-text\", className)}>\n {children}\n </div>\n );\n}\n\n/**\n * Base input component with consistent styling and state handling.\n * Extends the native input element with our custom styling system.\n *\n * @example\n * ```tsx\n * <Input\n * size=\"md\"\n * isInvalid={hasError}\n * isDisabled={isLoading}\n * transparent={false}\n * />\n * ```\n */\nexport function Input({ size = \"md\", isInvalid, isDisabled, isFocused, transparent, className, ...props }: InputProps) {\n return (\n <input\n className={getInputBaseStyles({\n isInvalid,\n isDisabled,\n isFocused,\n transparent,\n size,\n className,\n })}\n {...props}\n />\n );\n}\n\n/**\n * Container for grouping form elements with consistent styling.\n * Useful for creating compound components like input with buttons.\n *\n * @example\n * ```tsx\n * <FieldGroup>\n * <Input placeholder=\"Search...\" />\n * <Button>Search</Button>\n * </FieldGroup>\n * ```\n */\nexport function FieldGroup(props: FieldGroupProps) {\n const { children, ...rest } = props;\n return (\n <div {...rest} className={getFieldGroupStyles(props)}>\n {typeof children === \"function\" ? children(props) : children}\n </div>\n );\n}\n","import * as React from \"react\";\nimport { twMerge } from \"tailwind-merge\";\nimport { Description } from \"@/components/Field\";\nimport { Heading } from \"@/components/Heading\";\n\nexport interface FormSectionProps extends Omit<React.HTMLAttributes<HTMLDivElement>, \"title\"> {\n title?: string | React.ReactNode;\n description?: string | React.ReactNode;\n showDivider?: boolean;\n}\n\nexport function FormSection({ title, description, showDivider, className, children, ...rest }: FormSectionProps) {\n return (\n <section {...rest} className={twMerge(\"flex flex-col\", className)}>\n {(title || description) && (\n <div className=\"flex flex-col gap-1 mb-6\">\n {typeof title === \"string\" ? (\n <Heading tag=\"h3\" size=\"sm\">\n {title}\n </Heading>\n ) : (\n title\n )}\n {description ? <Description size=\"lg\">{description}</Description> : null}\n </div>\n )}\n <div className=\"flex flex-col gap-6\">{children}</div>\n {showDivider && <hr className=\"mt-2 border-border-muted\" />}\n </section>\n );\n}\n\nexport function FormDivider() {\n return <hr className=\"border-border-muted\" />;\n}\n","import { twMerge } from \"tailwind-merge\";\nimport { Icon } from \"@/components/Icon\";\n\nexport interface Step {\n id: string;\n title: string;\n description?: string;\n}\n\nexport interface FormStepperProps {\n steps: Step[];\n currentStepId: string;\n onStepClick?: (id: string) => void;\n className?: string;\n}\n\nexport function FormStepper({ steps, currentStepId, onStepClick, className }: FormStepperProps) {\n const currentIndex = steps.findIndex((s) => s.id === currentStepId);\n\n return (\n <nav aria-label=\"Progress\" className={twMerge(\"w-full\", className)}>\n <div className=\"relative mb-12\">\n {/* Steps container with known structure */}\n <ol className=\"relative flex items-start justify-between\">\n {steps.map((step, index) => {\n const isActive = step.id === currentStepId;\n const isCompleted = index < currentIndex;\n const isClickable = onStepClick && (isCompleted || isActive);\n\n return (\n <li\n key={step.id}\n className=\"relative flex flex-col items-center\"\n style={{ flex: `1 1 ${100 / steps.length}%` }}\n >\n {/* Step Circle */}\n <button\n type=\"button\"\n disabled={!isClickable}\n onClick={() => isClickable && onStepClick?.(step.id)}\n className={twMerge(\n \"relative z-10 flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-full border-2 transition-colors bg-background-body\",\n isCompleted &&\n \"border-action-primary bg-action-primary text-text-inverse hover:bg-action-primary/90\",\n isActive && \"border-action-primary bg-background-body text-action-primary\",\n !isCompleted && !isActive && \"border-border-default bg-background-body text-text-secondary\",\n isClickable && \"cursor-pointer\",\n !isClickable && \"cursor-default\"\n )}\n aria-current={isActive ? \"step\" : undefined}\n >\n {isCompleted ? (\n <Icon name=\"Check\" size={20} weight=\"bold\" />\n ) : (\n <span className=\"text-sm font-semibold\">{index + 1}</span>\n )}\n </button>\n\n {/* Connecting line to next step - rendered inside the step item */}\n {index < steps.length - 1 && (\n <div\n className=\"absolute top-5 h-0.5 transition-colors\"\n style={{\n left: \"50%\",\n width: \"100%\",\n marginLeft: \"20px\",\n backgroundColor:\n index < currentIndex ? \"var(--color-action-primary)\" : \"var(--color-border-default)\",\n }}\n />\n )}\n\n {/* Step Label */}\n <div className=\"mt-3 flex flex-col items-center text-center w-32\">\n <span\n className={twMerge(\n \"text-sm font-medium\",\n isActive && \"text-text-default\",\n isCompleted && \"text-text-primary\",\n !isActive && !isCompleted && \"text-text-secondary\"\n )}\n >\n {step.title}\n </span>\n {step.description && <span className=\"mt-1 text-xs text-text-secondary\">{step.description}</span>}\n </div>\n </li>\n );\n })}\n </ol>\n </div>\n </nav>\n );\n}\n","import { twMerge } from \"tailwind-merge\";\nimport { Button } from \"@/components/Button\";\n\nexport interface SaveBarProps {\n formId?: string;\n show: boolean;\n isSubmitting?: boolean;\n onCancel?: () => void;\n primaryLabel?: string;\n secondaryLabel?: string;\n className?: string;\n}\n\nexport function SaveBar({\n formId,\n show,\n isSubmitting,\n onCancel,\n primaryLabel = \"Save changes\",\n secondaryLabel = \"Cancel\",\n className,\n}: SaveBarProps) {\n if (!show) return null;\n\n return (\n <div\n className={twMerge(\n \"fixed inset-x-0 bottom-0 z-40 border-t border-border-muted bg-background-surface/95 backdrop-blur supports-[backdrop-filter]:bg-background-surface/70\",\n className\n )}\n >\n <div className=\"mx-auto flex max-w-screen-lg items-center justify-between gap-3 p-3\">\n <div className=\"text-sm text-text-secondary\">You have unsaved changes</div>\n <div className=\"flex gap-2\">\n <Button variant=\"secondary\" onPress={onCancel}>\n {secondaryLabel}\n </Button>\n <Button type=\"submit\" form={formId} isDisabled={!!isSubmitting}>\n {isSubmitting ? \"Saving...\" : primaryLabel}\n </Button>\n </div>\n </div>\n </div>\n );\n}\n","import * as React from \"react\";\n\nexport interface UnsavedChangesPromptProps {\n when: boolean;\n message?: string;\n}\n\nexport function UnsavedChangesPrompt({\n when,\n message = \"You have unsaved changes. Leave anyway?\",\n}: UnsavedChangesPromptProps) {\n React.useEffect(() => {\n if (!when) return;\n const handler = (e: BeforeUnloadEvent) => {\n e.preventDefault();\n e.returnValue = message;\n return message;\n };\n window.addEventListener(\"beforeunload\", handler);\n return () => window.removeEventListener(\"beforeunload\", handler);\n }, [when, message]);\n\n return null;\n}\n","import * as React from \"react\";\n\nexport interface WizardStep {\n id: string;\n title: string;\n description?: string;\n}\n\nexport interface UseWizardOptions {\n steps: WizardStep[];\n initialStepId?: string;\n canNavigate?: (fromId: string, toId: string) => Promise<boolean> | boolean;\n}\n\nexport function useWizard({ steps, initialStepId, canNavigate }: UseWizardOptions) {\n if (steps.length === 0) {\n throw new Error(\"useWizard: steps array cannot be empty\");\n }\n\n const [currentStepId, setCurrentStepId] = React.useState<string>(initialStepId || steps[0].id);\n\n const stepIndex = steps.findIndex((s) => s.id === currentStepId);\n const hasPrev = stepIndex > 0;\n const hasNext = stepIndex < steps.length - 1;\n\n const goTo = async (id: string) => {\n if (id === currentStepId) return true;\n if (canNavigate) {\n const ok = await canNavigate(currentStepId, id);\n if (!ok) return false;\n }\n setCurrentStepId(id);\n return true;\n };\n\n const next = async () => {\n if (!hasNext || stepIndex === -1) return false;\n return goTo(steps[stepIndex + 1].id);\n };\n\n const prev = async () => {\n if (!hasPrev || stepIndex === -1) return false;\n return goTo(steps[stepIndex - 1].id);\n };\n\n return {\n steps,\n currentStepId,\n setCurrentStepId: goTo,\n next,\n prev,\n hasNext,\n hasPrev,\n stepIndex,\n };\n}\n"]}
1
+ {"version":3,"sources":["../../src/components/Dialog/Dialog.tsx","../../src/hooks/useMediaQuery.ts","../../src/hooks/useVisualViewportHeight.ts","../../src/utils/classNames.ts","../../src/utils/typography.ts","../../src/utils/index.ts","../../src/utils/controlStyles.ts","../../src/components/Icon/customIcons/createTextureIcon.tsx","../../src/components/Icon/customIcons/registry.tsx","../../src/components/Icon/Icon.tsx","../../src/components/Button/Button.tsx","../../src/components/DialogFooter/DialogFooter.tsx","../../src/components/Heading/Heading.tsx","../../src/components/DialogHeader/DialogHeader.tsx","../../src/components/Skeleton/Skeleton.tsx","../../src/components/Card/Card.tsx","../../src/components/ErrorBoundary/ErrorBoundary.tsx","../../src/components/ModalBackdrop/ModalBackdrop.tsx","../../src/components/Tray/Tray.tsx","../../src/components/Form/Form.tsx","../../src/form/DialogForm.tsx","../../src/components/Drawer/Drawer.tsx","../../src/form/DrawerForm.tsx","../../src/form/FormActions.tsx","../../src/form/FormGrid.tsx","../../src/components/Field/Field.tsx","../../src/form/FormSection.tsx","../../src/form/FormStepper.tsx","../../src/form/SaveBar.tsx","../../src/form/UnsavedChangesPrompt.tsx","../../src/form/useWizard.tsx"],"names":["useMediaQuery","query","defaultValue","matches","setMatches","useState","useEffect","mediaQueryList","handleChange","event","useVisualViewportHeight","enabled","state","setState","vv","update","keyboardOffset","cx","classNames","typographyRole","typeRole","role","focusRing","showDefaultOutline","controlStyles","createTextureIcon","displayName","children","Component","forwardRef","size","color","className","mirrored","alt","rest","ref","hasAccessibleName","jsx","SwitchContactBase","jsxs","Fragment","OpenBlade","ClosedBlade","CountDial","TextureRecloser","TextureFuse","TextureBreaker","TextureSource","TextureCapacitor","TextureRegulator","TextureSwitch","TextureSwitchClosed","TextureSectionalizerOpen","TextureSectionalizerClosed","TextureTransformer","PHASE_YS","solidLine","y","dashedLine","TextureSinglePhaseOverheadLine","TextureTwoPhaseOverheadLine","TextureThreePhaseOverheadLine","TextureSinglePhaseUndergroundLine","TextureTwoPhaseUndergroundLine","TextureThreePhaseUndergroundLine","TextureSupportStructure","CUSTOM_ICON_REGISTRY","customName","PhosphorIcons","sizePresets","Icon","memo","name","weight","ariaLabel","props","IconComponent","resolvedSize","iconClassName","twMerge","IconWithContainer","variant","shape","containerSize","containerClassName","iconSize","resolvedContainerSize","containerClasses","baseStyles","primaryButtonStyles","variantStyles","widthStyles","disabledStyles","enabledStyles","badgePositionStyles","badgeVariantStyles","normalizeVariant","getButtonStyles","isDisabled","fullWidth","isLoading","normalizedVariant","styles","focusRingColor","Button","icon","loadingText","loadingIndicator","iconPosition","iconWeight","href","badgeNumber","badgeVariant","badgePosition","style","target","rel","restProps","iconElement","content","loadingNode","hasBadge","composedClassName","linkProps","_onPress","_onPressStart","_onPressEnd","_onPressChange","_onPressUp","_onAuxClick","_onContextMenu","_onDoubleClick","safeRestProps","buttonOrLink","RACLink","renderProps","RACButton","ActionButton","action","defaultVariant","defaultSize","hasFormId","DialogFooter","primaryAction","secondaryAction","tertiaryAction","footerContent","hasActions","variantSizeMap","heightVariants","Heading","Tag","height","sizeClasses","heightClasses","DialogHeader","title","onClose","hideCloseIcon","titleAlign","hasBackArrow","onBack","headerContent","Skeleton","width","animation","gradient","flex","stack","responsive","delay","adjustAnimationSpeedBasedOnWidth","dataTestId","visible","setVisible","timer","baseClasses","animationSpeed","numWidth","animationClasses","shapeClasses","layoutClasses","responsiveStyles","breakpoint","value","lineWidth","index","cardVariantStyles","cardBaseStyles","aspectRatioStyles","footerAlignStyles","Card","layout","CardHeader","subtitle","actions","CardMedia","src","aspectRatio","CardContent","fill","defaultPadding","CardFooter","align","ErrorBoundary","__publicField","error","errorInfo","ModalBackdrop","transparent","ModalOverlay","composeRenderProps","SWIPE_DISMISS_THRESHOLD","SWIPE_VELOCITY_THRESHOLD","Tray","isOpen","isDismissable","transparentOverlay","maxHeight","maxWidth","contentPadding","showHandle","animationVariant","isHandleAnimating","setIsHandleAnimating","dragOffset","setDragOffset","isTransitioning","setIsTransitioning","viewport","viewportHeight","containerRef","useRef","scrollContentRef","transitionTimeoutRef","dragStateRef","scrollEl","focusScrollTimeout","handleFocusIn","e","handlePointerDown","useCallback","handlePointerMove","isDragging","startY","pointerId","deltaY","handlePointerEnd","startTime","elapsed","velocity","threshold","hasHeader","hasFooter","open","Modal","RACDialog","Dialog","minWidth","mobileMaxHeight","mobileHeight","isMobile","mobileDialogRef","handleMobileDialogScroll","dialogRef","mobileScrollContentRef","handleDialogScroll","isControlled","Form","RACForm","DialogForm","formId","onSubmit","primaryLabel","secondaryLabel","onCancel","primaryVariant","secondaryVariant","dialogProps","form","Drawer","slideInFrom","DrawerForm","drawerProps","FormActions","gapClass","colsToClass","cols","base","md","lg","FormGrid","gap","InputWrapper","React","Description","FormSection","description","showDivider","FormDivider","FormStepper","steps","currentStepId","onStepClick","currentIndex","s","step","isActive","isCompleted","isClickable","SaveBar","show","isSubmitting","UnsavedChangesPrompt","when","message","Nt","handler","useWizard","initialStepId","canNavigate","setCurrentStepId","Rt","stepIndex","hasPrev","hasNext","goTo","id"],"mappings":"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","file":"index.js","sourcesContent":["\"use client\";\n\nimport React, { useCallback, useEffect, useRef } from \"react\";\nimport { Modal, Dialog as RACDialog } from \"react-aria-components\";\nimport { twMerge } from \"tailwind-merge\";\nimport { useMediaQuery } from \"../../hooks/useMediaQuery\";\nimport { useVisualViewportHeight } from \"../../hooks/useVisualViewportHeight\";\nimport { DialogFooter } from \"../DialogFooter\";\nimport { DialogHeader } from \"../DialogHeader\";\nimport { ErrorBoundary } from \"../ErrorBoundary\";\nimport { ModalBackdrop } from \"../ModalBackdrop\";\nimport { Tray } from \"../Tray\";\nimport type { DialogFooterConfig, DialogHeaderConfig } from \"./types\";\n\nexport interface DialogProps extends Omit<DialogHeaderConfig, \"onClose\">, DialogFooterConfig {\n /**\n * Whether the dialog is open (controlled mode)\n * When using DialogTrigger, leave this undefined for automatic state management\n * @default undefined\n */\n isOpen?: boolean;\n /**\n * Callback when the dialog is closed (controlled mode)\n * When using DialogTrigger, leave this undefined for automatic state management\n * @default undefined\n */\n onClose?: () => void;\n /**\n * Dialog content\n */\n children: React.ReactNode;\n /**\n * Whether to use a transparent backdrop\n * @default false\n */\n transparentOverlay?: boolean;\n /**\n * Maximum width of the dialog\n * @default \"600px\"\n */\n maxWidth?: string;\n /**\n * Minimum width of the dialog (desktop only, mobile uses full width)\n * @default \"400px\"\n */\n minWidth?: string;\n /**\n * Maximum height of the dialog on desktop\n * @default \"85vh\"\n */\n maxHeight?: string;\n /**\n * Explicit height of the dialog on desktop (overrides maxHeight if set)\n * Content will scroll within this fixed height\n * @default undefined\n */\n height?: string;\n /**\n * Maximum height of the dialog on mobile (tray version)\n * @default \"90vh\"\n */\n mobileMaxHeight?: string;\n /**\n * Explicit height of the dialog on mobile (overrides mobileMaxHeight if set)\n * Content will scroll within this fixed height\n * @default undefined\n */\n mobileHeight?: string;\n /**\n * Whether to include padding inside the content area\n * @default true\n */\n contentPadding?: boolean;\n /**\n * Additional CSS classes\n */\n className?: string;\n}\n\n/**\n * Dialog\n *\n * Responsive modal dialog component with backdrop.\n *\n * **Desktop (≥768px):** Centered modal with scale and fade animation\n * **Mobile (<768px):** Uses Tray component for native bottom sheet experience with drag handle\n *\n * Includes optional header with title/back button and footer with action buttons.\n *\n * ## Usage Patterns\n *\n * ### Uncontrolled with DialogTrigger (Recommended)\n * ```tsx\n * import { DialogTrigger, Dialog, Button } from \"@texturehq/edges\";\n *\n * <DialogTrigger>\n * <Button>Open Dialog</Button>\n * <Dialog title=\"My Dialog\">\n * <p>Dialog content</p>\n * </Dialog>\n * </DialogTrigger>\n * ```\n *\n * ### Controlled (Advanced)\n * ```tsx\n * const [isOpen, setIsOpen] = useState(false);\n *\n * <Dialog isOpen={isOpen} onClose={() => setIsOpen(false)} title=\"My Dialog\">\n * <p>Dialog content</p>\n * </Dialog>\n * ```\n */\nexport function Dialog({\n isOpen,\n onClose,\n title,\n headerContent,\n titleAlign = \"left\",\n hideCloseIcon = false,\n hasBackArrow = false,\n onBack,\n children,\n primaryAction,\n secondaryAction,\n tertiaryAction,\n footerContent,\n transparentOverlay = false,\n maxWidth = \"600px\",\n minWidth = \"400px\",\n maxHeight = \"85vh\",\n height,\n mobileMaxHeight = \"90vh\",\n mobileHeight,\n contentPadding = true,\n className,\n}: DialogProps) {\n // Check if we're on mobile - must be called before any early returns\n const isMobile = useMediaQuery(\"(max-width: 767px)\");\n\n // Track visual viewport height to handle iOS soft keyboard pushing the tray under the keyboard.\n // Only active on mobile in uncontrolled mode (isOpen===undefined). In controlled mode, Dialog\n // delegates to <Tray> which manages its own visualViewport subscription — enabling both would\n // create duplicate listeners and unnecessary re-renders.\n const viewport = useVisualViewportHeight(isMobile && isOpen === undefined);\n const viewportHeight = viewport?.height ?? null;\n const keyboardOffset = viewport?.keyboardOffset ?? 0;\n\n // Ref to prevent unwanted scroll on the dialog container (used for mobile uncontrolled mode)\n // When focus moves to an element inside the dialog, the browser may try to\n // scroll the dialog container itself (even with overflow:hidden) to bring\n // the focused element into view. This causes the entire dialog to shift up.\n const mobileDialogRef = useRef<HTMLElement>(null);\n\n // Reset any unwanted scroll on the mobile dialog container\n const handleMobileDialogScroll = useCallback(() => {\n if (mobileDialogRef.current && mobileDialogRef.current.scrollTop !== 0) {\n mobileDialogRef.current.scrollTop = 0;\n }\n }, []);\n\n // Ref to prevent unwanted scroll on the desktop dialog container\n const dialogRef = useRef<HTMLElement>(null);\n\n // Ref for the scrollable content area in the mobile uncontrolled path.\n const mobileScrollContentRef = useRef<HTMLDivElement>(null);\n\n // On iOS, focusing an input inside a non-body scroll container won't automatically\n // scroll it into view. Listen for focusin and manually scroll after the keyboard settles.\n useEffect(() => {\n const scrollEl = mobileScrollContentRef.current;\n if (!scrollEl || !isMobile) return;\n\n let focusScrollTimeout: ReturnType<typeof setTimeout> | null = null;\n\n const handleFocusIn = (e: FocusEvent) => {\n const target = e.target as HTMLElement | null;\n if (!target) return;\n if (![\"INPUT\", \"TEXTAREA\", \"SELECT\"].includes(target.tagName)) return;\n if (focusScrollTimeout) clearTimeout(focusScrollTimeout);\n focusScrollTimeout = setTimeout(() => {\n target.scrollIntoView({ block: \"nearest\", behavior: \"smooth\" });\n }, 320);\n };\n\n scrollEl.addEventListener(\"focusin\", handleFocusIn);\n return () => {\n scrollEl.removeEventListener(\"focusin\", handleFocusIn);\n if (focusScrollTimeout) clearTimeout(focusScrollTimeout);\n };\n }, [isMobile]);\n\n // Reset any unwanted scroll on the desktop dialog container\n const handleDialogScroll = useCallback(() => {\n if (dialogRef.current && dialogRef.current.scrollTop !== 0) {\n dialogRef.current.scrollTop = 0;\n }\n }, []);\n\n // In controlled mode, don't render if closed\n if (isOpen === false) return null;\n\n const hasHeader = title || headerContent;\n const hasFooter = primaryAction || secondaryAction || tertiaryAction || footerContent;\n\n // Determine if we're in controlled mode\n const isControlled = isOpen !== undefined;\n\n // On mobile, use Tray component\n if (isMobile) {\n // In uncontrolled mode (when used with DialogTrigger), we need to return the Tray\n // but let DialogTrigger handle the state. We can't use Tray directly in uncontrolled mode\n // because Tray requires isOpen prop. So we need to wrap it similarly to desktop.\n if (!isControlled) {\n // For uncontrolled mode, render nothing - DialogTrigger will handle rendering\n // This is a limitation: mobile will fall through to desktop rendering for uncontrolled mode\n return (\n <ErrorBoundary>\n <ModalBackdrop\n isDismissable\n transparent={transparentOverlay}\n style={{\n paddingBottom: keyboardOffset > 0 ? `${keyboardOffset}px` : undefined,\n transition: \"padding-bottom 0.25s ease-out\",\n }}\n className=\"flex items-end justify-center\"\n >\n <Modal className=\"w-full p-0 outline-none focus:outline-none focus-visible:outline-none ring-0 focus:ring-0 focus-visible:ring-0\">\n <RACDialog\n ref={mobileDialogRef}\n onScroll={handleMobileDialogScroll}\n className={twMerge(\n \"relative flex w-full flex-col\",\n \"bg-background-surface\",\n \"shadow-2xl shadow-black/20\",\n \"border-t border-x border-border-default/40\",\n \"rounded-t-xl\",\n \"overflow-hidden\",\n \"animate-in slide-in-from-bottom\",\n \"duration-300 ease-out\",\n \"data-[exiting]:animate-out data-[exiting]:slide-out-to-bottom\",\n \"data-[exiting]:duration-200 data-[exiting]:ease-in\",\n className\n )}\n style={{\n // Cap height to the visual viewport so the tray stays above the iOS keyboard.\n // dvh = dynamic viewport height (shrinks with iOS keyboard on Safari 15.4+).\n // visualViewport JS value = live tracking for older Safari / edge cases.\n ...(mobileHeight\n ? { height: mobileHeight }\n : {\n // CSS min() only accepts <length-percentage>, not keywords (e.g. \"none\",\n // \"max-content\"). If mobileMaxHeight is a bare keyword, pass it through;\n // otherwise compose with the live viewport clamp.\n maxHeight: /\\d/.test(mobileMaxHeight)\n ? viewportHeight !== null\n ? `min(${mobileMaxHeight}, ${Math.max(viewportHeight - 8, 0)}px, 100dvh)`\n : `min(${mobileMaxHeight}, 100dvh)`\n : mobileMaxHeight,\n }),\n }}\n >\n <div className=\"flex justify-center pt-2\">\n <div className=\"h-1.5 w-12 rounded-full bg-border-muted\" />\n </div>\n {hasHeader &&\n (hasBackArrow ? (\n <DialogHeader\n title={title}\n headerContent={headerContent}\n titleAlign={titleAlign}\n hideCloseIcon={hideCloseIcon || !onClose}\n hasBackArrow={true}\n onBack={onBack!}\n onClose={\n onClose ||\n (() => {\n /* no-op for uncontrolled mode */\n })\n }\n />\n ) : (\n <DialogHeader\n title={title}\n headerContent={headerContent}\n titleAlign={titleAlign}\n hideCloseIcon={hideCloseIcon || !onClose}\n onClose={\n onClose ||\n (() => {\n /* no-op for uncontrolled mode */\n })\n }\n />\n ))}\n <div\n ref={mobileScrollContentRef}\n className={twMerge(\n \"flex-1 min-h-0 overflow-y-auto overscroll-contain\",\n contentPadding ? \"px-6 py-6\" : \"p-0\"\n )}\n >\n {children}\n </div>\n {hasFooter && (\n <DialogFooter\n primaryAction={primaryAction}\n secondaryAction={secondaryAction}\n tertiaryAction={tertiaryAction}\n footerContent={footerContent}\n />\n )}\n </RACDialog>\n </Modal>\n </ModalBackdrop>\n </ErrorBoundary>\n );\n }\n\n // Controlled mode - use Tray\n return (\n <Tray\n isOpen={isOpen}\n onClose={onClose}\n title={title}\n headerContent={headerContent}\n titleAlign={titleAlign}\n hideCloseIcon={hideCloseIcon}\n hasBackArrow={hasBackArrow}\n onBack={onBack}\n primaryAction={primaryAction}\n secondaryAction={secondaryAction}\n footerContent={footerContent}\n transparentOverlay={transparentOverlay}\n maxHeight={mobileMaxHeight}\n height={mobileHeight}\n maxWidth={maxWidth}\n contentPadding={contentPadding}\n showHandle={true}\n animationVariant=\"scale\"\n className={className}\n >\n {children}\n </Tray>\n );\n }\n\n // On desktop, use centered modal\n return (\n <ErrorBoundary>\n <ModalBackdrop\n // Only pass isOpen/onOpenChange in controlled mode\n {...(isControlled\n ? {\n isOpen: isOpen,\n onOpenChange: (open) => {\n if (!open && onClose) onClose();\n },\n }\n : {})}\n isDismissable\n transparent={transparentOverlay}\n className=\"flex items-center justify-center\"\n >\n <Modal\n className=\"w-full p-4 outline-none focus:outline-none focus-visible:outline-none ring-0 focus:ring-0 focus-visible:ring-0\"\n style={{ maxWidth }}\n >\n <RACDialog\n ref={dialogRef}\n onScroll={handleDialogScroll}\n className={twMerge(\n // Base structure\n \"relative flex w-full flex-col\",\n // Visual styling\n \"bg-background-surface\",\n \"shadow-2xl shadow-black/20\",\n \"border border-border-default/50\",\n // Layout\n \"rounded-md\",\n \"overflow-hidden\",\n // Remove browser focus outline/ring on the dialog container\n \"outline-none focus:outline-none focus-visible:outline-none ring-0 focus:ring-0\",\n // Desktop: scale and fade animation\n \"animate-in fade-in zoom-in-96 slide-in-from-bottom-2\",\n \"duration-300 ease-out\",\n // Exit animations\n \"data-[exiting]:animate-out data-[exiting]:fade-out data-[exiting]:zoom-out-95\",\n \"data-[exiting]:duration-200 data-[exiting]:ease-in\",\n className\n )}\n style={{\n minWidth,\n ...(height ? { height } : { maxHeight }),\n }}\n >\n {hasHeader &&\n (hasBackArrow ? (\n <DialogHeader\n title={title}\n headerContent={headerContent}\n titleAlign={titleAlign}\n hideCloseIcon={hideCloseIcon || !onClose}\n hasBackArrow={true}\n onBack={onBack!}\n onClose={\n onClose ||\n (() => {\n /* no-op for uncontrolled mode */\n })\n }\n />\n ) : (\n <DialogHeader\n title={title}\n headerContent={headerContent}\n titleAlign={titleAlign}\n hideCloseIcon={hideCloseIcon || !onClose}\n onClose={\n onClose ||\n (() => {\n /* no-op for uncontrolled mode */\n })\n }\n />\n ))}\n <div className={twMerge(\"flex-1 min-h-0 overflow-y-auto\", contentPadding ? \"px-6 py-6\" : \"p-0\")}>\n {children}\n </div>\n {hasFooter && (\n <DialogFooter\n primaryAction={primaryAction}\n secondaryAction={secondaryAction}\n tertiaryAction={tertiaryAction}\n footerContent={footerContent}\n />\n )}\n </RACDialog>\n </Modal>\n </ModalBackdrop>\n </ErrorBoundary>\n );\n}\n\n// Export types\nexport type {\n DialogAction,\n DialogFooterConfig,\n DialogHeaderConfig,\n} from \"./types\";\n","import { useEffect, useState } from \"react\";\n\n/**\n * Hook to check if a media query matches the current viewport\n *\n * @param query - A CSS media query string (e.g., \"(min-width: 768px)\")\n * @param defaultValue - The default value to return during SSR or before the first render\n * @returns A boolean indicating whether the media query matches\n *\n * @example\n * ```tsx\n * const isMobile = useMediaQuery('(max-width: 767px)');\n * const prefersReducedMotion = useMediaQuery('(prefers-reduced-motion: reduce)');\n * const isLandscape = useMediaQuery('(orientation: landscape)');\n * ```\n */\nexport function useMediaQuery(query: string, defaultValue = false): boolean {\n const [matches, setMatches] = useState<boolean>(defaultValue);\n\n useEffect(() => {\n // Return early if window is not available (SSR)\n if (typeof window === \"undefined\") return;\n\n const mediaQueryList = window.matchMedia(query);\n\n // Set initial value\n setMatches(mediaQueryList.matches);\n\n // Handler for when the media query match state changes\n const handleChange = (event: MediaQueryListEvent) => {\n setMatches(event.matches);\n };\n\n // Listen for changes\n mediaQueryList.addEventListener(\"change\", handleChange);\n\n // Cleanup\n return () => {\n mediaQueryList.removeEventListener(\"change\", handleChange);\n };\n }, [query]);\n\n return matches;\n}\n","import { useEffect, useState } from \"react\";\n\nexport interface VisualViewportState {\n /** Current visual viewport height in px */\n height: number;\n /**\n * Pixels to shift a position:fixed element upward so it sits above the keyboard.\n * = window.innerHeight - visualViewport.height - visualViewport.offsetTop\n * Zero when no keyboard is open.\n */\n keyboardOffset: number;\n}\n\n/**\n * useVisualViewportHeight\n *\n * Tracks `window.visualViewport` to handle the iOS soft keyboard.\n *\n * On iOS Safari, `position: fixed` elements are anchored to the layout viewport\n * (full page size) and don't move when the keyboard opens. This hook returns:\n *\n * - `height`: the visible viewport height (shrinks when keyboard opens)\n * - `keyboardOffset`: how many px to translate a fixed element upward to clear the keyboard\n *\n * Returns `null` on SSR or in browsers that don't support `visualViewport`.\n */\nexport function useVisualViewportHeight(enabled = true): VisualViewportState | null {\n const [state, setState] = useState<VisualViewportState | null>(null);\n\n useEffect(() => {\n if (!enabled) {\n // Reset stale state so the next open doesn't briefly flash the old viewport height.\n setState(null);\n return;\n }\n\n const vv = typeof window !== \"undefined\" ? window.visualViewport : null;\n if (!vv) return;\n\n const update = () => {\n // keyboard offset = how far the visual viewport has been pushed up from the bottom\n // of the layout viewport by the keyboard.\n const keyboardOffset = Math.max(0, window.innerHeight - vv.height - (vv.offsetTop ?? 0));\n setState({ height: vv.height, keyboardOffset });\n };\n\n update();\n\n vv.addEventListener(\"resize\", update);\n vv.addEventListener(\"scroll\", update);\n return () => {\n vv.removeEventListener(\"resize\", update);\n vv.removeEventListener(\"scroll\", update);\n };\n }, [enabled]);\n\n return state;\n}\n","type ClassValue = string | false | null | undefined;\n\n/**\n * Small className joiner for generated semantic utilities that tailwind-merge\n * does not understand yet. Use when preserving both a typography role class\n * (`text-heading-md`) and a semantic color class (`text-text-primary`) matters.\n */\nexport function cx(...classNames: ClassValue[]): string {\n return classNames.filter(Boolean).join(\" \");\n}\n","import { cx } from \"./classNames\";\n\n/**\n * Semantic typography role classes generated by @texturehq/edges-tokens.\n *\n * These classes apply the full type role — family, size, line-height,\n * weight, and letter-spacing. Pair them with explicit semantic text-color\n * utilities at the callsite.\n */\nexport const typographyRole = {\n displayXl: \"text-display-xl\",\n displayLg: \"text-display-lg\",\n displayMd: \"text-display-md\",\n displaySm: \"text-display-sm\",\n headingXl: \"text-heading-xl\",\n headingLg: \"text-heading-lg\",\n headingMd: \"text-heading-md\",\n headingSm: \"text-heading-sm\",\n bodyLg: \"text-body-lg\",\n bodyMd: \"text-body-md\",\n bodySm: \"text-body-sm\",\n labelLg: \"text-label-lg\",\n labelMd: \"text-label-md\",\n labelSm: \"text-label-sm\",\n code: \"text-code\",\n agent: \"text-agent\",\n} as const;\n\nexport type TypographyRole = keyof typeof typographyRole;\n\n/**\n * Merge a semantic typography role with semantic color utilities and any\n * component-specific layout classes. This keeps components from hand-composing\n * `text-sm font-medium leading-*` whenever a role exists.\n */\nexport function typeRole(role: TypographyRole, ...classNames: Array<string | false | null | undefined>): string {\n return cx(typographyRole[role], ...classNames);\n}\n","import { composeRenderProps } from \"react-aria-components\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport type { BrandProviderProps, BrandVariables } from \"./BrandProvider\";\nexport { BrandProvider } from \"./BrandProvider\";\nexport { ColorModeProvider, useColorMode } from \"./ColorModeProvider\";\nexport { cx } from \"./classNames\";\n\n// Re-export formatting utilities from the new formatting module\nexport * from \"./formatting\";\n\n// Re-export time formatting utilities\nexport * from \"./timeFormat\";\n\n// Re-export semantic typography role helpers\nexport * from \"./typography\";\n\nexport function focusRing(showDefaultOutline: boolean = false) {\n // Use data-[focus-visible] instead of :focus-visible to work with React Aria's focus management\n const baseClasses = showDefaultOutline\n ? \"outline outline-1 outline-border-input data-[focus-visible]:outline-2 data-[focus-visible]:outline-action-default data-[focus-visible]:outline-offset-0 invalid:outline-2 invalid:outline-feedback-error-border group-invalid:outline-2 group-invalid:outline-feedback-error-border forced-colors:focus:outline-[Highlight] forced-colors:focus:outline-2 forced-colors:focus:outline-offset-2\"\n : \"outline-none data-[focus-visible]:outline data-[focus-visible]:outline-2 data-[focus-visible]:outline-action-default data-[focus-visible]:outline-offset-0 invalid:outline-2 invalid:outline-feedback-error-border group-invalid:outline-2 group-invalid:outline-feedback-error-border forced-colors:focus:outline-[Highlight] forced-colors:focus:outline-2 forced-colors:focus:outline-offset-2\";\n return `${baseClasses}`;\n}\n\nexport function composeTailwindRenderProps<T>(\n className: string | ((v: T) => string) | undefined,\n tw: string\n): string | ((v: T) => string) {\n return composeRenderProps(className, (className) => twMerge(tw, className));\n}\n","/**\n * Control-specific style utilities for form elements and interactive components.\n * These styles use CSS variables defined in the theme for consistent sizing\n * and spacing across all control elements.\n *\n * Text sizes follow the relationships defined in theme.css:\n * sm: --control-text-sm (maps to --text-xs)\n * md: --control-text-md (maps to --text-sm)\n * lg: --control-text-lg (maps to --text-base)\n * xl: --control-text-xl (maps to --text-lg)\n */\n\nexport type Size = \"sm\" | \"md\" | \"lg\" | \"xl\";\n\nexport const controlStyles = {\n sm: {\n text: \"text-[length:var(--control-text-sm)]\",\n height: \"h-[var(--control-sm-height)]\",\n padding: \"px-[var(--control-padding-sm)]\",\n paddingY: \"py-[var(--control-gap-sm)]\",\n gap: \"gap-[var(--control-gap-sm)]\",\n },\n md: {\n text: \"text-[length:var(--control-text-md)]\",\n height: \"h-[var(--control-md-height)]\",\n padding: \"px-[var(--control-padding-md)]\",\n paddingY: \"py-[var(--control-gap-md)]\",\n gap: \"gap-[var(--control-gap-md)]\",\n },\n lg: {\n text: \"text-[length:var(--control-text-lg)]\",\n height: \"h-[var(--control-lg-height)]\",\n padding: \"px-[var(--control-padding-lg)]\",\n paddingY: \"py-[var(--control-gap-lg)]\",\n gap: \"gap-[var(--control-gap-lg)]\",\n },\n xl: {\n text: \"text-[length:var(--control-text-xl)]\",\n height: \"h-[var(--control-xl-height)]\",\n padding: \"px-[var(--control-padding-xl)]\",\n paddingY: \"py-[var(--control-gap-xl)]\",\n gap: \"gap-[var(--control-gap-xl)]\",\n },\n} as const;\n","\"use client\";\nimport type { IconProps, Icon as PhosphorIcon } from \"@phosphor-icons/react\";\nimport { forwardRef, type ReactNode } from \"react\";\n\n/**\n * Factory for Texture-authored icons that are NOT available in Phosphor but\n * must plug into the Edges `<Icon name=\"…\" />` component with the exact same\n * API (size / color / weight / className / mirrored / aria-*).\n *\n * Each custom icon is authored as a Phosphor-compatible component:\n * - 256×256 viewBox (matches Phosphor's optical grid so custom + stock icons\n * sit at the same scale)\n * - `fill={color}` defaulting to `currentColor` (inherits text color like Phosphor)\n * - `size` drives both width and height\n *\n * `weight` is accepted for API parity but is a no-op for single-weight custom\n * glyphs. Author the `children` against the 256×256 grid.\n *\n * @example\n * ```tsx\n * export const TextureRecloserIcon = createTextureIcon(\n * \"TextureRecloser\",\n * <path d=\"M48 128 ...\" />,\n * );\n * ```\n */\nexport function createTextureIcon(displayName: string, children: ReactNode): PhosphorIcon {\n const Component = forwardRef<SVGSVGElement, IconProps>(\n ({ size = 24, color = \"currentColor\", className, mirrored, alt, ...rest }, ref) => {\n // The Edges `Icon` wrapper always layers on an accessible name via\n // `aria-label` (spread through `rest`). Treat the glyph as decorative\n // ONLY when neither an explicit `alt` nor an inherited `aria-label`\n // is present — otherwise a hard-coded `aria-hidden` would silence the\n // very label the wrapper just set, hiding custom glyphs from SR users.\n const hasAccessibleName = Boolean(alt) || \"aria-label\" in rest;\n return (\n <svg\n ref={ref}\n xmlns=\"http://www.w3.org/2000/svg\"\n width={size}\n height={size}\n viewBox=\"0 0 256 256\"\n fill={color}\n className={className}\n transform={mirrored ? \"scale(-1, 1)\" : undefined}\n aria-hidden={hasAccessibleName ? undefined : true}\n role={hasAccessibleName ? \"img\" : undefined}\n aria-label={alt}\n {...rest}\n >\n {children}\n </svg>\n );\n }\n );\n\n Component.displayName = displayName;\n // Custom icons are single-weight; the cast aligns the factory output with the\n // Phosphor `Icon` component type so both resolve uniformly in the registry.\n return Component as unknown as PhosphorIcon;\n}\n","\"use client\";\nimport type { Icon as PhosphorIcon } from \"@phosphor-icons/react\";\nimport { createTextureIcon } from \"./createTextureIcon\";\n\n/**\n * Texture-authored custom icons.\n *\n * These glyphs are NOT in @phosphor-icons/react but plug into the Edges\n * `<Icon name=\"…\" />` component with the same API. Each is authored via\n * `createTextureIcon` (256×256 viewBox, currentColor fill) so it resolves\n * uniformly alongside Phosphor icons.\n *\n * NAMING: every custom icon MUST be prefixed `Texture*`. Phosphor ships ~1,500\n * names and adds more each release; the prefix guarantees a future Phosphor\n * release can never silently shadow a custom icon, and makes it obvious in\n * call sites (e.g. ENTITY_CONFIG) which icons are bespoke. The disjoint-keyset\n * assertion in Icon.tsx enforces this in development.\n *\n * NOTE: the paths below are PLACEHOLDER glyphs (simple, legible stand-ins) so\n * the pattern is wired end-to-end. Replace the `children` with the real\n * Texture-designed SVG paths when they're ready — no other code changes needed.\n */\n\n/**\n * Shared switching-device geometry (256 grid, centered on y=128).\n *\n * The switching family — Switch, Breaker, Recloser, Motor Switch, Sectionalizer\n * — all share one SPST contact base (two terminal poles + leads). Each device\n * swings a blade UP (open) or near-flat across the poles (closed), giving every\n * switchable element a real open/closed geometry, and rides a distinguishing\n * marker on the blade midpoint:\n * • Switch — no marker\n * • Breaker — outlined square (the ANSI breaker box)\n * • Recloser — outlined circle (auto-reclose)\n * • Motor Switch — outlined diamond\n * • Sectionalizer — counter dial (operation counter)\n *\n * STATE = geometry (open vs closed), so the variants are distinct glyphs wired\n * via EntityConfig.states. STATUS COLOR stays a render-layer overlay\n * (GRID_STATE_COLORS) — never baked into these glyphs.\n *\n * Blade midpoints: open ≈ (127,95), closed ≈ (127,125).\n */\nconst SwitchContactBase = () => (\n <>\n <path d=\"M12 128h44M200 128h44\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"16\" strokeLinecap=\"round\" />\n <circle cx=\"76\" cy=\"128\" r=\"20\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"16\" />\n <circle cx=\"180\" cy=\"128\" r=\"20\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"16\" />\n </>\n);\nconst OpenBlade = () => (\n <path d=\"M166 120 88 70\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"16\" strokeLinecap=\"round\" />\n);\nconst ClosedBlade = () => (\n <path d=\"M162 122 92 128\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"16\" strokeLinecap=\"round\" />\n);\n/**\n * CountDial — the sectionalizer's operation-counter motif: a near-complete ring\n * (gap at the bottom, opening toward the switch) with a filled center hub. Reads\n * as a rotary counter/dial. Fixed to the body, so it stays put across open/closed\n * while only the blade swings. Centered at (128,58), r=32 on the 256 grid.\n */\nconst CountDial = () => (\n <>\n <path\n d=\"M112 85.7 A32 32 0 1 1 144 85.7\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"16\"\n strokeLinecap=\"round\"\n />\n <circle cx=\"128\" cy=\"58\" r=\"8\" fill=\"currentColor\" stroke=\"none\" />\n </>\n);\n\n/**\n * Recloser — a bold \"R\" inside a square. The letter is a real typeface glyph\n * (SVG <text>) so it reads cleanly at any size. State (open/closed) is NOT\n * expressed geometrically here — the letter-badge is a stable identity mark;\n * live open/closed status is conveyed by the render-layer color overlay.\n */\nconst TextureRecloser = createTextureIcon(\n \"TextureRecloser\",\n <>\n <rect x=\"36\" y=\"36\" width=\"184\" height=\"184\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"16\" />\n <text\n x=\"128\"\n y=\"126\"\n textAnchor=\"middle\"\n dominantBaseline=\"central\"\n fontFamily=\"ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif\"\n fontSize=\"140\"\n fontWeight=\"700\"\n fill=\"currentColor\"\n stroke=\"none\"\n >\n R\n </text>\n </>\n);\n\n/**\n * Fuse — a single stroked sine cycle (one up/down bump) on a horizontal lead,\n * extending flat to both edges. Starts from Phosphor's WaveSine motif but is a\n * thin stroked line (not the filled glyph) with leads, matching the schematic\n * fuse symbol. Authored on the 256 grid, centered on y=128.\n */\nconst TextureFuse = createTextureIcon(\n \"TextureFuse\",\n <path\n d=\"M20 128h72q18 -84 36 0q18 84 36 0h72\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"16\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n);\n\n/**\n * Breaker — a bold \"B\" inside a square. The letter is a real typeface glyph\n * (SVG <text>) so it reads cleanly at any size. State (open/closed) is NOT\n * expressed geometrically here — the letter-badge is a stable identity mark;\n * live open/closed status is conveyed by the render-layer color overlay.\n */\nconst TextureBreaker = createTextureIcon(\n \"TextureBreaker\",\n <>\n <rect x=\"36\" y=\"36\" width=\"184\" height=\"184\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"16\" />\n <text\n x=\"128\"\n y=\"126\"\n textAnchor=\"middle\"\n dominantBaseline=\"central\"\n fontFamily=\"ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif\"\n fontSize=\"140\"\n fontWeight=\"700\"\n fill=\"currentColor\"\n stroke=\"none\"\n >\n B\n </text>\n </>\n);\n\n/**\n * Source — the standard AC source symbol: a single stroked sine cycle (matching\n * the Fuse wave, minus the leads) centered inside a circle, with short\n * horizontal leads extending to each side.\n */\nconst TextureSource = createTextureIcon(\n \"TextureSource\",\n <>\n <path d=\"M4 128h40M212 128h40\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"16\" strokeLinecap=\"round\" />\n <circle cx=\"128\" cy=\"128\" r=\"84\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"16\" />\n <path\n d=\"M92 128q18 -84 36 0q18 84 36 0\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"16\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </>\n);\n\n/**\n * Capacitor — the standard schematic symbol: two parallel vertical plates in\n * the center with horizontal leads extending to each side.\n */\nconst TextureCapacitor = createTextureIcon(\n \"TextureCapacitor\",\n <>\n <path\n d=\"M4 128h106M146 128h106M110 72v112M146 72v112\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"16\"\n strokeLinecap=\"round\"\n />\n </>\n);\n\n/**\n * Regulator — a bold \"V\" inside a circle (mirrors the Recloser treatment, which\n * is an \"R\" in a square). The letter is a real typeface glyph (SVG <text>) so it\n * reads cleanly at any size.\n */\nconst TextureRegulator = createTextureIcon(\n \"TextureRegulator\",\n <>\n <circle cx=\"128\" cy=\"128\" r=\"92\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"16\" />\n <text\n x=\"128\"\n y=\"126\"\n textAnchor=\"middle\"\n dominantBaseline=\"central\"\n fontFamily=\"ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif\"\n fontSize=\"128\"\n fontWeight=\"700\"\n fill=\"currentColor\"\n stroke=\"none\"\n >\n V\n </text>\n </>\n);\n\n/**\n * Switch — SPST contact, no marker. Open swings the blade up; closed lays it\n * near-flat across the poles. Centered on y=128 via the shared base.\n */\nconst TextureSwitch = createTextureIcon(\n \"TextureSwitch\",\n <>\n <SwitchContactBase />\n <OpenBlade />\n </>\n);\n\nconst TextureSwitchClosed = createTextureIcon(\n \"TextureSwitchClosed\",\n <>\n <SwitchContactBase />\n <ClosedBlade />\n </>\n);\n\n/**\n * Sectionalizer — switch with an operation-counter dial. A sectionalizer counts\n * upstream recloser operations and opens during a dead interval, so the counter\n * dial is its identity mark. The dial is fixed to the body (stays put across\n * open/closed); only the blade swings.\n */\nconst TextureSectionalizerOpen = createTextureIcon(\n \"TextureSectionalizerOpen\",\n <>\n <SwitchContactBase />\n <OpenBlade />\n <CountDial />\n </>\n);\nconst TextureSectionalizerClosed = createTextureIcon(\n \"TextureSectionalizerClosed\",\n <>\n <SwitchContactBase />\n <ClosedBlade />\n <CountDial />\n </>\n);\n\n/**\n * Transformer — the standard schematic symbol: two facing windings (coils),\n * each drawn as a vertical stack of three semicircular bumps with horizontal\n * leads at top and bottom. Left coil bulges right, right coil bulges left, so\n * the two windings face each other across the core gap. Authored on the 256\n * grid; coils span y=64→196 (3 bumps, r=22).\n */\nconst TextureTransformer = createTextureIcon(\n \"TextureTransformer\",\n <>\n {/* left winding — bumps bulge right, leads exit left */}\n <path\n d=\"M40 64H88A22 22 0 0 1 88 108A22 22 0 0 1 88 152A22 22 0 0 1 88 196H40\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"16\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n {/* right winding — bumps bulge left, leads exit right */}\n <path\n d=\"M216 64H168A22 22 0 0 0 168 108A22 22 0 0 0 168 152A22 22 0 0 0 168 196H216\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"16\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </>\n);\n\n/**\n * Phase × medium line matrix. Lines are drawn as N parallel horizontal\n * conductors (1/2/3 = single/two/three-phase), SOLID for overhead and DASHED\n * for underground (buried / not visible). Authored on the 256 grid; the\n * conductor stack is vertically centered on y=128 with 36u spacing. The dash\n * uses pathLength=100 + \"20 20\" so it tiles evenly with no clipped end dash.\n */\nconst PHASE_YS = { 1: [128], 2: [110, 146], 3: [92, 128, 164] } as const;\n\nconst solidLine = (y: number) => (\n <path key={y} d={`M24 ${y}h208`} fill=\"none\" stroke=\"currentColor\" strokeWidth=\"16\" strokeLinecap=\"round\" />\n);\nconst dashedLine = (y: number) => (\n <path\n key={y}\n d={`M24 ${y}h208`}\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"16\"\n strokeLinecap=\"round\"\n pathLength={100}\n strokeDasharray=\"20 20\"\n />\n);\n\nconst TextureSinglePhaseOverheadLine = createTextureIcon(\n \"TextureSinglePhaseOverheadLine\",\n <>{PHASE_YS[1].map(solidLine)}</>\n);\nconst TextureTwoPhaseOverheadLine = createTextureIcon(\"TextureTwoPhaseOverheadLine\", <>{PHASE_YS[2].map(solidLine)}</>);\nconst TextureThreePhaseOverheadLine = createTextureIcon(\n \"TextureThreePhaseOverheadLine\",\n <>{PHASE_YS[3].map(solidLine)}</>\n);\nconst TextureSinglePhaseUndergroundLine = createTextureIcon(\n \"TextureSinglePhaseUndergroundLine\",\n <>{PHASE_YS[1].map(dashedLine)}</>\n);\nconst TextureTwoPhaseUndergroundLine = createTextureIcon(\n \"TextureTwoPhaseUndergroundLine\",\n <>{PHASE_YS[2].map(dashedLine)}</>\n);\nconst TextureThreePhaseUndergroundLine = createTextureIcon(\n \"TextureThreePhaseUndergroundLine\",\n <>{PHASE_YS[3].map(dashedLine)}</>\n);\n\n/**\n * Support Structure — a single bold filled dot, larger than Phosphor's Dot, to\n * mark a pole / support point on the network. Centered on the 256 grid.\n */\nconst TextureSupportStructure = createTextureIcon(\n \"TextureSupportStructure\",\n <circle cx=\"128\" cy=\"128\" r=\"40\" fill=\"currentColor\" stroke=\"none\" />\n);\n\n/**\n * Registry of all custom icons, keyed by name. The Edges `Icon` resolver checks\n * this map first, then falls back to Phosphor. `as const satisfies` keeps the\n * keys as a literal union (drives `CustomIconName` + autocomplete) while\n * type-checking each value is a Phosphor-compatible component.\n */\nexport const CUSTOM_ICON_REGISTRY = {\n TextureRecloser,\n TextureFuse,\n TextureBreaker,\n TextureSource,\n TextureCapacitor,\n TextureRegulator,\n TextureSwitch,\n TextureSwitchClosed,\n TextureSectionalizerOpen,\n TextureSectionalizerClosed,\n TextureTransformer,\n TextureSinglePhaseOverheadLine,\n TextureTwoPhaseOverheadLine,\n TextureThreePhaseOverheadLine,\n TextureSinglePhaseUndergroundLine,\n TextureTwoPhaseUndergroundLine,\n TextureThreePhaseUndergroundLine,\n TextureSupportStructure,\n} as const satisfies Record<string, PhosphorIcon>;\n\n/** Union of all custom icon names. Folded into `IconName`. */\nexport type CustomIconName = keyof typeof CUSTOM_ICON_REGISTRY;\n","\"use client\";\nimport type { IconProps as PhosphorIconProps } from \"@phosphor-icons/react\";\nimport * as PhosphorIcons from \"@phosphor-icons/react\";\nimport { memo } from \"react\";\nimport { twMerge } from \"tailwind-merge\";\nimport { CUSTOM_ICON_REGISTRY, type CustomIconName } from \"./customIcons\";\n\n// Type for any Phosphor icon component\ntype PhosphorIconComponent = typeof PhosphorIcons.House;\n\n// Extract all icon names from the Phosphor package\nexport type PhosphorIconName = keyof typeof PhosphorIcons;\n\n// Re-export custom icon names so consumers can reference the union directly.\nexport type { CustomIconName } from \"./customIcons\";\n\n/**\n * All icon names accepted by `<Icon name=\"…\" />` — every Phosphor icon plus\n * Texture's custom icons (see `customIcons/registry.tsx`). Custom names are\n * prefixed `Texture*` and resolve through `CUSTOM_ICON_REGISTRY` first, then\n * Phosphor.\n */\nexport type IconName = PhosphorIconName | CustomIconName;\n\n// Dev-time guard: a custom icon name must never collide with a Phosphor name,\n// otherwise a future Phosphor release could silently shadow (or be shadowed by)\n// a custom glyph. The `Texture*` prefix convention prevents this; this assert\n// makes a violation loud during development instead of a silent wrong-icon.\nif (process.env.NODE_ENV === \"development\") {\n for (const customName of Object.keys(CUSTOM_ICON_REGISTRY)) {\n if (customName in PhosphorIcons) {\n console.error(\n `Custom icon \"${customName}\" collides with a Phosphor icon of the same name. ` +\n `Rename it (use the \"Texture\" prefix) to keep the icon namespace unambiguous.`\n );\n }\n }\n}\n\n// Standard size presets for the design system\nconst sizePresets = {\n xs: 16,\n sm: 20,\n md: 24,\n lg: 32,\n xl: 40,\n \"2xl\": 48,\n} as const;\n\ntype SizePreset = keyof typeof sizePresets;\n\ninterface IconProps extends Omit<PhosphorIconProps, \"size\"> {\n /**\n * The name of the icon to render — any valid icon from @phosphor-icons/react,\n * or a Texture custom icon (see customIcons/registry.tsx).\n */\n name: IconName;\n\n /**\n * Size of the icon - can be a preset or custom number\n */\n size?: SizePreset | number;\n\n /**\n * Accessibility label (maps to aria-label)\n */\n ariaLabel?: string;\n}\n\n/**\n * Icon\n *\n * Icon wrapper component with standardized sizing and styling. Provides access\n * to the full Phosphor icon library PLUS Texture's custom icons through one\n * unified `name` API, with tree-shaking support and design system presets.\n * - TypeScript autocomplete for all icon names (Phosphor + custom)\n *\n * Custom icons resolve through `CUSTOM_ICON_REGISTRY` first, then fall back to\n * Phosphor — so `<Icon name=\"TextureRecloser\" />` works exactly like\n * `<Icon name=\"House\" />`.\n *\n * Usage:\n * ```tsx\n * <Icon name=\"House\" size=\"md\" />\n * <Icon name=\"TextureRecloser\" size={32} className=\"text-brand\" />\n * ```\n */\nexport const Icon = memo(\n ({ name, size = \"md\", color, weight = \"regular\", className, ariaLabel, ...props }: IconProps) => {\n // Resolve the icon: custom registry takes precedence, then Phosphor.\n const IconComponent =\n (CUSTOM_ICON_REGISTRY[name as CustomIconName] as PhosphorIconComponent | undefined) ??\n (PhosphorIcons[name as PhosphorIconName] as PhosphorIconComponent | undefined);\n\n if (!IconComponent) {\n if (process.env.NODE_ENV === \"development\") {\n console.error(`Icon \"${name}\" not found in @phosphor-icons/react or the custom icon registry`);\n }\n return null;\n }\n\n // Resolve size to pixel value\n const resolvedSize = typeof size === \"string\" && size in sizePresets ? sizePresets[size as SizePreset] : size;\n\n // Build className with design system defaults\n const iconClassName = twMerge(\n // Default styles\n \"inline-block flex-shrink-0\",\n // Allow color inheritance from parent\n !color && \"text-current\",\n // Custom classes\n className\n );\n\n return (\n <IconComponent\n {...props}\n size={resolvedSize as number}\n color={color}\n weight={weight}\n className={iconClassName}\n aria-label={ariaLabel || `${name} icon`}\n data-testid={`icon-${name}`}\n />\n );\n }\n);\n\nIcon.displayName = \"Icon\";\n\n/**\n * Helper component for icons with containers\n */\ninterface IconWithContainerProps extends IconProps {\n /**\n * Container variant\n */\n variant?: \"subtle\" | \"solid\" | \"outline\";\n\n /**\n * Container shape\n */\n shape?: \"square\" | \"circle\";\n\n /**\n * Container size (adds padding around icon)\n */\n containerSize?: SizePreset | number;\n\n /**\n * Container background color\n */\n containerClassName?: string;\n}\n\nexport const IconWithContainer = memo(\n ({\n variant = \"subtle\",\n shape = \"square\",\n containerSize,\n containerClassName,\n size = \"md\",\n className,\n name,\n color,\n weight,\n ariaLabel,\n ref,\n ...props\n }: IconWithContainerProps & { ref?: React.Ref<HTMLDivElement> }) => {\n // Calculate container size if not specified\n const iconSize = typeof size === \"string\" && size in sizePresets ? sizePresets[size as SizePreset] : size;\n const resolvedContainerSize = containerSize\n ? typeof containerSize === \"string\" && containerSize in sizePresets\n ? sizePresets[containerSize as SizePreset]\n : containerSize\n : (iconSize as number) * 1.75; // Default to 1.75x icon size\n\n const containerClasses = twMerge(\n // Base styles\n \"inline-flex items-center justify-center flex-shrink-0\",\n\n // Shape\n shape === \"circle\" ? \"rounded-full\" : \"rounded-lg\",\n\n // Variant styles using Tailwind 4 CSS variables\n variant === \"subtle\" && \"bg-background-muted\",\n variant === \"solid\" && \"bg-action-brand text-[color:var(--color-action-brand-text)]\",\n variant === \"outline\" && \"border-2 border-current\",\n\n // Container className for overrides\n containerClassName\n );\n\n return (\n <div\n className={containerClasses}\n style={{\n width: resolvedContainerSize,\n height: resolvedContainerSize,\n }}\n >\n <Icon\n {...props}\n name={name}\n size={size}\n color={color}\n weight={weight}\n className={className}\n ariaLabel={ariaLabel}\n />\n </div>\n );\n }\n);\n\nIconWithContainer.displayName = \"IconWithContainer\";\n","import type { ComponentProps, ReactNode } from \"react\";\nimport {\n ButtonRenderProps,\n LinkRenderProps,\n Button as RACButton,\n ButtonProps as RACButtonProps,\n Link as RACLink,\n LinkProps as RACLinkProps,\n} from \"react-aria-components\";\nimport { twMerge } from \"tailwind-merge\";\nimport { focusRing } from \"../../utils\";\nimport type { Size } from \"../../utils/controlStyles\";\nimport { controlStyles } from \"../../utils/controlStyles\";\nimport { Icon } from \"../Icon\";\n\ntype IconName = ComponentProps<typeof Icon>[\"name\"];\n\ntype BaseButtonProps = Omit<RACButtonProps, \"className\">;\n\n/**\n * Button\n *\n * A versatile action component that supports multiple visual variants, sizes,\n * optional icons, a loading state, and badge indicators. Follows the Edges\n * design system tokens and composes `react-aria-components` under the hood.\n *\n * Example usage:\n * ```tsx\n * <Button variant=\"primary\" size=\"md\" icon=\"Check\">Save</Button>\n * ```\n */\ntype ButtonVariant = \"primary\" | \"secondary\" | \"destructive\" | \"icon\" | \"link\" | \"unstyled\" | \"ghost\";\ntype LegacyButtonVariant = \"default\" | \"brand\";\n\nexport interface ButtonProps extends BaseButtonProps {\n /**\n * Visual treatment. Use `primary` for the main action and `secondary` for\n * lower-emphasis actions. `default` and `brand` are deprecated aliases for\n * `primary` during the primary/secondary migration.\n */\n variant?: ButtonVariant | LegacyButtonVariant;\n size?: Size;\n badgeNumber?: number;\n badgeVariant?: \"primary\" | \"destructive\";\n badgePosition?: \"top-right\" | \"top-left\" | \"bottom-right\" | \"bottom-left\";\n fullWidth?: boolean;\n icon?: IconName;\n iconWeight?: \"thin\" | \"light\" | \"regular\" | \"bold\" | \"fill\" | \"duotone\";\n iconPosition?: \"left\" | \"right\";\n isLoading?: boolean;\n loadingText?: string;\n loadingIndicator?: React.ReactNode;\n className?: string;\n href?: string;\n target?: string;\n rel?: string;\n style?: React.CSSProperties;\n}\n\nconst baseStyles =\n \"flex font-medium justify-center items-center gap-2 text-center transition rounded-[var(--control-border-radius)] whitespace-nowrap box-border\";\n\nconst primaryButtonStyles =\n \"bg-action-primary text-[color:var(--color-action-primary-text)] hover:bg-action-primary-hover forced-colors:bg-[ButtonText] forced-colors:text-[ButtonFace] border-2 border-transparent\";\n\nconst variantStyles = {\n primary: primaryButtonStyles,\n secondary:\n \"bg-action-secondary text-[color:var(--color-action-secondary-text)] border-2 border-border-muted hover:bg-action-secondary-hover forced-colors:border-[ButtonBorder] forced-colors:bg-[ButtonFace] forced-colors:text-[ButtonText]\",\n ghost:\n \"border-none text-text-primary hover:bg-text-primary/5 forced-colors:text-[ButtonText] forced-colors:hover:bg-[ButtonFace]\",\n destructive:\n \"bg-transparent text-feedback-error-text border-2 border-border-muted hover:bg-feedback-error-background/50 forced-colors:border-[ButtonBorder] forced-colors:bg-[ButtonFace] forced-colors:text-[Mark]\",\n link: \"!text-action-primary hover:text-action-primary/90 hover:underline hover:decoration-2 hover:underline-offset-4\",\n icon: \"border-none text-text-primary hover:bg-background-hover hover:text-text-primary forced-colors:text-[ButtonText] forced-colors:hover:bg-[ButtonFace] p-1 flex-shrink-0 rounded-[var(--control-border-radius)]\",\n unstyled: \"bg-transparent\",\n} as const;\n\nconst widthStyles = {\n full: \"w-full\",\n default: \"w-fit\",\n};\n\nconst disabledStyles = \"opacity-50 cursor-not-allowed pointer-events-none\";\nconst enabledStyles = \"opacity-100 cursor-pointer\";\n\nconst badgePositionStyles = {\n \"top-right\": \"-right-2 -top-2\",\n \"top-left\": \"-left-2 -top-2\",\n \"bottom-right\": \"-right-2 -bottom-2\",\n \"bottom-left\": \"-left-2 -bottom-2\",\n} as const;\n\nconst badgeVariantStyles = {\n primary: \"bg-action-primary text-[color:var(--color-action-primary-text)]\",\n destructive: \"bg-feedback-error-border text-text-inverse\",\n} as const;\n\nfunction normalizeVariant(variant: ButtonProps[\"variant\"]): ButtonVariant {\n if (!variant || variant === \"default\" || variant === \"brand\") {\n return \"primary\";\n }\n\n return variant;\n}\n\nfunction getButtonStyles(props: ButtonProps) {\n const { variant = \"primary\", size = \"md\", isDisabled, fullWidth = false, isLoading = false } = props;\n\n const normalizedVariant = normalizeVariant(variant);\n\n let styles = normalizedVariant === \"unstyled\" ? \"\" : `${baseStyles} ${variantStyles[normalizedVariant]}`;\n\n // Add size styles using controlStyles\n if (normalizedVariant !== \"unstyled\") {\n styles += ` ${controlStyles[size].text} ${controlStyles[size].height} ${controlStyles[size].padding} ${controlStyles[size].gap}`;\n }\n\n if (isDisabled || isLoading) {\n styles += ` ${disabledStyles}`;\n } else {\n styles += ` ${enabledStyles}`;\n }\n\n if (fullWidth) {\n styles += ` ${widthStyles.full}`;\n } else {\n styles += ` ${widthStyles.default}`;\n }\n\n const focusRingColor = normalizedVariant === \"primary\" ? \"focus-visible:outline-action-primary\" : undefined;\n\n return [styles, focusRing(), focusRingColor].filter(Boolean).join(\" \");\n}\n\n/**\n * Renders an Edges Button. When `href` is provided, renders a link-styled\n * button using the same visual system.\n */\nexport function Button(props: ButtonProps) {\n const {\n icon,\n children,\n isLoading = false,\n loadingText,\n loadingIndicator,\n size = \"md\",\n iconPosition = \"left\",\n iconWeight,\n href,\n className,\n badgeNumber,\n badgeVariant = \"primary\",\n badgePosition = \"top-right\",\n style,\n target,\n rel,\n ...restProps\n } = props;\n\n // Shared icon logic\n const iconElement = icon ? <Icon name={icon} size={size} weight={iconWeight} /> : null;\n\n // Shared content logic\n const content = (\n <>\n {iconPosition === \"left\" && iconElement}\n {typeof children === \"function\" ? null : children}\n {iconPosition === \"right\" && iconElement}\n </>\n );\n\n // Loading state\n const loadingNode = (\n <div className=\"relative inline-flex items-center justify-center\">\n <div className=\"absolute inset-0 flex items-center justify-center\">\n {loadingIndicator || <Icon name=\"CircleNotch\" size={size} className=\"animate-spin\" aria-hidden=\"true\" />}\n </div>\n <div className=\"invisible\" aria-hidden=\"true\">\n {content}\n </div>\n {loadingText && (\n <span className=\"sr-only\" role=\"status\" aria-live=\"polite\">\n {loadingText}\n </span>\n )}\n </div>\n );\n\n // Compose className using twMerge to properly handle Tailwind class conflicts\n const hasBadge = (badgeNumber ?? 0) > 0;\n const composedClassName = twMerge(getButtonStyles(props), className);\n\n // Create link-specific props by filtering out button-specific props\n const linkProps: Partial<RACLinkProps> = href\n ? {\n href,\n target,\n rel,\n // Only include props that are valid for both Button and Link\n ...(restProps as Record<string, unknown>),\n }\n : {};\n\n // Remove button-specific event handlers that don't apply to links\n if (href) {\n const {\n onPress: _onPress,\n onPressStart: _onPressStart,\n onPressEnd: _onPressEnd,\n onPressChange: _onPressChange,\n onPressUp: _onPressUp,\n onAuxClick: _onAuxClick,\n onContextMenu: _onContextMenu,\n onDoubleClick: _onDoubleClick,\n ...safeRestProps\n } = restProps as Record<string, unknown>;\n Object.assign(linkProps, safeRestProps);\n }\n\n // Compose the button or link element\n const buttonOrLink = href ? (\n <RACLink\n {...linkProps}\n {...(isLoading && { \"aria-busy\": true })}\n style={hasBadge ? undefined : style}\n className={composedClassName}\n >\n {isLoading\n ? loadingNode\n : typeof children === \"function\"\n ? (function (renderProps: LinkRenderProps & { defaultChildren: ReactNode }) {\n return (\n <>\n {iconPosition === \"left\" && iconElement}\n {children(\n renderProps as unknown as ButtonRenderProps & {\n defaultChildren: ReactNode;\n }\n )}\n {iconPosition === \"right\" && iconElement}\n </>\n );\n } as (props: LinkRenderProps & { defaultChildren: ReactNode }) => ReactNode)\n : content}\n </RACLink>\n ) : (\n <RACButton\n {...restProps}\n {...(isLoading && { \"aria-busy\": true })}\n style={hasBadge ? undefined : style}\n className={composedClassName}\n >\n {isLoading\n ? loadingNode\n : typeof children === \"function\"\n ? (function (renderProps: ButtonRenderProps & { defaultChildren: ReactNode }) {\n return (\n <>\n {iconPosition === \"left\" && iconElement}\n {children(renderProps)}\n {iconPosition === \"right\" && iconElement}\n </>\n );\n } as (props: ButtonRenderProps & { defaultChildren: ReactNode }) => ReactNode)\n : content}\n </RACButton>\n );\n\n // Render badge if badgeNumber is provided and > 0\n if (hasBadge) {\n return (\n <div className={twMerge(\"relative flex\", className)} style={style}>\n {buttonOrLink}\n <span\n className={`absolute ${badgePositionStyles[badgePosition]} flex h-5 w-5 items-center justify-center rounded-full ${badgeVariantStyles[badgeVariant]} text-xs font-medium`}\n aria-label={`${badgeNumber} items`}\n >\n {badgeNumber}\n </span>\n </div>\n );\n }\n\n return buttonOrLink;\n}\n","import React from \"react\";\nimport { Button } from \"../Button\";\nimport type { DialogAction } from \"../Dialog/types\";\n\nexport interface DialogFooterProps {\n /**\n * Primary action button configuration\n */\n primaryAction?: DialogAction;\n /**\n * Secondary action button configuration\n */\n secondaryAction?: DialogAction;\n /**\n * Tertiary action button configuration (typically left-aligned destructive action)\n */\n tertiaryAction?: DialogAction;\n /**\n * Custom footer content above the action buttons\n */\n footerContent?: React.ReactNode;\n}\n\n/**\n * Renders an action button, optionally as a form submit button\n */\nfunction ActionButton({\n action,\n defaultVariant,\n defaultSize = \"lg\",\n}: {\n action: DialogAction;\n defaultVariant: DialogAction[\"variant\"];\n defaultSize?: DialogAction[\"size\"];\n}) {\n const hasFormId = !!action.formId;\n\n return (\n <Button\n type={hasFormId ? \"submit\" : \"button\"}\n form={hasFormId ? action.formId : undefined}\n size={action.size || defaultSize}\n variant={action.variant || defaultVariant}\n onPress={hasFormId ? undefined : action.onPress}\n isLoading={action.isLoading}\n isDisabled={action.isDisabled}\n >\n {action.label}\n </Button>\n );\n}\n\n/**\n * DialogFooter\n *\n * Shared footer component for Dialog and Drawer.\n * Renders action buttons with consistent styling.\n *\n * Supports form integration via the `formId` prop on actions:\n * - When `formId` is set, the button becomes a submit button for that form\n * - Use `isDisabled` to control button state based on form validation\n */\nexport function DialogFooter({ primaryAction, secondaryAction, tertiaryAction, footerContent }: DialogFooterProps) {\n const hasActions = primaryAction || secondaryAction || tertiaryAction;\n\n if (!hasActions && !footerContent) {\n return null;\n }\n\n return (\n <div className={`flex w-full flex-col items-center justify-center border-t p-4 ${footerContent ? \"h-28\" : \"\"}`}>\n {footerContent && <div className=\"flex h-10 justify-center\">{footerContent}</div>}\n {hasActions && (\n <div className=\"flex w-full items-center justify-between gap-3\">\n {/* Left-aligned tertiary action (typically destructive) */}\n <div>{tertiaryAction && <ActionButton action={tertiaryAction} defaultVariant=\"destructive\" />}</div>\n\n {/* Right-aligned primary and secondary actions */}\n <div className=\"flex items-center gap-3\">\n {secondaryAction && <ActionButton action={secondaryAction} defaultVariant=\"secondary\" />}\n {primaryAction && <ActionButton action={primaryAction} defaultVariant=\"primary\" />}\n </div>\n </div>\n )}\n </div>\n );\n}\n","import React from \"react\";\nimport { cx } from \"../../utils/classNames\";\nimport { typographyRole } from \"../../utils/typography\";\n\nconst variantSizeMap = {\n heading: {\n sm: typographyRole.headingSm,\n md: typographyRole.headingMd,\n lg: typographyRole.headingLg,\n xl: typographyRole.headingXl,\n },\n display: {\n sm: typographyRole.displaySm,\n md: typographyRole.displayMd,\n lg: typographyRole.displayLg,\n xl: typographyRole.displayXl,\n },\n} as const;\n\nconst heightVariants = {\n page: \"h-16 leading-[62px]\",\n} as const;\n\nexport type HeadingVariant = keyof typeof variantSizeMap;\nexport type HeadingSize = keyof (typeof variantSizeMap)[\"heading\"] | \"xs\";\nexport type HeadingHeight = keyof typeof heightVariants;\n\n/**\n * Heading\n *\n * Typography component for page/section headings.\n *\n * - `variant=\"heading\"` (default) uses the Inter heading scale — for page titles,\n * section titles, card titles, and other product chrome.\n * - `variant=\"display\"` uses the display scale — reserved for brand moments\n * (signup, marketing surfaces) and big-number KPIs.\n *\n * Both variants share the same `sm` / `md` / `lg` / `xl` size scale.\n */\nexport interface HeadingProps {\n tag?: React.ElementType;\n /** Type scale to render in. Defaults to \"heading\". */\n variant?: HeadingVariant;\n /** Size within the chosen variant's scale. */\n size?: HeadingSize;\n height?: HeadingHeight;\n className?: string;\n children?: React.ReactNode;\n}\n\nexport function Heading({\n tag: Tag = \"h1\",\n variant = \"heading\",\n size = \"lg\",\n height,\n className = \"\",\n children,\n}: HeadingProps) {\n const resolvedSize = size === \"xs\" ? \"sm\" : size;\n const sizeClasses = variantSizeMap[variant][resolvedSize];\n const heightClasses = height ? heightVariants[height] : \"\";\n\n return <Tag className={cx(sizeClasses, \"text-text-primary\", heightClasses, className)}>{children}</Tag>;\n}\n","import React from \"react\";\nimport { twMerge } from \"tailwind-merge\";\nimport { Button } from \"../Button\";\nimport { Heading } from \"../Heading\";\nimport { Icon } from \"../Icon\";\n\ntype BaseDialogHeaderProps = {\n title?: string;\n onClose?: () => void;\n hideCloseIcon?: boolean;\n titleAlign?: \"left\" | \"center\";\n headerContent?: React.ReactNode;\n};\n\ntype WithBackArrow = BaseDialogHeaderProps & {\n hasBackArrow: true;\n onBack: () => void;\n};\n\ntype WithoutBackArrow = BaseDialogHeaderProps & {\n hasBackArrow?: false;\n onBack?: never;\n};\n\n/**\n * DialogHeader\n *\n * Header area for dialogs with optional back arrow.\n */\nexport type DialogHeaderProps = WithBackArrow | WithoutBackArrow;\n\nexport const DialogHeader: React.FC<DialogHeaderProps> = ({\n title,\n onClose,\n hideCloseIcon = false,\n titleAlign = \"left\",\n hasBackArrow = false,\n onBack,\n headerContent,\n}) => {\n return (\n <div\n className={twMerge(\n \"relative flex h-16 w-full flex-shrink-0 items-center justify-between border-b px-6\",\n title && \"border-b\",\n titleAlign === \"center\" ? \"justify-center\" : \"\"\n )}\n >\n {hasBackArrow && (\n <Button variant=\"icon\" onPress={onBack} className=\"absolute left-6\" aria-label=\"Go back\">\n <Icon name=\"CaretLeft\" data-testid=\"back-arrow\" />\n </Button>\n )}\n {headerContent || (\n <>\n {title && <Heading size=\"xs\">{title}</Heading>}\n {onClose && !hideCloseIcon && (\n <Button variant=\"icon\" onPress={onClose} aria-label=\"Close dialog\">\n <Icon name=\"X\" data-testid=\"close-button\" />\n </Button>\n )}\n </>\n )}\n </div>\n );\n};\n","\"use client\";\n\nimport React, { useEffect, useState } from \"react\";\nimport { twMerge } from \"tailwind-merge\";\n\ninterface SkeletonProps {\n width?: number | string;\n height?: number | string;\n variant?: \"text\" | \"rect\" | \"circle\";\n animation?: \"pulse\" | \"wave\" | \"none\";\n gradient?: boolean;\n flex?: boolean;\n stack?: (number | string)[]; // Array of widths for stacked skeletons\n responsive?: Record<string, string | number>;\n delay?: number;\n adjustAnimationSpeedBasedOnWidth?: boolean;\n ariaLabel?: string;\n className?: string;\n \"data-testid\"?: string;\n}\n\n/**\n * Skeleton\n *\n * Loading placeholder component that mimics content structure.\n * Supports various shapes, animations, and responsive configurations for skeleton screens.\n */\nexport const Skeleton: React.FC<SkeletonProps> = ({\n width,\n height,\n variant = \"rect\",\n animation = \"pulse\",\n gradient = false,\n flex = false,\n stack,\n responsive,\n delay = 0,\n adjustAnimationSpeedBasedOnWidth = false,\n ariaLabel,\n className,\n \"data-testid\": dataTestId,\n}) => {\n const [visible, setVisible] = useState(delay === 0);\n\n useEffect(() => {\n if (delay > 0) {\n const timer = setTimeout(() => setVisible(true), delay);\n return () => clearTimeout(timer);\n }\n }, [delay]);\n\n if (!visible) return null;\n\n // Base styles\n const baseClasses = gradient\n ? \"bg-gradient-to-r from-[var(--color-skeleton-base)] via-[var(--color-skeleton-highlight)] to-[var(--color-skeleton-base)]\"\n : \"bg-[var(--color-skeleton-base)]\";\n\n // Adjust animation speed dynamically based on width\n const animationSpeed =\n adjustAnimationSpeedBasedOnWidth && width\n ? (() => {\n const numWidth = typeof width === \"number\" ? width : parseFloat(String(width));\n return !isNaN(numWidth) ? `animation-duration-[${Math.max(0.8, numWidth / 100)}s]` : \"\";\n })()\n : \"\";\n\n // Animation styles\n const animationClasses =\n animation === \"pulse\"\n ? `animate-pulse ${animationSpeed}`\n : animation === \"wave\"\n ? `relative overflow-hidden before:absolute before:inset-0 before:bg-gradient-to-r before:from-transparent before:via-[var(--color-skeleton-wave)] before:to-transparent before:animate-wave ${animationSpeed}`\n : \"\";\n\n // Shape-specific styles\n let shapeClasses = \"rounded-sm\";\n if (variant === \"circle\") shapeClasses = \"rounded-full\";\n if (variant === \"text\") shapeClasses = \"h-4 w-full rounded-sm\";\n\n // Dynamic layout handling\n const layoutClasses = flex ? \"flex-1 min-w-0\" : \"\";\n\n // Responsive styles\n const responsiveStyles = responsive\n ? Object.entries(responsive)\n .map(([breakpoint, value]) => `${breakpoint}:w-[${value}]`)\n .join(\" \")\n : \"\";\n\n // Stacking Multiple Skeletons\n if (stack) {\n return (\n <div className=\"space-y-2\" data-testid={dataTestId}>\n {stack.map((lineWidth, index) => (\n <div\n key={index}\n className={twMerge(baseClasses, animationClasses, shapeClasses, layoutClasses, responsiveStyles, className)}\n style={{\n width: lineWidth,\n height,\n }}\n />\n ))}\n </div>\n );\n }\n\n return (\n <div\n className={twMerge(baseClasses, animationClasses, shapeClasses, layoutClasses, responsiveStyles, className)}\n style={{\n width,\n height,\n }}\n role=\"presentation\"\n aria-hidden={!ariaLabel}\n aria-label={ariaLabel ?? undefined}\n data-testid={dataTestId}\n />\n );\n};\n\ninterface SkeletonGroupProps {\n count?: number;\n children: React.ReactNode;\n className?: string;\n \"data-testid\"?: string;\n}\n\nexport const SkeletonGroup: React.FC<SkeletonGroupProps> = ({\n count = 1,\n children,\n className,\n \"data-testid\": dataTestId,\n}) => {\n return (\n <div className={className} data-testid={dataTestId}>\n {Array.from({ length: count }).map((_, index) => (\n <div key={index}>{children}</div>\n ))}\n </div>\n );\n};\n","import React from \"react\";\nimport { twMerge } from \"tailwind-merge\";\nimport { typeRole } from \"../../utils/typography\";\nimport { Heading } from \"../Heading\";\nimport { Skeleton } from \"../Skeleton\";\n\n/**\n * Card - Enterprise surface container component\n *\n * A flexible, composable card component following enterprise design system best practices.\n * Supports modular content sections with consistent styling and accessibility.\n *\n * Usage:\n * ```tsx\n * <Card variant=\"outlined\" size=\"md\">\n * <Card.Header\n * title=\"Card Title\"\n * subtitle=\"Optional subtitle\"\n * actions={<Button variant=\"ghost\" icon=\"MoreHorizontal\" />}\n * />\n * <Card.Media src=\"image.jpg\" alt=\"Description\" />\n * <Card.Content>\n * <p>Main content goes here</p>\n * </Card.Content>\n * <Card.Footer>\n * <Button variant=\"primary\">Action</Button>\n * </Card.Footer>\n * </Card>\n * ```\n */\n\n// ——————————————————————————————————————————\n// Types\n// ——————————————————————————————————————————\n\nexport type CardVariant = \"outlined\" | \"elevated\" | \"filled\" | \"ghost\";\nexport interface CardProps {\n variant?: CardVariant;\n className?: string;\n children?: React.ReactNode;\n isLoading?: boolean;\n /** Enable flex column layout so children can expand to fill space */\n layout?: \"default\" | \"flex\";\n}\n\nexport interface CardHeaderProps {\n title?: React.ReactNode;\n subtitle?: React.ReactNode;\n actions?: React.ReactNode;\n className?: string;\n isLoading?: boolean;\n}\n\nexport interface CardMediaProps {\n src?: string;\n alt?: string;\n aspectRatio?: \"square\" | \"video\" | \"wide\" | \"auto\";\n className?: string;\n children?: React.ReactNode;\n isLoading?: boolean;\n}\n\nexport interface CardContentProps {\n className?: string;\n children?: React.ReactNode;\n isLoading?: boolean;\n /** When true and parent Card has layout=\"flex\", content expands to fill available space */\n fill?: boolean;\n}\n\nexport interface CardFooterProps {\n className?: string;\n children?: React.ReactNode;\n align?: \"start\" | \"end\" | \"center\" | \"between\";\n isLoading?: boolean;\n}\n\n// ——————————————————————————————————————————\n// Styles\n// ——————————————————————————————————————————\n\nconst cardVariantStyles: Record<CardVariant, string> = {\n outlined: \"bg-background-surface border border-border-default\",\n elevated: \"bg-background-surface border-0 shadow-md\",\n filled: \"bg-background-muted border-0\",\n ghost: \"bg-transparent border-0 shadow-none\",\n};\n\nconst cardBaseStyles = \"rounded-lg\";\n\nconst aspectRatioStyles = {\n square: \"aspect-square\",\n video: \"aspect-video\",\n wide: \"aspect-[2/1]\",\n auto: \"\",\n};\n\nconst footerAlignStyles = {\n start: \"justify-start\",\n end: \"justify-end\",\n center: \"justify-center\",\n between: \"justify-between\",\n};\n\n// ——————————————————————————————————————————\n// Main Card Component\n// ——————————————————————————————————————————\n\nexport function Card({ variant = \"outlined\", className, children, isLoading = false, layout = \"default\" }: CardProps) {\n return (\n <div\n className={twMerge(\n \"w-full overflow-hidden\",\n cardVariantStyles[variant],\n cardBaseStyles,\n layout === \"flex\" && \"flex flex-col\",\n className\n )}\n data-testid=\"card\"\n >\n {isLoading ? (\n // Skeleton fills the card completely - respects height set on card\n <Skeleton width=\"100%\" height=\"100%\" className=\"rounded-none\" />\n ) : (\n children\n )}\n </div>\n );\n}\n\n// ——————————————————————————————————————————\n// Card Header\n// ——————————————————————————————————————————\n\nexport function CardHeader({ title, subtitle, actions, className, isLoading = false }: CardHeaderProps) {\n if (isLoading) {\n return (\n <div className={twMerge(\"p-6 pb-4\", className)}>\n <div className=\"flex justify-between items-start mb-1\">\n <Skeleton width={120} height={20} />\n <Skeleton width={24} height={24} />\n </div>\n {subtitle && <Skeleton width={200} height={16} />}\n </div>\n );\n }\n\n if (!title && !subtitle && !actions) {\n return null;\n }\n\n return (\n <div className={twMerge(\"p-6 pb-4\", className)}>\n <div className=\"flex justify-between items-start gap-4\">\n <div className=\"min-w-0 flex-1\">\n {title && (\n <div className=\"mb-1\">\n {typeof title === \"string\" ? (\n <Heading tag=\"h3\" size=\"sm\" className=\"text-text-primary\">\n {title}\n </Heading>\n ) : (\n title\n )}\n </div>\n )}\n {subtitle && <div className={typeRole(\"bodySm\", \"text-text-secondary\")}>{subtitle}</div>}\n </div>\n {actions && <div className=\"flex-shrink-0\">{actions}</div>}\n </div>\n </div>\n );\n}\n\n// ——————————————————————————————————————————\n// Card Media\n// ——————————————————————————————————————————\n\nexport function CardMedia({ src, alt, aspectRatio = \"auto\", className, children, isLoading = false }: CardMediaProps) {\n if (isLoading) {\n return (\n <div className={twMerge(\"bg-background-muted\", aspectRatioStyles[aspectRatio], className)}>\n <Skeleton width=\"100%\" height=\"100%\" />\n </div>\n );\n }\n\n if (children) {\n return <div className={twMerge(\"overflow-hidden\", aspectRatioStyles[aspectRatio], className)}>{children}</div>;\n }\n\n if (!src) {\n return null;\n }\n\n return (\n <div className={twMerge(\"overflow-hidden\", aspectRatioStyles[aspectRatio], className)}>\n <img src={src} alt={alt || \"\"} className=\"w-full h-full object-cover\" loading=\"lazy\" />\n </div>\n );\n}\n\n// ——————————————————————————————————————————\n// Card Content\n// ——————————————————————————————————————————\n\nexport function CardContent({ className, children, isLoading = false, fill = false }: CardContentProps) {\n // Extract padding classes from className - if any padding class is set, respect it\n const hasPadding = className?.match(/p(?:t|b|l|r|x|y)?-(?:\\d+(?:\\.\\d+)?|px|\\[.+?\\])/);\n const defaultPadding = hasPadding ? \"\" : \"px-6 py-4\";\n\n if (isLoading) {\n return (\n <div className={twMerge(defaultPadding, fill && \"flex-1 flex flex-col min-h-0\", className)}>\n <div className=\"space-y-2\">\n <Skeleton width=\"100%\" height={16} />\n <Skeleton width=\"80%\" height={16} />\n <Skeleton width=\"60%\" height={16} />\n </div>\n </div>\n );\n }\n\n if (!children) {\n return null;\n }\n\n return (\n <div className={twMerge(\"px-6 py-4 text-text-primary\", fill && \"flex-1 flex flex-col min-h-0\", className)}>\n {children}\n </div>\n );\n}\n\n// ——————————————————————————————————————————\n// Card Footer\n// ——————————————————————————————————————————\n\nexport function CardFooter({ className, children, align = \"end\", isLoading = false }: CardFooterProps) {\n if (isLoading) {\n return (\n <div className={twMerge(\"px-6 py-4 flex gap-2 justify-end\", className)}>\n <Skeleton width={80} height={32} />\n <Skeleton width={60} height={32} />\n </div>\n );\n }\n\n if (!children) {\n return null;\n }\n\n return (\n <div className={twMerge(\"px-6 py-4 flex items-center gap-2\", footerAlignStyles[align], className)}>{children}</div>\n );\n}\n\n// ——————————————————————————————————————————\n// Compound Component API\n// ——————————————————————————————————————————\n\nCard.Header = CardHeader;\nCard.Media = CardMedia;\nCard.Content = CardContent;\nCard.Footer = CardFooter;\n","import { Component, ErrorInfo, ReactNode } from \"react\";\nimport { Card } from \"../Card\";\n\ninterface Props {\n children: ReactNode;\n fallback?: ReactNode;\n title?: string;\n}\n\ninterface State {\n hasError: boolean;\n error?: Error;\n}\n\n/**\n * ErrorBoundary\n *\n * React error boundary component for graceful error handling.\n * Catches JavaScript errors in child components and displays a fallback UI with retry option.\n */\nexport class ErrorBoundary extends Component<Props, State> {\n public state: State = {\n hasError: false,\n };\n\n public static getDerivedStateFromError(error: Error): State {\n return { hasError: true, error };\n }\n\n public componentDidCatch(error: Error, errorInfo: ErrorInfo) {\n console.error(\"Error Boundary caught an error:\", error, errorInfo);\n }\n\n private handleRetry = () => {\n this.setState({ hasError: false, error: undefined });\n if (typeof window !== \"undefined\") {\n window.location.reload();\n }\n };\n\n public render() {\n if (this.state.hasError) {\n if (this.props.fallback) {\n return this.props.fallback;\n }\n\n return (\n <Card>\n {this.props.title && <Card.Header title={this.props.title} />}\n <Card.Content>\n <div className=\"flex flex-col items-center justify-center gap-4\" data-testid=\"error-boundary\">\n <p className=\"text-feedback-error-text\">{this.state.error?.message || \"Something went wrong\"}</p>\n <button\n className=\"rounded bg-action-default px-4 py-2 text-[color:var(--color-action-default-text)] hover:bg-action-default-hover\"\n onClick={this.handleRetry}\n >\n Retry\n </button>\n </div>\n </Card.Content>\n </Card>\n );\n }\n\n return this.props.children;\n }\n}\n","import { composeRenderProps, ModalOverlay, ModalOverlayProps } from \"react-aria-components\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport interface ModalBackdropProps extends ModalOverlayProps {\n /**\n * Whether to use a transparent backdrop instead of dark overlay\n * @default false\n */\n transparent?: boolean;\n /**\n * Additional CSS classes for the backdrop\n */\n className?: string;\n}\n\n/**\n * ModalBackdrop\n *\n * Shared backdrop/overlay component used by Dialog and Drawer.\n * Wraps React Aria's ModalOverlay with consistent styling and smooth animations.\n */\nexport function ModalBackdrop({ transparent = false, className, children, ...props }: ModalBackdropProps) {\n return (\n <ModalOverlay\n {...props}\n className={composeRenderProps(className, (className, renderProps) => {\n return twMerge(\n // Base positioning and layering\n \"fixed inset-0 z-50\",\n // Remove focus outlines from modal overlay\n \"outline-none focus:outline-none focus-visible:outline-none ring-0 focus:ring-0 focus-visible:ring-0\",\n // Backdrop styling - subtle gradient for depth\n transparent\n ? \"bg-transparent\"\n : [\n \"bg-gradient-to-br from-background-modal/20 via-background-modal/15 to-background-modal/20\",\n \"backdrop-blur-[2px]\",\n \"supports-[backdrop-filter]:bg-background-modal/15\",\n ].join(\" \"),\n // Smooth animations\n renderProps.isEntering && [\"animate-in fade-in\", \"duration-300 ease-out\"].join(\" \"),\n renderProps.isExiting && [\"animate-out fade-out\", \"duration-200 ease-in\"].join(\" \"),\n className\n );\n })}\n >\n {children}\n </ModalOverlay>\n );\n}\n","import React, { useCallback, useEffect, useRef, useState } from \"react\";\nimport { Modal, Dialog as RACDialog } from \"react-aria-components\";\nimport { twMerge } from \"tailwind-merge\";\nimport { useVisualViewportHeight } from \"../../hooks/useVisualViewportHeight\";\nimport type { DialogFooterConfig, DialogHeaderConfig } from \"../Dialog/types\";\nimport { DialogFooter } from \"../DialogFooter\";\nimport { DialogHeader } from \"../DialogHeader\";\nimport { ErrorBoundary } from \"../ErrorBoundary\";\nimport { ModalBackdrop } from \"../ModalBackdrop\";\n\nconst SWIPE_DISMISS_THRESHOLD = 0.3;\nconst SWIPE_VELOCITY_THRESHOLD = 0.5;\n\nexport interface TrayProps extends DialogHeaderConfig, DialogFooterConfig {\n /**\n * Tray content\n */\n children?: React.ReactNode;\n /**\n * Controls whether the tray is visible\n */\n isOpen: boolean;\n /**\n * Called when the tray should close\n */\n onClose?: () => void;\n /**\n * Whether clicking the backdrop should dismiss the tray\n * @default true\n */\n isDismissable?: boolean;\n /**\n * Whether to use a transparent overlay behind the tray\n * @default false\n */\n transparentOverlay?: boolean;\n /**\n * Maximum height for the tray content area\n * @default \"80vh\"\n */\n maxHeight?: string;\n /**\n * Explicit height for the tray (overrides maxHeight if set)\n * Content will scroll within this fixed height\n * @default undefined\n */\n height?: string;\n /**\n * Maximum width of the tray\n * @default \"640px\"\n */\n maxWidth?: string;\n /**\n * Whether to include padding around tray content\n * @default true\n */\n contentPadding?: boolean;\n /**\n * Whether to show the drag handle indicator on mobile\n * @default true\n */\n showHandle?: boolean;\n /**\n * Animation variant for the tray entrance/exit\n * @default \"scale\" - Slide with subtle scale effect for depth\n * \"slide\" - Simple slide up/down\n */\n animationVariant?: \"slide\" | \"scale\";\n /**\n * Additional CSS classes for the tray container\n */\n className?: string;\n}\n\n/**\n * Tray\n *\n * Bottom anchored overlay optimized for mobile experiences.\n * Provides optional header/footer slots that align with Dialog & Drawer APIs.\n */\nexport function Tray({\n children,\n title,\n headerContent,\n titleAlign = \"left\",\n hideCloseIcon = false,\n hasBackArrow = false,\n onBack,\n isOpen,\n onClose,\n isDismissable = true,\n transparentOverlay = false,\n primaryAction,\n secondaryAction,\n footerContent,\n maxHeight = \"80vh\",\n height,\n maxWidth = \"640px\",\n contentPadding = true,\n showHandle = true,\n animationVariant = \"scale\",\n className,\n}: TrayProps) {\n const [isHandleAnimating, setIsHandleAnimating] = useState(false);\n const [dragOffset, setDragOffset] = useState(0);\n const [isTransitioning, setIsTransitioning] = useState(false);\n // Track the available visual viewport height so the tray resizes and repositions\n // when the iOS soft keyboard pushes up the viewport.\n const viewport = useVisualViewportHeight(isOpen);\n const viewportHeight = viewport?.height ?? null;\n const keyboardOffset = viewport?.keyboardOffset ?? 0;\n const containerRef = useRef<HTMLDivElement>(null);\n // Ref for the scrollable content area — used to scroll focused inputs into view on iOS.\n const scrollContentRef = useRef<HTMLDivElement>(null);\n const transitionTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const dragStateRef = useRef<{\n isDragging: boolean;\n startY: number;\n startTime: number;\n pointerId: number | null;\n }>({\n isDragging: false,\n startY: 0,\n startTime: 0,\n pointerId: null,\n });\n\n // Trigger a subtle handle animation when tray opens\n useEffect(() => {\n if (isOpen) {\n const timer = setTimeout(() => {\n setIsHandleAnimating(true);\n setTimeout(() => setIsHandleAnimating(false), 600);\n }, 400);\n return () => clearTimeout(timer);\n }\n }, [isOpen]);\n\n // Reset drag state when tray closes\n useEffect(() => {\n if (!isOpen) {\n setDragOffset(0);\n setIsTransitioning(false);\n dragStateRef.current = {\n isDragging: false,\n startY: 0,\n startTime: 0,\n pointerId: null,\n };\n }\n }, [isOpen]);\n\n // On iOS, focusing an input inside a non-body scroll container won't automatically\n // scroll that container to bring the input into view — the browser scrolls the page\n // body instead (which is locked by the modal). We listen for focusin on the scroll\n // container and manually scroll the focused element into view after the keyboard has\n // had a chance to open (small timeout lets visualViewport settle first).\n useEffect(() => {\n const scrollEl = scrollContentRef.current;\n if (!scrollEl || !isOpen) return;\n\n let focusScrollTimeout: ReturnType<typeof setTimeout> | null = null;\n\n const handleFocusIn = (e: FocusEvent) => {\n const target = e.target as HTMLElement | null;\n if (!target) return;\n\n // Only act on actual form inputs\n if (![\"INPUT\", \"TEXTAREA\", \"SELECT\"].includes(target.tagName)) return;\n\n // Delay so the keyboard has time to open and visualViewport to update\n if (focusScrollTimeout) clearTimeout(focusScrollTimeout);\n focusScrollTimeout = setTimeout(() => {\n target.scrollIntoView({ block: \"nearest\", behavior: \"smooth\" });\n }, 320);\n };\n\n scrollEl.addEventListener(\"focusin\", handleFocusIn);\n return () => {\n scrollEl.removeEventListener(\"focusin\", handleFocusIn);\n if (focusScrollTimeout) clearTimeout(focusScrollTimeout);\n };\n }, [isOpen]);\n\n const handlePointerDown = useCallback(\n (e: React.PointerEvent) => {\n if (!isDismissable) return;\n if (e.pointerType !== \"touch\" && e.pointerType !== \"pen\") return;\n\n // Clear any pending transition timeout from previous gesture\n if (transitionTimeoutRef.current) {\n clearTimeout(transitionTimeoutRef.current);\n transitionTimeoutRef.current = null;\n }\n\n dragStateRef.current = {\n isDragging: true,\n startY: e.clientY,\n startTime: Date.now(),\n pointerId: e.pointerId,\n };\n setIsTransitioning(false);\n e.currentTarget.setPointerCapture(e.pointerId);\n },\n [isDismissable]\n );\n\n const handlePointerMove = useCallback((e: React.PointerEvent) => {\n const { isDragging, startY, pointerId } = dragStateRef.current;\n if (!isDragging || e.pointerId !== pointerId) return;\n\n const deltaY = e.clientY - startY;\n setDragOffset(Math.max(0, deltaY));\n }, []);\n\n const handlePointerEnd = useCallback(\n (e: React.PointerEvent) => {\n const { isDragging, startY, startTime, pointerId } = dragStateRef.current;\n if (!isDragging || e.pointerId !== pointerId) return;\n\n const deltaY = e.clientY - startY;\n const elapsed = Date.now() - startTime;\n const velocity = deltaY / elapsed;\n\n dragStateRef.current = {\n isDragging: false,\n startY: 0,\n startTime: 0,\n pointerId: null,\n };\n\n const containerHeight = containerRef.current?.getBoundingClientRect().height ?? 0;\n const threshold = containerHeight * SWIPE_DISMISS_THRESHOLD;\n const shouldDismiss = deltaY > threshold || (velocity > SWIPE_VELOCITY_THRESHOLD && deltaY > 50);\n\n if (shouldDismiss && isDismissable) {\n onClose?.();\n setDragOffset(0);\n } else {\n setIsTransitioning(true);\n setDragOffset(0);\n transitionTimeoutRef.current = setTimeout(() => {\n setIsTransitioning(false);\n transitionTimeoutRef.current = null;\n }, 200);\n }\n },\n [isDismissable, onClose]\n );\n\n if (!isOpen) return null;\n\n const hasHeader = title || headerContent;\n const hasFooter = primaryAction || secondaryAction || footerContent;\n\n return (\n <ErrorBoundary>\n <ModalBackdrop\n isOpen={isOpen}\n onOpenChange={(open) => {\n if (!open) onClose?.();\n }}\n isDismissable={isDismissable}\n transparent={transparentOverlay}\n // On iOS Safari, position:fixed overlays are anchored to the layout viewport\n // and don't shift when the soft keyboard opens. We apply bottom padding equal\n // to the keyboard height so the tray — which is flex-end aligned — gets pushed\n // up above the keyboard. Transition matches the iOS keyboard animation curve.\n style={{\n paddingBottom: keyboardOffset > 0 ? `${keyboardOffset}px` : undefined,\n transition: \"padding-bottom 0.25s ease-out\",\n }}\n className=\"flex items-end justify-center p-0 sm:p-4\"\n >\n <Modal\n className=\"w-full max-w-full p-0 sm:p-2 outline-none focus:outline-none focus-visible:outline-none ring-0 focus:ring-0 focus-visible:ring-0\"\n isDismissable={isDismissable}\n >\n <div\n ref={containerRef}\n className={twMerge(\"w-full\", isTransitioning && \"transition-transform duration-200\")}\n style={{\n transform: dragOffset > 0 ? `translateY(${dragOffset}px)` : undefined,\n }}\n >\n <RACDialog\n className={twMerge(\n // Base structure\n \"relative flex w-full flex-col overflow-hidden\",\n // Background and borders with elevation\n \"bg-background-surface\",\n \"shadow-2xl shadow-black/30 dark:shadow-black/60\",\n \"border-t border-x border-border-default/40\",\n // Suppress browser focus outline/rings on the dialog container itself\n // This is safe: React Aria manages focus on interactive elements inside the dialog.\n // The container doesn't need a focus indicator as it's not directly interactive.\n \"outline-none focus:outline-none focus-visible:outline-none ring-0 focus:ring-0 focus-visible:ring-0 focus:shadow-none\",\n // Transform origin for scale animation\n \"origin-bottom\",\n // Entrance animations using combined keyframes with enterprise-grade timing\n animationVariant === \"scale\"\n ? \"animate-[tray-enter-scale_400ms_cubic-bezier(0.32,0.72,0,1)]\"\n : \"animate-[tray-enter_400ms_cubic-bezier(0.32,0.72,0,1)]\",\n // Exit animations using data-[exiting] state - snappier for responsiveness\n animationVariant === \"scale\"\n ? \"data-[exiting]:animate-[tray-exit-scale_250ms_cubic-bezier(0.32,0,0.67,0)]\"\n : \"data-[exiting]:animate-[tray-exit_250ms_cubic-bezier(0.32,0,0.67,0)]\",\n className\n )}\n style={{\n maxWidth,\n // When the iOS soft keyboard is open, window.visualViewport.height\n // is smaller than the full window height. We use that value (minus a\n // small top offset so the tray doesn't touch the status bar) as the\n // ceiling, which keeps the tray — including its footer — fully visible\n // above the keyboard. Falls back to the prop value when visualViewport\n // is unavailable or hasn't been measured yet.\n ...(height\n ? { height }\n : {\n // Use the smaller of:\n // 1. The prop maxHeight (e.g. \"80vh\") — designer-controlled ceiling\n // 2. The live visual viewport height (JS, tracks keyboard in real-time)\n // 3. 100dvh — CSS-native dynamic viewport height, shrinks with iOS keyboard on Safari 15.4+\n // The dvh fallback ensures we never exceed the visible area even before\n // visualViewport fires its first event (e.g. on initial mount or slow paint).\n // CSS min() only accepts <length-percentage>, not keywords (e.g. \"none\",\n // \"max-content\"). If maxHeight is a bare keyword, pass it through;\n // otherwise compose with the live viewport clamp.\n maxHeight: /\\d/.test(maxHeight)\n ? viewportHeight !== null\n ? `min(${maxHeight}, ${Math.max(viewportHeight - 8, 0)}px, 100dvh)`\n : `min(${maxHeight}, 100dvh)`\n : maxHeight,\n }),\n }}\n >\n {showHandle && (\n <div\n className=\"absolute top-0 left-0 right-0 h-8 z-10 flex justify-center items-start pt-2 touch-none cursor-grab active:cursor-grabbing\"\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n onPointerUp={handlePointerEnd}\n onPointerCancel={handlePointerEnd}\n >\n <div\n className={twMerge(\n \"h-1 w-12 rounded-full bg-border-muted transition-all duration-300\",\n \"hover:bg-border-default hover:w-16\",\n isHandleAnimating && \"animate-[handle-wiggle_0.6s_ease-in-out]\"\n )}\n />\n </div>\n )}\n {hasHeader &&\n (hasBackArrow ? (\n <DialogHeader\n title={title}\n headerContent={headerContent}\n titleAlign={titleAlign}\n hideCloseIcon={hideCloseIcon || !onClose}\n hasBackArrow={true}\n onBack={\n onBack ??\n (() => {\n /* no-op */\n })\n }\n onClose={\n onClose ||\n (() => {\n /* Default handler */\n })\n }\n />\n ) : (\n <DialogHeader\n title={title}\n headerContent={headerContent}\n titleAlign={titleAlign}\n hideCloseIcon={hideCloseIcon || !onClose}\n onClose={\n onClose ||\n (() => {\n /* Default handler */\n })\n }\n />\n ))}\n <div\n ref={scrollContentRef}\n className={twMerge(\"flex-1 min-h-0 overflow-y-auto overscroll-contain\", contentPadding ? \"p-4\" : \"p-0\")}\n >\n {children}\n </div>\n {hasFooter && (\n <DialogFooter\n primaryAction={primaryAction}\n secondaryAction={secondaryAction}\n footerContent={footerContent}\n />\n )}\n </RACDialog>\n </div>\n </Modal>\n </ModalBackdrop>\n </ErrorBoundary>\n );\n}\n\nTray.displayName = \"Tray\";\n\n// Export types\nexport type { DialogAction } from \"../Dialog/types\";\n","import { FormProps, Form as RACForm } from \"react-aria-components\";\nimport { twMerge } from \"tailwind-merge\";\n\n/**\n * Form\n *\n * Accessibility-first form wrapper with consistent spacing.\n * Defaults to ARIA validation to use custom error styling instead of native browser tooltips.\n */\nexport function Form(props: FormProps) {\n return <RACForm validationBehavior=\"aria\" {...props} className={twMerge(\"flex flex-col gap-6\", props.className)} />;\n}\n","import * as React from \"react\";\nimport { Dialog, type DialogProps } from \"@/components/Dialog\";\nimport { Form } from \"@/components/Form\";\n\nexport interface DialogFormProps extends Omit<DialogProps, \"children\" | \"footerContent\"> {\n formId?: string;\n onSubmit?: React.FormEventHandler<HTMLFormElement>;\n primaryLabel?: string;\n secondaryLabel?: string;\n onCancel?: () => void;\n primaryVariant?: \"primary\" | \"secondary\" | \"destructive\" | \"icon\" | \"link\" | \"unstyled\" | \"ghost\";\n secondaryVariant?: \"primary\" | \"secondary\" | \"destructive\" | \"icon\" | \"link\" | \"unstyled\" | \"ghost\";\n children?: React.ReactNode;\n}\n\nexport function DialogForm({\n formId = \"dialog-form\",\n onSubmit,\n primaryLabel = \"Save\",\n secondaryLabel = \"Cancel\",\n onCancel,\n primaryVariant,\n secondaryVariant = \"secondary\",\n children,\n title,\n ...dialogProps\n}: DialogFormProps) {\n const handleFormSubmit = () => {\n // The form element itself will handle the submit event\n const form = document.getElementById(formId) as HTMLFormElement;\n if (form) {\n form.requestSubmit();\n }\n };\n\n return (\n <Dialog\n title={title}\n primaryAction={{\n label: primaryLabel,\n onPress: handleFormSubmit,\n variant: primaryVariant,\n }}\n secondaryAction={\n onCancel\n ? {\n label: secondaryLabel,\n onPress: onCancel,\n variant: secondaryVariant,\n }\n : undefined\n }\n {...dialogProps}\n >\n <Form id={formId} onSubmit={onSubmit}>\n {children}\n </Form>\n </Dialog>\n );\n}\n","import type React from \"react\";\nimport { Modal, Dialog as RACDialog } from \"react-aria-components\";\nimport { twMerge } from \"tailwind-merge\";\nimport type { DialogFooterConfig, DialogHeaderConfig } from \"../Dialog/types\";\nimport { DialogFooter } from \"../DialogFooter\";\nimport { DialogHeader } from \"../DialogHeader\";\nimport { ErrorBoundary } from \"../ErrorBoundary\";\nimport { ModalBackdrop } from \"../ModalBackdrop\";\n\nexport interface DrawerProps extends DialogHeaderConfig, DialogFooterConfig {\n /**\n * Drawer content\n */\n children?: React.ReactNode;\n /**\n * Whether the drawer is open\n */\n isOpen: boolean;\n /**\n * Side to slide in from\n * @default \"right\"\n */\n slideInFrom?: \"left\" | \"right\";\n /**\n * Whether to use a transparent backdrop\n * @default false\n */\n transparentOverlay?: boolean;\n /**\n * Callback when the drawer is closed\n */\n onClose?: () => void;\n /**\n * Additional CSS classes\n */\n className?: string;\n /**\n * Whether to include padding inside the content area\n * @default true\n */\n contentPadding?: boolean;\n /**\n * Maximum width of the drawer\n * @default \"400px\"\n */\n maxWidth?: string;\n}\n\n/**\n * Drawer\n *\n * Sliding panel that anchors to screen edges.\n */\nexport function Drawer({\n children,\n title,\n headerContent,\n titleAlign = \"left\",\n hideCloseIcon = false,\n hasBackArrow = false,\n onBack,\n isOpen,\n slideInFrom = \"right\",\n transparentOverlay = false,\n onClose,\n className,\n primaryAction,\n secondaryAction,\n tertiaryAction,\n footerContent,\n contentPadding = true,\n maxWidth = \"400px\",\n}: DrawerProps) {\n if (!isOpen) return null;\n\n const hasHeader = title || headerContent;\n const hasFooter = primaryAction || secondaryAction || tertiaryAction || footerContent;\n\n return (\n <ErrorBoundary>\n <ModalBackdrop\n isOpen={isOpen}\n onOpenChange={(open) => !open && onClose?.()}\n isDismissable\n transparent={transparentOverlay}\n >\n <Modal className=\"outline-none focus:outline-none focus-visible:outline-none ring-0 focus:ring-0 focus-visible:ring-0\">\n <RACDialog\n className={twMerge(\n \"fixed top-0 bottom-0 flex flex-col bg-background-surface shadow-xl overflow-hidden\",\n slideInFrom === \"right\" ? \"right-0\" : \"left-0\",\n slideInFrom === \"right\"\n ? \"animate-in slide-in-from-right duration-300 ease-out\"\n : \"animate-in slide-in-from-left duration-300 ease-out\",\n \"data-[exiting]:animate-out\",\n slideInFrom === \"right\" ? \"data-[exiting]:slide-out-to-right\" : \"data-[exiting]:slide-out-to-left\",\n \"data-[exiting]:duration-200 data-[exiting]:ease-in\",\n \"outline-none focus-visible:outline focus-visible:outline-2 focus-visible:outline-action-default focus-visible:outline-offset-0\",\n className\n )}\n style={{\n maxWidth: maxWidth,\n width: \"100%\",\n }}\n >\n {hasHeader &&\n (hasBackArrow && onBack ? (\n <DialogHeader\n title={title}\n headerContent={headerContent}\n titleAlign={titleAlign}\n hideCloseIcon={hideCloseIcon}\n hasBackArrow={true}\n onBack={onBack}\n onClose={onClose}\n />\n ) : (\n <DialogHeader\n title={title}\n headerContent={headerContent}\n titleAlign={titleAlign}\n hideCloseIcon={hideCloseIcon}\n onClose={onClose}\n />\n ))}\n <div className={twMerge(\"flex-1 overflow-y-auto overscroll-contain\", contentPadding ? \"px-6 py-6\" : \"p-0\")}>\n {children}\n </div>\n {hasFooter && (\n <DialogFooter\n primaryAction={primaryAction}\n secondaryAction={secondaryAction}\n tertiaryAction={tertiaryAction}\n footerContent={footerContent}\n />\n )}\n </RACDialog>\n </Modal>\n </ModalBackdrop>\n </ErrorBoundary>\n );\n}\n\nDrawer.displayName = \"Drawer\";\n\n// Export types\nexport type { DialogAction } from \"../Dialog/types\";\n","import * as React from \"react\";\nimport { Drawer, type DrawerProps } from \"@/components/Drawer\";\nimport { Form } from \"@/components/Form\";\n\nexport interface DrawerFormProps extends Omit<DrawerProps, \"children\" | \"footerContent\"> {\n formId?: string;\n onSubmit?: React.FormEventHandler<HTMLFormElement>;\n primaryLabel?: string;\n secondaryLabel?: string;\n onCancel?: () => void;\n primaryVariant?: \"primary\" | \"secondary\" | \"destructive\" | \"icon\" | \"link\" | \"unstyled\" | \"ghost\";\n secondaryVariant?: \"primary\" | \"secondary\" | \"destructive\" | \"icon\" | \"link\" | \"unstyled\" | \"ghost\";\n children?: React.ReactNode;\n}\n\nexport function DrawerForm({\n formId = \"drawer-form\",\n onSubmit,\n primaryLabel = \"Save\",\n secondaryLabel = \"Cancel\",\n onCancel,\n primaryVariant,\n secondaryVariant = \"secondary\",\n children,\n ...drawerProps\n}: DrawerFormProps) {\n const handleFormSubmit = () => {\n const form = document.getElementById(formId) as HTMLFormElement;\n if (form) {\n form.requestSubmit();\n }\n };\n\n return (\n <Drawer\n primaryAction={{\n label: primaryLabel,\n onPress: handleFormSubmit,\n variant: primaryVariant,\n }}\n secondaryAction={\n onCancel\n ? {\n label: secondaryLabel,\n onPress: onCancel,\n variant: secondaryVariant,\n }\n : undefined\n }\n {...drawerProps}\n >\n <Form id={formId} onSubmit={onSubmit} className=\"mt-2\">\n {children}\n </Form>\n </Drawer>\n );\n}\n","import * as React from \"react\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport interface FormActionsProps extends React.HTMLAttributes<HTMLDivElement> {\n align?: \"start\" | \"end\" | \"between\";\n}\n\nexport function FormActions({ align = \"end\", className, ...rest }: FormActionsProps) {\n const justify = align === \"start\" ? \"justify-start\" : align === \"between\" ? \"justify-between\" : \"justify-end\";\n return <div {...rest} className={twMerge(\"flex gap-2\", justify, className)} />;\n}\n","import * as React from \"react\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport interface FormGridProps extends React.HTMLAttributes<HTMLDivElement> {\n cols?: { base?: 1 | 2 | 3 | 4; md?: 1 | 2 | 3 | 4; lg?: 1 | 2 | 3 | 4 };\n gap?: \"sm\" | \"md\" | \"lg\";\n}\n\nconst gapClass = {\n sm: \"gap-2\",\n md: \"gap-4\",\n lg: \"gap-6\",\n} as const;\n\nfunction colsToClass(cols?: FormGridProps[\"cols\"]) {\n if (!cols) return \"\";\n const base = cols.base ? `grid-cols-${cols.base}` : \"\";\n const md = cols.md ? `md:grid-cols-${cols.md}` : \"\";\n const lg = cols.lg ? `lg:grid-cols-${cols.lg}` : \"\";\n return [base, md, lg].filter(Boolean).join(\" \");\n}\n\nexport function FormGrid({ cols = { base: 1 }, gap = \"lg\", className, ...rest }: FormGridProps) {\n return <div {...rest} className={twMerge(\"grid\", colsToClass(cols), gapClass[gap], className)} />;\n}\n","\"use client\";\n/**\n * Field Component System\n *\n * A comprehensive system for building form fields and input components with consistent\n * styling, accessibility, and behavior. This module provides both base components and\n * styling utilities that can be composed to create complex form controls.\n *\n * Key Features:\n * - Consistent styling across all form elements\n * - Built-in state handling (invalid, disabled, focused)\n * - Accessibility support out of the box\n * - Flexible composition through style utilities\n *\n * @example Basic Usage\n * ```tsx\n * <Label htmlFor=\"name\">Name</Label>\n * <Input id=\"name\" size=\"md\" />\n * ```\n *\n * @example Complex Field with All Components\n * ```tsx\n * <div>\n * <Label htmlFor=\"email\" tooltip=\"Enter your work email\">Email</Label>\n * <Input\n * id=\"email\"\n * type=\"email\"\n * isInvalid={hasError}\n * isDisabled={isSubmitting}\n * />\n * <Description>We'll never share your email</Description>\n * {hasError && <FieldError>Please enter a valid email</FieldError>}\n * </div>\n * ```\n */\n\nimport React from \"react\";\nimport type { TextProps } from \"react-aria-components\";\nimport { twMerge } from \"tailwind-merge\";\nimport { controlStyles, type Size } from \"../../utils/controlStyles\";\nimport { Icon } from \"../Icon/Icon\";\nimport { Tooltip } from \"../Tooltip/Tooltip\";\n\n// Base style props interface for all input-like components\nexport interface InputStyleProps {\n /** Whether the input is in an invalid state */\n isInvalid?: boolean;\n /** Whether the input is disabled */\n isDisabled?: boolean;\n /** Whether the input should have a transparent background */\n transparent?: boolean;\n /** The size variant of the input */\n size?: Size;\n /** Whether the input is currently focused */\n isFocused?: boolean;\n /** Additional CSS classes to apply */\n className?: string;\n}\n\n// Common interfaces\nexport interface BaseProps {\n /** The size variant of the component */\n size?: Size;\n /** Additional CSS classes to apply */\n className?: string;\n}\n\nexport type DescriptionPlacement = \"below\" | \"tooltip\" | \"inline\" | \"hidden\";\n\nexport interface BaseInputProps extends BaseProps {\n /** Whether the input should have a transparent background */\n transparent?: boolean;\n /** Whether to show a clear button when the input has a value */\n isClearable?: boolean;\n /** Callback when the clear button is clicked */\n onClear?: () => void;\n /** Whether to show a search icon */\n showSearchIcon?: boolean;\n /**\n * Whether to reserve space for error messages to prevent layout shift\n * @default true\n */\n reserveErrorSpace?: boolean;\n /**\n * Where to display the description text\n * - \"below\": Show below the field (default)\n * - \"tooltip\": Show as a tooltip on the label icon\n * - \"inline\": Show inline with the label\n * - \"hidden\": Don't display the description\n * @default \"below\"\n */\n descriptionPlacement?: DescriptionPlacement;\n}\n\nexport interface LabelProps extends BaseProps {\n /** The label content */\n children: React.ReactNode;\n /** Optional tooltip text to show next to the label */\n tooltip?: string;\n /** Optional description to show as tooltip or inline */\n description?: string;\n /** Where to display the description (only used if description is provided) */\n descriptionPlacement?: DescriptionPlacement;\n /** Whether to show a required field indicator (*) */\n isRequired?: boolean;\n /** The ID of the input this label is associated with */\n htmlFor?: string;\n}\n\nexport interface FieldErrorProps extends BaseProps {\n /** The error message to display */\n children: React.ReactNode;\n}\n\nexport interface InputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, \"size\">, InputStyleProps {\n /** The size variant of the input */\n size?: Size;\n}\n\nexport interface DescriptionProps extends Omit<TextProps, \"className\">, BaseProps {\n /** The description content */\n children: React.ReactNode;\n}\n\nexport interface FieldGroupProps extends Omit<React.HTMLAttributes<HTMLDivElement>, \"children\">, InputStyleProps {\n /** Whether any child of the group is focused */\n isFocusWithin?: boolean;\n /** Children can be either a ReactNode or a render function */\n children?: React.ReactNode | ((props: InputStyleProps) => React.ReactNode);\n}\n\n/**\n * Hook for managing input focus state\n */\nexport function useInputFocus() {\n const [isFocused, setIsFocused] = React.useState(false);\n\n const handleFocus = React.useCallback(\n (e: React.FocusEvent<HTMLInputElement>, onFocus?: (e: React.FocusEvent<HTMLInputElement>) => void) => {\n setIsFocused(true);\n onFocus?.(e);\n },\n []\n );\n\n const handleBlur = React.useCallback(\n (e: React.FocusEvent<HTMLInputElement>, onBlur?: (e: React.FocusEvent<HTMLInputElement>) => void) => {\n setIsFocused(false);\n onBlur?.(e);\n },\n []\n );\n\n return { isFocused, handleFocus, handleBlur };\n}\n\n/**\n * Wrapper component for input containers\n */\nexport const InputWrapper = React.forwardRef<\n HTMLDivElement,\n {\n children: React.ReactNode;\n className?: string;\n }\n>(({ children, className }, ref) => {\n return (\n <div ref={ref} className={twMerge(\"relative w-full\", className)}>\n {children}\n </div>\n );\n});\n\nInputWrapper.displayName = \"InputWrapper\";\n\n/**\n * Clear button component for inputs\n */\nexport function ClearButton({\n onClick,\n size = \"md\",\n className,\n}: {\n onClick: () => void;\n size?: Size;\n className?: string;\n}) {\n return (\n <button\n type=\"button\"\n onClick={(e) => {\n e.preventDefault();\n e.stopPropagation();\n onClick();\n }}\n className={twMerge(\n \"absolute right-2 top-[48%] -translate-y-1/2 transform text-text-secondary hover:text-text-primary cursor-pointer\",\n className\n )}\n aria-label=\"Clear input\"\n onMouseDown={(e) => {\n e.preventDefault();\n e.stopPropagation();\n }}\n >\n <Icon name=\"X\" size={size === \"sm\" ? 16 : 20} />\n </button>\n );\n}\n\n/**\n * Generates state-specific styles for inputs based on their current state\n * (invalid, disabled, focused).\n *\n * State Priority:\n * 1. Disabled (overrides all other states)\n * 2. Invalid + Focused\n * 3. Invalid\n * 4. Focused\n * 5. Default\n *\n * @example\n * ```tsx\n * const styles = getInputStateStyles({ isInvalid: true, isFocused: true });\n * ```\n */\nexport function getInputStateStyles(props: { isInvalid?: boolean; isDisabled?: boolean; isFocused?: boolean }) {\n const { isInvalid, isDisabled, isFocused } = props;\n const baseStyles = \"border rounded-[var(--control-border-radius)] !outline-none \";\n\n // Disabled state overrides all others\n if (isDisabled) {\n return `${baseStyles} border-border-muted`;\n }\n\n // Handle combinations of invalid and focus states\n if (isInvalid && isFocused) {\n return `${baseStyles} border-feedback-error-border shadow-[inset_0_0_0_1px_var(--color-feedback-error-border)]`;\n }\n\n if (isInvalid) {\n return `${baseStyles} border-feedback-error-border`;\n }\n\n if (isFocused) {\n return `${baseStyles} border-border-focus shadow-[inset_0_0_0_1px_var(--color-border-focus)]`;\n }\n\n // Default state - explicitly set border color\n return `${baseStyles} border-border-input`;\n}\n\n/**\n * Generates background styles based on the transparent and disabled props.\n * Uses Tailwind classes for consistent styling across light/dark modes.\n */\nexport function getInputBackgroundStyles(props: { transparent?: boolean; isDisabled?: boolean }) {\n if (props.isDisabled) {\n return \"bg-background-muted\";\n }\n return props.transparent ? \"bg-transparent\" : \"bg-background-input\";\n}\n\n/**\n * Returns the mobile font-size override class for input components.\n * iOS Safari zooms in on inputs with font-size < 16px when focused.\n * This ensures inputs use at least 16px on mobile to prevent auto-zoom,\n * while preserving the original size on desktop (768px+).\n *\n * Uses Tailwind responsive classes for proper handling by twMerge.\n */\nfunction getInputMobileFontClass(size: Size): string {\n // Only sm and md sizes need the override (they're < 16px)\n // lg and xl are already >= 16px\n // Use text-base (16px) on mobile, restore original size on md: breakpoint\n if (size === \"sm\") {\n return \"!text-base md:!text-[length:var(--control-text-sm)]\";\n }\n if (size === \"md\") {\n return \"!text-base md:!text-[length:var(--control-text-md)]\";\n }\n return \"\";\n}\n\n/**\n * Generates the complete set of base styles for input components.\n * This includes state styles, background, sizing, and custom classes.\n *\n * @example\n * ```tsx\n * const styles = getInputBaseStyles({\n * isInvalid: formState.hasError,\n * isDisabled: isLoading,\n * size: \"md\"\n * });\n * ```\n */\nexport function getInputBaseStyles(props: InputStyleProps) {\n const { isInvalid, isDisabled, isFocused, transparent, size = \"md\", className } = props;\n\n return twMerge(\n \"w-full\",\n getInputStateStyles({ isInvalid, isDisabled, isFocused }),\n getInputBackgroundStyles({ transparent, isDisabled }),\n controlStyles[size].text,\n controlStyles[size].height,\n controlStyles[size].padding,\n getInputMobileFontClass(size),\n className\n );\n}\n\n/**\n * Generates styles for grouped form elements (like input with buttons)\n *\n * @example\n * ```tsx\n * <div className={getFieldGroupStyles({ size: \"md\" })}>\n * <Input />\n * <Button>Submit</Button>\n * </div>\n * ```\n */\nexport function getFieldGroupStyles(props: FieldGroupProps) {\n const { size = \"md\", isFocusWithin, isInvalid, isDisabled, transparent, className } = props;\n\n return twMerge(\n \"group flex items-center rounded-[var(--control-border-radius)] overflow-hidden\",\n getInputBackgroundStyles({ transparent, isDisabled }),\n controlStyles[size].height,\n getInputStateStyles({ isFocused: isFocusWithin, isInvalid, isDisabled }),\n className\n );\n}\n\n// Components\n\n/**\n * Label component for form fields. Supports tooltips and required field indicators.\n *\n * @example\n * ```tsx\n * <Label\n * htmlFor=\"email\"\n * tooltip=\"Enter your work email\"\n * isRequired\n * >\n * Email Address\n * </Label>\n * ```\n */\nexport function Label({\n children,\n size = \"md\",\n tooltip,\n description,\n descriptionPlacement = \"below\",\n isRequired,\n className,\n htmlFor,\n}: LabelProps) {\n const showTooltip = tooltip || (description && descriptionPlacement === \"tooltip\");\n const tooltipContent = tooltip || description;\n const showInlineDescription = description && descriptionPlacement === \"inline\";\n\n const labelContent = (\n <label\n htmlFor={htmlFor}\n className={twMerge(controlStyles[size].text, \"!text-text-label font-semibold flex items-center gap-1\", className)}\n >\n {children}\n {isRequired && <span>*</span>}\n {showTooltip && (\n <span className=\"inline-flex items-center text-text-secondary\">\n <Icon name=\"Info\" size={size === \"sm\" ? 16 : 20} />\n </span>\n )}\n {showInlineDescription && <span className=\"text-text-secondary font-normal ml-1\">{description}</span>}\n </label>\n );\n\n if (showTooltip && tooltipContent) {\n return <Tooltip content={tooltipContent}>{labelContent}</Tooltip>;\n }\n\n return labelContent;\n}\n\n/**\n * Description component for providing additional context about a form field.\n *\n * @example\n * ```tsx\n * <Description>Must be at least 8 characters</Description>\n * ```\n */\nexport function Description({ size = \"md\", className, children, ...props }: DescriptionProps) {\n return (\n <div {...props} className={twMerge(\"leading-[2.25] text-text-secondary\", controlStyles[size].text, className)}>\n {children}\n </div>\n );\n}\n\n/**\n * Error message component for form fields. Automatically handles\n * accessibility attributes for screen readers.\n *\n * @example\n * ```tsx\n * {hasError && <FieldError>This field is required</FieldError>}\n * ```\n */\nexport function FieldError({ children, size = \"md\", className }: FieldErrorProps) {\n return (\n <div role=\"alert\" className={twMerge(controlStyles[size].text, \"text-feedback-error-text\", className)}>\n {children}\n </div>\n );\n}\n\n/**\n * Base input component with consistent styling and state handling.\n * Extends the native input element with our custom styling system.\n *\n * @example\n * ```tsx\n * <Input\n * size=\"md\"\n * isInvalid={hasError}\n * isDisabled={isLoading}\n * transparent={false}\n * />\n * ```\n */\nexport function Input({ size = \"md\", isInvalid, isDisabled, isFocused, transparent, className, ...props }: InputProps) {\n return (\n <input\n className={getInputBaseStyles({\n isInvalid,\n isDisabled,\n isFocused,\n transparent,\n size,\n className,\n })}\n {...props}\n />\n );\n}\n\n/**\n * Container for grouping form elements with consistent styling.\n * Useful for creating compound components like input with buttons.\n *\n * @example\n * ```tsx\n * <FieldGroup>\n * <Input placeholder=\"Search...\" />\n * <Button>Search</Button>\n * </FieldGroup>\n * ```\n */\nexport function FieldGroup(props: FieldGroupProps) {\n const { children, ...rest } = props;\n return (\n <div {...rest} className={getFieldGroupStyles(props)}>\n {typeof children === \"function\" ? children(props) : children}\n </div>\n );\n}\n","import * as React from \"react\";\nimport { twMerge } from \"tailwind-merge\";\nimport { Description } from \"@/components/Field\";\nimport { Heading } from \"@/components/Heading\";\n\nexport interface FormSectionProps extends Omit<React.HTMLAttributes<HTMLDivElement>, \"title\"> {\n title?: string | React.ReactNode;\n description?: string | React.ReactNode;\n showDivider?: boolean;\n}\n\nexport function FormSection({ title, description, showDivider, className, children, ...rest }: FormSectionProps) {\n return (\n <section {...rest} className={twMerge(\"flex flex-col\", className)}>\n {(title || description) && (\n <div className=\"flex flex-col gap-1 mb-6\">\n {typeof title === \"string\" ? (\n <Heading tag=\"h3\" size=\"sm\">\n {title}\n </Heading>\n ) : (\n title\n )}\n {description ? <Description size=\"lg\">{description}</Description> : null}\n </div>\n )}\n <div className=\"flex flex-col gap-6\">{children}</div>\n {showDivider && <hr className=\"mt-2 border-border-muted\" />}\n </section>\n );\n}\n\nexport function FormDivider() {\n return <hr className=\"border-border-muted\" />;\n}\n","import { twMerge } from \"tailwind-merge\";\nimport { Icon } from \"@/components/Icon\";\n\nexport interface Step {\n id: string;\n title: string;\n description?: string;\n}\n\nexport interface FormStepperProps {\n steps: Step[];\n currentStepId: string;\n onStepClick?: (id: string) => void;\n className?: string;\n}\n\nexport function FormStepper({ steps, currentStepId, onStepClick, className }: FormStepperProps) {\n const currentIndex = steps.findIndex((s) => s.id === currentStepId);\n\n return (\n <nav aria-label=\"Progress\" className={twMerge(\"w-full\", className)}>\n <div className=\"relative mb-12\">\n {/* Steps container with known structure */}\n <ol className=\"relative flex items-start justify-between\">\n {steps.map((step, index) => {\n const isActive = step.id === currentStepId;\n const isCompleted = index < currentIndex;\n const isClickable = onStepClick && (isCompleted || isActive);\n\n return (\n <li\n key={step.id}\n className=\"relative flex flex-col items-center\"\n style={{ flex: `1 1 ${100 / steps.length}%` }}\n >\n {/* Step Circle */}\n <button\n type=\"button\"\n disabled={!isClickable}\n onClick={() => isClickable && onStepClick?.(step.id)}\n className={twMerge(\n \"relative z-10 flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-full border-2 transition-colors bg-background-body\",\n isCompleted &&\n \"border-action-primary bg-action-primary text-text-inverse hover:bg-action-primary/90\",\n isActive && \"border-action-primary bg-background-body text-action-primary\",\n !isCompleted && !isActive && \"border-border-default bg-background-body text-text-secondary\",\n isClickable && \"cursor-pointer\",\n !isClickable && \"cursor-default\"\n )}\n aria-current={isActive ? \"step\" : undefined}\n >\n {isCompleted ? (\n <Icon name=\"Check\" size={20} weight=\"bold\" />\n ) : (\n <span className=\"text-sm font-semibold\">{index + 1}</span>\n )}\n </button>\n\n {/* Connecting line to next step - rendered inside the step item */}\n {index < steps.length - 1 && (\n <div\n className=\"absolute top-5 h-0.5 transition-colors\"\n style={{\n left: \"50%\",\n width: \"100%\",\n marginLeft: \"20px\",\n backgroundColor:\n index < currentIndex ? \"var(--color-action-primary)\" : \"var(--color-border-default)\",\n }}\n />\n )}\n\n {/* Step Label */}\n <div className=\"mt-3 flex flex-col items-center text-center w-32\">\n <span\n className={twMerge(\n \"text-sm font-medium\",\n isActive && \"text-text-default\",\n isCompleted && \"text-text-primary\",\n !isActive && !isCompleted && \"text-text-secondary\"\n )}\n >\n {step.title}\n </span>\n {step.description && <span className=\"mt-1 text-xs text-text-secondary\">{step.description}</span>}\n </div>\n </li>\n );\n })}\n </ol>\n </div>\n </nav>\n );\n}\n","import { twMerge } from \"tailwind-merge\";\nimport { Button } from \"@/components/Button\";\n\nexport interface SaveBarProps {\n formId?: string;\n show: boolean;\n isSubmitting?: boolean;\n onCancel?: () => void;\n primaryLabel?: string;\n secondaryLabel?: string;\n className?: string;\n}\n\nexport function SaveBar({\n formId,\n show,\n isSubmitting,\n onCancel,\n primaryLabel = \"Save changes\",\n secondaryLabel = \"Cancel\",\n className,\n}: SaveBarProps) {\n if (!show) return null;\n\n return (\n <div\n className={twMerge(\n \"fixed inset-x-0 bottom-0 z-40 border-t border-border-muted bg-background-surface/95 backdrop-blur supports-[backdrop-filter]:bg-background-surface/70\",\n className\n )}\n >\n <div className=\"mx-auto flex max-w-screen-lg items-center justify-between gap-3 p-3\">\n <div className=\"text-sm text-text-secondary\">You have unsaved changes</div>\n <div className=\"flex gap-2\">\n <Button variant=\"secondary\" onPress={onCancel}>\n {secondaryLabel}\n </Button>\n <Button type=\"submit\" form={formId} isDisabled={!!isSubmitting}>\n {isSubmitting ? \"Saving...\" : primaryLabel}\n </Button>\n </div>\n </div>\n </div>\n );\n}\n","import * as React from \"react\";\n\nexport interface UnsavedChangesPromptProps {\n when: boolean;\n message?: string;\n}\n\nexport function UnsavedChangesPrompt({\n when,\n message = \"You have unsaved changes. Leave anyway?\",\n}: UnsavedChangesPromptProps) {\n React.useEffect(() => {\n if (!when) return;\n const handler = (e: BeforeUnloadEvent) => {\n e.preventDefault();\n e.returnValue = message;\n return message;\n };\n window.addEventListener(\"beforeunload\", handler);\n return () => window.removeEventListener(\"beforeunload\", handler);\n }, [when, message]);\n\n return null;\n}\n","import * as React from \"react\";\n\nexport interface WizardStep {\n id: string;\n title: string;\n description?: string;\n}\n\nexport interface UseWizardOptions {\n steps: WizardStep[];\n initialStepId?: string;\n canNavigate?: (fromId: string, toId: string) => Promise<boolean> | boolean;\n}\n\nexport function useWizard({ steps, initialStepId, canNavigate }: UseWizardOptions) {\n if (steps.length === 0) {\n throw new Error(\"useWizard: steps array cannot be empty\");\n }\n\n const [currentStepId, setCurrentStepId] = React.useState<string>(initialStepId || steps[0].id);\n\n const stepIndex = steps.findIndex((s) => s.id === currentStepId);\n const hasPrev = stepIndex > 0;\n const hasNext = stepIndex < steps.length - 1;\n\n const goTo = async (id: string) => {\n if (id === currentStepId) return true;\n if (canNavigate) {\n const ok = await canNavigate(currentStepId, id);\n if (!ok) return false;\n }\n setCurrentStepId(id);\n return true;\n };\n\n const next = async () => {\n if (!hasNext || stepIndex === -1) return false;\n return goTo(steps[stepIndex + 1].id);\n };\n\n const prev = async () => {\n if (!hasPrev || stepIndex === -1) return false;\n return goTo(steps[stepIndex - 1].id);\n };\n\n return {\n steps,\n currentStepId,\n setCurrentStepId: goTo,\n next,\n prev,\n hasNext,\n hasPrev,\n stepIndex,\n };\n}\n"]}