@jobber/components 6.5.2 → 6.5.4-MIKEpull--7b61b13.30

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 (64) hide show
  1. package/dist/Autocomplete/index.cjs +1 -1
  2. package/dist/Autocomplete/index.mjs +1 -1
  3. package/dist/DataList/components/DataListSearch/index.cjs +2 -2
  4. package/dist/DataList/components/DataListSearch/index.mjs +2 -2
  5. package/dist/DataTable/index.cjs +1 -1
  6. package/dist/DataTable/index.mjs +1 -1
  7. package/dist/FormField/FormFieldAffix.d.ts +2 -2
  8. package/dist/FormField/FormFieldDescription.d.ts +3 -2
  9. package/dist/FormField/FormFieldPostFix.d.ts +2 -1
  10. package/dist/FormField/FormFieldTypes.d.ts +5 -0
  11. package/dist/FormField/FormFieldWrapper.d.ts +28 -3
  12. package/dist/FormField/components/ClearAction.d.ts +3 -1
  13. package/dist/FormField/hooks/useAtlantisFormField.d.ts +91 -0
  14. package/dist/FormField/hooks/useAtlantisFormFieldActions.d.ts +22 -0
  15. package/dist/FormField/hooks/useAtlantisFormFieldName.d.ts +6 -0
  16. package/dist/FormField/hooks/useAtlantisReactHookForm.d.ts +19 -0
  17. package/dist/FormField/hooks/useFormFieldWrapperStyles.d.ts +29 -0
  18. package/dist/FormField/index.cjs +9 -3
  19. package/dist/FormField/index.d.ts +6 -0
  20. package/dist/FormField/index.mjs +4 -4
  21. package/dist/FormField-cjs.js +264 -121
  22. package/dist/FormField-es.js +260 -123
  23. package/dist/InputDate/index.cjs +2 -2
  24. package/dist/InputDate/index.mjs +2 -2
  25. package/dist/InputDate-cjs.js +6 -0
  26. package/dist/InputDate-es.js +7 -1
  27. package/dist/InputEmail/index.cjs +3 -3
  28. package/dist/InputEmail/index.mjs +3 -3
  29. package/dist/InputEmail-cjs.js +6 -0
  30. package/dist/InputEmail-es.js +7 -1
  31. package/dist/InputNumber/index.cjs +3 -3
  32. package/dist/InputNumber/index.mjs +3 -3
  33. package/dist/InputNumber-cjs.js +6 -0
  34. package/dist/InputNumber-es.js +7 -1
  35. package/dist/InputPassword/index.cjs +3 -3
  36. package/dist/InputPassword/index.mjs +3 -3
  37. package/dist/InputPassword-cjs.js +6 -0
  38. package/dist/InputPassword-es.js +7 -1
  39. package/dist/InputPhoneNumber/index.cjs +1 -1
  40. package/dist/InputPhoneNumber/index.mjs +1 -1
  41. package/dist/InputPhoneNumber-cjs.js +4 -0
  42. package/dist/InputPhoneNumber-es.js +5 -1
  43. package/dist/InputText/InputText.d.ts +2 -0
  44. package/dist/InputText/index.cjs +3 -3
  45. package/dist/InputText/index.mjs +3 -3
  46. package/dist/InputText-cjs.js +6 -0
  47. package/dist/InputText-es.js +7 -1
  48. package/dist/InputTime/index.cjs +2 -2
  49. package/dist/InputTime/index.mjs +2 -2
  50. package/dist/InputTime-cjs.js +5 -0
  51. package/dist/InputTime-es.js +6 -1
  52. package/dist/InputValidation/InputValidation.d.ts +2 -1
  53. package/dist/InputValidation-cjs.js +3 -1
  54. package/dist/InputValidation-es.js +3 -1
  55. package/dist/Option-cjs.js +6 -0
  56. package/dist/Option-es.js +7 -1
  57. package/dist/RecurringSelect/index.cjs +2 -2
  58. package/dist/RecurringSelect/index.mjs +2 -2
  59. package/dist/Select/index.cjs +3 -3
  60. package/dist/Select/index.mjs +3 -3
  61. package/dist/index.cjs +6 -0
  62. package/dist/index.mjs +1 -1
  63. package/dist/utils/meta/meta.json +2 -1
  64. package/package.json +2 -2
@@ -1,19 +1,17 @@
1
1
  'use strict';
