@dev-dga/react 0.8.3 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/dist/{chunk-EFKAKU2X.js → chunk-66EVFQVL.js} +2 -2
  3. package/dist/{chunk-SOIZIH7F.js → chunk-6DN3JE3P.js} +10 -1
  4. package/dist/chunk-6DN3JE3P.js.map +1 -0
  5. package/dist/{chunk-D7BZ6L4Z.cjs → chunk-BBGCS5PZ.cjs} +7 -2
  6. package/dist/chunk-BBGCS5PZ.cjs.map +1 -0
  7. package/dist/{chunk-MUM6HKPT.js → chunk-BTP7G7WR.js} +7 -2
  8. package/dist/chunk-BTP7G7WR.js.map +1 -0
  9. package/dist/{chunk-LES7CZSC.cjs → chunk-CISRE6BC.cjs} +14 -3
  10. package/dist/chunk-CISRE6BC.cjs.map +1 -0
  11. package/dist/{chunk-4ZCLTLVC.cjs → chunk-CVQFSXRR.cjs} +10 -1
  12. package/dist/chunk-CVQFSXRR.cjs.map +1 -0
  13. package/dist/{chunk-BNULFLPC.js → chunk-HBAHWCBK.js} +14 -3
  14. package/dist/chunk-HBAHWCBK.js.map +1 -0
  15. package/dist/{chunk-54GIEP6E.cjs → chunk-I6BOBHO6.cjs} +7 -2
  16. package/dist/chunk-I6BOBHO6.cjs.map +1 -0
  17. package/dist/{chunk-DBB47IAX.js → chunk-IFB53HNO.js} +1 -1
  18. package/dist/chunk-IFB53HNO.js.map +1 -0
  19. package/dist/{chunk-TWCX4EZR.js → chunk-JOJ23OD4.js} +6 -1
  20. package/dist/{chunk-TWCX4EZR.js.map → chunk-JOJ23OD4.js.map} +1 -1
  21. package/dist/{chunk-PI4OPECU.cjs → chunk-LG2IADSZ.cjs} +1 -1
  22. package/dist/{chunk-PI4OPECU.cjs.map → chunk-LG2IADSZ.cjs.map} +1 -1
  23. package/dist/{chunk-CHE75QHA.js → chunk-MCHL23CE.js} +1 -1
  24. package/dist/{chunk-CHE75QHA.js.map → chunk-MCHL23CE.js.map} +1 -1
  25. package/dist/{chunk-MWOGVEQB.cjs → chunk-NUC6WJU4.cjs} +5 -5
  26. package/dist/{chunk-MWOGVEQB.cjs.map → chunk-NUC6WJU4.cjs.map} +1 -1
  27. package/dist/{chunk-JQO3EFLX.cjs → chunk-PAUY27WX.cjs} +3 -14
  28. package/dist/chunk-PAUY27WX.cjs.map +1 -0
  29. package/dist/{chunk-6A73DWVA.js → chunk-UAECZXU5.js} +3 -14
  30. package/dist/chunk-UAECZXU5.js.map +1 -0
  31. package/dist/{chunk-43763K2A.cjs → chunk-WI4WQGF6.cjs} +1 -1
  32. package/dist/{chunk-43763K2A.cjs.map → chunk-WI4WQGF6.cjs.map} +1 -1
  33. package/dist/components/Combobox/Combobox.cjs +2 -2
  34. package/dist/components/Combobox/Combobox.js +1 -1
  35. package/dist/components/Combobox/index.cjs +2 -2
  36. package/dist/components/Combobox/index.js +1 -1
  37. package/dist/components/DateRangePicker/DateRangePicker.cjs +2 -2
  38. package/dist/components/DateRangePicker/DateRangePicker.js +1 -1
  39. package/dist/components/DateRangePicker/index.cjs +2 -2
  40. package/dist/components/DateRangePicker/index.js +1 -1
  41. package/dist/components/Modal/Modal.cjs +4 -2
  42. package/dist/components/Modal/Modal.cjs.map +1 -1
  43. package/dist/components/Modal/Modal.js +3 -1
  44. package/dist/components/Modal/index.cjs +4 -2
  45. package/dist/components/Modal/index.cjs.map +1 -1
  46. package/dist/components/Modal/index.js +3 -1
  47. package/dist/components/ScrollArea/ScrollArea.cjs +2 -2
  48. package/dist/components/ScrollArea/ScrollArea.js +1 -1
  49. package/dist/components/ScrollArea/index.cjs +2 -2
  50. package/dist/components/ScrollArea/index.js +1 -1
  51. package/dist/components/Sidebar/Sidebar.cjs +2 -2
  52. package/dist/components/Sidebar/Sidebar.js +1 -1
  53. package/dist/components/Sidebar/SidebarMenu.cjs +3 -3
  54. package/dist/components/Sidebar/SidebarMenu.js +2 -2
  55. package/dist/components/Sidebar/index.cjs +4 -4
  56. package/dist/components/Sidebar/index.js +3 -3
  57. package/dist/components/TagInput/TagInput.cjs +2 -2
  58. package/dist/components/TagInput/TagInput.js +1 -1
  59. package/dist/components/TagInput/index.cjs +2 -2
  60. package/dist/components/TagInput/index.js +1 -1
  61. package/dist/components/Tooltip/Tooltip.cjs +2 -2
  62. package/dist/components/Tooltip/Tooltip.js +1 -1
  63. package/dist/components/Tooltip/index.cjs +2 -2
  64. package/dist/components/Tooltip/index.js +1 -1
  65. package/dist/index.cjs +19 -17
  66. package/dist/index.cjs.map +1 -1
  67. package/dist/index.d.cts +20 -6
  68. package/dist/index.d.ts +20 -6
  69. package/dist/index.js +22 -20
  70. package/package.json +3 -3
  71. package/dist/chunk-4ZCLTLVC.cjs.map +0 -1
  72. package/dist/chunk-54GIEP6E.cjs.map +0 -1
  73. package/dist/chunk-6A73DWVA.js.map +0 -1
  74. package/dist/chunk-BNULFLPC.js.map +0 -1
  75. package/dist/chunk-D7BZ6L4Z.cjs.map +0 -1
  76. package/dist/chunk-DBB47IAX.js.map +0 -1
  77. package/dist/chunk-JQO3EFLX.cjs.map +0 -1
  78. package/dist/chunk-LES7CZSC.cjs.map +0 -1
  79. package/dist/chunk-MUM6HKPT.js.map +0 -1
  80. package/dist/chunk-SOIZIH7F.js.map +0 -1
  81. /package/dist/{chunk-EFKAKU2X.js.map → chunk-66EVFQVL.js.map} +0 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # @dev-dga/react
2
2
 
3
+ ## 0.9.0
4
+
5
+ ### Minor Changes
6
+
7
+ - **Modal — new `<ModalBody>` scroll region.** A scrollable middle slot (mirrors `<DrawerBody>`): tall modal content scrolls inside it while the header and footer stay pinned, capped at the viewport with **zero consumer config** — no hand-rolled `<div style={{ maxHeight, overflow }}>` wrapper. Short, non-scrolling bodies can still drop content directly under `ModalContent`. Additive export; existing modals are unaffected.
8
+ - **Sidebar — `<SidebarInset scrollable>` opt-in.** Pass `scrollable` to make the inset its own vertical scroll region (tall content scrolls inside it; the sidebar + footer stay put) with **no consumer `flex`/`min-block-size`/`overflow` CSS**. The whole inset scrolls (header included); for a fixed header with only the body scrolling, leave it off and compose a nested scroll region (the App-shell pattern). Additive prop; default behavior unchanged.
9
+
10
+ ### Patch Changes
11
+
12
+ - **TagInput — required indicator.** `required` now renders the same `*` asterisk as every other text-entry control (Input/Textarea/…) and sets `aria-required` on the field. It deliberately does **not** set the native `required` attribute on the inner input — that holds the draft text, so native `required` would block form submit while committed tags exist.
13
+ - **Combobox — a11y dev-warning.** When `label` is a non-string node and no `aria-label`/`aria-labelledby` is given (the options popover then falls back to the untranslated name "Options"), a dev-only `console.warn` points to the fix. No production/runtime change.
14
+ - **Tooltip — docs.** JSDoc now states `Tooltip` must be rendered inside `<DgaProvider>` (which supplies the required Radix `TooltipProvider`).
15
+ - **ScrollArea — dead-class cleanup.** Stopped emitting the unused `--vertical` / `--horizontal` / `--both` modifier classes (no stylesheet matched them; orientation is driven by which scrollbar renders). `scrollAreaVariants` stays exported.
16
+ - Rides the `@dev-dga/css` Sidebar full-height + collapsed-rail + Skeleton + disabled-opacity changes in lockstep (see that changelog). Released in lockstep with `@dev-dga/css` and `@dev-dga/tokens`.
17
+
3
18
  ## 0.8.3
4
19
 
5
20
  ### Patch Changes
@@ -2,7 +2,7 @@ import {
2
2
  Tooltip,
3
3
  TooltipContent,
4
4
  TooltipTrigger
5
- } from "./chunk-DBB47IAX.js";
5
+ } from "./chunk-IFB53HNO.js";
6
6
  import {
7
7
  useSidebar
8
8
  } from "./chunk-F7NPGAKU.js";
@@ -174,4 +174,4 @@ export {
174
174
  sidebarMenuSubButtonVariants,
175
175
  SidebarMenuSubButton
176
176
  };
177
- //# sourceMappingURL=chunk-EFKAKU2X.js.map
177
+ //# sourceMappingURL=chunk-66EVFQVL.js.map
@@ -53,6 +53,14 @@ function useComboboxContext(component) {
53
53
  }
54
54
  return ctx;
55
55
  }
