@brycks/core-front 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/dist/components/data/List/List.cjs +1 -1
  2. package/dist/components/data/List/List.cjs.map +1 -1
  3. package/dist/components/data/List/List.js +68 -148
  4. package/dist/components/data/List/List.js.map +1 -1
  5. package/dist/components/data/Table/Table.cjs +1 -1
  6. package/dist/components/data/Table/Table.cjs.map +1 -1
  7. package/dist/components/data/Table/Table.js +142 -224
  8. package/dist/components/data/Table/Table.js.map +1 -1
  9. package/dist/components/data/TreeView/TreeView.cjs +1 -1
  10. package/dist/components/data/TreeView/TreeView.cjs.map +1 -1
  11. package/dist/components/data/TreeView/TreeView.js +141 -182
  12. package/dist/components/data/TreeView/TreeView.js.map +1 -1
  13. package/dist/components/feedback/Drawer/Drawer.cjs +1 -22
  14. package/dist/components/feedback/Drawer/Drawer.cjs.map +1 -1
  15. package/dist/components/feedback/Drawer/Drawer.js +84 -184
  16. package/dist/components/feedback/Drawer/Drawer.js.map +1 -1
  17. package/dist/components/feedback/Modal/Modal.cjs +1 -1
  18. package/dist/components/feedback/Modal/Modal.cjs.map +1 -1
  19. package/dist/components/feedback/Modal/Modal.js +65 -150
  20. package/dist/components/feedback/Modal/Modal.js.map +1 -1
  21. package/dist/components/feedback/Toast/Toast.cjs +1 -10
  22. package/dist/components/feedback/Toast/Toast.cjs.map +1 -1
  23. package/dist/components/feedback/Toast/Toast.js +94 -187
  24. package/dist/components/feedback/Toast/Toast.js.map +1 -1
  25. package/dist/components/form/Checkbox/Checkbox.cjs +1 -1
  26. package/dist/components/form/Checkbox/Checkbox.js +11 -11
  27. package/dist/components/form/Combobox/Combobox.cjs +1 -6
  28. package/dist/components/form/Combobox/Combobox.cjs.map +1 -1
  29. package/dist/components/form/Combobox/Combobox.js +187 -283
  30. package/dist/components/form/Combobox/Combobox.js.map +1 -1
  31. package/dist/components/form/Input/Input.cjs +1 -1
  32. package/dist/components/form/Input/Input.cjs.map +1 -1
  33. package/dist/components/form/Input/Input.js +38 -133
  34. package/dist/components/form/Input/Input.js.map +1 -1
  35. package/dist/components/form/Select/Select.cjs +1 -1
  36. package/dist/components/form/Select/Select.cjs.map +1 -1
  37. package/dist/components/form/Select/Select.js +36 -82
  38. package/dist/components/form/Select/Select.js.map +1 -1
  39. package/dist/components/form/TagInput/TagInput.cjs +1 -1
  40. package/dist/components/form/TagInput/TagInput.js +8 -8
  41. package/dist/components/form/Textarea/Textarea.cjs +1 -1
  42. package/dist/components/form/Textarea/Textarea.cjs.map +1 -1
  43. package/dist/components/form/Textarea/Textarea.js +61 -95
  44. package/dist/components/form/Textarea/Textarea.js.map +1 -1
  45. package/dist/components/navigation/ContextMenu/ContextMenu.cjs +1 -1
  46. package/dist/components/navigation/ContextMenu/ContextMenu.js +9 -9
  47. package/dist/components/navigation/Menu/Menu.cjs +1 -1
  48. package/dist/components/navigation/Menu/Menu.cjs.map +1 -1
  49. package/dist/components/navigation/Menu/Menu.js +70 -135
  50. package/dist/components/navigation/Menu/Menu.js.map +1 -1
  51. package/dist/components/navigation/Pagination/Pagination.cjs +1 -1
  52. package/dist/components/navigation/Pagination/Pagination.cjs.map +1 -1
  53. package/dist/components/navigation/Pagination/Pagination.js +87 -157
  54. package/dist/components/navigation/Pagination/Pagination.js.map +1 -1
  55. package/dist/styles.css +1 -1
  56. package/package.json +1 -1
@@ -2,10 +2,10 @@ import { jsx as o, jsxs as D } from "react/jsx-runtime";
2
2
  import { forwardRef as R, useState as k, useCallback as M, useEffect as I, createContext as A, useContext as W, useRef as $ } from "react";
3
3
  import { createPortal as j } from "react-dom";
4
4
  import { cx as O } from "../../../utils/styles.js";
5
+ import { componentPaddingY as K, componentPaddingX as N, iconSizes as S } from "../../../design-system/primitives/sizing.js";
5
6
  import { spacing as C } from "../../../design-system/tokens/spacing.js";
6
- import { durations as K, easings as N } from "../../../design-system/tokens/motion.js";
7
- import { fontSizes as S } from "../../../design-system/tokens/typography.js";
8
- import { componentPaddingY as X, componentPaddingX as Y, iconSizes as P } from "../../../design-system/primitives/sizing.js";
7
+ import { durations as X, easings as Y } from "../../../design-system/tokens/motion.js";
8
+ import { fontSizes as P } from "../../../design-system/tokens/typography.js";
9
9
  const E = A(null);
