@react-fabric/form 1.0.0-beta.5 → 1.0.0-beta.51

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 (174) hide show
  1. package/{src/input/ArrayInput.module.css → css/_arrayInput.css} +8 -8
  2. package/css/_colorPicker.css +65 -0
  3. package/{src/internal/Field.module.css → css/_field.css} +64 -29
  4. package/{src/input/File.module.css → css/_file.css} +21 -6
  5. package/css/styles.css +27 -0
  6. package/dist/cjs/builder/FileField.js +37 -25
  7. package/dist/cjs/builder/FormField.js +50 -34
  8. package/dist/cjs/builder/SchemaEditor.js +72 -0
  9. package/dist/cjs/builder/components/AddSchemaFields.js +62 -0
  10. package/dist/cjs/builder/components/SchemaArrayForm.js +143 -0
  11. package/dist/cjs/builder/components/SchemaField.js +414 -0
  12. package/dist/cjs/form/Controller.js +1 -1
  13. package/dist/cjs/form/Form.js +11 -6
  14. package/dist/cjs/hooks/useFormBuilder.js +27 -15
  15. package/dist/cjs/index.js +11 -2
  16. package/dist/cjs/input/ArrayInput.js +61 -33
  17. package/dist/cjs/input/AvatarInput.js +9 -8
  18. package/dist/cjs/input/Checkbox.js +6 -5
  19. package/dist/cjs/input/ColorInput.js +95 -56
  20. package/dist/cjs/input/ColorPicker.js +1 -35
  21. package/dist/cjs/input/DateInput.js +186 -0
  22. package/dist/cjs/input/Field.js +5 -4
  23. package/dist/cjs/input/File.js +4 -7
  24. package/dist/cjs/input/Hidden.js +3 -1
  25. package/dist/cjs/input/Input.js +11 -7
  26. package/dist/cjs/input/Number.js +9 -7
  27. package/dist/cjs/input/Password.js +10 -8
  28. package/dist/cjs/input/Radio.js +2 -2
  29. package/dist/cjs/input/RadioGroup.js +6 -3
  30. package/dist/cjs/input/{Range.js → RangeSlider.js} +5 -5
  31. package/dist/cjs/input/Search.js +16 -16
  32. package/dist/cjs/input/Slider.js +3 -3
  33. package/dist/cjs/input/Switch.js +30 -7
  34. package/dist/cjs/input/Textarea.js +13 -4
  35. package/dist/cjs/internal/ErrorIcon.js +1 -1
  36. package/dist/cjs/internal/FieldWrapper.js +11 -4
  37. package/dist/cjs/internal/InputWrapper.js +19 -16
  38. package/dist/cjs/select/AutoComplete.js +12 -8
  39. package/dist/cjs/select/DualList.js +4 -1
  40. package/dist/cjs/select/List.js +45 -20
  41. package/dist/cjs/select/Options.js +2 -2
  42. package/dist/cjs/select/Select.js +14 -4
  43. package/dist/cjs/select/useSelect.js +10 -6
  44. package/dist/cjs/types/schema.js +43 -0
  45. package/dist/cjs/utils/eventHandlers.js +11 -5
  46. package/dist/cjs/utils/getColor.js +6 -0
  47. package/dist/esm/builder/FileField.js +39 -27
  48. package/dist/esm/builder/FormField.js +50 -34
  49. package/dist/esm/builder/SchemaEditor.js +72 -0
  50. package/dist/esm/builder/components/AddSchemaFields.js +62 -0
  51. package/dist/esm/builder/components/SchemaArrayForm.js +143 -0
  52. package/dist/esm/builder/components/SchemaField.js +414 -0
  53. package/dist/esm/form/Controller.js +1 -1
  54. package/dist/esm/form/Form.js +11 -6
  55. package/dist/esm/hooks/useFormBuilder.js +25 -13
  56. package/dist/esm/index.js +5 -1
  57. package/dist/esm/input/ArrayInput.js +61 -33
  58. package/dist/esm/input/AvatarInput.js +9 -8
  59. package/dist/esm/input/Checkbox.js +6 -5
  60. package/dist/esm/input/ColorInput.js +97 -58
  61. package/dist/esm/input/ColorPicker.js +1 -35
  62. package/dist/esm/input/DateInput.js +186 -0
  63. package/dist/esm/input/Field.js +6 -5
  64. package/dist/esm/input/File.js +6 -9
  65. package/dist/esm/input/Hidden.js +3 -1
  66. package/dist/esm/input/Input.js +13 -9
  67. package/dist/esm/input/Number.js +11 -9
  68. package/dist/esm/input/Password.js +12 -10
  69. package/dist/esm/input/Radio.js +2 -2
  70. package/dist/esm/input/RadioGroup.js +7 -4
  71. package/dist/esm/input/{Range.js → RangeSlider.js} +5 -5
  72. package/dist/esm/input/Search.js +18 -18
  73. package/dist/esm/input/Slider.js +3 -3
  74. package/dist/esm/input/Switch.js +32 -9
  75. package/dist/esm/input/Textarea.js +14 -5
  76. package/dist/esm/internal/ErrorIcon.js +1 -1
  77. package/dist/esm/internal/FieldWrapper.js +11 -4
  78. package/dist/esm/internal/InputWrapper.js +19 -16
  79. package/dist/esm/select/AutoComplete.js +12 -8
  80. package/dist/esm/select/DualList.js +4 -1
  81. package/dist/esm/select/List.js +46 -21
  82. package/dist/esm/select/Options.js +2 -2
  83. package/dist/esm/select/Select.js +14 -4
  84. package/dist/esm/select/useSelect.js +11 -7
  85. package/{src/input/ColorPicker.module.css → dist/esm/types/schema.js} +18 -27
  86. package/dist/esm/utils/eventHandlers.js +11 -5
  87. package/dist/esm/utils/getColor.js +6 -1
  88. package/dist/types/builder/FileField.d.ts +4 -2
  89. package/dist/types/builder/FormField.d.ts +3 -1
  90. package/dist/types/builder/SchemaEditor.d.ts +2 -0
  91. package/dist/types/builder/components/AddSchemaFields.d.ts +2 -0
  92. package/dist/types/builder/components/SchemaArrayForm.d.ts +2 -0
  93. package/dist/types/builder/components/SchemaField.d.ts +10 -0
  94. package/dist/types/form/Controller.d.ts +2 -2
  95. package/dist/types/form/Form.d.ts +5 -1
  96. package/dist/types/hooks/useFormBuilder.d.ts +3 -1
  97. package/dist/types/index.d.ts +5 -2
  98. package/dist/types/input/ArrayInput.d.ts +39 -6
  99. package/dist/types/input/AvatarInput.d.ts +6 -3
  100. package/dist/types/input/Checkbox.d.ts +4 -4
  101. package/dist/types/input/ColorInput.d.ts +2 -2
  102. package/dist/types/input/ColorPicker.d.ts +1 -1
  103. package/dist/types/input/DateInput.d.ts +19 -0
  104. package/dist/types/input/Field.d.ts +0 -1
  105. package/dist/types/input/Input.d.ts +1 -1
  106. package/dist/types/input/Number.d.ts +1 -1
  107. package/dist/types/input/Password.d.ts +1 -1
  108. package/dist/types/input/Radio.d.ts +0 -1
  109. package/dist/types/input/RadioGroup.d.ts +18 -3
  110. package/dist/types/input/{Range.d.ts → RangeSlider.d.ts} +1 -1
  111. package/dist/types/input/Search.d.ts +5 -1
  112. package/dist/types/input/Switch.d.ts +7 -4
  113. package/dist/types/input/Textarea.d.ts +5 -1
  114. package/dist/types/internal/FieldWrapper.d.ts +1 -1
  115. package/dist/types/internal/InputWrapper.d.ts +1 -1
  116. package/dist/types/ranger/index.d.ts +2 -2
  117. package/dist/types/select/AutoComplete.d.ts +1 -1
  118. package/dist/types/select/DualList.d.ts +6 -2
  119. package/dist/types/select/List.d.ts +1 -1
  120. package/dist/types/select/Select.d.ts +1 -1
  121. package/dist/types/select/useSelect.d.ts +7 -15
  122. package/dist/types/types/index.d.ts +28 -7
  123. package/dist/types/types/schema.d.ts +78 -33
  124. package/dist/types/utils/eventHandlers.d.ts +1 -1
  125. package/package.json +15 -12
  126. package/src/builder/FileField.tsx +53 -27
  127. package/src/builder/FormField.tsx +52 -32
  128. package/src/builder/SchemaEditor.tsx +72 -0
  129. package/src/builder/components/AddSchemaFields.tsx +74 -0
  130. package/src/builder/components/SchemaArrayForm.tsx +158 -0
  131. package/src/builder/components/SchemaField.tsx +436 -0
  132. package/src/form/Controller.tsx +3 -3
  133. package/src/form/Form.tsx +14 -5
  134. package/src/hooks/useFormBuilder.tsx +29 -15
  135. package/src/index.ts +11 -2
  136. package/src/input/ArrayInput.tsx +130 -54
  137. package/src/input/AvatarInput.tsx +12 -8
  138. package/src/input/Checkbox.tsx +6 -5
  139. package/src/input/ColorInput.tsx +113 -69
  140. package/src/input/ColorPicker.tsx +2 -36
  141. package/src/input/DateInput.tsx +250 -0
  142. package/src/input/Field.tsx +10 -11
  143. package/src/input/File.tsx +7 -14
  144. package/src/input/Hidden.tsx +4 -1
  145. package/src/input/Input.tsx +15 -10
  146. package/src/input/Number.tsx +10 -10
  147. package/src/input/Password.tsx +13 -12
  148. package/src/input/Radio.tsx +2 -2
  149. package/src/input/RadioGroup.tsx +27 -4
  150. package/src/input/{Range.tsx → RangeSlider.tsx} +4 -4
  151. package/src/input/Search.tsx +20 -19
  152. package/src/input/Slider.tsx +3 -3
  153. package/src/input/Switch.tsx +43 -7
  154. package/src/input/Textarea.tsx +19 -5
  155. package/src/internal/ErrorIcon.tsx +1 -1
  156. package/src/internal/FieldWrapper.tsx +8 -4
  157. package/src/internal/InputWrapper.tsx +36 -20
  158. package/src/select/AutoComplete.tsx +5 -1
  159. package/src/select/DualList.tsx +8 -0
  160. package/src/select/List.tsx +41 -8
  161. package/src/select/Options.tsx +1 -1
  162. package/src/select/Select.tsx +13 -3
  163. package/src/select/useSelect.tsx +13 -5
  164. package/src/types/index.ts +34 -8
  165. package/src/types/schema.ts +96 -41
  166. package/src/utils/eventHandlers.ts +9 -3
  167. package/dist/cjs/input/ArrayInput.module.css +0 -1
  168. package/dist/cjs/input/ColorPicker.module.css +0 -1
  169. package/dist/cjs/input/File.module.css +0 -1
  170. package/dist/cjs/internal/Field.module.css +0 -1
  171. package/dist/esm/input/ArrayInput.module.css +0 -1
  172. package/dist/esm/input/ColorPicker.module.css +0 -1
  173. package/dist/esm/input/File.module.css +0 -1
  174. package/dist/esm/internal/Field.module.css +0 -1
