@xbeeant/form-engine-react 0.0.2 → 0.0.3
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/dist/cjs/components/FormController.cjs +1 -1
- package/dist/cjs/components/NexusField.cjs +1 -1
- package/dist/cjs/components/NexusForm.cjs +1 -1
- package/dist/cjs/hooks/useForm.cjs +1 -1
- package/dist/cjs/index.cjs +1 -1
- package/dist/cjs/styles.css +1 -0
- package/dist/cjs/tailwind.css +1 -0
- package/dist/es/components/FormController.d.ts +4 -0
- package/dist/es/components/FormController.js +6 -0
- package/dist/es/components/NexusField.js +59 -60
- package/dist/es/components/NexusForm.d.ts +8 -1
- package/dist/es/components/NexusForm.js +82 -75
- package/dist/es/hooks/useForm.d.ts +10 -1
- package/dist/es/hooks/useForm.js +9 -6
- package/dist/es/index.js +39 -38
- package/dist/es/styles.css +1 -0
- package/dist/es/tailwind.css +1 -0
- package/dist/umd/index.css +1 -0
- package/dist/umd/index.umd.cjs +1 -1
- package/package.json +3 -3
- package/src/components/FormController.ts +7 -0
- package/src/components/NexusField.tsx +52 -26
- package/src/components/NexusForm.tsx +24 -0
- package/src/hooks/useForm.ts +17 -3
- package/src/index.ts +2 -0
- package/src/styles.css +6 -0
- package/src/vite-env.d.ts +1 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const l=require("@xbeeant/form-engine");class o{engine;formElementRef;getOnFinish;getOnFinishFailed;removeHiddenData=!0;watchers=new Map;globalWatcher=null;constructor(e){this.engine=e??new l.NexusEngine,this.engine.hasPlugin("async-validator")||this.engine.use(new l.AsyncValidatorPlugin(this.engine)),this.formElementRef={current:null},this.getOnFinish=()=>()=>{},this.getOnFinishFailed=()=>()=>{}}_bind(e,t,i){this.formElementRef.current=e,this.getOnFinish=t,this.getOnFinishFailed=i,this.engine.registerOnFieldValueChange((n,r)=>this._onFieldValueChange(n,r))}_syncConfig(e){if(e.removeHiddenData!==void 0&&(this.removeHiddenData=e.removeHiddenData),e.watch){this.watchers.clear(),this.globalWatcher=null;for(const[t,i]of Object.entries(e.watch))t==="#"?this.globalWatcher=i:this.watchers.set(t,i)}}_onFieldValueChange(e,t){const i=this.engine.getFormData(),n=this.removeHiddenData?i:this.engine.getAllFormData();this.globalWatcher&&this.globalWatcher(n,n,e);const r=this.watchers.get(e);r&&r(t,n)}_getEngine(){return this.engine}async submit(){const e=await this.engine.validate();if(e.size>0){this.focusFirstError(e),this.getOnFinishFailed()?.(e);return}const t=this.removeHiddenData?this.engine.getFormData():this.engine.getAllFormData();await this.getOnFinish()?.(t)}focusFirstError(e){const t=this.formElementRef.current;if(!t||e.size===0)return;const i=new Set(e.keys());requestAnimationFrame(()=>{const r=t.querySelectorAll("[data-nexus-field]");for(const s of Array.from(r)){const a=s.getAttribute("data-nexus-field");if(!a||!i.has(a))continue;s.scrollIntoView({behavior:"smooth",block:"center"}),s.querySelector('input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])')?.focus();return}})}resetFields(){this.engine.reset()}setErrorFields(e){this.engine.setErrorFields(e)}setValues(e){this.engine.setFieldValues(e)}setValueByPath(e,t){this.engine.setFieldValue(e,t)}setSchemaByPath(e,t){this.engine.setSchemaByPath(e,t)}setSchema(e){this.engine.setSchema(e)}getValues(e){return this.engine.getFormData(e)}getHiddenValues(){return this.engine.getHiddenValues()}getAllValues(){return this.engine.getAllFormData()}getValueByPath(e){return this.engine.getFieldValue(e)}registerValidator(e,t){this.engine.registerFieldValidator(e,t)}unregisterValidator(e,t){this.engine.unregisterFieldValidator(e,t)}revalidateField(e){this.engine.validateField(e,{trigger:"change"})}getSchema(){return this.engine.getSchema()}removeErrorField(e){this.engine.removeErrorField(e)}scrollToPath(e){this.formElementRef.current?.querySelector(`[data-nexus-field="${e}"]`)?.scrollIntoView({behavior:"smooth",block:"center"})}getFieldError(e){return this.engine.getFieldError(e)}getFieldsError(){return this.engine.getFieldsError()}validateFields(e){return this.engine.validate(e)}getFieldState(e){return this.engine.getFieldState(e)}}exports.FormController=o;
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const l=require("@xbeeant/form-engine");class o{engine;formElementRef;getOnFinish;getOnFinishFailed;removeHiddenData=!0;watchers=new Map;globalWatcher=null;constructor(e){this.engine=e??new l.NexusEngine,this.engine.hasPlugin("async-validator")||this.engine.use(new l.AsyncValidatorPlugin(this.engine)),this.formElementRef={current:null},this.getOnFinish=()=>()=>{},this.getOnFinishFailed=()=>()=>{}}_bind(e,t,i){this.formElementRef.current=e,this.getOnFinish=t,this.getOnFinishFailed=i,this.engine.registerOnFieldValueChange((n,r)=>this._onFieldValueChange(n,r))}_syncConfig(e){if(e.removeHiddenData!==void 0&&(this.removeHiddenData=e.removeHiddenData),e.watch){this.watchers.clear(),this.globalWatcher=null;for(const[t,i]of Object.entries(e.watch))t==="#"?this.globalWatcher=i:this.watchers.set(t,i)}}_onFieldValueChange(e,t){const i=this.engine.getFormData(),n=this.removeHiddenData?i:this.engine.getAllFormData();this.globalWatcher&&this.globalWatcher(n,n,e);const r=this.watchers.get(e);r&&r(t,n)}_getEngine(){return this.engine}getEngine(){return this.engine}async submit(){const e=await this.engine.validate();if(e.size>0){this.focusFirstError(e),this.getOnFinishFailed()?.(e);return}const t=this.removeHiddenData?this.engine.getFormData():this.engine.getAllFormData();await this.getOnFinish()?.(t)}focusFirstError(e){const t=this.formElementRef.current;if(!t||e.size===0)return;const i=new Set(e.keys());requestAnimationFrame(()=>{const r=t.querySelectorAll("[data-nexus-field]");for(const s of Array.from(r)){const a=s.getAttribute("data-nexus-field");if(!a||!i.has(a))continue;s.scrollIntoView({behavior:"smooth",block:"center"}),s.querySelector('input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])')?.focus();return}})}resetFields(){this.engine.reset()}setErrorFields(e){this.engine.setErrorFields(e)}setValues(e){this.engine.setFieldValues(e)}setValueByPath(e,t){this.engine.setFieldValue(e,t)}setSchemaByPath(e,t){this.engine.setSchemaByPath(e,t)}setSchema(e){this.engine.setSchema(e)}getValues(e){return this.engine.getFormData(e)}getHiddenValues(){return this.engine.getHiddenValues()}getAllValues(){return this.engine.getAllFormData()}getValueByPath(e){return this.engine.getFieldValue(e)}registerValidator(e,t){this.engine.registerFieldValidator(e,t)}unregisterValidator(e,t){this.engine.unregisterFieldValidator(e,t)}revalidateField(e){this.engine.validateField(e,{trigger:"change"})}getSchema(){return this.engine.getSchema()}removeErrorField(e){this.engine.removeErrorField(e)}scrollToPath(e){this.formElementRef.current?.querySelector(`[data-nexus-field="${e}"]`)?.scrollIntoView({behavior:"smooth",block:"center"})}getFieldError(e){return this.engine.getFieldError(e)}getFieldsError(){return this.engine.getFieldsError()}validateFields(e){return this.engine.validate(e)}getFieldState(e){return this.engine.getFieldState(e)}}exports.FormController=o;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("react/jsx-runtime"),s=require("react"),_=require("../contexts/FieldInheritContext.cjs"),k=require("../contexts/GridContext.cjs"),L=require("../contexts/LayoutConfigContext.cjs"),M=require("../contexts/NexusContext.cjs"),B=require("../utils/resolveColSpan.cjs");function G({dataPath:t,layoutKey:u}){const{engine:n,config:l,form:b}=M.useNexusContext();s.useSyncExternalStore(i=>n.subscribeField(t,i),()=>n.getFieldVersion(t),()=>n.getFieldVersion(t));const e=n.getFieldState(t),F=s.useContext(k.GridContext),h=s.useContext(L.LayoutConfigContext),c=s.useContext(_.FieldInheritContext),v=s.useCallback(i=>{n.setFieldValue(t,i)},[n,t]),W=s.useCallback(i=>{i.currentTarget.contains(i.relatedTarget)||n.validateField(t,{trigger:"blur"})},[n,t]),w=s.useMemo(()=>e?.meta.enum?e.meta.enum.map((i,d)=>({value:i,label:e.meta.enumNames?.[d]??String(i)})):e?.props.options,[e?.meta.enum,e?.meta.enumNames,e?.props.options]),S=s.useMemo(()=>{const i={};if(e?.reactions){for(const d of e.reactions)if(d.dependencies)for(const y of d.dependencies)i[y]=n.getFieldValue(y)}return i},[e?.reactions,n]);if(!e)return n.getSnapshot()>0&&console.warn(`[NexusField] Field not found: ${t}`),null;if(c.visible===!1||!e.visible)return h.removeHidden===!0?null:o.jsx("div",{className:"hidden","data-nexus-hidden":t});const m=l.readOnly||c.readOnly===!0||e.readOnly,N=c.disabled===!0||e.disabled,p=m&&!!e.meta.readOnlyWidget,j=p?e.meta.readOnlyWidget:e.meta.widget;let r=n.getWidget(j);if(!r&&p&&(r=n.getWidget(e.meta.widget)),!r)return o.jsxs("div",{className:"text-xs text-red-500","data-nexus-field":t,children:['⚠️ Widget "',e.meta.widget,'" 未注册 (path: ',t,")"]});const q=e.meta.displayType??l.displayType,O=e.meta.labelWidth??l.labelWidth,T=e.meta.column??l.column,g=B.resolveColSpan(e.meta.colSpan,F),x={...e.meta.width?{width:e.meta.width,flexShrink:0}:{},...g?{gridColumn:`span ${g}`}:{}},f=n.getFieldWrapper(),V={label:e.meta.label,title:e.meta.title,description:e.meta.description,errors:e.errors,required:e.required,extra:e.meta.extra,width:e.meta.width,displayType:q,labelWidth:O,column:T},C={dataPath:t,path:t,value:e.value,onChange:v,disabled:N,readOnly:m,loading:e.loading,placeholder:e.meta.placeholder,options:w,form:b,dependValues:S,items:e.meta.items,...e.props};let a;return f?a=o.jsx(f,{...V,children:o.jsx(r,{...C})},u):a=o.jsx(r,{...C},u),o.jsx("div",{"data-nexus-field":t,onBlur:W,style:Object.keys(x).length>0?x:void 0,children:a})}exports.NexusField=G;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const u=require("react/jsx-runtime"),e=require("react"),Q=require("../utils/renderTreeNode.cjs"),U=require("./NexusFormProvider.cjs");function o(){}function X({form:r,schema:n,initialValues:h,widgets:l,layouts:c,onFinish:k,onFinishFailed:q,onMount:b,footer:f=!1,className:L,style:O,children:W,labelCol:a,labelWidth:P,colon:D,label:V,displayType:$,readOnly:y,column:I,watch:g,removeHiddenData:R=!0}){const t=r._getEngine(),x=e.useRef(null),F=$??n?.displayType??"row",S=V??n?.label??!0,j=D??n?.colon,s=P??n?.labelWidth,E=y??n?.readOnly??!1,i=I??n?.column;e.useEffect(()=>{l&&t.registerWidgets(l),c&&t.registerLayouts(c)},[t,l,c]);const T=e.useRef(!0),w=e.useRef(h);e.useEffect(()=>{n&&(T.current?(t.init(n,w.current),T.current=!1):t.init(n,t.getFormData()))},[t,n]);const m=e.useRef(b);m.current=b;const C=e.useRef(!1),N=!n||typeof n=="object"&&Object.keys(n).length===0;e.useEffect(()=>{C.current||N||(C.current=!0,m.current?.())},[N]);const v=e.useRef(o),_=e.useRef(o);v.current=k??o,_.current=q??o,e.useEffect(()=>{r._bind(x.current,()=>v.current,()=>_.current)},[r]),e.useEffect(()=>{r._syncConfig({removeHiddenData:R,watch:g})},[r,R,g]);const z=e.useSyncExternalStore(t.subscribeStore,t.getSnapshot,t.getSnapshot),A=e.useMemo(()=>t.getRenderTree(),[t,z]),B=e.useCallback(async p=>{p.preventDefault(),await r.submit()},[r]),G=e.useCallback(()=>{r.resetFields()},[r]);let d=null;f===!0?d=u.jsxs("div",{className:"mt-4",children:[u.jsx("button",{type:"submit",children:"提交"})," ",u.jsx("button",{type:"button",onClick:G,children:"重置"})]}):f&&(d=f);const M=e.useMemo(()=>{if(a)return a;if(s)return{style:{width:typeof s=="number"?`${s}px`:s}}},[a,s]),J=e.useMemo(()=>({labelCol:M,labelWidth:s,colon:j,label:S,displayType:F,readOnly:E,column:i}),[M,s,j,S,F,E,i]);return u.jsx(U.NexusFormProvider,{engine:t,config:J,form:r,children:u.jsxs("form",{ref:x,onSubmit:B,className:L,style:{...O,...i&&i>1?{display:"grid",gridTemplateColumns:`repeat(${i}, 1fr)`,gap:"0 16px"}:{}},noValidate:!0,children:[A.map((p,K)=>Q.renderTreeNode(p,K)),!y&&d,W]})})}exports.NexusForm=X;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("@xbeeant/form-engine"),t=require("react"),u=require("../components/FormController.cjs");function c(r,n){const e=t.useRef(null);return e.current||(e.current=new u.FormController(n??(r?new o.NexusEngine({formId:r}):void 0))),[e.current]}exports.useForm=c;
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./components/FormController.cjs"),o=require("./components/NexusField.cjs"),t=require("./components/NexusForm.cjs"),s=require("./components/NexusFormProvider.cjs"),r=require("./components/NexusLayout.cjs"),u=require("./components/NexusObject.cjs"),n=require("./contexts/FieldInheritContext.cjs"),i=require("./contexts/GridContext.cjs"),c=require("./contexts/LayoutConfigContext.cjs"),l=require("./hooks/useEngine.cjs"),a=require("./hooks/useFieldState.cjs"),F=require("./hooks/useFieldValidator.cjs"),x=require("./hooks/useFieldValue.cjs"),d=require("./hooks/useForm.cjs"),h=require("./hooks/useFormConfig.cjs"),m=require("./hooks/useFormData.cjs"),q=require("./hooks/useWatch.cjs"),_=require("./hooks/useWatchAll.cjs"),C=require("./hooks/useWatchMultiple.cjs"),N=require("./hooks/useWatchState.cjs");exports.FormController=e.FormController;exports.NexusField=o.NexusField;exports.NexusForm=t.NexusForm;exports.NexusFormProvider=s.NexusFormProvider;exports.NexusLayout=r.NexusLayout;exports.NexusObject=u.NexusObject;exports.FieldInheritContext=n.FieldInheritContext;exports.GridContext=i.GridContext;exports.LayoutConfigContext=c.LayoutConfigContext;exports.useEngine=l.useEngine;exports.useFieldState=a.useFieldState;exports.useFieldValidator=F.useFieldValidator;exports.useFieldValue=x.useFieldValue;exports.useForm=d.useForm;exports.useFormConfig=h.useFormConfig;exports.useFormData=m.useFormData;exports.useWatch=q.useWatch;exports.useWatchAll=_.useWatchAll;exports.useWatchMultiple=C.useWatchMultiple;exports.useWatchState=N.useWatchState;
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});require('./styles.css');;/* empty css */const e=require("./components/FormController.cjs"),o=require("./components/NexusField.cjs"),t=require("./components/NexusForm.cjs"),s=require("./components/NexusFormProvider.cjs"),r=require("./components/NexusLayout.cjs"),u=require("./components/NexusObject.cjs"),n=require("./contexts/FieldInheritContext.cjs"),i=require("./contexts/GridContext.cjs"),c=require("./contexts/LayoutConfigContext.cjs"),l=require("./hooks/useEngine.cjs"),a=require("./hooks/useFieldState.cjs"),F=require("./hooks/useFieldValidator.cjs"),x=require("./hooks/useFieldValue.cjs"),d=require("./hooks/useForm.cjs"),h=require("./hooks/useFormConfig.cjs"),m=require("./hooks/useFormData.cjs"),q=require("./hooks/useWatch.cjs"),_=require("./hooks/useWatchAll.cjs"),C=require("./hooks/useWatchMultiple.cjs"),N=require("./hooks/useWatchState.cjs");exports.FormController=e.FormController;exports.NexusField=o.NexusField;exports.NexusForm=t.NexusForm;exports.NexusFormProvider=s.NexusFormProvider;exports.NexusLayout=r.NexusLayout;exports.NexusObject=u.NexusObject;exports.FieldInheritContext=n.FieldInheritContext;exports.GridContext=i.GridContext;exports.LayoutConfigContext=c.LayoutConfigContext;exports.useEngine=l.useEngine;exports.useFieldState=a.useFieldState;exports.useFieldValidator=F.useFieldValidator;exports.useFieldValue=x.useFieldValue;exports.useForm=d.useForm;exports.useFormConfig=h.useFormConfig;exports.useFormData=m.useFormData;exports.useWatch=q.useWatch;exports.useWatchAll=_.useWatchAll;exports.useWatchMultiple=C.useWatchMultiple;exports.useWatchState=N.useWatchState;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-font-weight:initial;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-duration:initial;--tw-ease:initial}}}:root,:host{--color-red-500:oklch(63.7% .237 25.331);--spacing:.25rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--font-weight-bold:700;--ease-in-out:cubic-bezier(.4, 0, .2, 1);--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1)}.visible{visibility:visible}.mt-4{margin-top:calc(var(--spacing) * 4)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.rotate-0{rotate:0deg}.rotate-90{rotate:90deg}.cursor-pointer{cursor:pointer}.gap-1{gap:var(--spacing)}.gap-x-4{column-gap:calc(var(--spacing) * 4)}.border-none{--tw-border-style:none;border-style:none}.bg-transparent{background-color:#0000}.p-0{padding:0}.align-middle{vertical-align:middle}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.text-red-500{color:var(--color-red-500)}.blur{--tw-blur:blur(8px);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-200{--tw-duration:.2s;transition-duration:.2s}.ease-in-out{--tw-ease:var(--ease-in-out);transition-timing-function:var(--ease-in-out)}.select-none{-webkit-user-select:none;user-select:none}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-font-weight:initial;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-duration:initial;--tw-ease:initial}}}:root,:host{--color-red-500:oklch(63.7% .237 25.331);--spacing:.25rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--font-weight-bold:700;--ease-in-out:cubic-bezier(.4, 0, .2, 1);--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1)}.visible{visibility:visible}.mt-4{margin-top:calc(var(--spacing) * 4)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.rotate-0{rotate:0deg}.rotate-90{rotate:90deg}.cursor-pointer{cursor:pointer}.gap-1{gap:var(--spacing)}.gap-x-4{column-gap:calc(var(--spacing) * 4)}.border-none{--tw-border-style:none;border-style:none}.bg-transparent{background-color:#0000}.p-0{padding:0}.align-middle{vertical-align:middle}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.text-red-500{color:var(--color-red-500)}.blur{--tw-blur:blur(8px);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-200{--tw-duration:.2s;transition-duration:.2s}.ease-in-out{--tw-ease:var(--ease-in-out);transition-timing-function:var(--ease-in-out)}.select-none{-webkit-user-select:none;user-select:none}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}
|
|
@@ -25,6 +25,10 @@ export declare class FormController implements NexusFormInstance {
|
|
|
25
25
|
_onFieldValueChange(path: string, value: unknown): void;
|
|
26
26
|
/** 内部:获取 Engine 实例 */
|
|
27
27
|
_getEngine(): NexusEngine;
|
|
28
|
+
/**
|
|
29
|
+
* 获取底层 Engine 实例(用于跨表单联动:linkForm / setFormId 等)
|
|
30
|
+
*/
|
|
31
|
+
getEngine(): NexusEngine;
|
|
28
32
|
submit(): Promise<void>;
|
|
29
33
|
/**
|
|
30
34
|
* 定位到第一个校验失败的字段:按 DOM 渲染顺序查找(保证视觉上的"第一个"),
|
|
@@ -1,98 +1,97 @@
|
|
|
1
|
-
import { jsx as
|
|
2
|
-
import { useSyncExternalStore as
|
|
3
|
-
import { FieldInheritContext as
|
|
4
|
-
import { GridContext as
|
|
5
|
-
import { LayoutConfigContext as
|
|
6
|
-
import { useNexusContext as
|
|
7
|
-
import { resolveColSpan as
|
|
8
|
-
function
|
|
9
|
-
const { engine: i, config:
|
|
10
|
-
|
|
1
|
+
import { jsx as o, jsxs as L } from "react/jsx-runtime";
|
|
2
|
+
import { useSyncExternalStore as $, useContext as m, useCallback as C, useMemo as W } from "react";
|
|
3
|
+
import { FieldInheritContext as D } from "../contexts/FieldInheritContext.js";
|
|
4
|
+
import { GridContext as E } from "../contexts/GridContext.js";
|
|
5
|
+
import { LayoutConfigContext as G } from "../contexts/LayoutConfigContext.js";
|
|
6
|
+
import { useNexusContext as H } from "../contexts/NexusContext.js";
|
|
7
|
+
import { resolveColSpan as I } from "../utils/resolveColSpan.js";
|
|
8
|
+
function X({ dataPath: t, layoutKey: c }) {
|
|
9
|
+
const { engine: i, config: l, form: h } = H();
|
|
10
|
+
$(
|
|
11
11
|
(n) => i.subscribeField(t, n),
|
|
12
12
|
() => i.getFieldVersion(t),
|
|
13
13
|
() => i.getFieldVersion(t)
|
|
14
14
|
);
|
|
15
|
-
const e = i.getFieldState(t),
|
|
15
|
+
const e = i.getFieldState(t), w = m(E), F = m(G), d = m(D), v = C(
|
|
16
16
|
(n) => {
|
|
17
17
|
i.setFieldValue(t, n);
|
|
18
18
|
},
|
|
19
19
|
[i, t]
|
|
20
|
-
),
|
|
20
|
+
), S = C(
|
|
21
21
|
(n) => {
|
|
22
22
|
n.currentTarget.contains(n.relatedTarget) || i.validateField(t, { trigger: "blur" });
|
|
23
23
|
},
|
|
24
24
|
[i, t]
|
|
25
|
-
),
|
|
26
|
-
() => e?.meta.enum ? e.meta.enum.map((n,
|
|
25
|
+
), N = W(
|
|
26
|
+
() => e?.meta.enum ? e.meta.enum.map((n, s) => ({
|
|
27
27
|
value: n,
|
|
28
|
-
label: e.meta.enumNames?.[
|
|
28
|
+
label: e.meta.enumNames?.[s] ?? String(n)
|
|
29
29
|
})) : e?.props.options,
|
|
30
30
|
[e?.meta.enum, e?.meta.enumNames, e?.props.options]
|
|
31
|
-
),
|
|
31
|
+
), O = W(() => {
|
|
32
32
|
const n = {};
|
|
33
33
|
if (e?.reactions) {
|
|
34
|
-
for (const
|
|
35
|
-
if (
|
|
36
|
-
for (const
|
|
37
|
-
n[
|
|
34
|
+
for (const s of e.reactions)
|
|
35
|
+
if (s.dependencies)
|
|
36
|
+
for (const b of s.dependencies)
|
|
37
|
+
n[b] = i.getFieldValue(b);
|
|
38
38
|
}
|
|
39
39
|
return n;
|
|
40
40
|
}, [e?.reactions, i]);
|
|
41
41
|
if (!e)
|
|
42
42
|
return i.getSnapshot() > 0 && console.warn(`[NexusField] Field not found: ${t}`), null;
|
|
43
|
-
if (
|
|
44
|
-
return
|
|
45
|
-
const
|
|
46
|
-
let r = i.getWidget(
|
|
47
|
-
if (!r &&
|
|
48
|
-
return /* @__PURE__ */
|
|
43
|
+
if (d.visible === !1 || !e.visible)
|
|
44
|
+
return F.removeHidden === !0 ? null : /* @__PURE__ */ o("div", { className: "hidden", "data-nexus-hidden": t });
|
|
45
|
+
const p = l.readOnly || d.readOnly === !0 || e.readOnly, T = d.disabled === !0 || e.disabled, u = p && !!e.meta.readOnlyWidget, V = u ? e.meta.readOnlyWidget : e.meta.widget;
|
|
46
|
+
let r = i.getWidget(V);
|
|
47
|
+
if (!r && u && (r = i.getWidget(e.meta.widget)), !r)
|
|
48
|
+
return /* @__PURE__ */ L("div", { className: "text-xs text-red-500", "data-nexus-field": t, children: [
|
|
49
49
|
'⚠️ Widget "',
|
|
50
50
|
e.meta.widget,
|
|
51
51
|
'" 未注册 (path: ',
|
|
52
52
|
t,
|
|
53
53
|
")"
|
|
54
54
|
] });
|
|
55
|
-
const
|
|
55
|
+
const j = e.meta.displayType ?? l.displayType, k = e.meta.labelWidth ?? l.labelWidth, q = e.meta.column ?? l.column, f = I(e.meta.colSpan, w), g = {
|
|
56
56
|
...e.meta.width ? { width: e.meta.width, flexShrink: 0 } : {},
|
|
57
|
-
...
|
|
57
|
+
...f ? { gridColumn: `span ${f}` } : {}
|
|
58
|
+
}, x = i.getFieldWrapper(), B = {
|
|
59
|
+
label: e.meta.label,
|
|
60
|
+
title: e.meta.title,
|
|
61
|
+
description: e.meta.description,
|
|
62
|
+
errors: e.errors,
|
|
63
|
+
required: e.required,
|
|
64
|
+
extra: e.meta.extra,
|
|
65
|
+
width: e.meta.width,
|
|
66
|
+
displayType: j,
|
|
67
|
+
labelWidth: k,
|
|
68
|
+
column: q
|
|
69
|
+
}, y = {
|
|
70
|
+
dataPath: t,
|
|
71
|
+
path: t,
|
|
72
|
+
value: e.value,
|
|
73
|
+
onChange: v,
|
|
74
|
+
disabled: T,
|
|
75
|
+
readOnly: p,
|
|
76
|
+
loading: e.loading,
|
|
77
|
+
placeholder: e.meta.placeholder,
|
|
78
|
+
options: N,
|
|
79
|
+
form: h,
|
|
80
|
+
dependValues: O,
|
|
81
|
+
items: e.meta.items,
|
|
82
|
+
...e.props
|
|
58
83
|
};
|
|
59
|
-
|
|
84
|
+
let a;
|
|
85
|
+
return x ? a = /* @__PURE__ */ o(x, { ...B, children: /* @__PURE__ */ o(r, { ...y }) }, c) : a = /* @__PURE__ */ o(r, { ...y }, c), /* @__PURE__ */ o(
|
|
60
86
|
"div",
|
|
61
87
|
{
|
|
62
88
|
"data-nexus-field": t,
|
|
63
|
-
onBlur:
|
|
64
|
-
style: Object.keys(
|
|
65
|
-
children:
|
|
66
|
-
r,
|
|
67
|
-
{
|
|
68
|
-
dataPath: t,
|
|
69
|
-
path: t,
|
|
70
|
-
value: e.value,
|
|
71
|
-
onChange: F,
|
|
72
|
-
disabled: S,
|
|
73
|
-
readOnly: m,
|
|
74
|
-
loading: e.loading,
|
|
75
|
-
required: e.required,
|
|
76
|
-
title: e.meta.title,
|
|
77
|
-
description: e.meta.description,
|
|
78
|
-
placeholder: e.meta.placeholder,
|
|
79
|
-
label: e.meta.label,
|
|
80
|
-
options: h,
|
|
81
|
-
errors: e.errors,
|
|
82
|
-
extra: e.meta.extra,
|
|
83
|
-
displayType: O,
|
|
84
|
-
labelWidth: T,
|
|
85
|
-
column: V,
|
|
86
|
-
form: b,
|
|
87
|
-
dependValues: w,
|
|
88
|
-
items: e.meta.items,
|
|
89
|
-
...e.props
|
|
90
|
-
},
|
|
91
|
-
y
|
|
92
|
-
)
|
|
89
|
+
onBlur: S,
|
|
90
|
+
style: Object.keys(g).length > 0 ? g : void 0,
|
|
91
|
+
children: a
|
|
93
92
|
}
|
|
94
93
|
);
|
|
95
94
|
}
|
|
96
95
|
export {
|
|
97
|
-
|
|
96
|
+
X as NexusField
|
|
98
97
|
};
|
|
@@ -32,6 +32,13 @@ export interface NexusFormProps {
|
|
|
32
32
|
onFinish?: (formData: Record<string, unknown>) => void | Promise<void>;
|
|
33
33
|
/** 校验失败回调 */
|
|
34
34
|
onFinishFailed?: (errors: Map<string, string[]>) => void;
|
|
35
|
+
/**
|
|
36
|
+
* 表单首次加载回调:非空 schema 首次传入并完成渲染后执行一次
|
|
37
|
+
* - undefined / null / {}(无 properties)均视为「空」schema,不触发
|
|
38
|
+
* - schema 由空变为非空时,于首个非空渲染提交后触发
|
|
39
|
+
* - 后续 schema 变更不重复触发
|
|
40
|
+
*/
|
|
41
|
+
onMount?: () => void;
|
|
35
42
|
/** 是否显示默认 footer(提交/重置按钮),或自定义 footer */
|
|
36
43
|
footer?: boolean | ReactNode;
|
|
37
44
|
/** 自定义类名 */
|
|
@@ -74,4 +81,4 @@ export interface NexusFormProps {
|
|
|
74
81
|
/**
|
|
75
82
|
* NexusForm — 顶层表单组件
|
|
76
83
|
*/
|
|
77
|
-
export declare function NexusForm({ form, schema, initialValues, widgets, layouts, onFinish, onFinishFailed, footer, className, style, children, labelCol, labelWidth, colon, label, displayType, readOnly, column, watch, removeHiddenData, }: NexusFormProps): import("react").JSX.Element;
|
|
84
|
+
export declare function NexusForm({ form, schema, initialValues, widgets, layouts, onFinish, onFinishFailed, onMount, footer, className, style, children, labelCol, labelWidth, colon, label, displayType, readOnly, column, watch, removeHiddenData, }: NexusFormProps): import("react").JSX.Element;
|
|
@@ -1,120 +1,127 @@
|
|
|
1
|
-
import { jsx as b, jsxs as
|
|
2
|
-
import { useRef as
|
|
3
|
-
import { renderTreeNode as
|
|
4
|
-
import { NexusFormProvider as
|
|
1
|
+
import { jsx as b, jsxs as k } from "react/jsx-runtime";
|
|
2
|
+
import { useRef as i, useEffect as l, useSyncExternalStore as Z, useMemo as y, useCallback as O } from "react";
|
|
3
|
+
import { renderTreeNode as H } from "../utils/renderTreeNode.js";
|
|
4
|
+
import { NexusFormProvider as ee } from "./NexusFormProvider.js";
|
|
5
5
|
function s() {
|
|
6
6
|
}
|
|
7
|
-
function
|
|
8
|
-
form:
|
|
9
|
-
schema:
|
|
10
|
-
initialValues:
|
|
7
|
+
function oe({
|
|
8
|
+
form: t,
|
|
9
|
+
schema: e,
|
|
10
|
+
initialValues: D,
|
|
11
11
|
widgets: u,
|
|
12
12
|
layouts: c,
|
|
13
|
-
onFinish:
|
|
14
|
-
onFinishFailed:
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
13
|
+
onFinish: M,
|
|
14
|
+
onFinishFailed: V,
|
|
15
|
+
onMount: g,
|
|
16
|
+
footer: f = !1,
|
|
17
|
+
className: $,
|
|
18
|
+
style: I,
|
|
19
|
+
children: P,
|
|
20
|
+
labelCol: a,
|
|
21
|
+
labelWidth: q,
|
|
22
|
+
colon: w,
|
|
23
|
+
label: z,
|
|
24
|
+
displayType: A,
|
|
25
|
+
readOnly: R,
|
|
26
|
+
column: B,
|
|
26
27
|
watch: m,
|
|
27
|
-
removeHiddenData:
|
|
28
|
+
removeHiddenData: F = !0
|
|
28
29
|
}) {
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
u &&
|
|
32
|
-
}, [
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
}, [
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
|
|
30
|
+
const n = t._getEngine(), x = i(null), S = A ?? e?.displayType ?? "row", C = z ?? e?.label ?? !0, T = w ?? e?.colon, r = q ?? e?.labelWidth, E = R ?? e?.readOnly ?? !1, o = B ?? e?.column;
|
|
31
|
+
l(() => {
|
|
32
|
+
u && n.registerWidgets(u), c && n.registerLayouts(c);
|
|
33
|
+
}, [n, u, c]);
|
|
34
|
+
const N = i(!0), G = i(D);
|
|
35
|
+
l(() => {
|
|
36
|
+
e && (N.current ? (n.init(e, G.current), N.current = !1) : n.init(e, n.getFormData()));
|
|
37
|
+
}, [n, e]);
|
|
38
|
+
const h = i(g);
|
|
39
|
+
h.current = g;
|
|
40
|
+
const j = i(!1), v = !e || typeof e == "object" && Object.keys(e).length === 0;
|
|
41
|
+
l(() => {
|
|
42
|
+
j.current || v || (j.current = !0, h.current?.());
|
|
43
|
+
}, [v]);
|
|
44
|
+
const L = i(s), W = i(s);
|
|
45
|
+
L.current = M ?? s, W.current = V ?? s, l(() => {
|
|
46
|
+
t._bind(
|
|
40
47
|
x.current,
|
|
41
|
-
() =>
|
|
42
|
-
() =>
|
|
48
|
+
() => L.current,
|
|
49
|
+
() => W.current
|
|
43
50
|
);
|
|
44
|
-
}, [
|
|
45
|
-
|
|
46
|
-
}, [
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
),
|
|
51
|
+
}, [t]), l(() => {
|
|
52
|
+
t._syncConfig({ removeHiddenData: F, watch: m });
|
|
53
|
+
}, [t, F, m]);
|
|
54
|
+
const J = Z(
|
|
55
|
+
n.subscribeStore,
|
|
56
|
+
n.getSnapshot,
|
|
57
|
+
n.getSnapshot
|
|
58
|
+
), K = y(() => n.getRenderTree(), [n, J]), Q = O(
|
|
52
59
|
async (p) => {
|
|
53
|
-
p.preventDefault(), await
|
|
60
|
+
p.preventDefault(), await t.submit();
|
|
54
61
|
},
|
|
55
|
-
[
|
|
56
|
-
),
|
|
57
|
-
|
|
58
|
-
}, [
|
|
62
|
+
[t]
|
|
63
|
+
), U = O(() => {
|
|
64
|
+
t.resetFields();
|
|
65
|
+
}, [t]);
|
|
59
66
|
let d = null;
|
|
60
|
-
|
|
67
|
+
f === !0 ? d = /* @__PURE__ */ k("div", { className: "mt-4", children: [
|
|
61
68
|
/* @__PURE__ */ b("button", { type: "submit", children: "提交" }),
|
|
62
69
|
" ",
|
|
63
|
-
/* @__PURE__ */ b("button", { type: "button", onClick:
|
|
64
|
-
] }) :
|
|
65
|
-
const
|
|
66
|
-
if (
|
|
67
|
-
return
|
|
70
|
+
/* @__PURE__ */ b("button", { type: "button", onClick: U, children: "重置" })
|
|
71
|
+
] }) : f && (d = f);
|
|
72
|
+
const _ = y(() => {
|
|
73
|
+
if (a)
|
|
74
|
+
return a;
|
|
68
75
|
if (r)
|
|
69
76
|
return {
|
|
70
77
|
style: {
|
|
71
78
|
width: typeof r == "number" ? `${r}px` : r
|
|
72
79
|
}
|
|
73
80
|
};
|
|
74
|
-
}, [
|
|
81
|
+
}, [a, r]), X = y(
|
|
75
82
|
() => ({
|
|
76
|
-
labelCol:
|
|
83
|
+
labelCol: _,
|
|
77
84
|
labelWidth: r,
|
|
78
|
-
colon:
|
|
85
|
+
colon: T,
|
|
79
86
|
label: C,
|
|
80
|
-
displayType:
|
|
81
|
-
readOnly:
|
|
82
|
-
column:
|
|
87
|
+
displayType: S,
|
|
88
|
+
readOnly: E,
|
|
89
|
+
column: o
|
|
83
90
|
}),
|
|
84
91
|
[
|
|
85
|
-
|
|
92
|
+
_,
|
|
86
93
|
r,
|
|
87
|
-
S,
|
|
88
|
-
C,
|
|
89
|
-
F,
|
|
90
94
|
T,
|
|
91
|
-
|
|
95
|
+
C,
|
|
96
|
+
S,
|
|
97
|
+
E,
|
|
98
|
+
o
|
|
92
99
|
]
|
|
93
100
|
);
|
|
94
|
-
return /* @__PURE__ */ b(
|
|
101
|
+
return /* @__PURE__ */ b(ee, { engine: n, config: X, form: t, children: /* @__PURE__ */ k(
|
|
95
102
|
"form",
|
|
96
103
|
{
|
|
97
104
|
ref: x,
|
|
98
|
-
onSubmit:
|
|
99
|
-
className:
|
|
105
|
+
onSubmit: Q,
|
|
106
|
+
className: $,
|
|
100
107
|
style: {
|
|
101
|
-
...
|
|
108
|
+
...I,
|
|
102
109
|
// 当配置了 column 时,使用 CSS Grid 布局
|
|
103
|
-
...
|
|
110
|
+
...o && o > 1 ? {
|
|
104
111
|
display: "grid",
|
|
105
|
-
gridTemplateColumns: `repeat(${
|
|
112
|
+
gridTemplateColumns: `repeat(${o}, 1fr)`,
|
|
106
113
|
gap: "0 16px"
|
|
107
114
|
} : {}
|
|
108
115
|
},
|
|
109
116
|
noValidate: !0,
|
|
110
117
|
children: [
|
|
111
|
-
|
|
112
|
-
!
|
|
113
|
-
|
|
118
|
+
K.map((p, Y) => H(p, Y)),
|
|
119
|
+
!R && d,
|
|
120
|
+
P
|
|
114
121
|
]
|
|
115
122
|
}
|
|
116
123
|
) });
|
|
117
124
|
}
|
|
118
125
|
export {
|
|
119
|
-
|
|
126
|
+
oe as NexusForm
|
|
120
127
|
};
|
|
@@ -2,5 +2,14 @@ import { NexusEngine } from '@xbeeant/form-engine';
|
|
|
2
2
|
import { FormController } from '../components/FormController';
|
|
3
3
|
/**
|
|
4
4
|
* useForm — 创建 Form 实例
|
|
5
|
+
*
|
|
6
|
+
* 支持一个页面挂载多个表单实例:
|
|
7
|
+
* - `useForm()`:独立实例(未注册,不参与跨表单联动)
|
|
8
|
+
* - `useForm(formId)`:创建带 formId 的实例,自动注册到默认表单注册表,
|
|
9
|
+
* 可通过 schema `crossForm` reaction / `engine.linkForm` 与其他表单联动
|
|
10
|
+
* - `useForm(formId, engine)`:复用外部创建的引擎(如 `new NexusEngine({ formId })`)
|
|
11
|
+
*
|
|
12
|
+
* @param formId - 可选,表单实例唯一标识(跨表单联动寻址)
|
|
13
|
+
* @param engine - 可选,外部引擎实例(缺省内部创建)
|
|
5
14
|
*/
|
|
6
|
-
export declare function useForm(engine?: NexusEngine): [FormController];
|
|
15
|
+
export declare function useForm(formId?: string, engine?: NexusEngine): [FormController];
|
package/dist/es/hooks/useForm.js
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import { NexusEngine as n } from "@xbeeant/form-engine";
|
|
2
|
+
import { useRef as t } from "react";
|
|
3
|
+
import { FormController as u } from "../components/FormController.js";
|
|
4
|
+
function c(e, o) {
|
|
5
|
+
const r = t(null);
|
|
6
|
+
return r.current || (r.current = new u(
|
|
7
|
+
o ?? (e ? new n({ formId: e }) : void 0)
|
|
8
|
+
)), [r.current];
|
|
6
9
|
}
|
|
7
10
|
export {
|
|
8
|
-
|
|
11
|
+
c as useForm
|
|
9
12
|
};
|
package/dist/es/index.js
CHANGED
|
@@ -1,42 +1,43 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import './styles.css';/* empty css */
|
|
2
|
+
import { FormController as t } from "./components/FormController.js";
|
|
3
|
+
import { NexusField as m } from "./components/NexusField.js";
|
|
4
|
+
import { NexusForm as p } from "./components/NexusForm.js";
|
|
5
|
+
import { NexusFormProvider as s } from "./components/NexusFormProvider.js";
|
|
5
6
|
import { NexusLayout as a } from "./components/NexusLayout.js";
|
|
6
|
-
import { NexusObject as
|
|
7
|
-
import { FieldInheritContext as
|
|
8
|
-
import { GridContext as
|
|
9
|
-
import { LayoutConfigContext as
|
|
10
|
-
import { useEngine as
|
|
11
|
-
import { useFieldState as
|
|
12
|
-
import { useFieldValidator as
|
|
13
|
-
import { useFieldValue as
|
|
14
|
-
import { useForm as
|
|
15
|
-
import { useFormConfig as
|
|
16
|
-
import { useFormData as
|
|
17
|
-
import { useWatch as
|
|
18
|
-
import { useWatchAll as
|
|
19
|
-
import { useWatchMultiple as
|
|
20
|
-
import { useWatchState as
|
|
7
|
+
import { NexusObject as F } from "./components/NexusObject.js";
|
|
8
|
+
import { FieldInheritContext as d } from "./contexts/FieldInheritContext.js";
|
|
9
|
+
import { GridContext as c } from "./contexts/GridContext.js";
|
|
10
|
+
import { LayoutConfigContext as N } from "./contexts/LayoutConfigContext.js";
|
|
11
|
+
import { useEngine as g } from "./hooks/useEngine.js";
|
|
12
|
+
import { useFieldState as L } from "./hooks/useFieldState.js";
|
|
13
|
+
import { useFieldValidator as V } from "./hooks/useFieldValidator.js";
|
|
14
|
+
import { useFieldValue as j } from "./hooks/useFieldValue.js";
|
|
15
|
+
import { useForm as A } from "./hooks/useForm.js";
|
|
16
|
+
import { useFormConfig as E } from "./hooks/useFormConfig.js";
|
|
17
|
+
import { useFormData as I } from "./hooks/useFormData.js";
|
|
18
|
+
import { useWatch as O } from "./hooks/useWatch.js";
|
|
19
|
+
import { useWatchAll as k } from "./hooks/useWatchAll.js";
|
|
20
|
+
import { useWatchMultiple as w } from "./hooks/useWatchMultiple.js";
|
|
21
|
+
import { useWatchState as B } from "./hooks/useWatchState.js";
|
|
21
22
|
export {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
23
|
+
d as FieldInheritContext,
|
|
24
|
+
t as FormController,
|
|
25
|
+
c as GridContext,
|
|
26
|
+
N as LayoutConfigContext,
|
|
27
|
+
m as NexusField,
|
|
28
|
+
p as NexusForm,
|
|
29
|
+
s as NexusFormProvider,
|
|
29
30
|
a as NexusLayout,
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
31
|
+
F as NexusObject,
|
|
32
|
+
g as useEngine,
|
|
33
|
+
L as useFieldState,
|
|
34
|
+
V as useFieldValidator,
|
|
35
|
+
j as useFieldValue,
|
|
36
|
+
A as useForm,
|
|
37
|
+
E as useFormConfig,
|
|
38
|
+
I as useFormData,
|
|
39
|
+
O as useWatch,
|
|
40
|
+
k as useWatchAll,
|
|
41
|
+
w as useWatchMultiple,
|
|
42
|
+
B as useWatchState
|
|
42
43
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-font-weight:initial;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-duration:initial;--tw-ease:initial}}}:root,:host{--color-red-500:oklch(63.7% .237 25.331);--spacing:.25rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--font-weight-bold:700;--ease-in-out:cubic-bezier(.4, 0, .2, 1);--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1)}.visible{visibility:visible}.mt-4{margin-top:calc(var(--spacing) * 4)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.rotate-0{rotate:0deg}.rotate-90{rotate:90deg}.cursor-pointer{cursor:pointer}.gap-1{gap:var(--spacing)}.gap-x-4{column-gap:calc(var(--spacing) * 4)}.border-none{--tw-border-style:none;border-style:none}.bg-transparent{background-color:#0000}.p-0{padding:0}.align-middle{vertical-align:middle}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.text-red-500{color:var(--color-red-500)}.blur{--tw-blur:blur(8px);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-200{--tw-duration:.2s;transition-duration:.2s}.ease-in-out{--tw-ease:var(--ease-in-out);transition-timing-function:var(--ease-in-out)}.select-none{-webkit-user-select:none;user-select:none}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-font-weight:initial;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-duration:initial;--tw-ease:initial}}}:root,:host{--color-red-500:oklch(63.7% .237 25.331);--spacing:.25rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--font-weight-bold:700;--ease-in-out:cubic-bezier(.4, 0, .2, 1);--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1)}.visible{visibility:visible}.mt-4{margin-top:calc(var(--spacing) * 4)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.rotate-0{rotate:0deg}.rotate-90{rotate:90deg}.cursor-pointer{cursor:pointer}.gap-1{gap:var(--spacing)}.gap-x-4{column-gap:calc(var(--spacing) * 4)}.border-none{--tw-border-style:none;border-style:none}.bg-transparent{background-color:#0000}.p-0{padding:0}.align-middle{vertical-align:middle}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.text-red-500{color:var(--color-red-500)}.blur{--tw-blur:blur(8px);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-200{--tw-duration:.2s;transition-duration:.2s}.ease-in-out{--tw-ease:var(--ease-in-out);transition-timing-function:var(--ease-in-out)}.select-none{-webkit-user-select:none;user-select:none}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-font-weight:initial;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-duration:initial;--tw-ease:initial}}}:root,:host{--color-red-500:oklch(63.7% .237 25.331);--spacing:.25rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--font-weight-bold:700;--ease-in-out:cubic-bezier(.4, 0, .2, 1);--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1)}.visible{visibility:visible}.mt-4{margin-top:calc(var(--spacing) * 4)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.rotate-0{rotate:0deg}.rotate-90{rotate:90deg}.cursor-pointer{cursor:pointer}.gap-1{gap:var(--spacing)}.gap-x-4{column-gap:calc(var(--spacing) * 4)}.border-none{--tw-border-style:none;border-style:none}.bg-transparent{background-color:#0000}.p-0{padding:0}.align-middle{vertical-align:middle}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.text-red-500{color:var(--color-red-500)}.blur{--tw-blur:blur(8px);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-200{--tw-duration:.2s;transition-duration:.2s}.ease-in-out{--tw-ease:var(--ease-in-out);transition-timing-function:var(--ease-in-out)}.select-none{-webkit-user-select:none;user-select:none}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}
|
package/dist/umd/index.umd.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(a,N){typeof exports=="object"&&typeof module<"u"?N(exports,require("@xbeeant/form-engine"),require("react/jsx-runtime"),require("react")):typeof define=="function"&&define.amd?define(["exports","@xbeeant/form-engine","react/jsx-runtime","react"],N):(a=typeof globalThis<"u"?globalThis:a||self,N(a.NexusFormEngineReact={},a.formEngine,a.jsxRuntime,a.react))})(this,(function(a,N,c,s){"use strict";class P{engine;formElementRef;getOnFinish;getOnFinishFailed;removeHiddenData=!0;watchers=new Map;globalWatcher=null;constructor(t){this.engine=t??new N.NexusEngine,this.engine.hasPlugin("async-validator")||this.engine.use(new N.AsyncValidatorPlugin(this.engine)),this.formElementRef={current:null},this.getOnFinish=()=>()=>{},this.getOnFinishFailed=()=>()=>{}}_bind(t,i,r){this.formElementRef.current=t,this.getOnFinish=i,this.getOnFinishFailed=r,this.engine.registerOnFieldValueChange((l,n)=>this._onFieldValueChange(l,n))}_syncConfig(t){if(t.removeHiddenData!==void 0&&(this.removeHiddenData=t.removeHiddenData),t.watch){this.watchers.clear(),this.globalWatcher=null;for(const[i,r]of Object.entries(t.watch))i==="#"?this.globalWatcher=r:this.watchers.set(i,r)}}_onFieldValueChange(t,i){const r=this.engine.getFormData(),l=this.removeHiddenData?r:this.engine.getAllFormData();this.globalWatcher&&this.globalWatcher(l,l,t);const n=this.watchers.get(t);n&&n(i,l)}_getEngine(){return this.engine}async submit(){const t=await this.engine.validate();if(t.size>0){this.focusFirstError(t),this.getOnFinishFailed()?.(t);return}const i=this.removeHiddenData?this.engine.getFormData():this.engine.getAllFormData();await this.getOnFinish()?.(i)}focusFirstError(t){const i=this.formElementRef.current;if(!i||t.size===0)return;const r=new Set(t.keys());requestAnimationFrame(()=>{const n=i.querySelectorAll("[data-nexus-field]");for(const o of Array.from(n)){const u=o.getAttribute("data-nexus-field");if(!u||!r.has(u))continue;o.scrollIntoView({behavior:"smooth",block:"center"}),o.querySelector('input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])')?.focus();return}})}resetFields(){this.engine.reset()}setErrorFields(t){this.engine.setErrorFields(t)}setValues(t){this.engine.setFieldValues(t)}setValueByPath(t,i){this.engine.setFieldValue(t,i)}setSchemaByPath(t,i){this.engine.setSchemaByPath(t,i)}setSchema(t){this.engine.setSchema(t)}getValues(t){return this.engine.getFormData(t)}getHiddenValues(){return this.engine.getHiddenValues()}getAllValues(){return this.engine.getAllFormData()}getValueByPath(t){return this.engine.getFieldValue(t)}registerValidator(t,i){this.engine.registerFieldValidator(t,i)}unregisterValidator(t,i){this.engine.unregisterFieldValidator(t,i)}revalidateField(t){this.engine.validateField(t,{trigger:"change"})}getSchema(){return this.engine.getSchema()}removeErrorField(t){this.engine.removeErrorField(t)}scrollToPath(t){this.formElementRef.current?.querySelector(`[data-nexus-field="${t}"]`)?.scrollIntoView({behavior:"smooth",block:"center"})}getFieldError(t){return this.engine.getFieldError(t)}getFieldsError(){return this.engine.getFieldsError()}validateFields(t){return this.engine.validate(t)}getFieldState(t){return this.engine.getFieldState(t)}}const R=s.createContext({}),M=s.createContext(null),k=s.createContext({}),H=s.createContext(null);function S(){const e=s.useContext(H);if(!e)throw new Error("[NexusField] Must be used within <NexusFormProvider>");return e}function q(e,t){if(e!==void 0)return e;if(t&&t.column>0)return Math.max(1,Math.round(t.column/24))}function J({dataPath:e,layoutKey:t}){const{engine:i,config:r,form:l}=S();s.useSyncExternalStore(y=>i.subscribeField(e,y),()=>i.getFieldVersion(e),()=>i.getFieldVersion(e));const n=i.getFieldState(e),o=s.useContext(M),u=s.useContext(k),g=s.useContext(R),f=s.useCallback(y=>{i.setFieldValue(e,y)},[i,e]),b=s.useCallback(y=>{y.currentTarget.contains(y.relatedTarget)||i.validateField(e,{trigger:"blur"})},[i,e]),d=s.useMemo(()=>n?.meta.enum?n.meta.enum.map((y,E)=>({value:y,label:n.meta.enumNames?.[E]??String(y)})):n?.props.options,[n?.meta.enum,n?.meta.enumNames,n?.props.options]),F=s.useMemo(()=>{const y={};if(n?.reactions){for(const E of n.reactions)if(E.dependencies)for(const p of E.dependencies)y[p]=i.getFieldValue(p)}return y},[n?.reactions,i]);if(!n)return i.getSnapshot()>0&&console.warn(`[NexusField] Field not found: ${e}`),null;if(g.visible===!1||!n.visible)return u.removeHidden===!0?null:c.jsx("div",{className:"hidden","data-nexus-hidden":e});const h=r.readOnly||g.readOnly===!0||n.readOnly,C=g.disabled===!0||n.disabled,v=h&&!!n.meta.readOnlyWidget,x=v?n.meta.readOnlyWidget:n.meta.widget;let V=i.getWidget(x);if(!V&&v&&(V=i.getWidget(n.meta.widget)),!V)return c.jsxs("div",{className:"text-xs text-red-500","data-nexus-field":e,children:['⚠️ Widget "',n.meta.widget,'" 未注册 (path: ',e,")"]});const j=n.meta.displayType??r.displayType,D=n.meta.labelWidth??r.labelWidth,m=n.meta.column??r.column,O=q(n.meta.colSpan,o),w={...n.meta.width?{width:n.meta.width,flexShrink:0}:{},...O?{gridColumn:`span ${O}`}:{}};return c.jsx("div",{"data-nexus-field":e,onBlur:b,style:Object.keys(w).length>0?w:void 0,children:c.jsx(V,{dataPath:e,path:e,value:n.value,onChange:f,disabled:C,readOnly:h,loading:n.loading,required:n.required,title:n.meta.title,description:n.meta.description,placeholder:n.meta.placeholder,label:n.meta.label,options:d,errors:n.errors,extra:n.meta.extra,displayType:j,labelWidth:D,column:m,form:l,dependValues:F,items:n.meta.items,...n.props},t)})}function B({node:e}){const{engine:t}=S(),i=t.getLayout(e.type),r=e.children.map((h,C)=>$(h,C)),l=s.useContext(M),n=q(e.props.colSpan,l),o={...n?{gridColumn:`span ${n}`}:{},...e.props.width?{width:e.props.width,flexShrink:0}:{}},u=s.useMemo(()=>({removeHidden:e.props.removeHidden}),[e.props.removeHidden]);if(!i)return c.jsx(k.Provider,{value:u,children:c.jsxs("div",{"data-nexus-layout":e.type,className:"mb-4",style:Object.keys(o).length>0?o:void 0,children:[e.title&&c.jsx("div",{className:"mb-2 font-bold",children:e.title}),r]})});const{displayType:g,labelWidth:f,colSpan:b,width:d,...F}=e.props;return c.jsx(k.Provider,{value:u,children:c.jsx("div",{style:Object.keys(o).length>0?o:void 0,children:c.jsx(i,{...F,node:e,title:e.title,children:r})})})}function I({node:e}){const{engine:t,config:i}=S(),r=s.useContext(R);s.useSyncExternalStore(F=>t.subscribeField(e.dataPath,F),()=>t.getFieldVersion(e.dataPath),()=>t.getFieldVersion(e.dataPath));const l=t.getFieldState(e.dataPath),[n,o]=s.useState(!1),u=(i.column??1)>1,g=u?{gridTemplateColumns:`repeat(${i.column}, 1fr)`}:{},f={disabled:r.disabled??(l?.disabled===!0?!0:void 0),readOnly:r.readOnly??(l?.readOnly===!0?!0:void 0),visible:r.visible===!1||l?.visible===!1?!1:void 0},b=f.visible===!1,d=()=>o(F=>!F);return c.jsx(R.Provider,{value:f,children:c.jsxs("div",{"data-nexus-object":e.dataPath,className:`mb-4 ${b?"hidden":""}`,children:[e.title&&c.jsxs("div",{onClick:d,className:"flex gap-1 mb-2 cursor-pointer select-none border-none bg-transparent p-0 font-bold",children:[c.jsx("svg",{width:"12",height:"12",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",className:`align-middle transition-transform duration-200 ease-in-out ${n?"rotate-0":"rotate-90"}`,"aria-hidden":"true",children:c.jsx("polyline",{points:"9 18 15 12 9 6"})}),e.title]}),c.jsx("div",{className:`${u?"grid gap-x-4":""} ${n?"hidden":""}`,style:Object.keys(g).length>0?g:void 0,children:e.children.map((F,h)=>$(F,h))})]})})}function $(e,t){return e.type==="field"?c.jsx(J,{dataPath:e.dataPath,layoutKey:e.layoutKey},e.layoutKey||e.dataPath):e.type==="object"?c.jsx(I,{node:e},`object-${e.layoutKey}-${t}`):c.jsx(B,{node:e},`layout-${e.type}-${t}`)}function K({engine:e,config:t,form:i,children:r}){const l=s.useMemo(()=>({engine:e,config:t,form:i}),[e,t,i]);return c.jsx(H.Provider,{value:l,children:r})}function T(){}function Y({form:e,schema:t,initialValues:i,widgets:r,layouts:l,onFinish:n,onFinishFailed:o,footer:u=!1,className:g,style:f,children:b,labelCol:d,labelWidth:F,colon:h,label:C,displayType:v,readOnly:x,column:V,watch:j,removeHiddenData:D=!0}){const m=e._getEngine(),O=s.useRef(null),w=v??t?.displayType??"row",y=C??t?.label??!0,E=h??t?.colon,p=F??t?.labelWidth,G=x??t?.readOnly??!1,W=V??t?.column;s.useEffect(()=>{r&&m.registerWidgets(r),l&&m.registerLayouts(l)},[m,r,l]);const z=s.useRef(!0),ae=s.useRef(i);s.useEffect(()=>{t&&(z.current?(m.init(t,ae.current),z.current=!1):m.init(t,m.getFormData()))},[m,t]);const U=s.useRef(T),Q=s.useRef(T);U.current=n??T,Q.current=o??T,s.useEffect(()=>{e._bind(O.current,()=>U.current,()=>Q.current)},[e]),s.useEffect(()=>{e._syncConfig({removeHiddenData:D,watch:j})},[e,D,j]);const ce=s.useSyncExternalStore(m.subscribeStore,m.getSnapshot,m.getSnapshot),de=s.useMemo(()=>m.getRenderTree(),[m,ce]),fe=s.useCallback(async A=>{A.preventDefault(),await e.submit()},[e]),ge=s.useCallback(()=>{e.resetFields()},[e]);let L=null;u===!0?L=c.jsxs("div",{className:"mt-4",children:[c.jsx("button",{type:"submit",children:"提交"})," ",c.jsx("button",{type:"button",onClick:ge,children:"重置"})]}):u&&(L=u);const X=s.useMemo(()=>{if(d)return d;if(p)return{style:{width:typeof p=="number"?`${p}px`:p}}},[d,p]),he=s.useMemo(()=>({labelCol:X,labelWidth:p,colon:E,label:y,displayType:w,readOnly:G,column:W}),[X,p,E,y,w,G,W]);return c.jsx(K,{engine:m,config:he,form:e,children:c.jsxs("form",{ref:O,onSubmit:fe,className:g,style:{...f,...W&&W>1?{display:"grid",gridTemplateColumns:`repeat(${W}, 1fr)`,gap:"0 16px"}:{}},noValidate:!0,children:[de.map((A,be)=>$(A,be)),!x&&L,b]})})}function _(){const{engine:e}=S();return e}function Z(e){const{engine:t}=S();return s.useSyncExternalStore(i=>t.subscribeField(e,i),()=>t.getFieldVersion(e),()=>t.getFieldVersion(e)),t.getFieldState(e)}function ee(e,t,i,r){const{engine:l}=S(),n=s.useRef(i);n.current=i;const o=s.useRef(r?.dependsOn);o.current=r?.dependsOn;const u=r?.deps;s.useEffect(()=>{if(!e||!t)return;const g=n.current;return e.registerValidator(t,g),()=>{e.unregisterValidator(t,g)}},[e,t,...u??[]]),s.useEffect(()=>{if(!t||!o.current||o.current.length===0)return;const g=l;if(!g)return;const f=t,b=o.current.map(d=>g.subscribeField(d,()=>{e?.revalidateField(f)}));return()=>{for(const d of b)d()}},[l,e,t])}function te(e){const t=_();return s.useSyncExternalStore(i=>t.subscribeField(e,i),()=>t.getFieldVersion(e),()=>t.getFieldVersion(e)),t.getFieldValue(e)}function ne(e){const t=s.useRef(null);return t.current||(t.current=new P(e)),[t.current]}function ie(){const{config:e}=S();return e}function se(){const e=_(),t=s.useSyncExternalStore(e.subscribeStore,e.getSnapshot,e.getSnapshot);return s.useMemo(()=>e.getFormData(),[e,t])}function re(e,t,i,r){const{deep:l=!1}=r||{},n=s.useRef(void 0),o=s.useRef(i);return o.current=i,s.useEffect(()=>{if(!e)return;const u=e.getFieldValue(t);n.current===void 0&&(n.current=u),(l?JSON.stringify(u)!==JSON.stringify(n.current):u!==n.current)&&(n.current=u,o.current(u));const f=e.subscribe(t,b=>{const d=b.value;(l?JSON.stringify(d)!==JSON.stringify(n.current):d!==n.current)&&(n.current=d,o.current(d))});return()=>{f()}},[e,t,l]),n.current}function le(e,t,i){const{deep:r=!1}=i||{},l=s.useRef({}),n=s.useRef({}),o=s.useRef(t);return o.current=t,s.useEffect(()=>{if(!e)return;const u=e.getFormData();l.current=u,n.current=u,o.current(u);const g=e.subscribeAll(f=>{if(r)JSON.stringify(f)!==JSON.stringify(l.current)&&(l.current=f,n.current=f,o.current(f));else{let b=!1;for(const d in f)if(f[d]!==l.current[d]){b=!0;break}b&&(l.current=f,n.current=f,o.current(f))}});return()=>{g()}},[e,r]),n.current}function oe(e,t,i,r){const{deep:l=!1}=r||{},n=s.useRef({}),o=s.useRef({}),u=s.useRef(i);u.current=i;const g=s.useRef(t);g.current=t;const f=[...t].sort().join(",");return s.useEffect(()=>{if(!e)return;const b=g.current,d={};for(const h of b)d[h]=e.getFieldValue(h);n.current=d,o.current=d,u.current(d);const F=b.map(h=>e.subscribe(h,C=>{const v=C.value,x=n.current[h];(l?JSON.stringify(v)!==JSON.stringify(x):v!==x)&&(n.current[h]=v,o.current={[h]:v},u.current(o.current))}));return()=>{for(const h of F)h()}},[e,l,f]),o.current}function ue(e,t,i){const r=s.useRef(void 0),l=s.useRef(i);return l.current=i,s.useEffect(()=>{if(!e)return;const n=e.getFieldState(t);r.current=n,n&&l.current(n);const o=e.subscribe(t,u=>{r.current=u,l.current(u)});return()=>{o()}},[e,t]),r.current||{}}a.FieldInheritContext=R,a.FormController=P,a.GridContext=M,a.LayoutConfigContext=k,a.NexusField=J,a.NexusForm=Y,a.NexusFormProvider=K,a.NexusLayout=B,a.NexusObject=I,a.useEngine=_,a.useFieldState=Z,a.useFieldValidator=ee,a.useFieldValue=te,a.useForm=ne,a.useFormConfig=ie,a.useFormData=se,a.useWatch=re,a.useWatchAll=le,a.useWatchMultiple=oe,a.useWatchState=ue,Object.defineProperty(a,Symbol.toStringTag,{value:"Module"})}));
|
|
1
|
+
(function(c,x){typeof exports=="object"&&typeof module<"u"?x(exports,require("@xbeeant/form-engine"),require("react/jsx-runtime"),require("react")):typeof define=="function"&&define.amd?define(["exports","@xbeeant/form-engine","react/jsx-runtime","react"],x):(c=typeof globalThis<"u"?globalThis:c||self,x(c.NexusFormEngineReact={},c.formEngine,c.jsxRuntime,c.react))})(this,(function(c,x,a,s){"use strict";class J{engine;formElementRef;getOnFinish;getOnFinishFailed;removeHiddenData=!0;watchers=new Map;globalWatcher=null;constructor(t){this.engine=t??new x.NexusEngine,this.engine.hasPlugin("async-validator")||this.engine.use(new x.AsyncValidatorPlugin(this.engine)),this.formElementRef={current:null},this.getOnFinish=()=>()=>{},this.getOnFinishFailed=()=>()=>{}}_bind(t,i,r){this.formElementRef.current=t,this.getOnFinish=i,this.getOnFinishFailed=r,this.engine.registerOnFieldValueChange((l,n)=>this._onFieldValueChange(l,n))}_syncConfig(t){if(t.removeHiddenData!==void 0&&(this.removeHiddenData=t.removeHiddenData),t.watch){this.watchers.clear(),this.globalWatcher=null;for(const[i,r]of Object.entries(t.watch))i==="#"?this.globalWatcher=r:this.watchers.set(i,r)}}_onFieldValueChange(t,i){const r=this.engine.getFormData(),l=this.removeHiddenData?r:this.engine.getAllFormData();this.globalWatcher&&this.globalWatcher(l,l,t);const n=this.watchers.get(t);n&&n(i,l)}_getEngine(){return this.engine}getEngine(){return this.engine}async submit(){const t=await this.engine.validate();if(t.size>0){this.focusFirstError(t),this.getOnFinishFailed()?.(t);return}const i=this.removeHiddenData?this.engine.getFormData():this.engine.getAllFormData();await this.getOnFinish()?.(i)}focusFirstError(t){const i=this.formElementRef.current;if(!i||t.size===0)return;const r=new Set(t.keys());requestAnimationFrame(()=>{const n=i.querySelectorAll("[data-nexus-field]");for(const o of Array.from(n)){const u=o.getAttribute("data-nexus-field");if(!u||!r.has(u))continue;o.scrollIntoView({behavior:"smooth",block:"center"}),o.querySelector('input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])')?.focus();return}})}resetFields(){this.engine.reset()}setErrorFields(t){this.engine.setErrorFields(t)}setValues(t){this.engine.setFieldValues(t)}setValueByPath(t,i){this.engine.setFieldValue(t,i)}setSchemaByPath(t,i){this.engine.setSchemaByPath(t,i)}setSchema(t){this.engine.setSchema(t)}getValues(t){return this.engine.getFormData(t)}getHiddenValues(){return this.engine.getHiddenValues()}getAllValues(){return this.engine.getAllFormData()}getValueByPath(t){return this.engine.getFieldValue(t)}registerValidator(t,i){this.engine.registerFieldValidator(t,i)}unregisterValidator(t,i){this.engine.unregisterFieldValidator(t,i)}revalidateField(t){this.engine.validateField(t,{trigger:"change"})}getSchema(){return this.engine.getSchema()}removeErrorField(t){this.engine.removeErrorField(t)}scrollToPath(t){this.formElementRef.current?.querySelector(`[data-nexus-field="${t}"]`)?.scrollIntoView({behavior:"smooth",block:"center"})}getFieldError(t){return this.engine.getFieldError(t)}getFieldsError(){return this.engine.getFieldsError()}validateFields(t){return this.engine.validate(t)}getFieldState(t){return this.engine.getFieldState(t)}}const k=s.createContext({}),P=s.createContext(null),j=s.createContext({}),B=s.createContext(null);function V(){const e=s.useContext(B);if(!e)throw new Error("[NexusField] Must be used within <NexusFormProvider>");return e}function I(e,t){if(e!==void 0)return e;if(t&&t.column>0)return Math.max(1,Math.round(t.column/24))}function K({dataPath:e,layoutKey:t}){const{engine:i,config:r,form:l}=V();s.useSyncExternalStore(F=>i.subscribeField(e,F),()=>i.getFieldVersion(e),()=>i.getFieldVersion(e));const n=i.getFieldState(e),o=s.useContext(P),u=s.useContext(j),d=s.useContext(k),f=s.useCallback(F=>{i.setFieldValue(e,F)},[i,e]),b=s.useCallback(F=>{F.currentTarget.contains(F.relatedTarget)||i.validateField(e,{trigger:"blur"})},[i,e]),g=s.useMemo(()=>n?.meta.enum?n.meta.enum.map((F,v)=>({value:F,label:n.meta.enumNames?.[v]??String(F)})):n?.props.options,[n?.meta.enum,n?.meta.enumNames,n?.props.options]),y=s.useMemo(()=>{const F={};if(n?.reactions){for(const v of n.reactions)if(v.dependencies)for(const R of v.dependencies)F[R]=i.getFieldValue(R)}return F},[n?.reactions,i]);if(!n)return i.getSnapshot()>0&&console.warn(`[NexusField] Field not found: ${e}`),null;if(d.visible===!1||!n.visible)return u.removeHidden===!0?null:a.jsx("div",{className:"hidden","data-nexus-hidden":e});const h=r.readOnly||d.readOnly===!0||n.readOnly,E=d.disabled===!0||n.disabled,S=h&&!!n.meta.readOnlyWidget,N=S?n.meta.readOnlyWidget:n.meta.widget;let C=i.getWidget(N);if(!C&&S&&(C=i.getWidget(n.meta.widget)),!C)return a.jsxs("div",{className:"text-xs text-red-500","data-nexus-field":e,children:['⚠️ Widget "',n.meta.widget,'" 未注册 (path: ',e,")"]});const A=n.meta.displayType??r.displayType,D=n.meta.labelWidth??r.labelWidth,M=n.meta.column??r.column,m=I(n.meta.colSpan,o),O={...n.meta.width?{width:n.meta.width,flexShrink:0}:{},...m?{gridColumn:`span ${m}`}:{}},w=i.getFieldWrapper(),$={label:n.meta.label,title:n.meta.title,description:n.meta.description,errors:n.errors,required:n.required,extra:n.meta.extra,width:n.meta.width,displayType:A,labelWidth:D,column:M},W={dataPath:e,path:e,value:n.value,onChange:f,disabled:E,readOnly:h,loading:n.loading,placeholder:n.meta.placeholder,options:g,form:l,dependValues:y,items:n.meta.items,...n.props};let p;return w?p=a.jsx(w,{...$,children:a.jsx(C,{...W})},t):p=a.jsx(C,{...W},t),a.jsx("div",{"data-nexus-field":e,onBlur:b,style:Object.keys(O).length>0?O:void 0,children:p})}function G({node:e}){const{engine:t}=V(),i=t.getLayout(e.type),r=e.children.map((h,E)=>_(h,E)),l=s.useContext(P),n=I(e.props.colSpan,l),o={...n?{gridColumn:`span ${n}`}:{},...e.props.width?{width:e.props.width,flexShrink:0}:{}},u=s.useMemo(()=>({removeHidden:e.props.removeHidden}),[e.props.removeHidden]);if(!i)return a.jsx(j.Provider,{value:u,children:a.jsxs("div",{"data-nexus-layout":e.type,className:"mb-4",style:Object.keys(o).length>0?o:void 0,children:[e.title&&a.jsx("div",{className:"mb-2 font-bold",children:e.title}),r]})});const{displayType:d,labelWidth:f,colSpan:b,width:g,...y}=e.props;return a.jsx(j.Provider,{value:u,children:a.jsx("div",{style:Object.keys(o).length>0?o:void 0,children:a.jsx(i,{...y,node:e,title:e.title,children:r})})})}function z({node:e}){const{engine:t,config:i}=V(),r=s.useContext(k);s.useSyncExternalStore(y=>t.subscribeField(e.dataPath,y),()=>t.getFieldVersion(e.dataPath),()=>t.getFieldVersion(e.dataPath));const l=t.getFieldState(e.dataPath),[n,o]=s.useState(!1),u=(i.column??1)>1,d=u?{gridTemplateColumns:`repeat(${i.column}, 1fr)`}:{},f={disabled:r.disabled??(l?.disabled===!0?!0:void 0),readOnly:r.readOnly??(l?.readOnly===!0?!0:void 0),visible:r.visible===!1||l?.visible===!1?!1:void 0},b=f.visible===!1,g=()=>o(y=>!y);return a.jsx(k.Provider,{value:f,children:a.jsxs("div",{"data-nexus-object":e.dataPath,className:`mb-4 ${b?"hidden":""}`,children:[e.title&&a.jsxs("div",{onClick:g,className:"flex gap-1 mb-2 cursor-pointer select-none border-none bg-transparent p-0 font-bold",children:[a.jsx("svg",{width:"12",height:"12",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",className:`align-middle transition-transform duration-200 ease-in-out ${n?"rotate-0":"rotate-90"}`,"aria-hidden":"true",children:a.jsx("polyline",{points:"9 18 15 12 9 6"})}),e.title]}),a.jsx("div",{className:`${u?"grid gap-x-4":""} ${n?"hidden":""}`,style:Object.keys(d).length>0?d:void 0,children:e.children.map((y,h)=>_(y,h))})]})})}function _(e,t){return e.type==="field"?a.jsx(K,{dataPath:e.dataPath,layoutKey:e.layoutKey},e.layoutKey||e.dataPath):e.type==="object"?a.jsx(z,{node:e},`object-${e.layoutKey}-${t}`):a.jsx(G,{node:e},`layout-${e.type}-${t}`)}function U({engine:e,config:t,form:i,children:r}){const l=s.useMemo(()=>({engine:e,config:t,form:i}),[e,t,i]);return a.jsx(B.Provider,{value:l,children:r})}function T(){}function ne({form:e,schema:t,initialValues:i,widgets:r,layouts:l,onFinish:n,onFinishFailed:o,onMount:u,footer:d=!1,className:f,style:b,children:g,labelCol:y,labelWidth:h,colon:E,label:S,displayType:N,readOnly:C,column:A,watch:D,removeHiddenData:M=!0}){const m=e._getEngine(),O=s.useRef(null),w=N??t?.displayType??"row",$=S??t?.label??!0,W=E??t?.colon,p=h??t?.labelWidth,F=C??t?.readOnly??!1,v=A??t?.column;s.useEffect(()=>{r&&m.registerWidgets(r),l&&m.registerLayouts(l)},[m,r,l]);const R=s.useRef(!0),ge=s.useRef(i);s.useEffect(()=>{t&&(R.current?(m.init(t,ge.current),R.current=!1):m.init(t,m.getFormData()))},[m,t]);const Q=s.useRef(u);Q.current=u;const X=s.useRef(!1),Y=!t||typeof t=="object"&&Object.keys(t).length===0;s.useEffect(()=>{X.current||Y||(X.current=!0,Q.current?.())},[Y]);const Z=s.useRef(T),ee=s.useRef(T);Z.current=n??T,ee.current=o??T,s.useEffect(()=>{e._bind(O.current,()=>Z.current,()=>ee.current)},[e]),s.useEffect(()=>{e._syncConfig({removeHiddenData:M,watch:D})},[e,M,D]);const he=s.useSyncExternalStore(m.subscribeStore,m.getSnapshot,m.getSnapshot),be=s.useMemo(()=>m.getRenderTree(),[m,he]),ye=s.useCallback(async q=>{q.preventDefault(),await e.submit()},[e]),me=s.useCallback(()=>{e.resetFields()},[e]);let H=null;d===!0?H=a.jsxs("div",{className:"mt-4",children:[a.jsx("button",{type:"submit",children:"提交"})," ",a.jsx("button",{type:"button",onClick:me,children:"重置"})]}):d&&(H=d);const te=s.useMemo(()=>{if(y)return y;if(p)return{style:{width:typeof p=="number"?`${p}px`:p}}},[y,p]),Fe=s.useMemo(()=>({labelCol:te,labelWidth:p,colon:W,label:$,displayType:w,readOnly:F,column:v}),[te,p,W,$,w,F,v]);return a.jsx(U,{engine:m,config:Fe,form:e,children:a.jsxs("form",{ref:O,onSubmit:ye,className:f,style:{...b,...v&&v>1?{display:"grid",gridTemplateColumns:`repeat(${v}, 1fr)`,gap:"0 16px"}:{}},noValidate:!0,children:[be.map((q,pe)=>_(q,pe)),!C&&H,g]})})}function L(){const{engine:e}=V();return e}function ie(e){const{engine:t}=V();return s.useSyncExternalStore(i=>t.subscribeField(e,i),()=>t.getFieldVersion(e),()=>t.getFieldVersion(e)),t.getFieldState(e)}function se(e,t,i,r){const{engine:l}=V(),n=s.useRef(i);n.current=i;const o=s.useRef(r?.dependsOn);o.current=r?.dependsOn;const u=r?.deps;s.useEffect(()=>{if(!e||!t)return;const d=n.current;return e.registerValidator(t,d),()=>{e.unregisterValidator(t,d)}},[e,t,...u??[]]),s.useEffect(()=>{if(!t||!o.current||o.current.length===0)return;const d=l;if(!d)return;const f=t,b=o.current.map(g=>d.subscribeField(g,()=>{e?.revalidateField(f)}));return()=>{for(const g of b)g()}},[l,e,t])}function re(e){const t=L();return s.useSyncExternalStore(i=>t.subscribeField(e,i),()=>t.getFieldVersion(e),()=>t.getFieldVersion(e)),t.getFieldValue(e)}function le(e,t){const i=s.useRef(null);return i.current||(i.current=new J(t??(e?new x.NexusEngine({formId:e}):void 0))),[i.current]}function oe(){const{config:e}=V();return e}function ue(){const e=L(),t=s.useSyncExternalStore(e.subscribeStore,e.getSnapshot,e.getSnapshot);return s.useMemo(()=>e.getFormData(),[e,t])}function ce(e,t,i,r){const{deep:l=!1}=r||{},n=s.useRef(void 0),o=s.useRef(i);return o.current=i,s.useEffect(()=>{if(!e)return;const u=e.getFieldValue(t);n.current===void 0&&(n.current=u),(l?JSON.stringify(u)!==JSON.stringify(n.current):u!==n.current)&&(n.current=u,o.current(u));const f=e.subscribe(t,b=>{const g=b.value;(l?JSON.stringify(g)!==JSON.stringify(n.current):g!==n.current)&&(n.current=g,o.current(g))});return()=>{f()}},[e,t,l]),n.current}function ae(e,t,i){const{deep:r=!1}=i||{},l=s.useRef({}),n=s.useRef({}),o=s.useRef(t);return o.current=t,s.useEffect(()=>{if(!e)return;const u=e.getFormData();l.current=u,n.current=u,o.current(u);const d=e.subscribeAll(f=>{if(r)JSON.stringify(f)!==JSON.stringify(l.current)&&(l.current=f,n.current=f,o.current(f));else{let b=!1;for(const g in f)if(f[g]!==l.current[g]){b=!0;break}b&&(l.current=f,n.current=f,o.current(f))}});return()=>{d()}},[e,r]),n.current}function de(e,t,i,r){const{deep:l=!1}=r||{},n=s.useRef({}),o=s.useRef({}),u=s.useRef(i);u.current=i;const d=s.useRef(t);d.current=t;const f=[...t].sort().join(",");return s.useEffect(()=>{if(!e)return;const b=d.current,g={};for(const h of b)g[h]=e.getFieldValue(h);n.current=g,o.current=g,u.current(g);const y=b.map(h=>e.subscribe(h,E=>{const S=E.value,N=n.current[h];(l?JSON.stringify(S)!==JSON.stringify(N):S!==N)&&(n.current[h]=S,o.current={[h]:S},u.current(o.current))}));return()=>{for(const h of y)h()}},[e,l,f]),o.current}function fe(e,t,i){const r=s.useRef(void 0),l=s.useRef(i);return l.current=i,s.useEffect(()=>{if(!e)return;const n=e.getFieldState(t);r.current=n,n&&l.current(n);const o=e.subscribe(t,u=>{r.current=u,l.current(u)});return()=>{o()}},[e,t]),r.current||{}}c.FieldInheritContext=k,c.FormController=J,c.GridContext=P,c.LayoutConfigContext=j,c.NexusField=K,c.NexusForm=ne,c.NexusFormProvider=U,c.NexusLayout=G,c.NexusObject=z,c.useEngine=L,c.useFieldState=ie,c.useFieldValidator=se,c.useFieldValue=re,c.useForm=le,c.useFormConfig=oe,c.useFormData=ue,c.useWatch=ce,c.useWatchAll=ae,c.useWatchMultiple=de,c.useWatchState=fe,Object.defineProperty(c,Symbol.toStringTag,{value:"Module"})}));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xbeeant/form-engine-react",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public",
|
|
6
6
|
"registry": "https://registry.npmjs.org/"
|
|
@@ -70,7 +70,7 @@
|
|
|
70
70
|
}
|
|
71
71
|
},
|
|
72
72
|
"dependencies": {
|
|
73
|
-
"@xbeeant/form-engine": "^0.0.
|
|
73
|
+
"@xbeeant/form-engine": "^0.0.3"
|
|
74
74
|
},
|
|
75
|
-
"gitHead": "
|
|
75
|
+
"gitHead": "32282a81ac6acd1c5b26ccf081504b9da53e07de"
|
|
76
76
|
}
|
|
@@ -112,6 +112,13 @@ export class FormController implements NexusFormInstance {
|
|
|
112
112
|
return this.engine;
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
+
/**
|
|
116
|
+
* 获取底层 Engine 实例(用于跨表单联动:linkForm / setFormId 等)
|
|
117
|
+
*/
|
|
118
|
+
getEngine(): NexusEngine {
|
|
119
|
+
return this.engine;
|
|
120
|
+
}
|
|
121
|
+
|
|
115
122
|
async submit(): Promise<void> {
|
|
116
123
|
const errors = await this.engine.validate();
|
|
117
124
|
if (errors.size > 0) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { CSSProperties, FocusEvent } from 'react';
|
|
1
|
+
import type { CSSProperties, FocusEvent, ReactElement } from 'react';
|
|
2
2
|
import { useCallback, useContext, useMemo, useSyncExternalStore } from 'react';
|
|
3
3
|
import { FieldInheritContext } from '../contexts/FieldInheritContext';
|
|
4
4
|
import { GridContext } from '../contexts/GridContext';
|
|
@@ -146,37 +146,63 @@ export function NexusField({ dataPath, layoutKey }: NexusFieldProps) {
|
|
|
146
146
|
...(effectiveColSpan ? { gridColumn: `span ${effectiveColSpan}` } : {}),
|
|
147
147
|
};
|
|
148
148
|
|
|
149
|
+
// 默认包裹:所有 widget 统一由 FieldWrapper 包裹(引擎注册,UI 层提供),
|
|
150
|
+
// 仅当 label === false(字段级或表单级)时 FieldWrapper 不包裹 Form.Item。
|
|
151
|
+
// 未注册 FieldWrapper(纯 react 无 ui 层)时直接渲染裸 widget。
|
|
152
|
+
const FieldWrapper = engine.getFieldWrapper();
|
|
153
|
+
|
|
154
|
+
// Form.Item 消费的元数据 props 剥离给 FieldWrapper,避免透传到底层 antd 控件:
|
|
155
|
+
// - required: 会让 <input required> 触发浏览器原生校验
|
|
156
|
+
// - errors/title/description/label/extra/width/displayType/labelWidth/column:
|
|
157
|
+
// 作为未知属性透传到 DOM 会产生 React 警告
|
|
158
|
+
const fieldWrapperProps = {
|
|
159
|
+
label: state.meta.label,
|
|
160
|
+
title: state.meta.title,
|
|
161
|
+
description: state.meta.description,
|
|
162
|
+
errors: state.errors,
|
|
163
|
+
required: state.required,
|
|
164
|
+
extra: state.meta.extra,
|
|
165
|
+
width: state.meta.width,
|
|
166
|
+
displayType: fieldDisplayType,
|
|
167
|
+
labelWidth: fieldLabelWidth,
|
|
168
|
+
column: fieldColumn,
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
// widget 仅接收控件相关 props(value/onChange/状态/选项/表单引用/自有 props)
|
|
172
|
+
const widgetProps = {
|
|
173
|
+
dataPath,
|
|
174
|
+
path: dataPath,
|
|
175
|
+
value: state.value,
|
|
176
|
+
onChange: handleChange,
|
|
177
|
+
disabled,
|
|
178
|
+
readOnly,
|
|
179
|
+
loading: state.loading,
|
|
180
|
+
placeholder: state.meta.placeholder,
|
|
181
|
+
options,
|
|
182
|
+
form,
|
|
183
|
+
dependValues,
|
|
184
|
+
items: state.meta.items,
|
|
185
|
+
...state.props,
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
let control: ReactElement;
|
|
189
|
+
if (FieldWrapper) {
|
|
190
|
+
control = (
|
|
191
|
+
<FieldWrapper key={layoutKey} {...fieldWrapperProps}>
|
|
192
|
+
<Widget {...widgetProps} />
|
|
193
|
+
</FieldWrapper>
|
|
194
|
+
);
|
|
195
|
+
} else {
|
|
196
|
+
control = <Widget key={layoutKey} {...widgetProps} />;
|
|
197
|
+
}
|
|
198
|
+
|
|
149
199
|
return (
|
|
150
200
|
<div
|
|
151
201
|
data-nexus-field={dataPath}
|
|
152
202
|
onBlur={handleBlur}
|
|
153
203
|
style={Object.keys(wrapperStyle).length > 0 ? wrapperStyle : undefined}
|
|
154
204
|
>
|
|
155
|
-
|
|
156
|
-
key={layoutKey}
|
|
157
|
-
dataPath={dataPath}
|
|
158
|
-
path={dataPath}
|
|
159
|
-
value={state.value}
|
|
160
|
-
onChange={handleChange}
|
|
161
|
-
disabled={disabled}
|
|
162
|
-
readOnly={readOnly}
|
|
163
|
-
loading={state.loading}
|
|
164
|
-
required={state.required}
|
|
165
|
-
title={state.meta.title}
|
|
166
|
-
description={state.meta.description}
|
|
167
|
-
placeholder={state.meta.placeholder}
|
|
168
|
-
label={state.meta.label}
|
|
169
|
-
options={options}
|
|
170
|
-
errors={state.errors}
|
|
171
|
-
extra={state.meta.extra}
|
|
172
|
-
displayType={fieldDisplayType}
|
|
173
|
-
labelWidth={fieldLabelWidth}
|
|
174
|
-
column={fieldColumn}
|
|
175
|
-
form={form}
|
|
176
|
-
dependValues={dependValues}
|
|
177
|
-
items={state.meta.items}
|
|
178
|
-
{...state.props}
|
|
179
|
-
/>
|
|
205
|
+
{control}
|
|
180
206
|
</div>
|
|
181
207
|
);
|
|
182
208
|
}
|
|
@@ -48,6 +48,13 @@ export interface NexusFormProps {
|
|
|
48
48
|
onFinish?: (formData: Record<string, unknown>) => void | Promise<void>;
|
|
49
49
|
/** 校验失败回调 */
|
|
50
50
|
onFinishFailed?: (errors: Map<string, string[]>) => void;
|
|
51
|
+
/**
|
|
52
|
+
* 表单首次加载回调:非空 schema 首次传入并完成渲染后执行一次
|
|
53
|
+
* - undefined / null / {}(无 properties)均视为「空」schema,不触发
|
|
54
|
+
* - schema 由空变为非空时,于首个非空渲染提交后触发
|
|
55
|
+
* - 后续 schema 变更不重复触发
|
|
56
|
+
*/
|
|
57
|
+
onMount?: () => void;
|
|
51
58
|
/** 是否显示默认 footer(提交/重置按钮),或自定义 footer */
|
|
52
59
|
footer?: boolean | ReactNode;
|
|
53
60
|
/** 自定义类名 */
|
|
@@ -107,6 +114,7 @@ export function NexusForm({
|
|
|
107
114
|
layouts,
|
|
108
115
|
onFinish,
|
|
109
116
|
onFinishFailed,
|
|
117
|
+
onMount,
|
|
110
118
|
footer = false,
|
|
111
119
|
className,
|
|
112
120
|
style,
|
|
@@ -161,6 +169,22 @@ export function NexusForm({
|
|
|
161
169
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
162
170
|
}, [engine, schema]);
|
|
163
171
|
|
|
172
|
+
// onMount:首次传入「非空」schema 并完成渲染后执行一次
|
|
173
|
+
// undefined / null / {}(无任何键)均视为空 schema,不触发;
|
|
174
|
+
// schema 由空变为非空时,于首个非空渲染提交(useEffect)后触发。
|
|
175
|
+
const onMountRef = useRef(onMount);
|
|
176
|
+
onMountRef.current = onMount;
|
|
177
|
+
const onMountFiredRef = useRef(false);
|
|
178
|
+
const isSchemaEmpty =
|
|
179
|
+
!schema || (typeof schema === 'object' && Object.keys(schema).length === 0);
|
|
180
|
+
useEffect(() => {
|
|
181
|
+
if (onMountFiredRef.current || isSchemaEmpty) {
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
onMountFiredRef.current = true;
|
|
185
|
+
onMountRef.current?.();
|
|
186
|
+
}, [isSchemaEmpty]);
|
|
187
|
+
|
|
164
188
|
// 绑定 form controller
|
|
165
189
|
// 使用 ref 持有 onFinish / onFinishFailed,避免每次 re-render 都造成绑定逻辑重复执行
|
|
166
190
|
const onFinishRef =
|
package/src/hooks/useForm.ts
CHANGED
|
@@ -1,15 +1,29 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { NexusEngine } from '@xbeeant/form-engine';
|
|
2
2
|
import { useRef } from 'react';
|
|
3
3
|
|
|
4
4
|
import { FormController } from '../components/FormController';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* useForm — 创建 Form 实例
|
|
8
|
+
*
|
|
9
|
+
* 支持一个页面挂载多个表单实例:
|
|
10
|
+
* - `useForm()`:独立实例(未注册,不参与跨表单联动)
|
|
11
|
+
* - `useForm(formId)`:创建带 formId 的实例,自动注册到默认表单注册表,
|
|
12
|
+
* 可通过 schema `crossForm` reaction / `engine.linkForm` 与其他表单联动
|
|
13
|
+
* - `useForm(formId, engine)`:复用外部创建的引擎(如 `new NexusEngine({ formId })`)
|
|
14
|
+
*
|
|
15
|
+
* @param formId - 可选,表单实例唯一标识(跨表单联动寻址)
|
|
16
|
+
* @param engine - 可选,外部引擎实例(缺省内部创建)
|
|
8
17
|
*/
|
|
9
|
-
export function useForm(
|
|
18
|
+
export function useForm(
|
|
19
|
+
formId?: string,
|
|
20
|
+
engine?: NexusEngine,
|
|
21
|
+
): [FormController] {
|
|
10
22
|
const formRef = useRef<FormController | null>(null);
|
|
11
23
|
if (!formRef.current) {
|
|
12
|
-
formRef.current = new FormController(
|
|
24
|
+
formRef.current = new FormController(
|
|
25
|
+
engine ?? (formId ? new NexusEngine({ formId }) : undefined),
|
|
26
|
+
);
|
|
13
27
|
}
|
|
14
28
|
return [formRef.current];
|
|
15
29
|
}
|
package/src/index.ts
CHANGED
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
// 导出所有React组件、Hooks和类型定义,供上层应用使用
|
|
4
4
|
// ============================================================================
|
|
5
5
|
|
|
6
|
+
import './styles.css';
|
|
7
|
+
|
|
6
8
|
export { FormController } from './components/FormController';
|
|
7
9
|
export { NexusField } from './components/NexusField';
|
|
8
10
|
export type { NexusFormConfig } from './components/NexusForm';
|
package/src/styles.css
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/// <reference types="vite/client" />
|