10
10
  function B() {
11
11
  return /* @__PURE__ */ o("svg", { width: "12", height: "12", viewBox: "0 0 12 12", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ o("path", { d: "M4.5 3l3 3-3 3", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) });
@@ -75,24 +75,24 @@ function L({ items: a, position: h, onClose: l, level: f = 0 }) {
75
75
  display: "flex",
76
76
  alignItems: "center",
77
77
  gap: C[2],
78
- padding: `${X.sm}px ${Y.sm}px`,
79
- fontSize: S.sm,
78
+ padding: `${K.sm}px ${N.sm}px`,
79
+ fontSize: P.sm,
80
80
  fontWeight: 400,
81
81
  color: n ? "var(--brycks-foreground-disabled)" : "var(--brycks-foreground-default)",
82
82
  backgroundColor: e ? "var(--brycks-background-muted)" : "transparent",
83
83
  borderRadius: "var(--brycks-radius-md)",
84
84
  cursor: n ? "not-allowed" : "pointer",
85
- transition: `background-color ${K.fast}ms ${N.easeOut}`
85
+ transition: `background-color ${X.fast}ms ${Y.easeOut}`
86
86
  }), g = {
87
87
  display: "flex",
88
88
  alignItems: "center",
89
89
  justifyContent: "center",
90
- width: P.sm,
91
- height: P.sm,
90
+ width: S.sm,
91
+ height: S.sm,
92
92
  color: "inherit"
93
93
  }, d = {
94
94
  marginLeft: "auto",
95
- fontSize: S.xs,
95
+ fontSize: P.xs,
96
96
  color: "var(--brycks-foreground-muted)"
97
97
  }, w = {
98
98
  height: 1,
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const u=require("react/jsx-runtime"),r=require("react"),j=require("../../../utils/styles.cjs"),i=require("../../../design-system/primitives/sizing.cjs"),m=require("../../../design-system/tokens/spacing.cjs"),N=require("../../../design-system/tokens/motion.cjs"),C=require("../../../design-system/tokens/typography.cjs"),A=r.createContext(null);function G(){const g=r.useContext(A);if(!g)throw new Error("Menu components must be used within a Menu");return g}const H=r.forwardRef(function({activeItem:t,onChange:l,size:c="md",collapsed:s=!1,className:p,style:S,children:v,testId:y,...k},x){const[D,M]=r.useState(null),[h,o]=r.useState(-1),b=r.useRef([]),z=r.useRef(null),R=t!==void 0?t:D,a=e=>{t===void 0&&M(e),l?.(e)},d=r.useCallback(e=>{const n=b.current.indexOf(e);return n===-1?(b.current.push(e),b.current.length-1):n},[]),I=r.useCallback(e=>{const n=z.current?.querySelectorAll('[role="menuitem"]:not(:disabled)');if(!n?.length)return;const w=h>=0?h:0;switch(e.key){case"ArrowDown":{e.preventDefault();const f=(w+1)%n.length;o(f),n[f]?.focus();break}case"ArrowUp":{e.preventDefault();const f=(w-1+n.length)%n.length;o(f),n[f]?.focus();break}case"Home":e.preventDefault(),o(0),n[0]?.focus();break;case"End":e.preventDefault(),o(n.length-1),n[n.length-1]?.focus();break}},[h]),q={display:"flex",flexDirection:"column",gap:m.spacing[.5],padding:m.spacing[2],...S};return u.jsx(A.Provider,{value:{size:c,activeItem:R,setActiveItem:a,collapsed:s,focusedIndex:h,setFocusedIndex:o,registerItem:d},children:u.jsx("nav",{ref:e=>{z.current=e,typeof x=="function"?x(e):x&&(x.current=e)},role:"menu",className:j.cx("brycks-menu",`brycks-menu--${c}`,s&&"brycks-menu--collapsed",p),style:q,onKeyDown:I,"data-testid":y,...k,children:v})})});H.displayName="Menu";const O={sm:{height:i.componentHeights.sm,fontSize:C.fontSizes.base-1,iconSize:i.iconSizes.sm,padding:i.componentGap.lg},md:{height:i.componentHeights.md,fontSize:C.fontSizes.base,iconSize:i.iconSizes.md-2,padding:i.componentPaddingX.sm},lg:{height:i.componentHeights.lg,fontSize:C.fontSizes.md,iconSize:i.iconSizes.md,padding:m.spacing[3.5]}},T=r.forwardRef(function({value:t,icon:l,badge:c,disabled:s=!1,onClick:p,className:S,style:v,children:y,...k},x){const{size:D,activeItem:M,setActiveItem:h,collapsed:o,focusedIndex:b,setFocusedIndex:z,registerItem:R}=G(),a=M===t,d=O[D],I=R(t),q=()=>{s||(h(t),p?.(t))},e=()=>{z(I)},n={display:"flex",alignItems:"center",gap:i.componentGap.lg,width:"100%",minHeight:d.height,padding:o?d.padding:`0 ${d.padding}px`,fontSize:d.fontSize,fontWeight:a?600:500,color:s?"var(--brycks-foreground-disabled)":a?"var(--brycks-primary-default)":"var(--brycks-foreground-default)",backgroundColor:a?"var(--brycks-primary-muted)":"transparent",border:"none",borderRadius:"var(--brycks-radius-md)",cursor:s?"not-allowed":"pointer",transition:`all ${N.durations.quick}ms ${N.easings.easeOut}`,textAlign:"left",justifyContent:o?"center":"flex-start",...v},w={width:d.iconSize,height:d.iconSize,flexShrink:0,display:"flex",alignItems:"center",justifyContent:"center"},f={marginLeft:"auto"},E=b>=0?b===I:M?a:I===0;return u.jsxs("button",{ref:x,type:"button",role:"menuitem",disabled:s,tabIndex:E?0:-1,className:j.cx("brycks-menu-item",a&&"brycks-menu-item--active",S),style:n,onClick:q,onFocus:e,onMouseEnter:$=>{!s&&!a&&($.currentTarget.style.backgroundColor="var(--brycks-background-muted)")},onMouseLeave:$=>{a||($.currentTarget.style.backgroundColor="transparent")},title:o?String(y):void 0,...k,children:[l&&u.jsx("span",{style:w,children:l}),!o&&u.jsx("span",{style:{flex:1},children:y}),!o&&c&&u.jsx("span",{style:f,children:c})]})});T.displayName="MenuItem";const F=r.forwardRef(function({label:t,className:l,style:c,children:s,...p},S){const{collapsed:v}=G(),y={display:"flex",flexDirection:"column",gap:m.spacing[.5],...c},k={padding:`${m.spacing[3]}px ${m.spacing[3]}px ${i.componentPaddingY.sm}px ${m.spacing[3]}px`,fontSize:C.fontSizes.xs,fontWeight:600,color:"var(--brycks-foreground-muted)",textTransform:"uppercase",letterSpacing:"0.05em"};return u.jsxs("div",{ref:S,className:j.cx("brycks-menu-group",l),style:y,...p,children:[t&&!v&&u.jsx("div",{style:k,children:t}),s]})});F.displayName="MenuGroup";const P=r.forwardRef(function({className:t,style:l,...c},s){const p={height:1,backgroundColor:"var(--brycks-border-muted)",margin:`${m.spacing[2]}px 0`,...l};return u.jsx("div",{ref:s,role:"separator",className:j.cx("brycks-menu-divider",t),style:p,...c})});P.displayName="MenuDivider";exports.Menu=H;exports.MenuDivider=P;exports.MenuGroup=F;exports.MenuItem=T;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const u=require("react/jsx-runtime"),s=require("react"),h=require("../../../utils/styles.cjs"),R=s.createContext(null);function C(){const l=s.useContext(R);if(!l)throw new Error("Menu components must be used within a Menu");return l}const _=s.forwardRef(function({activeItem:n,onChange:o,size:r="md",collapsed:c=!1,className:d,style:f,children:x,testId:v,...g},m){const[I,w]=s.useState(null),[i,a]=s.useState(-1),p=s.useRef([]),M=s.useRef(null),k=n!==void 0?n:I,b=e=>{n===void 0&&w(e),o?.(e)},N=s.useCallback(e=>{const t=p.current.indexOf(e);return t===-1?(p.current.push(e),p.current.length-1):t},[]),j=s.useCallback(e=>{const t=M.current?.querySelectorAll('[role="menuitem"]:not(:disabled)');if(!t?.length)return;const D=i>=0?i:0;switch(e.key){case"ArrowDown":{e.preventDefault();const y=(D+1)%t.length;a(y),t[y]?.focus();break}case"ArrowUp":{e.preventDefault();const y=(D-1+t.length)%t.length;a(y),t[y]?.focus();break}case"Home":e.preventDefault(),a(0),t[0]?.focus();break;case"End":e.preventDefault(),a(t.length-1),t[t.length-1]?.focus();break}},[i]);return u.jsx(R.Provider,{value:{size:r,activeItem:k,setActiveItem:b,collapsed:c,focusedIndex:i,setFocusedIndex:a,registerItem:N},children:u.jsx("nav",{ref:e=>{M.current=e,typeof m=="function"?m(e):m&&(m.current=e)},role:"menu",className:h.cx("brycks-menu",`brycks-menu--${r}`,c&&"brycks-menu--collapsed",d),style:f,onKeyDown:j,"data-testid":v,...g,children:x})})});_.displayName="Menu";const S=s.forwardRef(function({value:n,icon:o,badge:r,disabled:c=!1,onClick:d,className:f,style:x,children:v,...g},m){const{activeItem:I,setActiveItem:w,collapsed:i,focusedIndex:a,setFocusedIndex:p,registerItem:M}=C(),k=I===n,b=M(n),N=()=>{c||(w(n),d?.(n))},j=()=>{p(b)},e=a>=0?a===b:I?k:b===0;return u.jsxs("button",{ref:m,type:"button",role:"menuitem",disabled:c,tabIndex:e?0:-1,className:h.cx("brycks-menu-item",k&&"brycks-menu-item--active",f),style:x,onClick:N,onFocus:j,title:i?String(v):void 0,...g,children:[o&&u.jsx("span",{className:"brycks-menu-item__icon",children:o}),!i&&u.jsx("span",{className:"brycks-menu-item__label",children:v}),!i&&r&&u.jsx("span",{className:"brycks-menu-item__badge",children:r})]})});S.displayName="MenuItem";const A=s.forwardRef(function({label:n,className:o,style:r,children:c,...d},f){const{collapsed:x}=C();return u.jsxs("div",{ref:f,className:h.cx("brycks-menu-group",o),style:r,...d,children:[n&&!x&&u.jsx("div",{className:"brycks-menu-group__label",children:n}),c]})});A.displayName="MenuGroup";const q=s.forwardRef(function({className:n,style:o,...r},c){return u.jsx("div",{ref:c,role:"separator",className:h.cx("brycks-menu-divider",n),style:o,...r})});q.displayName="MenuDivider";exports.Menu=_;exports.MenuDivider=q;exports.MenuGroup=A;exports.MenuItem=S;
2
2
  //# sourceMappingURL=Menu.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"Menu.cjs","sources":["../../../../src/components/navigation/Menu/Menu.tsx"],"sourcesContent":["/**\n * Menu Component\n *\n * A vertical navigation menu with support for nested items.\n * Suitable for sidebars and navigation panels.\n */\n\nimport {\n forwardRef,\n useState,\n useRef,\n useCallback,\n createContext,\n useContext,\n type CSSProperties,\n type ReactNode,\n type HTMLAttributes,\n type KeyboardEvent,\n} from 'react'\nimport { cx } from '../../../utils/styles'\nimport { spacing, fontSizes, durations, easings } from '../../../design-system'\nimport { componentHeights, componentGap, componentPaddingX, componentPaddingY, iconSizes } from '../../../design-system/primitives'\n\nexport type MenuSize = 'sm' | 'md' | 'lg'\n\ninterface MenuContextValue {\n size: MenuSize\n activeItem: string | null\n setActiveItem: (value: string | null) => void\n collapsed: boolean\n focusedIndex: number\n setFocusedIndex: (index: number) => void\n registerItem: (value: string) => number\n}\n\nconst MenuContext = createContext<MenuContextValue | null>(null)\n\nfunction useMenuContext() {\n const context = useContext(MenuContext)\n if (!context) {\n throw new Error('Menu components must be used within a Menu')\n }\n return context\n}\n\nexport interface MenuProps extends Omit<HTMLAttributes<HTMLElement>, 'onChange'> {\n /** Currently active item */\n activeItem?: string | null\n /** Callback when active item changes */\n onChange?: (value: string | null) => void\n /** Menu size */\n size?: MenuSize\n /** Whether the menu is collapsed (icons only) */\n collapsed?: boolean\n /** Custom class name */\n className?: string\n /** Test ID */\n testId?: string\n}\n\nexport const Menu = forwardRef<HTMLElement, MenuProps>(function Menu(\n {\n activeItem: controlledActiveItem,\n onChange,\n size = 'md',\n collapsed = false,\n className,\n style,\n children,\n testId,\n ...props\n },\n ref\n) {\n const [internalActiveItem, setInternalActiveItem] = useState<string | null>(null)\n const [focusedIndex, setFocusedIndex] = useState(-1)\n const itemsRef = useRef<string[]>([])\n const menuRef = useRef<HTMLElement>(null)\n const activeItem = controlledActiveItem !== undefined ? controlledActiveItem : internalActiveItem\n\n const setActiveItem = (value: string | null) => {\n if (controlledActiveItem === undefined) {\n setInternalActiveItem(value)\n }\n onChange?.(value)\n }\n\n // Register items for keyboard navigation\n const registerItem = useCallback((value: string) => {\n const index = itemsRef.current.indexOf(value)\n if (index === -1) {\n itemsRef.current.push(value)\n return itemsRef.current.length - 1\n }\n return index\n }, [])\n\n // Keyboard navigation\n const handleKeyDown = useCallback((e: KeyboardEvent<HTMLElement>) => {\n const items = menuRef.current?.querySelectorAll<HTMLButtonElement>('[role=\"menuitem\"]:not(:disabled)')\n if (!items?.length) return\n\n const currentIndex = focusedIndex >= 0 ? focusedIndex : 0\n\n switch (e.key) {\n case 'ArrowDown': {\n e.preventDefault()\n const nextIndex = (currentIndex + 1) % items.length\n setFocusedIndex(nextIndex)\n items[nextIndex]?.focus()\n break\n }\n case 'ArrowUp': {\n e.preventDefault()\n const prevIndex = (currentIndex - 1 + items.length) % items.length\n setFocusedIndex(prevIndex)\n items[prevIndex]?.focus()\n break\n }\n case 'Home':\n e.preventDefault()\n setFocusedIndex(0)\n items[0]?.focus()\n break\n case 'End':\n e.preventDefault()\n setFocusedIndex(items.length - 1)\n items[items.length - 1]?.focus()\n break\n }\n }, [focusedIndex])\n\n const menuStyle: CSSProperties = {\n display: 'flex',\n flexDirection: 'column',\n gap: spacing[0.5],\n padding: spacing[2],\n ...style,\n }\n\n return (\n <MenuContext.Provider value={{ size, activeItem, setActiveItem, collapsed, focusedIndex, setFocusedIndex, registerItem }}>\n <nav\n ref={(node) => {\n (menuRef as React.MutableRefObject<HTMLElement | null>).current = node\n if (typeof ref === 'function') ref(node)\n else if (ref) (ref as React.MutableRefObject<HTMLElement | null>).current = node\n }}\n role=\"menu\"\n className={cx('brycks-menu', `brycks-menu--${size}`, collapsed && 'brycks-menu--collapsed', className)}\n style={menuStyle}\n onKeyDown={handleKeyDown}\n data-testid={testId}\n {...props}\n >\n {children}\n </nav>\n </MenuContext.Provider>\n )\n})\n\nMenu.displayName = 'Menu'\n\n// MenuItem\nexport interface MenuItemProps extends Omit<HTMLAttributes<HTMLButtonElement>, 'onClick'> {\n /** Item value (unique identifier) */\n value: string\n /** Icon before the label */\n icon?: ReactNode\n /** Badge/count after the label */\n badge?: ReactNode\n /** Whether the item is disabled */\n disabled?: boolean\n /** Callback when clicked */\n onClick?: (value: string) => void\n /** Custom class name */\n className?: string\n}\n\nconst sizeConfig: Record<MenuSize, { height: number; fontSize: number; iconSize: number; padding: number }> = {\n sm: { height: componentHeights.sm, fontSize: fontSizes.base - 1, iconSize: iconSizes.sm, padding: componentGap.lg },\n md: { height: componentHeights.md, fontSize: fontSizes.base, iconSize: iconSizes.md - 2, padding: componentPaddingX.sm },\n lg: { height: componentHeights.lg, fontSize: fontSizes.md, iconSize: iconSizes.md, padding: spacing[3.5] },\n}\n\nexport const MenuItem = forwardRef<HTMLButtonElement, MenuItemProps>(function MenuItem(\n { value, icon, badge, disabled = false, onClick, className, style, children, ...props },\n ref\n) {\n const { size, activeItem, setActiveItem, collapsed, focusedIndex, setFocusedIndex, registerItem } = useMenuContext()\n const isActive = activeItem === value\n const config = sizeConfig[size]\n const itemIndex = registerItem(value)\n\n const handleClick = () => {\n if (disabled) return\n setActiveItem(value)\n onClick?.(value)\n }\n\n const handleFocus = () => {\n setFocusedIndex(itemIndex)\n }\n\n const itemStyle: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n gap: componentGap.lg,\n width: '100%',\n minHeight: config.height,\n padding: collapsed ? config.padding : `0 ${config.padding}px`,\n fontSize: config.fontSize,\n fontWeight: isActive ? 600 : 500,\n color: disabled\n ? 'var(--brycks-foreground-disabled)'\n : isActive\n ? 'var(--brycks-primary-default)'\n : 'var(--brycks-foreground-default)',\n backgroundColor: isActive ? 'var(--brycks-primary-muted)' : 'transparent',\n border: 'none',\n borderRadius: 'var(--brycks-radius-md)',\n cursor: disabled ? 'not-allowed' : 'pointer',\n transition: `all ${durations.quick}ms ${easings.easeOut}`,\n textAlign: 'left',\n justifyContent: collapsed ? 'center' : 'flex-start',\n ...style,\n }\n\n const iconStyle: CSSProperties = {\n width: config.iconSize,\n height: config.iconSize,\n flexShrink: 0,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }\n\n const badgeStyle: CSSProperties = {\n marginLeft: 'auto',\n }\n\n // Roving tabindex: before any item is focused (focusedIndex -1), Tab must\n // still be able to enter the menu through the active item or the first one.\n const isTabStop =\n focusedIndex >= 0 ? focusedIndex === itemIndex : activeItem ? isActive : itemIndex === 0\n\n return (\n <button\n ref={ref}\n type=\"button\"\n role=\"menuitem\"\n disabled={disabled}\n tabIndex={isTabStop ? 0 : -1}\n className={cx('brycks-menu-item', isActive && 'brycks-menu-item--active', className)}\n style={itemStyle}\n onClick={handleClick}\n onFocus={handleFocus}\n onMouseEnter={(e) => {\n if (!disabled && !isActive) {\n e.currentTarget.style.backgroundColor = 'var(--brycks-background-muted)'\n }\n }}\n onMouseLeave={(e) => {\n if (!isActive) {\n e.currentTarget.style.backgroundColor = 'transparent'\n }\n }}\n title={collapsed ? String(children) : undefined}\n {...props}\n >\n {icon && <span style={iconStyle}>{icon}</span>}\n {!collapsed && <span style={{ flex: 1 }}>{children}</span>}\n {!collapsed && badge && <span style={badgeStyle}>{badge}</span>}\n </button>\n )\n})\n\nMenuItem.displayName = 'MenuItem'\n\n// MenuGroup\nexport interface MenuGroupProps extends HTMLAttributes<HTMLDivElement> {\n /** Group label */\n label?: string\n /** Custom class name */\n className?: string\n}\n\nexport const MenuGroup = forwardRef<HTMLDivElement, MenuGroupProps>(function MenuGroup(\n { label, className, style, children, ...props },\n ref\n) {\n const { collapsed } = useMenuContext()\n\n const groupStyle: CSSProperties = {\n display: 'flex',\n flexDirection: 'column',\n gap: spacing[0.5],\n ...style,\n }\n\n const labelStyle: CSSProperties = {\n padding: `${spacing[3]}px ${spacing[3]}px ${componentPaddingY.sm}px ${spacing[3]}px`,\n fontSize: fontSizes.xs,\n fontWeight: 600,\n color: 'var(--brycks-foreground-muted)',\n textTransform: 'uppercase',\n letterSpacing: '0.05em',\n }\n\n return (\n <div ref={ref} className={cx('brycks-menu-group', className)} style={groupStyle} {...props}>\n {label && !collapsed && <div style={labelStyle}>{label}</div>}\n {children}\n </div>\n )\n})\n\nMenuGroup.displayName = 'MenuGroup'\n\n// MenuDivider\nexport interface MenuDividerProps extends HTMLAttributes<HTMLDivElement> {\n /** Custom class name */\n className?: string\n}\n\nexport const MenuDivider = forwardRef<HTMLDivElement, MenuDividerProps>(function MenuDivider(\n { className, style, ...props },\n ref\n) {\n const dividerStyle: CSSProperties = {\n height: 1,\n backgroundColor: 'var(--brycks-border-muted)',\n margin: `${spacing[2]}px 0`,\n ...style,\n }\n\n return (\n <div\n ref={ref}\n role=\"separator\"\n className={cx('brycks-menu-divider', className)}\n style={dividerStyle}\n {...props}\n />\n )\n})\n\nMenuDivider.displayName = 'MenuDivider'\n"],"names":["MenuContext","createContext","useMenuContext","context","useContext","Menu","forwardRef","controlledActiveItem","onChange","size","collapsed","className","style","children","testId","props","ref","internalActiveItem","setInternalActiveItem","useState","focusedIndex","setFocusedIndex","itemsRef","useRef","menuRef","activeItem","setActiveItem","value","registerItem","useCallback","index","handleKeyDown","items","currentIndex","nextIndex","prevIndex","menuStyle","spacing","jsx","node","cx","sizeConfig","componentHeights","fontSizes","iconSizes","componentGap","componentPaddingX","MenuItem","icon","badge","disabled","onClick","isActive","config","itemIndex","handleClick","handleFocus","itemStyle","durations","easings","iconStyle","badgeStyle","isTabStop","jsxs","e","MenuGroup","label","groupStyle","labelStyle","componentPaddingY","MenuDivider","dividerStyle"],"mappings":"gZAmCMA,EAAcC,EAAAA,cAAuC,IAAI,EAE/D,SAASC,GAAiB,CACxB,MAAMC,EAAUC,EAAAA,WAAWJ,CAAW,EACtC,GAAI,CAACG,EACH,MAAM,IAAI,MAAM,4CAA4C,EAE9D,OAAOA,CACT,CAiBO,MAAME,EAAOC,EAAAA,WAAmC,SACrD,CACE,WAAYC,EACZ,SAAAC,EACA,KAAAC,EAAO,KACP,UAAAC,EAAY,GACZ,UAAAC,EACA,MAAAC,EACA,SAAAC,EACA,OAAAC,EACA,GAAGC,CACL,EACAC,EACA,CACA,KAAM,CAACC,EAAoBC,CAAqB,EAAIC,EAAAA,SAAwB,IAAI,EAC1E,CAACC,EAAcC,CAAe,EAAIF,EAAAA,SAAS,EAAE,EAC7CG,EAAWC,EAAAA,OAAiB,EAAE,EAC9BC,EAAUD,EAAAA,OAAoB,IAAI,EAClCE,EAAalB,IAAyB,OAAYA,EAAuBU,EAEzES,EAAiBC,GAAyB,CAC1CpB,IAAyB,QAC3BW,EAAsBS,CAAK,EAE7BnB,IAAWmB,CAAK,CAClB,EAGMC,EAAeC,cAAaF,GAAkB,CAClD,MAAMG,EAAQR,EAAS,QAAQ,QAAQK,CAAK,EAC5C,OAAIG,IAAU,IACZR,EAAS,QAAQ,KAAKK,CAAK,EACpBL,EAAS,QAAQ,OAAS,GAE5BQ,CACT,EAAG,CAAA,CAAE,EAGCC,EAAgBF,cAAa,GAAkC,CACnE,MAAMG,EAAQR,EAAQ,SAAS,iBAAoC,kCAAkC,EACrG,GAAI,CAACQ,GAAO,OAAQ,OAEpB,MAAMC,EAAeb,GAAgB,EAAIA,EAAe,EAExD,OAAQ,EAAE,IAAA,CACR,IAAK,YAAa,CAChB,EAAE,eAAA,EACF,MAAMc,GAAaD,EAAe,GAAKD,EAAM,OAC7CX,EAAgBa,CAAS,EACzBF,EAAME,CAAS,GAAG,MAAA,EAClB,KACF,CACA,IAAK,UAAW,CACd,EAAE,eAAA,EACF,MAAMC,GAAaF,EAAe,EAAID,EAAM,QAAUA,EAAM,OAC5DX,EAAgBc,CAAS,EACzBH,EAAMG,CAAS,GAAG,MAAA,EAClB,KACF,CACA,IAAK,OACH,EAAE,eAAA,EACFd,EAAgB,CAAC,EACjBW,EAAM,CAAC,GAAG,MAAA,EACV,MACF,IAAK,MACH,EAAE,eAAA,EACFX,EAAgBW,EAAM,OAAS,CAAC,EAChCA,EAAMA,EAAM,OAAS,CAAC,GAAG,MAAA,EACzB,KAAA,CAEN,EAAG,CAACZ,CAAY,CAAC,EAEXgB,EAA2B,CAC/B,QAAS,OACT,cAAe,SACf,IAAKC,EAAAA,QAAQ,EAAG,EAChB,QAASA,EAAAA,QAAQ,CAAC,EAClB,GAAGzB,CAAA,EAGL,OACE0B,EAAAA,IAACtC,EAAY,SAAZ,CAAqB,MAAO,CAAE,KAAAS,EAAM,WAAAgB,EAAY,cAAAC,EAAe,UAAAhB,EAAW,aAAAU,EAAc,gBAAAC,EAAiB,aAAAO,GACxG,SAAAU,EAAAA,IAAC,MAAA,CACC,IAAMC,GAAS,CACZf,EAAuD,QAAUe,EAC9D,OAAOvB,GAAQ,WAAYA,EAAIuB,CAAI,EAC9BvB,IAAMA,EAAmD,QAAUuB,EAC9E,EACA,KAAK,OACL,UAAWC,EAAAA,GAAG,cAAe,gBAAgB/B,CAAI,GAAIC,GAAa,yBAA0BC,CAAS,EACrG,MAAOyB,EACP,UAAWL,EACX,cAAajB,EACZ,GAAGC,EAEH,SAAAF,CAAA,CAAA,EAEL,CAEJ,CAAC,EAEDR,EAAK,YAAc,OAkBnB,MAAMoC,EAAwG,CAC5G,GAAI,CAAE,OAAQC,EAAAA,iBAAiB,GAAI,SAAUC,EAAAA,UAAU,KAAO,EAAG,SAAUC,EAAAA,UAAU,GAAI,QAASC,EAAAA,aAAa,EAAA,EAC/G,GAAI,CAAE,OAAQH,EAAAA,iBAAiB,GAAI,SAAUC,EAAAA,UAAU,KAAM,SAAUC,EAAAA,UAAU,GAAK,EAAG,QAASE,EAAAA,kBAAkB,EAAA,EACpH,GAAI,CAAE,OAAQJ,EAAAA,iBAAiB,GAAI,SAAUC,EAAAA,UAAU,GAAI,SAAUC,EAAAA,UAAU,GAAI,QAASP,EAAAA,QAAQ,GAAG,CAAA,CACzG,EAEaU,EAAWzC,EAAAA,WAA6C,SACnE,CAAE,MAAAqB,EAAO,KAAAqB,EAAM,MAAAC,EAAO,SAAAC,EAAW,GAAO,QAAAC,EAAS,UAAAxC,EAAW,MAAAC,EAAO,SAAAC,EAAU,GAAGE,CAAA,EAChFC,EACA,CACA,KAAM,CAAE,KAAAP,EAAM,WAAAgB,EAAY,cAAAC,EAAe,UAAAhB,EAAW,aAAAU,EAAc,gBAAAC,EAAiB,aAAAO,CAAA,EAAiB1B,EAAA,EAC9FkD,EAAW3B,IAAeE,EAC1B0B,EAASZ,EAAWhC,CAAI,EACxB6C,EAAY1B,EAAaD,CAAK,EAE9B4B,EAAc,IAAM,CACpBL,IACJxB,EAAcC,CAAK,EACnBwB,IAAUxB,CAAK,EACjB,EAEM6B,EAAc,IAAM,CACxBnC,EAAgBiC,CAAS,CAC3B,EAEMG,EAA2B,CAC/B,QAAS,OACT,WAAY,SACZ,IAAKZ,EAAAA,aAAa,GAClB,MAAO,OACP,UAAWQ,EAAO,OAClB,QAAS3C,EAAY2C,EAAO,QAAU,KAAKA,EAAO,OAAO,KACzD,SAAUA,EAAO,SACjB,WAAYD,EAAW,IAAM,IAC7B,MAAOF,EACH,oCACAE,EACA,gCACA,mCACJ,gBAAiBA,EAAW,8BAAgC,cAC5D,OAAQ,OACR,aAAc,0BACd,OAAQF,EAAW,cAAgB,UACnC,WAAY,OAAOQ,EAAAA,UAAU,KAAK,MAAMC,EAAAA,QAAQ,OAAO,GACvD,UAAW,OACX,eAAgBjD,EAAY,SAAW,aACvC,GAAGE,CAAA,EAGCgD,EAA2B,CAC/B,MAAOP,EAAO,SACd,OAAQA,EAAO,SACf,WAAY,EACZ,QAAS,OACT,WAAY,SACZ,eAAgB,QAAA,EAGZQ,EAA4B,CAChC,WAAY,MAAA,EAKRC,EACJ1C,GAAgB,EAAIA,IAAiBkC,EAAY7B,EAAa2B,EAAWE,IAAc,EAEzF,OACES,EAAAA,KAAC,SAAA,CACC,IAAA/C,EACA,KAAK,SACL,KAAK,WACL,SAAAkC,EACA,SAAUY,EAAY,EAAI,GAC1B,UAAWtB,EAAAA,GAAG,mBAAoBY,GAAY,2BAA4BzC,CAAS,EACnF,MAAO8C,EACP,QAASF,EACT,QAASC,EACT,aAAeQ,GAAM,CACf,CAACd,GAAY,CAACE,IAChBY,EAAE,cAAc,MAAM,gBAAkB,iCAE5C,EACA,aAAeA,GAAM,CACdZ,IACHY,EAAE,cAAc,MAAM,gBAAkB,cAE5C,EACA,MAAOtD,EAAY,OAAOG,CAAQ,EAAI,OACrC,GAAGE,EAEH,SAAA,CAAAiC,GAAQV,EAAAA,IAAC,OAAA,CAAK,MAAOsB,EAAY,SAAAZ,EAAK,EACtC,CAACtC,GAAa4B,MAAC,OAAA,CAAK,MAAO,CAAE,KAAM,GAAM,SAAAzB,EAAS,EAClD,CAACH,GAAauC,SAAU,OAAA,CAAK,MAAOY,EAAa,SAAAZ,CAAA,CAAM,CAAA,CAAA,CAAA,CAG9D,CAAC,EAEDF,EAAS,YAAc,WAUhB,MAAMkB,EAAY3D,EAAAA,WAA2C,SAClE,CAAE,MAAA4D,EAAO,UAAAvD,EAAW,MAAAC,EAAO,SAAAC,EAAU,GAAGE,CAAA,EACxCC,EACA,CACA,KAAM,CAAE,UAAAN,CAAA,EAAcR,EAAA,EAEhBiE,EAA4B,CAChC,QAAS,OACT,cAAe,SACf,IAAK9B,EAAAA,QAAQ,EAAG,EAChB,GAAGzB,CAAA,EAGCwD,EAA4B,CAChC,QAAS,GAAG/B,EAAAA,QAAQ,CAAC,CAAC,MAAMA,EAAAA,QAAQ,CAAC,CAAC,MAAMgC,EAAAA,kBAAkB,EAAE,MAAMhC,EAAAA,QAAQ,CAAC,CAAC,KAChF,SAAUM,EAAAA,UAAU,GACpB,WAAY,IACZ,MAAO,iCACP,cAAe,YACf,cAAe,QAAA,EAGjB,OACEoB,EAAAA,KAAC,MAAA,CAAI,IAAA/C,EAAU,UAAWwB,EAAAA,GAAG,oBAAqB7B,CAAS,EAAG,MAAOwD,EAAa,GAAGpD,EAClF,SAAA,CAAAmD,GAAS,CAACxD,GAAa4B,EAAAA,IAAC,MAAA,CAAI,MAAO8B,EAAa,SAAAF,EAAM,EACtDrD,CAAA,EACH,CAEJ,CAAC,EAEDoD,EAAU,YAAc,YAQjB,MAAMK,EAAchE,EAAAA,WAA6C,SACtE,CAAE,UAAAK,EAAW,MAAAC,EAAO,GAAGG,CAAA,EACvBC,EACA,CACA,MAAMuD,EAA8B,CAClC,OAAQ,EACR,gBAAiB,6BACjB,OAAQ,GAAGlC,EAAAA,QAAQ,CAAC,CAAC,OACrB,GAAGzB,CAAA,EAGL,OACE0B,EAAAA,IAAC,MAAA,CACC,IAAAtB,EACA,KAAK,YACL,UAAWwB,EAAAA,GAAG,sBAAuB7B,CAAS,EAC9C,MAAO4D,EACN,GAAGxD,CAAA,CAAA,CAGV,CAAC,EAEDuD,EAAY,YAAc"}
1
+ {"version":3,"file":"Menu.cjs","sources":["../../../../src/components/navigation/Menu/Menu.tsx"],"sourcesContent":["/**\n * Menu Component\n *\n * A vertical navigation menu with support for nested items.\n * Suitable for sidebars and navigation panels.\n */\n\nimport {\n forwardRef,\n useState,\n useRef,\n useCallback,\n createContext,\n useContext,\n type ReactNode,\n type HTMLAttributes,\n type KeyboardEvent,\n} from 'react'\nimport { cx } from '../../../utils/styles'\n\nexport type MenuSize = 'sm' | 'md' | 'lg'\n\ninterface MenuContextValue {\n size: MenuSize\n activeItem: string | null\n setActiveItem: (value: string | null) => void\n collapsed: boolean\n focusedIndex: number\n setFocusedIndex: (index: number) => void\n registerItem: (value: string) => number\n}\n\nconst MenuContext = createContext<MenuContextValue | null>(null)\n\nfunction useMenuContext() {\n const context = useContext(MenuContext)\n if (!context) {\n throw new Error('Menu components must be used within a Menu')\n }\n return context\n}\n\nexport interface MenuProps extends Omit<HTMLAttributes<HTMLElement>, 'onChange'> {\n /** Currently active item */\n activeItem?: string | null\n /** Callback when active item changes */\n onChange?: (value: string | null) => void\n /** Menu size */\n size?: MenuSize\n /** Whether the menu is collapsed (icons only) */\n collapsed?: boolean\n /** Custom class name */\n className?: string\n /** Test ID */\n testId?: string\n}\n\nexport const Menu = forwardRef<HTMLElement, MenuProps>(function Menu(\n {\n activeItem: controlledActiveItem,\n onChange,\n size = 'md',\n collapsed = false,\n className,\n style,\n children,\n testId,\n ...props\n },\n ref\n) {\n const [internalActiveItem, setInternalActiveItem] = useState<string | null>(null)\n const [focusedIndex, setFocusedIndex] = useState(-1)\n const itemsRef = useRef<string[]>([])\n const menuRef = useRef<HTMLElement>(null)\n const activeItem = controlledActiveItem !== undefined ? controlledActiveItem : internalActiveItem\n\n const setActiveItem = (value: string | null) => {\n if (controlledActiveItem === undefined) {\n setInternalActiveItem(value)\n }\n onChange?.(value)\n }\n\n // Register items for keyboard navigation\n const registerItem = useCallback((value: string) => {\n const index = itemsRef.current.indexOf(value)\n if (index === -1) {\n itemsRef.current.push(value)\n return itemsRef.current.length - 1\n }\n return index\n }, [])\n\n // Keyboard navigation\n const handleKeyDown = useCallback((e: KeyboardEvent<HTMLElement>) => {\n const items = menuRef.current?.querySelectorAll<HTMLButtonElement>('[role=\"menuitem\"]:not(:disabled)')\n if (!items?.length) return\n\n const currentIndex = focusedIndex >= 0 ? focusedIndex : 0\n\n switch (e.key) {\n case 'ArrowDown': {\n e.preventDefault()\n const nextIndex = (currentIndex + 1) % items.length\n setFocusedIndex(nextIndex)\n items[nextIndex]?.focus()\n break\n }\n case 'ArrowUp': {\n e.preventDefault()\n const prevIndex = (currentIndex - 1 + items.length) % items.length\n setFocusedIndex(prevIndex)\n items[prevIndex]?.focus()\n break\n }\n case 'Home':\n e.preventDefault()\n setFocusedIndex(0)\n items[0]?.focus()\n break\n case 'End':\n e.preventDefault()\n setFocusedIndex(items.length - 1)\n items[items.length - 1]?.focus()\n break\n }\n }, [focusedIndex])\n\n return (\n <MenuContext.Provider value={{ size, activeItem, setActiveItem, collapsed, focusedIndex, setFocusedIndex, registerItem }}>\n <nav\n ref={(node) => {\n (menuRef as React.MutableRefObject<HTMLElement | null>).current = node\n if (typeof ref === 'function') ref(node)\n else if (ref) (ref as React.MutableRefObject<HTMLElement | null>).current = node\n }}\n role=\"menu\"\n className={cx('brycks-menu', `brycks-menu--${size}`, collapsed && 'brycks-menu--collapsed', className)}\n style={style}\n onKeyDown={handleKeyDown}\n data-testid={testId}\n {...props}\n >\n {children}\n </nav>\n </MenuContext.Provider>\n )\n})\n\nMenu.displayName = 'Menu'\n\n// MenuItem\nexport interface MenuItemProps extends Omit<HTMLAttributes<HTMLButtonElement>, 'onClick'> {\n /** Item value (unique identifier) */\n value: string\n /** Icon before the label */\n icon?: ReactNode\n /** Badge/count after the label */\n badge?: ReactNode\n /** Whether the item is disabled */\n disabled?: boolean\n /** Callback when clicked */\n onClick?: (value: string) => void\n /** Custom class name */\n className?: string\n}\n\nexport const MenuItem = forwardRef<HTMLButtonElement, MenuItemProps>(function MenuItem(\n { value, icon, badge, disabled = false, onClick, className, style, children, ...props },\n ref\n) {\n const { activeItem, setActiveItem, collapsed, focusedIndex, setFocusedIndex, registerItem } = useMenuContext()\n const isActive = activeItem === value\n const itemIndex = registerItem(value)\n\n const handleClick = () => {\n if (disabled) return\n setActiveItem(value)\n onClick?.(value)\n }\n\n const handleFocus = () => {\n setFocusedIndex(itemIndex)\n }\n\n // Roving tabindex: before any item is focused (focusedIndex -1), Tab must\n // still be able to enter the menu through the active item or the first one.\n const isTabStop =\n focusedIndex >= 0 ? focusedIndex === itemIndex : activeItem ? isActive : itemIndex === 0\n\n return (\n <button\n ref={ref}\n type=\"button\"\n role=\"menuitem\"\n disabled={disabled}\n tabIndex={isTabStop ? 0 : -1}\n className={cx('brycks-menu-item', isActive && 'brycks-menu-item--active', className)}\n style={style}\n onClick={handleClick}\n onFocus={handleFocus}\n title={collapsed ? String(children) : undefined}\n {...props}\n >\n {icon && <span className=\"brycks-menu-item__icon\">{icon}</span>}\n {!collapsed && <span className=\"brycks-menu-item__label\">{children}</span>}\n {!collapsed && badge && <span className=\"brycks-menu-item__badge\">{badge}</span>}\n </button>\n )\n})\n\nMenuItem.displayName = 'MenuItem'\n\n// MenuGroup\nexport interface MenuGroupProps extends HTMLAttributes<HTMLDivElement> {\n /** Group label */\n label?: string\n /** Custom class name */\n className?: string\n}\n\nexport const MenuGroup = forwardRef<HTMLDivElement, MenuGroupProps>(function MenuGroup(\n { label, className, style, children, ...props },\n ref\n) {\n const { collapsed } = useMenuContext()\n\n return (\n <div ref={ref} className={cx('brycks-menu-group', className)} style={style} {...props}>\n {label && !collapsed && <div className=\"brycks-menu-group__label\">{label}</div>}\n {children}\n </div>\n )\n})\n\nMenuGroup.displayName = 'MenuGroup'\n\n// MenuDivider\nexport interface MenuDividerProps extends HTMLAttributes<HTMLDivElement> {\n /** Custom class name */\n className?: string\n}\n\nexport const MenuDivider = forwardRef<HTMLDivElement, MenuDividerProps>(function MenuDivider(\n { className, style, ...props },\n ref\n) {\n return (\n <div\n ref={ref}\n role=\"separator\"\n className={cx('brycks-menu-divider', className)}\n style={style}\n {...props}\n />\n )\n})\n\nMenuDivider.displayName = 'MenuDivider'\n"],"names":["MenuContext","createContext","useMenuContext","context","useContext","Menu","forwardRef","controlledActiveItem","onChange","size","collapsed","className","style","children","testId","props","ref","internalActiveItem","setInternalActiveItem","useState","focusedIndex","setFocusedIndex","itemsRef","useRef","menuRef","activeItem","setActiveItem","value","registerItem","useCallback","index","handleKeyDown","items","currentIndex","nextIndex","prevIndex","jsx","node","cx","MenuItem","icon","badge","disabled","onClick","isActive","itemIndex","handleClick","handleFocus","isTabStop","jsxs","MenuGroup","label","MenuDivider"],"mappings":"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"}
@@ -1,190 +1,125 @@
1
- import { jsx as m, jsxs as E } from "react/jsx-runtime";
2
- import { forwardRef as C, useState as F, useRef as G, useCallback as T, createContext as L, useContext as O } from "react";
3
- import { cx as w } from "../../../utils/styles.js";
4
- import { iconSizes as R, componentHeights as j, componentPaddingX as W, componentGap as H, componentPaddingY as U } from "../../../design-system/primitives/sizing.js";
5
- import { spacing as u } from "../../../design-system/tokens/spacing.js";
6
- import { durations as X, easings as Y } from "../../../design-system/tokens/motion.js";
7
- import { fontSizes as z } from "../../../design-system/tokens/typography.js";
8
- const P = L(null);
9
- function q() {
10
- const f = O(P);
11
- if (!f)
1
+ import { jsx as i, jsxs as R } from "react/jsx-runtime";
2
+ import { forwardRef as k, useState as C, useRef as A, useCallback as F, createContext as j, useContext as E } from "react";
3
+ import { cx as M } from "../../../utils/styles.js";
4
+ const S = j(null);
5
+ function G() {
6
+ const a = E(S);
7
+ if (!a)
12
8
  throw new Error("Menu components must be used within a Menu");
13
- return f;
9
+ return a;
14
10
  }
15
- const B = C(function({
11
+ const K = k(function({
16
12
  activeItem: n,
17
13
  onChange: c,
18
14
  size: s = "md",
19
15
  collapsed: r = !1,
20
16
  className: l,
21
- style: h,
22
- children: b,
23
- testId: p,
24
- ...k
25
- }, g) {
26
- const [D, S] = F(null), [y, o] = F(-1), x = G([]), I = G(null), $ = n !== void 0 ? n : D, i = (e) => {
27
- n === void 0 && S(e), c?.(e);
28
- }, a = T((e) => {
29
- const t = x.current.indexOf(e);
30
- return t === -1 ? (x.current.push(e), x.current.length - 1) : t;
31
- }, []), v = T((e) => {
17
+ style: d,
18
+ children: f,
19
+ testId: y,
20
+ ...g
21
+ }, m) {
22
+ const [v, N] = C(null), [o, u] = C(-1), p = A([]), I = A(null), h = n !== void 0 ? n : v, b = (e) => {
23
+ n === void 0 && N(e), c?.(e);
24
+ }, w = F((e) => {
25
+ const t = p.current.indexOf(e);
26
+ return t === -1 ? (p.current.push(e), p.current.length - 1) : t;
27
+ }, []), D = F((e) => {
32
28
  const t = I.current?.querySelectorAll('[role="menuitem"]:not(:disabled)');
33
29
  if (!t?.length) return;
34
- const M = y >= 0 ? y : 0;
30
+ const _ = o >= 0 ? o : 0;
35
31
  switch (e.key) {
36
32
  case "ArrowDown": {
37
33
  e.preventDefault();
38
- const d = (M + 1) % t.length;
39
- o(d), t[d]?.focus();
34
+ const x = (_ + 1) % t.length;
35
+ u(x), t[x]?.focus();
40
36
  break;
41
37
  }
42
38
  case "ArrowUp": {
43
39
  e.preventDefault();
44
- const d = (M - 1 + t.length) % t.length;
45
- o(d), t[d]?.focus();
40
+ const x = (_ - 1 + t.length) % t.length;
41
+ u(x), t[x]?.focus();
46
42
  break;
47
43
  }
48
44
  case "Home":
49
- e.preventDefault(), o(0), t[0]?.focus();
45
+ e.preventDefault(), u(0), t[0]?.focus();
50
46
  break;
51
47
  case "End":
52
- e.preventDefault(), o(t.length - 1), t[t.length - 1]?.focus();
48
+ e.preventDefault(), u(t.length - 1), t[t.length - 1]?.focus();
53
49
  break;
54
50
  }
55
- }, [y]), N = {
56
- display: "flex",
57
- flexDirection: "column",
58
- gap: u[0.5],
59
- padding: u[2],
60
- ...h
61
- };
62
- return /* @__PURE__ */ m(P.Provider, { value: { size: s, activeItem: $, setActiveItem: i, collapsed: r, focusedIndex: y, setFocusedIndex: o, registerItem: a }, children: /* @__PURE__ */ m(
51
+ }, [o]);
52
+ return /* @__PURE__ */ i(S.Provider, { value: { size: s, activeItem: h, setActiveItem: b, collapsed: r, focusedIndex: o, setFocusedIndex: u, registerItem: w }, children: /* @__PURE__ */ i(
63
53
  "nav",
64
54
  {
65
55
  ref: (e) => {
66
- I.current = e, typeof g == "function" ? g(e) : g && (g.current = e);
56
+ I.current = e, typeof m == "function" ? m(e) : m && (m.current = e);
67
57
  },
68
58
  role: "menu",
69
- className: w("brycks-menu", `brycks-menu--${s}`, r && "brycks-menu--collapsed", l),
70
- style: N,
71
- onKeyDown: v,
72
- "data-testid": p,
73
- ...k,
74
- children: b
59
+ className: M("brycks-menu", `brycks-menu--${s}`, r && "brycks-menu--collapsed", l),
60
+ style: d,
61
+ onKeyDown: D,
62
+ "data-testid": y,
63
+ ...g,
64
+ children: f
75
65
  }
76
66
  ) });
77
67
  });
78
- B.displayName = "Menu";
79
- const J = {
80
- sm: { height: j.sm, fontSize: z.base - 1, iconSize: R.sm, padding: H.lg },
81
- md: { height: j.md, fontSize: z.base, iconSize: R.md - 2, padding: W.sm },
82
- lg: { height: j.lg, fontSize: z.md, iconSize: R.md, padding: u[3.5] }
83
- }, Q = C(function({ value: n, icon: c, badge: s, disabled: r = !1, onClick: l, className: h, style: b, children: p, ...k }, g) {
84
- const { size: D, activeItem: S, setActiveItem: y, collapsed: o, focusedIndex: x, setFocusedIndex: I, registerItem: $ } = q(), i = S === n, a = J[D], v = $(n), N = () => {
85
- r || (y(n), l?.(n));
86
- }, e = () => {
87
- I(v);
88
- }, t = {
89
- display: "flex",
90
- alignItems: "center",
91
- gap: H.lg,
92
- width: "100%",
93
- minHeight: a.height,
94
- padding: o ? a.padding : `0 ${a.padding}px`,
95
- fontSize: a.fontSize,
96
- fontWeight: i ? 600 : 500,
97
- color: r ? "var(--brycks-foreground-disabled)" : i ? "var(--brycks-primary-default)" : "var(--brycks-foreground-default)",
98
- backgroundColor: i ? "var(--brycks-primary-muted)" : "transparent",
99
- border: "none",
100
- borderRadius: "var(--brycks-radius-md)",
101
- cursor: r ? "not-allowed" : "pointer",
102
- transition: `all ${X.quick}ms ${Y.easeOut}`,
103
- textAlign: "left",
104
- justifyContent: o ? "center" : "flex-start",
105
- ...b
106
- }, M = {
107
- width: a.iconSize,
108
- height: a.iconSize,
109
- flexShrink: 0,
110
- display: "flex",
111
- alignItems: "center",
112
- justifyContent: "center"
113
- }, d = {
114
- marginLeft: "auto"
115
- }, K = x >= 0 ? x === v : S ? i : v === 0;
116
- return /* @__PURE__ */ E(
68
+ K.displayName = "Menu";
69
+ const q = k(function({ value: n, icon: c, badge: s, disabled: r = !1, onClick: l, className: d, style: f, children: y, ...g }, m) {
70
+ const { activeItem: v, setActiveItem: N, collapsed: o, focusedIndex: u, setFocusedIndex: p, registerItem: I } = G(), h = v === n, b = I(n), w = () => {
71
+ r || (N(n), l?.(n));
72
+ }, D = () => {
73
+ p(b);
74
+ }, e = u >= 0 ? u === b : v ? h : b === 0;
75
+ return /* @__PURE__ */ R(
117
76
  "button",
118
77
  {
119
- ref: g,
78
+ ref: m,
120
79
  type: "button",
121
80
  role: "menuitem",
122
81
  disabled: r,
123
- tabIndex: K ? 0 : -1,
124
- className: w("brycks-menu-item", i && "brycks-menu-item--active", h),
125
- style: t,
126
- onClick: N,
127
- onFocus: e,
128
- onMouseEnter: (A) => {
129
- !r && !i && (A.currentTarget.style.backgroundColor = "var(--brycks-background-muted)");
130
- },
131
- onMouseLeave: (A) => {
132
- i || (A.currentTarget.style.backgroundColor = "transparent");
133
- },
134
- title: o ? String(p) : void 0,
135
- ...k,
82
+ tabIndex: e ? 0 : -1,
83
+ className: M("brycks-menu-item", h && "brycks-menu-item--active", d),
84
+ style: f,
85
+ onClick: w,
86
+ onFocus: D,
87
+ title: o ? String(y) : void 0,
88
+ ...g,
136
89
  children: [
137
- c && /* @__PURE__ */ m("span", { style: M, children: c }),
138
- !o && /* @__PURE__ */ m("span", { style: { flex: 1 }, children: p }),
139
- !o && s && /* @__PURE__ */ m("span", { style: d, children: s })
90
+ c && /* @__PURE__ */ i("span", { className: "brycks-menu-item__icon", children: c }),
91
+ !o && /* @__PURE__ */ i("span", { className: "brycks-menu-item__label", children: y }),
92
+ !o && s && /* @__PURE__ */ i("span", { className: "brycks-menu-item__badge", children: s })
140
93
  ]
141
94
  }
142
95
  );
143
96
  });
144
- Q.displayName = "MenuItem";
145
- const V = C(function({ label: n, className: c, style: s, children: r, ...l }, h) {
146
- const { collapsed: b } = q(), p = {
147
- display: "flex",
148
- flexDirection: "column",
149
- gap: u[0.5],
150
- ...s
151
- }, k = {
152
- padding: `${u[3]}px ${u[3]}px ${U.sm}px ${u[3]}px`,
153
- fontSize: z.xs,
154
- fontWeight: 600,
155
- color: "var(--brycks-foreground-muted)",
156
- textTransform: "uppercase",
157
- letterSpacing: "0.05em"
158
- };
159
- return /* @__PURE__ */ E("div", { ref: h, className: w("brycks-menu-group", c), style: p, ...l, children: [
160
- n && !b && /* @__PURE__ */ m("div", { style: k, children: n }),
97
+ q.displayName = "MenuItem";
98
+ const H = k(function({ label: n, className: c, style: s, children: r, ...l }, d) {
99
+ const { collapsed: f } = G();
100
+ return /* @__PURE__ */ R("div", { ref: d, className: M("brycks-menu-group", c), style: s, ...l, children: [
101
+ n && !f && /* @__PURE__ */ i("div", { className: "brycks-menu-group__label", children: n }),
161
102
  r
162
103
  ] });
163
104
  });
164
- V.displayName = "MenuGroup";
165
- const Z = C(function({ className: n, style: c, ...s }, r) {
166
- const l = {
167
- height: 1,
168
- backgroundColor: "var(--brycks-border-muted)",
169
- margin: `${u[2]}px 0`,
170
- ...c
171
- };
172
- return /* @__PURE__ */ m(
105
+ H.displayName = "MenuGroup";
106
+ const O = k(function({ className: n, style: c, ...s }, r) {
107
+ return /* @__PURE__ */ i(
173
108
  "div",
174
109
  {
175
110
  ref: r,
176
111
  role: "separator",
177
- className: w("brycks-menu-divider", n),
178
- style: l,
112
+ className: M("brycks-menu-divider", n),
113
+ style: c,
179
114
  ...s
180
115
  }
181
116
  );
182
117
  });
183
- Z.displayName = "MenuDivider";
118
+ O.displayName = "MenuDivider";
184
119
  export {
185
- B as Menu,
186
- Z as MenuDivider,
187
- V as MenuGroup,
188
- Q as MenuItem
120
+ K as Menu,
121
+ O as MenuDivider,
122
+ H as MenuGroup,
123
+ q as MenuItem
189
124
  };
190
125
  //# sourceMappingURL=Menu.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Menu.js","sources":["../../../../src/components/navigation/Menu/Menu.tsx"],"sourcesContent":["/**\n * Menu Component\n *\n * A vertical navigation menu with support for nested items.\n * Suitable for sidebars and navigation panels.\n */\n\nimport {\n forwardRef,\n useState,\n useRef,\n useCallback,\n createContext,\n useContext,\n type CSSProperties,\n type ReactNode,\n type HTMLAttributes,\n type KeyboardEvent,\n} from 'react'\nimport { cx } from '../../../utils/styles'\nimport { spacing, fontSizes, durations, easings } from '../../../design-system'\nimport { componentHeights, componentGap, componentPaddingX, componentPaddingY, iconSizes } from '../../../design-system/primitives'\n\nexport type MenuSize = 'sm' | 'md' | 'lg'\n\ninterface MenuContextValue {\n size: MenuSize\n activeItem: string | null\n setActiveItem: (value: string | null) => void\n collapsed: boolean\n focusedIndex: number\n setFocusedIndex: (index: number) => void\n registerItem: (value: string) => number\n}\n\nconst MenuContext = createContext<MenuContextValue | null>(null)\n\nfunction useMenuContext() {\n const context = useContext(MenuContext)\n if (!context) {\n throw new Error('Menu components must be used within a Menu')\n }\n return context\n}\n\nexport interface MenuProps extends Omit<HTMLAttributes<HTMLElement>, 'onChange'> {\n /** Currently active item */\n activeItem?: string | null\n /** Callback when active item changes */\n onChange?: (value: string | null) => void\n /** Menu size */\n size?: MenuSize\n /** Whether the menu is collapsed (icons only) */\n collapsed?: boolean\n /** Custom class name */\n className?: string\n /** Test ID */\n testId?: string\n}\n\nexport const Menu = forwardRef<HTMLElement, MenuProps>(function Menu(\n {\n activeItem: controlledActiveItem,\n onChange,\n size = 'md',\n collapsed = false,\n className,\n style,\n children,\n testId,\n ...props\n },\n ref\n) {\n const [internalActiveItem, setInternalActiveItem] = useState<string | null>(null)\n const [focusedIndex, setFocusedIndex] = useState(-1)\n const itemsRef = useRef<string[]>([])\n const menuRef = useRef<HTMLElement>(null)\n const activeItem = controlledActiveItem !== undefined ? controlledActiveItem : internalActiveItem\n\n const setActiveItem = (value: string | null) => {\n if (controlledActiveItem === undefined) {\n setInternalActiveItem(value)\n }\n onChange?.(value)\n }\n\n // Register items for keyboard navigation\n const registerItem = useCallback((value: string) => {\n const index = itemsRef.current.indexOf(value)\n if (index === -1) {\n itemsRef.current.push(value)\n return itemsRef.current.length - 1\n }\n return index\n }, [])\n\n // Keyboard navigation\n const handleKeyDown = useCallback((e: KeyboardEvent<HTMLElement>) => {\n const items = menuRef.current?.querySelectorAll<HTMLButtonElement>('[role=\"menuitem\"]:not(:disabled)')\n if (!items?.length) return\n\n const currentIndex = focusedIndex >= 0 ? focusedIndex : 0\n\n switch (e.key) {\n case 'ArrowDown': {\n e.preventDefault()\n const nextIndex = (currentIndex + 1) % items.length\n setFocusedIndex(nextIndex)\n items[nextIndex]?.focus()\n break\n }\n case 'ArrowUp': {\n e.preventDefault()\n const prevIndex = (currentIndex - 1 + items.length) % items.length\n setFocusedIndex(prevIndex)\n items[prevIndex]?.focus()\n break\n }\n case 'Home':\n e.preventDefault()\n setFocusedIndex(0)\n items[0]?.focus()\n break\n case 'End':\n e.preventDefault()\n setFocusedIndex(items.length - 1)\n items[items.length - 1]?.focus()\n break\n }\n }, [focusedIndex])\n\n const menuStyle: CSSProperties = {\n display: 'flex',\n flexDirection: 'column',\n gap: spacing[0.5],\n padding: spacing[2],\n ...style,\n }\n\n return (\n <MenuContext.Provider value={{ size, activeItem, setActiveItem, collapsed, focusedIndex, setFocusedIndex, registerItem }}>\n <nav\n ref={(node) => {\n (menuRef as React.MutableRefObject<HTMLElement | null>).current = node\n if (typeof ref === 'function') ref(node)\n else if (ref) (ref as React.MutableRefObject<HTMLElement | null>).current = node\n }}\n role=\"menu\"\n className={cx('brycks-menu', `brycks-menu--${size}`, collapsed && 'brycks-menu--collapsed', className)}\n style={menuStyle}\n onKeyDown={handleKeyDown}\n data-testid={testId}\n {...props}\n >\n {children}\n </nav>\n </MenuContext.Provider>\n )\n})\n\nMenu.displayName = 'Menu'\n\n// MenuItem\nexport interface MenuItemProps extends Omit<HTMLAttributes<HTMLButtonElement>, 'onClick'> {\n /** Item value (unique identifier) */\n value: string\n /** Icon before the label */\n icon?: ReactNode\n /** Badge/count after the label */\n badge?: ReactNode\n /** Whether the item is disabled */\n disabled?: boolean\n /** Callback when clicked */\n onClick?: (value: string) => void\n /** Custom class name */\n className?: string\n}\n\nconst sizeConfig: Record<MenuSize, { height: number; fontSize: number; iconSize: number; padding: number }> = {\n sm: { height: componentHeights.sm, fontSize: fontSizes.base - 1, iconSize: iconSizes.sm, padding: componentGap.lg },\n md: { height: componentHeights.md, fontSize: fontSizes.base, iconSize: iconSizes.md - 2, padding: componentPaddingX.sm },\n lg: { height: componentHeights.lg, fontSize: fontSizes.md, iconSize: iconSizes.md, padding: spacing[3.5] },\n}\n\nexport const MenuItem = forwardRef<HTMLButtonElement, MenuItemProps>(function MenuItem(\n { value, icon, badge, disabled = false, onClick, className, style, children, ...props },\n ref\n) {\n const { size, activeItem, setActiveItem, collapsed, focusedIndex, setFocusedIndex, registerItem } = useMenuContext()\n const isActive = activeItem === value\n const config = sizeConfig[size]\n const itemIndex = registerItem(value)\n\n const handleClick = () => {\n if (disabled) return\n setActiveItem(value)\n onClick?.(value)\n }\n\n const handleFocus = () => {\n setFocusedIndex(itemIndex)\n }\n\n const itemStyle: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n gap: componentGap.lg,\n width: '100%',\n minHeight: config.height,\n padding: collapsed ? config.padding : `0 ${config.padding}px`,\n fontSize: config.fontSize,\n fontWeight: isActive ? 600 : 500,\n color: disabled\n ? 'var(--brycks-foreground-disabled)'\n : isActive\n ? 'var(--brycks-primary-default)'\n : 'var(--brycks-foreground-default)',\n backgroundColor: isActive ? 'var(--brycks-primary-muted)' : 'transparent',\n border: 'none',\n borderRadius: 'var(--brycks-radius-md)',\n cursor: disabled ? 'not-allowed' : 'pointer',\n transition: `all ${durations.quick}ms ${easings.easeOut}`,\n textAlign: 'left',\n justifyContent: collapsed ? 'center' : 'flex-start',\n ...style,\n }\n\n const iconStyle: CSSProperties = {\n width: config.iconSize,\n height: config.iconSize,\n flexShrink: 0,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }\n\n const badgeStyle: CSSProperties = {\n marginLeft: 'auto',\n }\n\n // Roving tabindex: before any item is focused (focusedIndex -1), Tab must\n // still be able to enter the menu through the active item or the first one.\n const isTabStop =\n focusedIndex >= 0 ? focusedIndex === itemIndex : activeItem ? isActive : itemIndex === 0\n\n return (\n <button\n ref={ref}\n type=\"button\"\n role=\"menuitem\"\n disabled={disabled}\n tabIndex={isTabStop ? 0 : -1}\n className={cx('brycks-menu-item', isActive && 'brycks-menu-item--active', className)}\n style={itemStyle}\n onClick={handleClick}\n onFocus={handleFocus}\n onMouseEnter={(e) => {\n if (!disabled && !isActive) {\n e.currentTarget.style.backgroundColor = 'var(--brycks-background-muted)'\n }\n }}\n onMouseLeave={(e) => {\n if (!isActive) {\n e.currentTarget.style.backgroundColor = 'transparent'\n }\n }}\n title={collapsed ? String(children) : undefined}\n {...props}\n >\n {icon && <span style={iconStyle}>{icon}</span>}\n {!collapsed && <span style={{ flex: 1 }}>{children}</span>}\n {!collapsed && badge && <span style={badgeStyle}>{badge}</span>}\n </button>\n )\n})\n\nMenuItem.displayName = 'MenuItem'\n\n// MenuGroup\nexport interface MenuGroupProps extends HTMLAttributes<HTMLDivElement> {\n /** Group label */\n label?: string\n /** Custom class name */\n className?: string\n}\n\nexport const MenuGroup = forwardRef<HTMLDivElement, MenuGroupProps>(function MenuGroup(\n { label, className, style, children, ...props },\n ref\n) {\n const { collapsed } = useMenuContext()\n\n const groupStyle: CSSProperties = {\n display: 'flex',\n flexDirection: 'column',\n gap: spacing[0.5],\n ...style,\n }\n\n const labelStyle: CSSProperties = {\n padding: `${spacing[3]}px ${spacing[3]}px ${componentPaddingY.sm}px ${spacing[3]}px`,\n fontSize: fontSizes.xs,\n fontWeight: 600,\n color: 'var(--brycks-foreground-muted)',\n textTransform: 'uppercase',\n letterSpacing: '0.05em',\n }\n\n return (\n <div ref={ref} className={cx('brycks-menu-group', className)} style={groupStyle} {...props}>\n {label && !collapsed && <div style={labelStyle}>{label}</div>}\n {children}\n </div>\n )\n})\n\nMenuGroup.displayName = 'MenuGroup'\n\n// MenuDivider\nexport interface MenuDividerProps extends HTMLAttributes<HTMLDivElement> {\n /** Custom class name */\n className?: string\n}\n\nexport const MenuDivider = forwardRef<HTMLDivElement, MenuDividerProps>(function MenuDivider(\n { className, style, ...props },\n ref\n) {\n const dividerStyle: CSSProperties = {\n height: 1,\n backgroundColor: 'var(--brycks-border-muted)',\n margin: `${spacing[2]}px 0`,\n ...style,\n }\n\n return (\n <div\n ref={ref}\n role=\"separator\"\n className={cx('brycks-menu-divider', className)}\n style={dividerStyle}\n {...props}\n />\n )\n})\n\nMenuDivider.displayName = 'MenuDivider'\n"],"names":["MenuContext","createContext","useMenuContext","context","useContext","Menu","forwardRef","controlledActiveItem","onChange","size","collapsed","className","style","children","testId","props","ref","internalActiveItem","setInternalActiveItem","useState","focusedIndex","setFocusedIndex","itemsRef","useRef","menuRef","activeItem","setActiveItem","value","registerItem","useCallback","index","handleKeyDown","items","currentIndex","nextIndex","prevIndex","menuStyle","spacing","jsx","node","cx","sizeConfig","componentHeights","fontSizes","iconSizes","componentGap","componentPaddingX","MenuItem","icon","badge","disabled","onClick","isActive","config","itemIndex","handleClick","handleFocus","itemStyle","durations","easings","iconStyle","badgeStyle","isTabStop","jsxs","e","MenuGroup","label","groupStyle","labelStyle","componentPaddingY","MenuDivider","dividerStyle"],"mappings":";;;;;;;AAmCA,MAAMA,IAAcC,EAAuC,IAAI;AAE/D,SAASC,IAAiB;AACxB,QAAMC,IAAUC,EAAWJ,CAAW;AACtC,MAAI,CAACG;AACH,UAAM,IAAI,MAAM,4CAA4C;AAE9D,SAAOA;AACT;AAiBO,MAAME,IAAOC,EAAmC,SACrD;AAAA,EACE,YAAYC;AAAA,EACZ,UAAAC;AAAA,EACA,MAAAC,IAAO;AAAA,EACP,WAAAC,IAAY;AAAA,EACZ,WAAAC;AAAA,EACA,OAAAC;AAAA,EACA,UAAAC;AAAA,EACA,QAAAC;AAAA,EACA,GAAGC;AACL,GACAC,GACA;AACA,QAAM,CAACC,GAAoBC,CAAqB,IAAIC,EAAwB,IAAI,GAC1E,CAACC,GAAcC,CAAe,IAAIF,EAAS,EAAE,GAC7CG,IAAWC,EAAiB,EAAE,GAC9BC,IAAUD,EAAoB,IAAI,GAClCE,IAAalB,MAAyB,SAAYA,IAAuBU,GAEzES,IAAgB,CAACC,MAAyB;AAC9C,IAAIpB,MAAyB,UAC3BW,EAAsBS,CAAK,GAE7BnB,IAAWmB,CAAK;AAAA,EAClB,GAGMC,IAAeC,EAAY,CAACF,MAAkB;AAClD,UAAMG,IAAQR,EAAS,QAAQ,QAAQK,CAAK;AAC5C,WAAIG,MAAU,MACZR,EAAS,QAAQ,KAAKK,CAAK,GACpBL,EAAS,QAAQ,SAAS,KAE5BQ;AAAA,EACT,GAAG,CAAA,CAAE,GAGCC,IAAgBF,EAAY,CAAC,MAAkC;AACnE,UAAMG,IAAQR,EAAQ,SAAS,iBAAoC,kCAAkC;AACrG,QAAI,CAACQ,GAAO,OAAQ;AAEpB,UAAMC,IAAeb,KAAgB,IAAIA,IAAe;AAExD,YAAQ,EAAE,KAAA;AAAA,MACR,KAAK,aAAa;AAChB,UAAE,eAAA;AACF,cAAMc,KAAaD,IAAe,KAAKD,EAAM;AAC7C,QAAAX,EAAgBa,CAAS,GACzBF,EAAME,CAAS,GAAG,MAAA;AAClB;AAAA,MACF;AAAA,MACA,KAAK,WAAW;AACd,UAAE,eAAA;AACF,cAAMC,KAAaF,IAAe,IAAID,EAAM,UAAUA,EAAM;AAC5D,QAAAX,EAAgBc,CAAS,GACzBH,EAAMG,CAAS,GAAG,MAAA;AAClB;AAAA,MACF;AAAA,MACA,KAAK;AACH,UAAE,eAAA,GACFd,EAAgB,CAAC,GACjBW,EAAM,CAAC,GAAG,MAAA;AACV;AAAA,MACF,KAAK;AACH,UAAE,eAAA,GACFX,EAAgBW,EAAM,SAAS,CAAC,GAChCA,EAAMA,EAAM,SAAS,CAAC,GAAG,MAAA;AACzB;AAAA,IAAA;AAAA,EAEN,GAAG,CAACZ,CAAY,CAAC,GAEXgB,IAA2B;AAAA,IAC/B,SAAS;AAAA,IACT,eAAe;AAAA,IACf,KAAKC,EAAQ,GAAG;AAAA,IAChB,SAASA,EAAQ,CAAC;AAAA,IAClB,GAAGzB;AAAA,EAAA;AAGL,SACE,gBAAA0B,EAACtC,EAAY,UAAZ,EAAqB,OAAO,EAAE,MAAAS,GAAM,YAAAgB,GAAY,eAAAC,GAAe,WAAAhB,GAAW,cAAAU,GAAc,iBAAAC,GAAiB,cAAAO,KACxG,UAAA,gBAAAU;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAK,CAACC,MAAS;AACZ,QAAAf,EAAuD,UAAUe,GAC9D,OAAOvB,KAAQ,aAAYA,EAAIuB,CAAI,IAC9BvB,MAAMA,EAAmD,UAAUuB;AAAA,MAC9E;AAAA,MACA,MAAK;AAAA,MACL,WAAWC,EAAG,eAAe,gBAAgB/B,CAAI,IAAIC,KAAa,0BAA0BC,CAAS;AAAA,MACrG,OAAOyB;AAAA,MACP,WAAWL;AAAA,MACX,eAAajB;AAAA,MACZ,GAAGC;AAAA,MAEH,UAAAF;AAAA,IAAA;AAAA,EAAA,GAEL;AAEJ,CAAC;AAEDR,EAAK,cAAc;AAkBnB,MAAMoC,IAAwG;AAAA,EAC5G,IAAI,EAAE,QAAQC,EAAiB,IAAI,UAAUC,EAAU,OAAO,GAAG,UAAUC,EAAU,IAAI,SAASC,EAAa,GAAA;AAAA,EAC/G,IAAI,EAAE,QAAQH,EAAiB,IAAI,UAAUC,EAAU,MAAM,UAAUC,EAAU,KAAK,GAAG,SAASE,EAAkB,GAAA;AAAA,EACpH,IAAI,EAAE,QAAQJ,EAAiB,IAAI,UAAUC,EAAU,IAAI,UAAUC,EAAU,IAAI,SAASP,EAAQ,GAAG,EAAA;AACzG,GAEaU,IAAWzC,EAA6C,SACnE,EAAE,OAAAqB,GAAO,MAAAqB,GAAM,OAAAC,GAAO,UAAAC,IAAW,IAAO,SAAAC,GAAS,WAAAxC,GAAW,OAAAC,GAAO,UAAAC,GAAU,GAAGE,EAAA,GAChFC,GACA;AACA,QAAM,EAAE,MAAAP,GAAM,YAAAgB,GAAY,eAAAC,GAAe,WAAAhB,GAAW,cAAAU,GAAc,iBAAAC,GAAiB,cAAAO,EAAA,IAAiB1B,EAAA,GAC9FkD,IAAW3B,MAAeE,GAC1B0B,IAASZ,EAAWhC,CAAI,GACxB6C,IAAY1B,EAAaD,CAAK,GAE9B4B,IAAc,MAAM;AACxB,IAAIL,MACJxB,EAAcC,CAAK,GACnBwB,IAAUxB,CAAK;AAAA,EACjB,GAEM6B,IAAc,MAAM;AACxB,IAAAnC,EAAgBiC,CAAS;AAAA,EAC3B,GAEMG,IAA2B;AAAA,IAC/B,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,KAAKZ,EAAa;AAAA,IAClB,OAAO;AAAA,IACP,WAAWQ,EAAO;AAAA,IAClB,SAAS3C,IAAY2C,EAAO,UAAU,KAAKA,EAAO,OAAO;AAAA,IACzD,UAAUA,EAAO;AAAA,IACjB,YAAYD,IAAW,MAAM;AAAA,IAC7B,OAAOF,IACH,sCACAE,IACA,kCACA;AAAA,IACJ,iBAAiBA,IAAW,gCAAgC;AAAA,IAC5D,QAAQ;AAAA,IACR,cAAc;AAAA,IACd,QAAQF,IAAW,gBAAgB;AAAA,IACnC,YAAY,OAAOQ,EAAU,KAAK,MAAMC,EAAQ,OAAO;AAAA,IACvD,WAAW;AAAA,IACX,gBAAgBjD,IAAY,WAAW;AAAA,IACvC,GAAGE;AAAA,EAAA,GAGCgD,IAA2B;AAAA,IAC/B,OAAOP,EAAO;AAAA,IACd,QAAQA,EAAO;AAAA,IACf,YAAY;AAAA,IACZ,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,gBAAgB;AAAA,EAAA,GAGZQ,IAA4B;AAAA,IAChC,YAAY;AAAA,EAAA,GAKRC,IACJ1C,KAAgB,IAAIA,MAAiBkC,IAAY7B,IAAa2B,IAAWE,MAAc;AAEzF,SACE,gBAAAS;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAA/C;AAAA,MACA,MAAK;AAAA,MACL,MAAK;AAAA,MACL,UAAAkC;AAAA,MACA,UAAUY,IAAY,IAAI;AAAA,MAC1B,WAAWtB,EAAG,oBAAoBY,KAAY,4BAA4BzC,CAAS;AAAA,MACnF,OAAO8C;AAAA,MACP,SAASF;AAAA,MACT,SAASC;AAAA,MACT,cAAc,CAACQ,MAAM;AACnB,QAAI,CAACd,KAAY,CAACE,MAChBY,EAAE,cAAc,MAAM,kBAAkB;AAAA,MAE5C;AAAA,MACA,cAAc,CAACA,MAAM;AACnB,QAAKZ,MACHY,EAAE,cAAc,MAAM,kBAAkB;AAAA,MAE5C;AAAA,MACA,OAAOtD,IAAY,OAAOG,CAAQ,IAAI;AAAA,MACrC,GAAGE;AAAA,MAEH,UAAA;AAAA,QAAAiC,KAAQ,gBAAAV,EAAC,QAAA,EAAK,OAAOsB,GAAY,UAAAZ,GAAK;AAAA,QACtC,CAACtC,KAAa,gBAAA4B,EAAC,QAAA,EAAK,OAAO,EAAE,MAAM,KAAM,UAAAzB,GAAS;AAAA,QAClD,CAACH,KAAauC,uBAAU,QAAA,EAAK,OAAOY,GAAa,UAAAZ,EAAA,CAAM;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAG9D,CAAC;AAEDF,EAAS,cAAc;AAUhB,MAAMkB,IAAY3D,EAA2C,SAClE,EAAE,OAAA4D,GAAO,WAAAvD,GAAW,OAAAC,GAAO,UAAAC,GAAU,GAAGE,EAAA,GACxCC,GACA;AACA,QAAM,EAAE,WAAAN,EAAA,IAAcR,EAAA,GAEhBiE,IAA4B;AAAA,IAChC,SAAS;AAAA,IACT,eAAe;AAAA,IACf,KAAK9B,EAAQ,GAAG;AAAA,IAChB,GAAGzB;AAAA,EAAA,GAGCwD,IAA4B;AAAA,IAChC,SAAS,GAAG/B,EAAQ,CAAC,CAAC,MAAMA,EAAQ,CAAC,CAAC,MAAMgC,EAAkB,EAAE,MAAMhC,EAAQ,CAAC,CAAC;AAAA,IAChF,UAAUM,EAAU;AAAA,IACpB,YAAY;AAAA,IACZ,OAAO;AAAA,IACP,eAAe;AAAA,IACf,eAAe;AAAA,EAAA;AAGjB,SACE,gBAAAoB,EAAC,OAAA,EAAI,KAAA/C,GAAU,WAAWwB,EAAG,qBAAqB7B,CAAS,GAAG,OAAOwD,GAAa,GAAGpD,GAClF,UAAA;AAAA,IAAAmD,KAAS,CAACxD,KAAa,gBAAA4B,EAAC,OAAA,EAAI,OAAO8B,GAAa,UAAAF,GAAM;AAAA,IACtDrD;AAAA,EAAA,GACH;AAEJ,CAAC;AAEDoD,EAAU,cAAc;AAQjB,MAAMK,IAAchE,EAA6C,SACtE,EAAE,WAAAK,GAAW,OAAAC,GAAO,GAAGG,EAAA,GACvBC,GACA;AACA,QAAMuD,IAA8B;AAAA,IAClC,QAAQ;AAAA,IACR,iBAAiB;AAAA,IACjB,QAAQ,GAAGlC,EAAQ,CAAC,CAAC;AAAA,IACrB,GAAGzB;AAAA,EAAA;AAGL,SACE,gBAAA0B;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAAtB;AAAA,MACA,MAAK;AAAA,MACL,WAAWwB,EAAG,uBAAuB7B,CAAS;AAAA,MAC9C,OAAO4D;AAAA,MACN,GAAGxD;AAAA,IAAA;AAAA,EAAA;AAGV,CAAC;AAEDuD,EAAY,cAAc;"}
1
+ {"version":3,"file":"Menu.js","sources":["../../../../src/components/navigation/Menu/Menu.tsx"],"sourcesContent":["/**\n * Menu Component\n *\n * A vertical navigation menu with support for nested items.\n * Suitable for sidebars and navigation panels.\n */\n\nimport {\n forwardRef,\n useState,\n useRef,\n useCallback,\n createContext,\n useContext,\n type ReactNode,\n type HTMLAttributes,\n type KeyboardEvent,\n} from 'react'\nimport { cx } from '../../../utils/styles'\n\nexport type MenuSize = 'sm' | 'md' | 'lg'\n\ninterface MenuContextValue {\n size: MenuSize\n activeItem: string | null\n setActiveItem: (value: string | null) => void\n collapsed: boolean\n focusedIndex: number\n setFocusedIndex: (index: number) => void\n registerItem: (value: string) => number\n}\n\nconst MenuContext = createContext<MenuContextValue | null>(null)\n\nfunction useMenuContext() {\n const context = useContext(MenuContext)\n if (!context) {\n throw new Error('Menu components must be used within a Menu')\n }\n return context\n}\n\nexport interface MenuProps extends Omit<HTMLAttributes<HTMLElement>, 'onChange'> {\n /** Currently active item */\n activeItem?: string | null\n /** Callback when active item changes */\n onChange?: (value: string | null) => void\n /** Menu size */\n size?: MenuSize\n /** Whether the menu is collapsed (icons only) */\n collapsed?: boolean\n /** Custom class name */\n className?: string\n /** Test ID */\n testId?: string\n}\n\nexport const Menu = forwardRef<HTMLElement, MenuProps>(function Menu(\n {\n activeItem: controlledActiveItem,\n onChange,\n size = 'md',\n collapsed = false,\n className,\n style,\n children,\n testId,\n ...props\n },\n ref\n) {\n const [internalActiveItem, setInternalActiveItem] = useState<string | null>(null)\n const [focusedIndex, setFocusedIndex] = useState(-1)\n const itemsRef = useRef<string[]>([])\n const menuRef = useRef<HTMLElement>(null)\n const activeItem = controlledActiveItem !== undefined ? controlledActiveItem : internalActiveItem\n\n const setActiveItem = (value: string | null) => {\n if (controlledActiveItem === undefined) {\n setInternalActiveItem(value)\n }\n onChange?.(value)\n }\n\n // Register items for keyboard navigation\n const registerItem = useCallback((value: string) => {\n const index = itemsRef.current.indexOf(value)\n if (index === -1) {\n itemsRef.current.push(value)\n return itemsRef.current.length - 1\n }\n return index\n }, [])\n\n // Keyboard navigation\n const handleKeyDown = useCallback((e: KeyboardEvent<HTMLElement>) => {\n const items = menuRef.current?.querySelectorAll<HTMLButtonElement>('[role=\"menuitem\"]:not(:disabled)')\n if (!items?.length) return\n\n const currentIndex = focusedIndex >= 0 ? focusedIndex : 0\n\n switch (e.key) {\n case 'ArrowDown': {\n e.preventDefault()\n const nextIndex = (currentIndex + 1) % items.length\n setFocusedIndex(nextIndex)\n items[nextIndex]?.focus()\n break\n }\n case 'ArrowUp': {\n e.preventDefault()\n const prevIndex = (currentIndex - 1 + items.length) % items.length\n setFocusedIndex(prevIndex)\n items[prevIndex]?.focus()\n break\n }\n case 'Home':\n e.preventDefault()\n setFocusedIndex(0)\n items[0]?.focus()\n break\n case 'End':\n e.preventDefault()\n setFocusedIndex(items.length - 1)\n items[items.length - 1]?.focus()\n break\n }\n }, [focusedIndex])\n\n return (\n <MenuContext.Provider value={{ size, activeItem, setActiveItem, collapsed, focusedIndex, setFocusedIndex, registerItem }}>\n <nav\n ref={(node) => {\n (menuRef as React.MutableRefObject<HTMLElement | null>).current = node\n if (typeof ref === 'function') ref(node)\n else if (ref) (ref as React.MutableRefObject<HTMLElement | null>).current = node\n }}\n role=\"menu\"\n className={cx('brycks-menu', `brycks-menu--${size}`, collapsed && 'brycks-menu--collapsed', className)}\n style={style}\n onKeyDown={handleKeyDown}\n data-testid={testId}\n {...props}\n >\n {children}\n </nav>\n </MenuContext.Provider>\n )\n})\n\nMenu.displayName = 'Menu'\n\n// MenuItem\nexport interface MenuItemProps extends Omit<HTMLAttributes<HTMLButtonElement>, 'onClick'> {\n /** Item value (unique identifier) */\n value: string\n /** Icon before the label */\n icon?: ReactNode\n /** Badge/count after the label */\n badge?: ReactNode\n /** Whether the item is disabled */\n disabled?: boolean\n /** Callback when clicked */\n onClick?: (value: string) => void\n /** Custom class name */\n className?: string\n}\n\nexport const MenuItem = forwardRef<HTMLButtonElement, MenuItemProps>(function MenuItem(\n { value, icon, badge, disabled = false, onClick, className, style, children, ...props },\n ref\n) {\n const { activeItem, setActiveItem, collapsed, focusedIndex, setFocusedIndex, registerItem } = useMenuContext()\n const isActive = activeItem === value\n const itemIndex = registerItem(value)\n\n const handleClick = () => {\n if (disabled) return\n setActiveItem(value)\n onClick?.(value)\n }\n\n const handleFocus = () => {\n setFocusedIndex(itemIndex)\n }\n\n // Roving tabindex: before any item is focused (focusedIndex -1), Tab must\n // still be able to enter the menu through the active item or the first one.\n const isTabStop =\n focusedIndex >= 0 ? focusedIndex === itemIndex : activeItem ? isActive : itemIndex === 0\n\n return (\n <button\n ref={ref}\n type=\"button\"\n role=\"menuitem\"\n disabled={disabled}\n tabIndex={isTabStop ? 0 : -1}\n className={cx('brycks-menu-item', isActive && 'brycks-menu-item--active', className)}\n style={style}\n onClick={handleClick}\n onFocus={handleFocus}\n title={collapsed ? String(children) : undefined}\n {...props}\n >\n {icon && <span className=\"brycks-menu-item__icon\">{icon}</span>}\n {!collapsed && <span className=\"brycks-menu-item__label\">{children}</span>}\n {!collapsed && badge && <span className=\"brycks-menu-item__badge\">{badge}</span>}\n </button>\n )\n})\n\nMenuItem.displayName = 'MenuItem'\n\n// MenuGroup\nexport interface MenuGroupProps extends HTMLAttributes<HTMLDivElement> {\n /** Group label */\n label?: string\n /** Custom class name */\n className?: string\n}\n\nexport const MenuGroup = forwardRef<HTMLDivElement, MenuGroupProps>(function MenuGroup(\n { label, className, style, children, ...props },\n ref\n) {\n const { collapsed } = useMenuContext()\n\n return (\n <div ref={ref} className={cx('brycks-menu-group', className)} style={style} {...props}>\n {label && !collapsed && <div className=\"brycks-menu-group__label\">{label}</div>}\n {children}\n </div>\n )\n})\n\nMenuGroup.displayName = 'MenuGroup'\n\n// MenuDivider\nexport interface MenuDividerProps extends HTMLAttributes<HTMLDivElement> {\n /** Custom class name */\n className?: string\n}\n\nexport const MenuDivider = forwardRef<HTMLDivElement, MenuDividerProps>(function MenuDivider(\n { className, style, ...props },\n ref\n) {\n return (\n <div\n ref={ref}\n role=\"separator\"\n className={cx('brycks-menu-divider', className)}\n style={style}\n {...props}\n />\n )\n})\n\nMenuDivider.displayName = 'MenuDivider'\n"],"names":["MenuContext","createContext","useMenuContext","context","useContext","Menu","forwardRef","controlledActiveItem","onChange","size","collapsed","className","style","children","testId","props","ref","internalActiveItem","setInternalActiveItem","useState","focusedIndex","setFocusedIndex","itemsRef","useRef","menuRef","activeItem","setActiveItem","value","registerItem","useCallback","index","handleKeyDown","items","currentIndex","nextIndex","prevIndex","jsx","node","cx","MenuItem","icon","badge","disabled","onClick","isActive","itemIndex","handleClick","handleFocus","isTabStop","jsxs","MenuGroup","label","MenuDivider"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("react/jsx-runtime"),j=require("react"),B=require("../../../utils/styles.cjs"),u=require("../../../design-system/tokens/spacing.cjs"),y=require("../../../design-system/tokens/typography.cjs"),N=require("../../../design-system/primitives/sizing.cjs"),v=require("../../../design-system/tokens/motion.cjs"),O={navigation:"Pagination",first:"First page",previous:"Previous page",next:"Next page",last:"Last page",page:p=>`Page ${p}`,of:(p,e)=>`Page ${p} of ${e}`},G={sm:{height:u.spacing[7],fontSize:y.fontSizes.sm,gap:u.spacing[1],minWidth:u.spacing[7]},md:{height:u.spacing[9],fontSize:y.fontSizes.base,gap:N.componentGap.sm,minWidth:u.spacing[9]},lg:{height:u.spacing[11],fontSize:y.fontSizes.md,gap:u.spacing[2],minWidth:u.spacing[11]}};function F(){return r.jsx("svg",{width:"16",height:"16",viewBox:"0 0 16 16",fill:"none",children:r.jsx("path",{d:"M10 12L6 8l4-4",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})}function H(){return r.jsx("svg",{width:"16",height:"16",viewBox:"0 0 16 16",fill:"none",children:r.jsx("path",{d:"M6 4l4 4-4 4",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})}function J(){return r.jsx("svg",{width:"16",height:"16",viewBox:"0 0 16 16",fill:"none",children:r.jsx("path",{d:"M11 12l-4-4 4-4M7 12l-4-4 4-4",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})}function K(){return r.jsx("svg",{width:"16",height:"16",viewBox:"0 0 16 16",fill:"none",children:r.jsx("path",{d:"M5 4l4 4-4 4M9 4l4 4-4 4",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})}const C=j.forwardRef(function({page:e,totalPages:t,onChange:M,size:k="md",variant:c="default",siblingCount:d=1,showFirstLast:m=!0,showPrevNext:b=!0,disabled:o=!1,labels:S,className:L,style:z,testId:W,...$},T){const s=G[k],l={...O,...S},q=j.useMemo(()=>{if(c==="minimal"||c==="simple")return[];const n=[],a=Math.max(e-d,1),h=Math.min(e+d,t),R=a>2,x=h<t-1;if(R)if(x){n.push(1),n.push("ellipsis");for(let i=a;i<=h;i++)n.push(i);n.push("ellipsis"),n.push(t)}else{n.push(1),n.push("ellipsis");for(let i=Math.max(t-2-d,1);i<=t;i++)n.push(i)}else{for(let i=1;i<=Math.min(3+d,t);i++)n.push(i);x&&(n.push("ellipsis"),n.push(t))}return n},[e,t,d,c]),w={display:"flex",alignItems:"center",gap:s.gap,...z},f=(n,a)=>({display:"inline-flex",alignItems:"center",justifyContent:"center",minWidth:s.minWidth,height:s.height,padding:`0 ${s.gap+4}px`,fontSize:s.fontSize,fontWeight:n?600:500,color:a?"var(--brycks-foreground-disabled)":n?"var(--brycks-primary-default)":"var(--brycks-foreground-default)",backgroundColor:n?"var(--brycks-primary-muted)":"transparent",border:"none",borderRadius:"var(--brycks-radius-md)",cursor:a?"not-allowed":"pointer",transition:`all ${v.durations.quick}ms ${v.easings.easeOut}`}),E={display:"flex",alignItems:"center",justifyContent:"center",minWidth:s.minWidth,height:s.height,color:"var(--brycks-foreground-muted)",fontSize:s.fontSize},I={fontSize:s.fontSize,color:"var(--brycks-foreground-muted)",padding:`0 ${s.gap}px`},g=n=>{n>=1&&n<=t&&n!==e&&!o&&M(n)};return r.jsxs("nav",{ref:T,role:"navigation","aria-label":l.navigation,className:B.cx("brycks-pagination",`brycks-pagination--${k}`,`brycks-pagination--${c}`,L),style:w,"data-testid":W,...$,children:[m&&c!=="minimal"&&r.jsx("button",{type:"button","aria-label":l.first,disabled:e===1||o,style:f(!1,e===1||o),onClick:()=>g(1),onMouseEnter:n=>{e!==1&&!o&&(n.currentTarget.style.backgroundColor="var(--brycks-background-muted)")},onMouseLeave:n=>{n.currentTarget.style.backgroundColor="transparent"},children:r.jsx(J,{})}),b&&r.jsx("button",{type:"button","aria-label":l.previous,disabled:e===1||o,style:f(!1,e===1||o),onClick:()=>g(e-1),onMouseEnter:n=>{e!==1&&!o&&(n.currentTarget.style.backgroundColor="var(--brycks-background-muted)")},onMouseLeave:n=>{n.currentTarget.style.backgroundColor="transparent"},children:r.jsx(F,{})}),c==="simple"||c==="minimal"?r.jsx("span",{style:I,children:c==="minimal"?`${e} / ${t}`:l.of(e,t)}):q.map((n,a)=>n==="ellipsis"?r.jsx("span",{style:E,children:"..."},`ellipsis-${a}`):r.jsx("button",{type:"button","aria-label":l.page(n),"aria-current":n===e?"page":void 0,disabled:o,style:f(n===e,o),onClick:()=>g(n),onMouseEnter:h=>{n!==e&&!o&&(h.currentTarget.style.backgroundColor="var(--brycks-background-muted)")},onMouseLeave:h=>{n!==e&&(h.currentTarget.style.backgroundColor="transparent")},children:n},n)),b&&r.jsx("button",{type:"button","aria-label":l.next,disabled:e===t||o,style:f(!1,e===t||o),onClick:()=>g(e+1),onMouseEnter:n=>{e!==t&&!o&&(n.currentTarget.style.backgroundColor="var(--brycks-background-muted)")},onMouseLeave:n=>{n.currentTarget.style.backgroundColor="transparent"},children:r.jsx(H,{})}),m&&c!=="minimal"&&r.jsx("button",{type:"button","aria-label":l.last,disabled:e===t||o,style:f(!1,e===t||o),onClick:()=>g(t),onMouseEnter:n=>{e!==t&&!o&&(n.currentTarget.style.backgroundColor="var(--brycks-background-muted)")},onMouseLeave:n=>{n.currentTarget.style.backgroundColor="transparent"},children:r.jsx(K,{})})]})});C.displayName="Pagination";exports.Pagination=C;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const n=require("react/jsx-runtime"),k=require("react"),x=require("../../../utils/styles.cjs"),w={navigation:"Pagination",first:"First page",previous:"Previous page",next:"Next page",last:"Last page",page:u=>`Page ${u}`,of:(u,t)=>`Page ${u} of ${t}`};function R(){return n.jsx("svg",{width:"16",height:"16",viewBox:"0 0 16 16",fill:"none",children:n.jsx("path",{d:"M10 12L6 8l4-4",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})}function B(){return n.jsx("svg",{width:"16",height:"16",viewBox:"0 0 16 16",fill:"none",children:n.jsx("path",{d:"M6 4l4 4-4 4",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})}function I(){return n.jsx("svg",{width:"16",height:"16",viewBox:"0 0 16 16",fill:"none",children:n.jsx("path",{d:"M11 12l-4-4 4-4M7 12l-4-4 4-4",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})}function S(){return n.jsx("svg",{width:"16",height:"16",viewBox:"0 0 16 16",fill:"none",children:n.jsx("path",{d:"M5 4l4 4-4 4M9 4l4 4-4 4",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})}const m=k.forwardRef(function({page:t,totalPages:e,onChange:j,size:y="md",variant:o="default",siblingCount:c=1,showFirstLast:p=!0,showPrevNext:d=!0,disabled:l=!1,labels:_,className:g,style:v,testId:L,...M},C){const r={...w,..._},N=k.useMemo(()=>{if(o==="minimal"||o==="simple")return[];const i=[],h=Math.max(t-c,1),b=Math.min(t+c,e),$=h>2,f=b<e-1;if($)if(f){i.push(1),i.push("ellipsis");for(let s=h;s<=b;s++)i.push(s);i.push("ellipsis"),i.push(e)}else{i.push(1),i.push("ellipsis");for(let s=Math.max(e-2-c,1);s<=e;s++)i.push(s)}else{for(let s=1;s<=Math.min(3+c,e);s++)i.push(s);f&&(i.push("ellipsis"),i.push(e))}return i},[t,e,c,o]),a=i=>{i>=1&&i<=e&&i!==t&&!l&&j(i)};return n.jsxs("nav",{ref:C,role:"navigation","aria-label":r.navigation,className:x.cx("brycks-pagination",`brycks-pagination--${y}`,`brycks-pagination--${o}`,g),style:v,"data-testid":L,...M,children:[p&&o!=="minimal"&&n.jsx("button",{type:"button","aria-label":r.first,disabled:t===1||l,className:"brycks-pagination__button",onClick:()=>a(1),children:n.jsx(I,{})}),d&&n.jsx("button",{type:"button","aria-label":r.previous,disabled:t===1||l,className:"brycks-pagination__button",onClick:()=>a(t-1),children:n.jsx(R,{})}),o==="simple"||o==="minimal"?n.jsx("span",{className:"brycks-pagination__info",children:o==="minimal"?`${t} / ${e}`:r.of(t,e)}):N.map((i,h)=>i==="ellipsis"?n.jsx("span",{className:"brycks-pagination__ellipsis",children:"..."},`ellipsis-${h}`):n.jsx("button",{type:"button","aria-label":r.page(i),"aria-current":i===t?"page":void 0,disabled:l,className:x.cx("brycks-pagination__button",i===t&&"brycks-pagination__button--active"),onClick:()=>a(i),children:i},i)),d&&n.jsx("button",{type:"button","aria-label":r.next,disabled:t===e||l,className:"brycks-pagination__button",onClick:()=>a(t+1),children:n.jsx(B,{})}),p&&o!=="minimal"&&n.jsx("button",{type:"button","aria-label":r.last,disabled:t===e||l,className:"brycks-pagination__button",onClick:()=>a(e),children:n.jsx(S,{})})]})});m.displayName="Pagination";exports.Pagination=m;
2
2
  //# sourceMappingURL=Pagination.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"Pagination.cjs","sources":["../../../../src/components/navigation/Pagination/Pagination.tsx"],"sourcesContent":["/**\n * Pagination Component\n *\n * A pagination control for navigating through pages.\n * Supports different sizes and display modes.\n */\n\nimport { forwardRef, useMemo, type CSSProperties, type HTMLAttributes } from 'react'\nimport { cx } from '../../../utils/styles'\nimport { spacing, fontSizes, durations, easings } from '../../../design-system'\nimport { componentGap } from '../../../design-system/primitives'\n\nexport type PaginationSize = 'sm' | 'md' | 'lg'\nexport type PaginationVariant = 'default' | 'simple' | 'minimal'\n\nexport interface PaginationLabels {\n /** aria-label of the nav landmark */\n navigation?: string\n /** aria-label of the first-page button */\n first?: string\n /** aria-label of the previous-page button */\n previous?: string\n /** aria-label of the next-page button */\n next?: string\n /** aria-label of the last-page button */\n last?: string\n /** aria-label of a numbered page button */\n page?: (page: number) => string\n /** Visible text of the `simple` variant */\n of?: (page: number, totalPages: number) => string\n}\n\nconst defaultLabels: Required<PaginationLabels> = {\n navigation: 'Pagination',\n first: 'First page',\n previous: 'Previous page',\n next: 'Next page',\n last: 'Last page',\n page: (page) => `Page ${page}`,\n of: (page, totalPages) => `Page ${page} of ${totalPages}`,\n}\n\nexport interface PaginationProps extends Omit<HTMLAttributes<HTMLElement>, 'onChange'> {\n /** Current page (1-indexed) */\n page: number\n /** Total number of pages */\n totalPages: number\n /** Callback when page changes */\n onChange: (page: number) => void\n /** Pagination size */\n size?: PaginationSize\n /** Pagination variant */\n variant?: PaginationVariant\n /** Number of sibling pages to show on each side */\n siblingCount?: number\n /** Whether to show first/last buttons */\n showFirstLast?: boolean\n /** Whether to show prev/next buttons */\n showPrevNext?: boolean\n /** Whether the component is disabled */\n disabled?: boolean\n /** Localizable labels (merged over English defaults) */\n labels?: PaginationLabels\n /** Custom class name */\n className?: string\n /** Test ID */\n testId?: string\n}\n\nconst sizeConfig: Record<PaginationSize, { height: number; fontSize: number; gap: number; minWidth: number }> = {\n sm: { height: spacing[7], fontSize: fontSizes.sm, gap: spacing[1], minWidth: spacing[7] },\n md: { height: spacing[9], fontSize: fontSizes.base, gap: componentGap.sm, minWidth: spacing[9] },\n lg: { height: spacing[11], fontSize: fontSizes.md, gap: spacing[2], minWidth: spacing[11] },\n}\n\nfunction ChevronLeftIcon() {\n return (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\">\n <path d=\"M10 12L6 8l4-4\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n )\n}\n\nfunction ChevronRightIcon() {\n return (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\">\n <path d=\"M6 4l4 4-4 4\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n )\n}\n\nfunction ChevronsLeftIcon() {\n return (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\">\n <path d=\"M11 12l-4-4 4-4M7 12l-4-4 4-4\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n )\n}\n\nfunction ChevronsRightIcon() {\n return (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\">\n <path d=\"M5 4l4 4-4 4M9 4l4 4-4 4\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n )\n}\n\nexport const Pagination = forwardRef<HTMLElement, PaginationProps>(function Pagination(\n {\n page,\n totalPages,\n onChange,\n size = 'md',\n variant = 'default',\n siblingCount = 1,\n showFirstLast = true,\n showPrevNext = true,\n disabled = false,\n labels,\n className,\n style,\n testId,\n ...props\n },\n ref\n) {\n const config = sizeConfig[size]\n const text = { ...defaultLabels, ...labels }\n\n // Generate page numbers to display\n const pages = useMemo(() => {\n if (variant === 'minimal' || variant === 'simple') {\n return []\n }\n\n const range: (number | 'ellipsis')[] = []\n const leftSibling = Math.max(page - siblingCount, 1)\n const rightSibling = Math.min(page + siblingCount, totalPages)\n\n const showLeftEllipsis = leftSibling > 2\n const showRightEllipsis = rightSibling < totalPages - 1\n\n if (!showLeftEllipsis) {\n for (let i = 1; i <= Math.min(3 + siblingCount, totalPages); i++) {\n range.push(i)\n }\n if (showRightEllipsis) {\n range.push('ellipsis')\n range.push(totalPages)\n }\n } else if (!showRightEllipsis) {\n range.push(1)\n range.push('ellipsis')\n for (let i = Math.max(totalPages - 2 - siblingCount, 1); i <= totalPages; i++) {\n range.push(i)\n }\n } else {\n range.push(1)\n range.push('ellipsis')\n for (let i = leftSibling; i <= rightSibling; i++) {\n range.push(i)\n }\n range.push('ellipsis')\n range.push(totalPages)\n }\n\n return range\n }, [page, totalPages, siblingCount, variant])\n\n const containerStyle: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n gap: config.gap,\n ...style,\n }\n\n const getButtonStyle = (isActive: boolean, isDisabled: boolean): CSSProperties => ({\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n minWidth: config.minWidth,\n height: config.height,\n padding: `0 ${config.gap + 4}px`,\n fontSize: config.fontSize,\n fontWeight: isActive ? 600 : 500,\n color: isDisabled\n ? 'var(--brycks-foreground-disabled)'\n : isActive\n ? 'var(--brycks-primary-default)'\n : 'var(--brycks-foreground-default)',\n backgroundColor: isActive ? 'var(--brycks-primary-muted)' : 'transparent',\n border: 'none',\n borderRadius: 'var(--brycks-radius-md)',\n cursor: isDisabled ? 'not-allowed' : 'pointer',\n transition: `all ${durations.quick}ms ${easings.easeOut}`,\n })\n\n const ellipsisStyle: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n minWidth: config.minWidth,\n height: config.height,\n color: 'var(--brycks-foreground-muted)',\n fontSize: config.fontSize,\n }\n\n const infoStyle: CSSProperties = {\n fontSize: config.fontSize,\n color: 'var(--brycks-foreground-muted)',\n padding: `0 ${config.gap}px`,\n }\n\n const handlePageChange = (newPage: number) => {\n if (newPage >= 1 && newPage <= totalPages && newPage !== page && !disabled) {\n onChange(newPage)\n }\n }\n\n return (\n <nav\n ref={ref}\n role=\"navigation\"\n aria-label={text.navigation}\n className={cx('brycks-pagination', `brycks-pagination--${size}`, `brycks-pagination--${variant}`, className)}\n style={containerStyle}\n data-testid={testId}\n {...props}\n >\n {showFirstLast && variant !== 'minimal' && (\n <button\n type=\"button\"\n aria-label={text.first}\n disabled={page === 1 || disabled}\n style={getButtonStyle(false, page === 1 || disabled)}\n onClick={() => handlePageChange(1)}\n onMouseEnter={(e) => {\n if (page !== 1 && !disabled) {\n e.currentTarget.style.backgroundColor = 'var(--brycks-background-muted)'\n }\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.backgroundColor = 'transparent'\n }}\n >\n <ChevronsLeftIcon />\n </button>\n )}\n\n {showPrevNext && (\n <button\n type=\"button\"\n aria-label={text.previous}\n disabled={page === 1 || disabled}\n style={getButtonStyle(false, page === 1 || disabled)}\n onClick={() => handlePageChange(page - 1)}\n onMouseEnter={(e) => {\n if (page !== 1 && !disabled) {\n e.currentTarget.style.backgroundColor = 'var(--brycks-background-muted)'\n }\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.backgroundColor = 'transparent'\n }}\n >\n <ChevronLeftIcon />\n </button>\n )}\n\n {variant === 'simple' || variant === 'minimal' ? (\n <span style={infoStyle}>\n {variant === 'minimal' ? `${page} / ${totalPages}` : text.of(page, totalPages)}\n </span>\n ) : (\n pages.map((p, index) =>\n p === 'ellipsis' ? (\n <span key={`ellipsis-${index}`} style={ellipsisStyle}>\n ...\n </span>\n ) : (\n <button\n key={p}\n type=\"button\"\n aria-label={text.page(p)}\n aria-current={p === page ? 'page' : undefined}\n disabled={disabled}\n style={getButtonStyle(p === page, disabled)}\n onClick={() => handlePageChange(p)}\n onMouseEnter={(e) => {\n if (p !== page && !disabled) {\n e.currentTarget.style.backgroundColor = 'var(--brycks-background-muted)'\n }\n }}\n onMouseLeave={(e) => {\n if (p !== page) {\n e.currentTarget.style.backgroundColor = 'transparent'\n }\n }}\n >\n {p}\n </button>\n )\n )\n )}\n\n {showPrevNext && (\n <button\n type=\"button\"\n aria-label={text.next}\n disabled={page === totalPages || disabled}\n style={getButtonStyle(false, page === totalPages || disabled)}\n onClick={() => handlePageChange(page + 1)}\n onMouseEnter={(e) => {\n if (page !== totalPages && !disabled) {\n e.currentTarget.style.backgroundColor = 'var(--brycks-background-muted)'\n }\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.backgroundColor = 'transparent'\n }}\n >\n <ChevronRightIcon />\n </button>\n )}\n\n {showFirstLast && variant !== 'minimal' && (\n <button\n type=\"button\"\n aria-label={text.last}\n disabled={page === totalPages || disabled}\n style={getButtonStyle(false, page === totalPages || disabled)}\n onClick={() => handlePageChange(totalPages)}\n onMouseEnter={(e) => {\n if (page !== totalPages && !disabled) {\n e.currentTarget.style.backgroundColor = 'var(--brycks-background-muted)'\n }\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.backgroundColor = 'transparent'\n }}\n >\n <ChevronsRightIcon />\n </button>\n )}\n </nav>\n )\n})\n\nPagination.displayName = 'Pagination'\n"],"names":["defaultLabels","page","totalPages","sizeConfig","spacing","fontSizes","componentGap","ChevronLeftIcon","jsx","ChevronRightIcon","ChevronsLeftIcon","ChevronsRightIcon","Pagination","forwardRef","onChange","size","variant","siblingCount","showFirstLast","showPrevNext","disabled","labels","className","style","testId","props","ref","config","text","pages","useMemo","range","leftSibling","rightSibling","showLeftEllipsis","showRightEllipsis","containerStyle","getButtonStyle","isActive","isDisabled","durations","easings","ellipsisStyle","infoStyle","handlePageChange","newPage","jsxs","cx","e","p","index"],"mappings":"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"}
1
+ {"version":3,"file":"Pagination.cjs","sources":["../../../../src/components/navigation/Pagination/Pagination.tsx"],"sourcesContent":["/**\n * Pagination Component\n *\n * A pagination control for navigating through pages.\n * Supports different sizes and display modes.\n */\n\nimport { forwardRef, useMemo, type HTMLAttributes } from 'react'\nimport { cx } from '../../../utils/styles'\n\nexport type PaginationSize = 'sm' | 'md' | 'lg'\nexport type PaginationVariant = 'default' | 'simple' | 'minimal'\n\nexport interface PaginationLabels {\n /** aria-label of the nav landmark */\n navigation?: string\n /** aria-label of the first-page button */\n first?: string\n /** aria-label of the previous-page button */\n previous?: string\n /** aria-label of the next-page button */\n next?: string\n /** aria-label of the last-page button */\n last?: string\n /** aria-label of a numbered page button */\n page?: (page: number) => string\n /** Visible text of the `simple` variant */\n of?: (page: number, totalPages: number) => string\n}\n\nconst defaultLabels: Required<PaginationLabels> = {\n navigation: 'Pagination',\n first: 'First page',\n previous: 'Previous page',\n next: 'Next page',\n last: 'Last page',\n page: (page) => `Page ${page}`,\n of: (page, totalPages) => `Page ${page} of ${totalPages}`,\n}\n\nexport interface PaginationProps extends Omit<HTMLAttributes<HTMLElement>, 'onChange'> {\n /** Current page (1-indexed) */\n page: number\n /** Total number of pages */\n totalPages: number\n /** Callback when page changes */\n onChange: (page: number) => void\n /** Pagination size */\n size?: PaginationSize\n /** Pagination variant */\n variant?: PaginationVariant\n /** Number of sibling pages to show on each side */\n siblingCount?: number\n /** Whether to show first/last buttons */\n showFirstLast?: boolean\n /** Whether to show prev/next buttons */\n showPrevNext?: boolean\n /** Whether the component is disabled */\n disabled?: boolean\n /** Localizable labels (merged over English defaults) */\n labels?: PaginationLabels\n /** Custom class name */\n className?: string\n /** Test ID */\n testId?: string\n}\n\nfunction ChevronLeftIcon() {\n return (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\">\n <path d=\"M10 12L6 8l4-4\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n )\n}\n\nfunction ChevronRightIcon() {\n return (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\">\n <path d=\"M6 4l4 4-4 4\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n )\n}\n\nfunction ChevronsLeftIcon() {\n return (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\">\n <path d=\"M11 12l-4-4 4-4M7 12l-4-4 4-4\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n )\n}\n\nfunction ChevronsRightIcon() {\n return (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\">\n <path d=\"M5 4l4 4-4 4M9 4l4 4-4 4\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n )\n}\n\nexport const Pagination = forwardRef<HTMLElement, PaginationProps>(function Pagination(\n {\n page,\n totalPages,\n onChange,\n size = 'md',\n variant = 'default',\n siblingCount = 1,\n showFirstLast = true,\n showPrevNext = true,\n disabled = false,\n labels,\n className,\n style,\n testId,\n ...props\n },\n ref\n) {\n const text = { ...defaultLabels, ...labels }\n\n // Generate page numbers to display\n const pages = useMemo(() => {\n if (variant === 'minimal' || variant === 'simple') {\n return []\n }\n\n const range: (number | 'ellipsis')[] = []\n const leftSibling = Math.max(page - siblingCount, 1)\n const rightSibling = Math.min(page + siblingCount, totalPages)\n\n const showLeftEllipsis = leftSibling > 2\n const showRightEllipsis = rightSibling < totalPages - 1\n\n if (!showLeftEllipsis) {\n for (let i = 1; i <= Math.min(3 + siblingCount, totalPages); i++) {\n range.push(i)\n }\n if (showRightEllipsis) {\n range.push('ellipsis')\n range.push(totalPages)\n }\n } else if (!showRightEllipsis) {\n range.push(1)\n range.push('ellipsis')\n for (let i = Math.max(totalPages - 2 - siblingCount, 1); i <= totalPages; i++) {\n range.push(i)\n }\n } else {\n range.push(1)\n range.push('ellipsis')\n for (let i = leftSibling; i <= rightSibling; i++) {\n range.push(i)\n }\n range.push('ellipsis')\n range.push(totalPages)\n }\n\n return range\n }, [page, totalPages, siblingCount, variant])\n\n const handlePageChange = (newPage: number) => {\n if (newPage >= 1 && newPage <= totalPages && newPage !== page && !disabled) {\n onChange(newPage)\n }\n }\n\n return (\n <nav\n ref={ref}\n role=\"navigation\"\n aria-label={text.navigation}\n className={cx('brycks-pagination', `brycks-pagination--${size}`, `brycks-pagination--${variant}`, className)}\n style={style}\n data-testid={testId}\n {...props}\n >\n {showFirstLast && variant !== 'minimal' && (\n <button\n type=\"button\"\n aria-label={text.first}\n disabled={page === 1 || disabled}\n className=\"brycks-pagination__button\"\n onClick={() => handlePageChange(1)}\n >\n <ChevronsLeftIcon />\n </button>\n )}\n\n {showPrevNext && (\n <button\n type=\"button\"\n aria-label={text.previous}\n disabled={page === 1 || disabled}\n className=\"brycks-pagination__button\"\n onClick={() => handlePageChange(page - 1)}\n >\n <ChevronLeftIcon />\n </button>\n )}\n\n {variant === 'simple' || variant === 'minimal' ? (\n <span className=\"brycks-pagination__info\">\n {variant === 'minimal' ? `${page} / ${totalPages}` : text.of(page, totalPages)}\n </span>\n ) : (\n pages.map((p, index) =>\n p === 'ellipsis' ? (\n <span key={`ellipsis-${index}`} className=\"brycks-pagination__ellipsis\">\n ...\n </span>\n ) : (\n <button\n key={p}\n type=\"button\"\n aria-label={text.page(p)}\n aria-current={p === page ? 'page' : undefined}\n disabled={disabled}\n className={cx('brycks-pagination__button', p === page && 'brycks-pagination__button--active')}\n onClick={() => handlePageChange(p)}\n >\n {p}\n </button>\n )\n )\n )}\n\n {showPrevNext && (\n <button\n type=\"button\"\n aria-label={text.next}\n disabled={page === totalPages || disabled}\n className=\"brycks-pagination__button\"\n onClick={() => handlePageChange(page + 1)}\n >\n <ChevronRightIcon />\n </button>\n )}\n\n {showFirstLast && variant !== 'minimal' && (\n <button\n type=\"button\"\n aria-label={text.last}\n disabled={page === totalPages || disabled}\n className=\"brycks-pagination__button\"\n onClick={() => handlePageChange(totalPages)}\n >\n <ChevronsRightIcon />\n </button>\n )}\n </nav>\n )\n})\n\nPagination.displayName = 'Pagination'\n"],"names":["defaultLabels","page","totalPages","ChevronLeftIcon","jsx","ChevronRightIcon","ChevronsLeftIcon","ChevronsRightIcon","Pagination","forwardRef","onChange","size","variant","siblingCount","showFirstLast","showPrevNext","disabled","labels","className","style","testId","props","ref","text","pages","useMemo","range","leftSibling","rightSibling","showLeftEllipsis","showRightEllipsis","i","handlePageChange","newPage","jsxs","cx","p","index"],"mappings":"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"}