@akinon/akiform-builder 1.0.0 → 1.0.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.
Files changed (33) hide show
  1. package/dist/cjs/__tests__/akiform-builder.test.js +257 -83
  2. package/dist/cjs/__tests__/field-builder.test.js +48 -3
  3. package/dist/cjs/index.css +10 -0
  4. package/dist/cjs/src/akiform-builder.d.ts.map +1 -1
  5. package/dist/cjs/src/akiform-builder.js +230 -63
  6. package/dist/cjs/src/field-builder.d.ts +22 -5
  7. package/dist/cjs/src/field-builder.d.ts.map +1 -1
  8. package/dist/cjs/src/field-builder.js +81 -22
  9. package/dist/cjs/src/i18n/translations/en.d.ts +7 -0
  10. package/dist/cjs/src/i18n/translations/en.d.ts.map +1 -1
  11. package/dist/cjs/src/i18n/translations/en.js +8 -1
  12. package/dist/cjs/src/i18n/translations/tr.d.ts +7 -0
  13. package/dist/cjs/src/i18n/translations/tr.d.ts.map +1 -1
  14. package/dist/cjs/src/i18n/translations/tr.js +8 -1
  15. package/dist/cjs/src/types.d.ts +27 -5
  16. package/dist/cjs/src/types.d.ts.map +1 -1
  17. package/dist/esm/__tests__/akiform-builder.test.js +257 -83
  18. package/dist/esm/__tests__/field-builder.test.js +48 -3
  19. package/dist/esm/index.css +10 -0
  20. package/dist/esm/src/akiform-builder.d.ts.map +1 -1
  21. package/dist/esm/src/akiform-builder.js +231 -64
  22. package/dist/esm/src/field-builder.d.ts +22 -5
  23. package/dist/esm/src/field-builder.d.ts.map +1 -1
  24. package/dist/esm/src/field-builder.js +81 -22
  25. package/dist/esm/src/i18n/translations/en.d.ts +7 -0
  26. package/dist/esm/src/i18n/translations/en.d.ts.map +1 -1
  27. package/dist/esm/src/i18n/translations/en.js +8 -1
  28. package/dist/esm/src/i18n/translations/tr.d.ts +7 -0
  29. package/dist/esm/src/i18n/translations/tr.d.ts.map +1 -1
  30. package/dist/esm/src/i18n/translations/tr.js +8 -1
  31. package/dist/esm/src/types.d.ts +27 -5
  32. package/dist/esm/src/types.d.ts.map +1 -1
  33. package/package.json +19 -16
@@ -118,10 +118,54 @@ describe('FieldBuilder', () => {
118
118
  render: renderFn
119
119
  });
120
120
  });
121
+ it('should build row and col fields', () => {
122
+ const customField = field()
123
+ .type('row')
124
+ .key('mainrow')
125
+ .rowProps({
126
+ align: 'middle'
127
+ })
128
+ .columnFields([
129
+ field()
130
+ .type('column')
131
+ .key('col1')
132
+ .columnProps({
133
+ span: 24
134
+ })
135
+ .fields([
136
+ field().type('text').key('test1').label('Text label').build()
137
+ ])
138
+ .build()
139
+ ])
140
+ .build();
141
+ expect(customField).toEqual({
142
+ type: 'row',
143
+ key: 'mainrow',
144
+ rowProps: {
145
+ align: 'middle'
146
+ },
147
+ columnFields: [
148
+ {
149
+ type: 'column',
150
+ key: 'col1',
151
+ columnProps: {
152
+ span: 24
153
+ },
154
+ fields: [
155
+ {
156
+ type: 'text',
157
+ key: 'test1',
158
+ label: 'Text label'
159
+ }
160
+ ]
161
+ }
162
+ ]
163
+ });
164
+ });
121
165
  it('should throw an error if required properties are missing', () => {
122
- expect(() => field().build()).toThrow('Field must have at least a key, label, and type');
123
- expect(() => field().key('test').build()).toThrow('Field must have at least a key, label, and type');
124
- expect(() => field().key('test').label('Test').build()).toThrow('Field must have at least a key, label, and type');
166
+ expect(() => field().build()).toThrow('Field must have at least a key and type');
167
+ expect(() => field().key('test').build()).toThrow('Field must have at least a key and type');
168
+ expect(() => field().type('text').build()).toThrow('Field must have at least a key and type');
125
169
  });
