@valfuse-node/react 0.2.0
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/LICENSE +22 -0
- package/README.md +620 -0
- package/dist/index.d.mts +446 -0
- package/dist/index.d.ts +446 -0
- package/dist/index.js +986 -0
- package/dist/index.mjs +957 -0
- package/package.json +48 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,986 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
LocalizationProvider: () => LocalizationProvider,
|
|
24
|
+
ValfuseController: () => ValfuseController,
|
|
25
|
+
composeStorage: () => composeStorage,
|
|
26
|
+
cookieStrategy: () => cookieStrategy,
|
|
27
|
+
createLazyLocaleLoader: () => createLazyLocaleLoader,
|
|
28
|
+
createLocalizationStore: () => createLocalizationStore,
|
|
29
|
+
createSsrLocalizationState: () => createSsrLocalizationState,
|
|
30
|
+
localStorageStrategy: () => localStorageStrategy,
|
|
31
|
+
memoryStrategy: () => memoryStrategy,
|
|
32
|
+
sessionStorageStrategy: () => sessionStorageStrategy,
|
|
33
|
+
useLocalization: () => useLocalization,
|
|
34
|
+
useLocalizationTree: () => useLocalizationTree,
|
|
35
|
+
useValfuseForm: () => useValfuseForm
|
|
36
|
+
});
|
|
37
|
+
module.exports = __toCommonJS(index_exports);
|
|
38
|
+
|
|
39
|
+
// src/hooks/use-valfuse-form.ts
|
|
40
|
+
var import_react7 = require("react");
|
|
41
|
+
|
|
42
|
+
// src/hooks/sub-hooks/use-form-core.ts
|
|
43
|
+
var import_react = require("react");
|
|
44
|
+
function useFormCore(props) {
|
|
45
|
+
const { schema, defaultValues, mode = "onSubmit" } = props;
|
|
46
|
+
const [values, setValues] = (0, import_react.useState)(
|
|
47
|
+
() => ({ ...defaultValues })
|
|
48
|
+
);
|
|
49
|
+
const [errors, setErrorsState] = (0, import_react.useState)({});
|
|
50
|
+
const [isSubmitting, setIsSubmitting] = (0, import_react.useState)(false);
|
|
51
|
+
const [isSubmitted, setIsSubmitted] = (0, import_react.useState)(false);
|
|
52
|
+
const [isSubmitSuccessful, setIsSubmitSuccessful] = (0, import_react.useState)(false);
|
|
53
|
+
const [submitCount, setSubmitCount] = (0, import_react.useState)(0);
|
|
54
|
+
const [touchedFields, setTouchedFields] = (0, import_react.useState)(
|
|
55
|
+
() => /* @__PURE__ */ new Set()
|
|
56
|
+
);
|
|
57
|
+
const valuesRef = (0, import_react.useRef)(values);
|
|
58
|
+
valuesRef.current = values;
|
|
59
|
+
const errorsRef = (0, import_react.useRef)(errors);
|
|
60
|
+
errorsRef.current = errors;
|
|
61
|
+
const touchedFieldsRef = (0, import_react.useRef)(touchedFields);
|
|
62
|
+
touchedFieldsRef.current = touchedFields;
|
|
63
|
+
const modeRef = (0, import_react.useRef)(mode);
|
|
64
|
+
modeRef.current = mode;
|
|
65
|
+
const schemaRef = (0, import_react.useRef)(schema);
|
|
66
|
+
schemaRef.current = schema;
|
|
67
|
+
const watchSubscribersRef = (0, import_react.useRef)(/* @__PURE__ */ new Set());
|
|
68
|
+
const lastChangedFieldRef = (0, import_react.useRef)(void 0);
|
|
69
|
+
return {
|
|
70
|
+
schema,
|
|
71
|
+
defaultValues,
|
|
72
|
+
mode,
|
|
73
|
+
values,
|
|
74
|
+
errors,
|
|
75
|
+
isSubmitting,
|
|
76
|
+
isSubmitted,
|
|
77
|
+
isSubmitSuccessful,
|
|
78
|
+
submitCount,
|
|
79
|
+
touchedFields,
|
|
80
|
+
setValues,
|
|
81
|
+
setErrorsState,
|
|
82
|
+
setTouchedFields,
|
|
83
|
+
setIsSubmitting,
|
|
84
|
+
setIsSubmitted,
|
|
85
|
+
setIsSubmitSuccessful,
|
|
86
|
+
setSubmitCount,
|
|
87
|
+
refs: {
|
|
88
|
+
valuesRef,
|
|
89
|
+
errorsRef,
|
|
90
|
+
touchedFieldsRef,
|
|
91
|
+
modeRef,
|
|
92
|
+
schemaRef,
|
|
93
|
+
lastChangedFieldRef,
|
|
94
|
+
watchSubscribersRef
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// src/hooks/sub-hooks/use-field-validation.ts
|
|
100
|
+
var import_react2 = require("react");
|
|
101
|
+
var import_form = require("@valfuse-node/form");
|
|
102
|
+
|
|
103
|
+
// src/helpers/validation-mode.ts
|
|
104
|
+
function shouldValidateOnChange(mode, isTouched) {
|
|
105
|
+
return mode === "onChange" || mode === "all" || mode === "onTouched" && isTouched;
|
|
106
|
+
}
|
|
107
|
+
function shouldValidateOnBlur(mode) {
|
|
108
|
+
return mode === "onBlur" || mode === "all" || mode === "onTouched";
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// src/helpers/field-error.ts
|
|
112
|
+
function buildFieldError(fieldErrors, field) {
|
|
113
|
+
const err = fieldErrors[field];
|
|
114
|
+
if (!err) return null;
|
|
115
|
+
return {
|
|
116
|
+
message: err.message,
|
|
117
|
+
type: err.type ?? "validation",
|
|
118
|
+
...err.code !== void 0 && { code: err.code }
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
function mapToFieldErrors(schemaErrors) {
|
|
122
|
+
return Object.fromEntries(
|
|
123
|
+
Object.entries(schemaErrors).map(([key, err]) => {
|
|
124
|
+
const fieldError = {
|
|
125
|
+
message: err.message,
|
|
126
|
+
type: err.type ?? "validation",
|
|
127
|
+
...err.code !== void 0 && { code: err.code },
|
|
128
|
+
...err.metadata !== void 0 && { metadata: err.metadata }
|
|
129
|
+
};
|
|
130
|
+
return [key, fieldError];
|
|
131
|
+
})
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// src/hooks/sub-hooks/use-field-validation.ts
|
|
136
|
+
function useFieldValidation({
|
|
137
|
+
schema,
|
|
138
|
+
setErrorsState
|
|
139
|
+
}) {
|
|
140
|
+
const validateField = (0, import_react2.useCallback)(
|
|
141
|
+
(name, currentValues) => {
|
|
142
|
+
if (!schema[name]) return;
|
|
143
|
+
const raw = (0, import_form.validateSchema)({ [name]: schema[name] }, currentValues);
|
|
144
|
+
const error = buildFieldError(raw, name);
|
|
145
|
+
setErrorsState((prev) => {
|
|
146
|
+
if (!error && !(name in prev)) return prev;
|
|
147
|
+
const prevError = prev[name];
|
|
148
|
+
if (error && prevError && error.message === prevError.message && error.type === prevError.type && error.code === prevError.code) return prev;
|
|
149
|
+
const next = { ...prev };
|
|
150
|
+
if (error) {
|
|
151
|
+
next[name] = error;
|
|
152
|
+
} else {
|
|
153
|
+
delete next[name];
|
|
154
|
+
}
|
|
155
|
+
return next;
|
|
156
|
+
});
|
|
157
|
+
},
|
|
158
|
+
[schema, setErrorsState]
|
|
159
|
+
);
|
|
160
|
+
const clearStaleFieldError = (0, import_react2.useCallback)(
|
|
161
|
+
(name) => {
|
|
162
|
+
setErrorsState((prev) => {
|
|
163
|
+
if (!(name in prev)) return prev;
|
|
164
|
+
const next = { ...prev };
|
|
165
|
+
delete next[name];
|
|
166
|
+
return next;
|
|
167
|
+
});
|
|
168
|
+
},
|
|
169
|
+
[setErrorsState]
|
|
170
|
+
);
|
|
171
|
+
return { validateField, clearStaleFieldError };
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// src/hooks/sub-hooks/use-form-registration.ts
|
|
175
|
+
var import_react3 = require("react");
|
|
176
|
+
function useFormRegistration({
|
|
177
|
+
core,
|
|
178
|
+
validateField,
|
|
179
|
+
clearStaleFieldError
|
|
180
|
+
}) {
|
|
181
|
+
const { values, refs, touchedFields, setValues, setTouchedFields } = core;
|
|
182
|
+
const valuesRef = refs.valuesRef;
|
|
183
|
+
const modeRef = refs.modeRef;
|
|
184
|
+
const schemaRef = refs.schemaRef;
|
|
185
|
+
const touchedFieldsRef = refs.touchedFieldsRef;
|
|
186
|
+
const lastChangedFieldRef = refs.lastChangedFieldRef;
|
|
187
|
+
const register = (0, import_react3.useCallback)(
|
|
188
|
+
(name) => ({
|
|
189
|
+
name,
|
|
190
|
+
value: valuesRef.current[name],
|
|
191
|
+
onChange: (e) => {
|
|
192
|
+
const rawValue = e.target.value;
|
|
193
|
+
const fieldTransform = schemaRef.current[name]?.transform;
|
|
194
|
+
const newValue = fieldTransform ? fieldTransform(rawValue) : rawValue;
|
|
195
|
+
const updated = { ...valuesRef.current, [name]: newValue };
|
|
196
|
+
lastChangedFieldRef.current = name;
|
|
197
|
+
setValues(updated);
|
|
198
|
+
if (shouldValidateOnChange(modeRef.current, touchedFieldsRef.current.has(name))) {
|
|
199
|
+
validateField(name, updated);
|
|
200
|
+
} else {
|
|
201
|
+
clearStaleFieldError(name);
|
|
202
|
+
}
|
|
203
|
+
},
|
|
204
|
+
onBlur: () => {
|
|
205
|
+
setTouchedFields((prev) => {
|
|
206
|
+
if (prev.has(name)) return prev;
|
|
207
|
+
const next = new Set(prev);
|
|
208
|
+
next.add(name);
|
|
209
|
+
return next;
|
|
210
|
+
});
|
|
211
|
+
if (shouldValidateOnBlur(modeRef.current)) {
|
|
212
|
+
const current = valuesRef.current;
|
|
213
|
+
const fieldTransform = schemaRef.current[name]?.transform;
|
|
214
|
+
const forValidation = fieldTransform ? { ...current, [name]: fieldTransform(current[name]) } : current;
|
|
215
|
+
validateField(name, forValidation);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}),
|
|
219
|
+
// mode/touchedFields/schema read via refs — only stable deps here.
|
|
220
|
+
[validateField, clearStaleFieldError]
|
|
221
|
+
);
|
|
222
|
+
const _updateField = (0, import_react3.useCallback)(
|
|
223
|
+
(name, value) => {
|
|
224
|
+
const fieldTransform = schemaRef.current[name]?.transform;
|
|
225
|
+
const transformedValue = fieldTransform ? fieldTransform(value) : value;
|
|
226
|
+
const updated = { ...valuesRef.current, [name]: transformedValue };
|
|
227
|
+
lastChangedFieldRef.current = name;
|
|
228
|
+
setValues(updated);
|
|
229
|
+
if (shouldValidateOnChange(modeRef.current, touchedFieldsRef.current.has(name))) {
|
|
230
|
+
validateField(name, updated);
|
|
231
|
+
} else {
|
|
232
|
+
clearStaleFieldError(name);
|
|
233
|
+
}
|
|
234
|
+
},
|
|
235
|
+
// schema/mode/touchedFields/values read via refs.
|
|
236
|
+
[validateField, clearStaleFieldError]
|
|
237
|
+
);
|
|
238
|
+
const _touchField = (0, import_react3.useCallback)(
|
|
239
|
+
(name) => {
|
|
240
|
+
setTouchedFields((prev) => {
|
|
241
|
+
if (prev.has(name)) return prev;
|
|
242
|
+
const next = new Set(prev);
|
|
243
|
+
next.add(name);
|
|
244
|
+
return next;
|
|
245
|
+
});
|
|
246
|
+
if (shouldValidateOnBlur(modeRef.current)) {
|
|
247
|
+
const current = valuesRef.current;
|
|
248
|
+
const fieldTransform = schemaRef.current[name]?.transform;
|
|
249
|
+
const forValidation = fieldTransform ? { ...current, [name]: fieldTransform(current[name]) } : current;
|
|
250
|
+
validateField(name, forValidation);
|
|
251
|
+
}
|
|
252
|
+
},
|
|
253
|
+
// schema/mode/values read via refs — only validateField is a dep.
|
|
254
|
+
[validateField]
|
|
255
|
+
);
|
|
256
|
+
const control = (0, import_react3.useMemo)(
|
|
257
|
+
() => ({
|
|
258
|
+
_values: values,
|
|
259
|
+
_errors: core.errors,
|
|
260
|
+
_updateField,
|
|
261
|
+
_touchField,
|
|
262
|
+
_touchedFields: touchedFields
|
|
263
|
+
}),
|
|
264
|
+
[values, core.errors, touchedFields, _updateField, _touchField]
|
|
265
|
+
);
|
|
266
|
+
return { register, control, _updateField, _touchField };
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// src/hooks/sub-hooks/use-form-watch.ts
|
|
270
|
+
var import_react4 = require("react");
|
|
271
|
+
function useFormWatch(core) {
|
|
272
|
+
const { watchSubscribersRef, lastChangedFieldRef } = core.refs;
|
|
273
|
+
(0, import_react4.useEffect)(() => {
|
|
274
|
+
if (watchSubscribersRef.current.size > 0) {
|
|
275
|
+
const info = {
|
|
276
|
+
name: lastChangedFieldRef.current,
|
|
277
|
+
type: lastChangedFieldRef.current ? "change" : void 0
|
|
278
|
+
};
|
|
279
|
+
watchSubscribersRef.current.forEach((cb) => cb(core.values, info));
|
|
280
|
+
}
|
|
281
|
+
lastChangedFieldRef.current = void 0;
|
|
282
|
+
}, [core.values, watchSubscribersRef, lastChangedFieldRef]);
|
|
283
|
+
const watch = (0, import_react4.useCallback)(
|
|
284
|
+
(nameOrNamesOrCallback) => {
|
|
285
|
+
const { valuesRef } = core.refs;
|
|
286
|
+
if (typeof nameOrNamesOrCallback === "function") {
|
|
287
|
+
const cb = nameOrNamesOrCallback;
|
|
288
|
+
watchSubscribersRef.current.add(cb);
|
|
289
|
+
return () => watchSubscribersRef.current.delete(cb);
|
|
290
|
+
}
|
|
291
|
+
if (Array.isArray(nameOrNamesOrCallback)) {
|
|
292
|
+
return nameOrNamesOrCallback.map(
|
|
293
|
+
(n) => valuesRef.current[n]
|
|
294
|
+
);
|
|
295
|
+
}
|
|
296
|
+
if (typeof nameOrNamesOrCallback === "string") {
|
|
297
|
+
return valuesRef.current[nameOrNamesOrCallback];
|
|
298
|
+
}
|
|
299
|
+
return valuesRef.current;
|
|
300
|
+
},
|
|
301
|
+
[core.refs, watchSubscribersRef]
|
|
302
|
+
);
|
|
303
|
+
return { watch };
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// src/hooks/sub-hooks/use-form-actions.ts
|
|
307
|
+
var import_react5 = require("react");
|
|
308
|
+
var import_form2 = require("@valfuse-node/form");
|
|
309
|
+
function useFormActions(core, clearStaleFieldError) {
|
|
310
|
+
const handleSubmit = (0, import_react5.useCallback)(
|
|
311
|
+
(onValid) => async (e) => {
|
|
312
|
+
e?.preventDefault?.();
|
|
313
|
+
const { schema, refs } = core;
|
|
314
|
+
const currentValues = refs.valuesRef.current;
|
|
315
|
+
const transformedValues = (0, import_form2.transformValues)(
|
|
316
|
+
schema,
|
|
317
|
+
currentValues
|
|
318
|
+
);
|
|
319
|
+
const schemaErrors = (0, import_form2.validateSchema)(
|
|
320
|
+
schema,
|
|
321
|
+
transformedValues
|
|
322
|
+
);
|
|
323
|
+
core.setSubmitCount((c) => c + 1);
|
|
324
|
+
core.setIsSubmitted(true);
|
|
325
|
+
if (Object.keys(schemaErrors).length > 0) {
|
|
326
|
+
core.setErrorsState(mapToFieldErrors(schemaErrors));
|
|
327
|
+
core.setIsSubmitSuccessful(false);
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
if (Object.keys(refs.errorsRef.current).length > 0) core.setErrorsState({});
|
|
331
|
+
core.setIsSubmitting(true);
|
|
332
|
+
try {
|
|
333
|
+
await onValid(transformedValues);
|
|
334
|
+
core.setIsSubmitSuccessful(true);
|
|
335
|
+
} catch (err) {
|
|
336
|
+
core.setIsSubmitSuccessful(false);
|
|
337
|
+
throw err;
|
|
338
|
+
} finally {
|
|
339
|
+
core.setIsSubmitting(false);
|
|
340
|
+
}
|
|
341
|
+
},
|
|
342
|
+
// All read via core.* — list each stable field explicitly.
|
|
343
|
+
[
|
|
344
|
+
core.schema,
|
|
345
|
+
core.refs.valuesRef,
|
|
346
|
+
core.refs.errorsRef,
|
|
347
|
+
core.setSubmitCount,
|
|
348
|
+
core.setIsSubmitted,
|
|
349
|
+
core.setIsSubmitting,
|
|
350
|
+
core.setIsSubmitSuccessful,
|
|
351
|
+
core.setErrorsState
|
|
352
|
+
]
|
|
353
|
+
);
|
|
354
|
+
const setErrors = (0, import_react5.useCallback)(
|
|
355
|
+
(fieldErrors) => {
|
|
356
|
+
core.setErrorsState((prev) => {
|
|
357
|
+
const next = { ...prev };
|
|
358
|
+
let changed = false;
|
|
359
|
+
for (const [fieldName, rawError] of Object.entries(fieldErrors)) {
|
|
360
|
+
if (rawError === void 0) continue;
|
|
361
|
+
const normalized = (0, import_form2.normalizeError)(rawError);
|
|
362
|
+
const prevFieldError = prev[fieldName];
|
|
363
|
+
if (prevFieldError && prevFieldError.message === normalized.message && prevFieldError.type === (normalized.type ?? "manual") && prevFieldError.code === normalized.code) continue;
|
|
364
|
+
next[fieldName] = {
|
|
365
|
+
message: normalized.message,
|
|
366
|
+
type: normalized.type ?? "manual",
|
|
367
|
+
...normalized.code !== void 0 && { code: normalized.code },
|
|
368
|
+
...normalized.metadata !== void 0 && {
|
|
369
|
+
metadata: normalized.metadata
|
|
370
|
+
}
|
|
371
|
+
};
|
|
372
|
+
changed = true;
|
|
373
|
+
}
|
|
374
|
+
return changed ? next : prev;
|
|
375
|
+
});
|
|
376
|
+
},
|
|
377
|
+
[core.setErrorsState]
|
|
378
|
+
);
|
|
379
|
+
const clearErrors = (0, import_react5.useCallback)(
|
|
380
|
+
(name) => {
|
|
381
|
+
if (name === void 0) {
|
|
382
|
+
if (Object.keys(core.refs.errorsRef.current).length === 0) return;
|
|
383
|
+
core.setErrorsState({});
|
|
384
|
+
return;
|
|
385
|
+
}
|
|
386
|
+
const fields = Array.isArray(name) ? name : [name];
|
|
387
|
+
core.setErrorsState((prev) => {
|
|
388
|
+
const toDelete = fields.filter((k) => k in prev);
|
|
389
|
+
if (toDelete.length === 0) return prev;
|
|
390
|
+
const next = { ...prev };
|
|
391
|
+
for (const n of toDelete) delete next[n];
|
|
392
|
+
return next;
|
|
393
|
+
});
|
|
394
|
+
},
|
|
395
|
+
[core.refs.errorsRef, core.setErrorsState]
|
|
396
|
+
);
|
|
397
|
+
const trigger = (0, import_react5.useCallback)(
|
|
398
|
+
(name) => {
|
|
399
|
+
const { schema, refs } = core;
|
|
400
|
+
const current = refs.valuesRef.current;
|
|
401
|
+
const transformed = (0, import_form2.transformValues)(schema, current);
|
|
402
|
+
const fieldsToValidate = name === void 0 ? Object.keys(schema) : Array.isArray(name) ? name : [name];
|
|
403
|
+
let allValid = true;
|
|
404
|
+
let changed = false;
|
|
405
|
+
const prevErrors = refs.errorsRef.current;
|
|
406
|
+
const nextErrors = { ...prevErrors };
|
|
407
|
+
for (const field of fieldsToValidate) {
|
|
408
|
+
if (!schema[field]) continue;
|
|
409
|
+
const raw = (0, import_form2.validateSchema)({ [field]: schema[field] }, transformed);
|
|
410
|
+
const error = buildFieldError(raw, field);
|
|
411
|
+
if (error) {
|
|
412
|
+
allValid = false;
|
|
413
|
+
const prev = prevErrors[field];
|
|
414
|
+
if (!prev || prev.message !== error.message || prev.type !== error.type || prev.code !== error.code) {
|
|
415
|
+
changed = true;
|
|
416
|
+
}
|
|
417
|
+
nextErrors[field] = error;
|
|
418
|
+
} else {
|
|
419
|
+
if (field in nextErrors) {
|
|
420
|
+
changed = true;
|
|
421
|
+
delete nextErrors[field];
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
if (changed) core.setErrorsState(nextErrors);
|
|
426
|
+
return allValid;
|
|
427
|
+
},
|
|
428
|
+
[core.schema, core.refs.valuesRef, core.refs.errorsRef, core.setErrorsState]
|
|
429
|
+
);
|
|
430
|
+
const setValue = (0, import_react5.useCallback)(
|
|
431
|
+
(name, value, options) => {
|
|
432
|
+
const { schema, refs } = core;
|
|
433
|
+
const fieldTransform = refs.schemaRef.current[name]?.transform;
|
|
434
|
+
const transformedValue = fieldTransform ? fieldTransform(value) : value;
|
|
435
|
+
const updated = { ...refs.valuesRef.current, [name]: transformedValue };
|
|
436
|
+
refs.valuesRef.current = updated;
|
|
437
|
+
refs.lastChangedFieldRef.current = name;
|
|
438
|
+
core.setValues(updated);
|
|
439
|
+
if (options?.shouldValidate) {
|
|
440
|
+
const field = name;
|
|
441
|
+
if (!schema[field]) return;
|
|
442
|
+
const raw = (0, import_form2.validateSchema)(
|
|
443
|
+
{ [field]: schema[field] },
|
|
444
|
+
updated
|
|
445
|
+
);
|
|
446
|
+
const error = buildFieldError(raw, field);
|
|
447
|
+
core.setErrorsState((prev) => {
|
|
448
|
+
if (!error && !(field in prev)) return prev;
|
|
449
|
+
const prevError = prev[name];
|
|
450
|
+
if (error && prevError && error.message === prevError.message && error.type === prevError.type && error.code === prevError.code) return prev;
|
|
451
|
+
const next = { ...prev };
|
|
452
|
+
if (error) {
|
|
453
|
+
next[name] = error;
|
|
454
|
+
} else {
|
|
455
|
+
delete next[name];
|
|
456
|
+
}
|
|
457
|
+
return next;
|
|
458
|
+
});
|
|
459
|
+
} else {
|
|
460
|
+
clearStaleFieldError(name);
|
|
461
|
+
}
|
|
462
|
+
},
|
|
463
|
+
[
|
|
464
|
+
core.schema,
|
|
465
|
+
core.refs.schemaRef,
|
|
466
|
+
core.refs.valuesRef,
|
|
467
|
+
core.refs.lastChangedFieldRef,
|
|
468
|
+
core.setValues,
|
|
469
|
+
core.setErrorsState,
|
|
470
|
+
clearStaleFieldError
|
|
471
|
+
]
|
|
472
|
+
);
|
|
473
|
+
const reset = (0, import_react5.useCallback)(
|
|
474
|
+
(newValues) => {
|
|
475
|
+
core.setValues({ ...core.defaultValues, ...newValues });
|
|
476
|
+
core.setErrorsState({});
|
|
477
|
+
core.setTouchedFields(/* @__PURE__ */ new Set());
|
|
478
|
+
core.setIsSubmitted(false);
|
|
479
|
+
core.setIsSubmitSuccessful(false);
|
|
480
|
+
core.setSubmitCount(0);
|
|
481
|
+
},
|
|
482
|
+
[
|
|
483
|
+
core.defaultValues,
|
|
484
|
+
core.setValues,
|
|
485
|
+
core.setErrorsState,
|
|
486
|
+
core.setTouchedFields,
|
|
487
|
+
core.setIsSubmitted,
|
|
488
|
+
core.setIsSubmitSuccessful,
|
|
489
|
+
core.setSubmitCount
|
|
490
|
+
]
|
|
491
|
+
);
|
|
492
|
+
return { handleSubmit, setErrors, clearErrors, setValue, trigger, reset };
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
// src/hooks/sub-hooks/use-form-derived-state.ts
|
|
496
|
+
var import_react6 = require("react");
|
|
497
|
+
var import_form3 = require("@valfuse-node/form");
|
|
498
|
+
function useFormDerivedState(core) {
|
|
499
|
+
const { schema, defaultValues, values, errors, touchedFields } = core;
|
|
500
|
+
const isDirty = (0, import_react6.useMemo)(
|
|
501
|
+
() => Object.keys(defaultValues).some(
|
|
502
|
+
(key) => values[key] !== defaultValues[key]
|
|
503
|
+
),
|
|
504
|
+
[values, defaultValues]
|
|
505
|
+
);
|
|
506
|
+
const dirtyFields = (0, import_react6.useMemo)(
|
|
507
|
+
() => Object.keys(defaultValues).reduce(
|
|
508
|
+
(acc, key) => {
|
|
509
|
+
const k = key;
|
|
510
|
+
if (values[k] !== defaultValues[k]) acc[k] = true;
|
|
511
|
+
return acc;
|
|
512
|
+
},
|
|
513
|
+
{}
|
|
514
|
+
),
|
|
515
|
+
[values, defaultValues]
|
|
516
|
+
);
|
|
517
|
+
const touchedFieldsRecord = (0, import_react6.useMemo)(
|
|
518
|
+
() => Array.from(touchedFields).reduce(
|
|
519
|
+
(acc, key) => {
|
|
520
|
+
acc[key] = true;
|
|
521
|
+
return acc;
|
|
522
|
+
},
|
|
523
|
+
{}
|
|
524
|
+
),
|
|
525
|
+
[touchedFields]
|
|
526
|
+
);
|
|
527
|
+
const isValid = (0, import_react6.useMemo)(() => {
|
|
528
|
+
if (Object.keys(errors).length > 0) return false;
|
|
529
|
+
const transformed = (0, import_form3.transformValues)(
|
|
530
|
+
schema,
|
|
531
|
+
values
|
|
532
|
+
);
|
|
533
|
+
return Object.keys((0, import_form3.validateSchema)(schema, transformed)).length === 0;
|
|
534
|
+
}, [schema, values, errors]);
|
|
535
|
+
return { isDirty, dirtyFields, touchedFieldsRecord, isValid };
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
// src/hooks/use-valfuse-form.ts
|
|
539
|
+
function useValfuseForm(props) {
|
|
540
|
+
const { defaultValues } = props;
|
|
541
|
+
const core = useFormCore(props);
|
|
542
|
+
const { validateField, clearStaleFieldError } = useFieldValidation({
|
|
543
|
+
schema: core.schema,
|
|
544
|
+
setErrorsState: core.setErrorsState
|
|
545
|
+
});
|
|
546
|
+
const { register, control } = useFormRegistration({
|
|
547
|
+
core,
|
|
548
|
+
validateField,
|
|
549
|
+
clearStaleFieldError
|
|
550
|
+
});
|
|
551
|
+
const { watch } = useFormWatch(core);
|
|
552
|
+
const { handleSubmit, setErrors, clearErrors, setValue, trigger, reset } = useFormActions(core, clearStaleFieldError);
|
|
553
|
+
const { isDirty, dirtyFields, touchedFieldsRecord, isValid } = useFormDerivedState(core);
|
|
554
|
+
const formState = (0, import_react7.useMemo)(
|
|
555
|
+
() => ({
|
|
556
|
+
errors: core.errors,
|
|
557
|
+
isSubmitting: core.isSubmitting,
|
|
558
|
+
isSubmitted: core.isSubmitted,
|
|
559
|
+
isSubmitSuccessful: core.isSubmitSuccessful,
|
|
560
|
+
submitCount: core.submitCount,
|
|
561
|
+
isDirty,
|
|
562
|
+
isValid,
|
|
563
|
+
dirtyFields,
|
|
564
|
+
touchedFields: touchedFieldsRecord,
|
|
565
|
+
defaultValues
|
|
566
|
+
}),
|
|
567
|
+
[
|
|
568
|
+
core.errors,
|
|
569
|
+
core.isSubmitting,
|
|
570
|
+
core.isSubmitted,
|
|
571
|
+
core.isSubmitSuccessful,
|
|
572
|
+
core.submitCount,
|
|
573
|
+
isDirty,
|
|
574
|
+
isValid,
|
|
575
|
+
dirtyFields,
|
|
576
|
+
touchedFieldsRecord,
|
|
577
|
+
defaultValues
|
|
578
|
+
]
|
|
579
|
+
);
|
|
580
|
+
return {
|
|
581
|
+
register,
|
|
582
|
+
control,
|
|
583
|
+
handleSubmit,
|
|
584
|
+
formState,
|
|
585
|
+
setErrors,
|
|
586
|
+
clearErrors,
|
|
587
|
+
setValue,
|
|
588
|
+
trigger,
|
|
589
|
+
watch,
|
|
590
|
+
reset
|
|
591
|
+
};
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
// src/components/valfuse-controller.tsx
|
|
595
|
+
var import_react8 = require("react");
|
|
596
|
+
function ValfuseController({
|
|
597
|
+
control,
|
|
598
|
+
name,
|
|
599
|
+
render
|
|
600
|
+
}) {
|
|
601
|
+
const onChange = (0, import_react8.useCallback)(
|
|
602
|
+
(value) => control._updateField(name, value),
|
|
603
|
+
[control._updateField, name]
|
|
604
|
+
);
|
|
605
|
+
const onBlur = (0, import_react8.useCallback)(
|
|
606
|
+
() => control._touchField(name),
|
|
607
|
+
[control._touchField, name]
|
|
608
|
+
);
|
|
609
|
+
const fieldValue = control._values[name];
|
|
610
|
+
const fieldError = control._errors[name];
|
|
611
|
+
const isTouched = control._touchedFields.has(name);
|
|
612
|
+
const field = (0, import_react8.useMemo)(
|
|
613
|
+
() => ({
|
|
614
|
+
name,
|
|
615
|
+
value: fieldValue,
|
|
616
|
+
onChange,
|
|
617
|
+
onBlur
|
|
618
|
+
}),
|
|
619
|
+
[name, fieldValue, onChange, onBlur]
|
|
620
|
+
);
|
|
621
|
+
const fieldState = (0, import_react8.useMemo)(
|
|
622
|
+
() => ({
|
|
623
|
+
error: fieldError,
|
|
624
|
+
isTouched
|
|
625
|
+
}),
|
|
626
|
+
[fieldError, isTouched]
|
|
627
|
+
);
|
|
628
|
+
return render({ field, fieldState });
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
// src/localization/provider/localization-provider.tsx
|
|
632
|
+
var import_react9 = require("react");
|
|
633
|
+
|
|
634
|
+
// src/localization/bridge/create-localization-store.ts
|
|
635
|
+
var import_runtime = require("@valfuse-node/localization/runtime");
|
|
636
|
+
function createLocalizationStore(manifest, initialLocale) {
|
|
637
|
+
let locale = initialLocale ?? manifest.base_locale;
|
|
638
|
+
return {
|
|
639
|
+
getLocale: () => locale,
|
|
640
|
+
setLocale(nextLocale) {
|
|
641
|
+
locale = nextLocale;
|
|
642
|
+
},
|
|
643
|
+
t(key, params) {
|
|
644
|
+
const value = (0, import_runtime.lookupMessage)(
|
|
645
|
+
{
|
|
646
|
+
locale,
|
|
647
|
+
fallbackLocale: manifest.fallback_locale,
|
|
648
|
+
messages: manifest.messages
|
|
649
|
+
},
|
|
650
|
+
key
|
|
651
|
+
);
|
|
652
|
+
return (0, import_runtime.interpolate)(value, params);
|
|
653
|
+
}
|
|
654
|
+
};
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
// src/localization/provider/localization-provider.tsx
|
|
658
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
659
|
+
var LocalizationContext = (0, import_react9.createContext)(null);
|
|
660
|
+
function determineInitialLocale(manifest, initialLocale, storage) {
|
|
661
|
+
const stored = storage?.get();
|
|
662
|
+
if (stored && manifest.locales.includes(stored)) return stored;
|
|
663
|
+
if (initialLocale && manifest.locales.includes(initialLocale)) return initialLocale;
|
|
664
|
+
return manifest.base_locale;
|
|
665
|
+
}
|
|
666
|
+
function LocalizationProvider({
|
|
667
|
+
manifest,
|
|
668
|
+
initialLocale,
|
|
669
|
+
storage,
|
|
670
|
+
children
|
|
671
|
+
}) {
|
|
672
|
+
const [locale, _setLocale] = (0, import_react9.useState)(
|
|
673
|
+
() => determineInitialLocale(manifest, initialLocale, storage)
|
|
674
|
+
);
|
|
675
|
+
const setLocale = (0, import_react9.useCallback)(
|
|
676
|
+
(nextLocale) => {
|
|
677
|
+
storage?.set(nextLocale);
|
|
678
|
+
_setLocale(nextLocale);
|
|
679
|
+
},
|
|
680
|
+
[storage]
|
|
681
|
+
);
|
|
682
|
+
const value = (0, import_react9.useMemo)(() => {
|
|
683
|
+
const store = createLocalizationStore(manifest, locale);
|
|
684
|
+
return { locale, setLocale, store, manifest };
|
|
685
|
+
}, [locale, manifest, setLocale]);
|
|
686
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LocalizationContext.Provider, { value, children });
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
// src/localization/hooks/use-localization.ts
|
|
690
|
+
var import_react10 = require("react");
|
|
691
|
+
var import_runtime2 = require("@valfuse-node/localization/runtime");
|
|
692
|
+
function pickFallbackText(fallback, key) {
|
|
693
|
+
if (!fallback) return void 0;
|
|
694
|
+
if (typeof fallback === "string") return fallback;
|
|
695
|
+
if (typeof fallback === "function") return fallback(key);
|
|
696
|
+
return fallback[key];
|
|
697
|
+
}
|
|
698
|
+
function useLocalization(options = {}) {
|
|
699
|
+
const context = (0, import_react10.useContext)(LocalizationContext);
|
|
700
|
+
if (!context) {
|
|
701
|
+
throw new Error("useLocalization must be used within LocalizationProvider.");
|
|
702
|
+
}
|
|
703
|
+
const { locale, manifest } = context;
|
|
704
|
+
const fallback = options.fallback;
|
|
705
|
+
const runtimeContext = (0, import_react10.useMemo)(
|
|
706
|
+
() => ({
|
|
707
|
+
locale,
|
|
708
|
+
fallbackLocale: manifest.fallback_locale,
|
|
709
|
+
messages: manifest.messages
|
|
710
|
+
}),
|
|
711
|
+
[locale, manifest.fallback_locale, manifest.messages]
|
|
712
|
+
);
|
|
713
|
+
const readTranslation = (0, import_react10.useCallback)(
|
|
714
|
+
(key) => (0, import_runtime2.lookupMessage)(runtimeContext, key),
|
|
715
|
+
[runtimeContext]
|
|
716
|
+
);
|
|
717
|
+
const hasKey = (0, import_react10.useCallback)(
|
|
718
|
+
(key) => key in (manifest.messages[locale] ?? {}) || key in (manifest.messages[manifest.fallback_locale] ?? {}),
|
|
719
|
+
[locale, manifest.fallback_locale, manifest.messages]
|
|
720
|
+
);
|
|
721
|
+
const translate = (0, import_react10.useCallback)(
|
|
722
|
+
(key, fallbackValue) => {
|
|
723
|
+
const translated = readTranslation(key);
|
|
724
|
+
if (!translated || translated === key) {
|
|
725
|
+
if (fallbackValue === null) return translated;
|
|
726
|
+
return fallbackValue ?? pickFallbackText(fallback, key) ?? translated;
|
|
727
|
+
}
|
|
728
|
+
return translated;
|
|
729
|
+
},
|
|
730
|
+
[fallback, readTranslation]
|
|
731
|
+
);
|
|
732
|
+
const format = (0, import_react10.useCallback)(
|
|
733
|
+
(key, params) => (0, import_runtime2.interpolate)(translate(key), params),
|
|
734
|
+
[translate]
|
|
735
|
+
);
|
|
736
|
+
const translateOrNull = (0, import_react10.useCallback)(
|
|
737
|
+
(key) => {
|
|
738
|
+
if (key == null) return null;
|
|
739
|
+
return hasKey(key) ? translate(key) : null;
|
|
740
|
+
},
|
|
741
|
+
[hasKey, translate]
|
|
742
|
+
);
|
|
743
|
+
const formatOrNull = (0, import_react10.useCallback)(
|
|
744
|
+
(key, params) => {
|
|
745
|
+
if (key == null) return null;
|
|
746
|
+
return hasKey(key) ? format(key, params) : null;
|
|
747
|
+
},
|
|
748
|
+
[hasKey, format]
|
|
749
|
+
);
|
|
750
|
+
const raw = (0, import_react10.useCallback)(
|
|
751
|
+
(key) => manifest.messages[locale]?.[key] ?? manifest.messages[manifest.fallback_locale]?.[key] ?? "",
|
|
752
|
+
[locale, manifest.fallback_locale, manifest.messages]
|
|
753
|
+
);
|
|
754
|
+
const plural = (0, import_react10.useCallback)(
|
|
755
|
+
(key, count) => (0, import_runtime2.pickStructuredPluralVariant)(raw(key), count),
|
|
756
|
+
[raw]
|
|
757
|
+
);
|
|
758
|
+
const pluralOrNull = (0, import_react10.useCallback)(
|
|
759
|
+
(key, count) => {
|
|
760
|
+
if (key == null) return null;
|
|
761
|
+
return hasKey(key) ? plural(key, count) : null;
|
|
762
|
+
},
|
|
763
|
+
[hasKey, plural]
|
|
764
|
+
);
|
|
765
|
+
const gender = (0, import_react10.useCallback)(
|
|
766
|
+
(key, value, params) => (0, import_runtime2.interpolate)((0, import_runtime2.pickStructuredGenderVariant)(raw(key), value), params),
|
|
767
|
+
[raw]
|
|
768
|
+
);
|
|
769
|
+
const contextFn = (0, import_react10.useCallback)(
|
|
770
|
+
(key, value, params) => {
|
|
771
|
+
const translated = (0, import_runtime2.pickStructuredContextVariant)(raw(key), value);
|
|
772
|
+
return params ? (0, import_runtime2.interpolate)(translated, params) : translated;
|
|
773
|
+
},
|
|
774
|
+
[raw]
|
|
775
|
+
);
|
|
776
|
+
const namespace = (0, import_react10.useCallback)(
|
|
777
|
+
(scope) => ({
|
|
778
|
+
translate: (key, fallbackValue) => translate(`${scope}.${key}`, fallbackValue),
|
|
779
|
+
translateOrNull: (key) => key == null ? null : translateOrNull(`${scope}.${key}`),
|
|
780
|
+
format: (key, params) => format(`${scope}.${key}`, params),
|
|
781
|
+
formatOrNull: (key, params) => key == null ? null : formatOrNull(`${scope}.${key}`, params),
|
|
782
|
+
plural: (key, count) => plural(`${scope}.${key}`, count),
|
|
783
|
+
pluralOrNull: (key, count) => key == null ? null : pluralOrNull(`${scope}.${key}`, count),
|
|
784
|
+
gender: (key, value, params) => gender(`${scope}.${key}`, value, params),
|
|
785
|
+
context: (key, value, params) => contextFn(`${scope}.${key}`, value, params)
|
|
786
|
+
}),
|
|
787
|
+
[translate, translateOrNull, format, formatOrNull, plural, pluralOrNull, gender, contextFn]
|
|
788
|
+
);
|
|
789
|
+
const entriesForLocale = (0, import_react10.useMemo)(
|
|
790
|
+
() => Object.entries(manifest.messages[locale] ?? {}).sort(
|
|
791
|
+
([a], [b]) => a.localeCompare(b)
|
|
792
|
+
),
|
|
793
|
+
[locale, manifest.messages]
|
|
794
|
+
);
|
|
795
|
+
return {
|
|
796
|
+
...context,
|
|
797
|
+
translate,
|
|
798
|
+
translateOrNull,
|
|
799
|
+
format,
|
|
800
|
+
formatOrNull,
|
|
801
|
+
plural,
|
|
802
|
+
pluralOrNull,
|
|
803
|
+
gender,
|
|
804
|
+
context: contextFn,
|
|
805
|
+
namespace,
|
|
806
|
+
entriesForLocale
|
|
807
|
+
};
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
// src/localization/hooks/use-localization-tree.ts
|
|
811
|
+
var import_react11 = require("react");
|
|
812
|
+
function toSegments(key) {
|
|
813
|
+
return key.split(".").slice(1);
|
|
814
|
+
}
|
|
815
|
+
function useLocalizationTree() {
|
|
816
|
+
const { store, manifest } = useLocalization();
|
|
817
|
+
return (0, import_react11.useMemo)(() => {
|
|
818
|
+
const strings = {};
|
|
819
|
+
const placeholders = {};
|
|
820
|
+
for (const entry of manifest.entries) {
|
|
821
|
+
const segments = toSegments(entry.key);
|
|
822
|
+
if (segments.length === 0) continue;
|
|
823
|
+
const target = entry.placeholders.length > 0 ? placeholders : strings;
|
|
824
|
+
let cursor = target;
|
|
825
|
+
for (let i = 0; i < segments.length - 1; i += 1) {
|
|
826
|
+
const segment = segments[i];
|
|
827
|
+
if (!segment) continue;
|
|
828
|
+
cursor[segment] ?? (cursor[segment] = {});
|
|
829
|
+
cursor = cursor[segment];
|
|
830
|
+
}
|
|
831
|
+
const leaf = segments[segments.length - 1];
|
|
832
|
+
if (!leaf) continue;
|
|
833
|
+
if (entry.placeholders.length > 0) {
|
|
834
|
+
cursor[leaf] = (params) => store.t(entry.key, params);
|
|
835
|
+
} else {
|
|
836
|
+
cursor[leaf] = store.t(entry.key);
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
return { strings, placeholders };
|
|
840
|
+
}, [store, manifest]);
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
// src/localization/lazy/create-lazy-locale-loader.ts
|
|
844
|
+
function createLazyLocaleLoader(manifest) {
|
|
845
|
+
return async (locale) => manifest.messages[locale] ?? {};
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
// src/localization/ssr/create-ssr-localization-state.ts
|
|
849
|
+
function createSsrLocalizationState(manifest, locale) {
|
|
850
|
+
const activeLocale = locale ?? manifest.base_locale;
|
|
851
|
+
return {
|
|
852
|
+
locale: activeLocale,
|
|
853
|
+
messages: manifest.messages[activeLocale] ?? {}
|
|
854
|
+
};
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
// src/localization/storage/locale-storage.ts
|
|
858
|
+
function localStorageStrategy(options = {}) {
|
|
859
|
+
const key = options.key ?? "locale";
|
|
860
|
+
return {
|
|
861
|
+
get() {
|
|
862
|
+
try {
|
|
863
|
+
return window.localStorage.getItem(key) ?? void 0;
|
|
864
|
+
} catch {
|
|
865
|
+
return void 0;
|
|
866
|
+
}
|
|
867
|
+
},
|
|
868
|
+
set(locale) {
|
|
869
|
+
try {
|
|
870
|
+
window.localStorage.setItem(key, locale);
|
|
871
|
+
} catch {
|
|
872
|
+
}
|
|
873
|
+
},
|
|
874
|
+
remove() {
|
|
875
|
+
try {
|
|
876
|
+
window.localStorage.removeItem(key);
|
|
877
|
+
} catch {
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
};
|
|
881
|
+
}
|
|
882
|
+
function sessionStorageStrategy(options = {}) {
|
|
883
|
+
const key = options.key ?? "locale";
|
|
884
|
+
return {
|
|
885
|
+
get() {
|
|
886
|
+
try {
|
|
887
|
+
return window.sessionStorage.getItem(key) ?? void 0;
|
|
888
|
+
} catch {
|
|
889
|
+
return void 0;
|
|
890
|
+
}
|
|
891
|
+
},
|
|
892
|
+
set(locale) {
|
|
893
|
+
try {
|
|
894
|
+
window.sessionStorage.setItem(key, locale);
|
|
895
|
+
} catch {
|
|
896
|
+
}
|
|
897
|
+
},
|
|
898
|
+
remove() {
|
|
899
|
+
try {
|
|
900
|
+
window.sessionStorage.removeItem(key);
|
|
901
|
+
} catch {
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
};
|
|
905
|
+
}
|
|
906
|
+
function cookieStrategy(options = {}) {
|
|
907
|
+
const {
|
|
908
|
+
key = "locale",
|
|
909
|
+
domain,
|
|
910
|
+
path = "/",
|
|
911
|
+
maxAge = 31536e3,
|
|
912
|
+
sameSite = "Lax"
|
|
913
|
+
} = options;
|
|
914
|
+
function buildCookie(value, age) {
|
|
915
|
+
const isSecure = options.secure !== void 0 ? options.secure : typeof location !== "undefined" && location.protocol === "https:";
|
|
916
|
+
let cookie = `${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
|
|
917
|
+
cookie += `; path=${path}`;
|
|
918
|
+
cookie += `; max-age=${age}`;
|
|
919
|
+
if (domain) cookie += `; domain=${domain}`;
|
|
920
|
+
if (isSecure) cookie += "; Secure";
|
|
921
|
+
cookie += `; SameSite=${sameSite}`;
|
|
922
|
+
return cookie;
|
|
923
|
+
}
|
|
924
|
+
return {
|
|
925
|
+
get() {
|
|
926
|
+
if (typeof document === "undefined") return void 0;
|
|
927
|
+
const encodedKey = encodeURIComponent(key);
|
|
928
|
+
const match = document.cookie.split("; ").find((c) => c.startsWith(`${encodedKey}=`));
|
|
929
|
+
const rawValue = match?.split("=").slice(1).join("=");
|
|
930
|
+
return rawValue !== void 0 ? decodeURIComponent(rawValue) : void 0;
|
|
931
|
+
},
|
|
932
|
+
set(locale) {
|
|
933
|
+
if (typeof document === "undefined") return;
|
|
934
|
+
document.cookie = buildCookie(locale, maxAge);
|
|
935
|
+
},
|
|
936
|
+
remove() {
|
|
937
|
+
if (typeof document === "undefined") return;
|
|
938
|
+
document.cookie = buildCookie("", 0);
|
|
939
|
+
}
|
|
940
|
+
};
|
|
941
|
+
}
|
|
942
|
+
function memoryStrategy(options = {}) {
|
|
943
|
+
let stored = options.initialLocale;
|
|
944
|
+
return {
|
|
945
|
+
get: () => stored,
|
|
946
|
+
set: (locale) => {
|
|
947
|
+
stored = locale;
|
|
948
|
+
},
|
|
949
|
+
remove: () => {
|
|
950
|
+
stored = void 0;
|
|
951
|
+
}
|
|
952
|
+
};
|
|
953
|
+
}
|
|
954
|
+
function composeStorage(...storages) {
|
|
955
|
+
return {
|
|
956
|
+
get() {
|
|
957
|
+
for (const s of storages) {
|
|
958
|
+
const v = s.get();
|
|
959
|
+
if (v !== void 0) return v;
|
|
960
|
+
}
|
|
961
|
+
return void 0;
|
|
962
|
+
},
|
|
963
|
+
set(locale) {
|
|
964
|
+
storages.forEach((s) => s.set(locale));
|
|
965
|
+
},
|
|
966
|
+
remove() {
|
|
967
|
+
storages.forEach((s) => s.remove?.());
|
|
968
|
+
}
|
|
969
|
+
};
|
|
970
|
+
}
|
|
971
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
972
|
+
0 && (module.exports = {
|
|
973
|
+
LocalizationProvider,
|
|
974
|
+
ValfuseController,
|
|
975
|
+
composeStorage,
|
|
976
|
+
cookieStrategy,
|
|
977
|
+
createLazyLocaleLoader,
|
|
978
|
+
createLocalizationStore,
|
|
979
|
+
createSsrLocalizationState,
|
|
980
|
+
localStorageStrategy,
|
|
981
|
+
memoryStrategy,
|
|
982
|
+
sessionStorageStrategy,
|
|
983
|
+
useLocalization,
|
|
984
|
+
useLocalizationTree,
|
|
985
|
+
useValfuseForm
|
|
986
|
+
});
|