@x15ventures/x15-ui-library 3.15.0 → 3.15.1
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/autoGenerated/libraryThemes.js +12 -12
- package/dist/cjs/autoGenerated/libraryThemes.js.map +1 -1
- package/dist/cjs/autoGenerated/libraryThemes.json +12 -12
- package/dist/cjs/components/design/dialog/Dialog.js +1 -1
- package/dist/cjs/components/design/dialog/Dialog.js.map +1 -1
- package/dist/cjs/components/design/headerBar/HeaderBar.js +3 -1
- package/dist/cjs/components/design/headerBar/HeaderBar.js.map +1 -1
- package/dist/cjs/components/design/headerBar/headerBar.css +6 -1
- package/dist/cjs/components/form/formFields/formFieldWrapper/FormField.js +8 -5
- package/dist/cjs/components/form/formFields/formFieldWrapper/FormField.js.map +1 -1
- package/dist/cjs/components/form/formFields/formFieldWrapper/formFieldProps.js.map +1 -1
- package/dist/cjs/components/form/formFields/subComponents/inputs/autocomplete/Autocomplete.js +15 -11
- package/dist/cjs/components/form/formFields/subComponents/inputs/autocomplete/Autocomplete.js.map +1 -1
- package/dist/cjs/components/form/formFields/subComponents/inputs/checkbox/InputCheckbox.js +37 -15
- package/dist/cjs/components/form/formFields/subComponents/inputs/checkbox/InputCheckbox.js.map +1 -1
- package/dist/cjs/components/form/formFields/subComponents/inputs/checkbox/inputCheckbox.css +4 -4
- package/dist/cjs/components/form/formFields/subComponents/inputs/checkbox/inputCheckboxProps.js.map +1 -1
- package/dist/cjs/components/form/formFields/subComponents/inputs/file/dragAndDrop/DragAndDropFileUpload.js +9 -9
- package/dist/cjs/components/form/formFields/subComponents/inputs/file/dragAndDrop/DragAndDropFileUpload.js.map +1 -1
- package/dist/cjs/components/form/formFields/subComponents/inputs/radio/styled/StyledRadioGroup.js +14 -4
- package/dist/cjs/components/form/formFields/subComponents/inputs/radio/styled/StyledRadioGroup.js.map +1 -1
- package/dist/cjs/components/form/formFields/subComponents/inputs/text/InputText.js +23 -17
- package/dist/cjs/components/form/formFields/subComponents/inputs/text/InputText.js.map +1 -1
- package/dist/cjs/components/form/formFields/subComponents/select/Select.js +6 -5
- package/dist/cjs/components/form/formFields/subComponents/select/Select.js.map +1 -1
- package/dist/cjs/components/form/formFields/subComponents/textarea/Textarea.js +55 -83
- package/dist/cjs/components/form/formFields/subComponents/textarea/Textarea.js.map +1 -1
- package/dist/cjs/components/form/formFields/subComponents/textarea/textarea.css +20 -0
- package/dist/cjs/components/form/hookFormWrapper/HookFormWrapper.js +22 -5
- package/dist/cjs/components/form/hookFormWrapper/HookFormWrapper.js.map +1 -1
- package/dist/cjs/components/form/validation/ValidationMessages.js +36 -38
- package/dist/cjs/components/form/validation/ValidationMessages.js.map +1 -1
- package/dist/cjs/exampleUIs/exampleComponents/DemoContactForm.js +1 -2
- package/dist/cjs/exampleUIs/exampleComponents/DemoContactForm.js.map +1 -1
- package/dist/cjs/helpers/index.js +12 -0
- package/dist/cjs/helpers/index.js.map +1 -1
- package/dist/cjs/helpers/stringHelpers.js +48 -2
- package/dist/cjs/helpers/stringHelpers.js.map +1 -1
- package/dist/cjs/interfaces/headerText.interface.js.map +1 -1
- package/dist/cjs/package.json +137 -151
- package/dist/cjs/styles/index.css +22 -25
- package/dist/cjs/styles/shared/_allPartials.css +22 -25
- package/dist/cjs/styles/shared/forms/_forms.css +22 -25
- package/dist/components/design/dialog/Dialog.d.ts.map +1 -1
- package/dist/components/design/dialog/Dialog.test.d.ts +5 -0
- package/dist/components/design/dialog/Dialog.test.d.ts.map +1 -0
- package/dist/components/design/headerBar/HeaderBar.d.ts.map +1 -1
- package/dist/components/form/formFields/formFieldWrapper/FormField.d.ts.map +1 -1
- package/dist/components/form/formFields/formFieldWrapper/formFieldProps.d.ts +7 -2
- package/dist/components/form/formFields/formFieldWrapper/formFieldProps.d.ts.map +1 -1
- package/dist/components/form/formFields/subComponents/inputs/autocomplete/Autocomplete.d.ts.map +1 -1
- package/dist/components/form/formFields/subComponents/inputs/checkbox/InputCheckbox.d.ts.map +1 -1
- package/dist/components/form/formFields/subComponents/inputs/checkbox/InputCheckbox.test.d.ts +5 -0
- package/dist/components/form/formFields/subComponents/inputs/checkbox/InputCheckbox.test.d.ts.map +1 -0
- package/dist/components/form/formFields/subComponents/inputs/checkbox/inputCheckboxProps.d.ts +8 -6
- package/dist/components/form/formFields/subComponents/inputs/checkbox/inputCheckboxProps.d.ts.map +1 -1
- package/dist/components/form/formFields/subComponents/inputs/file/dragAndDrop/DragAndDropFileUpload.d.ts.map +1 -1
- package/dist/components/form/formFields/subComponents/inputs/radio/styled/StyledRadioGroup.d.ts.map +1 -1
- package/dist/components/form/formFields/subComponents/inputs/text/InputText.d.ts.map +1 -1
- package/dist/components/form/formFields/subComponents/nestedFormContext.test.d.ts +5 -0
- package/dist/components/form/formFields/subComponents/nestedFormContext.test.d.ts.map +1 -0
- package/dist/components/form/formFields/subComponents/select/Select.d.ts.map +1 -1
- package/dist/components/form/formFields/subComponents/textarea/Textarea.d.ts +4 -3
- package/dist/components/form/formFields/subComponents/textarea/Textarea.d.ts.map +1 -1
- package/dist/components/form/hookFormWrapper/HookFormWrapper.d.ts +3 -0
- package/dist/components/form/hookFormWrapper/HookFormWrapper.d.ts.map +1 -1
- package/dist/components/form/hookFormWrapper/HookFormWrapper.test.d.ts +5 -0
- package/dist/components/form/hookFormWrapper/HookFormWrapper.test.d.ts.map +1 -0
- package/dist/components/form/validation/ValidationMessages.d.ts +8 -1
- package/dist/components/form/validation/ValidationMessages.d.ts.map +1 -1
- package/dist/components/form/validation/ValidationMessages.test.d.ts +5 -0
- package/dist/components/form/validation/ValidationMessages.test.d.ts.map +1 -0
- package/dist/esm/autoGenerated/libraryThemes.js +12 -12
- package/dist/esm/autoGenerated/libraryThemes.js.map +1 -1
- package/dist/esm/autoGenerated/libraryThemes.json +12 -12
- package/dist/esm/components/design/dialog/Dialog.js +1 -1
- package/dist/esm/components/design/dialog/Dialog.js.map +1 -1
- package/dist/esm/components/design/headerBar/HeaderBar.js +3 -1
- package/dist/esm/components/design/headerBar/HeaderBar.js.map +1 -1
- package/dist/esm/components/design/headerBar/headerBar.css +6 -1
- package/dist/esm/components/form/formFields/formFieldWrapper/FormField.js +8 -5
- package/dist/esm/components/form/formFields/formFieldWrapper/FormField.js.map +1 -1
- package/dist/esm/components/form/formFields/formFieldWrapper/formFieldProps.js.map +1 -1
- package/dist/esm/components/form/formFields/subComponents/inputs/autocomplete/Autocomplete.js +16 -12
- package/dist/esm/components/form/formFields/subComponents/inputs/autocomplete/Autocomplete.js.map +1 -1
- package/dist/esm/components/form/formFields/subComponents/inputs/checkbox/InputCheckbox.js +37 -15
- package/dist/esm/components/form/formFields/subComponents/inputs/checkbox/InputCheckbox.js.map +1 -1
- package/dist/esm/components/form/formFields/subComponents/inputs/checkbox/inputCheckbox.css +4 -4
- package/dist/esm/components/form/formFields/subComponents/inputs/checkbox/inputCheckboxProps.js.map +1 -1
- package/dist/esm/components/form/formFields/subComponents/inputs/file/dragAndDrop/DragAndDropFileUpload.js +8 -8
- package/dist/esm/components/form/formFields/subComponents/inputs/file/dragAndDrop/DragAndDropFileUpload.js.map +1 -1
- package/dist/esm/components/form/formFields/subComponents/inputs/radio/styled/StyledRadioGroup.js +16 -6
- package/dist/esm/components/form/formFields/subComponents/inputs/radio/styled/StyledRadioGroup.js.map +1 -1
- package/dist/esm/components/form/formFields/subComponents/inputs/text/InputText.js +23 -17
- package/dist/esm/components/form/formFields/subComponents/inputs/text/InputText.js.map +1 -1
- package/dist/esm/components/form/formFields/subComponents/select/Select.js +6 -5
- package/dist/esm/components/form/formFields/subComponents/select/Select.js.map +1 -1
- package/dist/esm/components/form/formFields/subComponents/textarea/Textarea.js +50 -78
- package/dist/esm/components/form/formFields/subComponents/textarea/Textarea.js.map +1 -1
- package/dist/esm/components/form/formFields/subComponents/textarea/textarea.css +20 -0
- package/dist/esm/components/form/hookFormWrapper/HookFormWrapper.js +22 -5
- package/dist/esm/components/form/hookFormWrapper/HookFormWrapper.js.map +1 -1
- package/dist/esm/components/form/validation/ValidationMessages.js +36 -38
- package/dist/esm/components/form/validation/ValidationMessages.js.map +1 -1
- package/dist/esm/exampleUIs/exampleComponents/DemoContactForm.js +1 -2
- package/dist/esm/exampleUIs/exampleComponents/DemoContactForm.js.map +1 -1
- package/dist/esm/helpers/index.js +1 -1
- package/dist/esm/helpers/index.js.map +1 -1
- package/dist/esm/helpers/stringHelpers.js +44 -0
- package/dist/esm/helpers/stringHelpers.js.map +1 -1
- package/dist/esm/interfaces/headerText.interface.js.map +1 -1
- package/dist/esm/package.json +137 -151
- package/dist/esm/styles/index.css +22 -25
- package/dist/esm/styles/shared/_allPartials.css +22 -25
- package/dist/esm/styles/shared/forms/_forms.css +22 -25
- package/dist/exampleUIs/exampleComponents/DemoContactForm.d.ts.map +1 -1
- package/dist/helpers/index.d.ts +1 -1
- package/dist/helpers/index.d.ts.map +1 -1
- package/dist/helpers/stringHelpers.d.ts +17 -0
- package/dist/helpers/stringHelpers.d.ts.map +1 -1
- package/dist/interfaces/headerText.interface.d.ts +1 -0
- package/dist/interfaces/headerText.interface.d.ts.map +1 -1
- package/dist/package.json +137 -151
- package/package.json +137 -151
- package/dist/cjs/components/form/formFields/utilities/formUtilities.js +0 -22
- package/dist/cjs/components/form/formFields/utilities/formUtilities.js.map +0 -1
- package/dist/components/form/formFields/utilities/formUtilities.d.ts +0 -18
- package/dist/components/form/formFields/utilities/formUtilities.d.ts.map +0 -1
- package/dist/esm/components/form/formFields/utilities/formUtilities.js +0 -16
- package/dist/esm/components/form/formFields/utilities/formUtilities.js.map +0 -1
|
@@ -3,35 +3,13 @@
|
|
|
3
3
|
import React, { useMemo, useState } from 'react';
|
|
4
4
|
import { useFormContext } from 'react-hook-form';
|
|
5
5
|
import { HookFormWrapper } from '../../../hookFormWrapper/HookFormWrapper';
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
function getCharacterCount(value) {
|
|
14
|
-
if (typeof Intl !== 'undefined' && 'Segmenter' in Intl) {
|
|
15
|
-
const segmenter = new Intl.Segmenter(undefined, {
|
|
16
|
-
granularity: 'grapheme'
|
|
17
|
-
});
|
|
18
|
-
return Array.from(segmenter.segment(value)).length;
|
|
19
|
-
}
|
|
20
|
-
return Array.from(value).length;
|
|
21
|
-
}
|
|
22
|
-
function clampToGraphemeMax(value, maxAllowed) {
|
|
23
|
-
if (getCharacterCount(value) <= maxAllowed) {
|
|
24
|
-
return value;
|
|
25
|
-
}
|
|
26
|
-
if (typeof Intl !== 'undefined' && 'Segmenter' in Intl) {
|
|
27
|
-
const segmenter = new Intl.Segmenter(undefined, {
|
|
28
|
-
granularity: 'grapheme'
|
|
29
|
-
});
|
|
30
|
-
return Array.from(segmenter.segment(value)).slice(0, maxAllowed).map(segment => segment.segment).join('');
|
|
31
|
-
}
|
|
32
|
-
return Array.from(value).slice(0, maxAllowed).join('');
|
|
33
|
-
}
|
|
34
|
-
export const Textarea = ({
|
|
6
|
+
import { extractError } from '../../../validation/ValidationMessages';
|
|
7
|
+
import { clampToGraphemeMax, getCharacterCount } from '../../../../../helpers/stringHelpers';
|
|
8
|
+
import './textarea.css';
|
|
9
|
+
export const Textarea = props => /*#__PURE__*/React.createElement(HookFormWrapper, {
|
|
10
|
+
formContext: props.formContext
|
|
11
|
+
}, /*#__PURE__*/React.createElement(TextareaField, props));
|
|
12
|
+
const TextareaField = ({
|
|
35
13
|
field: {
|
|
36
14
|
id,
|
|
37
15
|
name,
|
|
@@ -56,20 +34,16 @@ export const Textarea = ({
|
|
|
56
34
|
formState: {
|
|
57
35
|
errors
|
|
58
36
|
}
|
|
59
|
-
} = useFormContext()
|
|
37
|
+
} = useFormContext();
|
|
60
38
|
const fieldState = getFieldState(name);
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
const isInvalid = Boolean(fieldState?.invalid ?? hasFieldError);
|
|
39
|
+
// getFieldState alone does not subscribe to errors, so the direct lookup keeps this in sync.
|
|
40
|
+
const isInvalid = Boolean(fieldState?.invalid || extractError(errors, name));
|
|
41
|
+
const isRequiredError = fieldState?.error?.type === 'required';
|
|
65
42
|
const [count, setCount] = useState(() => getCharacterCount(defaultValue?.toString() || ''));
|
|
66
43
|
const [hasStartedTyping, setHasStartedTyping] = useState(false);
|
|
67
44
|
const hasMaxLength = typeof maxLength === 'number';
|
|
68
45
|
const isAtLimit = hasMaxLength ? count >= maxLength : false;
|
|
69
|
-
|
|
70
|
-
// should show counter instead of error message.
|
|
71
|
-
const isRequiredError = fieldState?.error?.type === 'required';
|
|
72
|
-
const characterCounter = !hasStartedTyping || !hasMaxLength || isRequiredError ? undefined : `${count}/${maxLength}`;
|
|
46
|
+
const showsCharacterCount = hasStartedTyping && hasMaxLength && !isRequiredError;
|
|
73
47
|
const cssClass = `${customCssClasses?.input || ''}${isInvalid ? ' invalidField' : ''}`;
|
|
74
48
|
const normalizedValidation = useMemo(() => {
|
|
75
49
|
if (!validation || typeof validation.maxLength === 'undefined') {
|
|
@@ -115,19 +89,21 @@ export const Textarea = ({
|
|
|
115
89
|
validate: graphemeMaxLengthValidator
|
|
116
90
|
};
|
|
117
91
|
}, [validation]);
|
|
118
|
-
const
|
|
92
|
+
const fieldRegistration = register(name, normalizedValidation);
|
|
119
93
|
|
|
120
94
|
/**
|
|
121
|
-
*
|
|
122
|
-
*
|
|
123
|
-
* can be treated as multiple characters. We avoid using native maxLength and enforce
|
|
124
|
-
* the limit here instead.
|
|
95
|
+
* Native maxLength counts UTF-16 units, so emojis and composed characters are treated as
|
|
96
|
+
* several characters. The limit is enforced here against grapheme clusters instead.
|
|
125
97
|
*/
|
|
126
98
|
const HandleBeforeInput = event => {
|
|
127
|
-
if (enforceMaxLength !== true || !hasMaxLength)
|
|
99
|
+
if (enforceMaxLength !== true || !hasMaxLength) {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
128
102
|
const nativeEvent = event.nativeEvent;
|
|
129
103
|
const inserted = nativeEvent.data ?? '';
|
|
130
|
-
if (!inserted)
|
|
104
|
+
if (!inserted) {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
131
107
|
const target = event.currentTarget;
|
|
132
108
|
const start = target.selectionStart ?? target.value.length;
|
|
133
109
|
const end = target.selectionEnd ?? target.value.length;
|
|
@@ -144,8 +120,22 @@ export const Textarea = ({
|
|
|
144
120
|
}
|
|
145
121
|
setHasStartedTyping(true);
|
|
146
122
|
setCount(getCharacterCount(newValue));
|
|
147
|
-
|
|
148
|
-
|
|
123
|
+
onChange(event);
|
|
124
|
+
fieldRegistration?.onChange?.(event);
|
|
125
|
+
};
|
|
126
|
+
const HandleAutoFill = event => {
|
|
127
|
+
// Browsers trigger onAnimationStart when autofill happens.
|
|
128
|
+
// We need to notify react-hook-form of the new value.
|
|
129
|
+
if (event.animationName === 'onAutoFill') {
|
|
130
|
+
const {
|
|
131
|
+
value
|
|
132
|
+
} = event.currentTarget;
|
|
133
|
+
setHasStartedTyping(true);
|
|
134
|
+
setCount(getCharacterCount(value || ''));
|
|
135
|
+
HandleChange({
|
|
136
|
+
target: event.currentTarget
|
|
137
|
+
});
|
|
138
|
+
}
|
|
149
139
|
};
|
|
150
140
|
const HandleOnBlur = event => {
|
|
151
141
|
const {
|
|
@@ -155,17 +145,12 @@ export const Textarea = ({
|
|
|
155
145
|
onTouched();
|
|
156
146
|
onBlur(event);
|
|
157
147
|
}
|
|
148
|
+
fieldRegistration?.onBlur?.(event);
|
|
158
149
|
};
|
|
159
150
|
const HandleKeyEvent = event => {
|
|
160
151
|
onTouched();
|
|
161
|
-
|
|
162
|
-
onTextareaKeyDown?.(event);
|
|
152
|
+
onKeyDown(event);
|
|
163
153
|
};
|
|
164
|
-
const characterCounterId = `${id}_characterCount`;
|
|
165
|
-
const errorsId = `${name}_errors`;
|
|
166
|
-
const existingDescribedBy = typeof htmlNativeDomProps['aria-describedby'] === 'string' ? htmlNativeDomProps['aria-describedby'] : undefined;
|
|
167
|
-
const showsRequiredError = isInvalid && isRequiredError;
|
|
168
|
-
const mergedDescribedBy = showsRequiredError ? [existingDescribedBy, errorsId].filter(Boolean).join(' ') : characterCounter !== undefined ? [existingDescribedBy, characterCounterId].filter(Boolean).join(' ') : existingDescribedBy;
|
|
169
154
|
const textareaProps = {
|
|
170
155
|
id,
|
|
171
156
|
className: cssClass,
|
|
@@ -177,38 +162,25 @@ export const Textarea = ({
|
|
|
177
162
|
...(validation && typeof validation.required !== 'undefined' ? {
|
|
178
163
|
required: true
|
|
179
164
|
} : {}),
|
|
180
|
-
...
|
|
165
|
+
...htmlNativeDomProps,
|
|
166
|
+
...fieldRegistration,
|
|
181
167
|
onBeforeInput: HandleBeforeInput,
|
|
182
|
-
onChange:
|
|
183
|
-
|
|
184
|
-
registered?.onChange?.(event);
|
|
185
|
-
},
|
|
186
|
-
onBlur: event => {
|
|
187
|
-
HandleOnBlur(event);
|
|
188
|
-
registered?.onBlur?.(event);
|
|
189
|
-
},
|
|
168
|
+
onChange: HandleChange,
|
|
169
|
+
onBlur: HandleOnBlur,
|
|
190
170
|
onKeyDown: HandleKeyEvent,
|
|
191
|
-
|
|
192
|
-
'aria-describedby': mergedDescribedBy
|
|
171
|
+
onAnimationStart: HandleAutoFill
|
|
193
172
|
};
|
|
194
|
-
|
|
173
|
+
const containerCssClass = `textareaFieldContainer${showsCharacterCount ? ' withCharacterCount' : ''}`;
|
|
174
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, customContent?.preField && /*#__PURE__*/React.createElement("span", {
|
|
195
175
|
className: "preField"
|
|
196
|
-
}, customContent?.preField), /*#__PURE__*/React.createElement("
|
|
197
|
-
className:
|
|
198
|
-
}, /*#__PURE__*/React.createElement("textarea", textareaProps), /*#__PURE__*/React.createElement("
|
|
199
|
-
className: "textareaFooter"
|
|
200
|
-
}, isInvalid && isRequiredError ? /*#__PURE__*/React.createElement(ValidationMessages, {
|
|
201
|
-
name: name,
|
|
202
|
-
validation: {
|
|
203
|
-
required: validation?.required
|
|
204
|
-
}
|
|
205
|
-
}) : /*#__PURE__*/React.createElement("div", {
|
|
206
|
-
id: characterCounterId,
|
|
176
|
+
}, customContent?.preField), /*#__PURE__*/React.createElement("span", {
|
|
177
|
+
className: containerCssClass
|
|
178
|
+
}, /*#__PURE__*/React.createElement("textarea", textareaProps), showsCharacterCount && /*#__PURE__*/React.createElement("span", {
|
|
207
179
|
className: `textareaCharacterCount ${isAtLimit ? 'textareaCharacterCountExceeded' : ''}`,
|
|
208
180
|
role: isAtLimit ? 'status' : undefined,
|
|
209
181
|
"aria-live": isAtLimit ? 'polite' : undefined,
|
|
210
182
|
"aria-atomic": isAtLimit ? 'true' : undefined
|
|
211
|
-
},
|
|
183
|
+
}, `${count}/${maxLength}`)), customContent?.postField && /*#__PURE__*/React.createElement("span", {
|
|
212
184
|
className: "postField"
|
|
213
185
|
}, customContent?.postField));
|
|
214
186
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Textarea.js","names":["React","useMemo","useState","useFormContext","HookFormWrapper","NoHookFormContext","extractError","ValidationMessages","getCharacterCount","value","Intl","segmenter","Segmenter","undefined","granularity","Array","from","segment","length","clampToGraphemeMax","maxAllowed","slice","map","join","Textarea","field","id","name","placeholder","defaultValue","maxLength","enforceMaxLength","onBlur","onChange","onKeyDown","onTouched","htmlNativeDomProps","validation","showSpinner","customCssClasses","customContent","register","getFieldState","formState","errors","fieldState","hasFieldError","Boolean","isInvalid","invalid","count","setCount","toString","hasStartedTyping","setHasStartedTyping","hasMaxLength","isAtLimit","isRequiredError","error","type","characterCounter","cssClass","input","normalizedValidation","maxLengthRule","maxLengthValue","Number","isNaN","maxLengthMessage","graphemeMaxLengthValidator","_maxLength","validate","restValidation","formValues","validationResult","graphemeMaxLength","registered","HandleBeforeInput","event","nativeEvent","inserted","data","target","currentTarget","start","selectionStart","end","selectionEnd","nextValue","preventDefault","HandleChange","rawValue","newValue","onTextareaChange","HandleOnBlur","HandleKeyEvent","onTextareaKeyDown","characterCounterId","errorsId","existingDescribedBy","showsRequiredError","mergedDescribedBy","filter","textareaProps","className","disabled","required","onBeforeInput","createElement","preField","role","postField"],"sources":["../../../../../../../src/components/form/formFields/subComponents/textarea/Textarea.tsx"],"sourcesContent":["'use client';\n\nimport React, { useMemo, useState } from 'react';\nimport { useFormContext } from 'react-hook-form';\nimport { HookFormWrapper } from '../../../hookFormWrapper/HookFormWrapper';\nimport { FormFieldProps } from '../../formFieldWrapper/formFieldProps';\nimport { NoHookFormContext } from '../../utilities/formUtilities';\nimport { extractError, ValidationMessages } from '../../../validation/ValidationMessages';\n\ninterface TextareaProps extends FormFieldProps, React.TextareaHTMLAttributes<HTMLTextAreaElement> {}\n\n/**\n* Counts user-perceived characters (grapheme clusters).\n* Treats emojis and composed characters (e.g. accented letters) as a single character.\n* Falls back to basic code-point counting if Intl.Segmenter is not available.\n*/\nfunction getCharacterCount(value: string): number {\n if (typeof Intl !== 'undefined' && 'Segmenter' in Intl) {\n const segmenter = new Intl.Segmenter(undefined, {\n granularity: 'grapheme',\n });\n return Array.from(segmenter.segment(value)).length;\n }\n return Array.from(value).length;\n}\n\nfunction clampToGraphemeMax(value: string, maxAllowed: number): string {\n if (getCharacterCount(value) <= maxAllowed) {\n return value;\n }\n\n if (typeof Intl !== 'undefined' && 'Segmenter' in Intl) {\n const segmenter = new Intl.Segmenter(undefined, {\n granularity: 'grapheme',\n });\n\n return Array.from(segmenter.segment(value))\n .slice(0, maxAllowed)\n .map((segment) => segment.segment)\n .join('');\n }\n\n return Array.from(value).slice(0, maxAllowed).join('');\n}\n\nexport const Textarea: React.FC<TextareaProps> = (\n {\n field: {\n id,\n name,\n placeholder,\n defaultValue,\n maxLength,\n enforceMaxLength,\n onBlur = () => {},\n onChange = () => {},\n onKeyDown = () => {},\n onTouched = () => {},\n ...htmlNativeDomProps\n },\n validation,\n showSpinner,\n customCssClasses,\n customContent\n }\n) => {\n const { register, getFieldState, formState: { errors } } = useFormContext() || NoHookFormContext;\n const fieldState = getFieldState(name);\n const hasFieldError = Boolean(extractError(errors, name));\n // Combine fieldState.invalid with a direct errors lookup so this component re-renders\n // whenever formState.errors changes (getFieldState alone does not subscribe to errors).\n const isInvalid = Boolean(fieldState?.invalid ?? hasFieldError);\n const [count, setCount] = useState<number>(() =>\n getCharacterCount(defaultValue?.toString() || '')\n );\n const [hasStartedTyping, setHasStartedTyping] = useState(false);\n const hasMaxLength = typeof maxLength === 'number';\n const isAtLimit = hasMaxLength ? count >= maxLength : false;\n // Only hide counter for 'required' error. All other errors (maxLength, pattern, etc)\n // should show counter instead of error message.\n const isRequiredError = fieldState?.error?.type === 'required';\n const characterCounter =\n !hasStartedTyping || !hasMaxLength || isRequiredError\n ? undefined\n : `${ count }/${ maxLength }`;\n const cssClass = `${ customCssClasses?.input || '' }${ isInvalid ? ' invalidField' : '' }`;\n\n const normalizedValidation = useMemo(() => {\n if (!validation || typeof validation.maxLength === 'undefined') {\n return validation;\n }\n\n const maxLengthRule = validation.maxLength;\n const maxLengthValue =\n typeof maxLengthRule === 'number'\n ? maxLengthRule\n : typeof maxLengthRule === 'object' && maxLengthRule && 'value' in maxLengthRule\n ? Number(maxLengthRule.value)\n : undefined;\n\n if (typeof maxLengthValue !== 'number' || Number.isNaN(maxLengthValue)) {\n return validation;\n }\n\n const maxLengthMessage = `Maximum length is ${ maxLengthValue }`;\n\n const graphemeMaxLengthValidator = (value: string) =>\n getCharacterCount(value || '') <= maxLengthValue || maxLengthMessage;\n\n // eslint-disable-next-line no-unused-vars\n const { maxLength: _maxLength, validate, ...restValidation } = validation;\n\n if (typeof validate === 'function') {\n return {\n ...restValidation,\n validate: async (value: string, formValues?: unknown) => {\n const validationResult = await validate(value, formValues);\n if (validationResult !== true) {\n return validationResult;\n }\n return graphemeMaxLengthValidator(value);\n },\n };\n }\n\n if (validate && typeof validate === 'object') {\n return {\n ...restValidation,\n validate: {\n ...validate,\n graphemeMaxLength: graphemeMaxLengthValidator,\n },\n };\n }\n\n return {\n ...restValidation,\n validate: graphemeMaxLengthValidator,\n };\n }, [validation]);\n\n const registered = register(name, normalizedValidation);\n\n /**\n * Prevents input that would exceed the maxLength when counting grapheme clusters.\n * Native <textarea maxLength> counts UTF-16 units, so emojis and composed characters\n * can be treated as multiple characters. We avoid using native maxLength and enforce\n * the limit here instead.\n */\n const HandleBeforeInput = (event: React.FormEvent<HTMLTextAreaElement>) => {\n if (enforceMaxLength !== true || !hasMaxLength) return;\n\n const nativeEvent = event.nativeEvent as InputEvent;\n const inserted = nativeEvent.data ?? '';\n\n if (!inserted) return;\n\n const target = event.currentTarget;\n const start = target.selectionStart ?? target.value.length;\n const end = target.selectionEnd ?? target.value.length;\n\n const nextValue =\n target.value.slice(0, start) +\n inserted +\n target.value.slice(end);\n\n if (getCharacterCount(nextValue) > maxLength) {\n event.preventDefault();\n }\n };\n\n const HandleChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {\n const rawValue = event.target.value || '';\n const newValue =\n enforceMaxLength === true && hasMaxLength\n ? clampToGraphemeMax(rawValue, maxLength)\n : rawValue;\n\n if (newValue !== rawValue) {\n event.target.value = newValue;\n }\n\n setHasStartedTyping(true);\n setCount(getCharacterCount(newValue));\n const onTextareaChange = onChange as\n | React.ChangeEventHandler<HTMLTextAreaElement>\n | undefined;\n onTextareaChange?.(event);\n };\n\n const HandleOnBlur = (event: React.FocusEvent<HTMLTextAreaElement>) => {\n const { target } = event;\n if (target) {\n onTouched();\n onBlur(event);\n }\n };\n\n const HandleKeyEvent = (event: React.KeyboardEvent<HTMLTextAreaElement>) => {\n onTouched();\n const onTextareaKeyDown = onKeyDown as\n | React.KeyboardEventHandler<HTMLTextAreaElement>\n | undefined;\n onTextareaKeyDown?.(event);\n };\n\n const characterCounterId = `${ id }_characterCount`;\n const errorsId = `${ name }_errors`;\n const existingDescribedBy =\n typeof htmlNativeDomProps['aria-describedby'] === 'string'\n ? htmlNativeDomProps['aria-describedby']\n : undefined;\n const showsRequiredError = isInvalid && isRequiredError;\n const mergedDescribedBy = showsRequiredError\n ? [existingDescribedBy, errorsId].filter(Boolean).join(' ')\n : characterCounter !== undefined\n ? [existingDescribedBy, characterCounterId].filter(Boolean).join(' ')\n : existingDescribedBy;\n \n const textareaProps = {\n id,\n className: cssClass,\n placeholder,\n defaultValue,\n ...(showSpinner ? { disabled: true } : {}),\n ...(validation && typeof validation.required !== 'undefined' ? { required: true } : {}),\n ...registered,\n onBeforeInput: HandleBeforeInput,\n onChange: (event: React.ChangeEvent<HTMLTextAreaElement>) => {\n HandleChange(event);\n registered?.onChange?.(event);\n },\n onBlur: (event: React.FocusEvent<HTMLTextAreaElement>) => {\n HandleOnBlur(event);\n registered?.onBlur?.(event);\n },\n onKeyDown: HandleKeyEvent,\n ...htmlNativeDomProps,\n 'aria-describedby': mergedDescribedBy,\n };\n\n return (\n <HookFormWrapper>\n { customContent?.preField && <span className=\"preField\">{ customContent?.preField }</span> }\n\n <div className=\"textareaFieldContainer\">\n <textarea { ...textareaProps } /> \n\n <div className=\"textareaFooter\">\n { isInvalid && isRequiredError\n ? <ValidationMessages name={ name } validation={ { required: validation?.required } } />\n : (\n <div\n id={ characterCounterId }\n className={ `textareaCharacterCount ${\n isAtLimit\n ? 'textareaCharacterCountExceeded'\n : ''\n }` }\n role={ isAtLimit ? 'status' : undefined }\n aria-live={ isAtLimit ? 'polite' : undefined }\n aria-atomic={ isAtLimit ? 'true' : undefined }\n >\n { characterCounter }\n </div>\n )\n }\n </div>\n </div>\n\n { customContent?.postField && <span className=\"postField\">{ customContent?.postField }</span> }\n </HookFormWrapper>\n );\n};\n"],"mappings":"AAAA,YAAY;;AAEZ,OAAOA,KAAK,IAAIC,OAAO,EAAEC,QAAQ,QAAQ,OAAO;AAChD,SAASC,cAAc,QAAQ,iBAAiB;AAChD,SAASC,eAAe,QAAQ,0CAA0C;AAE1E,SAASC,iBAAiB,QAAQ,+BAA+B;AACjE,SAASC,YAAY,EAAEC,kBAAkB,QAAQ,wCAAwC;AAIzF;AACA;AACA;AACA;AACA;AACA,SAASC,iBAAiBA,CAACC,KAAa,EAAU;EAChD,IAAI,OAAOC,IAAI,KAAK,WAAW,IAAI,WAAW,IAAIA,IAAI,EAAE;IACtD,MAAMC,SAAS,GAAG,IAAID,IAAI,CAACE,SAAS,CAACC,SAAS,EAAE;MAC9CC,WAAW,EAAE;IACf,CAAC,CAAC;IACF,OAAOC,KAAK,CAACC,IAAI,CAACL,SAAS,CAACM,OAAO,CAACR,KAAK,CAAC,CAAC,CAACS,MAAM;EACpD;EACA,OAAOH,KAAK,CAACC,IAAI,CAACP,KAAK,CAAC,CAACS,MAAM;AACjC;AAEA,SAASC,kBAAkBA,CAACV,KAAa,EAAEW,UAAkB,EAAU;EACrE,IAAIZ,iBAAiB,CAACC,KAAK,CAAC,IAAIW,UAAU,EAAE;IAC1C,OAAOX,KAAK;EACd;EAEA,IAAI,OAAOC,IAAI,KAAK,WAAW,IAAI,WAAW,IAAIA,IAAI,EAAE;IACtD,MAAMC,SAAS,GAAG,IAAID,IAAI,CAACE,SAAS,CAACC,SAAS,EAAE;MAC9CC,WAAW,EAAE;IACf,CAAC,CAAC;IAEF,OAAOC,KAAK,CAACC,IAAI,CAACL,SAAS,CAACM,OAAO,CAACR,KAAK,CAAC,CAAC,CACxCY,KAAK,CAAC,CAAC,EAAED,UAAU,CAAC,CACpBE,GAAG,CAAEL,OAAO,IAAKA,OAAO,CAACA,OAAO,CAAC,CACjCM,IAAI,CAAC,EAAE,CAAC;EACb;EAEA,OAAOR,KAAK,CAACC,IAAI,CAACP,KAAK,CAAC,CAACY,KAAK,CAAC,CAAC,EAAED,UAAU,CAAC,CAACG,IAAI,CAAC,EAAE,CAAC;AACxD;AAEA,OAAO,MAAMC,QAAiC,GAAGA,CAC/C;EACEC,KAAK,EAAE;IACLC,EAAE;IACFC,IAAI;IACJC,WAAW;IACXC,YAAY;IACZC,SAAS;IACTC,gBAAgB;IAChBC,MAAM,GAAGA,CAAA,KAAM,CAAC,CAAC;IACjBC,QAAQ,GAAGA,CAAA,KAAM,CAAC,CAAC;IACnBC,SAAS,GAAGA,CAAA,KAAM,CAAC,CAAC;IACpBC,SAAS,GAAGA,CAAA,KAAM,CAAC,CAAC;IACpB,GAAGC;EACL,CAAC;EACDC,UAAU;EACVC,WAAW;EACXC,gBAAgB;EAChBC;AACF,CAAC,KACE;EACH,MAAM;IAAEC,QAAQ;IAAEC,aAAa;IAAEC,SAAS,EAAE;MAAEC;IAAO;EAAE,CAAC,GAAGzC,cAAc,CAAC,CAAC,IAAIE,iBAAiB;EAChG,MAAMwC,UAAU,GAAGH,aAAa,CAACf,IAAI,CAAC;EACtC,MAAMmB,aAAa,GAAGC,OAAO,CAACzC,YAAY,CAACsC,MAAM,EAAEjB,IAAI,CAAC,CAAC;EACzD;EACA;EACA,MAAMqB,SAAS,GAAGD,OAAO,CAACF,UAAU,EAAEI,OAAO,IAAIH,aAAa,CAAC;EAC/D,MAAM,CAACI,KAAK,EAAEC,QAAQ,CAAC,GAAGjD,QAAQ,CAAS,MACzCM,iBAAiB,CAACqB,YAAY,EAAEuB,QAAQ,CAAC,CAAC,IAAI,EAAE,CAClD,CAAC;EACD,MAAM,CAACC,gBAAgB,EAAEC,mBAAmB,CAAC,GAAGpD,QAAQ,CAAC,KAAK,CAAC;EAC/D,MAAMqD,YAAY,GAAG,OAAOzB,SAAS,KAAK,QAAQ;EAClD,MAAM0B,SAAS,GAAGD,YAAY,GAAGL,KAAK,IAAIpB,SAAS,GAAG,KAAK;EAC3D;EACA;EACA,MAAM2B,eAAe,GAAGZ,UAAU,EAAEa,KAAK,EAAEC,IAAI,KAAK,UAAU;EAC9D,MAAMC,gBAAgB,GACpB,CAACP,gBAAgB,IAAI,CAACE,YAAY,IAAIE,eAAe,GACjD5C,SAAS,GACT,GAAIqC,KAAK,IAAMpB,SAAS,EAAG;EACjC,MAAM+B,QAAQ,GAAG,GAAItB,gBAAgB,EAAEuB,KAAK,IAAI,EAAE,GAAKd,SAAS,GAAG,eAAe,GAAG,EAAE,EAAG;EAE1F,MAAMe,oBAAoB,GAAG9D,OAAO,CAAC,MAAM;IACzC,IAAI,CAACoC,UAAU,IAAI,OAAOA,UAAU,CAACP,SAAS,KAAK,WAAW,EAAE;MAC9D,OAAOO,UAAU;IACnB;IAEA,MAAM2B,aAAa,GAAG3B,UAAU,CAACP,SAAS;IAC1C,MAAMmC,cAAc,GAClB,OAAOD,aAAa,KAAK,QAAQ,GAC7BA,aAAa,GACb,OAAOA,aAAa,KAAK,QAAQ,IAAIA,aAAa,IAAI,OAAO,IAAIA,aAAa,GAC5EE,MAAM,CAACF,aAAa,CAACvD,KAAK,CAAC,GAC3BI,SAAS;IAEjB,IAAI,OAAOoD,cAAc,KAAK,QAAQ,IAAIC,MAAM,CAACC,KAAK,CAACF,cAAc,CAAC,EAAE;MACtE,OAAO5B,UAAU;IACnB;IAEA,MAAM+B,gBAAgB,GAAG,qBAAsBH,cAAc,EAAG;IAEhE,MAAMI,0BAA0B,GAAI5D,KAAa,IAC/CD,iBAAiB,CAACC,KAAK,IAAI,EAAE,CAAC,IAAIwD,cAAc,IAAIG,gBAAgB;;IAEtE;IACA,MAAM;MAAEtC,SAAS,EAAEwC,UAAU;MAAEC,QAAQ;MAAE,GAAGC;IAAe,CAAC,GAAGnC,UAAU;IAEzE,IAAI,OAAOkC,QAAQ,KAAK,UAAU,EAAE;MAClC,OAAO;QACL,GAAGC,cAAc;QACjBD,QAAQ,EAAE,MAAAA,CAAO9D,KAAa,EAAEgE,UAAoB,KAAK;UACvD,MAAMC,gBAAgB,GAAG,MAAMH,QAAQ,CAAC9D,KAAK,EAAEgE,UAAU,CAAC;UAC1D,IAAIC,gBAAgB,KAAK,IAAI,EAAE;YAC7B,OAAOA,gBAAgB;UACzB;UACA,OAAOL,0BAA0B,CAAC5D,KAAK,CAAC;QAC1C;MACF,CAAC;IACH;IAEA,IAAI8D,QAAQ,IAAI,OAAOA,QAAQ,KAAK,QAAQ,EAAE;MAC5C,OAAO;QACL,GAAGC,cAAc;QACjBD,QAAQ,EAAE;UACR,GAAGA,QAAQ;UACXI,iBAAiB,EAAEN;QACrB;MACF,CAAC;IACH;IAEA,OAAO;MACL,GAAGG,cAAc;MACjBD,QAAQ,EAAEF;IACZ,CAAC;EACH,CAAC,EAAE,CAAChC,UAAU,CAAC,CAAC;EAEhB,MAAMuC,UAAU,GAAGnC,QAAQ,CAACd,IAAI,EAAEoC,oBAAoB,CAAC;;EAEvD;AACF;AACA;AACA;AACA;AACA;EACE,MAAMc,iBAAiB,GAAIC,KAA2C,IAAK;IACzE,IAAI/C,gBAAgB,KAAK,IAAI,IAAI,CAACwB,YAAY,EAAE;IAEhD,MAAMwB,WAAW,GAAGD,KAAK,CAACC,WAAyB;IACnD,MAAMC,QAAQ,GAAGD,WAAW,CAACE,IAAI,IAAI,EAAE;IAEvC,IAAI,CAACD,QAAQ,EAAE;IAEf,MAAME,MAAM,GAAGJ,KAAK,CAACK,aAAa;IAClC,MAAMC,KAAK,GAAGF,MAAM,CAACG,cAAc,IAAIH,MAAM,CAACzE,KAAK,CAACS,MAAM;IAC1D,MAAMoE,GAAG,GAAGJ,MAAM,CAACK,YAAY,IAAIL,MAAM,CAACzE,KAAK,CAACS,MAAM;IAEtD,MAAMsE,SAAS,GACbN,MAAM,CAACzE,KAAK,CAACY,KAAK,CAAC,CAAC,EAAE+D,KAAK,CAAC,GAC5BJ,QAAQ,GACRE,MAAM,CAACzE,KAAK,CAACY,KAAK,CAACiE,GAAG,CAAC;IAEzB,IAAI9E,iBAAiB,CAACgF,SAAS,CAAC,GAAG1D,SAAS,EAAE;MAC5CgD,KAAK,CAACW,cAAc,CAAC,CAAC;IACxB;EACF,CAAC;EAED,MAAMC,YAAY,GAAIZ,KAA6C,IAAK;IACtE,MAAMa,QAAQ,GAAGb,KAAK,CAACI,MAAM,CAACzE,KAAK,IAAI,EAAE;IACzC,MAAMmF,QAAQ,GACZ7D,gBAAgB,KAAK,IAAI,IAAIwB,YAAY,GACrCpC,kBAAkB,CAACwE,QAAQ,EAAE7D,SAAS,CAAC,GACvC6D,QAAQ;IAEd,IAAIC,QAAQ,KAAKD,QAAQ,EAAE;MACzBb,KAAK,CAACI,MAAM,CAACzE,KAAK,GAAGmF,QAAQ;IAC/B;IAEAtC,mBAAmB,CAAC,IAAI,CAAC;IACzBH,QAAQ,CAAC3C,iBAAiB,CAACoF,QAAQ,CAAC,CAAC;IACrC,MAAMC,gBAAgB,GAAG5D,QAEZ;IACb4D,gBAAgB,GAAGf,KAAK,CAAC;EAC3B,CAAC;EAED,MAAMgB,YAAY,GAAIhB,KAA4C,IAAK;IACrE,MAAM;MAAEI;IAAO,CAAC,GAAGJ,KAAK;IACxB,IAAII,MAAM,EAAE;MACV/C,SAAS,CAAC,CAAC;MACXH,MAAM,CAAC8C,KAAK,CAAC;IACf;EACF,CAAC;EAED,MAAMiB,cAAc,GAAIjB,KAA+C,IAAK;IAC1E3C,SAAS,CAAC,CAAC;IACX,MAAM6D,iBAAiB,GAAG9D,SAEb;IACb8D,iBAAiB,GAAGlB,KAAK,CAAC;EAC5B,CAAC;EAED,MAAMmB,kBAAkB,GAAG,GAAIvE,EAAE,iBAAkB;EACnD,MAAMwE,QAAQ,GAAG,GAAIvE,IAAI,SAAU;EACnC,MAAMwE,mBAAmB,GACvB,OAAO/D,kBAAkB,CAAC,kBAAkB,CAAC,KAAK,QAAQ,GACtDA,kBAAkB,CAAC,kBAAkB,CAAC,GACtCvB,SAAS;EACf,MAAMuF,kBAAkB,GAAGpD,SAAS,IAAIS,eAAe;EACvD,MAAM4C,iBAAiB,GAAGD,kBAAkB,GACxC,CAACD,mBAAmB,EAAED,QAAQ,CAAC,CAACI,MAAM,CAACvD,OAAO,CAAC,CAACxB,IAAI,CAAC,GAAG,CAAC,GACzDqC,gBAAgB,KAAK/C,SAAS,GAC5B,CAACsF,mBAAmB,EAAEF,kBAAkB,CAAC,CAACK,MAAM,CAACvD,OAAO,CAAC,CAACxB,IAAI,CAAC,GAAG,CAAC,GACnE4E,mBAAmB;EAEzB,MAAMI,aAAa,GAAG;IACpB7E,EAAE;IACF8E,SAAS,EAAE3C,QAAQ;IACnBjC,WAAW;IACXC,YAAY;IACZ,IAAIS,WAAW,GAAG;MAAEmE,QAAQ,EAAE;IAAK,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1C,IAAIpE,UAAU,IAAI,OAAOA,UAAU,CAACqE,QAAQ,KAAK,WAAW,GAAG;MAAEA,QAAQ,EAAE;IAAK,CAAC,GAAG,CAAC,CAAC,CAAC;IACvF,GAAG9B,UAAU;IACb+B,aAAa,EAAE9B,iBAAiB;IAChC5C,QAAQ,EAAG6C,KAA6C,IAAK;MAC3DY,YAAY,CAACZ,KAAK,CAAC;MACnBF,UAAU,EAAE3C,QAAQ,GAAG6C,KAAK,CAAC;IAC/B,CAAC;IACD9C,MAAM,EAAG8C,KAA4C,IAAK;MACxDgB,YAAY,CAAChB,KAAK,CAAC;MACnBF,UAAU,EAAE5C,MAAM,GAAG8C,KAAK,CAAC;IAC7B,CAAC;IACD5C,SAAS,EAAE6D,cAAc;IACzB,GAAG3D,kBAAkB;IACrB,kBAAkB,EAAEiE;EACtB,CAAC;EAED,oBACErG,KAAA,CAAA4G,aAAA,CAACxG,eAAe,QACZoC,aAAa,EAAEqE,QAAQ,iBAAI7G,KAAA,CAAA4G,aAAA;IAAMJ,SAAS,EAAC;EAAU,GAAGhE,aAAa,EAAEqE,QAAgB,CAAC,eAE1F7G,KAAA,CAAA4G,aAAA;IAAKJ,SAAS,EAAC;EAAwB,gBACrCxG,KAAA,CAAA4G,aAAA,aAAeL,aAAiB,CAAC,eAEjCvG,KAAA,CAAA4G,aAAA;IAAKJ,SAAS,EAAC;EAAgB,GAC3BxD,SAAS,IAAIS,eAAe,gBAC1BzD,KAAA,CAAA4G,aAAA,CAACrG,kBAAkB;IAACoB,IAAI,EAAGA,IAAM;IAACU,UAAU,EAAG;MAAEqE,QAAQ,EAAErE,UAAU,EAAEqE;IAAS;EAAG,CAAE,CAAC,gBAEtF1G,KAAA,CAAA4G,aAAA;IACElF,EAAE,EAAGuE,kBAAoB;IACzBO,SAAS,EAAG,0BACVhD,SAAS,GACL,gCAAgC,GAChC,EAAE,EACJ;IACJsD,IAAI,EAAGtD,SAAS,GAAG,QAAQ,GAAG3C,SAAW;IACzC,aAAY2C,SAAS,GAAG,QAAQ,GAAG3C,SAAW;IAC9C,eAAc2C,SAAS,GAAG,MAAM,GAAG3C;EAAW,GAE5C+C,gBACC,CAGN,CACF,CAAC,EAEJpB,aAAa,EAAEuE,SAAS,iBAAI/G,KAAA,CAAA4G,aAAA;IAAMJ,SAAS,EAAC;EAAW,GAAGhE,aAAa,EAAEuE,SAAiB,CAC7E,CAAC;AAEtB,CAAC","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"Textarea.js","names":["React","useMemo","useState","useFormContext","HookFormWrapper","extractError","clampToGraphemeMax","getCharacterCount","Textarea","props","createElement","formContext","TextareaField","field","id","name","placeholder","defaultValue","maxLength","enforceMaxLength","onBlur","onChange","onKeyDown","onTouched","htmlNativeDomProps","validation","showSpinner","customCssClasses","customContent","register","getFieldState","formState","errors","fieldState","isInvalid","Boolean","invalid","isRequiredError","error","type","count","setCount","toString","hasStartedTyping","setHasStartedTyping","hasMaxLength","isAtLimit","showsCharacterCount","cssClass","input","normalizedValidation","maxLengthRule","maxLengthValue","Number","value","undefined","isNaN","maxLengthMessage","graphemeMaxLengthValidator","_maxLength","validate","restValidation","formValues","validationResult","graphemeMaxLength","fieldRegistration","HandleBeforeInput","event","nativeEvent","inserted","data","target","currentTarget","start","selectionStart","length","end","selectionEnd","nextValue","slice","preventDefault","HandleChange","rawValue","newValue","HandleAutoFill","animationName","HandleOnBlur","HandleKeyEvent","textareaProps","className","disabled","required","onBeforeInput","onAnimationStart","containerCssClass","Fragment","preField","role","postField"],"sources":["../../../../../../../src/components/form/formFields/subComponents/textarea/Textarea.tsx"],"sourcesContent":["'use client';\n\nimport React, { useMemo, useState } from 'react';\nimport { useFormContext } from 'react-hook-form';\nimport { HookFormWrapper } from '../../../hookFormWrapper/HookFormWrapper';\nimport {\n FormFieldProps,\n TextareaFieldProps,\n} from '../../formFieldWrapper/formFieldProps';\nimport { extractError } from '../../../validation/ValidationMessages';\nimport { clampToGraphemeMax, getCharacterCount } from '../../../../../helpers/stringHelpers';\n\nimport './textarea.scss';\n\nexport interface TextareaProps extends Omit<FormFieldProps, 'field'> {\n field: Omit<TextareaFieldProps, 'type'>;\n}\n\nexport const Textarea: React.FC<TextareaProps> = (props) => (\n <HookFormWrapper formContext={ props.formContext }>\n <TextareaField { ...props } />\n </HookFormWrapper>\n);\n\nconst TextareaField: React.FC<TextareaProps> = (\n {\n field: {\n id,\n name,\n placeholder,\n defaultValue,\n maxLength,\n enforceMaxLength,\n onBlur = () => {},\n onChange = () => {},\n onKeyDown = () => {},\n onTouched = () => {},\n ...htmlNativeDomProps\n },\n validation,\n showSpinner,\n customCssClasses,\n customContent\n }\n) => {\n const { register, getFieldState, formState: { errors } } = useFormContext();\n const fieldState = getFieldState(name);\n // getFieldState alone does not subscribe to errors, so the direct lookup keeps this in sync.\n const isInvalid = Boolean(fieldState?.invalid || extractError(errors, name));\n const isRequiredError = fieldState?.error?.type === 'required';\n\n const [count, setCount] = useState<number>(() => getCharacterCount(defaultValue?.toString() || ''));\n const [hasStartedTyping, setHasStartedTyping] = useState(false);\n\n const hasMaxLength = typeof maxLength === 'number';\n const isAtLimit = hasMaxLength ? count >= maxLength : false;\n const showsCharacterCount = hasStartedTyping && hasMaxLength && !isRequiredError;\n\n const cssClass = `${ customCssClasses?.input || '' }${ isInvalid ? ' invalidField' : '' }`;\n\n const normalizedValidation = useMemo(() => {\n if (!validation || typeof validation.maxLength === 'undefined') {\n return validation;\n }\n\n const maxLengthRule = validation.maxLength;\n const maxLengthValue =\n typeof maxLengthRule === 'number'\n ? maxLengthRule\n : typeof maxLengthRule === 'object' && maxLengthRule && 'value' in maxLengthRule\n ? Number(maxLengthRule.value)\n : undefined;\n\n if (typeof maxLengthValue !== 'number' || Number.isNaN(maxLengthValue)) {\n return validation;\n }\n\n const maxLengthMessage = `Maximum length is ${ maxLengthValue }`;\n\n const graphemeMaxLengthValidator = (value: string) =>\n getCharacterCount(value || '') <= maxLengthValue || maxLengthMessage;\n\n // eslint-disable-next-line no-unused-vars\n const { maxLength: _maxLength, validate, ...restValidation } = validation;\n\n if (typeof validate === 'function') {\n return {\n ...restValidation,\n validate: async (value: string, formValues?: unknown) => {\n const validationResult = await validate(value, formValues);\n\n if (validationResult !== true) {\n return validationResult;\n }\n\n return graphemeMaxLengthValidator(value);\n },\n };\n }\n\n if (validate && typeof validate === 'object') {\n return {\n ...restValidation,\n validate: {\n ...validate,\n graphemeMaxLength: graphemeMaxLengthValidator,\n },\n };\n }\n\n return {\n ...restValidation,\n validate: graphemeMaxLengthValidator,\n };\n }, [validation]);\n\n const fieldRegistration = register(name, normalizedValidation);\n\n /**\n * Native maxLength counts UTF-16 units, so emojis and composed characters are treated as\n * several characters. The limit is enforced here against grapheme clusters instead.\n */\n const HandleBeforeInput = (event: React.FormEvent<HTMLTextAreaElement>) => {\n if (enforceMaxLength !== true || !hasMaxLength) {\n return;\n }\n\n const nativeEvent = event.nativeEvent as InputEvent;\n const inserted = nativeEvent.data ?? '';\n\n if (!inserted) {\n return;\n }\n\n const target = event.currentTarget;\n const start = target.selectionStart ?? target.value.length;\n const end = target.selectionEnd ?? target.value.length;\n const nextValue = target.value.slice(0, start) + inserted + target.value.slice(end);\n\n if (getCharacterCount(nextValue) > maxLength) {\n event.preventDefault();\n }\n };\n\n const HandleChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {\n const rawValue = event.target.value || '';\n const newValue = enforceMaxLength === true && hasMaxLength\n ? clampToGraphemeMax(rawValue, maxLength)\n : rawValue;\n\n if (newValue !== rawValue) {\n event.target.value = newValue;\n }\n\n setHasStartedTyping(true);\n setCount(getCharacterCount(newValue));\n\n (onChange as React.ChangeEventHandler<HTMLTextAreaElement>)(event);\n fieldRegistration?.onChange?.(event);\n };\n\n const HandleAutoFill = (event: React.AnimationEvent<HTMLTextAreaElement>) => {\n // Browsers trigger onAnimationStart when autofill happens.\n // We need to notify react-hook-form of the new value.\n if (event.animationName === 'onAutoFill') {\n const { value } = event.currentTarget;\n setHasStartedTyping(true);\n setCount(getCharacterCount(value || ''));\n HandleChange({ target: event.currentTarget } as unknown as React.ChangeEvent<HTMLTextAreaElement>);\n }\n };\n\n const HandleOnBlur = (event: React.FocusEvent<HTMLTextAreaElement>) => {\n const { target } = event;\n\n if (target) {\n onTouched();\n (onBlur as React.FocusEventHandler<HTMLTextAreaElement>)(event);\n }\n\n fieldRegistration?.onBlur?.(event);\n };\n\n const HandleKeyEvent = (event: React.KeyboardEvent<HTMLTextAreaElement>) => {\n onTouched();\n (onKeyDown as React.KeyboardEventHandler<HTMLTextAreaElement>)(event);\n };\n\n const textareaProps = {\n id,\n className: cssClass,\n placeholder,\n defaultValue,\n ...(showSpinner ? { disabled: true } : {}),\n ...(validation && typeof validation.required !== 'undefined' ? { required: true } : {}),\n ...htmlNativeDomProps,\n ...fieldRegistration,\n onBeforeInput: HandleBeforeInput,\n onChange: HandleChange,\n onBlur: HandleOnBlur,\n onKeyDown: HandleKeyEvent,\n onAnimationStart: HandleAutoFill,\n };\n\n const containerCssClass = `textareaFieldContainer${ showsCharacterCount ? ' withCharacterCount' : '' }`;\n\n return (\n <>\n { customContent?.preField && <span className=\"preField\">{ customContent?.preField }</span> }\n\n <span className={ containerCssClass }>\n <textarea { ...textareaProps } />\n\n {\n showsCharacterCount && (\n <span\n className={ `textareaCharacterCount ${ isAtLimit ? 'textareaCharacterCountExceeded' : '' }` }\n role={ isAtLimit ? 'status' : undefined }\n aria-live={ isAtLimit ? 'polite' : undefined }\n aria-atomic={ isAtLimit ? 'true' : undefined }\n >\n { `${ count }/${ maxLength }` }\n </span>\n )\n }\n </span>\n\n { customContent?.postField && <span className=\"postField\">{ customContent?.postField }</span> }\n </>\n );\n};\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
.textareaFieldContainer {
|
|
2
|
+
position: relative;
|
|
3
|
+
width: 100%;
|
|
4
|
+
}
|
|
5
|
+
.textareaFieldContainer.withCharacterCount textarea {
|
|
6
|
+
padding-bottom: 26px;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.textareaCharacterCount {
|
|
10
|
+
line-height: 15px;
|
|
11
|
+
font-size: 13px;
|
|
12
|
+
color: var(--inputLabelColor);
|
|
13
|
+
position: absolute;
|
|
14
|
+
right: 10px;
|
|
15
|
+
bottom: 10px;
|
|
16
|
+
pointer-events: none;
|
|
17
|
+
}
|
|
18
|
+
.textareaCharacterCount.textareaCharacterCountExceeded {
|
|
19
|
+
color: var(--inputErrorColor);
|
|
20
|
+
}
|
|
@@ -6,21 +6,38 @@ import { FormProvider, useForm, useFormContext } from 'react-hook-form';
|
|
|
6
6
|
export const HookFormWrapper = ({
|
|
7
7
|
formCssClass = 'x15StandardForm',
|
|
8
8
|
children,
|
|
9
|
-
formProps
|
|
9
|
+
formProps,
|
|
10
|
+
formContext,
|
|
11
|
+
onSubmit
|
|
10
12
|
}) => {
|
|
11
|
-
const
|
|
13
|
+
const inheritedHookFormContext = useFormContext();
|
|
12
14
|
const hookFormMethods = useForm({
|
|
13
15
|
mode: 'all',
|
|
14
16
|
criteriaMode: 'all',
|
|
15
17
|
shouldFocusError: true
|
|
16
18
|
});
|
|
17
|
-
|
|
18
|
-
|
|
19
|
+
|
|
20
|
+
// A manually supplied context re-publishes the form state across a boundary the
|
|
21
|
+
// React context could not cross (e.g. a Next.js server/client component split).
|
|
22
|
+
if (formContext) {
|
|
23
|
+
return /*#__PURE__*/React.createElement(FormProvider, formContext, children);
|
|
24
|
+
}
|
|
25
|
+
if (inheritedHookFormContext) {
|
|
26
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, children);
|
|
19
27
|
}
|
|
28
|
+
const {
|
|
29
|
+
onSubmit: nativeOnSubmit,
|
|
30
|
+
...remainingFormProps
|
|
31
|
+
} = formProps || {};
|
|
32
|
+
|
|
33
|
+
// `onSubmit` receives the validated values, so consumers never need to call useForm themselves.
|
|
34
|
+
const handleFormSubmit = onSubmit ? hookFormMethods.handleSubmit(onSubmit) : nativeOnSubmit;
|
|
20
35
|
return /*#__PURE__*/React.createElement(FormProvider, hookFormMethods, /*#__PURE__*/React.createElement("form", _extends({
|
|
21
36
|
className: formCssClass,
|
|
22
37
|
autoComplete: "off"
|
|
23
|
-
},
|
|
38
|
+
}, remainingFormProps, {
|
|
39
|
+
onSubmit: handleFormSubmit
|
|
40
|
+
}), children));
|
|
24
41
|
};
|
|
25
42
|
export default HookFormWrapper;
|
|
26
43
|
//# sourceMappingURL=HookFormWrapper.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HookFormWrapper.js","names":["_extends","React","FormProvider","useForm","useFormContext","HookFormWrapper","formCssClass","children","formProps","
|
|
1
|
+
{"version":3,"file":"HookFormWrapper.js","names":["_extends","React","FormProvider","useForm","useFormContext","HookFormWrapper","formCssClass","children","formProps","formContext","onSubmit","inheritedHookFormContext","hookFormMethods","mode","criteriaMode","shouldFocusError","createElement","Fragment","nativeOnSubmit","remainingFormProps","handleFormSubmit","handleSubmit","className","autoComplete"],"sources":["../../../../../src/components/form/hookFormWrapper/HookFormWrapper.tsx"],"sourcesContent":["'use client';\n\nimport React, { ReactNode, ReactElement, FormHTMLAttributes } from 'react';\nimport { FieldValues, FormProvider, useForm, useFormContext, UseFormReturn } from 'react-hook-form';\n\ninterface FormWrapperProps {\n formCssClass?: string;\n formProps?: FormHTMLAttributes<HTMLFormElement>;\n children: ReactNode | ReactElement;\n formContext?: UseFormReturn<FieldValues, any, FieldValues>\n /* eslint-disable-next-line no-unused-vars */\n onSubmit?: (values: FieldValues) => void | Promise<void>;\n}\n\nexport const HookFormWrapper: React.FC<FormWrapperProps> = (\n {\n formCssClass = 'x15StandardForm',\n children,\n formProps,\n formContext,\n onSubmit,\n }\n) => {\n const inheritedHookFormContext = useFormContext();\n\n const hookFormMethods = useForm({\n mode: 'all',\n criteriaMode: 'all',\n shouldFocusError: true\n });\n\n // A manually supplied context re-publishes the form state across a boundary the\n // React context could not cross (e.g. a Next.js server/client component split).\n if (formContext) {\n return (\n <FormProvider { ...formContext }>\n { children }\n </FormProvider>\n );\n }\n\n if (inheritedHookFormContext) {\n return <>{ children }</>;\n }\n\n const { onSubmit: nativeOnSubmit, ...remainingFormProps } = formProps || {};\n\n // `onSubmit` receives the validated values, so consumers never need to call useForm themselves.\n const handleFormSubmit = onSubmit\n ? hookFormMethods.handleSubmit(onSubmit)\n : nativeOnSubmit;\n\n return (\n <FormProvider { ...hookFormMethods }>\n <form\n className={ formCssClass }\n autoComplete=\"off\"\n { ...remainingFormProps }\n onSubmit={ handleFormSubmit }\n >\n {\n children\n }\n </form>\n </FormProvider>\n );\n};\n\nexport default HookFormWrapper;\n"],"mappings":"AAAA,YAAY;;AAAC,OAAAA,QAAA;AAEb,OAAOC,KAAK,MAAuD,OAAO;AAC1E,SAAsBC,YAAY,EAAEC,OAAO,EAAEC,cAAc,QAAuB,iBAAiB;AAWnG,OAAO,MAAMC,eAA2C,GAAGA,CACzD;EACEC,YAAY,GAAG,iBAAiB;EAChCC,QAAQ;EACRC,SAAS;EACTC,WAAW;EACXC;AACF,CAAC,KACE;EACH,MAAMC,wBAAwB,GAAGP,cAAc,CAAC,CAAC;EAEjD,MAAMQ,eAAe,GAAGT,OAAO,CAAC;IAC9BU,IAAI,EAAE,KAAK;IACXC,YAAY,EAAE,KAAK;IACnBC,gBAAgB,EAAE;EACpB,CAAC,CAAC;;EAEF;EACA;EACA,IAAIN,WAAW,EAAE;IACf,oBACER,KAAA,CAAAe,aAAA,CAACd,YAAY,EAAMO,WAAW,EAC1BF,QACU,CAAC;EAEnB;EAEA,IAAII,wBAAwB,EAAE;IAC5B,oBAAOV,KAAA,CAAAe,aAAA,CAAAf,KAAA,CAAAgB,QAAA,QAAIV,QAAY,CAAC;EAC1B;EAEA,MAAM;IAAEG,QAAQ,EAAEQ,cAAc;IAAE,GAAGC;EAAmB,CAAC,GAAGX,SAAS,IAAI,CAAC,CAAC;;EAE3E;EACA,MAAMY,gBAAgB,GAAGV,QAAQ,GAC7BE,eAAe,CAACS,YAAY,CAACX,QAAQ,CAAC,GACtCQ,cAAc;EAElB,oBACEjB,KAAA,CAAAe,aAAA,CAACd,YAAY,EAAMU,eAAe,eAChCX,KAAA,CAAAe,aAAA,SAAAhB,QAAA;IACEsB,SAAS,EAAGhB,YAAc;IAC1BiB,YAAY,EAAC;EAAK,GACbJ,kBAAkB;IACvBT,QAAQ,EAAGU;EAAkB,IAG3Bb,QAEE,CACM,CAAC;AAEnB,CAAC;AAED,eAAeF,eAAe","ignoreList":[]}
|
|
@@ -1,19 +1,27 @@
|
|
|
1
|
-
/* eslint-disable no-unused-vars */
|
|
2
|
-
|
|
3
1
|
'use client';
|
|
4
2
|
|
|
5
3
|
import React from 'react';
|
|
6
|
-
import { ErrorMessage } from '@hookform/error-message';
|
|
7
4
|
import { useFormContext } from 'react-hook-form';
|
|
8
|
-
import { NoHookFormContext } from '../formFields/utilities/formUtilities';
|
|
9
5
|
// Type for generic error messages
|
|
10
6
|
export const GenericErrorMessages = {
|
|
11
|
-
required:
|
|
12
|
-
minLength:
|
|
13
|
-
maxLength:
|
|
14
|
-
min:
|
|
15
|
-
max:
|
|
16
|
-
unknown:
|
|
7
|
+
required: 'This field is required. Please enter a value.',
|
|
8
|
+
minLength: 'Please provide a minimum of {value} characters.',
|
|
9
|
+
maxLength: 'Please provide a maximum of {value} characters.',
|
|
10
|
+
min: 'The value must be a minimum of {value}.',
|
|
11
|
+
max: 'The value must be a maximum of {value}.',
|
|
12
|
+
unknown: 'An unknown error has occurred.'
|
|
13
|
+
};
|
|
14
|
+
const isGenericErrorType = errorType => typeof errorType === 'string' && errorType !== 'unknown' && Object.prototype.hasOwnProperty.call(GenericErrorMessages, errorType);
|
|
15
|
+
const getValidationValue = validator => typeof validator === 'object' ? validator.value : validator;
|
|
16
|
+
const getGenericErrorMessage = (errorType, validation) => {
|
|
17
|
+
if (!isGenericErrorType(errorType)) {
|
|
18
|
+
return undefined;
|
|
19
|
+
}
|
|
20
|
+
if (errorType === 'required') {
|
|
21
|
+
return GenericErrorMessages.required;
|
|
22
|
+
}
|
|
23
|
+
const value = getValidationValue(validation?.[errorType]);
|
|
24
|
+
return value === undefined ? undefined : GenericErrorMessages[errorType].replace('{value}', String(value));
|
|
17
25
|
};
|
|
18
26
|
|
|
19
27
|
// Helper function to extract nested errors
|
|
@@ -33,49 +41,39 @@ export const ValidationMessages = ({
|
|
|
33
41
|
name,
|
|
34
42
|
validation
|
|
35
43
|
}) => {
|
|
44
|
+
const formContext = useFormContext();
|
|
45
|
+
if (!formContext) {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
36
48
|
const {
|
|
37
49
|
formState: {
|
|
38
50
|
errors
|
|
39
51
|
}
|
|
40
|
-
} =
|
|
52
|
+
} = formContext;
|
|
41
53
|
const fieldError = extractError(errors, name);
|
|
42
54
|
if (!fieldError) {
|
|
43
55
|
return null;
|
|
44
56
|
}
|
|
45
57
|
|
|
46
|
-
//
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
// @ts-ignore The hook form types don't seem to cater for versions with value properties properly
|
|
58
|
-
fieldError.message = GenericErrorMessages[validatorKey](validator.value || undefined);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
});
|
|
62
|
-
}
|
|
58
|
+
// Derive a fallback message rather than mutating the error object held in formState.
|
|
59
|
+
const resolveMessage = () => {
|
|
60
|
+
if (fieldError.message) {
|
|
61
|
+
return fieldError.message;
|
|
62
|
+
}
|
|
63
|
+
if (fieldError.type && fieldError.types && typeof fieldError.types[fieldError.type] === 'string') {
|
|
64
|
+
return fieldError.types[fieldError.type];
|
|
65
|
+
}
|
|
66
|
+
return getGenericErrorMessage(fieldError.type, validation);
|
|
67
|
+
};
|
|
68
|
+
const message = resolveMessage() || GenericErrorMessages.unknown;
|
|
63
69
|
return /*#__PURE__*/React.createElement("span", {
|
|
64
70
|
className: "validation",
|
|
65
71
|
id: `${name}_errors`
|
|
66
72
|
}, /*#__PURE__*/React.createElement("span", {
|
|
67
73
|
className: "message"
|
|
68
|
-
},
|
|
74
|
+
}, /*#__PURE__*/React.createElement("span", {
|
|
69
75
|
className: "error"
|
|
70
|
-
},
|
|
71
|
-
errors: errors,
|
|
72
|
-
name: name,
|
|
73
|
-
render: ({
|
|
74
|
-
message
|
|
75
|
-
}) => /*#__PURE__*/React.createElement("span", {
|
|
76
|
-
className: "error"
|
|
77
|
-
}, message)
|
|
78
|
-
})));
|
|
76
|
+
}, message)));
|
|
79
77
|
};
|
|
80
78
|
export default ValidationMessages;
|
|
81
79
|
//# sourceMappingURL=ValidationMessages.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ValidationMessages.js","names":["React","
|
|
1
|
+
{"version":3,"file":"ValidationMessages.js","names":["React","useFormContext","GenericErrorMessages","required","minLength","maxLength","min","max","unknown","isGenericErrorType","errorType","Object","prototype","hasOwnProperty","call","getValidationValue","validator","value","getGenericErrorMessage","validation","undefined","replace","String","extractError","errors","fieldName","pathComponents","split","reduce","accumulator","pathComponent","ValidationMessages","name","formContext","formState","fieldError","resolveMessage","message","type","types","createElement","className","id"],"sources":["../../../../../src/components/form/validation/ValidationMessages.tsx"],"sourcesContent":[" \n\n'use client';\n\nimport React from 'react';\nimport {\n FieldError,\n FieldErrors,\n FieldErrorsImpl,\n Merge,\n ValidationRule,\n useFormContext\n} from 'react-hook-form';\nimport {\n ValidationProps\n} from '../formFields/formFieldWrapper/formFieldProps';\nimport { InputCheckboxValidationProps } from '../formFields/subComponents/inputs/checkbox/inputCheckboxProps';\n\n// Type for generic error messages\nexport const GenericErrorMessages = {\n required: 'This field is required. Please enter a value.',\n minLength: 'Please provide a minimum of {value} characters.',\n maxLength: 'Please provide a maximum of {value} characters.',\n min: 'The value must be a minimum of {value}.',\n max: 'The value must be a maximum of {value}.',\n unknown: 'An unknown error has occurred.'\n};\n\ntype ValidationRules = ValidationProps | InputCheckboxValidationProps;\ntype GenericErrorType = Exclude<keyof typeof GenericErrorMessages, 'unknown'>;\ntype ValidationErrorType = NonNullable<ReturnType<typeof extractError>>['type'];\n\nconst isGenericErrorType = (errorType: ValidationErrorType): errorType is GenericErrorType =>\n typeof errorType === 'string'\n && errorType !== 'unknown'\n && Object.prototype.hasOwnProperty.call(GenericErrorMessages, errorType);\n\nconst getValidationValue = <TValue extends string | number>(\n validator: ValidationRule<TValue> | undefined\n): TValue | undefined => typeof validator === 'object' ? validator.value : validator;\n\nconst getGenericErrorMessage = (\n errorType: ValidationErrorType,\n validation?: ValidationRules\n): string | undefined => {\n if (!isGenericErrorType(errorType)) {\n return undefined;\n }\n\n if (errorType === 'required') {\n return GenericErrorMessages.required;\n }\n\n const value = getValidationValue(validation?.[errorType]);\n\n return value === undefined\n ? undefined\n : GenericErrorMessages[errorType].replace('{value}', String(value));\n};\n\n// Helper function to extract nested errors\nexport const extractError = (\n errors: FieldErrors,\n fieldName: string\n): FieldError | Merge<FieldError, FieldErrorsImpl<never>> | undefined => {\n if (!errors) {\n return undefined;\n }\n\n const pathComponents = fieldName.split('.');\n\n return pathComponents.reduce<FieldError | Merge<FieldError, FieldErrorsImpl<never>> | undefined>(\n (accumulator, pathComponent) => {\n if (!accumulator) {\n return undefined;\n }\n\n return (accumulator as never)[pathComponent];\n },\n errors as never\n );\n};\n\ninterface ValidationMessagesProps {\n name: string;\n validation?: ValidationProps | InputCheckboxValidationProps\n}\n\nexport const ValidationMessages: React.FC<ValidationMessagesProps> = (\n {\n name,\n validation\n }\n) => {\n const formContext = useFormContext();\n\n if (!formContext) {\n return null;\n }\n\n const { formState: { errors } } = formContext;\n\n const fieldError = extractError(errors, name);\n\n if (!fieldError) {\n return null;\n }\n\n // Derive a fallback message rather than mutating the error object held in formState.\n const resolveMessage = (): string | undefined => {\n if (fieldError.message) {\n return fieldError.message as string;\n }\n\n if (\n fieldError.type\n && fieldError.types\n && typeof fieldError.types[fieldError.type] === 'string'\n ) {\n return fieldError.types[fieldError.type] as string;\n }\n\n return getGenericErrorMessage(fieldError.type, validation);\n };\n\n const message = resolveMessage() || GenericErrorMessages.unknown;\n\n return (\n <span className=\"validation\" id={ `${ name }_errors` }>\n <span className=\"message\">\n <span className=\"error\">{ message }</span>\n </span>\n </span>\n );\n};\n\nexport default ValidationMessages;\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DemoContactForm.js","names":["React","useEffect","useFormContext","TextInput","EmailInput","PhoneInput","SimpleButton","Textarea","InputCheckbox","Tooltip","DemoContactForm","onConsentClick","consentIsGiven","hasConsent","setHasConsent","useState","formContext","handleConsentClick","event","isChecked","target","checked","setValue","createElement","className","field","id","name","label","text","validation","required","
|
|
1
|
+
{"version":3,"file":"DemoContactForm.js","names":["React","useEffect","useFormContext","TextInput","EmailInput","PhoneInput","SimpleButton","Textarea","InputCheckbox","Tooltip","DemoContactForm","onConsentClick","consentIsGiven","hasConsent","setHasConsent","useState","formContext","handleConsentClick","event","isChecked","target","checked","setValue","createElement","className","field","id","name","label","text","validation","required","defaultChecked","value","onChange","icon","buttonType","buttonStyle","color","rightIcon"],"sources":["../../../../src/exampleUIs/exampleComponents/DemoContactForm.tsx"],"sourcesContent":["import React, { FC, useEffect } from 'react';\nimport { useFormContext } from 'react-hook-form';\nimport {\n TextInput,\n EmailInput,\n PhoneInput\n} from '../../components/form/formFields/subComponents/InputVariants';\nimport { SimpleButton } from '../../components/form/buttons/SimpleButton';\nimport { Textarea } from '../../components/form/formFields/subComponents/textarea/Textarea';\nimport { InputCheckbox } from '../../components/form/formFields/subComponents/inputs/checkbox/InputCheckbox';\nimport { Tooltip } from '../../components/design/tooltip/Tooltip';\nimport { GenericFunction } from '../../interfaces/generic.interface';\n\nexport const DemoContactForm: FC<{\n onConsentClick: GenericFunction;\n consentIsGiven: boolean;\n}> = (\n {\n onConsentClick = () => {},\n consentIsGiven = false\n }\n) => {\n const [hasConsent, setHasConsent] = React.useState<boolean>(consentIsGiven);\n\n const formContext = useFormContext();\n\n const handleConsentClick = (event: React.ChangeEvent<HTMLInputElement>) => {\n const isChecked = event.target.checked;\n formContext.setValue('consentCheckbox1', isChecked);\n setHasConsent(isChecked);\n onConsentClick(isChecked);\n };\n\n useEffect(() => {\n formContext.setValue('consentCheckbox1', consentIsGiven);\n setHasConsent(consentIsGiven);\n });\n\n return (\n <div>\n <h2 className=\"spaceAfter\">Can't find what you're looking for?</h2>\n <h3 className=\"spaceAfter\">Send us a message</h3>\n\n <p className=\"spaceAfter\">To provide you with the best service possible we'll need some details about you.</p>\n\n <TextInput\n field={ {\n id: 'firstName',\n name: 'firstName'\n } }\n label={ {\n text: 'First Name'\n } }\n validation={ {\n required: 'This is required'\n } }\n />\n\n <TextInput\n field={ {\n id: 'lastName',\n name: 'lastName'\n } }\n label={ {\n text: 'Last Name'\n } }\n validation={ {\n required: 'This is required'\n } }\n />\n\n <EmailInput\n field={ {\n id: 'yourEmail',\n name: 'yourEmail'\n } }\n label={ {\n text: 'Your email address'\n } }\n />\n\n <PhoneInput\n field={ {\n id: 'yourPhone',\n name: 'yourPhone'\n } }\n label={ {\n text: 'A number we can reach you on'\n } }\n />\n\n <Textarea\n field={ {\n id: 'yourMessage',\n name: 'yourMessage',\n } }\n label={ {\n text: 'Your message'\n } }\n />\n\n <InputCheckbox\n field={ {\n defaultChecked: hasConsent,\n id: 'consentCheckbox1',\n name: 'consentCheckbox1',\n value: 'consentIsGiven',\n onChange: (event: React.ChangeEvent<HTMLInputElement>) => handleConsentClick(event)\n } }\n label={ {\n text: <span>By leaving this checked you are <strong>consenting</strong> to one of our support staff contacting you in the event that they need more information. <Tooltip icon=\"info\">More about why we might contact you.</Tooltip></span>\n } }\n />\n\n <div className=\"spaceBefore flexRow\">\n <SimpleButton\n label=\"Send Message\"\n id=\"demoSubmitButton1\"\n buttonType=\"submit\"\n buttonStyle={\n {\n color: 'primary'\n }\n }\n rightIcon={ {\n icon: 'telegram'\n } }\n />\n </div>\n </div>\n );\n};\n\nexport default DemoContactForm;"],"mappings":"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","ignoreList":[]}
|
|
@@ -4,6 +4,6 @@ export { transformPlacesData, extractNamePieces } from './dataHelpers';
|
|
|
4
4
|
export { dateToShortIsoString, isValidDate, dateToShortReadableDate, dateToShortReadableMonth, timeStampToShortReadableDate, dateToReadableTime, dateToShortReadableDateTime, getLastDateOfMonth, daysSince } from './dateHelpers';
|
|
5
5
|
export { USER_CURRENCY, intlCurrencyFormatter, intlNumberFormatter, formatNumberForLocale, formatAsCurrencyForLocale, getNumberAbbreviation, formatRoundedNumberWithAbbreviation, formatNumberWithAbbreviation, formatNumberForChartAxis, formatAsSimpleCurrencyForChartAxis, formatAsInternationalCurrencyForChartAxis, formatAsCurrencyWithAbbreviation, formatFileSize } from './formatters';
|
|
6
6
|
export { getRandomNumberBelow, getRandomBetweenInclusive, getRandomBetweenExclusive, hashCode, roundToDecimal, formatNumberToMinDigits, formatDigitalTime } from './numberHelpers';
|
|
7
|
-
export { richTextParser, capitalize, capitalizeFirstLetter, lowerCaseFirstLetter, useAnInsteadOfA, splitCamelCase, pluralize, pluralizeIfNeeded, getInitialsOrAcronym } from './stringHelpers';
|
|
7
|
+
export { richTextParser, capitalize, capitalizeFirstLetter, lowerCaseFirstLetter, getCharacterCount, clampToGraphemeMax, useAnInsteadOfA, splitCamelCase, pluralize, pluralizeIfNeeded, getInitialsOrAcronym } from './stringHelpers';
|
|
8
8
|
export { objectsAreTheSame, isAnObject, createCompareValueOverride, deepMergeObjects, overrideMergeObjects, makeInheritanceObject, updateNestedProperty, filterObject, getArrayOfObjectKeys, getArrayOfReadableObjectKeys, getBranchFromPath, deepRemoveProps } from './objectHelpers';
|
|
9
9
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["getMinAge","getMaxAge","getMinAndMaxAges","validateBirthdate","isDateEntryComplete","getAgeInWeeks","getAgeInYears","binaryFindInArray","addAndSortArray","moveItemInArrayMutate","moveItemInArrayCopy","getRandomItemFromArray","getItemIndexWithinArray","getRoundedMedian","getMostOccurringBoolean","cssClassesArrayToString","transformPlacesData","extractNamePieces","dateToShortIsoString","isValidDate","dateToShortReadableDate","dateToShortReadableMonth","timeStampToShortReadableDate","dateToReadableTime","dateToShortReadableDateTime","getLastDateOfMonth","daysSince","USER_CURRENCY","intlCurrencyFormatter","intlNumberFormatter","formatNumberForLocale","formatAsCurrencyForLocale","getNumberAbbreviation","formatRoundedNumberWithAbbreviation","formatNumberWithAbbreviation","formatNumberForChartAxis","formatAsSimpleCurrencyForChartAxis","formatAsInternationalCurrencyForChartAxis","formatAsCurrencyWithAbbreviation","formatFileSize","getRandomNumberBelow","getRandomBetweenInclusive","getRandomBetweenExclusive","hashCode","roundToDecimal","formatNumberToMinDigits","formatDigitalTime","richTextParser","capitalize","capitalizeFirstLetter","lowerCaseFirstLetter","useAnInsteadOfA","splitCamelCase","pluralize","pluralizeIfNeeded","getInitialsOrAcronym","objectsAreTheSame","isAnObject","createCompareValueOverride","deepMergeObjects","overrideMergeObjects","makeInheritanceObject","updateNestedProperty","filterObject","getArrayOfObjectKeys","getArrayOfReadableObjectKeys","getBranchFromPath","deepRemoveProps"],"sources":["../../../src/helpers/index.ts"],"sourcesContent":["export {\n getMinAge,\n getMaxAge,\n getMinAndMaxAges,\n validateBirthdate,\n isDateEntryComplete,\n getAgeInWeeks,\n getAgeInYears\n} from './ageHelpers';\n\nexport {\n binaryFindInArray,\n addAndSortArray,\n moveItemInArrayMutate,\n moveItemInArrayCopy,\n getRandomItemFromArray,\n getItemIndexWithinArray,\n getRoundedMedian,\n getMostOccurringBoolean,\n cssClassesArrayToString\n} from './arrayHelpers';\n\nexport {\n transformPlacesData,\n extractNamePieces\n} from './dataHelpers';\nexport type { NamePieces } from './dataHelpers';\n\nexport {\n dateToShortIsoString,\n isValidDate,\n dateToShortReadableDate,\n dateToShortReadableMonth,\n timeStampToShortReadableDate,\n dateToReadableTime,\n dateToShortReadableDateTime,\n getLastDateOfMonth,\n daysSince\n} from './dateHelpers';\n\nexport {\n USER_CURRENCY,\n intlCurrencyFormatter,\n intlNumberFormatter,\n formatNumberForLocale,\n formatAsCurrencyForLocale,\n getNumberAbbreviation,\n formatRoundedNumberWithAbbreviation,\n formatNumberWithAbbreviation,\n formatNumberForChartAxis,\n formatAsSimpleCurrencyForChartAxis,\n formatAsInternationalCurrencyForChartAxis,\n formatAsCurrencyWithAbbreviation,\n formatFileSize\n} from './formatters';\n\nexport {\n getRandomNumberBelow,\n getRandomBetweenInclusive,\n getRandomBetweenExclusive,\n hashCode,\n roundToDecimal,\n formatNumberToMinDigits,\n formatDigitalTime\n} from './numberHelpers';\n\nexport {\n richTextParser,\n capitalize,\n capitalizeFirstLetter,\n lowerCaseFirstLetter,\n useAnInsteadOfA,\n splitCamelCase,\n pluralize,\n pluralizeIfNeeded,\n getInitialsOrAcronym\n} from './stringHelpers';\n\nexport {\n objectsAreTheSame,\n isAnObject,\n createCompareValueOverride,\n deepMergeObjects,\n overrideMergeObjects,\n makeInheritanceObject,\n updateNestedProperty,\n filterObject,\n getArrayOfObjectKeys,\n getArrayOfReadableObjectKeys,\n getBranchFromPath,\n deepRemoveProps\n} from './objectHelpers';\n"],"mappings":"AAAA,SACEA,SAAS,EACTC,SAAS,EACTC,gBAAgB,EAChBC,iBAAiB,EACjBC,mBAAmB,EACnBC,aAAa,EACbC,aAAa,QACR,cAAc;AAErB,SACEC,iBAAiB,EACjBC,eAAe,EACfC,qBAAqB,EACrBC,mBAAmB,EACnBC,sBAAsB,EACtBC,uBAAuB,EACvBC,gBAAgB,EAChBC,uBAAuB,EACvBC,uBAAuB,QAClB,gBAAgB;AAEvB,SACEC,mBAAmB,EACnBC,iBAAiB,QACZ,eAAe;AAGtB,SACEC,oBAAoB,EACpBC,WAAW,EACXC,uBAAuB,EACvBC,wBAAwB,EACxBC,4BAA4B,EAC5BC,kBAAkB,EAClBC,2BAA2B,EAC3BC,kBAAkB,EAClBC,SAAS,QACJ,eAAe;AAEtB,SACEC,aAAa,EACbC,qBAAqB,EACrBC,mBAAmB,EACnBC,qBAAqB,EACrBC,yBAAyB,EACzBC,qBAAqB,EACrBC,mCAAmC,EACnCC,4BAA4B,EAC5BC,wBAAwB,EACxBC,kCAAkC,EAClCC,yCAAyC,EACzCC,gCAAgC,EAChCC,cAAc,QACT,cAAc;AAErB,SACEC,oBAAoB,EACpBC,yBAAyB,EACzBC,yBAAyB,EACzBC,QAAQ,EACRC,cAAc,EACdC,uBAAuB,EACvBC,iBAAiB,QACZ,iBAAiB;AAExB,SACEC,cAAc,EACdC,UAAU,EACVC,qBAAqB,EACrBC,oBAAoB,EACpBC,eAAe,EACfC,cAAc,EACdC,SAAS,EACTC,iBAAiB,EACjBC,oBAAoB,QACf,iBAAiB;AAExB,SACEC,iBAAiB,EACjBC,UAAU,EACVC,0BAA0B,EAC1BC,gBAAgB,EAChBC,oBAAoB,EACpBC,qBAAqB,EACrBC,oBAAoB,EACpBC,YAAY,EACZC,oBAAoB,EACpBC,4BAA4B,EAC5BC,iBAAiB,EACjBC,eAAe,QACV,iBAAiB","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"index.js","names":["getMinAge","getMaxAge","getMinAndMaxAges","validateBirthdate","isDateEntryComplete","getAgeInWeeks","getAgeInYears","binaryFindInArray","addAndSortArray","moveItemInArrayMutate","moveItemInArrayCopy","getRandomItemFromArray","getItemIndexWithinArray","getRoundedMedian","getMostOccurringBoolean","cssClassesArrayToString","transformPlacesData","extractNamePieces","dateToShortIsoString","isValidDate","dateToShortReadableDate","dateToShortReadableMonth","timeStampToShortReadableDate","dateToReadableTime","dateToShortReadableDateTime","getLastDateOfMonth","daysSince","USER_CURRENCY","intlCurrencyFormatter","intlNumberFormatter","formatNumberForLocale","formatAsCurrencyForLocale","getNumberAbbreviation","formatRoundedNumberWithAbbreviation","formatNumberWithAbbreviation","formatNumberForChartAxis","formatAsSimpleCurrencyForChartAxis","formatAsInternationalCurrencyForChartAxis","formatAsCurrencyWithAbbreviation","formatFileSize","getRandomNumberBelow","getRandomBetweenInclusive","getRandomBetweenExclusive","hashCode","roundToDecimal","formatNumberToMinDigits","formatDigitalTime","richTextParser","capitalize","capitalizeFirstLetter","lowerCaseFirstLetter","getCharacterCount","clampToGraphemeMax","useAnInsteadOfA","splitCamelCase","pluralize","pluralizeIfNeeded","getInitialsOrAcronym","objectsAreTheSame","isAnObject","createCompareValueOverride","deepMergeObjects","overrideMergeObjects","makeInheritanceObject","updateNestedProperty","filterObject","getArrayOfObjectKeys","getArrayOfReadableObjectKeys","getBranchFromPath","deepRemoveProps"],"sources":["../../../src/helpers/index.ts"],"sourcesContent":["export {\n getMinAge,\n getMaxAge,\n getMinAndMaxAges,\n validateBirthdate,\n isDateEntryComplete,\n getAgeInWeeks,\n getAgeInYears\n} from './ageHelpers';\n\nexport {\n binaryFindInArray,\n addAndSortArray,\n moveItemInArrayMutate,\n moveItemInArrayCopy,\n getRandomItemFromArray,\n getItemIndexWithinArray,\n getRoundedMedian,\n getMostOccurringBoolean,\n cssClassesArrayToString\n} from './arrayHelpers';\n\nexport {\n transformPlacesData,\n extractNamePieces\n} from './dataHelpers';\nexport type { NamePieces } from './dataHelpers';\n\nexport {\n dateToShortIsoString,\n isValidDate,\n dateToShortReadableDate,\n dateToShortReadableMonth,\n timeStampToShortReadableDate,\n dateToReadableTime,\n dateToShortReadableDateTime,\n getLastDateOfMonth,\n daysSince\n} from './dateHelpers';\n\nexport {\n USER_CURRENCY,\n intlCurrencyFormatter,\n intlNumberFormatter,\n formatNumberForLocale,\n formatAsCurrencyForLocale,\n getNumberAbbreviation,\n formatRoundedNumberWithAbbreviation,\n formatNumberWithAbbreviation,\n formatNumberForChartAxis,\n formatAsSimpleCurrencyForChartAxis,\n formatAsInternationalCurrencyForChartAxis,\n formatAsCurrencyWithAbbreviation,\n formatFileSize\n} from './formatters';\n\nexport {\n getRandomNumberBelow,\n getRandomBetweenInclusive,\n getRandomBetweenExclusive,\n hashCode,\n roundToDecimal,\n formatNumberToMinDigits,\n formatDigitalTime\n} from './numberHelpers';\n\nexport {\n richTextParser,\n capitalize,\n capitalizeFirstLetter,\n lowerCaseFirstLetter,\n getCharacterCount,\n clampToGraphemeMax,\n useAnInsteadOfA,\n splitCamelCase,\n pluralize,\n pluralizeIfNeeded,\n getInitialsOrAcronym\n} from './stringHelpers';\n\nexport {\n objectsAreTheSame,\n isAnObject,\n createCompareValueOverride,\n deepMergeObjects,\n overrideMergeObjects,\n makeInheritanceObject,\n updateNestedProperty,\n filterObject,\n getArrayOfObjectKeys,\n getArrayOfReadableObjectKeys,\n getBranchFromPath,\n deepRemoveProps\n} from './objectHelpers';\n"],"mappings":"AAAA,SACEA,SAAS,EACTC,SAAS,EACTC,gBAAgB,EAChBC,iBAAiB,EACjBC,mBAAmB,EACnBC,aAAa,EACbC,aAAa,QACR,cAAc;AAErB,SACEC,iBAAiB,EACjBC,eAAe,EACfC,qBAAqB,EACrBC,mBAAmB,EACnBC,sBAAsB,EACtBC,uBAAuB,EACvBC,gBAAgB,EAChBC,uBAAuB,EACvBC,uBAAuB,QAClB,gBAAgB;AAEvB,SACEC,mBAAmB,EACnBC,iBAAiB,QACZ,eAAe;AAGtB,SACEC,oBAAoB,EACpBC,WAAW,EACXC,uBAAuB,EACvBC,wBAAwB,EACxBC,4BAA4B,EAC5BC,kBAAkB,EAClBC,2BAA2B,EAC3BC,kBAAkB,EAClBC,SAAS,QACJ,eAAe;AAEtB,SACEC,aAAa,EACbC,qBAAqB,EACrBC,mBAAmB,EACnBC,qBAAqB,EACrBC,yBAAyB,EACzBC,qBAAqB,EACrBC,mCAAmC,EACnCC,4BAA4B,EAC5BC,wBAAwB,EACxBC,kCAAkC,EAClCC,yCAAyC,EACzCC,gCAAgC,EAChCC,cAAc,QACT,cAAc;AAErB,SACEC,oBAAoB,EACpBC,yBAAyB,EACzBC,yBAAyB,EACzBC,QAAQ,EACRC,cAAc,EACdC,uBAAuB,EACvBC,iBAAiB,QACZ,iBAAiB;AAExB,SACEC,cAAc,EACdC,UAAU,EACVC,qBAAqB,EACrBC,oBAAoB,EACpBC,iBAAiB,EACjBC,kBAAkB,EAClBC,eAAe,EACfC,cAAc,EACdC,SAAS,EACTC,iBAAiB,EACjBC,oBAAoB,QACf,iBAAiB;AAExB,SACEC,iBAAiB,EACjBC,UAAU,EACVC,0BAA0B,EAC1BC,gBAAgB,EAChBC,oBAAoB,EACpBC,qBAAqB,EACrBC,oBAAoB,EACpBC,YAAY,EACZC,oBAAoB,EACpBC,4BAA4B,EAC5BC,iBAAiB,EACjBC,eAAe,QACV,iBAAiB","ignoreList":[]}
|