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":"Autocomplete.js","sources":["../../src/components/Autocomplete.tsx"],"sourcesContent":["import React, { useState, useRef, useEffect, useId } from 'react'\nimport { useConfig } from '../providers/ConfigProvider'\n\n// DaisyUI classes\nconst dDropdown = 'dropdown'\nconst dDropdownBottom = 'dropdown-bottom'\nconst dDropdownOpen = 'dropdown-open'\nconst dDropdownContent = 'dropdown-content'\nconst dMenu = 'menu'\nconst dInput = 'input'\nconst dInputXs = 'input-xs'\nconst dInputSm = 'input-sm'\nconst dInputMd = 'input-md'\nconst dInputLg = 'input-lg'\nconst dInputXl = 'input-xl'\nconst dInputNeutral = 'input-neutral'\nconst dInputPrimary = 'input-primary'\nconst dInputSecondary = 'input-secondary'\nconst dInputAccent = 'input-accent'\nconst dInputInfo = 'input-info'\nconst dInputSuccess = 'input-success'\nconst dInputWarning = 'input-warning'\nconst dInputError = 'input-error'\n\nexport interface AutocompleteOption {\n value: string\n label: string\n disabled?: boolean\n}\n\nexport interface AutocompleteProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange' | 'onSelect'> {\n value?: string\n defaultValue?: string\n onChange?: (value: string) => void\n onSelect?: (value: string, option: AutocompleteOption) => void\n onSearch?: (value: string) => void\n options: AutocompleteOption[] | string[]\n placeholder?: string\n disabled?: boolean\n size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'\n color?: 'neutral' | 'primary' | 'secondary' | 'accent' | 'info' | 'success' | 'warning' | 'error'\n /** Validation status */\n status?: 'error' | 'warning'\n allowCustomValue?: boolean\n filterOption?: (option: AutocompleteOption, inputValue: string) => boolean\n notFoundContent?: React.ReactNode\n /** Show clear button when input has value */\n allowClear?: boolean | { clearIcon?: React.ReactNode }\n /** Callback when clear button is clicked */\n onClear?: () => void\n /** Controlled open state */\n open?: boolean\n /** Default open state */\n defaultOpen?: boolean\n /** Callback when open state changes */\n onOpenChange?: (open: boolean) => void\n /** Activate first option by default */\n defaultActiveFirstOption?: boolean\n}\n\n// Clear icon component\nconst ClearIcon: React.FC<{ onClick: (e: React.MouseEvent) => void; className?: string }> = ({ onClick, className }) => (\n <button\n type=\"button\"\n onClick={onClick}\n className={`flex items-center justify-center opacity-50 hover:opacity-100 transition-opacity ${className || ''}`}\n aria-label=\"Clear input\"\n tabIndex={-1}\n >\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=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n)\n\nexport const Autocomplete: React.FC<AutocompleteProps> = ({\n value,\n defaultValue = '',\n onChange,\n onSelect,\n onSearch,\n options: rawOptions,\n placeholder = 'Type to search...',\n disabled = false,\n size,\n color,\n status,\n className = '',\n allowCustomValue = true,\n filterOption,\n notFoundContent = 'No results found',\n allowClear,\n onClear,\n open: controlledOpen,\n defaultOpen = false,\n onOpenChange,\n defaultActiveFirstOption = true,\n ...rest\n}) => {\n const { componentSize } = useConfig()\n const effectiveSize = size ?? componentSize ?? 'md'\n // Generate unique IDs for ARIA\n const baseId = useId()\n const inputId = `${baseId}-input`\n const listboxId = `${baseId}-listbox`\n\n // Normalize options to AutocompleteOption[]\n const options: AutocompleteOption[] = rawOptions.map((opt) =>\n typeof opt === 'string' ? { value: opt, label: opt } : opt\n )\n\n const [inputValue, setInputValue] = useState(defaultValue)\n const [internalOpen, setInternalOpen] = useState(defaultOpen)\n const [highlightedIndex, setHighlightedIndex] = useState(-1)\n const inputRef = useRef<HTMLInputElement>(null)\n const dropdownRef = useRef<HTMLUListElement>(null)\n\n // Determine if open state is controlled\n const isOpenControlled = controlledOpen !== undefined\n const isOpen = isOpenControlled ? controlledOpen : internalOpen\n\n const setIsOpen = (newOpen: boolean) => {\n if (!isOpenControlled) {\n setInternalOpen(newOpen)\n }\n onOpenChange?.(newOpen)\n }\n\n // Update input value when controlled value changes\n useEffect(() => {\n if (value !== undefined) {\n const selectedOption = options.find((opt) => opt.value === value)\n setInputValue(selectedOption?.label || value)\n }\n }, [value, options])\n\n // Filter options based on input\n const defaultFilter = (option: AutocompleteOption, input: string) =>\n option.label.toLowerCase().includes(input.toLowerCase())\n\n const filteredOptions = options.filter((option) =>\n filterOption ? filterOption(option, inputValue) : defaultFilter(option, inputValue)\n )\n\n // Get only enabled options for keyboard navigation\n const enabledOptions = filteredOptions.filter(opt => !opt.disabled)\n\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const newInputValue = e.target.value\n setInputValue(newInputValue)\n setIsOpen(true)\n\n if (defaultActiveFirstOption && enabledOptions.length > 0) {\n setHighlightedIndex(0)\n } else {\n setHighlightedIndex(-1)\n }\n\n onSearch?.(newInputValue)\n\n if (allowCustomValue) {\n onChange?.(newInputValue)\n }\n }\n\n const handleOptionClick = (option: AutocompleteOption) => {\n if (option.disabled) return\n\n setInputValue(option.label)\n setIsOpen(false)\n setHighlightedIndex(-1)\n\n onChange?.(option.value)\n onSelect?.(option.value, option)\n inputRef.current?.focus()\n }\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (!isOpen && (e.key === 'ArrowDown' || e.key === 'ArrowUp')) {\n setIsOpen(true)\n if (defaultActiveFirstOption && enabledOptions.length > 0) {\n setHighlightedIndex(0)\n }\n return\n }\n\n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault()\n setHighlightedIndex((prev) => {\n // Find next enabled option\n for (let i = prev + 1; i < filteredOptions.length; i++) {\n if (!filteredOptions[i].disabled) return i\n }\n return prev\n })\n break\n case 'ArrowUp':\n e.preventDefault()\n setHighlightedIndex((prev) => {\n // Find previous enabled option\n for (let i = prev - 1; i >= 0; i--) {\n if (!filteredOptions[i].disabled) return i\n }\n return prev\n })\n break\n case 'Enter':\n e.preventDefault()\n if (highlightedIndex >= 0 && filteredOptions[highlightedIndex] && !filteredOptions[highlightedIndex].disabled) {\n handleOptionClick(filteredOptions[highlightedIndex])\n } else if (!allowCustomValue && enabledOptions.length > 0) {\n handleOptionClick(enabledOptions[0])\n }\n break\n case 'Escape':\n setIsOpen(false)\n setHighlightedIndex(-1)\n inputRef.current?.blur()\n break\n }\n }\n\n const handleFocus = () => {\n setIsOpen(true)\n if (defaultActiveFirstOption && enabledOptions.length > 0) {\n setHighlightedIndex(0)\n }\n }\n\n const handleBlur = (e: React.FocusEvent) => {\n // Don't close if clicking inside dropdown\n if (dropdownRef.current && dropdownRef.current.contains(e.relatedTarget as Node)) {\n return\n }\n setTimeout(() => setIsOpen(false), 200)\n }\n\n const handleClear = (e: React.MouseEvent) => {\n e.stopPropagation()\n setInputValue('')\n onChange?.('')\n onClear?.()\n inputRef.current?.focus()\n }\n\n const sizeClasses = {\n xs: dInputXs,\n sm: dInputSm,\n md: dInputMd,\n lg: dInputLg,\n xl: dInputXl,\n }\n\n const colorClasses = {\n neutral: dInputNeutral,\n primary: dInputPrimary,\n secondary: dInputSecondary,\n accent: dInputAccent,\n info: dInputInfo,\n success: dInputSuccess,\n warning: dInputWarning,\n error: dInputError,\n }\n\n const statusClasses = {\n error: dInputError,\n warning: dInputWarning,\n }\n\n // Status takes precedence over color for validation feedback\n const effectiveColorClass = status ? statusClasses[status] : (color ? colorClasses[color] : '')\n\n // Scroll highlighted option into view\n useEffect(() => {\n if (highlightedIndex >= 0 && dropdownRef.current) {\n const highlightedElement = dropdownRef.current.children[highlightedIndex] as HTMLElement\n highlightedElement?.scrollIntoView({ block: 'nearest' })\n }\n }, [highlightedIndex])\n\n // Determine if we should show clear button\n const showClear = allowClear && inputValue && !disabled\n\n // Get custom clear icon if provided\n const clearIcon = typeof allowClear === 'object' && allowClear.clearIcon\n ? allowClear.clearIcon\n : null\n\n // Get option ID for ARIA\n const getOptionId = (index: number) => `${baseId}-option-${index}`\n\n const inputClasses = [\n `${dInput} w-full`,\n sizeClasses[effectiveSize],\n effectiveColorClass,\n showClear && 'pr-10',\n ].filter(Boolean).join(' ')\n\n return (\n <div\n className={`${dDropdown} ${dDropdownBottom} w-full ${isOpen && !disabled ? dDropdownOpen : ''} ${className}`}\n data-state={isOpen ? 'open' : 'closed'}\n {...rest}\n >\n <div className=\"relative w-full\">\n <input\n ref={inputRef}\n id={inputId}\n type=\"text\"\n role=\"combobox\"\n aria-expanded={isOpen}\n aria-haspopup=\"listbox\"\n aria-controls={listboxId}\n aria-autocomplete=\"list\"\n aria-activedescendant={highlightedIndex >= 0 ? getOptionId(highlightedIndex) : undefined}\n aria-invalid={status === 'error' ? true : undefined}\n value={inputValue}\n onChange={handleInputChange}\n onKeyDown={handleKeyDown}\n onFocus={handleFocus}\n onBlur={handleBlur}\n placeholder={placeholder}\n disabled={disabled}\n className={inputClasses}\n />\n {showClear && (\n <span className=\"absolute right-3 top-1/2 -translate-y-1/2 z-10\">\n {clearIcon || <ClearIcon onClick={handleClear} />}\n </span>\n )}\n </div>\n\n {isOpen && !disabled && (\n <ul\n ref={dropdownRef}\n id={listboxId}\n role=\"listbox\"\n aria-label=\"Suggestions\"\n tabIndex={-1}\n className={`${dDropdownContent} ${dMenu} bg-base-100 rounded-box z-50 w-full shadow-lg border border-base-300 max-h-60 overflow-auto flex-nowrap`}\n >\n {filteredOptions.length > 0 ? (\n filteredOptions.map((option, index) => (\n <li key={option.value}>\n <a\n id={getOptionId(index)}\n role=\"option\"\n aria-selected={highlightedIndex === index}\n aria-disabled={option.disabled}\n onMouseDown={(e) => {\n e.preventDefault()\n handleOptionClick(option)\n }}\n onMouseEnter={() => !option.disabled && setHighlightedIndex(index)}\n className={[\n index === highlightedIndex && !option.disabled && 'active',\n option.disabled && 'disabled text-base-content/40 cursor-not-allowed',\n ].filter(Boolean).join(' ')}\n >\n {option.label}\n </a>\n </li>\n ))\n ) : (\n <li className=\"disabled\">\n <span className=\"text-base-content/60 text-center cursor-default\">{notFoundContent}</span>\n </li>\n )}\n </ul>\n )}\n </div>\n )\n}\n"],"names":["dDropdown","dDropdownBottom","dDropdownOpen","dDropdownContent","dMenu","dInput","dInputXs","dInputSm","dInputMd","dInputLg","dInputXl","dInputNeutral","dInputPrimary","dInputSecondary","dInputAccent","dInputInfo","dInputSuccess","dInputWarning","dInputError","ClearIcon","onClick","className","jsx","Autocomplete","value","defaultValue","onChange","onSelect","onSearch","rawOptions","placeholder","disabled","size","color","status","allowCustomValue","filterOption","notFoundContent","allowClear","onClear","controlledOpen","defaultOpen","onOpenChange","defaultActiveFirstOption","rest","componentSize","useConfig","effectiveSize","baseId","useId","inputId","listboxId","options","opt","inputValue","setInputValue","useState","internalOpen","setInternalOpen","highlightedIndex","setHighlightedIndex","inputRef","useRef","dropdownRef","isOpenControlled","isOpen","setIsOpen","newOpen","useEffect","selectedOption","defaultFilter","option","input","filteredOptions","enabledOptions","handleInputChange","newInputValue","handleOptionClick","handleKeyDown","prev","i","handleFocus","handleBlur","handleClear","sizeClasses","effectiveColorClass","showClear","clearIcon","getOptionId","index","inputClasses","jsxs","e"],"mappings":";;;AAIA,MAAMA,KAAY,YACZC,KAAkB,mBAClBC,KAAgB,iBAChBC,KAAmB,oBACnBC,KAAQ,QACRC,KAAS,SACTC,KAAW,YACXC,KAAW,YACXC,KAAW,YACXC,KAAW,YACXC,KAAW,YACXC,KAAgB,iBAChBC,KAAgB,iBAChBC,KAAkB,mBAClBC,KAAe,gBACfC,KAAa,cACbC,KAAgB,iBAChBC,IAAgB,iBAChBC,IAAc,eAuCdC,KAAsF,CAAC,EAAE,SAAAC,GAAS,WAAAC,QACtG,gBAAAC;AAAA,EAAC;AAAA,EAAA;AAAA,IACC,MAAK;AAAA,IACL,SAAAF;AAAA,IACA,WAAW,oFAAoFC,KAAa,EAAE;AAAA,IAC9G,cAAW;AAAA,IACX,UAAU;AAAA,IAEV,UAAA,gBAAAC,EAAC,SAAI,WAAU,WAAU,MAAK,QAAO,SAAQ,aAAY,QAAO,gBAAe,eAAY,QACzF,UAAA,gBAAAA,EAAC,QAAA,EAAK,eAAc,SAAQ,gBAAe,SAAQ,aAAa,GAAG,GAAE,uBAAA,CAAuB,EAAA,CAC9F;AAAA,EAAA;AACF,GAGWC,KAA4C,CAAC;AAAA,EACxD,OAAAC;AAAA,EACA,cAAAC,IAAe;AAAA,EACf,UAAAC;AAAA,EACA,UAAAC;AAAA,EACA,UAAAC;AAAA,EACA,SAASC;AAAA,EACT,aAAAC,IAAc;AAAA,EACd,UAAAC,IAAW;AAAA,EACX,MAAAC;AAAA,EACA,OAAAC;AAAA,EACA,QAAAC;AAAA,EACA,WAAAb,IAAY;AAAA,EACZ,kBAAAc,IAAmB;AAAA,EACnB,cAAAC;AAAA,EACA,iBAAAC,IAAkB;AAAA,EAClB,YAAAC;AAAA,EACA,SAAAC;AAAA,EACA,MAAMC;AAAA,EACN,aAAAC,IAAc;AAAA,EACd,cAAAC;AAAA,EACA,0BAAAC,IAA2B;AAAA,EAC3B,GAAGC;AACL,MAAM;AACJ,QAAM,EAAE,eAAAC,EAAA,IAAkBC,GAAA,GACpBC,IAAgBf,KAAQa,KAAiB,MAEzCG,IAASC,GAAA,GACTC,IAAU,GAAGF,CAAM,UACnBG,IAAY,GAAGH,CAAM,YAGrBI,IAAgCvB,EAAW;AAAA,IAAI,CAACwB,MACpD,OAAOA,KAAQ,WAAW,EAAE,OAAOA,GAAK,OAAOA,MAAQA;AAAA,EAAA,GAGnD,CAACC,GAAYC,CAAa,IAAIC,EAAS/B,CAAY,GACnD,CAACgC,GAAcC,CAAe,IAAIF,EAASf,CAAW,GACtD,CAACkB,GAAkBC,CAAmB,IAAIJ,EAAS,EAAE,GACrDK,IAAWC,EAAyB,IAAI,GACxCC,IAAcD,EAAyB,IAAI,GAG3CE,IAAmBxB,MAAmB,QACtCyB,IAASD,IAAmBxB,IAAiBiB,GAE7CS,IAAY,CAACC,MAAqB;AACtC,IAAKH,KACHN,EAAgBS,CAAO,GAEzBzB,IAAeyB,CAAO;AAAA,EACxB;AAGA,EAAAC,EAAU,MAAM;AACd,QAAI5C,MAAU,QAAW;AACvB,YAAM6C,IAAiBjB,EAAQ,KAAK,CAACC,MAAQA,EAAI,UAAU7B,CAAK;AAChE,MAAA+B,EAAcc,GAAgB,SAAS7C,CAAK;AAAA,IAC9C;AAAA,EACF,GAAG,CAACA,GAAO4B,CAAO,CAAC;AAGnB,QAAMkB,KAAgB,CAACC,GAA4BC,MACjDD,EAAO,MAAM,cAAc,SAASC,EAAM,YAAA,CAAa,GAEnDC,IAAkBrB,EAAQ;AAAA,IAAO,CAACmB,MACtCnC,IAAeA,EAAamC,GAAQjB,CAAU,IAAIgB,GAAcC,GAAQjB,CAAU;AAAA,EAAA,GAI9EoB,IAAiBD,EAAgB,OAAO,CAAApB,MAAO,CAACA,EAAI,QAAQ,GAE5DsB,KAAoB,CAAC,MAA2C;AACpE,UAAMC,IAAgB,EAAE,OAAO;AAC/B,IAAArB,EAAcqB,CAAa,GAC3BV,EAAU,EAAI,GAEVvB,KAA4B+B,EAAe,SAAS,IACtDd,EAAoB,CAAC,IAErBA,EAAoB,EAAE,GAGxBhC,IAAWgD,CAAa,GAEpBzC,KACFT,IAAWkD,CAAa;AAAA,EAE5B,GAEMC,IAAoB,CAACN,MAA+B;AACxD,IAAIA,EAAO,aAEXhB,EAAcgB,EAAO,KAAK,GAC1BL,EAAU,EAAK,GACfN,EAAoB,EAAE,GAEtBlC,IAAW6C,EAAO,KAAK,GACvB5C,IAAW4C,EAAO,OAAOA,CAAM,GAC/BV,EAAS,SAAS,MAAA;AAAA,EACpB,GAEMiB,KAAgB,CAAC,MAA6C;AAClE,QAAI,CAACb,MAAW,EAAE,QAAQ,eAAe,EAAE,QAAQ,YAAY;AAC7D,MAAAC,EAAU,EAAI,GACVvB,KAA4B+B,EAAe,SAAS,KACtDd,EAAoB,CAAC;AAEvB;AAAA,IACF;AAEA,YAAQ,EAAE,KAAA;AAAA,MACR,KAAK;AACH,UAAE,eAAA,GACFA,EAAoB,CAACmB,MAAS;AAE5B,mBAASC,IAAID,IAAO,GAAGC,IAAIP,EAAgB,QAAQO;AACjD,gBAAI,CAACP,EAAgBO,CAAC,EAAE,SAAU,QAAOA;AAE3C,iBAAOD;AAAA,QACT,CAAC;AACD;AAAA,MACF,KAAK;AACH,UAAE,eAAA,GACFnB,EAAoB,CAACmB,MAAS;AAE5B,mBAASC,IAAID,IAAO,GAAGC,KAAK,GAAGA;AAC7B,gBAAI,CAACP,EAAgBO,CAAC,EAAE,SAAU,QAAOA;AAE3C,iBAAOD;AAAA,QACT,CAAC;AACD;AAAA,MACF,KAAK;AACH,UAAE,eAAA,GACEpB,KAAoB,KAAKc,EAAgBd,CAAgB,KAAK,CAACc,EAAgBd,CAAgB,EAAE,WACnGkB,EAAkBJ,EAAgBd,CAAgB,CAAC,IAC1C,CAACxB,KAAoBuC,EAAe,SAAS,KACtDG,EAAkBH,EAAe,CAAC,CAAC;AAErC;AAAA,MACF,KAAK;AACH,QAAAR,EAAU,EAAK,GACfN,EAAoB,EAAE,GACtBC,EAAS,SAAS,KAAA;AAClB;AAAA,IAAA;AAAA,EAEN,GAEMoB,KAAc,MAAM;AACxB,IAAAf,EAAU,EAAI,GACVvB,KAA4B+B,EAAe,SAAS,KACtDd,EAAoB,CAAC;AAAA,EAEzB,GAEMsB,KAAa,CAAC,MAAwB;AAE1C,IAAInB,EAAY,WAAWA,EAAY,QAAQ,SAAS,EAAE,aAAqB,KAG/E,WAAW,MAAMG,EAAU,EAAK,GAAG,GAAG;AAAA,EACxC,GAEMiB,KAAc,CAAC,MAAwB;AAC3C,MAAE,gBAAA,GACF5B,EAAc,EAAE,GAChB7B,IAAW,EAAE,GACba,IAAA,GACAsB,EAAS,SAAS,MAAA;AAAA,EACpB,GAEMuB,KAAc;AAAA,IAClB,IAAI9E;AAAA,IACJ,IAAIC;AAAA,IACJ,IAAIC;AAAA,IACJ,IAAIC;AAAA,IACJ,IAAIC;AAAA,EAAA,GAoBA2E,KAAsBnD,IANN;AAAA,IACpB,OAAOhB;AAAA,IACP,SAASD;AAAA,EAAA,EAIwCiB,CAAM,IAAKD,IAjBzC;AAAA,IACnB,SAAStB;AAAA,IACT,SAASC;AAAA,IACT,WAAWC;AAAA,IACX,QAAQC;AAAA,IACR,MAAMC;AAAA,IACN,SAASC;AAAA,IACT,SAASC;AAAA,IACT,OAAOC;AAAA,EAAA,EAS0Ee,CAAK,IAAI;AAG5F,EAAAmC,EAAU,MAAM;AACd,IAAIT,KAAoB,KAAKI,EAAY,WACZA,EAAY,QAAQ,SAASJ,CAAgB,GACpD,eAAe,EAAE,OAAO,UAAA,CAAW;AAAA,EAE3D,GAAG,CAACA,CAAgB,CAAC;AAGrB,QAAM2B,IAAYhD,KAAcgB,KAAc,CAACvB,GAGzCwD,KAAY,OAAOjD,KAAe,YAAYA,EAAW,YAC3DA,EAAW,YACX,MAGEkD,IAAc,CAACC,MAAkB,GAAGzC,CAAM,WAAWyC,CAAK,IAE1DC,KAAe;AAAA,IACnB,GAAGrF,EAAM;AAAA,IACT+E,GAAYrC,CAAa;AAAA,IACzBsC;AAAA,IACAC,KAAa;AAAA,EAAA,EACb,OAAO,OAAO,EAAE,KAAK,GAAG;AAE1B,SACE,gBAAAK;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAW,GAAG3F,EAAS,IAAIC,EAAe,WAAWgE,KAAU,CAAClC,IAAW7B,KAAgB,EAAE,IAAImB,CAAS;AAAA,MAC1G,cAAY4C,IAAS,SAAS;AAAA,MAC7B,GAAGrB;AAAA,MAEJ,UAAA;AAAA,QAAA,gBAAA+C,EAAC,OAAA,EAAI,WAAU,mBACb,UAAA;AAAA,UAAA,gBAAArE;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,KAAKuC;AAAA,cACL,IAAIX;AAAA,cACJ,MAAK;AAAA,cACL,MAAK;AAAA,cACL,iBAAee;AAAA,cACf,iBAAc;AAAA,cACd,iBAAed;AAAA,cACf,qBAAkB;AAAA,cAClB,yBAAuBQ,KAAoB,IAAI6B,EAAY7B,CAAgB,IAAI;AAAA,cAC/E,gBAAczB,MAAW,UAAU,KAAO;AAAA,cAC1C,OAAOoB;AAAA,cACP,UAAUqB;AAAA,cACV,WAAWG;AAAA,cACX,SAASG;AAAA,cACT,QAAQC;AAAA,cACR,aAAApD;AAAA,cACA,UAAAC;AAAA,cACA,WAAW2D;AAAA,YAAA;AAAA,UAAA;AAAA,UAEZJ,KACC,gBAAAhE,EAAC,QAAA,EAAK,WAAU,kDACb,gBAAa,gBAAAA,EAACH,IAAA,EAAU,SAASgE,GAAA,CAAa,EAAA,CACjD;AAAA,QAAA,GAEJ;AAAA,QAEClB,KAAU,CAAClC,KACV,gBAAAT;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,KAAKyC;AAAA,YACL,IAAIZ;AAAA,YACJ,MAAK;AAAA,YACL,cAAW;AAAA,YACX,UAAU;AAAA,YACV,WAAW,GAAGhD,EAAgB,IAAIC,EAAK;AAAA,YAEtC,UAAAqE,EAAgB,SAAS,IACxBA,EAAgB,IAAI,CAACF,GAAQkB,MAC3B,gBAAAnE,EAAC,MAAA,EACC,UAAA,gBAAAA;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,IAAIkE,EAAYC,CAAK;AAAA,gBACrB,MAAK;AAAA,gBACL,iBAAe9B,MAAqB8B;AAAA,gBACpC,iBAAelB,EAAO;AAAA,gBACtB,aAAa,CAACqB,MAAM;AAClB,kBAAAA,EAAE,eAAA,GACFf,EAAkBN,CAAM;AAAA,gBAC1B;AAAA,gBACA,cAAc,MAAM,CAACA,EAAO,YAAYX,EAAoB6B,CAAK;AAAA,gBACjE,WAAW;AAAA,kBACTA,MAAU9B,KAAoB,CAACY,EAAO,YAAY;AAAA,kBAClDA,EAAO,YAAY;AAAA,gBAAA,EACnB,OAAO,OAAO,EAAE,KAAK,GAAG;AAAA,gBAEzB,UAAAA,EAAO;AAAA,cAAA;AAAA,YAAA,EACV,GAjBOA,EAAO,KAkBhB,CACD,IAED,gBAAAjD,EAAC,MAAA,EAAG,WAAU,YACZ,UAAA,gBAAAA,EAAC,QAAA,EAAK,WAAU,mDAAmD,aAAgB,EAAA,CACrF;AAAA,UAAA;AAAA,QAAA;AAAA,MAEJ;AAAA,IAAA;AAAA,EAAA;AAIR;"}
|
|
1
|
+
{"version":3,"file":"Autocomplete.js","sources":["../../src/components/Autocomplete.tsx"],"sourcesContent":["import React, { useState, useRef, useEffect, useId } from 'react'\nimport { useConfig } from '../providers/ConfigProvider'\n\n// DaisyUI classes\nconst dDropdown = 'dropdown'\nconst dDropdownBottom = 'dropdown-bottom'\nconst dDropdownOpen = 'dropdown-open'\nconst dDropdownContent = 'dropdown-content'\nconst dMenu = 'menu'\nconst dInput = 'input'\nconst dInputXs = 'input-xs'\nconst dInputSm = 'input-sm'\nconst dInputMd = 'input-md'\nconst dInputLg = 'input-lg'\nconst dInputXl = 'input-xl'\nconst dInputNeutral = 'input-neutral'\nconst dInputPrimary = 'input-primary'\nconst dInputSecondary = 'input-secondary'\nconst dInputAccent = 'input-accent'\nconst dInputInfo = 'input-info'\nconst dInputSuccess = 'input-success'\nconst dInputWarning = 'input-warning'\nconst dInputError = 'input-error'\n\nexport interface AutocompleteOption {\n value: string\n label: string\n disabled?: boolean\n}\n\nexport interface AutocompleteProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange' | 'onSelect'> {\n value?: string\n defaultValue?: string\n onChange?: (value: string) => void\n onSelect?: (value: string, option: AutocompleteOption) => void\n onSearch?: (value: string) => void\n options: AutocompleteOption[] | string[]\n placeholder?: string\n disabled?: boolean\n size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'\n color?: 'neutral' | 'primary' | 'secondary' | 'accent' | 'info' | 'success' | 'warning' | 'error'\n /** Validation status */\n status?: 'error' | 'warning'\n allowCustomValue?: boolean\n filterOption?: (option: AutocompleteOption, inputValue: string) => boolean\n notFoundContent?: React.ReactNode\n /** Show clear button when input has value */\n allowClear?: boolean | { clearIcon?: React.ReactNode }\n /** Callback when clear button is clicked */\n onClear?: () => void\n /** Controlled open state */\n open?: boolean\n /** Default open state */\n defaultOpen?: boolean\n /** Callback when open state changes */\n onOpenChange?: (open: boolean) => void\n /** Activate first option by default */\n defaultActiveFirstOption?: boolean\n 'data-testid'?: string\n}\n\n// Clear icon component\nconst ClearIcon: React.FC<{ onClick: (e: React.MouseEvent) => void; className?: string }> = ({ onClick, className }) => (\n <button\n type=\"button\"\n onClick={onClick}\n className={`flex items-center justify-center opacity-50 hover:opacity-100 transition-opacity ${className || ''}`}\n aria-label=\"Clear input\"\n tabIndex={-1}\n >\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=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n)\n\nexport const Autocomplete: React.FC<AutocompleteProps> = ({\n value,\n defaultValue = '',\n onChange,\n onSelect,\n onSearch,\n options: rawOptions,\n placeholder = 'Type to search...',\n disabled = false,\n size,\n color,\n status,\n className = '',\n allowCustomValue = true,\n filterOption,\n notFoundContent = 'No results found',\n allowClear,\n onClear,\n open: controlledOpen,\n defaultOpen = false,\n onOpenChange,\n defaultActiveFirstOption = true,\n 'data-testid': testId,\n ...rest\n}) => {\n const { componentSize } = useConfig()\n const effectiveSize = size ?? componentSize ?? 'md'\n // Generate unique IDs for ARIA\n const baseId = useId()\n const inputId = `${baseId}-input`\n const listboxId = `${baseId}-listbox`\n\n // Normalize options to AutocompleteOption[]\n const options: AutocompleteOption[] = rawOptions.map((opt) =>\n typeof opt === 'string' ? { value: opt, label: opt } : opt\n )\n\n const [inputValue, setInputValue] = useState(defaultValue)\n const [internalOpen, setInternalOpen] = useState(defaultOpen)\n const [highlightedIndex, setHighlightedIndex] = useState(-1)\n const inputRef = useRef<HTMLInputElement>(null)\n const dropdownRef = useRef<HTMLUListElement>(null)\n\n // Determine if open state is controlled\n const isOpenControlled = controlledOpen !== undefined\n const isOpen = isOpenControlled ? controlledOpen : internalOpen\n\n const setIsOpen = (newOpen: boolean) => {\n if (!isOpenControlled) {\n setInternalOpen(newOpen)\n }\n onOpenChange?.(newOpen)\n }\n\n // Update input value when controlled value changes\n useEffect(() => {\n if (value !== undefined) {\n const selectedOption = options.find((opt) => opt.value === value)\n setInputValue(selectedOption?.label || value)\n }\n }, [value, options])\n\n // Filter options based on input\n const defaultFilter = (option: AutocompleteOption, input: string) =>\n option.label.toLowerCase().includes(input.toLowerCase())\n\n const filteredOptions = options.filter((option) =>\n filterOption ? filterOption(option, inputValue) : defaultFilter(option, inputValue)\n )\n\n // Get only enabled options for keyboard navigation\n const enabledOptions = filteredOptions.filter(opt => !opt.disabled)\n\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const newInputValue = e.target.value\n setInputValue(newInputValue)\n setIsOpen(true)\n\n if (defaultActiveFirstOption && enabledOptions.length > 0) {\n setHighlightedIndex(0)\n } else {\n setHighlightedIndex(-1)\n }\n\n onSearch?.(newInputValue)\n\n if (allowCustomValue) {\n onChange?.(newInputValue)\n }\n }\n\n const handleOptionClick = (option: AutocompleteOption) => {\n if (option.disabled) return\n\n setInputValue(option.label)\n setIsOpen(false)\n setHighlightedIndex(-1)\n\n onChange?.(option.value)\n onSelect?.(option.value, option)\n inputRef.current?.focus()\n }\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (!isOpen && (e.key === 'ArrowDown' || e.key === 'ArrowUp')) {\n setIsOpen(true)\n if (defaultActiveFirstOption && enabledOptions.length > 0) {\n setHighlightedIndex(0)\n }\n return\n }\n\n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault()\n setHighlightedIndex((prev) => {\n // Find next enabled option\n for (let i = prev + 1; i < filteredOptions.length; i++) {\n if (!filteredOptions[i].disabled) return i\n }\n return prev\n })\n break\n case 'ArrowUp':\n e.preventDefault()\n setHighlightedIndex((prev) => {\n // Find previous enabled option\n for (let i = prev - 1; i >= 0; i--) {\n if (!filteredOptions[i].disabled) return i\n }\n return prev\n })\n break\n case 'Enter':\n e.preventDefault()\n if (highlightedIndex >= 0 && filteredOptions[highlightedIndex] && !filteredOptions[highlightedIndex].disabled) {\n handleOptionClick(filteredOptions[highlightedIndex])\n } else if (!allowCustomValue && enabledOptions.length > 0) {\n handleOptionClick(enabledOptions[0])\n }\n break\n case 'Escape':\n setIsOpen(false)\n setHighlightedIndex(-1)\n inputRef.current?.blur()\n break\n }\n }\n\n const handleFocus = () => {\n setIsOpen(true)\n if (defaultActiveFirstOption && enabledOptions.length > 0) {\n setHighlightedIndex(0)\n }\n }\n\n const handleBlur = (e: React.FocusEvent) => {\n // Don't close if clicking inside dropdown\n if (dropdownRef.current && dropdownRef.current.contains(e.relatedTarget as Node)) {\n return\n }\n setTimeout(() => setIsOpen(false), 200)\n }\n\n const handleClear = (e: React.MouseEvent) => {\n e.stopPropagation()\n setInputValue('')\n onChange?.('')\n onClear?.()\n inputRef.current?.focus()\n }\n\n const sizeClasses = {\n xs: dInputXs,\n sm: dInputSm,\n md: dInputMd,\n lg: dInputLg,\n xl: dInputXl,\n }\n\n const colorClasses = {\n neutral: dInputNeutral,\n primary: dInputPrimary,\n secondary: dInputSecondary,\n accent: dInputAccent,\n info: dInputInfo,\n success: dInputSuccess,\n warning: dInputWarning,\n error: dInputError,\n }\n\n const statusClasses = {\n error: dInputError,\n warning: dInputWarning,\n }\n\n // Status takes precedence over color for validation feedback\n const effectiveColorClass = status ? statusClasses[status] : (color ? colorClasses[color] : '')\n\n // Scroll highlighted option into view\n useEffect(() => {\n if (highlightedIndex >= 0 && dropdownRef.current) {\n const highlightedElement = dropdownRef.current.children[highlightedIndex] as HTMLElement\n highlightedElement?.scrollIntoView({ block: 'nearest' })\n }\n }, [highlightedIndex])\n\n // Determine if we should show clear button\n const showClear = allowClear && inputValue && !disabled\n\n // Get custom clear icon if provided\n const clearIcon = typeof allowClear === 'object' && allowClear.clearIcon\n ? allowClear.clearIcon\n : null\n\n // Get option ID for ARIA\n const getOptionId = (index: number) => `${baseId}-option-${index}`\n\n const inputClasses = [\n `${dInput} w-full`,\n sizeClasses[effectiveSize],\n effectiveColorClass,\n showClear && 'pr-10',\n ].filter(Boolean).join(' ')\n\n const getTestId = (suffix: string) => (testId ? `${testId}-${suffix}` : undefined)\n\n return (\n <div\n className={`${dDropdown} ${dDropdownBottom} w-full ${isOpen && !disabled ? dDropdownOpen : ''} ${className}`}\n data-state={isOpen ? 'open' : 'closed'}\n data-testid={testId}\n {...rest}\n >\n <div className=\"relative w-full\">\n <input\n ref={inputRef}\n id={inputId}\n type=\"text\"\n role=\"combobox\"\n aria-expanded={isOpen}\n aria-haspopup=\"listbox\"\n aria-controls={listboxId}\n aria-autocomplete=\"list\"\n aria-activedescendant={highlightedIndex >= 0 ? getOptionId(highlightedIndex) : undefined}\n aria-invalid={status === 'error' ? true : undefined}\n value={inputValue}\n onChange={handleInputChange}\n onKeyDown={handleKeyDown}\n onFocus={handleFocus}\n onBlur={handleBlur}\n placeholder={placeholder}\n disabled={disabled}\n className={inputClasses}\n data-testid={getTestId('input')}\n />\n {showClear && (\n <span className=\"absolute right-3 top-1/2 -translate-y-1/2 z-10\" data-testid={getTestId('clear')}>\n {clearIcon || <ClearIcon onClick={handleClear} />}\n </span>\n )}\n </div>\n\n {isOpen && !disabled && (\n <ul\n ref={dropdownRef}\n id={listboxId}\n role=\"listbox\"\n aria-label=\"Suggestions\"\n tabIndex={-1}\n className={`${dDropdownContent} ${dMenu} bg-base-100 rounded-box z-50 w-full shadow-lg border border-base-300 max-h-60 overflow-auto flex-nowrap`}\n data-testid={getTestId('listbox')}\n >\n {filteredOptions.length > 0 ? (\n filteredOptions.map((option, index) => (\n <li key={option.value}>\n <a\n id={getOptionId(index)}\n role=\"option\"\n aria-selected={highlightedIndex === index}\n aria-disabled={option.disabled}\n onMouseDown={(e) => {\n e.preventDefault()\n handleOptionClick(option)\n }}\n onMouseEnter={() => !option.disabled && setHighlightedIndex(index)}\n className={[\n index === highlightedIndex && !option.disabled && 'active',\n option.disabled && 'disabled text-base-content/40 cursor-not-allowed',\n ].filter(Boolean).join(' ')}\n data-testid={getTestId(`option-${option.value || index}`)}\n >\n {option.label}\n </a>\n </li>\n ))\n ) : (\n <li className=\"disabled\" data-testid={getTestId('empty')}>\n <span className=\"text-base-content/60 text-center cursor-default\">{notFoundContent}</span>\n </li>\n )}\n </ul>\n )}\n </div>\n )\n}\n"],"names":["dDropdown","dDropdownBottom","dDropdownOpen","dDropdownContent","dMenu","dInput","dInputXs","dInputSm","dInputMd","dInputLg","dInputXl","dInputNeutral","dInputPrimary","dInputSecondary","dInputAccent","dInputInfo","dInputSuccess","dInputWarning","dInputError","ClearIcon","onClick","className","jsx","Autocomplete","value","defaultValue","onChange","onSelect","onSearch","rawOptions","placeholder","disabled","size","color","status","allowCustomValue","filterOption","notFoundContent","allowClear","onClear","controlledOpen","defaultOpen","onOpenChange","defaultActiveFirstOption","testId","rest","componentSize","useConfig","effectiveSize","baseId","useId","inputId","listboxId","options","opt","inputValue","setInputValue","useState","internalOpen","setInternalOpen","highlightedIndex","setHighlightedIndex","inputRef","useRef","dropdownRef","isOpenControlled","isOpen","setIsOpen","newOpen","useEffect","selectedOption","defaultFilter","option","input","filteredOptions","enabledOptions","handleInputChange","newInputValue","handleOptionClick","handleKeyDown","prev","i","handleFocus","handleBlur","handleClear","sizeClasses","effectiveColorClass","showClear","clearIcon","getOptionId","index","inputClasses","getTestId","suffix","jsxs","e"],"mappings":"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"}
|
|
@@ -16,6 +16,7 @@ export interface BreadcrumbProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
|
16
16
|
items?: BreadcrumbItemType[];
|
|
17
17
|
/** Custom separator between items */
|
|
18
18
|
separator?: React.ReactNode;
|
|
19
|
+
'data-testid'?: string;
|
|
19
20
|
}
|
|
20
21
|
export interface BreadcrumbItemProps extends Omit<React.LiHTMLAttributes<HTMLLIElement>, 'onClick'> {
|
|
21
22
|
children: React.ReactNode;
|
|
@@ -23,9 +24,10 @@ export interface BreadcrumbItemProps extends Omit<React.LiHTMLAttributes<HTMLLIE
|
|
|
23
24
|
onClick?: () => void;
|
|
24
25
|
/** Icon to display before the label */
|
|
25
26
|
icon?: React.ReactNode;
|
|
27
|
+
'data-testid'?: string;
|
|
26
28
|
}
|
|
27
|
-
declare function BreadcrumbRoot({ children, items, separator, className, ...rest }: BreadcrumbProps): import("react/jsx-runtime").JSX.Element;
|
|
28
|
-
declare function BreadcrumbItem({ children, href, onClick, icon, className, ...rest }: BreadcrumbItemProps): import("react/jsx-runtime").JSX.Element;
|
|
29
|
+
declare function BreadcrumbRoot({ children, items, separator, className, 'data-testid': testId, ...rest }: BreadcrumbProps): import("react/jsx-runtime").JSX.Element;
|
|
30
|
+
declare function BreadcrumbItem({ children, href, onClick, icon, className, 'data-testid': testId, ...rest }: BreadcrumbItemProps): import("react/jsx-runtime").JSX.Element;
|
|
29
31
|
export declare const Breadcrumb: typeof BreadcrumbRoot & {
|
|
30
32
|
Item: typeof BreadcrumbItem;
|
|
31
33
|
};
|
|
@@ -1,37 +1,62 @@
|
|
|
1
|
-
import { jsx as
|
|
2
|
-
import
|
|
3
|
-
const
|
|
4
|
-
function
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
return /* @__PURE__ */ m
|
|
8
|
-
/* @__PURE__ */
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
1
|
+
import { jsx as a, jsxs as $ } from "react/jsx-runtime";
|
|
2
|
+
import m from "react";
|
|
3
|
+
const p = "breadcrumbs";
|
|
4
|
+
function C({ children: s, items: r, separator: n, className: l = "", "data-testid": c, ...i }) {
|
|
5
|
+
const d = n !== void 0, o = typeof n == "string" ? "px-2" : "px-1", h = (t) => c ? `${c}-${t}` : void 0, b = () => !r || r.length === 0 ? null : r.map((t, e) => {
|
|
6
|
+
const u = e === r.length - 1;
|
|
7
|
+
return /* @__PURE__ */ $(m.Fragment, { children: [
|
|
8
|
+
/* @__PURE__ */ a(
|
|
9
|
+
"li",
|
|
10
|
+
{
|
|
11
|
+
className: t.className,
|
|
12
|
+
"aria-current": u ? "page" : void 0,
|
|
13
|
+
"data-testid": h(`item-${t.href ?? e}`),
|
|
14
|
+
children: t.href || t.onClick ? /* @__PURE__ */ a("a", { href: t.href, onClick: t.onClick, "data-testid": h(`link-${t.href ?? e}`), children: t.title }) : t.title
|
|
15
|
+
}
|
|
16
|
+
),
|
|
17
|
+
d && !u && /* @__PURE__ */ a(
|
|
18
|
+
"li",
|
|
19
|
+
{
|
|
20
|
+
className: `flex items-center ${o} text-base-content/50`,
|
|
21
|
+
"aria-hidden": "true",
|
|
22
|
+
"data-testid": h(`separator-${e}`),
|
|
23
|
+
children: n
|
|
24
|
+
}
|
|
25
|
+
)
|
|
26
|
+
] }, e);
|
|
27
|
+
}), g = () => {
|
|
28
|
+
if (r && r.length > 0)
|
|
13
29
|
return b();
|
|
14
|
-
if (
|
|
15
|
-
const
|
|
16
|
-
return
|
|
17
|
-
|
|
18
|
-
/* @__PURE__ */
|
|
30
|
+
if (d && s) {
|
|
31
|
+
const t = m.Children.toArray(s), e = [];
|
|
32
|
+
return t.forEach((u, f) => {
|
|
33
|
+
e.push(u), f < t.length - 1 && e.push(
|
|
34
|
+
/* @__PURE__ */ a(
|
|
35
|
+
"li",
|
|
36
|
+
{
|
|
37
|
+
className: `flex items-center ${o} text-base-content/50`,
|
|
38
|
+
"aria-hidden": "true",
|
|
39
|
+
"data-testid": h(`separator-${f}`),
|
|
40
|
+
children: n
|
|
41
|
+
},
|
|
42
|
+
`sep-${f}`
|
|
43
|
+
)
|
|
19
44
|
);
|
|
20
|
-
}),
|
|
45
|
+
}), e;
|
|
21
46
|
}
|
|
22
|
-
return
|
|
23
|
-
},
|
|
24
|
-
return /* @__PURE__ */
|
|
47
|
+
return s;
|
|
48
|
+
}, x = d ? `${p} text-sm [&_li::before]:!hidden ${l}` : `${p} text-sm ${l}`;
|
|
49
|
+
return /* @__PURE__ */ a("nav", { className: x, "aria-label": "Breadcrumb", "data-testid": c, ...i, children: /* @__PURE__ */ a("ul", { children: g() }) });
|
|
25
50
|
}
|
|
26
|
-
function
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
] }) :
|
|
31
|
-
return
|
|
51
|
+
function v({ children: s, href: r, onClick: n, icon: l, className: c = "", "data-testid": i, ...d }) {
|
|
52
|
+
const o = l ? /* @__PURE__ */ $("span", { className: "inline-flex items-center gap-2", children: [
|
|
53
|
+
l,
|
|
54
|
+
s
|
|
55
|
+
] }) : s;
|
|
56
|
+
return r || n ? /* @__PURE__ */ a("li", { className: c, "data-testid": i, ...d, children: /* @__PURE__ */ a("a", { href: r, onClick: n, "data-testid": i ? `${i}-link` : void 0, children: o }) }) : /* @__PURE__ */ a("li", { className: c, "data-testid": i, ...d, children: o });
|
|
32
57
|
}
|
|
33
|
-
const N = Object.assign(
|
|
34
|
-
Item:
|
|
58
|
+
const N = Object.assign(C, {
|
|
59
|
+
Item: v
|
|
35
60
|
});
|
|
36
61
|
export {
|
|
37
62
|
N as Breadcrumb
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Breadcrumb.js","sources":["../../src/components/Breadcrumb.tsx"],"sourcesContent":["import React from 'react'\n\n// DaisyUI classes\nconst dBreadcrumbs = 'breadcrumbs'\n\nexport interface BreadcrumbItemType {\n /** Item title/label */\n title: React.ReactNode\n /** Link URL */\n href?: string\n /** Click handler */\n onClick?: () => void\n /** Custom class name */\n className?: string\n}\n\nexport interface BreadcrumbProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Breadcrumb.Item children (compound pattern) */\n children?: React.ReactNode\n /** Breadcrumb items data (data-driven pattern) */\n items?: BreadcrumbItemType[]\n /** Custom separator between items */\n separator?: React.ReactNode\n}\n\nexport interface BreadcrumbItemProps extends Omit<React.LiHTMLAttributes<HTMLLIElement>, 'onClick'> {\n children: React.ReactNode\n href?: string\n onClick?: () => void\n /** Icon to display before the label */\n icon?: React.ReactNode\n}\n\nfunction BreadcrumbRoot({ children, items, separator, className = '', ...rest }: BreadcrumbProps) {\n const hasCustomSeparator = separator !== undefined\n // Text separators need more padding than icon separators\n const separatorPadding = typeof separator === 'string' ? 'px-2' : 'px-1'\n\n const renderFromItems = () => {\n if (!items || items.length === 0) return null\n\n return items.map((item, index) => {\n const isLast = index === items.length - 1\n return (\n <React.Fragment key={index}>\n <li
|
|
1
|
+
{"version":3,"file":"Breadcrumb.js","sources":["../../src/components/Breadcrumb.tsx"],"sourcesContent":["import React from 'react'\n\n// DaisyUI classes\nconst dBreadcrumbs = 'breadcrumbs'\n\nexport interface BreadcrumbItemType {\n /** Item title/label */\n title: React.ReactNode\n /** Link URL */\n href?: string\n /** Click handler */\n onClick?: () => void\n /** Custom class name */\n className?: string\n}\n\nexport interface BreadcrumbProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Breadcrumb.Item children (compound pattern) */\n children?: React.ReactNode\n /** Breadcrumb items data (data-driven pattern) */\n items?: BreadcrumbItemType[]\n /** Custom separator between items */\n separator?: React.ReactNode\n 'data-testid'?: string\n}\n\nexport interface BreadcrumbItemProps extends Omit<React.LiHTMLAttributes<HTMLLIElement>, 'onClick'> {\n children: React.ReactNode\n href?: string\n onClick?: () => void\n /** Icon to display before the label */\n icon?: React.ReactNode\n 'data-testid'?: string\n}\n\nfunction BreadcrumbRoot({ children, items, separator, className = '', 'data-testid': testId, ...rest }: BreadcrumbProps) {\n const hasCustomSeparator = separator !== undefined\n // Text separators need more padding than icon separators\n const separatorPadding = typeof separator === 'string' ? 'px-2' : 'px-1'\n const getTestId = (suffix: string) => (testId ? `${testId}-${suffix}` : undefined)\n\n const renderFromItems = () => {\n if (!items || items.length === 0) return null\n\n return items.map((item, index) => {\n const isLast = index === items.length - 1\n return (\n <React.Fragment key={index}>\n <li\n className={item.className}\n aria-current={isLast ? 'page' : undefined}\n data-testid={getTestId(`item-${item.href ?? index}`)}\n >\n {item.href || item.onClick ? (\n <a href={item.href} onClick={item.onClick} data-testid={getTestId(`link-${item.href ?? index}`)}>\n {item.title}\n </a>\n ) : (\n item.title\n )}\n </li>\n {hasCustomSeparator && !isLast && (\n <li\n className={`flex items-center ${separatorPadding} text-base-content/50`}\n aria-hidden=\"true\"\n data-testid={getTestId(`separator-${index}`)}\n >\n {separator}\n </li>\n )}\n </React.Fragment>\n )\n })\n }\n\n const renderChildren = () => {\n if (items && items.length > 0) {\n return renderFromItems()\n }\n\n if (hasCustomSeparator && children) {\n // Insert custom separator nodes between children\n const childArray = React.Children.toArray(children)\n const result: React.ReactNode[] = []\n childArray.forEach((child, index) => {\n result.push(child)\n if (index < childArray.length - 1) {\n result.push(\n <li\n key={`sep-${index}`}\n className={`flex items-center ${separatorPadding} text-base-content/50`}\n aria-hidden=\"true\"\n data-testid={getTestId(`separator-${index}`)}\n >\n {separator}\n </li>\n )\n }\n })\n return result\n }\n\n return children\n }\n\n // When custom separator is provided, hide default DaisyUI separator\n const cssClass = hasCustomSeparator\n ? `${dBreadcrumbs} text-sm [&_li::before]:!hidden ${className}`\n : `${dBreadcrumbs} text-sm ${className}`\n\n return (\n <nav className={cssClass} aria-label=\"Breadcrumb\" data-testid={testId} {...rest}>\n <ul>{renderChildren()}</ul>\n </nav>\n )\n}\n\nfunction BreadcrumbItem({ children, href, onClick, icon, className = '', 'data-testid': testId, ...rest }: BreadcrumbItemProps) {\n const content = icon ? (\n <span className=\"inline-flex items-center gap-2\">\n {icon}\n {children}\n </span>\n ) : children\n\n if (href || onClick) {\n return (\n <li className={className} data-testid={testId} {...rest}>\n <a href={href} onClick={onClick} data-testid={testId ? `${testId}-link` : undefined}>\n {content}\n </a>\n </li>\n )\n }\n\n return <li className={className} data-testid={testId} {...rest}>{content}</li>\n}\n\nexport const Breadcrumb = Object.assign(BreadcrumbRoot, {\n Item: BreadcrumbItem,\n})\n"],"names":["dBreadcrumbs","BreadcrumbRoot","children","items","separator","className","testId","rest","hasCustomSeparator","separatorPadding","getTestId","suffix","renderFromItems","item","index","isLast","jsxs","React","jsx","renderChildren","childArray","result","child","cssClass","BreadcrumbItem","href","onClick","icon","content","Breadcrumb"],"mappings":"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"}
|
|
@@ -17,11 +17,15 @@ type BaseButtonProps = {
|
|
|
17
17
|
/** Icon element to display */
|
|
18
18
|
icon?: React.ReactNode;
|
|
19
19
|
/** Position of the icon */
|
|
20
|
+
iconPlacement?: 'start' | 'end';
|
|
21
|
+
/** @deprecated Use iconPlacement instead */
|
|
20
22
|
iconPosition?: 'start' | 'end';
|
|
21
23
|
/** Applies error/danger styling (shorthand for color="error") */
|
|
22
24
|
danger?: boolean;
|
|
23
25
|
/** Toggle button pressed state (sets aria-pressed) */
|
|
24
26
|
pressed?: boolean;
|
|
27
|
+
/** Test ID for testing */
|
|
28
|
+
'data-testid'?: string;
|
|
25
29
|
};
|
|
26
30
|
type ButtonAsButton = BaseButtonProps & Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'type'> & {
|
|
27
31
|
href?: undefined;
|
|
@@ -34,5 +38,5 @@ type ButtonAsAnchor = BaseButtonProps & Omit<React.AnchorHTMLAttributes<HTMLAnch
|
|
|
34
38
|
disabled?: boolean;
|
|
35
39
|
};
|
|
36
40
|
export type ButtonProps = ButtonAsButton | ButtonAsAnchor;
|
|
37
|
-
export declare const Button: React.
|
|
41
|
+
export declare const Button: React.ForwardRefExoticComponent<ButtonProps & React.RefAttributes<HTMLAnchorElement | HTMLButtonElement>>;
|
|
38
42
|
export {};
|
|
@@ -1,114 +1,124 @@
|
|
|
1
|
-
import { jsx as
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
1
|
+
import { jsx as o, jsxs as W, Fragment as X } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef as F } from "react";
|
|
3
|
+
import { SizeProvider as G } from "../contexts/SizeContext.js";
|
|
4
|
+
import { useConfig as M } from "../providers/ConfigProvider.js";
|
|
5
|
+
const O = "btn", R = "btn-primary", H = "btn-secondary", J = "btn-accent", Q = "btn-info", U = "btn-success", V = "btn-warning", Y = "btn-error", Z = "btn-neutral", _ = "btn-outline", tt = "btn-dash", nt = "btn-soft", st = "btn-ghost", et = "btn-link", ot = "btn-xs", ct = "btn-sm", rt = "btn-md", at = "btn-lg", it = "btn-xl", dt = "btn-active", lt = "btn-square", mt = "btn-circle", bt = "btn-wide", ut = "btn-block", ft = "loading", Bt = "loading-spinner", ht = F(
|
|
6
|
+
({
|
|
7
|
+
children: c,
|
|
8
|
+
color: g,
|
|
9
|
+
variant: d,
|
|
10
|
+
size: C,
|
|
11
|
+
active: k = !1,
|
|
12
|
+
loading: t = !1,
|
|
13
|
+
shape: l,
|
|
14
|
+
noAnimation: S = !1,
|
|
15
|
+
icon: r,
|
|
16
|
+
iconPlacement: x,
|
|
17
|
+
iconPosition: v,
|
|
18
|
+
danger: w = !1,
|
|
19
|
+
pressed: m,
|
|
20
|
+
className: D = "",
|
|
21
|
+
"data-testid": b,
|
|
22
|
+
...a
|
|
23
|
+
}, u) => {
|
|
24
|
+
const { componentSize: z } = M(), i = C ?? z ?? "md", f = w ? "error" : g, n = x ?? v ?? "start", N = {
|
|
25
|
+
primary: R,
|
|
26
|
+
secondary: H,
|
|
27
|
+
accent: J,
|
|
28
|
+
info: Q,
|
|
29
|
+
success: U,
|
|
30
|
+
warning: V,
|
|
31
|
+
error: Y,
|
|
32
|
+
neutral: Z
|
|
33
|
+
}, P = {
|
|
34
|
+
solid: "",
|
|
35
|
+
// default, no extra class needed
|
|
36
|
+
outline: _,
|
|
37
|
+
dash: tt,
|
|
38
|
+
soft: nt,
|
|
39
|
+
ghost: st,
|
|
40
|
+
link: et
|
|
41
|
+
}, K = {
|
|
42
|
+
xs: ot,
|
|
43
|
+
sm: ct,
|
|
44
|
+
md: rt,
|
|
45
|
+
lg: at,
|
|
46
|
+
xl: it
|
|
47
|
+
}, L = {
|
|
48
|
+
square: lt,
|
|
49
|
+
circle: mt,
|
|
50
|
+
wide: bt,
|
|
51
|
+
block: ut,
|
|
52
|
+
round: "rounded-full"
|
|
53
|
+
}, B = [
|
|
54
|
+
O,
|
|
55
|
+
f && N[f],
|
|
56
|
+
d && P[d],
|
|
57
|
+
K[i],
|
|
58
|
+
k && dt,
|
|
59
|
+
l && L[l],
|
|
60
|
+
S && "no-animation",
|
|
61
|
+
D
|
|
62
|
+
].filter(Boolean).join(" "), T = c != null && c !== "" ? {
|
|
63
|
+
xs: n === "start" ? "mr-1" : "ml-1",
|
|
64
|
+
sm: n === "start" ? "mr-1" : "ml-1",
|
|
65
|
+
md: n === "start" ? "mr-1.5" : "ml-1.5",
|
|
66
|
+
lg: n === "start" ? "mr-2" : "ml-2",
|
|
67
|
+
xl: n === "start" ? "mr-2" : "ml-2"
|
|
68
|
+
}[i] : "", h = r && /* @__PURE__ */ o(G, { size: i, children: /* @__PURE__ */ o("span", { className: `inline-flex items-center ${T}`, "aria-hidden": "true", children: r }) }), y = /* @__PURE__ */ W(X, { children: [
|
|
69
|
+
t && /* @__PURE__ */ o("span", { className: `${ft} ${Bt}`, "aria-hidden": "true" }),
|
|
70
|
+
!t && r && n === "start" && h,
|
|
71
|
+
c,
|
|
72
|
+
!t && r && n === "end" && h
|
|
73
|
+
] });
|
|
74
|
+
if ("href" in a && a.href !== void 0) {
|
|
75
|
+
const { href: q, disabled: $, onKeyDown: A, onClick: E, ...I } = a, e = $ || t;
|
|
76
|
+
return /* @__PURE__ */ o(
|
|
77
|
+
"a",
|
|
78
|
+
{
|
|
79
|
+
ref: u,
|
|
80
|
+
href: e ? void 0 : q,
|
|
81
|
+
role: "button",
|
|
82
|
+
className: B,
|
|
83
|
+
"aria-disabled": e || void 0,
|
|
84
|
+
"aria-busy": t || void 0,
|
|
85
|
+
"aria-pressed": m,
|
|
86
|
+
tabIndex: e ? -1 : 0,
|
|
87
|
+
onKeyDown: (s) => {
|
|
88
|
+
s.key === " " && !e && (s.preventDefault(), s.currentTarget.click()), A?.(s);
|
|
89
|
+
},
|
|
90
|
+
onClick: (s) => {
|
|
91
|
+
if (e) {
|
|
92
|
+
s.preventDefault();
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
E?.(s);
|
|
96
|
+
},
|
|
97
|
+
"data-testid": b,
|
|
98
|
+
...I,
|
|
99
|
+
children: y
|
|
100
|
+
}
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
const { htmlType: j, ...p } = a;
|
|
104
|
+
return /* @__PURE__ */ o(
|
|
105
|
+
"button",
|
|
74
106
|
{
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
className:
|
|
78
|
-
"aria-
|
|
79
|
-
"aria-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
},
|
|
85
|
-
onClick: (s) => {
|
|
86
|
-
if (e) {
|
|
87
|
-
s.preventDefault();
|
|
88
|
-
return;
|
|
89
|
-
}
|
|
90
|
-
q?.(s);
|
|
91
|
-
},
|
|
92
|
-
...$,
|
|
93
|
-
children: B
|
|
107
|
+
ref: u,
|
|
108
|
+
type: j ?? "button",
|
|
109
|
+
className: B,
|
|
110
|
+
"aria-busy": t || void 0,
|
|
111
|
+
"aria-pressed": m,
|
|
112
|
+
disabled: t || p.disabled,
|
|
113
|
+
"data-testid": b,
|
|
114
|
+
...p,
|
|
115
|
+
children: y
|
|
94
116
|
}
|
|
95
117
|
);
|
|
96
118
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
"button",
|
|
100
|
-
{
|
|
101
|
-
type: K ?? "button",
|
|
102
|
-
className: u,
|
|
103
|
-
"aria-busy": n || void 0,
|
|
104
|
-
"aria-pressed": b,
|
|
105
|
-
disabled: n || h.disabled,
|
|
106
|
-
...h,
|
|
107
|
-
children: B
|
|
108
|
-
}
|
|
109
|
-
);
|
|
110
|
-
};
|
|
119
|
+
);
|
|
120
|
+
ht.displayName = "Button";
|
|
111
121
|
export {
|
|
112
|
-
|
|
122
|
+
ht as Button
|
|
113
123
|
};
|
|
114
124
|
//# sourceMappingURL=Button.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Button.js","sources":["../../src/components/Button.tsx"],"sourcesContent":["import React from 'react'\nimport { SizeProvider } from '../contexts/SizeContext'\nimport { useConfig } from '../providers/ConfigProvider'\n\n// DaisyUI classes\nconst dBtn = 'btn'\nconst dBtnPrimary = 'btn-primary'\nconst dBtnSecondary = 'btn-secondary'\nconst dBtnAccent = 'btn-accent'\nconst dBtnInfo = 'btn-info'\nconst dBtnSuccess = 'btn-success'\nconst dBtnWarning = 'btn-warning'\nconst dBtnError = 'btn-error'\nconst dBtnNeutral = 'btn-neutral'\nconst dBtnOutline = 'btn-outline'\nconst dBtnDash = 'btn-dash'\nconst dBtnSoft = 'btn-soft'\nconst dBtnGhost = 'btn-ghost'\nconst dBtnLink = 'btn-link'\nconst dBtnXs = 'btn-xs'\nconst dBtnSm = 'btn-sm'\nconst dBtnLg = 'btn-lg'\nconst dBtnXl = 'btn-xl'\nconst dBtnActive = 'btn-active'\nconst dBtnSquare = 'btn-square'\nconst dBtnCircle = 'btn-circle'\nconst dBtnWide = 'btn-wide'\nconst dBtnBlock = 'btn-block'\nconst dLoading = 'loading'\nconst dLoadingSpinner = 'loading-spinner'\n\ntype BaseButtonProps = {\n /** Button color */\n color?: 'primary' | 'secondary' | 'accent' | 'info' | 'success' | 'warning' | 'error' | 'neutral'\n /** Button style variant */\n variant?: 'solid' | 'outline' | 'dash' | 'soft' | 'ghost' | 'link'\n /** Button size */\n size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'\n /** Active/pressed visual state */\n active?: boolean\n /** Show loading spinner and disable button */\n loading?: boolean\n /** Button shape */\n shape?: 'square' | 'circle' | 'wide' | 'block' | 'round'\n /** Disable click animation */\n noAnimation?: boolean\n /** Icon element to display */\n icon?: React.ReactNode\n /** Position of the icon */\n iconPosition?: 'start' | 'end'\n /** Applies error/danger styling (shorthand for color=\"error\") */\n danger?: boolean\n /** Toggle button pressed state (sets aria-pressed) */\n pressed?: boolean\n}\n\ntype ButtonAsButton = BaseButtonProps &\n Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'type'> & {\n href?: undefined\n htmlType?: 'button' | 'submit' | 'reset'\n }\n\ntype ButtonAsAnchor = BaseButtonProps &\n Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, 'type'> & {\n href: string\n htmlType?: undefined\n /** Disable the link button */\n disabled?: boolean\n }\n\nexport type ButtonProps = ButtonAsButton | ButtonAsAnchor\n\nexport const Button: React.FC<ButtonProps> = ({\n children,\n color,\n variant,\n size,\n active = false,\n loading = false,\n shape,\n noAnimation = false,\n icon,\n iconPosition = 'start',\n danger = false,\n pressed,\n className = '',\n ...props\n}) => {\n const { componentSize } = useConfig()\n const effectiveSize = size ?? componentSize ?? 'md'\n // danger prop is a shorthand for color=\"error\"\n const effectiveColor = danger ? 'error' : color\n\n const colorClasses = {\n primary: dBtnPrimary,\n secondary: dBtnSecondary,\n accent: dBtnAccent,\n info: dBtnInfo,\n success: dBtnSuccess,\n warning: dBtnWarning,\n error: dBtnError,\n neutral: dBtnNeutral,\n }\n\n const variantClasses = {\n solid: '', // default, no extra class needed\n outline: dBtnOutline,\n dash: dBtnDash,\n soft: dBtnSoft,\n ghost: dBtnGhost,\n link: dBtnLink,\n }\n\n const sizeClasses = {\n xs: dBtnXs,\n sm: dBtnSm,\n md: '',\n lg: dBtnLg,\n xl: dBtnXl,\n }\n\n const shapeClasses = {\n square: dBtnSquare,\n circle: dBtnCircle,\n wide: dBtnWide,\n block: dBtnBlock,\n round: 'rounded-full',\n }\n\n const classes = [\n dBtn,\n effectiveColor && colorClasses[effectiveColor],\n variant && variantClasses[variant],\n sizeClasses[effectiveSize],\n active && dBtnActive,\n shape && shapeClasses[shape],\n noAnimation && 'no-animation',\n className,\n ]\n .filter(Boolean)\n .join(' ')\n\n // Determine icon spacing based on whether there's text content and button size\n const hasChildren = children !== undefined && children !== null && children !== ''\n const spacingBySize = {\n xs: iconPosition === 'start' ? 'mr-1' : 'ml-1',\n sm: iconPosition === 'start' ? 'mr-1' : 'ml-1',\n md: iconPosition === 'start' ? 'mr-1.5' : 'ml-1.5',\n lg: iconPosition === 'start' ? 'mr-2' : 'ml-2',\n xl: iconPosition === 'start' ? 'mr-2' : 'ml-2',\n }\n const iconSpacing = hasChildren ? spacingBySize[effectiveSize] : ''\n\n const iconElement = icon && (\n <SizeProvider size={effectiveSize}>\n <span className={`inline-flex items-center ${iconSpacing}`} aria-hidden=\"true\">\n {icon}\n </span>\n </SizeProvider>\n )\n\n const content = (\n <>\n {loading && <span className={`${dLoading} ${dLoadingSpinner}`} aria-hidden=\"true\"></span>}\n {!loading && icon && iconPosition === 'start' && iconElement}\n {children}\n {!loading && icon && iconPosition === 'end' && iconElement}\n </>\n )\n\n if ('href' in props && props.href !== undefined) {\n const { href, disabled, onKeyDown, onClick, ...anchorProps } = props as ButtonAsAnchor & {\n onKeyDown?: React.KeyboardEventHandler<HTMLAnchorElement>\n onClick?: React.MouseEventHandler<HTMLAnchorElement>\n }\n const isDisabled = disabled || loading\n\n // Handle Space key for anchor buttons (links only respond to Enter natively)\n const handleKeyDown = (event: React.KeyboardEvent<HTMLAnchorElement>) => {\n if (event.key === ' ' && !isDisabled) {\n event.preventDefault()\n event.currentTarget.click()\n }\n onKeyDown?.(event)\n }\n\n // Prevent click when disabled\n const handleClick = (event: React.MouseEvent<HTMLAnchorElement>) => {\n if (isDisabled) {\n event.preventDefault()\n return\n }\n onClick?.(event)\n }\n\n return (\n <a\n href={isDisabled ? undefined : href}\n role=\"button\"\n className={classes}\n aria-disabled={isDisabled || undefined}\n aria-busy={loading || undefined}\n aria-pressed={pressed}\n tabIndex={isDisabled ? -1 : 0}\n onKeyDown={handleKeyDown}\n onClick={handleClick}\n {...anchorProps}\n >\n {content}\n </a>\n )\n }\n\n const { htmlType, ...buttonProps } = props as Omit<ButtonAsButton, keyof BaseButtonProps>\n const buttonType: 'button' | 'submit' | 'reset' = htmlType ?? 'button'\n return (\n <button\n type={buttonType}\n className={classes}\n aria-busy={loading || undefined}\n aria-pressed={pressed}\n disabled={loading || buttonProps.disabled}\n {...buttonProps}\n >\n {content}\n </button>\n )\n}\n"],"names":["dBtn","dBtnPrimary","dBtnSecondary","dBtnAccent","dBtnInfo","dBtnSuccess","dBtnWarning","dBtnError","dBtnNeutral","dBtnOutline","dBtnDash","dBtnSoft","dBtnGhost","dBtnLink","dBtnXs","dBtnSm","dBtnLg","dBtnXl","dBtnActive","dBtnSquare","dBtnCircle","dBtnWide","dBtnBlock","dLoading","dLoadingSpinner","Button","children","color","variant","size","active","loading","shape","noAnimation","icon","iconPosition","danger","pressed","className","props","componentSize","useConfig","effectiveSize","effectiveColor","colorClasses","variantClasses","sizeClasses","shapeClasses","classes","iconSpacing","iconElement","jsx","SizeProvider","content","jsxs","Fragment","href","disabled","onKeyDown","onClick","anchorProps","isDisabled","event","htmlType","buttonProps"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Button.js","sources":["../../src/components/Button.tsx"],"sourcesContent":["import React, { forwardRef } from 'react'\nimport { SizeProvider } from '../contexts/SizeContext'\nimport { useConfig } from '../providers/ConfigProvider'\n\n// DaisyUI classes\nconst dBtn = 'btn'\nconst dBtnPrimary = 'btn-primary'\nconst dBtnSecondary = 'btn-secondary'\nconst dBtnAccent = 'btn-accent'\nconst dBtnInfo = 'btn-info'\nconst dBtnSuccess = 'btn-success'\nconst dBtnWarning = 'btn-warning'\nconst dBtnError = 'btn-error'\nconst dBtnNeutral = 'btn-neutral'\nconst dBtnOutline = 'btn-outline'\nconst dBtnDash = 'btn-dash'\nconst dBtnSoft = 'btn-soft'\nconst dBtnGhost = 'btn-ghost'\nconst dBtnLink = 'btn-link'\nconst dBtnXs = 'btn-xs'\nconst dBtnSm = 'btn-sm'\nconst dBtnMd = 'btn-md'\nconst dBtnLg = 'btn-lg'\nconst dBtnXl = 'btn-xl'\nconst dBtnActive = 'btn-active'\nconst dBtnSquare = 'btn-square'\nconst dBtnCircle = 'btn-circle'\nconst dBtnWide = 'btn-wide'\nconst dBtnBlock = 'btn-block'\nconst dLoading = 'loading'\nconst dLoadingSpinner = 'loading-spinner'\n\ntype BaseButtonProps = {\n /** Button color */\n color?: 'primary' | 'secondary' | 'accent' | 'info' | 'success' | 'warning' | 'error' | 'neutral'\n /** Button style variant */\n variant?: 'solid' | 'outline' | 'dash' | 'soft' | 'ghost' | 'link'\n /** Button size */\n size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'\n /** Active/pressed visual state */\n active?: boolean\n /** Show loading spinner and disable button */\n loading?: boolean\n /** Button shape */\n shape?: 'square' | 'circle' | 'wide' | 'block' | 'round'\n /** Disable click animation */\n noAnimation?: boolean\n /** Icon element to display */\n icon?: React.ReactNode\n /** Position of the icon */\n iconPlacement?: 'start' | 'end'\n /** @deprecated Use iconPlacement instead */\n iconPosition?: 'start' | 'end'\n /** Applies error/danger styling (shorthand for color=\"error\") */\n danger?: boolean\n /** Toggle button pressed state (sets aria-pressed) */\n pressed?: boolean\n /** Test ID for testing */\n 'data-testid'?: string\n}\n\ntype ButtonAsButton = BaseButtonProps &\n Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'type'> & {\n href?: undefined\n htmlType?: 'button' | 'submit' | 'reset'\n }\n\ntype ButtonAsAnchor = BaseButtonProps &\n Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, 'type'> & {\n href: string\n htmlType?: undefined\n /** Disable the link button */\n disabled?: boolean\n }\n\nexport type ButtonProps = ButtonAsButton | ButtonAsAnchor\n\nexport const Button = forwardRef<HTMLButtonElement | HTMLAnchorElement, ButtonProps>(\n (\n {\n children,\n color,\n variant,\n size,\n active = false,\n loading = false,\n shape,\n noAnimation = false,\n icon,\n iconPlacement,\n iconPosition,\n danger = false,\n pressed,\n className = '',\n 'data-testid': testId,\n ...props\n },\n ref\n ) => {\n const { componentSize } = useConfig()\n const effectiveSize = size ?? componentSize ?? 'md'\n // danger prop is a shorthand for color=\"error\"\n const effectiveColor = danger ? 'error' : color\n // iconPlacement takes precedence over deprecated iconPosition\n const effectiveIconPlacement = iconPlacement ?? iconPosition ?? 'start'\n\n const colorClasses = {\n primary: dBtnPrimary,\n secondary: dBtnSecondary,\n accent: dBtnAccent,\n info: dBtnInfo,\n success: dBtnSuccess,\n warning: dBtnWarning,\n error: dBtnError,\n neutral: dBtnNeutral,\n }\n\n const variantClasses = {\n solid: '', // default, no extra class needed\n outline: dBtnOutline,\n dash: dBtnDash,\n soft: dBtnSoft,\n ghost: dBtnGhost,\n link: dBtnLink,\n }\n\n const sizeClasses = {\n xs: dBtnXs,\n sm: dBtnSm,\n md: dBtnMd,\n lg: dBtnLg,\n xl: dBtnXl,\n }\n\n const shapeClasses = {\n square: dBtnSquare,\n circle: dBtnCircle,\n wide: dBtnWide,\n block: dBtnBlock,\n round: 'rounded-full',\n }\n\n const classes = [\n dBtn,\n effectiveColor && colorClasses[effectiveColor],\n variant && variantClasses[variant],\n sizeClasses[effectiveSize],\n active && dBtnActive,\n shape && shapeClasses[shape],\n noAnimation && 'no-animation',\n className,\n ]\n .filter(Boolean)\n .join(' ')\n\n // Determine icon spacing based on whether there's text content and button size\n const hasChildren = children !== undefined && children !== null && children !== ''\n const spacingBySize = {\n xs: effectiveIconPlacement === 'start' ? 'mr-1' : 'ml-1',\n sm: effectiveIconPlacement === 'start' ? 'mr-1' : 'ml-1',\n md: effectiveIconPlacement === 'start' ? 'mr-1.5' : 'ml-1.5',\n lg: effectiveIconPlacement === 'start' ? 'mr-2' : 'ml-2',\n xl: effectiveIconPlacement === 'start' ? 'mr-2' : 'ml-2',\n }\n const iconSpacing = hasChildren ? spacingBySize[effectiveSize] : ''\n\n const iconElement = icon && (\n <SizeProvider size={effectiveSize}>\n <span className={`inline-flex items-center ${iconSpacing}`} aria-hidden=\"true\">\n {icon}\n </span>\n </SizeProvider>\n )\n\n const content = (\n <>\n {loading && <span className={`${dLoading} ${dLoadingSpinner}`} aria-hidden=\"true\"></span>}\n {!loading && icon && effectiveIconPlacement === 'start' && iconElement}\n {children}\n {!loading && icon && effectiveIconPlacement === 'end' && iconElement}\n </>\n )\n\n if ('href' in props && props.href !== undefined) {\n const { href, disabled, onKeyDown, onClick, ...anchorProps } = props as ButtonAsAnchor & {\n onKeyDown?: React.KeyboardEventHandler<HTMLAnchorElement>\n onClick?: React.MouseEventHandler<HTMLAnchorElement>\n }\n const isDisabled = disabled || loading\n\n // Handle Space key for anchor buttons (links only respond to Enter natively)\n const handleKeyDown = (event: React.KeyboardEvent<HTMLAnchorElement>) => {\n if (event.key === ' ' && !isDisabled) {\n event.preventDefault()\n event.currentTarget.click()\n }\n onKeyDown?.(event)\n }\n\n // Prevent click when disabled\n const handleClick = (event: React.MouseEvent<HTMLAnchorElement>) => {\n if (isDisabled) {\n event.preventDefault()\n return\n }\n onClick?.(event)\n }\n\n return (\n <a\n ref={ref as React.Ref<HTMLAnchorElement>}\n href={isDisabled ? undefined : href}\n role=\"button\"\n className={classes}\n aria-disabled={isDisabled || undefined}\n aria-busy={loading || undefined}\n aria-pressed={pressed}\n tabIndex={isDisabled ? -1 : 0}\n onKeyDown={handleKeyDown}\n onClick={handleClick}\n data-testid={testId}\n {...anchorProps}\n >\n {content}\n </a>\n )\n }\n\n const { htmlType, ...buttonProps } = props as Omit<ButtonAsButton, keyof BaseButtonProps>\n const buttonType: 'button' | 'submit' | 'reset' = htmlType ?? 'button'\n return (\n <button\n ref={ref as React.Ref<HTMLButtonElement>}\n type={buttonType}\n className={classes}\n aria-busy={loading || undefined}\n aria-pressed={pressed}\n disabled={loading || buttonProps.disabled}\n data-testid={testId}\n {...buttonProps}\n >\n {content}\n </button>\n )\n }\n)\n\nButton.displayName = 'Button'\n"],"names":["dBtn","dBtnPrimary","dBtnSecondary","dBtnAccent","dBtnInfo","dBtnSuccess","dBtnWarning","dBtnError","dBtnNeutral","dBtnOutline","dBtnDash","dBtnSoft","dBtnGhost","dBtnLink","dBtnXs","dBtnSm","dBtnMd","dBtnLg","dBtnXl","dBtnActive","dBtnSquare","dBtnCircle","dBtnWide","dBtnBlock","dLoading","dLoadingSpinner","Button","forwardRef","children","color","variant","size","active","loading","shape","noAnimation","icon","iconPlacement","iconPosition","danger","pressed","className","testId","props","ref","componentSize","useConfig","effectiveSize","effectiveColor","effectiveIconPlacement","colorClasses","variantClasses","sizeClasses","shapeClasses","classes","iconSpacing","iconElement","jsx","SizeProvider","content","jsxs","Fragment","href","disabled","onKeyDown","onClick","anchorProps","isDisabled","event","htmlType","buttonProps"],"mappings":"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"}
|