react-luna-form 0.0.27 → 0.0.29

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,2708 +1 @@
1
- // src/component/control.tsx
2
- import { jsx } from "react/jsx-runtime";
3
- function Control(props) {
4
- const content = typeof props.children === "function" ? props.children({ isPending: props.isPending }) : props.children;
5
- return /* @__PURE__ */ jsx("div", { "data-slot": "field-control", className: "w-full", children: content });
6
- }
7
-
8
- // src/component/field/field-set-advanced.tsx
9
- import { Activity, useCallback, useState } from "react";
10
-
11
- // src/component/chevron-icon.tsx
12
- import { jsx as jsx2 } from "react/jsx-runtime";
13
- function ChevronIcon(props) {
14
- return /* @__PURE__ */ jsx2(
15
- "svg",
16
- {
17
- xmlns: "http://www.w3.org/2000/svg",
18
- viewBox: "0 0 20 20",
19
- fill: "currentColor",
20
- className: `size-4 transition-transform duration-200 ${props.expanded ? "rotate-90" : ""}`,
21
- children: /* @__PURE__ */ jsx2(
22
- "path",
23
- {
24
- fillRule: "evenodd",
25
- 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",
26
- clipRule: "evenodd"
27
- }
28
- )
29
- }
30
- );
31
- }
32
-
33
- // ../luna-core/src/util/constant.ts
34
- var INPUT = "input";
35
- var INPUT_EMAIL = "input/email";
36
- var INPUT_NUMBER = "input/number";
37
- var TEXTAREA = "textarea";
38
- var RADIO = "radio";
39
- var CHECKBOX = "checkbox";
40
- var LIST = "list";
41
- var SELECT = "select";
42
- var SELECT_MONTH = "select/month";
43
- var SELECT_YEAR = "select/year";
44
- var COLUMN = "column";
45
- var FIELDS = "fields";
46
- var LABEL = "label";
47
- var VALUE = "value";
48
- var OPTIONS = "options";
49
- var TYPE_EMAIL = "email";
50
- var TYPE_NUMBER = "number";
51
- var TYPE_PASSWORD = "password";
52
- var TYPE_TEL = "tel";
53
- var TYPE_TEXT = "text";
54
- var ARIA_ERROR_MESSAGE = "aria-errormessage";
55
- var ARIA_INVALID = "aria-invalid";
56
- var DATA_INVALID = "data-invalid";
57
- var DATA_READONLY = "data-readonly";
58
- var PREFIX_ARIA = "aria";
59
- var PREFIX_DATA = "data";
60
- var MIN = "min";
61
- var MAX = "max";
62
- var MIN_LENGTH = "minLength";
63
- var MAX_LENGTH = "maxLength";
64
- var $REF = "$ref";
65
- var SOURCE = "source";
66
- var STATE = "state";
67
- var COMMON_URL = "http://luna.internal";
68
- var VERTICAL = "vertical";
69
- var HORIZONTAL = "horizontal";
70
- var TYPE = "type";
71
-
72
- // ../luna-core/src/util/is-type.ts
73
- function isObject(value) {
74
- return value !== null && Object.prototype.toString.call(value) === "[object Object]";
75
- }
76
- function isEmpty(value) {
77
- return value === null || value === void 0 || value === "";
78
- }
79
- function isValue(value) {
80
- return isString(value) || typeof value === "number" || isBoolean(value);
81
- }
82
- function isString(value) {
83
- return typeof value === "string";
84
- }
85
- function isDataSource(value) {
86
- return isObject(value) && "url" in value;
87
- }
88
- function isBoolean(value) {
89
- return typeof value === "boolean";
90
- }
91
-
92
- // ../luna-core/src/util/extract.ts
93
- var REGEX_TYPE = /[^/]+$/;
94
- var REGEX_NUMERIC = /^\d+$/;
95
- function getEntity(selected, collection = [], entity = VALUE) {
96
- if (Array.isArray(collection)) {
97
- return collection.find((item) => {
98
- const current = getCurrentValue(item, entity);
99
- if (current !== void 0 && `${current}` === selected) {
100
- return item;
101
- }
102
- }) ?? { value: selected };
103
- }
104
- return { value: selected };
105
- }
106
- function getCurrentValue(value, entity = VALUE) {
107
- if (value !== null && value !== void 0) {
108
- if (isValue(value)) {
109
- return value;
110
- }
111
- if (isObject(value)) {
112
- const result = getValue(value, entity);
113
- if (isValue(result)) {
114
- return result;
115
- }
116
- }
117
- }
118
- }
119
- function getValue(value, namespace) {
120
- const result = extract(value, namespace);
121
- if (isValue(result)) {
122
- return result;
123
- }
124
- }
125
- function getArray(value, namespace) {
126
- if (Array.isArray(value)) {
127
- return value;
128
- }
129
- const result = extract(value, namespace);
130
- if (Array.isArray(result)) {
131
- return result;
132
- }
133
- return null;
134
- }
135
- function extract(value, namespace) {
136
- if (!namespace || !isObject(value)) {
137
- return null;
138
- }
139
- const keys = namespace.split(".").filter((key) => key !== "");
140
- if (keys.length === 0) {
141
- return null;
142
- }
143
- let result = value;
144
- for (const key of keys) {
145
- if (isObject(result) && key in result) {
146
- const obj = result;
147
- result = obj[key];
148
- } else {
149
- return null;
150
- }
151
- }
152
- return result;
153
- }
154
- function toOptions(data, options = { label: LABEL, value: VALUE }) {
155
- return data.map((item) => {
156
- if (isObject(item)) {
157
- const label = extract(item, options.label);
158
- const value = extract(item, options.value);
159
- if (isValue(label) && isValue(value)) {
160
- return {
161
- label: `${label}`,
162
- value: `${value}`
163
- };
164
- }
165
- }
166
- return item;
167
- });
168
- }
169
- function getType(value = TYPE_TEXT) {
170
- if (value) {
171
- const result = value.match(REGEX_TYPE);
172
- if (result) {
173
- const [type] = result;
174
- if (type !== INPUT) {
175
- return type.trim().toLowerCase();
176
- }
177
- }
178
- }
179
- return TYPE_TEXT;
180
- }
181
- function getFormData(formData) {
182
- const data = {};
183
- for (const key of formData.keys()) {
184
- const values = formData.getAll(key);
185
- data[key] = values.length > 1 ? values : values[0];
186
- }
187
- return data;
188
- }
189
- function unflatten(data) {
190
- const result = {};
191
- for (const key in data) {
192
- const parts = key.split(".");
193
- if (parts.length === 1) {
194
- result[key] = data[key];
195
- continue;
196
- }
197
- let current = result;
198
- for (let i = 0; i < parts.length - 1; i++) {
199
- const part = parts[i];
200
- const next = parts[i + 1];
201
- const isNextIndex = REGEX_NUMERIC.test(next);
202
- if (!(part in current)) {
203
- current[part] = isNextIndex ? [] : {};
204
- }
205
- current = current[part];
206
- }
207
- const last = parts[parts.length - 1];
208
- current[last] = data[key];
209
- }
210
- compactArrays(result);
211
- return result;
212
- }
213
- function compactArrays(obj) {
214
- for (const key in obj) {
215
- const value = obj[key];
216
- if (Array.isArray(value)) {
217
- const compacted = value.filter((item) => item !== void 0);
218
- compacted.forEach((item) => {
219
- if (item !== null && typeof item === "object" && !Array.isArray(item)) {
220
- compactArrays(item);
221
- }
222
- });
223
- obj[key] = compacted;
224
- } else if (value !== null && typeof value === "object") {
225
- compactArrays(value);
226
- }
227
- }
228
- }
229
-
230
- // ../luna-core/src/util/string.ts
231
- var REGEX_MARKDOWN_LINK = /\[([^\]]+)\]\(([^)]+)\)/g;
232
- function interpolate(template, values = {}) {
233
- if (isString(template)) {
234
- return replacePlaceholders(template, values);
235
- }
236
- if (Array.isArray(template)) {
237
- return template.map((item) => {
238
- return interpolate(item, values);
239
- });
240
- }
241
- if (isObject(template)) {
242
- const results = {};
243
- for (const key in template) {
244
- results[key] = interpolate(template[key], values);
245
- }
246
- return results;
247
- }
248
- return template;
249
- }
250
- function interpolateIfNeeded(template, values = {}) {
251
- return isInterpolated(template) ? interpolate(template, values) : template;
252
- }
253
- function isInterpolated(template) {
254
- if (isString(template)) {
255
- return /{([^}]+)}/.test(template);
256
- }
257
- if (Array.isArray(template)) {
258
- return template.some((item) => isInterpolated(item));
259
- }
260
- if (isObject(template)) {
261
- return Object.values(template).some((value) => isInterpolated(value));
262
- }
263
- return false;
264
- }
265
- function replacePlaceholders(template, values = {}) {
266
- return template.replace(/{([^}]+)}/g, (match, key) => {
267
- const value = key.includes(".") ? extract(values, key) : values[key];
268
- if (isValue(value)) {
269
- return String(value);
270
- }
271
- return match;
272
- });
273
- }
274
- function formatMarkdown(text, callback) {
275
- if (!text || text.trim().length === 0) {
276
- return null;
277
- }
278
- let match;
279
- let lastIndex = 0;
280
- let hasMatch = false;
281
- const parts = [];
282
- while ((match = REGEX_MARKDOWN_LINK.exec(text)) !== null) {
283
- const [fullMatch, linkText, url] = match;
284
- const index = match.index;
285
- hasMatch = true;
286
- if (index > lastIndex) {
287
- parts.push(text.substring(lastIndex, index));
288
- }
289
- const value = callback ? callback(index, url, linkText) : fullMatch;
290
- parts.push(value);
291
- lastIndex = index + fullMatch.length;
292
- }
293
- if (!hasMatch) {
294
- return text;
295
- }
296
- if (lastIndex < text.length) {
297
- parts.push(text.substring(lastIndex));
298
- }
299
- return parts;
300
- }
301
-
302
- // ../luna-core/src/util/logger.ts
303
- var logger = {
304
- error: (...args) => {
305
- if (isConsoleAvailable() && !isProduction()) {
306
- getConsole().error("[Luna Form]", ...args);
307
- }
308
- },
309
- warn: (...args) => {
310
- if (isConsoleAvailable() && !isProduction()) {
311
- getConsole().warn("[Luna Form]", ...args);
312
- }
313
- },
314
- info: (...args) => {
315
- if (isConsoleAvailable() && !isProduction()) {
316
- getConsole().info("[Luna Form]", ...args);
317
- }
318
- }
319
- };
320
- var isConsoleAvailable = () => typeof getConsole() !== "undefined";
321
- var isProduction = () => false;
322
- var getConsole = () => globalThis.console;
323
-
324
- // ../luna-core/src/handle/proxy-event.ts
325
- function handleProxyEvent(events = [], callback) {
326
- const values = [];
327
- const sources = [];
328
- const states = [];
329
- for (const event of events) {
330
- if (event.action === VALUE) {
331
- values.push(event);
332
- }
333
- if (event.action === SOURCE) {
334
- sources.push(event);
335
- }
336
- if (event.action === STATE) {
337
- states.push(event);
338
- }
339
- }
340
- callback({ sources, states, values });
341
- }
342
-
343
- // ../luna-core/src/handle/source-event.ts
344
- function handleSourceEvent(selected = null, events = [], setSource) {
345
- for (const event of events) {
346
- const { target, source } = event;
347
- if (!selected) {
348
- setSource(target, void 0);
349
- continue;
350
- }
351
- if (isDataSource(source)) {
352
- const newUrl = interpolate(source.url, selected);
353
- const newBody = source.body ? interpolate(source.body, selected) : source.body;
354
- setSource(target, {
355
- ...source,
356
- url: newUrl,
357
- body: newBody
358
- });
359
- }
360
- }
361
- }
362
-
363
- // ../luna-core/src/util/operator.ts
364
- var operators = {
365
- eq,
366
- gt,
367
- gte,
368
- in: includes,
369
- lt,
370
- lte,
371
- neq,
372
- nin
373
- };
374
- var ISO_DATE_REGEX = /^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}:\d{2})?/;
375
- var DMY_DATE_REGEX = /^(\d{2})[/-](\d{2})[/-](\d{4})(?: (\d{2}):(\d{2})(?::(\d{2}))?)?$/;
376
- function isISODateString(value) {
377
- return typeof value === "string" && ISO_DATE_REGEX.test(value);
378
- }
379
- function isDMYDateString(value) {
380
- return typeof value === "string" && DMY_DATE_REGEX.test(value);
381
- }
382
- function parseDMYDate(value) {
383
- const match = value.match(DMY_DATE_REGEX);
384
- if (match) {
385
- const [, day, month, year, hours, minutes, seconds] = match;
386
- return new Date(
387
- Number(year),
388
- Number(month) - 1,
389
- Number(day),
390
- Number(hours ?? 0),
391
- Number(minutes ?? 0),
392
- Number(seconds ?? 0)
393
- ).getTime();
394
- }
395
- return NaN;
396
- }
397
- function toComparableNumber(value) {
398
- if (isISODateString(value)) {
399
- return new Date(value).getTime();
400
- }
401
- if (isDMYDateString(value)) {
402
- return parseDMYDate(value);
403
- }
404
- return Number(value);
405
- }
406
- function eq(current, value) {
407
- return current === value;
408
- }
409
- function neq(current, value) {
410
- return current !== value;
411
- }
412
- function includes(current, value) {
413
- return Array.isArray(value) && value.includes(String(current));
414
- }
415
- function nin(current, value) {
416
- return Array.isArray(value) && !value.includes(String(current));
417
- }
418
- function gt(current, value) {
419
- return toComparableNumber(current) > toComparableNumber(value);
420
- }
421
- function gte(current, value) {
422
- return toComparableNumber(current) >= toComparableNumber(value);
423
- }
424
- function lt(current, value) {
425
- return toComparableNumber(current) < toComparableNumber(value);
426
- }
427
- function lte(current, value) {
428
- return toComparableNumber(current) <= toComparableNumber(value);
429
- }
430
-
431
- // ../luna-core/src/handle/state-event.ts
432
- function handleStateEvent(selected = null, events = [], setState) {
433
- for (const event of events) {
434
- const { target, state, when } = event;
435
- const targets = Array.isArray(target) ? target : [target];
436
- if (!selected) {
437
- setState(targets);
438
- continue;
439
- }
440
- logger.info(`Selected value for state event: ${JSON.stringify(selected)}, evaluating condition: ${JSON.stringify(when)}`);
441
- const matches = evaluateCondition(selected, when);
442
- logger.info(`Condition evaluated to: ${matches}, setting state for targets: ${targets.join(", ")}`);
443
- setState(targets, matches ? state : void 0);
444
- }
445
- }
446
- function evaluateCondition(selected, when) {
447
- if (when === void 0) {
448
- return true;
449
- }
450
- if (isString(when)) {
451
- logger.info(`Evaluating string condition: ${when} against selected value: ${JSON.stringify(selected)} using VALUE field`);
452
- logger.info(`Extracted value for comparison: ${JSON.stringify(getValue2(selected, VALUE))}`);
453
- logger.info(`Comparison result: ${getValue2(selected, VALUE) === when}`);
454
- return getValue2(selected, VALUE) === when;
455
- }
456
- if (isBoolean(when)) {
457
- return Boolean(getValue2(selected, VALUE)) === when;
458
- }
459
- if (Array.isArray(when)) {
460
- return when.includes(String(getValue2(selected, VALUE)));
461
- }
462
- return evaluateOperator(selected, when);
463
- }
464
- function evaluateOperator(selected = null, condition) {
465
- const current = getValue2(selected, condition.field ?? VALUE);
466
- const { operator = "eq", value } = condition;
467
- const operation = operators[operator];
468
- if (operation) {
469
- return operation(current, value);
470
- }
471
- return false;
472
- }
473
- function getValue2(selected, field) {
474
- if (isObject(selected)) {
475
- return extract(selected, field);
476
- }
477
- return selected;
478
- }
479
-
480
- // ../luna-core/src/handle/value-event.ts
481
- function handleValueEvent(selected = null, events = [], setValue) {
482
- for (const event of events) {
483
- for (const [target, value] of Object.entries(event.value)) {
484
- setValue(target, selected ? interpolate(value, selected) : void 0);
485
- }
486
- }
487
- }
488
-
489
- // ../luna-core/src/util/is-input.ts
490
- var isSelectMonth = (field) => createTypeChecker(SELECT_MONTH)(field);
491
- var isSelectYear = (field) => createTypeChecker(SELECT_YEAR)(field);
492
- var isCheckbox = createTypeChecker(CHECKBOX);
493
- var isInput = createTypeChecker(INPUT);
494
- var isRadio = createTypeChecker(RADIO);
495
- var isSelect = createTypeChecker(SELECT);
496
- var isTextArea = createTypeChecker(TEXTAREA);
497
- var isText = createTypeChecker(
498
- TYPE_TEXT,
499
- TYPE_EMAIL,
500
- TYPE_PASSWORD,
501
- TYPE_TEL
502
- );
503
- var isEmail = createTypeChecker(INPUT_EMAIL, TYPE_EMAIL);
504
- var isNumber = createTypeChecker(INPUT_NUMBER, TYPE_NUMBER);
505
- function isClickable(field) {
506
- return isRadio(field) || isCheckbox(field);
507
- }
508
- function isList(slot) {
509
- return slot.type === LIST;
510
- }
511
- function isColumn(slot) {
512
- return slot.type === COLUMN;
513
- }
514
- function isField(slot) {
515
- return slot.type !== COLUMN && slot.type !== LIST;
516
- }
517
- function isOptions(field) {
518
- return isSelect(field) || isRadio(field);
519
- }
520
- function isTextable(field) {
521
- return isInput(field) || isTextArea(field);
522
- }
523
- function isValidValue(value) {
524
- return value !== void 0 && value !== null && value !== "";
525
- }
526
- function createTypeChecker(...types) {
527
- return (field) => {
528
- const inputType = isString(field.type) ? field.type : void 0;
529
- if (!inputType) {
530
- return false;
531
- }
532
- return types.some((type) => {
533
- return inputType === type || inputType?.startsWith(`${type}/`);
534
- });
535
- };
536
- }
537
-
538
- // ../luna-core/src/util/build.ts
539
- function buildOptions(field, values = {}) {
540
- if (isSelect(field) && field.disabled) {
541
- const current = field.name ? values?.[field.name] : void 0;
542
- if (current && isObject(current)) {
543
- return [current];
544
- }
545
- }
546
- }
547
- function buildOrientation(field) {
548
- if (isRadio(field) || isCheckbox(field)) {
549
- return HORIZONTAL;
550
- }
551
- return field.advanced?.orientation ?? VERTICAL;
552
- }
553
- function buildReverse(field) {
554
- if (!isCheckbox(field)) {
555
- return false;
556
- }
557
- return field.advanced?.reverse !== false;
558
- }
559
- function buildDisabled(field, disabled) {
560
- const readonly = field.readonly ?? false;
561
- return disabled ? disabled : readonly;
562
- }
563
- function buildSource(field) {
564
- if (isRadio(field) || isSelect(field) && !field.disabled) {
565
- const source = field.source;
566
- if (Array.isArray(source) || isObject(source) && !($REF in source)) {
567
- return source;
568
- }
569
- }
570
- }
571
-
572
- // ../luna-core/src/util/date.ts
573
- var REGEX_DIGITS = /^\d+$/;
574
- function getMonth() {
575
- return Array.from({ length: 12 }, (_, i) => ({
576
- value: (i + 1).toString(),
577
- label: new Date(0, i).toLocaleString("default", {
578
- month: "long"
579
- })
580
- }));
581
- }
582
- function getYear(min2, max2) {
583
- if (max2 >= min2) {
584
- return Array.from({ length: max2 - min2 + 1 }, (_, i) => {
585
- const year = min2 + i;
586
- return {
587
- value: year.toString(),
588
- label: year.toString()
589
- };
590
- });
591
- }
592
- return [];
593
- }
594
- function getCurrentYear() {
595
- return (/* @__PURE__ */ new Date()).getFullYear();
596
- }
597
- function getConvert(value, current) {
598
- if (typeof value === "number") {
599
- return value;
600
- }
601
- const now2 = current ?? getCurrentYear();
602
- const trimmed = value.trim().toLowerCase();
603
- if (trimmed.startsWith("current")) {
604
- const match = trimmed.match(/^current([+-])(\d+)$/);
605
- if (match) {
606
- const [, operator, offsetStr] = match;
607
- const offset = parseInt(offsetStr, 10);
608
- if (!isNaN(offset)) {
609
- return operator === "+" ? now2 + offset : now2 - offset;
610
- }
611
- }
612
- return now2;
613
- }
614
- if (REGEX_DIGITS.test(trimmed)) {
615
- return parseInt(trimmed, 10);
616
- }
617
- return now2;
618
- }
619
-
620
- // ../luna-core/src/helper/input.ts
621
- var now = getCurrentYear();
622
- function buildOptionSelect(field) {
623
- if (isSelect(field)) {
624
- return defineOption(field);
625
- }
626
- }
627
- function defineOption(select) {
628
- if (isSelectMonth(select)) {
629
- return getMonth();
630
- }
631
- if (isSelectYear(select)) {
632
- const min2 = select.advanced?.length?.min ?? now;
633
- const max2 = select.advanced?.length?.max ?? now + 5;
634
- return getYear(getConvert(min2, now), getConvert(max2, now));
635
- }
636
- }
637
- function buildCommon(field, disabled = false) {
638
- const commonProps = {
639
- disabled,
640
- id: field.name,
641
- name: field.name,
642
- placeholder: field.placeholder,
643
- required: field.required
644
- };
645
- if (isInput(field)) {
646
- return {
647
- ...commonProps,
648
- ...defineInput(field)
649
- };
650
- }
651
- if (isSelect(field)) {
652
- return {
653
- ...commonProps,
654
- ...defineSelect(field)
655
- };
656
- }
657
- if (isTextArea(field)) {
658
- return {
659
- ...commonProps,
660
- ...defineTextArea(field)
661
- };
662
- }
663
- return commonProps;
664
- }
665
- function defineInput(input) {
666
- const type = getType(input.type);
667
- const copy = { ...input, type };
668
- return {
669
- ...defineAutoComplete(input),
670
- ...defineNumberLimits(copy),
671
- ...isText(copy) ? defineLength(copy) : {},
672
- type
673
- };
674
- }
675
- function defineSelect(field) {
676
- const options = buildOptionSelect(field);
677
- if (options) {
678
- return { options };
679
- }
680
- return {};
681
- }
682
- function defineTextArea(field) {
683
- return {
684
- ...defineAutoComplete(field),
685
- ...defineLength(field)
686
- };
687
- }
688
- function defineAutoComplete(input) {
689
- const autoComplete = input.advanced?.autocomplete;
690
- if (autoComplete) {
691
- return { autoComplete };
692
- }
693
- return {};
694
- }
695
- function defineNumberLimits(input) {
696
- if (isNumber(input)) {
697
- return defineMinMax(input);
698
- }
699
- return {};
700
- }
701
- function defineLength(input) {
702
- return defineConstraints(input, { min: MIN_LENGTH, max: MAX_LENGTH });
703
- }
704
- function defineMinMax(input) {
705
- return defineConstraints(input, { min: MIN, max: MAX });
706
- }
707
- function defineConstraints(input, keys) {
708
- const result = {};
709
- const length = input.advanced?.length;
710
- if (length) {
711
- if (length.min !== void 0) {
712
- result[keys.min] = length.min;
713
- }
714
- if (length.max !== void 0) {
715
- result[keys.max] = length.max;
716
- }
717
- }
718
- return result;
719
- }
720
- function resolveSource(field, value) {
721
- const current = buildSource(field);
722
- if (current) {
723
- return current;
724
- }
725
- return buildOptions(field, value);
726
- }
727
- function getInputValue(field, value) {
728
- const newValue = isObject(value) && field.name in value ? value[field.name] : value;
729
- return getCurrentValue(newValue, field.advanced?.entity);
730
- }
731
- function mergeOptionsProps(field, commonProps, options) {
732
- return isOptions(field) && Array.isArray(options) ? { ...commonProps, [OPTIONS]: options } : commonProps;
733
- }
734
- function getPreselectedValue(field, commonProps, value) {
735
- if (field.required && !isValidValue(value)) {
736
- if (isSelect(field)) {
737
- if (field.advanced?.preselected !== false && OPTIONS in commonProps) {
738
- const options = commonProps[OPTIONS];
739
- if (Array.isArray(options) && options.length === 1) {
740
- return options[0];
741
- }
742
- }
743
- }
744
- }
745
- return value;
746
- }
747
- function getOptions(field, data) {
748
- if (isSelect(field) && Array.isArray(data)) {
749
- return toOptions(data, field.advanced?.options);
750
- }
751
- return data;
752
- }
753
- function prepareInputProps(field, commonProps, data, value) {
754
- const currentValue = getInputValue(field, value);
755
- const options = Array.isArray(data) ? getOptions(field, data) : data;
756
- const commonPropsWithOptions = mergeOptionsProps(field, commonProps, options);
757
- const defaultValue = getPreselectedValue(
758
- field,
759
- commonPropsWithOptions,
760
- currentValue
761
- );
762
- return {
763
- commonPropsWithOptions,
764
- defaultValue
765
- };
766
- }
767
- function prepareInputValue(field, value) {
768
- if (isCheckbox(field)) {
769
- return {
770
- checked: isValidValue(value) ? value : false
771
- };
772
- }
773
- return { value: value ?? "" };
774
- }
775
-
776
- // ../luna-core/src/util/prepare.ts
777
- var REGEX_REF = /^#\/definition\//;
778
- function prepare(base = [], definition) {
779
- const resolved = resolveRefs(base, definition);
780
- return Array.isArray(resolved) ? resolved.filter(filter).sort((a, b) => getOrder(a) - getOrder(b)) : [];
781
- }
782
- function resolveRefs(base, definition, cache = /* @__PURE__ */ new Map(), visited = /* @__PURE__ */ new WeakSet()) {
783
- if (!isDefinition(definition) || !base || typeof base !== "object") {
784
- return base;
785
- }
786
- if (cache.has(base)) {
787
- return cache.get(base);
788
- }
789
- if (visited.has(base)) {
790
- return base;
791
- }
792
- visited.add(base);
793
- if (Array.isArray(base)) {
794
- return base.map((item) => resolveRefs(item, definition, cache, visited));
795
- }
796
- if ($REF in base && isString(base[$REF])) {
797
- const path = base[$REF].replace(REGEX_REF, "");
798
- const resolved = extract(definition, path);
799
- if (resolved !== null) {
800
- return resolveRefs(resolved, definition, cache, visited);
801
- }
802
- return base;
803
- }
804
- const result = {};
805
- for (const [key, value] of Object.entries(base)) {
806
- result[key] = resolveRefs(value, definition, cache, visited);
807
- }
808
- visited.delete(base);
809
- cache.set(base, result);
810
- return result;
811
- }
812
- function entries(values) {
813
- return Object.entries(values ?? {});
814
- }
815
- function getOrder(item) {
816
- return item.order ?? Number.MAX_VALUE;
817
- }
818
- function isDefinition(definition) {
819
- return definition !== void 0 && isObject(definition) && Object.keys(definition).length > 0;
820
- }
821
- function filter(base) {
822
- if (TYPE in base) {
823
- return true;
824
- }
825
- if (Array.isArray(base[FIELDS])) {
826
- return base[FIELDS].length > 0;
827
- }
828
- return true;
829
- }
830
-
831
- // ../luna-core/src/util/attributes.ts
832
- function getPrefixedAttributes(prefix, record) {
833
- const attrs = {};
834
- for (const [key, value] of entries(record)) {
835
- attrs[`${prefix}-${key}`] = value;
836
- }
837
- return attrs;
838
- }
839
- function getAriaAttributes(record) {
840
- return getPrefixedAttributes(PREFIX_ARIA, record);
841
- }
842
- function getDataAttributes(record) {
843
- return getPrefixedAttributes(PREFIX_DATA, record);
844
- }
845
- function buildAriaAttributes(field, errors) {
846
- const ariaAttributes = getAriaAttributes(field.advanced?.aria);
847
- if (errors && errors.length > 0) {
848
- ariaAttributes[ARIA_INVALID] = "true";
849
- ariaAttributes[ARIA_ERROR_MESSAGE] = `${field.name}-error`;
850
- }
851
- return ariaAttributes;
852
- }
853
- function buildDataAttributes(field) {
854
- return getDataAttributes(field.advanced?.data);
855
- }
856
-
857
- // ../luna-core/src/util/column.ts
858
- var cols = {
859
- 1: "md:grid-cols-1",
860
- 2: "md:grid-cols-2",
861
- 3: "md:grid-cols-3"
862
- };
863
- var span = {
864
- 1: "md:col-span-1",
865
- 2: "md:col-span-2",
866
- 3: "md:col-span-3"
867
- };
868
- function getColumn(value, defaultCols = 2) {
869
- return cols[value && value in cols ? value : defaultCols];
870
- }
871
- function getSpan(value) {
872
- if (value && value in span) {
873
- return span[value];
874
- }
875
- }
876
-
877
- // ../luna-core/src/util/list.ts
878
- function getInitialCount(list, value) {
879
- const min2 = list.advanced?.length?.min ?? 1;
880
- if (value) {
881
- const data = extract(value, list.name);
882
- if (Array.isArray(data)) {
883
- return Math.max(data.length, min2);
884
- }
885
- }
886
- return Math.max(min2, 0);
887
- }
888
- function isMultiFieldList(list) {
889
- if (!Array.isArray(list.fields) || list.fields.length === 0) {
890
- return false;
891
- }
892
- return list.fields.length > 1 || list.fields[0].type === COLUMN;
893
- }
894
- function getInitialList(list, value) {
895
- const count = getInitialCount(list, value);
896
- return Array.from({ length: count }, (_, index) => index);
897
- }
898
- function getLabel(list) {
899
- return list.label ?? list.name;
900
- }
901
-
902
- // ../luna-core/src/util/schema.ts
903
- import { z } from "zod";
904
-
905
- // ../luna-core/src/util/translate.ts
906
- function translate(key, dictionary) {
907
- if (!key) {
908
- return "";
909
- }
910
- if (!dictionary) {
911
- return key;
912
- }
913
- return dictionary[key] ?? key;
914
- }
915
-
916
- // ../luna-core/src/util/schema.ts
917
- var approach = [
918
- [isNumber, getNumber],
919
- [isEmail, getEmail],
920
- [isSelectYear, getYearSchema],
921
- [isSelectMonth, getMonthSchema],
922
- [isCheckbox, getBoolean],
923
- [isRadio, getRadio]
924
- ];
925
- function buildSchema(schemas, fields = [], translations) {
926
- const schema = z.object(schemas);
927
- if (fields.length === 0) {
928
- return schema;
929
- }
930
- return applyCustomValidation(schema, fields, translations);
931
- }
932
- function flatten(error) {
933
- const results = {};
934
- const errors = z.flattenError(error).fieldErrors;
935
- for (const [key, value] of Object.entries(errors)) {
936
- if (value !== void 0) {
937
- results[key] = value;
938
- }
939
- }
940
- return results;
941
- }
942
- function getSchema(input, translations) {
943
- for (const [check, getSchema2] of approach) {
944
- if (check(input)) {
945
- return getSchema2(input, translations);
946
- }
947
- }
948
- return getText(input, translations);
949
- }
950
- function getEmail(input, translations) {
951
- const baseSchema = z.string().trim();
952
- if (input.required) {
953
- const message = getRequiredMessage(input, translations);
954
- const schema = baseSchema.min(1, message).pipe(applyEmail(input, translations));
955
- return z.preprocess((value) => isEmpty(value) ? "" : value, schema);
956
- }
957
- return baseSchema.pipe(applyEmail(input, translations)).or(z.literal("")).nullable();
958
- }
959
- function getBoolean(input, translations) {
960
- let schema = z.coerce.boolean();
961
- if (input.required) {
962
- schema = schema.refine((value) => value === true, {
963
- message: getRequiredMessage(input, translations)
964
- });
965
- return z.preprocess((value) => value === null ? false : value, schema);
966
- }
967
- return schema.nullable();
968
- }
969
- function getRadio(input, translations) {
970
- let schema = z.coerce.string();
971
- if (input.required) {
972
- schema = schema.min(1, getRequiredMessage(input, translations));
973
- return z.preprocess((value) => isEmpty(value) ? "" : value, schema);
974
- }
975
- return schema.or(z.literal("")).nullable();
976
- }
977
- function getText(input, translations) {
978
- let schema = z.coerce.string().trim();
979
- schema = applyMinAndMax(schema, input, translations);
980
- if (input.required) {
981
- schema = applyRequired(schema, input, translations);
982
- return z.preprocess((value) => isEmpty(value) ? "" : value, schema);
983
- }
984
- return schema.nullable();
985
- }
986
- function getNumber(input, translations) {
987
- let schema = z.coerce.number().int();
988
- schema = applyMinAndMax(schema, input, translations);
989
- if (input.required) {
990
- schema = applyRequired(schema, input, translations);
991
- return z.preprocess((value) => value === null ? void 0 : value, schema);
992
- }
993
- return schema.nullable();
994
- }
995
- function getYearSchema(input, translations) {
996
- if (input.required) {
997
- return z.preprocess(
998
- normalize,
999
- z.coerce.number({ message: getRequiredMessage(input, translations) }).int()
1000
- );
1001
- }
1002
- return z.coerce.number().int().nullable();
1003
- }
1004
- function getMonthSchema(input, translations) {
1005
- const message = getRequiredMessage(input, translations);
1006
- const schema = z.coerce.number().int().min(1, message).max(12, message);
1007
- return !input.required ? schema.nullable() : schema;
1008
- }
1009
- function normalize(value) {
1010
- return value === null || value === "" ? void 0 : value;
1011
- }
1012
- function applyEmail(input, translations) {
1013
- const message = input.validation?.email ? translate(input.validation?.email, translations) : void 0;
1014
- return z.email(message);
1015
- }
1016
- function applyMinAndMax(schema, input, translations) {
1017
- schema = min(schema, input, translations);
1018
- schema = max(schema, input, translations);
1019
- return schema;
1020
- }
1021
- function applyRequired(schema, input, translations) {
1022
- const min2 = input.advanced?.length?.min;
1023
- if (min2 === void 0 || min2 < 1) {
1024
- return schema.min(1, getRequiredMessage(input, translations));
1025
- }
1026
- return schema;
1027
- }
1028
- var min = (schema, input, translations) => applyConstraint(schema, input, MIN, translations);
1029
- var max = (schema, input, translations) => applyConstraint(schema, input, MAX, translations);
1030
- function applyConstraint(schema, input, method, translations) {
1031
- const value = input.advanced?.length?.[method];
1032
- if (value !== void 0) {
1033
- const message = input.validation?.length?.[method] ? translate(input.validation?.length?.[method], translations) : void 0;
1034
- return schema[method](value, message);
1035
- }
1036
- return schema;
1037
- }
1038
- function applyCustomValidation(schema, fields = [], translations) {
1039
- const rules = getRules(fields);
1040
- if (rules.length === 0) {
1041
- return schema;
1042
- }
1043
- return schema.superRefine((data, context) => {
1044
- for (const { name, rule } of rules) {
1045
- if (!evaluate(data, name, rule)) {
1046
- const message = translate(rule.message, translations);
1047
- context.addIssue({
1048
- code: "custom",
1049
- message,
1050
- path: [name]
1051
- });
1052
- }
1053
- }
1054
- });
1055
- }
1056
- function evaluate(data, name, rule) {
1057
- const operator = rule.operator ?? "eq";
1058
- const operation = operators[operator];
1059
- if (operation) {
1060
- return operation(data[name], data[rule.field]);
1061
- }
1062
- return false;
1063
- }
1064
- function getRules(fields) {
1065
- const results = [];
1066
- for (const field of fields) {
1067
- const custom = field.validation?.custom;
1068
- if (!custom) {
1069
- continue;
1070
- }
1071
- const rules = Array.isArray(custom) ? custom : [custom];
1072
- for (const rule of rules) {
1073
- results.push({ name: field.name, rule });
1074
- }
1075
- }
1076
- return results;
1077
- }
1078
- function validateCustom(value, rules, getValue3, translations) {
1079
- const errors = [];
1080
- const collections = Array.isArray(rules) ? rules : [rules];
1081
- for (const rule of collections) {
1082
- const operator = rule.operator ?? "eq";
1083
- const operation = operators[operator];
1084
- if (operation && !operation(value, getValue3(rule.field))) {
1085
- if (rule.message) {
1086
- const message = translate(rule.message, translations);
1087
- errors.push(message);
1088
- }
1089
- }
1090
- }
1091
- return errors;
1092
- }
1093
- function getRequiredMessage(input, translations) {
1094
- return input.validation?.required ? translate(input.validation?.required, translations) : void 0;
1095
- }
1096
-
1097
- // ../luna-core/src/util/url.ts
1098
- function matchRemotePattern(urlStr, patterns) {
1099
- if (!patterns || !isExternalUrl(urlStr)) {
1100
- return true;
1101
- }
1102
- if (patterns.length === 0) {
1103
- return false;
1104
- }
1105
- try {
1106
- const url = new URL(urlStr);
1107
- const protocol = url.protocol.replace(":", "");
1108
- const hostname = url.hostname;
1109
- const port = url.port || getPort(protocol);
1110
- return patterns.some((pattern) => {
1111
- if (pattern.protocol && pattern.protocol !== protocol) {
1112
- return false;
1113
- }
1114
- if (pattern.hostname && pattern.hostname !== hostname) {
1115
- return false;
1116
- }
1117
- if (pattern.port !== void 0 && String(pattern.port) !== port) {
1118
- return false;
1119
- }
1120
- return true;
1121
- });
1122
- } catch {
1123
- return false;
1124
- }
1125
- }
1126
- function getPort(protocol) {
1127
- return protocol === "https" ? "443" : "80";
1128
- }
1129
- function isExternalUrl(url) {
1130
- return /^(https?:)?\/\//.test(url);
1131
- }
1132
- function mergeUrl(baseUrl, targetUrl) {
1133
- try {
1134
- if (!baseUrl) {
1135
- return targetUrl;
1136
- }
1137
- if (!targetUrl) {
1138
- return baseUrl;
1139
- }
1140
- const url1 = new URL(baseUrl, COMMON_URL);
1141
- const url2 = new URL(targetUrl, COMMON_URL);
1142
- url2.searchParams.forEach((value, key) => {
1143
- url1.searchParams.set(key, value);
1144
- });
1145
- const result = url1.toString();
1146
- return baseUrl.startsWith("/") || !baseUrl.includes("://") ? result.replace(COMMON_URL, "") : result;
1147
- } catch {
1148
- return targetUrl || baseUrl;
1149
- }
1150
- }
1151
-
1152
- // ../luna-core/src/util/source.ts
1153
- function mergeSource(sources) {
1154
- if (!Array.isArray(sources) || sources.length === 0) {
1155
- return null;
1156
- }
1157
- return sources.reduce((previous, current) => {
1158
- const url = mergeUrl(previous.url, current.url);
1159
- const body = getBody(previous, current);
1160
- const headers = getHeaders(previous, current);
1161
- return {
1162
- ...previous,
1163
- ...current,
1164
- url,
1165
- body,
1166
- headers
1167
- };
1168
- });
1169
- }
1170
- function getBody(previous, current) {
1171
- if (isObject(current.body) && isObject(previous?.body)) {
1172
- return {
1173
- ...previous.body,
1174
- ...current.body
1175
- };
1176
- }
1177
- return current.body ?? previous?.body;
1178
- }
1179
- function getHeaders(previous, current) {
1180
- if (isObject(current.headers) && isObject(previous?.headers)) {
1181
- return {
1182
- ...previous.headers,
1183
- ...current.headers
1184
- };
1185
- }
1186
- return current.headers ?? previous?.headers;
1187
- }
1188
-
1189
- // ../luna-core/src/util/style.ts
1190
- function mergeStyle(globalStyle, localStyle) {
1191
- return { ...globalStyle, ...localStyle };
1192
- }
1193
-
1194
- // src/lib/string.tsx
1195
- import { jsx as jsx3 } from "react/jsx-runtime";
1196
- function formatMarkdown2(text) {
1197
- return formatMarkdown(
1198
- text,
1199
- (index, url, text2) => {
1200
- return /* @__PURE__ */ jsx3(
1201
- "a",
1202
- {
1203
- className: "underline",
1204
- href: url,
1205
- rel: "noopener noreferrer",
1206
- target: "_blank",
1207
- children: text2
1208
- },
1209
- `${url}-${index}`
1210
- );
1211
- }
1212
- );
1213
- }
1214
-
1215
- // src/component/field/field-set-advanced.tsx
1216
- import { jsx as jsx4, jsxs } from "react/jsx-runtime";
1217
- function FieldSetAdvanced(props) {
1218
- const { fields = [] } = props.section;
1219
- const [isOpen, setIsOpen] = useState(false);
1220
- const handleOpen = useCallback(() => setIsOpen((previous) => !previous), []);
1221
- return /* @__PURE__ */ jsxs(
1222
- "fieldset",
1223
- {
1224
- "data-slot": "field-set",
1225
- "data-advanced": "true",
1226
- "data-expanded": isOpen,
1227
- "data-empty": fields.length === 0,
1228
- className: "flex flex-col",
1229
- id: props.section.id?.toString(),
1230
- children: [
1231
- /* @__PURE__ */ jsx4("legend", { children: /* @__PURE__ */ jsxs(
1232
- "button",
1233
- {
1234
- className: "flex cursor-pointer items-center gap-2 text-base font-medium text-slate-600 dark:text-slate-400",
1235
- onClick: handleOpen,
1236
- type: "button",
1237
- children: [
1238
- /* @__PURE__ */ jsx4(ChevronIcon, { expanded: isOpen }),
1239
- /* @__PURE__ */ jsx4("span", { children: formatMarkdown2(props.section.title) })
1240
- ]
1241
- }
1242
- ) }),
1243
- /* @__PURE__ */ jsx4(Activity, { mode: isOpen ? "visible" : "hidden", children: /* @__PURE__ */ jsxs(
1244
- "div",
1245
- {
1246
- className: "mt-3 ml-1.5 flex flex-col gap-4 border-l-2 border-slate-300 pl-4 dark:border-slate-600",
1247
- "data-slot": "field-set-content",
1248
- children: [
1249
- props.section.description && /* @__PURE__ */ jsx4("p", { className: "text-sm leading-normal font-normal text-slate-600 dark:text-slate-400", children: formatMarkdown2(props.section.description) }),
1250
- props.group
1251
- ]
1252
- }
1253
- ) })
1254
- ]
1255
- }
1256
- );
1257
- }
1258
-
1259
- // src/component/legend.tsx
1260
- import { Fragment, jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
1261
- function Legend(props) {
1262
- return /* @__PURE__ */ jsxs2(Fragment, { children: [
1263
- props.title && /* @__PURE__ */ jsx5("legend", { className: "mb-3 font-medium text-slate-800 dark:text-slate-200", children: formatMarkdown2(props.title) }),
1264
- props.description && /* @__PURE__ */ jsx5("p", { className: "-mt-2 text-sm leading-normal font-normal text-slate-600 dark:text-slate-400", children: formatMarkdown2(props.description) })
1265
- ] });
1266
- }
1267
-
1268
- // src/component/field/field-set-base.tsx
1269
- import { jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
1270
- function FieldSetBase(props) {
1271
- return /* @__PURE__ */ jsxs3(
1272
- "fieldset",
1273
- {
1274
- "data-slot": "field-set",
1275
- "data-empty": props.empty,
1276
- className: "flex flex-col data-[empty=false]:gap-6",
1277
- id: props.id,
1278
- children: [
1279
- /* @__PURE__ */ jsx6(Legend, { description: props.description, title: props.title }),
1280
- props.children
1281
- ]
1282
- }
1283
- );
1284
- }
1285
-
1286
- // src/component/group.tsx
1287
- import { jsx as jsx7 } from "react/jsx-runtime";
1288
- function Group(props) {
1289
- return /* @__PURE__ */ jsx7(
1290
- "div",
1291
- {
1292
- "data-slot": "field-group",
1293
- "data-compact": props.compact,
1294
- className: "flex w-full flex-col gap-8 data-[compact=true]:gap-3",
1295
- children: props.children
1296
- }
1297
- );
1298
- }
1299
-
1300
- // src/component/field/field-set.tsx
1301
- import { jsx as jsx8 } from "react/jsx-runtime";
1302
- function FieldSet(props) {
1303
- const { fields = [] } = props.section;
1304
- const { compact } = mergeStyle(props.style, {
1305
- compact: props.section.compact
1306
- });
1307
- const group = /* @__PURE__ */ jsx8(Group, { compact, children: props.children });
1308
- if (!props.section.title && !props.section.description) {
1309
- return group;
1310
- }
1311
- if (props.section.advanced) {
1312
- return /* @__PURE__ */ jsx8(FieldSetAdvanced, { section: props.section, group });
1313
- }
1314
- return /* @__PURE__ */ jsx8(
1315
- FieldSetBase,
1316
- {
1317
- description: props.section.description,
1318
- empty: fields.length === 0,
1319
- id: props.section.id?.toString(),
1320
- title: props.section.title,
1321
- children: group
1322
- }
1323
- );
1324
- }
1325
-
1326
- // src/client/component/guard/visibility-guard.tsx
1327
- import { useAtomValue } from "jotai";
1328
-
1329
- // src/client/lib/store-helper.ts
1330
- import { atom } from "jotai";
1331
- import { atomFamily } from "jotai-family";
1332
- import { deepEqual } from "fast-equals";
1333
- function createRecordAtomFamily(baseAtom) {
1334
- return atomFamily(
1335
- (name) => atom(
1336
- (get) => {
1337
- return get(baseAtom)[name] ?? void 0;
1338
- },
1339
- (get, set, newValue) => {
1340
- const current = get(baseAtom);
1341
- if (newValue !== void 0 && newValue !== null) {
1342
- const currentValue = current[name];
1343
- if (!currentValue || !deepEqual(currentValue, newValue)) {
1344
- set(baseAtom, { ...current, [name]: newValue });
1345
- }
1346
- } else if (current[name]) {
1347
- const { [name]: _unused, ...rest } = current;
1348
- set(baseAtom, rest);
1349
- }
1350
- }
1351
- )
1352
- );
1353
- }
1354
- function createClearAllAtom(baseAtom) {
1355
- return atom(null, (get, set) => {
1356
- const current = get(baseAtom);
1357
- if (current && Object.keys(current).length > 0) {
1358
- set(baseAtom, {});
1359
- }
1360
- });
1361
- }
1362
- function createClearAtom(baseAtom) {
1363
- return atom(null, (get, set, names) => {
1364
- const current = get(baseAtom);
1365
- const next = { ...current };
1366
- let hasChanges = false;
1367
- for (const name of names) {
1368
- if (next[name]) {
1369
- delete next[name];
1370
- hasChanges = true;
1371
- }
1372
- }
1373
- if (hasChanges) {
1374
- set(baseAtom, next);
1375
- }
1376
- });
1377
- }
1378
- function createBulkReportAtom(baseAtom) {
1379
- return atom(null, (get, set, newValue) => {
1380
- const current = get(baseAtom);
1381
- if (!deepEqual(current, newValue)) {
1382
- set(baseAtom, newValue);
1383
- }
1384
- });
1385
- }
1386
- function createNestedRecordAtomFamily(baseAtom, options = {}) {
1387
- const { merge: merge2, validateTarget } = options;
1388
- return atomFamily(
1389
- (contributorName) => atom(
1390
- (get) => {
1391
- const current = get(baseAtom)[contributorName];
1392
- if (current && merge2) {
1393
- return merge2(Object.values(current));
1394
- }
1395
- return void 0;
1396
- },
1397
- (get, set, target, value) => {
1398
- if (validateTarget && !validateTarget(target)) {
1399
- return;
1400
- }
1401
- const current = get(baseAtom);
1402
- const targetContributions = { ...current[target] ?? {} };
1403
- if (value !== void 0 && value !== null) {
1404
- const currentContribution = targetContributions[contributorName];
1405
- if (!currentContribution || !deepEqual(currentContribution, value)) {
1406
- targetContributions[contributorName] = value;
1407
- set(baseAtom, {
1408
- ...current,
1409
- [target]: targetContributions
1410
- });
1411
- }
1412
- } else if (targetContributions[contributorName]) {
1413
- delete targetContributions[contributorName];
1414
- if (Object.keys(targetContributions).length === 0) {
1415
- const { [target]: _unused, ...rest } = current;
1416
- set(baseAtom, rest);
1417
- } else {
1418
- set(baseAtom, {
1419
- ...current,
1420
- [target]: targetContributions
1421
- });
1422
- }
1423
- }
1424
- }
1425
- )
1426
- );
1427
- }
1428
- function createNestedClearAtom(baseAtom) {
1429
- return atom(null, (get, set, contributorNames) => {
1430
- const current = get(baseAtom);
1431
- const next = { ...current };
1432
- let hasChanges = false;
1433
- for (const name of contributorNames) {
1434
- if (next[name]) {
1435
- delete next[name];
1436
- hasChanges = true;
1437
- }
1438
- }
1439
- for (const target in next) {
1440
- const targetContributions = { ...next[target] };
1441
- let targetChanged = false;
1442
- for (const contributorName of contributorNames) {
1443
- if (targetContributions[contributorName]) {
1444
- delete targetContributions[contributorName];
1445
- targetChanged = true;
1446
- hasChanges = true;
1447
- }
1448
- }
1449
- if (targetChanged) {
1450
- if (Object.keys(targetContributions).length === 0) {
1451
- delete next[target];
1452
- } else {
1453
- next[target] = targetContributions;
1454
- }
1455
- }
1456
- }
1457
- if (hasChanges) {
1458
- set(baseAtom, next);
1459
- }
1460
- });
1461
- }
1462
- function createAtomStore(initialValue = {}) {
1463
- const baseAtom = atom(initialValue);
1464
- return {
1465
- atom: baseAtom,
1466
- clearAll: createClearAllAtom(baseAtom),
1467
- clear: createClearAtom(baseAtom),
1468
- bulkReport: createBulkReportAtom(baseAtom),
1469
- report: createRecordAtomFamily(baseAtom)
1470
- };
1471
- }
1472
-
1473
- // src/client/lib/state-store.ts
1474
- var store = createAtomStore();
1475
- var fieldStateAtom = store.atom;
1476
- var reportFieldStateAtom = store.report;
1477
-
1478
- // src/client/component/guard/visibility-guard.tsx
1479
- function isColumnHidden(column, states) {
1480
- return column.fields.every((field) => isFieldHidden(field, states));
1481
- }
1482
- function isFieldHidden(field, states) {
1483
- return states[field.name]?.hidden ?? field.hidden ?? false;
1484
- }
1485
- function isEntryHidden(entry, states) {
1486
- return isColumn(entry) ? isColumnHidden(entry, states) : isFieldHidden(entry, states);
1487
- }
1488
- function VisibilityGuard(props) {
1489
- const states = useAtomValue(fieldStateAtom);
1490
- if (props.container) {
1491
- const hidden = states[props.container.name]?.hidden ?? props.container.hidden ?? false;
1492
- if (hidden) {
1493
- return null;
1494
- }
1495
- }
1496
- if (props.fields.length === 0) {
1497
- return null;
1498
- }
1499
- const allHidden = props.fields.every((entry) => isEntryHidden(entry, states));
1500
- if (allHidden) {
1501
- return null;
1502
- }
1503
- return props.children;
1504
- }
1505
-
1506
- // src/component/separator.tsx
1507
- import { jsx as jsx9 } from "react/jsx-runtime";
1508
- function Separator() {
1509
- return /* @__PURE__ */ jsx9("div", { "data-slot": "field-separator", className: "relative -my-2 h-5 text-sm", children: /* @__PURE__ */ jsx9("div", { className: "absolute inset-0 top-1/2 h-px w-full bg-slate-200 dark:bg-slate-800" }) });
1510
- }
1511
-
1512
- // src/component/form.tsx
1513
- import { jsx as jsx10, jsxs as jsxs4 } from "react/jsx-runtime";
1514
- function Form(props) {
1515
- const sections = prepare(props.sections, props.definition);
1516
- return /* @__PURE__ */ jsx10("div", { className: "h-full w-full", children: /* @__PURE__ */ jsx10("form", { noValidate: props.noValidate, action: props.action, children: /* @__PURE__ */ jsxs4(Group, { children: [
1517
- sections.map((section, index) => /* @__PURE__ */ jsxs4(VisibilityGuard, { fields: section.fields ?? [], children: [
1518
- /* @__PURE__ */ jsx10(FieldSet, { section, style: props.config.style, children: props.children({
1519
- disabled: props.readOnly,
1520
- fields: section.fields
1521
- }) }),
1522
- section.separator && /* @__PURE__ */ jsx10(Separator, {})
1523
- ] }, index)),
1524
- props.control && /* @__PURE__ */ jsx10(Control, { isPending: props.isPending, children: props.control })
1525
- ] }) }) });
1526
- }
1527
-
1528
- // src/component/description.tsx
1529
- import { jsx as jsx11 } from "react/jsx-runtime";
1530
- function Description(props) {
1531
- return /* @__PURE__ */ jsx11("p", { className: "-mt-2 text-xs leading-normal font-normal text-slate-600 dark:text-slate-400", children: props.children });
1532
- }
1533
-
1534
- // src/component/formatted-description.tsx
1535
- import { jsx as jsx12 } from "react/jsx-runtime";
1536
- function FormattedDescription(props) {
1537
- const content = formatMarkdown2(props.text);
1538
- if (content) {
1539
- return /* @__PURE__ */ jsx12(Description, { children: content });
1540
- }
1541
- return null;
1542
- }
1543
-
1544
- // src/component/label.tsx
1545
- import { twMerge } from "tailwind-merge";
1546
- import { jsx as jsx13, jsxs as jsxs5 } from "react/jsx-runtime";
1547
- function Label(props) {
1548
- const showOptionalLabel = props.style?.showOptionalLabel ?? true;
1549
- const normal = isRadio(props.field) || isCheckbox(props.field);
1550
- return /* @__PURE__ */ jsxs5(
1551
- "label",
1552
- {
1553
- "data-slot": "field-label",
1554
- "data-normal": normal,
1555
- className: twMerge(
1556
- "flex w-fit items-center gap-2 text-sm leading-snug font-medium select-none",
1557
- "data-[normal=true]:font-normal",
1558
- "group-data-[readonly=true]:cursor-not-allowed group-data-[readonly=true]:opacity-50"
1559
- ),
1560
- htmlFor: props.field.name,
1561
- children: [
1562
- props.children,
1563
- showOptionalLabel && !props.field.required && /* @__PURE__ */ jsx13("span", { className: "text-sm text-slate-600 dark:text-slate-400", children: translate("(Optional)", props.translations) })
1564
- ]
1565
- }
1566
- );
1567
- }
1568
-
1569
- // src/component/input-label.tsx
1570
- import { jsx as jsx14, jsxs as jsxs6 } from "react/jsx-runtime";
1571
- function InputLabel(props) {
1572
- const interpolateOpts = {
1573
- context: props.context,
1574
- env: props.config?.env
1575
- };
1576
- const label = interpolateIfNeeded(props.field.label, interpolateOpts);
1577
- const description = interpolateIfNeeded(
1578
- props.field.description,
1579
- interpolateOpts
1580
- );
1581
- return /* @__PURE__ */ jsxs6(
1582
- "div",
1583
- {
1584
- "data-slot": "field-content",
1585
- className: "flex w-full flex-1 flex-col gap-1.5 leading-snug",
1586
- children: [
1587
- /* @__PURE__ */ jsx14(
1588
- Label,
1589
- {
1590
- field: props.field,
1591
- style: props.config?.style,
1592
- translations: props.translations,
1593
- children: translate(label, props.translations)
1594
- }
1595
- ),
1596
- props.orientation === HORIZONTAL && /* @__PURE__ */ jsx14(
1597
- FormattedDescription,
1598
- {
1599
- text: translate(description, props.translations)
1600
- }
1601
- )
1602
- ]
1603
- }
1604
- );
1605
- }
1606
-
1607
- // src/component/input-group.tsx
1608
- import { Fragment as Fragment2, jsx as jsx15, jsxs as jsxs7 } from "react/jsx-runtime";
1609
- function InputGroup(props) {
1610
- return /* @__PURE__ */ jsxs7(Fragment2, { children: [
1611
- props.field.name && props.field.label && /* @__PURE__ */ jsx15(
1612
- InputLabel,
1613
- {
1614
- config: props.config,
1615
- context: props.context,
1616
- field: props.field,
1617
- orientation: props.orientation,
1618
- translations: props.translations
1619
- }
1620
- ),
1621
- props.children,
1622
- props.orientation === VERTICAL && props.field.description && /* @__PURE__ */ jsx15(
1623
- FormattedDescription,
1624
- {
1625
- text: translate(props.field.description, props.translations)
1626
- }
1627
- )
1628
- ] });
1629
- }
1630
-
1631
- // src/lib/render-If-exists.ts
1632
- function renderIfExists(value, render) {
1633
- if (!value) {
1634
- return null;
1635
- }
1636
- return render(value);
1637
- }
1638
-
1639
- // src/client/lib/error-store.ts
1640
- var store2 = createAtomStore();
1641
- var clearInputErrorAtom = store2.clear;
1642
- var reportErrorAtom = store2.bulkReport;
1643
- var reportInputErrorAtom = store2.report;
1644
-
1645
- // src/client/component/input.tsx
1646
- import { useCallback as useCallback4, useRef as useRef3, useTransition } from "react";
1647
-
1648
- // src/client/lib/source-store.ts
1649
- import { atom as atom2 } from "jotai";
1650
- var merge = (values) => {
1651
- const merged = mergeSource(values);
1652
- if (merged) {
1653
- return merged;
1654
- }
1655
- return void 0;
1656
- };
1657
- var validate = (target) => target.trim() !== "";
1658
- var sourceAtom = atom2({});
1659
- var reportSourceAtom = createNestedRecordAtomFamily(
1660
- sourceAtom,
1661
- {
1662
- merge,
1663
- validateTarget: validate
1664
- }
1665
- );
1666
- var clearInputSourceAtom = createNestedClearAtom(sourceAtom);
1667
-
1668
- // src/client/hook/use-data-source.ts
1669
- import { useAtom } from "jotai";
1670
-
1671
- // src/client/hook/use-fetch.ts
1672
- import useSWR from "swr";
1673
- function useFetch(dataSource = null, config, disabled = false) {
1674
- const { data, error } = useSWR(
1675
- buildSource2(dataSource, config, disabled),
1676
- config.fetcher.provider
1677
- );
1678
- if (error) {
1679
- logger.error("Error fetching data source:", error);
1680
- }
1681
- if (dataSource) {
1682
- if (Array.isArray(dataSource)) {
1683
- return dataSource;
1684
- }
1685
- if (data) {
1686
- return getArray(data, dataSource.namespace);
1687
- }
1688
- }
1689
- return null;
1690
- }
1691
- function buildSource2(dataSource = null, config, disabled = false) {
1692
- if (dataSource && !Array.isArray(dataSource) && !disabled) {
1693
- if (dataSource.url) {
1694
- const interpolated = isInterpolated(dataSource.url);
1695
- if (!interpolated) {
1696
- const allowed = matchRemotePattern(
1697
- dataSource.url,
1698
- config.fetcher.remotePatterns
1699
- );
1700
- if (allowed) {
1701
- return dataSource;
1702
- }
1703
- logger.warn(
1704
- `URL blocked by remotePatterns: ${dataSource.url}. Check your luna.config.ts`
1705
- );
1706
- }
1707
- }
1708
- }
1709
- return null;
1710
- }
1711
-
1712
- // src/client/hook/use-data-source.ts
1713
- function useDataSource(field, config, value) {
1714
- const dataSource = resolveSource(field, value);
1715
- const [source, setSource] = useAtom(reportSourceAtom(field.name));
1716
- const currentSource = source ?? dataSource;
1717
- const data = useFetch(currentSource, config, field.disabled);
1718
- return [data, setSource];
1719
- }
1720
-
1721
- // src/client/hook/use-input.ts
1722
- import { useEffect, useEffectEvent, useMemo } from "react";
1723
- function useInput(field, onMount, onUnmount, translations) {
1724
- const { name } = field;
1725
- const schema = useMemo(
1726
- () => getSchema(field, translations),
1727
- [field, translations]
1728
- );
1729
- const onMountHandler = useEffectEvent((name2) => {
1730
- if (name2) {
1731
- onMount(name2, schema, field);
1732
- }
1733
- });
1734
- const onUnmountHandler = useEffectEvent((name2) => {
1735
- if (name2) {
1736
- onUnmount(name2);
1737
- }
1738
- });
1739
- useEffect(() => {
1740
- onMountHandler(name);
1741
- return () => {
1742
- onUnmountHandler(name);
1743
- };
1744
- }, [name]);
1745
- return schema;
1746
- }
1747
-
1748
- // src/client/component/input.tsx
1749
- import { useSetAtom, useStore } from "jotai";
1750
-
1751
- // src/client/hook/use-timeout.ts
1752
- import { useCallback as useCallback2, useEffect as useEffect2, useRef } from "react";
1753
- function useTimeout() {
1754
- const timeoutRef = useRef(null);
1755
- useEffect2(() => {
1756
- return () => {
1757
- if (timeoutRef.current) {
1758
- clearTimeout(timeoutRef.current);
1759
- }
1760
- };
1761
- }, []);
1762
- const setTimeoutRef = useCallback2((callback, delay) => {
1763
- if (timeoutRef.current) {
1764
- clearTimeout(timeoutRef.current);
1765
- timeoutRef.current = null;
1766
- }
1767
- timeoutRef.current = setTimeout(callback, delay);
1768
- }, []);
1769
- return setTimeoutRef;
1770
- }
1771
-
1772
- // src/client/lib/value-store.ts
1773
- var store3 = createAtomStore();
1774
- var valueAtom = store3.atom;
1775
- var clearAllValueAtom = store3.clearAll;
1776
- var clearInputValueAtom = store3.clear;
1777
- var reportValueAtom = store3.report;
1778
-
1779
- // src/client/hook/use-value.ts
1780
- import { useAtom as useAtom2 } from "jotai";
1781
- import { useCallback as useCallback3, useEffect as useEffect3, useRef as useRef2, useEffectEvent as useEffectEvent2 } from "react";
1782
- function useValue(field, currentValue) {
1783
- const { name } = field;
1784
- const skipNextOnChangeRef = useRef2(false);
1785
- const [value, setValue] = useAtom2(reportValueAtom(name));
1786
- const onCurrentValueChange = useEffectEvent2(
1787
- (currentValue2) => {
1788
- const newValue = resolveValue(name, currentValue2);
1789
- if (isValidValue(newValue)) {
1790
- skipNextOnChangeRef.current = true;
1791
- setValue(newValue);
1792
- }
1793
- }
1794
- );
1795
- useEffect3(() => {
1796
- if (!currentValue) {
1797
- return;
1798
- }
1799
- onCurrentValueChange(currentValue);
1800
- }, [currentValue]);
1801
- const shouldSkipOnChange = useCallback3(() => {
1802
- if (skipNextOnChangeRef.current) {
1803
- skipNextOnChangeRef.current = false;
1804
- return true;
1805
- }
1806
- return false;
1807
- }, []);
1808
- return {
1809
- setValue,
1810
- shouldSkipOnChange,
1811
- value
1812
- };
1813
- }
1814
- function resolveValue(name, currentValue) {
1815
- if (name in currentValue) {
1816
- return currentValue[name];
1817
- }
1818
- if (!name.includes(".")) {
1819
- return void 0;
1820
- }
1821
- const keys = name.split(".");
1822
- let result = currentValue;
1823
- for (const key of keys) {
1824
- if (result === null || result === void 0) {
1825
- return void 0;
1826
- }
1827
- if (Array.isArray(result)) {
1828
- const index = Number(key);
1829
- result = Number.isInteger(index) ? result[index] : void 0;
1830
- } else if (typeof result === "object") {
1831
- result = result[key];
1832
- } else {
1833
- return void 0;
1834
- }
1835
- }
1836
- return result;
1837
- }
1838
-
1839
- // src/client/component/input.tsx
1840
- import { jsx as jsx16 } from "react/jsx-runtime";
1841
- function Input(props) {
1842
- const entity = props.field.advanced?.entity;
1843
- const store4 = useStore();
1844
- const setTimeoutRef = useTimeout();
1845
- const [, startTransition2] = useTransition();
1846
- const { setValue, shouldSkipOnChange, value } = useValue(
1847
- props.field,
1848
- props.value
1849
- );
1850
- const valueRef = useRef3(value);
1851
- valueRef.current = value;
1852
- const translationsRef = useRef3(props.translations);
1853
- translationsRef.current = props.translations;
1854
- const hasTextable = isTextable(props.field);
1855
- const hasClickable = isClickable(props.field);
1856
- const setValues = useSetAtom(valueAtom);
1857
- const setFieldStates = useSetAtom(fieldStateAtom);
1858
- const setErrors = useSetAtom(reportInputErrorAtom(props.field.name));
1859
- const [data, setSource] = useDataSource(props.field, props.config, value);
1860
- const schema = useInput(
1861
- props.field,
1862
- props.onMount,
1863
- props.onUnmount,
1864
- props.translations
1865
- );
1866
- const placeholder = translate(
1867
- props.commonProps.placeholder,
1868
- props.translations
1869
- );
1870
- const commonProps = {
1871
- ...props.commonProps,
1872
- placeholder
1873
- };
1874
- const { commonPropsWithOptions, defaultValue } = prepareInputProps(
1875
- props.field,
1876
- commonProps,
1877
- data,
1878
- value
1879
- );
1880
- const onValueChangeRef = useRef3(null);
1881
- onValueChangeRef.current = (value2) => {
1882
- setValue(value2);
1883
- if (props.onValueChange) {
1884
- props.onValueChange({ name: props.field.name, value: value2 });
1885
- }
1886
- };
1887
- const inputProps = prepareInputValue(props.field, defaultValue);
1888
- const validated = useCallback4(
1889
- (value2) => {
1890
- const results = schema.safeParse(value2);
1891
- const errors = results.error?.issues.map((issue) => issue.message) ?? [];
1892
- const custom = props.field.validation?.custom;
1893
- const customErrors = custom ? validateCustom(
1894
- value2,
1895
- custom,
1896
- (name) => store4.get(reportValueAtom(name)),
1897
- translationsRef.current
1898
- ) : [];
1899
- setErrors([...errors, ...customErrors]);
1900
- },
1901
- [props.field.validation?.custom, schema, setErrors, store4]
1902
- );
1903
- const handleTriggerEvent = useCallback4(
1904
- (value2, callback) => {
1905
- if (hasTextable) {
1906
- setTimeoutRef(() => {
1907
- callback({ value: value2 });
1908
- }, 500);
1909
- return;
1910
- }
1911
- callback(getEntity(value2, data, entity));
1912
- },
1913
- [data, entity, hasTextable, setTimeoutRef]
1914
- );
1915
- const onChange = useCallback4(
1916
- (event) => {
1917
- const inputValue = event.target.value;
1918
- if (!hasClickable && shouldSkipOnChange()) {
1919
- if (!hasTextable || inputValue === valueRef.current) {
1920
- return;
1921
- }
1922
- }
1923
- onValueChangeRef.current?.(inputValue);
1924
- if (props.config.validation.change) {
1925
- validated(inputValue);
1926
- }
1927
- const events = props.field.event?.change;
1928
- if (events) {
1929
- handleTriggerEvent(inputValue, (selected) => {
1930
- handleProxyEvent(events, ({ sources, states, values }) => {
1931
- startTransition2(() => {
1932
- handleSourceEvent(
1933
- selected,
1934
- sources,
1935
- (target, source) => setSource(target, source)
1936
- );
1937
- handleStateEvent(selected, states, (targets, state) => {
1938
- logger.info(
1939
- `Setting field states for targets: ${targets.join(
1940
- ", "
1941
- )} with state: ${JSON.stringify(state)}`
1942
- );
1943
- setFieldStates((prev) => {
1944
- if (state) {
1945
- return targets.reduce(
1946
- (acc, target) => ({
1947
- ...acc,
1948
- [target]: state
1949
- }),
1950
- prev
1951
- );
1952
- }
1953
- return targets.reduce((acc, target) => {
1954
- const { [target]: _removed, ...rest } = acc;
1955
- return rest;
1956
- }, prev);
1957
- });
1958
- });
1959
- handleValueEvent(selected, values, (target, value2) => {
1960
- setValues((prev) => ({
1961
- ...prev,
1962
- [target]: value2
1963
- }));
1964
- });
1965
- });
1966
- });
1967
- });
1968
- }
1969
- },
1970
- [
1971
- handleTriggerEvent,
1972
- hasClickable,
1973
- hasTextable,
1974
- props.config.validation.change,
1975
- props.field.event?.change,
1976
- setFieldStates,
1977
- setSource,
1978
- setValues,
1979
- shouldSkipOnChange,
1980
- validated
1981
- ]
1982
- );
1983
- const onBlur = useCallback4(
1984
- (event) => {
1985
- if (!hasClickable) {
1986
- const value2 = event.target.value;
1987
- if (props.config.validation.blur) {
1988
- validated(value2);
1989
- }
1990
- }
1991
- },
1992
- [hasClickable, props.config.validation.blur, validated]
1993
- );
1994
- return renderIfExists(props.config.inputs[props.field.type], (Component) => /* @__PURE__ */ jsx16(
1995
- InputGroup,
1996
- {
1997
- config: props.config,
1998
- context: props.context,
1999
- field: props.field,
2000
- orientation: props.orientation,
2001
- translations: props.translations,
2002
- children: /* @__PURE__ */ jsx16(
2003
- Component,
2004
- {
2005
- ...commonPropsWithOptions,
2006
- ...props.ariaAttributes,
2007
- ...props.dataAttributes,
2008
- ...inputProps,
2009
- onBlur,
2010
- onChange
2011
- }
2012
- )
2013
- }
2014
- ));
2015
- }
2016
-
2017
- // src/component/field/field-error.tsx
2018
- import { jsx as jsx17 } from "react/jsx-runtime";
2019
- function FieldError(props) {
2020
- if (!props.errors || props.errors.length === 0) {
2021
- return null;
2022
- }
2023
- return /* @__PURE__ */ jsx17(
2024
- "ul",
2025
- {
2026
- className: "text-sm text-red-600 dark:text-red-500",
2027
- id: props.name ? `${props.name}-error` : void 0,
2028
- children: props.errors?.map((error, index) => /* @__PURE__ */ jsx17("li", { children: error }, props.name ? `${props.name}-error-${index}` : index))
2029
- }
2030
- );
2031
- }
2032
-
2033
- // src/component/field/field-base.tsx
2034
- import { twMerge as twMerge2 } from "tailwind-merge";
2035
- import { jsx as jsx18 } from "react/jsx-runtime";
2036
- function FieldBase(props) {
2037
- const errors = props.errors && props.errors.length > 0;
2038
- return /* @__PURE__ */ jsx18(
2039
- "div",
2040
- {
2041
- "data-slot": "field",
2042
- "data-clickable": props.isClickable ? "true" : "false",
2043
- ...errors && { [DATA_INVALID]: "true" },
2044
- ...props.disabled && { [DATA_READONLY]: "true" },
2045
- "data-orientation": props.orientation,
2046
- className: twMerge2(
2047
- "group flex w-full flex-col items-center data-[invalid=true]:text-red-600 data-[invalid=true]:dark:text-red-500",
2048
- "data-[clickable=true]:items-start",
2049
- props.isCheckbox && (props.isReversed ? "flex-row-reverse!" : "flex-row!"),
2050
- "data-[clickable=true]:has-[>[data-slot=field-content]]:[&>:first-child]:mt-px",
2051
- props.className
2052
- ),
2053
- children: props.children
2054
- }
2055
- );
2056
- }
2057
-
2058
- // src/component/field/field-vertical.tsx
2059
- import { twMerge as twMerge3 } from "tailwind-merge";
2060
- import { jsx as jsx19 } from "react/jsx-runtime";
2061
- function FieldVertical(props) {
2062
- return /* @__PURE__ */ jsx19(
2063
- FieldBase,
2064
- {
2065
- ...props,
2066
- orientation: VERTICAL,
2067
- className: twMerge3(
2068
- "gap-3 has-[>[data-slot=field-content]]:items-start",
2069
- !props.isClickable && "[&>*]:w-full"
2070
- ),
2071
- children: props.children
2072
- }
2073
- );
2074
- }
2075
-
2076
- // src/component/field/field-horizontal.tsx
2077
- import { twMerge as twMerge4 } from "tailwind-merge";
2078
- import { jsx as jsx20 } from "react/jsx-runtime";
2079
- function FieldHorizontal(props) {
2080
- return /* @__PURE__ */ jsx20(
2081
- FieldBase,
2082
- {
2083
- ...props,
2084
- orientation: HORIZONTAL,
2085
- className: twMerge4(
2086
- "gap-2 md:flex-row md:gap-4",
2087
- "[&>[data-slot=field-content]]:min-w-0 [&>[data-slot=field-content]]:flex-grow [&>[data-slot=field-content]]:self-start",
2088
- "[&_[role=checkbox]]:mt-[1.5px]",
2089
- props.isClickable && "md:flex-col",
2090
- !props.isClickable && [
2091
- "md:justify-between",
2092
- "[&>*:not([data-slot=field-content])]:w-full",
2093
- "[&>*:not([data-slot=field-content])]:md:w-1/2",
2094
- "[&>*:not([data-slot=field-content])]:xl:w-2/5"
2095
- ]
2096
- ),
2097
- children: props.children
2098
- }
2099
- );
2100
- }
2101
-
2102
- // src/component/field/field-group.tsx
2103
- import { jsx as jsx21 } from "react/jsx-runtime";
2104
- function FieldGroup(props) {
2105
- const clickable = isClickable(props.field);
2106
- const checkbox = isCheckbox(props.field);
2107
- const reversed = buildReverse(props.field);
2108
- if (props.orientation === VERTICAL) {
2109
- return /* @__PURE__ */ jsx21(
2110
- FieldVertical,
2111
- {
2112
- disabled: props.disabled,
2113
- errors: props.errors,
2114
- isCheckbox: checkbox,
2115
- isReversed: reversed,
2116
- isClickable: clickable,
2117
- children: props.children
2118
- }
2119
- );
2120
- }
2121
- return /* @__PURE__ */ jsx21(
2122
- FieldHorizontal,
2123
- {
2124
- disabled: props.disabled,
2125
- errors: props.errors,
2126
- isCheckbox: checkbox,
2127
- isReversed: reversed,
2128
- isClickable: clickable,
2129
- children: props.children
2130
- }
2131
- );
2132
- }
2133
-
2134
- // src/component/input/input-base.tsx
2135
- function InputBase(props) {
2136
- if (!props.field.type) {
2137
- return null;
2138
- }
2139
- const commonProps = buildCommon(props.field, props.disabled);
2140
- const dataAttributes = buildDataAttributes(props.field);
2141
- const ariaAttributes = buildAriaAttributes(props.field, props.errors);
2142
- const field = {
2143
- ...props.field,
2144
- disabled: commonProps.disabled
2145
- };
2146
- return props.children({
2147
- ariaAttributes,
2148
- commonProps,
2149
- dataAttributes,
2150
- field,
2151
- orientation: props.orientation
2152
- });
2153
- }
2154
-
2155
- // src/component/field/field.tsx
2156
- import { twMerge as twMerge5 } from "tailwind-merge";
2157
- import { jsx as jsx22, jsxs as jsxs8 } from "react/jsx-runtime";
2158
- function Field(props) {
2159
- const cols2 = props.field.advanced?.cols;
2160
- const errors = props.field.name ? props.errors?.[props.field.name] : void 0;
2161
- const { orientation } = mergeStyle(props.style, {
2162
- orientation: buildOrientation(props.field)
2163
- });
2164
- const disabled = buildDisabled(props.field, props.disabled);
2165
- return /* @__PURE__ */ jsxs8("div", { className: twMerge5("flex flex-col gap-3", getSpan(cols2)), children: [
2166
- /* @__PURE__ */ jsx22(
2167
- FieldGroup,
2168
- {
2169
- disabled,
2170
- errors,
2171
- field: props.field,
2172
- orientation,
2173
- children: /* @__PURE__ */ jsx22(
2174
- InputBase,
2175
- {
2176
- disabled,
2177
- errors,
2178
- field: props.field,
2179
- orientation,
2180
- children: props.children
2181
- }
2182
- )
2183
- }
2184
- ),
2185
- /* @__PURE__ */ jsx22(FieldError, { errors, name: props.field.name })
2186
- ] });
2187
- }
2188
-
2189
- // src/client/component/field/field-with-error.tsx
2190
- import { useAtomValue as useAtomValue2 } from "jotai";
2191
- import { jsx as jsx23 } from "react/jsx-runtime";
2192
- function withError(Component) {
2193
- const WithError = (props) => {
2194
- const errors = useAtomValue2(reportInputErrorAtom(props.field.name));
2195
- return /* @__PURE__ */ jsx23(
2196
- Component,
2197
- {
2198
- ...props,
2199
- errors: errors ? { [props.field.name]: errors } : void 0
2200
- }
2201
- );
2202
- };
2203
- return WithError;
2204
- }
2205
-
2206
- // src/client/component/field/field-with-state.tsx
2207
- import { useAtomValue as useAtomValue3 } from "jotai";
2208
- import { jsx as jsx24 } from "react/jsx-runtime";
2209
- function withState(Component) {
2210
- const WithFieldState = (props) => {
2211
- const fieldState = useAtomValue3(reportFieldStateAtom(props.field.name));
2212
- const hidden = fieldState?.hidden ?? props.field.hidden ?? false;
2213
- if (hidden) {
2214
- return null;
2215
- }
2216
- return /* @__PURE__ */ jsx24(Component, { ...props, disabled: fieldState?.disabled ?? props.disabled });
2217
- };
2218
- return WithFieldState;
2219
- }
2220
-
2221
- // src/client/component/field/field.tsx
2222
- var Field2 = withState(withError(Field));
2223
-
2224
- // src/component/field/field-list-item.tsx
2225
- import { twMerge as twMerge6 } from "tailwind-merge";
2226
- import { jsx as jsx25, jsxs as jsxs9 } from "react/jsx-runtime";
2227
- function FieldListItem(props) {
2228
- function handleRemove() {
2229
- if (props.canRemove && props.onRemove) {
2230
- props.onRemove(props.index);
2231
- }
2232
- }
2233
- const removeButton = props.canRemove && props.onRemove != null && /* @__PURE__ */ jsx25(
2234
- "button",
2235
- {
2236
- "aria-label": `Remove ${props.label} item ${props.index + 1}`,
2237
- className: twMerge6(
2238
- "rounded p-1 text-xl text-slate-400",
2239
- "transition-colors duration-150",
2240
- "hover:text-red-500",
2241
- "focus-visible:ring-2 focus-visible:ring-slate-400 focus-visible:outline-none",
2242
- "dark:text-slate-500 dark:hover:text-red-400"
2243
- ),
2244
- onClick: handleRemove,
2245
- type: "button",
2246
- children: /* @__PURE__ */ jsx25("span", { "aria-hidden": "true", children: "\xD7" })
2247
- }
2248
- );
2249
- if (props.isMultiField) {
2250
- return /* @__PURE__ */ jsxs9("div", { className: "rounded-lg border border-slate-100 p-4 dark:border-slate-900", children: [
2251
- /* @__PURE__ */ jsxs9("div", { className: "mb-3 flex items-center justify-between", children: [
2252
- /* @__PURE__ */ jsxs9("span", { className: "text-sm font-medium text-slate-400 dark:text-slate-500", children: [
2253
- props.label,
2254
- " ",
2255
- props.index + 1
2256
- ] }),
2257
- removeButton
2258
- ] }),
2259
- /* @__PURE__ */ jsx25(Group, { children: props.children })
2260
- ] });
2261
- }
2262
- return /* @__PURE__ */ jsxs9("div", { className: "flex items-start gap-2", children: [
2263
- /* @__PURE__ */ jsx25(Group, { children: props.children }),
2264
- removeButton && /* @__PURE__ */ jsx25("div", { className: "shrink-0", children: removeButton })
2265
- ] });
2266
- }
2267
-
2268
- // src/client/component/field/field-list.tsx
2269
- import { twMerge as twMerge7 } from "tailwind-merge";
2270
-
2271
- // src/client/hook/use-field-list.ts
2272
- import { useSetAtom as useSetAtom2 } from "jotai";
2273
- import { useCallback as useCallback5, useRef as useRef4, useState as useState2 } from "react";
2274
- function useFieldList(field, value) {
2275
- const min2 = field.advanced?.length?.min ?? 1;
2276
- const max2 = field.advanced?.length?.max ?? Infinity;
2277
- const [items, setItems] = useState2(
2278
- () => getInitialList(field, value)
2279
- );
2280
- const nextId = useRef4(items.length);
2281
- const itemsRef = useRef4(items);
2282
- itemsRef.current = items;
2283
- const setValues = useSetAtom2(valueAtom);
2284
- const addItem = useCallback5(() => {
2285
- setItems((previous) => {
2286
- if (previous.length >= max2) {
2287
- return previous;
2288
- }
2289
- const id = nextId.current++;
2290
- return [...previous, id];
2291
- });
2292
- }, [max2]);
2293
- const handleRemove = useCallback5(
2294
- (index) => {
2295
- if (items.length <= min2) {
2296
- return;
2297
- }
2298
- const stableId = items[index];
2299
- setItems((previous) => {
2300
- if (previous.length <= min2) {
2301
- return previous;
2302
- }
2303
- return previous.filter((_, i) => i !== index);
2304
- });
2305
- setValues((current) => {
2306
- const next = { ...current };
2307
- const prefix = `${field.name}.`;
2308
- const leafNames = [];
2309
- for (const row of field.fields) {
2310
- if (isColumn(row)) {
2311
- for (const columnField of row.fields) {
2312
- leafNames.push(columnField.name);
2313
- }
2314
- } else {
2315
- leafNames.push(row.name);
2316
- }
2317
- }
2318
- for (const name of leafNames) {
2319
- delete next[`${prefix}${stableId}.${name}`];
2320
- }
2321
- return next;
2322
- });
2323
- },
2324
- [field.name, field.fields, items, min2, setValues]
2325
- );
2326
- const canAdd = items.length < max2;
2327
- const canRemove = items.length > min2;
2328
- return [items, addItem, handleRemove, canAdd, canRemove, max2];
2329
- }
2330
-
2331
- // src/client/component/field/field-list.tsx
2332
- import { Fragment as Fragment3, jsx as jsx26, jsxs as jsxs10 } from "react/jsx-runtime";
2333
- function FieldList(props) {
2334
- const [items, addItem, handleRemove, canAdd, canRemove, max2] = useFieldList(
2335
- props.field,
2336
- props.value
2337
- );
2338
- const label = getLabel(props.field);
2339
- const action = props.field.advanced?.action ?? "Add item";
2340
- const hasLimit = max2 !== Infinity;
2341
- const isMultiField = isMultiFieldList(props.field);
2342
- return /* @__PURE__ */ jsxs10(Fragment3, { children: [
2343
- items.map((key, index) => /* @__PURE__ */ jsx26(
2344
- FieldListItem,
2345
- {
2346
- canRemove,
2347
- index,
2348
- isMultiField,
2349
- label,
2350
- onRemove: handleRemove,
2351
- children: props.children(key)
2352
- },
2353
- key
2354
- )),
2355
- /* @__PURE__ */ jsxs10(
2356
- "button",
2357
- {
2358
- "aria-disabled": !canAdd,
2359
- "aria-label": hasLimit ? `${action}, ${items.length} of ${max2}` : action,
2360
- className: twMerge7(
2361
- "flex w-full items-center gap-1.5 rounded py-1",
2362
- "text-sm font-medium text-slate-500",
2363
- "transition-colors duration-150",
2364
- "hover:text-slate-800",
2365
- "focus-visible:ring-2 focus-visible:ring-slate-400 focus-visible:ring-offset-2 focus-visible:outline-none",
2366
- "dark:text-slate-400 dark:hover:text-slate-200",
2367
- !canAdd && "cursor-not-allowed opacity-50 hover:text-slate-500 dark:hover:text-slate-400"
2368
- ),
2369
- disabled: !canAdd,
2370
- onClick: addItem,
2371
- type: "button",
2372
- children: [
2373
- /* @__PURE__ */ jsx26("span", { "aria-hidden": "true", children: "+" }),
2374
- action,
2375
- hasLimit && /* @__PURE__ */ jsxs10(
2376
- "span",
2377
- {
2378
- "aria-hidden": "true",
2379
- className: "ml-auto text-slate-400 tabular-nums dark:text-slate-500",
2380
- children: [
2381
- items.length,
2382
- " / ",
2383
- max2
2384
- ]
2385
- }
2386
- )
2387
- ]
2388
- }
2389
- )
2390
- ] });
2391
- }
2392
-
2393
- // src/component/list.tsx
2394
- import { jsx as jsx27 } from "react/jsx-runtime";
2395
- function List(props) {
2396
- const empty = Array.isArray(props.field.fields) && props.field.fields.length === 0;
2397
- return /* @__PURE__ */ jsx27(
2398
- FieldSetBase,
2399
- {
2400
- description: props.field.description,
2401
- empty,
2402
- id: props.field.name,
2403
- title: props.field.label,
2404
- children: props.children
2405
- }
2406
- );
2407
- }
2408
-
2409
- // src/client/component/guard/list-guard.tsx
2410
- import { jsx as jsx28 } from "react/jsx-runtime";
2411
- function ListGuard({ children, field, value }) {
2412
- return /* @__PURE__ */ jsx28(VisibilityGuard, { container: field, fields: field.fields, children: /* @__PURE__ */ jsx28(List, { field, children: /* @__PURE__ */ jsx28(FieldList, { field, value, children }) }) });
2413
- }
2414
-
2415
- // src/component/column.tsx
2416
- import { twMerge as twMerge8 } from "tailwind-merge";
2417
- import { jsx as jsx29 } from "react/jsx-runtime";
2418
- function Column(props) {
2419
- const cols2 = getColumn(props.column?.advanced?.cols);
2420
- return /* @__PURE__ */ jsx29("div", { className: "flex w-full flex-col gap-4", children: /* @__PURE__ */ jsx29("div", { className: twMerge8("grid grid-cols-1 gap-3 sm:gap-4", cols2), children: props.children }) });
2421
- }
2422
-
2423
- // src/component/slot/slot-base.tsx
2424
- import { Fragment as Fragment4 } from "react";
2425
-
2426
- // src/component/slot/slot-list.tsx
2427
- import { jsx as jsx30 } from "react/jsx-runtime";
2428
- function SlotList(props) {
2429
- const fields = Array.isArray(props.field.fields) ? props.field.fields.map((field) => {
2430
- if (isField(field)) {
2431
- return {
2432
- ...field,
2433
- name: `${props.field.name}.${props.index}.${field.name}`
2434
- };
2435
- }
2436
- if (isColumn(field)) {
2437
- return {
2438
- ...field,
2439
- fields: field.fields.map((columnField) => ({
2440
- ...columnField,
2441
- name: `${props.field.name}.${props.index}.${columnField.name}`
2442
- }))
2443
- };
2444
- }
2445
- return field;
2446
- }) : [];
2447
- return /* @__PURE__ */ jsx30(
2448
- SlotBase,
2449
- {
2450
- children: props.children,
2451
- components: props.components,
2452
- disabled: props.disabled,
2453
- fields,
2454
- style: props.style,
2455
- value: props.value
2456
- }
2457
- );
2458
- }
2459
-
2460
- // src/component/slot/slot-base.tsx
2461
- import { jsx as jsx31, jsxs as jsxs11 } from "react/jsx-runtime";
2462
- function SlotBase(props) {
2463
- const { field: Field3, list: List2 } = props.components;
2464
- return prepare(props.fields).map((field, index) => /* @__PURE__ */ jsxs11(Fragment4, { children: [
2465
- isColumn(field) && /* @__PURE__ */ jsx31(Column, { column: field, children: /* @__PURE__ */ jsx31(SlotBase, { ...props, fields: field.fields }) }),
2466
- isField(field) && /* @__PURE__ */ jsx31(Field3, { disabled: props.disabled, field, style: props.style, children: props.children }),
2467
- isList(field) && /* @__PURE__ */ jsx31(List2, { field, value: props.value, children: (index2) => /* @__PURE__ */ jsx31(
2468
- SlotList,
2469
- {
2470
- children: props.children,
2471
- components: props.components,
2472
- disabled: props.disabled,
2473
- field,
2474
- index: index2,
2475
- style: props.style,
2476
- value: props.value
2477
- }
2478
- ) })
2479
- ] }, index));
2480
- }
2481
-
2482
- // src/component/slot/slot-create.tsx
2483
- import { jsx as jsx32 } from "react/jsx-runtime";
2484
- function createSlot(components) {
2485
- const CreateSlot = (props) => /* @__PURE__ */ jsx32(SlotBase, { ...props, components });
2486
- return CreateSlot;
2487
- }
2488
-
2489
- // src/client/component/slot/slot.tsx
2490
- var Slot = createSlot({ field: Field2, list: ListGuard });
2491
-
2492
- // src/client/hook/use-form-action.ts
2493
- import { useSetAtom as useSetAtom3 } from "jotai";
2494
- import { startTransition, useActionState } from "react";
2495
- function useFormState(getSchema2, action, options) {
2496
- const {
2497
- onSuccess,
2498
- preserveValues = false,
2499
- validation = true,
2500
- translations
2501
- } = options ?? {};
2502
- const setError = useSetAtom3(reportErrorAtom);
2503
- const clearValues = useSetAtom3(clearAllValueAtom);
2504
- const initialState = {
2505
- data: null,
2506
- error: null,
2507
- success: false
2508
- };
2509
- const [state, formAction, isPending] = useActionState(
2510
- async (prevState, formData) => {
2511
- const [schemas, fields] = getSchema2();
2512
- const schema = buildSchema(schemas, fields, translations);
2513
- if (validation === false) {
2514
- if (action) {
2515
- return await action(formData, schema);
2516
- }
2517
- return prevState;
2518
- }
2519
- const form = getFormData(formData);
2520
- const validated = schema.safeParse(form);
2521
- if (!validated.success) {
2522
- const errors = flatten(validated.error);
2523
- startTransition(() => {
2524
- setError(errors);
2525
- });
2526
- return failure(form, {
2527
- description: translate(
2528
- "Please correct the errors and try again.",
2529
- translations
2530
- ),
2531
- details: [],
2532
- title: translate(
2533
- "There were validation errors submitting the form.",
2534
- translations
2535
- )
2536
- });
2537
- }
2538
- const unflattened = unflatten(form);
2539
- if (action) {
2540
- try {
2541
- const result = await action(unflattened, schema);
2542
- if (!result.success) {
2543
- return failure(unflattened, result.error);
2544
- }
2545
- onSuccess?.(result.data);
2546
- if (!preserveValues) {
2547
- startTransition(() => {
2548
- clearValues();
2549
- });
2550
- }
2551
- return success(unflattened, preserveValues);
2552
- } catch (error) {
2553
- logger.error("Error executing form action:", error);
2554
- return failure(unflattened, {
2555
- title: translate(
2556
- "An unexpected error occurred submitting the form.",
2557
- translations
2558
- ),
2559
- details: buildError(error, translations)
2560
- });
2561
- }
2562
- }
2563
- return success(validated.data, preserveValues);
2564
- },
2565
- initialState
2566
- );
2567
- return [formAction, state, isPending];
2568
- }
2569
- function buildError(error, translations) {
2570
- if (error instanceof Error) {
2571
- return [error.message];
2572
- }
2573
- return [translate("Unknown error", translations)];
2574
- }
2575
- function success(value, preserveValues = false) {
2576
- const data = preserveValues ? value : null;
2577
- return {
2578
- data,
2579
- error: null,
2580
- success: true
2581
- };
2582
- }
2583
- function failure(value, error) {
2584
- return {
2585
- data: value,
2586
- error,
2587
- success: false
2588
- };
2589
- }
2590
-
2591
- // src/client/hook/use-schema.ts
2592
- import { useCallback as useCallback7, useRef as useRef5 } from "react";
2593
-
2594
- // src/client/hook/use-store.ts
2595
- import { useCallback as useCallback6 } from "react";
2596
- import { useSetAtom as useSetAtom4 } from "jotai";
2597
- function useStore2() {
2598
- const clearErrors = useSetAtom4(clearInputErrorAtom);
2599
- const clearValues = useSetAtom4(clearInputValueAtom);
2600
- const clearSources = useSetAtom4(clearInputSourceAtom);
2601
- return useCallback6(
2602
- (names) => {
2603
- const target = Array.isArray(names) ? names : [names];
2604
- clearErrors(target);
2605
- clearSources(target);
2606
- clearValues(target);
2607
- },
2608
- [clearErrors, clearSources, clearValues]
2609
- );
2610
- }
2611
-
2612
- // src/client/hook/use-schema.ts
2613
- function useSchema() {
2614
- const clear = useStore2();
2615
- const schemaRef = useRef5({});
2616
- const fieldsRef = useRef5([]);
2617
- const onMount = useCallback7((name, schema, field) => {
2618
- if (!(name in schemaRef.current)) {
2619
- schemaRef.current[name] = schema;
2620
- fieldsRef.current.push(field);
2621
- }
2622
- }, []);
2623
- const onUnmount = useCallback7(
2624
- (name) => {
2625
- if (schemaRef.current[name]) {
2626
- delete schemaRef.current[name];
2627
- fieldsRef.current = fieldsRef.current.filter((field) => {
2628
- return field.name !== name;
2629
- });
2630
- clear([name]);
2631
- }
2632
- },
2633
- [clear]
2634
- );
2635
- const getSchema2 = useCallback7(() => {
2636
- return [schemaRef.current, fieldsRef.current];
2637
- }, []);
2638
- return [getSchema2, onMount, onUnmount];
2639
- }
2640
-
2641
- // src/client/component/form-content.tsx
2642
- import { Fragment as Fragment5, jsx as jsx33, jsxs as jsxs12 } from "react/jsx-runtime";
2643
- function FormContent(props) {
2644
- const translations = props.translations?.[props.lang ?? ""];
2645
- const [schema, onMount, onUnmount] = useSchema();
2646
- const [action, state, isPending] = useFormState(schema, props.action, {
2647
- onSuccess: props.onSuccess,
2648
- validation: props.config.validation.submit,
2649
- translations
2650
- });
2651
- const isShowingError = props.config.validation.showError && !state.success && state.error;
2652
- const value = state.data ?? props.value;
2653
- return /* @__PURE__ */ jsxs12(Fragment5, { children: [
2654
- isShowingError && renderIfExists(props.config.alert, (Alert) => /* @__PURE__ */ jsx33("div", { className: "mb-4 w-full", children: /* @__PURE__ */ jsx33(
2655
- Alert,
2656
- {
2657
- description: state.error?.description,
2658
- details: state.error?.details,
2659
- title: state.error.title
2660
- }
2661
- ) })),
2662
- /* @__PURE__ */ jsx33(
2663
- Form,
2664
- {
2665
- action,
2666
- config: props.config,
2667
- control: props.children,
2668
- definition: props.definition,
2669
- isPending,
2670
- noValidate: true,
2671
- readOnly: props.readOnly,
2672
- sections: props.sections,
2673
- children: ({ disabled, fields }) => /* @__PURE__ */ jsx33(
2674
- Slot,
2675
- {
2676
- disabled,
2677
- fields,
2678
- style: props.config.style,
2679
- value,
2680
- children: (internal) => /* @__PURE__ */ jsx33(
2681
- Input,
2682
- {
2683
- ...internal,
2684
- config: props.config,
2685
- context: props.context,
2686
- onMount,
2687
- onUnmount,
2688
- onValueChange: props.onValueChange,
2689
- translations,
2690
- value
2691
- }
2692
- )
2693
- }
2694
- )
2695
- }
2696
- )
2697
- ] });
2698
- }
2699
-
2700
- // src/client/component/form.tsx
2701
- import { Provider } from "jotai";
2702
- import { jsx as jsx34 } from "react/jsx-runtime";
2703
- function Form2(props) {
2704
- return /* @__PURE__ */ jsx34(Provider, { children: /* @__PURE__ */ jsx34(FormContent, { ...props }) });
2705
- }
2706
- export {
2707
- Form2 as Form
2708
- };
1
+ import{jsx as uo}from"react/jsx-runtime";function Rt(e){let t=typeof e.children=="function"?e.children({isPending:e.isPending}):e.children;return uo("div",{"data-slot":"field-control",className:"w-full",children:t})}import{Activity as mi,useCallback as gi,useState as pi}from"react";import{jsx as Tt}from"react/jsx-runtime";function St(e){return Tt("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 20 20",fill:"currentColor",className:`size-4 transition-transform duration-200 ${e.expanded?"rotate-90":""}`,children:Tt("path",{fillRule:"evenodd",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",clipRule:"evenodd"})})}var fe="input",At="input/email",vt="input/number";var Ft="textarea",Ct="radio",Nt="checkbox",Ze="list";var Et="select",kt="select/month",It="select/year";var z="column",Ke="fields",wt="label",S="value",me="options",We="email",Lt="number",Pt="password",Ot="tel",J="text",Vt="aria-errormessage",Dt="aria-invalid",Mt="data-invalid",_t="data-readonly",Bt="aria",Gt="data",ge="min",pe="max",$t="minLength",Ut="maxLength",q="$ref";var Ht="source",Yt="state",ye="http://luna.internal",V="vertical",Z="horizontal";var Xt="type";function d(e){return e!==null&&Object.prototype.toString.call(e)==="[object Object]"}function be(e){return e==null||e===""}function D(e){return E(e)||typeof e=="number"||ze(e)}function E(e){return typeof e=="string"}function qt(e){return d(e)&&"url"in e}function ze(e){return typeof e=="boolean"}var fo=/^\d+$/;function Qe(e,t=[],n=S){return Array.isArray(t)?t.find(r=>{let o=je(r,n);if(o!==void 0&&`${o}`===e)return r})??{value:e}:{value:e}}function je(e,t=S){if(e!=null){if(D(e))return e;if(d(e)){let n=mo(e,t);if(D(n))return n}}}function mo(e,t){let n=h(e,t);if(D(n))return n}function Zt(e,t){if(Array.isArray(e))return e;let n=h(e,t);return Array.isArray(n)?n:null}function h(e,t){if(!t||!d(e))return null;let n=t.split(".").filter(o=>o!=="");if(n.length===0)return null;let r=e;for(let o of n)if(d(r)&&o in r)r=r[o];else return null;return r}function Kt(e,t={label:wt,value:S}){return e.map(n=>{if(d(n)){let r=h(n,t.label),o=h(n,t.value);if(D(r)&&D(o))return{label:`${r}`,value:`${o}`}}return n})}function Wt(e=J){if(e){let t=e.lastIndexOf("/"),n=t===-1?e:e.slice(t+1);if(n&&n!==fe)return n.trim().toLowerCase()}return J}function zt(e){let t={};for(let n of e.keys()){let r=e.getAll(n);t[n]=r.length>1?r:r[0]}return t}function Jt(e){let t={};for(let n in e){let r=n.split(".");if(r.length===1){t[n]=e[n];continue}let o=t;for(let l=0;l<r.length-1;l++){let a=r[l],s=r[l+1],c=fo.test(s);a in o||(o[a]=c?[]:{}),o=o[a]}let i=r[r.length-1];o[i]=e[n]}return Je(t),t}function Je(e){for(let t in e){let n=e[t];if(Array.isArray(n)){let r=n.filter(o=>o!==void 0);r.forEach(o=>{o!==null&&typeof o=="object"&&!Array.isArray(o)&&Je(o)}),e[t]=r}else n!==null&&typeof n=="object"&&Je(n)}}var go=/\[([^\]]{1,500})\]\(([^)]{1,2000})\)/g;function M(e,t={}){if(E(e))return po(e,t);if(Array.isArray(e))return e.map(n=>M(n,t));if(d(e)){let n={};for(let r in e)n[r]=M(e[r],t);return n}return e}function et(e,t={}){return Q(e)?M(e,t):e}function Q(e){return E(e)?/{([^}]{1,200})}/.test(e):Array.isArray(e)?e.some(t=>Q(t)):d(e)?Object.values(e).some(t=>Q(t)):!1}function po(e,t={}){return e.replace(/{([^}]{1,200})}/g,(n,r)=>{let o=r.includes(".")?h(t,r):t[r];return D(o)?String(o):n})}function Qt(e,t){if(!e||e.trim().length===0)return null;let n,r=0,o=!1,i=[];for(;(n=go.exec(e))!==null;){let[l,a,s]=n,c=n.index;o=!0,c>r&&i.push(e.substring(r,c));let u=t?t(c,s,a):l;i.push(u),r=c+l.length}return o?(r<e.length&&i.push(e.substring(r)),i):e}var j={error:(...e)=>{tt()&&!nt()&&xe().error("[Luna Form]",...e)},warn:(...e)=>{tt()&&!nt()&&xe().warn("[Luna Form]",...e)},info:(...e)=>{tt()&&!nt()&&xe().info("[Luna Form]",...e)}},tt=()=>typeof xe()<"u",nt=()=>!0,xe=()=>globalThis.console;function jt(e=[],t){let n=[],r=[],o=[];for(let i of e)i.action===S&&n.push(i),i.action===Ht&&r.push(i),i.action===Yt&&o.push(i);t({sources:r,states:o,values:n})}function en(e=null,t=[],n){for(let r of t){let{target:o,source:i}=r;if(!e){n(o,void 0);continue}if(qt(i)){let l=M(i.url,e),a=i.body?M(i.body,e):i.body;n(o,{...i,url:l,body:a})}}}var ee={eq:Ro,gt:vo,gte:Fo,in:So,lt:Co,lte:No,neq:To,nin:Ao},yo=/^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}:\d{2})?/,tn=/^(\d{2})[/-](\d{2})[/-](\d{4})(?: (\d{2}):(\d{2})(?::(\d{2}))?)?$/;function bo(e){return typeof e=="string"&&yo.test(e)}function xo(e){return typeof e=="string"&&tn.test(e)}function ho(e){let t=e.match(tn);if(t){let[,n,r,o,i,l,a]=t;return new Date(Number(o),Number(r)-1,Number(n),Number(i??0),Number(l??0),Number(a??0)).getTime()}return NaN}function _(e){return bo(e)?new Date(e).getTime():xo(e)?ho(e):Number(e)}function Ro(e,t){return e===t}function To(e,t){return e!==t}function So(e,t){return Array.isArray(t)&&t.includes(String(e))}function Ao(e,t){return Array.isArray(t)&&!t.includes(String(e))}function vo(e,t){return _(e)>_(t)}function Fo(e,t){return _(e)>=_(t)}function Co(e,t){return _(e)<_(t)}function No(e,t){return _(e)<=_(t)}function nn(e=null,t=[],n){for(let r of t){let{target:o,state:i,when:l}=r,a=Array.isArray(o)?o:[o];if(!e){n(a);continue}let s=Eo(e,l);n(a,s?i:void 0)}}function Eo(e,t){return t===void 0?!0:E(t)?he(e,S)===t:ze(t)?!!he(e,S)===t:Array.isArray(t)?t.includes(String(he(e,S))):ko(e,t)}function ko(e=null,t){let n=he(e,t.field??S),{operator:r="eq",value:o}=t,i=ee[r];return i?i(n,o):!1}function he(e,t){return d(e)?h(e,t):e}function rn(e=null,t=[],n){for(let r of t)for(let[o,i]of Object.entries(r.value))n(o,e?M(i,e):void 0)}var Re=e=>k(kt)(e),Te=e=>k(It)(e),R=k(Nt),rt=k(fe),w=k(Ct),L=k(Et),ot=k(Ft),on=k(J,We,Pt,Ot),ln=k(At,We),Se=k(vt,Lt);function Ae(e){return w(e)||R(e)}function an(e){return e.type===Ze}function B(e){return e.type===z}function ve(e){return e.type!==z&&e.type!==Ze}function Fe(e){return L(e)||w(e)}function sn(e){return rt(e)||ot(e)}function U(e){return e!=null&&e!==""}function k(...e){return t=>{let n=E(t.type)?t.type:void 0;return n?e.some(r=>n===r||n?.startsWith(`${r}/`)):!1}}function cn(e,t={}){if(L(e)&&e.disabled){let n=e.name?t?.[e.name]:void 0;if(n&&d(n))return[n]}}function un(e){return w(e)||R(e)?Z:e.advanced?.orientation??V}function dn(e){return R(e)?e.advanced?.reverse!==!1:!1}function fn(e,t){let n=e.readonly??!1;return t||n}function mn(e){if(w(e)||L(e)&&!e.disabled){let t=e.source;if(Array.isArray(t)||d(t)&&!(q in t))return t}}var Io=/^\d+$/;function gn(){return Array.from({length:12},(e,t)=>({value:(t+1).toString(),label:new Date(0,t).toLocaleString("default",{month:"long"})}))}function pn(e,t){return t>=e?Array.from({length:t-e+1},(n,r)=>{let o=e+r;return{value:o.toString(),label:o.toString()}}):[]}function it(){return new Date().getFullYear()}function lt(e,t){if(typeof e=="number")return e;let n=t??it(),r=e.trim().toLowerCase();if(r.startsWith("current")){let o=r.match(/^current([+-])(\d+)$/);if(o){let[,i,l]=o,a=parseInt(l,10);if(!isNaN(a))return i==="+"?n+a:n-a}return n}return Io.test(r)?parseInt(r,10):n}var Ce=it();function wo(e){if(L(e))return Lo(e)}function Lo(e){if(Re(e))return gn();if(Te(e)){let t=e.advanced?.length?.min??Ce,n=e.advanced?.length?.max??Ce+5;return pn(lt(t,Ce),lt(n,Ce))}}function yn(e,t=!1){let n={disabled:t,id:e.name,name:e.name,placeholder:e.placeholder,required:e.required};return rt(e)?{...n,...Po(e)}:L(e)?{...n,...Oo(e)}:ot(e)?{...n,...Vo(e)}:n}function Po(e){let t=Wt(e.type),n={...e,type:t};return{...bn(e),...Do(n),...on(n)?xn(n):{},type:t}}function Oo(e){let t=wo(e);return t?{options:t}:{}}function Vo(e){return{...bn(e),...xn(e)}}function bn(e){let t=e.advanced?.autocomplete;return t?{autoComplete:t}:{}}function Do(e){return Se(e)?Mo(e):{}}function xn(e){return hn(e,{min:$t,max:Ut})}function Mo(e){return hn(e,{min:ge,max:pe})}function hn(e,t){let n={},r=e.advanced?.length;return r&&(r.min!==void 0&&(n[t.min]=r.min),r.max!==void 0&&(n[t.max]=r.max)),n}function Rn(e,t){let n=mn(e);return n||cn(e,t)}function _o(e,t){let n=d(t)&&e.name in t?t[e.name]:t;return je(n,e.advanced?.entity)}function Bo(e,t,n){return Fe(e)&&Array.isArray(n)?{...t,[me]:n}:t}function Go(e,t,n){if(e.required&&!U(n)&&L(e)&&e.advanced?.preselected!==!1&&me in t){let r=t[me];if(Array.isArray(r)&&r.length===1)return r[0]}return n}function $o(e,t){return L(e)&&Array.isArray(t)?Kt(t,e.advanced?.options):t}function Tn(e,t,n,r){let o=_o(e,r),i=Array.isArray(n)?$o(e,n):n,l=Bo(e,t,i),a=Go(e,l,o);return{commonPropsWithOptions:l,defaultValue:a}}function Sn(e,t){return R(e)?{checked:U(t)?t:!1}:{value:t??""}}var Uo=/^#\/definition\//;function Ee(e=[],t){let n=Ne(e,t);return Array.isArray(n)?n.filter(Yo).sort((r,o)=>An(r)-An(o)):[]}function Ne(e,t,n=new Map,r=new WeakSet){if(!Ho(t)||!e||typeof e!="object")return e;if(n.has(e))return n.get(e);if(r.has(e))return e;if(r.add(e),Array.isArray(e))return e.map(i=>Ne(i,t,n,r));if(q in e&&E(e[q])){let i=e[q].replace(Uo,""),l=h(t,i);return l!==null?Ne(l,t,n,r):e}let o={};for(let[i,l]of Object.entries(e))o[i]=Ne(l,t,n,r);return r.delete(e),n.set(e,o),o}function vn(e){return Object.entries(e??{})}function An(e){return e.order??Number.MAX_VALUE}function Ho(e){return e!==void 0&&d(e)&&Object.keys(e).length>0}function Yo(e){return Xt in e?!0:Array.isArray(e[Ke])?e[Ke].length>0:!0}function Fn(e,t){let n={};for(let[r,o]of vn(t))n[`${e}-${r}`]=o;return n}function Xo(e){return Fn(Bt,e)}function qo(e){return Fn(Gt,e)}function Cn(e,t){let n=Xo(e.advanced?.aria);return t&&t.length>0&&(n[Dt]="true",n[Vt]=`${e.name}-error`),n}function Nn(e){return qo(e.advanced?.data)}var En={1:"md:grid-cols-1",2:"md:grid-cols-2",3:"md:grid-cols-3"},kn={1:"md:col-span-1",2:"md:col-span-2",3:"md:col-span-3"};function In(e,t=2){return En[e&&e in En?e:t]}function wn(e){if(e&&e in kn)return kn[e]}function Zo(e,t){let n=e.advanced?.length?.min??1;if(t){let r=h(t,e.name);if(Array.isArray(r))return Math.max(r.length,n)}return Math.max(n,0)}function Ln(e){return!Array.isArray(e.fields)||e.fields.length===0?!1:e.fields.length>1||e.fields[0].type===z}function Pn(e,t){let n=Zo(e,t);return Array.from({length:n},(r,o)=>o)}function On(e){return e.label??e.name}import{z as g}from"zod";function f(e,t){return e?t?t[e]??e:e:""}var Ko=[[Se,jo],[ln,Wo],[Te,ei],[Re,ti],[R,zo],[w,Jo]];function Dn(e,t=[],n){let r=g.object(e);return t.length===0?r:ii(r,t,n)}function Mn(e){let t={},n=g.flattenError(e).fieldErrors;for(let[r,o]of Object.entries(n))o!==void 0&&(t[r]=o);return t}function _n(e,t){for(let[n,r]of Ko)if(n(e))return r(e,t);return Qo(e,t)}function Wo(e,t){let n=g.string().trim();if(e.required){let r=K(e,t),o=n.min(1,r).pipe(Vn(e,t));return g.preprocess(i=>be(i)?"":i,o)}return n.pipe(Vn(e,t)).or(g.literal("")).nullable()}function zo(e,t){let n=g.coerce.boolean();return e.required?(n=n.refine(r=>r===!0,{message:K(e,t)}),g.preprocess(r=>r===null?!1:r,n)):n.nullable()}function Jo(e,t){let n=g.coerce.string();return e.required?(n=n.min(1,K(e,t)),g.preprocess(r=>be(r)?"":r,n)):n.or(g.literal("")).nullable()}function Qo(e,t){let n=g.coerce.string().trim();return n=Bn(n,e,t),e.required?(n=Gn(n,e,t),g.preprocess(r=>be(r)?"":r,n)):n.nullable()}function jo(e,t){let n=g.coerce.number().int();return n=Bn(n,e,t),e.required?(n=Gn(n,e,t),g.preprocess(r=>r===null?void 0:r,n)):n.nullable()}function ei(e,t){return e.required?g.preprocess(ni,g.coerce.number({message:K(e,t)}).int()):g.coerce.number().int().nullable()}function ti(e,t){let n=K(e,t),r=g.coerce.number().int().min(1,n).max(12,n);return e.required?r:r.nullable()}function ni(e){return e===null||e===""?void 0:e}function Vn(e,t){let n=e.validation?.email?f(e.validation?.email,t):void 0;return g.email(n)}function Bn(e,t,n){return e=ri(e,t,n),e=oi(e,t,n),e}function Gn(e,t,n){let r=t.advanced?.length?.min;return r===void 0||r<1?e.min(1,K(t,n)):e}var ri=(e,t,n)=>$n(e,t,ge,n),oi=(e,t,n)=>$n(e,t,pe,n);function $n(e,t,n,r){let o=t.advanced?.length?.[n];if(o!==void 0){let i=t.validation?.length?.[n]?f(t.validation?.length?.[n],r):void 0;return e[n](o,i)}return e}function ii(e,t=[],n){let r=ai(t);return r.length===0?e:e.superRefine((o,i)=>{for(let{name:l,rule:a}of r)if(!li(o,l,a)){let s=f(a.message,n);i.addIssue({code:"custom",message:s,path:[l]})}})}function li(e,t,n){let r=n.operator??"eq",o=ee[r];return o?o(e[t],e[n.field]):!1}function ai(e){let t=[];for(let n of e){let r=n.validation?.custom;if(!r)continue;let o=Array.isArray(r)?r:[r];for(let i of o)t.push({name:n.name,rule:i})}return t}function Un(e,t,n,r){let o=[],i=Array.isArray(t)?t:[t];for(let l of i){let a=l.operator??"eq",s=ee[a];if(s&&!s(e,n(l.field))&&l.message){let c=f(l.message,r);o.push(c)}}return o}function K(e,t){return e.validation?.required?f(e.validation?.required,t):void 0}function Hn(e,t){if(!t||!ci(e))return!0;if(t.length===0)return!1;try{let n=new URL(e),r=n.protocol.replace(":",""),o=n.hostname,i=n.port||si(r);return t.some(l=>!(l.protocol&&l.protocol!==r||l.hostname&&l.hostname!==o||l.port!==void 0&&String(l.port)!==i))}catch{return!1}}function si(e){return e==="https"?"443":"80"}function ci(e){return/^(https?:)?\/\//.test(e)}function Yn(e,t){try{if(!e)return t;if(!t)return e;let n=new URL(e,ye);new URL(t,ye).searchParams.forEach((i,l)=>{n.searchParams.set(l,i)});let o=n.toString();return e.startsWith("/")||!e.includes("://")?o.replace(ye,""):o}catch{return t||e}}function Xn(e){return!Array.isArray(e)||e.length===0?null:e.reduce((t,n)=>{let r=Yn(t.url,n.url),o=ui(t,n),i=di(t,n);return{...t,...n,url:r,body:o,headers:i}})}function ui(e,t){return d(t.body)&&d(e?.body)?{...e.body,...t.body}:t.body??e?.body}function di(e,t){return d(t.headers)&&d(e?.headers)?{...e.headers,...t.headers}:t.headers??e?.headers}function ke(e,t){return{...e,...t}}import{jsx as fi}from"react/jsx-runtime";function G(e){return Qt(e,(t,n,r)=>fi("a",{className:"underline",href:n,rel:"noopener noreferrer",target:"_blank",children:r},`${n}-${t}`))}import{jsx as te,jsxs as at}from"react/jsx-runtime";function qn(e){let{fields:t=[]}=e.section,[n,r]=pi(!1),o=gi(()=>r(i=>!i),[]);return at("fieldset",{"data-slot":"field-set","data-advanced":"true","data-expanded":n,"data-empty":t.length===0,className:"flex flex-col",id:e.section.id?.toString(),children:[te("legend",{children:at("button",{className:"flex cursor-pointer items-center gap-2 text-base font-medium text-slate-600 dark:text-slate-400",onClick:o,type:"button",children:[te(St,{expanded:n}),te("span",{children:G(e.section.title)})]})}),te(mi,{mode:n?"visible":"hidden",children:at("div",{className:"mt-3 ml-1.5 flex flex-col gap-4 border-l-2 border-slate-300 pl-4 dark:border-slate-600","data-slot":"field-set-content",children:[e.section.description&&te("p",{className:"text-sm leading-normal font-normal text-slate-600 dark:text-slate-400",children:G(e.section.description)}),e.group]})})]})}import{Fragment as yi,jsx as Zn,jsxs as bi}from"react/jsx-runtime";function Kn(e){return bi(yi,{children:[e.title&&Zn("legend",{className:"mb-3 font-medium text-slate-800 dark:text-slate-200",children:G(e.title)}),e.description&&Zn("p",{className:"-mt-2 text-sm leading-normal font-normal text-slate-600 dark:text-slate-400",children:G(e.description)})]})}import{jsx as xi,jsxs as hi}from"react/jsx-runtime";function Ie(e){return hi("fieldset",{"data-slot":"field-set","data-empty":e.empty,className:"flex flex-col data-[empty=false]:gap-6",id:e.id,children:[xi(Kn,{description:e.description,title:e.title}),e.children]})}import{jsx as Ri}from"react/jsx-runtime";function H(e){return Ri("div",{"data-slot":"field-group","data-compact":e.compact,className:"flex w-full flex-col gap-8 data-[compact=true]:gap-3",children:e.children})}import{jsx as st}from"react/jsx-runtime";function Wn(e){let{fields:t=[]}=e.section,{compact:n}=ke(e.style,{compact:e.section.compact}),r=st(H,{compact:n,children:e.children});return!e.section.title&&!e.section.description?r:e.section.advanced?st(qn,{section:e.section,group:r}):st(Ie,{description:e.section.description,empty:t.length===0,id:e.section.id?.toString(),title:e.section.title,children:r})}import{useAtomValue as Fi}from"jotai";import{atom as Y}from"jotai";import{atomFamily as zn}from"jotai-family";import{deepEqual as ct}from"fast-equals";function we(e,t){let{[t]:n,...r}=e;return r}function Ti(e){return zn(t=>Y(n=>n(e)[t]??void 0,(n,r,o)=>{let i=n(e);if(o!=null){let l=i[t];(!l||!ct(l,o))&&r(e,{...i,[t]:o})}else i[t]&&r(e,we(i,t))}))}function Si(e){return Y(null,(t,n)=>{let r=t(e);r&&Object.keys(r).length>0&&n(e,{})})}function Ai(e){return Y(null,(t,n,r)=>{let i={...t(e)},l=!1;for(let a of r)i[a]&&(delete i[a],l=!0);l&&n(e,i)})}function vi(e){return Y(null,(t,n,r)=>{let o=t(e);ct(o,r)||n(e,r)})}function Jn(e,t={}){let{merge:n,validateTarget:r}=t;return zn(o=>Y(i=>{let l=i(e)[o];if(l&&n)return n(Object.values(l))},(i,l,a,s)=>{if(r&&!r(a))return;let c=i(e),u={...c[a]??{}};if(s!=null){let p=u[o];(!p||!ct(p,s))&&(u[o]=s,l(e,{...c,[a]:u}))}else u[o]&&(delete u[o],Object.keys(u).length===0?l(e,we(c,a)):l(e,{...c,[a]:u}))}))}function Qn(e){return Y(null,(t,n,r)=>{let i={...t(e)},l=!1;for(let a of r)i[a]&&(delete i[a],l=!0);for(let a in i){let s={...i[a]},c=!1;for(let u of r)s[u]&&(delete s[u],c=!0,l=!0);c&&(Object.keys(s).length===0?delete i[a]:i[a]=s)}l&&n(e,i)})}function W(e={}){let t=Y(e);return{atom:t,clearAll:Si(t),clear:Ai(t),bulkReport:vi(t),report:Ti(t)}}var jn=W(),Le=jn.atom,er=jn.report;function Ci(e,t){return e.fields.every(n=>tr(n,t))}function tr(e,t){return t[e.name]?.hidden??e.hidden??!1}function Ni(e,t){return B(e)?Ci(e,t):tr(e,t)}function Pe(e){let t=Fi(Le);return e.container&&(t[e.container.name]?.hidden??e.container.hidden??!1)||e.fields.length===0||e.fields.every(r=>Ni(r,t))?null:e.children}import{jsx as nr}from"react/jsx-runtime";function rr(){return nr("div",{"data-slot":"field-separator",className:"relative -my-2 h-5 text-sm",children:nr("div",{className:"absolute inset-0 top-1/2 h-px w-full bg-slate-200 dark:bg-slate-800"})})}import{jsx as ne,jsxs as or}from"react/jsx-runtime";function ir(e){let t=Ee(e.sections,e.definition);return ne("div",{className:"h-full w-full",children:ne("form",{noValidate:e.noValidate,action:e.action,children:or(H,{children:[t.map((n,r)=>or(Pe,{fields:n.fields??[],children:[ne(Wn,{section:n,style:e.config.style,children:e.children({disabled:e.readOnly,fields:n.fields})}),n.separator&&ne(rr,{})]},r)),e.control&&ne(Rt,{isPending:e.isPending,children:e.control})]})})})}import{jsx as Ei}from"react/jsx-runtime";function lr(e){return Ei("p",{className:"-mt-2 text-xs leading-normal font-normal text-slate-600 dark:text-slate-400",children:e.children})}import{jsx as ki}from"react/jsx-runtime";function Oe(e){let t=G(e.text);return t?ki(lr,{children:t}):null}import{twMerge as Ii}from"tailwind-merge";import{jsx as wi,jsxs as Li}from"react/jsx-runtime";function ar(e){let t=e.style?.showOptionalLabel??!0,n=w(e.field)||R(e.field);return Li("label",{"data-slot":"field-label","data-normal":n,className:Ii("flex w-fit items-center gap-2 text-sm leading-snug font-medium select-none","data-[normal=true]:font-normal","group-data-[readonly=true]:cursor-not-allowed group-data-[readonly=true]:opacity-50"),htmlFor:e.field.name,children:[e.children,t&&!e.field.required&&wi("span",{className:"text-sm text-slate-600 dark:text-slate-400",children:f("(Optional)",e.translations)})]})}import{jsx as sr,jsxs as Pi}from"react/jsx-runtime";function cr(e){let t={context:e.context,env:e.config?.env},n=et(e.field.label,t),r=et(e.field.description,t);return Pi("div",{"data-slot":"field-content",className:"flex w-full flex-1 flex-col gap-1.5 leading-snug",children:[sr(ar,{field:e.field,style:e.config?.style,translations:e.translations,children:f(n,e.translations)}),e.orientation===Z&&sr(Oe,{text:f(r,e.translations)})]})}import{Fragment as Oi,jsx as ur,jsxs as Vi}from"react/jsx-runtime";function dr(e){return Vi(Oi,{children:[e.field.name&&e.field.label&&ur(cr,{config:e.config,context:e.context,field:e.field,orientation:e.orientation,translations:e.translations}),e.children,e.orientation===V&&e.field.description&&ur(Oe,{text:f(e.field.description,e.translations)})]})}function Ve(e,t){return e?t(e):null}var ut=W(),fr=ut.clear,mr=ut.bulkReport,De=ut.report;var Me=W(),_e=Me.atom,gr=Me.clearAll,pr=Me.clear,Be=Me.report;import{useCallback as Ge,useEffect as ji,useRef as re,useTransition as el}from"react";import{atom as Di}from"jotai";var Mi=e=>{let t=Xn(e);if(t)return t},_i=e=>e.trim()!=="",yr=Di({}),br=Jn(yr,{merge:Mi,validateTarget:_i}),xr=Qn(yr);import{useAtom as $i}from"jotai";import Bi from"swr";function hr(e=null,t,n=!1){let{data:r,error:o}=Bi(Gi(e,t,n),t.fetcher.provider);if(o&&j.error("Error fetching data source:",o),e){if(Array.isArray(e))return e;if(r)return Zt(r,e.namespace)}return null}function Gi(e=null,t,n=!1){if(e&&!Array.isArray(e)&&!n&&e.url&&!Q(e.url)){if(Hn(e.url,t.fetcher.remotePatterns))return e;j.warn(`URL blocked by remotePatterns: ${e.url}. Check your luna.config.ts`)}return null}function Rr(e,t,n){let r=Rn(e,n),[o,i]=$i(br(e.name));return[hr(o??r,t,e.disabled),i]}import{useEffect as Ui,useEffectEvent as Tr,useMemo as Hi}from"react";function Sr(e,t,n,r){let{name:o}=e,i=Hi(()=>_n(e,r),[e,r]),l=Tr(s=>{s&&t(s,i,e)}),a=Tr(s=>{s&&n(s)});return Ui(()=>(l(o),()=>{a(o)}),[o]),i}import{useSetAtom as dt,useStore as tl}from"jotai";import{useCallback as Yi,useEffect as Xi,useRef as qi}from"react";function Ar(){let e=qi(null);return Xi(()=>()=>{e.current&&clearTimeout(e.current)},[]),Yi((n,r)=>{e.current&&(clearTimeout(e.current),e.current=null),e.current=setTimeout(n,r)},[])}import{useAtom as Zi}from"jotai";import{useCallback as Ki,useEffect as Wi,useRef as zi,useEffectEvent as Ji}from"react";function vr(e,t){let{name:n}=e,r=zi(!1),[o,i]=Zi(Be(n)),l=Ji(s=>{let c=Qi(n,s);U(c)&&(r.current=!0,i(c))});Wi(()=>{t&&l(t)},[t]);let a=Ki(()=>r.current?(r.current=!1,!0):!1,[]);return{setValue:i,shouldSkipOnChange:a,value:o}}function Qi(e,t){if(e in t)return t[e];if(!e.includes("."))return;let n=e.split("."),r=t;for(let o of n){if(r==null)return;if(Array.isArray(r)){let i=Number(o);r=Number.isInteger(i)?r[i]:void 0}else if(typeof r=="object")r=r[o];else return}return r}import{jsx as Fr}from"react/jsx-runtime";function Cr(e){let t=e.field.advanced?.entity,n=tl(),r=Ar(),[,o]=el(),{setValue:i,shouldSkipOnChange:l,value:a}=vr(e.field,e.value),s=re(!1),c=re(a);c.current=a;let u=re(e.translations);u.current=e.translations;let p=sn(e.field),x=Ae(e.field),A=dt(_e),P=dt(Le),v=dt(De(e.field.name)),[b,I]=Rr(e.field,e.config,a),F=Sr(e.field,e.onMount,e.onUnmount,e.translations),T=f(e.commonProps.placeholder,e.translations),O={...e.commonProps,placeholder:T},{commonPropsWithOptions:C,defaultValue:se}=Tn(e.field,O,b,a),xt=re(null);xt.current=m=>{i(m),e.onValueChange&&e.onValueChange({name:e.field.name,value:m})};let He=re(null);He.current=m=>{let y=e.field.event?.change;y&&jt(y,({sources:$,states:ue,values:Ye})=>{o(()=>{en(m,$,(N,X)=>I(N,X)),nn(m,ue,(N,X)=>{P(de=>X?N.reduce((Xe,qe)=>({...Xe,[qe]:X}),de):N.reduce((Xe,qe)=>we(Xe,qe),de))}),rn(m,Ye,(N,X)=>{A(de=>({...de,[N]:X}))})})})};let ao=Sn(e.field,se),ce=Ge(m=>{let $=F.safeParse(m).error?.issues.map(N=>N.message)??[],ue=e.field.validation?.custom,Ye=ue?Un(m,ue,N=>n.get(Be(N)),u.current):[];v([...$,...Ye])},[e.field.validation?.custom,F,v,n]),ht=Ge((m,y)=>{if(p){r(()=>{y({value:m})},500);return}y(Qe(m,b,t))},[b,t,p,r]);ji(()=>{if(s.current||!e.value)return;if(!e.field.event?.change){s.current=!0;return}if(!((!Fe(e.field)||!!b&&b.length>0)&&U(se)))return;s.current=!0;let y=String(se),$=p?{value:y}:Qe(y,b,t);He.current?.($)},[b,se,t,p,e.field,e.value]);let so=Ge(m=>{let y=m.target.value;!x&&l()&&(!p||y===c.current)||(xt.current?.(y),e.config.validation.change&&ce(y),e.field.event?.change&&ht(y,$=>{He.current?.($)}))},[ht,x,p,e.config.validation.change,e.field.event?.change,l,ce]),co=Ge(m=>{if(!x){let y=m.target.value;e.config.validation.blur&&ce(y)}},[x,e.config.validation.blur,ce]);return Ve(e.config.inputs[e.field.type],m=>Fr(dr,{config:e.config,context:e.context,field:e.field,orientation:e.orientation,translations:e.translations,children:Fr(m,{...C,...e.ariaAttributes,...e.dataAttributes,...ao,onBlur:co,onChange:so})}))}import{jsx as Nr}from"react/jsx-runtime";function Er(e){return!e.errors||e.errors.length===0?null:Nr("ul",{className:"text-sm text-red-600 dark:text-red-500",id:e.name?`${e.name}-error`:void 0,children:e.errors?.map((t,n)=>Nr("li",{children:t},e.name?`${e.name}-error-${n}`:n))})}import{twMerge as nl}from"tailwind-merge";import{jsx as rl}from"react/jsx-runtime";function $e(e){let t=e.errors&&e.errors.length>0;return rl("div",{"data-slot":"field","data-clickable":e.isClickable?"true":"false",...t&&{[Mt]:"true"},...e.disabled&&{[_t]:"true"},"data-orientation":e.orientation,className:nl("group flex w-full flex-col items-center data-[invalid=true]:text-red-600 data-[invalid=true]:dark:text-red-500","data-[clickable=true]:items-start",e.isCheckbox&&(e.isReversed?"flex-row-reverse!":"flex-row!"),"data-[clickable=true]:has-[>[data-slot=field-content]]:[&>:first-child]:mt-px",e.className),children:e.children})}import{twMerge as ol}from"tailwind-merge";import{jsx as il}from"react/jsx-runtime";function kr(e){return il($e,{...e,orientation:V,className:ol("gap-3 has-[>[data-slot=field-content]]:items-start",!e.isClickable&&"[&>*]:w-full"),children:e.children})}import{twMerge as ll}from"tailwind-merge";import{jsx as al}from"react/jsx-runtime";function Ir(e){return al($e,{...e,orientation:Z,className:ll("gap-2 md:flex-row md:gap-4","[&>[data-slot=field-content]]:min-w-0 [&>[data-slot=field-content]]:flex-grow [&>[data-slot=field-content]]:self-start","[&_[role=checkbox]]:mt-[1.5px]",e.isClickable&&"md:flex-col",!e.isClickable&&["md:justify-between","[&>*:not([data-slot=field-content])]:w-full","[&>*:not([data-slot=field-content])]:md:w-1/2","[&>*:not([data-slot=field-content])]:xl:w-2/5"]),children:e.children})}import{jsx as wr}from"react/jsx-runtime";function Lr(e){let t=Ae(e.field),n=R(e.field),r=dn(e.field);return e.orientation===V?wr(kr,{disabled:e.disabled,errors:e.errors,isCheckbox:n,isReversed:r,isClickable:t,children:e.children}):wr(Ir,{disabled:e.disabled,errors:e.errors,isCheckbox:n,isReversed:r,isClickable:t,children:e.children})}function Pr(e){if(!e.field.type)return null;let t=yn(e.field,e.disabled),n=Nn(e.field),r=Cn(e.field,e.errors),o={...e.field,disabled:t.disabled};return e.children({ariaAttributes:r,commonProps:t,dataAttributes:n,field:o,orientation:e.orientation})}import{twMerge as sl}from"tailwind-merge";import{jsx as ft,jsxs as cl}from"react/jsx-runtime";function Or(e){let t=e.field.advanced?.cols,n=e.field.name?e.errors?.[e.field.name]:void 0,{orientation:r}=ke(e.style,{orientation:un(e.field)}),o=fn(e.field,e.disabled);return cl("div",{className:sl("flex flex-col gap-3",wn(t)),children:[ft(Lr,{disabled:o,errors:n,field:e.field,orientation:r,children:ft(Pr,{disabled:o,errors:n,field:e.field,orientation:r,children:e.children})}),ft(Er,{errors:n,name:e.field.name})]})}import{useAtomValue as ul}from"jotai";import{jsx as ml}from"react/jsx-runtime";function Vr(e){return(t,n)=>o=>{let i=ul(e(o.field.name)),l=n(i,o);return l===null?null:ml(t,{...o,...l})}}var dl=Vr(De);function Dr(e){return dl(e,(t,n)=>({errors:t?{[n.field.name]:t}:void 0}))}var fl=Vr(er);function Mr(e){return fl(e,(t,n)=>t?.hidden??n.field.hidden??!1?null:{disabled:t?.disabled??n.disabled})}var _r=Mr(Dr(Or));import{twMerge as gl}from"tailwind-merge";import{jsx as oe,jsxs as Ue}from"react/jsx-runtime";function Br(e){function t(){e.canRemove&&e.onRemove&&e.onRemove(e.index)}let n=e.canRemove&&e.onRemove!=null&&oe("button",{"aria-label":`Remove ${e.label} item ${e.index+1}`,className:gl("rounded p-1 text-xl text-slate-400","transition-colors duration-150","hover:text-red-500","focus-visible:ring-2 focus-visible:ring-slate-400 focus-visible:outline-none","dark:text-slate-500 dark:hover:text-red-400"),onClick:t,type:"button",children:oe("span",{"aria-hidden":"true",children:"\xD7"})});return e.isMultiField?Ue("div",{className:"rounded-lg border border-slate-100 p-4 dark:border-slate-900",children:[Ue("div",{className:"mb-3 flex items-center justify-between",children:[Ue("span",{className:"text-sm font-medium text-slate-400 dark:text-slate-500",children:[e.label," ",e.index+1]}),n]}),oe(H,{children:e.children})]}):Ue("div",{className:"flex items-start gap-2",children:[oe(H,{children:e.children}),n&&oe("div",{className:"shrink-0",children:n})]})}import{twMerge as xl}from"tailwind-merge";import{useSetAtom as pl}from"jotai";import{useCallback as Gr,useLayoutEffect as yl,useRef as $r,useState as bl}from"react";function Ur(e,t){let n=e.advanced?.length?.min??1,r=e.advanced?.length?.max??1/0,[o,i]=bl(()=>Pn(e,t)),l=$r(o.length),a=$r(o);yl(()=>{a.current=o});let s=pl(_e),c=Gr(()=>{i(A=>{if(A.length>=r)return A;let P=l.current++;return[...A,P]})},[r]),u=Gr(A=>{if(a.current.length<=n)return;let P=a.current[A];i(v=>v.length<=n?v:v.filter((b,I)=>I!==A)),s(v=>{let b={...v},I=`${e.name}.`,F=[];for(let T of e.fields)if(B(T))for(let O of T.fields)F.push(O.name);else F.push(T.name);for(let T of F)delete b[`${I}${P}.${T}`];return b})},[e.name,e.fields,n,s]),p=o.length<r,x=o.length>n;return[o,c,u,p,x,r]}import{Fragment as hl,jsx as Hr,jsxs as mt}from"react/jsx-runtime";function Yr(e){let[t,n,r,o,i,l]=Ur(e.field,e.value),a=On(e.field),s=e.field.advanced?.action??"Add item",c=l!==1/0,u=Ln(e.field);return mt(hl,{children:[t.map((p,x)=>Hr(Br,{canRemove:i,index:x,isMultiField:u,label:a,onRemove:r,children:e.children(p)},p)),mt("button",{"aria-disabled":!o,"aria-label":c?`${s}, ${t.length} of ${l}`:s,className:xl("flex w-full items-center gap-1.5 rounded py-1","text-sm font-medium text-slate-500","transition-colors duration-150","hover:text-slate-800","focus-visible:ring-2 focus-visible:ring-slate-400 focus-visible:ring-offset-2 focus-visible:outline-none","dark:text-slate-400 dark:hover:text-slate-200",!o&&"cursor-not-allowed opacity-50 hover:text-slate-500 dark:hover:text-slate-400"),disabled:!o,onClick:n,type:"button",children:[Hr("span",{"aria-hidden":"true",children:"+"}),s,c&&mt("span",{"aria-hidden":"true",className:"ml-auto text-slate-400 tabular-nums dark:text-slate-500",children:[t.length," / ",l]})]})]})}import{jsx as Rl}from"react/jsx-runtime";function Xr(e){let t=Array.isArray(e.field.fields)&&e.field.fields.length===0;return Rl(Ie,{description:e.field.description,empty:t,id:e.field.name,title:e.field.label,children:e.children})}import{jsx as gt}from"react/jsx-runtime";function qr({children:e,field:t,value:n}){return gt(Pe,{container:t,fields:t.fields,children:gt(Xr,{field:t,children:gt(Yr,{field:t,value:n,children:e})})})}import{twMerge as Tl}from"tailwind-merge";import{jsx as Zr}from"react/jsx-runtime";function Kr(e){let t=In(e.column?.advanced?.cols);return Zr("div",{className:"flex w-full flex-col gap-4",children:Zr("div",{className:Tl("grid grid-cols-1 gap-3 sm:gap-4",t),children:e.children})})}import{Fragment as Al}from"react";import{jsx as Sl}from"react/jsx-runtime";function Wr(e){let t=Array.isArray(e.field.fields)?e.field.fields.map(n=>ve(n)?{...n,name:`${e.field.name}.${e.index}.${n.name}`}:B(n)?{...n,fields:n.fields.map(r=>({...r,name:`${e.field.name}.${e.index}.${r.name}`}))}:n):[];return Sl(ie,{children:e.children,components:e.components,disabled:e.disabled,fields:t,style:e.style,value:e.value})}import{jsx as le,jsxs as vl}from"react/jsx-runtime";function ie(e){let{field:t,list:n}=e.components;return Ee(e.fields).map((r,o)=>vl(Al,{children:[B(r)&&le(Kr,{column:r,children:le(ie,{...e,fields:r.fields})}),ve(r)&&le(t,{disabled:e.disabled,field:r,style:e.style,children:e.children}),an(r)&&le(n,{field:r,value:e.value,children:i=>le(Wr,{children:e.children,components:e.components,disabled:e.disabled,field:r,index:i,style:e.style,value:e.value})})]},o))}import{jsx as Fl}from"react/jsx-runtime";function zr(e){return n=>Fl(ie,{...n,components:e})}var Jr=zr({field:_r,list:qr});import{useSetAtom as Qr}from"jotai";import{startTransition as jr,useActionState as Cl}from"react";function to(e,t,n){let{onSuccess:r,preserveValues:o=!1,validation:i=!0,translations:l}=n??{},a=Qr(mr),s=Qr(gr),c={data:null,error:null,success:!1},[u,p,x]=Cl(async(A,P)=>{let[v,b]=e(),I=Dn(v,b,l);if(i===!1)return t?await t(P,I):A;let F=zt(P),T=I.safeParse(F);if(!T.success){let C=Mn(T.error);return jr(()=>{a(C)}),pt(F,{description:f("Please correct the errors and try again.",l),details:[],title:f("There were validation errors submitting the form.",l)})}let O=Jt(F);if(t)try{let C=await t(O,I);return C.success?(r?.(C.data),o||jr(()=>{s()}),eo(O,o)):pt(O,C.error)}catch(C){return j.error("Error executing form action:",C),pt(O,{title:f("An unexpected error occurred submitting the form.",l),details:Nl(C,l)})}return eo(T.data,o)},c);return[p,u,x]}function Nl(e,t){return e instanceof Error?[e.message]:[f("Unknown error",t)]}function eo(e,t=!1){return{data:t?e:null,error:null,success:!0}}function pt(e,t){return{data:e,error:t,success:!1}}import{useCallback as bt,useRef as ro}from"react";import{useCallback as El}from"react";import{useSetAtom as yt}from"jotai";function no(){let e=yt(fr),t=yt(pr),n=yt(xr);return El(r=>{let o=Array.isArray(r)?r:[r];e(o),n(o),t(o)},[e,n,t])}function oo(){let e=no(),t=ro({}),n=ro([]),r=bt((l,a,s)=>{l in t.current||(t.current[l]=a,n.current.push(s))},[]),o=bt(l=>{t.current[l]&&(delete t.current[l],n.current=n.current.filter(a=>a.name!==l),e([l]))},[e]);return[bt(()=>[t.current,n.current],[]),r,o]}import{Fragment as kl,jsx as ae,jsxs as Il}from"react/jsx-runtime";function io(e){let t=e.translations?.[e.lang??""],[n,r,o]=oo(),[i,l,a]=to(n,e.action,{onSuccess:e.onSuccess,validation:e.config.validation.submit,translations:t}),s=e.config.validation.showError&&!l.success&&l.error,c=l.data??e.value;return Il(kl,{children:[s&&Ve(e.config.alert,u=>ae("div",{className:"mb-4 w-full",children:ae(u,{description:l.error?.description,details:l.error?.details,title:l.error.title})})),ae(ir,{action:i,config:e.config,control:e.children,definition:e.definition,isPending:a,noValidate:!0,readOnly:e.readOnly,sections:e.sections,children:({disabled:u,fields:p})=>ae(Jr,{disabled:u,fields:p,style:e.config.style,value:c,children:x=>ae(Cr,{...x,config:e.config,context:e.context,onMount:r,onUnmount:o,onValueChange:e.onValueChange,translations:t,value:c})})})]})}import{Provider as wl}from"jotai";import{jsx as lo}from"react/jsx-runtime";function Ll(e){return lo(wl,{children:lo(io,{...e})})}export{Ll as Form};