react-luna-form 0.0.40 → 0.0.42
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/cjs/index.js +1 -1
- package/dist/client/esm/index.js +1 -1
- package/dist/server/cjs/index.js +1 -1
- package/dist/server/esm/index.js +1 -1
- package/dist/timezone/cjs/index.js +1 -0
- package/dist/timezone/esm/chunk-6YOSEW3U.js +1 -0
- package/dist/timezone/esm/chunk-AJTG6FUX.js +1 -0
- package/dist/timezone/esm/chunk-EFQWCKYQ.js +818 -0
- package/dist/timezone/esm/chunk-JRS2SJNX.js +818 -0
- package/dist/timezone/esm/index.js +1 -0
- package/dist/timezone/esm/input-timezone-3TSHVJH7.js +766 -0
- package/dist/timezone/esm/input-timezone-D6UUK3LG.js +1 -0
- package/dist/timezone/esm/input-timezone-E45Y56W6.js +766 -0
- package/dist/timezone/esm/input-timezone-K27DM6BM.js +1 -0
- package/dist/timezone/esm/timezone-data-G5A3C2I7.js +1 -0
- package/dist/timezone/esm/timezone-data-LPD7JMNB.js +412 -0
- package/dist/timezone/esm/timezone-data-STGETEL3.js +1 -0
- package/dist/timezone/esm/timezone-data-XTIMFTET.js +412 -0
- package/dist/types/luna-react/src/client/component/input-base.d.ts +7 -0
- package/dist/types/luna-react/src/client/component/input-create.d.ts +3 -0
- package/dist/types/luna-react/src/client/component/input-dateable.d.ts +1 -0
- package/dist/types/luna-react/src/client/component/input-registry.d.ts +8 -0
- package/dist/types/luna-react/src/client/component/input-selectable.d.ts +1 -0
- package/dist/types/luna-react/src/client/component/input-strategies.d.ts +29 -0
- package/dist/types/luna-react/src/client/component/input-textable.d.ts +1 -0
- package/dist/types/luna-react/src/client/component/input-timezone.d.ts +2 -0
- package/dist/types/luna-react/src/client/component/input.d.ts +2 -16
- package/dist/types/luna-react/src/client/hook/use-input-core.d.ts +42 -0
- package/dist/types/luna-react/src/client/hook/use-timezone-options.d.ts +7 -0
- package/dist/types/luna-react/src/client/hook/use-write-only-source.d.ts +7 -0
- package/dist/types/luna-react/src/timezone/index.d.ts +3 -0
- package/package.json +12 -3
- package/dist/types/luna-react/src/client/component/input-date.d.ts +0 -16
|
@@ -0,0 +1,766 @@
|
|
|
1
|
+
import {
|
|
2
|
+
formatMarkdown,
|
|
3
|
+
getEntity,
|
|
4
|
+
getSchema,
|
|
5
|
+
handleProxyEvent,
|
|
6
|
+
handleSourceEvent,
|
|
7
|
+
handleStateEvent,
|
|
8
|
+
handleValueEvent,
|
|
9
|
+
interpolateIfNeeded,
|
|
10
|
+
isCheckbox,
|
|
11
|
+
isClickable,
|
|
12
|
+
isOptions,
|
|
13
|
+
isRadio,
|
|
14
|
+
isValidValue,
|
|
15
|
+
loadTimezones,
|
|
16
|
+
mergeSource,
|
|
17
|
+
prepareInputProps,
|
|
18
|
+
prepareInputValue,
|
|
19
|
+
translate,
|
|
20
|
+
validateCustom
|
|
21
|
+
} from "./chunk-EFQWCKYQ.js";
|
|
22
|
+
|
|
23
|
+
// src/component/description.tsx
|
|
24
|
+
import { jsx } from "react/jsx-runtime";
|
|
25
|
+
function Description(props) {
|
|
26
|
+
return /* @__PURE__ */ jsx("p", { className: "-mt-2 text-xs leading-normal font-normal text-slate-600 dark:text-slate-400", children: props.children });
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// src/lib/string.tsx
|
|
30
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
31
|
+
function formatMarkdown2(text) {
|
|
32
|
+
return formatMarkdown(
|
|
33
|
+
text,
|
|
34
|
+
(index, url, text2) => {
|
|
35
|
+
return /* @__PURE__ */ jsx2(
|
|
36
|
+
"a",
|
|
37
|
+
{
|
|
38
|
+
className: "underline",
|
|
39
|
+
href: url,
|
|
40
|
+
rel: "noopener noreferrer",
|
|
41
|
+
target: "_blank",
|
|
42
|
+
children: text2
|
|
43
|
+
},
|
|
44
|
+
`${url}-${index}`
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// src/component/formatted-description.tsx
|
|
51
|
+
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
52
|
+
function FormattedDescription(props) {
|
|
53
|
+
const interpolateOpts = {
|
|
54
|
+
context: props.context,
|
|
55
|
+
env: props.config?.env
|
|
56
|
+
};
|
|
57
|
+
const text = translate(
|
|
58
|
+
interpolateIfNeeded(props.text, interpolateOpts),
|
|
59
|
+
props.translations
|
|
60
|
+
);
|
|
61
|
+
const content = formatMarkdown2(text);
|
|
62
|
+
if (content) {
|
|
63
|
+
return /* @__PURE__ */ jsx3(Description, { children: content });
|
|
64
|
+
}
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// src/component/label.tsx
|
|
69
|
+
import { twMerge } from "tailwind-merge";
|
|
70
|
+
import { jsx as jsx4, jsxs } from "react/jsx-runtime";
|
|
71
|
+
function Label(props) {
|
|
72
|
+
const showOptionalLabel = props.style?.showOptionalLabel ?? true;
|
|
73
|
+
const normal = isRadio(props.field) || isCheckbox(props.field);
|
|
74
|
+
return /* @__PURE__ */ jsxs(
|
|
75
|
+
"label",
|
|
76
|
+
{
|
|
77
|
+
"data-slot": "field-label",
|
|
78
|
+
"data-normal": normal,
|
|
79
|
+
className: twMerge(
|
|
80
|
+
"flex w-fit items-center gap-2 text-sm leading-snug font-medium select-none",
|
|
81
|
+
"data-[normal=true]:font-normal",
|
|
82
|
+
"group-data-[readonly=true]:cursor-not-allowed group-data-[readonly=true]:opacity-50"
|
|
83
|
+
),
|
|
84
|
+
htmlFor: props.field.name,
|
|
85
|
+
children: [
|
|
86
|
+
props.children,
|
|
87
|
+
showOptionalLabel && !props.field.required && /* @__PURE__ */ jsx4("span", { className: "text-sm text-slate-600 dark:text-slate-400", children: translate("(Optional)", props.translations) })
|
|
88
|
+
]
|
|
89
|
+
}
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// src/component/input-label.tsx
|
|
94
|
+
import { jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
95
|
+
function InputLabel(props) {
|
|
96
|
+
const interpolateOpts = {
|
|
97
|
+
context: props.context,
|
|
98
|
+
env: props.config?.env
|
|
99
|
+
};
|
|
100
|
+
const label = interpolateIfNeeded(props.field.label, interpolateOpts);
|
|
101
|
+
return /* @__PURE__ */ jsxs2(
|
|
102
|
+
"div",
|
|
103
|
+
{
|
|
104
|
+
"data-slot": "field-content",
|
|
105
|
+
className: "flex w-full flex-1 flex-col gap-1.5 leading-snug",
|
|
106
|
+
children: [
|
|
107
|
+
/* @__PURE__ */ jsx5(
|
|
108
|
+
Label,
|
|
109
|
+
{
|
|
110
|
+
field: props.field,
|
|
111
|
+
style: props.config?.style,
|
|
112
|
+
translations: props.translations,
|
|
113
|
+
children: translate(label, props.translations)
|
|
114
|
+
}
|
|
115
|
+
),
|
|
116
|
+
props.horizontal === true && /* @__PURE__ */ jsx5(
|
|
117
|
+
FormattedDescription,
|
|
118
|
+
{
|
|
119
|
+
config: props.config,
|
|
120
|
+
context: props.context,
|
|
121
|
+
text: props.field.description,
|
|
122
|
+
translations: props.translations
|
|
123
|
+
}
|
|
124
|
+
)
|
|
125
|
+
]
|
|
126
|
+
}
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// src/component/input-group.tsx
|
|
131
|
+
import { Fragment, jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
132
|
+
function InputGroup(props) {
|
|
133
|
+
return /* @__PURE__ */ jsxs3(Fragment, { children: [
|
|
134
|
+
props.field.name && props.field.label && /* @__PURE__ */ jsx6(
|
|
135
|
+
InputLabel,
|
|
136
|
+
{
|
|
137
|
+
config: props.config,
|
|
138
|
+
context: props.context,
|
|
139
|
+
field: props.field,
|
|
140
|
+
horizontal: props.horizontal,
|
|
141
|
+
translations: props.translations
|
|
142
|
+
}
|
|
143
|
+
),
|
|
144
|
+
props.children,
|
|
145
|
+
props.horizontal === false && /* @__PURE__ */ jsx6(
|
|
146
|
+
FormattedDescription,
|
|
147
|
+
{
|
|
148
|
+
config: props.config,
|
|
149
|
+
context: props.context,
|
|
150
|
+
text: props.field.description,
|
|
151
|
+
translations: props.translations
|
|
152
|
+
}
|
|
153
|
+
)
|
|
154
|
+
] });
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// src/lib/render-If-exists.ts
|
|
158
|
+
function renderIfExists(value, render) {
|
|
159
|
+
if (!value) {
|
|
160
|
+
return null;
|
|
161
|
+
}
|
|
162
|
+
return render(value);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// src/client/component/input-base.tsx
|
|
166
|
+
import { useCallback as useCallback4, useEffect as useEffect4, useRef as useRef4 } from "react";
|
|
167
|
+
|
|
168
|
+
// src/client/lib/store-helper.ts
|
|
169
|
+
import { atom } from "jotai";
|
|
170
|
+
import { atomFamily } from "jotai-family";
|
|
171
|
+
import { deepEqual } from "fast-equals";
|
|
172
|
+
function omitKey(obj, key) {
|
|
173
|
+
const { [key]: _removed, ...rest } = obj;
|
|
174
|
+
return rest;
|
|
175
|
+
}
|
|
176
|
+
function createRecordAtomFamily(baseAtom) {
|
|
177
|
+
return atomFamily(
|
|
178
|
+
(name) => atom(
|
|
179
|
+
(get) => {
|
|
180
|
+
return get(baseAtom)[name] ?? void 0;
|
|
181
|
+
},
|
|
182
|
+
(get, set, newValue) => {
|
|
183
|
+
const current = get(baseAtom);
|
|
184
|
+
if (newValue !== void 0 && newValue !== null) {
|
|
185
|
+
const currentValue = current[name];
|
|
186
|
+
if (!deepEqual(currentValue, newValue)) {
|
|
187
|
+
set(baseAtom, { ...current, [name]: newValue });
|
|
188
|
+
}
|
|
189
|
+
} else if (name in current) {
|
|
190
|
+
set(baseAtom, omitKey(current, name));
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
)
|
|
194
|
+
);
|
|
195
|
+
}
|
|
196
|
+
function createClearAllAtom(baseAtom) {
|
|
197
|
+
return atom(null, (get, set) => {
|
|
198
|
+
const current = get(baseAtom);
|
|
199
|
+
if (current && Object.keys(current).length > 0) {
|
|
200
|
+
set(baseAtom, {});
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
function createClearAtom(baseAtom) {
|
|
205
|
+
return atom(null, (get, set, names) => {
|
|
206
|
+
const current = get(baseAtom);
|
|
207
|
+
const next = { ...current };
|
|
208
|
+
let hasChanges = false;
|
|
209
|
+
for (const name of names) {
|
|
210
|
+
if (name in next) {
|
|
211
|
+
delete next[name];
|
|
212
|
+
hasChanges = true;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
if (hasChanges) {
|
|
216
|
+
set(baseAtom, next);
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
function createBulkReportAtom(baseAtom) {
|
|
221
|
+
return atom(null, (get, set, newValue) => {
|
|
222
|
+
const current = get(baseAtom);
|
|
223
|
+
if (!deepEqual(current, newValue)) {
|
|
224
|
+
set(baseAtom, newValue);
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
function createNestedRecordAtomFamily(baseAtom, options = {}) {
|
|
229
|
+
const { merge: merge2, validateTarget } = options;
|
|
230
|
+
return atomFamily(
|
|
231
|
+
(contributorName) => atom(
|
|
232
|
+
(get) => {
|
|
233
|
+
const current = get(baseAtom)[contributorName];
|
|
234
|
+
if (current && merge2) {
|
|
235
|
+
return merge2(Object.values(current));
|
|
236
|
+
}
|
|
237
|
+
return void 0;
|
|
238
|
+
},
|
|
239
|
+
(get, set, target, value) => {
|
|
240
|
+
if (validateTarget && !validateTarget(target)) {
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
const current = get(baseAtom);
|
|
244
|
+
const targetContributions = { ...current[target] ?? {} };
|
|
245
|
+
if (value !== void 0 && value !== null) {
|
|
246
|
+
const currentContribution = targetContributions[contributorName];
|
|
247
|
+
if (!currentContribution || !deepEqual(currentContribution, value)) {
|
|
248
|
+
targetContributions[contributorName] = value;
|
|
249
|
+
set(baseAtom, {
|
|
250
|
+
...current,
|
|
251
|
+
[target]: targetContributions
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
} else if (contributorName in targetContributions) {
|
|
255
|
+
delete targetContributions[contributorName];
|
|
256
|
+
if (Object.keys(targetContributions).length === 0) {
|
|
257
|
+
set(baseAtom, omitKey(current, target));
|
|
258
|
+
} else {
|
|
259
|
+
set(baseAtom, {
|
|
260
|
+
...current,
|
|
261
|
+
[target]: targetContributions
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
)
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
function createNestedClearAtom(baseAtom) {
|
|
270
|
+
return atom(null, (get, set, contributorNames) => {
|
|
271
|
+
const current = get(baseAtom);
|
|
272
|
+
const next = { ...current };
|
|
273
|
+
let hasChanges = false;
|
|
274
|
+
for (const name of contributorNames) {
|
|
275
|
+
if (name in next) {
|
|
276
|
+
delete next[name];
|
|
277
|
+
hasChanges = true;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
for (const target in next) {
|
|
281
|
+
const targetContributions = { ...next[target] };
|
|
282
|
+
let targetChanged = false;
|
|
283
|
+
for (const contributorName of contributorNames) {
|
|
284
|
+
if (contributorName in targetContributions) {
|
|
285
|
+
delete targetContributions[contributorName];
|
|
286
|
+
targetChanged = true;
|
|
287
|
+
hasChanges = true;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
if (targetChanged) {
|
|
291
|
+
if (Object.keys(targetContributions).length === 0) {
|
|
292
|
+
delete next[target];
|
|
293
|
+
} else {
|
|
294
|
+
next[target] = targetContributions;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
if (hasChanges) {
|
|
299
|
+
set(baseAtom, next);
|
|
300
|
+
}
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
function createAtomStore(initialValue = {}) {
|
|
304
|
+
const baseAtom = atom(initialValue);
|
|
305
|
+
return {
|
|
306
|
+
atom: baseAtom,
|
|
307
|
+
clearAll: createClearAllAtom(baseAtom),
|
|
308
|
+
clear: createClearAtom(baseAtom),
|
|
309
|
+
bulkReport: createBulkReportAtom(baseAtom),
|
|
310
|
+
report: createRecordAtomFamily(baseAtom)
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// src/client/lib/state-store.ts
|
|
315
|
+
var store = createAtomStore();
|
|
316
|
+
var fieldStateAtom = store.atom;
|
|
317
|
+
var reportFieldStateAtom = store.report;
|
|
318
|
+
|
|
319
|
+
// src/client/lib/error-store.ts
|
|
320
|
+
var store2 = createAtomStore();
|
|
321
|
+
var clearInputErrorAtom = store2.clear;
|
|
322
|
+
var reportErrorAtom = store2.bulkReport;
|
|
323
|
+
var reportInputErrorAtom = store2.report;
|
|
324
|
+
|
|
325
|
+
// src/client/lib/value-store.ts
|
|
326
|
+
var store3 = createAtomStore();
|
|
327
|
+
var valueAtom = store3.atom;
|
|
328
|
+
var clearAllValueAtom = store3.clearAll;
|
|
329
|
+
var clearInputValueAtom = store3.clear;
|
|
330
|
+
var reportValueAtom = store3.report;
|
|
331
|
+
|
|
332
|
+
// src/client/hook/use-input-core.ts
|
|
333
|
+
import { useCallback as useCallback2, useRef as useRef2, useTransition } from "react";
|
|
334
|
+
|
|
335
|
+
// src/client/hook/use-input.ts
|
|
336
|
+
import { useEffect, useEffectEvent, useMemo } from "react";
|
|
337
|
+
function useInput(field, onMount, onUnmount, translations) {
|
|
338
|
+
const { name } = field;
|
|
339
|
+
const schema = useMemo(
|
|
340
|
+
() => getSchema(field, translations),
|
|
341
|
+
[field, translations]
|
|
342
|
+
);
|
|
343
|
+
const onMountHandler = useEffectEvent((name2) => {
|
|
344
|
+
if (name2) {
|
|
345
|
+
onMount(name2, schema, field);
|
|
346
|
+
}
|
|
347
|
+
});
|
|
348
|
+
const onUnmountHandler = useEffectEvent((name2) => {
|
|
349
|
+
if (name2) {
|
|
350
|
+
onUnmount(name2);
|
|
351
|
+
}
|
|
352
|
+
});
|
|
353
|
+
useEffect(() => {
|
|
354
|
+
onMountHandler(name);
|
|
355
|
+
return () => {
|
|
356
|
+
onUnmountHandler(name);
|
|
357
|
+
};
|
|
358
|
+
}, [name]);
|
|
359
|
+
return schema;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// src/client/hook/use-input-core.ts
|
|
363
|
+
import { useSetAtom, useStore } from "jotai";
|
|
364
|
+
|
|
365
|
+
// src/client/hook/use-timeout.ts
|
|
366
|
+
import { useCallback, useEffect as useEffect2, useRef } from "react";
|
|
367
|
+
function useTimeout() {
|
|
368
|
+
const timeoutRef = useRef(null);
|
|
369
|
+
useEffect2(() => {
|
|
370
|
+
return () => {
|
|
371
|
+
if (timeoutRef.current) {
|
|
372
|
+
clearTimeout(timeoutRef.current);
|
|
373
|
+
}
|
|
374
|
+
};
|
|
375
|
+
}, []);
|
|
376
|
+
const setTimeoutRef = useCallback((callback, delay) => {
|
|
377
|
+
if (timeoutRef.current) {
|
|
378
|
+
clearTimeout(timeoutRef.current);
|
|
379
|
+
timeoutRef.current = null;
|
|
380
|
+
}
|
|
381
|
+
timeoutRef.current = setTimeout(callback, delay);
|
|
382
|
+
}, []);
|
|
383
|
+
return setTimeoutRef;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
// src/client/hook/use-input-core.ts
|
|
387
|
+
function useInputCore(props, deps) {
|
|
388
|
+
const store4 = useStore();
|
|
389
|
+
const entity = props.field.advanced?.entity;
|
|
390
|
+
const setTimeoutRef = useTimeout();
|
|
391
|
+
const [, startTransition] = useTransition();
|
|
392
|
+
const { setValue, shouldSkipOnChange, value, setSource } = deps;
|
|
393
|
+
const valueRef = useRef2(value);
|
|
394
|
+
valueRef.current = value;
|
|
395
|
+
const translationsRef = useRef2(props.translations);
|
|
396
|
+
translationsRef.current = props.translations;
|
|
397
|
+
const hasClickable = isClickable(props.field);
|
|
398
|
+
const setValues = useSetAtom(valueAtom);
|
|
399
|
+
const setFieldStates = useSetAtom(fieldStateAtom);
|
|
400
|
+
const setErrors = useSetAtom(reportInputErrorAtom(props.field.name));
|
|
401
|
+
const schema = useInput(
|
|
402
|
+
props.field,
|
|
403
|
+
props.onMount,
|
|
404
|
+
props.onUnmount,
|
|
405
|
+
props.translations
|
|
406
|
+
);
|
|
407
|
+
const placeholder = translate(
|
|
408
|
+
props.commonProps.placeholder,
|
|
409
|
+
props.translations
|
|
410
|
+
);
|
|
411
|
+
const commonProps = {
|
|
412
|
+
...props.commonProps,
|
|
413
|
+
placeholder
|
|
414
|
+
};
|
|
415
|
+
const onValueChangeRef = useRef2(null);
|
|
416
|
+
onValueChangeRef.current = (value2) => {
|
|
417
|
+
setValue(value2);
|
|
418
|
+
if (props.onValueChange) {
|
|
419
|
+
const attributes = props.dataAttributes ?? {};
|
|
420
|
+
props.onValueChange({
|
|
421
|
+
data: Object.keys(attributes).length > 0 ? attributes : void 0,
|
|
422
|
+
name: props.field.name,
|
|
423
|
+
type: props.field.type,
|
|
424
|
+
value: value2
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
};
|
|
428
|
+
const applyChangeEventsRef = useRef2(
|
|
429
|
+
null
|
|
430
|
+
);
|
|
431
|
+
applyChangeEventsRef.current = (selected) => {
|
|
432
|
+
const events = props.field.event?.change;
|
|
433
|
+
if (!events) {
|
|
434
|
+
return;
|
|
435
|
+
}
|
|
436
|
+
handleProxyEvent(events, ({ sources, states, values }) => {
|
|
437
|
+
startTransition(() => {
|
|
438
|
+
handleSourceEvent(
|
|
439
|
+
selected,
|
|
440
|
+
sources,
|
|
441
|
+
(target, source) => setSource(target, source)
|
|
442
|
+
);
|
|
443
|
+
handleStateEvent(selected, states, (targets, state) => {
|
|
444
|
+
setFieldStates((prev) => {
|
|
445
|
+
if (state) {
|
|
446
|
+
return targets.reduce(
|
|
447
|
+
(acc, target) => ({
|
|
448
|
+
...acc,
|
|
449
|
+
[target]: state
|
|
450
|
+
}),
|
|
451
|
+
prev
|
|
452
|
+
);
|
|
453
|
+
}
|
|
454
|
+
return targets.reduce((acc, target) => omitKey(acc, target), prev);
|
|
455
|
+
});
|
|
456
|
+
});
|
|
457
|
+
handleValueEvent(selected, values, (target, value2) => {
|
|
458
|
+
setValues((prev) => ({
|
|
459
|
+
...prev,
|
|
460
|
+
[target]: value2
|
|
461
|
+
}));
|
|
462
|
+
});
|
|
463
|
+
});
|
|
464
|
+
});
|
|
465
|
+
};
|
|
466
|
+
const validated = useCallback2(
|
|
467
|
+
(value2) => {
|
|
468
|
+
const results = schema.safeParse(value2);
|
|
469
|
+
const errors = results.error?.issues.map((issue) => issue.message) ?? [];
|
|
470
|
+
const custom = props.field.validation?.custom;
|
|
471
|
+
const customErrors = custom ? validateCustom(
|
|
472
|
+
value2,
|
|
473
|
+
custom,
|
|
474
|
+
(name) => store4.get(reportValueAtom(name)),
|
|
475
|
+
translationsRef.current
|
|
476
|
+
) : [];
|
|
477
|
+
setErrors([...errors, ...customErrors]);
|
|
478
|
+
},
|
|
479
|
+
[props.field.validation?.custom, schema, setErrors, store4]
|
|
480
|
+
);
|
|
481
|
+
const onBlur = useCallback2(
|
|
482
|
+
(event) => {
|
|
483
|
+
if (!hasClickable) {
|
|
484
|
+
const value2 = event.target.value;
|
|
485
|
+
if (props.config.validation.blur) {
|
|
486
|
+
validated(value2);
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
},
|
|
490
|
+
[hasClickable, props.config.validation.blur, validated]
|
|
491
|
+
);
|
|
492
|
+
return {
|
|
493
|
+
applyChangeEventsRef,
|
|
494
|
+
commonProps,
|
|
495
|
+
entity,
|
|
496
|
+
hasClickable,
|
|
497
|
+
onBlur,
|
|
498
|
+
onValueChangeRef,
|
|
499
|
+
setTimeoutRef,
|
|
500
|
+
shouldSkipOnChange,
|
|
501
|
+
validated,
|
|
502
|
+
valueRef
|
|
503
|
+
};
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
// src/client/hook/use-value.ts
|
|
507
|
+
import { deepEqual as deepEqual2 } from "fast-equals";
|
|
508
|
+
import { useAtom } from "jotai";
|
|
509
|
+
import { useCallback as useCallback3, useEffect as useEffect3, useRef as useRef3, useEffectEvent as useEffectEvent2 } from "react";
|
|
510
|
+
function useValue(field, currentValue) {
|
|
511
|
+
const { name } = field;
|
|
512
|
+
const skipNextOnChangeRef = useRef3(false);
|
|
513
|
+
const [value, setValue] = useAtom(reportValueAtom(name));
|
|
514
|
+
const onCurrentValueChange = useEffectEvent2(
|
|
515
|
+
(currentValue2) => {
|
|
516
|
+
const newValue = resolveValue(name, currentValue2);
|
|
517
|
+
if (isValidValue(newValue)) {
|
|
518
|
+
if (!deepEqual2(value, newValue)) {
|
|
519
|
+
skipNextOnChangeRef.current = true;
|
|
520
|
+
}
|
|
521
|
+
setValue(newValue);
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
);
|
|
525
|
+
useEffect3(() => {
|
|
526
|
+
if (!currentValue) {
|
|
527
|
+
return;
|
|
528
|
+
}
|
|
529
|
+
onCurrentValueChange(currentValue);
|
|
530
|
+
}, [currentValue]);
|
|
531
|
+
const shouldSkipOnChange = useCallback3(() => {
|
|
532
|
+
if (skipNextOnChangeRef.current) {
|
|
533
|
+
skipNextOnChangeRef.current = false;
|
|
534
|
+
return true;
|
|
535
|
+
}
|
|
536
|
+
return false;
|
|
537
|
+
}, []);
|
|
538
|
+
return {
|
|
539
|
+
setValue,
|
|
540
|
+
shouldSkipOnChange,
|
|
541
|
+
value
|
|
542
|
+
};
|
|
543
|
+
}
|
|
544
|
+
function resolveValue(name, currentValue) {
|
|
545
|
+
if (name in currentValue) {
|
|
546
|
+
return currentValue[name];
|
|
547
|
+
}
|
|
548
|
+
if (!name.includes(".")) {
|
|
549
|
+
return void 0;
|
|
550
|
+
}
|
|
551
|
+
const keys = name.split(".");
|
|
552
|
+
let result = currentValue;
|
|
553
|
+
for (const key of keys) {
|
|
554
|
+
if (result === null || result === void 0) {
|
|
555
|
+
return void 0;
|
|
556
|
+
}
|
|
557
|
+
if (Array.isArray(result)) {
|
|
558
|
+
const index = Number(key);
|
|
559
|
+
result = Number.isInteger(index) ? result[index] : void 0;
|
|
560
|
+
} else if (typeof result === "object") {
|
|
561
|
+
result = result[key];
|
|
562
|
+
} else {
|
|
563
|
+
return void 0;
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
return result;
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
// src/client/component/input-base.tsx
|
|
570
|
+
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
571
|
+
function InputBase(props) {
|
|
572
|
+
const {
|
|
573
|
+
useSource,
|
|
574
|
+
useExtraProps,
|
|
575
|
+
getValue,
|
|
576
|
+
shouldSkipChange,
|
|
577
|
+
dispatchChange,
|
|
578
|
+
buildInitialSelected,
|
|
579
|
+
isInitialReady
|
|
580
|
+
} = props.strategies;
|
|
581
|
+
const { setValue, shouldSkipOnChange, value } = useValue(
|
|
582
|
+
props.field,
|
|
583
|
+
props.value
|
|
584
|
+
);
|
|
585
|
+
const { data, setSource } = useSource(props.field, props.config, value);
|
|
586
|
+
const {
|
|
587
|
+
applyChangeEventsRef,
|
|
588
|
+
commonProps,
|
|
589
|
+
entity,
|
|
590
|
+
hasClickable,
|
|
591
|
+
onBlur,
|
|
592
|
+
onValueChangeRef,
|
|
593
|
+
setTimeoutRef,
|
|
594
|
+
validated,
|
|
595
|
+
valueRef
|
|
596
|
+
} = useInputCore(props, { setValue, shouldSkipOnChange, value, setSource });
|
|
597
|
+
const extraProps = useExtraProps?.(props.field);
|
|
598
|
+
const initialEventsProcessedRef = useRef4(false);
|
|
599
|
+
const { commonPropsWithOptions, defaultValue } = prepareInputProps(
|
|
600
|
+
props.field,
|
|
601
|
+
commonProps,
|
|
602
|
+
data,
|
|
603
|
+
value
|
|
604
|
+
);
|
|
605
|
+
const inputProps = prepareInputValue(props.field, defaultValue);
|
|
606
|
+
useEffect4(() => {
|
|
607
|
+
if (initialEventsProcessedRef.current || !props.value) {
|
|
608
|
+
return;
|
|
609
|
+
}
|
|
610
|
+
if (!props.field.event?.change) {
|
|
611
|
+
initialEventsProcessedRef.current = true;
|
|
612
|
+
return;
|
|
613
|
+
}
|
|
614
|
+
if (!isValidValue(defaultValue)) {
|
|
615
|
+
return;
|
|
616
|
+
}
|
|
617
|
+
if (!isInitialReady(props.field, defaultValue, data)) {
|
|
618
|
+
return;
|
|
619
|
+
}
|
|
620
|
+
initialEventsProcessedRef.current = true;
|
|
621
|
+
const selected = buildInitialSelected(defaultValue, data, entity);
|
|
622
|
+
applyChangeEventsRef.current?.(selected);
|
|
623
|
+
}, [
|
|
624
|
+
applyChangeEventsRef,
|
|
625
|
+
buildInitialSelected,
|
|
626
|
+
data,
|
|
627
|
+
defaultValue,
|
|
628
|
+
entity,
|
|
629
|
+
isInitialReady,
|
|
630
|
+
props.field,
|
|
631
|
+
props.value
|
|
632
|
+
]);
|
|
633
|
+
const onChange = useCallback4(
|
|
634
|
+
(event) => {
|
|
635
|
+
const inputValue = getValue(event, props.field);
|
|
636
|
+
if (shouldSkipChange({
|
|
637
|
+
shouldSkipOnChange,
|
|
638
|
+
hasClickable,
|
|
639
|
+
inputValue,
|
|
640
|
+
valueRef
|
|
641
|
+
})) {
|
|
642
|
+
return;
|
|
643
|
+
}
|
|
644
|
+
onValueChangeRef.current?.(inputValue);
|
|
645
|
+
if (props.config.validation.change) {
|
|
646
|
+
validated(inputValue);
|
|
647
|
+
}
|
|
648
|
+
if (props.field.event?.change) {
|
|
649
|
+
dispatchChange({
|
|
650
|
+
applyChangeEventsRef,
|
|
651
|
+
data,
|
|
652
|
+
entity,
|
|
653
|
+
inputValue,
|
|
654
|
+
setTimeoutRef
|
|
655
|
+
});
|
|
656
|
+
}
|
|
657
|
+
},
|
|
658
|
+
[
|
|
659
|
+
applyChangeEventsRef,
|
|
660
|
+
data,
|
|
661
|
+
dispatchChange,
|
|
662
|
+
entity,
|
|
663
|
+
getValue,
|
|
664
|
+
hasClickable,
|
|
665
|
+
onValueChangeRef,
|
|
666
|
+
props.config.validation.change,
|
|
667
|
+
props.field,
|
|
668
|
+
setTimeoutRef,
|
|
669
|
+
shouldSkipChange,
|
|
670
|
+
shouldSkipOnChange,
|
|
671
|
+
validated,
|
|
672
|
+
valueRef
|
|
673
|
+
]
|
|
674
|
+
);
|
|
675
|
+
return renderIfExists(props.config.inputs[props.field.type], (Component) => /* @__PURE__ */ jsx7(
|
|
676
|
+
InputGroup,
|
|
677
|
+
{
|
|
678
|
+
config: props.config,
|
|
679
|
+
context: props.context,
|
|
680
|
+
field: props.field,
|
|
681
|
+
horizontal: props.horizontal,
|
|
682
|
+
translations: props.translations,
|
|
683
|
+
children: /* @__PURE__ */ jsx7(
|
|
684
|
+
Component,
|
|
685
|
+
{
|
|
686
|
+
...commonPropsWithOptions,
|
|
687
|
+
...props.ariaAttributes,
|
|
688
|
+
...props.dataAttributes,
|
|
689
|
+
...extraProps,
|
|
690
|
+
...inputProps,
|
|
691
|
+
onBlur,
|
|
692
|
+
onChange
|
|
693
|
+
}
|
|
694
|
+
)
|
|
695
|
+
}
|
|
696
|
+
));
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
// src/client/component/input-create.tsx
|
|
700
|
+
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
701
|
+
function createInput(strategies) {
|
|
702
|
+
return function CreateInput(props) {
|
|
703
|
+
return /* @__PURE__ */ jsx8(InputBase, { ...props, strategies });
|
|
704
|
+
};
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
// src/client/lib/source-store.ts
|
|
708
|
+
import { atom as atom2 } from "jotai";
|
|
709
|
+
var merge = (values) => {
|
|
710
|
+
const merged = mergeSource(values);
|
|
711
|
+
if (merged) {
|
|
712
|
+
return merged;
|
|
713
|
+
}
|
|
714
|
+
return void 0;
|
|
715
|
+
};
|
|
716
|
+
var validate = (target) => target.trim() !== "";
|
|
717
|
+
var sourceAtom = atom2({});
|
|
718
|
+
var reportSourceAtom = createNestedRecordAtomFamily(
|
|
719
|
+
sourceAtom,
|
|
720
|
+
{
|
|
721
|
+
merge,
|
|
722
|
+
validateTarget: validate
|
|
723
|
+
}
|
|
724
|
+
);
|
|
725
|
+
var clearInputSourceAtom = createNestedClearAtom(sourceAtom);
|
|
726
|
+
|
|
727
|
+
// src/client/hook/use-timezone-options.ts
|
|
728
|
+
import { useEffect as useEffect5, useState } from "react";
|
|
729
|
+
import { useSetAtom as useSetAtom2 } from "jotai";
|
|
730
|
+
var cache = null;
|
|
731
|
+
function useTimezoneOptions(field) {
|
|
732
|
+
const setSource = useSetAtom2(reportSourceAtom(field.name));
|
|
733
|
+
const [data, setData] = useState(cache);
|
|
734
|
+
useEffect5(() => {
|
|
735
|
+
if (cache) {
|
|
736
|
+
return;
|
|
737
|
+
}
|
|
738
|
+
let cancelled = false;
|
|
739
|
+
loadTimezones().then((groups) => {
|
|
740
|
+
cache = groups;
|
|
741
|
+
if (!cancelled) {
|
|
742
|
+
setData(groups);
|
|
743
|
+
}
|
|
744
|
+
});
|
|
745
|
+
return () => {
|
|
746
|
+
cancelled = true;
|
|
747
|
+
};
|
|
748
|
+
}, []);
|
|
749
|
+
return { data, setSource };
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
// src/client/component/input-timezone.tsx
|
|
753
|
+
var InputTimezone = createInput({
|
|
754
|
+
useSource: useTimezoneOptions,
|
|
755
|
+
getValue: (event) => event.target.value,
|
|
756
|
+
shouldSkipChange: ({ shouldSkipOnChange, hasClickable }) => !hasClickable && shouldSkipOnChange(),
|
|
757
|
+
dispatchChange: ({ applyChangeEventsRef, data, entity, inputValue }) => {
|
|
758
|
+
applyChangeEventsRef.current?.(getEntity(inputValue, data, entity));
|
|
759
|
+
},
|
|
760
|
+
buildInitialSelected: (defaultValue, data, entity) => getEntity(String(defaultValue), data, entity),
|
|
761
|
+
isInitialReady: (field, defaultValue, data) => (!isOptions(field) || !!data && data.length > 0) && isValidValue(defaultValue)
|
|
762
|
+
});
|
|
763
|
+
var input_timezone_default = InputTimezone;
|
|
764
|
+
export {
|
|
765
|
+
input_timezone_default as default
|
|
766
|
+
};
|