analytica-frontend-lib 1.0.47 → 1.0.49

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.
@@ -125,7 +125,7 @@ var MenuItem = (0, import_react.forwardRef)(
125
125
  className: `
126
126
  w-full flex flex-col gap-0.5 items-center py-1 px-2 rounded-sm font-medium text-xs
127
127
  [&>svg]:size-6 cursor-pointer hover:bg-primary-600 hover:text-text
128
- focus:outline-none focus:border-2-indicator-info focus:border-2
128
+ focus:outline-none focus:border-indicator-info focus:border-2
129
129
  ${selectedValue === value ? "bg-primary-50 text-primary-950" : "text-text-950"}
130
130
  ${className ?? ""}
131
131
  `,
@@ -138,7 +138,8 @@ var MenuItem = (0, import_react.forwardRef)(
138
138
  {
139
139
  "data-variant": "menu2",
140
140
  className: `
141
- flex flex-row items-center p-4 gap-2 border-b-2 border-transparent text-text-950 text-sx font-bold cursor-pointer
141
+ flex flex-row items-center p-4 gap-2 border-b-2 border-transparent text-text-950 text-sx font-bold cursor-pointer focus:rounded-sm
142
+ focus:outline-none focus:border-indicator-info focus:border-2
142
143
  ${selectedValue === value ? "border-b-primary-950" : ""}
143
144
  `,
144
145
  ...commonProps,
@@ -150,7 +151,7 @@ var MenuItem = (0, import_react.forwardRef)(
150
151
  {
151
152
  "data-variant": "breadcrumb",
152
153
  className: `
153
- p-2 rounded-lg hover:text-primary-600 cursor-pointer font-bold text-xs
154
+ p-2 rounded-lg hover:text-primary-600 cursor-pointer font-bold text-xs
154
155
  focus:outline-none focus:border-indicator-info focus:border-2
155
156
  ${selectedValue === value ? "text-primary-950" : "text-text-600"}
156
157
  ${className ?? ""}
@@ -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\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<HTMLUListElement> {\n children: ReactNode;\n defaultValue: string;\n value?: string;\n variant?: 'menu' | 'menu2' | 'breadcrumb';\n onValueChange?: (value: string) => void;\n}\n\nconst VARIANT_CLASSES = {\n menu: 'bg-background shadow-soft-shadow-1',\n menu2: 'overflow-x-auto scroll-smooth',\n breadcrumb: '',\n};\n\nconst Menu = forwardRef<HTMLUListElement, 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 useEffect(() => {\n onValueChange?.(value);\n }, [value, onValueChange]);\n\n const baseClasses = 'w-full flex flex-row items-center gap-2 py-2 px-6';\n\n const variantClasses = VARIANT_CLASSES[variant];\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 {injectStore(children, store)}\n </ul>\n );\n }\n);\nMenu.displayName = 'Menu';\n\ninterface MenuItemProps extends HTMLAttributes<HTMLLIElement> {\n value: string;\n disabled?: boolean;\n store?: MenuStoreApi;\n variant?: 'menu' | 'menu2' | 'breadcrumb';\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-2-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 flex flex-row items-center p-4 gap-2 border-b-2 border-transparent text-text-950 text-sx font-bold cursor-pointer\n ${selectedValue === value ? 'border-b-primary-950' : ''}\n `}\n {...commonProps}\n >\n {children}\n </li>\n ),\n breadcrumb: (\n <li\n data-variant=\"breadcrumb\"\n className={`\n 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-primary-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\n ${selectedValue === value ? 'border-b-primary-950' : '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<HTMLUListElement> {\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\"\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 ref={containerRef}\n variant=\"menu2\"\n defaultValue={defaultValue}\n onValueChange={onValueChange}\n value={value}\n {...props}\n >\n {children}\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\"\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 { Menu, MenuItem, MenuSeparator, MenuOverflow, MenuItemIcon };\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\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<HTMLUListElement> {\n children: ReactNode;\n defaultValue: string;\n value?: string;\n variant?: 'menu' | 'menu2' | 'breadcrumb';\n onValueChange?: (value: string) => void;\n}\n\nconst VARIANT_CLASSES = {\n menu: 'bg-background shadow-soft-shadow-1',\n menu2: 'overflow-x-auto scroll-smooth',\n breadcrumb: '',\n};\n\nconst Menu = forwardRef<HTMLUListElement, 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 useEffect(() => {\n onValueChange?.(value);\n }, [value, onValueChange]);\n\n const baseClasses = 'w-full flex flex-row items-center gap-2 py-2 px-6';\n\n const variantClasses = VARIANT_CLASSES[variant];\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 {injectStore(children, store)}\n </ul>\n );\n }\n);\nMenu.displayName = 'Menu';\n\ninterface MenuItemProps extends HTMLAttributes<HTMLLIElement> {\n value: string;\n disabled?: boolean;\n store?: MenuStoreApi;\n variant?: 'menu' | 'menu2' | 'breadcrumb';\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 flex flex-row items-center p-4 gap-2 border-b-2 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 `}\n {...commonProps}\n >\n {children}\n </li>\n ),\n breadcrumb: (\n <li\n data-variant=\"breadcrumb\"\n className={`\n 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-primary-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\n ${selectedValue === value ? 'border-b-primary-950' : '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<HTMLUListElement> {\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\"\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 ref={containerRef}\n variant=\"menu2\"\n defaultValue={defaultValue}\n onValueChange={onValueChange}\n value={value}\n {...props}\n >\n {children}\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\"\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 { Menu, MenuItem, MenuSeparator, MenuOverflow, MenuItemIcon };\n"],"mappings":"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","names":[]}
@@ -101,7 +101,7 @@ var MenuItem = forwardRef(
101
101
  className: `
102
102
  w-full flex flex-col gap-0.5 items-center py-1 px-2 rounded-sm font-medium text-xs
103
103
  [&>svg]:size-6 cursor-pointer hover:bg-primary-600 hover:text-text
104
- focus:outline-none focus:border-2-indicator-info focus:border-2
104
+ focus:outline-none focus:border-indicator-info focus:border-2
105
105
  ${selectedValue === value ? "bg-primary-50 text-primary-950" : "text-text-950"}
106
106
  ${className ?? ""}
107
107
  `,
@@ -114,7 +114,8 @@ var MenuItem = forwardRef(
114
114
  {
115
115
  "data-variant": "menu2",
116
116
  className: `
117
- flex flex-row items-center p-4 gap-2 border-b-2 border-transparent text-text-950 text-sx font-bold cursor-pointer
117
+ flex flex-row items-center p-4 gap-2 border-b-2 border-transparent text-text-950 text-sx font-bold cursor-pointer focus:rounded-sm
118
+ focus:outline-none focus:border-indicator-info focus:border-2
118
119
  ${selectedValue === value ? "border-b-primary-950" : ""}
119
120
  `,
120
121
  ...commonProps,
@@ -126,7 +127,7 @@ var MenuItem = forwardRef(
126
127
  {
127
128
  "data-variant": "breadcrumb",
128
129
  className: `
129
- p-2 rounded-lg hover:text-primary-600 cursor-pointer font-bold text-xs
130
+ p-2 rounded-lg hover:text-primary-600 cursor-pointer font-bold text-xs
130
131
  focus:outline-none focus:border-indicator-info focus:border-2
131
132
  ${selectedValue === value ? "text-primary-950" : "text-text-600"}
132
133
  ${className ?? ""}
@@ -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\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<HTMLUListElement> {\n children: ReactNode;\n defaultValue: string;\n value?: string;\n variant?: 'menu' | 'menu2' | 'breadcrumb';\n onValueChange?: (value: string) => void;\n}\n\nconst VARIANT_CLASSES = {\n menu: 'bg-background shadow-soft-shadow-1',\n menu2: 'overflow-x-auto scroll-smooth',\n breadcrumb: '',\n};\n\nconst Menu = forwardRef<HTMLUListElement, 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 useEffect(() => {\n onValueChange?.(value);\n }, [value, onValueChange]);\n\n const baseClasses = 'w-full flex flex-row items-center gap-2 py-2 px-6';\n\n const variantClasses = VARIANT_CLASSES[variant];\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 {injectStore(children, store)}\n </ul>\n );\n }\n);\nMenu.displayName = 'Menu';\n\ninterface MenuItemProps extends HTMLAttributes<HTMLLIElement> {\n value: string;\n disabled?: boolean;\n store?: MenuStoreApi;\n variant?: 'menu' | 'menu2' | 'breadcrumb';\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-2-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 flex flex-row items-center p-4 gap-2 border-b-2 border-transparent text-text-950 text-sx font-bold cursor-pointer\n ${selectedValue === value ? 'border-b-primary-950' : ''}\n `}\n {...commonProps}\n >\n {children}\n </li>\n ),\n breadcrumb: (\n <li\n data-variant=\"breadcrumb\"\n className={`\n 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-primary-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\n ${selectedValue === value ? 'border-b-primary-950' : '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<HTMLUListElement> {\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\"\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 ref={containerRef}\n variant=\"menu2\"\n defaultValue={defaultValue}\n onValueChange={onValueChange}\n value={value}\n {...props}\n >\n {children}\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\"\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 { Menu, MenuItem, MenuSeparator, MenuOverflow, MenuItemIcon };\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\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<HTMLUListElement> {\n children: ReactNode;\n defaultValue: string;\n value?: string;\n variant?: 'menu' | 'menu2' | 'breadcrumb';\n onValueChange?: (value: string) => void;\n}\n\nconst VARIANT_CLASSES = {\n menu: 'bg-background shadow-soft-shadow-1',\n menu2: 'overflow-x-auto scroll-smooth',\n breadcrumb: '',\n};\n\nconst Menu = forwardRef<HTMLUListElement, 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 useEffect(() => {\n onValueChange?.(value);\n }, [value, onValueChange]);\n\n const baseClasses = 'w-full flex flex-row items-center gap-2 py-2 px-6';\n\n const variantClasses = VARIANT_CLASSES[variant];\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 {injectStore(children, store)}\n </ul>\n );\n }\n);\nMenu.displayName = 'Menu';\n\ninterface MenuItemProps extends HTMLAttributes<HTMLLIElement> {\n value: string;\n disabled?: boolean;\n store?: MenuStoreApi;\n variant?: 'menu' | 'menu2' | 'breadcrumb';\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 flex flex-row items-center p-4 gap-2 border-b-2 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 `}\n {...commonProps}\n >\n {children}\n </li>\n ),\n breadcrumb: (\n <li\n data-variant=\"breadcrumb\"\n className={`\n 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-primary-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\n ${selectedValue === value ? 'border-b-primary-950' : '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<HTMLUListElement> {\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\"\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 ref={containerRef}\n variant=\"menu2\"\n defaultValue={defaultValue}\n onValueChange={onValueChange}\n value={value}\n {...props}\n >\n {children}\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\"\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 { Menu, MenuItem, MenuSeparator, MenuOverflow, MenuItemIcon };\n"],"mappings":"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","names":[]}
@@ -0,0 +1,66 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ReactNode } from 'react';
3
+
4
+ /**
5
+ * Modal component props interface
6
+ */
7
+ type ModalProps = {
8
+ /** Whether the modal is open */
9
+ isOpen: boolean;
10
+ /** Function to close the modal */
11
+ onClose: () => void;
12
+ /** Modal title */
13
+ title: string;
14
+ /** Modal description/content */
15
+ children: ReactNode;
16
+ /** Size of the modal */
17
+ size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
18
+ /** Additional CSS classes for the modal content */
19
+ className?: string;
20
+ /** Whether clicking the backdrop should close the modal */
21
+ closeOnBackdropClick?: boolean;
22
+ /** Whether pressing Escape should close the modal */
23
+ closeOnEscape?: boolean;
24
+ /** Footer content (typically buttons) */
25
+ footer?: ReactNode;
26
+ /** Hide the close button */
27
+ hideCloseButton?: boolean;
28
+ };
29
+ /**
30
+ * Modal component for Analytica Ensino platforms
31
+ *
32
+ * A flexible modal component with multiple size variants and customizable behavior.
33
+ *
34
+ * @param isOpen - Whether the modal is currently open
35
+ * @param onClose - Callback function called when the modal should be closed
36
+ * @param title - The title displayed at the top of the modal
37
+ * @param children - The main content of the modal
38
+ * @param size - The size variant (xs, sm, md, lg, xl)
39
+ * @param className - Additional CSS classes for the modal content
40
+ * @param closeOnBackdropClick - Whether clicking the backdrop closes the modal (default: true)
41
+ * @param closeOnEscape - Whether pressing Escape closes the modal (default: true)
42
+ * @param footer - Footer content, typically action buttons
43
+ * @param hideCloseButton - Whether to hide the X close button (default: false)
44
+ * @returns A modal overlay with content
45
+ *
46
+ * @example
47
+ * ```tsx
48
+ * <Modal
49
+ * isOpen={isModalOpen}
50
+ * onClose={() => setIsModalOpen(false)}
51
+ * title="Invite your team"
52
+ * size="md"
53
+ * footer={
54
+ * <div className="flex gap-3">
55
+ * <Button variant="outline" onClick={() => setIsModalOpen(false)}>Cancel</Button>
56
+ * <Button variant="solid" onClick={handleExplore}>Explore</Button>
57
+ * </div>
58
+ * }
59
+ * >
60
+ * Elevate user interactions with our versatile modals.
61
+ * </Modal>
62
+ * ```
63
+ */
64
+ declare const Modal: ({ isOpen, onClose, title, children, size, className, closeOnBackdropClick, closeOnEscape, footer, hideCloseButton, }: ModalProps) => react_jsx_runtime.JSX.Element | null;
65
+
66
+ export { Modal as default };
@@ -0,0 +1,66 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ReactNode } from 'react';
3
+
4
+ /**
5
+ * Modal component props interface
6
+ */
7
+ type ModalProps = {
8
+ /** Whether the modal is open */
9
+ isOpen: boolean;
10
+ /** Function to close the modal */
11
+ onClose: () => void;
12
+ /** Modal title */
13
+ title: string;
14
+ /** Modal description/content */
15
+ children: ReactNode;
16
+ /** Size of the modal */
17
+ size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
18
+ /** Additional CSS classes for the modal content */
19
+ className?: string;
20
+ /** Whether clicking the backdrop should close the modal */
21
+ closeOnBackdropClick?: boolean;
22
+ /** Whether pressing Escape should close the modal */
23
+ closeOnEscape?: boolean;
24
+ /** Footer content (typically buttons) */
25
+ footer?: ReactNode;
26
+ /** Hide the close button */
27
+ hideCloseButton?: boolean;
28
+ };
29
+ /**
30
+ * Modal component for Analytica Ensino platforms
31
+ *
32
+ * A flexible modal component with multiple size variants and customizable behavior.
33
+ *
34
+ * @param isOpen - Whether the modal is currently open
35
+ * @param onClose - Callback function called when the modal should be closed
36
+ * @param title - The title displayed at the top of the modal
37
+ * @param children - The main content of the modal
38
+ * @param size - The size variant (xs, sm, md, lg, xl)
39
+ * @param className - Additional CSS classes for the modal content
40
+ * @param closeOnBackdropClick - Whether clicking the backdrop closes the modal (default: true)
41
+ * @param closeOnEscape - Whether pressing Escape closes the modal (default: true)
42
+ * @param footer - Footer content, typically action buttons
43
+ * @param hideCloseButton - Whether to hide the X close button (default: false)
44
+ * @returns A modal overlay with content
45
+ *
46
+ * @example
47
+ * ```tsx
48
+ * <Modal
49
+ * isOpen={isModalOpen}
50
+ * onClose={() => setIsModalOpen(false)}
51
+ * title="Invite your team"
52
+ * size="md"
53
+ * footer={
54
+ * <div className="flex gap-3">
55
+ * <Button variant="outline" onClick={() => setIsModalOpen(false)}>Cancel</Button>
56
+ * <Button variant="solid" onClick={handleExplore}>Explore</Button>
57
+ * </div>
58
+ * }
59
+ * >
60
+ * Elevate user interactions with our versatile modals.
61
+ * </Modal>
62
+ * ```
63
+ */
64
+ declare const Modal: ({ isOpen, onClose, title, children, size, className, closeOnBackdropClick, closeOnEscape, footer, hideCloseButton, }: ModalProps) => react_jsx_runtime.JSX.Element | null;
65
+
66
+ export { Modal as default };
@@ -0,0 +1,113 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/components/Modal/Modal.tsx
21
+ var Modal_exports = {};
22
+ __export(Modal_exports, {
23
+ default: () => Modal_default
24
+ });
25
+ module.exports = __toCommonJS(Modal_exports);
26
+ var import_react = require("react");
27
+ var import_phosphor_react = require("phosphor-react");
28
+ var import_jsx_runtime = require("react/jsx-runtime");
29
+ var SIZE_CLASSES = {
30
+ xs: "max-w-[360px]",
31
+ sm: "max-w-[420px]",
32
+ md: "max-w-[510px]",
33
+ lg: "max-w-[640px]",
34
+ xl: "max-w-[970px]"
35
+ };
36
+ var Modal = ({
37
+ isOpen,
38
+ onClose,
39
+ title,
40
+ children,
41
+ size = "md",
42
+ className = "",
43
+ closeOnBackdropClick = true,
44
+ closeOnEscape = true,
45
+ footer,
46
+ hideCloseButton = false
47
+ }) => {
48
+ (0, import_react.useEffect)(() => {
49
+ if (!isOpen || !closeOnEscape) return;
50
+ const handleEscape = (event) => {
51
+ if (event.key === "Escape") {
52
+ onClose();
53
+ }
54
+ };
55
+ document.addEventListener("keydown", handleEscape);
56
+ return () => document.removeEventListener("keydown", handleEscape);
57
+ }, [isOpen, closeOnEscape, onClose]);
58
+ (0, import_react.useEffect)(() => {
59
+ const originalOverflow = document.body.style.overflow;
60
+ if (isOpen) {
61
+ document.body.style.overflow = "hidden";
62
+ } else {
63
+ document.body.style.overflow = originalOverflow;
64
+ }
65
+ return () => {
66
+ document.body.style.overflow = originalOverflow;
67
+ };
68
+ }, [isOpen]);
69
+ const handleBackdropClick = (event) => {
70
+ if (closeOnBackdropClick && event.target === event.currentTarget) {
71
+ onClose();
72
+ }
73
+ };
74
+ const handleBackdropKeyDown = (event) => {
75
+ if (closeOnBackdropClick && (event.key === "Enter" || event.key === " ")) {
76
+ onClose();
77
+ }
78
+ };
79
+ if (!isOpen) return null;
80
+ const sizeClasses = SIZE_CLASSES[size];
81
+ const baseClasses = "bg-background rounded-3xl shadow-hard-shadow-2 border border-border-100 w-full mx-4";
82
+ const dialogResetClasses = "p-0 m-0 border-none outline-none max-h-none static";
83
+ const modalClasses = `${baseClasses} ${sizeClasses} ${dialogResetClasses} ${className}`;
84
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
85
+ "div",
86
+ {
87
+ className: "fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-xs",
88
+ onClick: handleBackdropClick,
89
+ onKeyDown: handleBackdropKeyDown,
90
+ role: "button",
91
+ tabIndex: closeOnBackdropClick ? 0 : -1,
92
+ "aria-label": "Fechar modal clicando no fundo",
93
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("dialog", { className: modalClasses, "aria-labelledby": "modal-title", open: true, children: [
94
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center justify-between px-6 py-6", children: [
95
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { id: "modal-title", className: "text-lg font-semibold text-text-950", children: title }),
96
+ !hideCloseButton && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
97
+ "button",
98
+ {
99
+ onClick: onClose,
100
+ className: "p-1 text-text-500 hover:text-text-700 hover:bg-background-50 rounded-md transition-colors focus:outline-none focus:ring-2 focus:ring-indicator-info focus:ring-offset-2",
101
+ "aria-label": "Fechar modal",
102
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_phosphor_react.X, { size: 18 })
103
+ }
104
+ )
105
+ ] }),
106
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "px-6 pb-6", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "text-text-500 font-normal text-sm leading-6", children }) }),
107
+ footer && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex justify-end gap-3 px-6 pb-6", children: footer })
108
+ ] })
109
+ }
110
+ );
111
+ };
112
+ var Modal_default = Modal;
113
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/Modal/Modal.tsx"],"sourcesContent":["import { ReactNode, MouseEvent, useEffect, KeyboardEvent } from 'react';\nimport { X } from 'phosphor-react';\n\n/**\n * Lookup table for size classes\n */\nconst SIZE_CLASSES = {\n xs: 'max-w-[360px]',\n sm: 'max-w-[420px]',\n md: 'max-w-[510px]',\n lg: 'max-w-[640px]',\n xl: 'max-w-[970px]',\n} as const;\n\n/**\n * Modal component props interface\n */\ntype ModalProps = {\n /** Whether the modal is open */\n isOpen: boolean;\n /** Function to close the modal */\n onClose: () => void;\n /** Modal title */\n title: string;\n /** Modal description/content */\n children: ReactNode;\n /** Size of the modal */\n size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';\n /** Additional CSS classes for the modal content */\n className?: string;\n /** Whether clicking the backdrop should close the modal */\n closeOnBackdropClick?: boolean;\n /** Whether pressing Escape should close the modal */\n closeOnEscape?: boolean;\n /** Footer content (typically buttons) */\n footer?: ReactNode;\n /** Hide the close button */\n hideCloseButton?: boolean;\n};\n\n/**\n * Modal component for Analytica Ensino platforms\n *\n * A flexible modal component with multiple size variants and customizable behavior.\n *\n * @param isOpen - Whether the modal is currently open\n * @param onClose - Callback function called when the modal should be closed\n * @param title - The title displayed at the top of the modal\n * @param children - The main content of the modal\n * @param size - The size variant (xs, sm, md, lg, xl)\n * @param className - Additional CSS classes for the modal content\n * @param closeOnBackdropClick - Whether clicking the backdrop closes the modal (default: true)\n * @param closeOnEscape - Whether pressing Escape closes the modal (default: true)\n * @param footer - Footer content, typically action buttons\n * @param hideCloseButton - Whether to hide the X close button (default: false)\n * @returns A modal overlay with content\n *\n * @example\n * ```tsx\n * <Modal\n * isOpen={isModalOpen}\n * onClose={() => setIsModalOpen(false)}\n * title=\"Invite your team\"\n * size=\"md\"\n * footer={\n * <div className=\"flex gap-3\">\n * <Button variant=\"outline\" onClick={() => setIsModalOpen(false)}>Cancel</Button>\n * <Button variant=\"solid\" onClick={handleExplore}>Explore</Button>\n * </div>\n * }\n * >\n * Elevate user interactions with our versatile modals.\n * </Modal>\n * ```\n */\nconst Modal = ({\n isOpen,\n onClose,\n title,\n children,\n size = 'md',\n className = '',\n closeOnBackdropClick = true,\n closeOnEscape = true,\n footer,\n hideCloseButton = false,\n}: ModalProps) => {\n // Handle escape key\n useEffect(() => {\n if (!isOpen || !closeOnEscape) return;\n\n const handleEscape = (event: globalThis.KeyboardEvent) => {\n if (event.key === 'Escape') {\n onClose();\n }\n };\n\n document.addEventListener('keydown', handleEscape);\n return () => document.removeEventListener('keydown', handleEscape);\n }, [isOpen, closeOnEscape, onClose]);\n\n // Handle body scroll lock\n useEffect(() => {\n const originalOverflow = document.body.style.overflow;\n if (isOpen) {\n document.body.style.overflow = 'hidden';\n } else {\n document.body.style.overflow = originalOverflow;\n }\n\n return () => {\n document.body.style.overflow = originalOverflow;\n };\n }, [isOpen]);\n\n // Handle backdrop click\n const handleBackdropClick = (event: MouseEvent<HTMLDivElement>) => {\n if (closeOnBackdropClick && event.target === event.currentTarget) {\n onClose();\n }\n };\n\n // Handle backdrop keyboard interaction\n const handleBackdropKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {\n if (closeOnBackdropClick && (event.key === 'Enter' || event.key === ' ')) {\n onClose();\n }\n };\n\n if (!isOpen) return null;\n\n const sizeClasses = SIZE_CLASSES[size];\n const baseClasses =\n 'bg-background rounded-3xl shadow-hard-shadow-2 border border-border-100 w-full mx-4';\n // Reset dialog default styles to prevent positioning issues\n const dialogResetClasses =\n 'p-0 m-0 border-none outline-none max-h-none static';\n const modalClasses = `${baseClasses} ${sizeClasses} ${dialogResetClasses} ${className}`;\n\n return (\n <div\n className=\"fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-xs\"\n onClick={handleBackdropClick}\n onKeyDown={handleBackdropKeyDown}\n role=\"button\"\n tabIndex={closeOnBackdropClick ? 0 : -1}\n aria-label=\"Fechar modal clicando no fundo\"\n >\n <dialog className={modalClasses} aria-labelledby=\"modal-title\" open>\n {/* Header */}\n <div className=\"flex items-center justify-between px-6 py-6\">\n <h2 id=\"modal-title\" className=\"text-lg font-semibold text-text-950\">\n {title}\n </h2>\n {!hideCloseButton && (\n <button\n onClick={onClose}\n className=\"p-1 text-text-500 hover:text-text-700 hover:bg-background-50 rounded-md transition-colors focus:outline-none focus:ring-2 focus:ring-indicator-info focus:ring-offset-2\"\n aria-label=\"Fechar modal\"\n >\n <X size={18} />\n </button>\n )}\n </div>\n\n {/* Content */}\n <div className=\"px-6 pb-6\">\n <div className=\"text-text-500 font-normal text-sm leading-6\">\n {children}\n </div>\n </div>\n\n {/* Footer */}\n {footer && (\n <div className=\"flex justify-end gap-3 px-6 pb-6\">{footer}</div>\n )}\n </dialog>\n </div>\n );\n};\n\nexport default Modal;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAgE;AAChE,4BAAkB;AAqJV;AAhJR,IAAM,eAAe;AAAA,EACnB,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AACN;AA+DA,IAAM,QAAQ,CAAC;AAAA,EACb;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,OAAO;AAAA,EACP,YAAY;AAAA,EACZ,uBAAuB;AAAA,EACvB,gBAAgB;AAAA,EAChB;AAAA,EACA,kBAAkB;AACpB,MAAkB;AAEhB,8BAAU,MAAM;AACd,QAAI,CAAC,UAAU,CAAC,cAAe;AAE/B,UAAM,eAAe,CAAC,UAAoC;AACxD,UAAI,MAAM,QAAQ,UAAU;AAC1B,gBAAQ;AAAA,MACV;AAAA,IACF;AAEA,aAAS,iBAAiB,WAAW,YAAY;AACjD,WAAO,MAAM,SAAS,oBAAoB,WAAW,YAAY;AAAA,EACnE,GAAG,CAAC,QAAQ,eAAe,OAAO,CAAC;AAGnC,8BAAU,MAAM;AACd,UAAM,mBAAmB,SAAS,KAAK,MAAM;AAC7C,QAAI,QAAQ;AACV,eAAS,KAAK,MAAM,WAAW;AAAA,IACjC,OAAO;AACL,eAAS,KAAK,MAAM,WAAW;AAAA,IACjC;AAEA,WAAO,MAAM;AACX,eAAS,KAAK,MAAM,WAAW;AAAA,IACjC;AAAA,EACF,GAAG,CAAC,MAAM,CAAC;AAGX,QAAM,sBAAsB,CAAC,UAAsC;AACjE,QAAI,wBAAwB,MAAM,WAAW,MAAM,eAAe;AAChE,cAAQ;AAAA,IACV;AAAA,EACF;AAGA,QAAM,wBAAwB,CAAC,UAAyC;AACtE,QAAI,yBAAyB,MAAM,QAAQ,WAAW,MAAM,QAAQ,MAAM;AACxE,cAAQ;AAAA,IACV;AAAA,EACF;AAEA,MAAI,CAAC,OAAQ,QAAO;AAEpB,QAAM,cAAc,aAAa,IAAI;AACrC,QAAM,cACJ;AAEF,QAAM,qBACJ;AACF,QAAM,eAAe,GAAG,WAAW,IAAI,WAAW,IAAI,kBAAkB,IAAI,SAAS;AAErF,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAU;AAAA,MACV,SAAS;AAAA,MACT,WAAW;AAAA,MACX,MAAK;AAAA,MACL,UAAU,uBAAuB,IAAI;AAAA,MACrC,cAAW;AAAA,MAEX,uDAAC,YAAO,WAAW,cAAc,mBAAgB,eAAc,MAAI,MAEjE;AAAA,qDAAC,SAAI,WAAU,+CACb;AAAA,sDAAC,QAAG,IAAG,eAAc,WAAU,uCAC5B,iBACH;AAAA,UACC,CAAC,mBACA;AAAA,YAAC;AAAA;AAAA,cACC,SAAS;AAAA,cACT,WAAU;AAAA,cACV,cAAW;AAAA,cAEX,sDAAC,2BAAE,MAAM,IAAI;AAAA;AAAA,UACf;AAAA,WAEJ;AAAA,QAGA,4CAAC,SAAI,WAAU,aACb,sDAAC,SAAI,WAAU,+CACZ,UACH,GACF;AAAA,QAGC,UACC,4CAAC,SAAI,WAAU,oCAAoC,kBAAO;AAAA,SAE9D;AAAA;AAAA,EACF;AAEJ;AAEA,IAAO,gBAAQ;","names":[]}
@@ -0,0 +1,92 @@
1
+ // src/components/Modal/Modal.tsx
2
+ import { useEffect } from "react";
3
+ import { X } from "phosphor-react";
4
+ import { jsx, jsxs } from "react/jsx-runtime";
5
+ var SIZE_CLASSES = {
6
+ xs: "max-w-[360px]",
7
+ sm: "max-w-[420px]",
8
+ md: "max-w-[510px]",
9
+ lg: "max-w-[640px]",
10
+ xl: "max-w-[970px]"
11
+ };
12
+ var Modal = ({
13
+ isOpen,
14
+ onClose,
15
+ title,
16
+ children,
17
+ size = "md",
18
+ className = "",
19
+ closeOnBackdropClick = true,
20
+ closeOnEscape = true,
21
+ footer,
22
+ hideCloseButton = false
23
+ }) => {
24
+ useEffect(() => {
25
+ if (!isOpen || !closeOnEscape) return;
26
+ const handleEscape = (event) => {
27
+ if (event.key === "Escape") {
28
+ onClose();
29
+ }
30
+ };
31
+ document.addEventListener("keydown", handleEscape);
32
+ return () => document.removeEventListener("keydown", handleEscape);
33
+ }, [isOpen, closeOnEscape, onClose]);
34
+ useEffect(() => {
35
+ const originalOverflow = document.body.style.overflow;
36
+ if (isOpen) {
37
+ document.body.style.overflow = "hidden";
38
+ } else {
39
+ document.body.style.overflow = originalOverflow;
40
+ }
41
+ return () => {
42
+ document.body.style.overflow = originalOverflow;
43
+ };
44
+ }, [isOpen]);
45
+ const handleBackdropClick = (event) => {
46
+ if (closeOnBackdropClick && event.target === event.currentTarget) {
47
+ onClose();
48
+ }
49
+ };
50
+ const handleBackdropKeyDown = (event) => {
51
+ if (closeOnBackdropClick && (event.key === "Enter" || event.key === " ")) {
52
+ onClose();
53
+ }
54
+ };
55
+ if (!isOpen) return null;
56
+ const sizeClasses = SIZE_CLASSES[size];
57
+ const baseClasses = "bg-background rounded-3xl shadow-hard-shadow-2 border border-border-100 w-full mx-4";
58
+ const dialogResetClasses = "p-0 m-0 border-none outline-none max-h-none static";
59
+ const modalClasses = `${baseClasses} ${sizeClasses} ${dialogResetClasses} ${className}`;
60
+ return /* @__PURE__ */ jsx(
61
+ "div",
62
+ {
63
+ className: "fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-xs",
64
+ onClick: handleBackdropClick,
65
+ onKeyDown: handleBackdropKeyDown,
66
+ role: "button",
67
+ tabIndex: closeOnBackdropClick ? 0 : -1,
68
+ "aria-label": "Fechar modal clicando no fundo",
69
+ children: /* @__PURE__ */ jsxs("dialog", { className: modalClasses, "aria-labelledby": "modal-title", open: true, children: [
70
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-6 py-6", children: [
71
+ /* @__PURE__ */ jsx("h2", { id: "modal-title", className: "text-lg font-semibold text-text-950", children: title }),
72
+ !hideCloseButton && /* @__PURE__ */ jsx(
73
+ "button",
74
+ {
75
+ onClick: onClose,
76
+ className: "p-1 text-text-500 hover:text-text-700 hover:bg-background-50 rounded-md transition-colors focus:outline-none focus:ring-2 focus:ring-indicator-info focus:ring-offset-2",
77
+ "aria-label": "Fechar modal",
78
+ children: /* @__PURE__ */ jsx(X, { size: 18 })
79
+ }
80
+ )
81
+ ] }),
82
+ /* @__PURE__ */ jsx("div", { className: "px-6 pb-6", children: /* @__PURE__ */ jsx("div", { className: "text-text-500 font-normal text-sm leading-6", children }) }),
83
+ footer && /* @__PURE__ */ jsx("div", { className: "flex justify-end gap-3 px-6 pb-6", children: footer })
84
+ ] })
85
+ }
86
+ );
87
+ };
88
+ var Modal_default = Modal;
89
+ export {
90
+ Modal_default as default
91
+ };
92
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/Modal/Modal.tsx"],"sourcesContent":["import { ReactNode, MouseEvent, useEffect, KeyboardEvent } from 'react';\nimport { X } from 'phosphor-react';\n\n/**\n * Lookup table for size classes\n */\nconst SIZE_CLASSES = {\n xs: 'max-w-[360px]',\n sm: 'max-w-[420px]',\n md: 'max-w-[510px]',\n lg: 'max-w-[640px]',\n xl: 'max-w-[970px]',\n} as const;\n\n/**\n * Modal component props interface\n */\ntype ModalProps = {\n /** Whether the modal is open */\n isOpen: boolean;\n /** Function to close the modal */\n onClose: () => void;\n /** Modal title */\n title: string;\n /** Modal description/content */\n children: ReactNode;\n /** Size of the modal */\n size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';\n /** Additional CSS classes for the modal content */\n className?: string;\n /** Whether clicking the backdrop should close the modal */\n closeOnBackdropClick?: boolean;\n /** Whether pressing Escape should close the modal */\n closeOnEscape?: boolean;\n /** Footer content (typically buttons) */\n footer?: ReactNode;\n /** Hide the close button */\n hideCloseButton?: boolean;\n};\n\n/**\n * Modal component for Analytica Ensino platforms\n *\n * A flexible modal component with multiple size variants and customizable behavior.\n *\n * @param isOpen - Whether the modal is currently open\n * @param onClose - Callback function called when the modal should be closed\n * @param title - The title displayed at the top of the modal\n * @param children - The main content of the modal\n * @param size - The size variant (xs, sm, md, lg, xl)\n * @param className - Additional CSS classes for the modal content\n * @param closeOnBackdropClick - Whether clicking the backdrop closes the modal (default: true)\n * @param closeOnEscape - Whether pressing Escape closes the modal (default: true)\n * @param footer - Footer content, typically action buttons\n * @param hideCloseButton - Whether to hide the X close button (default: false)\n * @returns A modal overlay with content\n *\n * @example\n * ```tsx\n * <Modal\n * isOpen={isModalOpen}\n * onClose={() => setIsModalOpen(false)}\n * title=\"Invite your team\"\n * size=\"md\"\n * footer={\n * <div className=\"flex gap-3\">\n * <Button variant=\"outline\" onClick={() => setIsModalOpen(false)}>Cancel</Button>\n * <Button variant=\"solid\" onClick={handleExplore}>Explore</Button>\n * </div>\n * }\n * >\n * Elevate user interactions with our versatile modals.\n * </Modal>\n * ```\n */\nconst Modal = ({\n isOpen,\n onClose,\n title,\n children,\n size = 'md',\n className = '',\n closeOnBackdropClick = true,\n closeOnEscape = true,\n footer,\n hideCloseButton = false,\n}: ModalProps) => {\n // Handle escape key\n useEffect(() => {\n if (!isOpen || !closeOnEscape) return;\n\n const handleEscape = (event: globalThis.KeyboardEvent) => {\n if (event.key === 'Escape') {\n onClose();\n }\n };\n\n document.addEventListener('keydown', handleEscape);\n return () => document.removeEventListener('keydown', handleEscape);\n }, [isOpen, closeOnEscape, onClose]);\n\n // Handle body scroll lock\n useEffect(() => {\n const originalOverflow = document.body.style.overflow;\n if (isOpen) {\n document.body.style.overflow = 'hidden';\n } else {\n document.body.style.overflow = originalOverflow;\n }\n\n return () => {\n document.body.style.overflow = originalOverflow;\n };\n }, [isOpen]);\n\n // Handle backdrop click\n const handleBackdropClick = (event: MouseEvent<HTMLDivElement>) => {\n if (closeOnBackdropClick && event.target === event.currentTarget) {\n onClose();\n }\n };\n\n // Handle backdrop keyboard interaction\n const handleBackdropKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {\n if (closeOnBackdropClick && (event.key === 'Enter' || event.key === ' ')) {\n onClose();\n }\n };\n\n if (!isOpen) return null;\n\n const sizeClasses = SIZE_CLASSES[size];\n const baseClasses =\n 'bg-background rounded-3xl shadow-hard-shadow-2 border border-border-100 w-full mx-4';\n // Reset dialog default styles to prevent positioning issues\n const dialogResetClasses =\n 'p-0 m-0 border-none outline-none max-h-none static';\n const modalClasses = `${baseClasses} ${sizeClasses} ${dialogResetClasses} ${className}`;\n\n return (\n <div\n className=\"fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-xs\"\n onClick={handleBackdropClick}\n onKeyDown={handleBackdropKeyDown}\n role=\"button\"\n tabIndex={closeOnBackdropClick ? 0 : -1}\n aria-label=\"Fechar modal clicando no fundo\"\n >\n <dialog className={modalClasses} aria-labelledby=\"modal-title\" open>\n {/* Header */}\n <div className=\"flex items-center justify-between px-6 py-6\">\n <h2 id=\"modal-title\" className=\"text-lg font-semibold text-text-950\">\n {title}\n </h2>\n {!hideCloseButton && (\n <button\n onClick={onClose}\n className=\"p-1 text-text-500 hover:text-text-700 hover:bg-background-50 rounded-md transition-colors focus:outline-none focus:ring-2 focus:ring-indicator-info focus:ring-offset-2\"\n aria-label=\"Fechar modal\"\n >\n <X size={18} />\n </button>\n )}\n </div>\n\n {/* Content */}\n <div className=\"px-6 pb-6\">\n <div className=\"text-text-500 font-normal text-sm leading-6\">\n {children}\n </div>\n </div>\n\n {/* Footer */}\n {footer && (\n <div className=\"flex justify-end gap-3 px-6 pb-6\">{footer}</div>\n )}\n </dialog>\n </div>\n );\n};\n\nexport default Modal;\n"],"mappings":";AAAA,SAAgC,iBAAgC;AAChE,SAAS,SAAS;AAqJV,SACE,KADF;AAhJR,IAAM,eAAe;AAAA,EACnB,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AACN;AA+DA,IAAM,QAAQ,CAAC;AAAA,EACb;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,OAAO;AAAA,EACP,YAAY;AAAA,EACZ,uBAAuB;AAAA,EACvB,gBAAgB;AAAA,EAChB;AAAA,EACA,kBAAkB;AACpB,MAAkB;AAEhB,YAAU,MAAM;AACd,QAAI,CAAC,UAAU,CAAC,cAAe;AAE/B,UAAM,eAAe,CAAC,UAAoC;AACxD,UAAI,MAAM,QAAQ,UAAU;AAC1B,gBAAQ;AAAA,MACV;AAAA,IACF;AAEA,aAAS,iBAAiB,WAAW,YAAY;AACjD,WAAO,MAAM,SAAS,oBAAoB,WAAW,YAAY;AAAA,EACnE,GAAG,CAAC,QAAQ,eAAe,OAAO,CAAC;AAGnC,YAAU,MAAM;AACd,UAAM,mBAAmB,SAAS,KAAK,MAAM;AAC7C,QAAI,QAAQ;AACV,eAAS,KAAK,MAAM,WAAW;AAAA,IACjC,OAAO;AACL,eAAS,KAAK,MAAM,WAAW;AAAA,IACjC;AAEA,WAAO,MAAM;AACX,eAAS,KAAK,MAAM,WAAW;AAAA,IACjC;AAAA,EACF,GAAG,CAAC,MAAM,CAAC;AAGX,QAAM,sBAAsB,CAAC,UAAsC;AACjE,QAAI,wBAAwB,MAAM,WAAW,MAAM,eAAe;AAChE,cAAQ;AAAA,IACV;AAAA,EACF;AAGA,QAAM,wBAAwB,CAAC,UAAyC;AACtE,QAAI,yBAAyB,MAAM,QAAQ,WAAW,MAAM,QAAQ,MAAM;AACxE,cAAQ;AAAA,IACV;AAAA,EACF;AAEA,MAAI,CAAC,OAAQ,QAAO;AAEpB,QAAM,cAAc,aAAa,IAAI;AACrC,QAAM,cACJ;AAEF,QAAM,qBACJ;AACF,QAAM,eAAe,GAAG,WAAW,IAAI,WAAW,IAAI,kBAAkB,IAAI,SAAS;AAErF,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAU;AAAA,MACV,SAAS;AAAA,MACT,WAAW;AAAA,MACX,MAAK;AAAA,MACL,UAAU,uBAAuB,IAAI;AAAA,MACrC,cAAW;AAAA,MAEX,+BAAC,YAAO,WAAW,cAAc,mBAAgB,eAAc,MAAI,MAEjE;AAAA,6BAAC,SAAI,WAAU,+CACb;AAAA,8BAAC,QAAG,IAAG,eAAc,WAAU,uCAC5B,iBACH;AAAA,UACC,CAAC,mBACA;AAAA,YAAC;AAAA;AAAA,cACC,SAAS;AAAA,cACT,WAAU;AAAA,cACV,cAAW;AAAA,cAEX,8BAAC,KAAE,MAAM,IAAI;AAAA;AAAA,UACf;AAAA,WAEJ;AAAA,QAGA,oBAAC,SAAI,WAAU,aACb,8BAAC,SAAI,WAAU,+CACZ,UACH,GACF;AAAA,QAGC,UACC,oBAAC,SAAI,WAAU,oCAAoC,kBAAO;AAAA,SAE9D;AAAA;AAAA,EACF;AAEJ;AAEA,IAAO,gBAAQ;","names":[]}
@@ -80,29 +80,21 @@ var Text_default = Text;
80
80
  var import_jsx_runtime2 = require("react/jsx-runtime");
81
81
  var SIZE_CLASSES = {
82
82
  small: {
83
- container: "w-72",
84
- // 288px width
85
83
  textarea: "h-24 text-sm",
86
84
  // 96px height, 14px font
87
85
  textSize: "sm"
88
86
  },
89
87
  medium: {
90
- container: "w-72",
91
- // 288px width
92
88
  textarea: "h-24 text-base",
93
89
  // 96px height, 16px font
94
90
  textSize: "md"
95
91
  },
96
92
  large: {
97
- container: "w-72",
98
- // 288px width
99
93
  textarea: "h-24 text-lg",
100
94
  // 96px height, 18px font
101
95
  textSize: "lg"
102
96
  },
103
97
  extraLarge: {
104
- container: "w-72",
105
- // 288px width
106
98
  textarea: "h-24 text-xl",
107
99
  // 96px height, 20px font
108
100
  textSize: "xl"
@@ -172,7 +164,7 @@ var TextArea = (0, import_react.forwardRef)(
172
164
  const sizeClasses = SIZE_CLASSES[size];
173
165
  const stateClasses = STATE_CLASSES[currentState];
174
166
  const textareaClasses = `${BASE_TEXTAREA_CLASSES} ${sizeClasses.textarea} ${stateClasses.base} ${stateClasses.hover} ${stateClasses.focus} ${className}`;
175
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: `flex flex-col ${sizeClasses.container}`, children: [
167
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: `flex flex-col`, children: [
176
168
  label && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
177
169
  Text_default,
178
170
  {