@vritti/quantum-ui 0.3.7 → 0.3.9
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/Avatar.js +4 -4
- package/dist/Checkbox2.js +2 -2
- package/dist/ConfirmHost.js +109 -0
- package/dist/ConfirmHost.js.map +1 -0
- package/dist/Dialog.js +74 -42
- package/dist/Dialog.js.map +1 -1
- package/dist/DropdownMenu.js +1 -2
- package/dist/DropdownMenu.js.map +1 -1
- package/dist/Form.js +50 -26
- package/dist/Form.js.map +1 -1
- package/dist/Progress.js +2 -2
- package/dist/RadioGroup.js +2 -2
- package/dist/Sidebar.js +1 -1
- package/dist/Switch.js +2 -2
- package/dist/TabsSkeleton.js +48 -22
- package/dist/TabsSkeleton.js.map +1 -1
- package/dist/Toggle.js +1 -1
- package/dist/assets/quantum-ui.css +43 -5
- package/dist/cells.js +46 -43
- package/dist/cells.js.map +1 -1
- package/dist/components/ConfirmHost.js +2 -0
- package/dist/components/ConfirmHost.js.map +1 -0
- package/dist/components/RichTextEditor.js +1 -1
- package/dist/context/index.js +0 -1
- package/dist/context/index.js.map +1 -1
- package/dist/dropdown-menu.js +2 -2
- package/dist/image-component.js +1 -1
- package/dist/index.js +2 -2
- package/dist/index13.js +1 -1
- package/dist/index14.js +3 -3
- package/dist/index15.js +1 -1
- package/dist/index16.js +1 -1
- package/dist/index17.js +1 -1
- package/dist/index20.js +1 -1
- package/dist/index25.js +1 -1
- package/dist/index26.js +2 -2
- package/dist/index29.js +1123 -35
- package/dist/index29.js.map +1 -1
- package/dist/index30.js +36 -310
- package/dist/index30.js.map +1 -1
- package/dist/index31.js +309 -7
- package/dist/index31.js.map +1 -1
- package/dist/index32.js +8 -30
- package/dist/index32.js.map +1 -1
- package/dist/index33.js +29 -59
- package/dist/index33.js.map +1 -1
- package/dist/index34.js +59 -10
- package/dist/index34.js.map +1 -1
- package/dist/index35.js +10 -35
- package/dist/index35.js.map +1 -1
- package/dist/index36.js +27 -36809
- package/dist/index36.js.map +1 -1
- package/dist/index37.js +36809 -70
- package/dist/index37.js.map +1 -1
- package/dist/index38.js +72 -187
- package/dist/index38.js.map +1 -1
- package/dist/index39.js +199 -0
- package/dist/index39.js.map +1 -0
- package/dist/lib/components/ConfirmHost/ConfirmHost.d.ts +39 -0
- package/dist/lib/components/ConfirmHost/ConfirmHost.d.ts.map +1 -0
- package/dist/lib/components/ConfirmHost/index.d.ts +2 -0
- package/dist/lib/components/ConfirmHost/index.d.ts.map +1 -0
- package/dist/lib/components/Dialog/Dialog.d.ts +2 -3
- package/dist/lib/components/Dialog/Dialog.d.ts.map +1 -1
- package/dist/lib/components/DropdownMenu/DropdownMenu.d.ts.map +1 -1
- package/dist/lib/components/DropdownMenu/types.d.ts +0 -1
- package/dist/lib/components/DropdownMenu/types.d.ts.map +1 -1
- package/dist/lib/components/Form/Form.d.ts.map +1 -1
- package/dist/lib/components/Tabs/Tabs.d.ts +2 -1
- package/dist/lib/components/Tabs/Tabs.d.ts.map +1 -1
- package/dist/lib/components/index.d.ts +1 -0
- package/dist/lib/components/index.d.ts.map +1 -1
- package/dist/lib/context/index.d.ts +0 -1
- package/dist/lib/context/index.d.ts.map +1 -1
- package/dist/lib/hooks/useConfirm.d.ts +3 -3
- package/dist/lib/hooks/useConfirm.d.ts.map +1 -1
- package/dist/useConfirm.js +3 -7
- package/dist/useConfirm.js.map +1 -1
- package/dist/utils/motion.js +2 -2
- package/dist/value.js +1 -1
- package/package.json +5 -1
- package/dist/Combination.js +0 -1129
- package/dist/Combination.js.map +0 -1
- package/dist/ConfirmContext.js +0 -96
- package/dist/ConfirmContext.js.map +0 -1
- package/dist/lib/context/ConfirmContext.d.ts +0 -26
- package/dist/lib/context/ConfirmContext.d.ts.map +0 -1
package/dist/Form.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Form.js","sources":["../lib/utils/formHelpers.ts","../lib/components/Form/Form.tsx"],"sourcesContent":["import type { FieldPath, FieldValues, UseFormReturn } from 'react-hook-form';\n\n/**\n * Field mapping configuration for API error to form field mapping\n */\nexport interface FieldMapping {\n [apiField: string]: string; // Maps API field names to form field names\n}\n\n/**\n * Axios error structure (or similar HTTP client error structure)\n */\ninterface AxiosLikeError {\n response?: {\n data?: unknown;\n };\n}\n\n/**\n * RFC 9457 field error structure\n */\nexport interface FieldError {\n field: string;\n message: string;\n}\n\n/**\n * API error structure with field-specific errors\n * Supports RFC 9457 Problem Details format\n */\nexport interface ApiErrorResponse {\n type?: string; // RFC 9457: URI reference identifying the problem type\n title?: string; // RFC 9457: Short human-readable summary\n status?: number; // RFC 9457: HTTP status code\n label?: string; // Root error heading displayed to the user\n detail?: string; // RFC 9457: Human-readable explanation\n instance?: string; // RFC 9457: URI reference for the specific occurrence\n errors?: FieldError[];\n}\n\n/**\n * Options for mapping API errors to form\n */\nexport interface MapApiErrorsOptions {\n /**\n * Field name mapping from API to form fields\n */\n fieldMapping?: FieldMapping;\n\n /**\n * Whether to set root error for general messages\n */\n setRootError?: boolean;\n}\n\n/**\n * Maps an RFC 9457 Problem Details API error response to react-hook-form errors.\n *\n * Root errors (`label`/`title` + `detail`) and field errors (`errors[]`) are\n * handled independently -- a single response can populate both the root error\n * alert and inline field errors at the same time.\n *\n * @param error - The error object from API response\n * @param form - The react-hook-form instance\n * @param options - Mapping options\n *\n * @example\n * ```tsx\n * try {\n * await api.post('/login', data);\n * } catch (error) {\n * mapApiErrorsToForm(error.response?.data, form, {\n * fieldMapping: {\n * 'email_address': 'email',\n * 'password_hash': 'password'\n * }\n * });\n * }\n * ```\n */\nexport function mapApiErrorsToForm<TFieldValues extends FieldValues = FieldValues>(\n error: unknown,\n form: UseFormReturn<TFieldValues>,\n options: MapApiErrorsOptions = {},\n): void {\n const { fieldMapping = {}, setRootError = true } = options;\n\n if (!error || typeof error !== 'object') {\n if (setRootError) {\n form.setError('root', {\n type: 'Error',\n message: 'An error occurred',\n });\n }\n return;\n }\n\n // Extract error data from axios response structure\n const axiosError = error as AxiosLikeError;\n const errorData = axiosError.response?.data || error;\n const apiError = errorData as ApiErrorResponse;\n\n // Extract title/label for error heading (RFC 9457)\n const errorTitle = apiError.label || apiError.title || 'Error';\n const generalMessage = apiError.detail;\n\n // Map field-specific errors (field is always present in RFC 9457)\n let mappedFieldErrorsCount = 0;\n if (apiError.errors && Array.isArray(apiError.errors)) {\n for (const errorItem of apiError.errors) {\n const formField = fieldMapping[errorItem.field] || errorItem.field;\n\n form.setError(formField as FieldPath<TFieldValues>, {\n type: 'manual',\n message: errorItem.message,\n });\n mappedFieldErrorsCount += 1;\n }\n }\n\n // Root error is shown only when no field errors are present\n if (generalMessage && setRootError && mappedFieldErrorsCount === 0) {\n form.setError('root', {\n type: errorTitle,\n message: generalMessage,\n });\n }\n}\n","import type { UseMutationResult } from '@tanstack/react-query';\nimport type React from 'react';\nimport { Children, cloneElement, Fragment, isValidElement, useCallback } from 'react';\nimport {\n Controller,\n type ControllerProps,\n type FieldPath,\n type FieldValues,\n FormProvider,\n type UseFormReturn,\n} from 'react-hook-form';\nimport type { Country } from 'react-phone-number-input';\nimport { cn } from '../../../shadcn/utils';\nimport { axios } from '../../utils/axios';\nimport { type FieldMapping, mapApiErrorsToForm } from '../../utils/formHelpers';\nimport { Alert } from '../Alert';\nimport { Button } from '../Button';\nimport { Checkbox } from '../Checkbox';\nimport { CheckboxGroup } from '../CheckboxGroup';\nimport { DatePicker } from '../DatePicker';\nimport { DateTimePicker } from '../DateTimePicker';\nimport { PhoneField } from '../PhoneField';\nimport { RadioGroup } from '../RadioGroup';\nimport { Switch } from '../Switch';\nimport { UploadFile } from '../UploadFile';\n\n// Re-export Controller for explicit usage\nexport { Controller } from 'react-hook-form';\n\n/**\n * Recursively process children to wrap form fields with Controller\n * and inject loading state into submit buttons\n */\nfunction processChildren<\n TFieldValues extends FieldValues = FieldValues,\n _TContext = any,\n TTransformedValues extends FieldValues | undefined = TFieldValues,\n>(\n children: React.ReactNode,\n control: ControllerProps<TFieldValues, FieldPath<TFieldValues>, TTransformedValues>['control'],\n isSubmitting: boolean,\n setValue: UseFormReturn<TFieldValues, _TContext, TTransformedValues>['setValue'],\n onCancel?: () => void,\n reset?: UseFormReturn<TFieldValues, _TContext, TTransformedValues>['reset'],\n): React.ReactNode {\n return Children.map(children, (child) => {\n // Handle non-element children (strings, numbers, null, etc.)\n if (!isValidElement(child)) {\n return child;\n }\n\n const childProps = child.props as any;\n const isFragment = child.type === Fragment;\n\n // Handle form fields with name prop (but not Fragments)\n if (!isFragment && childProps.name && typeof childProps.name === 'string') {\n const name = childProps.name as FieldPath<TFieldValues>;\n\n return (\n <Controller\n key={name}\n control={control}\n name={name}\n render={({ field, fieldState }) => {\n // Check if this is a Checkbox, Switch, RadioGroup, or CheckboxGroup component\n const isCheckbox = child.type === Checkbox;\n const isSwitch = child.type === Switch;\n const isRadioGroup = child.type === RadioGroup;\n const isCheckboxGroup = child.type === CheckboxGroup;\n const isPhone = child.type === PhoneField;\n const isDatePicker = child.type === DatePicker;\n const isDateTimePicker = child.type === DateTimePicker;\n\n const fieldProps =\n isCheckbox || isSwitch\n ? {\n checked: field.value,\n onCheckedChange: field.onChange,\n onBlur: field.onBlur,\n ref: field.ref,\n }\n : isRadioGroup || isCheckboxGroup\n ? {\n value: field.value,\n onValueChange: field.onChange,\n onBlur: field.onBlur,\n }\n : isDatePicker\n ? {\n value: field.value,\n onValueChange: field.onChange,\n onBlur: field.onBlur,\n ref: field.ref,\n }\n : isDateTimePicker\n ? {\n value: field.value,\n onValueChange: field.onChange,\n onBlur: field.onBlur,\n ref: field.ref,\n }\n : isPhone\n ? {\n ...field,\n onCountryChange: (country: Country | undefined) => {\n setValue(`${name}Country` as FieldPath<TFieldValues>, country as any);\n },\n }\n : field;\n\n const isUploadFile = child.type === UploadFile;\n\n return cloneElement(child, {\n ...childProps,\n ...fieldProps,\n error: fieldState.error?.message || (fieldState.error ? 'Invalid' : undefined),\n name: undefined, // Remove name to avoid passing it to the underlying input\n ...(isUploadFile ? { isLoading: isSubmitting } : {}),\n });\n }}\n />\n );\n }\n\n // Handle cancel buttons - wire up form.reset() + onCancel callback\n if (childProps['data-cancel'] && onCancel && reset) {\n return cloneElement(child, {\n ...childProps,\n onClick: () => {\n reset();\n onCancel();\n },\n });\n }\n\n // Handle submit buttons - inject loading state via isLoading prop\n if (childProps.type === 'submit') {\n const isButtonElement =\n child.type === Button || (typeof child.type === 'function' && (child.type as any).displayName === 'Button');\n\n if (isButtonElement) {\n return cloneElement(child, {\n ...childProps,\n isLoading: isSubmitting,\n });\n }\n }\n\n // Handle React Fragments - process their children directly\n if (isFragment) {\n return processChildren(childProps.children, control, isSubmitting, setValue, onCancel, reset);\n }\n\n // Recurse into children for container elements (divs, FieldGroups, etc.)\n if (childProps.children != null) {\n return cloneElement(child, {\n ...childProps,\n children: processChildren(childProps.children, control, isSubmitting, setValue, onCancel, reset),\n });\n }\n\n // Return unchanged if no name prop and no children\n return child;\n });\n}\n\nexport interface FormProps<\n TFieldValues extends FieldValues = FieldValues,\n TContext = any,\n TTransformedValues extends FieldValues | undefined = TFieldValues,\n TMutationData = unknown,\n TMutationError = Error,\n TMutationVariables = any,\n> extends Omit<React.FormHTMLAttributes<HTMLFormElement>, 'onSubmit'> {\n /**\n * The react-hook-form form instance\n */\n form: UseFormReturn<TFieldValues, TContext, TTransformedValues>;\n\n /**\n * Form submit handler - receives the transformed values if transformation is applied.\n * Optional when using `mutation` prop.\n */\n onSubmit?: Parameters<UseFormReturn<TFieldValues, TContext, TTransformedValues>['handleSubmit']>[0];\n\n /**\n * Children elements - automatically wrapped with Controller if they have a name prop\n */\n children: React.ReactNode;\n\n /**\n * Position of the root error display\n * @default 'bottom'\n */\n rootErrorPosition?: 'top' | 'bottom';\n\n /**\n * Additional classes for the root error display\n */\n rootErrorClassName?: string;\n\n /**\n * Action element rendered in the root error Alert (e.g. button or link)\n * Positioned in the top-right corner using AlertAction\n */\n rootErrorAction?: React.ReactNode;\n\n /**\n * Field mapping for automatic API error mapping\n * Maps API field names to form field names\n */\n fieldMapping?: FieldMapping;\n\n /**\n * TanStack Query mutation for automatic handling.\n * When provided, the form will use `mutateAsync` to submit data and handle errors automatically.\n * The mutation's own callbacks (onSuccess, onError, etc.) will fire automatically.\n * Form only adds `mapApiErrorsToForm` as an extra error handling layer.\n * Optional - you can use `onSubmit` instead for forms that don't use mutations.\n */\n mutation?: UseMutationResult<TMutationData, TMutationError, TMutationVariables, unknown>;\n\n /**\n * Transform form data to mutation variables before submission.\n * Only used when `mutation` prop is provided.\n */\n transformSubmit?: (\n data: TTransformedValues extends undefined ? TFieldValues : TTransformedValues,\n ) => TMutationVariables;\n\n /**\n * Automatically calls form.reset() after a successful mutation.\n * Set to false for \"edit\" forms where resetting clears pre-populated values.\n * @default true\n */\n resetOnSuccess?: boolean;\n\n /**\n * Called when a cancel button (marked with data-cancel) is clicked.\n * Form.reset() is called automatically before invoking this callback.\n */\n onCancel?: () => void;\n}\n\n/**\n * Smart Form component that automatically wraps children with Controller\n *\n * Usage with onSubmit:\n * ```tsx\n * <Form form={form} onSubmit={handleSubmit}>\n * <TextField name=\"email\" label=\"Email\" description=\"Your email address\" />\n * <PasswordField name=\"password\" label=\"Password\" />\n * <Button type=\"submit\">Submit</Button>\n * </Form>\n * ```\n *\n * Usage with TanStack Query mutation:\n * ```tsx\n * const mutation = useMutation({\n * mutationFn: (data) => api.post('/login', data),\n * onSuccess: (data) => console.log('Success!', data),\n * onError: (error) => console.error('Error!', error),\n * });\n *\n * <Form\n * form={form}\n * mutation={mutation}\n * transformSubmit={(data) => ({ ...data, timestamp: Date.now() })}\n * >\n * <TextField name=\"email\" label=\"Email\" />\n * <Button type=\"submit\">Submit</Button>\n * </Form>\n * ```\n */\nexport function Form<\n TFieldValues extends FieldValues = FieldValues,\n TContext = any,\n TTransformedValues extends FieldValues | undefined = TFieldValues,\n TMutationData = unknown,\n TMutationError = Error,\n TMutationVariables = any,\n>({\n form,\n onSubmit,\n children,\n rootErrorPosition = 'bottom',\n rootErrorClassName,\n rootErrorAction,\n fieldMapping,\n mutation,\n transformSubmit,\n resetOnSuccess,\n onCancel,\n className,\n ...props\n}: FormProps<TFieldValues, TContext, TTransformedValues, TMutationData, TMutationError, TMutationVariables>) {\n // Compute isSubmitting from both form state and mutation state\n const isSubmitting = form.formState.isSubmitting || (mutation?.isPending ?? false);\n\n // Wrap the submit handler with automatic error mapping (always enabled)\n // Form only adds mapApiErrorsToForm - the mutation's own callbacks fire automatically\n const wrappedOnSubmit = useCallback(\n async (data: TTransformedValues extends undefined ? TFieldValues : TTransformedValues) => {\n // Suppress error toasts during form submission — Form handles errors inline\n const interceptorId = axios.interceptors.request.use((config) => ({\n ...config,\n showErrorToast: false,\n }));\n\n try {\n if (mutation) {\n const variables = transformSubmit ? transformSubmit(data) : data;\n // mutateAsync will trigger the mutation's onSuccess/onError callbacks\n await mutation.mutateAsync(variables as TMutationVariables);\n } else if (onSubmit) {\n await onSubmit(data as any);\n }\n\n // Reset form after successful submission (default: true)\n if (resetOnSuccess !== false) form.reset();\n } catch (error) {\n // Form's only job: map API errors to form fields\n // mapApiErrorsToForm handles axios error structure extraction internally\n mapApiErrorsToForm(error, form as any, {\n fieldMapping,\n });\n // Log error for debugging\n console.error('[Form Submission Error]', error);\n // Error is swallowed, not re-thrown (mutation's onError already fired)\n } finally {\n axios.interceptors.request.eject(interceptorId);\n }\n },\n [onSubmit, mutation, transformSubmit, fieldMapping, form, resetOnSuccess],\n );\n\n const handleSubmit = form.handleSubmit(wrappedOnSubmit as any);\n\n // Process children recursively to automatically wrap with Controller\n const processedChildren = processChildren(children, form.control, isSubmitting, form.setValue, onCancel, form.reset);\n\n return (\n <FormProvider {...form}>\n <form onSubmit={handleSubmit} className={cn('space-y-4', className)} {...props}>\n {/* Top position error */}\n {rootErrorPosition === 'top' && form.formState.errors.root && (\n <Alert\n variant=\"destructive\"\n title={form.formState.errors.root.type || 'Error'}\n description={form.formState.errors.root.message}\n action={rootErrorAction}\n className={cn('mb-4', rootErrorClassName)}\n />\n )}\n\n {processedChildren}\n\n {/* Bottom position error */}\n {rootErrorPosition === 'bottom' && form.formState.errors.root && (\n <Alert\n variant=\"destructive\"\n title={form.formState.errors.root.type || 'Error'}\n description={form.formState.errors.root.message}\n action={rootErrorAction}\n className={cn('mt-4', rootErrorClassName)}\n />\n )}\n </form>\n </FormProvider>\n );\n}\n\nForm.displayName = 'Form';\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAgFO,SAAS,kBAAA,CACd,KAAA,EACA,IAAA,EACA,OAAA,GAA+B,EAAC,EAC1B;AACN,EAAA,MAAM,EAAE,YAAA,GAAe,EAAC,EAAG,YAAA,GAAe,MAAK,GAAI,OAAA;AAEnD,EAAA,IAAI,CAAC,KAAA,IAAS,OAAO,KAAA,KAAU,QAAA,EAAU;AACvC,IAAA,IAAI,YAAA,EAAc;AAChB,MAAA,IAAA,CAAK,SAAS,MAAA,EAAQ;AAAA,QACpB,IAAA,EAAM,OAAA;AAAA,QACN,OAAA,EAAS;AAAA,OACV,CAAA;AAAA,IACH;AACA,IAAA;AAAA,EACF;AAGA,EAAA,MAAM,UAAA,GAAa,KAAA;AACnB,EAAA,MAAM,SAAA,GAAY,UAAA,CAAW,QAAA,EAAU,IAAA,IAAQ,KAAA;AAC/C,EAAA,MAAM,QAAA,GAAW,SAAA;AAGjB,EAAA,MAAM,UAAA,GAAa,QAAA,CAAS,KAAA,IAAS,QAAA,CAAS,KAAA,IAAS,OAAA;AACvD,EAAA,MAAM,iBAAiB,QAAA,CAAS,MAAA;AAGhC,EAAA,IAAI,sBAAA,GAAyB,CAAA;AAC7B,EAAA,IAAI,SAAS,MAAA,IAAU,KAAA,CAAM,OAAA,CAAQ,QAAA,CAAS,MAAM,CAAA,EAAG;AACrD,IAAA,KAAA,MAAW,SAAA,IAAa,SAAS,MAAA,EAAQ;AACvC,MAAA,MAAM,SAAA,GAAY,YAAA,CAAa,SAAA,CAAU,KAAK,KAAK,SAAA,CAAU,KAAA;AAE7D,MAAA,IAAA,CAAK,SAAS,SAAA,EAAsC;AAAA,QAClD,IAAA,EAAM,QAAA;AAAA,QACN,SAAS,SAAA,CAAU;AAAA,OACpB,CAAA;AACD,MAAA,sBAAA,IAA0B,CAAA;AAAA,IAC5B;AAAA,EACF;AAGA,EAAA,IAAI,cAAA,IAAkB,YAAA,IAAgB,sBAAA,KAA2B,CAAA,EAAG;AAClE,IAAA,IAAA,CAAK,SAAS,MAAA,EAAQ;AAAA,MACpB,IAAA,EAAM,UAAA;AAAA,MACN,OAAA,EAAS;AAAA,KACV,CAAA;AAAA,EACH;AACF;;AC9FA,SAAS,gBAKP,QAAA,EACA,OAAA,EACA,YAAA,EACA,QAAA,EACA,UACA,KAAA,EACiB;AACjB,EAAA,OAAO,QAAA,CAAS,GAAA,CAAI,QAAA,EAAU,CAAC,KAAA,KAAU;AAEvC,IAAA,IAAI,CAAC,cAAA,CAAe,KAAK,CAAA,EAAG;AAC1B,MAAA,OAAO,KAAA;AAAA,IACT;AAEA,IAAA,MAAM,aAAa,KAAA,CAAM,KAAA;AACzB,IAAA,MAAM,UAAA,GAAa,MAAM,IAAA,KAAS,QAAA;AAGlC,IAAA,IAAI,CAAC,UAAA,IAAc,UAAA,CAAW,QAAQ,OAAO,UAAA,CAAW,SAAS,QAAA,EAAU;AACzE,MAAA,MAAM,OAAO,UAAA,CAAW,IAAA;AAExB,MAAA,uBACE,GAAA;AAAA,QAAC,UAAA;AAAA,QAAA;AAAA,UAEC,OAAA;AAAA,UACA,IAAA;AAAA,UACA,MAAA,EAAQ,CAAC,EAAE,KAAA,EAAO,YAAW,KAAM;AAEjC,YAAA,MAAM,UAAA,GAAa,MAAM,IAAA,KAAS,QAAA;AAClC,YAAA,MAAM,QAAA,GAAW,MAAM,IAAA,KAAS,MAAA;AAChC,YAAA,MAAM,YAAA,GAAe,MAAM,IAAA,KAAS,UAAA;AACpC,YAAA,MAAM,eAAA,GAAkB,MAAM,IAAA,KAAS,aAAA;AACvC,YAAA,MAAM,OAAA,GAAU,MAAM,IAAA,KAAS,UAAA;AAC/B,YAAA,MAAM,YAAA,GAAe,MAAM,IAAA,KAAS,UAAA;AACpC,YAAA,MAAM,gBAAA,GAAmB,MAAM,IAAA,KAAS,cAAA;AAExC,YAAA,MAAM,UAAA,GACJ,cAAc,QAAA,GACV;AAAA,cACE,SAAS,KAAA,CAAM,KAAA;AAAA,cACf,iBAAiB,KAAA,CAAM,QAAA;AAAA,cACvB,QAAQ,KAAA,CAAM,MAAA;AAAA,cACd,KAAK,KAAA,CAAM;AAAA,aACb,GACA,gBAAgB,eAAA,GACd;AAAA,cACE,OAAO,KAAA,CAAM,KAAA;AAAA,cACb,eAAe,KAAA,CAAM,QAAA;AAAA,cACrB,QAAQ,KAAA,CAAM;AAAA,gBAEhB,YAAA,GACE;AAAA,cACE,OAAO,KAAA,CAAM,KAAA;AAAA,cACb,eAAe,KAAA,CAAM,QAAA;AAAA,cACrB,QAAQ,KAAA,CAAM,MAAA;AAAA,cACd,KAAK,KAAA,CAAM;AAAA,gBAEb,gBAAA,GACE;AAAA,cACE,OAAO,KAAA,CAAM,KAAA;AAAA,cACb,eAAe,KAAA,CAAM,QAAA;AAAA,cACrB,QAAQ,KAAA,CAAM,MAAA;AAAA,cACd,KAAK,KAAA,CAAM;AAAA,gBAEb,OAAA,GACE;AAAA,cACE,GAAG,KAAA;AAAA,cACH,eAAA,EAAiB,CAAC,OAAA,KAAiC;AACjD,gBAAA,QAAA,CAAS,CAAA,EAAG,IAAI,CAAA,OAAA,CAAA,EAAsC,OAAc,CAAA;AAAA,cACtE;AAAA,aACF,GACA,KAAA;AAEd,YAAA,MAAM,YAAA,GAAe,MAAM,IAAA,KAAS,UAAA;AAEpC,YAAA,OAAO,aAAa,KAAA,EAAO;AAAA,cACzB,GAAG,UAAA;AAAA,cACH,GAAG,UAAA;AAAA,cACH,OAAO,UAAA,CAAW,KAAA,EAAO,OAAA,KAAY,UAAA,CAAW,QAAQ,SAAA,GAAY,MAAA,CAAA;AAAA,cACpE,IAAA,EAAM,MAAA;AAAA;AAAA,cACN,GAAI,YAAA,GAAe,EAAE,SAAA,EAAW,YAAA,KAAiB;AAAC,aACnD,CAAA;AAAA,UACH;AAAA,SAAA;AAAA,QA3DK;AAAA,OA4DP;AAAA,IAEJ;AAGA,IAAA,IAAI,UAAA,CAAW,aAAa,CAAA,IAAK,QAAA,IAAY,KAAA,EAAO;AAClD,MAAA,OAAO,aAAa,KAAA,EAAO;AAAA,QACzB,GAAG,UAAA;AAAA,QACH,SAAS,MAAM;AACb,UAAA,KAAA,EAAM;AACN,UAAA,QAAA,EAAS;AAAA,QACX;AAAA,OACD,CAAA;AAAA,IACH;AAGA,IAAA,IAAI,UAAA,CAAW,SAAS,QAAA,EAAU;AAChC,MAAA,MAAM,eAAA,GACJ,KAAA,CAAM,IAAA,KAAS,MAAA,IAAW,OAAO,MAAM,IAAA,KAAS,UAAA,IAAe,KAAA,CAAM,IAAA,CAAa,WAAA,KAAgB,QAAA;AAEpG,MAAA,IAAI,eAAA,EAAiB;AACnB,QAAA,OAAO,aAAa,KAAA,EAAO;AAAA,UACzB,GAAG,UAAA;AAAA,UACH,SAAA,EAAW;AAAA,SACZ,CAAA;AAAA,MACH;AAAA,IACF;AAGA,IAAA,IAAI,UAAA,EAAY;AACd,MAAA,OAAO,gBAAgB,UAAA,CAAW,QAAA,EAAU,SAAS,YAAA,EAAc,QAAA,EAAU,UAAU,KAAK,CAAA;AAAA,IAC9F;AAGA,IAAA,IAAI,UAAA,CAAW,YAAY,IAAA,EAAM;AAC/B,MAAA,OAAO,aAAa,KAAA,EAAO;AAAA,QACzB,GAAG,UAAA;AAAA,QACH,QAAA,EAAU,gBAAgB,UAAA,CAAW,QAAA,EAAU,SAAS,YAAA,EAAc,QAAA,EAAU,UAAU,KAAK;AAAA,OAChG,CAAA;AAAA,IACH;AAGA,IAAA,OAAO,KAAA;AAAA,EACT,CAAC,CAAA;AACH;AA8GO,SAAS,IAAA,CAOd;AAAA,EACA,IAAA;AAAA,EACA,QAAA;AAAA,EACA,QAAA;AAAA,EACA,iBAAA,GAAoB,QAAA;AAAA,EACpB,kBAAA;AAAA,EACA,eAAA;AAAA,EACA,YAAA;AAAA,EACA,QAAA;AAAA,EACA,eAAA;AAAA,EACA,cAAA;AAAA,EACA,QAAA;AAAA,EACA,SAAA;AAAA,EACA,GAAG;AACL,CAAA,EAA6G;AAE3G,EAAA,MAAM,YAAA,GAAe,IAAA,CAAK,SAAA,CAAU,YAAA,KAAiB,UAAU,SAAA,IAAa,KAAA,CAAA;AAI5E,EAAA,MAAM,eAAA,GAAkB,WAAA;AAAA,IACtB,OAAO,IAAA,KAAmF;AAExF,MAAA,MAAM,gBAAgB,KAAA,CAAM,YAAA,CAAa,OAAA,CAAQ,GAAA,CAAI,CAAC,MAAA,MAAY;AAAA,QAChE,GAAG,MAAA;AAAA,QACH,cAAA,EAAgB;AAAA,OAClB,CAAE,CAAA;AAEF,MAAA,IAAI;AACF,QAAA,IAAI,QAAA,EAAU;AACZ,UAAA,MAAM,SAAA,GAAY,eAAA,GAAkB,eAAA,CAAgB,IAAI,CAAA,GAAI,IAAA;AAE5D,UAAA,MAAM,QAAA,CAAS,YAAY,SAA+B,CAAA;AAAA,QAC5D,WAAW,QAAA,EAAU;AACnB,UAAA,MAAM,SAAS,IAAW,CAAA;AAAA,QAC5B;AAGA,QAAA,IAAI,cAAA,KAAmB,KAAA,EAAO,IAAA,CAAK,KAAA,EAAM;AAAA,MAC3C,SAAS,KAAA,EAAO;AAGd,QAAA,kBAAA,CAAmB,OAAO,IAAA,EAAa;AAAA,UACrC;AAAA,SACD,CAAA;AAED,QAAA,OAAA,CAAQ,KAAA,CAAM,2BAA2B,KAAK,CAAA;AAAA,MAEhD,CAAA,SAAE;AACA,QAAA,KAAA,CAAM,YAAA,CAAa,OAAA,CAAQ,KAAA,CAAM,aAAa,CAAA;AAAA,MAChD;AAAA,IACF,CAAA;AAAA,IACA,CAAC,QAAA,EAAU,QAAA,EAAU,eAAA,EAAiB,YAAA,EAAc,MAAM,cAAc;AAAA,GAC1E;AAEA,EAAA,MAAM,YAAA,GAAe,IAAA,CAAK,YAAA,CAAa,eAAsB,CAAA;AAG7D,EAAA,MAAM,iBAAA,GAAoB,eAAA,CAAgB,QAAA,EAAU,IAAA,CAAK,OAAA,EAAS,cAAc,IAAA,CAAK,QAAA,EAAU,QAAA,EAAU,IAAA,CAAK,KAAK,CAAA;AAEnH,EAAA,uBACE,GAAA,CAAC,YAAA,EAAA,EAAc,GAAG,IAAA,EAChB,+BAAC,MAAA,EAAA,EAAK,QAAA,EAAU,YAAA,EAAc,SAAA,EAAW,EAAA,CAAG,WAAA,EAAa,SAAS,CAAA,EAAI,GAAG,KAAA,EAEtE,QAAA,EAAA;AAAA,IAAA,iBAAA,KAAsB,KAAA,IAAS,IAAA,CAAK,SAAA,CAAU,MAAA,CAAO,IAAA,oBACpD,GAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,OAAA,EAAQ,aAAA;AAAA,QACR,KAAA,EAAO,IAAA,CAAK,SAAA,CAAU,MAAA,CAAO,KAAK,IAAA,IAAQ,OAAA;AAAA,QAC1C,WAAA,EAAa,IAAA,CAAK,SAAA,CAAU,MAAA,CAAO,IAAA,CAAK,OAAA;AAAA,QACxC,MAAA,EAAQ,eAAA;AAAA,QACR,SAAA,EAAW,EAAA,CAAG,MAAA,EAAQ,kBAAkB;AAAA;AAAA,KAC1C;AAAA,IAGD,iBAAA;AAAA,IAGA,iBAAA,KAAsB,QAAA,IAAY,IAAA,CAAK,SAAA,CAAU,OAAO,IAAA,oBACvD,GAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,OAAA,EAAQ,aAAA;AAAA,QACR,KAAA,EAAO,IAAA,CAAK,SAAA,CAAU,MAAA,CAAO,KAAK,IAAA,IAAQ,OAAA;AAAA,QAC1C,WAAA,EAAa,IAAA,CAAK,SAAA,CAAU,MAAA,CAAO,IAAA,CAAK,OAAA;AAAA,QACxC,MAAA,EAAQ,eAAA;AAAA,QACR,SAAA,EAAW,EAAA,CAAG,MAAA,EAAQ,kBAAkB;AAAA;AAAA;AAC1C,GAAA,EAEJ,CAAA,EACF,CAAA;AAEJ;AAEA,IAAA,CAAK,WAAA,GAAc,MAAA;;;;"}
|
|
1
|
+
{"version":3,"file":"Form.js","sources":["../lib/utils/formHelpers.ts","../lib/components/Form/Form.tsx"],"sourcesContent":["import type { FieldPath, FieldValues, UseFormReturn } from 'react-hook-form';\n\n/**\n * Field mapping configuration for API error to form field mapping\n */\nexport interface FieldMapping {\n [apiField: string]: string; // Maps API field names to form field names\n}\n\n/**\n * Axios error structure (or similar HTTP client error structure)\n */\ninterface AxiosLikeError {\n response?: {\n data?: unknown;\n };\n}\n\n/**\n * RFC 9457 field error structure\n */\nexport interface FieldError {\n field: string;\n message: string;\n}\n\n/**\n * API error structure with field-specific errors\n * Supports RFC 9457 Problem Details format\n */\nexport interface ApiErrorResponse {\n type?: string; // RFC 9457: URI reference identifying the problem type\n title?: string; // RFC 9457: Short human-readable summary\n status?: number; // RFC 9457: HTTP status code\n label?: string; // Root error heading displayed to the user\n detail?: string; // RFC 9457: Human-readable explanation\n instance?: string; // RFC 9457: URI reference for the specific occurrence\n errors?: FieldError[];\n}\n\n/**\n * Options for mapping API errors to form\n */\nexport interface MapApiErrorsOptions {\n /**\n * Field name mapping from API to form fields\n */\n fieldMapping?: FieldMapping;\n\n /**\n * Whether to set root error for general messages\n */\n setRootError?: boolean;\n}\n\n/**\n * Maps an RFC 9457 Problem Details API error response to react-hook-form errors.\n *\n * Root errors (`label`/`title` + `detail`) and field errors (`errors[]`) are\n * handled independently -- a single response can populate both the root error\n * alert and inline field errors at the same time.\n *\n * @param error - The error object from API response\n * @param form - The react-hook-form instance\n * @param options - Mapping options\n *\n * @example\n * ```tsx\n * try {\n * await api.post('/login', data);\n * } catch (error) {\n * mapApiErrorsToForm(error.response?.data, form, {\n * fieldMapping: {\n * 'email_address': 'email',\n * 'password_hash': 'password'\n * }\n * });\n * }\n * ```\n */\nexport function mapApiErrorsToForm<TFieldValues extends FieldValues = FieldValues>(\n error: unknown,\n form: UseFormReturn<TFieldValues>,\n options: MapApiErrorsOptions = {},\n): void {\n const { fieldMapping = {}, setRootError = true } = options;\n\n if (!error || typeof error !== 'object') {\n if (setRootError) {\n form.setError('root', {\n type: 'Error',\n message: 'An error occurred',\n });\n }\n return;\n }\n\n // Extract error data from axios response structure\n const axiosError = error as AxiosLikeError;\n const errorData = axiosError.response?.data || error;\n const apiError = errorData as ApiErrorResponse;\n\n // Extract title/label for error heading (RFC 9457)\n const errorTitle = apiError.label || apiError.title || 'Error';\n const generalMessage = apiError.detail;\n\n // Map field-specific errors (field is always present in RFC 9457)\n let mappedFieldErrorsCount = 0;\n if (apiError.errors && Array.isArray(apiError.errors)) {\n for (const errorItem of apiError.errors) {\n const formField = fieldMapping[errorItem.field] || errorItem.field;\n\n form.setError(formField as FieldPath<TFieldValues>, {\n type: 'manual',\n message: errorItem.message,\n });\n mappedFieldErrorsCount += 1;\n }\n }\n\n // Root error is shown only when no field errors are present\n if (generalMessage && setRootError && mappedFieldErrorsCount === 0) {\n form.setError('root', {\n type: errorTitle,\n message: generalMessage,\n });\n }\n}\n","import type { UseMutationResult } from '@tanstack/react-query';\nimport type React from 'react';\nimport { Children, cloneElement, Fragment, isValidElement, useCallback } from 'react';\nimport {\n Controller,\n type ControllerProps,\n type FieldPath,\n type FieldValues,\n FormProvider,\n type UseFormReturn,\n} from 'react-hook-form';\nimport type { Country } from 'react-phone-number-input';\nimport { cn } from '../../../shadcn/utils';\nimport { axios } from '../../utils/axios';\nimport { type FieldMapping, mapApiErrorsToForm } from '../../utils/formHelpers';\nimport { Alert } from '../Alert';\nimport { Button } from '../Button';\nimport { Checkbox } from '../Checkbox';\nimport { CheckboxGroup } from '../CheckboxGroup';\nimport { DatePicker } from '../DatePicker';\nimport { DateTimePicker } from '../DateTimePicker';\nimport { PhoneField } from '../PhoneField';\nimport { RadioGroup } from '../RadioGroup';\nimport { Switch } from '../Switch';\nimport { UploadFile } from '../UploadFile';\n\n// Re-export Controller for explicit usage\nexport { Controller } from 'react-hook-form';\n\n/**\n * Recursively process children to wrap form fields with Controller\n * and inject loading state into submit buttons\n */\nfunction processChildren<\n TFieldValues extends FieldValues = FieldValues,\n _TContext = any,\n TTransformedValues extends FieldValues | undefined = TFieldValues,\n>(\n children: React.ReactNode,\n control: ControllerProps<TFieldValues, FieldPath<TFieldValues>, TTransformedValues>['control'],\n isSubmitting: boolean,\n setValue: UseFormReturn<TFieldValues, _TContext, TTransformedValues>['setValue'],\n onCancel?: () => void,\n reset?: UseFormReturn<TFieldValues, _TContext, TTransformedValues>['reset'],\n): React.ReactNode {\n return Children.map(children, (child) => {\n // Handle non-element children (strings, numbers, null, etc.)\n if (!isValidElement(child)) {\n return child;\n }\n\n const childProps = child.props as any;\n const isFragment = child.type === Fragment;\n\n // Handle form fields with name prop (but not Fragments)\n if (!isFragment && childProps.name && typeof childProps.name === 'string') {\n const name = childProps.name as FieldPath<TFieldValues>;\n\n return (\n <Controller\n key={name}\n control={control}\n name={name}\n render={({ field, fieldState }) => {\n // Check if this is a Checkbox, Switch, RadioGroup, or CheckboxGroup component\n const isCheckbox = child.type === Checkbox;\n const isSwitch = child.type === Switch;\n const isRadioGroup = child.type === RadioGroup;\n const isCheckboxGroup = child.type === CheckboxGroup;\n const isPhone = child.type === PhoneField;\n const isDatePicker = child.type === DatePicker;\n const isDateTimePicker = child.type === DateTimePicker;\n\n const fieldProps =\n isCheckbox || isSwitch\n ? {\n checked: field.value,\n onCheckedChange: field.onChange,\n onBlur: field.onBlur,\n ref: field.ref,\n }\n : isRadioGroup || isCheckboxGroup\n ? {\n value: field.value,\n onValueChange: field.onChange,\n onBlur: field.onBlur,\n }\n : isDatePicker\n ? {\n value: field.value,\n onValueChange: field.onChange,\n onBlur: field.onBlur,\n ref: field.ref,\n }\n : isDateTimePicker\n ? {\n value: field.value,\n onValueChange: field.onChange,\n onBlur: field.onBlur,\n ref: field.ref,\n }\n : isPhone\n ? {\n ...field,\n onCountryChange: (country: Country | undefined) => {\n setValue(`${name}Country` as FieldPath<TFieldValues>, country as any);\n },\n }\n : field;\n\n const isUploadFile = child.type === UploadFile;\n\n return cloneElement(child, {\n ...childProps,\n ...fieldProps,\n error: fieldState.error?.message || (fieldState.error ? 'Invalid' : undefined),\n name: undefined, // Remove name to avoid passing it to the underlying input\n ...(isUploadFile ? { isLoading: isSubmitting } : {}),\n });\n }}\n />\n );\n }\n\n // Handle cancel buttons - wire up form.reset() + onCancel callback\n if (childProps['data-cancel'] && onCancel && reset) {\n return cloneElement(child, {\n ...childProps,\n onClick: () => {\n reset();\n onCancel();\n },\n });\n }\n\n // Handle submit buttons - inject loading state via isLoading prop\n if (childProps.type === 'submit') {\n const isButtonElement =\n child.type === Button || (typeof child.type === 'function' && (child.type as any).displayName === 'Button');\n\n if (isButtonElement) {\n return cloneElement(child, {\n ...childProps,\n isLoading: isSubmitting,\n });\n }\n }\n\n // Handle React Fragments - process their children directly\n if (isFragment) {\n return processChildren(childProps.children, control, isSubmitting, setValue, onCancel, reset);\n }\n\n // Recurse into children for container elements (divs, FieldGroups, etc.)\n if (childProps.children != null) {\n return cloneElement(child, {\n ...childProps,\n children: processChildren(childProps.children, control, isSubmitting, setValue, onCancel, reset),\n });\n }\n\n // Return unchanged if no name prop and no children\n return child;\n });\n}\n\nexport interface FormProps<\n TFieldValues extends FieldValues = FieldValues,\n TContext = any,\n TTransformedValues extends FieldValues | undefined = TFieldValues,\n TMutationData = unknown,\n TMutationError = Error,\n TMutationVariables = any,\n> extends Omit<React.FormHTMLAttributes<HTMLFormElement>, 'onSubmit'> {\n /**\n * The react-hook-form form instance\n */\n form: UseFormReturn<TFieldValues, TContext, TTransformedValues>;\n\n /**\n * Form submit handler - receives the transformed values if transformation is applied.\n * Optional when using `mutation` prop.\n */\n onSubmit?: Parameters<UseFormReturn<TFieldValues, TContext, TTransformedValues>['handleSubmit']>[0];\n\n /**\n * Children elements - automatically wrapped with Controller if they have a name prop\n */\n children: React.ReactNode;\n\n /**\n * Position of the root error display\n * @default 'bottom'\n */\n rootErrorPosition?: 'top' | 'bottom';\n\n /**\n * Additional classes for the root error display\n */\n rootErrorClassName?: string;\n\n /**\n * Action element rendered in the root error Alert (e.g. button or link)\n * Positioned in the top-right corner using AlertAction\n */\n rootErrorAction?: React.ReactNode;\n\n /**\n * Field mapping for automatic API error mapping\n * Maps API field names to form field names\n */\n fieldMapping?: FieldMapping;\n\n /**\n * TanStack Query mutation for automatic handling.\n * When provided, the form will use `mutateAsync` to submit data and handle errors automatically.\n * The mutation's own callbacks (onSuccess, onError, etc.) will fire automatically.\n * Form only adds `mapApiErrorsToForm` as an extra error handling layer.\n * Optional - you can use `onSubmit` instead for forms that don't use mutations.\n */\n mutation?: UseMutationResult<TMutationData, TMutationError, TMutationVariables, unknown>;\n\n /**\n * Transform form data to mutation variables before submission.\n * Only used when `mutation` prop is provided.\n */\n transformSubmit?: (\n data: TTransformedValues extends undefined ? TFieldValues : TTransformedValues,\n ) => TMutationVariables;\n\n /**\n * Automatically calls form.reset() after a successful mutation.\n * Set to false for \"edit\" forms where resetting clears pre-populated values.\n * @default true\n */\n resetOnSuccess?: boolean;\n\n /**\n * Called when a cancel button (marked with data-cancel) is clicked.\n * Form.reset() is called automatically before invoking this callback.\n */\n onCancel?: () => void;\n}\n\n/**\n * Smart Form component that automatically wraps children with Controller\n *\n * Usage with onSubmit:\n * ```tsx\n * <Form form={form} onSubmit={handleSubmit}>\n * <TextField name=\"email\" label=\"Email\" description=\"Your email address\" />\n * <PasswordField name=\"password\" label=\"Password\" />\n * <Button type=\"submit\">Submit</Button>\n * </Form>\n * ```\n *\n * Usage with TanStack Query mutation:\n * ```tsx\n * const mutation = useMutation({\n * mutationFn: (data) => api.post('/login', data),\n * onSuccess: (data) => console.log('Success!', data),\n * onError: (error) => console.error('Error!', error),\n * });\n *\n * <Form\n * form={form}\n * mutation={mutation}\n * transformSubmit={(data) => ({ ...data, timestamp: Date.now() })}\n * >\n * <TextField name=\"email\" label=\"Email\" />\n * <Button type=\"submit\">Submit</Button>\n * </Form>\n * ```\n */\nexport function Form<\n TFieldValues extends FieldValues = FieldValues,\n TContext = any,\n TTransformedValues extends FieldValues | undefined = TFieldValues,\n TMutationData = unknown,\n TMutationError = Error,\n TMutationVariables = any,\n>({\n form,\n onSubmit,\n children,\n rootErrorPosition = 'bottom',\n rootErrorClassName,\n rootErrorAction,\n fieldMapping,\n mutation,\n transformSubmit,\n resetOnSuccess,\n onCancel,\n className,\n ...props\n}: FormProps<TFieldValues, TContext, TTransformedValues, TMutationData, TMutationError, TMutationVariables>) {\n // Compute isSubmitting from both form state and mutation state\n const isSubmitting = form.formState.isSubmitting || (mutation?.isPending ?? false);\n\n // Wrap the submit handler with automatic error mapping (always enabled)\n // Form only adds mapApiErrorsToForm - the mutation's own callbacks fire automatically\n const wrappedOnSubmit = useCallback(\n async (data: TTransformedValues extends undefined ? TFieldValues : TTransformedValues) => {\n // Suppress error toasts during form submission — Form handles errors inline\n const interceptorId = axios.interceptors.request.use((config) => ({\n ...config,\n showErrorToast: false,\n }));\n\n try {\n if (mutation) {\n const variables = transformSubmit ? transformSubmit(data) : data;\n // mutateAsync will trigger the mutation's onSuccess/onError callbacks\n await mutation.mutateAsync(variables as TMutationVariables);\n } else if (onSubmit) {\n await onSubmit(data as any);\n }\n\n // Reset form after successful submission (default: true)\n if (resetOnSuccess !== false) form.reset();\n } catch (error) {\n // Form's only job: map API errors to form fields\n // mapApiErrorsToForm handles axios error structure extraction internally\n mapApiErrorsToForm(error, form as any, {\n fieldMapping,\n });\n // Log error for debugging\n console.error('[Form Submission Error]', error);\n // Error is swallowed, not re-thrown (mutation's onError already fired)\n } finally {\n axios.interceptors.request.eject(interceptorId);\n }\n },\n [onSubmit, mutation, transformSubmit, fieldMapping, form, resetOnSuccess],\n );\n\n const handleSubmit = form.handleSubmit(wrappedOnSubmit as any);\n\n // Process children recursively to automatically wrap with Controller\n const processedChildren = processChildren(children, form.control, isSubmitting, form.setValue, onCancel, form.reset);\n\n const childArray = Children.toArray(processedChildren);\n const actionsIndex = childArray.findIndex(\n (child) => isValidElement(child) && (child.type as { displayName?: string })?.displayName === 'DialogActions',\n );\n const hasActions = actionsIndex !== -1;\n const bodyChildren = hasActions ? childArray.filter((_, index) => index !== actionsIndex) : processedChildren;\n const actions = hasActions ? childArray[actionsIndex] : null;\n\n const topError =\n rootErrorPosition === 'top' && form.formState.errors.root ? (\n <Alert\n variant=\"destructive\"\n title={form.formState.errors.root.type || 'Error'}\n description={form.formState.errors.root.message}\n action={rootErrorAction}\n className={cn('mb-4', rootErrorClassName)}\n />\n ) : null;\n const bottomError =\n rootErrorPosition === 'bottom' && form.formState.errors.root ? (\n <Alert\n variant=\"destructive\"\n title={form.formState.errors.root.type || 'Error'}\n description={form.formState.errors.root.message}\n action={rootErrorAction}\n className={cn('mt-4', rootErrorClassName)}\n />\n ) : null;\n\n return (\n <FormProvider {...form}>\n <form\n onSubmit={handleSubmit}\n className={cn(hasActions ? 'flex min-h-0 flex-1 flex-col' : 'space-y-4', className)}\n {...props}\n >\n {hasActions ? (\n <>\n <div className=\"min-h-0 flex-1 space-y-4 overflow-y-auto overscroll-contain px-6 py-4 [scrollbar-gutter:stable]\">\n {topError}\n {bodyChildren}\n {bottomError}\n </div>\n {actions}\n </>\n ) : (\n <>\n {topError}\n {processedChildren}\n {bottomError}\n </>\n )}\n </form>\n </FormProvider>\n );\n}\n\nForm.displayName = 'Form';\n"],"names":["Fragment"],"mappings":"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"}
|
package/dist/Progress.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { jsx } from 'react/jsx-runtime';
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
import { forwardRef } from 'react';
|
|
4
|
-
import { c as createContextScope } from './
|
|
5
|
-
import { P as Primitive } from './
|
|
4
|
+
import { c as createContextScope } from './index34.js';
|
|
5
|
+
import { P as Primitive } from './index30.js';
|
|
6
6
|
import { c as cn } from './utils.js';
|
|
7
7
|
|
|
8
8
|
var PROGRESS_NAME = "Progress";
|
package/dist/RadioGroup.js
CHANGED
|
@@ -8,8 +8,8 @@ import { u as useComposedRefs } from './index11.js';
|
|
|
8
8
|
import { c as createContextScope } from './index19.js';
|
|
9
9
|
import { R as Root, c as createRovingFocusGroupScope, I as Item } from './index20.js';
|
|
10
10
|
import { u as useDirection } from './index22.js';
|
|
11
|
-
import { u as useSize } from './
|
|
12
|
-
import { u as usePrevious } from './
|
|
11
|
+
import { u as useSize } from './index36.js';
|
|
12
|
+
import { u as usePrevious } from './index35.js';
|
|
13
13
|
import { P as Presence } from './index21.js';
|
|
14
14
|
|
|
15
15
|
var RADIO_NAME = "Radio";
|
package/dist/Sidebar.js
CHANGED
|
@@ -6,7 +6,7 @@ import { forwardRef, useState, useCallback, useEffect, useMemo, useRef, createCo
|
|
|
6
6
|
import { u as useIsMobile } from './useIsMobile.js';
|
|
7
7
|
import { c as cn } from './utils.js';
|
|
8
8
|
import { T as TooltipProvider, a as Tooltip, b as TooltipTrigger, c as TooltipContent } from './tooltip.js';
|
|
9
|
-
import { R as Root, P as Portal, C as Content, a as Close, b as Title, D as Description, O as Overlay } from './
|
|
9
|
+
import { R as Root, P as Portal, C as Content, a as Close, b as Title, D as Description, O as Overlay } from './index31.js';
|
|
10
10
|
import { X } from './x.js';
|
|
11
11
|
import { D as DropdownMenu, a as DropdownMenuTrigger, b as DropdownMenuContent, e as DropdownMenuLabel, c as DropdownMenuItem } from './dropdown-menu.js';
|
|
12
12
|
import { c as createLucideIcon } from './createLucideIcon.js';
|
package/dist/Switch.js
CHANGED
|
@@ -5,8 +5,8 @@ import { F as Field, e as FieldLabel, c as FieldError } from './field.js';
|
|
|
5
5
|
import { u as useControllableState, P as Primitive, c as composeEventHandlers } from './index18.js';
|
|
6
6
|
import { u as useComposedRefs } from './index11.js';
|
|
7
7
|
import { c as createContextScope } from './index19.js';
|
|
8
|
-
import { u as usePrevious } from './
|
|
9
|
-
import { u as useSize } from './
|
|
8
|
+
import { u as usePrevious } from './index35.js';
|
|
9
|
+
import { u as useSize } from './index36.js';
|
|
10
10
|
import { c as cn } from './utils.js';
|
|
11
11
|
|
|
12
12
|
var SWITCH_NAME = "Switch";
|
package/dist/TabsSkeleton.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
2
|
import { C as Content, L as List, T as Trigger, R as Root2 } from './index17.js';
|
|
3
|
-
import {
|
|
3
|
+
import { useState, useId } from 'react';
|
|
4
|
+
import { useParams, useNavigate, useLocation } from 'react-router-dom';
|
|
4
5
|
import { c as cn } from './utils.js';
|
|
5
|
-
import { L as LayoutGroup } from './
|
|
6
|
+
import { L as LayoutGroup } from './index38.js';
|
|
6
7
|
import { m as motion, A as AnimatePresence } from './proxy.js';
|
|
7
8
|
import { S as Skeleton } from './Skeleton.js';
|
|
8
9
|
|
|
@@ -56,27 +57,57 @@ function TabsContent$1({ className, ...props }) {
|
|
|
56
57
|
return /* @__PURE__ */ jsx(Content, { "data-slot": "tabs-content", className: cn("flex-1 outline-none", className), ...props });
|
|
57
58
|
}
|
|
58
59
|
|
|
59
|
-
function Tabs({
|
|
60
|
+
function Tabs(props) {
|
|
61
|
+
if (props.routeParam) return /* @__PURE__ */ jsx(RoutedTabs, { ...props, routeParam: props.routeParam });
|
|
62
|
+
return /* @__PURE__ */ jsx(StatefulTabs, { ...props });
|
|
63
|
+
}
|
|
64
|
+
Tabs.displayName = "Tabs";
|
|
65
|
+
function StatefulTabs({ routeParam: _routeParam, defaultValue, value, onValueChange, tabs, ...rest }) {
|
|
66
|
+
const [activeTab, setActiveTab] = useState(value ?? defaultValue ?? tabs[0]?.value);
|
|
67
|
+
function handleValueChange(newValue) {
|
|
68
|
+
setActiveTab(newValue);
|
|
69
|
+
onValueChange?.(newValue);
|
|
70
|
+
}
|
|
71
|
+
return /* @__PURE__ */ jsx(TabsView, { value: value ?? activeTab, onValueChange: handleValueChange, tabs, ...rest });
|
|
72
|
+
}
|
|
73
|
+
function RoutedTabs({ routeParam, defaultValue, onValueChange, tabs, ...rest }) {
|
|
74
|
+
const params = useParams();
|
|
75
|
+
const navigate = useNavigate();
|
|
76
|
+
const { pathname } = useLocation();
|
|
77
|
+
const fallback = defaultValue ?? tabs[0]?.value ?? "";
|
|
78
|
+
const current = params[routeParam] ?? fallback;
|
|
79
|
+
function handleValueChange(newValue) {
|
|
80
|
+
const existing = params[routeParam];
|
|
81
|
+
if (existing) {
|
|
82
|
+
const segments = pathname.split("/");
|
|
83
|
+
const index = segments.lastIndexOf(existing);
|
|
84
|
+
if (index >= 0) {
|
|
85
|
+
segments[index] = newValue;
|
|
86
|
+
navigate(segments.join("/"));
|
|
87
|
+
} else {
|
|
88
|
+
navigate(`${pathname.replace(/\/+$/, "")}/${newValue}`);
|
|
89
|
+
}
|
|
90
|
+
} else {
|
|
91
|
+
navigate(`${pathname.replace(/\/+$/, "")}/${newValue}`);
|
|
92
|
+
}
|
|
93
|
+
onValueChange?.(newValue);
|
|
94
|
+
}
|
|
95
|
+
return /* @__PURE__ */ jsx(TabsView, { value: current, onValueChange: handleValueChange, tabs, ...rest });
|
|
96
|
+
}
|
|
97
|
+
function TabsView({
|
|
98
|
+
value,
|
|
99
|
+
onValueChange,
|
|
60
100
|
tabs,
|
|
61
101
|
listClassName,
|
|
62
102
|
contentClassName,
|
|
63
103
|
disabled,
|
|
64
104
|
mountStrategy = "active",
|
|
65
105
|
animated = true,
|
|
66
|
-
defaultValue,
|
|
67
|
-
value,
|
|
68
|
-
onValueChange,
|
|
69
106
|
...props
|
|
70
107
|
}) {
|
|
71
108
|
const layoutId = useId();
|
|
72
|
-
const [activeTab, setActiveTab] = useState(value ?? defaultValue ?? tabs[0]?.value);
|
|
73
|
-
function handleValueChange(newValue) {
|
|
74
|
-
setActiveTab(newValue);
|
|
75
|
-
onValueChange?.(newValue);
|
|
76
|
-
}
|
|
77
|
-
const controlledValue = value ?? activeTab;
|
|
78
109
|
if (!animated) {
|
|
79
|
-
return /* @__PURE__ */ jsxs(Tabs$1, { value
|
|
110
|
+
return /* @__PURE__ */ jsxs(Tabs$1, { value, onValueChange, ...props, children: [
|
|
80
111
|
/* @__PURE__ */ jsx(TabsList$1, { className: listClassName, children: tabs.map((tab) => /* @__PURE__ */ jsx(
|
|
81
112
|
TabsTrigger$1,
|
|
82
113
|
{
|
|
@@ -99,8 +130,8 @@ function Tabs({
|
|
|
99
130
|
))
|
|
100
131
|
] });
|
|
101
132
|
}
|
|
102
|
-
const activeTabItem = tabs.find((t) => t.value ===
|
|
103
|
-
return /* @__PURE__ */ jsxs(Tabs$1, { value
|
|
133
|
+
const activeTabItem = tabs.find((t) => t.value === value);
|
|
134
|
+
return /* @__PURE__ */ jsxs(Tabs$1, { value, onValueChange, ...props, children: [
|
|
104
135
|
/* @__PURE__ */ jsx(LayoutGroup, { id: layoutId, children: /* @__PURE__ */ jsx(TabsList$1, { className: listClassName, children: tabs.map((tab) => /* @__PURE__ */ jsxs(
|
|
105
136
|
Trigger,
|
|
106
137
|
{
|
|
@@ -119,16 +150,12 @@ function Tabs({
|
|
|
119
150
|
tab.className
|
|
120
151
|
),
|
|
121
152
|
children: [
|
|
122
|
-
|
|
153
|
+
value === tab.value && /* @__PURE__ */ jsx(
|
|
123
154
|
motion.span,
|
|
124
155
|
{
|
|
125
156
|
layoutId: "tab-pill",
|
|
126
157
|
className: "absolute inset-0 rounded-md bg-background shadow-sm",
|
|
127
|
-
transition: {
|
|
128
|
-
type: "spring",
|
|
129
|
-
visualDuration: 0.3,
|
|
130
|
-
bounce: 0.05
|
|
131
|
-
}
|
|
158
|
+
transition: { type: "spring", visualDuration: 0.3, bounce: 0.05 }
|
|
132
159
|
}
|
|
133
160
|
),
|
|
134
161
|
/* @__PURE__ */ jsx("span", { className: "relative z-10", children: tab.label })
|
|
@@ -150,7 +177,6 @@ function Tabs({
|
|
|
150
177
|
) })
|
|
151
178
|
] });
|
|
152
179
|
}
|
|
153
|
-
Tabs.displayName = "Tabs";
|
|
154
180
|
const TabsList = TabsList$1;
|
|
155
181
|
const TabsContent = TabsContent$1;
|
|
156
182
|
const TabsTrigger = TabsTrigger$1;
|
package/dist/TabsSkeleton.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TabsSkeleton.js","sources":["../shadcn/shadcnTabs/tabs.tsx","../lib/components/Tabs/Tabs.tsx","../lib/components/Tabs/TabsSkeleton.tsx"],"sourcesContent":["import * as TabsPrimitive from '@radix-ui/react-tabs';\nimport type * as React from 'react';\nimport { cn } from '../utils';\n\n// Tabs root component wrapping Radix Tabs primitive\nfunction Tabs({ className, ...props }: React.ComponentPropsWithoutRef<typeof TabsPrimitive.Root>) {\n return <TabsPrimitive.Root data-slot=\"tabs\" className={cn('flex flex-col gap-2', className)} {...props} />;\n}\n\n// Container for tab trigger buttons\nfunction TabsList({ className, ...props }: React.ComponentPropsWithoutRef<typeof TabsPrimitive.List>) {\n return (\n <TabsPrimitive.List\n data-slot=\"tabs-list\"\n className={cn(\n 'bg-muted text-muted-foreground inline-flex h-9 w-fit items-center justify-center rounded-lg p-[3px]',\n className,\n )}\n {...props}\n />\n );\n}\n\n// Individual tab trigger button\nfunction TabsTrigger({ className, ...props }: React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>) {\n return (\n <TabsPrimitive.Trigger\n data-slot=\"tabs-trigger\"\n className={cn(\n // layout\n 'inline-flex items-center justify-center gap-1.5',\n // sizing & spacing\n 'rounded-md border border-transparent px-3 py-1',\n // typography\n 'text-sm font-medium whitespace-nowrap',\n // colors\n 'text-muted-foreground dark:text-muted-foreground',\n // active state\n 'data-[state=active]:bg-background data-[state=active]:text-foreground dark:data-[state=active]:text-foreground data-[state=active]:shadow-sm',\n // transitions\n 'transition-all',\n // focus\n 'focus-visible:outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50',\n // disabled\n 'disabled:pointer-events-none disabled:opacity-50',\n // svg children\n \"[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n className,\n )}\n {...props}\n />\n );\n}\n\n// Tab panel content shown when its trigger is active\nfunction TabsContent({ className, ...props }: React.ComponentPropsWithoutRef<typeof TabsPrimitive.Content>) {\n return <TabsPrimitive.Content data-slot=\"tabs-content\" className={cn('flex-1 outline-none', className)} {...props} />;\n}\n\nexport { Tabs, TabsList, TabsTrigger, TabsContent };\n","import * as TabsPrimitive from '@radix-ui/react-tabs';\nimport { AnimatePresence, LayoutGroup, motion } from 'motion/react';\nimport type React from 'react';\nimport { useId, useState } from 'react';\nimport {\n Tabs as ShadcnTabs,\n TabsContent as ShadcnTabsContent,\n TabsList as ShadcnTabsList,\n TabsTrigger as ShadcnTabsTrigger,\n} from '../../../shadcn/shadcnTabs';\nimport { cn } from '../../../shadcn/utils';\n\nexport interface TabItem {\n value: string;\n label: React.ReactNode;\n content: React.ReactNode;\n disabled?: boolean;\n className?: string;\n contentClassName?: string;\n}\n\nexport interface TabsProps extends React.ComponentPropsWithoutRef<typeof TabsPrimitive.Root> {\n tabs: TabItem[];\n listClassName?: string;\n contentClassName?: string;\n disabled?: boolean;\n mountStrategy?: 'active' | 'all';\n animated?: boolean;\n}\n\n// Tabs root — renders list and content panels from the tabs array\nexport function Tabs({\n tabs,\n listClassName,\n contentClassName,\n disabled,\n mountStrategy = 'active',\n animated = true,\n defaultValue,\n value,\n onValueChange,\n ...props\n}: TabsProps) {\n const layoutId = useId();\n const [activeTab, setActiveTab] = useState(value ?? defaultValue ?? tabs[0]?.value);\n\n function handleValueChange(newValue: string) {\n setActiveTab(newValue);\n onValueChange?.(newValue);\n }\n\n const controlledValue = value ?? activeTab;\n\n if (!animated) {\n return (\n <ShadcnTabs value={controlledValue} onValueChange={handleValueChange} {...props}>\n <ShadcnTabsList className={listClassName}>\n {tabs.map((tab) => (\n <ShadcnTabsTrigger\n key={tab.value}\n value={tab.value}\n disabled={disabled || tab.disabled}\n className={tab.className}\n >\n {tab.label}\n </ShadcnTabsTrigger>\n ))}\n </ShadcnTabsList>\n {tabs.map((tab) => (\n <ShadcnTabsContent\n key={tab.value}\n value={tab.value}\n forceMount={mountStrategy === 'all' ? true : undefined}\n className={cn(contentClassName, tab.contentClassName)}\n >\n {tab.content}\n </ShadcnTabsContent>\n ))}\n </ShadcnTabs>\n );\n }\n\n const activeTabItem = tabs.find((t) => t.value === controlledValue);\n\n return (\n <ShadcnTabs value={controlledValue} onValueChange={handleValueChange} {...props}>\n <LayoutGroup id={layoutId}>\n <ShadcnTabsList className={listClassName}>\n {tabs.map((tab) => (\n <TabsPrimitive.Trigger\n key={tab.value}\n value={tab.value}\n disabled={disabled || tab.disabled}\n className={cn(\n 'relative inline-flex items-center justify-center gap-1.5',\n 'rounded-md px-3 py-1',\n 'text-sm font-medium whitespace-nowrap',\n 'text-muted-foreground',\n 'data-[state=active]:text-foreground',\n 'transition-colors duration-150',\n 'focus-visible:outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50',\n 'disabled:pointer-events-none disabled:opacity-50',\n \"[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n tab.className,\n )}\n >\n {controlledValue === tab.value && (\n <motion.span\n layoutId=\"tab-pill\"\n className=\"absolute inset-0 rounded-md bg-background shadow-sm\"\n transition={{\n type: 'spring',\n visualDuration: 0.3,\n bounce: 0.05,\n }}\n />\n )}\n <span className=\"relative z-10\">{tab.label}</span>\n </TabsPrimitive.Trigger>\n ))}\n </ShadcnTabsList>\n </LayoutGroup>\n <AnimatePresence mode=\"wait\" initial={false}>\n {activeTabItem && (\n <motion.div\n key={activeTabItem.value}\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={{ opacity: 0 }}\n transition={{ duration: 0.15, ease: 'easeOut' }}\n className={cn('flex-1 outline-none', contentClassName, activeTabItem.contentClassName)}\n >\n {activeTabItem.content}\n </motion.div>\n )}\n </AnimatePresence>\n </ShadcnTabs>\n );\n}\n\nTabs.displayName = 'Tabs';\n\nexport const TabsList = ShadcnTabsList;\nexport const TabsContent = ShadcnTabsContent;\nexport const TabsTrigger = ShadcnTabsTrigger;\n","import type * as React from 'react';\nimport { cn } from '../../../shadcn/utils';\nimport { Skeleton } from '../Skeleton';\n\nconst DEFAULT_TAB_WIDTHS = ['w-20', 'w-14', 'w-16', 'w-24', 'w-18'];\n\nexport interface TabsSkeletonProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Number of tab triggers to render */\n count?: number;\n /** Height of the content area below the tabs */\n contentHeight?: string;\n /** Custom widths for each tab trigger (Tailwind width classes) */\n tabWidths?: string[];\n}\n\nexport const TabsSkeleton = ({\n count = 3,\n contentHeight = '500px',\n tabWidths,\n className,\n ...props\n}: TabsSkeletonProps) => {\n const widths = tabWidths ?? DEFAULT_TAB_WIDTHS;\n\n return (\n <div className={cn('flex flex-col gap-2', className)} {...props}>\n <div className=\"inline-flex h-9 w-fit items-center gap-0.5 rounded-lg bg-muted p-[3px]\">\n {Array.from({ length: count }, (_, i) => (\n <Skeleton\n // biome-ignore lint/suspicious/noArrayIndexKey: <static list of skeletons, not dynamic>\n key={i}\n className={cn('h-7 rounded-md', widths[i % widths.length], i === 0 && 'bg-background')}\n />\n ))}\n </div>\n <Skeleton className=\"w-full rounded-lg\" style={{ height: contentHeight }} />\n </div>\n );\n};\n\nTabsSkeleton.displayName = 'TabsSkeleton';\n"],"names":["Tabs","TabsPrimitive.Root","TabsList","TabsPrimitive.List","TabsTrigger","TabsPrimitive.Trigger","TabsContent","TabsPrimitive.Content","ShadcnTabs","ShadcnTabsList","ShadcnTabsTrigger","ShadcnTabsContent"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"TabsSkeleton.js","sources":["../shadcn/shadcnTabs/tabs.tsx","../lib/components/Tabs/Tabs.tsx","../lib/components/Tabs/TabsSkeleton.tsx"],"sourcesContent":["import * as TabsPrimitive from '@radix-ui/react-tabs';\nimport type * as React from 'react';\nimport { cn } from '../utils';\n\n// Tabs root component wrapping Radix Tabs primitive\nfunction Tabs({ className, ...props }: React.ComponentPropsWithoutRef<typeof TabsPrimitive.Root>) {\n return <TabsPrimitive.Root data-slot=\"tabs\" className={cn('flex flex-col gap-2', className)} {...props} />;\n}\n\n// Container for tab trigger buttons\nfunction TabsList({ className, ...props }: React.ComponentPropsWithoutRef<typeof TabsPrimitive.List>) {\n return (\n <TabsPrimitive.List\n data-slot=\"tabs-list\"\n className={cn(\n 'bg-muted text-muted-foreground inline-flex h-9 w-fit items-center justify-center rounded-lg p-[3px]',\n className,\n )}\n {...props}\n />\n );\n}\n\n// Individual tab trigger button\nfunction TabsTrigger({ className, ...props }: React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>) {\n return (\n <TabsPrimitive.Trigger\n data-slot=\"tabs-trigger\"\n className={cn(\n // layout\n 'inline-flex items-center justify-center gap-1.5',\n // sizing & spacing\n 'rounded-md border border-transparent px-3 py-1',\n // typography\n 'text-sm font-medium whitespace-nowrap',\n // colors\n 'text-muted-foreground dark:text-muted-foreground',\n // active state\n 'data-[state=active]:bg-background data-[state=active]:text-foreground dark:data-[state=active]:text-foreground data-[state=active]:shadow-sm',\n // transitions\n 'transition-all',\n // focus\n 'focus-visible:outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50',\n // disabled\n 'disabled:pointer-events-none disabled:opacity-50',\n // svg children\n \"[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n className,\n )}\n {...props}\n />\n );\n}\n\n// Tab panel content shown when its trigger is active\nfunction TabsContent({ className, ...props }: React.ComponentPropsWithoutRef<typeof TabsPrimitive.Content>) {\n return <TabsPrimitive.Content data-slot=\"tabs-content\" className={cn('flex-1 outline-none', className)} {...props} />;\n}\n\nexport { Tabs, TabsList, TabsTrigger, TabsContent };\n","import * as TabsPrimitive from '@radix-ui/react-tabs';\nimport { AnimatePresence, LayoutGroup, motion } from 'motion/react';\nimport type React from 'react';\nimport { useId, useState } from 'react';\nimport { useLocation, useNavigate, useParams } from 'react-router-dom';\nimport {\n Tabs as ShadcnTabs,\n TabsContent as ShadcnTabsContent,\n TabsList as ShadcnTabsList,\n TabsTrigger as ShadcnTabsTrigger,\n} from '../../../shadcn/shadcnTabs';\nimport { cn } from '../../../shadcn/utils';\n\nexport interface TabItem {\n value: string;\n label: React.ReactNode;\n content: React.ReactNode;\n disabled?: boolean;\n className?: string;\n contentClassName?: string;\n}\n\nexport interface TabsProps extends React.ComponentPropsWithoutRef<typeof TabsPrimitive.Root> {\n tabs: TabItem[];\n listClassName?: string;\n contentClassName?: string;\n disabled?: boolean;\n mountStrategy?: 'active' | 'all';\n animated?: boolean;\n // When set, the active tab is bound to this URL path param (e.g. \"versionTab\").\n // The route must include that segment; switching tabs navigates to update it,\n // so the selection is deep-linkable and survives refresh.\n routeParam?: string;\n}\n\ninterface TabsViewProps extends Omit<TabsProps, 'routeParam' | 'defaultValue' | 'value' | 'onValueChange'> {\n value: string;\n onValueChange: (value: string) => void;\n}\n\n// Tabs root — URL-path-bound when routeParam is set, otherwise internal/controlled state\nexport function Tabs(props: TabsProps) {\n if (props.routeParam) return <RoutedTabs {...props} routeParam={props.routeParam} />;\n return <StatefulTabs {...props} />;\n}\n\nTabs.displayName = 'Tabs';\n\n// Internal-state mode — preserves the original uncontrolled/`value`-controlled behavior\nfunction StatefulTabs({ routeParam: _routeParam, defaultValue, value, onValueChange, tabs, ...rest }: TabsProps) {\n const [activeTab, setActiveTab] = useState(value ?? defaultValue ?? tabs[0]?.value);\n\n function handleValueChange(newValue: string) {\n setActiveTab(newValue);\n onValueChange?.(newValue);\n }\n\n return <TabsView value={(value ?? activeTab) as string} onValueChange={handleValueChange} tabs={tabs} {...rest} />;\n}\n\n// URL-path mode — the active tab is read from / written to a route path param\nfunction RoutedTabs({ routeParam, defaultValue, onValueChange, tabs, ...rest }: TabsProps & { routeParam: string }) {\n const params = useParams();\n const navigate = useNavigate();\n const { pathname } = useLocation();\n\n const fallback = ((defaultValue as string) ?? tabs[0]?.value) ?? '';\n const current = params[routeParam] ?? fallback;\n\n function handleValueChange(newValue: string) {\n const existing = params[routeParam];\n if (existing) {\n const segments = pathname.split('/');\n const index = segments.lastIndexOf(existing);\n if (index >= 0) {\n segments[index] = newValue;\n navigate(segments.join('/'));\n } else {\n navigate(`${pathname.replace(/\\/+$/, '')}/${newValue}`);\n }\n } else {\n navigate(`${pathname.replace(/\\/+$/, '')}/${newValue}`);\n }\n onValueChange?.(newValue);\n }\n\n return <TabsView value={current} onValueChange={handleValueChange} tabs={tabs} {...rest} />;\n}\n\n// Presentational tabs — fully controlled by value + onValueChange\nfunction TabsView({\n value,\n onValueChange,\n tabs,\n listClassName,\n contentClassName,\n disabled,\n mountStrategy = 'active',\n animated = true,\n ...props\n}: TabsViewProps) {\n const layoutId = useId();\n\n if (!animated) {\n return (\n <ShadcnTabs value={value} onValueChange={onValueChange} {...props}>\n <ShadcnTabsList className={listClassName}>\n {tabs.map((tab) => (\n <ShadcnTabsTrigger\n key={tab.value}\n value={tab.value}\n disabled={disabled || tab.disabled}\n className={tab.className}\n >\n {tab.label}\n </ShadcnTabsTrigger>\n ))}\n </ShadcnTabsList>\n {tabs.map((tab) => (\n <ShadcnTabsContent\n key={tab.value}\n value={tab.value}\n forceMount={mountStrategy === 'all' ? true : undefined}\n className={cn(contentClassName, tab.contentClassName)}\n >\n {tab.content}\n </ShadcnTabsContent>\n ))}\n </ShadcnTabs>\n );\n }\n\n const activeTabItem = tabs.find((t) => t.value === value);\n\n return (\n <ShadcnTabs value={value} onValueChange={onValueChange} {...props}>\n <LayoutGroup id={layoutId}>\n <ShadcnTabsList className={listClassName}>\n {tabs.map((tab) => (\n <TabsPrimitive.Trigger\n key={tab.value}\n value={tab.value}\n disabled={disabled || tab.disabled}\n className={cn(\n 'relative inline-flex items-center justify-center gap-1.5',\n 'rounded-md px-3 py-1',\n 'text-sm font-medium whitespace-nowrap',\n 'text-muted-foreground',\n 'data-[state=active]:text-foreground',\n 'transition-colors duration-150',\n 'focus-visible:outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50',\n 'disabled:pointer-events-none disabled:opacity-50',\n \"[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n tab.className,\n )}\n >\n {value === tab.value && (\n <motion.span\n layoutId=\"tab-pill\"\n className=\"absolute inset-0 rounded-md bg-background shadow-sm\"\n transition={{ type: 'spring', visualDuration: 0.3, bounce: 0.05 }}\n />\n )}\n <span className=\"relative z-10\">{tab.label}</span>\n </TabsPrimitive.Trigger>\n ))}\n </ShadcnTabsList>\n </LayoutGroup>\n <AnimatePresence mode=\"wait\" initial={false}>\n {activeTabItem && (\n <motion.div\n key={activeTabItem.value}\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={{ opacity: 0 }}\n transition={{ duration: 0.15, ease: 'easeOut' }}\n className={cn('flex-1 outline-none', contentClassName, activeTabItem.contentClassName)}\n >\n {activeTabItem.content}\n </motion.div>\n )}\n </AnimatePresence>\n </ShadcnTabs>\n );\n}\n\nexport const TabsList = ShadcnTabsList;\nexport const TabsContent = ShadcnTabsContent;\nexport const TabsTrigger = ShadcnTabsTrigger;\n","import type * as React from 'react';\nimport { cn } from '../../../shadcn/utils';\nimport { Skeleton } from '../Skeleton';\n\nconst DEFAULT_TAB_WIDTHS = ['w-20', 'w-14', 'w-16', 'w-24', 'w-18'];\n\nexport interface TabsSkeletonProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Number of tab triggers to render */\n count?: number;\n /** Height of the content area below the tabs */\n contentHeight?: string;\n /** Custom widths for each tab trigger (Tailwind width classes) */\n tabWidths?: string[];\n}\n\nexport const TabsSkeleton = ({\n count = 3,\n contentHeight = '500px',\n tabWidths,\n className,\n ...props\n}: TabsSkeletonProps) => {\n const widths = tabWidths ?? DEFAULT_TAB_WIDTHS;\n\n return (\n <div className={cn('flex flex-col gap-2', className)} {...props}>\n <div className=\"inline-flex h-9 w-fit items-center gap-0.5 rounded-lg bg-muted p-[3px]\">\n {Array.from({ length: count }, (_, i) => (\n <Skeleton\n // biome-ignore lint/suspicious/noArrayIndexKey: <static list of skeletons, not dynamic>\n key={i}\n className={cn('h-7 rounded-md', widths[i % widths.length], i === 0 && 'bg-background')}\n />\n ))}\n </div>\n <Skeleton className=\"w-full rounded-lg\" style={{ height: contentHeight }} />\n </div>\n );\n};\n\nTabsSkeleton.displayName = 'TabsSkeleton';\n"],"names":["Tabs","TabsPrimitive.Root","TabsList","TabsPrimitive.List","TabsTrigger","TabsPrimitive.Trigger","TabsContent","TabsPrimitive.Content","ShadcnTabs","ShadcnTabsList","ShadcnTabsTrigger","ShadcnTabsContent"],"mappings":"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"}
|
package/dist/Toggle.js
CHANGED
|
@@ -1552,6 +1552,10 @@ select:-webkit-autofill:active {
|
|
|
1552
1552
|
margin-inline: calc(var(--spacing) * -1);
|
|
1553
1553
|
}
|
|
1554
1554
|
|
|
1555
|
+
.-mx-6 {
|
|
1556
|
+
margin-inline: calc(var(--spacing) * -6);
|
|
1557
|
+
}
|
|
1558
|
+
|
|
1555
1559
|
.mx-0 {
|
|
1556
1560
|
margin-inline: calc(var(--spacing) * 0);
|
|
1557
1561
|
}
|
|
@@ -1972,14 +1976,14 @@ select:-webkit-autofill:active {
|
|
|
1972
1976
|
max-height: calc(var(--spacing) * 60);
|
|
1973
1977
|
}
|
|
1974
1978
|
|
|
1975
|
-
.max-h-64 {
|
|
1976
|
-
max-height: calc(var(--spacing) * 64);
|
|
1977
|
-
}
|
|
1978
|
-
|
|
1979
1979
|
.max-h-80 {
|
|
1980
1980
|
max-height: calc(var(--spacing) * 80);
|
|
1981
1981
|
}
|
|
1982
1982
|
|
|
1983
|
+
.max-h-\[95vh\] {
|
|
1984
|
+
max-height: 95vh;
|
|
1985
|
+
}
|
|
1986
|
+
|
|
1983
1987
|
.max-h-\[300px\] {
|
|
1984
1988
|
max-height: 300px;
|
|
1985
1989
|
}
|
|
@@ -2004,6 +2008,10 @@ select:-webkit-autofill:active {
|
|
|
2004
2008
|
min-height: calc(var(--spacing) * 16);
|
|
2005
2009
|
}
|
|
2006
2010
|
|
|
2011
|
+
.min-h-32 {
|
|
2012
|
+
min-height: calc(var(--spacing) * 32);
|
|
2013
|
+
}
|
|
2014
|
+
|
|
2007
2015
|
.min-h-72 {
|
|
2008
2016
|
min-height: calc(var(--spacing) * 72);
|
|
2009
2017
|
}
|
|
@@ -2666,6 +2674,10 @@ select:-webkit-autofill:active {
|
|
|
2666
2674
|
justify-content: flex-start;
|
|
2667
2675
|
}
|
|
2668
2676
|
|
|
2677
|
+
.gap-0 {
|
|
2678
|
+
gap: calc(var(--spacing) * 0);
|
|
2679
|
+
}
|
|
2680
|
+
|
|
2669
2681
|
.gap-0\.5 {
|
|
2670
2682
|
gap: calc(var(--spacing) * .5);
|
|
2671
2683
|
}
|
|
@@ -2855,6 +2867,10 @@ select:-webkit-autofill:active {
|
|
|
2855
2867
|
overscroll-behavior: auto;
|
|
2856
2868
|
}
|
|
2857
2869
|
|
|
2870
|
+
.overscroll-contain {
|
|
2871
|
+
overscroll-behavior: contain;
|
|
2872
|
+
}
|
|
2873
|
+
|
|
2858
2874
|
.rounded {
|
|
2859
2875
|
border-radius: .25rem;
|
|
2860
2876
|
}
|
|
@@ -3446,7 +3462,17 @@ select:-webkit-autofill:active {
|
|
|
3446
3462
|
background-color: #0000;
|
|
3447
3463
|
}
|
|
3448
3464
|
|
|
3449
|
-
.bg-warning, .bg-warning\/
|
|
3465
|
+
.bg-warning, .bg-warning\/10 {
|
|
3466
|
+
background-color: var(--warning);
|
|
3467
|
+
}
|
|
3468
|
+
|
|
3469
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
3470
|
+
.bg-warning\/10 {
|
|
3471
|
+
background-color: color-mix(in oklab, var(--warning) 10%, transparent);
|
|
3472
|
+
}
|
|
3473
|
+
}
|
|
3474
|
+
|
|
3475
|
+
.bg-warning\/15 {
|
|
3450
3476
|
background-color: var(--warning);
|
|
3451
3477
|
}
|
|
3452
3478
|
|
|
@@ -3662,6 +3688,10 @@ select:-webkit-autofill:active {
|
|
|
3662
3688
|
padding-top: calc(var(--spacing) * 4);
|
|
3663
3689
|
}
|
|
3664
3690
|
|
|
3691
|
+
.pt-6 {
|
|
3692
|
+
padding-top: calc(var(--spacing) * 6);
|
|
3693
|
+
}
|
|
3694
|
+
|
|
3665
3695
|
.pt-16 {
|
|
3666
3696
|
padding-top: calc(var(--spacing) * 16);
|
|
3667
3697
|
}
|
|
@@ -3706,6 +3736,10 @@ select:-webkit-autofill:active {
|
|
|
3706
3736
|
padding-bottom: calc(var(--spacing) * 4);
|
|
3707
3737
|
}
|
|
3708
3738
|
|
|
3739
|
+
.pb-6 {
|
|
3740
|
+
padding-bottom: calc(var(--spacing) * 6);
|
|
3741
|
+
}
|
|
3742
|
+
|
|
3709
3743
|
.pl-2 {
|
|
3710
3744
|
padding-left: calc(var(--spacing) * 2);
|
|
3711
3745
|
}
|
|
@@ -4366,6 +4400,10 @@ select:-webkit-autofill:active {
|
|
|
4366
4400
|
-moz-appearance: textfield;
|
|
4367
4401
|
}
|
|
4368
4402
|
|
|
4403
|
+
.\[scrollbar-gutter\:stable\] {
|
|
4404
|
+
scrollbar-gutter: stable;
|
|
4405
|
+
}
|
|
4406
|
+
|
|
4369
4407
|
.\[text-decoration\:underline_line-through\] {
|
|
4370
4408
|
text-decoration: underline line-through;
|
|
4371
4409
|
}
|
package/dist/cells.js
CHANGED
|
@@ -21822,53 +21822,55 @@ function ManageViewsDialog({ tableSlug, open, onClose }) {
|
|
|
21822
21822
|
if (!v) onClose();
|
|
21823
21823
|
}
|
|
21824
21824
|
};
|
|
21825
|
-
return /* @__PURE__ */
|
|
21825
|
+
return /* @__PURE__ */ jsxs(
|
|
21826
21826
|
Dialog,
|
|
21827
21827
|
{
|
|
21828
21828
|
handle,
|
|
21829
21829
|
icon: Settings2,
|
|
21830
21830
|
title: "Manage Views",
|
|
21831
21831
|
description: "Share or delete saved views for this table.",
|
|
21832
|
-
|
|
21833
|
-
|
|
21834
|
-
|
|
21835
|
-
|
|
21836
|
-
|
|
21837
|
-
|
|
21838
|
-
|
|
21839
|
-
|
|
21840
|
-
|
|
21841
|
-
|
|
21842
|
-
|
|
21843
|
-
|
|
21844
|
-
|
|
21845
|
-
|
|
21846
|
-
|
|
21847
|
-
|
|
21848
|
-
|
|
21849
|
-
|
|
21850
|
-
|
|
21851
|
-
|
|
21852
|
-
|
|
21853
|
-
|
|
21854
|
-
|
|
21855
|
-
|
|
21856
|
-
|
|
21857
|
-
|
|
21858
|
-
|
|
21859
|
-
|
|
21860
|
-
|
|
21861
|
-
|
|
21862
|
-
|
|
21863
|
-
|
|
21864
|
-
|
|
21865
|
-
|
|
21866
|
-
|
|
21867
|
-
|
|
21868
|
-
|
|
21869
|
-
|
|
21870
|
-
|
|
21871
|
-
|
|
21832
|
+
children: [
|
|
21833
|
+
/* @__PURE__ */ jsxs("div", { className: "flex max-h-80 min-h-32 flex-col gap-1 overflow-y-auto py-1", children: [
|
|
21834
|
+
views.length === 0 && /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground text-center py-4", children: "No saved views yet." }),
|
|
21835
|
+
views.map((view) => /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between rounded-md px-3 py-2 hover:bg-accent/50", children: [
|
|
21836
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm truncate", children: view.name }),
|
|
21837
|
+
view.isOwn && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 shrink-0", children: [
|
|
21838
|
+
/* @__PURE__ */ jsx(
|
|
21839
|
+
Button,
|
|
21840
|
+
{
|
|
21841
|
+
variant: "ghost",
|
|
21842
|
+
size: "icon",
|
|
21843
|
+
className: "size-7 text-muted-foreground hover:text-foreground",
|
|
21844
|
+
title: view.isShared ? "Make private" : "Share with everyone",
|
|
21845
|
+
onClick: () => shareMut.mutate({ id: view.id, isShared: !view.isShared }),
|
|
21846
|
+
disabled: shareMut.isPending,
|
|
21847
|
+
children: view.isShared ? /* @__PURE__ */ jsx(EyeOff, { className: "size-4" }) : /* @__PURE__ */ jsx(Share2, { className: "size-4" })
|
|
21848
|
+
}
|
|
21849
|
+
),
|
|
21850
|
+
/* @__PURE__ */ jsx(
|
|
21851
|
+
Button,
|
|
21852
|
+
{
|
|
21853
|
+
variant: "ghost",
|
|
21854
|
+
size: "icon",
|
|
21855
|
+
className: "size-7 text-destructive hover:text-destructive",
|
|
21856
|
+
onClick: async () => {
|
|
21857
|
+
const confirmed = await confirm({
|
|
21858
|
+
title: `Delete "${view.name}"?`,
|
|
21859
|
+
description: "This view will be permanently removed.",
|
|
21860
|
+
confirmLabel: "Delete",
|
|
21861
|
+
variant: "destructive"
|
|
21862
|
+
});
|
|
21863
|
+
if (confirmed) deleteMut.mutate(view.id);
|
|
21864
|
+
},
|
|
21865
|
+
disabled: deleteMut.isPending,
|
|
21866
|
+
children: /* @__PURE__ */ jsx(Trash2, { className: "size-4" })
|
|
21867
|
+
}
|
|
21868
|
+
)
|
|
21869
|
+
] })
|
|
21870
|
+
] }, view.id))
|
|
21871
|
+
] }),
|
|
21872
|
+
/* @__PURE__ */ jsx("div", { className: "-mx-6 mt-4 flex flex-col-reverse gap-2 border-t px-6 pt-4 sm:flex-row sm:justify-end", children: /* @__PURE__ */ jsx(Button, { variant: "outline", onClick: onClose, children: "Close" }) })
|
|
21873
|
+
]
|
|
21872
21874
|
}
|
|
21873
21875
|
);
|
|
21874
21876
|
}
|
|
@@ -22056,9 +22058,10 @@ function DataTableViewTabs({ slug }) {
|
|
|
22056
22058
|
{
|
|
22057
22059
|
handle: dirtyGuard,
|
|
22058
22060
|
icon: TriangleAlert,
|
|
22061
|
+
iconVariant: "warning",
|
|
22059
22062
|
title: "Unsaved Changes",
|
|
22060
22063
|
description: "This view has unsaved changes. What would you like to do?",
|
|
22061
|
-
|
|
22064
|
+
children: /* @__PURE__ */ jsxs("div", { className: "flex gap-2 justify-end w-full", children: [
|
|
22062
22065
|
/* @__PURE__ */ jsx(
|
|
22063
22066
|
Button,
|
|
22064
22067
|
{
|
|
@@ -22109,7 +22112,7 @@ const densityClasses = {
|
|
|
22109
22112
|
};
|
|
22110
22113
|
const MODE_HEIGHTS = {
|
|
22111
22114
|
page: "calc(100vh - 280px)",
|
|
22112
|
-
tab: "calc(100vh -
|
|
22115
|
+
tab: "calc(100vh - 320px)",
|
|
22113
22116
|
compact: "calc(100vh - 570px)"
|
|
22114
22117
|
};
|
|
22115
22118
|
function buildNoResultsDescription(flags) {
|