@skybin-tech/nebula-ui 0.0.30 → 0.0.31
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/cjs/components/Form/DatePicker.cjs +8 -2
- package/dist/cjs/components/Form/DatePicker.cjs.map +1 -1
- package/dist/cjs/components/Form/DateTimePicker.cjs +202 -0
- package/dist/cjs/components/Form/DateTimePicker.cjs.map +1 -0
- package/dist/cjs/components/Form/PasswordRevealToggle.cjs +21 -0
- package/dist/cjs/components/Form/PasswordRevealToggle.cjs.map +1 -0
- package/dist/cjs/components/Form/TextBox.cjs +29 -14
- package/dist/cjs/components/Form/TextBox.cjs.map +1 -1
- package/dist/cjs/components/Form/TimePicker.cjs +111 -0
- package/dist/cjs/components/Form/TimePicker.cjs.map +1 -0
- package/dist/cjs/components/Form/context.cjs +1 -1
- package/dist/cjs/components/Form/context.cjs.map +1 -1
- package/dist/cjs/components/Form/index.cjs +7 -0
- package/dist/cjs/components/Input/Input.cjs +32 -4
- package/dist/cjs/components/Input/Input.cjs.map +1 -1
- package/dist/cjs/index.cjs +7 -0
- package/dist/components/Form/DatePicker.d.ts.map +1 -1
- package/dist/components/Form/DatePicker.js +9 -3
- package/dist/components/Form/DatePicker.js.map +1 -1
- package/dist/components/Form/DateTimePicker.d.ts +28 -0
- package/dist/components/Form/DateTimePicker.d.ts.map +1 -0
- package/dist/components/Form/DateTimePicker.js +202 -0
- package/dist/components/Form/DateTimePicker.js.map +1 -0
- package/dist/components/Form/PasswordRevealToggle.d.ts +7 -0
- package/dist/components/Form/PasswordRevealToggle.d.ts.map +1 -0
- package/dist/components/Form/PasswordRevealToggle.js +21 -0
- package/dist/components/Form/PasswordRevealToggle.js.map +1 -0
- package/dist/components/Form/TextBox.d.ts +5 -0
- package/dist/components/Form/TextBox.d.ts.map +1 -1
- package/dist/components/Form/TextBox.js +30 -15
- package/dist/components/Form/TextBox.js.map +1 -1
- package/dist/components/Form/TimePicker.d.ts +14 -0
- package/dist/components/Form/TimePicker.d.ts.map +1 -0
- package/dist/components/Form/TimePicker.js +111 -0
- package/dist/components/Form/TimePicker.js.map +1 -0
- package/dist/components/Form/context.d.ts +1 -1
- package/dist/components/Form/context.d.ts.map +1 -1
- package/dist/components/Form/context.js +1 -1
- package/dist/components/Form/context.js.map +1 -1
- package/dist/components/Form/index.d.ts +6 -0
- package/dist/components/Form/index.d.ts.map +1 -1
- package/dist/components/Form/index.js +4 -1
- package/dist/components/Input/Input.d.ts +14 -2
- package/dist/components/Input/Input.d.ts.map +1 -1
- package/dist/components/Input/Input.js +34 -6
- package/dist/components/Input/Input.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/package.json +1 -1
|
@@ -72,7 +72,7 @@ function buildZodSchemaFromRules(type, rules) {
|
|
|
72
72
|
if (rules.required) return finalizeSchema(schema.refine((val) => val === true, { message: typeof rules.required === "string" ? rules.required : "This field is required" }), rules);
|
|
73
73
|
return finalizeSchema(schema.optional(), rules);
|
|
74
74
|
}
|
|
75
|
-
if (type === "date") {
|
|
75
|
+
if (type === "date" || type === "datetime") {
|
|
76
76
|
const schema = zod.z.coerce.date();
|
|
77
77
|
if (!rules.required) return finalizeSchema(schema.optional(), rules);
|
|
78
78
|
return finalizeSchema(schema, rules);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.cjs","names":[],"sources":["../../../../src/components/Form/context.ts"],"sourcesContent":["'use client';\r\n\r\nimport { createContext, useCallback, useRef } from \"react\";\r\nimport type { UseFormReturn, FieldValues } from \"react-hook-form\";\r\nimport { z } from \"zod\";\r\n\r\n/**\r\n * Validation rule types that can be applied to form fields\r\n */\r\nexport interface FieldValidationRules {\r\n /** Field is required */\r\n required?: boolean | string;\r\n /** Minimum length for strings */\r\n minLength?: number | { value: number; message: string };\r\n /** Maximum length for strings */\r\n maxLength?: number | { value: number; message: string };\r\n /** Minimum value for numbers */\r\n min?: number | { value: number; message: string };\r\n /** Maximum value for numbers */\r\n max?: number | { value: number; message: string };\r\n /** Regex pattern for validation */\r\n pattern?: RegExp | { value: RegExp; message: string };\r\n /** Email validation */\r\n email?: boolean | string;\r\n /** URL validation */\r\n url?: boolean | string;\r\n /** Custom validation function */\r\n validate?: (value: unknown) => boolean | string | Promise<boolean | string>;\r\n}\r\n\r\n/**\r\n * Form configuration options\r\n */\r\nexport interface FormConfig {\r\n /** Show validation errors inline */\r\n showInlineErrors?: boolean;\r\n /** Validate on blur */\r\n validateOnBlur?: boolean;\r\n /** Validate on change */\r\n validateOnChange?: boolean;\r\n /** Size of form controls */\r\n size?: \"sm\" | \"md\" | \"lg\";\r\n /** Layout direction */\r\n layout?: \"horizontal\" | \"vertical\" | \"inline\";\r\n /** Label width for horizontal layout */\r\n labelWidth?: string | number;\r\n /** Whether form is disabled */\r\n disabled?: boolean;\r\n /** Colon after label */\r\n colon?: boolean;\r\n}\r\n\r\n/**\r\n * Field registration info\r\n */\r\nexport interface FieldRegistration {\r\n name: string;\r\n type: \"string\" | \"number\" | \"boolean\" | \"date\" | \"array\";\r\n rules: FieldValidationRules;\r\n}\r\n\r\n/**\r\n * Form context value\r\n */\r\nexport interface FormContextValue<TFieldValues extends FieldValues = FieldValues>\r\n extends FormConfig {\r\n form: UseFormReturn<TFieldValues>;\r\n /** Register a field's validation rules */\r\n registerFieldValidation: (field: FieldRegistration) => void;\r\n /** Unregister a field's validation rules */\r\n unregisterFieldValidation: (name: string) => void;\r\n /** Get current validation schema */\r\n getValidationSchema: () => z.ZodObject<Record<string, z.ZodTypeAny>>;\r\n /** Trigger validation for a specific field */\r\n triggerValidation: (name: string) => Promise<boolean>;\r\n}\r\n\r\n/**\r\n * Default form configuration\r\n */\r\nexport const defaultFormConfig: FormConfig = {\r\n showInlineErrors: true,\r\n validateOnBlur: true,\r\n validateOnChange: false,\r\n size: \"md\",\r\n layout: \"vertical\",\r\n disabled: false,\r\n colon: true,\r\n};\r\n\r\n/**\r\n * Form context for sharing form state and configuration\r\n */\r\nexport const FormConfigContext = createContext<FormContextValue | null>(null);\r\n\r\n/**\r\n * Build a Zod schema from validation rules\r\n */\r\nexport function buildZodSchemaFromRules(\r\n type: FieldRegistration[\"type\"],\r\n rules: FieldValidationRules\r\n): z.ZodTypeAny {\r\n // Helper to extract value and message\r\n const getValueAndMessage = <T>(\r\n rule: T | { value: T; message: string } | undefined,\r\n defaultMessage: string\r\n ): { value: T; message: string } | null => {\r\n if (rule === undefined) return null;\r\n if (typeof rule === \"object\" && rule !== null && \"value\" in rule) {\r\n return rule as { value: T; message: string };\r\n }\r\n return { value: rule as T, message: defaultMessage };\r\n };\r\n\r\n // Build string schema\r\n if (type === \"string\") {\r\n let schema = z.string();\r\n\r\n const minLengthRule = getValueAndMessage(\r\n rules.minLength,\r\n `Minimum ${typeof rules.minLength === \"number\" ? rules.minLength : (rules.minLength as { value: number })?.value} characters required`\r\n );\r\n if (minLengthRule) {\r\n schema = schema.min(minLengthRule.value as number, minLengthRule.message);\r\n }\r\n\r\n const maxLengthRule = getValueAndMessage(\r\n rules.maxLength,\r\n `Maximum ${typeof rules.maxLength === \"number\" ? rules.maxLength : (rules.maxLength as { value: number })?.value} characters allowed`\r\n );\r\n if (maxLengthRule) {\r\n schema = schema.max(maxLengthRule.value as number, maxLengthRule.message);\r\n }\r\n\r\n if (rules.pattern !== undefined) {\r\n const patternRule = rules.pattern instanceof RegExp\r\n ? { value: rules.pattern, message: \"Invalid format\" }\r\n : rules.pattern;\r\n schema = schema.regex(patternRule.value, patternRule.message);\r\n }\r\n\r\n if (rules.email) {\r\n const message = typeof rules.email === \"string\" ? rules.email : \"Invalid email address\";\r\n schema = schema.email(message);\r\n }\r\n\r\n if (rules.url) {\r\n const message = typeof rules.url === \"string\" ? rules.url : \"Invalid URL\";\r\n schema = schema.url(message);\r\n }\r\n\r\n // Handle required - for strings, require non-empty\r\n if (rules.required) {\r\n const message = typeof rules.required === \"string\" ? rules.required : \"This field is required\";\r\n return finalizeSchema(\r\n z.preprocess(\r\n (value) => (value === undefined || value === null ? \"\" : value),\r\n schema.min(1, message)\r\n ),\r\n rules\r\n );\r\n }\r\n\r\n return finalizeSchema(schema.optional(), rules);\r\n }\r\n\r\n // Build number schema\r\n if (type === \"number\") {\r\n let schema = z.coerce.number();\r\n\r\n const minRule = getValueAndMessage(\r\n rules.min,\r\n `Minimum value is ${typeof rules.min === \"number\" ? rules.min : (rules.min as { value: number })?.value}`\r\n );\r\n if (minRule) {\r\n schema = schema.min(minRule.value as number, minRule.message);\r\n }\r\n\r\n const maxRule = getValueAndMessage(\r\n rules.max,\r\n `Maximum value is ${typeof rules.max === \"number\" ? rules.max : (rules.max as { value: number })?.value}`\r\n );\r\n if (maxRule) {\r\n schema = schema.max(maxRule.value as number, maxRule.message);\r\n }\r\n\r\n if (!rules.required) {\r\n return finalizeSchema(schema.optional(), rules);\r\n }\r\n return finalizeSchema(schema, rules);\r\n }\r\n\r\n // Build boolean schema\r\n if (type === \"boolean\") {\r\n const schema = z.boolean();\r\n if (rules.required) {\r\n return finalizeSchema(\r\n schema.refine((val) => val === true, {\r\n message: typeof rules.required === \"string\" ? rules.required : \"This field is required\",\r\n }),\r\n rules\r\n );\r\n }\r\n return finalizeSchema(schema.optional(), rules);\r\n }\r\n\r\n // Build date schema\r\n if (type === \"date\") {\r\n const schema = z.coerce.date();\r\n if (!rules.required) {\r\n return finalizeSchema(schema.optional(), rules);\r\n }\r\n return finalizeSchema(schema, rules);\r\n }\r\n\r\n // Build array schema\r\n if (type === \"array\") {\r\n let schema = z.array(z.unknown());\r\n if (rules.required) {\r\n const message = typeof rules.required === \"string\" ? rules.required : \"This field is required\";\r\n schema = schema.min(1, message);\r\n }\r\n return finalizeSchema(schema, rules);\r\n }\r\n\r\n // Default fallback\r\n return finalizeSchema(z.unknown(), rules);\r\n}\r\n\r\nfunction applyCustomValidate(\r\n schema: z.ZodTypeAny,\r\n rules: FieldValidationRules\r\n): z.ZodTypeAny {\r\n if (!rules.validate) {\r\n return schema;\r\n }\r\n\r\n const validateFn = rules.validate;\r\n\r\n return schema.superRefine(async (value, ctx) => {\r\n const result = await validateFn(value);\r\n\r\n if (result === true) {\r\n return;\r\n }\r\n\r\n ctx.addIssue({\r\n code: z.ZodIssueCode.custom,\r\n message: typeof result === \"string\" ? result : \"Invalid value\",\r\n });\r\n });\r\n}\r\n\r\nfunction finalizeSchema(\r\n schema: z.ZodTypeAny,\r\n rules: FieldValidationRules\r\n): z.ZodTypeAny {\r\n return applyCustomValidate(schema, rules);\r\n}\r\n\r\n/**\r\n * Hook to manage field validations\r\n */\r\nexport function useFieldValidationRegistry() {\r\n const fieldsRef = useRef<Map<string, FieldRegistration>>(new Map());\r\n\r\n const registerFieldValidation = useCallback((field: FieldRegistration) => {\r\n fieldsRef.current.set(field.name, field);\r\n }, []);\r\n\r\n const unregisterFieldValidation = useCallback((name: string) => {\r\n fieldsRef.current.delete(name);\r\n }, []);\r\n\r\n const getValidationSchema = useCallback(() => {\r\n const shape: Record<string, z.ZodTypeAny> = {};\r\n \r\n fieldsRef.current.forEach((field) => {\r\n shape[field.name] = buildZodSchemaFromRules(field.type, field.rules);\r\n });\r\n\r\n return z.object(shape);\r\n }, []);\r\n\r\n return {\r\n registerFieldValidation,\r\n unregisterFieldValidation,\r\n getValidationSchema,\r\n fieldsRef,\r\n };\r\n}\r\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"context.cjs","names":[],"sources":["../../../../src/components/Form/context.ts"],"sourcesContent":["'use client';\r\n\r\nimport { createContext, useCallback, useRef } from \"react\";\r\nimport type { UseFormReturn, FieldValues } from \"react-hook-form\";\r\nimport { z } from \"zod\";\r\n\r\n/**\r\n * Validation rule types that can be applied to form fields\r\n */\r\nexport interface FieldValidationRules {\r\n /** Field is required */\r\n required?: boolean | string;\r\n /** Minimum length for strings */\r\n minLength?: number | { value: number; message: string };\r\n /** Maximum length for strings */\r\n maxLength?: number | { value: number; message: string };\r\n /** Minimum value for numbers */\r\n min?: number | { value: number; message: string };\r\n /** Maximum value for numbers */\r\n max?: number | { value: number; message: string };\r\n /** Regex pattern for validation */\r\n pattern?: RegExp | { value: RegExp; message: string };\r\n /** Email validation */\r\n email?: boolean | string;\r\n /** URL validation */\r\n url?: boolean | string;\r\n /** Custom validation function */\r\n validate?: (value: unknown) => boolean | string | Promise<boolean | string>;\r\n}\r\n\r\n/**\r\n * Form configuration options\r\n */\r\nexport interface FormConfig {\r\n /** Show validation errors inline */\r\n showInlineErrors?: boolean;\r\n /** Validate on blur */\r\n validateOnBlur?: boolean;\r\n /** Validate on change */\r\n validateOnChange?: boolean;\r\n /** Size of form controls */\r\n size?: \"sm\" | \"md\" | \"lg\";\r\n /** Layout direction */\r\n layout?: \"horizontal\" | \"vertical\" | \"inline\";\r\n /** Label width for horizontal layout */\r\n labelWidth?: string | number;\r\n /** Whether form is disabled */\r\n disabled?: boolean;\r\n /** Colon after label */\r\n colon?: boolean;\r\n}\r\n\r\n/**\r\n * Field registration info\r\n */\r\nexport interface FieldRegistration {\r\n name: string;\r\n type: \"string\" | \"number\" | \"boolean\" | \"date\" | \"datetime\" | \"array\";\r\n rules: FieldValidationRules;\r\n}\r\n\r\n/**\r\n * Form context value\r\n */\r\nexport interface FormContextValue<TFieldValues extends FieldValues = FieldValues>\r\n extends FormConfig {\r\n form: UseFormReturn<TFieldValues>;\r\n /** Register a field's validation rules */\r\n registerFieldValidation: (field: FieldRegistration) => void;\r\n /** Unregister a field's validation rules */\r\n unregisterFieldValidation: (name: string) => void;\r\n /** Get current validation schema */\r\n getValidationSchema: () => z.ZodObject<Record<string, z.ZodTypeAny>>;\r\n /** Trigger validation for a specific field */\r\n triggerValidation: (name: string) => Promise<boolean>;\r\n}\r\n\r\n/**\r\n * Default form configuration\r\n */\r\nexport const defaultFormConfig: FormConfig = {\r\n showInlineErrors: true,\r\n validateOnBlur: true,\r\n validateOnChange: false,\r\n size: \"md\",\r\n layout: \"vertical\",\r\n disabled: false,\r\n colon: true,\r\n};\r\n\r\n/**\r\n * Form context for sharing form state and configuration\r\n */\r\nexport const FormConfigContext = createContext<FormContextValue | null>(null);\r\n\r\n/**\r\n * Build a Zod schema from validation rules\r\n */\r\nexport function buildZodSchemaFromRules(\r\n type: FieldRegistration[\"type\"],\r\n rules: FieldValidationRules\r\n): z.ZodTypeAny {\r\n // Helper to extract value and message\r\n const getValueAndMessage = <T>(\r\n rule: T | { value: T; message: string } | undefined,\r\n defaultMessage: string\r\n ): { value: T; message: string } | null => {\r\n if (rule === undefined) return null;\r\n if (typeof rule === \"object\" && rule !== null && \"value\" in rule) {\r\n return rule as { value: T; message: string };\r\n }\r\n return { value: rule as T, message: defaultMessage };\r\n };\r\n\r\n // Build string schema\r\n if (type === \"string\") {\r\n let schema = z.string();\r\n\r\n const minLengthRule = getValueAndMessage(\r\n rules.minLength,\r\n `Minimum ${typeof rules.minLength === \"number\" ? rules.minLength : (rules.minLength as { value: number })?.value} characters required`\r\n );\r\n if (minLengthRule) {\r\n schema = schema.min(minLengthRule.value as number, minLengthRule.message);\r\n }\r\n\r\n const maxLengthRule = getValueAndMessage(\r\n rules.maxLength,\r\n `Maximum ${typeof rules.maxLength === \"number\" ? rules.maxLength : (rules.maxLength as { value: number })?.value} characters allowed`\r\n );\r\n if (maxLengthRule) {\r\n schema = schema.max(maxLengthRule.value as number, maxLengthRule.message);\r\n }\r\n\r\n if (rules.pattern !== undefined) {\r\n const patternRule = rules.pattern instanceof RegExp\r\n ? { value: rules.pattern, message: \"Invalid format\" }\r\n : rules.pattern;\r\n schema = schema.regex(patternRule.value, patternRule.message);\r\n }\r\n\r\n if (rules.email) {\r\n const message = typeof rules.email === \"string\" ? rules.email : \"Invalid email address\";\r\n schema = schema.email(message);\r\n }\r\n\r\n if (rules.url) {\r\n const message = typeof rules.url === \"string\" ? rules.url : \"Invalid URL\";\r\n schema = schema.url(message);\r\n }\r\n\r\n // Handle required - for strings, require non-empty\r\n if (rules.required) {\r\n const message = typeof rules.required === \"string\" ? rules.required : \"This field is required\";\r\n return finalizeSchema(\r\n z.preprocess(\r\n (value) => (value === undefined || value === null ? \"\" : value),\r\n schema.min(1, message)\r\n ),\r\n rules\r\n );\r\n }\r\n\r\n return finalizeSchema(schema.optional(), rules);\r\n }\r\n\r\n // Build number schema\r\n if (type === \"number\") {\r\n let schema = z.coerce.number();\r\n\r\n const minRule = getValueAndMessage(\r\n rules.min,\r\n `Minimum value is ${typeof rules.min === \"number\" ? rules.min : (rules.min as { value: number })?.value}`\r\n );\r\n if (minRule) {\r\n schema = schema.min(minRule.value as number, minRule.message);\r\n }\r\n\r\n const maxRule = getValueAndMessage(\r\n rules.max,\r\n `Maximum value is ${typeof rules.max === \"number\" ? rules.max : (rules.max as { value: number })?.value}`\r\n );\r\n if (maxRule) {\r\n schema = schema.max(maxRule.value as number, maxRule.message);\r\n }\r\n\r\n if (!rules.required) {\r\n return finalizeSchema(schema.optional(), rules);\r\n }\r\n return finalizeSchema(schema, rules);\r\n }\r\n\r\n // Build boolean schema\r\n if (type === \"boolean\") {\r\n const schema = z.boolean();\r\n if (rules.required) {\r\n return finalizeSchema(\r\n schema.refine((val) => val === true, {\r\n message: typeof rules.required === \"string\" ? rules.required : \"This field is required\",\r\n }),\r\n rules\r\n );\r\n }\r\n return finalizeSchema(schema.optional(), rules);\r\n }\r\n\r\n // Build date / datetime schema\r\n if (type === \"date\" || type === \"datetime\") {\r\n const schema = z.coerce.date();\r\n if (!rules.required) {\r\n return finalizeSchema(schema.optional(), rules);\r\n }\r\n return finalizeSchema(schema, rules);\r\n }\r\n\r\n // Build array schema\r\n if (type === \"array\") {\r\n let schema = z.array(z.unknown());\r\n if (rules.required) {\r\n const message = typeof rules.required === \"string\" ? rules.required : \"This field is required\";\r\n schema = schema.min(1, message);\r\n }\r\n return finalizeSchema(schema, rules);\r\n }\r\n\r\n // Default fallback\r\n return finalizeSchema(z.unknown(), rules);\r\n}\r\n\r\nfunction applyCustomValidate(\r\n schema: z.ZodTypeAny,\r\n rules: FieldValidationRules\r\n): z.ZodTypeAny {\r\n if (!rules.validate) {\r\n return schema;\r\n }\r\n\r\n const validateFn = rules.validate;\r\n\r\n return schema.superRefine(async (value, ctx) => {\r\n const result = await validateFn(value);\r\n\r\n if (result === true) {\r\n return;\r\n }\r\n\r\n ctx.addIssue({\r\n code: z.ZodIssueCode.custom,\r\n message: typeof result === \"string\" ? result : \"Invalid value\",\r\n });\r\n });\r\n}\r\n\r\nfunction finalizeSchema(\r\n schema: z.ZodTypeAny,\r\n rules: FieldValidationRules\r\n): z.ZodTypeAny {\r\n return applyCustomValidate(schema, rules);\r\n}\r\n\r\n/**\r\n * Hook to manage field validations\r\n */\r\nexport function useFieldValidationRegistry() {\r\n const fieldsRef = useRef<Map<string, FieldRegistration>>(new Map());\r\n\r\n const registerFieldValidation = useCallback((field: FieldRegistration) => {\r\n fieldsRef.current.set(field.name, field);\r\n }, []);\r\n\r\n const unregisterFieldValidation = useCallback((name: string) => {\r\n fieldsRef.current.delete(name);\r\n }, []);\r\n\r\n const getValidationSchema = useCallback(() => {\r\n const shape: Record<string, z.ZodTypeAny> = {};\r\n \r\n fieldsRef.current.forEach((field) => {\r\n shape[field.name] = buildZodSchemaFromRules(field.type, field.rules);\r\n });\r\n\r\n return z.object(shape);\r\n }, []);\r\n\r\n return {\r\n registerFieldValidation,\r\n unregisterFieldValidation,\r\n getValidationSchema,\r\n fieldsRef,\r\n };\r\n}\r\n"],"mappings":"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"}
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
|
3
3
|
const require_context = require("./context.cjs");
|
|
4
4
|
const require_Form = require("./Form.cjs");
|
|
5
5
|
const require_FieldLayout = require("./FieldLayout.cjs");
|
|
6
|
+
const require_PasswordRevealToggle = require("./PasswordRevealToggle.cjs");
|
|
6
7
|
const require_TextBox = require("./TextBox.cjs");
|
|
7
8
|
const require_TextArea = require("./TextArea.cjs");
|
|
8
9
|
const require_Select = require("./Select.cjs");
|
|
@@ -10,6 +11,8 @@ const require_CountryPicker = require("./CountryPicker.cjs");
|
|
|
10
11
|
const require_CountrySelect = require("./CountrySelect.cjs");
|
|
11
12
|
const require_PhoneInput = require("./PhoneInput.cjs");
|
|
12
13
|
const require_DatePicker = require("./DatePicker.cjs");
|
|
14
|
+
const require_TimePicker = require("./TimePicker.cjs");
|
|
15
|
+
const require_DateTimePicker = require("./DateTimePicker.cjs");
|
|
13
16
|
const require_Combobox = require("./Combobox.cjs");
|
|
14
17
|
const require_Checkbox = require("./Checkbox.cjs");
|
|
15
18
|
const require_Radio = require("./Radio.cjs");
|
|
@@ -20,6 +23,7 @@ exports.Combobox = require_Combobox.Combobox;
|
|
|
20
23
|
exports.CountryPicker = require_CountryPicker.CountryPicker;
|
|
21
24
|
exports.CountrySelect = require_CountrySelect.CountrySelect;
|
|
22
25
|
exports.DatePicker = require_DatePicker.DatePicker;
|
|
26
|
+
exports.DateTimePicker = require_DateTimePicker.DateTimePicker;
|
|
23
27
|
exports.FieldLayout = require_FieldLayout.FieldLayout;
|
|
24
28
|
exports.Form = require_Form.Form;
|
|
25
29
|
exports.FormCheckbox = require_Checkbox.Checkbox;
|
|
@@ -27,15 +31,18 @@ exports.FormCombobox = require_Combobox.Combobox;
|
|
|
27
31
|
exports.FormConfigContext = require_context.FormConfigContext;
|
|
28
32
|
exports.FormCountrySelect = require_CountrySelect.CountrySelect;
|
|
29
33
|
exports.FormDatePicker = require_DatePicker.DatePicker;
|
|
34
|
+
exports.FormDateTimePicker = require_DateTimePicker.DateTimePicker;
|
|
30
35
|
exports.FormPhoneInput = require_PhoneInput.PhoneInput;
|
|
31
36
|
exports.FormSelect = require_Select.Select;
|
|
32
37
|
exports.FormSwitch = require_FormSwitch.FormSwitch;
|
|
38
|
+
exports.PasswordRevealToggle = require_PasswordRevealToggle.PasswordRevealToggle;
|
|
33
39
|
exports.PhoneInput = require_PhoneInput.PhoneInput;
|
|
34
40
|
exports.RadioGroup = require_Radio.RadioGroup;
|
|
35
41
|
exports.RadioItem = require_Radio.RadioItem;
|
|
36
42
|
exports.Select = require_Select.Select;
|
|
37
43
|
exports.TextArea = require_TextArea.TextArea;
|
|
38
44
|
exports.TextBox = require_TextBox.TextBox;
|
|
45
|
+
exports.TimePicker = require_TimePicker.TimePicker;
|
|
39
46
|
exports.buildZodSchemaFromRules = require_context.buildZodSchemaFromRules;
|
|
40
47
|
exports.defaultFormConfig = require_context.defaultFormConfig;
|
|
41
48
|
exports.useFieldError = require_hooks.useFieldError;
|
|
@@ -1,12 +1,40 @@
|
|
|
1
1
|
"use client";
|
|
2
|
+
"use client";
|
|
3
|
+
const require_cn = require("../../utils/cn.cjs");
|
|
4
|
+
const require_PasswordRevealToggle = require("../Form/PasswordRevealToggle.cjs");
|
|
2
5
|
const require_textbox = require("../../primitives/textbox.cjs");
|
|
3
6
|
let react = require("react");
|
|
4
7
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
5
8
|
//#region src/components/Input/Input.tsx
|
|
6
|
-
var Input = (0, react.forwardRef)((
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
9
|
+
var Input = (0, react.forwardRef)(({ type, className, passwordToggle, disabled, ...props }, ref) => {
|
|
10
|
+
const [passwordVisible, setPasswordVisible] = (0, react.useState)(false);
|
|
11
|
+
const showPasswordToggle = type === "password" && passwordToggle !== false;
|
|
12
|
+
const resolvedType = showPasswordToggle && passwordVisible ? "text" : type;
|
|
13
|
+
if (!showPasswordToggle) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_textbox.TextBoxPrimitive, {
|
|
14
|
+
ref,
|
|
15
|
+
type,
|
|
16
|
+
className,
|
|
17
|
+
disabled,
|
|
18
|
+
...props
|
|
19
|
+
});
|
|
20
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
21
|
+
className: "relative w-full",
|
|
22
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_textbox.TextBoxPrimitive, {
|
|
23
|
+
ref,
|
|
24
|
+
type: resolvedType,
|
|
25
|
+
className: require_cn.cn("pr-10", className),
|
|
26
|
+
disabled,
|
|
27
|
+
...props
|
|
28
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
29
|
+
className: "absolute right-3 top-1/2 -translate-y-1/2",
|
|
30
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_PasswordRevealToggle.PasswordRevealToggle, {
|
|
31
|
+
visible: passwordVisible,
|
|
32
|
+
onToggle: () => setPasswordVisible((visible) => !visible),
|
|
33
|
+
disabled
|
|
34
|
+
})
|
|
35
|
+
})]
|
|
36
|
+
});
|
|
37
|
+
});
|
|
10
38
|
Input.displayName = "Input";
|
|
11
39
|
//#endregion
|
|
12
40
|
exports.Input = Input;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Input.cjs","names":[],"sources":["../../../../src/components/Input/Input.tsx"],"sourcesContent":["
|
|
1
|
+
{"version":3,"file":"Input.cjs","names":[],"sources":["../../../../src/components/Input/Input.tsx"],"sourcesContent":["\"use client\"\r\n\r\nimport { forwardRef, useState } from \"react\"\r\nimport type { ComponentPropsWithoutRef, ElementRef } from \"react\"\r\nimport { Input as InputPrimitive } from \"../../primitives/input\"\r\nimport { cn } from \"../../utils/cn\"\r\nimport { PasswordRevealToggle } from \"../Form/PasswordRevealToggle\"\r\n\r\nexport type InputProps = ComponentPropsWithoutRef<typeof InputPrimitive> & {\r\n /**\r\n * Show an eye toggle for password fields.\r\n * Defaults to true when `type=\"password\"`.\r\n */\r\n passwordToggle?: boolean\r\n}\r\n\r\nexport const Input = forwardRef<\r\n ElementRef<typeof InputPrimitive>,\r\n InputProps\r\n>(({ type, className, passwordToggle, disabled, ...props }, ref) => {\r\n const [passwordVisible, setPasswordVisible] = useState(false)\r\n const isPasswordType = type === \"password\"\r\n const showPasswordToggle = isPasswordType && passwordToggle !== false\r\n const resolvedType = showPasswordToggle && passwordVisible ? \"text\" : type\r\n\r\n if (!showPasswordToggle) {\r\n return (\r\n <InputPrimitive\r\n ref={ref}\r\n type={type}\r\n className={className}\r\n disabled={disabled}\r\n {...props}\r\n />\r\n )\r\n }\r\n\r\n return (\r\n <div className=\"relative w-full\">\r\n <InputPrimitive\r\n ref={ref}\r\n type={resolvedType}\r\n className={cn(\"pr-10\", className)}\r\n disabled={disabled}\r\n {...props}\r\n />\r\n <div className=\"absolute right-3 top-1/2 -translate-y-1/2\">\r\n <PasswordRevealToggle\r\n visible={passwordVisible}\r\n onToggle={() => setPasswordVisible((visible) => !visible)}\r\n disabled={disabled}\r\n />\r\n </div>\r\n </div>\r\n )\r\n})\r\nInput.displayName = \"Input\"\r\n"],"mappings":";;;;;;;;AAgBA,IAAa,SAAA,GAAQ,MAAA,WAAA,EAGlB,EAAE,MAAM,WAAW,gBAAgB,UAAU,GAAG,SAAS,QAAQ;CAClE,MAAM,CAAC,iBAAiB,uBAAA,GAAsB,MAAA,SAAA,CAAS,KAAK;CAE5D,MAAM,qBADiB,SAAS,cACa,mBAAmB;CAChE,MAAM,eAAe,sBAAsB,kBAAkB,SAAS;CAEtE,IAAI,CAAC,oBACH,OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,gBAAA,kBAAD;EACO;EACC;EACK;EACD;EACV,GAAI;CACL,CAAA;CAIL,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;EAAK,WAAU;EAAf,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,gBAAA,kBAAD;GACO;GACL,MAAM;GACN,WAAW,WAAA,GAAG,SAAS,SAAS;GACtB;GACV,GAAI;EACL,CAAA,GACD,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;GAAK,WAAU;GACb,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,6BAAA,sBAAD;IACE,SAAS;IACT,gBAAgB,oBAAoB,YAAY,CAAC,OAAO;IAC9C;GACX,CAAA;EACE,CAAA,CACF;;AAET,CAAC;AACD,MAAM,cAAc"}
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -4,6 +4,7 @@ const require_cn = require("./utils/cn.cjs");
|
|
|
4
4
|
const require_Button = require("./components/Button/Button.cjs");
|
|
5
5
|
const require_context = require("./components/Form/context.cjs");
|
|
6
6
|
const require_Form = require("./components/Form/Form.cjs");
|
|
7
|
+
const require_PasswordRevealToggle = require("./components/Form/PasswordRevealToggle.cjs");
|
|
7
8
|
const require_TextBox = require("./components/Form/TextBox.cjs");
|
|
8
9
|
const require_TextArea = require("./components/Form/TextArea.cjs");
|
|
9
10
|
const require_select = require("./primitives/select.cjs");
|
|
@@ -16,6 +17,8 @@ const require_CountrySelect = require("./components/Form/CountrySelect.cjs");
|
|
|
16
17
|
const require_PhoneInput = require("./components/Form/PhoneInput.cjs");
|
|
17
18
|
const require_calendar = require("./primitives/calendar.cjs");
|
|
18
19
|
const require_DatePicker = require("./components/Form/DatePicker.cjs");
|
|
20
|
+
const require_TimePicker = require("./components/Form/TimePicker.cjs");
|
|
21
|
+
const require_DateTimePicker = require("./components/Form/DateTimePicker.cjs");
|
|
19
22
|
const require_Combobox = require("./components/Form/Combobox.cjs");
|
|
20
23
|
const require_Checkbox = require("./components/Form/Checkbox.cjs");
|
|
21
24
|
const require_Radio = require("./components/Form/Radio.cjs");
|
|
@@ -102,6 +105,7 @@ exports.CommandSeparator = require_command.CommandSeparator;
|
|
|
102
105
|
exports.CommandShortcut = require_command.CommandShortcut;
|
|
103
106
|
exports.CountrySelect = require_CountrySelect.CountrySelect;
|
|
104
107
|
exports.DatePicker = require_DatePicker.DatePicker;
|
|
108
|
+
exports.DateTimePicker = require_DateTimePicker.DateTimePicker;
|
|
105
109
|
exports.Dialog = require_dialog.Dialog;
|
|
106
110
|
exports.DialogClose = require_dialog.DialogClose;
|
|
107
111
|
exports.DialogContent = require_dialog.DialogContent;
|
|
@@ -133,6 +137,7 @@ exports.FormCombobox = require_Combobox.Combobox;
|
|
|
133
137
|
exports.FormConfigContext = require_context.FormConfigContext;
|
|
134
138
|
exports.FormCountrySelect = require_CountrySelect.CountrySelect;
|
|
135
139
|
exports.FormDatePicker = require_DatePicker.DatePicker;
|
|
140
|
+
exports.FormDateTimePicker = require_DateTimePicker.DateTimePicker;
|
|
136
141
|
exports.FormPhoneInput = require_PhoneInput.PhoneInput;
|
|
137
142
|
exports.FormSelect = require_Select.Select;
|
|
138
143
|
exports.FormSwitch = require_FormSwitch.FormSwitch;
|
|
@@ -149,6 +154,7 @@ exports.PaginationItem = require_Pagination.PaginationItem;
|
|
|
149
154
|
exports.PaginationLink = require_Pagination.PaginationLink;
|
|
150
155
|
exports.PaginationNext = require_Pagination.PaginationNext;
|
|
151
156
|
exports.PaginationPrevious = require_Pagination.PaginationPrevious;
|
|
157
|
+
exports.PasswordRevealToggle = require_PasswordRevealToggle.PasswordRevealToggle;
|
|
152
158
|
exports.PhoneInput = require_PhoneInput.PhoneInput;
|
|
153
159
|
exports.Popover = require_popover.Popover;
|
|
154
160
|
exports.PopoverAnchor = require_popover.PopoverAnchor;
|
|
@@ -198,6 +204,7 @@ exports.TabsTrigger = require_Tabs.TabsTrigger;
|
|
|
198
204
|
exports.TextArea = require_TextArea.TextArea;
|
|
199
205
|
exports.TextBox = require_TextBox.TextBox;
|
|
200
206
|
exports.Textarea = require_Textarea.Textarea;
|
|
207
|
+
exports.TimePicker = require_TimePicker.TimePicker;
|
|
201
208
|
exports.Toast = require_toast.Toast;
|
|
202
209
|
exports.ToastAction = require_toast.ToastAction;
|
|
203
210
|
exports.ToastClose = require_toast.ToastClose;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DatePicker.d.ts","sourceRoot":"","sources":["../../../src/components/Form/DatePicker.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAsD,KAAK,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,WAAW,EAAE,MAAM,iBAAiB,CAAC;AACrI,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"DatePicker.d.ts","sourceRoot":"","sources":["../../../src/components/Form/DatePicker.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAsD,KAAK,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,WAAW,EAAE,MAAM,iBAAiB,CAAC;AACrI,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAqBlE,QAAA,MAAM,kBAAkB;;;8EAiBtB,CAAC;AAEH,MAAM,WAAW,eAAe,CAC9B,YAAY,SAAS,WAAW,GAAG,WAAW,EAC9C,KAAK,SAAS,SAAS,CAAC,YAAY,CAAC,GAAG,SAAS,CAAC,YAAY,CAAC,CAC/D,SAAQ,YAAY,CAAC,OAAO,kBAAkB,CAAC;IAC/C,IAAI,EAAE,KAAK,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;IAChC,QAAQ,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC5B,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,MAAM,CAAC,CAAC;CAC7E;AAED,wBAAgB,UAAU,CACxB,YAAY,SAAS,WAAW,GAAG,WAAW,EAC9C,KAAK,SAAS,SAAS,CAAC,YAAY,CAAC,GAAG,SAAS,CAAC,YAAY,CAAC,EAC/D,EACA,IAAI,EACJ,KAAK,EACL,UAAU,EACV,SAAgB,EAChB,KAAK,EAAE,WAAW,EAClB,IAAI,EACJ,OAAO,EACP,SAAgB,EAChB,WAA2B,EAC3B,QAAQ,EACR,SAAS,EACT,EAAE,EAAE,UAAU,EACd,OAAO,EAAE,eAAe,EACxB,QAAQ,EACR,QAAQ,GACT,EAAE,eAAe,CAAC,YAAY,EAAE,KAAK,CAAC,+BAkGtC;yBArHe,UAAU"}
|
|
@@ -11,8 +11,14 @@ import { cva } from "class-variance-authority";
|
|
|
11
11
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
12
12
|
import { useController, useFormContext } from "react-hook-form";
|
|
13
13
|
import { CalendarIcon } from "lucide-react";
|
|
14
|
-
import { format } from "date-fns";
|
|
14
|
+
import { format, startOfDay } from "date-fns";
|
|
15
15
|
//#region src/components/Form/DatePicker.tsx
|
|
16
|
+
function toStartOfDay(value) {
|
|
17
|
+
if (!value || value === "") return;
|
|
18
|
+
const date = value instanceof Date ? value : new Date(value);
|
|
19
|
+
if (Number.isNaN(date.getTime())) return;
|
|
20
|
+
return startOfDay(date);
|
|
21
|
+
}
|
|
16
22
|
var datePickerVariants = cva("w-full justify-start text-left font-normal", {
|
|
17
23
|
variants: {
|
|
18
24
|
size: {
|
|
@@ -66,7 +72,7 @@ function DatePicker({ name, label, helperText, showError = true, error: customEr
|
|
|
66
72
|
name,
|
|
67
73
|
control
|
|
68
74
|
});
|
|
69
|
-
const selectedDate =
|
|
75
|
+
const selectedDate = toStartOfDay(field.value);
|
|
70
76
|
const fieldError = fieldState.error?.message;
|
|
71
77
|
const errorMessage = customError ?? fieldError;
|
|
72
78
|
const hasError = !!errorMessage;
|
|
@@ -107,7 +113,7 @@ function DatePicker({ name, label, helperText, showError = true, error: customEr
|
|
|
107
113
|
mode: "single",
|
|
108
114
|
selected: selectedDate,
|
|
109
115
|
onSelect: (date) => {
|
|
110
|
-
field.onChange(date
|
|
116
|
+
field.onChange(date ? startOfDay(date) : "");
|
|
111
117
|
setOpen(false);
|
|
112
118
|
}
|
|
113
119
|
})
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DatePicker.js","names":[],"sources":["../../../src/components/Form/DatePicker.tsx"],"sourcesContent":["'use client';\r\n\r\nimport { useContext, useEffect, useId, useState } from \"react\";\r\nimport { format } from \"date-fns\";\r\nimport { CalendarIcon } from \"lucide-react\";\r\nimport { useController, useFormContext as useRHFFormContext, type Control, type FieldPath, type FieldValues } from \"react-hook-form\";\r\nimport { cva, type VariantProps } from \"class-variance-authority\";\r\nimport { cn } from \"../../utils/cn\";\r\nimport { Button } from \"../../primitives/button\";\r\nimport { Calendar } from \"../../primitives/calendar\";\r\nimport { Popover, PopoverContent, PopoverTrigger } from \"../../primitives/popover\";\r\nimport { FormConfigContext, type FieldValidationRules, type FormConfig } from \"./context\";\r\nimport { FieldLayout } from \"./FieldLayout\";\r\n\r\nconst datePickerVariants = cva(\"w-full justify-start text-left font-normal\", {\r\n variants: {\r\n size: {\r\n sm: \"h-8 text-xs\",\r\n md: \"h-10 text-sm\",\r\n lg: \"h-12 text-base\",\r\n },\r\n variant: {\r\n default: \"border-input\",\r\n error: \"border-destructive\",\r\n success: \"border-green-500\",\r\n },\r\n },\r\n defaultVariants: {\r\n size: \"md\",\r\n variant: \"default\",\r\n },\r\n});\r\n\r\nexport interface DatePickerProps<\r\n TFieldValues extends FieldValues = FieldValues,\r\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>\r\n> extends VariantProps<typeof datePickerVariants> {\r\n name: TName;\r\n label?: string;\r\n helperText?: string;\r\n showError?: boolean;\r\n error?: string;\r\n fullWidth?: boolean;\r\n placeholder?: string;\r\n disabled?: boolean;\r\n className?: string;\r\n id?: string;\r\n control?: Control<TFieldValues>;\r\n required?: boolean | string;\r\n validate?: (value: unknown) => boolean | string | Promise<boolean | string>;\r\n}\r\n\r\nexport function DatePicker<\r\n TFieldValues extends FieldValues = FieldValues,\r\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>\r\n>({\r\n name,\r\n label,\r\n helperText,\r\n showError = true,\r\n error: customError,\r\n size,\r\n variant,\r\n fullWidth = true,\r\n placeholder = \"Pick a date\",\r\n disabled,\r\n className,\r\n id: providedId,\r\n control: externalControl,\r\n required,\r\n validate,\r\n}: DatePickerProps<TFieldValues, TName>) {\r\n const generatedId = useId();\r\n const inputId = providedId ?? generatedId;\r\n const [open, setOpen] = useState(false);\r\n const formConfigContext = useContext(FormConfigContext);\r\n const formConfig: FormConfig = formConfigContext ?? {};\r\n const rhfContext = useRHFFormContext<TFieldValues>();\r\n const control = externalControl ?? rhfContext?.control;\r\n\r\n const registerFieldValidation = formConfigContext?.registerFieldValidation;\r\n const unregisterFieldValidation = formConfigContext?.unregisterFieldValidation;\r\n\r\n useEffect(() => {\r\n if (registerFieldValidation) {\r\n const rules: FieldValidationRules = {};\r\n if (required !== undefined) rules.required = required;\r\n if (validate !== undefined) rules.validate = validate;\r\n\r\n registerFieldValidation({\r\n name: name as string,\r\n type: \"date\",\r\n rules,\r\n });\r\n\r\n return () => {\r\n unregisterFieldValidation?.(name as string);\r\n };\r\n }\r\n }, [\r\n registerFieldValidation,\r\n unregisterFieldValidation,\r\n name,\r\n required,\r\n validate,\r\n ]);\r\n\r\n const { field, fieldState } = useController<TFieldValues, TName>({\r\n name,\r\n control,\r\n });\r\n\r\n const selectedDate =
|
|
1
|
+
{"version":3,"file":"DatePicker.js","names":[],"sources":["../../../src/components/Form/DatePicker.tsx"],"sourcesContent":["'use client';\r\n\r\nimport { useContext, useEffect, useId, useState } from \"react\";\r\nimport { format, startOfDay } from \"date-fns\";\r\nimport { CalendarIcon } from \"lucide-react\";\r\nimport { useController, useFormContext as useRHFFormContext, type Control, type FieldPath, type FieldValues } from \"react-hook-form\";\r\nimport { cva, type VariantProps } from \"class-variance-authority\";\r\nimport { cn } from \"../../utils/cn\";\r\nimport { Button } from \"../../primitives/button\";\r\nimport { Calendar } from \"../../primitives/calendar\";\r\nimport { Popover, PopoverContent, PopoverTrigger } from \"../../primitives/popover\";\r\nimport { FormConfigContext, type FieldValidationRules, type FormConfig } from \"./context\";\r\nimport { FieldLayout } from \"./FieldLayout\";\r\n\r\nfunction toStartOfDay(value: unknown): Date | undefined {\r\n if (!value || value === \"\") {\r\n return undefined;\r\n }\r\n\r\n const date = value instanceof Date ? value : new Date(value as string | number);\r\n if (Number.isNaN(date.getTime())) {\r\n return undefined;\r\n }\r\n\r\n return startOfDay(date);\r\n}\r\n\r\nconst datePickerVariants = cva(\"w-full justify-start text-left font-normal\", {\r\n variants: {\r\n size: {\r\n sm: \"h-8 text-xs\",\r\n md: \"h-10 text-sm\",\r\n lg: \"h-12 text-base\",\r\n },\r\n variant: {\r\n default: \"border-input\",\r\n error: \"border-destructive\",\r\n success: \"border-green-500\",\r\n },\r\n },\r\n defaultVariants: {\r\n size: \"md\",\r\n variant: \"default\",\r\n },\r\n});\r\n\r\nexport interface DatePickerProps<\r\n TFieldValues extends FieldValues = FieldValues,\r\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>\r\n> extends VariantProps<typeof datePickerVariants> {\r\n name: TName;\r\n label?: string;\r\n helperText?: string;\r\n showError?: boolean;\r\n error?: string;\r\n fullWidth?: boolean;\r\n placeholder?: string;\r\n disabled?: boolean;\r\n className?: string;\r\n id?: string;\r\n control?: Control<TFieldValues>;\r\n required?: boolean | string;\r\n validate?: (value: unknown) => boolean | string | Promise<boolean | string>;\r\n}\r\n\r\nexport function DatePicker<\r\n TFieldValues extends FieldValues = FieldValues,\r\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>\r\n>({\r\n name,\r\n label,\r\n helperText,\r\n showError = true,\r\n error: customError,\r\n size,\r\n variant,\r\n fullWidth = true,\r\n placeholder = \"Pick a date\",\r\n disabled,\r\n className,\r\n id: providedId,\r\n control: externalControl,\r\n required,\r\n validate,\r\n}: DatePickerProps<TFieldValues, TName>) {\r\n const generatedId = useId();\r\n const inputId = providedId ?? generatedId;\r\n const [open, setOpen] = useState(false);\r\n const formConfigContext = useContext(FormConfigContext);\r\n const formConfig: FormConfig = formConfigContext ?? {};\r\n const rhfContext = useRHFFormContext<TFieldValues>();\r\n const control = externalControl ?? rhfContext?.control;\r\n\r\n const registerFieldValidation = formConfigContext?.registerFieldValidation;\r\n const unregisterFieldValidation = formConfigContext?.unregisterFieldValidation;\r\n\r\n useEffect(() => {\r\n if (registerFieldValidation) {\r\n const rules: FieldValidationRules = {};\r\n if (required !== undefined) rules.required = required;\r\n if (validate !== undefined) rules.validate = validate;\r\n\r\n registerFieldValidation({\r\n name: name as string,\r\n type: \"date\",\r\n rules,\r\n });\r\n\r\n return () => {\r\n unregisterFieldValidation?.(name as string);\r\n };\r\n }\r\n }, [\r\n registerFieldValidation,\r\n unregisterFieldValidation,\r\n name,\r\n required,\r\n validate,\r\n ]);\r\n\r\n const { field, fieldState } = useController<TFieldValues, TName>({\r\n name,\r\n control,\r\n });\r\n\r\n const selectedDate = toStartOfDay(field.value);\r\n const fieldError = fieldState.error?.message;\r\n const errorMessage = customError ?? fieldError;\r\n const hasError = !!errorMessage;\r\n const effectiveSize = size ?? formConfig.size ?? \"md\";\r\n const effectiveDisabled = disabled ?? formConfig.disabled;\r\n const effectiveVariant = hasError ? \"error\" : variant;\r\n\r\n return (\r\n <FieldLayout\r\n inputId={inputId}\r\n label={label}\r\n required={!!required}\r\n helperText={helperText}\r\n errorMessage={showError ? errorMessage : undefined}\r\n showError={showError}\r\n fullWidth={fullWidth}\r\n formConfig={formConfig}\r\n >\r\n <Popover open={open} onOpenChange={setOpen}>\r\n <PopoverTrigger asChild>\r\n <Button\r\n id={inputId}\r\n type=\"button\"\r\n variant=\"outline\"\r\n disabled={effectiveDisabled}\r\n aria-invalid={hasError}\r\n aria-describedby={\r\n hasError\r\n ? `${inputId}-error`\r\n : helperText\r\n ? `${inputId}-helper`\r\n : undefined\r\n }\r\n className={cn(\r\n datePickerVariants({ size: effectiveSize, variant: effectiveVariant }),\r\n !selectedDate && \"text-muted-foreground\",\r\n className\r\n )}\r\n >\r\n <CalendarIcon className=\"mr-2 h-4 w-4\" />\r\n {selectedDate ? format(selectedDate, \"PPP\") : placeholder}\r\n </Button>\r\n </PopoverTrigger>\r\n <PopoverContent className=\"w-auto p-0\" align=\"start\">\r\n <Calendar\r\n mode=\"single\"\r\n selected={selectedDate}\r\n onSelect={(date) => {\r\n field.onChange(date ? startOfDay(date) : \"\");\r\n setOpen(false);\r\n }}\r\n />\r\n </PopoverContent>\r\n </Popover>\r\n </FieldLayout>\r\n );\r\n}\r\n\r\nDatePicker.displayName = \"DatePicker\";\r\n"],"mappings":";;;;;;;;;;;;;;;AAcA,SAAS,aAAa,OAAkC;CACtD,IAAI,CAAC,SAAS,UAAU,IACtB;CAGF,MAAM,OAAO,iBAAiB,OAAO,QAAQ,IAAI,KAAK,KAAwB;CAC9E,IAAI,OAAO,MAAM,KAAK,QAAQ,CAAC,GAC7B;CAGF,OAAO,WAAW,IAAI;AACxB;AAEA,IAAM,qBAAqB,IAAI,8CAA8C;CAC3E,UAAU;EACR,MAAM;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;EACN;EACA,SAAS;GACP,SAAS;GACT,OAAO;GACP,SAAS;EACX;CACF;CACA,iBAAiB;EACf,MAAM;EACN,SAAS;CACX;AACF,CAAC;AAqBD,SAAgB,WAGd,EACA,MACA,OACA,YACA,YAAY,MACZ,OAAO,aACP,MACA,SACA,YAAY,MACZ,cAAc,eACd,UACA,WACA,IAAI,YACJ,SAAS,iBACT,UACA,YACuC;CACvC,MAAM,cAAc,MAAM;CAC1B,MAAM,UAAU,cAAc;CAC9B,MAAM,CAAC,MAAM,WAAW,SAAS,KAAK;CACtC,MAAM,oBAAoB,WAAW,iBAAiB;CACtD,MAAM,aAAyB,qBAAqB,CAAC;CACrD,MAAM,aAAa,eAAgC;CACnD,MAAM,UAAU,mBAAmB,YAAY;CAE/C,MAAM,0BAA0B,mBAAmB;CACnD,MAAM,4BAA4B,mBAAmB;CAErD,gBAAgB;EACd,IAAI,yBAAyB;GAC3B,MAAM,QAA8B,CAAC;GACrC,IAAI,aAAa,KAAA,GAAW,MAAM,WAAW;GAC7C,IAAI,aAAa,KAAA,GAAW,MAAM,WAAW;GAE7C,wBAAwB;IAChB;IACN,MAAM;IACN;GACF,CAAC;GAED,aAAa;IACX,4BAA4B,IAAc;GAC5C;EACF;CACF,GAAG;EACD;EACA;EACA;EACA;EACA;CACF,CAAC;CAED,MAAM,EAAE,OAAO,eAAe,cAAmC;EAC/D;EACA;CACF,CAAC;CAED,MAAM,eAAe,aAAa,MAAM,KAAK;CAC7C,MAAM,aAAa,WAAW,OAAO;CACrC,MAAM,eAAe,eAAe;CACpC,MAAM,WAAW,CAAC,CAAC;CACnB,MAAM,gBAAgB,QAAQ,WAAW,QAAQ;CACjD,MAAM,oBAAoB,YAAY,WAAW;CACjD,MAAM,mBAAmB,WAAW,UAAU;CAE9C,OACE,oBAAC,aAAD;EACW;EACF;EACP,UAAU,CAAC,CAAC;EACA;EACZ,cAAc,YAAY,eAAe,KAAA;EAC9B;EACA;EACC;EAEZ,UAAA,qBAAC,SAAD;GAAe;GAAM,cAAc;GAAnC,UAAA,CACE,oBAAC,gBAAD;IAAgB,SAAA;IACd,UAAA,qBAAC,QAAD;KACE,IAAI;KACJ,MAAK;KACL,SAAQ;KACR,UAAU;KACV,gBAAc;KACd,oBACE,WACI,GAAG,QAAQ,UACX,aACE,GAAG,QAAQ,WACX,KAAA;KAER,WAAW,GACT,mBAAmB;MAAE,MAAM;MAAe,SAAS;KAAiB,CAAC,GACrE,CAAC,gBAAgB,yBACjB,SACF;KAjBF,UAAA,CAmBE,oBAAC,cAAD,EAAc,WAAU,eAAgB,CAAA,GACvC,eAAe,OAAO,cAAc,KAAK,IAAI,WACxC;;GACM,CAAA,GAChB,oBAAC,gBAAD;IAAgB,WAAU;IAAa,OAAM;IAC3C,UAAA,oBAAC,UAAD;KACE,MAAK;KACL,UAAU;KACV,WAAW,SAAS;MAClB,MAAM,SAAS,OAAO,WAAW,IAAI,IAAI,EAAE;MAC3C,QAAQ,KAAK;KACf;IACD,CAAA;GACa,CAAA,CACT;;CACE,CAAA;AAEjB;AAEA,WAAW,cAAc"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Control, FieldPath, FieldValues } from 'react-hook-form';
|
|
2
|
+
import { VariantProps } from 'class-variance-authority';
|
|
3
|
+
declare const dateTimePickerVariants: (props?: ({
|
|
4
|
+
size?: "sm" | "lg" | "md" | null | undefined;
|
|
5
|
+
variant?: "default" | "error" | "success" | null | undefined;
|
|
6
|
+
} & import('class-variance-authority/types').ClassProp) | undefined) => string;
|
|
7
|
+
export interface DateTimePickerProps<TFieldValues extends FieldValues = FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>> extends VariantProps<typeof dateTimePickerVariants> {
|
|
8
|
+
name: TName;
|
|
9
|
+
label?: string;
|
|
10
|
+
helperText?: string;
|
|
11
|
+
showError?: boolean;
|
|
12
|
+
error?: string;
|
|
13
|
+
fullWidth?: boolean;
|
|
14
|
+
placeholder?: string;
|
|
15
|
+
disabled?: boolean;
|
|
16
|
+
className?: string;
|
|
17
|
+
id?: string;
|
|
18
|
+
control?: Control<TFieldValues>;
|
|
19
|
+
required?: boolean | string;
|
|
20
|
+
validate?: (value: unknown) => boolean | string | Promise<boolean | string>;
|
|
21
|
+
minuteStep?: number;
|
|
22
|
+
}
|
|
23
|
+
export declare function DateTimePicker<TFieldValues extends FieldValues = FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>>({ name, label, helperText, showError, error: customError, size, variant, fullWidth, placeholder, disabled, className, id: providedId, control: externalControl, required, validate, minuteStep, }: DateTimePickerProps<TFieldValues, TName>): import("react").JSX.Element;
|
|
24
|
+
export declare namespace DateTimePicker {
|
|
25
|
+
var displayName: string;
|
|
26
|
+
}
|
|
27
|
+
export {};
|
|
28
|
+
//# sourceMappingURL=DateTimePicker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DateTimePicker.d.ts","sourceRoot":"","sources":["../../../src/components/Form/DateTimePicker.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAsD,KAAK,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,WAAW,EAAE,MAAM,iBAAiB,CAAC;AACrI,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAUlE,QAAA,MAAM,sBAAsB;;;8EAiB1B,CAAC;AAEH,MAAM,WAAW,mBAAmB,CAClC,YAAY,SAAS,WAAW,GAAG,WAAW,EAC9C,KAAK,SAAS,SAAS,CAAC,YAAY,CAAC,GAAG,SAAS,CAAC,YAAY,CAAC,CAC/D,SAAQ,YAAY,CAAC,OAAO,sBAAsB,CAAC;IACnD,IAAI,EAAE,KAAK,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;IAChC,QAAQ,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC5B,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,MAAM,CAAC,CAAC;IAC5E,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAkCD,wBAAgB,cAAc,CAC5B,YAAY,SAAS,WAAW,GAAG,WAAW,EAC9C,KAAK,SAAS,SAAS,CAAC,YAAY,CAAC,GAAG,SAAS,CAAC,YAAY,CAAC,EAC/D,EACA,IAAI,EACJ,KAAK,EACL,UAAU,EACV,SAAgB,EAChB,KAAK,EAAE,WAAW,EAClB,IAAI,EACJ,OAAO,EACP,SAAgB,EAChB,WAA2B,EAC3B,QAAQ,EACR,SAAS,EACT,EAAE,EAAE,UAAU,EACd,OAAO,EAAE,eAAe,EACxB,QAAQ,EACR,QAAQ,EACR,UAAc,GACf,EAAE,mBAAmB,CAAC,YAAY,EAAE,KAAK,CAAC,+BAuL1C;yBA3Me,cAAc"}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use client";
|
|
3
|
+
import { cn } from "../../utils/cn.js";
|
|
4
|
+
import { Button } from "../../primitives/button.js";
|
|
5
|
+
import { FormConfigContext } from "./context.js";
|
|
6
|
+
import { FieldLayout } from "./FieldLayout.js";
|
|
7
|
+
import { Popover, PopoverContent, PopoverTrigger } from "../../primitives/popover.js";
|
|
8
|
+
import { Calendar } from "../../primitives/calendar.js";
|
|
9
|
+
import { Separator } from "../../primitives/separator.js";
|
|
10
|
+
import { TimePicker } from "./TimePicker.js";
|
|
11
|
+
import { useContext, useEffect, useId, useState } from "react";
|
|
12
|
+
import { cva } from "class-variance-authority";
|
|
13
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
14
|
+
import { useController, useFormContext } from "react-hook-form";
|
|
15
|
+
import { CalendarIcon, Clock } from "lucide-react";
|
|
16
|
+
import { format, startOfDay } from "date-fns";
|
|
17
|
+
//#region src/components/Form/DateTimePicker.tsx
|
|
18
|
+
var dateTimePickerVariants = cva("w-full justify-start text-left font-normal", {
|
|
19
|
+
variants: {
|
|
20
|
+
size: {
|
|
21
|
+
sm: "h-8 text-xs",
|
|
22
|
+
md: "h-10 text-sm",
|
|
23
|
+
lg: "h-12 text-base"
|
|
24
|
+
},
|
|
25
|
+
variant: {
|
|
26
|
+
default: "border-input",
|
|
27
|
+
error: "border-destructive",
|
|
28
|
+
success: "border-green-500"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
defaultVariants: {
|
|
32
|
+
size: "md",
|
|
33
|
+
variant: "default"
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
function toValidDate(value) {
|
|
37
|
+
if (!value || value === "") return;
|
|
38
|
+
const date = value instanceof Date ? value : new Date(value);
|
|
39
|
+
if (Number.isNaN(date.getTime())) return;
|
|
40
|
+
return date;
|
|
41
|
+
}
|
|
42
|
+
function hasTimePart(date) {
|
|
43
|
+
return date.getHours() !== 0 || date.getMinutes() !== 0 || date.getSeconds() !== 0 || date.getMilliseconds() !== 0;
|
|
44
|
+
}
|
|
45
|
+
function withPreservedTime(nextDay, previous) {
|
|
46
|
+
const next = new Date(nextDay);
|
|
47
|
+
next.setHours(previous.getHours(), previous.getMinutes(), previous.getSeconds(), previous.getMilliseconds());
|
|
48
|
+
return next;
|
|
49
|
+
}
|
|
50
|
+
function isSelectEventTarget(target) {
|
|
51
|
+
return target instanceof Element && Boolean(target.closest("[data-radix-select-content]"));
|
|
52
|
+
}
|
|
53
|
+
function DateTimePicker({ name, label, helperText, showError = true, error: customError, size, variant, fullWidth = true, placeholder = "Pick a date", disabled, className, id: providedId, control: externalControl, required, validate, minuteStep = 5 }) {
|
|
54
|
+
const generatedId = useId();
|
|
55
|
+
const inputId = providedId ?? generatedId;
|
|
56
|
+
const [open, setOpen] = useState(false);
|
|
57
|
+
const [timeOpen, setTimeOpen] = useState(false);
|
|
58
|
+
const [timeSet, setTimeSet] = useState(false);
|
|
59
|
+
const formConfigContext = useContext(FormConfigContext);
|
|
60
|
+
const formConfig = formConfigContext ?? {};
|
|
61
|
+
const rhfContext = useFormContext();
|
|
62
|
+
const control = externalControl ?? rhfContext?.control;
|
|
63
|
+
const registerFieldValidation = formConfigContext?.registerFieldValidation;
|
|
64
|
+
const unregisterFieldValidation = formConfigContext?.unregisterFieldValidation;
|
|
65
|
+
useEffect(() => {
|
|
66
|
+
if (registerFieldValidation) {
|
|
67
|
+
const rules = {};
|
|
68
|
+
if (required !== void 0) rules.required = required;
|
|
69
|
+
if (validate !== void 0) rules.validate = validate;
|
|
70
|
+
registerFieldValidation({
|
|
71
|
+
name,
|
|
72
|
+
type: "datetime",
|
|
73
|
+
rules
|
|
74
|
+
});
|
|
75
|
+
return () => {
|
|
76
|
+
unregisterFieldValidation?.(name);
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
}, [
|
|
80
|
+
registerFieldValidation,
|
|
81
|
+
unregisterFieldValidation,
|
|
82
|
+
name,
|
|
83
|
+
required,
|
|
84
|
+
validate
|
|
85
|
+
]);
|
|
86
|
+
const { field, fieldState } = useController({
|
|
87
|
+
name,
|
|
88
|
+
control
|
|
89
|
+
});
|
|
90
|
+
const selectedDate = toValidDate(field.value);
|
|
91
|
+
useEffect(() => {
|
|
92
|
+
const date = toValidDate(field.value);
|
|
93
|
+
if (!date) {
|
|
94
|
+
setTimeSet(false);
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
if (hasTimePart(date)) setTimeSet(true);
|
|
98
|
+
}, [field.value]);
|
|
99
|
+
const fieldError = fieldState.error?.message;
|
|
100
|
+
const errorMessage = customError ?? fieldError;
|
|
101
|
+
const hasError = !!errorMessage;
|
|
102
|
+
const effectiveSize = size ?? formConfig.size ?? "md";
|
|
103
|
+
const effectiveDisabled = disabled ?? formConfig.disabled;
|
|
104
|
+
const effectiveVariant = hasError ? "error" : variant;
|
|
105
|
+
const displayHasTime = timeSet && !!selectedDate;
|
|
106
|
+
const handleOpenChange = (nextOpen) => {
|
|
107
|
+
setOpen(nextOpen);
|
|
108
|
+
if (nextOpen && timeSet) {
|
|
109
|
+
setTimeOpen(true);
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
if (!nextOpen) setTimeOpen(false);
|
|
113
|
+
};
|
|
114
|
+
return /* @__PURE__ */ jsx(FieldLayout, {
|
|
115
|
+
inputId,
|
|
116
|
+
label,
|
|
117
|
+
required: !!required,
|
|
118
|
+
helperText,
|
|
119
|
+
errorMessage: showError ? errorMessage : void 0,
|
|
120
|
+
showError,
|
|
121
|
+
fullWidth,
|
|
122
|
+
formConfig,
|
|
123
|
+
children: /* @__PURE__ */ jsxs(Popover, {
|
|
124
|
+
open,
|
|
125
|
+
onOpenChange: handleOpenChange,
|
|
126
|
+
children: [/* @__PURE__ */ jsx(PopoverTrigger, {
|
|
127
|
+
asChild: true,
|
|
128
|
+
children: /* @__PURE__ */ jsxs(Button, {
|
|
129
|
+
id: inputId,
|
|
130
|
+
type: "button",
|
|
131
|
+
variant: "outline",
|
|
132
|
+
disabled: effectiveDisabled,
|
|
133
|
+
"aria-invalid": hasError,
|
|
134
|
+
"aria-describedby": hasError ? `${inputId}-error` : helperText ? `${inputId}-helper` : void 0,
|
|
135
|
+
className: cn(dateTimePickerVariants({
|
|
136
|
+
size: effectiveSize,
|
|
137
|
+
variant: effectiveVariant
|
|
138
|
+
}), !selectedDate && "text-muted-foreground", className),
|
|
139
|
+
children: [/* @__PURE__ */ jsx(CalendarIcon, { className: "mr-2 h-4 w-4" }), selectedDate ? format(selectedDate, displayHasTime ? "PPP p" : "PPP") : placeholder]
|
|
140
|
+
})
|
|
141
|
+
}), /* @__PURE__ */ jsxs(PopoverContent, {
|
|
142
|
+
className: "w-auto p-0",
|
|
143
|
+
align: "start",
|
|
144
|
+
onPointerDownOutside: (event) => {
|
|
145
|
+
if (isSelectEventTarget(event.target)) event.preventDefault();
|
|
146
|
+
},
|
|
147
|
+
onFocusOutside: (event) => {
|
|
148
|
+
if (isSelectEventTarget(event.target)) event.preventDefault();
|
|
149
|
+
},
|
|
150
|
+
children: [
|
|
151
|
+
/* @__PURE__ */ jsx(Calendar, {
|
|
152
|
+
mode: "single",
|
|
153
|
+
selected: selectedDate,
|
|
154
|
+
onSelect: (date) => {
|
|
155
|
+
if (!date) {
|
|
156
|
+
field.onChange("");
|
|
157
|
+
setTimeSet(false);
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
if (selectedDate && timeSet) {
|
|
161
|
+
field.onChange(withPreservedTime(date, selectedDate));
|
|
162
|
+
setOpen(false);
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
field.onChange(startOfDay(date));
|
|
166
|
+
}
|
|
167
|
+
}),
|
|
168
|
+
/* @__PURE__ */ jsx(Separator, {}),
|
|
169
|
+
/* @__PURE__ */ jsxs("div", {
|
|
170
|
+
className: "p-3",
|
|
171
|
+
children: [/* @__PURE__ */ jsxs(Button, {
|
|
172
|
+
type: "button",
|
|
173
|
+
variant: "ghost",
|
|
174
|
+
disabled: effectiveDisabled,
|
|
175
|
+
className: "h-8 w-full justify-start px-2 font-normal",
|
|
176
|
+
onClick: () => setTimeOpen((current) => !current),
|
|
177
|
+
children: [/* @__PURE__ */ jsx(Clock, { className: "mr-2 h-4 w-4" }), displayHasTime && selectedDate ? format(selectedDate, "p") : "Add time"]
|
|
178
|
+
}), timeOpen ? /* @__PURE__ */ jsx(TimePicker, {
|
|
179
|
+
className: "mt-2",
|
|
180
|
+
value: selectedDate,
|
|
181
|
+
minuteStep,
|
|
182
|
+
disabled: effectiveDisabled,
|
|
183
|
+
onChange: (date) => {
|
|
184
|
+
field.onChange(date);
|
|
185
|
+
setTimeSet(true);
|
|
186
|
+
},
|
|
187
|
+
onClear: () => {
|
|
188
|
+
if (selectedDate) field.onChange(startOfDay(selectedDate));
|
|
189
|
+
setTimeSet(false);
|
|
190
|
+
}
|
|
191
|
+
}) : null]
|
|
192
|
+
})
|
|
193
|
+
]
|
|
194
|
+
})]
|
|
195
|
+
})
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
DateTimePicker.displayName = "DateTimePicker";
|
|
199
|
+
//#endregion
|
|
200
|
+
export { DateTimePicker };
|
|
201
|
+
|
|
202
|
+
//# sourceMappingURL=DateTimePicker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DateTimePicker.js","names":[],"sources":["../../../src/components/Form/DateTimePicker.tsx"],"sourcesContent":["'use client';\r\n\r\nimport { useContext, useEffect, useId, useState } from \"react\";\r\nimport { format, startOfDay } from \"date-fns\";\r\nimport { CalendarIcon, Clock } from \"lucide-react\";\r\nimport { useController, useFormContext as useRHFFormContext, type Control, type FieldPath, type FieldValues } from \"react-hook-form\";\r\nimport { cva, type VariantProps } from \"class-variance-authority\";\r\nimport { cn } from \"../../utils/cn\";\r\nimport { Button } from \"../../primitives/button\";\r\nimport { Calendar } from \"../../primitives/calendar\";\r\nimport { Popover, PopoverContent, PopoverTrigger } from \"../../primitives/popover\";\r\nimport { Separator } from \"../../primitives/separator\";\r\nimport { FormConfigContext, type FieldValidationRules, type FormConfig } from \"./context\";\r\nimport { FieldLayout } from \"./FieldLayout\";\r\nimport { TimePicker } from \"./TimePicker\";\r\n\r\nconst dateTimePickerVariants = cva(\"w-full justify-start text-left font-normal\", {\r\n variants: {\r\n size: {\r\n sm: \"h-8 text-xs\",\r\n md: \"h-10 text-sm\",\r\n lg: \"h-12 text-base\",\r\n },\r\n variant: {\r\n default: \"border-input\",\r\n error: \"border-destructive\",\r\n success: \"border-green-500\",\r\n },\r\n },\r\n defaultVariants: {\r\n size: \"md\",\r\n variant: \"default\",\r\n },\r\n});\r\n\r\nexport interface DateTimePickerProps<\r\n TFieldValues extends FieldValues = FieldValues,\r\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>\r\n> extends VariantProps<typeof dateTimePickerVariants> {\r\n name: TName;\r\n label?: string;\r\n helperText?: string;\r\n showError?: boolean;\r\n error?: string;\r\n fullWidth?: boolean;\r\n placeholder?: string;\r\n disabled?: boolean;\r\n className?: string;\r\n id?: string;\r\n control?: Control<TFieldValues>;\r\n required?: boolean | string;\r\n validate?: (value: unknown) => boolean | string | Promise<boolean | string>;\r\n minuteStep?: number;\r\n}\r\n\r\nfunction toValidDate(value: unknown): Date | undefined {\r\n if (!value || value === \"\") {\r\n return undefined;\r\n }\r\n\r\n const date = value instanceof Date ? value : new Date(value as string | number);\r\n if (Number.isNaN(date.getTime())) {\r\n return undefined;\r\n }\r\n\r\n return date;\r\n}\r\n\r\nfunction hasTimePart(date: Date): boolean {\r\n return date.getHours() !== 0 || date.getMinutes() !== 0 || date.getSeconds() !== 0 || date.getMilliseconds() !== 0;\r\n}\r\n\r\nfunction withPreservedTime(nextDay: Date, previous: Date): Date {\r\n const next = new Date(nextDay);\r\n next.setHours(\r\n previous.getHours(),\r\n previous.getMinutes(),\r\n previous.getSeconds(),\r\n previous.getMilliseconds()\r\n );\r\n return next;\r\n}\r\n\r\nfunction isSelectEventTarget(target: EventTarget | null): boolean {\r\n return target instanceof Element && Boolean(target.closest(\"[data-radix-select-content]\"));\r\n}\r\n\r\nexport function DateTimePicker<\r\n TFieldValues extends FieldValues = FieldValues,\r\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>\r\n>({\r\n name,\r\n label,\r\n helperText,\r\n showError = true,\r\n error: customError,\r\n size,\r\n variant,\r\n fullWidth = true,\r\n placeholder = \"Pick a date\",\r\n disabled,\r\n className,\r\n id: providedId,\r\n control: externalControl,\r\n required,\r\n validate,\r\n minuteStep = 5,\r\n}: DateTimePickerProps<TFieldValues, TName>) {\r\n const generatedId = useId();\r\n const inputId = providedId ?? generatedId;\r\n const [open, setOpen] = useState(false);\r\n const [timeOpen, setTimeOpen] = useState(false);\r\n const [timeSet, setTimeSet] = useState(false);\r\n const formConfigContext = useContext(FormConfigContext);\r\n const formConfig: FormConfig = formConfigContext ?? {};\r\n const rhfContext = useRHFFormContext<TFieldValues>();\r\n const control = externalControl ?? rhfContext?.control;\r\n\r\n const registerFieldValidation = formConfigContext?.registerFieldValidation;\r\n const unregisterFieldValidation = formConfigContext?.unregisterFieldValidation;\r\n\r\n useEffect(() => {\r\n if (registerFieldValidation) {\r\n const rules: FieldValidationRules = {};\r\n if (required !== undefined) rules.required = required;\r\n if (validate !== undefined) rules.validate = validate;\r\n\r\n registerFieldValidation({\r\n name: name as string,\r\n type: \"datetime\",\r\n rules,\r\n });\r\n\r\n return () => {\r\n unregisterFieldValidation?.(name as string);\r\n };\r\n }\r\n }, [\r\n registerFieldValidation,\r\n unregisterFieldValidation,\r\n name,\r\n required,\r\n validate,\r\n ]);\r\n\r\n const { field, fieldState } = useController<TFieldValues, TName>({\r\n name,\r\n control,\r\n });\r\n\r\n const selectedDate = toValidDate(field.value);\r\n\r\n useEffect(() => {\r\n const date = toValidDate(field.value);\r\n if (!date) {\r\n setTimeSet(false);\r\n return;\r\n }\r\n\r\n if (hasTimePart(date)) {\r\n setTimeSet(true);\r\n }\r\n }, [field.value]);\r\n\r\n const fieldError = fieldState.error?.message;\r\n const errorMessage = customError ?? fieldError;\r\n const hasError = !!errorMessage;\r\n const effectiveSize = size ?? formConfig.size ?? \"md\";\r\n const effectiveDisabled = disabled ?? formConfig.disabled;\r\n const effectiveVariant = hasError ? \"error\" : variant;\r\n const displayHasTime = timeSet && !!selectedDate;\r\n\r\n const handleOpenChange = (nextOpen: boolean) => {\r\n setOpen(nextOpen);\r\n if (nextOpen && timeSet) {\r\n setTimeOpen(true);\r\n return;\r\n }\r\n\r\n if (!nextOpen) {\r\n setTimeOpen(false);\r\n }\r\n };\r\n\r\n return (\r\n <FieldLayout\r\n inputId={inputId}\r\n label={label}\r\n required={!!required}\r\n helperText={helperText}\r\n errorMessage={showError ? errorMessage : undefined}\r\n showError={showError}\r\n fullWidth={fullWidth}\r\n formConfig={formConfig}\r\n >\r\n <Popover open={open} onOpenChange={handleOpenChange}>\r\n <PopoverTrigger asChild>\r\n <Button\r\n id={inputId}\r\n type=\"button\"\r\n variant=\"outline\"\r\n disabled={effectiveDisabled}\r\n aria-invalid={hasError}\r\n aria-describedby={\r\n hasError\r\n ? `${inputId}-error`\r\n : helperText\r\n ? `${inputId}-helper`\r\n : undefined\r\n }\r\n className={cn(\r\n dateTimePickerVariants({ size: effectiveSize, variant: effectiveVariant }),\r\n !selectedDate && \"text-muted-foreground\",\r\n className\r\n )}\r\n >\r\n <CalendarIcon className=\"mr-2 h-4 w-4\" />\r\n {selectedDate\r\n ? format(selectedDate, displayHasTime ? \"PPP p\" : \"PPP\")\r\n : placeholder}\r\n </Button>\r\n </PopoverTrigger>\r\n <PopoverContent\r\n className=\"w-auto p-0\"\r\n align=\"start\"\r\n onPointerDownOutside={(event) => {\r\n if (isSelectEventTarget(event.target)) {\r\n event.preventDefault();\r\n }\r\n }}\r\n onFocusOutside={(event) => {\r\n if (isSelectEventTarget(event.target)) {\r\n event.preventDefault();\r\n }\r\n }}\r\n >\r\n <Calendar\r\n mode=\"single\"\r\n selected={selectedDate}\r\n onSelect={(date) => {\r\n if (!date) {\r\n field.onChange(\"\");\r\n setTimeSet(false);\r\n return;\r\n }\r\n\r\n if (selectedDate && timeSet) {\r\n field.onChange(withPreservedTime(date, selectedDate));\r\n setOpen(false);\r\n return;\r\n }\r\n\r\n field.onChange(startOfDay(date));\r\n }}\r\n />\r\n <Separator />\r\n <div className=\"p-3\">\r\n <Button\r\n type=\"button\"\r\n variant=\"ghost\"\r\n disabled={effectiveDisabled}\r\n className=\"h-8 w-full justify-start px-2 font-normal\"\r\n onClick={() => setTimeOpen((current) => !current)}\r\n >\r\n <Clock className=\"mr-2 h-4 w-4\" />\r\n {displayHasTime && selectedDate ? format(selectedDate, \"p\") : \"Add time\"}\r\n </Button>\r\n {timeOpen ? (\r\n <TimePicker\r\n className=\"mt-2\"\r\n value={selectedDate}\r\n minuteStep={minuteStep}\r\n disabled={effectiveDisabled}\r\n onChange={(date) => {\r\n field.onChange(date);\r\n setTimeSet(true);\r\n }}\r\n onClear={() => {\r\n if (selectedDate) {\r\n field.onChange(startOfDay(selectedDate));\r\n }\r\n setTimeSet(false);\r\n }}\r\n />\r\n ) : null}\r\n </div>\r\n </PopoverContent>\r\n </Popover>\r\n </FieldLayout>\r\n );\r\n}\r\n\r\nDateTimePicker.displayName = \"DateTimePicker\";\r\n"],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export interface PasswordRevealToggleProps {
|
|
2
|
+
visible: boolean;
|
|
3
|
+
onToggle: () => void;
|
|
4
|
+
disabled?: boolean;
|
|
5
|
+
}
|
|
6
|
+
export declare function PasswordRevealToggle({ visible, onToggle, disabled, }: PasswordRevealToggleProps): import("react").JSX.Element;
|
|
7
|
+
//# sourceMappingURL=PasswordRevealToggle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PasswordRevealToggle.d.ts","sourceRoot":"","sources":["../../../src/components/Form/PasswordRevealToggle.tsx"],"names":[],"mappings":"AAIA,MAAM,WAAW,yBAAyB;IACzC,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,wBAAgB,oBAAoB,CAAC,EACpC,OAAO,EACP,QAAQ,EACR,QAAgB,GAChB,EAAE,yBAAyB,+BAc3B"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use client";
|
|
3
|
+
import { jsx } from "react/jsx-runtime";
|
|
4
|
+
import { Eye, EyeOff } from "lucide-react";
|
|
5
|
+
//#region src/components/Form/PasswordRevealToggle.tsx
|
|
6
|
+
function PasswordRevealToggle({ visible, onToggle, disabled = false }) {
|
|
7
|
+
return /* @__PURE__ */ jsx("button", {
|
|
8
|
+
type: "button",
|
|
9
|
+
onClick: onToggle,
|
|
10
|
+
disabled,
|
|
11
|
+
className: "text-muted-foreground hover:text-foreground transition-colors disabled:pointer-events-none disabled:opacity-50",
|
|
12
|
+
tabIndex: -1,
|
|
13
|
+
"aria-label": visible ? "Hide password" : "Show password",
|
|
14
|
+
"aria-pressed": visible,
|
|
15
|
+
children: visible ? /* @__PURE__ */ jsx(EyeOff, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx(Eye, { className: "h-4 w-4" })
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
//#endregion
|
|
19
|
+
export { PasswordRevealToggle };
|
|
20
|
+
|
|
21
|
+
//# sourceMappingURL=PasswordRevealToggle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PasswordRevealToggle.js","names":[],"sources":["../../../src/components/Form/PasswordRevealToggle.tsx"],"sourcesContent":["\"use client\";\n\nimport { Eye, EyeOff } from \"lucide-react\";\n\nexport interface PasswordRevealToggleProps {\n\tvisible: boolean;\n\tonToggle: () => void;\n\tdisabled?: boolean;\n}\n\nexport function PasswordRevealToggle({\n\tvisible,\n\tonToggle,\n\tdisabled = false,\n}: PasswordRevealToggleProps) {\n\treturn (\n\t\t<button\n\t\t\ttype=\"button\"\n\t\t\tonClick={onToggle}\n\t\t\tdisabled={disabled}\n\t\t\tclassName=\"text-muted-foreground hover:text-foreground transition-colors disabled:pointer-events-none disabled:opacity-50\"\n\t\t\ttabIndex={-1}\n\t\t\taria-label={visible ? \"Hide password\" : \"Show password\"}\n\t\t\taria-pressed={visible}\n\t\t>\n\t\t\t{visible ? <EyeOff className=\"h-4 w-4\" /> : <Eye className=\"h-4 w-4\" />}\n\t\t</button>\n\t);\n}\n"],"mappings":";;;;;AAUA,SAAgB,qBAAqB,EACpC,SACA,UACA,WAAW,SACkB;CAC7B,OACC,oBAAC,UAAD;EACC,MAAK;EACL,SAAS;EACC;EACV,WAAU;EACV,UAAU;EACV,cAAY,UAAU,kBAAkB;EACxC,gBAAc;EAEb,UAAA,UAAU,oBAAC,QAAD,EAAQ,WAAU,UAAW,CAAA,IAAI,oBAAC,KAAD,EAAK,WAAU,UAAW,CAAA;CAC/D,CAAA;AAEV"}
|
|
@@ -33,6 +33,11 @@ export interface TextBoxProps<TFieldValues extends FieldValues = FieldValues, TN
|
|
|
33
33
|
allowClear?: boolean;
|
|
34
34
|
/** Callback when clear is clicked */
|
|
35
35
|
onClear?: () => void;
|
|
36
|
+
/**
|
|
37
|
+
* Show an eye toggle for password fields.
|
|
38
|
+
* Defaults to true when `type="password"`.
|
|
39
|
+
*/
|
|
40
|
+
passwordToggle?: boolean;
|
|
36
41
|
/** External control (for use outside Form) */
|
|
37
42
|
control?: Control<TFieldValues>;
|
|
38
43
|
/** Field is required */
|