@fabio.caffarello/react-design-system 3.13.0 → 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/granular/ui/components/Autocomplete/Autocomplete.js +116 -88
- package/dist/granular/ui/components/Autocomplete/Autocomplete.js.map +1 -1
- package/dist/granular/ui/components/Autocomplete/AutocompleteList.js +57 -47
- package/dist/granular/ui/components/Autocomplete/AutocompleteList.js.map +1 -1
- package/dist/granular/ui/components/Autocomplete/AutocompleteOption.js +21 -20
- package/dist/granular/ui/components/Autocomplete/AutocompleteOption.js.map +1 -1
- package/dist/granular/ui/components/Breadcrumb/Breadcrumb.js.map +1 -1
- package/dist/granular/ui/components/ColorPicker/ColorPicker.js.map +1 -1
- package/dist/granular/ui/components/CommandPalette/CommandPalette.js +187 -149
- package/dist/granular/ui/components/CommandPalette/CommandPalette.js.map +1 -1
- package/dist/granular/ui/components/DataGrid/DataGrid.js +92 -92
- package/dist/granular/ui/components/DataGrid/DataGrid.js.map +1 -1
- package/dist/granular/ui/components/DatePicker/DatePickerCalendar.js +154 -139
- package/dist/granular/ui/components/DatePicker/DatePickerCalendar.js.map +1 -1
- package/dist/granular/ui/components/Dialog/AlertDialog.js +73 -40
- package/dist/granular/ui/components/Dialog/AlertDialog.js.map +1 -1
- package/dist/granular/ui/components/Dialog/DialogContent.js +54 -48
- package/dist/granular/ui/components/Dialog/DialogContent.js.map +1 -1
- package/dist/granular/ui/components/Dialog/DialogDescription.js +31 -31
- package/dist/granular/ui/components/Dialog/DialogDescription.js.map +1 -1
- package/dist/granular/ui/components/Dialog/DialogTitle.js +30 -30
- package/dist/granular/ui/components/Dialog/DialogTitle.js.map +1 -1
- package/dist/granular/ui/components/Drawer/Drawer.js.map +1 -1
- package/dist/granular/ui/components/Dropdown/Dropdown.js.map +1 -1
- package/dist/granular/ui/components/EmptyState/EmptyState.js.map +1 -1
- package/dist/granular/ui/components/FileUpload/FileUpload.js.map +1 -1
- package/dist/granular/ui/components/Form/Form.js +38 -37
- package/dist/granular/ui/components/Form/Form.js.map +1 -1
- package/dist/granular/ui/components/Form/FormField.js +28 -26
- package/dist/granular/ui/components/Form/FormField.js.map +1 -1
- package/dist/granular/ui/components/Header/Header.js.map +1 -1
- package/dist/granular/ui/components/Header/components/HeaderActions.js.map +1 -1
- package/dist/granular/ui/components/Header/components/HeaderHamburger.js.map +1 -1
- package/dist/granular/ui/components/Header/components/HeaderLogo.js.map +1 -1
- package/dist/granular/ui/components/Header/components/HeaderMobileMenu.js.map +1 -1
- package/dist/granular/ui/components/Header/components/HeaderNavigation.js.map +1 -1
- package/dist/granular/ui/components/Header/contexts/HeaderContext.js.map +1 -1
- package/dist/granular/ui/components/Menu/Menu.js.map +1 -1
- package/dist/granular/ui/components/Modal/Modal.js +98 -86
- package/dist/granular/ui/components/Modal/Modal.js.map +1 -1
- package/dist/granular/ui/components/MultiSelect/MultiSelect.js +122 -106
- package/dist/granular/ui/components/MultiSelect/MultiSelect.js.map +1 -1
- package/dist/granular/ui/components/Navigation/Navigation.js.map +1 -1
- package/dist/granular/ui/components/PageHeader/PageHeader.js.map +1 -1
- package/dist/granular/ui/components/Pagination/Pagination.js.map +1 -1
- package/dist/granular/ui/components/Popover/Popover.js.map +1 -1
- package/dist/granular/ui/components/Rating/Rating.js.map +1 -1
- package/dist/granular/ui/components/SearchInput/SearchInput.js.map +1 -1
- package/dist/granular/ui/components/SideNavbar/components/Navbar/NavbarGroup.js +82 -64
- package/dist/granular/ui/components/SideNavbar/components/Navbar/NavbarGroup.js.map +1 -1
- package/dist/granular/ui/components/SideNavbar/components/Navbar/NavbarItem.js +30 -29
- package/dist/granular/ui/components/SideNavbar/components/Navbar/NavbarItem.js.map +1 -1
- package/dist/granular/ui/components/SideNavbar/components/SideNavbarResizeHandle.js +37 -35
- package/dist/granular/ui/components/SideNavbar/components/SideNavbarResizeHandle.js.map +1 -1
- package/dist/granular/ui/components/SideNavbar/providers/SideNavbarStateProvider.js +57 -57
- package/dist/granular/ui/components/SideNavbar/providers/SideNavbarStateProvider.js.map +1 -1
- package/dist/granular/ui/components/Stepper/Stepper.js +102 -94
- package/dist/granular/ui/components/Stepper/Stepper.js.map +1 -1
- package/dist/granular/ui/components/Table/Table.js +41 -35
- package/dist/granular/ui/components/Table/Table.js.map +1 -1
- package/dist/granular/ui/components/Table/TableActions/TableActions.js.map +1 -1
- package/dist/granular/ui/components/Table/TableFilters/TableFilters.js +49 -46
- package/dist/granular/ui/components/Table/TableFilters/TableFilters.js.map +1 -1
- package/dist/granular/ui/components/Table/TablePagination/TablePagination.js.map +1 -1
- package/dist/granular/ui/components/Table/TableProvider.js +82 -80
- package/dist/granular/ui/components/Table/TableProvider.js.map +1 -1
- package/dist/granular/ui/components/Table/TableRow.js +57 -53
- package/dist/granular/ui/components/Table/TableRow.js.map +1 -1
- package/dist/granular/ui/components/Table/useColumnResizing.js +53 -53
- package/dist/granular/ui/components/Table/useColumnResizing.js.map +1 -1
- package/dist/granular/ui/components/TimePicker/TimePicker.js +149 -103
- package/dist/granular/ui/components/TimePicker/TimePicker.js.map +1 -1
- package/dist/granular/ui/components/Timeline/Timeline.js.map +1 -1
- package/dist/granular/ui/hooks/useFocusRestore.js +14 -15
- package/dist/granular/ui/hooks/useFocusRestore.js.map +1 -1
- package/dist/granular/ui/primitives/Badge/Badge.js.map +1 -1
- package/dist/granular/ui/primitives/Button/Button.js +86 -104
- package/dist/granular/ui/primitives/Button/Button.js.map +1 -1
- package/dist/granular/ui/primitives/Checkbox/Checkbox.js.map +1 -1
- package/dist/granular/ui/primitives/Chip/Chip.js +91 -71
- package/dist/granular/ui/primitives/Chip/Chip.js.map +1 -1
- package/dist/granular/ui/primitives/ErrorMessage/ErrorMessage.js.map +1 -1
- package/dist/granular/ui/primitives/Input/Input.js.map +1 -1
- package/dist/granular/ui/primitives/Label/Label.js.map +1 -1
- package/dist/granular/ui/primitives/NavLink/NavLink.js.map +1 -1
- package/dist/granular/ui/primitives/Radio/Radio.js.map +1 -1
- package/dist/granular/ui/primitives/Select/Select.js.map +1 -1
- package/dist/granular/ui/primitives/Separator/Separator.js.map +1 -1
- package/dist/granular/ui/primitives/Skeleton/Skeleton.js.map +1 -1
- package/dist/granular/ui/primitives/Slider/Slider.js.map +1 -1
- package/dist/granular/ui/primitives/Spinner/Spinner.js.map +1 -1
- package/dist/granular/ui/primitives/Switch/Switch.js.map +1 -1
- package/dist/granular/ui/primitives/Tooltip/Tooltip.js.map +1 -1
- package/dist/granular/ui/providers/DialogContext.js.map +1 -1
- package/dist/granular/ui/providers/DialogProvider.js +24 -20
- package/dist/granular/ui/providers/DialogProvider.js.map +1 -1
- package/dist/index.cjs +144 -144
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +5896 -5609
- package/dist/index.js.map +1 -1
- package/dist/react-design-system.css +1 -1
- package/dist/server/index.cjs +13 -13
- package/dist/server/index.cjs.map +1 -1
- package/dist/server/index.js +1050 -789
- package/dist/server/index.js.map +1 -1
- package/dist/ui/components/Autocomplete/Autocomplete.d.ts +21 -0
- package/dist/ui/components/Autocomplete/AutocompleteList.d.ts +4 -0
- package/dist/ui/components/Autocomplete/AutocompleteOption.d.ts +8 -0
- package/dist/ui/components/Breadcrumb/Breadcrumb.d.ts +0 -1
- package/dist/ui/components/ColorPicker/ColorPicker.d.ts +0 -1
- package/dist/ui/components/CommandPalette/CommandPalette.d.ts +0 -1
- package/dist/ui/components/DataGrid/DataGrid.d.ts +0 -1
- package/dist/ui/components/Dialog/DialogContent.d.ts +20 -1
- package/dist/ui/components/Drawer/Drawer.d.ts +0 -1
- package/dist/ui/components/Dropdown/Dropdown.d.ts +0 -1
- package/dist/ui/components/EmptyState/EmptyState.d.ts +0 -1
- package/dist/ui/components/FileUpload/FileUpload.d.ts +0 -1
- package/dist/ui/components/Form/FormField.d.ts +7 -0
- package/dist/ui/components/Header/Header.d.ts +1 -1
- package/dist/ui/components/Header/components/HeaderActions.d.ts +1 -1
- package/dist/ui/components/Header/components/HeaderHamburger.d.ts +1 -1
- package/dist/ui/components/Header/components/HeaderLogo.d.ts +1 -1
- package/dist/ui/components/Header/components/HeaderMobileMenu.d.ts +1 -1
- package/dist/ui/components/Header/components/HeaderNavigation.d.ts +1 -1
- package/dist/ui/components/Header/contexts/HeaderContext.d.ts +1 -1
- package/dist/ui/components/Menu/Menu.d.ts +0 -1
- package/dist/ui/components/Modal/Modal.d.ts +1 -2
- package/dist/ui/components/Navigation/Navigation.d.ts +1 -1
- package/dist/ui/components/PageHeader/PageHeader.d.ts +1 -1
- package/dist/ui/components/Pagination/Pagination.d.ts +0 -1
- package/dist/ui/components/Popover/Popover.d.ts +0 -1
- package/dist/ui/components/Rating/Rating.d.ts +0 -1
- package/dist/ui/components/SearchInput/SearchInput.d.ts +0 -1
- package/dist/ui/components/Stepper/Stepper.d.ts +0 -1
- package/dist/ui/components/Table/TableActions/TableActions.d.ts +0 -1
- package/dist/ui/components/Table/TableFilters/TableFilters.d.ts +0 -1
- package/dist/ui/components/Table/TablePagination/TablePagination.d.ts +0 -1
- package/dist/ui/components/TimePicker/TimePicker.d.ts +0 -1
- package/dist/ui/components/Timeline/Timeline.d.ts +0 -1
- package/dist/ui/primitives/Checkbox/Checkbox.d.ts +0 -1
- package/dist/ui/primitives/Chip/Chip.d.ts +21 -0
- package/dist/ui/primitives/ErrorMessage/ErrorMessage.d.ts +0 -1
- package/dist/ui/primitives/Input/Input.d.ts +0 -1
- package/dist/ui/primitives/Label/Label.d.ts +0 -1
- package/dist/ui/primitives/NavLink/NavLink.d.ts +1 -1
- package/dist/ui/primitives/Radio/Radio.d.ts +0 -1
- package/dist/ui/primitives/Select/Select.d.ts +0 -1
- package/dist/ui/primitives/Skeleton/Skeleton.d.ts +0 -1
- package/dist/ui/primitives/Slider/Slider.d.ts +0 -1
- package/dist/ui/primitives/Switch/Switch.d.ts +0 -1
- package/dist/ui/primitives/Tooltip/Tooltip.d.ts +0 -1
- package/dist/ui/providers/DialogContext.d.ts +8 -0
- package/dist/ui/server.d.ts +2 -0
- package/package.json +7 -7
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Dropdown.js","sources":["../../../../../src/ui/components/Dropdown/Dropdown.tsx"],"sourcesContent":["\"use client\";\n\nimport type { HTMLAttributes, ReactNode, KeyboardEvent } from \"react\";\nimport React, { useState, useRef, useEffect, useId } from \"react\";\nimport { cn, mergeRefs } from \"../../utils\";\nimport {\n getRadiusClass,\n getSpacingClass,\n getTypographySize,\n getShadowClass,\n} from \"../../tokens\";\n\nexport interface DropdownItem {\n label: string;\n onClick: () => void;\n disabled?: boolean;\n variant?: \"default\" | \"danger\";\n}\n\n/**\n * Shape of the props the trigger element accepts when cloned. Limits\n * what cloneElement is allowed to override and what `props.ref` is\n * permitted to be — both essential for React 19's tighter\n * ReactElement<unknown> typing.\n */\ntype TriggerChildProps = {\n onClick?: (e: React.MouseEvent) => void;\n onKeyDown?: (e: React.KeyboardEvent) => void;\n \"aria-label\"?: string;\n \"aria-haspopup\"?: React.AriaAttributes[\"aria-haspopup\"];\n \"aria-expanded\"?: React.AriaAttributes[\"aria-expanded\"];\n \"aria-controls\"?: React.AriaAttributes[\"aria-controls\"];\n id?: string;\n ref?: React.Ref<HTMLElement>;\n};\n\nexport interface DropdownProps extends HTMLAttributes<HTMLDivElement> {\n trigger: ReactNode;\n items: DropdownItem[];\n align?: \"left\" | \"right\";\n variant?: \"default\" | \"minimal\";\n \"aria-label\"?: string;\n}\n\n/**\n * Dropdown Component\n *\n * A dropdown menu component for displaying actions and options.\n * Follows Atomic Design principles as a Molecule component.\n *\n * @example\n * ```tsx\n * <Dropdown\n * trigger={<Button>Actions</Button>}\n * items={[\n * { label: \"Edit\", onClick: () => handleEdit() },\n * { label: \"Delete\", onClick: () => handleDelete(), variant: \"danger\" },\n * ]}\n * />\n * ```\n */\nexport default function Dropdown({\n trigger,\n items,\n align = \"right\",\n variant: _variant = \"default\",\n className = \"\",\n \"aria-label\": ariaLabel,\n ...props\n}: DropdownProps) {\n const [isOpen, setIsOpen] = useState(false);\n const [activeIndex, setActiveIndex] = useState<number>(-1);\n const dropdownRef = useRef<HTMLDivElement>(null);\n const triggerRef = useRef<HTMLElement | null>(null);\n const menuRef = useRef<HTMLDivElement>(null);\n const itemRefs = useRef<(HTMLButtonElement | null)[]>([]);\n\n // Stable per-instance IDs. Math.random() at the call site regenerated\n // both IDs on every render, so aria-controls / aria-labelledby (which\n // pair the trigger with the menu) silently desynced across renders.\n // useId is SSR-safe and stable per component instance.\n const reactId = useId();\n const menuId = `dropdown-menu-${reactId}`;\n const triggerId = `dropdown-trigger-${reactId}`;\n\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (\n dropdownRef.current &&\n !dropdownRef.current.contains(event.target as Node)\n ) {\n setIsOpen(false);\n setActiveIndex(-1);\n }\n };\n\n if (isOpen) {\n document.addEventListener(\"mousedown\", handleClickOutside);\n // Focus first item when opening\n setTimeout(() => {\n const firstEnabledIndex = items.findIndex((item) => !item.disabled);\n if (firstEnabledIndex >= 0) {\n setActiveIndex(firstEnabledIndex);\n itemRefs.current[firstEnabledIndex]?.focus();\n }\n }, 0);\n }\n\n return () => {\n document.removeEventListener(\"mousedown\", handleClickOutside);\n };\n }, [isOpen, items]);\n\n // Keyboard navigation\n useEffect(() => {\n if (!isOpen) return;\n\n const handleKeyDown = (e: KeyboardEvent<HTMLDivElement>) => {\n const enabledItems = items\n .map((item, index) => ({ item, index }))\n .filter(({ item }) => !item.disabled);\n const currentEnabledIndex = enabledItems.findIndex(\n ({ index }) => index === activeIndex,\n );\n\n switch (e.key) {\n case \"ArrowDown\": {\n e.preventDefault();\n const nextIndex =\n currentEnabledIndex < enabledItems.length - 1\n ? enabledItems[currentEnabledIndex + 1].index\n : enabledItems[0].index;\n setActiveIndex(nextIndex);\n itemRefs.current[nextIndex]?.focus();\n break;\n }\n case \"ArrowUp\": {\n e.preventDefault();\n const prevIndex =\n currentEnabledIndex > 0\n ? enabledItems[currentEnabledIndex - 1].index\n : enabledItems[enabledItems.length - 1].index;\n setActiveIndex(prevIndex);\n itemRefs.current[prevIndex]?.focus();\n break;\n }\n case \"Home\": {\n e.preventDefault();\n const firstIndex = enabledItems[0].index;\n setActiveIndex(firstIndex);\n itemRefs.current[firstIndex]?.focus();\n break;\n }\n case \"End\": {\n e.preventDefault();\n const lastIndex = enabledItems[enabledItems.length - 1].index;\n setActiveIndex(lastIndex);\n itemRefs.current[lastIndex]?.focus();\n break;\n }\n case \"Enter\":\n case \" \":\n e.preventDefault();\n if (activeIndex >= 0 && !items[activeIndex].disabled) {\n handleItemClick(items[activeIndex]);\n }\n break;\n case \"Escape\":\n e.preventDefault();\n setIsOpen(false);\n setActiveIndex(-1);\n // Restore focus to trigger after closing\n setTimeout(() => {\n triggerRef.current?.focus();\n }, 0);\n break;\n }\n };\n\n const menuElement = menuRef.current;\n if (menuElement) {\n const typedHandleKeyDown = handleKeyDown as unknown as (e: Event) => void;\n menuElement.addEventListener(\"keydown\", typedHandleKeyDown);\n return () => {\n menuElement.removeEventListener(\"keydown\", typedHandleKeyDown);\n };\n }\n }, [isOpen, activeIndex, items]);\n\n const handleItemClick = (item: DropdownItem) => {\n if (!item.disabled) {\n item.onClick();\n setIsOpen(false);\n setActiveIndex(-1);\n // Restore focus to trigger after item selection\n setTimeout(() => {\n triggerRef.current?.focus();\n }, 0);\n }\n };\n\n const handleTriggerClick = () => {\n setIsOpen(!isOpen);\n setActiveIndex(-1);\n };\n\n const handleTriggerKeyDown = (e: KeyboardEvent) => {\n if (e.key === \"Enter\" || e.key === \" \" || e.key === \"ArrowDown\") {\n e.preventDefault();\n setIsOpen(true);\n }\n };\n\n const alignClasses = align === \"right\" ? \"right-0\" : \"left-0\";\n\n // Clone trigger to add accessibility props. Handles both Button and\n // native elements. React 19 surfaces consumer-supplied refs via\n // `child.props.ref` (no longer on the element itself), so mergeRefs\n // composes the parent's internal triggerRef with whatever the\n // consumer attached.\n const triggerWithProps = React.isValidElement<TriggerChildProps>(trigger) ? (\n React.cloneElement(trigger, {\n onClick: (e: React.MouseEvent) => {\n handleTriggerClick();\n trigger.props.onClick?.(e);\n },\n onKeyDown: (e: React.KeyboardEvent) => {\n handleTriggerKeyDown(e);\n trigger.props.onKeyDown?.(e);\n },\n \"aria-haspopup\": \"menu\",\n \"aria-expanded\": isOpen,\n \"aria-controls\": menuId,\n \"aria-label\": ariaLabel || trigger.props[\"aria-label\"] || \"Open menu\",\n id: triggerId,\n ref: mergeRefs<HTMLElement>(triggerRef, trigger.props.ref),\n })\n ) : (\n <div\n ref={(node) => {\n // Else-branch: trigger is a plain ReactNode (string/fragment/etc),\n // so we wrap it in a div. Forward the div node into the shared\n // HTMLElement-typed triggerRef via callback (RefObject is invariant\n // — direct assignment of RefObject<HTMLElement> to a HTMLDivElement\n // ref slot does not typecheck).\n triggerRef.current = node;\n }}\n onClick={handleTriggerClick}\n onKeyDown={handleTriggerKeyDown}\n role=\"button\"\n tabIndex={0}\n aria-haspopup=\"menu\"\n aria-expanded={isOpen}\n aria-controls={menuId}\n aria-label={ariaLabel || \"Open menu\"}\n id={triggerId}\n >\n {trigger}\n </div>\n );\n\n return (\n <div\n className={cn(\"relative\", \"inline-block\", className)}\n ref={dropdownRef}\n {...props}\n >\n {triggerWithProps}\n\n {isOpen && (\n <>\n <div\n // micro-z: dropdown click-outside backdrop internal to dropdown scope\n className={cn(\"fixed\", \"inset-0\", \"z-10\")}\n onClick={() => {\n setIsOpen(false);\n setActiveIndex(-1);\n }}\n aria-hidden=\"true\"\n />\n <div\n ref={menuRef}\n id={menuId}\n className={cn(\n \"absolute\",\n // micro-z: dropdown content above its own backdrop\n \"z-20\",\n getSpacingClass(\"sm\", \"mt\"),\n \"w-48\", // Fixed width for dropdown menu - justified as layout constraint\n getRadiusClass(\"md\"),\n getShadowClass(\"lg\"),\n \"bg-surface-overlay\",\n \"ring-1\",\n \"ring-line-strong\",\n \"ring-opacity-5\",\n alignClasses,\n )}\n role=\"menu\"\n aria-orientation=\"vertical\"\n aria-labelledby={triggerId}\n aria-activedescendant={\n activeIndex >= 0 ? `${menuId}-item-${activeIndex}` : undefined\n }\n >\n <div className={cn(getSpacingClass(\"xs\", \"py\"))} role=\"none\">\n {items.map((item, index) => {\n const itemClasses = cn(\n \"block\",\n getSpacingClass(\"base\", \"px\"),\n getSpacingClass(\"xs\", \"py\"),\n getTypographySize(\"bodySmall\"),\n \"w-full\",\n \"text-left\",\n \"focus:outline-none\",\n item.disabled\n ? cn(\"text-fg-disabled\", \"cursor-not-allowed\", \"opacity-50\")\n : item.variant === \"danger\"\n ? cn(\n \"text-error-dark\",\n \"hover:bg-error-bg-emphasis\",\n \"focus:bg-error-bg-emphasis\",\n )\n : cn(\n \"text-fg-primary\",\n \"hover:bg-surface-hover\",\n \"focus:bg-surface-hover\",\n ),\n );\n\n return (\n <button\n key={index}\n id={`${menuId}-item-${index}`}\n ref={(el) => {\n itemRefs.current[index] = el;\n }}\n type=\"button\"\n className={itemClasses}\n onClick={() => handleItemClick(item)}\n disabled={item.disabled}\n role=\"menuitem\"\n aria-disabled={item.disabled}\n tabIndex={\n item.disabled ? -1 : activeIndex === index ? 0 : -1\n }\n >\n {item.label}\n </button>\n );\n })}\n </div>\n </div>\n </>\n )}\n </div>\n );\n}\n"],"names":["Dropdown","_a","_b","trigger","items","align","_variant","className","ariaLabel","props","__objRest","isOpen","setIsOpen","useState","activeIndex","setActiveIndex","dropdownRef","useRef","triggerRef","menuRef","itemRefs","reactId","useId","menuId","triggerId","useEffect","handleClickOutside","event","firstEnabledIndex","item","handleKeyDown","e","enabledItems","index","currentEnabledIndex","nextIndex","prevIndex","firstIndex","_c","lastIndex","_d","handleItemClick","menuElement","typedHandleKeyDown","handleTriggerClick","handleTriggerKeyDown","alignClasses","triggerWithProps","React","mergeRefs","jsx","node","jsxs","__spreadProps","__spreadValues","cn","Fragment","getSpacingClass","getRadiusClass","getShadowClass","itemClasses","getTypographySize","el"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Dropdown.js","sources":["../../../../../src/ui/components/Dropdown/Dropdown.tsx"],"sourcesContent":["\"use client\";\n\nimport type { HTMLAttributes, ReactNode, KeyboardEvent } from \"react\";\nimport React, { useState, useRef, useEffect, useId } from \"react\";\nimport { cn, mergeRefs } from \"../../utils\";\nimport {\n getRadiusClass,\n getSpacingClass,\n getTypographySize,\n getShadowClass,\n} from \"../../tokens\";\n\nexport interface DropdownItem {\n label: string;\n onClick: () => void;\n disabled?: boolean;\n variant?: \"default\" | \"danger\";\n}\n\n/**\n * Shape of the props the trigger element accepts when cloned. Limits\n * what cloneElement is allowed to override and what `props.ref` is\n * permitted to be — both essential for React 19's tighter\n * ReactElement<unknown> typing.\n */\ntype TriggerChildProps = {\n onClick?: (e: React.MouseEvent) => void;\n onKeyDown?: (e: React.KeyboardEvent) => void;\n \"aria-label\"?: string;\n \"aria-haspopup\"?: React.AriaAttributes[\"aria-haspopup\"];\n \"aria-expanded\"?: React.AriaAttributes[\"aria-expanded\"];\n \"aria-controls\"?: React.AriaAttributes[\"aria-controls\"];\n id?: string;\n ref?: React.Ref<HTMLElement>;\n};\n\nexport interface DropdownProps extends HTMLAttributes<HTMLDivElement> {\n trigger: ReactNode;\n items: DropdownItem[];\n align?: \"left\" | \"right\";\n variant?: \"default\" | \"minimal\";\n \"aria-label\"?: string;\n}\n\n/**\n * Dropdown Component\n *\n * A dropdown menu component for displaying actions and options.\n *\n * @example\n * ```tsx\n * <Dropdown\n * trigger={<Button>Actions</Button>}\n * items={[\n * { label: \"Edit\", onClick: () => handleEdit() },\n * { label: \"Delete\", onClick: () => handleDelete(), variant: \"danger\" },\n * ]}\n * />\n * ```\n */\nexport default function Dropdown({\n trigger,\n items,\n align = \"right\",\n variant: _variant = \"default\",\n className = \"\",\n \"aria-label\": ariaLabel,\n ...props\n}: DropdownProps) {\n const [isOpen, setIsOpen] = useState(false);\n const [activeIndex, setActiveIndex] = useState<number>(-1);\n const dropdownRef = useRef<HTMLDivElement>(null);\n const triggerRef = useRef<HTMLElement | null>(null);\n const menuRef = useRef<HTMLDivElement>(null);\n const itemRefs = useRef<(HTMLButtonElement | null)[]>([]);\n\n // Stable per-instance IDs. Math.random() at the call site regenerated\n // both IDs on every render, so aria-controls / aria-labelledby (which\n // pair the trigger with the menu) silently desynced across renders.\n // useId is SSR-safe and stable per component instance.\n const reactId = useId();\n const menuId = `dropdown-menu-${reactId}`;\n const triggerId = `dropdown-trigger-${reactId}`;\n\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (\n dropdownRef.current &&\n !dropdownRef.current.contains(event.target as Node)\n ) {\n setIsOpen(false);\n setActiveIndex(-1);\n }\n };\n\n if (isOpen) {\n document.addEventListener(\"mousedown\", handleClickOutside);\n // Focus first item when opening\n setTimeout(() => {\n const firstEnabledIndex = items.findIndex((item) => !item.disabled);\n if (firstEnabledIndex >= 0) {\n setActiveIndex(firstEnabledIndex);\n itemRefs.current[firstEnabledIndex]?.focus();\n }\n }, 0);\n }\n\n return () => {\n document.removeEventListener(\"mousedown\", handleClickOutside);\n };\n }, [isOpen, items]);\n\n // Keyboard navigation\n useEffect(() => {\n if (!isOpen) return;\n\n const handleKeyDown = (e: KeyboardEvent<HTMLDivElement>) => {\n const enabledItems = items\n .map((item, index) => ({ item, index }))\n .filter(({ item }) => !item.disabled);\n const currentEnabledIndex = enabledItems.findIndex(\n ({ index }) => index === activeIndex,\n );\n\n switch (e.key) {\n case \"ArrowDown\": {\n e.preventDefault();\n const nextIndex =\n currentEnabledIndex < enabledItems.length - 1\n ? enabledItems[currentEnabledIndex + 1].index\n : enabledItems[0].index;\n setActiveIndex(nextIndex);\n itemRefs.current[nextIndex]?.focus();\n break;\n }\n case \"ArrowUp\": {\n e.preventDefault();\n const prevIndex =\n currentEnabledIndex > 0\n ? enabledItems[currentEnabledIndex - 1].index\n : enabledItems[enabledItems.length - 1].index;\n setActiveIndex(prevIndex);\n itemRefs.current[prevIndex]?.focus();\n break;\n }\n case \"Home\": {\n e.preventDefault();\n const firstIndex = enabledItems[0].index;\n setActiveIndex(firstIndex);\n itemRefs.current[firstIndex]?.focus();\n break;\n }\n case \"End\": {\n e.preventDefault();\n const lastIndex = enabledItems[enabledItems.length - 1].index;\n setActiveIndex(lastIndex);\n itemRefs.current[lastIndex]?.focus();\n break;\n }\n case \"Enter\":\n case \" \":\n e.preventDefault();\n if (activeIndex >= 0 && !items[activeIndex].disabled) {\n handleItemClick(items[activeIndex]);\n }\n break;\n case \"Escape\":\n e.preventDefault();\n setIsOpen(false);\n setActiveIndex(-1);\n // Restore focus to trigger after closing\n setTimeout(() => {\n triggerRef.current?.focus();\n }, 0);\n break;\n }\n };\n\n const menuElement = menuRef.current;\n if (menuElement) {\n const typedHandleKeyDown = handleKeyDown as unknown as (e: Event) => void;\n menuElement.addEventListener(\"keydown\", typedHandleKeyDown);\n return () => {\n menuElement.removeEventListener(\"keydown\", typedHandleKeyDown);\n };\n }\n }, [isOpen, activeIndex, items]);\n\n const handleItemClick = (item: DropdownItem) => {\n if (!item.disabled) {\n item.onClick();\n setIsOpen(false);\n setActiveIndex(-1);\n // Restore focus to trigger after item selection\n setTimeout(() => {\n triggerRef.current?.focus();\n }, 0);\n }\n };\n\n const handleTriggerClick = () => {\n setIsOpen(!isOpen);\n setActiveIndex(-1);\n };\n\n const handleTriggerKeyDown = (e: KeyboardEvent) => {\n if (e.key === \"Enter\" || e.key === \" \" || e.key === \"ArrowDown\") {\n e.preventDefault();\n setIsOpen(true);\n }\n };\n\n const alignClasses = align === \"right\" ? \"right-0\" : \"left-0\";\n\n // Clone trigger to add accessibility props. Handles both Button and\n // native elements. React 19 surfaces consumer-supplied refs via\n // `child.props.ref` (no longer on the element itself), so mergeRefs\n // composes the parent's internal triggerRef with whatever the\n // consumer attached.\n const triggerWithProps = React.isValidElement<TriggerChildProps>(trigger) ? (\n React.cloneElement(trigger, {\n onClick: (e: React.MouseEvent) => {\n handleTriggerClick();\n trigger.props.onClick?.(e);\n },\n onKeyDown: (e: React.KeyboardEvent) => {\n handleTriggerKeyDown(e);\n trigger.props.onKeyDown?.(e);\n },\n \"aria-haspopup\": \"menu\",\n \"aria-expanded\": isOpen,\n \"aria-controls\": menuId,\n \"aria-label\": ariaLabel || trigger.props[\"aria-label\"] || \"Open menu\",\n id: triggerId,\n ref: mergeRefs<HTMLElement>(triggerRef, trigger.props.ref),\n })\n ) : (\n <div\n ref={(node) => {\n // Else-branch: trigger is a plain ReactNode (string/fragment/etc),\n // so we wrap it in a div. Forward the div node into the shared\n // HTMLElement-typed triggerRef via callback (RefObject is invariant\n // — direct assignment of RefObject<HTMLElement> to a HTMLDivElement\n // ref slot does not typecheck).\n triggerRef.current = node;\n }}\n onClick={handleTriggerClick}\n onKeyDown={handleTriggerKeyDown}\n role=\"button\"\n tabIndex={0}\n aria-haspopup=\"menu\"\n aria-expanded={isOpen}\n aria-controls={menuId}\n aria-label={ariaLabel || \"Open menu\"}\n id={triggerId}\n >\n {trigger}\n </div>\n );\n\n return (\n <div\n className={cn(\"relative\", \"inline-block\", className)}\n ref={dropdownRef}\n {...props}\n >\n {triggerWithProps}\n\n {isOpen && (\n <>\n <div\n // micro-z: dropdown click-outside backdrop internal to dropdown scope\n className={cn(\"fixed\", \"inset-0\", \"z-10\")}\n onClick={() => {\n setIsOpen(false);\n setActiveIndex(-1);\n }}\n aria-hidden=\"true\"\n />\n <div\n ref={menuRef}\n id={menuId}\n className={cn(\n \"absolute\",\n // micro-z: dropdown content above its own backdrop\n \"z-20\",\n getSpacingClass(\"sm\", \"mt\"),\n \"w-48\", // Fixed width for dropdown menu - justified as layout constraint\n getRadiusClass(\"md\"),\n getShadowClass(\"lg\"),\n \"bg-surface-overlay\",\n \"ring-1\",\n \"ring-line-strong\",\n \"ring-opacity-5\",\n alignClasses,\n )}\n role=\"menu\"\n aria-orientation=\"vertical\"\n aria-labelledby={triggerId}\n aria-activedescendant={\n activeIndex >= 0 ? `${menuId}-item-${activeIndex}` : undefined\n }\n >\n <div className={cn(getSpacingClass(\"xs\", \"py\"))} role=\"none\">\n {items.map((item, index) => {\n const itemClasses = cn(\n \"block\",\n getSpacingClass(\"base\", \"px\"),\n getSpacingClass(\"xs\", \"py\"),\n getTypographySize(\"bodySmall\"),\n \"w-full\",\n \"text-left\",\n \"focus:outline-none\",\n item.disabled\n ? cn(\"text-fg-disabled\", \"cursor-not-allowed\", \"opacity-50\")\n : item.variant === \"danger\"\n ? cn(\n \"text-error-dark\",\n \"hover:bg-error-bg-emphasis\",\n \"focus:bg-error-bg-emphasis\",\n )\n : cn(\n \"text-fg-primary\",\n \"hover:bg-surface-hover\",\n \"focus:bg-surface-hover\",\n ),\n );\n\n return (\n <button\n key={index}\n id={`${menuId}-item-${index}`}\n ref={(el) => {\n itemRefs.current[index] = el;\n }}\n type=\"button\"\n className={itemClasses}\n onClick={() => handleItemClick(item)}\n disabled={item.disabled}\n role=\"menuitem\"\n aria-disabled={item.disabled}\n tabIndex={\n item.disabled ? -1 : activeIndex === index ? 0 : -1\n }\n >\n {item.label}\n </button>\n );\n })}\n </div>\n </div>\n </>\n )}\n </div>\n );\n}\n"],"names":["Dropdown","_a","_b","trigger","items","align","_variant","className","ariaLabel","props","__objRest","isOpen","setIsOpen","useState","activeIndex","setActiveIndex","dropdownRef","useRef","triggerRef","menuRef","itemRefs","reactId","useId","menuId","triggerId","useEffect","handleClickOutside","event","firstEnabledIndex","item","handleKeyDown","e","enabledItems","index","currentEnabledIndex","nextIndex","prevIndex","firstIndex","_c","lastIndex","_d","handleItemClick","menuElement","typedHandleKeyDown","handleTriggerClick","handleTriggerKeyDown","alignClasses","triggerWithProps","React","mergeRefs","jsx","node","jsxs","__spreadProps","__spreadValues","cn","Fragment","getSpacingClass","getRadiusClass","getShadowClass","itemClasses","getTypographySize","el"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EmptyState.js","sources":["../../../../../src/ui/components/EmptyState/EmptyState.tsx"],"sourcesContent":["\"use client\";\n\nimport type { HTMLAttributes, ReactNode } from \"react\";\nimport { Button } from \"../../primitives\";\nimport { Text } from \"../../primitives\";\nimport { cn } from \"../../utils\";\nimport {\n getSpacingClass,\n getTypographySize,\n getTypographyWeightFromFontWeight,\n} from \"../../tokens\";\n\nexport interface EmptyStateProps extends HTMLAttributes<HTMLDivElement> {\n title: string;\n message: string;\n actionLabel?: string;\n onAction?: () => void;\n illustration?: ReactNode;\n variant?: \"default\" | \"withAction\" | \"withIllustration\";\n}\n\n/**\n * EmptyState Component\n *\n * A component for displaying empty states when there's no content to show.\n
|
|
1
|
+
{"version":3,"file":"EmptyState.js","sources":["../../../../../src/ui/components/EmptyState/EmptyState.tsx"],"sourcesContent":["\"use client\";\n\nimport type { HTMLAttributes, ReactNode } from \"react\";\nimport { Button } from \"../../primitives\";\nimport { Text } from \"../../primitives\";\nimport { cn } from \"../../utils\";\nimport {\n getSpacingClass,\n getTypographySize,\n getTypographyWeightFromFontWeight,\n} from \"../../tokens\";\n\nexport interface EmptyStateProps extends HTMLAttributes<HTMLDivElement> {\n title: string;\n message: string;\n actionLabel?: string;\n onAction?: () => void;\n illustration?: ReactNode;\n variant?: \"default\" | \"withAction\" | \"withIllustration\";\n}\n\n/**\n * EmptyState Component\n *\n * A component for displaying empty states when there's no content to show.\n *\n * @example\n * ```tsx\n * <EmptyState\n * title=\"No epics yet\"\n * message=\"Get started by creating your first epic\"\n * actionLabel=\"Create Epic\"\n * onAction={() => router.push('/epics/new')}\n * />\n * ```\n */\nexport default function EmptyState({\n title,\n message,\n actionLabel,\n onAction,\n illustration,\n variant = \"default\",\n className = \"\",\n ...props\n}: EmptyStateProps) {\n const classes = cn(\n \"flex\",\n \"flex-col\",\n \"items-center\",\n \"justify-center\",\n \"text-center\",\n getSpacingClass(\"xl\", \"py\"),\n getSpacingClass(\"base\", \"px\"),\n className,\n );\n\n const showAction = variant === \"withAction\" || (actionLabel && onAction);\n const showIllustration = variant === \"withIllustration\" || illustration;\n\n return (\n <div\n className={classes}\n role=\"status\"\n aria-live=\"polite\"\n aria-label={`${title}. ${message}`}\n {...props}\n >\n {showIllustration && illustration && (\n <div className={cn(getSpacingClass(\"base\", \"mb\"))} aria-hidden=\"true\">\n {illustration}\n </div>\n )}\n\n <Text\n as=\"h3\"\n className={cn(\n getTypographySize(\"h4\"),\n getTypographyWeightFromFontWeight(\"semibold\"),\n \"text-fg-primary\",\n getSpacingClass(\"sm\", \"mb\"),\n )}\n >\n {title}\n </Text>\n\n <Text\n as=\"p\"\n className={cn(\n getTypographySize(\"bodySmall\"),\n \"text-fg-secondary\",\n getSpacingClass(\"md\", \"mb\"),\n \"max-w-sm\", // Max width utility - justified as layout constraint\n )}\n >\n {message}\n </Text>\n\n {showAction && actionLabel && onAction && (\n <Button variant=\"primary\" onClick={onAction}>\n {actionLabel}\n </Button>\n )}\n </div>\n );\n}\n"],"names":["EmptyState","_a","_b","title","message","actionLabel","onAction","illustration","variant","className","props","__objRest","classes","cn","getSpacingClass","showAction","showIllustration","jsxs","__spreadProps","__spreadValues","jsx","Text","getTypographySize","getTypographyWeightFromFontWeight","Button"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoCA,SAAwBA,EAAWC,GASf;AATe,MAAAC,IAAAD,GACjC;AAAA,WAAAE;AAAA,IACA,SAAAC;AAAA,IACA,aAAAC;AAAA,IACA,UAAAC;AAAA,IACA,cAAAC;AAAA,IACA,SAAAC,IAAU;AAAA,IACV,WAAAC,IAAY;AAAA,MAPqBP,GAQ9BQ,IAAAC,EAR8BT,GAQ9B;AAAA,IAPH;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAGA,QAAMU,IAAUC;AAAA,IACd;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACAC,EAAgB,MAAM,IAAI;AAAA,IAC1BA,EAAgB,QAAQ,IAAI;AAAA,IAC5BL;AAAA,EAAA,GAGIM,IAAaP,MAAY,gBAAiBH,KAAeC,GACzDU,IAAmBR,MAAY,sBAAsBD;AAE3D,SACE,gBAAAU;AAAA,IAAC;AAAA,IAAAC,EAAAC,EAAA;AAAA,MACC,WAAWP;AAAA,MACX,MAAK;AAAA,MACL,aAAU;AAAA,MACV,cAAY,GAAGT,CAAK,KAAKC,CAAO;AAAA,OAC5BM,IALL;AAAA,MAOE,UAAA;AAAA,QAAAM,KAAoBT,KACnB,gBAAAa,EAAC,OAAA,EAAI,WAAWP,EAAGC,EAAgB,QAAQ,IAAI,CAAC,GAAG,eAAY,QAC5D,UAAAP,GACH;AAAA,QAGF,gBAAAa;AAAA,UAACC;AAAA,UAAA;AAAA,YACC,IAAG;AAAA,YACH,WAAWR;AAAA,cACTS,EAAkB,IAAI;AAAA,cACtBC,EAAkC,UAAU;AAAA,cAC5C;AAAA,cACAT,EAAgB,MAAM,IAAI;AAAA,YAAA;AAAA,YAG3B,UAAAX;AAAA,UAAA;AAAA,QAAA;AAAA,QAGH,gBAAAiB;AAAA,UAACC;AAAA,UAAA;AAAA,YACC,IAAG;AAAA,YACH,WAAWR;AAAA,cACTS,EAAkB,WAAW;AAAA,cAC7B;AAAA,cACAR,EAAgB,MAAM,IAAI;AAAA,cAC1B;AAAA;AAAA,YAAA;AAAA,YAGD,UAAAV;AAAA,UAAA;AAAA,QAAA;AAAA,QAGFW,KAAcV,KAAeC,KAC5B,gBAAAc,EAACI,KAAO,SAAQ,WAAU,SAASlB,GAChC,UAAAD,EAAA,CACH;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAIR;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FileUpload.js","sources":["../../../../../src/ui/components/FileUpload/FileUpload.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState, useRef, type DragEvent, type ChangeEvent } from \"react\";\nimport { Upload, X, File, CheckCircle2, AlertCircle } from \"lucide-react\";\nimport { cn } from \"../../utils\";\nimport {\n getSpacingClass,\n getRadiusClass,\n getAnimationClass,\n getTypographySizeFromFontSize,\n getTypographyWeightFromFontWeight,\n} from \"../../tokens\";\nimport Button from \"../../primitives/Button/Button\";\nimport Progress from \"../../primitives/Progress/Progress\";\n\nexport interface FileUploadFile {\n file: File;\n id: string;\n preview?: string;\n progress?: number;\n error?: string;\n}\n\nexport interface FileUploadProps {\n accept?: string;\n multiple?: boolean;\n maxSize?: number; // in bytes\n maxFiles?: number;\n onFilesChange?: (files: FileUploadFile[]) => void;\n onFileRemove?: (fileId: string) => void;\n showPreview?: boolean;\n showProgress?: boolean;\n disabled?: boolean;\n className?: string;\n label?: string;\n description?: string;\n}\n\n/**\n * FileUpload Component\n *\n * A file upload component with drag and drop, preview, validation, and progress.\n * Follows Atomic Design principles as a Molecule component.\n *\n * @example\n * ```tsx\n * <FileUpload\n * accept=\"image/*\"\n * maxSize={5 * 1024 * 1024} // 5MB\n * onFilesChange={(files) => console.log(files)}\n * />\n * ```\n */\nexport default function FileUpload({\n accept,\n multiple = false,\n maxSize,\n maxFiles,\n onFilesChange,\n onFileRemove,\n showPreview = true,\n showProgress = false,\n disabled = false,\n className = \"\",\n label,\n description,\n}: FileUploadProps) {\n const [files, setFiles] = useState<FileUploadFile[]>([]);\n const [isDragging, setIsDragging] = useState(false);\n const fileInputRef = useRef<HTMLInputElement>(null);\n\n const formatFileSize = (bytes: number): string => {\n if (bytes === 0) return \"0 Bytes\";\n const k = 1024;\n const sizes = [\"Bytes\", \"KB\", \"MB\", \"GB\"];\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n return Math.round((bytes / Math.pow(k, i)) * 100) / 100 + \" \" + sizes[i];\n };\n\n const validateFile = (file: File): string | null => {\n if (maxSize && file.size > maxSize) {\n return `File size exceeds ${formatFileSize(maxSize)}`;\n }\n return null;\n };\n\n const processFiles = (fileList: FileList | File[]): FileUploadFile[] => {\n const fileArray = Array.from(fileList);\n const newFiles: FileUploadFile[] = [];\n\n fileArray.forEach((file) => {\n const error = validateFile(file);\n const fileId = `${Date.now()}-${Math.random().toString(36).slice(2, 11)}`;\n\n const fileUpload: FileUploadFile = {\n file,\n id: fileId,\n error: error ?? undefined,\n progress: showProgress ? 0 : undefined,\n };\n\n // Generate preview for images\n if (showPreview && file.type.startsWith(\"image/\")) {\n const reader = new FileReader();\n reader.onload = (e) => {\n setFiles((prev) =>\n prev.map((f) =>\n f.id === fileId\n ? { ...f, preview: e.target?.result as string }\n : f,\n ),\n );\n };\n reader.readAsDataURL(file);\n }\n\n newFiles.push(fileUpload);\n });\n\n return newFiles;\n };\n\n const handleFiles = (newFiles: FileUploadFile[]) => {\n const updatedFiles = multiple ? [...files, ...newFiles] : newFiles;\n const limitedFiles = maxFiles\n ? updatedFiles.slice(0, maxFiles)\n : updatedFiles;\n\n setFiles(limitedFiles);\n onFilesChange?.(limitedFiles);\n };\n\n const handleDrop = (e: DragEvent<HTMLDivElement>) => {\n e.preventDefault();\n setIsDragging(false);\n\n if (disabled) return;\n\n const droppedFiles = e.dataTransfer.files;\n if (droppedFiles.length > 0) {\n const processedFiles = processFiles(droppedFiles);\n handleFiles(processedFiles);\n }\n };\n\n const handleDragOver = (e: DragEvent<HTMLDivElement>) => {\n e.preventDefault();\n if (!disabled) {\n setIsDragging(true);\n }\n };\n\n const handleDragLeave = (e: DragEvent<HTMLDivElement>) => {\n e.preventDefault();\n setIsDragging(false);\n };\n\n const handleFileInput = (e: ChangeEvent<HTMLInputElement>) => {\n if (e.target.files && e.target.files.length > 0) {\n const processedFiles = processFiles(e.target.files);\n handleFiles(processedFiles);\n }\n // Reset input\n if (fileInputRef.current) {\n fileInputRef.current.value = \"\";\n }\n };\n\n const handleRemove = (fileId: string) => {\n const updatedFiles = files.filter((f) => f.id !== fileId);\n setFiles(updatedFiles);\n onFilesChange?.(updatedFiles);\n onFileRemove?.(fileId);\n };\n\n const handleClick = () => {\n if (!disabled) {\n fileInputRef.current?.click();\n }\n };\n\n return (\n <div\n className={cn(\n getSpacingClass(\"lg\", \"gap\"),\n \"flex\",\n \"flex-col\",\n className,\n )}\n >\n {(label || description) && (\n <div>\n {label && (\n <label\n className={cn(\n \"block\",\n getTypographySizeFromFontSize(\"sm\"),\n getTypographyWeightFromFontWeight(\"medium\"),\n \"text-fg-primary\",\n getSpacingClass(\"xs\", \"mb\"),\n )}\n >\n {label}\n </label>\n )}\n {description && (\n <p\n className={cn(\n getTypographySizeFromFontSize(\"sm\"),\n \"text-fg-secondary\",\n )}\n >\n {description}\n </p>\n )}\n </div>\n )}\n\n <div\n onDrop={handleDrop}\n onDragOver={handleDragOver}\n onDragLeave={handleDragLeave}\n onClick={handleClick}\n className={cn(\n \"relative\",\n \"border-2\",\n \"border-dashed\",\n isDragging ? \"border-line-brand\" : \"border-line-default\",\n getRadiusClass(\"lg\"),\n getSpacingClass(\"lg\", \"p\"),\n \"text-center\",\n \"cursor-pointer\",\n getAnimationClass(\"base\"),\n \"focus:border-line-focus\",\n disabled\n ? \"opacity-50 cursor-not-allowed\"\n : cn(\n \"hover:border-line-strong\",\n \"focus:outline-none\",\n \"focus:ring-2\",\n \"focus:ring-offset-2\",\n ),\n )}\n role=\"button\"\n tabIndex={disabled ? -1 : 0}\n aria-label=\"Upload files\"\n aria-disabled={disabled}\n >\n <input\n ref={fileInputRef}\n type=\"file\"\n accept={accept}\n multiple={multiple}\n onChange={handleFileInput}\n disabled={disabled}\n className=\"hidden\"\n />\n\n <div\n className={cn(\n \"flex\",\n \"flex-col\",\n \"items-center\",\n getSpacingClass(\"sm\", \"gap\"),\n )}\n >\n <Upload\n className={cn(\n \"h-8\",\n \"w-8\",\n isDragging ? \"text-fg-brand\" : \"text-fg-secondary\",\n )}\n />\n <div>\n <span\n className={cn(\n getTypographySizeFromFontSize(\"sm\"),\n getTypographyWeightFromFontWeight(\"medium\"),\n \"text-fg-primary\",\n )}\n >\n {isDragging\n ? \"Drop files here\"\n : \"Click to upload or drag and drop\"}\n </span>\n {accept && (\n <p\n className={cn(\n getTypographySizeFromFontSize(\"xs\"),\n \"text-fg-secondary\",\n getSpacingClass(\"xs\", \"mt\"),\n )}\n >\n Accepted: {accept}\n </p>\n )}\n {maxSize && (\n <p\n className={cn(\n getTypographySizeFromFontSize(\"xs\"),\n \"text-fg-secondary\",\n )}\n >\n Max size: {formatFileSize(maxSize)}\n </p>\n )}\n </div>\n </div>\n </div>\n\n {files.length > 0 && (\n <div className={cn(\"flex\", \"flex-col\", getSpacingClass(\"sm\", \"gap\"))}>\n {files.map((fileUpload) => (\n <div\n key={fileUpload.id}\n className={cn(\n \"flex\",\n \"items-center\",\n getSpacingClass(\"md\", \"gap\"),\n getSpacingClass(\"base\", \"p\"),\n \"border\",\n \"border-line-default\",\n getRadiusClass(\"md\"),\n fileUpload.error ? \"bg-error-bg\" : \"bg-surface-muted\",\n )}\n >\n {showPreview && fileUpload.preview ? (\n <img\n src={fileUpload.preview}\n alt={fileUpload.file.name}\n className={cn(\n \"w-12\",\n \"h-12\",\n \"object-cover\",\n getRadiusClass(\"md\"),\n )}\n />\n ) : (\n <File className={cn(\"h-8\", \"w-8\", \"text-fg-secondary\")} />\n )}\n\n <div className={cn(\"flex-1\", \"min-w-0\")}>\n <p\n className={cn(\n getTypographySizeFromFontSize(\"sm\"),\n getTypographyWeightFromFontWeight(\"medium\"),\n \"text-fg-primary\",\n \"truncate\",\n )}\n >\n {fileUpload.file.name}\n </p>\n <p\n className={cn(\n getTypographySizeFromFontSize(\"xs\"),\n \"text-fg-secondary\",\n )}\n >\n {formatFileSize(fileUpload.file.size)}\n </p>\n {fileUpload.error && (\n <div\n className={cn(\n \"flex\",\n \"items-center\",\n getSpacingClass(\"xs\", \"gap\"),\n getSpacingClass(\"xs\", \"mt\"),\n )}\n >\n <AlertCircle\n className={cn(\"h-3\", \"w-3\", \"text-fg-error\")}\n />\n <span\n className={cn(\n getTypographySizeFromFontSize(\"xs\"),\n \"text-fg-error\",\n )}\n >\n {fileUpload.error}\n </span>\n </div>\n )}\n {showProgress && fileUpload.progress !== undefined && (\n <div className={cn(getSpacingClass(\"sm\", \"mt\"))}>\n <Progress value={fileUpload.progress} size=\"sm\" />\n </div>\n )}\n </div>\n\n {!fileUpload.error && !showProgress && (\n <CheckCircle2 className={cn(\"h-5\", \"w-5\", \"text-fg-success\")} />\n )}\n\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={(e) => {\n e.stopPropagation();\n handleRemove(fileUpload.id);\n }}\n className={`h-auto ${getSpacingClass(\"xs\", \"p\")}`}\n aria-label={`Remove ${fileUpload.file.name}`}\n >\n <X className=\"h-4 w-4\" />\n </Button>\n </div>\n ))}\n </div>\n )}\n </div>\n );\n}\n"],"names":["FileUpload","accept","multiple","maxSize","maxFiles","onFilesChange","onFileRemove","showPreview","showProgress","disabled","className","label","description","files","setFiles","useState","isDragging","setIsDragging","fileInputRef","useRef","formatFileSize","bytes","k","sizes","i","validateFile","file","processFiles","fileList","fileArray","newFiles","error","fileId","fileUpload","reader","e","prev","f","__spreadProps","__spreadValues","_a","handleFiles","updatedFiles","limitedFiles","handleDrop","droppedFiles","processedFiles","handleDragOver","handleDragLeave","handleFileInput","handleRemove","handleClick","jsxs","cn","getSpacingClass","jsx","getTypographySizeFromFontSize","getTypographyWeightFromFontWeight","getRadiusClass","getAnimationClass","Upload","File","AlertCircle","Progress","CheckCircle2","Button","X"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"FileUpload.js","sources":["../../../../../src/ui/components/FileUpload/FileUpload.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState, useRef, type DragEvent, type ChangeEvent } from \"react\";\nimport { Upload, X, File, CheckCircle2, AlertCircle } from \"lucide-react\";\nimport { cn } from \"../../utils\";\nimport {\n getSpacingClass,\n getRadiusClass,\n getAnimationClass,\n getTypographySizeFromFontSize,\n getTypographyWeightFromFontWeight,\n} from \"../../tokens\";\nimport Button from \"../../primitives/Button/Button\";\nimport Progress from \"../../primitives/Progress/Progress\";\n\nexport interface FileUploadFile {\n file: File;\n id: string;\n preview?: string;\n progress?: number;\n error?: string;\n}\n\nexport interface FileUploadProps {\n accept?: string;\n multiple?: boolean;\n maxSize?: number; // in bytes\n maxFiles?: number;\n onFilesChange?: (files: FileUploadFile[]) => void;\n onFileRemove?: (fileId: string) => void;\n showPreview?: boolean;\n showProgress?: boolean;\n disabled?: boolean;\n className?: string;\n label?: string;\n description?: string;\n}\n\n/**\n * FileUpload Component\n *\n * A file upload component with drag and drop, preview, validation, and progress.\n *\n * @example\n * ```tsx\n * <FileUpload\n * accept=\"image/*\"\n * maxSize={5 * 1024 * 1024} // 5MB\n * onFilesChange={(files) => console.log(files)}\n * />\n * ```\n */\nexport default function FileUpload({\n accept,\n multiple = false,\n maxSize,\n maxFiles,\n onFilesChange,\n onFileRemove,\n showPreview = true,\n showProgress = false,\n disabled = false,\n className = \"\",\n label,\n description,\n}: FileUploadProps) {\n const [files, setFiles] = useState<FileUploadFile[]>([]);\n const [isDragging, setIsDragging] = useState(false);\n const fileInputRef = useRef<HTMLInputElement>(null);\n\n const formatFileSize = (bytes: number): string => {\n if (bytes === 0) return \"0 Bytes\";\n const k = 1024;\n const sizes = [\"Bytes\", \"KB\", \"MB\", \"GB\"];\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n return Math.round((bytes / Math.pow(k, i)) * 100) / 100 + \" \" + sizes[i];\n };\n\n const validateFile = (file: File): string | null => {\n if (maxSize && file.size > maxSize) {\n return `File size exceeds ${formatFileSize(maxSize)}`;\n }\n return null;\n };\n\n const processFiles = (fileList: FileList | File[]): FileUploadFile[] => {\n const fileArray = Array.from(fileList);\n const newFiles: FileUploadFile[] = [];\n\n fileArray.forEach((file) => {\n const error = validateFile(file);\n const fileId = `${Date.now()}-${Math.random().toString(36).slice(2, 11)}`;\n\n const fileUpload: FileUploadFile = {\n file,\n id: fileId,\n error: error ?? undefined,\n progress: showProgress ? 0 : undefined,\n };\n\n // Generate preview for images\n if (showPreview && file.type.startsWith(\"image/\")) {\n const reader = new FileReader();\n reader.onload = (e) => {\n setFiles((prev) =>\n prev.map((f) =>\n f.id === fileId\n ? { ...f, preview: e.target?.result as string }\n : f,\n ),\n );\n };\n reader.readAsDataURL(file);\n }\n\n newFiles.push(fileUpload);\n });\n\n return newFiles;\n };\n\n const handleFiles = (newFiles: FileUploadFile[]) => {\n const updatedFiles = multiple ? [...files, ...newFiles] : newFiles;\n const limitedFiles = maxFiles\n ? updatedFiles.slice(0, maxFiles)\n : updatedFiles;\n\n setFiles(limitedFiles);\n onFilesChange?.(limitedFiles);\n };\n\n const handleDrop = (e: DragEvent<HTMLDivElement>) => {\n e.preventDefault();\n setIsDragging(false);\n\n if (disabled) return;\n\n const droppedFiles = e.dataTransfer.files;\n if (droppedFiles.length > 0) {\n const processedFiles = processFiles(droppedFiles);\n handleFiles(processedFiles);\n }\n };\n\n const handleDragOver = (e: DragEvent<HTMLDivElement>) => {\n e.preventDefault();\n if (!disabled) {\n setIsDragging(true);\n }\n };\n\n const handleDragLeave = (e: DragEvent<HTMLDivElement>) => {\n e.preventDefault();\n setIsDragging(false);\n };\n\n const handleFileInput = (e: ChangeEvent<HTMLInputElement>) => {\n if (e.target.files && e.target.files.length > 0) {\n const processedFiles = processFiles(e.target.files);\n handleFiles(processedFiles);\n }\n // Reset input\n if (fileInputRef.current) {\n fileInputRef.current.value = \"\";\n }\n };\n\n const handleRemove = (fileId: string) => {\n const updatedFiles = files.filter((f) => f.id !== fileId);\n setFiles(updatedFiles);\n onFilesChange?.(updatedFiles);\n onFileRemove?.(fileId);\n };\n\n const handleClick = () => {\n if (!disabled) {\n fileInputRef.current?.click();\n }\n };\n\n return (\n <div\n className={cn(\n getSpacingClass(\"lg\", \"gap\"),\n \"flex\",\n \"flex-col\",\n className,\n )}\n >\n {(label || description) && (\n <div>\n {label && (\n <label\n className={cn(\n \"block\",\n getTypographySizeFromFontSize(\"sm\"),\n getTypographyWeightFromFontWeight(\"medium\"),\n \"text-fg-primary\",\n getSpacingClass(\"xs\", \"mb\"),\n )}\n >\n {label}\n </label>\n )}\n {description && (\n <p\n className={cn(\n getTypographySizeFromFontSize(\"sm\"),\n \"text-fg-secondary\",\n )}\n >\n {description}\n </p>\n )}\n </div>\n )}\n\n <div\n onDrop={handleDrop}\n onDragOver={handleDragOver}\n onDragLeave={handleDragLeave}\n onClick={handleClick}\n className={cn(\n \"relative\",\n \"border-2\",\n \"border-dashed\",\n isDragging ? \"border-line-brand\" : \"border-line-default\",\n getRadiusClass(\"lg\"),\n getSpacingClass(\"lg\", \"p\"),\n \"text-center\",\n \"cursor-pointer\",\n getAnimationClass(\"base\"),\n \"focus:border-line-focus\",\n disabled\n ? \"opacity-50 cursor-not-allowed\"\n : cn(\n \"hover:border-line-strong\",\n \"focus:outline-none\",\n \"focus:ring-2\",\n \"focus:ring-offset-2\",\n ),\n )}\n role=\"button\"\n tabIndex={disabled ? -1 : 0}\n aria-label=\"Upload files\"\n aria-disabled={disabled}\n >\n <input\n ref={fileInputRef}\n type=\"file\"\n accept={accept}\n multiple={multiple}\n onChange={handleFileInput}\n disabled={disabled}\n className=\"hidden\"\n />\n\n <div\n className={cn(\n \"flex\",\n \"flex-col\",\n \"items-center\",\n getSpacingClass(\"sm\", \"gap\"),\n )}\n >\n <Upload\n className={cn(\n \"h-8\",\n \"w-8\",\n isDragging ? \"text-fg-brand\" : \"text-fg-secondary\",\n )}\n />\n <div>\n <span\n className={cn(\n getTypographySizeFromFontSize(\"sm\"),\n getTypographyWeightFromFontWeight(\"medium\"),\n \"text-fg-primary\",\n )}\n >\n {isDragging\n ? \"Drop files here\"\n : \"Click to upload or drag and drop\"}\n </span>\n {accept && (\n <p\n className={cn(\n getTypographySizeFromFontSize(\"xs\"),\n \"text-fg-secondary\",\n getSpacingClass(\"xs\", \"mt\"),\n )}\n >\n Accepted: {accept}\n </p>\n )}\n {maxSize && (\n <p\n className={cn(\n getTypographySizeFromFontSize(\"xs\"),\n \"text-fg-secondary\",\n )}\n >\n Max size: {formatFileSize(maxSize)}\n </p>\n )}\n </div>\n </div>\n </div>\n\n {files.length > 0 && (\n <div className={cn(\"flex\", \"flex-col\", getSpacingClass(\"sm\", \"gap\"))}>\n {files.map((fileUpload) => (\n <div\n key={fileUpload.id}\n className={cn(\n \"flex\",\n \"items-center\",\n getSpacingClass(\"md\", \"gap\"),\n getSpacingClass(\"base\", \"p\"),\n \"border\",\n \"border-line-default\",\n getRadiusClass(\"md\"),\n fileUpload.error ? \"bg-error-bg\" : \"bg-surface-muted\",\n )}\n >\n {showPreview && fileUpload.preview ? (\n <img\n src={fileUpload.preview}\n alt={fileUpload.file.name}\n className={cn(\n \"w-12\",\n \"h-12\",\n \"object-cover\",\n getRadiusClass(\"md\"),\n )}\n />\n ) : (\n <File className={cn(\"h-8\", \"w-8\", \"text-fg-secondary\")} />\n )}\n\n <div className={cn(\"flex-1\", \"min-w-0\")}>\n <p\n className={cn(\n getTypographySizeFromFontSize(\"sm\"),\n getTypographyWeightFromFontWeight(\"medium\"),\n \"text-fg-primary\",\n \"truncate\",\n )}\n >\n {fileUpload.file.name}\n </p>\n <p\n className={cn(\n getTypographySizeFromFontSize(\"xs\"),\n \"text-fg-secondary\",\n )}\n >\n {formatFileSize(fileUpload.file.size)}\n </p>\n {fileUpload.error && (\n <div\n className={cn(\n \"flex\",\n \"items-center\",\n getSpacingClass(\"xs\", \"gap\"),\n getSpacingClass(\"xs\", \"mt\"),\n )}\n >\n <AlertCircle\n className={cn(\"h-3\", \"w-3\", \"text-fg-error\")}\n />\n <span\n className={cn(\n getTypographySizeFromFontSize(\"xs\"),\n \"text-fg-error\",\n )}\n >\n {fileUpload.error}\n </span>\n </div>\n )}\n {showProgress && fileUpload.progress !== undefined && (\n <div className={cn(getSpacingClass(\"sm\", \"mt\"))}>\n <Progress value={fileUpload.progress} size=\"sm\" />\n </div>\n )}\n </div>\n\n {!fileUpload.error && !showProgress && (\n <CheckCircle2 className={cn(\"h-5\", \"w-5\", \"text-fg-success\")} />\n )}\n\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={(e) => {\n e.stopPropagation();\n handleRemove(fileUpload.id);\n }}\n className={`h-auto ${getSpacingClass(\"xs\", \"p\")}`}\n aria-label={`Remove ${fileUpload.file.name}`}\n >\n <X className=\"h-4 w-4\" />\n </Button>\n </div>\n ))}\n </div>\n )}\n </div>\n );\n}\n"],"names":["FileUpload","accept","multiple","maxSize","maxFiles","onFilesChange","onFileRemove","showPreview","showProgress","disabled","className","label","description","files","setFiles","useState","isDragging","setIsDragging","fileInputRef","useRef","formatFileSize","bytes","k","sizes","i","validateFile","file","processFiles","fileList","fileArray","newFiles","error","fileId","fileUpload","reader","e","prev","f","__spreadProps","__spreadValues","_a","handleFiles","updatedFiles","limitedFiles","handleDrop","droppedFiles","processedFiles","handleDragOver","handleDragLeave","handleFileInput","handleRemove","handleClick","jsxs","cn","getSpacingClass","jsx","getTypographySizeFromFontSize","getTypographyWeightFromFontWeight","getRadiusClass","getAnimationClass","Upload","File","AlertCircle","Progress","CheckCircle2","Button","X"],"mappings":"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"}
|
|
@@ -3,38 +3,38 @@ var _ = Object.defineProperty, q = Object.defineProperties;
|
|
|
3
3
|
var A = Object.getOwnPropertyDescriptors;
|
|
4
4
|
var g = Object.getOwnPropertySymbols;
|
|
5
5
|
var R = Object.prototype.hasOwnProperty, j = Object.prototype.propertyIsEnumerable;
|
|
6
|
-
var P = (
|
|
7
|
-
for (var
|
|
8
|
-
R.call(
|
|
6
|
+
var P = (e, t, r) => t in e ? _(e, t, { enumerable: !0, configurable: !0, writable: !0, value: r }) : e[t] = r, k = (e, t) => {
|
|
7
|
+
for (var r in t || (t = {}))
|
|
8
|
+
R.call(t, r) && P(e, r, t[r]);
|
|
9
9
|
if (g)
|
|
10
|
-
for (var
|
|
11
|
-
j.call(
|
|
12
|
-
return r;
|
|
13
|
-
}, F = (r, o) => q(r, A(o));
|
|
14
|
-
var h = (r, o) => {
|
|
15
|
-
var e = {};
|
|
16
|
-
for (var t in r)
|
|
17
|
-
R.call(r, t) && o.indexOf(t) < 0 && (e[t] = r[t]);
|
|
18
|
-
if (r != null && g)
|
|
19
|
-
for (var t of g(r))
|
|
20
|
-
o.indexOf(t) < 0 && j.call(r, t) && (e[t] = r[t]);
|
|
10
|
+
for (var r of g(t))
|
|
11
|
+
j.call(t, r) && P(e, r, t[r]);
|
|
21
12
|
return e;
|
|
13
|
+
}, F = (e, t) => q(e, A(t));
|
|
14
|
+
var h = (e, t) => {
|
|
15
|
+
var r = {};
|
|
16
|
+
for (var o in e)
|
|
17
|
+
R.call(e, o) && t.indexOf(o) < 0 && (r[o] = e[o]);
|
|
18
|
+
if (e != null && g)
|
|
19
|
+
for (var o of g(e))
|
|
20
|
+
t.indexOf(o) < 0 && j.call(e, o) && (r[o] = e[o]);
|
|
21
|
+
return r;
|
|
22
22
|
};
|
|
23
|
-
var z = (
|
|
23
|
+
var z = (e, t, r) => new Promise((o, m) => {
|
|
24
24
|
var S = (s) => {
|
|
25
25
|
try {
|
|
26
|
-
f(
|
|
26
|
+
f(r.next(s));
|
|
27
27
|
} catch (l) {
|
|
28
28
|
m(l);
|
|
29
29
|
}
|
|
30
30
|
}, a = (s) => {
|
|
31
31
|
try {
|
|
32
|
-
f(
|
|
32
|
+
f(r.throw(s));
|
|
33
33
|
} catch (l) {
|
|
34
34
|
m(l);
|
|
35
35
|
}
|
|
36
|
-
}, f = (s) => s.done ?
|
|
37
|
-
f((
|
|
36
|
+
}, f = (s) => s.done ? o(s.value) : Promise.resolve(s.value).then(S, a);
|
|
37
|
+
f((r = r.apply(e, t)).next());
|
|
38
38
|
});
|
|
39
39
|
import { jsx as c, jsxs as C } from "react/jsx-runtime";
|
|
40
40
|
import { FormProvider as B } from "./FormProvider.js";
|
|
@@ -44,10 +44,10 @@ import { getRadiusClass as p } from "../../tokens/radius.js";
|
|
|
44
44
|
import { getTypographySizeFromFontSize as x } from "../../tokens/typography.js";
|
|
45
45
|
function X(f) {
|
|
46
46
|
var s = f, {
|
|
47
|
-
children:
|
|
48
|
-
onSubmit:
|
|
49
|
-
loading:
|
|
50
|
-
error:
|
|
47
|
+
children: e,
|
|
48
|
+
onSubmit: t,
|
|
49
|
+
loading: r = !1,
|
|
50
|
+
error: o = null,
|
|
51
51
|
success: m = null,
|
|
52
52
|
className: S = ""
|
|
53
53
|
} = s, a = h(s, [
|
|
@@ -75,17 +75,18 @@ function X(f) {
|
|
|
75
75
|
"onSubmitError"
|
|
76
76
|
]), w = i.handleSubmit(
|
|
77
77
|
(v) => z(null, null, function* () {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
78
|
+
if (!r)
|
|
79
|
+
try {
|
|
80
|
+
yield H(v);
|
|
81
|
+
} catch (T) {
|
|
82
|
+
d == null || d(T);
|
|
83
|
+
}
|
|
83
84
|
}),
|
|
84
85
|
(v) => {
|
|
85
86
|
d == null || d(v);
|
|
86
87
|
}
|
|
87
88
|
);
|
|
88
|
-
return /* @__PURE__ */ c(B, { form: i, loading:
|
|
89
|
+
return /* @__PURE__ */ c(B, { form: i, loading: r, children: /* @__PURE__ */ C(
|
|
89
90
|
"form",
|
|
90
91
|
F(k({
|
|
91
92
|
className: l,
|
|
@@ -93,8 +94,8 @@ function X(f) {
|
|
|
93
94
|
noValidate: !0
|
|
94
95
|
}, V), {
|
|
95
96
|
children: [
|
|
96
|
-
|
|
97
|
-
|
|
97
|
+
e,
|
|
98
|
+
o && /* @__PURE__ */ c(
|
|
98
99
|
"div",
|
|
99
100
|
{
|
|
100
101
|
role: "alert",
|
|
@@ -107,7 +108,7 @@ function X(f) {
|
|
|
107
108
|
"border-error",
|
|
108
109
|
p("md")
|
|
109
110
|
),
|
|
110
|
-
children:
|
|
111
|
+
children: o
|
|
111
112
|
}
|
|
112
113
|
),
|
|
113
114
|
m && /* @__PURE__ */ c(
|
|
@@ -130,19 +131,19 @@ function X(f) {
|
|
|
130
131
|
})
|
|
131
132
|
) });
|
|
132
133
|
}
|
|
133
|
-
const u = a.onSubmit ||
|
|
134
|
+
const u = a.onSubmit || t, y = a, { onSubmit: I } = y, D = h(y, ["onSubmit"]);
|
|
134
135
|
return /* @__PURE__ */ C(
|
|
135
136
|
"form",
|
|
136
137
|
F(k({
|
|
137
138
|
className: l,
|
|
138
139
|
onSubmit: (i) => {
|
|
139
|
-
i.preventDefault(), u && !
|
|
140
|
+
i.preventDefault(), u && !r && (u == null || u(i));
|
|
140
141
|
},
|
|
141
142
|
noValidate: !0
|
|
142
143
|
}, D), {
|
|
143
144
|
children: [
|
|
144
|
-
|
|
145
|
-
|
|
145
|
+
e,
|
|
146
|
+
o && /* @__PURE__ */ c(
|
|
146
147
|
"div",
|
|
147
148
|
{
|
|
148
149
|
role: "alert",
|
|
@@ -155,7 +156,7 @@ function X(f) {
|
|
|
155
156
|
"border-error",
|
|
156
157
|
p("md")
|
|
157
158
|
),
|
|
158
|
-
children:
|
|
159
|
+
children: o
|
|
159
160
|
}
|
|
160
161
|
),
|
|
161
162
|
m && /* @__PURE__ */ c(
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Form.js","sources":["../../../../../src/ui/components/Form/Form.tsx"],"sourcesContent":["\"use client\";\n\nimport type { FormHTMLAttributes, ReactNode } from \"react\";\nimport { FormProvider } from \"./FormProvider\";\nimport type { FieldValues, UseFormReturn } from \"react-hook-form\";\nimport { cn } from \"../../utils\";\nimport {\n getSpacingClass,\n getRadiusClass,\n getTypographySizeFromFontSize,\n} from \"../../tokens\";\n\n// Simple Form Props\ninterface SimpleFormProps extends FormHTMLAttributes<HTMLFormElement> {\n children: ReactNode;\n onSubmit?: (e: React.FormEvent<HTMLFormElement>) => void;\n loading?: boolean;\n error?: string | null;\n success?: string | null;\n form?: never; // Cannot use form prop in simple mode\n}\n\n// React Hook Form Props\ninterface ReactHookFormProps<\n TFieldValues extends FieldValues = FieldValues,\n> extends Omit<FormHTMLAttributes<HTMLFormElement>, \"onSubmit\"> {\n children: ReactNode;\n form: UseFormReturn<TFieldValues>;\n onSubmit: (data: TFieldValues) => void | Promise<void>;\n loading?: boolean;\n error?: string | null;\n success?: string | null;\n onSubmitError?: (errors: unknown) => void;\n}\n\ntype FormProps<TFieldValues extends FieldValues = FieldValues> =\n | SimpleFormProps\n | ReactHookFormProps<TFieldValues>;\n\n/**\n * Form Component\n *\n * A flexible form component that supports both simple forms and react-hook-form integration.\n *\n * @example\n * ```tsx\n * // Simple form\n * <Form onSubmit={handleSubmit} loading={isSubmitting}>\n * <Input name=\"email\" />\n * <Button type=\"submit\">Submit</Button>\n * </Form>\n *\n * // With react-hook-form\n * const form = useForm({ resolver: zodResolver(schema) });\n * <Form form={form} onSubmit={handleSubmit}>\n * <FormField name=\"email\">\n * {({ register, error }) => (\n * <>\n * <Input {...register('email')} />\n * {error && <ErrorMessage>{error}</ErrorMessage>}\n * </>\n * )}\n * </FormField>\n * </Form>\n * ```\n */\nexport default function Form<TFieldValues extends FieldValues = FieldValues>({\n children,\n onSubmit,\n loading = false,\n error = null,\n success = null,\n className = \"\",\n ...props\n}: FormProps<TFieldValues>) {\n const classes = cn(\n getSpacingClass(\"lg\", \"gap\"),\n \"flex\",\n \"flex-col\",\n className,\n );\n\n // Check if using react-hook-form\n const isReactHookForm = \"form\" in props && props.form !== undefined;\n\n if (isReactHookForm) {\n const {\n form,\n onSubmit: onSubmitData,\n onSubmitError,\n ...formProps\n } = props as ReactHookFormProps<TFieldValues>;\n\n const handleSubmit = form.handleSubmit(\n async (data) => {\n try {\n await onSubmitData(data);\n } catch (err) {\n onSubmitError?.(err);\n }\n },\n (errors) => {\n onSubmitError?.(errors);\n },\n );\n\n return (\n <FormProvider form={form} loading={loading}>\n <form\n className={classes}\n onSubmit={handleSubmit}\n noValidate\n {...formProps}\n >\n {children}\n {error && (\n <div\n role=\"alert\"\n className={cn(\n getSpacingClass(\"md\", \"p\"),\n getTypographySizeFromFontSize(\"sm\"),\n \"text-error-dark\",\n \"bg-error-bg\",\n \"border\",\n \"border-error\",\n getRadiusClass(\"md\"),\n )}\n >\n {error}\n </div>\n )}\n {success && (\n <div\n role=\"alert\"\n className={cn(\n getSpacingClass(\"md\", \"p\"),\n getTypographySizeFromFontSize(\"sm\"),\n \"text-success-dark\",\n \"bg-success-bg\",\n \"border\",\n \"border-success\",\n getRadiusClass(\"md\"),\n )}\n >\n {success}\n </div>\n )}\n </form>\n </FormProvider>\n );\n }\n\n // Simple form mode\n // Use onSubmit from props or from direct prop\n const onSubmitSimple = (props as SimpleFormProps).onSubmit || onSubmit;\n const { onSubmit: _, ...simpleProps } = props as SimpleFormProps;\n\n const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {\n e.preventDefault();\n if (onSubmitSimple && !loading) {\n // Narrow the union: we're in the !isReactHookForm branch, so\n // onSubmit takes a FormEvent. TS sees the union member's intersected\n // parameter type and can't prove it; the cast names the branch.\n (onSubmitSimple as SimpleFormProps[\"onSubmit\"])?.(e);\n }\n };\n\n return (\n <form\n className={classes}\n onSubmit={handleSubmit}\n noValidate\n {...simpleProps}\n >\n {children}\n {error && (\n <div\n role=\"alert\"\n className={cn(\n getSpacingClass(\"md\", \"p\"),\n getTypographySizeFromFontSize(\"sm\"),\n \"text-error-dark\",\n \"bg-error-bg\",\n \"border\",\n \"border-error\",\n getRadiusClass(\"md\"),\n )}\n >\n {error}\n </div>\n )}\n {success && (\n <div\n role=\"alert\"\n className={cn(\n getSpacingClass(\"md\", \"p\"),\n getTypographySizeFromFontSize(\"sm\"),\n \"text-success-dark\",\n \"bg-success-bg\",\n \"border\",\n \"border-success\",\n getRadiusClass(\"md\"),\n )}\n >\n {success}\n </div>\n )}\n </form>\n );\n}\n"],"names":["Form","_a","_b","children","onSubmit","loading","error","success","className","props","__objRest","classes","cn","getSpacingClass","form","onSubmitData","onSubmitError","formProps","handleSubmit","data","__async","err","errors","jsx","FormProvider","jsxs","__spreadProps","__spreadValues","getTypographySizeFromFontSize","getRadiusClass","onSubmitSimple","_","simpleProps","e"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkEA,SAAwBA,EAAqDC,GAQjD;AARiD,MAAAC,IAAAD,GAC3E;AAAA,cAAAE;AAAA,IACA,UAAAC;AAAA,IACA,SAAAC,IAAU;AAAA,IACV,OAAAC,IAAQ;AAAA,IACR,SAAAC,IAAU;AAAA,IACV,WAAAC,IAAY;AAAA,MAN+DN,GAOxEO,IAAAC,EAPwER,GAOxE;AAAA,IANH;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAGA,QAAMS,IAAUC;AAAA,IACdC,EAAgB,MAAM,KAAK;AAAA,IAC3B;AAAA,IACA;AAAA,IACAL;AAAA,EAAA;AAMF,MAFwB,UAAUC,KAASA,EAAM,SAAS,QAErC;AACnB,UAKIR,IAAAQ,GAJF;AAAA,YAAAK;AAAA,MACA,UAAUC;AAAA,MACV,eAAAC;AAAA,QAEEf,GADCgB,IAAAP,EACDT,GADC;AAAA,MAHH;AAAA,MACA;AAAA,MACA;AAAA,QAIIiB,IAAeJ,EAAK;AAAA,MACxB,CAAOK,MAASC,EAAA;
|
|
1
|
+
{"version":3,"file":"Form.js","sources":["../../../../../src/ui/components/Form/Form.tsx"],"sourcesContent":["\"use client\";\n\nimport type { FormHTMLAttributes, ReactNode } from \"react\";\nimport { FormProvider } from \"./FormProvider\";\nimport type { FieldValues, UseFormReturn } from \"react-hook-form\";\nimport { cn } from \"../../utils\";\nimport {\n getSpacingClass,\n getRadiusClass,\n getTypographySizeFromFontSize,\n} from \"../../tokens\";\n\n// Simple Form Props\ninterface SimpleFormProps extends FormHTMLAttributes<HTMLFormElement> {\n children: ReactNode;\n onSubmit?: (e: React.FormEvent<HTMLFormElement>) => void;\n loading?: boolean;\n error?: string | null;\n success?: string | null;\n form?: never; // Cannot use form prop in simple mode\n}\n\n// React Hook Form Props\ninterface ReactHookFormProps<\n TFieldValues extends FieldValues = FieldValues,\n> extends Omit<FormHTMLAttributes<HTMLFormElement>, \"onSubmit\"> {\n children: ReactNode;\n form: UseFormReturn<TFieldValues>;\n onSubmit: (data: TFieldValues) => void | Promise<void>;\n loading?: boolean;\n error?: string | null;\n success?: string | null;\n onSubmitError?: (errors: unknown) => void;\n}\n\ntype FormProps<TFieldValues extends FieldValues = FieldValues> =\n | SimpleFormProps\n | ReactHookFormProps<TFieldValues>;\n\n/**\n * Form Component\n *\n * A flexible form component that supports both simple forms and react-hook-form integration.\n *\n * @example\n * ```tsx\n * // Simple form\n * <Form onSubmit={handleSubmit} loading={isSubmitting}>\n * <Input name=\"email\" />\n * <Button type=\"submit\">Submit</Button>\n * </Form>\n *\n * // With react-hook-form\n * const form = useForm({ resolver: zodResolver(schema) });\n * <Form form={form} onSubmit={handleSubmit}>\n * <FormField name=\"email\">\n * {({ register, error }) => (\n * <>\n * <Input {...register('email')} />\n * {error && <ErrorMessage>{error}</ErrorMessage>}\n * </>\n * )}\n * </FormField>\n * </Form>\n * ```\n */\nexport default function Form<TFieldValues extends FieldValues = FieldValues>({\n children,\n onSubmit,\n loading = false,\n error = null,\n success = null,\n className = \"\",\n ...props\n}: FormProps<TFieldValues>) {\n const classes = cn(\n getSpacingClass(\"lg\", \"gap\"),\n \"flex\",\n \"flex-col\",\n className,\n );\n\n // Check if using react-hook-form\n const isReactHookForm = \"form\" in props && props.form !== undefined;\n\n if (isReactHookForm) {\n const {\n form,\n onSubmit: onSubmitData,\n onSubmitError,\n ...formProps\n } = props as ReactHookFormProps<TFieldValues>;\n\n const handleSubmit = form.handleSubmit(\n async (data) => {\n // Honor `loading` the same way simple mode does (line ~160) so an\n // in-flight submit isn't fired a second time (duplicate API call).\n if (loading) return;\n try {\n await onSubmitData(data);\n } catch (err) {\n onSubmitError?.(err);\n }\n },\n (errors) => {\n onSubmitError?.(errors);\n },\n );\n\n return (\n <FormProvider form={form} loading={loading}>\n <form\n className={classes}\n onSubmit={handleSubmit}\n noValidate\n {...formProps}\n >\n {children}\n {error && (\n <div\n role=\"alert\"\n className={cn(\n getSpacingClass(\"md\", \"p\"),\n getTypographySizeFromFontSize(\"sm\"),\n \"text-error-dark\",\n \"bg-error-bg\",\n \"border\",\n \"border-error\",\n getRadiusClass(\"md\"),\n )}\n >\n {error}\n </div>\n )}\n {success && (\n <div\n role=\"alert\"\n className={cn(\n getSpacingClass(\"md\", \"p\"),\n getTypographySizeFromFontSize(\"sm\"),\n \"text-success-dark\",\n \"bg-success-bg\",\n \"border\",\n \"border-success\",\n getRadiusClass(\"md\"),\n )}\n >\n {success}\n </div>\n )}\n </form>\n </FormProvider>\n );\n }\n\n // Simple form mode\n // Use onSubmit from props or from direct prop\n const onSubmitSimple = (props as SimpleFormProps).onSubmit || onSubmit;\n const { onSubmit: _, ...simpleProps } = props as SimpleFormProps;\n\n const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {\n e.preventDefault();\n if (onSubmitSimple && !loading) {\n // Narrow the union: we're in the !isReactHookForm branch, so\n // onSubmit takes a FormEvent. TS sees the union member's intersected\n // parameter type and can't prove it; the cast names the branch.\n (onSubmitSimple as SimpleFormProps[\"onSubmit\"])?.(e);\n }\n };\n\n return (\n <form\n className={classes}\n onSubmit={handleSubmit}\n noValidate\n {...simpleProps}\n >\n {children}\n {error && (\n <div\n role=\"alert\"\n className={cn(\n getSpacingClass(\"md\", \"p\"),\n getTypographySizeFromFontSize(\"sm\"),\n \"text-error-dark\",\n \"bg-error-bg\",\n \"border\",\n \"border-error\",\n getRadiusClass(\"md\"),\n )}\n >\n {error}\n </div>\n )}\n {success && (\n <div\n role=\"alert\"\n className={cn(\n getSpacingClass(\"md\", \"p\"),\n getTypographySizeFromFontSize(\"sm\"),\n \"text-success-dark\",\n \"bg-success-bg\",\n \"border\",\n \"border-success\",\n getRadiusClass(\"md\"),\n )}\n >\n {success}\n </div>\n )}\n </form>\n );\n}\n"],"names":["Form","_a","_b","children","onSubmit","loading","error","success","className","props","__objRest","classes","cn","getSpacingClass","form","onSubmitData","onSubmitError","formProps","handleSubmit","data","__async","err","errors","jsx","FormProvider","jsxs","__spreadProps","__spreadValues","getTypographySizeFromFontSize","getRadiusClass","onSubmitSimple","_","simpleProps","e"],"mappings":"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"}
|
|
@@ -1,66 +1,68 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { jsxs as
|
|
3
|
-
import { useFormContext as
|
|
4
|
-
import x from "
|
|
2
|
+
import { jsxs as d, jsx as g } from "react/jsx-runtime";
|
|
3
|
+
import { useFormContext as u } from "./FormContext.js";
|
|
4
|
+
import { get as x } from "react-hook-form";
|
|
5
|
+
import w from "../../primitives/Label/Label.js";
|
|
5
6
|
import { cn as c } from "../../utils/cn.js";
|
|
6
|
-
import { getTypographyWeightFromFontWeight as
|
|
7
|
-
import
|
|
8
|
-
import { getSpacingClass as
|
|
9
|
-
function
|
|
7
|
+
import { getTypographyWeightFromFontWeight as y, getTypographySizeFromFontSize as C } from "../../tokens/typography.js";
|
|
8
|
+
import S from "../../primitives/ErrorMessage/ErrorMessage.js";
|
|
9
|
+
import { getSpacingClass as b } from "../../tokens/spacing.js";
|
|
10
|
+
function W({
|
|
10
11
|
name: r,
|
|
11
|
-
label:
|
|
12
|
-
children:
|
|
13
|
-
rules:
|
|
14
|
-
className:
|
|
12
|
+
label: t,
|
|
13
|
+
children: f,
|
|
14
|
+
rules: e,
|
|
15
|
+
className: p = ""
|
|
15
16
|
}) {
|
|
16
17
|
var n;
|
|
17
|
-
const { form: i } =
|
|
18
|
+
const { form: i } = u();
|
|
18
19
|
if (!i)
|
|
19
20
|
throw new Error(
|
|
20
21
|
"FormField must be used within a Form component with react-hook-form integration"
|
|
21
22
|
);
|
|
22
23
|
const {
|
|
23
24
|
register: m,
|
|
24
|
-
formState: { errors:
|
|
25
|
+
formState: { errors: a },
|
|
25
26
|
watch: l
|
|
26
|
-
} = i, s = m(r,
|
|
27
|
-
return /* @__PURE__ */
|
|
27
|
+
} = i, s = m(r, e), o = (n = x(a, r)) == null ? void 0 : n.message, h = l(r);
|
|
28
|
+
return /* @__PURE__ */ d(
|
|
28
29
|
"div",
|
|
29
30
|
{
|
|
30
31
|
className: c(
|
|
31
32
|
"flex",
|
|
32
33
|
"flex-col",
|
|
33
|
-
|
|
34
|
-
|
|
34
|
+
b("sm", "gap"),
|
|
35
|
+
p
|
|
35
36
|
),
|
|
36
37
|
children: [
|
|
37
|
-
|
|
38
|
-
|
|
38
|
+
t && /* @__PURE__ */ g(
|
|
39
|
+
w,
|
|
39
40
|
{
|
|
40
41
|
htmlFor: r,
|
|
41
42
|
className: c(
|
|
42
43
|
"block",
|
|
43
|
-
|
|
44
|
-
|
|
44
|
+
C("sm"),
|
|
45
|
+
y("medium"),
|
|
45
46
|
"text-fg-primary"
|
|
46
47
|
),
|
|
47
|
-
children:
|
|
48
|
+
children: t
|
|
48
49
|
}
|
|
49
50
|
),
|
|
50
|
-
|
|
51
|
+
f({
|
|
51
52
|
name: r,
|
|
52
|
-
|
|
53
|
+
id: r,
|
|
54
|
+
register: (F) => m(F, e),
|
|
53
55
|
error: o,
|
|
54
56
|
value: h,
|
|
55
57
|
onChange: s.onChange,
|
|
56
58
|
onBlur: s.onBlur
|
|
57
59
|
}),
|
|
58
|
-
o && /* @__PURE__ */ g(
|
|
60
|
+
o && /* @__PURE__ */ g(S, { message: o })
|
|
59
61
|
]
|
|
60
62
|
}
|
|
61
63
|
);
|
|
62
64
|
}
|
|
63
65
|
export {
|
|
64
|
-
|
|
66
|
+
W as FormField
|
|
65
67
|
};
|
|
66
68
|
//# sourceMappingURL=FormField.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FormField.js","sources":["../../../../../src/ui/components/Form/FormField.tsx"],"sourcesContent":["\"use client\";\n\nimport { useFormContext } from \"./FormContext\";\nimport { ErrorMessage, Label } from \"../../primitives\";\nimport { cn } from \"../../utils\";\nimport {\n getSpacingClass,\n getTypographySizeFromFontSize,\n getTypographyWeightFromFontWeight,\n} from \"../../tokens\";\nimport type { FieldValues, Path, RegisterOptions } from \"react-hook-form\";\nimport type { ReactNode } from \"react\";\nimport type { UseFormReturn } from \"react-hook-form\";\n\nexport interface FormFieldProps<\n TFieldValues extends FieldValues = FieldValues,\n> {\n name: Path<TFieldValues>;\n label?: string;\n children: (props: {\n name: string;\n register: (\n fieldName: Path<TFieldValues>,\n ) => ReturnType<UseFormReturn<TFieldValues>[\"register\"]>;\n error?: string;\n value?: unknown;\n onChange?: ReturnType<UseFormReturn<TFieldValues>[\"register\"]>[\"onChange\"];\n onBlur?: ReturnType<UseFormReturn<TFieldValues>[\"register\"]>[\"onBlur\"];\n }) => ReactNode;\n rules?: RegisterOptions<TFieldValues>;\n className?: string;\n}\n\n/**\n * FormField Component\n *\n * A wrapper component for form fields that integrates with react-hook-form.\n * Provides register, error, and validation state to children.\n *\n * @example\n * ```tsx\n * <FormField name=\"email\" label=\"Email\">\n * {({ register, error }) => (\n * <>\n * <Label htmlFor=\"email\">Email</Label>\n * <Input id=\"email\" {...register('email')} />\n * {error && <ErrorMessage>{error}</ErrorMessage>}\n * </>\n * )}\n * </FormField>\n * ```\n */\nexport function FormField<TFieldValues extends FieldValues = FieldValues>({\n name,\n label,\n children,\n rules,\n className = \"\",\n}: FormFieldProps<TFieldValues>) {\n const { form } = useFormContext<TFieldValues>();\n\n if (!form) {\n throw new Error(\n \"FormField must be used within a Form component with react-hook-form integration\",\n );\n }\n\n const {\n register,\n formState: { errors },\n watch,\n } = form;\n\n const fieldRegister = register(name, rules);\n const error = errors
|
|
1
|
+
{"version":3,"file":"FormField.js","sources":["../../../../../src/ui/components/Form/FormField.tsx"],"sourcesContent":["\"use client\";\n\nimport { useFormContext } from \"./FormContext\";\nimport { ErrorMessage, Label } from \"../../primitives\";\nimport { cn } from \"../../utils\";\nimport {\n getSpacingClass,\n getTypographySizeFromFontSize,\n getTypographyWeightFromFontWeight,\n} from \"../../tokens\";\nimport { get } from \"react-hook-form\";\nimport type { FieldValues, Path, RegisterOptions } from \"react-hook-form\";\nimport type { ReactNode } from \"react\";\nimport type { UseFormReturn } from \"react-hook-form\";\n\nexport interface FormFieldProps<\n TFieldValues extends FieldValues = FieldValues,\n> {\n name: Path<TFieldValues>;\n label?: string;\n children: (props: {\n name: string;\n /**\n * Stable id owned by FormField — equal to `name` and already wired to\n * the label's `htmlFor`. Spread it onto the input so the label points\n * at a real element (`<Input id={id} {...register(name)} />`) instead\n * of relying on the consumer to remember to hardcode a matching id.\n */\n id: string;\n register: (\n fieldName: Path<TFieldValues>,\n ) => ReturnType<UseFormReturn<TFieldValues>[\"register\"]>;\n error?: string;\n value?: unknown;\n onChange?: ReturnType<UseFormReturn<TFieldValues>[\"register\"]>[\"onChange\"];\n onBlur?: ReturnType<UseFormReturn<TFieldValues>[\"register\"]>[\"onBlur\"];\n }) => ReactNode;\n rules?: RegisterOptions<TFieldValues>;\n className?: string;\n}\n\n/**\n * FormField Component\n *\n * A wrapper component for form fields that integrates with react-hook-form.\n * Provides register, error, and validation state to children.\n *\n * @example\n * ```tsx\n * <FormField name=\"email\" label=\"Email\">\n * {({ register, error }) => (\n * <>\n * <Label htmlFor=\"email\">Email</Label>\n * <Input id=\"email\" {...register('email')} />\n * {error && <ErrorMessage>{error}</ErrorMessage>}\n * </>\n * )}\n * </FormField>\n * ```\n */\nexport function FormField<TFieldValues extends FieldValues = FieldValues>({\n name,\n label,\n children,\n rules,\n className = \"\",\n}: FormFieldProps<TFieldValues>) {\n const { form } = useFormContext<TFieldValues>();\n\n if (!form) {\n throw new Error(\n \"FormField must be used within a Form component with react-hook-form integration\",\n );\n }\n\n const {\n register,\n formState: { errors },\n watch,\n } = form;\n\n const fieldRegister = register(name, rules);\n // react-hook-form stores errors in a nested object keyed by path\n // segments, not by the dotted string. A flat `errors[name]` lookup is\n // always undefined for dotted paths (`items.0.name`, `user.email`),\n // silently swallowing the error. `get` resolves the path the same way\n // RHF does internally — and the same way `watch(name)` below already\n // does for the value.\n const error = get(errors, name)?.message as string | undefined;\n const value = watch(name);\n\n return (\n <div\n className={cn(\n \"flex\",\n \"flex-col\",\n getSpacingClass(\"sm\", \"gap\"),\n className,\n )}\n >\n {label && (\n <Label\n htmlFor={name}\n className={cn(\n \"block\",\n getTypographySizeFromFontSize(\"sm\"),\n getTypographyWeightFromFontWeight(\"medium\"),\n \"text-fg-primary\",\n )}\n >\n {label}\n </Label>\n )}\n {children({\n name,\n id: name,\n register: (fieldName: Path<TFieldValues>) => register(fieldName, rules),\n error,\n value,\n onChange: fieldRegister.onChange,\n onBlur: fieldRegister.onBlur,\n })}\n {error && <ErrorMessage message={error} />}\n </div>\n );\n}\n"],"names":["FormField","name","label","children","rules","className","form","useFormContext","register","errors","watch","fieldRegister","error","_a","get","value","jsxs","cn","getSpacingClass","jsx","Label","getTypographySizeFromFontSize","getTypographyWeightFromFontWeight","fieldName","ErrorMessage"],"mappings":";;;;;;;;;AA4DO,SAASA,EAA0D;AAAA,EACxE,MAAAC;AAAA,EACA,OAAAC;AAAA,EACA,UAAAC;AAAA,EACA,OAAAC;AAAA,EACA,WAAAC,IAAY;AACd,GAAiC;;AAC/B,QAAM,EAAE,MAAAC,EAAA,IAASC,EAAA;AAEjB,MAAI,CAACD;AACH,UAAM,IAAI;AAAA,MACR;AAAA,IAAA;AAIJ,QAAM;AAAA,IACJ,UAAAE;AAAA,IACA,WAAW,EAAE,QAAAC,EAAA;AAAA,IACb,OAAAC;AAAA,EAAA,IACEJ,GAEEK,IAAgBH,EAASP,GAAMG,CAAK,GAOpCQ,KAAQC,IAAAC,EAAIL,GAAQR,CAAI,MAAhB,gBAAAY,EAAmB,SAC3BE,IAAQL,EAAMT,CAAI;AAExB,SACE,gBAAAe;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAWC;AAAA,QACT;AAAA,QACA;AAAA,QACAC,EAAgB,MAAM,KAAK;AAAA,QAC3Bb;AAAA,MAAA;AAAA,MAGD,UAAA;AAAA,QAAAH,KACC,gBAAAiB;AAAA,UAACC;AAAA,UAAA;AAAA,YACC,SAASnB;AAAA,YACT,WAAWgB;AAAA,cACT;AAAA,cACAI,EAA8B,IAAI;AAAA,cAClCC,EAAkC,QAAQ;AAAA,cAC1C;AAAA,YAAA;AAAA,YAGD,UAAApB;AAAA,UAAA;AAAA,QAAA;AAAA,QAGJC,EAAS;AAAA,UACR,MAAAF;AAAA,UACA,IAAIA;AAAA,UACJ,UAAU,CAACsB,MAAkCf,EAASe,GAAWnB,CAAK;AAAA,UACtE,OAAAQ;AAAA,UACA,OAAAG;AAAA,UACA,UAAUJ,EAAc;AAAA,UACxB,QAAQA,EAAc;AAAA,QAAA,CACvB;AAAA,QACAC,KAAS,gBAAAO,EAACK,GAAA,EAAa,SAASZ,EAAA,CAAO;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAG9C;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Header.js","sources":["../../../../../src/ui/components/Header/Header.tsx"],"sourcesContent":["/**\n * Header Component\n *\n * Horizontal header component with logo, navigation, and actions slots.\n * Uses compound components pattern for maximum flexibility.\n *\n * @see EPIC-002: Header Component
|
|
1
|
+
{"version":3,"file":"Header.js","sources":["../../../../../src/ui/components/Header/Header.tsx"],"sourcesContent":["/**\n * Header Component\n *\n * Horizontal header component with logo, navigation, and actions slots.\n * Uses compound components pattern for maximum flexibility.\n *\n * @see EPIC-002: Header Component\n * @see RFC-003: Header Composition Pattern (APPROVED)\n * @see ADR-002: Header + SideNavbar Compatibility (ACCEPTED)\n */\n\n\"use client\";\n\nimport { HeaderProvider } from \"./contexts/HeaderContext\";\nimport { HeaderLogo } from \"./components/HeaderLogo\";\nimport { HeaderNavigation } from \"./components/HeaderNavigation\";\nimport { HeaderActions } from \"./components/HeaderActions\";\nimport { HeaderHamburger } from \"./components/HeaderHamburger\";\nimport { HeaderMobileMenu } from \"./components/HeaderMobileMenu\";\nimport { getShadowClass } from \"../../tokens/shadows\";\nimport { getSpacingClass } from \"../../tokens/spacing\";\nimport { getZIndexClass } from \"../../tokens/z-index\";\nimport type { HeaderProps } from \"./types\";\nimport { cn, cva } from \"../../utils\";\nimport { Container } from \"../../layouts\";\n\n/**\n * Header Variants using CVA\n * Type-safe variant system for Header component\n */\nconst headerVariants = cva(\n // Base classes\n cn(\"w-full\", \"bg-surface-base\", \"transition-shadow\", \"transition-colors\"),\n {\n variants: {\n variant: {\n default: \"\",\n elevated: getShadowClass(\"sm\"),\n bordered: cn(\"border-b\", \"border-line-muted\"),\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n },\n);\n\n/**\n * Header Component\n *\n * Horizontal header with compound components pattern.\n *\n * @example\n * ```tsx\n * <Header>\n * <Header.Logo href=\"/\">MyApp</Header.Logo>\n * <Header.Navigation>\n * <NavLink href=\"/home\">Home</NavLink>\n * <NavLink href=\"/about\">About</NavLink>\n * </Header.Navigation>\n * <Header.Actions>\n * <Button>Sign In</Button>\n * </Header.Actions>\n * </Header>\n * ```\n */\nexport function Header({\n children,\n variant = \"default\",\n sticky = false,\n maxWidth = \"full\",\n bare = false,\n className,\n ...props\n}: HeaderProps) {\n const content = (\n <div\n className={`flex items-center justify-between ${getSpacingClass(\"base\", \"gap\")}`}\n >\n {/* Children are rendered here - compound components handle their own layout */}\n {children}\n </div>\n );\n\n // Bare mode: Just render content without header/Container wrapper\n // Useful when used inside DashboardLayout which provides the wrapper\n if (bare) {\n return (\n <HeaderProvider>\n <div className={cn(className)} {...props}>\n {content}\n </div>\n </HeaderProvider>\n );\n }\n\n // Normal mode: Create header element with Container\n return (\n <HeaderProvider>\n <header\n className={cn(\n headerVariants({ variant }),\n sticky && `sticky top-0 ${getZIndexClass(\"sticky\")}`,\n sticky && \"backdrop-blur-sm bg-surface-base/95\",\n className,\n )}\n {...props}\n >\n <Container maxWidth={maxWidth} paddingX=\"base\" paddingY=\"sm\">\n {content}\n </Container>\n </header>\n </HeaderProvider>\n );\n}\n\n// Compound Components\nHeader.Logo = HeaderLogo;\nHeader.Navigation = HeaderNavigation;\nHeader.Actions = HeaderActions;\nHeader.Hamburger = HeaderHamburger;\nHeader.MobileMenu = HeaderMobileMenu;\n\nexport default Header;\n"],"names":["headerVariants","cva","cn","getShadowClass","Header","_a","_b","children","variant","sticky","maxWidth","bare","className","props","__objRest","content","jsx","getSpacingClass","HeaderProvider","__spreadProps","__spreadValues","getZIndexClass","Container","HeaderLogo","HeaderNavigation","HeaderActions","HeaderHamburger","HeaderMobileMenu"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BA,MAAMA,IAAiBC;AAAA;AAAA,EAErBC,EAAG,UAAU,mBAAmB,qBAAqB,mBAAmB;AAAA,EACxE;AAAA,IACE,UAAU;AAAA,MACR,SAAS;AAAA,QACP,SAAS;AAAA,QACT,UAAUC,EAAe,IAAI;AAAA,QAC7B,UAAUD,EAAG,YAAY,mBAAmB;AAAA,MAAA;AAAA,IAC9C;AAAA,IAEF,iBAAiB;AAAA,MACf,SAAS;AAAA,IAAA;AAAA,EACX;AAEJ;AAqBO,SAASE,EAAOC,GAQP;AARO,MAAAC,IAAAD,GACrB;AAAA,cAAAE;AAAA,IACA,SAAAC,IAAU;AAAA,IACV,QAAAC,IAAS;AAAA,IACT,UAAAC,IAAW;AAAA,IACX,MAAAC,IAAO;AAAA,IACP,WAAAC;AAAA,MANqBN,GAOlBO,IAAAC,EAPkBR,GAOlB;AAAA,IANH;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAGA,QAAMS,IACJ,gBAAAC;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAW,qCAAqCC,EAAgB,QAAQ,KAAK,CAAC;AAAA,MAG7E,UAAAV;AAAA,IAAA;AAAA,EAAA;AAML,SAAII,IAEA,gBAAAK,EAACE,GAAA,EACC,UAAA,gBAAAF,EAAC,OAAAG,EAAAC,EAAA,EAAI,WAAWlB,EAAGU,CAAS,KAAOC,IAAlC,EACE,UAAAE,EAAA,EACH,GACF,sBAMDG,GAAA,EACC,UAAA,gBAAAF;AAAA,IAAC;AAAA,IAAAG,EAAAC,EAAA;AAAA,MACC,WAAWlB;AAAA,QACTF,EAAe,EAAE,SAAAQ,GAAS;AAAA,QAC1BC,KAAU,gBAAgBY,EAAe,QAAQ,CAAC;AAAA,QAClDZ,KAAU;AAAA,QACVG;AAAA,MAAA;AAAA,OAEEC,IAPL;AAAA,MASC,4BAACS,GAAA,EAAU,UAAAZ,GAAoB,UAAS,QAAO,UAAS,MACrD,UAAAK,EAAA,CACH;AAAA,IAAA;AAAA,EAAA,GAEJ;AAEJ;AAGAX,EAAO,OAAOmB;AACdnB,EAAO,aAAaoB;AACpBpB,EAAO,UAAUqB;AACjBrB,EAAO,YAAYsB;AACnBtB,EAAO,aAAauB;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HeaderActions.js","sources":["../../../../../../src/ui/components/Header/components/HeaderActions.tsx"],"sourcesContent":["/**\n * HeaderActions Component\n *\n * Actions slot component for Header (typically buttons, user menu, etc.).\n *\n * @see EPIC-002: Header Component
|
|
1
|
+
{"version":3,"file":"HeaderActions.js","sources":["../../../../../../src/ui/components/Header/components/HeaderActions.tsx"],"sourcesContent":["/**\n * HeaderActions Component\n *\n * Actions slot component for Header (typically buttons, user menu, etc.).\n *\n * @see EPIC-002: Header Component\n * @see RFC-003: Header Composition Pattern (APPROVED)\n */\n\n\"use client\";\n\nimport { type ReactNode } from \"react\";\nimport { cn } from \"../../../utils\";\nimport { getSpacingClass } from \"../../../tokens/spacing\";\n\nexport interface HeaderActionsProps {\n /**\n * Actions content (typically Button components)\n */\n children: ReactNode;\n\n /**\n * Additional CSS classes\n */\n className?: string;\n}\n\n/**\n * HeaderActions Component\n *\n * Actions slot for Header. Typically contains Button components or user menu.\n *\n * @example\n * ```tsx\n * <Header.Actions>\n * <Button variant=\"outline\">Sign In</Button>\n * <Button variant=\"primary\">Sign Up</Button>\n * </Header.Actions>\n * ```\n */\nexport function HeaderActions({ children, className }: HeaderActionsProps) {\n return (\n <div\n className={cn(\n \"flex-shrink-0 flex items-center\",\n getSpacingClass(\"sm\", \"gap\"),\n className,\n )}\n >\n {children}\n </div>\n );\n}\n"],"names":["HeaderActions","children","className","jsx","cn","getSpacingClass"],"mappings":";;;;AAwCO,SAASA,EAAc,EAAE,UAAAC,GAAU,WAAAC,KAAiC;AACzE,SACE,gBAAAC;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAWC;AAAA,QACT;AAAA,QACAC,EAAgB,MAAM,KAAK;AAAA,QAC3BH;AAAA,MAAA;AAAA,MAGD,UAAAD;AAAA,IAAA;AAAA,EAAA;AAGP;"}
|