@schemx/vue 0.1.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/README.md +136 -0
  2. package/dist/components/FormGroup/index.d.ts +17 -0
  3. package/dist/components/FormGroup/index.d.ts.map +1 -0
  4. package/dist/components/FormItem/index.d.ts +17 -0
  5. package/dist/components/FormItem/index.d.ts.map +1 -0
  6. package/dist/form.d.ts +34 -0
  7. package/dist/form.d.ts.map +1 -0
  8. package/dist/hocs/index.d.ts +10 -0
  9. package/dist/hocs/index.d.ts.map +1 -0
  10. package/dist/hocs/withRemoteOptions.d.ts +74 -0
  11. package/dist/hocs/withRemoteOptions.d.ts.map +1 -0
  12. package/dist/hooks/index.d.ts +24 -0
  13. package/dist/hooks/index.d.ts.map +1 -0
  14. package/dist/hooks/useContext.d.ts +40 -0
  15. package/dist/hooks/useContext.d.ts.map +1 -0
  16. package/dist/hooks/useDictionary.d.ts +63 -0
  17. package/dist/hooks/useDictionary.d.ts.map +1 -0
  18. package/dist/hooks/useEffect.d.ts +34 -0
  19. package/dist/hooks/useEffect.d.ts.map +1 -0
  20. package/dist/hooks/useField.d.ts +38 -0
  21. package/dist/hooks/useField.d.ts.map +1 -0
  22. package/dist/hooks/useFieldContext.d.ts +23 -0
  23. package/dist/hooks/useFieldContext.d.ts.map +1 -0
  24. package/dist/hooks/useForm.d.ts +59 -0
  25. package/dist/hooks/useForm.d.ts.map +1 -0
  26. package/dist/hooks/useStableRef.d.ts +28 -0
  27. package/dist/hooks/useStableRef.d.ts.map +1 -0
  28. package/dist/hooks/useViewSchemas.d.ts +6 -0
  29. package/dist/hooks/useViewSchemas.d.ts.map +1 -0
  30. package/dist/hooks/useWatch.d.ts +65 -0
  31. package/dist/hooks/useWatch.d.ts.map +1 -0
  32. package/dist/index.cjs +2 -0
  33. package/dist/index.cjs.map +1 -0
  34. package/dist/index.d.ts +19 -0
  35. package/dist/index.d.ts.map +1 -0
  36. package/dist/index.mjs +686 -0
  37. package/dist/index.mjs.map +1 -0
  38. package/dist/index.umd.js +2 -0
  39. package/dist/index.umd.js.map +1 -0
  40. package/dist/style.css +1 -0
  41. package/dist/types/field.d.ts +23 -0
  42. package/dist/types/field.d.ts.map +1 -0
  43. package/dist/types/form.d.ts +18 -0
  44. package/dist/types/form.d.ts.map +1 -0
  45. package/dist/types/index.d.ts +2 -0
  46. package/dist/types/index.d.ts.map +1 -0
  47. package/dist/utils/diff.d.ts +33 -0
  48. package/dist/utils/diff.d.ts.map +1 -0
  49. package/dist/utils/dynamic.d.ts +99 -0
  50. package/dist/utils/dynamic.d.ts.map +1 -0
  51. package/dist/utils/equal.d.ts +22 -0
  52. package/dist/utils/equal.d.ts.map +1 -0
  53. package/dist/utils/index.d.ts +13 -0
  54. package/dist/utils/index.d.ts.map +1 -0
  55. package/dist/utils/rendererProvider.d.ts +17 -0
  56. package/dist/utils/rendererProvider.d.ts.map +1 -0
  57. package/dist/utils/rulesProvider.d.ts +17 -0
  58. package/dist/utils/rulesProvider.d.ts.map +1 -0
  59. package/dist/utils/slot.d.ts +49 -0
  60. package/dist/utils/slot.d.ts.map +1 -0
  61. package/dist/utils/validation.d.ts +43 -0
  62. package/dist/utils/validation.d.ts.map +1 -0
  63. package/package.json +64 -0