2
2
 
3
- var tslib_es6 = require('./tslib.es6-cjs.js');
4
3
  var React = require('react');
5
- var reactHookForm = require('react-hook-form');
6
- var classnames = require('classnames');
7
4
  var framerMotion = require('framer-motion');
8
5
  var design = require('@jobber/design');
6
+ var classnames = require('classnames');
9
7
  var Button = require('./Button-cjs.js');
10
8
  var Icon = require('./Icon-cjs.js');
11
9
  var Text = require('./Text-cjs.js');
12
10
  var useFormFieldFocus = require('./useFormFieldFocus-cjs.js');
13
11
  var InputValidation = require('./InputValidation-cjs.js');
14
12
  var Spinner = require('./Spinner-cjs.js');
15
-
16
- var styles$1 = {"container":"YL-mNv-Bl6g-","wrapper":"_8lhbGTQ-hhg-","horizontalWrapper":"b5mv1x1H7YE-","textarea":"hGr6YW4AeLM-","safari":"QBCWi9GBgMs-","timeInputLabel":"_0pmqVa2zSE4-","miniLabel":"F1t76G6bDKo-","large":"_9tjyT9QUtP8-","text":"QmMiyoAWp-g-","invalid":"XWDSfe6weSY-","disabled":"Tz9LK9ABKMk-","small":"Sw5O4I0lMJg-","inline":"SaORbL7SYWY-","center":"ozy2UoT2vsg-","right":"_3TJdT91YD3c-","maxLength":"W6GrMqLy2qk-","inputWrapper":"-LmjnYRU0r0-","childrenWrapper":"yVXYv6hkuOA-","input":"vtSDcuzNr9Q-","label":"Dgk00tzlODA-","select":"NwQGiWBWIsc-","postfix":"yTDzs9h1otI-","affixIcon":"m0YpdssD2dY-","suffix":"_-3mMnjSh6ok-","hasAction":"OLE9N3Uem4o-","affixLabel":"-Wzcb0pBh5I-","description":"DHX5ijY3xIw-","toolbar":"AL-2brNI7dk-","spinning":"_8Rzv7CcDW80-"};
13
+ var tslib_es6 = require('./tslib.es6-cjs.js');
14
+ var reactHookForm = require('react-hook-form');
17
15
 
18
16
  var useShowClear$1 = {};
19
17
 
@@ -35,10 +33,14 @@ function useShowClear({ clearable, multiline, focused, hasValue, disabled = fals
35
33
  }
36
34
  }
37
35
 
36
+ var styles$1 = {"container":"YL-mNv-Bl6g-","wrapper":"_8lhbGTQ-hhg-","horizontalWrapper":"b5mv1x1H7YE-","textarea":"hGr6YW4AeLM-","safari":"QBCWi9GBgMs-","timeInputLabel":"_0pmqVa2zSE4-","miniLabel":"F1t76G6bDKo-","large":"_9tjyT9QUtP8-","text":"QmMiyoAWp-g-","invalid":"XWDSfe6weSY-","disabled":"Tz9LK9ABKMk-","small":"Sw5O4I0lMJg-","inline":"SaORbL7SYWY-","center":"ozy2UoT2vsg-","right":"_3TJdT91YD3c-","maxLength":"W6GrMqLy2qk-","inputWrapper":"-LmjnYRU0r0-","childrenWrapper":"yVXYv6hkuOA-","input":"vtSDcuzNr9Q-","label":"Dgk00tzlODA-","select":"NwQGiWBWIsc-","postfix":"yTDzs9h1otI-","affixIcon":"m0YpdssD2dY-","suffix":"_-3mMnjSh6ok-","hasAction":"OLE9N3Uem4o-","affixLabel":"-Wzcb0pBh5I-","description":"DHX5ijY3xIw-","toolbar":"AL-2brNI7dk-","spinning":"_8Rzv7CcDW80-"};
37
+
38
38
  function AffixLabel({ label, variation = "prefix", labelRef, }) {
39
39
  const affixLabelClass = classnames(styles$1.affixLabel, {
40
40
  [styles$1.suffix]: variation === "suffix",
41
41
  });
42
+ if (!label)
43
+ return null;
42
44
  return (React.createElement("div", { ref: labelRef, className: affixLabelClass }, label));
43
45
  }
