asterui 0.12.58 → 0.12.59

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/dist/components/Autocomplete.js +1 -1
  2. package/dist/components/Autocomplete.js.map +1 -1
  3. package/dist/components/Button.js +1 -1
  4. package/dist/components/Button.js.map +1 -1
  5. package/dist/components/Checkbox.js +1 -1
  6. package/dist/components/Checkbox.js.map +1 -1
  7. package/dist/components/ColorPicker.js +1 -1
  8. package/dist/components/ColorPicker.js.map +1 -1
  9. package/dist/components/CopyButton.js +1 -1
  10. package/dist/components/CopyButton.js.map +1 -1
  11. package/dist/components/Countdown.js +1 -1
  12. package/dist/components/Countdown.js.map +1 -1
  13. package/dist/components/DatePicker.js +1 -1
  14. package/dist/components/DatePicker.js.map +1 -1
  15. package/dist/components/Dock.js +1 -1
  16. package/dist/components/Dock.js.map +1 -1
  17. package/dist/components/Empty.js +1 -1
  18. package/dist/components/Empty.js.map +1 -1
  19. package/dist/components/FileInput.js +1 -1
  20. package/dist/components/FileInput.js.map +1 -1
  21. package/dist/components/Filter.js +1 -1
  22. package/dist/components/Filter.js.map +1 -1
  23. package/dist/components/Form.js +1 -1
  24. package/dist/components/Form.js.map +1 -1
  25. package/dist/components/Input.js +1 -1
  26. package/dist/components/Input.js.map +1 -1
  27. package/dist/components/InputNumber.js +1 -1
  28. package/dist/components/InputNumber.js.map +1 -1
  29. package/dist/components/List.js +1 -1
  30. package/dist/components/List.js.map +1 -1
  31. package/dist/components/Loading.js +1 -1
  32. package/dist/components/Loading.js.map +1 -1
  33. package/dist/components/Modal.js +1 -1
  34. package/dist/components/Modal.js.map +1 -1
  35. package/dist/components/OTPInput.js +1 -1
  36. package/dist/components/OTPInput.js.map +1 -1
  37. package/dist/components/Pagination.js +1 -1
  38. package/dist/components/Pagination.js.map +1 -1
  39. package/dist/components/Popconfirm.js +1 -1
  40. package/dist/components/Popconfirm.js.map +1 -1
  41. package/dist/components/Radio.js +1 -1
  42. package/dist/components/Radio.js.map +1 -1
  43. package/dist/components/Range.js +1 -1
  44. package/dist/components/Range.js.map +1 -1
  45. package/dist/components/Rating.js +1 -1
  46. package/dist/components/Rating.js.map +1 -1
  47. package/dist/components/RichTextEditor.js +1 -1
  48. package/dist/components/RichTextEditor.js.map +1 -1
  49. package/dist/components/Segmented.js +1 -1
  50. package/dist/components/Segmented.js.map +1 -1
  51. package/dist/components/Select.js +1 -1
  52. package/dist/components/Select.js.map +1 -1
  53. package/dist/components/Table.d.ts +19 -0
  54. package/dist/components/Table.js +348 -310
  55. package/dist/components/Table.js.map +1 -1
  56. package/dist/components/Tabs.js +1 -1
  57. package/dist/components/Tabs.js.map +1 -1
  58. package/dist/components/Textarea.js +1 -1
  59. package/dist/components/Textarea.js.map +1 -1
  60. package/dist/components/ThemeController.js +1 -1
  61. package/dist/components/ThemeController.js.map +1 -1
  62. package/dist/components/TimePicker.js +1 -1
  63. package/dist/components/TimePicker.js.map +1 -1
  64. package/dist/components/Toggle.js +1 -1
  65. package/dist/components/Toggle.js.map +1 -1
  66. package/dist/hooks/useTheme.d.ts +1 -1
  67. package/dist/hooks/useTheme.js +1 -1
  68. package/dist/hooks/useTheme.js.map +1 -1
  69. package/dist/index.d.ts +4 -4
  70. package/dist/index.js +2 -2
  71. package/dist/providers/ConfigProvider.js.map +1 -0
  72. package/dist/providers/ThemeProvider.js.map +1 -0
  73. package/package.json +1 -1
  74. package/dist/components/ConfigProvider.js.map +0 -1
  75. package/dist/components/ThemeProvider.js.map +0 -1
  76. /package/dist/{components → providers}/ConfigProvider.d.ts +0 -0
  77. /package/dist/{components → providers}/ConfigProvider.js +0 -0
  78. /package/dist/{components → providers}/ThemeProvider.d.ts +0 -0
  79. /package/dist/{components → providers}/ThemeProvider.js +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"TimePicker.js","sources":["../../src/components/TimePicker.tsx"],"sourcesContent":["import React, { useState, useRef, useEffect, forwardRef, useCallback, useId } from 'react'\nimport { Input } from './Input'\nimport { useConfig } from './ConfigProvider'\n\n// DaisyUI classes\nconst dBtn = 'btn'\nconst dBtnGhost = 'btn-ghost'\nconst dBtnPrimary = 'btn-primary'\nconst dBtnXs = 'btn-xs'\nconst dBtnSm = 'btn-sm'\nconst dBtnCircle = 'btn-circle'\nconst dInputError = 'input-error'\nconst dInputWarning = 'input-warning'\n\nexport interface TimePickerProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange' | 'defaultValue'> {\n value?: Date | null\n defaultValue?: Date | null\n onChange?: (date: Date | null) => void\n format?: '12' | '24'\n placeholder?: string\n disabled?: boolean\n size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'\n showSeconds?: boolean\n allowClear?: boolean\n open?: boolean\n onOpenChange?: (open: boolean) => void\n hourStep?: number\n minuteStep?: number\n secondStep?: number\n status?: 'error' | 'warning'\n 'data-testid'?: string\n}\n\nfunction formatTime(date: Date | null, format: '12' | '24' = '24', showSeconds: boolean = false): string {\n if (!date) return ''\n\n let hours = date.getHours()\n const minutes = String(date.getMinutes()).padStart(2, '0')\n const seconds = String(date.getSeconds()).padStart(2, '0')\n\n if (format === '12') {\n const period = hours >= 12 ? 'PM' : 'AM'\n hours = hours % 12 || 12\n const timeStr = showSeconds\n ? `${hours}:${minutes}:${seconds} ${period}`\n : `${hours}:${minutes} ${period}`\n return timeStr\n }\n\n const hoursStr = String(hours).padStart(2, '0')\n return showSeconds ? `${hoursStr}:${minutes}:${seconds}` : `${hoursStr}:${minutes}`\n}\n\nexport const TimePicker = forwardRef<HTMLDivElement, TimePickerProps>(({\n value,\n defaultValue,\n onChange,\n format = '24',\n placeholder = 'Select time',\n disabled = false,\n className,\n size,\n showSeconds = false,\n allowClear = true,\n open: controlledOpen,\n onOpenChange,\n hourStep = 1,\n minuteStep = 1,\n secondStep = 1,\n status,\n 'data-testid': testId,\n ...rest\n}, ref) => {\n const { componentSize } = useConfig()\n const effectiveSize = size ?? componentSize ?? 'md'\n const [selectedTime, setSelectedTime] = useState<Date | null>(\n value !== undefined ? value : defaultValue || null\n )\n const [internalOpen, setInternalOpen] = useState(false)\n const isOpen = controlledOpen !== undefined ? controlledOpen : internalOpen\n const [hours, setHours] = useState(selectedTime ? selectedTime.getHours() : 0)\n const [minutes, setMinutes] = useState(selectedTime ? selectedTime.getMinutes() : 0)\n const [seconds, setSeconds] = useState(selectedTime ? selectedTime.getSeconds() : 0)\n const [period, setPeriod] = useState<'AM' | 'PM'>(\n selectedTime && selectedTime.getHours() >= 12 ? 'PM' : 'AM'\n )\n const [focusedColumn, setFocusedColumn] = useState<'hour' | 'minute' | 'second' | 'period'>('hour')\n\n const containerRef = useRef<HTMLDivElement>(null)\n const dropdownRef = useRef<HTMLDivElement>(null)\n const uniqueId = useId()\n const baseTestId = testId || 'timepicker'\n\n useEffect(() => {\n if (value !== undefined) {\n setSelectedTime(value)\n if (value) {\n setHours(value.getHours())\n setMinutes(value.getMinutes())\n setSeconds(value.getSeconds())\n setPeriod(value.getHours() >= 12 ? 'PM' : 'AM')\n }\n }\n }, [value])\n\n const setOpen = useCallback((newOpen: boolean) => {\n if (controlledOpen === undefined) {\n setInternalOpen(newOpen)\n }\n onOpenChange?.(newOpen)\n }, [controlledOpen, onOpenChange])\n\n useEffect(() => {\n function handleClickOutside(event: MouseEvent) {\n if (containerRef.current && !containerRef.current.contains(event.target as Node)) {\n setOpen(false)\n }\n }\n\n if (isOpen) {\n document.addEventListener('mousedown', handleClickOutside)\n return () => document.removeEventListener('mousedown', handleClickOutside)\n }\n }, [isOpen, setOpen])\n\n // Focus trap and keyboard navigation\n useEffect(() => {\n if (!isOpen) return\n\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n setOpen(false)\n return\n }\n\n if (e.key === 'Tab') {\n // Allow tab to cycle through columns\n return\n }\n\n if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {\n e.preventDefault()\n const delta = e.key === 'ArrowUp' ? -1 : 1\n\n if (focusedColumn === 'hour') {\n const maxHour = format === '12' ? 12 : 23\n const minHour = format === '12' ? 1 : 0\n let newHour = hours + (delta * hourStep)\n if (newHour > maxHour) newHour = minHour\n if (newHour < minHour) newHour = maxHour\n handleHourChange(newHour)\n } else if (focusedColumn === 'minute') {\n let newMinute = minutes + (delta * minuteStep)\n if (newMinute > 59) newMinute = 0\n if (newMinute < 0) newMinute = 59\n handleMinuteChange(newMinute)\n } else if (focusedColumn === 'second') {\n let newSecond = seconds + (delta * secondStep)\n if (newSecond > 59) newSecond = 0\n if (newSecond < 0) newSecond = 59\n handleSecondChange(newSecond)\n } else if (focusedColumn === 'period') {\n handlePeriodChange(period === 'AM' ? 'PM' : 'AM')\n }\n }\n\n if (e.key === 'ArrowLeft' || e.key === 'ArrowRight') {\n e.preventDefault()\n const columns: Array<'hour' | 'minute' | 'second' | 'period'> = ['hour', 'minute']\n if (showSeconds) columns.push('second')\n if (format === '12') columns.push('period')\n\n const currentIndex = columns.indexOf(focusedColumn)\n const delta = e.key === 'ArrowLeft' ? -1 : 1\n let newIndex = currentIndex + delta\n if (newIndex < 0) newIndex = columns.length - 1\n if (newIndex >= columns.length) newIndex = 0\n setFocusedColumn(columns[newIndex])\n }\n\n if (e.key === 'Enter') {\n setOpen(false)\n }\n }\n\n document.addEventListener('keydown', handleKeyDown)\n return () => document.removeEventListener('keydown', handleKeyDown)\n }, [isOpen, focusedColumn, hours, minutes, seconds, period, format, showSeconds, hourStep, minuteStep, secondStep, setOpen])\n\n const handleClear = useCallback((e: React.MouseEvent) => {\n e.stopPropagation()\n setSelectedTime(null)\n setHours(0)\n setMinutes(0)\n setSeconds(0)\n setPeriod('AM')\n onChange?.(null)\n }, [onChange])\n\n const handleTimeChange = (newHours: number, newMinutes: number, newSeconds: number) => {\n const now = new Date()\n const newTime = new Date(\n now.getFullYear(),\n now.getMonth(),\n now.getDate(),\n newHours,\n newMinutes,\n newSeconds\n )\n setSelectedTime(newTime)\n onChange?.(newTime)\n }\n\n const handleHourChange = (newHour: number) => {\n let actualHour = newHour\n if (format === '12') {\n actualHour = period === 'PM' ? (newHour % 12) + 12 : newHour % 12\n }\n setHours(actualHour)\n handleTimeChange(actualHour, minutes, seconds)\n }\n\n const handleMinuteChange = (newMinute: number) => {\n setMinutes(newMinute)\n handleTimeChange(hours, newMinute, seconds)\n }\n\n const handleSecondChange = (newSecond: number) => {\n setSeconds(newSecond)\n handleTimeChange(hours, minutes, newSecond)\n }\n\n const handlePeriodChange = (newPeriod: 'AM' | 'PM') => {\n setPeriod(newPeriod)\n const newHours = newPeriod === 'PM'\n ? (hours % 12) + 12\n : hours % 12\n setHours(newHours)\n handleTimeChange(newHours, minutes, seconds)\n }\n\n const renderTimeColumn = (\n columnType: 'hour' | 'minute' | 'second',\n label: string,\n maxValue: number,\n currentValue: number,\n onChangeValue: (value: number) => void,\n step: number = 1,\n start: number = 0\n ) => {\n const items: number[] = []\n for (let i = start; i <= maxValue; i += step) {\n items.push(i)\n }\n const listboxId = `${uniqueId}-${columnType}-listbox`\n const isFocused = focusedColumn === columnType\n\n return (\n <div\n className=\"flex flex-col w-16\"\n role=\"listbox\"\n aria-label={`Select ${label.toLowerCase()}`}\n id={listboxId}\n data-testid={`${baseTestId}-${columnType}-column`}\n tabIndex={0}\n onFocus={() => setFocusedColumn(columnType)}\n >\n <div className=\"text-xs font-semibold text-center text-base-content/60 py-2\" aria-hidden=\"true\">\n {label}\n </div>\n <div className=\"overflow-y-auto max-h-48\">\n {items.map((item) => {\n const isSelected = currentValue === item\n return (\n <button\n key={item}\n type=\"button\"\n role=\"option\"\n aria-selected={isSelected}\n onClick={() => onChangeValue(item)}\n data-testid={`${baseTestId}-${columnType}-${item}`}\n className={[\n 'w-full px-4 py-2 text-center hover:bg-base-200 transition-colors',\n isSelected ? 'bg-primary text-primary-content' : '',\n isFocused && isSelected ? 'ring-2 ring-primary ring-offset-1' : ''\n ].filter(Boolean).join(' ')}\n >\n {String(item).padStart(2, '0')}\n </button>\n )\n })}\n </div>\n </div>\n )\n }\n\n const displayHours = format === '12' ? (hours % 12 || 12) : hours\n\n const statusClasses = {\n error: dInputError,\n warning: dInputWarning,\n }\n\n return (\n <div\n ref={(node) => {\n containerRef.current = node\n if (typeof ref === 'function') ref(node)\n else if (ref) ref.current = node\n }}\n className={['relative', className].filter(Boolean).join(' ')}\n data-testid={baseTestId}\n data-state={isOpen ? 'open' : 'closed'}\n {...rest}\n >\n <div className=\"relative\">\n <Input\n value={formatTime(selectedTime, format, showSeconds)}\n placeholder={placeholder}\n disabled={disabled}\n size={effectiveSize}\n readOnly\n onClick={() => !disabled && setOpen(!isOpen)}\n className={['cursor-pointer pr-8', status ? statusClasses[status] : ''].filter(Boolean).join(' ')}\n aria-haspopup=\"listbox\"\n aria-expanded={isOpen}\n aria-controls={isOpen ? `${uniqueId}-dropdown` : undefined}\n data-testid={`${baseTestId}-input`}\n />\n {allowClear && selectedTime && !disabled && (\n <button\n type=\"button\"\n onClick={handleClear}\n className={`absolute right-2 top-1/2 -translate-y-1/2 ${dBtn} ${dBtnGhost} ${dBtnXs} ${dBtnCircle}`}\n aria-label=\"Clear time\"\n data-testid={`${baseTestId}-clear`}\n >\n <svg className=\"w-3 h-3\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n )}\n </div>\n\n {isOpen && (\n <div\n ref={dropdownRef}\n id={`${uniqueId}-dropdown`}\n className=\"absolute top-full left-0 mt-2 bg-base-100 border border-base-300 rounded-lg shadow-xl z-[9999] w-fit\"\n role=\"dialog\"\n aria-label=\"Time picker\"\n data-testid={`${baseTestId}-dropdown`}\n >\n <div className=\"flex divide-x divide-base-300\">\n {renderTimeColumn(\n 'hour',\n 'Hour',\n format === '12' ? 12 : 23,\n displayHours,\n handleHourChange,\n hourStep,\n format === '12' ? 1 : 0\n )}\n\n {renderTimeColumn('minute', 'Min', 59, minutes, handleMinuteChange, minuteStep)}\n\n {showSeconds && renderTimeColumn('second', 'Sec', 59, seconds, handleSecondChange, secondStep)}\n\n {format === '12' && (\n <div\n className=\"flex flex-col w-16\"\n role=\"listbox\"\n aria-label=\"Select period\"\n data-testid={`${baseTestId}-period-column`}\n tabIndex={0}\n onFocus={() => setFocusedColumn('period')}\n >\n <div className=\"text-xs font-semibold text-center text-base-content/60 py-2\" aria-hidden=\"true\">\n Period\n </div>\n <div className=\"flex flex-col p-2 gap-2\">\n <button\n type=\"button\"\n role=\"option\"\n aria-selected={period === 'AM'}\n onClick={() => handlePeriodChange('AM')}\n data-testid={`${baseTestId}-period-am`}\n className={[\n dBtn, dBtnSm,\n period === 'AM' ? dBtnPrimary : dBtnGhost\n ].join(' ')}\n >\n AM\n </button>\n <button\n type=\"button\"\n role=\"option\"\n aria-selected={period === 'PM'}\n onClick={() => handlePeriodChange('PM')}\n data-testid={`${baseTestId}-period-pm`}\n className={[\n dBtn, dBtnSm,\n period === 'PM' ? dBtnPrimary : dBtnGhost\n ].join(' ')}\n >\n PM\n </button>\n </div>\n </div>\n )}\n </div>\n\n <div className=\"flex justify-end gap-2 p-3 border-t border-base-300\">\n <button\n type=\"button\"\n onClick={() => {\n const now = new Date()\n setHours(now.getHours())\n setMinutes(now.getMinutes())\n setSeconds(now.getSeconds())\n setPeriod(now.getHours() >= 12 ? 'PM' : 'AM')\n handleTimeChange(now.getHours(), now.getMinutes(), now.getSeconds())\n }}\n className={`${dBtn} ${dBtnGhost} ${dBtnSm}`}\n data-testid={`${baseTestId}-now`}\n >\n Now\n </button>\n <button\n type=\"button\"\n onClick={() => setOpen(false)}\n className={`${dBtn} ${dBtnPrimary} ${dBtnSm}`}\n data-testid={`${baseTestId}-ok`}\n >\n OK\n </button>\n </div>\n </div>\n )}\n </div>\n )\n})\n\nTimePicker.displayName = 'TimePicker'\n"],"names":["dBtn","dBtnGhost","dBtnPrimary","dBtnXs","dBtnSm","dBtnCircle","dInputError","dInputWarning","formatTime","date","format","showSeconds","hours","minutes","seconds","period","hoursStr","TimePicker","forwardRef","value","defaultValue","onChange","placeholder","disabled","className","size","allowClear","controlledOpen","onOpenChange","hourStep","minuteStep","secondStep","status","testId","rest","ref","componentSize","useConfig","effectiveSize","selectedTime","setSelectedTime","useState","internalOpen","setInternalOpen","isOpen","setHours","setMinutes","setSeconds","setPeriod","focusedColumn","setFocusedColumn","containerRef","useRef","dropdownRef","uniqueId","useId","baseTestId","useEffect","setOpen","useCallback","newOpen","handleClickOutside","event","handleKeyDown","e","delta","maxHour","minHour","newHour","handleHourChange","newMinute","handleMinuteChange","newSecond","handleSecondChange","handlePeriodChange","columns","currentIndex","newIndex","handleClear","handleTimeChange","newHours","newMinutes","newSeconds","now","newTime","actualHour","newPeriod","renderTimeColumn","columnType","label","maxValue","currentValue","onChangeValue","step","start","items","i","listboxId","isFocused","jsxs","jsx","item","isSelected","displayHours","statusClasses","node","Input"],"mappings":"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"}
