@nocoo/basalt 3.2.0 → 3.2.1
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/ai/DESIGN.md +20 -9
- package/ai/INTEGRATION.md +9 -9
- package/ai/USAGE.md +1 -1
- package/ai/registry.json +73 -73
- package/dist/charts/frame.js +2 -2
- package/dist/charts/frame.js.map +1 -1
- package/dist/charts/heatmap-calendar.js +4 -4
- package/dist/charts/heatmap-calendar.js.map +1 -1
- package/dist/charts/heatmap-matrix.js +3 -3
- package/dist/charts/heatmap-matrix.js.map +1 -1
- package/dist/components/app-header.js +1 -1
- package/dist/components/app-header.js.map +1 -1
- package/dist/components/app-shell.js +1 -1
- package/dist/components/app-shell.js.map +1 -1
- package/dist/components/chat-composer.js +1 -1
- package/dist/components/chat-composer.js.map +1 -1
- package/dist/components/chat-message.js +1 -1
- package/dist/components/chat-message.js.map +1 -1
- package/dist/components/code.js +1 -1
- package/dist/components/code.js.map +1 -1
- package/dist/components/command-palette.js +2 -2
- package/dist/components/command-palette.js.map +1 -1
- package/dist/components/context-cards.js +1 -1
- package/dist/components/context-cards.js.map +1 -1
- package/dist/components/context-menu.js +1 -1
- package/dist/components/context-menu.js.map +1 -1
- package/dist/components/data-table.js +127 -124
- package/dist/components/data-table.js.map +1 -1
- package/dist/components/diff-table.js +1 -1
- package/dist/components/diff-table.js.map +1 -1
- package/dist/components/dropdown-menu.js +1 -1
- package/dist/components/dropdown-menu.js.map +1 -1
- package/dist/components/editable-nav-item.js +2 -2
- package/dist/components/editable-nav-item.js.map +1 -1
- package/dist/components/file-dropzone.js +1 -1
- package/dist/components/file-dropzone.js.map +1 -1
- package/dist/components/filter-bar.js +1 -1
- package/dist/components/filter-bar.js.map +1 -1
- package/dist/components/icon-picker.js +3 -3
- package/dist/components/icon-picker.js.map +1 -1
- package/dist/components/inline-editable.js +1 -1
- package/dist/components/inline-editable.js.map +1 -1
- package/dist/components/input-group.js +2 -2
- package/dist/components/input-group.js.map +1 -1
- package/dist/components/layer-card.js +2 -1
- package/dist/components/layer-card.js.map +1 -1
- package/dist/components/link.js +1 -1
- package/dist/components/link.js.map +1 -1
- package/dist/components/menu-bar.js +2 -2
- package/dist/components/menu-bar.js.map +1 -1
- package/dist/components/multi-select.js +1 -1
- package/dist/components/multi-select.js.map +1 -1
- package/dist/components/overlay.d.ts +3 -6
- package/dist/components/overlay.js +3 -3
- package/dist/components/overlay.js.map +1 -1
- package/dist/components/responsive-master-detail.js +2 -2
- package/dist/components/responsive-master-detail.js.map +1 -1
- package/dist/components/scroll-area.js +1 -1
- package/dist/components/scroll-area.js.map +1 -1
- package/dist/components/segment-control.js +1 -1
- package/dist/components/segment-control.js.map +1 -1
- package/dist/components/select.js +1 -1
- package/dist/components/select.js.map +1 -1
- package/dist/components/sensitive-input.js +1 -1
- package/dist/components/sensitive-input.js.map +1 -1
- package/dist/components/sidebar.js +1 -1
- package/dist/components/sidebar.js.map +1 -1
- package/dist/components/table.js +1 -1
- package/dist/components/table.js.map +1 -1
- package/dist/components/tabs.js +1 -1
- package/dist/components/tabs.js.map +1 -1
- package/dist/components/tag-color-picker.js +2 -2
- package/dist/components/tag-color-picker.js.map +1 -1
- package/dist/components/toast.js +1 -1
- package/dist/components/toast.js.map +1 -1
- package/dist/components/toolbar.js +8 -8
- package/dist/components/toolbar.js.map +1 -1
- package/dist/styles/base.css +71 -0
- package/dist/styles/standalone.css +72 -87
- package/dist/styles/tailwind.css +8 -2
- package/dist/styles/tokens.css +4 -1
- package/dist/utils/navigation.d.ts +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dropdown-menu.js","names":["React","DropdownMenuPrimitive","DropdownMenu","DropdownMenuTrigger","DropdownMenuGroup","DropdownMenuPortal","DropdownMenuSub","DropdownMenuRadioGroup","DropdownMenuContent","props","highlightRef","useHoverHighlight","ref","overlayPanelClass","cn","className","DropdownMenuItem","overlayItemClass"],"sources":["../../src/components/dropdown-menu.tsx"],"sourcesContent":["import * as DropdownMenuPrimitive from \"@radix-ui/react-dropdown-menu\";\nimport * as React from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { useHoverHighlight } from \"../utils/use-hover-highlight\";\nimport { MENU_GAP, overlayItemClass, overlayPanelClass } from \"./overlay\";\n\ntype RadixDropdownMenuProps = React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Root>;\ntype RadixDropdownMenuTriggerProps = React.ComponentPropsWithoutRef<\n\ttypeof DropdownMenuPrimitive.Trigger\n>;\ntype RadixDropdownMenuGroupProps = React.ComponentPropsWithoutRef<\n\ttypeof DropdownMenuPrimitive.Group\n>;\ntype RadixDropdownMenuPortalProps = React.ComponentPropsWithoutRef<\n\ttypeof DropdownMenuPrimitive.Portal\n>;\ntype RadixDropdownMenuSubProps = React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Sub>;\ntype RadixDropdownMenuRadioGroupProps = React.ComponentPropsWithoutRef<\n\ttypeof DropdownMenuPrimitive.RadioGroup\n>;\ntype RadixDropdownMenuContentProps = React.ComponentPropsWithoutRef<\n\ttypeof DropdownMenuPrimitive.Content\n>;\ntype RadixDropdownMenuItemProps = React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item>;\n\nexport interface DropdownMenuProps\n\textends Omit<\n\t\tRadixDropdownMenuProps,\n\t\t\"open\" | \"defaultOpen\" | \"onOpenChange\" | \"dir\" | \"modal\" | \"children\"\n\t> {\n\t/**\n\t * Structure elements comprising the dropdown menu, typically trigger and content.\n\t */\n\tchildren?: React.ReactNode;\n\t/**\n\t * The controlled open state of the dropdown menu.\n\t */\n\topen?: RadixDropdownMenuProps[\"open\"];\n\t/**\n\t * The uncontrolled initial open state of the dropdown menu.\n\t * @default false\n\t */\n\tdefaultOpen?: RadixDropdownMenuProps[\"defaultOpen\"];\n\t/**\n\t * Called when the open state changes.\n\t */\n\tonOpenChange?: RadixDropdownMenuProps[\"onOpenChange\"];\n\t/**\n\t * The reading direction of the dropdown menu. Inherited from DirectionProvider if present,\n\t * or defaults to \"ltr\".\n\t * @default \"ltr\"\n\t */\n\tdir?: RadixDropdownMenuProps[\"dir\"];\n\t/**\n\t * The modality of the dropdown menu. When set to true, interaction with outside elements\n\t * will be disabled and only menu content will be visible to screen readers.\n\t * @default true\n\t */\n\tmodal?: RadixDropdownMenuProps[\"modal\"];\n}\n\nexport const DropdownMenu: React.FC<DropdownMenuProps> = DropdownMenuPrimitive.Root;\n\nexport interface DropdownMenuTriggerProps\n\textends Omit<RadixDropdownMenuTriggerProps, \"asChild\" | \"children\"> {\n\t/**\n\t * Trigger element content.\n\t */\n\tchildren?: React.ReactNode;\n\t/**\n\t * Change the default rendered button element to the child element, merging props and behavior.\n\t * DropdownMenuTrigger forwards ref to HTMLButtonElement and inherits native button attributes.\n\t * @default false\n\t */\n\tasChild?: RadixDropdownMenuTriggerProps[\"asChild\"];\n}\n\nexport const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;\n\nexport interface DropdownMenuGroupProps\n\textends Omit<RadixDropdownMenuGroupProps, \"asChild\" | \"children\"> {\n\t/**\n\t * Menu items or elements grouped together.\n\t */\n\tchildren?: React.ReactNode;\n\t/**\n\t * Change the default rendered div element to the child element, merging props and behavior.\n\t * DropdownMenuGroup forwards ref to HTMLDivElement and inherits native div attributes.\n\t * @default false\n\t */\n\tasChild?: RadixDropdownMenuGroupProps[\"asChild\"];\n}\n\nexport const DropdownMenuGroup = DropdownMenuPrimitive.Group;\n\nexport interface DropdownMenuPortalProps\n\textends Omit<RadixDropdownMenuPortalProps, \"container\" | \"forceMount\" | \"children\"> {\n\t/**\n\t * Content to render into the portal target.\n\t */\n\tchildren?: React.ReactNode;\n\t/**\n\t * Specify a container element to portal the content into.\n\t * Note: Only controls direct portal children; does not override the destination\n\t * container of the built-in portal inside DropdownMenuContent.\n\t */\n\tcontainer?: RadixDropdownMenuPortalProps[\"container\"];\n\t/**\n\t * Used to force mounting when more control is needed. Useful when\n\t * controlling animation with React animation libraries.\n\t */\n\tforceMount?: RadixDropdownMenuPortalProps[\"forceMount\"];\n}\n\nexport const DropdownMenuPortal = DropdownMenuPrimitive.Portal;\n\nexport interface DropdownMenuSubProps\n\textends Omit<RadixDropdownMenuSubProps, \"open\" | \"defaultOpen\" | \"onOpenChange\" | \"children\"> {\n\t/**\n\t * Submenu structure elements.\n\t * Note: Basalt does not export styled DropdownMenuSubTrigger or DropdownMenuSubContent components;\n\t * compose with underlying Radix primitives when building nested submenus.\n\t */\n\tchildren?: React.ReactNode;\n\t/**\n\t * The controlled open state of the submenu.\n\t */\n\topen?: RadixDropdownMenuSubProps[\"open\"];\n\t/**\n\t * The uncontrolled initial open state of the submenu.\n\t * @default false\n\t */\n\tdefaultOpen?: RadixDropdownMenuSubProps[\"defaultOpen\"];\n\t/**\n\t * Event handler called when the open state of the submenu changes.\n\t */\n\tonOpenChange?: RadixDropdownMenuSubProps[\"onOpenChange\"];\n}\n\nexport const DropdownMenuSub = DropdownMenuPrimitive.Sub;\n\nexport interface DropdownMenuRadioGroupProps\n\textends Omit<\n\t\tRadixDropdownMenuRadioGroupProps,\n\t\t\"value\" | \"onValueChange\" | \"asChild\" | \"children\"\n\t> {\n\t/**\n\t * Radio item elements grouped together.\n\t * Note: Basalt does not export styled DropdownMenuRadioItem or indicator components;\n\t * compose with underlying Radix primitives when building radio selection groups.\n\t */\n\tchildren?: React.ReactNode;\n\t/**\n\t * The value of the currently selected radio item.\n\t */\n\tvalue?: RadixDropdownMenuRadioGroupProps[\"value\"];\n\t/**\n\t * Event handler called when the value changes.\n\t */\n\tonValueChange?: RadixDropdownMenuRadioGroupProps[\"onValueChange\"];\n\t/**\n\t * Change the default rendered div element to the child element, merging props and behavior.\n\t * DropdownMenuRadioGroup forwards ref to HTMLDivElement and inherits native div attributes.\n\t * @default false\n\t */\n\tasChild?: RadixDropdownMenuRadioGroupProps[\"asChild\"];\n}\n\nexport const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup;\n\nexport interface DropdownMenuContentProps\n\textends Omit<\n\t\tRadixDropdownMenuContentProps,\n\t\t| \"side\"\n\t\t| \"sideOffset\"\n\t\t| \"align\"\n\t\t| \"alignOffset\"\n\t\t| \"avoidCollisions\"\n\t\t| \"collisionBoundary\"\n\t\t| \"collisionPadding\"\n\t\t| \"arrowPadding\"\n\t\t| \"sticky\"\n\t\t| \"hideWhenDetached\"\n\t\t| \"updatePositionStrategy\"\n\t\t| \"loop\"\n\t\t| \"onCloseAutoFocus\"\n\t\t| \"onEscapeKeyDown\"\n\t\t| \"onPointerDownOutside\"\n\t\t| \"onFocusOutside\"\n\t\t| \"onInteractOutside\"\n\t\t| \"forceMount\"\n\t\t| \"asChild\"\n\t> {\n\t/**\n\t * Preferred placement side relative to trigger.\n\t * @default \"bottom\"\n\t */\n\tside?: RadixDropdownMenuContentProps[\"side\"];\n\t/**\n\t * Distance in pixels between trigger and floating content panel.\n\t * In Basalt, defaults to MENU_GAP (8).\n\t * @default 8\n\t */\n\tsideOffset?: RadixDropdownMenuContentProps[\"sideOffset\"];\n\t/**\n\t * Preferred alignment along the side axis.\n\t * @default \"center\"\n\t */\n\talign?: RadixDropdownMenuContentProps[\"align\"];\n\t/**\n\t * Offset in pixels from the start or end alignment position.\n\t * @default 0\n\t */\n\talignOffset?: RadixDropdownMenuContentProps[\"alignOffset\"];\n\t/**\n\t * Whether to reposition content to avoid viewport boundary collisions.\n\t * @default true\n\t */\n\tavoidCollisions?: RadixDropdownMenuContentProps[\"avoidCollisions\"];\n\t/**\n\t * Element or elements bounding boundary collision calculations.\n\t * @default []\n\t */\n\tcollisionBoundary?: RadixDropdownMenuContentProps[\"collisionBoundary\"];\n\t/**\n\t * Virtual padding from collision boundaries in pixels.\n\t * @default 0\n\t */\n\tcollisionPadding?: RadixDropdownMenuContentProps[\"collisionPadding\"];\n\t/**\n\t * Padding in pixels between popper arrow and floating panel edge.\n\t * @default 0\n\t */\n\tarrowPadding?: RadixDropdownMenuContentProps[\"arrowPadding\"];\n\t/**\n\t * Sticky positioning behavior along the align axis when overflowing.\n\t * @default \"partial\"\n\t */\n\tsticky?: RadixDropdownMenuContentProps[\"sticky\"];\n\t/**\n\t * Whether to hide content completely when trigger is fully occluded.\n\t * @default false\n\t */\n\thideWhenDetached?: RadixDropdownMenuContentProps[\"hideWhenDetached\"];\n\t/**\n\t * Strategy used to calculate and update popper position.\n\t * @default \"optimized\"\n\t */\n\tupdatePositionStrategy?: RadixDropdownMenuContentProps[\"updatePositionStrategy\"];\n\t/**\n\t * Whether keyboard navigation should loop around item boundaries.\n\t * @default false\n\t */\n\tloop?: RadixDropdownMenuContentProps[\"loop\"];\n\t/**\n\t * Callback fired when auto-focusing on close. Can be prevented.\n\t */\n\tonCloseAutoFocus?: RadixDropdownMenuContentProps[\"onCloseAutoFocus\"];\n\t/**\n\t * Callback fired when the Escape key is down on the content layer. Can be prevented.\n\t */\n\tonEscapeKeyDown?: RadixDropdownMenuContentProps[\"onEscapeKeyDown\"];\n\t/**\n\t * Callback fired when a pointerdown event happens outside the bounds of the content. Can be prevented.\n\t */\n\tonPointerDownOutside?: RadixDropdownMenuContentProps[\"onPointerDownOutside\"];\n\t/**\n\t * Callback fired when focus moves outside the bounds of the content. Can be prevented.\n\t */\n\tonFocusOutside?: RadixDropdownMenuContentProps[\"onFocusOutside\"];\n\t/**\n\t * Callback fired when an interaction (pointerdown or focus) happens outside the bounds of the content. Can be prevented.\n\t */\n\tonInteractOutside?: RadixDropdownMenuContentProps[\"onInteractOutside\"];\n\t/**\n\t * Force mounting content in DOM for external animation controls.\n\t * When forceMount is true, the content remains mounted even when closed.\n\t * The caller is responsible for visibility transitions and unmounting after animation completes.\n\t * Note: Keeping modal content forceMounted may isolate background interactions until unmounted.\n\t */\n\tforceMount?: true;\n\t/**\n\t * Change the default rendered div element to the child element, merging props and behavior.\n\t * DropdownMenuContent forwards ref to HTMLDivElement and inherits native div attributes.\n\t * @default false\n\t */\n\tasChild?: RadixDropdownMenuContentProps[\"asChild\"];\n}\n\nexport const DropdownMenuContent = React.forwardRef<\n\tReact.ElementRef<typeof DropdownMenuPrimitive.Content>,\n\tDropdownMenuContentProps\n>(({ className, sideOffset = MENU_GAP, ...props }, ref) => {\n\tconst highlightRef = useHoverHighlight(ref);\n\treturn (\n\t\t<DropdownMenuPrimitive.Portal forceMount={props.forceMount}>\n\t\t\t<DropdownMenuPrimitive.Content\n\t\t\t\tref={highlightRef}\n\t\t\t\tsideOffset={sideOffset}\n\t\t\t\tclassName={overlayPanelClass(cn(\"basalt-hover-list min-w-basalt-40\", className))}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t</DropdownMenuPrimitive.Portal>\n\t);\n});\nDropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;\n\nexport interface DropdownMenuItemProps\n\textends Omit<RadixDropdownMenuItemProps, \"disabled\" | \"onSelect\" | \"textValue\" | \"asChild\"> {\n\t/**\n\t * Disable the menu item.\n\t * @default false\n\t */\n\tdisabled?: RadixDropdownMenuItemProps[\"disabled\"];\n\t/**\n\t * Event handler called when the menu item is selected (via click or keyboard).\n\t * Note that this is a Radix CustomEvent, not native DOM onSelect.\n\t */\n\tonSelect?: RadixDropdownMenuItemProps[\"onSelect\"];\n\t/**\n\t * Optional text used for typeahead navigation. By default typeahead uses item text content.\n\t */\n\ttextValue?: RadixDropdownMenuItemProps[\"textValue\"];\n\t/**\n\t * Change the default rendered div element to the child element, merging props and behavior.\n\t * DropdownMenuItem forwards ref to HTMLDivElement and inherits native div attributes.\n\t * @default false\n\t */\n\tasChild?: RadixDropdownMenuItemProps[\"asChild\"];\n}\n\nexport const DropdownMenuItem = React.forwardRef<\n\tReact.ElementRef<typeof DropdownMenuPrimitive.Item>,\n\tDropdownMenuItemProps\n>(({ className, ...props }, ref) => (\n\t<DropdownMenuPrimitive.Item\n\t\tdata-basalt-hover-item=\"\"\n\t\tref={ref}\n\t\tclassName={overlayItemClass(\n\t\t\tcn(\n\t\t\t\t\"relative outline-hidden data-disabled:pointer-events-none data-disabled:opacity-50\",\n\t\t\t\tclassName,\n\t\t\t),\n\t\t)}\n\t\t{...props}\n\t/>\n));\nDropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;\n"],"mappings":";;;;;;;;AA6DA,IAAaE,IAA4CD,EAAsB,MAgBlEE,IAAsBF,EAAsB,SAgB5CG,IAAoBH,EAAsB,OAqB1CI,IAAqBJ,EAAsB,QAyB3CK,IAAkBL,EAAsB,KA6BxCM,IAAyBN,EAAsB,YAyH/CO,IAAsBR,EAAM,YAGtC,EAAE,cAAW,gBAAA,GAAuB,GAAGS,KAAS,MAAQ;CAC1D,IAAMC,IAAeC,EAAkBC,CAAG;CAC1C,OACC,kBAACX,EAAsB,QAAvB;EAA8B,YAAYQ,EAAM;EAC/C,UAAA,kBAACR,EAAsB,SAAvB;GACC,KAAKS;GACO;GACZ,WAAWG,EAAkBC,EAAG,qCAAqCC,CAAS,CAAC;GAC/E,GAAIN;EACJ,CAAA;CAC4B,CAAA;AAEhC,CAAC;AACD,EAAoB,cAAcR,EAAsB,QAAQ;AA0BhE,IAAae,IAAmBhB,EAAM,YAGnC,EAAE,cAAW,GAAGS,KAAS,MAC3B,kBAACR,EAAsB,MAAvB;CACC,0BAAuB;CAClB;CACL,WAAWgB,EACVH,EACC,sFACAC,CACD,CACD;CACA,GAAIN;AACJ,CAAA,CACD;AACD,EAAiB,cAAcR,EAAsB,KAAK"}
|
|
1
|
+
{"version":3,"file":"dropdown-menu.js","names":["React","DropdownMenuPrimitive","DropdownMenu","DropdownMenuTrigger","DropdownMenuGroup","DropdownMenuPortal","DropdownMenuSub","DropdownMenuRadioGroup","DropdownMenuContent","props","highlightRef","useHoverHighlight","ref","overlayPanelClass","cn","className","DropdownMenuItem","overlayItemClass"],"sources":["../../src/components/dropdown-menu.tsx"],"sourcesContent":["import * as DropdownMenuPrimitive from \"@radix-ui/react-dropdown-menu\";\nimport * as React from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { useHoverHighlight } from \"../utils/use-hover-highlight\";\nimport { MENU_GAP, overlayItemClass, overlayPanelClass } from \"./overlay\";\n\ntype RadixDropdownMenuProps = React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Root>;\ntype RadixDropdownMenuTriggerProps = React.ComponentPropsWithoutRef<\n\ttypeof DropdownMenuPrimitive.Trigger\n>;\ntype RadixDropdownMenuGroupProps = React.ComponentPropsWithoutRef<\n\ttypeof DropdownMenuPrimitive.Group\n>;\ntype RadixDropdownMenuPortalProps = React.ComponentPropsWithoutRef<\n\ttypeof DropdownMenuPrimitive.Portal\n>;\ntype RadixDropdownMenuSubProps = React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Sub>;\ntype RadixDropdownMenuRadioGroupProps = React.ComponentPropsWithoutRef<\n\ttypeof DropdownMenuPrimitive.RadioGroup\n>;\ntype RadixDropdownMenuContentProps = React.ComponentPropsWithoutRef<\n\ttypeof DropdownMenuPrimitive.Content\n>;\ntype RadixDropdownMenuItemProps = React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item>;\n\nexport interface DropdownMenuProps\n\textends Omit<\n\t\tRadixDropdownMenuProps,\n\t\t\"open\" | \"defaultOpen\" | \"onOpenChange\" | \"dir\" | \"modal\" | \"children\"\n\t> {\n\t/**\n\t * Structure elements comprising the dropdown menu, typically trigger and content.\n\t */\n\tchildren?: React.ReactNode;\n\t/**\n\t * The controlled open state of the dropdown menu.\n\t */\n\topen?: RadixDropdownMenuProps[\"open\"];\n\t/**\n\t * The uncontrolled initial open state of the dropdown menu.\n\t * @default false\n\t */\n\tdefaultOpen?: RadixDropdownMenuProps[\"defaultOpen\"];\n\t/**\n\t * Called when the open state changes.\n\t */\n\tonOpenChange?: RadixDropdownMenuProps[\"onOpenChange\"];\n\t/**\n\t * The reading direction of the dropdown menu. Inherited from DirectionProvider if present,\n\t * or defaults to \"ltr\".\n\t * @default \"ltr\"\n\t */\n\tdir?: RadixDropdownMenuProps[\"dir\"];\n\t/**\n\t * The modality of the dropdown menu. When set to true, interaction with outside elements\n\t * will be disabled and only menu content will be visible to screen readers.\n\t * @default true\n\t */\n\tmodal?: RadixDropdownMenuProps[\"modal\"];\n}\n\nexport const DropdownMenu: React.FC<DropdownMenuProps> = DropdownMenuPrimitive.Root;\n\nexport interface DropdownMenuTriggerProps\n\textends Omit<RadixDropdownMenuTriggerProps, \"asChild\" | \"children\"> {\n\t/**\n\t * Trigger element content.\n\t */\n\tchildren?: React.ReactNode;\n\t/**\n\t * Change the default rendered button element to the child element, merging props and behavior.\n\t * DropdownMenuTrigger forwards ref to HTMLButtonElement and inherits native button attributes.\n\t * @default false\n\t */\n\tasChild?: RadixDropdownMenuTriggerProps[\"asChild\"];\n}\n\nexport const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;\n\nexport interface DropdownMenuGroupProps\n\textends Omit<RadixDropdownMenuGroupProps, \"asChild\" | \"children\"> {\n\t/**\n\t * Menu items or elements grouped together.\n\t */\n\tchildren?: React.ReactNode;\n\t/**\n\t * Change the default rendered div element to the child element, merging props and behavior.\n\t * DropdownMenuGroup forwards ref to HTMLDivElement and inherits native div attributes.\n\t * @default false\n\t */\n\tasChild?: RadixDropdownMenuGroupProps[\"asChild\"];\n}\n\nexport const DropdownMenuGroup = DropdownMenuPrimitive.Group;\n\nexport interface DropdownMenuPortalProps\n\textends Omit<RadixDropdownMenuPortalProps, \"container\" | \"forceMount\" | \"children\"> {\n\t/**\n\t * Content to render into the portal target.\n\t */\n\tchildren?: React.ReactNode;\n\t/**\n\t * Specify a container element to portal the content into.\n\t * Note: Only controls direct portal children; does not override the destination\n\t * container of the built-in portal inside DropdownMenuContent.\n\t */\n\tcontainer?: RadixDropdownMenuPortalProps[\"container\"];\n\t/**\n\t * Used to force mounting when more control is needed. Useful when\n\t * controlling animation with React animation libraries.\n\t */\n\tforceMount?: RadixDropdownMenuPortalProps[\"forceMount\"];\n}\n\nexport const DropdownMenuPortal = DropdownMenuPrimitive.Portal;\n\nexport interface DropdownMenuSubProps\n\textends Omit<RadixDropdownMenuSubProps, \"open\" | \"defaultOpen\" | \"onOpenChange\" | \"children\"> {\n\t/**\n\t * Submenu structure elements.\n\t * Note: Basalt does not export styled DropdownMenuSubTrigger or DropdownMenuSubContent components;\n\t * compose with underlying Radix primitives when building nested submenus.\n\t */\n\tchildren?: React.ReactNode;\n\t/**\n\t * The controlled open state of the submenu.\n\t */\n\topen?: RadixDropdownMenuSubProps[\"open\"];\n\t/**\n\t * The uncontrolled initial open state of the submenu.\n\t * @default false\n\t */\n\tdefaultOpen?: RadixDropdownMenuSubProps[\"defaultOpen\"];\n\t/**\n\t * Event handler called when the open state of the submenu changes.\n\t */\n\tonOpenChange?: RadixDropdownMenuSubProps[\"onOpenChange\"];\n}\n\nexport const DropdownMenuSub = DropdownMenuPrimitive.Sub;\n\nexport interface DropdownMenuRadioGroupProps\n\textends Omit<\n\t\tRadixDropdownMenuRadioGroupProps,\n\t\t\"value\" | \"onValueChange\" | \"asChild\" | \"children\"\n\t> {\n\t/**\n\t * Radio item elements grouped together.\n\t * Note: Basalt does not export styled DropdownMenuRadioItem or indicator components;\n\t * compose with underlying Radix primitives when building radio selection groups.\n\t */\n\tchildren?: React.ReactNode;\n\t/**\n\t * The value of the currently selected radio item.\n\t */\n\tvalue?: RadixDropdownMenuRadioGroupProps[\"value\"];\n\t/**\n\t * Event handler called when the value changes.\n\t */\n\tonValueChange?: RadixDropdownMenuRadioGroupProps[\"onValueChange\"];\n\t/**\n\t * Change the default rendered div element to the child element, merging props and behavior.\n\t * DropdownMenuRadioGroup forwards ref to HTMLDivElement and inherits native div attributes.\n\t * @default false\n\t */\n\tasChild?: RadixDropdownMenuRadioGroupProps[\"asChild\"];\n}\n\nexport const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup;\n\nexport interface DropdownMenuContentProps\n\textends Omit<\n\t\tRadixDropdownMenuContentProps,\n\t\t| \"side\"\n\t\t| \"sideOffset\"\n\t\t| \"align\"\n\t\t| \"alignOffset\"\n\t\t| \"avoidCollisions\"\n\t\t| \"collisionBoundary\"\n\t\t| \"collisionPadding\"\n\t\t| \"arrowPadding\"\n\t\t| \"sticky\"\n\t\t| \"hideWhenDetached\"\n\t\t| \"updatePositionStrategy\"\n\t\t| \"loop\"\n\t\t| \"onCloseAutoFocus\"\n\t\t| \"onEscapeKeyDown\"\n\t\t| \"onPointerDownOutside\"\n\t\t| \"onFocusOutside\"\n\t\t| \"onInteractOutside\"\n\t\t| \"forceMount\"\n\t\t| \"asChild\"\n\t> {\n\t/**\n\t * Preferred placement side relative to trigger.\n\t * @default \"bottom\"\n\t */\n\tside?: RadixDropdownMenuContentProps[\"side\"];\n\t/**\n\t * Distance in pixels between trigger and floating content panel.\n\t * In Basalt, defaults to MENU_GAP (8).\n\t * @default 8\n\t */\n\tsideOffset?: RadixDropdownMenuContentProps[\"sideOffset\"];\n\t/**\n\t * Preferred alignment along the side axis.\n\t * @default \"center\"\n\t */\n\talign?: RadixDropdownMenuContentProps[\"align\"];\n\t/**\n\t * Offset in pixels from the start or end alignment position.\n\t * @default 0\n\t */\n\talignOffset?: RadixDropdownMenuContentProps[\"alignOffset\"];\n\t/**\n\t * Whether to reposition content to avoid viewport boundary collisions.\n\t * @default true\n\t */\n\tavoidCollisions?: RadixDropdownMenuContentProps[\"avoidCollisions\"];\n\t/**\n\t * Element or elements bounding boundary collision calculations.\n\t * @default []\n\t */\n\tcollisionBoundary?: RadixDropdownMenuContentProps[\"collisionBoundary\"];\n\t/**\n\t * Virtual padding from collision boundaries in pixels.\n\t * @default 0\n\t */\n\tcollisionPadding?: RadixDropdownMenuContentProps[\"collisionPadding\"];\n\t/**\n\t * Padding in pixels between popper arrow and floating panel edge.\n\t * @default 0\n\t */\n\tarrowPadding?: RadixDropdownMenuContentProps[\"arrowPadding\"];\n\t/**\n\t * Sticky positioning behavior along the align axis when overflowing.\n\t * @default \"partial\"\n\t */\n\tsticky?: RadixDropdownMenuContentProps[\"sticky\"];\n\t/**\n\t * Whether to hide content completely when trigger is fully occluded.\n\t * @default false\n\t */\n\thideWhenDetached?: RadixDropdownMenuContentProps[\"hideWhenDetached\"];\n\t/**\n\t * Strategy used to calculate and update popper position.\n\t * @default \"optimized\"\n\t */\n\tupdatePositionStrategy?: RadixDropdownMenuContentProps[\"updatePositionStrategy\"];\n\t/**\n\t * Whether keyboard navigation should loop around item boundaries.\n\t * @default false\n\t */\n\tloop?: RadixDropdownMenuContentProps[\"loop\"];\n\t/**\n\t * Callback fired when auto-focusing on close. Can be prevented.\n\t */\n\tonCloseAutoFocus?: RadixDropdownMenuContentProps[\"onCloseAutoFocus\"];\n\t/**\n\t * Callback fired when the Escape key is down on the content layer. Can be prevented.\n\t */\n\tonEscapeKeyDown?: RadixDropdownMenuContentProps[\"onEscapeKeyDown\"];\n\t/**\n\t * Callback fired when a pointerdown event happens outside the bounds of the content. Can be prevented.\n\t */\n\tonPointerDownOutside?: RadixDropdownMenuContentProps[\"onPointerDownOutside\"];\n\t/**\n\t * Callback fired when focus moves outside the bounds of the content. Can be prevented.\n\t */\n\tonFocusOutside?: RadixDropdownMenuContentProps[\"onFocusOutside\"];\n\t/**\n\t * Callback fired when an interaction (pointerdown or focus) happens outside the bounds of the content. Can be prevented.\n\t */\n\tonInteractOutside?: RadixDropdownMenuContentProps[\"onInteractOutside\"];\n\t/**\n\t * Force mounting content in DOM for external animation controls.\n\t * When forceMount is true, the content remains mounted even when closed.\n\t * The caller is responsible for visibility transitions and unmounting after animation completes.\n\t * Note: Keeping modal content forceMounted may isolate background interactions until unmounted.\n\t */\n\tforceMount?: true;\n\t/**\n\t * Change the default rendered div element to the child element, merging props and behavior.\n\t * DropdownMenuContent forwards ref to HTMLDivElement and inherits native div attributes.\n\t * @default false\n\t */\n\tasChild?: RadixDropdownMenuContentProps[\"asChild\"];\n}\n\nexport const DropdownMenuContent = React.forwardRef<\n\tReact.ElementRef<typeof DropdownMenuPrimitive.Content>,\n\tDropdownMenuContentProps\n>(({ className, sideOffset = MENU_GAP, ...props }, ref) => {\n\tconst highlightRef = useHoverHighlight(ref);\n\treturn (\n\t\t<DropdownMenuPrimitive.Portal forceMount={props.forceMount}>\n\t\t\t<DropdownMenuPrimitive.Content\n\t\t\t\tref={highlightRef}\n\t\t\t\tsideOffset={sideOffset}\n\t\t\t\tclassName={overlayPanelClass(cn(\"basalt-hover-list min-w-basalt-40\", className))}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t</DropdownMenuPrimitive.Portal>\n\t);\n});\nDropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;\n\nexport interface DropdownMenuItemProps\n\textends Omit<RadixDropdownMenuItemProps, \"disabled\" | \"onSelect\" | \"textValue\" | \"asChild\"> {\n\t/**\n\t * Disable the menu item.\n\t * @default false\n\t */\n\tdisabled?: RadixDropdownMenuItemProps[\"disabled\"];\n\t/**\n\t * Event handler called when the menu item is selected (via click or keyboard).\n\t * Note that this is a Radix CustomEvent, not native DOM onSelect.\n\t */\n\tonSelect?: RadixDropdownMenuItemProps[\"onSelect\"];\n\t/**\n\t * Optional text used for typeahead navigation. By default typeahead uses item text content.\n\t */\n\ttextValue?: RadixDropdownMenuItemProps[\"textValue\"];\n\t/**\n\t * Change the default rendered div element to the child element, merging props and behavior.\n\t * DropdownMenuItem forwards ref to HTMLDivElement and inherits native div attributes.\n\t * @default false\n\t */\n\tasChild?: RadixDropdownMenuItemProps[\"asChild\"];\n}\n\nexport const DropdownMenuItem = React.forwardRef<\n\tReact.ElementRef<typeof DropdownMenuPrimitive.Item>,\n\tDropdownMenuItemProps\n>(({ className, ...props }, ref) => (\n\t<DropdownMenuPrimitive.Item\n\t\tdata-basalt-hover-item=\"\"\n\t\tref={ref}\n\t\tclassName={overlayItemClass(\n\t\t\tcn(\"relative data-disabled:pointer-events-none data-disabled:opacity-50\", className),\n\t\t)}\n\t\t{...props}\n\t/>\n));\nDropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;\n"],"mappings":";;;;;;;;AA6DA,IAAaE,IAA4CD,EAAsB,MAgBlEE,IAAsBF,EAAsB,SAgB5CG,IAAoBH,EAAsB,OAqB1CI,IAAqBJ,EAAsB,QAyB3CK,IAAkBL,EAAsB,KA6BxCM,IAAyBN,EAAsB,YAyH/CO,IAAsBR,EAAM,YAGtC,EAAE,cAAW,gBAAA,GAAuB,GAAGS,KAAS,MAAQ;CAC1D,IAAMC,IAAeC,EAAkBC,CAAG;CAC1C,OACC,kBAACX,EAAsB,QAAvB;EAA8B,YAAYQ,EAAM;EAC/C,UAAA,kBAACR,EAAsB,SAAvB;GACC,KAAKS;GACO;GACZ,WAAWG,EAAkBC,EAAG,qCAAqCC,CAAS,CAAC;GAC/E,GAAIN;EACJ,CAAA;CAC4B,CAAA;AAEhC,CAAC;AACD,EAAoB,cAAcR,EAAsB,QAAQ;AA0BhE,IAAae,IAAmBhB,EAAM,YAGnC,EAAE,cAAW,GAAGS,KAAS,MAC3B,kBAACR,EAAsB,MAAvB;CACC,0BAAuB;CAClB;CACL,WAAWgB,EACVH,EAAG,uEAAuEC,CAAS,CACpF;CACA,GAAIN;AACJ,CAAA,CACD;AACD,EAAiB,cAAcR,EAAsB,KAAK"}
|
|
@@ -49,13 +49,13 @@ function g({ label: d, href: g, onSelect: _, selected: v = !1, icon: y, count: b
|
|
|
49
49
|
M.current = !e && t !== "blur", k(e);
|
|
50
50
|
}
|
|
51
51
|
}) : /* @__PURE__ */ h("div", {
|
|
52
|
-
className: "flex min-w-0 items-center gap-basalt-
|
|
52
|
+
className: "basalt-nav-actions flex min-w-0 items-center gap-basalt-space-xs",
|
|
53
53
|
children: [
|
|
54
54
|
/* @__PURE__ */ m(r, {
|
|
55
55
|
asChild: !!g,
|
|
56
56
|
variant: "ghost",
|
|
57
57
|
disabled: C,
|
|
58
|
-
className: e(a, n, "h-auto flex-1 justify-start hover:bg-transparent hover:border-transparent
|
|
58
|
+
className: e(a, n, "h-auto flex-1 justify-start hover:bg-transparent hover:border-transparent"),
|
|
59
59
|
"aria-current": v ? "page" : void 0,
|
|
60
60
|
"aria-label": d,
|
|
61
61
|
"aria-describedby": b == null ? void 0 : A,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"editable-nav-item.js","names":["_Fragment","Fragment$1","EditableNavItem","editing","setEditing","useState","countId","useId","rename","useRef","restore","content","icon","label","count","selected","disabled","cn","BASALT_UI_CLASS","className","onRename","InlineEditable","renameLabel","next","reason","Button","href","NAV_ROW_CLASS","FOCUS_INSET","onSelect","Link","Pencil","actions","FolderNavItem","Folder","props"],"sources":["../../src/components/editable-nav-item.tsx"],"sourcesContent":["import { Folder, Pencil } from \"lucide-react\";\nimport { type ReactNode, useId, useLayoutEffect, useRef, useState } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { BASALT_UI_CLASS } from \"../utils/control-surface\";\nimport { NAV_ROW_CLASS } from \"../utils/navigation\";\nimport { Button } from \"./button\";\nimport { InlineEditable } from \"./inline-editable\";\nimport { Link } from \"./link\";\nimport { FOCUS_INSET } from \"./overlay\";\n\nexport interface EditableNavItemProps {\n\t/** Current display name. */\n\tlabel: string;\n\t/** Application route, interpreted by LinkProvider. */\n\thref?: string;\n\t/** Navigation/selection request. */\n\tonSelect?: () => void;\n\t/** Selected location. @default false */\n\tselected?: boolean;\n\t/** Caller-owned leading icon. */\n\ticon?: ReactNode;\n\t/** Caller-formatted count or status. */\n\tcount?: ReactNode;\n\t/** Separate row actions, never nested inside the navigation button/link. */\n\tactions?: ReactNode;\n\t/** Enable renaming; rejected promises keep the editor and draft available. */\n\tonRename?: (name: string) => void | Promise<void>;\n\t/** Disable navigation and renaming. Application action slots retain their own permissions. @default false */\n\tdisabled?: boolean;\n\t/** Rename action prefix. @default \"Rename\" */\n\trenameLabel?: string;\n\t/** Accessible save action. @default \"Save\" */\n\tsaveLabel?: string;\n\t/** Accessible cancel action. @default \"Cancel\" */\n\tcancelLabel?: string;\n\t/** Additional root classes. */\n\tclassName?: string;\n}\nexport function EditableNavItem({\n\tlabel,\n\thref,\n\tonSelect,\n\tselected = false,\n\ticon,\n\tcount,\n\tactions,\n\tonRename,\n\tdisabled = false,\n\trenameLabel = \"Rename\",\n\tsaveLabel = \"Save\",\n\tcancelLabel = \"Cancel\",\n\tclassName,\n}: EditableNavItemProps) {\n\tconst [editing, setEditing] = useState(false);\n\tconst countId = useId();\n\tconst rename = useRef<HTMLButtonElement>(null);\n\tconst restore = useRef(false);\n\tuseLayoutEffect(() => {\n\t\tif (!editing && restore.current) {\n\t\t\trestore.current = false;\n\t\t\trename.current?.focus();\n\t\t}\n\t}, [editing]);\n\tconst content = (\n\t\t<>\n\t\t\t{icon && (\n\t\t\t\t<span\n\t\t\t\t\tclassName=\"flex size-basalt-icon-lg shrink-0 items-center justify-center [&>svg]:size-basalt-icon-lg\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t>\n\t\t\t\t\t{icon}\n\t\t\t\t</span>\n\t\t\t)}\n\t\t\t<span className=\"min-w-0 flex-1 truncate text-left\">{label}</span>\n\t\t\t{count != null && (\n\t\t\t\t<span\n\t\t\t\t\tid={countId}\n\t\t\t\t\tclassName=\"shrink-0 text-basalt-sm tabular-nums text-basalt-muted-foreground\"\n\t\t\t\t>\n\t\t\t\t\t{\" \"}\n\t\t\t\t\t{count}\n\t\t\t\t</span>\n\t\t\t)}\n\t\t</>\n\t);\n\treturn (\n\t\t<div\n\t\t\tdata-basalt-hover-item={editing ? undefined : \"\"}\n\t\t\tdata-hover-selected={selected && !editing}\n\t\t\tdata-disabled={disabled ? \"\" : undefined}\n\t\t\tclassName={cn(\n\t\t\t\tBASALT_UI_CLASS,\n\t\t\t\t\"basalt-nav-item min-w-0 shrink-0 rounded-basalt-md data-disabled:cursor-default data-disabled:hover:bg-transparent\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t>\n\t\t\t{editing && onRename ? (\n\t\t\t\t<InlineEditable\n\t\t\t\t\tclassName=\"p-basalt-space-lg\"\n\t\t\t\t\tlabel={`${renameLabel} ${label}`}\n\t\t\t\t\tvalue={label}\n\t\t\t\t\tediting\n\t\t\t\t\tonSave={onRename}\n\t\t\t\t\tsaveLabel={saveLabel}\n\t\t\t\t\tcancelLabel={cancelLabel}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\tonEditingChange={(next, reason) => {\n\t\t\t\t\t\trestore.current = !next && reason !== \"blur\";\n\t\t\t\t\t\tsetEditing(next);\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t) : (\n\t\t\t\t<div className=\"flex min-w-0 items-center gap-basalt-
|
|
1
|
+
{"version":3,"file":"editable-nav-item.js","names":["_Fragment","Fragment$1","EditableNavItem","editing","setEditing","useState","countId","useId","rename","useRef","restore","content","icon","label","count","selected","disabled","cn","BASALT_UI_CLASS","className","onRename","InlineEditable","renameLabel","next","reason","Button","href","NAV_ROW_CLASS","FOCUS_INSET","onSelect","Link","Pencil","actions","FolderNavItem","Folder","props"],"sources":["../../src/components/editable-nav-item.tsx"],"sourcesContent":["import { Folder, Pencil } from \"lucide-react\";\nimport { type ReactNode, useId, useLayoutEffect, useRef, useState } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { BASALT_UI_CLASS } from \"../utils/control-surface\";\nimport { NAV_ROW_CLASS } from \"../utils/navigation\";\nimport { Button } from \"./button\";\nimport { InlineEditable } from \"./inline-editable\";\nimport { Link } from \"./link\";\nimport { FOCUS_INSET } from \"./overlay\";\n\nexport interface EditableNavItemProps {\n\t/** Current display name. */\n\tlabel: string;\n\t/** Application route, interpreted by LinkProvider. */\n\thref?: string;\n\t/** Navigation/selection request. */\n\tonSelect?: () => void;\n\t/** Selected location. @default false */\n\tselected?: boolean;\n\t/** Caller-owned leading icon. */\n\ticon?: ReactNode;\n\t/** Caller-formatted count or status. */\n\tcount?: ReactNode;\n\t/** Separate row actions, never nested inside the navigation button/link. */\n\tactions?: ReactNode;\n\t/** Enable renaming; rejected promises keep the editor and draft available. */\n\tonRename?: (name: string) => void | Promise<void>;\n\t/** Disable navigation and renaming. Application action slots retain their own permissions. @default false */\n\tdisabled?: boolean;\n\t/** Rename action prefix. @default \"Rename\" */\n\trenameLabel?: string;\n\t/** Accessible save action. @default \"Save\" */\n\tsaveLabel?: string;\n\t/** Accessible cancel action. @default \"Cancel\" */\n\tcancelLabel?: string;\n\t/** Additional root classes. */\n\tclassName?: string;\n}\nexport function EditableNavItem({\n\tlabel,\n\thref,\n\tonSelect,\n\tselected = false,\n\ticon,\n\tcount,\n\tactions,\n\tonRename,\n\tdisabled = false,\n\trenameLabel = \"Rename\",\n\tsaveLabel = \"Save\",\n\tcancelLabel = \"Cancel\",\n\tclassName,\n}: EditableNavItemProps) {\n\tconst [editing, setEditing] = useState(false);\n\tconst countId = useId();\n\tconst rename = useRef<HTMLButtonElement>(null);\n\tconst restore = useRef(false);\n\tuseLayoutEffect(() => {\n\t\tif (!editing && restore.current) {\n\t\t\trestore.current = false;\n\t\t\trename.current?.focus();\n\t\t}\n\t}, [editing]);\n\tconst content = (\n\t\t<>\n\t\t\t{icon && (\n\t\t\t\t<span\n\t\t\t\t\tclassName=\"flex size-basalt-icon-lg shrink-0 items-center justify-center [&>svg]:size-basalt-icon-lg\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t>\n\t\t\t\t\t{icon}\n\t\t\t\t</span>\n\t\t\t)}\n\t\t\t<span className=\"min-w-0 flex-1 truncate text-left\">{label}</span>\n\t\t\t{count != null && (\n\t\t\t\t<span\n\t\t\t\t\tid={countId}\n\t\t\t\t\tclassName=\"shrink-0 text-basalt-sm tabular-nums text-basalt-muted-foreground\"\n\t\t\t\t>\n\t\t\t\t\t{\" \"}\n\t\t\t\t\t{count}\n\t\t\t\t</span>\n\t\t\t)}\n\t\t</>\n\t);\n\treturn (\n\t\t<div\n\t\t\tdata-basalt-hover-item={editing ? undefined : \"\"}\n\t\t\tdata-hover-selected={selected && !editing}\n\t\t\tdata-disabled={disabled ? \"\" : undefined}\n\t\t\tclassName={cn(\n\t\t\t\tBASALT_UI_CLASS,\n\t\t\t\t\"basalt-nav-item min-w-0 shrink-0 rounded-basalt-md data-disabled:cursor-default data-disabled:hover:bg-transparent\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t>\n\t\t\t{editing && onRename ? (\n\t\t\t\t<InlineEditable\n\t\t\t\t\tclassName=\"p-basalt-space-lg\"\n\t\t\t\t\tlabel={`${renameLabel} ${label}`}\n\t\t\t\t\tvalue={label}\n\t\t\t\t\tediting\n\t\t\t\t\tonSave={onRename}\n\t\t\t\t\tsaveLabel={saveLabel}\n\t\t\t\t\tcancelLabel={cancelLabel}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\tonEditingChange={(next, reason) => {\n\t\t\t\t\t\trestore.current = !next && reason !== \"blur\";\n\t\t\t\t\t\tsetEditing(next);\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t) : (\n\t\t\t\t<div className=\"basalt-nav-actions flex min-w-0 items-center gap-basalt-space-xs\">\n\t\t\t\t\t<Button\n\t\t\t\t\t\tasChild={!!href}\n\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\tNAV_ROW_CLASS,\n\t\t\t\t\t\t\tFOCUS_INSET,\n\t\t\t\t\t\t\t\"h-auto flex-1 justify-start hover:bg-transparent hover:border-transparent\",\n\t\t\t\t\t\t)}\n\t\t\t\t\t\taria-current={selected ? \"page\" : undefined}\n\t\t\t\t\t\taria-label={label}\n\t\t\t\t\t\taria-describedby={count != null ? countId : undefined}\n\t\t\t\t\t\tonClick={onSelect}\n\t\t\t\t\t>\n\t\t\t\t\t\t{href ? (\n\t\t\t\t\t\t\t<Link href={href} className=\"text-inherit no-underline hover:no-underline\">\n\t\t\t\t\t\t\t\t{content}\n\t\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\tcontent\n\t\t\t\t\t\t)}\n\t\t\t\t\t</Button>\n\t\t\t\t\t{onRename && (\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\tref={rename}\n\t\t\t\t\t\t\tsize=\"icon\"\n\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t\taria-label={`${renameLabel} ${label}`}\n\t\t\t\t\t\t\tonClick={() => setEditing(true)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<Pencil />\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t)}\n\t\t\t\t\t{actions && (\n\t\t\t\t\t\t<div className=\"flex shrink-0 items-center gap-basalt-space-sm\">{actions}</div>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n\nexport type FolderNavItemProps = EditableNavItemProps;\n/** Folder presentation with an overridable icon; no tree, router or permission model. */\nexport function FolderNavItem({\n\ticon = <Folder className=\"size-basalt-icon-lg\" />,\n\t...props\n}: FolderNavItemProps) {\n\treturn <EditableNavItem icon={icon} {...props} />;\n}\n"],"mappings":";;;;;;;;;;;;AAsCA,SAAgBE,EAAgB,EAC/B,UACA,SACA,aACA,cAAW,IACX,SACA,UACA,YACA,aACA,cAAW,IACX,iBAAc,UACd,eAAY,QACZ,iBAAc,UACd,gBACwB;CACxB,IAAM,CAACC,GAASC,KAAcC,EAAS,EAAK,GACtCC,IAAUC,EAAM,GAChBC,IAASC,EAA0B,IAAI,GACvCC,IAAUD,EAAO,EAAK;CAC5B,QAAsB;EACrB,AAAI,CAACN,KAAWO,EAAQ,YACvB,EAAQ,UAAU,IAClBF,EAAO,SAAS,MAAM;CAExB,GAAG,CAACL,CAAO,CAAC;CACZ,IAAMQ,IACL,kBAAAX,GAAA,EAAA,UAAA;EACEY,KACA,kBAAC,QAAD;GACC,WAAU;GACV,eAAY;GAEX,UAAAA;EACI,CAAA;EAEP,kBAAC,QAAD;GAAM,WAAU;GAAqC,UAAAC;EAAY,CAAA;EAChEC,KAAS,QACT,kBAAC,QAAD;GACC,IAAIR;GACJ,WAAU;GAFX,UAAA,CAIE,KACAQ,CACI;;CAEN,EAAA,CAAA;CAEH,OACC,kBAAC,OAAD;EACC,0BAAwBX,IAAU,KAAA,IAAY;EAC9C,uBAAqBY,KAAY,CAACZ;EAClC,iBAAea,IAAW,KAAK,KAAA;EAC/B,WAAWC,EACVC,GACA,sHACAC,CACD;EAEC,UAAAhB,KAAWiB,IACX,kBAACC,GAAD;GACC,WAAU;GACV,OAAO,GAAGC,EAAY,GAAGT;GACzB,OAAOA;GACP,SAAA;GACA,QAAQO;GACG;GACE;GACH;GACV,kBAAkB,GAAM,MAAW;IAElC,AADA,EAAQ,UAAU,CAACG,KAAQC,MAAW,QACtCpB,EAAWmB,CAAI;GAChB;EACA,CAAA,IAED,kBAAC,OAAD;GAAK,WAAU;GAAf,UAAA;IACC,kBAACE,GAAD;KACC,SAAS,CAAC,CAACC;KACX,SAAQ;KACE;KACV,WAAWT,EACVU,GACAC,GACA,2EACD;KACA,gBAAcb,IAAW,SAAS,KAAA;KAClC,cAAYF;KACZ,oBAAkBC,KAAS,OAAiB,KAAA,IAAVR;KAClC,SAASuB;KAER,UAAAH,IACA,kBAACI,GAAD;MAAY;MAAM,WAAU;MAC1B,UAAAnB;KACI,CAAA,IAENA;IAEM,CAAA;IACPS,KACA,kBAACK,GAAD;KACC,KAAKjB;KACL,MAAK;KACL,SAAQ;KACE;KACV,cAAY,GAAGc,EAAY,GAAGT;KAC9B,eAAeT,EAAW,EAAI;KAE9B,UAAA,kBAAC2B,GAAD,CAAS,CAAA;IACF,CAAA;IAERC,KACA,kBAAC,OAAD;KAAK,WAAU;KAAkD,UAAAA;IAAa,CAAA;GAE3E;;CAEF,CAAA;AAEP;AAIA,SAAgBC,EAAc,EAC7B,UAAO,kBAACC,GAAD,EAAQ,WAAU,sBAAuB,CAAA,GAChD,GAAGC,KACmB;CACtB,OAAO,kBAACjC,GAAD;EAAuB;EAAM,GAAIiC;CAAQ,CAAA;AACjD"}
|
|
@@ -65,7 +65,7 @@ function u({ label: u, description: d, accept: f = "", multiple: p = !0, maxFile
|
|
|
65
65
|
onDrop: (e) => {
|
|
66
66
|
e.preventDefault(), e.stopPropagation(), T.current = 0, D(!1), j(Array.from(e.dataTransfer.files));
|
|
67
67
|
},
|
|
68
|
-
className: e("flex w-full min-w-0 flex-col items-center gap-basalt-space-lg rounded-basalt-lg border-2 border-dashed px-basalt-card py-basalt-card text-center transition-colors basalt-motion
|
|
68
|
+
className: e("basalt-focus flex w-full min-w-0 flex-col items-center gap-basalt-space-lg rounded-basalt-lg border-2 border-dashed px-basalt-card py-basalt-card text-center transition-colors basalt-motion disabled:cursor-not-allowed disabled:opacity-50", E && !_ ? "border-basalt-primary bg-basalt-selected" : "border-basalt-border bg-basalt-control hover:bg-basalt-hover"),
|
|
69
69
|
children: [
|
|
70
70
|
/* @__PURE__ */ o(a, {
|
|
71
71
|
className: "size-basalt-icon-display text-basalt-muted-foreground",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-dropzone.js","names":["accepts","rules","accept","rule","file","REASONS","FileDropzone","input","useRef","depth","dragging","setDragging","useState","rejections","setRejections","id","useId","receive","disabled","accepted","rejected","limit","multiple","maxFiles","files","code","maxSize","fileCount","onFilesAccepted","onFilesRejected","label","cn","BASALT_UI_CLASS","className","event","browseLabel","description","Upload","dropLabel","formatRejection","item","index"],"sources":["../../src/components/file-dropzone.tsx"],"sourcesContent":["import { Upload } from \"lucide-react\";\nimport { useId, useRef, useState } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { BASALT_UI_CLASS } from \"../utils/control-surface\";\n\nexport interface FileRejection {\n\t/** Original File; the component never creates preview URLs. */\n\tfile: File;\n\t/** Machine-readable reason for application handling. */\n\tcode: \"file-invalid-type\" | \"file-too-large\" | \"too-many-files\";\n}\n\nexport interface FileDropzoneProps {\n\t/** Visible and accessible upload field name. */\n\tlabel: string;\n\t/** Optional file requirements shown under the label. */\n\tdescription?: string;\n\t/** Accepted extensions/MIME types using native accept syntax, e.g. .pdf,image/*. */\n\taccept?: string;\n\t/** Allow multiple files. @default true */\n\tmultiple?: boolean;\n\t/** Maximum accepted file count including fileCount. @default Infinity */\n\tmaxFiles?: number;\n\t/** Number already held by the application. @default 0 */\n\tfileCount?: number;\n\t/** Maximum size of an individual file in bytes. @default Infinity */\n\tmaxSize?: number;\n\t/** Prevent both file browsing and drops. @default false */\n\tdisabled?: boolean;\n\t/** Accepted files from this gesture; transport and queue ownership belong to the caller. */\n\tonFilesAccepted: (files: File[]) => void;\n\t/** Rejected files from this gesture, with one primary reason per file. */\n\tonFilesRejected?: (rejections: FileRejection[]) => void;\n\t/** Browse action text. @default \"Browse files\" */\n\tbrowseLabel?: string;\n\t/** Text while a file is dragged over the field. @default \"Drop files here\" */\n\tdropLabel?: string;\n\t/** Localized rejection message; defaults to a name and reason. */\n\tformatRejection?: (rejection: FileRejection) => string;\n\t/** Additional root classes. */\n\tclassName?: string;\n}\n\nfunction accepts(file: File, accept: string) {\n\tconst rules = accept\n\t\t.split(\",\")\n\t\t.map((rule) => rule.trim().toLowerCase())\n\t\t.filter(Boolean);\n\treturn (\n\t\trules.length === 0 ||\n\t\trules.some((rule) =>\n\t\t\trule.startsWith(\".\")\n\t\t\t\t? file.name.toLowerCase().endsWith(rule)\n\t\t\t\t: rule.endsWith(\"/*\")\n\t\t\t\t\t? file.type.toLowerCase().startsWith(rule.slice(0, -1))\n\t\t\t\t\t: file.type.toLowerCase() === rule,\n\t\t)\n\t);\n}\n\nconst REASONS = {\n\t\"file-invalid-type\": \"File type is not accepted.\",\n\t\"file-too-large\": \"File exceeds the size limit.\",\n\t\"too-many-files\": \"File count limit reached.\",\n};\n\nexport function FileDropzone({\n\tlabel,\n\tdescription,\n\taccept = \"\",\n\tmultiple = true,\n\tmaxFiles = Infinity,\n\tfileCount = 0,\n\tmaxSize = Infinity,\n\tdisabled = false,\n\tonFilesAccepted,\n\tonFilesRejected,\n\tbrowseLabel = \"Browse files\",\n\tdropLabel = \"Drop files here\",\n\tformatRejection,\n\tclassName,\n}: FileDropzoneProps) {\n\tconst input = useRef<HTMLInputElement>(null);\n\tconst depth = useRef(0);\n\tconst [dragging, setDragging] = useState(false);\n\tconst [rejections, setRejections] = useState<FileRejection[]>([]);\n\tconst id = useId();\n\tfunction receive(files: File[]) {\n\t\tif (disabled) return;\n\t\tconst accepted: File[] = [];\n\t\tconst rejected: FileRejection[] = [];\n\t\tconst limit = Math.max(0, multiple ? maxFiles : Math.min(1, maxFiles));\n\t\tfor (const file of files) {\n\t\t\tconst code = !accepts(file, accept)\n\t\t\t\t? \"file-invalid-type\"\n\t\t\t\t: file.size > maxSize\n\t\t\t\t\t? \"file-too-large\"\n\t\t\t\t\t: accepted.length + fileCount >= limit\n\t\t\t\t\t\t? \"too-many-files\"\n\t\t\t\t\t\t: null;\n\t\t\tif (code) rejected.push({ file, code });\n\t\t\telse accepted.push(file);\n\t\t}\n\t\tsetRejections(rejected);\n\t\tif (accepted.length) onFilesAccepted(accepted);\n\t\tif (rejected.length) onFilesRejected?.(rejected);\n\t}\n\treturn (\n\t\t<div\n\t\t\trole=\"group\"\n\t\t\taria-label={label}\n\t\t\tclassName={cn(BASALT_UI_CLASS, \"min-w-0 space-y-basalt-space-lg\", className)}\n\t\t>\n\t\t\t<input\n\t\t\t\tref={input}\n\t\t\t\ttype=\"file\"\n\t\t\t\taccept={accept}\n\t\t\t\tmultiple={multiple}\n\t\t\t\tdisabled={disabled}\n\t\t\t\ttabIndex={-1}\n\t\t\t\taria-label={label}\n\t\t\t\tclassName=\"hidden\"\n\t\t\t\tonChange={(event) => {\n\t\t\t\t\treceive(Array.from(event.currentTarget.files ?? []));\n\t\t\t\t\tevent.currentTarget.value = \"\";\n\t\t\t\t}}\n\t\t\t/>\n\t\t\t<button\n\t\t\t\ttype=\"button\"\n\t\t\t\tdisabled={disabled}\n\t\t\t\taria-label={`${browseLabel}: ${label}`}\n\t\t\t\taria-describedby={description ? `${id}-description` : undefined}\n\t\t\t\tdata-drag-active={dragging && !disabled}\n\t\t\t\tonClick={() => input.current?.click()}\n\t\t\t\tonDragEnter={(event) => {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tdepth.current += 1;\n\t\t\t\t\tif (!disabled) setDragging(true);\n\t\t\t\t}}\n\t\t\t\tonDragOver={(event) => {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tif (!disabled) event.dataTransfer.dropEffect = \"copy\";\n\t\t\t\t}}\n\t\t\t\tonDragLeave={(event) => {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tdepth.current = Math.max(0, depth.current - 1);\n\t\t\t\t\tif (depth.current === 0) setDragging(false);\n\t\t\t\t}}\n\t\t\t\tonDrop={(event) => {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\tdepth.current = 0;\n\t\t\t\t\tsetDragging(false);\n\t\t\t\t\treceive(Array.from(event.dataTransfer.files));\n\t\t\t\t}}\n\t\t\t\tclassName={cn(\n\t\t\t\t\t\"flex w-full min-w-0 flex-col items-center gap-basalt-space-lg rounded-basalt-lg border-2 border-dashed px-basalt-card py-basalt-card text-center transition-colors basalt-motion focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-basalt-ring disabled:cursor-not-allowed disabled:opacity-50\",\n\t\t\t\t\tdragging && !disabled\n\t\t\t\t\t\t? \"border-basalt-primary bg-basalt-selected\"\n\t\t\t\t\t\t: \"border-basalt-border bg-basalt-control hover:bg-basalt-hover\",\n\t\t\t\t)}\n\t\t\t>\n\t\t\t\t<Upload\n\t\t\t\t\tclassName=\"size-basalt-icon-display text-basalt-muted-foreground\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t/>\n\t\t\t\t<span className=\"text-basalt-base font-medium\">\n\t\t\t\t\t{dragging && !disabled ? dropLabel : label}\n\t\t\t\t</span>\n\t\t\t\t{description && (\n\t\t\t\t\t<span id={`${id}-description`} className=\"text-basalt-sm text-basalt-muted-foreground\">\n\t\t\t\t\t\t{description}\n\t\t\t\t\t</span>\n\t\t\t\t)}\n\t\t\t\t<span className=\"rounded-basalt-md border border-basalt-border px-basalt-space-lg py-basalt-space-sm text-basalt-sm\">\n\t\t\t\t\t{browseLabel}\n\t\t\t\t</span>\n\t\t\t</button>\n\t\t\t{rejections.length > 0 && (\n\t\t\t\t<ul role=\"alert\" className=\"space-y-basalt-space-sm text-basalt-sm text-basalt-destructive\">\n\t\t\t\t\t{rejections.map((item, index) => (\n\t\t\t\t\t\t<li key={`${item.file.name}-${index}`} className=\"break-words\">\n\t\t\t\t\t\t\t{formatRejection ? formatRejection(item) : `${item.file.name}: ${REASONS[item.code]}`}\n\t\t\t\t\t\t</li>\n\t\t\t\t\t))}\n\t\t\t\t</ul>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n"],"mappings":";;;;;;;AA2CA,SAASA,EAAQ,GAAY,GAAgB;CAC5C,IAAMC,IAAQC,EACZ,MAAM,GAAG,CAAC,CACV,KAAK,MAASC,EAAK,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC,CACxC,OAAO,OAAO;CAChB,OACCF,EAAM,WAAW,KACjBA,EAAM,MAAM,MACXE,EAAK,WAAW,GAAG,IAChBC,EAAK,KAAK,YAAY,CAAC,CAAC,SAASD,CAAI,IACrCA,EAAK,SAAS,IAAI,IACjBC,EAAK,KAAK,YAAY,CAAC,CAAC,WAAWD,EAAK,MAAM,GAAG,EAAE,CAAC,IACpDC,EAAK,KAAK,YAAY,MAAMD,CACjC;AAEF;AAEA,IAAME,IAAU;CACf,qBAAqB;CACrB,kBAAkB;CAClB,kBAAkB;AACnB;AAEA,SAAgBC,EAAa,EAC5B,UACA,gBACA,YAAS,IACT,cAAW,IACX,cAAW,UACX,eAAY,GACZ,aAAU,UACV,cAAW,IACX,oBACA,oBACA,iBAAc,gBACd,eAAY,mBACZ,oBACA,gBACqB;CACrB,IAAMC,IAAQC,EAAyB,IAAI,GACrCC,IAAQD,EAAO,CAAC,GAChB,CAACE,GAAUC,KAAeC,EAAS,EAAK,GACxC,CAACC,GAAYC,KAAiBF,EAA0B,CAAC,CAAC,GAC1DG,IAAKC,EAAM;CACjB,SAASC,EAAQ,GAAe;EAC/B,IAAIC,GAAU;EACd,IAAMC,IAAmB,CAAC,GACpBC,IAA4B,CAAC,GAC7BC,IAAQ,KAAK,IAAI,GAAGC,IAAWC,IAAW,KAAK,IAAI,GAAGA,CAAQ,CAAC;EACrE,KAAK,IAAMnB,KAAQoB,GAAO;GACzB,IAAMC,IAAQzB,EAAQI,GAAMF,CAAM,IAE/BE,EAAK,OAAOsB,IACX,mBACAP,EAAS,SAASQ,KAAaN,IAC9B,mBACA,OALF;GAMH,AAAII,IAAML,EAAS,KAAK;IAAE;IAAM;GAAK,CAAC,IACjCD,EAAS,KAAKf,CAAI;EACxB;EAGA,AAFAU,EAAcM,CAAQ,GAClBD,EAAS,UAAQS,EAAgBT,CAAQ,GACzCC,EAAS,UAAQS,IAAkBT,CAAQ;CAChD;CACA,OACC,kBAAC,OAAD;EACC,MAAK;EACL,cAAYU;EACZ,WAAWC,EAAGC,GAAiB,mCAAmCC,CAAS;EAH5E,UAAA;GAKC,kBAAC,SAAD;IACC,KAAK1B;IACL,MAAK;IACG;IACE;IACA;IACV,UAAU;IACV,cAAYuB;IACZ,WAAU;IACV,WAAW,MAAU;KAEpB,AADAb,EAAQ,MAAM,KAAKiB,EAAM,cAAc,SAAS,CAAC,CAAC,CAAC,GACnD,EAAM,cAAc,QAAQ;IAC7B;GACA,CAAA;GACD,kBAAC,UAAD;IACC,MAAK;IACK;IACV,cAAY,GAAGC,EAAY,IAAIL;IAC/B,oBAAkBM,IAAc,GAAGrB,EAAG,gBAAgB,KAAA;IACtD,oBAAkBL,KAAY,CAACQ;IAC/B,eAAeX,EAAM,SAAS,MAAM;IACpC,cAAc,MAAU;KAGvB,AAFA2B,EAAM,eAAe,GACrB,EAAM,WAAW,GACZhB,KAAUP,EAAY,EAAI;IAChC;IACA,aAAa,MAAU;KAEtB,AADAuB,EAAM,eAAe,GAChBhB,MAAU,EAAM,aAAa,aAAa;IAChD;IACA,cAAc,MAAU;KAGvB,AAFAgB,EAAM,eAAe,GACrB,EAAM,UAAU,KAAK,IAAI,GAAGzB,EAAM,UAAU,CAAC,GACzCA,EAAM,YAAY,KAAGE,EAAY,EAAK;IAC3C;IACA,SAAS,MAAU;KAKlB,AAJAuB,EAAM,eAAe,GACrBA,EAAM,gBAAgB,GACtB,EAAM,UAAU,GAChBvB,EAAY,EAAK,GACjBM,EAAQ,MAAM,KAAKiB,EAAM,aAAa,KAAK,CAAC;IAC7C;IACA,WAAWH,EACV,6TACArB,KAAY,CAACQ,IACV,6CACA,8DACJ;IAjCD,UAAA;KAmCC,kBAACmB,GAAD;MACC,WAAU;MACV,eAAY;KACZ,CAAA;KACD,kBAAC,QAAD;MAAM,WAAU;MACd,UAAA3B,KAAY,CAACQ,IAAWoB,IAAYR;KAChC,CAAA;KACLM,KACA,kBAAC,QAAD;MAAM,IAAI,GAAGrB,EAAG;MAAe,WAAU;MACvC,UAAAqB;KACI,CAAA;KAEP,kBAAC,QAAD;MAAM,WAAU;MACd,UAAAD;KACI,CAAA;IACC;;GACPtB,EAAW,SAAS,KACpB,kBAAC,MAAD;IAAI,MAAK;IAAQ,WAAU;IACzB,UAAAA,EAAW,KAAK,GAAM,MACtB,kBAAC,MAAD;KAAuC,WAAU;KAC/C,UAAA0B,IAAkBA,EAAgBC,CAAI,IAAI,GAAGA,EAAK,KAAK,KAAK,IAAInC,EAAQmC,EAAK;IAC3E,GAFK,GAAGA,EAAK,KAAK,KAAK,GAAGC,GAE1B,CACJ;GACE,CAAA;EAED;;AAEP"}
|
|
1
|
+
{"version":3,"file":"file-dropzone.js","names":["accepts","rules","accept","rule","file","REASONS","FileDropzone","input","useRef","depth","dragging","setDragging","useState","rejections","setRejections","id","useId","receive","disabled","accepted","rejected","limit","multiple","maxFiles","files","code","maxSize","fileCount","onFilesAccepted","onFilesRejected","label","cn","BASALT_UI_CLASS","className","event","browseLabel","description","Upload","dropLabel","formatRejection","item","index"],"sources":["../../src/components/file-dropzone.tsx"],"sourcesContent":["import { Upload } from \"lucide-react\";\nimport { useId, useRef, useState } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { BASALT_UI_CLASS } from \"../utils/control-surface\";\n\nexport interface FileRejection {\n\t/** Original File; the component never creates preview URLs. */\n\tfile: File;\n\t/** Machine-readable reason for application handling. */\n\tcode: \"file-invalid-type\" | \"file-too-large\" | \"too-many-files\";\n}\n\nexport interface FileDropzoneProps {\n\t/** Visible and accessible upload field name. */\n\tlabel: string;\n\t/** Optional file requirements shown under the label. */\n\tdescription?: string;\n\t/** Accepted extensions/MIME types using native accept syntax, e.g. .pdf,image/*. */\n\taccept?: string;\n\t/** Allow multiple files. @default true */\n\tmultiple?: boolean;\n\t/** Maximum accepted file count including fileCount. @default Infinity */\n\tmaxFiles?: number;\n\t/** Number already held by the application. @default 0 */\n\tfileCount?: number;\n\t/** Maximum size of an individual file in bytes. @default Infinity */\n\tmaxSize?: number;\n\t/** Prevent both file browsing and drops. @default false */\n\tdisabled?: boolean;\n\t/** Accepted files from this gesture; transport and queue ownership belong to the caller. */\n\tonFilesAccepted: (files: File[]) => void;\n\t/** Rejected files from this gesture, with one primary reason per file. */\n\tonFilesRejected?: (rejections: FileRejection[]) => void;\n\t/** Browse action text. @default \"Browse files\" */\n\tbrowseLabel?: string;\n\t/** Text while a file is dragged over the field. @default \"Drop files here\" */\n\tdropLabel?: string;\n\t/** Localized rejection message; defaults to a name and reason. */\n\tformatRejection?: (rejection: FileRejection) => string;\n\t/** Additional root classes. */\n\tclassName?: string;\n}\n\nfunction accepts(file: File, accept: string) {\n\tconst rules = accept\n\t\t.split(\",\")\n\t\t.map((rule) => rule.trim().toLowerCase())\n\t\t.filter(Boolean);\n\treturn (\n\t\trules.length === 0 ||\n\t\trules.some((rule) =>\n\t\t\trule.startsWith(\".\")\n\t\t\t\t? file.name.toLowerCase().endsWith(rule)\n\t\t\t\t: rule.endsWith(\"/*\")\n\t\t\t\t\t? file.type.toLowerCase().startsWith(rule.slice(0, -1))\n\t\t\t\t\t: file.type.toLowerCase() === rule,\n\t\t)\n\t);\n}\n\nconst REASONS = {\n\t\"file-invalid-type\": \"File type is not accepted.\",\n\t\"file-too-large\": \"File exceeds the size limit.\",\n\t\"too-many-files\": \"File count limit reached.\",\n};\n\nexport function FileDropzone({\n\tlabel,\n\tdescription,\n\taccept = \"\",\n\tmultiple = true,\n\tmaxFiles = Infinity,\n\tfileCount = 0,\n\tmaxSize = Infinity,\n\tdisabled = false,\n\tonFilesAccepted,\n\tonFilesRejected,\n\tbrowseLabel = \"Browse files\",\n\tdropLabel = \"Drop files here\",\n\tformatRejection,\n\tclassName,\n}: FileDropzoneProps) {\n\tconst input = useRef<HTMLInputElement>(null);\n\tconst depth = useRef(0);\n\tconst [dragging, setDragging] = useState(false);\n\tconst [rejections, setRejections] = useState<FileRejection[]>([]);\n\tconst id = useId();\n\tfunction receive(files: File[]) {\n\t\tif (disabled) return;\n\t\tconst accepted: File[] = [];\n\t\tconst rejected: FileRejection[] = [];\n\t\tconst limit = Math.max(0, multiple ? maxFiles : Math.min(1, maxFiles));\n\t\tfor (const file of files) {\n\t\t\tconst code = !accepts(file, accept)\n\t\t\t\t? \"file-invalid-type\"\n\t\t\t\t: file.size > maxSize\n\t\t\t\t\t? \"file-too-large\"\n\t\t\t\t\t: accepted.length + fileCount >= limit\n\t\t\t\t\t\t? \"too-many-files\"\n\t\t\t\t\t\t: null;\n\t\t\tif (code) rejected.push({ file, code });\n\t\t\telse accepted.push(file);\n\t\t}\n\t\tsetRejections(rejected);\n\t\tif (accepted.length) onFilesAccepted(accepted);\n\t\tif (rejected.length) onFilesRejected?.(rejected);\n\t}\n\treturn (\n\t\t<div\n\t\t\trole=\"group\"\n\t\t\taria-label={label}\n\t\t\tclassName={cn(BASALT_UI_CLASS, \"min-w-0 space-y-basalt-space-lg\", className)}\n\t\t>\n\t\t\t<input\n\t\t\t\tref={input}\n\t\t\t\ttype=\"file\"\n\t\t\t\taccept={accept}\n\t\t\t\tmultiple={multiple}\n\t\t\t\tdisabled={disabled}\n\t\t\t\ttabIndex={-1}\n\t\t\t\taria-label={label}\n\t\t\t\tclassName=\"hidden\"\n\t\t\t\tonChange={(event) => {\n\t\t\t\t\treceive(Array.from(event.currentTarget.files ?? []));\n\t\t\t\t\tevent.currentTarget.value = \"\";\n\t\t\t\t}}\n\t\t\t/>\n\t\t\t<button\n\t\t\t\ttype=\"button\"\n\t\t\t\tdisabled={disabled}\n\t\t\t\taria-label={`${browseLabel}: ${label}`}\n\t\t\t\taria-describedby={description ? `${id}-description` : undefined}\n\t\t\t\tdata-drag-active={dragging && !disabled}\n\t\t\t\tonClick={() => input.current?.click()}\n\t\t\t\tonDragEnter={(event) => {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tdepth.current += 1;\n\t\t\t\t\tif (!disabled) setDragging(true);\n\t\t\t\t}}\n\t\t\t\tonDragOver={(event) => {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tif (!disabled) event.dataTransfer.dropEffect = \"copy\";\n\t\t\t\t}}\n\t\t\t\tonDragLeave={(event) => {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tdepth.current = Math.max(0, depth.current - 1);\n\t\t\t\t\tif (depth.current === 0) setDragging(false);\n\t\t\t\t}}\n\t\t\t\tonDrop={(event) => {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\tdepth.current = 0;\n\t\t\t\t\tsetDragging(false);\n\t\t\t\t\treceive(Array.from(event.dataTransfer.files));\n\t\t\t\t}}\n\t\t\t\tclassName={cn(\n\t\t\t\t\t\"basalt-focus flex w-full min-w-0 flex-col items-center gap-basalt-space-lg rounded-basalt-lg border-2 border-dashed px-basalt-card py-basalt-card text-center transition-colors basalt-motion disabled:cursor-not-allowed disabled:opacity-50\",\n\t\t\t\t\tdragging && !disabled\n\t\t\t\t\t\t? \"border-basalt-primary bg-basalt-selected\"\n\t\t\t\t\t\t: \"border-basalt-border bg-basalt-control hover:bg-basalt-hover\",\n\t\t\t\t)}\n\t\t\t>\n\t\t\t\t<Upload\n\t\t\t\t\tclassName=\"size-basalt-icon-display text-basalt-muted-foreground\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t/>\n\t\t\t\t<span className=\"text-basalt-base font-medium\">\n\t\t\t\t\t{dragging && !disabled ? dropLabel : label}\n\t\t\t\t</span>\n\t\t\t\t{description && (\n\t\t\t\t\t<span id={`${id}-description`} className=\"text-basalt-sm text-basalt-muted-foreground\">\n\t\t\t\t\t\t{description}\n\t\t\t\t\t</span>\n\t\t\t\t)}\n\t\t\t\t<span className=\"rounded-basalt-md border border-basalt-border px-basalt-space-lg py-basalt-space-sm text-basalt-sm\">\n\t\t\t\t\t{browseLabel}\n\t\t\t\t</span>\n\t\t\t</button>\n\t\t\t{rejections.length > 0 && (\n\t\t\t\t<ul role=\"alert\" className=\"space-y-basalt-space-sm text-basalt-sm text-basalt-destructive\">\n\t\t\t\t\t{rejections.map((item, index) => (\n\t\t\t\t\t\t<li key={`${item.file.name}-${index}`} className=\"break-words\">\n\t\t\t\t\t\t\t{formatRejection ? formatRejection(item) : `${item.file.name}: ${REASONS[item.code]}`}\n\t\t\t\t\t\t</li>\n\t\t\t\t\t))}\n\t\t\t\t</ul>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n"],"mappings":"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"}
|
|
@@ -38,7 +38,7 @@ function s({ label: n, value: o, onRemove: s, removeLabel: c, disabled: l = !1,
|
|
|
38
38
|
disabled: l,
|
|
39
39
|
"aria-label": c ?? `Remove ${n}`,
|
|
40
40
|
onClick: s,
|
|
41
|
-
className: "shrink-0 rounded-basalt-full p-basalt-space-sm
|
|
41
|
+
className: "basalt-focus basalt-focus-inset shrink-0 rounded-basalt-full p-basalt-space-sm disabled:opacity-50",
|
|
42
42
|
children: /* @__PURE__ */ i(r, {
|
|
43
43
|
className: "size-basalt-icon-sm",
|
|
44
44
|
"aria-hidden": "true"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filter-bar.js","names":["FilterBar","label","cn","BASALT_UI_CLASS","className","children","active","onClear","Button","clearLabel","chips","FilterChip","value","removeLabel","onRemove","X"],"sources":["../../src/components/filter-bar.tsx"],"sourcesContent":["import { X } from \"lucide-react\";\nimport type { ReactNode } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { BASALT_UI_CLASS } from \"../utils/control-surface\";\nimport { Button } from \"./button\";\n\nexport interface FilterBarProps {\n\t/** Accessible group name. */\n\tlabel: string;\n\t/** Application-owned search, select, and date controls. */\n\tchildren: ReactNode;\n\t/** Active chips, shown on their own wrapping row. */\n\tchips?: ReactNode;\n\t/** Whether the clear action is available. @default false */\n\tactive?: boolean;\n\t/** Requests clearing application-owned filters. */\n\tonClear?: () => void;\n\t/** Clear action text. @default \"Clear filters\" */\n\tclearLabel?: string;\n\t/** Additional root classes. */\n\tclassName?: string;\n}\n\n/** Layout only; URL serialization, query execution, and date presets belong to the caller. */\nexport function FilterBar({\n\tlabel,\n\tchildren,\n\tchips,\n\tactive = false,\n\tonClear,\n\tclearLabel = \"Clear filters\",\n\tclassName,\n}: FilterBarProps) {\n\treturn (\n\t\t<div\n\t\t\trole=\"group\"\n\t\t\taria-label={label}\n\t\t\tclassName={cn(BASALT_UI_CLASS, \"min-w-0 space-y-basalt-space-lg\", className)}\n\t\t>\n\t\t\t<div className=\"flex flex-wrap items-end gap-basalt-space-lg [&>*]:min-w-0\">\n\t\t\t\t{children}\n\t\t\t\t{active && onClear && (\n\t\t\t\t\t<Button size=\"sm\" variant=\"ghost\" onClick={onClear}>\n\t\t\t\t\t\t{clearLabel}\n\t\t\t\t\t</Button>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t\t{chips != null && (\n\t\t\t\t<div className=\"flex flex-wrap items-center gap-basalt-space-lg\">{chips}</div>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n\nexport interface FilterChipProps {\n\t/** Filter dimension, e.g. Status. */\n\tlabel: string;\n\t/** Display value. */\n\tvalue: ReactNode;\n\t/** Requests removal from the application's filter state. */\n\tonRemove: () => void;\n\t/** Full accessible removal label; defaults to Remove plus the dimension label. */\n\tremoveLabel?: string;\n\t/** Disable removal. @default false */\n\tdisabled?: boolean;\n\t/** Additional root classes. */\n\tclassName?: string;\n}\n\nexport function FilterChip({\n\tlabel,\n\tvalue,\n\tonRemove,\n\tremoveLabel,\n\tdisabled = false,\n\tclassName,\n}: FilterChipProps) {\n\treturn (\n\t\t<span\n\t\t\tclassName={cn(\n\t\t\t\tBASALT_UI_CLASS,\n\t\t\t\t\"inline-flex max-w-full items-center gap-basalt-space-sm rounded-basalt-full border border-basalt-border bg-basalt-selected py-basalt-space-sm pl-basalt-space-lg pr-basalt-space-sm text-basalt-sm\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t>\n\t\t\t<span className=\"min-w-0 break-words\">\n\t\t\t\t<span className=\"text-basalt-muted-foreground\">{label}: </span>\n\t\t\t\t{value}\n\t\t\t</span>\n\t\t\t<button\n\t\t\t\ttype=\"button\"\n\t\t\t\tdisabled={disabled}\n\t\t\t\taria-label={removeLabel ?? `Remove ${label}`}\n\t\t\t\tonClick={onRemove}\n\t\t\t\tclassName=\"shrink-0 rounded-basalt-full p-basalt-space-sm
|
|
1
|
+
{"version":3,"file":"filter-bar.js","names":["FilterBar","label","cn","BASALT_UI_CLASS","className","children","active","onClear","Button","clearLabel","chips","FilterChip","value","removeLabel","onRemove","X"],"sources":["../../src/components/filter-bar.tsx"],"sourcesContent":["import { X } from \"lucide-react\";\nimport type { ReactNode } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { BASALT_UI_CLASS } from \"../utils/control-surface\";\nimport { Button } from \"./button\";\n\nexport interface FilterBarProps {\n\t/** Accessible group name. */\n\tlabel: string;\n\t/** Application-owned search, select, and date controls. */\n\tchildren: ReactNode;\n\t/** Active chips, shown on their own wrapping row. */\n\tchips?: ReactNode;\n\t/** Whether the clear action is available. @default false */\n\tactive?: boolean;\n\t/** Requests clearing application-owned filters. */\n\tonClear?: () => void;\n\t/** Clear action text. @default \"Clear filters\" */\n\tclearLabel?: string;\n\t/** Additional root classes. */\n\tclassName?: string;\n}\n\n/** Layout only; URL serialization, query execution, and date presets belong to the caller. */\nexport function FilterBar({\n\tlabel,\n\tchildren,\n\tchips,\n\tactive = false,\n\tonClear,\n\tclearLabel = \"Clear filters\",\n\tclassName,\n}: FilterBarProps) {\n\treturn (\n\t\t<div\n\t\t\trole=\"group\"\n\t\t\taria-label={label}\n\t\t\tclassName={cn(BASALT_UI_CLASS, \"min-w-0 space-y-basalt-space-lg\", className)}\n\t\t>\n\t\t\t<div className=\"flex flex-wrap items-end gap-basalt-space-lg [&>*]:min-w-0\">\n\t\t\t\t{children}\n\t\t\t\t{active && onClear && (\n\t\t\t\t\t<Button size=\"sm\" variant=\"ghost\" onClick={onClear}>\n\t\t\t\t\t\t{clearLabel}\n\t\t\t\t\t</Button>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t\t{chips != null && (\n\t\t\t\t<div className=\"flex flex-wrap items-center gap-basalt-space-lg\">{chips}</div>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n\nexport interface FilterChipProps {\n\t/** Filter dimension, e.g. Status. */\n\tlabel: string;\n\t/** Display value. */\n\tvalue: ReactNode;\n\t/** Requests removal from the application's filter state. */\n\tonRemove: () => void;\n\t/** Full accessible removal label; defaults to Remove plus the dimension label. */\n\tremoveLabel?: string;\n\t/** Disable removal. @default false */\n\tdisabled?: boolean;\n\t/** Additional root classes. */\n\tclassName?: string;\n}\n\nexport function FilterChip({\n\tlabel,\n\tvalue,\n\tonRemove,\n\tremoveLabel,\n\tdisabled = false,\n\tclassName,\n}: FilterChipProps) {\n\treturn (\n\t\t<span\n\t\t\tclassName={cn(\n\t\t\t\tBASALT_UI_CLASS,\n\t\t\t\t\"inline-flex max-w-full items-center gap-basalt-space-sm rounded-basalt-full border border-basalt-border bg-basalt-selected py-basalt-space-sm pl-basalt-space-lg pr-basalt-space-sm text-basalt-sm\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t>\n\t\t\t<span className=\"min-w-0 break-words\">\n\t\t\t\t<span className=\"text-basalt-muted-foreground\">{label}: </span>\n\t\t\t\t{value}\n\t\t\t</span>\n\t\t\t<button\n\t\t\t\ttype=\"button\"\n\t\t\t\tdisabled={disabled}\n\t\t\t\taria-label={removeLabel ?? `Remove ${label}`}\n\t\t\t\tonClick={onRemove}\n\t\t\t\tclassName=\"basalt-focus basalt-focus-inset shrink-0 rounded-basalt-full p-basalt-space-sm disabled:opacity-50\"\n\t\t\t>\n\t\t\t\t<X className=\"size-basalt-icon-sm\" aria-hidden=\"true\" />\n\t\t\t</button>\n\t\t</span>\n\t);\n}\n"],"mappings":";;;;;;;AAwBA,SAAgBA,EAAU,EACzB,UACA,aACA,UACA,YAAS,IACT,YACA,gBAAa,iBACb,gBACkB;CAClB,OACC,kBAAC,OAAD;EACC,MAAK;EACL,cAAYC;EACZ,WAAWC,EAAGC,GAAiB,mCAAmCC,CAAS;EAH5E,UAAA,CAKC,kBAAC,OAAD;GAAK,WAAU;GAAf,UAAA,CACEC,GACAC,KAAUC,KACV,kBAACC,GAAD;IAAQ,MAAK;IAAK,SAAQ;IAAQ,SAASD;IACzC,UAAAE;GACM,CAAA,CAEL;EACJ,CAAA,GAAAC,KAAS,QACT,kBAAC,OAAD;GAAK,WAAU;GAAmD,UAAAA;EAAW,CAAA,CAE1E;;AAEP;AAiBA,SAAgBC,EAAW,EAC1B,UACA,UACA,aACA,gBACA,cAAW,IACX,gBACmB;CACnB,OACC,kBAAC,QAAD;EACC,WAAWT,EACVC,GACA,sMACAC,CACD;EALD,UAAA,CAOC,kBAAC,QAAD;GAAM,WAAU;GAAhB,UAAA,CACC,kBAAC,QAAD;IAAM,WAAU;IAAhB,UAAA,CAAgDH,GAAM,IAAQ;GAC7D,CAAA,GAAAW,CACI;EACN,CAAA,GAAA,kBAAC,UAAD;GACC,MAAK;GACK;GACV,cAAYC,KAAe,UAAUZ;GACrC,SAASa;GACT,WAAU;GAEV,UAAA,kBAACC,GAAD;IAAG,WAAU;IAAsB,eAAY;GAAQ,CAAA;EAChD,CAAA,CACH;;AAER"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { cn as e } from "../utils/cn.js";
|
|
3
3
|
import { BASALT_UI_CLASS as t } from "../utils/control-surface.js";
|
|
4
|
-
import {
|
|
4
|
+
import { FOCUS_RING as n } from "./overlay.js";
|
|
5
5
|
import { Button as r } from "./button.js";
|
|
6
6
|
import { Input as i } from "./input.js";
|
|
7
7
|
import { Popover as a, PopoverContent as o, PopoverTrigger as s } from "./popover.js";
|
|
@@ -63,7 +63,7 @@ function h({ label: h, options: g, value: _, defaultValue: v = "", onValueChange
|
|
|
63
63
|
type: "single",
|
|
64
64
|
"aria-label": h,
|
|
65
65
|
value: P,
|
|
66
|
-
className: "grid max-h-basalt-64 grid-cols-2 gap-basalt-space-lg overflow-y-auto",
|
|
66
|
+
className: "grid max-h-basalt-64 grid-cols-2 gap-basalt-space-lg overflow-y-auto p-basalt-space-sm",
|
|
67
67
|
onValueChange: (e) => {
|
|
68
68
|
e && (_ === void 0 && k(e), y?.(e), j(!1), N(""));
|
|
69
69
|
},
|
|
@@ -72,7 +72,7 @@ function h({ label: h, options: g, value: _, defaultValue: v = "", onValueChange
|
|
|
72
72
|
disabled: t.disabled,
|
|
73
73
|
"aria-label": t.label,
|
|
74
74
|
title: t.label,
|
|
75
|
-
className: e("group relative flex min-w-0 flex-col items-center justify-center gap-basalt-space-lg rounded-basalt-md p-basalt-layout-sm text-basalt-foreground data-[state=on]:bg-basalt-primary data-[state=on]:text-basalt-primary-foreground disabled:cursor-not-allowed disabled:opacity-40", n
|
|
75
|
+
className: e("group relative flex min-w-0 flex-col items-center justify-center gap-basalt-space-lg rounded-basalt-md p-basalt-layout-sm text-basalt-foreground data-[state=on]:bg-basalt-primary data-[state=on]:text-basalt-primary-foreground disabled:cursor-not-allowed disabled:opacity-40", n),
|
|
76
76
|
children: [
|
|
77
77
|
/* @__PURE__ */ f("span", {
|
|
78
78
|
"aria-hidden": "true",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"icon-picker.js","names":["ToggleGroupPrimitive","IconPicker","ariaInvalid","describedBy","localValue","setLocalValue","useState","defaultValue","open","setOpen","query","setQuery","selected","value","option","options","matches","Popover","disabled","next","PopoverTrigger","Button","label","placeholder","cn","BASALT_UI_CLASS","className","ChevronDown","PopoverContent","Search","Input","searchPlaceholder","event","onValueChange","item","
|
|
1
|
+
{"version":3,"file":"icon-picker.js","names":["ToggleGroupPrimitive","IconPicker","ariaInvalid","describedBy","localValue","setLocalValue","useState","defaultValue","open","setOpen","query","setQuery","selected","value","option","options","matches","Popover","disabled","next","PopoverTrigger","Button","label","placeholder","cn","BASALT_UI_CLASS","className","ChevronDown","PopoverContent","Search","Input","searchPlaceholder","event","onValueChange","item","FOCUS_RING","Check","emptyLabel"],"sources":["../../src/components/icon-picker.tsx"],"sourcesContent":["import * as ToggleGroupPrimitive from \"@radix-ui/react-toggle-group\";\nimport { Check, ChevronDown, Search } from \"lucide-react\";\nimport { type AriaAttributes, type ReactNode, useState } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { BASALT_UI_CLASS } from \"../utils/control-surface\";\nimport { Button } from \"./button\";\nimport { Input } from \"./input\";\nimport { FOCUS_RING } from \"./overlay\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"./popover\";\n\nexport interface IconPickerOption {\n\t/** Stable application-owned identifier. */\n\tvalue: string;\n\t/** Visible selection text and accessible icon name. */\n\tlabel: string;\n\t/** Caller-rendered icon, from a deliberately small subset. */\n\ticon: ReactNode;\n\t/** Exclude this option from selection and keyboard navigation. */\n\tdisabled?: boolean;\n}\nexport interface IconPickerProps {\n\t/** Accessible picker name. */\n\tlabel: string;\n\t/** Caller-supplied icon subset; the library never imports an icon catalog. */\n\toptions: readonly IconPickerOption[];\n\t/** Controlled icon identifier. */\n\tvalue?: string;\n\t/** Initial uncontrolled icon identifier. */\n\tdefaultValue?: string;\n\t/** Selection request. */\n\tonValueChange?: (value: string) => void;\n\t/** Disable selection. @default false */\n\tdisabled?: boolean;\n\t/** Empty selection prompt. @default \"Choose icon\" */\n\tplaceholder?: string;\n\t/** Search placeholder. @default \"Search icons…\" */\n\tsearchPlaceholder?: string;\n\t/** Empty-search text. @default \"No icons found.\" */\n\temptyLabel?: string;\n\t/** Forwarded to the trigger so Field and Label can own it. */\n\tid?: string;\n\t/** Forwarded to the trigger; Field sets it while the value is invalid. */\n\t\"aria-invalid\"?: AriaAttributes[\"aria-invalid\"];\n\t/** Forwarded to the trigger; Field points it at the hint or error. */\n\t\"aria-describedby\"?: string;\n\t/** Additional root classes. */\n\tclassName?: string;\n}\nexport function IconPicker({\n\tlabel,\n\toptions,\n\tvalue,\n\tdefaultValue = \"\",\n\tonValueChange,\n\tdisabled = false,\n\tplaceholder = \"Choose icon\",\n\tsearchPlaceholder = \"Search icons…\",\n\temptyLabel = \"No icons found.\",\n\tid,\n\t\"aria-invalid\": ariaInvalid,\n\t\"aria-describedby\": describedBy,\n\tclassName,\n}: IconPickerProps) {\n\tconst [localValue, setLocalValue] = useState(defaultValue);\n\tconst [open, setOpen] = useState(false);\n\tconst [query, setQuery] = useState(\"\");\n\tconst selected = value ?? localValue;\n\tconst option = options.find((option) => option.value === selected);\n\tconst matches = options.filter((option) =>\n\t\toption.label.toLocaleLowerCase().includes(query.trim().toLocaleLowerCase()),\n\t);\n\treturn (\n\t\t<Popover\n\t\t\topen={open && !disabled}\n\t\t\tonOpenChange={(next) => {\n\t\t\t\tsetOpen(next);\n\t\t\t\tif (!next) setQuery(\"\");\n\t\t\t}}\n\t\t>\n\t\t\t<PopoverTrigger asChild>\n\t\t\t\t<Button\n\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\tid={id}\n\t\t\t\t\taria-invalid={ariaInvalid}\n\t\t\t\t\taria-describedby={describedBy}\n\t\t\t\t\taria-label={`${label}: ${option?.label ?? placeholder}`}\n\t\t\t\t\tclassName={cn(BASALT_UI_CLASS, \"max-w-full\", className)}\n\t\t\t\t>\n\t\t\t\t\t<span aria-hidden=\"true\" className=\"shrink-0\">\n\t\t\t\t\t\t{option?.icon}\n\t\t\t\t\t</span>\n\t\t\t\t\t<span className=\"truncate\">{option?.label ?? placeholder}</span>\n\t\t\t\t\t<ChevronDown className=\"shrink-0\" />\n\t\t\t\t</Button>\n\t\t\t</PopoverTrigger>\n\t\t\t<PopoverContent\n\t\t\t\talign=\"start\"\n\t\t\t\tarrow={false}\n\t\t\t\tclassName=\"w-basalt-72 max-w-[calc(100vw-2rem)] space-y-basalt-layout-sm\"\n\t\t\t\taria-label={label}\n\t\t\t>\n\t\t\t\t<div className=\"relative\">\n\t\t\t\t\t<Search\n\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\tclassName=\"pointer-events-none absolute left-basalt-space-lg top-1/2 size-basalt-icon -translate-y-1/2 text-basalt-muted-foreground\"\n\t\t\t\t\t/>\n\t\t\t\t\t<Input\n\t\t\t\t\t\tclassName=\"pl-basalt-card-xl\"\n\t\t\t\t\t\taria-label={`${label}: search`}\n\t\t\t\t\t\tvalue={query}\n\t\t\t\t\t\tplaceholder={searchPlaceholder}\n\t\t\t\t\t\tonChange={(event) => setQuery(event.target.value)}\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\t\t\t\t<ToggleGroupPrimitive.Root\n\t\t\t\t\ttype=\"single\"\n\t\t\t\t\taria-label={label}\n\t\t\t\t\tvalue={selected}\n\t\t\t\t\tclassName=\"grid max-h-basalt-64 grid-cols-2 gap-basalt-space-lg overflow-y-auto p-basalt-space-sm\"\n\t\t\t\t\tonValueChange={(next) => {\n\t\t\t\t\t\tif (!next) return;\n\t\t\t\t\t\tif (value === undefined) setLocalValue(next);\n\t\t\t\t\t\tonValueChange?.(next);\n\t\t\t\t\t\tsetOpen(false);\n\t\t\t\t\t\tsetQuery(\"\");\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t{matches.map((item) => (\n\t\t\t\t\t\t<ToggleGroupPrimitive.Item\n\t\t\t\t\t\t\tkey={item.value}\n\t\t\t\t\t\t\tvalue={item.value}\n\t\t\t\t\t\t\tdisabled={item.disabled}\n\t\t\t\t\t\t\taria-label={item.label}\n\t\t\t\t\t\t\ttitle={item.label}\n\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t// Accent choice grid: selection is the documented primary fill and its\n\t\t\t\t\t\t\t\t// contrast-corrected foreground, never a control fill plus a frame.\n\t\t\t\t\t\t\t\t\"group relative flex min-w-0 flex-col items-center justify-center gap-basalt-space-lg rounded-basalt-md p-basalt-layout-sm text-basalt-foreground data-[state=on]:bg-basalt-primary data-[state=on]:text-basalt-primary-foreground disabled:cursor-not-allowed disabled:opacity-40\",\n\t\t\t\t\t\t\t\tFOCUS_RING,\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t\t\tclassName=\"flex size-basalt-6 items-center justify-center [&>svg]:size-basalt-6\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{item.icon}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t<span className=\"max-w-full break-words text-basalt-sm font-medium\">\n\t\t\t\t\t\t\t\t{item.label}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t<Check\n\t\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t\t\tclassName=\"absolute right-basalt-space-sm top-basalt-space-sm size-basalt-icon-sm opacity-0 group-data-[state=on]:opacity-100\"\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</ToggleGroupPrimitive.Item>\n\t\t\t\t\t))}\n\t\t\t\t</ToggleGroupPrimitive.Root>\n\t\t\t\t{matches.length === 0 && (\n\t\t\t\t\t<p role=\"status\" className=\"text-basalt-base text-basalt-muted-foreground\">\n\t\t\t\t\t\t{emptyLabel}\n\t\t\t\t\t</p>\n\t\t\t\t)}\n\t\t\t</PopoverContent>\n\t\t</Popover>\n\t);\n}\n"],"mappings":";;;;;;;;;;;;AAgDA,SAAgBC,EAAW,EAC1B,UACA,YACA,UACA,kBAAe,IACf,kBACA,cAAW,IACX,iBAAc,eACd,uBAAoB,iBACpB,gBAAa,mBACb,OACA,gBAAgBC,GAChB,oBAAoBC,GACpB,gBACmB;CACnB,IAAM,CAACC,GAAYC,KAAiBC,EAASC,CAAY,GACnD,CAACC,GAAMC,KAAWH,EAAS,EAAK,GAChC,CAACI,GAAOC,KAAYL,EAAS,EAAE,GAC/BM,IAAWC,KAAST,GACpBU,IAASC,EAAQ,MAAM,MAAWD,EAAO,UAAUF,CAAQ,GAC3DI,IAAUD,EAAQ,QAAQ,MAC/BD,EAAO,MAAM,kBAAkB,CAAC,CAAC,SAASJ,EAAM,KAAK,CAAC,CAAC,kBAAkB,CAAC,CAC3E;CACA,OACC,kBAACO,GAAD;EACC,MAAMT,KAAQ,CAACU;EACf,eAAe,MAAS;GAEvB,AADAT,EAAQU,CAAI,GACPA,KAAMR,EAAS,EAAE;EACvB;EALD,UAAA,CAOC,kBAACS,GAAD;GAAgB,SAAA;GACf,UAAA,kBAACC,GAAD;IACC,SAAQ;IACE;IACN;IACJ,gBAAcnB;IACd,oBAAkBC;IAClB,cAAY,GAAGmB,EAAM,IAAIR,GAAQ,SAASS;IAC1C,WAAWC,EAAGC,GAAiB,cAAcC,CAAS;IAPvD,UAAA;KASC,kBAAC,QAAD;MAAM,eAAY;MAAO,WAAU;MACjC,UAAAZ,GAAQ;KACJ,CAAA;KACN,kBAAC,QAAD;MAAM,WAAU;MAAY,UAAAA,GAAQ,SAASS;KAAkB,CAAA;KAC/D,kBAACI,GAAD,EAAa,WAAU,WAAY,CAAA;IAC5B;;EACO,CAAA,GAChB,kBAACC,GAAD;GACC,OAAM;GACN,OAAO;GACP,WAAU;GACV,cAAYN;GAJb,UAAA;IAMC,kBAAC,OAAD;KAAK,WAAU;KAAf,UAAA,CACC,kBAACO,GAAD;MACC,eAAY;MACZ,WAAU;KACV,CAAA,GACD,kBAACC,GAAD;MACC,WAAU;MACV,cAAY,GAAGR,EAAM;MACrB,OAAOZ;MACP,aAAaqB;MACb,WAAW,MAAUpB,EAASqB,EAAM,OAAO,KAAK;KAChD,CAAA,CACG;;IACL,kBAAChC,EAAqB,MAAtB;KACC,MAAK;KACL,cAAYsB;KACZ,OAAOV;KACP,WAAU;KACV,gBAAgB,MAAS;MACxB,AAAKO,MACDN,MAAU,KAAA,KAAWR,EAAcc,CAAI,GAC3Cc,IAAgBd,CAAI,GACpBV,EAAQ,EAAK,GACbE,EAAS,EAAE;KACZ;KAEC,UAAAK,EAAQ,KAAK,MACb,kBAAChB,EAAqB,MAAtB;MAEC,OAAOkC,EAAK;MACZ,UAAUA,EAAK;MACf,cAAYA,EAAK;MACjB,OAAOA,EAAK;MACZ,WAAWV,EAGV,qRACAW,CACD;MAXD,UAAA;OAaC,kBAAC,QAAD;QACC,eAAY;QACZ,WAAU;QAET,UAAAD,EAAK;OACD,CAAA;OACN,kBAAC,QAAD;QAAM,WAAU;QACd,UAAAA,EAAK;OACD,CAAA;OACN,kBAACE,GAAD;QACC,eAAY;QACZ,WAAU;OACV,CAAA;MACyB;KAzBrB,GAAAF,EAAK,KAyBgB,CAC3B;IACyB,CAAA;IAC1BlB,EAAQ,WAAW,KACnB,kBAAC,KAAD;KAAG,MAAK;KAAS,WAAU;KACzB,UAAAqB;IACC,CAAA;GAEW;EACR,CAAA,CAAA;;AAEX"}
|
|
@@ -92,7 +92,7 @@ function f({ label: f, value: p, onSave: m, editing: h, defaultEditing: g = !1,
|
|
|
92
92
|
type: "button",
|
|
93
93
|
disabled: b || v,
|
|
94
94
|
"aria-label": `${E} ${f}`,
|
|
95
|
-
className: "group flex max-w-full items-center gap-basalt-space-lg rounded-basalt-md px-basalt-space-sm py-basalt-space-sm text-left text-basalt-base hover:bg-basalt-hover
|
|
95
|
+
className: "basalt-focus group flex max-w-full items-center gap-basalt-space-lg rounded-basalt-md px-basalt-space-sm py-basalt-space-sm text-left text-basalt-base hover:bg-basalt-hover disabled:opacity-50",
|
|
96
96
|
onClick: () => {
|
|
97
97
|
I(p), B(void 0), Z(!0, "edit");
|
|
98
98
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inline-editable.js","names":["InlineEditable","localEditing","setLocalEditing","useState","defaultEditing","draft","setDraft","value","saving","setSaving","failure","setFailure","input","useRef","trigger","mounted","operation","locked","restore","id","useId","isEditing","editing","busy","pending","message","error","useEffect","useLayoutEffect","disabled","changeEditing","next","onEditingChange","reason","finish","save","trim","invalid","required","requiredLabel","validate","ticket","onSave","cause","errorLabel","label","cn","BASALT_UI_CLASS","className","saveOnBlur","event","Input","Button","saveLabel","cancelLabel","editLabel","placeholder","Pencil","pendingLabel"],"sources":["../../src/components/inline-editable.tsx"],"sourcesContent":["import { Pencil } from \"lucide-react\";\nimport { useEffect, useId, useLayoutEffect, useRef, useState } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { BASALT_UI_CLASS } from \"../utils/control-surface\";\nimport { Button } from \"./button\";\nimport { Input } from \"./input\";\n\nexport type InlineEditableChangeReason = \"edit\" | \"save\" | \"blur\" | \"cancel\";\nexport interface InlineEditableProps {\n\t/** Accessible name of the edited field. */\n\tlabel: string;\n\t/** Committed value, owned by the application. */\n\tvalue: string;\n\t/** Persist the draft. Return a promise to keep the editor pending; rejection preserves the draft. */\n\tonSave: (value: string) => void | Promise<void>;\n\t/** Controlled edit mode. */\n\tediting?: boolean;\n\t/** Initial uncontrolled edit mode. @default false */\n\tdefaultEditing?: boolean;\n\t/** Edit-mode requests with their cause, including blur that must not steal focus. */\n\tonEditingChange?: (editing: boolean, reason: InlineEditableChangeReason) => void;\n\t/** External pending state. @default false */\n\tpending?: boolean;\n\t/** Application-owned error message. */\n\terror?: string;\n\t/** Disable editing and saving. @default false */\n\tdisabled?: boolean;\n\t/** Reject an empty draft. @default true */\n\trequired?: boolean;\n\t/** Trim whitespace before validation and save. @default true */\n\ttrim?: boolean;\n\t/** Commit when focus leaves the whole editor, including its actions. @default true */\n\tsaveOnBlur?: boolean;\n\t/** Return a validation message to retain the draft without invoking onSave. */\n\tvalidate?: (value: string) => string | undefined;\n\t/** Empty committed-value prompt. @default \"Untitled\" */\n\tplaceholder?: string;\n\t/** Edit action label prefix. @default \"Edit\" */\n\teditLabel?: string;\n\t/** Save action text. @default \"Save\" */\n\tsaveLabel?: string;\n\t/** Cancel action text. @default \"Cancel\" */\n\tcancelLabel?: string;\n\t/** Pending announcement. @default \"Saving…\" */\n\tpendingLabel?: string;\n\t/** Empty-value validation message. @default \"Enter a value.\" */\n\trequiredLabel?: string;\n\t/** Fallback for non-Error rejections. @default \"Could not save changes.\" */\n\terrorLabel?: string;\n\t/** Additional root classes. */\n\tclassName?: string;\n}\n\nexport function InlineEditable({\n\tlabel,\n\tvalue,\n\tonSave,\n\tediting,\n\tdefaultEditing = false,\n\tonEditingChange,\n\tpending = false,\n\terror,\n\tdisabled = false,\n\trequired = true,\n\ttrim = true,\n\tsaveOnBlur = true,\n\tvalidate,\n\tplaceholder = \"Untitled\",\n\teditLabel = \"Edit\",\n\tsaveLabel = \"Save\",\n\tcancelLabel = \"Cancel\",\n\tpendingLabel = \"Saving…\",\n\trequiredLabel = \"Enter a value.\",\n\terrorLabel = \"Could not save changes.\",\n\tclassName,\n}: InlineEditableProps) {\n\tconst [localEditing, setLocalEditing] = useState(defaultEditing);\n\tconst [draft, setDraft] = useState(value);\n\tconst [saving, setSaving] = useState(false);\n\tconst [failure, setFailure] = useState<string>();\n\tconst input = useRef<HTMLInputElement>(null);\n\tconst trigger = useRef<HTMLButtonElement>(null);\n\tconst mounted = useRef(true);\n\tconst operation = useRef(0);\n\tconst locked = useRef(false);\n\tconst restore = useRef(false);\n\tconst id = useId();\n\tconst isEditing = editing ?? localEditing;\n\tconst busy = pending || saving;\n\tconst message = error ?? failure;\n\tuseEffect(() => {\n\t\tmounted.current = true;\n\t\treturn () => {\n\t\t\tmounted.current = false;\n\t\t\toperation.current += 1;\n\t\t};\n\t}, []);\n\tuseLayoutEffect(() => {\n\t\tif (isEditing && !disabled) {\n\t\t\tinput.current?.focus();\n\t\t\tinput.current?.select();\n\t\t} else if (!isEditing && restore.current) {\n\t\t\trestore.current = false;\n\t\t\ttrigger.current?.focus();\n\t\t}\n\t}, [isEditing, disabled]);\n\tuseEffect(() => {\n\t\tif (!isEditing) {\n\t\t\toperation.current += 1;\n\t\t\tlocked.current = false;\n\t\t\tsetSaving(false);\n\t\t\tsetDraft(value);\n\t\t\tsetFailure(undefined);\n\t\t}\n\t}, [isEditing, value]);\n\tfunction changeEditing(next: boolean, reason: InlineEditableChangeReason) {\n\t\tif (editing === undefined) setLocalEditing(next);\n\t\tonEditingChange?.(next, reason);\n\t}\n\tfunction finish(reason: InlineEditableChangeReason) {\n\t\trestore.current = reason !== \"blur\";\n\t\tchangeEditing(false, reason);\n\t}\n\tasync function save(reason: \"save\" | \"blur\") {\n\t\tif (!isEditing || disabled || busy || locked.current) return;\n\t\tconst next = trim ? draft.trim() : draft;\n\t\tconst invalid = required && !next ? requiredLabel : validate?.(next);\n\t\tif (invalid) {\n\t\t\tsetFailure(invalid);\n\t\t\treturn;\n\t\t}\n\t\tif (next === value) {\n\t\t\tfinish(reason);\n\t\t\treturn;\n\t\t}\n\t\tlocked.current = true;\n\t\tsetSaving(true);\n\t\tsetFailure(undefined);\n\t\tconst ticket = ++operation.current;\n\t\ttry {\n\t\t\tawait onSave(next);\n\t\t\tif (mounted.current && ticket === operation.current) finish(reason);\n\t\t} catch (cause) {\n\t\t\tif (mounted.current && ticket === operation.current)\n\t\t\t\tsetFailure(cause instanceof Error && cause.message ? cause.message : errorLabel);\n\t\t} finally {\n\t\t\tif (mounted.current && ticket === operation.current) {\n\t\t\t\tlocked.current = false;\n\t\t\t\tsetSaving(false);\n\t\t\t}\n\t\t}\n\t}\n\treturn (\n\t\t<div\n\t\t\trole=\"group\"\n\t\t\taria-label={label}\n\t\t\taria-busy={busy}\n\t\t\tclassName={cn(BASALT_UI_CLASS, \"min-w-0 space-y-basalt-space-lg\", className)}\n\t\t\tonBlur={(event) => {\n\t\t\t\tif (saveOnBlur && !event.currentTarget.contains(event.relatedTarget)) void save(\"blur\");\n\t\t\t}}\n\t\t>\n\t\t\t{isEditing ? (\n\t\t\t\t<div className=\"flex flex-wrap items-center gap-basalt-space-lg\">\n\t\t\t\t\t<Input\n\t\t\t\t\t\tref={input}\n\t\t\t\t\t\taria-label={label}\n\t\t\t\t\t\tclassName=\"min-w-0 flex-1 basis-32\"\n\t\t\t\t\t\tvalue={draft}\n\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\treadOnly={busy}\n\t\t\t\t\t\taria-invalid={!!message}\n\t\t\t\t\t\taria-describedby={message ? `${id}-error` : undefined}\n\t\t\t\t\t\tonChange={(event) => {\n\t\t\t\t\t\t\tsetDraft(event.target.value);\n\t\t\t\t\t\t\tsetFailure(undefined);\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tonKeyDown={(event) => {\n\t\t\t\t\t\t\tif (event.nativeEvent.isComposing) return;\n\t\t\t\t\t\t\tif (event.key === \"Enter\") {\n\t\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\t\tvoid save(\"save\");\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (event.key === \"Escape\" && !busy) {\n\t\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\t\t\t\tsetDraft(value);\n\t\t\t\t\t\t\t\tsetFailure(undefined);\n\t\t\t\t\t\t\t\tfinish(\"cancel\");\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}}\n\t\t\t\t\t/>\n\t\t\t\t\t<Button size=\"sm\" disabled={disabled || busy} onClick={() => void save(\"save\")}>\n\t\t\t\t\t\t{saveLabel}\n\t\t\t\t\t</Button>\n\t\t\t\t\t<Button\n\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\tdisabled={busy}\n\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\tsetDraft(value);\n\t\t\t\t\t\t\tsetFailure(undefined);\n\t\t\t\t\t\t\tfinish(\"cancel\");\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t{cancelLabel}\n\t\t\t\t\t</Button>\n\t\t\t\t</div>\n\t\t\t) : (\n\t\t\t\t<button\n\t\t\t\t\tref={trigger}\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tdisabled={disabled || pending}\n\t\t\t\t\taria-label={`${editLabel} ${label}`}\n\t\t\t\t\tclassName=\"group flex max-w-full items-center gap-basalt-space-lg rounded-basalt-md px-basalt-space-sm py-basalt-space-sm text-left text-basalt-base hover:bg-basalt-hover focus-visible:outline-2 focus-visible:outline-basalt-ring disabled:opacity-50\"\n\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\tsetDraft(value);\n\t\t\t\t\t\tsetFailure(undefined);\n\t\t\t\t\t\tchangeEditing(true, \"edit\");\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t<span className={cn(\"min-w-0 break-words\", !value && \"text-basalt-muted-foreground\")}>\n\t\t\t\t\t\t{value || placeholder}\n\t\t\t\t\t</span>\n\t\t\t\t\t<Pencil\n\t\t\t\t\t\tclassName=\"size-basalt-icon shrink-0 text-basalt-muted-foreground\"\n\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t/>\n\t\t\t\t</button>\n\t\t\t)}\n\t\t\t{busy && (\n\t\t\t\t<p role=\"status\" className=\"text-basalt-sm text-basalt-muted-foreground\">\n\t\t\t\t\t{pendingLabel}\n\t\t\t\t</p>\n\t\t\t)}\n\t\t\t{message && (\n\t\t\t\t<p id={`${id}-error`} role=\"alert\" className=\"text-basalt-sm text-basalt-destructive\">\n\t\t\t\t\t{message}\n\t\t\t\t</p>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"inline-editable.js","names":["InlineEditable","localEditing","setLocalEditing","useState","defaultEditing","draft","setDraft","value","saving","setSaving","failure","setFailure","input","useRef","trigger","mounted","operation","locked","restore","id","useId","isEditing","editing","busy","pending","message","error","useEffect","useLayoutEffect","disabled","changeEditing","next","onEditingChange","reason","finish","save","trim","invalid","required","requiredLabel","validate","ticket","onSave","cause","errorLabel","label","cn","BASALT_UI_CLASS","className","saveOnBlur","event","Input","Button","saveLabel","cancelLabel","editLabel","placeholder","Pencil","pendingLabel"],"sources":["../../src/components/inline-editable.tsx"],"sourcesContent":["import { Pencil } from \"lucide-react\";\nimport { useEffect, useId, useLayoutEffect, useRef, useState } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { BASALT_UI_CLASS } from \"../utils/control-surface\";\nimport { Button } from \"./button\";\nimport { Input } from \"./input\";\n\nexport type InlineEditableChangeReason = \"edit\" | \"save\" | \"blur\" | \"cancel\";\nexport interface InlineEditableProps {\n\t/** Accessible name of the edited field. */\n\tlabel: string;\n\t/** Committed value, owned by the application. */\n\tvalue: string;\n\t/** Persist the draft. Return a promise to keep the editor pending; rejection preserves the draft. */\n\tonSave: (value: string) => void | Promise<void>;\n\t/** Controlled edit mode. */\n\tediting?: boolean;\n\t/** Initial uncontrolled edit mode. @default false */\n\tdefaultEditing?: boolean;\n\t/** Edit-mode requests with their cause, including blur that must not steal focus. */\n\tonEditingChange?: (editing: boolean, reason: InlineEditableChangeReason) => void;\n\t/** External pending state. @default false */\n\tpending?: boolean;\n\t/** Application-owned error message. */\n\terror?: string;\n\t/** Disable editing and saving. @default false */\n\tdisabled?: boolean;\n\t/** Reject an empty draft. @default true */\n\trequired?: boolean;\n\t/** Trim whitespace before validation and save. @default true */\n\ttrim?: boolean;\n\t/** Commit when focus leaves the whole editor, including its actions. @default true */\n\tsaveOnBlur?: boolean;\n\t/** Return a validation message to retain the draft without invoking onSave. */\n\tvalidate?: (value: string) => string | undefined;\n\t/** Empty committed-value prompt. @default \"Untitled\" */\n\tplaceholder?: string;\n\t/** Edit action label prefix. @default \"Edit\" */\n\teditLabel?: string;\n\t/** Save action text. @default \"Save\" */\n\tsaveLabel?: string;\n\t/** Cancel action text. @default \"Cancel\" */\n\tcancelLabel?: string;\n\t/** Pending announcement. @default \"Saving…\" */\n\tpendingLabel?: string;\n\t/** Empty-value validation message. @default \"Enter a value.\" */\n\trequiredLabel?: string;\n\t/** Fallback for non-Error rejections. @default \"Could not save changes.\" */\n\terrorLabel?: string;\n\t/** Additional root classes. */\n\tclassName?: string;\n}\n\nexport function InlineEditable({\n\tlabel,\n\tvalue,\n\tonSave,\n\tediting,\n\tdefaultEditing = false,\n\tonEditingChange,\n\tpending = false,\n\terror,\n\tdisabled = false,\n\trequired = true,\n\ttrim = true,\n\tsaveOnBlur = true,\n\tvalidate,\n\tplaceholder = \"Untitled\",\n\teditLabel = \"Edit\",\n\tsaveLabel = \"Save\",\n\tcancelLabel = \"Cancel\",\n\tpendingLabel = \"Saving…\",\n\trequiredLabel = \"Enter a value.\",\n\terrorLabel = \"Could not save changes.\",\n\tclassName,\n}: InlineEditableProps) {\n\tconst [localEditing, setLocalEditing] = useState(defaultEditing);\n\tconst [draft, setDraft] = useState(value);\n\tconst [saving, setSaving] = useState(false);\n\tconst [failure, setFailure] = useState<string>();\n\tconst input = useRef<HTMLInputElement>(null);\n\tconst trigger = useRef<HTMLButtonElement>(null);\n\tconst mounted = useRef(true);\n\tconst operation = useRef(0);\n\tconst locked = useRef(false);\n\tconst restore = useRef(false);\n\tconst id = useId();\n\tconst isEditing = editing ?? localEditing;\n\tconst busy = pending || saving;\n\tconst message = error ?? failure;\n\tuseEffect(() => {\n\t\tmounted.current = true;\n\t\treturn () => {\n\t\t\tmounted.current = false;\n\t\t\toperation.current += 1;\n\t\t};\n\t}, []);\n\tuseLayoutEffect(() => {\n\t\tif (isEditing && !disabled) {\n\t\t\tinput.current?.focus();\n\t\t\tinput.current?.select();\n\t\t} else if (!isEditing && restore.current) {\n\t\t\trestore.current = false;\n\t\t\ttrigger.current?.focus();\n\t\t}\n\t}, [isEditing, disabled]);\n\tuseEffect(() => {\n\t\tif (!isEditing) {\n\t\t\toperation.current += 1;\n\t\t\tlocked.current = false;\n\t\t\tsetSaving(false);\n\t\t\tsetDraft(value);\n\t\t\tsetFailure(undefined);\n\t\t}\n\t}, [isEditing, value]);\n\tfunction changeEditing(next: boolean, reason: InlineEditableChangeReason) {\n\t\tif (editing === undefined) setLocalEditing(next);\n\t\tonEditingChange?.(next, reason);\n\t}\n\tfunction finish(reason: InlineEditableChangeReason) {\n\t\trestore.current = reason !== \"blur\";\n\t\tchangeEditing(false, reason);\n\t}\n\tasync function save(reason: \"save\" | \"blur\") {\n\t\tif (!isEditing || disabled || busy || locked.current) return;\n\t\tconst next = trim ? draft.trim() : draft;\n\t\tconst invalid = required && !next ? requiredLabel : validate?.(next);\n\t\tif (invalid) {\n\t\t\tsetFailure(invalid);\n\t\t\treturn;\n\t\t}\n\t\tif (next === value) {\n\t\t\tfinish(reason);\n\t\t\treturn;\n\t\t}\n\t\tlocked.current = true;\n\t\tsetSaving(true);\n\t\tsetFailure(undefined);\n\t\tconst ticket = ++operation.current;\n\t\ttry {\n\t\t\tawait onSave(next);\n\t\t\tif (mounted.current && ticket === operation.current) finish(reason);\n\t\t} catch (cause) {\n\t\t\tif (mounted.current && ticket === operation.current)\n\t\t\t\tsetFailure(cause instanceof Error && cause.message ? cause.message : errorLabel);\n\t\t} finally {\n\t\t\tif (mounted.current && ticket === operation.current) {\n\t\t\t\tlocked.current = false;\n\t\t\t\tsetSaving(false);\n\t\t\t}\n\t\t}\n\t}\n\treturn (\n\t\t<div\n\t\t\trole=\"group\"\n\t\t\taria-label={label}\n\t\t\taria-busy={busy}\n\t\t\tclassName={cn(BASALT_UI_CLASS, \"min-w-0 space-y-basalt-space-lg\", className)}\n\t\t\tonBlur={(event) => {\n\t\t\t\tif (saveOnBlur && !event.currentTarget.contains(event.relatedTarget)) void save(\"blur\");\n\t\t\t}}\n\t\t>\n\t\t\t{isEditing ? (\n\t\t\t\t<div className=\"flex flex-wrap items-center gap-basalt-space-lg\">\n\t\t\t\t\t<Input\n\t\t\t\t\t\tref={input}\n\t\t\t\t\t\taria-label={label}\n\t\t\t\t\t\tclassName=\"min-w-0 flex-1 basis-32\"\n\t\t\t\t\t\tvalue={draft}\n\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\treadOnly={busy}\n\t\t\t\t\t\taria-invalid={!!message}\n\t\t\t\t\t\taria-describedby={message ? `${id}-error` : undefined}\n\t\t\t\t\t\tonChange={(event) => {\n\t\t\t\t\t\t\tsetDraft(event.target.value);\n\t\t\t\t\t\t\tsetFailure(undefined);\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tonKeyDown={(event) => {\n\t\t\t\t\t\t\tif (event.nativeEvent.isComposing) return;\n\t\t\t\t\t\t\tif (event.key === \"Enter\") {\n\t\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\t\tvoid save(\"save\");\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (event.key === \"Escape\" && !busy) {\n\t\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\t\t\t\tsetDraft(value);\n\t\t\t\t\t\t\t\tsetFailure(undefined);\n\t\t\t\t\t\t\t\tfinish(\"cancel\");\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}}\n\t\t\t\t\t/>\n\t\t\t\t\t<Button size=\"sm\" disabled={disabled || busy} onClick={() => void save(\"save\")}>\n\t\t\t\t\t\t{saveLabel}\n\t\t\t\t\t</Button>\n\t\t\t\t\t<Button\n\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\tdisabled={busy}\n\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\tsetDraft(value);\n\t\t\t\t\t\t\tsetFailure(undefined);\n\t\t\t\t\t\t\tfinish(\"cancel\");\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t{cancelLabel}\n\t\t\t\t\t</Button>\n\t\t\t\t</div>\n\t\t\t) : (\n\t\t\t\t<button\n\t\t\t\t\tref={trigger}\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tdisabled={disabled || pending}\n\t\t\t\t\taria-label={`${editLabel} ${label}`}\n\t\t\t\t\tclassName=\"basalt-focus group flex max-w-full items-center gap-basalt-space-lg rounded-basalt-md px-basalt-space-sm py-basalt-space-sm text-left text-basalt-base hover:bg-basalt-hover disabled:opacity-50\"\n\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\tsetDraft(value);\n\t\t\t\t\t\tsetFailure(undefined);\n\t\t\t\t\t\tchangeEditing(true, \"edit\");\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t<span className={cn(\"min-w-0 break-words\", !value && \"text-basalt-muted-foreground\")}>\n\t\t\t\t\t\t{value || placeholder}\n\t\t\t\t\t</span>\n\t\t\t\t\t<Pencil\n\t\t\t\t\t\tclassName=\"size-basalt-icon shrink-0 text-basalt-muted-foreground\"\n\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t/>\n\t\t\t\t</button>\n\t\t\t)}\n\t\t\t{busy && (\n\t\t\t\t<p role=\"status\" className=\"text-basalt-sm text-basalt-muted-foreground\">\n\t\t\t\t\t{pendingLabel}\n\t\t\t\t</p>\n\t\t\t)}\n\t\t\t{message && (\n\t\t\t\t<p id={`${id}-error`} role=\"alert\" className=\"text-basalt-sm text-basalt-destructive\">\n\t\t\t\t\t{message}\n\t\t\t\t</p>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n"],"mappings":"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"}
|
|
@@ -14,7 +14,7 @@ var o = i.createContext(!1), s = i.forwardRef(({ className: n, disabled: r, onCl
|
|
|
14
14
|
"data-disabled": r ? "" : void 0,
|
|
15
15
|
"aria-disabled": r || void 0,
|
|
16
16
|
inert: r || void 0,
|
|
17
|
-
className: t(e("flex w-full items-center text-basalt-base shadow-xs", "[&>:first-child]:rounded-l-basalt-md [&>:last-child]:rounded-r-basalt-md", "
|
|
17
|
+
className: t(e("flex w-full items-center text-basalt-base shadow-xs", "[&>:first-child]:rounded-l-basalt-md [&>:last-child]:rounded-r-basalt-md", "basalt-focus-group has-[input[aria-invalid=true]]:border-basalt-destructive", "has-[[data-slot=input-group-addon-start]]:[&_input]:pl-basalt-space-lg", "has-[[data-slot=input-group-addon-end]]:[&_input]:pr-basalt-space-lg", "has-[[data-slot=input-group-suffix]]:[&_input]:flex-none", "has-[[data-slot=input-group-suffix]]:[&_input]:[field-sizing:content]", "has-[[data-slot=input-group-suffix]]:[&_input]:pr-0", "data-[disabled]:pointer-events-none data-[disabled]:opacity-50", n)),
|
|
18
18
|
onClick: (e) => {
|
|
19
19
|
i?.(e), !(e.defaultPrevented || r) && (e.target.closest("input, textarea, button, a") || e.currentTarget.querySelector("input")?.focus());
|
|
20
20
|
},
|
|
@@ -28,7 +28,7 @@ var c = i.forwardRef(({ className: t, disabled: n, ...s }, c) => {
|
|
|
28
28
|
return /* @__PURE__ */ a(r, {
|
|
29
29
|
ref: c,
|
|
30
30
|
disabled: n || l,
|
|
31
|
-
className: e("min-w-0 w-auto! flex-1 rounded-none border-0 bg-transparent px-basalt-space-lg shadow-none",
|
|
31
|
+
className: e("min-w-0 w-auto! flex-1 rounded-none border-0 bg-transparent px-basalt-space-lg shadow-none", t),
|
|
32
32
|
...s
|
|
33
33
|
});
|
|
34
34
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"input-group.js","names":["React","InputGroupDisabled","InputGroupRoot","props","disabled","controlSurfaceClass","cn","className","onClick","event","InputGroupInput","groupDisabled","Input","InputGroupAddon","align","InputGroupSuffix","InputGroupButton","Button","InputGroup"],"sources":["../../src/components/input-group.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { controlSurfaceClass } from \"../utils/control-surface\";\nimport { Button, type ButtonProps } from \"./button\";\nimport { Input } from \"./input\";\n\nexport type InputGroupProps = React.HTMLAttributes<HTMLDivElement> & {\n\t/**\n\t * Disable the input and nested actions.\n\t * @default false\n\t */\n\tdisabled?: boolean;\n};\n\nconst InputGroupDisabled = React.createContext(false);\n\nconst InputGroupRoot = React.forwardRef<HTMLDivElement, InputGroupProps>(\n\t({ className, disabled, onClick, children, ...props }, ref) => (\n\t\t<InputGroupDisabled.Provider value={Boolean(disabled)}>\n\t\t\t<div\n\t\t\t\tref={ref}\n\t\t\t\tdata-slot=\"input-group\"\n\t\t\t\tdata-disabled={disabled ? \"\" : undefined}\n\t\t\t\taria-disabled={disabled || undefined}\n\t\t\t\tinert={disabled || undefined}\n\t\t\t\tclassName={controlSurfaceClass(\n\t\t\t\t\tcn(\n\t\t\t\t\t\t\"flex w-full items-center text-basalt-base shadow-xs\",\n\t\t\t\t\t\t\"[&>:first-child]:rounded-l-basalt-md [&>:last-child]:rounded-r-basalt-md\",\n\t\t\t\t\t\t\"
|
|
1
|
+
{"version":3,"file":"input-group.js","names":["React","InputGroupDisabled","InputGroupRoot","props","disabled","controlSurfaceClass","cn","className","onClick","event","InputGroupInput","groupDisabled","Input","InputGroupAddon","align","InputGroupSuffix","InputGroupButton","Button","InputGroup"],"sources":["../../src/components/input-group.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { controlSurfaceClass } from \"../utils/control-surface\";\nimport { Button, type ButtonProps } from \"./button\";\nimport { Input } from \"./input\";\n\nexport type InputGroupProps = React.HTMLAttributes<HTMLDivElement> & {\n\t/**\n\t * Disable the input and nested actions.\n\t * @default false\n\t */\n\tdisabled?: boolean;\n};\n\nconst InputGroupDisabled = React.createContext(false);\n\nconst InputGroupRoot = React.forwardRef<HTMLDivElement, InputGroupProps>(\n\t({ className, disabled, onClick, children, ...props }, ref) => (\n\t\t<InputGroupDisabled.Provider value={Boolean(disabled)}>\n\t\t\t<div\n\t\t\t\tref={ref}\n\t\t\t\tdata-slot=\"input-group\"\n\t\t\t\tdata-disabled={disabled ? \"\" : undefined}\n\t\t\t\taria-disabled={disabled || undefined}\n\t\t\t\tinert={disabled || undefined}\n\t\t\t\tclassName={controlSurfaceClass(\n\t\t\t\t\tcn(\n\t\t\t\t\t\t\"flex w-full items-center text-basalt-base shadow-xs\",\n\t\t\t\t\t\t\"[&>:first-child]:rounded-l-basalt-md [&>:last-child]:rounded-r-basalt-md\",\n\t\t\t\t\t\t\"basalt-focus-group has-[input[aria-invalid=true]]:border-basalt-destructive\",\n\t\t\t\t\t\t\"has-[[data-slot=input-group-addon-start]]:[&_input]:pl-basalt-space-lg\",\n\t\t\t\t\t\t\"has-[[data-slot=input-group-addon-end]]:[&_input]:pr-basalt-space-lg\",\n\t\t\t\t\t\t\"has-[[data-slot=input-group-suffix]]:[&_input]:flex-none\",\n\t\t\t\t\t\t\"has-[[data-slot=input-group-suffix]]:[&_input]:[field-sizing:content]\",\n\t\t\t\t\t\t\"has-[[data-slot=input-group-suffix]]:[&_input]:pr-0\",\n\t\t\t\t\t\t\"data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\n\t\t\t\t\t\tclassName,\n\t\t\t\t\t),\n\t\t\t\t)}\n\t\t\t\tonClick={(event) => {\n\t\t\t\t\tonClick?.(event);\n\t\t\t\t\tif (event.defaultPrevented || disabled) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tconst target = event.target as HTMLElement;\n\t\t\t\t\tif (target.closest(\"input, textarea, button, a\")) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tevent.currentTarget.querySelector(\"input\")?.focus();\n\t\t\t\t}}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</div>\n\t\t</InputGroupDisabled.Provider>\n\t),\n);\nInputGroupRoot.displayName = \"InputGroup\";\n\nexport type InputGroupInputProps = Omit<\n\tReact.ComponentPropsWithoutRef<typeof Input>,\n\t\"type\" | \"size\" | \"passwordManagerIgnore\"\n> & {\n\t/**\n\t * The type of input control to render.\n\t */\n\ttype?: React.HTMLInputTypeAttribute;\n};\n\nconst InputGroupInput = React.forwardRef<HTMLInputElement, InputGroupInputProps>(\n\t({ className, disabled, ...props }, ref) => {\n\t\tconst groupDisabled = React.useContext(InputGroupDisabled);\n\t\treturn (\n\t\t\t<Input\n\t\t\t\tref={ref}\n\t\t\t\tdisabled={disabled || groupDisabled}\n\t\t\t\tclassName={cn(\n\t\t\t\t\t\"min-w-0 w-auto! flex-1 rounded-none border-0 bg-transparent px-basalt-space-lg shadow-none\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t);\n\t},\n);\nInputGroupInput.displayName = \"InputGroup.Input\";\n\nexport type InputGroupAddonProps = React.HTMLAttributes<HTMLDivElement> & {\n\t/**\n\t * Place the addon at the start or end of the group.\n\t * @default start\n\t */\n\talign?: \"start\" | \"end\";\n};\n\nfunction InputGroupAddon({ align = \"start\", className, children, ...props }: InputGroupAddonProps) {\n\treturn (\n\t\t<div\n\t\t\tdata-slot={align === \"end\" ? \"input-group-addon-end\" : \"input-group-addon-start\"}\n\t\t\tclassName={cn(\n\t\t\t\t\"pointer-events-none flex shrink-0 items-center text-basalt-muted-foreground *:pointer-events-auto [&_svg]:size-basalt-icon-lg\",\n\t\t\t\talign === \"start\" ? \"-order-1 pl-basalt-space-lg\" : \"order-1 pr-basalt-space-lg\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t>\n\t\t\t{children}\n\t\t</div>\n\t);\n}\nInputGroupAddon.displayName = \"InputGroup.Addon\";\n\nexport type InputGroupSuffixProps = React.HTMLAttributes<HTMLDivElement>;\n\nfunction InputGroupSuffix({ className, children, ...props }: InputGroupSuffixProps) {\n\treturn (\n\t\t<div\n\t\t\tdata-slot=\"input-group-suffix\"\n\t\t\tclassName={cn(\n\t\t\t\t\"pointer-events-none flex min-w-0 flex-1 items-center pr-basalt-space-lg text-basalt-muted-foreground select-none\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t>\n\t\t\t<span className=\"truncate\">{children}</span>\n\t\t</div>\n\t);\n}\nInputGroupSuffix.displayName = \"InputGroup.Suffix\";\n\nexport interface InputGroupButtonProps\n\textends Omit<ButtonProps, \"variant\" | \"size\" | \"asChild\" | \"loading\" | \"icon\"> {\n\t/**\n\t * Visual style for the nested action.\n\t * @default ghost\n\t */\n\tvariant?: ButtonProps[\"variant\"];\n\t/**\n\t * Size for the nested action.\n\t * @default icon\n\t */\n\tsize?: ButtonProps[\"size\"];\n\t/**\n\t * Render the nested action through its child element.\n\t * @default false\n\t */\n\tasChild?: boolean;\n\t/**\n\t * Show a spinner and disable the nested action.\n\t * @default false\n\t */\n\tloading?: boolean;\n\t/**\n\t * Icon rendered before the nested action label.\n\t */\n\ticon?: React.ReactNode;\n}\n\nconst InputGroupButton = React.forwardRef<HTMLButtonElement, InputGroupButtonProps>(\n\t({ className, variant = \"ghost\", size = \"icon\", disabled, ...props }, ref) => {\n\t\tconst groupDisabled = React.useContext(InputGroupDisabled);\n\t\treturn (\n\t\t\t<Button\n\t\t\t\tref={ref}\n\t\t\t\tvariant={variant}\n\t\t\t\tsize={size}\n\t\t\t\tdisabled={disabled || groupDisabled}\n\t\t\t\tclassName={cn(\"basalt-action-inset shrink-0 rounded-basalt-sm\", className)}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t);\n\t},\n);\nInputGroupButton.displayName = \"InputGroup.Button\";\n\nexport const InputGroup = Object.assign(InputGroupRoot, {\n\tInput: InputGroupInput,\n\tAddon: InputGroupAddon,\n\tSuffix: InputGroupSuffix,\n\tButton: InputGroupButton,\n});\n"],"mappings":";;;;;;;;AAcA,IAAMC,IAAqBD,EAAM,cAAc,EAAK,GAE9CE,IAAiBF,EAAM,YAC3B,EAAE,cAAW,aAAU,YAAS,aAAU,GAAGG,KAAS,MACtD,kBAACF,EAAmB,UAApB;CAA6B,OAAO,EAAQG;CAC3C,UAAA,kBAAC,OAAD;EACM;EACL,aAAU;EACV,iBAAeA,IAAW,KAAK,KAAA;EAC/B,iBAAeA,KAAY,KAAA;EAC3B,OAAOA,KAAY,KAAA;EACnB,WAAWC,EACVC,EACC,uDACA,4EACA,+EACA,0EACA,wEACA,4DACA,yEACA,uDACA,kEACAC,CACD,CACD;EACA,UAAU,MAAU;GAEnB,AADAC,IAAUC,CAAK,GACX,IAAM,oBAAoBL,OAGfK,EAAM,OACV,QAAQ,4BAA4B,KAG/CA,EAAM,cAAc,cAAc,OAAO,CAAC,EAAE,MAAM;EACnD;EACA,GAAIN;EAEH;CACG,CAAA;AACuB,CAAA,CAE/B;AACA,EAAe,cAAc;AAY7B,IAAMO,IAAkBV,EAAM,YAC5B,EAAE,cAAW,aAAU,GAAGG,KAAS,MAAQ;CAC3C,IAAMQ,IAAgBX,EAAM,WAAWC,CAAkB;CACzD,OACC,kBAACW,GAAD;EACM;EACL,UAAUR,KAAYO;EACtB,WAAWL,EACV,8FACAC,CACD;EACA,GAAIJ;CACJ,CAAA;AAEH,CACD;AACA,EAAgB,cAAc;AAU9B,SAASU,EAAgB,EAAE,WAAQ,SAAS,cAAW,aAAU,GAAGV,KAA+B;CAClG,OACC,kBAAC,OAAD;EACC,aAAWW,MAAU,QAAQ,0BAA0B;EACvD,WAAWR,EACV,iIACAQ,MAAU,UAAU,gCAAgC,8BACpDP,CACD;EACA,GAAIJ;EAEH;CACG,CAAA;AAEP;AACA,EAAgB,cAAc;AAI9B,SAASY,EAAiB,EAAE,cAAW,aAAU,GAAGZ,KAAgC;CACnF,OACC,kBAAC,OAAD;EACC,aAAU;EACV,WAAWG,EACV,oHACAC,CACD;EACA,GAAIJ;EAEJ,UAAA,kBAAC,QAAD;GAAM,WAAU;GAAY;EAAe,CAAA;CACvC,CAAA;AAEP;AACA,EAAiB,cAAc;AA8B/B,IAAMa,IAAmBhB,EAAM,YAC7B,EAAE,cAAW,aAAU,SAAS,UAAO,QAAQ,aAAU,GAAGG,KAAS,MAAQ;CAC7E,IAAMQ,IAAgBX,EAAM,WAAWC,CAAkB;CACzD,OACC,kBAACgB,GAAD;EACM;EACI;EACH;EACN,UAAUb,KAAYO;EACtB,WAAWL,EAAG,kDAAkDC,CAAS;EACzE,GAAIJ;CACJ,CAAA;AAEH,CACD;AACA,EAAiB,cAAc;AAE/B,IAAae,IAAa,OAAO,OAAOhB,GAAgB;CACvD,OAAOQ;CACP,OAAOG;CACP,QAAQE;CACR,QAAQC;AACT,CAAC"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { cn as e } from "../utils/cn.js";
|
|
3
3
|
import { BASALT_UI_CLASS as t } from "../utils/control-surface.js";
|
|
4
|
+
import "./overlay.js";
|
|
4
5
|
import { Empty as n } from "./empty.js";
|
|
5
6
|
import { SkeletonLine as r } from "./skeleton-line.js";
|
|
6
7
|
import { Children as i, Fragment as a, forwardRef as o, isValidElement as s } from "react";
|
|
@@ -35,7 +36,7 @@ h.displayName = "LayerCard";
|
|
|
35
36
|
function g({ className: t, asChild: n = !1, divided: r = !1, ...i }) {
|
|
36
37
|
return /* @__PURE__ */ l(n ? c : "div", {
|
|
37
38
|
"data-slot": "card-header",
|
|
38
|
-
className: e("flex min-w-0 justify-between gap-basalt-space-lg text-basalt-base font-medium tracking-tight text-basalt-foreground", n ? "w-full items-center px-basalt-card py-basalt-card-sm data-[state=open]:border-b data-[state=open]:border-basalt-border" : r ? "items-start p-basalt-card border-b border-basalt-border" : "items-start px-basalt-card pt-basalt-card pb-0", t),
|
|
39
|
+
className: e("flex min-w-0 justify-between gap-basalt-space-lg text-basalt-base font-medium tracking-tight text-basalt-foreground", n ? "w-full items-center rounded-none rounded-t-basalt-lg last:rounded-b-basalt-lg data-[state=closed]:rounded-b-basalt-lg px-basalt-card py-basalt-card-sm data-[state=open]:border-b data-[state=open]:border-basalt-border" : r ? "items-start p-basalt-card border-b border-basalt-border" : "items-start px-basalt-card pt-basalt-card pb-0", n && "basalt-focus basalt-focus-inset", t),
|
|
39
40
|
...i
|
|
40
41
|
});
|
|
41
42
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layer-card.js","names":["ROOT_CLASSES","BASALT_UI_CLASS","PADDING_CLASSES","isElement","isValidElement","child","hasSlot","Children","children","match","Fragment","LayerCardRoot","forwardRef","props","structured","STRUCTURED_TYPES","type","cn","padding","outlined","className","LayerCardHeader","asChild","Slot","divided","LayerCardBody","LayerCardWell","LayerCardPrimary","LayerCardSecondary","LayerCardFooter","LayerCardLoading","label","SkeletonLine","LayerCardEmpty","Empty","LayerCard"],"sources":["../../src/components/layer-card.tsx"],"sourcesContent":["import { Slot } from \"@radix-ui/react-slot\";\nimport {\n\tChildren,\n\tFragment,\n\tforwardRef,\n\ttype HTMLAttributes,\n\tisValidElement,\n\ttype ReactElement,\n\ttype ReactNode,\n} from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { BASALT_UI_CLASS } from \"../utils/control-surface\";\nimport { Empty } from \"./empty\";\nimport { SkeletonLine } from \"./skeleton-line\";\n\nconst ROOT_CLASSES = `${BASALT_UI_CLASS} overflow-hidden rounded-basalt-lg ring-1 ring-basalt-border/50 text-basalt-foreground`;\nconst PADDING_CLASSES = {\n\tnone: \"\",\n\tsm: \"p-basalt-card-sm\",\n\tmd: \"p-basalt-card\",\n\tlg: \"p-basalt-card-lg\",\n\txl: \"p-basalt-card-xl\",\n} as const;\n\nexport type LayerCardPadding = keyof typeof PADDING_CLASSES;\n\nexport type LayerCardProps = Omit<HTMLAttributes<HTMLDivElement>, \"className\"> & {\n\t/**\n\t * Additional classes for the card root.\n\t */\n\tclassName?: string;\n\t/**\n\t * Strengthen the default perimeter hairline.\n\t * @default false\n\t */\n\toutlined?: boolean;\n\t/**\n\t * Inner spacing for unstructured card content.\n\t * @default \"md\"\n\t */\n\tpadding?: LayerCardPadding;\n};\nexport type LayerCardSectionProps = HTMLAttributes<HTMLDivElement>;\nexport type LayerCardHeaderProps = LayerCardSectionProps & {\n\t/** Apply header insets to one child, such as a CollapsibleTrigger, without another wrapper. @default false */\n\tasChild?: boolean;\n\t/** Separate the header from its body with a divider. @default false */\n\tdivided?: boolean;\n};\nexport type LayerCardWellProps = LayerCardSectionProps & {\n\t/**\n\t * Draw a hairline ring on a nested well.\n\t * @default false\n\t */\n\toutlined?: boolean;\n};\nexport type LayerCardLoadingProps = Omit<HTMLAttributes<HTMLDivElement>, \"aria-label\"> & {\n\t/**\n\t * Accessible label announced for the loading state.\n\t * @default \"Loading\"\n\t */\n\tlabel?: string;\n};\nexport type LayerCardEmptyProps = Omit<HTMLAttributes<HTMLDivElement>, \"title\" | \"children\"> & {\n\t/**\n\t * Empty-state heading.\n\t * @default \"No content\"\n\t */\n\ttitle?: string;\n\t/**\n\t * Supporting empty-state text.\n\t */\n\tdescription?: string;\n\t/**\n\t * Optional empty-state icon.\n\t */\n\ticon?: ReactNode;\n\t/**\n\t * Optional interactive action element rendered below empty content.\n\t */\n\taction?: ReactNode;\n\t/**\n\t * Custom supporting content or custom layout rendered between description and action.\n\t */\n\tchildren?: ReactNode;\n};\n\nfunction isElement(child: ReactNode): child is ReactElement<{ children?: ReactNode }> {\n\treturn isValidElement(child);\n}\n\nfunction hasSlot(children: ReactNode, match: (type: unknown) => boolean): boolean {\n\treturn Children.toArray(children).some((child) => {\n\t\tif (!isElement(child)) {\n\t\t\treturn false;\n\t\t}\n\t\tif (match(child.type)) {\n\t\t\treturn true;\n\t\t}\n\t\tif (child.type === Fragment) {\n\t\t\treturn hasSlot(child.props.children, match);\n\t\t}\n\t\treturn false;\n\t});\n}\n\nconst LayerCardRoot = forwardRef<HTMLDivElement, LayerCardProps>(\n\t({ className, children, outlined = false, padding = \"md\", ...props }, ref) => {\n\t\tconst structured = hasSlot(children, (type) => STRUCTURED_TYPES.has(type));\n\t\treturn (\n\t\t\t<div\n\t\t\t\tref={ref}\n\t\t\t\tdata-basalt-surface=\"\"\n\t\t\t\tdata-card-structured={structured || undefined}\n\t\t\t\tclassName={cn(\n\t\t\t\t\tROOT_CLASSES,\n\t\t\t\t\tstructured ? \"flex w-full flex-col\" : PADDING_CLASSES[padding],\n\t\t\t\t\toutlined && \"ring-basalt-border\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</div>\n\t\t);\n\t},\n);\nLayerCardRoot.displayName = \"LayerCard\";\n\nfunction LayerCardHeader({\n\tclassName,\n\tasChild = false,\n\tdivided = false,\n\t...props\n}: LayerCardHeaderProps) {\n\tconst Component = asChild ? Slot : \"div\";\n\treturn (\n\t\t<Component\n\t\t\tdata-slot=\"card-header\"\n\t\t\tclassName={cn(\n\t\t\t\t\"flex min-w-0 justify-between gap-basalt-space-lg text-basalt-base font-medium tracking-tight text-basalt-foreground\",\n\t\t\t\tasChild\n\t\t\t\t\t? \"w-full items-center px-basalt-card py-basalt-card-sm data-[state=open]:border-b data-[state=open]:border-basalt-border\"\n\t\t\t\t\t: divided\n\t\t\t\t\t\t? \"items-start p-basalt-card border-b border-basalt-border\"\n\t\t\t\t\t\t: \"items-start px-basalt-card pt-basalt-card pb-0\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\nLayerCardHeader.displayName = \"LayerCard.Header\";\n\nfunction LayerCardBody({ className, ...props }: LayerCardSectionProps) {\n\treturn (\n\t\t<div data-slot=\"card-body\" className={cn(\"min-w-0 p-basalt-card\", className)} {...props} />\n\t);\n}\nLayerCardBody.displayName = \"LayerCard.Body\";\n\nfunction LayerCardWell({ className, outlined = false, ...props }: LayerCardWellProps) {\n\treturn (\n\t\t<div\n\t\t\tdata-basalt-surface=\"\"\n\t\t\tclassName={cn(\"min-w-0 p-basalt-card\", outlined && \"ring-1 ring-basalt-border/40\", className)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\nLayerCardWell.displayName = \"LayerCard.Well\";\n\nfunction LayerCardPrimary(props: LayerCardWellProps) {\n\treturn <LayerCardWell {...props} />;\n}\nLayerCardPrimary.displayName = \"LayerCard.Primary\";\n\nfunction LayerCardSecondary(props: LayerCardHeaderProps) {\n\treturn <LayerCardHeader {...props} />;\n}\nLayerCardSecondary.displayName = \"LayerCard.Secondary\";\n\nfunction LayerCardFooter({ className, ...props }: LayerCardSectionProps) {\n\treturn (\n\t\t<div\n\t\t\tclassName={cn(\n\t\t\t\t\"flex flex-wrap items-center justify-end gap-basalt-space-lg border-t border-basalt-border px-basalt-card py-basalt-card-sm\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\nLayerCardFooter.displayName = \"LayerCard.Footer\";\n\nfunction LayerCardLoading({ label = \"Loading\", className, ...props }: LayerCardLoadingProps) {\n\treturn (\n\t\t<div\n\t\t\trole=\"status\"\n\t\t\taria-label={label}\n\t\t\tclassName={cn(\"space-y-basalt-space-lg p-basalt-card\", className)}\n\t\t\t{...props}\n\t\t>\n\t\t\t<SkeletonLine minWidth={100} maxWidth={100} />\n\t\t\t<SkeletonLine minWidth={72} maxWidth={72} />\n\t\t\t<SkeletonLine minWidth={88} maxWidth={88} />\n\t\t</div>\n\t);\n}\nLayerCardLoading.displayName = \"LayerCard.Loading\";\n\nfunction LayerCardEmpty({ title = \"No content\", className, ...props }: LayerCardEmptyProps) {\n\treturn <Empty title={title} className={cn(\"p-basalt-card\", className)} {...props} />;\n}\nLayerCardEmpty.displayName = \"LayerCard.Empty\";\n\nconst STRUCTURED_TYPES = new Set<unknown>([\n\tLayerCardHeader,\n\tLayerCardBody,\n\tLayerCardWell,\n\tLayerCardFooter,\n\tLayerCardLoading,\n\tLayerCardEmpty,\n\tLayerCardPrimary,\n\tLayerCardSecondary,\n]);\n\nexport const LayerCard = Object.assign(LayerCardRoot, {\n\tPrimary: LayerCardPrimary,\n\tSecondary: LayerCardSecondary,\n\tHeader: LayerCardHeader,\n\tBody: LayerCardBody,\n\tWell: LayerCardWell,\n\tFooter: LayerCardFooter,\n\tLoading: LayerCardLoading,\n\tEmpty: LayerCardEmpty,\n});\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"layer-card.js","names":["ROOT_CLASSES","BASALT_UI_CLASS","PADDING_CLASSES","isElement","isValidElement","child","hasSlot","Children","children","match","Fragment","LayerCardRoot","forwardRef","props","structured","STRUCTURED_TYPES","type","cn","padding","outlined","className","LayerCardHeader","asChild","Slot","divided","LayerCardBody","LayerCardWell","LayerCardPrimary","LayerCardSecondary","LayerCardFooter","LayerCardLoading","label","SkeletonLine","LayerCardEmpty","Empty","LayerCard"],"sources":["../../src/components/layer-card.tsx"],"sourcesContent":["import { Slot } from \"@radix-ui/react-slot\";\nimport {\n\tChildren,\n\tFragment,\n\tforwardRef,\n\ttype HTMLAttributes,\n\tisValidElement,\n\ttype ReactElement,\n\ttype ReactNode,\n} from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { BASALT_UI_CLASS } from \"../utils/control-surface\";\nimport { Empty } from \"./empty\";\nimport { FOCUS_INSET } from \"./overlay\";\nimport { SkeletonLine } from \"./skeleton-line\";\n\nconst ROOT_CLASSES = `${BASALT_UI_CLASS} overflow-hidden rounded-basalt-lg ring-1 ring-basalt-border/50 text-basalt-foreground`;\nconst PADDING_CLASSES = {\n\tnone: \"\",\n\tsm: \"p-basalt-card-sm\",\n\tmd: \"p-basalt-card\",\n\tlg: \"p-basalt-card-lg\",\n\txl: \"p-basalt-card-xl\",\n} as const;\n\nexport type LayerCardPadding = keyof typeof PADDING_CLASSES;\n\nexport type LayerCardProps = Omit<HTMLAttributes<HTMLDivElement>, \"className\"> & {\n\t/**\n\t * Additional classes for the card root.\n\t */\n\tclassName?: string;\n\t/**\n\t * Strengthen the default perimeter hairline.\n\t * @default false\n\t */\n\toutlined?: boolean;\n\t/**\n\t * Inner spacing for unstructured card content.\n\t * @default \"md\"\n\t */\n\tpadding?: LayerCardPadding;\n};\nexport type LayerCardSectionProps = HTMLAttributes<HTMLDivElement>;\nexport type LayerCardHeaderProps = LayerCardSectionProps & {\n\t/** Apply header insets to one child, such as a CollapsibleTrigger, without another wrapper. @default false */\n\tasChild?: boolean;\n\t/** Separate the header from its body with a divider. @default false */\n\tdivided?: boolean;\n};\nexport type LayerCardWellProps = LayerCardSectionProps & {\n\t/**\n\t * Draw a hairline ring on a nested well.\n\t * @default false\n\t */\n\toutlined?: boolean;\n};\nexport type LayerCardLoadingProps = Omit<HTMLAttributes<HTMLDivElement>, \"aria-label\"> & {\n\t/**\n\t * Accessible label announced for the loading state.\n\t * @default \"Loading\"\n\t */\n\tlabel?: string;\n};\nexport type LayerCardEmptyProps = Omit<HTMLAttributes<HTMLDivElement>, \"title\" | \"children\"> & {\n\t/**\n\t * Empty-state heading.\n\t * @default \"No content\"\n\t */\n\ttitle?: string;\n\t/**\n\t * Supporting empty-state text.\n\t */\n\tdescription?: string;\n\t/**\n\t * Optional empty-state icon.\n\t */\n\ticon?: ReactNode;\n\t/**\n\t * Optional interactive action element rendered below empty content.\n\t */\n\taction?: ReactNode;\n\t/**\n\t * Custom supporting content or custom layout rendered between description and action.\n\t */\n\tchildren?: ReactNode;\n};\n\nfunction isElement(child: ReactNode): child is ReactElement<{ children?: ReactNode }> {\n\treturn isValidElement(child);\n}\n\nfunction hasSlot(children: ReactNode, match: (type: unknown) => boolean): boolean {\n\treturn Children.toArray(children).some((child) => {\n\t\tif (!isElement(child)) {\n\t\t\treturn false;\n\t\t}\n\t\tif (match(child.type)) {\n\t\t\treturn true;\n\t\t}\n\t\tif (child.type === Fragment) {\n\t\t\treturn hasSlot(child.props.children, match);\n\t\t}\n\t\treturn false;\n\t});\n}\n\nconst LayerCardRoot = forwardRef<HTMLDivElement, LayerCardProps>(\n\t({ className, children, outlined = false, padding = \"md\", ...props }, ref) => {\n\t\tconst structured = hasSlot(children, (type) => STRUCTURED_TYPES.has(type));\n\t\treturn (\n\t\t\t<div\n\t\t\t\tref={ref}\n\t\t\t\tdata-basalt-surface=\"\"\n\t\t\t\tdata-card-structured={structured || undefined}\n\t\t\t\tclassName={cn(\n\t\t\t\t\tROOT_CLASSES,\n\t\t\t\t\tstructured ? \"flex w-full flex-col\" : PADDING_CLASSES[padding],\n\t\t\t\t\toutlined && \"ring-basalt-border\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</div>\n\t\t);\n\t},\n);\nLayerCardRoot.displayName = \"LayerCard\";\n\nfunction LayerCardHeader({\n\tclassName,\n\tasChild = false,\n\tdivided = false,\n\t...props\n}: LayerCardHeaderProps) {\n\tconst Component = asChild ? Slot : \"div\";\n\treturn (\n\t\t<Component\n\t\t\tdata-slot=\"card-header\"\n\t\t\tclassName={cn(\n\t\t\t\t\"flex min-w-0 justify-between gap-basalt-space-lg text-basalt-base font-medium tracking-tight text-basalt-foreground\",\n\t\t\t\tasChild\n\t\t\t\t\t? \"w-full items-center rounded-none rounded-t-basalt-lg last:rounded-b-basalt-lg data-[state=closed]:rounded-b-basalt-lg px-basalt-card py-basalt-card-sm data-[state=open]:border-b data-[state=open]:border-basalt-border\"\n\t\t\t\t\t: divided\n\t\t\t\t\t\t? \"items-start p-basalt-card border-b border-basalt-border\"\n\t\t\t\t\t\t: \"items-start px-basalt-card pt-basalt-card pb-0\",\n\t\t\t\tasChild && FOCUS_INSET,\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\nLayerCardHeader.displayName = \"LayerCard.Header\";\n\nfunction LayerCardBody({ className, ...props }: LayerCardSectionProps) {\n\treturn (\n\t\t<div data-slot=\"card-body\" className={cn(\"min-w-0 p-basalt-card\", className)} {...props} />\n\t);\n}\nLayerCardBody.displayName = \"LayerCard.Body\";\n\nfunction LayerCardWell({ className, outlined = false, ...props }: LayerCardWellProps) {\n\treturn (\n\t\t<div\n\t\t\tdata-basalt-surface=\"\"\n\t\t\tclassName={cn(\"min-w-0 p-basalt-card\", outlined && \"ring-1 ring-basalt-border/40\", className)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\nLayerCardWell.displayName = \"LayerCard.Well\";\n\nfunction LayerCardPrimary(props: LayerCardWellProps) {\n\treturn <LayerCardWell {...props} />;\n}\nLayerCardPrimary.displayName = \"LayerCard.Primary\";\n\nfunction LayerCardSecondary(props: LayerCardHeaderProps) {\n\treturn <LayerCardHeader {...props} />;\n}\nLayerCardSecondary.displayName = \"LayerCard.Secondary\";\n\nfunction LayerCardFooter({ className, ...props }: LayerCardSectionProps) {\n\treturn (\n\t\t<div\n\t\t\tclassName={cn(\n\t\t\t\t\"flex flex-wrap items-center justify-end gap-basalt-space-lg border-t border-basalt-border px-basalt-card py-basalt-card-sm\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\nLayerCardFooter.displayName = \"LayerCard.Footer\";\n\nfunction LayerCardLoading({ label = \"Loading\", className, ...props }: LayerCardLoadingProps) {\n\treturn (\n\t\t<div\n\t\t\trole=\"status\"\n\t\t\taria-label={label}\n\t\t\tclassName={cn(\"space-y-basalt-space-lg p-basalt-card\", className)}\n\t\t\t{...props}\n\t\t>\n\t\t\t<SkeletonLine minWidth={100} maxWidth={100} />\n\t\t\t<SkeletonLine minWidth={72} maxWidth={72} />\n\t\t\t<SkeletonLine minWidth={88} maxWidth={88} />\n\t\t</div>\n\t);\n}\nLayerCardLoading.displayName = \"LayerCard.Loading\";\n\nfunction LayerCardEmpty({ title = \"No content\", className, ...props }: LayerCardEmptyProps) {\n\treturn <Empty title={title} className={cn(\"p-basalt-card\", className)} {...props} />;\n}\nLayerCardEmpty.displayName = \"LayerCard.Empty\";\n\nconst STRUCTURED_TYPES = new Set<unknown>([\n\tLayerCardHeader,\n\tLayerCardBody,\n\tLayerCardWell,\n\tLayerCardFooter,\n\tLayerCardLoading,\n\tLayerCardEmpty,\n\tLayerCardPrimary,\n\tLayerCardSecondary,\n]);\n\nexport const LayerCard = Object.assign(LayerCardRoot, {\n\tPrimary: LayerCardPrimary,\n\tSecondary: LayerCardSecondary,\n\tHeader: LayerCardHeader,\n\tBody: LayerCardBody,\n\tWell: LayerCardWell,\n\tFooter: LayerCardFooter,\n\tLoading: LayerCardLoading,\n\tEmpty: LayerCardEmpty,\n});\n"],"mappings":"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"}
|
package/dist/components/link.js
CHANGED
|
@@ -7,7 +7,7 @@ function r({ className: r, href: i, children: a, ...o }) {
|
|
|
7
7
|
let s = t();
|
|
8
8
|
return /* @__PURE__ */ n(s, {
|
|
9
9
|
href: i,
|
|
10
|
-
className: e("text-basalt-primary underline-offset-4 hover:underline", r),
|
|
10
|
+
className: e("basalt-focus text-basalt-primary underline-offset-4 hover:underline", r),
|
|
11
11
|
...o,
|
|
12
12
|
children: a
|
|
13
13
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"link.js","names":["Link","props","Comp","useLinkComponent","cn","className"],"sources":["../../src/components/link.tsx"],"sourcesContent":["import type * as React from \"react\";\nimport { useLinkComponent } from \"../providers/link\";\nimport { cn } from \"../utils/cn\";\n\nexport type LinkProps = Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, \"href\"> &\n\tRecord<string, unknown> & {\n\t\t/**\n\t\t * The link destination.\n\t\t */\n\t\thref: string;\n\t};\n\nexport function Link({ className, href, children, ...props }: LinkProps) {\n\tconst Comp = useLinkComponent();\n\treturn (\n\t\t<Comp\n\t\t\thref={href}\n\t\t\tclassName={cn(\"text-basalt-primary underline-offset-4 hover:underline\"
|
|
1
|
+
{"version":3,"file":"link.js","names":["Link","props","Comp","useLinkComponent","cn","className"],"sources":["../../src/components/link.tsx"],"sourcesContent":["import type * as React from \"react\";\nimport { useLinkComponent } from \"../providers/link\";\nimport { cn } from \"../utils/cn\";\n\nexport type LinkProps = Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, \"href\"> &\n\tRecord<string, unknown> & {\n\t\t/**\n\t\t * The link destination.\n\t\t */\n\t\thref: string;\n\t};\n\nexport function Link({ className, href, children, ...props }: LinkProps) {\n\tconst Comp = useLinkComponent();\n\treturn (\n\t\t<Comp\n\t\t\thref={href}\n\t\t\tclassName={cn(\n\t\t\t\t\"basalt-focus text-basalt-primary underline-offset-4 hover:underline\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t>\n\t\t\t{children}\n\t\t</Comp>\n\t);\n}\n"],"mappings":";;;;;AAYA,SAAgBA,EAAK,EAAE,cAAW,SAAM,aAAU,GAAGC,KAAoB;CACxE,IAAMC,IAAOC,EAAiB;CAC9B,OACC,kBAACD,GAAD;EACO;EACN,WAAWE,EACV,uEACAC,CACD;EACA,GAAIJ;EAEH;CACI,CAAA;AAER"}
|
|
@@ -15,7 +15,7 @@ function l(e) {
|
|
|
15
15
|
}
|
|
16
16
|
var u = a.forwardRef(({ className: n, ...r }, i) => /* @__PURE__ */ o(s.Trigger, {
|
|
17
17
|
ref: i,
|
|
18
|
-
className: e(t, "inline-flex min-h-basalt-control items-center rounded-basalt-sm px-basalt-space-lg text-basalt-base font-medium
|
|
18
|
+
className: e(t, "basalt-focus basalt-focus-inset inline-flex min-h-basalt-control items-center rounded-basalt-sm px-basalt-space-lg text-basalt-base font-medium hover:bg-basalt-hover data-[state=open]:bg-basalt-selected", n),
|
|
19
19
|
...r
|
|
20
20
|
}));
|
|
21
21
|
u.displayName = s.Trigger.displayName;
|
|
@@ -35,7 +35,7 @@ d.displayName = s.Content.displayName;
|
|
|
35
35
|
var f = a.forwardRef(({ className: t, ...r }, i) => /* @__PURE__ */ o(s.Item, {
|
|
36
36
|
"data-basalt-hover-item": "",
|
|
37
37
|
ref: i,
|
|
38
|
-
className: n(e("relative
|
|
38
|
+
className: n(e("relative", t)),
|
|
39
39
|
...r
|
|
40
40
|
}));
|
|
41
41
|
f.displayName = s.Item.displayName;
|