@refraction-ui/react 0.23.1 → 0.23.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,11 +1,8 @@
1
1
  import {
2
- Keys,
3
2
  cn,
4
3
  createKeyboardHandler,
5
- createMachine,
6
4
  cva,
7
- devWarn,
8
- generateId
5
+ devWarn
9
6
  } from "./chunk-75BKRTPO.js";
10
7
 
11
8
  // ../react-dropdown-menu/dist/index.js
@@ -13,88 +10,6 @@ import * as React from "react";
13
10
  import * as ReactDOM from "react-dom";
14
11
 
15
12
  // ../dropdown-menu/dist/index.js
16
- function createDropdownMenu(props = {}) {
17
- const { open: controlledOpen, defaultOpen = false, onOpenChange } = props;
18
- const machine = createMachine({
19
- initial: controlledOpen ?? defaultOpen ? "open" : "closed",
20
- states: {
21
- closed: { on: { OPEN: "open" } },
22
- open: { on: { CLOSE: "closed" } }
23
- }
24
- });
25
- const contentId = generateId("rfr-dropdown-menu");
26
- function isOpen() {
27
- if (controlledOpen !== void 0) return controlledOpen;
28
- return machine.matches("open");
29
- }
30
- function openMenu() {
31
- machine.send("OPEN");
32
- onOpenChange?.(true);
33
- }
34
- function closeMenu() {
35
- machine.send("CLOSE");
36
- onOpenChange?.(false);
37
- }
38
- function toggleMenu() {
39
- if (isOpen()) {
40
- closeMenu();
41
- } else {
42
- openMenu();
43
- }
44
- }
45
- function getItemProps(item) {
46
- return {
47
- role: "menuitem",
48
- tabIndex: item.disabled ? -1 : 0,
49
- "data-disabled": item.disabled ? "" : void 0,
50
- "aria-disabled": item.disabled || void 0
51
- };
52
- }
53
- const keyboardHandlers = {
54
- [Keys.Escape]: (e) => {
55
- e.preventDefault();
56
- closeMenu();
57
- },
58
- [Keys.ArrowDown]: (e) => {
59
- e.preventDefault();
60
- },
61
- [Keys.ArrowUp]: (e) => {
62
- e.preventDefault();
63
- },
64
- [Keys.Enter]: (e) => {
65
- e.preventDefault();
66
- },
67
- [Keys.Home]: (e) => {
68
- e.preventDefault();
69
- },
70
- [Keys.End]: (e) => {
71
- e.preventDefault();
72
- }
73
- };
74
- const triggerProps = {
75
- "aria-expanded": isOpen(),
76
- "aria-controls": contentId,
77
- "aria-haspopup": "menu"
78
- };
79
- const contentProps = {
80
- role: "menu",
81
- id: contentId,
82
- "data-state": isOpen() ? "open" : "closed"
83
- };
84
- return {
85
- state: { open: isOpen() },
86
- triggerProps,
87
- contentProps,
88
- getItemProps,
89
- open: openMenu,
90
- close: closeMenu,
91
- toggle: toggleMenu,
92
- keyboardHandlers,
93
- ids: {
94
- content: contentId
95
- }
96
- };
97
- }
98
13
  var menuContentVariants = cva({
99
14
  base: "z-50 rounded-md border bg-popover shadow-md"
100
15
  });
@@ -133,20 +48,16 @@ function DropdownMenu({
133
48
  },
134
49
  [isControlled, onOpenChange]
135
50
  );
136
- const apiRef = React.useRef(null);
137
- if (apiRef.current === null) {
138
- apiRef.current = createDropdownMenu({ open });
139
- }
140
- const api = apiRef.current;
51
+ const contentId = `rfr-dropdown-menu-${React.useId()}`;
141
52
  const triggerRef = React.useRef(null);
142
53
  const ctx = React.useMemo(
143
54
  () => ({
144
55
  open,
145
56
  onOpenChange: handleOpenChange,
146
- contentId: api.ids.content,
57
+ contentId,
147
58
  triggerRef
148
59
  }),
149
- [open, handleOpenChange, api.ids.content]
60
+ [open, handleOpenChange, contentId]
150
61
  );
151
62
  return React.createElement(DropdownMenuContext.Provider, { value: ctx }, children);
