@fovestta2/web-react 1.1.0

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 (55) hide show
  1. package/dist/components/AddUpdateForm.d.ts +64 -0
  2. package/dist/components/AddUpdateForm.js +244 -0
  3. package/dist/components/FvCheckbox.d.ts +12 -0
  4. package/dist/components/FvCheckbox.js +19 -0
  5. package/dist/components/FvDateField.d.ts +19 -0
  6. package/dist/components/FvDateField.js +123 -0
  7. package/dist/components/FvDocumentField.d.ts +22 -0
  8. package/dist/components/FvDocumentField.js +242 -0
  9. package/dist/components/FvDropdown.d.ts +33 -0
  10. package/dist/components/FvDropdown.js +346 -0
  11. package/dist/components/FvEmailField.d.ts +18 -0
  12. package/dist/components/FvEmailField.js +103 -0
  13. package/dist/components/FvEntryField.d.ts +21 -0
  14. package/dist/components/FvEntryField.js +101 -0
  15. package/dist/components/FvEsiField.d.ts +16 -0
  16. package/dist/components/FvEsiField.js +92 -0
  17. package/dist/components/FvFileSelector.d.ts +22 -0
  18. package/dist/components/FvFileSelector.js +153 -0
  19. package/dist/components/FvIbanField.d.ts +16 -0
  20. package/dist/components/FvIbanField.js +92 -0
  21. package/dist/components/FvIfscField.d.ts +16 -0
  22. package/dist/components/FvIfscField.js +92 -0
  23. package/dist/components/FvImageSelector.d.ts +22 -0
  24. package/dist/components/FvImageSelector.js +317 -0
  25. package/dist/components/FvMicrField.d.ts +16 -0
  26. package/dist/components/FvMicrField.js +92 -0
  27. package/dist/components/FvMonthYearField.d.ts +19 -0
  28. package/dist/components/FvMonthYearField.js +139 -0
  29. package/dist/components/FvNameCode.d.ts +23 -0
  30. package/dist/components/FvNameCode.js +239 -0
  31. package/dist/components/FvNumberField.d.ts +21 -0
  32. package/dist/components/FvNumberField.js +98 -0
  33. package/dist/components/FvPasswordField.d.ts +18 -0
  34. package/dist/components/FvPasswordField.js +114 -0
  35. package/dist/components/FvPfField.d.ts +16 -0
  36. package/dist/components/FvPfField.js +106 -0
  37. package/dist/components/FvPhoneField.d.ts +16 -0
  38. package/dist/components/FvPhoneField.js +95 -0
  39. package/dist/components/FvRadioGroup.d.ts +20 -0
  40. package/dist/components/FvRadioGroup.js +64 -0
  41. package/dist/components/FvRichTextEditor.d.ts +20 -0
  42. package/dist/components/FvRichTextEditor.js +199 -0
  43. package/dist/components/FvServicePeriod.d.ts +10 -0
  44. package/dist/components/FvServicePeriod.js +122 -0
  45. package/dist/components/FvTimeField.d.ts +17 -0
  46. package/dist/components/FvTimeField.js +190 -0
  47. package/dist/components/FvToggle.d.ts +12 -0
  48. package/dist/components/FvToggle.js +39 -0
  49. package/dist/components/FvUanField.d.ts +16 -0
  50. package/dist/components/FvUanField.js +92 -0
  51. package/dist/components/QueryForm.d.ts +31 -0
  52. package/dist/components/QueryForm.js +214 -0
  53. package/dist/index.d.ts +28 -0
  54. package/dist/index.js +47 -0
  55. package/package.json +39 -0
