@cleverbrush/react-form 0.0.0-beta-20260908144649 → 0.0.0-beta-20260909084207
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 +11 -0
- package/dist/components.d.ts +1 -1
- package/dist/helpers.d.ts +1 -1
- package/dist/hooks.d.ts +2 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/system.d.ts +12 -8
- package/dist/types.d.ts +2 -2
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -58,6 +58,17 @@ For typed renderer props/variants and managed submission, see the new
|
|
|
58
58
|
[consumer examples and migration guide](../../docs/cache-form-migration.md).
|
|
59
59
|
The provider-based APIs below remain supported.
|
|
60
60
|
|
|
61
|
+
Typed fields and headless `form.useField()` accept properties with schema
|
|
62
|
+
defaults, including enums, booleans, arrays, and nullable values. A default
|
|
63
|
+
does not erase the property's inferred type. Defaults are applied during
|
|
64
|
+
validation; call `form.reset(values)` to establish a visible clean baseline.
|
|
65
|
+
`reset()` still clears the store rather than restoring schema defaults.
|
|
66
|
+
|
|
67
|
+
Shared UI packages can directly export `createFormSystem(...)` results and
|
|
68
|
+
`system.Field` while emitting TypeScript declarations. The named
|
|
69
|
+
`TypedFormSystem` and `TypedFieldComponent` types preserve the registry's
|
|
70
|
+
field/variant/props checks across package boundaries.
|
|
71
|
+
|
|
61
72
|
```tsx
|
|
62
73
|
import { object, string, number } from '@cleverbrush/schema';
|
|
63
74
|
import { useSchemaForm, FormSystemProvider, Field } from '@cleverbrush/react-form';
|
package/dist/components.d.ts
CHANGED
|
@@ -45,7 +45,7 @@ export declare function FormProvider<TSchema extends ObjectSchemaBuilder<any, an
|
|
|
45
45
|
* const name = useField<typeof MySchema>((t) => t.name);
|
|
46
46
|
* ```
|
|
47
47
|
*/
|
|
48
|
-
export declare function useField<TSchema extends ObjectSchemaBuilder<any, any, any>, TPropertySchema extends SchemaBuilder<any, any, any> =
|
|
48
|
+
export declare function useField<TSchema extends ObjectSchemaBuilder<any, any, any>, TPropertySchema extends SchemaBuilder<any, any, any, any> = any>(forProperty: (tree: PropertyDescriptorTree<TSchema, TSchema>) => PropertyDescriptor<TSchema, TPropertySchema, any>): UseFieldResult<InferType<TPropertySchema>>;
|
|
49
49
|
/**
|
|
50
50
|
* Hook to access FormSystem configuration.
|
|
51
51
|
*/
|
package/dist/helpers.d.ts
CHANGED
|
@@ -12,7 +12,7 @@ export declare function getDescriptorPath(inner: PropertyDescriptorInner<any, an
|
|
|
12
12
|
/**
|
|
13
13
|
* Returns the schema type string (e.g. "string", "number", "object").
|
|
14
14
|
*/
|
|
15
|
-
export declare function getSchemaType(schema: SchemaBuilder<any, any, any>): string;
|
|
15
|
+
export declare function getSchemaType(schema: SchemaBuilder<any, any, any, any>): string;
|
|
16
16
|
/**
|
|
17
17
|
* Builds a selector function from a dot-separated path string.
|
|
18
18
|
* The selector traverses the PropertyDescriptorTree by property access.
|
package/dist/hooks.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import type { FormContextValue } from './contexts.js';
|
|
|
4
4
|
import type { FieldRenderer, FormSubmissionState, FormSubmitHandler, FormSubmitOptions, FormSubmitResult, FormSystemConfig, UseFieldResult, UseSchemaFormOptions } from './types.js';
|
|
5
5
|
/** A stable form controller with reactive field and submission subscriptions. */
|
|
6
6
|
export type SchemaFormInstance<TSchema extends ObjectSchemaBuilder<any, any, any>> = {
|
|
7
|
-
useField: <TPropertySchema extends SchemaBuilder<any, any, any>>(forProperty: (tree: PropertyDescriptorTree<TSchema, TSchema>) => PropertyDescriptor<TSchema, TPropertySchema, any>) => UseFieldResult<InferType<TPropertySchema>>;
|
|
7
|
+
useField: <TPropertySchema extends SchemaBuilder<any, any, any, any>>(forProperty: (tree: PropertyDescriptorTree<TSchema, TSchema>) => PropertyDescriptor<TSchema, TPropertySchema, any>) => UseFieldResult<InferType<TPropertySchema>>;
|
|
8
8
|
submit: () => Promise<ValidationResult<InferType<TSchema>>>;
|
|
9
9
|
validate: () => Promise<ValidationResult<InferType<TSchema>>>;
|
|
10
10
|
/** Clear values, or establish supplied values as the new clean baseline. */
|
|
@@ -23,4 +23,4 @@ export declare function useSchemaForm<TSchema extends ObjectSchemaBuilder<any, a
|
|
|
23
23
|
/** Internal field binding shared by direct and context-based hooks. */
|
|
24
24
|
export declare function useFieldFromContext(formContext: FormContextValue, forProperty: (tree: any) => any, triggerValidation?: ((markTouched: boolean) => Promise<unknown>) | undefined): UseFieldResult;
|
|
25
25
|
/** Resolve type:variant first, falling back to the base type. */
|
|
26
|
-
export declare function resolveRenderer(config: FormSystemConfig | null, schema: SchemaBuilder<any, any, any>, variant?: string): FieldRenderer | undefined;
|
|
26
|
+
export declare function resolveRenderer(config: FormSystemConfig | null, schema: SchemaBuilder<any, any, any, any>, variant?: string): FieldRenderer | undefined;
|
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,6 @@ export type { FieldProps, FormProviderProps, FormSystemProviderProps } from './c
|
|
|
2
2
|
export { Field, FormProvider, FormSystemProvider, useField, useFormSystem } from './components.js';
|
|
3
3
|
export type { SchemaFormInstance } from './hooks.js';
|
|
4
4
|
export { useSchemaForm } from './hooks.js';
|
|
5
|
-
export type { TypedFieldProps, TypedFieldRenderer, TypedRendererRegistry } from './system.js';
|
|
5
|
+
export type { TypedFieldComponent, TypedFieldProps, TypedFieldRenderer, TypedFormSystem, TypedRendererRegistry } from './system.js';
|
|
6
6
|
export { createFormSystem, defineFieldRenderer } from './system.js';
|
|
7
7
|
export type { FieldRenderer, FieldRenderProps, FieldState, FormSubmissionState, FormSubmitHandler, FormSubmitOptions, FormSubmitResult, FormSystemConfig, UseFieldResult, UseSchemaFormOptions } from './types.js';
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{useContext as H,useMemo as ye}from"react";import{createContext as X}from"react";var
|
|
1
|
+
import{useContext as H,useMemo as ye}from"react";import{createContext as X}from"react";var N=X(null),G=X(null);import{ObjectSchemaBuilder as ee,SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR as Z}from"@cleverbrush/schema";function J(n,o){let i=new Map,e=o.introspect();if(!e.properties)return i;for(let s of Object.keys(e.properties)){let a=n[s];if(!a||!(Z in a))continue;let m=a[Z];i.set(m,s);let r=e.properties[s];if(r instanceof ee){let p=J(a,r);for(let[y,l]of p)i.set(y,`${s}.${l}`)}}return i}function O(n){return n.introspect()?.type??"unknown"}function W(n,o){let i=o.introspect();if(!i.properties)return n??{};let e=n!=null?{...n}:{};for(let s of Object.keys(i.properties)){let a=i.properties[s];a instanceof ee&&(e[s]=W(e[s],a))}return e}import{ObjectSchemaBuilder as me,SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR as le}from"@cleverbrush/schema";import{useCallback as f,useEffect as ne,useMemo as oe,useRef as h,useSyncExternalStore as se}from"react";import{deepClone as w,deepEqual as re}from"@cleverbrush/deep";function te(n){let o=w(n??{}),i=o,e=0,s={submitting:!1,error:void 0},a=new Map,m=new Map,r=new Map,p=new Set;function y(t,u){let d=t?.getValue(u);return d?.success?d.value:void 0}function l(t){if(!m.has(t)){let u=a.get(t),d=y(u,o),c=y(u,i);m.set(t,{value:d,initialValue:c,dirty:!re(d,c),touched:!1,error:void 0,validating:!1})}return m.get(t)}function F(t,u){return a.has(t)||a.set(t,u),l(t)}function g(t){for(let u of r.get(t)??[])u()}function b(){for(let t of r.keys())g(t);for(let t of p)t()}function v(t,u){let d=l(t);Object.entries(u).every(([c,S])=>Object.is(d[c],S))||(m.set(t,{...d,...u}),g(t))}function T(t){for(let[u,d]of a){let c=y(d,o),S=y(d,i);v(u,{value:c,initialValue:S,dirty:!re(c,S),validating:!1,...t?{touched:!1,error:void 0}:{}})}}function P(t,u){let d=r.get(t);return d||(d=new Set,r.set(t,d)),d.add(u),()=>{d.delete(u),d.size===0&&r.delete(t)}}function C(t){return p.add(t),()=>{p.delete(t)}}function E(){return s}function I(t){let u={...s,...t};if(!(u.submitting===s.submitting&&u.error===s.error)){s=u;for(let d of p)d()}}function k(){return o}function _(){return e}function B(t){o=w(t??{}),e++,T(!1)}function A(t,u,d){let c=w(o);a.get(t)?.setValue(c,w(u),{createMissingStructure:d})&&B(c)}function U(t){o=w(t??{}),i=o,e++,T(!0),I({error:void 0})}function j(){return Array.from(a.keys())}return{registerField:F,getFieldState:l,updateFieldState:v,subscribe:P,subscribeGlobal:C,getValues:k,setValues:B,setFieldValue:A,resetAll:U,getAllFieldPaths:j,getRevision:_,getSubmissionState:E,setSubmissionState:I,notifyAll:b}}function pe(n,o){let i=h(null);i.current||(i.current=te({}));let e=i.current,s=h(null);s.current||(s.current=me.getPropertiesFor(n));let a=s.current,m=h(null);m.current||(m.current=J(a,n));let r=m.current;for(let[c]of r)e.registerField(c.toJsonPointer(),c);let p=h(n),y=h({});y.current={createMissingStructure:!0,...o};let l=h(!0),F=h(0),g=h(0),b=h(!1),v=h(null),T=f(()=>{v.current!==null&&clearTimeout(v.current),v.current=null},[]);ne(()=>(l.current=!0,()=>{l.current=!1,F.current++,g.current++,T()}),[T]);let P=f(async c=>{T();let S=++g.current,Y=e.getRevision();for(let x of e.getAllFieldPaths())e.updateFieldState(x,{validating:!0});let K=W(e.getValues(),p.current),R;try{R=await p.current.validateAsync(K,{doNotStopOnFirstError:!0})}catch{R={valid:!1}}if(!l.current||S!==g.current||Y!==e.getRevision())return R;for(let x of e.getAllFieldPaths())e.updateFieldState(x,{error:void 0,validating:!1,...c?{touched:!0}:{}});let $=R.getErrorsFor;if(typeof $=="function")for(let[x]of r){let M=x.toJsonPointer(),V=M.slice(1).split("/").map(D=>D.replace(/~1/g,"/").replace(/~0/g,"~"));try{let D=$(L=>V.reduce((ue,de)=>ue?.[de],L));Array.isArray(D?.errors)&&D.errors.length&&e.updateFieldState(M,{error:D.errors[0]})}catch{}}return R},[T,e,r]),C=f(()=>P(!0),[P]),E=f(()=>C(),[C]),I=f(c=>{F.current++,g.current++,T(),e.resetAll(c)},[e,T]),k=f(()=>e.getValues(),[e]),_=f(c=>{T(),e.setValues({...e.getValues(),...c})},[e,T]),B=f(c=>{T();let S=y.current.validationDebounceMs;return S!=null&&S>0?(v.current=setTimeout(()=>{v.current=null,P(c)},S),Promise.resolve()):P(c)},[P,T]),A=f((c,S)=>async Y=>{if(Y?.preventDefault(),b.current||!l.current)return;b.current=!0;let K=F.current,R=()=>l.current&&K===F.current;e.setSubmissionState({submitting:!0,error:void 0});try{let $=e.getRevision(),x=await P(!0);if(!R()||$!==e.getRevision()||!x.valid||x.object===void 0)return;let M=x.object,V;try{V=await c(M)}catch(D){if(!R())return;if(!S?.onError)throw D;let L=await S.onError(D);R()&&e.setSubmissionState({error:L});return}if(!R())return;if(V&&!V.ok){e.setSubmissionState({error:V.error});return}await S?.onSuccess?.(V?.data,M)}finally{b.current=!1,l.current&&e.setSubmissionState({submitting:!1})}},[P,e]),U=oe(()=>({store:e,descriptorTree:a,schema:p.current,pathMap:r,get options(){return y.current},triggerValidation:B}),[e,a,r,B]),j=h(U);j.current=U;let t=f(()=>j.current,[]),u=f(c=>q(j.current,c),[]),d=h(o?.validateOnMount);return ne(()=>{d.current&&P(!0)},[P]),se(e.subscribeGlobal,e.getSubmissionState,e.getSubmissionState),oe(()=>({useField:u,submit:E,validate:C,reset:I,getValue:k,setValue:_,handleSubmit:A,_getFormContext:t,get submitting(){return e.getSubmissionState().submitting},get error(){return e.getSubmissionState().error}}),[u,E,C,I,k,_,A,t,e])}function q(n,o,i=n.triggerValidation){let{store:e,descriptorTree:s,options:a}=n,m=o(s)[le],r=m.toJsonPointer();e.registerField(r,m);let p=f(b=>e.subscribe(r,b),[e,r]),y=f(()=>e.getFieldState(r),[e,r]),l=se(p,y,y),F=f(b=>{e.setFieldValue(r,b,a.createMissingStructure!==!1),i?.(!1)},[e,r,a.createMissingStructure,i]),g=f(()=>e.updateFieldState(r,{touched:!0}),[e,r]);return{...l,onChange:F,onBlur:g,setValue:F,schema:m.getSchema()}}function ie(n,o,i){if(!n?.renderers)return;let e=O(o);return(i?n.renderers[`${e}:${i}`]:void 0)??n.renderers[e]}import{jsx as ae}from"react/jsx-runtime";function z({renderers:n,config:o,children:i}){let e=H(N),s=ye(()=>{let a={...o,renderers:{...o?.renderers,...n}};return e?{...e,...a,renderers:{...e.renderers,...a.renderers}}:a},[e,o,n]);return ae(N.Provider,{value:s,children:i})}function fe({form:n,children:o}){let i=n._getFormContext();return ae(G.Provider,{value:i,children:o})}function Se(n){let o=H(G);if(!o)throw new Error("useField must be used within a FormProvider. Wrap your component tree with <FormProvider form={form}>.");return q(o,n)}function Te(){let n=H(N);if(!n)throw new Error("useFormSystem must be used within a FormSystemProvider");return n}function Q({forProperty:n,form:o,renderer:i,variant:e,label:s,name:a,fieldProps:m}){let r=o.useField(n),p=H(N),y=i??ie(p,r.schema,e);if(!y){let l=O(r.schema),F=e?`"${l}:${e}" or "${l}"`:`"${l}"`;throw new Error(`No renderer found for schema type ${F}. Provide a renderer prop or configure one in FormSystemProvider.`)}return y({value:r.value,initialValue:r.initialValue,dirty:r.dirty,touched:r.touched,error:r.error,validating:r.validating,onChange:r.onChange,onBlur:r.onBlur,setValue:r.setValue,schema:r.schema,variant:e,label:s,name:a,fieldProps:m})}import{SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR as he}from"@cleverbrush/schema";import{jsx as ce}from"react/jsx-runtime";function Fe(n){return n}function Pe(n){let o=Object.freeze({...n.renderers});function i(s){let a=s.forProperty(s.form._getFormContext().descriptorTree),m=O(a[he].getSchema()),r=s.variant?`${m}:${s.variant}`:m,p=o[r];if(!p)throw new Error(`No renderer registered for "${r}" in this form system.`);return ce(Q,{...s,renderer:p})}function e({children:s}){return ce(z,{renderers:o,children:s})}return{Field:i,Provider:e,renderers:o}}export{Q as Field,fe as FormProvider,z as FormSystemProvider,Pe as createFormSystem,Fe as defineFieldRenderer,Se as useField,Te as useFormSystem,pe as useSchemaForm};
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components.tsx","../src/contexts.ts","../src/helpers.ts","../src/hooks.ts","../src/FormStore.ts","../src/system.tsx"],"sourcesContent":["import type {\n InferType,\n ObjectSchemaBuilder,\n PropertyDescriptor,\n PropertyDescriptorTree,\n SchemaBuilder\n} from '@cleverbrush/schema';\nimport type React from 'react';\nimport { useContext, useMemo } from 'react';\nimport { FormContext, FormSystemContext } from './contexts.js';\nimport { getSchemaType } from './helpers.js';\nimport type { SchemaFormInstance } from './hooks.js';\nimport { resolveRenderer, useFieldFromContext } from './hooks.js';\nimport type {\n FieldRenderer,\n FormSystemConfig,\n UseFieldResult\n} from './types.js';\n\n// ─── FormSystemProvider ──────────────────────────────────────────────────────\n\nexport type FormSystemProviderProps = {\n /**\n * Renderer registry mapping schema types to renderer functions.\n * Example: `{ string: (props) => <input .../>, number: (props) => <input type=\"number\" .../> }`\n */\n renderers?: Record<string, FieldRenderer>;\n /**\n * Full configuration object (for future extensibility).\n * If both `renderers` and `config.renderers` are provided, `renderers` takes precedence.\n */\n config?: FormSystemConfig;\n children: React.ReactNode;\n};\n\n/**\n * Provides global renderer configuration via React Context.\n * Supports nesting — inner provider overrides outer.\n *\n * @example\n * ```tsx\n * <FormSystemProvider renderers={htmlRenderers}>\n * <App />\n * </FormSystemProvider>\n * ```\n */\nexport function FormSystemProvider({\n renderers,\n config,\n children\n}: FormSystemProviderProps): React.ReactNode {\n const parentConfig = useContext(FormSystemContext);\n\n const resolvedConfig: FormSystemConfig = useMemo(() => {\n const current: FormSystemConfig = {\n ...config,\n renderers: {\n ...config?.renderers,\n ...renderers\n }\n };\n if (!parentConfig) return current;\n return {\n ...parentConfig,\n ...current,\n renderers: {\n ...parentConfig.renderers,\n ...current.renderers\n }\n };\n }, [parentConfig, config, renderers]);\n\n return (\n <FormSystemContext.Provider value={resolvedConfig}>\n {children}\n </FormSystemContext.Provider>\n );\n}\n\n// ─── FormProvider ────────────────────────────────────────────────────────────\n\nexport type FormProviderProps<\n TSchema extends ObjectSchemaBuilder<any, any, any>\n> = {\n form: SchemaFormInstance<TSchema>;\n children: React.ReactNode;\n};\n\n/**\n * Provides form context to children so they can use the context-based useField.\n */\nexport function FormProvider<\n TSchema extends ObjectSchemaBuilder<any, any, any>\n>({ form, children }: FormProviderProps<TSchema>): React.ReactNode {\n const formContext = form._getFormContext();\n return (\n <FormContext.Provider value={formContext}>\n {children}\n </FormContext.Provider>\n );\n}\n\n// ─── Context-based useField ──────────────────────────────────────────────────\n\n/**\n * Context-based useField — can be used inside a FormProvider.\n * For best IntelliSense, prefer `form.useField()` which infers field types from the schema.\n * When using this context-based version, specify the schema type explicitly:\n *\n * @example\n * ```tsx\n * const name = useField<typeof MySchema>((t) => t.name);\n * ```\n */\nexport function useField<\n TSchema extends ObjectSchemaBuilder<any, any, any>,\n TPropertySchema extends SchemaBuilder<any, any, any> = SchemaBuilder<\n any,\n any,\n any\n >\n>(\n forProperty: (\n tree: PropertyDescriptorTree<TSchema, TSchema>\n ) => PropertyDescriptor<TSchema, TPropertySchema, any>\n): UseFieldResult<InferType<TPropertySchema>> {\n const formContext = useContext(FormContext);\n if (!formContext) {\n throw new Error(\n 'useField must be used within a FormProvider. ' +\n 'Wrap your component tree with <FormProvider form={form}>.'\n );\n }\n return useFieldFromContext(formContext, forProperty) as UseFieldResult<\n InferType<TPropertySchema>\n >;\n}\n\n// ─── useFormSystem ───────────────────────────────────────────────────────────\n\n/**\n * Hook to access FormSystem configuration.\n */\nexport function useFormSystem(): FormSystemConfig {\n const config = useContext(FormSystemContext);\n if (!config) {\n throw new Error(\n 'useFormSystem must be used within a FormSystemProvider'\n );\n }\n return config;\n}\n\n// ─── Field Component ─────────────────────────────────────────────────────────\n\nexport type FieldProps<TSchema extends ObjectSchemaBuilder<any, any, any>> = {\n forProperty: (\n tree: PropertyDescriptorTree<TSchema, TSchema>\n ) => PropertyDescriptor<TSchema, any, any>;\n form: SchemaFormInstance<TSchema>;\n renderer?: FieldRenderer;\n /**\n * Rendering variant hint. Participates in renderer resolution:\n * the registry is checked for `\"type:variant\"` (e.g. `\"string:password\"`)\n * before falling back to the base `\"type\"` key.\n * Also forwarded to the renderer via `FieldRenderProps.variant`.\n */\n variant?: string;\n /** Visible label text forwarded to the renderer via `FieldRenderProps.label`. */\n label?: string;\n /** HTML `name` attribute forwarded to the renderer via `FieldRenderProps.name`. */\n name?: string;\n /**\n * Bag of extra renderer-specific props forwarded to the renderer via\n * `FieldRenderProps.fieldProps` (e.g. `placeholder`, `autoComplete`).\n */\n fieldProps?: Record<string, unknown>;\n};\n\n/**\n * UI-agnostic Field component.\n *\n * Resolves a renderer from:\n * 1. Explicit `renderer` prop\n * 2. FormSystemProvider registry — checked for `\"type:variant\"` first,\n * then for the base `\"type\"`\n *\n * All rendering hints (`variant`, `label`, `name`, `fieldProps`) are\n * forwarded to the resolved renderer via `FieldRenderProps`.\n *\n * @example\n * ```tsx\n * <Field forProperty={(t) => t.password} form={form}\n * variant=\"password\" label=\"Password\"\n * fieldProps={{ placeholder: \"Enter password\", autoComplete: \"current-password\" }} />\n * ```\n */\nexport function Field<TSchema extends ObjectSchemaBuilder<any, any, any>>({\n forProperty,\n form,\n renderer,\n variant,\n label,\n name,\n fieldProps\n}: FieldProps<TSchema>): React.ReactNode {\n const fieldResult = form.useField(forProperty);\n const systemConfig = useContext(FormSystemContext);\n\n const resolvedRenderer =\n renderer ?? resolveRenderer(systemConfig, fieldResult.schema, variant);\n\n if (!resolvedRenderer) {\n const schemaType = getSchemaType(fieldResult.schema);\n const tried = variant\n ? `\"${schemaType}:${variant}\" or \"${schemaType}\"`\n : `\"${schemaType}\"`;\n throw new Error(\n `No renderer found for schema type ${tried}. ` +\n 'Provide a renderer prop or configure one in FormSystemProvider.'\n );\n }\n\n return resolvedRenderer({\n value: fieldResult.value,\n initialValue: fieldResult.initialValue,\n dirty: fieldResult.dirty,\n touched: fieldResult.touched,\n error: fieldResult.error,\n validating: fieldResult.validating,\n onChange: fieldResult.onChange,\n onBlur: fieldResult.onBlur,\n setValue: fieldResult.setValue,\n schema: fieldResult.schema,\n variant,\n label,\n name,\n fieldProps\n });\n}\n","import type {\n ObjectSchemaBuilder,\n PropertyDescriptorInner,\n PropertyDescriptorTree\n} from '@cleverbrush/schema';\nimport { createContext } from 'react';\nimport type { FormStore } from './FormStore.js';\nimport type { FormSystemConfig, UseSchemaFormOptions } from './types.js';\n\n/**\n * Context for global form system configuration (renderers, etc).\n */\nexport const FormSystemContext = createContext<FormSystemConfig | null>(null);\n\n/**\n * Internal form context value — used to bridge useSchemaForm store\n * to the context-based useField and Field component.\n */\nexport type FormContextValue = {\n store: FormStore;\n descriptorTree: PropertyDescriptorTree<any, any>;\n schema: ObjectSchemaBuilder<any, any, any>;\n options: UseSchemaFormOptions;\n pathMap: Map<PropertyDescriptorInner<any, any, any>, string>;\n triggerValidation?: (markTouched: boolean) => Promise<unknown>;\n};\n\n/**\n * Context for per-form data — allows useField to work via context.\n */\nexport const FormContext = createContext<FormContextValue | null>(null);\n","import type {\n PropertyDescriptorInner,\n PropertyDescriptorTree,\n SchemaBuilder\n} from '@cleverbrush/schema';\nimport {\n ObjectSchemaBuilder,\n SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR\n} from '@cleverbrush/schema';\n\n/**\n * Builds a map from PropertyDescriptorInner identity → dot-separated path\n * by traversing the descriptor tree recursively.\n */\nexport function buildDescriptorPathMap(\n tree: PropertyDescriptorTree<any, any>,\n schema: ObjectSchemaBuilder<any, any, any>\n): Map<PropertyDescriptorInner<any, any, any>, string> {\n const map = new Map<PropertyDescriptorInner<any, any, any>, string>();\n const introspected = schema.introspect();\n if (!introspected.properties) return map;\n\n for (const propName of Object.keys(introspected.properties)) {\n const propDescriptor = (tree as any)[propName];\n if (\n !propDescriptor ||\n !(SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR in propDescriptor)\n ) {\n continue;\n }\n const inner = propDescriptor[\n SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR\n ] as PropertyDescriptorInner<any, any, any>;\n map.set(inner, propName);\n\n // Recurse into nested objects\n const propSchema = introspected.properties[propName];\n if (propSchema instanceof ObjectSchemaBuilder) {\n const childMap = buildDescriptorPathMap(propDescriptor, propSchema);\n for (const [childInner, childPath] of childMap) {\n map.set(childInner, `${propName}.${childPath}`);\n }\n }\n }\n\n return map;\n}\n\n/**\n * Looks up the path for a given descriptor from the pre-built map.\n */\nexport function getDescriptorPath(\n inner: PropertyDescriptorInner<any, any, any>,\n pathMap: Map<PropertyDescriptorInner<any, any, any>, string>\n): string {\n return pathMap.get(inner) ?? '';\n}\n\n/**\n * Returns the schema type string (e.g. \"string\", \"number\", \"object\").\n */\nexport function getSchemaType(schema: SchemaBuilder<any, any, any>): string {\n const introspected = schema.introspect();\n return introspected?.type ?? 'unknown';\n}\n\n/**\n * Builds a selector function from a dot-separated path string.\n * The selector traverses the PropertyDescriptorTree by property access.\n * Example: \"customer.address.city\" → (tree) => tree.customer.address.city\n */\nexport function buildSelectorFromPath(path: string): (tree: any) => any {\n const parts = path.split('.');\n return (tree: any) => {\n let current = tree;\n for (const part of parts) {\n if (current == null) return undefined;\n current = current[part];\n }\n return current;\n };\n}\n\n/**\n * Checks whether a validation error path matches a field's expected error path.\n * Matches exact path, path with nested suffix, or path with validator suffix.\n * Example: isErrorPathMatch(\"$.user.name\", \"$.user.name\") → true\n * isErrorPathMatch(\"$.user.name($validators[0])\", \"$.user.name\") → true\n */\nexport function isErrorPathMatch(\n errPath: string,\n fieldErrorPath: string\n): boolean {\n return (\n errPath === fieldErrorPath ||\n errPath.startsWith(fieldErrorPath + '.') ||\n errPath.startsWith(fieldErrorPath + '(')\n );\n}\n\n/**\n * Ensures all nested object structures exist in the values object\n * by traversing the schema and creating empty objects where needed.\n * This prevents ObjectSchemaBuilder.validate() from throwing when\n * nested object properties are undefined.\n *\n * Example: ensureNestedStructure({}, OrderSchema)\n * → { customer: { address: {} } }\n */\nexport function ensureNestedStructure(\n values: any,\n schema: ObjectSchemaBuilder<any, any, any>\n): any {\n const introspected = schema.introspect();\n if (!introspected.properties) return values != null ? values : {};\n\n const result = values != null ? { ...values } : {};\n for (const key of Object.keys(introspected.properties)) {\n const propSchema = introspected.properties[key];\n if (propSchema instanceof ObjectSchemaBuilder) {\n result[key] = ensureNestedStructure(result[key], propSchema);\n }\n }\n return result;\n}\n","import type {\n InferType,\n PropertyDescriptor,\n PropertyDescriptorInner,\n PropertyDescriptorTree,\n SchemaBuilder,\n ValidationResult\n} from '@cleverbrush/schema';\nimport {\n ObjectSchemaBuilder,\n SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR\n} from '@cleverbrush/schema';\nimport {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useSyncExternalStore\n} from 'react';\nimport type { FormContextValue } from './contexts.js';\nimport type { FormStore } from './FormStore.js';\nimport { createFormStore } from './FormStore.js';\nimport {\n buildDescriptorPathMap,\n ensureNestedStructure,\n getSchemaType\n} from './helpers.js';\nimport type {\n FieldRenderer,\n FormSubmissionState,\n FormSubmitHandler,\n FormSubmitOptions,\n FormSubmitResult,\n FormSystemConfig,\n UseFieldResult,\n UseSchemaFormOptions\n} from './types.js';\n\n/** A stable form controller with reactive field and submission subscriptions. */\nexport type SchemaFormInstance<\n TSchema extends ObjectSchemaBuilder<any, any, any>\n> = {\n useField: <TPropertySchema extends SchemaBuilder<any, any, any>>(\n forProperty: (\n tree: PropertyDescriptorTree<TSchema, TSchema>\n ) => PropertyDescriptor<TSchema, TPropertySchema, any>\n ) => UseFieldResult<InferType<TPropertySchema>>;\n submit: () => Promise<ValidationResult<InferType<TSchema>>>;\n validate: () => Promise<ValidationResult<InferType<TSchema>>>;\n /** Clear values, or establish supplied values as the new clean baseline. */\n reset: (values?: Partial<InferType<TSchema>>) => void;\n /** Read the current snapshot. Use setters rather than mutating it. */\n getValue: () => InferType<TSchema>;\n /** Shallow-merge values without marking fields touched. */\n setValue: (values: Partial<InferType<TSchema>>) => void;\n /** Validate and submit once; repeated calls while pending are ignored. */\n handleSubmit: <TData = void>(\n onValid: (\n values: InferType<TSchema>\n ) => FormSubmitResult<TData> | Promise<FormSubmitResult<TData>>,\n options?: FormSubmitOptions<InferType<TSchema>, TData>\n ) => FormSubmitHandler;\n /** @internal — Used by FormProvider and Field to access internal context. */\n _getFormContext: () => FormContextValue;\n} & FormSubmissionState;\n\n/** Bind a schema to independently subscribed fields and a stable form instance. */\nexport function useSchemaForm<\n TSchema extends ObjectSchemaBuilder<any, any, any>\n>(\n schema: TSchema,\n options?: UseSchemaFormOptions\n): SchemaFormInstance<TSchema> {\n const storeRef = useRef<FormStore | null>(null);\n if (!storeRef.current) storeRef.current = createFormStore({});\n const store = storeRef.current;\n const descriptorTreeRef = useRef<PropertyDescriptorTree<\n TSchema,\n TSchema\n > | null>(null);\n if (!descriptorTreeRef.current) {\n descriptorTreeRef.current = ObjectSchemaBuilder.getPropertiesFor(\n schema\n ) as PropertyDescriptorTree<TSchema, TSchema>;\n }\n const descriptorTree = descriptorTreeRef.current;\n const pathMapRef = useRef<Map<\n PropertyDescriptorInner<any, any, any>,\n string\n > | null>(null);\n if (!pathMapRef.current) {\n pathMapRef.current = buildDescriptorPathMap(descriptorTree, schema);\n }\n const pathMap = pathMapRef.current;\n for (const [descriptor] of pathMap) {\n store.registerField(descriptor.toJsonPointer(), descriptor);\n }\n const schemaRef = useRef(schema);\n const optionsRef = useRef<UseSchemaFormOptions>({});\n optionsRef.current = { createMissingStructure: true, ...options };\n const mountedRef = useRef(true);\n const epochRef = useRef(0);\n const validationGenRef = useRef(0);\n const submissionLockRef = useRef(false);\n const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const cancelScheduledValidation = useCallback(() => {\n if (timerRef.current !== null) clearTimeout(timerRef.current);\n timerRef.current = null;\n }, []);\n useEffect(() => {\n mountedRef.current = true;\n return () => {\n mountedRef.current = false;\n epochRef.current++;\n validationGenRef.current++;\n cancelScheduledValidation();\n };\n }, [cancelScheduledValidation]);\n\n const runValidation = useCallback(\n async (\n markTouched: boolean\n ): Promise<ValidationResult<InferType<TSchema>>> => {\n cancelScheduledValidation();\n const gen = ++validationGenRef.current;\n const revision = store.getRevision();\n for (const path of store.getAllFieldPaths()) {\n store.updateFieldState(path, { validating: true });\n }\n const safeValues = ensureNestedStructure(\n store.getValues(),\n schemaRef.current\n );\n let result: ValidationResult<InferType<TSchema>>;\n try {\n result = (await schemaRef.current.validateAsync(safeValues, {\n doNotStopOnFirstError: true\n })) as ValidationResult<InferType<TSchema>>;\n } catch {\n result = { valid: false } as ValidationResult<\n InferType<TSchema>\n >;\n }\n // A value update invalidates validation immediately, even while the next\n // validation is only scheduled (debounced) and has not started yet.\n if (\n !mountedRef.current ||\n gen !== validationGenRef.current ||\n revision !== store.getRevision()\n )\n return result;\n\n for (const path of store.getAllFieldPaths()) {\n store.updateFieldState(path, {\n error: undefined,\n validating: false,\n ...(markTouched ? { touched: true } : {})\n });\n }\n const getErrorsFor = (result as any).getErrorsFor;\n if (typeof getErrorsFor === 'function') {\n for (const [descriptor] of pathMap) {\n const path = descriptor.toJsonPointer();\n const parts = path\n .slice(1)\n .split('/')\n .map(part =>\n part.replace(/~1/g, '/').replace(/~0/g, '~')\n );\n try {\n const field = getErrorsFor((tree: any) =>\n parts.reduce(\n (value: any, key) => value?.[key],\n tree\n )\n );\n if (\n Array.isArray(field?.errors) &&\n field.errors.length\n ) {\n store.updateFieldState(path, {\n error: field.errors[0]\n });\n }\n } catch {\n // A missing error selector must not prevent other fields\n // from receiving their validation results.\n }\n }\n }\n return result;\n },\n [cancelScheduledValidation, store, pathMap]\n );\n\n const validate = useCallback(() => runValidation(true), [runValidation]);\n const submit = useCallback(() => validate(), [validate]);\n const reset = useCallback(\n (values?: Partial<InferType<TSchema>>) => {\n epochRef.current++;\n validationGenRef.current++;\n cancelScheduledValidation();\n store.resetAll(values);\n },\n [store, cancelScheduledValidation]\n );\n const getValue = useCallback(\n (): InferType<TSchema> => store.getValues(),\n [store]\n );\n const setValue = useCallback(\n (values: Partial<InferType<TSchema>>) => {\n cancelScheduledValidation();\n store.setValues({ ...store.getValues(), ...values });\n },\n [store, cancelScheduledValidation]\n );\n const triggerValidation = useCallback(\n (markTouched: boolean) => {\n cancelScheduledValidation();\n const delay = optionsRef.current.validationDebounceMs;\n if (delay != null && delay > 0) {\n timerRef.current = setTimeout(() => {\n timerRef.current = null;\n void runValidation(markTouched);\n }, delay);\n return Promise.resolve();\n }\n return runValidation(markTouched);\n },\n [runValidation, cancelScheduledValidation]\n );\n\n const handleSubmit = useCallback(\n <TData>(\n onValid: (\n values: InferType<TSchema>\n ) => FormSubmitResult<TData> | Promise<FormSubmitResult<TData>>,\n submissionOptions?: FormSubmitOptions<InferType<TSchema>, TData>\n ): FormSubmitHandler =>\n async event => {\n event?.preventDefault();\n if (submissionLockRef.current || !mountedRef.current) return;\n submissionLockRef.current = true;\n const epoch = epochRef.current;\n const current = () =>\n mountedRef.current && epoch === epochRef.current;\n store.setSubmissionState({\n submitting: true,\n error: undefined\n });\n try {\n const revision = store.getRevision();\n const result = await runValidation(true);\n if (\n !current() ||\n revision !== store.getRevision() ||\n !result.valid ||\n result.object === undefined\n )\n return;\n const values = result.object;\n let outcome: FormSubmitResult<TData>;\n try {\n outcome = await onValid(values);\n } catch (error) {\n if (!current()) return;\n if (!submissionOptions?.onError) throw error;\n const message = await submissionOptions.onError(error);\n if (current())\n store.setSubmissionState({ error: message });\n return;\n }\n if (!current()) return;\n if (outcome && !outcome.ok) {\n store.setSubmissionState({ error: outcome.error });\n return;\n }\n // Errors from success callbacks (including redirects) propagate;\n // they are not translated as failures of a completed submission.\n await submissionOptions?.onSuccess?.(outcome?.data, values);\n } finally {\n submissionLockRef.current = false;\n if (mountedRef.current)\n store.setSubmissionState({ submitting: false });\n }\n },\n [runValidation, store]\n );\n\n const formContextValue = useMemo<FormContextValue>(\n () => ({\n store,\n descriptorTree,\n schema: schemaRef.current,\n pathMap,\n get options() {\n return optionsRef.current;\n },\n triggerValidation\n }),\n [store, descriptorTree, pathMap, triggerValidation]\n );\n const formContextRef = useRef(formContextValue);\n formContextRef.current = formContextValue;\n const _getFormContext = useCallback(() => formContextRef.current, []);\n const useFieldHook = useCallback(\n <TPropertySchema extends SchemaBuilder<any, any, any>>(\n selector: (\n tree: PropertyDescriptorTree<TSchema, TSchema>\n ) => PropertyDescriptor<TSchema, TPropertySchema, any>\n ): UseFieldResult<InferType<TPropertySchema>> =>\n useFieldFromContext(formContextRef.current, selector),\n []\n );\n const validateOnMountRef = useRef(options?.validateOnMount);\n useEffect(() => {\n if (validateOnMountRef.current) void runValidation(true);\n }, [runValidation]);\n\n // Subscribe to submission state without changing the controller's identity.\n useSyncExternalStore(\n store.subscribeGlobal,\n store.getSubmissionState,\n store.getSubmissionState\n );\n return useMemo(\n () => ({\n useField: useFieldHook,\n submit,\n validate,\n reset,\n getValue,\n setValue,\n handleSubmit,\n _getFormContext,\n get submitting() {\n return store.getSubmissionState().submitting;\n },\n get error() {\n return store.getSubmissionState().error;\n }\n }),\n [\n useFieldHook,\n submit,\n validate,\n reset,\n getValue,\n setValue,\n handleSubmit,\n _getFormContext,\n store\n ]\n );\n}\n\n/** Internal field binding shared by direct and context-based hooks. */\nexport function useFieldFromContext(\n formContext: FormContextValue,\n forProperty: (tree: any) => any,\n triggerValidation = formContext.triggerValidation\n): UseFieldResult {\n const { store, descriptorTree, options } = formContext;\n const inner =\n forProperty(descriptorTree)[SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR];\n const path = inner.toJsonPointer();\n store.registerField(path, inner);\n const subscribe = useCallback(\n (listener: () => void) => store.subscribe(path, listener),\n [store, path]\n );\n const getSnapshot = useCallback(\n () => store.getFieldState(path),\n [store, path]\n );\n const fieldState = useSyncExternalStore(\n subscribe,\n getSnapshot,\n getSnapshot\n );\n const onChange = useCallback(\n (value: any) => {\n store.setFieldValue(\n path,\n value,\n options.createMissingStructure !== false\n );\n void triggerValidation?.(false);\n },\n [store, path, options.createMissingStructure, triggerValidation]\n );\n const onBlur = useCallback(\n () => store.updateFieldState(path, { touched: true }),\n [store, path]\n );\n return {\n ...fieldState,\n onChange,\n onBlur,\n setValue: onChange,\n schema: inner.getSchema()\n };\n}\n\n/** Resolve type:variant first, falling back to the base type. */\nexport function resolveRenderer(\n config: FormSystemConfig | null,\n schema: SchemaBuilder<any, any, any>,\n variant?: string\n): FieldRenderer | undefined {\n if (!config?.renderers) return undefined;\n const type = getSchemaType(schema);\n return (\n (variant ? config.renderers[`${type}:${variant}`] : undefined) ??\n config.renderers[type]\n );\n}\n","import { deepClone, deepEqual } from '@cleverbrush/deep';\nimport type { FieldState, FormSubmissionState } from './types.js';\n\ntype Binding = {\n getValue: (values: any) => { success: boolean; value?: any };\n setValue: (values: any, value: any, options: any) => boolean;\n};\n\n/** Internal immutable snapshots shared by all bindings of a form. */\nexport function createFormStore(initialValues: any) {\n let values = deepClone(initialValues ?? {});\n let baseline = values;\n let revision = 0;\n let submission: FormSubmissionState = {\n submitting: false,\n error: undefined\n };\n const bindings = new Map<string, Binding>();\n const fieldStates = new Map<string, FieldState>();\n const listeners = new Map<string, Set<() => void>>();\n const globalListeners = new Set<() => void>();\n\n function read(binding: Binding | undefined, source: any) {\n const result = binding?.getValue(source);\n return result?.success ? result.value : undefined;\n }\n function getFieldState(path: string): FieldState {\n if (!fieldStates.has(path)) {\n const binding = bindings.get(path);\n const value = read(binding, values);\n const initialValue = read(binding, baseline);\n fieldStates.set(path, {\n value,\n initialValue,\n dirty: !deepEqual(value, initialValue),\n touched: false,\n error: undefined,\n validating: false\n });\n }\n return fieldStates.get(path)!;\n }\n function registerField(path: string, binding: Binding) {\n if (!bindings.has(path)) bindings.set(path, binding);\n return getFieldState(path);\n }\n function notifyPath(path: string) {\n for (const listener of listeners.get(path) ?? []) listener();\n }\n function notifyAll() {\n for (const path of listeners.keys()) notifyPath(path);\n for (const listener of globalListeners) listener();\n }\n function updateFieldState(path: string, patch: Partial<FieldState>) {\n const current = getFieldState(path);\n if (\n Object.entries(patch).every(([key, value]) =>\n Object.is(current[key as keyof FieldState], value)\n )\n )\n return;\n fieldStates.set(path, { ...current, ...patch });\n notifyPath(path);\n }\n function syncFields(reset: boolean) {\n for (const [path, binding] of bindings) {\n const value = read(binding, values);\n const initialValue = read(binding, baseline);\n updateFieldState(path, {\n value,\n initialValue,\n dirty: !deepEqual(value, initialValue),\n validating: false,\n ...(reset ? { touched: false, error: undefined } : {})\n });\n }\n }\n function subscribe(path: string, listener: () => void): () => void {\n let set = listeners.get(path);\n if (!set) {\n set = new Set();\n listeners.set(path, set);\n }\n set.add(listener);\n return () => {\n set.delete(listener);\n if (set.size === 0) listeners.delete(path);\n };\n }\n function subscribeGlobal(listener: () => void): () => void {\n globalListeners.add(listener);\n return () => {\n globalListeners.delete(listener);\n };\n }\n function getSubmissionState() {\n return submission;\n }\n function setSubmissionState(patch: Partial<FormSubmissionState>) {\n const next = { ...submission, ...patch };\n if (\n next.submitting === submission.submitting &&\n next.error === submission.error\n )\n return;\n submission = next;\n for (const listener of globalListeners) listener();\n }\n function getValues() {\n return values;\n }\n function getRevision() {\n return revision;\n }\n function setValues(newValues: any) {\n values = deepClone(newValues ?? {});\n revision++;\n syncFields(false);\n }\n function setFieldValue(\n path: string,\n value: any,\n createMissingStructure: boolean\n ) {\n const next = deepClone(values);\n if (\n bindings\n .get(path)\n ?.setValue(next, deepClone(value), { createMissingStructure })\n ) {\n setValues(next);\n }\n }\n function resetAll(newInitialValues?: any) {\n values = deepClone(newInitialValues ?? {});\n baseline = values;\n revision++;\n syncFields(true);\n setSubmissionState({ error: undefined });\n }\n function getAllFieldPaths() {\n return Array.from(bindings.keys());\n }\n\n return {\n registerField,\n getFieldState,\n updateFieldState,\n subscribe,\n subscribeGlobal,\n getValues,\n setValues,\n setFieldValue,\n resetAll,\n getAllFieldPaths,\n getRevision,\n getSubmissionState,\n setSubmissionState,\n notifyAll\n };\n}\n\nexport type FormStore = ReturnType<typeof createFormStore>;\n","import type {\n InferType,\n ObjectSchemaBuilder,\n PropertyDescriptorTree,\n SchemaBuilder\n} from '@cleverbrush/schema';\nimport { SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR } from '@cleverbrush/schema';\nimport type { ReactNode } from 'react';\nimport { Field, type FieldProps, FormSystemProvider } from './components.js';\nimport { getSchemaType } from './helpers.js';\nimport type { SchemaFormInstance } from './hooks.js';\nimport type { FieldRenderer } from './types.js';\n\ndeclare const rendererTypes: unique symbol;\n\n/** A renderer whose accepted values and custom props survive registration. */\nexport type TypedFieldRenderer<TValue, TProps> = FieldRenderer<\n TValue,\n TProps\n> & {\n readonly [rendererTypes]: { value: TValue; props: TProps };\n};\n\n/**\n * Attach type information without adding a UI dependency or runtime wrapper.\n * Include null in TValue when the renderer supports nullable fields.\n */\nexport function defineFieldRenderer<TValue, TProps = Record<string, never>>(\n renderer: FieldRenderer<TValue, TProps>\n): TypedFieldRenderer<TValue, TProps> {\n return renderer as TypedFieldRenderer<TValue, TProps>;\n}\n\nexport type TypedRendererRegistry = Readonly<\n Record<string, TypedFieldRenderer<any, any>>\n>;\n\ntype ValueOf<T> = T extends TypedFieldRenderer<infer V, any> ? V : never;\ntype PropsOf<T> = T extends TypedFieldRenderer<any, infer P> ? P : never;\ntype KindOf<T> = 0 extends 1 & T\n ? string\n : [NonNullable<T>] extends [string]\n ? 'string'\n : [NonNullable<T>] extends [number]\n ? 'number'\n : [NonNullable<T>] extends [boolean]\n ? 'boolean'\n : [NonNullable<T>] extends [Date]\n ? 'date'\n : [NonNullable<T>] extends [readonly unknown[]]\n ? 'array'\n : [NonNullable<T>] extends [object]\n ? 'object'\n : never;\ntype CustomProps<P> = {} extends P ? { fieldProps?: P } : { fieldProps: P };\ntype RendererChoice<R extends TypedRendererRegistry, V> = {\n [K in keyof R & string]: [Exclude<V, undefined>] extends [ValueOf<R[K]>]\n ? K extends `${KindOf<V>}:${infer Variant}`\n ? { variant: Variant } & CustomProps<PropsOf<R[K]>>\n : K extends KindOf<V>\n ? { variant?: undefined } & CustomProps<PropsOf<R[K]>>\n : never\n : never;\n}[keyof R & string];\n\ntype FieldDescriptor = {\n readonly [SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR]: {\n getSchema: () => SchemaBuilder<any, any, any>;\n };\n};\ntype DescriptorValue<D extends FieldDescriptor> = InferType<\n ReturnType<D[typeof SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR]['getSchema']>\n>;\n\n/** Props are inferred from the selected schema property and registered variant. */\nexport type TypedFieldProps<\n R extends TypedRendererRegistry,\n TSchema extends ObjectSchemaBuilder<any, any, any>,\n TDescriptor extends FieldDescriptor\n> = {\n form: SchemaFormInstance<TSchema>;\n forProperty: (\n tree: PropertyDescriptorTree<TSchema, TSchema>\n ) => TDescriptor;\n label?: string;\n name?: string;\n} & RendererChoice<R, NoInfer<DescriptorValue<TDescriptor>>>;\n\n/**\n * Create a typed Field and a provider for an application's renderer registry.\n * The typed Field resolves from this factory's closed registry, so an untyped\n * ancestor provider cannot silently replace a renderer with incompatible props.\n * The Provider also configures legacy Field consumers and supports nesting.\n * Extend a system with createFormSystem({ renderers: { ...system.renderers,\n * 'string:custom': customRenderer } }). Existing global APIs remain available.\n */\nexport function createFormSystem<\n const R extends TypedRendererRegistry\n>(config: { renderers: R }) {\n const renderers = Object.freeze({ ...config.renderers });\n function TypedField<\n TSchema extends ObjectSchemaBuilder<any, any, any>,\n TDescriptor extends FieldDescriptor\n >(props: TypedFieldProps<R, TSchema, TDescriptor>): ReactNode {\n const descriptor = props.forProperty(\n props.form._getFormContext()\n .descriptorTree as PropertyDescriptorTree<TSchema, TSchema>\n );\n const type = getSchemaType(\n descriptor[SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR].getSchema()\n );\n const key = props.variant ? `${type}:${props.variant}` : type;\n const renderer = renderers[key];\n if (!renderer)\n throw new Error(\n `No renderer registered for \"${key}\" in this form system.`\n );\n // Field's legacy signature erases descriptor parent types. The factory\n // has already checked the selected value and renderer-specific props.\n return (\n <Field\n {...(props as unknown as FieldProps<TSchema>)}\n renderer={renderer}\n />\n );\n }\n function Provider({ children }: { children: ReactNode }): ReactNode {\n return (\n <FormSystemProvider renderers={renderers}>\n {children}\n </FormSystemProvider>\n );\n }\n return { Field: TypedField, Provider, renderers };\n}\n"],"mappings":"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","names":["useContext","useMemo","createContext","FormSystemContext","FormContext","ObjectSchemaBuilder","SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR","buildDescriptorPathMap","tree","schema","map","introspected","propName","propDescriptor","inner","propSchema","childMap","childInner","childPath","getSchemaType","schema","ensureNestedStructure","values","schema","introspected","result","key","propSchema","ObjectSchemaBuilder","ObjectSchemaBuilder","SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR","useCallback","useEffect","useMemo","useRef","useSyncExternalStore","deepClone","deepEqual","createFormStore","initialValues","values","baseline","revision","submission","bindings","fieldStates","listeners","globalListeners","read","binding","source","result","getFieldState","path","value","initialValue","registerField","notifyPath","listener","notifyAll","updateFieldState","patch","current","key","syncFields","reset","subscribe","set","subscribeGlobal","getSubmissionState","setSubmissionState","next","getValues","getRevision","setValues","newValues","setFieldValue","createMissingStructure","resetAll","newInitialValues","getAllFieldPaths","useSchemaForm","schema","options","storeRef","useRef","createFormStore","store","descriptorTreeRef","ObjectSchemaBuilder","descriptorTree","pathMapRef","buildDescriptorPathMap","pathMap","descriptor","schemaRef","optionsRef","mountedRef","epochRef","validationGenRef","submissionLockRef","timerRef","cancelScheduledValidation","useCallback","useEffect","runValidation","markTouched","gen","revision","path","safeValues","ensureNestedStructure","result","getErrorsFor","parts","part","field","tree","value","key","validate","submit","reset","values","getValue","setValue","triggerValidation","delay","handleSubmit","onValid","submissionOptions","event","epoch","current","outcome","error","message","formContextValue","useMemo","formContextRef","_getFormContext","useFieldHook","selector","useFieldFromContext","validateOnMountRef","useSyncExternalStore","formContext","forProperty","inner","SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR","subscribe","listener","getSnapshot","fieldState","onChange","onBlur","resolveRenderer","config","variant","type","getSchemaType","jsx","FormSystemProvider","renderers","config","children","parentConfig","useContext","FormSystemContext","resolvedConfig","useMemo","current","FormProvider","form","formContext","FormContext","useField","forProperty","useFieldFromContext","useFormSystem","Field","renderer","variant","label","name","fieldProps","fieldResult","systemConfig","resolvedRenderer","resolveRenderer","schemaType","getSchemaType","tried","SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR","jsx","defineFieldRenderer","renderer","createFormSystem","config","renderers","TypedField","props","descriptor","type","getSchemaType","SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR","key","Field","Provider","children","FormSystemProvider"]}
|
|
1
|
+
{"version":3,"sources":["../src/components.tsx","../src/contexts.ts","../src/helpers.ts","../src/hooks.ts","../src/FormStore.ts","../src/system.tsx"],"sourcesContent":["import type {\n InferType,\n ObjectSchemaBuilder,\n PropertyDescriptor,\n PropertyDescriptorTree,\n SchemaBuilder\n} from '@cleverbrush/schema';\nimport type React from 'react';\nimport { useContext, useMemo } from 'react';\nimport { FormContext, FormSystemContext } from './contexts.js';\nimport { getSchemaType } from './helpers.js';\nimport type { SchemaFormInstance } from './hooks.js';\nimport { resolveRenderer, useFieldFromContext } from './hooks.js';\nimport type {\n FieldRenderer,\n FormSystemConfig,\n UseFieldResult\n} from './types.js';\n\n// ─── FormSystemProvider ──────────────────────────────────────────────────────\n\nexport type FormSystemProviderProps = {\n /**\n * Renderer registry mapping schema types to renderer functions.\n * Example: `{ string: (props) => <input .../>, number: (props) => <input type=\"number\" .../> }`\n */\n renderers?: Record<string, FieldRenderer>;\n /**\n * Full configuration object (for future extensibility).\n * If both `renderers` and `config.renderers` are provided, `renderers` takes precedence.\n */\n config?: FormSystemConfig;\n children: React.ReactNode;\n};\n\n/**\n * Provides global renderer configuration via React Context.\n * Supports nesting — inner provider overrides outer.\n *\n * @example\n * ```tsx\n * <FormSystemProvider renderers={htmlRenderers}>\n * <App />\n * </FormSystemProvider>\n * ```\n */\nexport function FormSystemProvider({\n renderers,\n config,\n children\n}: FormSystemProviderProps): React.ReactNode {\n const parentConfig = useContext(FormSystemContext);\n\n const resolvedConfig: FormSystemConfig = useMemo(() => {\n const current: FormSystemConfig = {\n ...config,\n renderers: {\n ...config?.renderers,\n ...renderers\n }\n };\n if (!parentConfig) return current;\n return {\n ...parentConfig,\n ...current,\n renderers: {\n ...parentConfig.renderers,\n ...current.renderers\n }\n };\n }, [parentConfig, config, renderers]);\n\n return (\n <FormSystemContext.Provider value={resolvedConfig}>\n {children}\n </FormSystemContext.Provider>\n );\n}\n\n// ─── FormProvider ────────────────────────────────────────────────────────────\n\nexport type FormProviderProps<\n TSchema extends ObjectSchemaBuilder<any, any, any>\n> = {\n form: SchemaFormInstance<TSchema>;\n children: React.ReactNode;\n};\n\n/**\n * Provides form context to children so they can use the context-based useField.\n */\nexport function FormProvider<\n TSchema extends ObjectSchemaBuilder<any, any, any>\n>({ form, children }: FormProviderProps<TSchema>): React.ReactNode {\n const formContext = form._getFormContext();\n return (\n <FormContext.Provider value={formContext}>\n {children}\n </FormContext.Provider>\n );\n}\n\n// ─── Context-based useField ──────────────────────────────────────────────────\n\n/**\n * Context-based useField — can be used inside a FormProvider.\n * For best IntelliSense, prefer `form.useField()` which infers field types from the schema.\n * When using this context-based version, specify the schema type explicitly:\n *\n * @example\n * ```tsx\n * const name = useField<typeof MySchema>((t) => t.name);\n * ```\n */\nexport function useField<\n TSchema extends ObjectSchemaBuilder<any, any, any>,\n TPropertySchema extends SchemaBuilder<any, any, any, any> = any\n>(\n forProperty: (\n tree: PropertyDescriptorTree<TSchema, TSchema>\n ) => PropertyDescriptor<TSchema, TPropertySchema, any>\n): UseFieldResult<InferType<TPropertySchema>> {\n const formContext = useContext(FormContext);\n if (!formContext) {\n throw new Error(\n 'useField must be used within a FormProvider. ' +\n 'Wrap your component tree with <FormProvider form={form}>.'\n );\n }\n return useFieldFromContext(formContext, forProperty) as UseFieldResult<\n InferType<TPropertySchema>\n >;\n}\n\n// ─── useFormSystem ───────────────────────────────────────────────────────────\n\n/**\n * Hook to access FormSystem configuration.\n */\nexport function useFormSystem(): FormSystemConfig {\n const config = useContext(FormSystemContext);\n if (!config) {\n throw new Error(\n 'useFormSystem must be used within a FormSystemProvider'\n );\n }\n return config;\n}\n\n// ─── Field Component ─────────────────────────────────────────────────────────\n\nexport type FieldProps<TSchema extends ObjectSchemaBuilder<any, any, any>> = {\n forProperty: (\n tree: PropertyDescriptorTree<TSchema, TSchema>\n ) => PropertyDescriptor<TSchema, any, any>;\n form: SchemaFormInstance<TSchema>;\n renderer?: FieldRenderer;\n /**\n * Rendering variant hint. Participates in renderer resolution:\n * the registry is checked for `\"type:variant\"` (e.g. `\"string:password\"`)\n * before falling back to the base `\"type\"` key.\n * Also forwarded to the renderer via `FieldRenderProps.variant`.\n */\n variant?: string;\n /** Visible label text forwarded to the renderer via `FieldRenderProps.label`. */\n label?: string;\n /** HTML `name` attribute forwarded to the renderer via `FieldRenderProps.name`. */\n name?: string;\n /**\n * Bag of extra renderer-specific props forwarded to the renderer via\n * `FieldRenderProps.fieldProps` (e.g. `placeholder`, `autoComplete`).\n */\n fieldProps?: Record<string, unknown>;\n};\n\n/**\n * UI-agnostic Field component.\n *\n * Resolves a renderer from:\n * 1. Explicit `renderer` prop\n * 2. FormSystemProvider registry — checked for `\"type:variant\"` first,\n * then for the base `\"type\"`\n *\n * All rendering hints (`variant`, `label`, `name`, `fieldProps`) are\n * forwarded to the resolved renderer via `FieldRenderProps`.\n *\n * @example\n * ```tsx\n * <Field forProperty={(t) => t.password} form={form}\n * variant=\"password\" label=\"Password\"\n * fieldProps={{ placeholder: \"Enter password\", autoComplete: \"current-password\" }} />\n * ```\n */\nexport function Field<TSchema extends ObjectSchemaBuilder<any, any, any>>({\n forProperty,\n form,\n renderer,\n variant,\n label,\n name,\n fieldProps\n}: FieldProps<TSchema>): React.ReactNode {\n const fieldResult = form.useField(forProperty);\n const systemConfig = useContext(FormSystemContext);\n\n const resolvedRenderer =\n renderer ?? resolveRenderer(systemConfig, fieldResult.schema, variant);\n\n if (!resolvedRenderer) {\n const schemaType = getSchemaType(fieldResult.schema);\n const tried = variant\n ? `\"${schemaType}:${variant}\" or \"${schemaType}\"`\n : `\"${schemaType}\"`;\n throw new Error(\n `No renderer found for schema type ${tried}. ` +\n 'Provide a renderer prop or configure one in FormSystemProvider.'\n );\n }\n\n return resolvedRenderer({\n value: fieldResult.value,\n initialValue: fieldResult.initialValue,\n dirty: fieldResult.dirty,\n touched: fieldResult.touched,\n error: fieldResult.error,\n validating: fieldResult.validating,\n onChange: fieldResult.onChange,\n onBlur: fieldResult.onBlur,\n setValue: fieldResult.setValue,\n schema: fieldResult.schema,\n variant,\n label,\n name,\n fieldProps\n });\n}\n","import type {\n ObjectSchemaBuilder,\n PropertyDescriptorInner,\n PropertyDescriptorTree\n} from '@cleverbrush/schema';\nimport { createContext } from 'react';\nimport type { FormStore } from './FormStore.js';\nimport type { FormSystemConfig, UseSchemaFormOptions } from './types.js';\n\n/**\n * Context for global form system configuration (renderers, etc).\n */\nexport const FormSystemContext = createContext<FormSystemConfig | null>(null);\n\n/**\n * Internal form context value — used to bridge useSchemaForm store\n * to the context-based useField and Field component.\n */\nexport type FormContextValue = {\n store: FormStore;\n descriptorTree: PropertyDescriptorTree<any, any>;\n schema: ObjectSchemaBuilder<any, any, any>;\n options: UseSchemaFormOptions;\n pathMap: Map<PropertyDescriptorInner<any, any, any>, string>;\n triggerValidation?: (markTouched: boolean) => Promise<unknown>;\n};\n\n/**\n * Context for per-form data — allows useField to work via context.\n */\nexport const FormContext = createContext<FormContextValue | null>(null);\n","import type {\n PropertyDescriptorInner,\n PropertyDescriptorTree,\n SchemaBuilder\n} from '@cleverbrush/schema';\nimport {\n ObjectSchemaBuilder,\n SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR\n} from '@cleverbrush/schema';\n\n/**\n * Builds a map from PropertyDescriptorInner identity → dot-separated path\n * by traversing the descriptor tree recursively.\n */\nexport function buildDescriptorPathMap(\n tree: PropertyDescriptorTree<any, any>,\n schema: ObjectSchemaBuilder<any, any, any>\n): Map<PropertyDescriptorInner<any, any, any>, string> {\n const map = new Map<PropertyDescriptorInner<any, any, any>, string>();\n const introspected = schema.introspect();\n if (!introspected.properties) return map;\n\n for (const propName of Object.keys(introspected.properties)) {\n const propDescriptor = (tree as any)[propName];\n if (\n !propDescriptor ||\n !(SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR in propDescriptor)\n ) {\n continue;\n }\n const inner = propDescriptor[\n SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR\n ] as PropertyDescriptorInner<any, any, any>;\n map.set(inner, propName);\n\n // Recurse into nested objects\n const propSchema = introspected.properties[propName];\n if (propSchema instanceof ObjectSchemaBuilder) {\n const childMap = buildDescriptorPathMap(propDescriptor, propSchema);\n for (const [childInner, childPath] of childMap) {\n map.set(childInner, `${propName}.${childPath}`);\n }\n }\n }\n\n return map;\n}\n\n/**\n * Looks up the path for a given descriptor from the pre-built map.\n */\nexport function getDescriptorPath(\n inner: PropertyDescriptorInner<any, any, any>,\n pathMap: Map<PropertyDescriptorInner<any, any, any>, string>\n): string {\n return pathMap.get(inner) ?? '';\n}\n\n/**\n * Returns the schema type string (e.g. \"string\", \"number\", \"object\").\n */\nexport function getSchemaType(\n schema: SchemaBuilder<any, any, any, any>\n): string {\n const introspected = schema.introspect();\n return introspected?.type ?? 'unknown';\n}\n\n/**\n * Builds a selector function from a dot-separated path string.\n * The selector traverses the PropertyDescriptorTree by property access.\n * Example: \"customer.address.city\" → (tree) => tree.customer.address.city\n */\nexport function buildSelectorFromPath(path: string): (tree: any) => any {\n const parts = path.split('.');\n return (tree: any) => {\n let current = tree;\n for (const part of parts) {\n if (current == null) return undefined;\n current = current[part];\n }\n return current;\n };\n}\n\n/**\n * Checks whether a validation error path matches a field's expected error path.\n * Matches exact path, path with nested suffix, or path with validator suffix.\n * Example: isErrorPathMatch(\"$.user.name\", \"$.user.name\") → true\n * isErrorPathMatch(\"$.user.name($validators[0])\", \"$.user.name\") → true\n */\nexport function isErrorPathMatch(\n errPath: string,\n fieldErrorPath: string\n): boolean {\n return (\n errPath === fieldErrorPath ||\n errPath.startsWith(fieldErrorPath + '.') ||\n errPath.startsWith(fieldErrorPath + '(')\n );\n}\n\n/**\n * Ensures all nested object structures exist in the values object\n * by traversing the schema and creating empty objects where needed.\n * This prevents ObjectSchemaBuilder.validate() from throwing when\n * nested object properties are undefined.\n *\n * Example: ensureNestedStructure({}, OrderSchema)\n * → { customer: { address: {} } }\n */\nexport function ensureNestedStructure(\n values: any,\n schema: ObjectSchemaBuilder<any, any, any>\n): any {\n const introspected = schema.introspect();\n if (!introspected.properties) return values != null ? values : {};\n\n const result = values != null ? { ...values } : {};\n for (const key of Object.keys(introspected.properties)) {\n const propSchema = introspected.properties[key];\n if (propSchema instanceof ObjectSchemaBuilder) {\n result[key] = ensureNestedStructure(result[key], propSchema);\n }\n }\n return result;\n}\n","import type {\n InferType,\n PropertyDescriptor,\n PropertyDescriptorInner,\n PropertyDescriptorTree,\n SchemaBuilder,\n ValidationResult\n} from '@cleverbrush/schema';\nimport {\n ObjectSchemaBuilder,\n SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR\n} from '@cleverbrush/schema';\nimport {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useSyncExternalStore\n} from 'react';\nimport type { FormContextValue } from './contexts.js';\nimport type { FormStore } from './FormStore.js';\nimport { createFormStore } from './FormStore.js';\nimport {\n buildDescriptorPathMap,\n ensureNestedStructure,\n getSchemaType\n} from './helpers.js';\nimport type {\n FieldRenderer,\n FormSubmissionState,\n FormSubmitHandler,\n FormSubmitOptions,\n FormSubmitResult,\n FormSystemConfig,\n UseFieldResult,\n UseSchemaFormOptions\n} from './types.js';\n\n/** A stable form controller with reactive field and submission subscriptions. */\nexport type SchemaFormInstance<\n TSchema extends ObjectSchemaBuilder<any, any, any>\n> = {\n useField: <TPropertySchema extends SchemaBuilder<any, any, any, any>>(\n forProperty: (\n tree: PropertyDescriptorTree<TSchema, TSchema>\n ) => PropertyDescriptor<TSchema, TPropertySchema, any>\n ) => UseFieldResult<InferType<TPropertySchema>>;\n submit: () => Promise<ValidationResult<InferType<TSchema>>>;\n validate: () => Promise<ValidationResult<InferType<TSchema>>>;\n /** Clear values, or establish supplied values as the new clean baseline. */\n reset: (values?: Partial<InferType<TSchema>>) => void;\n /** Read the current snapshot. Use setters rather than mutating it. */\n getValue: () => InferType<TSchema>;\n /** Shallow-merge values without marking fields touched. */\n setValue: (values: Partial<InferType<TSchema>>) => void;\n /** Validate and submit once; repeated calls while pending are ignored. */\n handleSubmit: <TData = void>(\n onValid: (\n values: InferType<TSchema>\n ) => FormSubmitResult<TData> | Promise<FormSubmitResult<TData>>,\n options?: FormSubmitOptions<InferType<TSchema>, TData>\n ) => FormSubmitHandler;\n /** @internal — Used by FormProvider and Field to access internal context. */\n _getFormContext: () => FormContextValue;\n} & FormSubmissionState;\n\n/** Bind a schema to independently subscribed fields and a stable form instance. */\nexport function useSchemaForm<\n TSchema extends ObjectSchemaBuilder<any, any, any>\n>(\n schema: TSchema,\n options?: UseSchemaFormOptions\n): SchemaFormInstance<TSchema> {\n const storeRef = useRef<FormStore | null>(null);\n if (!storeRef.current) storeRef.current = createFormStore({});\n const store = storeRef.current;\n const descriptorTreeRef = useRef<PropertyDescriptorTree<\n TSchema,\n TSchema\n > | null>(null);\n if (!descriptorTreeRef.current) {\n descriptorTreeRef.current = ObjectSchemaBuilder.getPropertiesFor(\n schema\n ) as PropertyDescriptorTree<TSchema, TSchema>;\n }\n const descriptorTree = descriptorTreeRef.current;\n const pathMapRef = useRef<Map<\n PropertyDescriptorInner<any, any, any>,\n string\n > | null>(null);\n if (!pathMapRef.current) {\n pathMapRef.current = buildDescriptorPathMap(descriptorTree, schema);\n }\n const pathMap = pathMapRef.current;\n for (const [descriptor] of pathMap) {\n store.registerField(descriptor.toJsonPointer(), descriptor);\n }\n const schemaRef = useRef(schema);\n const optionsRef = useRef<UseSchemaFormOptions>({});\n optionsRef.current = { createMissingStructure: true, ...options };\n const mountedRef = useRef(true);\n const epochRef = useRef(0);\n const validationGenRef = useRef(0);\n const submissionLockRef = useRef(false);\n const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const cancelScheduledValidation = useCallback(() => {\n if (timerRef.current !== null) clearTimeout(timerRef.current);\n timerRef.current = null;\n }, []);\n useEffect(() => {\n mountedRef.current = true;\n return () => {\n mountedRef.current = false;\n epochRef.current++;\n validationGenRef.current++;\n cancelScheduledValidation();\n };\n }, [cancelScheduledValidation]);\n\n const runValidation = useCallback(\n async (\n markTouched: boolean\n ): Promise<ValidationResult<InferType<TSchema>>> => {\n cancelScheduledValidation();\n const gen = ++validationGenRef.current;\n const revision = store.getRevision();\n for (const path of store.getAllFieldPaths()) {\n store.updateFieldState(path, { validating: true });\n }\n const safeValues = ensureNestedStructure(\n store.getValues(),\n schemaRef.current\n );\n let result: ValidationResult<InferType<TSchema>>;\n try {\n result = (await schemaRef.current.validateAsync(safeValues, {\n doNotStopOnFirstError: true\n })) as ValidationResult<InferType<TSchema>>;\n } catch {\n result = { valid: false } as ValidationResult<\n InferType<TSchema>\n >;\n }\n // A value update invalidates validation immediately, even while the next\n // validation is only scheduled (debounced) and has not started yet.\n if (\n !mountedRef.current ||\n gen !== validationGenRef.current ||\n revision !== store.getRevision()\n )\n return result;\n\n for (const path of store.getAllFieldPaths()) {\n store.updateFieldState(path, {\n error: undefined,\n validating: false,\n ...(markTouched ? { touched: true } : {})\n });\n }\n const getErrorsFor = (result as any).getErrorsFor;\n if (typeof getErrorsFor === 'function') {\n for (const [descriptor] of pathMap) {\n const path = descriptor.toJsonPointer();\n const parts = path\n .slice(1)\n .split('/')\n .map(part =>\n part.replace(/~1/g, '/').replace(/~0/g, '~')\n );\n try {\n const field = getErrorsFor((tree: any) =>\n parts.reduce(\n (value: any, key) => value?.[key],\n tree\n )\n );\n if (\n Array.isArray(field?.errors) &&\n field.errors.length\n ) {\n store.updateFieldState(path, {\n error: field.errors[0]\n });\n }\n } catch {\n // A missing error selector must not prevent other fields\n // from receiving their validation results.\n }\n }\n }\n return result;\n },\n [cancelScheduledValidation, store, pathMap]\n );\n\n const validate = useCallback(() => runValidation(true), [runValidation]);\n const submit = useCallback(() => validate(), [validate]);\n const reset = useCallback(\n (values?: Partial<InferType<TSchema>>) => {\n epochRef.current++;\n validationGenRef.current++;\n cancelScheduledValidation();\n store.resetAll(values);\n },\n [store, cancelScheduledValidation]\n );\n const getValue = useCallback(\n (): InferType<TSchema> => store.getValues(),\n [store]\n );\n const setValue = useCallback(\n (values: Partial<InferType<TSchema>>) => {\n cancelScheduledValidation();\n store.setValues({ ...store.getValues(), ...values });\n },\n [store, cancelScheduledValidation]\n );\n const triggerValidation = useCallback(\n (markTouched: boolean) => {\n cancelScheduledValidation();\n const delay = optionsRef.current.validationDebounceMs;\n if (delay != null && delay > 0) {\n timerRef.current = setTimeout(() => {\n timerRef.current = null;\n void runValidation(markTouched);\n }, delay);\n return Promise.resolve();\n }\n return runValidation(markTouched);\n },\n [runValidation, cancelScheduledValidation]\n );\n\n const handleSubmit = useCallback(\n <TData>(\n onValid: (\n values: InferType<TSchema>\n ) => FormSubmitResult<TData> | Promise<FormSubmitResult<TData>>,\n submissionOptions?: FormSubmitOptions<InferType<TSchema>, TData>\n ): FormSubmitHandler =>\n async event => {\n event?.preventDefault();\n if (submissionLockRef.current || !mountedRef.current) return;\n submissionLockRef.current = true;\n const epoch = epochRef.current;\n const current = () =>\n mountedRef.current && epoch === epochRef.current;\n store.setSubmissionState({\n submitting: true,\n error: undefined\n });\n try {\n const revision = store.getRevision();\n const result = await runValidation(true);\n if (\n !current() ||\n revision !== store.getRevision() ||\n !result.valid ||\n result.object === undefined\n )\n return;\n const values = result.object;\n let outcome: FormSubmitResult<TData>;\n try {\n outcome = await onValid(values);\n } catch (error) {\n if (!current()) return;\n if (!submissionOptions?.onError) throw error;\n const message = await submissionOptions.onError(error);\n if (current())\n store.setSubmissionState({ error: message });\n return;\n }\n if (!current()) return;\n if (outcome && !outcome.ok) {\n store.setSubmissionState({ error: outcome.error });\n return;\n }\n // Errors from success callbacks (including redirects) propagate;\n // they are not translated as failures of a completed submission.\n await submissionOptions?.onSuccess?.(outcome?.data, values);\n } finally {\n submissionLockRef.current = false;\n if (mountedRef.current)\n store.setSubmissionState({ submitting: false });\n }\n },\n [runValidation, store]\n );\n\n const formContextValue = useMemo<FormContextValue>(\n () => ({\n store,\n descriptorTree,\n schema: schemaRef.current,\n pathMap,\n get options() {\n return optionsRef.current;\n },\n triggerValidation\n }),\n [store, descriptorTree, pathMap, triggerValidation]\n );\n const formContextRef = useRef(formContextValue);\n formContextRef.current = formContextValue;\n const _getFormContext = useCallback(() => formContextRef.current, []);\n const useFieldHook = useCallback(\n <TPropertySchema extends SchemaBuilder<any, any, any, any>>(\n selector: (\n tree: PropertyDescriptorTree<TSchema, TSchema>\n ) => PropertyDescriptor<TSchema, TPropertySchema, any>\n ): UseFieldResult<InferType<TPropertySchema>> =>\n useFieldFromContext(formContextRef.current, selector),\n []\n );\n const validateOnMountRef = useRef(options?.validateOnMount);\n useEffect(() => {\n if (validateOnMountRef.current) void runValidation(true);\n }, [runValidation]);\n\n // Subscribe to submission state without changing the controller's identity.\n useSyncExternalStore(\n store.subscribeGlobal,\n store.getSubmissionState,\n store.getSubmissionState\n );\n return useMemo(\n () => ({\n useField: useFieldHook,\n submit,\n validate,\n reset,\n getValue,\n setValue,\n handleSubmit,\n _getFormContext,\n get submitting() {\n return store.getSubmissionState().submitting;\n },\n get error() {\n return store.getSubmissionState().error;\n }\n }),\n [\n useFieldHook,\n submit,\n validate,\n reset,\n getValue,\n setValue,\n handleSubmit,\n _getFormContext,\n store\n ]\n );\n}\n\n/** Internal field binding shared by direct and context-based hooks. */\nexport function useFieldFromContext(\n formContext: FormContextValue,\n forProperty: (tree: any) => any,\n triggerValidation = formContext.triggerValidation\n): UseFieldResult {\n const { store, descriptorTree, options } = formContext;\n const inner =\n forProperty(descriptorTree)[SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR];\n const path = inner.toJsonPointer();\n store.registerField(path, inner);\n const subscribe = useCallback(\n (listener: () => void) => store.subscribe(path, listener),\n [store, path]\n );\n const getSnapshot = useCallback(\n () => store.getFieldState(path),\n [store, path]\n );\n const fieldState = useSyncExternalStore(\n subscribe,\n getSnapshot,\n getSnapshot\n );\n const onChange = useCallback(\n (value: any) => {\n store.setFieldValue(\n path,\n value,\n options.createMissingStructure !== false\n );\n void triggerValidation?.(false);\n },\n [store, path, options.createMissingStructure, triggerValidation]\n );\n const onBlur = useCallback(\n () => store.updateFieldState(path, { touched: true }),\n [store, path]\n );\n return {\n ...fieldState,\n onChange,\n onBlur,\n setValue: onChange,\n schema: inner.getSchema()\n };\n}\n\n/** Resolve type:variant first, falling back to the base type. */\nexport function resolveRenderer(\n config: FormSystemConfig | null,\n schema: SchemaBuilder<any, any, any, any>,\n variant?: string\n): FieldRenderer | undefined {\n if (!config?.renderers) return undefined;\n const type = getSchemaType(schema);\n return (\n (variant ? config.renderers[`${type}:${variant}`] : undefined) ??\n config.renderers[type]\n );\n}\n","import { deepClone, deepEqual } from '@cleverbrush/deep';\nimport type { FieldState, FormSubmissionState } from './types.js';\n\ntype Binding = {\n getValue: (values: any) => { success: boolean; value?: any };\n setValue: (values: any, value: any, options: any) => boolean;\n};\n\n/** Internal immutable snapshots shared by all bindings of a form. */\nexport function createFormStore(initialValues: any) {\n let values = deepClone(initialValues ?? {});\n let baseline = values;\n let revision = 0;\n let submission: FormSubmissionState = {\n submitting: false,\n error: undefined\n };\n const bindings = new Map<string, Binding>();\n const fieldStates = new Map<string, FieldState>();\n const listeners = new Map<string, Set<() => void>>();\n const globalListeners = new Set<() => void>();\n\n function read(binding: Binding | undefined, source: any) {\n const result = binding?.getValue(source);\n return result?.success ? result.value : undefined;\n }\n function getFieldState(path: string): FieldState {\n if (!fieldStates.has(path)) {\n const binding = bindings.get(path);\n const value = read(binding, values);\n const initialValue = read(binding, baseline);\n fieldStates.set(path, {\n value,\n initialValue,\n dirty: !deepEqual(value, initialValue),\n touched: false,\n error: undefined,\n validating: false\n });\n }\n return fieldStates.get(path)!;\n }\n function registerField(path: string, binding: Binding) {\n if (!bindings.has(path)) bindings.set(path, binding);\n return getFieldState(path);\n }\n function notifyPath(path: string) {\n for (const listener of listeners.get(path) ?? []) listener();\n }\n function notifyAll() {\n for (const path of listeners.keys()) notifyPath(path);\n for (const listener of globalListeners) listener();\n }\n function updateFieldState(path: string, patch: Partial<FieldState>) {\n const current = getFieldState(path);\n if (\n Object.entries(patch).every(([key, value]) =>\n Object.is(current[key as keyof FieldState], value)\n )\n )\n return;\n fieldStates.set(path, { ...current, ...patch });\n notifyPath(path);\n }\n function syncFields(reset: boolean) {\n for (const [path, binding] of bindings) {\n const value = read(binding, values);\n const initialValue = read(binding, baseline);\n updateFieldState(path, {\n value,\n initialValue,\n dirty: !deepEqual(value, initialValue),\n validating: false,\n ...(reset ? { touched: false, error: undefined } : {})\n });\n }\n }\n function subscribe(path: string, listener: () => void): () => void {\n let set = listeners.get(path);\n if (!set) {\n set = new Set();\n listeners.set(path, set);\n }\n set.add(listener);\n return () => {\n set.delete(listener);\n if (set.size === 0) listeners.delete(path);\n };\n }\n function subscribeGlobal(listener: () => void): () => void {\n globalListeners.add(listener);\n return () => {\n globalListeners.delete(listener);\n };\n }\n function getSubmissionState() {\n return submission;\n }\n function setSubmissionState(patch: Partial<FormSubmissionState>) {\n const next = { ...submission, ...patch };\n if (\n next.submitting === submission.submitting &&\n next.error === submission.error\n )\n return;\n submission = next;\n for (const listener of globalListeners) listener();\n }\n function getValues() {\n return values;\n }\n function getRevision() {\n return revision;\n }\n function setValues(newValues: any) {\n values = deepClone(newValues ?? {});\n revision++;\n syncFields(false);\n }\n function setFieldValue(\n path: string,\n value: any,\n createMissingStructure: boolean\n ) {\n const next = deepClone(values);\n if (\n bindings\n .get(path)\n ?.setValue(next, deepClone(value), { createMissingStructure })\n ) {\n setValues(next);\n }\n }\n function resetAll(newInitialValues?: any) {\n values = deepClone(newInitialValues ?? {});\n baseline = values;\n revision++;\n syncFields(true);\n setSubmissionState({ error: undefined });\n }\n function getAllFieldPaths() {\n return Array.from(bindings.keys());\n }\n\n return {\n registerField,\n getFieldState,\n updateFieldState,\n subscribe,\n subscribeGlobal,\n getValues,\n setValues,\n setFieldValue,\n resetAll,\n getAllFieldPaths,\n getRevision,\n getSubmissionState,\n setSubmissionState,\n notifyAll\n };\n}\n\nexport type FormStore = ReturnType<typeof createFormStore>;\n","import type {\n InferType,\n ObjectSchemaBuilder,\n PropertyDescriptorTree,\n SchemaBuilder\n} from '@cleverbrush/schema';\nimport { SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR } from '@cleverbrush/schema';\nimport type { ReactNode } from 'react';\nimport { Field, type FieldProps, FormSystemProvider } from './components.js';\nimport { getSchemaType } from './helpers.js';\nimport type { SchemaFormInstance } from './hooks.js';\nimport type { FieldRenderer } from './types.js';\n\ndeclare const rendererTypes: unique symbol;\n\n/** A renderer whose accepted values and custom props survive registration. */\nexport type TypedFieldRenderer<TValue, TProps> = FieldRenderer<\n TValue,\n TProps\n> & {\n readonly [rendererTypes]: { value: TValue; props: TProps };\n};\n\n/**\n * Attach type information without adding a UI dependency or runtime wrapper.\n * Include null in TValue when the renderer supports nullable fields.\n */\nexport function defineFieldRenderer<TValue, TProps = Record<string, never>>(\n renderer: FieldRenderer<TValue, TProps>\n): TypedFieldRenderer<TValue, TProps> {\n return renderer as TypedFieldRenderer<TValue, TProps>;\n}\n\nexport type TypedRendererRegistry = Readonly<\n Record<string, TypedFieldRenderer<any, any>>\n>;\n\ntype ValueOf<T> = T extends TypedFieldRenderer<infer V, any> ? V : never;\ntype PropsOf<T> = T extends TypedFieldRenderer<any, infer P> ? P : never;\ntype KindOf<T> = 0 extends 1 & T\n ? string\n : [NonNullable<T>] extends [string]\n ? 'string'\n : [NonNullable<T>] extends [number]\n ? 'number'\n : [NonNullable<T>] extends [boolean]\n ? 'boolean'\n : [NonNullable<T>] extends [Date]\n ? 'date'\n : [NonNullable<T>] extends [readonly unknown[]]\n ? 'array'\n : [NonNullable<T>] extends [object]\n ? 'object'\n : never;\ntype CustomProps<P> = {} extends P ? { fieldProps?: P } : { fieldProps: P };\ntype RendererChoice<R extends TypedRendererRegistry, V> = {\n [K in keyof R & string]: [Exclude<V, undefined>] extends [ValueOf<R[K]>]\n ? K extends `${KindOf<V>}:${infer Variant}`\n ? { variant: Variant } & CustomProps<PropsOf<R[K]>>\n : K extends KindOf<V>\n ? { variant?: undefined } & CustomProps<PropsOf<R[K]>>\n : never\n : never;\n}[keyof R & string];\n\ntype FieldDescriptor = {\n readonly [SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR]: {\n getSchema: () => SchemaBuilder<any, any, any, any>;\n };\n};\ntype DescriptorValue<D extends FieldDescriptor> = InferType<\n ReturnType<D[typeof SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR]['getSchema']>\n>;\n\n/** Props are inferred from the selected schema property and registered variant. */\nexport type TypedFieldProps<\n R extends TypedRendererRegistry,\n TSchema extends ObjectSchemaBuilder<any, any, any>,\n TDescriptor extends FieldDescriptor\n> = {\n form: SchemaFormInstance<TSchema>;\n forProperty: (\n tree: PropertyDescriptorTree<TSchema, TSchema>\n ) => TDescriptor;\n label?: string;\n name?: string;\n} & RendererChoice<R, NoInfer<DescriptorValue<TDescriptor>>>;\n\n/** Named callable type also supports exporting system.Field from UI packages. */\nexport type TypedFieldComponent<R extends TypedRendererRegistry> = <\n TSchema extends ObjectSchemaBuilder<any, any, any>,\n TDescriptor extends FieldDescriptor\n>(\n props: TypedFieldProps<R, TSchema, TDescriptor>\n) => ReactNode;\n\n/** Named return type keeps exported consumer registries declaration-safe. */\nexport type TypedFormSystem<R extends TypedRendererRegistry> = {\n Field: TypedFieldComponent<R>;\n Provider: (props: { children: ReactNode }) => ReactNode;\n renderers: Readonly<R>;\n};\n\n/**\n * Create a typed Field and a provider for an application's renderer registry.\n * The typed Field resolves from this factory's closed registry, so an untyped\n * ancestor provider cannot silently replace a renderer with incompatible props.\n * The Provider also configures legacy Field consumers and supports nesting.\n * Extend a system with createFormSystem({ renderers: { ...system.renderers,\n * 'string:custom': customRenderer } }). Existing global APIs remain available.\n */\nexport function createFormSystem<\n const R extends TypedRendererRegistry\n>(config: { renderers: R }): TypedFormSystem<R> {\n const renderers = Object.freeze({ ...config.renderers });\n function TypedField<\n TSchema extends ObjectSchemaBuilder<any, any, any>,\n TDescriptor extends FieldDescriptor\n >(props: TypedFieldProps<R, TSchema, TDescriptor>): ReactNode {\n const descriptor = props.forProperty(\n props.form._getFormContext()\n .descriptorTree as PropertyDescriptorTree<TSchema, TSchema>\n );\n const type = getSchemaType(\n descriptor[SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR].getSchema()\n );\n const key = props.variant ? `${type}:${props.variant}` : type;\n const renderer = renderers[key];\n if (!renderer)\n throw new Error(\n `No renderer registered for \"${key}\" in this form system.`\n );\n // Field's legacy signature erases descriptor parent types. The factory\n // has already checked the selected value and renderer-specific props.\n return (\n <Field\n {...(props as unknown as FieldProps<TSchema>)}\n renderer={renderer}\n />\n );\n }\n function Provider({ children }: { children: ReactNode }): ReactNode {\n return (\n <FormSystemProvider renderers={renderers}>\n {children}\n </FormSystemProvider>\n );\n }\n return { Field: TypedField, Provider, renderers };\n}\n"],"mappings":"AAQA,OAAS,cAAAA,EAAY,WAAAC,OAAe,QCHpC,OAAS,iBAAAC,MAAqB,QAOvB,IAAMC,EAAoBD,EAAuC,IAAI,EAkB/DE,EAAcF,EAAuC,IAAI,ECzBtE,OACI,uBAAAG,GACA,qCAAAC,MACG,sBAMA,SAASC,EACZC,EACAC,EACmD,CACnD,IAAMC,EAAM,IAAI,IACVC,EAAeF,EAAO,WAAW,EACvC,GAAI,CAACE,EAAa,WAAY,OAAOD,EAErC,QAAWE,KAAY,OAAO,KAAKD,EAAa,UAAU,EAAG,CACzD,IAAME,EAAkBL,EAAaI,CAAQ,EAC7C,GACI,CAACC,GACD,EAAEP,KAAqCO,GAEvC,SAEJ,IAAMC,EAAQD,EACVP,CACJ,EACAI,EAAI,IAAII,EAAOF,CAAQ,EAGvB,IAAMG,EAAaJ,EAAa,WAAWC,CAAQ,EACnD,GAAIG,aAAsBV,GAAqB,CAC3C,IAAMW,EAAWT,EAAuBM,EAAgBE,CAAU,EAClE,OAAW,CAACE,EAAYC,CAAS,IAAKF,EAClCN,EAAI,IAAIO,EAAY,GAAGL,CAAQ,IAAIM,CAAS,EAAE,CAEtD,CACJ,CAEA,OAAOR,CACX,CAeO,SAASS,EACZC,EACM,CAEN,OADqBA,EAAO,WAAW,GAClB,MAAQ,SACjC,CA6CO,SAASC,EACZC,EACAC,EACG,CACH,IAAMC,EAAeD,EAAO,WAAW,EACvC,GAAI,CAACC,EAAa,WAAY,OAAOF,GAA0B,CAAC,EAEhE,IAAMG,EAASH,GAAU,KAAO,CAAE,GAAGA,CAAO,EAAI,CAAC,EACjD,QAAWI,KAAO,OAAO,KAAKF,EAAa,UAAU,EAAG,CACpD,IAAMG,EAAaH,EAAa,WAAWE,CAAG,EAC1CC,aAAsBC,KACtBH,EAAOC,CAAG,EAAIL,EAAsBI,EAAOC,CAAG,EAAGC,CAAU,EAEnE,CACA,OAAOF,CACX,CCtHA,OACI,uBAAAI,GACA,qCAAAC,OACG,sBACP,OACI,eAAAC,EACA,aAAAC,GACA,WAAAC,GACA,UAAAC,EACA,wBAAAC,OACG,QClBP,OAAS,aAAAC,EAAW,aAAAC,OAAiB,oBAS9B,SAASC,GAAgBC,EAAoB,CAChD,IAAIC,EAASJ,EAAUG,GAAiB,CAAC,CAAC,EACtCE,EAAWD,EACXE,EAAW,EACXC,EAAkC,CAClC,WAAY,GACZ,MAAO,MACX,EACMC,EAAW,IAAI,IACfC,EAAc,IAAI,IAClBC,EAAY,IAAI,IAChBC,EAAkB,IAAI,IAE5B,SAASC,EAAKC,EAA8BC,EAAa,CACrD,IAAMC,EAASF,GAAS,SAASC,CAAM,EACvC,OAAOC,GAAQ,QAAUA,EAAO,MAAQ,MAC5C,CACA,SAASC,EAAcC,EAA0B,CAC7C,GAAI,CAACR,EAAY,IAAIQ,CAAI,EAAG,CACxB,IAAMJ,EAAUL,EAAS,IAAIS,CAAI,EAC3BC,EAAQN,EAAKC,EAAST,CAAM,EAC5Be,EAAeP,EAAKC,EAASR,CAAQ,EAC3CI,EAAY,IAAIQ,EAAM,CAClB,MAAAC,EACA,aAAAC,EACA,MAAO,CAAClB,GAAUiB,EAAOC,CAAY,EACrC,QAAS,GACT,MAAO,OACP,WAAY,EAChB,CAAC,CACL,CACA,OAAOV,EAAY,IAAIQ,CAAI,CAC/B,CACA,SAASG,EAAcH,EAAcJ,EAAkB,CACnD,OAAKL,EAAS,IAAIS,CAAI,GAAGT,EAAS,IAAIS,EAAMJ,CAAO,EAC5CG,EAAcC,CAAI,CAC7B,CACA,SAASI,EAAWJ,EAAc,CAC9B,QAAWK,KAAYZ,EAAU,IAAIO,CAAI,GAAK,CAAC,EAAGK,EAAS,CAC/D,CACA,SAASC,GAAY,CACjB,QAAWN,KAAQP,EAAU,KAAK,EAAGW,EAAWJ,CAAI,EACpD,QAAWK,KAAYX,EAAiBW,EAAS,CACrD,CACA,SAASE,EAAiBP,EAAcQ,EAA4B,CAChE,IAAMC,EAAUV,EAAcC,CAAI,EAE9B,OAAO,QAAQQ,CAAK,EAAE,MAAM,CAAC,CAACE,EAAKT,CAAK,IACpC,OAAO,GAAGQ,EAAQC,CAAuB,EAAGT,CAAK,CACrD,IAGJT,EAAY,IAAIQ,EAAM,CAAE,GAAGS,EAAS,GAAGD,CAAM,CAAC,EAC9CJ,EAAWJ,CAAI,EACnB,CACA,SAASW,EAAWC,EAAgB,CAChC,OAAW,CAACZ,EAAMJ,CAAO,IAAKL,EAAU,CACpC,IAAMU,EAAQN,EAAKC,EAAST,CAAM,EAC5Be,EAAeP,EAAKC,EAASR,CAAQ,EAC3CmB,EAAiBP,EAAM,CACnB,MAAAC,EACA,aAAAC,EACA,MAAO,CAAClB,GAAUiB,EAAOC,CAAY,EACrC,WAAY,GACZ,GAAIU,EAAQ,CAAE,QAAS,GAAO,MAAO,MAAU,EAAI,CAAC,CACxD,CAAC,CACL,CACJ,CACA,SAASC,EAAUb,EAAcK,EAAkC,CAC/D,IAAIS,EAAMrB,EAAU,IAAIO,CAAI,EAC5B,OAAKc,IACDA,EAAM,IAAI,IACVrB,EAAU,IAAIO,EAAMc,CAAG,GAE3BA,EAAI,IAAIT,CAAQ,EACT,IAAM,CACTS,EAAI,OAAOT,CAAQ,EACfS,EAAI,OAAS,GAAGrB,EAAU,OAAOO,CAAI,CAC7C,CACJ,CACA,SAASe,EAAgBV,EAAkC,CACvD,OAAAX,EAAgB,IAAIW,CAAQ,EACrB,IAAM,CACTX,EAAgB,OAAOW,CAAQ,CACnC,CACJ,CACA,SAASW,GAAqB,CAC1B,OAAO1B,CACX,CACA,SAAS2B,EAAmBT,EAAqC,CAC7D,IAAMU,EAAO,CAAE,GAAG5B,EAAY,GAAGkB,CAAM,EACvC,GACI,EAAAU,EAAK,aAAe5B,EAAW,YAC/B4B,EAAK,QAAU5B,EAAW,OAG9B,CAAAA,EAAa4B,EACb,QAAWb,KAAYX,EAAiBW,EAAS,EACrD,CACA,SAASc,GAAY,CACjB,OAAOhC,CACX,CACA,SAASiC,GAAc,CACnB,OAAO/B,CACX,CACA,SAASgC,EAAUC,EAAgB,CAC/BnC,EAASJ,EAAUuC,GAAa,CAAC,CAAC,EAClCjC,IACAsB,EAAW,EAAK,CACpB,CACA,SAASY,EACLvB,EACAC,EACAuB,EACF,CACE,IAAMN,EAAOnC,EAAUI,CAAM,EAEzBI,EACK,IAAIS,CAAI,GACP,SAASkB,EAAMnC,EAAUkB,CAAK,EAAG,CAAE,uBAAAuB,CAAuB,CAAC,GAEjEH,EAAUH,CAAI,CAEtB,CACA,SAASO,EAASC,EAAwB,CACtCvC,EAASJ,EAAU2C,GAAoB,CAAC,CAAC,EACzCtC,EAAWD,EACXE,IACAsB,EAAW,EAAI,EACfM,EAAmB,CAAE,MAAO,MAAU,CAAC,CAC3C,CACA,SAASU,GAAmB,CACxB,OAAO,MAAM,KAAKpC,EAAS,KAAK,CAAC,CACrC,CAEA,MAAO,CACH,cAAAY,EACA,cAAAJ,EACA,iBAAAQ,EACA,UAAAM,EACA,gBAAAE,EACA,UAAAI,EACA,UAAAE,EACA,cAAAE,EACA,SAAAE,EACA,iBAAAE,EACA,YAAAP,EACA,mBAAAJ,EACA,mBAAAC,EACA,UAAAX,CACJ,CACJ,CD7FO,SAASsB,GAGZC,EACAC,EAC2B,CAC3B,IAAMC,EAAWC,EAAyB,IAAI,EACzCD,EAAS,UAASA,EAAS,QAAUE,GAAgB,CAAC,CAAC,GAC5D,IAAMC,EAAQH,EAAS,QACjBI,EAAoBH,EAGhB,IAAI,EACTG,EAAkB,UACnBA,EAAkB,QAAUC,GAAoB,iBAC5CP,CACJ,GAEJ,IAAMQ,EAAiBF,EAAkB,QACnCG,EAAaN,EAGT,IAAI,EACTM,EAAW,UACZA,EAAW,QAAUC,EAAuBF,EAAgBR,CAAM,GAEtE,IAAMW,EAAUF,EAAW,QAC3B,OAAW,CAACG,CAAU,IAAKD,EACvBN,EAAM,cAAcO,EAAW,cAAc,EAAGA,CAAU,EAE9D,IAAMC,EAAYV,EAAOH,CAAM,EACzBc,EAAaX,EAA6B,CAAC,CAAC,EAClDW,EAAW,QAAU,CAAE,uBAAwB,GAAM,GAAGb,CAAQ,EAChE,IAAMc,EAAaZ,EAAO,EAAI,EACxBa,EAAWb,EAAO,CAAC,EACnBc,EAAmBd,EAAO,CAAC,EAC3Be,EAAoBf,EAAO,EAAK,EAChCgB,EAAWhB,EAA6C,IAAI,EAC5DiB,EAA4BC,EAAY,IAAM,CAC5CF,EAAS,UAAY,MAAM,aAAaA,EAAS,OAAO,EAC5DA,EAAS,QAAU,IACvB,EAAG,CAAC,CAAC,EACLG,GAAU,KACNP,EAAW,QAAU,GACd,IAAM,CACTA,EAAW,QAAU,GACrBC,EAAS,UACTC,EAAiB,UACjBG,EAA0B,CAC9B,GACD,CAACA,CAAyB,CAAC,EAE9B,IAAMG,EAAgBF,EAClB,MACIG,GACgD,CAChDJ,EAA0B,EAC1B,IAAMK,EAAM,EAAER,EAAiB,QACzBS,EAAWrB,EAAM,YAAY,EACnC,QAAWsB,KAAQtB,EAAM,iBAAiB,EACtCA,EAAM,iBAAiBsB,EAAM,CAAE,WAAY,EAAK,CAAC,EAErD,IAAMC,EAAaC,EACfxB,EAAM,UAAU,EAChBQ,EAAU,OACd,EACIiB,EACJ,GAAI,CACAA,EAAU,MAAMjB,EAAU,QAAQ,cAAce,EAAY,CACxD,sBAAuB,EAC3B,CAAC,CACL,MAAQ,CACJE,EAAS,CAAE,MAAO,EAAM,CAG5B,CAGA,GACI,CAACf,EAAW,SACZU,IAAQR,EAAiB,SACzBS,IAAarB,EAAM,YAAY,EAE/B,OAAOyB,EAEX,QAAWH,KAAQtB,EAAM,iBAAiB,EACtCA,EAAM,iBAAiBsB,EAAM,CACzB,MAAO,OACP,WAAY,GACZ,GAAIH,EAAc,CAAE,QAAS,EAAK,EAAI,CAAC,CAC3C,CAAC,EAEL,IAAMO,EAAgBD,EAAe,aACrC,GAAI,OAAOC,GAAiB,WACxB,OAAW,CAACnB,CAAU,IAAKD,EAAS,CAChC,IAAMgB,EAAOf,EAAW,cAAc,EAChCoB,EAAQL,EACT,MAAM,CAAC,EACP,MAAM,GAAG,EACT,IAAIM,GACDA,EAAK,QAAQ,MAAO,GAAG,EAAE,QAAQ,MAAO,GAAG,CAC/C,EACJ,GAAI,CACA,IAAMC,EAAQH,EAAcI,GACxBH,EAAM,OACF,CAACI,GAAYC,KAAQD,KAAQC,EAAG,EAChCF,CACJ,CACJ,EAEI,MAAM,QAAQD,GAAO,MAAM,GAC3BA,EAAM,OAAO,QAEb7B,EAAM,iBAAiBsB,EAAM,CACzB,MAAOO,EAAM,OAAO,CAAC,CACzB,CAAC,CAET,MAAQ,CAGR,CACJ,CAEJ,OAAOJ,CACX,EACA,CAACV,EAA2Bf,EAAOM,CAAO,CAC9C,EAEM2B,EAAWjB,EAAY,IAAME,EAAc,EAAI,EAAG,CAACA,CAAa,CAAC,EACjEgB,EAASlB,EAAY,IAAMiB,EAAS,EAAG,CAACA,CAAQ,CAAC,EACjDE,EAAQnB,EACToB,GAAyC,CACtCzB,EAAS,UACTC,EAAiB,UACjBG,EAA0B,EAC1Bf,EAAM,SAASoC,CAAM,CACzB,EACA,CAACpC,EAAOe,CAAyB,CACrC,EACMsB,EAAWrB,EACb,IAA0BhB,EAAM,UAAU,EAC1C,CAACA,CAAK,CACV,EACMsC,EAAWtB,EACZoB,GAAwC,CACrCrB,EAA0B,EAC1Bf,EAAM,UAAU,CAAE,GAAGA,EAAM,UAAU,EAAG,GAAGoC,CAAO,CAAC,CACvD,EACA,CAACpC,EAAOe,CAAyB,CACrC,EACMwB,EAAoBvB,EACrBG,GAAyB,CACtBJ,EAA0B,EAC1B,IAAMyB,EAAQ/B,EAAW,QAAQ,qBACjC,OAAI+B,GAAS,MAAQA,EAAQ,GACzB1B,EAAS,QAAU,WAAW,IAAM,CAChCA,EAAS,QAAU,KACdI,EAAcC,CAAW,CAClC,EAAGqB,CAAK,EACD,QAAQ,QAAQ,GAEpBtB,EAAcC,CAAW,CACpC,EACA,CAACD,EAAeH,CAAyB,CAC7C,EAEM0B,EAAezB,EACjB,CACI0B,EAGAC,IAEA,MAAMC,GAAS,CAEX,GADAA,GAAO,eAAe,EAClB/B,EAAkB,SAAW,CAACH,EAAW,QAAS,OACtDG,EAAkB,QAAU,GAC5B,IAAMgC,EAAQlC,EAAS,QACjBmC,EAAU,IACZpC,EAAW,SAAWmC,IAAUlC,EAAS,QAC7CX,EAAM,mBAAmB,CACrB,WAAY,GACZ,MAAO,MACX,CAAC,EACD,GAAI,CACA,IAAMqB,EAAWrB,EAAM,YAAY,EAC7ByB,EAAS,MAAMP,EAAc,EAAI,EACvC,GACI,CAAC4B,EAAQ,GACTzB,IAAarB,EAAM,YAAY,GAC/B,CAACyB,EAAO,OACRA,EAAO,SAAW,OAElB,OACJ,IAAMW,EAASX,EAAO,OAClBsB,EACJ,GAAI,CACAA,EAAU,MAAML,EAAQN,CAAM,CAClC,OAASY,EAAO,CACZ,GAAI,CAACF,EAAQ,EAAG,OAChB,GAAI,CAACH,GAAmB,QAAS,MAAMK,EACvC,IAAMC,EAAU,MAAMN,EAAkB,QAAQK,CAAK,EACjDF,EAAQ,GACR9C,EAAM,mBAAmB,CAAE,MAAOiD,CAAQ,CAAC,EAC/C,MACJ,CACA,GAAI,CAACH,EAAQ,EAAG,OAChB,GAAIC,GAAW,CAACA,EAAQ,GAAI,CACxB/C,EAAM,mBAAmB,CAAE,MAAO+C,EAAQ,KAAM,CAAC,EACjD,MACJ,CAGA,MAAMJ,GAAmB,YAAYI,GAAS,KAAMX,CAAM,CAC9D,QAAE,CACEvB,EAAkB,QAAU,GACxBH,EAAW,SACXV,EAAM,mBAAmB,CAAE,WAAY,EAAM,CAAC,CACtD,CACJ,EACJ,CAACkB,EAAelB,CAAK,CACzB,EAEMkD,EAAmBC,GACrB,KAAO,CACH,MAAAnD,EACA,eAAAG,EACA,OAAQK,EAAU,QAClB,QAAAF,EACA,IAAI,SAAU,CACV,OAAOG,EAAW,OACtB,EACA,kBAAA8B,CACJ,GACA,CAACvC,EAAOG,EAAgBG,EAASiC,CAAiB,CACtD,EACMa,EAAiBtD,EAAOoD,CAAgB,EAC9CE,EAAe,QAAUF,EACzB,IAAMG,EAAkBrC,EAAY,IAAMoC,EAAe,QAAS,CAAC,CAAC,EAC9DE,EAAetC,EAEbuC,GAIAC,EAAoBJ,EAAe,QAASG,CAAQ,EACxD,CAAC,CACL,EACME,EAAqB3D,EAAOF,GAAS,eAAe,EAC1D,OAAAqB,GAAU,IAAM,CACRwC,EAAmB,SAAcvC,EAAc,EAAI,CAC3D,EAAG,CAACA,CAAa,CAAC,EAGlBwC,GACI1D,EAAM,gBACNA,EAAM,mBACNA,EAAM,kBACV,EACOmD,GACH,KAAO,CACH,SAAUG,EACV,OAAApB,EACA,SAAAD,EACA,MAAAE,EACA,SAAAE,EACA,SAAAC,EACA,aAAAG,EACA,gBAAAY,EACA,IAAI,YAAa,CACb,OAAOrD,EAAM,mBAAmB,EAAE,UACtC,EACA,IAAI,OAAQ,CACR,OAAOA,EAAM,mBAAmB,EAAE,KACtC,CACJ,GACA,CACIsD,EACApB,EACAD,EACAE,EACAE,EACAC,EACAG,EACAY,EACArD,CACJ,CACJ,CACJ,CAGO,SAASwD,EACZG,EACAC,EACArB,EAAoBoB,EAAY,kBAClB,CACd,GAAM,CAAE,MAAA3D,EAAO,eAAAG,EAAgB,QAAAP,CAAQ,EAAI+D,EACrCE,EACFD,EAAYzD,CAAc,EAAE2D,EAAiC,EAC3DxC,EAAOuC,EAAM,cAAc,EACjC7D,EAAM,cAAcsB,EAAMuC,CAAK,EAC/B,IAAME,EAAY/C,EACbgD,GAAyBhE,EAAM,UAAUsB,EAAM0C,CAAQ,EACxD,CAAChE,EAAOsB,CAAI,CAChB,EACM2C,EAAcjD,EAChB,IAAMhB,EAAM,cAAcsB,CAAI,EAC9B,CAACtB,EAAOsB,CAAI,CAChB,EACM4C,EAAaR,GACfK,EACAE,EACAA,CACJ,EACME,EAAWnD,EACZe,GAAe,CACZ/B,EAAM,cACFsB,EACAS,EACAnC,EAAQ,yBAA2B,EACvC,EACK2C,IAAoB,EAAK,CAClC,EACA,CAACvC,EAAOsB,EAAM1B,EAAQ,uBAAwB2C,CAAiB,CACnE,EACM6B,EAASpD,EACX,IAAMhB,EAAM,iBAAiBsB,EAAM,CAAE,QAAS,EAAK,CAAC,EACpD,CAACtB,EAAOsB,CAAI,CAChB,EACA,MAAO,CACH,GAAG4C,EACH,SAAAC,EACA,OAAAC,EACA,SAAUD,EACV,OAAQN,EAAM,UAAU,CAC5B,CACJ,CAGO,SAASQ,GACZC,EACA3E,EACA4E,EACyB,CACzB,GAAI,CAACD,GAAQ,UAAW,OACxB,IAAME,EAAOC,EAAc9E,CAAM,EACjC,OACK4E,EAAUD,EAAO,UAAU,GAAGE,CAAI,IAAID,CAAO,EAAE,EAAI,SACpDD,EAAO,UAAUE,CAAI,CAE7B,CHxVQ,cAAAE,OAAA,oBA3BD,SAASC,EAAmB,CAC/B,UAAAC,EACA,OAAAC,EACA,SAAAC,CACJ,EAA6C,CACzC,IAAMC,EAAeC,EAAWC,CAAiB,EAE3CC,EAAmCC,GAAQ,IAAM,CACnD,IAAMC,EAA4B,CAC9B,GAAGP,EACH,UAAW,CACP,GAAGA,GAAQ,UACX,GAAGD,CACP,CACJ,EACA,OAAKG,EACE,CACH,GAAGA,EACH,GAAGK,EACH,UAAW,CACP,GAAGL,EAAa,UAChB,GAAGK,EAAQ,SACf,CACJ,EAR0BA,CAS9B,EAAG,CAACL,EAAcF,EAAQD,CAAS,CAAC,EAEpC,OACIF,GAACO,EAAkB,SAAlB,CAA2B,MAAOC,EAC9B,SAAAJ,EACL,CAER,CAcO,SAASO,GAEd,CAAE,KAAAC,EAAM,SAAAR,CAAS,EAAgD,CAC/D,IAAMS,EAAcD,EAAK,gBAAgB,EACzC,OACIZ,GAACc,EAAY,SAAZ,CAAqB,MAAOD,EACxB,SAAAT,EACL,CAER,CAcO,SAASW,GAIZC,EAG0C,CAC1C,IAAMH,EAAcP,EAAWQ,CAAW,EAC1C,GAAI,CAACD,EACD,MAAM,IAAI,MACN,wGAEJ,EAEJ,OAAOI,EAAoBJ,EAAaG,CAAW,CAGvD,CAOO,SAASE,IAAkC,CAC9C,IAAMf,EAASG,EAAWC,CAAiB,EAC3C,GAAI,CAACJ,EACD,MAAM,IAAI,MACN,wDACJ,EAEJ,OAAOA,CACX,CA8CO,SAASgB,EAA0D,CACtE,YAAAH,EACA,KAAAJ,EACA,SAAAQ,EACA,QAAAC,EACA,MAAAC,EACA,KAAAC,EACA,WAAAC,CACJ,EAAyC,CACrC,IAAMC,EAAcb,EAAK,SAASI,CAAW,EACvCU,EAAepB,EAAWC,CAAiB,EAE3CoB,EACFP,GAAYQ,GAAgBF,EAAcD,EAAY,OAAQJ,CAAO,EAEzE,GAAI,CAACM,EAAkB,CACnB,IAAME,EAAaC,EAAcL,EAAY,MAAM,EAC7CM,EAAQV,EACR,IAAIQ,CAAU,IAAIR,CAAO,SAASQ,CAAU,IAC5C,IAAIA,CAAU,IACpB,MAAM,IAAI,MACN,qCAAqCE,CAAK,mEAE9C,CACJ,CAEA,OAAOJ,EAAiB,CACpB,MAAOF,EAAY,MACnB,aAAcA,EAAY,aAC1B,MAAOA,EAAY,MACnB,QAASA,EAAY,QACrB,MAAOA,EAAY,MACnB,WAAYA,EAAY,WACxB,SAAUA,EAAY,SACtB,OAAQA,EAAY,OACpB,SAAUA,EAAY,SACtB,OAAQA,EAAY,OACpB,QAAAJ,EACA,MAAAC,EACA,KAAAC,EACA,WAAAC,CACJ,CAAC,CACL,CKrOA,OAAS,qCAAAQ,OAAyC,sBAiItC,cAAAC,OAAA,oBA5GL,SAASC,GACZC,EACkC,CAClC,OAAOA,CACX,CAgFO,SAASC,GAEdC,EAA8C,CAC5C,IAAMC,EAAY,OAAO,OAAO,CAAE,GAAGD,EAAO,SAAU,CAAC,EACvD,SAASE,EAGPC,EAA4D,CAC1D,IAAMC,EAAaD,EAAM,YACrBA,EAAM,KAAK,gBAAgB,EACtB,cACT,EACME,EAAOC,EACTF,EAAWG,EAAiC,EAAE,UAAU,CAC5D,EACMC,EAAML,EAAM,QAAU,GAAGE,CAAI,IAAIF,EAAM,OAAO,GAAKE,EACnDP,EAAWG,EAAUO,CAAG,EAC9B,GAAI,CAACV,EACD,MAAM,IAAI,MACN,+BAA+BU,CAAG,wBACtC,EAGJ,OACIZ,GAACa,EAAA,CACI,GAAIN,EACL,SAAUL,EACd,CAER,CACA,SAASY,EAAS,CAAE,SAAAC,CAAS,EAAuC,CAChE,OACIf,GAACgB,EAAA,CAAmB,UAAWX,EAC1B,SAAAU,EACL,CAER,CACA,MAAO,CAAE,MAAOT,EAAY,SAAAQ,EAAU,UAAAT,CAAU,CACpD","names":["useContext","useMemo","createContext","FormSystemContext","FormContext","ObjectSchemaBuilder","SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR","buildDescriptorPathMap","tree","schema","map","introspected","propName","propDescriptor","inner","propSchema","childMap","childInner","childPath","getSchemaType","schema","ensureNestedStructure","values","schema","introspected","result","key","propSchema","ObjectSchemaBuilder","ObjectSchemaBuilder","SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR","useCallback","useEffect","useMemo","useRef","useSyncExternalStore","deepClone","deepEqual","createFormStore","initialValues","values","baseline","revision","submission","bindings","fieldStates","listeners","globalListeners","read","binding","source","result","getFieldState","path","value","initialValue","registerField","notifyPath","listener","notifyAll","updateFieldState","patch","current","key","syncFields","reset","subscribe","set","subscribeGlobal","getSubmissionState","setSubmissionState","next","getValues","getRevision","setValues","newValues","setFieldValue","createMissingStructure","resetAll","newInitialValues","getAllFieldPaths","useSchemaForm","schema","options","storeRef","useRef","createFormStore","store","descriptorTreeRef","ObjectSchemaBuilder","descriptorTree","pathMapRef","buildDescriptorPathMap","pathMap","descriptor","schemaRef","optionsRef","mountedRef","epochRef","validationGenRef","submissionLockRef","timerRef","cancelScheduledValidation","useCallback","useEffect","runValidation","markTouched","gen","revision","path","safeValues","ensureNestedStructure","result","getErrorsFor","parts","part","field","tree","value","key","validate","submit","reset","values","getValue","setValue","triggerValidation","delay","handleSubmit","onValid","submissionOptions","event","epoch","current","outcome","error","message","formContextValue","useMemo","formContextRef","_getFormContext","useFieldHook","selector","useFieldFromContext","validateOnMountRef","useSyncExternalStore","formContext","forProperty","inner","SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR","subscribe","listener","getSnapshot","fieldState","onChange","onBlur","resolveRenderer","config","variant","type","getSchemaType","jsx","FormSystemProvider","renderers","config","children","parentConfig","useContext","FormSystemContext","resolvedConfig","useMemo","current","FormProvider","form","formContext","FormContext","useField","forProperty","useFieldFromContext","useFormSystem","Field","renderer","variant","label","name","fieldProps","fieldResult","systemConfig","resolvedRenderer","resolveRenderer","schemaType","getSchemaType","tried","SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR","jsx","defineFieldRenderer","renderer","createFormSystem","config","renderers","TypedField","props","descriptor","type","getSchemaType","SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR","key","Field","Provider","children","FormSystemProvider"]}
|
package/dist/system.d.ts
CHANGED
|
@@ -34,7 +34,7 @@ type RendererChoice<R extends TypedRendererRegistry, V> = {
|
|
|
34
34
|
}[keyof R & string];
|
|
35
35
|
type FieldDescriptor = {
|
|
36
36
|
readonly [SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR]: {
|
|
37
|
-
getSchema: () => SchemaBuilder<any, any, any>;
|
|
37
|
+
getSchema: () => SchemaBuilder<any, any, any, any>;
|
|
38
38
|
};
|
|
39
39
|
};
|
|
40
40
|
type DescriptorValue<D extends FieldDescriptor> = InferType<ReturnType<D[typeof SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR]['getSchema']>>;
|
|
@@ -45,6 +45,16 @@ export type TypedFieldProps<R extends TypedRendererRegistry, TSchema extends Obj
|
|
|
45
45
|
label?: string;
|
|
46
46
|
name?: string;
|
|
47
47
|
} & RendererChoice<R, NoInfer<DescriptorValue<TDescriptor>>>;
|
|
48
|
+
/** Named callable type also supports exporting system.Field from UI packages. */
|
|
49
|
+
export type TypedFieldComponent<R extends TypedRendererRegistry> = <TSchema extends ObjectSchemaBuilder<any, any, any>, TDescriptor extends FieldDescriptor>(props: TypedFieldProps<R, TSchema, TDescriptor>) => ReactNode;
|
|
50
|
+
/** Named return type keeps exported consumer registries declaration-safe. */
|
|
51
|
+
export type TypedFormSystem<R extends TypedRendererRegistry> = {
|
|
52
|
+
Field: TypedFieldComponent<R>;
|
|
53
|
+
Provider: (props: {
|
|
54
|
+
children: ReactNode;
|
|
55
|
+
}) => ReactNode;
|
|
56
|
+
renderers: Readonly<R>;
|
|
57
|
+
};
|
|
48
58
|
/**
|
|
49
59
|
* Create a typed Field and a provider for an application's renderer registry.
|
|
50
60
|
* The typed Field resolves from this factory's closed registry, so an untyped
|
|
@@ -55,11 +65,5 @@ export type TypedFieldProps<R extends TypedRendererRegistry, TSchema extends Obj
|
|
|
55
65
|
*/
|
|
56
66
|
export declare function createFormSystem<const R extends TypedRendererRegistry>(config: {
|
|
57
67
|
renderers: R;
|
|
58
|
-
}):
|
|
59
|
-
Field: <TSchema extends ObjectSchemaBuilder<any, any, any>, TDescriptor extends FieldDescriptor>(props: TypedFieldProps<R, TSchema, TDescriptor>) => ReactNode;
|
|
60
|
-
Provider: ({ children }: {
|
|
61
|
-
children: ReactNode;
|
|
62
|
-
}) => ReactNode;
|
|
63
|
-
renderers: Readonly<R>;
|
|
64
|
-
};
|
|
68
|
+
}): TypedFormSystem<R>;
|
|
65
69
|
export {};
|
package/dist/types.d.ts
CHANGED
|
@@ -17,7 +17,7 @@ export type FieldRenderProps<TValue = any, TProps = Record<string, unknown>> = {
|
|
|
17
17
|
onChange: (value: TValue) => void;
|
|
18
18
|
onBlur: () => void;
|
|
19
19
|
setValue: (value: TValue) => void;
|
|
20
|
-
schema: SchemaBuilder<any, any, any>;
|
|
20
|
+
schema: SchemaBuilder<any, any, any, any>;
|
|
21
21
|
/**
|
|
22
22
|
* Rendering variant hint passed from the `Field` component.
|
|
23
23
|
* Used by renderers to select a sub-variant of the base schema type
|
|
@@ -100,7 +100,7 @@ export type UseFieldResult<T = any> = {
|
|
|
100
100
|
onChange: (value: T) => void;
|
|
101
101
|
onBlur: () => void;
|
|
102
102
|
setValue: (value: T) => void;
|
|
103
|
-
schema: SchemaBuilder<any, any, any>;
|
|
103
|
+
schema: SchemaBuilder<any, any, any, any>;
|
|
104
104
|
};
|
|
105
105
|
/**
|
|
106
106
|
* Options for useSchemaForm.
|
package/package.json
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
"email": "andrew_zol@cleverbrush.com"
|
|
6
6
|
},
|
|
7
7
|
"dependencies": {
|
|
8
|
-
"@cleverbrush/deep": "0.0.0-beta-
|
|
9
|
-
"@cleverbrush/schema": "0.0.0-beta-
|
|
8
|
+
"@cleverbrush/deep": "0.0.0-beta-20260909084207",
|
|
9
|
+
"@cleverbrush/schema": "0.0.0-beta-20260909084207"
|
|
10
10
|
},
|
|
11
11
|
"devDependencies": {
|
|
12
12
|
"@types/react": "^19.0.0",
|
|
@@ -48,5 +48,5 @@
|
|
|
48
48
|
},
|
|
49
49
|
"type": "module",
|
|
50
50
|
"types": "./dist/index.d.ts",
|
|
51
|
-
"version": "0.0.0-beta-
|
|
51
|
+
"version": "0.0.0-beta-20260909084207"
|
|
52
52
|
}
|