152
63
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../dropdown-menu/src/dropdown-menu.ts", "../../dropdown-menu/src/dropdown-menu.styles.ts", "../../react-dropdown-menu/src/dropdown-menu.tsx"],
4
- "sourcesContent": ["import type { AccessibilityProps, KeyboardHandlerMap } from '@refraction-ui/shared'\nimport { createMachine, Keys, generateId } from '@refraction-ui/shared'\n\nexport interface DropdownMenuProps {\n /** Whether the menu is open (controlled) */\n open?: boolean\n /** Whether the menu starts open (uncontrolled) */\n defaultOpen?: boolean\n /** Callback when open state changes */\n onOpenChange?: (open: boolean) => void\n}\n\nexport interface MenuItemProps {\n /** Whether the item is disabled */\n disabled?: boolean\n /** Callback when the item is selected */\n onSelect?: () => void\n}\n\nexport interface DropdownMenuState {\n open: boolean\n}\n\nexport interface DropdownMenuAPI {\n /** Current menu state */\n state: DropdownMenuState\n /** ARIA attributes for the trigger button */\n triggerProps: Partial<AccessibilityProps> & Record<string, unknown>\n /** ARIA attributes for the menu content */\n contentProps: Partial<AccessibilityProps> & Record<string, unknown>\n /** Factory for menu item props */\n getItemProps(item: MenuItemProps): Partial<AccessibilityProps> & Record<string, unknown>\n /** Open the menu */\n open(): void\n /** Close the menu */\n close(): void\n /** Toggle the menu */\n toggle(): void\n /** Keyboard handlers for the menu */\n keyboardHandlers: KeyboardHandlerMap\n /** Generated IDs for aria linking */\n ids: {\n content: string\n }\n}\n\nexport function createDropdownMenu(props: DropdownMenuProps = {}): DropdownMenuAPI {\n const { open: controlledOpen, defaultOpen = false, onOpenChange } = props\n\n const machine = createMachine<'open' | 'closed', 'OPEN' | 'CLOSE'>({\n initial: controlledOpen ?? defaultOpen ? 'open' : 'closed',\n states: {\n closed: { on: { OPEN: 'open' } },\n open: { on: { CLOSE: 'closed' } },\n },\n })\n\n const contentId = generateId('rfr-dropdown-menu')\n\n function isOpen(): boolean {\n if (controlledOpen !== undefined) return controlledOpen\n return machine.matches('open')\n }\n\n function openMenu(): void {\n machine.send('OPEN')\n onOpenChange?.(true)\n }\n\n function closeMenu(): void {\n machine.send('CLOSE')\n onOpenChange?.(false)\n }\n\n function toggleMenu(): void {\n if (isOpen()) {\n closeMenu()\n } else {\n openMenu()\n }\n }\n\n function getItemProps(item: MenuItemProps): Partial<AccessibilityProps> & Record<string, unknown> {\n return {\n role: 'menuitem',\n tabIndex: item.disabled ? -1 : 0,\n 'data-disabled': item.disabled ? '' : undefined,\n 'aria-disabled': item.disabled || undefined,\n }\n }\n\n const keyboardHandlers: KeyboardHandlerMap = {\n [Keys.Escape]: (e: KeyboardEvent) => {\n e.preventDefault()\n closeMenu()\n },\n [Keys.ArrowDown]: (e: KeyboardEvent) => {\n e.preventDefault()\n },\n [Keys.ArrowUp]: (e: KeyboardEvent) => {\n e.preventDefault()\n },\n [Keys.Enter]: (e: KeyboardEvent) => {\n e.preventDefault()\n },\n [Keys.Home]: (e: KeyboardEvent) => {\n e.preventDefault()\n },\n [Keys.End]: (e: KeyboardEvent) => {\n e.preventDefault()\n },\n }\n\n const triggerProps: Partial<AccessibilityProps> & Record<string, unknown> = {\n 'aria-expanded': isOpen(),\n 'aria-controls': contentId,\n 'aria-haspopup': 'menu',\n }\n\n const contentProps: Partial<AccessibilityProps> & Record<string, unknown> = {\n role: 'menu',\n id: contentId,\n 'data-state': isOpen() ? 'open' : 'closed',\n }\n\n return {\n state: { open: isOpen() },\n triggerProps,\n contentProps,\n getItemProps,\n open: openMenu,\n close: closeMenu,\n toggle: toggleMenu,\n keyboardHandlers,\n ids: {\n content: contentId,\n },\n }\n}\n", "import { cva } from '@refraction-ui/shared'\n\nexport const menuContentVariants = cva({\n base: 'z-50 rounded-md border bg-popover shadow-md',\n})\n\nexport const menuItemVariants = cva({\n base: 'relative flex cursor-default items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\n})\n", "import * as React from 'react'\nimport * as ReactDOM from 'react-dom'\nimport {\n createDropdownMenu,\n menuContentVariants,\n menuItemVariants,\n type DropdownMenuProps as CoreDropdownMenuProps,\n type MenuItemProps as CoreMenuItemProps,\n} from '@refraction-ui/dropdown-menu'\nimport { cn, createKeyboardHandler, devWarn } from '@refraction-ui/shared'\n\n// ---------------------------------------------------------------------------\n// Context\n// ---------------------------------------------------------------------------\n\ninterface DropdownMenuContextValue {\n open: boolean\n onOpenChange: (open: boolean) => void\n contentId: string\n /** The trigger element, so the portalled content can anchor to it. */\n triggerRef: React.MutableRefObject<HTMLElement | null>\n}\n\nconst DropdownMenuContext = React.createContext<DropdownMenuContextValue | null>(null)\n\nfunction useDropdownMenuContext(): DropdownMenuContextValue {\n const ctx = React.useContext(DropdownMenuContext)\n if (!ctx) {\n devWarn(\n 'react-dropdown-menu/context-outside-provider',\n 'DropdownMenu compound components (DropdownMenuTrigger/DropdownMenuContent/DropdownMenuItem/etc.) must be rendered inside a <DropdownMenu>. The missing DropdownMenuContext makes this throw.',\n )\n throw new Error('DropdownMenu compound components must be used within <DropdownMenu>')\n }\n return ctx\n}\n\n// ---------------------------------------------------------------------------\n// DropdownMenu (root provider)\n// ---------------------------------------------------------------------------\n\nexport interface DropdownMenuProps {\n open?: boolean\n defaultOpen?: boolean\n onOpenChange?: (open: boolean) => void\n children?: React.ReactNode\n}\n\nexport function DropdownMenu({\n open: controlledOpen,\n defaultOpen = false,\n onOpenChange,\n children,\n}: DropdownMenuProps) {\n const [uncontrolledOpen, setUncontrolledOpen] = React.useState(defaultOpen)\n const isControlled = controlledOpen !== undefined\n const open = isControlled ? controlledOpen : uncontrolledOpen\n\n const handleOpenChange = React.useCallback(\n (next: boolean) => {\n if (!isControlled) {\n setUncontrolledOpen(next)\n }\n onOpenChange?.(next)\n },\n [isControlled, onOpenChange],\n )\n\n // Use the headless core to get stable IDs\n const apiRef = React.useRef<ReturnType<typeof createDropdownMenu> | null>(null)\n if (apiRef.current === null) {\n apiRef.current = createDropdownMenu({ open })\n }\n const api = apiRef.current\n\n const triggerRef = React.useRef<HTMLElement | null>(null)\n\n const ctx = React.useMemo<DropdownMenuContextValue>(\n () => ({\n open,\n onOpenChange: handleOpenChange,\n contentId: api.ids.content,\n triggerRef,\n }),\n [open, handleOpenChange, api.ids.content],\n )\n\n return React.createElement(DropdownMenuContext.Provider, { value: ctx }, children)\n}\n\n// ---------------------------------------------------------------------------\n// DropdownMenuTrigger\n// ---------------------------------------------------------------------------\n\nexport interface DropdownMenuTriggerProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n /** Merge the trigger's props/behavior onto the child element instead of\n * rendering a `<button>` around it (Radix-style `asChild`). Use it with\n * styled triggers like `<Button>` — otherwise you'd nest a button in a\n * button (invalid HTML and a hydration error). */\n asChild?: boolean\n}\n\nexport const DropdownMenuTrigger = React.forwardRef<HTMLButtonElement, DropdownMenuTriggerProps>(\n function DropdownMenuTrigger({ asChild = false, onClick, children, ...props }, ref) {\n const { open, onOpenChange, contentId, triggerRef } = useDropdownMenuContext()\n const setRefs = (node: HTMLButtonElement | null) => {\n triggerRef.current = node\n if (typeof ref === 'function') ref(node)\n else if (ref) ref.current = node\n }\n\n const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {\n onOpenChange(!open)\n onClick?.(e)\n }\n\n const triggerProps = {\n type: 'button' as const,\n 'aria-expanded': open,\n 'aria-controls': contentId,\n 'aria-haspopup': 'menu' as const,\n onClick: handleClick,\n ...props,\n }\n\n if (asChild) {\n if (!React.isValidElement(children)) {\n devWarn(\n 'dropdown-menu-trigger-asChild-child',\n 'DropdownMenuTrigger: `asChild` expects a single React element child; rendering nothing.',\n )\n return null\n }\n const child = children as React.ReactElement<\n Record<string, unknown>\n > & { ref?: React.Ref<HTMLButtonElement> }\n const childOnClick = child.props.onClick as\n | ((e: React.MouseEvent<HTMLButtonElement>) => void)\n | undefined\n const childRef = child.ref\n const mergedProps = {\n ...triggerProps,\n onClick: (e: React.MouseEvent<HTMLButtonElement>) => {\n childOnClick?.(e)\n if (!e.defaultPrevented) handleClick(e)\n },\n ref: (node: HTMLButtonElement | null) => {\n setRefs(node)\n if (typeof childRef === 'function') childRef(node)\n else if (childRef) childRef.current = node\n },\n }\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return React.cloneElement(child, mergedProps as any)\n }\n\n return React.createElement('button', { ref: setRefs, ...triggerProps }, children)\n },\n)\n\n// ---------------------------------------------------------------------------\n// Positioning\n// ---------------------------------------------------------------------------\n\nexport type DropdownMenuAlign = 'start' | 'center' | 'end'\n\nconst DEFAULT_SIDE_OFFSET = 4\n\nconst useIsomorphicLayoutEffect = typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect\n\n/**\n * Fixed-position coordinates that place a menu under its trigger, aligned to\n * the trigger's start, centre or end edge. Pure, so it is unit-testable.\n */\nexport function computeMenuPosition(\n trigger: { top: number; bottom: number; left: number; right: number; width: number },\n contentWidth: number,\n align: DropdownMenuAlign,\n sideOffset: number,\n): React.CSSProperties {\n const left =\n align === 'end'\n ? trigger.right - contentWidth\n : align === 'center'\n ? trigger.left + trigger.width / 2 - contentWidth / 2\n : trigger.left\n return { position: 'fixed', top: trigger.bottom + sideOffset, left: Math.max(0, left), minWidth: trigger.width }\n}\n\n// ---------------------------------------------------------------------------\n// DropdownMenuContent\n// ---------------------------------------------------------------------------\n\nexport interface DropdownMenuContentProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Horizontal alignment to the trigger. Defaults to `start`. */\n align?: DropdownMenuAlign\n /** Gap between trigger and menu in px. Defaults to 4. */\n sideOffset?: number\n}\n\nexport const DropdownMenuContent = React.forwardRef<HTMLDivElement, DropdownMenuContentProps>(\n function DropdownMenuContent(\n { className, children, onKeyDown, align = 'start', sideOffset = DEFAULT_SIDE_OFFSET, style, ...props },\n forwardedRef,\n ) {\n const { open, onOpenChange, contentId, triggerRef } = useDropdownMenuContext()\n const contentRef = React.useRef<HTMLDivElement | null>(null)\n const ref = React.useCallback(\n (node: HTMLDivElement | null) => {\n contentRef.current = node\n if (typeof forwardedRef === 'function') forwardedRef(node)\n else if (forwardedRef) forwardedRef.current = node\n },\n [forwardedRef],\n )\n const [position, setPosition] = React.useState<React.CSSProperties | null>(null)\n\n // The content is portalled to <body>, so anchor it to the trigger with\n // fixed coordinates, and follow the trigger on scroll / resize.\n useIsomorphicLayoutEffect(() => {\n if (!open) return\n const update = () => {\n const trigger = triggerRef.current\n const content = contentRef.current\n if (!trigger) return\n setPosition(\n computeMenuPosition(trigger.getBoundingClientRect(), content?.offsetWidth ?? 0, align, sideOffset),\n )\n }\n update()\n window.addEventListener('resize', update)\n window.addEventListener('scroll', update, true)\n return () => {\n window.removeEventListener('resize', update)\n window.removeEventListener('scroll', update, true)\n }\n }, [open, align, sideOffset, triggerRef])\n\n // Close on a pointer press outside the menu and its trigger.\n React.useEffect(() => {\n if (!open) return\n const onPointerDown = (event: PointerEvent) => {\n const target = event.target as Node\n if (contentRef.current?.contains(target) || triggerRef.current?.contains(target)) return\n onOpenChange(false)\n }\n document.addEventListener('pointerdown', onPointerDown)\n return () => document.removeEventListener('pointerdown', onPointerDown)\n }, [open, onOpenChange, triggerRef])\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {\n const handler = createKeyboardHandler({\n Escape: (ev) => {\n ev.preventDefault()\n onOpenChange(false)\n },\n })\n handler(e.nativeEvent)\n onKeyDown?.(e)\n }\n\n if (!open) return null\n\n const content = React.createElement(\n 'div',\n {\n ref,\n role: 'menu',\n id: contentId,\n 'data-state': open ? 'open' : 'closed',\n className: cn(menuContentVariants(), className),\n style: position ? { ...position, ...style } : style,\n 'data-align': align,\n onKeyDown: handleKeyDown,\n tabIndex: -1,\n ...props,\n },\n children,\n )\n\n // Render via portal if document is available (client-side)\n if (typeof document !== 'undefined') {\n return ReactDOM.createPortal(content, document.body)\n }\n\n // SSR fallback: render inline\n return content\n },\n)\n\n// ---------------------------------------------------------------------------\n// DropdownMenuItem\n// ---------------------------------------------------------------------------\n\nexport interface DropdownMenuItemProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onSelect'> {\n disabled?: boolean\n onSelect?: () => void\n}\n\nexport const DropdownMenuItem = React.forwardRef<HTMLDivElement, DropdownMenuItemProps>(\n function DropdownMenuItem({ className, disabled, onSelect, onClick, children, ...props }, ref) {\n const { onOpenChange } = useDropdownMenuContext()\n\n const handleClick = (e: React.MouseEvent<HTMLDivElement>) => {\n if (disabled) return\n onSelect?.()\n onOpenChange(false)\n onClick?.(e)\n }\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {\n if (disabled) return\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n onSelect?.()\n onOpenChange(false)\n }\n }\n\n return React.createElement(\n 'div',\n {\n ref,\n role: 'menuitem',\n tabIndex: disabled ? -1 : 0,\n 'data-disabled': disabled ? '' : undefined,\n 'aria-disabled': disabled || undefined,\n className: cn(menuItemVariants(), className),\n onClick: handleClick,\n onKeyDown: handleKeyDown,\n ...props,\n },\n children,\n )\n },\n)\n\n// ---------------------------------------------------------------------------\n// DropdownMenuSeparator\n// ---------------------------------------------------------------------------\n\nexport interface DropdownMenuSeparatorProps extends React.HTMLAttributes<HTMLDivElement> {}\n\nexport const DropdownMenuSeparator = React.forwardRef<HTMLDivElement, DropdownMenuSeparatorProps>(\n function DropdownMenuSeparator({ className, ...props }, ref) {\n return React.createElement('div', {\n ref,\n role: 'separator',\n className: cn('-mx-1 my-1 h-px bg-muted', className),\n ...props,\n })\n },\n)\n\n// ---------------------------------------------------------------------------\n// DropdownMenuLabel\n// ---------------------------------------------------------------------------\n\nexport interface DropdownMenuLabelProps extends React.HTMLAttributes<HTMLDivElement> {}\n\nexport const DropdownMenuLabel = React.forwardRef<HTMLDivElement, DropdownMenuLabelProps>(\n function DropdownMenuLabel({ className, ...props }, ref) {\n return React.createElement('div', {\n ref,\n className: cn('px-2 py-1.5 text-sm font-semibold', className),\n ...props,\n })\n },\n)\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type { AccessibilityProps, KeyboardHandlerMap } from '@refraction-ui/shared'\nimport { createMachine, Keys, generateId } from '@refraction-ui/shared'\n\nexport interface DropdownMenuProps {\n /** Whether the menu is open (controlled) */\n open?: boolean\n /** Whether the menu starts open (uncontrolled) */\n defaultOpen?: boolean\n /** Callback when open state changes */\n onOpenChange?: (open: boolean) => void\n}\n\nexport interface MenuItemProps {\n /** Whether the item is disabled */\n disabled?: boolean\n /** Callback when the item is selected */\n onSelect?: () => void\n}\n\nexport interface DropdownMenuState {\n open: boolean\n}\n\nexport interface DropdownMenuAPI {\n /** Current menu state */\n state: DropdownMenuState\n /** ARIA attributes for the trigger button */\n triggerProps: Partial<AccessibilityProps> & Record<string, unknown>\n /** ARIA attributes for the menu content */\n contentProps: Partial<AccessibilityProps> & Record<string, unknown>\n /** Factory for menu item props */\n getItemProps(item: MenuItemProps): Partial<AccessibilityProps> & Record<string, unknown>\n /** Open the menu */\n open(): void\n /** Close the menu */\n close(): void\n /** Toggle the menu */\n toggle(): void\n /** Keyboard handlers for the menu */\n keyboardHandlers: KeyboardHandlerMap\n /** Generated IDs for aria linking */\n ids: {\n content: string\n }\n}\n\nexport function createDropdownMenu(props: DropdownMenuProps = {}): DropdownMenuAPI {\n const { open: controlledOpen, defaultOpen = false, onOpenChange } = props\n\n const machine = createMachine<'open' | 'closed', 'OPEN' | 'CLOSE'>({\n initial: controlledOpen ?? defaultOpen ? 'open' : 'closed',\n states: {\n closed: { on: { OPEN: 'open' } },\n open: { on: { CLOSE: 'closed' } },\n },\n })\n\n const contentId = generateId('rfr-dropdown-menu')\n\n function isOpen(): boolean {\n if (controlledOpen !== undefined) return controlledOpen\n return machine.matches('open')\n }\n\n function openMenu(): void {\n machine.send('OPEN')\n onOpenChange?.(true)\n }\n\n function closeMenu(): void {\n machine.send('CLOSE')\n onOpenChange?.(false)\n }\n\n function toggleMenu(): void {\n if (isOpen()) {\n closeMenu()\n } else {\n openMenu()\n }\n }\n\n function getItemProps(item: MenuItemProps): Partial<AccessibilityProps> & Record<string, unknown> {\n return {\n role: 'menuitem',\n tabIndex: item.disabled ? -1 : 0,\n 'data-disabled': item.disabled ? '' : undefined,\n 'aria-disabled': item.disabled || undefined,\n }\n }\n\n const keyboardHandlers: KeyboardHandlerMap = {\n [Keys.Escape]: (e: KeyboardEvent) => {\n e.preventDefault()\n closeMenu()\n },\n [Keys.ArrowDown]: (e: KeyboardEvent) => {\n e.preventDefault()\n },\n [Keys.ArrowUp]: (e: KeyboardEvent) => {\n e.preventDefault()\n },\n [Keys.Enter]: (e: KeyboardEvent) => {\n e.preventDefault()\n },\n [Keys.Home]: (e: KeyboardEvent) => {\n e.preventDefault()\n },\n [Keys.End]: (e: KeyboardEvent) => {\n e.preventDefault()\n },\n }\n\n const triggerProps: Partial<AccessibilityProps> & Record<string, unknown> = {\n 'aria-expanded': isOpen(),\n 'aria-controls': contentId,\n 'aria-haspopup': 'menu',\n }\n\n const contentProps: Partial<AccessibilityProps> & Record<string, unknown> = {\n role: 'menu',\n id: contentId,\n 'data-state': isOpen() ? 'open' : 'closed',\n }\n\n return {\n state: { open: isOpen() },\n triggerProps,\n contentProps,\n getItemProps,\n open: openMenu,\n close: closeMenu,\n toggle: toggleMenu,\n keyboardHandlers,\n ids: {\n content: contentId,\n },\n }\n}\n", "import { cva } from '@refraction-ui/shared'\n\nexport const menuContentVariants = cva({\n base: 'z-50 rounded-md border bg-popover shadow-md',\n})\n\nexport const menuItemVariants = cva({\n base: 'relative flex cursor-default items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\n})\n", "import * as React from 'react'\nimport * as ReactDOM from 'react-dom'\nimport {\n menuContentVariants,\n menuItemVariants,\n type DropdownMenuProps as CoreDropdownMenuProps,\n type MenuItemProps as CoreMenuItemProps,\n} from '@refraction-ui/dropdown-menu'\nimport { cn, createKeyboardHandler, devWarn } from '@refraction-ui/shared'\n\n// ---------------------------------------------------------------------------\n// Context\n// ---------------------------------------------------------------------------\n\ninterface DropdownMenuContextValue {\n open: boolean\n onOpenChange: (open: boolean) => void\n contentId: string\n /** The trigger element, so the portalled content can anchor to it. */\n triggerRef: React.MutableRefObject<HTMLElement | null>\n}\n\nconst DropdownMenuContext = React.createContext<DropdownMenuContextValue | null>(null)\n\nfunction useDropdownMenuContext(): DropdownMenuContextValue {\n const ctx = React.useContext(DropdownMenuContext)\n if (!ctx) {\n devWarn(\n 'react-dropdown-menu/context-outside-provider',\n 'DropdownMenu compound components (DropdownMenuTrigger/DropdownMenuContent/DropdownMenuItem/etc.) must be rendered inside a <DropdownMenu>. The missing DropdownMenuContext makes this throw.',\n )\n throw new Error('DropdownMenu compound components must be used within <DropdownMenu>')\n }\n return ctx\n}\n\n// ---------------------------------------------------------------------------\n// DropdownMenu (root provider)\n// ---------------------------------------------------------------------------\n\nexport interface DropdownMenuProps {\n open?: boolean\n defaultOpen?: boolean\n onOpenChange?: (open: boolean) => void\n children?: React.ReactNode\n}\n\nexport function DropdownMenu({\n open: controlledOpen,\n defaultOpen = false,\n onOpenChange,\n children,\n}: DropdownMenuProps) {\n const [uncontrolledOpen, setUncontrolledOpen] = React.useState(defaultOpen)\n const isControlled = controlledOpen !== undefined\n const open = isControlled ? controlledOpen : uncontrolledOpen\n\n const handleOpenChange = React.useCallback(\n (next: boolean) => {\n if (!isControlled) {\n setUncontrolledOpen(next)\n }\n onOpenChange?.(next)\n },\n [isControlled, onOpenChange],\n )\n\n // React IDs agree across SSR and hydration, unlike the core's process counter.\n const contentId = `rfr-dropdown-menu-${React.useId()}`\n\n const triggerRef = React.useRef<HTMLElement | null>(null)\n\n const ctx = React.useMemo<DropdownMenuContextValue>(\n () => ({\n open,\n onOpenChange: handleOpenChange,\n contentId,\n triggerRef,\n }),\n [open, handleOpenChange, contentId],\n )\n\n return React.createElement(DropdownMenuContext.Provider, { value: ctx }, children)\n}\n\n// ---------------------------------------------------------------------------\n// DropdownMenuTrigger\n// ---------------------------------------------------------------------------\n\nexport interface DropdownMenuTriggerProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n /** Merge the trigger's props/behavior onto the child element instead of\n * rendering a `<button>` around it (Radix-style `asChild`). Use it with\n * styled triggers like `<Button>` — otherwise you'd nest a button in a\n * button (invalid HTML and a hydration error). */\n asChild?: boolean\n}\n\nexport const DropdownMenuTrigger = React.forwardRef<HTMLButtonElement, DropdownMenuTriggerProps>(\n function DropdownMenuTrigger({ asChild = false, onClick, children, ...props }, ref) {\n const { open, onOpenChange, contentId, triggerRef } = useDropdownMenuContext()\n const setRefs = (node: HTMLButtonElement | null) => {\n triggerRef.current = node\n if (typeof ref === 'function') ref(node)\n else if (ref) ref.current = node\n }\n\n const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {\n onOpenChange(!open)\n onClick?.(e)\n }\n\n const triggerProps = {\n type: 'button' as const,\n 'aria-expanded': open,\n 'aria-controls': contentId,\n 'aria-haspopup': 'menu' as const,\n onClick: handleClick,\n ...props,\n }\n\n if (asChild) {\n if (!React.isValidElement(children)) {\n devWarn(\n 'dropdown-menu-trigger-asChild-child',\n 'DropdownMenuTrigger: `asChild` expects a single React element child; rendering nothing.',\n )\n return null\n }\n const child = children as React.ReactElement<\n Record<string, unknown>\n > & { ref?: React.Ref<HTMLButtonElement> }\n const childOnClick = child.props.onClick as\n | ((e: React.MouseEvent<HTMLButtonElement>) => void)\n | undefined\n const childRef = child.ref\n const mergedProps = {\n ...triggerProps,\n onClick: (e: React.MouseEvent<HTMLButtonElement>) => {\n childOnClick?.(e)\n if (!e.defaultPrevented) handleClick(e)\n },\n ref: (node: HTMLButtonElement | null) => {\n setRefs(node)\n if (typeof childRef === 'function') childRef(node)\n else if (childRef) childRef.current = node\n },\n }\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return React.cloneElement(child, mergedProps as any)\n }\n\n return React.createElement('button', { ref: setRefs, ...triggerProps }, children)\n },\n)\n\n// ---------------------------------------------------------------------------\n// Positioning\n// ---------------------------------------------------------------------------\n\nexport type DropdownMenuAlign = 'start' | 'center' | 'end'\n\nconst DEFAULT_SIDE_OFFSET = 4\n\nconst useIsomorphicLayoutEffect = typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect\n\n/**\n * Fixed-position coordinates that place a menu under its trigger, aligned to\n * the trigger's start, centre or end edge. Pure, so it is unit-testable.\n */\nexport function computeMenuPosition(\n trigger: { top: number; bottom: number; left: number; right: number; width: number },\n contentWidth: number,\n align: DropdownMenuAlign,\n sideOffset: number,\n): React.CSSProperties {\n const left =\n align === 'end'\n ? trigger.right - contentWidth\n : align === 'center'\n ? trigger.left + trigger.width / 2 - contentWidth / 2\n : trigger.left\n return { position: 'fixed', top: trigger.bottom + sideOffset, left: Math.max(0, left), minWidth: trigger.width }\n}\n\n// ---------------------------------------------------------------------------\n// DropdownMenuContent\n// ---------------------------------------------------------------------------\n\nexport interface DropdownMenuContentProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Horizontal alignment to the trigger. Defaults to `start`. */\n align?: DropdownMenuAlign\n /** Gap between trigger and menu in px. Defaults to 4. */\n sideOffset?: number\n}\n\nexport const DropdownMenuContent = React.forwardRef<HTMLDivElement, DropdownMenuContentProps>(\n function DropdownMenuContent(\n { className, children, onKeyDown, align = 'start', sideOffset = DEFAULT_SIDE_OFFSET, style, ...props },\n forwardedRef,\n ) {\n const { open, onOpenChange, contentId, triggerRef } = useDropdownMenuContext()\n const contentRef = React.useRef<HTMLDivElement | null>(null)\n const ref = React.useCallback(\n (node: HTMLDivElement | null) => {\n contentRef.current = node\n if (typeof forwardedRef === 'function') forwardedRef(node)\n else if (forwardedRef) forwardedRef.current = node\n },\n [forwardedRef],\n )\n const [position, setPosition] = React.useState<React.CSSProperties | null>(null)\n\n // The content is portalled to <body>, so anchor it to the trigger with\n // fixed coordinates, and follow the trigger on scroll / resize.\n useIsomorphicLayoutEffect(() => {\n if (!open) return\n const update = () => {\n const trigger = triggerRef.current\n const content = contentRef.current\n if (!trigger) return\n setPosition(\n computeMenuPosition(trigger.getBoundingClientRect(), content?.offsetWidth ?? 0, align, sideOffset),\n )\n }\n update()\n window.addEventListener('resize', update)\n window.addEventListener('scroll', update, true)\n return () => {\n window.removeEventListener('resize', update)\n window.removeEventListener('scroll', update, true)\n }\n }, [open, align, sideOffset, triggerRef])\n\n // Close on a pointer press outside the menu and its trigger.\n React.useEffect(() => {\n if (!open) return\n const onPointerDown = (event: PointerEvent) => {\n const target = event.target as Node\n if (contentRef.current?.contains(target) || triggerRef.current?.contains(target)) return\n onOpenChange(false)\n }\n document.addEventListener('pointerdown', onPointerDown)\n return () => document.removeEventListener('pointerdown', onPointerDown)\n }, [open, onOpenChange, triggerRef])\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {\n const handler = createKeyboardHandler({\n Escape: (ev) => {\n ev.preventDefault()\n onOpenChange(false)\n },\n })\n handler(e.nativeEvent)\n onKeyDown?.(e)\n }\n\n if (!open) return null\n\n const content = React.createElement(\n 'div',\n {\n ref,\n role: 'menu',\n id: contentId,\n 'data-state': open ? 'open' : 'closed',\n className: cn(menuContentVariants(), className),\n style: position ? { ...position, ...style } : style,\n 'data-align': align,\n onKeyDown: handleKeyDown,\n tabIndex: -1,\n ...props,\n },\n children,\n )\n\n // Render via portal if document is available (client-side)\n if (typeof document !== 'undefined') {\n return ReactDOM.createPortal(content, document.body)\n }\n\n // SSR fallback: render inline\n return content\n },\n)\n\n// ---------------------------------------------------------------------------\n// DropdownMenuItem\n// ---------------------------------------------------------------------------\n\nexport interface DropdownMenuItemProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onSelect'> {\n disabled?: boolean\n onSelect?: () => void\n}\n\nexport const DropdownMenuItem = React.forwardRef<HTMLDivElement, DropdownMenuItemProps>(\n function DropdownMenuItem({ className, disabled, onSelect, onClick, children, ...props }, ref) {\n const { onOpenChange } = useDropdownMenuContext()\n\n const handleClick = (e: React.MouseEvent<HTMLDivElement>) => {\n if (disabled) return\n onSelect?.()\n onOpenChange(false)\n onClick?.(e)\n }\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {\n if (disabled) return\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n onSelect?.()\n onOpenChange(false)\n }\n }\n\n return React.createElement(\n 'div',\n {\n ref,\n role: 'menuitem',\n tabIndex: disabled ? -1 : 0,\n 'data-disabled': disabled ? '' : undefined,\n 'aria-disabled': disabled || undefined,\n className: cn(menuItemVariants(), className),\n onClick: handleClick,\n onKeyDown: handleKeyDown,\n ...props,\n },\n children,\n )\n },\n)\n\n// ---------------------------------------------------------------------------\n// DropdownMenuSeparator\n// ---------------------------------------------------------------------------\n\nexport interface DropdownMenuSeparatorProps extends React.HTMLAttributes<HTMLDivElement> {}\n\nexport const DropdownMenuSeparator = React.forwardRef<HTMLDivElement, DropdownMenuSeparatorProps>(\n function DropdownMenuSeparator({ className, ...props }, ref) {\n return React.createElement('div', {\n ref,\n role: 'separator',\n className: cn('-mx-1 my-1 h-px bg-muted', className),\n ...props,\n })\n },\n)\n\n// ---------------------------------------------------------------------------\n// DropdownMenuLabel\n// ---------------------------------------------------------------------------\n\nexport interface DropdownMenuLabelProps extends React.HTMLAttributes<HTMLDivElement> {}\n\nexport const DropdownMenuLabel = React.forwardRef<HTMLDivElement, DropdownMenuLabelProps>(\n function DropdownMenuLabel({ className, ...props }, ref) {\n return React.createElement('div', {\n ref,\n className: cn('px-2 py-1.5 text-sm font-semibold', className),\n ...props,\n })\n },\n)\n"],
5
+ "mappings": "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",
6
6
  "names": ["DropdownMenuTrigger", "DropdownMenuContent", "content", "DropdownMenuItem", "DropdownMenuSeparator", "DropdownMenuLabel"]
