analytica-frontend-lib 1.0.60 → 1.0.61

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/Menu/Menu.tsx"],"sourcesContent":["import { create, StoreApi, useStore } from 'zustand';\nimport {\n ReactNode,\n useEffect,\n useRef,\n forwardRef,\n HTMLAttributes,\n KeyboardEvent,\n MouseEvent,\n ReactElement,\n isValidElement,\n Children,\n cloneElement,\n useState,\n} from 'react';\nimport { CaretLeft, CaretRight } from 'phosphor-react';\n\ntype MenuVariant = 'menu' | 'menu2' | 'breadcrumb';\n\ninterface MenuStore {\n value: string;\n setValue: (value: string) => void;\n}\n\ntype MenuStoreApi = StoreApi<MenuStore>;\n\nconst createMenuStore = (): MenuStoreApi =>\n create<MenuStore>((set) => ({\n value: '',\n setValue: (value) => set({ value }),\n }));\n\nexport const useMenuStore = (externalStore?: MenuStoreApi) => {\n if (!externalStore) throw new Error('MenuItem must be inside Menu');\n return externalStore;\n};\n\ninterface MenuProps extends HTMLAttributes<HTMLDivElement> {\n children: ReactNode;\n defaultValue: string;\n value?: string;\n variant?: MenuVariant;\n onValueChange?: (value: string) => void;\n}\n\nconst VARIANT_CLASSES = {\n menu: 'bg-background shadow-soft-shadow-1',\n menu2: '',\n breadcrumb: '',\n};\n\nconst Menu = forwardRef<HTMLDivElement, MenuProps>(\n (\n {\n className,\n children,\n defaultValue,\n value: propValue,\n variant = 'menu',\n onValueChange,\n ...props\n },\n ref\n ) => {\n const storeRef = useRef<MenuStoreApi>(null);\n storeRef.current ??= createMenuStore();\n const store = storeRef.current;\n const { setValue, value } = useStore(store, (s) => s);\n\n useEffect(() => {\n setValue(propValue ?? defaultValue);\n }, [defaultValue, propValue, setValue]);\n\n const onValueChangeRef = useRef(onValueChange);\n const isInitializedRef = useRef(false);\n onValueChangeRef.current = onValueChange;\n\n useEffect(() => {\n // Só chama onValueChange se não for a inicialização\n if (isInitializedRef.current) {\n onValueChangeRef.current?.(value);\n } else {\n isInitializedRef.current = true;\n }\n }, [value]);\n\n const baseClasses =\n 'w-full py-2 px-6 flex flex-row items-center justify-center';\n const variantClasses = VARIANT_CLASSES[variant];\n\n return (\n <div\n ref={ref}\n className={`\n ${baseClasses}\n ${variantClasses}\n ${className ?? ''}\n `}\n {...props}\n >\n {injectStore(children, store)}\n </div>\n );\n }\n);\nMenu.displayName = 'Menu';\n\ninterface MenuContentProps extends HTMLAttributes<HTMLUListElement> {\n children: ReactNode;\n variant?: MenuVariant;\n}\n\nconst MenuContent = forwardRef<HTMLUListElement, MenuContentProps>(\n ({ className, children, variant = 'menu', ...props }, ref) => {\n const baseClasses = 'w-full flex flex-row items-center gap-2';\n\n const variantClasses =\n variant === 'menu2' ? 'overflow-x-auto scroll-smooth' : '';\n\n return (\n <ul\n ref={ref}\n className={`\n ${baseClasses}\n ${variantClasses}\n ${className ?? ''}\n `}\n style={\n variant === 'menu2'\n ? { scrollbarWidth: 'none', msOverflowStyle: 'none' }\n : undefined\n }\n {...props}\n >\n {children}\n </ul>\n );\n }\n);\nMenuContent.displayName = 'MenuContent';\n\ninterface MenuItemProps extends HTMLAttributes<HTMLLIElement> {\n value: string;\n disabled?: boolean;\n store?: MenuStoreApi;\n variant?: MenuVariant;\n}\n\nconst MenuItem = forwardRef<HTMLLIElement, MenuItemProps>(\n (\n {\n className,\n children,\n value,\n disabled = false,\n store: externalStore,\n variant = 'menu',\n ...props\n },\n ref\n ) => {\n const store = useMenuStore(externalStore);\n const { value: selectedValue, setValue } = useStore(store, (s) => s);\n\n const handleClick = (\n e: MouseEvent<HTMLLIElement> | KeyboardEvent<HTMLLIElement>\n ) => {\n if (!disabled) setValue(value);\n props.onClick?.(e as MouseEvent<HTMLLIElement>);\n };\n\n const commonProps = {\n role: 'menuitem',\n 'aria-disabled': disabled,\n ref,\n onClick: handleClick,\n onKeyDown: (e: KeyboardEvent<HTMLLIElement>) => {\n if (['Enter', ' '].includes(e.key)) handleClick(e);\n },\n tabIndex: disabled ? -1 : 0,\n onMouseDown: (e: MouseEvent<HTMLLIElement>) => {\n e.preventDefault();\n },\n ...props,\n };\n\n const variants: Record<string, ReactNode> = {\n menu: (\n <li\n data-variant=\"menu\"\n className={`\n w-full flex flex-col gap-0.5 items-center py-1 px-2 rounded-sm font-medium text-xs\n [&>svg]:size-6 cursor-pointer hover:bg-primary-600 hover:text-text\n focus:outline-none focus:border-indicator-info focus:border-2\n ${selectedValue === value ? 'bg-primary-50 text-primary-950' : 'text-text-950'}\n ${className ?? ''}\n `}\n {...commonProps}\n >\n {children}\n </li>\n ),\n menu2: (\n <li\n data-variant=\"menu2\"\n className={`\n w-full flex flex-row items-center p-4 gap-2 border-b-4 border-transparent text-text-950 text-sx font-bold cursor-pointer focus:rounded-sm\n focus:outline-none focus:border-indicator-info focus:border-2\n ${selectedValue === value ? 'border-b-primary-950' : ''}\n ${className ?? ''}\n `}\n {...commonProps}\n >\n {children}\n </li>\n ),\n breadcrumb: (\n <li\n data-variant=\"breadcrumb\"\n className={`\n w-full p-2 rounded-lg hover:text-primary-600 cursor-pointer font-bold text-xs\n focus:outline-none focus:border-indicator-info focus:border-2\n ${selectedValue === value ? 'text-text-950' : 'text-text-600'}\n ${className ?? ''}\n `}\n {...commonProps}\n >\n <span\n className={`\n border-b border-text-600 hover:border-primary-600 text-inherit text-xs\n ${selectedValue === value ? 'border-b-0 font-bold' : 'border-b-primary-600'}\n `}\n >\n {children}\n </span>\n </li>\n ),\n };\n\n return variants[variant] ?? variants['menu'];\n }\n);\nMenuItem.displayName = 'MenuItem';\n\nconst MenuItemIcon = ({\n className,\n icon,\n ...props\n}: HTMLAttributes<HTMLSpanElement> & { icon: ReactNode }) => (\n <span\n className={`\n bg-background-500 w-[21px] h-[21px] flex items-center justify-center\n [&>svg]:w-[17px] [&>svg]:h-[17px] rounded-sm ${className ?? ''}\n `}\n {...props}\n >\n {icon}\n </span>\n);\n\nconst MenuSeparator = forwardRef<HTMLLIElement, HTMLAttributes<HTMLLIElement>>(\n ({ className, children, ...props }, ref) => (\n <li\n ref={ref}\n aria-hidden=\"true\"\n className={`[&>svg]:w-4 [&>svg]:h-4 text-text-600 ${className ?? ''}`}\n {...props}\n >\n {children ?? <CaretRight />}\n </li>\n )\n);\nMenuSeparator.displayName = 'MenuSeparator';\n\nexport const internalScroll = (\n container: HTMLUListElement | null,\n direction: 'left' | 'right'\n) => {\n if (!container) return;\n container.scrollBy({\n left: direction === 'left' ? -150 : 150,\n behavior: 'smooth',\n });\n};\n\nexport const internalCheckScroll = (\n container: HTMLUListElement | null,\n setShowLeftArrow: (v: boolean) => void,\n setShowRightArrow: (v: boolean) => void\n) => {\n if (!container) return;\n const { scrollLeft, scrollWidth, clientWidth } = container;\n setShowLeftArrow(scrollLeft > 0);\n setShowRightArrow(scrollLeft + clientWidth < scrollWidth);\n};\n\ninterface MenuOverflowProps extends HTMLAttributes<HTMLDivElement> {\n children: ReactNode;\n defaultValue: string;\n value?: string;\n onValueChange?: (value: string) => void;\n}\n\nconst MenuOverflow = ({\n children,\n className,\n defaultValue,\n value,\n onValueChange,\n ...props\n}: MenuOverflowProps) => {\n const containerRef = useRef<HTMLUListElement>(null);\n const [showLeftArrow, setShowLeftArrow] = useState(false);\n const [showRightArrow, setShowRightArrow] = useState(false);\n\n useEffect(() => {\n const checkScroll = () =>\n internalCheckScroll(\n containerRef.current,\n setShowLeftArrow,\n setShowRightArrow\n );\n checkScroll();\n const container = containerRef.current;\n container?.addEventListener('scroll', checkScroll);\n window.addEventListener('resize', checkScroll);\n return () => {\n container?.removeEventListener('scroll', checkScroll);\n window.removeEventListener('resize', checkScroll);\n };\n }, []);\n\n return (\n <div\n data-testid=\"menu-overflow-wrapper\"\n className={`relative w-full overflow-hidden ${className ?? ''}`}\n >\n {showLeftArrow && (\n <button\n onClick={() => internalScroll(containerRef.current, 'left')}\n className=\"absolute left-0 top-1/2 -translate-y-1/2 z-10 flex h-8 w-8 items-center justify-center rounded-full bg-white shadow-md cursor-pointer\"\n data-testid=\"scroll-left-button\"\n >\n <CaretLeft size={16} />\n <span className=\"sr-only\">Scroll left</span>\n </button>\n )}\n\n <Menu\n defaultValue={defaultValue}\n onValueChange={onValueChange}\n value={value}\n variant=\"menu2\"\n {...props}\n >\n <MenuContent ref={containerRef} variant=\"menu2\">\n {children}\n </MenuContent>\n </Menu>\n\n {showRightArrow && (\n <button\n onClick={() => internalScroll(containerRef.current, 'right')}\n className=\"absolute right-0 top-1/2 -translate-y-1/2 z-10 flex h-8 w-8 items-center justify-center rounded-full bg-white shadow-md cursor-pointer\"\n data-testid=\"scroll-right-button\"\n >\n <CaretRight size={16} />\n <span className=\"sr-only\">Scroll right</span>\n </button>\n )}\n </div>\n );\n};\n\nconst injectStore = (children: ReactNode, store: MenuStoreApi): ReactNode =>\n Children.map(children, (child) => {\n if (!isValidElement(child)) return child;\n /* eslint-disable-next-line @typescript-eslint/no-explicit-any */\n const typedChild = child as ReactElement<any>;\n const shouldInject = typedChild.type === MenuItem;\n return cloneElement(typedChild, {\n ...(shouldInject ? { store } : {}),\n ...(typedChild.props.children\n ? { children: injectStore(typedChild.props.children, store) }\n : {}),\n });\n });\n\nexport default Menu;\nexport {\n Menu,\n MenuContent,\n MenuItem,\n MenuSeparator,\n MenuOverflow,\n MenuItemIcon,\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAA2C;AAC3C,mBAaO;AACP,4BAAsC;AA4EhC;AAjEN,IAAM,kBAAkB,UACtB,uBAAkB,CAAC,SAAS;AAAA,EAC1B,OAAO;AAAA,EACP,UAAU,CAAC,UAAU,IAAI,EAAE,MAAM,CAAC;AACpC,EAAE;AAEG,IAAM,eAAe,CAAC,kBAAiC;AAC5D,MAAI,CAAC,cAAe,OAAM,IAAI,MAAM,8BAA8B;AAClE,SAAO;AACT;AAUA,IAAM,kBAAkB;AAAA,EACtB,MAAM;AAAA,EACN,OAAO;AAAA,EACP,YAAY;AACd;AAEA,IAAM,WAAO;AAAA,EACX,CACE;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,IACA,OAAO;AAAA,IACP,UAAU;AAAA,IACV;AAAA,IACA,GAAG;AAAA,EACL,GACA,QACG;AACH,UAAM,eAAW,qBAAqB,IAAI;AAC1C,aAAS,YAAY,gBAAgB;AACrC,UAAM,QAAQ,SAAS;AACvB,UAAM,EAAE,UAAU,MAAM,QAAI,yBAAS,OAAO,CAAC,MAAM,CAAC;AAEpD,gCAAU,MAAM;AACd,eAAS,aAAa,YAAY;AAAA,IACpC,GAAG,CAAC,cAAc,WAAW,QAAQ,CAAC;AAEtC,UAAM,uBAAmB,qBAAO,aAAa;AAC7C,UAAM,uBAAmB,qBAAO,KAAK;AACrC,qBAAiB,UAAU;AAE3B,gCAAU,MAAM;AAEd,UAAI,iBAAiB,SAAS;AAC5B,yBAAiB,UAAU,KAAK;AAAA,MAClC,OAAO;AACL,yBAAiB,UAAU;AAAA,MAC7B;AAAA,IACF,GAAG,CAAC,KAAK,CAAC;AAEV,UAAM,cACJ;AACF,UAAM,iBAAiB,gBAAgB,OAAO;AAE9C,WACE;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,WAAW;AAAA,YACP,WAAW;AAAA,YACX,cAAc;AAAA,YACd,aAAa,EAAE;AAAA;AAAA,QAElB,GAAG;AAAA,QAEH,sBAAY,UAAU,KAAK;AAAA;AAAA,IAC9B;AAAA,EAEJ;AACF;AACA,KAAK,cAAc;AAOnB,IAAM,kBAAc;AAAA,EAClB,CAAC,EAAE,WAAW,UAAU,UAAU,QAAQ,GAAG,MAAM,GAAG,QAAQ;AAC5D,UAAM,cAAc;AAEpB,UAAM,iBACJ,YAAY,UAAU,kCAAkC;AAE1D,WACE;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,WAAW;AAAA,YACP,WAAW;AAAA,YACX,cAAc;AAAA,YACd,aAAa,EAAE;AAAA;AAAA,QAEnB,OACE,YAAY,UACR,EAAE,gBAAgB,QAAQ,iBAAiB,OAAO,IAClD;AAAA,QAEL,GAAG;AAAA,QAEH;AAAA;AAAA,IACH;AAAA,EAEJ;AACF;AACA,YAAY,cAAc;AAS1B,IAAM,eAAW;AAAA,EACf,CACE;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,IACA,WAAW;AAAA,IACX,OAAO;AAAA,IACP,UAAU;AAAA,IACV,GAAG;AAAA,EACL,GACA,QACG;AACH,UAAM,QAAQ,aAAa,aAAa;AACxC,UAAM,EAAE,OAAO,eAAe,SAAS,QAAI,yBAAS,OAAO,CAAC,MAAM,CAAC;AAEnE,UAAM,cAAc,CAClB,MACG;AACH,UAAI,CAAC,SAAU,UAAS,KAAK;AAC7B,YAAM,UAAU,CAA8B;AAAA,IAChD;AAEA,UAAM,cAAc;AAAA,MAClB,MAAM;AAAA,MACN,iBAAiB;AAAA,MACjB;AAAA,MACA,SAAS;AAAA,MACT,WAAW,CAAC,MAAoC;AAC9C,YAAI,CAAC,SAAS,GAAG,EAAE,SAAS,EAAE,GAAG,EAAG,aAAY,CAAC;AAAA,MACnD;AAAA,MACA,UAAU,WAAW,KAAK;AAAA,MAC1B,aAAa,CAAC,MAAiC;AAC7C,UAAE,eAAe;AAAA,MACnB;AAAA,MACA,GAAG;AAAA,IACL;AAEA,UAAM,WAAsC;AAAA,MAC1C,MACE;AAAA,QAAC;AAAA;AAAA,UACC,gBAAa;AAAA,UACb,WAAW;AAAA;AAAA;AAAA;AAAA,cAIP,kBAAkB,QAAQ,mCAAmC,eAAe;AAAA,cAC5E,aAAa,EAAE;AAAA;AAAA,UAElB,GAAG;AAAA,UAEH;AAAA;AAAA,MACH;AAAA,MAEF,OACE;AAAA,QAAC;AAAA;AAAA,UACC,gBAAa;AAAA,UACb,WAAW;AAAA;AAAA;AAAA,cAGP,kBAAkB,QAAQ,yBAAyB,EAAE;AAAA,cACrD,aAAa,EAAE;AAAA;AAAA,UAElB,GAAG;AAAA,UAEH;AAAA;AAAA,MACH;AAAA,MAEF,YACE;AAAA,QAAC;AAAA;AAAA,UACC,gBAAa;AAAA,UACb,WAAW;AAAA;AAAA;AAAA,cAGP,kBAAkB,QAAQ,kBAAkB,eAAe;AAAA,cAC3D,aAAa,EAAE;AAAA;AAAA,UAElB,GAAG;AAAA,UAEJ;AAAA,YAAC;AAAA;AAAA,cACC,WAAW;AAAA;AAAA,gBAEP,kBAAkB,QAAQ,yBAAyB,sBAAsB;AAAA;AAAA,cAG5E;AAAA;AAAA,UACH;AAAA;AAAA,MACF;AAAA,IAEJ;AAEA,WAAO,SAAS,OAAO,KAAK,SAAS,MAAM;AAAA,EAC7C;AACF;AACA,SAAS,cAAc;AAEvB,IAAM,eAAe,CAAC;AAAA,EACpB;AAAA,EACA;AAAA,EACA,GAAG;AACL,MACE;AAAA,EAAC;AAAA;AAAA,IACC,WAAW;AAAA;AAAA,qDAEsC,aAAa,EAAE;AAAA;AAAA,IAE/D,GAAG;AAAA,IAEH;AAAA;AACH;AAGF,IAAM,oBAAgB;AAAA,EACpB,CAAC,EAAE,WAAW,UAAU,GAAG,MAAM,GAAG,QAClC;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,eAAY;AAAA,MACZ,WAAW,yCAAyC,aAAa,EAAE;AAAA,MAClE,GAAG;AAAA,MAEH,sBAAY,4CAAC,oCAAW;AAAA;AAAA,EAC3B;AAEJ;AACA,cAAc,cAAc;AAErB,IAAM,iBAAiB,CAC5B,WACA,cACG;AACH,MAAI,CAAC,UAAW;AAChB,YAAU,SAAS;AAAA,IACjB,MAAM,cAAc,SAAS,OAAO;AAAA,IACpC,UAAU;AAAA,EACZ,CAAC;AACH;AAEO,IAAM,sBAAsB,CACjC,WACA,kBACA,sBACG;AACH,MAAI,CAAC,UAAW;AAChB,QAAM,EAAE,YAAY,aAAa,YAAY,IAAI;AACjD,mBAAiB,aAAa,CAAC;AAC/B,oBAAkB,aAAa,cAAc,WAAW;AAC1D;AASA,IAAM,eAAe,CAAC;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,MAAyB;AACvB,QAAM,mBAAe,qBAAyB,IAAI;AAClD,QAAM,CAAC,eAAe,gBAAgB,QAAI,uBAAS,KAAK;AACxD,QAAM,CAAC,gBAAgB,iBAAiB,QAAI,uBAAS,KAAK;AAE1D,8BAAU,MAAM;AACd,UAAM,cAAc,MAClB;AAAA,MACE,aAAa;AAAA,MACb;AAAA,MACA;AAAA,IACF;AACF,gBAAY;AACZ,UAAM,YAAY,aAAa;AAC/B,eAAW,iBAAiB,UAAU,WAAW;AACjD,WAAO,iBAAiB,UAAU,WAAW;AAC7C,WAAO,MAAM;AACX,iBAAW,oBAAoB,UAAU,WAAW;AACpD,aAAO,oBAAoB,UAAU,WAAW;AAAA,IAClD;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,SACE;AAAA,IAAC;AAAA;AAAA,MACC,eAAY;AAAA,MACZ,WAAW,mCAAmC,aAAa,EAAE;AAAA,MAE5D;AAAA,yBACC;AAAA,UAAC;AAAA;AAAA,YACC,SAAS,MAAM,eAAe,aAAa,SAAS,MAAM;AAAA,YAC1D,WAAU;AAAA,YACV,eAAY;AAAA,YAEZ;AAAA,0DAAC,mCAAU,MAAM,IAAI;AAAA,cACrB,4CAAC,UAAK,WAAU,WAAU,yBAAW;AAAA;AAAA;AAAA,QACvC;AAAA,QAGF;AAAA,UAAC;AAAA;AAAA,YACC;AAAA,YACA;AAAA,YACA;AAAA,YACA,SAAQ;AAAA,YACP,GAAG;AAAA,YAEJ,sDAAC,eAAY,KAAK,cAAc,SAAQ,SACrC,UACH;AAAA;AAAA,QACF;AAAA,QAEC,kBACC;AAAA,UAAC;AAAA;AAAA,YACC,SAAS,MAAM,eAAe,aAAa,SAAS,OAAO;AAAA,YAC3D,WAAU;AAAA,YACV,eAAY;AAAA,YAEZ;AAAA,0DAAC,oCAAW,MAAM,IAAI;AAAA,cACtB,4CAAC,UAAK,WAAU,WAAU,0BAAY;AAAA;AAAA;AAAA,QACxC;AAAA;AAAA;AAAA,EAEJ;AAEJ;AAEA,IAAM,cAAc,CAAC,UAAqB,UACxC,sBAAS,IAAI,UAAU,CAAC,UAAU;AAChC,MAAI,KAAC,6BAAe,KAAK,EAAG,QAAO;AAEnC,QAAM,aAAa;AACnB,QAAM,eAAe,WAAW,SAAS;AACzC,aAAO,2BAAa,YAAY;AAAA,IAC9B,GAAI,eAAe,EAAE,MAAM,IAAI,CAAC;AAAA,IAChC,GAAI,WAAW,MAAM,WACjB,EAAE,UAAU,YAAY,WAAW,MAAM,UAAU,KAAK,EAAE,IAC1D,CAAC;AAAA,EACP,CAAC;AACH,CAAC;AAEH,IAAO,eAAQ;","names":[]}
1
+ {"version":3,"sources":["../../src/components/Menu/Menu.tsx"],"sourcesContent":["import { create, StoreApi, useStore } from 'zustand';\nimport {\n ReactNode,\n useEffect,\n useRef,\n forwardRef,\n HTMLAttributes,\n KeyboardEvent,\n MouseEvent,\n ReactElement,\n isValidElement,\n Children,\n cloneElement,\n useState,\n} from 'react';\nimport { CaretLeft, CaretRight } from 'phosphor-react';\n\ntype MenuVariant = 'menu' | 'menu2' | 'breadcrumb';\n\ninterface MenuStore {\n value: string;\n setValue: (value: string) => void;\n}\n\ntype MenuStoreApi = StoreApi<MenuStore>;\n\nconst createMenuStore = (): MenuStoreApi =>\n create<MenuStore>((set) => ({\n value: '',\n setValue: (value) => set({ value }),\n }));\n\nexport const useMenuStore = (externalStore?: MenuStoreApi) => {\n if (!externalStore) throw new Error('MenuItem must be inside Menu');\n return externalStore;\n};\n\ninterface MenuProps extends HTMLAttributes<HTMLDivElement> {\n children: ReactNode;\n defaultValue: string;\n value?: string;\n variant?: MenuVariant;\n onValueChange?: (value: string) => void;\n}\n\nconst VARIANT_CLASSES = {\n menu: 'bg-background shadow-soft-shadow-1',\n menu2: '',\n breadcrumb: '',\n};\n\nconst Menu = forwardRef<HTMLDivElement, MenuProps>(\n (\n {\n className,\n children,\n defaultValue,\n value: propValue,\n variant = 'menu',\n onValueChange,\n ...props\n },\n ref\n ) => {\n const storeRef = useRef<MenuStoreApi>(null);\n storeRef.current ??= createMenuStore();\n const store = storeRef.current;\n const { setValue, value } = useStore(store, (s) => s);\n\n useEffect(() => {\n setValue(propValue ?? defaultValue);\n }, [defaultValue, propValue, setValue]);\n\n const onValueChangeRef = useRef(onValueChange);\n const isInitializedRef = useRef(false);\n onValueChangeRef.current = onValueChange;\n\n useEffect(() => {\n // Só chama onValueChange se não for a inicialização\n if (isInitializedRef.current) {\n onValueChangeRef.current?.(value);\n } else {\n isInitializedRef.current = true;\n }\n }, [value]);\n\n const baseClasses =\n 'w-full py-2 px-6 flex flex-row items-center justify-center';\n const variantClasses = VARIANT_CLASSES[variant];\n\n return (\n <div\n ref={ref}\n className={`\n ${baseClasses}\n ${variantClasses}\n ${className ?? ''}\n `}\n {...props}\n >\n {injectStore(children, store)}\n </div>\n );\n }\n);\nMenu.displayName = 'Menu';\n\ninterface MenuContentProps extends HTMLAttributes<HTMLUListElement> {\n children: ReactNode;\n variant?: MenuVariant;\n}\n\nconst MenuContent = forwardRef<HTMLUListElement, MenuContentProps>(\n ({ className, children, variant = 'menu', ...props }, ref) => {\n const baseClasses = 'w-full flex flex-row items-center gap-2';\n\n const variantClasses =\n variant === 'menu2' ? 'overflow-x-auto scroll-smooth' : '';\n\n return (\n <ul\n ref={ref}\n className={`\n ${baseClasses}\n ${variantClasses}\n ${className ?? ''}\n `}\n style={\n variant === 'menu2'\n ? { scrollbarWidth: 'none', msOverflowStyle: 'none' }\n : undefined\n }\n {...props}\n >\n {children}\n </ul>\n );\n }\n);\nMenuContent.displayName = 'MenuContent';\n\ninterface MenuItemProps extends HTMLAttributes<HTMLLIElement> {\n value: string;\n disabled?: boolean;\n store?: MenuStoreApi;\n variant?: MenuVariant;\n}\n\nconst MenuItem = forwardRef<HTMLLIElement, MenuItemProps>(\n (\n {\n className,\n children,\n value,\n disabled = false,\n store: externalStore,\n variant = 'menu',\n ...props\n },\n ref\n ) => {\n const store = useMenuStore(externalStore);\n const { value: selectedValue, setValue } = useStore(store, (s) => s);\n\n const handleClick = (\n e: MouseEvent<HTMLLIElement> | KeyboardEvent<HTMLLIElement>\n ) => {\n if (!disabled) setValue(value);\n props.onClick?.(e as MouseEvent<HTMLLIElement>);\n };\n\n const commonProps = {\n role: 'menuitem',\n 'aria-disabled': disabled,\n ref,\n onClick: handleClick,\n onKeyDown: (e: KeyboardEvent<HTMLLIElement>) => {\n if (['Enter', ' '].includes(e.key)) handleClick(e);\n },\n tabIndex: disabled ? -1 : 0,\n onMouseDown: (e: MouseEvent<HTMLLIElement>) => {\n e.preventDefault();\n },\n ...props,\n };\n\n const variants: Record<string, ReactNode> = {\n menu: (\n <li\n data-variant=\"menu\"\n className={`\n w-full flex flex-col items-center justify-center gap-0.5 py-1 px-2 rounded-sm font-medium text-xs\n [&>svg]:size-6 cursor-pointer hover:bg-primary-600 hover:text-text\n focus:outline-none focus:border-indicator-info focus:border-2\n ${selectedValue === value ? 'bg-primary-50 text-primary-950' : 'text-text-950'}\n ${className ?? ''}\n `}\n {...commonProps}\n >\n {children}\n </li>\n ),\n menu2: (\n <li\n data-variant=\"menu2\"\n className={`\n w-full flex flex-row items-center p-4 gap-2 border-b-4 border-transparent text-text-950 text-sx font-bold cursor-pointer focus:rounded-sm\n focus:outline-none focus:border-indicator-info focus:border-2\n ${selectedValue === value ? 'border-b-primary-950' : ''}\n ${className ?? ''}\n `}\n {...commonProps}\n >\n {children}\n </li>\n ),\n breadcrumb: (\n <li\n data-variant=\"breadcrumb\"\n className={`\n w-full p-2 rounded-lg hover:text-primary-600 cursor-pointer font-bold text-xs\n focus:outline-none focus:border-indicator-info focus:border-2\n ${selectedValue === value ? 'text-text-950' : 'text-text-600'}\n ${className ?? ''}\n `}\n {...commonProps}\n >\n <span\n className={`\n border-b border-text-600 hover:border-primary-600 text-inherit text-xs\n ${selectedValue === value ? 'border-b-0 font-bold' : 'border-b-primary-600'}\n `}\n >\n {children}\n </span>\n </li>\n ),\n };\n\n return variants[variant] ?? variants['menu'];\n }\n);\nMenuItem.displayName = 'MenuItem';\n\nconst MenuItemIcon = ({\n className,\n icon,\n ...props\n}: HTMLAttributes<HTMLSpanElement> & { icon: ReactNode }) => (\n <span\n className={`\n bg-background-500 w-[21px] h-[21px] flex items-center justify-center\n [&>svg]:w-[17px] [&>svg]:h-[17px] rounded-sm ${className ?? ''}\n `}\n {...props}\n >\n {icon}\n </span>\n);\n\nconst MenuSeparator = forwardRef<HTMLLIElement, HTMLAttributes<HTMLLIElement>>(\n ({ className, children, ...props }, ref) => (\n <li\n ref={ref}\n aria-hidden=\"true\"\n className={`[&>svg]:w-4 [&>svg]:h-4 text-text-600 ${className ?? ''}`}\n {...props}\n >\n {children ?? <CaretRight />}\n </li>\n )\n);\nMenuSeparator.displayName = 'MenuSeparator';\n\nexport const internalScroll = (\n container: HTMLUListElement | null,\n direction: 'left' | 'right'\n) => {\n if (!container) return;\n container.scrollBy({\n left: direction === 'left' ? -150 : 150,\n behavior: 'smooth',\n });\n};\n\nexport const internalCheckScroll = (\n container: HTMLUListElement | null,\n setShowLeftArrow: (v: boolean) => void,\n setShowRightArrow: (v: boolean) => void\n) => {\n if (!container) return;\n const { scrollLeft, scrollWidth, clientWidth } = container;\n setShowLeftArrow(scrollLeft > 0);\n setShowRightArrow(scrollLeft + clientWidth < scrollWidth);\n};\n\ninterface MenuOverflowProps extends HTMLAttributes<HTMLDivElement> {\n children: ReactNode;\n defaultValue: string;\n value?: string;\n onValueChange?: (value: string) => void;\n}\n\nconst MenuOverflow = ({\n children,\n className,\n defaultValue,\n value,\n onValueChange,\n ...props\n}: MenuOverflowProps) => {\n const containerRef = useRef<HTMLUListElement>(null);\n const [showLeftArrow, setShowLeftArrow] = useState(false);\n const [showRightArrow, setShowRightArrow] = useState(false);\n\n useEffect(() => {\n const checkScroll = () =>\n internalCheckScroll(\n containerRef.current,\n setShowLeftArrow,\n setShowRightArrow\n );\n checkScroll();\n const container = containerRef.current;\n container?.addEventListener('scroll', checkScroll);\n window.addEventListener('resize', checkScroll);\n return () => {\n container?.removeEventListener('scroll', checkScroll);\n window.removeEventListener('resize', checkScroll);\n };\n }, []);\n\n return (\n <div\n data-testid=\"menu-overflow-wrapper\"\n className={`relative w-full overflow-hidden ${className ?? ''}`}\n >\n {showLeftArrow && (\n <button\n onClick={() => internalScroll(containerRef.current, 'left')}\n className=\"absolute left-0 top-1/2 -translate-y-1/2 z-10 flex h-8 w-8 items-center justify-center rounded-full bg-white shadow-md cursor-pointer\"\n data-testid=\"scroll-left-button\"\n >\n <CaretLeft size={16} />\n <span className=\"sr-only\">Scroll left</span>\n </button>\n )}\n\n <Menu\n defaultValue={defaultValue}\n onValueChange={onValueChange}\n value={value}\n variant=\"menu2\"\n {...props}\n >\n <MenuContent ref={containerRef} variant=\"menu2\">\n {children}\n </MenuContent>\n </Menu>\n\n {showRightArrow && (\n <button\n onClick={() => internalScroll(containerRef.current, 'right')}\n className=\"absolute right-0 top-1/2 -translate-y-1/2 z-10 flex h-8 w-8 items-center justify-center rounded-full bg-white shadow-md cursor-pointer\"\n data-testid=\"scroll-right-button\"\n >\n <CaretRight size={16} />\n <span className=\"sr-only\">Scroll right</span>\n </button>\n )}\n </div>\n );\n};\n\nconst injectStore = (children: ReactNode, store: MenuStoreApi): ReactNode =>\n Children.map(children, (child) => {\n if (!isValidElement(child)) return child;\n /* eslint-disable-next-line @typescript-eslint/no-explicit-any */\n const typedChild = child as ReactElement<any>;\n const shouldInject = typedChild.type === MenuItem;\n return cloneElement(typedChild, {\n ...(shouldInject ? { store } : {}),\n ...(typedChild.props.children\n ? { children: injectStore(typedChild.props.children, store) }\n : {}),\n });\n });\n\nexport default Menu;\nexport {\n Menu,\n MenuContent,\n MenuItem,\n MenuSeparator,\n MenuOverflow,\n MenuItemIcon,\n};\n"],"mappings":"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","names":[]}
@@ -126,7 +126,7 @@ var MenuItem = forwardRef(
126
126
  {
127
127
  "data-variant": "menu",
128
128
  className: `
129
- w-full flex flex-col gap-0.5 items-center py-1 px-2 rounded-sm font-medium text-xs
129
+ w-full flex flex-col items-center justify-center gap-0.5 py-1 px-2 rounded-sm font-medium text-xs
130
130
  [&>svg]:size-6 cursor-pointer hover:bg-primary-600 hover:text-text
131
131
  focus:outline-none focus:border-indicator-info focus:border-2
132
132
  ${selectedValue === value ? "bg-primary-50 text-primary-950" : "text-text-950"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/Menu/Menu.tsx"],"sourcesContent":["import { create, StoreApi, useStore } from 'zustand';\nimport {\n ReactNode,\n useEffect,\n useRef,\n forwardRef,\n HTMLAttributes,\n KeyboardEvent,\n MouseEvent,\n ReactElement,\n isValidElement,\n Children,\n cloneElement,\n useState,\n} from 'react';\nimport { CaretLeft, CaretRight } from 'phosphor-react';\n\ntype MenuVariant = 'menu' | 'menu2' | 'breadcrumb';\n\ninterface MenuStore {\n value: string;\n setValue: (value: string) => void;\n}\n\ntype MenuStoreApi = StoreApi<MenuStore>;\n\nconst createMenuStore = (): MenuStoreApi =>\n create<MenuStore>((set) => ({\n value: '',\n setValue: (value) => set({ value }),\n }));\n\nexport const useMenuStore = (externalStore?: MenuStoreApi) => {\n if (!externalStore) throw new Error('MenuItem must be inside Menu');\n return externalStore;\n};\n\ninterface MenuProps extends HTMLAttributes<HTMLDivElement> {\n children: ReactNode;\n defaultValue: string;\n value?: string;\n variant?: MenuVariant;\n onValueChange?: (value: string) => void;\n}\n\nconst VARIANT_CLASSES = {\n menu: 'bg-background shadow-soft-shadow-1',\n menu2: '',\n breadcrumb: '',\n};\n\nconst Menu = forwardRef<HTMLDivElement, MenuProps>(\n (\n {\n className,\n children,\n defaultValue,\n value: propValue,\n variant = 'menu',\n onValueChange,\n ...props\n },\n ref\n ) => {\n const storeRef = useRef<MenuStoreApi>(null);\n storeRef.current ??= createMenuStore();\n const store = storeRef.current;\n const { setValue, value } = useStore(store, (s) => s);\n\n useEffect(() => {\n setValue(propValue ?? defaultValue);\n }, [defaultValue, propValue, setValue]);\n\n const onValueChangeRef = useRef(onValueChange);\n const isInitializedRef = useRef(false);\n onValueChangeRef.current = onValueChange;\n\n useEffect(() => {\n // Só chama onValueChange se não for a inicialização\n if (isInitializedRef.current) {\n onValueChangeRef.current?.(value);\n } else {\n isInitializedRef.current = true;\n }\n }, [value]);\n\n const baseClasses =\n 'w-full py-2 px-6 flex flex-row items-center justify-center';\n const variantClasses = VARIANT_CLASSES[variant];\n\n return (\n <div\n ref={ref}\n className={`\n ${baseClasses}\n ${variantClasses}\n ${className ?? ''}\n `}\n {...props}\n >\n {injectStore(children, store)}\n </div>\n );\n }\n);\nMenu.displayName = 'Menu';\n\ninterface MenuContentProps extends HTMLAttributes<HTMLUListElement> {\n children: ReactNode;\n variant?: MenuVariant;\n}\n\nconst MenuContent = forwardRef<HTMLUListElement, MenuContentProps>(\n ({ className, children, variant = 'menu', ...props }, ref) => {\n const baseClasses = 'w-full flex flex-row items-center gap-2';\n\n const variantClasses =\n variant === 'menu2' ? 'overflow-x-auto scroll-smooth' : '';\n\n return (\n <ul\n ref={ref}\n className={`\n ${baseClasses}\n ${variantClasses}\n ${className ?? ''}\n `}\n style={\n variant === 'menu2'\n ? { scrollbarWidth: 'none', msOverflowStyle: 'none' }\n : undefined\n }\n {...props}\n >\n {children}\n </ul>\n );\n }\n);\nMenuContent.displayName = 'MenuContent';\n\ninterface MenuItemProps extends HTMLAttributes<HTMLLIElement> {\n value: string;\n disabled?: boolean;\n store?: MenuStoreApi;\n variant?: MenuVariant;\n}\n\nconst MenuItem = forwardRef<HTMLLIElement, MenuItemProps>(\n (\n {\n className,\n children,\n value,\n disabled = false,\n store: externalStore,\n variant = 'menu',\n ...props\n },\n ref\n ) => {\n const store = useMenuStore(externalStore);\n const { value: selectedValue, setValue } = useStore(store, (s) => s);\n\n const handleClick = (\n e: MouseEvent<HTMLLIElement> | KeyboardEvent<HTMLLIElement>\n ) => {\n if (!disabled) setValue(value);\n props.onClick?.(e as MouseEvent<HTMLLIElement>);\n };\n\n const commonProps = {\n role: 'menuitem',\n 'aria-disabled': disabled,\n ref,\n onClick: handleClick,\n onKeyDown: (e: KeyboardEvent<HTMLLIElement>) => {\n if (['Enter', ' '].includes(e.key)) handleClick(e);\n },\n tabIndex: disabled ? -1 : 0,\n onMouseDown: (e: MouseEvent<HTMLLIElement>) => {\n e.preventDefault();\n },\n ...props,\n };\n\n const variants: Record<string, ReactNode> = {\n menu: (\n <li\n data-variant=\"menu\"\n className={`\n w-full flex flex-col gap-0.5 items-center py-1 px-2 rounded-sm font-medium text-xs\n [&>svg]:size-6 cursor-pointer hover:bg-primary-600 hover:text-text\n focus:outline-none focus:border-indicator-info focus:border-2\n ${selectedValue === value ? 'bg-primary-50 text-primary-950' : 'text-text-950'}\n ${className ?? ''}\n `}\n {...commonProps}\n >\n {children}\n </li>\n ),\n menu2: (\n <li\n data-variant=\"menu2\"\n className={`\n w-full flex flex-row items-center p-4 gap-2 border-b-4 border-transparent text-text-950 text-sx font-bold cursor-pointer focus:rounded-sm\n focus:outline-none focus:border-indicator-info focus:border-2\n ${selectedValue === value ? 'border-b-primary-950' : ''}\n ${className ?? ''}\n `}\n {...commonProps}\n >\n {children}\n </li>\n ),\n breadcrumb: (\n <li\n data-variant=\"breadcrumb\"\n className={`\n w-full p-2 rounded-lg hover:text-primary-600 cursor-pointer font-bold text-xs\n focus:outline-none focus:border-indicator-info focus:border-2\n ${selectedValue === value ? 'text-text-950' : 'text-text-600'}\n ${className ?? ''}\n `}\n {...commonProps}\n >\n <span\n className={`\n border-b border-text-600 hover:border-primary-600 text-inherit text-xs\n ${selectedValue === value ? 'border-b-0 font-bold' : 'border-b-primary-600'}\n `}\n >\n {children}\n </span>\n </li>\n ),\n };\n\n return variants[variant] ?? variants['menu'];\n }\n);\nMenuItem.displayName = 'MenuItem';\n\nconst MenuItemIcon = ({\n className,\n icon,\n ...props\n}: HTMLAttributes<HTMLSpanElement> & { icon: ReactNode }) => (\n <span\n className={`\n bg-background-500 w-[21px] h-[21px] flex items-center justify-center\n [&>svg]:w-[17px] [&>svg]:h-[17px] rounded-sm ${className ?? ''}\n `}\n {...props}\n >\n {icon}\n </span>\n);\n\nconst MenuSeparator = forwardRef<HTMLLIElement, HTMLAttributes<HTMLLIElement>>(\n ({ className, children, ...props }, ref) => (\n <li\n ref={ref}\n aria-hidden=\"true\"\n className={`[&>svg]:w-4 [&>svg]:h-4 text-text-600 ${className ?? ''}`}\n {...props}\n >\n {children ?? <CaretRight />}\n </li>\n )\n);\nMenuSeparator.displayName = 'MenuSeparator';\n\nexport const internalScroll = (\n container: HTMLUListElement | null,\n direction: 'left' | 'right'\n) => {\n if (!container) return;\n container.scrollBy({\n left: direction === 'left' ? -150 : 150,\n behavior: 'smooth',\n });\n};\n\nexport const internalCheckScroll = (\n container: HTMLUListElement | null,\n setShowLeftArrow: (v: boolean) => void,\n setShowRightArrow: (v: boolean) => void\n) => {\n if (!container) return;\n const { scrollLeft, scrollWidth, clientWidth } = container;\n setShowLeftArrow(scrollLeft > 0);\n setShowRightArrow(scrollLeft + clientWidth < scrollWidth);\n};\n\ninterface MenuOverflowProps extends HTMLAttributes<HTMLDivElement> {\n children: ReactNode;\n defaultValue: string;\n value?: string;\n onValueChange?: (value: string) => void;\n}\n\nconst MenuOverflow = ({\n children,\n className,\n defaultValue,\n value,\n onValueChange,\n ...props\n}: MenuOverflowProps) => {\n const containerRef = useRef<HTMLUListElement>(null);\n const [showLeftArrow, setShowLeftArrow] = useState(false);\n const [showRightArrow, setShowRightArrow] = useState(false);\n\n useEffect(() => {\n const checkScroll = () =>\n internalCheckScroll(\n containerRef.current,\n setShowLeftArrow,\n setShowRightArrow\n );\n checkScroll();\n const container = containerRef.current;\n container?.addEventListener('scroll', checkScroll);\n window.addEventListener('resize', checkScroll);\n return () => {\n container?.removeEventListener('scroll', checkScroll);\n window.removeEventListener('resize', checkScroll);\n };\n }, []);\n\n return (\n <div\n data-testid=\"menu-overflow-wrapper\"\n className={`relative w-full overflow-hidden ${className ?? ''}`}\n >\n {showLeftArrow && (\n <button\n onClick={() => internalScroll(containerRef.current, 'left')}\n className=\"absolute left-0 top-1/2 -translate-y-1/2 z-10 flex h-8 w-8 items-center justify-center rounded-full bg-white shadow-md cursor-pointer\"\n data-testid=\"scroll-left-button\"\n >\n <CaretLeft size={16} />\n <span className=\"sr-only\">Scroll left</span>\n </button>\n )}\n\n <Menu\n defaultValue={defaultValue}\n onValueChange={onValueChange}\n value={value}\n variant=\"menu2\"\n {...props}\n >\n <MenuContent ref={containerRef} variant=\"menu2\">\n {children}\n </MenuContent>\n </Menu>\n\n {showRightArrow && (\n <button\n onClick={() => internalScroll(containerRef.current, 'right')}\n className=\"absolute right-0 top-1/2 -translate-y-1/2 z-10 flex h-8 w-8 items-center justify-center rounded-full bg-white shadow-md cursor-pointer\"\n data-testid=\"scroll-right-button\"\n >\n <CaretRight size={16} />\n <span className=\"sr-only\">Scroll right</span>\n </button>\n )}\n </div>\n );\n};\n\nconst injectStore = (children: ReactNode, store: MenuStoreApi): ReactNode =>\n Children.map(children, (child) => {\n if (!isValidElement(child)) return child;\n /* eslint-disable-next-line @typescript-eslint/no-explicit-any */\n const typedChild = child as ReactElement<any>;\n const shouldInject = typedChild.type === MenuItem;\n return cloneElement(typedChild, {\n ...(shouldInject ? { store } : {}),\n ...(typedChild.props.children\n ? { children: injectStore(typedChild.props.children, store) }\n : {}),\n });\n });\n\nexport default Menu;\nexport {\n Menu,\n MenuContent,\n MenuItem,\n MenuSeparator,\n MenuOverflow,\n MenuItemIcon,\n};\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/components/Menu/Menu.tsx"],"sourcesContent":["import { create, StoreApi, useStore } from 'zustand';\nimport {\n ReactNode,\n useEffect,\n useRef,\n forwardRef,\n HTMLAttributes,\n KeyboardEvent,\n MouseEvent,\n ReactElement,\n isValidElement,\n Children,\n cloneElement,\n useState,\n} from 'react';\nimport { CaretLeft, CaretRight } from 'phosphor-react';\n\ntype MenuVariant = 'menu' | 'menu2' | 'breadcrumb';\n\ninterface MenuStore {\n value: string;\n setValue: (value: string) => void;\n}\n\ntype MenuStoreApi = StoreApi<MenuStore>;\n\nconst createMenuStore = (): MenuStoreApi =>\n create<MenuStore>((set) => ({\n value: '',\n setValue: (value) => set({ value }),\n }));\n\nexport const useMenuStore = (externalStore?: MenuStoreApi) => {\n if (!externalStore) throw new Error('MenuItem must be inside Menu');\n return externalStore;\n};\n\ninterface MenuProps extends HTMLAttributes<HTMLDivElement> {\n children: ReactNode;\n defaultValue: string;\n value?: string;\n variant?: MenuVariant;\n onValueChange?: (value: string) => void;\n}\n\nconst VARIANT_CLASSES = {\n menu: 'bg-background shadow-soft-shadow-1',\n menu2: '',\n breadcrumb: '',\n};\n\nconst Menu = forwardRef<HTMLDivElement, MenuProps>(\n (\n {\n className,\n children,\n defaultValue,\n value: propValue,\n variant = 'menu',\n onValueChange,\n ...props\n },\n ref\n ) => {\n const storeRef = useRef<MenuStoreApi>(null);\n storeRef.current ??= createMenuStore();\n const store = storeRef.current;\n const { setValue, value } = useStore(store, (s) => s);\n\n useEffect(() => {\n setValue(propValue ?? defaultValue);\n }, [defaultValue, propValue, setValue]);\n\n const onValueChangeRef = useRef(onValueChange);\n const isInitializedRef = useRef(false);\n onValueChangeRef.current = onValueChange;\n\n useEffect(() => {\n // Só chama onValueChange se não for a inicialização\n if (isInitializedRef.current) {\n onValueChangeRef.current?.(value);\n } else {\n isInitializedRef.current = true;\n }\n }, [value]);\n\n const baseClasses =\n 'w-full py-2 px-6 flex flex-row items-center justify-center';\n const variantClasses = VARIANT_CLASSES[variant];\n\n return (\n <div\n ref={ref}\n className={`\n ${baseClasses}\n ${variantClasses}\n ${className ?? ''}\n `}\n {...props}\n >\n {injectStore(children, store)}\n </div>\n );\n }\n);\nMenu.displayName = 'Menu';\n\ninterface MenuContentProps extends HTMLAttributes<HTMLUListElement> {\n children: ReactNode;\n variant?: MenuVariant;\n}\n\nconst MenuContent = forwardRef<HTMLUListElement, MenuContentProps>(\n ({ className, children, variant = 'menu', ...props }, ref) => {\n const baseClasses = 'w-full flex flex-row items-center gap-2';\n\n const variantClasses =\n variant === 'menu2' ? 'overflow-x-auto scroll-smooth' : '';\n\n return (\n <ul\n ref={ref}\n className={`\n ${baseClasses}\n ${variantClasses}\n ${className ?? ''}\n `}\n style={\n variant === 'menu2'\n ? { scrollbarWidth: 'none', msOverflowStyle: 'none' }\n : undefined\n }\n {...props}\n >\n {children}\n </ul>\n );\n }\n);\nMenuContent.displayName = 'MenuContent';\n\ninterface MenuItemProps extends HTMLAttributes<HTMLLIElement> {\n value: string;\n disabled?: boolean;\n store?: MenuStoreApi;\n variant?: MenuVariant;\n}\n\nconst MenuItem = forwardRef<HTMLLIElement, MenuItemProps>(\n (\n {\n className,\n children,\n value,\n disabled = false,\n store: externalStore,\n variant = 'menu',\n ...props\n },\n ref\n ) => {\n const store = useMenuStore(externalStore);\n const { value: selectedValue, setValue } = useStore(store, (s) => s);\n\n const handleClick = (\n e: MouseEvent<HTMLLIElement> | KeyboardEvent<HTMLLIElement>\n ) => {\n if (!disabled) setValue(value);\n props.onClick?.(e as MouseEvent<HTMLLIElement>);\n };\n\n const commonProps = {\n role: 'menuitem',\n 'aria-disabled': disabled,\n ref,\n onClick: handleClick,\n onKeyDown: (e: KeyboardEvent<HTMLLIElement>) => {\n if (['Enter', ' '].includes(e.key)) handleClick(e);\n },\n tabIndex: disabled ? -1 : 0,\n onMouseDown: (e: MouseEvent<HTMLLIElement>) => {\n e.preventDefault();\n },\n ...props,\n };\n\n const variants: Record<string, ReactNode> = {\n menu: (\n <li\n data-variant=\"menu\"\n className={`\n w-full flex flex-col items-center justify-center gap-0.5 py-1 px-2 rounded-sm font-medium text-xs\n [&>svg]:size-6 cursor-pointer hover:bg-primary-600 hover:text-text\n focus:outline-none focus:border-indicator-info focus:border-2\n ${selectedValue === value ? 'bg-primary-50 text-primary-950' : 'text-text-950'}\n ${className ?? ''}\n `}\n {...commonProps}\n >\n {children}\n </li>\n ),\n menu2: (\n <li\n data-variant=\"menu2\"\n className={`\n w-full flex flex-row items-center p-4 gap-2 border-b-4 border-transparent text-text-950 text-sx font-bold cursor-pointer focus:rounded-sm\n focus:outline-none focus:border-indicator-info focus:border-2\n ${selectedValue === value ? 'border-b-primary-950' : ''}\n ${className ?? ''}\n `}\n {...commonProps}\n >\n {children}\n </li>\n ),\n breadcrumb: (\n <li\n data-variant=\"breadcrumb\"\n className={`\n w-full p-2 rounded-lg hover:text-primary-600 cursor-pointer font-bold text-xs\n focus:outline-none focus:border-indicator-info focus:border-2\n ${selectedValue === value ? 'text-text-950' : 'text-text-600'}\n ${className ?? ''}\n `}\n {...commonProps}\n >\n <span\n className={`\n border-b border-text-600 hover:border-primary-600 text-inherit text-xs\n ${selectedValue === value ? 'border-b-0 font-bold' : 'border-b-primary-600'}\n `}\n >\n {children}\n </span>\n </li>\n ),\n };\n\n return variants[variant] ?? variants['menu'];\n }\n);\nMenuItem.displayName = 'MenuItem';\n\nconst MenuItemIcon = ({\n className,\n icon,\n ...props\n}: HTMLAttributes<HTMLSpanElement> & { icon: ReactNode }) => (\n <span\n className={`\n bg-background-500 w-[21px] h-[21px] flex items-center justify-center\n [&>svg]:w-[17px] [&>svg]:h-[17px] rounded-sm ${className ?? ''}\n `}\n {...props}\n >\n {icon}\n </span>\n);\n\nconst MenuSeparator = forwardRef<HTMLLIElement, HTMLAttributes<HTMLLIElement>>(\n ({ className, children, ...props }, ref) => (\n <li\n ref={ref}\n aria-hidden=\"true\"\n className={`[&>svg]:w-4 [&>svg]:h-4 text-text-600 ${className ?? ''}`}\n {...props}\n >\n {children ?? <CaretRight />}\n </li>\n )\n);\nMenuSeparator.displayName = 'MenuSeparator';\n\nexport const internalScroll = (\n container: HTMLUListElement | null,\n direction: 'left' | 'right'\n) => {\n if (!container) return;\n container.scrollBy({\n left: direction === 'left' ? -150 : 150,\n behavior: 'smooth',\n });\n};\n\nexport const internalCheckScroll = (\n container: HTMLUListElement | null,\n setShowLeftArrow: (v: boolean) => void,\n setShowRightArrow: (v: boolean) => void\n) => {\n if (!container) return;\n const { scrollLeft, scrollWidth, clientWidth } = container;\n setShowLeftArrow(scrollLeft > 0);\n setShowRightArrow(scrollLeft + clientWidth < scrollWidth);\n};\n\ninterface MenuOverflowProps extends HTMLAttributes<HTMLDivElement> {\n children: ReactNode;\n defaultValue: string;\n value?: string;\n onValueChange?: (value: string) => void;\n}\n\nconst MenuOverflow = ({\n children,\n className,\n defaultValue,\n value,\n onValueChange,\n ...props\n}: MenuOverflowProps) => {\n const containerRef = useRef<HTMLUListElement>(null);\n const [showLeftArrow, setShowLeftArrow] = useState(false);\n const [showRightArrow, setShowRightArrow] = useState(false);\n\n useEffect(() => {\n const checkScroll = () =>\n internalCheckScroll(\n containerRef.current,\n setShowLeftArrow,\n setShowRightArrow\n );\n checkScroll();\n const container = containerRef.current;\n container?.addEventListener('scroll', checkScroll);\n window.addEventListener('resize', checkScroll);\n return () => {\n container?.removeEventListener('scroll', checkScroll);\n window.removeEventListener('resize', checkScroll);\n };\n }, []);\n\n return (\n <div\n data-testid=\"menu-overflow-wrapper\"\n className={`relative w-full overflow-hidden ${className ?? ''}`}\n >\n {showLeftArrow && (\n <button\n onClick={() => internalScroll(containerRef.current, 'left')}\n className=\"absolute left-0 top-1/2 -translate-y-1/2 z-10 flex h-8 w-8 items-center justify-center rounded-full bg-white shadow-md cursor-pointer\"\n data-testid=\"scroll-left-button\"\n >\n <CaretLeft size={16} />\n <span className=\"sr-only\">Scroll left</span>\n </button>\n )}\n\n <Menu\n defaultValue={defaultValue}\n onValueChange={onValueChange}\n value={value}\n variant=\"menu2\"\n {...props}\n >\n <MenuContent ref={containerRef} variant=\"menu2\">\n {children}\n </MenuContent>\n </Menu>\n\n {showRightArrow && (\n <button\n onClick={() => internalScroll(containerRef.current, 'right')}\n className=\"absolute right-0 top-1/2 -translate-y-1/2 z-10 flex h-8 w-8 items-center justify-center rounded-full bg-white shadow-md cursor-pointer\"\n data-testid=\"scroll-right-button\"\n >\n <CaretRight size={16} />\n <span className=\"sr-only\">Scroll right</span>\n </button>\n )}\n </div>\n );\n};\n\nconst injectStore = (children: ReactNode, store: MenuStoreApi): ReactNode =>\n Children.map(children, (child) => {\n if (!isValidElement(child)) return child;\n /* eslint-disable-next-line @typescript-eslint/no-explicit-any */\n const typedChild = child as ReactElement<any>;\n const shouldInject = typedChild.type === MenuItem;\n return cloneElement(typedChild, {\n ...(shouldInject ? { store } : {}),\n ...(typedChild.props.children\n ? { children: injectStore(typedChild.props.children, store) }\n : {}),\n });\n });\n\nexport default Menu;\nexport {\n Menu,\n MenuContent,\n MenuItem,\n MenuSeparator,\n MenuOverflow,\n MenuItemIcon,\n};\n"],"mappings":"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","names":[]}
package/dist/index.css CHANGED
@@ -26,6 +26,7 @@
26
26
  --color-amber-500: oklch(76.9% 0.188 70.08);
27
27
  --color-yellow-300: oklch(90.5% 0.182 98.111);
28
28
  --color-yellow-500: oklch(79.5% 0.184 86.047);
29
+ --color-green-500: oklch(72.3% 0.219 149.579);
29
30
  --color-blue-500: oklch(62.3% 0.214 259.815);
30
31
  --color-gray-800: oklch(27.8% 0.033 256.848);
31
32
  --color-black: #000;
@@ -900,21 +901,12 @@
900
901
  .max-w-\[90px\] {
901
902
  max-width: 90px;
902
903
  }
903
- .max-w-\[128px\] {
904
- max-width: 128px;
905
- }
906
- .max-w-\[180px\] {
907
- max-width: 180px;
908
- }
909
- .max-w-\[262px\] {
910
- max-width: 262px;
904
+ .max-w-\[140px\] {
905
+ max-width: 140px;
911
906
  }
912
907
  .max-w-\[360px\] {
913
908
  max-width: 360px;
914
909
  }
915
- .max-w-\[380px\] {
916
- max-width: 380px;
917
- }
918
910
  .max-w-\[390px\] {
919
911
  max-width: 390px;
920
912
  }
@@ -1182,6 +1174,13 @@
1182
1174
  margin-block-end: calc(calc(var(--spacing) * 8) * calc(1 - var(--tw-space-y-reverse)));
1183
1175
  }
1184
1176
  }
1177
+ .space-y-12 {
1178
+ :where(& > :not(:last-child)) {
1179
+ --tw-space-y-reverse: 0;
1180
+ margin-block-start: calc(calc(var(--spacing) * 12) * var(--tw-space-y-reverse));
1181
+ margin-block-end: calc(calc(var(--spacing) * 12) * calc(1 - var(--tw-space-y-reverse)));
1182
+ }
1183
+ }
1185
1184
  .space-x-2 {
1186
1185
  :where(& > :not(:last-child)) {
1187
1186
  --tw-space-x-reverse: 0;
@@ -1803,6 +1802,9 @@
1803
1802
  .bg-exam-4 {
1804
1803
  background-color: var(--color-exam-4);
1805
1804
  }
1805
+ .bg-green-500 {
1806
+ background-color: var(--color-green-500);
1807
+ }
1806
1808
  .bg-indicator-error {
1807
1809
  background-color: var(--color-indicator-error);
1808
1810
  }
@@ -7433,6 +7435,16 @@
7433
7435
  max-width: none;
7434
7436
  }
7435
7437
  }
7438
+ .lg\:grid-cols-2 {
7439
+ @media (width >= 64rem) {
7440
+ grid-template-columns: repeat(2, minmax(0, 1fr));
7441
+ }
7442
+ }
7443
+ .lg\:grid-cols-3 {
7444
+ @media (width >= 64rem) {
7445
+ grid-template-columns: repeat(3, minmax(0, 1fr));
7446
+ }
7447
+ }
7436
7448
  .lg\:grid-cols-4 {
7437
7449
  @media (width >= 64rem) {
7438
7450
  grid-template-columns: repeat(4, minmax(0, 1fr));