@@ -0,0 +1,414 @@
1
+ 'use client';
2
+
3
+ import _toConsumableArray from '@babel/runtime/helpers/toConsumableArray';
4
+ import _defineProperty from '@babel/runtime/helpers/defineProperty';
5
+ import _slicedToArray from '@babel/runtime/helpers/slicedToArray';
6
+ import { useSortable } from '@dnd-kit/sortable';
7
+ import { CSS } from '@dnd-kit/utilities';
8
+ import { useOverlayService, Modal, Content, Footer, Button, Collapsable, CoreIcons, ToggleButtonGroup } from '@react-fabric/core';
9
+ import { EMPTY_ARRAY } from '@react-fabric/utilities';
10
+ import classNames from 'classnames';
11
+ import { useState, useCallback, useEffect, Fragment } from 'react';
12
+ import { Controller } from '../../form/Controller.js';
13
+ import { ArrayInput } from '../../input/ArrayInput.js';
14
+ import { Checkbox } from '../../input/Checkbox.js';
15
+ import { DateInput } from '../../input/DateInput.js';
16
+ import { Field } from '../../input/Field.js';
17
+ import { HiddenInput } from '../../input/Hidden.js';
18
+ import { Input } from '../../input/Input.js';
19
+ import { Number } from '../../input/Number.js';
20
+ import { Select } from '../../select/Select.js';
21
+ import { SCHEMA_CUSTOM_LIST, DATA_TYPES } from '../../types/schema.js';
22
+ import { jsxs, jsx } from 'react/jsx-runtime';
23
+
24
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
25
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
26
+ var SchemaField = function SchemaField(_ref) {
27
+ var id = _ref.id,
28
+ field = _ref.field,
29
+ fieldId = _ref.fieldId,
30
+ getModel = _ref.getModel,
31
+ onRemove = _ref.onRemove,
32
+ _ref$defaultOpen = _ref.defaultOpen,
33
+ defaultOpen = _ref$defaultOpen === void 0 ? true : _ref$defaultOpen,
34
+ _ref$optionLists = _ref.optionLists,
35
+ optionLists = _ref$optionLists === void 0 ? EMPTY_ARRAY : _ref$optionLists,
36
+ dynamic = _ref.dynamic,
37
+ onTypeChange = _ref.onTypeChange,
38
+ acceptableTypes = _ref.acceptableTypes;
39
+ var _useState = useState(),
40
+ _useState2 = _slicedToArray(_useState, 2),
41
+ type = _useState2[0],
42
+ setType = _useState2[1];
43
+ var _useState3 = useState(false),
44
+ _useState4 = _slicedToArray(_useState3, 2),
45
+ multiple = _useState4[0],
46
+ setMultiple = _useState4[1];
47
+ var _useState5 = useState(false),
48
+ _useState6 = _slicedToArray(_useState5, 2),
49
+ hasOptions = _useState6[0],
50
+ setHasOptions = _useState6[1];
51
+ var _useState7 = useState(false),
52
+ _useState8 = _slicedToArray(_useState7, 2),
53
+ customOptions = _useState8[0],
54
+ setCustomOptions = _useState8[1];
55
+ var SortableItem = useCallback(function (_ref2) {
56
+ var id = _ref2.id,
57
+ children = _ref2.children,
58
+ className = _ref2.className;
59
+ if (dynamic) {
60
+ var _useSortable = useSortable({
61
+ id: id
62
+ }),
63
+ attributes = _useSortable.attributes,
64
+ listeners = _useSortable.listeners,
65
+ setNodeRef = _useSortable.setNodeRef,
66
+ transform = _useSortable.transform,
67
+ transition = _useSortable.transition,
68
+ isDragging = _useSortable.isDragging;
69
+ return /*#__PURE__*/jsxs("div", {
70
+ className: className,
71
+ ref: setNodeRef,
72
+ style: {
73
+ transform: CSS.Transform.toString(transform),
74
+ transition: transition
75
+ },
76
+ children: [/*#__PURE__*/jsx("div", _objectSpread(_objectSpread(_objectSpread({
77
+ className: classNames("invisible group-hover/field:visible my-2 w-4", isDragging ? "cursor-grabbing" : "cursor-grab")
78
+ }, attributes), listeners), {}, {
79
+ style: {
80
+ backgroundImage: "url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='4' width='4'%3E%3Ccircle cx='2' cy='2' r='1' fill='%238888' /%3E%3C/svg%3E \")"
81
+ }
82
+ })), children]
83
+ });
84
+ }
85
+ return /*#__PURE__*/jsx("div", {
86
+ className: className,
87
+ children: children
88
+ });
89
+ }, [dynamic]);
90
+ // @ts-expect-error ignore
91
+ SortableItem.displayName = "SortableItem";
92
+ var _useOverlayService = useOverlayService(function (props) {
93
+ return /*#__PURE__*/jsxs(Modal, _objectSpread(_objectSpread({}, props), {}, {
94
+ children: [/*#__PURE__*/jsx(Content, {
95
+ children: /*#__PURE__*/jsx(ArrayInput, {
96
+ name: "".concat(field, ".options"),
97
+ onAdd: function onAdd() {
98
+ return String("");
99
+ },
100
+ children: /*#__PURE__*/jsx(Controller, {
101
+ children: /*#__PURE__*/jsx(Input, {})
102
+ })
103
+ })
104
+ }), /*#__PURE__*/jsx(Footer, {
105
+ flex: true,
106
+ justify: "end",
107
+ className: "sticky bottom-0 border-t bg-base px-6 py-2",
108
+ children: /*#__PURE__*/jsx(Button, {
109
+ variant: "link",
110
+ onClick: props.onClose,
111
+ children: "Close"
112
+ })
113
+ })]
114
+ }));
115
+ }),
116
+ _useOverlayService2 = _slicedToArray(_useOverlayService, 2),
117
+ OptionModal = _useOverlayService2[0],
118
+ openOptionModal = _useOverlayService2[1];
119
+ useEffect(function () {
120
+ setTimeout(function () {
121
+ var model = getModel();
122
+ setType(model.datatype);
123
+ setMultiple(model.multiple);
124
+ setHasOptions(!!model.optionList);
125
+ setCustomOptions(model.optionList === SCHEMA_CUSTOM_LIST);
126
+ }, 10);
127
+ }, []);
128
+ var handleTypeChange = useCallback(function (type) {
129
+ if (type) {
130
+ var modelRef = getModel();
131
+ var reset = {
132
+ datatype: type,
133
+ id: id,
134
+ label: modelRef.label,
135
+ defaultValue: modelRef.defaultValue,
136
+ required: modelRef.required,
137
+ multiple: type === DATA_TYPES.AVATAR ? false : modelRef.multiple,
138
+ minItems: modelRef.minItems,
139
+ maxItems: modelRef.maxItems
140
+ };
141
+ if (type === DATA_TYPES.STRING) {
142
+ reset = Object.assign(reset, {
143
+ optionList: modelRef.optionList,
144
+ options: modelRef.options,
145
+ regex: modelRef.regex
146
+ });
147
+ } else if (type === DATA_TYPES.DATE) {
148
+ reset = Object.assign(reset, {
149
+ min: modelRef.min,
150
+ max: modelRef.max
151
+ });
152
+ } else if (type === DATA_TYPES.NUMBER || type === DATA_TYPES.RANGE) {
153
+ reset = Object.assign(reset, {
154
+ min: modelRef.min,
155
+ max: modelRef.max,
156
+ step: modelRef.step
157
+ });
158
+ }
159
+ if (type === DATA_TYPES.AVATAR) {
160
+ setMultiple(false);
161
+ }
162
+ onTypeChange(reset);
163
+ setType(type);
164
+ }
165
+ }, [id]);
166
+ return /*#__PURE__*/jsx(SortableItem, {
167
+ id: fieldId,
168
+ className: "flex flex-nowrap gap-1 group/field",
169
+ children: /*#__PURE__*/jsxs(Collapsable, {
170
+ open: defaultOpen,
171
+ className: "flex-1",
172
+ children: [/*#__PURE__*/jsxs("div", {
173
+ className: "flex flex-nowrap items-center",
174
+ children: [/*#__PURE__*/jsx("span", {
175
+ className: "flex-1 truncate",
176
+ children: id
177
+ }), dynamic && /*#__PURE__*/jsx(Button, {
178
+ size: "sm",
179
+ color: "danger",
180
+ variant: "link",
181
+ "aria-label": "Delete",
182
+ stopPropagation: true,
183
+ icon: CoreIcons.trash,
184
+ onClick: onRemove,
185
+ className: "invisible group-hover/field:visible"
186
+ })]
187
+ }), /*#__PURE__*/jsxs("div", {
188
+ className: "flex flex-col gap-1 pb-4",
189
+ children: [/*#__PURE__*/jsx(Controller, {
190
+ name: "".concat(field, ".id"),
191
+ children: /*#__PURE__*/jsx(HiddenInput, {
192
+ hiddenValue: id
193
+ })
194
+ }), /*#__PURE__*/jsx(Controller, {
195
+ name: "".concat(field, ".datatype"),
196
+ children: /*#__PURE__*/jsx(Select, {
197
+ inline: true,
198
+ label: "Type",
199
+ placeholder: "Data type",
200
+ options: acceptableTypes,
201
+ onChange: function onChange(val) {
202
+ return handleTypeChange(val);
203
+ }
204
+ })
205
+ }), /*#__PURE__*/jsx(Controller, {
206
+ name: "".concat(field, ".label"),
207
+ children: /*#__PURE__*/jsx(Input, {
208
+ inline: true,
209
+ label: "Label",
210
+ allowClear: true,
211
+ placeholder: "Label...",
212
+ decorateEndShowWhenEmpty: true,
213
+ decorateEnd: /*#__PURE__*/jsx("span", {
214
+ className: "text-sm text-tint-300 px-1",
215
+ children: "OPTIONAL"
216
+ })
217
+ })
218
+ }), type === DATA_TYPES.STRING && /*#__PURE__*/jsxs(Fragment, {
219
+ children: [/*#__PURE__*/jsx(Controller, {
220
+ name: "".concat(field, ".regex"),
221
+ children: /*#__PURE__*/jsx(Input, {
222
+ inline: true,
223
+ label: "Regex validation",
224
+ allowClear: true,
225
+ placeholder: "Regex value...",
226
+ decorateEndShowWhenEmpty: true,
227
+ decorateEnd: /*#__PURE__*/jsx("span", {
228
+ className: "text-sm text-tint-300 px-1",
229
+ children: "OPTIONAL"
230
+ })
231
+ })
232
+ }), /*#__PURE__*/jsxs(Field, {
233
+ inline: true,
234
+ label: "Option list",
235
+ children: [/*#__PURE__*/jsx(Controller, {
236
+ name: "".concat(field, ".optionList"),
237
+ children: /*#__PURE__*/jsx(Select, {
238
+ allowClear: true,
239
+ options: [SCHEMA_CUSTOM_LIST].concat(_toConsumableArray(optionLists)),
240
+ onChange: function onChange(v) {
241
+ return setCustomOptions(v === SCHEMA_CUSTOM_LIST);
242
+ }
243
+ })
244
+ }), customOptions && /*#__PURE__*/jsx(Button, {
245
+ icon: CoreIcons.list,
246
+ "aria-label": "Custom options",
247
+ onClick: function onClick() {
248
+ void openOptionModal({
249
+ title: "".concat(id, " Options")
250
+ });
251
+ }
252
+ })]
253
+ }), OptionModal]
254
+ }), type === DATA_TYPES.FILE && /*#__PURE__*/jsx(Fragment, {
255
+ children: /*#__PURE__*/jsx(Controller, {
256
+ name: "".concat(field, ".accept"),
257
+ children: /*#__PURE__*/jsx(Input, {
258
+ inline: true,
259
+ label: "Accept types",
260
+ allowClear: true,
261
+ placeholder: "Accept value...",
262
+ decorateEndShowWhenEmpty: true,
263
+ decorateEnd: /*#__PURE__*/jsx("span", {
264
+ className: "text-sm text-tint-300 px-1",
265
+ children: "OPTIONAL"
266
+ })
267
+ })
268
+ })
269
+ }), [DATA_TYPES.NUMBER, DATA_TYPES.RANGE].includes(type) && /*#__PURE__*/jsxs(Fragment, {
270
+ children: [/*#__PURE__*/jsx(Controller, {
271
+ name: "".concat(field, ".min"),
272
+ children: /*#__PURE__*/jsx(Number, {
273
+ inline: true,
274
+ label: "Min value",
275
+ allowClear: true,
276
+ placeholder: "Minimum value...",
277
+ decorateEndShowWhenEmpty: true,
278
+ decorateEnd: /*#__PURE__*/jsx("span", {
279
+ className: "text-sm text-tint-300 px-1",
280
+ children: "OPTIONAL"
281
+ })
282
+ })
283
+ }), /*#__PURE__*/jsx(Controller, {
284
+ name: "".concat(field, ".max"),
285
+ children: /*#__PURE__*/jsx(Number, {
286
+ inline: true,
287
+ label: "Max value",
288
+ allowClear: true,
289
+ placeholder: "Maximum value...",
290
+ decorateEndShowWhenEmpty: true,
291
+ decorateEnd: /*#__PURE__*/jsx("span", {
292
+ className: "text-sm text-tint-300 px-1",
293
+ children: "OPTIONAL"
294
+ })
295
+ })
296
+ }), /*#__PURE__*/jsx(Controller, {
297
+ name: "".concat(field, ".step"),
298
+ children: /*#__PURE__*/jsx(Number, {
299
+ inline: true,
300
+ label: "Step value",
301
+ allowClear: true,
302
+ placeholder: "Step value...",
303
+ decorateEndShowWhenEmpty: true,
304
+ decorateEnd: /*#__PURE__*/jsx("span", {
305
+ className: "text-sm text-tint-300 px-1",
306
+ children: "OPTIONAL"
307
+ })
308
+ })
309
+ })]
310
+ }), type === DATA_TYPES.DATE && /*#__PURE__*/jsxs(Fragment, {
311
+ children: [/*#__PURE__*/jsx(Field, {
312
+ inline: true,
313
+ label: "Type",
314
+ plain: true,
315
+ children: /*#__PURE__*/jsx(Controller, {
316
+ name: "".concat(field, ".type"),
317
+ children: /*#__PURE__*/jsxs(ToggleButtonGroup, {
318
+ value: "",
319
+ fullWidth: true,
320
+ className: "flex-1",
321
+ children: [/*#__PURE__*/jsx(Button, {
322
+ className: "flex-1",
323
+ value: "date",
324
+ children: "Date"
325
+ }), /*#__PURE__*/jsx(Button, {
326
+ className: "flex-1",
327
+ value: "datetime",
328
+ children: "Date Time"
329
+ })]
330
+ })
331
+ })
332
+ }), /*#__PURE__*/jsx(Controller, {
333
+ name: "".concat(field, ".min"),
334
+ children: /*#__PURE__*/jsx(DateInput, {
335
+ inline: true,
336
+ label: "Min value",
337
+ allowClear: true,
338
+ placeholder: "Minimum value...",
339
+ decorateEndShowWhenEmpty: true,
340
+ decorateEnd: /*#__PURE__*/jsx("span", {
341
+ className: "text-sm text-tint-300 px-1",
342
+ children: "OPTIONAL"
343
+ })
344
+ })
345
+ }), /*#__PURE__*/jsx(Controller, {
346
+ name: "".concat(field, ".max"),
347
+ children: /*#__PURE__*/jsx(DateInput, {
348
+ inline: true,
349
+ label: "Max value",
350
+ allowClear: true,
351
+ placeholder: "Maximum value...",
352
+ decorateEndShowWhenEmpty: true,
353
+ decorateEnd: /*#__PURE__*/jsx("span", {
354
+ className: "text-sm text-tint-300 px-1",
355
+ children: "OPTIONAL"
356
+ })
357
+ })
358
+ })]
359
+ }), /*#__PURE__*/jsxs(Field, {
360
+ label: " ",
361
+ inline: true,
362
+ plain: true,
363
+ children: [/*#__PURE__*/jsx(Controller, {
364
+ name: "".concat(field, ".required"),
365
+ children: /*#__PURE__*/jsx(Checkbox, {
366
+ label: "Required"
367
+ })
368
+ }), type !== DATA_TYPES.AVATAR && /*#__PURE__*/jsx(Controller, {
369
+ name: "".concat(field, ".multiple"),
370
+ children: /*#__PURE__*/jsx(Checkbox, {
371
+ label: "Multiple",
372
+ onChange: setMultiple
373
+ })
374
+ }), hasOptions && /*#__PURE__*/jsx(Controller, {
375
+ name: "".concat(field, ".allowCustom"),
376
+ children: /*#__PURE__*/jsx(Checkbox, {
377
+ label: "Allow custom value"
378
+ })
379
+ })]
380
+ }), multiple && /*#__PURE__*/jsxs(Fragment, {
381
+ children: [/*#__PURE__*/jsx(Controller, {
382
+ name: "".concat(field, ".minItems"),
383
+ children: /*#__PURE__*/jsx(Number, {
384
+ inline: true,
385
+ label: "Min items",
386
+ allowClear: true,
387
+ placeholder: "Minimum items...",
388
+ decorateEndShowWhenEmpty: true,
389
+ decorateEnd: /*#__PURE__*/jsx("span", {
390
+ className: "text-sm text-tint-300 px-1",
391
+ children: "OPTIONAL"
392
+ })
393
+ })
394
+ }), /*#__PURE__*/jsx(Controller, {
395
+ name: "".concat(field, ".maxItems"),
396
+ children: /*#__PURE__*/jsx(Number, {
397
+ inline: true,
398
+ label: "Max items",
399
+ allowClear: true,
400
+ placeholder: "Maximum items...",
401
+ decorateEndShowWhenEmpty: true,
402
+ decorateEnd: /*#__PURE__*/jsx("span", {
403
+ className: "text-sm text-tint-300 px-1",
404
+ children: "OPTIONAL"
405
+ })
406
+ })
407
+ })]
408
+ })]
409
+ })]
410
+ }, fieldId)
411
+ });
412
+ };
413
+
414
+ export { SchemaField };
@@ -46,7 +46,7 @@ var Controller = function Controller(_ref) {
46
46
  (_children$props$onCha = (_children$props = children.props).onChange) === null || _children$props$onCha === void 0 || _children$props$onCha.call(_children$props, v);
47
47
  }
