react-f0rm 1.3.0 → 1.4.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.
Files changed (98) hide show
  1. package/README.md +88 -1143
  2. package/devtools.d.ts +1 -0
  3. package/devtools.js +1 -0
  4. package/dist/array-3hAjl6Bz.d.ts +160 -0
  5. package/dist/devtools/index.cjs.js +1 -1
  6. package/dist/devtools/index.cjs.js.map +1 -1
  7. package/dist/devtools/index.d.cts +34 -0
  8. package/dist/devtools/index.d.mts +34 -0
  9. package/dist/devtools/index.d.ts +3 -2
  10. package/dist/devtools/index.mjs +1 -1
  11. package/dist/devtools/index.mjs.map +1 -1
  12. package/dist/errors-8oPux7GR.cjs.js +2 -0
  13. package/dist/errors-8oPux7GR.cjs.js.map +1 -0
  14. package/dist/errors-ClH3eV1R.mjs +2 -0
  15. package/dist/errors-ClH3eV1R.mjs.map +1 -0
  16. package/dist/index.cjs.js +1 -1
  17. package/dist/index.cjs.js.map +1 -1
  18. package/dist/index.d.cts +1833 -0
  19. package/dist/index.d.mts +1833 -0
  20. package/dist/index.d.ts +372 -117
  21. package/dist/index.mjs +1 -1
  22. package/dist/index.mjs.map +1 -1
  23. package/dist/index.umd.js +859 -225
  24. package/dist/index.umd.js.map +1 -1
  25. package/dist/index.umd.min.js +2 -2
  26. package/dist/index.umd.min.js.map +1 -1
  27. package/dist/persist.cjs.js +1 -1
  28. package/dist/persist.cjs.js.map +1 -1
  29. package/dist/persist.d.cts +49 -0
  30. package/dist/persist.d.mts +49 -0
  31. package/dist/persist.mjs +1 -1
  32. package/dist/persist.mjs.map +1 -1
  33. package/dist/resolvers/standard-schema.cjs.js +1 -1
  34. package/dist/resolvers/standard-schema.cjs.js.map +1 -1
  35. package/dist/resolvers/standard-schema.d.cts +2 -0
  36. package/dist/resolvers/standard-schema.d.mts +2 -0
  37. package/dist/resolvers/standard-schema.d.ts +1 -67
  38. package/dist/resolvers/standard-schema.mjs +1 -1
  39. package/dist/resolvers/standard-schema.mjs.map +1 -1
  40. package/dist/resolvers/yup.cjs.js +1 -1
  41. package/dist/resolvers/yup.cjs.js.map +1 -1
  42. package/dist/resolvers/yup.d.cts +6 -0
  43. package/dist/resolvers/yup.d.mts +6 -0
  44. package/dist/resolvers/yup.d.ts +0 -1
  45. package/dist/resolvers/yup.mjs +1 -1
  46. package/dist/resolvers/yup.mjs.map +1 -1
  47. package/dist/resolvers/zod.cjs.js +1 -1
  48. package/dist/resolvers/zod.cjs.js.map +1 -1
  49. package/dist/resolvers/zod.d.cts +6 -0
  50. package/dist/resolvers/zod.d.mts +6 -0
  51. package/dist/resolvers/zod.d.ts +0 -1
  52. package/dist/resolvers/zod.mjs +1 -1
  53. package/dist/resolvers/zod.mjs.map +1 -1
  54. package/dist/server/index.cjs.js +1 -1
  55. package/dist/server/index.cjs.js.map +1 -1
  56. package/dist/server/index.d.cts +106 -0
  57. package/dist/server/index.d.mts +106 -0
  58. package/dist/server/index.d.ts +31 -2
  59. package/dist/server/index.mjs +1 -1
  60. package/dist/server/index.mjs.map +1 -1
  61. package/dist/standard-schema-CYbnugL7.d.ts +1184 -0
  62. package/dist/standardSchema-BpZvg0tZ.mjs +2 -0
  63. package/dist/standardSchema-BpZvg0tZ.mjs.map +1 -0
  64. package/dist/standardSchema-CxV_DhBO.cjs.js +2 -0
  65. package/dist/standardSchema-CxV_DhBO.cjs.js.map +1 -0
  66. package/dist/validate-BEjNsNvd.mjs +2 -0
  67. package/dist/validate-BEjNsNvd.mjs.map +1 -0
  68. package/dist/validate-BvN6hiEG.cjs.js +2 -0
  69. package/dist/validate-BvN6hiEG.cjs.js.map +1 -0
  70. package/dist/values-Bod74Kzu.mjs +2 -0
  71. package/dist/values-Bod74Kzu.mjs.map +1 -0
  72. package/dist/values-DKpOCD5J.cjs.js +2 -0
  73. package/dist/values-DKpOCD5J.cjs.js.map +1 -0
  74. package/package.json +72 -27
  75. package/persist.d.ts +1 -0
  76. package/persist.js +1 -0
  77. package/resolvers/standard-schema.d.ts +1 -0
  78. package/resolvers/standard-schema.js +1 -0
  79. package/resolvers/yup.d.ts +1 -0
  80. package/resolvers/yup.js +1 -0
  81. package/resolvers/zod.d.ts +1 -0
  82. package/resolvers/zod.js +1 -0
  83. package/server.d.ts +1 -0
  84. package/server.js +1 -0
  85. package/dist/errors-BKrUdpfI.cjs.js +0 -2
  86. package/dist/errors-BKrUdpfI.cjs.js.map +0 -1
  87. package/dist/errors-CrQBddrJ.mjs +0 -2
  88. package/dist/errors-CrQBddrJ.mjs.map +0 -1
  89. package/dist/form-CeKSBs31.d.ts +0 -486
  90. package/dist/validate-CNtuUhmk.mjs +0 -2
  91. package/dist/validate-CNtuUhmk.mjs.map +0 -1
  92. package/dist/validate-Cl4ksNFu.cjs.js +0 -2
  93. package/dist/validate-Cl4ksNFu.cjs.js.map +0 -1
  94. package/dist/validate-nksgv1pR.d.ts +0 -272
  95. package/dist/values-Cu6awQOJ.cjs.js +0 -2
  96. package/dist/values-Cu6awQOJ.cjs.js.map +0 -1
  97. package/dist/values-DRY-a32G.mjs +0 -2
  98. package/dist/values-DRY-a32G.mjs.map +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-f0rm",
3
- "version": "1.3.0",
3
+ "version": "1.4.0",
4
4
  "packageManager": "pnpm@11.4.0",
5
5
  "description": "react form",
6
6
  "main": "dist/index.cjs.js",
@@ -8,51 +8,93 @@
8
8
  "unpkg": "dist/index.umd.min.js",
9
9
  "exports": {
10
10
  ".": {
11
- "types": "./dist/index.d.ts",
12
- "import": "./dist/index.mjs",
13
- "require": "./dist/index.cjs.js"
11
+ "import": {
12
+ "types": "./dist/index.d.mts",
13
+ "default": "./dist/index.mjs"
14
+ },
15
+ "require": {
16
+ "types": "./dist/index.d.cts",
17
+ "default": "./dist/index.cjs.js"
18
+ }
14
19
  },
15
20
  "./resolvers/standard-schema": {
16
- "types": "./dist/resolvers/standard-schema.d.ts",
17
- "import": "./dist/resolvers/standard-schema.mjs",
18
- "require": "./dist/resolvers/standard-schema.cjs.js"
21
+ "import": {
22
+ "types": "./dist/resolvers/standard-schema.d.mts",
23
+ "default": "./dist/resolvers/standard-schema.mjs"
24
+ },
25
+ "require": {
26
+ "types": "./dist/resolvers/standard-schema.d.cts",
27
+ "default": "./dist/resolvers/standard-schema.cjs.js"
28
+ }
19
29
  },
20
30
  "./resolvers/zod": {
21
- "types": "./dist/resolvers/zod.d.ts",
22
- "import": "./dist/resolvers/zod.mjs",
23
- "require": "./dist/resolvers/zod.cjs.js"
31
+ "import": {
32
+ "types": "./dist/resolvers/zod.d.mts",
33
+ "default": "./dist/resolvers/zod.mjs"
34
+ },
35
+ "require": {
36
+ "types": "./dist/resolvers/zod.d.cts",
37
+ "default": "./dist/resolvers/zod.cjs.js"
38
+ }
24
39
  },
25
40
  "./resolvers/yup": {
26
- "types": "./dist/resolvers/yup.d.ts",
27
- "import": "./dist/resolvers/yup.mjs",
28
- "require": "./dist/resolvers/yup.cjs.js"
41
+ "import": {
42
+ "types": "./dist/resolvers/yup.d.mts",
43
+ "default": "./dist/resolvers/yup.mjs"
44
+ },
45
+ "require": {
46
+ "types": "./dist/resolvers/yup.d.cts",
47
+ "default": "./dist/resolvers/yup.cjs.js"
48
+ }
29
49
  },
30
50
  "./devtools": {
31
- "types": "./dist/devtools/index.d.ts",
32
- "import": "./dist/devtools/index.mjs",
33
- "require": "./dist/devtools/index.cjs.js"
51
+ "import": {
52
+ "types": "./dist/devtools/index.d.mts",
53
+ "default": "./dist/devtools/index.mjs"
54
+ },
55
+ "require": {
56
+ "types": "./dist/devtools/index.d.cts",
57
+ "default": "./dist/devtools/index.cjs.js"
58
+ }
34
59
  },
35
60
  "./server": {
36
- "types": "./dist/server/index.d.ts",
37
- "import": "./dist/server/index.mjs",
38
- "require": "./dist/server/index.cjs.js"
61
+ "import": {
62
+ "types": "./dist/server/index.d.mts",
63
+ "default": "./dist/server/index.mjs"
64
+ },
65
+ "require": {
66
+ "types": "./dist/server/index.d.cts",
67
+ "default": "./dist/server/index.cjs.js"
68
+ }
39
69
  },
40
70
  "./persist": {
41
- "types": "./dist/persist.d.ts",
42
- "import": "./dist/persist.mjs",
43
- "require": "./dist/persist.cjs.js"
71
+ "import": {
72
+ "types": "./dist/persist.d.mts",
73
+ "default": "./dist/persist.mjs"
74
+ },
75
+ "require": {
76
+ "types": "./dist/persist.d.cts",
77
+ "default": "./dist/persist.cjs.js"
78
+ }
44
79
  }
45
80
  },
46
81
  "types": "dist/index.d.ts",
47
82
  "files": [
48
- "dist"
83
+ "dist",
84
+ "server.js",
85
+ "server.d.ts",
86
+ "devtools.js",
87
+ "devtools.d.ts",
88
+ "persist.js",
89
+ "persist.d.ts",
90
+ "resolvers"
49
91
  ],