1
+ {"version":3,"file":"TimePicker.js","sources":["../../src/components/TimePicker.tsx"],"sourcesContent":["import React, { useState, useRef, useEffect, forwardRef, useCallback, useId } from 'react'\nimport { Input } from './Input'\nimport { useConfig } from '../providers/ConfigProvider'\n\n// DaisyUI classes\nconst dBtn = 'btn'\nconst dBtnGhost = 'btn-ghost'\nconst dBtnPrimary = 'btn-primary'\nconst dBtnXs = 'btn-xs'\nconst dBtnSm = 'btn-sm'\nconst dBtnCircle = 'btn-circle'\nconst dInputError = 'input-error'\nconst dInputWarning = 'input-warning'\n\nexport interface TimePickerProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange' | 'defaultValue'> {\n value?: Date | null\n defaultValue?: Date | null\n onChange?: (date: Date | null) => void\n format?: '12' | '24'\n placeholder?: string\n disabled?: boolean\n size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'\n showSeconds?: boolean\n allowClear?: boolean\n open?: boolean\n onOpenChange?: (open: boolean) => void\n hourStep?: number\n minuteStep?: number\n secondStep?: number\n status?: 'error' | 'warning'\n 'data-testid'?: string\n}\n\nfunction formatTime(date: Date | null, format: '12' | '24' = '24', showSeconds: boolean = false): string {\n if (!date) return ''\n\n let hours = date.getHours()\n const minutes = String(date.getMinutes()).padStart(2, '0')\n const seconds = String(date.getSeconds()).padStart(2, '0')\n\n if (format === '12') {\n const period = hours >= 12 ? 'PM' : 'AM'\n hours = hours % 12 || 12\n const timeStr = showSeconds\n ? `${hours}:${minutes}:${seconds} ${period}`\n : `${hours}:${minutes} ${period}`\n return timeStr\n }\n\n const hoursStr = String(hours).padStart(2, '0')\n return showSeconds ? `${hoursStr}:${minutes}:${seconds}` : `${hoursStr}:${minutes}`\n}\n\nexport const TimePicker = forwardRef<HTMLDivElement, TimePickerProps>(({\n value,\n defaultValue,\n onChange,\n format = '24',\n placeholder = 'Select time',\n disabled = false,\n className,\n size,\n showSeconds = false,\n allowClear = true,\n open: controlledOpen,\n onOpenChange,\n hourStep = 1,\n minuteStep = 1,\n secondStep = 1,\n status,\n 'data-testid': testId,\n ...rest\n}, ref) => {\n const { componentSize } = useConfig()\n const effectiveSize = size ?? componentSize ?? 'md'\n const [selectedTime, setSelectedTime] = useState<Date | null>(\n value !== undefined ? value : defaultValue || null\n )\n const [internalOpen, setInternalOpen] = useState(false)\n const isOpen = controlledOpen !== undefined ? controlledOpen : internalOpen\n const [hours, setHours] = useState(selectedTime ? selectedTime.getHours() : 0)\n const [minutes, setMinutes] = useState(selectedTime ? selectedTime.getMinutes() : 0)\n const [seconds, setSeconds] = useState(selectedTime ? selectedTime.getSeconds() : 0)\n const [period, setPeriod] = useState<'AM' | 'PM'>(\n selectedTime && selectedTime.getHours() >= 12 ? 'PM' : 'AM'\n )\n const [focusedColumn, setFocusedColumn] = useState<'hour' | 'minute' | 'second' | 'period'>('hour')\n\n const containerRef = useRef<HTMLDivElement>(null)\n const dropdownRef = useRef<HTMLDivElement>(null)\n const uniqueId = useId()\n const baseTestId = testId || 'timepicker'\n\n useEffect(() => {\n if (value !== undefined) {\n setSelectedTime(value)\n if (value) {\n setHours(value.getHours())\n setMinutes(value.getMinutes())\n setSeconds(value.getSeconds())\n setPeriod(value.getHours() >= 12 ? 'PM' : 'AM')\n }\n }\n }, [value])\n\n const setOpen = useCallback((newOpen: boolean) => {\n if (controlledOpen === undefined) {\n setInternalOpen(newOpen)\n }\n onOpenChange?.(newOpen)\n }, [controlledOpen, onOpenChange])\n\n useEffect(() => {\n function handleClickOutside(event: MouseEvent) {\n if (containerRef.current && !containerRef.current.contains(event.target as Node)) {\n setOpen(false)\n }\n }\n\n if (isOpen) {\n document.addEventListener('mousedown', handleClickOutside)\n return () => document.removeEventListener('mousedown', handleClickOutside)\n }\n }, [isOpen, setOpen])\n\n // Focus trap and keyboard navigation\n useEffect(() => {\n if (!isOpen) return\n\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n setOpen(false)\n return\n }\n\n if (e.key === 'Tab') {\n // Allow tab to cycle through columns\n return\n }\n\n if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {\n e.preventDefault()\n const delta = e.key === 'ArrowUp' ? -1 : 1\n\n if (focusedColumn === 'hour') {\n const maxHour = format === '12' ? 12 : 23\n const minHour = format === '12' ? 1 : 0\n let newHour = hours + (delta * hourStep)\n if (newHour > maxHour) newHour = minHour\n if (newHour < minHour) newHour = maxHour\n handleHourChange(newHour)\n } else if (focusedColumn === 'minute') {\n let newMinute = minutes + (delta * minuteStep)\n if (newMinute > 59) newMinute = 0\n if (newMinute < 0) newMinute = 59\n handleMinuteChange(newMinute)\n } else if (focusedColumn === 'second') {\n let newSecond = seconds + (delta * secondStep)\n if (newSecond > 59) newSecond = 0\n if (newSecond < 0) newSecond = 59\n handleSecondChange(newSecond)\n } else if (focusedColumn === 'period') {\n handlePeriodChange(period === 'AM' ? 'PM' : 'AM')\n }\n }\n\n if (e.key === 'ArrowLeft' || e.key === 'ArrowRight') {\n e.preventDefault()\n const columns: Array<'hour' | 'minute' | 'second' | 'period'> = ['hour', 'minute']\n if (showSeconds) columns.push('second')\n if (format === '12') columns.push('period')\n\n const currentIndex = columns.indexOf(focusedColumn)\n const delta = e.key === 'ArrowLeft' ? -1 : 1\n let newIndex = currentIndex + delta\n if (newIndex < 0) newIndex = columns.length - 1\n if (newIndex >= columns.length) newIndex = 0\n setFocusedColumn(columns[newIndex])\n }\n\n if (e.key === 'Enter') {\n setOpen(false)\n }\n }\n\n document.addEventListener('keydown', handleKeyDown)\n return () => document.removeEventListener('keydown', handleKeyDown)\n }, [isOpen, focusedColumn, hours, minutes, seconds, period, format, showSeconds, hourStep, minuteStep, secondStep, setOpen])\n\n const handleClear = useCallback((e: React.MouseEvent) => {\n e.stopPropagation()\n setSelectedTime(null)\n setHours(0)\n setMinutes(0)\n setSeconds(0)\n setPeriod('AM')\n onChange?.(null)\n }, [onChange])\n\n const handleTimeChange = (newHours: number, newMinutes: number, newSeconds: number) => {\n const now = new Date()\n const newTime = new Date(\n now.getFullYear(),\n now.getMonth(),\n now.getDate(),\n newHours,\n newMinutes,\n newSeconds\n )\n setSelectedTime(newTime)\n onChange?.(newTime)\n }\n\n const handleHourChange = (newHour: number) => {\n let actualHour = newHour\n if (format === '12') {\n actualHour = period === 'PM' ? (newHour % 12) + 12 : newHour % 12\n }\n setHours(actualHour)\n handleTimeChange(actualHour, minutes, seconds)\n }\n\n const handleMinuteChange = (newMinute: number) => {\n setMinutes(newMinute)\n handleTimeChange(hours, newMinute, seconds)\n }\n\n const handleSecondChange = (newSecond: number) => {\n setSeconds(newSecond)\n handleTimeChange(hours, minutes, newSecond)\n }\n\n const handlePeriodChange = (newPeriod: 'AM' | 'PM') => {\n setPeriod(newPeriod)\n const newHours = newPeriod === 'PM'\n ? (hours % 12) + 12\n : hours % 12\n setHours(newHours)\n handleTimeChange(newHours, minutes, seconds)\n }\n\n const renderTimeColumn = (\n columnType: 'hour' | 'minute' | 'second',\n label: string,\n maxValue: number,\n currentValue: number,\n onChangeValue: (value: number) => void,\n step: number = 1,\n start: number = 0\n ) => {\n const items: number[] = []\n for (let i = start; i <= maxValue; i += step) {\n items.push(i)\n }\n const listboxId = `${uniqueId}-${columnType}-listbox`\n const isFocused = focusedColumn === columnType\n\n return (\n <div\n className=\"flex flex-col w-16\"\n role=\"listbox\"\n aria-label={`Select ${label.toLowerCase()}`}\n id={listboxId}\n data-testid={`${baseTestId}-${columnType}-column`}\n tabIndex={0}\n onFocus={() => setFocusedColumn(columnType)}\n >\n <div className=\"text-xs font-semibold text-center text-base-content/60 py-2\" aria-hidden=\"true\">\n {label}\n </div>\n <div className=\"overflow-y-auto max-h-48\">\n {items.map((item) => {\n const isSelected = currentValue === item\n return (\n <button\n key={item}\n type=\"button\"\n role=\"option\"\n aria-selected={isSelected}\n onClick={() => onChangeValue(item)}\n data-testid={`${baseTestId}-${columnType}-${item}`}\n className={[\n 'w-full px-4 py-2 text-center hover:bg-base-200 transition-colors',\n isSelected ? 'bg-primary text-primary-content' : '',\n isFocused && isSelected ? 'ring-2 ring-primary ring-offset-1' : ''\n ].filter(Boolean).join(' ')}\n >\n {String(item).padStart(2, '0')}\n </button>\n )\n })}\n </div>\n </div>\n )\n }\n\n const displayHours = format === '12' ? (hours % 12 || 12) : hours\n\n const statusClasses = {\n error: dInputError,\n warning: dInputWarning,\n }\n\n return (\n <div\n ref={(node) => {\n containerRef.current = node\n if (typeof ref === 'function') ref(node)\n else if (ref) ref.current = node\n }}\n className={['relative', className].filter(Boolean).join(' ')}\n data-testid={baseTestId}\n data-state={isOpen ? 'open' : 'closed'}\n {...rest}\n >\n <div className=\"relative\">\n <Input\n value={formatTime(selectedTime, format, showSeconds)}\n placeholder={placeholder}\n disabled={disabled}\n size={effectiveSize}\n readOnly\n onClick={() => !disabled && setOpen(!isOpen)}\n className={['cursor-pointer pr-8', status ? statusClasses[status] : ''].filter(Boolean).join(' ')}\n aria-haspopup=\"listbox\"\n aria-expanded={isOpen}\n aria-controls={isOpen ? `${uniqueId}-dropdown` : undefined}\n data-testid={`${baseTestId}-input`}\n />\n {allowClear && selectedTime && !disabled && (\n <button\n type=\"button\"\n onClick={handleClear}\n className={`absolute right-2 top-1/2 -translate-y-1/2 ${dBtn} ${dBtnGhost} ${dBtnXs} ${dBtnCircle}`}\n aria-label=\"Clear time\"\n data-testid={`${baseTestId}-clear`}\n >\n <svg className=\"w-3 h-3\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n )}\n </div>\n\n {isOpen && (\n <div\n ref={dropdownRef}\n id={`${uniqueId}-dropdown`}\n className=\"absolute top-full left-0 mt-2 bg-base-100 border border-base-300 rounded-lg shadow-xl z-[9999] w-fit\"\n role=\"dialog\"\n aria-label=\"Time picker\"\n data-testid={`${baseTestId}-dropdown`}\n >\n <div className=\"flex divide-x divide-base-300\">\n {renderTimeColumn(\n 'hour',\n 'Hour',\n format === '12' ? 12 : 23,\n displayHours,\n handleHourChange,\n hourStep,\n format === '12' ? 1 : 0\n )}\n\n {renderTimeColumn('minute', 'Min', 59, minutes, handleMinuteChange, minuteStep)}\n\n {showSeconds && renderTimeColumn('second', 'Sec', 59, seconds, handleSecondChange, secondStep)}\n\n {format === '12' && (\n <div\n className=\"flex flex-col w-16\"\n role=\"listbox\"\n aria-label=\"Select period\"\n data-testid={`${baseTestId}-period-column`}\n tabIndex={0}\n onFocus={() => setFocusedColumn('period')}\n >\n <div className=\"text-xs font-semibold text-center text-base-content/60 py-2\" aria-hidden=\"true\">\n Period\n </div>\n <div className=\"flex flex-col p-2 gap-2\">\n <button\n type=\"button\"\n role=\"option\"\n aria-selected={period === 'AM'}\n onClick={() => handlePeriodChange('AM')}\n data-testid={`${baseTestId}-period-am`}\n className={[\n dBtn, dBtnSm,\n period === 'AM' ? dBtnPrimary : dBtnGhost\n ].join(' ')}\n >\n AM\n </button>\n <button\n type=\"button\"\n role=\"option\"\n aria-selected={period === 'PM'}\n onClick={() => handlePeriodChange('PM')}\n data-testid={`${baseTestId}-period-pm`}\n className={[\n dBtn, dBtnSm,\n period === 'PM' ? dBtnPrimary : dBtnGhost\n ].join(' ')}\n >\n PM\n </button>\n </div>\n </div>\n )}\n </div>\n\n <div className=\"flex justify-end gap-2 p-3 border-t border-base-300\">\n <button\n type=\"button\"\n onClick={() => {\n const now = new Date()\n setHours(now.getHours())\n setMinutes(now.getMinutes())\n setSeconds(now.getSeconds())\n setPeriod(now.getHours() >= 12 ? 'PM' : 'AM')\n handleTimeChange(now.getHours(), now.getMinutes(), now.getSeconds())\n }}\n className={`${dBtn} ${dBtnGhost} ${dBtnSm}`}\n data-testid={`${baseTestId}-now`}\n >\n Now\n </button>\n <button\n type=\"button\"\n onClick={() => setOpen(false)}\n className={`${dBtn} ${dBtnPrimary} ${dBtnSm}`}\n data-testid={`${baseTestId}-ok`}\n >\n OK\n </button>\n </div>\n </div>\n )}\n </div>\n )\n})\n\nTimePicker.displayName = 'TimePicker'\n"],"names":["dBtn","dBtnGhost","dBtnPrimary","dBtnXs","dBtnSm","dBtnCircle","dInputError","dInputWarning","formatTime","date","format","showSeconds","hours","minutes","seconds","period","hoursStr","TimePicker","forwardRef","value","defaultValue","onChange","placeholder","disabled","className","size","allowClear","controlledOpen","onOpenChange","hourStep","minuteStep","secondStep","status","testId","rest","ref","componentSize","useConfig","effectiveSize","selectedTime","setSelectedTime","useState","internalOpen","setInternalOpen","isOpen","setHours","setMinutes","setSeconds","setPeriod","focusedColumn","setFocusedColumn","containerRef","useRef","dropdownRef","uniqueId","useId","baseTestId","useEffect","setOpen","useCallback","newOpen","handleClickOutside","event","handleKeyDown","e","delta","maxHour","minHour","newHour","handleHourChange","newMinute","handleMinuteChange","newSecond","handleSecondChange","handlePeriodChange","columns","currentIndex","newIndex","handleClear","handleTimeChange","newHours","newMinutes","newSeconds","now","newTime","actualHour","newPeriod","renderTimeColumn","columnType","label","maxValue","currentValue","onChangeValue","step","start","items","i","listboxId","isFocused","jsxs","jsx","item","isSelected","displayHours","statusClasses","node","Input"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { jsx as i } from "react/jsx-runtime";
2
2
  import { forwardRef as m } from "react";
3
- import { useConfig as T } from "./ConfigProvider.js";
3
+ import { useConfig as T } from "../providers/ConfigProvider.js";
4
4
  const f = "toggle", u = "toggle-xs", p = "toggle-sm", y = "toggle-md", x = "toggle-lg", S = "toggle-xl", h = "toggle-primary", k = "toggle-secondary", C = "toggle-accent", w = "toggle-neutral", z = "toggle-success", N = "toggle-warning", j = "toggle-info", X = "toggle-error", b = m(
5
5
  ({
6
6
  size: t,
@@ -1 +1 @@
1
- {"version":3,"file":"Toggle.js","sources":["../../src/components/Toggle.tsx"],"sourcesContent":["import React, { forwardRef } from 'react'\nimport { useConfig } from './ConfigProvider'\n\n// DaisyUI classes\nconst dToggle = 'toggle'\nconst dToggleXs = 'toggle-xs'\nconst dToggleSm = 'toggle-sm'\nconst dToggleMd = 'toggle-md'\nconst dToggleLg = 'toggle-lg'\nconst dToggleXl = 'toggle-xl'\nconst dTogglePrimary = 'toggle-primary'\nconst dToggleSecondary = 'toggle-secondary'\nconst dToggleAccent = 'toggle-accent'\nconst dToggleNeutral = 'toggle-neutral'\nconst dToggleSuccess = 'toggle-success'\nconst dToggleWarning = 'toggle-warning'\nconst dToggleInfo = 'toggle-info'\nconst dToggleError = 'toggle-error'\n\nexport interface ToggleProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'size' | 'type'> {\n size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'\n color?: 'primary' | 'secondary' | 'accent' | 'neutral' | 'success' | 'warning' | 'info' | 'error'\n className?: string\n}\n\nexport const Toggle = forwardRef<HTMLInputElement, ToggleProps>(\n (\n {\n size,\n color,\n className = '',\n ...props\n },\n ref\n ) => {\n const { componentSize } = useConfig()\n const effectiveSize = size ?? componentSize ?? 'md'\n\n const sizeClasses = {\n xs: dToggleXs,\n sm: dToggleSm,\n md: dToggleMd,\n lg: dToggleLg,\n xl: dToggleXl,\n }\n\n const colorClasses = {\n primary: dTogglePrimary,\n secondary: dToggleSecondary,\n accent: dToggleAccent,\n neutral: dToggleNeutral,\n success: dToggleSuccess,\n warning: dToggleWarning,\n info: dToggleInfo,\n error: dToggleError,\n }\n\n const toggleClasses = [\n dToggle,\n effectiveSize && sizeClasses[effectiveSize],\n color && colorClasses[color],\n className,\n ]\n .filter(Boolean)\n .join(' ')\n\n const dataState = props.checked ? 'checked' : 'unchecked'\n return <input ref={ref} type=\"checkbox\" className={toggleClasses} data-state={dataState} {...props} />\n }\n)\n\nToggle.displayName = 'Toggle'\n"],"names":["dToggle","dToggleXs","dToggleSm","dToggleMd","dToggleLg","dToggleXl","dTogglePrimary","dToggleSecondary","dToggleAccent","dToggleNeutral","dToggleSuccess","dToggleWarning","dToggleInfo","dToggleError","Toggle","forwardRef","size","color","className","props","ref","componentSize","useConfig","effectiveSize","sizeClasses","colorClasses","toggleClasses","dataState","jsx"],"mappings":";;;AAIA,MAAMA,IAAU,UACVC,IAAY,aACZC,IAAY,aACZC,IAAY,aACZC,IAAY,aACZC,IAAY,aACZC,IAAiB,kBACjBC,IAAmB,oBACnBC,IAAgB,iBAChBC,IAAiB,kBACjBC,IAAiB,kBACjBC,IAAiB,kBACjBC,IAAc,eACdC,IAAe,gBAQRC,IAASC;AAAA,EACpB,CACE;AAAA,IACE,MAAAC;AAAA,IACA,OAAAC;AAAA,IACA,WAAAC,IAAY;AAAA,IACZ,GAAGC;AAAA,EAAA,GAELC,MACG;AACH,UAAM,EAAE,eAAAC,EAAA,IAAkBC,EAAA,GACpBC,IAAgBP,KAAQK,KAAiB,MAEzCG,IAAc;AAAA,MAClB,IAAIvB;AAAA,MACJ,IAAIC;AAAA,MACJ,IAAIC;AAAA,MACJ,IAAIC;AAAA,MACJ,IAAIC;AAAA,IAAA,GAGAoB,IAAe;AAAA,MACnB,SAASnB;AAAA,MACT,WAAWC;AAAA,MACX,QAAQC;AAAA,MACR,SAASC;AAAA,MACT,SAASC;AAAA,MACT,SAASC;AAAA,MACT,MAAMC;AAAA,MACN,OAAOC;AAAA,IAAA,GAGHa,IAAgB;AAAA,MACpB1B;AAAA,MACAuB,KAAiBC,EAAYD,CAAa;AAAA,MAC1CN,KAASQ,EAAaR,CAAK;AAAA,MAC3BC;AAAA,IAAA,EAEC,OAAO,OAAO,EACd,KAAK,GAAG,GAELS,IAAYR,EAAM,UAAU,YAAY;AAC9C,WAAO,gBAAAS,EAAC,SAAA,EAAM,KAAAR,GAAU,MAAK,YAAW,WAAWM,GAAe,cAAYC,GAAY,GAAGR,EAAA,CAAO;AAAA,EACtG;AACF;AAEAL,EAAO,cAAc;"}
1
+ {"version":3,"file":"Toggle.js","sources":["../../src/components/Toggle.tsx"],"sourcesContent":["import React, { forwardRef } from 'react'\nimport { useConfig } from '../providers/ConfigProvider'\n\n// DaisyUI classes\nconst dToggle = 'toggle'\nconst dToggleXs = 'toggle-xs'\nconst dToggleSm = 'toggle-sm'\nconst dToggleMd = 'toggle-md'\nconst dToggleLg = 'toggle-lg'\nconst dToggleXl = 'toggle-xl'\nconst dTogglePrimary = 'toggle-primary'\nconst dToggleSecondary = 'toggle-secondary'\nconst dToggleAccent = 'toggle-accent'\nconst dToggleNeutral = 'toggle-neutral'\nconst dToggleSuccess = 'toggle-success'\nconst dToggleWarning = 'toggle-warning'\nconst dToggleInfo = 'toggle-info'\nconst dToggleError = 'toggle-error'\n\nexport interface ToggleProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'size' | 'type'> {\n size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'\n color?: 'primary' | 'secondary' | 'accent' | 'neutral' | 'success' | 'warning' | 'info' | 'error'\n className?: string\n}\n\nexport const Toggle = forwardRef<HTMLInputElement, ToggleProps>(\n (\n {\n size,\n color,\n className = '',\n ...props\n },\n ref\n ) => {\n const { componentSize } = useConfig()\n const effectiveSize = size ?? componentSize ?? 'md'\n\n const sizeClasses = {\n xs: dToggleXs,\n sm: dToggleSm,\n md: dToggleMd,\n lg: dToggleLg,\n xl: dToggleXl,\n }\n\n const colorClasses = {\n primary: dTogglePrimary,\n secondary: dToggleSecondary,\n accent: dToggleAccent,\n neutral: dToggleNeutral,\n success: dToggleSuccess,\n warning: dToggleWarning,\n info: dToggleInfo,\n error: dToggleError,\n }\n\n const toggleClasses = [\n dToggle,\n effectiveSize && sizeClasses[effectiveSize],\n color && colorClasses[color],\n className,\n ]\n .filter(Boolean)\n .join(' ')\n\n const dataState = props.checked ? 'checked' : 'unchecked'\n return <input ref={ref} type=\"checkbox\" className={toggleClasses} data-state={dataState} {...props} />\n }\n)\n\nToggle.displayName = 'Toggle'\n"],"names":["dToggle","dToggleXs","dToggleSm","dToggleMd","dToggleLg","dToggleXl","dTogglePrimary","dToggleSecondary","dToggleAccent","dToggleNeutral","dToggleSuccess","dToggleWarning","dToggleInfo","dToggleError","Toggle","forwardRef","size","color","className","props","ref","componentSize","useConfig","effectiveSize","sizeClasses","colorClasses","toggleClasses","dataState","jsx"],"mappings":";;;AAIA,MAAMA,IAAU,UACVC,IAAY,aACZC,IAAY,aACZC,IAAY,aACZC,IAAY,aACZC,IAAY,aACZC,IAAiB,kBACjBC,IAAmB,oBACnBC,IAAgB,iBAChBC,IAAiB,kBACjBC,IAAiB,kBACjBC,IAAiB,kBACjBC,IAAc,eACdC,IAAe,gBAQRC,IAASC;AAAA,EACpB,CACE;AAAA,IACE,MAAAC;AAAA,IACA,OAAAC;AAAA,IACA,WAAAC,IAAY;AAAA,IACZ,GAAGC;AAAA,EAAA,GAELC,MACG;AACH,UAAM,EAAE,eAAAC,EAAA,IAAkBC,EAAA,GACpBC,IAAgBP,KAAQK,KAAiB,MAEzCG,IAAc;AAAA,MAClB,IAAIvB;AAAA,MACJ,IAAIC;AAAA,MACJ,IAAIC;AAAA,MACJ,IAAIC;AAAA,MACJ,IAAIC;AAAA,IAAA,GAGAoB,IAAe;AAAA,MACnB,SAASnB;AAAA,MACT,WAAWC;AAAA,MACX,QAAQC;AAAA,MACR,SAASC;AAAA,MACT,SAASC;AAAA,MACT,SAASC;AAAA,MACT,MAAMC;AAAA,MACN,OAAOC;AAAA,IAAA,GAGHa,IAAgB;AAAA,MACpB1B;AAAA,MACAuB,KAAiBC,EAAYD,CAAa;AAAA,MAC1CN,KAASQ,EAAaR,CAAK;AAAA,MAC3BC;AAAA,IAAA,EAEC,OAAO,OAAO,EACd,KAAK,GAAG,GAELS,IAAYR,EAAM,UAAU,YAAY;AAC9C,WAAO,gBAAAS,EAAC,SAAA,EAAM,KAAAR,GAAU,MAAK,YAAW,WAAWM,GAAe,cAAYC,GAAY,GAAGR,EAAA,CAAO;AAAA,EACtG;AACF;AAEAL,EAAO,cAAc;"}
@@ -1,4 +1,4 @@
1
- import { ThemeColors } from '../components/ThemeProvider';
1
+ import { ThemeColors } from '../providers/ThemeProvider';
2
2
  export type { ThemeColors };
3
3
  export interface UseThemeReturn {
4
4
  /** The theme setting (what user selected). Only available with ThemeProvider. */
@@ -1,5 +1,5 @@
1
1
  import { useState as i, useEffect as m, useMemo as u } from "react";
2
- import { useHasThemeProvider as d, useThemeContext as l } from "../components/ThemeProvider.js";
2
+ import { useHasThemeProvider as d, useThemeContext as l } from "../providers/ThemeProvider.js";
3
3
  const h = /* @__PURE__ */ new Set([
4
4
  "dark",
5
5
  "synthwave",
@@ -1 +1 @@
1
- {"version":3,"file":"useTheme.js","sources":["../../src/hooks/useTheme.ts"],"sourcesContent":["import { useEffect, useState, useMemo } from 'react'\nimport { useHasThemeProvider, useThemeContext, type ThemeColors } from '../components/ThemeProvider'\n\nexport type { ThemeColors }\n\n// Common dark themes in DaisyUI\nconst DARK_THEMES = new Set([\n 'dark', 'synthwave', 'halloween', 'forest', 'black', 'luxury', 'dracula',\n 'business', 'night', 'coffee', 'dim', 'sunset'\n])\n\nexport interface UseThemeReturn {\n /** The theme setting (what user selected). Only available with ThemeProvider. */\n theme: string | undefined\n /** The actual applied theme. Only available with ThemeProvider. */\n resolvedTheme: string | undefined\n /** Whether dark mode is active */\n isDark: boolean\n /** Set the theme. Only available with ThemeProvider. */\n setTheme: ((theme: string) => void) | undefined\n /** Computed theme colors as hex values */\n colors: ThemeColors\n /** The system preference. Only available with ThemeProvider. */\n systemTheme: 'light' | 'dark' | undefined\n}\n\n// Convert any CSS color to hex\nfunction colorToHex(color: string): string {\n if (typeof document === 'undefined') return '#000000'\n const canvas = document.createElement('canvas')\n canvas.width = canvas.height = 1\n const ctx = canvas.getContext('2d')\n if (!ctx) return '#000000'\n ctx.fillStyle = color\n ctx.fillRect(0, 0, 1, 1)\n const [r, g, b] = ctx.getImageData(0, 0, 1, 1).data\n return `#${((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1)}`\n}\n\nfunction getThemeColors(): ThemeColors {\n if (typeof document === 'undefined') {\n return {\n background: '#ffffff',\n foreground: '#000000',\n primary: '#6366f1',\n primaryContent: '#ffffff',\n secondary: '#f000b8',\n accent: '#37cdbe',\n info: '#3abff8',\n success: '#36d399',\n warning: '#fbbd23',\n error: '#f87272',\n }\n }\n\n const style = getComputedStyle(document.documentElement)\n const getColor = (varName: string, fallback: string): string => {\n const value = style.getPropertyValue(varName).trim()\n return value ? colorToHex(value) : fallback\n }\n\n return {\n background: getColor('--color-base-100', '#ffffff'),\n foreground: getColor('--color-base-content', '#000000'),\n primary: getColor('--color-primary', '#6366f1'),\n primaryContent: getColor('--color-primary-content', '#ffffff'),\n secondary: getColor('--color-secondary', '#f000b8'),\n accent: getColor('--color-accent', '#37cdbe'),\n info: getColor('--color-info', '#3abff8'),\n success: getColor('--color-success', '#36d399'),\n warning: getColor('--color-warning', '#fbbd23'),\n error: getColor('--color-error', '#f87272'),\n }\n}\n\nfunction getSystemTheme(): 'light' | 'dark' {\n if (typeof window === 'undefined') return 'light'\n return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'\n}\n\nfunction getCurrentTheme(): string | null {\n if (typeof document === 'undefined') return null\n return document.documentElement.getAttribute('data-theme')\n}\n\n/**\n * Hook to detect current theme and get computed colors.\n *\n * When used within a ThemeProvider, returns full theme control including\n * setTheme, theme selection, and resolved theme.\n *\n * When used standalone (without ThemeProvider), provides read-only access\n * to isDark and colors based on the current data-theme attribute and\n * system preference.\n *\n * @example\n * // With ThemeProvider (full control)\n * const { theme, setTheme, resolvedTheme, isDark, colors } = useTheme()\n * setTheme('dark')\n * setTheme('system')\n *\n * @example\n * // Without ThemeProvider (read-only)\n * const { isDark, colors } = useTheme()\n * // colors.primary, colors.foreground, etc.\n */\nexport function useTheme(): UseThemeReturn {\n const hasProvider = useHasThemeProvider()\n\n // If we have a provider, use its context\n if (hasProvider) {\n // This is safe because hasProvider is stable after initial render\n // eslint-disable-next-line react-hooks/rules-of-hooks\n const context = useThemeContext()\n return {\n theme: context.theme,\n resolvedTheme: context.resolvedTheme,\n isDark: context.isDark,\n setTheme: context.setTheme,\n colors: context.colors,\n systemTheme: context.systemTheme,\n }\n }\n\n // Standalone mode - no provider\n // eslint-disable-next-line react-hooks/rules-of-hooks\n return useThemeStandalone()\n}\n\n/**\n * Standalone theme detection (no ThemeProvider)\n */\nfunction useThemeStandalone(): UseThemeReturn {\n const [state, setState] = useState<{ isDark: boolean; colors: ThemeColors }>(() => ({\n isDark: false,\n colors: getThemeColors(),\n }))\n\n useEffect(() => {\n const updateTheme = () => {\n const currentTheme = getCurrentTheme()\n const systemTheme = getSystemTheme()\n\n // Determine if dark based on data-theme or system preference\n let isDark = false\n if (currentTheme) {\n isDark = DARK_THEMES.has(currentTheme)\n } else {\n isDark = systemTheme === 'dark'\n }\n\n // Double RAF ensures CSS has fully recalculated\n requestAnimationFrame(() => {\n requestAnimationFrame(() => {\n setState({\n isDark,\n colors: getThemeColors(),\n })\n })\n })\n }\n\n updateTheme()\n\n // Watch for theme changes via attribute mutation\n const observer = new MutationObserver(updateTheme)\n observer.observe(document.documentElement, {\n attributes: true,\n attributeFilter: ['data-theme', 'class']\n })\n\n // Watch for system preference changes\n const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)')\n mediaQuery.addEventListener('change', updateTheme)\n\n return () => {\n observer.disconnect()\n mediaQuery.removeEventListener('change', updateTheme)\n }\n }, [])\n\n return useMemo(() => ({\n theme: undefined,\n resolvedTheme: undefined,\n isDark: state.isDark,\n setTheme: undefined,\n colors: state.colors,\n systemTheme: undefined,\n }), [state.isDark, state.colors])\n}\n\nexport default useTheme\n"],"names":["DARK_THEMES","colorToHex","color","canvas","ctx","r","g","b","getThemeColors","style","getColor","varName","fallback","value","getSystemTheme","getCurrentTheme","useTheme","useHasThemeProvider","context","useThemeContext","useThemeStandalone","state","setState","useState","useEffect","updateTheme","currentTheme","systemTheme","isDark","observer","mediaQuery","useMemo"],"mappings":"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"}
1
+ {"version":3,"file":"useTheme.js","sources":["../../src/hooks/useTheme.ts"],"sourcesContent":["import { useEffect, useState, useMemo } from 'react'\nimport { useHasThemeProvider, useThemeContext, type ThemeColors } from '../providers/ThemeProvider'\n\nexport type { ThemeColors }\n\n// Common dark themes in DaisyUI\nconst DARK_THEMES = new Set([\n 'dark', 'synthwave', 'halloween', 'forest', 'black', 'luxury', 'dracula',\n 'business', 'night', 'coffee', 'dim', 'sunset'\n])\n\nexport interface UseThemeReturn {\n /** The theme setting (what user selected). Only available with ThemeProvider. */\n theme: string | undefined\n /** The actual applied theme. Only available with ThemeProvider. */\n resolvedTheme: string | undefined\n /** Whether dark mode is active */\n isDark: boolean\n /** Set the theme. Only available with ThemeProvider. */\n setTheme: ((theme: string) => void) | undefined\n /** Computed theme colors as hex values */\n colors: ThemeColors\n /** The system preference. Only available with ThemeProvider. */\n systemTheme: 'light' | 'dark' | undefined\n}\n\n// Convert any CSS color to hex\nfunction colorToHex(color: string): string {\n if (typeof document === 'undefined') return '#000000'\n const canvas = document.createElement('canvas')\n canvas.width = canvas.height = 1\n const ctx = canvas.getContext('2d')\n if (!ctx) return '#000000'\n ctx.fillStyle = color\n ctx.fillRect(0, 0, 1, 1)\n const [r, g, b] = ctx.getImageData(0, 0, 1, 1).data\n return `#${((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1)}`\n}\n\nfunction getThemeColors(): ThemeColors {\n if (typeof document === 'undefined') {\n return {\n background: '#ffffff',\n foreground: '#000000',\n primary: '#6366f1',\n primaryContent: '#ffffff',\n secondary: '#f000b8',\n accent: '#37cdbe',\n info: '#3abff8',\n success: '#36d399',\n warning: '#fbbd23',\n error: '#f87272',\n }\n }\n\n const style = getComputedStyle(document.documentElement)\n const getColor = (varName: string, fallback: string): string => {\n const value = style.getPropertyValue(varName).trim()\n return value ? colorToHex(value) : fallback\n }\n\n return {\n background: getColor('--color-base-100', '#ffffff'),\n foreground: getColor('--color-base-content', '#000000'),\n primary: getColor('--color-primary', '#6366f1'),\n primaryContent: getColor('--color-primary-content', '#ffffff'),\n secondary: getColor('--color-secondary', '#f000b8'),\n accent: getColor('--color-accent', '#37cdbe'),\n info: getColor('--color-info', '#3abff8'),\n success: getColor('--color-success', '#36d399'),\n warning: getColor('--color-warning', '#fbbd23'),\n error: getColor('--color-error', '#f87272'),\n }\n}\n\nfunction getSystemTheme(): 'light' | 'dark' {\n if (typeof window === 'undefined') return 'light'\n return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'\n}\n\nfunction getCurrentTheme(): string | null {\n if (typeof document === 'undefined') return null\n return document.documentElement.getAttribute('data-theme')\n}\n\n/**\n * Hook to detect current theme and get computed colors.\n *\n * When used within a ThemeProvider, returns full theme control including\n * setTheme, theme selection, and resolved theme.\n *\n * When used standalone (without ThemeProvider), provides read-only access\n * to isDark and colors based on the current data-theme attribute and\n * system preference.\n *\n * @example\n * // With ThemeProvider (full control)\n * const { theme, setTheme, resolvedTheme, isDark, colors } = useTheme()\n * setTheme('dark')\n * setTheme('system')\n *\n * @example\n * // Without ThemeProvider (read-only)\n * const { isDark, colors } = useTheme()\n * // colors.primary, colors.foreground, etc.\n */\nexport function useTheme(): UseThemeReturn {\n const hasProvider = useHasThemeProvider()\n\n // If we have a provider, use its context\n if (hasProvider) {\n // This is safe because hasProvider is stable after initial render\n // eslint-disable-next-line react-hooks/rules-of-hooks\n const context = useThemeContext()\n return {\n theme: context.theme,\n resolvedTheme: context.resolvedTheme,\n isDark: context.isDark,\n setTheme: context.setTheme,\n colors: context.colors,\n systemTheme: context.systemTheme,\n }\n }\n\n // Standalone mode - no provider\n // eslint-disable-next-line react-hooks/rules-of-hooks\n return useThemeStandalone()\n}\n\n/**\n * Standalone theme detection (no ThemeProvider)\n */\nfunction useThemeStandalone(): UseThemeReturn {\n const [state, setState] = useState<{ isDark: boolean; colors: ThemeColors }>(() => ({\n isDark: false,\n colors: getThemeColors(),\n }))\n\n useEffect(() => {\n const updateTheme = () => {\n const currentTheme = getCurrentTheme()\n const systemTheme = getSystemTheme()\n\n // Determine if dark based on data-theme or system preference\n let isDark = false\n if (currentTheme) {\n isDark = DARK_THEMES.has(currentTheme)\n } else {\n isDark = systemTheme === 'dark'\n }\n\n // Double RAF ensures CSS has fully recalculated\n requestAnimationFrame(() => {\n requestAnimationFrame(() => {\n setState({\n isDark,\n colors: getThemeColors(),\n })\n })\n })\n }\n\n updateTheme()\n\n // Watch for theme changes via attribute mutation\n const observer = new MutationObserver(updateTheme)\n observer.observe(document.documentElement, {\n attributes: true,\n attributeFilter: ['data-theme', 'class']\n })\n\n // Watch for system preference changes\n const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)')\n mediaQuery.addEventListener('change', updateTheme)\n\n return () => {\n observer.disconnect()\n mediaQuery.removeEventListener('change', updateTheme)\n }\n }, [])\n\n return useMemo(() => ({\n theme: undefined,\n resolvedTheme: undefined,\n isDark: state.isDark,\n setTheme: undefined,\n colors: state.colors,\n systemTheme: undefined,\n }), [state.isDark, state.colors])\n}\n\nexport default useTheme\n"],"names":["DARK_THEMES","colorToHex","color","canvas","ctx","r","g","b","getThemeColors","style","getColor","varName","fallback","value","getSystemTheme","getCurrentTheme","useTheme","useHasThemeProvider","context","useThemeContext","useThemeStandalone","state","setState","useState","useEffect","updateTheme","currentTheme","systemTheme","isDark","observer","mediaQuery","useMemo"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -30,8 +30,8 @@ export { Carousel } from './components/Carousel';
30
30
  export type { CarouselProps, CarouselItemProps, CarouselRef, CarouselEffect, CarouselDotPlacement } from './components/Carousel';
31
31
  export { Cascader } from './components/Cascader';
32
32
  export type { CascaderProps, CascaderOption } from './components/Cascader';
33
- export { ConfigProvider, useConfig, useLocale, useComponentLocale, ConfigContext } from './components/ConfigProvider';
34
- export type { ConfigProviderProps, ConfigContextValue, ComponentSize, Direction } from './components/ConfigProvider';
33
+ export { ConfigProvider, useConfig, useLocale, useComponentLocale, ConfigContext } from './providers/ConfigProvider';
34
+ export type { ConfigProviderProps, ConfigContextValue, ComponentSize, Direction } from './providers/ConfigProvider';
35
35
  export type { Locale } from './locale';
36
36
  export { enUS, enGB, enCA, zhCN, esES, jaJP, ptBR, deDE, frFR, koKR } from './locale';
37
37
  export { Collapse } from './components/Collapse';
@@ -174,8 +174,8 @@ export { Tag, CheckableTag, TagLiveRegion } from './components/Tag';
174
174
  export type { TagProps, CheckableTagProps, TagSize, TagColor, TagVariant } from './components/Tag';
175
175
  export { ThemeController } from './components/ThemeController';
176
176
  export type { ThemeControllerSwapProps, ThemeControllerDropdownProps, ThemeControllerToggleProps } from './components/ThemeController';
177
- export { ThemeProvider, useThemeContext, useHasThemeProvider } from './components/ThemeProvider';
178
- export type { ThemeProviderProps, ThemeContextValue } from './components/ThemeProvider';
177
+ export { ThemeProvider, useThemeContext, useHasThemeProvider } from './providers/ThemeProvider';
178
+ export type { ThemeProviderProps, ThemeContextValue } from './providers/ThemeProvider';
179
179
  export { TimePicker } from './components/TimePicker';
180
180
  export type { TimePickerProps } from './components/TimePicker';
181
181
  export { Timeline } from './components/Timeline';
package/dist/index.js CHANGED
@@ -14,7 +14,7 @@ import { ColorPicker as B } from "./components/ColorPicker.js";
14
14
  import { Card as M } from "./components/Card.js";
15
15
  import { Carousel as L } from "./components/Carousel.js";
16
16
  import { Cascader as z } from "./components/Cascader.js";
17
- import { ConfigContext as G, ConfigProvider as K, useComponentLocale as W, useConfig as E, useLocale as N } from "./components/ConfigProvider.js";
17
+ import { ConfigContext as G, ConfigProvider as K, useComponentLocale as W, useConfig as E, useLocale as N } from "./providers/ConfigProvider.js";
18
18
  import { Collapse as O } from "./components/Collapse.js";
19
19
  import { Command as j } from "./components/Command.js";
20
20
  import { Container as Q } from "./components/Container.js";
@@ -85,7 +85,7 @@ import { Textarea as Se } from "./components/Textarea.js";
85
85
  import { TextRotate as he } from "./components/TextRotate.js";
86
86
  import { CheckableTag as ve, Tag as Re, TagLiveRegion as be } from "./components/Tag.js";
87
87
  import { ThemeController as we } from "./components/ThemeController.js";
88
- import { ThemeProvider as Be, useHasThemeProvider as Fe, useThemeContext as Me } from "./components/ThemeProvider.js";
88
+ import { ThemeProvider as Be, useHasThemeProvider as Fe, useThemeContext as Me } from "./providers/ThemeProvider.js";
89
89
  import { TimePicker as Le } from "./components/TimePicker.js";
90
90
  import { Timeline as ze } from "./components/Timeline.js";
91
91
  import { Toggle as Ge } from "./components/Toggle.js";
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConfigProvider.js","sources":["../../src/providers/ConfigProvider.tsx"],"sourcesContent":["import React, { createContext, useContext, useMemo } from 'react'\nimport type { Locale } from '../locale'\nimport enUS from '../locale/en-US'\n\nexport type ComponentSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl'\nexport type Direction = 'ltr' | 'rtl'\n\nexport interface ConfigContextValue {\n /** Current locale */\n locale: Locale\n /** Component size */\n componentSize?: ComponentSize\n /** Layout direction */\n direction?: Direction\n /** Prefix for CSS classes */\n prefixCls?: string\n /** Default container for portals (modals, dropdowns, etc.) */\n getPopupContainer?: (triggerNode?: HTMLElement) => HTMLElement\n}\n\nexport interface ConfigProviderProps {\n /** Locale configuration */\n locale?: Locale\n /** Component size for all child components */\n componentSize?: ComponentSize\n /** Layout direction (ltr or rtl) */\n direction?: Direction\n /** Prefix for CSS classes */\n prefixCls?: string\n /** Default container for portals */\n getPopupContainer?: (triggerNode?: HTMLElement) => HTMLElement\n /** Child components */\n children?: React.ReactNode\n}\n\nconst defaultConfig: ConfigContextValue = {\n locale: enUS,\n componentSize: 'md',\n direction: 'ltr',\n}\n\nconst ConfigContext = createContext<ConfigContextValue>(defaultConfig)\n\n/**\n * Hook to access the current configuration\n */\nexport function useConfig(): ConfigContextValue {\n return useContext(ConfigContext)\n}\n\n/**\n * Hook to access the current locale\n */\nexport function useLocale(): Locale {\n const { locale } = useContext(ConfigContext)\n return locale\n}\n\n/**\n * Hook to get locale strings for a specific component\n */\nexport function useComponentLocale<K extends keyof Locale>(\n componentName: K\n): NonNullable<Locale[K]> {\n const locale = useLocale()\n return (locale[componentName] ?? enUS[componentName] ?? {}) as NonNullable<Locale[K]>\n}\n\n/**\n * ConfigProvider component for global configuration\n *\n * Provides locale, component size, direction, and other settings to all child components.\n *\n * @example\n * ```tsx\n * import { ConfigProvider, zhCN } from 'asterui'\n *\n * <ConfigProvider locale={zhCN} componentSize=\"small\">\n * <App />\n * </ConfigProvider>\n * ```\n */\nexport const ConfigProvider: React.FC<ConfigProviderProps> = ({\n locale,\n componentSize,\n direction,\n prefixCls,\n getPopupContainer,\n children,\n}) => {\n // Get parent config if nested\n const parentConfig = useContext(ConfigContext)\n\n const config = useMemo<ConfigContextValue>(\n () => ({\n locale: locale ?? parentConfig.locale,\n componentSize: componentSize ?? parentConfig.componentSize,\n direction: direction ?? parentConfig.direction,\n prefixCls: prefixCls ?? parentConfig.prefixCls,\n getPopupContainer: getPopupContainer ?? parentConfig.getPopupContainer,\n }),\n [locale, componentSize, direction, prefixCls, getPopupContainer, parentConfig]\n )\n\n return <ConfigContext.Provider value={config}>{children}</ConfigContext.Provider>\n}\n\n// Also export the context for advanced use cases\nexport { ConfigContext }\n"],"names":["defaultConfig","enUS","ConfigContext","createContext","useConfig","useContext","useLocale","locale","useComponentLocale","componentName","ConfigProvider","componentSize","direction","prefixCls","getPopupContainer","children","parentConfig","config","useMemo"],"mappings":";;;AAmCA,MAAMA,IAAoC;AAAA,EACxC,QAAQC;AAAA,EACR,eAAe;AAAA,EACf,WAAW;AACb,GAEMC,IAAgBC,EAAkCH,CAAa;AAK9D,SAASI,IAAgC;AAC9C,SAAOC,EAAWH,CAAa;AACjC;AAKO,SAASI,IAAoB;AAClC,QAAM,EAAE,QAAAC,EAAA,IAAWF,EAAWH,CAAa;AAC3C,SAAOK;AACT;AAKO,SAASC,EACdC,GACwB;AAExB,SADeH,EAAA,EACAG,CAAa,KAAKR,EAAKQ,CAAa,KAAK,CAAA;AAC1D;AAgBO,MAAMC,IAAgD,CAAC;AAAA,EAC5D,QAAAH;AAAA,EACA,eAAAI;AAAA,EACA,WAAAC;AAAA,EACA,WAAAC;AAAA,EACA,mBAAAC;AAAA,EACA,UAAAC;AACF,MAAM;AAEJ,QAAMC,IAAeX,EAAWH,CAAa,GAEvCe,IAASC;AAAA,IACb,OAAO;AAAA,MACL,QAAQX,KAAUS,EAAa;AAAA,MAC/B,eAAeL,KAAiBK,EAAa;AAAA,MAC7C,WAAWJ,KAAaI,EAAa;AAAA,MACrC,WAAWH,KAAaG,EAAa;AAAA,MACrC,mBAAmBF,KAAqBE,EAAa;AAAA,IAAA;AAAA,IAEvD,CAACT,GAAQI,GAAeC,GAAWC,GAAWC,GAAmBE,CAAY;AAAA,EAAA;AAG/E,2BAAQd,EAAc,UAAd,EAAuB,OAAOe,GAAS,UAAAF,GAAS;AAC1D;"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ThemeProvider.js","sources":["../../src/providers/ThemeProvider.tsx"],"sourcesContent":["import React, { createContext, useContext, useEffect, useState, useCallback, useMemo } from 'react'\n\n// Common dark themes in DaisyUI\nconst DARK_THEMES = new Set([\n 'dark', 'synthwave', 'halloween', 'forest', 'black', 'luxury', 'dracula',\n 'business', 'night', 'coffee', 'dim', 'sunset'\n])\n\nexport interface ThemeProviderProps {\n children: React.ReactNode\n /** Default theme. Use \"system\" to follow browser preference. */\n defaultTheme?: string\n /** localStorage key for persisting theme. Set to false to disable persistence. */\n storageKey?: string | false\n /** Light theme to use when system preference is light */\n lightTheme?: string\n /** Dark theme to use when system preference is dark */\n darkTheme?: string\n /** Custom function to determine if a theme is dark */\n isDarkTheme?: (theme: string) => boolean\n}\n\nexport interface ThemeColors {\n background: string\n foreground: string\n primary: string\n primaryContent: string\n secondary: string\n accent: string\n info: string\n success: string\n warning: string\n error: string\n}\n\nexport interface ThemeContextValue {\n /** The theme setting (what user selected: \"system\", \"light\", \"dark\", etc.) */\n theme: string\n /** The actual applied theme after resolving \"system\" */\n resolvedTheme: string\n /** Whether the resolved theme is dark */\n isDark: boolean\n /** Set the theme */\n setTheme: (theme: string) => void\n /** Computed theme colors as hex values (for canvas/non-CSS contexts) */\n colors: ThemeColors\n /** The system preference (\"light\" or \"dark\") */\n systemTheme: 'light' | 'dark'\n}\n\nconst ThemeContext = createContext<ThemeContextValue | undefined>(undefined)\n\n// Convert any CSS color to hex\nfunction colorToHex(color: string): string {\n if (typeof document === 'undefined') return '#000000'\n const canvas = document.createElement('canvas')\n canvas.width = canvas.height = 1\n const ctx = canvas.getContext('2d')\n if (!ctx) return '#000000'\n ctx.fillStyle = color\n ctx.fillRect(0, 0, 1, 1)\n const [r, g, b] = ctx.getImageData(0, 0, 1, 1).data\n return `#${((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1)}`\n}\n\nfunction getThemeColors(): ThemeColors {\n if (typeof document === 'undefined') {\n return {\n background: '#ffffff',\n foreground: '#000000',\n primary: '#6366f1',\n primaryContent: '#ffffff',\n secondary: '#f000b8',\n accent: '#37cdbe',\n info: '#3abff8',\n success: '#36d399',\n warning: '#fbbd23',\n error: '#f87272',\n }\n }\n\n const style = getComputedStyle(document.documentElement)\n const getColor = (varName: string, fallback: string): string => {\n const value = style.getPropertyValue(varName).trim()\n return value ? colorToHex(value) : fallback\n }\n\n return {\n background: getColor('--color-base-100', '#ffffff'),\n foreground: getColor('--color-base-content', '#000000'),\n primary: getColor('--color-primary', '#6366f1'),\n primaryContent: getColor('--color-primary-content', '#ffffff'),\n secondary: getColor('--color-secondary', '#f000b8'),\n accent: getColor('--color-accent', '#37cdbe'),\n info: getColor('--color-info', '#3abff8'),\n success: getColor('--color-success', '#36d399'),\n warning: getColor('--color-warning', '#fbbd23'),\n error: getColor('--color-error', '#f87272'),\n }\n}\n\nfunction getSystemTheme(): 'light' | 'dark' {\n if (typeof window === 'undefined') return 'light'\n return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'\n}\n\nfunction getStoredTheme(key: string | false): string | null {\n if (!key || typeof window === 'undefined') return null\n try {\n return localStorage.getItem(key)\n } catch {\n return null\n }\n}\n\nfunction storeTheme(key: string | false, theme: string): void {\n if (!key || typeof window === 'undefined') return\n try {\n localStorage.setItem(key, theme)\n } catch {\n // Ignore storage errors\n }\n}\n\nexport function ThemeProvider({\n children,\n defaultTheme = 'system',\n storageKey = 'asterui-theme',\n lightTheme = 'light',\n darkTheme = 'dark',\n isDarkTheme,\n}: ThemeProviderProps) {\n // Initialize theme from storage or default\n const [theme, setThemeState] = useState<string>(() => {\n const stored = getStoredTheme(storageKey)\n return stored || defaultTheme\n })\n\n // Track system preference\n const [systemTheme, setSystemTheme] = useState<'light' | 'dark'>(getSystemTheme)\n\n // Resolve the actual theme\n const resolvedTheme = useMemo(() => {\n if (theme === 'system') {\n return systemTheme === 'dark' ? darkTheme : lightTheme\n }\n return theme\n }, [theme, systemTheme, lightTheme, darkTheme])\n\n // Determine if dark\n const isDark = useMemo(() => {\n if (isDarkTheme) return isDarkTheme(resolvedTheme)\n return DARK_THEMES.has(resolvedTheme)\n }, [resolvedTheme, isDarkTheme])\n\n // Track colors (updated after theme applies)\n const [colors, setColors] = useState<ThemeColors>(getThemeColors)\n\n // Set theme function\n const setTheme = useCallback((newTheme: string) => {\n setThemeState(newTheme)\n storeTheme(storageKey, newTheme)\n }, [storageKey])\n\n // Apply theme to document\n useEffect(() => {\n if (typeof document === 'undefined') return\n document.documentElement.setAttribute('data-theme', resolvedTheme)\n\n // Double RAF ensures CSS has fully recalculated after attribute change\n requestAnimationFrame(() => {\n requestAnimationFrame(() => {\n setColors(getThemeColors())\n })\n })\n }, [resolvedTheme])\n\n // Listen for system preference changes\n useEffect(() => {\n if (typeof window === 'undefined') return\n\n const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)')\n const handleChange = (e: MediaQueryListEvent) => {\n setSystemTheme(e.matches ? 'dark' : 'light')\n }\n\n mediaQuery.addEventListener('change', handleChange)\n return () => mediaQuery.removeEventListener('change', handleChange)\n }, [])\n\n // Listen for storage changes (cross-tab sync)\n useEffect(() => {\n if (!storageKey || typeof window === 'undefined') return\n\n const handleStorage = (e: StorageEvent) => {\n if (e.key === storageKey && e.newValue) {\n setThemeState(e.newValue)\n }\n }\n\n window.addEventListener('storage', handleStorage)\n return () => window.removeEventListener('storage', handleStorage)\n }, [storageKey])\n\n const value = useMemo<ThemeContextValue>(() => ({\n theme,\n resolvedTheme,\n isDark,\n setTheme,\n colors,\n systemTheme,\n }), [theme, resolvedTheme, isDark, setTheme, colors, systemTheme])\n\n return (\n <ThemeContext.Provider value={value}>\n {children}\n </ThemeContext.Provider>\n )\n}\n\n/**\n * Hook to access theme context.\n * Must be used within a ThemeProvider.\n */\nexport function useThemeContext(): ThemeContextValue {\n const context = useContext(ThemeContext)\n if (!context) {\n throw new Error('useThemeContext must be used within a ThemeProvider')\n }\n return context\n}\n\n/**\n * Check if ThemeProvider is present in the tree.\n */\nexport function useHasThemeProvider(): boolean {\n return useContext(ThemeContext) !== undefined\n}\n"],"names":["DARK_THEMES","ThemeContext","createContext","colorToHex","color","canvas","ctx","r","g","b","getThemeColors","style","getColor","varName","fallback","value","getSystemTheme","getStoredTheme","key","storeTheme","theme","ThemeProvider","children","defaultTheme","storageKey","lightTheme","darkTheme","isDarkTheme","setThemeState","useState","systemTheme","setSystemTheme","resolvedTheme","useMemo","isDark","colors","setColors","setTheme","useCallback","newTheme","useEffect","mediaQuery","handleChange","e","handleStorage","jsx","useThemeContext","context","useContext","useHasThemeProvider"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "asterui",
3
- "version": "0.12.58",
3
+ "version": "0.12.59",
4
4
  "description": "React UI component library with DaisyUI",
5
5
  "homepage": "https://asterui.com",
6
6
  "repository": {
@@ -1 +0,0 @@
1
- {"version":3,"file":"ConfigProvider.js","sources":["../../src/components/ConfigProvider.tsx"],"sourcesContent":["import React, { createContext, useContext, useMemo } from 'react'\nimport type { Locale } from '../locale'\nimport enUS from '../locale/en-US'\n\nexport type ComponentSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl'\nexport type Direction = 'ltr' | 'rtl'\n\nexport interface ConfigContextValue {\n /** Current locale */\n locale: Locale\n /** Component size */\n componentSize?: ComponentSize\n /** Layout direction */\n direction?: Direction\n /** Prefix for CSS classes */\n prefixCls?: string\n /** Default container for portals (modals, dropdowns, etc.) */\n getPopupContainer?: (triggerNode?: HTMLElement) => HTMLElement\n}\n\nexport interface ConfigProviderProps {\n /** Locale configuration */\n locale?: Locale\n /** Component size for all child components */\n componentSize?: ComponentSize\n /** Layout direction (ltr or rtl) */\n direction?: Direction\n /** Prefix for CSS classes */\n prefixCls?: string\n /** Default container for portals */\n getPopupContainer?: (triggerNode?: HTMLElement) => HTMLElement\n /** Child components */\n children?: React.ReactNode\n}\n\nconst defaultConfig: ConfigContextValue = {\n locale: enUS,\n componentSize: 'md',\n direction: 'ltr',\n}\n\nconst ConfigContext = createContext<ConfigContextValue>(defaultConfig)\n\n/**\n * Hook to access the current configuration\n */\nexport function useConfig(): ConfigContextValue {\n return useContext(ConfigContext)\n}\n\n/**\n * Hook to access the current locale\n */\nexport function useLocale(): Locale {\n const { locale } = useContext(ConfigContext)\n return locale\n}\n\n/**\n * Hook to get locale strings for a specific component\n */\nexport function useComponentLocale<K extends keyof Locale>(\n componentName: K\n): NonNullable<Locale[K]> {\n const locale = useLocale()\n return (locale[componentName] ?? enUS[componentName] ?? {}) as NonNullable<Locale[K]>\n}\n\n/**\n * ConfigProvider component for global configuration\n *\n * Provides locale, component size, direction, and other settings to all child components.\n *\n * @example\n * ```tsx\n * import { ConfigProvider, zhCN } from 'asterui'\n *\n * <ConfigProvider locale={zhCN} componentSize=\"small\">\n * <App />\n * </ConfigProvider>\n * ```\n */\nexport const ConfigProvider: React.FC<ConfigProviderProps> = ({\n locale,\n componentSize,\n direction,\n prefixCls,\n getPopupContainer,\n children,\n}) => {\n // Get parent config if nested\n const parentConfig = useContext(ConfigContext)\n\n const config = useMemo<ConfigContextValue>(\n () => ({\n locale: locale ?? parentConfig.locale,\n componentSize: componentSize ?? parentConfig.componentSize,\n direction: direction ?? parentConfig.direction,\n prefixCls: prefixCls ?? parentConfig.prefixCls,\n getPopupContainer: getPopupContainer ?? parentConfig.getPopupContainer,\n }),\n [locale, componentSize, direction, prefixCls, getPopupContainer, parentConfig]\n )\n\n return <ConfigContext.Provider value={config}>{children}</ConfigContext.Provider>\n}\n\n// Also export the context for advanced use cases\nexport { ConfigContext }\n"],"names":["defaultConfig","enUS","ConfigContext","createContext","useConfig","useContext","useLocale","locale","useComponentLocale","componentName","ConfigProvider","componentSize","direction","prefixCls","getPopupContainer","children","parentConfig","config","useMemo"],"mappings":";;;AAmCA,MAAMA,IAAoC;AAAA,EACxC,QAAQC;AAAA,EACR,eAAe;AAAA,EACf,WAAW;AACb,GAEMC,IAAgBC,EAAkCH,CAAa;AAK9D,SAASI,IAAgC;AAC9C,SAAOC,EAAWH,CAAa;AACjC;AAKO,SAASI,IAAoB;AAClC,QAAM,EAAE,QAAAC,EAAA,IAAWF,EAAWH,CAAa;AAC3C,SAAOK;AACT;AAKO,SAASC,EACdC,GACwB;AAExB,SADeH,EAAA,EACAG,CAAa,KAAKR,EAAKQ,CAAa,KAAK,CAAA;AAC1D;AAgBO,MAAMC,IAAgD,CAAC;AAAA,EAC5D,QAAAH;AAAA,EACA,eAAAI;AAAA,EACA,WAAAC;AAAA,EACA,WAAAC;AAAA,EACA,mBAAAC;AAAA,EACA,UAAAC;AACF,MAAM;AAEJ,QAAMC,IAAeX,EAAWH,CAAa,GAEvCe,IAASC;AAAA,IACb,OAAO;AAAA,MACL,QAAQX,KAAUS,EAAa;AAAA,MAC/B,eAAeL,KAAiBK,EAAa;AAAA,MAC7C,WAAWJ,KAAaI,EAAa;AAAA,MACrC,WAAWH,KAAaG,EAAa;AAAA,MACrC,mBAAmBF,KAAqBE,EAAa;AAAA,IAAA;AAAA,IAEvD,CAACT,GAAQI,GAAeC,GAAWC,GAAWC,GAAmBE,CAAY;AAAA,EAAA;AAG/E,2BAAQd,EAAc,UAAd,EAAuB,OAAOe,GAAS,UAAAF,GAAS;AAC1D;"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"ThemeProvider.js","sources":["../../src/components/ThemeProvider.tsx"],"sourcesContent":["import React, { createContext, useContext, useEffect, useState, useCallback, useMemo } from 'react'\n\n// Common dark themes in DaisyUI\nconst DARK_THEMES = new Set([\n 'dark', 'synthwave', 'halloween', 'forest', 'black', 'luxury', 'dracula',\n 'business', 'night', 'coffee', 'dim', 'sunset'\n])\n\nexport interface ThemeProviderProps {\n children: React.ReactNode\n /** Default theme. Use \"system\" to follow browser preference. */\n defaultTheme?: string\n /** localStorage key for persisting theme. Set to false to disable persistence. */\n storageKey?: string | false\n /** Light theme to use when system preference is light */\n lightTheme?: string\n /** Dark theme to use when system preference is dark */\n darkTheme?: string\n /** Custom function to determine if a theme is dark */\n isDarkTheme?: (theme: string) => boolean\n}\n\nexport interface ThemeColors {\n background: string\n foreground: string\n primary: string\n primaryContent: string\n secondary: string\n accent: string\n info: string\n success: string\n warning: string\n error: string\n}\n\nexport interface ThemeContextValue {\n /** The theme setting (what user selected: \"system\", \"light\", \"dark\", etc.) */\n theme: string\n /** The actual applied theme after resolving \"system\" */\n resolvedTheme: string\n /** Whether the resolved theme is dark */\n isDark: boolean\n /** Set the theme */\n setTheme: (theme: string) => void\n /** Computed theme colors as hex values (for canvas/non-CSS contexts) */\n colors: ThemeColors\n /** The system preference (\"light\" or \"dark\") */\n systemTheme: 'light' | 'dark'\n}\n\nconst ThemeContext = createContext<ThemeContextValue | undefined>(undefined)\n\n// Convert any CSS color to hex\nfunction colorToHex(color: string): string {\n if (typeof document === 'undefined') return '#000000'\n const canvas = document.createElement('canvas')\n canvas.width = canvas.height = 1\n const ctx = canvas.getContext('2d')\n if (!ctx) return '#000000'\n ctx.fillStyle = color\n ctx.fillRect(0, 0, 1, 1)\n const [r, g, b] = ctx.getImageData(0, 0, 1, 1).data\n return `#${((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1)}`\n}\n\nfunction getThemeColors(): ThemeColors {\n if (typeof document === 'undefined') {\n return {\n background: '#ffffff',\n foreground: '#000000',\n primary: '#6366f1',\n primaryContent: '#ffffff',\n secondary: '#f000b8',\n accent: '#37cdbe',\n info: '#3abff8',\n success: '#36d399',\n warning: '#fbbd23',\n error: '#f87272',\n }\n }\n\n const style = getComputedStyle(document.documentElement)\n const getColor = (varName: string, fallback: string): string => {\n const value = style.getPropertyValue(varName).trim()\n return value ? colorToHex(value) : fallback\n }\n\n return {\n background: getColor('--color-base-100', '#ffffff'),\n foreground: getColor('--color-base-content', '#000000'),\n primary: getColor('--color-primary', '#6366f1'),\n primaryContent: getColor('--color-primary-content', '#ffffff'),\n secondary: getColor('--color-secondary', '#f000b8'),\n accent: getColor('--color-accent', '#37cdbe'),\n info: getColor('--color-info', '#3abff8'),\n success: getColor('--color-success', '#36d399'),\n warning: getColor('--color-warning', '#fbbd23'),\n error: getColor('--color-error', '#f87272'),\n }\n}\n\nfunction getSystemTheme(): 'light' | 'dark' {\n if (typeof window === 'undefined') return 'light'\n return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'\n}\n\nfunction getStoredTheme(key: string | false): string | null {\n if (!key || typeof window === 'undefined') return null\n try {\n return localStorage.getItem(key)\n } catch {\n return null\n }\n}\n\nfunction storeTheme(key: string | false, theme: string): void {\n if (!key || typeof window === 'undefined') return\n try {\n localStorage.setItem(key, theme)\n } catch {\n // Ignore storage errors\n }\n}\n\nexport function ThemeProvider({\n children,\n defaultTheme = 'system',\n storageKey = 'asterui-theme',\n lightTheme = 'light',\n darkTheme = 'dark',\n isDarkTheme,\n}: ThemeProviderProps) {\n // Initialize theme from storage or default\n const [theme, setThemeState] = useState<string>(() => {\n const stored = getStoredTheme(storageKey)\n return stored || defaultTheme\n })\n\n // Track system preference\n const [systemTheme, setSystemTheme] = useState<'light' | 'dark'>(getSystemTheme)\n\n // Resolve the actual theme\n const resolvedTheme = useMemo(() => {\n if (theme === 'system') {\n return systemTheme === 'dark' ? darkTheme : lightTheme\n }\n return theme\n }, [theme, systemTheme, lightTheme, darkTheme])\n\n // Determine if dark\n const isDark = useMemo(() => {\n if (isDarkTheme) return isDarkTheme(resolvedTheme)\n return DARK_THEMES.has(resolvedTheme)\n }, [resolvedTheme, isDarkTheme])\n\n // Track colors (updated after theme applies)\n const [colors, setColors] = useState<ThemeColors>(getThemeColors)\n\n // Set theme function\n const setTheme = useCallback((newTheme: string) => {\n setThemeState(newTheme)\n storeTheme(storageKey, newTheme)\n }, [storageKey])\n\n // Apply theme to document\n useEffect(() => {\n if (typeof document === 'undefined') return\n document.documentElement.setAttribute('data-theme', resolvedTheme)\n\n // Double RAF ensures CSS has fully recalculated after attribute change\n requestAnimationFrame(() => {\n requestAnimationFrame(() => {\n setColors(getThemeColors())\n })\n })\n }, [resolvedTheme])\n\n // Listen for system preference changes\n useEffect(() => {\n if (typeof window === 'undefined') return\n\n const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)')\n const handleChange = (e: MediaQueryListEvent) => {\n setSystemTheme(e.matches ? 'dark' : 'light')\n }\n\n mediaQuery.addEventListener('change', handleChange)\n return () => mediaQuery.removeEventListener('change', handleChange)\n }, [])\n\n // Listen for storage changes (cross-tab sync)\n useEffect(() => {\n if (!storageKey || typeof window === 'undefined') return\n\n const handleStorage = (e: StorageEvent) => {\n if (e.key === storageKey && e.newValue) {\n setThemeState(e.newValue)\n }\n }\n\n window.addEventListener('storage', handleStorage)\n return () => window.removeEventListener('storage', handleStorage)\n }, [storageKey])\n\n const value = useMemo<ThemeContextValue>(() => ({\n theme,\n resolvedTheme,\n isDark,\n setTheme,\n colors,\n systemTheme,\n }), [theme, resolvedTheme, isDark, setTheme, colors, systemTheme])\n\n return (\n <ThemeContext.Provider value={value}>\n {children}\n </ThemeContext.Provider>\n )\n}\n\n/**\n * Hook to access theme context.\n * Must be used within a ThemeProvider.\n */\nexport function useThemeContext(): ThemeContextValue {\n const context = useContext(ThemeContext)\n if (!context) {\n throw new Error('useThemeContext must be used within a ThemeProvider')\n }\n return context\n}\n\n/**\n * Check if ThemeProvider is present in the tree.\n */\nexport function useHasThemeProvider(): boolean {\n return useContext(ThemeContext) !== undefined\n}\n"],"names":["DARK_THEMES","ThemeContext","createContext","colorToHex","color","canvas","ctx","r","g","b","getThemeColors","style","getColor","varName","fallback","value","getSystemTheme","getStoredTheme","key","storeTheme","theme","ThemeProvider","children","defaultTheme","storageKey","lightTheme","darkTheme","isDarkTheme","setThemeState","useState","systemTheme","setSystemTheme","resolvedTheme","useMemo","isDark","colors","setColors","setTheme","useCallback","newTheme","useEffect","mediaQuery","handleChange","e","handleStorage","jsx","useThemeContext","context","useContext","useHasThemeProvider"],"mappings":"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"}
File without changes