7
7
  }
@@ -15,7 +15,7 @@ function createPageHeader(props = {}) {
15
15
  };
16
16
  }
17
17
  var pageHeaderClass = "flex flex-wrap items-start justify-between gap-4";
18
- var pageHeaderTextClass = "flex min-w-0 flex-1 flex-col gap-1";
18
+ var pageHeaderTextClass = "flex min-w-0 basis-64 grow flex-col gap-1";
19
19
  var pageHeaderKickerClass = "break-words text-[11px] uppercase tracking-wider text-muted-foreground";
20
20
  var pageHeaderTitleClass = "break-words text-xl font-semibold text-foreground";
21
21
  var pageHeaderDescriptionClass = "max-w-prose text-sm text-muted-foreground";
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../page-header/src/page-header.ts", "../../page-header/src/page-header.styles.ts", "../../react-page-header/src/page-header.tsx"],
4
- "sourcesContent": ["/** Heading element used for the page title. */\nexport type PageHeaderTitleLevel = 'h1' | 'h2' | 'h3'\n\nexport interface PageHeaderProps {\n /** Whether an actions slot will be rendered. */\n hasActions?: boolean\n}\n\nexport interface PageHeaderAPI {\n /** Data attributes for styling hooks. */\n dataAttributes: Record<string, string>\n}\n\n/**\n * Build the framework-agnostic data attributes for a PageHeader — the heading\n * cluster at the top of an application page (kicker, title, description and a\n * trailing actions row). Unlike SectionHead (a centred marketing heading) it is\n * sized for dense app chrome and never centres.\n */\nexport function createPageHeader(props: PageHeaderProps = {}): PageHeaderAPI {\n return {\n dataAttributes: {\n 'data-slot': 'page-header',\n 'data-has-actions': props.hasActions ? 'true' : 'false',\n },\n }\n}\n", "/**\n * Root: text cluster on the leading edge, actions on the trailing edge; wraps\n * on narrow screens. Carries no outer margin — the page layout spaces it.\n */\nexport const pageHeaderClass = 'flex flex-wrap items-start justify-between gap-4'\n\n/** Text cluster (kicker, title, description). */\nexport const pageHeaderTextClass = 'flex min-w-0 flex-1 flex-col gap-1'\n\n/** Small uppercase eyebrow above the title. */\nexport const pageHeaderKickerClass =\n 'break-words text-[11px] uppercase tracking-wider text-muted-foreground'\n\n/** Title — app-sized, not a marketing display size. */\nexport const pageHeaderTitleClass = 'break-words text-xl font-semibold text-foreground'\n\n/** Supporting copy under the title, capped at a readable measure. */\nexport const pageHeaderDescriptionClass = 'max-w-prose text-sm text-muted-foreground'\n\n/** Trailing actions row. */\nexport const pageHeaderActionsClass = 'flex flex-none flex-wrap items-center gap-2'\n", "import * as React from 'react'\nimport {\n createPageHeader,\n pageHeaderClass,\n pageHeaderTextClass,\n pageHeaderKickerClass,\n pageHeaderTitleClass,\n pageHeaderDescriptionClass,\n pageHeaderActionsClass,\n type PageHeaderTitleLevel,\n} from '@refraction-ui/page-header'\nimport { cn } from '@refraction-ui/shared'\n\nexport type { PageHeaderTitleLevel }\n\nexport interface PageHeaderProps extends Omit<React.HTMLAttributes<HTMLElement>, 'title'> {\n /** Optional eyebrow rendered above the title. */\n kicker?: React.ReactNode\n /** The page title (required). */\n title: React.ReactNode\n /** Optional supporting copy under the title. */\n description?: React.ReactNode\n /** Optional actions (buttons, menus) on the trailing edge. */\n actions?: React.ReactNode\n /** Heading element for the title. Defaults to `h1`. */\n as?: PageHeaderTitleLevel\n}\n\n/**\n * PageHeader — the heading cluster at the top of an application page: kicker,\n * title, description and a trailing actions row. Renders a `<header>`.\n */\nexport const PageHeader = React.forwardRef<HTMLElement, PageHeaderProps>(function PageHeader(\n { kicker, title, description, actions, as: Title = 'h1', className, ...props },\n ref,\n) {\n const { dataAttributes } = createPageHeader({ hasActions: actions != null })\n return (\n <header ref={ref} className={cn(pageHeaderClass, className)} {...dataAttributes} {...props}>\n <div className={pageHeaderTextClass}>\n {kicker != null && <p className={pageHeaderKickerClass}>{kicker}</p>}\n <Title className={pageHeaderTitleClass}>{title}</Title>\n {description != null && <div className={pageHeaderDescriptionClass}>{description}</div>}\n </div>\n {actions != null && <div className={pageHeaderActionsClass}>{actions}</div>}\n </header>\n )\n})\n"],
4
+ "sourcesContent": ["/** Heading element used for the page title. */\nexport type PageHeaderTitleLevel = 'h1' | 'h2' | 'h3'\n\nexport interface PageHeaderProps {\n /** Whether an actions slot will be rendered. */\n hasActions?: boolean\n}\n\nexport interface PageHeaderAPI {\n /** Data attributes for styling hooks. */\n dataAttributes: Record<string, string>\n}\n\n/**\n * Build the framework-agnostic data attributes for a PageHeader — the heading\n * cluster at the top of an application page (kicker, title, description and a\n * trailing actions row). Unlike SectionHead (a centred marketing heading) it is\n * sized for dense app chrome and never centres.\n */\nexport function createPageHeader(props: PageHeaderProps = {}): PageHeaderAPI {\n return {\n dataAttributes: {\n 'data-slot': 'page-header',\n 'data-has-actions': props.hasActions ? 'true' : 'false',\n },\n }\n}\n", "/**\n * Root: text cluster on the leading edge, actions on the trailing edge; wraps\n * on narrow screens. Carries no outer margin — the page layout spaces it.\n */\nexport const pageHeaderClass = 'flex flex-wrap items-start justify-between gap-4'\n\n/** Give text a preferred width so actions wrap before squeezing the heading. */\nexport const pageHeaderTextClass = 'flex min-w-0 basis-64 grow flex-col gap-1'\n\n/** Small uppercase eyebrow above the title. */\nexport const pageHeaderKickerClass =\n 'break-words text-[11px] uppercase tracking-wider text-muted-foreground'\n\n/** Title — app-sized, not a marketing display size. */\nexport const pageHeaderTitleClass = 'break-words text-xl font-semibold text-foreground'\n\n/** Supporting copy under the title, capped at a readable measure. */\nexport const pageHeaderDescriptionClass = 'max-w-prose text-sm text-muted-foreground'\n\n/** Trailing actions row. */\nexport const pageHeaderActionsClass = 'flex flex-none flex-wrap items-center gap-2'\n", "import * as React from 'react'\nimport {\n createPageHeader,\n pageHeaderClass,\n pageHeaderTextClass,\n pageHeaderKickerClass,\n pageHeaderTitleClass,\n pageHeaderDescriptionClass,\n pageHeaderActionsClass,\n type PageHeaderTitleLevel,\n} from '@refraction-ui/page-header'\nimport { cn } from '@refraction-ui/shared'\n\nexport type { PageHeaderTitleLevel }\n\nexport interface PageHeaderProps extends Omit<React.HTMLAttributes<HTMLElement>, 'title'> {\n /** Optional eyebrow rendered above the title. */\n kicker?: React.ReactNode\n /** The page title (required). */\n title: React.ReactNode\n /** Optional supporting copy under the title. */\n description?: React.ReactNode\n /** Optional actions (buttons, menus) on the trailing edge. */\n actions?: React.ReactNode\n /** Heading element for the title. Defaults to `h1`. */\n as?: PageHeaderTitleLevel\n}\n\n/**\n * PageHeader — the heading cluster at the top of an application page: kicker,\n * title, description and a trailing actions row. Renders a `<header>`.\n */\nexport const PageHeader = React.forwardRef<HTMLElement, PageHeaderProps>(function PageHeader(\n { kicker, title, description, actions, as: Title = 'h1', className, ...props },\n ref,\n) {\n const { dataAttributes } = createPageHeader({ hasActions: actions != null })\n return (\n <header ref={ref} className={cn(pageHeaderClass, className)} {...dataAttributes} {...props}>\n <div className={pageHeaderTextClass}>\n {kicker != null && <p className={pageHeaderKickerClass}>{kicker}</p>}\n <Title className={pageHeaderTitleClass}>{title}</Title>\n {description != null && <div className={pageHeaderDescriptionClass}>{description}</div>}\n </div>\n {actions != null && <div className={pageHeaderActionsClass}>{actions}</div>}\n </header>\n )\n})\n"],
5
5
  "mappings": ";;;;;;;;AAmBO,SAAS,iBAAiB,QAAyB,CAAA,GAAmB;AAC3E,SAAO;IACL,gBAAgB;MACd,aAAa;MACb,oBAAoB,MAAM,aAAa,SAAS;IAAA;EAClD;AAEJ;ACtBO,IAAM,kBAAkB;AAGxB,IAAM,sBAAsB;AAG5B,IAAM,wBACX;AAGK,IAAM,uBAAuB;AAG7B,IAAM,6BAA6B;AAGnC,IAAM,yBAAyB;;;;ACY/B,IAAM,aAAmB,iBAAyC,SAASA,YAChF,EAAE,QAAQ,OAAO,aAAa,SAAS,IAAI,QAAQ,MAAM,WAAW,GAAG,MAAA,GACvE,KACA;AACA,QAAM,EAAE,eAAA,IAAmB,iBAAiB,EAAE,YAAY,WAAW,KAAA,CAAM;AAC3E,SACE,qBAAC,UAAA,EAAO,KAAU,WAAW,GAAG,iBAAiB,SAAS,GAAI,GAAG,gBAAiB,GAAG,OACnF,UAAA;IAAA,qBAAC,OAAA,EAAI,WAAW,qBACb,UAAA;MAAA,UAAU,QAAQ,oBAAC,KAAA,EAAE,WAAW,uBAAwB,UAAA,OAAA,CAAO;MAChE,oBAAC,OAAA,EAAM,WAAW,sBAAuB,UAAA,MAAA,CAAM;MAC9C,eAAe,QAAQ,oBAAC,OAAA,EAAI,WAAW,4BAA6B,UAAA,YAAA,CAAY;IAAA,EAAA,CACnF;IACC,WAAW,QAAQ,oBAAC,OAAA,EAAI,WAAW,wBAAyB,UAAA,QAAA,CAAQ;EAAA,EAAA,CACvE;AAEJ,CAAC;",