@@ -0,0 +1,6 @@
1
+ import { ShallowRef } from 'vue';
2
+ import { SchemxInstance, SchemxViewSchema, Values } from '@schemx/core';
3
+
4
+ export declare function useViewSchemas<T extends Values = Values>(form: SchemxInstance<T>): ShallowRef<readonly SchemxViewSchema<T>[]>;
5
+ export default useViewSchemas;
6
+ //# sourceMappingURL=useViewSchemas.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useViewSchemas.d.ts","sourceRoot":"","sources":["../../src/hooks/useViewSchemas.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,KAAK,CAAA;AAErC,OAAO,KAAK,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAE5E,wBAAgB,cAAc,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EACtD,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC,GACtB,UAAU,CAAC,SAAS,gBAAgB,CAAC,CAAC,CAAC,EAAE,CAAC,CAU5C;AAED,eAAe,cAAc,CAAA"}
@@ -0,0 +1,65 @@
1
+ import { NamePath, Values, CreateWatchOptions, WatchAllCallback, WatchFieldCallback, WatchFieldsCallback } from '@schemx/core';
2
+
3
+ /**
4
+ * 监听所有字段变化
5
+ *
6
+ * @param callback - 全局变化回调
7
+ * @param options - 监听选项
8
+ * @returns 取消监听函数
9
+ */
10
+ export declare function useWatch<T extends Values>(callback: WatchAllCallback<T>, options?: CreateWatchOptions): () => void;
11
+ /**
12
+ * 监听单个字段变化
13
+ *
14
+ * @param name - 字段路径
15
+ * @param callback - 单字段变化回调
16
+ * @param options - 监听选项
17
+ * @returns 取消监听函数
18
+ */
19
+ export declare function useWatch<T extends Values>(name: NamePath<T>, callback: WatchFieldCallback<T>, options?: CreateWatchOptions): () => void;
20
+ /**
21
+ * 监听多个字段变化
22
+ *
23
+ * @param names - 字段路径数组
24
+ * @param callback - 多字段变化回调
25
+ * @param options - 监听选项
26
+ * @returns 取消监听函数
27
+ */
28
+ export declare function useWatch<T extends Values>(names: NamePath<T>[], callback: WatchFieldsCallback<T>, options?: CreateWatchOptions): () => void;
29
+ /**
30
+ * 监听单个字段变化的便捷方法
31
+ *
32
+ * 等价于 `useWatch(name, callback, options)`,语义更明确。
33
+ * 自动绑定 formContext 并在组件卸载时取消监听。
34
+ *
35
+ * @param name - 要监听的字段路径
36
+ * @param callback - 字段变化回调
37
+ * @param options - 可选配置
38
+ * @returns 取消监听函数
39
+ */
40
+ export declare function useWatchField<T extends Values = Values>(name: NamePath<T>, callback: WatchFieldCallback<T>, options?: CreateWatchOptions): () => void;
41
+ /**
42
+ * 监听多个字段变化的便捷方法
43
+ *
44
+ * 等价于 `useWatch(names, callback, options)`,语义更明确。
45
+ * 自动绑定 formContext 并在组件卸载时取消监听。
46
+ *
47
+ * @param names - 要监听的字段路径数组
48
+ * @param callback - 字段变化回调
49
+ * @param options - 可选配置
50
+ * @returns 取消监听函数
51
+ */
52
+ export declare function useWatchFields<T extends Values>(names: NamePath<T>[], callback: WatchFieldsCallback<T>, options?: CreateWatchOptions): () => void;
53
+ /**
54
+ * 监听所有字段变化的便捷方法
55
+ *
56
+ * 等价于 `useWatch(callback, options)`,语义更明确。
57
+ * 自动绑定 formContext 并在组件卸载时取消监听。
58
+ *
59
+ * @param callback - 全局变化回调
60
+ * @param options - 可选配置
61
+ * @returns 取消监听函数
62
+ */
63
+ export declare function useWatchAll<T extends Values = Values>(callback: WatchAllCallback<T>, options?: CreateWatchOptions): () => void;
64
+ export default useWatch;
65
+ //# sourceMappingURL=useWatch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useWatch.d.ts","sourceRoot":"","sources":["../../src/hooks/useWatch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAQH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AACpD,OAAO,KAAK,EACV,kBAAkB,EAClB,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,EACpB,MAAM,cAAc,CAAA;AAErB;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,CAAC,SAAS,MAAM,EACvC,QAAQ,EAAE,gBAAgB,CAAC,CAAC,CAAC,EAC7B,OAAO,CAAC,EAAE,kBAAkB,GAC3B,MAAM,IAAI,CAAA;AACb;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CAAC,CAAC,SAAS,MAAM,EACvC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,EACjB,QAAQ,EAAE,kBAAkB,CAAC,CAAC,CAAC,EAC/B,OAAO,CAAC,EAAE,kBAAkB,GAC3B,MAAM,IAAI,CAAA;AACb;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CAAC,CAAC,SAAS,MAAM,EACvC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,EACpB,QAAQ,EAAE,mBAAmB,CAAC,CAAC,CAAC,EAChC,OAAO,CAAC,EAAE,kBAAkB,GAC3B,MAAM,IAAI,CAAA;AAuBb;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EACrD,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,EACjB,QAAQ,EAAE,kBAAkB,CAAC,CAAC,CAAC,EAC/B,OAAO,CAAC,EAAE,kBAAkB,GAC3B,MAAM,IAAI,CAEZ;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,CAAC,SAAS,MAAM,EAC7C,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,EACpB,QAAQ,EAAE,mBAAmB,CAAC,CAAC,CAAC,EAChC,OAAO,CAAC,EAAE,kBAAkB,GAC3B,MAAM,IAAI,CAEZ;AAED;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EACnD,QAAQ,EAAE,gBAAgB,CAAC,CAAC,CAAC,EAC7B,OAAO,CAAC,EAAE,kBAAkB,GAC3B,MAAM,IAAI,CAEZ;AAED,eAAe,QAAQ,CAAA"}
package/dist/index.cjs ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("vue"),t=require("classnames"),r=require("es-toolkit"),o=require("@schemx/core"),n=o.createRendererRegistry("input"),a=o.createValidatorsRegistry(),l=Symbol("SCHEMX_INSTANCE");function s(t){const{...r}=t,s={...r,rendererRegistry:r.rendererRegistry??n,validatorRegistry:r.validatorRegistry??a},i=e.computed(()=>o.createForm(s));return e.provide(l,i.value),e.onUnmounted(()=>{i.value.destroy()}),i.value}function i(){const t=e.inject(l);if(!t)throw new Error("useFormInstance must be used within a Form");return t}const c=new WeakMap;const u=t=>{const r=i(),n=t;let a=c.get(r);a||(a=new Map,c.set(r,a));const l=a.get(n);let s;if(l)l.refCount++,s=l;else{const{result:l,dispose:i}=function(t,r){const n=o.createField(t,r),a=e.shallowRef(n.getValue()),l=e.shallowRef(n.getError()),s=e.shallowRef(n.isPending()),i=n.effect(()=>{a.value=n.getValue(),l.value=n.getError(),s.value=n.isPending()}),c=e.computed(()=>l.value),u=e.computed(()=>(a.value,n.isTouched())),d=e.computed(()=>s.value);return{result:{value:a,error:c,dirty:u,pending:d,...n,getValue:()=>a.value},dispose:i}}(r,t);s={refCount:1,result:l,dispose:i},a.set(n,s)}return e.onUnmounted(()=>{--s.refCount<=0&&(s.dispose(),a.delete(n))}),s.result};function d(t,r,n){const a=i(),l=o.createWatch(a,t,r,n);return e.onUnmounted(l),l}function m(e,t,r){return d(e,t,r)}function p(e){return e instanceof Error?e:new Error(String(e))}const h=(t,r)=>{var o;const n=i(),a=e.ref([]),l=e.ref(!1),s=e.ref(void 0);let c=0;const u=async()=>{try{const e=n.getFieldsValue();if("function"==typeof t.shouldFetch&&!t.shouldFetch(e))return a.value=[],void(l.value=!1);l.value=!0,s.value=void 0;const r=++c,o=await(async e=>{const r=t.retryCount??0,o=t.retryInterval??1e3;let a=new Error("Unknown error");for(let s=0;s<=r;s++)try{return await t.api(e,n)}catch(l){a=p(l),s<r&&await new Promise(e=>setTimeout(e,o))}throw a})(e);if(r!==c)return;const i=await(async e=>"function"==typeof(null==t?void 0:t.formatter)?await t.formatter(e,n):e)(o);if(r!==c)return;a.value=i,s.value=void 0,"function"==typeof t.onSuccess&&t.onSuccess(i,n),l.value=!1}catch(e){const r=p(e);s.value=r,a.value=[],l.value=!1,"function"==typeof t.onError&&t.onError(r,n)}};(null==(o=t.dependsOn)?void 0:o.length)&&m(t.dependsOn,(e,o)=>{"function"==typeof t.onDepsChange&&t.onDepsChange(o,n),t.resetOnDepsChange&&r&&n.setFieldValue(r,void 0),u()});const d=t.immediate??!0;return e.onMounted(()=>{d&&u()}),{list:a,loading:l,error:s,loadDict:u,refresh:()=>u(),mutate:e=>{a.value=e}}},v=Symbol("FormContext");function f(){const t=e.inject(v);if(!t)throw new Error("useContext must be used within a Form");return t}function y(t){const r=e.shallowRef({});return e.watchEffect(()=>{const e=t();((e,t)=>{const r=Object.keys(e),o=Object.keys(t);return r.length===o.length&&r.every(r=>e[r]===t[r])})(r.value,e)||(r.value=e)}),r}const g=Symbol("schemx:field");function b(e){return void 0!==e&&(!Array.isArray(e)||0!==e.length)}function x(e,t){if(!t)return!1;return(Array.isArray(t)?t:[t]).some(t=>function(e){return{onBlur:"blur",onChange:"change",onSubmit:"submit",blur:"blur",change:"change",submit:"submit"}[e]??"submit"}(t)===e)}const F=e=>/[A-Z]/.test(e),w=e=>e.includes("-"),C=e=>e.replace(/([A-Z])/g,"-$1").toLowerCase(),V=e=>e.replace(/-([a-z])/g,(e,t)=>t.toUpperCase()),_=(e,t)=>{if(e[t])return e[t];const r=F(t)?C(t):w(t)?V(t):void 0;return r&&e[r]?e[r]:void 0},R=(e,t)=>{const r={},o=(n=String(e),(w(n)?V(n):n)+":");var n;const a=(e=>F(e)?C(e):e)(String(e))+":";for(const[l,s]of Object.entries(t))l.startsWith(o)?r[l.slice(o.length)]=s:l.startsWith(a)&&a!==o&&(r[l.slice(a.length)]=s);return r},S=e.defineComponent((r,{slots:o})=>{const n=e.ref(Boolean(r.schema.defaultCollapsed)),a=()=>{r.schema.collapsible&&(n.value=!n.value)};return()=>{const l=r.schema,s=Boolean(l.collapsible);return e.createVNode("div",{class:t("schemx-group",{"schemx-group--collapsed":n.value},l.class),"data-key":l.key},[l.label&&e.createVNode("div",{role:s?"button":void 0,tabindex:s?0:void 0,class:t("schemx-group__header",{"schemx-group__header--clickable":s}),onClick:a,onKeydown:e=>{"Enter"!==e.key&&" "!==e.key||(e.preventDefault(),a())}},[e.createVNode("span",{class:"schemx-group__title"},[l.label]),s&&e.createVNode("span",{class:t("schemx-group__arrow",{"schemx-group__arrow--down":!n.value})},null)]),!n.value&&e.createVNode("div",{class:"schemx-group__body"},[l.children.map(t=>e.createVNode(E,{key:t.key,schema:t},o))])])}},{name:"SchemxGroup",props:{schema:{type:Object,required:!0}}}),E=e.defineComponent((o,{slots:n})=>{const a=e.toRef(o,"schema");if(k(a.value))return()=>e.h(S,{schema:a.value},n);const l=i(),s=f(),c=()=>a.value,d=u(c().name);!function(t){e.provide(g,t)}(d);const m=e.computed(()=>{return e=c().validationTrigger,t=s.validationTrigger,r="onChange",b(e)?e:b(t)?t:r;var e,t,r}),p=e.computed(()=>{const e=c().visible&&!c().readonly&&!c().disabled,t=c().rules,r=Array.isArray(t)?(null==t?void 0:t.length)>0:!!c().rules;return e&&r}),h=e=>{var t,r;d.setValue(e),null==(r=null==(t=c().componentProps)?void 0:t.onChange)||r.call(t,e),p.value&&x("change",m.value)&&d.validate()},v=()=>{p.value&&x("blur",m.value)&&d.validate()},F=e.computed(()=>({...r.omit(c(),["componentProps"]),name:c().name,componentType:c().componentType,class:t("schemx-item",c().class),required:c().required,readonly:c().readonly,disabled:c().disabled,visible:c().visible,placeholder:c().placeholder,validationTrigger:m.value})),w=y(()=>({...c().componentProps,formItemProps:F.value,value:d.getValue(),readonly:c().readonly,disabled:c().disabled,placeholder:c().placeholder,onChange:h,onBlur:v,"onUpdate:value":e=>d.setValue(e)})),C=()=>{const t=_(n,`${c().name}Label`);if(t)return t(F.value);const r=c().labelAlign||s.labelAlign,o=c().labelWidth||s.labelWidth,a=c().colon??s.colon;return e.createVNode("label",{class:"schemx-item__label",style:{width:o,textAlign:r}},[!c().required||c().disabled||c().readonly?null:e.createVNode("span",{class:"schemx-item__required"},[e.createTextVNode("*")]),e.createVNode("span",{class:"schemx-item__label-text"},[c().label,a?":":""])])},V=()=>{const t=l.getRenderer(c().componentType);if(!t)throw new Error(`[schemx] Can not find component renderer of "${c().componentType}".`);const r=R(A(c().name),n),o=e.h(t,w.value,r),a=_(n,`${c().name}Content`);return a?a({...F.value,columnElement:o}):e.createVNode("div",{class:"schemx-item__control"},[o])},E=()=>{const t=_(n,`${c().name}Error`);return t?t({...F.value,errors:d.error.value}):Array.isArray(d.error.value)&&0!==d.error.value.length?e.createVNode("div",{class:"schemx-item__error"},[d.error.value[0]]):null};return()=>{if(!c().visible)return null;const r=_(n,A(c().name));if(r)return r(F.value);const o=c().labelPosition||s.labelPosition;return e.createVNode("div",{class:t("schemx-item-wrapper",{"is-readonly":c().readonly,"is-disabled":c().disabled})},[e.createVNode("div",{class:t("schemx-item",`schemx-item--label-${o}`,c().class),style:{...c().style??{}}},[C(),e.createVNode("div",{class:"schemx-item__content"},[V(),E()])])])}},{name:"SchemxItem",props:{schema:{type:Object,required:!0}}}),k=e=>"group"===e.componentType,A=e=>Array.isArray(e)?e.map(e=>String(e)).join("."):String(e),N=e.defineComponent({name:"SchemxForm",__name:"form",props:{class:{default:""},style:{default:()=>({})},required:{type:Boolean},readonly:{type:Boolean},disabled:{type:Boolean},visible:{type:Boolean},labelIcon:{},labelAlign:{},labelPosition:{},labelWidth:{},contentAlign:{},validationTrigger:{},colon:{type:Boolean},modelValue:{default:()=>({})},initialValues:{default:()=>({})},schemas:{default:()=>[]},form:{default:void 0},rendererRegistry:{default:void 0},defaultRendererType:{},validatorRegistry:{default:void 0},onFinish:{type:Function,default:void 0},onFinishFailed:{type:Function,default:void 0},onValuesChange:{type:Function,default:void 0},onFieldsChange:{type:Function,default:void 0}},emits:["update:modelValue"],setup(t,{expose:o,emit:n}){const a=t,l=n;(t=>{e.provide(v,t)})(r.omit(a,["form","modelValue","rendererRegistry","defaultRendererType","validatorRegistry","onFinish","onFinishFailed","onValuesChange","onFieldsChange"]));const i=a.form?a.form:s({schemas:a.schemas,initialValues:a.initialValues,rendererRegistry:a.rendererRegistry,defaultRendererType:a.defaultRendererType,validatorRegistry:a.validatorRegistry,readonly:a.readonly,disabled:a.disabled,onFinish:async e=>{var t;null==(t=a.onFinish)||t.call(a,e)},onFinishFailed:async e=>{var t;null==(t=a.onFinishFailed)||t.call(a,e)},onValuesChange:(e,t)=>{var r;l("update:modelValue",t),null==(r=a.onValuesChange)||r.call(a,e,t)},onFieldsChange:(e,t)=>{var r;null==(r=a.onFieldsChange)||r.call(a,e,t)}});e.watch(()=>a.schemas,e=>{i.setSchemas(e)},{deep:!1,immediate:!!a.form});const c=function(t){const r=e.shallowRef(t.getViewSchemas()),o=t.subscribeViewSchemas(e=>{r.value=e});return e.onScopeDispose(o),r}(i);return e.watchEffect(()=>{i.updateDefaultProps(a)}),o({...i}),(t,r)=>(e.openBlock(),e.createElementBlock("div",{class:e.normalizeClass(["schemx",a.class])},[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(e.unref(c),r=>(e.openBlock(),e.createBlock(e.unref(E),{key:r.key,schema:r},e.createSlots({_:2},[e.renderList(t.$slots,(r,o)=>({name:o,fn:e.withCtx(r=>[e.renderSlot(t.$slots,o,e.mergeProps({ref_for:!0},r??{}))])}))]),1032,["schema"]))),128))],2))}});const T=(O=N,j={install(e,t){e.component("SchemxForm",N)},FormItem:E},Object.assign(O,j));var O,j;exports.FormGroup=S,exports.FormItem=E,exports.WithRemoteOptions=function(t){return e.defineComponent({name:`WithRemoteOptions(${t.name||"Anonymous"})`,inheritAttrs:!1,props:{dict:{type:Object,default:void 0},fieldName:{type:[String,Array],default:void 0}},setup(r,{attrs:o,slots:n}){const a=r.dict?h(r.dict,r.fieldName):null,l=e.computed(()=>({...o,dict:r.dict,options:r.dict?null==a?void 0:a.list.value:o.options,loading:r.dict?null==a?void 0:a.loading.value:o.loading}));return()=>e.h(t,l.value,n)}})},exports.default=T,exports.rendererRegistry=n,exports.schemxForm=T,exports.useContext=f,exports.useDictionary=h,exports.useEffect=function(t){const r=o.createEffect(t);return e.onUnmounted(r),r},exports.useField=u,exports.useFieldContext=function(){const t=e.inject(g);if(!t)throw new Error("[schemx] useFieldContext() must be used inside a FormItem tree");return t},exports.useForm=s,exports.useWatch=d,exports.useWatchAll=function(e,t){return d(e,t)},exports.useWatchField=function(e,t,r){return d(e,t,r)},exports.useWatchFields=m,exports.validatorRegistry=a,Object.keys(o).forEach(e=>{"default"===e||Object.prototype.hasOwnProperty.call(exports,e)||Object.defineProperty(exports,e,{enumerable:!0,get:()=>o[e]})});
2
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","sources":["../src/utils/rendererProvider.ts","../src/utils/rulesProvider.ts","../src/hooks/useForm.ts","../src/hooks/useField.ts","../src/hooks/useWatch.ts","../src/hooks/useDictionary.ts","../src/hooks/useContext.ts","../src/hooks/useStableRef.ts","../src/utils/equal.ts","../src/hooks/useFieldContext.ts","../src/utils/validation.ts","../src/utils/slot.ts","../src/components/FormGroup/index.tsx","../src/components/FormItem/index.tsx","../src/form.vue","../src/hooks/useViewSchemas.ts","../src/form.ts","../src/hocs/withRemoteOptions.ts","../src/hooks/useEffect.ts"],"sourcesContent":["/**\n * 全局渲染器注册实例\n *\n * 模块级单例,由 ES Module 保证全局唯一。\n * vant 等 UI 适配层通过 import 后调用 registerAll 注册渲染器,\n * useForm 内部自动使用此实例作为 fallback。\n *\n * @module utils/rendererProvider\n */\n\nimport {\n createRendererRegistry,\n type RendererRegistryType,\n type SchemxRendererKey,\n} from \"@schemx/core\"\n\n/**\n * 全局渲染器注册实例\n *\n * @example\n * ```ts\n * // UI 适配层注册渲染器\n * import { rendererRegistry } from '@schemx/vue'\n * rendererRegistry.registerAll({ input: InputRenderer, ... })\n *\n * // useForm 内部自动使用\n * // props 传入的 rendererRegistry 优先级更高\n * ```\n */\nexport const rendererRegistry: RendererRegistryType<SchemxRendererKey> =\n createRendererRegistry<SchemxRendererKey>(\"input\")\n","/**\n * 全局校验规则注册实例\n *\n * 模块级单例,由 ES Module 保证全局唯一。\n * UI 适配层通过 import 后调用 register/registerAll 注册自定义规则,\n * useForm 内部自动使用此实例作为 fallback。\n *\n * @module utils/rulesProvider\n */\n\nimport { createValidatorsRegistry, type ValidatorsRegistryType } from \"@schemx/core\"\n\n/**\n * 全局校验规则注册实例\n *\n * @example\n * ```ts\n * // 注册自定义规则\n * import { validatorRegistry } from '@schemx/vue'\n * validatorRegistry.register('phone', phoneRule)\n *\n * // useForm 内部自动使用\n * // props 传入的 validatorRegistry 优先级更高\n * ```\n */\nexport const validatorRegistry: ValidatorsRegistryType = createValidatorsRegistry()\n","/**\n * SchemxInstance - 表单实例核心类\n *\n * 组合 Store、Validator,提供统一的表单操作接口。\n * 实现 SchemxInstance 接口,作为 useForm 的底层实现。\n *\n * @module hooks/useForm\n *\n * @example\n * ```typescript\n * import { useForm } from './useForm'\n *\n * // 在 Vue 组件中使用\n * const form = useForm({\n * schemas: [...],\n * initialValues: { name: '', age: 0 },\n * onFinish: (values) => console.log(values),\n * })\n *\n * // 或直接创建实例(非组件场景)\n * const instance = createForm({ initialValues: { name: '' } })\n * ```\n */\nimport { computed, inject, onUnmounted, provide } from \"vue\"\n\nimport { createForm } from \"@schemx/core\"\n\nimport { rendererRegistry as globalRendererRegistry } from \"@/utils/rendererProvider\"\nimport { validatorRegistry as globalRulesRegistry } from \"@/utils/rulesProvider\"\n\nimport type { CreateFormOptions, NamePath, SchemxInstance, Values } from \"@schemx/core\"\n\n/** SchemxInstance 在 Vue provide/inject 中的注入 key */\nexport const SCHEMX_INSTANCE_KEY = Symbol(\"SCHEMX_INSTANCE\")\n/** @deprecated 请使用 SCHEMX_INSTANCE_KEY。保留给旧测试和旧适配代码兼容。 */\nexport const FORM_INSTANCE_KEY = SCHEMX_INSTANCE_KEY\n\n/**\n * useForm 配置选项\n *\n * 扩展 core 层的 CreateFormOptions,增加 Vue 层特有的 request 配置。\n *\n * @typeParam TValues - 表单值类型\n */\nexport interface UseFormOptions<TValues extends Values> extends CreateFormOptions<\n TValues,\n NamePath<TValues>\n> {}\n\n/**\n * 表单组合式函数\n *\n * 创建 SchemxInstance 并通过 Vue provide 注入到子组件树中,\n * 组件卸载时自动销毁实例。\n *\n * @typeParam TValues - 表单值类型\n *\n * @param options - 表单配置选项\n * @returns 表单实例(SchemxInstance 接口)\n *\n * @example\n * ```typescript\n * // 在 setup 中使用\n * const form = useForm({\n * initialValues: { name: '', email: '' },\n * onFinish: async (values) => {\n * await api.submit(values)\n * },\n * })\n *\n * form.setFieldValue('name', 'John')\n * ```\n */\nexport function useForm<TValues extends Values = Values>(\n options: UseFormOptions<TValues>\n): SchemxInstance<TValues> {\n const { ...formOptions } = options\n\n const mergedOptions: CreateFormOptions<TValues> = {\n ...formOptions,\n rendererRegistry: formOptions.rendererRegistry ?? globalRendererRegistry,\n validatorRegistry: formOptions.validatorRegistry ?? globalRulesRegistry,\n }\n\n const instance = computed(() => createForm<TValues>(mergedOptions))\n\n provide<SchemxInstance<TValues>>(SCHEMX_INSTANCE_KEY, instance.value)\n\n onUnmounted(() => {\n instance.value.destroy()\n })\n\n return instance.value\n}\n\n/**\n * 获取表单实例\n *\n * 在子组件中获取 useForm 创建的 SchemxInstance,\n * 可用于读写字段值、校验、订阅等操作。\n *\n * @typeParam TValues - 表单值类型\n * @returns 表单实例\n *\n * @throws Error 如果不在 schemx 提供的上下文中调用\n *\n * @example\n * ```ts\n * const form = useFormInstance()\n * form.setFieldValue('name', 'hello')\n * ```\n */\nexport function useFormInstance<\n TValues extends Values = Values,\n>(): SchemxInstance<TValues> {\n const instance = inject<SchemxInstance<TValues>>(SCHEMX_INSTANCE_KEY)\n\n if (!instance) {\n throw new Error(\"useFormInstance must be used within a Form\")\n }\n\n return instance\n}\n","/**\n * useField - 字段控制 Hook\n *\n * 基于 core 层的 {@link createField} 实现,\n * 通过 subscribe 回调将 Signal 变化桥接到 Vue 响应式系统。\n *\n * @module hooks/useField\n *\n * @remarks\n * core 层的 createField 封装了所有框架无关的字段操作逻辑,\n * useField 只负责:\n * 1. 从 Vue context 中获取 form 实例\n * 2. 创建 shallowRef 容器\n * 3. 通过 subscribe 将 Signal 变化同步到 shallowRef\n * 4. 包装 computed 只读状态\n * 5. 管理 onUnmounted 生命周期清理\n */\n\nimport { computed, onUnmounted, shallowRef } from \"vue\"\n\nimport { createField } from \"@schemx/core\"\n\nimport { FieldInstance } from \"@/types/field\"\n\nimport { useFormInstance } from \"./useForm\"\n\nimport type { NamePath, SchemxInstance, Values } from \"@schemx/core\"\n\n/**\n * useField 针对 (form, name) 的缓存条目\n *\n * 通过引用计数确保同一 (form, name) 的多次 useField 调用\n * 共享同一份 shallowRef 和 effect 桥接,避免重复订阅。\n *\n * @typeParam TValues - 表单值类型\n */\ninterface FieldHookCacheEntry<TValues extends Values = Values> {\n /** 当前活跃的引用计数,归零时释放 dispose 并从缓存中移除 */\n refCount: number\n /** 共享的字段控制器实例(含 Vue Ref 包装) */\n result: FieldInstance<TValues>\n /** 取消 Signal effect 订阅并清理资源 */\n dispose: () => void\n}\n\n/** 模块级缓存:form 实例 → 字段名 → 缓存条目 */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst fieldHookCache = new WeakMap<any, Map<string, FieldHookCacheEntry>>()\n\n/**\n * 创建字段 hook 的响应式状态\n *\n * 从 createField 生成 FieldInstance,创建 shallowRef 容器\n * 并通过 field.effect 将 Signal 变化桥接到 Vue 响应式系统。\n */\nfunction createFieldHook<TValues extends Values = Values>(\n form: SchemxInstance<TValues>,\n name: NamePath<TValues>\n) {\n const field = createField<TValues>(form, name)\n\n const fieldValue = shallowRef(field.getValue())\n const fieldError = shallowRef(field.getError())\n const fieldPending = shallowRef(field.isPending())\n\n const dispose = field.effect(() => {\n fieldValue.value = field.getValue()\n fieldError.value = field.getError()\n\n fieldPending.value = field.isPending()\n })\n\n const error = computed(() => fieldError.value)\n\n const dirty = computed(() => {\n void fieldValue.value\n\n return field.isTouched()\n })\n\n const pending = computed(() => fieldPending.value)\n\n const result = {\n value: fieldValue,\n error,\n dirty,\n pending,\n ...field,\n getValue: () => fieldValue.value,\n }\n\n return { result, dispose }\n}\n\n/**\n * 获取单个字段的控制能力\n *\n * 通过 core 层 createField 提供字段操作方法,\n * 通过 subscribe 回调桥接 Signal 变化到 Vue shallowRef。\n *\n * @param name - 字段名(支持嵌套路径,如 'user.address.city')\n * @returns 字段状态和操作方法\n *\n * @example\n * ```typescript\n * const field = useField('username')\n *\n * // 响应式值(在 computed/watchEffect/template 中自动追踪)\n * field.getValue()\n *\n * // 响应式错误\n * field.error.value // string[] | undefined\n *\n * // 响应式脏状态\n * field.dirty.value // boolean\n *\n * // 响应式操作中状态\n * field.pending.value // boolean\n *\n * // 写入值\n * field.setValue('new value')\n *\n * // 校验\n * const result = await field.validate()\n * ```\n */\nexport const useField = <TValues extends Values = Values>(\n name: NamePath<TValues>\n): FieldInstance<TValues> => {\n const form = useFormInstance<TValues>()\n\n const key = name\n\n let formCache = fieldHookCache.get(form)\n\n if (!formCache) {\n formCache = new Map()\n fieldHookCache.set(form, formCache)\n }\n\n const cachedEntry = formCache.get(key) as FieldHookCacheEntry<TValues> | undefined\n\n let activeEntry: FieldHookCacheEntry<TValues>\n\n if (cachedEntry) {\n cachedEntry.refCount++\n activeEntry = cachedEntry\n } else {\n const { result, dispose } = createFieldHook<TValues>(form, name)\n\n activeEntry = {\n refCount: 1,\n result,\n dispose,\n }\n\n formCache.set(key, activeEntry as any)\n }\n\n onUnmounted(() => {\n if (--activeEntry.refCount <= 0) {\n activeEntry.dispose()\n formCache.delete(key)\n }\n })\n\n return activeEntry.result\n}\n\nexport default useField\n","/**\n * useWatch - 监听字段变化(Vue 组合式 API 版本)\n *\n * 基于 core 层的 {@link createWatch} 实现,\n * 自动通过 `useFormInstance` 获取 formContext,\n * 并在 `onUnmounted` 时自动取消监听,无需手动管理生命周期。\n *\n * 提供三种监听模式:\n * - 全局监听:`useWatch(callback, options?)` — 监听表单中任意字段变化\n * - 单字段监听:`useWatch(name, callback, options?)` — 监听指定字段变化\n * - 多字段监听:`useWatch(names, callback, options?)` — 监听一组字段变化\n *\n * 同时提供语义化的便捷方法:\n * - {@link useWatchField} — 单字段监听\n * - {@link useWatchFields} — 多字段监听\n * - {@link useWatchAll} — 全局监听\n *\n * @module hooks/useWatch\n *\n * @example\n * ```ts\n * // 全局监听\n * useWatch((snapshot) => {\n * console.log('form changed:', snapshot)\n * })\n *\n * // 单字段监听\n * useWatch('username', (current, prev) => {\n * console.log('username changed:', prev, '->', current)\n * }, { immediate: true })\n *\n * // 多字段监听\n * useWatch(['firstName', 'lastName'], (currentValues, prevValues) => {\n * console.log('name changed:', currentValues)\n * }, { inequality: true })\n * ```\n */\n\nimport { onUnmounted } from \"vue\"\n\nimport { createWatch } from \"@schemx/core\"\n\nimport { useFormInstance } from \"./useForm\"\n\nimport type { NamePath, Values } from \"@schemx/core\"\nimport type {\n CreateWatchOptions,\n WatchAllCallback,\n WatchFieldCallback,\n WatchFieldsCallback,\n} from \"@schemx/core\"\n\n/**\n * 监听所有字段变化\n *\n * @param callback - 全局变化回调\n * @param options - 监听选项\n * @returns 取消监听函数\n */\nexport function useWatch<T extends Values>(\n callback: WatchAllCallback<T>,\n options?: CreateWatchOptions\n): () => void\n/**\n * 监听单个字段变化\n *\n * @param name - 字段路径\n * @param callback - 单字段变化回调\n * @param options - 监听选项\n * @returns 取消监听函数\n */\nexport function useWatch<T extends Values>(\n name: NamePath<T>,\n callback: WatchFieldCallback<T>,\n options?: CreateWatchOptions\n): () => void\n/**\n * 监听多个字段变化\n *\n * @param names - 字段路径数组\n * @param callback - 多字段变化回调\n * @param options - 监听选项\n * @returns 取消监听函数\n */\nexport function useWatch<T extends Values>(\n names: NamePath<T>[],\n callback: WatchFieldsCallback<T>,\n options?: CreateWatchOptions\n): () => void\n/**\n * useWatch 实现 — 获取 form 实例后委托给 core 层的 createWatch\n */\nexport function useWatch<T extends Values>(\n nameOrNamesOrCallback: NamePath<T> | NamePath<T>[] | WatchAllCallback<T>,\n callbackOrOptions?: WatchFieldCallback<T> | WatchFieldsCallback<T> | CreateWatchOptions,\n maybeOptions?: CreateWatchOptions\n): () => void {\n const form = useFormInstance<T>()\n\n const dispose = (createWatch as any)(\n form,\n nameOrNamesOrCallback,\n callbackOrOptions,\n maybeOptions\n )\n\n onUnmounted(dispose)\n\n return dispose\n}\n\n/**\n * 监听单个字段变化的便捷方法\n *\n * 等价于 `useWatch(name, callback, options)`,语义更明确。\n * 自动绑定 formContext 并在组件卸载时取消监听。\n *\n * @param name - 要监听的字段路径\n * @param callback - 字段变化回调\n * @param options - 可选配置\n * @returns 取消监听函数\n */\nexport function useWatchField<T extends Values = Values>(\n name: NamePath<T>,\n callback: WatchFieldCallback<T>,\n options?: CreateWatchOptions\n): () => void {\n return useWatch<T>(name, callback, options)\n}\n\n/**\n * 监听多个字段变化的便捷方法\n *\n * 等价于 `useWatch(names, callback, options)`,语义更明确。\n * 自动绑定 formContext 并在组件卸载时取消监听。\n *\n * @param names - 要监听的字段路径数组\n * @param callback - 字段变化回调\n * @param options - 可选配置\n * @returns 取消监听函数\n */\nexport function useWatchFields<T extends Values>(\n names: NamePath<T>[],\n callback: WatchFieldsCallback<T>,\n options?: CreateWatchOptions\n): () => void {\n return useWatch<T>(names, callback, options)\n}\n\n/**\n * 监听所有字段变化的便捷方法\n *\n * 等价于 `useWatch(callback, options)`,语义更明确。\n * 自动绑定 formContext 并在组件卸载时取消监听。\n *\n * @param callback - 全局变化回调\n * @param options - 可选配置\n * @returns 取消监听函数\n */\nexport function useWatchAll<T extends Values = Values>(\n callback: WatchAllCallback<T>,\n options?: CreateWatchOptions\n): () => void {\n return useWatch(callback, options)\n}\n\nexport default useWatch\n","/**\n * useDictionary - 字典选项 Hook\n *\n * 通过 api 函数加载字典选项,支持完整的表单值泛型推导。\n * 自动在组件挂载时加载,支持通过 dependsOn 声明依赖字段,\n * 当依赖字段变化时自动重新请求。\n *\n * @module hooks/useDictionary\n */\n\nimport { onMounted, Ref, ref } from \"vue\"\n\nimport { useFormInstance } from \"./useForm\"\nimport { useWatchFields } from \"./useWatch\"\n\nimport type { FieldValue, NamePath, SchemxDictionary, Values } from \"@schemx/core\"\n\nexport type { SchemxDictionary, SchemxWithDictionary } from \"@schemx/core\"\n\n/**\n * useDictionary 返回值\n */\nexport interface UseDictOptionsReturn {\n /** 远程加载的字典选项列表(响应式) */\n list: Ref<any[]>\n /** 请求加载状态(响应式) */\n loading: Ref<boolean>\n /** 请求错误信息(响应式) */\n error: Ref<Error | undefined>\n /** 触发字典选项加载 */\n loadDict: () => Promise<void>\n /** 使用当前配置重新执行 api */\n refresh: () => Promise<void>\n /** 直接修改 list 的值,不触发 api 调用 */\n mutate: (data: any[]) => void\n}\n\n/**\n * 将未知抛出值规范化为 `Error` 实例\n *\n * @param err - 捕获的值(可能是任意类型)\n * @returns 包装原始值的 `Error` 对象\n */\nexport function normalizeError(err: unknown): Error {\n if (err instanceof Error) return err\n\n return new Error(String(err))\n}\n\n/**\n * 加载字典选项\n *\n * 通过 api 函数获取数据,支持完整的表单值泛型推导。\n * 自动在组件挂载时加载,支持依赖字段联动、竞态控制、\n * 重试、错误处理等能力。\n *\n * @typeParam TValues - 表单值类型\n * @param options - 字典配置选项\n * @param fieldName - 当前字段名,用于 resetOnDepsChange 时清空字段值\n * @returns 响应式选项列表、loading/error 状态及控制方法\n *\n * @example\n * ```ts\n * // 基础用法\n * const { list } = useDictionary({\n * api: async () => {\n * const res = await fetch('/api/options')\n * return res.json()\n * },\n * })\n *\n * // 依赖联动(带泛型)\n * const { list } = useDictionary<MyFormValues>({\n * api: async (values) => fetchCities(values.province),\n * dependsOn: ['province'],\n * shouldFetch: (values) => !!values.province,\n * resetOnDepsChange: true,\n * immediate: false,\n * }, 'city')\n * ```\n */\nexport const useDictionary = <\n TValues extends Values = Values,\n TName extends NamePath<TValues> = NamePath<TValues>,\n TValue = FieldValue<TValues, TName>,\n>(\n options: SchemxDictionary<TValues>,\n fieldName?: TName\n): UseDictOptionsReturn => {\n const instance = useFormInstance<TValues>()\n\n const list = ref<any[]>([])\n const loading = ref<boolean>(false)\n const error = ref<Error | undefined>(undefined)\n\n // 竞态控制:仅最新请求写入状态\n let requestCount = 0\n\n /**\n * 使用配置的 formatter 格式化原始响应数据\n */\n const format = async (res: any): Promise<any> => {\n if (typeof options?.formatter === \"function\") {\n return await options.formatter(res, instance)\n }\n\n return res\n }\n\n /**\n * 带重试的执行\n */\n const executeWithRetry = async (formValues: TValues): Promise<any> => {\n const maxRetries = options.retryCount ?? 0\n const retryDelay = options.retryInterval ?? 1000\n let lastError: Error = new Error(\"Unknown error\")\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n return await options.api(formValues, instance)\n } catch (err) {\n lastError = normalizeError(err)\n\n if (attempt < maxRetries) {\n await new Promise((r) => setTimeout(r, retryDelay))\n }\n }\n }\n\n throw lastError\n }\n\n /**\n * 执行 api 函数加载字典选项\n */\n const loadDict = async (): Promise<void> => {\n try {\n const formValues = instance.getFieldsValue()\n\n // shouldFetch 检查\n if (typeof options.shouldFetch === \"function\" && !options.shouldFetch(formValues)) {\n list.value = []\n loading.value = false\n\n return\n }\n\n loading.value = true\n error.value = undefined\n\n // 递增请求计数器用于竞态控制\n const currentCount = ++requestCount\n\n const res = await executeWithRetry(formValues)\n\n // 竞态检查:丢弃过期响应\n if (currentCount !== requestCount) return\n\n const formatted = await format(res)\n\n // 格式化后再次竞态检查(格式化可能是异步的)\n if (currentCount !== requestCount) return\n\n list.value = formatted\n error.value = undefined\n\n // onSuccess 回调\n if (typeof options.onSuccess === \"function\") {\n options.onSuccess(formatted, instance)\n }\n\n loading.value = false\n } catch (err) {\n const normalized = normalizeError(err)\n\n error.value = normalized\n list.value = []\n loading.value = false\n\n if (typeof options.onError === \"function\") {\n options.onError(normalized, instance)\n }\n }\n }\n\n const refresh = (): Promise<void> => loadDict()\n\n const mutate = (data: any[]): void => {\n list.value = data\n }\n\n // ========== 依赖字段监听 ==========\n if (options.dependsOn?.length) {\n useWatchFields(options.dependsOn, (_payload, latestSnapshot) => {\n // 1. 触发 onDepsChange 回调\n if (typeof options.onDepsChange === \"function\") {\n options.onDepsChange(latestSnapshot as TValues, instance)\n }\n\n // 2. 清空当前字段值\n if (options.resetOnDepsChange && fieldName) {\n instance.setFieldValue(fieldName, undefined)\n }\n\n // 3. 重新执行 api\n void loadDict()\n })\n }\n\n // ========== 挂载行为 ==========\n const immediate = options.immediate ?? true\n\n onMounted(() => {\n if (immediate) {\n void loadDict()\n }\n })\n\n return { list, loading, error, loadDict, refresh, mutate }\n}\n\nexport default useDictionary\n","/**\n * useContext - 表单上下文 Hook\n *\n * 提供表单上下文的创建与消费能力。\n * schemx 通过 createContext 注入全局配置,\n * 子组件通过 useContext 获取。\n *\n * @module hooks/useContext\n */\n\nimport { inject, provide } from \"vue\"\n\nimport type { SchemxFormProps } from \"@/types\"\n\nimport type { Values } from \"@schemx/core\"\n\n/** FormContext 注入 key */\nexport const FORM_CONTEXT_KEY = Symbol(\"FormContext\")\n\n/**\n * 表单上下文属性\n *\n * 由 schemx 组件注入,包含表单级别的全局配置。\n *\n * @typeParam T - 表单值类型\n */\nexport interface FormContextProps<T extends Values = Values> extends Omit<\n SchemxFormProps<T>,\n | \"form\"\n | \"modelValue\"\n | \"rendererRegistry\"\n | \"defaultRendererType\"\n | \"rulesRegistery\"\n | \"onFinish\"\n | \"onFinishFailed\"\n | \"onValuesChange\"\n | \"onFieldsChange\"\n> {}\n\n/**\n * 创建并注入表单上下文\n *\n * 在 schemx 的 setup 中调用,将表单级别配置注入到子组件树中。\n *\n * @typeParam T - 表单值类型\n * @param props - 表单上下文属性\n */\nexport const createContext = <T extends Values = Values>(props: FormContextProps<T>) => {\n provide<FormContextProps<T>>(FORM_CONTEXT_KEY, props)\n}\n\n/**\n * 获取表单上下文配置\n *\n * 在子组件中获取 schemx 注入的全局配置(readonly、disabled、labelAlign 等)。\n *\n * @returns 表单上下文属性\n *\n * @throws Error 如果不在 schemx 提供的上下文中调用\n *\n * @example\n * ```ts\n * const context = useContext()\n * console.log(context.readonly, context.disabled)\n * ```\n */\nexport function useContext(): FormContextProps {\n const context = inject<FormContextProps>(FORM_CONTEXT_KEY)\n\n if (!context) {\n throw new Error(\"useContext must be used within a Form\")\n }\n\n return context\n}\n","/**\n * useStableRef - 引用稳定化的 shallowRef\n *\n * 封装 `shallowRef` + `watchEffect` + `isShallowEqual`,\n * 仅在工厂函数返回值与当前值浅不相等时才更新引用,\n * 避免下游组件因对象引用变化而不必要地重渲染。\n *\n * @module hooks/useStableRef\n *\n * @example\n * ```ts\n * import { useStableRef } from '@schemx/vue'\n *\n * const stableProps = useStableRef(() => ({\n * visible: visible.value,\n * disabled: disabled.value,\n * value: field.getValue(),\n * }))\n * ```\n */\n\nimport { type ShallowRef, shallowRef, watchEffect } from \"vue\"\n\nimport { isShallowEqual } from \"@/utils/equal\"\n\n/**\n * 创建一个引用稳定的 shallowRef。\n *\n * 在 watchEffect 中执行工厂函数,自动追踪响应式依赖。\n * 仅当新旧值浅比较不相等时才替换 `.value`,保持引用稳定。\n *\n * @typeParam T - 对象类型\n *\n * @param factory - 返回目标对象的工厂函数,在 watchEffect 内执行\n *\n * @returns 只读的 ShallowRef,引用仅在属性值真正变化时更新\n *\n * @example\n * ```ts\n * const props = useStableRef(() => ({\n * value: field.getValue(),\n * onChange: handleChange,\n * }))\n *\n * // props.value 的引用在属性值未变时保持不变\n * h(Component, props.value)\n * ```\n */\nexport function useStableRef<T extends Record<string, any>>(\n factory: () => T\n): Readonly<ShallowRef<T>> {\n const stableRef = shallowRef({} as T) as ShallowRef<T>\n\n watchEffect(() => {\n const next = factory()\n\n if (!isShallowEqual(stableRef.value, next)) {\n stableRef.value = next\n }\n })\n\n return stableRef\n}\n\nexport default useStableRef\n","/**\n * 对象浅比较工具\n *\n * @module utils/equal\n */\n\n/**\n * 浅比较两个对象的自有属性值是否相同。\n *\n * 用于避免 computed / shallowRef 每次返回新对象引用导致子组件不必要的更新。\n * 仅比较第一层属性,函数引用通过 === 判断。\n *\n * @param a - 旧对象\n * @param b - 新对象\n *\n * @returns 两个对象浅相等时返回 true\n *\n * @example\n * shallowEqual({ a: 1, b: 2 }, { a: 1, b: 2 }) // => true\n * shallowEqual({ a: 1 }, { a: 1, b: 2 }) // => false\n */\nexport const isShallowEqual = (\n a: Record<string, any>,\n b: Record<string, any>\n): boolean => {\n const keysA = Object.keys(a)\n const keysB = Object.keys(b)\n if (keysA.length !== keysB.length) return false\n\n return keysA.every((key) => a[key] === b[key])\n}\n","/**\n * useFieldContext - 通过 Vue provide/inject 获取当前字段上下文\n *\n * FormItem 通过 provideFieldContext 将 useField 创建的字段实例注入子树,\n * 渲染器通过 useFieldContext 获取,无需知道字段名。\n *\n * @module hooks/useFieldContext\n *\n * @example\n * ```typescript\n * // FormItem 中\n * const field = useField('date')\n * provideFieldContext(field)\n *\n * // 渲染器中\n * const field = useFieldContext()\n * field.error.value // string[] | undefined\n * field.getValue() // 当前字段值(Vue 响应式)\n * ```\n */\n\nimport { inject, type InjectionKey, provide } from \"vue\"\n\nimport { Values } from \"@schemx/core\"\n\nimport { FieldInstance } from \"@/types/field\"\n\nimport type { useField } from \"./useField\"\n\n/** 字段上下文注入 key */\nconst FIELD_CONTEXT_KEY: InjectionKey<FieldInstance> = Symbol(\"schemx:field\")\n\n/**\n * 向子组件树注入当前字段上下文。\n *\n * 应在 FormItem(或任何创建了 useField 的组件)的 setup 中调用。\n *\n * @param field - useField 返回的字段实例\n */\nexport function provideFieldContext<TValues extends Values = Values>(\n field: FieldInstance<TValues>\n): void {\n provide(FIELD_CONTEXT_KEY, field as FieldInstance)\n}\n\n/**\n * 从最近的 FormItem 获取当前字段上下文。\n *\n * 必须在 FormItem 的组件子树内调用,否则抛出错误。\n *\n * @returns useField 返回的字段实例\n *\n * @throws 当不在 FormItem 子树内时抛出\n */\nexport function useFieldContext(): ReturnType<typeof useField> {\n const field = inject(FIELD_CONTEXT_KEY)\n\n if (!field) {\n throw new Error(\"[schemx] useFieldContext() must be used inside a FormItem tree\")\n }\n\n return field\n}\n","/**\n * 校验触发工具\n *\n * 提供校验触发时机的合并、归一化和匹配判断功能。\n *\n * @module utils/validation\n */\n\nimport type { ValidationTrigger } from \"@schemx/core\"\n\n/** 触发时机类型(支持单个或数组) */\nexport type TriggerConfig = ValidationTrigger | ValidationTrigger[]\n\n/** 归一化后的触发类型 */\nexport type NormalizedTrigger = \"blur\" | \"change\" | \"submit\"\n\n/**\n * 判断触发时机配置是否有效。\n *\n * undefined 和空数组视为无效,其余值(包括单个字符串、非空数组)视为有效。\n *\n * @param v - 触发时机配置\n *\n * @returns 配置有效时返回 true\n */\nfunction isValidTrigger(v: TriggerConfig | undefined): v is TriggerConfig {\n if (v === undefined) return false\n if (Array.isArray(v) && v.length === 0) return false\n\n return true\n}\n\n/**\n * 合并校验触发时机配置。\n *\n * 按优先级从高到低取值:列级配置 > 表单上下文配置 > 默认值。\n * 跳过 undefined 和空数组,确保空数组不会意外覆盖后续配置。\n *\n * @param columnTrigger - 列级配置的触发时机\n * @param contextTrigger - 表单上下文配置的触发时机\n * @param defaultTrigger - 兜底默认值\n *\n * @returns 最终生效的触发时机\n *\n * @example\n * mergeTrigger(\"onBlur\", \"onChange\", \"onSubmit\") // => \"onBlur\"\n * mergeTrigger(undefined, \"onChange\", \"onSubmit\") // => \"onChange\"\n * mergeTrigger([], \"onChange\", \"onSubmit\") // => \"onChange\"\n * mergeTrigger(undefined, undefined, \"onSubmit\") // => \"onSubmit\"\n */\nexport function mergeTrigger(\n columnTrigger: TriggerConfig | undefined,\n contextTrigger: TriggerConfig | undefined,\n defaultTrigger: TriggerConfig\n): TriggerConfig {\n if (isValidTrigger(columnTrigger)) return columnTrigger\n\n if (isValidTrigger(contextTrigger)) return contextTrigger\n\n return defaultTrigger\n}\n\n/**\n * 归一化触发类型字符串。\n *\n * 将带 `on` 前缀的格式统一为短格式:\n * `\"onBlur\"` → `\"blur\"`、`\"onChange\"` → `\"change\"`、`\"onSubmit\"` → `\"submit\"`。\n *\n * @param t - 原始触发类型\n *\n * @returns 归一化后的触发类型\n */\nfunction normalizeTrigger(t: ValidationTrigger): NormalizedTrigger {\n const map: Record<ValidationTrigger, NormalizedTrigger> = {\n onBlur: \"blur\",\n onChange: \"change\",\n onSubmit: \"submit\",\n blur: \"blur\",\n change: \"change\",\n submit: \"submit\",\n }\n\n return map[t] ?? \"submit\"\n}\n\n/**\n * 判断当前事件是否应该触发校验。\n *\n * 将配置的触发时机归一化后,与当前事件类型进行匹配。\n *\n * @param event - 当前触发的事件类型\n * @param trigger - 配置的触发时机(支持单个或数组)\n *\n * @returns 是否应该触发校验\n *\n * @example\n * shouldValidateOn(\"change\", \"onChange\") // => true\n * shouldValidateOn(\"blur\", [\"onBlur\", \"onChange\"]) // => true\n * shouldValidateOn(\"change\", \"onSubmit\") // => false\n * shouldValidateOn(\"change\", undefined) // => false\n */\nexport function shouldValidateOn(\n event: NormalizedTrigger,\n trigger?: TriggerConfig\n): boolean {\n if (!trigger) return false\n const triggers = Array.isArray(trigger) ? trigger : [trigger]\n\n return triggers.some((t) => normalizeTrigger(t) === event)\n}\n","/**\n * 插槽解析与子插槽提取工具。\n *\n * 提供 camelCase / kebab-case 双向查找插槽,\n * 以及按字段名前缀提取子渲染器插槽。\n *\n * @module utils/slot\n */\n\n/**\n * 检查字符串是否包含大写字母(驼峰格式特征)。\n *\n * @param str - 待检测的字符串\n * @returns 是否包含大写字母\n */\nconst isCamelCase = (str: string): boolean => /[A-Z]/.test(str)\n\n/**\n * 检查字符串是否包含连字符(kebab-case 特征)。\n *\n * @param str - 待检测的字符串\n * @returns 是否包含连字符\n */\nconst isKebabCase = (str: string): boolean => str.includes(\"-\")\n\n/**\n * 将驼峰命名转换为连字符命名(kebab-case)。\n *\n * @param str - 驼峰格式的字符串\n * @returns 转换后的 kebab-case 字符串\n */\nconst camelToKebab = (str: string): string => {\n return str.replace(/([A-Z])/g, \"-$1\").toLowerCase()\n}\n\n/**\n * 将连字符命名转换为驼峰命名(camelCase)。\n *\n * @param str - kebab-case 格式的字符串\n * @returns 转换后的 camelCase 字符串\n */\nconst kebabToCamel = (str: string): string => {\n return str.replace(/-([a-z])/g, (_match, letter) => letter.toUpperCase())\n}\n\n/**\n * 将命名格式归一化为 kebab-case。\n *\n * @param str - 任意命名格式的字符串\n * @returns kebab-case 格式的字符串\n */\nconst normalizeToKebab = (str: string): string => {\n if (isCamelCase(str)) return camelToKebab(str)\n\n return str\n}\n\n/**\n * 将命名格式归一化为 camelCase。\n *\n * @param str - 任意命名格式的字符串\n * @returns camelCase 格式的字符串\n */\nconst normalizeToCamel = (str: string): string => {\n if (isKebabCase(str)) return kebabToCamel(str)\n\n return str\n}\n\n/**\n * 从插槽对象中按名称查找插槽,同时支持 camelCase 和 kebab-case。\n *\n * 优先查找原始名称,未找到时尝试另一种命名格式。\n * 例如传入 `userName` 时,先查 `userName`,再查 `user-name`;\n * 传入 `user-name` 时,先查 `user-name`,再查 `userName`。\n *\n * @param slots - Vue 插槽对象\n * @param name - 插槽名称(camelCase 或 kebab-case)\n *\n * @returns 匹配的插槽函数,未找到返回 undefined\n *\n * @example\n * ```typescript\n * // slots 中定义了 'user-name' 插槽\n * resolveSlot(slots, 'userName') // => 找到 'user-name' 插槽\n * resolveSlot(slots, 'user-name') // => 找到 'user-name' 插槽\n * ```\n */\nexport const resolveSlot = (\n slots: Record<string, any>,\n name: string\n): ((...args: any[]) => any) | undefined => {\n if (slots[name]) return slots[name]\n\n const alt = isCamelCase(name)\n ? camelToKebab(name)\n : isKebabCase(name)\n ? kebabToCamel(name)\n : undefined\n\n if (alt && slots[alt]) return slots[alt]\n\n return undefined\n}\n\n/**\n * 从父级插槽中提取子渲染器插槽。\n *\n * 按 `fieldName:slotName` 和 `fieldName:slot-name` 格式匹配,\n * 提取后去掉前缀作为子渲染器的插槽名。\n * 同时支持 camelCase 和 kebab-case 的 fieldName。\n *\n * @param fieldName - 字段名\n * @param allSlots - 父级全部插槽\n *\n * @returns 子渲染器的插槽对象\n *\n * @example\n * ```typescript\n * // 父级插槽: { 'userName:prefix': fn, 'userName:suffix': fn, 'userNameLabel': fn }\n * extractChildSlots('userName', slots)\n * // => { prefix: fn, suffix: fn }\n * ```\n */\nexport const extractChildSlots = (\n fieldName: string,\n allSlots: Record<string, any>\n): Record<string, any> => {\n const result: Record<string, any> = {}\n const camelPrefix = normalizeToCamel(String(fieldName)) + \":\"\n const kebabPrefix = normalizeToKebab(String(fieldName)) + \":\"\n\n for (const [key, value] of Object.entries(allSlots)) {\n if (key.startsWith(camelPrefix)) {\n result[key.slice(camelPrefix.length)] = value\n } else if (key.startsWith(kebabPrefix) && kebabPrefix !== camelPrefix) {\n result[key.slice(kebabPrefix.length)] = value\n }\n }\n\n return result\n}\n","/**\n * FormGroup - 分组字段组件\n *\n * 用于渲染 componentType 为 \"group\" 的分组字段配置。\n * 支持可折叠的分组容器,内部渲染子 columns。\n *\n * @module components/FormGroup\n */\n\nimport { defineComponent, PropType, ref } from \"vue\"\nimport type { SetupContext, VNodeChild } from \"vue\"\n\nimport classnames from \"classnames\"\n\nimport FormItem from \"../FormItem\"\n\nimport type { SchemxViewGroupSchema, SchemxViewSchema, Values } from \"@schemx/core\"\n\n/**\n * FormGroup Props\n *\n * @typeParam T - 表单值类型\n */\nexport interface SchemxGroupProps<T extends Values = Values> {\n schema: SchemxViewGroupSchema<T>\n}\n\nconst FormGroup = defineComponent(\n <T extends Values = Values>(props: SchemxGroupProps<T>, { slots }: SetupContext) => {\n const collapsed = ref(Boolean(props.schema.defaultCollapsed))\n\n const toggle = () => {\n if (props.schema.collapsible) {\n collapsed.value = !collapsed.value\n }\n }\n\n return (): VNodeChild => {\n const schema = props.schema\n const collapsible = Boolean(schema.collapsible)\n\n return (\n <div\n class={classnames(\n \"schemx-group\",\n { \"schemx-group--collapsed\": collapsed.value },\n schema.class as string | undefined\n )}\n data-key={schema.key}\n >\n {schema.label && (\n <div\n role={collapsible ? \"button\" : undefined}\n tabindex={collapsible ? 0 : undefined}\n class={classnames(\"schemx-group__header\", {\n \"schemx-group__header--clickable\": collapsible,\n })}\n onClick={toggle}\n onKeydown={(e: KeyboardEvent) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault()\n toggle()\n }\n }}\n >\n <span class=\"schemx-group__title\">{schema.label}</span>\n {collapsible && (\n <span\n class={classnames(\"schemx-group__arrow\", {\n \"schemx-group__arrow--down\": !collapsed.value,\n })}\n />\n )}\n </div>\n )}\n {!collapsed.value && (\n <div class=\"schemx-group__body\">\n {schema.children.map((child) => (\n <FormItem\n key={child.key}\n schema={child as SchemxViewSchema}\n v-slots={slots}\n />\n ))}\n </div>\n )}\n </div>\n )\n }\n },\n {\n name: \"SchemxGroup\",\n\n props: {\n schema: {\n type: Object as PropType<SchemxViewGroupSchema>,\n required: true,\n },\n },\n }\n)\n\nexport default FormGroup\n","/**\n * FormItem\n *\n * schemx 和 FormGroup 实际渲染字段的组件。\n * 动态属性已由 core 解析到 ViewSchema 中;这里只负责消费\n * 已解析 schema、创建字段实例、组装渲染器属性与插槽。\n *\n * @module components/FormItem\n */\n\nimport { computed, defineComponent, h, PropType, toRef } from \"vue\"\nimport type { SetupContext, VNodeChild } from \"vue\"\n\nimport classnames from \"classnames\"\nimport { omit } from \"es-toolkit\"\n\nimport { useField } from \"@/hooks\"\nimport { useContext } from \"@/hooks/useContext\"\nimport { provideFieldContext } from \"@/hooks/useFieldContext\"\nimport { useFormInstance } from \"@/hooks/useForm\"\nimport { useStableRef } from \"@/hooks/useStableRef\"\nimport { extractChildSlots, mergeTrigger, resolveSlot, shouldValidateOn } from \"@/utils\"\nimport type { TriggerConfig } from \"@/utils\"\n\nimport FormGroup from \"../FormGroup\"\n\nimport type {\n FieldValue,\n NamePath,\n SchemxComponentProps,\n SchemxFormItemProps,\n SchemxViewFieldSchema,\n SchemxViewGroupSchema,\n SchemxViewSchema,\n Values,\n} from \"@schemx/core\"\n\n/**\n * FormItem 属性。\n *\n * @typeParam T - 表单值类型\n */\nexport interface SchemxItemProps<T extends Values = Values> {\n schema: SchemxViewSchema<T>\n}\n\nconst FormItem = defineComponent(\n <T extends Values = Values>(props: SchemxItemProps<T>, { slots }: SetupContext) => {\n const schemaRef = toRef(props, \"schema\")\n\n if (isViewGroupSchema(schemaRef.value)) {\n return (): VNodeChild => {\n return h(FormGroup, { schema: schemaRef.value as SchemxViewGroupSchema }, slots)\n }\n }\n\n const form = useFormInstance<T>()\n const formContext = useContext()\n\n const schema = (): SchemxViewFieldSchema<T> =>\n schemaRef.value as SchemxViewFieldSchema<T>\n\n const field = useField(schema().name)\n\n provideFieldContext(field)\n\n const trigger = computed<TriggerConfig>(() =>\n mergeTrigger(schema().validationTrigger, formContext.validationTrigger, \"onChange\")\n )\n\n /**\n * 是否需要进行校验。\n *\n * 当字段不可见、只读或禁用时,无需进行校验。\n */\n const canVerified = computed(() => {\n const isOperate = schema().visible && !schema().readonly && !schema().disabled\n\n const rules = schema().rules\n\n const hasRules = Array.isArray(rules) ? rules?.length > 0 : !!schema().rules\n\n return isOperate && hasRules\n })\n\n /** 值变化处理,设置值后根据触发时机决定是否校验 */\n const handleChange = (v: FieldValue<T, NamePath<T>>) => {\n field.setValue(v)\n schema().componentProps?.onChange?.(v)\n\n if (canVerified.value && shouldValidateOn(\"change\", trigger.value)) {\n field.validate()\n }\n }\n\n /** 失焦处理,根据触发时机决定是否校验 */\n const handleBlur = () => {\n // schema().componentProps?.onBlur?.()\n\n if (canVerified.value && shouldValidateOn(\"blur\", trigger.value)) {\n field.validate()\n }\n }\n\n /**\n * schemas 每一项的 props\n */\n const formItemProps = computed<SchemxFormItemProps<T>>((): SchemxFormItemProps<T> => {\n return {\n ...(omit(schema(), [\"componentProps\"]) satisfies SchemxFormItemProps<T>),\n name: schema().name,\n componentType: schema().componentType,\n class: classnames(\"schemx-item\", schema().class),\n required: schema().required,\n readonly: schema().readonly,\n disabled: schema().disabled,\n visible: schema().visible,\n placeholder: schema().placeholder,\n validationTrigger: trigger.value,\n }\n })\n\n // 使用 useStableRef 避免每次生成新对象引用\n const componentProps = useStableRef<SchemxComponentProps<T>>(\n (): SchemxComponentProps<T> => ({\n ...schema().componentProps,\n formItemProps: formItemProps.value,\n value: field.getValue(),\n readonly: schema().readonly,\n disabled: schema().disabled,\n placeholder: schema().placeholder,\n onChange: handleChange,\n onBlur: handleBlur,\n \"onUpdate:value\": (v) => field.setValue(v),\n })\n )\n\n /**\n * 渲染 required 星号。\n *\n * 当字段为必填且非禁用/只读状态时,在 label 前显示红色星号标记。\n *\n * @returns 星号 VNode 或空片段\n */\n const renderRequired = (): VNodeChild => {\n if (!schema().required || schema().disabled || schema().readonly) {\n return null\n }\n\n return <span class=\"schemx-item__required\">*</span>\n }\n\n /**\n * 渲染 formItem label 区域。\n *\n * 优先使用 `{name}Label` 插槽(支持 camelCase / kebab-case),\n * 未提供时渲染默认 label(含 required 星号、label 文本、冒号)。\n *\n * @returns label VNode\n */\n const renderLabel = (): VNodeChild => {\n const labelSlot = resolveSlot(slots, `${schema().name}Label`)\n\n if (labelSlot) {\n return labelSlot(formItemProps.value)\n }\n\n const labelAlign = schema().labelAlign || formContext.labelAlign\n const labelWidth = schema().labelWidth || formContext.labelWidth\n const colon = schema().colon ?? formContext.colon\n\n return (\n <label\n class=\"schemx-item__label\"\n style={{ width: labelWidth, textAlign: labelAlign }}\n >\n {renderRequired()}\n <span class=\"schemx-item__label-text\">\n {schema().label}\n {colon ? \":\" : \"\"}\n </span>\n </label>\n )\n }\n\n /**\n * 渲染 formItem content 区域(仅控件)。\n *\n * 优先使用 `{name}Content` 插槽(支持 camelCase / kebab-case),\n * 插槽参数包含 formItemProps 和 columnElement(渲染器 VNode)。\n * 未提供插槽时,渲染默认控件布局。\n *\n * @returns content VNode\n */\n const renderContent = (): VNodeChild => {\n const component = form.getRenderer(schema().componentType)\n\n if (!component) {\n throw new Error(\n `[schemx] Can not find component renderer of \"${schema().componentType}\".`\n )\n }\n\n // 提取子渲染器插槽(fieldName:slotName 格式)\n const childSlots = extractChildSlots(normalizeNameKey(schema().name), slots)\n const columnElement = h(component, componentProps.value, childSlots)\n\n const contentSlot = resolveSlot(slots, `${schema().name}Content`)\n\n if (contentSlot) {\n return contentSlot({\n ...formItemProps.value,\n columnElement,\n })\n }\n\n return <div class=\"schemx-item__control\">{columnElement}</div>\n }\n\n /**\n * 渲染 formItem error 区域。\n *\n * 优先使用 `{name}Error` 插槽(支持 camelCase / kebab-case),\n * 插槽参数包含 formItemProps 和 errors 数组。\n * 未提供插槽时,仅在存在错误时显示第一条错误信息。\n *\n * @returns error VNode 或 null\n */\n const renderError = (): VNodeChild => {\n const errorSlot = resolveSlot(slots, `${schema().name}Error`)\n\n if (errorSlot) {\n return errorSlot({\n ...formItemProps.value,\n errors: field.error.value,\n })\n }\n\n if (!Array.isArray(field.error.value) || field.error.value.length === 0) {\n return null\n }\n\n return <div class=\"schemx-item__error\">{field.error.value[0]}</div>\n }\n\n return (): VNodeChild => {\n if (!schema().visible) {\n return null\n }\n\n // 整体插槽:完全接管渲染,不包裹任何默认结构\n const itemSlot = resolveSlot(slots, normalizeNameKey(schema().name))\n\n if (itemSlot) {\n return itemSlot(formItemProps.value)\n }\n\n const labelPosition = schema().labelPosition || formContext.labelPosition\n\n return (\n <div\n class={classnames(\"schemx-item-wrapper\", {\n \"is-readonly\": schema().readonly,\n \"is-disabled\": schema().disabled,\n })}\n >\n <div\n class={classnames(\n \"schemx-item\",\n `schemx-item--label-${labelPosition}`,\n schema().class\n )}\n style={{ ...(schema().style ?? {}) }}\n >\n {renderLabel()}\n\n <div class=\"schemx-item__content\">\n {renderContent()}\n {renderError()}\n </div>\n </div>\n </div>\n )\n }\n },\n {\n name: \"SchemxItem\",\n\n props: {\n schema: {\n type: Object as PropType<SchemxViewSchema>,\n required: true,\n },\n },\n }\n)\n\nexport default FormItem\n\nconst isViewGroupSchema = <T extends Values>(\n schema: SchemxViewSchema<T>\n): schema is SchemxViewGroupSchema<T> => {\n return schema.componentType === \"group\"\n}\n\nconst normalizeNameKey = (name: unknown): string => {\n if (Array.isArray(name)) {\n return name.map((part) => String(part)).join(\".\")\n }\n\n return String(name)\n}\n","<!--\n schemx - 主组件\n\n 基于 Schema 配置的表单组件,使用 useForm Hook 管理状态。\n\n @module schemx\n-->\n\n<script lang=\"ts\" setup generic=\"T extends Values = Values\">\n import { watch, watchEffect } from \"vue\"\n\n import { omit } from \"es-toolkit\"\n\n import type { SchemxFormProps } from \"@/types\"\n\n import FormItem from \"./components/FormItem\"\n import { createContext } from \"./hooks/useContext\"\n import { useForm } from \"./hooks/useForm\"\n import { useViewSchemas } from \"./hooks/useViewSchemas\"\n\n import type { SchemxViewSchema, Values } from \"@schemx/core\"\n\n import \"./styles/index.css\"\n\n defineOptions({ name: \"SchemxForm\" })\n\n const props = withDefaults(defineProps<SchemxFormProps<T>>(), {\n modelValue: () => ({}) as T,\n initialValues: () => ({}) as T,\n form: undefined,\n schemas: () => [],\n class: \"\",\n style: () => ({}),\n onFinish: undefined,\n onFinishFailed: undefined,\n onValuesChange: undefined,\n onFieldsChange: undefined,\n rendererRegistry: undefined,\n validatorRegistry: undefined,\n })\n\n const emit = defineEmits<{\n \"update:modelValue\": [value: T]\n }>()\n\n /**\n * 创建 FormContext 上下文\n *\n * 为子组件提供表单配置信息。\n */\n createContext(\n omit(props, [\n \"form\",\n \"modelValue\",\n \"rendererRegistry\",\n \"defaultRendererType\",\n \"validatorRegistry\",\n \"onFinish\",\n \"onFinishFailed\",\n \"onValuesChange\",\n \"onFieldsChange\",\n ])\n )\n\n /**\n * 获取或创建表单实例\n *\n * 优先使用外部传入的 form,否则内部通过 useForm 创建。\n * 必须在 setup 同步阶段调用,确保 provide 正确注入。\n */\n const form = props.form\n ? props.form\n : useForm<T>({\n schemas: props.schemas,\n initialValues: props.initialValues,\n rendererRegistry: props.rendererRegistry,\n defaultRendererType: props.defaultRendererType,\n validatorRegistry: props.validatorRegistry,\n\n readonly: props.readonly,\n disabled: props.disabled,\n\n onFinish: async (values) => {\n props.onFinish?.(values)\n },\n onFinishFailed: async (errors) => {\n props.onFinishFailed?.(errors)\n },\n onValuesChange: (changedValues, latestSnapshot) => {\n emit(\"update:modelValue\", latestSnapshot as T)\n props.onValuesChange?.(changedValues, latestSnapshot)\n },\n onFieldsChange: (changedPaths, allPaths) => {\n props.onFieldsChange?.(changedPaths, allPaths)\n },\n })\n\n watch(\n () => props.schemas,\n (schemas) => {\n form.setSchemas(schemas)\n },\n { deep: false, immediate: !!props.form }\n )\n\n const viewSchemas = useViewSchemas(form)\n\n watchEffect(() => {\n form.updateDefaultProps(props)\n })\n\n defineExpose({\n ...form,\n })\n</script>\n\n<template>\n <div :class=\"['schemx', props.class]\">\n <FormItem\n v-for=\"schema in viewSchemas\"\n :key=\"schema.key\"\n :schema=\"schema as SchemxViewSchema\"\n >\n <template v-for=\"(_, slotName) in $slots\" #[slotName]=\"slotProps\">\n <slot :name=\"slotName\" v-bind=\"slotProps ?? {}\" />\n </template>\n </FormItem>\n </div>\n</template>\n","/**\n * useViewSchemas - Vue ViewSchemas bridge.\n *\n * @module hooks/useViewSchemas\n */\n\nimport { onScopeDispose, shallowRef } from \"vue\"\nimport type { ShallowRef } from \"vue\"\n\nimport type { SchemxInstance, SchemxViewSchema, Values } from \"@schemx/core\"\n\nexport function useViewSchemas<T extends Values = Values>(\n form: SchemxInstance<T>\n): ShallowRef<readonly SchemxViewSchema<T>[]> {\n const viewSchemas = shallowRef<readonly SchemxViewSchema<T>[]>(form.getViewSchemas())\n\n const unsubscribe = form.subscribeViewSchemas((nextSchemas) => {\n viewSchemas.value = nextSchemas\n })\n\n onScopeDispose(unsubscribe)\n\n return viewSchemas\n}\n\nexport default useViewSchemas\n","/**\n * schemx 组件导出\n *\n * 为 SchemxForm 组件挂载静态方法(install、FormItem、registerRequest 等),\n * 并作为默认导出。\n *\n * @module formExport\n */\n\nimport type { App, DefineComponent } from \"vue\"\n\nimport FormItem from \"./components/FormItem\"\nimport SchemxForm from \"./formRuntime.js\"\n\nimport type { SchemxFormProps } from \"./types\"\n\n/**\n * SchemxForm 插件安装选项\n *\n * 在 `app.use(SchemxForm, options)` 时传入,用于配置全局默认行为。\n *\n * @example\n * ```ts\n * import SchemxForm from '@schemx/vue'\n *\n * app.use(SchemxForm, {\n * request: (url) => fetch(url).then(r => r.json()),\n * })\n * ```\n */\nexport interface SchemxInstallOptions {}\n\n/**\n * 为组件挂载静态属性并保留原始类型\n *\n * @param comp - 原始组件\n * @param extra - 要挂载的静态属性\n */\nexport function withInstall<T extends object, E extends Record<string, unknown>>(\n comp: T,\n extra: E\n) {\n return Object.assign(comp, extra) as T & E\n}\n\nexport type SchemxFormPlugin = DefineComponent<SchemxFormProps> & {\n install: (app: App, options?: SchemxInstallOptions) => void\n FormItem: typeof FormItem\n}\n\nconst SchemxFormExport = withInstall(SchemxForm, {\n /** Vue 插件安装方法 */\n install(app: App, _options?: SchemxInstallOptions) {\n app.component(\"SchemxForm\", SchemxForm)\n },\n /** FormItem 子组件引用 */\n FormItem,\n}) as unknown as SchemxFormPlugin\n\nexport default SchemxFormExport\n","/**\n * WithRemoteOptions - 选项高阶组件\n *\n * 包装任意渲染器组件,自动注入 useDictionary 的选项加载能力。\n * 被包装组件会额外收到 options、loading 两个 props,\n * 无需自行调用 useDictionary。\n *\n * @module hocs/withRemoteOptions\n */\n\nimport { Component, computed, defineComponent, h, PropType, SetupContext } from \"vue\"\n\nimport { useDictionary } from \"@/hooks/useDictionary\"\n\nimport type { NamePath, SchemxDictionary } from \"@schemx/core\"\n\nexport type { SchemxDictionary, SchemxWithDictionary } from \"@schemx/core\"\n\n/**\n * WithRemoteOptions 注入给被包装组件的额外 Props\n */\nexport interface RemoteOptionsInjectedProps {\n /** 加载的选项列表 */\n options: any[]\n /** 加载状态 */\n loading: boolean\n}\n\n/**\n * 选项高阶组件\n *\n * 包装一个渲染器组件,当 dict prop 存在时,\n * 调用 useDictionary 加载选项,并将结果作为 options prop 注入。\n *\n * 当组件自身已传入非空 options 且无 dict 时,优先使用静态 options。\n *\n * @param WrappedComponent - 被包装的渲染器组件\n * @returns 增强后的组件,自动具备选项加载能力\n *\n * @example\n * ```ts\n * import { WithRemoteOptions } from '@schemx/vue'\n * import MySelect from './MySelect.vue'\n *\n * const RemoteSelect = WithRemoteOptions(MySelect)\n *\n * // 在 schema 中使用\n * const schema = {\n * name: 'city',\n * label: '城市',\n * componentType: 'select',\n * componentProps: {\n * dict: {\n * api: async (values) => fetchCities(values.province),\n * dependsOn: ['province'],\n * shouldFetch: (values) => !!values.province,\n * resetOnDepsChange: true,\n * immediate: false,\n * },\n * },\n * }\n * ```\n */\nexport function WithRemoteOptions(WrappedComponent: Component) {\n return defineComponent({\n name: `WithRemoteOptions(${WrappedComponent.name || \"Anonymous\"})`,\n inheritAttrs: false,\n props: {\n dict: {\n type: Object as PropType<SchemxDictionary>,\n default: undefined,\n },\n fieldName: {\n type: [String, Array] as PropType<NamePath>,\n default: undefined,\n },\n },\n setup(props, { attrs, slots }: SetupContext) {\n // 仅在 dict 配置存在时调用 useDictionary\n const dictResult = props.dict ? useDictionary(props.dict, props.fieldName) : null\n\n const childrenProps = computed(() => {\n return {\n ...attrs,\n dict: props.dict,\n options: props.dict ? dictResult?.list.value : attrs.options,\n loading: props.dict ? dictResult?.loading.value : attrs.loading,\n }\n })\n\n return () => h(WrappedComponent, childrenProps.value, slots)\n },\n })\n}\n\nexport default WithRemoteOptions\n","/**\n * useEffect - Vue 组合式 API 版本的 Signal effect\n *\n * 封装 `@schemx/core` 的 `createEffect`,在组件卸载时自动 dispose,\n * 无需手动管理生命周期。\n *\n * @module hooks/useEffect\n *\n * @example\n * ```ts\n * import { useEffect } from '@schemx/vue'\n *\n * // 在 setup 中使用\n * useEffect(() => {\n * const name = form.getFieldValue('name')\n * console.log('name:', name)\n *\n * return () => {\n * // 清理逻辑\n * }\n * })\n * ```\n */\n\nimport { onUnmounted } from \"vue\"\n\nimport { createEffect } from \"@schemx/core\"\n\nimport type { CreateEffectReturn, EffectCallback } from \"@schemx/core\"\n\n/**\n * 创建 Signal effect 并在组件卸载时自动取消。\n *\n * 在 effect 回调中访问任何 Signal 值时自动追踪依赖,\n * 依赖变化时自动重新执行回调。\n * 回调可返回一个清理函数,在 effect 重新执行前或被 dispose 时调用。\n *\n * @param callback - effect 回调函数,可选返回清理函数\n *\n * @returns 取消 effect 的 dispose 函数(通常无需手动调用,组件卸载时自动取消)\n *\n * @example\n * ```ts\n * // 监听字段值变化\n * useEffect(() => {\n * const name = form.getFieldValue('name')\n * console.log('name changed:', name)\n * })\n *\n * // 带清理函数\n * useEffect(() => {\n * const timer = setInterval(() => {\n * console.log('value:', form.getFieldValue('count'))\n * }, 1000)\n *\n * return () => clearInterval(timer)\n * })\n * ```\n */\nexport function useEffect(callback: EffectCallback): CreateEffectReturn {\n const dispose = createEffect(callback)\n\n onUnmounted(dispose)\n\n return dispose\n}\n\nexport default useEffect\n"],"names":["rendererRegistry","createRendererRegistry","validatorRegistry","createValidatorsRegistry","SCHEMX_INSTANCE_KEY","Symbol","useForm","options","formOptions","mergedOptions","globalRendererRegistry","globalRulesRegistry","instance","computed","createForm","provide","value","onUnmounted","destroy","useFormInstance","inject","Error","fieldHookCache","WeakMap","useField","name","form","key","formCache","get","Map","set","cachedEntry","activeEntry","refCount","result","dispose","field","createField","fieldValue","shallowRef","getValue","fieldError","getError","fieldPending","isPending","effect","error","dirty","isTouched","pending","createFieldHook","delete","useWatch","nameOrNamesOrCallback","callbackOrOptions","maybeOptions","createWatch","useWatchFields","names","callback","normalizeError","err","String","useDictionary","fieldName","list","ref","loading","requestCount","loadDict","async","formValues","getFieldsValue","shouldFetch","currentCount","res","maxRetries","retryCount","retryDelay","retryInterval","lastError","attempt","api","Promise","r","setTimeout","executeWithRetry","formatted","formatter","format","onSuccess","normalized","onError","_a","dependsOn","length","_payload","latestSnapshot","onDepsChange","resetOnDepsChange","setFieldValue","immediate","onMounted","refresh","mutate","data","FORM_CONTEXT_KEY","useContext","context","useStableRef","factory","stableRef","watchEffect","next","a","b","keysA","Object","keys","keysB","every","isShallowEqual","FIELD_CONTEXT_KEY","isValidTrigger","v","Array","isArray","shouldValidateOn","event","trigger","some","t","onBlur","onChange","onSubmit","blur","change","submit","normalizeTrigger","isCamelCase","str","test","isKebabCase","includes","camelToKebab","replace","toLowerCase","kebabToCamel","_match","letter","toUpperCase","resolveSlot","slots","alt","extractChildSlots","allSlots","camelPrefix","kebabPrefix","normalizeToKebab","entries","startsWith","slice","FormGroup","defineComponent","props","collapsed","Boolean","schema","defaultCollapsed","toggle","collapsible","_createVNode","class","classnames","label","role","undefined","tabindex","onClick","onKeydown","e","preventDefault","children","map","child","FormItem","type","required","schemaRef","toRef","isViewGroupSchema","h","formContext","provideFieldContext","mergeTrigger","columnTrigger","validationTrigger","contextTrigger","defaultTrigger","canVerified","isOperate","visible","readonly","disabled","rules","hasRules","handleChange","setValue","componentProps","validate","handleBlur","formItemProps","omit","componentType","placeholder","renderLabel","labelSlot","labelAlign","labelWidth","colon","style","width","textAlign","_createTextVNode","renderContent","component","getRenderer","childSlots","normalizeNameKey","columnElement","contentSlot","renderError","errorSlot","errors","itemSlot","labelPosition","part","join","__props","emit","__emit","createContext","schemas","initialValues","defaultRendererType","onFinish","values","call","onFinishFailed","onValuesChange","changedValues","onFieldsChange","changedPaths","allPaths","watch","setSchemas","deep","viewSchemas","getViewSchemas","unsubscribe","subscribeViewSchemas","nextSchemas","onScopeDispose","useViewSchemas","updateDefaultProps","__expose","_createElementBlock","_normalizeClass","_Fragment","_renderList","_unref","_createBlock","$slots","_","slotName","fn","_withCtx","slotProps","_renderSlot","_ctx","_mergeProps","SchemxFormExport","comp","SchemxForm","extra","install","app","_options","assign","WrappedComponent","inheritAttrs","dict","default","setup","attrs","dictResult","childrenProps","createEffect"],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+
2
+ /** 默认导出 */
3
+ export { default } from './form';
4
+ export { default as schemxForm } from './form';
5
+ export type { SchemxInstallOptions } from './form';
6
+ /** 全局渲染器注册实例 */
7
+ export { rendererRegistry } from './utils/rendererProvider';
8
+ /** 全局校验规则注册实例 */
9
+ export { validatorRegistry } from './utils/rulesProvider';
10
+ /** Hooks */
11
+ export { useForm, useField, useWatch, useWatchField, useWatchFields, useWatchAll, useDictionary, useContext, useEffect, useFieldContext, type UseDictOptionsReturn, type FormContextProps, } from './hooks';
12
+ /** 高阶组件 */
13
+ export { WithRemoteOptions } from './hocs';
14
+ /** 组件 */
15
+ export { default as FormItem } from './components/FormItem';
16
+ export { default as FormGroup } from './components/FormGroup';
17
+ /** schemx/core 导出 */
18
+ export * from '@schemx/core';
19
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,oBAAoB,CAAA;AAE3B,WAAW;AACX,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAA;AAChC,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,QAAQ,CAAA;AAC9C,YAAY,EAAE,oBAAoB,EAAE,MAAM,QAAQ,CAAA;AAElD,gBAAgB;AAChB,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAA;AAE3D,iBAAiB;AACjB,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAA;AAEzD,YAAY;AACZ,OAAO,EACL,OAAO,EACP,QAAQ,EACR,QAAQ,EACR,aAAa,EACb,cAAc,EACd,WAAW,EACX,aAAa,EACb,UAAU,EACV,SAAS,EACT,eAAe,EACf,KAAK,oBAAoB,EACzB,KAAK,gBAAgB,GACtB,MAAM,SAAS,CAAA;AAEhB,WAAW;AACX,OAAO,EAAE,iBAAiB,EAAE,MAAM,QAAQ,CAAA;AAE1C,SAAS;AACT,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,uBAAuB,CAAA;AAC3D,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,wBAAwB,CAAA;AAE7D,qBAAqB;AACrB,cAAc,cAAc,CAAA"}