@formisch/qwik 0.12.0 → 0.13.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.
@@ -47,11 +47,13 @@ function initializeFieldStore(internalFieldStore, schema, initialInput, path, nu
47
47
  else {
48
48
  internalFieldStore.schema = schema;
49
49
  internalFieldStore.name = JSON.stringify(path);
50
+ internalFieldStore.path = path;
50
51
  const initialElements = [];
51
52
  internalFieldStore.initialElements = initialElements;
52
53
  internalFieldStore.elements = initialElements;
53
54
  internalFieldStore.errors = createSignal(null);
54
55
  internalFieldStore.isTouched = createSignal(false);
56
+ internalFieldStore.isEdited = createSignal(false);
55
57
  internalFieldStore.isDirty = createSignal(false);
56
58
  if (schema.type === "array" || schema.type === "loose_tuple" || schema.type === "strict_tuple" || schema.type === "tuple") {
57
59
  if (internalFieldStore.kind && internalFieldStore.kind !== "array") throw new Error(`Store initialized as "${internalFieldStore.kind}" cannot be reinitialized as "array"`);
@@ -61,16 +63,13 @@ function initializeFieldStore(internalFieldStore, schema, initialInput, path, nu
61
63
  if (schema.type === "array") {
62
64
  if (initialInput) for (let index = 0; index < initialInput.length; index++) {
63
65
  internalFieldStore.children[index] = {};
64
- path.push(index);
65
- initializeFieldStore(internalFieldStore.children[index], schema.item, initialInput[index], path);
66
- path.pop();
66
+ initializeFieldStore(internalFieldStore.children[index], schema.item, initialInput[index], [...path, index]);
67
67
  }
68
68
  } else for (let index = 0; index < schema.items.length; index++) {
69
69
  internalFieldStore.children[index] = {};
70
- path.push(index);
71
- initializeFieldStore(internalFieldStore.children[index], schema.items[index], initialInput?.[index], path);
72
- path.pop();
70
+ initializeFieldStore(internalFieldStore.children[index], schema.items[index], initialInput?.[index], [...path, index]);
73
71
  }
72
+ internalFieldStore.isNullish = nullish;
74
73
  const arrayInput = nullish && initialInput == null ? initialInput : true;
75
74
  internalFieldStore.initialInput = createSignal(arrayInput);
76
75
  internalFieldStore.startInput = createSignal(arrayInput);
@@ -87,10 +86,9 @@ function initializeFieldStore(internalFieldStore, schema, initialInput, path, nu
87
86
  internalFieldStore.children ??= {};
88
87
  for (const key in schema.entries) {
89
88
  internalFieldStore.children[key] ??= {};
90
- path.push(key);
91
- initializeFieldStore(internalFieldStore.children[key], schema.entries[key], initialInput?.[key], path);
92
- path.pop();
89
+ initializeFieldStore(internalFieldStore.children[key], schema.entries[key], initialInput?.[key], [...path, key]);
93
90
  }
91
+ internalFieldStore.isNullish = nullish;
94
92
  const objectInput = nullish && initialInput == null ? initialInput : true;
95
93
  internalFieldStore.initialInput = createSignal(objectInput);
96
94
  internalFieldStore.startInput = createSignal(objectInput);
@@ -110,8 +108,9 @@ function initializeFieldStore(internalFieldStore, schema, initialInput, path, nu
110
108
  /**
111
109
  * Copies the deeply nested state (signal values) from one field store to
112
110
  * another. This includes the `elements`, `errors`, `startInput`, `input`,
113
- * `isTouched`, `isDirty`, and for arrays `startItems` and `items` properties.
114
- * Recursively walks through the field stores and copies all signal values.
111
+ * `isTouched`, `isEdited`, `isDirty`, and for arrays `startItems` and `items`
112
+ * properties. Recursively walks through the field stores and copies all signal
113
+ * values.
115
114
  *
116
115
  * @param fromInternalFieldStore The source field store to copy from.
117
116
  * @param toInternalFieldStore The destination field store to copy to.
@@ -124,19 +123,16 @@ function copyItemState(fromInternalFieldStore, toInternalFieldStore) {
124
123
  toInternalFieldStore.startInput.value = fromInternalFieldStore.startInput.value;
125
124
  toInternalFieldStore.input.value = fromInternalFieldStore.input.value;
126
125
  toInternalFieldStore.isTouched.value = fromInternalFieldStore.isTouched.value;
126
+ toInternalFieldStore.isEdited.value = fromInternalFieldStore.isEdited.value;
127
127
  toInternalFieldStore.isDirty.value = fromInternalFieldStore.isDirty.value;
128
128
  if (fromInternalFieldStore.kind === "array" && toInternalFieldStore.kind === "array") {
129
129
  const fromItems = fromInternalFieldStore.items.value;
130
130
  toInternalFieldStore.startItems.value = fromInternalFieldStore.startItems.value;
131
131
  toInternalFieldStore.items.value = fromItems;
132
- let path;
133
132
  for (let index = 0; index < fromItems.length; index++) {
134
133
  if (!toInternalFieldStore.children[index]) {
135
- path ??= JSON.parse(toInternalFieldStore.name);
136
134
  toInternalFieldStore.children[index] = {};
137
- path.push(index);
138
- initializeFieldStore(toInternalFieldStore.children[index], toInternalFieldStore.schema.item, void 0, path);
139
- path.pop();
135
+ initializeFieldStore(toInternalFieldStore.children[index], toInternalFieldStore.schema.item, void 0, [...toInternalFieldStore.path, index]);
140
136
  }
141
137
  copyItemState(fromInternalFieldStore.children[index], toInternalFieldStore.children[index]);
142
138
  }
@@ -146,10 +142,10 @@ function copyItemState(fromInternalFieldStore, toInternalFieldStore) {
146
142
  }
147
143
  /**
148
144
  * Resets the state of a field store (signal values) deeply nested. Sets
149
- * `elements` to empty array, `errors` to `null`, `isTouched` and `isDirty` to
150
- * `false`, and `startInput`, `input`, `startItems`, and `items` to the new
151
- * input value. Keeps the `initialInput` and `initialItems` state unchanged for
152
- * form reset functionality.
145
+ * `elements` to empty array, `errors` to `null`, `isTouched`, `isEdited` and
146
+ * `isDirty` to `false`, and `startInput`, `input`, `startItems`, and `items` to
147
+ * the new input value. Keeps the `initialInput` and `initialItems` state
148
+ * unchanged for form reset functionality.
153
149
  *
154
150
  * @param internalFieldStore The field store to reset.
155
151
  * @param input The new input value (can be any type including array or object).
@@ -164,30 +160,32 @@ function resetItemState(internalFieldStore, input, keepStart = false) {
164
160
  internalFieldStore.elements = elements;
165
161
  internalFieldStore.errors.value = null;
166
162
  internalFieldStore.isTouched.value = false;
163
+ internalFieldStore.isEdited.value = false;
167
164
  internalFieldStore.isDirty.value = false;
168
165
  if (internalFieldStore.kind === "array" || internalFieldStore.kind === "object") {
169
- const objectInput = input == null ? input : true;
166
+ const objectInput = internalFieldStore.isNullish && input == null ? input : true;
170
167
  if (!keepStart) internalFieldStore.startInput.value = objectInput;
171
168
  internalFieldStore.input.value = objectInput;
172
- if (internalFieldStore.kind === "array") if (input) {
173
- const length = internalFieldStore.schema.type === "array" ? input.length : internalFieldStore.children.length;
174
- const newItems = Array.from({ length }, createId);
175
- if (!keepStart) internalFieldStore.startItems.value = newItems;
176
- internalFieldStore.items.value = newItems;
177
- let path;
178
- for (let index = 0; index < length; index++) if (internalFieldStore.children[index]) resetItemState(internalFieldStore.children[index], input[index], keepStart);
179
- else {
180
- path ??= JSON.parse(internalFieldStore.name);
181
- internalFieldStore.children[index] = {};
182
- path.push(index);
183
- initializeFieldStore(internalFieldStore.children[index], internalFieldStore.schema.item, input[index], path);
184
- path.pop();
169
+ if (internalFieldStore.kind === "array") {
170
+ const isTuple = internalFieldStore.schema.type !== "array";
171
+ if (input || isTuple) {
172
+ const length = isTuple ? internalFieldStore.children.length : input.length;
173
+ const newItems = Array.from({ length }, createId);
174
+ if (!keepStart) internalFieldStore.startItems.value = newItems;
175
+ internalFieldStore.items.value = newItems;
176
+ for (let index = 0; index < length; index++) {
177
+ const itemInput = input?.[index];
178
+ if (internalFieldStore.children[index]) resetItemState(internalFieldStore.children[index], itemInput, keepStart);
179
+ else {
180
+ internalFieldStore.children[index] = {};
181
+ initializeFieldStore(internalFieldStore.children[index], internalFieldStore.schema.item, itemInput, [...internalFieldStore.path, index]);
182
+ }
183
+ }
184
+ } else {
185
+ if (!keepStart) internalFieldStore.startItems.value = [];
186
+ internalFieldStore.items.value = [];
185
187
  }
186
- } else {
187
- if (!keepStart) internalFieldStore.startItems.value = [];
188
- internalFieldStore.items.value = [];
189
- }
190
- else for (const key in internalFieldStore.children) resetItemState(internalFieldStore.children[key], input?.[key], keepStart);
188
+ } else for (const key in internalFieldStore.children) resetItemState(internalFieldStore.children[key], input?.[key], keepStart);
191
189
  } else {
192
190
  if (!keepStart) internalFieldStore.startInput.value = input;
193
191
  internalFieldStore.input.value = input;
@@ -197,8 +195,8 @@ function resetItemState(internalFieldStore, input, keepStart = false) {
197
195
  /**
198
196
  * Swaps the deeply nested state (signal values) between two field stores. This
199
197
  * includes the `elements`, `errors`, `startInput`, `input`, `isTouched`,
200
- * `isDirty`, and for arrays `startItems` and `items` properties. Recursively
201
- * walks through the field stores and swaps all signal values.
198
+ * `isEdited`, `isDirty`, and for arrays `startItems` and `items` properties.
199
+ * Recursively walks through the field stores and swaps all signal values.
202
200
  *
203
201
  * @param firstInternalFieldStore The first field store to swap.
204
202
  * @param secondInternalFieldStore The second field store to swap.
@@ -221,6 +219,9 @@ function swapItemState(firstInternalFieldStore, secondInternalFieldStore) {
221
219
  const tempIsTouched = firstInternalFieldStore.isTouched.value;
222
220
  firstInternalFieldStore.isTouched.value = secondInternalFieldStore.isTouched.value;
223
221
  secondInternalFieldStore.isTouched.value = tempIsTouched;
222
+ const tempIsEdited = firstInternalFieldStore.isEdited.value;
223
+ firstInternalFieldStore.isEdited.value = secondInternalFieldStore.isEdited.value;
224
+ secondInternalFieldStore.isEdited.value = tempIsEdited;
224
225
  const tempIsDirty = firstInternalFieldStore.isDirty.value;
225
226
  firstInternalFieldStore.isDirty.value = secondInternalFieldStore.isDirty.value;
226
227
  secondInternalFieldStore.isDirty.value = tempIsDirty;
@@ -233,22 +234,14 @@ function swapItemState(firstInternalFieldStore, secondInternalFieldStore) {
233
234
  firstInternalFieldStore.items.value = secondItems;
234
235
  secondInternalFieldStore.items.value = firstItems;
235
236
  const maxLength = Math.max(firstItems.length, secondItems.length);
236
- let firstPath;
237
- let secondPath;
238
237
  for (let index = 0; index < maxLength; index++) {
239
238
  if (!firstInternalFieldStore.children[index]) {
240
- firstPath ??= JSON.parse(firstInternalFieldStore.name);
241
239
  firstInternalFieldStore.children[index] = {};
242
- firstPath.push(index);
243
- initializeFieldStore(firstInternalFieldStore.children[index], firstInternalFieldStore.schema.item, void 0, firstPath);
244
- firstPath.pop();
240
+ initializeFieldStore(firstInternalFieldStore.children[index], firstInternalFieldStore.schema.item, void 0, [...firstInternalFieldStore.path, index]);
245
241
  }
246
242
  if (!secondInternalFieldStore.children[index]) {
247
- secondPath ??= JSON.parse(secondInternalFieldStore.name);
248
243
  secondInternalFieldStore.children[index] = {};
249
- secondPath.push(index);
250
- initializeFieldStore(secondInternalFieldStore.children[index], secondInternalFieldStore.schema.item, void 0, secondPath);
251
- secondPath.pop();
244
+ initializeFieldStore(secondInternalFieldStore.children[index], secondInternalFieldStore.schema.item, void 0, [...secondInternalFieldStore.path, index]);
252
245
  }
253
246
  swapItemState(firstInternalFieldStore.children[index], secondInternalFieldStore.children[index]);
254
247
  }
@@ -279,6 +272,29 @@ function focusFieldElement(internalFieldStore) {
279
272
  return false;
280
273
  }
281
274
  /**
275
+ * Walks through the field store and all nested children, calling the callback
276
+ * for each field store in depth-first order. The callback may return `true` to
277
+ * stop the walk early, in which case `walkFieldStore` returns `true` as well.
278
+ *
279
+ * The walk reads array `items` reactively, so a reactive caller subscribes to
280
+ * structural changes naturally. Imperative callers that must not subscribe
281
+ * (e.g. when invoked inside an effect) should wrap the call in `untrack`.
282
+ *
283
+ * @param internalFieldStore The field store to walk.
284
+ * @param callback The callback to invoke for each field store. Return `true` to stop the walk early.
285
+ *
286
+ * @returns Whether the walk was stopped early by the callback.
287
+ */
288
+ function walkFieldStore(internalFieldStore, callback) {
289
+ if (callback(internalFieldStore)) return true;
290
+ if (internalFieldStore.kind === "array") {
291
+ for (let index = 0; index < internalFieldStore.items.value.length; index++) if (walkFieldStore(internalFieldStore.children[index], callback)) return true;
292
+ } else if (internalFieldStore.kind === "object") {
293
+ for (const key in internalFieldStore.children) if (walkFieldStore(internalFieldStore.children[key], callback)) return true;
294
+ }
295
+ return false;
296
+ }
297
+ /**
282
298
  * Returns whether the specified boolean property is true for the field store
283
299
  * or any of its nested children. Recursively checks arrays and objects.
284
300
  *
@@ -289,16 +305,7 @@ function focusFieldElement(internalFieldStore) {
289
305
  */
290
306
  /* @__NO_SIDE_EFFECTS__ */
291
307
  function getFieldBool(internalFieldStore, type) {
292
- if (internalFieldStore[type].value) return true;
293
- if (internalFieldStore.kind === "array") {
294
- for (let index = 0; index < internalFieldStore.items.value.length; index++) if (/* @__PURE__ */ getFieldBool(internalFieldStore.children[index], type)) return true;
295
- return false;
296
- }
297
- if (internalFieldStore.kind == "object") {
298
- for (const key in internalFieldStore.children) if (/* @__PURE__ */ getFieldBool(internalFieldStore.children[key], type)) return true;
299
- return false;
300
- }
301
- return false;
308
+ return walkFieldStore(internalFieldStore, (internalFieldStore$1) => Boolean(internalFieldStore$1[type].value));
302
309
  }
303
310
  /**
304
311
  * Returns only the dirty input of the field store. Arrays are treated as
@@ -416,9 +423,11 @@ function getFieldStore(internalFormStore, path) {
416
423
  */
417
424
  function setFieldBool(internalFieldStore, type, bool) {
418
425
  batch(() => {
419
- internalFieldStore[type].value = bool;
420
- if (internalFieldStore.kind === "array") for (let index = 0; index < untrack(() => internalFieldStore.items.value).length; index++) setFieldBool(internalFieldStore.children[index], type, bool);
421
- else if (internalFieldStore.kind === "object") for (const key in internalFieldStore.children) setFieldBool(internalFieldStore.children[key], type, bool);
426
+ untrack(() => {
427
+ walkFieldStore(internalFieldStore, (internalFieldStore$1) => {
428
+ internalFieldStore$1[type].value = bool;
429
+ });
430
+ });
422
431
  });
423
432
  }
424
433
  /**
@@ -430,19 +439,17 @@ function setFieldBool(internalFieldStore, type, bool) {
430
439
  */
431
440
  function setNestedInput(internalFieldStore, input) {
432
441
  internalFieldStore.isTouched.value = true;
442
+ internalFieldStore.isEdited.value = true;
433
443
  if (internalFieldStore.kind === "array") {
434
444
  const arrayInput = input ?? [];
435
445
  const items = internalFieldStore.items.value;
436
446
  const length = internalFieldStore.schema.type === "array" ? arrayInput.length : internalFieldStore.children.length;
437
447
  if (length < items.length) internalFieldStore.items.value = items.slice(0, length);
438
448
  else if (length > items.length) {
439
- const path = JSON.parse(internalFieldStore.name);
440
449
  for (let index = items.length; index < length; index++) if (internalFieldStore.children[index]) resetItemState(internalFieldStore.children[index], arrayInput[index], true);
441
450
  else {
442
451
  internalFieldStore.children[index] = {};
443
- path.push(index);
444
- initializeFieldStore(internalFieldStore.children[index], internalFieldStore.schema.item, arrayInput[index], path);
445
- path.pop();
452
+ initializeFieldStore(internalFieldStore.children[index], internalFieldStore.schema.item, arrayInput[index], [...internalFieldStore.path, index]);
446
453
  }
447
454
  internalFieldStore.items.value = [...items, ...Array.from({ length: length - items.length }, createId)];
448
455
  }
@@ -493,14 +500,9 @@ function setInitialFieldInput(internalFieldStore, initialInput) {
493
500
  internalFieldStore.initialInput.value = initialInput == null ? initialInput : true;
494
501
  const initialArrayInput = initialInput ?? [];
495
502
  const length = internalFieldStore.schema.type === "array" ? initialArrayInput.length : internalFieldStore.children.length;
496
- if (length > internalFieldStore.children.length) {
497
- const path = JSON.parse(internalFieldStore.name);
498
- for (let index = internalFieldStore.children.length; index < length; index++) {
499
- internalFieldStore.children[index] = {};
500
- path.push(index);
501
- initializeFieldStore(internalFieldStore.children[index], internalFieldStore.schema.item, initialArrayInput[index], path);
502
- path.pop();
503
- }
503
+ if (length > internalFieldStore.children.length) for (let index = internalFieldStore.children.length; index < length; index++) {
504
+ internalFieldStore.children[index] = {};
505
+ initializeFieldStore(internalFieldStore.children[index], internalFieldStore.schema.item, initialArrayInput[index], [...internalFieldStore.path, index]);
504
506
  }
505
507
  internalFieldStore.initialItems.value = Array.from({ length }, createId);
506
508
  for (let index = 0; index < internalFieldStore.children.length; index++) setInitialFieldInput(internalFieldStore.children[index], initialArrayInput[index]);
@@ -511,18 +513,6 @@ function setInitialFieldInput(internalFieldStore, initialInput) {
511
513
  });
512
514
  }
513
515
  /**
514
- * Walks through the field store and all nested children, calling the callback
515
- * for each field store in depth-first order.
516
- *
517
- * @param internalFieldStore The field store to walk.
518
- * @param callback The callback to invoke for each field store.
519
- */
520
- function walkFieldStore(internalFieldStore, callback) {
521
- callback(internalFieldStore);
522
- if (internalFieldStore.kind === "array") for (let index = 0; index < untrack(() => internalFieldStore.items.value).length; index++) walkFieldStore(internalFieldStore.children[index], callback);
523
- else if (internalFieldStore.kind === "object") for (const key in internalFieldStore.children) walkFieldStore(internalFieldStore.children[key], callback);
524
- }
525
- /**
526
516
  * Creates a new internal form store from the provided configuration.
527
517
  * Initializes the field store hierarchy, sets validation modes, and
528
518
  * creates form state signals.
@@ -581,13 +571,15 @@ async function validateFormInput(internalFormStore, config) {
581
571
  }
582
572
  let shouldFocus = config?.shouldFocus ?? false;
583
573
  batch(() => {
584
- walkFieldStore(internalFormStore, (internalFieldStore) => {
585
- if (internalFieldStore.name === "[]") internalFieldStore.errors.value = rootErrors ?? null;
586
- else {
587
- const fieldErrors = nestedErrors?.[internalFieldStore.name] ?? null;
588
- internalFieldStore.errors.value = fieldErrors;
589
- if (shouldFocus && fieldErrors && focusFieldElement(internalFieldStore)) shouldFocus = false;
590
- }
574
+ untrack(() => {
575
+ walkFieldStore(internalFormStore, (internalFieldStore) => {
576
+ if (internalFieldStore.path.length === 0) internalFieldStore.errors.value = rootErrors ?? null;
577
+ else {
578
+ const fieldErrors = nestedErrors?.[internalFieldStore.name] ?? null;
579
+ internalFieldStore.errors.value = fieldErrors;
580
+ if (shouldFocus && fieldErrors && focusFieldElement(internalFieldStore)) shouldFocus = false;
581
+ }
582
+ });
591
583
  });
592
584
  internalFormStore.validators--;
593
585
  internalFormStore.isValidating.value = internalFormStore.validators > 0;
@@ -631,25 +623,27 @@ const INTERNAL = "~internal";
631
623
  function focus(form, config) {
632
624
  focusFieldElement(getFieldStore(form[INTERNAL], config.path));
633
625
  }
634
- /**
635
- * Retrieves all error messages from all fields in the form by walking through
636
- * the entire field store tree. This is useful for displaying a summary of all
637
- * validation errors across the form.
638
- *
639
- * @param form The form store to retrieve errors from.
640
- *
641
- * @returns A non-empty array of error messages, or null if no errors exist.
642
- */
643
626
  /* @__NO_SIDE_EFFECTS__ */
644
- function getAllErrors(form) {
645
- let allErrors = null;
646
- walkFieldStore(form[INTERNAL], (internalFieldStore) => {
647
- if (internalFieldStore.kind === "array") internalFieldStore.items.value;
627
+ function getDeepErrorEntries(form, config) {
628
+ const entries = [];
629
+ walkFieldStore(config?.path ? getFieldStore(form[INTERNAL], config.path) : form[INTERNAL], (internalFieldStore) => {
648
630
  const errors = internalFieldStore.errors.value;
649
- if (errors) if (allErrors) allErrors.push(...errors);
650
- else allErrors = [...errors];
631
+ if (errors) entries.push({
632
+ path: internalFieldStore.path,
633
+ errors
634
+ });
651
635
  });
652
- return allErrors;
636
+ return entries;
637
+ }
638
+ /* @__NO_SIDE_EFFECTS__ */
639
+ function getDeepErrors(form, config) {
640
+ let deepErrors = null;
641
+ walkFieldStore(config?.path ? getFieldStore(form[INTERNAL], config.path) : form[INTERNAL], (internalFieldStore) => {
642
+ const errors = internalFieldStore.errors.value;
643
+ if (errors) if (deepErrors) deepErrors.push(...errors);
644
+ else deepErrors = [...errors];
645
+ });
646
+ return deepErrors;
653
647
  }
654
648
  /* @__NO_SIDE_EFFECTS__ */
655
649
  function getDirtyInput(form, config) {
@@ -657,9 +651,8 @@ function getDirtyInput(form, config) {
657
651
  }
658
652
  /* @__NO_SIDE_EFFECTS__ */
659
653
  function getDirtyPaths(form, config) {
660
- config?.path ? getFieldStore(form[INTERNAL], config.path) : form[INTERNAL];
661
654
  const paths = [];
662
- config?.path && [...config.path];
655
+ config?.path ? getFieldStore(form[INTERNAL], config.path) : form[INTERNAL];
663
656
  return paths;
664
657
  }
665
658
  /* @__NO_SIDE_EFFECTS__ */
@@ -710,25 +703,38 @@ function insert(form, config) {
710
703
  internalArrayStore.items.value = newItems;
711
704
  for (let index = items.length; index > insertIndex; index--) {
712
705
  if (!internalArrayStore.children[index]) {
713
- const path = JSON.parse(internalArrayStore.name);
714
706
  internalArrayStore.children[index] = {};
715
- path.push(index);
716
- initializeFieldStore(internalArrayStore.children[index], internalArrayStore.schema.item, void 0, path);
707
+ initializeFieldStore(internalArrayStore.children[index], internalArrayStore.schema.item, void 0, [...internalArrayStore.path, index]);
717
708
  }
718
709
  copyItemState(internalArrayStore.children[index - 1], internalArrayStore.children[index]);
719
710
  }
720
711
  if (!internalArrayStore.children[insertIndex]) {
721
- const path = JSON.parse(internalArrayStore.name);
722
712
  internalArrayStore.children[insertIndex] = {};
723
- path.push(insertIndex);
724
- initializeFieldStore(internalArrayStore.children[insertIndex], internalArrayStore.schema.item, config.initialInput, path);
713
+ initializeFieldStore(internalArrayStore.children[insertIndex], internalArrayStore.schema.item, config.initialInput, [...internalArrayStore.path, insertIndex]);
725
714
  } else resetItemState(internalArrayStore.children[insertIndex], config.initialInput);
726
715
  internalArrayStore.input.value = true;
727
716
  internalArrayStore.isTouched.value = true;
717
+ internalArrayStore.isEdited.value = true;
728
718
  internalArrayStore.isDirty.value = true;
729
719
  validateIfRequired(internalFormStore, internalArrayStore, "input");
730
720
  });
731
721
  }
722
+ /* @__NO_SIDE_EFFECTS__ */
723
+ function isDirty(form, config) {
724
+ return getFieldBool(config?.path ? getFieldStore(form[INTERNAL], config.path) : form[INTERNAL], "isDirty");
725
+ }
726
+ /* @__NO_SIDE_EFFECTS__ */
727
+ function isEdited(form, config) {
728
+ return getFieldBool(config?.path ? getFieldStore(form[INTERNAL], config.path) : form[INTERNAL], "isEdited");
729
+ }
730
+ /* @__NO_SIDE_EFFECTS__ */
731
+ function isTouched(form, config) {
732
+ return getFieldBool(config?.path ? getFieldStore(form[INTERNAL], config.path) : form[INTERNAL], "isTouched");
733
+ }
734
+ /* @__NO_SIDE_EFFECTS__ */
735
+ function isValid(form, config) {
736
+ return !getFieldBool(config?.path ? getFieldStore(form[INTERNAL], config.path) : form[INTERNAL], "errors");
737
+ }
732
738
  /**
733
739
  * Moves an item from one index to another within a field array. All items
734
740
  * between the source and destination indices are shifted accordingly.
@@ -751,6 +757,7 @@ function move(form, config) {
751
757
  else for (let index = config.from; index > config.to; index--) copyItemState(internalArrayStore.children[index - 1], internalArrayStore.children[index]);
752
758
  copyItemState(tempInternalFieldStore, internalArrayStore.children[config.to]);
753
759
  internalArrayStore.isTouched.value = true;
760
+ internalArrayStore.isEdited.value = true;
754
761
  internalArrayStore.isDirty.value = internalArrayStore.startItems.value.join() !== newItems.join();
755
762
  validateIfRequired(internalFormStore, internalArrayStore, "input");
756
763
  });
@@ -814,6 +821,7 @@ function remove(form, config) {
814
821
  internalArrayStore.items.value = newItems;
815
822
  for (let index = config.at; index < items.length - 1; index++) copyItemState(internalArrayStore.children[index + 1], internalArrayStore.children[index]);
816
823
  internalArrayStore.isTouched.value = true;
824
+ internalArrayStore.isEdited.value = true;
817
825
  internalArrayStore.isDirty.value = internalArrayStore.startItems.value.join() !== newItems.join();
818
826
  validateIfRequired(internalFormStore, internalArrayStore, "input");
819
827
  });
@@ -834,6 +842,7 @@ function replace(form, config) {
834
842
  internalArrayStore.items.value = newItems;
835
843
  resetItemState(internalArrayStore.children[config.at], config.initialInput);
836
844
  internalArrayStore.isTouched.value = true;
845
+ internalArrayStore.isEdited.value = true;
837
846
  internalArrayStore.isDirty.value = true;
838
847
  validateIfRequired(internalFormStore, internalArrayStore, "input");
839
848
  });
@@ -848,6 +857,7 @@ function reset(form, config) {
848
857
  internalFieldStore$1.elements = internalFieldStore$1.initialElements;
849
858
  if (!config?.keepErrors) internalFieldStore$1.errors.value = null;
850
859
  if (!config?.keepTouched) internalFieldStore$1.isTouched.value = false;
860
+ if (!config?.keepEdited) internalFieldStore$1.isEdited.value = false;
851
861
  internalFieldStore$1.startInput.value = internalFieldStore$1.initialInput.value;
852
862
  if (!config?.keepInput) internalFieldStore$1.input.value = internalFieldStore$1.initialInput.value;
853
863
  if (internalFieldStore$1.kind === "array") {
@@ -906,6 +916,7 @@ function swap(form, config) {
906
916
  internalArrayStore.items.value = newItems;
907
917
  swapItemState(internalArrayStore.children[config.at], internalArrayStore.children[config.and]);
908
918
  internalArrayStore.isTouched.value = true;
919
+ internalArrayStore.isEdited.value = true;
909
920
  internalArrayStore.isDirty.value = internalArrayStore.startItems.value.join() !== newItems.join();
910
921
  validateIfRequired(internalFormStore, internalArrayStore, "input");
911
922
  });
@@ -968,6 +979,7 @@ function useField(form, config) {
968
979
  input: createComputed$(() => getFieldInput(internalFieldStore.value)),
969
980
  errors: createComputed$(() => internalFieldStore.value.errors.value),
970
981
  isTouched: createComputed$(() => getFieldBool(internalFieldStore.value, "isTouched")),
982
+ isEdited: createComputed$(() => getFieldBool(internalFieldStore.value, "isEdited")),
971
983
  isDirty: createComputed$(() => getFieldBool(internalFieldStore.value, "isDirty")),
972
984
  isValid: createComputed$(() => !getFieldBool(internalFieldStore.value, "errors")),
973
985
  onInput: $((value) => {
@@ -1011,6 +1023,7 @@ function useFieldArray(form, config) {
1011
1023
  items: createComputed$(() => internalFieldStore.value.items.value),
1012
1024
  errors: createComputed$(() => internalFieldStore.value.errors.value),
1013
1025
  isTouched: createComputed$(() => getFieldBool(internalFieldStore.value, "isTouched")),
1026
+ isEdited: createComputed$(() => getFieldBool(internalFieldStore.value, "isEdited")),
1014
1027
  isDirty: createComputed$(() => getFieldBool(internalFieldStore.value, "isDirty")),
1015
1028
  isValid: createComputed$(() => !getFieldBool(internalFieldStore.value, "errors"))
1016
1029
  }));
@@ -1053,6 +1066,7 @@ function useFormQrl(configQrl) {
1053
1066
  isSubmitted: internalFormStore.isSubmitted,
1054
1067
  isValidating: internalFormStore.isValidating,
1055
1068
  isTouched: createComputed$(() => getFieldBool(internalFormStore, "isTouched")),
1069
+ isEdited: createComputed$(() => getFieldBool(internalFormStore, "isEdited")),
1056
1070
  isDirty: createComputed$(() => getFieldBool(internalFormStore, "isDirty")),
1057
1071
  isValid: createComputed$(() => !getFieldBool(internalFormStore, "errors")),
1058
1072
  errors: internalFormStore.errors
@@ -1127,4 +1141,4 @@ const Form = component$(({ of, onSubmit$,...other }) => {
1127
1141
  });
1128
1142
 
1129
1143
  //#endregion
1130
- export { Field, FieldArray, Form, focus, getAllErrors, getDirtyInput, getDirtyPaths, getErrors, getInput, handleSubmit, insert, move, pickDirty, remove, replace, reset, setErrors, setInput, submit, swap, useField, useFieldArray, useForm$, useFormQrl, validate };
1144
+ export { Field, FieldArray, Form, focus, getDeepErrorEntries, getDeepErrors, getDirtyInput, getDirtyPaths, getErrors, getInput, handleSubmit, insert, isDirty, isEdited, isTouched, isValid, move, pickDirty, remove, replace, reset, setErrors, setInput, submit, swap, useField, useFieldArray, useForm$, useFormQrl, validate };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@formisch/qwik",
3
3
  "description": "The lightweight, schema-first, and fully type-safe form library for Qwik",
4
- "version": "0.12.0",
4
+ "version": "0.13.0",
5
5
  "license": "MIT",
6
6
  "author": "Fabian Hiller",
7
7
  "homepage": "https://formisch.dev",