@trungkhai/dynamic-form 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs.js CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const m=require("react/jsx-runtime"),w=require("antd"),l=require("react"),z=require("dayjs"),_e=require("@ant-design/icons"),X=l.createContext(null);function P(){const e=l.useContext(X);if(!e)throw new Error("useDynamicFormContext must be used within DynamicFormProvider");return e}function Ne(){return l.useContext(X)}function ve(e,t=[]){for(const i of t){if(typeof i=="function")continue;const{match:a,render:s}=i;if(typeof a=="string"){if(a===e.field?.type?.code||a===e.code)return s}else if(a(e))return s}const n=e.field?.type?.code;for(const i of t);}function ge(e,t=[],n={}){return ve(e,t)??n[e.code]??n[e.field?.type?.code??""]}function we(e,t){const n=t.option_config?.label_attr,i=t.option_config?.value_attr||"value";let a;if(n?.length){const s=n.join(" - ");e[s]!==void 0?a=String(e[s]):a=n.map(r=>e[r]).filter(r=>r!=null&&r!=="").join(" - ")}else a=String(e[i]??"");return{label:a,value:e[i]}}function Se(e,t){return t.option_config&&t.is_option_api?e?.map(n=>we(n,t)):t.metas?.map(n=>({label:n.label,value:n.value}))}function H(e,t){let n;return(...i)=>{n&&clearTimeout(n),n=setTimeout(()=>e(...i),t)}}const Ye=({onSearchKeyword:e,searchDebounceMs:t=500,...n})=>{const[i,a]=l.useState(""),s=l.useMemo(()=>H(o=>e?.(o),t),[e,t]),r=o=>{a(o),s(o)};return m.jsx(w.Select,{allowClear:!0,showSearch:!0,searchValue:i,onSearch:r,filterOption:!1,...n})},Je=l.memo(Ye),Qe=({fieldName:e,formInstance:t,...n})=>{const i=w.Form.useWatch(e,t);l.useEffect(()=>{if(i?.fileList?.length&&i.fileList.some(r=>!r.type?.startsWith("image/"))){const r=i.fileList.filter(o=>o.type?.startsWith("image/"));t.setFieldValue(e,r?.length?{file:r[0]?.originFileObj,fileList:r}:null)}},[e,t,i]);const a=m.jsx("button",{style:{border:0,background:"none",cursor:"pointer"},type:"button",children:m.jsx(_e.FileImageOutlined,{})});return m.jsx(w.Upload,{listType:"picture-card",accept:"image/*",...n,children:a})},Xe=l.memo(Qe),Ze=({fieldName:e,formInstance:t,...n})=>{const i=w.Form.useWatch(e,t);return m.jsx(w.Upload,{fileList:i?.fileList,...n,children:m.jsx(w.Button,{icon:m.jsx(_e.UploadOutlined,{})})})},et=l.memo(Ze),Fe=({formInstance:e,uploadUrl:t,setFieldState:n})=>{const{client:i,upload:a,i18n:s,renderers:r}=P(),{messages:o}=s,u=l.useCallback(()=>{if(a.upload)return a.upload;const c=t??a.uploadUrl;if(c)return async({file:h,signal:p,onProgress:y,fieldCode:x,fieldGroup:g,metadata:S})=>{const f=a.getPayload?a.getPayload({file:h,fieldCode:x,fieldGroup:g,uploadUrl:c,signal:p,onProgress:y,metadata:S}):(()=>{const v=new FormData;return v.append("file",h),S&&Object.entries(S).forEach(([A,R])=>{v.append(A,String(R))}),v})(),F=(await i.request({method:"POST",url:c,data:f,headers:f instanceof FormData?{"Content-Type":"multipart/form-data"}:void 0,signal:p,onUploadProgress:v=>{y?.(Math.round(v.loaded*100/(v.total||1)))}})).data;return{uid:h.uid,...F,path:String(F.path??"")}}},[i,a,t]),d=l.useCallback((c,h)=>p=>{const{file:y,onProgress:x,onError:g,onSuccess:S}=p,f=new AbortController,j=u();return j?(j({file:y,fieldCode:c,fieldGroup:h,uploadUrl:t??a.uploadUrl,signal:f.signal,onProgress:F=>x?.({percent:F})}).then(F=>S?.({...F,uid:F.uid??y.uid,path:F.path,upload_date:z().format("YYYY-MM-DD HH:mm:ss")})).catch(F=>g?.(F)),{abort:()=>f.abort()}):(g?.(new Error(o.uploadError??"Upload not configured")),{abort(){}})},[o.uploadError,u,a.uploadUrl,t]),b=l.useCallback((c,h)=>async p=>{const y=p.response?.path;return y?a.remove({path:y,fieldCode:c,fieldGroup:h}):!0},[a]),_=l.useCallback((c,{state:h,options:p,optionsLoading:y,optionsError:x,onSearchKeyword:g,readOnly:S=!1})=>{const{additional_config:f,field:j}=c,F=j?.type?.code,v=S||c.is_readonly||h?.disabled,A=ge(c,r.fields);if(A)return A(c,{state:h,options:p,optionsLoading:y,optionsError:x,onSearchKeyword:g,readOnly:S,formInstance:e,disabled:!!v,setFieldState:n});const R=Se(p,c);switch(F){case"text":return f?.text?.textarea?m.jsx(w.Input.TextArea,{disabled:v,placeholder:o.inputPlaceholder(c.label),rows:f?.text?.rows}):m.jsx(w.Input,{disabled:v,placeholder:o.inputPlaceholder(c.label)});case"number":return m.jsx(w.InputNumber,{style:{width:"100%"},disabled:v,placeholder:o.inputPlaceholder(c.label),min:f?.number?.min,max:f?.number?.max});case"select":{const M={disabled:v,options:R,placeholder:o.selectPlaceholder(c.label),allowClear:!0,loading:y,mode:f?.select?.multiple?"multiple":void 0,notFoundContent:x?o.optionError:y?o.optionLoading:void 0};return g?m.jsx(Je,{...M,onSearchKeyword:g,searchDebounceMs:f?.select?.searchDebounceMs??500}):m.jsx(w.Select,{...M,showSearch:!0,optionFilterProp:"label"})}case"radio":return m.jsx(w.Radio.Group,{disabled:v,options:R});case"checkbox":return m.jsx(w.Checkbox.Group,{disabled:v,options:R});case"datetime":return m.jsx(w.DatePicker,{style:{width:"100%"},disabled:v,showTime:f?.datetime?.showTime,format:f?.datetime?.format});case"file":return m.jsx(et,{disabled:v,fieldName:c.code,formInstance:e,multiple:f?.file?.multiple||!1,maxCount:f?.file?.max,accept:f?.file?.accept,customRequest:d(c.code,c),onRemove:b(c.code,c)});case"image":return m.jsx(Xe,{disabled:v,fieldName:c.code,formInstance:e,multiple:f?.image?.multiple||!1,maxCount:f?.image?.max,accept:f?.image?.accept??"image/*",customRequest:d(c.code,c),onRemove:b(c.code,c)});default:return null}},[d,b,e,o,r.fields,n]);return l.useMemo(()=>({getDynamicField:_}),[_])};function N(e){return JSON.stringify(e)}function xe(e,t){const n=e.get(t);if(n){if(Date.now()>n.expiresAt){e.delete(t);return}return n.data}}function je(e,t,n,i){e.set(t,{data:n,expiresAt:Date.now()+i})}async function Z(e,t,n,i,a){const s=e[t];if(e.cache.enabled){const d=xe(s,n);if(d!==void 0)return d}const r=new AbortController,o=a?AbortSignal.any([a,r.signal]):r.signal,u=await i(o);return e.cache.enabled&&je(s,n,u,e.cache.ttlMs),u}function T(e,t){return t.split(".").reduce((n,i)=>{if(n&&typeof n=="object")return n[i]},e)}function tt(e,t){if(typeof e!="string")return e;const n=e.match(/^\{\{(.+?)\}\}$/);if(!n)return e;const i=n[1].trim(),a=T(t,i);return a!==void 0?a:e}function Ae(e,t){const n={};for(const i in e)n[i]=tt(e[i],t);return n}function nt(e,t){const n={...e};return t.forEach(i=>{const a=e[i.code];if(a==null)return;switch(i.field?.type?.code){case"datetime":{const r=z(a);r.isValid()&&(n[i.code]=r);break}case"file":case"image":{if(Array.isArray(a)&&a.length>0){const r=a.map((o,u)=>{const d=o;return{uid:String(d.uid??d.path??u),name:d.name??`file-${u}`,status:"done",percent:100,type:d.type,size:d.size,response:o}});n[i.code]={fileList:r}}break}}}),n}function Ce(e){const t=e.option_config?.api_options?.params||{},n=e.option_config?.api_options?.data||{},i=a=>Object.values(a).filter(s=>typeof s=="string"&&s.startsWith("{{")&&s.endsWith("}}")).map(s=>s.slice(2,-2).trim());return Array.from(new Set([...i(t),...i(n)]))}function E(e,t){const n={};for(const i in e){const a=e[i];if(typeof a=="string"&&a.startsWith("{{")&&a.endsWith("}}")){const s=a.slice(2,-2).trim();n[i]=t?.[s]}else n[i]=a}return n}function Re(e,t){return e.replace(/\{\{\s*(\w+)\s*\}\}/g,(n,i)=>{const a=t?.[i];return a!=null?String(a):""})}function De(e,t){const n=l.useMemo(()=>Ce(e),[e]),i=w.Form.useWatch(n.length>0?n:void 0,t);return l.useMemo(()=>{if(!n.length)return{};const a={};return n.forEach((s,r)=>{Array.isArray(i)?a[s]=i[r]:a[s]=i}),a},[n,i])}function Me({group:e,formInstance:t,searchKeyword:n="",searchDebounceMs:i=500}){const a=P(),s=De(e,t),[r,o]=l.useState(),[u,d]=l.useState(!1),[b,_]=l.useState(),c=l.useRef(null),[h,p]=l.useState(n),y=e.additional_config?.select?.search_keyword??!1,x=l.useMemo(()=>H(f=>p(f),i),[i]);l.useEffect(()=>{y?x(n):p("")},[n,y,x]);const g=l.useMemo(()=>{const f=e.option_config?.api_options?.params,j=e.option_config?.api_options?.data;if(!(!f&&!j))return{params:f?E(f,s):void 0,data:j?E(j,s):void 0}},[s,e]),S=l.useCallback(async()=>{if(!e.option_config||!e.is_option_api||!e.option_config.url)return;c.current?.abort();const f=new AbortController;c.current=f;const j=e.option_config.method?.toUpperCase()==="GET"||!e.option_config.method,F=y?h:"",v=N([e.code,e.option_config.url,e.option_config.method,g,F]);d(!0),_(void 0);try{const A=await Z(a,"optionCache",v,async R=>{const M=await a.client.request({method:e.option_config?.method||"GET",url:e.option_config?.url,params:j&&y?{...g?.params,keywords:F}:g?.params,data:!j&&y?{...g?.data,keywords:F}:g?.data,signal:R});return a.parsers.optionResponse(M.data,e)},f.signal);f.signal.aborted||o(A)}catch(A){f.signal.aborted||_(A)}finally{f.signal.aborted||d(!1)}},[g,a,h,e,y]);return l.useEffect(()=>(e.option_config&&e.is_option_api&&S(),()=>c.current?.abort()),[S,e]),{options:r,isLoading:u,error:b,refetch:S}}const it=({group:e,formInstance:t,fieldState:n,setFieldState:i,uploadUrl:a,readOnly:s=!1,size:r="middle",...o})=>{const{getDynamicField:u}=Fe({formInstance:t,uploadUrl:a,setFieldState:i}),d=w.Form.useWatch(e.code,t),[b,_]=l.useState(""),c=e.additional_config?.select?.search_keyword??!1,{options:h,isLoading:p,error:y}=Me({group:e,formInstance:t,searchKeyword:b,searchDebounceMs:e.additional_config?.select?.searchDebounceMs??500}),x=l.useCallback(S=>{_(S)},[]);l.useEffect(()=>{if(e.additional_config?.on_field_change?.clear?.length){const S=t.getFieldsValue(e.additional_config.on_field_change.clear),f=e.additional_config.on_field_change.clear.filter(j=>S?.[j]);f.length&&t.resetFields(f)}e.additional_config?.on_field_empty?.disable?.length&&e.additional_config.on_field_empty.disable.forEach(S=>{i(S,{disabled:!d})})},[d,t,e,i]);const g=r==="small"?4:12;return m.jsx(w.Form.Item,{label:e.label,name:e.code,hidden:n?.hidden,rules:[{required:n?.required||!1}],style:{marginBottom:g,...o.style},...o,children:u(e,{state:n,options:h,optionsLoading:p,optionsError:y,onSearchKeyword:c?x:void 0,readOnly:s})})};function at(e,t){return e.group.id===t.group.id&&e.readOnly===t.readOnly&&e.uploadUrl===t.uploadUrl&&e.size===t.size&&e.fieldState?.disabled===t.fieldState?.disabled&&e.fieldState?.hidden===t.fieldState?.hidden&&e.fieldState?.required===t.fieldState?.required}const ke=l.memo(it,at);function Ee({fieldGroups:e,fieldStates:t,renderField:n,gutter:i,defaultColSpan:a}){return m.jsx(w.Row,{gutter:i,children:e.map(s=>{const r=t[s.code]?.hidden?0:Number(s.additional_config?.field_col_span)||a;return m.jsx(w.Col,{xs:r,children:n(s)},s.id)})})}function Ve(e){return l.useMemo(()=>{const t=e?.form?.field_groups??[],n=new Map,i={};t.forEach(s=>{n.set(s.code,s),s.additional_config?.default!==void 0&&(i[s.code]=s.additional_config.default)});const a=t.filter(s=>!s.is_hidden);return{fieldGroups:t,fieldByCode:n,visibleFieldGroups:a,initialValues:i}},[e])}function ye(e){const t={};return e.forEach(n=>{t[n.code]={disabled:n.is_readonly,hidden:n.is_hidden,required:n.is_required}}),t}function Pe(e){const[t,n]=l.useState(()=>ye(e));l.useEffect(()=>{n(ye(e))},[e]);const i=l.useCallback((a,s)=>{n(r=>({...r,[a]:{...r[a],...s}}))},[]);return{fieldStates:t,setFieldStates:n,setFieldState:i}}function Te({formInstance:e,fieldByCode:t,relatedData:n,transformers:i}){return{buildProcessedValues:l.useCallback(async()=>{await e.validateFields();const s=e.getFieldsValue(),r={};for(const d of Object.keys(s)){const b=t.get(d);if(!b)continue;let _;switch(b.field?.type?.code){case"datetime":_=s[d]?z(s[d]).format(b.additional_config?.datetime?.format):null;break;case"image":case"file":s[d]?.fileList?.length&&(_=s[d].fileList.filter(c=>c.percent===100).map(c=>({...c.response,name:c.name,type:c.type,size:c.size})));break;default:_=s[d]}i.transformFieldValue&&(_=i.transformFieldValue(d,_,b)),r[d]=_}let o=r;return i.transformSubmitValues&&(o=i.transformSubmitValues(o,Array.from(t.values()),n)),(i.parseRelatedDataTemplates??Ae)(o,n??{})},[t,e,n,i])}}const Oe=l.forwardRef(({formConfig:e,formInstance:t,relatedData:n,uploadUrl:i,uploadResourceUrl:a,submitTrackingUrl:s,onBeforeSubmit:r,onSubmitSuccess:o,onSubmitError:u,isRedirectAfterCreate:d,onRedirect:b,size:_="middle",manualSubmit:c=!1,onValuesChange:h,readOnly:p=!1,submitDebounceMs:y,gutter:x=[8,0],defaultColSpan:g=12,submitButtonLabel:S},f)=>{const{message:j}=w.App.useApp(),F=P(),{i18n:v,client:A,parsers:R,redirectHandler:M,renderers:q,transformers:I}=F,oe=i??a,re=y??F.submitDebounceMs,le=S??v.messages.submit,{fieldGroups:k,fieldByCode:$e,initialValues:U}=Ve(e),{fieldStates:G,setFieldState:ce}=Pe(k),{buildProcessedValues:W}=Te({formInstance:t,fieldByCode:$e,relatedData:n,transformers:I}),B=l.useRef(!1),[de,ue]=l.useState(!1),[me,fe]=l.useState(!1);l.useEffect(()=>{if(Object.keys(U).length>0){const C=I.normalizeInitialValues?I.normalizeInitialValues(U,k):U;t.setFieldsValue(C)}},[k,t,U,I]);const K=l.useCallback(async()=>{if(!B.current){B.current=!0,ue(!0);try{let C=await W();try{s&&(fe(!0),await A.request({method:"POST",url:s,data:C}));const D=await r?.(C);if(D===!1)return;D&&typeof D=="object"&&(C=D)}catch(D){console.error(D);return}finally{fe(!1)}const O=await A.request({method:e.method,url:e.action,data:C});t.resetFields(k.filter(D=>!D.is_hidden).map(D=>D.code));const Y=R.submitResponse(O.data);d&&Y.redirectUrl&&(b??M)(Y.redirectUrl,"_blank"),o?.({values:C,response:O.data,data:Y.data??O.data})}catch(C){const O=C;j.error(O?.response?.data?.message??v.messages.submitError),u?.(C)}finally{B.current=!1,ue(!1)}}},[W,A,k,e.action,e.method,t,v.messages.submitError,d,j,r,b,u,o,R,M,s]);l.useImperativeHandle(f,()=>({submit:K,getProcessedValues:W,isSubmitting:()=>B.current}),[W,K]);const pe=l.useMemo(()=>H(()=>{K()},re),[K,re]),he=l.useCallback(C=>m.jsx(ke,{group:C,formInstance:t,fieldState:G[C.code],setFieldState:ce,uploadUrl:oe,readOnly:p,size:_},C.id),[G,t,p,oe,ce,_]),ze=q.layout?q.layout({fieldGroups:k,fieldStates:G,renderField:he,gutter:x,defaultColSpan:g,size:_}):m.jsx(Ee,{fieldGroups:k,fieldStates:G,renderField:he,gutter:x,defaultColSpan:g,size:_}),He=!c&&!p&&(q.submitActions?q.submitActions({onSubmit:pe,loading:de||me,label:le}):m.jsx(w.Flex,{justify:"flex-end",children:m.jsx(w.Button,{type:"primary",onClick:pe,loading:de||me,children:le})}));return m.jsxs(w.Form,{layout:"vertical",form:t,size:_,onValuesChange:h,children:[ze,He]})});Oe.displayName="DynamicForm";function ee(e){if(!e)return;const{mode:t}=e;if(t==="api"&&e.api?.url)return e.api;if(t==="api_ids"&&e.api_ids?.url){const n=e.api_ids,i=n.method?.toUpperCase()==="POST";return{url:n.url,method:n.method,data_path:n.data_path,mapping_attr:n.mapping_attr,link:n.link,result_type:n.result_type??"array",params:n.params??(!i&&!n.data?{ids:"{{value}}"}:void 0),data:n.data??(i&&!n.params?{ids:"{{value}}"}:void 0)}}if(t==="api_detail"&&e.api_detail?.url){const n=e.api_detail;return{url:n.url,method:n.method,data_path:n.data_path,mapping_attr:n.mapping_attr,link:n.link,result_type:n.result_type??"object",url_template:n.url_template??!0,params:n.params,data:n.data}}}function be(e){return{value:e,id:e}}function Le(e,t){const n=t.method||"GET",i=n.toUpperCase()==="GET";if(t.url_template)return(Array.isArray(e)?e.filter(u=>u!=null&&u!==""):e!=null&&e!==""?[e]:[]).map(u=>{const d=be(u),b=Re(t.url,d),_=t.params?E(t.params,d):void 0,c=t.data?E(t.data,d):void 0;return{method:n,url:b,params:i?_:void 0,data:i?void 0:c}});const a=be(e),s=t.params?E(t.params,a):void 0,r=t.data?E(t.data,a):void 0;return[{method:n,url:t.url,params:i?s:void 0,data:i?void 0:r}]}function te(e,t){const n=t.data_path?T(e,t.data_path):e;return(t.result_type??(Array.isArray(n)?"array":"object"))==="array"?Array.isArray(n)?n:n!=null?[n]:[]:Array.isArray(n)?n.length?[n[0]]:[]:n&&typeof n=="object"?[n]:[]}function ne(e,t){return dt(e,t.mapping_attr)}function ie(e,t){return ut(t.link,e)}async function qe(e,t,n,i){const a=Le(e,t);if(!a.length)return[];const s=await Promise.all(a.map(o=>n({...o,signal:i}))),r=[];for(const o of s)r.push(...te(o.data,t));return r}function V(e){return!!(e==null||e===""||Array.isArray(e)&&e.length===0)}function Ie(e,t){const n=e.option_config?.api_options?.params,i=e.option_config?.api_options?.data;if(!n&&!i)return;const a=s=>{const r={};for(const o in s)if(typeof s[o]=="string"&&s[o].startsWith("{{")&&s[o].endsWith("}}")){const u=s[o].slice(2,-2).trim();r[o]=t?.[u]}else r[o]=s[o];return r};return{params:n?a(n):void 0,data:i?a(i):void 0}}function st(e,t){const n=t.option_config?.label_attr,i=t.option_config?.value_attr||"";if(n?.length){const a=n.join(" - ");return e[a]!==void 0?String(e[a]):n.map(s=>e[s]).filter(s=>s!=null&&s!=="").join(" - ")}return String(e[i]??"")}function ot(e,t){if(!t?.length)return null;const i=(Array.isArray(e)?e:[e]).map(a=>t.find(s=>String(s.value)===String(a))?.label).filter(a=>!!a);return i.length?i.join(", "):null}function rt(e,t,n){if(V(e))return null;const i=t.option_config?.value_attr||"value",a=Array.isArray(e)?e:[e];if(t.is_option_api&&n?.length){const r=a.map(o=>{const u=n.find(d=>String(d[i])===String(o));return u?st(u,t):String(o)}).filter(Boolean);return r.length?r.join(", "):null}const s=ot(e,t.metas);return s||a.map(String).join(", ")}function lt(e,t){if(V(e))return null;const n=t.additional_config?.datetime?.format,i=z(e);return i.isValid()?n?i.format(n):i.format("YYYY-MM-DD HH:mm:ss"):String(e)}function ct(e){if(V(e))return null;if(Array.isArray(e)){const t=e.map(n=>typeof n=="object"&&n&&"name"in n?String(n.name):String(n)).filter(Boolean);return t.length?t.join(", "):null}return String(e)}function dt(e,t){return t?.length?t.map(n=>{const i=T(e,n)??e[n];return i!=null?String(i):""}).filter(Boolean).join(" - "):JSON.stringify(e)}function ut(e,t){return e?e.replace(/\{\{(.+?)\}\}/g,(n,i)=>{const a=i.trim(),s=T(t,a)??t[a];return s!=null?String(s):""}):null}function Q(e,t,n){if(V(e))return null;switch(t?.mode??"formatted"){case"raw":case"formatted":return Array.isArray(e)?e.map(String).join(", "):String(e);case"api":case"api_ids":case"api_detail":{const a=ee(t);if(!n||!a)return Array.isArray(e)?e.map(String).join(", "):String(e);const s=te(n,a);return s.length?s.map(o=>{const u=ne(o,a),d=ie(o,a);return d?`${u} (${d})`:u}).filter(Boolean).join(", ")||null:String(e)}default:return String(e)}}function Ue(e,t,n){const i=e.additional_config?.view_value;if(i?.mode==="api"||i?.mode==="api_ids"||i?.mode==="api_detail")return Q(t,i,n.viewValueFetched);switch(e.field?.type?.code){case"text":case"number":return V(t)?null:String(t);case"datetime":return lt(t,e);case"select":case"radio":case"checkbox":return rt(t,e,n.optionList);case"image":case"file":return ct(t);default:return i?Q(t,i,n.viewValueFetched):V(t)?null:String(t)}}function ae(e,t,n=!0){const i=P(),[a,s]=l.useState(),[r,o]=l.useState(!1),[u,d]=l.useState(),b=l.useRef(null),_=l.useCallback(async()=>{if(!n)return;b.current?.abort();const c=new AbortController;b.current=c;const h=N(e);o(!0),d(void 0);try{const p=await Z(i,"viewCache",h,t,c.signal);return c.signal.aborted||s(p),p}catch(p){throw c.signal.aborted||d(p),p}finally{c.signal.aborted||o(!1)}},[e,i,n,t]);return l.useEffect(()=>(n&&_(),()=>b.current?.abort()),[n,_]),{data:a,isLoading:r,error:u,refetch:_}}const mt=({value:e,code:t,modeConfig:n,viewConfig:i})=>{const{client:a,renderers:s,i18n:r}=P(),o=n??(i?ee(i):void 0),{data:u,isLoading:d,error:b}=ae(["api_view",t,e,o?.url,o?.method,o?.data_path],async h=>o?qe(e,o,p=>a.request(p),h):[],!!(e&&o?.url)),_=(h,p,y)=>s.link?s.link({url:h,label:p,data:y}):m.jsx("a",{href:h,target:"_blank",rel:"noreferrer",children:p}),c=(h,p)=>{if(!o)return null;const y=ne(h,o),x=ie(h,o),g=x?_(x,y,h):y;return m.jsx("div",{children:g},h.id??p)};return d?m.jsx(m.Fragment,{children:s.viewLoading?.()??m.jsx(w.Spin,{size:"small"})}):b?m.jsx(m.Fragment,{children:s.viewError?.(b)??r.messages.viewError}):u?.length?o?.result_type==="object"&&u.length===1?c(u[0],0):m.jsx(w.Flex,{vertical:!0,children:u.map(c)}):m.jsx(m.Fragment,{children:s.viewEmpty?.()??r.messages.viewEmpty})},L=l.memo(mt);function ft(e){return!!(e.option_config&&e.is_option_api)}function pt(e){return e==="api"||e==="api_ids"||e==="api_detail"}function ht(e,t){const n=P(),i=N(["viewModeOptions",e.map(s=>s.code),t]),{data:a}=ae([i],async s=>{const r={};return await Promise.all(e.map(async o=>{if(!o.option_config?.url)return;const u=Ie(o,t),d=o.option_config.method?.toUpperCase()==="GET"||!o.option_config.method,b=await n.client.request({method:o.option_config.method||"GET",url:o.option_config.url,params:d?u?.params:void 0,data:d?void 0:u?.data,signal:s});r[o.code]={optionList:n.parsers.optionResponse(b.data,o)}})),r},e.length>0);return a??{}}const yt=({formConfig:e,formValues:t})=>{const n=e?.form?.field_groups??[],i=l.useMemo(()=>n.filter(ft),[n]),a=ht(i,t);return l.useMemo(()=>n.filter(r=>!r.is_hidden).map(r=>{const o=t?.[r.code],u=r.additional_config?.view_value,d=u?.mode;if(pt(d)&&u)return{key:r.code,label:r.label,rawValue:o,viewValue:m.jsx(L,{code:r.code,value:o,viewConfig:u}),field_group:r};const b=a[r.code]??{};return{key:r.code,label:r.label,rawValue:o,viewValue:Ue(r,o,b),field_group:r}}),[a,n,t])},bt=({code:e,value:t,fieldGroup:n})=>{const i=n?.additional_config?.view_value;switch(i?.mode){case"raw":return t;case"api":case"api_ids":case"api_detail":return m.jsx(L,{code:e,value:t,viewConfig:i});default:return t}},_t=l.memo(bt),vt=({value:e,code:t,modeConfig:n})=>m.jsx(L,{code:t,value:e,viewConfig:n?{mode:"api_ids",api_ids:n}:void 0}),gt=l.memo(vt),wt=({value:e,code:t,modeConfig:n})=>m.jsx(L,{code:t,value:e,viewConfig:n?{mode:"api_detail",api_detail:n}:void 0}),St=l.memo(wt),se={submit:"Save",submitError:"Failed to submit form",inputPlaceholder:e=>`Enter ${e}`,selectPlaceholder:e=>`Select ${e}`,optionLoading:"Loading...",optionError:"Failed to load options",uploadError:"Upload failed",viewLoading:"Loading...",viewEmpty:"-",viewError:"Failed to load"},Ft={messages:se},Ge=e=>{if(Array.isArray(e))return e;if(e&&typeof e=="object"&&"items"in e&&Array.isArray(e.items))return e.items;if(e&&typeof e=="object"&&"data"in e&&e.data&&typeof e.data=="object"&&"items"in(e.data??{})){const t=e.data;return Array.isArray(t.items)?t.items:[]}return[]},We=e=>({redirectUrl:e?.redirect_after_create,data:e}),Be=(e,t)=>t?.dataPath?T(e,t.dataPath):e,$={optionResponse:Ge,submitResponse:We,viewResponse:Be},Ke=(e,t="_blank")=>{window.open(e,t)},J={upload:async()=>{throw new Error("Upload adapter is not configured")},remove:async()=>!1};function xt({children:e,client:t,upload:n,i18n:i,parsers:a,renderers:s={},transformers:r={},cache:o,submitDebounceMs:u=200,redirectHandler:d,requestClient:b,uploadAdapter:_,deleteUploadAdapter:c,messages:h,optionResponseParser:p,customFieldRenderers:y}){const x=l.useRef(new Map),g=l.useRef(new Map),S=l.useMemo(()=>{const f=t??{request:b??(()=>{throw new Error("DynamicFormProvider requires client or requestClient")})},j=y?Object.entries(y).map(([A,R])=>({match:A,render:R})):[],F={...se,...i?.messages,...h},v={...J,...n,upload:n?.upload??_??J.upload,remove:n?.remove??(c?A=>c(A.path):J.remove)};return{client:f,upload:v,i18n:{messages:F},parsers:{optionResponse:a?.optionResponse??p??$.optionResponse,submitResponse:a?.submitResponse??$.submitResponse,viewResponse:a?.viewResponse??$.viewResponse},renderers:{...s,fields:[...s.fields??[],...j]},transformers:r,cache:{enabled:o?.enabled??!0,ttlMs:o?.ttlMs??6e4},submitDebounceMs:u,redirectHandler:d??Ke,optionCache:x.current,viewCache:g.current}},[t,b,n,_,c,i?.messages,h,a?.optionResponse,a?.submitResponse,a?.viewResponse,p,s,y,r,o?.enabled,o?.ttlMs,u,d]);return m.jsx(X.Provider,{value:S,children:e})}function jt(e){return{request:async t=>({data:(await e({method:t.method,url:t.url,params:t.params,data:t.data,signal:t.signal,headers:t.headers,onUploadProgress:t.onUploadProgress})).data})}}exports.ApiDetailItem=St;exports.ApiItem=gt;exports.ApiViewItem=L;exports.DefaultLayout=Ee;exports.DynamicForm=Oe;exports.DynamicFormProvider=xt;exports.FormItem=ke;exports.MetaItemValue=_t;exports.buildApiViewRequests=Le;exports.buildCacheKey=N;exports.cachedRequest=Z;exports.createAxiosDynamicFormClient=jt;exports.debounce=H;exports.defaultI18n=Ft;exports.defaultMessages=se;exports.defaultOptionResponseParser=Ge;exports.defaultParsers=$;exports.defaultRedirectHandler=Ke;exports.defaultSubmitResponseParser=We;exports.defaultViewResponseParser=Be;exports.extractDependencyFields=Ce;exports.extractViewData=te;exports.fetchApiViewItems=qe;exports.fillTemplate=Re;exports.getByPath=T;exports.getCached=xe;exports.getMappedLabel=ne;exports.getMappedLink=ie;exports.isEmptyValue=V;exports.mapOptionToSelectItem=we;exports.mapOptions=Se;exports.normalizeApiViewConfig=ee;exports.normalizeMetaForForm=nt;exports.parseFormValues=Ae;exports.replaceTemplateInObject=E;exports.resolveApiOptionMeta=Ie;exports.resolveFieldRenderer=ve;exports.resolveFieldRendererFromMap=ge;exports.resolveFieldViewValue=Ue;exports.resolveViewValueConfig=Q;exports.setCache=je;exports.useCachedViewRequest=ae;exports.useDependencyValues=De;exports.useDynamicField=Fe;exports.useDynamicFormContext=P;exports.useDynamicFormContextOptional=Ne;exports.useDynamicOptions=Me;exports.useFieldGroups=Ve;exports.useFieldStates=Pe;exports.useProcessedValues=Te;exports.useViewMode=yt;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const m=require("react/jsx-runtime"),F=require("antd"),c=require("react"),N=require("dayjs"),ge=require("@ant-design/icons"),ne=c.createContext(null);function k(){const e=c.useContext(ne);if(!e)throw new Error("useDynamicFormContext must be used within DynamicFormProvider");return e}function Je(){return c.useContext(ne)}function Se(e,t=[]){for(const i of t){if(typeof i=="function")continue;const{match:r,render:a}=i;if(typeof r=="string"){if(r===e.field?.type?.code||r===e.code)return a}else if(r(e))return a}const n=e.field?.type?.code;for(const i of t);}function Fe(e,t=[],n={}){return Se(e,t)??n[e.code]??n[e.field?.type?.code??""]}function xe(e,t){const n=t.option_config?.label_attr,i=t.option_config?.value_attr||"value";let r;if(n?.length){const a=n.join(" - ");e[a]!==void 0?r=String(e[a]):r=n.map(o=>e[o]).filter(o=>o!=null&&o!=="").join(" - ")}else r=String(e[i]??"");return{label:r,value:e[i]}}function je(e,t){return t.option_config&&t.is_option_api?e?.map(n=>xe(n,t)):t.metas?.map(n=>({label:n.label,value:n.value}))}function Y(e,t){let n;return(...i)=>{n&&clearTimeout(n),n=setTimeout(()=>e(...i),t)}}const Qe=({onSearchKeyword:e,searchDebounceMs:t=500,...n})=>{const[i,r]=c.useState(""),a=c.useMemo(()=>Y(s=>e?.(s),t),[e,t]),o=s=>{r(s),a(s)};return m.jsx(F.Select,{allowClear:!0,showSearch:!0,searchValue:i,onSearch:o,filterOption:!1,...n})},Xe=c.memo(Qe),Ze=({fieldName:e,formInstance:t,...n})=>{const i=F.Form.useWatch(e,t);c.useEffect(()=>{if(i?.fileList?.length&&i.fileList.some(o=>!o.type?.startsWith("image/"))){const o=i.fileList.filter(s=>s.type?.startsWith("image/"));t.setFieldValue(e,o?.length?{file:o[0]?.originFileObj,fileList:o}:null)}},[e,t,i]);const r=m.jsx("button",{style:{border:0,background:"none",cursor:"pointer"},type:"button",children:m.jsx(ge.FileImageOutlined,{})});return m.jsx(F.Upload,{listType:"picture-card",accept:"image/*",...n,children:r})},et=c.memo(Ze),tt=({fieldName:e,formInstance:t,...n})=>{const i=F.Form.useWatch(e,t);return m.jsx(F.Upload,{fileList:i?.fileList,...n,children:m.jsx(F.Button,{icon:m.jsx(ge.UploadOutlined,{})})})},nt=c.memo(tt),Ae=({formInstance:e,uploadUrl:t,setFieldState:n})=>{const{client:i,upload:r,i18n:a,renderers:o}=k(),{messages:s}=a,f=c.useCallback(()=>{if(r.upload)return r.upload;const l=t??r.uploadUrl;if(l)return async({file:_,signal:h,onProgress:u,fieldCode:w,fieldGroup:v,metadata:g})=>{const p=r.getPayload?r.getPayload({file:_,fieldCode:w,fieldGroup:v,uploadUrl:l,signal:h,onProgress:u,metadata:g}):(()=>{const S=new FormData;return S.append("file",_),g&&Object.entries(g).forEach(([A,M])=>{S.append(A,String(M))}),S})(),x=(await i.request({method:"POST",url:l,data:p,headers:p instanceof FormData?{"Content-Type":"multipart/form-data"}:void 0,signal:h,onUploadProgress:S=>{u?.(Math.round(S.loaded*100/(S.total||1)))}})).data;return{uid:_.uid,...x,path:String(x.path??"")}}},[i,r,t]),d=c.useCallback((l,_)=>h=>{const{file:u,onProgress:w,onError:v,onSuccess:g}=h,p=new AbortController,j=f();return j?(j({file:u,fieldCode:l,fieldGroup:_,uploadUrl:t??r.uploadUrl,signal:p.signal,onProgress:x=>w?.({percent:x})}).then(x=>g?.({...x,uid:x.uid??u.uid,path:x.path,upload_date:N().format("YYYY-MM-DD HH:mm:ss")})).catch(x=>v?.(x)),{abort:()=>p.abort()}):(v?.(new Error(s.uploadError??"Upload not configured")),{abort(){}})},[s.uploadError,f,r.uploadUrl,t]),y=c.useCallback((l,_)=>async h=>{const u=h.response?.path;return u?r.remove({path:u,fieldCode:l,fieldGroup:_}):!0},[r]),b=c.useCallback((l,{state:_,options:h,optionsLoading:u,optionsError:w,onSearchKeyword:v,readOnly:g=!1})=>{const{additional_config:p,field:j}=l,x=j?.type?.code,S=g||l.is_readonly||_?.disabled,A=Fe(l,o.fields);if(A)return A(l,{state:_,options:h,optionsLoading:u,optionsError:w,onSearchKeyword:v,readOnly:g,formInstance:e,disabled:!!S,setFieldState:n});const M=je(h,l);switch(x){case"text":return p?.text?.textarea?m.jsx(F.Input.TextArea,{disabled:S,placeholder:s.inputPlaceholder(l.label),rows:p?.text?.rows}):m.jsx(F.Input,{disabled:S,placeholder:s.inputPlaceholder(l.label)});case"number":return m.jsx(F.InputNumber,{style:{width:"100%"},disabled:S,placeholder:s.inputPlaceholder(l.label),min:p?.number?.min,max:p?.number?.max});case"select":{const D={disabled:S,options:M,placeholder:s.selectPlaceholder(l.label),allowClear:!0,loading:u,mode:p?.select?.multiple?"multiple":void 0,notFoundContent:w?s.optionError:u?s.optionLoading:void 0};return v?m.jsx(Xe,{...D,onSearchKeyword:v,searchDebounceMs:p?.select?.searchDebounceMs??500}):m.jsx(F.Select,{...D,showSearch:!0,optionFilterProp:"label"})}case"radio":return m.jsx(F.Radio.Group,{disabled:S,options:M});case"checkbox":return m.jsx(F.Checkbox.Group,{disabled:S,options:M});case"datetime":return m.jsx(F.DatePicker,{style:{width:"100%"},disabled:S,showTime:p?.datetime?.showTime,format:p?.datetime?.format});case"file":return m.jsx(nt,{disabled:S,fieldName:l.code,formInstance:e,multiple:p?.file?.multiple||!1,maxCount:p?.file?.max,accept:p?.file?.accept,customRequest:d(l.code,l),onRemove:y(l.code,l)});case"image":return m.jsx(et,{disabled:S,fieldName:l.code,formInstance:e,multiple:p?.image?.multiple||!1,maxCount:p?.image?.max,accept:p?.image?.accept??"image/*",customRequest:d(l.code,l),onRemove:y(l.code,l)});default:return null}},[d,y,e,s,o.fields,n]);return c.useMemo(()=>({getDynamicField:b}),[b])};function J(e){return JSON.stringify(e)}function Re(e,t){const n=e.get(t);if(n){if(Date.now()>n.expiresAt){e.delete(t);return}return n.data}}function Me(e,t,n,i){e.set(t,{data:n,expiresAt:Date.now()+i})}async function z(e,t,n,i,r){const a=e[t];if(e.cache.enabled){const d=Re(a,n);if(d!==void 0)return d}const o=new AbortController,s=r?AbortSignal.any([r,o.signal]):o.signal,f=await i(s);return e.cache.enabled&&Me(a,n,f,e.cache.ttlMs),f}function T(e,t){return t.split(".").reduce((n,i)=>{if(n&&typeof n=="object")return n[i]},e)}function it(e,t){if(typeof e!="string")return e;const n=e.match(/^\{\{(.+?)\}\}$/);if(!n)return e;const i=n[1].trim(),r=T(t,i);return r!==void 0?r:e}function Ce(e,t){const n={};for(const i in e)n[i]=it(e[i],t);return n}function rt(e,t){const n={...e};return t.forEach(i=>{const r=e[i.code];if(r==null)return;switch(i.field?.type?.code){case"datetime":{const o=N(r);o.isValid()&&(n[i.code]=o);break}case"file":case"image":{if(Array.isArray(r)&&r.length>0){const o=r.map((s,f)=>{const d=s;return{uid:String(d.uid??d.path??f),name:d.name??`file-${f}`,status:"done",percent:100,type:d.type,size:d.size,response:s}});n[i.code]={fileList:o}}break}}}),n}function ke(e){const t=e.option_config?.api_options?.params||{},n=e.option_config?.api_options?.data||{},i=r=>Object.values(r).filter(a=>typeof a=="string"&&a.startsWith("{{")&&a.endsWith("}}")).map(a=>a.slice(2,-2).trim());return Array.from(new Set([...i(t),...i(n)]))}function P(e,t){const n={};for(const i in e){const r=e[i];if(typeof r=="string"&&r.startsWith("{{")&&r.endsWith("}}")){const a=r.slice(2,-2).trim();n[i]=t?.[a]}else n[i]=r}return n}function H(e,t){return e.replace(/\{\{\s*(\w+)\s*\}\}/g,(n,i)=>{const r=t?.[i];return r!=null?String(r):""})}function De(e,t){const n=c.useMemo(()=>ke(e),[e]),i=F.Form.useWatch(n.length>0?n:void 0,t);return c.useMemo(()=>{if(!n.length)return{};const r={};return n.forEach((a,o)=>{Array.isArray(i)?r[a]=i[o]:r[a]=i}),r},[n,i])}function Ee({group:e,formInstance:t,searchKeyword:n="",searchDebounceMs:i=500}){const r=k(),a=De(e,t),[o,s]=c.useState(),[f,d]=c.useState(!1),[y,b]=c.useState(),l=c.useRef(null),[_,h]=c.useState(n),u=e.additional_config?.select?.search_keyword??!1,w=c.useMemo(()=>Y(p=>h(p),i),[i]);c.useEffect(()=>{u?w(n):h("")},[n,u,w]);const v=c.useMemo(()=>{const p=e.option_config?.api_options?.params,j=e.option_config?.api_options?.data;if(!(!p&&!j))return{params:p?P(p,a):void 0,data:j?P(j,a):void 0}},[a,e]),g=c.useCallback(async()=>{if(!e.option_config||!e.is_option_api||!e.option_config.url)return;l.current?.abort();const p=new AbortController;l.current=p;const j=e.option_config.method?.toUpperCase()==="GET"||!e.option_config.method,x=u?_:"",S=J([e.code,e.option_config.url,e.option_config.method,v,x]);d(!0),b(void 0);try{const A=await z(r,"optionCache",S,async M=>{const D=await r.client.request({method:e.option_config?.method||"GET",url:e.option_config?.url,params:j&&u?{...v?.params,keywords:x}:v?.params,data:!j&&u?{...v?.data,keywords:x}:v?.data,signal:M});return r.parsers.optionResponse(D.data,e)},p.signal);p.signal.aborted||s(A)}catch(A){p.signal.aborted||b(A)}finally{p.signal.aborted||d(!1)}},[v,r,_,e,u]);return c.useEffect(()=>(e.option_config&&e.is_option_api&&g(),()=>l.current?.abort()),[g,e]),{options:o,isLoading:f,error:y,refetch:g}}const at=({group:e,formInstance:t,fieldState:n,setFieldState:i,uploadUrl:r,readOnly:a=!1,size:o="middle",...s})=>{const{getDynamicField:f}=Ae({formInstance:t,uploadUrl:r,setFieldState:i}),d=F.Form.useWatch(e.code,t),[y,b]=c.useState(""),l=e.additional_config?.select?.search_keyword??!1,{options:_,isLoading:h,error:u}=Ee({group:e,formInstance:t,searchKeyword:y,searchDebounceMs:e.additional_config?.select?.searchDebounceMs??500}),w=c.useCallback(g=>{b(g)},[]);c.useEffect(()=>{if(e.additional_config?.on_field_change?.clear?.length){const g=t.getFieldsValue(e.additional_config.on_field_change.clear),p=e.additional_config.on_field_change.clear.filter(j=>g?.[j]);p.length&&t.resetFields(p)}e.additional_config?.on_field_empty?.disable?.length&&e.additional_config.on_field_empty.disable.forEach(g=>{i(g,{disabled:!d})})},[d,t,e,i]);const v=o==="small"?4:12;return m.jsx(F.Form.Item,{label:e.label,name:e.code,hidden:n?.hidden,rules:[{required:n?.required||!1}],style:{marginBottom:v,...s.style},...s,children:f(e,{state:n,options:_,optionsLoading:h,optionsError:u,onSearchKeyword:l?w:void 0,readOnly:a})})};function st(e,t){return e.group.id===t.group.id&&e.readOnly===t.readOnly&&e.uploadUrl===t.uploadUrl&&e.size===t.size&&e.fieldState?.disabled===t.fieldState?.disabled&&e.fieldState?.hidden===t.fieldState?.hidden&&e.fieldState?.required===t.fieldState?.required}const Pe=c.memo(at,st);function Ve({fieldGroups:e,fieldStates:t,renderField:n,gutter:i,defaultColSpan:r}){return m.jsx(F.Row,{gutter:i,children:e.map(a=>{const o=t[a.code]?.hidden?0:Number(a.additional_config?.field_col_span)||r;return m.jsx(F.Col,{xs:o,children:n(a)},a.id)})})}function Te(e){return c.useMemo(()=>{const t=e?.form?.field_groups??[],n=new Map,i={};t.forEach(a=>{n.set(a.code,a),a.additional_config?.default!==void 0&&(i[a.code]=a.additional_config.default)});const r=t.filter(a=>!a.is_hidden);return{fieldGroups:t,fieldByCode:n,visibleFieldGroups:r,initialValues:i}},[e])}function _e(e){const t={};return e.forEach(n=>{t[n.code]={disabled:n.is_readonly,hidden:n.is_hidden,required:n.is_required}}),t}function Le(e){const[t,n]=c.useState(()=>_e(e));c.useEffect(()=>{n(_e(e))},[e]);const i=c.useCallback((r,a)=>{n(o=>({...o,[r]:{...o[r],...a}}))},[]);return{fieldStates:t,setFieldStates:n,setFieldState:i}}function Oe({formInstance:e,fieldByCode:t,relatedData:n,transformers:i}){return{buildProcessedValues:c.useCallback(async()=>{await e.validateFields();const a=e.getFieldsValue(),o={};for(const d of Object.keys(a)){const y=t.get(d);if(!y)continue;let b;switch(y.field?.type?.code){case"datetime":b=a[d]?N(a[d]).format(y.additional_config?.datetime?.format):null;break;case"image":case"file":a[d]?.fileList?.length&&(b=a[d].fileList.filter(l=>l.percent===100).map(l=>({...l.response,name:l.name,type:l.type,size:l.size})));break;default:b=a[d]}i.transformFieldValue&&(b=i.transformFieldValue(d,b,y)),o[d]=b}let s=o;return i.transformSubmitValues&&(s=i.transformSubmitValues(s,Array.from(t.values()),n)),(i.parseRelatedDataTemplates??Ce)(s,n??{})},[t,e,n,i])}}const qe=c.forwardRef(({formConfig:e,formInstance:t,relatedData:n,uploadUrl:i,uploadResourceUrl:r,submitTrackingUrl:a,onBeforeSubmit:o,onSubmitSuccess:s,onSubmitError:f,isRedirectAfterCreate:d,onRedirect:y,size:b="middle",manualSubmit:l=!1,onValuesChange:_,readOnly:h=!1,submitDebounceMs:u,gutter:w=[8,0],defaultColSpan:v=12,submitButtonLabel:g},p)=>{const{message:j}=F.App.useApp(),x=k(),{i18n:S,client:A,parsers:M,redirectHandler:D,renderers:O,transformers:q}=x,le=i??r,ce=u??x.submitDebounceMs,de=g??S.messages.submit,{fieldGroups:E,fieldByCode:$e,initialValues:I}=Te(e),{fieldStates:U,setFieldState:ue}=Le(E),{buildProcessedValues:B}=Oe({formInstance:t,fieldByCode:$e,relatedData:n,transformers:q}),W=c.useRef(!1),[me,fe]=c.useState(!1),[pe,he]=c.useState(!1);c.useEffect(()=>{if(Object.keys(I).length>0){const R=q.normalizeInitialValues?q.normalizeInitialValues(I,E):I;t.setFieldsValue(R)}},[E,t,I,q]);const G=c.useCallback(async()=>{if(!W.current){W.current=!0,fe(!0);try{let R=await B();try{a&&(he(!0),await A.request({method:"POST",url:a,data:R}));const C=await o?.(R);if(C===!1)return;C&&typeof C=="object"&&(R=C)}catch(C){console.error(C);return}finally{he(!1)}const L=await A.request({method:e.method,url:e.action,data:R});t.resetFields(E.filter(C=>!C.is_hidden).map(C=>C.code));const Z=M.submitResponse(L.data);d&&Z.redirectUrl&&(y??D)(Z.redirectUrl,"_blank"),s?.({values:R,response:L.data,data:Z.data??L.data})}catch(R){const L=R;j.error(L?.response?.data?.message??S.messages.submitError),f?.(R)}finally{W.current=!1,fe(!1)}}},[B,A,E,e.action,e.method,t,S.messages.submitError,d,j,o,y,f,s,M,D,a]);c.useImperativeHandle(p,()=>({submit:G,getProcessedValues:B,isSubmitting:()=>W.current}),[B,G]);const ye=c.useMemo(()=>Y(()=>{G()},ce),[G,ce]),be=c.useCallback(R=>m.jsx(Pe,{group:R,formInstance:t,fieldState:U[R.code],setFieldState:ue,uploadUrl:le,readOnly:h,size:b},R.id),[U,t,h,le,ue,b]),Ne=O.layout?O.layout({fieldGroups:E,fieldStates:U,renderField:be,gutter:w,defaultColSpan:v,size:b}):m.jsx(Ve,{fieldGroups:E,fieldStates:U,renderField:be,gutter:w,defaultColSpan:v,size:b}),Ye=!l&&!h&&(O.submitActions?O.submitActions({onSubmit:ye,loading:me||pe,label:de}):m.jsx(F.Flex,{justify:"flex-end",children:m.jsx(F.Button,{type:"primary",onClick:ye,loading:me||pe,children:de})}));return m.jsxs(F.Form,{layout:"vertical",form:t,size:b,onValuesChange:_,children:[Ne,Ye]})});qe.displayName="DynamicForm";function ie(e){if(!e)return;const{mode:t}=e;if(t==="api"&&e.api?.url)return e.api;if(t==="api_ids"&&e.api_ids?.url){const n=e.api_ids,i=n.method?.toUpperCase()==="POST";return{url:n.url,method:n.method,data_path:n.data_path,mapping_attr:n.mapping_attr,link:n.link,result_type:n.result_type??"array",params:n.params??(!i&&!n.data?{ids:"{{value}}"}:void 0),data:n.data??(i&&!n.params?{ids:"{{value}}"}:void 0)}}if(t==="api_detail"&&e.api_detail?.url){const n=e.api_detail;return{url:n.url,method:n.method,data_path:n.data_path,mapping_attr:n.mapping_attr,link:n.link,result_type:n.result_type??"object",url_template:n.url_template??!0,params:n.params,data:n.data}}}function ve(e){return{value:e,id:e}}function Ie(e,t){const n=t.method||"GET",i=n.toUpperCase()==="GET";if(t.url_template)return(Array.isArray(e)?e.filter(f=>f!=null&&f!==""):e!=null&&e!==""?[e]:[]).map(f=>{const d=ve(f),y=H(t.url,d),b=t.params?P(t.params,d):void 0,l=t.data?P(t.data,d):void 0;return{method:n,url:y,params:i?b:void 0,data:i?void 0:l}});const r=ve(e),a=t.params?P(t.params,r):void 0,o=t.data?P(t.data,r):void 0;return[{method:n,url:t.url,params:i?a:void 0,data:i?void 0:o}]}function re(e,t){const n=t.data_path?T(e,t.data_path):e;return(t.result_type??(Array.isArray(n)?"array":"object"))==="array"?Array.isArray(n)?n:n!=null?[n]:[]:Array.isArray(n)?n.length?[n[0]]:[]:n&&typeof n=="object"?[n]:[]}function ae(e,t){return mt(e,t.mapping_attr)}function se(e,t){return ft(t.link,e)}async function Ue(e,t,n,i){const r=Ie(e,t);if(!r.length)return[];const a=await Promise.all(r.map(s=>n({...s,signal:i}))),o=[];for(const s of a)o.push(...re(s.data,t));return o}function V(e){return!!(e==null||e===""||Array.isArray(e)&&e.length===0)}function Be(e,t){const n=e.option_config?.api_options?.params,i=e.option_config?.api_options?.data;if(!n&&!i)return;const r=a=>{const o={};for(const s in a)if(typeof a[s]=="string"&&a[s].startsWith("{{")&&a[s].endsWith("}}")){const f=a[s].slice(2,-2).trim();o[s]=t?.[f]}else o[s]=a[s];return o};return{params:n?r(n):void 0,data:i?r(i):void 0}}function ot(e,t){const n=t.option_config?.label_attr,i=t.option_config?.value_attr||"";if(n?.length){const r=n.join(" - ");return e[r]!==void 0?String(e[r]):n.map(a=>e[a]).filter(a=>a!=null&&a!=="").join(" - ")}return String(e[i]??"")}function lt(e,t){if(!t?.length)return null;const i=(Array.isArray(e)?e:[e]).map(r=>t.find(a=>String(a.value)===String(r))?.label).filter(r=>!!r);return i.length?i.join(", "):null}function ct(e,t,n){if(V(e))return null;const i=t.option_config?.value_attr||"value",r=Array.isArray(e)?e:[e];if(t.is_option_api&&n?.length){const o=r.map(s=>{const f=n.find(d=>String(d[i])===String(s));return f?ot(f,t):String(s)}).filter(Boolean);return o.length?o.join(", "):null}const a=lt(e,t.metas);return a||r.map(String).join(", ")}function dt(e,t){if(V(e))return null;const n=t.additional_config?.datetime?.format,i=N(e);return i.isValid()?n?i.format(n):i.format("YYYY-MM-DD HH:mm:ss"):String(e)}function ut(e){if(V(e))return null;if(Array.isArray(e)){const t=e.map(n=>typeof n=="object"&&n&&"name"in n?String(n.name):String(n)).filter(Boolean);return t.length?t.join(", "):null}return String(e)}function mt(e,t){return t?.length?t.map(n=>{const i=T(e,n)??e[n];return i!=null?String(i):""}).filter(Boolean).join(" - "):JSON.stringify(e)}function ft(e,t){return e?e.replace(/\{\{(.+?)\}\}/g,(n,i)=>{const r=i.trim(),a=T(t,r)??t[r];return a!=null?String(a):""}):null}function te(e,t,n){if(V(e))return null;switch(t?.mode??"formatted"){case"raw":case"formatted":return Array.isArray(e)?e.map(String).join(", "):String(e);case"api":case"api_ids":case"api_detail":{const r=ie(t);if(!n||!r)return Array.isArray(e)?e.map(String).join(", "):String(e);const a=re(n,r);return a.length?a.map(s=>{const f=ae(s,r),d=se(s,r);return d?`${f} (${d})`:f}).filter(Boolean).join(", ")||null:String(e)}default:return String(e)}}function We(e,t,n){const i=e.additional_config?.view_value;if(i?.mode==="api"||i?.mode==="api_ids"||i?.mode==="api_detail")return te(t,i,n.viewValueFetched);switch(e.field?.type?.code){case"text":case"number":return V(t)?null:String(t);case"datetime":return dt(t,e);case"select":case"radio":case"checkbox":return ct(t,e,n.optionList);case"image":case"file":return ut(t);default:return i?te(t,i,n.viewValueFetched):V(t)?null:String(t)}}const $=new Map,pt=3e4;function ht(e){const t=$.get(e);if(t){if(Date.now()>t.expiresAt){$.delete(e);return}return t.error}}function we(e,t){$.set(e,{error:t,expiresAt:Date.now()+pt})}function Q(e,t,n=!0){const i=k(),[r,a]=c.useState(),[o,s]=c.useState(!1),[f,d]=c.useState(),y=c.useRef(t),b=c.useRef(i);y.current=t,b.current=i;const l=J(e);return c.useEffect(()=>{if(!n){a(void 0),d(void 0),s(!1);return}const h=ht(l);if(h!==void 0){d(h),s(!1);return}const u=new AbortController;return s(!0),d(void 0),(async()=>{try{const v=await z(b.current,"viewCache",l,g=>y.current(g),u.signal);u.signal.aborted||(a(v),d(void 0))}catch(v){u.signal.aborted||(we(l,v),d(v))}finally{u.signal.aborted||s(!1)}})(),()=>u.abort()},[n,l]),{data:r,isLoading:o,error:f,refetch:async()=>{if($.delete(l),!n)return;const h=new AbortController;s(!0),d(void 0);try{const u=await z(b.current,"viewCache",l,w=>y.current(w),h.signal);return a(u),u}catch(u){throw we(l,u),d(u),u}finally{s(!1)}}}}const yt=({value:e,code:t,modeConfig:n,viewConfig:i})=>{const{client:r,renderers:a,i18n:o}=k(),s=c.useMemo(()=>n??(i?ie(i):void 0),[n,i]),f=c.useMemo(()=>["api_view",t,e,s?.url,s?.method,s?.data_path],[t,e,s?.url,s?.method,s?.data_path]),d=c.useCallback(async u=>s?Ue(e,s,w=>r.request({...w,signal:u})):[],[r,s,e]),{data:y,isLoading:b,error:l}=Q(f,d,!!(e&&s?.url)),_=(u,w,v)=>a.link?a.link({url:u,label:w,data:v}):m.jsx("a",{href:u,target:"_blank",rel:"noreferrer",children:w}),h=(u,w)=>{if(!s)return null;const v=ae(u,s),g=se(u,s),p=g?_(g,v,u):v;return m.jsx("div",{children:p},u.id??w)};return b?m.jsx(m.Fragment,{children:a.viewLoading?.()??m.jsx(F.Spin,{size:"small"})}):l?m.jsx(m.Fragment,{children:a.viewError?.(l)??o.messages.viewError}):y?.length?s?.result_type==="object"&&y.length===1?h(y[0],0):m.jsx(F.Flex,{vertical:!0,children:y.map(h)}):m.jsx(m.Fragment,{children:a.viewEmpty?.()??o.messages.viewEmpty})},X=c.memo(yt);function bt(e){return!!(e.option_config&&e.is_option_api)}function _t(e){return e==="api"||e==="api_ids"||e==="api_detail"}function vt(e,t){const n=k(),i=J(["viewModeOptions",e.map(a=>a.code),t]),{data:r}=Q([i],async a=>{const o={};return await Promise.all(e.map(async s=>{if(!s.option_config?.url)return;const f=Be(s,t),d=s.option_config.method?.toUpperCase()==="GET"||!s.option_config.method,y=await n.client.request({method:s.option_config.method||"GET",url:s.option_config.url,params:d?f?.params:void 0,data:d?void 0:f?.data,signal:a});o[s.code]={optionList:n.parsers.optionResponse(y.data,s)}})),o},e.length>0);return r??{}}const wt=({formConfig:e,formValues:t})=>{const n=e?.form?.field_groups??[],i=c.useMemo(()=>n.filter(bt),[n]),r=vt(i,t);return c.useMemo(()=>n.filter(o=>!o.is_hidden).map(o=>{const s=t?.[o.code],f=o.additional_config?.view_value,d=f?.mode;if(_t(d)&&f)return{key:o.code,label:o.label,rawValue:s,viewValue:m.jsx(X,{code:o.code,value:s,viewConfig:f}),field_group:o};const y=r[o.code]??{};return{key:o.code,label:o.label,rawValue:s,viewValue:We(o,s,y),field_group:o}}),[r,n,t])},gt=({code:e,value:t,fieldGroup:n})=>{const i=n?.additional_config?.view_value;switch(i?.mode){case"raw":return t;case"api":case"api_ids":case"api_detail":return m.jsx(X,{code:e,value:t,viewConfig:i});default:return t}},St=c.memo(gt),Ft=({value:e,code:t,modeConfig:n})=>m.jsx(X,{code:t,value:e,viewConfig:n?{mode:"api_ids",api_ids:n}:void 0}),xt=c.memo(Ft),jt=({value:e,code:t,modeConfig:n})=>{const{client:i,renderers:r,i18n:a}=k(),o=c.useMemo(()=>(Array.isArray(e)?e:[e]).filter(Boolean),[e]),{data:s,isLoading:f,error:d}=Q(["api_detail",t,o,n?.url,n?.method],async l=>(await Promise.all(o.map(async h=>{const u=H(n?.url||"",{id:h});return(await i.request({method:n?.method,url:u,signal:l})).data}))).filter(Boolean),!!(o.length&&n?.url)),y=(l,_,h)=>r.link?r.link({url:l,label:_,data:h}):m.jsx("a",{href:l,target:"_blank",rel:"noreferrer",children:_}),b=l=>{const _=n?.mapping_attr?.map(h=>l?.[h]).join(" - ");if(n?.link){const h=H(n.link,l);return y(h,_,l)}return _};return f?m.jsx(m.Fragment,{children:r.viewLoading?.()??m.jsx(F.Spin,{size:"small"})}):d?m.jsx(m.Fragment,{children:r.viewError?.(d)??a.messages.viewError}):s?.length?m.jsx(m.Fragment,{children:s.map((l,_)=>m.jsx("div",{children:b(l)},_))}):m.jsx(m.Fragment,{children:r.viewEmpty?.()??a.messages.viewEmpty})},At=c.memo(jt),oe={submit:"Save",submitError:"Failed to submit form",inputPlaceholder:e=>`Enter ${e}`,selectPlaceholder:e=>`Select ${e}`,optionLoading:"Loading...",optionError:"Failed to load options",uploadError:"Upload failed",viewLoading:"Loading...",viewEmpty:"-",viewError:"Failed to load"},Rt={messages:oe},Ge=e=>{if(Array.isArray(e))return e;if(e&&typeof e=="object"&&"items"in e&&Array.isArray(e.items))return e.items;if(e&&typeof e=="object"&&"data"in e&&e.data&&typeof e.data=="object"&&"items"in(e.data??{})){const t=e.data;return Array.isArray(t.items)?t.items:[]}return[]},Ke=e=>({redirectUrl:e?.redirect_after_create,data:e}),ze=(e,t)=>t?.dataPath?T(e,t.dataPath):e,K={optionResponse:Ge,submitResponse:Ke,viewResponse:ze},He=(e,t="_blank")=>{window.open(e,t)},ee={upload:async()=>{throw new Error("Upload adapter is not configured")},remove:async()=>!1};function Mt({children:e,client:t,upload:n,i18n:i,parsers:r,renderers:a={},transformers:o={},cache:s,submitDebounceMs:f=200,redirectHandler:d,requestClient:y,uploadAdapter:b,deleteUploadAdapter:l,messages:_,optionResponseParser:h,customFieldRenderers:u}){const w=c.useRef(new Map),v=c.useRef(new Map),g=c.useMemo(()=>{const p=t??{request:y??(()=>{throw new Error("DynamicFormProvider requires client or requestClient")})},j=u?Object.entries(u).map(([A,M])=>({match:A,render:M})):[],x={...oe,...i?.messages,..._},S={...ee,...n,upload:n?.upload??b??ee.upload,remove:n?.remove??(l?A=>l(A.path):ee.remove)};return{client:p,upload:S,i18n:{messages:x},parsers:{optionResponse:r?.optionResponse??h??K.optionResponse,submitResponse:r?.submitResponse??K.submitResponse,viewResponse:r?.viewResponse??K.viewResponse},renderers:{...a,fields:[...a.fields??[],...j]},transformers:o,cache:{enabled:s?.enabled??!0,ttlMs:s?.ttlMs??6e4},submitDebounceMs:f,redirectHandler:d??He,optionCache:w.current,viewCache:v.current}},[t,y,n,b,l,i?.messages,_,r?.optionResponse,r?.submitResponse,r?.viewResponse,h,a,u,o,s?.enabled,s?.ttlMs,f,d]);return m.jsx(ne.Provider,{value:g,children:e})}function Ct(e){return{request:async t=>({data:(await e({method:t.method,url:t.url,params:t.params,data:t.data,signal:t.signal,headers:t.headers,onUploadProgress:t.onUploadProgress})).data})}}exports.ApiDetailItem=At;exports.ApiItem=xt;exports.ApiViewItem=X;exports.DefaultLayout=Ve;exports.DynamicForm=qe;exports.DynamicFormProvider=Mt;exports.FormItem=Pe;exports.MetaItemValue=St;exports.buildApiViewRequests=Ie;exports.buildCacheKey=J;exports.cachedRequest=z;exports.createAxiosDynamicFormClient=Ct;exports.debounce=Y;exports.defaultI18n=Rt;exports.defaultMessages=oe;exports.defaultOptionResponseParser=Ge;exports.defaultParsers=K;exports.defaultRedirectHandler=He;exports.defaultSubmitResponseParser=Ke;exports.defaultViewResponseParser=ze;exports.extractDependencyFields=ke;exports.extractViewData=re;exports.fetchApiViewItems=Ue;exports.fillTemplate=H;exports.getByPath=T;exports.getCached=Re;exports.getMappedLabel=ae;exports.getMappedLink=se;exports.isEmptyValue=V;exports.mapOptionToSelectItem=xe;exports.mapOptions=je;exports.normalizeApiViewConfig=ie;exports.normalizeMetaForForm=rt;exports.parseFormValues=Ce;exports.replaceTemplateInObject=P;exports.resolveApiOptionMeta=Be;exports.resolveFieldRenderer=Se;exports.resolveFieldRendererFromMap=Fe;exports.resolveFieldViewValue=We;exports.resolveViewValueConfig=te;exports.setCache=Me;exports.useCachedViewRequest=Q;exports.useDependencyValues=De;exports.useDynamicField=Ae;exports.useDynamicFormContext=k;exports.useDynamicFormContextOptional=Je;exports.useDynamicOptions=Ee;exports.useFieldGroups=Te;exports.useFieldStates=Le;exports.useProcessedValues=Oe;exports.useViewMode=wt;
package/dist/index.d.ts CHANGED
@@ -59,11 +59,10 @@ export declare interface AdditionalConfig {
59
59
 
60
60
  export declare const ApiDetailItem: MemoExoticComponent<({ value, code, modeConfig }: ApiDetailItemProps) => JSX.Element>;
61
61
 
62
- /** @deprecated Use ApiViewItem with mode: "api" */
63
62
  declare type ApiDetailItemProps = {
64
63
  value?: unknown;
65
64
  code?: string;
66
- modeConfig?: ApiViewConfig;
65
+ modeConfig?: ViewValueConfig["api_detail"];
67
66
  };
68
67
 
69
68
  export declare const ApiItem: MemoExoticComponent<({ value, code, modeConfig }: ApiItemProps) => JSX.Element>;