@capyx/components-library 0.0.1 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/README.md +250 -210
  2. package/dist/addons/AutocompleteInput.d.ts +40 -0
  3. package/dist/addons/AutocompleteInput.d.ts.map +1 -0
  4. package/dist/addons/AutocompleteInput.js +101 -0
  5. package/dist/addons/CharacterCountInput.d.ts +73 -0
  6. package/dist/addons/CharacterCountInput.d.ts.map +1 -0
  7. package/dist/addons/CharacterCountInput.js +130 -0
  8. package/dist/addons/index.d.ts +5 -0
  9. package/dist/addons/index.d.ts.map +1 -0
  10. package/dist/addons/index.js +2 -0
  11. package/dist/components/CheckInput.d.ts +49 -0
  12. package/dist/components/CheckInput.d.ts.map +1 -0
  13. package/dist/components/CheckInput.js +58 -0
  14. package/dist/components/DateInput.d.ts +63 -0
  15. package/dist/components/DateInput.d.ts.map +1 -0
  16. package/dist/components/DateInput.js +86 -0
  17. package/dist/components/FileInput.d.ts +102 -0
  18. package/dist/components/FileInput.d.ts.map +1 -0
  19. package/dist/components/FileInput.js +164 -0
  20. package/dist/components/RichTextInput.d.ts +34 -0
  21. package/dist/components/RichTextInput.d.ts.map +1 -0
  22. package/dist/components/RichTextInput.js +57 -0
  23. package/dist/components/SelectInput.d.ts +54 -0
  24. package/dist/components/SelectInput.d.ts.map +1 -0
  25. package/dist/components/SelectInput.js +64 -0
  26. package/dist/components/SwitchInput.d.ts +46 -0
  27. package/dist/components/SwitchInput.d.ts.map +1 -0
  28. package/dist/components/SwitchInput.js +53 -0
  29. package/dist/components/TagsInput.d.ts +35 -0
  30. package/dist/components/TagsInput.d.ts.map +1 -0
  31. package/dist/components/TagsInput.js +67 -0
  32. package/dist/components/TextAreaInput.d.ts +71 -0
  33. package/dist/components/TextAreaInput.d.ts.map +1 -0
  34. package/dist/components/TextAreaInput.js +113 -0
  35. package/dist/components/TextInput.d.ts +68 -0
  36. package/dist/components/TextInput.d.ts.map +1 -0
  37. package/dist/components/TextInput.js +77 -0
  38. package/dist/components/index.d.ts +10 -0
  39. package/dist/components/index.d.ts.map +1 -0
  40. package/dist/index.cjs +18 -0
  41. package/dist/index.d.ts +3 -0
  42. package/dist/index.d.ts.map +1 -0
  43. package/package.json +87 -72
  44. package/.storybook/main.ts +0 -33
  45. package/.storybook/preview.ts +0 -36
  46. package/.storybook/vitest.setup.ts +0 -7
  47. package/biome.json +0 -37
  48. package/lib/addons/CharacterCountInput.tsx +0 -204
  49. package/lib/addons/index.ts +0 -2
  50. package/lib/components/CheckInput.tsx +0 -126
  51. package/lib/components/DateInput.tsx +0 -179
  52. package/lib/components/FileInput.tsx +0 -353
  53. package/lib/components/RichTextInput.tsx +0 -112
  54. package/lib/components/SelectInput.tsx +0 -144
  55. package/lib/components/SwitchInput.tsx +0 -116
  56. package/lib/components/TagsInput.tsx +0 -118
  57. package/lib/components/TextAreaInput.tsx +0 -211
  58. package/lib/components/TextInput.tsx +0 -381
  59. package/stories/CharacterCountInput.stories.tsx +0 -104
  60. package/stories/CheckInput.stories.tsx +0 -80
  61. package/stories/DateInput.stories.tsx +0 -137
  62. package/stories/FileInput.stories.tsx +0 -125
  63. package/stories/RichTextInput.stories.tsx +0 -77
  64. package/stories/SelectInput.stories.tsx +0 -131
  65. package/stories/SwitchInput.stories.tsx +0 -80
  66. package/stories/TagsInput.stories.tsx +0 -69
  67. package/stories/TextAreaInput.stories.tsx +0 -117
  68. package/stories/TextInput.stories.tsx +0 -167
  69. package/vitest.config.ts +0 -37
  70. package/vitest.shims.d.ts +0 -1
  71. /package/{lib/components/index.ts → dist/components/index.js} +0 -0
  72. /package/{lib/index.ts → dist/index.js} +0 -0
