@ttoss/forms 0.14.27 → 0.14.29
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/esm/index.js +109 -38
- package/dist/index.d.ts +17 -8
- package/dist/index.js +111 -36
- package/package.json +9 -9
- package/src/ErrorMessage.tsx +3 -1
- package/src/FormFieldInput.tsx +7 -46
- package/src/FormGroup.tsx +116 -0
- package/src/index.ts +1 -0
package/dist/esm/index.js
CHANGED
|
@@ -39,7 +39,8 @@ import { HelpText } from "@ttoss/ui";
|
|
|
39
39
|
import { ErrorMessage as HookFormErrorMessage } from "@hookform/error-message";
|
|
40
40
|
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
41
41
|
var ErrorMessage = ({
|
|
42
|
-
name
|
|
42
|
+
name,
|
|
43
|
+
disabled
|
|
43
44
|
}) => {
|
|
44
45
|
const {
|
|
45
46
|
formState: {
|
|
@@ -50,7 +51,8 @@ var ErrorMessage = ({
|
|
|
50
51
|
errors,
|
|
51
52
|
name,
|
|
52
53
|
as: /* @__PURE__ */jsx2(HelpText, {
|
|
53
|
-
negative: true
|
|
54
|
+
negative: true,
|
|
55
|
+
disabled
|
|
54
56
|
})
|
|
55
57
|
});
|
|
56
58
|
};
|
|
@@ -139,15 +141,14 @@ var FormFieldCheckbox = ({
|
|
|
139
141
|
};
|
|
140
142
|
|
|
141
143
|
// src/FormFieldInput.tsx
|
|
142
|
-
import { Box as Box4,
|
|
144
|
+
import { Box as Box4, Input, Label as Label3 } from "@ttoss/ui";
|
|
143
145
|
import { useController as useController3 } from "react-hook-form";
|
|
144
|
-
import React3 from "react";
|
|
145
146
|
import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
146
147
|
var FormFieldInput = ({
|
|
147
148
|
label,
|
|
148
149
|
name,
|
|
149
|
-
|
|
150
|
-
|
|
150
|
+
tooltip,
|
|
151
|
+
onTooltipClick,
|
|
151
152
|
...inputProps
|
|
152
153
|
}) => {
|
|
153
154
|
const {
|
|
@@ -164,42 +165,15 @@ var FormFieldInput = ({
|
|
|
164
165
|
name,
|
|
165
166
|
defaultValue: ""
|
|
166
167
|
});
|
|
167
|
-
const characterCounter = React3.useMemo(() => {
|
|
168
|
-
if (!value) {
|
|
169
|
-
return 0;
|
|
170
|
-
}
|
|
171
|
-
return String(value).length;
|
|
172
|
-
}, [value]);
|
|
173
168
|
const id = `form-field-input-${name}`;
|
|
174
169
|
const hasError = !!errors[name]?.message;
|
|
175
170
|
return /* @__PURE__ */jsxs3(Box4, {
|
|
176
|
-
children: [label && /* @__PURE__ */
|
|
177
|
-
sx: {
|
|
178
|
-
display: "flex",
|
|
179
|
-
alignItems: "center"
|
|
180
|
-
},
|
|
171
|
+
children: [label && /* @__PURE__ */jsx5(Label3, {
|
|
181
172
|
"aria-disabled": inputProps.disabled,
|
|
182
173
|
htmlFor: id,
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
fontSize: "xs",
|
|
187
|
-
lineHeight: 0
|
|
188
|
-
},
|
|
189
|
-
variant: "tooltip-icon",
|
|
190
|
-
children: /* @__PURE__ */jsx5(Icon, {
|
|
191
|
-
icon: tooltipIcon
|
|
192
|
-
})
|
|
193
|
-
}), showCharacterCounter && /* @__PURE__ */jsx5(Text, {
|
|
194
|
-
sx: {
|
|
195
|
-
marginLeft: "auto",
|
|
196
|
-
fontSize: "xs",
|
|
197
|
-
lineHeight: 0,
|
|
198
|
-
color: "underemphasize"
|
|
199
|
-
},
|
|
200
|
-
variant: "character-counter",
|
|
201
|
-
children: characterCounter
|
|
202
|
-
})]
|
|
174
|
+
tooltip,
|
|
175
|
+
onTooltipClick,
|
|
176
|
+
children: label
|
|
203
177
|
}), /* @__PURE__ */jsx5(Input, {
|
|
204
178
|
ref,
|
|
205
179
|
onChange,
|
|
@@ -331,4 +305,101 @@ var FormFieldTextarea = ({
|
|
|
331
305
|
}
|
|
332
306
|
});
|
|
333
307
|
};
|
|
334
|
-
|
|
308
|
+
|
|
309
|
+
// src/FormGroup.tsx
|
|
310
|
+
import { Flex as Flex2 } from "@ttoss/ui";
|
|
311
|
+
import React3 from "react";
|
|
312
|
+
import { jsx as jsx9 } from "react/jsx-runtime";
|
|
313
|
+
var FormGroupLevelsManagerContext = /*#__PURE__*/React3.createContext({
|
|
314
|
+
registerChild: () => {
|
|
315
|
+
return null;
|
|
316
|
+
}
|
|
317
|
+
});
|
|
318
|
+
var FormGroupLevelsManager = ({
|
|
319
|
+
children
|
|
320
|
+
}) => {
|
|
321
|
+
const [levelsLength, setLevelsLength] = React3.useState(0);
|
|
322
|
+
const registerChild = React3.useCallback(level => {
|
|
323
|
+
if (level + 1 > levelsLength) {
|
|
324
|
+
setLevelsLength(level + 1);
|
|
325
|
+
}
|
|
326
|
+
}, [levelsLength]);
|
|
327
|
+
return /* @__PURE__ */jsx9(FormGroupLevelsManagerContext.Provider, {
|
|
328
|
+
value: {
|
|
329
|
+
levelsLength,
|
|
330
|
+
registerChild
|
|
331
|
+
},
|
|
332
|
+
children
|
|
333
|
+
});
|
|
334
|
+
};
|
|
335
|
+
var FormGroupContext = /*#__PURE__*/React3.createContext({});
|
|
336
|
+
var useFormGroup = () => {
|
|
337
|
+
const {
|
|
338
|
+
parentLevel
|
|
339
|
+
} = React3.useContext(FormGroupContext);
|
|
340
|
+
const {
|
|
341
|
+
levelsLength
|
|
342
|
+
} = React3.useContext(FormGroupLevelsManagerContext);
|
|
343
|
+
return {
|
|
344
|
+
level: parentLevel,
|
|
345
|
+
levelsLength
|
|
346
|
+
};
|
|
347
|
+
};
|
|
348
|
+
var FormGroupWrapper = ({
|
|
349
|
+
children
|
|
350
|
+
}) => {
|
|
351
|
+
const {
|
|
352
|
+
level,
|
|
353
|
+
levelsLength
|
|
354
|
+
} = useFormGroup();
|
|
355
|
+
const {
|
|
356
|
+
registerChild
|
|
357
|
+
} = React3.useContext(FormGroupLevelsManagerContext);
|
|
358
|
+
React3.useEffect(() => {
|
|
359
|
+
if (typeof level === "number") {
|
|
360
|
+
registerChild(level);
|
|
361
|
+
}
|
|
362
|
+
}, [level, registerChild]);
|
|
363
|
+
const sx = React3.useMemo(() => {
|
|
364
|
+
return {
|
|
365
|
+
flexDirection: "column",
|
|
366
|
+
width: "100%",
|
|
367
|
+
gap: "md",
|
|
368
|
+
paddingLeft: ({
|
|
369
|
+
space
|
|
370
|
+
}) => {
|
|
371
|
+
if (!level || !levelsLength) {
|
|
372
|
+
return 0;
|
|
373
|
+
}
|
|
374
|
+
const value = levelsLength / level;
|
|
375
|
+
return `calc(${space["lg"]} / ${value})`;
|
|
376
|
+
}
|
|
377
|
+
};
|
|
378
|
+
}, [level, levelsLength]);
|
|
379
|
+
return /* @__PURE__ */jsx9(Flex2, {
|
|
380
|
+
"aria-level": level,
|
|
381
|
+
sx,
|
|
382
|
+
children
|
|
383
|
+
});
|
|
384
|
+
};
|
|
385
|
+
var FormGroup = ({
|
|
386
|
+
children
|
|
387
|
+
}) => {
|
|
388
|
+
const {
|
|
389
|
+
level
|
|
390
|
+
} = useFormGroup();
|
|
391
|
+
const currentLevel = level === void 0 ? 0 : level + 1;
|
|
392
|
+
return /* @__PURE__ */jsx9(FormGroupContext.Provider, {
|
|
393
|
+
value: {
|
|
394
|
+
parentLevel: currentLevel
|
|
395
|
+
},
|
|
396
|
+
children: currentLevel === 0 ? /* @__PURE__ */jsx9(FormGroupLevelsManager, {
|
|
397
|
+
children: /* @__PURE__ */jsx9(FormGroupWrapper, {
|
|
398
|
+
children
|
|
399
|
+
})
|
|
400
|
+
}) : /* @__PURE__ */jsx9(FormGroupWrapper, {
|
|
401
|
+
children
|
|
402
|
+
})
|
|
403
|
+
});
|
|
404
|
+
};
|
|
405
|
+
export { Form, FormField, FormFieldCheckbox, FormFieldInput, FormFieldRadio, FormFieldSelect, FormFieldTextarea, FormGroup, useFormGroup, yup, yupResolver };
|
package/dist/index.d.ts
CHANGED
|
@@ -5,7 +5,9 @@ export * from 'react-hook-form';
|
|
|
5
5
|
import * as yup from 'yup';
|
|
6
6
|
export { yup };
|
|
7
7
|
import * as React from 'react';
|
|
8
|
-
import
|
|
8
|
+
import React__default from 'react';
|
|
9
|
+
import * as _ttoss_ui from '@ttoss/ui';
|
|
10
|
+
import { BoxProps, CheckboxProps, LabelProps, RadioProps, TextareaProps } from '@ttoss/ui';
|
|
9
11
|
import * as theme_ui from 'theme-ui';
|
|
10
12
|
|
|
11
13
|
declare const Form: <TFieldValues extends FieldValues = FieldValues>({ children, onSubmit, sx, ...formMethods }: {
|
|
@@ -29,15 +31,13 @@ declare const FormFieldCheckbox: <TFieldValues extends FieldValues = FieldValues
|
|
|
29
31
|
name: FieldPath<TFieldValues>;
|
|
30
32
|
} & CheckboxProps) => JSX.Element;
|
|
31
33
|
|
|
32
|
-
declare const FormFieldInput: <TFieldValues extends FieldValues = FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>>({ label, name,
|
|
34
|
+
declare const FormFieldInput: <TFieldValues extends FieldValues = FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>>({ label, name, tooltip, onTooltipClick, ...inputProps }: {
|
|
33
35
|
label?: string | undefined;
|
|
34
36
|
name: TName;
|
|
35
|
-
tooltipIcon?: IconType | undefined;
|
|
36
|
-
showCharacterCounter?: boolean | undefined;
|
|
37
37
|
} & theme_ui.InputProps & {
|
|
38
|
-
leadingIcon?: IconType | undefined;
|
|
39
|
-
trailingIcon?: IconType | undefined;
|
|
40
|
-
}) => JSX.Element;
|
|
38
|
+
leadingIcon?: _ttoss_ui.IconType | undefined;
|
|
39
|
+
trailingIcon?: _ttoss_ui.IconType | undefined;
|
|
40
|
+
} & Pick<LabelProps, "tooltip" | "onTooltipClick">) => JSX.Element;
|
|
41
41
|
|
|
42
42
|
type FormRadioOption$1 = {
|
|
43
43
|
value: string | number;
|
|
@@ -64,4 +64,13 @@ declare const FormFieldTextarea: <TFieldValues extends FieldValues = FieldValues
|
|
|
64
64
|
name: TName;
|
|
65
65
|
} & TextareaProps) => JSX.Element;
|
|
66
66
|
|
|
67
|
-
|
|
67
|
+
declare const useFormGroup: () => {
|
|
68
|
+
level: number | undefined;
|
|
69
|
+
levelsLength: number | undefined;
|
|
70
|
+
};
|
|
71
|
+
type FormGroupProps = {
|
|
72
|
+
children: React__default.ReactNode;
|
|
73
|
+
};
|
|
74
|
+
declare const FormGroup: ({ children }: FormGroupProps) => JSX.Element;
|
|
75
|
+
|
|
76
|
+
export { Form, FormField, FormFieldCheckbox, FormFieldInput, FormFieldRadio, FormFieldSelect, FormFieldTextarea, FormGroup, useFormGroup };
|
package/dist/index.js
CHANGED
|
@@ -46,6 +46,8 @@ __export(src_exports, {
|
|
|
46
46
|
FormFieldRadio: () => FormFieldRadio,
|
|
47
47
|
FormFieldSelect: () => FormFieldSelect,
|
|
48
48
|
FormFieldTextarea: () => FormFieldTextarea,
|
|
49
|
+
FormGroup: () => FormGroup,
|
|
50
|
+
useFormGroup: () => useFormGroup,
|
|
49
51
|
yup: () => yup,
|
|
50
52
|
yupResolver: () => import_yup.yupResolver
|
|
51
53
|
});
|
|
@@ -88,7 +90,8 @@ var import_ui2 = require("@ttoss/ui");
|
|
|
88
90
|
var import_error_message = require("@hookform/error-message");
|
|
89
91
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
90
92
|
var ErrorMessage = ({
|
|
91
|
-
name
|
|
93
|
+
name,
|
|
94
|
+
disabled
|
|
92
95
|
}) => {
|
|
93
96
|
const {
|
|
94
97
|
formState: {
|
|
@@ -99,7 +102,8 @@ var ErrorMessage = ({
|
|
|
99
102
|
errors,
|
|
100
103
|
name,
|
|
101
104
|
as: /* @__PURE__ */(0, import_jsx_runtime2.jsx)(import_ui2.HelpText, {
|
|
102
|
-
negative: true
|
|
105
|
+
negative: true,
|
|
106
|
+
disabled
|
|
103
107
|
})
|
|
104
108
|
});
|
|
105
109
|
};
|
|
@@ -190,13 +194,12 @@ var FormFieldCheckbox = ({
|
|
|
190
194
|
// src/FormFieldInput.tsx
|
|
191
195
|
var import_ui5 = require("@ttoss/ui");
|
|
192
196
|
var import_react_hook_form5 = require("react-hook-form");
|
|
193
|
-
var import_react = __toESM(require("react"));
|
|
194
197
|
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
195
198
|
var FormFieldInput = ({
|
|
196
199
|
label,
|
|
197
200
|
name,
|
|
198
|
-
|
|
199
|
-
|
|
201
|
+
tooltip,
|
|
202
|
+
onTooltipClick,
|
|
200
203
|
...inputProps
|
|
201
204
|
}) => {
|
|
202
205
|
const {
|
|
@@ -213,42 +216,15 @@ var FormFieldInput = ({
|
|
|
213
216
|
name,
|
|
214
217
|
defaultValue: ""
|
|
215
218
|
});
|
|
216
|
-
const characterCounter = import_react.default.useMemo(() => {
|
|
217
|
-
if (!value) {
|
|
218
|
-
return 0;
|
|
219
|
-
}
|
|
220
|
-
return String(value).length;
|
|
221
|
-
}, [value]);
|
|
222
219
|
const id = `form-field-input-${name}`;
|
|
223
220
|
const hasError = !!errors[name]?.message;
|
|
224
221
|
return /* @__PURE__ */(0, import_jsx_runtime5.jsxs)(import_ui5.Box, {
|
|
225
|
-
children: [label && /* @__PURE__ */(0, import_jsx_runtime5.
|
|
226
|
-
sx: {
|
|
227
|
-
display: "flex",
|
|
228
|
-
alignItems: "center"
|
|
229
|
-
},
|
|
222
|
+
children: [label && /* @__PURE__ */(0, import_jsx_runtime5.jsx)(import_ui5.Label, {
|
|
230
223
|
"aria-disabled": inputProps.disabled,
|
|
231
224
|
htmlFor: id,
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
fontSize: "xs",
|
|
236
|
-
lineHeight: 0
|
|
237
|
-
},
|
|
238
|
-
variant: "tooltip-icon",
|
|
239
|
-
children: /* @__PURE__ */(0, import_jsx_runtime5.jsx)(import_ui5.Icon, {
|
|
240
|
-
icon: tooltipIcon
|
|
241
|
-
})
|
|
242
|
-
}), showCharacterCounter && /* @__PURE__ */(0, import_jsx_runtime5.jsx)(import_ui5.Text, {
|
|
243
|
-
sx: {
|
|
244
|
-
marginLeft: "auto",
|
|
245
|
-
fontSize: "xs",
|
|
246
|
-
lineHeight: 0,
|
|
247
|
-
color: "underemphasize"
|
|
248
|
-
},
|
|
249
|
-
variant: "character-counter",
|
|
250
|
-
children: characterCounter
|
|
251
|
-
})]
|
|
225
|
+
tooltip,
|
|
226
|
+
onTooltipClick,
|
|
227
|
+
children: label
|
|
252
228
|
}), /* @__PURE__ */(0, import_jsx_runtime5.jsx)(import_ui5.Input, {
|
|
253
229
|
ref,
|
|
254
230
|
onChange,
|
|
@@ -380,6 +356,103 @@ var FormFieldTextarea = ({
|
|
|
380
356
|
}
|
|
381
357
|
});
|
|
382
358
|
};
|
|
359
|
+
|
|
360
|
+
// src/FormGroup.tsx
|
|
361
|
+
var import_ui9 = require("@ttoss/ui");
|
|
362
|
+
var import_react = __toESM(require("react"));
|
|
363
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
364
|
+
var FormGroupLevelsManagerContext = import_react.default.createContext({
|
|
365
|
+
registerChild: () => {
|
|
366
|
+
return null;
|
|
367
|
+
}
|
|
368
|
+
});
|
|
369
|
+
var FormGroupLevelsManager = ({
|
|
370
|
+
children
|
|
371
|
+
}) => {
|
|
372
|
+
const [levelsLength, setLevelsLength] = import_react.default.useState(0);
|
|
373
|
+
const registerChild = import_react.default.useCallback(level => {
|
|
374
|
+
if (level + 1 > levelsLength) {
|
|
375
|
+
setLevelsLength(level + 1);
|
|
376
|
+
}
|
|
377
|
+
}, [levelsLength]);
|
|
378
|
+
return /* @__PURE__ */(0, import_jsx_runtime9.jsx)(FormGroupLevelsManagerContext.Provider, {
|
|
379
|
+
value: {
|
|
380
|
+
levelsLength,
|
|
381
|
+
registerChild
|
|
382
|
+
},
|
|
383
|
+
children
|
|
384
|
+
});
|
|
385
|
+
};
|
|
386
|
+
var FormGroupContext = import_react.default.createContext({});
|
|
387
|
+
var useFormGroup = () => {
|
|
388
|
+
const {
|
|
389
|
+
parentLevel
|
|
390
|
+
} = import_react.default.useContext(FormGroupContext);
|
|
391
|
+
const {
|
|
392
|
+
levelsLength
|
|
393
|
+
} = import_react.default.useContext(FormGroupLevelsManagerContext);
|
|
394
|
+
return {
|
|
395
|
+
level: parentLevel,
|
|
396
|
+
levelsLength
|
|
397
|
+
};
|
|
398
|
+
};
|
|
399
|
+
var FormGroupWrapper = ({
|
|
400
|
+
children
|
|
401
|
+
}) => {
|
|
402
|
+
const {
|
|
403
|
+
level,
|
|
404
|
+
levelsLength
|
|
405
|
+
} = useFormGroup();
|
|
406
|
+
const {
|
|
407
|
+
registerChild
|
|
408
|
+
} = import_react.default.useContext(FormGroupLevelsManagerContext);
|
|
409
|
+
import_react.default.useEffect(() => {
|
|
410
|
+
if (typeof level === "number") {
|
|
411
|
+
registerChild(level);
|
|
412
|
+
}
|
|
413
|
+
}, [level, registerChild]);
|
|
414
|
+
const sx = import_react.default.useMemo(() => {
|
|
415
|
+
return {
|
|
416
|
+
flexDirection: "column",
|
|
417
|
+
width: "100%",
|
|
418
|
+
gap: "md",
|
|
419
|
+
paddingLeft: ({
|
|
420
|
+
space
|
|
421
|
+
}) => {
|
|
422
|
+
if (!level || !levelsLength) {
|
|
423
|
+
return 0;
|
|
424
|
+
}
|
|
425
|
+
const value = levelsLength / level;
|
|
426
|
+
return `calc(${space["lg"]} / ${value})`;
|
|
427
|
+
}
|
|
428
|
+
};
|
|
429
|
+
}, [level, levelsLength]);
|
|
430
|
+
return /* @__PURE__ */(0, import_jsx_runtime9.jsx)(import_ui9.Flex, {
|
|
431
|
+
"aria-level": level,
|
|
432
|
+
sx,
|
|
433
|
+
children
|
|
434
|
+
});
|
|
435
|
+
};
|
|
436
|
+
var FormGroup = ({
|
|
437
|
+
children
|
|
438
|
+
}) => {
|
|
439
|
+
const {
|
|
440
|
+
level
|
|
441
|
+
} = useFormGroup();
|
|
442
|
+
const currentLevel = level === void 0 ? 0 : level + 1;
|
|
443
|
+
return /* @__PURE__ */(0, import_jsx_runtime9.jsx)(FormGroupContext.Provider, {
|
|
444
|
+
value: {
|
|
445
|
+
parentLevel: currentLevel
|
|
446
|
+
},
|
|
447
|
+
children: currentLevel === 0 ? /* @__PURE__ */(0, import_jsx_runtime9.jsx)(FormGroupLevelsManager, {
|
|
448
|
+
children: /* @__PURE__ */(0, import_jsx_runtime9.jsx)(FormGroupWrapper, {
|
|
449
|
+
children
|
|
450
|
+
})
|
|
451
|
+
}) : /* @__PURE__ */(0, import_jsx_runtime9.jsx)(FormGroupWrapper, {
|
|
452
|
+
children
|
|
453
|
+
})
|
|
454
|
+
});
|
|
455
|
+
};
|
|
383
456
|
// Annotate the CommonJS export names for ESM import in node:
|
|
384
457
|
0 && (module.exports = {
|
|
385
458
|
Form,
|
|
@@ -389,6 +462,8 @@ var FormFieldTextarea = ({
|
|
|
389
462
|
FormFieldRadio,
|
|
390
463
|
FormFieldSelect,
|
|
391
464
|
FormFieldTextarea,
|
|
465
|
+
FormGroup,
|
|
466
|
+
useFormGroup,
|
|
392
467
|
yup,
|
|
393
468
|
yupResolver,
|
|
394
469
|
...require("react-hook-form")
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ttoss/forms",
|
|
3
|
-
"version": "0.14.
|
|
3
|
+
"version": "0.14.29",
|
|
4
4
|
"license": "UNLICENSED",
|
|
5
5
|
"author": "ttoss",
|
|
6
6
|
"contributors": [
|
|
@@ -20,26 +20,26 @@
|
|
|
20
20
|
"typings": "dist/index.d.ts",
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"@hookform/error-message": "^2.0.1",
|
|
23
|
-
"@hookform/resolvers": "^
|
|
24
|
-
"react-hook-form": "^7.43.
|
|
25
|
-
"yup": "^1.
|
|
23
|
+
"@hookform/resolvers": "^3.0.1",
|
|
24
|
+
"react-hook-form": "^7.43.9",
|
|
25
|
+
"yup": "^1.1.0"
|
|
26
26
|
},
|
|
27
27
|
"peerDependencies": {
|
|
28
|
-
"@ttoss/ui": "^1.
|
|
28
|
+
"@ttoss/ui": "^1.31.15",
|
|
29
29
|
"react": "^18.2.0"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"@ttoss/config": "^1.29.3",
|
|
33
33
|
"@ttoss/test-utils": "^1.21.2",
|
|
34
|
-
"@ttoss/ui": "^1.31.
|
|
34
|
+
"@ttoss/ui": "^1.31.15",
|
|
35
35
|
"@types/jest": "^29.5.0",
|
|
36
36
|
"jest": "^29.5.0",
|
|
37
37
|
"react": "^18.2.0",
|
|
38
|
-
"react-hook-form": "^7.43.
|
|
39
|
-
"yup": "^1.
|
|
38
|
+
"react-hook-form": "^7.43.9",
|
|
39
|
+
"yup": "^1.1.0"
|
|
40
40
|
},
|
|
41
41
|
"publishConfig": {
|
|
42
42
|
"access": "public"
|
|
43
43
|
},
|
|
44
|
-
"gitHead": "
|
|
44
|
+
"gitHead": "8ef9fc83abcc00169860b2b6391bbb4d7374d911"
|
|
45
45
|
}
|
package/src/ErrorMessage.tsx
CHANGED
|
@@ -4,8 +4,10 @@ import { ErrorMessage as HookFormErrorMessage } from '@hookform/error-message';
|
|
|
4
4
|
|
|
5
5
|
export const ErrorMessage = <TFieldValues extends FieldValues = FieldValues>({
|
|
6
6
|
name,
|
|
7
|
+
disabled,
|
|
7
8
|
}: {
|
|
8
9
|
name: FieldName<TFieldValues>;
|
|
10
|
+
disabled?: boolean;
|
|
9
11
|
}) => {
|
|
10
12
|
const {
|
|
11
13
|
formState: { errors },
|
|
@@ -15,7 +17,7 @@ export const ErrorMessage = <TFieldValues extends FieldValues = FieldValues>({
|
|
|
15
17
|
<HookFormErrorMessage
|
|
16
18
|
errors={errors}
|
|
17
19
|
name={name as any}
|
|
18
|
-
as={<HelpText negative />}
|
|
20
|
+
as={<HelpText negative disabled={disabled} />}
|
|
19
21
|
/>
|
|
20
22
|
);
|
|
21
23
|
};
|
package/src/FormFieldInput.tsx
CHANGED
|
@@ -1,15 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Box,
|
|
3
|
-
Icon,
|
|
4
|
-
type IconType,
|
|
5
|
-
Input,
|
|
6
|
-
type InputProps,
|
|
7
|
-
Label,
|
|
8
|
-
Text,
|
|
9
|
-
} from '@ttoss/ui';
|
|
1
|
+
import { Box, Input, type InputProps, Label, type LabelProps } from '@ttoss/ui';
|
|
10
2
|
import { ErrorMessage } from './ErrorMessage';
|
|
11
3
|
import { FieldPath, FieldValues, useController } from 'react-hook-form';
|
|
12
|
-
import React from 'react';
|
|
13
4
|
|
|
14
5
|
export const FormFieldInput = <
|
|
15
6
|
TFieldValues extends FieldValues = FieldValues,
|
|
@@ -17,15 +8,14 @@ export const FormFieldInput = <
|
|
|
17
8
|
>({
|
|
18
9
|
label,
|
|
19
10
|
name,
|
|
20
|
-
|
|
21
|
-
|
|
11
|
+
tooltip,
|
|
12
|
+
onTooltipClick,
|
|
22
13
|
...inputProps
|
|
23
14
|
}: {
|
|
24
15
|
label?: string;
|
|
25
16
|
name: TName;
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
} & InputProps) => {
|
|
17
|
+
} & InputProps &
|
|
18
|
+
Pick<LabelProps, 'tooltip' | 'onTooltipClick'>) => {
|
|
29
19
|
const {
|
|
30
20
|
field: { onChange, onBlur, value, ref },
|
|
31
21
|
formState: { errors },
|
|
@@ -34,14 +24,6 @@ export const FormFieldInput = <
|
|
|
34
24
|
defaultValue: '',
|
|
35
25
|
});
|
|
36
26
|
|
|
37
|
-
const characterCounter = React.useMemo(() => {
|
|
38
|
-
if (!value) {
|
|
39
|
-
return 0;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
return String(value).length;
|
|
43
|
-
}, [value]);
|
|
44
|
-
|
|
45
27
|
const id = `form-field-input-${name}`;
|
|
46
28
|
|
|
47
29
|
const hasError = !!errors[name]?.message;
|
|
@@ -50,33 +32,12 @@ export const FormFieldInput = <
|
|
|
50
32
|
<Box>
|
|
51
33
|
{label && (
|
|
52
34
|
<Label
|
|
53
|
-
sx={{ display: 'flex', alignItems: 'center' }}
|
|
54
35
|
aria-disabled={inputProps.disabled}
|
|
55
36
|
htmlFor={id}
|
|
37
|
+
tooltip={tooltip}
|
|
38
|
+
onTooltipClick={onTooltipClick}
|
|
56
39
|
>
|
|
57
40
|
{label}
|
|
58
|
-
{tooltipIcon && (
|
|
59
|
-
<Text
|
|
60
|
-
sx={{ marginLeft: 'md', fontSize: 'xs', lineHeight: 0 }}
|
|
61
|
-
variant="tooltip-icon"
|
|
62
|
-
>
|
|
63
|
-
<Icon icon={tooltipIcon} />
|
|
64
|
-
</Text>
|
|
65
|
-
)}
|
|
66
|
-
|
|
67
|
-
{showCharacterCounter && (
|
|
68
|
-
<Text
|
|
69
|
-
sx={{
|
|
70
|
-
marginLeft: 'auto',
|
|
71
|
-
fontSize: 'xs',
|
|
72
|
-
lineHeight: 0,
|
|
73
|
-
color: 'underemphasize',
|
|
74
|
-
}}
|
|
75
|
-
variant="character-counter"
|
|
76
|
-
>
|
|
77
|
-
{characterCounter}
|
|
78
|
-
</Text>
|
|
79
|
-
)}
|
|
80
41
|
</Label>
|
|
81
42
|
)}
|
|
82
43
|
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { Flex, FlexProps } from '@ttoss/ui';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
|
|
4
|
+
type FormGroupLevelsManagerContextType = {
|
|
5
|
+
levelsLength?: number;
|
|
6
|
+
registerChild: (level: number) => void;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
const FormGroupLevelsManagerContext =
|
|
10
|
+
React.createContext<FormGroupLevelsManagerContextType>({
|
|
11
|
+
registerChild: () => {
|
|
12
|
+
return null;
|
|
13
|
+
},
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
const FormGroupLevelsManager = ({
|
|
17
|
+
children,
|
|
18
|
+
}: {
|
|
19
|
+
children: React.ReactNode;
|
|
20
|
+
}) => {
|
|
21
|
+
const [levelsLength, setLevelsLength] = React.useState(0);
|
|
22
|
+
|
|
23
|
+
const registerChild = React.useCallback(
|
|
24
|
+
(level: number) => {
|
|
25
|
+
if (level + 1 > levelsLength) {
|
|
26
|
+
setLevelsLength(level + 1);
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
[levelsLength]
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
<FormGroupLevelsManagerContext.Provider
|
|
34
|
+
value={{ levelsLength, registerChild }}
|
|
35
|
+
>
|
|
36
|
+
{children}
|
|
37
|
+
</FormGroupLevelsManagerContext.Provider>
|
|
38
|
+
);
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
type FormGroupContextType = {
|
|
42
|
+
parentLevel?: number;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const FormGroupContext = React.createContext<FormGroupContextType>({});
|
|
46
|
+
|
|
47
|
+
export const useFormGroup = () => {
|
|
48
|
+
const { parentLevel } = React.useContext(FormGroupContext);
|
|
49
|
+
const { levelsLength } = React.useContext(FormGroupLevelsManagerContext);
|
|
50
|
+
|
|
51
|
+
return {
|
|
52
|
+
level: parentLevel,
|
|
53
|
+
levelsLength,
|
|
54
|
+
};
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
type FormGroupProps = {
|
|
58
|
+
children: React.ReactNode;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const FormGroupWrapper = ({ children }: { children: React.ReactNode }) => {
|
|
62
|
+
const { level, levelsLength } = useFormGroup();
|
|
63
|
+
|
|
64
|
+
const { registerChild } = React.useContext(FormGroupLevelsManagerContext);
|
|
65
|
+
|
|
66
|
+
React.useEffect(() => {
|
|
67
|
+
/**
|
|
68
|
+
* We can't use if(level) because level can be 0 and we want to register
|
|
69
|
+
* it anyway.
|
|
70
|
+
*/
|
|
71
|
+
if (typeof level === 'number') {
|
|
72
|
+
registerChild(level);
|
|
73
|
+
}
|
|
74
|
+
}, [level, registerChild]);
|
|
75
|
+
|
|
76
|
+
const sx: FlexProps['sx'] = React.useMemo(() => {
|
|
77
|
+
return {
|
|
78
|
+
flexDirection: 'column',
|
|
79
|
+
width: '100%',
|
|
80
|
+
gap: 'md',
|
|
81
|
+
paddingLeft: ({ space }: any) => {
|
|
82
|
+
if (!level || !levelsLength) {
|
|
83
|
+
return 0;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const value = levelsLength / level;
|
|
87
|
+
|
|
88
|
+
return `calc(${space['lg']} / ${value})`;
|
|
89
|
+
},
|
|
90
|
+
};
|
|
91
|
+
}, [level, levelsLength]);
|
|
92
|
+
|
|
93
|
+
return (
|
|
94
|
+
<Flex aria-level={level} sx={sx}>
|
|
95
|
+
{children}
|
|
96
|
+
</Flex>
|
|
97
|
+
);
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
export const FormGroup = ({ children }: FormGroupProps) => {
|
|
101
|
+
const { level } = useFormGroup();
|
|
102
|
+
|
|
103
|
+
const currentLevel = level === undefined ? 0 : level + 1;
|
|
104
|
+
|
|
105
|
+
return (
|
|
106
|
+
<FormGroupContext.Provider value={{ parentLevel: currentLevel }}>
|
|
107
|
+
{currentLevel === 0 ? (
|
|
108
|
+
<FormGroupLevelsManager>
|
|
109
|
+
<FormGroupWrapper>{children}</FormGroupWrapper>
|
|
110
|
+
</FormGroupLevelsManager>
|
|
111
|
+
) : (
|
|
112
|
+
<FormGroupWrapper>{children}</FormGroupWrapper>
|
|
113
|
+
)}
|
|
114
|
+
</FormGroupContext.Provider>
|
|
115
|
+
);
|
|
116
|
+
};
|
package/src/index.ts
CHANGED
|
@@ -9,3 +9,4 @@ export { FormFieldInput } from './FormFieldInput';
|
|
|
9
9
|
export { FormFieldRadio } from './FormFieldRadio';
|
|
10
10
|
export { FormFieldSelect } from './FormFieldSelect';
|
|
11
11
|
export { FormFieldTextarea } from './FormFieldTextarea';
|
|
12
|
+
export { FormGroup, useFormGroup } from './FormGroup';
|