asterui 0.12.62 → 0.12.63
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.
- package/dist/components/Anchor.d.ts +2 -0
- package/dist/components/Anchor.js +79 -75
- package/dist/components/Anchor.js.map +1 -1
- package/dist/components/Autocomplete.d.ts +1 -0
- package/dist/components/Autocomplete.js +115 -110
- package/dist/components/Autocomplete.js.map +1 -1
- package/dist/components/Breadcrumb.d.ts +4 -2
- package/dist/components/Breadcrumb.js +54 -29
- package/dist/components/Breadcrumb.js.map +1 -1
- package/dist/components/Button.d.ts +5 -1
- package/dist/components/Button.js +117 -107
- package/dist/components/Button.js.map +1 -1
- package/dist/components/Chart.d.ts +1 -0
- package/dist/components/Chart.js +31 -30
- package/dist/components/Chart.js.map +1 -1
- package/dist/components/Chat.d.ts +1 -0
- package/dist/components/Chat.js +32 -30
- package/dist/components/Chat.js.map +1 -1
- package/dist/components/Command.d.ts +5 -2
- package/dist/components/Command.js +262 -233
- package/dist/components/Command.js.map +1 -1
- package/dist/components/ContextMenu.d.ts +4 -0
- package/dist/components/ContextMenu.js +149 -130
- package/dist/components/ContextMenu.js.map +1 -1
- package/dist/components/Dock.d.ts +2 -0
- package/dist/components/Dock.js +70 -46
- package/dist/components/Dock.js.map +1 -1
- package/dist/components/FileInput.d.ts +1 -0
- package/dist/components/FileInput.js +26 -26
- package/dist/components/FileInput.js.map +1 -1
- package/dist/components/Filter.d.ts +1 -0
- package/dist/components/Filter.js +43 -40
- package/dist/components/Filter.js.map +1 -1
- package/dist/components/Flex.d.ts +1 -0
- package/dist/components/Flex.js +43 -42
- package/dist/components/Flex.js.map +1 -1
- package/dist/components/FloatButton.d.ts +3 -0
- package/dist/components/FloatButton.js +178 -127
- package/dist/components/FloatButton.js.map +1 -1
- package/dist/components/Input.d.ts +1 -0
- package/dist/components/Input.js +201 -184
- package/dist/components/Input.js.map +1 -1
- package/dist/components/Loading.d.ts +1 -0
- package/dist/components/Loading.js +40 -37
- package/dist/components/Loading.js.map +1 -1
- package/dist/components/Masonry.d.ts +1 -0
- package/dist/components/Masonry.js +45 -42
- package/dist/components/Masonry.js.map +1 -1
- package/dist/components/Mention.d.ts +1 -0
- package/dist/components/Mention.js +95 -91
- package/dist/components/Mention.js.map +1 -1
- package/dist/components/MonthCalendar.d.ts +1 -0
- package/dist/components/MonthCalendar.js +104 -97
- package/dist/components/MonthCalendar.js.map +1 -1
- package/dist/components/QRCode.d.ts +1 -0
- package/dist/components/QRCode.js +84 -55
- package/dist/components/QRCode.js.map +1 -1
- package/dist/components/RadialProgress.d.ts +1 -0
- package/dist/components/RadialProgress.js +19 -17
- package/dist/components/RadialProgress.js.map +1 -1
- package/dist/components/Range.d.ts +1 -0
- package/dist/components/Range.js +45 -43
- package/dist/components/Range.js.map +1 -1
- package/dist/components/Rating.d.ts +4 -2
- package/dist/components/Rating.js +83 -79
- package/dist/components/Rating.js.map +1 -1
- package/dist/components/Responsive.d.ts +4 -2
- package/dist/components/Responsive.js +10 -9
- package/dist/components/Responsive.js.map +1 -1
- package/dist/components/Result.d.ts +1 -0
- package/dist/components/Result.js +24 -22
- package/dist/components/Result.js.map +1 -1
- package/dist/components/Select.d.ts +1 -0
- package/dist/components/Select.js +72 -62
- package/dist/components/Select.js.map +1 -1
- package/dist/components/Splitter.d.ts +2 -0
- package/dist/components/Splitter.js +137 -131
- package/dist/components/Splitter.js.map +1 -1
- package/dist/components/Stat.d.ts +4 -2
- package/dist/components/Stat.js +19 -18
- package/dist/components/Stat.js.map +1 -1
- package/dist/components/Steps.d.ts +4 -2
- package/dist/components/Steps.js +56 -52
- package/dist/components/Steps.js.map +1 -1
- package/dist/components/TextRotate.d.ts +1 -0
- package/dist/components/TextRotate.js +14 -12
- package/dist/components/TextRotate.js.map +1 -1
- package/dist/components/Textarea.d.ts +1 -0
- package/dist/components/Textarea.js +31 -30
- package/dist/components/Textarea.js.map +1 -1
- package/dist/components/ThemeController.d.ts +6 -3
- package/dist/components/ThemeController.js +101 -92
- package/dist/components/ThemeController.js.map +1 -1
- package/dist/components/Typography.d.ts +10 -5
- package/dist/components/Typography.js +84 -81
- package/dist/components/Typography.js.map +1 -1
- package/dist/components/VirtualList.d.ts +2 -1
- package/dist/components/VirtualList.js +40 -36
- package/dist/components/VirtualList.js.map +1 -1
- package/dist/components/Watermark.d.ts +1 -0
- package/dist/components/Watermark.js +74 -71
- package/dist/components/Watermark.js.map +1 -1
- package/dist/components/WeekCalendar.d.ts +1 -0
- package/dist/components/WeekCalendar.js +91 -76
- package/dist/components/WeekCalendar.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ContextMenu.js","sources":["../../src/components/ContextMenu.tsx"],"sourcesContent":["import React, { useState, useRef, useEffect, useCallback, createContext, useContext } from 'react'\nimport { createPortal } from 'react-dom'\nimport { useConfig } from '../providers/ConfigProvider'\n\n// DaisyUI classes\nconst dMenu = 'menu'\nconst dDivider = 'divider'\n\nexport interface ContextMenuItem {\n key: string\n label: React.ReactNode\n icon?: React.ReactNode\n disabled?: boolean\n danger?: boolean\n divider?: boolean\n children?: ContextMenuItem[]\n}\n\nexport interface ContextMenuProps {\n /** Element that triggers the context menu on right-click */\n children: React.ReactNode\n /** Menu items (data-driven pattern) */\n items?: ContextMenuItem[]\n /** Callback when an item is selected */\n onSelect?: (key: string) => void\n /** Whether the context menu is disabled */\n disabled?: boolean\n /** Additional CSS classes for the menu */\n className?: string\n}\n\nexport interface ContextMenuItemProps {\n /** Item content */\n children: React.ReactNode\n /** Icon to display before label */\n icon?: React.ReactNode\n /** Whether the item is disabled */\n disabled?: boolean\n /** Show as danger/destructive action */\n danger?: boolean\n /** Additional CSS classes */\n className?: string\n /** @internal */\n _key?: string\n}\n\nexport interface ContextMenuDividerProps {\n /** Additional CSS classes */\n className?: string\n}\n\nexport interface ContextMenuSubMenuProps {\n /** Submenu label */\n label: React.ReactNode\n /** Icon to display before label */\n icon?: React.ReactNode\n /** Whether the submenu is disabled */\n disabled?: boolean\n /** Submenu items */\n children: React.ReactNode\n /** Additional CSS classes */\n className?: string\n /** @internal */\n _key?: string\n}\n\ninterface ContextMenuContextValue {\n onSelect: (key: string) => void\n onClose: () => void\n}\n\ninterface MenuPosition {\n x: number\n y: number\n}\n\nconst ContextMenuContext = createContext<ContextMenuContextValue | null>(null)\n\nconst useContextMenuContext = () => {\n const context = useContext(ContextMenuContext)\n if (!context) {\n throw new Error('ContextMenu compound components must be used within a ContextMenu')\n }\n return context\n}\n\n// Compound pattern components\nconst ContextMenuItemComponent: React.FC<ContextMenuItemProps> = ({\n children,\n icon,\n disabled = false,\n danger = false,\n className = '',\n _key,\n}) => {\n const { onSelect, onClose } = useContextMenuContext()\n\n const handleClick = () => {\n if (disabled || !_key) return\n onSelect(_key)\n onClose()\n }\n\n return (\n <li className={className} role=\"none\">\n <button\n onClick={handleClick}\n disabled={disabled}\n role=\"menuitem\"\n aria-disabled={disabled}\n className={`\n flex items-center gap-2 w-full px-4 py-2 text-left text-sm\n ${disabled ? 'opacity-50 cursor-not-allowed' : 'hover:bg-base-200'}\n ${danger ? 'text-error hover:bg-error/10' : ''}\n `}\n >\n {icon && <span className=\"w-4 h-4\" aria-hidden=\"true\">{icon}</span>}\n <span className=\"flex-1\">{children}</span>\n </button>\n </li>\n )\n}\n\nconst ContextMenuDividerComponent: React.FC<ContextMenuDividerProps> = ({ className = '' }) => {\n return <li className={`${dDivider} my-1 ${className}`} role=\"separator\"></li>\n}\n\nconst ContextMenuSubMenuComponent: React.FC<ContextMenuSubMenuProps> = ({\n label,\n icon,\n disabled = false,\n children,\n className = '',\n _key: _unusedKey,\n}) => {\n const [showSubmenu, setShowSubmenu] = useState(false)\n const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null)\n\n const handleMouseEnter = () => {\n if (disabled) return\n if (timeoutRef.current) clearTimeout(timeoutRef.current)\n setShowSubmenu(true)\n }\n\n const handleMouseLeave = () => {\n timeoutRef.current = setTimeout(() => setShowSubmenu(false), 100)\n }\n\n return (\n <li\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n className={`relative ${className}`}\n role=\"none\"\n >\n <button\n disabled={disabled}\n role=\"menuitem\"\n aria-haspopup=\"menu\"\n aria-expanded={showSubmenu}\n aria-disabled={disabled}\n className={`\n flex items-center gap-2 w-full px-4 py-2 text-left text-sm\n ${disabled ? 'opacity-50 cursor-not-allowed' : 'hover:bg-base-200'}\n `}\n >\n {icon && <span className=\"w-4 h-4\" aria-hidden=\"true\">{icon}</span>}\n <span className=\"flex-1\">{label}</span>\n <svg className=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" aria-hidden=\"true\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M9 5l7 7-7 7\" />\n </svg>\n </button>\n {showSubmenu && (\n <ul\n className={`${dMenu} bg-base-100 rounded-box shadow-lg border border-base-300 absolute left-full top-0 min-w-[160px] z-50 p-1`}\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n role=\"menu\"\n >\n {children}\n </ul>\n )}\n </li>\n )\n}\n\n// Data-driven pattern internal component\nconst MenuItem: React.FC<{\n item: ContextMenuItem\n onSelect: (key: string) => void\n onClose: () => void\n}> = ({ item, onSelect, onClose }) => {\n const [showSubmenu, setShowSubmenu] = useState(false)\n const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null)\n\n if (item.divider) {\n return <li className={`${dDivider} my-1`} role=\"separator\"></li>\n }\n\n const handleClick = () => {\n if (item.disabled) return\n if (item.children && item.children.length > 0) return\n onSelect(item.key)\n onClose()\n }\n\n const hasSubmenu = item.children && item.children.length > 0\n\n const handleMouseEnter = () => {\n if (!hasSubmenu) return\n if (timeoutRef.current) clearTimeout(timeoutRef.current)\n setShowSubmenu(true)\n }\n\n const handleMouseLeave = () => {\n if (!hasSubmenu) return\n timeoutRef.current = setTimeout(() => setShowSubmenu(false), 100)\n }\n\n return (\n <li\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n className=\"relative\"\n role=\"none\"\n >\n <button\n onClick={handleClick}\n disabled={item.disabled}\n role=\"menuitem\"\n aria-haspopup={hasSubmenu ? 'menu' : undefined}\n aria-expanded={hasSubmenu ? showSubmenu : undefined}\n aria-disabled={item.disabled}\n className={`\n flex items-center gap-2 w-full px-4 py-2 text-left text-sm\n ${item.disabled ? 'opacity-50 cursor-not-allowed' : 'hover:bg-base-200'}\n ${item.danger ? 'text-error hover:bg-error/10' : ''}\n `}\n >\n {item.icon && <span className=\"w-4 h-4\" aria-hidden=\"true\">{item.icon}</span>}\n <span className=\"flex-1\">{item.label}</span>\n {hasSubmenu && (\n <svg className=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" aria-hidden=\"true\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M9 5l7 7-7 7\" />\n </svg>\n )}\n </button>\n {hasSubmenu && showSubmenu && (\n <ul\n className={`${dMenu} bg-base-100 rounded-box shadow-lg border border-base-300 absolute left-full top-0 min-w-[160px] z-50 p-1`}\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n role=\"menu\"\n >\n {item.children!.map((child) => (\n <MenuItem key={child.key} item={child} onSelect={onSelect} onClose={onClose} />\n ))}\n </ul>\n )}\n </li>\n )\n}\n\nconst ContextMenuRoot: React.FC<ContextMenuProps> = ({\n children,\n items,\n onSelect,\n disabled = false,\n className = '',\n}) => {\n const { getPopupContainer } = useConfig()\n const [visible, setVisible] = useState(false)\n const [position, setPosition] = useState<MenuPosition>({ x: 0, y: 0 })\n const menuRef = useRef<HTMLUListElement>(null)\n const triggerRef = useRef<HTMLDivElement>(null)\n\n const handleContextMenu = useCallback(\n (e: React.MouseEvent) => {\n if (disabled) return\n e.preventDefault()\n e.stopPropagation()\n\n // Calculate position, ensuring menu stays within viewport\n let x = e.clientX\n let y = e.clientY\n\n // We'll adjust after render when we know menu dimensions\n setPosition({ x, y })\n setVisible(true)\n },\n [disabled]\n )\n\n const handleClose = useCallback(() => {\n setVisible(false)\n }, [])\n\n const handleSelect = useCallback(\n (key: string) => {\n onSelect?.(key)\n },\n [onSelect]\n )\n\n // Adjust position after menu renders to keep it in viewport\n useEffect(() => {\n if (visible && menuRef.current) {\n const menu = menuRef.current\n const rect = menu.getBoundingClientRect()\n const viewportWidth = window.innerWidth\n const viewportHeight = window.innerHeight\n\n let { x, y } = position\n\n if (x + rect.width > viewportWidth) {\n x = viewportWidth - rect.width - 8\n }\n if (y + rect.height > viewportHeight) {\n y = viewportHeight - rect.height - 8\n }\n\n if (x !== position.x || y !== position.y) {\n setPosition({ x, y })\n }\n }\n }, [visible, position])\n\n // Close on click outside or escape\n useEffect(() => {\n if (!visible) return\n\n const handleClickOutside = (e: MouseEvent) => {\n if (menuRef.current && !menuRef.current.contains(e.target as Node)) {\n handleClose()\n }\n }\n\n const handleEscape = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n handleClose()\n }\n }\n\n const handleScroll = () => {\n handleClose()\n }\n\n document.addEventListener('mousedown', handleClickOutside)\n document.addEventListener('keydown', handleEscape)\n document.addEventListener('scroll', handleScroll, true)\n\n return () => {\n document.removeEventListener('mousedown', handleClickOutside)\n document.removeEventListener('keydown', handleEscape)\n document.removeEventListener('scroll', handleScroll, true)\n }\n }, [visible, handleClose])\n\n // Clone children to extract keys\n const cloneChildrenWithKeys = (children: React.ReactNode): React.ReactNode => {\n return React.Children.map(children, (child) => {\n if (React.isValidElement(child)) {\n const childKey = child.key != null ? String(child.key) : undefined\n if (child.type === ContextMenuItemComponent || child.type === ContextMenuSubMenuComponent) {\n return React.cloneElement(child as React.ReactElement<any>, { _key: childKey })\n }\n }\n return child\n })\n }\n\n // Determine if using data-driven or compound pattern\n // Find menu content children (not the trigger element)\n const childArray = React.Children.toArray(children)\n const triggerChild = childArray[0]\n const menuChildren = cloneChildrenWithKeys(childArray.slice(1))\n const useDataDriven = items && items.length > 0\n\n const contextValue: ContextMenuContextValue = {\n onSelect: handleSelect,\n onClose: handleClose,\n }\n\n return (\n <>\n <div ref={triggerRef} onContextMenu={handleContextMenu} className=\"inline-block\">\n {triggerChild}\n </div>\n {visible &&\n createPortal(\n <ContextMenuContext.Provider value={contextValue}>\n <ul\n ref={menuRef}\n className={`${dMenu} bg-base-100 rounded-box shadow-lg border border-base-300 min-w-[160px] p-1 fixed z-[9999] ${className}`}\n style={{ left: position.x, top: position.y }}\n role=\"menu\"\n aria-label=\"Context menu\"\n >\n {useDataDriven\n ? items!.map((item) => (\n <MenuItem key={item.key} item={item} onSelect={handleSelect} onClose={handleClose} />\n ))\n : menuChildren}\n </ul>\n </ContextMenuContext.Provider>,\n getPopupContainer ? getPopupContainer(document.body) : document.body\n )}\n </>\n )\n}\n\n// Assign compound components\nexport const ContextMenu = Object.assign(ContextMenuRoot, {\n Item: ContextMenuItemComponent,\n Divider: ContextMenuDividerComponent,\n SubMenu: ContextMenuSubMenuComponent,\n})\n"],"names":["dMenu","dDivider","ContextMenuContext","createContext","useContextMenuContext","context","useContext","ContextMenuItemComponent","children","icon","disabled","danger","className","_key","onSelect","onClose","jsx","jsxs","ContextMenuDividerComponent","ContextMenuSubMenuComponent","label","_unusedKey","showSubmenu","setShowSubmenu","useState","timeoutRef","useRef","handleMouseEnter","handleMouseLeave","MenuItem","item","handleClick","hasSubmenu","child","ContextMenuRoot","items","getPopupContainer","useConfig","visible","setVisible","position","setPosition","menuRef","triggerRef","handleContextMenu","useCallback","e","x","y","handleClose","handleSelect","key","useEffect","rect","viewportWidth","viewportHeight","handleClickOutside","handleEscape","handleScroll","cloneChildrenWithKeys","React","childKey","childArray","triggerChild","menuChildren","useDataDriven","contextValue","Fragment","createPortal","ContextMenu"],"mappings":";;;;AAKA,MAAMA,IAAQ,QACRC,IAAW,WAsEXC,IAAqBC,EAA8C,IAAI,GAEvEC,IAAwB,MAAM;AAClC,QAAMC,IAAUC,EAAWJ,CAAkB;AAC7C,MAAI,CAACG;AACH,UAAM,IAAI,MAAM,mEAAmE;AAErF,SAAOA;AACT,GAGME,IAA2D,CAAC;AAAA,EAChE,UAAAC;AAAA,EACA,MAAAC;AAAA,EACA,UAAAC,IAAW;AAAA,EACX,QAAAC,IAAS;AAAA,EACT,WAAAC,IAAY;AAAA,EACZ,MAAAC;AACF,MAAM;AACJ,QAAM,EAAE,UAAAC,GAAU,SAAAC,EAAA,IAAYX,EAAA;AAQ9B,SACE,gBAAAY,EAAC,MAAA,EAAG,WAAAJ,GAAsB,MAAK,QAC7B,UAAA,gBAAAK;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,SATc,MAAM;AACxB,QAAIP,KAAY,CAACG,MACjBC,EAASD,CAAI,GACbE,EAAA;AAAA,MACF;AAAA,MAMM,UAAAL;AAAA,MACA,MAAK;AAAA,MACL,iBAAeA;AAAA,MACf,WAAW;AAAA;AAAA,YAEPA,IAAW,kCAAkC,mBAAmB;AAAA,YAChEC,IAAS,iCAAiC,EAAE;AAAA;AAAA,MAG/C,UAAA;AAAA,QAAAF,uBAAS,QAAA,EAAK,WAAU,WAAU,eAAY,QAAQ,UAAAA,GAAK;AAAA,QAC5D,gBAAAO,EAAC,QAAA,EAAK,WAAU,UAAU,UAAAR,EAAA,CAAS;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA,GAEvC;AAEJ,GAEMU,IAAiE,CAAC,EAAE,WAAAN,IAAY,SAC7E,gBAAAI,EAAC,QAAG,WAAW,GAAGf,CAAQ,SAASW,CAAS,IAAI,MAAK,YAAA,CAAY,GAGpEO,IAAiE,CAAC;AAAA,EACtE,OAAAC;AAAA,EACA,MAAAX;AAAA,EACA,UAAAC,IAAW;AAAA,EACX,UAAAF;AAAA,EACA,WAAAI,IAAY;AAAA,EACZ,MAAMS;AACR,MAAM;AACJ,QAAM,CAACC,GAAaC,CAAc,IAAIC,EAAS,EAAK,GAC9CC,IAAaC,EAA6C,IAAI,GAE9DC,IAAmB,MAAM;AAC7B,IAAIjB,MACAe,EAAW,WAAS,aAAaA,EAAW,OAAO,GACvDF,EAAe,EAAI;AAAA,EACrB,GAEMK,IAAmB,MAAM;AAC7B,IAAAH,EAAW,UAAU,WAAW,MAAMF,EAAe,EAAK,GAAG,GAAG;AAAA,EAClE;AAEA,SACE,gBAAAN;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,cAAcU;AAAA,MACd,cAAcC;AAAA,MACd,WAAW,YAAYhB,CAAS;AAAA,MAChC,MAAK;AAAA,MAEL,UAAA;AAAA,QAAA,gBAAAK;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,UAAAP;AAAA,YACA,MAAK;AAAA,YACL,iBAAc;AAAA,YACd,iBAAeY;AAAA,YACf,iBAAeZ;AAAA,YACf,WAAW;AAAA;AAAA,YAEPA,IAAW,kCAAkC,mBAAmB;AAAA;AAAA,YAGnE,UAAA;AAAA,cAAAD,uBAAS,QAAA,EAAK,WAAU,WAAU,eAAY,QAAQ,UAAAA,GAAK;AAAA,cAC5D,gBAAAO,EAAC,QAAA,EAAK,WAAU,UAAU,UAAAI,GAAM;AAAA,cAChC,gBAAAJ,EAAC,SAAI,WAAU,WAAU,MAAK,QAAO,SAAQ,aAAY,QAAO,gBAAe,eAAY,QACzF,UAAA,gBAAAA,EAAC,QAAA,EAAK,eAAc,SAAQ,gBAAe,SAAQ,aAAa,GAAG,GAAE,eAAA,CAAe,EAAA,CACtF;AAAA,YAAA;AAAA,UAAA;AAAA,QAAA;AAAA,QAEDM,KACC,gBAAAN;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAW,GAAGhB,CAAK;AAAA,YACnB,cAAc2B;AAAA,YACd,cAAcC;AAAA,YACd,MAAK;AAAA,YAEJ,UAAApB;AAAA,UAAA;AAAA,QAAA;AAAA,MACH;AAAA,IAAA;AAAA,EAAA;AAIR,GAGMqB,IAID,CAAC,EAAE,MAAAC,GAAM,UAAAhB,GAAU,SAAAC,QAAc;AACpC,QAAM,CAACO,GAAaC,CAAc,IAAIC,EAAS,EAAK,GAC9CC,IAAaC,EAA6C,IAAI;AAEpE,MAAII,EAAK;AACP,6BAAQ,MAAA,EAAG,WAAW,GAAG7B,CAAQ,SAAS,MAAK,aAAY;AAG7D,QAAM8B,IAAc,MAAM;AACxB,IAAID,EAAK,YACLA,EAAK,YAAYA,EAAK,SAAS,SAAS,MAC5ChB,EAASgB,EAAK,GAAG,GACjBf,EAAA;AAAA,EACF,GAEMiB,IAAaF,EAAK,YAAYA,EAAK,SAAS,SAAS,GAErDH,IAAmB,MAAM;AAC7B,IAAKK,MACDP,EAAW,WAAS,aAAaA,EAAW,OAAO,GACvDF,EAAe,EAAI;AAAA,EACrB,GAEMK,IAAmB,MAAM;AAC7B,IAAKI,MACLP,EAAW,UAAU,WAAW,MAAMF,EAAe,EAAK,GAAG,GAAG;AAAA,EAClE;AAEA,SACE,gBAAAN;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,cAAcU;AAAA,MACd,cAAcC;AAAA,MACd,WAAU;AAAA,MACV,MAAK;AAAA,MAEL,UAAA;AAAA,QAAA,gBAAAX;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,SAASc;AAAA,YACT,UAAUD,EAAK;AAAA,YACf,MAAK;AAAA,YACL,iBAAeE,IAAa,SAAS;AAAA,YACrC,iBAAeA,IAAaV,IAAc;AAAA,YAC1C,iBAAeQ,EAAK;AAAA,YACpB,WAAW;AAAA;AAAA,YAEPA,EAAK,WAAW,kCAAkC,mBAAmB;AAAA,YACrEA,EAAK,SAAS,iCAAiC,EAAE;AAAA;AAAA,YAGpD,UAAA;AAAA,cAAAA,EAAK,0BAAS,QAAA,EAAK,WAAU,WAAU,eAAY,QAAQ,YAAK,KAAA,CAAK;AAAA,cACtE,gBAAAd,EAAC,QAAA,EAAK,WAAU,UAAU,YAAK,OAAM;AAAA,cACpCgB,uBACE,OAAA,EAAI,WAAU,WAAU,MAAK,QAAO,SAAQ,aAAY,QAAO,gBAAe,eAAY,QACzF,UAAA,gBAAAhB,EAAC,QAAA,EAAK,eAAc,SAAQ,gBAAe,SAAQ,aAAa,GAAG,GAAE,eAAA,CAAe,EAAA,CACtF;AAAA,YAAA;AAAA,UAAA;AAAA,QAAA;AAAA,QAGHgB,KAAcV,KACb,gBAAAN;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAW,GAAGhB,CAAK;AAAA,YACnB,cAAc2B;AAAA,YACd,cAAcC;AAAA,YACd,MAAK;AAAA,YAEJ,UAAAE,EAAK,SAAU,IAAI,CAACG,MACnB,gBAAAjB,EAACa,GAAA,EAAyB,MAAMI,GAAO,UAAAnB,GAAoB,SAAAC,EAAA,GAA5CkB,EAAM,GAAwD,CAC9E;AAAA,UAAA;AAAA,QAAA;AAAA,MACH;AAAA,IAAA;AAAA,EAAA;AAIR,GAEMC,IAA8C,CAAC;AAAA,EACnD,UAAA1B;AAAA,EACA,OAAA2B;AAAA,EACA,UAAArB;AAAA,EACA,UAAAJ,IAAW;AAAA,EACX,WAAAE,IAAY;AACd,MAAM;AACJ,QAAM,EAAE,mBAAAwB,EAAA,IAAsBC,EAAA,GACxB,CAACC,GAASC,CAAU,IAAIf,EAAS,EAAK,GACtC,CAACgB,GAAUC,CAAW,IAAIjB,EAAuB,EAAE,GAAG,GAAG,GAAG,GAAG,GAC/DkB,IAAUhB,EAAyB,IAAI,GACvCiB,IAAajB,EAAuB,IAAI,GAExCkB,IAAoBC;AAAA,IACxB,CAACC,MAAwB;AACvB,UAAIpC,EAAU;AACd,MAAAoC,EAAE,eAAA,GACFA,EAAE,gBAAA;AAGF,UAAIC,IAAID,EAAE,SACNE,IAAIF,EAAE;AAGV,MAAAL,EAAY,EAAE,GAAAM,GAAG,GAAAC,GAAG,GACpBT,EAAW,EAAI;AAAA,IACjB;AAAA,IACA,CAAC7B,CAAQ;AAAA,EAAA,GAGLuC,IAAcJ,EAAY,MAAM;AACpC,IAAAN,EAAW,EAAK;AAAA,EAClB,GAAG,CAAA,CAAE,GAECW,IAAeL;AAAA,IACnB,CAACM,MAAgB;AACf,MAAArC,IAAWqC,CAAG;AAAA,IAChB;AAAA,IACA,CAACrC,CAAQ;AAAA,EAAA;AAIX,EAAAsC,EAAU,MAAM;AACd,QAAId,KAAWI,EAAQ,SAAS;AAE9B,YAAMW,IADOX,EAAQ,QACH,sBAAA,GACZY,IAAgB,OAAO,YACvBC,IAAiB,OAAO;AAE9B,UAAI,EAAE,GAAAR,GAAG,GAAAC,EAAA,IAAMR;AAEf,MAAIO,IAAIM,EAAK,QAAQC,MACnBP,IAAIO,IAAgBD,EAAK,QAAQ,IAE/BL,IAAIK,EAAK,SAASE,MACpBP,IAAIO,IAAiBF,EAAK,SAAS,KAGjCN,MAAMP,EAAS,KAAKQ,MAAMR,EAAS,MACrCC,EAAY,EAAE,GAAAM,GAAG,GAAAC,GAAG;AAAA,IAExB;AAAA,EACF,GAAG,CAACV,GAASE,CAAQ,CAAC,GAGtBY,EAAU,MAAM;AACd,QAAI,CAACd,EAAS;AAEd,UAAMkB,IAAqB,CAACV,MAAkB;AAC5C,MAAIJ,EAAQ,WAAW,CAACA,EAAQ,QAAQ,SAASI,EAAE,MAAc,KAC/DG,EAAA;AAAA,IAEJ,GAEMQ,IAAe,CAACX,MAAqB;AACzC,MAAIA,EAAE,QAAQ,YACZG,EAAA;AAAA,IAEJ,GAEMS,IAAe,MAAM;AACzB,MAAAT,EAAA;AAAA,IACF;AAEA,oBAAS,iBAAiB,aAAaO,CAAkB,GACzD,SAAS,iBAAiB,WAAWC,CAAY,GACjD,SAAS,iBAAiB,UAAUC,GAAc,EAAI,GAE/C,MAAM;AACX,eAAS,oBAAoB,aAAaF,CAAkB,GAC5D,SAAS,oBAAoB,WAAWC,CAAY,GACpD,SAAS,oBAAoB,UAAUC,GAAc,EAAI;AAAA,IAC3D;AAAA,EACF,GAAG,CAACpB,GAASW,CAAW,CAAC;AAGzB,QAAMU,IAAwB,CAACnD,MACtBoD,EAAM,SAAS,IAAIpD,GAAU,CAACyB,MAAU;AAC7C,QAAI2B,EAAM,eAAe3B,CAAK,GAAG;AAC/B,YAAM4B,IAAW5B,EAAM,OAAO,OAAO,OAAOA,EAAM,GAAG,IAAI;AACzD,UAAIA,EAAM,SAAS1B,KAA4B0B,EAAM,SAASd;AAC5D,eAAOyC,EAAM,aAAa3B,GAAkC,EAAE,MAAM4B,GAAU;AAAA,IAElF;AACA,WAAO5B;AAAA,EACT,CAAC,GAKG6B,IAAaF,EAAM,SAAS,QAAQpD,CAAQ,GAC5CuD,IAAeD,EAAW,CAAC,GAC3BE,IAAeL,EAAsBG,EAAW,MAAM,CAAC,CAAC,GACxDG,IAAgB9B,KAASA,EAAM,SAAS,GAExC+B,IAAwC;AAAA,IAC5C,UAAUhB;AAAA,IACV,SAASD;AAAA,EAAA;AAGX,SACE,gBAAAhC,EAAAkD,GAAA,EACE,UAAA;AAAA,IAAA,gBAAAnD,EAAC,SAAI,KAAK2B,GAAY,eAAeC,GAAmB,WAAU,gBAC/D,UAAAmB,EAAA,CACH;AAAA,IACCzB,KACC8B;AAAA,MACE,gBAAApD,EAACd,EAAmB,UAAnB,EAA4B,OAAOgE,GAClC,UAAA,gBAAAlD;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,KAAK0B;AAAA,UACL,WAAW,GAAG1C,CAAK,8FAA8FY,CAAS;AAAA,UAC1H,OAAO,EAAE,MAAM4B,EAAS,GAAG,KAAKA,EAAS,EAAA;AAAA,UACzC,MAAK;AAAA,UACL,cAAW;AAAA,UAEV,UAAAyB,IACG9B,EAAO,IAAI,CAACL,MACV,gBAAAd,EAACa,GAAA,EAAwB,MAAAC,GAAY,UAAUoB,GAAc,SAASD,EAAA,GAAvDnB,EAAK,GAA+D,CACpF,IACDkC;AAAA,QAAA;AAAA,MAAA,GAER;AAAA,MACA5B,IAAoBA,EAAkB,SAAS,IAAI,IAAI,SAAS;AAAA,IAAA;AAAA,EAClE,GACJ;AAEJ,GAGaiC,IAAc,OAAO,OAAOnC,GAAiB;AAAA,EACxD,MAAM3B;AAAA,EACN,SAASW;AAAA,EACT,SAASC;AACX,CAAC;"}
|
|
1
|
+
{"version":3,"file":"ContextMenu.js","sources":["../../src/components/ContextMenu.tsx"],"sourcesContent":["import React, { useState, useRef, useEffect, useCallback, createContext, useContext } from 'react'\nimport { createPortal } from 'react-dom'\nimport { useConfig } from '../providers/ConfigProvider'\n\n// DaisyUI classes\nconst dMenu = 'menu'\nconst dDivider = 'divider'\n\nexport interface ContextMenuItem {\n key: string\n label: React.ReactNode\n icon?: React.ReactNode\n disabled?: boolean\n danger?: boolean\n divider?: boolean\n children?: ContextMenuItem[]\n}\n\nexport interface ContextMenuProps {\n /** Element that triggers the context menu on right-click */\n children: React.ReactNode\n /** Menu items (data-driven pattern) */\n items?: ContextMenuItem[]\n /** Callback when an item is selected */\n onSelect?: (key: string) => void\n /** Whether the context menu is disabled */\n disabled?: boolean\n /** Additional CSS classes for the menu */\n className?: string\n 'data-testid'?: string\n}\n\nexport interface ContextMenuItemProps {\n /** Item content */\n children: React.ReactNode\n /** Icon to display before label */\n icon?: React.ReactNode\n /** Whether the item is disabled */\n disabled?: boolean\n /** Show as danger/destructive action */\n danger?: boolean\n /** Additional CSS classes */\n className?: string\n /** @internal */\n _key?: string\n 'data-testid'?: string\n}\n\nexport interface ContextMenuDividerProps {\n /** Additional CSS classes */\n className?: string\n 'data-testid'?: string\n}\n\nexport interface ContextMenuSubMenuProps {\n /** Submenu label */\n label: React.ReactNode\n /** Icon to display before label */\n icon?: React.ReactNode\n /** Whether the submenu is disabled */\n disabled?: boolean\n /** Submenu items */\n children: React.ReactNode\n /** Additional CSS classes */\n className?: string\n /** @internal */\n _key?: string\n 'data-testid'?: string\n}\n\ninterface ContextMenuContextValue {\n onSelect: (key: string) => void\n onClose: () => void\n getTestId?: (suffix: string) => string | undefined\n}\n\ninterface MenuPosition {\n x: number\n y: number\n}\n\nconst ContextMenuContext = createContext<ContextMenuContextValue | null>(null)\n\nconst useContextMenuContext = () => {\n const context = useContext(ContextMenuContext)\n if (!context) {\n throw new Error('ContextMenu compound components must be used within a ContextMenu')\n }\n return context\n}\n\n// Compound pattern components\nconst ContextMenuItemComponent: React.FC<ContextMenuItemProps> = ({\n children,\n icon,\n disabled = false,\n danger = false,\n className = '',\n _key,\n 'data-testid': testId,\n}) => {\n const { onSelect, onClose, getTestId } = useContextMenuContext()\n const itemTestId = testId ?? (_key ? getTestId?.(`item-${_key}`) : undefined)\n\n const handleClick = () => {\n if (disabled || !_key) return\n onSelect(_key)\n onClose()\n }\n\n return (\n <li className={className} role=\"none\">\n <button\n onClick={handleClick}\n disabled={disabled}\n role=\"menuitem\"\n aria-disabled={disabled}\n data-testid={itemTestId}\n className={`\n flex items-center gap-2 w-full px-4 py-2 text-left text-sm\n ${disabled ? 'opacity-50 cursor-not-allowed' : 'hover:bg-base-200'}\n ${danger ? 'text-error hover:bg-error/10' : ''}\n `}\n >\n {icon && <span className=\"w-4 h-4\" aria-hidden=\"true\">{icon}</span>}\n <span className=\"flex-1\">{children}</span>\n </button>\n </li>\n )\n}\n\nconst ContextMenuDividerComponent: React.FC<ContextMenuDividerProps> = ({ className = '', 'data-testid': testId }) => {\n return <li className={`${dDivider} my-1 ${className}`} role=\"separator\" data-testid={testId}></li>\n}\n\nconst ContextMenuSubMenuComponent: React.FC<ContextMenuSubMenuProps> = ({\n label,\n icon,\n disabled = false,\n children,\n className = '',\n _key: _unusedKey,\n 'data-testid': testId,\n}) => {\n const { getTestId } = useContextMenuContext()\n const [showSubmenu, setShowSubmenu] = useState(false)\n const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null)\n const submenuTestId = testId ?? (_unusedKey ? getTestId?.(`submenu-${_unusedKey}`) : undefined)\n\n const handleMouseEnter = () => {\n if (disabled) return\n if (timeoutRef.current) clearTimeout(timeoutRef.current)\n setShowSubmenu(true)\n }\n\n const handleMouseLeave = () => {\n timeoutRef.current = setTimeout(() => setShowSubmenu(false), 100)\n }\n\n return (\n <li\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n className={`relative ${className}`}\n role=\"none\"\n >\n <button\n disabled={disabled}\n role=\"menuitem\"\n aria-haspopup=\"menu\"\n aria-expanded={showSubmenu}\n aria-disabled={disabled}\n data-testid={submenuTestId}\n className={`\n flex items-center gap-2 w-full px-4 py-2 text-left text-sm\n ${disabled ? 'opacity-50 cursor-not-allowed' : 'hover:bg-base-200'}\n `}\n >\n {icon && <span className=\"w-4 h-4\" aria-hidden=\"true\">{icon}</span>}\n <span className=\"flex-1\">{label}</span>\n <svg className=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" aria-hidden=\"true\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M9 5l7 7-7 7\" />\n </svg>\n </button>\n {showSubmenu && (\n <ul\n className={`${dMenu} bg-base-100 rounded-box shadow-lg border border-base-300 absolute left-full top-0 min-w-[160px] z-50 p-1`}\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n role=\"menu\"\n data-testid={submenuTestId ? `${submenuTestId}-menu` : undefined}\n >\n {children}\n </ul>\n )}\n </li>\n )\n}\n\n// Data-driven pattern internal component\nconst MenuItem: React.FC<{\n item: ContextMenuItem\n onSelect: (key: string) => void\n onClose: () => void\n getTestId?: (suffix: string) => string | undefined\n}> = ({ item, onSelect, onClose, getTestId }) => {\n const [showSubmenu, setShowSubmenu] = useState(false)\n const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null)\n const itemTestId = getTestId?.(`item-${item.key}`)\n\n if (item.divider) {\n return <li className={`${dDivider} my-1`} role=\"separator\" data-testid={getTestId?.(`separator-${item.key}`)}></li>\n }\n\n const handleClick = () => {\n if (item.disabled) return\n if (item.children && item.children.length > 0) return\n onSelect(item.key)\n onClose()\n }\n\n const hasSubmenu = item.children && item.children.length > 0\n\n const handleMouseEnter = () => {\n if (!hasSubmenu) return\n if (timeoutRef.current) clearTimeout(timeoutRef.current)\n setShowSubmenu(true)\n }\n\n const handleMouseLeave = () => {\n if (!hasSubmenu) return\n timeoutRef.current = setTimeout(() => setShowSubmenu(false), 100)\n }\n\n return (\n <li\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n className=\"relative\"\n role=\"none\"\n >\n <button\n onClick={handleClick}\n disabled={item.disabled}\n role=\"menuitem\"\n aria-haspopup={hasSubmenu ? 'menu' : undefined}\n aria-expanded={hasSubmenu ? showSubmenu : undefined}\n aria-disabled={item.disabled}\n data-testid={itemTestId}\n className={`\n flex items-center gap-2 w-full px-4 py-2 text-left text-sm\n ${item.disabled ? 'opacity-50 cursor-not-allowed' : 'hover:bg-base-200'}\n ${item.danger ? 'text-error hover:bg-error/10' : ''}\n `}\n >\n {item.icon && <span className=\"w-4 h-4\" aria-hidden=\"true\">{item.icon}</span>}\n <span className=\"flex-1\">{item.label}</span>\n {hasSubmenu && (\n <svg className=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" aria-hidden=\"true\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M9 5l7 7-7 7\" />\n </svg>\n )}\n </button>\n {hasSubmenu && showSubmenu && (\n <ul\n className={`${dMenu} bg-base-100 rounded-box shadow-lg border border-base-300 absolute left-full top-0 min-w-[160px] z-50 p-1`}\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n role=\"menu\"\n data-testid={itemTestId ? `${itemTestId}-menu` : undefined}\n >\n {item.children!.map((child) => (\n <MenuItem key={child.key} item={child} onSelect={onSelect} onClose={onClose} getTestId={getTestId} />\n ))}\n </ul>\n )}\n </li>\n )\n}\n\nconst ContextMenuRoot: React.FC<ContextMenuProps> = ({\n children,\n items,\n onSelect,\n disabled = false,\n className = '',\n 'data-testid': testId,\n}) => {\n const { getPopupContainer } = useConfig()\n const [visible, setVisible] = useState(false)\n const [position, setPosition] = useState<MenuPosition>({ x: 0, y: 0 })\n const menuRef = useRef<HTMLUListElement>(null)\n const triggerRef = useRef<HTMLDivElement>(null)\n\n const handleContextMenu = useCallback(\n (e: React.MouseEvent) => {\n if (disabled) return\n e.preventDefault()\n e.stopPropagation()\n\n // Calculate position, ensuring menu stays within viewport\n let x = e.clientX\n let y = e.clientY\n\n // We'll adjust after render when we know menu dimensions\n setPosition({ x, y })\n setVisible(true)\n },\n [disabled]\n )\n\n const handleClose = useCallback(() => {\n setVisible(false)\n }, [])\n\n const handleSelect = useCallback(\n (key: string) => {\n onSelect?.(key)\n },\n [onSelect]\n )\n\n // Adjust position after menu renders to keep it in viewport\n useEffect(() => {\n if (visible && menuRef.current) {\n const menu = menuRef.current\n const rect = menu.getBoundingClientRect()\n const viewportWidth = window.innerWidth\n const viewportHeight = window.innerHeight\n\n let { x, y } = position\n\n if (x + rect.width > viewportWidth) {\n x = viewportWidth - rect.width - 8\n }\n if (y + rect.height > viewportHeight) {\n y = viewportHeight - rect.height - 8\n }\n\n if (x !== position.x || y !== position.y) {\n setPosition({ x, y })\n }\n }\n }, [visible, position])\n\n // Close on click outside or escape\n useEffect(() => {\n if (!visible) return\n\n const handleClickOutside = (e: MouseEvent) => {\n if (menuRef.current && !menuRef.current.contains(e.target as Node)) {\n handleClose()\n }\n }\n\n const handleEscape = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n handleClose()\n }\n }\n\n const handleScroll = () => {\n handleClose()\n }\n\n document.addEventListener('mousedown', handleClickOutside)\n document.addEventListener('keydown', handleEscape)\n document.addEventListener('scroll', handleScroll, true)\n\n return () => {\n document.removeEventListener('mousedown', handleClickOutside)\n document.removeEventListener('keydown', handleEscape)\n document.removeEventListener('scroll', handleScroll, true)\n }\n }, [visible, handleClose])\n\n // Clone children to extract keys\n const cloneChildrenWithKeys = (children: React.ReactNode): React.ReactNode => {\n return React.Children.map(children, (child) => {\n if (React.isValidElement(child)) {\n const childKey = child.key != null ? String(child.key) : undefined\n if (child.type === ContextMenuItemComponent || child.type === ContextMenuSubMenuComponent) {\n return React.cloneElement(child as React.ReactElement<any>, { _key: childKey })\n }\n }\n return child\n })\n }\n\n // Determine if using data-driven or compound pattern\n // Find menu content children (not the trigger element)\n const childArray = React.Children.toArray(children)\n const triggerChild = childArray[0]\n const menuChildren = cloneChildrenWithKeys(childArray.slice(1))\n const useDataDriven = items && items.length > 0\n\n const contextValue: ContextMenuContextValue = {\n onSelect: handleSelect,\n onClose: handleClose,\n getTestId: testId ? (suffix: string) => `${testId}-${suffix}` : undefined,\n }\n const getTestId = (suffix: string) => (testId ? `${testId}-${suffix}` : undefined)\n\n return (\n <>\n <div\n ref={triggerRef}\n onContextMenu={handleContextMenu}\n className=\"inline-block\"\n data-testid={testId}\n >\n {triggerChild}\n </div>\n {visible &&\n createPortal(\n <ContextMenuContext.Provider value={contextValue}>\n <ul\n ref={menuRef}\n className={`${dMenu} bg-base-100 rounded-box shadow-lg border border-base-300 min-w-[160px] p-1 fixed z-[9999] ${className}`}\n style={{ left: position.x, top: position.y }}\n role=\"menu\"\n aria-label=\"Context menu\"\n data-testid={getTestId('menu')}\n >\n {useDataDriven\n ? items!.map((item) => (\n <MenuItem key={item.key} item={item} onSelect={handleSelect} onClose={handleClose} getTestId={getTestId} />\n ))\n : menuChildren}\n </ul>\n </ContextMenuContext.Provider>,\n getPopupContainer ? getPopupContainer(document.body) : document.body\n )}\n </>\n )\n}\n\n// Assign compound components\nexport const ContextMenu = Object.assign(ContextMenuRoot, {\n Item: ContextMenuItemComponent,\n Divider: ContextMenuDividerComponent,\n SubMenu: ContextMenuSubMenuComponent,\n})\n"],"names":["dMenu","dDivider","ContextMenuContext","createContext","useContextMenuContext","context","useContext","ContextMenuItemComponent","children","icon","disabled","danger","className","_key","testId","onSelect","onClose","getTestId","itemTestId","jsx","jsxs","ContextMenuDividerComponent","ContextMenuSubMenuComponent","label","_unusedKey","showSubmenu","setShowSubmenu","useState","timeoutRef","useRef","submenuTestId","handleMouseEnter","handleMouseLeave","MenuItem","item","handleClick","hasSubmenu","child","ContextMenuRoot","items","getPopupContainer","useConfig","visible","setVisible","position","setPosition","menuRef","triggerRef","handleContextMenu","useCallback","e","x","y","handleClose","handleSelect","key","useEffect","rect","viewportWidth","viewportHeight","handleClickOutside","handleEscape","handleScroll","cloneChildrenWithKeys","React","childKey","childArray","triggerChild","menuChildren","useDataDriven","contextValue","suffix","Fragment","createPortal","ContextMenu"],"mappings":"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"}
|
|
@@ -28,6 +28,7 @@ export interface DockProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'o
|
|
|
28
28
|
className?: string;
|
|
29
29
|
/** Accessible label for the dock */
|
|
30
30
|
'aria-label'?: string;
|
|
31
|
+
'data-testid'?: string;
|
|
31
32
|
}
|
|
32
33
|
export interface DockItemProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
33
34
|
/** Whether this item is active */
|
|
@@ -36,6 +37,7 @@ export interface DockItemProps extends React.ButtonHTMLAttributes<HTMLButtonElem
|
|
|
36
37
|
children: React.ReactNode;
|
|
37
38
|
/** Additional CSS classes */
|
|
38
39
|
className?: string;
|
|
40
|
+
'data-testid'?: string;
|
|
39
41
|
}
|
|
40
42
|
export declare const Dock: React.ForwardRefExoticComponent<DockProps & React.RefAttributes<HTMLDivElement>> & {
|
|
41
43
|
Item: React.ForwardRefExoticComponent<DockItemProps & React.RefAttributes<HTMLButtonElement>>;
|
package/dist/components/Dock.js
CHANGED
|
@@ -1,60 +1,84 @@
|
|
|
1
|
-
import { jsx as
|
|
2
|
-
import { forwardRef as
|
|
3
|
-
import { useConfig as
|
|
4
|
-
const
|
|
5
|
-
({ active:
|
|
6
|
-
const
|
|
7
|
-
return /* @__PURE__ */
|
|
1
|
+
import { jsx as c, jsxs as g } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef as D } from "react";
|
|
3
|
+
import { useConfig as h } from "../providers/ConfigProvider.js";
|
|
4
|
+
const j = "dock", z = "dock-xs", C = "dock-sm", y = "dock-md", S = "dock-lg", x = "dock-xl", f = "dock-active", L = "dock-label", u = D(
|
|
5
|
+
({ active: s, children: d, className: e = "", "data-testid": i, ...n }, r) => {
|
|
6
|
+
const a = [s && f, e].filter(Boolean).join(" ");
|
|
7
|
+
return /* @__PURE__ */ c(
|
|
8
8
|
"button",
|
|
9
9
|
{
|
|
10
|
-
ref:
|
|
11
|
-
className:
|
|
10
|
+
ref: r,
|
|
11
|
+
className: a || void 0,
|
|
12
12
|
type: "button",
|
|
13
|
-
"aria-pressed":
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
"aria-pressed": s,
|
|
14
|
+
"data-testid": i,
|
|
15
|
+
...n,
|
|
16
|
+
children: d
|
|
16
17
|
}
|
|
17
18
|
);
|
|
18
19
|
}
|
|
19
20
|
);
|
|
20
|
-
|
|
21
|
-
const
|
|
22
|
-
({ items:
|
|
23
|
-
const { componentSize:
|
|
24
|
-
xs:
|
|
25
|
-
sm:
|
|
26
|
-
md:
|
|
27
|
-
lg:
|
|
21
|
+
u.displayName = "Dock.Item";
|
|
22
|
+
const v = D(
|
|
23
|
+
({ items: s, size: d, activeIndex: e, onChange: i, children: n, className: r = "", "data-testid": a, ...t }, k) => {
|
|
24
|
+
const { componentSize: p } = h(), b = [j, {
|
|
25
|
+
xs: z,
|
|
26
|
+
sm: C,
|
|
27
|
+
md: y,
|
|
28
|
+
lg: S,
|
|
28
29
|
xl: x
|
|
29
|
-
}[
|
|
30
|
-
return
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
30
|
+
}[d ?? p ?? "md"], r].filter(Boolean).join(" "), N = (o) => a ? `${a}-${o}` : void 0;
|
|
31
|
+
return s ? /* @__PURE__ */ c(
|
|
32
|
+
"div",
|
|
33
|
+
{
|
|
34
|
+
ref: k,
|
|
35
|
+
className: b,
|
|
36
|
+
role: "toolbar",
|
|
37
|
+
"aria-label": t["aria-label"] || "Dock",
|
|
38
|
+
"data-testid": a,
|
|
39
|
+
...t,
|
|
40
|
+
children: s.map((o, l) => {
|
|
41
|
+
const m = e !== void 0 ? e === l : o.active;
|
|
42
|
+
return /* @__PURE__ */ g(
|
|
43
|
+
"button",
|
|
44
|
+
{
|
|
45
|
+
type: "button",
|
|
46
|
+
className: m ? f : void 0,
|
|
47
|
+
disabled: o.disabled,
|
|
48
|
+
"aria-pressed": m,
|
|
49
|
+
"aria-label": o.ariaLabel || o.label,
|
|
50
|
+
"data-testid": N(`item-${l}`),
|
|
51
|
+
onClick: () => {
|
|
52
|
+
o.onClick?.(), i?.(l);
|
|
53
|
+
},
|
|
54
|
+
children: [
|
|
55
|
+
/* @__PURE__ */ c("span", { "aria-hidden": "true", children: o.icon }),
|
|
56
|
+
o.label && /* @__PURE__ */ c("span", { className: L, children: o.label })
|
|
57
|
+
]
|
|
58
|
+
},
|
|
59
|
+
l
|
|
60
|
+
);
|
|
61
|
+
})
|
|
62
|
+
}
|
|
63
|
+
) : /* @__PURE__ */ c(
|
|
64
|
+
"div",
|
|
65
|
+
{
|
|
66
|
+
ref: k,
|
|
67
|
+
className: b,
|
|
68
|
+
role: "toolbar",
|
|
69
|
+
"aria-label": t["aria-label"] || "Dock",
|
|
70
|
+
"data-testid": a,
|
|
71
|
+
...t,
|
|
72
|
+
children: n
|
|
73
|
+
}
|
|
74
|
+
);
|
|
51
75
|
}
|
|
52
76
|
);
|
|
53
|
-
|
|
54
|
-
const
|
|
55
|
-
Item:
|
|
77
|
+
v.displayName = "Dock";
|
|
78
|
+
const w = Object.assign(v, {
|
|
79
|
+
Item: u
|
|
56
80
|
});
|
|
57
81
|
export {
|
|
58
|
-
|
|
82
|
+
w as Dock
|
|
59
83
|
};
|
|
60
84
|
//# sourceMappingURL=Dock.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Dock.js","sources":["../../src/components/Dock.tsx"],"sourcesContent":["import React, { forwardRef } from 'react'\nimport { useConfig } from '../providers/ConfigProvider'\n\n// DaisyUI classes\nconst dDock = 'dock'\nconst dDockXs = 'dock-xs'\nconst dDockSm = 'dock-sm'\nconst dDockMd = 'dock-md'\nconst dDockLg = 'dock-lg'\nconst dDockXl = 'dock-xl'\nconst dDockActive = 'dock-active'\nconst dDockLabel = 'dock-label'\n\nexport interface DockItemConfig {\n /** Icon element */\n icon: React.ReactNode\n /** Label text */\n label?: string\n /** Accessible label for screen readers (required if no label provided) */\n ariaLabel?: string\n /** Whether this item is active */\n active?: boolean\n /** Whether this item is disabled */\n disabled?: boolean\n /** Click handler for this item */\n onClick?: () => void\n}\n\nexport interface DockProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange'> {\n /** Dock items configuration */\n items?: DockItemConfig[]\n /** Size variant */\n size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'\n /** Controlled active index */\n activeIndex?: number\n /** Callback when an item is clicked */\n onChange?: (index: number) => void\n /** Children (alternative to items prop) */\n children?: React.ReactNode\n /** Additional CSS classes */\n className?: string\n /** Accessible label for the dock */\n 'aria-label'?: string\n}\n\nexport interface DockItemProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n /** Whether this item is active */\n active?: boolean\n /** Children (icon and optional label) */\n children: React.ReactNode\n /** Additional CSS classes */\n className?: string\n}\n\nconst DockItem = forwardRef<HTMLButtonElement, DockItemProps>(\n ({ active, children, className = '', ...props }, ref) => {\n const classes = [active && dDockActive, className].filter(Boolean).join(' ')\n\n return (\n <button\n ref={ref}\n className={classes || undefined}\n type=\"button\"\n aria-pressed={active}\n {...props}\n >\n {children}\n </button>\n )\n }\n)\n\nDockItem.displayName = 'Dock.Item'\n\nconst DockRoot = forwardRef<HTMLDivElement, DockProps>(\n ({ items, size, activeIndex, onChange, children, className = '', ...props }, ref) => {\n const { componentSize } = useConfig()\n const effectiveSize = size ?? componentSize ?? 'md'\n\n const sizeClasses = {\n xs: dDockXs,\n sm: dDockSm,\n md: dDockMd,\n lg: dDockLg,\n xl: dDockXl,\n }\n\n const classes = [dDock, sizeClasses[effectiveSize], className].filter(Boolean).join(' ')\n\n // If items array is provided, render from config\n if (items) {\n return (\n <div
|
|
1
|
+
{"version":3,"file":"Dock.js","sources":["../../src/components/Dock.tsx"],"sourcesContent":["import React, { forwardRef } from 'react'\nimport { useConfig } from '../providers/ConfigProvider'\n\n// DaisyUI classes\nconst dDock = 'dock'\nconst dDockXs = 'dock-xs'\nconst dDockSm = 'dock-sm'\nconst dDockMd = 'dock-md'\nconst dDockLg = 'dock-lg'\nconst dDockXl = 'dock-xl'\nconst dDockActive = 'dock-active'\nconst dDockLabel = 'dock-label'\n\nexport interface DockItemConfig {\n /** Icon element */\n icon: React.ReactNode\n /** Label text */\n label?: string\n /** Accessible label for screen readers (required if no label provided) */\n ariaLabel?: string\n /** Whether this item is active */\n active?: boolean\n /** Whether this item is disabled */\n disabled?: boolean\n /** Click handler for this item */\n onClick?: () => void\n}\n\nexport interface DockProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange'> {\n /** Dock items configuration */\n items?: DockItemConfig[]\n /** Size variant */\n size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'\n /** Controlled active index */\n activeIndex?: number\n /** Callback when an item is clicked */\n onChange?: (index: number) => void\n /** Children (alternative to items prop) */\n children?: React.ReactNode\n /** Additional CSS classes */\n className?: string\n /** Accessible label for the dock */\n 'aria-label'?: string\n 'data-testid'?: string\n}\n\nexport interface DockItemProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n /** Whether this item is active */\n active?: boolean\n /** Children (icon and optional label) */\n children: React.ReactNode\n /** Additional CSS classes */\n className?: string\n 'data-testid'?: string\n}\n\nconst DockItem = forwardRef<HTMLButtonElement, DockItemProps>(\n ({ active, children, className = '', 'data-testid': testId, ...props }, ref) => {\n const classes = [active && dDockActive, className].filter(Boolean).join(' ')\n\n return (\n <button\n ref={ref}\n className={classes || undefined}\n type=\"button\"\n aria-pressed={active}\n data-testid={testId}\n {...props}\n >\n {children}\n </button>\n )\n }\n)\n\nDockItem.displayName = 'Dock.Item'\n\nconst DockRoot = forwardRef<HTMLDivElement, DockProps>(\n ({ items, size, activeIndex, onChange, children, className = '', 'data-testid': testId, ...props }, ref) => {\n const { componentSize } = useConfig()\n const effectiveSize = size ?? componentSize ?? 'md'\n\n const sizeClasses = {\n xs: dDockXs,\n sm: dDockSm,\n md: dDockMd,\n lg: dDockLg,\n xl: dDockXl,\n }\n\n const classes = [dDock, sizeClasses[effectiveSize], className].filter(Boolean).join(' ')\n const getTestId = (suffix: string) => (testId ? `${testId}-${suffix}` : undefined)\n\n // If items array is provided, render from config\n if (items) {\n return (\n <div\n ref={ref}\n className={classes}\n role=\"toolbar\"\n aria-label={props['aria-label'] || 'Dock'}\n data-testid={testId}\n {...props}\n >\n {items.map((item, index) => {\n const isActive = activeIndex !== undefined ? activeIndex === index : item.active\n\n return (\n <button\n key={index}\n type=\"button\"\n className={isActive ? dDockActive : undefined}\n disabled={item.disabled}\n aria-pressed={isActive}\n aria-label={item.ariaLabel || item.label}\n data-testid={getTestId(`item-${index}`)}\n onClick={() => {\n item.onClick?.()\n onChange?.(index)\n }}\n >\n <span aria-hidden=\"true\">{item.icon}</span>\n {item.label && <span className={dDockLabel}>{item.label}</span>}\n </button>\n )\n })}\n </div>\n )\n }\n\n // Otherwise render children\n return (\n <div\n ref={ref}\n className={classes}\n role=\"toolbar\"\n aria-label={props['aria-label'] || 'Dock'}\n data-testid={testId}\n {...props}\n >\n {children}\n </div>\n )\n }\n)\n\nDockRoot.displayName = 'Dock'\n\nexport const Dock = Object.assign(DockRoot, {\n Item: DockItem,\n})\n"],"names":["dDock","dDockXs","dDockSm","dDockMd","dDockLg","dDockXl","dDockActive","dDockLabel","DockItem","forwardRef","active","children","className","testId","props","ref","classes","jsx","DockRoot","items","size","activeIndex","onChange","componentSize","useConfig","getTestId","suffix","item","index","isActive","jsxs","Dock"],"mappings":";;;AAIA,MAAMA,IAAQ,QACRC,IAAU,WACVC,IAAU,WACVC,IAAU,WACVC,IAAU,WACVC,IAAU,WACVC,IAAc,eACdC,IAAa,cA6CbC,IAAWC;AAAA,EACf,CAAC,EAAE,QAAAC,GAAQ,UAAAC,GAAU,WAAAC,IAAY,IAAI,eAAeC,GAAQ,GAAGC,EAAA,GAASC,MAAQ;AAC9E,UAAMC,IAAU,CAACN,KAAUJ,GAAaM,CAAS,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG;AAE3E,WACE,gBAAAK;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAAF;AAAA,QACA,WAAWC,KAAW;AAAA,QACtB,MAAK;AAAA,QACL,gBAAcN;AAAA,QACd,eAAaG;AAAA,QACZ,GAAGC;AAAA,QAEH,UAAAH;AAAA,MAAA;AAAA,IAAA;AAAA,EAGP;AACF;AAEAH,EAAS,cAAc;AAEvB,MAAMU,IAAWT;AAAA,EACf,CAAC,EAAE,OAAAU,GAAO,MAAAC,GAAM,aAAAC,GAAa,UAAAC,GAAU,UAAAX,GAAU,WAAAC,IAAY,IAAI,eAAeC,GAAQ,GAAGC,EAAA,GAASC,MAAQ;AAC1G,UAAM,EAAE,eAAAQ,EAAA,IAAkBC,EAAA,GAWpBR,IAAU,CAAChB,GARG;AAAA,MAClB,IAAIC;AAAA,MACJ,IAAIC;AAAA,MACJ,IAAIC;AAAA,MACJ,IAAIC;AAAA,MACJ,IAAIC;AAAA,IAAA,EAPgBe,KAAQG,KAAiB,IAUE,GAAGX,CAAS,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG,GACjFa,IAAY,CAACC,MAAoBb,IAAS,GAAGA,CAAM,IAAIa,CAAM,KAAK;AAGxE,WAAIP,IAEA,gBAAAF;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAAF;AAAA,QACA,WAAWC;AAAA,QACX,MAAK;AAAA,QACL,cAAYF,EAAM,YAAY,KAAK;AAAA,QACnC,eAAaD;AAAA,QACZ,GAAGC;AAAA,QAEH,UAAAK,EAAM,IAAI,CAACQ,GAAMC,MAAU;AAC1B,gBAAMC,IAAWR,MAAgB,SAAYA,MAAgBO,IAAQD,EAAK;AAE1E,iBACE,gBAAAG;AAAA,YAAC;AAAA,YAAA;AAAA,cAEC,MAAK;AAAA,cACL,WAAWD,IAAWvB,IAAc;AAAA,cACpC,UAAUqB,EAAK;AAAA,cACf,gBAAcE;AAAA,cACd,cAAYF,EAAK,aAAaA,EAAK;AAAA,cACnC,eAAaF,EAAU,QAAQG,CAAK,EAAE;AAAA,cACtC,SAAS,MAAM;AACb,gBAAAD,EAAK,UAAA,GACLL,IAAWM,CAAK;AAAA,cAClB;AAAA,cAEA,UAAA;AAAA,gBAAA,gBAAAX,EAAC,QAAA,EAAK,eAAY,QAAQ,UAAAU,EAAK,MAAK;AAAA,gBACnCA,EAAK,SAAS,gBAAAV,EAAC,UAAK,WAAWV,GAAa,YAAK,MAAA,CAAM;AAAA,cAAA;AAAA,YAAA;AAAA,YAbnDqB;AAAA,UAAA;AAAA,QAgBX,CAAC;AAAA,MAAA;AAAA,IAAA,IAOL,gBAAAX;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAAF;AAAA,QACA,WAAWC;AAAA,QACX,MAAK;AAAA,QACL,cAAYF,EAAM,YAAY,KAAK;AAAA,QACnC,eAAaD;AAAA,QACZ,GAAGC;AAAA,QAEH,UAAAH;AAAA,MAAA;AAAA,IAAA;AAAA,EAGP;AACF;AAEAO,EAAS,cAAc;AAEhB,MAAMa,IAAO,OAAO,OAAOb,GAAU;AAAA,EAC1C,MAAMV;AACR,CAAC;"}
|
|
@@ -5,5 +5,6 @@ export interface FileInputProps extends Omit<React.InputHTMLAttributes<HTMLInput
|
|
|
5
5
|
ghost?: boolean;
|
|
6
6
|
bordered?: boolean;
|
|
7
7
|
className?: string;
|
|
8
|
+
'data-testid'?: string;
|
|
8
9
|
}
|
|
9
10
|
export declare const FileInput: React.ForwardRefExoticComponent<FileInputProps & React.RefAttributes<HTMLInputElement>>;
|
|
@@ -1,38 +1,38 @@
|
|
|
1
|
-
import { jsx as
|
|
2
|
-
import { forwardRef as
|
|
3
|
-
import { useConfig as
|
|
4
|
-
const
|
|
5
|
-
({ size: i, color:
|
|
6
|
-
const { componentSize:
|
|
7
|
-
xs:
|
|
8
|
-
sm:
|
|
9
|
-
md:
|
|
10
|
-
lg:
|
|
11
|
-
xl:
|
|
12
|
-
},
|
|
13
|
-
neutral:
|
|
14
|
-
primary:
|
|
15
|
-
secondary:
|
|
16
|
-
accent:
|
|
17
|
-
info:
|
|
18
|
-
success:
|
|
19
|
-
warning:
|
|
20
|
-
error:
|
|
21
|
-
},
|
|
22
|
-
|
|
1
|
+
import { jsx as I } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef as m } from "react";
|
|
3
|
+
import { useConfig as F } from "../providers/ConfigProvider.js";
|
|
4
|
+
const g = "file-input", y = "file-input-xs", x = "file-input-sm", S = "file-input-md", w = "file-input-lg", C = "file-input-xl", z = "file-input-neutral", N = "file-input-primary", h = "file-input-secondary", j = "file-input-accent", X = "file-input-info", v = "file-input-success", A = "file-input-warning", B = "file-input-error", e = "file-input-ghost", E = m(
|
|
5
|
+
({ size: i, color: t, ghost: s = !1, bordered: l = !0, className: o = "", "data-testid": u, ...p }, c) => {
|
|
6
|
+
const { componentSize: r } = F(), n = i ?? r ?? "md", f = {
|
|
7
|
+
xs: y,
|
|
8
|
+
sm: x,
|
|
9
|
+
md: S,
|
|
10
|
+
lg: w,
|
|
11
|
+
xl: C
|
|
12
|
+
}, a = {
|
|
13
|
+
neutral: z,
|
|
14
|
+
primary: N,
|
|
15
|
+
secondary: h,
|
|
16
|
+
accent: j,
|
|
17
|
+
info: X,
|
|
18
|
+
success: v,
|
|
19
|
+
warning: A,
|
|
20
|
+
error: B
|
|
21
|
+
}, d = [
|
|
22
|
+
g,
|
|
23
23
|
"w-full",
|
|
24
24
|
// In DaisyUI 5, borders are on by default. Use ghost to remove them.
|
|
25
25
|
!l && e,
|
|
26
26
|
s && e,
|
|
27
|
-
t && r[t],
|
|
28
27
|
n && f[n],
|
|
28
|
+
t && a[t],
|
|
29
29
|
o
|
|
30
30
|
].filter(Boolean).join(" ");
|
|
31
|
-
return /* @__PURE__ */
|
|
31
|
+
return /* @__PURE__ */ I("input", { ref: c, type: "file", className: d, "data-testid": u, ...p });
|
|
32
32
|
}
|
|
33
33
|
);
|
|
34
|
-
|
|
34
|
+
E.displayName = "FileInput";
|
|
35
35
|
export {
|
|
36
|
-
|
|
36
|
+
E as FileInput
|
|
37
37
|
};
|
|
38
38
|
//# sourceMappingURL=FileInput.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FileInput.js","sources":["../../src/components/FileInput.tsx"],"sourcesContent":["import React, { forwardRef } from 'react'\nimport { useConfig } from '../providers/ConfigProvider'\n\n// DaisyUI classes\nconst dFileInput = 'file-input'\nconst dFileInputXs = 'file-input-xs'\nconst dFileInputSm = 'file-input-sm'\nconst dFileInputMd = 'file-input-md'\nconst dFileInputLg = 'file-input-lg'\nconst dFileInputXl = 'file-input-xl'\nconst dFileInputNeutral = 'file-input-neutral'\nconst dFileInputPrimary = 'file-input-primary'\nconst dFileInputSecondary = 'file-input-secondary'\nconst dFileInputAccent = 'file-input-accent'\nconst dFileInputInfo = 'file-input-info'\nconst dFileInputSuccess = 'file-input-success'\nconst dFileInputWarning = 'file-input-warning'\nconst dFileInputError = 'file-input-error'\nconst dFileInputGhost = 'file-input-ghost'\n\nexport interface FileInputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'size' | 'type'> {\n size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'\n color?: 'neutral' | 'primary' | 'secondary' | 'accent' | 'info' | 'success' | 'warning' | 'error'\n ghost?: boolean\n bordered?: boolean\n className?: string\n}\n\nexport const FileInput = forwardRef<HTMLInputElement, FileInputProps>(\n ({ size, color, ghost = false, bordered = true, className = '', ...props }, ref) => {\n const { componentSize } = useConfig()\n const effectiveSize = size ?? componentSize ?? 'md'\n\n const sizeClasses = {\n xs: dFileInputXs,\n sm: dFileInputSm,\n md: dFileInputMd,\n lg: dFileInputLg,\n xl: dFileInputXl,\n }\n\n const colorClasses = {\n neutral: dFileInputNeutral,\n primary: dFileInputPrimary,\n secondary: dFileInputSecondary,\n accent: dFileInputAccent,\n info: dFileInputInfo,\n success: dFileInputSuccess,\n warning: dFileInputWarning,\n error: dFileInputError,\n }\n\n const fileInputClasses = [\n dFileInput,\n 'w-full',\n // In DaisyUI 5, borders are on by default. Use ghost to remove them.\n !bordered && dFileInputGhost,\n ghost && dFileInputGhost,\n effectiveSize && sizeClasses[effectiveSize],\n color && colorClasses[color],\n className,\n ]\n .filter(Boolean)\n .join(' ')\n\n return <input ref={ref} type=\"file\" className={fileInputClasses} {...props} />\n }\n)\n\nFileInput.displayName = 'FileInput'\n"],"names":["dFileInput","dFileInputXs","dFileInputSm","dFileInputMd","dFileInputLg","dFileInputXl","dFileInputNeutral","dFileInputPrimary","dFileInputSecondary","dFileInputAccent","dFileInputInfo","dFileInputSuccess","dFileInputWarning","dFileInputError","dFileInputGhost","FileInput","forwardRef","size","color","ghost","bordered","className","props","ref","componentSize","useConfig","effectiveSize","sizeClasses","colorClasses","fileInputClasses","jsx"],"mappings":";;;AAIA,MAAMA,IAAa,cACbC,IAAe,iBACfC,IAAe,iBACfC,IAAe,iBACfC,IAAe,iBACfC,IAAe,iBACfC,IAAoB,sBACpBC,IAAoB,sBACpBC,IAAsB,wBACtBC,IAAmB,qBACnBC,IAAiB,mBACjBC,IAAoB,sBACpBC,IAAoB,sBACpBC,IAAkB,oBAClBC,IAAkB,
|
|
1
|
+
{"version":3,"file":"FileInput.js","sources":["../../src/components/FileInput.tsx"],"sourcesContent":["import React, { forwardRef } from 'react'\nimport { useConfig } from '../providers/ConfigProvider'\n\n// DaisyUI classes\nconst dFileInput = 'file-input'\nconst dFileInputXs = 'file-input-xs'\nconst dFileInputSm = 'file-input-sm'\nconst dFileInputMd = 'file-input-md'\nconst dFileInputLg = 'file-input-lg'\nconst dFileInputXl = 'file-input-xl'\nconst dFileInputNeutral = 'file-input-neutral'\nconst dFileInputPrimary = 'file-input-primary'\nconst dFileInputSecondary = 'file-input-secondary'\nconst dFileInputAccent = 'file-input-accent'\nconst dFileInputInfo = 'file-input-info'\nconst dFileInputSuccess = 'file-input-success'\nconst dFileInputWarning = 'file-input-warning'\nconst dFileInputError = 'file-input-error'\nconst dFileInputGhost = 'file-input-ghost'\n\nexport interface FileInputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'size' | 'type'> {\n size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'\n color?: 'neutral' | 'primary' | 'secondary' | 'accent' | 'info' | 'success' | 'warning' | 'error'\n ghost?: boolean\n bordered?: boolean\n className?: string\n 'data-testid'?: string\n}\n\nexport const FileInput = forwardRef<HTMLInputElement, FileInputProps>(\n ({ size, color, ghost = false, bordered = true, className = '', 'data-testid': testId, ...props }, ref) => {\n const { componentSize } = useConfig()\n const effectiveSize = size ?? componentSize ?? 'md'\n\n const sizeClasses = {\n xs: dFileInputXs,\n sm: dFileInputSm,\n md: dFileInputMd,\n lg: dFileInputLg,\n xl: dFileInputXl,\n }\n\n const colorClasses = {\n neutral: dFileInputNeutral,\n primary: dFileInputPrimary,\n secondary: dFileInputSecondary,\n accent: dFileInputAccent,\n info: dFileInputInfo,\n success: dFileInputSuccess,\n warning: dFileInputWarning,\n error: dFileInputError,\n }\n\n const fileInputClasses = [\n dFileInput,\n 'w-full',\n // In DaisyUI 5, borders are on by default. Use ghost to remove them.\n !bordered && dFileInputGhost,\n ghost && dFileInputGhost,\n effectiveSize && sizeClasses[effectiveSize],\n color && colorClasses[color],\n className,\n ]\n .filter(Boolean)\n .join(' ')\n\n return <input ref={ref} type=\"file\" className={fileInputClasses} data-testid={testId} {...props} />\n }\n)\n\nFileInput.displayName = 'FileInput'\n"],"names":["dFileInput","dFileInputXs","dFileInputSm","dFileInputMd","dFileInputLg","dFileInputXl","dFileInputNeutral","dFileInputPrimary","dFileInputSecondary","dFileInputAccent","dFileInputInfo","dFileInputSuccess","dFileInputWarning","dFileInputError","dFileInputGhost","FileInput","forwardRef","size","color","ghost","bordered","className","testId","props","ref","componentSize","useConfig","effectiveSize","sizeClasses","colorClasses","fileInputClasses","jsx"],"mappings":";;;AAIA,MAAMA,IAAa,cACbC,IAAe,iBACfC,IAAe,iBACfC,IAAe,iBACfC,IAAe,iBACfC,IAAe,iBACfC,IAAoB,sBACpBC,IAAoB,sBACpBC,IAAsB,wBACtBC,IAAmB,qBACnBC,IAAiB,mBACjBC,IAAoB,sBACpBC,IAAoB,sBACpBC,IAAkB,oBAClBC,IAAkB,oBAWXC,IAAYC;AAAA,EACvB,CAAC,EAAE,MAAAC,GAAM,OAAAC,GAAO,OAAAC,IAAQ,IAAO,UAAAC,IAAW,IAAM,WAAAC,IAAY,IAAI,eAAeC,GAAQ,GAAGC,EAAA,GAASC,MAAQ;AACzG,UAAM,EAAE,eAAAC,EAAA,IAAkBC,EAAA,GACpBC,IAAgBV,KAAQQ,KAAiB,MAEzCG,IAAc;AAAA,MAClB,IAAI3B;AAAA,MACJ,IAAIC;AAAA,MACJ,IAAIC;AAAA,MACJ,IAAIC;AAAA,MACJ,IAAIC;AAAA,IAAA,GAGAwB,IAAe;AAAA,MACnB,SAASvB;AAAA,MACT,SAASC;AAAA,MACT,WAAWC;AAAA,MACX,QAAQC;AAAA,MACR,MAAMC;AAAA,MACN,SAASC;AAAA,MACT,SAASC;AAAA,MACT,OAAOC;AAAA,IAAA,GAGHiB,IAAmB;AAAA,MACvB9B;AAAA,MACA;AAAA;AAAA,MAEA,CAACoB,KAAYN;AAAA,MACbK,KAASL;AAAA,MACTa,KAAiBC,EAAYD,CAAa;AAAA,MAC1CT,KAASW,EAAaX,CAAK;AAAA,MAC3BG;AAAA,IAAA,EAEC,OAAO,OAAO,EACd,KAAK,GAAG;AAEX,WAAO,gBAAAU,EAAC,SAAA,EAAM,KAAAP,GAAU,MAAK,QAAO,WAAWM,GAAkB,eAAaR,GAAS,GAAGC,EAAA,CAAO;AAAA,EACnG;AACF;AAEAR,EAAU,cAAc;"}
|
|
@@ -1,57 +1,60 @@
|
|
|
1
|
-
import { jsxs as
|
|
2
|
-
import { useId as
|
|
3
|
-
import { useConfig as
|
|
4
|
-
const
|
|
5
|
-
xs:
|
|
6
|
-
sm:
|
|
1
|
+
import { jsxs as R, jsx as d } from "react/jsx-runtime";
|
|
2
|
+
import { useId as q, useState as F } from "react";
|
|
3
|
+
import { useConfig as I } from "../providers/ConfigProvider.js";
|
|
4
|
+
const V = "filter", c = "btn", X = "btn-xs", k = "btn-sm", O = "btn-lg", T = "btn-xl", A = "btn-square", m = {
|
|
5
|
+
xs: X,
|
|
6
|
+
sm: k,
|
|
7
7
|
md: "",
|
|
8
|
-
lg:
|
|
9
|
-
xl:
|
|
10
|
-
},
|
|
11
|
-
options:
|
|
12
|
-
value:
|
|
13
|
-
defaultValue:
|
|
14
|
-
onChange:
|
|
15
|
-
name:
|
|
16
|
-
size:
|
|
17
|
-
showReset:
|
|
18
|
-
resetLabel:
|
|
19
|
-
className:
|
|
8
|
+
lg: O,
|
|
9
|
+
xl: T
|
|
10
|
+
}, H = ({
|
|
11
|
+
options: u,
|
|
12
|
+
value: e,
|
|
13
|
+
defaultValue: f,
|
|
14
|
+
onChange: n,
|
|
15
|
+
name: v,
|
|
16
|
+
size: b,
|
|
17
|
+
showReset: g = !0,
|
|
18
|
+
resetLabel: a = "×",
|
|
19
|
+
className: B = "",
|
|
20
|
+
"data-testid": s
|
|
20
21
|
}) => {
|
|
21
|
-
const { componentSize:
|
|
22
|
-
(
|
|
23
|
-
),
|
|
24
|
-
|
|
25
|
-
},
|
|
26
|
-
|
|
27
|
-
},
|
|
28
|
-
return /* @__PURE__ */
|
|
29
|
-
|
|
22
|
+
const { componentSize: p } = I(), l = b ?? p ?? "md", x = q(), C = v || `filter-${x}`, [$, o] = F(f), h = e !== void 0 ? e : $, i = e !== void 0, S = u.map(
|
|
23
|
+
(t) => typeof t == "string" ? { label: t, value: t } : t
|
|
24
|
+
), j = (t) => {
|
|
25
|
+
i || o(t), n?.(t);
|
|
26
|
+
}, y = () => {
|
|
27
|
+
i || o(void 0), n?.(void 0);
|
|
28
|
+
}, z = [c, m[l]].filter(Boolean).join(" "), N = [c, A, m[l]].filter(Boolean).join(" "), r = (t) => s ? `${s}-${t}` : void 0;
|
|
29
|
+
return /* @__PURE__ */ R("form", { className: `${V} ${B}`.trim(), onReset: y, "data-testid": s, children: [
|
|
30
|
+
g && /* @__PURE__ */ d(
|
|
30
31
|
"input",
|
|
31
32
|
{
|
|
32
|
-
className:
|
|
33
|
+
className: N,
|
|
33
34
|
type: "reset",
|
|
34
|
-
value: typeof
|
|
35
|
-
"aria-label": "Reset filter"
|
|
35
|
+
value: typeof a == "string" ? a : void 0,
|
|
36
|
+
"aria-label": "Reset filter",
|
|
37
|
+
"data-testid": r("reset")
|
|
36
38
|
}
|
|
37
39
|
),
|
|
38
|
-
|
|
40
|
+
S.map((t) => /* @__PURE__ */ d(
|
|
39
41
|
"input",
|
|
40
42
|
{
|
|
41
|
-
className:
|
|
43
|
+
className: z,
|
|
42
44
|
type: "radio",
|
|
43
|
-
name:
|
|
44
|
-
value:
|
|
45
|
-
"aria-label":
|
|
46
|
-
checked:
|
|
47
|
-
onChange: () =>
|
|
48
|
-
disabled:
|
|
45
|
+
name: C,
|
|
46
|
+
value: t.value,
|
|
47
|
+
"aria-label": t.label,
|
|
48
|
+
checked: h === t.value,
|
|
49
|
+
onChange: () => j(t.value),
|
|
50
|
+
disabled: t.disabled,
|
|
51
|
+
"data-testid": r(`option-${t.value}`)
|
|
49
52
|
},
|
|
50
|
-
|
|
53
|
+
t.value
|
|
51
54
|
))
|
|
52
55
|
] });
|
|
53
56
|
};
|
|
54
57
|
export {
|
|
55
|
-
|
|
58
|
+
H as Filter
|
|
56
59
|
};
|
|
57
60
|
//# sourceMappingURL=Filter.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Filter.js","sources":["../../src/components/Filter.tsx"],"sourcesContent":["import React, { useState, useId } from 'react'\nimport { useConfig } from '../providers/ConfigProvider'\n\n// DaisyUI classes\nconst dFilter = 'filter'\nconst dBtn = 'btn'\nconst dBtnXs = 'btn-xs'\nconst dBtnSm = 'btn-sm'\nconst dBtnLg = 'btn-lg'\nconst dBtnXl = 'btn-xl'\nconst dBtnSquare = 'btn-square'\n\nexport interface FilterOption {\n label: string\n value: string\n disabled?: boolean\n}\n\nexport interface FilterProps {\n /** Filter options */\n options: (string | FilterOption)[]\n /** Controlled value */\n value?: string\n /** Default value for uncontrolled mode */\n defaultValue?: string\n /** Change handler */\n onChange?: (value: string | undefined) => void\n /** Radio group name (auto-generated if not provided) */\n name?: string\n /** Button size */\n size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'\n /** Show reset button */\n showReset?: boolean\n /** Reset button label */\n resetLabel?: React.ReactNode\n /** Additional CSS classes for container */\n className?: string\n}\n\nconst sizeClasses: Record<string, string> = {\n xs: dBtnXs,\n sm: dBtnSm,\n md: '',\n lg: dBtnLg,\n xl: dBtnXl,\n}\n\nexport const Filter: React.FC<FilterProps> = ({\n options,\n value,\n defaultValue,\n onChange,\n name,\n size,\n showReset = true,\n resetLabel = '×',\n className = '',\n}) => {\n const { componentSize } = useConfig()\n const effectiveSize = size ?? componentSize ?? 'md'\n\n const autoId = useId()\n const groupName = name || `filter-${autoId}`\n\n const [internalValue, setInternalValue] = useState<string | undefined>(defaultValue)\n const currentValue = value !== undefined ? value : internalValue\n const isControlled = value !== undefined\n\n const normalizedOptions: FilterOption[] = options.map((opt) =>\n typeof opt === 'string' ? { label: opt, value: opt } : opt\n )\n\n const handleChange = (newValue: string) => {\n if (!isControlled) {\n setInternalValue(newValue)\n }\n onChange?.(newValue)\n }\n\n const handleReset = () => {\n if (!isControlled) {\n setInternalValue(undefined)\n }\n onChange?.(undefined)\n }\n\n const buttonClasses = [dBtn, sizeClasses[effectiveSize]].filter(Boolean).join(' ')\n const resetClasses = [dBtn, dBtnSquare, sizeClasses[effectiveSize]].filter(Boolean).join(' ')\n\n return (\n <form className={`${dFilter} ${className}`.trim()} onReset={handleReset}>\n {showReset && (\n <input\n className={resetClasses}\n type=\"reset\"\n value={typeof resetLabel === 'string' ? resetLabel : undefined}\n aria-label=\"Reset filter\"\n />\n )}\n {normalizedOptions.map((option) => (\n <input\n key={option.value}\n className={buttonClasses}\n type=\"radio\"\n name={groupName}\n value={option.value}\n aria-label={option.label}\n checked={currentValue === option.value}\n onChange={() => handleChange(option.value)}\n disabled={option.disabled}\n />\n ))}\n </form>\n )\n}\n"],"names":["dFilter","dBtn","dBtnXs","dBtnSm","dBtnLg","dBtnXl","dBtnSquare","sizeClasses","Filter","options","value","defaultValue","onChange","name","size","showReset","resetLabel","className","componentSize","useConfig","effectiveSize","autoId","useId","groupName","internalValue","setInternalValue","useState","currentValue","isControlled","normalizedOptions","opt","handleChange","newValue","handleReset","buttonClasses","resetClasses","jsxs","jsx","option"],"mappings":";;;AAIA,MAAMA,IAAU,UACVC,IAAO,OACPC,IAAS,UACTC,IAAS,UACTC,IAAS,UACTC,IAAS,UACTC,IAAa,
|
|
1
|
+
{"version":3,"file":"Filter.js","sources":["../../src/components/Filter.tsx"],"sourcesContent":["import React, { useState, useId } from 'react'\nimport { useConfig } from '../providers/ConfigProvider'\n\n// DaisyUI classes\nconst dFilter = 'filter'\nconst dBtn = 'btn'\nconst dBtnXs = 'btn-xs'\nconst dBtnSm = 'btn-sm'\nconst dBtnLg = 'btn-lg'\nconst dBtnXl = 'btn-xl'\nconst dBtnSquare = 'btn-square'\n\nexport interface FilterOption {\n label: string\n value: string\n disabled?: boolean\n}\n\nexport interface FilterProps {\n /** Filter options */\n options: (string | FilterOption)[]\n /** Controlled value */\n value?: string\n /** Default value for uncontrolled mode */\n defaultValue?: string\n /** Change handler */\n onChange?: (value: string | undefined) => void\n /** Radio group name (auto-generated if not provided) */\n name?: string\n /** Button size */\n size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'\n /** Show reset button */\n showReset?: boolean\n /** Reset button label */\n resetLabel?: React.ReactNode\n /** Additional CSS classes for container */\n className?: string\n 'data-testid'?: string\n}\n\nconst sizeClasses: Record<string, string> = {\n xs: dBtnXs,\n sm: dBtnSm,\n md: '',\n lg: dBtnLg,\n xl: dBtnXl,\n}\n\nexport const Filter: React.FC<FilterProps> = ({\n options,\n value,\n defaultValue,\n onChange,\n name,\n size,\n showReset = true,\n resetLabel = '×',\n className = '',\n 'data-testid': testId,\n}) => {\n const { componentSize } = useConfig()\n const effectiveSize = size ?? componentSize ?? 'md'\n\n const autoId = useId()\n const groupName = name || `filter-${autoId}`\n\n const [internalValue, setInternalValue] = useState<string | undefined>(defaultValue)\n const currentValue = value !== undefined ? value : internalValue\n const isControlled = value !== undefined\n\n const normalizedOptions: FilterOption[] = options.map((opt) =>\n typeof opt === 'string' ? { label: opt, value: opt } : opt\n )\n\n const handleChange = (newValue: string) => {\n if (!isControlled) {\n setInternalValue(newValue)\n }\n onChange?.(newValue)\n }\n\n const handleReset = () => {\n if (!isControlled) {\n setInternalValue(undefined)\n }\n onChange?.(undefined)\n }\n\n const buttonClasses = [dBtn, sizeClasses[effectiveSize]].filter(Boolean).join(' ')\n const resetClasses = [dBtn, dBtnSquare, sizeClasses[effectiveSize]].filter(Boolean).join(' ')\n const getTestId = (suffix: string) => (testId ? `${testId}-${suffix}` : undefined)\n\n return (\n <form className={`${dFilter} ${className}`.trim()} onReset={handleReset} data-testid={testId}>\n {showReset && (\n <input\n className={resetClasses}\n type=\"reset\"\n value={typeof resetLabel === 'string' ? resetLabel : undefined}\n aria-label=\"Reset filter\"\n data-testid={getTestId('reset')}\n />\n )}\n {normalizedOptions.map((option) => (\n <input\n key={option.value}\n className={buttonClasses}\n type=\"radio\"\n name={groupName}\n value={option.value}\n aria-label={option.label}\n checked={currentValue === option.value}\n onChange={() => handleChange(option.value)}\n disabled={option.disabled}\n data-testid={getTestId(`option-${option.value}`)}\n />\n ))}\n </form>\n )\n}\n"],"names":["dFilter","dBtn","dBtnXs","dBtnSm","dBtnLg","dBtnXl","dBtnSquare","sizeClasses","Filter","options","value","defaultValue","onChange","name","size","showReset","resetLabel","className","testId","componentSize","useConfig","effectiveSize","autoId","useId","groupName","internalValue","setInternalValue","useState","currentValue","isControlled","normalizedOptions","opt","handleChange","newValue","handleReset","buttonClasses","resetClasses","getTestId","suffix","jsxs","jsx","option"],"mappings":";;;AAIA,MAAMA,IAAU,UACVC,IAAO,OACPC,IAAS,UACTC,IAAS,UACTC,IAAS,UACTC,IAAS,UACTC,IAAa,cA8BbC,IAAsC;AAAA,EAC1C,IAAIL;AAAA,EACJ,IAAIC;AAAA,EACJ,IAAI;AAAA,EACJ,IAAIC;AAAA,EACJ,IAAIC;AACN,GAEaG,IAAgC,CAAC;AAAA,EAC5C,SAAAC;AAAA,EACA,OAAAC;AAAA,EACA,cAAAC;AAAA,EACA,UAAAC;AAAA,EACA,MAAAC;AAAA,EACA,MAAAC;AAAA,EACA,WAAAC,IAAY;AAAA,EACZ,YAAAC,IAAa;AAAA,EACb,WAAAC,IAAY;AAAA,EACZ,eAAeC;AACjB,MAAM;AACJ,QAAM,EAAE,eAAAC,EAAA,IAAkBC,EAAA,GACpBC,IAAgBP,KAAQK,KAAiB,MAEzCG,IAASC,EAAA,GACTC,IAAYX,KAAQ,UAAUS,CAAM,IAEpC,CAACG,GAAeC,CAAgB,IAAIC,EAA6BhB,CAAY,GAC7EiB,IAAelB,MAAU,SAAYA,IAAQe,GAC7CI,IAAenB,MAAU,QAEzBoB,IAAoCrB,EAAQ;AAAA,IAAI,CAACsB,MACrD,OAAOA,KAAQ,WAAW,EAAE,OAAOA,GAAK,OAAOA,MAAQA;AAAA,EAAA,GAGnDC,IAAe,CAACC,MAAqB;AACzC,IAAKJ,KACHH,EAAiBO,CAAQ,GAE3BrB,IAAWqB,CAAQ;AAAA,EACrB,GAEMC,IAAc,MAAM;AACxB,IAAKL,KACHH,EAAiB,MAAS,GAE5Bd,IAAW,MAAS;AAAA,EACtB,GAEMuB,IAAgB,CAAClC,GAAMM,EAAYc,CAAa,CAAC,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG,GAC3Ee,IAAe,CAACnC,GAAMK,GAAYC,EAAYc,CAAa,CAAC,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG,GACtFgB,IAAY,CAACC,MAAoBpB,IAAS,GAAGA,CAAM,IAAIoB,CAAM,KAAK;AAExE,SACE,gBAAAC,EAAC,QAAA,EAAK,WAAW,GAAGvC,CAAO,IAAIiB,CAAS,GAAG,KAAA,GAAQ,SAASiB,GAAa,eAAahB,GACnF,UAAA;AAAA,IAAAH,KACC,gBAAAyB;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAWJ;AAAA,QACX,MAAK;AAAA,QACL,OAAO,OAAOpB,KAAe,WAAWA,IAAa;AAAA,QACrD,cAAW;AAAA,QACX,eAAaqB,EAAU,OAAO;AAAA,MAAA;AAAA,IAAA;AAAA,IAGjCP,EAAkB,IAAI,CAACW,MACtB,gBAAAD;AAAA,MAAC;AAAA,MAAA;AAAA,QAEC,WAAWL;AAAA,QACX,MAAK;AAAA,QACL,MAAMX;AAAA,QACN,OAAOiB,EAAO;AAAA,QACd,cAAYA,EAAO;AAAA,QACnB,SAASb,MAAiBa,EAAO;AAAA,QACjC,UAAU,MAAMT,EAAaS,EAAO,KAAK;AAAA,QACzC,UAAUA,EAAO;AAAA,QACjB,eAAaJ,EAAU,UAAUI,EAAO,KAAK,EAAE;AAAA,MAAA;AAAA,MAT1CA,EAAO;AAAA,IAAA,CAWf;AAAA,EAAA,GACH;AAEJ;"}
|
|
@@ -10,5 +10,6 @@ export interface FlexProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
|
10
10
|
minHeight?: 'screen' | 'full' | 'fit' | 'min' | 'max';
|
|
11
11
|
minWidth?: 'full' | 'fit' | 'min' | 'max';
|
|
12
12
|
children?: React.ReactNode;
|
|
13
|
+
'data-testid'?: string;
|
|
13
14
|
}
|
|
14
15
|
export declare const Flex: React.FC<FlexProps>;
|