@@ -0,0 +1,106 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.FvPfField = void 0;
27
+ const react_1 = __importStar(require("react"));
28
+ const validation_engine_1 = require("@fovestta2/validation-engine");
29
+ const FvPfField = ({ label = 'PF Number', value, schema, disabled = false, className = '', inputClassName = '', labelClassName = '', errorClassName = '', onChange, onBlur, onFocus, }) => {
30
+ const [errorMessage, setErrorMessage] = (0, react_1.useState)(null);
31
+ const activeSchema = schema || {
32
+ controlType: 'PfField',
33
+ errorPriority: ['required', 'regex'],
34
+ rules: [
35
+ {
36
+ name: 'regex',
37
+ params: {
38
+ pattern: '^[A-Z]{2}/[A-Z]{3}/[0-9]{7}/[0-9]{3}/[0-9]{7}$'
39
+ },
40
+ errorKey: 'ERR_PF_INVALID'
41
+ }
42
+ ]
43
+ };
44
+ (0, react_1.useEffect)(() => {
45
+ validateValue(value);
46
+ }, [value, activeSchema]);
47
+ const validateValue = (val) => {
48
+ if (!activeSchema)
49
+ return;
50
+ const result = validation_engine_1.Validator.validate(val, activeSchema);
51
+ if (!result.isValid && result.errorKey) {
52
+ setErrorMessage(result.errorKey);
53
+ }
54
+ else {
55
+ setErrorMessage(null);
56
+ }
57
+ };
58
+ const handleInput = (e) => {
59
+ let rawVal = e.target.value;
60
+ const formatted = rawVal.replace(/[^a-zA-Z0-9/]/g, '').toUpperCase();
61
+ onChange(formatted);
62
+ };
63
+ const handleBlur = (e) => {
64
+ validateValue(value);
65
+ if (onBlur)
66
+ onBlur();
67
+ };
68
+ const handleFocus = (e) => {
69
+ if (onFocus)
70
+ onFocus();
71
+ };
72
+ const isRequired = () => {
73
+ var _a;
74
+ return ((_a = activeSchema === null || activeSchema === void 0 ? void 0 : activeSchema.rules) === null || _a === void 0 ? void 0 : _a.some((r) => { var _a; return r.name === 'required' && ((_a = r.params) === null || _a === void 0 ? void 0 : _a['enabled']); })) || false;
75
+ };
76
+ const getErrorMessage = () => {
77
+ if (!errorMessage)
78
+ return '';
79
+ const errorMessages = {
80
+ ERR_REQUIRED: 'PF Number is required',
81
+ ERR_PF_INVALID: 'Invalid PF Number format (e.g. AA/AAA/0000000/000/0000000)',
82
+ ERR_REGEX_MISMATCH: 'Invalid PF Number format'
83
+ };
84
+ return errorMessages[errorMessage] || errorMessage;
85
+ };
86
+ return (react_1.default.createElement("div", { className: `fv-field-container ${className}`, style: { marginBottom: '16px', display: 'flex', flexDirection: 'column' } },
87
+ label && (react_1.default.createElement("label", { className: `fv-label ${labelClassName}`, style: { marginBottom: '6px', fontSize: '14px', fontWeight: 500, color: disabled ? '#999' : '#333' } },
88
+ label,
89
+ isRequired() && react_1.default.createElement("span", { className: "fv-required", style: { color: '#dc3545', fontWeight: 'bold' } }, " *"))),
90
+ react_1.default.createElement("input", { type: "text", value: value, onChange: handleInput, onBlur: handleBlur, onFocus: handleFocus, disabled: disabled, className: `fv-input ${errorMessage ? 'fv-input-error' : ''} ${inputClassName}`, style: {
91
+ padding: '10px',
92
+ border: errorMessage ? '1px solid #dc3545' : '1px solid #ccc',
93
+ borderRadius: '4px',
94
+ fontSize: '14px',
95
+ backgroundColor: disabled ? '#f5f5f5' : '#fff',
96
+ cursor: disabled ? 'not-allowed' : 'text',
97
+ outline: 'none',
98
+ boxSizing: 'border-box',
99
+ width: '100%',
100
+ ...(disabled ? { opacity: 0.6 } : {})
101
+ } }),
102
+ errorMessage && (react_1.default.createElement("span", { className: `fv-error-text ${errorClassName}`, style: { marginTop: '4px', fontSize: '12px', color: '#dc3545' } },
103
+ "\u26A0 ",
104
+ getErrorMessage()))));
105
+ };
106
+ exports.FvPfField = FvPfField;
@@ -0,0 +1,16 @@
1
+ import React from 'react';
2
+ import { ValidationSchema } from '@fovestta2/validation-engine';
3
+ export interface FvPhoneFieldProps {
4
+ label?: string;
5
+ value: string;
6
+ schema?: ValidationSchema;
7
+ disabled?: boolean;
8
+ className?: string;
9
+ inputClassName?: string;
10
+ labelClassName?: string;
11
+ errorClassName?: string;
12
+ onChange: (value: string) => void;
13
+ onBlur?: () => void;
14
+ onFocus?: () => void;
15
+ }
16
+ export declare const FvPhoneField: React.FC<FvPhoneFieldProps>;
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.FvPhoneField = void 0;
27
+ const react_1 = __importStar(require("react"));
28
+ const validation_engine_1 = require("@fovestta2/validation-engine");
29
+ const FvPhoneField = ({ label = 'Phone Number', value, schema, disabled = false, className = '', inputClassName = '', labelClassName = '', errorClassName = '', onChange, onBlur, onFocus, }) => {
30
+ const [errorMessage, setErrorMessage] = (0, react_1.useState)(null);
31
+ (0, react_1.useEffect)(() => {
32
+ validateValue(value);
33
+ }, [value, schema]);
34
+ const validateValue = (val) => {
35
+ if (!schema)
36
+ return;
37
+ const result = validation_engine_1.Validator.validate(val, schema);
38
+ if (!result.isValid && result.errorKey) {
39
+ setErrorMessage(result.errorKey);
40
+ }
41
+ else {
42
+ setErrorMessage(null);
43
+ }
44
+ };
45
+ const handleInput = (e) => {
46
+ let rawVal = e.target.value;
47
+ const numericValue = rawVal.replace(/[^0-9]/g, '');
48
+ const truncatedValue = numericValue.substring(0, 10);
49
+ onChange(truncatedValue);
50
+ };
51
+ const handleBlur = (e) => {
52
+ validateValue(value);
53
+ if (onBlur)
54
+ onBlur();
55
+ };
56
+ const handleFocus = (e) => {
57
+ if (onFocus)
58
+ onFocus();
59
+ };
60
+ const isRequired = () => {
61
+ var _a;
62
+ return ((_a = schema === null || schema === void 0 ? void 0 : schema.rules) === null || _a === void 0 ? void 0 : _a.some((r) => { var _a; return r.name === 'required' && ((_a = r.params) === null || _a === void 0 ? void 0 : _a['enabled']); })) || false;
63
+ };
64
+ const getErrorMessage = () => {
65
+ if (!errorMessage)
66
+ return '';
67
+ const errorMessages = {
68
+ ERR_REQUIRED: 'Phone number is required',
69
+ ERR_MIN_LENGTH: 'Invalid phone number',
70
+ ERR_MAX_LENGTH: 'Invalid phone number',
71
+ ERR_REGEX_MISMATCH: 'Invalid phone number format',
72
+ };
73
+ return errorMessages[errorMessage] || errorMessage;
74
+ };
75
+ return (react_1.default.createElement("div", { className: `fv-field-container ${className}`, style: { marginBottom: '16px', display: 'flex', flexDirection: 'column' } },
76
+ label && (react_1.default.createElement("label", { className: `fv-label ${labelClassName}`, style: { marginBottom: '6px', fontSize: '14px', fontWeight: 500, color: disabled ? '#999' : '#333' } },
77
+ label,
78
+ isRequired() && react_1.default.createElement("span", { className: "fv-required", style: { color: '#dc3545', fontWeight: 'bold' } }, " *"))),
79
+ react_1.default.createElement("input", { type: "tel", value: value, onChange: handleInput, onBlur: handleBlur, onFocus: handleFocus, disabled: disabled, className: `fv-input ${errorMessage ? 'fv-input-error' : ''} ${inputClassName}`, style: {
80
+ padding: '10px',
81
+ border: errorMessage ? '1px solid #dc3545' : '1px solid #ccc',
82
+ borderRadius: '4px',
83
+ fontSize: '14px',
84
+ backgroundColor: disabled ? '#f5f5f5' : '#fff',
85
+ cursor: disabled ? 'not-allowed' : 'text',
86
+ outline: 'none',
87
+ boxSizing: 'border-box',
88
+ width: '100%',
89
+ ...(disabled ? { opacity: 0.6 } : {})
90
+ } }),
91
+ errorMessage && (react_1.default.createElement("span", { className: `fv-error-text ${errorClassName}`, style: { marginTop: '4px', fontSize: '12px', color: '#dc3545' } },
92
+ "\u26A0 ",
93
+ getErrorMessage()))));
94
+ };
95
+ exports.FvPhoneField = FvPhoneField;
@@ -0,0 +1,20 @@
1
+ import React from 'react';
2
+ export interface RadioOption {
3
+ value: any;
4
+ label: string;
5
+ disabled?: boolean;
6
+ }
7
+ export interface FvRadioGroupProps {
8
+ label?: string;
9
+ value: any;
10
+ options: RadioOption[];
11
+ disabled?: boolean;
12
+ required?: boolean;
13
+ name?: string;
14
+ layout?: 'vertical' | 'horizontal';
15
+ className?: string;
16
+ labelClassName?: string;
17
+ radioClassName?: string;
18
+ onChange: (value: any) => void;
19
+ }
20
+ export declare const FvRadioGroup: React.FC<FvRadioGroupProps>;
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.FvRadioGroup = void 0;
27
+ const react_1 = __importStar(require("react"));
28
+ const FvRadioGroup = ({ label = '', value, options = [], disabled = false, required = false, name, layout = 'vertical', className = '', labelClassName = '', radioClassName = '', onChange, }) => {
29
+ const generatedId = (0, react_1.useId)();
30
+ const groupName = name || `fv-radio-${generatedId}`;
31
+ const handleChange = (val) => {
32
+ if (!disabled) {
33
+ onChange(val);
34
+ }
35
+ };
36
+ return (react_1.default.createElement("div", { className: `fv-radio-group-container ${className}`, style: { marginBottom: '16px', display: 'flex', flexDirection: 'column' } },
37
+ label && (react_1.default.createElement("label", { className: `fv-radio-group-label ${labelClassName}`, style: { marginBottom: '8px', fontSize: '14px', fontWeight: 500, color: disabled ? '#999' : '#333' } },
38
+ label,
39
+ required && react_1.default.createElement("span", { className: "fv-required-asterisk", style: { color: '#dc3545', fontWeight: 'bold' } }, " *"))),
40
+ react_1.default.createElement("div", { className: "fv-radio-options", style: {
41
+ display: 'flex',
42
+ flexDirection: layout === 'horizontal' ? 'row' : 'column',
43
+ gap: layout === 'horizontal' ? '15px' : '8px',
44
+ flexWrap: 'wrap'
45
+ } }, options.map((option, index) => {
46
+ const isSelected = value === option.value;
47
+ const isOptionDisabled = disabled || option.disabled;
48
+ return (react_1.default.createElement("label", { key: index, className: `fv-radio-option ${isOptionDisabled ? 'fv-radio-disabled' : ''} ${radioClassName}`, style: {
49
+ display: 'flex',
50
+ alignItems: 'center',
51
+ cursor: isOptionDisabled ? 'not-allowed' : 'pointer',
52
+ opacity: isOptionDisabled ? 0.6 : 1
53
+ } },
54
+ react_1.default.createElement("input", { type: "radio", name: groupName, value: option.value, checked: isSelected, disabled: isOptionDisabled, onChange: () => handleChange(option.value), className: "fv-radio-input", style: {
55
+ marginRight: '8px',
56
+ cursor: isOptionDisabled ? 'not-allowed' : 'pointer',
57
+ width: '18px',
58
+ height: '18px',
59
+ accentColor: '#007bff'
60
+ } }),
61
+ react_1.default.createElement("span", { className: "fv-radio-label-text", style: { fontSize: '14px', color: '#333' } }, option.label)));
62
+ }))));
63
+ };
64
+ exports.FvRadioGroup = FvRadioGroup;
@@ -0,0 +1,20 @@
1
+ import React from 'react';
2
+ import { ValidationSchema } from '@fovestta2/validation-engine';
3
+ export interface FvRichTextEditorProps {
4
+ label?: string;
5
+ placeholder?: string;
6
+ value: string;
7
+ schema?: ValidationSchema;
8
+ disabled?: boolean;
9
+ readonly?: boolean;
10
+ minHeight?: number;
11
+ showToolbar?: boolean;
12
+ className?: string;
13
+ inputClassName?: string;
14
+ labelClassName?: string;
15
+ errorClassName?: string;
16
+ onChange: (value: string) => void;
17
+ onBlur?: () => void;
18
+ onFocus?: () => void;
19
+ }
20
+ export declare const FvRichTextEditor: React.FC<FvRichTextEditorProps>;
@@ -0,0 +1,199 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.FvRichTextEditor = void 0;
27
+ const react_1 = __importStar(require("react"));
28
+ const validation_engine_1 = require("@fovestta2/validation-engine");
29
+ const FvRichTextEditor = ({ label = '', placeholder = 'Enter text...', value, schema, disabled = false, readonly = false, minHeight = 150, showToolbar = true, className = '', inputClassName = '', labelClassName = '', errorClassName = '', onChange, onBlur, onFocus, }) => {
30
+ const [errorMessage, setErrorMessage] = (0, react_1.useState)(null);
31
+ const [isFocused, setIsFocused] = (0, react_1.useState)(false);
32
+ const editorRef = (0, react_1.useRef)(null);
33
+ (0, react_1.useEffect)(() => {
34
+ validateValue(value);
35
+ }, [value, schema]);
36
+ const validateValue = (val) => {
37
+ if (!schema)
38
+ return;
39
+ const result = validation_engine_1.Validator.validate(val, schema);
40
+ if (!result.isValid && result.errorKey) {
41
+ setErrorMessage(result.errorKey);
42
+ }
43
+ else {
44
+ setErrorMessage(null);
45
+ }
46
+ };
47
+ const handleTextChange = (e) => {
48
+ onChange(e.target.value);
49
+ };
50
+ const handleFocus = () => {
51
+ setIsFocused(true);
52
+ if (onFocus)
53
+ onFocus();
54
+ };
55
+ const handleBlur = () => {
56
+ setIsFocused(false);
57
+ validateValue(value);
58
+ if (onBlur)
59
+ onBlur();
60
+ };
61
+ const insertText = (before, after = before) => {
62
+ if (disabled || readonly || !editorRef.current)
63
+ return;
64
+ const textarea = editorRef.current;
65
+ const start = textarea.selectionStart;
66
+ const end = textarea.selectionEnd;
67
+ const text = value || '';
68
+ const selectedText = text.substring(start, end);
69
+ const newText = text.substring(0, start) + before + selectedText + after + text.substring(end);
70
+ onChange(newText);
71
+ // Restore cursor position
72
+ setTimeout(() => {
73
+ const newPosition = start + before.length + selectedText.length;
74
+ textarea.setSelectionRange(newPosition, newPosition);
75
+ textarea.focus();
76
+ }, 0);
77
+ };
78
+ const handleBulletList = () => {
79
+ if (disabled || readonly || !editorRef.current)
80
+ return;
81
+ const text = value || '';
82
+ const lines = text.split('\n');
83
+ const bulletedLines = lines.map((line) => (line.trim() ? `• ${line}` : line));
84
+ onChange(bulletedLines.join('\n'));
85
+ };
86
+ const handleNumberedList = () => {
87
+ if (disabled || readonly || !editorRef.current)
88
+ return;
89
+ const text = value || '';
90
+ const lines = text.split('\n').filter((line) => line.trim());
91
+ const numberedLines = lines.map((line, index) => `${index + 1}. ${line}`);
92
+ onChange(numberedLines.join('\n'));
93
+ };
94
+ const handleClear = () => {
95
+ if (disabled || readonly)
96
+ return;
97
+ onChange('');
98
+ };
99
+ const getCharacterCount = () => {
100
+ return (value === null || value === void 0 ? void 0 : value.length) || 0;
101
+ };
102
+ const getWordCount = () => {
103
+ const text = value || '';
104
+ return text.trim() ? text.trim().split(/\s+/).length : 0;
105
+ };
106
+ const isRequired = () => {
107
+ var _a;
108
+ return ((_a = schema === null || schema === void 0 ? void 0 : schema.rules) === null || _a === void 0 ? void 0 : _a.some((r) => { var _a; return r.name === 'required' && ((_a = r.params) === null || _a === void 0 ? void 0 : _a['enabled']); })) || false;
109
+ };
110
+ const getErrorMessage = () => {
111
+ if (!errorMessage)
112
+ return '';
113
+ const errorMessages = {
114
+ ERR_REQUIRED: 'This field is required',
115
+ ERR_MIN_LENGTH: 'Text is too short',
116
+ ERR_MAX_LENGTH: 'Text is too long',
117
+ };
118
+ return errorMessages[errorMessage] || errorMessage;
119
+ };
120
+ return (react_1.default.createElement("div", { className: `fv-rich-text-container ${className}`, style: { marginBottom: '16px', display: 'flex', flexDirection: 'column' } },
121
+ label && (react_1.default.createElement("label", { className: `fv-label ${labelClassName}`, style: { marginBottom: '6px', fontSize: '14px', fontWeight: 500, color: disabled ? '#999' : '#333' } },
122
+ label,
123
+ isRequired() && react_1.default.createElement("span", { className: "fv-required", style: { color: '#dc3545', fontWeight: 'bold' } }, " *"))),
124
+ react_1.default.createElement("div", { className: `fv-editor-wrapper ${isFocused ? 'focused' : ''} ${errorMessage ? 'error' : ''}`, style: {
125
+ border: errorMessage ? '1px solid #dc3545' : (isFocused ? '1px solid #3498db' : '1px solid #e0e0e0'),
126
+ borderRadius: '8px',
127
+ overflow: 'hidden',
128
+ backgroundColor: disabled ? '#f5f5f5' : '#fff',
129
+ transition: 'border-color 0.2s, box-shadow 0.2s',
130
+ boxShadow: isFocused ? '0 0 0 3px rgba(52, 152, 219, 0.1)' : 'none',
131
+ display: 'flex',
132
+ flexDirection: 'column'
133
+ } },
134
+ showToolbar && !readonly && (react_1.default.createElement("div", { className: "fv-editor-toolbar", style: {
135
+ padding: '8px 12px',
136
+ borderBottom: '1px solid #e0e0e0',
137
+ backgroundColor: '#f9fafb',
138
+ display: 'flex',
139
+ gap: '8px',
140
+ alignItems: 'center',
141
+ flexWrap: 'wrap'
142
+ } },
143
+ react_1.default.createElement("div", { className: "toolbar-group", style: { display: 'flex', gap: '4px' } },
144
+ react_1.default.createElement("button", { type: "button", className: "toolbar-btn", onClick: () => insertText('**'), disabled: disabled, title: "Bold", style: toolbarBtnStyle }, "B"),
145
+ react_1.default.createElement("button", { type: "button", className: "toolbar-btn", onClick: () => insertText('*'), disabled: disabled, title: "Italic", style: { ...toolbarBtnStyle, fontStyle: 'italic' } }, "I"),
146
+ react_1.default.createElement("button", { type: "button", className: "toolbar-btn", onClick: () => insertText('__'), disabled: disabled, title: "Underline", style: { ...toolbarBtnStyle, textDecoration: 'underline' } }, "U")),
147
+ react_1.default.createElement("div", { className: "toolbar-separator", style: { width: '1px', height: '20px', backgroundColor: '#ddd', margin: '0 4px' } }),
148
+ react_1.default.createElement("div", { className: "toolbar-group", style: { display: 'flex', gap: '4px' } },
149
+ react_1.default.createElement("button", { type: "button", className: "toolbar-btn", onClick: handleBulletList, disabled: disabled, title: "Bullet List", style: toolbarBtnStyle }, "\u2022 List"),
150
+ react_1.default.createElement("button", { type: "button", className: "toolbar-btn", onClick: handleNumberedList, disabled: disabled, title: "Numbered List", style: toolbarBtnStyle }, "1. List")),
151
+ react_1.default.createElement("div", { className: "toolbar-separator", style: { width: '1px', height: '20px', backgroundColor: '#ddd', margin: '0 4px' } }),
152
+ react_1.default.createElement("button", { type: "button", className: "toolbar-btn clear-btn", onClick: handleClear, disabled: disabled || !value, title: "Clear text", style: { ...toolbarBtnStyle, marginLeft: 'auto', color: '#e74c3c' } }, "Clear"))),
153
+ react_1.default.createElement("textarea", { ref: editorRef, value: value, onChange: handleTextChange, onFocus: handleFocus, onBlur: handleBlur, disabled: disabled, readOnly: readonly, placeholder: placeholder, className: `fv-editor-textarea ${inputClassName}`, style: {
154
+ minHeight: `${minHeight}px`,
155
+ padding: '12px',
156
+ border: 'none',
157
+ resize: 'vertical',
158
+ outline: 'none',
159
+ fontSize: '14px',
160
+ color: '#1f2b41',
161
+ lineHeight: 1.5,
162
+ width: '100%',
163
+ boxSizing: 'border-box',
164
+ backgroundColor: 'transparent',
165
+ ...(disabled ? { cursor: 'not-allowed' } : {})
166
+ } }),
167
+ react_1.default.createElement("div", { className: "fv-editor-footer", style: {
168
+ display: 'flex',
169
+ justifyContent: 'space-between',
170
+ padding: '4px 12px 8px',
171
+ fontSize: '12px',
172
+ color: '#888',
173
+ backgroundColor: '#fafafa',
174
+ borderTop: '1px solid #f0f0f0'
175
+ } },
176
+ errorMessage ? (react_1.default.createElement("span", { className: `fv-error-text ${errorClassName}`, style: { color: '#dc3545' } },
177
+ "\u26A0 ",
178
+ getErrorMessage())) : (react_1.default.createElement("span", null)),
179
+ react_1.default.createElement("span", { className: "fv-stats" },
180
+ getWordCount(),
181
+ " words | ",
182
+ getCharacterCount(),
183
+ " characters")))));
184
+ };
185
+ exports.FvRichTextEditor = FvRichTextEditor;
186
+ const toolbarBtnStyle = {
187
+ background: 'none',
188
+ border: '1px solid transparent',
189
+ borderRadius: '4px',
190
+ padding: '4px 8px',
191
+ cursor: 'pointer',
192
+ fontSize: '13px',
193
+ fontWeight: 600,
194
+ color: '#444',
195
+ display: 'flex',
196
+ alignItems: 'center',
197
+ justifyContent: 'center',
198
+ transition: 'all 0.2s',
199
+ };
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+ export interface FvServicePeriodProps {
3
+ label?: string;
4
+ startDate?: string;
5
+ endDate?: string;
6
+ roundToYears?: boolean;
7
+ onRoundChange?: (checked: boolean) => void;
8
+ className?: string;
9
+ }
10
+ export declare const FvServicePeriod: React.FC<FvServicePeriodProps>;
@@ -0,0 +1,122 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.FvServicePeriod = void 0;
27
+ const react_1 = __importStar(require("react"));
28
+ const FvServicePeriod = ({ label = 'Service Period', startDate, endDate, roundToYears = false, onRoundChange, className = '', }) => {
29
+ const [years, setYears] = (0, react_1.useState)(0);
30
+ const [months, setMonths] = (0, react_1.useState)(0);
31
+ const [days, setDays] = (0, react_1.useState)(0);
32
+ const [totalDays, setTotalDays] = (0, react_1.useState)(0);
33
+ (0, react_1.useEffect)(() => {
34
+ calculatePeriod();
35
+ }, [startDate, endDate, roundToYears]);
36
+ const resetValues = () => {
37
+ setYears(0);
38
+ setMonths(0);
39
+ setDays(0);
40
+ setTotalDays(0);
41
+ };
42
+ const calculatePeriod = () => {
43
+ if (!startDate || !endDate) {
44
+ resetValues();
45
+ return;
46
+ }
47
+ const start = new Date(startDate);
48
+ const end = new Date(endDate);
49
+ if (isNaN(start.getTime()) || isNaN(end.getTime())) {
50
+ resetValues();
51
+ return;
52
+ }
53
+ if (end < start) {
54
+ resetValues();
55
+ return;
56
+ }
57
+ // Calculate difference
58
+ let calcYears = end.getFullYear() - start.getFullYear();
59
+ let calcMonths = end.getMonth() - start.getMonth();
60
+ let calcDays = end.getDate() - start.getDate();
61
+ if (calcDays < 0) {
62
+ calcMonths--;
63
+ // Days in previous month
64
+ const prevMonth = new Date(end.getFullYear(), end.getMonth(), 0);
65
+ calcDays += prevMonth.getDate();
66
+ }
67
+ if (calcMonths < 0) {
68
+ calcYears--;
69
+ calcMonths += 12;
70
+ }
71
+ // Apply Rounding if checkbox is checked
72
+ if (roundToYears) {
73
+ if (calcMonths >= 6) {
74
+ calcYears++;
75
+ }
76
+ calcMonths = 0;
77
+ calcDays = 0;
78
+ }
79
+ setYears(calcYears);
80
+ setMonths(calcMonths);
81
+ setDays(calcDays);
82
+ // Total Days
83
+ const diffTime = Math.abs(end.getTime() - start.getTime());
84
+ setTotalDays(Math.ceil(diffTime / (1000 * 60 * 60 * 24)));
85
+ };
86
+ const handleCheckboxChange = (e) => {
87
+ if (onRoundChange) {
88
+ onRoundChange(e.target.checked);
89
+ }
90
+ };
91
+ return (react_1.default.createElement("div", { className: `service-period-card ${className}`, style: {
92
+ border: '1px solid #eee',
93
+ borderRadius: '8px',
94
+ padding: '16px',
95
+ backgroundColor: '#fff',
96
+ boxShadow: '0 2px 4px rgba(0,0,0,0.05)',
97
+ marginBottom: '16px'
98
+ } },
99
+ react_1.default.createElement("div", { className: "sp-header", style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '12px' } },
100
+ react_1.default.createElement("div", { className: "sp-title-group", style: { display: 'flex', alignItems: 'center' } },
101
+ react_1.default.createElement("span", { className: "sp-label", style: { fontSize: '14px', fontWeight: 'bold', color: '#151D48', marginRight: '8px' } }, label),
102
+ react_1.default.createElement("svg", { className: "sp-icon", viewBox: "0 0 24 24", width: "18", height: "18", fill: "#151D48" },
103
+ react_1.default.createElement("path", { d: "M19 3h-1V1h-2v2H8V1H6v2H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V8h14v11zM7 10h5v5H7z" })))),
104
+ react_1.default.createElement("div", { className: "sp-content", style: { marginBottom: '12px' } },
105
+ react_1.default.createElement("div", { className: "sp-duration", style: { fontSize: '14px', color: '#333', marginBottom: '4px' } },
106
+ years,
107
+ " Years, ",
108
+ months,
109
+ " Months, ",
110
+ days,
111
+ " Days"),
112
+ react_1.default.createElement("div", { className: "sp-total", style: { fontSize: '13px', color: '#666' } },
113
+ "Total: ",
114
+ totalDays,
115
+ " days")),
116
+ react_1.default.createElement("div", { className: "sp-divider", style: { height: '1px', backgroundColor: '#eee', margin: '12px 0' } }),
117
+ onRoundChange && (react_1.default.createElement("div", { className: "sp-footer" },
118
+ react_1.default.createElement("label", { className: "sp-checkbox-label", style: { display: 'flex', alignItems: 'center', fontSize: '13px', color: '#333', cursor: 'pointer' } },
119
+ react_1.default.createElement("input", { type: "checkbox", checked: roundToYears, onChange: handleCheckboxChange, style: { marginRight: '8px' } }),
120
+ "Round to years (if months >= 6)")))));
121
+ };
122
+ exports.FvServicePeriod = FvServicePeriod;