@@ -0,0 +1,73 @@
1
+ import { type FC, type PropsWithChildren, type ReactNode } from 'react';
2
+ /**
3
+ * Props for the CharacterCountInput component
4
+ */
5
+ export type CharacterCountInputProps = PropsWithChildren<{
6
+ /** Array of valid HTML element types to monitor (e.g., ["text", "email", "textarea"]) */
7
+ validHTMLElements?: string[];
8
+ /** CSS class for the container wrapper */
9
+ containerClassName?: string;
10
+ /** CSS class for the character counter element */
11
+ counterClassName?: string;
12
+ /** CSS class applied when character count is normal */
13
+ normalClassName?: string;
14
+ /** CSS class applied when character count is near the limit */
15
+ warningClassName?: string;
16
+ /** CSS class applied when character count reaches the limit */
17
+ dangerClassName?: string;
18
+ /** Number of characters remaining before warning state (default: 10) */
19
+ warningThreshold?: number;
20
+ /** Custom function to format the counter display */
21
+ formatCounter?: (current: number, max: number) => ReactNode;
22
+ /** Whether to show the character counter (default: true) */
23
+ showCounter?: boolean;
24
+ /** Whether to show counter even when input is empty (default: false) */
25
+ showWhenEmpty?: boolean;
26
+ }>;
27
+ /**
28
+ * A wrapper component that adds a character counter to text inputs and textareas.
29
+ * Automatically detects the maxLength property from the child input and displays
30
+ * the current character count with visual feedback.
31
+ *
32
+ * Features:
33
+ * - Automatic character counting from input/textarea children
34
+ * - Visual feedback with customizable warning and danger states
35
+ * - Configurable warning threshold
36
+ * - Custom counter formatting
37
+ * - Support for multiple input types (text, email, password, textarea, etc.)
38
+ * - Show/hide counter toggle
39
+ *
40
+ * @example
41
+ * // Basic usage with TextInput
42
+ * <CharacterCountInput>
43
+ * <TextInput
44
+ * name="bio"
45
+ * type="text"
46
+ * maxLength={100}
47
+ * placeholder="Enter your bio"
48
+ * />
49
+ * </CharacterCountInput>
50
+ *
51
+ * @example
52
+ * // With custom styling and warning threshold
53
+ * <CharacterCountInput
54
+ * warningThreshold={20}
55
+ * normalClassName="text-muted"
56
+ * warningClassName="text-warning"
57
+ * dangerClassName="text-danger"
58
+ * >
59
+ * <TextAreaInput name="message" maxLength={200} />
60
+ * </CharacterCountInput>
61
+ *
62
+ * @example
63
+ * // With custom counter format
64
+ * <CharacterCountInput
65
+ * formatCounter={(current, max) => (
66
+ * <span>{max - current} characters remaining</span>
67
+ * )}
68
+ * >
69
+ * <TextInput name="title" maxLength={50} />
70
+ * </CharacterCountInput>
71
+ */
72
+ export declare const CharacterCountInput: FC<CharacterCountInputProps>;
73
+ //# sourceMappingURL=CharacterCountInput.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CharacterCountInput.d.ts","sourceRoot":"","sources":["../../lib/addons/CharacterCountInput.tsx"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,EAAE,EACP,KAAK,iBAAiB,EAEtB,KAAK,SAAS,EAId,MAAM,OAAO,CAAC;AAaf;;GAEG;AACH,MAAM,MAAM,wBAAwB,GAAG,iBAAiB,CAAC;IACxD,yFAAyF;IACzF,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,0CAA0C;IAC1C,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,kDAAkD;IAClD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,uDAAuD;IACvD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,+DAA+D;IAC/D,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,+DAA+D;IAC/D,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,wEAAwE;IACxE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,oDAAoD;IACpD,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,SAAS,CAAC;IAC5D,4DAA4D;IAC5D,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,wEAAwE;IACxE,aAAa,CAAC,EAAE,OAAO,CAAC;CACxB,CAAC,CAAC;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,eAAO,MAAM,mBAAmB,EAAE,EAAE,CAAC,wBAAwB,CA+G5D,CAAC"}
@@ -0,0 +1,130 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useRef, useState, } from 'react';
3
+ import { Form } from 'react-bootstrap';
4
+ const _DEFAULT_VALID_HTML_ELEMENTS = [
5
+ 'text',
6
+ 'email',
7
+ 'password',
8
+ 'search',
9
+ 'tel',
10
+ 'url',
11
+ 'textarea',
12
+ ];
13
+ /**
14
+ * A wrapper component that adds a character counter to text inputs and textareas.
15
+ * Automatically detects the maxLength property from the child input and displays
16
+ * the current character count with visual feedback.
17
+ *
18
+ * Features:
19
+ * - Automatic character counting from input/textarea children
20
+ * - Visual feedback with customizable warning and danger states
21
+ * - Configurable warning threshold
22
+ * - Custom counter formatting
23
+ * - Support for multiple input types (text, email, password, textarea, etc.)
24
+ * - Show/hide counter toggle
25
+ *
26
+ * @example
27
+ * // Basic usage with TextInput
28
+ * <CharacterCountInput>
29
+ * <TextInput
30
+ * name="bio"
31
+ * type="text"
32
+ * maxLength={100}
33
+ * placeholder="Enter your bio"
34
+ * />
35
+ * </CharacterCountInput>
36
+ *
37
+ * @example
38
+ * // With custom styling and warning threshold
39
+ * <CharacterCountInput
40
+ * warningThreshold={20}
41
+ * normalClassName="text-muted"
42
+ * warningClassName="text-warning"
43
+ * dangerClassName="text-danger"
44
+ * >
45
+ * <TextAreaInput name="message" maxLength={200} />
46
+ * </CharacterCountInput>
47
+ *
48
+ * @example
49
+ * // With custom counter format
50
+ * <CharacterCountInput
51
+ * formatCounter={(current, max) => (
52
+ * <span>{max - current} characters remaining</span>
53
+ * )}
54
+ * >
55
+ * <TextInput name="title" maxLength={50} />
56
+ * </CharacterCountInput>
57
+ */
58
+ export const CharacterCountInput = ({ validHTMLElements: _validHTMLElements, children, containerClassName = 'text-end', counterClassName = '', normalClassName = 'text-muted', warningClassName = 'text-warning', dangerClassName = 'text-danger', warningThreshold = 10, formatCounter, showCounter = true, showWhenEmpty = false, }) => {
59
+ const containerRef = useRef(null);
60
+ const [characterCount, setCharacterCount] = useState(0);
61
+ const [maxLength, setMaxLength] = useState(null);
62
+ useEffect(() => {
63
+ if (!containerRef.current)
64
+ return;
65
+ // Extract maxLength from child props
66
+ const childProps = children?.props;
67
+ if (childProps?.maxLength) {
68
+ setMaxLength(childProps.maxLength);
69
+ }
70
+ // Use MutationObserver to wait for input element to be rendered
71
+ const findAndAttachInput = () => {
72
+ const input = containerRef.current?.querySelector('input, textarea');
73
+ if (!input)
74
+ return null;
75
+ const inputReader = () => {
76
+ setCharacterCount(input.value?.length ?? 0);
77
+ };
78
+ input.addEventListener('input', inputReader);
79
+ input.addEventListener('keyup', inputReader);
80
+ inputReader(); // Initial read
81
+ return () => {
82
+ input.removeEventListener('input', inputReader);
83
+ input.removeEventListener('keyup', inputReader);
84
+ };
85
+ };
86
+ // Try to find input immediately
87
+ let cleanup = findAndAttachInput();
88
+ // If not found, wait for it to be rendered
89
+ if (!cleanup && containerRef.current) {
90
+ const observer = new MutationObserver(() => {
91
+ if (!cleanup) {
92
+ cleanup = findAndAttachInput();
93
+ if (cleanup) {
94
+ observer.disconnect();
95
+ }
96
+ }
97
+ });
98
+ observer.observe(containerRef.current, {
99
+ childList: true,
100
+ subtree: true,
101
+ });
102
+ return () => {
103
+ observer.disconnect();
104
+ cleanup?.();
105
+ };
106
+ }
107
+ return cleanup || undefined;
108
+ }, [children]);
109
+ const getCounterClassName = () => {
110
+ if (maxLength === null)
111
+ return normalClassName;
112
+ if (characterCount === maxLength)
113
+ return dangerClassName;
114
+ if (characterCount >= maxLength - warningThreshold)
115
+ return warningClassName;
116
+ return normalClassName;
117
+ };
118
+ const renderCounter = () => {
119
+ if (!showCounter || maxLength === null)
120
+ return null;
121
+ if (!showWhenEmpty && characterCount === 0)
122
+ return null;
123
+ const className = `${counterClassName} ${getCounterClassName()}`.trim();
124
+ const content = formatCounter
125
+ ? formatCounter(characterCount, maxLength)
126
+ : `${characterCount} / ${maxLength}`;
127
+ return _jsx(Form.Text, { className: className, children: content });
128
+ };
129
+ return (_jsxs("div", { ref: containerRef, className: containerClassName, children: [children, renderCounter()] }));
130
+ };
@@ -0,0 +1,5 @@
1
+ export type { AutocompleteInputProps } from './AutocompleteInput';
2
+ export { AutocompleteInput } from './AutocompleteInput';
3
+ export type { CharacterCountInputProps } from './CharacterCountInput';
4
+ export { CharacterCountInput } from './CharacterCountInput';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../lib/addons/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,YAAY,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AACtE,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { AutocompleteInput } from './AutocompleteInput';
2
+ export { CharacterCountInput } from './CharacterCountInput';
@@ -0,0 +1,49 @@
1
+ import type { FC } from 'react';
2
+ /**
3
+ * Props for the CheckInput component
4
+ */
5
+ export type CheckInputProps = {
6
+ /** The name of the checkbox input field */
7
+ name: string;
8
+ /** Label text displayed next to the checkbox */
9
+ label?: string;
10
+ /** Whether the checkbox is required */
11
+ required?: boolean;
12
+ /** Current checked state (standalone mode) */
13
+ value?: boolean;
14
+ /** Callback function called when the checked state changes */
15
+ onChange?: (checked: boolean) => void;
16
+ /** Callback function called when the checkbox loses focus */
17
+ onBlur?: () => void;
18
+ /** Whether the checkbox is disabled */
19
+ disabled?: boolean;
20
+ /** Custom HTML id for the checkbox element */
21
+ id?: string;
22
+ };
23
+ /**
24
+ * CheckInput - A checkbox input component with react-hook-form integration
25
+ *
26
+ * Provides a checkbox input that works both standalone and with react-hook-form.
27
+ * Automatically integrates with FormProvider when available, providing validation
28
+ * and error handling.
29
+ *
30
+ * @example
31
+ * ```tsx
32
+ * // With react-hook-form
33
+ * <CheckInput
34
+ * name="agreeToTerms"
35
+ * label="I agree to the terms"
36
+ * required
37
+ * />
38
+ *
39
+ * // Standalone mode
40
+ * <CheckInput
41
+ * name="newsletter"
42
+ * label="Subscribe to newsletter"
43
+ * value={subscribed}
44
+ * onChange={setSubscribed}
45
+ * />
46
+ * ```
47
+ */
48
+ export declare const CheckInput: FC<CheckInputProps>;
49
+ //# sourceMappingURL=CheckInput.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CheckInput.d.ts","sourceRoot":"","sources":["../../lib/components/CheckInput.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAIhC;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG;IAC7B,2CAA2C;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,gDAAgD;IAChD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uCAAuC;IACvC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,8CAA8C;IAC9C,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IACtC,6DAA6D;IAC7D,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,uCAAuC;IACvC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,8CAA8C;IAC9C,EAAE,CAAC,EAAE,MAAM,CAAC;CACZ,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,eAAO,MAAM,UAAU,EAAE,EAAE,CAAC,eAAe,CA0E1C,CAAC"}
@@ -0,0 +1,58 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Form } from 'react-bootstrap';
3
+ import { Controller, useFormContext } from 'react-hook-form';
4
+ /**
5
+ * CheckInput - A checkbox input component with react-hook-form integration
6
+ *
7
+ * Provides a checkbox input that works both standalone and with react-hook-form.
8
+ * Automatically integrates with FormProvider when available, providing validation
9
+ * and error handling.
10
+ *
11
+ * @example
12
+ * ```tsx
13
+ * // With react-hook-form
14
+ * <CheckInput
15
+ * name="agreeToTerms"
16
+ * label="I agree to the terms"
17
+ * required
18
+ * />
19
+ *
20
+ * // Standalone mode
21
+ * <CheckInput
22
+ * name="newsletter"
23
+ * label="Subscribe to newsletter"
24
+ * value={subscribed}
25
+ * onChange={setSubscribed}
26
+ * />
27
+ * ```
28
+ */
29
+ export const CheckInput = ({ name, label, required = false, value, onChange, onBlur, disabled = false, id, }) => {
30
+ const formContext = useFormContext();
31
+ // Helper to safely get nested error
32
+ const getFieldError = (fieldName) => {
33
+ try {
34
+ const error = formContext?.formState?.errors?.[fieldName];
35
+ return error?.message;
36
+ }
37
+ catch {
38
+ return undefined;
39
+ }
40
+ };
41
+ const errorMessage = getFieldError(name);
42
+ const inputId = id || `check-input-${name}`;
43
+ // Integrated with react-hook-form
44
+ if (formContext) {
45
+ return (_jsx(Controller, { name: name, control: formContext.control, rules: {
46
+ required: required ? `${label || 'This field'} is required` : false,
47
+ }, render: ({ field }) => (_jsx(Form.Check, { ...field, id: inputId, type: "checkbox", label: label, checked: field.value ?? false, onChange: (e) => {
48
+ const checked = e.target.checked;
49
+ field.onChange(checked);
50
+ onChange?.(checked);
51
+ }, onBlur: () => {
52
+ field.onBlur();
53
+ onBlur?.();
54
+ }, disabled: disabled, required: required, isInvalid: !!errorMessage, feedback: errorMessage, feedbackType: "invalid" })) }));
55
+ }
56
+ // Standalone mode (no form context)
57
+ return (_jsx(Form.Check, { id: inputId, type: "checkbox", label: label, checked: value ?? false, onChange: (e) => onChange?.(e.target.checked), onBlur: onBlur, disabled: disabled, required: required }));
58
+ };
@@ -0,0 +1,63 @@
1
+ import type { FC } from 'react';
2
+ /**
3
+ * Props for the DateInput component
4
+ */
5
+ export type DateInputProps = {
6
+ /** The name of the date input field */
7
+ name: string;
8
+ /** Label text displayed for the date picker */
9
+ label?: string;
10
+ /** Current date value (standalone mode) */
11
+ value?: Date | null;
12
+ /** Callback function called when the date changes */
13
+ onChange?: (date: Date | null) => void;
14
+ /** Callback function called when the input loses focus */
15
+ onBlur?: () => void;
16
+ /** Whether the date field is required */
17
+ required?: boolean;
18
+ /** Whether the date picker is disabled */
19
+ disabled?: boolean;
20
+ /** Minimum selectable date */
21
+ minDate?: Date;
22
+ /** Maximum selectable date */
23
+ maxDate?: Date;
24
+ /** Date format string (default: "DD/MM/YYYY") */
25
+ dateFormat?: string;
26
+ /** Size of the text field (default: "small") */
27
+ textFieldSize?: 'small' | 'medium';
28
+ /** Whether to disable future dates */
29
+ disableFuture?: boolean;
30
+ /** Whether to disable past dates */
31
+ disablePast?: boolean;
32
+ /** Which calendar views to display */
33
+ views?: Array<'year' | 'month' | 'day'>;
34
+ };
35
+ /**
36
+ * DateInput - A date picker component using Material-UI with react-hook-form integration
37
+ *
38
+ * Provides a date picker with calendar interface that works both standalone and with
39
+ * react-hook-form. Uses MUI DatePicker internally with customizable date ranges,
40
+ * formats, and validation.
41
+ *
42
+ * @example
43
+ * ```tsx
44
+ * // With react-hook-form
45
+ * <DateInput
46
+ * name="birthdate"
47
+ * label="Date of Birth"
48
+ * required
49
+ * disableFuture
50
+ * />
51
+ *
52
+ * // Standalone mode
53
+ * <DateInput
54
+ * name="appointmentDate"
55
+ * label="Select Date"
56
+ * value={selectedDate}
57
+ * onChange={setSelectedDate}
58
+ * minDate={new Date()}
59
+ * />
60
+ * ```
61
+ */
62
+ export declare const DateInput: FC<DateInputProps>;
63
+ //# sourceMappingURL=DateInput.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DateInput.d.ts","sourceRoot":"","sources":["../../lib/components/DateInput.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAIhC;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG;IAC5B,uCAAuC;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,+CAA+C;IAC/C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2CAA2C;IAC3C,KAAK,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IACpB,qDAAqD;IACrD,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,KAAK,IAAI,CAAC;IACvC,0DAA0D;IAC1D,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,yCAAyC;IACzC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,0CAA0C;IAC1C,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,8BAA8B;IAC9B,OAAO,CAAC,EAAE,IAAI,CAAC;IACf,8BAA8B;IAC9B,OAAO,CAAC,EAAE,IAAI,CAAC;IACf,iDAAiD;IACjD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gDAAgD;IAChD,aAAa,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;IACnC,sCAAsC;IACtC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,oCAAoC;IACpC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,sCAAsC;IACtC,KAAK,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,OAAO,GAAG,KAAK,CAAC,CAAC;CACxC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,eAAO,MAAM,SAAS,EAAE,EAAE,CAAC,cAAc,CAgHxC,CAAC"}
@@ -0,0 +1,86 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { DatePicker } from '@mui/x-date-pickers';
3
+ import dayjs from 'dayjs';
4
+ import { Form } from 'react-bootstrap';
5
+ import { Controller, useFormContext } from 'react-hook-form';
6
+ /**
7
+ * DateInput - A date picker component using Material-UI with react-hook-form integration
8
+ *
9
+ * Provides a date picker with calendar interface that works both standalone and with
10
+ * react-hook-form. Uses MUI DatePicker internally with customizable date ranges,
11
+ * formats, and validation.
12
+ *
13
+ * @example
14
+ * ```tsx
15
+ * // With react-hook-form
16
+ * <DateInput
17
+ * name="birthdate"
18
+ * label="Date of Birth"
19
+ * required
20
+ * disableFuture
21
+ * />
22
+ *
23
+ * // Standalone mode
24
+ * <DateInput
25
+ * name="appointmentDate"
26
+ * label="Select Date"
27
+ * value={selectedDate}
28
+ * onChange={setSelectedDate}
29
+ * minDate={new Date()}
30
+ * />
31
+ * ```
32
+ */
33
+ export const DateInput = ({ name, label, value, onChange, onBlur, required = false, disabled = false, minDate, maxDate, dateFormat = 'DD/MM/YYYY', textFieldSize = 'small', disableFuture = false, disablePast = false, views, }) => {
34
+ const formContext = useFormContext();
35
+ // Helper to safely get nested error
36
+ const getFieldError = (fieldName) => {
37
+ try {
38
+ const error = formContext?.formState?.errors?.[fieldName];
39
+ return error?.message;
40
+ }
41
+ catch {
42
+ return undefined;
43
+ }
44
+ };
45
+ const errorMessage = getFieldError(name);
46
+ // Convert Date to Dayjs
47
+ const convertToDateValue = (date) => {
48
+ if (!date)
49
+ return undefined;
50
+ return dayjs(date);
51
+ };
52
+ // Integrated with react-hook-form
53
+ if (formContext) {
54
+ return (_jsx(Controller, { name: name, control: formContext.control, rules: {
55
+ required: required ? `${label || 'This field'} is required` : false,
56
+ }, render: ({ field }) => (_jsx(Form.Group, { children: _jsx(DatePicker, { label: label, value: convertToDateValue(field.value), onChange: (newValue) => {
57
+ const dateValue = newValue?.isValid()
58
+ ? newValue.toDate()
59
+ : null;
60
+ field.onChange(dateValue);
61
+ onChange?.(dateValue);
62
+ }, disabled: disabled, format: dateFormat, minDate: convertToDateValue(minDate), maxDate: convertToDateValue(maxDate), disableFuture: disableFuture, disablePast: disablePast, views: views, slotProps: {
63
+ textField: {
64
+ size: textFieldSize,
65
+ required: required,
66
+ error: !!errorMessage,
67
+ helperText: errorMessage,
68
+ onBlur: () => {
69
+ field.onBlur();
70
+ onBlur?.();
71
+ },
72
+ },
73
+ } }) })) }));
74
+ }
75
+ // Standalone mode (no form context)
76
+ return (_jsx(Form.Group, { children: _jsx(DatePicker, { label: label, value: convertToDateValue(value), onChange: (newValue) => {
77
+ const dateValue = newValue?.isValid() ? newValue.toDate() : null;
78
+ onChange?.(dateValue);
79
+ }, disabled: disabled, format: dateFormat, minDate: convertToDateValue(minDate), maxDate: convertToDateValue(maxDate), disableFuture: disableFuture, disablePast: disablePast, views: views, slotProps: {
80
+ textField: {
81
+ size: textFieldSize,
82
+ required: required,
83
+ onBlur: onBlur,
84
+ },
85
+ } }) }));
86
+ };
@@ -0,0 +1,102 @@
1
+ import { type FC, type ReactNode } from 'react';
2
+ /**
3
+ * Props for the FileInput component
4
+ */
5
+ export type FileInputProps = {
6
+ /** The name of the file input field for form integration */
7
+ name?: string;
8
+ /** File types to accept (e.g., "image/*", ".pdf,.doc") */
9
+ accept?: string;
10
+ /** Whether to allow selecting multiple files */
11
+ multiple?: boolean;
12
+ /** Callback fired when file selection changes */
13
+ onChange?: (files: File | File[] | null) => void;
14
+ /** Callback fired when upload process starts */
15
+ onUploadStart?: () => void;
16
+ /** Callback fired when upload completes successfully */
17
+ onUploadComplete?: () => void;
18
+ /** Callback fired when upload encounters an error */
19
+ onUploadError?: (error: Error) => void;
20
+ /** Whether the file input is disabled */
21
+ disabled?: boolean;
22
+ /** Maximum file size in bytes */
23
+ maxSize?: number;
24
+ /** CSS class for the container element */
25
+ containerClassName?: string;
26
+ /** CSS class for the label element */
27
+ labelClassName?: string;
28
+ /** CSS class for the button element */
29
+ buttonClassName?: string;
30
+ /** CSS class for the file info text */
31
+ fileInfoClassName?: string;
32
+ /** CSS class for error messages */
33
+ errorClassName?: string;
34
+ /** Label text or element displayed above the input */
35
+ label?: ReactNode;
36
+ /** Text or element displayed on the button */
37
+ buttonText?: ReactNode;
38
+ /** Text shown when no file is selected */
39
+ noFileText?: ReactNode;
40
+ /** Text shown during file upload */
41
+ uploadingText?: ReactNode;
42
+ /** Custom function to format the file info display */
43
+ formatFileInfo?: (files: File | File[]) => ReactNode;
44
+ /** Custom validation function for individual files */
45
+ validateFile?: (file: File) => {
46
+ valid: boolean;
47
+ error?: string;
48
+ };
49
+ /** Whether file selection is required */
50
+ required?: boolean;
51
+ };
52
+ /**
53
+ * A customizable file input component with validation, upload lifecycle hooks,
54
+ * and react-hook-form integration.
55
+ *
56
+ * Features:
57
+ * - Single or multiple file selection
58
+ * - File type filtering via accept attribute
59
+ * - File size validation with configurable max size
60
+ * - Custom file validation logic
61
+ * - Upload lifecycle callbacks (start, complete, error)
62
+ * - Fully customizable UI with className props
63
+ * - Integration with react-hook-form for form validation
64
+ * - Custom formatting for file information display
65
+ *
66
+ * @example
67
+ * // Basic file upload with react-hook-form
68
+ * <FileInput
69
+ * name="avatar"
70
+ * label="Profile Picture"
71
+ * accept="image/*"
72
+ * required
73
+ * maxSize={5 * 1024 * 1024} // 5MB
74
+ * />
75
+ *
76
+ * @example
77
+ * // Multiple files with custom validation
78
+ * <FileInput
79
+ * name="documents"
80
+ * label="Upload Documents"
81
+ * multiple
82
+ * accept=".pdf,.doc,.docx"
83
+ * validateFile={(file) => {
84
+ * if (file.name.length > 100) {
85
+ * return { valid: false, error: "Filename too long" };
86
+ * }
87
+ * return { valid: true };
88
+ * }}
89
+ * onChange={(files) => console.log(files)}
90
+ * />
91
+ *
92
+ * @example
93
+ * // With upload lifecycle hooks
94
+ * <FileInput
95
+ * name="report"
96
+ * onUploadStart={() => console.log("Starting upload...")}
97
+ * onUploadComplete={() => console.log("Upload complete!")}
98
+ * onUploadError={(error) => console.error(error)}
99
+ * />
100
+ */
101
+ export declare const FileInput: FC<FileInputProps>;
102
+ //# sourceMappingURL=FileInput.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FileInput.d.ts","sourceRoot":"","sources":["../../lib/components/FileInput.tsx"],"names":[],"mappings":"AAAA,OAAO,EAEN,KAAK,EAAE,EACP,KAAK,SAAS,EAGd,MAAM,OAAO,CAAC;AAIf;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG;IAC5B,4DAA4D;IAC5D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,0DAA0D;IAC1D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gDAAgD;IAChD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,iDAAiD;IACjD,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,GAAG,IAAI,EAAE,GAAG,IAAI,KAAK,IAAI,CAAC;IACjD,gDAAgD;IAChD,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,wDAAwD;IACxD,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B,qDAAqD;IACrD,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACvC,yCAAyC;IACzC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,iCAAiC;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,0CAA0C;IAC1C,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,sCAAsC;IACtC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,uCAAuC;IACvC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,uCAAuC;IACvC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,mCAAmC;IACnC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,sDAAsD;IACtD,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,8CAA8C;IAC9C,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,0CAA0C;IAC1C,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,oCAAoC;IACpC,aAAa,CAAC,EAAE,SAAS,CAAC;IAC1B,sDAAsD;IACtD,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,GAAG,IAAI,EAAE,KAAK,SAAS,CAAC;IACrD,sDAAsD;IACtD,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAClE,yCAAyC;IACzC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AACH,eAAO,MAAM,SAAS,EAAE,EAAE,CAAC,cAAc,CAqPxC,CAAC"}