6
6
  "names": ["PageHeader"]
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../stat-grid/src/stat-grid.ts", "../../stat-grid/src/stat-grid.styles.ts", "../../react-stat-grid/src/stat-grid.tsx"],
4
- "sourcesContent": ["/** Semantic colour of a stat's value. */\nexport type StatTone = 'default' | 'positive' | 'negative' | 'caution'\n/** `plain` = marketing callouts; `card` = bordered dashboard KPI cards. */\nexport type StatGridVariant = 'plain' | 'card'\n/** Whether the label sits under the value (callout) or above it (KPI). */\nexport type StatGridLayout = 'value-first' | 'label-first'\n/** Column count: a fixed maximum that reflows down on narrow screens, or `auto`. */\nexport type StatGridColumns = 1 | 2 | 3 | 4 | 'auto'\n\n/** A single stat callout displayed in the grid. */\nexport type StatItem = {\n /** The primary value displayed prominently (e.g. \"10k+\", \"$4.2M\"). */\n value: string\n /** The descriptive label. */\n label: string\n /** Stable key; defaults to the index. */\n id?: string\n /** Optional line explaining the figure (how it was computed, a delta). */\n description?: string\n /** Colour of the value. Defaults to `default`. */\n tone?: StatTone\n}\n\nexport interface StatGridAPI {\n /** ARIA attributes to spread on the grid container element (`role=\"list\"`). */\n ariaProps: { role: 'list' }\n /** Data attributes for styling hooks. */\n dataAttributes: Record<string, string>\n}\n\n/**\n * Compute the number of grid columns for a stat grid.\n *\n * - 1 item → 1 column\n * - 2 items → 2 columns\n * - 3 or more items → capped at `max` (default 3)\n */\nexport function statColumns(count: number, max = 3): 1 | 2 | 3 | 4 {\n if (count <= 1) return 1\n if (count === 2) return 2\n return Math.min(count, max, 4) as 3 | 4\n}\n\n/** The cva key for a column setting (clamped to the supported 1–4). */\nexport function statColumnsKey(columns: StatGridColumns): '1' | '2' | '3' | '4' | 'auto' {\n if (columns === 'auto') return 'auto'\n return String(Math.min(Math.max(Math.round(columns), 1), 4)) as '1' | '2' | '3' | '4'\n}\n\n/**\n * Build the framework-agnostic container props for a stat grid.\n *\n * Returns `role=\"list\"` and data attributes; adapters spread these onto their\n * container element and render the items themselves.\n */\nexport function createStatGrid(): StatGridAPI {\n return {\n ariaProps: { role: 'list' },\n dataAttributes: {},\n }\n}\n", "import { cva } from '@refraction-ui/shared'\n\n/**\n * Grid container. Column counts are responsive (one column on a phone, more\n * as the width allows) — never a fixed inline template that cannot reflow.\n * `auto` fits as many ~12rem items per row as the width allows.\n */\nexport const statGridVariants = cva({\n base: 'grid',\n variants: {\n columns: {\n '1': 'grid-cols-1',\n '2': 'grid-cols-1 sm:grid-cols-2',\n '3': 'grid-cols-1 sm:grid-cols-2 lg:grid-cols-3',\n '4': 'grid-cols-1 sm:grid-cols-2 lg:grid-cols-4',\n auto: 'grid-cols-[repeat(auto-fill,minmax(12rem,1fr))]',\n },\n variant: {\n plain: 'gap-8',\n card: 'gap-3',\n },\n },\n defaultVariants: {\n columns: '3',\n variant: 'plain',\n },\n})\n\n/** Individual stat item container (role=\"listitem\"). */\nexport const statItemVariants = cva({\n base: 'flex min-w-0 flex-col',\n variants: {\n variant: {\n plain: '',\n card: 'gap-1 rounded-lg border border-border bg-card p-4 text-card-foreground',\n },\n },\n defaultVariants: {\n variant: 'plain',\n },\n})\n\n/** @deprecated Use `statItemVariants()`; kept for existing imports. */\nexport const statItemClass = 'flex flex-col'\n\n/** The value of a stat, by variant and tone. */\nexport const statValueVariants = cva({\n base: 'font-bold tabular-nums',\n variants: {\n variant: {\n plain: 'text-xl sm:text-2xl',\n card: 'text-2xl leading-tight',\n },\n tone: {\n default: '',\n positive: 'text-success',\n negative: 'text-destructive',\n caution: 'text-warning',\n },\n },\n compoundVariants: [\n { variant: 'plain', tone: 'default', class: 'text-primary' },\n { variant: 'card', tone: 'default', class: 'text-foreground' },\n ],\n defaultVariants: {\n variant: 'plain',\n tone: 'default',\n },\n})\n\n/** @deprecated Use `statValueVariants()`; kept for existing imports. */\nexport const statValueClass = 'text-xl sm:text-2xl font-bold text-primary'\n\n/** The descriptive label. Above the value it reads as a small caption. */\nexport const statLabelVariants = cva({\n base: 'text-muted-foreground',\n variants: {\n layout: {\n 'value-first': 'mt-1 text-sm leading-snug',\n 'label-first': 'text-xs uppercase tracking-wide',\n },\n },\n defaultVariants: {\n layout: 'value-first',\n },\n})\n\n/** @deprecated Use `statLabelVariants()`; kept for existing imports. */\nexport const statLabelClass = 'mt-1 text-sm text-muted-foreground leading-snug'\n\n/** Optional line under a stat explaining how it was computed. */\nexport const statDescriptionClass = 'text-xs leading-snug text-muted-foreground'\n", "import * as React from 'react'\nimport {\n createStatGrid,\n statColumns,\n statColumnsKey,\n statGridVariants,\n statItemVariants,\n statValueVariants,\n statLabelVariants,\n statDescriptionClass,\n type StatTone,\n type StatGridVariant,\n type StatGridLayout,\n type StatGridColumns,\n} from '@refraction-ui/stat-grid'\nimport { cn } from '@refraction-ui/shared'\n\nexport type { StatItem, StatTone, StatGridVariant, StatGridLayout, StatGridColumns } from '@refraction-ui/stat-grid'\n\nexport interface StatGridItem {\n /** The primary value displayed prominently. Allows rich content in React. */\n value: React.ReactNode\n /** The descriptive label. */\n label: React.ReactNode\n /** Stable key; defaults to the index. */\n id?: string\n /** Optional line explaining the figure (how it was computed, a delta). */\n description?: React.ReactNode\n /** Colour of the value. Defaults to `default`. */\n tone?: StatTone\n /** Extra attributes for this item's element (`data-*`, `aria-*`, `title`, className). */\n props?: React.HTMLAttributes<HTMLDivElement>\n}\n\nexport interface StatGridProps\n extends Omit<React.HTMLAttributes<HTMLDivElement>, 'content'> {\n /** The stat items to display in the grid. */\n items: StatGridItem[]\n /**\n * Maximum columns (reflows to fewer on narrow screens), or `auto` to fit as\n * many ~12rem items as the width allows. Defaults to\n * `statColumns(items.length)`: 1 → 1, 2 → 2, 3+ → 3.\n */\n columns?: StatGridColumns\n /** `plain` marketing callouts (default) or bordered `card` KPIs. */\n variant?: StatGridVariant\n /** `value-first` (default) or `label-first` (dashboard KPI order). */\n layout?: StatGridLayout\n}\n\n/**\n * StatGrid — a responsive grid of stats: marketing callouts (`plain`) or\n * dashboard KPI cards (`card`), value- or label-first, with an optional\n * description and a tone per item. Uses `role=\"list\"` / `role=\"listitem\"`.\n */\nexport const StatGrid = React.forwardRef<HTMLDivElement, StatGridProps>(\n function StatGrid(\n { items, columns, variant = 'plain', layout = 'value-first', className, ...props },\n ref,\n ) {\n const cols = statColumnsKey(columns ?? statColumns(items.length))\n const { ariaProps, dataAttributes } = createStatGrid()\n\n return (\n <div\n ref={ref}\n className={cn(statGridVariants({ columns: cols, variant }), className)}\n data-variant={variant}\n data-layout={layout}\n {...ariaProps}\n {...dataAttributes}\n {...props}\n >\n {items.map((item, index) => {\n const { className: itemClassName, ...itemProps } = item.props ?? {}\n const label = <span className={statLabelVariants({ layout })}>{item.label}</span>\n return (\n <div\n key={item.id ?? index}\n role=\"listitem\"\n className={cn(statItemVariants({ variant }), itemClassName)}\n data-tone={item.tone ?? 'default'}\n {...itemProps}\n >\n {layout === 'label-first' && label}\n <span className={statValueVariants({ variant, tone: item.tone ?? 'default' })}>{item.value}</span>\n {layout === 'value-first' && label}\n {item.description != null && <span className={statDescriptionClass}>{item.description}</span>}\n </div>\n )\n })}\n </div>\n )\n },\n)\n"],
4
+ "sourcesContent": ["/** Semantic colour of a stat's value. */\nexport type StatTone = 'default' | 'positive' | 'negative' | 'caution'\n/** `plain` = marketing callouts; `card` = bordered dashboard KPI cards. */\nexport type StatGridVariant = 'plain' | 'card'\n/** Whether the label sits under the value (callout) or above it (KPI). */\nexport type StatGridLayout = 'value-first' | 'label-first'\n/** Column count: a fixed maximum that reflows down on narrow screens, or `auto`. */\nexport type StatGridColumns = 1 | 2 | 3 | 4 | 'auto'\n\n/** A single stat callout displayed in the grid. */\nexport type StatItem = {\n /** The primary value displayed prominently (e.g. \"10k+\", \"$4.2M\"). */\n value: string\n /** The descriptive label. */\n label: string\n /** Stable key; defaults to the index. */\n id?: string\n /** Optional line explaining the figure (how it was computed, a delta). */\n description?: string\n /** Colour of the value. Defaults to `default`. */\n tone?: StatTone\n}\n\nexport interface StatGridAPI {\n /** ARIA attributes to spread on the grid container element (`role=\"list\"`). */\n ariaProps: { role: 'list' }\n /** Data attributes for styling hooks. */\n dataAttributes: Record<string, string>\n}\n\n/**\n * Compute the number of grid columns for a stat grid.\n *\n * - 1 item → 1 column\n * - 2 items → 2 columns\n * - 3 or more items → capped at `max` (default 3)\n */\nexport function statColumns(count: number, max = 3): 1 | 2 | 3 | 4 {\n if (count <= 1) return 1\n if (count === 2) return 2\n return Math.min(count, max, 4) as 3 | 4\n}\n\n/** The cva key for a column setting (clamped to the supported 1–4). */\nexport function statColumnsKey(columns: StatGridColumns): '1' | '2' | '3' | '4' | 'auto' {\n if (columns === 'auto') return 'auto'\n return String(Math.min(Math.max(Math.round(columns), 1), 4)) as '1' | '2' | '3' | '4'\n}\n\n/**\n * Build the framework-agnostic container props for a stat grid.\n *\n * Returns `role=\"list\"` and data attributes; adapters spread these onto their\n * container element and render the items themselves.\n */\nexport function createStatGrid(): StatGridAPI {\n return {\n ariaProps: { role: 'list' },\n dataAttributes: {},\n }\n}\n", "import { cva } from '@refraction-ui/shared'\n\n/**\n * Grid container. Column counts are responsive (one column on a phone, more\n * as the width allows) — never a fixed inline template that cannot reflow.\n * `auto` fits as many ~12rem items per row as the width allows.\n */\nexport const statGridVariants = cva({\n base: 'grid',\n variants: {\n columns: {\n '1': 'grid-cols-1',\n '2': 'grid-cols-1 sm:grid-cols-2',\n '3': 'grid-cols-1 sm:grid-cols-2 lg:grid-cols-3',\n '4': 'grid-cols-1 sm:grid-cols-2 lg:grid-cols-4',\n auto: 'grid-cols-[repeat(auto-fill,minmax(12rem,1fr))]',\n },\n variant: {\n plain: 'gap-8',\n card: 'gap-3',\n },\n },\n defaultVariants: {\n columns: '3',\n variant: 'plain',\n },\n})\n\n/** Individual stat item container (role=\"listitem\"). */\nexport const statItemVariants = cva({\n base: 'flex min-w-0 flex-col',\n variants: {\n variant: {\n plain: '',\n card: 'gap-1 rounded-lg border border-border bg-card p-4 text-card-foreground',\n },\n },\n defaultVariants: {\n variant: 'plain',\n },\n})\n\n/** @deprecated Use `statItemVariants()`; kept for existing imports. */\nexport const statItemClass = 'flex flex-col'\n\n/** The value of a stat, by variant and tone. */\nexport const statValueVariants = cva({\n base: 'font-bold tabular-nums',\n variants: {\n variant: {\n plain: 'text-xl sm:text-2xl',\n card: 'text-2xl leading-tight',\n },\n tone: {\n default: '',\n positive: 'text-success',\n negative: 'text-destructive',\n caution: 'text-warning',\n },\n },\n compoundVariants: [\n { variant: 'plain', tone: 'default', class: 'text-primary' },\n { variant: 'card', tone: 'default', class: 'text-foreground' },\n ],\n defaultVariants: {\n variant: 'plain',\n tone: 'default',\n },\n})\n\n/** @deprecated Use `statValueVariants()`; kept for existing imports. */\nexport const statValueClass = 'text-xl sm:text-2xl font-bold text-primary'\n\n/** The descriptive label. Above the value it reads as a small caption. */\nexport const statLabelVariants = cva({\n base: 'text-muted-foreground',\n variants: {\n layout: {\n 'value-first': 'mt-1 text-sm leading-snug',\n 'label-first': 'text-xs uppercase tracking-wide',\n },\n },\n defaultVariants: {\n layout: 'value-first',\n },\n})\n\n/** @deprecated Use `statLabelVariants()`; kept for existing imports. */\nexport const statLabelClass = 'mt-1 text-sm text-muted-foreground leading-snug'\n\n/** Optional line under a stat explaining how it was computed. */\nexport const statDescriptionClass = 'text-xs leading-snug text-muted-foreground'\n", "import * as React from 'react'\nimport {\n createStatGrid,\n statColumns,\n statColumnsKey,\n statGridVariants,\n statItemVariants,\n statValueVariants,\n statLabelVariants,\n statDescriptionClass,\n type StatTone,\n type StatGridVariant,\n type StatGridLayout,\n type StatGridColumns,\n} from '@refraction-ui/stat-grid'\nimport { cn, type DataAttributes } from '@refraction-ui/shared'\n\nexport type { StatItem, StatTone, StatGridVariant, StatGridLayout, StatGridColumns } from '@refraction-ui/stat-grid'\n\nexport interface StatGridItem {\n /** The primary value displayed prominently. Allows rich content in React. */\n value: React.ReactNode\n /** The descriptive label. */\n label: React.ReactNode\n /** Stable key; defaults to the index. */\n id?: string\n /** Optional line explaining the figure (how it was computed, a delta). */\n description?: React.ReactNode\n /** Colour of the value. Defaults to `default`. */\n tone?: StatTone\n /** Extra attributes for this item's element (`data-*`, `aria-*`, `title`, className). */\n props?: React.HTMLAttributes<HTMLDivElement> & DataAttributes\n}\n\nexport interface StatGridProps\n extends Omit<React.HTMLAttributes<HTMLDivElement>, 'content'> {\n /** The stat items to display in the grid. */\n items: StatGridItem[]\n /**\n * Maximum columns (reflows to fewer on narrow screens), or `auto` to fit as\n * many ~12rem items as the width allows. Defaults to\n * `statColumns(items.length)`: 1 → 1, 2 → 2, 3+ → 3.\n */\n columns?: StatGridColumns\n /** `plain` marketing callouts (default) or bordered `card` KPIs. */\n variant?: StatGridVariant\n /** `value-first` (default) or `label-first` (dashboard KPI order). */\n layout?: StatGridLayout\n}\n\n/**\n * StatGrid — a responsive grid of stats: marketing callouts (`plain`) or\n * dashboard KPI cards (`card`), value- or label-first, with an optional\n * description and a tone per item. Uses `role=\"list\"` / `role=\"listitem\"`.\n */\nexport const StatGrid = React.forwardRef<HTMLDivElement, StatGridProps>(\n function StatGrid(\n { items, columns, variant = 'plain', layout = 'value-first', className, ...props },\n ref,\n ) {\n const cols = statColumnsKey(columns ?? statColumns(items.length))\n const { ariaProps, dataAttributes } = createStatGrid()\n\n return (\n <div\n ref={ref}\n className={cn(statGridVariants({ columns: cols, variant }), className)}\n data-variant={variant}\n data-layout={layout}\n {...ariaProps}\n {...dataAttributes}\n {...props}\n >\n {items.map((item, index) => {\n const { className: itemClassName, ...itemProps } = item.props ?? {}\n const label = <span className={statLabelVariants({ layout })}>{item.label}</span>\n return (\n <div\n key={item.id ?? index}\n role=\"listitem\"\n className={cn(statItemVariants({ variant }), itemClassName)}\n data-tone={item.tone ?? 'default'}\n {...itemProps}\n >\n {layout === 'label-first' && label}\n <span className={statValueVariants({ variant, tone: item.tone ?? 'default' })}>{item.value}</span>\n {layout === 'value-first' && label}\n {item.description != null && <span className={statDescriptionClass}>{item.description}</span>}\n </div>\n )\n })}\n </div>\n )\n },\n)\n"],
5
5
  "mappings": ";;;;;;;;;AAqCO,SAAS,YAAY,OAAe,MAAM,GAAkB;AACjE,MAAI,SAAS,EAAG,QAAO;AACvB,MAAI,UAAU,EAAG,QAAO;AACxB,SAAO,KAAK,IAAI,OAAO,KAAK,CAAC;AAC/B;AAGO,SAAS,eAAe,SAA0D;AACvF,MAAI,YAAY,OAAQ,QAAO;AAC/B,SAAO,OAAO,KAAK,IAAI,KAAK,IAAI,KAAK,MAAM,OAAO,GAAG,CAAC,GAAG,CAAC,CAAC;AAC7D;AAQO,SAAS,iBAA8B;AAC5C,SAAO;IACL,WAAW,EAAE,MAAM,OAAA;IACnB,gBAAgB,CAAA;EAAC;AAErB;ACrDO,IAAM,mBAAmB,IAAI;EAClC,MAAM;EACN,UAAU;IACR,SAAS;MACP,KAAK;MACL,KAAK;MACL,KAAK;MACL,KAAK;MACL,MAAM;IAAA;IAER,SAAS;MACP,OAAO;MACP,MAAM;IAAA;EACR;EAEF,iBAAiB;IACf,SAAS;IACT,SAAS;EAAA;AAEb,CAAC;AAGM,IAAM,mBAAmB,IAAI;EAClC,MAAM;EACN,UAAU;IACR,SAAS;MACP,OAAO;MACP,MAAM;IAAA;EACR;EAEF,iBAAiB;IACf,SAAS;EAAA;AAEb,CAAC;AAMM,IAAM,oBAAoB,IAAI;EACnC,MAAM;EACN,UAAU;IACR,SAAS;MACP,OAAO;MACP,MAAM;IAAA;IAER,MAAM;MACJ,SAAS;MACT,UAAU;MACV,UAAU;MACV,SAAS;IAAA;EACX;EAEF,kBAAkB;IAChB,EAAE,SAAS,SAAS,MAAM,WAAW,OAAO,eAAA;IAC5C,EAAE,SAAS,QAAQ,MAAM,WAAW,OAAO,kBAAA;EAAkB;EAE/D,iBAAiB;IACf,SAAS;IACT,MAAM;EAAA;AAEV,CAAC;AAMM,IAAM,oBAAoB,IAAI;EACnC,MAAM;EACN,UAAU;IACR,QAAQ;MACN,eAAe;MACf,eAAe;IAAA;EACjB;EAEF,iBAAiB;IACf,QAAQ;EAAA;AAEZ,CAAC;AAMM,IAAM,uBAAuB;;;;ACpC7B,IAAM,WAAiB;EAC5B,SAASA,UACP,EAAE,OAAO,SAAS,UAAU,SAAS,SAAS,eAAe,WAAW,GAAG,MAAA,GAC3E,KACA;AACA,UAAM,OAAO,eAAe,WAAW,YAAY,MAAM,MAAM,CAAC;AAChE,UAAM,EAAE,WAAW,eAAA,IAAmB,eAAA;AAEtC,WACE;MAAC;MAAA;QACC;QACA,WAAW,GAAG,iBAAiB,EAAE,SAAS,MAAM,QAAA,CAAS,GAAG,SAAS;QACrE,gBAAc;QACd,eAAa;QACZ,GAAG;QACH,GAAG;QACH,GAAG;QAEH,UAAA,MAAM,IAAI,CAAC,MAAM,UAAU;AAC1B,gBAAM,EAAE,WAAW,eAAe,GAAG,UAAA,IAAc,KAAK,SAAS,CAAA;AACjE,gBAAM,QAAQ,oBAAC,QAAA,EAAK,WAAW,kBAAkB,EAAE,OAAA,CAAQ,GAAI,UAAA,KAAK,MAAA,CAAM;AAC1E,iBACE;YAAC;YAAA;cAEC,MAAK;cACL,WAAW,GAAG,iBAAiB,EAAE,QAAA,CAAS,GAAG,aAAa;cAC1D,aAAW,KAAK,QAAQ;cACvB,GAAG;cAEH,UAAA;gBAAA,WAAW,iBAAiB;gBAC7B,oBAAC,QAAA,EAAK,WAAW,kBAAkB,EAAE,SAAS,MAAM,KAAK,QAAQ,UAAA,CAAW,GAAI,UAAA,KAAK,MAAA,CAAM;gBAC1F,WAAW,iBAAiB;gBAC5B,KAAK,eAAe,QAAQ,oBAAC,QAAA,EAAK,WAAW,sBAAuB,UAAA,KAAK,YAAA,CAAY;cAAA;YAAA;YATjF,KAAK,MAAM;UAAA;QAYtB,CAAC;MAAA;IAAA;EAGP;AACF;",