126
170
  it('should only allow options for select fields', () => {
127
171
  const selectField = field()
@@ -236,6 +280,7 @@ describe('FieldBuilder', () => {
236
280
  .key('name')
237
281
  .label('Name')
238
282
  .type('text')
283
+ // @ts-expect-error : We are explicitly waiting .fields to throw an error.
239
284
  .fields([field().key('invalid').label('Invalid').type('text').build()])
240
285
  .build();
241
286
  expect(textField).toEqual({
@@ -5,3 +5,13 @@
5
5
  .akiform-builder-field-array {
6
6
  padding-bottom: 1rem;
7
7
  }
8
+
9
+ .akiform-builder-form-actions {
10
+ display: flex;
11
+ align-items: center;
12
+ gap: 0.5rem;
13
+ }
14
+
15
+ .akiform-builder-action-icon {
16
+ cursor: pointer;
17
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"akiform-builder.d.ts","sourceRoot":"","sources":["../../../src/akiform-builder.tsx"],"names":[],"mappings":"AAAA,OAAO,aAAa,CAAC;AAErB,OAAO,EAKL,WAAW,EAMZ,MAAM,iBAAiB,CAAC;AAWzB,OAAO,KAWN,MAAM,OAAO,CAAC;AAGf,OAAO,EACL,mBAAmB,EACnB,iBAAiB,EAMlB,MAAM,SAAS,CAAC;AAEjB,eAAO,MAAM,cAAc,MAAM,CAAC;AAgJlC,eAAO,MAAM,cAAc,yHAwS1B,CAAC"}
1
+ {"version":3,"file":"akiform-builder.d.ts","sourceRoot":"","sources":["../../../src/akiform-builder.tsx"],"names":[],"mappings":"AAAA,OAAO,aAAa,CAAC;AAErB,OAAO,EAML,WAAW,EAMZ,MAAM,iBAAiB,CAAC;AAczB,OAAO,KAWN,MAAM,OAAO,CAAC;AAGf,OAAO,EACL,mBAAmB,EACnB,iBAAiB,EAQlB,MAAM,SAAS,CAAC;AAEjB,eAAO,MAAM,cAAc,MAAM,CAAC;AA6WlC,eAAO,MAAM,cAAc,yHA+V1B,CAAC"}
@@ -12,35 +12,120 @@ var __rest = (this && this.__rest) || function (s, e) {
12
12
  import './index.css';
13
13
  import { Akiform, akivalResolver, FormItem, useFieldArray, useForm, useWatch } from '@akinon/akiform';
14
14
  import { akival } from '@akinon/akival';
15
+ import { Icon } from '@akinon/icons';
15
16
  import { Button } from '@akinon/ui-button';
16
17
  import { Checkbox } from '@akinon/ui-checkbox';
17
18
  import { Collapse } from '@akinon/ui-collapse';
18
19
  import { DatePicker } from '@akinon/ui-date-picker';
20
+ import { Divider } from '@akinon/ui-divider';
19
21
  import { Input, InputTextArea } from '@akinon/ui-input';
20
22
  import { InputNumber } from '@akinon/ui-input-number';
23
+ import { Col, Row } from '@akinon/ui-layout';
21
24
  import { Select } from '@akinon/ui-select';
22
- import { Space } from '@akinon/ui-space';
23
- import { Title } from '@akinon/ui-typography';
25
+ import { Text } from '@akinon/ui-typography';
26
+ import clsx from 'clsx';
24
27
  import React, { forwardRef, Fragment, useCallback, useEffect, useImperativeHandle, useMemo, useRef } from 'react';
25
28
  import { i18n } from './i18n';
26
29
  export const THROTTLE_DELAY = 300; // ms
30
+ const checkIsDisabled = ({ field, formValues }) => {
31
+ var _a;
32
+ const configDisabledProperty = (_a = field.config) === null || _a === void 0 ? void 0 : _a.disabled;
33
+ return typeof configDisabledProperty === 'function'
34
+ ? configDisabledProperty(formValues)
35
+ : !!configDisabledProperty;
36
+ };
37
+ const checkIsVisible = ({ field, formValues }) => {
38
+ var _a;
39
+ const configVisibleProperty = (_a = field.config) === null || _a === void 0 ? void 0 : _a.visible;
40
+ return typeof configVisibleProperty === 'function'
41
+ ? configVisibleProperty(formValues)
42
+ : configVisibleProperty !== false;
43
+ };
27
44
  const SectionComponent = ({ field, control, formValues, formState, layout, layoutOptions }) => {
28
- return (React.createElement(Collapse, { defaultActiveKey: field.defaultExpanded ? [field.key] : [], items: [
29
- {
30
- label: field.label,
31
- key: field.key,
32
- children: field.fields.map(nestedField => {
33
- var _a, _b;
34
- const isVisible = typeof ((_a = nestedField.config) === null || _a === void 0 ? void 0 : _a.visible) === 'function'
35
- ? nestedField.config.visible(formValues)
36
- : ((_b = nestedField.config) === null || _b === void 0 ? void 0 : _b.visible) !== false;
37
- if (!isVisible) {
38
- return null;
39
- }
40
- return (React.createElement(FormItem, { key: nestedField.key, control: control, name: nestedField.key, label: nestedField.label }, renderField(nestedField, control, formValues, formState, layout, layoutOptions)));
41
- })
42
- }
43
- ] }));
45
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
46
+ const { errors } = formState;
47
+ if (field.collapsible) {
48
+ return (React.createElement(Collapse, { defaultActiveKey: field.defaultExpanded ? [field.key] : [], expandIcon: panelProps => ({
49
+ name: 'circle-down',
50
+ style: {
51
+ color: 'var(--color-azure-500)',
52
+ transform: panelProps.isActive ? 'rotate(-180deg)' : 'rotate(0deg)',
53
+ transition: 'transform 0.3s'
54
+ },
55
+ size: 20
56
+ }), items: [
57
+ {
58
+ label: (React.createElement("div", { className: "akiform-builder-form-actions" },
59
+ React.createElement(Text, { strong: true }, field.label),
60
+ Object.keys(errors).length > 0 ? (React.createElement(Text, { strong: true, type: "danger" }, i18n.t('an_error_occurred'))) : null)),
61
+ key: field.key,
62
+ children: field.fields.map(nestedField => {
63
+ return renderFormItem({
64
+ field: nestedField,
65
+ control,
66
+ formValues,
67
+ formState,
68
+ layout,
69
+ layoutOptions
70
+ });
71
+ })
72
+ }
73
+ ] }));
74
+ }
75
+ else {
76
+ return (React.createElement(React.Fragment, null,
77
+ React.createElement(Divider, { orientation: "left", plain: true, plainOffset: 40 }, field.label),
78
+ field.fields.map(nestedField => {
79
+ return renderFormItem({
80
+ field: nestedField,
81
+ control,
82
+ formValues,
83
+ formState,
84
+ layout,
85
+ layoutOptions
86
+ });
87
+ })));
88
+ }
89
+ };
90
+ const RowComponent = ({ field, control, formValues, formState, layout, layoutOptions }) => {
91
+ const { columnFields, rowProps } = field;
92
+ if (!(columnFields === null || columnFields === void 0 ? void 0 : columnFields.length))
93
+ return;
94
+ return (React.createElement(Row, Object.assign({}, rowProps), columnFields.map(columnField => {
95
+ const { columnProps } = columnField;
96
+ const isVisible = checkIsVisible({
97
+ field: columnField,
98
+ formValues
99
+ });
100
+ if (!isVisible)
101
+ return null;
102
+ return (React.createElement(Col, Object.assign({ key: columnField.key, flex: "1" }, columnProps),
103
+ React.createElement(ColumnComponent, { field: columnField, control: control, formValues: formValues, formState: formState, layout: layout, layoutOptions: layoutOptions })));
104
+ })));
105
+ };
106
+ const ColumnComponent = ({ field, control, formValues, formState, layout, layoutOptions }) => {
107
+ const { fields } = field;
108
+ if (!(fields === null || fields === void 0 ? void 0 : fields.length))
109
+ return;
110
+ return fields.map(rowField => {
111
+ const isVisible = checkIsVisible({
112
+ field: rowField,
113
+ formValues
114
+ });
115
+ if (!isVisible)
116
+ return null;
117
+ const isRowField = rowField.type === 'row';
118
+ return isRowField
119
+ ? renderField(rowField, control, formValues, formState, layout, layoutOptions)
120
+ : renderFormItem({
121
+ field: rowField,
122
+ control,
123
+ formValues,
124
+ formState,
125
+ layout,
126
+ layoutOptions
127
+ });
128
+ });
44
129
  };
45
130
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
46
131
  const renderField = (field, control, formValues,
@@ -60,7 +145,7 @@ formState, layout, layoutOptions) => {
60
145
  case 'checkbox':
61
146
  return (React.createElement(Checkbox, Object.assign({ checked: formValues[field.key] }, commonProps), field.label));
62
147
  case 'date':
63
- return (React.createElement(DatePicker, Object.assign({ placeholder: field.placeholder, size: "large" }, commonProps)));
148
+ return (React.createElement(DatePicker, Object.assign({ placeholder: field.placeholder, showTime: field.showTime }, commonProps)));
64
149
  case 'textarea':
65
150
  return React.createElement(InputTextArea, Object.assign({ placeholder: field.placeholder }, commonProps));
66
151
  case 'fieldArray':
@@ -73,13 +158,32 @@ formState, layout, layoutOptions) => {
73
158
  return React.createElement(Fragment, null);
74
159
  case 'section':
75
160
  return (React.createElement(SectionComponent, { field: field, control: control, formValues: formValues, formState: formState, layout: layout, layoutOptions: layoutOptions }));
161
+ case 'row':
162
+ return (React.createElement(RowComponent, { field: field, control: control, formValues: formValues, formState: formState, layout: layout, layoutOptions: layoutOptions }));
163
+ case 'column':
164
+ return (React.createElement(ColumnComponent, { field: field, control: control, formValues: formValues, formState: formState, layout: layout, layoutOptions: layoutOptions }));
76
165
  default:
77
166
  return React.createElement(Fragment, null);
78
167
  }
79
168
  };
169
+ const renderFormItem = ({ field, control, formValues, formState, layout, layoutOptions, customVisibleCheck }) => {
170
+ const isVisible = customVisibleCheck
171
+ ? customVisibleCheck()
172
+ : checkIsVisible({
173
+ field,
174
+ formValues
175
+ });
176
+ if (!isVisible)
177
+ return null;
178
+ const isDisabled = checkIsDisabled({
179
+ field,
180
+ formValues
181
+ });
182
+ return (React.createElement(FormItem, { key: field.key, control: control, name: field.key, label: field.label, required: field.validation ? true : false, tooltip: field.tooltip, disabled: isDisabled, help: field.help, labelDescription: field.labelDescription }, renderField(field, control, formValues, formState, layout, layoutOptions)));
183
+ };
80
184
  export const AkiformBuilder = forwardRef((_a, ref) => {
81
185
  var _b, _c;
82
- var { fields, onSubmit, layout = 'vertical', layoutOptions, showResetButton = false, onReset, controlled = false, values, onValueChange } = _a, rest = __rest(_a, ["fields", "onSubmit", "layout", "layoutOptions", "showResetButton", "onReset", "controlled", "values", "onValueChange"]);
186
+ var { fields, onSubmit, layout = 'vertical', layoutOptions, showResetButton = false, onReset, controlled = false, values, onValueChange, submitButtonProps, resetButtonProps } = _a, rest = __rest(_a, ["fields", "onSubmit", "layout", "layoutOptions", "showResetButton", "onReset", "controlled", "values", "onValueChange", "submitButtonProps", "resetButtonProps"]);
83
187
  const validationSchema = useMemo(() => {
84
188
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
85
189
  const schema = {};
@@ -109,6 +213,8 @@ export const AkiformBuilder = forwardRef((_a, ref) => {
109
213
  const prevFormValuesRef = useRef(null);
110
214
  const isInitialRenderRef = useRef(true);
111
215
  const throttleTimeoutRef = useRef(null);
216
+ const hasSubmitButton = !!onSubmit;
217
+ const hasFormActions = hasSubmitButton || showResetButton;
112
218
  const handleValueChange = useCallback((values) => {
113
219
  if (!controlled) {
114
220
  if (throttleTimeoutRef.current) {
@@ -214,47 +320,78 @@ export const AkiformBuilder = forwardRef((_a, ref) => {
214
320
  }
215
321
  }
216
322
  }));
323
+ const renderSubmitButton = () => {
324
+ const _a = submitButtonProps || {}, { children, block = false, className } = _a, otherSubmitButtonProps = __rest(_a, ["children", "block", "className"]);
325
+ const submitButtonClassName = clsx(className, {
326
+ 'w-full': block
327
+ });
328
+ return (React.createElement(Button, Object.assign({ className: submitButtonClassName, type: "primary" }, otherSubmitButtonProps, { htmlType: "submit" }), children || i18n.t('submit')));
329
+ };
330
+ const renderShowResetButton = () => {
331
+ const _a = resetButtonProps || {}, { children, block = false, className, onClick } = _a, otherResetButtonProps = __rest(_a, ["children", "block", "className", "onClick"]);
332
+ const resetButtonClassName = clsx(className, {
333
+ 'w-full': block
334
+ });
335
+ const handleOnClickReset = event => {
336
+ handleReset(event);
337
+ if (onClick) {
338
+ onClick(event);
339
+ }
340
+ };
341
+ return (React.createElement(Button
342
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
343
+ , Object.assign({
344
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
345
+ onClick: handleOnClickReset, className: resetButtonClassName, type: "default" }, otherResetButtonProps, { htmlType: "reset" }), children || i18n.t('reset')));
346
+ };
347
+ const renderFormActions = () => {
348
+ return (React.createElement("div", { className: "akiform-builder-form-actions" },
349
+ hasSubmitButton && renderSubmitButton(),
350
+ showResetButton && renderShowResetButton()));
351
+ };
217
352
  return (React.createElement("div", { className: "akiform-builder" },
218
- React.createElement(Akiform, Object.assign({ onFinish: handleSubmit(onSubmit), onReset: handleReset, layout: layout }, formItemLayout, rest, { "data-testid": "akiform-builder", role: "form", "aria-label": i18n.t('formLabel'), requiredMark: true }),
353
+ React.createElement(Akiform, Object.assign({}, (hasSubmitButton && { onFinish: handleSubmit(onSubmit) }), { onReset: handleReset, layout: layout }, formItemLayout, rest, { "data-testid": "akiform-builder", role: "form", "aria-label": i18n.t('formLabel'), requiredMark: true }),
219
354
  fields.map(field => {
220
- var _a, _b, _c, _d;
221
- const isDisabled = typeof ((_a = field.config) === null || _a === void 0 ? void 0 : _a.disabled) === 'function'
222
- ? field.config.disabled(formValues)
223
- : (_b = field.config) === null || _b === void 0 ? void 0 : _b.disabled;
224
- const isVisible = typeof ((_c = field.config) === null || _c === void 0 ? void 0 : _c.visible) === 'function'
225
- ? field.config.visible(formValues)
226
- : ((_d = field.config) === null || _d === void 0 ? void 0 : _d.visible) !== false;
355
+ const isVisible = checkIsVisible({
356
+ field,
357
+ formValues
358
+ });
227
359
  if (!isVisible) {
228
360
  return null;
229
361
  }
230
- if (field.type === 'section') {
231
- return (React.createElement(SectionComponent, { key: field.key, field: field, control: control, formValues: formValues, formState: formState, layout: layout, layoutOptions: layoutOptions }));
362
+ switch (field.type) {
363
+ case 'section':
364
+ return (React.createElement(SectionComponent, { key: field.key, field: field, control: control, formValues: formValues, formState: formState, layout: layout, layoutOptions: layoutOptions }));
365
+ case 'fieldArray':
366
+ return (React.createElement("div", { className: "akiform-builder-field-array", key: field.key },
367
+ React.createElement(Divider, { orientation: "left", plain: true, plainOffset: 40 },
368
+ React.createElement("span", { id: `${field.key}-label` }, field.label)),
369
+ renderField(field, control, formValues, formState, layout, layoutOptions)));
370
+ case 'row':
371
+ return renderField(field, control, formValues, formState, layout, layoutOptions);
372
+ default:
373
+ return renderFormItem({
374
+ field,
375
+ control,
376
+ formValues,
377
+ formState,
378
+ layout,
379
+ layoutOptions
380
+ });
232
381
  }
233
- if (field.type === 'fieldArray') {
234
- return (React.createElement("div", { className: "akiform-builder-field-array", key: field.key },
235
- React.createElement(Title, { level: 5 }, field.label),
236
- renderField(field, control, formValues, formState, layout, layoutOptions)));
237
- }
238
- return (React.createElement(FormItem, { key: field.key, control: control, name: field.key, label: field.label, disabled: isDisabled, required: field.validation ? true : false, tooltip: field.tooltip }, renderField(field, control, formValues, formState, layout, layoutOptions)));
239
382
  }),
240
- React.createElement(FormItem, { control: control, name: 'form_actions', wrapperCol: layout === 'horizontal'
383
+ hasFormActions && (React.createElement(FormItem, { control: control, name: 'form_actions', wrapperCol: layout === 'horizontal'
241
384
  ? {
242
385
  offset: (_b = formItemLayout.labelCol) === null || _b === void 0 ? void 0 : _b.span,
243
386
  span: (_c = formItemLayout.wrapperCol) === null || _c === void 0 ? void 0 : _c.span
244
387
  }
245
- : undefined },
246
- React.createElement(Space, null,
247
- React.createElement(Button, { type: "primary", htmlType: "submit" }, i18n.t('submit')),
248
- showResetButton && (React.createElement(Button
249
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
250
- , {
251
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
252
- onClick: handleReset, type: "default", htmlType: "reset" }, i18n.t('reset'))))))));
388
+ : undefined }, renderFormActions())))));
253
389
  });
254
390
  AkiformBuilder.displayName = 'AkiformBuilder';
255
391
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
256
392
  const FieldArrayComponent = ({ field, control, formValues, formState, layout, layoutOptions }) => {
257
- const { fields, append, remove } = useFieldArray({
393
+ const { errors } = formState;
394
+ const { fields, append, remove, insert } = useFieldArray({
258
395
  control,
259
396
  name: field.key
260
397
  });
@@ -267,22 +404,52 @@ const FieldArrayComponent = ({ field, control, formValues, formState, layout, la
267
404
  {});
268
405
  };
269
406
  return (React.createElement("div", { role: "group", "aria-labelledby": `${field.key}-label` },
270
- React.createElement("div", { id: `${field.key}-label`, className: "sr-only", "aria-hidden": true }, field.label),
271
- fields.map((item, index) => (React.createElement("div", { key: item.id },
272
- field.fields.map(nestedField => {
273
- var _a, _b;
274
- const isVisible = typeof ((_a = nestedField.config) === null || _a === void 0 ? void 0 : _a.visible) === 'function'
275
- ? nestedField.config.visible(((_b = formValues[field.key]) === null || _b === void 0 ? void 0 : _b[index]) || {})
276
- : true;
277
- if (!isVisible) {
278
- return null;
279
- }
280
- return (React.createElement(FormItem, { key: `${field.key}.${index}.${nestedField.key}`, control: control, name: `${field.key}.${index}.${nestedField.key}`, label: nestedField.label, required: nestedField.validation ? true : false }, renderField(Object.assign(Object.assign({}, nestedField), {
281
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
282
- key: `${field.key}.${index}.${nestedField.key}` }), control, formValues, formState, layout, layoutOptions)));
283
- }),
284
- React.createElement(Button, { icon: "eksi", size: "small", danger: true, onClick: () => remove(index), "aria-label": `Remove ${field.label} ${index + 1}` }, "Remove")))),
285
- React.createElement(Button, { icon: "arti", size: "small", type: "text",
286
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
287
- onClick: () => append(createInitialValue()), "aria-label": `Add ${field.label}` }, "Add")));
407
+ !fields.length && (React.createElement("div", { className: "akiform-builder-form-actions akiform-builder-action-icon", "data-testid": `${field.key}-add-button`, onClick: () => append(createInitialValue()) },
408
+ React.createElement(Icon, { icon: "plus", size: 20, color: "var(--color-green-500)", "aria-label": i18n.t('add', { label: field.label }) }),
409
+ React.createElement(Text, { strong: true }, i18n.t('add', { label: field.label })))),
410
+ fields.map((item, index) => {
411
+ var _a;
412
+ return (React.createElement(Fragment, { key: item.id },
413
+ React.createElement(Collapse, { collapsible: "icon", defaultActiveKey: field.defaultExpanded ? [item.id] : [], expandIcon: panelProps => ({
414
+ name: 'circle-down',
415
+ style: {
416
+ color: 'var(--color-azure-500)',
417
+ transform: panelProps.isActive
418
+ ? 'rotate(-180deg)'
419
+ : 'rotate(0deg)',
420
+ transition: 'transform 0.3s'
421
+ },
422
+ size: 20
423
+ }), items: [
424
+ {
425
+ label: (React.createElement("div", { className: "akiform-builder-form-actions" },
426
+ React.createElement(Text, { strong: true }, i18n.t('itemof', {
427
+ label: field.label,
428
+ count: index + 1,
429
+ ordinal: true
430
+ })),
431
+ React.createElement(Icon, { className: "akiform-builder-action-icon", onClick: () => remove(index), icon: "minus", size: 20, color: "var(--color-red-500)", "aria-label": i18n.t('remove', { label: field.label }) }),
432
+ React.createElement(Icon, { className: "akiform-builder-action-icon", onClick: () => insert(index + 1, createInitialValue()), icon: "plus", size: 20, color: "var(--color-green-500)", "aria-label": i18n.t('add', { label: field.label }) }),
433
+ ((_a = errors[field.key]) === null || _a === void 0 ? void 0 : _a[index]) ? (React.createElement(Text, { strong: true, type: "danger" }, i18n.t('an_error_occurred'))) : null)),
434
+ key: field.key,
435
+ children: field.fields.map(nestedField => {
436
+ return renderFormItem({
437
+ field: Object.assign(Object.assign({}, nestedField), { key: `${field.key}.${index}.${nestedField.key}` }),
438
+ control,
439
+ formValues,
440
+ formState,
441
+ layout,
442
+ layoutOptions,
443
+ customVisibleCheck: () => {
444
+ var _a, _b;
445
+ return typeof ((_a = nestedField.config) === null || _a === void 0 ? void 0 : _a.visible) === 'function'
446
+ ? nestedField.config.visible(((_b = formValues[field.key]) === null || _b === void 0 ? void 0 : _b[index]) || {})
447
+ : true;
448
+ }
449
+ });
450
+ })
451
+ }
452
+ ] }),
453
+ React.createElement(Divider, { plain: true })));
454
+ })));
288
455
  };
@@ -1,10 +1,11 @@
1
1
  import { FieldPath, FieldValues } from '@akinon/akiform';
2
2
  import { AnySchema } from '@akinon/akival';
3
+ import { ColProps, RowProps } from '@akinon/ui-layout';
3
4
  import { TooltipProps } from '@akinon/ui-tooltip';
4
5
  import { FieldConfig, FieldType, FormField } from './types';
5
- type FieldTypeToBuilder<T extends FieldType, TFieldValues extends FieldValues = FieldValues> = T extends 'select' ? SelectFieldBuilder<TFieldValues> : T extends 'custom' ? CustomFieldBuilder<TFieldValues> : T extends 'section' ? SectionFieldBuilder<TFieldValues> : BaseFieldBuilder<TFieldValues>;
6
+ type FieldTypeToBuilder<T extends FieldType, TFieldValues extends FieldValues = FieldValues> = T extends 'select' ? SelectFieldBuilder<TFieldValues> : T extends 'date' ? DateFieldBuilder<TFieldValues> : T extends 'custom' ? CustomFieldBuilder<TFieldValues> : T extends 'section' ? SectionFieldBuilder<TFieldValues> : T extends 'fieldArray' ? FieldArrayOrSectionFieldBuilder<TFieldValues> : T extends 'row' ? RowFieldBuilder<TFieldValues> : T extends 'column' ? ColumnFieldBuilder<TFieldValues> : BaseFieldBuilder<TFieldValues>;
6
7
  declare class BaseFieldBuilder<TFieldValues extends FieldValues = FieldValues> {
7
- protected field: Partial<FormField<TFieldValues>>;
8
+ field: Partial<FormField<TFieldValues>>;
8
9
  key(key: FieldPath<TFieldValues>): this;
9
10
  label(label: string): this;
10
11
  type<T extends FieldType>(type: T): FieldTypeToBuilder<T, TFieldValues>;
@@ -12,8 +13,9 @@ declare class BaseFieldBuilder<TFieldValues extends FieldValues = FieldValues> {
12
13
  defaultValue(value: any): this;
13
14
  validation(schema: AnySchema): this;
14
15
  config(config: FieldConfig<TFieldValues>): this;
15
- fields(fields: FormField<TFieldValues>[]): this;
16
16
  tooltip(tooltipProps: TooltipProps | string): this;
17
+ help(help: string): this;
18
+ labelDescription(labelDescription: string): this;
17
19
  build(): FormField<TFieldValues>;
18
20
  }
19
21
  declare class SelectFieldBuilder<TFieldValues extends FieldValues = FieldValues> extends BaseFieldBuilder<TFieldValues> {
@@ -22,6 +24,9 @@ declare class SelectFieldBuilder<TFieldValues extends FieldValues = FieldValues>
22
24
  label: string;
23
25
  }>): this;
24
26
  }
27
+ declare class DateFieldBuilder<TFieldValues extends FieldValues = FieldValues> extends BaseFieldBuilder<TFieldValues> {
28
+ showTime(showTime: boolean): this;
29
+ }
25
30
  declare class CustomFieldBuilder<TFieldValues extends FieldValues = FieldValues> extends BaseFieldBuilder<TFieldValues> {
26
31
  render(renderFn: (props: {
27
32
  field: FormField<TFieldValues>;
@@ -29,9 +34,21 @@ declare class CustomFieldBuilder<TFieldValues extends FieldValues = FieldValues>
29
34
  control: any;
30
35
  }) => React.ReactElement): this;
31
36
  }
32
- declare class SectionFieldBuilder<TFieldValues extends FieldValues = FieldValues> extends BaseFieldBuilder<TFieldValues> {
37
+ declare class FieldArrayOrSectionFieldBuilder<TFieldValues extends FieldValues = FieldValues> extends BaseFieldBuilder<TFieldValues> {
33
38
  defaultExpanded(expanded: boolean): this;
39
+ fields(fields: FormField<TFieldValues>[]): this;
40
+ }
41
+ declare class SectionFieldBuilder<TFieldValues extends FieldValues = FieldValues> extends FieldArrayOrSectionFieldBuilder<TFieldValues> {
42
+ collapsible(collapsible: boolean): this;
43
+ }
44
+ declare class RowFieldBuilder<TFieldValues extends FieldValues = FieldValues> extends BaseFieldBuilder<TFieldValues> {
45
+ columnFields(columnFields: FormField<TFieldValues>[]): this;
46
+ rowProps(rowProps: RowProps): this;
47
+ }
48
+ declare class ColumnFieldBuilder<TFieldValues extends FieldValues = FieldValues> extends BaseFieldBuilder<TFieldValues> {
49
+ fields(fields: FormField<TFieldValues>[]): this;
50
+ columnProps(columnProps: ColProps): this;
34
51
  }
35
- export declare function field<TFieldValues extends FieldValues = FieldValues>(): BaseFieldBuilder<TFieldValues> & SelectFieldBuilder<TFieldValues> & CustomFieldBuilder<TFieldValues> & SectionFieldBuilder<TFieldValues>;
52
+ export declare function field<TFieldValues extends FieldValues = FieldValues>(): BaseFieldBuilder<TFieldValues> & SelectFieldBuilder<TFieldValues> & DateFieldBuilder<TFieldValues> & CustomFieldBuilder<TFieldValues> & SectionFieldBuilder<TFieldValues> & FieldArrayOrSectionFieldBuilder<TFieldValues>;
36
53
  export {};
37
54
  //# sourceMappingURL=field-builder.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"field-builder.d.ts","sourceRoot":"","sources":["../../../src/field-builder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,OAAO,EAEL,WAAW,EACX,SAAS,EACT,SAAS,EAEV,MAAM,SAAS,CAAC;AAEjB,KAAK,kBAAkB,CACrB,CAAC,SAAS,SAAS,EACnB,YAAY,SAAS,WAAW,GAAG,WAAW,IAC5C,CAAC,SAAS,QAAQ,GAClB,kBAAkB,CAAC,YAAY,CAAC,GAChC,CAAC,SAAS,QAAQ,GAChB,kBAAkB,CAAC,YAAY,CAAC,GAChC,CAAC,SAAS,SAAS,GACjB,mBAAmB,CAAC,YAAY,CAAC,GACjC,gBAAgB,CAAC,YAAY,CAAC,CAAC;AAEvC,cAAM,gBAAgB,CAAC,YAAY,SAAS,WAAW,GAAG,WAAW;IACnE,SAAS,CAAC,KAAK,EAAE,OAAO,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAM;IAEvD,GAAG,CAAC,GAAG,EAAE,SAAS,CAAC,YAAY,CAAC,GAAG,IAAI;IAKvC,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAK1B,IAAI,CAAC,CAAC,SAAS,SAAS,EAAE,IAAI,EAAE,CAAC,GAAG,kBAAkB,CAAC,CAAC,EAAE,YAAY,CAAC;IAKvE,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;IAMtC,YAAY,CAAC,KAAK,EAAE,GAAG,GAAG,IAAI;IAK9B,UAAU,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI;IAKnC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,YAAY,CAAC,GAAG,IAAI;IAM/C,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,YAAY,CAAC,EAAE,GAAG,IAAI;IAa/C,OAAO,CAAC,YAAY,EAAE,YAAY,GAAG,MAAM,GAAG,IAAI;IAKlD,KAAK,IAAI,SAAS,CAAC,YAAY,CAAC;CAMjC;AAED,cAAM,kBAAkB,CACtB,YAAY,SAAS,WAAW,GAAG,WAAW,CAC9C,SAAQ,gBAAgB,CAAC,YAAY,CAAC;IACtC,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,GAAG,IAAI;CAKzE;AAED,cAAM,kBAAkB,CACtB,YAAY,SAAS,WAAW,GAAG,WAAW,CAC9C,SAAQ,gBAAgB,CAAC,YAAY,CAAC;IACtC,MAAM,CACJ,QAAQ,EAAE,CAAC,KAAK,EAAE;QAChB,KAAK,EAAE,SAAS,CAAC,YAAY,CAAC,CAAC;QAC/B,UAAU,EAAE,YAAY,CAAC;QAEzB,OAAO,EAAE,GAAG,CAAC;KACd,KAAK,KAAK,CAAC,YAAY,GACvB,IAAI;CAKR;AAED,cAAM,mBAAmB,CACvB,YAAY,SAAS,WAAW,GAAG,WAAW,CAC9C,SAAQ,gBAAgB,CAAC,YAAY,CAAC;IACtC,eAAe,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI;CAIzC;AAED,wBAAgB,KAAK,CACnB,YAAY,SAAS,WAAW,GAAG,WAAW,KAC3C,gBAAgB,CAAC,YAAY,CAAC,GACjC,kBAAkB,CAAC,YAAY,CAAC,GAChC,kBAAkB,CAAC,YAAY,CAAC,GAChC,mBAAmB,CAAC,YAAY,CAAC,CAoBlC"}
1
+ {"version":3,"file":"field-builder.d.ts","sourceRoot":"","sources":["../../../src/field-builder.ts"],"names":[],"mappings":"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"}