notform 2.0.0-alpha.6 → 2.0.0-alpha.8
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/README.md +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +51 -7
- package/package.json +3 -3
package/README.md
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -199,7 +199,7 @@ type NotFormProps = {
|
|
|
199
199
|
};
|
|
200
200
|
/** Slots for the `NotForm` component. */
|
|
201
201
|
type NotFormSlots = {
|
|
202
|
-
default: [];
|
|
202
|
+
/** The default slot receives the full form instance */default: [];
|
|
203
203
|
};
|
|
204
204
|
//#endregion
|
|
205
205
|
//#region src/composables/use-not-form.d.ts
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { computed, createBlock, createCommentVNode, createElementBlock, createTextVNode, defineComponent, guardReactiveProps, inject, markRaw, mergeProps, nextTick, normalizeProps, onMounted, openBlock, provide, reactive, ref, renderSlot, resolveDynamicComponent, toDisplayString, toValue, unref, useAttrs, withCtx } from "vue";
|
|
1
|
+
import { computed, createBlock, createCommentVNode, createElementBlock, createTextVNode, defineComponent, guardReactiveProps, inject, markRaw, mergeProps, nextTick, normalizeProps, onMounted, openBlock, provide, reactive, ref, renderSlot, resolveDynamicComponent, toDisplayString, toValue, unref, useAttrs, watch, withCtx } from "vue";
|
|
2
2
|
import { klona } from "klona/full";
|
|
3
3
|
import { dequal } from "dequal";
|
|
4
4
|
import { deepKeys, deleteProperty, getProperty, hasProperty, parsePath, setProperty } from "dot-prop";
|
|
@@ -56,6 +56,11 @@ function useNotForm(config) {
|
|
|
56
56
|
/**
|
|
57
57
|
* Mutable so `reset()` can replace the reference when new values are provided.
|
|
58
58
|
* Always deep-cloned to prevent external mutation from affecting the baseline.
|
|
59
|
+
*
|
|
60
|
+
* These are intentionally `let` — `reset()` replaces them, and the instance
|
|
61
|
+
* exposes them via getters so consumers always read the current snapshot.
|
|
62
|
+
* The `readonly` modifier on the type prevents external assignment while still
|
|
63
|
+
* allowing the getter to return the latest value after a reset.
|
|
59
64
|
*/
|
|
60
65
|
let initialValues = klona(config.initialValues ?? {});
|
|
61
66
|
let initialErrors = klona(config.initialErrors ?? []);
|
|
@@ -85,6 +90,25 @@ function useNotForm(config) {
|
|
|
85
90
|
const isSubmitting = ref(false);
|
|
86
91
|
const isValidating = ref(false);
|
|
87
92
|
/**
|
|
93
|
+
* Counter-based validation tracking.
|
|
94
|
+
*
|
|
95
|
+
* A boolean flag flips to `false` as soon as the first concurrent
|
|
96
|
+
* validation resolves, even if others are still running.
|
|
97
|
+
* A counter fixes this: `isValidating` stays `true` until every
|
|
98
|
+
* in-flight call has settled.
|
|
99
|
+
*/
|
|
100
|
+
let validatingCount = 0;
|
|
101
|
+
/** Increments the validation counter and sets `isValidating` to true. */
|
|
102
|
+
const beginValidating = () => {
|
|
103
|
+
validatingCount++;
|
|
104
|
+
isValidating.value = true;
|
|
105
|
+
};
|
|
106
|
+
/** Decrements the validation counter and sets `isValidating` to false if the counter reaches zero. */
|
|
107
|
+
const endValidating = () => {
|
|
108
|
+
validatingCount--;
|
|
109
|
+
if (validatingCount === 0) isValidating.value = false;
|
|
110
|
+
};
|
|
111
|
+
/**
|
|
88
112
|
* Reactive Sets using `reactive()` for the same Pinia-compatibility reason
|
|
89
113
|
* as `errors` above — `ref(new Set())` would be unwrapped to a plain Set.
|
|
90
114
|
*/
|
|
@@ -129,7 +153,7 @@ function useNotForm(config) {
|
|
|
129
153
|
return errors.filter((error) => isIssuePathEqual(error.path, pathSegments));
|
|
130
154
|
};
|
|
131
155
|
const validate = async () => {
|
|
132
|
-
|
|
156
|
+
beginValidating();
|
|
133
157
|
try {
|
|
134
158
|
const result = await runSchema();
|
|
135
159
|
if (result?.issues) {
|
|
@@ -139,11 +163,11 @@ function useNotForm(config) {
|
|
|
139
163
|
clearErrors();
|
|
140
164
|
return { value: result.value };
|
|
141
165
|
} finally {
|
|
142
|
-
|
|
166
|
+
endValidating();
|
|
143
167
|
}
|
|
144
168
|
};
|
|
145
169
|
const validateField = async (path) => {
|
|
146
|
-
|
|
170
|
+
beginValidating();
|
|
147
171
|
try {
|
|
148
172
|
const result = await runSchema();
|
|
149
173
|
const pathSegments = parsePath(path);
|
|
@@ -162,7 +186,7 @@ function useNotForm(config) {
|
|
|
162
186
|
}
|
|
163
187
|
return { value: getProperty(result.value, path) };
|
|
164
188
|
} finally {
|
|
165
|
-
|
|
189
|
+
endValidating();
|
|
166
190
|
}
|
|
167
191
|
};
|
|
168
192
|
const submit = async (event) => {
|
|
@@ -197,8 +221,12 @@ function useNotForm(config) {
|
|
|
197
221
|
dirtyFields.clear();
|
|
198
222
|
};
|
|
199
223
|
return markRaw({
|
|
200
|
-
initialValues
|
|
201
|
-
|
|
224
|
+
get initialValues() {
|
|
225
|
+
return initialValues;
|
|
226
|
+
},
|
|
227
|
+
get initialErrors() {
|
|
228
|
+
return initialErrors;
|
|
229
|
+
},
|
|
202
230
|
validateOn,
|
|
203
231
|
validationMode,
|
|
204
232
|
values,
|
|
@@ -533,6 +561,22 @@ var not_array_field_default = /* @__PURE__ */ defineComponent({
|
|
|
533
561
|
await nextTick();
|
|
534
562
|
if (validateOn.value.onMount) validate();
|
|
535
563
|
});
|
|
564
|
+
/**
|
|
565
|
+
* Syncs `itemKeys` whenever the underlying array changes outside of this
|
|
566
|
+
* component's own mutation methods — most commonly after `form.reset()`.
|
|
567
|
+
*
|
|
568
|
+
* Without this, `itemKeys` would be stale until the next mutation:
|
|
569
|
+
* - If the reset shrinks the array, a subsequent `append` would call
|
|
570
|
+
* `syncKeys` and regenerate keys for the surviving items, causing
|
|
571
|
+
* Vue to remount them unnecessarily.
|
|
572
|
+
* - If the reset grows the array, items render with `fallback` keys
|
|
573
|
+
* until the next mutation, breaking key stability guarantees.
|
|
574
|
+
*
|
|
575
|
+
* Our own mutations already manage keys explicitly before writing to
|
|
576
|
+
* the array, so when this watcher fires after them, `syncKeys` is a
|
|
577
|
+
* cheap no-op (lengths already match).
|
|
578
|
+
*/
|
|
579
|
+
watch(array, () => syncKeys());
|
|
536
580
|
const slotProps = computed(() => ({
|
|
537
581
|
path: props.path,
|
|
538
582
|
items: items.value,
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "notform",
|
|
3
|
-
"version": "2.0.0-alpha.
|
|
3
|
+
"version": "2.0.0-alpha.8",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"private": false,
|
|
6
6
|
"description": "Vue Forms Without the Friction",
|
|
7
7
|
"author": "Favour Emeka <favorodera@gmail.com>",
|
|
8
8
|
"license": "MIT",
|
|
9
|
-
"homepage": "https://
|
|
9
|
+
"homepage": "https://notformdocs.vercel.app/",
|
|
10
10
|
"repository": {
|
|
11
11
|
"type": "git",
|
|
12
12
|
"url": "git+https://github.com/favorodera/notform.git"
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
"vue form validator"
|
|
58
58
|
],
|
|
59
59
|
"engines": {
|
|
60
|
-
"node": ">=
|
|
60
|
+
"node": ">=22.0.0"
|
|
61
61
|
},
|
|
62
62
|
"scripts": {
|
|
63
63
|
"build": "tsdown",
|