6
6
  "names": ["StatGrid"]
7
7
  }
@@ -1,101 +1,13 @@
1
1
  import {
2
- Keys,
3
2
  cn,
4
3
  cva,
5
- devWarn,
6
- generateId
4
+ devWarn
7
5
  } from "./chunk-75BKRTPO.js";
8
6
 
9
7
  // ../react-tabs/dist/index.js
10
8
  import * as React from "react";
11
9
 
12
10
  // ../tabs/dist/index.js
13
- function createTabs(props = {}) {
14
- const {
15
- value: controlledValue,
16
- defaultValue = "",
17
- onValueChange,
18
- orientation = "horizontal"
19
- } = props;
20
- let uncontrolledValue = controlledValue ?? defaultValue;
21
- const idPrefix = generateId("rfr-tabs");
22
- function getActiveValue() {
23
- if (controlledValue !== void 0) return controlledValue;
24
- return uncontrolledValue;
25
- }
26
- function select(value) {
27
- uncontrolledValue = value;
28
- onValueChange?.(value);
29
- }
30
- function getTabId(value) {
31
- return `${idPrefix}-tab-${value}`;
32
- }
33
- function getPanelId(value) {
34
- return `${idPrefix}-panel-${value}`;
35
- }
36
- function getTabProps(value) {
37
- const isSelected = getActiveValue() === value;
38
- return {
39
- role: "tab",
40
- "aria-selected": isSelected,
41
- "aria-controls": getPanelId(value),
42
- tabIndex: isSelected ? 0 : -1,
43
- id: getTabId(value),
44
- "data-state": isSelected ? "active" : "inactive"
45
- };
46
- }
47
- function getPanelProps(value) {
48
- const isSelected = getActiveValue() === value;
49
- return {
50
- role: "tabpanel",
51
- "aria-labelledby": getTabId(value),
52
- id: getPanelId(value),
53
- hidden: !isSelected || void 0,
54
- tabIndex: 0,
55
- "data-state": isSelected ? "active" : "inactive"
56
- };
57
- }
58
- const listProps = {
59
- role: "tablist",
60
- "aria-orientation": orientation
61
- };
62
- const keyboardHandlers = orientation === "horizontal" ? {
63
- [Keys.ArrowLeft]: (e) => {
64
- e.preventDefault();
65
- },
66
- [Keys.ArrowRight]: (e) => {
67
- e.preventDefault();
68
- },
69
- [Keys.Home]: (e) => {
70
- e.preventDefault();
71
- },
72
- [Keys.End]: (e) => {
73
- e.preventDefault();
74
- }
75
- } : {
76
- [Keys.ArrowUp]: (e) => {
77
- e.preventDefault();
78
- },
79
- [Keys.ArrowDown]: (e) => {
80
- e.preventDefault();
81
- },
82
- [Keys.Home]: (e) => {
83
- e.preventDefault();
84
- },
85
- [Keys.End]: (e) => {
86
- e.preventDefault();
87
- }
88
- };
89
- return {
90
- state: { activeValue: getActiveValue() },
91
- listProps,
92
- getTabProps,
93
- getPanelProps,
94
- select,
95
- keyboardHandlers,
96
- idPrefix
97
- };
98
- }
99
11
  function getNextTabIndex(current, key, count, orientation = "horizontal") {
100
12
  if (count === 0) return null;
101
13
  const prev = orientation === "horizontal" ? "ArrowLeft" : "ArrowUp";
@@ -147,11 +59,7 @@ var Tabs = React.forwardRef(
147
59
  },
148
60
  [isControlled, onValueChange]
149
61
  );