44
46
  function AffixIcon({ icon, onClick, ariaLabel, variation = "prefix", size, }) {
@@ -48,7 +50,7 @@ function AffixIcon({ icon, onClick, ariaLabel, variation = "prefix", size, }) {
48
50
  });
49
51
  const iconSize = size === "small" ? "small" : "base";
50
52
  if (!icon)
51
- return React.createElement(React.Fragment, null);
53
+ return null;
52
54
  return (React.createElement("div", { className: affixIconClass }, onClick ? (React.createElement(Button.Button
53
55
  /**
54
56
  * We can cast the ariaLabel here as a `Suffix`
@@ -62,14 +64,18 @@ function AffixIcon({ icon, onClick, ariaLabel, variation = "prefix", size, }) {
62
64
  ariaLabel: ariaLabel, icon: icon, onClick: onClick, variation: "subtle", type: "tertiary", size: iconSize })) : (React.createElement(Icon.Icon, { name: icon, size: iconSize, color: "greyBlue" }))));
63
65
  }
64
66
 
65
- function FormFieldDescription({ id, description, }) {
67
+ function FormFieldDescription({ id, description, visible = true, }) {
68
+ if (!visible)
69
+ return null;
66
70
  return (React.createElement("div", { id: id, className: styles$1.description },
67
71
  React.createElement(Text.Text, { size: "small", variation: "subdued" }, description)));
68
72
  }
69
73
 
70
74
  var styles = {"clearInput":"YmRTd-KeXv4-","spinning":"B25z9B8I3gs-"};
71
75
 
72
- function ClearAction({ onClick }) {
76
+ function ClearAction({ onClick, visible, }) {
77
+ if (!visible)
78
+ return null;
73
79
  return (React.createElement("button", { className: styles.clearInput, onClick: onClick, type: "button", "aria-label": "Clear input" },
74
80
  React.createElement(Icon.Icon, { name: "remove", size: "small" })));
75
81
  }
@@ -92,8 +98,10 @@ function useIsSafari() {
92
98
  : false;
93
99
  }
94
100
 
95
- // eslint-disable-next-line max-statements
96
- function FormFieldWrapper({ align, description, descriptionIdentifier, placeholder, value, children, invalid, error, size, prefix, suffix, max, maxLength, type, disabled, inline, identifier, clearable, onClear, toolbar, toolbarVisibility = "while-editing", wrapperRef, }) {
101
+ /**
102
+ * Hook for getting the correct styles for the FormField and its children
103
+ */
104
+ function useFormFieldWrapperStyles({ size, align, placeholder, value, invalid, error, max, prefixRef, suffixRef, maxLength, type, disabled, inline, }) {
97
105
  const isSafari = useIsSafari();
98
106
  const wrapperClasses = classnames(styles$1.wrapper, size && styles$1[size], align && styles$1[align], {
99
107
  [styles$1.miniLabel]: (placeholder && value !== "") ||
@@ -115,15 +123,67 @@ function FormFieldWrapper({ align, description, descriptionIdentifier, placehold
115
123
  const wrapperInlineStyle = {
116
124
  ["--formField-maxLength"]: maxLength || max,
117
125
  };
118
- const prefixRef = React.useRef();
119
- const suffixRef = React.useRef();
120
126
  const [labelStyle, setLabelStyle] = React.useState({
121
127
  paddingLeft: undefined,
122
128
  paddingRight: undefined,
123
129
  });
124
130
  React.useEffect(() => {
125
- setLabelStyle(getAffixPaddding);
131
+ var _a, _b;
132
+ setLabelStyle(getAffixPaddding({
133
+ value,
134
+ type,
135
+ prefixWidth: ((_a = prefixRef.current) === null || _a === void 0 ? void 0 : _a.offsetWidth) || 0,
136
+ suffixWidth: ((_b = suffixRef.current) === null || _b === void 0 ? void 0 : _b.offsetWidth) || 0,
137
+ }));
126
138
  }, [value]);
139
+ return {
140
+ inputStyle: styles$1.input,
141
+ wrapperClasses,
142
+ containerClasses,
143
+ wrapperInlineStyle,
144
+ labelStyle,
145
+ setLabelStyle,
146
+ };
147
+ }
148
+ function getAffixPaddding({ value, type, prefixWidth, suffixWidth, }) {
149
+ const hasValue = value !== "";
150
+ const newPadding = {
151
+ paddingLeft: undefined,
152
+ paddingRight: undefined,
153
+ };
154
+ // Naively assume that if the the type is tel, it is the InputPhoneNumber
155
+ if (type === "tel")
156
+ return newPadding;
157
+ if (prefixWidth && !hasValue) {
158
+ newPadding.paddingLeft = offset(prefixWidth);
159
+ }
160
+ if (suffixWidth && !hasValue) {
161
+ newPadding.paddingRight = offset(suffixWidth);
162
+ }
163
+ function offset(width) {
164
+ return `calc(${width}px + var(--space-smallest)`;
165
+ }
166
+ return newPadding;
167
+ }
168
+
169
+ function FormFieldWrapper({ align, description, descriptionIdentifier, placeholder, value, children, invalid, error, size, prefix, suffix, max, maxLength, type, disabled, inline, identifier, clearable, onClear, toolbar, toolbarVisibility = "while-editing", wrapperRef, }) {
170
+ const prefixRef = React.useRef();
171
+ const suffixRef = React.useRef();
172
+ const { wrapperClasses, containerClasses, wrapperInlineStyle, labelStyle } = useFormFieldWrapperStyles({
173
+ align,
174
+ max,
175
+ maxLength,
176
+ prefixRef,
177
+ suffixRef,
178
+ placeholder,
179
+ value,
180
+ invalid,
181
+ error,
182
+ type,
183
+ disabled,
184
+ inline,
185
+ size,
186
+ });
127
187
  const { focused } = useFormFieldFocus.useFormFieldFocus({ wrapperRef });
128
188
  const showClear = useShowClear_2({
129
189
  clearable,
@@ -139,50 +199,124 @@ function FormFieldWrapper({ align, description, descriptionIdentifier, placehold
139
199
  });
140
200
  return (React.createElement("div", { className: containerClasses },
141
201
  React.createElement("div", { className: wrapperClasses, style: wrapperInlineStyle, "data-testid": "Form-Field-Wrapper", ref: wrapperRef },
142
- React.createElement("div", { className: styles$1.horizontalWrapper },
143
- (prefix === null || prefix === void 0 ? void 0 : prefix.icon) && React.createElement(AffixIcon, Object.assign({}, prefix, { size: size })),
144
- React.createElement("div", { className: styles$1.inputWrapper },
145
- placeholder && (React.createElement("label", { className: styles$1.label, htmlFor: identifier, style: (prefixRef === null || prefixRef === void 0 ? void 0 : prefixRef.current) || (suffixRef === null || suffixRef === void 0 ? void 0 : suffixRef.current)
202
+ React.createElement(FormFieldInputHorizontalWrapper, null,
203
+ React.createElement(AffixIcon, Object.assign({}, prefix, { size: size })),
204
+ React.createElement(FormFieldInputWrapperStyles, null,
205
+ React.createElement(FormFieldLabel, { placeholder: placeholder, identifier: identifier, style: (prefixRef === null || prefixRef === void 0 ? void 0 : prefixRef.current) || (suffixRef === null || suffixRef === void 0 ? void 0 : suffixRef.current)
146
206
  ? labelStyle
147
- : undefined }, placeholder)),
148
- (prefix === null || prefix === void 0 ? void 0 : prefix.label) && React.createElement(AffixLabel, Object.assign({}, prefix, { labelRef: prefixRef })),
149
- React.createElement("div", { className: styles$1.childrenWrapper, tabIndex: -1 }, children),
150
- (suffix === null || suffix === void 0 ? void 0 : suffix.label) && (React.createElement(AffixLabel, Object.assign({}, suffix, { labelRef: suffixRef, variation: "suffix" })))),
151
- showClear && React.createElement(ClearAction, { onClick: onClear }),
152
- (suffix === null || suffix === void 0 ? void 0 : suffix.icon) && (React.createElement(AffixIcon, Object.assign({}, suffix, { variation: "suffix", size: size })))),
153
- React.createElement(framerMotion.AnimatePresence, { initial: toolbarVisibility === "always" ? false : true }, isToolbarVisible && (React.createElement(framerMotion.motion.div, { key: "toolbar", initial: toolbarAnimationEnd, animate: toolbarAnimationStart, exit: toolbarAnimationEnd, transition: {
154
- duration: design.tokens["timing-base"] / 1000,
155
- ease: "easeInOut",
156
- }, tabIndex: -1 },
157
- React.createElement("div", { className: styles$1.toolbar, "data-testid": "ATL-InputText-Toolbar" }, toolbar))))),
158
- description && !inline && (React.createElement(FormFieldDescription, { id: descriptionIdentifier, description: description })),
159
- error && !inline && React.createElement(InputValidation.InputValidation, { message: error })));
160
- function getAffixPaddding() {
161
- const hasValue = value !== "";
162
- const newPadding = {
163
- paddingLeft: undefined,
164
- paddingRight: undefined,
165
- };
166
- // Naively assume that if the the type is tel, it is the InputPhoneNumber
167
- if (type === "tel")
168
- return newPadding;
169
- if ((prefixRef === null || prefixRef === void 0 ? void 0 : prefixRef.current) && !hasValue) {
170
- const { offsetWidth } = prefixRef.current;
171
- newPadding.paddingLeft = offset(offsetWidth);
172
- }
173
- if ((suffixRef === null || suffixRef === void 0 ? void 0 : suffixRef.current) && !hasValue) {
174
- const { offsetWidth } = suffixRef.current;
175
- newPadding.paddingRight = offset(offsetWidth);
207
+ : undefined }),
208
+ React.createElement(AffixLabel, Object.assign({}, prefix, { labelRef: prefixRef })),
209
+ React.createElement(FormFieldWrapperMain, null, children),
210
+ React.createElement(AffixLabel, Object.assign({}, suffix, { labelRef: suffixRef, variation: "suffix" }))),
211
+ React.createElement(ClearAction, { onClick: onClear, visible: showClear }),
212
+ React.createElement(AffixIcon, Object.assign({}, suffix, { variation: "suffix", size: size }))),
213
+ React.createElement(FormFieldWrapperToolbar, { toolbarVisibility: toolbarVisibility, isToolbarVisible: isToolbarVisible, toolbarAnimationEnd: toolbarAnimationEnd, toolbarAnimationStart: toolbarAnimationStart, toolbar: toolbar })),
214
+ React.createElement(FormFieldDescription, { visible: !!description && !inline, id: descriptionIdentifier, description: description }),
215
+ React.createElement(InputValidation.InputValidation, { message: error, visible: !!error && !inline })));
216
+ }
217
+ function FormFieldInputHorizontalWrapper({ children, }) {
218
+ return React.createElement("div", { className: styles$1.horizontalWrapper }, children);
219
+ }
220
+ function FormFieldInputWrapperStyles({ children, }) {
221
+ return React.createElement("div", { className: styles$1.inputWrapper }, children);
222
+ }
223
+ function FormFieldWrapperMain({ children, tabIndex = -1, }) {
224
+ return (React.createElement("div", { className: styles$1.childrenWrapper, tabIndex: tabIndex }, children));
225
+ }
226
+ function FormFieldLabel({ placeholder, identifier, style, }) {
227
+ if (!placeholder)
228
+ return null;
229
+ return (React.createElement("label", { className: styles$1.label, htmlFor: identifier, style: style }, placeholder));
230
+ }
231
+ function FormFieldWrapperToolbar({ toolbar, isToolbarVisible, toolbarAnimationEnd, toolbarAnimationStart, toolbarVisibility, }) {
232
+ return (React.createElement(framerMotion.AnimatePresence, { initial: toolbarVisibility === "always" ? false : true }, isToolbarVisible && (React.createElement(framerMotion.motion.div, { key: "toolbar", initial: toolbarAnimationEnd, animate: toolbarAnimationStart, exit: toolbarAnimationEnd, transition: {
233
+ duration: design.tokens["timing-base"] / 1000,
234
+ ease: "easeInOut",
235
+ }, tabIndex: -1 },
236
+ React.createElement("div", { className: styles$1.toolbar, "data-testid": "ATL-InputText-Toolbar" }, toolbar)))));
237
+ }
238
+
239
+ function FormFieldPostFix({ variation, visible = true, }) {
240
+ if (!visible)
241
+ return null;
242
+ return (React.createElement("span", { className: styles$1.postfix }, variation === "select" ? (React.createElement(Icon.Icon, { name: "arrowDown" })) : (React.createElement(Spinner.Spinner, { size: "small" }))));
243
+ }
244
+
245
+ /**
246
+ * Combines the actions from the props of the FormField with the actions from react-hook-form. This is used to
247
+ * manage the form state of a field through react-hook-form while providing support for additional callbacks
248
+ */
249
+ function useAtlantisFormFieldActions({ name, onChange, inputRef, onControllerChange, onControllerBlur, onEnter, readonly, type, setValue, onFocus, onBlur, onValidation, }) {
250
+ function handleClear() {
251
+ var _a;
252
+ handleBlur();
253
+ setValue(name, "", { shouldValidate: true });
254
+ onChange && onChange("");
255
+ (_a = inputRef === null || inputRef === void 0 ? void 0 : inputRef.current) === null || _a === void 0 ? void 0 : _a.focus();
256
+ }
257
+ function handleChange(event) {
258
+ let newValue;
259
+ newValue = event.currentTarget.value;
260
+ if (type === "number" && newValue.length > 0) {
261
+ newValue = parseFloat(newValue);
176
262
  }
177
- function offset(width) {
178
- return `calc(${width}px + var(--space-smallest)`;
263
+ onChange && onChange(newValue, event);
264
+ onControllerChange(event);
265
+ }
266
+ function handleKeyDown(event) {
267
+ if (!onEnter)
268
+ return;
269
+ if (event.key !== "Enter")
270
+ return;
271
+ if (event.shiftKey || event.ctrlKey)
272
+ return;
273
+ event.preventDefault();
274
+ onEnter && onEnter(event);
275
+ }
276
+ function handleFocus(event) {
277
+ const target = event.currentTarget;
278
+ if (target.select) {
279
+ setTimeout(() => readonly && target.select());
179
280
  }
180
- return newPadding;
281
+ onFocus && onFocus();
282
+ }
283
+ function handleBlur() {
284
+ onBlur && onBlur();
285
+ onControllerBlur();
286
+ }
287
+ function handleValidation(message) {
288
+ onValidation && onValidation(message);
181
289
  }
290
+ return {
291
+ handleClear,
292
+ handleChange,
293
+ handleKeyDown,
294
+ handleFocus,
295
+ handleBlur,
296
+ handleValidation,
297
+ };
182
298
  }
183
299
 
184
- function FormFieldPostFix({ variation }) {
185
- return (React.createElement("span", { className: styles$1.postfix }, variation === "select" ? (React.createElement(Icon.Icon, { name: "arrowDown" })) : (React.createElement(Spinner.Spinner, { size: "small" }))));
300
+ /**
301
+ * Provides the props for the html fields rendered by the FormField component
302
+ */
303
+ function useAtlantisFormField({ id, nameProp, name, useControllerField: useControllerField, description, disabled, readonly, keyboard, autofocus, handleChange, handleBlur, handleFocus, inline, validations, handleKeyDown, handleValidation, errorMessage, }) {
304
+ const descriptionIdentifier = `descriptionUUID--${id}`;
305
+ const fieldProps = Object.assign(Object.assign(Object.assign({}, useControllerField), { id, className: styles$1.input, name: (validations || nameProp) && name, disabled: disabled, readOnly: readonly, inputMode: keyboard, onChange: handleChange, onBlur: handleBlur, onFocus: handleFocus, autoFocus: autofocus }), (description &&
306
+ !inline && { "aria-describedby": descriptionIdentifier }));
307
+ const textFieldProps = Object.assign(Object.assign({}, fieldProps), { autoFocus: autofocus, onKeyDown: handleKeyDown });
308
+ React.useEffect(() => handleValidation(errorMessage), [errorMessage]);
309
+ return { textFieldProps, fieldProps, descriptionIdentifier };
310
+ }
311
+
312
+ function useAtlantisFormFieldName({ id, nameProp, }) {
313
+ /**
314
+ * Generate a name if one is not supplied, this is the name
315
+ * that will be used for react-hook-form and not neccessarily
316
+ * attached to the DOM
317
+ */
318
+ const name = nameProp ? nameProp : `generatedName--${id}`;
319
+ return { name };
186
320
  }
187
321
 
188
322
  /**
@@ -202,50 +336,93 @@ function mergeRefs(refs) {
202
336
  };
203
337
  }
204
338
 
205
- function FormField(props) {
206
- // Warning: do not move useId into FormFieldInternal. This must be here to avoid
207
- // a problem where useId isn't stable across multiple StrictMode renders.
208
- // https://github.com/facebook/react/issues/27103
209
- const id = React.useId();
210
- return React.createElement(FormFieldInternal, Object.assign({}, props, { id: id }));
211
- }
212
- // eslint-disable-next-line max-statements
213
- function FormFieldInternal(props) {
339
+ /**
340
+ * Hook used to manage the form state of a field through react-hook-form
341
+ */
342
+ function useAtlantisReactForm({ actionsRef, name, defaultValue, value, validations, inputRef, }) {
214
343
  var _a;
215
- const { actionsRef, autocomplete = true, children, defaultValue, description, disabled, id, inputRef, inline, keyboard, max, maxLength, min, name: nameProp, readonly, rows, loading, type = "text", validations, value, onChange, onEnter, onFocus, onBlur, onValidation, onKeyUp, clearable = "never", autofocus, } = props;
216
344
  const formContext = reactHookForm.useFormContext();
217
345
  // If there isn't a Form Context being provided, get a form for this field.
218
346
  const { control, setValue, watch } = formContext !== null && formContext !== void 0 ? formContext : reactHookForm.useForm({ mode: "onTouched" });
219
- const descriptionIdentifier = `descriptionUUID--${id}`;
220
- /**
221
- * Generate a name if one is not supplied, this is the name
222
- * that will be used for react-hook-form and not neccessarily
223
- * attached to the DOM
224
- */
225
- const name = nameProp ? nameProp : `generatedName--${id}`;
226
- React.useEffect(() => {
227
- if (value != undefined) {
228
- setValue(name, value);
229
- }
230
- }, [value, watch(name)]);
231
347
  React.useImperativeHandle(actionsRef, () => ({
232
348
  setValue: newValue => {
233
349
  setValue(name, newValue, { shouldValidate: true });
234
350
  },
235
351
  }));
236
- const _b = reactHookForm.useController({
352
+ const { field, fieldState: { error }, } = reactHookForm.useController({
237
353
  name,
238
354
  control,
239
355
  rules: validations,
240
356
  defaultValue: (_a = value !== null && value !== void 0 ? value : defaultValue) !== null && _a !== void 0 ? _a : "",
241
- }), _c = _b.field, { onChange: onControllerChange, onBlur: onControllerBlur, ref: fieldRef } = _c, rest = tslib_es6.__rest(_c, ["onChange", "onBlur", "ref"]), { fieldState: { error } } = _b;
242
- const errorMessage = (error === null || error === void 0 ? void 0 : error.message) || "";
243
- React.useEffect(() => handleValidation(errorMessage), [errorMessage]);
244
- const fieldProps = Object.assign(Object.assign(Object.assign({}, rest), { id, className: styles$1.input, name: (validations || nameProp) && name, disabled: disabled, readOnly: readonly, inputMode: keyboard, onChange: handleChange, onBlur: handleBlur, onFocus: handleFocus, autoFocus: autofocus }), (description &&
245
- !inline && { "aria-describedby": descriptionIdentifier }));
246
- const textFieldProps = Object.assign(Object.assign({}, fieldProps), { autoFocus: autofocus, onKeyDown: handleKeyDown });
357
+ });
358
+ const { onChange, onBlur, ref: fieldRef } = field, useControllerField = tslib_es6.__rest(field, ["onChange", "onBlur", "ref"]);
359
+ React.useEffect(() => {
360
+ if (value != undefined) {
361
+ setValue(name, value);
362
+ }
363
+ }, [value, watch(name)]);
247
364
  const inputRefs = mergeRefs([inputRef, fieldRef]);
248
- return (React.createElement(FormFieldWrapper, Object.assign({}, props, { value: rest.value, error: errorMessage, identifier: id, descriptionIdentifier: descriptionIdentifier, clearable: clearable, onClear: handleClear }), renderField()));
365
+ return {
366
+ inputRefs,
367
+ useControllerField,
368
+ setValue,
369
+ errorMessage: (error === null || error === void 0 ? void 0 : error.message) || "",
370
+ onControllerChange: onChange,
371
+ onControllerBlur: onBlur,
372
+ };
373
+ }
374
+
375
+ function FormField(props) {
376
+ // Warning: do not move useId into FormFieldInternal. This must be here to avoid
377
+ // a problem where useId isn't stable across multiple StrictMode renders.
378
+ // https://github.com/facebook/react/issues/27103
379
+ const id = React.useId();
380
+ return React.createElement(FormFieldInternal, Object.assign({}, props, { id: id }));
381
+ }
382
+ function FormFieldInternal(props) {
383
+ const { actionsRef, autocomplete = true, children, defaultValue, description, disabled, id, inputRef, inline, keyboard, max, maxLength, min, name: nameProp, readonly, rows, loading, type = "text", validations, value, onChange, onEnter, onFocus, onBlur, onValidation, onKeyUp, clearable = "never", autofocus, } = props;
384
+ const { name } = useAtlantisFormFieldName({ id, nameProp });
385
+ const { errorMessage, inputRefs, useControllerField, setValue, onControllerBlur, onControllerChange, } = useAtlantisReactForm({
386
+ actionsRef,
387
+ name,
388
+ defaultValue,
389
+ value,
390
+ validations,
391
+ inputRef,
392
+ });
393
+ const { handleValidation, handleBlur, handleChange, handleClear, handleFocus, handleKeyDown, } = useAtlantisFormFieldActions({
394
+ onChange,
395
+ onEnter,
396
+ readonly,
397
+ type,
398
+ onFocus,
399
+ setValue,
400
+ onBlur,
401
+ onValidation,
402
+ onControllerBlur,
403
+ onControllerChange,
404
+ name,
405
+ });
406
+ const { textFieldProps, fieldProps, descriptionIdentifier } = useAtlantisFormField({
407
+ id,
408
+ useControllerField,
409
+ name,
410
+ nameProp,
411
+ description,
412
+ validations: !!validations,
413
+ disabled,
414
+ readonly,
415
+ keyboard,
416
+ autofocus,
417
+ handleChange,
418
+ handleBlur,
419
+ handleFocus,
420
+ inline,
421
+ errorMessage,
422
+ handleValidation,
423
+ handleKeyDown,
424
+ });
425
+ return (React.createElement(FormFieldWrapper, Object.assign({}, props, { value: useControllerField.value, error: errorMessage, identifier: id, descriptionIdentifier: descriptionIdentifier, clearable: clearable, onClear: handleClear }), renderField()));
249
426
  function renderField() {
250
427
  switch (type) {
251
428
  case "select":
@@ -261,46 +438,6 @@ function FormFieldInternal(props) {
261
438
  children));
262
439
  }
263
440
  }
264
- function handleClear() {
265
- var _a;
266
- handleBlur();
267
- setValue(name, "", { shouldValidate: true });
268
- onChange && onChange("");
269
- (_a = inputRef === null || inputRef === void 0 ? void 0 : inputRef.current) === null || _a === void 0 ? void 0 : _a.focus();
270
- }
271
- function handleChange(event) {
272
- let newValue;
273
- newValue = event.currentTarget.value;
274
- if (type === "number" && newValue.length > 0) {
275
- newValue = parseFloat(newValue);
276
- }
277
- onChange && onChange(newValue, event);
278
- onControllerChange(event);
279
- }
280
- function handleKeyDown(event) {
281
- if (!onEnter)
282
- return;
283
- if (event.key !== "Enter")
284
- return;
285
- if (event.shiftKey || event.ctrlKey)
286
- return;
287
- event.preventDefault();
288
- onEnter && onEnter(event);
289
- }
290
- function handleFocus(event) {
291
- const target = event.currentTarget;
292
- if (target.select) {
293
- setTimeout(() => readonly && target.select());
294
- }
295
- onFocus && onFocus();
296
- }
297
- function handleBlur() {
298
- onBlur && onBlur();
299
- onControllerBlur();
300
- }
301
- function handleValidation(message) {
302
- onValidation && onValidation(message);
303
- }
304
441
  }
305
442
  function setAutocomplete(autocompleteSetting) {
306
443
  if (autocompleteSetting === true) {
@@ -313,3 +450,9 @@ function setAutocomplete(autocompleteSetting) {
313
450
  }
314
451
 
315
452
  exports.FormField = FormField;
453
+ exports.FormFieldWrapper = FormFieldWrapper;
454
+ exports.useAtlantisFormField = useAtlantisFormField;
455
+ exports.useAtlantisFormFieldActions = useAtlantisFormFieldActions;
456
+ exports.useAtlantisFormFieldName = useAtlantisFormFieldName;
457
+ exports.useAtlantisReactForm = useAtlantisReactForm;
458
+ exports.useFormFieldWrapperStyles = useFormFieldWrapperStyles;