48
48
  })) : children(_objectSpread(_objectSpread(_objectSpread({}, field), rest), {}, {
49
- inputRef: function inputRef(el) {
49
+ ref: function ref(el) {
50
50
  el && _ref3(el);
51
51
  },
52
52
  readOnly: isSubmitting,
@@ -7,6 +7,7 @@ import _objectWithoutProperties from '@babel/runtime/helpers/objectWithoutProper
7
7
  import _regeneratorRuntime from '@babel/runtime/regenerator';
8
8
  import { yupResolver } from '@hookform/resolvers/yup';
9
9
  import { useDebounce } from '@react-fabric/core';
10
+ import { EMPTY_OBJECT } from '@react-fabric/utilities';
10
11
  import { useRef, useTransition, useEffect, useCallback, useImperativeHandle } from 'react';
11
12
  import { useForm, FormProvider } from 'react-hook-form';
12
13
  import { jsx, jsxs } from 'react/jsx-runtime';
@@ -21,9 +22,10 @@ var Form = function Form(_ref) {
21
22
  var formRef = _ref.formRef,
22
23
  schema = _ref.schema,
23
24
  children = _ref.children,
24
- defaultValues = _ref.defaultValues,
25
+ _ref$defaultValues = _ref.defaultValues,
26
+ defaultValues = _ref$defaultValues === void 0 ? EMPTY_OBJECT : _ref$defaultValues,
25
27
  _ref$onSubmit = _ref.onSubmit,
26
- onSubmit = _ref$onSubmit === void 0 ? DEFAULT_SUBMIT : _ref$onSubmit,
28
+ _onSubmit = _ref$onSubmit === void 0 ? DEFAULT_SUBMIT : _ref$onSubmit,
27
29
  onChange = _ref.onChange,
28
30
  rest = _objectWithoutProperties(_ref, _excluded);
29
31
  var ref = useRef(null);
@@ -35,7 +37,7 @@ var Form = function Form(_ref) {
35
37
  var _useTransition = useTransition(),
36
38
  _useTransition2 = _slicedToArray(_useTransition, 2),
37
39
  startTransition = _useTransition2[1];
38
- var changeHandler = useDebounce(onChange, [onChange]);
40
+ var changeHandler = useDebounce(onChange, [onChange], 300);
39
41
  useEffect(function () {
40
42
  var subscription = form.watch(function (value) {
41
43
  startTransition(function () {
@@ -63,7 +65,7 @@ var Form = function Form(_ref) {
63
65
  return handleReset();
64
66
  },
65
67
  submit: function submit() {
66
- return form.handleSubmit(onSubmit);
68
+ return form.handleSubmit(_onSubmit);
67
69
  },
68
70
  validate: function () {
69
71
  var _validate = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
@@ -102,7 +104,7 @@ var Form = function Form(_ref) {
102
104
  }, 50);
103
105
  }
104
106
  };
105
- }, [onSubmit, form, form.formState, defaultValues]);
107
+ }, [_onSubmit, form, form.formState, defaultValues]);
106
108
  var onInvalid = useCallback(function (_, e) {
107
109
  var el = e.target;
108
110
  setTimeout(function () {
@@ -116,7 +118,10 @@ var Form = function Form(_ref) {
116
118
  onReset: function onReset() {
117
119
  return handleReset(defaultValues);
118
120
  },
119
- onSubmit: form.handleSubmit(onSubmit, onInvalid),
121
+ onSubmit: function onSubmit(e) {
122
+ e.stopPropagation();
123
+ void form.handleSubmit(_onSubmit, onInvalid)(e);
124
+ },
120
125
  "data-loading": form.formState.isSubmitting,
121
126
  className: "contents",
122
127
  autoComplete: "off"
@@ -1,33 +1,42 @@
1
1
  'use client';
2
2
 
3
3
  import _defineProperty from '@babel/runtime/helpers/defineProperty';
4
+ import { EmptyContent } from '@react-fabric/core';
4
5
  import { yup, isNil, isEmpty } from '@react-fabric/utilities';
5
6
  import { useMemo, Fragment } from 'react';
6
7
  import { FormField } from '../builder/FormField.js';
7
- import { jsx } from 'react/jsx-runtime';
8
+ import { DATA_TYPES } from '../types/schema.js';
9
+ import { jsxs, jsx } from 'react/jsx-runtime';
8
10
 
9
11
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
10
12
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
11
13
  var makeYupField = function makeYupField(field) {
12
- var yupField = yup.string();
13
- if (field.datatype === "schema") {
14
+ var yupField = yup.string().trim();
15
+ if (field.datatype === DATA_TYPES.SCHEMA) {
14
16
  var child = Object.fromEntries(field.schema.map(function (field) {
15
17
  return [field.id, makeYupField(field)];
16
18
  }));
17
19
  yupField = yup.object(child);
18
20
  }
19
- if (field.datatype === "boolean") yupField = yup["boolean"]();
20
- if (field.datatype === "decimal" || field.datatype === "number" || field.datatype === "range") {
21
+ if (field.datatype === DATA_TYPES.BOOL) {
22
+ yupField = yup["boolean"]();
23
+ if (field.required) yupField = yupField.test({
24
+ test: function test(value) {
25
+ return !!value;
26
+ }
27
+ });
28
+ }
29
+ if (field.datatype === DATA_TYPES.NUMBER || field.datatype === DATA_TYPES.RANGE) {
21
30
  yupField = yup.number();
22
31
  !isNil(field.min) && (yupField = yupField.min(field.min));
23
32
  !isNil(field.max) && (yupField = yupField.max(field.max));
24
- if (field.datatype === "range") yupField = yup.array(yupField);
33
+ if (field.datatype === DATA_TYPES.RANGE) yupField = yup.array(yupField);
25
34
  }
26
- if (field.datatype === "string") {
27
- field.options && (yupField = yupField.oneOf(field.options));
35
+ if (field.datatype === DATA_TYPES.STRING) {
36
+ field.options && !field.allowCustom && (yupField = yupField.oneOf(field.options));
28
37
  field.regex && (yupField = yupField.matches(new RegExp(field.regex)));
29
38
  }
30
- if (field.datatype === "file") {
39
+ if (field.datatype === DATA_TYPES.FILE) {
31
40
  yupField = yup.object({
32
41
  filename: yup.string().required(),
33
42
  path: yup.string().required()
@@ -64,19 +73,22 @@ var useFormBuilder = function useFormBuilder(schema) {
64
73
  var schemaDef = yup.object(Object.fromEntries(filteredSchema.map(function (field) {
65
74
  return [field.id, makeYupField(field)];
66
75
  })));
67
- var formDef = /*#__PURE__*/jsx(Fragment, {
68
- children: filteredSchema.map(function (field, idx) {
76
+ var formDef = /*#__PURE__*/jsxs(Fragment, {
77
+ children: [filteredSchema.map(function (field, idx) {
69
78
  return /*#__PURE__*/jsx("div", {
70
79
  className: "mb-4",
71
- children: field.datatype === "schema" ? null : /*#__PURE__*/jsx(FormField, _objectSpread(_objectSpread({}, field), {}, {
80
+ children: field.datatype === DATA_TYPES.SCHEMA ? null : /*#__PURE__*/jsx(FormField, _objectSpread(_objectSpread({}, field), {}, {
72
81
  autoFocus: idx === 0,
73
82
  fileUrl: options.fileUrl,
83
+ optionLists: options.optionLists,
74
84
  uploadHandler: options.uploadHandler,
75
85
  inline: options.inline,
76
86
  prefix: options.prefix
77
87
  }))
78
88
  }, field.id);
79
- })
89
+ }), filteredSchema.length === 0 && /*#__PURE__*/jsx(EmptyContent, {
90
+ message: "No schema defined"
91
+ })]
80
92
  });
81
93
  return {
82
94
  formDef: formDef,
package/dist/esm/index.js CHANGED
@@ -3,12 +3,16 @@
3
3
  import './i18n/index.js';
4
4
  export { Controller } from './form/Controller.js';
5
5
  export { Form } from './form/Form.js';
6
+ export { SchemaEditor } from './builder/SchemaEditor.js';
6
7
  export { useFileUploader } from './hooks/useFileUploader.js';
7
8
  export { useFormBuilder } from './hooks/useFormBuilder.js';
9
+ export { DATA_TYPES, SCHEMA_CUSTOM_LIST } from './types/schema.js';
8
10
  export { ArrayInput } from './input/ArrayInput.js';
11
+ export { AvatarInput } from './input/AvatarInput.js';
9
12
  export { Checkbox } from './input/Checkbox.js';
10
13
  export { ColorInput } from './input/ColorInput.js';
11
14
  export { ColorPicker } from './input/ColorPicker.js';
15
+ export { DateInput } from './input/DateInput.js';
12
16
  export { Field } from './input/Field.js';
13
17
  export { FileInput } from './input/File.js';
14
18
  export { HiddenInput } from './input/Hidden.js';
@@ -17,7 +21,7 @@ export { Number } from './input/Number.js';
17
21
  export { Password } from './input/Password.js';
18
22
  export { Radio } from './input/Radio.js';
19
23
  export { RadioGroup } from './input/RadioGroup.js';
20
- export { Range } from './input/Range.js';
24
+ export { RangeSlider } from './input/RangeSlider.js';
21
25
  export { Search } from './input/Search.js';
22
26
  export { Slider } from './input/Slider.js';
23
27
  export { Switch } from './input/Switch.js';