150
- const apiRef = React.useRef(null);
151
- if (apiRef.current === null) {
152
- apiRef.current = createTabs({ value, orientation });
153
- }
154
- const api = apiRef.current;
62
+ const idPrefix = `rfr-tabs-${React.useId()}`;
155
63
  const [panels, setPanels] = React.useState(() => /* @__PURE__ */ new Set());
156
64
  const registerPanel = React.useCallback((panelValue) => {
157
65
  setPanels((prev) => prev.has(panelValue) ? prev : new Set(prev).add(panelValue));
@@ -172,11 +80,11 @@ var Tabs = React.forwardRef(
172
80
  value,
173
81
  onValueChange: handleValueChange,
174
82
  orientation,
175
- idPrefix: api.idPrefix,
83
+ idPrefix,
176
84
  panels: allPanels,
177
85
  registerPanel
178
86
  }),
179
- [value, handleValueChange, orientation, api.idPrefix, allPanels, registerPanel]
87
+ [value, handleValueChange, orientation, idPrefix, allPanels, registerPanel]
180
88
  );
181
89
  return React.createElement(
182
90
  "div",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../tabs/src/tabs.ts", "../../tabs/src/tabs.styles.ts", "../../react-tabs/src/tabs.tsx"],
4
- "sourcesContent": ["import type { AccessibilityProps, KeyboardHandlerMap } from '@refraction-ui/shared'\nimport { Keys, generateId } from '@refraction-ui/shared'\n\nexport interface TabsProps {\n /** The active tab value (controlled) */\n value?: string\n /** The default active tab value (uncontrolled) */\n defaultValue?: string\n /** Callback when active tab changes */\n onValueChange?: (value: string) => void\n /** Orientation of the tab list */\n orientation?: 'horizontal' | 'vertical'\n}\n\nexport interface TabsState {\n activeValue: string\n}\n\nexport interface TabsAPI {\n /** Current tabs state */\n state: TabsState\n /** ARIA attributes for the tab list */\n listProps: Partial<AccessibilityProps> & Record<string, unknown>\n /** Factory for individual tab trigger props */\n getTabProps(value: string): Partial<AccessibilityProps> & Record<string, unknown>\n /** Factory for individual tab panel props */\n getPanelProps(value: string): Partial<AccessibilityProps> & Record<string, unknown>\n /** Select a tab by value */\n select(value: string): void\n /** Keyboard handlers for the tab list */\n keyboardHandlers: KeyboardHandlerMap\n /** Generated ID prefix for aria linking */\n idPrefix: string\n}\n\nexport function createTabs(props: TabsProps = {}): TabsAPI {\n const {\n value: controlledValue,\n defaultValue = '',\n onValueChange,\n orientation = 'horizontal',\n } = props\n\n let uncontrolledValue = controlledValue ?? defaultValue\n const idPrefix = generateId('rfr-tabs')\n\n function getActiveValue(): string {\n if (controlledValue !== undefined) return controlledValue\n return uncontrolledValue\n }\n\n function select(value: string): void {\n uncontrolledValue = value\n onValueChange?.(value)\n }\n\n function getTabId(value: string): string {\n return `${idPrefix}-tab-${value}`\n }\n\n function getPanelId(value: string): string {\n return `${idPrefix}-panel-${value}`\n }\n\n function getTabProps(value: string): Partial<AccessibilityProps> & Record<string, unknown> {\n const isSelected = getActiveValue() === value\n return {\n role: 'tab',\n 'aria-selected': isSelected,\n 'aria-controls': getPanelId(value),\n tabIndex: isSelected ? 0 : -1,\n id: getTabId(value),\n 'data-state': isSelected ? 'active' : 'inactive',\n }\n }\n\n function getPanelProps(value: string): Partial<AccessibilityProps> & Record<string, unknown> {\n const isSelected = getActiveValue() === value\n return {\n role: 'tabpanel',\n 'aria-labelledby': getTabId(value),\n id: getPanelId(value),\n hidden: !isSelected || undefined,\n tabIndex: 0,\n 'data-state': isSelected ? 'active' : 'inactive',\n }\n }\n\n const listProps: Partial<AccessibilityProps> & Record<string, unknown> = {\n role: 'tablist',\n 'aria-orientation': orientation,\n }\n\n const keyboardHandlers: KeyboardHandlerMap = orientation === 'horizontal'\n ? {\n [Keys.ArrowLeft]: (e) => {\n e.preventDefault()\n },\n [Keys.ArrowRight]: (e) => {\n e.preventDefault()\n },\n [Keys.Home]: (e) => {\n e.preventDefault()\n },\n [Keys.End]: (e) => {\n e.preventDefault()\n },\n }\n : {\n [Keys.ArrowUp]: (e) => {\n e.preventDefault()\n },\n [Keys.ArrowDown]: (e) => {\n e.preventDefault()\n },\n [Keys.Home]: (e) => {\n e.preventDefault()\n },\n [Keys.End]: (e) => {\n e.preventDefault()\n },\n }\n\n return {\n state: { activeValue: getActiveValue() },\n listProps,\n getTabProps,\n getPanelProps,\n select,\n keyboardHandlers,\n idPrefix,\n }\n}\n\n/**\n * Roving-focus target for a key press inside a tab list (WAI-ARIA Tabs\n * pattern). Given the index of the focused tab among the ENABLED tabs, returns\n * the index to move to, or `null` when the key is not a navigation key for this\n * orientation. Arrow keys wrap; Home/End jump to the ends.\n */\nexport function getNextTabIndex(\n current: number,\n key: string,\n count: number,\n orientation: 'horizontal' | 'vertical' = 'horizontal',\n): number | null {\n if (count === 0) return null\n const prev = orientation === 'horizontal' ? 'ArrowLeft' : 'ArrowUp'\n const next = orientation === 'horizontal' ? 'ArrowRight' : 'ArrowDown'\n switch (key) {\n case next:\n return current < 0 ? 0 : (current + 1) % count\n case prev:\n return current < 0 ? count - 1 : (current - 1 + count) % count\n case 'Home':\n return 0\n case 'End':\n return count - 1\n default:\n return null\n }\n}\n", "import { cva } from '@refraction-ui/shared'\n\nexport const tabsListVariants = cva({\n base: 'inline-flex max-w-full overflow-x-auto items-center justify-center rounded-lg bg-muted p-1 text-muted-foreground',\n})\n\nexport const tabsTriggerVariants = cva({\n base: 'inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-1 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow',\n})\n", "import * as React from 'react'\nimport {\n createTabs,\n getNextTabIndex,\n tabsListVariants,\n tabsTriggerVariants,\n type TabsProps as CoreTabsProps,\n} from '@refraction-ui/tabs'\nimport { cn, createKeyboardHandler, Keys, devWarn } from '@refraction-ui/shared'\n\n// ---------------------------------------------------------------------------\n// Context\n// ---------------------------------------------------------------------------\n\ninterface TabsContextValue {\n value: string\n onValueChange: (value: string) => void\n orientation: 'horizontal' | 'vertical'\n idPrefix: string\n /** Values that have a TabsContent, so triggers only reference real panels. */\n panels: ReadonlySet<string>\n registerPanel: (value: string) => () => void\n}\n\nconst TabsContext = React.createContext<TabsContextValue | null>(null)\n\nfunction useTabsContext(): TabsContextValue {\n const ctx = React.useContext(TabsContext)\n if (!ctx) {\n devWarn(\n 'react-tabs/context-outside-provider',\n 'Tabs compound components (TabsList/TabsTrigger/TabsContent) must be rendered inside a <Tabs>. The missing TabsContext makes this throw.',\n )\n throw new Error('Tabs compound components must be used within <Tabs>')\n }\n return ctx\n}\n\n// ---------------------------------------------------------------------------\n// Tabs (root provider)\n// ---------------------------------------------------------------------------\n\nexport interface TabsProps extends React.HTMLAttributes<HTMLDivElement> {\n value?: string\n defaultValue?: string\n onValueChange?: (value: string) => void\n orientation?: 'horizontal' | 'vertical'\n className?: string\n children?: React.ReactNode\n}\n\nexport const Tabs = React.forwardRef<HTMLDivElement, TabsProps>(\n function Tabs({ value: controlledValue, defaultValue = '', onValueChange, orientation = 'horizontal', className, children, ...props }: TabsProps, ref) {\n const [uncontrolledValue, setUncontrolledValue] = React.useState(defaultValue)\n const isControlled = controlledValue !== undefined\n const value = isControlled ? controlledValue : uncontrolledValue\n\n const handleValueChange = React.useCallback(\n (next: string) => {\n if (!isControlled) {\n setUncontrolledValue(next)\n }\n onValueChange?.(next)\n },\n [isControlled, onValueChange],\n )\n\n // Use the headless core to get stable IDs\n const apiRef = React.useRef<ReturnType<typeof createTabs> | null>(null)\n if (apiRef.current === null) {\n apiRef.current = createTabs({ value, orientation })\n }\n const api = apiRef.current\n\n const [panels, setPanels] = React.useState<ReadonlySet<string>>(() => new Set())\n const registerPanel = React.useCallback((panelValue: string) => {\n setPanels((prev) => (prev.has(panelValue) ? prev : new Set(prev).add(panelValue)))\n return () =>\n setPanels((prev) => {\n if (!prev.has(panelValue)) return prev\n const next = new Set(prev)\n next.delete(panelValue)\n return next\n })\n }, [])\n\n // Panels found in the element tree cover the first/server render; mounted\n // panels (possibly nested in custom components) register themselves.\n const allPanels = React.useMemo(() => {\n const found = new Set(panels)\n collectPanelValues(children, found)\n return found\n }, [children, panels])\n\n const ctx = React.useMemo<TabsContextValue>(\n () => ({\n value,\n onValueChange: handleValueChange,\n orientation,\n idPrefix: api.idPrefix,\n panels: allPanels,\n registerPanel,\n }),\n [value, handleValueChange, orientation, api.idPrefix, allPanels, registerPanel],\n )\n\n return React.createElement(\n 'div',\n { ref, className, 'data-orientation': orientation, ...props },\n React.createElement(TabsContext.Provider, { value: ctx }, children),\n )\n },\n)\n\nfunction collectPanelValues(node: React.ReactNode, into: Set<string>): void {\n React.Children.forEach(node, (child) => {\n if (!React.isValidElement<{ value?: unknown; children?: React.ReactNode }>(child)) return\n if (child.type === TabsContent && typeof child.props.value === 'string') {\n into.add(child.props.value)\n return\n }\n collectPanelValues(child.props.children, into)\n })\n}\n\n// ---------------------------------------------------------------------------\n// TabsList\n// ---------------------------------------------------------------------------\n\nexport interface TabsListProps extends React.HTMLAttributes<HTMLDivElement> {}\n\nexport const TabsList = React.forwardRef<HTMLDivElement, TabsListProps>(\n function TabsList({ className, onKeyDown, ...props }, forwardedRef) {\n const { orientation } = useTabsContext()\n const listRef = React.useRef<HTMLDivElement | null>(null)\n const ref = React.useCallback(\n (node: HTMLDivElement | null) => {\n listRef.current = node\n if (typeof forwardedRef === 'function') forwardedRef(node)\n else if (forwardedRef) forwardedRef.current = node\n },\n [forwardedRef],\n )\n\n // Roving tabindex needs exactly one tab stop. A trigger only knows whether\n // IT is selected, so when no enabled trigger matches the value (no\n // defaultValue, or the selected tab is disabled) nothing would be\n // tabbable; make the first enabled tab the stop in that case.\n // This effect owns the final tabindex of every trigger (React leaves a\n // DOM value alone while its prop is unchanged, so patching only the\n // fallback would leave two tab stops after the next selection).\n React.useEffect(() => {\n const tabs = enabledTabs(listRef.current)\n const stop = tabs.find((tab) => tab.getAttribute('aria-selected') === 'true') ?? tabs[0]\n for (const tab of tabs) tab.tabIndex = tab === stop ? 0 : -1\n })\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {\n onKeyDown?.(e)\n if (e.defaultPrevented) return\n const tabs = enabledTabs(listRef.current)\n const current = tabs.indexOf(e.target as HTMLButtonElement)\n if (current === -1) return\n const next = getNextTabIndex(current, e.key, tabs.length, orientation)\n if (next === null) return\n e.preventDefault()\n tabs[next].focus()\n // Automatic activation: moving focus selects the tab.\n tabs[next].click()\n }\n\n return React.createElement('div', {\n ref,\n role: 'tablist',\n 'aria-orientation': orientation,\n className: cn(tabsListVariants(), className),\n onKeyDown: handleKeyDown,\n ...props,\n })\n },\n)\n\nfunction enabledTabs(list: HTMLElement | null): HTMLButtonElement[] {\n if (!list) return []\n return Array.from(list.querySelectorAll<HTMLButtonElement>('[role=\"tab\"]:not([disabled])'))\n}\n\n// ---------------------------------------------------------------------------\n// TabsTrigger\n// ---------------------------------------------------------------------------\n\nexport interface TabsTriggerProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n value: string\n}\n\nexport const TabsTrigger = React.forwardRef<HTMLButtonElement, TabsTriggerProps>(\n function TabsTrigger({ value, className, onClick, onKeyDown, children, ...props }, ref) {\n const { value: activeValue, onValueChange, idPrefix, panels } = useTabsContext()\n\n const isSelected = activeValue === value\n const tabId = `${idPrefix}-tab-${value}`\n const panelId = `${idPrefix}-panel-${value}`\n\n const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {\n onValueChange(value)\n onClick?.(e)\n }\n\n // Arrow / Home / End navigation is handled by TabsList (roving focus);\n // a consumer onKeyDown runs first and can preventDefault to opt out.\n const handleKeyDown = (e: React.KeyboardEvent<HTMLButtonElement>) => {\n onKeyDown?.(e)\n }\n\n return React.createElement(\n 'button',\n {\n ref,\n type: 'button',\n role: 'tab',\n 'aria-selected': isSelected,\n // Only the selected panel is rendered; never reference a missing element.\n 'aria-controls': isSelected && panels.has(value) ? panelId : undefined,\n tabIndex: isSelected ? 0 : -1,\n id: tabId,\n 'data-state': isSelected ? 'active' : 'inactive',\n className: cn(tabsTriggerVariants(), className),\n onClick: handleClick,\n onKeyDown: handleKeyDown,\n ...props,\n },\n children,\n )\n },\n)\n\n// ---------------------------------------------------------------------------\n// TabsContent\n// ---------------------------------------------------------------------------\n\nexport interface TabsContentProps extends React.HTMLAttributes<HTMLDivElement> {\n value: string\n}\n\nexport const TabsContent = React.forwardRef<HTMLDivElement, TabsContentProps>(\n function TabsContent({ value, className, children, ...props }, ref) {\n const { value: activeValue, idPrefix, registerPanel } = useTabsContext()\n React.useEffect(() => registerPanel(value), [registerPanel, value])\n\n const isSelected = activeValue === value\n const tabId = `${idPrefix}-tab-${value}`\n const panelId = `${idPrefix}-panel-${value}`\n\n if (!isSelected) return null\n\n return React.createElement(\n 'div',\n {\n ref,\n role: 'tabpanel',\n 'aria-labelledby': tabId,\n id: panelId,\n tabIndex: 0,\n 'data-state': 'active',\n className,\n ...props,\n },\n children,\n )\n },\n)\n"],
5
- "mappings": ";;;;;;;;;;;;AAmCO,SAAS,WAAW,QAAmB,CAAA,GAAa;AACzD,QAAM;IACJ,OAAO;IACP,eAAe;IACf;IACA,cAAc;EAAA,IACZ;AAEJ,MAAI,oBAAoB,mBAAmB;AAC3C,QAAM,WAAW,WAAW,UAAU;AAEtC,WAAS,iBAAyB;AAChC,QAAI,oBAAoB,OAAW,QAAO;AAC1C,WAAO;EACT;AAEA,WAAS,OAAO,OAAqB;AACnC,wBAAoB;AACpB,oBAAgB,KAAK;EACvB;AAEA,WAAS,SAAS,OAAuB;AACvC,WAAO,GAAG,QAAQ,QAAQ,KAAK;EACjC;AAEA,WAAS,WAAW,OAAuB;AACzC,WAAO,GAAG,QAAQ,UAAU,KAAK;EACnC;AAEA,WAAS,YAAY,OAAsE;AACzF,UAAM,aAAa,eAAA,MAAqB;AACxC,WAAO;MACL,MAAM;MACN,iBAAiB;MACjB,iBAAiB,WAAW,KAAK;MACjC,UAAU,aAAa,IAAI;MAC3B,IAAI,SAAS,KAAK;MAClB,cAAc,aAAa,WAAW;IAAA;EAE1C;AAEA,WAAS,cAAc,OAAsE;AAC3F,UAAM,aAAa,eAAA,MAAqB;AACxC,WAAO;MACL,MAAM;MACN,mBAAmB,SAAS,KAAK;MACjC,IAAI,WAAW,KAAK;MACpB,QAAQ,CAAC,cAAc;MACvB,UAAU;MACV,cAAc,aAAa,WAAW;IAAA;EAE1C;AAEA,QAAM,YAAmE;IACvE,MAAM;IACN,oBAAoB;EAAA;AAGtB,QAAM,mBAAuC,gBAAgB,eACzD;IACE,CAAC,KAAK,SAAS,GAAG,CAAC,MAAM;AACvB,QAAE,eAAA;IACJ;IACA,CAAC,KAAK,UAAU,GAAG,CAAC,MAAM;AACxB,QAAE,eAAA;IACJ;IACA,CAAC,KAAK,IAAI,GAAG,CAAC,MAAM;AAClB,QAAE,eAAA;IACJ;IACA,CAAC,KAAK,GAAG,GAAG,CAAC,MAAM;AACjB,QAAE,eAAA;IACJ;EAAA,IAEF;IACE,CAAC,KAAK,OAAO,GAAG,CAAC,MAAM;AACrB,QAAE,eAAA;IACJ;IACA,CAAC,KAAK,SAAS,GAAG,CAAC,MAAM;AACvB,QAAE,eAAA;IACJ;IACA,CAAC,KAAK,IAAI,GAAG,CAAC,MAAM;AAClB,QAAE,eAAA;IACJ;IACA,CAAC,KAAK,GAAG,GAAG,CAAC,MAAM;AACjB,QAAE,eAAA;IACJ;EAAA;AAGN,SAAO;IACL,OAAO,EAAE,aAAa,eAAA,EAAe;IACrC;IACA;IACA;IACA;IACA;IACA;EAAA;AAEJ;AAQO,SAAS,gBACd,SACA,KACA,OACA,cAAyC,cAC1B;AACf,MAAI,UAAU,EAAG,QAAO;AACxB,QAAM,OAAO,gBAAgB,eAAe,cAAc;AAC1D,QAAM,OAAO,gBAAgB,eAAe,eAAe;AAC3D,UAAQ,KAAA;IACN,KAAK;AACH,aAAO,UAAU,IAAI,KAAK,UAAU,KAAK;IAC3C,KAAK;AACH,aAAO,UAAU,IAAI,QAAQ,KAAK,UAAU,IAAI,SAAS;IAC3D,KAAK;AACH,aAAO;IACT,KAAK;AACH,aAAO,QAAQ;IACjB;AACE,aAAO;EAAA;AAEb;AC/JO,IAAM,mBAAmB,IAAI;EAClC,MAAM;AACR,CAAC;AAEM,IAAM,sBAAsB,IAAI;EACrC,MAAM;AACR,CAAC;;;ACgBD,IAAM,cAAoB,oBAAuC,IAAI;AAErE,SAAS,iBAAmC;AAC1C,QAAM,MAAY,iBAAW,WAAW;AACxC,MAAI,CAAC,KAAK;AACR;MACE;MACA;IAAA;AAEF,UAAM,IAAI,MAAM,qDAAqD;EACvE;AACA,SAAO;AACT;AAeO,IAAM,OAAa;EACxB,SAASA,MAAK,EAAE,OAAO,iBAAiB,eAAe,IAAI,eAAe,cAAc,cAAc,WAAW,UAAU,GAAG,MAAA,GAAoB,KAAK;AACvJ,UAAM,CAAC,mBAAmB,oBAAoB,IAAU,eAAS,YAAY;AAC7E,UAAM,eAAe,oBAAoB;AACzC,UAAM,QAAQ,eAAe,kBAAkB;AAE/C,UAAM,oBAA0B;MAC9B,CAAC,SAAiB;AAChB,YAAI,CAAC,cAAc;AACjB,+BAAqB,IAAI;QAC3B;AACA,wBAAgB,IAAI;MACtB;MACA,CAAC,cAAc,aAAa;IAAA;AAI9B,UAAM,SAAe,aAA6C,IAAI;AACtE,QAAI,OAAO,YAAY,MAAM;AAC3B,aAAO,UAAU,WAAW,EAAE,OAAO,YAAA,CAAa;IACpD;AACA,UAAM,MAAM,OAAO;AAEnB,UAAM,CAAC,QAAQ,SAAS,IAAU,eAA8B,MAAM,oBAAI,IAAA,CAAK;AAC/E,UAAM,gBAAsB,kBAAY,CAAC,eAAuB;AAC9D,gBAAU,CAAC,SAAU,KAAK,IAAI,UAAU,IAAI,OAAO,IAAI,IAAI,IAAI,EAAE,IAAI,UAAU,CAAE;AACjF,aAAO,MACL,UAAU,CAAC,SAAS;AAClB,YAAI,CAAC,KAAK,IAAI,UAAU,EAAG,QAAO;AAClC,cAAM,OAAO,IAAI,IAAI,IAAI;AACzB,aAAK,OAAO,UAAU;AACtB,eAAO;MACT,CAAC;IACL,GAAG,CAAA,CAAE;AAIL,UAAM,YAAkB,cAAQ,MAAM;AACpC,YAAM,QAAQ,IAAI,IAAI,MAAM;AAC5B,yBAAmB,UAAU,KAAK;AAClC,aAAO;IACT,GAAG,CAAC,UAAU,MAAM,CAAC;AAErB,UAAM,MAAY;MAChB,OAAO;QACL;QACA,eAAe;QACf;QACA,UAAU,IAAI;QACd,QAAQ;QACR;MAAA;MAEF,CAAC,OAAO,mBAAmB,aAAa,IAAI,UAAU,WAAW,aAAa;IAAA;AAGhF,WAAa;MACX;MACA,EAAE,KAAK,WAAW,oBAAoB,aAAa,GAAG,MAAA;MAChD,oBAAc,YAAY,UAAU,EAAE,OAAO,IAAA,GAAO,QAAQ;IAAA;EAEpE;AACF;AAEA,SAAS,mBAAmB,MAAuB,MAAyB;AACpE,EAAA,eAAS,QAAQ,MAAM,CAAC,UAAU;AACtC,QAAI,CAAO,qBAAgE,KAAK,EAAG;AACnF,QAAI,MAAM,SAAS,eAAe,OAAO,MAAM,MAAM,UAAU,UAAU;AACvE,WAAK,IAAI,MAAM,MAAM,KAAK;AAC1B;IACF;AACA,uBAAmB,MAAM,MAAM,UAAU,IAAI;EAC/C,CAAC;AACH;AAQO,IAAM,WAAiB;EAC5B,SAASC,UAAS,EAAE,WAAW,WAAW,GAAG,MAAA,GAAS,cAAc;AAClE,UAAM,EAAE,YAAA,IAAgB,eAAA;AACxB,UAAM,UAAgB,aAA8B,IAAI;AACxD,UAAM,MAAY;MAChB,CAAC,SAAgC;AAC/B,gBAAQ,UAAU;AAClB,YAAI,OAAO,iBAAiB,WAAY,cAAa,IAAI;iBAChD,aAAA,cAA2B,UAAU;MAChD;MACA,CAAC,YAAY;IAAA;AAUT,IAAA,gBAAU,MAAM;AACpB,YAAM,OAAO,YAAY,QAAQ,OAAO;AACxC,YAAM,OAAO,KAAK,KAAK,CAAC,QAAQ,IAAI,aAAa,eAAe,MAAM,MAAM,KAAK,KAAK,CAAC;AACvF,iBAAW,OAAO,KAAM,KAAI,WAAW,QAAQ,OAAO,IAAI;IAC5D,CAAC;AAED,UAAM,gBAAgB,CAAC,MAA2C;AAChE,kBAAY,CAAC;AACb,UAAI,EAAE,iBAAkB;AACxB,YAAM,OAAO,YAAY,QAAQ,OAAO;AACxC,YAAM,UAAU,KAAK,QAAQ,EAAE,MAA2B;AAC1D,UAAI,YAAY,GAAI;AACpB,YAAM,OAAO,gBAAgB,SAAS,EAAE,KAAK,KAAK,QAAQ,WAAW;AACrE,UAAI,SAAS,KAAM;AACnB,QAAE,eAAA;AACF,WAAK,IAAI,EAAE,MAAA;AAEX,WAAK,IAAI,EAAE,MAAA;IACb;AAEA,WAAa,oBAAc,OAAO;MAChC;MACA,MAAM;MACN,oBAAoB;MACpB,WAAW,GAAG,iBAAA,GAAoB,SAAS;MAC3C,WAAW;MACX,GAAG;IAAA,CACJ;EACH;AACF;AAEA,SAAS,YAAY,MAA+C;AAClE,MAAI,CAAC,KAAM,QAAO,CAAA;AAClB,SAAO,MAAM,KAAK,KAAK,iBAAoC,8BAA8B,CAAC;AAC5F;AAUO,IAAM,cAAoB;EAC/B,SAASC,aAAY,EAAE,OAAO,WAAW,SAAS,WAAW,UAAU,GAAG,MAAA,GAAS,KAAK;AACtF,UAAM,EAAE,OAAO,aAAa,eAAe,UAAU,OAAA,IAAW,eAAA;AAEhE,UAAM,aAAa,gBAAgB;AACnC,UAAM,QAAQ,GAAG,QAAQ,QAAQ,KAAK;AACtC,UAAM,UAAU,GAAG,QAAQ,UAAU,KAAK;AAE1C,UAAM,cAAc,CAAC,MAA2C;AAC9D,oBAAc,KAAK;AACnB,gBAAU,CAAC;IACb;AAIA,UAAM,gBAAgB,CAAC,MAA8C;AACnE,kBAAY,CAAC;IACf;AAEA,WAAa;MACX;MACA;QACE;QACA,MAAM;QACN,MAAM;QACN,iBAAiB;;QAEjB,iBAAiB,cAAc,OAAO,IAAI,KAAK,IAAI,UAAU;QAC7D,UAAU,aAAa,IAAI;QAC3B,IAAI;QACJ,cAAc,aAAa,WAAW;QACtC,WAAW,GAAG,oBAAA,GAAuB,SAAS;QAC9C,SAAS;QACT,WAAW;QACX,GAAG;MAAA;MAEL;IAAA;EAEJ;AACF;AAUO,IAAM,cAAoB;EAC/B,SAASC,aAAY,EAAE,OAAO,WAAW,UAAU,GAAG,MAAA,GAAS,KAAK;AAClE,UAAM,EAAE,OAAO,aAAa,UAAU,cAAA,IAAkB,eAAA;AAClD,IAAA,gBAAU,MAAM,cAAc,KAAK,GAAG,CAAC,eAAe,KAAK,CAAC;AAElE,UAAM,aAAa,gBAAgB;AACnC,UAAM,QAAQ,GAAG,QAAQ,QAAQ,KAAK;AACtC,UAAM,UAAU,GAAG,QAAQ,UAAU,KAAK;AAE1C,QAAI,CAAC,WAAY,QAAO;AAExB,WAAa;MACX;MACA;QACE;QACA,MAAM;QACN,mBAAmB;QACnB,IAAI;QACJ,UAAU;QACV,cAAc;QACd;QACA,GAAG;MAAA;MAEL;IAAA;EAEJ;AACF;",
4
+ "sourcesContent": ["import type { AccessibilityProps, KeyboardHandlerMap } from '@refraction-ui/shared'\nimport { Keys, generateId } from '@refraction-ui/shared'\n\nexport interface TabsProps {\n /** The active tab value (controlled) */\n value?: string\n /** The default active tab value (uncontrolled) */\n defaultValue?: string\n /** Callback when active tab changes */\n onValueChange?: (value: string) => void\n /** Orientation of the tab list */\n orientation?: 'horizontal' | 'vertical'\n}\n\nexport interface TabsState {\n activeValue: string\n}\n\nexport interface TabsAPI {\n /** Current tabs state */\n state: TabsState\n /** ARIA attributes for the tab list */\n listProps: Partial<AccessibilityProps> & Record<string, unknown>\n /** Factory for individual tab trigger props */\n getTabProps(value: string): Partial<AccessibilityProps> & Record<string, unknown>\n /** Factory for individual tab panel props */\n getPanelProps(value: string): Partial<AccessibilityProps> & Record<string, unknown>\n /** Select a tab by value */\n select(value: string): void\n /** Keyboard handlers for the tab list */\n keyboardHandlers: KeyboardHandlerMap\n /** Generated ID prefix for aria linking */\n idPrefix: string\n}\n\nexport function createTabs(props: TabsProps = {}): TabsAPI {\n const {\n value: controlledValue,\n defaultValue = '',\n onValueChange,\n orientation = 'horizontal',\n } = props\n\n let uncontrolledValue = controlledValue ?? defaultValue\n const idPrefix = generateId('rfr-tabs')\n\n function getActiveValue(): string {\n if (controlledValue !== undefined) return controlledValue\n return uncontrolledValue\n }\n\n function select(value: string): void {\n uncontrolledValue = value\n onValueChange?.(value)\n }\n\n function getTabId(value: string): string {\n return `${idPrefix}-tab-${value}`\n }\n\n function getPanelId(value: string): string {\n return `${idPrefix}-panel-${value}`\n }\n\n function getTabProps(value: string): Partial<AccessibilityProps> & Record<string, unknown> {\n const isSelected = getActiveValue() === value\n return {\n role: 'tab',\n 'aria-selected': isSelected,\n 'aria-controls': getPanelId(value),\n tabIndex: isSelected ? 0 : -1,\n id: getTabId(value),\n 'data-state': isSelected ? 'active' : 'inactive',\n }\n }\n\n function getPanelProps(value: string): Partial<AccessibilityProps> & Record<string, unknown> {\n const isSelected = getActiveValue() === value\n return {\n role: 'tabpanel',\n 'aria-labelledby': getTabId(value),\n id: getPanelId(value),\n hidden: !isSelected || undefined,\n tabIndex: 0,\n 'data-state': isSelected ? 'active' : 'inactive',\n }\n }\n\n const listProps: Partial<AccessibilityProps> & Record<string, unknown> = {\n role: 'tablist',\n 'aria-orientation': orientation,\n }\n\n const keyboardHandlers: KeyboardHandlerMap = orientation === 'horizontal'\n ? {\n [Keys.ArrowLeft]: (e) => {\n e.preventDefault()\n },\n [Keys.ArrowRight]: (e) => {\n e.preventDefault()\n },\n [Keys.Home]: (e) => {\n e.preventDefault()\n },\n [Keys.End]: (e) => {\n e.preventDefault()\n },\n }\n : {\n [Keys.ArrowUp]: (e) => {\n e.preventDefault()\n },\n [Keys.ArrowDown]: (e) => {\n e.preventDefault()\n },\n [Keys.Home]: (e) => {\n e.preventDefault()\n },\n [Keys.End]: (e) => {\n e.preventDefault()\n },\n }\n\n return {\n state: { activeValue: getActiveValue() },\n listProps,\n getTabProps,\n getPanelProps,\n select,\n keyboardHandlers,\n idPrefix,\n }\n}\n\n/**\n * Roving-focus target for a key press inside a tab list (WAI-ARIA Tabs\n * pattern). Given the index of the focused tab among the ENABLED tabs, returns\n * the index to move to, or `null` when the key is not a navigation key for this\n * orientation. Arrow keys wrap; Home/End jump to the ends.\n */\nexport function getNextTabIndex(\n current: number,\n key: string,\n count: number,\n orientation: 'horizontal' | 'vertical' = 'horizontal',\n): number | null {\n if (count === 0) return null\n const prev = orientation === 'horizontal' ? 'ArrowLeft' : 'ArrowUp'\n const next = orientation === 'horizontal' ? 'ArrowRight' : 'ArrowDown'\n switch (key) {\n case next:\n return current < 0 ? 0 : (current + 1) % count\n case prev:\n return current < 0 ? count - 1 : (current - 1 + count) % count\n case 'Home':\n return 0\n case 'End':\n return count - 1\n default:\n return null\n }\n}\n", "import { cva } from '@refraction-ui/shared'\n\nexport const tabsListVariants = cva({\n base: 'inline-flex max-w-full overflow-x-auto items-center justify-center rounded-lg bg-muted p-1 text-muted-foreground',\n})\n\nexport const tabsTriggerVariants = cva({\n base: 'inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-1 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow',\n})\n", "import * as React from 'react'\nimport {\n getNextTabIndex,\n tabsListVariants,\n tabsTriggerVariants,\n type TabsProps as CoreTabsProps,\n} from '@refraction-ui/tabs'\nimport { cn, createKeyboardHandler, Keys, devWarn } from '@refraction-ui/shared'\n\n// ---------------------------------------------------------------------------\n// Context\n// ---------------------------------------------------------------------------\n\ninterface TabsContextValue {\n value: string\n onValueChange: (value: string) => void\n orientation: 'horizontal' | 'vertical'\n idPrefix: string\n /** Values that have a TabsContent, so triggers only reference real panels. */\n panels: ReadonlySet<string>\n registerPanel: (value: string) => () => void\n}\n\nconst TabsContext = React.createContext<TabsContextValue | null>(null)\n\nfunction useTabsContext(): TabsContextValue {\n const ctx = React.useContext(TabsContext)\n if (!ctx) {\n devWarn(\n 'react-tabs/context-outside-provider',\n 'Tabs compound components (TabsList/TabsTrigger/TabsContent) must be rendered inside a <Tabs>. The missing TabsContext makes this throw.',\n )\n throw new Error('Tabs compound components must be used within <Tabs>')\n }\n return ctx\n}\n\n// ---------------------------------------------------------------------------\n// Tabs (root provider)\n// ---------------------------------------------------------------------------\n\nexport interface TabsProps extends React.HTMLAttributes<HTMLDivElement> {\n value?: string\n defaultValue?: string\n onValueChange?: (value: string) => void\n orientation?: 'horizontal' | 'vertical'\n className?: string\n children?: React.ReactNode\n}\n\nexport const Tabs = React.forwardRef<HTMLDivElement, TabsProps>(\n function Tabs({ value: controlledValue, defaultValue = '', onValueChange, orientation = 'horizontal', className, children, ...props }: TabsProps, ref) {\n const [uncontrolledValue, setUncontrolledValue] = React.useState(defaultValue)\n const isControlled = controlledValue !== undefined\n const value = isControlled ? controlledValue : uncontrolledValue\n\n const handleValueChange = React.useCallback(\n (next: string) => {\n if (!isControlled) {\n setUncontrolledValue(next)\n }\n onValueChange?.(next)\n },\n [isControlled, onValueChange],\n )\n\n // React IDs agree across SSR and hydration, unlike the core's process counter.\n const idPrefix = `rfr-tabs-${React.useId()}`\n\n const [panels, setPanels] = React.useState<ReadonlySet<string>>(() => new Set())\n const registerPanel = React.useCallback((panelValue: string) => {\n setPanels((prev) => (prev.has(panelValue) ? prev : new Set(prev).add(panelValue)))\n return () =>\n setPanels((prev) => {\n if (!prev.has(panelValue)) return prev\n const next = new Set(prev)\n next.delete(panelValue)\n return next\n })\n }, [])\n\n // Panels found in the element tree cover the first/server render; mounted\n // panels (possibly nested in custom components) register themselves.\n const allPanels = React.useMemo(() => {\n const found = new Set(panels)\n collectPanelValues(children, found)\n return found\n }, [children, panels])\n\n const ctx = React.useMemo<TabsContextValue>(\n () => ({\n value,\n onValueChange: handleValueChange,\n orientation,\n idPrefix,\n panels: allPanels,\n registerPanel,\n }),\n [value, handleValueChange, orientation, idPrefix, allPanels, registerPanel],\n )\n\n return React.createElement(\n 'div',\n { ref, className, 'data-orientation': orientation, ...props },\n React.createElement(TabsContext.Provider, { value: ctx }, children),\n )\n },\n)\n\nfunction collectPanelValues(node: React.ReactNode, into: Set<string>): void {\n React.Children.forEach(node, (child) => {\n if (!React.isValidElement<{ value?: unknown; children?: React.ReactNode }>(child)) return\n if (child.type === TabsContent && typeof child.props.value === 'string') {\n into.add(child.props.value)\n return\n }\n collectPanelValues(child.props.children, into)\n })\n}\n\n// ---------------------------------------------------------------------------\n// TabsList\n// ---------------------------------------------------------------------------\n\nexport interface TabsListProps extends React.HTMLAttributes<HTMLDivElement> {}\n\nexport const TabsList = React.forwardRef<HTMLDivElement, TabsListProps>(\n function TabsList({ className, onKeyDown, ...props }, forwardedRef) {\n const { orientation } = useTabsContext()\n const listRef = React.useRef<HTMLDivElement | null>(null)\n const ref = React.useCallback(\n (node: HTMLDivElement | null) => {\n listRef.current = node\n if (typeof forwardedRef === 'function') forwardedRef(node)\n else if (forwardedRef) forwardedRef.current = node\n },\n [forwardedRef],\n )\n\n // Roving tabindex needs exactly one tab stop. A trigger only knows whether\n // IT is selected, so when no enabled trigger matches the value (no\n // defaultValue, or the selected tab is disabled) nothing would be\n // tabbable; make the first enabled tab the stop in that case.\n // This effect owns the final tabindex of every trigger (React leaves a\n // DOM value alone while its prop is unchanged, so patching only the\n // fallback would leave two tab stops after the next selection).\n React.useEffect(() => {\n const tabs = enabledTabs(listRef.current)\n const stop = tabs.find((tab) => tab.getAttribute('aria-selected') === 'true') ?? tabs[0]\n for (const tab of tabs) tab.tabIndex = tab === stop ? 0 : -1\n })\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {\n onKeyDown?.(e)\n if (e.defaultPrevented) return\n const tabs = enabledTabs(listRef.current)\n const current = tabs.indexOf(e.target as HTMLButtonElement)\n if (current === -1) return\n const next = getNextTabIndex(current, e.key, tabs.length, orientation)\n if (next === null) return\n e.preventDefault()\n tabs[next].focus()\n // Automatic activation: moving focus selects the tab.\n tabs[next].click()\n }\n\n return React.createElement('div', {\n ref,\n role: 'tablist',\n 'aria-orientation': orientation,\n className: cn(tabsListVariants(), className),\n onKeyDown: handleKeyDown,\n ...props,\n })\n },\n)\n\nfunction enabledTabs(list: HTMLElement | null): HTMLButtonElement[] {\n if (!list) return []\n return Array.from(list.querySelectorAll<HTMLButtonElement>('[role=\"tab\"]:not([disabled])'))\n}\n\n// ---------------------------------------------------------------------------\n// TabsTrigger\n// ---------------------------------------------------------------------------\n\nexport interface TabsTriggerProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n value: string\n}\n\nexport const TabsTrigger = React.forwardRef<HTMLButtonElement, TabsTriggerProps>(\n function TabsTrigger({ value, className, onClick, onKeyDown, children, ...props }, ref) {\n const { value: activeValue, onValueChange, idPrefix, panels } = useTabsContext()\n\n const isSelected = activeValue === value\n const tabId = `${idPrefix}-tab-${value}`\n const panelId = `${idPrefix}-panel-${value}`\n\n const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {\n onValueChange(value)\n onClick?.(e)\n }\n\n // Arrow / Home / End navigation is handled by TabsList (roving focus);\n // a consumer onKeyDown runs first and can preventDefault to opt out.\n const handleKeyDown = (e: React.KeyboardEvent<HTMLButtonElement>) => {\n onKeyDown?.(e)\n }\n\n return React.createElement(\n 'button',\n {\n ref,\n type: 'button',\n role: 'tab',\n 'aria-selected': isSelected,\n // Only the selected panel is rendered; never reference a missing element.\n 'aria-controls': isSelected && panels.has(value) ? panelId : undefined,\n tabIndex: isSelected ? 0 : -1,\n id: tabId,\n 'data-state': isSelected ? 'active' : 'inactive',\n className: cn(tabsTriggerVariants(), className),\n onClick: handleClick,\n onKeyDown: handleKeyDown,\n ...props,\n },\n children,\n )\n },\n)\n\n// ---------------------------------------------------------------------------\n// TabsContent\n// ---------------------------------------------------------------------------\n\nexport interface TabsContentProps extends React.HTMLAttributes<HTMLDivElement> {\n value: string\n}\n\nexport const TabsContent = React.forwardRef<HTMLDivElement, TabsContentProps>(\n function TabsContent({ value, className, children, ...props }, ref) {\n const { value: activeValue, idPrefix, registerPanel } = useTabsContext()\n React.useEffect(() => registerPanel(value), [registerPanel, value])\n\n const isSelected = activeValue === value\n const tabId = `${idPrefix}-tab-${value}`\n const panelId = `${idPrefix}-panel-${value}`\n\n if (!isSelected) return null\n\n return React.createElement(\n 'div',\n {\n ref,\n role: 'tabpanel',\n 'aria-labelledby': tabId,\n id: panelId,\n tabIndex: 0,\n 'data-state': 'active',\n className,\n ...props,\n },\n children,\n )\n },\n)\n"],
5
+ "mappings": "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",
6
6
  "names": ["Tabs", "TabsList", "TabsTrigger", "TabsContent"]
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@refraction-ui/react",
3
- "version": "0.23.1",
3
+ "version": "0.23.3",
4
4
  "description": "All Refraction UI React components in one package — headless, accessible, zero-dependency",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",