@object-ui/plugin-form 0.5.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +8 -6
- package/CHANGELOG.md +15 -0
- package/dist/index.js +1388 -283
- package/dist/index.umd.cjs +2 -2
- package/dist/packages/plugin-form/src/DrawerForm.d.ts +61 -0
- package/dist/packages/plugin-form/src/FormSection.d.ts +49 -0
- package/dist/packages/plugin-form/src/FormVariants.test.d.ts +0 -0
- package/dist/packages/plugin-form/src/ModalForm.d.ts +60 -0
- package/dist/packages/plugin-form/src/SplitForm.d.ts +50 -0
- package/dist/packages/plugin-form/src/TabbedForm.d.ts +123 -0
- package/dist/packages/plugin-form/src/WizardForm.d.ts +112 -0
- package/dist/packages/plugin-form/src/__tests__/NewVariants.test.d.ts +8 -0
- package/dist/packages/plugin-form/src/index.d.ts +12 -0
- package/package.json +8 -8
- package/src/DrawerForm.tsx +385 -0
- package/src/FormSection.tsx +144 -0
- package/src/FormVariants.test.tsx +219 -0
- package/src/ModalForm.tsx +379 -0
- package/src/ObjectForm.msw.test.tsx +29 -2
- package/src/ObjectForm.tsx +204 -6
- package/src/SplitForm.tsx +299 -0
- package/src/TabbedForm.tsx +394 -0
- package/src/WizardForm.tsx +501 -0
- package/src/__tests__/NewVariants.test.tsx +488 -0
- package/src/index.tsx +60 -3
- package/vitest.config.ts +12 -0
- package/vitest.setup.ts +1 -0
package/dist/index.umd.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
(function(
|
|
1
|
+
(function(z,o){typeof exports=="object"&&typeof module<"u"?o(exports,require("react"),require("@object-ui/core"),require("@object-ui/react"),require("@object-ui/fields"),require("@object-ui/components"),require("lucide-react")):typeof define=="function"&&define.amd?define(["exports","react","@object-ui/core","@object-ui/react","@object-ui/fields","@object-ui/components","lucide-react"],o):(z=typeof globalThis<"u"?globalThis:z||self,o(z.ObjectUIPluginForm={},z.React,z.core,z.react,z.fields,z.components,z.lucideReact))})(this,(function(z,o,K,R,L,j,H){"use strict";var G={exports:{}},B={};var ee;function me(){if(ee)return B;ee=1;var e=Symbol.for("react.transitional.element"),l=Symbol.for("react.fragment");function c(u,v,m){var C=null;if(m!==void 0&&(C=""+m),v.key!==void 0&&(C=""+v.key),"key"in v){m={};for(var O in v)O!=="key"&&(m[O]=v[O])}else m=v;return v=m.ref,{$$typeof:e,type:u,key:C,ref:v!==void 0?v:null,props:m}}return B.Fragment=l,B.jsx=c,B.jsxs=c,B}var J={};var te;function ye(){return te||(te=1,process.env.NODE_ENV!=="production"&&(function(){function e(r){if(r==null)return null;if(typeof r=="function")return r.$$typeof===W?null:r.displayName||r.name||null;if(typeof r=="string")return r;switch(r){case I:return"Fragment";case M:return"Profiler";case k:return"StrictMode";case s:return"Suspense";case d:return"SuspenseList";case S:return"Activity"}if(typeof r=="object")switch(typeof r.tag=="number"&&console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."),r.$$typeof){case $:return"Portal";case a:return r.displayName||"Context";case p:return(r._context.displayName||"Context")+".Consumer";case i:var y=r.render;return r=r.displayName,r||(r=y.displayName||y.name||"",r=r!==""?"ForwardRef("+r+")":"ForwardRef"),r;case f:return y=r.displayName||null,y!==null?y:e(r.type)||"Memo";case n:y=r._payload,r=r._init;try{return e(r(y))}catch{}}return null}function l(r){return""+r}function c(r){try{l(r);var y=!1}catch{y=!0}if(y){y=console;var F=y.error,h=typeof Symbol=="function"&&Symbol.toStringTag&&r[Symbol.toStringTag]||r.constructor.name||"Object";return F.call(y,"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",h),l(r)}}function u(r){if(r===I)return"<>";if(typeof r=="object"&&r!==null&&r.$$typeof===n)return"<...>";try{var y=e(r);return y?"<"+y+">":"<...>"}catch{return"<...>"}}function v(){var r=b.A;return r===null?null:r.getOwner()}function m(){return Error("react-stack-top-frame")}function C(r){if(g.call(r,"key")){var y=Object.getOwnPropertyDescriptor(r,"key").get;if(y&&y.isReactWarning)return!1}return r.key!==void 0}function O(r,y){function F(){q||(q=!0,console.error("%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",y))}F.isReactWarning=!0,Object.defineProperty(r,"key",{get:F,configurable:!0})}function T(){var r=e(this.type);return fe[r]||(fe[r]=!0,console.error("Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release.")),r=this.props.ref,r!==void 0?r:null}function E(r,y,F,h,X,Q){var P=F.ref;return r={$$typeof:V,type:r,key:y,props:F,_owner:h},(P!==void 0?P:null)!==null?Object.defineProperty(r,"ref",{enumerable:!1,get:T}):Object.defineProperty(r,"ref",{enumerable:!1,value:null}),r._store={},Object.defineProperty(r._store,"validated",{configurable:!1,enumerable:!1,writable:!0,value:0}),Object.defineProperty(r,"_debugInfo",{configurable:!1,enumerable:!1,writable:!0,value:null}),Object.defineProperty(r,"_debugStack",{configurable:!1,enumerable:!1,writable:!0,value:X}),Object.defineProperty(r,"_debugTask",{configurable:!1,enumerable:!1,writable:!0,value:Q}),Object.freeze&&(Object.freeze(r.props),Object.freeze(r)),r}function w(r,y,F,h,X,Q){var P=y.children;if(P!==void 0)if(h)if(_(P)){for(h=0;h<P.length;h++)x(P[h]);Object.freeze&&Object.freeze(P)}else console.error("React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead.");else x(P);if(g.call(y,"key")){P=e(r);var U=Object.keys(y).filter(function(ge){return ge!=="key"});h=0<U.length?"{key: someKey, "+U.join(": ..., ")+": ...}":"{key: someKey}",be[P+h]||(U=0<U.length?"{"+U.join(": ..., ")+": ...}":"{}",console.error(`A props object containing a "key" prop is being spread into JSX:
|
|
2
2
|
let props = %s;
|
|
3
3
|
<%s {...props} />
|
|
4
4
|
React keys must be passed directly to JSX without using spread:
|
|
5
5
|
let props = %s;
|
|
6
|
-
<%s key={someKey} {...props} />`,s,u,N,u),te[u+s]=!0)}if(u=null,i!==void 0&&(d(i),u=""+i),R(n)&&(d(n.key),u=""+n.key),"key"in n){i={};for(var J in n)J!=="key"&&(i[J]=n[J])}else i=n;return u&&_(i,typeof e=="function"?e.displayName||e.name||"Unknown":e),T(e,u,i,b(),Y,W)}function w(e){p(e)?e._store&&(e._store.validated=1):typeof e=="object"&&e!==null&&e.$$typeof===S&&(e._payload.status==="fulfilled"?p(e._payload.value)&&e._payload.value._store&&(e._payload.value._store.validated=1):e._store&&(e._store.validated=1))}function p(e){return typeof e=="object"&&e!==null&&e.$$typeof===D}var x=c,D=Symbol.for("react.transitional.element"),B=Symbol.for("react.portal"),F=Symbol.for("react.fragment"),L=Symbol.for("react.strict_mode"),a=Symbol.for("react.profiler"),l=Symbol.for("react.consumer"),m=Symbol.for("react.context"),g=Symbol.for("react.forward_ref"),O=Symbol.for("react.suspense"),r=Symbol.for("react.suspense_list"),M=Symbol.for("react.memo"),S=Symbol.for("react.lazy"),o=Symbol.for("react.activity"),k=Symbol.for("react.client.reference"),z=x.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,Q=Object.prototype.hasOwnProperty,se=Array.isArray,U=console.createTask?console.createTask:function(){return null};x={react_stack_bottom_frame:function(e){return e()}};var Z,K={},$=x.react_stack_bottom_frame.bind(x,y)(),ee=U(j(y)),te={};P.Fragment=F,P.jsx=function(e,n,i){var s=1e4>z.recentlyCreatedOwnerStacks++;return h(e,n,i,!1,s?Error("react-stack-top-frame"):$,s?U(j(e)):ee)},P.jsxs=function(e,n,i){var s=1e4>z.recentlyCreatedOwnerStacks++;return h(e,n,i,!0,s?Error("react-stack-top-frame"):$,s?U(j(e)):ee)}})()),P}var q;function ae(){return q||(q=1,process.env.NODE_ENV==="production"?I.exports=oe():I.exports=ie()),I.exports}var v=ae();const H=({schema:t,dataSource:f})=>{const[d,j]=c.useState(null),[b,y]=c.useState([]),[R,_]=c.useState(null),[V,T]=c.useState(!0),[h,w]=c.useState(null),p=t.customFields&&t.customFields.length>0;c.useEffect(()=>{p&&(_(t.initialData||t.initialValues||{}),T(!1))},[p,t.initialData,t.initialValues]),c.useEffect(()=>{const a=async()=>{try{if(!f)throw new Error("DataSource is required when using ObjectQL schema fetching (inline fields not provided)");const l=await f.getObjectSchema(t.objectName);j(l)}catch(l){console.error("Failed to fetch object schema:",l),w(l)}};p?j({name:t.objectName,fields:{}}):t.objectName&&f&&a()},[t.objectName,f,p]),c.useEffect(()=>{d&&!p&&(async()=>{if(!t.recordId||t.mode==="create"){_(t.initialData||t.initialValues||{}),T(!1);return}if(!p){if(!f){w(new Error("DataSource is required for fetching record data (inline data not provided)")),T(!1);return}T(!0);try{const l=await f.findOne(t.objectName,t.recordId);_(l)}catch(l){console.error("Failed to fetch record:",l),w(l)}finally{T(!1)}}})()},[t.objectName,t.recordId,t.mode,t.initialValues,t.initialData,f,d,p]),c.useEffect(()=>{if(p&&t.customFields){y(t.customFields),T(!1);return}if(!d)return;const a=[],l=t.fields||Object.keys(d.fields||{});(Array.isArray(l)?l:Object.keys(l)).forEach(g=>{const O=typeof g=="string"?g:g.name;if(!O)return;const r=d.fields?.[O];if(!r&&!p)return;const M=!r?.permissions||r?.permissions.write!==!1;if(t.mode!=="view"&&!M)return;const S=t.customFields?.find(o=>o.name===O);if(S)a.push(S);else if(r){const o={name:O,label:r.label||g,type:C.mapFieldTypeToFormType(r.type),required:r.required||!1,disabled:t.readOnly||t.mode==="view"||r.readonly,placeholder:r.placeholder,description:r.help||r.description,validation:C.buildValidationRules(r),field:r};if((r.type==="select"||r.type==="lookup"||r.type==="master_detail")&&(o.options=r.options||[],o.multiple=r.multiple),(r.type==="number"||r.type==="currency"||r.type==="percent")&&(o.inputType="number",o.min=r.min,o.max=r.max,o.step=r.precision?Math.pow(10,-r.precision):void 0),r.type==="date"&&(o.inputType="date"),r.type==="datetime"&&(o.inputType="datetime-local"),(r.type==="text"||r.type==="textarea"||r.type==="markdown"||r.type==="html")&&(o.maxLength=r.max_length,o.minLength=r.min_length),(r.type==="file"||r.type==="image")&&(o.inputType="file",o.multiple=r.multiple,o.accept=r.accept?r.accept.join(","):void 0,r.max_size)){const k=`Max size: ${C.formatFileSize(r.max_size)}`;o.description=o.description?`${o.description} (${k})`:k}r.type==="email"&&(o.inputType="email"),r.type==="phone"&&(o.inputType="tel"),r.type==="url"&&(o.inputType="url"),r.type==="password"&&(o.inputType="password"),r.type==="time"&&(o.inputType="time"),(r.type==="formula"||r.type==="summary"||r.type==="auto_number")&&(o.disabled=!0),r.visible_on&&(o.visible=k=>C.evaluateCondition(r.visible_on,k)),a.push(o)}}),y(a),T(!1)},[d,t.fields,t.customFields,t.readOnly,t.mode,p]);const x=c.useCallback(async(a,l)=>{if(a&&(a.nativeEvent||a._reactName==="onSubmit")&&(console.warn("ObjectForm: Received Event instead of data in handleSubmit! This suggests a Form renderer issue."),l===void 0&&(l=a,a={})),p&&!f)return t.onSuccess&&await t.onSuccess(a),a;if(!f)throw new Error("DataSource is required for form submission (inline mode not configured)");try{let m;if(t.mode==="create")m=await f.create(t.objectName,a);else if(t.mode==="edit"&&t.recordId)m=await f.update(t.objectName,t.recordId,a);else throw new Error("Invalid form mode or missing record ID");return t.onSuccess&&await t.onSuccess(m),m}catch(m){throw console.error("Failed to submit form:",m),t.onError&&t.onError(m),m}},[t,f,p]),D=c.useCallback(()=>{t.onCancel&&t.onCancel()},[t]),F={...c.useMemo(()=>{if(!d?.fields)return{};const a={};return Object.keys(d.fields).forEach(l=>{const m=d.fields[l];m.defaultValue!==void 0&&(a[l]=m.defaultValue)}),a},[d]),...R};if(h)return v.jsxs("div",{className:"p-4 border border-red-300 bg-red-50 rounded-md",children:[v.jsx("h3",{className:"text-red-800 font-semibold",children:"Error loading form"}),v.jsx("p",{className:"text-red-600 text-sm mt-1",children:h.message})]});if(V)return v.jsxs("div",{className:"p-8 text-center",children:[v.jsx("div",{className:"inline-block animate-spin rounded-full h-8 w-8 border-b-2 border-gray-900"}),v.jsx("p",{className:"mt-2 text-sm text-gray-600",children:"Loading form..."})]});const L={type:"form",fields:b,layout:t.layout==="vertical"||t.layout==="horizontal"?t.layout:"vertical",columns:t.columns,submitLabel:t.submitText||(t.mode==="create"?"Create":"Update"),cancelLabel:t.cancelText,showSubmit:t.showSubmit!==!1&&t.mode!=="view",showCancel:t.showCancel!==!1,resetOnSubmit:t.showReset,defaultValues:F,onSubmit:x,onCancel:D,className:t.className};return v.jsx("div",{className:"w-full",children:v.jsx(ne.SchemaRenderer,{schema:L})})},le=({schema:t})=>v.jsx(H,{schema:t});re.ComponentRegistry.register("object-form",le,{namespace:"plugin-form"}),E.ObjectForm=H,Object.defineProperty(E,Symbol.toStringTag,{value:"Module"})}));
|
|
6
|
+
<%s key={someKey} {...props} />`,h,P,U,P),be[P+h]=!0)}if(P=null,F!==void 0&&(c(F),P=""+F),C(y)&&(c(y.key),P=""+y.key),"key"in y){F={};for(var Z in y)Z!=="key"&&(F[Z]=y[Z])}else F=y;return P&&O(F,typeof r=="function"?r.displayName||r.name||"Unknown":r),E(r,P,F,v(),X,Q)}function x(r){N(r)?r._store&&(r._store.validated=1):typeof r=="object"&&r!==null&&r.$$typeof===n&&(r._payload.status==="fulfilled"?N(r._payload.value)&&r._payload.value._store&&(r._payload.value._store.validated=1):r._store&&(r._store.validated=1))}function N(r){return typeof r=="object"&&r!==null&&r.$$typeof===V}var D=o,V=Symbol.for("react.transitional.element"),$=Symbol.for("react.portal"),I=Symbol.for("react.fragment"),k=Symbol.for("react.strict_mode"),M=Symbol.for("react.profiler"),p=Symbol.for("react.consumer"),a=Symbol.for("react.context"),i=Symbol.for("react.forward_ref"),s=Symbol.for("react.suspense"),d=Symbol.for("react.suspense_list"),f=Symbol.for("react.memo"),n=Symbol.for("react.lazy"),S=Symbol.for("react.activity"),W=Symbol.for("react.client.reference"),b=D.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,g=Object.prototype.hasOwnProperty,_=Array.isArray,A=console.createTask?console.createTask:function(){return null};D={react_stack_bottom_frame:function(r){return r()}};var q,fe={},ce=D.react_stack_bottom_frame.bind(D,m)(),pe=A(u(m)),be={};J.Fragment=I,J.jsx=function(r,y,F){var h=1e4>b.recentlyCreatedOwnerStacks++;return w(r,y,F,!1,h?Error("react-stack-top-frame"):ce,h?A(u(r)):pe)},J.jsxs=function(r,y,F){var h=1e4>b.recentlyCreatedOwnerStacks++;return w(r,y,F,!0,h?Error("react-stack-top-frame"):ce,h?A(u(r)):pe)}})()),J}var re;function je(){return re||(re=1,process.env.NODE_ENV==="production"?G.exports=me():G.exports=ye()),G.exports}var t=je();const Y=({label:e,description:l,collapsible:c=!1,collapsed:u=!1,columns:v=1,children:m,className:C})=>{const[O,T]=o.useState(u),E={1:"grid-cols-1",2:"grid-cols-1 md:grid-cols-2",3:"grid-cols-1 md:grid-cols-2 lg:grid-cols-3",4:"grid-cols-1 md:grid-cols-2 lg:grid-cols-4"},w=()=>{c&&T(!O)};return t.jsxs("div",{className:j.cn("form-section",C),children:[(e||l)&&t.jsxs("div",{className:j.cn("flex items-start gap-2 mb-4",c&&"cursor-pointer select-none"),onClick:w,role:c?"button":void 0,"aria-expanded":c?!O:void 0,children:[c&&t.jsx("span",{className:"mt-0.5 text-muted-foreground",children:O?t.jsx(H.ChevronRight,{className:"h-4 w-4"}):t.jsx(H.ChevronDown,{className:"h-4 w-4"})}),t.jsxs("div",{className:"flex-1",children:[e&&t.jsx("h3",{className:"text-base font-semibold text-foreground",children:e}),l&&t.jsx("p",{className:"text-sm text-muted-foreground mt-0.5",children:l})]})]}),!O&&t.jsx("div",{className:j.cn("grid gap-4",E[v]),children:m})]})},le=({schema:e,dataSource:l,className:c})=>{const[u,v]=o.useState(null),[m,C]=o.useState({}),[O,T]=o.useState(!0),[E,w]=o.useState(null),[x,N]=o.useState(e.defaultTab||e.sections[0]?.name||e.sections[0]?.label||"tab-0");o.useEffect(()=>{(async()=>{if(!l){T(!1);return}try{const i=await l.getObjectSchema(e.objectName);v(i)}catch(i){w(i)}})()},[e.objectName,l]),o.useEffect(()=>{(u||!l)&&(async()=>{if(e.mode==="create"||!e.recordId||!l){C(e.initialData||e.initialValues||{}),T(!1);return}try{const i=await l.findOne(e.objectName,e.recordId);C(i||{})}catch(i){w(i)}finally{T(!1)}})()},[u,e.mode,e.recordId,e.initialData,e.initialValues,l,e.objectName]);const D=o.useCallback(a=>{const i=[];for(const s of a.fields){const d=typeof s=="string"?s:s.name;if(typeof s=="object")i.push(s);else if(u?.fields?.[d]){const f=u.fields[d];i.push({name:d,label:f.label||d,type:L.mapFieldTypeToFormType(f.type),required:f.required||!1,disabled:e.readOnly||e.mode==="view"||f.readonly,placeholder:f.placeholder,description:f.help||f.description,validation:L.buildValidationRules(f),field:f,options:f.options,multiple:f.multiple})}else i.push({name:d,label:d,type:"input"})}return i},[u,e.readOnly,e.mode]),V=o.useCallback(async a=>{if(!l)return e.onSuccess&&await e.onSuccess(a),a;try{let i;return e.mode==="create"?i=await l.create(e.objectName,a):e.mode==="edit"&&e.recordId&&(i=await l.update(e.objectName,e.recordId,a)),e.onSuccess&&await e.onSuccess(i),i}catch(i){throw e.onError&&e.onError(i),i}},[e,l]),$=o.useCallback(()=>{e.onCancel&&e.onCancel()},[e]),I=(a,i)=>a.name||a.label||`tab-${i}`;if(E)return t.jsxs("div",{className:"p-4 border border-red-300 bg-red-50 rounded-md",children:[t.jsx("h3",{className:"text-red-800 font-semibold",children:"Error loading form"}),t.jsx("p",{className:"text-red-600 text-sm mt-1",children:E.message})]});if(O)return t.jsxs("div",{className:"p-8 text-center",children:[t.jsx("div",{className:"inline-block animate-spin rounded-full h-8 w-8 border-b-2 border-gray-900"}),t.jsx("p",{className:"mt-2 text-sm text-gray-600",children:"Loading form..."})]});const M={type:"form",fields:e.sections.flatMap(a=>D(a)),layout:"vertical",defaultValues:m,submitLabel:e.submitText||(e.mode==="create"?"Create":"Update"),cancelLabel:e.cancelText,showSubmit:e.showSubmit!==!1&&e.mode!=="view",showCancel:e.showCancel!==!1,onSubmit:V,onCancel:$},p=e.tabPosition==="left"||e.tabPosition==="right";return t.jsx("div",{className:j.cn("w-full",c,e.className),children:t.jsxs(j.Tabs,{value:x,onValueChange:N,orientation:p?"vertical":"horizontal",className:j.cn(p&&"flex gap-4"),children:[t.jsx(j.TabsList,{className:j.cn(p?"flex-col h-auto":"",e.tabPosition==="bottom"&&"order-last",e.tabPosition==="right"&&"order-last"),children:e.sections.map((a,i)=>t.jsx(j.TabsTrigger,{value:I(a,i),className:p?"w-full justify-start":"",children:a.label||`Tab ${i+1}`},I(a,i)))}),t.jsx("div",{className:"flex-1",children:e.sections.map((a,i)=>t.jsx(j.TabsContent,{value:I(a,i),className:"mt-0",children:t.jsx(Y,{description:a.description,columns:a.columns||1,children:t.jsx(R.SchemaRenderer,{schema:{...M,fields:D(a),showSubmit:e.showSubmit!==!1&&e.mode!=="view",showCancel:e.showCancel!==!1}})})},I(a,i)))})]})})},ie=({schema:e,dataSource:l,className:c})=>{const[u,v]=o.useState(null),[m,C]=o.useState({}),[O,T]=o.useState(!0),[E,w]=o.useState(null),[x,N]=o.useState(0),[D,V]=o.useState(new Set),[$,I]=o.useState(!1),k=e.sections.length,M=x===0,p=x===k-1;o.useEffect(()=>{(async()=>{if(!l){T(!1);return}try{const g=await l.getObjectSchema(e.objectName);v(g)}catch(g){w(g)}})()},[e.objectName,l]),o.useEffect(()=>{(u||!l)&&(async()=>{if(e.mode==="create"||!e.recordId||!l){C(e.initialData||e.initialValues||{}),T(!1);return}try{const g=await l.findOne(e.objectName,e.recordId);C(g||{})}catch(g){w(g)}finally{T(!1)}})()},[u,e.mode,e.recordId,e.initialData,e.initialValues,l,e.objectName]);const a=o.useCallback(b=>{const g=[];for(const _ of b.fields){const A=typeof _=="string"?_:_.name;if(typeof _=="object")g.push(_);else if(u?.fields?.[A]){const q=u.fields[A];g.push({name:A,label:q.label||A,type:L.mapFieldTypeToFormType(q.type),required:q.required||!1,disabled:e.readOnly||e.mode==="view"||q.readonly,placeholder:q.placeholder,description:q.help||q.description,validation:L.buildValidationRules(q),field:q,options:q.options,multiple:q.multiple})}else g.push({name:A,label:A,type:"input"})}return g},[u,e.readOnly,e.mode]),i=o.useMemo(()=>x>=0&&x<k?a(e.sections[x]):[],[x,k,e.sections,a]),s=o.useCallback(async b=>{const g={...m,...b};if(C(g),V(_=>new Set(_).add(x)),p){I(!0);try{if(!l)return e.onSuccess&&await e.onSuccess(g),g;let _;return e.mode==="create"?_=await l.create(e.objectName,g):e.mode==="edit"&&e.recordId&&(_=await l.update(e.objectName,e.recordId,g)),e.onSuccess&&await e.onSuccess(_),_}catch(_){throw e.onError&&e.onError(_),_}finally{I(!1)}}else d(x+1)},[m,x,p,e,l]),d=o.useCallback(b=>{b>=0&&b<k&&(N(b),e.onStepChange&&e.onStepChange(b))},[k,e]),f=o.useCallback(()=>{d(x-1)},[x,d]),n=o.useCallback(()=>{e.onCancel&&e.onCancel()},[e]),S=o.useCallback(b=>{(e.allowSkip||D.has(b)||b<=x)&&d(b)},[e.allowSkip,D,x,d]);if(E)return t.jsxs("div",{className:"p-4 border border-red-300 bg-red-50 rounded-md",children:[t.jsx("h3",{className:"text-red-800 font-semibold",children:"Error loading form"}),t.jsx("p",{className:"text-red-600 text-sm mt-1",children:E.message})]});if(O)return t.jsxs("div",{className:"p-8 text-center",children:[t.jsx("div",{className:"inline-block animate-spin rounded-full h-8 w-8 border-b-2 border-gray-900"}),t.jsx("p",{className:"mt-2 text-sm text-gray-600",children:"Loading form..."})]});const W=e.sections[x];return t.jsxs("div",{className:j.cn("w-full",c,e.className),children:[e.showStepIndicator!==!1&&t.jsx("nav",{"aria-label":"Progress",className:"mb-8",children:t.jsx("ol",{className:"flex items-center",children:e.sections.map((b,g)=>{const _=g===x,A=D.has(g),q=e.allowSkip||A||g<=x;return t.jsxs("li",{className:j.cn("relative flex-1",g!==k-1&&"pr-8 sm:pr-12"),children:[g!==k-1&&t.jsx("div",{className:"absolute top-4 left-8 -right-4 sm:left-10 sm:-right-2 h-0.5","aria-hidden":"true",children:t.jsx("div",{className:j.cn("h-full",A?"bg-primary":"bg-muted")})}),t.jsxs("button",{type:"button",className:j.cn("group relative flex items-center",q?"cursor-pointer":"cursor-not-allowed"),onClick:()=>S(g),disabled:!q,children:[t.jsx("span",{className:j.cn("flex h-8 w-8 items-center justify-center rounded-full text-sm font-medium transition-colors",A&&"bg-primary text-primary-foreground",_&&!A&&"border-2 border-primary bg-background text-primary",!_&&!A&&"border-2 border-muted bg-background text-muted-foreground"),children:A?t.jsx(H.Check,{className:"h-4 w-4"}):g+1}),t.jsx("span",{className:"ml-3 text-sm font-medium hidden sm:block",children:t.jsx("span",{className:j.cn(_?"text-foreground":"text-muted-foreground"),children:b.label||`Step ${g+1}`})})]})]},g)})})}),t.jsx("div",{className:"min-h-[200px]",children:W&&t.jsx(Y,{label:W.label,description:W.description,columns:W.columns||1,children:i.length>0?t.jsx(R.SchemaRenderer,{schema:{type:"form",fields:i,layout:"vertical",defaultValues:m,showSubmit:!1,showCancel:!1,onSubmit:s}}):t.jsx("div",{className:"text-center py-8 text-muted-foreground",children:"No fields configured for this step"})})}),t.jsxs("div",{className:"flex items-center justify-between mt-6 pt-4 border-t",children:[t.jsx("div",{children:e.showCancel!==!1&&t.jsx(j.Button,{variant:"ghost",onClick:n,children:e.cancelText||"Cancel"})}),t.jsxs("div",{className:"flex items-center gap-2",children:[t.jsxs("span",{className:"text-sm text-muted-foreground mr-2",children:["Step ",x+1," of ",k]}),!M&&t.jsxs(j.Button,{variant:"outline",onClick:f,children:[t.jsx(H.ChevronLeft,{className:"h-4 w-4 mr-1"}),e.prevText||"Back"]}),p?t.jsx(j.Button,{onClick:()=>s(m),disabled:$||e.mode==="view",children:$?"Submitting...":e.submitText||(e.mode==="create"?"Create":"Update")}):t.jsxs(j.Button,{onClick:()=>s(m),children:[e.nextText||"Next",t.jsx(H.ChevronRight,{className:"h-4 w-4 ml-1"})]})]})]})]})},ne=({schema:e,dataSource:l,className:c})=>{const[u,v]=o.useState(null),[m,C]=o.useState({}),[O,T]=o.useState(!0),[E,w]=o.useState(null);o.useEffect(()=>{(async()=>{if(!l){T(!1);return}try{const i=await l.getObjectSchema(e.objectName);v(i)}catch(i){w(i),T(!1)}})()},[e.objectName,l]),o.useEffect(()=>{(u||!l)&&(async()=>{if(e.mode==="create"||!e.recordId){C(e.initialData||e.initialValues||{}),T(!1);return}if(!l){C(e.initialData||e.initialValues||{}),T(!1);return}try{const i=await l.findOne(e.objectName,e.recordId);C(i||{})}catch(i){w(i)}finally{T(!1)}})()},[u,e.mode,e.recordId,e.initialData,e.initialValues,l,e.objectName]);const x=o.useCallback(a=>{const i=[];for(const s of a.fields){const d=typeof s=="string"?s:s.name;if(typeof s=="object")i.push(s);else if(u?.fields?.[d]){const f=u.fields[d];i.push({name:d,label:f.label||d,type:L.mapFieldTypeToFormType(f.type),required:f.required||!1,disabled:e.readOnly||e.mode==="view"||f.readonly,placeholder:f.placeholder,description:f.help||f.description,validation:L.buildValidationRules(f),field:f,options:f.options,multiple:f.multiple})}else i.push({name:d,label:d,type:"input"})}return i},[u,e.readOnly,e.mode]),N=o.useCallback(async a=>{if(!l)return e.onSuccess&&await e.onSuccess(a),a;try{let i;return e.mode==="create"?i=await l.create(e.objectName,a):e.mode==="edit"&&e.recordId&&(i=await l.update(e.objectName,e.recordId,a)),e.onSuccess&&await e.onSuccess(i),i}catch(i){throw e.onError&&e.onError(i),i}},[e,l]),D=o.useCallback(()=>{e.onCancel&&e.onCancel()},[e]),V=o.useMemo(()=>e.sections.slice(0,1),[e.sections]),$=o.useMemo(()=>e.sections.slice(1),[e.sections]);o.useMemo(()=>e.sections.flatMap(a=>x(a)),[e.sections,x]);const I=e.splitDirection||"horizontal",k=e.splitSize||50;if(E)return t.jsxs("div",{className:"p-4 border border-red-300 bg-red-50 rounded-md",children:[t.jsx("h3",{className:"text-red-800 font-semibold",children:"Error loading form"}),t.jsx("p",{className:"text-red-600 text-sm mt-1",children:E.message})]});if(O)return t.jsxs("div",{className:"p-8 text-center",children:[t.jsx("div",{className:"inline-block animate-spin rounded-full h-8 w-8 border-b-2 border-gray-900"}),t.jsx("p",{className:"mt-2 text-sm text-gray-600",children:"Loading form..."})]});const M={type:"form",layout:"vertical",defaultValues:m,onSubmit:N,onCancel:D},p=(a,i)=>t.jsx("div",{className:"space-y-4 p-4",children:a.map((s,d)=>t.jsx(Y,{label:s.label,description:s.description,columns:s.columns||1,children:t.jsx(R.SchemaRenderer,{schema:{...M,fields:x(s),showSubmit:i&&e.showSubmit!==!1&&e.mode!=="view",showCancel:i&&e.showCancel!==!1,submitLabel:e.submitText||(e.mode==="create"?"Create":"Update"),cancelLabel:e.cancelText}})},s.name||s.label||d))});return t.jsx("div",{className:j.cn("w-full",c,e.className),children:t.jsxs(j.ResizablePanelGroup,{orientation:I,className:"min-h-[300px] rounded-lg border",children:[t.jsx(j.ResizablePanel,{defaultSize:k,minSize:20,children:p(V,$.length===0)}),$.length>0&&t.jsxs(t.Fragment,{children:[t.jsx(j.ResizableHandle,{withHandle:e.splitResizable!==!1}),t.jsx(j.ResizablePanel,{defaultSize:100-k,minSize:20,children:p($,!0)})]})]})})},oe=({schema:e,dataSource:l,className:c})=>{const[u,v]=o.useState(null),[m,C]=o.useState([]),[O,T]=o.useState({}),[E,w]=o.useState(!0),[x,N]=o.useState(null),D=e.open!==!1,V=e.drawerSide||"right";o.useEffect(()=>{(async()=>{if(!l){w(!1);return}try{const d=await l.getObjectSchema(e.objectName);v(d)}catch(d){N(d),w(!1)}})()},[e.objectName,l]),o.useEffect(()=>{(u||!l)&&(async()=>{if(e.mode==="create"||!e.recordId){T(e.initialData||e.initialValues||{}),w(!1);return}if(!l){T(e.initialData||e.initialValues||{}),w(!1);return}try{const d=await l.findOne(e.objectName,e.recordId);T(d||{})}catch(d){N(d)}finally{w(!1)}})()},[u,e.mode,e.recordId,e.initialData,e.initialValues,l,e.objectName]);const $=o.useCallback(s=>{const d=[];for(const f of s.fields){const n=typeof f=="string"?f:f.name;if(typeof f=="object")d.push(f);else if(u?.fields?.[n]){const S=u.fields[n];d.push({name:n,label:S.label||n,type:L.mapFieldTypeToFormType(S.type),required:S.required||!1,disabled:e.readOnly||e.mode==="view"||S.readonly,placeholder:S.placeholder,description:S.help||S.description,validation:L.buildValidationRules(S),field:S,options:S.options,multiple:S.multiple})}else d.push({name:n,label:n,type:"input"})}return d},[u,e.readOnly,e.mode]);o.useEffect(()=>{if(!u&&l)return;if(e.customFields?.length){C(e.customFields),w(!1);return}if(e.sections?.length){w(!1);return}if(!u)return;const s=e.fields||Object.keys(u.fields||{}),d=[];for(const f of s){const n=typeof f=="string"?f:f.name;if(!n)continue;const S=u.fields?.[n];S&&d.push({name:n,label:S.label||n,type:L.mapFieldTypeToFormType(S.type),required:S.required||!1,disabled:e.readOnly||e.mode==="view"||S.readonly,placeholder:S.placeholder,description:S.help||S.description,validation:L.buildValidationRules(S),field:S,options:S.options,multiple:S.multiple})}C(d),w(!1)},[u,e.fields,e.customFields,e.sections,e.readOnly,e.mode,l]);const I=o.useCallback(async s=>{if(!l)return e.onSuccess&&await e.onSuccess(s),e.onOpenChange?.(!1),s;try{let d;return e.mode==="create"?d=await l.create(e.objectName,s):e.mode==="edit"&&e.recordId&&(d=await l.update(e.objectName,e.recordId,s)),e.onSuccess&&await e.onSuccess(d),e.onOpenChange?.(!1),d}catch(d){throw e.onError&&e.onError(d),d}},[e,l]),k=o.useCallback(()=>{e.onCancel&&e.onCancel(),e.onOpenChange?.(!1)},[e]),M=o.useMemo(()=>e.drawerWidth?V==="left"||V==="right"?{width:e.drawerWidth,maxWidth:e.drawerWidth}:{height:e.drawerWidth,maxHeight:e.drawerWidth}:void 0,[e.drawerWidth,V]),a={type:"form",layout:e.layout==="vertical"||e.layout==="horizontal"?e.layout:"vertical",defaultValues:O,submitLabel:e.submitText||(e.mode==="create"?"Create":"Update"),cancelLabel:e.cancelText,showSubmit:e.showSubmit!==!1&&e.mode!=="view",showCancel:e.showCancel!==!1,onSubmit:I,onCancel:k},i=()=>x?t.jsxs("div",{className:"p-4 border border-red-300 bg-red-50 rounded-md",children:[t.jsx("h3",{className:"text-red-800 font-semibold",children:"Error loading form"}),t.jsx("p",{className:"text-red-600 text-sm mt-1",children:x.message})]}):E?t.jsxs("div",{className:"p-8 text-center",children:[t.jsx("div",{className:"inline-block animate-spin rounded-full h-8 w-8 border-b-2 border-gray-900"}),t.jsx("p",{className:"mt-2 text-sm text-gray-600",children:"Loading form..."})]}):e.sections?.length?t.jsx("div",{className:"space-y-6",children:e.sections.map((s,d)=>t.jsx(Y,{label:s.label,description:s.description,columns:s.columns||1,children:t.jsx(R.SchemaRenderer,{schema:{...a,fields:$(s),showSubmit:d===e.sections.length-1&&a.showSubmit,showCancel:d===e.sections.length-1&&a.showCancel}})},s.name||s.label||d))}):t.jsx(R.SchemaRenderer,{schema:{...a,fields:m,columns:e.columns}});return t.jsx(j.Sheet,{open:D,onOpenChange:e.onOpenChange,children:t.jsxs(j.SheetContent,{side:V,className:j.cn("overflow-y-auto",c,e.className),style:M,children:[(e.title||e.description)&&t.jsxs(j.SheetHeader,{children:[e.title&&t.jsx(j.SheetTitle,{children:e.title}),e.description&&t.jsx(j.SheetDescription,{children:e.description})]}),t.jsx("div",{className:"py-4",children:i()})]})})},se={sm:"max-w-sm",default:"max-w-lg",lg:"max-w-2xl",xl:"max-w-4xl",full:"max-w-[95vw] w-full"},ae=({schema:e,dataSource:l,className:c})=>{const[u,v]=o.useState(null),[m,C]=o.useState([]),[O,T]=o.useState({}),[E,w]=o.useState(!0),[x,N]=o.useState(null),D=e.open!==!1,V=se[e.modalSize||"default"]||se.default;o.useEffect(()=>{(async()=>{if(!l){w(!1);return}try{const s=await l.getObjectSchema(e.objectName);v(s)}catch(s){N(s),w(!1)}})()},[e.objectName,l]),o.useEffect(()=>{(u||!l)&&(async()=>{if(e.mode==="create"||!e.recordId){T(e.initialData||e.initialValues||{}),w(!1);return}if(!l){T(e.initialData||e.initialValues||{}),w(!1);return}try{const s=await l.findOne(e.objectName,e.recordId);T(s||{})}catch(s){N(s)}finally{w(!1)}})()},[u,e.mode,e.recordId,e.initialData,e.initialValues,l,e.objectName]);const $=o.useCallback(i=>{const s=[];for(const d of i.fields){const f=typeof d=="string"?d:d.name;if(typeof d=="object")s.push(d);else if(u?.fields?.[f]){const n=u.fields[f];s.push({name:f,label:n.label||f,type:L.mapFieldTypeToFormType(n.type),required:n.required||!1,disabled:e.readOnly||e.mode==="view"||n.readonly,placeholder:n.placeholder,description:n.help||n.description,validation:L.buildValidationRules(n),field:n,options:n.options,multiple:n.multiple})}else s.push({name:f,label:f,type:"input"})}return s},[u,e.readOnly,e.mode]);o.useEffect(()=>{if(!u&&l)return;if(e.customFields?.length){C(e.customFields),w(!1);return}if(e.sections?.length){w(!1);return}if(!u)return;const i=e.fields||Object.keys(u.fields||{}),s=[];for(const d of i){const f=typeof d=="string"?d:d.name;if(!f)continue;const n=u.fields?.[f];n&&s.push({name:f,label:n.label||f,type:L.mapFieldTypeToFormType(n.type),required:n.required||!1,disabled:e.readOnly||e.mode==="view"||n.readonly,placeholder:n.placeholder,description:n.help||n.description,validation:L.buildValidationRules(n),field:n,options:n.options,multiple:n.multiple})}C(s),w(!1)},[u,e.fields,e.customFields,e.sections,e.readOnly,e.mode,l]);const I=o.useCallback(async i=>{if(!l)return e.onSuccess&&await e.onSuccess(i),e.onOpenChange?.(!1),i;try{let s;return e.mode==="create"?s=await l.create(e.objectName,i):e.mode==="edit"&&e.recordId&&(s=await l.update(e.objectName,e.recordId,i)),e.onSuccess&&await e.onSuccess(s),e.onOpenChange?.(!1),s}catch(s){throw e.onError&&e.onError(s),s}},[e,l]),k=o.useCallback(()=>{e.onCancel&&e.onCancel(),e.onOpenChange?.(!1)},[e]),p={type:"form",layout:e.layout==="vertical"||e.layout==="horizontal"?e.layout:"vertical",defaultValues:O,submitLabel:e.submitText||(e.mode==="create"?"Create":"Update"),cancelLabel:e.cancelText,showSubmit:e.showSubmit!==!1&&e.mode!=="view",showCancel:e.showCancel!==!1,onSubmit:I,onCancel:k},a=()=>x?t.jsxs("div",{className:"p-4 border border-red-300 bg-red-50 rounded-md",children:[t.jsx("h3",{className:"text-red-800 font-semibold",children:"Error loading form"}),t.jsx("p",{className:"text-red-600 text-sm mt-1",children:x.message})]}):E?t.jsxs("div",{className:"p-8 text-center",children:[t.jsx("div",{className:"inline-block animate-spin rounded-full h-8 w-8 border-b-2 border-gray-900"}),t.jsx("p",{className:"mt-2 text-sm text-gray-600",children:"Loading form..."})]}):e.sections?.length?t.jsx("div",{className:"space-y-6",children:e.sections.map((i,s)=>t.jsx(Y,{label:i.label,description:i.description,columns:i.columns||1,children:t.jsx(R.SchemaRenderer,{schema:{...p,fields:$(i),showSubmit:s===e.sections.length-1&&p.showSubmit,showCancel:s===e.sections.length-1&&p.showCancel}})},i.name||i.label||s))}):t.jsx(R.SchemaRenderer,{schema:{...p,fields:m,columns:e.columns}});return t.jsx(j.Dialog,{open:D,onOpenChange:e.onOpenChange,children:t.jsxs(j.DialogContent,{className:j.cn(V,"max-h-[90vh] overflow-y-auto",c,e.className),children:[(e.title||e.description)&&t.jsxs(j.DialogHeader,{children:[e.title&&t.jsx(j.DialogTitle,{children:e.title}),e.description&&t.jsx(j.DialogDescription,{children:e.description})]}),t.jsx("div",{className:"py-2",children:a()})]})})},de=({schema:e,dataSource:l})=>{if(e.formType==="tabbed"&&e.sections?.length)return t.jsx(le,{schema:{...e,formType:"tabbed",sections:e.sections.map(c=>({name:c.name,label:c.label,description:c.description,columns:c.columns,fields:c.fields})),defaultTab:e.defaultTab,tabPosition:e.tabPosition},dataSource:l,className:e.className});if(e.formType==="wizard"&&e.sections?.length)return t.jsx(ie,{schema:{...e,formType:"wizard",sections:e.sections.map(c=>({name:c.name,label:c.label,description:c.description,columns:c.columns,fields:c.fields})),allowSkip:e.allowSkip,showStepIndicator:e.showStepIndicator,nextText:e.nextText,prevText:e.prevText,onStepChange:e.onStepChange},dataSource:l,className:e.className});if(e.formType==="split"&&e.sections?.length)return t.jsx(ne,{schema:{...e,formType:"split",sections:e.sections.map(c=>({name:c.name,label:c.label,description:c.description,columns:c.columns,fields:c.fields})),splitDirection:e.splitDirection,splitSize:e.splitSize,splitResizable:e.splitResizable},dataSource:l,className:e.className});if(e.formType==="drawer"){const{layout:c,...u}=e,v=e.layout==="vertical"||e.layout==="horizontal"?e.layout:void 0;return t.jsx(oe,{schema:{...u,layout:v,formType:"drawer",sections:e.sections?.map(m=>({name:m.name,label:m.label,description:m.description,columns:m.columns,fields:m.fields})),open:e.open,onOpenChange:e.onOpenChange,drawerSide:e.drawerSide,drawerWidth:e.drawerWidth},dataSource:l,className:e.className})}if(e.formType==="modal"){const{layout:c,...u}=e,v=e.layout==="vertical"||e.layout==="horizontal"?e.layout:void 0;return t.jsx(ae,{schema:{...u,layout:v,formType:"modal",sections:e.sections?.map(m=>({name:m.name,label:m.label,description:m.description,columns:m.columns,fields:m.fields})),open:e.open,onOpenChange:e.onOpenChange,modalSize:e.modalSize,modalCloseButton:e.modalCloseButton},dataSource:l,className:e.className})}return t.jsx(xe,{schema:e,dataSource:l})},xe=({schema:e,dataSource:l})=>{const[c,u]=o.useState(null),[v,m]=o.useState([]),[C,O]=o.useState(null),[T,E]=o.useState(!0),[w,x]=o.useState(null),N=e.customFields&&e.customFields.length>0;o.useEffect(()=>{N&&(O(e.initialData||e.initialValues||{}),E(!1))},[N,e.initialData,e.initialValues]),o.useEffect(()=>{const p=async()=>{try{if(!l)throw new Error("DataSource is required when using ObjectQL schema fetching (inline fields not provided)");const a=await l.getObjectSchema(e.objectName);if(!a)throw new Error(`No schema found for object "${e.objectName}"`);u(a)}catch(a){x(a),E(!1)}};N?u({name:e.objectName,fields:{}}):e.objectName&&l?p():N||E(!1)},[e.objectName,l,N]),o.useEffect(()=>{c&&!N&&(async()=>{if(!e.recordId||e.mode==="create"){O(e.initialData||e.initialValues||{}),E(!1);return}if(!N){if(!l){x(new Error("DataSource is required for fetching record data (inline data not provided)")),E(!1);return}E(!0);try{const a=await l.findOne(e.objectName,e.recordId);O(a)}catch(a){console.error("Failed to fetch record:",a),x(a)}finally{E(!1)}}})()},[e.objectName,e.recordId,e.mode,e.initialValues,e.initialData,l,c,N]),o.useEffect(()=>{if(N&&e.customFields){m(e.customFields),E(!1);return}if(!c)return;const p=[],a=e.fields||Object.keys(c.fields||{});(Array.isArray(a)?a:Object.keys(a)).forEach(d=>{const f=typeof d=="string"?d:d.name;if(!f)return;const n=c.fields?.[f];if(!n&&!N)return;const S=!n?.permissions||n?.permissions.write!==!1;if(e.mode!=="view"&&!S)return;const W=e.customFields?.find(b=>b.name===f);if(W)p.push(W);else if(n){const b={name:f,label:n.label||d,type:L.mapFieldTypeToFormType(n.type),required:n.required||!1,disabled:e.readOnly||e.mode==="view"||n.readonly,placeholder:n.placeholder,description:n.help||n.description,validation:L.buildValidationRules(n),field:n};if((n.type==="select"||n.type==="lookup"||n.type==="master_detail")&&(b.options=n.options||[],b.multiple=n.multiple),(n.type==="number"||n.type==="currency"||n.type==="percent")&&(b.inputType="number",b.min=n.min,b.max=n.max,b.step=n.precision?Math.pow(10,-n.precision):void 0),n.type==="date"&&(b.inputType="date"),n.type==="datetime"&&(b.inputType="datetime-local"),(n.type==="text"||n.type==="textarea"||n.type==="markdown"||n.type==="html")&&(b.maxLength=n.max_length,b.minLength=n.min_length),(n.type==="file"||n.type==="image")&&(b.inputType="file",b.multiple=n.multiple,b.accept=n.accept?n.accept.join(","):void 0,n.max_size)){const g=`Max size: ${L.formatFileSize(n.max_size)}`;b.description=b.description?`${b.description} (${g})`:g}n.type==="email"&&(b.inputType="email"),n.type==="phone"&&(b.inputType="tel"),n.type==="url"&&(b.inputType="url"),n.type==="password"&&(b.inputType="password"),n.type==="time"&&(b.inputType="time"),(n.type==="formula"||n.type==="summary"||n.type==="auto_number")&&(b.disabled=!0),n.visible_on&&(b.visible=g=>L.evaluateCondition(n.visible_on,g)),p.push(b)}}),m(p),!N&&e.recordId&&e.mode!=="create"&&l||E(!1)},[c,e.fields,e.customFields,e.readOnly,e.mode,N,e.recordId,l]);const D=o.useCallback(async(p,a)=>{if(p&&(p.nativeEvent||p._reactName==="onSubmit")&&(console.warn("ObjectForm: Received Event instead of data in handleSubmit! This suggests a Form renderer issue."),a===void 0&&(a=p,p={})),N&&!l)return e.onSuccess&&await e.onSuccess(p),p;if(!l)throw new Error("DataSource is required for form submission (inline mode not configured)");try{let i;if(e.mode==="create")i=await l.create(e.objectName,p);else if(e.mode==="edit"&&e.recordId)i=await l.update(e.objectName,e.recordId,p);else throw new Error("Invalid form mode or missing record ID");return e.onSuccess&&await e.onSuccess(i),i}catch(i){throw console.error("Failed to submit form:",i),e.onError&&e.onError(i),i}},[e,l,N]),V=o.useCallback(()=>{e.onCancel&&e.onCancel()},[e]),I={...o.useMemo(()=>{if(!c?.fields)return{};const p={};return Object.keys(c.fields).forEach(a=>{const i=c.fields[a];i.defaultValue!==void 0&&(p[a]=i.defaultValue)}),p},[c]),...C};if(w)return t.jsxs("div",{className:"p-4 border border-red-300 bg-red-50 rounded-md",children:[t.jsx("h3",{className:"text-red-800 font-semibold",children:"Error loading form"}),t.jsx("p",{className:"text-red-600 text-sm mt-1",children:w.message})]});if(T)return t.jsxs("div",{className:"p-8 text-center",children:[t.jsx("div",{className:"inline-block animate-spin rounded-full h-8 w-8 border-b-2 border-gray-900"}),t.jsx("p",{className:"mt-2 text-sm text-gray-600",children:"Loading form..."})]});const k=e.layout==="vertical"||e.layout==="horizontal"?e.layout:"vertical";if(e.sections?.length&&(!e.formType||e.formType==="simple"))return t.jsx("div",{className:"w-full space-y-6",children:e.sections.map((p,a)=>{const i=p.fields.map(d=>typeof d=="string"?d:d.name),s=v.filter(d=>i.includes(d.name));return t.jsx(Y,{label:p.label,description:p.description,collapsible:p.collapsible,collapsed:p.collapsed,columns:p.columns,children:t.jsx(R.SchemaRenderer,{schema:{type:"form",fields:s,layout:k,defaultValues:I,showSubmit:a===e.sections.length-1&&e.showSubmit!==!1&&e.mode!=="view",showCancel:a===e.sections.length-1&&e.showCancel!==!1,submitLabel:e.submitText||(e.mode==="create"?"Create":"Update"),cancelLabel:e.cancelText,onSubmit:D,onCancel:V}})},p.name||p.label||a)})});const M={type:"form",fields:v,layout:k,columns:e.columns,submitLabel:e.submitText||(e.mode==="create"?"Create":"Update"),cancelLabel:e.cancelText,showSubmit:e.showSubmit!==!1&&e.mode!=="view",showCancel:e.showCancel!==!1,resetOnSubmit:e.showReset,defaultValues:I,onSubmit:D,onCancel:V,className:e.className};return t.jsx("div",{className:"w-full",children:t.jsx(R.SchemaRenderer,{schema:M})})},ue=({schema:e})=>t.jsx(de,{schema:e});K.ComponentRegistry.register("object-form",ue,{namespace:"plugin-form",label:"Object Form",category:"plugin",inputs:[{name:"objectName",type:"string",label:"Object Name",required:!0},{name:"fields",type:"array",label:"Fields"},{name:"mode",type:"enum",label:"Mode",enum:["create","edit","view"]},{name:"formType",type:"enum",label:"Form Type",enum:["simple","tabbed","wizard","split","drawer","modal"]},{name:"sections",type:"array",label:"Sections"},{name:"title",type:"string",label:"Title"},{name:"description",type:"string",label:"Description"},{name:"layout",type:"enum",label:"Layout",enum:["vertical","horizontal","inline","grid"]},{name:"columns",type:"number",label:"Columns"},{name:"defaultTab",type:"string",label:"Default Tab"},{name:"tabPosition",type:"enum",label:"Tab Position",enum:["top","bottom","left","right"]},{name:"allowSkip",type:"boolean",label:"Allow Skip Steps"},{name:"showStepIndicator",type:"boolean",label:"Show Step Indicator"},{name:"splitDirection",type:"enum",label:"Split Direction",enum:["horizontal","vertical"]},{name:"splitSize",type:"number",label:"Split Panel Size (%)"},{name:"splitResizable",type:"boolean",label:"Split Resizable"},{name:"drawerSide",type:"enum",label:"Drawer Side",enum:["top","bottom","left","right"]},{name:"drawerWidth",type:"string",label:"Drawer Width"},{name:"modalSize",type:"enum",label:"Modal Size",enum:["sm","default","lg","xl","full"]}]}),K.ComponentRegistry.register("form",ue,{namespace:"view",skipFallback:!0,label:"Data Form View",category:"view",inputs:[{name:"objectName",type:"string",label:"Object Name",required:!0},{name:"fields",type:"array",label:"Fields"},{name:"mode",type:"enum",label:"Mode",enum:["create","edit","view"]}]}),z.DrawerForm=oe,z.FormSection=Y,z.ModalForm=ae,z.ObjectForm=de,z.SplitForm=ne,z.TabbedForm=le,z.WizardForm=ie,Object.defineProperty(z,Symbol.toStringTag,{value:"Module"})}));
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
import { FormField, DataSource } from '../../types/src';
|
|
3
|
+
export interface DrawerFormSectionConfig {
|
|
4
|
+
name?: string;
|
|
5
|
+
label?: string;
|
|
6
|
+
description?: string;
|
|
7
|
+
columns?: 1 | 2 | 3 | 4;
|
|
8
|
+
fields: (string | FormField)[];
|
|
9
|
+
}
|
|
10
|
+
export interface DrawerFormSchema {
|
|
11
|
+
type: 'object-form';
|
|
12
|
+
formType: 'drawer';
|
|
13
|
+
objectName: string;
|
|
14
|
+
mode: 'create' | 'edit' | 'view';
|
|
15
|
+
recordId?: string | number;
|
|
16
|
+
title?: string;
|
|
17
|
+
description?: string;
|
|
18
|
+
sections?: DrawerFormSectionConfig[];
|
|
19
|
+
fields?: string[];
|
|
20
|
+
customFields?: FormField[];
|
|
21
|
+
/**
|
|
22
|
+
* Whether the drawer is open.
|
|
23
|
+
* @default true
|
|
24
|
+
*/
|
|
25
|
+
open?: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Callback when open state changes.
|
|
28
|
+
*/
|
|
29
|
+
onOpenChange?: (open: boolean) => void;
|
|
30
|
+
/**
|
|
31
|
+
* Drawer side.
|
|
32
|
+
* @default 'right'
|
|
33
|
+
*/
|
|
34
|
+
drawerSide?: 'top' | 'bottom' | 'left' | 'right';
|
|
35
|
+
/**
|
|
36
|
+
* Drawer width (CSS value for left/right, or height for top/bottom).
|
|
37
|
+
* Applied via className overrides since Sheet uses cva variants.
|
|
38
|
+
* @default undefined (uses Sheet default)
|
|
39
|
+
*/
|
|
40
|
+
drawerWidth?: string;
|
|
41
|
+
showSubmit?: boolean;
|
|
42
|
+
submitText?: string;
|
|
43
|
+
showCancel?: boolean;
|
|
44
|
+
cancelText?: string;
|
|
45
|
+
initialValues?: Record<string, any>;
|
|
46
|
+
initialData?: Record<string, any>;
|
|
47
|
+
readOnly?: boolean;
|
|
48
|
+
layout?: 'vertical' | 'horizontal';
|
|
49
|
+
columns?: number;
|
|
50
|
+
onSuccess?: (data: any) => void | Promise<void>;
|
|
51
|
+
onError?: (error: Error) => void;
|
|
52
|
+
onCancel?: () => void;
|
|
53
|
+
className?: string;
|
|
54
|
+
}
|
|
55
|
+
export interface DrawerFormProps {
|
|
56
|
+
schema: DrawerFormSchema;
|
|
57
|
+
dataSource?: DataSource;
|
|
58
|
+
className?: string;
|
|
59
|
+
}
|
|
60
|
+
export declare const DrawerForm: React.FC<DrawerFormProps>;
|
|
61
|
+
export default DrawerForm;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
export interface FormSectionProps {
|
|
3
|
+
/**
|
|
4
|
+
* Section title/label
|
|
5
|
+
*/
|
|
6
|
+
label?: string;
|
|
7
|
+
/**
|
|
8
|
+
* Section description
|
|
9
|
+
*/
|
|
10
|
+
description?: string;
|
|
11
|
+
/**
|
|
12
|
+
* Whether the section can be collapsed
|
|
13
|
+
* @default false
|
|
14
|
+
*/
|
|
15
|
+
collapsible?: boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Whether the section is initially collapsed
|
|
18
|
+
* @default false
|
|
19
|
+
*/
|
|
20
|
+
collapsed?: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Number of columns for field layout
|
|
23
|
+
* @default 1
|
|
24
|
+
*/
|
|
25
|
+
columns?: 1 | 2 | 3 | 4;
|
|
26
|
+
/**
|
|
27
|
+
* Section children (form fields)
|
|
28
|
+
*/
|
|
29
|
+
children: React.ReactNode;
|
|
30
|
+
/**
|
|
31
|
+
* Additional CSS classes
|
|
32
|
+
*/
|
|
33
|
+
className?: string;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* FormSection Component
|
|
37
|
+
*
|
|
38
|
+
* Groups form fields with optional header, collapsibility, and multi-column layout.
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```tsx
|
|
42
|
+
* <FormSection label="Contact Details" columns={2} collapsible>
|
|
43
|
+
* <FormField name="firstName" />
|
|
44
|
+
* <FormField name="lastName" />
|
|
45
|
+
* </FormSection>
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
export declare const FormSection: React.FC<FormSectionProps>;
|
|
49
|
+
export default FormSection;
|
|
File without changes
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
import { FormField, DataSource } from '../../types/src';
|
|
3
|
+
export interface ModalFormSectionConfig {
|
|
4
|
+
name?: string;
|
|
5
|
+
label?: string;
|
|
6
|
+
description?: string;
|
|
7
|
+
columns?: 1 | 2 | 3 | 4;
|
|
8
|
+
fields: (string | FormField)[];
|
|
9
|
+
}
|
|
10
|
+
export interface ModalFormSchema {
|
|
11
|
+
type: 'object-form';
|
|
12
|
+
formType: 'modal';
|
|
13
|
+
objectName: string;
|
|
14
|
+
mode: 'create' | 'edit' | 'view';
|
|
15
|
+
recordId?: string | number;
|
|
16
|
+
title?: string;
|
|
17
|
+
description?: string;
|
|
18
|
+
sections?: ModalFormSectionConfig[];
|
|
19
|
+
fields?: string[];
|
|
20
|
+
customFields?: FormField[];
|
|
21
|
+
/**
|
|
22
|
+
* Whether the modal is open.
|
|
23
|
+
* @default true
|
|
24
|
+
*/
|
|
25
|
+
open?: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Callback when open state changes.
|
|
28
|
+
*/
|
|
29
|
+
onOpenChange?: (open: boolean) => void;
|
|
30
|
+
/**
|
|
31
|
+
* Modal dialog size.
|
|
32
|
+
* @default 'default'
|
|
33
|
+
*/
|
|
34
|
+
modalSize?: 'sm' | 'default' | 'lg' | 'xl' | 'full';
|
|
35
|
+
/**
|
|
36
|
+
* Whether to show a close button in the header.
|
|
37
|
+
* @default true
|
|
38
|
+
*/
|
|
39
|
+
modalCloseButton?: boolean;
|
|
40
|
+
showSubmit?: boolean;
|
|
41
|
+
submitText?: string;
|
|
42
|
+
showCancel?: boolean;
|
|
43
|
+
cancelText?: string;
|
|
44
|
+
initialValues?: Record<string, any>;
|
|
45
|
+
initialData?: Record<string, any>;
|
|
46
|
+
readOnly?: boolean;
|
|
47
|
+
layout?: 'vertical' | 'horizontal';
|
|
48
|
+
columns?: number;
|
|
49
|
+
onSuccess?: (data: any) => void | Promise<void>;
|
|
50
|
+
onError?: (error: Error) => void;
|
|
51
|
+
onCancel?: () => void;
|
|
52
|
+
className?: string;
|
|
53
|
+
}
|
|
54
|
+
export interface ModalFormProps {
|
|
55
|
+
schema: ModalFormSchema;
|
|
56
|
+
dataSource?: DataSource;
|
|
57
|
+
className?: string;
|
|
58
|
+
}
|
|
59
|
+
export declare const ModalForm: React.FC<ModalFormProps>;
|
|
60
|
+
export default ModalForm;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
import { FormField, DataSource } from '../../types/src';
|
|
3
|
+
export interface SplitFormSectionConfig {
|
|
4
|
+
name?: string;
|
|
5
|
+
label?: string;
|
|
6
|
+
description?: string;
|
|
7
|
+
columns?: 1 | 2 | 3 | 4;
|
|
8
|
+
fields: (string | FormField)[];
|
|
9
|
+
}
|
|
10
|
+
export interface SplitFormSchema {
|
|
11
|
+
type: 'object-form';
|
|
12
|
+
formType: 'split';
|
|
13
|
+
objectName: string;
|
|
14
|
+
mode: 'create' | 'edit' | 'view';
|
|
15
|
+
recordId?: string | number;
|
|
16
|
+
sections: SplitFormSectionConfig[];
|
|
17
|
+
/**
|
|
18
|
+
* Split direction.
|
|
19
|
+
* @default 'horizontal'
|
|
20
|
+
*/
|
|
21
|
+
splitDirection?: 'horizontal' | 'vertical';
|
|
22
|
+
/**
|
|
23
|
+
* Size of the first panel (percentage 1-99).
|
|
24
|
+
* @default 50
|
|
25
|
+
*/
|
|
26
|
+
splitSize?: number;
|
|
27
|
+
/**
|
|
28
|
+
* Whether panels can be resized.
|
|
29
|
+
* @default true
|
|
30
|
+
*/
|
|
31
|
+
splitResizable?: boolean;
|
|
32
|
+
showSubmit?: boolean;
|
|
33
|
+
submitText?: string;
|
|
34
|
+
showCancel?: boolean;
|
|
35
|
+
cancelText?: string;
|
|
36
|
+
initialValues?: Record<string, any>;
|
|
37
|
+
initialData?: Record<string, any>;
|
|
38
|
+
readOnly?: boolean;
|
|
39
|
+
onSuccess?: (data: any) => void | Promise<void>;
|
|
40
|
+
onError?: (error: Error) => void;
|
|
41
|
+
onCancel?: () => void;
|
|
42
|
+
className?: string;
|
|
43
|
+
}
|
|
44
|
+
export interface SplitFormProps {
|
|
45
|
+
schema: SplitFormSchema;
|
|
46
|
+
dataSource?: DataSource;
|
|
47
|
+
className?: string;
|
|
48
|
+
}
|
|
49
|
+
export declare const SplitForm: React.FC<SplitFormProps>;
|
|
50
|
+
export default SplitForm;
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
import { FormField, DataSource } from '../../types/src';
|
|
3
|
+
export interface FormSectionConfig {
|
|
4
|
+
/**
|
|
5
|
+
* Section identifier (used as tab value)
|
|
6
|
+
*/
|
|
7
|
+
name?: string;
|
|
8
|
+
/**
|
|
9
|
+
* Section label (used as tab trigger text)
|
|
10
|
+
*/
|
|
11
|
+
label?: string;
|
|
12
|
+
/**
|
|
13
|
+
* Section description
|
|
14
|
+
*/
|
|
15
|
+
description?: string;
|
|
16
|
+
/**
|
|
17
|
+
* Number of columns in the section
|
|
18
|
+
* @default 1
|
|
19
|
+
*/
|
|
20
|
+
columns?: 1 | 2 | 3 | 4;
|
|
21
|
+
/**
|
|
22
|
+
* Field names or configurations in this section
|
|
23
|
+
*/
|
|
24
|
+
fields: (string | FormField)[];
|
|
25
|
+
}
|
|
26
|
+
export interface TabbedFormSchema {
|
|
27
|
+
type: 'object-form';
|
|
28
|
+
formType: 'tabbed';
|
|
29
|
+
/**
|
|
30
|
+
* Object name for ObjectQL schema lookup
|
|
31
|
+
*/
|
|
32
|
+
objectName: string;
|
|
33
|
+
/**
|
|
34
|
+
* Form mode
|
|
35
|
+
*/
|
|
36
|
+
mode: 'create' | 'edit' | 'view';
|
|
37
|
+
/**
|
|
38
|
+
* Record ID (for edit/view modes)
|
|
39
|
+
*/
|
|
40
|
+
recordId?: string | number;
|
|
41
|
+
/**
|
|
42
|
+
* Tab sections configuration
|
|
43
|
+
*/
|
|
44
|
+
sections: FormSectionConfig[];
|
|
45
|
+
/**
|
|
46
|
+
* Default active tab (section name)
|
|
47
|
+
*/
|
|
48
|
+
defaultTab?: string;
|
|
49
|
+
/**
|
|
50
|
+
* Tab position
|
|
51
|
+
* @default 'top'
|
|
52
|
+
*/
|
|
53
|
+
tabPosition?: 'top' | 'bottom' | 'left' | 'right';
|
|
54
|
+
/**
|
|
55
|
+
* Show submit button
|
|
56
|
+
* @default true
|
|
57
|
+
*/
|
|
58
|
+
showSubmit?: boolean;
|
|
59
|
+
/**
|
|
60
|
+
* Submit button text
|
|
61
|
+
*/
|
|
62
|
+
submitText?: string;
|
|
63
|
+
/**
|
|
64
|
+
* Show cancel button
|
|
65
|
+
* @default true
|
|
66
|
+
*/
|
|
67
|
+
showCancel?: boolean;
|
|
68
|
+
/**
|
|
69
|
+
* Cancel button text
|
|
70
|
+
*/
|
|
71
|
+
cancelText?: string;
|
|
72
|
+
/**
|
|
73
|
+
* Initial values
|
|
74
|
+
*/
|
|
75
|
+
initialValues?: Record<string, any>;
|
|
76
|
+
/**
|
|
77
|
+
* Initial data (alias for initialValues)
|
|
78
|
+
*/
|
|
79
|
+
initialData?: Record<string, any>;
|
|
80
|
+
/**
|
|
81
|
+
* Read-only mode
|
|
82
|
+
*/
|
|
83
|
+
readOnly?: boolean;
|
|
84
|
+
/**
|
|
85
|
+
* Callbacks
|
|
86
|
+
*/
|
|
87
|
+
onSuccess?: (data: any) => void | Promise<void>;
|
|
88
|
+
onError?: (error: Error) => void;
|
|
89
|
+
onCancel?: () => void;
|
|
90
|
+
/**
|
|
91
|
+
* CSS class
|
|
92
|
+
*/
|
|
93
|
+
className?: string;
|
|
94
|
+
}
|
|
95
|
+
export interface TabbedFormProps {
|
|
96
|
+
schema: TabbedFormSchema;
|
|
97
|
+
dataSource?: DataSource;
|
|
98
|
+
className?: string;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* TabbedForm Component
|
|
102
|
+
*
|
|
103
|
+
* Renders a form with sections organized as tabs.
|
|
104
|
+
*
|
|
105
|
+
* @example
|
|
106
|
+
* ```tsx
|
|
107
|
+
* <TabbedForm
|
|
108
|
+
* schema={{
|
|
109
|
+
* type: 'object-form',
|
|
110
|
+
* formType: 'tabbed',
|
|
111
|
+
* objectName: 'contacts',
|
|
112
|
+
* mode: 'create',
|
|
113
|
+
* sections: [
|
|
114
|
+
* { label: 'Basic Info', fields: ['firstName', 'lastName', 'email'] },
|
|
115
|
+
* { label: 'Address', fields: ['street', 'city', 'country'] },
|
|
116
|
+
* ]
|
|
117
|
+
* }}
|
|
118
|
+
* dataSource={dataSource}
|
|
119
|
+
* />
|
|
120
|
+
* ```
|
|
121
|
+
*/
|
|
122
|
+
export declare const TabbedForm: React.FC<TabbedFormProps>;
|
|
123
|
+
export default TabbedForm;
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
import { DataSource } from '../../types/src';
|
|
3
|
+
import { FormSectionConfig } from './TabbedForm';
|
|
4
|
+
export interface WizardFormSchema {
|
|
5
|
+
type: 'object-form';
|
|
6
|
+
formType: 'wizard';
|
|
7
|
+
/**
|
|
8
|
+
* Object name for ObjectQL schema lookup
|
|
9
|
+
*/
|
|
10
|
+
objectName: string;
|
|
11
|
+
/**
|
|
12
|
+
* Form mode
|
|
13
|
+
*/
|
|
14
|
+
mode: 'create' | 'edit' | 'view';
|
|
15
|
+
/**
|
|
16
|
+
* Record ID (for edit/view modes)
|
|
17
|
+
*/
|
|
18
|
+
recordId?: string | number;
|
|
19
|
+
/**
|
|
20
|
+
* Wizard step sections
|
|
21
|
+
*/
|
|
22
|
+
sections: FormSectionConfig[];
|
|
23
|
+
/**
|
|
24
|
+
* Allow navigation to any step (not just sequential)
|
|
25
|
+
* @default false
|
|
26
|
+
*/
|
|
27
|
+
allowSkip?: boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Show step indicators
|
|
30
|
+
* @default true
|
|
31
|
+
*/
|
|
32
|
+
showStepIndicator?: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Text for Next button
|
|
35
|
+
* @default 'Next'
|
|
36
|
+
*/
|
|
37
|
+
nextText?: string;
|
|
38
|
+
/**
|
|
39
|
+
* Text for Previous button
|
|
40
|
+
* @default 'Back'
|
|
41
|
+
*/
|
|
42
|
+
prevText?: string;
|
|
43
|
+
/**
|
|
44
|
+
* Submit button text (shown on last step)
|
|
45
|
+
*/
|
|
46
|
+
submitText?: string;
|
|
47
|
+
/**
|
|
48
|
+
* Show cancel button
|
|
49
|
+
* @default true
|
|
50
|
+
*/
|
|
51
|
+
showCancel?: boolean;
|
|
52
|
+
/**
|
|
53
|
+
* Cancel button text
|
|
54
|
+
*/
|
|
55
|
+
cancelText?: string;
|
|
56
|
+
/**
|
|
57
|
+
* Initial values
|
|
58
|
+
*/
|
|
59
|
+
initialValues?: Record<string, any>;
|
|
60
|
+
/**
|
|
61
|
+
* Initial data (alias)
|
|
62
|
+
*/
|
|
63
|
+
initialData?: Record<string, any>;
|
|
64
|
+
/**
|
|
65
|
+
* Read-only mode
|
|
66
|
+
*/
|
|
67
|
+
readOnly?: boolean;
|
|
68
|
+
/**
|
|
69
|
+
* Callbacks
|
|
70
|
+
*/
|
|
71
|
+
onSuccess?: (data: any) => void | Promise<void>;
|
|
72
|
+
onError?: (error: Error) => void;
|
|
73
|
+
onCancel?: () => void;
|
|
74
|
+
/**
|
|
75
|
+
* Called when step changes
|
|
76
|
+
*/
|
|
77
|
+
onStepChange?: (step: number) => void;
|
|
78
|
+
/**
|
|
79
|
+
* CSS class
|
|
80
|
+
*/
|
|
81
|
+
className?: string;
|
|
82
|
+
}
|
|
83
|
+
export interface WizardFormProps {
|
|
84
|
+
schema: WizardFormSchema;
|
|
85
|
+
dataSource?: DataSource;
|
|
86
|
+
className?: string;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* WizardForm Component
|
|
90
|
+
*
|
|
91
|
+
* Renders a multi-step wizard form with step indicators and navigation.
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* ```tsx
|
|
95
|
+
* <WizardForm
|
|
96
|
+
* schema={{
|
|
97
|
+
* type: 'object-form',
|
|
98
|
+
* formType: 'wizard',
|
|
99
|
+
* objectName: 'users',
|
|
100
|
+
* mode: 'create',
|
|
101
|
+
* sections: [
|
|
102
|
+
* { label: 'Step 1: Personal', fields: ['firstName', 'lastName'] },
|
|
103
|
+
* { label: 'Step 2: Contact', fields: ['email', 'phone'] },
|
|
104
|
+
* { label: 'Step 3: Review', fields: [] },
|
|
105
|
+
* ]
|
|
106
|
+
* }}
|
|
107
|
+
* dataSource={dataSource}
|
|
108
|
+
* />
|
|
109
|
+
* ```
|
|
110
|
+
*/
|
|
111
|
+
export declare const WizardForm: React.FC<WizardFormProps>;
|
|
112
|
+
export default WizardForm;
|
|
@@ -1,3 +1,15 @@
|
|
|
1
1
|
import { ObjectForm } from './ObjectForm';
|
|
2
2
|
export { ObjectForm };
|
|
3
3
|
export type { ObjectFormProps } from './ObjectForm';
|
|
4
|
+
export { FormSection } from './FormSection';
|
|
5
|
+
export type { FormSectionProps } from './FormSection';
|
|
6
|
+
export { TabbedForm } from './TabbedForm';
|
|
7
|
+
export type { TabbedFormProps, TabbedFormSchema, FormSectionConfig } from './TabbedForm';
|
|
8
|
+
export { WizardForm } from './WizardForm';
|
|
9
|
+
export type { WizardFormProps, WizardFormSchema } from './WizardForm';
|
|
10
|
+
export { SplitForm } from './SplitForm';
|
|
11
|
+
export type { SplitFormProps, SplitFormSchema } from './SplitForm';
|
|
12
|
+
export { DrawerForm } from './DrawerForm';
|
|
13
|
+
export type { DrawerFormProps, DrawerFormSchema } from './DrawerForm';
|
|
14
|
+
export { ModalForm } from './ModalForm';
|
|
15
|
+
export type { ModalFormProps, ModalFormSchema } from './ModalForm';
|