react-luna-form 0.0.25 → 0.0.27
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/client/cjs/index.js +927 -447
- package/dist/client/esm/index.js +916 -436
- package/dist/server/cjs/index.js +462 -101
- package/dist/server/esm/index.js +463 -102
- package/dist/types/luna-core/src/handle/state-event.d.ts +1 -1
- package/dist/types/luna-core/src/index.d.ts +1 -0
- package/dist/types/luna-core/src/type.d.ts +17 -2
- package/dist/types/luna-core/src/util/constant.d.ts +4 -0
- package/dist/types/luna-core/src/util/extract.d.ts +2 -1
- package/dist/types/luna-core/src/util/is-input.d.ts +4 -3
- package/dist/types/luna-core/src/util/is-type.d.ts +1 -0
- package/dist/types/luna-core/src/util/list.d.ts +4 -0
- package/dist/types/luna-core/src/util/prepare.d.ts +2 -2
- package/dist/types/luna-core/src/util/string.d.ts +1 -0
- package/dist/types/luna-react/src/client/component/field/field-list.d.ts +2 -0
- package/dist/types/luna-react/src/client/component/{wrapper/with-error.d.ts → field/field-with-error.d.ts} +1 -1
- package/dist/types/luna-react/src/client/component/{wrapper/with-field-state.d.ts → field/field-with-state.d.ts} +1 -1
- package/dist/types/luna-react/src/client/component/guard/list-guard.d.ts +2 -0
- package/dist/types/luna-react/src/client/component/guard/visibility-guard.d.ts +6 -0
- package/dist/types/luna-react/src/client/component/slot/slot.d.ts +7 -0
- package/dist/types/luna-react/src/client/hook/use-field-list.d.ts +2 -0
- package/dist/types/luna-react/src/component/chevron-icon.d.ts +3 -0
- package/dist/types/luna-react/src/component/column.d.ts +2 -3
- package/dist/types/luna-react/src/component/field/field-base.d.ts +4 -2
- package/dist/types/luna-react/src/component/field/field-horizontal.d.ts +2 -8
- package/dist/types/luna-react/src/component/field/field-list-item.d.ts +8 -0
- package/dist/types/luna-react/src/component/field/field-list.d.ts +7 -0
- package/dist/types/luna-react/src/component/field/field-set-advanced.d.ts +5 -0
- package/dist/types/luna-react/src/component/field/field-set-base.d.ts +7 -0
- package/dist/types/luna-react/src/component/field/field-vertical.d.ts +2 -8
- package/dist/types/luna-react/src/component/list.d.ts +5 -0
- package/dist/types/luna-react/src/component/slot/list-slot.d.ts +2 -0
- package/dist/types/luna-react/src/component/slot/slot-base.d.ts +8 -6
- package/dist/types/luna-react/src/component/slot/slot-create.d.ts +4 -3
- package/dist/types/luna-react/src/component/slot/slot-list.d.ts +12 -0
- package/dist/types/luna-react/src/component/slot/slot.d.ts +1 -0
- package/package.json +5 -5
- package/dist/types/luna-react/src/component/input/input-attributes.d.ts +0 -3
- package/dist/types/luna-react/src/component/input/input-common.d.ts +0 -2
- package/dist/types/luna-react/src/component/input/input-option-select.d.ts +0 -5
- /package/dist/types/luna-react/src/client/component/{wrapper/index.d.ts → field/field.d.ts} +0 -0
package/dist/client/cjs/index.js
CHANGED
|
@@ -34,18 +34,34 @@ __export(index_exports, {
|
|
|
34
34
|
});
|
|
35
35
|
module.exports = __toCommonJS(index_exports);
|
|
36
36
|
|
|
37
|
-
// src/component/
|
|
37
|
+
// src/component/control.tsx
|
|
38
38
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
39
|
-
function
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
39
|
+
function Control(props) {
|
|
40
|
+
const content = typeof props.children === "function" ? props.children({ isPending: props.isPending }) : props.children;
|
|
41
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { "data-slot": "field-control", className: "w-full", children: content });
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// src/component/field/field-set-advanced.tsx
|
|
45
|
+
var import_react = require("react");
|
|
46
|
+
|
|
47
|
+
// src/component/chevron-icon.tsx
|
|
48
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
49
|
+
function ChevronIcon(props) {
|
|
50
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
51
|
+
"svg",
|
|
45
52
|
{
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
53
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
54
|
+
viewBox: "0 0 20 20",
|
|
55
|
+
fill: "currentColor",
|
|
56
|
+
className: `size-4 transition-transform duration-200 ${props.expanded ? "rotate-90" : ""}`,
|
|
57
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
58
|
+
"path",
|
|
59
|
+
{
|
|
60
|
+
fillRule: "evenodd",
|
|
61
|
+
d: "M8.22 5.22a.75.75 0 0 1 1.06 0l4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.75.75 0 0 1-1.06-1.06L11.94 10 8.22 6.28a.75.75 0 0 1 0-1.06Z",
|
|
62
|
+
clipRule: "evenodd"
|
|
63
|
+
}
|
|
64
|
+
)
|
|
49
65
|
}
|
|
50
66
|
);
|
|
51
67
|
}
|
|
@@ -57,10 +73,12 @@ var INPUT_NUMBER = "input/number";
|
|
|
57
73
|
var TEXTAREA = "textarea";
|
|
58
74
|
var RADIO = "radio";
|
|
59
75
|
var CHECKBOX = "checkbox";
|
|
76
|
+
var LIST = "list";
|
|
60
77
|
var SELECT = "select";
|
|
61
78
|
var SELECT_MONTH = "select/month";
|
|
62
79
|
var SELECT_YEAR = "select/year";
|
|
63
80
|
var COLUMN = "column";
|
|
81
|
+
var FIELDS = "fields";
|
|
64
82
|
var LABEL = "label";
|
|
65
83
|
var VALUE = "value";
|
|
66
84
|
var OPTIONS = "options";
|
|
@@ -85,6 +103,7 @@ var STATE = "state";
|
|
|
85
103
|
var COMMON_URL = "http://luna.internal";
|
|
86
104
|
var VERTICAL = "vertical";
|
|
87
105
|
var HORIZONTAL = "horizontal";
|
|
106
|
+
var TYPE = "type";
|
|
88
107
|
|
|
89
108
|
// ../luna-core/src/util/is-type.ts
|
|
90
109
|
function isObject(value) {
|
|
@@ -94,7 +113,7 @@ function isEmpty(value) {
|
|
|
94
113
|
return value === null || value === void 0 || value === "";
|
|
95
114
|
}
|
|
96
115
|
function isValue(value) {
|
|
97
|
-
return
|
|
116
|
+
return isString(value) || typeof value === "number" || isBoolean(value);
|
|
98
117
|
}
|
|
99
118
|
function isString(value) {
|
|
100
119
|
return typeof value === "string";
|
|
@@ -102,9 +121,13 @@ function isString(value) {
|
|
|
102
121
|
function isDataSource(value) {
|
|
103
122
|
return isObject(value) && "url" in value;
|
|
104
123
|
}
|
|
124
|
+
function isBoolean(value) {
|
|
125
|
+
return typeof value === "boolean";
|
|
126
|
+
}
|
|
105
127
|
|
|
106
128
|
// ../luna-core/src/util/extract.ts
|
|
107
129
|
var REGEX_TYPE = /[^/]+$/;
|
|
130
|
+
var REGEX_NUMERIC = /^\d+$/;
|
|
108
131
|
function getEntity(selected, collection = [], entity = VALUE) {
|
|
109
132
|
if (Array.isArray(collection)) {
|
|
110
133
|
return collection.find((item) => {
|
|
@@ -114,6 +137,7 @@ function getEntity(selected, collection = [], entity = VALUE) {
|
|
|
114
137
|
}
|
|
115
138
|
}) ?? { value: selected };
|
|
116
139
|
}
|
|
140
|
+
return { value: selected };
|
|
117
141
|
}
|
|
118
142
|
function getCurrentValue(value, entity = VALUE) {
|
|
119
143
|
if (value !== null && value !== void 0) {
|
|
@@ -198,6 +222,46 @@ function getFormData(formData) {
|
|
|
198
222
|
}
|
|
199
223
|
return data;
|
|
200
224
|
}
|
|
225
|
+
function unflatten(data) {
|
|
226
|
+
const result = {};
|
|
227
|
+
for (const key in data) {
|
|
228
|
+
const parts = key.split(".");
|
|
229
|
+
if (parts.length === 1) {
|
|
230
|
+
result[key] = data[key];
|
|
231
|
+
continue;
|
|
232
|
+
}
|
|
233
|
+
let current = result;
|
|
234
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
235
|
+
const part = parts[i];
|
|
236
|
+
const next = parts[i + 1];
|
|
237
|
+
const isNextIndex = REGEX_NUMERIC.test(next);
|
|
238
|
+
if (!(part in current)) {
|
|
239
|
+
current[part] = isNextIndex ? [] : {};
|
|
240
|
+
}
|
|
241
|
+
current = current[part];
|
|
242
|
+
}
|
|
243
|
+
const last = parts[parts.length - 1];
|
|
244
|
+
current[last] = data[key];
|
|
245
|
+
}
|
|
246
|
+
compactArrays(result);
|
|
247
|
+
return result;
|
|
248
|
+
}
|
|
249
|
+
function compactArrays(obj) {
|
|
250
|
+
for (const key in obj) {
|
|
251
|
+
const value = obj[key];
|
|
252
|
+
if (Array.isArray(value)) {
|
|
253
|
+
const compacted = value.filter((item) => item !== void 0);
|
|
254
|
+
compacted.forEach((item) => {
|
|
255
|
+
if (item !== null && typeof item === "object" && !Array.isArray(item)) {
|
|
256
|
+
compactArrays(item);
|
|
257
|
+
}
|
|
258
|
+
});
|
|
259
|
+
obj[key] = compacted;
|
|
260
|
+
} else if (value !== null && typeof value === "object") {
|
|
261
|
+
compactArrays(value);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
201
265
|
|
|
202
266
|
// ../luna-core/src/util/string.ts
|
|
203
267
|
var REGEX_MARKDOWN_LINK = /\[([^\]]+)\]\(([^)]+)\)/g;
|
|
@@ -219,6 +283,9 @@ function interpolate(template, values = {}) {
|
|
|
219
283
|
}
|
|
220
284
|
return template;
|
|
221
285
|
}
|
|
286
|
+
function interpolateIfNeeded(template, values = {}) {
|
|
287
|
+
return isInterpolated(template) ? interpolate(template, values) : template;
|
|
288
|
+
}
|
|
222
289
|
function isInterpolated(template) {
|
|
223
290
|
if (isString(template)) {
|
|
224
291
|
return /{([^}]+)}/.test(template);
|
|
@@ -295,7 +362,7 @@ function handleProxyEvent(events = [], callback) {
|
|
|
295
362
|
const values = [];
|
|
296
363
|
const sources = [];
|
|
297
364
|
const states = [];
|
|
298
|
-
|
|
365
|
+
for (const event of events) {
|
|
299
366
|
if (event.action === VALUE) {
|
|
300
367
|
values.push(event);
|
|
301
368
|
}
|
|
@@ -305,17 +372,17 @@ function handleProxyEvent(events = [], callback) {
|
|
|
305
372
|
if (event.action === STATE) {
|
|
306
373
|
states.push(event);
|
|
307
374
|
}
|
|
308
|
-
}
|
|
375
|
+
}
|
|
309
376
|
callback({ sources, states, values });
|
|
310
377
|
}
|
|
311
378
|
|
|
312
379
|
// ../luna-core/src/handle/source-event.ts
|
|
313
380
|
function handleSourceEvent(selected = null, events = [], setSource) {
|
|
314
|
-
|
|
381
|
+
for (const event of events) {
|
|
315
382
|
const { target, source } = event;
|
|
316
383
|
if (!selected) {
|
|
317
384
|
setSource(target, void 0);
|
|
318
|
-
|
|
385
|
+
continue;
|
|
319
386
|
}
|
|
320
387
|
if (isDataSource(source)) {
|
|
321
388
|
const newUrl = interpolate(source.url, selected);
|
|
@@ -326,7 +393,7 @@ function handleSourceEvent(selected = null, events = [], setSource) {
|
|
|
326
393
|
body: newBody
|
|
327
394
|
});
|
|
328
395
|
}
|
|
329
|
-
}
|
|
396
|
+
}
|
|
330
397
|
}
|
|
331
398
|
|
|
332
399
|
// ../luna-core/src/util/operator.ts
|
|
@@ -399,31 +466,39 @@ function lte(current, value) {
|
|
|
399
466
|
|
|
400
467
|
// ../luna-core/src/handle/state-event.ts
|
|
401
468
|
function handleStateEvent(selected = null, events = [], setState) {
|
|
402
|
-
|
|
469
|
+
for (const event of events) {
|
|
403
470
|
const { target, state, when } = event;
|
|
471
|
+
const targets = Array.isArray(target) ? target : [target];
|
|
404
472
|
if (!selected) {
|
|
405
|
-
setState(
|
|
406
|
-
|
|
473
|
+
setState(targets);
|
|
474
|
+
continue;
|
|
407
475
|
}
|
|
476
|
+
logger.info(`Selected value for state event: ${JSON.stringify(selected)}, evaluating condition: ${JSON.stringify(when)}`);
|
|
408
477
|
const matches = evaluateCondition(selected, when);
|
|
409
|
-
|
|
410
|
-
|
|
478
|
+
logger.info(`Condition evaluated to: ${matches}, setting state for targets: ${targets.join(", ")}`);
|
|
479
|
+
setState(targets, matches ? state : void 0);
|
|
480
|
+
}
|
|
411
481
|
}
|
|
412
482
|
function evaluateCondition(selected, when) {
|
|
413
483
|
if (when === void 0) {
|
|
414
484
|
return true;
|
|
415
485
|
}
|
|
416
486
|
if (isString(when)) {
|
|
417
|
-
|
|
487
|
+
logger.info(`Evaluating string condition: ${when} against selected value: ${JSON.stringify(selected)} using VALUE field`);
|
|
488
|
+
logger.info(`Extracted value for comparison: ${JSON.stringify(getValue2(selected, VALUE))}`);
|
|
489
|
+
logger.info(`Comparison result: ${getValue2(selected, VALUE) === when}`);
|
|
490
|
+
return getValue2(selected, VALUE) === when;
|
|
491
|
+
}
|
|
492
|
+
if (isBoolean(when)) {
|
|
493
|
+
return Boolean(getValue2(selected, VALUE)) === when;
|
|
418
494
|
}
|
|
419
495
|
if (Array.isArray(when)) {
|
|
420
|
-
|
|
421
|
-
return when.includes(String(current));
|
|
496
|
+
return when.includes(String(getValue2(selected, VALUE)));
|
|
422
497
|
}
|
|
423
498
|
return evaluateOperator(selected, when);
|
|
424
499
|
}
|
|
425
500
|
function evaluateOperator(selected = null, condition) {
|
|
426
|
-
const current = getValue2(selected, condition.field ??
|
|
501
|
+
const current = getValue2(selected, condition.field ?? VALUE);
|
|
427
502
|
const { operator = "eq", value } = condition;
|
|
428
503
|
const operation = operators[operator];
|
|
429
504
|
if (operation) {
|
|
@@ -433,18 +508,18 @@ function evaluateOperator(selected = null, condition) {
|
|
|
433
508
|
}
|
|
434
509
|
function getValue2(selected, field) {
|
|
435
510
|
if (isObject(selected)) {
|
|
436
|
-
return
|
|
511
|
+
return extract(selected, field);
|
|
437
512
|
}
|
|
438
513
|
return selected;
|
|
439
514
|
}
|
|
440
515
|
|
|
441
516
|
// ../luna-core/src/handle/value-event.ts
|
|
442
517
|
function handleValueEvent(selected = null, events = [], setValue) {
|
|
443
|
-
|
|
444
|
-
Object.entries(event.value)
|
|
518
|
+
for (const event of events) {
|
|
519
|
+
for (const [target, value] of Object.entries(event.value)) {
|
|
445
520
|
setValue(target, selected ? interpolate(value, selected) : void 0);
|
|
446
|
-
}
|
|
447
|
-
}
|
|
521
|
+
}
|
|
522
|
+
}
|
|
448
523
|
}
|
|
449
524
|
|
|
450
525
|
// ../luna-core/src/util/is-input.ts
|
|
@@ -466,11 +541,14 @@ var isNumber = createTypeChecker(INPUT_NUMBER, TYPE_NUMBER);
|
|
|
466
541
|
function isClickable(field) {
|
|
467
542
|
return isRadio(field) || isCheckbox(field);
|
|
468
543
|
}
|
|
544
|
+
function isList(slot) {
|
|
545
|
+
return slot.type === LIST;
|
|
546
|
+
}
|
|
469
547
|
function isColumn(slot) {
|
|
470
548
|
return slot.type === COLUMN;
|
|
471
549
|
}
|
|
472
550
|
function isField(slot) {
|
|
473
|
-
return slot.type !== COLUMN;
|
|
551
|
+
return slot.type !== COLUMN && slot.type !== LIST;
|
|
474
552
|
}
|
|
475
553
|
function isOptions(field) {
|
|
476
554
|
return isSelect(field) || isRadio(field);
|
|
@@ -735,7 +813,7 @@ function prepareInputValue(field, value) {
|
|
|
735
813
|
var REGEX_REF = /^#\/definition\//;
|
|
736
814
|
function prepare(base = [], definition) {
|
|
737
815
|
const resolved = resolveRefs(base, definition);
|
|
738
|
-
return Array.isArray(resolved) ? resolved.sort((a, b) => getOrder(a) - getOrder(b)) : [];
|
|
816
|
+
return Array.isArray(resolved) ? resolved.filter(filter).sort((a, b) => getOrder(a) - getOrder(b)) : [];
|
|
739
817
|
}
|
|
740
818
|
function resolveRefs(base, definition, cache = /* @__PURE__ */ new Map(), visited = /* @__PURE__ */ new WeakSet()) {
|
|
741
819
|
if (!isDefinition(definition) || !base || typeof base !== "object") {
|
|
@@ -776,6 +854,15 @@ function getOrder(item) {
|
|
|
776
854
|
function isDefinition(definition) {
|
|
777
855
|
return definition !== void 0 && isObject(definition) && Object.keys(definition).length > 0;
|
|
778
856
|
}
|
|
857
|
+
function filter(base) {
|
|
858
|
+
if (TYPE in base) {
|
|
859
|
+
return true;
|
|
860
|
+
}
|
|
861
|
+
if (Array.isArray(base[FIELDS])) {
|
|
862
|
+
return base[FIELDS].length > 0;
|
|
863
|
+
}
|
|
864
|
+
return true;
|
|
865
|
+
}
|
|
779
866
|
|
|
780
867
|
// ../luna-core/src/util/attributes.ts
|
|
781
868
|
function getPrefixedAttributes(prefix, record) {
|
|
@@ -823,6 +910,31 @@ function getSpan(value) {
|
|
|
823
910
|
}
|
|
824
911
|
}
|
|
825
912
|
|
|
913
|
+
// ../luna-core/src/util/list.ts
|
|
914
|
+
function getInitialCount(list, value) {
|
|
915
|
+
const min2 = list.advanced?.length?.min ?? 1;
|
|
916
|
+
if (value) {
|
|
917
|
+
const data = extract(value, list.name);
|
|
918
|
+
if (Array.isArray(data)) {
|
|
919
|
+
return Math.max(data.length, min2);
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
return Math.max(min2, 0);
|
|
923
|
+
}
|
|
924
|
+
function isMultiFieldList(list) {
|
|
925
|
+
if (!Array.isArray(list.fields) || list.fields.length === 0) {
|
|
926
|
+
return false;
|
|
927
|
+
}
|
|
928
|
+
return list.fields.length > 1 || list.fields[0].type === COLUMN;
|
|
929
|
+
}
|
|
930
|
+
function getInitialList(list, value) {
|
|
931
|
+
const count = getInitialCount(list, value);
|
|
932
|
+
return Array.from({ length: count }, (_, index) => index);
|
|
933
|
+
}
|
|
934
|
+
function getLabel(list) {
|
|
935
|
+
return list.label ?? list.name;
|
|
936
|
+
}
|
|
937
|
+
|
|
826
938
|
// ../luna-core/src/util/schema.ts
|
|
827
939
|
var import_zod = require("zod");
|
|
828
940
|
|
|
@@ -1115,161 +1227,140 @@ function mergeStyle(globalStyle, localStyle) {
|
|
|
1115
1227
|
return { ...globalStyle, ...localStyle };
|
|
1116
1228
|
}
|
|
1117
1229
|
|
|
1118
|
-
// src/
|
|
1119
|
-
var
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
"data-[clickable=true]:has-[>[data-slot=field-content]]:[&>:first-child]:mt-px",
|
|
1136
|
-
props.className
|
|
1137
|
-
),
|
|
1138
|
-
children: props.children
|
|
1230
|
+
// src/lib/string.tsx
|
|
1231
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
1232
|
+
function formatMarkdown2(text) {
|
|
1233
|
+
return formatMarkdown(
|
|
1234
|
+
text,
|
|
1235
|
+
(index, url, text2) => {
|
|
1236
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1237
|
+
"a",
|
|
1238
|
+
{
|
|
1239
|
+
className: "underline",
|
|
1240
|
+
href: url,
|
|
1241
|
+
rel: "noopener noreferrer",
|
|
1242
|
+
target: "_blank",
|
|
1243
|
+
children: text2
|
|
1244
|
+
},
|
|
1245
|
+
`${url}-${index}`
|
|
1246
|
+
);
|
|
1139
1247
|
}
|
|
1140
1248
|
);
|
|
1141
1249
|
}
|
|
1142
1250
|
|
|
1143
|
-
// src/component/field/field-
|
|
1144
|
-
var
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1251
|
+
// src/component/field/field-set-advanced.tsx
|
|
1252
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
1253
|
+
function FieldSetAdvanced(props) {
|
|
1254
|
+
const { fields = [] } = props.section;
|
|
1255
|
+
const [isOpen, setIsOpen] = (0, import_react.useState)(false);
|
|
1256
|
+
const handleOpen = (0, import_react.useCallback)(() => setIsOpen((previous) => !previous), []);
|
|
1257
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
1258
|
+
"fieldset",
|
|
1149
1259
|
{
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
),
|
|
1156
|
-
children:
|
|
1260
|
+
"data-slot": "field-set",
|
|
1261
|
+
"data-advanced": "true",
|
|
1262
|
+
"data-expanded": isOpen,
|
|
1263
|
+
"data-empty": fields.length === 0,
|
|
1264
|
+
className: "flex flex-col",
|
|
1265
|
+
id: props.section.id?.toString(),
|
|
1266
|
+
children: [
|
|
1267
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("legend", { children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
1268
|
+
"button",
|
|
1269
|
+
{
|
|
1270
|
+
className: "flex cursor-pointer items-center gap-2 text-base font-medium text-slate-600 dark:text-slate-400",
|
|
1271
|
+
onClick: handleOpen,
|
|
1272
|
+
type: "button",
|
|
1273
|
+
children: [
|
|
1274
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ChevronIcon, { expanded: isOpen }),
|
|
1275
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: formatMarkdown2(props.section.title) })
|
|
1276
|
+
]
|
|
1277
|
+
}
|
|
1278
|
+
) }),
|
|
1279
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react.Activity, { mode: isOpen ? "visible" : "hidden", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
1280
|
+
"div",
|
|
1281
|
+
{
|
|
1282
|
+
className: "mt-3 ml-1.5 flex flex-col gap-4 border-l-2 border-slate-300 pl-4 dark:border-slate-600",
|
|
1283
|
+
"data-slot": "field-set-content",
|
|
1284
|
+
children: [
|
|
1285
|
+
props.section.description && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "text-sm leading-normal font-normal text-slate-600 dark:text-slate-400", children: formatMarkdown2(props.section.description) }),
|
|
1286
|
+
props.group
|
|
1287
|
+
]
|
|
1288
|
+
}
|
|
1289
|
+
) })
|
|
1290
|
+
]
|
|
1157
1291
|
}
|
|
1158
1292
|
);
|
|
1159
1293
|
}
|
|
1160
1294
|
|
|
1161
|
-
// src/component/
|
|
1162
|
-
var
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1295
|
+
// src/component/legend.tsx
|
|
1296
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
1297
|
+
function Legend(props) {
|
|
1298
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
|
|
1299
|
+
props.title && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("legend", { className: "mb-3 font-medium text-slate-800 dark:text-slate-200", children: formatMarkdown2(props.title) }),
|
|
1300
|
+
props.description && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "-mt-2 text-sm leading-normal font-normal text-slate-600 dark:text-slate-400", children: formatMarkdown2(props.description) })
|
|
1301
|
+
] });
|
|
1302
|
+
}
|
|
1303
|
+
|
|
1304
|
+
// src/component/field/field-set-base.tsx
|
|
1305
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
1306
|
+
function FieldSetBase(props) {
|
|
1307
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
1308
|
+
"fieldset",
|
|
1167
1309
|
{
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
className:
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
props.
|
|
1175
|
-
|
|
1176
|
-
"md:justify-between",
|
|
1177
|
-
"[&>*:not([data-slot=field-content])]:w-full",
|
|
1178
|
-
"[&>*:not([data-slot=field-content])]:md:w-1/2",
|
|
1179
|
-
"[&>*:not([data-slot=field-content])]:xl:w-2/5"
|
|
1180
|
-
]
|
|
1181
|
-
),
|
|
1182
|
-
children: props.children
|
|
1310
|
+
"data-slot": "field-set",
|
|
1311
|
+
"data-empty": props.empty,
|
|
1312
|
+
className: "flex flex-col data-[empty=false]:gap-6",
|
|
1313
|
+
id: props.id,
|
|
1314
|
+
children: [
|
|
1315
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Legend, { description: props.description, title: props.title }),
|
|
1316
|
+
props.children
|
|
1317
|
+
]
|
|
1183
1318
|
}
|
|
1184
1319
|
);
|
|
1185
1320
|
}
|
|
1186
1321
|
|
|
1187
|
-
// src/component/
|
|
1188
|
-
var
|
|
1189
|
-
function
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
const reversed = buildReverse(props.field);
|
|
1193
|
-
if (props.orientation === VERTICAL) {
|
|
1194
|
-
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1195
|
-
FieldVertical,
|
|
1196
|
-
{
|
|
1197
|
-
disabled: props.disabled,
|
|
1198
|
-
errors: props.errors,
|
|
1199
|
-
isCheckbox: checkbox,
|
|
1200
|
-
isReversed: reversed,
|
|
1201
|
-
isClickable: clickable,
|
|
1202
|
-
children: props.children
|
|
1203
|
-
}
|
|
1204
|
-
);
|
|
1205
|
-
}
|
|
1206
|
-
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1207
|
-
FieldHorizontal,
|
|
1322
|
+
// src/component/group.tsx
|
|
1323
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
1324
|
+
function Group(props) {
|
|
1325
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1326
|
+
"div",
|
|
1208
1327
|
{
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
isReversed: reversed,
|
|
1213
|
-
isClickable: clickable,
|
|
1328
|
+
"data-slot": "field-group",
|
|
1329
|
+
"data-compact": props.compact,
|
|
1330
|
+
className: "flex w-full flex-col gap-8 data-[compact=true]:gap-3",
|
|
1214
1331
|
children: props.children
|
|
1215
1332
|
}
|
|
1216
1333
|
);
|
|
1217
1334
|
}
|
|
1218
1335
|
|
|
1219
|
-
// src/component/
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
}
|
|
1224
|
-
|
|
1225
|
-
const dataAttributes = buildDataAttributes(props.field);
|
|
1226
|
-
const ariaAttributes = buildAriaAttributes(props.field, props.errors);
|
|
1227
|
-
const field = {
|
|
1228
|
-
...props.field,
|
|
1229
|
-
disabled: commonProps.disabled
|
|
1230
|
-
};
|
|
1231
|
-
return props.children({
|
|
1232
|
-
ariaAttributes,
|
|
1233
|
-
commonProps,
|
|
1234
|
-
dataAttributes,
|
|
1235
|
-
field,
|
|
1236
|
-
orientation: props.orientation
|
|
1336
|
+
// src/component/field/field-set.tsx
|
|
1337
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
1338
|
+
function FieldSet(props) {
|
|
1339
|
+
const { fields = [] } = props.section;
|
|
1340
|
+
const { compact } = mergeStyle(props.style, {
|
|
1341
|
+
compact: props.section.compact
|
|
1237
1342
|
});
|
|
1343
|
+
const group = /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Group, { compact, children: props.children });
|
|
1344
|
+
if (!props.section.title && !props.section.description) {
|
|
1345
|
+
return group;
|
|
1346
|
+
}
|
|
1347
|
+
if (props.section.advanced) {
|
|
1348
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(FieldSetAdvanced, { section: props.section, group });
|
|
1349
|
+
}
|
|
1350
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1351
|
+
FieldSetBase,
|
|
1352
|
+
{
|
|
1353
|
+
description: props.section.description,
|
|
1354
|
+
empty: fields.length === 0,
|
|
1355
|
+
id: props.section.id?.toString(),
|
|
1356
|
+
title: props.section.title,
|
|
1357
|
+
children: group
|
|
1358
|
+
}
|
|
1359
|
+
);
|
|
1238
1360
|
}
|
|
1239
1361
|
|
|
1240
|
-
// src/component/
|
|
1241
|
-
var
|
|
1242
|
-
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
1243
|
-
function Field(props) {
|
|
1244
|
-
const cols2 = props.field.advanced?.cols;
|
|
1245
|
-
const errors = props.field.name ? props.errors?.[props.field.name] : void 0;
|
|
1246
|
-
const { orientation } = mergeStyle(props.style, {
|
|
1247
|
-
orientation: buildOrientation(props.field)
|
|
1248
|
-
});
|
|
1249
|
-
const disabled = buildDisabled(props.field, props.disabled);
|
|
1250
|
-
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: (0, import_tailwind_merge4.twMerge)("flex flex-col gap-3", getSpan(cols2)), children: [
|
|
1251
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1252
|
-
FieldGroup,
|
|
1253
|
-
{
|
|
1254
|
-
disabled,
|
|
1255
|
-
errors,
|
|
1256
|
-
field: props.field,
|
|
1257
|
-
orientation,
|
|
1258
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1259
|
-
InputBase,
|
|
1260
|
-
{
|
|
1261
|
-
disabled,
|
|
1262
|
-
errors,
|
|
1263
|
-
field: props.field,
|
|
1264
|
-
orientation,
|
|
1265
|
-
children: props.children
|
|
1266
|
-
}
|
|
1267
|
-
)
|
|
1268
|
-
}
|
|
1269
|
-
),
|
|
1270
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(FieldError, { errors, name: props.field.name })
|
|
1271
|
-
] });
|
|
1272
|
-
}
|
|
1362
|
+
// src/client/component/guard/visibility-guard.tsx
|
|
1363
|
+
var import_jotai2 = require("jotai");
|
|
1273
1364
|
|
|
1274
1365
|
// src/client/lib/store-helper.ts
|
|
1275
1366
|
var import_jotai = require("jotai");
|
|
@@ -1415,188 +1506,89 @@ function createAtomStore(initialValue = {}) {
|
|
|
1415
1506
|
};
|
|
1416
1507
|
}
|
|
1417
1508
|
|
|
1418
|
-
// src/client/lib/
|
|
1509
|
+
// src/client/lib/state-store.ts
|
|
1419
1510
|
var store = createAtomStore();
|
|
1420
|
-
var
|
|
1421
|
-
var
|
|
1422
|
-
var reportInputErrorAtom = store.report;
|
|
1511
|
+
var fieldStateAtom = store.atom;
|
|
1512
|
+
var reportFieldStateAtom = store.report;
|
|
1423
1513
|
|
|
1424
|
-
// src/client/component/
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
function withErrors(Component) {
|
|
1428
|
-
const WithErrors = (props) => {
|
|
1429
|
-
const errors = (0, import_jotai2.useAtomValue)(reportInputErrorAtom(props.field.name));
|
|
1430
|
-
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1431
|
-
Component,
|
|
1432
|
-
{
|
|
1433
|
-
...props,
|
|
1434
|
-
errors: errors ? { [props.field.name]: errors } : void 0
|
|
1435
|
-
}
|
|
1436
|
-
);
|
|
1437
|
-
};
|
|
1438
|
-
return WithErrors;
|
|
1514
|
+
// src/client/component/guard/visibility-guard.tsx
|
|
1515
|
+
function isColumnHidden(column, states) {
|
|
1516
|
+
return column.fields.every((field) => isFieldHidden(field, states));
|
|
1439
1517
|
}
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
var store2 = createAtomStore();
|
|
1443
|
-
var fieldStateAtom = store2.atom;
|
|
1444
|
-
var reportFieldStateAtom = store2.report;
|
|
1445
|
-
|
|
1446
|
-
// src/client/component/wrapper/with-field-state.tsx
|
|
1447
|
-
var import_jotai3 = require("jotai");
|
|
1448
|
-
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
1449
|
-
function withFieldState(Component) {
|
|
1450
|
-
const WithFieldState = (props) => {
|
|
1451
|
-
const fieldState = (0, import_jotai3.useAtomValue)(reportFieldStateAtom(props.field.name));
|
|
1452
|
-
const hidden = fieldState?.hidden ?? props.field.hidden ?? false;
|
|
1453
|
-
if (hidden) {
|
|
1454
|
-
return null;
|
|
1455
|
-
}
|
|
1456
|
-
const disabled = fieldState?.disabled ?? props.disabled;
|
|
1457
|
-
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Component, { ...props, disabled });
|
|
1458
|
-
};
|
|
1459
|
-
return WithFieldState;
|
|
1518
|
+
function isFieldHidden(field, states) {
|
|
1519
|
+
return states[field.name]?.hidden ?? field.hidden ?? false;
|
|
1460
1520
|
}
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
var Field2 = withFieldState(withErrors(Field));
|
|
1464
|
-
|
|
1465
|
-
// src/component/control.tsx
|
|
1466
|
-
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
1467
|
-
function Control(props) {
|
|
1468
|
-
const content = typeof props.children === "function" ? props.children({ isPending: props.isPending }) : props.children;
|
|
1469
|
-
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { "data-slot": "field-control", className: "w-full", children: content });
|
|
1470
|
-
}
|
|
1471
|
-
|
|
1472
|
-
// src/component/group.tsx
|
|
1473
|
-
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
1474
|
-
function Group(props) {
|
|
1475
|
-
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1476
|
-
"div",
|
|
1477
|
-
{
|
|
1478
|
-
"data-slot": "field-group",
|
|
1479
|
-
"data-compact": props.compact,
|
|
1480
|
-
className: "flex w-full flex-col gap-8 data-[compact=true]:gap-3",
|
|
1481
|
-
children: props.children
|
|
1482
|
-
}
|
|
1483
|
-
);
|
|
1521
|
+
function isEntryHidden(entry, states) {
|
|
1522
|
+
return isColumn(entry) ? isColumnHidden(entry, states) : isFieldHidden(entry, states);
|
|
1484
1523
|
}
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
(index, url, text2) => {
|
|
1492
|
-
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1493
|
-
"a",
|
|
1494
|
-
{
|
|
1495
|
-
className: "underline",
|
|
1496
|
-
href: url,
|
|
1497
|
-
rel: "noopener noreferrer",
|
|
1498
|
-
target: "_blank",
|
|
1499
|
-
children: text2
|
|
1500
|
-
},
|
|
1501
|
-
`${url}-${index}`
|
|
1502
|
-
);
|
|
1524
|
+
function VisibilityGuard(props) {
|
|
1525
|
+
const states = (0, import_jotai2.useAtomValue)(fieldStateAtom);
|
|
1526
|
+
if (props.container) {
|
|
1527
|
+
const hidden = states[props.container.name]?.hidden ?? props.container.hidden ?? false;
|
|
1528
|
+
if (hidden) {
|
|
1529
|
+
return null;
|
|
1503
1530
|
}
|
|
1504
|
-
);
|
|
1505
|
-
}
|
|
1506
|
-
|
|
1507
|
-
// src/component/legend.tsx
|
|
1508
|
-
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
1509
|
-
function Legend(props) {
|
|
1510
|
-
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
|
|
1511
|
-
props.title && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("legend", { className: "mb-3 font-medium text-slate-800 dark:text-slate-200", children: formatMarkdown2(props.title) }),
|
|
1512
|
-
props.description && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "-mt-2 text-sm leading-normal font-normal text-slate-600 dark:text-slate-400", children: formatMarkdown2(props.description) })
|
|
1513
|
-
] });
|
|
1514
|
-
}
|
|
1515
|
-
|
|
1516
|
-
// src/component/field/field-set.tsx
|
|
1517
|
-
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
1518
|
-
function FieldSet(props) {
|
|
1519
|
-
const fields = props.section.fields || [];
|
|
1520
|
-
const { compact } = mergeStyle(props.style, {
|
|
1521
|
-
compact: props.section.compact
|
|
1522
|
-
});
|
|
1523
|
-
if (!props.section.title && !props.section.description) {
|
|
1524
|
-
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Group, { compact, children: props.children });
|
|
1525
1531
|
}
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
1535
|
-
Legend,
|
|
1536
|
-
{
|
|
1537
|
-
description: props.section.description,
|
|
1538
|
-
title: props.section.title
|
|
1539
|
-
}
|
|
1540
|
-
),
|
|
1541
|
-
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Group, { compact, children: props.children })
|
|
1542
|
-
]
|
|
1543
|
-
}
|
|
1544
|
-
);
|
|
1532
|
+
if (props.fields.length === 0) {
|
|
1533
|
+
return null;
|
|
1534
|
+
}
|
|
1535
|
+
const allHidden = props.fields.every((entry) => isEntryHidden(entry, states));
|
|
1536
|
+
if (allHidden) {
|
|
1537
|
+
return null;
|
|
1538
|
+
}
|
|
1539
|
+
return props.children;
|
|
1545
1540
|
}
|
|
1546
1541
|
|
|
1547
|
-
// src/component/form.tsx
|
|
1548
|
-
var import_react = require("react");
|
|
1549
|
-
|
|
1550
1542
|
// src/component/separator.tsx
|
|
1551
|
-
var
|
|
1543
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
1552
1544
|
function Separator() {
|
|
1553
|
-
return /* @__PURE__ */ (0,
|
|
1545
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { "data-slot": "field-separator", className: "relative -my-2 h-5 text-sm", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "absolute inset-0 top-1/2 h-px w-full bg-slate-200 dark:bg-slate-800" }) });
|
|
1554
1546
|
}
|
|
1555
1547
|
|
|
1556
1548
|
// src/component/form.tsx
|
|
1557
|
-
var
|
|
1549
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
1558
1550
|
function Form(props) {
|
|
1559
1551
|
const sections = prepare(props.sections, props.definition);
|
|
1560
|
-
return /* @__PURE__ */ (0,
|
|
1561
|
-
sections.map((section, index) => /* @__PURE__ */ (0,
|
|
1562
|
-
/* @__PURE__ */ (0,
|
|
1552
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "h-full w-full", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("form", { noValidate: props.noValidate, action: props.action, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Group, { children: [
|
|
1553
|
+
sections.map((section, index) => /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(VisibilityGuard, { fields: section.fields ?? [], children: [
|
|
1554
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(FieldSet, { section, style: props.config.style, children: props.children({
|
|
1563
1555
|
disabled: props.readOnly,
|
|
1564
1556
|
fields: section.fields
|
|
1565
1557
|
}) }),
|
|
1566
|
-
section.separator && /* @__PURE__ */ (0,
|
|
1558
|
+
section.separator && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Separator, {})
|
|
1567
1559
|
] }, index)),
|
|
1568
|
-
props.control && /* @__PURE__ */ (0,
|
|
1560
|
+
props.control && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Control, { isPending: props.isPending, children: props.control })
|
|
1569
1561
|
] }) }) });
|
|
1570
1562
|
}
|
|
1571
1563
|
|
|
1572
1564
|
// src/component/description.tsx
|
|
1573
|
-
var
|
|
1565
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
1574
1566
|
function Description(props) {
|
|
1575
|
-
return /* @__PURE__ */ (0,
|
|
1567
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { className: "-mt-2 text-xs leading-normal font-normal text-slate-600 dark:text-slate-400", children: props.children });
|
|
1576
1568
|
}
|
|
1577
1569
|
|
|
1578
1570
|
// src/component/formatted-description.tsx
|
|
1579
|
-
var
|
|
1571
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
1580
1572
|
function FormattedDescription(props) {
|
|
1581
1573
|
const content = formatMarkdown2(props.text);
|
|
1582
1574
|
if (content) {
|
|
1583
|
-
return /* @__PURE__ */ (0,
|
|
1575
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Description, { children: content });
|
|
1584
1576
|
}
|
|
1585
1577
|
return null;
|
|
1586
1578
|
}
|
|
1587
1579
|
|
|
1588
1580
|
// src/component/label.tsx
|
|
1589
|
-
var
|
|
1590
|
-
var
|
|
1581
|
+
var import_tailwind_merge = require("tailwind-merge");
|
|
1582
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
1591
1583
|
function Label(props) {
|
|
1592
1584
|
const showOptionalLabel = props.style?.showOptionalLabel ?? true;
|
|
1593
1585
|
const normal = isRadio(props.field) || isCheckbox(props.field);
|
|
1594
|
-
return /* @__PURE__ */ (0,
|
|
1586
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
1595
1587
|
"label",
|
|
1596
1588
|
{
|
|
1597
1589
|
"data-slot": "field-label",
|
|
1598
1590
|
"data-normal": normal,
|
|
1599
|
-
className: (0,
|
|
1591
|
+
className: (0, import_tailwind_merge.twMerge)(
|
|
1600
1592
|
"flex w-fit items-center gap-2 text-sm leading-snug font-medium select-none",
|
|
1601
1593
|
"data-[normal=true]:font-normal",
|
|
1602
1594
|
"group-data-[readonly=true]:cursor-not-allowed group-data-[readonly=true]:opacity-50"
|
|
@@ -1604,30 +1596,31 @@ function Label(props) {
|
|
|
1604
1596
|
htmlFor: props.field.name,
|
|
1605
1597
|
children: [
|
|
1606
1598
|
props.children,
|
|
1607
|
-
showOptionalLabel && !props.field.required && /* @__PURE__ */ (0,
|
|
1599
|
+
showOptionalLabel && !props.field.required && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "text-sm text-slate-600 dark:text-slate-400", children: translate("(Optional)", props.translations) })
|
|
1608
1600
|
]
|
|
1609
1601
|
}
|
|
1610
1602
|
);
|
|
1611
1603
|
}
|
|
1612
1604
|
|
|
1613
1605
|
// src/component/input-label.tsx
|
|
1614
|
-
var
|
|
1606
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
1615
1607
|
function InputLabel(props) {
|
|
1616
|
-
const
|
|
1617
|
-
context: props.context,
|
|
1618
|
-
env: props.config?.env
|
|
1619
|
-
}) : props.field.label;
|
|
1620
|
-
const description = isInterpolated(props.field.description) ? interpolate(props.field.description, {
|
|
1608
|
+
const interpolateOpts = {
|
|
1621
1609
|
context: props.context,
|
|
1622
1610
|
env: props.config?.env
|
|
1623
|
-
}
|
|
1624
|
-
|
|
1611
|
+
};
|
|
1612
|
+
const label = interpolateIfNeeded(props.field.label, interpolateOpts);
|
|
1613
|
+
const description = interpolateIfNeeded(
|
|
1614
|
+
props.field.description,
|
|
1615
|
+
interpolateOpts
|
|
1616
|
+
);
|
|
1617
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
|
|
1625
1618
|
"div",
|
|
1626
1619
|
{
|
|
1627
1620
|
"data-slot": "field-content",
|
|
1628
1621
|
className: "flex w-full flex-1 flex-col gap-1.5 leading-snug",
|
|
1629
1622
|
children: [
|
|
1630
|
-
/* @__PURE__ */ (0,
|
|
1623
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1631
1624
|
Label,
|
|
1632
1625
|
{
|
|
1633
1626
|
field: props.field,
|
|
@@ -1636,7 +1629,7 @@ function InputLabel(props) {
|
|
|
1636
1629
|
children: translate(label, props.translations)
|
|
1637
1630
|
}
|
|
1638
1631
|
),
|
|
1639
|
-
props.orientation === HORIZONTAL && /* @__PURE__ */ (0,
|
|
1632
|
+
props.orientation === HORIZONTAL && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1640
1633
|
FormattedDescription,
|
|
1641
1634
|
{
|
|
1642
1635
|
text: translate(description, props.translations)
|
|
@@ -1648,10 +1641,10 @@ function InputLabel(props) {
|
|
|
1648
1641
|
}
|
|
1649
1642
|
|
|
1650
1643
|
// src/component/input-group.tsx
|
|
1651
|
-
var
|
|
1644
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
1652
1645
|
function InputGroup(props) {
|
|
1653
|
-
return /* @__PURE__ */ (0,
|
|
1654
|
-
props.field.name && props.field.label && /* @__PURE__ */ (0,
|
|
1646
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
|
|
1647
|
+
props.field.name && props.field.label && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
1655
1648
|
InputLabel,
|
|
1656
1649
|
{
|
|
1657
1650
|
config: props.config,
|
|
@@ -1662,7 +1655,7 @@ function InputGroup(props) {
|
|
|
1662
1655
|
}
|
|
1663
1656
|
),
|
|
1664
1657
|
props.children,
|
|
1665
|
-
props.orientation === VERTICAL && props.field.description && /* @__PURE__ */ (0,
|
|
1658
|
+
props.orientation === VERTICAL && props.field.description && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
1666
1659
|
FormattedDescription,
|
|
1667
1660
|
{
|
|
1668
1661
|
text: translate(props.field.description, props.translations)
|
|
@@ -1679,11 +1672,17 @@ function renderIfExists(value, render) {
|
|
|
1679
1672
|
return render(value);
|
|
1680
1673
|
}
|
|
1681
1674
|
|
|
1675
|
+
// src/client/lib/error-store.ts
|
|
1676
|
+
var store2 = createAtomStore();
|
|
1677
|
+
var clearInputErrorAtom = store2.clear;
|
|
1678
|
+
var reportErrorAtom = store2.bulkReport;
|
|
1679
|
+
var reportInputErrorAtom = store2.report;
|
|
1680
|
+
|
|
1682
1681
|
// src/client/component/input.tsx
|
|
1683
1682
|
var import_react5 = require("react");
|
|
1684
1683
|
|
|
1685
1684
|
// src/client/lib/source-store.ts
|
|
1686
|
-
var
|
|
1685
|
+
var import_jotai3 = require("jotai");
|
|
1687
1686
|
var merge = (values) => {
|
|
1688
1687
|
const merged = mergeSource(values);
|
|
1689
1688
|
if (merged) {
|
|
@@ -1692,7 +1691,7 @@ var merge = (values) => {
|
|
|
1692
1691
|
return void 0;
|
|
1693
1692
|
};
|
|
1694
1693
|
var validate = (target) => target.trim() !== "";
|
|
1695
|
-
var sourceAtom = (0,
|
|
1694
|
+
var sourceAtom = (0, import_jotai3.atom)({});
|
|
1696
1695
|
var reportSourceAtom = createNestedRecordAtomFamily(
|
|
1697
1696
|
sourceAtom,
|
|
1698
1697
|
{
|
|
@@ -1703,7 +1702,7 @@ var reportSourceAtom = createNestedRecordAtomFamily(
|
|
|
1703
1702
|
var clearInputSourceAtom = createNestedClearAtom(sourceAtom);
|
|
1704
1703
|
|
|
1705
1704
|
// src/client/hook/use-data-source.ts
|
|
1706
|
-
var
|
|
1705
|
+
var import_jotai4 = require("jotai");
|
|
1707
1706
|
|
|
1708
1707
|
// src/client/hook/use-fetch.ts
|
|
1709
1708
|
var import_swr = __toESM(require("swr"), 1);
|
|
@@ -1749,7 +1748,7 @@ function buildSource2(dataSource = null, config, disabled = false) {
|
|
|
1749
1748
|
// src/client/hook/use-data-source.ts
|
|
1750
1749
|
function useDataSource(field, config, value) {
|
|
1751
1750
|
const dataSource = resolveSource(field, value);
|
|
1752
|
-
const [source, setSource] = (0,
|
|
1751
|
+
const [source, setSource] = (0, import_jotai4.useAtom)(reportSourceAtom(field.name));
|
|
1753
1752
|
const currentSource = source ?? dataSource;
|
|
1754
1753
|
const data = useFetch(currentSource, config, field.disabled);
|
|
1755
1754
|
return [data, setSource];
|
|
@@ -1783,7 +1782,7 @@ function useInput(field, onMount, onUnmount, translations) {
|
|
|
1783
1782
|
}
|
|
1784
1783
|
|
|
1785
1784
|
// src/client/component/input.tsx
|
|
1786
|
-
var
|
|
1785
|
+
var import_jotai6 = require("jotai");
|
|
1787
1786
|
|
|
1788
1787
|
// src/client/hook/use-timeout.ts
|
|
1789
1788
|
var import_react3 = require("react");
|
|
@@ -1796,14 +1795,11 @@ function useTimeout() {
|
|
|
1796
1795
|
}
|
|
1797
1796
|
};
|
|
1798
1797
|
}, []);
|
|
1799
|
-
|
|
1798
|
+
const setTimeoutRef = (0, import_react3.useCallback)((callback, delay) => {
|
|
1800
1799
|
if (timeoutRef.current) {
|
|
1801
1800
|
clearTimeout(timeoutRef.current);
|
|
1802
1801
|
timeoutRef.current = null;
|
|
1803
1802
|
}
|
|
1804
|
-
}
|
|
1805
|
-
const setTimeoutRef = (0, import_react3.useCallback)((callback, delay) => {
|
|
1806
|
-
clearTimeoutRef();
|
|
1807
1803
|
timeoutRef.current = setTimeout(callback, delay);
|
|
1808
1804
|
}, []);
|
|
1809
1805
|
return setTimeoutRef;
|
|
@@ -1817,26 +1813,27 @@ var clearInputValueAtom = store3.clear;
|
|
|
1817
1813
|
var reportValueAtom = store3.report;
|
|
1818
1814
|
|
|
1819
1815
|
// src/client/hook/use-value.ts
|
|
1820
|
-
var
|
|
1816
|
+
var import_jotai5 = require("jotai");
|
|
1821
1817
|
var import_react4 = require("react");
|
|
1822
1818
|
function useValue(field, currentValue) {
|
|
1823
1819
|
const { name } = field;
|
|
1824
1820
|
const skipNextOnChangeRef = (0, import_react4.useRef)(false);
|
|
1825
|
-
const [value, setValue] = (0,
|
|
1821
|
+
const [value, setValue] = (0, import_jotai5.useAtom)(reportValueAtom(name));
|
|
1822
|
+
const onCurrentValueChange = (0, import_react4.useEffectEvent)(
|
|
1823
|
+
(currentValue2) => {
|
|
1824
|
+
const newValue = resolveValue(name, currentValue2);
|
|
1825
|
+
if (isValidValue(newValue)) {
|
|
1826
|
+
skipNextOnChangeRef.current = true;
|
|
1827
|
+
setValue(newValue);
|
|
1828
|
+
}
|
|
1829
|
+
}
|
|
1830
|
+
);
|
|
1826
1831
|
(0, import_react4.useEffect)(() => {
|
|
1827
|
-
if (!currentValue
|
|
1832
|
+
if (!currentValue) {
|
|
1828
1833
|
return;
|
|
1829
1834
|
}
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
logger.info("useValue: setting skipNextOnChange to true", {
|
|
1833
|
-
fieldName: name,
|
|
1834
|
-
newValue
|
|
1835
|
-
});
|
|
1836
|
-
skipNextOnChangeRef.current = true;
|
|
1837
|
-
setValue(newValue);
|
|
1838
|
-
}
|
|
1839
|
-
}, [name, currentValue, setValue]);
|
|
1835
|
+
onCurrentValueChange(currentValue);
|
|
1836
|
+
}, [currentValue]);
|
|
1840
1837
|
const shouldSkipOnChange = (0, import_react4.useCallback)(() => {
|
|
1841
1838
|
if (skipNextOnChangeRef.current) {
|
|
1842
1839
|
skipNextOnChangeRef.current = false;
|
|
@@ -1850,14 +1847,38 @@ function useValue(field, currentValue) {
|
|
|
1850
1847
|
value
|
|
1851
1848
|
};
|
|
1852
1849
|
}
|
|
1850
|
+
function resolveValue(name, currentValue) {
|
|
1851
|
+
if (name in currentValue) {
|
|
1852
|
+
return currentValue[name];
|
|
1853
|
+
}
|
|
1854
|
+
if (!name.includes(".")) {
|
|
1855
|
+
return void 0;
|
|
1856
|
+
}
|
|
1857
|
+
const keys = name.split(".");
|
|
1858
|
+
let result = currentValue;
|
|
1859
|
+
for (const key of keys) {
|
|
1860
|
+
if (result === null || result === void 0) {
|
|
1861
|
+
return void 0;
|
|
1862
|
+
}
|
|
1863
|
+
if (Array.isArray(result)) {
|
|
1864
|
+
const index = Number(key);
|
|
1865
|
+
result = Number.isInteger(index) ? result[index] : void 0;
|
|
1866
|
+
} else if (typeof result === "object") {
|
|
1867
|
+
result = result[key];
|
|
1868
|
+
} else {
|
|
1869
|
+
return void 0;
|
|
1870
|
+
}
|
|
1871
|
+
}
|
|
1872
|
+
return result;
|
|
1873
|
+
}
|
|
1853
1874
|
|
|
1854
1875
|
// src/client/component/input.tsx
|
|
1855
|
-
var
|
|
1876
|
+
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
1856
1877
|
function Input(props) {
|
|
1857
1878
|
const entity = props.field.advanced?.entity;
|
|
1858
|
-
const store4 = (0,
|
|
1879
|
+
const store4 = (0, import_jotai6.useStore)();
|
|
1859
1880
|
const setTimeoutRef = useTimeout();
|
|
1860
|
-
const [,
|
|
1881
|
+
const [, startTransition2] = (0, import_react5.useTransition)();
|
|
1861
1882
|
const { setValue, shouldSkipOnChange, value } = useValue(
|
|
1862
1883
|
props.field,
|
|
1863
1884
|
props.value
|
|
@@ -1868,9 +1889,9 @@ function Input(props) {
|
|
|
1868
1889
|
translationsRef.current = props.translations;
|
|
1869
1890
|
const hasTextable = isTextable(props.field);
|
|
1870
1891
|
const hasClickable = isClickable(props.field);
|
|
1871
|
-
const setValues = (0,
|
|
1872
|
-
const setFieldStates = (0,
|
|
1873
|
-
const setErrors = (0,
|
|
1892
|
+
const setValues = (0, import_jotai6.useSetAtom)(valueAtom);
|
|
1893
|
+
const setFieldStates = (0, import_jotai6.useSetAtom)(fieldStateAtom);
|
|
1894
|
+
const setErrors = (0, import_jotai6.useSetAtom)(reportInputErrorAtom(props.field.name));
|
|
1874
1895
|
const [data, setSource] = useDataSource(props.field, props.config, value);
|
|
1875
1896
|
const schema = useInput(
|
|
1876
1897
|
props.field,
|
|
@@ -1923,37 +1944,18 @@ function Input(props) {
|
|
|
1923
1944
|
}, 500);
|
|
1924
1945
|
return;
|
|
1925
1946
|
}
|
|
1926
|
-
|
|
1927
|
-
callback(currentValue);
|
|
1947
|
+
callback(getEntity(value2, data, entity));
|
|
1928
1948
|
},
|
|
1929
1949
|
[data, entity, hasTextable, setTimeoutRef]
|
|
1930
1950
|
);
|
|
1931
1951
|
const onChange = (0, import_react5.useCallback)(
|
|
1932
1952
|
(event) => {
|
|
1933
1953
|
const inputValue = event.target.value;
|
|
1934
|
-
logger.info("onChange fired", {
|
|
1935
|
-
fieldName: props.field.name,
|
|
1936
|
-
fieldType: props.field.type,
|
|
1937
|
-
inputValue,
|
|
1938
|
-
currentValue: valueRef.current,
|
|
1939
|
-
hasTextable,
|
|
1940
|
-
hasClickable
|
|
1941
|
-
});
|
|
1942
1954
|
if (!hasClickable && shouldSkipOnChange()) {
|
|
1943
|
-
logger.info("shouldSkipOnChange returned true", {
|
|
1944
|
-
fieldName: props.field.name,
|
|
1945
|
-
willSkip: !hasTextable || inputValue === valueRef.current,
|
|
1946
|
-
reason: !hasTextable ? "not textable (checkbox/radio/select)" : "value unchanged"
|
|
1947
|
-
});
|
|
1948
1955
|
if (!hasTextable || inputValue === valueRef.current) {
|
|
1949
|
-
logger.info("SKIPPING onChange", { fieldName: props.field.name });
|
|
1950
1956
|
return;
|
|
1951
1957
|
}
|
|
1952
1958
|
}
|
|
1953
|
-
logger.info("onChange processing", {
|
|
1954
|
-
fieldName: props.field.name,
|
|
1955
|
-
inputValue
|
|
1956
|
-
});
|
|
1957
1959
|
onValueChangeRef.current?.(inputValue);
|
|
1958
1960
|
if (props.config.validation.change) {
|
|
1959
1961
|
validated(inputValue);
|
|
@@ -1962,19 +1964,32 @@ function Input(props) {
|
|
|
1962
1964
|
if (events) {
|
|
1963
1965
|
handleTriggerEvent(inputValue, (selected) => {
|
|
1964
1966
|
handleProxyEvent(events, ({ sources, states, values }) => {
|
|
1965
|
-
|
|
1967
|
+
startTransition2(() => {
|
|
1966
1968
|
handleSourceEvent(
|
|
1967
1969
|
selected,
|
|
1968
1970
|
sources,
|
|
1969
1971
|
(target, source) => setSource(target, source)
|
|
1970
1972
|
);
|
|
1971
|
-
handleStateEvent(selected, states, (
|
|
1973
|
+
handleStateEvent(selected, states, (targets, state) => {
|
|
1974
|
+
logger.info(
|
|
1975
|
+
`Setting field states for targets: ${targets.join(
|
|
1976
|
+
", "
|
|
1977
|
+
)} with state: ${JSON.stringify(state)}`
|
|
1978
|
+
);
|
|
1972
1979
|
setFieldStates((prev) => {
|
|
1973
1980
|
if (state) {
|
|
1974
|
-
return
|
|
1981
|
+
return targets.reduce(
|
|
1982
|
+
(acc, target) => ({
|
|
1983
|
+
...acc,
|
|
1984
|
+
[target]: state
|
|
1985
|
+
}),
|
|
1986
|
+
prev
|
|
1987
|
+
);
|
|
1975
1988
|
}
|
|
1976
|
-
|
|
1977
|
-
|
|
1989
|
+
return targets.reduce((acc, target) => {
|
|
1990
|
+
const { [target]: _removed, ...rest } = acc;
|
|
1991
|
+
return rest;
|
|
1992
|
+
}, prev);
|
|
1978
1993
|
});
|
|
1979
1994
|
});
|
|
1980
1995
|
handleValueEvent(selected, values, (target, value2) => {
|
|
@@ -1994,8 +2009,6 @@ function Input(props) {
|
|
|
1994
2009
|
hasTextable,
|
|
1995
2010
|
props.config.validation.change,
|
|
1996
2011
|
props.field.event?.change,
|
|
1997
|
-
props.field.name,
|
|
1998
|
-
props.field.type,
|
|
1999
2012
|
setFieldStates,
|
|
2000
2013
|
setSource,
|
|
2001
2014
|
setValues,
|
|
@@ -2014,7 +2027,7 @@ function Input(props) {
|
|
|
2014
2027
|
},
|
|
2015
2028
|
[hasClickable, props.config.validation.blur, validated]
|
|
2016
2029
|
);
|
|
2017
|
-
return renderIfExists(props.config.inputs[props.field.type], (Component) => /* @__PURE__ */ (0,
|
|
2030
|
+
return renderIfExists(props.config.inputs[props.field.type], (Component) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
2018
2031
|
InputGroup,
|
|
2019
2032
|
{
|
|
2020
2033
|
config: props.config,
|
|
@@ -2022,7 +2035,7 @@ function Input(props) {
|
|
|
2022
2035
|
field: props.field,
|
|
2023
2036
|
orientation: props.orientation,
|
|
2024
2037
|
translations: props.translations,
|
|
2025
|
-
children: /* @__PURE__ */ (0,
|
|
2038
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
2026
2039
|
Component,
|
|
2027
2040
|
{
|
|
2028
2041
|
...commonPropsWithOptions,
|
|
@@ -2037,48 +2050,502 @@ function Input(props) {
|
|
|
2037
2050
|
));
|
|
2038
2051
|
}
|
|
2039
2052
|
|
|
2040
|
-
// src/component/
|
|
2041
|
-
var
|
|
2053
|
+
// src/component/field/field-error.tsx
|
|
2054
|
+
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
2055
|
+
function FieldError(props) {
|
|
2056
|
+
if (!props.errors || props.errors.length === 0) {
|
|
2057
|
+
return null;
|
|
2058
|
+
}
|
|
2059
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
2060
|
+
"ul",
|
|
2061
|
+
{
|
|
2062
|
+
className: "text-sm text-red-600 dark:text-red-500",
|
|
2063
|
+
id: props.name ? `${props.name}-error` : void 0,
|
|
2064
|
+
children: props.errors?.map((error, index) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("li", { children: error }, props.name ? `${props.name}-error-${index}` : index))
|
|
2065
|
+
}
|
|
2066
|
+
);
|
|
2067
|
+
}
|
|
2068
|
+
|
|
2069
|
+
// src/component/field/field-base.tsx
|
|
2070
|
+
var import_tailwind_merge2 = require("tailwind-merge");
|
|
2071
|
+
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
2072
|
+
function FieldBase(props) {
|
|
2073
|
+
const errors = props.errors && props.errors.length > 0;
|
|
2074
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
2075
|
+
"div",
|
|
2076
|
+
{
|
|
2077
|
+
"data-slot": "field",
|
|
2078
|
+
"data-clickable": props.isClickable ? "true" : "false",
|
|
2079
|
+
...errors && { [DATA_INVALID]: "true" },
|
|
2080
|
+
...props.disabled && { [DATA_READONLY]: "true" },
|
|
2081
|
+
"data-orientation": props.orientation,
|
|
2082
|
+
className: (0, import_tailwind_merge2.twMerge)(
|
|
2083
|
+
"group flex w-full flex-col items-center data-[invalid=true]:text-red-600 data-[invalid=true]:dark:text-red-500",
|
|
2084
|
+
"data-[clickable=true]:items-start",
|
|
2085
|
+
props.isCheckbox && (props.isReversed ? "flex-row-reverse!" : "flex-row!"),
|
|
2086
|
+
"data-[clickable=true]:has-[>[data-slot=field-content]]:[&>:first-child]:mt-px",
|
|
2087
|
+
props.className
|
|
2088
|
+
),
|
|
2089
|
+
children: props.children
|
|
2090
|
+
}
|
|
2091
|
+
);
|
|
2092
|
+
}
|
|
2093
|
+
|
|
2094
|
+
// src/component/field/field-vertical.tsx
|
|
2095
|
+
var import_tailwind_merge3 = require("tailwind-merge");
|
|
2096
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
2097
|
+
function FieldVertical(props) {
|
|
2098
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2099
|
+
FieldBase,
|
|
2100
|
+
{
|
|
2101
|
+
...props,
|
|
2102
|
+
orientation: VERTICAL,
|
|
2103
|
+
className: (0, import_tailwind_merge3.twMerge)(
|
|
2104
|
+
"gap-3 has-[>[data-slot=field-content]]:items-start",
|
|
2105
|
+
!props.isClickable && "[&>*]:w-full"
|
|
2106
|
+
),
|
|
2107
|
+
children: props.children
|
|
2108
|
+
}
|
|
2109
|
+
);
|
|
2110
|
+
}
|
|
2111
|
+
|
|
2112
|
+
// src/component/field/field-horizontal.tsx
|
|
2113
|
+
var import_tailwind_merge4 = require("tailwind-merge");
|
|
2114
|
+
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
2115
|
+
function FieldHorizontal(props) {
|
|
2116
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
2117
|
+
FieldBase,
|
|
2118
|
+
{
|
|
2119
|
+
...props,
|
|
2120
|
+
orientation: HORIZONTAL,
|
|
2121
|
+
className: (0, import_tailwind_merge4.twMerge)(
|
|
2122
|
+
"gap-2 md:flex-row md:gap-4",
|
|
2123
|
+
"[&>[data-slot=field-content]]:min-w-0 [&>[data-slot=field-content]]:flex-grow [&>[data-slot=field-content]]:self-start",
|
|
2124
|
+
"[&_[role=checkbox]]:mt-[1.5px]",
|
|
2125
|
+
props.isClickable && "md:flex-col",
|
|
2126
|
+
!props.isClickable && [
|
|
2127
|
+
"md:justify-between",
|
|
2128
|
+
"[&>*:not([data-slot=field-content])]:w-full",
|
|
2129
|
+
"[&>*:not([data-slot=field-content])]:md:w-1/2",
|
|
2130
|
+
"[&>*:not([data-slot=field-content])]:xl:w-2/5"
|
|
2131
|
+
]
|
|
2132
|
+
),
|
|
2133
|
+
children: props.children
|
|
2134
|
+
}
|
|
2135
|
+
);
|
|
2136
|
+
}
|
|
2137
|
+
|
|
2138
|
+
// src/component/field/field-group.tsx
|
|
2139
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
2140
|
+
function FieldGroup(props) {
|
|
2141
|
+
const clickable = isClickable(props.field);
|
|
2142
|
+
const checkbox = isCheckbox(props.field);
|
|
2143
|
+
const reversed = buildReverse(props.field);
|
|
2144
|
+
if (props.orientation === VERTICAL) {
|
|
2145
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2146
|
+
FieldVertical,
|
|
2147
|
+
{
|
|
2148
|
+
disabled: props.disabled,
|
|
2149
|
+
errors: props.errors,
|
|
2150
|
+
isCheckbox: checkbox,
|
|
2151
|
+
isReversed: reversed,
|
|
2152
|
+
isClickable: clickable,
|
|
2153
|
+
children: props.children
|
|
2154
|
+
}
|
|
2155
|
+
);
|
|
2156
|
+
}
|
|
2157
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2158
|
+
FieldHorizontal,
|
|
2159
|
+
{
|
|
2160
|
+
disabled: props.disabled,
|
|
2161
|
+
errors: props.errors,
|
|
2162
|
+
isCheckbox: checkbox,
|
|
2163
|
+
isReversed: reversed,
|
|
2164
|
+
isClickable: clickable,
|
|
2165
|
+
children: props.children
|
|
2166
|
+
}
|
|
2167
|
+
);
|
|
2168
|
+
}
|
|
2169
|
+
|
|
2170
|
+
// src/component/input/input-base.tsx
|
|
2171
|
+
function InputBase(props) {
|
|
2172
|
+
if (!props.field.type) {
|
|
2173
|
+
return null;
|
|
2174
|
+
}
|
|
2175
|
+
const commonProps = buildCommon(props.field, props.disabled);
|
|
2176
|
+
const dataAttributes = buildDataAttributes(props.field);
|
|
2177
|
+
const ariaAttributes = buildAriaAttributes(props.field, props.errors);
|
|
2178
|
+
const field = {
|
|
2179
|
+
...props.field,
|
|
2180
|
+
disabled: commonProps.disabled
|
|
2181
|
+
};
|
|
2182
|
+
return props.children({
|
|
2183
|
+
ariaAttributes,
|
|
2184
|
+
commonProps,
|
|
2185
|
+
dataAttributes,
|
|
2186
|
+
field,
|
|
2187
|
+
orientation: props.orientation
|
|
2188
|
+
});
|
|
2189
|
+
}
|
|
2190
|
+
|
|
2191
|
+
// src/component/field/field.tsx
|
|
2192
|
+
var import_tailwind_merge5 = require("tailwind-merge");
|
|
2042
2193
|
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
2194
|
+
function Field(props) {
|
|
2195
|
+
const cols2 = props.field.advanced?.cols;
|
|
2196
|
+
const errors = props.field.name ? props.errors?.[props.field.name] : void 0;
|
|
2197
|
+
const { orientation } = mergeStyle(props.style, {
|
|
2198
|
+
orientation: buildOrientation(props.field)
|
|
2199
|
+
});
|
|
2200
|
+
const disabled = buildDisabled(props.field, props.disabled);
|
|
2201
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: (0, import_tailwind_merge5.twMerge)("flex flex-col gap-3", getSpan(cols2)), children: [
|
|
2202
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2203
|
+
FieldGroup,
|
|
2204
|
+
{
|
|
2205
|
+
disabled,
|
|
2206
|
+
errors,
|
|
2207
|
+
field: props.field,
|
|
2208
|
+
orientation,
|
|
2209
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2210
|
+
InputBase,
|
|
2211
|
+
{
|
|
2212
|
+
disabled,
|
|
2213
|
+
errors,
|
|
2214
|
+
field: props.field,
|
|
2215
|
+
orientation,
|
|
2216
|
+
children: props.children
|
|
2217
|
+
}
|
|
2218
|
+
)
|
|
2219
|
+
}
|
|
2220
|
+
),
|
|
2221
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(FieldError, { errors, name: props.field.name })
|
|
2222
|
+
] });
|
|
2223
|
+
}
|
|
2224
|
+
|
|
2225
|
+
// src/client/component/field/field-with-error.tsx
|
|
2226
|
+
var import_jotai7 = require("jotai");
|
|
2227
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
2228
|
+
function withError(Component) {
|
|
2229
|
+
const WithError = (props) => {
|
|
2230
|
+
const errors = (0, import_jotai7.useAtomValue)(reportInputErrorAtom(props.field.name));
|
|
2231
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
2232
|
+
Component,
|
|
2233
|
+
{
|
|
2234
|
+
...props,
|
|
2235
|
+
errors: errors ? { [props.field.name]: errors } : void 0
|
|
2236
|
+
}
|
|
2237
|
+
);
|
|
2238
|
+
};
|
|
2239
|
+
return WithError;
|
|
2240
|
+
}
|
|
2241
|
+
|
|
2242
|
+
// src/client/component/field/field-with-state.tsx
|
|
2243
|
+
var import_jotai8 = require("jotai");
|
|
2244
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
2245
|
+
function withState(Component) {
|
|
2246
|
+
const WithFieldState = (props) => {
|
|
2247
|
+
const fieldState = (0, import_jotai8.useAtomValue)(reportFieldStateAtom(props.field.name));
|
|
2248
|
+
const hidden = fieldState?.hidden ?? props.field.hidden ?? false;
|
|
2249
|
+
if (hidden) {
|
|
2250
|
+
return null;
|
|
2251
|
+
}
|
|
2252
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Component, { ...props, disabled: fieldState?.disabled ?? props.disabled });
|
|
2253
|
+
};
|
|
2254
|
+
return WithFieldState;
|
|
2255
|
+
}
|
|
2256
|
+
|
|
2257
|
+
// src/client/component/field/field.tsx
|
|
2258
|
+
var Field2 = withState(withError(Field));
|
|
2259
|
+
|
|
2260
|
+
// src/component/field/field-list-item.tsx
|
|
2261
|
+
var import_tailwind_merge6 = require("tailwind-merge");
|
|
2262
|
+
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
2263
|
+
function FieldListItem(props) {
|
|
2264
|
+
function handleRemove() {
|
|
2265
|
+
if (props.canRemove && props.onRemove) {
|
|
2266
|
+
props.onRemove(props.index);
|
|
2267
|
+
}
|
|
2268
|
+
}
|
|
2269
|
+
const removeButton = props.canRemove && props.onRemove != null && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
2270
|
+
"button",
|
|
2271
|
+
{
|
|
2272
|
+
"aria-label": `Remove ${props.label} item ${props.index + 1}`,
|
|
2273
|
+
className: (0, import_tailwind_merge6.twMerge)(
|
|
2274
|
+
"rounded p-1 text-xl text-slate-400",
|
|
2275
|
+
"transition-colors duration-150",
|
|
2276
|
+
"hover:text-red-500",
|
|
2277
|
+
"focus-visible:ring-2 focus-visible:ring-slate-400 focus-visible:outline-none",
|
|
2278
|
+
"dark:text-slate-500 dark:hover:text-red-400"
|
|
2279
|
+
),
|
|
2280
|
+
onClick: handleRemove,
|
|
2281
|
+
type: "button",
|
|
2282
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { "aria-hidden": "true", children: "\xD7" })
|
|
2283
|
+
}
|
|
2284
|
+
);
|
|
2285
|
+
if (props.isMultiField) {
|
|
2286
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "rounded-lg border border-slate-100 p-4 dark:border-slate-900", children: [
|
|
2287
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "mb-3 flex items-center justify-between", children: [
|
|
2288
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("span", { className: "text-sm font-medium text-slate-400 dark:text-slate-500", children: [
|
|
2289
|
+
props.label,
|
|
2290
|
+
" ",
|
|
2291
|
+
props.index + 1
|
|
2292
|
+
] }),
|
|
2293
|
+
removeButton
|
|
2294
|
+
] }),
|
|
2295
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Group, { children: props.children })
|
|
2296
|
+
] });
|
|
2297
|
+
}
|
|
2298
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex items-start gap-2", children: [
|
|
2299
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Group, { children: props.children }),
|
|
2300
|
+
removeButton && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "shrink-0", children: removeButton })
|
|
2301
|
+
] });
|
|
2302
|
+
}
|
|
2303
|
+
|
|
2304
|
+
// src/client/component/field/field-list.tsx
|
|
2305
|
+
var import_tailwind_merge7 = require("tailwind-merge");
|
|
2306
|
+
|
|
2307
|
+
// src/client/hook/use-field-list.ts
|
|
2308
|
+
var import_jotai9 = require("jotai");
|
|
2309
|
+
var import_react6 = require("react");
|
|
2310
|
+
function useFieldList(field, value) {
|
|
2311
|
+
const min2 = field.advanced?.length?.min ?? 1;
|
|
2312
|
+
const max2 = field.advanced?.length?.max ?? Infinity;
|
|
2313
|
+
const [items, setItems] = (0, import_react6.useState)(
|
|
2314
|
+
() => getInitialList(field, value)
|
|
2315
|
+
);
|
|
2316
|
+
const nextId = (0, import_react6.useRef)(items.length);
|
|
2317
|
+
const itemsRef = (0, import_react6.useRef)(items);
|
|
2318
|
+
itemsRef.current = items;
|
|
2319
|
+
const setValues = (0, import_jotai9.useSetAtom)(valueAtom);
|
|
2320
|
+
const addItem = (0, import_react6.useCallback)(() => {
|
|
2321
|
+
setItems((previous) => {
|
|
2322
|
+
if (previous.length >= max2) {
|
|
2323
|
+
return previous;
|
|
2324
|
+
}
|
|
2325
|
+
const id = nextId.current++;
|
|
2326
|
+
return [...previous, id];
|
|
2327
|
+
});
|
|
2328
|
+
}, [max2]);
|
|
2329
|
+
const handleRemove = (0, import_react6.useCallback)(
|
|
2330
|
+
(index) => {
|
|
2331
|
+
if (items.length <= min2) {
|
|
2332
|
+
return;
|
|
2333
|
+
}
|
|
2334
|
+
const stableId = items[index];
|
|
2335
|
+
setItems((previous) => {
|
|
2336
|
+
if (previous.length <= min2) {
|
|
2337
|
+
return previous;
|
|
2338
|
+
}
|
|
2339
|
+
return previous.filter((_, i) => i !== index);
|
|
2340
|
+
});
|
|
2341
|
+
setValues((current) => {
|
|
2342
|
+
const next = { ...current };
|
|
2343
|
+
const prefix = `${field.name}.`;
|
|
2344
|
+
const leafNames = [];
|
|
2345
|
+
for (const row of field.fields) {
|
|
2346
|
+
if (isColumn(row)) {
|
|
2347
|
+
for (const columnField of row.fields) {
|
|
2348
|
+
leafNames.push(columnField.name);
|
|
2349
|
+
}
|
|
2350
|
+
} else {
|
|
2351
|
+
leafNames.push(row.name);
|
|
2352
|
+
}
|
|
2353
|
+
}
|
|
2354
|
+
for (const name of leafNames) {
|
|
2355
|
+
delete next[`${prefix}${stableId}.${name}`];
|
|
2356
|
+
}
|
|
2357
|
+
return next;
|
|
2358
|
+
});
|
|
2359
|
+
},
|
|
2360
|
+
[field.name, field.fields, items, min2, setValues]
|
|
2361
|
+
);
|
|
2362
|
+
const canAdd = items.length < max2;
|
|
2363
|
+
const canRemove = items.length > min2;
|
|
2364
|
+
return [items, addItem, handleRemove, canAdd, canRemove, max2];
|
|
2365
|
+
}
|
|
2366
|
+
|
|
2367
|
+
// src/client/component/field/field-list.tsx
|
|
2368
|
+
var import_jsx_runtime26 = require("react/jsx-runtime");
|
|
2369
|
+
function FieldList(props) {
|
|
2370
|
+
const [items, addItem, handleRemove, canAdd, canRemove, max2] = useFieldList(
|
|
2371
|
+
props.field,
|
|
2372
|
+
props.value
|
|
2373
|
+
);
|
|
2374
|
+
const label = getLabel(props.field);
|
|
2375
|
+
const action = props.field.advanced?.action ?? "Add item";
|
|
2376
|
+
const hasLimit = max2 !== Infinity;
|
|
2377
|
+
const isMultiField = isMultiFieldList(props.field);
|
|
2378
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_jsx_runtime26.Fragment, { children: [
|
|
2379
|
+
items.map((key, index) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
2380
|
+
FieldListItem,
|
|
2381
|
+
{
|
|
2382
|
+
canRemove,
|
|
2383
|
+
index,
|
|
2384
|
+
isMultiField,
|
|
2385
|
+
label,
|
|
2386
|
+
onRemove: handleRemove,
|
|
2387
|
+
children: props.children(key)
|
|
2388
|
+
},
|
|
2389
|
+
key
|
|
2390
|
+
)),
|
|
2391
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
|
|
2392
|
+
"button",
|
|
2393
|
+
{
|
|
2394
|
+
"aria-disabled": !canAdd,
|
|
2395
|
+
"aria-label": hasLimit ? `${action}, ${items.length} of ${max2}` : action,
|
|
2396
|
+
className: (0, import_tailwind_merge7.twMerge)(
|
|
2397
|
+
"flex w-full items-center gap-1.5 rounded py-1",
|
|
2398
|
+
"text-sm font-medium text-slate-500",
|
|
2399
|
+
"transition-colors duration-150",
|
|
2400
|
+
"hover:text-slate-800",
|
|
2401
|
+
"focus-visible:ring-2 focus-visible:ring-slate-400 focus-visible:ring-offset-2 focus-visible:outline-none",
|
|
2402
|
+
"dark:text-slate-400 dark:hover:text-slate-200",
|
|
2403
|
+
!canAdd && "cursor-not-allowed opacity-50 hover:text-slate-500 dark:hover:text-slate-400"
|
|
2404
|
+
),
|
|
2405
|
+
disabled: !canAdd,
|
|
2406
|
+
onClick: addItem,
|
|
2407
|
+
type: "button",
|
|
2408
|
+
children: [
|
|
2409
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { "aria-hidden": "true", children: "+" }),
|
|
2410
|
+
action,
|
|
2411
|
+
hasLimit && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
|
|
2412
|
+
"span",
|
|
2413
|
+
{
|
|
2414
|
+
"aria-hidden": "true",
|
|
2415
|
+
className: "ml-auto text-slate-400 tabular-nums dark:text-slate-500",
|
|
2416
|
+
children: [
|
|
2417
|
+
items.length,
|
|
2418
|
+
" / ",
|
|
2419
|
+
max2
|
|
2420
|
+
]
|
|
2421
|
+
}
|
|
2422
|
+
)
|
|
2423
|
+
]
|
|
2424
|
+
}
|
|
2425
|
+
)
|
|
2426
|
+
] });
|
|
2427
|
+
}
|
|
2428
|
+
|
|
2429
|
+
// src/component/list.tsx
|
|
2430
|
+
var import_jsx_runtime27 = require("react/jsx-runtime");
|
|
2431
|
+
function List(props) {
|
|
2432
|
+
const empty = Array.isArray(props.field.fields) && props.field.fields.length === 0;
|
|
2433
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
2434
|
+
FieldSetBase,
|
|
2435
|
+
{
|
|
2436
|
+
description: props.field.description,
|
|
2437
|
+
empty,
|
|
2438
|
+
id: props.field.name,
|
|
2439
|
+
title: props.field.label,
|
|
2440
|
+
children: props.children
|
|
2441
|
+
}
|
|
2442
|
+
);
|
|
2443
|
+
}
|
|
2444
|
+
|
|
2445
|
+
// src/client/component/guard/list-guard.tsx
|
|
2446
|
+
var import_jsx_runtime28 = require("react/jsx-runtime");
|
|
2447
|
+
function ListGuard({ children, field, value }) {
|
|
2448
|
+
return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(VisibilityGuard, { container: field, fields: field.fields, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(List, { field, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(FieldList, { field, value, children }) }) });
|
|
2449
|
+
}
|
|
2450
|
+
|
|
2451
|
+
// src/component/column.tsx
|
|
2452
|
+
var import_tailwind_merge8 = require("tailwind-merge");
|
|
2453
|
+
var import_jsx_runtime29 = require("react/jsx-runtime");
|
|
2043
2454
|
function Column(props) {
|
|
2044
2455
|
const cols2 = getColumn(props.column?.advanced?.cols);
|
|
2045
|
-
return /* @__PURE__ */ (0,
|
|
2456
|
+
return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "flex w-full flex-col gap-4", children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: (0, import_tailwind_merge8.twMerge)("grid grid-cols-1 gap-3 sm:gap-4", cols2), children: props.children }) });
|
|
2046
2457
|
}
|
|
2047
2458
|
|
|
2048
2459
|
// src/component/slot/slot-base.tsx
|
|
2049
|
-
var
|
|
2050
|
-
|
|
2460
|
+
var import_react7 = require("react");
|
|
2461
|
+
|
|
2462
|
+
// src/component/slot/slot-list.tsx
|
|
2463
|
+
var import_jsx_runtime30 = require("react/jsx-runtime");
|
|
2464
|
+
function SlotList(props) {
|
|
2465
|
+
const fields = Array.isArray(props.field.fields) ? props.field.fields.map((field) => {
|
|
2466
|
+
if (isField(field)) {
|
|
2467
|
+
return {
|
|
2468
|
+
...field,
|
|
2469
|
+
name: `${props.field.name}.${props.index}.${field.name}`
|
|
2470
|
+
};
|
|
2471
|
+
}
|
|
2472
|
+
if (isColumn(field)) {
|
|
2473
|
+
return {
|
|
2474
|
+
...field,
|
|
2475
|
+
fields: field.fields.map((columnField) => ({
|
|
2476
|
+
...columnField,
|
|
2477
|
+
name: `${props.field.name}.${props.index}.${columnField.name}`
|
|
2478
|
+
}))
|
|
2479
|
+
};
|
|
2480
|
+
}
|
|
2481
|
+
return field;
|
|
2482
|
+
}) : [];
|
|
2483
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
2484
|
+
SlotBase,
|
|
2485
|
+
{
|
|
2486
|
+
children: props.children,
|
|
2487
|
+
components: props.components,
|
|
2488
|
+
disabled: props.disabled,
|
|
2489
|
+
fields,
|
|
2490
|
+
style: props.style,
|
|
2491
|
+
value: props.value
|
|
2492
|
+
}
|
|
2493
|
+
);
|
|
2494
|
+
}
|
|
2495
|
+
|
|
2496
|
+
// src/component/slot/slot-base.tsx
|
|
2497
|
+
var import_jsx_runtime31 = require("react/jsx-runtime");
|
|
2051
2498
|
function SlotBase(props) {
|
|
2052
|
-
const {
|
|
2053
|
-
return prepare(props.fields).map((field, index) => /* @__PURE__ */ (0,
|
|
2054
|
-
isColumn(field) && /* @__PURE__ */ (0,
|
|
2055
|
-
isField(field) && /* @__PURE__ */ (0,
|
|
2499
|
+
const { field: Field3, list: List2 } = props.components;
|
|
2500
|
+
return prepare(props.fields).map((field, index) => /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(import_react7.Fragment, { children: [
|
|
2501
|
+
isColumn(field) && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(Column, { column: field, children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(SlotBase, { ...props, fields: field.fields }) }),
|
|
2502
|
+
isField(field) && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(Field3, { disabled: props.disabled, field, style: props.style, children: props.children }),
|
|
2503
|
+
isList(field) && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(List2, { field, value: props.value, children: (index2) => /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
2504
|
+
SlotList,
|
|
2505
|
+
{
|
|
2506
|
+
children: props.children,
|
|
2507
|
+
components: props.components,
|
|
2508
|
+
disabled: props.disabled,
|
|
2509
|
+
field,
|
|
2510
|
+
index: index2,
|
|
2511
|
+
style: props.style,
|
|
2512
|
+
value: props.value
|
|
2513
|
+
}
|
|
2514
|
+
) })
|
|
2056
2515
|
] }, index));
|
|
2057
2516
|
}
|
|
2058
2517
|
|
|
2059
2518
|
// src/component/slot/slot-create.tsx
|
|
2060
|
-
var
|
|
2061
|
-
function createSlot(
|
|
2062
|
-
const CreateSlot = (props) => /* @__PURE__ */ (0,
|
|
2519
|
+
var import_jsx_runtime32 = require("react/jsx-runtime");
|
|
2520
|
+
function createSlot(components) {
|
|
2521
|
+
const CreateSlot = (props) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(SlotBase, { ...props, components });
|
|
2063
2522
|
return CreateSlot;
|
|
2064
2523
|
}
|
|
2065
2524
|
|
|
2525
|
+
// src/client/component/slot/slot.tsx
|
|
2526
|
+
var Slot = createSlot({ field: Field2, list: ListGuard });
|
|
2527
|
+
|
|
2066
2528
|
// src/client/hook/use-form-action.ts
|
|
2067
|
-
var
|
|
2068
|
-
var
|
|
2529
|
+
var import_jotai10 = require("jotai");
|
|
2530
|
+
var import_react8 = require("react");
|
|
2069
2531
|
function useFormState(getSchema2, action, options) {
|
|
2070
|
-
const {
|
|
2071
|
-
|
|
2072
|
-
|
|
2532
|
+
const {
|
|
2533
|
+
onSuccess,
|
|
2534
|
+
preserveValues = false,
|
|
2535
|
+
validation = true,
|
|
2536
|
+
translations
|
|
2537
|
+
} = options ?? {};
|
|
2538
|
+
const setError = (0, import_jotai10.useSetAtom)(reportErrorAtom);
|
|
2539
|
+
const clearValues = (0, import_jotai10.useSetAtom)(clearAllValueAtom);
|
|
2073
2540
|
const initialState = {
|
|
2074
2541
|
data: null,
|
|
2075
2542
|
error: null,
|
|
2076
2543
|
success: false
|
|
2077
2544
|
};
|
|
2078
|
-
const [state, formAction, isPending] = (0,
|
|
2545
|
+
const [state, formAction, isPending] = (0, import_react8.useActionState)(
|
|
2079
2546
|
async (prevState, formData) => {
|
|
2080
2547
|
const [schemas, fields] = getSchema2();
|
|
2081
|
-
const schema = buildSchema(schemas, fields,
|
|
2548
|
+
const schema = buildSchema(schemas, fields, translations);
|
|
2082
2549
|
if (validation === false) {
|
|
2083
2550
|
if (action) {
|
|
2084
2551
|
return await action(formData, schema);
|
|
@@ -2089,33 +2556,43 @@ function useFormState(getSchema2, action, options) {
|
|
|
2089
2556
|
const validated = schema.safeParse(form);
|
|
2090
2557
|
if (!validated.success) {
|
|
2091
2558
|
const errors = flatten(validated.error);
|
|
2092
|
-
(0,
|
|
2559
|
+
(0, import_react8.startTransition)(() => {
|
|
2093
2560
|
setError(errors);
|
|
2094
2561
|
});
|
|
2095
2562
|
return failure(form, {
|
|
2096
|
-
description:
|
|
2563
|
+
description: translate(
|
|
2564
|
+
"Please correct the errors and try again.",
|
|
2565
|
+
translations
|
|
2566
|
+
),
|
|
2097
2567
|
details: [],
|
|
2098
|
-
title:
|
|
2568
|
+
title: translate(
|
|
2569
|
+
"There were validation errors submitting the form.",
|
|
2570
|
+
translations
|
|
2571
|
+
)
|
|
2099
2572
|
});
|
|
2100
2573
|
}
|
|
2574
|
+
const unflattened = unflatten(form);
|
|
2101
2575
|
if (action) {
|
|
2102
2576
|
try {
|
|
2103
|
-
const result = await action(
|
|
2577
|
+
const result = await action(unflattened, schema);
|
|
2104
2578
|
if (!result.success) {
|
|
2105
|
-
return failure(
|
|
2579
|
+
return failure(unflattened, result.error);
|
|
2106
2580
|
}
|
|
2107
2581
|
onSuccess?.(result.data);
|
|
2108
2582
|
if (!preserveValues) {
|
|
2109
|
-
(0,
|
|
2583
|
+
(0, import_react8.startTransition)(() => {
|
|
2110
2584
|
clearValues();
|
|
2111
2585
|
});
|
|
2112
2586
|
}
|
|
2113
|
-
return success(
|
|
2587
|
+
return success(unflattened, preserveValues);
|
|
2114
2588
|
} catch (error) {
|
|
2115
2589
|
logger.error("Error executing form action:", error);
|
|
2116
|
-
return failure(
|
|
2117
|
-
title:
|
|
2118
|
-
|
|
2590
|
+
return failure(unflattened, {
|
|
2591
|
+
title: translate(
|
|
2592
|
+
"An unexpected error occurred submitting the form.",
|
|
2593
|
+
translations
|
|
2594
|
+
),
|
|
2595
|
+
details: buildError(error, translations)
|
|
2119
2596
|
});
|
|
2120
2597
|
}
|
|
2121
2598
|
}
|
|
@@ -2125,9 +2602,11 @@ function useFormState(getSchema2, action, options) {
|
|
|
2125
2602
|
);
|
|
2126
2603
|
return [formAction, state, isPending];
|
|
2127
2604
|
}
|
|
2128
|
-
function buildError(error) {
|
|
2129
|
-
|
|
2130
|
-
|
|
2605
|
+
function buildError(error, translations) {
|
|
2606
|
+
if (error instanceof Error) {
|
|
2607
|
+
return [error.message];
|
|
2608
|
+
}
|
|
2609
|
+
return [translate("Unknown error", translations)];
|
|
2131
2610
|
}
|
|
2132
2611
|
function success(value, preserveValues = false) {
|
|
2133
2612
|
const data = preserveValues ? value : null;
|
|
@@ -2146,16 +2625,16 @@ function failure(value, error) {
|
|
|
2146
2625
|
}
|
|
2147
2626
|
|
|
2148
2627
|
// src/client/hook/use-schema.ts
|
|
2149
|
-
var
|
|
2628
|
+
var import_react10 = require("react");
|
|
2150
2629
|
|
|
2151
2630
|
// src/client/hook/use-store.ts
|
|
2152
|
-
var
|
|
2153
|
-
var
|
|
2631
|
+
var import_react9 = require("react");
|
|
2632
|
+
var import_jotai11 = require("jotai");
|
|
2154
2633
|
function useStore2() {
|
|
2155
|
-
const clearErrors = (0,
|
|
2156
|
-
const
|
|
2157
|
-
const
|
|
2158
|
-
return (0,
|
|
2634
|
+
const clearErrors = (0, import_jotai11.useSetAtom)(clearInputErrorAtom);
|
|
2635
|
+
const clearValues = (0, import_jotai11.useSetAtom)(clearInputValueAtom);
|
|
2636
|
+
const clearSources = (0, import_jotai11.useSetAtom)(clearInputSourceAtom);
|
|
2637
|
+
return (0, import_react9.useCallback)(
|
|
2159
2638
|
(names) => {
|
|
2160
2639
|
const target = Array.isArray(names) ? names : [names];
|
|
2161
2640
|
clearErrors(target);
|
|
@@ -2169,42 +2648,34 @@ function useStore2() {
|
|
|
2169
2648
|
// src/client/hook/use-schema.ts
|
|
2170
2649
|
function useSchema() {
|
|
2171
2650
|
const clear = useStore2();
|
|
2172
|
-
const schemaRef = (0,
|
|
2173
|
-
const fieldsRef = (0,
|
|
2174
|
-
const
|
|
2175
|
-
const onMount = (0, import_react9.useCallback)((name, schema, field) => {
|
|
2651
|
+
const schemaRef = (0, import_react10.useRef)({});
|
|
2652
|
+
const fieldsRef = (0, import_react10.useRef)([]);
|
|
2653
|
+
const onMount = (0, import_react10.useCallback)((name, schema, field) => {
|
|
2176
2654
|
if (!(name in schemaRef.current)) {
|
|
2177
2655
|
schemaRef.current[name] = schema;
|
|
2178
2656
|
fieldsRef.current.push(field);
|
|
2179
2657
|
}
|
|
2180
2658
|
}, []);
|
|
2181
|
-
const onUnmount = (0,
|
|
2659
|
+
const onUnmount = (0, import_react10.useCallback)(
|
|
2182
2660
|
(name) => {
|
|
2183
2661
|
if (schemaRef.current[name]) {
|
|
2184
2662
|
delete schemaRef.current[name];
|
|
2185
2663
|
fieldsRef.current = fieldsRef.current.filter((field) => {
|
|
2186
2664
|
return field.name !== name;
|
|
2187
2665
|
});
|
|
2188
|
-
|
|
2189
|
-
(0, import_react9.startTransition)(() => {
|
|
2190
|
-
if (pendingUnmounts.current.size > 0) {
|
|
2191
|
-
clear(Array.from(pendingUnmounts.current));
|
|
2192
|
-
pendingUnmounts.current.clear();
|
|
2193
|
-
}
|
|
2194
|
-
});
|
|
2666
|
+
clear([name]);
|
|
2195
2667
|
}
|
|
2196
2668
|
},
|
|
2197
2669
|
[clear]
|
|
2198
2670
|
);
|
|
2199
|
-
|
|
2671
|
+
const getSchema2 = (0, import_react10.useCallback)(() => {
|
|
2200
2672
|
return [schemaRef.current, fieldsRef.current];
|
|
2201
|
-
}
|
|
2673
|
+
}, []);
|
|
2202
2674
|
return [getSchema2, onMount, onUnmount];
|
|
2203
2675
|
}
|
|
2204
2676
|
|
|
2205
2677
|
// src/client/component/form-content.tsx
|
|
2206
|
-
var
|
|
2207
|
-
var Slot = createSlot(Field2);
|
|
2678
|
+
var import_jsx_runtime33 = require("react/jsx-runtime");
|
|
2208
2679
|
function FormContent(props) {
|
|
2209
2680
|
const translations = props.translations?.[props.lang ?? ""];
|
|
2210
2681
|
const [schema, onMount, onUnmount] = useSchema();
|
|
@@ -2215,8 +2686,8 @@ function FormContent(props) {
|
|
|
2215
2686
|
});
|
|
2216
2687
|
const isShowingError = props.config.validation.showError && !state.success && state.error;
|
|
2217
2688
|
const value = state.data ?? props.value;
|
|
2218
|
-
return /* @__PURE__ */ (0,
|
|
2219
|
-
isShowingError && renderIfExists(props.config.alert, (Alert) => /* @__PURE__ */ (0,
|
|
2689
|
+
return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
|
|
2690
|
+
isShowingError && renderIfExists(props.config.alert, (Alert) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "mb-4 w-full", children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
2220
2691
|
Alert,
|
|
2221
2692
|
{
|
|
2222
2693
|
description: state.error?.description,
|
|
@@ -2224,7 +2695,7 @@ function FormContent(props) {
|
|
|
2224
2695
|
title: state.error.title
|
|
2225
2696
|
}
|
|
2226
2697
|
) })),
|
|
2227
|
-
/* @__PURE__ */ (0,
|
|
2698
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
2228
2699
|
Form,
|
|
2229
2700
|
{
|
|
2230
2701
|
action,
|
|
@@ -2235,27 +2706,36 @@ function FormContent(props) {
|
|
|
2235
2706
|
noValidate: true,
|
|
2236
2707
|
readOnly: props.readOnly,
|
|
2237
2708
|
sections: props.sections,
|
|
2238
|
-
children: ({ disabled, fields }) => /* @__PURE__ */ (0,
|
|
2239
|
-
|
|
2709
|
+
children: ({ disabled, fields }) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
2710
|
+
Slot,
|
|
2240
2711
|
{
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2712
|
+
disabled,
|
|
2713
|
+
fields,
|
|
2714
|
+
style: props.config.style,
|
|
2715
|
+
value,
|
|
2716
|
+
children: (internal) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
2717
|
+
Input,
|
|
2718
|
+
{
|
|
2719
|
+
...internal,
|
|
2720
|
+
config: props.config,
|
|
2721
|
+
context: props.context,
|
|
2722
|
+
onMount,
|
|
2723
|
+
onUnmount,
|
|
2724
|
+
onValueChange: props.onValueChange,
|
|
2725
|
+
translations,
|
|
2726
|
+
value
|
|
2727
|
+
}
|
|
2728
|
+
)
|
|
2249
2729
|
}
|
|
2250
|
-
)
|
|
2730
|
+
)
|
|
2251
2731
|
}
|
|
2252
2732
|
)
|
|
2253
2733
|
] });
|
|
2254
2734
|
}
|
|
2255
2735
|
|
|
2256
2736
|
// src/client/component/form.tsx
|
|
2257
|
-
var
|
|
2258
|
-
var
|
|
2737
|
+
var import_jotai12 = require("jotai");
|
|
2738
|
+
var import_jsx_runtime34 = require("react/jsx-runtime");
|
|
2259
2739
|
function Form2(props) {
|
|
2260
|
-
return /* @__PURE__ */ (0,
|
|
2740
|
+
return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_jotai12.Provider, { children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(FormContent, { ...props }) });
|
|
2261
2741
|
}
|