react-f0rm 1.4.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -4
- package/dist/array-Bu7W8BSz.d.ts +54 -0
- package/dist/devtools/index.cjs.js +1 -1
- package/dist/devtools/index.cjs.js.map +1 -1
- package/dist/devtools/index.d.cts +8 -18
- package/dist/devtools/index.d.mts +8 -18
- package/dist/devtools/index.d.ts +8 -18
- package/dist/devtools/index.mjs +1 -1
- package/dist/devtools/index.mjs.map +1 -1
- package/dist/errors-DA4ReEd9.mjs +2 -0
- package/dist/errors-DA4ReEd9.mjs.map +1 -0
- package/dist/errors-TzyWwBfw.cjs.js +2 -0
- package/dist/errors-TzyWwBfw.cjs.js.map +1 -0
- package/dist/index.cjs.js +1 -1
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.cts +347 -927
- package/dist/index.d.mts +347 -927
- package/dist/index.d.ts +347 -927
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/index.umd.js +538 -451
- package/dist/index.umd.js.map +1 -1
- package/dist/index.umd.min.js +2 -2
- package/dist/index.umd.min.js.map +1 -1
- package/dist/persist.cjs.js +1 -1
- package/dist/persist.cjs.js.map +1 -1
- package/dist/persist.d.cts +9 -30
- package/dist/persist.d.mts +9 -30
- package/dist/persist.d.ts +9 -30
- package/dist/persist.mjs +1 -1
- package/dist/persist.mjs.map +1 -1
- package/dist/resolvers/standard-schema.cjs.js +1 -1
- package/dist/resolvers/standard-schema.d.cts +1 -1
- package/dist/resolvers/standard-schema.d.mts +1 -1
- package/dist/resolvers/standard-schema.d.ts +1 -1
- package/dist/resolvers/standard-schema.mjs +1 -1
- package/dist/resolvers/yup.cjs.js +1 -1
- package/dist/resolvers/yup.mjs +1 -1
- package/dist/resolvers/zod.cjs.js +1 -1
- package/dist/resolvers/zod.cjs.js.map +1 -1
- package/dist/resolvers/zod.d.cts +30 -2
- package/dist/resolvers/zod.d.mts +30 -2
- package/dist/resolvers/zod.d.ts +30 -2
- package/dist/resolvers/zod.mjs +1 -1
- package/dist/resolvers/zod.mjs.map +1 -1
- package/dist/server/index.cjs.js +1 -1
- package/dist/server/index.cjs.js.map +1 -1
- package/dist/server/index.d.cts +24 -92
- package/dist/server/index.d.mts +24 -92
- package/dist/server/index.d.ts +24 -92
- package/dist/server/index.mjs +1 -1
- package/dist/server/index.mjs.map +1 -1
- package/dist/standard-schema-BAaTmAHh.d.ts +682 -0
- package/dist/standardSchema-5WezjHlp.mjs +2 -0
- package/dist/standardSchema-5WezjHlp.mjs.map +1 -0
- package/dist/standardSchema-DINHlsYR.cjs.js +2 -0
- package/dist/standardSchema-DINHlsYR.cjs.js.map +1 -0
- package/dist/validate-2pX-N1O6.cjs.js +2 -0
- package/dist/validate-2pX-N1O6.cjs.js.map +1 -0
- package/dist/validate-C0HOsP9v.mjs +2 -0
- package/dist/validate-C0HOsP9v.mjs.map +1 -0
- package/dist/values-BbPnLByD.cjs.js +2 -0
- package/dist/values-BbPnLByD.cjs.js.map +1 -0
- package/dist/values-CHsmcZk4.mjs +2 -0
- package/dist/values-CHsmcZk4.mjs.map +1 -0
- package/package.json +6 -4
- package/dist/array-3hAjl6Bz.d.ts +0 -160
- package/dist/errors-8oPux7GR.cjs.js +0 -2
- package/dist/errors-8oPux7GR.cjs.js.map +0 -1
- package/dist/errors-ClH3eV1R.mjs +0 -2
- package/dist/errors-ClH3eV1R.mjs.map +0 -1
- package/dist/standard-schema-CYbnugL7.d.ts +0 -1184
- package/dist/standardSchema-BpZvg0tZ.mjs +0 -2
- package/dist/standardSchema-BpZvg0tZ.mjs.map +0 -1
- package/dist/standardSchema-CxV_DhBO.cjs.js +0 -2
- package/dist/standardSchema-CxV_DhBO.cjs.js.map +0 -1
- package/dist/validate-BEjNsNvd.mjs +0 -2
- package/dist/validate-BEjNsNvd.mjs.map +0 -1
- package/dist/validate-BvN6hiEG.cjs.js +0 -2
- package/dist/validate-BvN6hiEG.cjs.js.map +0 -1
- package/dist/values-Bod74Kzu.mjs +0 -2
- package/dist/values-Bod74Kzu.mjs.map +0 -1
- package/dist/values-DKpOCD5J.cjs.js +0 -2
- package/dist/values-DKpOCD5J.cjs.js.map +0 -1
package/README.md
CHANGED
|
@@ -30,8 +30,14 @@ A headless, event-driven React form library with field-level subscriptions.
|
|
|
30
30
|
- **Nested error tree.** `useErrorsTree(form)` / `getErrorsTree(form)` read errors as `errors.items?.[0]?.name` — the typed optional-chain shape RHF's `formState.errors` uses — alongside the flat dotted record (`useErrors`). One cache, both views, stable references.
|
|
31
31
|
- **Form-level validation cadence.** `createForm({validateMode: 'onChange' | 'onBlur'})` re-runs the form-level `validate` on every user change/blur — TanStack `validators.onChange/onBlur` parity without enumerating `validateDeps`; rounds own their errors, so a passing re-run clears what the last round wrote.
|
|
32
32
|
- **Disabled subtrees.** A field declared `disabled: true` disables its descendants (RHF subtree semantics); a descendant opts back out with `disabled: false`. The form-level flag still disables everything.
|
|
33
|
+
- **`<ErrorSummary />`.** GOV.UK-style a11y summary box: every error links to its field's error element (`fieldErrorId`), clicking focuses the field through the focus channel, and a failed submit focuses the box itself; bound inputs carry `aria-invalid`/`aria-describedby` and `aria-busy` while validating.
|
|
34
|
+
- **Single-flight submits.** A submit attempt arriving while one is in flight is ignored outright (double clicks, Enter repeats) — `useCanSubmit` remains the submit button's flag.
|
|
35
|
+
- **Controlled values with keep-flags.** `useForm({values, resetOptions})` — RHF's `resetOptions` contract: a genuinely changed `values` re-syncs through `reset` so flags like `keepDirtyValues` decide what survives; the default `setInitialValues` semantics are unchanged.
|
|
36
|
+
- **Row-add focus.** `append`/`prepend`/`insert` take `{focus: true | 'fieldName'}` — the new row's field takes focus once it commits (opt-in, unlike RHF's default-on).
|
|
37
|
+
- **Form-level rule messages.** `createForm({messages})` overrides every `rules` default message once — string with `{bound}` interpolation or `(bound) => string`; per-rule and per-field messages still win. i18n in one place.
|
|
38
|
+
- **Schema introspection tools.** `constraintsFromSchema`/`defaultsFromSchema` from `react-f0rm/resolvers/zod` derive per-field `rules` constraints and an `initialValues` tree from a zod v3/v4 schema — form generators stop hand-writing the schema twice.
|
|
33
39
|
- **Tombstone unregister, async initial values, declarative `rules`** (store-side errors + native constraint attributes), `validateOnMount`, `validateDeps` cross-field re-runs, `useTransform` async transforms, `createFormContext` typed isolated contexts, `reset`/`resetField` with RHF-parity keep-flags, `<Devtools />` from `react-f0rm/devtools`, `react-f0rm/persist` — see the [docs site](https://wmzy.github.io/react-f0rm/) for the full surface.
|
|
34
|
-
- **14.
|
|
40
|
+
- **14.81 KB gzip core** (13.5 KB brotli, emitter-external measurement); devtools/server/persist/resolvers ship as separate tree-shakeable entries.
|
|
35
41
|
|
|
36
42
|
## Install
|
|
37
43
|
|
|
@@ -151,18 +157,18 @@ npx vitest bench --run test/bench/scale.bench.ts # the three scale scenarios a
|
|
|
151
157
|
|
|
152
158
|
react-f0rm vs React Hook Form, TanStack Form and Formik — rendering model, schema adapters, path typing, async validation, bundle size, ecosystem maturity — lives on the [Comparison page](https://wmzy.github.io/react-f0rm/comparison) of the docs site.
|
|
153
159
|
|
|
154
|
-
Short version: **pick react-f0rm** for controlled components with true per-field subscriptions (design systems, editor-like forms), one Standard Schema adapter, compile-time-checked paths, `register`-style bindings when you want them, and a core
|
|
160
|
+
Short version: **pick react-f0rm** for controlled components with true per-field subscriptions (design systems, editor-like forms), one Standard Schema adapter, compile-time-checked paths, `register`-style bindings when you want them, and a core ~5% over RHF's entry (components layer included, tree-shakeable headless) — and you are comfortable with a young library. **Pick React Hook Form** for the mature ecosystem today (its performance edge is gone at the rendering level — see the bench notes). **TanStack Form** sits in between: the deepest possible type inference, at a larger core.
|
|
155
161
|
|
|
156
162
|
## Docs Map
|
|
157
163
|
|
|
158
|
-
- Guides: [Validation](https://wmzy.github.io/react-f0rm/guides/validation) · [Field Arrays](https://wmzy.github.io/react-f0rm/guides/field-arrays) · [Submission](https://wmzy.github.io/react-f0rm/guides/submission) · [Sub-forms](https://wmzy.github.io/react-f0rm/guides/sub-forms) · [React 19 Server Actions](https://wmzy.github.io/react-f0rm/guides/react19-server-actions) · [SSR](https://wmzy.github.io/react-f0rm/guides/ssr) · [TypeScript](https://wmzy.github.io/react-f0rm/guides/typescript) · [Custom components](https://wmzy.github.io/react-f0rm/guides/custom-components) · [UI-kit integration](https://wmzy.github.io/react-f0rm/guides/ui-integration) · [Testing](https://wmzy.github.io/react-f0rm/guides/testing) · [Hooks Reference](https://wmzy.github.io/react-f0rm/guides/hooks-reference) · [Headless & React Native](https://wmzy.github.io/react-f0rm/guides/headless-react-native)
|
|
164
|
+
- Guides: [Validation](https://wmzy.github.io/react-f0rm/guides/validation) · [Field Arrays](https://wmzy.github.io/react-f0rm/guides/field-arrays) · [Submission](https://wmzy.github.io/react-f0rm/guides/submission) · [Sub-forms](https://wmzy.github.io/react-f0rm/guides/sub-forms) · [Derived Fields](https://wmzy.github.io/react-f0rm/guides/derived-fields) · [React 19 Server Actions](https://wmzy.github.io/react-f0rm/guides/react19-server-actions) · [SSR](https://wmzy.github.io/react-f0rm/guides/ssr) · [TypeScript](https://wmzy.github.io/react-f0rm/guides/typescript) · [Custom components](https://wmzy.github.io/react-f0rm/guides/custom-components) · [UI-kit integration](https://wmzy.github.io/react-f0rm/guides/ui-integration) · [Testing](https://wmzy.github.io/react-f0rm/guides/testing) · [Hooks Reference](https://wmzy.github.io/react-f0rm/guides/hooks-reference) · [Headless & React Native](https://wmzy.github.io/react-f0rm/guides/headless-react-native)
|
|
159
165
|
- Examples: [Basic](https://wmzy.github.io/react-f0rm/examples/basic) · [Dynamic fields](https://wmzy.github.io/react-f0rm/examples/dynamic) · [Real-world form](https://wmzy.github.io/react-f0rm/examples/real-world-form) (wizard + cross-field validation + server backfill)
|
|
160
166
|
- Migration: [from Formik](https://wmzy.github.io/react-f0rm/migration/from-formik) · [from React Hook Form](https://wmzy.github.io/react-f0rm/migration/from-react-hook-form) · [from TanStack Form](https://wmzy.github.io/react-f0rm/migration/from-tanstack-form) · [Breaking changes](https://wmzy.github.io/react-f0rm/migration/breaking-changes)
|
|
161
167
|
|
|
162
168
|
## Development
|
|
163
169
|
|
|
164
170
|
```bash
|
|
165
|
-
npm test #
|
|
171
|
+
npm test # 962 tests, vmThreads pool (~3s)
|
|
166
172
|
npm run test:watch # watch mode
|
|
167
173
|
npm run coverage # coverage report (95/90/95/95 thresholds enforced)
|
|
168
174
|
npx vitest bench --run test/bench/ # benchmarks
|
|
@@ -173,6 +179,13 @@ npm run storybook # Storybook dev server
|
|
|
173
179
|
npm run docs:build # Docusaurus build (docs-site/)
|
|
174
180
|
```
|
|
175
181
|
|
|
182
|
+
Migrating from React Hook Form? The codemods directory ships two jscodeshift transforms (`defaultValues`→`initialValues`, register-rules wrapping) plus the manual-steps checklist:
|
|
183
|
+
|
|
184
|
+
```sh
|
|
185
|
+
pnpm exec jscodeshift -t codemods/transforms/use-form-options.js src/
|
|
186
|
+
pnpm exec jscodeshift -t codemods/transforms/register-binding.js src/
|
|
187
|
+
```
|
|
188
|
+
|
|
176
189
|
## License
|
|
177
190
|
|
|
178
191
|
ISC
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { A as AnyPath, F as Form, e as ArrayItemOf, P as Path } from './standard-schema-BAaTmAHh.js';
|
|
2
|
+
|
|
3
|
+
/** Append one value to the array at `path`. */
|
|
4
|
+
declare function appendValueByPath(form: Form, path: Path, value: any): void;
|
|
5
|
+
/** Prepend one value to the array at `path`. */
|
|
6
|
+
declare function prependValueByPath(form: Form, path: Path, value: any): void;
|
|
7
|
+
/** Insert one value at `index` in the array at `path` (`index === length`
|
|
8
|
+
* appends). Returns `false` — without touching the form — when the index
|
|
9
|
+
* is out of range; `true` once the value landed. */
|
|
10
|
+
declare function insertValueByPath(form: Form, path: Path, index: number, value: any): boolean;
|
|
11
|
+
/** Remove one or several rows from the array at `path` in a single write.
|
|
12
|
+
* Indices may repeat; out-of-range entries are ignored. Returns the
|
|
13
|
+
* indices actually dropped, sorted descending so caller-side row-id
|
|
14
|
+
* bookkeeping can splice them without re-indexing drift; `[]` when nothing
|
|
15
|
+
* was removable. */
|
|
16
|
+
declare function removeValueByPath(form: Form, path: Path, indices: number | number[]): number[];
|
|
17
|
+
/** Move the row at `from` to `to` (rows in between shift one position).
|
|
18
|
+
* Returns `false` — without touching the form — when either index is out
|
|
19
|
+
* of range or they are equal; `true` once the row moved. */
|
|
20
|
+
declare function moveValueByPath(form: Form, path: Path, from: number, to: number): boolean;
|
|
21
|
+
/** Swap the rows at `from` and `to`. Returns `false` — without touching
|
|
22
|
+
* the form — when either index is out of range or they are equal; `true`
|
|
23
|
+
* once the rows swapped. */
|
|
24
|
+
declare function swapValuesByPath(form: Form, path: Path, from: number, to: number): boolean;
|
|
25
|
+
/** Wholesale-replace the array at `path` (length may change) in one write. */
|
|
26
|
+
declare function replaceValuesByPath(form: Form, path: Path, values: any[]): void;
|
|
27
|
+
/** Overwrite one row of the array at `path` in place (a whole-array write,
|
|
28
|
+
* so the row's position and every other row are untouched). Returns
|
|
29
|
+
* `false` when the index is out of range; `true` once the value landed. */
|
|
30
|
+
declare function updateValueByPath(form: Form, path: Path, index: number, value: any): boolean;
|
|
31
|
+
/** Append one value to the array at `name`. */
|
|
32
|
+
declare function appendValue<T extends Record<string, any> = any, P extends AnyPath<T> = AnyPath<T>>(form: Form<T>, name: P, value: ArrayItemOf<T, P>): void;
|
|
33
|
+
/** Prepend one value to the array at `name`. See {@link appendValue}. */
|
|
34
|
+
declare function prependValue<T extends Record<string, any> = any, P extends AnyPath<T> = AnyPath<T>>(form: Form<T>, name: P, value: ArrayItemOf<T, P>): void;
|
|
35
|
+
/** Insert one value at `index` in the array at `name`. Returns `false` on
|
|
36
|
+
* an out-of-range index (see {@link insertValueByPath}). */
|
|
37
|
+
declare function insertValue<T extends Record<string, any> = any, P extends AnyPath<T> = AnyPath<T>>(form: Form<T>, name: P, index: number, value: ArrayItemOf<T, P>): boolean;
|
|
38
|
+
/** Remove one or several rows from the array at `name` in a single write.
|
|
39
|
+
* Returns the indices actually dropped, descending (see
|
|
40
|
+
* {@link removeValueByPath}). */
|
|
41
|
+
declare function removeValue<T extends Record<string, any> = any, P extends AnyPath<T> = AnyPath<T>>(form: Form<T>, name: P, indices: number | number[]): number[];
|
|
42
|
+
/** Move the row at `from` to `to` in the array at `name`. Returns `false`
|
|
43
|
+
* on an out-of-range or no-op move (see {@link moveValueByPath}). */
|
|
44
|
+
declare function moveValue<T extends Record<string, any> = any, P extends AnyPath<T> = AnyPath<T>>(form: Form<T>, name: P, from: number, to: number): boolean;
|
|
45
|
+
/** Swap the rows at `from` and `to` in the array at `name`. Returns
|
|
46
|
+
* `false` on an out-of-range or no-op swap (see {@link swapValuesByPath}). */
|
|
47
|
+
declare function swapValues<T extends Record<string, any> = any, P extends AnyPath<T> = AnyPath<T>>(form: Form<T>, name: P, from: number, to: number): boolean;
|
|
48
|
+
/** Wholesale-replace the array at `name` (see {@link replaceValuesByPath}). */
|
|
49
|
+
declare function replaceValues<T extends Record<string, any> = any, P extends AnyPath<T> = AnyPath<T>>(form: Form<T>, name: P, values: ArrayItemOf<T, P>[]): void;
|
|
50
|
+
/** Overwrite one row of the array at `name` in place. Returns `false` on
|
|
51
|
+
* an out-of-range index (see {@link updateValueByPath}). */
|
|
52
|
+
declare function updateValue<T extends Record<string, any> = any, P extends AnyPath<T> = AnyPath<T>>(form: Form<T>, name: P, index: number, value: ArrayItemOf<T, P>): boolean;
|
|
53
|
+
|
|
54
|
+
export { appendValue as a, replaceValues as b, appendValueByPath as c, insertValueByPath as d, moveValueByPath as e, prependValueByPath as f, removeValueByPath as g, replaceValuesByPath as h, insertValue as i, swapValuesByPath as j, updateValueByPath as k, moveValue as m, prependValue as p, removeValue as r, swapValues as s, updateValue as u };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var e=require("react"),t=require("@for-fun/event-emitter"),n=require("../errors-8oPux7GR.cjs.js"),r=require("../values-DKpOCD5J.cjs.js"),a=require("../validate-BvN6hiEG.cjs.js");function o(e){var t=Object.create(null);return e&&Object.keys(e).forEach(function(n){if("default"!==n){var r=Object.getOwnPropertyDescriptor(e,n);Object.defineProperty(t,n,r.get?r:{enumerable:!0,get:function(){return e[n]}})}}),t.default=e,Object.freeze(t)}var s=o(e);function l(e){const t={};return function(e,t){for(const[r,a]of e.values){const o=JSON.parse(r);n.getDirtyBaseline(e,r,o)!==a&&t(o.join("."))}}(e,e=>{t[e]=!0}),t}function i(e){let t=n.dirtyFieldsCaches.get(e);if(t){if(t.version>0){const n=l(e);(function(e,t){const n=Object.keys(e);return n.length===Object.keys(t).length&&n.every(e=>!0===t[e])})(t.result,n)||(t.result=n),t.version=0}}else t={version:0,result:l(e)},n.dirtyFieldsCaches.set(e,t);return t.result}function d(n,r,a,o){const s="emitter"in n?n.emitter:n;return function(t,n,r){const a=e.useRef(null);null===a.current&&(a.current={hasValue:!1});const o=a.current,s=e.useRef(n);s.current=n;const l=e.useRef(r);l.current=r;const i=e.useCallback(()=>(o.hasValue||(o.value=s.current(),o.hasValue=!0),o.value),[o]),d=e.useCallback(e=>(o.hasValue=!1,t(()=>{const t=l.current;if(t&&o.hasValue){const n=s.current();if(t(o.value,n))return;return o.value=n,void e()}o.hasValue=!1,e()})),[t,o]);return e.useSyncExternalStore(d,i,i)}(e.useCallback(e=>t.on(s,r,e),[s,r]),a,o)}const c=e.createContext(null);c.Provider;e.createContext(null).Provider;function m({name:t,value:n,depth:r=0}){const[a,o]=e.useState(r<=1),l=void 0===t?null:s.createElement(s.Fragment,null,s.createElement("span",{className:"rf0-dt-key"},String(t)),s.createElement("span",{className:"rf0-dt-punct"},": "));if(null!==n&&"object"==typeof n){const e=Array.isArray(n),t=e?n.map((e,t)=>[t,e]):Object.entries(n),i=e?"[":"{",d=e?"]":"}",c=a?"":`${i}…${d} ${t.length}`;return s.createElement("div",{className:"rf0-dt-row",style:{paddingLeft:12*r}},s.createElement("button",{type:"button",className:"rf0-dt-node-toggle","aria-expanded":a,onClick:()=>o(!a)},s.createElement("span",{className:"rf0-dt-caret"},a?"▾":"▸"),l,s.createElement("span",{className:"rf0-dt-punct"},a?i:c)),a&&s.createElement(s.Fragment,null,t.map(([e,t])=>s.createElement(m,{key:String(e),name:e,value:t,depth:r+1})),s.createElement("span",{className:"rf0-dt-punct",style:{paddingLeft:12*r}},d)))}return s.createElement("span",{className:"rf0-dt-row",style:{paddingLeft:12*r,display:"block"}},l,s.createElement(f,{value:n}))}function f({value:e}){return void 0===e?s.createElement("span",{className:"rf0-dt-null"},"undefined"):null===e?s.createElement("span",{className:"rf0-dt-null"},"null"):"string"==typeof e?s.createElement("span",{className:"rf0-dt-string"},'"',e,'"'):"boolean"==typeof e?s.createElement("span",{className:"rf0-dt-boolean"},String(e)):s.createElement("span",{className:"rf0-dt-number"},String(e))}const p="react-f0rm-devtools-style";const u=["values","errors","touched","dirty","submits","events"];function b(e){if(void 0!==e)return e?"rf0-dt-ok":"rf0-dt-err"}function g(e){if(null===e||"object"!=typeof e)return 1;let t=0;for(const n of Object.values(e))t+=g(n);return t}exports.Devtools=function({form:o,position:l="top-right"}){!function(){if("undefined"==typeof document)return;if(document.getElementById(p))return;const e=document.createElement("style");e.id=p,e.textContent="\n.rf0-dt {\n position: fixed;\n z-index: 2147483000;\n box-sizing: border-box;\n width: 308px;\n max-width: calc(100vw - 16px);\n max-height: min(70vh, 560px);\n display: flex;\n flex-direction: column;\n font-family: ui-monospace, 'SF Mono', 'Cascadia Code', 'JetBrains Mono',\n Menlo, Consolas, 'Liberation Mono', monospace;\n font-size: 11px;\n line-height: 1.45;\n color: #c7d0dc;\n background: #0c1017;\n border: 1px solid #1f2735;\n border-radius: 4px;\n box-shadow: 0 12px 32px rgba(0, 0, 0, 0.55), 0 0 0 1px rgba(0, 0, 0, 0.4);\n}\n.rf0-dt *,\n.rf0-dt-badge * {\n box-sizing: border-box;\n}\n.rf0-dt--top-right { top: 8px; right: 8px; }\n.rf0-dt--bottom-right { bottom: 8px; right: 8px; }\n.rf0-dt--top-left { top: 8px; left: 8px; }\n.rf0-dt--bottom-left { bottom: 8px; left: 8px; }\n\n/* ---- header -------------------------------------------------------- */\n.rf0-dt-header {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 5px 6px 5px 9px;\n border-bottom: 1px solid #1f2735;\n background: #10151e;\n}\n.rf0-dt-title {\n flex: 1;\n min-width: 0;\n color: #8b96a5;\n font-size: 10px;\n font-weight: 700;\n letter-spacing: 0.14em;\n text-transform: uppercase;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.rf0-dt-title::before {\n content: '';\n display: inline-block;\n width: 6px;\n height: 6px;\n margin-right: 6px;\n border-radius: 50%;\n background: #e2b93b;\n vertical-align: 1px;\n}\n.rf0-dt-headerbtn {\n border: 1px solid transparent;\n border-radius: 3px;\n padding: 1px 5px;\n color: #8b96a5;\n background: transparent;\n font: inherit;\n font-size: 10px;\n cursor: pointer;\n}\n.rf0-dt-headerbtn:hover { color: #dce3ec; border-color: #2a3547; }\n.rf0-dt-headerbtn:focus-visible,\n.rf0-dt-tab:focus-visible,\n.rf0-dt-action:focus-visible,\n.rf0-dt-badge:focus-visible,\n.rf0-dt-node-toggle:focus-visible {\n outline: 1px solid #e2b93b;\n outline-offset: 1px;\n}\n\n/* ---- tabs ---------------------------------------------------------- */\n.rf0-dt-tablist {\n display: flex;\n border-bottom: 1px solid #1f2735;\n background: #0e131b;\n}\n.rf0-dt-tab {\n flex: 1;\n padding: 4px 2px 5px;\n border: 0;\n border-bottom: 2px solid transparent;\n background: transparent;\n color: #6b7686;\n font: inherit;\n font-size: 10px;\n letter-spacing: 0.1em;\n text-transform: uppercase;\n cursor: pointer;\n white-space: nowrap;\n}\n.rf0-dt-tab:hover { color: #aab5c4; }\n.rf0-dt-tab[aria-selected='true'] {\n color: #e7edf4;\n border-bottom-color: #e2b93b;\n}\n.rf0-dt-tab-count {\n margin-left: 3px;\n color: inherit;\n opacity: 0.75;\n}\n.rf0-dt-tab--danger[aria-selected='true'] {\n border-bottom-color: #f0647c;\n}\n\n/* ---- panels -------------------------------------------------------- */\n.rf0-dt-panel {\n flex: 1;\n min-height: 84px;\n overflow: auto;\n padding: 6px 8px;\n scrollbar-width: thin;\n scrollbar-color: #2a3547 transparent;\n}\n.rf0-dt-empty {\n padding: 10px 2px;\n color: #4d5766;\n font-style: italic;\n}\n\n/* json tree */\n.rf0-dt-row {\n display: block;\n white-space: pre;\n tab-size: 2;\n}\n.rf0-dt-node-toggle {\n border: 0;\n padding: 0;\n background: transparent;\n color: inherit;\n font: inherit;\n text-align: left;\n cursor: pointer;\n white-space: pre;\n}\n.rf0-dt-node-toggle:hover .rf0-dt-key { color: #dce3ec; }\n.rf0-dt-caret {\n display: inline-block;\n width: 1.2em;\n color: #4d5766;\n}\n.rf0-dt-key { color: #8b96a5; }\n.rf0-dt-punct { color: #4d5766; }\n.rf0-dt-string { color: #8fd68a; }\n.rf0-dt-number { color: #e2b93b; }\n.rf0-dt-boolean { color: #6fb3d9; }\n.rf0-dt-null { color: #55607080; font-style: italic; }\n\n/* errors / touched / dirty lists */\n.rf0-dt-item {\n padding: 3px 2px;\n border-bottom: 1px dotted #1a2230;\n display: flex;\n gap: 8px;\n align-items: baseline;\n}\n.rf0-dt-item:last-child { border-bottom: 0; }\n.rf0-dt-item-path {\n color: #aab5c4;\n word-break: break-all;\n}\n.rf0-dt-item-msg {\n color: #f0647c;\n word-break: break-word;\n}\n.rf0-dt-item-msg--ok { color: #8fd68a; }\n.rf0-dt-item-tag {\n flex: none;\n color: #4d5766;\n font-size: 10px;\n}\n.rf0-dt-item--touched .rf0-dt-item-path { color: #6fb3d9; }\n.rf0-dt-item--dirty .rf0-dt-item-path { color: #e2b93b; }\n\n/* ---- submit status + actions --------------------------------------- */\n.rf0-dt-status {\n display: flex;\n gap: 10px;\n padding: 4px 9px;\n border-top: 1px solid #1f2735;\n background: #10151e;\n color: #6b7686;\n font-size: 10px;\n letter-spacing: 0.04em;\n white-space: nowrap;\n overflow: hidden;\n}\n.rf0-dt-status b { color: #aab5c4; font-weight: 400; }\n.rf0-dt-status .rf0-dt-on { color: #e2b93b; }\n.rf0-dt-status .rf0-dt-ok { color: #8fd68a; }\n.rf0-dt-status .rf0-dt-err { color: #f0647c; }\n.rf0-dt-actions {\n display: flex;\n gap: 6px;\n padding: 6px 8px;\n border-top: 1px solid #1f2735;\n background: #10151e;\n}\n.rf0-dt-action {\n flex: 1;\n padding: 3px 0;\n border: 1px solid #2a3547;\n border-radius: 3px;\n background: #151b26;\n color: #c7d0dc;\n font: inherit;\n font-size: 10px;\n letter-spacing: 0.1em;\n text-transform: uppercase;\n cursor: pointer;\n}\n.rf0-dt-action:hover { border-color: #3b4a61; background: #1a2230; color: #e7edf4; }\n.rf0-dt-action:active { transform: translateY(1px); }\n\n/* ---- collapsed badge ----------------------------------------------- */\n.rf0-dt-badge {\n position: fixed;\n z-index: 2147483000;\n width: 26px;\n height: 26px;\n border: 1px solid #2a3547;\n border-radius: 50%;\n background: #0c1017;\n color: #e2b93b;\n font: inherit;\n font-family: ui-monospace, 'SF Mono', 'Cascadia Code', 'JetBrains Mono',\n Menlo, Consolas, 'Liberation Mono', monospace;\n font-size: 10px;\n font-weight: 700;\n letter-spacing: 0.02em;\n cursor: pointer;\n box-shadow: 0 4px 14px rgba(0, 0, 0, 0.5);\n}\n.rf0-dt-badge:hover { border-color: #e2b93b; }\n.rf0-dt-badge--top-right { top: 10px; right: 10px; }\n.rf0-dt-badge--bottom-right { bottom: 10px; right: 10px; }\n.rf0-dt-badge--top-left { top: 10px; left: 10px; }\n.rf0-dt-badge--bottom-left { bottom: 10px; left: 10px; }\n.rf0-dt-badge .rf0-dt-dot {\n position: absolute;\n top: 3px;\n right: 3px;\n width: 5px;\n height: 5px;\n border-radius: 50%;\n background: #f0647c;\n display: none;\n}\n.rf0-dt-badge--has-errors .rf0-dt-dot { display: block; }\n\n/* ---- submit traces -------------------------------------------------- */\n.rf0-dt-submit { border-bottom: 1px solid #1f2735; }\n.rf0-dt-submit:last-child { border-bottom: none; }\n.rf0-dt-submit-summary {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 4px 6px;\n cursor: pointer;\n list-style: none;\n color: #8b96a5;\n}\n.rf0-dt-submit-summary::-webkit-details-marker { display: none; }\n.rf0-dt-submit-summary:hover { color: #dce3ec; }\n.rf0-dt-submit-n { color: #dce3ec; font-weight: 700; }\n.rf0-dt-submit-time { margin-left: auto; color: #56616f; }\n.rf0-dt-submit[open] .rf0-dt-submit-summary { border-bottom: 1px dashed #1f2735; }\n.rf0-dt-submit-errors { padding: 2px 6px; }\n",document.head.appendChild(e)}();const f=e.useContext(c),h=o??f;if(!h)throw new Error("<Devtools> needs a form: pass the `form` prop or render it inside a <Form> / FormProvider.");const[x,y]=e.useState(!0),[v,E]=e.useState("values"),k=e.useId().replace(/[^a-zA-Z0-9-]/g,""),N=d(h,"change",r.getValues.bind(null,h)),w=d(h,"errors",n.getErrors.bind(null,h)),C=function(e){return d(e,"touched",r.getTouchedFields.bind(null,e))}(h),S=function(e){return d(e,"change",i.bind(null,e))}(h),$=function(e){return d(e,"submitting",()=>e.isSubmitting)}(h),j=function(e){return d(e,"submitCount",()=>e.submitCount)}(h),O=d(h,"submitSuccessful",()=>h.isSubmitSuccessful),[z,F]=e.useState([]);e.useEffect(()=>t.on(h.emitter,"submitting",()=>{h.isSubmitting||queueMicrotask(()=>{h.isSubmitting||0===h.submitCount||F(e=>[{n:h.submitCount,ok:h.isSubmitSuccessful,at:Date.now(),values:r.getValues(h),errors:n.getErrors(h)},...e].slice(0,10))})}),[h]);const[D,V]=e.useState([]);if(e.useEffect(()=>{let e=0;const n=(t,n)=>{e+=1;const r={n:e,event:t,at:Date.now()};void 0!==n&&(r.path=n),V(e=>[r,...e].slice(0,50))},r=[];for(const e of["change","errors","touched","validating"])r.push(t.on(h.emitter,e,t=>n(e,t?t.value.join("."):void 0)));r.push(t.on(h.emitter,"focusError",e=>{try{n("focusError",JSON.parse(e).join("."))}catch{n("focusError",e)}}));for(const e of["submitting","submitCount","submitSuccessful","reset","disabled","status","loading"])r.push(t.on(h.emitter,e,()=>n(e)));return()=>r.forEach(e=>e())},[h]),!x)return s.createElement("button",{type:"button",className:`rf0-dt-badge rf0-dt-badge--${l}${w.length>0?" rf0-dt-badge--has-errors":""}`,"aria-expanded":!1,"aria-label":`Open react-f0rm devtools (${w.length} errors)`,onClick:()=>y(!0)},"f0",s.createElement("span",{className:"rf0-dt-dot"}));const M={values:g(N),errors:w.length,touched:C.length,dirty:Object.keys(S).length,submits:z.length,events:D.length};return s.createElement("section",{className:`rf0-dt rf0-dt--${l}`,"aria-label":"react-f0rm devtools"},s.createElement("header",{className:"rf0-dt-header"},s.createElement("span",{className:"rf0-dt-title"},"react-f0rm"),s.createElement("button",{type:"button",className:"rf0-dt-headerbtn","aria-label":"Collapse devtools",onClick:()=>y(!1)},"–")),s.createElement("div",{className:"rf0-dt-tablist",role:"tablist","aria-label":"Form state",tabIndex:-1,onKeyDown:e=>{const t={ArrowRight:1,ArrowLeft:-1}[e.key];if(!t)return;e.preventDefault();const n=u[(u.indexOf(v)+t+u.length)%u.length];E(n),document.getElementById(`${k}-tab-${n}`)?.focus()}},u.map(e=>s.createElement("button",{key:e,id:`${k}-tab-${e}`,type:"button",role:"tab",className:"rf0-dt-tab"+("errors"===e?" rf0-dt-tab--danger":""),"aria-selected":v===e,"aria-controls":`${k}-panel-${e}`,tabIndex:v===e?0:-1,onClick:()=>E(e)},e,s.createElement("span",{className:"rf0-dt-tab-count"},M[e])))),s.createElement("div",{id:`${k}-panel-${v}`,role:"tabpanel","aria-labelledby":`${k}-tab-${v}`,className:"rf0-dt-panel"},"values"===v&&s.createElement(m,{value:N}),"errors"===v&&(0===w.length?s.createElement("p",{className:"rf0-dt-empty"},"no errors"):w.map(({path:e,type:t,message:n},r)=>s.createElement("div",{key:`${e}:${r}`,className:"rf0-dt-item"},s.createElement("span",{className:"rf0-dt-item-path"},e),s.createElement("span",{className:"rf0-dt-item-msg"},n),s.createElement("span",{className:"rf0-dt-item-tag"},t)))),"touched"===v&&(0===C.length?s.createElement("p",{className:"rf0-dt-empty"},"no touched fields"):C.map(e=>s.createElement("div",{key:e,className:"rf0-dt-item rf0-dt-item--touched"},s.createElement("span",{className:"rf0-dt-item-path"},e)))),"dirty"===v&&(0===Object.keys(S).length?s.createElement("p",{className:"rf0-dt-empty"},"no dirty fields"):Object.keys(S).map(e=>s.createElement("div",{key:e,className:"rf0-dt-item rf0-dt-item--dirty"},s.createElement("span",{className:"rf0-dt-item-path"},e),s.createElement("span",{className:"rf0-dt-item-msg rf0-dt-item-msg--ok"},"changed")))),"submits"===v&&(0===z.length?s.createElement("p",{className:"rf0-dt-empty"},"no submits yet"):z.map(e=>s.createElement("details",{key:`${e.n}-${e.at}`,className:"rf0-dt-submit"},s.createElement("summary",{className:"rf0-dt-submit-summary"},s.createElement("span",{className:"rf0-dt-submit-n"},"#",e.n),s.createElement("span",{className:b(e.ok)},!0===e.ok?"ok":!1===e.ok?"failed":"–"),s.createElement("span",{className:"rf0-dt-submit-time"},new Date(e.at).toLocaleTimeString())),e.errors.length>0&&s.createElement("div",{className:"rf0-dt-submit-errors"},e.errors.map(({path:e,type:t,message:n},r)=>s.createElement("div",{key:`${e}:${r}`,className:"rf0-dt-item"},s.createElement("span",{className:"rf0-dt-item-path"},e),s.createElement("span",{className:"rf0-dt-item-msg"},n),s.createElement("span",{className:"rf0-dt-item-tag"},t)))),s.createElement(m,{value:e.values})))),"events"===v&&(0===D.length?s.createElement("p",{className:"rf0-dt-empty"},"no events yet"):s.createElement(s.Fragment,null,s.createElement("div",null,s.createElement("button",{type:"button",className:"rf0-dt-action",onClick:()=>V([])},"Clear")),D.map(e=>s.createElement("div",{key:`${e.n}:${e.at}`,className:"rf0-dt-item"},s.createElement("span",{className:"rf0-dt-item-tag"},e.event),s.createElement("span",{className:"rf0-dt-item-path"},e.path??"—"),s.createElement("span",{className:"rf0-dt-item-msg rf0-dt-item-msg--ok"},new Date(e.at).toLocaleTimeString())))))),s.createElement("p",{className:"rf0-dt-status","aria-live":"polite"},s.createElement("span",{className:$?"rf0-dt-on":void 0},"submitting ",s.createElement("b",null,String($))),s.createElement("span",null,"submits ",s.createElement("b",null,j)),s.createElement("span",{className:b(O)},"ok"," ",s.createElement("b",null,void 0===O?"–":String(O)))),s.createElement("div",{className:"rf0-dt-actions"},s.createElement("button",{type:"button",className:"rf0-dt-action",onClick:()=>r.reset(h,h.initialValues)},"Reset"),s.createElement("button",{type:"button",className:"rf0-dt-action",onClick:()=>a.trigger(h)},"Validate")))};
|
|
1
|
+
"use strict";var e=require("react"),t=require("@for-fun/event-emitter"),n=require("../errors-TzyWwBfw.cjs.js"),r=require("../values-BbPnLByD.cjs.js"),a=require("../validate-2pX-N1O6.cjs.js");function o(e){var t=Object.create(null);return e&&Object.keys(e).forEach(function(n){if("default"!==n){var r=Object.getOwnPropertyDescriptor(e,n);Object.defineProperty(t,n,r.get?r:{enumerable:!0,get:function(){return e[n]}})}}),t.default=e,Object.freeze(t)}var s=o(e);function l(e){const t={};return function(e,t){for(const[r,a]of e.values){const o=n.segmentsFromKey(r);n.getDirtyBaseline(e,r,o)!==a&&t(o.join("."))}}(e,e=>{t[e]=!0}),t}function i(e){const t=n.getOrCreate(n.dirtyFieldsCaches,e,()=>({version:0,result:l(e)}));if(t.version>0){const n=l(e);(function(e,t){const n=Object.keys(e);return n.length===Object.keys(t).length&&n.every(e=>!0===t[e])})(t.result,n)||(t.result=n),t.version=0}return t.result}function c(n,r,a,o){const s="emitter"in n?n.emitter:n;return function(t,n,r){const a=e.useRef(null);null===a.current&&(a.current={hasValue:!1});const o=a.current,s=e.useRef(n);s.current=n;const l=e.useRef(r);l.current=r;const i=e.useCallback(()=>(o.hasValue||(o.value=s.current(),o.hasValue=!0),o.value),[o]),c=e.useCallback(e=>(o.hasValue=!1,t(()=>{const t=l.current;if(t&&o.hasValue){const n=s.current();if(t(o.value,n))return;return o.value=n,void e()}o.hasValue=!1,e()})),[t,o]);return e.useSyncExternalStore(c,i,i)}(e.useCallback(e=>t.on(s,r,e),[s,r]),a,o)}const d=e.createContext(null);d.Provider;e.createContext(null).Provider;function m({name:t,value:n,depth:r=0}){const[a,o]=e.useState(r<=1),l=12*r,i=void 0===t?null:s.createElement(s.Fragment,null,s.createElement("span",{className:"rf0-dt-key"},String(t)),s.createElement("span",{className:"rf0-dt-punct"},": "));if(null!==n&&"object"==typeof n){const e=Array.isArray(n),t=e?n.map((e,t)=>[t,e]):Object.entries(n),c=e?"[":"{",d=e?"]":"}",u=a?"":`${c}…${d} ${t.length}`;return s.createElement("div",{className:"rf0-dt-row",style:{paddingLeft:l}},s.createElement("button",{type:"button",className:"rf0-dt-node-toggle","aria-expanded":a,onClick:()=>o(!a)},s.createElement("span",{className:"rf0-dt-caret"},a?"▾":"▸"),i,s.createElement("span",{className:"rf0-dt-punct"},a?c:u)),a&&s.createElement(s.Fragment,null,t.map(([e,t])=>s.createElement(m,{key:String(e),name:e,value:t,depth:r+1})),s.createElement("span",{className:"rf0-dt-punct",style:{paddingLeft:l}},d)))}return s.createElement("span",{className:"rf0-dt-row",style:{paddingLeft:l,display:"block"}},i,s.createElement(u,{value:n}))}function u({value:e}){return void 0===e?s.createElement("span",{className:"rf0-dt-null"},"undefined"):null===e?s.createElement("span",{className:"rf0-dt-null"},"null"):"string"==typeof e?s.createElement("span",{className:"rf0-dt-string"},'"',e,'"'):"boolean"==typeof e?s.createElement("span",{className:"rf0-dt-boolean"},String(e)):s.createElement("span",{className:"rf0-dt-number"},String(e))}const f="react-f0rm-devtools-style";const p=["values","errors","touched","dirty","submits","subs","events"],b=["change","errors","touched","validating","submitting","submitCount","submitSuccessful","reset","disabled","status","loading","focusError"];function g(e){if(void 0!==e)return e?"rf0-dt-ok":"rf0-dt-err"}function h(e){return null===e||"object"!=typeof e?1:Object.values(e).reduce((e,t)=>e+h(t),0)}const x={ArrowRight:1,ArrowLeft:-1};function E({tab:e,idPrefix:t,counts:n,onSelect:r}){return s.createElement("div",{className:"rf0-dt-tablist",role:"tablist","aria-label":"Form state",tabIndex:-1,onKeyDown:n=>{const a=x[n.key];if(!a)return;n.preventDefault();const o=p[(p.indexOf(e)+a+p.length)%p.length];r(o),document.getElementById(`${t}-tab-${o}`)?.focus()}},p.map(a=>s.createElement("button",{key:a,id:`${t}-tab-${a}`,type:"button",role:"tab",className:"rf0-dt-tab"+("errors"===a?" rf0-dt-tab--danger":""),"aria-selected":e===a,"aria-controls":`${t}-panel-${a}`,tabIndex:e===a?0:-1,onClick:()=>r(a)},a,s.createElement("span",{className:"rf0-dt-tab-count"},n[a]))))}function v({path:e,type:t,message:n}){return s.createElement("div",{className:"rf0-dt-item"},s.createElement("span",{className:"rf0-dt-item-path"},e),s.createElement("span",{className:"rf0-dt-item-msg"},n),s.createElement("span",{className:"rf0-dt-item-tag"},t))}function y({errors:e}){return 0===e.length?s.createElement("p",{className:"rf0-dt-empty"},"no errors"):s.createElement(s.Fragment,null,e.map(({path:e,type:t,message:n},r)=>s.createElement(v,{key:`${e}:${r}`,path:e,type:t,message:n})))}function k({touched:e}){return 0===e.length?s.createElement("p",{className:"rf0-dt-empty"},"no touched fields"):s.createElement(s.Fragment,null,e.map(e=>s.createElement("div",{key:e,className:"rf0-dt-item rf0-dt-item--touched"},s.createElement("span",{className:"rf0-dt-item-path"},e))))}function N({dirty:e}){const t=Object.keys(e);return 0===t.length?s.createElement("p",{className:"rf0-dt-empty"},"no dirty fields"):s.createElement(s.Fragment,null,t.map(e=>s.createElement("div",{key:e,className:"rf0-dt-item rf0-dt-item--dirty"},s.createElement("span",{className:"rf0-dt-item-path"},e),s.createElement("span",{className:"rf0-dt-item-msg rf0-dt-item-msg--ok"},"changed"))))}function w({submits:e}){return 0===e.length?s.createElement("p",{className:"rf0-dt-empty"},"no submits yet"):s.createElement(s.Fragment,null,e.map(e=>s.createElement(C,{key:`${e.n}-${e.at}`,trace:e})))}function C({trace:e}){return s.createElement("details",{className:"rf0-dt-submit"},s.createElement("summary",{className:"rf0-dt-submit-summary"},s.createElement("span",{className:"rf0-dt-submit-n"},"#",e.n),s.createElement("span",{className:g(e.ok)},void 0===(t=e.ok)?"–":t?"ok":"failed"),s.createElement("span",{className:"rf0-dt-submit-time"},new Date(e.at).toLocaleTimeString())),e.errors.length>0&&s.createElement("div",{className:"rf0-dt-submit-errors"},s.createElement(y,{errors:e.errors})),s.createElement(m,{value:e.values}));var t}function S({events:e,onClear:t}){return 0===e.length?s.createElement("p",{className:"rf0-dt-empty"},"no events yet"):s.createElement(s.Fragment,null,s.createElement("div",null,s.createElement("button",{type:"button",className:"rf0-dt-action",onClick:t},"Clear")),e.map(e=>s.createElement("div",{key:`${e.n}:${e.at}`,className:"rf0-dt-item"},s.createElement("span",{className:"rf0-dt-item-tag"},e.event),s.createElement("span",{className:"rf0-dt-item-path"},e.path??"—"),s.createElement("span",{className:"rf0-dt-item-msg rf0-dt-item-msg--ok"},new Date(e.at).toLocaleTimeString()))))}function j({stats:e}){return s.createElement(s.Fragment,null,b.map(t=>{const n=e[t];return s.createElement("div",{key:t,className:"rf0-dt-item"},s.createElement("span",{className:"rf0-dt-item-tag"},t),s.createElement("span",{className:"rf0-dt-item-path"},n?.last??"—"),s.createElement("span",{className:"rf0-dt-item-msg rf0-dt-item-msg--ok"},n?.count??0))}))}function $({tab:e,values:t,errors:n,touched:r,dirty:a,submits:o,stats:l,events:i,onClearEvents:c}){return"values"===e?s.createElement(m,{value:t}):"errors"===e?s.createElement(y,{errors:n}):"touched"===e?s.createElement(k,{touched:r}):"dirty"===e?s.createElement(N,{dirty:a}):"submits"===e?s.createElement(w,{submits:o}):"subs"===e?s.createElement(j,{stats:l}):s.createElement(S,{events:i,onClear:c})}exports.Devtools=function({form:o,position:l="top-right"}){!function(){if("undefined"==typeof document)return;if(document.getElementById(f))return;const e=document.createElement("style");e.id=f,e.textContent="\n.rf0-dt {\n position: fixed;\n z-index: 2147483000;\n box-sizing: border-box;\n width: 308px;\n max-width: calc(100vw - 16px);\n max-height: min(70vh, 560px);\n display: flex;\n flex-direction: column;\n font-family: ui-monospace, 'SF Mono', 'Cascadia Code', 'JetBrains Mono',\n Menlo, Consolas, 'Liberation Mono', monospace;\n font-size: 11px;\n line-height: 1.45;\n color: #c7d0dc;\n background: #0c1017;\n border: 1px solid #1f2735;\n border-radius: 4px;\n box-shadow: 0 12px 32px rgba(0, 0, 0, 0.55), 0 0 0 1px rgba(0, 0, 0, 0.4);\n}\n.rf0-dt *,\n.rf0-dt-badge * {\n box-sizing: border-box;\n}\n.rf0-dt--top-right { top: 8px; right: 8px; }\n.rf0-dt--bottom-right { bottom: 8px; right: 8px; }\n.rf0-dt--top-left { top: 8px; left: 8px; }\n.rf0-dt--bottom-left { bottom: 8px; left: 8px; }\n\n/* ---- header -------------------------------------------------------- */\n.rf0-dt-header {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 5px 6px 5px 9px;\n border-bottom: 1px solid #1f2735;\n background: #10151e;\n}\n.rf0-dt-title {\n flex: 1;\n min-width: 0;\n color: #8b96a5;\n font-size: 10px;\n font-weight: 700;\n letter-spacing: 0.14em;\n text-transform: uppercase;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.rf0-dt-title::before {\n content: '';\n display: inline-block;\n width: 6px;\n height: 6px;\n margin-right: 6px;\n border-radius: 50%;\n background: #e2b93b;\n vertical-align: 1px;\n}\n.rf0-dt-headerbtn {\n border: 1px solid transparent;\n border-radius: 3px;\n padding: 1px 5px;\n color: #8b96a5;\n background: transparent;\n font: inherit;\n font-size: 10px;\n cursor: pointer;\n}\n.rf0-dt-headerbtn:hover { color: #dce3ec; border-color: #2a3547; }\n.rf0-dt-headerbtn:focus-visible,\n.rf0-dt-tab:focus-visible,\n.rf0-dt-action:focus-visible,\n.rf0-dt-badge:focus-visible,\n.rf0-dt-node-toggle:focus-visible {\n outline: 1px solid #e2b93b;\n outline-offset: 1px;\n}\n\n/* ---- tabs ---------------------------------------------------------- */\n.rf0-dt-tablist {\n display: flex;\n border-bottom: 1px solid #1f2735;\n background: #0e131b;\n}\n.rf0-dt-tab {\n flex: 1;\n padding: 4px 2px 5px;\n border: 0;\n border-bottom: 2px solid transparent;\n background: transparent;\n color: #6b7686;\n font: inherit;\n font-size: 10px;\n letter-spacing: 0.1em;\n text-transform: uppercase;\n cursor: pointer;\n white-space: nowrap;\n}\n.rf0-dt-tab:hover { color: #aab5c4; }\n.rf0-dt-tab[aria-selected='true'] {\n color: #e7edf4;\n border-bottom-color: #e2b93b;\n}\n.rf0-dt-tab-count {\n margin-left: 3px;\n color: inherit;\n opacity: 0.75;\n}\n.rf0-dt-tab--danger[aria-selected='true'] {\n border-bottom-color: #f0647c;\n}\n\n/* ---- panels -------------------------------------------------------- */\n.rf0-dt-panel {\n flex: 1;\n min-height: 84px;\n overflow: auto;\n padding: 6px 8px;\n scrollbar-width: thin;\n scrollbar-color: #2a3547 transparent;\n}\n.rf0-dt-empty {\n padding: 10px 2px;\n color: #4d5766;\n font-style: italic;\n}\n\n/* json tree */\n.rf0-dt-row {\n display: block;\n white-space: pre;\n tab-size: 2;\n}\n.rf0-dt-node-toggle {\n border: 0;\n padding: 0;\n background: transparent;\n color: inherit;\n font: inherit;\n text-align: left;\n cursor: pointer;\n white-space: pre;\n}\n.rf0-dt-node-toggle:hover .rf0-dt-key { color: #dce3ec; }\n.rf0-dt-caret {\n display: inline-block;\n width: 1.2em;\n color: #4d5766;\n}\n.rf0-dt-key { color: #8b96a5; }\n.rf0-dt-punct { color: #4d5766; }\n.rf0-dt-string { color: #8fd68a; }\n.rf0-dt-number { color: #e2b93b; }\n.rf0-dt-boolean { color: #6fb3d9; }\n.rf0-dt-null { color: #55607080; font-style: italic; }\n\n/* errors / touched / dirty lists */\n.rf0-dt-item {\n padding: 3px 2px;\n border-bottom: 1px dotted #1a2230;\n display: flex;\n gap: 8px;\n align-items: baseline;\n}\n.rf0-dt-item:last-child { border-bottom: 0; }\n.rf0-dt-item-path {\n color: #aab5c4;\n word-break: break-all;\n}\n.rf0-dt-item-msg {\n color: #f0647c;\n word-break: break-word;\n}\n.rf0-dt-item-msg--ok { color: #8fd68a; }\n.rf0-dt-item-tag {\n flex: none;\n color: #4d5766;\n font-size: 10px;\n}\n.rf0-dt-item--touched .rf0-dt-item-path { color: #6fb3d9; }\n.rf0-dt-item--dirty .rf0-dt-item-path { color: #e2b93b; }\n\n/* ---- submit status + actions --------------------------------------- */\n.rf0-dt-status {\n display: flex;\n gap: 10px;\n padding: 4px 9px;\n border-top: 1px solid #1f2735;\n background: #10151e;\n color: #6b7686;\n font-size: 10px;\n letter-spacing: 0.04em;\n white-space: nowrap;\n overflow: hidden;\n}\n.rf0-dt-status b { color: #aab5c4; font-weight: 400; }\n.rf0-dt-status .rf0-dt-on { color: #e2b93b; }\n.rf0-dt-status .rf0-dt-ok { color: #8fd68a; }\n.rf0-dt-status .rf0-dt-err { color: #f0647c; }\n.rf0-dt-actions {\n display: flex;\n gap: 6px;\n padding: 6px 8px;\n border-top: 1px solid #1f2735;\n background: #10151e;\n}\n.rf0-dt-action {\n flex: 1;\n padding: 3px 0;\n border: 1px solid #2a3547;\n border-radius: 3px;\n background: #151b26;\n color: #c7d0dc;\n font: inherit;\n font-size: 10px;\n letter-spacing: 0.1em;\n text-transform: uppercase;\n cursor: pointer;\n}\n.rf0-dt-action:hover { border-color: #3b4a61; background: #1a2230; color: #e7edf4; }\n.rf0-dt-action:active { transform: translateY(1px); }\n\n/* ---- collapsed badge ----------------------------------------------- */\n.rf0-dt-badge {\n position: fixed;\n z-index: 2147483000;\n width: 26px;\n height: 26px;\n border: 1px solid #2a3547;\n border-radius: 50%;\n background: #0c1017;\n color: #e2b93b;\n font: inherit;\n font-family: ui-monospace, 'SF Mono', 'Cascadia Code', 'JetBrains Mono',\n Menlo, Consolas, 'Liberation Mono', monospace;\n font-size: 10px;\n font-weight: 700;\n letter-spacing: 0.02em;\n cursor: pointer;\n box-shadow: 0 4px 14px rgba(0, 0, 0, 0.5);\n}\n.rf0-dt-badge:hover { border-color: #e2b93b; }\n.rf0-dt-badge--top-right { top: 10px; right: 10px; }\n.rf0-dt-badge--bottom-right { bottom: 10px; right: 10px; }\n.rf0-dt-badge--top-left { top: 10px; left: 10px; }\n.rf0-dt-badge--bottom-left { bottom: 10px; left: 10px; }\n.rf0-dt-badge .rf0-dt-dot {\n position: absolute;\n top: 3px;\n right: 3px;\n width: 5px;\n height: 5px;\n border-radius: 50%;\n background: #f0647c;\n display: none;\n}\n.rf0-dt-badge--has-errors .rf0-dt-dot { display: block; }\n\n/* ---- submit traces -------------------------------------------------- */\n.rf0-dt-submit { border-bottom: 1px solid #1f2735; }\n.rf0-dt-submit:last-child { border-bottom: none; }\n.rf0-dt-submit-summary {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 4px 6px;\n cursor: pointer;\n list-style: none;\n color: #8b96a5;\n}\n.rf0-dt-submit-summary::-webkit-details-marker { display: none; }\n.rf0-dt-submit-summary:hover { color: #dce3ec; }\n.rf0-dt-submit-n { color: #dce3ec; font-weight: 700; }\n.rf0-dt-submit-time { margin-left: auto; color: #56616f; }\n.rf0-dt-submit[open] .rf0-dt-submit-summary { border-bottom: 1px dashed #1f2735; }\n.rf0-dt-submit-errors { padding: 2px 6px; }\n",document.head.appendChild(e)}();const m=e.useContext(d),u=o??m;if(!u)throw new Error("<Devtools> needs a form: pass the `form` prop or render it inside a <Form> / FormProvider.");const[p,b]=e.useState(!0),[x,v]=e.useState("values"),y=e.useId().replace(/[^a-zA-Z0-9-]/g,""),k=c(u,"change",r.getValues.bind(null,u)),N=c(u,"errors",n.getErrors.bind(null,u)),w=function(e){return c(e,"touched",r.getTouchedFields.bind(null,e))}(u),C=function(e){return c(e,"change",i.bind(null,e))}(u),S=function(e){return c(e,"submitting",()=>e.isSubmitting)}(u),j=function(e){return c(e,"submitCount",()=>e.submitCount)}(u),O=c(u,"submitSuccessful",()=>u.isSubmitSuccessful),[F,z]=e.useState([]);e.useEffect(()=>t.on(u.emitter,"submitting",()=>{u.isSubmitting||queueMicrotask(()=>{u.isSubmitting||0===u.submitCount||z(e=>[{n:u.submitCount,ok:u.isSubmitSuccessful,at:Date.now(),values:r.getValues(u),errors:n.getErrors(u)},...e].slice(0,10))})}),[u]);const[D,V]=e.useState([]),[M,L]=e.useState({});if(e.useEffect(()=>{let e=0;const n=(t,n)=>{e+=1;const r={n:e,event:t,at:Date.now()};void 0!==n&&(r.path=n),V(e=>[r,...e].slice(0,50)),L(e=>{const r=e[t],a={count:(r?.count??0)+1};void 0!==n?a.last=n:void 0!==r?.last&&(a.last=r.last);const o={...e};return o[t]=a,o})},r=[];for(const e of["change","errors","touched","validating","disabled"])r.push(t.on(u.emitter,e,t=>n(e,t?t.value.join("."):void 0)));r.push(t.on(u.emitter,"focusError",e=>{try{n("focusError",JSON.parse(e).join("."))}catch{n("focusError",e)}}));for(const e of["submitting","submitCount","submitSuccessful","reset","status","loading"])r.push(t.on(u.emitter,e,()=>n(e)));return()=>r.forEach(e=>e())},[u]),!p)return s.createElement("button",{type:"button",className:`rf0-dt-badge rf0-dt-badge--${l}${N.length>0?" rf0-dt-badge--has-errors":""}`,"aria-expanded":!1,"aria-label":`Open react-f0rm devtools (${N.length} errors)`,onClick:()=>b(!0)},"f0",s.createElement("span",{className:"rf0-dt-dot"}));const P={values:h(k),errors:N.length,touched:w.length,dirty:Object.keys(C).length,submits:F.length,subs:Object.keys(M).length,events:D.length};return s.createElement("section",{className:`rf0-dt rf0-dt--${l}`,"aria-label":"react-f0rm devtools"},s.createElement("header",{className:"rf0-dt-header"},s.createElement("span",{className:"rf0-dt-title"},"react-f0rm"),s.createElement("button",{type:"button",className:"rf0-dt-headerbtn","aria-label":"Collapse devtools",onClick:()=>b(!1)},"–")),s.createElement(E,{tab:x,idPrefix:y,counts:P,onSelect:v}),s.createElement("div",{id:`${y}-panel-${x}`,role:"tabpanel","aria-labelledby":`${y}-tab-${x}`,className:"rf0-dt-panel"},s.createElement($,{tab:x,values:k,errors:N,touched:w,dirty:C,submits:F,stats:M,events:D,onClearEvents:()=>V([])})),s.createElement("p",{className:"rf0-dt-status","aria-live":"polite"},s.createElement("span",{className:S?"rf0-dt-on":void 0},"submitting ",s.createElement("b",null,String(S))),s.createElement("span",null,"submits ",s.createElement("b",null,j)),s.createElement("span",{className:g(O)},"ok"," ",s.createElement("b",null,void 0===O?"–":String(O)))),s.createElement("div",{className:"rf0-dt-actions"},s.createElement("button",{type:"button",className:"rf0-dt-action",onClick:()=>r.reset(u,u.initialValues)},"Reset"),s.createElement("button",{type:"button",className:"rf0-dt-action",onClick:()=>a.trigger(u)},"Validate")))};
|
|
2
2
|
//# sourceMappingURL=index.cjs.js.map
|