50
92
  "sideEffects": false,
51
93
  "scripts": {
52
94
  "prepare": "husky",
53
95
  "start": "vitest --watch",
54
96
  "commit": "lint-staged && git-cz -n",
55
- "build": "npm run clean && cross-env NODE_ENV=production rollup -c",
97
+ "build": "npm run clean && cross-env NODE_ENV=production rollup -c && node scripts/postbuild.mjs",
56
98
  "prepublishOnly": "rimraf dist && npm run build",
57
99
  "coverage": "vitest run --coverage",
58
100
  "test": "vitest run",
@@ -64,6 +106,7 @@
64
106
  "storybook": "storybook dev -p 6006",
65
107
  "build-storybook": "storybook build",
66
108
  "size": "size-limit",
109
+ "bench:report": "vitest bench --run --reporter=json --outputFile=bench-results.json test/bench/ && node scripts/bench-report.mjs",
67
110
  "docs:build": "cd docs-site && npm run build",
68
111
  "docs:deploy": "cd docs-site && npm run deploy"
69
112
  },
@@ -107,6 +150,7 @@
107
150
  }
108
151
  },
109
152
  "devDependencies": {
153
+ "@arethetypeswrong/cli": "^0.18.5",
110
154
  "@babel/core": "^8.0.1",
111
155
  "@babel/preset-env": "^8.0.2",
112
156
  "@babel/preset-react": "^8.0.1",
@@ -149,6 +193,7 @@
149
193
  "eslint-plugin-jsx-a11y": "^6.10.2",
150
194
  "eslint-plugin-prettier": "^5.5.6",
151
195
  "eslint-plugin-react": "^7.37.5",
196
+ "eslint-plugin-react-compiler": "19.1.0-rc.2",
152
197
  "eslint-plugin-react-hooks": "^7.1.1",
153
198
  "eslint-plugin-storybook": "^10.6.0",
154
199
  "globals": "^17.12.0",
@@ -171,14 +216,14 @@
171
216
  "size-limit": [
172
217
  {
173
218
  "path": "dist/index.mjs",
174
- "limit": "12 KB",
219
+ "limit": "13.1 KB",
175
220
  "ignore": [
176
221
  "@for-fun/event-emitter"
177
222
  ]
178
223
  },
179
224
  {
180
225
  "path": "dist/index.mjs",
181
- "limit": "12.5 KB",
226
+ "limit": "14.6 KB",
182
227
  "gzip": true,
183
228
  "ignore": [
184
229
  "@for-fun/event-emitter"
@@ -206,7 +251,7 @@
206
251
  },
207
252
  {
208
253
  "path": "dist/server/index.mjs",
209
- "limit": "5 KB",
254
+ "limit": "7.5 KB",
210
255
  "gzip": true
211
256
  },
212
257
  {
package/persist.d.ts ADDED
@@ -0,0 +1 @@
1
+ export * from './dist/persist';
package/persist.js ADDED
@@ -0,0 +1 @@
1
+ module.exports = require('./dist/persist.cjs.js');
@@ -0,0 +1 @@
1
+ export * from '../dist/resolvers/standard-schema';
@@ -0,0 +1 @@
1
+ module.exports = require('../dist/resolvers/standard-schema.cjs.js');
@@ -0,0 +1 @@
1
+ export * from '../dist/resolvers/yup';
@@ -0,0 +1 @@
1
+ module.exports = require('../dist/resolvers/yup.cjs.js');
@@ -0,0 +1 @@
1
+ export * from '../dist/resolvers/zod';
@@ -0,0 +1 @@
1
+ module.exports = require('../dist/resolvers/zod.cjs.js');
package/server.d.ts ADDED
@@ -0,0 +1 @@
1
+ export * from './dist/server/index';
package/server.js ADDED
@@ -0,0 +1 @@
1
+ module.exports = require('./dist/server/index.cjs.js');
@@ -1,2 +0,0 @@
1
- "use strict";var e=require("@for-fun/event-emitter");const t=new Map;function r(e){if(Array.isArray(e))return e;const r=t.get(e);if(r)return r;const o=function(e){const t=[];let r="";const o=()=>{if(n(r)){const n=[...t.map(String),r].join("."),o=t.reduce((e,t)=>e+("number"==typeof t?`[${t}]`:`${e?".":""}${t}`),"");throw new TypeError(`Numeric path segment must use bracket notation: "${n}" → "${o}[${r}]" (path: ${e})`)}t.push(r),r=""};for(let s=0;s<e.length;s++){const i=e[s];if("."===i)""!==r&&o();else if("["===i){""!==r&&o();const i=e[s+1];if('"'===i||"'"===i){const r=e.indexOf(i,s+2);if(-1===r)throw new TypeError(`Unterminated quote in path: ${e}`);if("]"!==e[r+1])throw new TypeError(`Expected "]" after quoted segment in path: ${e}`);t.push(e.slice(s+2,r)),s=r+1}else{const r=e.indexOf("]",s+1);if(-1===r)throw new TypeError(`Unterminated bracket in path: ${e}`);const o=e.slice(s+1,r);t.push(n(o)?Number(o):o),s=r}}else r+=i}""===r&&0!==t.length||o();return t}(e);if(t.size>=1e4){const e=t.keys().next();e.done||t.delete(e.value)}return t.set(e,o),o}const n=e=>/^-?\d+$/.test(e);function o(e,t){return t.reduce((e,t)=>{if(null!=e)return e[t]},e)}function s(e,t,r){if(!t.length)return r;const[o,...i]=t,u="number"==typeof o?o:Array.isArray(e)&&"string"==typeof o&&n(o)?Number(o):void 0;if(void 0!==u){const t=Array.isArray(e)?e.slice():[];return t[u]=s(t[u],i,r),t}return{...e,[o]:s(e&&e[o],i,r)}}function i(e){const t=r(e);return{value:t,key:JSON.stringify(t)}}const u=new WeakMap;function c(e){const t=u.get(e);t&&t.version++}const f=new WeakMap;const a=new WeakMap;function p(e){return!!e&&"object"==typeof e&&"string"==typeof e.type&&"string"==typeof e.message}const l=Symbol("validation-outcome");exports.FORM_ERROR="_form",exports.VALIDATION_OUTCOME=l,exports.bumpDirtyVersion=function(e){const t=a.get(e);t&&t.version++},exports.bumpValuesVersion=c,exports.clearDirtyBaselines=function(e,t){const r=f.get(e);r&&r.clear()},exports.clearErrors=function(t,r){const{emitter:n,errors:o}=t;return o.clear(),void e.emit(n,"errors")},exports.create=i,exports.dirtyFieldsCaches=a,exports.get=o,exports.getDirtyBaseline=function(e,t,r){const n=f.get(e);return n?.has(t)?n.get(t):o(e.initialValues,r)},exports.getErrors=function({errors:e}){const t=[];for(const[r,n]of e){const e=JSON.parse(r).join(".");for(const{type:r,message:o}of n)t.push({path:e,type:r,message:o})}return t},exports.hasErrors=function({errors:e}){return e.size>0},exports.isEqual=function e(t,r){if(Object.is(t,r))return!0;if(t instanceof Date&&r instanceof Date)return t.getTime()===r.getTime();if(!t||!r||"object"!=typeof t||"object"!=typeof r)return!1;const n=Array.isArray(t);if(n!==Array.isArray(r))return!1;if(n){if(t.length!==r.length)return!1;for(let n=0;n<t.length;n++)if(!e(t[n],r[n]))return!1;return!0}const o=Object.getPrototypeOf(t);if(o!==Object.prototype&&null!==o)return!1;if(Object.getPrototypeOf(r)!==o)return!1;const s=Object.keys(t),i=Object.keys(r);if(s.length!==i.length)return!1;for(const n of s)if(!e(t[n],r[n]))return!1;return!0},exports.isFieldError=p,exports.isIndex=n,exports.isPromise=function(e){return e&&"function"==typeof e.then},exports.normalizePath=r,exports.pruneDirtyBaselines=function(e,{key:t}){const r=f.get(e);if(!r?.size)return;const n=`${t.slice(0,-1)},`;for(const e of r.keys())e.startsWith(n)&&r.delete(e)},exports.setError=function(t,r,n,o){!function(t,r,n){const{emitter:o,errors:s}=t,i=function(e){if("string"==typeof e)return e?[{type:"custom",message:e}]:void 0;if(p(e))return[e];if(!e)return;const t=[];return e.forEach(e=>{"string"==typeof e&&e?t.push({type:"custom",message:e}):p(e)&&t.push(e)}),t.length?t:void 0}(n);i?s.set(r.key,i):s.delete(r.key);e.emit(o,"errors",r)}(t,i(r),n)},exports.setOwned=function(e,t,r,o){if(!t.length)return r;let s=e,i=null,u="";for(let c=0;c<t.length;c++){const f=t[c];if(!o.has(s)){let t;t="number"==typeof f||Array.isArray(s)&&"string"==typeof f&&n(f)?Array.isArray(s)?s.slice():[]:{...s},o.add(t),0===c?e=t:i[u]=t,s=t}c===t.length-1?s[f]=r:(i=s,u=f,s=s[f])}return e},exports.setParsedValues=function(t,r){void 0!==r&&r!==t.parsedValues&&(t.parsedValues=r,c(t),e.emit(t.emitter,"change"))},exports.unset=function e(t,r){if(!r.length||null==t)return t;const[n,...o]=r;if(o.length){const r=e(t[n],o);return r===t[n]?t:s(t,[n],r)}if(Array.isArray(t)){if(!(n in t))return t;const e=t.slice();return delete e[n],e}if("object"!=typeof t||!(n in t))return t;const i={...t};return delete i[n],i},exports.valuesCaches=u,exports.waitUntil=function(t,r,n,o){return new Promise((s,i)=>{if(o())return void i();if(n())return void s();const u=e.on(t,r,()=>{if(o())return u(),void i();n()&&(u(),s())})})};
2
- //# sourceMappingURL=errors-BKrUdpfI.cjs.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"errors-BKrUdpfI.cjs.js","sources":["../src/util.ts","../src/path.ts","../src/core/internals.ts","../src/core/errors.ts"],"sourcesContent":["import {on} from './emitter';\nimport type {EventEmitter} from './emitter';\n\n/** FIFO bound for {@link pathCache}. Static field names ('user.email')\n * number in the dozens per app, so the cache barely grows in practice;\n * the cap is only a backstop for dynamic keys ('items[' + id + ']'\n * style — array inputs skip the cache entirely), where long-lived forms\n * would otherwise accumulate entries forever. Map preserves insertion\n * order, so eviction drops the oldest entry; a dropped string only\n * costs a re-parse the next time normalizePath sees it — results are\n * deterministic, so eviction affects performance, never behavior. */\nconst PATH_CACHE_LIMIT = 1e4;\n\nconst pathCache = new Map<string, (string | number)[]>();\n\n/** Test-only view of the path cache size. Not re-exported from the\n * package entry — tests import this module directly to assert the\n * FIFO bound above. */\nexport const pathCacheSize = () => pathCache.size;\n\nexport function normalizePath(\n path: string | (string | number)[]\n): (string | number)[] {\n if (Array.isArray(path)) return path;\n const cached = pathCache.get(path);\n if (cached) return cached;\n const value = parsePath(path);\n if (pathCache.size >= PATH_CACHE_LIMIT) {\n // Insertion order is FIFO order; the cache is non-empty here\n // because size >= 1e4.\n const oldest = pathCache.keys().next();\n if (!oldest.done) pathCache.delete(oldest.value);\n }\n pathCache.set(path, value);\n return value;\n}\n\n/** Does a segment string denote an integer array index (optionally\n * negative)? The parser feeds it bracket contents ('items[0]' → number)\n * and rejects dotted numerics outright ('items.0' throws), so parsed\n * paths never carry index-looking strings. Its remaining duty is\n * defending programmatic segments: normalizePath also accepts raw\n * (string | number)[] arrays, and index-shaped strings can still arrive\n * from internal callers (error-tree keys) or array containers met\n * during set/setOwned walks. */\nexport const isIndex = (segment: string) => /^-?\\d+$/.test(segment);\n\nfunction parsePath(path: string): (string | number)[] {\n const result: (string | number)[] = [];\n let identifier = '';\n const flushIdentifier = () => {\n if (isIndex(identifier)) {\n // Rebuild both spellings for an actionable message: the dotted\n // form the caller wrote vs. the bracket form the parser accepts.\n const dotted = [...result.map(String), identifier].join('.');\n const bracket = result.reduce(\n (acc: string, seg: string | number) =>\n acc +\n (typeof seg === 'number' ? `[${seg}]` : `${acc ? '.' : ''}${seg}`),\n ''\n );\n throw new TypeError(\n `Numeric path segment must use bracket notation: \"${dotted}\" → \"${bracket}[${identifier}]\" (path: ${path})`\n );\n }\n result.push(identifier);\n identifier = '';\n };\n\n for (let i = 0; i < path.length; i++) {\n const char = path[i];\n if (char === '.') {\n if (identifier !== '') flushIdentifier();\n } else if (char === '[') {\n if (identifier !== '') flushIdentifier();\n const quote = path[i + 1];\n if (quote === '\"' || quote === \"'\") {\n const close = path.indexOf(quote, i + 2);\n if (close === -1) {\n throw new TypeError(`Unterminated quote in path: ${path}`);\n }\n if (path[close + 1] !== ']') {\n throw new TypeError(\n `Expected \"]\" after quoted segment in path: ${path}`\n );\n }\n result.push(path.slice(i + 2, close));\n i = close + 1;\n } else {\n const close = path.indexOf(']', i + 1);\n if (close === -1) {\n throw new TypeError(`Unterminated bracket in path: ${path}`);\n }\n const content = path.slice(i + 1, close);\n result.push(isIndex(content) ? Number(content) : content);\n i = close;\n }\n } else {\n identifier += char;\n }\n }\n if (identifier !== '' || result.length === 0) flushIdentifier();\n return result;\n}\n\nexport function get(values: any, path: (string | number)[]): any {\n return path.reduce((current: any, p: string | number) => {\n if (current == null) return undefined;\n return current[p];\n }, values);\n}\n\n/**\n * Immutable counterpart of {@link set}: removes the path from the value\n * tree, copying only along the touched branch (untouched branches stay\n * shared with the source, like set). Deletes the key entirely rather than\n * writing undefined, so the result carries no `a: undefined` entries.\n */\nexport function unset(values: any, path: (string | number)[]): any {\n if (!path.length || values == null) return values;\n const [prop, ...props] = path;\n if (props.length) {\n const next = unset(values[prop], props);\n // Reattach the pruned child at its parent key — NOT at the full path,\n // which would write the pruned subtree back under the removed key.\n return next === values[prop] ? values : set(values, [prop], next);\n }\n if (Array.isArray(values)) {\n if (!(prop in values)) return values;\n const arr = values.slice();\n delete arr[prop as number];\n return arr;\n }\n if (typeof values !== 'object' || !(prop in values)) return values;\n const copy = {...values};\n delete copy[prop as string];\n return copy;\n}\n\nexport function set(values: any, path: (string | number)[], value: any): any {\n if (!path.length) return value;\n\n const [prop, ...props] = path;\n // A numeric segment lands with the array copy rule — numbers, and the\n // string form dotted paths parse to ('a.0'), on an array container: an\n // object spread there would corrupt the array into {'0': ...}.\n const index =\n typeof prop === 'number'\n ? prop\n : Array.isArray(values) && typeof prop === 'string' && isIndex(prop)\n ? Number(prop)\n : undefined;\n if (index !== undefined) {\n const arr = Array.isArray(values) ? values.slice() : [];\n arr[index] = set(arr[index], props, value);\n return arr;\n }\n return {...values, [prop]: set(values && values[prop], props, value)};\n}\n\n/**\n * Ownership-tracked {@link set}: merge many paths into one tree without\n * re-copying containers the merge itself already created.\n *\n * Containers present in `owned` (freshly created by an earlier call of the\n * same merge) are mutated in place; every other container -- nodes borrowed\n * from the seed tree and user leaf values -- is copied first with the exact\n * copy rules `set` applies (numeric prop: array slice, or a fresh array\n * when the node is not one; string prop: object spread). Chaining\n * `setOwned` over a list of paths therefore produces the tree chaining\n * `set` would, in the same insertion order, but allocates each distinct\n * container once (O(distinct path prefixes)) instead of re-copying the\n * whole branch for every path (O(paths x depth)).\n *\n * Use a fresh `owned` set per merge and thread the returned root (a copied\n * replacement when the seed root itself had to be copied) into the next\n * call. Borrowed containers are never mutated.\n */\nexport function setOwned(\n root: any,\n path: (string | number)[],\n value: any,\n owned: Set<object>\n): any {\n if (!path.length) return value;\n let container = root;\n let parent: any = null;\n let parentProp: string | number = '';\n for (let i = 0; i < path.length; i++) {\n const prop = path[i];\n if (!owned.has(container)) {\n let copy: any;\n if (\n typeof prop === 'number' ||\n (Array.isArray(container) && typeof prop === 'string' && isIndex(prop))\n ) {\n copy = Array.isArray(container) ? container.slice() : [];\n } else {\n copy = {...container};\n }\n owned.add(copy);\n if (i === 0) root = copy;\n else parent[parentProp] = copy;\n container = copy;\n }\n if (i === path.length - 1) {\n container[prop] = value;\n } else {\n parent = container;\n parentProp = prop;\n container = container[prop];\n }\n }\n return root;\n}\n\nexport function isEmpty(value: any): boolean {\n if (value == null) return true;\n if (typeof value !== 'object') return false;\n\n const values = Object.values(value);\n return values.length === 0 || values.every(isEmpty);\n}\n\nexport function isPromise(value: any): value is Promise<any> {\n return value && typeof value.then === 'function';\n}\n\n/** Structural equality for form default data (primitives, arrays, plain\n * objects, Dates). Class instances and other exotic objects compare as\n * unequal, which errs on the side of re-seeding when {@link\n * setInitialValues} uses it to tell a re-rendered inline literal from\n * genuinely changed content. */\nexport function isEqual(a: any, b: any): boolean {\n if (Object.is(a, b)) return true;\n if (a instanceof Date && b instanceof Date)\n return a.getTime() === b.getTime();\n if (!a || !b || typeof a !== 'object' || typeof b !== 'object') return false;\n const isArray = Array.isArray(a);\n if (isArray !== Array.isArray(b)) return false;\n if (isArray) {\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n if (!isEqual(a[i], b[i])) return false;\n }\n return true;\n }\n const proto = Object.getPrototypeOf(a);\n if (proto !== Object.prototype && proto !== null) return false;\n if (Object.getPrototypeOf(b) !== proto) return false;\n const keysA = Object.keys(a);\n const keysB = Object.keys(b);\n if (keysA.length !== keysB.length) return false;\n for (const key of keysA) {\n if (!isEqual(a[key], b[key])) return false;\n }\n return true;\n}\n\nexport function waitUntil(\n emitter: EventEmitter<any>,\n event: string,\n isResolve: () => boolean,\n isReject: () => boolean\n): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n if (isReject()) return void reject();\n if (isResolve()) return void resolve();\n\n const off = on(emitter, event as any, () => {\n if (isReject()) {\n off();\n reject();\n return;\n }\n // Condition not reached yet — stay subscribed and keep waiting. (The\n // previous `if (isResolve()) return` was inverted: it hung forever\n // once the condition held and resolved prematurely while it didn't.)\n if (!isResolve()) return;\n off();\n resolve();\n });\n });\n}\n\n/**\n * DEV-only snapshot guard for {@link getValues}: deep-clones and freezes\n * plain objects and arrays so a consumer mutating the returned tree throws\n * immediately instead of silently corrupting the shared memoized result\n * (getValues hands the same cached reference to every reader between\n * writes). Non-plain values (Date, File, Blob, class instances, Map/Set)\n * pass through by reference, unfrozen — cloning would strip their\n * prototypes and freezing would break legitimate methods like\n * Date#setHours. Callers gate the call behind `__DEV__` so production\n * builds pay nothing.\n */\nexport function freezeValues(value: any): any {\n if (value === null || typeof value !== 'object') return value;\n if (Array.isArray(value)) {\n return Object.freeze(value.map(freezeValues));\n }\n if (Object.getPrototypeOf(value) !== Object.prototype) return value;\n const clone: Record<string, any> = {};\n for (const key of Object.keys(value)) clone[key] = freezeValues(value[key]);\n return Object.freeze(clone);\n}\n","import {normalizePath} from './util';\n\nexport type PathSegments = (string | number)[];\nexport type Name = string | PathSegments;\nexport type Path = {value: PathSegments; key: string};\n\nexport default function create(name: Name): Path {\n const value = normalizePath(name);\n return {value, key: JSON.stringify(value)};\n}\n","import {emit} from '../emitter';\nimport {get} from '../util';\nimport type {Name, Path, PathSegments} from '../path';\nimport type {FieldError, Form} from '../form';\n\n/** Per-form memoization of {@link getValues}, the same version-bump/read\n * pattern {@link dirtyFieldsCaches} gives {@link getDirtyFields}. */\ntype ValuesCache = {version: number; result: any};\n\nexport const valuesCaches = new WeakMap<Form, ValuesCache>();\n\n/**\n * Invalidate `form`'s cached {@link getValues} result. Called at every\n * point that can change values, parsedValues or initialValues\n * (setValueByPath, removeFieldByPath, setInitialValues, reset, resetField,\n * setParsedValues) so repeated reads hand back a stable reference until\n * the next write.\n */\nexport function bumpValuesVersion(form: Form): void {\n const cache = valuesCaches.get(form);\n if (cache) cache.version++;\n}\n\n/**\n * Get form values: the values Map layered over parsedValues (when a schema\n * validation produced them) layered over initialValues.\n *\n * Merged with copy-on-write ownership tracking ({@link setOwned}): every\n * distinct container on a written path is allocated once and shared by all\n * paths through it, instead of re-copying the whole branch for every key.\n * One owned set spans the whole merge, so containers borrowed from the\n * parsedValues tree are copied before mutation exactly like initialValues\n * ones. The result is a freshly merged tree per mutation, with untouched\n * branches sharing references with the baseline exactly like chained\n * `set` did.\n *\n * Memoized per form like {@link getDirtyFields}: every value write bumps a\n * `version` counter ({@link bumpValuesVersion}) while reads reset it, so\n * consecutive reads hand back the same reference (submit, changeValue and\n * form-level validate all read the whole tree, often several times per\n * interaction). Treat the result as read-only — the next read after a\n * write returns a fresh tree, but between writes the cached one is shared\n * with every other reader.\n *\n * parsedValues is the schema's complete output tree: once validation\n * succeeds it replaces the initialValues baseline (fields the schema\n * dropped disappear), while live edits in the values Map still win over\n * both. It never affects dirty state — {@link isDirty} and\n * {@link getDirtyFields} compare live edits against initialValues only,\n * because parsing is not a user edit.\n *\n * @param form\n */\n/** Per-path dirty-comparison baselines installed by writes with\n * `shouldDirty: false`: the written value becomes that field's baseline —\n * the write reads as a commit, not an edit. Module-private (like\n * {@link dirtyFieldsCaches}) so the Form shape is untouched for forms that\n * never opt in. */\nconst dirtyBaselines = new WeakMap<Form, Map<string, any>>();\n\n/** The value a field's dirtiness is measured against: its committed\n * baseline when one exists, initialValues at the path otherwise. */\nexport function getDirtyBaseline(\n form: Form,\n key: string,\n segments: PathSegments\n): any {\n const baselines = dirtyBaselines.get(form);\n if (baselines?.has(key)) return baselines.get(key);\n return get(form.initialValues, segments);\n}\n\n/** Install a committed baseline for a `shouldDirty: false` write: the\n * field reads clean until a later write diverges from the new baseline. */\nexport function setDirtyBaseline(form: Form, {key}: Path, value: any): void {\n let baselines = dirtyBaselines.get(form);\n if (!baselines) {\n baselines = new Map();\n dirtyBaselines.set(form, baselines);\n }\n baselines.set(key, value);\n}\n\n/** A wholesale write at a path replaces the subtree below it, so baselines\n * committed under the branch die with the data they were committed against\n * (array movers rewrite the parent path, re-aligning row indices). Called\n * from every write — a no-op unless the form ever opted in. */\nexport function pruneDirtyBaselines(form: Form, {key}: Path): void {\n const baselines = dirtyBaselines.get(form);\n if (!baselines?.size) return;\n const stem = `${key.slice(0, -1)},`;\n for (const baselineKey of baselines.keys()) {\n if (baselineKey.startsWith(stem)) baselines.delete(baselineKey);\n }\n}\n\n/** Drop committed baselines at one path ({@link removeFieldByPath} /\n * {@link resetField}) or all of them ({@link setInitialValues} /\n * {@link reset}) — the state they were measured against is gone. */\nexport function clearDirtyBaselines(form: Form, key?: string): void {\n const baselines = dirtyBaselines.get(form);\n if (!baselines) return;\n if (key === undefined) baselines.clear();\n else baselines.delete(key);\n}\n\n/** Per-form memoization of {@link getDirtyFields}. `version` counts value\n * mutations since the cached `result` was computed: bump points increment\n * it, reads reset it, so a non-zero version means the cache is stale. */\ntype DirtyFieldsCache = {version: number; result: Record<string, boolean>};\n\nexport const dirtyFieldsCaches = new WeakMap<Form, DirtyFieldsCache>();\n\n/**\n * Invalidate `form`'s cached {@link getDirtyFields} result. Called at every\n * point that can change values or initialValues (setValueByPath,\n * removeFieldByPath, setInitialValues, reset) so repeated reads hand out a\n * stable reference and useWatch's Object.is snapshot check can skip\n * re-renders.\n */\nexport function bumpDirtyVersion(form: Form): void {\n const cache = dirtyFieldsCaches.get(form);\n if (cache) cache.version++;\n}\n/** Numbers only occur inside a segments path (`['a', 0]`), never as\n * standalone names, so a top-level number marks `name` as one single path\n * rather than a list of names. */\nexport function isSegmentsPath(\n name: PathSegments | Name[]\n): name is PathSegments {\n return (name as (number | unknown)[]).some(part => typeof part === 'number');\n}\n\nexport function isFieldError(value: any): value is FieldError {\n return (\n !!value &&\n typeof value === 'object' &&\n typeof value.type === 'string' &&\n typeof value.message === 'string'\n );\n}\n\n/**\n * Flatten a form-level validate result and write each leaf error through\n * setError. Nested objects descend into deeper paths ({a: {b: 'msg'}} sets\n * the 'a.b' error), array values contribute every non-empty string they\n * hold as separate errors (zod flatten() formErrors style), and\n * FieldError-shaped objects are stored as-is. Falsy values are skipped.\n *\n * When `footprint` is passed (validateDeps forms only), every leaf this\n * round actually stored is recorded into it — the exact stored array —\n * so the next round can drop exactly what this one wrote.\n/** Store a schema validator's parsed output as the getValues baseline\n * layer above initialValues. Payload-less 'change' notifies value\n * watchers (useValue, useDirtyFields, ...); dirty state is untouched —\n * it only compares live edits against initialValues, and parsing is not\n * an edit. */\nexport function setParsedValues(form: Form, values: any): void {\n if (values === undefined || values === form.parsedValues) return;\n form.parsedValues = values;\n // parsedValues is a getValues layer above initialValues, so a new parse\n // invalidates the cached merge (dirty state is untouched — parsing is\n // not an edit, hence no bumpDirtyVersion here).\n bumpValuesVersion(form);\n emit(form.emitter, 'change');\n}\n\n/**\n * Land a form-level validate result. A plain record keeps the\n * long-standing behavior — flattened into field errors by\n * {@link setFormErrors}. A branded {@link ValidationOutcome} splits\n * instead: `errors` flattens exactly like a plain record, and `values`\n * (the schema's parsed output — coerced/transformed values included)\n * becomes the form's parsedValues baseline. Falsy results are skipped,\n * branded or not.\n *\n * Forms that opted into `validateDeps` additionally get round-scoped\n * error ownership: before the new result lands, the errors the previous\n * round wrote are dropped ({@link clearFormValidateErrors}), so a re-run\n * that passes makes the cross-field error disappear — and the new\n * round's own writes become the tracked footprint. Forms without the\n * option keep the historical write-only behavior untouched.\n */\n","import {emit} from '../emitter';\nimport createPath from '../path';\nimport type {Name, Path, PathSegments} from '../path';\nimport type {FieldPath} from '../types';\nimport type {FieldError, FieldErrorEntry, Form} from '../form';\nimport {isFieldError, isSegmentsPath} from './internals';\n\n/** Reserved top-level path segment for form-level errors. The Standard\n * Schema form-level adapter lands path-less issues under this key; the\n * exported constant replaces the magic string, and readers consume it via\n * getError(form, FORM_ERROR) / getFieldErrors(form, FORM_ERROR). */\nexport const FORM_ERROR = '_form';\n\n/** When a field is validated:\n * - `'onSubmit'` (default): only on submit\n * - `'onBlur'`: when the field loses focus\n * - `'onChange'`: on every change\n * - `'onTouched'`: on first blur, then on every change\n * - `'all'`: on both change and blur\n */\n/** Brand marking a form-level validate result as a structured\n * {@link ValidationOutcome} (parsed values and/or errors) rather than a\n * plain nested error record. Symbols cannot collide with user error\n * records, so detection is an exact `VALIDATION_OUTCOME in result`. */\nexport const VALIDATION_OUTCOME: unique symbol = Symbol('validation-outcome');\n\n/** Structured form-level validate result: `errors` uses the same nested\n * shape a plain error record uses, `values` is the schema's parsed output\n * (coerce/transform results included). Either side may be omitted. */\n/**\n * Get field error\n * @param form\n * @param name\n * @return FieldError object or undefined\n */\nexport function getError<\n T extends Record<string, any> = any,\n P extends FieldPath<T> | PathSegments = FieldPath<T> | PathSegments\n>(form: Form<T>, name: P): FieldError | undefined {\n return getErrorByPath(form, createPath(name));\n}\n\n/**\n * Get field error by path\n * @param form\n * @param path\n * @return first FieldError of the field, or undefined\n */\nexport function getErrorByPath(\n {errors}: Form,\n path: Path\n): FieldError | undefined {\n return errors.get(path.key)?.[0];\n}\n\n/** Shared empty result for {@link getFieldErrorsByPath}: a fresh `[]` per\n * call would allocate on the hot no-error path, and the stored arrays are\n * handed out by reference too, so callers must treat results as read-only. */\nconst NO_ERRORS: FieldError[] = [];\n\n/**\n * Get all errors of a field\n * @param form\n * @param name\n * @return every error registered for the field (insertion order); an empty\n * array when the field has none\n */\nexport function getFieldErrors<\n T extends Record<string, any> = any,\n P extends FieldPath<T> | PathSegments = FieldPath<T> | PathSegments\n>(form: Form<T>, name: P): FieldError[] {\n return getFieldErrorsByPath(form, createPath(name));\n}\n\n/**\n * Get all errors of a field by path\n * @param form\n * @param path\n * @return every error registered for the field (insertion order); an empty\n * array when the field has none\n */\nexport function getFieldErrorsByPath({errors}: Form, path: Path): FieldError[] {\n return errors.get(path.key) ?? NO_ERRORS;\n}\n\n/**\n * Get all errors\n * @param form\n * @return array of {path, type, message} entries, in insertion order; path\n * is the user-facing dotted field path ('a.b', 'list.0'), and a\n * field holding several errors contributes one entry per error\n */\nexport function getErrors({errors}: Form): FieldErrorEntry[] {\n const entries: FieldErrorEntry[] = [];\n for (const [key, list] of errors) {\n const path = (JSON.parse(key) as PathSegments).join('.');\n for (const {type, message} of list) entries.push({path, type, message});\n }\n return entries;\n}\n\n/**\n * Get first error message\n * @param form\n * @return first error's message string, or undefined when there are no errors\n */\nexport function getFirstError({errors}: Form): string | undefined {\n return errors.values().next().value?.[0]?.message;\n}\n\n/** Snapshot of one field's aggregated state, as {@link getFieldState}\n * returns it. `errors` is the stored array shared with the form — treat it\n * as read-only, like every {@link getFieldErrors} result. */\n/** Options accepted by {@link setError}. */\nexport type SetErrorOptions = {\n /**\n * Focus the named field's element after the error lands (react-hook-form's\n * `setError` `shouldFocus`). Rides the same 'focusError' channel\n * `setFocus` and a failed submit's auto-focus use: only mounted bound\n * fields react, unmounted ones are silent no-ops.\n */\n shouldFocus?: boolean;\n};\n\n/**\n * Set field error\n * @param form\n * @param name\n * @param error string is normalized to {type: 'custom', message}; a\n * FieldError object is stored as-is; an array holds several errors\n * (falsy items dropped, strings normalized); undefined clears\n * @param options {@link SetErrorOptions} — `shouldFocus` focuses the field\n * after the error lands\n */\nexport function setError<\n T extends Record<string, any> = any,\n P extends FieldPath<T> | PathSegments = FieldPath<T> | PathSegments\n>(\n form: Form<T>,\n name: P,\n error: string | FieldError | (string | FieldError)[] | undefined,\n options?: SetErrorOptions\n): void {\n setErrorByPath(form, createPath(name), error, options);\n}\n\n/**\n * Set field error\n * @param form\n * @param path\n * @param error string is normalized to {type: 'custom', message}; a\n * FieldError object is stored as-is; an array holds several errors\n * (falsy items dropped, strings normalized); undefined clears\n * @param options {@link SetErrorOptions} — `shouldFocus` focuses the field\n * after the error lands\n */\nexport function setErrorByPath(\n form: Form,\n path: Path,\n error: string | FieldError | (string | FieldError)[] | undefined,\n options?: SetErrorOptions\n): void {\n const {emitter, errors} = form;\n const list = normalizeErrors(error);\n // An empty result (undefined, '', or an array of only falsy items) clears\n // the key: the errors Map never stores an empty list, so hasErrors stays\n // a plain size check and readers can index [0] unguarded.\n if (list) errors.set(path.key, list);\n else errors.delete(path.key);\n // Path payload lets key-scoped subscribers (onKeyEvent) skip unrelated\n // fields; payload-less listeners ignore it.\n emit(emitter, 'errors', path);\n if (options?.shouldFocus) emit(emitter, 'focusError', path.key);\n}\n\n/** Normalize any {@link setErrorByPath} input into the stored non-empty\n * FieldError[] shape, or undefined when there is nothing to store. */\nfunction normalizeErrors(\n error: string | FieldError | (string | FieldError)[] | undefined\n): FieldError[] | undefined {\n if (typeof error === 'string') {\n return error ? [{type: 'custom', message: error}] : undefined;\n }\n if (isFieldError(error)) return [error];\n if (!error) return undefined;\n // Falsy items drop out before normalization, so '' never becomes a\n // stored {type: 'custom', message: ''} placeholder.\n const list: FieldError[] = [];\n error.forEach(item => {\n if (typeof item === 'string' && item) {\n list.push({type: 'custom', message: item});\n } else if (isFieldError(item)) {\n list.push(item);\n }\n });\n return list.length ? list : undefined;\n}\n\n/**\n * Clear errors\n * @param form\n * @param name a single path or a list of paths; omit to clear every error\n */\nexport function clearErrors(form: Form, name?: Name | Name[]): void {\n const {emitter, errors} = form;\n if (name === undefined) {\n errors.clear();\n // Payload-less broadcast: every error subscriber re-syncs.\n emit(emitter, 'errors');\n return;\n }\n // Same single-path vs list discrimination as trigger: a segment array\n // holding a number is one path ('a.0' shape), not a list of names.\n const paths =\n typeof name === 'string' || isSegmentsPath(name)\n ? [createPath(name)]\n : name.map(one => createPath(one));\n for (const {key} of paths) errors.delete(key);\n // Path-payload emits — the setErrorByPath scoping — wake exactly the\n // affected fields' subscribers.\n for (const path of paths) emit(emitter, 'errors', path);\n}\n\n/** Options accepted by {@link setServerErrors}. */\nexport type SetServerErrorsOptions = {\n /** Keep existing field errors instead of clearing them first. Defaults\n * to `false`: a fresh server response replaces the prior error state. */\n keepExisting?: boolean;\n};\n\n/**\n * Land a server-side error response on the form: each entry becomes the\n * named field's error(s) with `type: 'server'`, ready for the same\n * renderError/`useError` channel client-side validation uses. Takes the\n * flat `Record<string, string | string[]>` shape REST APIs commonly\n * return (RealWorld: `422 {errors: {email: ['has already been taken']}}`)\n * without a hand-rolled `Object.entries` + `setError` loop.\n *\n * A string value lands as one error, a string array as several (first one\n * is what `getError`/`error` expose); an empty array clears that field's\n * errors. By default every existing error is cleared first — a fresh\n * response describes the current state, not a patch onto stale client\n * errors; pass `keepExisting: true` to layer instead.\n * @param form\n * @param errors field errors keyed by name\n * @param options\n */\nexport function setServerErrors(\n form: Form,\n errors: Record<string, string | string[]>,\n options?: SetServerErrorsOptions\n): void {\n if (!options?.keepExisting) clearErrors(form);\n for (const [name, error] of Object.entries(errors)) {\n setError(\n form,\n name,\n (Array.isArray(error) ? error : [error]).map(message => ({\n type: 'server',\n message\n }))\n );\n }\n}\n\n/**\n * Set field touched state\n * @param form\n * @param name\n */\n/**\n * @param form\n */\nexport function hasErrors({errors}: Form): boolean {\n return errors.size > 0;\n}\n\n/** Options accepted by {@link trigger}. `shouldTouch` defaults to `false`;\n * omitting the options object entirely keeps the plain validate-only\n * behavior, so the historical two-argument calls are untouched. */\n"],"names":["pathCache","Map","normalizePath","path","Array","isArray","cached","get","value","result","identifier","flushIdentifier","isIndex","dotted","map","String","join","bracket","reduce","acc","seg","TypeError","push","i","length","char","quote","close","indexOf","slice","content","Number","parsePath","size","oldest","keys","next","done","delete","set","segment","test","values","current","p","prop","props","index","arr","create","name","key","JSON","stringify","valuesCaches","WeakMap","bumpValuesVersion","form","cache","version","dirtyBaselines","dirtyFieldsCaches","isFieldError","type","message","VALIDATION_OUTCOME","baselines","clear","emitter","errors","emit","segments","has","initialValues","entries","list","parse","isEqual","a","b","Object","is","Date","getTime","proto","getPrototypeOf","prototype","keysA","keysB","then","stem","baselineKey","startsWith","error","options","forEach","item","normalizeErrors","setErrorByPath","createPath","root","owned","container","parent","parentProp","copy","add","parsedValues","unset","event","isResolve","isReject","Promise","resolve","reject","off","on"],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- import{on as e,emit as t}from"@for-fun/event-emitter";const n=new Map;function r(e){if(Array.isArray(e))return e;const t=n.get(e);if(t)return t;const r=function(e){const t=[];let n="";const r=()=>{if(o(n)){const r=[...t.map(String),n].join("."),o=t.reduce((e,t)=>e+("number"==typeof t?`[${t}]`:`${e?".":""}${t}`),"");throw new TypeError(`Numeric path segment must use bracket notation: "${r}" → "${o}[${n}]" (path: ${e})`)}t.push(n),n=""};for(let s=0;s<e.length;s++){const i=e[s];if("."===i)""!==n&&r();else if("["===i){""!==n&&r();const i=e[s+1];if('"'===i||"'"===i){const n=e.indexOf(i,s+2);if(-1===n)throw new TypeError(`Unterminated quote in path: ${e}`);if("]"!==e[n+1])throw new TypeError(`Expected "]" after quoted segment in path: ${e}`);t.push(e.slice(s+2,n)),s=n+1}else{const n=e.indexOf("]",s+1);if(-1===n)throw new TypeError(`Unterminated bracket in path: ${e}`);const r=e.slice(s+1,n);t.push(o(r)?Number(r):r),s=n}}else n+=i}""===n&&0!==t.length||r();return t}(e);if(n.size>=1e4){const e=n.keys().next();e.done||n.delete(e.value)}return n.set(e,r),r}const o=e=>/^-?\d+$/.test(e);function s(e,t){return t.reduce((e,t)=>{if(null!=e)return e[t]},e)}function i(e,t){if(!t.length||null==e)return e;const[n,...r]=t;if(r.length){const t=i(e[n],r);return t===e[n]?e:f(e,[n],t)}if(Array.isArray(e)){if(!(n in e))return e;const t=e.slice();return delete t[n],t}if("object"!=typeof e||!(n in e))return e;const o={...e};return delete o[n],o}function f(e,t,n){if(!t.length)return n;const[r,...s]=t,i="number"==typeof r?r:Array.isArray(e)&&"string"==typeof r&&o(r)?Number(r):void 0;if(void 0!==i){const t=Array.isArray(e)?e.slice():[];return t[i]=f(t[i],s,n),t}return{...e,[r]:f(e&&e[r],s,n)}}function u(e,t,n,r){if(!t.length)return n;let s=e,i=null,f="";for(let u=0;u<t.length;u++){const c=t[u];if(!r.has(s)){let t;t="number"==typeof c||Array.isArray(s)&&"string"==typeof c&&o(c)?Array.isArray(s)?s.slice():[]:{...s},r.add(t),0===u?e=t:i[f]=t,s=t}u===t.length-1?s[c]=n:(i=s,f=c,s=s[c])}return e}function c(e){return e&&"function"==typeof e.then}function a(e,t){if(Object.is(e,t))return!0;if(e instanceof Date&&t instanceof Date)return e.getTime()===t.getTime();if(!e||!t||"object"!=typeof e||"object"!=typeof t)return!1;const n=Array.isArray(e);if(n!==Array.isArray(t))return!1;if(n){if(e.length!==t.length)return!1;for(let n=0;n<e.length;n++)if(!a(e[n],t[n]))return!1;return!0}const r=Object.getPrototypeOf(e);if(r!==Object.prototype&&null!==r)return!1;if(Object.getPrototypeOf(t)!==r)return!1;const o=Object.keys(e),s=Object.keys(t);if(o.length!==s.length)return!1;for(const n of o)if(!a(e[n],t[n]))return!1;return!0}function l(t,n,r,o){return new Promise((s,i)=>{if(o())return void i();if(r())return void s();const f=e(t,n,()=>{if(o())return f(),void i();r()&&(f(),s())})})}function y(e){const t=r(e);return{value:t,key:JSON.stringify(t)}}const p=new WeakMap;function g(e){const t=p.get(e);t&&t.version++}const h=new WeakMap;function m(e,t,n){const r=h.get(e);return r?.has(t)?r.get(t):s(e.initialValues,n)}function d(e,{key:t}){const n=h.get(e);if(!n?.size)return;const r=`${t.slice(0,-1)},`;for(const e of n.keys())e.startsWith(r)&&n.delete(e)}function b(e,t){const n=h.get(e);n&&n.clear()}const v=new WeakMap;function A(e){const t=v.get(e);t&&t.version++}function k(e){return!!e&&"object"==typeof e&&"string"==typeof e.type&&"string"==typeof e.message}function w(e,n){void 0!==n&&n!==e.parsedValues&&(e.parsedValues=n,g(e),t(e.emitter,"change"))}const j="_form",O=Symbol("validation-outcome");function $({errors:e}){const t=[];for(const[n,r]of e){const e=JSON.parse(n).join(".");for(const{type:n,message:o}of r)t.push({path:e,type:n,message:o})}return t}function E(e,n,r,o){!function(e,n,r){const{emitter:o,errors:s}=e,i=function(e){if("string"==typeof e)return e?[{type:"custom",message:e}]:void 0;if(k(e))return[e];if(!e)return;const t=[];return e.forEach(e=>{"string"==typeof e&&e?t.push({type:"custom",message:e}):k(e)&&t.push(e)}),t.length?t:void 0}(r);i?s.set(n.key,i):s.delete(n.key);t(o,"errors",n)}(e,y(n),r)}function T(e,n){const{emitter:r,errors:o}=e;return o.clear(),void t(r,"errors")}function x({errors:e}){return e.size>0}export{j as F,O as V,$ as a,o as b,y as c,v as d,E as e,k as f,m as g,x as h,c as i,T as j,b as k,A as l,g as m,r as n,u as o,d as p,a as q,s as r,w as s,i as u,p as v,l as w};
2
- //# sourceMappingURL=errors-CrQBddrJ.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"errors-CrQBddrJ.mjs","sources":["../src/util.ts","../src/path.ts","../src/core/internals.ts","../src/core/errors.ts"],"sourcesContent":["import {on} from './emitter';\nimport type {EventEmitter} from './emitter';\n\n/** FIFO bound for {@link pathCache}. Static field names ('user.email')\n * number in the dozens per app, so the cache barely grows in practice;\n * the cap is only a backstop for dynamic keys ('items[' + id + ']'\n * style — array inputs skip the cache entirely), where long-lived forms\n * would otherwise accumulate entries forever. Map preserves insertion\n * order, so eviction drops the oldest entry; a dropped string only\n * costs a re-parse the next time normalizePath sees it — results are\n * deterministic, so eviction affects performance, never behavior. */\nconst PATH_CACHE_LIMIT = 1e4;\n\nconst pathCache = new Map<string, (string | number)[]>();\n\n/** Test-only view of the path cache size. Not re-exported from the\n * package entry — tests import this module directly to assert the\n * FIFO bound above. */\nexport const pathCacheSize = () => pathCache.size;\n\nexport function normalizePath(\n path: string | (string | number)[]\n): (string | number)[] {\n if (Array.isArray(path)) return path;\n const cached = pathCache.get(path);\n if (cached) return cached;\n const value = parsePath(path);\n if (pathCache.size >= PATH_CACHE_LIMIT) {\n // Insertion order is FIFO order; the cache is non-empty here\n // because size >= 1e4.\n const oldest = pathCache.keys().next();\n if (!oldest.done) pathCache.delete(oldest.value);\n }\n pathCache.set(path, value);\n return value;\n}\n\n/** Does a segment string denote an integer array index (optionally\n * negative)? The parser feeds it bracket contents ('items[0]' → number)\n * and rejects dotted numerics outright ('items.0' throws), so parsed\n * paths never carry index-looking strings. Its remaining duty is\n * defending programmatic segments: normalizePath also accepts raw\n * (string | number)[] arrays, and index-shaped strings can still arrive\n * from internal callers (error-tree keys) or array containers met\n * during set/setOwned walks. */\nexport const isIndex = (segment: string) => /^-?\\d+$/.test(segment);\n\nfunction parsePath(path: string): (string | number)[] {\n const result: (string | number)[] = [];\n let identifier = '';\n const flushIdentifier = () => {\n if (isIndex(identifier)) {\n // Rebuild both spellings for an actionable message: the dotted\n // form the caller wrote vs. the bracket form the parser accepts.\n const dotted = [...result.map(String), identifier].join('.');\n const bracket = result.reduce(\n (acc: string, seg: string | number) =>\n acc +\n (typeof seg === 'number' ? `[${seg}]` : `${acc ? '.' : ''}${seg}`),\n ''\n );\n throw new TypeError(\n `Numeric path segment must use bracket notation: \"${dotted}\" → \"${bracket}[${identifier}]\" (path: ${path})`\n );\n }\n result.push(identifier);\n identifier = '';\n };\n\n for (let i = 0; i < path.length; i++) {\n const char = path[i];\n if (char === '.') {\n if (identifier !== '') flushIdentifier();\n } else if (char === '[') {\n if (identifier !== '') flushIdentifier();\n const quote = path[i + 1];\n if (quote === '\"' || quote === \"'\") {\n const close = path.indexOf(quote, i + 2);\n if (close === -1) {\n throw new TypeError(`Unterminated quote in path: ${path}`);\n }\n if (path[close + 1] !== ']') {\n throw new TypeError(\n `Expected \"]\" after quoted segment in path: ${path}`\n );\n }\n result.push(path.slice(i + 2, close));\n i = close + 1;\n } else {\n const close = path.indexOf(']', i + 1);\n if (close === -1) {\n throw new TypeError(`Unterminated bracket in path: ${path}`);\n }\n const content = path.slice(i + 1, close);\n result.push(isIndex(content) ? Number(content) : content);\n i = close;\n }\n } else {\n identifier += char;\n }\n }\n if (identifier !== '' || result.length === 0) flushIdentifier();\n return result;\n}\n\nexport function get(values: any, path: (string | number)[]): any {\n return path.reduce((current: any, p: string | number) => {\n if (current == null) return undefined;\n return current[p];\n }, values);\n}\n\n/**\n * Immutable counterpart of {@link set}: removes the path from the value\n * tree, copying only along the touched branch (untouched branches stay\n * shared with the source, like set). Deletes the key entirely rather than\n * writing undefined, so the result carries no `a: undefined` entries.\n */\nexport function unset(values: any, path: (string | number)[]): any {\n if (!path.length || values == null) return values;\n const [prop, ...props] = path;\n if (props.length) {\n const next = unset(values[prop], props);\n // Reattach the pruned child at its parent key — NOT at the full path,\n // which would write the pruned subtree back under the removed key.\n return next === values[prop] ? values : set(values, [prop], next);\n }\n if (Array.isArray(values)) {\n if (!(prop in values)) return values;\n const arr = values.slice();\n delete arr[prop as number];\n return arr;\n }\n if (typeof values !== 'object' || !(prop in values)) return values;\n const copy = {...values};\n delete copy[prop as string];\n return copy;\n}\n\nexport function set(values: any, path: (string | number)[], value: any): any {\n if (!path.length) return value;\n\n const [prop, ...props] = path;\n // A numeric segment lands with the array copy rule — numbers, and the\n // string form dotted paths parse to ('a.0'), on an array container: an\n // object spread there would corrupt the array into {'0': ...}.\n const index =\n typeof prop === 'number'\n ? prop\n : Array.isArray(values) && typeof prop === 'string' && isIndex(prop)\n ? Number(prop)\n : undefined;\n if (index !== undefined) {\n const arr = Array.isArray(values) ? values.slice() : [];\n arr[index] = set(arr[index], props, value);\n return arr;\n }\n return {...values, [prop]: set(values && values[prop], props, value)};\n}\n\n/**\n * Ownership-tracked {@link set}: merge many paths into one tree without\n * re-copying containers the merge itself already created.\n *\n * Containers present in `owned` (freshly created by an earlier call of the\n * same merge) are mutated in place; every other container -- nodes borrowed\n * from the seed tree and user leaf values -- is copied first with the exact\n * copy rules `set` applies (numeric prop: array slice, or a fresh array\n * when the node is not one; string prop: object spread). Chaining\n * `setOwned` over a list of paths therefore produces the tree chaining\n * `set` would, in the same insertion order, but allocates each distinct\n * container once (O(distinct path prefixes)) instead of re-copying the\n * whole branch for every path (O(paths x depth)).\n *\n * Use a fresh `owned` set per merge and thread the returned root (a copied\n * replacement when the seed root itself had to be copied) into the next\n * call. Borrowed containers are never mutated.\n */\nexport function setOwned(\n root: any,\n path: (string | number)[],\n value: any,\n owned: Set<object>\n): any {\n if (!path.length) return value;\n let container = root;\n let parent: any = null;\n let parentProp: string | number = '';\n for (let i = 0; i < path.length; i++) {\n const prop = path[i];\n if (!owned.has(container)) {\n let copy: any;\n if (\n typeof prop === 'number' ||\n (Array.isArray(container) && typeof prop === 'string' && isIndex(prop))\n ) {\n copy = Array.isArray(container) ? container.slice() : [];\n } else {\n copy = {...container};\n }\n owned.add(copy);\n if (i === 0) root = copy;\n else parent[parentProp] = copy;\n container = copy;\n }\n if (i === path.length - 1) {\n container[prop] = value;\n } else {\n parent = container;\n parentProp = prop;\n container = container[prop];\n }\n }\n return root;\n}\n\nexport function isEmpty(value: any): boolean {\n if (value == null) return true;\n if (typeof value !== 'object') return false;\n\n const values = Object.values(value);\n return values.length === 0 || values.every(isEmpty);\n}\n\nexport function isPromise(value: any): value is Promise<any> {\n return value && typeof value.then === 'function';\n}\n\n/** Structural equality for form default data (primitives, arrays, plain\n * objects, Dates). Class instances and other exotic objects compare as\n * unequal, which errs on the side of re-seeding when {@link\n * setInitialValues} uses it to tell a re-rendered inline literal from\n * genuinely changed content. */\nexport function isEqual(a: any, b: any): boolean {\n if (Object.is(a, b)) return true;\n if (a instanceof Date && b instanceof Date)\n return a.getTime() === b.getTime();\n if (!a || !b || typeof a !== 'object' || typeof b !== 'object') return false;\n const isArray = Array.isArray(a);\n if (isArray !== Array.isArray(b)) return false;\n if (isArray) {\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n if (!isEqual(a[i], b[i])) return false;\n }\n return true;\n }\n const proto = Object.getPrototypeOf(a);\n if (proto !== Object.prototype && proto !== null) return false;\n if (Object.getPrototypeOf(b) !== proto) return false;\n const keysA = Object.keys(a);\n const keysB = Object.keys(b);\n if (keysA.length !== keysB.length) return false;\n for (const key of keysA) {\n if (!isEqual(a[key], b[key])) return false;\n }\n return true;\n}\n\nexport function waitUntil(\n emitter: EventEmitter<any>,\n event: string,\n isResolve: () => boolean,\n isReject: () => boolean\n): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n if (isReject()) return void reject();\n if (isResolve()) return void resolve();\n\n const off = on(emitter, event as any, () => {\n if (isReject()) {\n off();\n reject();\n return;\n }\n // Condition not reached yet — stay subscribed and keep waiting. (The\n // previous `if (isResolve()) return` was inverted: it hung forever\n // once the condition held and resolved prematurely while it didn't.)\n if (!isResolve()) return;\n off();\n resolve();\n });\n });\n}\n\n/**\n * DEV-only snapshot guard for {@link getValues}: deep-clones and freezes\n * plain objects and arrays so a consumer mutating the returned tree throws\n * immediately instead of silently corrupting the shared memoized result\n * (getValues hands the same cached reference to every reader between\n * writes). Non-plain values (Date, File, Blob, class instances, Map/Set)\n * pass through by reference, unfrozen — cloning would strip their\n * prototypes and freezing would break legitimate methods like\n * Date#setHours. Callers gate the call behind `__DEV__` so production\n * builds pay nothing.\n */\nexport function freezeValues(value: any): any {\n if (value === null || typeof value !== 'object') return value;\n if (Array.isArray(value)) {\n return Object.freeze(value.map(freezeValues));\n }\n if (Object.getPrototypeOf(value) !== Object.prototype) return value;\n const clone: Record<string, any> = {};\n for (const key of Object.keys(value)) clone[key] = freezeValues(value[key]);\n return Object.freeze(clone);\n}\n","import {normalizePath} from './util';\n\nexport type PathSegments = (string | number)[];\nexport type Name = string | PathSegments;\nexport type Path = {value: PathSegments; key: string};\n\nexport default function create(name: Name): Path {\n const value = normalizePath(name);\n return {value, key: JSON.stringify(value)};\n}\n","import {emit} from '../emitter';\nimport {get} from '../util';\nimport type {Name, Path, PathSegments} from '../path';\nimport type {FieldError, Form} from '../form';\n\n/** Per-form memoization of {@link getValues}, the same version-bump/read\n * pattern {@link dirtyFieldsCaches} gives {@link getDirtyFields}. */\ntype ValuesCache = {version: number; result: any};\n\nexport const valuesCaches = new WeakMap<Form, ValuesCache>();\n\n/**\n * Invalidate `form`'s cached {@link getValues} result. Called at every\n * point that can change values, parsedValues or initialValues\n * (setValueByPath, removeFieldByPath, setInitialValues, reset, resetField,\n * setParsedValues) so repeated reads hand back a stable reference until\n * the next write.\n */\nexport function bumpValuesVersion(form: Form): void {\n const cache = valuesCaches.get(form);\n if (cache) cache.version++;\n}\n\n/**\n * Get form values: the values Map layered over parsedValues (when a schema\n * validation produced them) layered over initialValues.\n *\n * Merged with copy-on-write ownership tracking ({@link setOwned}): every\n * distinct container on a written path is allocated once and shared by all\n * paths through it, instead of re-copying the whole branch for every key.\n * One owned set spans the whole merge, so containers borrowed from the\n * parsedValues tree are copied before mutation exactly like initialValues\n * ones. The result is a freshly merged tree per mutation, with untouched\n * branches sharing references with the baseline exactly like chained\n * `set` did.\n *\n * Memoized per form like {@link getDirtyFields}: every value write bumps a\n * `version` counter ({@link bumpValuesVersion}) while reads reset it, so\n * consecutive reads hand back the same reference (submit, changeValue and\n * form-level validate all read the whole tree, often several times per\n * interaction). Treat the result as read-only — the next read after a\n * write returns a fresh tree, but between writes the cached one is shared\n * with every other reader.\n *\n * parsedValues is the schema's complete output tree: once validation\n * succeeds it replaces the initialValues baseline (fields the schema\n * dropped disappear), while live edits in the values Map still win over\n * both. It never affects dirty state — {@link isDirty} and\n * {@link getDirtyFields} compare live edits against initialValues only,\n * because parsing is not a user edit.\n *\n * @param form\n */\n/** Per-path dirty-comparison baselines installed by writes with\n * `shouldDirty: false`: the written value becomes that field's baseline —\n * the write reads as a commit, not an edit. Module-private (like\n * {@link dirtyFieldsCaches}) so the Form shape is untouched for forms that\n * never opt in. */\nconst dirtyBaselines = new WeakMap<Form, Map<string, any>>();\n\n/** The value a field's dirtiness is measured against: its committed\n * baseline when one exists, initialValues at the path otherwise. */\nexport function getDirtyBaseline(\n form: Form,\n key: string,\n segments: PathSegments\n): any {\n const baselines = dirtyBaselines.get(form);\n if (baselines?.has(key)) return baselines.get(key);\n return get(form.initialValues, segments);\n}\n\n/** Install a committed baseline for a `shouldDirty: false` write: the\n * field reads clean until a later write diverges from the new baseline. */\nexport function setDirtyBaseline(form: Form, {key}: Path, value: any): void {\n let baselines = dirtyBaselines.get(form);\n if (!baselines) {\n baselines = new Map();\n dirtyBaselines.set(form, baselines);\n }\n baselines.set(key, value);\n}\n\n/** A wholesale write at a path replaces the subtree below it, so baselines\n * committed under the branch die with the data they were committed against\n * (array movers rewrite the parent path, re-aligning row indices). Called\n * from every write — a no-op unless the form ever opted in. */\nexport function pruneDirtyBaselines(form: Form, {key}: Path): void {\n const baselines = dirtyBaselines.get(form);\n if (!baselines?.size) return;\n const stem = `${key.slice(0, -1)},`;\n for (const baselineKey of baselines.keys()) {\n if (baselineKey.startsWith(stem)) baselines.delete(baselineKey);\n }\n}\n\n/** Drop committed baselines at one path ({@link removeFieldByPath} /\n * {@link resetField}) or all of them ({@link setInitialValues} /\n * {@link reset}) — the state they were measured against is gone. */\nexport function clearDirtyBaselines(form: Form, key?: string): void {\n const baselines = dirtyBaselines.get(form);\n if (!baselines) return;\n if (key === undefined) baselines.clear();\n else baselines.delete(key);\n}\n\n/** Per-form memoization of {@link getDirtyFields}. `version` counts value\n * mutations since the cached `result` was computed: bump points increment\n * it, reads reset it, so a non-zero version means the cache is stale. */\ntype DirtyFieldsCache = {version: number; result: Record<string, boolean>};\n\nexport const dirtyFieldsCaches = new WeakMap<Form, DirtyFieldsCache>();\n\n/**\n * Invalidate `form`'s cached {@link getDirtyFields} result. Called at every\n * point that can change values or initialValues (setValueByPath,\n * removeFieldByPath, setInitialValues, reset) so repeated reads hand out a\n * stable reference and useWatch's Object.is snapshot check can skip\n * re-renders.\n */\nexport function bumpDirtyVersion(form: Form): void {\n const cache = dirtyFieldsCaches.get(form);\n if (cache) cache.version++;\n}\n/** Numbers only occur inside a segments path (`['a', 0]`), never as\n * standalone names, so a top-level number marks `name` as one single path\n * rather than a list of names. */\nexport function isSegmentsPath(\n name: PathSegments | Name[]\n): name is PathSegments {\n return (name as (number | unknown)[]).some(part => typeof part === 'number');\n}\n\nexport function isFieldError(value: any): value is FieldError {\n return (\n !!value &&\n typeof value === 'object' &&\n typeof value.type === 'string' &&\n typeof value.message === 'string'\n );\n}\n\n/**\n * Flatten a form-level validate result and write each leaf error through\n * setError. Nested objects descend into deeper paths ({a: {b: 'msg'}} sets\n * the 'a.b' error), array values contribute every non-empty string they\n * hold as separate errors (zod flatten() formErrors style), and\n * FieldError-shaped objects are stored as-is. Falsy values are skipped.\n *\n * When `footprint` is passed (validateDeps forms only), every leaf this\n * round actually stored is recorded into it — the exact stored array —\n * so the next round can drop exactly what this one wrote.\n/** Store a schema validator's parsed output as the getValues baseline\n * layer above initialValues. Payload-less 'change' notifies value\n * watchers (useValue, useDirtyFields, ...); dirty state is untouched —\n * it only compares live edits against initialValues, and parsing is not\n * an edit. */\nexport function setParsedValues(form: Form, values: any): void {\n if (values === undefined || values === form.parsedValues) return;\n form.parsedValues = values;\n // parsedValues is a getValues layer above initialValues, so a new parse\n // invalidates the cached merge (dirty state is untouched — parsing is\n // not an edit, hence no bumpDirtyVersion here).\n bumpValuesVersion(form);\n emit(form.emitter, 'change');\n}\n\n/**\n * Land a form-level validate result. A plain record keeps the\n * long-standing behavior — flattened into field errors by\n * {@link setFormErrors}. A branded {@link ValidationOutcome} splits\n * instead: `errors` flattens exactly like a plain record, and `values`\n * (the schema's parsed output — coerced/transformed values included)\n * becomes the form's parsedValues baseline. Falsy results are skipped,\n * branded or not.\n *\n * Forms that opted into `validateDeps` additionally get round-scoped\n * error ownership: before the new result lands, the errors the previous\n * round wrote are dropped ({@link clearFormValidateErrors}), so a re-run\n * that passes makes the cross-field error disappear — and the new\n * round's own writes become the tracked footprint. Forms without the\n * option keep the historical write-only behavior untouched.\n */\n","import {emit} from '../emitter';\nimport createPath from '../path';\nimport type {Name, Path, PathSegments} from '../path';\nimport type {FieldPath} from '../types';\nimport type {FieldError, FieldErrorEntry, Form} from '../form';\nimport {isFieldError, isSegmentsPath} from './internals';\n\n/** Reserved top-level path segment for form-level errors. The Standard\n * Schema form-level adapter lands path-less issues under this key; the\n * exported constant replaces the magic string, and readers consume it via\n * getError(form, FORM_ERROR) / getFieldErrors(form, FORM_ERROR). */\nexport const FORM_ERROR = '_form';\n\n/** When a field is validated:\n * - `'onSubmit'` (default): only on submit\n * - `'onBlur'`: when the field loses focus\n * - `'onChange'`: on every change\n * - `'onTouched'`: on first blur, then on every change\n * - `'all'`: on both change and blur\n */\n/** Brand marking a form-level validate result as a structured\n * {@link ValidationOutcome} (parsed values and/or errors) rather than a\n * plain nested error record. Symbols cannot collide with user error\n * records, so detection is an exact `VALIDATION_OUTCOME in result`. */\nexport const VALIDATION_OUTCOME: unique symbol = Symbol('validation-outcome');\n\n/** Structured form-level validate result: `errors` uses the same nested\n * shape a plain error record uses, `values` is the schema's parsed output\n * (coerce/transform results included). Either side may be omitted. */\n/**\n * Get field error\n * @param form\n * @param name\n * @return FieldError object or undefined\n */\nexport function getError<\n T extends Record<string, any> = any,\n P extends FieldPath<T> | PathSegments = FieldPath<T> | PathSegments\n>(form: Form<T>, name: P): FieldError | undefined {\n return getErrorByPath(form, createPath(name));\n}\n\n/**\n * Get field error by path\n * @param form\n * @param path\n * @return first FieldError of the field, or undefined\n */\nexport function getErrorByPath(\n {errors}: Form,\n path: Path\n): FieldError | undefined {\n return errors.get(path.key)?.[0];\n}\n\n/** Shared empty result for {@link getFieldErrorsByPath}: a fresh `[]` per\n * call would allocate on the hot no-error path, and the stored arrays are\n * handed out by reference too, so callers must treat results as read-only. */\nconst NO_ERRORS: FieldError[] = [];\n\n/**\n * Get all errors of a field\n * @param form\n * @param name\n * @return every error registered for the field (insertion order); an empty\n * array when the field has none\n */\nexport function getFieldErrors<\n T extends Record<string, any> = any,\n P extends FieldPath<T> | PathSegments = FieldPath<T> | PathSegments\n>(form: Form<T>, name: P): FieldError[] {\n return getFieldErrorsByPath(form, createPath(name));\n}\n\n/**\n * Get all errors of a field by path\n * @param form\n * @param path\n * @return every error registered for the field (insertion order); an empty\n * array when the field has none\n */\nexport function getFieldErrorsByPath({errors}: Form, path: Path): FieldError[] {\n return errors.get(path.key) ?? NO_ERRORS;\n}\n\n/**\n * Get all errors\n * @param form\n * @return array of {path, type, message} entries, in insertion order; path\n * is the user-facing dotted field path ('a.b', 'list.0'), and a\n * field holding several errors contributes one entry per error\n */\nexport function getErrors({errors}: Form): FieldErrorEntry[] {\n const entries: FieldErrorEntry[] = [];\n for (const [key, list] of errors) {\n const path = (JSON.parse(key) as PathSegments).join('.');\n for (const {type, message} of list) entries.push({path, type, message});\n }\n return entries;\n}\n\n/**\n * Get first error message\n * @param form\n * @return first error's message string, or undefined when there are no errors\n */\nexport function getFirstError({errors}: Form): string | undefined {\n return errors.values().next().value?.[0]?.message;\n}\n\n/** Snapshot of one field's aggregated state, as {@link getFieldState}\n * returns it. `errors` is the stored array shared with the form — treat it\n * as read-only, like every {@link getFieldErrors} result. */\n/** Options accepted by {@link setError}. */\nexport type SetErrorOptions = {\n /**\n * Focus the named field's element after the error lands (react-hook-form's\n * `setError` `shouldFocus`). Rides the same 'focusError' channel\n * `setFocus` and a failed submit's auto-focus use: only mounted bound\n * fields react, unmounted ones are silent no-ops.\n */\n shouldFocus?: boolean;\n};\n\n/**\n * Set field error\n * @param form\n * @param name\n * @param error string is normalized to {type: 'custom', message}; a\n * FieldError object is stored as-is; an array holds several errors\n * (falsy items dropped, strings normalized); undefined clears\n * @param options {@link SetErrorOptions} — `shouldFocus` focuses the field\n * after the error lands\n */\nexport function setError<\n T extends Record<string, any> = any,\n P extends FieldPath<T> | PathSegments = FieldPath<T> | PathSegments\n>(\n form: Form<T>,\n name: P,\n error: string | FieldError | (string | FieldError)[] | undefined,\n options?: SetErrorOptions\n): void {\n setErrorByPath(form, createPath(name), error, options);\n}\n\n/**\n * Set field error\n * @param form\n * @param path\n * @param error string is normalized to {type: 'custom', message}; a\n * FieldError object is stored as-is; an array holds several errors\n * (falsy items dropped, strings normalized); undefined clears\n * @param options {@link SetErrorOptions} — `shouldFocus` focuses the field\n * after the error lands\n */\nexport function setErrorByPath(\n form: Form,\n path: Path,\n error: string | FieldError | (string | FieldError)[] | undefined,\n options?: SetErrorOptions\n): void {\n const {emitter, errors} = form;\n const list = normalizeErrors(error);\n // An empty result (undefined, '', or an array of only falsy items) clears\n // the key: the errors Map never stores an empty list, so hasErrors stays\n // a plain size check and readers can index [0] unguarded.\n if (list) errors.set(path.key, list);\n else errors.delete(path.key);\n // Path payload lets key-scoped subscribers (onKeyEvent) skip unrelated\n // fields; payload-less listeners ignore it.\n emit(emitter, 'errors', path);\n if (options?.shouldFocus) emit(emitter, 'focusError', path.key);\n}\n\n/** Normalize any {@link setErrorByPath} input into the stored non-empty\n * FieldError[] shape, or undefined when there is nothing to store. */\nfunction normalizeErrors(\n error: string | FieldError | (string | FieldError)[] | undefined\n): FieldError[] | undefined {\n if (typeof error === 'string') {\n return error ? [{type: 'custom', message: error}] : undefined;\n }\n if (isFieldError(error)) return [error];\n if (!error) return undefined;\n // Falsy items drop out before normalization, so '' never becomes a\n // stored {type: 'custom', message: ''} placeholder.\n const list: FieldError[] = [];\n error.forEach(item => {\n if (typeof item === 'string' && item) {\n list.push({type: 'custom', message: item});\n } else if (isFieldError(item)) {\n list.push(item);\n }\n });\n return list.length ? list : undefined;\n}\n\n/**\n * Clear errors\n * @param form\n * @param name a single path or a list of paths; omit to clear every error\n */\nexport function clearErrors(form: Form, name?: Name | Name[]): void {\n const {emitter, errors} = form;\n if (name === undefined) {\n errors.clear();\n // Payload-less broadcast: every error subscriber re-syncs.\n emit(emitter, 'errors');\n return;\n }\n // Same single-path vs list discrimination as trigger: a segment array\n // holding a number is one path ('a.0' shape), not a list of names.\n const paths =\n typeof name === 'string' || isSegmentsPath(name)\n ? [createPath(name)]\n : name.map(one => createPath(one));\n for (const {key} of paths) errors.delete(key);\n // Path-payload emits — the setErrorByPath scoping — wake exactly the\n // affected fields' subscribers.\n for (const path of paths) emit(emitter, 'errors', path);\n}\n\n/** Options accepted by {@link setServerErrors}. */\nexport type SetServerErrorsOptions = {\n /** Keep existing field errors instead of clearing them first. Defaults\n * to `false`: a fresh server response replaces the prior error state. */\n keepExisting?: boolean;\n};\n\n/**\n * Land a server-side error response on the form: each entry becomes the\n * named field's error(s) with `type: 'server'`, ready for the same\n * renderError/`useError` channel client-side validation uses. Takes the\n * flat `Record<string, string | string[]>` shape REST APIs commonly\n * return (RealWorld: `422 {errors: {email: ['has already been taken']}}`)\n * without a hand-rolled `Object.entries` + `setError` loop.\n *\n * A string value lands as one error, a string array as several (first one\n * is what `getError`/`error` expose); an empty array clears that field's\n * errors. By default every existing error is cleared first — a fresh\n * response describes the current state, not a patch onto stale client\n * errors; pass `keepExisting: true` to layer instead.\n * @param form\n * @param errors field errors keyed by name\n * @param options\n */\nexport function setServerErrors(\n form: Form,\n errors: Record<string, string | string[]>,\n options?: SetServerErrorsOptions\n): void {\n if (!options?.keepExisting) clearErrors(form);\n for (const [name, error] of Object.entries(errors)) {\n setError(\n form,\n name,\n (Array.isArray(error) ? error : [error]).map(message => ({\n type: 'server',\n message\n }))\n );\n }\n}\n\n/**\n * Set field touched state\n * @param form\n * @param name\n */\n/**\n * @param form\n */\nexport function hasErrors({errors}: Form): boolean {\n return errors.size > 0;\n}\n\n/** Options accepted by {@link trigger}. `shouldTouch` defaults to `false`;\n * omitting the options object entirely keeps the plain validate-only\n * behavior, so the historical two-argument calls are untouched. */\n"],"names":["pathCache","Map","normalizePath","path","Array","isArray","cached","get","value","result","identifier","flushIdentifier","isIndex","dotted","map","String","join","bracket","reduce","acc","seg","TypeError","push","i","length","char","quote","close","indexOf","slice","content","Number","parsePath","size","oldest","keys","next","done","delete","set","segment","test","values","current","p","unset","prop","props","arr","copy","index","setOwned","root","owned","container","parent","parentProp","has","add","isPromise","then","isEqual","a","b","Object","is","Date","getTime","proto","getPrototypeOf","prototype","keysA","keysB","key","waitUntil","emitter","event","isResolve","isReject","Promise","resolve","reject","off","on","create","name","JSON","stringify","valuesCaches","WeakMap","bumpValuesVersion","form","cache","version","dirtyBaselines","getDirtyBaseline","segments","baselines","initialValues","pruneDirtyBaselines","stem","baselineKey","startsWith","clearDirtyBaselines","clear","dirtyFieldsCaches","bumpDirtyVersion","isFieldError","type","message","setParsedValues","parsedValues","emit","FORM_ERROR","VALIDATION_OUTCOME","getErrors","errors","entries","list","parse","setError","error","options","forEach","item","normalizeErrors","setErrorByPath","createPath","clearErrors","hasErrors"],"mappings":"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"}