56
+ function warnRichLabelNeedsAriaLabel(label, ariaLabel, ariaLabelledBy) {
57
+ if (process.env.NODE_ENV === "production") return;
58
+ if (ariaLabel || ariaLabelledBy) return;
59
+ if (label === void 0 || label === null || typeof label === "string") return;
60
+ console.warn(
61
+ '[dga/Combobox] `label` is a non-string node and no `aria-label`/`aria-labelledby` was given, so the options popover falls back to the untranslated name "Options". Pass a localized `aria-label` to name the popover for screen-reader users.'
62
+ );
63
+ }
56
64
  function Combobox({
57
65
  value: controlledValue,
58
66
  defaultValue,
@@ -77,6 +85,7 @@ function Combobox({
77
85
  "aria-label": ariaLabel,
78
86
  "aria-labelledby": ariaLabelledBy
79
87
  }) {
88
+ warnRichLabelNeedsAriaLabel(label, ariaLabel, ariaLabelledBy);
80
89
  const [internalValue, setInternalValue] = useState(defaultValue);
81
90
  const isControlled = controlledValue !== void 0;
82
91
  const value = isControlled ? controlledValue : internalValue;
@@ -259,4 +268,4 @@ export {
259
268
  ComboboxGroup,
260
269
  ComboboxSeparator
261
270
  };
262
- //# sourceMappingURL=chunk-SOIZIH7F.js.map
271
+ //# sourceMappingURL=chunk-6DN3JE3P.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/Combobox/Combobox.tsx"],"sourcesContent":["'use client';\n\nimport {\n Children,\n createContext,\n isValidElement,\n useCallback,\n useContext,\n useId,\n useMemo,\n useState,\n type ReactNode,\n} from 'react';\nimport { Command } from 'cmdk';\nimport { Popover as PopoverPrimitive } from 'radix-ui';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { cn } from '../../utils/cn';\nimport { Check, ChevronDown } from '../../internal/icons';\nimport { useFieldA11y, FieldMessage } from '../../field';\nimport { DgaContext } from '../../providers/DgaContext';\n\n// ─── 1. Variants ─── //\n\n// Trigger height matches Input/Select so a Combobox lines up in a form row.\nconst comboboxTriggerVariants = cva('ddga-combobox-trigger', {\n variants: {\n size: {\n sm: 'ddga-combobox-trigger--sm',\n md: 'ddga-combobox-trigger--md',\n },\n error: {\n true: 'ddga-combobox-trigger--error',\n },\n },\n defaultVariants: {\n size: 'md',\n },\n});\n\n// Keep a no-op `comboboxVariants` for parity with the project's barrel\n// convention (every component re-exports a *Variants from its barrel).\nconst comboboxVariants = comboboxTriggerVariants;\n\n// ─── 2. Context (bridges Root state to Items + label lookup) ─── //\n//\n// Items register `value → label` on mount so the trigger can render the\n// selected option's human-readable label without consumers having to thread\n// a separate `displayValue` function in the common case. Async-loaded\n// options can still override via `<Combobox getLabel={...}>` below.\n\ninterface ComboboxContextValue {\n value?: string;\n select: (value: string) => void;\n}\n\nconst ComboboxContext = createContext<ComboboxContextValue | null>(null);\n\nfunction useComboboxContext(component: string): ComboboxContextValue {\n const ctx = useContext(ComboboxContext);\n if (!ctx) {\n throw new Error(`<${component}> must be rendered inside <Combobox>.`);\n }\n return ctx;\n}\n\n// ─── 3. Types ─── //\n\ninterface ComboboxProps extends VariantProps<typeof comboboxTriggerVariants> {\n /** Currently selected option value (controlled). */\n value?: string;\n /** Initial value when uncontrolled. */\n defaultValue?: string;\n /** Fires whenever the selection changes (controlled or uncontrolled). */\n onValueChange?: (value: string) => void;\n /** Controlled popover open state. */\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n /** Visible label above the trigger. */\n label?: ReactNode;\n /** Hint shown below the trigger when there's no error. */\n helperText?: ReactNode;\n /** Message shown below the trigger when `error` is true. */\n errorMessage?: ReactNode;\n /** Marks the field invalid — sets `aria-invalid` and the error border. */\n error?: boolean;\n /** Marks the field required — adds the asterisk + `aria-required`. */\n required?: boolean;\n /** Disables the trigger entirely. */\n disabled?: boolean;\n /** Placeholder shown in the trigger when no value is selected. */\n placeholder?: ReactNode;\n /** Placeholder for the search input inside the panel. Defaults to `\"Search…\"`. */\n searchPlaceholder?: string;\n /** Shown when no item matches the search query. Defaults to `\"No results.\"`. */\n emptyMessage?: ReactNode;\n /**\n * Override the trigger label resolver — useful when items are loaded async\n * after the value is set, or when the trigger should show a richer label\n * than the item's rendered children. Receives the current value, returns\n * the node to display. Falls back to the registered item's label.\n */\n getLabel?: (value: string) => ReactNode;\n /** Caller-supplied id for the trigger; falls back to a generated one. */\n id?: string;\n /** Forwarded to the trigger (the focusable button). */\n className?: string;\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n /** `<ComboboxItem>` (+ optional Group / Separator) children. */\n children: ReactNode;\n}\n\ninterface ComboboxItemProps extends Omit<\n React.ComponentProps<typeof Command.Item>,\n 'value' | 'onSelect'\n> {\n /** Stable value for filtering + selection. */\n value: string;\n /** Extra search terms cmdk should match against the input. */\n keywords?: string[];\n /** Disable this item from selection. */\n disabled?: boolean;\n /** Optional select handler — fires alongside the root's `onValueChange`. */\n onSelect?: (value: string) => void;\n}\n\ninterface ComboboxGroupProps extends React.ComponentProps<typeof Command.Group> {\n /** Group heading rendered above its items. */\n heading?: ReactNode;\n}\n\ntype ComboboxSeparatorProps = React.ComponentProps<typeof Command.Separator>;\n\n// ─── 4. Root ─── //\n\n// Dev-only nudge: when `label` is a rich (non-string) node and no\n// `aria-label`/`aria-labelledby` is given, the options popover (role=\"dialog\")\n// falls back to the untranslated name \"Options\". Point i18n-conscious consumers\n// at the fix. Mirrors the ScrollArea/Popover a11y warnings.\nfunction warnRichLabelNeedsAriaLabel(\n label: ReactNode,\n ariaLabel?: string,\n ariaLabelledBy?: string,\n) {\n if (process.env.NODE_ENV === 'production') return;\n if (ariaLabel || ariaLabelledBy) return;\n if (label === undefined || label === null || typeof label === 'string') return;\n console.warn(\n '[dga/Combobox] `label` is a non-string node and no `aria-label`/`aria-labelledby` was ' +\n 'given, so the options popover falls back to the untranslated name \"Options\". Pass a ' +\n 'localized `aria-label` to name the popover for screen-reader users.',\n );\n}\n\nfunction Combobox({\n value: controlledValue,\n defaultValue,\n onValueChange,\n open: controlledOpen,\n defaultOpen,\n onOpenChange,\n label,\n helperText,\n errorMessage,\n error,\n required,\n disabled,\n size,\n placeholder,\n searchPlaceholder = 'Search…',\n emptyMessage = 'No results.',\n getLabel,\n id: externalId,\n className,\n children,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n}: ComboboxProps) {\n warnRichLabelNeedsAriaLabel(label, ariaLabel, ariaLabelledBy);\n\n // Uncontrolled fallbacks.\n const [internalValue, setInternalValue] = useState<string | undefined>(defaultValue);\n const isControlled = controlledValue !== undefined;\n const value = isControlled ? controlledValue : internalValue;\n\n const [internalOpen, setInternalOpen] = useState(defaultOpen ?? false);\n const isOpenControlled = controlledOpen !== undefined;\n const open = isOpenControlled ? controlledOpen : internalOpen;\n\n const setOpen = useCallback(\n (next: boolean) => {\n if (!isOpenControlled) setInternalOpen(next);\n onOpenChange?.(next);\n },\n [isOpenControlled, onOpenChange],\n );\n\n const select = useCallback(\n (next: string) => {\n if (!isControlled) setInternalValue(next);\n onValueChange?.(next);\n setOpen(false);\n },\n [isControlled, onValueChange, setOpen],\n );\n\n const ctx = useMemo<ComboboxContextValue>(() => ({ value, select }), [value, select]);\n\n // Walk `children` once to build a value → label map. Synchronous so the\n // trigger shows the right label on first render — registration via\n // useEffect would only fire when items mount, and items don't mount until\n // the popover opens (Radix Portal lazy-mounts). Recurses through\n // `ComboboxGroup` so grouped items still resolve. Bare children only —\n // doesn't dive into arbitrary nested DOM.\n const itemLabels = useMemo<Map<string, ReactNode>>(() => {\n const map = new Map<string, ReactNode>();\n const visit = (nodes: ReactNode): void => {\n Children.forEach(nodes, (child) => {\n if (!isValidElement(child)) return;\n const childProps = child.props as { value?: unknown; children?: ReactNode };\n if (typeof childProps.value === 'string') {\n map.set(childProps.value, childProps.children);\n } else if (childProps.children) {\n visit(childProps.children);\n }\n });\n };\n visit(children);\n return map;\n }, [children]);\n\n // Field a11y wiring — same primitive as Select.\n const { fieldId, errorId, helperId, hasError, hasErrorMessage, hasHelper, controlProps } =\n useFieldA11y({\n name: 'Combobox',\n id: externalId,\n label,\n error,\n errorMessage,\n helperText,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n });\n\n // Portal anchored to DgaProvider root (mirrors Select/Modal/DropdownMenu).\n const providerCtx = useContext(DgaContext);\n // Body-mounted portal target (see DgaProvider) — escapes ancestor\n // clipping while keeping theme inheritance via mirrored data-theme/vars.\n const portalContainer = providerCtx?.portalEl ?? providerCtx?.rootEl ?? undefined;\n\n // Trigger label — explicit override wins; otherwise look up from the\n // children-derived map; otherwise fall back to the placeholder.\n const triggerLabel = useMemo<ReactNode>(() => {\n if (value === undefined) return null;\n if (getLabel) return getLabel(value);\n return itemLabels.get(value) ?? null;\n }, [value, getLabel, itemLabels]);\n\n const searchId = useId();\n\n return (\n <ComboboxContext.Provider value={ctx}>\n <div data-slot=\"combobox-field\" className=\"ddga-field\">\n {label && (\n <label htmlFor={fieldId} className=\"ddga-combobox__label\">\n {label}\n {required && (\n <span aria-hidden=\"true\" className=\"ddga-combobox__required\">\n *\n </span>\n )}\n </label>\n )}\n <PopoverPrimitive.Root open={open} onOpenChange={setOpen}>\n <PopoverPrimitive.Trigger asChild>\n <button\n type=\"button\"\n {...controlProps}\n // Trigger stays a plain button — Radix Popover.Trigger sets\n // aria-haspopup + aria-expanded + aria-controls so AT users\n // hear \"Pick a fruit, button, has popup\". We declared role=\"combobox\"\n // earlier but it requires aria-controls pointing to the listbox,\n // which Radix wires for dialog semantics — axe flagged the mismatch.\n aria-required={required || undefined}\n disabled={disabled}\n data-slot=\"combobox-trigger\"\n className={cn(comboboxTriggerVariants({ size, error: hasError }), className)}\n >\n <span className=\"ddga-combobox__value\">\n {triggerLabel ?? <span className=\"ddga-combobox__placeholder\">{placeholder}</span>}\n </span>\n <ChevronDown aria-hidden=\"true\" className=\"ddga-combobox__icon\" />\n </button>\n </PopoverPrimitive.Trigger>\n <PopoverPrimitive.Portal container={portalContainer}>\n <PopoverPrimitive.Content\n data-slot=\"combobox-content\"\n className=\"ddga-combobox-content\"\n sideOffset={4}\n align=\"start\"\n // Popover.Content is role=\"dialog\" → axe requires an accessible\n // name. Use the field label when it's a string; otherwise fall\n // back to a generic \"Options\" so a11y stays valid even when the\n // consumer composes a rich React node as the label.\n aria-label={ariaLabel ?? (typeof label === 'string' ? label : 'Options')}\n aria-labelledby={ariaLabelledBy}\n // Match trigger width so the panel doesn't visually float over.\n style={{ inlineSize: 'var(--radix-popover-trigger-width)' }}\n onOpenAutoFocus={(event) => {\n // cmdk handles its own focus management (Input gets focused on\n // mount via autoFocus below). Prevent Radix from also moving\n // focus or we lose the search input as the auto-focus target.\n event.preventDefault();\n }}\n >\n <Command\n id={searchId}\n data-slot=\"combobox-command\"\n className=\"ddga-combobox-command\"\n // cmdk's default filter matches if the input is a substring of\n // the item value OR any keyword — fine for our v1 use case.\n >\n <Command.Input\n autoFocus\n placeholder={searchPlaceholder}\n data-slot=\"combobox-input\"\n className=\"ddga-combobox-input\"\n />\n <Command.List data-slot=\"combobox-list\" className=\"ddga-combobox-list\">\n <Command.Empty data-slot=\"combobox-empty\" className=\"ddga-combobox-empty\">\n {emptyMessage}\n </Command.Empty>\n {children}\n </Command.List>\n </Command>\n </PopoverPrimitive.Content>\n </PopoverPrimitive.Portal>\n </PopoverPrimitive.Root>\n {hasErrorMessage && (\n <FieldMessage id={errorId} variant=\"error\">\n {errorMessage}\n </FieldMessage>\n )}\n {hasHelper && (\n <FieldMessage id={helperId} variant=\"helper\">\n {helperText}\n </FieldMessage>\n )}\n </div>\n </ComboboxContext.Provider>\n );\n}\n\n// ─── 5. Item ─── //\n\nfunction ComboboxItem({\n value,\n keywords,\n disabled,\n onSelect,\n className,\n children,\n ...props\n}: ComboboxItemProps) {\n const { value: selectedValue, select } = useComboboxContext('ComboboxItem');\n\n const isSelected = selectedValue === value;\n\n return (\n <Command.Item\n value={value}\n keywords={keywords}\n disabled={disabled}\n onSelect={(v) => {\n onSelect?.(v);\n select(v);\n }}\n data-slot=\"combobox-item\"\n // cmdk owns `data-selected` for keyboard highlight — use a separate\n // attribute for the chosen value so the two don't collide.\n data-active={isSelected ? '' : undefined}\n className={cn('ddga-combobox-item', className)}\n {...props}\n >\n <span className=\"ddga-combobox-item__check\" aria-hidden=\"true\">\n {isSelected ? <Check /> : null}\n </span>\n <span className=\"ddga-combobox-item__label\">{children}</span>\n </Command.Item>\n );\n}\n\n// ─── 6. Group + Separator (cmdk passthroughs) ─── //\n\nfunction ComboboxGroup({ className, heading, ...props }: ComboboxGroupProps) {\n return (\n <Command.Group\n heading={heading}\n data-slot=\"combobox-group\"\n className={cn('ddga-combobox-group', className)}\n {...props}\n />\n );\n}\n\nfunction ComboboxSeparator({ className, ...props }: ComboboxSeparatorProps) {\n return (\n <Command.Separator\n data-slot=\"combobox-separator\"\n className={cn('ddga-combobox-separator', className)}\n {...props}\n />\n );\n}\n\n// ─── 7. Exports ─── //\n\nexport {\n Combobox,\n ComboboxItem,\n ComboboxGroup,\n ComboboxSeparator,\n comboboxTriggerVariants,\n comboboxVariants,\n};\nexport type { ComboboxProps, ComboboxItemProps, ComboboxGroupProps, ComboboxSeparatorProps };\n"],"mappings":"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","names":[]}
@@ -41,6 +41,7 @@ function TagInput({
41
41
  error,
42
42
  size,
43
43
  disabled,
44
+ required,
44
45
  placeholder,
45
46
  max,
46
47
  allowDuplicates = false,
@@ -144,7 +145,10 @@ function TagInput({
144
145
  };
145
146
  const chipSize = size === "lg" ? "md" : "sm";
146
147
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { "data-slot": "tag-input-field", className: "ddga-field", children: [
147
- label && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "label", { htmlFor: fieldId, className: "ddga-tag-input__label", children: label }),
148
+ label && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "label", { htmlFor: fieldId, className: "ddga-tag-input__label", children: [
149
+ label,
150
+ required && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { "aria-hidden": "true", className: "ddga-tag-input__required", children: "*" })
151
+ ] }),
148
152
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
149
153
  "div",
150
154
  {
@@ -185,6 +189,7 @@ function TagInput({
185
189
  type: "text",
186
190
  value: draft,
187
191
  disabled,
192
+ "aria-required": required || void 0,
188
193
  placeholder: tags.length === 0 ? placeholder : void 0,
189
194
  onChange: (event) => setDraft(event.target.value),
190
195
  onKeyDown: handleKeyDown,
@@ -204,4 +209,4 @@ function TagInput({
204
209
 
205
210
 
206
211
  exports.tagInputVariants = tagInputVariants; exports.TagInput = TagInput;
207
- //# sourceMappingURL=chunk-D7BZ6L4Z.cjs.map
212
+ //# sourceMappingURL=chunk-BBGCS5PZ.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/home/devdhaif/work/react/dga-dev/packages/react/dist/chunk-BBGCS5PZ.cjs","../src/components/TagInput/TagInput.tsx"],"names":[],"mappings":"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","file":"/home/devdhaif/work/react/dga-dev/packages/react/dist/chunk-BBGCS5PZ.cjs","sourcesContent":[null,"'use client';\n\nimport { useRef, useState, type ReactNode } from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { cn } from '../../utils/cn';\nimport { useFieldA11y, FieldMessage } from '../../field';\nimport { Badge, type BadgeProps } from '../Badge';\n\n// ─── 1. Variants (cva) ─── //\n\n// Applied to the *control* (the bordered box), not the raw <input> — the box\n// owns the border, sizing, focus ring and disabled/error styling so the chips\n// and the text input wrap inside the field. Mirrors Input's box, but the box\n// grows vertically as chips wrap (min-block-size, not a fixed height).\nconst tagInputVariants = cva('ddga-tag-input', {\n variants: {\n size: {\n sm: 'ddga-tag-input--sm',\n md: 'ddga-tag-input--md',\n lg: 'ddga-tag-input--lg',\n },\n error: {\n true: 'ddga-tag-input--error',\n },\n },\n defaultVariants: {\n size: 'md',\n },\n});\n\n// ─── 2. Types ─── //\n\n// We own `value` / `defaultValue` (string[] tags, not strings), `onChange`\n// (fires with the tag array), and the design-system `size` variant — so they\n// are stripped from the native input props the rest are spread onto.\ntype NativeInputProps = Omit<\n React.ComponentProps<'input'>,\n 'value' | 'defaultValue' | 'onChange' | 'size'\n>;\n\ninterface TagInputProps\n extends NativeInputProps, Omit<VariantProps<typeof tagInputVariants>, 'error'> {\n /** Controlled tag list. */\n value?: string[];\n /** Uncontrolled initial tag list. */\n defaultValue?: string[];\n /** Fires with the full accepted tag set after every add/remove. */\n onChange?: (tags: string[]) => void;\n /** Visible field label, associated to the text input. */\n label?: ReactNode;\n /** Hint shown below the field. Hidden while an error message is showing. */\n helperText?: ReactNode;\n /** Message shown below the field when invalid. */\n errorMessage?: ReactNode;\n /** Marks the field invalid: sets `aria-invalid` and error styling. */\n error?: boolean;\n /** Caps the number of tags. Adds beyond the cap are no-ops. */\n max?: number;\n /** Allow the same tag more than once. Off → duplicates are rejected. */\n allowDuplicates?: boolean;\n /** Make duplicate detection case-sensitive. Default: case-insensitive. */\n caseSensitive?: boolean;\n /** Consumer gate run on each candidate tag. Return false to reject (draft kept). */\n validate?: (tag: string, tags: string[]) => boolean;\n /** Characters that commit the draft and split a paste. Newline always splits a paste. */\n delimiters?: string[];\n /** Badge variant used for the chips. */\n chipVariant?: BadgeProps['variant'];\n /** Accessible name for each chip's remove button. */\n removeLabel?: (tag: string) => string;\n /** Live-region text announced on add/remove (screen readers). */\n formatAnnouncement?: (tag: string, action: 'add' | 'remove') => string;\n}\n\n// ─── 3. Component ─── //\n\nfunction TagInput({\n id: externalId,\n value,\n defaultValue,\n onChange,\n label,\n helperText,\n errorMessage,\n error,\n size,\n disabled,\n required,\n placeholder,\n max,\n allowDuplicates = false,\n caseSensitive = false,\n validate,\n delimiters = [','],\n chipVariant = 'secondary',\n removeLabel = (tag) => `Remove ${tag}`,\n formatAnnouncement = (tag, action) => `${tag} ${action === 'add' ? 'added' : 'removed'}`,\n className,\n ...props\n}: TagInputProps) {\n const isControlled = value !== undefined;\n const [uncontrolledTags, setUncontrolledTags] = useState<string[]>(defaultValue ?? []);\n const tags = isControlled ? value : uncontrolledTags;\n\n const [draft, setDraft] = useState('');\n const [announcement, setAnnouncement] = useState('');\n const inputRef = useRef<HTMLInputElement>(null);\n\n const { fieldId, errorId, helperId, hasError, hasErrorMessage, hasHelper, controlProps } =\n useFieldA11y({\n name: 'TagInput',\n id: externalId,\n label,\n error,\n errorMessage,\n helperText,\n 'aria-label': props['aria-label'],\n 'aria-labelledby': props['aria-labelledby'],\n });\n\n const commit = (next: string[]) => {\n if (!isControlled) setUncontrolledTags(next);\n onChange?.(next);\n };\n\n const norm = (t: string) => (caseSensitive ? t : t.toLowerCase());\n\n // Run raw fragments through the full accept pipeline (trim → drop-empty →\n // max cap → dedup → validate), appending the survivors. Only ever appends,\n // so the accepted set is `next.slice(current.length)`.\n const accept = (raw: string[], current: string[]): string[] => {\n let next = current;\n for (const fragment of raw) {\n const trimmed = fragment.trim();\n if (!trimmed) continue;\n if (max !== undefined && next.length >= max) break;\n if (!allowDuplicates && next.some((t) => norm(t) === norm(trimmed))) continue;\n if (validate && !validate(trimmed, next)) continue;\n next = [...next, trimmed];\n }\n return next;\n };\n\n const announceAdded = (added: string[]) => {\n if (added.length > 0) {\n setAnnouncement(added.map((t) => formatAnnouncement(t, 'add')).join(', '));\n }\n };\n\n const commitDraft = () => {\n const next = accept([draft], tags);\n if (next.length > tags.length) {\n commit(next);\n announceAdded(next.slice(tags.length));\n setDraft('');\n }\n // Rejected (dup / max / validate / empty): keep the draft so it can be fixed.\n };\n\n // Build a paste splitter from the delimiter chars + newlines. `-` is escaped\n // too (trailing in the class) so a delimiter like `-` can't form an invalid\n // character-class range (e.g. `['|','-']` → `[|-…]` would throw).\n const splitPaste = (text: string): string[] => {\n const escaped = delimiters.map((d) => d.replace(/[.*+?^${}()|[\\]\\\\-]/g, '\\\\$&'));\n const pattern = new RegExp(`[${escaped.join('')}\\\\n\\\\r]`);\n return text.split(pattern);\n };\n\n const removeTag = (index: number) => {\n const removed = tags[index];\n commit(tags.filter((_, i) => i !== index));\n setAnnouncement(formatAnnouncement(removed, 'remove'));\n inputRef.current?.focus();\n };\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {\n if (disabled) return;\n if (event.key === 'Enter') {\n // Always swallow Enter so it adds a tag instead of submitting the form.\n event.preventDefault();\n if (draft.trim()) commitDraft();\n } else if (delimiters.includes(event.key)) {\n event.preventDefault();\n if (draft.trim()) commitDraft();\n } else if (event.key === 'Backspace' && draft === '' && tags.length > 0) {\n event.preventDefault();\n removeTag(tags.length - 1);\n }\n };\n\n const handlePaste = (event: React.ClipboardEvent<HTMLInputElement>) => {\n if (disabled) return;\n const text = event.clipboardData.getData('text');\n const fragments = splitPaste(text);\n // No delimiter in the pasted text → let it type normally into the draft.\n if (fragments.length <= 1) return;\n event.preventDefault();\n const next = accept(fragments, tags);\n if (next.length > tags.length) {\n commit(next);\n announceAdded(next.slice(tags.length));\n // Clear any in-progress draft so it isn't left stranded after the paste.\n setDraft('');\n }\n };\n\n // Clicking the box chrome (not a chip button or the input) focuses the input.\n const handleBoxMouseDown = (event: React.MouseEvent<HTMLDivElement>) => {\n const target = event.target as HTMLElement;\n if (target === inputRef.current || target.closest('button')) return;\n event.preventDefault();\n inputRef.current?.focus();\n };\n\n const chipSize: BadgeProps['size'] = size === 'lg' ? 'md' : 'sm';\n\n return (\n <div data-slot=\"tag-input-field\" className=\"ddga-field\">\n {label && (\n <label htmlFor={fieldId} className=\"ddga-tag-input__label\">\n {label}\n {required && (\n <span aria-hidden=\"true\" className=\"ddga-tag-input__required\">\n *\n </span>\n )}\n </label>\n )}\n <div\n data-slot=\"tag-input-control\"\n className={cn(tagInputVariants({ size, error: hasError }), className)}\n data-disabled={disabled || undefined}\n onMouseDown={disabled ? undefined : handleBoxMouseDown}\n >\n {tags.length > 0 && (\n <ul data-slot=\"tag-input-list\" className=\"ddga-tag-input__list\" role=\"list\">\n {tags.map((tag, index) => (\n <li\n // Tags can repeat (allowDuplicates) so the value alone is not a\n // stable key; pair it with the index.\n key={`${tag}-${index}`}\n data-slot=\"tag-input-item\"\n className=\"ddga-tag-input__item\"\n // `display:contents` on the list/item can drop the implicit\n // list semantics in some engines; re-assert them explicitly.\n role=\"listitem\"\n >\n <Badge\n variant={chipVariant}\n size={chipSize}\n // Controlled-open: the chip never self-hides — removal flows\n // through onChange so controlled consumers stay the source of truth.\n open\n dismissible={!disabled}\n onDismiss={() => removeTag(index)}\n closeLabel={removeLabel(tag)}\n >\n {tag}\n </Badge>\n </li>\n ))}\n </ul>\n )}\n <input\n // Spread consumer props first, then our a11y contract + handlers so\n // they cannot be clobbered.\n {...props}\n {...controlProps}\n ref={inputRef}\n data-slot=\"tag-input\"\n className=\"ddga-tag-input__field\"\n type=\"text\"\n value={draft}\n disabled={disabled}\n // `aria-required` (not native `required`): the input holds the draft,\n // not the committed tags, so native `required` would block form\n // submit whenever the draft is empty even though tags exist.\n aria-required={required || undefined}\n placeholder={tags.length === 0 ? placeholder : undefined}\n onChange={(event) => setDraft(event.target.value)}\n onKeyDown={handleKeyDown}\n onPaste={handlePaste}\n />\n </div>\n <div data-slot=\"tag-input-live\" className=\"ddga-sr-only\" role=\"status\" aria-live=\"polite\">\n {announcement}\n </div>\n {hasErrorMessage && (\n <FieldMessage id={errorId} variant=\"error\">\n {errorMessage}\n </FieldMessage>\n )}\n {hasHelper && (\n <FieldMessage id={helperId} variant=\"helper\">\n {helperText}\n </FieldMessage>\n )}\n </div>\n );\n}\n\n// ─── 4. Exports ─── //\n\nexport { TagInput, tagInputVariants };\nexport type { TagInputProps };\n"]}
@@ -41,6 +41,7 @@ function TagInput({
41
41
  error,
42
42
  size,
43
43
  disabled,
44
+ required,
44
45
  placeholder,
45
46
  max,
46
47
  allowDuplicates = false,
@@ -144,7 +145,10 @@ function TagInput({
144
145
  };
145
146
  const chipSize = size === "lg" ? "md" : "sm";
146
147
  return /* @__PURE__ */ jsxs("div", { "data-slot": "tag-input-field", className: "ddga-field", children: [
147
- label && /* @__PURE__ */ jsx("label", { htmlFor: fieldId, className: "ddga-tag-input__label", children: label }),
148
+ label && /* @__PURE__ */ jsxs("label", { htmlFor: fieldId, className: "ddga-tag-input__label", children: [
149
+ label,
150
+ required && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "ddga-tag-input__required", children: "*" })
151
+ ] }),
148
152
  /* @__PURE__ */ jsxs(
149
153
  "div",
150
154
  {
@@ -185,6 +189,7 @@ function TagInput({
185
189
  type: "text",
186
190
  value: draft,
187
191
  disabled,
192
+ "aria-required": required || void 0,
188
193
  placeholder: tags.length === 0 ? placeholder : void 0,
189
194
  onChange: (event) => setDraft(event.target.value),
190
195
  onKeyDown: handleKeyDown,
@@ -204,4 +209,4 @@ export {
204
209
  tagInputVariants,
205
210
  TagInput
206
211
  };
207
- //# sourceMappingURL=chunk-MUM6HKPT.js.map
212
+ //# sourceMappingURL=chunk-BTP7G7WR.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/TagInput/TagInput.tsx"],"sourcesContent":["'use client';\n\nimport { useRef, useState, type ReactNode } from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { cn } from '../../utils/cn';\nimport { useFieldA11y, FieldMessage } from '../../field';\nimport { Badge, type BadgeProps } from '../Badge';\n\n// ─── 1. Variants (cva) ─── //\n\n// Applied to the *control* (the bordered box), not the raw <input> — the box\n// owns the border, sizing, focus ring and disabled/error styling so the chips\n// and the text input wrap inside the field. Mirrors Input's box, but the box\n// grows vertically as chips wrap (min-block-size, not a fixed height).\nconst tagInputVariants = cva('ddga-tag-input', {\n variants: {\n size: {\n sm: 'ddga-tag-input--sm',\n md: 'ddga-tag-input--md',\n lg: 'ddga-tag-input--lg',\n },\n error: {\n true: 'ddga-tag-input--error',\n },\n },\n defaultVariants: {\n size: 'md',\n },\n});\n\n// ─── 2. Types ─── //\n\n// We own `value` / `defaultValue` (string[] tags, not strings), `onChange`\n// (fires with the tag array), and the design-system `size` variant — so they\n// are stripped from the native input props the rest are spread onto.\ntype NativeInputProps = Omit<\n React.ComponentProps<'input'>,\n 'value' | 'defaultValue' | 'onChange' | 'size'\n>;\n\ninterface TagInputProps\n extends NativeInputProps, Omit<VariantProps<typeof tagInputVariants>, 'error'> {\n /** Controlled tag list. */\n value?: string[];\n /** Uncontrolled initial tag list. */\n defaultValue?: string[];\n /** Fires with the full accepted tag set after every add/remove. */\n onChange?: (tags: string[]) => void;\n /** Visible field label, associated to the text input. */\n label?: ReactNode;\n /** Hint shown below the field. Hidden while an error message is showing. */\n helperText?: ReactNode;\n /** Message shown below the field when invalid. */\n errorMessage?: ReactNode;\n /** Marks the field invalid: sets `aria-invalid` and error styling. */\n error?: boolean;\n /** Caps the number of tags. Adds beyond the cap are no-ops. */\n max?: number;\n /** Allow the same tag more than once. Off → duplicates are rejected. */\n allowDuplicates?: boolean;\n /** Make duplicate detection case-sensitive. Default: case-insensitive. */\n caseSensitive?: boolean;\n /** Consumer gate run on each candidate tag. Return false to reject (draft kept). */\n validate?: (tag: string, tags: string[]) => boolean;\n /** Characters that commit the draft and split a paste. Newline always splits a paste. */\n delimiters?: string[];\n /** Badge variant used for the chips. */\n chipVariant?: BadgeProps['variant'];\n /** Accessible name for each chip's remove button. */\n removeLabel?: (tag: string) => string;\n /** Live-region text announced on add/remove (screen readers). */\n formatAnnouncement?: (tag: string, action: 'add' | 'remove') => string;\n}\n\n// ─── 3. Component ─── //\n\nfunction TagInput({\n id: externalId,\n value,\n defaultValue,\n onChange,\n label,\n helperText,\n errorMessage,\n error,\n size,\n disabled,\n required,\n placeholder,\n max,\n allowDuplicates = false,\n caseSensitive = false,\n validate,\n delimiters = [','],\n chipVariant = 'secondary',\n removeLabel = (tag) => `Remove ${tag}`,\n formatAnnouncement = (tag, action) => `${tag} ${action === 'add' ? 'added' : 'removed'}`,\n className,\n ...props\n}: TagInputProps) {\n const isControlled = value !== undefined;\n const [uncontrolledTags, setUncontrolledTags] = useState<string[]>(defaultValue ?? []);\n const tags = isControlled ? value : uncontrolledTags;\n\n const [draft, setDraft] = useState('');\n const [announcement, setAnnouncement] = useState('');\n const inputRef = useRef<HTMLInputElement>(null);\n\n const { fieldId, errorId, helperId, hasError, hasErrorMessage, hasHelper, controlProps } =\n useFieldA11y({\n name: 'TagInput',\n id: externalId,\n label,\n error,\n errorMessage,\n helperText,\n 'aria-label': props['aria-label'],\n 'aria-labelledby': props['aria-labelledby'],\n });\n\n const commit = (next: string[]) => {\n if (!isControlled) setUncontrolledTags(next);\n onChange?.(next);\n };\n\n const norm = (t: string) => (caseSensitive ? t : t.toLowerCase());\n\n // Run raw fragments through the full accept pipeline (trim → drop-empty →\n // max cap → dedup → validate), appending the survivors. Only ever appends,\n // so the accepted set is `next.slice(current.length)`.\n const accept = (raw: string[], current: string[]): string[] => {\n let next = current;\n for (const fragment of raw) {\n const trimmed = fragment.trim();\n if (!trimmed) continue;\n if (max !== undefined && next.length >= max) break;\n if (!allowDuplicates && next.some((t) => norm(t) === norm(trimmed))) continue;\n if (validate && !validate(trimmed, next)) continue;\n next = [...next, trimmed];\n }\n return next;\n };\n\n const announceAdded = (added: string[]) => {\n if (added.length > 0) {\n setAnnouncement(added.map((t) => formatAnnouncement(t, 'add')).join(', '));\n }\n };\n\n const commitDraft = () => {\n const next = accept([draft], tags);\n if (next.length > tags.length) {\n commit(next);\n announceAdded(next.slice(tags.length));\n setDraft('');\n }\n // Rejected (dup / max / validate / empty): keep the draft so it can be fixed.\n };\n\n // Build a paste splitter from the delimiter chars + newlines. `-` is escaped\n // too (trailing in the class) so a delimiter like `-` can't form an invalid\n // character-class range (e.g. `['|','-']` → `[|-…]` would throw).\n const splitPaste = (text: string): string[] => {\n const escaped = delimiters.map((d) => d.replace(/[.*+?^${}()|[\\]\\\\-]/g, '\\\\$&'));\n const pattern = new RegExp(`[${escaped.join('')}\\\\n\\\\r]`);\n return text.split(pattern);\n };\n\n const removeTag = (index: number) => {\n const removed = tags[index];\n commit(tags.filter((_, i) => i !== index));\n setAnnouncement(formatAnnouncement(removed, 'remove'));\n inputRef.current?.focus();\n };\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {\n if (disabled) return;\n if (event.key === 'Enter') {\n // Always swallow Enter so it adds a tag instead of submitting the form.\n event.preventDefault();\n if (draft.trim()) commitDraft();\n } else if (delimiters.includes(event.key)) {\n event.preventDefault();\n if (draft.trim()) commitDraft();\n } else if (event.key === 'Backspace' && draft === '' && tags.length > 0) {\n event.preventDefault();\n removeTag(tags.length - 1);\n }\n };\n\n const handlePaste = (event: React.ClipboardEvent<HTMLInputElement>) => {\n if (disabled) return;\n const text = event.clipboardData.getData('text');\n const fragments = splitPaste(text);\n // No delimiter in the pasted text → let it type normally into the draft.\n if (fragments.length <= 1) return;\n event.preventDefault();\n const next = accept(fragments, tags);\n if (next.length > tags.length) {\n commit(next);\n announceAdded(next.slice(tags.length));\n // Clear any in-progress draft so it isn't left stranded after the paste.\n setDraft('');\n }\n };\n\n // Clicking the box chrome (not a chip button or the input) focuses the input.\n const handleBoxMouseDown = (event: React.MouseEvent<HTMLDivElement>) => {\n const target = event.target as HTMLElement;\n if (target === inputRef.current || target.closest('button')) return;\n event.preventDefault();\n inputRef.current?.focus();\n };\n\n const chipSize: BadgeProps['size'] = size === 'lg' ? 'md' : 'sm';\n\n return (\n <div data-slot=\"tag-input-field\" className=\"ddga-field\">\n {label && (\n <label htmlFor={fieldId} className=\"ddga-tag-input__label\">\n {label}\n {required && (\n <span aria-hidden=\"true\" className=\"ddga-tag-input__required\">\n *\n </span>\n )}\n </label>\n )}\n <div\n data-slot=\"tag-input-control\"\n className={cn(tagInputVariants({ size, error: hasError }), className)}\n data-disabled={disabled || undefined}\n onMouseDown={disabled ? undefined : handleBoxMouseDown}\n >\n {tags.length > 0 && (\n <ul data-slot=\"tag-input-list\" className=\"ddga-tag-input__list\" role=\"list\">\n {tags.map((tag, index) => (\n <li\n // Tags can repeat (allowDuplicates) so the value alone is not a\n // stable key; pair it with the index.\n key={`${tag}-${index}`}\n data-slot=\"tag-input-item\"\n className=\"ddga-tag-input__item\"\n // `display:contents` on the list/item can drop the implicit\n // list semantics in some engines; re-assert them explicitly.\n role=\"listitem\"\n >\n <Badge\n variant={chipVariant}\n size={chipSize}\n // Controlled-open: the chip never self-hides — removal flows\n // through onChange so controlled consumers stay the source of truth.\n open\n dismissible={!disabled}\n onDismiss={() => removeTag(index)}\n closeLabel={removeLabel(tag)}\n >\n {tag}\n </Badge>\n </li>\n ))}\n </ul>\n )}\n <input\n // Spread consumer props first, then our a11y contract + handlers so\n // they cannot be clobbered.\n {...props}\n {...controlProps}\n ref={inputRef}\n data-slot=\"tag-input\"\n className=\"ddga-tag-input__field\"\n type=\"text\"\n value={draft}\n disabled={disabled}\n // `aria-required` (not native `required`): the input holds the draft,\n // not the committed tags, so native `required` would block form\n // submit whenever the draft is empty even though tags exist.\n aria-required={required || undefined}\n placeholder={tags.length === 0 ? placeholder : undefined}\n onChange={(event) => setDraft(event.target.value)}\n onKeyDown={handleKeyDown}\n onPaste={handlePaste}\n />\n </div>\n <div data-slot=\"tag-input-live\" className=\"ddga-sr-only\" role=\"status\" aria-live=\"polite\">\n {announcement}\n </div>\n {hasErrorMessage && (\n <FieldMessage id={errorId} variant=\"error\">\n {errorMessage}\n </FieldMessage>\n )}\n {hasHelper && (\n <FieldMessage id={helperId} variant=\"helper\">\n {helperText}\n </FieldMessage>\n )}\n </div>\n );\n}\n\n// ─── 4. Exports ─── //\n\nexport { TagInput, tagInputVariants };\nexport type { TagInputProps };\n"],"mappings":"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","names":[]}
@@ -171,9 +171,20 @@ function SidebarRail({
171
171
  }
172
172
  );
173
173
  }
174
- function SidebarInset({ asChild, className, ...props }) {
174
+ function SidebarInset({ asChild, scrollable, className, ...props }) {
175
175
  const Comp = asChild ? _radixui.Slot.Slot : "main";
176
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Comp, { "data-slot": "sidebar-inset", className: _chunkV6MXOJQ4cjs.cn.call(void 0, "ddga-sidebar-inset", className), ...props });
176
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
177
+ Comp,
178
+ {
179
+ "data-slot": "sidebar-inset",
180
+ className: _chunkV6MXOJQ4cjs.cn.call(void 0,
181
+ "ddga-sidebar-inset",
182
+ scrollable && "ddga-sidebar-inset--scrollable",
183
+ className
184
+ ),
185
+ ...props
186
+ }
187
+ );
177
188
  }
178
189
  function SidebarHeader({ asChild, className, ...props }) {
179
190
  const Comp = asChild ? _radixui.Slot.Slot : "div";
@@ -216,4 +227,4 @@ function SidebarSeparator({ className, ...props }) {
216
227
 
217
228
 
218
229
  exports.SidebarProvider = SidebarProvider; exports.Sidebar = Sidebar; exports.SidebarTrigger = SidebarTrigger; exports.SidebarRail = SidebarRail; exports.SidebarInset = SidebarInset; exports.SidebarHeader = SidebarHeader; exports.SidebarContent = SidebarContent; exports.SidebarFooter = SidebarFooter; exports.SidebarSeparator = SidebarSeparator;
219
- //# sourceMappingURL=chunk-LES7CZSC.cjs.map
230
+ //# sourceMappingURL=chunk-CISRE6BC.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/home/devdhaif/work/react/dga-dev/packages/react/dist/chunk-CISRE6BC.cjs","../src/components/Sidebar/Sidebar.tsx"],"names":["value"],"mappings":"AAAA;AACE;AACA;AACF,wDAA6B;AAC7B;AACE;AACF,wDAA6B;AAC7B;AACE;AACA;AACF,wDAA6B;AAC7B;AACE;AACF,wDAA6B;AAC7B;AACE;AACF,wDAA6B;AAC7B;AACA;AChBA,8BAA0D;AAC1D,mCAAsC;AAgFhC,+CAAA;AA3DN,SAAS,eAAA,CAAgB;AAAA,EACvB,YAAA,EAAc,IAAA;AAAA,EACd,IAAA,EAAM,QAAA;AAAA,EACN,YAAA;AAAA,EACA,iBAAA,EAAmB,GAAA;AAAA,EACnB,iBAAA,EAAmB,IAAA;AAAA,EACnB,SAAA;AAAA,EACA,KAAA;AAAA,EACA,QAAA;AAAA,EACA,GAAG;AACL,CAAA,EAAyB;AACvB,EAAA,MAAM,SAAA,EAAW,2CAAA,gBAA4B,CAAA;AAC7C,EAAA,MAAM,CAAC,UAAA,EAAY,aAAa,EAAA,EAAI,6BAAA,KAAc,CAAA;AAElD,EAAA,MAAM,aAAA,EAAe,SAAA,IAAa,KAAA,CAAA;AAClC,EAAA,MAAM,CAAC,YAAA,EAAc,eAAe,EAAA,EAAI,6BAAA,WAAoB,CAAA;AAC5D,EAAA,MAAM,KAAA,EAAO,aAAA,EAAgB,SAAA,EAAuB,YAAA;AAEpD,EAAA,MAAM,QAAA,EAAU,gCAAA;AAAA,IACd,CAACA,MAAAA,EAAAA,GAAmB;AAClB,MAAA,GAAA,CAAI,CAAC,YAAA,EAAc,eAAA,CAAgBA,MAAK,CAAA;AACxC,sBAAA,YAAA,wBAAA,CAAeA,MAAK,GAAA;AAAA,IACtB,CAAA;AAAA,IACA,CAAC,YAAA,EAAc,YAAY;AAAA,EAC7B,CAAA;AAEA,EAAA,MAAM,cAAA,EAAgB,gCAAA,CAAY,EAAA,GAAM;AACtC,IAAA,GAAA,CAAI,QAAA,EAAU;AACZ,MAAA,aAAA,CAAc,CAAC,CAAA,EAAA,GAAM,CAAC,CAAC,CAAA;AACvB,MAAA,MAAA;AAAA,IACF;AACA,IAAA,GAAA,CAAI,YAAA,EAAc;AAChB,sBAAA,YAAA,0BAAA,CAAe,CAAC,IAAI,GAAA;AAAA,IACtB,EAAA,KAAO;AACL,MAAA,eAAA,CAAgB,CAAC,CAAA,EAAA,GAAM,CAAC,CAAC,CAAA;AAAA,IAC3B;AAAA,EACF,CAAA,EAAG,CAAC,QAAA,EAAU,YAAA,EAAc,YAAA,EAAc,IAAI,CAAC,CAAA;AAE/C,EAAA,8BAAA,CAAU,EAAA,GAAM;AACd,IAAA,GAAA,CAAI,CAAC,gBAAA,EAAkB,MAAA;AACvB,IAAA,MAAM,UAAA,EAAY,CAAC,CAAA,EAAA,GAAqB;AACtC,MAAA,GAAA,CAAI,CAAA,CAAE,GAAA,CAAI,WAAA,CAAY,EAAA,IAAM,IAAA,GAAA,CAAQ,CAAA,CAAE,QAAA,GAAW,CAAA,CAAE,OAAA,CAAA,EAAU;AAC3D,QAAA,CAAA,CAAE,cAAA,CAAe,CAAA;AACjB,QAAA,aAAA,CAAc,CAAA;AAAA,MAChB;AAAA,IACF,CAAA;AACA,IAAA,MAAA,CAAO,gBAAA,CAAiB,SAAA,EAAW,SAAS,CAAA;AAC5C,IAAA,OAAO,CAAA,EAAA,GAAM,MAAA,CAAO,mBAAA,CAAoB,SAAA,EAAW,SAAS,CAAA;AAAA,EAC9D,CAAA,EAAG,CAAC,gBAAA,EAAkB,aAAa,CAAC,CAAA;AAEpC,EAAA,MAAM,MAAA,EAAkC,KAAA,EAAO,WAAA,EAAa,WAAA;AAE5D,EAAA,MAAM,MAAA,EAAQ,4BAAA;AAAA,IACZ,CAAA,EAAA,GAAA,CAAO,EAAE,KAAA,EAAO,IAAA,EAAM,OAAA,EAAS,UAAA,EAAY,aAAA,EAAe,QAAA,EAAU,cAAc,CAAA,CAAA;AAAA,IAClF,CAAC,KAAA,EAAO,IAAA,EAAM,OAAA,EAAS,UAAA,EAAY,QAAA,EAAU,aAAa;AAAA,EAC5D,CAAA;AAEA,EAAA,uBACE,6BAAA,gCAAC,CAAe,QAAA,EAAf,EAAwB,KAAA,EACvB,QAAA,kBAAA,6BAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,WAAA,EAAU,iBAAA;AAAA,MACV,SAAA,EAAW,kCAAA,sBAAG,EAAwB,SAAS,CAAA;AAAA,MAC/C,KAAA;AAAA,MACC,GAAG,KAAA;AAAA,MAEH;AAAA,IAAA;AAAA,EACH,EAAA,CACF,CAAA;AAEJ;AAWA,SAAS,OAAA,CAAQ;AAAA,EACf,QAAA,EAAU,SAAA;AAAA,EACV,YAAA,EAAc,MAAA;AAAA,EACd,KAAA,EAAO,OAAA;AAAA,EACP,SAAA;AAAA,EACA,QAAA;AAAA,EACA,YAAA,EAAc,UAAA,EAAY,SAAA;AAAA,EAC1B,GAAG;AACL,CAAA,EAAiB;AACf,EAAA,MAAM,EAAE,QAAA,EAAU,UAAA,EAAY,aAAA,EAAe,MAAM,EAAA,EAAI,0CAAA,CAAW;AAElE,EAAA,GAAA,CAAI,QAAA,EAAU;AACZ,IAAA,uBACE,6BAAA,wBAAC,EAAA,EAAO,IAAA,EAAM,UAAA,EAAY,YAAA,EAAc,aAAA,EACtC,QAAA,kBAAA,6BAAA;AAAA,MAAC,+BAAA;AAAA,MAAA;AAAA,QACC,IAAA;AAAA,QACA,IAAA,EAAK,IAAA;AAAA,QACL,YAAA,EAAY,SAAA;AAAA,QACZ,WAAA,EAAU,SAAA;AAAA,QACV,aAAA,EAAY,MAAA;AAAA,QACZ,cAAA,EAAc,OAAA;AAAA,QACd,WAAA,EAAW,IAAA;AAAA,QACX,SAAA,EAAW,kCAAA,cAAG,EAAgB,sBAAA,EAAwB,SAAS,CAAA;AAAA,QAC9D,GAAG,KAAA;AAAA,QAEH;AAAA,MAAA;AAAA,IACH,EAAA,CACF,CAAA;AAAA,EAEJ;AAEA,EAAA,uBACE,6BAAA;AAAA,IAAC,OAAA;AAAA,IAAA;AAAA,MACC,WAAA,EAAU,SAAA;AAAA,MACV,YAAA,EAAY,SAAA;AAAA,MACZ,YAAA,EAAY,KAAA;AAAA,MACZ,kBAAA,EAAkB,WAAA;AAAA,MAClB,cAAA,EAAc,OAAA;AAAA,MACd,WAAA,EAAW,IAAA;AAAA,MACX,SAAA,EAAW,kCAAA,cAAG,EAAgB,SAAS,CAAA;AAAA,MACtC,GAAG,KAAA;AAAA,MAEH;AAAA,IAAA;AAAA,EACH,CAAA;AAEJ;AAQA,SAAS,cAAA,CAAe;AAAA,EACtB,OAAA;AAAA,EACA,SAAA;AAAA,EACA,OAAA;AAAA,EACA,QAAA;AAAA,EACA,YAAA,EAAc,UAAA,EAAY,gBAAA;AAAA,EAC1B,GAAG;AACL,CAAA,EAAwB;AACtB,EAAA,MAAM,EAAE,aAAA,EAAe,IAAA,EAAM,UAAA,EAAY,SAAS,EAAA,EAAI,0CAAA,CAAW;AACjE,EAAA,MAAM,KAAA,EAAO,QAAA,EAAU,aAAA,CAAc,KAAA,EAAO,QAAA;AAC5C,EAAA,uBACE,6BAAA;AAAA,IAAC,IAAA;AAAA,IAAA;AAAA,MACC,IAAA,EAAM,QAAA,EAAU,KAAA,EAAA,EAAY,QAAA;AAAA,MAC5B,WAAA,EAAU,iBAAA;AAAA,MAEV,YAAA,EAAY,QAAA,EAAU,KAAA,EAAA,EAAY,SAAA;AAAA,MAClC,eAAA,EAAe,SAAA,EAAW,SAAA,EAAW,KAAA,CAAA;AAAA,MACrC,eAAA,EAAe,SAAA,EAAW,WAAA,EAAa,IAAA;AAAA,MACvC,SAAA,EAAW,kCAAA,uBAAG,EAAyB,SAAS,CAAA;AAAA,MAChD,OAAA,EAAS,CAAC,CAAA,EAAA,GAA2C;AACnD,wBAAA,OAAA,0BAAA,CAAU,CAAC,GAAA;AACX,QAAA,aAAA,CAAc,CAAA;AAAA,MAChB,CAAA;AAAA,MACC,GAAG,KAAA;AAAA,MAEH,QAAA,mBAAA,QAAA,0BAAY,6BAAA,2BAAC,EAAA,EAAU,aAAA,EAAY,OAAA,CAAO;AAAA,IAAA;AAAA,EAC7C,CAAA;AAEJ;AAEA,SAAS,WAAA,CAAY;AAAA,EACnB,SAAA;AAAA,EACA,YAAA,EAAc,UAAA,EAAY,gBAAA;AAAA,EAC1B,GAAG;AACL,CAAA,EAAmC;AACjC,EAAA,MAAM,EAAE,cAAc,EAAA,EAAI,0CAAA,CAAW;AACrC,EAAA,uBACE,6BAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,IAAA,EAAK,QAAA;AAAA,MACL,WAAA,EAAU,cAAA;AAAA,MACV,YAAA,EAAY,SAAA;AAAA,MACZ,KAAA,EAAO,SAAA;AAAA,MACP,QAAA,EAAU,CAAA,CAAA;AAAA,MACV,SAAA,EAAW,kCAAA,oBAAG,EAAsB,SAAS,CAAA;AAAA,MAC7C,OAAA,EAAS,aAAA;AAAA,MACR,GAAG;AAAA,IAAA;AAAA,EACN,CAAA;AAEJ;AAeA,SAAS,YAAA,CAAa,EAAE,OAAA,EAAS,UAAA,EAAY,SAAA,EAAW,GAAG,MAAM,CAAA,EAAsB;AACrF,EAAA,MAAM,KAAA,EAAO,QAAA,EAAU,aAAA,CAAc,KAAA,EAAO,MAAA;AAC5C,EAAA,uBACE,6BAAA;AAAA,IAAC,IAAA;AAAA,IAAA;AAAA,MACC,WAAA,EAAU,eAAA;AAAA,MACV,SAAA,EAAW,kCAAA;AAAA,QACT,oBAAA;AAAA,QACA,WAAA,GAAc,gCAAA;AAAA,QACd;AAAA,MACF,CAAA;AAAA,MACC,GAAG;AAAA,IAAA;AAAA,EACN,CAAA;AAEJ;AAMA,SAAS,aAAA,CAAc,EAAE,OAAA,EAAS,SAAA,EAAW,GAAG,MAAM,CAAA,EAAwB;AAC5E,EAAA,MAAM,KAAA,EAAO,QAAA,EAAU,aAAA,CAAc,KAAA,EAAO,KAAA;AAC5C,EAAA,uBACE,6BAAA,IAAC,EAAA,EAAK,WAAA,EAAU,gBAAA,EAAiB,SAAA,EAAW,kCAAA,sBAAG,EAAwB,SAAS,CAAA,EAAI,GAAG,MAAA,CAAO,CAAA;AAElG;AAEA,SAAS,cAAA,CAAe,EAAE,OAAA,EAAS,SAAA,EAAW,GAAG,MAAM,CAAA,EAAwB;AAC7E,EAAA,MAAM,KAAA,EAAO,QAAA,EAAU,aAAA,CAAc,KAAA,EAAO,KAAA;AAC5C,EAAA,uBACE,6BAAA;AAAA,IAAC,IAAA;AAAA,IAAA;AAAA,MACC,WAAA,EAAU,iBAAA;AAAA,MACV,SAAA,EAAW,kCAAA,uBAAG,EAAyB,SAAS,CAAA;AAAA,MAC/C,GAAG;AAAA,IAAA;AAAA,EACN,CAAA;AAEJ;AAEA,SAAS,aAAA,CAAc,EAAE,OAAA,EAAS,SAAA,EAAW,GAAG,MAAM,CAAA,EAAwB;AAC5E,EAAA,MAAM,KAAA,EAAO,QAAA,EAAU,aAAA,CAAc,KAAA,EAAO,KAAA;AAC5C,EAAA,uBACE,6BAAA,IAAC,EAAA,EAAK,WAAA,EAAU,gBAAA,EAAiB,SAAA,EAAW,kCAAA,sBAAG,EAAwB,SAAS,CAAA,EAAI,GAAG,MAAA,CAAO,CAAA;AAElG;AAEA,SAAS,gBAAA,CAAiB,EAAE,SAAA,EAAW,GAAG,MAAM,CAAA,EAA+B;AAC7E,EAAA,uBACE,6BAAA;AAAA,IAAC,IAAA;AAAA,IAAA;AAAA,MACC,WAAA,EAAU,mBAAA;AAAA,MACV,SAAA,EAAW,kCAAA,yBAAG,EAA2B,SAAS,CAAA;AAAA,MACjD,GAAG;AAAA,IAAA;AAAA,EACN,CAAA;AAEJ;ADvDA;AACA;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,0VAAC","file":"/home/devdhaif/work/react/dga-dev/packages/react/dist/chunk-CISRE6BC.cjs","sourcesContent":[null,"'use client';\n\nimport { useCallback, useEffect, useMemo, useState } from 'react';\nimport { Slot as SlotPrimitive } from 'radix-ui';\nimport { cn } from '../../utils/cn';\nimport { Drawer, DrawerContent } from '../Drawer';\nimport { PanelLeft } from '../../internal/icons';\nimport { SidebarContext, useSidebar, type SidebarContextValue } from './SidebarContext';\nimport { useIsMobile } from './useIsMobile';\n\n// ─── SidebarProvider ─── //\n\ninterface SidebarProviderProps extends React.ComponentProps<'div'> {\n /** Uncontrolled initial desktop state. Default true (expanded). */\n defaultOpen?: boolean;\n /** Controlled desktop open state. */\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n /** Viewport width (px) below which the mobile Drawer engages. Default 768. */\n mobileBreakpoint?: number;\n /** Register Cmd/Ctrl+B to toggle. Default true. */\n keyboardShortcut?: boolean;\n}\n\nfunction SidebarProvider({\n defaultOpen = true,\n open: openProp,\n onOpenChange,\n mobileBreakpoint = 768,\n keyboardShortcut = true,\n className,\n style,\n children,\n ...props\n}: SidebarProviderProps) {\n const isMobile = useIsMobile(mobileBreakpoint);\n const [openMobile, setOpenMobile] = useState(false);\n\n const isControlled = openProp !== undefined;\n const [openInternal, setOpenInternal] = useState(defaultOpen);\n const open = isControlled ? (openProp as boolean) : openInternal;\n\n const setOpen = useCallback(\n (value: boolean) => {\n if (!isControlled) setOpenInternal(value);\n onOpenChange?.(value);\n },\n [isControlled, onOpenChange],\n );\n\n const toggleSidebar = useCallback(() => {\n if (isMobile) {\n setOpenMobile((v) => !v);\n return;\n }\n if (isControlled) {\n onOpenChange?.(!open);\n } else {\n setOpenInternal((v) => !v);\n }\n }, [isMobile, isControlled, onOpenChange, open]);\n\n useEffect(() => {\n if (!keyboardShortcut) return;\n const onKeyDown = (e: KeyboardEvent) => {\n if (e.key.toLowerCase() === 'b' && (e.metaKey || e.ctrlKey)) {\n e.preventDefault();\n toggleSidebar();\n }\n };\n window.addEventListener('keydown', onKeyDown);\n return () => window.removeEventListener('keydown', onKeyDown);\n }, [keyboardShortcut, toggleSidebar]);\n\n const state: 'expanded' | 'collapsed' = open ? 'expanded' : 'collapsed';\n\n const value = useMemo<SidebarContextValue>(\n () => ({ state, open, setOpen, openMobile, setOpenMobile, isMobile, toggleSidebar }),\n [state, open, setOpen, openMobile, isMobile, toggleSidebar],\n );\n\n return (\n <SidebarContext.Provider value={value}>\n <div\n data-slot=\"sidebar-wrapper\"\n className={cn('ddga-sidebar-wrapper', className)}\n style={style}\n {...props}\n >\n {children}\n </div>\n </SidebarContext.Provider>\n );\n}\n\n// ─── Sidebar (container) ─── //\n\ninterface SidebarProps extends React.ComponentProps<'div'> {\n variant?: 'sidebar' | 'floating' | 'inset';\n collapsible?: 'icon' | 'offcanvas' | 'none';\n /** Logical side; flips with dir. Default 'start'. */\n side?: 'start' | 'end';\n}\n\nfunction Sidebar({\n variant = 'sidebar',\n collapsible = 'icon',\n side = 'start',\n className,\n children,\n 'aria-label': ariaLabel = 'Sidebar',\n ...props\n}: SidebarProps) {\n const { isMobile, openMobile, setOpenMobile, state } = useSidebar();\n\n if (isMobile) {\n return (\n <Drawer open={openMobile} onOpenChange={setOpenMobile}>\n <DrawerContent\n side={side}\n size=\"sm\"\n aria-label={ariaLabel}\n data-slot=\"sidebar\"\n data-mobile=\"true\"\n data-variant={variant}\n data-side={side}\n className={cn('ddga-sidebar', 'ddga-sidebar--mobile', className)}\n {...props}\n >\n {children}\n </DrawerContent>\n </Drawer>\n );\n }\n\n return (\n <aside\n data-slot=\"sidebar\"\n aria-label={ariaLabel}\n data-state={state}\n data-collapsible={collapsible}\n data-variant={variant}\n data-side={side}\n className={cn('ddga-sidebar', className)}\n {...props}\n >\n {children}\n </aside>\n );\n}\n\n// ─── Trigger / Rail / Inset ─── //\n\ninterface SidebarTriggerProps extends React.ComponentProps<'button'> {\n asChild?: boolean;\n}\n\nfunction SidebarTrigger({\n asChild,\n className,\n onClick,\n children,\n 'aria-label': ariaLabel = 'Toggle sidebar',\n ...props\n}: SidebarTriggerProps) {\n const { toggleSidebar, open, openMobile, isMobile } = useSidebar();\n const Comp = asChild ? SlotPrimitive.Slot : 'button';\n return (\n <Comp\n type={asChild ? undefined : 'button'}\n data-slot=\"sidebar-trigger\"\n // Don't override the child element's accessible name when asChild.\n aria-label={asChild ? undefined : ariaLabel}\n aria-haspopup={isMobile ? 'dialog' : undefined}\n aria-expanded={isMobile ? openMobile : open}\n className={cn('ddga-sidebar__trigger', className)}\n onClick={(e: React.MouseEvent<HTMLButtonElement>) => {\n onClick?.(e);\n toggleSidebar();\n }}\n {...props}\n >\n {children ?? <PanelLeft aria-hidden=\"true\" />}\n </Comp>\n );\n}\n\nfunction SidebarRail({\n className,\n 'aria-label': ariaLabel = 'Toggle sidebar',\n ...props\n}: React.ComponentProps<'button'>) {\n const { toggleSidebar } = useSidebar();\n return (\n <button\n type=\"button\"\n data-slot=\"sidebar-rail\"\n aria-label={ariaLabel}\n title={ariaLabel}\n tabIndex={-1}\n className={cn('ddga-sidebar__rail', className)}\n onClick={toggleSidebar}\n {...props}\n />\n );\n}\n\ninterface SidebarInsetProps extends React.ComponentProps<'main'> {\n asChild?: boolean;\n /**\n * Make the inset its own vertical scroll region: tall content scrolls inside\n * it (the sidebar + footer stay put) with zero consumer layout CSS — no\n * `flex` / `min-block-size:0` / `overflow-y:auto` boilerplate. The whole inset\n * scrolls, header included; for a fixed header with only the body scrolling,\n * leave this off and compose a nested scroll region inside the inset (see the\n * App shell story).\n */\n scrollable?: boolean;\n}\n\nfunction SidebarInset({ asChild, scrollable, className, ...props }: SidebarInsetProps) {\n const Comp = asChild ? SlotPrimitive.Slot : 'main';\n return (\n <Comp\n data-slot=\"sidebar-inset\"\n className={cn(\n 'ddga-sidebar-inset',\n scrollable && 'ddga-sidebar-inset--scrollable',\n className,\n )}\n {...props}\n />\n );\n}\n\n// ─── Structure ─── //\n\ntype SidebarSectionProps = React.ComponentProps<'div'> & { asChild?: boolean };\n\nfunction SidebarHeader({ asChild, className, ...props }: SidebarSectionProps) {\n const Comp = asChild ? SlotPrimitive.Slot : 'div';\n return (\n <Comp data-slot=\"sidebar-header\" className={cn('ddga-sidebar__header', className)} {...props} />\n );\n}\n\nfunction SidebarContent({ asChild, className, ...props }: SidebarSectionProps) {\n const Comp = asChild ? SlotPrimitive.Slot : 'div';\n return (\n <Comp\n data-slot=\"sidebar-content\"\n className={cn('ddga-sidebar__content', className)}\n {...props}\n />\n );\n}\n\nfunction SidebarFooter({ asChild, className, ...props }: SidebarSectionProps) {\n const Comp = asChild ? SlotPrimitive.Slot : 'div';\n return (\n <Comp data-slot=\"sidebar-footer\" className={cn('ddga-sidebar__footer', className)} {...props} />\n );\n}\n\nfunction SidebarSeparator({ className, ...props }: React.ComponentProps<'hr'>) {\n return (\n <hr\n data-slot=\"sidebar-separator\"\n className={cn('ddga-sidebar__separator', className)}\n {...props}\n />\n );\n}\n\n// ─── Exports ─── //\n\nexport { SidebarProvider };\nexport type { SidebarProviderProps };\n\nexport { Sidebar };\nexport type { SidebarProps };\n\nexport { SidebarTrigger, SidebarRail, SidebarInset };\nexport type { SidebarTriggerProps, SidebarInsetProps };\n\nexport { SidebarHeader, SidebarContent, SidebarFooter, SidebarSeparator };\nexport type { SidebarSectionProps };\n\nexport { useSidebar };\nexport type { SidebarContextValue };\n"]}
@@ -53,6 +53,14 @@ function useComboboxContext(component) {
53
53
  }
54
54
  return ctx;
55
55
  }
56
+ function warnRichLabelNeedsAriaLabel(label, ariaLabel, ariaLabelledBy) {
57
+ if (process.env.NODE_ENV === "production") return;
58
+ if (ariaLabel || ariaLabelledBy) return;
59
+ if (label === void 0 || label === null || typeof label === "string") return;
60
+ console.warn(
61
+ '[dga/Combobox] `label` is a non-string node and no `aria-label`/`aria-labelledby` was given, so the options popover falls back to the untranslated name "Options". Pass a localized `aria-label` to name the popover for screen-reader users.'
62
+ );
63
+ }
56
64
  function Combobox({
57
65
  value: controlledValue,
58
66
  defaultValue,
@@ -77,6 +85,7 @@ function Combobox({
77
85
  "aria-label": ariaLabel,
78
86
  "aria-labelledby": ariaLabelledBy
79
87
  }) {
88
+ warnRichLabelNeedsAriaLabel(label, ariaLabel, ariaLabelledBy);
80
89
  const [internalValue, setInternalValue] = _react.useState.call(void 0, defaultValue);
81
90
  const isControlled = controlledValue !== void 0;
82
91
  const value = isControlled ? controlledValue : internalValue;
@@ -259,4 +268,4 @@ function ComboboxSeparator({ className, ...props }) {
259
268
 
260
269
 
261
270
  exports.comboboxTriggerVariants = comboboxTriggerVariants; exports.comboboxVariants = comboboxVariants; exports.Combobox = Combobox; exports.ComboboxItem = ComboboxItem; exports.ComboboxGroup = ComboboxGroup; exports.ComboboxSeparator = ComboboxSeparator;
262
- //# sourceMappingURL=chunk-4ZCLTLVC.cjs.map
271
+ //# sourceMappingURL=chunk-CVQFSXRR.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/home/devdhaif/work/react/dga-dev/packages/react/dist/chunk-CVQFSXRR.cjs","../src/components/Combobox/Combobox.tsx"],"names":[],"mappings":"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","file":"/home/devdhaif/work/react/dga-dev/packages/react/dist/chunk-CVQFSXRR.cjs","sourcesContent":[null,"'use client';\n\nimport {\n Children,\n createContext,\n isValidElement,\n useCallback,\n useContext,\n useId,\n useMemo,\n useState,\n type ReactNode,\n} from 'react';\nimport { Command } from 'cmdk';\nimport { Popover as PopoverPrimitive } from 'radix-ui';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { cn } from '../../utils/cn';\nimport { Check, ChevronDown } from '../../internal/icons';\nimport { useFieldA11y, FieldMessage } from '../../field';\nimport { DgaContext } from '../../providers/DgaContext';\n\n// ─── 1. Variants ─── //\n\n// Trigger height matches Input/Select so a Combobox lines up in a form row.\nconst comboboxTriggerVariants = cva('ddga-combobox-trigger', {\n variants: {\n size: {\n sm: 'ddga-combobox-trigger--sm',\n md: 'ddga-combobox-trigger--md',\n },\n error: {\n true: 'ddga-combobox-trigger--error',\n },\n },\n defaultVariants: {\n size: 'md',\n },\n});\n\n// Keep a no-op `comboboxVariants` for parity with the project's barrel\n// convention (every component re-exports a *Variants from its barrel).\nconst comboboxVariants = comboboxTriggerVariants;\n\n// ─── 2. Context (bridges Root state to Items + label lookup) ─── //\n//\n// Items register `value → label` on mount so the trigger can render the\n// selected option's human-readable label without consumers having to thread\n// a separate `displayValue` function in the common case. Async-loaded\n// options can still override via `<Combobox getLabel={...}>` below.\n\ninterface ComboboxContextValue {\n value?: string;\n select: (value: string) => void;\n}\n\nconst ComboboxContext = createContext<ComboboxContextValue | null>(null);\n\nfunction useComboboxContext(component: string): ComboboxContextValue {\n const ctx = useContext(ComboboxContext);\n if (!ctx) {\n throw new Error(`<${component}> must be rendered inside <Combobox>.`);\n }\n return ctx;\n}\n\n// ─── 3. Types ─── //\n\ninterface ComboboxProps extends VariantProps<typeof comboboxTriggerVariants> {\n /** Currently selected option value (controlled). */\n value?: string;\n /** Initial value when uncontrolled. */\n defaultValue?: string;\n /** Fires whenever the selection changes (controlled or uncontrolled). */\n onValueChange?: (value: string) => void;\n /** Controlled popover open state. */\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n /** Visible label above the trigger. */\n label?: ReactNode;\n /** Hint shown below the trigger when there's no error. */\n helperText?: ReactNode;\n /** Message shown below the trigger when `error` is true. */\n errorMessage?: ReactNode;\n /** Marks the field invalid — sets `aria-invalid` and the error border. */\n error?: boolean;\n /** Marks the field required — adds the asterisk + `aria-required`. */\n required?: boolean;\n /** Disables the trigger entirely. */\n disabled?: boolean;\n /** Placeholder shown in the trigger when no value is selected. */\n placeholder?: ReactNode;\n /** Placeholder for the search input inside the panel. Defaults to `\"Search…\"`. */\n searchPlaceholder?: string;\n /** Shown when no item matches the search query. Defaults to `\"No results.\"`. */\n emptyMessage?: ReactNode;\n /**\n * Override the trigger label resolver — useful when items are loaded async\n * after the value is set, or when the trigger should show a richer label\n * than the item's rendered children. Receives the current value, returns\n * the node to display. Falls back to the registered item's label.\n */\n getLabel?: (value: string) => ReactNode;\n /** Caller-supplied id for the trigger; falls back to a generated one. */\n id?: string;\n /** Forwarded to the trigger (the focusable button). */\n className?: string;\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n /** `<ComboboxItem>` (+ optional Group / Separator) children. */\n children: ReactNode;\n}\n\ninterface ComboboxItemProps extends Omit<\n React.ComponentProps<typeof Command.Item>,\n 'value' | 'onSelect'\n> {\n /** Stable value for filtering + selection. */\n value: string;\n /** Extra search terms cmdk should match against the input. */\n keywords?: string[];\n /** Disable this item from selection. */\n disabled?: boolean;\n /** Optional select handler — fires alongside the root's `onValueChange`. */\n onSelect?: (value: string) => void;\n}\n\ninterface ComboboxGroupProps extends React.ComponentProps<typeof Command.Group> {\n /** Group heading rendered above its items. */\n heading?: ReactNode;\n}\n\ntype ComboboxSeparatorProps = React.ComponentProps<typeof Command.Separator>;\n\n// ─── 4. Root ─── //\n\n// Dev-only nudge: when `label` is a rich (non-string) node and no\n// `aria-label`/`aria-labelledby` is given, the options popover (role=\"dialog\")\n// falls back to the untranslated name \"Options\". Point i18n-conscious consumers\n// at the fix. Mirrors the ScrollArea/Popover a11y warnings.\nfunction warnRichLabelNeedsAriaLabel(\n label: ReactNode,\n ariaLabel?: string,\n ariaLabelledBy?: string,\n) {\n if (process.env.NODE_ENV === 'production') return;\n if (ariaLabel || ariaLabelledBy) return;\n if (label === undefined || label === null || typeof label === 'string') return;\n console.warn(\n '[dga/Combobox] `label` is a non-string node and no `aria-label`/`aria-labelledby` was ' +\n 'given, so the options popover falls back to the untranslated name \"Options\". Pass a ' +\n 'localized `aria-label` to name the popover for screen-reader users.',\n );\n}\n\nfunction Combobox({\n value: controlledValue,\n defaultValue,\n onValueChange,\n open: controlledOpen,\n defaultOpen,\n onOpenChange,\n label,\n helperText,\n errorMessage,\n error,\n required,\n disabled,\n size,\n placeholder,\n searchPlaceholder = 'Search…',\n emptyMessage = 'No results.',\n getLabel,\n id: externalId,\n className,\n children,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n}: ComboboxProps) {\n warnRichLabelNeedsAriaLabel(label, ariaLabel, ariaLabelledBy);\n\n // Uncontrolled fallbacks.\n const [internalValue, setInternalValue] = useState<string | undefined>(defaultValue);\n const isControlled = controlledValue !== undefined;\n const value = isControlled ? controlledValue : internalValue;\n\n const [internalOpen, setInternalOpen] = useState(defaultOpen ?? false);\n const isOpenControlled = controlledOpen !== undefined;\n const open = isOpenControlled ? controlledOpen : internalOpen;\n\n const setOpen = useCallback(\n (next: boolean) => {\n if (!isOpenControlled) setInternalOpen(next);\n onOpenChange?.(next);\n },\n [isOpenControlled, onOpenChange],\n );\n\n const select = useCallback(\n (next: string) => {\n if (!isControlled) setInternalValue(next);\n onValueChange?.(next);\n setOpen(false);\n },\n [isControlled, onValueChange, setOpen],\n );\n\n const ctx = useMemo<ComboboxContextValue>(() => ({ value, select }), [value, select]);\n\n // Walk `children` once to build a value → label map. Synchronous so the\n // trigger shows the right label on first render — registration via\n // useEffect would only fire when items mount, and items don't mount until\n // the popover opens (Radix Portal lazy-mounts). Recurses through\n // `ComboboxGroup` so grouped items still resolve. Bare children only —\n // doesn't dive into arbitrary nested DOM.\n const itemLabels = useMemo<Map<string, ReactNode>>(() => {\n const map = new Map<string, ReactNode>();\n const visit = (nodes: ReactNode): void => {\n Children.forEach(nodes, (child) => {\n if (!isValidElement(child)) return;\n const childProps = child.props as { value?: unknown; children?: ReactNode };\n if (typeof childProps.value === 'string') {\n map.set(childProps.value, childProps.children);\n } else if (childProps.children) {\n visit(childProps.children);\n }\n });\n };\n visit(children);\n return map;\n }, [children]);\n\n // Field a11y wiring — same primitive as Select.\n const { fieldId, errorId, helperId, hasError, hasErrorMessage, hasHelper, controlProps } =\n useFieldA11y({\n name: 'Combobox',\n id: externalId,\n label,\n error,\n errorMessage,\n helperText,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n });\n\n // Portal anchored to DgaProvider root (mirrors Select/Modal/DropdownMenu).\n const providerCtx = useContext(DgaContext);\n // Body-mounted portal target (see DgaProvider) — escapes ancestor\n // clipping while keeping theme inheritance via mirrored data-theme/vars.\n const portalContainer = providerCtx?.portalEl ?? providerCtx?.rootEl ?? undefined;\n\n // Trigger label — explicit override wins; otherwise look up from the\n // children-derived map; otherwise fall back to the placeholder.\n const triggerLabel = useMemo<ReactNode>(() => {\n if (value === undefined) return null;\n if (getLabel) return getLabel(value);\n return itemLabels.get(value) ?? null;\n }, [value, getLabel, itemLabels]);\n\n const searchId = useId();\n\n return (\n <ComboboxContext.Provider value={ctx}>\n <div data-slot=\"combobox-field\" className=\"ddga-field\">\n {label && (\n <label htmlFor={fieldId} className=\"ddga-combobox__label\">\n {label}\n {required && (\n <span aria-hidden=\"true\" className=\"ddga-combobox__required\">\n *\n </span>\n )}\n </label>\n )}\n <PopoverPrimitive.Root open={open} onOpenChange={setOpen}>\n <PopoverPrimitive.Trigger asChild>\n <button\n type=\"button\"\n {...controlProps}\n // Trigger stays a plain button — Radix Popover.Trigger sets\n // aria-haspopup + aria-expanded + aria-controls so AT users\n // hear \"Pick a fruit, button, has popup\". We declared role=\"combobox\"\n // earlier but it requires aria-controls pointing to the listbox,\n // which Radix wires for dialog semantics — axe flagged the mismatch.\n aria-required={required || undefined}\n disabled={disabled}\n data-slot=\"combobox-trigger\"\n className={cn(comboboxTriggerVariants({ size, error: hasError }), className)}\n >\n <span className=\"ddga-combobox__value\">\n {triggerLabel ?? <span className=\"ddga-combobox__placeholder\">{placeholder}</span>}\n </span>\n <ChevronDown aria-hidden=\"true\" className=\"ddga-combobox__icon\" />\n </button>\n </PopoverPrimitive.Trigger>\n <PopoverPrimitive.Portal container={portalContainer}>\n <PopoverPrimitive.Content\n data-slot=\"combobox-content\"\n className=\"ddga-combobox-content\"\n sideOffset={4}\n align=\"start\"\n // Popover.Content is role=\"dialog\" → axe requires an accessible\n // name. Use the field label when it's a string; otherwise fall\n // back to a generic \"Options\" so a11y stays valid even when the\n // consumer composes a rich React node as the label.\n aria-label={ariaLabel ?? (typeof label === 'string' ? label : 'Options')}\n aria-labelledby={ariaLabelledBy}\n // Match trigger width so the panel doesn't visually float over.\n style={{ inlineSize: 'var(--radix-popover-trigger-width)' }}\n onOpenAutoFocus={(event) => {\n // cmdk handles its own focus management (Input gets focused on\n // mount via autoFocus below). Prevent Radix from also moving\n // focus or we lose the search input as the auto-focus target.\n event.preventDefault();\n }}\n >\n <Command\n id={searchId}\n data-slot=\"combobox-command\"\n className=\"ddga-combobox-command\"\n // cmdk's default filter matches if the input is a substring of\n // the item value OR any keyword — fine for our v1 use case.\n >\n <Command.Input\n autoFocus\n placeholder={searchPlaceholder}\n data-slot=\"combobox-input\"\n className=\"ddga-combobox-input\"\n />\n <Command.List data-slot=\"combobox-list\" className=\"ddga-combobox-list\">\n <Command.Empty data-slot=\"combobox-empty\" className=\"ddga-combobox-empty\">\n {emptyMessage}\n </Command.Empty>\n {children}\n </Command.List>\n </Command>\n </PopoverPrimitive.Content>\n </PopoverPrimitive.Portal>\n </PopoverPrimitive.Root>\n {hasErrorMessage && (\n <FieldMessage id={errorId} variant=\"error\">\n {errorMessage}\n </FieldMessage>\n )}\n {hasHelper && (\n <FieldMessage id={helperId} variant=\"helper\">\n {helperText}\n </FieldMessage>\n )}\n </div>\n </ComboboxContext.Provider>\n );\n}\n\n// ─── 5. Item ─── //\n\nfunction ComboboxItem({\n value,\n keywords,\n disabled,\n onSelect,\n className,\n children,\n ...props\n}: ComboboxItemProps) {\n const { value: selectedValue, select } = useComboboxContext('ComboboxItem');\n\n const isSelected = selectedValue === value;\n\n return (\n <Command.Item\n value={value}\n keywords={keywords}\n disabled={disabled}\n onSelect={(v) => {\n onSelect?.(v);\n select(v);\n }}\n data-slot=\"combobox-item\"\n // cmdk owns `data-selected` for keyboard highlight — use a separate\n // attribute for the chosen value so the two don't collide.\n data-active={isSelected ? '' : undefined}\n className={cn('ddga-combobox-item', className)}\n {...props}\n >\n <span className=\"ddga-combobox-item__check\" aria-hidden=\"true\">\n {isSelected ? <Check /> : null}\n </span>\n <span className=\"ddga-combobox-item__label\">{children}</span>\n </Command.Item>\n );\n}\n\n// ─── 6. Group + Separator (cmdk passthroughs) ─── //\n\nfunction ComboboxGroup({ className, heading, ...props }: ComboboxGroupProps) {\n return (\n <Command.Group\n heading={heading}\n data-slot=\"combobox-group\"\n className={cn('ddga-combobox-group', className)}\n {...props}\n />\n );\n}\n\nfunction ComboboxSeparator({ className, ...props }: ComboboxSeparatorProps) {\n return (\n <Command.Separator\n data-slot=\"combobox-separator\"\n className={cn('ddga-combobox-separator', className)}\n {...props}\n />\n );\n}\n\n// ─── 7. Exports ─── //\n\nexport {\n Combobox,\n ComboboxItem,\n ComboboxGroup,\n ComboboxSeparator,\n comboboxTriggerVariants,\n comboboxVariants,\n};\nexport type { ComboboxProps, ComboboxItemProps, ComboboxGroupProps, ComboboxSeparatorProps };\n"]}
@@ -171,9 +171,20 @@ function SidebarRail({
171
171
  }
172
172
  );
173
173
  }
174
- function SidebarInset({ asChild, className, ...props }) {
174
+ function SidebarInset({ asChild, scrollable, className, ...props }) {
175
175
  const Comp = asChild ? SlotPrimitive.Slot : "main";
176
- return /* @__PURE__ */ jsx(Comp, { "data-slot": "sidebar-inset", className: cn("ddga-sidebar-inset", className), ...props });
176
+ return /* @__PURE__ */ jsx(
177
+ Comp,
178
+ {
179
+ "data-slot": "sidebar-inset",
180
+ className: cn(
181
+ "ddga-sidebar-inset",
182
+ scrollable && "ddga-sidebar-inset--scrollable",
183
+ className
184
+ ),
185
+ ...props
186
+ }
187
+ );
177
188
  }
178
189
  function SidebarHeader({ asChild, className, ...props }) {
179
190
  const Comp = asChild ? SlotPrimitive.Slot : "div";
@@ -216,4 +227,4 @@ export {
216
227
  SidebarFooter,
217
228
  SidebarSeparator
218
229
  };
219
- //# sourceMappingURL=chunk-BNULFLPC.js.map
230
+ //# sourceMappingURL=chunk-HBAHWCBK.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/Sidebar/Sidebar.tsx"],"sourcesContent":["'use client';\n\nimport { useCallback, useEffect, useMemo, useState } from 'react';\nimport { Slot as SlotPrimitive } from 'radix-ui';\nimport { cn } from '../../utils/cn';\nimport { Drawer, DrawerContent } from '../Drawer';\nimport { PanelLeft } from '../../internal/icons';\nimport { SidebarContext, useSidebar, type SidebarContextValue } from './SidebarContext';\nimport { useIsMobile } from './useIsMobile';\n\n// ─── SidebarProvider ─── //\n\ninterface SidebarProviderProps extends React.ComponentProps<'div'> {\n /** Uncontrolled initial desktop state. Default true (expanded). */\n defaultOpen?: boolean;\n /** Controlled desktop open state. */\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n /** Viewport width (px) below which the mobile Drawer engages. Default 768. */\n mobileBreakpoint?: number;\n /** Register Cmd/Ctrl+B to toggle. Default true. */\n keyboardShortcut?: boolean;\n}\n\nfunction SidebarProvider({\n defaultOpen = true,\n open: openProp,\n onOpenChange,\n mobileBreakpoint = 768,\n keyboardShortcut = true,\n className,\n style,\n children,\n ...props\n}: SidebarProviderProps) {\n const isMobile = useIsMobile(mobileBreakpoint);\n const [openMobile, setOpenMobile] = useState(false);\n\n const isControlled = openProp !== undefined;\n const [openInternal, setOpenInternal] = useState(defaultOpen);\n const open = isControlled ? (openProp as boolean) : openInternal;\n\n const setOpen = useCallback(\n (value: boolean) => {\n if (!isControlled) setOpenInternal(value);\n onOpenChange?.(value);\n },\n [isControlled, onOpenChange],\n );\n\n const toggleSidebar = useCallback(() => {\n if (isMobile) {\n setOpenMobile((v) => !v);\n return;\n }\n if (isControlled) {\n onOpenChange?.(!open);\n } else {\n setOpenInternal((v) => !v);\n }\n }, [isMobile, isControlled, onOpenChange, open]);\n\n useEffect(() => {\n if (!keyboardShortcut) return;\n const onKeyDown = (e: KeyboardEvent) => {\n if (e.key.toLowerCase() === 'b' && (e.metaKey || e.ctrlKey)) {\n e.preventDefault();\n toggleSidebar();\n }\n };\n window.addEventListener('keydown', onKeyDown);\n return () => window.removeEventListener('keydown', onKeyDown);\n }, [keyboardShortcut, toggleSidebar]);\n\n const state: 'expanded' | 'collapsed' = open ? 'expanded' : 'collapsed';\n\n const value = useMemo<SidebarContextValue>(\n () => ({ state, open, setOpen, openMobile, setOpenMobile, isMobile, toggleSidebar }),\n [state, open, setOpen, openMobile, isMobile, toggleSidebar],\n );\n\n return (\n <SidebarContext.Provider value={value}>\n <div\n data-slot=\"sidebar-wrapper\"\n className={cn('ddga-sidebar-wrapper', className)}\n style={style}\n {...props}\n >\n {children}\n </div>\n </SidebarContext.Provider>\n );\n}\n\n// ─── Sidebar (container) ─── //\n\ninterface SidebarProps extends React.ComponentProps<'div'> {\n variant?: 'sidebar' | 'floating' | 'inset';\n collapsible?: 'icon' | 'offcanvas' | 'none';\n /** Logical side; flips with dir. Default 'start'. */\n side?: 'start' | 'end';\n}\n\nfunction Sidebar({\n variant = 'sidebar',\n collapsible = 'icon',\n side = 'start',\n className,\n children,\n 'aria-label': ariaLabel = 'Sidebar',\n ...props\n}: SidebarProps) {\n const { isMobile, openMobile, setOpenMobile, state } = useSidebar();\n\n if (isMobile) {\n return (\n <Drawer open={openMobile} onOpenChange={setOpenMobile}>\n <DrawerContent\n side={side}\n size=\"sm\"\n aria-label={ariaLabel}\n data-slot=\"sidebar\"\n data-mobile=\"true\"\n data-variant={variant}\n data-side={side}\n className={cn('ddga-sidebar', 'ddga-sidebar--mobile', className)}\n {...props}\n >\n {children}\n </DrawerContent>\n </Drawer>\n );\n }\n\n return (\n <aside\n data-slot=\"sidebar\"\n aria-label={ariaLabel}\n data-state={state}\n data-collapsible={collapsible}\n data-variant={variant}\n data-side={side}\n className={cn('ddga-sidebar', className)}\n {...props}\n >\n {children}\n </aside>\n );\n}\n\n// ─── Trigger / Rail / Inset ─── //\n\ninterface SidebarTriggerProps extends React.ComponentProps<'button'> {\n asChild?: boolean;\n}\n\nfunction SidebarTrigger({\n asChild,\n className,\n onClick,\n children,\n 'aria-label': ariaLabel = 'Toggle sidebar',\n ...props\n}: SidebarTriggerProps) {\n const { toggleSidebar, open, openMobile, isMobile } = useSidebar();\n const Comp = asChild ? SlotPrimitive.Slot : 'button';\n return (\n <Comp\n type={asChild ? undefined : 'button'}\n data-slot=\"sidebar-trigger\"\n // Don't override the child element's accessible name when asChild.\n aria-label={asChild ? undefined : ariaLabel}\n aria-haspopup={isMobile ? 'dialog' : undefined}\n aria-expanded={isMobile ? openMobile : open}\n className={cn('ddga-sidebar__trigger', className)}\n onClick={(e: React.MouseEvent<HTMLButtonElement>) => {\n onClick?.(e);\n toggleSidebar();\n }}\n {...props}\n >\n {children ?? <PanelLeft aria-hidden=\"true\" />}\n </Comp>\n );\n}\n\nfunction SidebarRail({\n className,\n 'aria-label': ariaLabel = 'Toggle sidebar',\n ...props\n}: React.ComponentProps<'button'>) {\n const { toggleSidebar } = useSidebar();\n return (\n <button\n type=\"button\"\n data-slot=\"sidebar-rail\"\n aria-label={ariaLabel}\n title={ariaLabel}\n tabIndex={-1}\n className={cn('ddga-sidebar__rail', className)}\n onClick={toggleSidebar}\n {...props}\n />\n );\n}\n\ninterface SidebarInsetProps extends React.ComponentProps<'main'> {\n asChild?: boolean;\n /**\n * Make the inset its own vertical scroll region: tall content scrolls inside\n * it (the sidebar + footer stay put) with zero consumer layout CSS — no\n * `flex` / `min-block-size:0` / `overflow-y:auto` boilerplate. The whole inset\n * scrolls, header included; for a fixed header with only the body scrolling,\n * leave this off and compose a nested scroll region inside the inset (see the\n * App shell story).\n */\n scrollable?: boolean;\n}\n\nfunction SidebarInset({ asChild, scrollable, className, ...props }: SidebarInsetProps) {\n const Comp = asChild ? SlotPrimitive.Slot : 'main';\n return (\n <Comp\n data-slot=\"sidebar-inset\"\n className={cn(\n 'ddga-sidebar-inset',\n scrollable && 'ddga-sidebar-inset--scrollable',\n className,\n )}\n {...props}\n />\n );\n}\n\n// ─── Structure ─── //\n\ntype SidebarSectionProps = React.ComponentProps<'div'> & { asChild?: boolean };\n\nfunction SidebarHeader({ asChild, className, ...props }: SidebarSectionProps) {\n const Comp = asChild ? SlotPrimitive.Slot : 'div';\n return (\n <Comp data-slot=\"sidebar-header\" className={cn('ddga-sidebar__header', className)} {...props} />\n );\n}\n\nfunction SidebarContent({ asChild, className, ...props }: SidebarSectionProps) {\n const Comp = asChild ? SlotPrimitive.Slot : 'div';\n return (\n <Comp\n data-slot=\"sidebar-content\"\n className={cn('ddga-sidebar__content', className)}\n {...props}\n />\n );\n}\n\nfunction SidebarFooter({ asChild, className, ...props }: SidebarSectionProps) {\n const Comp = asChild ? SlotPrimitive.Slot : 'div';\n return (\n <Comp data-slot=\"sidebar-footer\" className={cn('ddga-sidebar__footer', className)} {...props} />\n );\n}\n\nfunction SidebarSeparator({ className, ...props }: React.ComponentProps<'hr'>) {\n return (\n <hr\n data-slot=\"sidebar-separator\"\n className={cn('ddga-sidebar__separator', className)}\n {...props}\n />\n );\n}\n\n// ─── Exports ─── //\n\nexport { SidebarProvider };\nexport type { SidebarProviderProps };\n\nexport { Sidebar };\nexport type { SidebarProps };\n\nexport { SidebarTrigger, SidebarRail, SidebarInset };\nexport type { SidebarTriggerProps, SidebarInsetProps };\n\nexport { SidebarHeader, SidebarContent, SidebarFooter, SidebarSeparator };\nexport type { SidebarSectionProps };\n\nexport { useSidebar };\nexport type { SidebarContextValue };\n"],"mappings":"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","names":["value"]}
@@ -93,6 +93,10 @@ function ModalDescription({ asChild, className, ...props }) {
93
93
  }
94
94
  );
95
95
  }
96
+ function ModalBody({ asChild, className, ...props }) {
97
+ const Comp = asChild ? _radixui.Slot.Slot : "div";
98
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Comp, { "data-slot": "modal-body", className: _chunkV6MXOJQ4cjs.cn.call(void 0, "ddga-modal__body", className), ...props });
99
+ }
96
100
  function ModalFooter({ asChild, className, ...props }) {
97
101
  const Comp = asChild ? _radixui.Slot.Slot : "div";
98
102
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Comp, { "data-slot": "modal-footer", className: _chunkV6MXOJQ4cjs.cn.call(void 0, "ddga-modal__footer", className), ...props });
@@ -111,5 +115,6 @@ function ModalClose({ className, ...props }) {
111
115
 
112
116
 
113
117
 
114
- exports.modalContentVariants = modalContentVariants; exports.Modal = Modal; exports.ModalTrigger = ModalTrigger; exports.ModalContent = ModalContent; exports.ModalHeader = ModalHeader; exports.ModalTitle = ModalTitle; exports.ModalDescription = ModalDescription; exports.ModalFooter = ModalFooter; exports.ModalClose = ModalClose;
115
- //# sourceMappingURL=chunk-54GIEP6E.cjs.map
118
+
119
+ exports.modalContentVariants = modalContentVariants; exports.Modal = Modal; exports.ModalTrigger = ModalTrigger; exports.ModalContent = ModalContent; exports.ModalHeader = ModalHeader; exports.ModalTitle = ModalTitle; exports.ModalDescription = ModalDescription; exports.ModalBody = ModalBody; exports.ModalFooter = ModalFooter; exports.ModalClose = ModalClose;
120
+ //# sourceMappingURL=chunk-I6BOBHO6.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/home/devdhaif/work/react/dga-dev/packages/react/dist/chunk-I6BOBHO6.cjs","../src/components/Modal/Modal.tsx"],"names":[],"mappings":"AAAA;AACE;AACF,wDAA6B;AAC7B;AACE;AACF,wDAA6B;AAC7B;AACE;AACF,wDAA6B;AAC7B;AACA;ACRA,8BAA2B;AAC3B,mCAAiE;AACjE,kEAAuC;AA8D9B,+CAAA;AAvDT,IAAM,qBAAA,EAAuB,yCAAA,YAAI,EAAc;AAAA,EAC7C,QAAA,EAAU;AAAA,IACR,IAAA,EAAM;AAAA,MACJ,EAAA,EAAI,gBAAA;AAAA,MACJ,EAAA,EAAI,gBAAA;AAAA,MACJ,EAAA,EAAI,gBAAA;AAAA,MACJ,EAAA,EAAI,gBAAA;AAAA,MACJ,IAAA,EAAM;AAAA,IACR;AAAA,EACF,CAAA;AAAA,EACA,eAAA,EAAiB;AAAA,IACf,IAAA,EAAM;AAAA,EACR;AACF,CAAC,CAAA;AAyCD,SAAS,KAAA,CAAM,KAAA,EAAmB;AAChC,EAAA,uBAAO,6BAAA,eAAC,CAAgB,IAAA,EAAhB,EAAsB,GAAG,MAAA,CAAO,CAAA;AAC1C;AAEA,SAAS,YAAA,CAAa,EAAE,SAAA,EAAW,GAAG,MAAM,CAAA,EAAsB;AAEhE,EAAA,uBAAO,6BAAA,eAAC,CAAgB,OAAA,EAAhB,EAAwB,WAAA,EAAU,eAAA,EAAgB,SAAA,EAAuB,GAAG,MAAA,CAAO,CAAA;AAC7F;AAEA,SAAS,YAAA,CAAa;AAAA,EACpB,IAAA;AAAA,EACA,gBAAA,EAAkB,IAAA;AAAA,EAClB,WAAA,EAAa,OAAA;AAAA,EACb,SAAA;AAAA,EACA,QAAA;AAAA,EACA,GAAG;AACL,CAAA,EAAsB;AAQpB,EAAA,MAAM,IAAA,EAAM,+BAAA,4BAAqB,CAAA;AACjC,EAAA,MAAM,gBAAA,oDAAkB,GAAA,2BAAK,UAAA,0BAAY,GAAA,6BAAK,UAAA,UAAU,KAAA,GAAA;AAExD,EAAA,uBACE,8BAAA,eAAC,CAAgB,MAAA,EAAhB,EAAuB,SAAA,EAAW,eAAA,EACjC,QAAA,EAAA;AAAA,oBAAA,6BAAA,eAAC,CAAgB,OAAA,EAAhB,EAAwB,SAAA,EAAU,qBAAA,EAAsB,WAAA,EAAU,gBAAA,CAAgB,CAAA;AAAA,oBACnF,8BAAA;AAAA,MAAC,eAAA,CAAgB,OAAA;AAAA,MAAhB;AAAA,QACC,WAAA,EAAU,eAAA;AAAA,QACV,SAAA,EAAW,kCAAA,oBAAG,CAAqB,EAAE,KAAK,CAAC,CAAA,EAAG,SAAS,CAAA;AAAA,QACtD,GAAG,KAAA;AAAA,QAEH,QAAA,EAAA;AAAA,UAAA,QAAA;AAAA,UACA,gBAAA,kBACC,6BAAA;AAAA,YAAC,eAAA,CAAgB,KAAA;AAAA,YAAhB;AAAA,cACC,SAAA,EAAU,mBAAA;AAAA,cACV,YAAA,EAAY,UAAA;AAAA,cACZ,WAAA,EAAU,eAAA;AAAA,cAEV,QAAA,kBAAA,6BAAA,uBAAC,EAAA,EAAM,aAAA,EAAY,OAAA,CAAO;AAAA,YAAA;AAAA,UAC5B,EAAA,EACE;AAAA,QAAA;AAAA,MAAA;AAAA,IACN;AAAA,EAAA,EAAA,CACF,CAAA;AAEJ;AAEA,SAAS,WAAA,CAAY,EAAE,OAAA,EAAS,SAAA,EAAW,GAAG,MAAM,CAAA,EAAsB;AACxE,EAAA,MAAM,KAAA,EAAO,QAAA,EAAU,aAAA,CAAc,KAAA,EAAO,KAAA;AAC5C,EAAA,uBACE,6BAAA,IAAC,EAAA,EAAK,WAAA,EAAU,cAAA,EAAe,SAAA,EAAW,kCAAA,oBAAG,EAAsB,SAAS,CAAA,EAAI,GAAG,MAAA,CAAO,CAAA;AAE9F;AAEA,SAAS,UAAA,CAAW,EAAE,OAAA,EAAS,SAAA,EAAW,GAAG,MAAM,CAAA,EAAoB;AAIrE,EAAA,uBACE,6BAAA;AAAA,IAAC,eAAA,CAAgB,KAAA;AAAA,IAAhB;AAAA,MACC,OAAA;AAAA,MACA,WAAA,EAAU,aAAA;AAAA,MACV,SAAA,EAAW,kCAAA,mBAAG,EAAqB,SAAS,CAAA;AAAA,MAC3C,GAAG;AAAA,IAAA;AAAA,EACN,CAAA;AAEJ;AAEA,SAAS,gBAAA,CAAiB,EAAE,OAAA,EAAS,SAAA,EAAW,GAAG,MAAM,CAAA,EAA0B;AAGjF,EAAA,uBACE,6BAAA;AAAA,IAAC,eAAA,CAAgB,WAAA;AAAA,IAAhB;AAAA,MACC,OAAA;AAAA,MACA,WAAA,EAAU,mBAAA;AAAA,MACV,SAAA,EAAW,kCAAA,yBAAG,EAA2B,SAAS,CAAA;AAAA,MACjD,GAAG;AAAA,IAAA;AAAA,EACN,CAAA;AAEJ;AAEA,SAAS,SAAA,CAAU,EAAE,OAAA,EAAS,SAAA,EAAW,GAAG,MAAM,CAAA,EAAsB;AAMtE,EAAA,MAAM,KAAA,EAAO,QAAA,EAAU,aAAA,CAAc,KAAA,EAAO,KAAA;AAC5C,EAAA,uBAAO,6BAAA,IAAC,EAAA,EAAK,WAAA,EAAU,YAAA,EAAa,SAAA,EAAW,kCAAA,kBAAG,EAAoB,SAAS,CAAA,EAAI,GAAG,MAAA,CAAO,CAAA;AAC/F;AAEA,SAAS,WAAA,CAAY,EAAE,OAAA,EAAS,SAAA,EAAW,GAAG,MAAM,CAAA,EAAsB;AACxE,EAAA,MAAM,KAAA,EAAO,QAAA,EAAU,aAAA,CAAc,KAAA,EAAO,KAAA;AAC5C,EAAA,uBACE,6BAAA,IAAC,EAAA,EAAK,WAAA,EAAU,cAAA,EAAe,SAAA,EAAW,kCAAA,oBAAG,EAAsB,SAAS,CAAA,EAAI,GAAG,MAAA,CAAO,CAAA;AAE9F;AAEA,SAAS,UAAA,CAAW,EAAE,SAAA,EAAW,GAAG,MAAM,CAAA,EAAoB;AAG5D,EAAA,uBAAO,6BAAA,eAAC,CAAgB,KAAA,EAAhB,EAAsB,WAAA,EAAU,aAAA,EAAc,SAAA,EAAuB,GAAG,MAAA,CAAO,CAAA;AACzF;ADhEA;AACA;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,yWAAC","file":"/home/devdhaif/work/react/dga-dev/packages/react/dist/chunk-I6BOBHO6.cjs","sourcesContent":[null,"'use client';\n\nimport { useContext } from 'react';\nimport { Dialog as DialogPrimitive, Slot as SlotPrimitive } from 'radix-ui';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { cn } from '../../utils/cn';\nimport { DgaContext } from '../../providers/DgaContext';\nimport { Close } from '../../internal/icons';\n\n// ─── 1. Variants (cva) ─── //\n\nconst modalContentVariants = cva('ddga-modal', {\n variants: {\n size: {\n sm: 'ddga-modal--sm',\n md: 'ddga-modal--md',\n lg: 'ddga-modal--lg',\n xl: 'ddga-modal--xl',\n full: 'ddga-modal--full',\n },\n },\n defaultVariants: {\n size: 'md',\n },\n});\n\n// ─── 2. Types ─── //\n//\n// Closed compound shape that hides Radix's Portal/Overlay plumbing. The Portal\n// is anchored to `DgaContext.rootEl` so `data-theme` + custom theme classes\n// set on the provider inherit into the modal — without it, the modal would\n// silently mount under <body> and miss dark mode / palette switches.\n\ntype ModalProps = React.ComponentProps<typeof DialogPrimitive.Root>;\ntype ModalTriggerProps = React.ComponentProps<typeof DialogPrimitive.Trigger>;\ntype ModalCloseProps = React.ComponentProps<typeof DialogPrimitive.Close>;\n\ninterface ModalContentProps\n extends\n React.ComponentProps<typeof DialogPrimitive.Content>,\n VariantProps<typeof modalContentVariants> {\n /**\n * Render a corner X close button. Defaults to `true`. Set `false` for\n * action-forcing dialogs (e.g. \"Are you sure?\") where the user must pick\n * one of the explicit footer buttons.\n */\n showCloseButton?: boolean;\n /** Localized label for the close button. Defaults to `\"Close\"`. */\n closeLabel?: string;\n}\n\ntype ModalSectionProps = React.ComponentProps<'div'> & { asChild?: boolean };\n\ninterface ModalTitleProps extends React.ComponentProps<typeof DialogPrimitive.Title> {\n /** Override the heading element (e.g. render an `<h3>` instead of the default `<h2>`). */\n asChild?: boolean;\n}\n\ninterface ModalDescriptionProps extends React.ComponentProps<typeof DialogPrimitive.Description> {\n /** Override the element (e.g. render a `<div>` for richer markup). */\n asChild?: boolean;\n}\n\n// ─── 3. Components ─── //\n\nfunction Modal(props: ModalProps) {\n return <DialogPrimitive.Root {...props} />;\n}\n\nfunction ModalTrigger({ className, ...props }: ModalTriggerProps) {\n // Radix Trigger supports asChild natively — pass through.\n return <DialogPrimitive.Trigger data-slot=\"modal-trigger\" className={className} {...props} />;\n}\n\nfunction ModalContent({\n size,\n showCloseButton = true,\n closeLabel = 'Close',\n className,\n children,\n ...props\n}: ModalContentProps) {\n // Anchor the Portal to the DgaProvider's body-level portal container.\n // Pattern documented in DgaContext.ts; regression test in Modal.test.tsx\n // mirrors Select/Tooltip. The portal container mirrors data-theme + dir +\n // CSS vars from the provider so theming still flows; using it (rather\n // than the in-tree `rootEl`) keeps the modal's `position: fixed` overlay\n // from being trapped by an ancestor `transform` or `overflow: hidden`\n // (Storybook autodocs is the motivating case).\n const ctx = useContext(DgaContext);\n const portalContainer = ctx?.portalEl ?? ctx?.rootEl ?? undefined;\n\n return (\n <DialogPrimitive.Portal container={portalContainer}>\n <DialogPrimitive.Overlay className=\"ddga-modal__overlay\" data-slot=\"modal-overlay\" />\n <DialogPrimitive.Content\n data-slot=\"modal-content\"\n className={cn(modalContentVariants({ size }), className)}\n {...props}\n >\n {children}\n {showCloseButton ? (\n <DialogPrimitive.Close\n className=\"ddga-modal__close\"\n aria-label={closeLabel}\n data-slot=\"modal-close-x\"\n >\n <Close aria-hidden=\"true\" />\n </DialogPrimitive.Close>\n ) : null}\n </DialogPrimitive.Content>\n </DialogPrimitive.Portal>\n );\n}\n\nfunction ModalHeader({ asChild, className, ...props }: ModalSectionProps) {\n const Comp = asChild ? SlotPrimitive.Slot : 'div';\n return (\n <Comp data-slot=\"modal-header\" className={cn('ddga-modal__header', className)} {...props} />\n );\n}\n\nfunction ModalTitle({ asChild, className, ...props }: ModalTitleProps) {\n // Dialog.Title wires aria-labelledby on the parent Content. We pass asChild\n // through so consumers can swap heading level (h2 → h1/h3) without losing\n // the labelling link.\n return (\n <DialogPrimitive.Title\n asChild={asChild}\n data-slot=\"modal-title\"\n className={cn('ddga-modal__title', className)}\n {...props}\n />\n );\n}\n\nfunction ModalDescription({ asChild, className, ...props }: ModalDescriptionProps) {\n // Dialog.Description wires aria-describedby on the parent Content. asChild\n // lets consumers swap the element if they need richer markup.\n return (\n <DialogPrimitive.Description\n asChild={asChild}\n data-slot=\"modal-description\"\n className={cn('ddga-modal__description', className)}\n {...props}\n />\n );\n}\n\nfunction ModalBody({ asChild, className, ...props }: ModalSectionProps) {\n // Scrollable middle region (mirrors DrawerBody) — grows to fill the space\n // between a pinned header and footer and scrolls internally when content\n // overflows, so a tall modal never clips and the footer stays visible with\n // zero consumer config. Optional: short, non-scrolling bodies can still drop\n // raw content directly under ModalContent (it gets the same inline padding).\n const Comp = asChild ? SlotPrimitive.Slot : 'div';\n return <Comp data-slot=\"modal-body\" className={cn('ddga-modal__body', className)} {...props} />;\n}\n\nfunction ModalFooter({ asChild, className, ...props }: ModalSectionProps) {\n const Comp = asChild ? SlotPrimitive.Slot : 'div';\n return (\n <Comp data-slot=\"modal-footer\" className={cn('ddga-modal__footer', className)} {...props} />\n );\n}\n\nfunction ModalClose({ className, ...props }: ModalCloseProps) {\n // Consumer-level close trigger for footer buttons etc. Radix Close supports\n // asChild natively — pass through so consumers can wrap a <Button>.\n return <DialogPrimitive.Close data-slot=\"modal-close\" className={className} {...props} />;\n}\n\n// ─── 4. Exports ─── //\n\nexport {\n Modal,\n ModalTrigger,\n ModalContent,\n ModalHeader,\n ModalTitle,\n ModalDescription,\n ModalBody,\n ModalFooter,\n ModalClose,\n modalContentVariants,\n};\nexport type {\n ModalProps,\n ModalTriggerProps,\n ModalContentProps,\n ModalSectionProps,\n ModalTitleProps,\n ModalDescriptionProps,\n ModalCloseProps,\n};\n"]}
@@ -58,4 +58,4 @@ export {
58
58
  TooltipTrigger,
59
59
  TooltipContent
60
60
  };
61
- //# sourceMappingURL=chunk-DBB47IAX.js.map
61
+ //# sourceMappingURL=chunk-IFB53HNO.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/Tooltip/Tooltip.tsx"],"sourcesContent":["'use client';\n\nimport { useContext } from 'react';\nimport { Tooltip as TooltipPrimitive } from 'radix-ui';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { cn } from '../../utils/cn';\nimport { DgaContext } from '../../providers/DgaContext';\n\n// ─── 1. Variants (cva) ─── //\n\nconst tooltipContentVariants = cva('ddga-tooltip', {\n variants: {\n size: {\n sm: 'ddga-tooltip--sm',\n md: 'ddga-tooltip--md',\n },\n },\n defaultVariants: {\n size: 'md',\n },\n});\n\n// ─── 2. Types ─── //\n//\n// We expose a closed compound shape that hides Radix's Provider/Portal/Arrow\n// details. `TooltipProvider` is already nested in `DgaProvider`, so consumers\n// don't need to add their own. The Portal container is wired from\n// `DgaContext.rootEl` (see DgaContext.ts) so the tooltip inherits `data-theme`\n// + custom theme classes set on the provider — without it, the tooltip would\n// silently mount under <body> and miss dark mode.\n\ntype TooltipProps = React.ComponentProps<typeof TooltipPrimitive.Root>;\n\ntype TooltipTriggerProps = React.ComponentProps<typeof TooltipPrimitive.Trigger>;\n\ninterface TooltipContentProps\n extends\n Omit<React.ComponentProps<typeof TooltipPrimitive.Content>, 'asChild'>,\n VariantProps<typeof tooltipContentVariants> {\n /** Show a small arrow pointing at the trigger. Defaults to true. */\n arrow?: boolean;\n}\n\n// ─── 3. Components ─── //\n\n/**\n * Tooltip root. **Must be rendered inside `<DgaProvider>`** — the provider\n * supplies the Radix `TooltipProvider` this depends on (and the themed portal\n * container). There is no need to add your own `TooltipProvider`; used outside\n * a `DgaProvider` the tooltip will not work.\n */\nfunction Tooltip(props: TooltipProps) {\n return <TooltipPrimitive.Root {...props} />;\n}\n\nfunction TooltipTrigger({ className, ...props }: TooltipTriggerProps) {\n // Radix Trigger already supports asChild natively — pass through.\n return <TooltipPrimitive.Trigger data-slot=\"tooltip-trigger\" className={className} {...props} />;\n}\n\nfunction TooltipContent({\n size,\n arrow = true,\n sideOffset = 6,\n className,\n children,\n ...props\n}: TooltipContentProps) {\n // Anchor the Portal to the DgaProvider's body-level portal container.\n // Theme + dark mode inherit through mirrored data-theme/dir/CSS vars on\n // the portal element; using it (rather than the in-tree `rootEl`) keeps\n // the tooltip from being clipped by ancestor overflow or trapped by an\n // ancestor `transform`. Falls back to <body> if used outside a provider.\n const ctx = useContext(DgaContext);\n const portalContainer = ctx?.portalEl ?? ctx?.rootEl ?? undefined;\n\n return (\n <TooltipPrimitive.Portal container={portalContainer}>\n <TooltipPrimitive.Content\n data-slot=\"tooltip-content\"\n sideOffset={sideOffset}\n className={cn(tooltipContentVariants({ size }), className)}\n {...props}\n >\n {children}\n {arrow ? <TooltipPrimitive.Arrow className=\"ddga-tooltip__arrow\" /> : null}\n </TooltipPrimitive.Content>\n </TooltipPrimitive.Portal>\n );\n}\n\n// ─── 4. Exports ─── //\n\nexport { Tooltip, TooltipTrigger, TooltipContent, tooltipContentVariants };\nexport type { TooltipProps, TooltipTriggerProps, TooltipContentProps };\n"],"mappings":";;;;;;;;AAEA,SAAS,kBAAkB;AAC3B,SAAS,WAAW,wBAAwB;AAC5C,SAAS,WAA8B;AAgD9B,cA0BH,YA1BG;AA1CT,IAAM,yBAAyB,IAAI,gBAAgB;AAAA,EACjD,UAAU;AAAA,IACR,MAAM;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,IACN;AAAA,EACF;AAAA,EACA,iBAAiB;AAAA,IACf,MAAM;AAAA,EACR;AACF,CAAC;AA+BD,SAAS,QAAQ,OAAqB;AACpC,SAAO,oBAAC,iBAAiB,MAAjB,EAAuB,GAAG,OAAO;AAC3C;AAEA,SAAS,eAAe,EAAE,WAAW,GAAG,MAAM,GAAwB;AAEpE,SAAO,oBAAC,iBAAiB,SAAjB,EAAyB,aAAU,mBAAkB,WAAuB,GAAG,OAAO;AAChG;AAEA,SAAS,eAAe;AAAA,EACtB;AAAA,EACA,QAAQ;AAAA,EACR,aAAa;AAAA,EACb;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAAwB;AAMtB,QAAM,MAAM,WAAW,UAAU;AACjC,QAAM,kBAAkB,KAAK,YAAY,KAAK,UAAU;AAExD,SACE,oBAAC,iBAAiB,QAAjB,EAAwB,WAAW,iBAClC;AAAA,IAAC,iBAAiB;AAAA,IAAjB;AAAA,MACC,aAAU;AAAA,MACV;AAAA,MACA,WAAW,GAAG,uBAAuB,EAAE,KAAK,CAAC,GAAG,SAAS;AAAA,MACxD,GAAG;AAAA,MAEH;AAAA;AAAA,QACA,QAAQ,oBAAC,iBAAiB,OAAjB,EAAuB,WAAU,uBAAsB,IAAK;AAAA;AAAA;AAAA,EACxE,GACF;AAEJ;","names":[]}
@@ -93,6 +93,10 @@ function ModalDescription({ asChild, className, ...props }) {
93
93
  }
94
94
  );
95
95
  }
96
+ function ModalBody({ asChild, className, ...props }) {
97
+ const Comp = asChild ? SlotPrimitive.Slot : "div";
98
+ return /* @__PURE__ */ jsx(Comp, { "data-slot": "modal-body", className: cn("ddga-modal__body", className), ...props });
99
+ }
96
100
  function ModalFooter({ asChild, className, ...props }) {
97
101
  const Comp = asChild ? SlotPrimitive.Slot : "div";
98
102
  return /* @__PURE__ */ jsx(Comp, { "data-slot": "modal-footer", className: cn("ddga-modal__footer", className), ...props });
@@ -109,7 +113,8 @@ export {
109
113
  ModalHeader,
110
114
  ModalTitle,
111
115
  ModalDescription,
116
+ ModalBody,
112
117
  ModalFooter,
113
118
  ModalClose
114
119
  };
115
- //# sourceMappingURL=chunk-TWCX4EZR.js.map
120
+ //# sourceMappingURL=chunk-JOJ23OD4.js.map