asterui 0.12.57 → 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.
- package/dist/components/Autocomplete.js +1 -1
- package/dist/components/Autocomplete.js.map +1 -1
- package/dist/components/Button.js +1 -1
- package/dist/components/Button.js.map +1 -1
- package/dist/components/Checkbox.js +1 -1
- package/dist/components/Checkbox.js.map +1 -1
- package/dist/components/ColorPicker.js +1 -1
- package/dist/components/ColorPicker.js.map +1 -1
- package/dist/components/CopyButton.js +1 -1
- package/dist/components/CopyButton.js.map +1 -1
- package/dist/components/Countdown.js +1 -1
- package/dist/components/Countdown.js.map +1 -1
- package/dist/components/DatePicker.js +1 -1
- package/dist/components/DatePicker.js.map +1 -1
- package/dist/components/Dock.js +1 -1
- package/dist/components/Dock.js.map +1 -1
- package/dist/components/Empty.js +1 -1
- package/dist/components/Empty.js.map +1 -1
- package/dist/components/FileInput.js +1 -1
- package/dist/components/FileInput.js.map +1 -1
- package/dist/components/Filter.js +1 -1
- package/dist/components/Filter.js.map +1 -1
- package/dist/components/Form.d.ts +10 -1
- package/dist/components/Form.js +205 -184
- package/dist/components/Form.js.map +1 -1
- package/dist/components/Input.js +1 -1
- package/dist/components/Input.js.map +1 -1
- package/dist/components/InputNumber.js +1 -1
- package/dist/components/InputNumber.js.map +1 -1
- package/dist/components/List.js +1 -1
- package/dist/components/List.js.map +1 -1
- package/dist/components/Loading.js +1 -1
- package/dist/components/Loading.js.map +1 -1
- package/dist/components/Modal.js +1 -1
- package/dist/components/Modal.js.map +1 -1
- package/dist/components/OTPInput.js +1 -1
- package/dist/components/OTPInput.js.map +1 -1
- package/dist/components/Pagination.js +1 -1
- package/dist/components/Pagination.js.map +1 -1
- package/dist/components/Popconfirm.js +1 -1
- package/dist/components/Popconfirm.js.map +1 -1
- package/dist/components/Radio.js +1 -1
- package/dist/components/Radio.js.map +1 -1
- package/dist/components/Range.js +1 -1
- package/dist/components/Range.js.map +1 -1
- package/dist/components/Rating.js +1 -1
- package/dist/components/Rating.js.map +1 -1
- package/dist/components/RichTextEditor.js +1 -1
- package/dist/components/RichTextEditor.js.map +1 -1
- package/dist/components/Segmented.js +1 -1
- package/dist/components/Segmented.js.map +1 -1
- package/dist/components/Select.js +1 -1
- package/dist/components/Select.js.map +1 -1
- package/dist/components/Table.d.ts +19 -0
- package/dist/components/Table.js +348 -310
- package/dist/components/Table.js.map +1 -1
- package/dist/components/Tabs.js +1 -1
- package/dist/components/Tabs.js.map +1 -1
- package/dist/components/Textarea.js +1 -1
- package/dist/components/Textarea.js.map +1 -1
- package/dist/components/ThemeController.js +1 -1
- package/dist/components/ThemeController.js.map +1 -1
- package/dist/components/TimePicker.js +1 -1
- package/dist/components/TimePicker.js.map +1 -1
- package/dist/components/Toggle.js +1 -1
- package/dist/components/Toggle.js.map +1 -1
- package/dist/hooks/useTheme.d.ts +1 -1
- package/dist/hooks/useTheme.js +1 -1
- package/dist/hooks/useTheme.js.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.js +2 -2
- package/dist/providers/ConfigProvider.js.map +1 -0
- package/dist/providers/ThemeProvider.js.map +1 -0
- package/package.json +1 -1
- package/dist/components/ConfigProvider.js.map +0 -1
- package/dist/components/ThemeProvider.js.map +0 -1
- /package/dist/{components → providers}/ConfigProvider.d.ts +0 -0
- /package/dist/{components → providers}/ConfigProvider.js +0 -0
- /package/dist/{components → providers}/ThemeProvider.d.ts +0 -0
- /package/dist/{components → providers}/ThemeProvider.js +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Form.js","sources":["../../src/components/Form.tsx"],"sourcesContent":["import React, { createContext, useContext, cloneElement, isValidElement, useId, useEffect, useRef } from 'react'\nimport { useForm, UseFormReturn, FieldValues, SubmitHandler, UseFormProps, Controller, useFieldArray, FieldArrayPath, FieldArray, useWatch } from 'react-hook-form'\nimport { useConfig } from './ConfigProvider'\n\n// DaisyUI classes\nconst dInput = 'input'\nconst dInputXs = 'input-xs'\nconst dInputSm = 'input-sm'\nconst dInputMd = 'input-md'\nconst dInputLg = 'input-lg'\nconst dInputXl = 'input-xl'\nconst dFloatingLabel = 'floating-label'\nconst dLoading = 'loading'\nconst dLoadingSpinner = 'loading-spinner'\nconst dLoadingXs = 'loading-xs'\nconst dTooltip = 'tooltip'\nconst dTooltipTop = 'tooltip-top'\n\ninterface FormContextValue {\n form: UseFormReturn<any>\n layout?: 'vertical' | 'horizontal' | 'inline'\n size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'\n labelWidth?: number\n listName?: string\n disabled?: boolean\n}\n\nconst FormContext = createContext<FormContextValue | undefined>(undefined)\n\n// Built-in type validators\nconst TYPE_VALIDATORS = {\n email: {\n value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,}$/i,\n message: 'Please enter a valid email address',\n },\n url: {\n value: /^https?:\\/\\/(www\\.)?[-a-zA-Z0-9@:%._\\+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b([-a-zA-Z0-9()@:%_\\+.~#?&//=]*)$/,\n message: 'Please enter a valid URL',\n },\n number: {\n value: /^-?\\d+(\\.\\d+)?$/,\n message: 'Please enter a valid number',\n },\n}\n\nexport interface FormProps<TFieldValues extends FieldValues = FieldValues>\n extends Omit<React.FormHTMLAttributes<HTMLFormElement>, 'onSubmit'> {\n form?: UseFormReturn<TFieldValues>\n onFinish?: SubmitHandler<TFieldValues>\n /** Called when form validation fails */\n onFinishFailed?: (errorInfo: { values: TFieldValues; errorFields: Array<{ name: string; errors: string[] }> }) => void\n initialValues?: UseFormProps<TFieldValues>['defaultValues']\n layout?: 'vertical' | 'horizontal' | 'inline'\n /** Label width in pixels for horizontal layout (default: 80) */\n labelWidth?: number\n size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'\n /** Disable all form fields */\n disabled?: boolean\n children: React.ReactNode\n /** Test ID for the form element */\n 'data-testid'?: string\n}\n\nexport interface FormRule {\n required?: boolean | string\n type?: 'email' | 'url' | 'number'\n min?: number | { value: number; message: string }\n max?: number | { value: number; message: string }\n pattern?: RegExp | { value: RegExp; message: string }\n message?: string\n validate?: (value: any) => boolean | string | Promise<boolean | string>\n}\n\nexport type ValidateTrigger = 'onChange' | 'onBlur' | 'onSubmit' | ('onChange' | 'onBlur' | 'onSubmit')[]\n\nexport interface FormItemProps {\n name?: string | string[]\n label?: string\n /** Floating label text (alternative to label, uses DaisyUI floating-label) */\n floatingLabel?: string\n help?: string\n required?: boolean\n rules?: FormRule | FormRule[]\n valuePropName?: string\n inline?: boolean\n className?: string\n children: React.ReactElement\n /** Tooltip text to show next to label */\n tooltip?: string\n /** Additional content below the form control */\n extra?: React.ReactNode\n /** Show validation feedback icon */\n hasFeedback?: boolean\n /** Field names that this field depends on for validation */\n dependencies?: string[]\n /** When to trigger validation */\n validateTrigger?: ValidateTrigger\n /** Initial value for this field (overrides Form's initialValues) */\n initialValue?: any\n /** Hide this field (still validates and submits) */\n hidden?: boolean\n /** Text/element before input (outside, using DaisyUI label) */\n addonBefore?: React.ReactNode\n /** Text/element after input (outside, using DaisyUI label) */\n addonAfter?: React.ReactNode\n /** Test ID for the form item (used as prefix for child elements) */\n 'data-testid'?: string\n}\n\nexport interface FormListProps<TFieldValues extends FieldValues = FieldValues> {\n name: FieldArrayPath<TFieldValues>\n children: (\n fields: FieldArray<TFieldValues>[],\n operations: {\n add: (value?: any) => void\n remove: (index: number) => void\n move: (from: number, to: number) => void\n }\n ) => React.ReactNode\n}\n\nfunction useFormContext() {\n const context = useContext(FormContext)\n if (!context) {\n throw new Error('Form compound components must be used within Form')\n }\n return context\n}\n\nfunction FormRoot<TFieldValues extends FieldValues = FieldValues>({\n form: externalForm,\n onFinish,\n onFinishFailed,\n initialValues,\n layout = 'vertical',\n labelWidth = 60,\n size,\n disabled = false,\n children,\n className = '',\n noValidate = true,\n ...props\n}: FormProps<TFieldValues>) {\n const { componentSize } = useConfig()\n const effectiveSize = size ?? componentSize ?? 'md'\n\n const internalForm = useForm<TFieldValues>({\n defaultValues: initialValues,\n })\n\n const form = externalForm || internalForm\n\n const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {\n e.preventDefault()\n\n // Trigger validation\n const isValid = await form.trigger()\n\n if (isValid) {\n if (onFinish) {\n onFinish(form.getValues())\n }\n } else {\n if (onFinishFailed) {\n const errors = form.formState.errors\n const errorFields: Array<{ name: string; errors: string[] }> = []\n\n // Flatten errors into errorFields array\n const flattenErrors = (obj: any, prefix = '') => {\n for (const key in obj) {\n const fullKey = prefix ? `${prefix}.${key}` : key\n const value = obj[key]\n if (value?.message) {\n errorFields.push({ name: fullKey, errors: [value.message as string] })\n } else if (typeof value === 'object' && value !== null) {\n flattenErrors(value, fullKey)\n }\n }\n }\n flattenErrors(errors)\n\n onFinishFailed({ values: form.getValues(), errorFields })\n }\n }\n }\n\n const handleReset = (e: React.FormEvent<HTMLFormElement>) => {\n e.preventDefault()\n form.reset(initialValues as any)\n }\n\n return (\n <FormContext.Provider value={{ form, layout, labelWidth, size: effectiveSize, disabled }}>\n <form onSubmit={handleSubmit} onReset={handleReset} className={className} noValidate={noValidate} {...props}>\n {children}\n </form>\n </FormContext.Provider>\n )\n}\n\nfunction FormItem({\n name,\n label,\n floatingLabel,\n help,\n required = false,\n rules,\n valuePropName = 'value',\n inline = false,\n className = '',\n children,\n tooltip,\n extra,\n hasFeedback = false,\n dependencies,\n validateTrigger = 'onChange',\n initialValue,\n hidden = false,\n addonBefore,\n addonAfter,\n 'data-testid': testId,\n}: FormItemProps) {\n const { form, size, listName, layout, labelWidth, disabled: formDisabled } = useFormContext()\n const inputId = useId()\n const errorId = useId()\n\n if (!name) {\n // Render without form control if no name provided\n return <div className={`${inline ? 'w-auto' : 'w-full'} ${className}`} style={hidden ? { display: 'none' } : undefined}>{children}</div>\n }\n\n // Handle nested field names (for Form.List)\n let fieldName: string\n if (Array.isArray(name)) {\n // If we're inside a Form.List, prepend the list name\n const fullPath = listName ? [listName, ...name] : name\n fieldName = fullPath.join('.')\n } else {\n fieldName = name\n }\n\n // Set initial value if provided\n useEffect(() => {\n if (initialValue !== undefined) {\n const currentValue = form.getValues(fieldName as any)\n if (currentValue === undefined) {\n form.setValue(fieldName as any, initialValue)\n }\n }\n }, []) // eslint-disable-line react-hooks/exhaustive-deps\n\n // Watch dependencies and re-validate when they change\n const watchedDeps = useWatch({\n control: form.control,\n name: dependencies as any,\n disabled: !dependencies || dependencies.length === 0,\n })\n\n // Use refs to avoid infinite loops\n const formRef = useRef(form)\n formRef.current = form\n const prevDepsRef = useRef<string | undefined>(undefined)\n\n useEffect(() => {\n // Skip if no dependencies\n if (!dependencies || dependencies.length === 0) return\n\n // Skip initial render\n if (prevDepsRef.current === undefined) {\n prevDepsRef.current = JSON.stringify(watchedDeps)\n return\n }\n\n // Only trigger if dependency values actually changed\n const currentDeps = JSON.stringify(watchedDeps)\n if (prevDepsRef.current !== currentDeps) {\n prevDepsRef.current = currentDeps\n formRef.current.trigger(fieldName as any)\n }\n }, [watchedDeps, dependencies, fieldName])\n\n // Get error by traversing the error object path\n const getErrorByPath = (path: string) => {\n const keys = path.split('.')\n let error: any = form.formState.errors\n for (const key of keys) {\n if (!error) break\n error = error[key]\n }\n return error\n }\n\n const error = getErrorByPath(fieldName)\n const errorMessage = error?.message as string | undefined\n\n // Normalize rules to array\n const rulesArray: FormRule[] = rules\n ? Array.isArray(rules) ? rules : [rules]\n : []\n\n // Build validation rules\n const validationRules: any = {}\n const patternValidators: Array<{ pattern: RegExp; message: string }> = []\n const customValidators: Array<(value: any) => boolean | string | Promise<boolean | string>> = []\n\n // Handle top-level required prop\n if (required) {\n validationRules.required = 'This field is required'\n }\n\n // Process each rule\n for (const rule of rulesArray) {\n // Required\n if (rule.required) {\n validationRules.required = typeof rule.required === 'string'\n ? rule.required\n : rule.message || 'This field is required'\n }\n\n // Type validator\n if (rule.type && TYPE_VALIDATORS[rule.type]) {\n patternValidators.push({\n pattern: TYPE_VALIDATORS[rule.type].value,\n message: rule.message || TYPE_VALIDATORS[rule.type].message,\n })\n }\n\n // Min length\n if (rule.min !== undefined) {\n const minValue = typeof rule.min === 'object' ? rule.min.value : rule.min\n const minMessage = typeof rule.min === 'object'\n ? rule.min.message\n : rule.message || `Minimum length is ${minValue} characters`\n validationRules.minLength = { value: minValue, message: minMessage }\n }\n\n // Max length\n if (rule.max !== undefined) {\n const maxValue = typeof rule.max === 'object' ? rule.max.value : rule.max\n const maxMessage = typeof rule.max === 'object'\n ? rule.max.message\n : rule.message || `Maximum length is ${maxValue} characters`\n validationRules.maxLength = { value: maxValue, message: maxMessage }\n }\n\n // Pattern - collect all patterns\n if (rule.pattern) {\n const patternValue = rule.pattern instanceof RegExp ? rule.pattern : rule.pattern.value\n const patternMessage = rule.pattern instanceof RegExp\n ? rule.message || 'Invalid format'\n : rule.pattern.message\n patternValidators.push({ pattern: patternValue, message: patternMessage })\n }\n\n // Custom validator\n if (rule.validate) {\n customValidators.push(rule.validate)\n }\n }\n\n // Combine all pattern and custom validators into a single validate function\n if (patternValidators.length > 0 || customValidators.length > 0) {\n validationRules.validate = async (value: any) => {\n // Skip validation if empty (required rule handles that)\n if (!value && !validationRules.required) return true\n\n // Check all patterns\n for (const { pattern, message } of patternValidators) {\n if (value && !pattern.test(value)) {\n return message\n }\n }\n\n // Run all custom validators\n for (const validator of customValidators) {\n const result = await validator(value)\n if (result !== true) {\n return result\n }\n }\n\n return true\n }\n }\n\n // Normalize validateTrigger to array\n const triggers = Array.isArray(validateTrigger) ? validateTrigger : [validateTrigger]\n const shouldValidateOnChange = triggers.includes('onChange')\n const shouldValidateOnBlur = triggers.includes('onBlur')\n\n // Feedback icons\n const FeedbackIcon = ({ hasError, isValidating }: { hasError: boolean; isValidating: boolean }) => {\n if (isValidating) {\n return (\n <span className={`${dLoading} ${dLoadingSpinner} ${dLoadingXs} text-base-content/50`} />\n )\n }\n if (hasError) {\n return (\n <svg className=\"w-4 h-4 text-error\" 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 )\n }\n return (\n <svg className=\"w-4 h-4 text-success\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M5 13l4 4L19 7\" />\n </svg>\n )\n }\n\n // Tooltip icon\n const TooltipIcon = () => (\n <div className={`${dTooltip} ${dTooltipTop} ml-1`} data-tip={tooltip}>\n <svg className=\"w-4 h-4 text-base-content/50 cursor-help\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z\" />\n </svg>\n </div>\n )\n\n return (\n <Controller\n name={fieldName}\n control={form.control}\n rules={validationRules}\n render={({ field, fieldState }) => {\n const { value, onChange, onBlur, ref } = field\n const isValidating = fieldState.isTouched && form.formState.isValidating\n\n // Clone the child element and inject form control props\n const childProps: any = {\n id: inputId,\n ref,\n 'aria-invalid': error ? true : undefined,\n 'aria-describedby': error ? errorId : undefined,\n 'data-testid': testId ? `${testId}-input` : undefined,\n }\n\n // Handle onBlur based on validateTrigger\n childProps.onBlur = () => {\n onBlur()\n if (shouldValidateOnBlur) {\n form.trigger(fieldName as any)\n }\n }\n\n // Handle different value prop names (e.g., 'checked' for checkboxes)\n if (valuePropName === 'checked') {\n childProps.checked = value\n childProps.onChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n onChange(e.target.checked)\n if (shouldValidateOnChange) {\n form.trigger(fieldName as any)\n }\n }\n } else {\n childProps.value = value || ''\n childProps.onChange = (eventOrValue: any) => {\n // Handle components that pass value directly (e.g., Range, Rating)\n // vs components that pass event object (e.g., Input, Select)\n if (eventOrValue && eventOrValue.target !== undefined) {\n onChange(eventOrValue.target.value)\n } else {\n onChange(eventOrValue)\n }\n if (shouldValidateOnChange) {\n form.trigger(fieldName as any)\n }\n }\n }\n\n // Apply size if specified at form level\n if (size && isValidElement(children)) {\n const existingProps = children.props as any\n if (!existingProps.size) {\n childProps.size = size\n }\n }\n\n // Apply error styling and accessibility\n if (error) {\n childProps.color = 'error'\n childProps['aria-invalid'] = true\n }\n\n // Apply form-level disabled state\n if (formDisabled) {\n childProps.disabled = true\n }\n\n // When wrapped with addons, the child input should be unstyled (the wrapper has the styling)\n const hasAddons = addonBefore || addonAfter\n if (hasAddons) {\n childProps.unstyled = true\n }\n\n const enhancedChild = isValidElement(children)\n ? cloneElement(children as React.ReactElement<any>, childProps)\n : children\n\n const isHorizontal = layout === 'horizontal'\n const isInline = layout === 'inline'\n\n // Size class for floating label\n const floatingSizeClasses: Record<string, string> = {\n xs: dInputXs,\n sm: dInputSm,\n md: dInputMd,\n lg: dInputLg,\n xl: dInputXl,\n }\n\n // Build the input element with optional floating label wrapper\n const renderInputElement = () => {\n const inputWithFeedback = (\n <div className={`${isHorizontal ? 'flex-1' : ''} ${hasFeedback ? 'relative' : ''}`}>\n {enhancedChild}\n {hasFeedback && fieldState.isTouched && (\n <span className=\"absolute right-3 top-1/2 -translate-y-1/2 pointer-events-none\">\n <FeedbackIcon hasError={!!error} isValidating={isValidating} />\n </span>\n )}\n </div>\n )\n\n // Floating label variant\n if (floatingLabel) {\n const floatingClasses = [\n dFloatingLabel,\n size && floatingSizeClasses[size],\n ].filter(Boolean).join(' ')\n\n return (\n <label className={floatingClasses}>\n {enhancedChild}\n <span>{floatingLabel}{required && <span className=\"text-error ml-1\">*</span>}</span>\n </label>\n )\n }\n\n return inputWithFeedback\n }\n\n // Wrap with external addons if specified using DaisyUI input wrapper pattern\n const renderWithAddons = (input: React.ReactNode) => {\n if (!addonBefore && !addonAfter) return input\n\n const addonClasses = [\n dInput,\n 'flex',\n 'items-center',\n 'gap-2',\n size && floatingSizeClasses[size],\n ].filter(Boolean).join(' ')\n\n return (\n <label className={addonClasses}>\n {addonBefore && <span className=\"text-base-content/70\">{addonBefore}</span>}\n {input}\n {addonAfter && <span className=\"text-base-content/70\">{addonAfter}</span>}\n </label>\n )\n }\n\n return (\n <div className={`${inline ? 'w-auto' : 'w-full'} ${isHorizontal ? 'mb-4' : ''} ${isInline ? 'inline-flex mr-4' : ''} ${className}`} style={hidden ? { display: 'none' } : undefined} data-testid={testId}>\n <div className={isHorizontal ? 'flex items-center gap-4' : ''}>\n {label && !floatingLabel && (\n <label\n htmlFor={inputId}\n className={`block text-sm font-medium ${isHorizontal ? 'flex-shrink-0 text-right' : ''} ${!isHorizontal && !isInline ? 'mb-1' : ''}`}\n style={isHorizontal ? { width: labelWidth } : undefined}\n data-testid={testId ? `${testId}-label` : undefined}\n >\n <span className=\"flex items-center\">\n {label}\n {required && <span className=\"text-error ml-1\">*</span>}\n {tooltip && <TooltipIcon />}\n </span>\n </label>\n )}\n {renderWithAddons(renderInputElement())}\n </div>\n {!isHorizontal && !inline && (\n <p id={errorId} className={`validator-hint ${errorMessage ? '!visible text-error' : ''} min-h-[1.25rem]`} role={errorMessage ? 'alert' : undefined} data-testid={testId ? `${testId}-error` : undefined}>\n {errorMessage || (help && <span className=\"text-base-content/70\">{help}</span>) || '\\u00A0'}\n </p>\n )}\n {isHorizontal && (errorMessage || help) && (\n <p id={errorId} className={`validator-hint ${errorMessage ? '!visible text-error' : ''} min-h-[1.25rem]`} role={errorMessage ? 'alert' : undefined} data-testid={testId ? `${testId}-error` : undefined}>\n {errorMessage || (help && <span className=\"text-base-content/70\">{help}</span>)}\n </p>\n )}\n {extra && (\n <div className=\"text-sm text-base-content/60 mt-1\" data-testid={testId ? `${testId}-extra` : undefined}>{extra}</div>\n )}\n </div>\n )\n }}\n />\n )\n}\n\nfunction FormList<TFieldValues extends FieldValues = FieldValues>({\n name,\n children,\n}: FormListProps<TFieldValues>) {\n const { form, layout, size, disabled } = useFormContext()\n\n const { fields, append, remove, move } = useFieldArray({\n control: form.control,\n name,\n })\n\n // Add name (index) to each field for proper path construction\n const fieldsWithName = fields.map((field, index) => ({\n ...field,\n name: index,\n }))\n\n return (\n <FormContext.Provider value={{ form, layout, size, listName: name as string, disabled }}>\n {children(fieldsWithName as any, {\n add: append,\n remove,\n move,\n })}\n </FormContext.Provider>\n )\n}\n\n// Enhanced hook to expose full form API\nexport function useFormInstance<TFieldValues extends FieldValues = FieldValues>() {\n const formInstance = useForm<TFieldValues>()\n\n // Add convenience methods to the instance\n const enhancedInstance = formInstance as typeof formInstance & {\n setFieldValue: typeof formInstance.setValue\n getFieldValue: (name: any) => any\n getFieldsValue: typeof formInstance.getValues\n setFieldsValue: (values: any) => void\n validateFields: typeof formInstance.trigger\n resetFields: typeof formInstance.reset\n isFieldTouched: (name: string) => boolean\n getFieldError: (name: string) => string | undefined\n }\n\n // Add the alias methods\n enhancedInstance.setFieldValue = formInstance.setValue\n enhancedInstance.getFieldValue = (name: any) => formInstance.getValues(name)\n enhancedInstance.getFieldsValue = formInstance.getValues\n enhancedInstance.setFieldsValue = (values: any) => {\n Object.keys(values).forEach((key) => {\n formInstance.setValue(key as any, values[key])\n })\n }\n enhancedInstance.validateFields = formInstance.trigger\n enhancedInstance.resetFields = formInstance.reset\n enhancedInstance.isFieldTouched = (name: string) => {\n const touched = formInstance.formState.touchedFields as any\n return !!touched[name]\n }\n enhancedInstance.getFieldError = (name: string) => {\n const errors = formInstance.formState.errors as any\n return errors[name]?.message as string | undefined\n }\n\n return enhancedInstance\n}\n\nexport interface FormErrorListProps {\n /** Specific field names to show errors for (shows all errors if not specified) */\n fields?: string[]\n /** Custom className */\n className?: string\n /** Test ID for the error list */\n 'data-testid'?: string\n}\n\nfunction FormErrorList({ fields, className = '', 'data-testid': testId }: FormErrorListProps) {\n const { form } = useFormContext()\n const { errors } = form.formState\n\n // Flatten nested errors into a list\n const flattenErrors = (obj: any, prefix = ''): Array<{ field: string; message: string }> => {\n const result: Array<{ field: string; message: string }> = []\n\n for (const key in obj) {\n const fullKey = prefix ? `${prefix}.${key}` : key\n const value = obj[key]\n\n if (value?.message) {\n result.push({ field: fullKey, message: value.message as string })\n } else if (typeof value === 'object' && value !== null) {\n result.push(...flattenErrors(value, fullKey))\n }\n }\n\n return result\n }\n\n const allErrors = flattenErrors(errors)\n const filteredErrors = fields\n ? allErrors.filter(e => fields.includes(e.field))\n : allErrors\n\n if (filteredErrors.length === 0) {\n return null\n }\n\n return (\n <ul className={`text-error text-sm space-y-1 ${className}`} role=\"alert\" data-testid={testId}>\n {filteredErrors.map((error, index) => (\n <li key={`${error.field}-${index}`} className=\"flex items-start gap-2\" data-testid={testId ? `${testId}-${error.field}` : undefined}>\n <svg className=\"w-4 h-4 mt-0.5 flex-shrink-0\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z\" />\n </svg>\n <span>{error.message}</span>\n </li>\n ))}\n </ul>\n )\n}\n\nexport const Form = Object.assign(FormRoot, {\n Item: FormItem,\n List: FormList,\n ErrorList: FormErrorList,\n useForm: useFormInstance,\n})\n\nexport type { UseFormReturn as FormInstance }\n"],"names":["dInput","dInputXs","dInputSm","dInputMd","dInputLg","dInputXl","dFloatingLabel","dLoading","dLoadingSpinner","dLoadingXs","dTooltip","dTooltipTop","FormContext","createContext","TYPE_VALIDATORS","useFormContext","context","useContext","FormRoot","externalForm","onFinish","onFinishFailed","initialValues","layout","labelWidth","size","disabled","children","className","noValidate","props","componentSize","useConfig","effectiveSize","internalForm","useForm","form","handleSubmit","e","errors","errorFields","flattenErrors","obj","prefix","key","fullKey","value","handleReset","jsx","FormItem","name","label","floatingLabel","help","required","rules","valuePropName","inline","tooltip","extra","hasFeedback","dependencies","validateTrigger","initialValue","hidden","addonBefore","addonAfter","testId","listName","formDisabled","inputId","useId","errorId","fieldName","useEffect","watchedDeps","useWatch","formRef","useRef","prevDepsRef","currentDeps","error","path","keys","errorMessage","rulesArray","validationRules","patternValidators","customValidators","rule","minValue","minMessage","maxValue","maxMessage","patternValue","patternMessage","pattern","message","validator","result","triggers","shouldValidateOnChange","shouldValidateOnBlur","FeedbackIcon","hasError","isValidating","TooltipIcon","Controller","field","fieldState","onChange","onBlur","ref","childProps","eventOrValue","isValidElement","enhancedChild","cloneElement","isHorizontal","isInline","floatingSizeClasses","renderInputElement","inputWithFeedback","jsxs","floatingClasses","renderWithAddons","input","addonClasses","FormList","fields","append","remove","move","useFieldArray","fieldsWithName","index","useFormInstance","formInstance","enhancedInstance","values","FormErrorList","allErrors","filteredErrors","Form"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Form.js","sources":["../../src/components/Form.tsx"],"sourcesContent":["import React, { createContext, useContext, cloneElement, isValidElement, useId, useEffect, useRef } from 'react'\nimport { useForm, UseFormReturn, FieldValues, SubmitHandler, UseFormProps, Controller, useFieldArray, FieldArrayPath, FieldArray, useWatch } from 'react-hook-form'\nimport { useConfig } from '../providers/ConfigProvider'\n\n// DaisyUI classes\nconst dInput = 'input'\nconst dInputXs = 'input-xs'\nconst dInputSm = 'input-sm'\nconst dInputMd = 'input-md'\nconst dInputLg = 'input-lg'\nconst dInputXl = 'input-xl'\nconst dFloatingLabel = 'floating-label'\nconst dLoading = 'loading'\nconst dLoadingSpinner = 'loading-spinner'\nconst dLoadingXs = 'loading-xs'\nconst dTooltip = 'tooltip'\nconst dTooltipTop = 'tooltip-top'\nconst dValidatorHint = 'validator-hint'\n\ninterface FormContextValue {\n form: UseFormReturn<any>\n layout?: 'vertical' | 'horizontal' | 'inline'\n size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'\n labelWidth?: number\n listName?: string\n disabled?: boolean\n}\n\nconst FormContext = createContext<FormContextValue | undefined>(undefined)\n\n// Built-in type validators\nconst TYPE_VALIDATORS = {\n email: {\n value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,}$/i,\n message: 'Please enter a valid email address',\n },\n url: {\n value: /^https?:\\/\\/(www\\.)?[-a-zA-Z0-9@:%._\\+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b([-a-zA-Z0-9()@:%_\\+.~#?&//=]*)$/,\n message: 'Please enter a valid URL',\n },\n number: {\n value: /^-?\\d+(\\.\\d+)?$/,\n message: 'Please enter a valid number',\n },\n}\n\nexport interface FormProps<TFieldValues extends FieldValues = FieldValues>\n extends Omit<React.FormHTMLAttributes<HTMLFormElement>, 'onSubmit'> {\n form?: UseFormReturn<TFieldValues>\n onFinish?: SubmitHandler<TFieldValues>\n /** Called when form validation fails */\n onFinishFailed?: (errorInfo: { values: TFieldValues; errorFields: Array<{ name: string; errors: string[] }> }) => void\n initialValues?: UseFormProps<TFieldValues>['defaultValues']\n layout?: 'vertical' | 'horizontal' | 'inline'\n /** Label width in pixels for horizontal layout (default: 80) */\n labelWidth?: number\n size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'\n /** Disable all form fields */\n disabled?: boolean\n children: React.ReactNode\n /** Test ID for the form element */\n 'data-testid'?: string\n}\n\nexport interface FormRule {\n required?: boolean | string\n type?: 'email' | 'url' | 'number'\n min?: number | { value: number; message: string }\n max?: number | { value: number; message: string }\n pattern?: RegExp | { value: RegExp; message: string }\n message?: string\n validate?: (value: any) => boolean | string | Promise<boolean | string>\n /** Ant Design style validator (for compatibility) */\n validator?: (rule: any, value: any) => Promise<void>\n}\n\n/** Form methods passed to rule functions (Ant Design style) */\nexport interface FormRuleMethods {\n getFieldValue: (name: string) => any\n getFieldsValue: () => any\n}\n\n/** A rule can be an object or a function that returns a rule object */\nexport type FormRuleInput = FormRule | ((methods: FormRuleMethods) => FormRule)\n\nexport type ValidateTrigger = 'onChange' | 'onBlur' | 'onSubmit' | ('onChange' | 'onBlur' | 'onSubmit')[]\n\nexport interface FormItemProps {\n name?: string | string[]\n label?: string\n /** Floating label text (alternative to label, uses DaisyUI floating-label) */\n floatingLabel?: string\n help?: string\n required?: boolean\n rules?: FormRuleInput | FormRuleInput[]\n valuePropName?: string\n inline?: boolean\n className?: string\n children: React.ReactElement\n /** Tooltip text to show next to label */\n tooltip?: string\n /** Additional content below the form control */\n extra?: React.ReactNode\n /** Show validation feedback icon */\n hasFeedback?: boolean\n /** Field names that this field depends on for validation */\n dependencies?: string[]\n /** When to trigger validation */\n validateTrigger?: ValidateTrigger\n /** Initial value for this field (overrides Form's initialValues) */\n initialValue?: any\n /** Hide this field (still validates and submits) */\n hidden?: boolean\n /** Text/element before input (outside, using DaisyUI label) */\n addonBefore?: React.ReactNode\n /** Text/element after input (outside, using DaisyUI label) */\n addonAfter?: React.ReactNode\n /** Test ID for the form item (used as prefix for child elements) */\n 'data-testid'?: string\n}\n\nexport interface FormListProps<TFieldValues extends FieldValues = FieldValues> {\n name: FieldArrayPath<TFieldValues>\n children: (\n fields: FieldArray<TFieldValues>[],\n operations: {\n add: (value?: any) => void\n remove: (index: number) => void\n move: (from: number, to: number) => void\n }\n ) => React.ReactNode\n}\n\nfunction useFormContext() {\n const context = useContext(FormContext)\n if (!context) {\n throw new Error('Form compound components must be used within Form')\n }\n return context\n}\n\nfunction FormRoot<TFieldValues extends FieldValues = FieldValues>({\n form: externalForm,\n onFinish,\n onFinishFailed,\n initialValues,\n layout = 'vertical',\n labelWidth = 60,\n size,\n disabled = false,\n children,\n className = '',\n noValidate = true,\n ...props\n}: FormProps<TFieldValues>) {\n const { componentSize } = useConfig()\n const effectiveSize = size ?? componentSize ?? 'md'\n\n const internalForm = useForm<TFieldValues>({\n defaultValues: initialValues,\n })\n\n const form = externalForm || internalForm\n\n const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {\n e.preventDefault()\n\n // Trigger validation\n const isValid = await form.trigger()\n\n if (isValid) {\n if (onFinish) {\n onFinish(form.getValues())\n }\n } else {\n if (onFinishFailed) {\n const errors = form.formState.errors\n const errorFields: Array<{ name: string; errors: string[] }> = []\n\n // Flatten errors into errorFields array\n const flattenErrors = (obj: any, prefix = '') => {\n for (const key in obj) {\n const fullKey = prefix ? `${prefix}.${key}` : key\n const value = obj[key]\n if (value?.message) {\n errorFields.push({ name: fullKey, errors: [value.message as string] })\n } else if (typeof value === 'object' && value !== null) {\n flattenErrors(value, fullKey)\n }\n }\n }\n flattenErrors(errors)\n\n onFinishFailed({ values: form.getValues(), errorFields })\n }\n }\n }\n\n const handleReset = (e: React.FormEvent<HTMLFormElement>) => {\n e.preventDefault()\n form.reset(initialValues as any)\n }\n\n return (\n <FormContext.Provider value={{ form, layout, labelWidth, size: effectiveSize, disabled }}>\n <form onSubmit={handleSubmit} onReset={handleReset} className={className} noValidate={noValidate} {...props}>\n {children}\n </form>\n </FormContext.Provider>\n )\n}\n\nfunction FormItem({\n name,\n label,\n floatingLabel,\n help,\n required = false,\n rules,\n valuePropName = 'value',\n inline = false,\n className = '',\n children,\n tooltip,\n extra,\n hasFeedback = false,\n dependencies,\n validateTrigger = 'onChange',\n initialValue,\n hidden = false,\n addonBefore,\n addonAfter,\n 'data-testid': testId,\n}: FormItemProps) {\n const { form, size, listName, layout, labelWidth, disabled: formDisabled } = useFormContext()\n const inputId = useId()\n const errorId = useId()\n\n if (!name) {\n // Render without form control if no name provided\n return <div className={`${inline ? 'w-auto' : 'w-full'} ${className}`} style={hidden ? { display: 'none' } : undefined}>{children}</div>\n }\n\n // Handle nested field names (for Form.List)\n let fieldName: string\n if (Array.isArray(name)) {\n // If we're inside a Form.List, prepend the list name\n const fullPath = listName ? [listName, ...name] : name\n fieldName = fullPath.join('.')\n } else {\n fieldName = name\n }\n\n // Set initial value if provided\n useEffect(() => {\n if (initialValue !== undefined) {\n const currentValue = form.getValues(fieldName as any)\n if (currentValue === undefined) {\n form.setValue(fieldName as any, initialValue)\n }\n }\n }, []) // eslint-disable-line react-hooks/exhaustive-deps\n\n // Watch dependencies and re-validate when they change\n const watchedDeps = useWatch({\n control: form.control,\n name: dependencies as any,\n disabled: !dependencies || dependencies.length === 0,\n })\n\n // Use refs to avoid infinite loops\n const formRef = useRef(form)\n formRef.current = form\n const prevDepsRef = useRef<string | undefined>(undefined)\n\n useEffect(() => {\n // Skip if no dependencies\n if (!dependencies || dependencies.length === 0) return\n\n // Skip initial render\n if (prevDepsRef.current === undefined) {\n prevDepsRef.current = JSON.stringify(watchedDeps)\n return\n }\n\n // Only trigger if dependency values actually changed\n const currentDeps = JSON.stringify(watchedDeps)\n if (prevDepsRef.current !== currentDeps) {\n prevDepsRef.current = currentDeps\n // Only re-validate if this field has been touched\n const touchedFields = formRef.current.formState.touchedFields as any\n const isTouched = fieldName.split('.').reduce((obj, key) => obj?.[key], touchedFields)\n if (isTouched) {\n formRef.current.trigger(fieldName as any)\n }\n }\n }, [watchedDeps, dependencies, fieldName])\n\n // Get error by traversing the error object path\n const getErrorByPath = (path: string) => {\n const keys = path.split('.')\n let error: any = form.formState.errors\n for (const key of keys) {\n if (!error) break\n error = error[key]\n }\n return error\n }\n\n const error = getErrorByPath(fieldName)\n const errorMessage = error?.message as string | undefined\n\n // Normalize rules to array\n const rulesInputArray: FormRuleInput[] = rules\n ? Array.isArray(rules) ? rules : [rules]\n : []\n\n // Store form ref for use in validators (to get fresh values at validation time)\n const validatorFormRef = useRef(form)\n validatorFormRef.current = form\n\n // Create form methods for rule functions (Ant Design style)\n // These methods always access current form values via ref\n const formMethods: FormRuleMethods = {\n getFieldValue: (name: string) => validatorFormRef.current.getValues(name as any),\n getFieldsValue: () => validatorFormRef.current.getValues(),\n }\n\n // Resolve function rules to rule objects\n const rulesArray: FormRule[] = rulesInputArray.map(rule =>\n typeof rule === 'function' ? rule(formMethods) : rule\n )\n\n // Build validation rules\n const validationRules: any = {}\n const patternValidators: Array<{ pattern: RegExp; message: string }> = []\n const customValidators: Array<(value: any) => boolean | string | Promise<boolean | string>> = []\n\n // Handle top-level required prop\n if (required) {\n validationRules.required = 'This field is required'\n }\n\n // Process each rule\n for (const rule of rulesArray) {\n // Required\n if (rule.required) {\n validationRules.required = typeof rule.required === 'string'\n ? rule.required\n : rule.message || 'This field is required'\n }\n\n // Type validator\n if (rule.type && TYPE_VALIDATORS[rule.type]) {\n patternValidators.push({\n pattern: TYPE_VALIDATORS[rule.type].value,\n message: rule.message || TYPE_VALIDATORS[rule.type].message,\n })\n }\n\n // Min length\n if (rule.min !== undefined) {\n const minValue = typeof rule.min === 'object' ? rule.min.value : rule.min\n const minMessage = typeof rule.min === 'object'\n ? rule.min.message\n : rule.message || `Minimum length is ${minValue} characters`\n validationRules.minLength = { value: minValue, message: minMessage }\n }\n\n // Max length\n if (rule.max !== undefined) {\n const maxValue = typeof rule.max === 'object' ? rule.max.value : rule.max\n const maxMessage = typeof rule.max === 'object'\n ? rule.max.message\n : rule.message || `Maximum length is ${maxValue} characters`\n validationRules.maxLength = { value: maxValue, message: maxMessage }\n }\n\n // Pattern - collect all patterns\n if (rule.pattern) {\n const patternValue = rule.pattern instanceof RegExp ? rule.pattern : rule.pattern.value\n const patternMessage = rule.pattern instanceof RegExp\n ? rule.message || 'Invalid format'\n : rule.pattern.message\n patternValidators.push({ pattern: patternValue, message: patternMessage })\n }\n\n // Custom validator (our style)\n if (rule.validate) {\n customValidators.push(rule.validate)\n }\n\n // Ant Design style validator\n if (rule.validator) {\n const antValidator = rule.validator\n customValidators.push(async (value: any) => {\n try {\n await antValidator(rule, value)\n return true\n } catch (err) {\n return err instanceof Error ? err.message : String(err)\n }\n })\n }\n }\n\n // Combine all pattern and custom validators into a single validate function\n if (patternValidators.length > 0 || customValidators.length > 0) {\n validationRules.validate = async (value: any) => {\n // Check all patterns (skip if empty - required rule handles that)\n for (const { pattern, message } of patternValidators) {\n if (value && !pattern.test(value)) {\n return message\n }\n }\n\n // Run all custom validators (always run - they may validate empty/false values)\n for (const validator of customValidators) {\n const result = await validator(value)\n if (result !== true) {\n return result\n }\n }\n\n return true\n }\n }\n\n // Normalize validateTrigger to array\n const triggers = Array.isArray(validateTrigger) ? validateTrigger : [validateTrigger]\n const shouldValidateOnChange = triggers.includes('onChange')\n const shouldValidateOnBlur = triggers.includes('onBlur')\n\n // Feedback icons\n const FeedbackIcon = ({ hasError, isValidating }: { hasError: boolean; isValidating: boolean }) => {\n if (isValidating) {\n return (\n <span className={`${dLoading} ${dLoadingSpinner} ${dLoadingXs} text-base-content/50`} />\n )\n }\n if (hasError) {\n return (\n <svg className=\"w-4 h-4 text-error\" 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 )\n }\n return (\n <svg className=\"w-4 h-4 text-success\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M5 13l4 4L19 7\" />\n </svg>\n )\n }\n\n // Tooltip icon\n const TooltipIcon = () => (\n <div className={`${dTooltip} ${dTooltipTop} ml-1`} data-tip={tooltip}>\n <svg className=\"w-4 h-4 text-base-content/50 cursor-help\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z\" />\n </svg>\n </div>\n )\n\n return (\n <Controller\n name={fieldName}\n control={form.control}\n rules={validationRules}\n render={({ field, fieldState }) => {\n const { value, onChange, onBlur, ref } = field\n const isValidating = fieldState.isTouched && form.formState.isValidating\n\n // Clone the child element and inject form control props\n const childProps: any = {\n id: inputId,\n ref,\n 'aria-invalid': error ? true : undefined,\n 'aria-describedby': error ? errorId : undefined,\n 'data-testid': testId ? `${testId}-input` : undefined,\n }\n\n // Handle onBlur based on validateTrigger\n childProps.onBlur = () => {\n onBlur()\n if (shouldValidateOnBlur) {\n form.trigger(fieldName as any)\n }\n }\n\n // Get the original onChange from the child element (if any)\n const originalOnChange = isValidElement(children) ? (children.props as any).onChange : undefined\n\n // Handle different value prop names (e.g., 'checked' for checkboxes)\n if (valuePropName === 'checked') {\n childProps.checked = value\n childProps.onChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n onChange(e.target.checked)\n if (shouldValidateOnChange) {\n form.trigger(fieldName as any)\n }\n // Call original onChange if provided\n originalOnChange?.(e)\n }\n } else {\n childProps.value = value || ''\n childProps.onChange = (eventOrValue: any) => {\n // Handle components that pass value directly (e.g., Range, Rating)\n // vs components that pass event object (e.g., Input, Select)\n if (eventOrValue && eventOrValue.target !== undefined) {\n onChange(eventOrValue.target.value)\n } else {\n onChange(eventOrValue)\n }\n if (shouldValidateOnChange) {\n form.trigger(fieldName as any)\n }\n // Call original onChange if provided\n originalOnChange?.(eventOrValue)\n }\n }\n\n // Apply size if specified at form level\n if (size && isValidElement(children)) {\n const existingProps = children.props as any\n if (!existingProps.size) {\n childProps.size = size\n }\n }\n\n // Apply error styling and accessibility\n if (error) {\n childProps.color = 'error'\n childProps['aria-invalid'] = true\n }\n\n // Apply form-level disabled state\n if (formDisabled) {\n childProps.disabled = true\n }\n\n // When wrapped with addons, the child input should be unstyled (the wrapper has the styling)\n const hasAddons = addonBefore || addonAfter\n if (hasAddons) {\n childProps.unstyled = true\n }\n\n const enhancedChild = isValidElement(children)\n ? cloneElement(children as React.ReactElement<any>, childProps)\n : children\n\n const isHorizontal = layout === 'horizontal'\n const isInline = layout === 'inline'\n\n // Size class for floating label\n const floatingSizeClasses: Record<string, string> = {\n xs: dInputXs,\n sm: dInputSm,\n md: dInputMd,\n lg: dInputLg,\n xl: dInputXl,\n }\n\n // Build the input element with optional floating label wrapper\n const renderInputElement = () => {\n const inputWithFeedback = (\n <div className={`${isHorizontal ? 'flex-1' : ''} ${hasFeedback ? 'relative' : ''}`}>\n {enhancedChild}\n {hasFeedback && fieldState.isTouched && (\n <span className=\"absolute right-3 top-1/2 -translate-y-1/2 pointer-events-none\">\n <FeedbackIcon hasError={!!error} isValidating={isValidating} />\n </span>\n )}\n </div>\n )\n\n // Floating label variant\n if (floatingLabel) {\n const floatingClasses = [\n dFloatingLabel,\n size && floatingSizeClasses[size],\n ].filter(Boolean).join(' ')\n\n return (\n <label className={floatingClasses}>\n {enhancedChild}\n <span>{floatingLabel}{required && <span className=\"text-error ml-1\">*</span>}</span>\n </label>\n )\n }\n\n return inputWithFeedback\n }\n\n // Wrap with external addons if specified using DaisyUI input wrapper pattern\n const renderWithAddons = (input: React.ReactNode) => {\n if (!addonBefore && !addonAfter) return input\n\n const addonClasses = [\n dInput,\n 'flex',\n 'items-center',\n 'gap-2',\n size && floatingSizeClasses[size],\n ].filter(Boolean).join(' ')\n\n return (\n <label className={addonClasses}>\n {addonBefore && <span className=\"text-base-content/70\">{addonBefore}</span>}\n {input}\n {addonAfter && <span className=\"text-base-content/70\">{addonAfter}</span>}\n </label>\n )\n }\n\n return (\n <div className={`${inline ? 'w-auto' : 'w-full'} ${isHorizontal ? 'mb-4' : ''} ${isInline ? 'inline-flex mr-4' : ''} ${className}`} style={hidden ? { display: 'none' } : undefined} data-testid={testId}>\n <div className={isHorizontal ? 'flex items-center gap-4' : ''}>\n {label && !floatingLabel && (\n <label\n htmlFor={inputId}\n className={`block text-sm font-medium ${isHorizontal ? 'flex-shrink-0 text-right' : ''} ${!isHorizontal && !isInline ? 'mb-1' : ''}`}\n style={isHorizontal ? { width: labelWidth } : undefined}\n data-testid={testId ? `${testId}-label` : undefined}\n >\n <span className=\"flex items-center\">\n {label}\n {required && <span className=\"text-error ml-1\">*</span>}\n {tooltip && <TooltipIcon />}\n </span>\n </label>\n )}\n {renderWithAddons(renderInputElement())}\n </div>\n {!isHorizontal && !inline && (\n <p id={errorId} className={`${dValidatorHint} ${errorMessage ? '!visible text-error' : ''} min-h-[1.25rem]`} role={errorMessage ? 'alert' : undefined} data-testid={testId ? `${testId}-error` : undefined}>\n {errorMessage || (help && <span className=\"text-base-content/70\">{help}</span>) || '\\u00A0'}\n </p>\n )}\n {isHorizontal && (errorMessage || help) && (\n <p id={errorId} className={`${dValidatorHint} ${errorMessage ? '!visible text-error' : ''} min-h-[1.25rem]`} role={errorMessage ? 'alert' : undefined} data-testid={testId ? `${testId}-error` : undefined}>\n {errorMessage || (help && <span className=\"text-base-content/70\">{help}</span>)}\n </p>\n )}\n {extra && (\n <div className=\"text-sm text-base-content/60 mt-1\" data-testid={testId ? `${testId}-extra` : undefined}>{extra}</div>\n )}\n </div>\n )\n }}\n />\n )\n}\n\nfunction FormList<TFieldValues extends FieldValues = FieldValues>({\n name,\n children,\n}: FormListProps<TFieldValues>) {\n const { form, layout, size, disabled } = useFormContext()\n\n const { fields, append, remove, move } = useFieldArray({\n control: form.control,\n name,\n })\n\n // Add name (index) to each field for proper path construction\n const fieldsWithName = fields.map((field, index) => ({\n ...field,\n name: index,\n }))\n\n return (\n <FormContext.Provider value={{ form, layout, size, listName: name as string, disabled }}>\n {children(fieldsWithName as any, {\n add: append,\n remove,\n move,\n })}\n </FormContext.Provider>\n )\n}\n\n// Enhanced hook to expose full form API\nexport function useFormInstance<TFieldValues extends FieldValues = FieldValues>() {\n const formInstance = useForm<TFieldValues>()\n\n // Add convenience methods to the instance\n const enhancedInstance = formInstance as typeof formInstance & {\n setFieldValue: typeof formInstance.setValue\n getFieldValue: (name: any) => any\n getFieldsValue: typeof formInstance.getValues\n setFieldsValue: (values: any) => void\n validateFields: typeof formInstance.trigger\n resetFields: typeof formInstance.reset\n isFieldTouched: (name: string) => boolean\n getFieldError: (name: string) => string | undefined\n }\n\n // Add the alias methods\n enhancedInstance.setFieldValue = formInstance.setValue\n enhancedInstance.getFieldValue = (name: any) => formInstance.getValues(name)\n enhancedInstance.getFieldsValue = formInstance.getValues\n enhancedInstance.setFieldsValue = (values: any) => {\n Object.keys(values).forEach((key) => {\n formInstance.setValue(key as any, values[key])\n })\n }\n enhancedInstance.validateFields = formInstance.trigger\n enhancedInstance.resetFields = formInstance.reset\n enhancedInstance.isFieldTouched = (name: string) => {\n const touched = formInstance.formState.touchedFields as any\n return !!touched[name]\n }\n enhancedInstance.getFieldError = (name: string) => {\n const errors = formInstance.formState.errors as any\n return errors[name]?.message as string | undefined\n }\n\n return enhancedInstance\n}\n\nexport interface FormErrorListProps {\n /** Specific field names to show errors for (shows all errors if not specified) */\n fields?: string[]\n /** Custom className */\n className?: string\n /** Test ID for the error list */\n 'data-testid'?: string\n}\n\nfunction FormErrorList({ fields, className = '', 'data-testid': testId }: FormErrorListProps) {\n const { form } = useFormContext()\n const { errors } = form.formState\n\n // Flatten nested errors into a list\n const flattenErrors = (obj: any, prefix = ''): Array<{ field: string; message: string }> => {\n const result: Array<{ field: string; message: string }> = []\n\n for (const key in obj) {\n const fullKey = prefix ? `${prefix}.${key}` : key\n const value = obj[key]\n\n if (value?.message) {\n result.push({ field: fullKey, message: value.message as string })\n } else if (typeof value === 'object' && value !== null) {\n result.push(...flattenErrors(value, fullKey))\n }\n }\n\n return result\n }\n\n const allErrors = flattenErrors(errors)\n const filteredErrors = fields\n ? allErrors.filter(e => fields.includes(e.field))\n : allErrors\n\n if (filteredErrors.length === 0) {\n return null\n }\n\n return (\n <ul className={`text-error text-sm space-y-1 ${className}`} role=\"alert\" data-testid={testId}>\n {filteredErrors.map((error, index) => (\n <li key={`${error.field}-${index}`} className=\"flex items-start gap-2\" data-testid={testId ? `${testId}-${error.field}` : undefined}>\n <svg className=\"w-4 h-4 mt-0.5 flex-shrink-0\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z\" />\n </svg>\n <span>{error.message}</span>\n </li>\n ))}\n </ul>\n )\n}\n\nexport const Form = Object.assign(FormRoot, {\n Item: FormItem,\n List: FormList,\n ErrorList: FormErrorList,\n useForm: useFormInstance,\n})\n\nexport type { UseFormReturn as FormInstance }\n"],"names":["dInput","dInputXs","dInputSm","dInputMd","dInputLg","dInputXl","dFloatingLabel","dLoading","dLoadingSpinner","dLoadingXs","dTooltip","dTooltipTop","dValidatorHint","FormContext","createContext","TYPE_VALIDATORS","useFormContext","context","useContext","FormRoot","externalForm","onFinish","onFinishFailed","initialValues","layout","labelWidth","size","disabled","children","className","noValidate","props","componentSize","useConfig","effectiveSize","internalForm","useForm","form","handleSubmit","e","errors","errorFields","flattenErrors","obj","prefix","key","fullKey","value","handleReset","jsx","FormItem","name","label","floatingLabel","help","required","rules","valuePropName","inline","tooltip","extra","hasFeedback","dependencies","validateTrigger","initialValue","hidden","addonBefore","addonAfter","testId","listName","formDisabled","inputId","useId","errorId","fieldName","useEffect","watchedDeps","useWatch","formRef","useRef","prevDepsRef","currentDeps","touchedFields","error","path","keys","errorMessage","rulesInputArray","validatorFormRef","formMethods","rulesArray","rule","validationRules","patternValidators","customValidators","minValue","minMessage","maxValue","maxMessage","patternValue","patternMessage","antValidator","err","pattern","message","validator","result","triggers","shouldValidateOnChange","shouldValidateOnBlur","FeedbackIcon","hasError","isValidating","TooltipIcon","Controller","field","fieldState","onChange","onBlur","ref","childProps","originalOnChange","isValidElement","eventOrValue","enhancedChild","cloneElement","isHorizontal","isInline","floatingSizeClasses","renderInputElement","inputWithFeedback","jsxs","floatingClasses","renderWithAddons","input","addonClasses","FormList","fields","append","remove","move","useFieldArray","fieldsWithName","index","useFormInstance","formInstance","enhancedInstance","values","FormErrorList","allErrors","filteredErrors","Form"],"mappings":"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"}
|
package/dist/components/Input.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as p, jsxs as L } from "react/jsx-runtime";
|
|
2
2
|
import { forwardRef as St, useRef as Bt, useCallback as z, useState as Q, useEffect as Y } from "react";
|
|
3
|
-
import { useConfig as Mt } from "
|
|
3
|
+
import { useConfig as Mt } from "../providers/ConfigProvider.js";
|
|
4
4
|
const F = "input", lt = "input-xs", ut = "input-sm", at = "input-md", pt = "input-lg", dt = "input-xl", Wt = "input-neutral", Tt = "input-primary", $t = "input-secondary", Lt = "input-accent", Ft = "input-info", Ut = "input-success", ft = "input-warning", gt = "input-error", Xt = "input-ghost", Zt = "floating-label";
|
|
5
5
|
function q(e, s, i) {
|
|
6
6
|
let l = "", o = 0;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Input.js","sources":["../../src/components/Input.tsx"],"sourcesContent":["import React, { forwardRef, useState, useCallback, useRef, useEffect } from 'react'\nimport { useConfig } from './ConfigProvider'\n\n// DaisyUI classes\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'\nconst dInputGhost = 'input-ghost'\nconst dFloatingLabel = 'floating-label'\n\nexport interface InputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'size' | 'prefix'> {\n type?: 'text' | 'password' | 'email' | 'number' | 'date' | 'datetime-local' | 'week' | 'month' | 'tel' | 'url' | 'search' | 'time'\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 ghost?: boolean\n bordered?: boolean\n className?: string\n /** Input mask pattern. Use # for digits, A for letters, * for alphanumeric */\n mask?: string\n /** Placeholder character shown in mask (default: _) */\n maskPlaceholder?: string\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 /** Prefix icon or element (inside input) */\n prefix?: React.ReactNode\n /** Suffix icon or element (inside input) */\n suffix?: React.ReactNode\n /** Text/element before input (outside, using DaisyUI label) */\n addonBefore?: React.ReactNode\n /** Text/element after input (outside, using DaisyUI label) */\n addonAfter?: React.ReactNode\n /** Floating label text (uses DaisyUI floating-label) */\n floatingLabel?: string\n /** ID for error message element (for aria-describedby) */\n errorId?: string\n /** Render as unstyled input (for use inside styled wrappers) */\n unstyled?: boolean\n}\n\n// Helper to apply mask to raw value\nfunction applyMask(raw: string, mask: string, placeholder: string): string {\n let result = ''\n let rawIndex = 0\n\n for (let i = 0; i < mask.length && rawIndex <= raw.length; i++) {\n const maskChar = mask[i]\n if (maskChar === '#' || maskChar === 'A' || maskChar === '*') {\n if (rawIndex < raw.length) {\n result += raw[rawIndex]\n rawIndex++\n } else {\n result += placeholder\n }\n } else {\n result += maskChar\n }\n }\n\n return result\n}\n\n// Extract raw value from masked input\nfunction extractRaw(value: string, mask: string, placeholder: string): string {\n let raw = ''\n for (let i = 0; i < value.length && i < mask.length; i++) {\n const maskChar = mask[i]\n if ((maskChar === '#' || maskChar === 'A' || maskChar === '*') && value[i] !== placeholder) {\n raw += value[i]\n }\n }\n return raw\n}\n\n// Check if character is valid for mask position\nfunction isValidChar(char: string, maskChar: string): boolean {\n if (maskChar === '#') return /\\d/.test(char)\n if (maskChar === 'A') return /[a-zA-Z]/.test(char)\n if (maskChar === '*') return /[a-zA-Z0-9]/.test(char)\n return false\n}\n\n// Find next input position in mask\nfunction findNextInputPosition(mask: string, fromIndex: number): number {\n for (let i = fromIndex; i < mask.length; i++) {\n if (mask[i] === '#' || mask[i] === 'A' || mask[i] === '*') {\n return i\n }\n }\n return mask.length\n}\n\n// Clear icon component\nconst ClearIcon: React.FC<{ onClick: () => 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 Input = forwardRef<HTMLInputElement, InputProps>(\n (\n {\n type = 'text',\n size,\n color,\n status,\n ghost = false,\n bordered = true,\n className = '',\n mask,\n maskPlaceholder = '_',\n allowClear,\n onClear,\n prefix,\n suffix,\n addonBefore,\n addonAfter,\n floatingLabel,\n errorId,\n unstyled = false,\n value,\n defaultValue,\n onChange,\n onKeyDown,\n disabled,\n required,\n ...props\n },\n ref\n ) => {\n const { componentSize } = useConfig()\n const effectiveSize = size ?? componentSize ?? 'md'\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 // When wrapped with external addons OR unstyled prop, the wrapper has the input styling\n // Inner input should be unstyled (grow to fill space)\n const hasExternalAddons = addonBefore || addonAfter\n const shouldBeUnstyled = hasExternalAddons || unstyled\n\n const inputClasses = shouldBeUnstyled\n ? ['grow', 'bg-transparent', 'border-0', 'outline-none', 'focus:outline-none', className].filter(Boolean).join(' ')\n : [\n dInput,\n !bordered && 'border-0',\n ghost && dInputGhost,\n sizeClasses[effectiveSize],\n effectiveColorClass,\n className,\n ].filter(Boolean).join(' ')\n\n // Mask handling\n const innerRef = useRef<HTMLInputElement>(null)\n const inputRef = (ref as React.RefObject<HTMLInputElement>) || innerRef\n\n const getInitialRaw = useCallback(() => {\n if (!mask) return ''\n const initial = (value ?? defaultValue ?? '') as string\n return extractRaw(initial, mask, maskPlaceholder)\n }, [mask, value, defaultValue, maskPlaceholder])\n\n const [rawValue, setRawValue] = useState(getInitialRaw)\n const [cursorPos, setCursorPos] = useState<number | null>(null)\n\n // Sync with controlled value\n useEffect(() => {\n if (mask && value !== undefined) {\n setRawValue(extractRaw(value as string, mask, maskPlaceholder))\n }\n }, [mask, value, maskPlaceholder])\n\n // Set cursor position after render\n useEffect(() => {\n if (cursorPos !== null && inputRef.current) {\n inputRef.current.setSelectionRange(cursorPos, cursorPos)\n setCursorPos(null)\n }\n }, [cursorPos, inputRef])\n\n const handleMaskedChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n if (!mask) {\n onChange?.(e)\n return\n }\n\n const input = e.target\n const inputValue = input.value\n\n // Extract what the user is trying to type\n const newRaw = extractRaw(inputValue, mask, maskPlaceholder)\n\n // Filter to only valid characters\n let filteredRaw = ''\n let rawIdx = 0\n for (let i = 0; i < mask.length && rawIdx < newRaw.length; i++) {\n const maskChar = mask[i]\n if (maskChar === '#' || maskChar === 'A' || maskChar === '*') {\n if (isValidChar(newRaw[rawIdx], maskChar)) {\n filteredRaw += newRaw[rawIdx]\n }\n rawIdx++\n }\n }\n\n setRawValue(filteredRaw)\n\n // Calculate new cursor position\n const maskedValue = applyMask(filteredRaw, mask, maskPlaceholder)\n let newCursor = findNextInputPosition(mask, 0)\n let charsPlaced = 0\n for (let i = 0; i < mask.length; i++) {\n const maskChar = mask[i]\n if (maskChar === '#' || maskChar === 'A' || maskChar === '*') {\n if (charsPlaced < filteredRaw.length) {\n charsPlaced++\n newCursor = i + 1\n }\n }\n }\n // Skip to next input position if we're on a literal\n newCursor = findNextInputPosition(mask, newCursor)\n if (newCursor > mask.length) newCursor = mask.length\n\n setCursorPos(newCursor)\n\n // Create synthetic event with masked value\n const syntheticEvent = {\n ...e,\n target: { ...input, value: maskedValue },\n currentTarget: { ...input, value: maskedValue },\n } as React.ChangeEvent<HTMLInputElement>\n\n onChange?.(syntheticEvent)\n },\n [mask, maskPlaceholder, onChange]\n )\n\n const handleMaskedKeyDown = useCallback(\n (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (!mask) {\n onKeyDown?.(e)\n return\n }\n\n if (e.key === 'Backspace') {\n e.preventDefault()\n const newRaw = rawValue.slice(0, -1)\n setRawValue(newRaw)\n\n // Calculate cursor position\n let newCursor = 0\n let charsPlaced = 0\n for (let i = 0; i < mask.length; i++) {\n const maskChar = mask[i]\n if (maskChar === '#' || maskChar === 'A' || maskChar === '*') {\n if (charsPlaced < newRaw.length) {\n charsPlaced++\n newCursor = i + 1\n } else {\n newCursor = i\n break\n }\n }\n }\n setCursorPos(newCursor)\n\n const maskedValue = applyMask(newRaw, mask, maskPlaceholder)\n const input = e.currentTarget\n const syntheticEvent = {\n target: { ...input, value: maskedValue },\n currentTarget: { ...input, value: maskedValue },\n } as unknown as React.ChangeEvent<HTMLInputElement>\n\n onChange?.(syntheticEvent)\n }\n\n onKeyDown?.(e)\n },\n [mask, maskPlaceholder, rawValue, onChange, onKeyDown]\n )\n\n // Track internal value for allowClear visibility\n const [internalValue, setInternalValue] = useState((value ?? defaultValue ?? '') as string)\n\n // Sync internal value with controlled value\n useEffect(() => {\n if (value !== undefined) {\n setInternalValue(value as string)\n }\n }, [value])\n\n const handleChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {\n setInternalValue(e.target.value)\n onChange?.(e)\n }, [onChange])\n\n const handleClear = useCallback(() => {\n setInternalValue('')\n setRawValue('')\n onClear?.()\n // Create synthetic event for onChange\n if (onChange && inputRef.current) {\n const syntheticEvent = {\n target: { ...inputRef.current, value: '' },\n currentTarget: { ...inputRef.current, value: '' },\n } as React.ChangeEvent<HTMLInputElement>\n onChange(syntheticEvent)\n }\n }, [onClear, onChange, inputRef])\n\n // Determine if we should show clear button\n const currentValue = mask ? rawValue : internalValue\n const showClear = allowClear && currentValue && !disabled\n\n // Get custom clear icon if provided\n const clearIcon = typeof allowClear === 'object' && allowClear.clearIcon\n ? allowClear.clearIcon\n : null\n\n // Accessibility attributes\n const ariaProps: Record<string, string | boolean | undefined> = {}\n if (status === 'error') {\n ariaProps['aria-invalid'] = true\n }\n if (errorId) {\n ariaProps['aria-describedby'] = errorId\n }\n if (required) {\n ariaProps['aria-required'] = true\n }\n\n // If we have prefix, suffix, or allowClear, wrap in a container\n const hasInternalAddons = prefix || suffix || allowClear\n\n // Size class for floating label\n const floatingSizeClasses = {\n xs: dInputXs,\n sm: dInputSm,\n md: dInputMd,\n lg: dInputLg,\n xl: dInputXl,\n }\n\n // Build the masked value if needed\n const maskedValue = mask ? applyMask(rawValue, mask, maskPlaceholder) : undefined\n\n // Build the core input element\n const buildInput = (extraClasses?: string) => (\n <input\n ref={inputRef}\n type={mask ? 'text' : type}\n className={[\n inputClasses,\n hasInternalAddons && 'w-full',\n prefix && 'pl-10',\n (suffix || showClear) && 'pr-10',\n extraClasses,\n ].filter(Boolean).join(' ')}\n value={maskedValue ?? (value !== undefined ? value : (hasInternalAddons ? internalValue : value))}\n defaultValue={value === undefined && !mask ? defaultValue : undefined}\n onChange={mask ? handleMaskedChange : (hasInternalAddons ? handleChange : onChange)}\n onKeyDown={mask ? handleMaskedKeyDown : onKeyDown}\n disabled={disabled}\n required={required}\n {...ariaProps}\n {...props}\n />\n )\n\n // Build input with internal addons (prefix icon, suffix icon, clear button)\n const buildInputWithInternalAddons = (extraClasses?: string) => {\n if (!hasInternalAddons) {\n return buildInput(extraClasses)\n }\n\n return (\n <div className={`relative flex items-center ${extraClasses || ''}`}>\n {prefix && (\n <span className=\"absolute left-3 flex items-center text-base-content/70 pointer-events-none z-10\">\n {prefix}\n </span>\n )}\n {buildInput()}\n {(suffix || showClear) && (\n <span className=\"absolute right-3 flex items-center gap-1 z-10\">\n {showClear && (clearIcon || <ClearIcon onClick={handleClear} />)}\n {suffix && <span className=\"text-base-content/70\">{suffix}</span>}\n </span>\n )}\n </div>\n )\n }\n\n // Wrap with floating label if specified\n const wrapWithFloatingLabel = (input: React.ReactNode) => {\n if (!floatingLabel) return input\n\n const floatingClasses = [\n dFloatingLabel,\n floatingSizeClasses[effectiveSize],\n ].filter(Boolean).join(' ')\n\n return (\n <label className={floatingClasses}>\n {input}\n <span>{floatingLabel}</span>\n </label>\n )\n }\n\n // Wrap with external addons (addonBefore/addonAfter) using DaisyUI input wrapper pattern\n const wrapWithExternalAddons = (input: React.ReactNode) => {\n if (!hasExternalAddons) return input\n\n const addonClasses = [\n dInput,\n 'flex',\n 'items-center',\n 'gap-2',\n sizeClasses[effectiveSize],\n effectiveColorClass,\n ].filter(Boolean).join(' ')\n\n return (\n <label className={addonClasses}>\n {addonBefore && <span className=\"text-base-content/70\">{addonBefore}</span>}\n {input}\n {addonAfter && <span className=\"text-base-content/70\">{addonAfter}</span>}\n </label>\n )\n }\n\n // Build the final element\n const inputElement = buildInputWithInternalAddons(\n floatingLabel ? `${dInput} w-full` : undefined\n )\n\n // Apply wrappers\n return wrapWithExternalAddons(wrapWithFloatingLabel(\n floatingLabel ? (\n // For floating label, use raw input (label wrapper provides styling)\n <input\n ref={inputRef}\n type={mask ? 'text' : type}\n className={`${dInput} w-full`}\n value={maskedValue ?? (value !== undefined ? value : internalValue)}\n defaultValue={value === undefined && !mask ? defaultValue : undefined}\n onChange={mask ? handleMaskedChange : handleChange}\n onKeyDown={mask ? handleMaskedKeyDown : onKeyDown}\n disabled={disabled}\n required={required}\n {...ariaProps}\n {...props}\n />\n ) : inputElement\n ))\n }\n)\n\nInput.displayName = 'Input'\n"],"names":["dInput","dInputXs","dInputSm","dInputMd","dInputLg","dInputXl","dInputNeutral","dInputPrimary","dInputSecondary","dInputAccent","dInputInfo","dInputSuccess","dInputWarning","dInputError","dInputGhost","dFloatingLabel","applyMask","raw","mask","placeholder","result","rawIndex","i","maskChar","extractRaw","value","isValidChar","char","findNextInputPosition","fromIndex","ClearIcon","onClick","className","jsx","Input","forwardRef","type","size","color","status","ghost","bordered","maskPlaceholder","allowClear","onClear","prefix","suffix","addonBefore","addonAfter","floatingLabel","errorId","unstyled","defaultValue","onChange","onKeyDown","disabled","required","props","ref","componentSize","useConfig","effectiveSize","sizeClasses","effectiveColorClass","hasExternalAddons","inputClasses","innerRef","useRef","inputRef","getInitialRaw","useCallback","rawValue","setRawValue","useState","cursorPos","setCursorPos","useEffect","handleMaskedChange","e","input","inputValue","newRaw","filteredRaw","rawIdx","maskedValue","newCursor","charsPlaced","syntheticEvent","handleMaskedKeyDown","internalValue","setInternalValue","handleChange","handleClear","showClear","clearIcon","ariaProps","hasInternalAddons","floatingSizeClasses","buildInput","extraClasses","buildInputWithInternalAddons","jsxs","wrapWithFloatingLabel","floatingClasses","wrapWithExternalAddons","addonClasses","inputElement"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Input.js","sources":["../../src/components/Input.tsx"],"sourcesContent":["import React, { forwardRef, useState, useCallback, useRef, useEffect } from 'react'\nimport { useConfig } from '../providers/ConfigProvider'\n\n// DaisyUI classes\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'\nconst dInputGhost = 'input-ghost'\nconst dFloatingLabel = 'floating-label'\n\nexport interface InputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'size' | 'prefix'> {\n type?: 'text' | 'password' | 'email' | 'number' | 'date' | 'datetime-local' | 'week' | 'month' | 'tel' | 'url' | 'search' | 'time'\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 ghost?: boolean\n bordered?: boolean\n className?: string\n /** Input mask pattern. Use # for digits, A for letters, * for alphanumeric */\n mask?: string\n /** Placeholder character shown in mask (default: _) */\n maskPlaceholder?: string\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 /** Prefix icon or element (inside input) */\n prefix?: React.ReactNode\n /** Suffix icon or element (inside input) */\n suffix?: React.ReactNode\n /** Text/element before input (outside, using DaisyUI label) */\n addonBefore?: React.ReactNode\n /** Text/element after input (outside, using DaisyUI label) */\n addonAfter?: React.ReactNode\n /** Floating label text (uses DaisyUI floating-label) */\n floatingLabel?: string\n /** ID for error message element (for aria-describedby) */\n errorId?: string\n /** Render as unstyled input (for use inside styled wrappers) */\n unstyled?: boolean\n}\n\n// Helper to apply mask to raw value\nfunction applyMask(raw: string, mask: string, placeholder: string): string {\n let result = ''\n let rawIndex = 0\n\n for (let i = 0; i < mask.length && rawIndex <= raw.length; i++) {\n const maskChar = mask[i]\n if (maskChar === '#' || maskChar === 'A' || maskChar === '*') {\n if (rawIndex < raw.length) {\n result += raw[rawIndex]\n rawIndex++\n } else {\n result += placeholder\n }\n } else {\n result += maskChar\n }\n }\n\n return result\n}\n\n// Extract raw value from masked input\nfunction extractRaw(value: string, mask: string, placeholder: string): string {\n let raw = ''\n for (let i = 0; i < value.length && i < mask.length; i++) {\n const maskChar = mask[i]\n if ((maskChar === '#' || maskChar === 'A' || maskChar === '*') && value[i] !== placeholder) {\n raw += value[i]\n }\n }\n return raw\n}\n\n// Check if character is valid for mask position\nfunction isValidChar(char: string, maskChar: string): boolean {\n if (maskChar === '#') return /\\d/.test(char)\n if (maskChar === 'A') return /[a-zA-Z]/.test(char)\n if (maskChar === '*') return /[a-zA-Z0-9]/.test(char)\n return false\n}\n\n// Find next input position in mask\nfunction findNextInputPosition(mask: string, fromIndex: number): number {\n for (let i = fromIndex; i < mask.length; i++) {\n if (mask[i] === '#' || mask[i] === 'A' || mask[i] === '*') {\n return i\n }\n }\n return mask.length\n}\n\n// Clear icon component\nconst ClearIcon: React.FC<{ onClick: () => 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 Input = forwardRef<HTMLInputElement, InputProps>(\n (\n {\n type = 'text',\n size,\n color,\n status,\n ghost = false,\n bordered = true,\n className = '',\n mask,\n maskPlaceholder = '_',\n allowClear,\n onClear,\n prefix,\n suffix,\n addonBefore,\n addonAfter,\n floatingLabel,\n errorId,\n unstyled = false,\n value,\n defaultValue,\n onChange,\n onKeyDown,\n disabled,\n required,\n ...props\n },\n ref\n ) => {\n const { componentSize } = useConfig()\n const effectiveSize = size ?? componentSize ?? 'md'\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 // When wrapped with external addons OR unstyled prop, the wrapper has the input styling\n // Inner input should be unstyled (grow to fill space)\n const hasExternalAddons = addonBefore || addonAfter\n const shouldBeUnstyled = hasExternalAddons || unstyled\n\n const inputClasses = shouldBeUnstyled\n ? ['grow', 'bg-transparent', 'border-0', 'outline-none', 'focus:outline-none', className].filter(Boolean).join(' ')\n : [\n dInput,\n !bordered && 'border-0',\n ghost && dInputGhost,\n sizeClasses[effectiveSize],\n effectiveColorClass,\n className,\n ].filter(Boolean).join(' ')\n\n // Mask handling\n const innerRef = useRef<HTMLInputElement>(null)\n const inputRef = (ref as React.RefObject<HTMLInputElement>) || innerRef\n\n const getInitialRaw = useCallback(() => {\n if (!mask) return ''\n const initial = (value ?? defaultValue ?? '') as string\n return extractRaw(initial, mask, maskPlaceholder)\n }, [mask, value, defaultValue, maskPlaceholder])\n\n const [rawValue, setRawValue] = useState(getInitialRaw)\n const [cursorPos, setCursorPos] = useState<number | null>(null)\n\n // Sync with controlled value\n useEffect(() => {\n if (mask && value !== undefined) {\n setRawValue(extractRaw(value as string, mask, maskPlaceholder))\n }\n }, [mask, value, maskPlaceholder])\n\n // Set cursor position after render\n useEffect(() => {\n if (cursorPos !== null && inputRef.current) {\n inputRef.current.setSelectionRange(cursorPos, cursorPos)\n setCursorPos(null)\n }\n }, [cursorPos, inputRef])\n\n const handleMaskedChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n if (!mask) {\n onChange?.(e)\n return\n }\n\n const input = e.target\n const inputValue = input.value\n\n // Extract what the user is trying to type\n const newRaw = extractRaw(inputValue, mask, maskPlaceholder)\n\n // Filter to only valid characters\n let filteredRaw = ''\n let rawIdx = 0\n for (let i = 0; i < mask.length && rawIdx < newRaw.length; i++) {\n const maskChar = mask[i]\n if (maskChar === '#' || maskChar === 'A' || maskChar === '*') {\n if (isValidChar(newRaw[rawIdx], maskChar)) {\n filteredRaw += newRaw[rawIdx]\n }\n rawIdx++\n }\n }\n\n setRawValue(filteredRaw)\n\n // Calculate new cursor position\n const maskedValue = applyMask(filteredRaw, mask, maskPlaceholder)\n let newCursor = findNextInputPosition(mask, 0)\n let charsPlaced = 0\n for (let i = 0; i < mask.length; i++) {\n const maskChar = mask[i]\n if (maskChar === '#' || maskChar === 'A' || maskChar === '*') {\n if (charsPlaced < filteredRaw.length) {\n charsPlaced++\n newCursor = i + 1\n }\n }\n }\n // Skip to next input position if we're on a literal\n newCursor = findNextInputPosition(mask, newCursor)\n if (newCursor > mask.length) newCursor = mask.length\n\n setCursorPos(newCursor)\n\n // Create synthetic event with masked value\n const syntheticEvent = {\n ...e,\n target: { ...input, value: maskedValue },\n currentTarget: { ...input, value: maskedValue },\n } as React.ChangeEvent<HTMLInputElement>\n\n onChange?.(syntheticEvent)\n },\n [mask, maskPlaceholder, onChange]\n )\n\n const handleMaskedKeyDown = useCallback(\n (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (!mask) {\n onKeyDown?.(e)\n return\n }\n\n if (e.key === 'Backspace') {\n e.preventDefault()\n const newRaw = rawValue.slice(0, -1)\n setRawValue(newRaw)\n\n // Calculate cursor position\n let newCursor = 0\n let charsPlaced = 0\n for (let i = 0; i < mask.length; i++) {\n const maskChar = mask[i]\n if (maskChar === '#' || maskChar === 'A' || maskChar === '*') {\n if (charsPlaced < newRaw.length) {\n charsPlaced++\n newCursor = i + 1\n } else {\n newCursor = i\n break\n }\n }\n }\n setCursorPos(newCursor)\n\n const maskedValue = applyMask(newRaw, mask, maskPlaceholder)\n const input = e.currentTarget\n const syntheticEvent = {\n target: { ...input, value: maskedValue },\n currentTarget: { ...input, value: maskedValue },\n } as unknown as React.ChangeEvent<HTMLInputElement>\n\n onChange?.(syntheticEvent)\n }\n\n onKeyDown?.(e)\n },\n [mask, maskPlaceholder, rawValue, onChange, onKeyDown]\n )\n\n // Track internal value for allowClear visibility\n const [internalValue, setInternalValue] = useState((value ?? defaultValue ?? '') as string)\n\n // Sync internal value with controlled value\n useEffect(() => {\n if (value !== undefined) {\n setInternalValue(value as string)\n }\n }, [value])\n\n const handleChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {\n setInternalValue(e.target.value)\n onChange?.(e)\n }, [onChange])\n\n const handleClear = useCallback(() => {\n setInternalValue('')\n setRawValue('')\n onClear?.()\n // Create synthetic event for onChange\n if (onChange && inputRef.current) {\n const syntheticEvent = {\n target: { ...inputRef.current, value: '' },\n currentTarget: { ...inputRef.current, value: '' },\n } as React.ChangeEvent<HTMLInputElement>\n onChange(syntheticEvent)\n }\n }, [onClear, onChange, inputRef])\n\n // Determine if we should show clear button\n const currentValue = mask ? rawValue : internalValue\n const showClear = allowClear && currentValue && !disabled\n\n // Get custom clear icon if provided\n const clearIcon = typeof allowClear === 'object' && allowClear.clearIcon\n ? allowClear.clearIcon\n : null\n\n // Accessibility attributes\n const ariaProps: Record<string, string | boolean | undefined> = {}\n if (status === 'error') {\n ariaProps['aria-invalid'] = true\n }\n if (errorId) {\n ariaProps['aria-describedby'] = errorId\n }\n if (required) {\n ariaProps['aria-required'] = true\n }\n\n // If we have prefix, suffix, or allowClear, wrap in a container\n const hasInternalAddons = prefix || suffix || allowClear\n\n // Size class for floating label\n const floatingSizeClasses = {\n xs: dInputXs,\n sm: dInputSm,\n md: dInputMd,\n lg: dInputLg,\n xl: dInputXl,\n }\n\n // Build the masked value if needed\n const maskedValue = mask ? applyMask(rawValue, mask, maskPlaceholder) : undefined\n\n // Build the core input element\n const buildInput = (extraClasses?: string) => (\n <input\n ref={inputRef}\n type={mask ? 'text' : type}\n className={[\n inputClasses,\n hasInternalAddons && 'w-full',\n prefix && 'pl-10',\n (suffix || showClear) && 'pr-10',\n extraClasses,\n ].filter(Boolean).join(' ')}\n value={maskedValue ?? (value !== undefined ? value : (hasInternalAddons ? internalValue : value))}\n defaultValue={value === undefined && !mask ? defaultValue : undefined}\n onChange={mask ? handleMaskedChange : (hasInternalAddons ? handleChange : onChange)}\n onKeyDown={mask ? handleMaskedKeyDown : onKeyDown}\n disabled={disabled}\n required={required}\n {...ariaProps}\n {...props}\n />\n )\n\n // Build input with internal addons (prefix icon, suffix icon, clear button)\n const buildInputWithInternalAddons = (extraClasses?: string) => {\n if (!hasInternalAddons) {\n return buildInput(extraClasses)\n }\n\n return (\n <div className={`relative flex items-center ${extraClasses || ''}`}>\n {prefix && (\n <span className=\"absolute left-3 flex items-center text-base-content/70 pointer-events-none z-10\">\n {prefix}\n </span>\n )}\n {buildInput()}\n {(suffix || showClear) && (\n <span className=\"absolute right-3 flex items-center gap-1 z-10\">\n {showClear && (clearIcon || <ClearIcon onClick={handleClear} />)}\n {suffix && <span className=\"text-base-content/70\">{suffix}</span>}\n </span>\n )}\n </div>\n )\n }\n\n // Wrap with floating label if specified\n const wrapWithFloatingLabel = (input: React.ReactNode) => {\n if (!floatingLabel) return input\n\n const floatingClasses = [\n dFloatingLabel,\n floatingSizeClasses[effectiveSize],\n ].filter(Boolean).join(' ')\n\n return (\n <label className={floatingClasses}>\n {input}\n <span>{floatingLabel}</span>\n </label>\n )\n }\n\n // Wrap with external addons (addonBefore/addonAfter) using DaisyUI input wrapper pattern\n const wrapWithExternalAddons = (input: React.ReactNode) => {\n if (!hasExternalAddons) return input\n\n const addonClasses = [\n dInput,\n 'flex',\n 'items-center',\n 'gap-2',\n sizeClasses[effectiveSize],\n effectiveColorClass,\n ].filter(Boolean).join(' ')\n\n return (\n <label className={addonClasses}>\n {addonBefore && <span className=\"text-base-content/70\">{addonBefore}</span>}\n {input}\n {addonAfter && <span className=\"text-base-content/70\">{addonAfter}</span>}\n </label>\n )\n }\n\n // Build the final element\n const inputElement = buildInputWithInternalAddons(\n floatingLabel ? `${dInput} w-full` : undefined\n )\n\n // Apply wrappers\n return wrapWithExternalAddons(wrapWithFloatingLabel(\n floatingLabel ? (\n // For floating label, use raw input (label wrapper provides styling)\n <input\n ref={inputRef}\n type={mask ? 'text' : type}\n className={`${dInput} w-full`}\n value={maskedValue ?? (value !== undefined ? value : internalValue)}\n defaultValue={value === undefined && !mask ? defaultValue : undefined}\n onChange={mask ? handleMaskedChange : handleChange}\n onKeyDown={mask ? handleMaskedKeyDown : onKeyDown}\n disabled={disabled}\n required={required}\n {...ariaProps}\n {...props}\n />\n ) : inputElement\n ))\n }\n)\n\nInput.displayName = 'Input'\n"],"names":["dInput","dInputXs","dInputSm","dInputMd","dInputLg","dInputXl","dInputNeutral","dInputPrimary","dInputSecondary","dInputAccent","dInputInfo","dInputSuccess","dInputWarning","dInputError","dInputGhost","dFloatingLabel","applyMask","raw","mask","placeholder","result","rawIndex","i","maskChar","extractRaw","value","isValidChar","char","findNextInputPosition","fromIndex","ClearIcon","onClick","className","jsx","Input","forwardRef","type","size","color","status","ghost","bordered","maskPlaceholder","allowClear","onClear","prefix","suffix","addonBefore","addonAfter","floatingLabel","errorId","unstyled","defaultValue","onChange","onKeyDown","disabled","required","props","ref","componentSize","useConfig","effectiveSize","sizeClasses","effectiveColorClass","hasExternalAddons","inputClasses","innerRef","useRef","inputRef","getInitialRaw","useCallback","rawValue","setRawValue","useState","cursorPos","setCursorPos","useEffect","handleMaskedChange","e","input","inputValue","newRaw","filteredRaw","rawIdx","maskedValue","newCursor","charsPlaced","syntheticEvent","handleMaskedKeyDown","internalValue","setInternalValue","handleChange","handleClear","showClear","clearIcon","ariaProps","hasInternalAddons","floatingSizeClasses","buildInput","extraClasses","buildInputWithInternalAddons","jsxs","wrapWithFloatingLabel","floatingClasses","wrapWithExternalAddons","addonClasses","inputElement"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsxs as w, jsx as l } from "react/jsx-runtime";
|
|
2
2
|
import { forwardRef as G, useState as H, useRef as T, useImperativeHandle as U } from "react";
|
|
3
|
-
import { useConfig as q } from "
|
|
3
|
+
import { useConfig as q } from "../providers/ConfigProvider.js";
|
|
4
4
|
const E = "input", J = "input-xs", O = "input-sm", P = "input-md", Q = "input-lg", Y = "input-xl", Z = "input-disabled", $ = "btn", _ = "btn-xs", tt = "btn-sm", B = "btn-ghost", nt = G(
|
|
5
5
|
({
|
|
6
6
|
value: s,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InputNumber.js","sources":["../../src/components/InputNumber.tsx"],"sourcesContent":["import React, { useState, useRef, forwardRef, useImperativeHandle } from 'react'\nimport { useConfig } from './ConfigProvider'\n\n// DaisyUI classes\nconst dInput = 'input'\nconst dInputXs = 'input-xs'\nconst dInputSm = 'input-sm'\nconst dInputMd = 'input-md'\nconst dInputLg = 'input-lg'\nconst dInputXl = 'input-xl'\nconst dInputDisabled = 'input-disabled'\nconst dBtn = 'btn'\nconst dBtnXs = 'btn-xs'\nconst dBtnSm = 'btn-sm'\nconst dBtnGhost = 'btn-ghost'\n\nexport interface InputNumberProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'size' | 'onChange' | 'value' | 'defaultValue'> {\n value?: number\n defaultValue?: number\n min?: number\n max?: number\n step?: number\n precision?: number\n size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'\n disabled?: boolean\n onChange?: (value: number | null) => void\n formatter?: (value: number | undefined) => string\n parser?: (displayValue: string) => number\n className?: string\n controls?: boolean\n block?: boolean\n /** Test ID prefix for child elements */\n 'data-testid'?: string\n}\n\nexport const InputNumber = forwardRef<HTMLInputElement, InputNumberProps>(\n (\n {\n value: controlledValue,\n defaultValue,\n min = -Infinity,\n max = Infinity,\n step = 1,\n precision,\n size,\n disabled = false,\n onChange,\n formatter,\n parser,\n className = '',\n controls = true,\n block = false,\n 'data-testid': testId,\n ...props\n },\n ref\n ) => {\n const { componentSize } = useConfig()\n\n // Helper for test IDs\n const getTestId = (suffix: string) => (testId ? `${testId}-${suffix}` : undefined)\n const effectiveSize = size ?? componentSize ?? 'md'\n\n const [internalValue, setInternalValue] = useState<number | null>(defaultValue ?? null)\n const inputRef = useRef<HTMLInputElement>(null)\n\n useImperativeHandle(ref, () => inputRef.current!)\n\n const value = controlledValue !== undefined ? controlledValue : internalValue\n\n const formatValue = (num: number | null): string => {\n if (num === null) return ''\n let formatted = num\n if (precision !== undefined) {\n formatted = Number(num.toFixed(precision))\n }\n return formatter ? formatter(formatted) : String(formatted)\n }\n\n const parseValue = (str: string): number | null => {\n if (!str) return null\n const parsed = parser ? parser(str) : parseFloat(str)\n if (isNaN(parsed)) return null\n return parsed\n }\n\n const clampValue = (num: number): number => {\n let clamped = Math.max(min, Math.min(max, num))\n if (precision !== undefined) {\n clamped = Number(clamped.toFixed(precision))\n }\n return clamped\n }\n\n const updateValue = (newValue: number | null) => {\n if (newValue === null) {\n if (controlledValue === undefined) {\n setInternalValue(null)\n }\n onChange?.(null)\n return\n }\n\n const clamped = clampValue(newValue)\n if (controlledValue === undefined) {\n setInternalValue(clamped)\n }\n onChange?.(clamped)\n }\n\n const handleIncrement = () => {\n if (disabled) return\n const currentValue = value ?? 0\n updateValue(currentValue + step)\n }\n\n const handleDecrement = () => {\n if (disabled) return\n const currentValue = value ?? 0\n updateValue(currentValue - step)\n }\n\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const parsed = parseValue(e.target.value)\n if (parsed !== null) {\n updateValue(parsed)\n } else if (e.target.value === '') {\n updateValue(null)\n }\n }\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (disabled) return\n\n if (e.key === 'ArrowUp') {\n e.preventDefault()\n handleIncrement()\n } else if (e.key === 'ArrowDown') {\n e.preventDefault()\n handleDecrement()\n }\n }\n\n const handleBlur = () => {\n // Ensure value is within bounds on blur\n if (value !== null && (value < min || value > max)) {\n updateValue(clampValue(value))\n }\n }\n\n const sizeClasses = {\n xs: dInputXs,\n sm: dInputSm,\n md: dInputMd,\n lg: dInputLg,\n xl: dInputXl,\n }\n\n const inputClasses = [\n dInput,\n 'w-full',\n effectiveSize && sizeClasses[effectiveSize],\n disabled && dInputDisabled,\n controls && 'pr-8',\n ]\n .filter(Boolean)\n .join(' ')\n\n const buttonSize = effectiveSize === 'xs' || effectiveSize === 'sm' ? dBtnXs : dBtnSm\n\n return (\n <div className={`relative ${block ? 'w-full' : 'inline-block'} group ${className}`} data-testid={testId}>\n <input\n ref={inputRef}\n data-testid={getTestId('input')}\n type=\"text\"\n inputMode=\"decimal\"\n role=\"spinbutton\"\n aria-valuemin={min !== -Infinity ? min : undefined}\n aria-valuemax={max !== Infinity ? max : undefined}\n aria-valuenow={value ?? undefined}\n className={inputClasses}\n value={formatValue(value)}\n onChange={handleInputChange}\n onKeyDown={handleKeyDown}\n onBlur={handleBlur}\n disabled={disabled}\n {...props}\n />\n {controls && (\n <div className=\"absolute right-1 top-1/2 -translate-y-1/2 flex flex-col gap-0.5 opacity-0 group-hover:opacity-100 transition-opacity\">\n <button\n type=\"button\"\n aria-label=\"Increase value\"\n className={`${dBtn} ${buttonSize} ${dBtnGhost} px-1 min-h-0 h-3.5`}\n onClick={handleIncrement}\n disabled={disabled || (value !== null && value >= max)}\n tabIndex={-1}\n data-testid={getTestId('increment')}\n >\n <svg\n className=\"w-3 h-3\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M5 15l7-7 7 7\"\n />\n </svg>\n </button>\n <button\n type=\"button\"\n aria-label=\"Decrease value\"\n className={`${dBtn} ${buttonSize} ${dBtnGhost} px-1 min-h-0 h-3.5`}\n onClick={handleDecrement}\n disabled={disabled || (value !== null && value <= min)}\n tabIndex={-1}\n data-testid={getTestId('decrement')}\n >\n <svg\n className=\"w-3 h-3\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M19 9l-7 7-7-7\"\n />\n </svg>\n </button>\n </div>\n )}\n </div>\n )\n }\n)\n\nInputNumber.displayName = 'InputNumber'\n\nexport default InputNumber\n"],"names":["dInput","dInputXs","dInputSm","dInputMd","dInputLg","dInputXl","dInputDisabled","dBtn","dBtnXs","dBtnSm","dBtnGhost","InputNumber","forwardRef","controlledValue","defaultValue","min","max","step","precision","size","disabled","onChange","formatter","parser","className","controls","block","testId","props","ref","componentSize","useConfig","getTestId","suffix","effectiveSize","internalValue","setInternalValue","useState","inputRef","useRef","useImperativeHandle","value","formatValue","num","formatted","parseValue","str","parsed","clampValue","clamped","updateValue","newValue","handleIncrement","handleDecrement","handleInputChange","e","handleKeyDown","handleBlur","inputClasses","buttonSize","jsxs","jsx"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"InputNumber.js","sources":["../../src/components/InputNumber.tsx"],"sourcesContent":["import React, { useState, useRef, forwardRef, useImperativeHandle } from 'react'\nimport { useConfig } from '../providers/ConfigProvider'\n\n// DaisyUI classes\nconst dInput = 'input'\nconst dInputXs = 'input-xs'\nconst dInputSm = 'input-sm'\nconst dInputMd = 'input-md'\nconst dInputLg = 'input-lg'\nconst dInputXl = 'input-xl'\nconst dInputDisabled = 'input-disabled'\nconst dBtn = 'btn'\nconst dBtnXs = 'btn-xs'\nconst dBtnSm = 'btn-sm'\nconst dBtnGhost = 'btn-ghost'\n\nexport interface InputNumberProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'size' | 'onChange' | 'value' | 'defaultValue'> {\n value?: number\n defaultValue?: number\n min?: number\n max?: number\n step?: number\n precision?: number\n size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'\n disabled?: boolean\n onChange?: (value: number | null) => void\n formatter?: (value: number | undefined) => string\n parser?: (displayValue: string) => number\n className?: string\n controls?: boolean\n block?: boolean\n /** Test ID prefix for child elements */\n 'data-testid'?: string\n}\n\nexport const InputNumber = forwardRef<HTMLInputElement, InputNumberProps>(\n (\n {\n value: controlledValue,\n defaultValue,\n min = -Infinity,\n max = Infinity,\n step = 1,\n precision,\n size,\n disabled = false,\n onChange,\n formatter,\n parser,\n className = '',\n controls = true,\n block = false,\n 'data-testid': testId,\n ...props\n },\n ref\n ) => {\n const { componentSize } = useConfig()\n\n // Helper for test IDs\n const getTestId = (suffix: string) => (testId ? `${testId}-${suffix}` : undefined)\n const effectiveSize = size ?? componentSize ?? 'md'\n\n const [internalValue, setInternalValue] = useState<number | null>(defaultValue ?? null)\n const inputRef = useRef<HTMLInputElement>(null)\n\n useImperativeHandle(ref, () => inputRef.current!)\n\n const value = controlledValue !== undefined ? controlledValue : internalValue\n\n const formatValue = (num: number | null): string => {\n if (num === null) return ''\n let formatted = num\n if (precision !== undefined) {\n formatted = Number(num.toFixed(precision))\n }\n return formatter ? formatter(formatted) : String(formatted)\n }\n\n const parseValue = (str: string): number | null => {\n if (!str) return null\n const parsed = parser ? parser(str) : parseFloat(str)\n if (isNaN(parsed)) return null\n return parsed\n }\n\n const clampValue = (num: number): number => {\n let clamped = Math.max(min, Math.min(max, num))\n if (precision !== undefined) {\n clamped = Number(clamped.toFixed(precision))\n }\n return clamped\n }\n\n const updateValue = (newValue: number | null) => {\n if (newValue === null) {\n if (controlledValue === undefined) {\n setInternalValue(null)\n }\n onChange?.(null)\n return\n }\n\n const clamped = clampValue(newValue)\n if (controlledValue === undefined) {\n setInternalValue(clamped)\n }\n onChange?.(clamped)\n }\n\n const handleIncrement = () => {\n if (disabled) return\n const currentValue = value ?? 0\n updateValue(currentValue + step)\n }\n\n const handleDecrement = () => {\n if (disabled) return\n const currentValue = value ?? 0\n updateValue(currentValue - step)\n }\n\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const parsed = parseValue(e.target.value)\n if (parsed !== null) {\n updateValue(parsed)\n } else if (e.target.value === '') {\n updateValue(null)\n }\n }\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (disabled) return\n\n if (e.key === 'ArrowUp') {\n e.preventDefault()\n handleIncrement()\n } else if (e.key === 'ArrowDown') {\n e.preventDefault()\n handleDecrement()\n }\n }\n\n const handleBlur = () => {\n // Ensure value is within bounds on blur\n if (value !== null && (value < min || value > max)) {\n updateValue(clampValue(value))\n }\n }\n\n const sizeClasses = {\n xs: dInputXs,\n sm: dInputSm,\n md: dInputMd,\n lg: dInputLg,\n xl: dInputXl,\n }\n\n const inputClasses = [\n dInput,\n 'w-full',\n effectiveSize && sizeClasses[effectiveSize],\n disabled && dInputDisabled,\n controls && 'pr-8',\n ]\n .filter(Boolean)\n .join(' ')\n\n const buttonSize = effectiveSize === 'xs' || effectiveSize === 'sm' ? dBtnXs : dBtnSm\n\n return (\n <div className={`relative ${block ? 'w-full' : 'inline-block'} group ${className}`} data-testid={testId}>\n <input\n ref={inputRef}\n data-testid={getTestId('input')}\n type=\"text\"\n inputMode=\"decimal\"\n role=\"spinbutton\"\n aria-valuemin={min !== -Infinity ? min : undefined}\n aria-valuemax={max !== Infinity ? max : undefined}\n aria-valuenow={value ?? undefined}\n className={inputClasses}\n value={formatValue(value)}\n onChange={handleInputChange}\n onKeyDown={handleKeyDown}\n onBlur={handleBlur}\n disabled={disabled}\n {...props}\n />\n {controls && (\n <div className=\"absolute right-1 top-1/2 -translate-y-1/2 flex flex-col gap-0.5 opacity-0 group-hover:opacity-100 transition-opacity\">\n <button\n type=\"button\"\n aria-label=\"Increase value\"\n className={`${dBtn} ${buttonSize} ${dBtnGhost} px-1 min-h-0 h-3.5`}\n onClick={handleIncrement}\n disabled={disabled || (value !== null && value >= max)}\n tabIndex={-1}\n data-testid={getTestId('increment')}\n >\n <svg\n className=\"w-3 h-3\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M5 15l7-7 7 7\"\n />\n </svg>\n </button>\n <button\n type=\"button\"\n aria-label=\"Decrease value\"\n className={`${dBtn} ${buttonSize} ${dBtnGhost} px-1 min-h-0 h-3.5`}\n onClick={handleDecrement}\n disabled={disabled || (value !== null && value <= min)}\n tabIndex={-1}\n data-testid={getTestId('decrement')}\n >\n <svg\n className=\"w-3 h-3\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M19 9l-7 7-7-7\"\n />\n </svg>\n </button>\n </div>\n )}\n </div>\n )\n }\n)\n\nInputNumber.displayName = 'InputNumber'\n\nexport default InputNumber\n"],"names":["dInput","dInputXs","dInputSm","dInputMd","dInputLg","dInputXl","dInputDisabled","dBtn","dBtnXs","dBtnSm","dBtnGhost","InputNumber","forwardRef","controlledValue","defaultValue","min","max","step","precision","size","disabled","onChange","formatter","parser","className","controls","block","testId","props","ref","componentSize","useConfig","getTestId","suffix","effectiveSize","internalValue","setInternalValue","useState","inputRef","useRef","useImperativeHandle","value","formatValue","num","formatted","parseValue","str","parsed","clampValue","clamped","updateValue","newValue","handleIncrement","handleDecrement","handleInputChange","e","handleKeyDown","handleBlur","inputClasses","buttonSize","jsxs","jsx"],"mappings":";;;AAIA,MAAMA,IAAS,SACTC,IAAW,YACXC,IAAW,YACXC,IAAW,YACXC,IAAW,YACXC,IAAW,YACXC,IAAiB,kBACjBC,IAAO,OACPC,IAAS,UACTC,KAAS,UACTC,IAAY,aAqBLC,KAAcC;AAAA,EACzB,CACE;AAAA,IACE,OAAOC;AAAA,IACP,cAAAC;AAAA,IACA,KAAAC,IAAM;AAAA,IACN,KAAAC,IAAM;AAAA,IACN,MAAAC,IAAO;AAAA,IACP,WAAAC;AAAA,IACA,MAAAC;AAAA,IACA,UAAAC,IAAW;AAAA,IACX,UAAAC;AAAA,IACA,WAAAC;AAAA,IACA,QAAAC;AAAA,IACA,WAAAC,IAAY;AAAA,IACZ,UAAAC,IAAW;AAAA,IACX,OAAAC,IAAQ;AAAA,IACR,eAAeC;AAAA,IACf,GAAGC;AAAA,EAAA,GAELC,MACG;AACH,UAAM,EAAE,eAAAC,EAAA,IAAkBC,EAAA,GAGpBC,IAAY,CAACC,MAAoBN,IAAS,GAAGA,CAAM,IAAIM,CAAM,KAAK,QAClEC,IAAgBf,KAAQW,KAAiB,MAEzC,CAACK,GAAeC,CAAgB,IAAIC,EAAwBvB,KAAgB,IAAI,GAChFwB,IAAWC,EAAyB,IAAI;AAE9C,IAAAC,EAAoBX,GAAK,MAAMS,EAAS,OAAQ;AAEhD,UAAMG,IAAQ5B,MAAoB,SAAYA,IAAkBsB,GAE1DO,IAAc,CAACC,MAA+B;AAClD,UAAIA,MAAQ,KAAM,QAAO;AACzB,UAAIC,IAAYD;AAChB,aAAIzB,MAAc,WAChB0B,IAAY,OAAOD,EAAI,QAAQzB,CAAS,CAAC,IAEpCI,IAAYA,EAAUsB,CAAS,IAAI,OAAOA,CAAS;AAAA,IAC5D,GAEMC,IAAa,CAACC,MAA+B;AACjD,UAAI,CAACA,EAAK,QAAO;AACjB,YAAMC,IAASxB,IAASA,EAAOuB,CAAG,IAAI,WAAWA,CAAG;AACpD,aAAI,MAAMC,CAAM,IAAU,OACnBA;AAAA,IACT,GAEMC,IAAa,CAACL,MAAwB;AAC1C,UAAIM,IAAU,KAAK,IAAIlC,GAAK,KAAK,IAAIC,GAAK2B,CAAG,CAAC;AAC9C,aAAIzB,MAAc,WAChB+B,IAAU,OAAOA,EAAQ,QAAQ/B,CAAS,CAAC,IAEtC+B;AAAA,IACT,GAEMC,IAAc,CAACC,MAA4B;AAC/C,UAAIA,MAAa,MAAM;AACrB,QAAItC,MAAoB,UACtBuB,EAAiB,IAAI,GAEvBf,IAAW,IAAI;AACf;AAAA,MACF;AAEA,YAAM4B,IAAUD,EAAWG,CAAQ;AACnC,MAAItC,MAAoB,UACtBuB,EAAiBa,CAAO,GAE1B5B,IAAW4B,CAAO;AAAA,IACpB,GAEMG,IAAkB,MAAM;AAC5B,UAAIhC,EAAU;AAEd,MAAA8B,GADqBT,KAAS,KACHxB,CAAI;AAAA,IACjC,GAEMoC,IAAkB,MAAM;AAC5B,UAAIjC,EAAU;AAEd,MAAA8B,GADqBT,KAAS,KACHxB,CAAI;AAAA,IACjC,GAEMqC,IAAoB,CAACC,MAA2C;AACpE,YAAMR,IAASF,EAAWU,EAAE,OAAO,KAAK;AACxC,MAAIR,MAAW,OACbG,EAAYH,CAAM,IACTQ,EAAE,OAAO,UAAU,MAC5BL,EAAY,IAAI;AAAA,IAEpB,GAEMM,IAAgB,CAACD,MAA6C;AAClE,MAAInC,MAEAmC,EAAE,QAAQ,aACZA,EAAE,eAAA,GACFH,EAAA,KACSG,EAAE,QAAQ,gBACnBA,EAAE,eAAA,GACFF,EAAA;AAAA,IAEJ,GAEMI,IAAa,MAAM;AAEvB,MAAIhB,MAAU,SAASA,IAAQ1B,KAAO0B,IAAQzB,MAC5CkC,EAAYF,EAAWP,CAAK,CAAC;AAAA,IAEjC,GAUMiB,IAAe;AAAA,MACnB1D;AAAA,MACA;AAAA,MACAkC,KAXkB;AAAA,QAClB,IAAIjC;AAAA,QACJ,IAAIC;AAAA,QACJ,IAAIC;AAAA,QACJ,IAAIC;AAAA,QACJ,IAAIC;AAAA,MAAA,EAMyB6B,CAAa;AAAA,MAC1Cd,KAAYd;AAAA,MACZmB,KAAY;AAAA,IAAA,EAEX,OAAO,OAAO,EACd,KAAK,GAAG,GAELkC,IAAazB,MAAkB,QAAQA,MAAkB,OAAO1B,IAASC;AAE/E,WACE,gBAAAmD,EAAC,OAAA,EAAI,WAAW,YAAYlC,IAAQ,WAAW,cAAc,UAAUF,CAAS,IAAI,eAAaG,GAC/F,UAAA;AAAA,MAAA,gBAAAkC;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,KAAKvB;AAAA,UACL,eAAaN,EAAU,OAAO;AAAA,UAC9B,MAAK;AAAA,UACL,WAAU;AAAA,UACV,MAAK;AAAA,UACL,iBAAejB,MAAQ,SAAYA,IAAM;AAAA,UACzC,iBAAeC,MAAQ,QAAWA,IAAM;AAAA,UACxC,iBAAeyB,KAAS;AAAA,UACxB,WAAWiB;AAAA,UACX,OAAOhB,EAAYD,CAAK;AAAA,UACxB,UAAUa;AAAA,UACV,WAAWE;AAAA,UACX,QAAQC;AAAA,UACR,UAAArC;AAAA,UACC,GAAGQ;AAAA,QAAA;AAAA,MAAA;AAAA,MAELH,KACC,gBAAAmC,EAAC,OAAA,EAAI,WAAU,wHACb,UAAA;AAAA,QAAA,gBAAAC;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,cAAW;AAAA,YACX,WAAW,GAAGtD,CAAI,IAAIoD,CAAU,IAAIjD,CAAS;AAAA,YAC7C,SAAS0C;AAAA,YACT,UAAUhC,KAAaqB,MAAU,QAAQA,KAASzB;AAAA,YAClD,UAAU;AAAA,YACV,eAAagB,EAAU,WAAW;AAAA,YAElC,UAAA,gBAAA6B;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,WAAU;AAAA,gBACV,MAAK;AAAA,gBACL,SAAQ;AAAA,gBACR,QAAO;AAAA,gBACP,eAAY;AAAA,gBAEZ,UAAA,gBAAAA;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACC,eAAc;AAAA,oBACd,gBAAe;AAAA,oBACf,aAAa;AAAA,oBACb,GAAE;AAAA,kBAAA;AAAA,gBAAA;AAAA,cACJ;AAAA,YAAA;AAAA,UACF;AAAA,QAAA;AAAA,QAEF,gBAAAA;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,cAAW;AAAA,YACX,WAAW,GAAGtD,CAAI,IAAIoD,CAAU,IAAIjD,CAAS;AAAA,YAC7C,SAAS2C;AAAA,YACT,UAAUjC,KAAaqB,MAAU,QAAQA,KAAS1B;AAAA,YAClD,UAAU;AAAA,YACV,eAAaiB,EAAU,WAAW;AAAA,YAElC,UAAA,gBAAA6B;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,WAAU;AAAA,gBACV,MAAK;AAAA,gBACL,SAAQ;AAAA,gBACR,QAAO;AAAA,gBACP,eAAY;AAAA,gBAEZ,UAAA,gBAAAA;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACC,eAAc;AAAA,oBACd,gBAAe;AAAA,oBACf,aAAa;AAAA,oBACb,GAAE;AAAA,kBAAA;AAAA,gBAAA;AAAA,cACJ;AAAA,YAAA;AAAA,UACF;AAAA,QAAA;AAAA,MACF,EAAA,CACF;AAAA,IAAA,GAEJ;AAAA,EAEJ;AACF;AAEAlD,GAAY,cAAc;"}
|
package/dist/components/List.js
CHANGED
|
@@ -2,7 +2,7 @@ import { jsxs as b, jsx as e } from "react/jsx-runtime";
|
|
|
2
2
|
import p, { forwardRef as j } from "react";
|
|
3
3
|
import { Pagination as A } from "./Pagination.js";
|
|
4
4
|
import { Loading as D } from "./Loading.js";
|
|
5
|
-
import { useConfig as F } from "
|
|
5
|
+
import { useConfig as F } from "../providers/ConfigProvider.js";
|
|
6
6
|
const G = "list", u = "list-row", H = {
|
|
7
7
|
xs: "py-1",
|
|
8
8
|
sm: "py-2",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"List.js","sources":["../../src/components/List.tsx"],"sourcesContent":["import React, { forwardRef } from 'react'\nimport { Pagination } from './Pagination'\nimport { Loading } from './Loading'\nimport { useConfig } from './ConfigProvider'\n\n// DaisyUI classes\nconst dList = 'list'\nconst dListRow = 'list-row'\n\nexport interface ListPaginationConfig {\n current?: number\n pageSize?: number\n total?: number\n onChange?: (page: number, pageSize: number) => void\n}\n\nexport interface ListGridConfig {\n gutter?: number\n column?: number\n xs?: number\n sm?: number\n md?: number\n lg?: number\n xl?: number\n}\n\nexport interface ListProps<T = unknown> extends Omit<React.HTMLAttributes<HTMLUListElement>, 'children'> {\n /** Data source array */\n dataSource?: T[]\n /** Function to render each item */\n renderItem?: (item: T, index: number) => React.ReactNode\n /** List header content */\n header?: React.ReactNode\n /** List footer content */\n footer?: React.ReactNode\n /** Show loading state */\n loading?: boolean\n /** Pagination configuration or false to disable */\n pagination?: ListPaginationConfig | false\n /** Grid layout configuration */\n grid?: ListGridConfig\n /** Show border around list */\n bordered?: boolean\n /** Show divider between items */\n split?: boolean\n /** Size variant */\n size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'\n /** Layout direction */\n itemLayout?: 'horizontal' | 'vertical'\n /** Empty state text */\n locale?: { emptyText?: React.ReactNode }\n /** Load more content (e.g., button) */\n loadMore?: React.ReactNode\n /** Custom key extraction function */\n rowKey?: keyof T | ((item: T) => React.Key)\n /** Compound pattern children */\n children?: React.ReactNode\n /** Accessible label for the list */\n 'aria-label'?: string\n /** Test ID for the component */\n 'data-testid'?: string\n}\n\nexport interface ListItemProps extends React.LiHTMLAttributes<HTMLLIElement> {\n /** Item content */\n children: React.ReactNode\n /** Action buttons */\n actions?: React.ReactNode[]\n /** Extra content on the right */\n extra?: React.ReactNode\n /** Test ID for this item */\n 'data-testid'?: string\n}\n\nexport interface ListItemMetaProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'title'> {\n /** Avatar or icon */\n avatar?: React.ReactNode\n /** Title content */\n title?: React.ReactNode\n /** Description content */\n description?: React.ReactNode\n}\n\n// Also export as ListRowProps for backwards compatibility with DaisyUI pattern\nexport type ListRowProps = ListItemProps\n\nconst sizeClasses = {\n xs: 'py-1',\n sm: 'py-2',\n md: 'py-3',\n lg: 'py-4',\n xl: 'py-5',\n}\n\nconst ListItem = forwardRef<HTMLLIElement, ListItemProps>(\n ({ children, actions, extra, className = '', 'data-testid': testId, ...rest }, ref) => {\n const classes = [dListRow, className].filter(Boolean).join(' ')\n\n return (\n <li ref={ref} className={classes} data-testid={testId} {...rest}>\n <div className=\"flex-1\">{children}</div>\n {extra && <div className=\"flex-shrink-0\">{extra}</div>}\n {actions && actions.length > 0 && (\n <div className=\"flex items-center gap-2 flex-shrink-0\">\n {actions.map((action, index) => (\n <span key={index}>{action}</span>\n ))}\n </div>\n )}\n </li>\n )\n }\n)\n\nListItem.displayName = 'List.Item'\n\nconst ListItemMeta: React.FC<ListItemMetaProps> = ({\n avatar,\n title,\n description,\n className = '',\n ...rest\n}) => {\n return (\n <div className={`flex items-center gap-3 ${className}`} {...rest}>\n {avatar && <div className=\"flex-shrink-0\">{avatar}</div>}\n <div className=\"flex-1 min-w-0\">\n {title && <div className=\"font-medium truncate\">{title}</div>}\n {description && (\n <div className=\"text-sm text-base-content/70 truncate\">{description}</div>\n )}\n </div>\n </div>\n )\n}\n\nListItemMeta.displayName = 'List.Item.Meta'\n\nconst ListRoot = forwardRef<HTMLUListElement, ListProps>(\n (\n {\n dataSource,\n renderItem,\n header,\n footer,\n loading = false,\n pagination = false,\n grid,\n bordered = true,\n split = true,\n size,\n itemLayout = 'horizontal',\n locale,\n loadMore,\n rowKey,\n children,\n className = '',\n 'aria-label': ariaLabel,\n 'data-testid': testId = 'list',\n ...rest\n },\n ref\n ) => {\n const { componentSize } = useConfig()\n const effectiveSize = size ?? componentSize ?? 'md'\n\n const listClasses = [\n `${dList} bg-base-100 rounded-box`,\n bordered && 'border border-base-300',\n split && `[&_.${dListRow}]:border-b [&_.${dListRow}]:border-base-200 [&_.${dListRow}:last-child]:border-b-0`,\n className,\n ]\n .filter(Boolean)\n .join(' ')\n\n const itemClasses = sizeClasses[effectiveSize]\n\n // Grid styles\n const gridStyles: React.CSSProperties = grid\n ? {\n display: 'grid',\n gridTemplateColumns: `repeat(${grid.column || 1}, minmax(0, 1fr))`,\n gap: grid.gutter ? `${grid.gutter}px` : undefined,\n }\n : {}\n\n // Get key for item\n const getItemKey = (item: unknown, index: number): React.Key => {\n if (!rowKey) return index\n if (typeof rowKey === 'function') return rowKey(item as Parameters<typeof rowKey>[0])\n return String((item as Record<string, unknown>)[rowKey as string] ?? index)\n }\n\n // Layout class for vertical items\n const layoutClass = itemLayout === 'vertical' ? 'flex-col items-start' : ''\n\n // Render items from dataSource or children\n const renderContent = () => {\n if (loading) {\n return (\n <div className=\"flex justify-center py-8\" data-testid={`${testId}-loading`} role=\"status\">\n <Loading size=\"md\" aria-label=\"Loading list\" />\n </div>\n )\n }\n\n // Use dataSource + renderItem if provided\n if (dataSource && renderItem) {\n if (dataSource.length === 0) {\n return (\n <div className=\"text-center py-8 text-base-content/50\" data-testid={`${testId}-empty`}>\n {locale?.emptyText ?? 'No data'}\n </div>\n )\n }\n\n return dataSource.map((item, index) => {\n const rendered = renderItem(item, index)\n const key = getItemKey(item, index)\n // Inject size and layout classes into list items\n if (React.isValidElement(rendered)) {\n const existingClassName = (rendered.props as { className?: string }).className || ''\n return React.cloneElement(rendered, {\n key,\n className: `${existingClassName} ${itemClasses} ${layoutClass}`.trim(),\n 'data-testid': `${testId}-item-${index}`,\n } as React.Attributes & { className?: string; 'data-testid'?: string })\n }\n return rendered\n })\n }\n\n // Use compound children pattern\n if (children) {\n return React.Children.map(children, (child, index) => {\n if (React.isValidElement(child)) {\n const existingClassName = (child.props as { className?: string }).className || ''\n return React.cloneElement(child, {\n className: `${existingClassName} ${itemClasses} ${layoutClass}`.trim(),\n 'data-testid': `${testId}-item-${index}`,\n } as React.Attributes & { className?: string; 'data-testid'?: string })\n }\n return child\n })\n }\n\n return (\n <div className=\"text-center py-8 text-base-content/50\" data-testid={`${testId}-empty`}>\n {locale?.emptyText ?? 'No data'}\n </div>\n )\n }\n\n return (\n <div data-testid={testId} aria-busy={loading}>\n {header && (\n <div className=\"px-4 py-3 border-b border-base-200 font-medium\" data-testid={`${testId}-header`}>\n {header}\n </div>\n )}\n\n <ul\n ref={ref}\n role=\"list\"\n aria-label={ariaLabel}\n className={listClasses}\n style={gridStyles}\n {...rest}\n >\n {renderContent()}\n </ul>\n\n {footer && (\n <div className=\"px-4 py-3 border-t border-base-200\" data-testid={`${testId}-footer`}>\n {footer}\n </div>\n )}\n\n {loadMore && (\n <div className=\"py-4 text-center\" data-testid={`${testId}-load-more`}>\n {loadMore}\n </div>\n )}\n\n {pagination && pagination.total !== undefined && (\n <div className=\"flex justify-end pt-4\" data-testid={`${testId}-pagination`}>\n <Pagination\n current={pagination.current}\n pageSize={pagination.pageSize}\n total={pagination.total}\n onChange={pagination.onChange}\n />\n </div>\n )}\n </div>\n )\n }\n)\n\nListRoot.displayName = 'List'\n\n// Compound component with Item and Item.Meta\nconst ItemWithMeta = Object.assign(ListItem, {\n Meta: ListItemMeta,\n})\n\nexport const List = Object.assign(ListRoot, {\n Item: ItemWithMeta,\n Row: ListItem, // Backwards compatibility with DaisyUI pattern\n})\n"],"names":["dList","dListRow","sizeClasses","ListItem","forwardRef","children","actions","extra","className","testId","rest","ref","classes","jsxs","jsx","action","index","ListItemMeta","avatar","title","description","ListRoot","dataSource","renderItem","header","footer","loading","pagination","grid","bordered","split","size","itemLayout","locale","loadMore","rowKey","ariaLabel","componentSize","useConfig","effectiveSize","listClasses","itemClasses","gridStyles","getItemKey","item","layoutClass","renderContent","Loading","rendered","key","React","existingClassName","child","Pagination","ItemWithMeta","List"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"List.js","sources":["../../src/components/List.tsx"],"sourcesContent":["import React, { forwardRef } from 'react'\nimport { Pagination } from './Pagination'\nimport { Loading } from './Loading'\nimport { useConfig } from '../providers/ConfigProvider'\n\n// DaisyUI classes\nconst dList = 'list'\nconst dListRow = 'list-row'\n\nexport interface ListPaginationConfig {\n current?: number\n pageSize?: number\n total?: number\n onChange?: (page: number, pageSize: number) => void\n}\n\nexport interface ListGridConfig {\n gutter?: number\n column?: number\n xs?: number\n sm?: number\n md?: number\n lg?: number\n xl?: number\n}\n\nexport interface ListProps<T = unknown> extends Omit<React.HTMLAttributes<HTMLUListElement>, 'children'> {\n /** Data source array */\n dataSource?: T[]\n /** Function to render each item */\n renderItem?: (item: T, index: number) => React.ReactNode\n /** List header content */\n header?: React.ReactNode\n /** List footer content */\n footer?: React.ReactNode\n /** Show loading state */\n loading?: boolean\n /** Pagination configuration or false to disable */\n pagination?: ListPaginationConfig | false\n /** Grid layout configuration */\n grid?: ListGridConfig\n /** Show border around list */\n bordered?: boolean\n /** Show divider between items */\n split?: boolean\n /** Size variant */\n size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'\n /** Layout direction */\n itemLayout?: 'horizontal' | 'vertical'\n /** Empty state text */\n locale?: { emptyText?: React.ReactNode }\n /** Load more content (e.g., button) */\n loadMore?: React.ReactNode\n /** Custom key extraction function */\n rowKey?: keyof T | ((item: T) => React.Key)\n /** Compound pattern children */\n children?: React.ReactNode\n /** Accessible label for the list */\n 'aria-label'?: string\n /** Test ID for the component */\n 'data-testid'?: string\n}\n\nexport interface ListItemProps extends React.LiHTMLAttributes<HTMLLIElement> {\n /** Item content */\n children: React.ReactNode\n /** Action buttons */\n actions?: React.ReactNode[]\n /** Extra content on the right */\n extra?: React.ReactNode\n /** Test ID for this item */\n 'data-testid'?: string\n}\n\nexport interface ListItemMetaProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'title'> {\n /** Avatar or icon */\n avatar?: React.ReactNode\n /** Title content */\n title?: React.ReactNode\n /** Description content */\n description?: React.ReactNode\n}\n\n// Also export as ListRowProps for backwards compatibility with DaisyUI pattern\nexport type ListRowProps = ListItemProps\n\nconst sizeClasses = {\n xs: 'py-1',\n sm: 'py-2',\n md: 'py-3',\n lg: 'py-4',\n xl: 'py-5',\n}\n\nconst ListItem = forwardRef<HTMLLIElement, ListItemProps>(\n ({ children, actions, extra, className = '', 'data-testid': testId, ...rest }, ref) => {\n const classes = [dListRow, className].filter(Boolean).join(' ')\n\n return (\n <li ref={ref} className={classes} data-testid={testId} {...rest}>\n <div className=\"flex-1\">{children}</div>\n {extra && <div className=\"flex-shrink-0\">{extra}</div>}\n {actions && actions.length > 0 && (\n <div className=\"flex items-center gap-2 flex-shrink-0\">\n {actions.map((action, index) => (\n <span key={index}>{action}</span>\n ))}\n </div>\n )}\n </li>\n )\n }\n)\n\nListItem.displayName = 'List.Item'\n\nconst ListItemMeta: React.FC<ListItemMetaProps> = ({\n avatar,\n title,\n description,\n className = '',\n ...rest\n}) => {\n return (\n <div className={`flex items-center gap-3 ${className}`} {...rest}>\n {avatar && <div className=\"flex-shrink-0\">{avatar}</div>}\n <div className=\"flex-1 min-w-0\">\n {title && <div className=\"font-medium truncate\">{title}</div>}\n {description && (\n <div className=\"text-sm text-base-content/70 truncate\">{description}</div>\n )}\n </div>\n </div>\n )\n}\n\nListItemMeta.displayName = 'List.Item.Meta'\n\nconst ListRoot = forwardRef<HTMLUListElement, ListProps>(\n (\n {\n dataSource,\n renderItem,\n header,\n footer,\n loading = false,\n pagination = false,\n grid,\n bordered = true,\n split = true,\n size,\n itemLayout = 'horizontal',\n locale,\n loadMore,\n rowKey,\n children,\n className = '',\n 'aria-label': ariaLabel,\n 'data-testid': testId = 'list',\n ...rest\n },\n ref\n ) => {\n const { componentSize } = useConfig()\n const effectiveSize = size ?? componentSize ?? 'md'\n\n const listClasses = [\n `${dList} bg-base-100 rounded-box`,\n bordered && 'border border-base-300',\n split && `[&_.${dListRow}]:border-b [&_.${dListRow}]:border-base-200 [&_.${dListRow}:last-child]:border-b-0`,\n className,\n ]\n .filter(Boolean)\n .join(' ')\n\n const itemClasses = sizeClasses[effectiveSize]\n\n // Grid styles\n const gridStyles: React.CSSProperties = grid\n ? {\n display: 'grid',\n gridTemplateColumns: `repeat(${grid.column || 1}, minmax(0, 1fr))`,\n gap: grid.gutter ? `${grid.gutter}px` : undefined,\n }\n : {}\n\n // Get key for item\n const getItemKey = (item: unknown, index: number): React.Key => {\n if (!rowKey) return index\n if (typeof rowKey === 'function') return rowKey(item as Parameters<typeof rowKey>[0])\n return String((item as Record<string, unknown>)[rowKey as string] ?? index)\n }\n\n // Layout class for vertical items\n const layoutClass = itemLayout === 'vertical' ? 'flex-col items-start' : ''\n\n // Render items from dataSource or children\n const renderContent = () => {\n if (loading) {\n return (\n <div className=\"flex justify-center py-8\" data-testid={`${testId}-loading`} role=\"status\">\n <Loading size=\"md\" aria-label=\"Loading list\" />\n </div>\n )\n }\n\n // Use dataSource + renderItem if provided\n if (dataSource && renderItem) {\n if (dataSource.length === 0) {\n return (\n <div className=\"text-center py-8 text-base-content/50\" data-testid={`${testId}-empty`}>\n {locale?.emptyText ?? 'No data'}\n </div>\n )\n }\n\n return dataSource.map((item, index) => {\n const rendered = renderItem(item, index)\n const key = getItemKey(item, index)\n // Inject size and layout classes into list items\n if (React.isValidElement(rendered)) {\n const existingClassName = (rendered.props as { className?: string }).className || ''\n return React.cloneElement(rendered, {\n key,\n className: `${existingClassName} ${itemClasses} ${layoutClass}`.trim(),\n 'data-testid': `${testId}-item-${index}`,\n } as React.Attributes & { className?: string; 'data-testid'?: string })\n }\n return rendered\n })\n }\n\n // Use compound children pattern\n if (children) {\n return React.Children.map(children, (child, index) => {\n if (React.isValidElement(child)) {\n const existingClassName = (child.props as { className?: string }).className || ''\n return React.cloneElement(child, {\n className: `${existingClassName} ${itemClasses} ${layoutClass}`.trim(),\n 'data-testid': `${testId}-item-${index}`,\n } as React.Attributes & { className?: string; 'data-testid'?: string })\n }\n return child\n })\n }\n\n return (\n <div className=\"text-center py-8 text-base-content/50\" data-testid={`${testId}-empty`}>\n {locale?.emptyText ?? 'No data'}\n </div>\n )\n }\n\n return (\n <div data-testid={testId} aria-busy={loading}>\n {header && (\n <div className=\"px-4 py-3 border-b border-base-200 font-medium\" data-testid={`${testId}-header`}>\n {header}\n </div>\n )}\n\n <ul\n ref={ref}\n role=\"list\"\n aria-label={ariaLabel}\n className={listClasses}\n style={gridStyles}\n {...rest}\n >\n {renderContent()}\n </ul>\n\n {footer && (\n <div className=\"px-4 py-3 border-t border-base-200\" data-testid={`${testId}-footer`}>\n {footer}\n </div>\n )}\n\n {loadMore && (\n <div className=\"py-4 text-center\" data-testid={`${testId}-load-more`}>\n {loadMore}\n </div>\n )}\n\n {pagination && pagination.total !== undefined && (\n <div className=\"flex justify-end pt-4\" data-testid={`${testId}-pagination`}>\n <Pagination\n current={pagination.current}\n pageSize={pagination.pageSize}\n total={pagination.total}\n onChange={pagination.onChange}\n />\n </div>\n )}\n </div>\n )\n }\n)\n\nListRoot.displayName = 'List'\n\n// Compound component with Item and Item.Meta\nconst ItemWithMeta = Object.assign(ListItem, {\n Meta: ListItemMeta,\n})\n\nexport const List = Object.assign(ListRoot, {\n Item: ItemWithMeta,\n Row: ListItem, // Backwards compatibility with DaisyUI pattern\n})\n"],"names":["dList","dListRow","sizeClasses","ListItem","forwardRef","children","actions","extra","className","testId","rest","ref","classes","jsxs","jsx","action","index","ListItemMeta","avatar","title","description","ListRoot","dataSource","renderItem","header","footer","loading","pagination","grid","bordered","split","size","itemLayout","locale","loadMore","rowKey","ariaLabel","componentSize","useConfig","effectiveSize","listClasses","itemClasses","gridStyles","getItemKey","item","layoutClass","renderContent","Loading","rendered","key","React","existingClassName","child","Pagination","ItemWithMeta","List"],"mappings":";;;;;AAMA,MAAMA,IAAQ,QACRC,IAAW,YA+EXC,IAAc;AAAA,EAClB,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AACN,GAEMC,IAAWC;AAAA,EACf,CAAC,EAAE,UAAAC,GAAU,SAAAC,GAAS,OAAAC,GAAO,WAAAC,IAAY,IAAI,eAAeC,GAAQ,GAAGC,EAAA,GAAQC,MAAQ;AACrF,UAAMC,IAAU,CAACX,GAAUO,CAAS,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG;AAE9D,WACE,gBAAAK,EAAC,QAAG,KAAAF,GAAU,WAAWC,GAAS,eAAaH,GAAS,GAAGC,GACzD,UAAA;AAAA,MAAA,gBAAAI,EAAC,OAAA,EAAI,WAAU,UAAU,UAAAT,EAAA,CAAS;AAAA,MACjCE,KAAS,gBAAAO,EAAC,OAAA,EAAI,WAAU,iBAAiB,UAAAP,GAAM;AAAA,MAC/CD,KAAWA,EAAQ,SAAS,KAC3B,gBAAAQ,EAAC,OAAA,EAAI,WAAU,yCACZ,UAAAR,EAAQ,IAAI,CAACS,GAAQC,MACpB,gBAAAF,EAAC,UAAkB,UAAAC,EAAA,GAARC,CAAe,CAC3B,EAAA,CACH;AAAA,IAAA,GAEJ;AAAA,EAEJ;AACF;AAEAb,EAAS,cAAc;AAEvB,MAAMc,IAA4C,CAAC;AAAA,EACjD,QAAAC;AAAA,EACA,OAAAC;AAAA,EACA,aAAAC;AAAA,EACA,WAAAZ,IAAY;AAAA,EACZ,GAAGE;AACL,wBAEK,OAAA,EAAI,WAAW,2BAA2BF,CAAS,IAAK,GAAGE,GACzD,UAAA;AAAA,EAAAQ,KAAU,gBAAAJ,EAAC,OAAA,EAAI,WAAU,iBAAiB,UAAAI,GAAO;AAAA,EAClD,gBAAAL,EAAC,OAAA,EAAI,WAAU,kBACZ,UAAA;AAAA,IAAAM,KAAS,gBAAAL,EAAC,OAAA,EAAI,WAAU,wBAAwB,UAAAK,GAAM;AAAA,IACtDC,KACC,gBAAAN,EAAC,OAAA,EAAI,WAAU,yCAAyC,UAAAM,EAAA,CAAY;AAAA,EAAA,EAAA,CAExE;AAAA,GACF;AAIJH,EAAa,cAAc;AAE3B,MAAMI,IAAWjB;AAAA,EACf,CACE;AAAA,IACE,YAAAkB;AAAA,IACA,YAAAC;AAAA,IACA,QAAAC;AAAA,IACA,QAAAC;AAAA,IACA,SAAAC,IAAU;AAAA,IACV,YAAAC,IAAa;AAAA,IACb,MAAAC;AAAA,IACA,UAAAC,IAAW;AAAA,IACX,OAAAC,IAAQ;AAAA,IACR,MAAAC;AAAA,IACA,YAAAC,IAAa;AAAA,IACb,QAAAC;AAAA,IACA,UAAAC;AAAA,IACA,QAAAC;AAAA,IACA,UAAA9B;AAAA,IACA,WAAAG,IAAY;AAAA,IACZ,cAAc4B;AAAA,IACd,eAAe3B,IAAS;AAAA,IACxB,GAAGC;AAAA,EAAA,GAELC,MACG;AACH,UAAM,EAAE,eAAA0B,EAAA,IAAkBC,EAAA,GACpBC,IAAgBR,KAAQM,KAAiB,MAEzCG,IAAc;AAAA,MAClB,GAAGxC,CAAK;AAAA,MACR6B,KAAY;AAAA,MACZC,KAAS,OAAO7B,CAAQ,kBAAkBA,CAAQ,yBAAyBA,CAAQ;AAAA,MACnFO;AAAA,IAAA,EAEC,OAAO,OAAO,EACd,KAAK,GAAG,GAELiC,IAAcvC,EAAYqC,CAAa,GAGvCG,IAAkCd,IACpC;AAAA,MACE,SAAS;AAAA,MACT,qBAAqB,UAAUA,EAAK,UAAU,CAAC;AAAA,MAC/C,KAAKA,EAAK,SAAS,GAAGA,EAAK,MAAM,OAAO;AAAA,IAAA,IAE1C,CAAA,GAGEe,IAAa,CAACC,GAAe5B,MAC5BmB,IACD,OAAOA,KAAW,aAAmBA,EAAOS,CAAoC,IAC7E,OAAQA,EAAiCT,CAAgB,KAAKnB,CAAK,IAFtDA,GAMhB6B,IAAcb,MAAe,aAAa,yBAAyB,IAGnEc,IAAgB,MAChBpB,sBAEC,OAAA,EAAI,WAAU,4BAA2B,eAAa,GAAGjB,CAAM,YAAY,MAAK,UAC/E,4BAACsC,GAAA,EAAQ,MAAK,MAAK,cAAW,gBAAe,GAC/C,IAKAzB,KAAcC,IACZD,EAAW,WAAW,IAEtB,gBAAAR,EAAC,OAAA,EAAI,WAAU,yCAAwC,eAAa,GAAGL,CAAM,UAC1E,UAAAwB,GAAQ,aAAa,UAAA,CACxB,IAIGX,EAAW,IAAI,CAACsB,GAAM5B,MAAU;AACrC,YAAMgC,IAAWzB,EAAWqB,GAAM5B,CAAK,GACjCiC,IAAMN,EAAWC,GAAM5B,CAAK;AAElC,UAAIkC,EAAM,eAAeF,CAAQ,GAAG;AAClC,cAAMG,IAAqBH,EAAS,MAAiC,aAAa;AAClF,eAAOE,EAAM,aAAaF,GAAU;AAAA,UAClC,KAAAC;AAAA,UACA,WAAW,GAAGE,CAAiB,IAAIV,CAAW,IAAII,CAAW,GAAG,KAAA;AAAA,UAChE,eAAe,GAAGpC,CAAM,SAASO,CAAK;AAAA,QAAA,CAC8B;AAAA,MACxE;AACA,aAAOgC;AAAA,IACT,CAAC,IAIC3C,IACK6C,EAAM,SAAS,IAAI7C,GAAU,CAAC+C,GAAOpC,MAAU;AACpD,UAAIkC,EAAM,eAAeE,CAAK,GAAG;AAC/B,cAAMD,IAAqBC,EAAM,MAAiC,aAAa;AAC/E,eAAOF,EAAM,aAAaE,GAAO;AAAA,UAC/B,WAAW,GAAGD,CAAiB,IAAIV,CAAW,IAAII,CAAW,GAAG,KAAA;AAAA,UAChE,eAAe,GAAGpC,CAAM,SAASO,CAAK;AAAA,QAAA,CAC8B;AAAA,MACxE;AACA,aAAOoC;AAAA,IACT,CAAC,IAID,gBAAAtC,EAAC,OAAA,EAAI,WAAU,yCAAwC,eAAa,GAAGL,CAAM,UAC1E,UAAAwB,GAAQ,aAAa,UAAA,CACxB;AAIJ,WACE,gBAAApB,EAAC,OAAA,EAAI,eAAaJ,GAAQ,aAAWiB,GAClC,UAAA;AAAA,MAAAF,KACC,gBAAAV,EAAC,SAAI,WAAU,kDAAiD,eAAa,GAAGL,CAAM,WACnF,UAAAe,EAAA,CACH;AAAA,MAGF,gBAAAV;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,KAAAH;AAAA,UACA,MAAK;AAAA,UACL,cAAYyB;AAAA,UACZ,WAAWI;AAAA,UACX,OAAOE;AAAA,UACN,GAAGhC;AAAA,UAEH,UAAAoC,EAAA;AAAA,QAAc;AAAA,MAAA;AAAA,MAGhBrB,uBACE,OAAA,EAAI,WAAU,sCAAqC,eAAa,GAAGhB,CAAM,WACvE,UAAAgB,EAAA,CACH;AAAA,MAGDS,uBACE,OAAA,EAAI,WAAU,oBAAmB,eAAa,GAAGzB,CAAM,cACrD,UAAAyB,EAAA,CACH;AAAA,MAGDP,KAAcA,EAAW,UAAU,UAClC,gBAAAb,EAAC,OAAA,EAAI,WAAU,yBAAwB,eAAa,GAAGL,CAAM,eAC3D,UAAA,gBAAAK;AAAA,QAACuC;AAAA,QAAA;AAAA,UACC,SAAS1B,EAAW;AAAA,UACpB,UAAUA,EAAW;AAAA,UACrB,OAAOA,EAAW;AAAA,UAClB,UAAUA,EAAW;AAAA,QAAA;AAAA,MAAA,EACvB,CACF;AAAA,IAAA,GAEJ;AAAA,EAEJ;AACF;AAEAN,EAAS,cAAc;AAGvB,MAAMiC,IAAe,OAAO,OAAOnD,GAAU;AAAA,EAC3C,MAAMc;AACR,CAAC,GAEYsC,IAAO,OAAO,OAAOlC,GAAU;AAAA,EAC1C,MAAMiC;AAAA,EACN,KAAKnD;AAAA;AACP,CAAC;"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsxs as e, jsx as n } from "react/jsx-runtime";
|
|
2
|
-
import { useConfig as f } from "
|
|
2
|
+
import { useConfig as f } from "../providers/ConfigProvider.js";
|
|
3
3
|
const L = "loading", p = "loading-xs", x = "loading-sm", b = "loading-md", u = "loading-lg", N = "loading-xl", v = "loading-spinner", y = "loading-dots", C = "loading-ring", h = "loading-ball", j = "loading-bars", z = "loading-infinity", k = ({
|
|
4
4
|
size: l,
|
|
5
5
|
type: t = "spinner",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Loading.js","sources":["../../src/components/Loading.tsx"],"sourcesContent":["import React from 'react'\nimport { useConfig } from '
|
|
1
|
+
{"version":3,"file":"Loading.js","sources":["../../src/components/Loading.tsx"],"sourcesContent":["import React from 'react'\nimport { useConfig } from '../providers/ConfigProvider'\n\n// DaisyUI classes\nconst dLoading = 'loading'\nconst dLoadingXs = 'loading-xs'\nconst dLoadingSm = 'loading-sm'\nconst dLoadingMd = 'loading-md'\nconst dLoadingLg = 'loading-lg'\nconst dLoadingXl = 'loading-xl'\nconst dLoadingSpinner = 'loading-spinner'\nconst dLoadingDots = 'loading-dots'\nconst dLoadingRing = 'loading-ring'\nconst dLoadingBall = 'loading-ball'\nconst dLoadingBars = 'loading-bars'\nconst dLoadingInfinity = 'loading-infinity'\n\nexport interface LoadingProps extends React.HTMLAttributes<HTMLDivElement> {\n size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'\n type?: 'spinner' | 'dots' | 'ring' | 'ball' | 'bars' | 'infinity'\n spinning?: boolean\n children?: React.ReactNode\n tip?: string\n}\n\nexport const Loading: React.FC<LoadingProps> = ({\n size,\n type = 'spinner',\n className = '',\n spinning = true,\n children,\n tip,\n ...rest\n}) => {\n const { componentSize } = useConfig()\n const effectiveSize = size ?? componentSize ?? 'md'\n\n const sizeClasses = {\n xs: dLoadingXs,\n sm: dLoadingSm,\n md: dLoadingMd,\n lg: dLoadingLg,\n xl: dLoadingXl,\n }\n\n const typeClasses = {\n spinner: dLoadingSpinner,\n dots: dLoadingDots,\n ring: dLoadingRing,\n ball: dLoadingBall,\n bars: dLoadingBars,\n infinity: dLoadingInfinity,\n }\n\n const spinnerClasses = [dLoading, typeClasses[type], sizeClasses[effectiveSize], className]\n .filter(Boolean)\n .join(' ')\n\n if (children) {\n return (\n <div className=\"relative\" {...rest}>\n {spinning && (\n <div className=\"absolute inset-0 flex flex-col items-center justify-center bg-base-100/50 backdrop-blur-sm z-10\">\n <span className={spinnerClasses}></span>\n {tip && <p className=\"mt-2 text-sm\">{tip}</p>}\n </div>\n )}\n <div className={spinning ? 'pointer-events-none' : ''}>{children}</div>\n </div>\n )\n }\n\n if (!spinning) {\n return null\n }\n\n return (\n <div className=\"flex flex-col items-center gap-2\" {...rest}>\n <span className={spinnerClasses}></span>\n {tip && <p className=\"text-sm\">{tip}</p>}\n </div>\n )\n}\n"],"names":["dLoading","dLoadingXs","dLoadingSm","dLoadingMd","dLoadingLg","dLoadingXl","dLoadingSpinner","dLoadingDots","dLoadingRing","dLoadingBall","dLoadingBars","dLoadingInfinity","Loading","size","type","className","spinning","children","tip","rest","componentSize","useConfig","effectiveSize","sizeClasses","spinnerClasses","jsxs","jsx"],"mappings":";;AAIA,MAAMA,IAAW,WACXC,IAAa,cACbC,IAAa,cACbC,IAAa,cACbC,IAAa,cACbC,IAAa,cACbC,IAAkB,mBAClBC,IAAe,gBACfC,IAAe,gBACfC,IAAe,gBACfC,IAAe,gBACfC,IAAmB,oBAUZC,IAAkC,CAAC;AAAA,EAC9C,MAAAC;AAAA,EACA,MAAAC,IAAO;AAAA,EACP,WAAAC,IAAY;AAAA,EACZ,UAAAC,IAAW;AAAA,EACX,UAAAC;AAAA,EACA,KAAAC;AAAA,EACA,GAAGC;AACL,MAAM;AACJ,QAAM,EAAE,eAAAC,EAAA,IAAkBC,EAAA,GACpBC,IAAgBT,KAAQO,KAAiB,MAEzCG,IAAc;AAAA,IAClB,IAAItB;AAAA,IACJ,IAAIC;AAAA,IACJ,IAAIC;AAAA,IACJ,IAAIC;AAAA,IACJ,IAAIC;AAAA,EAAA,GAYAmB,IAAiB,CAACxB,GATJ;AAAA,IAClB,SAASM;AAAA,IACT,MAAMC;AAAA,IACN,MAAMC;AAAA,IACN,MAAMC;AAAA,IACN,MAAMC;AAAA,IACN,UAAUC;AAAA,EAAA,EAGkCG,CAAI,GAAGS,EAAYD,CAAa,GAAGP,CAAS,EACvF,OAAO,OAAO,EACd,KAAK,GAAG;AAEX,SAAIE,IAEA,gBAAAQ,EAAC,OAAA,EAAI,WAAU,YAAY,GAAGN,GAC3B,UAAA;AAAA,IAAAH,KACC,gBAAAS,EAAC,OAAA,EAAI,WAAU,mGACb,UAAA;AAAA,MAAA,gBAAAC,EAAC,QAAA,EAAK,WAAWF,EAAA,CAAgB;AAAA,MAChCN,KAAO,gBAAAQ,EAAC,KAAA,EAAE,WAAU,gBAAgB,UAAAR,EAAA,CAAI;AAAA,IAAA,GAC3C;AAAA,sBAED,OAAA,EAAI,WAAWF,IAAW,wBAAwB,IAAK,UAAAC,EAAA,CAAS;AAAA,EAAA,GACnE,IAICD,IAKH,gBAAAS,EAAC,OAAA,EAAI,WAAU,oCAAoC,GAAGN,GACpD,UAAA;AAAA,IAAA,gBAAAO,EAAC,QAAA,EAAK,WAAWF,EAAA,CAAgB;AAAA,IAChCN,KAAO,gBAAAQ,EAAC,KAAA,EAAE,WAAU,WAAW,UAAAR,EAAA,CAAI;AAAA,EAAA,GACtC,IAPO;AASX;"}
|
package/dist/components/Modal.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsxs as f, jsx as t, Fragment as Ce } from "react/jsx-runtime";
|
|
2
2
|
import B, { forwardRef as Me, useRef as k, useId as V, useImperativeHandle as Ne, useEffect as X } from "react";
|
|
3
3
|
import { createRoot as Te } from "react-dom/client";
|
|
4
|
-
import { useConfig as oe } from "
|
|
4
|
+
import { useConfig as oe } from "../providers/ConfigProvider.js";
|
|
5
5
|
const Be = "modal", Y = "modal-top", Z = "modal-middle", _ = "modal-bottom", $e = "modal-start", Le = "modal-end", Re = "modal-box", ee = "modal-action", Se = "modal-backdrop", x = "btn", W = "btn-primary", te = "btn-error", Ae = "alert", Ee = "alert-info", je = "alert-success", We = "alert-warning", Oe = "alert-error", ne = Me(function({
|
|
6
6
|
children: s,
|
|
7
7
|
title: d,
|