@rytass/bpm-core-react 0.17.9 → 0.18.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.
Files changed (53) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/README.md +8 -0
  3. package/dist/chunks/{FormBuilderView-ClLnQ1e_.js → FormBuilderView-BVKY1j_0.js} +504 -452
  4. package/dist/chunks/FormBuilderView-BVKY1j_0.js.map +1 -0
  5. package/dist/chunks/FormBuilderView-SrGltzFT.cjs +3 -0
  6. package/dist/chunks/FormBuilderView-SrGltzFT.cjs.map +1 -0
  7. package/dist/chunks/approver-filled-form-Dm3Iw7iw.cjs +2 -0
  8. package/dist/chunks/approver-filled-form-Dm3Iw7iw.cjs.map +1 -0
  9. package/dist/chunks/{approver-filled-form-DuQGPtNB.js → approver-filled-form-ZEwpmsHJ.js} +21 -8
  10. package/dist/chunks/approver-filled-form-ZEwpmsHJ.js.map +1 -0
  11. package/dist/chunks/{compose-jnvnnVfN.js → compose-B1GlrZW9.js} +3 -3
  12. package/dist/chunks/{compose-jnvnnVfN.js.map → compose-B1GlrZW9.js.map} +1 -1
  13. package/dist/chunks/{compose-Cock_B2Q.cjs → compose-DZk-SfHT.cjs} +2 -2
  14. package/dist/chunks/{compose-Cock_B2Q.cjs.map → compose-DZk-SfHT.cjs.map} +1 -1
  15. package/dist/chunks/{designer-B8Gvew_k.js → designer-BCLrjb4H.js} +886 -851
  16. package/dist/chunks/designer-BCLrjb4H.js.map +1 -0
  17. package/dist/chunks/designer-BYYxEN9L.cjs +65 -0
  18. package/dist/chunks/designer-BYYxEN9L.cjs.map +1 -0
  19. package/dist/chunks/{detail-CExpbazF.js → detail-4F39ggBn.js} +580 -572
  20. package/dist/chunks/detail-4F39ggBn.js.map +1 -0
  21. package/dist/chunks/detail-BkMtA_0K.cjs +2 -0
  22. package/dist/chunks/detail-BkMtA_0K.cjs.map +1 -0
  23. package/dist/pages/instances/detail/index.cjs +1 -1
  24. package/dist/pages/instances/detail/index.js +1 -1
  25. package/dist/pages/templates/compose/index.cjs +1 -1
  26. package/dist/pages/templates/compose/index.js +1 -1
  27. package/dist/pages/templates/designer/index.cjs +1 -1
  28. package/dist/pages/templates/designer/index.js +1 -1
  29. package/dist/views/forms/builder/index.cjs +1 -1
  30. package/dist/views/forms/builder/index.js +1 -1
  31. package/dist/views/instances/detail/index.cjs +1 -1
  32. package/dist/views/instances/detail/index.js +1 -1
  33. package/dist/views/instances/new/index.cjs +1 -1
  34. package/dist/views/instances/new/index.cjs.map +1 -1
  35. package/dist/views/instances/new/index.js +15 -11
  36. package/dist/views/instances/new/index.js.map +1 -1
  37. package/dist/views/templates/compose/index.cjs +1 -1
  38. package/dist/views/templates/compose/index.js +1 -1
  39. package/dist/views/templates/designer/index.cjs +1 -1
  40. package/dist/views/templates/designer/index.js +1 -1
  41. package/package.json +3 -3
  42. package/dist/chunks/FormBuilderView-CUOyS07f.cjs +0 -3
  43. package/dist/chunks/FormBuilderView-CUOyS07f.cjs.map +0 -1
  44. package/dist/chunks/FormBuilderView-ClLnQ1e_.js.map +0 -1
  45. package/dist/chunks/approver-filled-form-D1DmqDVP.cjs +0 -2
  46. package/dist/chunks/approver-filled-form-D1DmqDVP.cjs.map +0 -1
  47. package/dist/chunks/approver-filled-form-DuQGPtNB.js.map +0 -1
  48. package/dist/chunks/designer-B8Gvew_k.js.map +0 -1
  49. package/dist/chunks/designer-CAEFV1ve.cjs +0 -65
  50. package/dist/chunks/designer-CAEFV1ve.cjs.map +0 -1
  51. package/dist/chunks/detail-CExpbazF.js.map +0 -1
  52. package/dist/chunks/detail-DIY-L4i-.cjs +0 -2
  53. package/dist/chunks/detail-DIY-L4i-.cjs.map +0 -1
@@ -1,2 +1,2 @@
1
- Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});const e=require("../../../chunks/detail-DIY-L4i-.cjs");let t=require("react/jsx-runtime");var n={title:`案件詳情 | BPM Admin`};async function r({params:n}){let{id:r}=await n;return(0,t.jsx)(e.t,{instanceId:r})}exports.default=r,exports.metadata=n;
1
+ Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});const e=require("../../../chunks/detail-BkMtA_0K.cjs");let t=require("react/jsx-runtime");var n={title:`案件詳情 | BPM Admin`};async function r({params:n}){let{id:r}=await n;return(0,t.jsx)(e.t,{instanceId:r})}exports.default=r,exports.metadata=n;
2
2
  //# sourceMappingURL=index.cjs.map
@@ -1,4 +1,4 @@
1
- import { t as e } from "../../../chunks/detail-CExpbazF.js";
1
+ import { t as e } from "../../../chunks/detail-4F39ggBn.js";
2
2
  import { jsx as t } from "react/jsx-runtime";
3
3
  //#region src/pages/instances/detail/index.tsx
4
4
  var n = { title: "案件詳情 | BPM Admin" };
@@ -1,2 +1,2 @@
1
- Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});const e=require("../../../chunks/compose-Cock_B2Q.cjs");let t=require("react/jsx-runtime"),n=require("next/server");var r={title:`建立模板(表單 + 流程) | BPM Admin`,description:`以精靈式流程一次完成 BPM 表單與簽核流程設計並發佈。`};async function i(){return await(0,n.connection)(),(0,t.jsx)(e.t,{aiAssistantAvailable:!!process.env.OPENAI_API_KEY,showAiAssistant:process.env.BPM_AI_ASSISTANT_ENABLED===`true`})}exports.default=i,exports.metadata=r;
1
+ Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});const e=require("../../../chunks/compose-DZk-SfHT.cjs");let t=require("react/jsx-runtime"),n=require("next/server");var r={title:`建立模板(表單 + 流程) | BPM Admin`,description:`以精靈式流程一次完成 BPM 表單與簽核流程設計並發佈。`};async function i(){return await(0,n.connection)(),(0,t.jsx)(e.t,{aiAssistantAvailable:!!process.env.OPENAI_API_KEY,showAiAssistant:process.env.BPM_AI_ASSISTANT_ENABLED===`true`})}exports.default=i,exports.metadata=r;
2
2
  //# sourceMappingURL=index.cjs.map
@@ -1,4 +1,4 @@
1
- import { t as e } from "../../../chunks/compose-jnvnnVfN.js";
1
+ import { t as e } from "../../../chunks/compose-B1GlrZW9.js";
2
2
  import { jsx as t } from "react/jsx-runtime";
3
3
  import { connection as n } from "next/server";
4
4
  //#region src/pages/templates/compose/index.tsx
@@ -1,2 +1,2 @@
1
- Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});const e=require("../../../chunks/designer-CAEFV1ve.cjs");let t=require("react/jsx-runtime");var n={title:`流程設計器 | BPM Admin`,description:`以視覺化設計器編輯 BPM 簽核流程節點、條件與發佈版本。`};async function r({params:n}){let{id:r}=await n;return(0,t.jsx)(e.t,{aiAssistantAvailable:!!process.env.OPENAI_API_KEY,showAiAssistant:process.env.BPM_AI_ASSISTANT_ENABLED===`true`,showDryRun:process.env.BPM_TEMPLATE_DRY_RUN_ENABLED!==`false`,templateId:r})}exports.default=r,exports.metadata=n;
1
+ Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});const e=require("../../../chunks/designer-BYYxEN9L.cjs");let t=require("react/jsx-runtime");var n={title:`流程設計器 | BPM Admin`,description:`以視覺化設計器編輯 BPM 簽核流程節點、條件與發佈版本。`};async function r({params:n}){let{id:r}=await n;return(0,t.jsx)(e.t,{aiAssistantAvailable:!!process.env.OPENAI_API_KEY,showAiAssistant:process.env.BPM_AI_ASSISTANT_ENABLED===`true`,showDryRun:process.env.BPM_TEMPLATE_DRY_RUN_ENABLED!==`false`,templateId:r})}exports.default=r,exports.metadata=n;
2
2
  //# sourceMappingURL=index.cjs.map
@@ -1,4 +1,4 @@
1
- import { t as e } from "../../../chunks/designer-B8Gvew_k.js";
1
+ import { t as e } from "../../../chunks/designer-BCLrjb4H.js";
2
2
  import { jsx as t } from "react/jsx-runtime";
3
3
  //#region src/pages/templates/designer/index.tsx
4
4
  var n = {
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../../../chunks/FormBuilderView-CUOyS07f.cjs");exports.FormBuilderView=e.t;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../../../chunks/FormBuilderView-SrGltzFT.cjs");exports.FormBuilderView=e.t;
@@ -1 +1 @@
1
- export { t as FormBuilderView } from "../../../chunks/FormBuilderView-ClLnQ1e_.js";
1
+ export { t as FormBuilderView } from "../../../chunks/FormBuilderView-BVKY1j_0.js";
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../../../chunks/detail-DIY-L4i-.cjs");exports.InstanceAttachmentsSection=e.o,exports.InstanceDetailView=e.t,exports.InstanceFormSection=e.s,exports.InstanceHistorySection=e.r,exports.InstanceSignaturesSection=e.i,exports.InstanceTasksSection=e.a,exports.InstanceWebhookDeliveriesSection=e.n;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../../../chunks/detail-BkMtA_0K.cjs");exports.InstanceAttachmentsSection=e.o,exports.InstanceDetailView=e.t,exports.InstanceFormSection=e.s,exports.InstanceHistorySection=e.r,exports.InstanceSignaturesSection=e.i,exports.InstanceTasksSection=e.a,exports.InstanceWebhookDeliveriesSection=e.n;
@@ -1 +1 @@
1
- export { o as InstanceAttachmentsSection, t as InstanceDetailView, s as InstanceFormSection, r as InstanceHistorySection, i as InstanceSignaturesSection, a as InstanceTasksSection, n as InstanceWebhookDeliveriesSection } from "../../../chunks/detail-CExpbazF.js";
1
+ export { o as InstanceAttachmentsSection, t as InstanceDetailView, s as InstanceFormSection, r as InstanceHistorySection, i as InstanceSignaturesSection, a as InstanceTasksSection, n as InstanceWebhookDeliveriesSection } from "../../../chunks/detail-4F39ggBn.js";
@@ -1,2 +1,2 @@
1
- "use client";Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../../../chunks/rolldown-runtime-BocRIvOZ.cjs"),t=require("../../../chunks/router-adapter--gYs13E8.cjs"),n=require("../../../chunks/auth-provider-4BeCw7cI.cjs"),r=require("../../../chunks/format-date-time-D-cx5M8z.cjs"),i=require("../../../chunks/routes-config-C1j_vFKo.cjs"),a=require("../../../chunks/approver-filled-form-D1DmqDVP.cjs"),o=require("../../../chunks/FormRendererView-GpsE03np.cjs");let s=require("react"),c=require("@mezzanine-ui/react"),l=require("react/jsx-runtime"),u=require("@rytass/bpm-core-client/workflow"),d=require("@mezzanine-ui/react/ContentHeader");d=e.t(d,1);let f=require("@mezzanine-ui/icons"),p=require("@rytass/bpm-core-client/form");var m={display:`grid`,gap:16};function h(e={}){return(0,l.jsx)(s.Suspense,{fallback:(0,l.jsx)(_,{}),children:(0,l.jsx)(g,{templateId:e.templateId??void 0})})}function g({templateId:e}){let h=t.r(),g=i.r(),{member:_}=n.n(),y=_?.memberId??null,b=e??null,[x,S]=(0,s.useState)(null),[C,w]=(0,s.useState)({}),[T,E]=(0,s.useState)([]),[D,O]=(0,s.useState)(null),[k,A]=(0,s.useState)({}),[j,M]=(0,s.useState)(!0),[N,P]=(0,s.useState)(!1),[F,I]=(0,s.useState)({}),L=(0,s.useMemo)(()=>x?a.n(x.formVersion.schema,x.templateVersion.workflowDefinition):null,[x]),R=(0,s.useCallback)((e,t)=>{I(n=>{let r=n[e];return r?.hasValue===t.hasValue&&r.status===t.status?n:{...n,[e]:{hasValue:t.hasValue,status:t.status}}})},[]);(0,s.useEffect)(()=>{b?U(b):H()},[b]);let z=(0,s.useMemo)(()=>T.map(e=>({...e,key:e.id,updatedAt:r.t(e.updatedAt),versionLabel:`v${e.version}`})),[T]),B=(0,s.useMemo)(()=>[{dataIndex:`name`,key:`name`,title:`模板名稱`,width:240},{dataIndex:`versionLabel`,key:`versionLabel`,title:`發布版本`,width:120},{dataIndex:`updatedAt`,key:`updatedAt`,title:`更新時間`,width:220}],[]),V=(0,s.useMemo)(()=>({render:e=>[{name:`發起`,onClick:()=>h.push(g.caseNew(e.id)),variant:`base-primary`}],variant:`base-secondary`,width:88}),[h]);async function H(){M(!0),O(null),S(null),I({});try{E(await(0,u.listLaunchableTemplates)())}catch(e){O(v(e))}finally{M(!1)}}async function U(e){M(!0),O(null),E([]),I({});try{S(await(0,u.readLaunchContext)(e))}catch(e){O(v(e))}finally{M(!1)}}async function W(){if(!x||!L||!y)return;P(!0),O(null),A({});let e=o.o(Object.values(F));if(e){O(e),P(!1);return}let t=a.r((0,p.buildFormRendererValues)(L.fields,C),x.templateVersion.workflowDefinition),n=(0,p.validateFormRendererValues)({schema:L,uiSchema:x.formVersion.uiSchema,values:t});if(!n.valid)A(n.errors),O(`請先補齊必填欄位。`),n.firstInvalidFieldKey&&(0,p.focusFormRendererField)(n.firstInvalidFieldKey),P(!1);else try{let e=await(0,u.submitApprovalInstance)({formData:t,initiatorMemberId:y,templateId:x.template.id,title:(0,u.readFormDataCaseTitle)({fallbackTitle:x.template.name,formData:t,schema:L,uiSchema:x.formVersion.uiSchema})});h.push(g.caseDetail(e))}catch(e){O(v(e))}finally{P(!1)}}async function G(e,t){if(!y)throw Error(`尚未登入,無法上傳附件`);return{id:(await(0,u.uploadAttachment)({file:t,formFieldPath:`form.${e.fieldKey}`})).id}}return(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(c.PageHeader,{children:(0,l.jsx)(d.default,{description:x?`${x.template.name} · 表單 v${x.formVersion.version}`:`選擇可發起的已發布模板後填寫表單內容。`,title:`發起簽核`,children:x?(0,l.jsx)(c.Button,{disabled:j||N,icon:f.CheckedIcon,iconType:`leading`,onClick:W,variant:`base-primary`,children:`送出`}):null})}),(0,l.jsx)(c.SectionGroup,{children:(0,l.jsx)(c.Section,{children:(0,l.jsxs)(`div`,{style:m,children:[D?(0,l.jsx)(c.Typography,{color:`text-error`,variant:`body`,children:D}):null,j?(0,l.jsx)(c.Typography,{color:`text-neutral`,variant:`body`,children:`載入中...`}):null,x&&L?(0,l.jsx)(o.t,{dataSourceContext:{kind:`runtime`,templateId:x.template.id},errors:k,maxWidth:480,onChange:e=>{w(e),A({})},onDataSourceStateChange:R,onUploadAttachment:G,schema:L,singleColumn:!0,uiSchema:x.formVersion.uiSchema,value:C}):null,!b&&!j?z.length>0?(0,l.jsx)(c.Table,{actions:V,columns:B,dataSource:z,fullWidth:!0}):(0,l.jsx)(c.Typography,{color:`text-neutral`,variant:`body`,children:`目前沒有可發起的已發布模板。`}):null]})})})]})}function _(){return(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(c.PageHeader,{children:(0,l.jsx)(d.default,{description:`選擇可發起的已發布模板後填寫表單內容。`,title:`發起簽核`})}),(0,l.jsx)(c.SectionGroup,{children:(0,l.jsx)(c.Section,{children:(0,l.jsx)(c.Typography,{color:`text-neutral`,variant:`body`,children:`載入中...`})})})]})}function v(e){return(0,p.readFormDataSourceErrorMessage)(e)||(e instanceof Error?e.message:`發生未知錯誤`)}exports.InstanceNewView=h;
1
+ "use client";Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../../../chunks/rolldown-runtime-BocRIvOZ.cjs"),t=require("../../../chunks/router-adapter--gYs13E8.cjs"),n=require("../../../chunks/auth-provider-4BeCw7cI.cjs"),r=require("../../../chunks/format-date-time-D-cx5M8z.cjs"),i=require("../../../chunks/routes-config-C1j_vFKo.cjs"),a=require("../../../chunks/approver-filled-form-Dm3Iw7iw.cjs"),o=require("../../../chunks/FormRendererView-GpsE03np.cjs");let s=require("react"),c=require("@mezzanine-ui/react"),l=require("react/jsx-runtime"),u=require("@rytass/bpm-core-client/workflow"),d=require("@mezzanine-ui/react/ContentHeader");d=e.t(d,1);let f=require("@mezzanine-ui/icons"),p=require("@rytass/bpm-core-client/form");var m={display:`grid`,gap:16};function h(e={}){return(0,l.jsx)(s.Suspense,{fallback:(0,l.jsx)(_,{}),children:(0,l.jsx)(g,{templateId:e.templateId??void 0})})}function g({templateId:e}){let h=t.r(),g=i.r(),{member:_}=n.n(),y=_?.memberId??null,b=e??null,[x,S]=(0,s.useState)(null),[C,w]=(0,s.useState)({}),[T,E]=(0,s.useState)([]),[D,O]=(0,s.useState)(null),[k,A]=(0,s.useState)({}),[j,M]=(0,s.useState)(!0),[N,P]=(0,s.useState)(!1),[F,I]=(0,s.useState)({}),L=(0,s.useMemo)(()=>x?a.n(x.formVersion.schema,x.templateVersion.workflowDefinition):null,[x]),R=(0,s.useCallback)((e,t)=>{I(n=>{let r=n[e];return r?.hasValue===t.hasValue&&r.status===t.status?n:{...n,[e]:{hasValue:t.hasValue,status:t.status}}})},[]);(0,s.useEffect)(()=>{b?U(b):H()},[b]);let z=(0,s.useMemo)(()=>T.map(e=>({...e,key:e.id,updatedAt:r.t(e.updatedAt),versionLabel:`v${e.version}`})),[T]),B=(0,s.useMemo)(()=>[{dataIndex:`name`,key:`name`,title:`模板名稱`,width:240},{dataIndex:`versionLabel`,key:`versionLabel`,title:`發布版本`,width:120},{dataIndex:`updatedAt`,key:`updatedAt`,title:`更新時間`,width:220}],[]),V=(0,s.useMemo)(()=>({render:e=>[{name:`發起`,onClick:()=>h.push(g.caseNew(e.id)),variant:`base-primary`}],variant:`base-secondary`,width:88}),[h]);async function H(){M(!0),O(null),S(null),I({});try{E(await(0,u.listLaunchableTemplates)())}catch(e){O(v(e))}finally{M(!1)}}async function U(e){M(!0),O(null),E([]),I({});try{S(await(0,u.readLaunchContext)(e))}catch(e){O(v(e))}finally{M(!1)}}async function W(){if(!x||!L||!y)return;P(!0),O(null),A({});let e=o.o(Object.values(F));if(e){O(e),P(!1);return}let t=a.r((0,p.buildFormRendererValues)(L.fields,C),x.templateVersion.workflowDefinition);try{let e=await(0,p.validateFormRendererValuesInWorker)({schema:L,uiSchema:x.formVersion.uiSchema,values:t});if(!e.valid){A(e.errors),O(`請先修正表單中標示的欄位。`),e.firstInvalidFieldKey&&(0,p.focusFormRendererField)(e.firstInvalidFieldKey);return}let n=await(0,u.submitApprovalInstance)({formData:t,initiatorMemberId:y,templateId:x.template.id,title:(0,u.readFormDataCaseTitle)({fallbackTitle:x.template.name,formData:t,schema:L,uiSchema:x.formVersion.uiSchema})});h.push(g.caseDetail(n))}catch(e){O(v(e))}finally{P(!1)}}async function G(e,t){if(!y)throw Error(`尚未登入,無法上傳附件`);return{id:(await(0,u.uploadAttachment)({file:t,formFieldPath:`form.${e.fieldKey}`})).id}}return(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(c.PageHeader,{children:(0,l.jsx)(d.default,{description:x?`${x.template.name} · 表單 v${x.formVersion.version}`:`選擇可發起的已發布模板後填寫表單內容。`,title:`發起簽核`,children:x?(0,l.jsx)(c.Button,{disabled:j||N,icon:f.CheckedIcon,iconType:`leading`,onClick:W,variant:`base-primary`,children:`送出`}):null})}),(0,l.jsx)(c.SectionGroup,{children:(0,l.jsx)(c.Section,{children:(0,l.jsxs)(`div`,{style:m,children:[D?(0,l.jsx)(c.Typography,{color:`text-error`,variant:`body`,children:D}):null,j?(0,l.jsx)(c.Typography,{color:`text-neutral`,variant:`body`,children:`載入中...`}):null,x&&L?(0,l.jsx)(o.t,{dataSourceContext:{kind:`runtime`,templateId:x.template.id},errors:k,maxWidth:480,onChange:e=>{w(e),A({})},onDataSourceStateChange:R,onUploadAttachment:G,schema:L,singleColumn:!0,uiSchema:x.formVersion.uiSchema,value:C}):null,!b&&!j?z.length>0?(0,l.jsx)(c.Table,{actions:V,columns:B,dataSource:z,fullWidth:!0}):(0,l.jsx)(c.Typography,{color:`text-neutral`,variant:`body`,children:`目前沒有可發起的已發布模板。`}):null]})})})]})}function _(){return(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(c.PageHeader,{children:(0,l.jsx)(d.default,{description:`選擇可發起的已發布模板後填寫表單內容。`,title:`發起簽核`})}),(0,l.jsx)(c.SectionGroup,{children:(0,l.jsx)(c.Section,{children:(0,l.jsx)(c.Typography,{color:`text-neutral`,variant:`body`,children:`載入中...`})})})]})}function v(e){return(0,p.readFormDataSourceErrorMessage)(e)||(e instanceof Error?e.message:`發生未知錯誤`)}exports.InstanceNewView=h;
2
2
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["Suspense","useRouterAdapter","useBPMRoutes","useAuth","useState","useMemo","readApplicantFormSchema","useCallback","formatDateTime","listLaunchableTemplates","readLaunchContext","readFormDataSourceSubmissionBlockMessage","readApplicantSubmission","buildFormRendererValues","validateFormRendererValues","submitApprovalInstance","readFormDataCaseTitle","uploadAttachment","_Fragment","PageHeader","ContentHeader","Button","CheckedIcon","SectionGroup","Section","Typography","FormRenderer","Table","readFormDataSourceErrorMessage","require_rolldown_runtime","require_router_adapter","require_auth_provider","require_format_date_time","require_routes_config","require_approver_filled_form","require_FormRendererView","react","_mezzanine_ui_react","react_jsx_runtime","_rytass_bpm_core_client_workflow","_mezzanine_ui_react_ContentHeader","_mezzanine_ui_icons","_rytass_bpm_core_client_form","FORM_SECTION_STYLE","InstanceNewView","NewApprovalInstanceLoading","NewApprovalInstanceContent","props","templateIdProp","router","routes","currentMemberId","member","templateId","context","setContext","formValues","setFormValues","templates","setTemplates","error","setError","formErrors","setFormErrors","loading","setLoading","submitting","setSubmitting","dataSourceStates","setDataSourceStates","applicantSchema","handleDataSourceStateChange","currentState","currentStates","fieldKey","state","refreshContext","refreshTemplates","rows","template","columns","tableActions","record","requestError","readErrorMessage","nextTemplateId","handleSubmit","dataSourceBlockMessage","submittedValues","validation","instanceId","handleUploadAttachment","field","values"],"sources":["../../../../src/views/instances/new/InstanceNewView.tsx"],"sourcesContent":["'use client';\n\nimport {\n CSSProperties,\n ReactElement,\n Suspense,\n useCallback,\n useEffect,\n useMemo,\n useState,\n} from 'react';\nimport {\n Button,\n PageHeader,\n Section,\n SectionGroup,\n Table,\n Typography,\n} from '@mezzanine-ui/react';\nimport ContentHeader from '@mezzanine-ui/react/ContentHeader';\nimport { CheckedIcon } from '@mezzanine-ui/icons';\nimport type { TableActions, TableColumn } from '@mezzanine-ui/core/table';\nimport { FormFieldDefinition } from '@rytass/bpm-core-shared/form';\nimport {\n buildFormRendererValues,\n focusFormRendererField,\n FormRendererValues,\n readFormDataSourceErrorMessage,\n validateFormRendererValues,\n} from '@rytass/bpm-core-client/form';\nimport {\n LaunchContext,\n LaunchableTemplateRecord,\n listLaunchableTemplates,\n readFormDataCaseTitle,\n readLaunchContext,\n submitApprovalInstance,\n uploadAttachment,\n} from '@rytass/bpm-core-client/workflow';\nimport {\n readApplicantFormSchema,\n readApplicantSubmission,\n} from '../approver-filled-form';\nimport { formatDateTime } from '../../../lib/format-date-time';\nimport { useAuth } from '../../../lib/auth-provider';\nimport { useRouterAdapter } from '../../../lib/router-adapter';\nimport { useBPMRoutes } from '../../../lib/routes-config';\nimport { FormRenderer } from '../../forms/renderer/FormRendererView';\nimport {\n readFormDataSourceSubmissionBlockMessage,\n type FormDataSourceFieldState,\n} from '../../forms/renderer/form-data-source-field';\n\nconst FORM_SECTION_STYLE: CSSProperties = {\n display: 'grid',\n gap: 16,\n};\n\ntype LaunchableTemplateRow = Readonly<\n Record<string, unknown> &\n LaunchableTemplateRecord & {\n key: string;\n versionLabel: string;\n }\n>;\n\nexport interface InstanceNewViewProps {\n /**\n * Optional template id pre-selected by the host. The Server Component\n * page should read `?templateId=` from its `searchParams` and pass the\n * value through this prop.\n */\n readonly templateId?: string | null;\n}\n\n/**\n * Framework-agnostic view for the BPM \"發起簽核\" launch page. Mechanical port\n * of `apps/client/src/app/instances/new/page.tsx` — picks a launchable\n * template and submits the launch form.\n */\nexport function InstanceNewView(\n props: InstanceNewViewProps = {},\n): ReactElement {\n return (\n <Suspense fallback={<NewApprovalInstanceLoading />}>\n <NewApprovalInstanceContent templateId={props.templateId ?? undefined} />\n </Suspense>\n );\n}\n\nfunction NewApprovalInstanceContent({\n templateId: templateIdProp,\n}: {\n readonly templateId?: string;\n}): ReactElement {\n const router = useRouterAdapter();\n const routes = useBPMRoutes();\n const { member } = useAuth();\n const currentMemberId = member?.memberId ?? null;\n const templateId = templateIdProp ?? null;\n const [context, setContext] = useState<LaunchContext | null>(null);\n const [formValues, setFormValues] = useState<FormRendererValues>({});\n const [templates, setTemplates] = useState<\n readonly LaunchableTemplateRecord[]\n >([]);\n const [error, setError] = useState<string | null>(null);\n const [formErrors, setFormErrors] = useState<\n Readonly<Record<string, string>>\n >({});\n const [loading, setLoading] = useState(true);\n const [submitting, setSubmitting] = useState(false);\n const [dataSourceStates, setDataSourceStates] = useState<\n Readonly<\n Record<string, Pick<FormDataSourceFieldState, 'hasValue' | 'status'>>\n >\n >({});\n\n // The form the applicant sees: approver-filled fields are not theirs to fill\n // (the server drops them), so they are left out of everything below.\n const applicantSchema = useMemo(\n () =>\n context\n ? readApplicantFormSchema(\n context.formVersion.schema,\n context.templateVersion.workflowDefinition,\n )\n : null,\n [context],\n );\n\n const handleDataSourceStateChange = useCallback(\n (\n fieldKey: string,\n state: Pick<\n FormDataSourceFieldState,\n 'hasValue' | 'invalidValues' | 'status'\n >,\n ): void => {\n setDataSourceStates((currentStates) => {\n const currentState = currentStates[fieldKey];\n\n if (\n currentState?.hasValue === state.hasValue &&\n currentState.status === state.status\n ) {\n return currentStates;\n }\n\n return {\n ...currentStates,\n [fieldKey]: {\n hasValue: state.hasValue,\n status: state.status,\n },\n };\n });\n },\n [],\n );\n\n useEffect((): void => {\n if (!templateId) {\n void refreshTemplates();\n\n return;\n }\n\n void refreshContext(templateId);\n }, [templateId]);\n\n const rows = useMemo(\n (): LaunchableTemplateRow[] =>\n templates.map((template) => ({\n ...template,\n key: template.id,\n updatedAt: formatDateTime(template.updatedAt),\n versionLabel: `v${template.version}`,\n })),\n [templates],\n );\n const columns = useMemo(\n (): TableColumn<LaunchableTemplateRow>[] => [\n { dataIndex: 'name', key: 'name', title: '模板名稱', width: 240 },\n {\n dataIndex: 'versionLabel',\n key: 'versionLabel',\n title: '發布版本',\n width: 120,\n },\n {\n dataIndex: 'updatedAt',\n key: 'updatedAt',\n title: '更新時間',\n width: 220,\n },\n ],\n [],\n );\n const tableActions = useMemo(\n (): TableActions<LaunchableTemplateRow> => ({\n render: (\n record,\n ): ReturnType<TableActions<LaunchableTemplateRow>['render']> => [\n {\n name: '發起',\n onClick: (): void =>\n router.push(routes.caseNew(record.id)),\n variant: 'base-primary',\n },\n ],\n variant: 'base-secondary',\n width: 88,\n }),\n [router],\n );\n\n async function refreshTemplates(): Promise<void> {\n setLoading(true);\n setError(null);\n setContext(null);\n setDataSourceStates({});\n\n try {\n setTemplates(await listLaunchableTemplates());\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setLoading(false);\n }\n }\n\n async function refreshContext(nextTemplateId: string): Promise<void> {\n setLoading(true);\n setError(null);\n setTemplates([]);\n setDataSourceStates({});\n\n try {\n setContext(await readLaunchContext(nextTemplateId));\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setLoading(false);\n }\n }\n\n async function handleSubmit(): Promise<void> {\n if (!context || !applicantSchema || !currentMemberId) {\n return;\n }\n\n setSubmitting(true);\n setError(null);\n setFormErrors({});\n\n const dataSourceBlockMessage = readFormDataSourceSubmissionBlockMessage(\n Object.values(dataSourceStates),\n );\n\n if (dataSourceBlockMessage) {\n setError(dataSourceBlockMessage);\n setSubmitting(false);\n\n return;\n }\n\n // What the renderer shows, not just what has been touched: a table seeds\n // its `minRows` rows and a field can carry a `defaultValue`, and neither\n // reaches this state until the filler edits something. Validating and\n // submitting the raw state would reject a table the user can plainly see\n // rows in — and submit a default the backend never receives.\n const submittedValues = readApplicantSubmission(\n buildFormRendererValues(applicantSchema.fields, formValues),\n context.templateVersion.workflowDefinition,\n );\n const validation = validateFormRendererValues({\n schema: applicantSchema,\n uiSchema: context.formVersion.uiSchema,\n values: submittedValues,\n });\n\n if (!validation.valid) {\n setFormErrors(validation.errors);\n setError('請先補齊必填欄位。');\n\n if (validation.firstInvalidFieldKey) {\n focusFormRendererField(validation.firstInvalidFieldKey);\n }\n\n setSubmitting(false);\n\n return;\n }\n\n try {\n const instanceId = await submitApprovalInstance({\n formData: submittedValues,\n initiatorMemberId: currentMemberId,\n templateId: context.template.id,\n title: readFormDataCaseTitle({\n fallbackTitle: context.template.name,\n formData: submittedValues,\n schema: applicantSchema,\n uiSchema: context.formVersion.uiSchema,\n }),\n });\n\n router.push(routes.caseDetail(instanceId));\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setSubmitting(false);\n }\n }\n\n async function handleUploadAttachment(\n field: FormFieldDefinition,\n file: File,\n ): Promise<{ readonly id: string }> {\n if (!currentMemberId) {\n throw new Error('尚未登入,無法上傳附件');\n }\n\n const attachment = await uploadAttachment({\n file,\n formFieldPath: `form.${field.fieldKey}`,\n });\n\n return { id: attachment.id };\n }\n\n return (\n <>\n <PageHeader>\n <ContentHeader\n description={\n context\n ? `${context.template.name} · 表單 v${context.formVersion.version}`\n : '選擇可發起的已發布模板後填寫表單內容。'\n }\n title=\"發起簽核\"\n >\n {context ? (\n <Button\n disabled={loading || submitting}\n icon={CheckedIcon}\n iconType=\"leading\"\n onClick={handleSubmit}\n variant=\"base-primary\"\n >\n 送出\n </Button>\n ) : null}\n </ContentHeader>\n </PageHeader>\n\n <SectionGroup>\n <Section>\n <div style={FORM_SECTION_STYLE}>\n {error ? (\n <Typography color=\"text-error\" variant=\"body\">\n {error}\n </Typography>\n ) : null}\n\n {loading ? (\n <Typography color=\"text-neutral\" variant=\"body\">\n 載入中...\n </Typography>\n ) : null}\n\n {context && applicantSchema ? (\n <FormRenderer\n dataSourceContext={{\n kind: 'runtime',\n templateId: context.template.id,\n }}\n errors={formErrors}\n maxWidth={480}\n onChange={(values): void => {\n setFormValues(values);\n setFormErrors({});\n }}\n onDataSourceStateChange={handleDataSourceStateChange}\n onUploadAttachment={handleUploadAttachment}\n schema={applicantSchema}\n singleColumn\n uiSchema={context.formVersion.uiSchema}\n value={formValues}\n />\n ) : null}\n\n {!templateId && !loading ? (\n rows.length > 0 ? (\n <Table\n actions={tableActions}\n columns={columns}\n dataSource={rows}\n fullWidth\n />\n ) : (\n <Typography color=\"text-neutral\" variant=\"body\">\n 目前沒有可發起的已發布模板。\n </Typography>\n )\n ) : null}\n </div>\n </Section>\n </SectionGroup>\n </>\n );\n}\n\nfunction NewApprovalInstanceLoading(): ReactElement {\n return (\n <>\n <PageHeader>\n <ContentHeader\n description=\"選擇可發起的已發布模板後填寫表單內容。\"\n title=\"發起簽核\"\n />\n </PageHeader>\n\n <SectionGroup>\n <Section>\n <Typography color=\"text-neutral\" variant=\"body\">\n 載入中...\n </Typography>\n </Section>\n </SectionGroup>\n </>\n );\n}\n\nfunction readErrorMessage(error: unknown): string {\n // DataSource failures arrive as stable codes so the backend never leaks\n // upstream transport detail; translate them instead of showing the raw code.\n const dataSourceMessage = readFormDataSourceErrorMessage(error);\n\n if (dataSourceMessage) {\n return dataSourceMessage;\n }\n\n return error instanceof Error ? error.message : '發生未知錯誤';\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":["Suspense","useRouterAdapter","useBPMRoutes","useAuth","useState","useMemo","readApplicantFormSchema","useCallback","formatDateTime","listLaunchableTemplates","readLaunchContext","readFormDataSourceSubmissionBlockMessage","readApplicantSubmission","buildFormRendererValues","validateFormRendererValuesInWorker","submitApprovalInstance","readFormDataCaseTitle","uploadAttachment","_Fragment","PageHeader","ContentHeader","Button","CheckedIcon","SectionGroup","Section","Typography","FormRenderer","Table","readFormDataSourceErrorMessage","require_rolldown_runtime","require_router_adapter","require_auth_provider","require_format_date_time","require_routes_config","require_approver_filled_form","require_FormRendererView","react","_mezzanine_ui_react","react_jsx_runtime","_rytass_bpm_core_client_workflow","_mezzanine_ui_react_ContentHeader","_mezzanine_ui_icons","_rytass_bpm_core_client_form","FORM_SECTION_STYLE","InstanceNewView","NewApprovalInstanceLoading","NewApprovalInstanceContent","props","templateIdProp","router","routes","currentMemberId","member","templateId","context","setContext","formValues","setFormValues","templates","setTemplates","error","setError","formErrors","setFormErrors","loading","setLoading","submitting","setSubmitting","dataSourceStates","setDataSourceStates","applicantSchema","handleDataSourceStateChange","currentState","currentStates","fieldKey","state","refreshContext","refreshTemplates","rows","template","columns","tableActions","record","requestError","readErrorMessage","nextTemplateId","handleSubmit","dataSourceBlockMessage","submittedValues","validation","instanceId","handleUploadAttachment","field","values"],"sources":["../../../../src/views/instances/new/InstanceNewView.tsx"],"sourcesContent":["'use client';\n\nimport {\n CSSProperties,\n ReactElement,\n Suspense,\n useCallback,\n useEffect,\n useMemo,\n useState,\n} from 'react';\nimport {\n Button,\n PageHeader,\n Section,\n SectionGroup,\n Table,\n Typography,\n} from '@mezzanine-ui/react';\nimport ContentHeader from '@mezzanine-ui/react/ContentHeader';\nimport { CheckedIcon } from '@mezzanine-ui/icons';\nimport type { TableActions, TableColumn } from '@mezzanine-ui/core/table';\nimport { FormFieldDefinition } from '@rytass/bpm-core-shared/form';\nimport {\n buildFormRendererValues,\n focusFormRendererField,\n FormRendererValues,\n readFormDataSourceErrorMessage,\n validateFormRendererValuesInWorker,\n} from '@rytass/bpm-core-client/form';\nimport {\n LaunchContext,\n LaunchableTemplateRecord,\n listLaunchableTemplates,\n readFormDataCaseTitle,\n readLaunchContext,\n submitApprovalInstance,\n uploadAttachment,\n} from '@rytass/bpm-core-client/workflow';\nimport {\n readApplicantFormSchema,\n readApplicantSubmission,\n} from '../approver-filled-form';\nimport { formatDateTime } from '../../../lib/format-date-time';\nimport { useAuth } from '../../../lib/auth-provider';\nimport { useRouterAdapter } from '../../../lib/router-adapter';\nimport { useBPMRoutes } from '../../../lib/routes-config';\nimport { FormRenderer } from '../../forms/renderer/FormRendererView';\nimport {\n readFormDataSourceSubmissionBlockMessage,\n type FormDataSourceFieldState,\n} from '../../forms/renderer/form-data-source-field';\n\nconst FORM_SECTION_STYLE: CSSProperties = {\n display: 'grid',\n gap: 16,\n};\n\ntype LaunchableTemplateRow = Readonly<\n Record<string, unknown> &\n LaunchableTemplateRecord & {\n key: string;\n versionLabel: string;\n }\n>;\n\nexport interface InstanceNewViewProps {\n /**\n * Optional template id pre-selected by the host. The Server Component\n * page should read `?templateId=` from its `searchParams` and pass the\n * value through this prop.\n */\n readonly templateId?: string | null;\n}\n\n/**\n * Framework-agnostic view for the BPM \"發起簽核\" launch page. Mechanical port\n * of `apps/client/src/app/instances/new/page.tsx` — picks a launchable\n * template and submits the launch form.\n */\nexport function InstanceNewView(\n props: InstanceNewViewProps = {},\n): ReactElement {\n return (\n <Suspense fallback={<NewApprovalInstanceLoading />}>\n <NewApprovalInstanceContent templateId={props.templateId ?? undefined} />\n </Suspense>\n );\n}\n\nfunction NewApprovalInstanceContent({\n templateId: templateIdProp,\n}: {\n readonly templateId?: string;\n}): ReactElement {\n const router = useRouterAdapter();\n const routes = useBPMRoutes();\n const { member } = useAuth();\n const currentMemberId = member?.memberId ?? null;\n const templateId = templateIdProp ?? null;\n const [context, setContext] = useState<LaunchContext | null>(null);\n const [formValues, setFormValues] = useState<FormRendererValues>({});\n const [templates, setTemplates] = useState<\n readonly LaunchableTemplateRecord[]\n >([]);\n const [error, setError] = useState<string | null>(null);\n const [formErrors, setFormErrors] = useState<\n Readonly<Record<string, string>>\n >({});\n const [loading, setLoading] = useState(true);\n const [submitting, setSubmitting] = useState(false);\n const [dataSourceStates, setDataSourceStates] = useState<\n Readonly<\n Record<string, Pick<FormDataSourceFieldState, 'hasValue' | 'status'>>\n >\n >({});\n\n // The form the applicant sees: approver-filled fields are not theirs to fill\n // (the server drops them), so they are left out of everything below.\n const applicantSchema = useMemo(\n () =>\n context\n ? readApplicantFormSchema(\n context.formVersion.schema,\n context.templateVersion.workflowDefinition,\n )\n : null,\n [context],\n );\n\n const handleDataSourceStateChange = useCallback(\n (\n fieldKey: string,\n state: Pick<\n FormDataSourceFieldState,\n 'hasValue' | 'invalidValues' | 'status'\n >,\n ): void => {\n setDataSourceStates((currentStates) => {\n const currentState = currentStates[fieldKey];\n\n if (\n currentState?.hasValue === state.hasValue &&\n currentState.status === state.status\n ) {\n return currentStates;\n }\n\n return {\n ...currentStates,\n [fieldKey]: {\n hasValue: state.hasValue,\n status: state.status,\n },\n };\n });\n },\n [],\n );\n\n useEffect((): void => {\n if (!templateId) {\n void refreshTemplates();\n\n return;\n }\n\n void refreshContext(templateId);\n }, [templateId]);\n\n const rows = useMemo(\n (): LaunchableTemplateRow[] =>\n templates.map((template) => ({\n ...template,\n key: template.id,\n updatedAt: formatDateTime(template.updatedAt),\n versionLabel: `v${template.version}`,\n })),\n [templates],\n );\n const columns = useMemo(\n (): TableColumn<LaunchableTemplateRow>[] => [\n { dataIndex: 'name', key: 'name', title: '模板名稱', width: 240 },\n {\n dataIndex: 'versionLabel',\n key: 'versionLabel',\n title: '發布版本',\n width: 120,\n },\n {\n dataIndex: 'updatedAt',\n key: 'updatedAt',\n title: '更新時間',\n width: 220,\n },\n ],\n [],\n );\n const tableActions = useMemo(\n (): TableActions<LaunchableTemplateRow> => ({\n render: (\n record,\n ): ReturnType<TableActions<LaunchableTemplateRow>['render']> => [\n {\n name: '發起',\n onClick: (): void =>\n router.push(routes.caseNew(record.id)),\n variant: 'base-primary',\n },\n ],\n variant: 'base-secondary',\n width: 88,\n }),\n [router],\n );\n\n async function refreshTemplates(): Promise<void> {\n setLoading(true);\n setError(null);\n setContext(null);\n setDataSourceStates({});\n\n try {\n setTemplates(await listLaunchableTemplates());\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setLoading(false);\n }\n }\n\n async function refreshContext(nextTemplateId: string): Promise<void> {\n setLoading(true);\n setError(null);\n setTemplates([]);\n setDataSourceStates({});\n\n try {\n setContext(await readLaunchContext(nextTemplateId));\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setLoading(false);\n }\n }\n\n async function handleSubmit(): Promise<void> {\n if (!context || !applicantSchema || !currentMemberId) {\n return;\n }\n\n setSubmitting(true);\n setError(null);\n setFormErrors({});\n\n const dataSourceBlockMessage = readFormDataSourceSubmissionBlockMessage(\n Object.values(dataSourceStates),\n );\n\n if (dataSourceBlockMessage) {\n setError(dataSourceBlockMessage);\n setSubmitting(false);\n\n return;\n }\n\n // What the renderer shows, not just what has been touched: a table seeds\n // its `minRows` rows and a field can carry a `defaultValue`, and neither\n // reaches this state until the filler edits something. Validating and\n // submitting the raw state would reject a table the user can plainly see\n // rows in — and submit a default the backend never receives.\n const submittedValues = readApplicantSubmission(\n buildFormRendererValues(applicantSchema.fields, formValues),\n context.templateVersion.workflowDefinition,\n );\n // Inside the `try`, so a validation that throws still clears `submitting`\n // and shows its error instead of leaving the button busy for good.\n try {\n // The format patterns run in a worker under the engine's time budget, so\n // a pattern that backtracks cannot freeze the page.\n const validation = await validateFormRendererValuesInWorker({\n schema: applicantSchema,\n uiSchema: context.formVersion.uiSchema,\n values: submittedValues,\n });\n\n if (!validation.valid) {\n setFormErrors(validation.errors);\n setError('請先修正表單中標示的欄位。');\n\n if (validation.firstInvalidFieldKey) {\n focusFormRendererField(validation.firstInvalidFieldKey);\n }\n\n return;\n }\n\n const instanceId = await submitApprovalInstance({\n formData: submittedValues,\n initiatorMemberId: currentMemberId,\n templateId: context.template.id,\n title: readFormDataCaseTitle({\n fallbackTitle: context.template.name,\n formData: submittedValues,\n schema: applicantSchema,\n uiSchema: context.formVersion.uiSchema,\n }),\n });\n\n router.push(routes.caseDetail(instanceId));\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setSubmitting(false);\n }\n }\n\n async function handleUploadAttachment(\n field: FormFieldDefinition,\n file: File,\n ): Promise<{ readonly id: string }> {\n if (!currentMemberId) {\n throw new Error('尚未登入,無法上傳附件');\n }\n\n const attachment = await uploadAttachment({\n file,\n formFieldPath: `form.${field.fieldKey}`,\n });\n\n return { id: attachment.id };\n }\n\n return (\n <>\n <PageHeader>\n <ContentHeader\n description={\n context\n ? `${context.template.name} · 表單 v${context.formVersion.version}`\n : '選擇可發起的已發布模板後填寫表單內容。'\n }\n title=\"發起簽核\"\n >\n {context ? (\n <Button\n disabled={loading || submitting}\n icon={CheckedIcon}\n iconType=\"leading\"\n onClick={handleSubmit}\n variant=\"base-primary\"\n >\n 送出\n </Button>\n ) : null}\n </ContentHeader>\n </PageHeader>\n\n <SectionGroup>\n <Section>\n <div style={FORM_SECTION_STYLE}>\n {error ? (\n <Typography color=\"text-error\" variant=\"body\">\n {error}\n </Typography>\n ) : null}\n\n {loading ? (\n <Typography color=\"text-neutral\" variant=\"body\">\n 載入中...\n </Typography>\n ) : null}\n\n {context && applicantSchema ? (\n <FormRenderer\n dataSourceContext={{\n kind: 'runtime',\n templateId: context.template.id,\n }}\n errors={formErrors}\n maxWidth={480}\n onChange={(values): void => {\n setFormValues(values);\n setFormErrors({});\n }}\n onDataSourceStateChange={handleDataSourceStateChange}\n onUploadAttachment={handleUploadAttachment}\n schema={applicantSchema}\n singleColumn\n uiSchema={context.formVersion.uiSchema}\n value={formValues}\n />\n ) : null}\n\n {!templateId && !loading ? (\n rows.length > 0 ? (\n <Table\n actions={tableActions}\n columns={columns}\n dataSource={rows}\n fullWidth\n />\n ) : (\n <Typography color=\"text-neutral\" variant=\"body\">\n 目前沒有可發起的已發布模板。\n </Typography>\n )\n ) : null}\n </div>\n </Section>\n </SectionGroup>\n </>\n );\n}\n\nfunction NewApprovalInstanceLoading(): ReactElement {\n return (\n <>\n <PageHeader>\n <ContentHeader\n description=\"選擇可發起的已發布模板後填寫表單內容。\"\n title=\"發起簽核\"\n />\n </PageHeader>\n\n <SectionGroup>\n <Section>\n <Typography color=\"text-neutral\" variant=\"body\">\n 載入中...\n </Typography>\n </Section>\n </SectionGroup>\n </>\n );\n}\n\nfunction readErrorMessage(error: unknown): string {\n // DataSource failures arrive as stable codes so the backend never leaks\n // upstream transport detail; translate them instead of showing the raw code.\n const dataSourceMessage = readFormDataSourceErrorMessage(error);\n\n if (dataSourceMessage) {\n return dataSourceMessage;\n }\n\n return error instanceof Error ? error.message : '發生未知錯誤';\n}\n"],"mappings":"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"}
@@ -3,7 +3,7 @@ import { r as e } from "../../../chunks/router-adapter-DftlFTOd.js";
3
3
  import { n as t } from "../../../chunks/auth-provider-B5oPmvk2.js";
4
4
  import { t as n } from "../../../chunks/format-date-time-CB-LxzqT.js";
5
5
  import { r } from "../../../chunks/routes-config-yZbESPlw.js";
6
- import { n as i, r as a } from "../../../chunks/approver-filled-form-DuQGPtNB.js";
6
+ import { n as i, r as a } from "../../../chunks/approver-filled-form-ZEwpmsHJ.js";
7
7
  import { o, t as s } from "../../../chunks/FormRendererView-BsTwZkqU.js";
8
8
  import { Suspense as c, useCallback as ee, useEffect as l, useMemo as u, useState as d } from "react";
9
9
  import { Button as f, PageHeader as p, Section as m, SectionGroup as h, Table as te, Typography as g } from "@mezzanine-ui/react";
@@ -11,7 +11,7 @@ import { Fragment as _, jsx as v, jsxs as y } from "react/jsx-runtime";
11
11
  import { listLaunchableTemplates as b, readFormDataCaseTitle as x, readLaunchContext as S, submitApprovalInstance as C, uploadAttachment as w } from "@rytass/bpm-core-client/workflow";
12
12
  import T from "@mezzanine-ui/react/ContentHeader";
13
13
  import { CheckedIcon as E } from "@mezzanine-ui/icons";
14
- import { buildFormRendererValues as D, focusFormRendererField as O, readFormDataSourceErrorMessage as k, validateFormRendererValues as ne } from "@rytass/bpm-core-client/form";
14
+ import { buildFormRendererValues as D, focusFormRendererField as O, readFormDataSourceErrorMessage as k, validateFormRendererValuesInWorker as ne } from "@rytass/bpm-core-client/form";
15
15
  //#region src/views/instances/new/InstanceNewView.tsx
16
16
  var re = {
17
17
  display: "grid",
@@ -100,14 +100,18 @@ function j({ templateId: c }) {
100
100
  H(e), J(!1);
101
101
  return;
102
102
  }
103
- let t = a(D(Z.fields, L), F.templateVersion.workflowDefinition), n = ne({
104
- schema: Z,
105
- uiSchema: F.formVersion.uiSchema,
106
- values: t
107
- });
108
- if (!n.valid) W(n.errors), H("請先補齊必填欄位。"), n.firstInvalidFieldKey && O(n.firstInvalidFieldKey), J(!1);
109
- else try {
110
- let e = await C({
103
+ let t = a(D(Z.fields, L), F.templateVersion.workflowDefinition);
104
+ try {
105
+ let e = await ne({
106
+ schema: Z,
107
+ uiSchema: F.formVersion.uiSchema,
108
+ values: t
109
+ });
110
+ if (!e.valid) {
111
+ W(e.errors), H("請先修正表單中標示的欄位。"), e.firstInvalidFieldKey && O(e.firstInvalidFieldKey);
112
+ return;
113
+ }
114
+ let n = await C({
111
115
  formData: t,
112
116
  initiatorMemberId: M,
113
117
  templateId: F.template.id,
@@ -118,7 +122,7 @@ function j({ templateId: c }) {
118
122
  uiSchema: F.formVersion.uiSchema
119
123
  })
120
124
  });
121
- k.push(A.caseDetail(e));
125
+ k.push(A.caseDetail(n));
122
126
  } catch (e) {
123
127
  H(N(e));
124
128
  } finally {
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["_Fragment","useRouterAdapter","useAuth","formatDateTime","readApplicantFormSchema","readApplicantSubmission","FormRenderer","Fragment$1","ContentHeader","FORM_SECTION_STYLE","InstanceNewView","Suspense","NewApprovalInstanceLoading","NewApprovalInstanceContent","props","templateIdProp","router","routes","useBPMRoutes","currentMemberId","member","templateId","context","setContext","useState","formValues","setFormValues","templates","setTemplates","error","setError","formErrors","setFormErrors","loading","setLoading","submitting","setSubmitting","dataSourceStates","setDataSourceStates","applicantSchema","useMemo","handleDataSourceStateChange","useCallback","currentState","currentStates","fieldKey","state","refreshContext","refreshTemplates","rows","template","columns","tableActions","record","listLaunchableTemplates","requestError","readErrorMessage","readLaunchContext","nextTemplateId","handleSubmit","dataSourceBlockMessage","readFormDataSourceSubmissionBlockMessage","submittedValues","buildFormRendererValues","validation","validateFormRendererValues","focusFormRendererField","instanceId","submitApprovalInstance","readFormDataCaseTitle","handleUploadAttachment","uploadAttachment","field","PageHeader","Button","CheckedIcon","SectionGroup","Section","Typography","values","Table","readFormDataSourceErrorMessage"],"sources":["../../../../src/views/instances/new/InstanceNewView.tsx"],"sourcesContent":["'use client';\n\nimport {\n CSSProperties,\n ReactElement,\n Suspense,\n useCallback,\n useEffect,\n useMemo,\n useState,\n} from 'react';\nimport {\n Button,\n PageHeader,\n Section,\n SectionGroup,\n Table,\n Typography,\n} from '@mezzanine-ui/react';\nimport ContentHeader from '@mezzanine-ui/react/ContentHeader';\nimport { CheckedIcon } from '@mezzanine-ui/icons';\nimport type { TableActions, TableColumn } from '@mezzanine-ui/core/table';\nimport { FormFieldDefinition } from '@rytass/bpm-core-shared/form';\nimport {\n buildFormRendererValues,\n focusFormRendererField,\n FormRendererValues,\n readFormDataSourceErrorMessage,\n validateFormRendererValues,\n} from '@rytass/bpm-core-client/form';\nimport {\n LaunchContext,\n LaunchableTemplateRecord,\n listLaunchableTemplates,\n readFormDataCaseTitle,\n readLaunchContext,\n submitApprovalInstance,\n uploadAttachment,\n} from '@rytass/bpm-core-client/workflow';\nimport {\n readApplicantFormSchema,\n readApplicantSubmission,\n} from '../approver-filled-form';\nimport { formatDateTime } from '../../../lib/format-date-time';\nimport { useAuth } from '../../../lib/auth-provider';\nimport { useRouterAdapter } from '../../../lib/router-adapter';\nimport { useBPMRoutes } from '../../../lib/routes-config';\nimport { FormRenderer } from '../../forms/renderer/FormRendererView';\nimport {\n readFormDataSourceSubmissionBlockMessage,\n type FormDataSourceFieldState,\n} from '../../forms/renderer/form-data-source-field';\n\nconst FORM_SECTION_STYLE: CSSProperties = {\n display: 'grid',\n gap: 16,\n};\n\ntype LaunchableTemplateRow = Readonly<\n Record<string, unknown> &\n LaunchableTemplateRecord & {\n key: string;\n versionLabel: string;\n }\n>;\n\nexport interface InstanceNewViewProps {\n /**\n * Optional template id pre-selected by the host. The Server Component\n * page should read `?templateId=` from its `searchParams` and pass the\n * value through this prop.\n */\n readonly templateId?: string | null;\n}\n\n/**\n * Framework-agnostic view for the BPM \"發起簽核\" launch page. Mechanical port\n * of `apps/client/src/app/instances/new/page.tsx` — picks a launchable\n * template and submits the launch form.\n */\nexport function InstanceNewView(\n props: InstanceNewViewProps = {},\n): ReactElement {\n return (\n <Suspense fallback={<NewApprovalInstanceLoading />}>\n <NewApprovalInstanceContent templateId={props.templateId ?? undefined} />\n </Suspense>\n );\n}\n\nfunction NewApprovalInstanceContent({\n templateId: templateIdProp,\n}: {\n readonly templateId?: string;\n}): ReactElement {\n const router = useRouterAdapter();\n const routes = useBPMRoutes();\n const { member } = useAuth();\n const currentMemberId = member?.memberId ?? null;\n const templateId = templateIdProp ?? null;\n const [context, setContext] = useState<LaunchContext | null>(null);\n const [formValues, setFormValues] = useState<FormRendererValues>({});\n const [templates, setTemplates] = useState<\n readonly LaunchableTemplateRecord[]\n >([]);\n const [error, setError] = useState<string | null>(null);\n const [formErrors, setFormErrors] = useState<\n Readonly<Record<string, string>>\n >({});\n const [loading, setLoading] = useState(true);\n const [submitting, setSubmitting] = useState(false);\n const [dataSourceStates, setDataSourceStates] = useState<\n Readonly<\n Record<string, Pick<FormDataSourceFieldState, 'hasValue' | 'status'>>\n >\n >({});\n\n // The form the applicant sees: approver-filled fields are not theirs to fill\n // (the server drops them), so they are left out of everything below.\n const applicantSchema = useMemo(\n () =>\n context\n ? readApplicantFormSchema(\n context.formVersion.schema,\n context.templateVersion.workflowDefinition,\n )\n : null,\n [context],\n );\n\n const handleDataSourceStateChange = useCallback(\n (\n fieldKey: string,\n state: Pick<\n FormDataSourceFieldState,\n 'hasValue' | 'invalidValues' | 'status'\n >,\n ): void => {\n setDataSourceStates((currentStates) => {\n const currentState = currentStates[fieldKey];\n\n if (\n currentState?.hasValue === state.hasValue &&\n currentState.status === state.status\n ) {\n return currentStates;\n }\n\n return {\n ...currentStates,\n [fieldKey]: {\n hasValue: state.hasValue,\n status: state.status,\n },\n };\n });\n },\n [],\n );\n\n useEffect((): void => {\n if (!templateId) {\n void refreshTemplates();\n\n return;\n }\n\n void refreshContext(templateId);\n }, [templateId]);\n\n const rows = useMemo(\n (): LaunchableTemplateRow[] =>\n templates.map((template) => ({\n ...template,\n key: template.id,\n updatedAt: formatDateTime(template.updatedAt),\n versionLabel: `v${template.version}`,\n })),\n [templates],\n );\n const columns = useMemo(\n (): TableColumn<LaunchableTemplateRow>[] => [\n { dataIndex: 'name', key: 'name', title: '模板名稱', width: 240 },\n {\n dataIndex: 'versionLabel',\n key: 'versionLabel',\n title: '發布版本',\n width: 120,\n },\n {\n dataIndex: 'updatedAt',\n key: 'updatedAt',\n title: '更新時間',\n width: 220,\n },\n ],\n [],\n );\n const tableActions = useMemo(\n (): TableActions<LaunchableTemplateRow> => ({\n render: (\n record,\n ): ReturnType<TableActions<LaunchableTemplateRow>['render']> => [\n {\n name: '發起',\n onClick: (): void =>\n router.push(routes.caseNew(record.id)),\n variant: 'base-primary',\n },\n ],\n variant: 'base-secondary',\n width: 88,\n }),\n [router],\n );\n\n async function refreshTemplates(): Promise<void> {\n setLoading(true);\n setError(null);\n setContext(null);\n setDataSourceStates({});\n\n try {\n setTemplates(await listLaunchableTemplates());\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setLoading(false);\n }\n }\n\n async function refreshContext(nextTemplateId: string): Promise<void> {\n setLoading(true);\n setError(null);\n setTemplates([]);\n setDataSourceStates({});\n\n try {\n setContext(await readLaunchContext(nextTemplateId));\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setLoading(false);\n }\n }\n\n async function handleSubmit(): Promise<void> {\n if (!context || !applicantSchema || !currentMemberId) {\n return;\n }\n\n setSubmitting(true);\n setError(null);\n setFormErrors({});\n\n const dataSourceBlockMessage = readFormDataSourceSubmissionBlockMessage(\n Object.values(dataSourceStates),\n );\n\n if (dataSourceBlockMessage) {\n setError(dataSourceBlockMessage);\n setSubmitting(false);\n\n return;\n }\n\n // What the renderer shows, not just what has been touched: a table seeds\n // its `minRows` rows and a field can carry a `defaultValue`, and neither\n // reaches this state until the filler edits something. Validating and\n // submitting the raw state would reject a table the user can plainly see\n // rows in — and submit a default the backend never receives.\n const submittedValues = readApplicantSubmission(\n buildFormRendererValues(applicantSchema.fields, formValues),\n context.templateVersion.workflowDefinition,\n );\n const validation = validateFormRendererValues({\n schema: applicantSchema,\n uiSchema: context.formVersion.uiSchema,\n values: submittedValues,\n });\n\n if (!validation.valid) {\n setFormErrors(validation.errors);\n setError('請先補齊必填欄位。');\n\n if (validation.firstInvalidFieldKey) {\n focusFormRendererField(validation.firstInvalidFieldKey);\n }\n\n setSubmitting(false);\n\n return;\n }\n\n try {\n const instanceId = await submitApprovalInstance({\n formData: submittedValues,\n initiatorMemberId: currentMemberId,\n templateId: context.template.id,\n title: readFormDataCaseTitle({\n fallbackTitle: context.template.name,\n formData: submittedValues,\n schema: applicantSchema,\n uiSchema: context.formVersion.uiSchema,\n }),\n });\n\n router.push(routes.caseDetail(instanceId));\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setSubmitting(false);\n }\n }\n\n async function handleUploadAttachment(\n field: FormFieldDefinition,\n file: File,\n ): Promise<{ readonly id: string }> {\n if (!currentMemberId) {\n throw new Error('尚未登入,無法上傳附件');\n }\n\n const attachment = await uploadAttachment({\n file,\n formFieldPath: `form.${field.fieldKey}`,\n });\n\n return { id: attachment.id };\n }\n\n return (\n <>\n <PageHeader>\n <ContentHeader\n description={\n context\n ? `${context.template.name} · 表單 v${context.formVersion.version}`\n : '選擇可發起的已發布模板後填寫表單內容。'\n }\n title=\"發起簽核\"\n >\n {context ? (\n <Button\n disabled={loading || submitting}\n icon={CheckedIcon}\n iconType=\"leading\"\n onClick={handleSubmit}\n variant=\"base-primary\"\n >\n 送出\n </Button>\n ) : null}\n </ContentHeader>\n </PageHeader>\n\n <SectionGroup>\n <Section>\n <div style={FORM_SECTION_STYLE}>\n {error ? (\n <Typography color=\"text-error\" variant=\"body\">\n {error}\n </Typography>\n ) : null}\n\n {loading ? (\n <Typography color=\"text-neutral\" variant=\"body\">\n 載入中...\n </Typography>\n ) : null}\n\n {context && applicantSchema ? (\n <FormRenderer\n dataSourceContext={{\n kind: 'runtime',\n templateId: context.template.id,\n }}\n errors={formErrors}\n maxWidth={480}\n onChange={(values): void => {\n setFormValues(values);\n setFormErrors({});\n }}\n onDataSourceStateChange={handleDataSourceStateChange}\n onUploadAttachment={handleUploadAttachment}\n schema={applicantSchema}\n singleColumn\n uiSchema={context.formVersion.uiSchema}\n value={formValues}\n />\n ) : null}\n\n {!templateId && !loading ? (\n rows.length > 0 ? (\n <Table\n actions={tableActions}\n columns={columns}\n dataSource={rows}\n fullWidth\n />\n ) : (\n <Typography color=\"text-neutral\" variant=\"body\">\n 目前沒有可發起的已發布模板。\n </Typography>\n )\n ) : null}\n </div>\n </Section>\n </SectionGroup>\n </>\n );\n}\n\nfunction NewApprovalInstanceLoading(): ReactElement {\n return (\n <>\n <PageHeader>\n <ContentHeader\n description=\"選擇可發起的已發布模板後填寫表單內容。\"\n title=\"發起簽核\"\n />\n </PageHeader>\n\n <SectionGroup>\n <Section>\n <Typography color=\"text-neutral\" variant=\"body\">\n 載入中...\n </Typography>\n </Section>\n </SectionGroup>\n </>\n );\n}\n\nfunction readErrorMessage(error: unknown): string {\n // DataSource failures arrive as stable codes so the backend never leaks\n // upstream transport detail; translate them instead of showing the raw code.\n const dataSourceMessage = readFormDataSourceErrorMessage(error);\n\n if (dataSourceMessage) {\n return dataSourceMessage;\n }\n\n return error instanceof Error ? error.message : '發生未知錯誤';\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["_Fragment","useRouterAdapter","useAuth","formatDateTime","readApplicantFormSchema","readApplicantSubmission","FormRenderer","Fragment$1","ContentHeader","FORM_SECTION_STYLE","InstanceNewView","Suspense","NewApprovalInstanceLoading","NewApprovalInstanceContent","props","templateIdProp","router","routes","useBPMRoutes","currentMemberId","member","templateId","context","setContext","useState","formValues","setFormValues","templates","setTemplates","error","setError","formErrors","setFormErrors","loading","setLoading","submitting","setSubmitting","dataSourceStates","setDataSourceStates","applicantSchema","useMemo","handleDataSourceStateChange","useCallback","currentState","currentStates","fieldKey","state","refreshContext","refreshTemplates","rows","template","columns","tableActions","record","listLaunchableTemplates","requestError","readErrorMessage","readLaunchContext","nextTemplateId","handleSubmit","dataSourceBlockMessage","readFormDataSourceSubmissionBlockMessage","submittedValues","buildFormRendererValues","validation","validateFormRendererValuesInWorker","focusFormRendererField","instanceId","submitApprovalInstance","readFormDataCaseTitle","handleUploadAttachment","uploadAttachment","field","PageHeader","Button","CheckedIcon","SectionGroup","Section","Typography","values","Table","readFormDataSourceErrorMessage"],"sources":["../../../../src/views/instances/new/InstanceNewView.tsx"],"sourcesContent":["'use client';\n\nimport {\n CSSProperties,\n ReactElement,\n Suspense,\n useCallback,\n useEffect,\n useMemo,\n useState,\n} from 'react';\nimport {\n Button,\n PageHeader,\n Section,\n SectionGroup,\n Table,\n Typography,\n} from '@mezzanine-ui/react';\nimport ContentHeader from '@mezzanine-ui/react/ContentHeader';\nimport { CheckedIcon } from '@mezzanine-ui/icons';\nimport type { TableActions, TableColumn } from '@mezzanine-ui/core/table';\nimport { FormFieldDefinition } from '@rytass/bpm-core-shared/form';\nimport {\n buildFormRendererValues,\n focusFormRendererField,\n FormRendererValues,\n readFormDataSourceErrorMessage,\n validateFormRendererValuesInWorker,\n} from '@rytass/bpm-core-client/form';\nimport {\n LaunchContext,\n LaunchableTemplateRecord,\n listLaunchableTemplates,\n readFormDataCaseTitle,\n readLaunchContext,\n submitApprovalInstance,\n uploadAttachment,\n} from '@rytass/bpm-core-client/workflow';\nimport {\n readApplicantFormSchema,\n readApplicantSubmission,\n} from '../approver-filled-form';\nimport { formatDateTime } from '../../../lib/format-date-time';\nimport { useAuth } from '../../../lib/auth-provider';\nimport { useRouterAdapter } from '../../../lib/router-adapter';\nimport { useBPMRoutes } from '../../../lib/routes-config';\nimport { FormRenderer } from '../../forms/renderer/FormRendererView';\nimport {\n readFormDataSourceSubmissionBlockMessage,\n type FormDataSourceFieldState,\n} from '../../forms/renderer/form-data-source-field';\n\nconst FORM_SECTION_STYLE: CSSProperties = {\n display: 'grid',\n gap: 16,\n};\n\ntype LaunchableTemplateRow = Readonly<\n Record<string, unknown> &\n LaunchableTemplateRecord & {\n key: string;\n versionLabel: string;\n }\n>;\n\nexport interface InstanceNewViewProps {\n /**\n * Optional template id pre-selected by the host. The Server Component\n * page should read `?templateId=` from its `searchParams` and pass the\n * value through this prop.\n */\n readonly templateId?: string | null;\n}\n\n/**\n * Framework-agnostic view for the BPM \"發起簽核\" launch page. Mechanical port\n * of `apps/client/src/app/instances/new/page.tsx` — picks a launchable\n * template and submits the launch form.\n */\nexport function InstanceNewView(\n props: InstanceNewViewProps = {},\n): ReactElement {\n return (\n <Suspense fallback={<NewApprovalInstanceLoading />}>\n <NewApprovalInstanceContent templateId={props.templateId ?? undefined} />\n </Suspense>\n );\n}\n\nfunction NewApprovalInstanceContent({\n templateId: templateIdProp,\n}: {\n readonly templateId?: string;\n}): ReactElement {\n const router = useRouterAdapter();\n const routes = useBPMRoutes();\n const { member } = useAuth();\n const currentMemberId = member?.memberId ?? null;\n const templateId = templateIdProp ?? null;\n const [context, setContext] = useState<LaunchContext | null>(null);\n const [formValues, setFormValues] = useState<FormRendererValues>({});\n const [templates, setTemplates] = useState<\n readonly LaunchableTemplateRecord[]\n >([]);\n const [error, setError] = useState<string | null>(null);\n const [formErrors, setFormErrors] = useState<\n Readonly<Record<string, string>>\n >({});\n const [loading, setLoading] = useState(true);\n const [submitting, setSubmitting] = useState(false);\n const [dataSourceStates, setDataSourceStates] = useState<\n Readonly<\n Record<string, Pick<FormDataSourceFieldState, 'hasValue' | 'status'>>\n >\n >({});\n\n // The form the applicant sees: approver-filled fields are not theirs to fill\n // (the server drops them), so they are left out of everything below.\n const applicantSchema = useMemo(\n () =>\n context\n ? readApplicantFormSchema(\n context.formVersion.schema,\n context.templateVersion.workflowDefinition,\n )\n : null,\n [context],\n );\n\n const handleDataSourceStateChange = useCallback(\n (\n fieldKey: string,\n state: Pick<\n FormDataSourceFieldState,\n 'hasValue' | 'invalidValues' | 'status'\n >,\n ): void => {\n setDataSourceStates((currentStates) => {\n const currentState = currentStates[fieldKey];\n\n if (\n currentState?.hasValue === state.hasValue &&\n currentState.status === state.status\n ) {\n return currentStates;\n }\n\n return {\n ...currentStates,\n [fieldKey]: {\n hasValue: state.hasValue,\n status: state.status,\n },\n };\n });\n },\n [],\n );\n\n useEffect((): void => {\n if (!templateId) {\n void refreshTemplates();\n\n return;\n }\n\n void refreshContext(templateId);\n }, [templateId]);\n\n const rows = useMemo(\n (): LaunchableTemplateRow[] =>\n templates.map((template) => ({\n ...template,\n key: template.id,\n updatedAt: formatDateTime(template.updatedAt),\n versionLabel: `v${template.version}`,\n })),\n [templates],\n );\n const columns = useMemo(\n (): TableColumn<LaunchableTemplateRow>[] => [\n { dataIndex: 'name', key: 'name', title: '模板名稱', width: 240 },\n {\n dataIndex: 'versionLabel',\n key: 'versionLabel',\n title: '發布版本',\n width: 120,\n },\n {\n dataIndex: 'updatedAt',\n key: 'updatedAt',\n title: '更新時間',\n width: 220,\n },\n ],\n [],\n );\n const tableActions = useMemo(\n (): TableActions<LaunchableTemplateRow> => ({\n render: (\n record,\n ): ReturnType<TableActions<LaunchableTemplateRow>['render']> => [\n {\n name: '發起',\n onClick: (): void =>\n router.push(routes.caseNew(record.id)),\n variant: 'base-primary',\n },\n ],\n variant: 'base-secondary',\n width: 88,\n }),\n [router],\n );\n\n async function refreshTemplates(): Promise<void> {\n setLoading(true);\n setError(null);\n setContext(null);\n setDataSourceStates({});\n\n try {\n setTemplates(await listLaunchableTemplates());\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setLoading(false);\n }\n }\n\n async function refreshContext(nextTemplateId: string): Promise<void> {\n setLoading(true);\n setError(null);\n setTemplates([]);\n setDataSourceStates({});\n\n try {\n setContext(await readLaunchContext(nextTemplateId));\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setLoading(false);\n }\n }\n\n async function handleSubmit(): Promise<void> {\n if (!context || !applicantSchema || !currentMemberId) {\n return;\n }\n\n setSubmitting(true);\n setError(null);\n setFormErrors({});\n\n const dataSourceBlockMessage = readFormDataSourceSubmissionBlockMessage(\n Object.values(dataSourceStates),\n );\n\n if (dataSourceBlockMessage) {\n setError(dataSourceBlockMessage);\n setSubmitting(false);\n\n return;\n }\n\n // What the renderer shows, not just what has been touched: a table seeds\n // its `minRows` rows and a field can carry a `defaultValue`, and neither\n // reaches this state until the filler edits something. Validating and\n // submitting the raw state would reject a table the user can plainly see\n // rows in — and submit a default the backend never receives.\n const submittedValues = readApplicantSubmission(\n buildFormRendererValues(applicantSchema.fields, formValues),\n context.templateVersion.workflowDefinition,\n );\n // Inside the `try`, so a validation that throws still clears `submitting`\n // and shows its error instead of leaving the button busy for good.\n try {\n // The format patterns run in a worker under the engine's time budget, so\n // a pattern that backtracks cannot freeze the page.\n const validation = await validateFormRendererValuesInWorker({\n schema: applicantSchema,\n uiSchema: context.formVersion.uiSchema,\n values: submittedValues,\n });\n\n if (!validation.valid) {\n setFormErrors(validation.errors);\n setError('請先修正表單中標示的欄位。');\n\n if (validation.firstInvalidFieldKey) {\n focusFormRendererField(validation.firstInvalidFieldKey);\n }\n\n return;\n }\n\n const instanceId = await submitApprovalInstance({\n formData: submittedValues,\n initiatorMemberId: currentMemberId,\n templateId: context.template.id,\n title: readFormDataCaseTitle({\n fallbackTitle: context.template.name,\n formData: submittedValues,\n schema: applicantSchema,\n uiSchema: context.formVersion.uiSchema,\n }),\n });\n\n router.push(routes.caseDetail(instanceId));\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setSubmitting(false);\n }\n }\n\n async function handleUploadAttachment(\n field: FormFieldDefinition,\n file: File,\n ): Promise<{ readonly id: string }> {\n if (!currentMemberId) {\n throw new Error('尚未登入,無法上傳附件');\n }\n\n const attachment = await uploadAttachment({\n file,\n formFieldPath: `form.${field.fieldKey}`,\n });\n\n return { id: attachment.id };\n }\n\n return (\n <>\n <PageHeader>\n <ContentHeader\n description={\n context\n ? `${context.template.name} · 表單 v${context.formVersion.version}`\n : '選擇可發起的已發布模板後填寫表單內容。'\n }\n title=\"發起簽核\"\n >\n {context ? (\n <Button\n disabled={loading || submitting}\n icon={CheckedIcon}\n iconType=\"leading\"\n onClick={handleSubmit}\n variant=\"base-primary\"\n >\n 送出\n </Button>\n ) : null}\n </ContentHeader>\n </PageHeader>\n\n <SectionGroup>\n <Section>\n <div style={FORM_SECTION_STYLE}>\n {error ? (\n <Typography color=\"text-error\" variant=\"body\">\n {error}\n </Typography>\n ) : null}\n\n {loading ? (\n <Typography color=\"text-neutral\" variant=\"body\">\n 載入中...\n </Typography>\n ) : null}\n\n {context && applicantSchema ? (\n <FormRenderer\n dataSourceContext={{\n kind: 'runtime',\n templateId: context.template.id,\n }}\n errors={formErrors}\n maxWidth={480}\n onChange={(values): void => {\n setFormValues(values);\n setFormErrors({});\n }}\n onDataSourceStateChange={handleDataSourceStateChange}\n onUploadAttachment={handleUploadAttachment}\n schema={applicantSchema}\n singleColumn\n uiSchema={context.formVersion.uiSchema}\n value={formValues}\n />\n ) : null}\n\n {!templateId && !loading ? (\n rows.length > 0 ? (\n <Table\n actions={tableActions}\n columns={columns}\n dataSource={rows}\n fullWidth\n />\n ) : (\n <Typography color=\"text-neutral\" variant=\"body\">\n 目前沒有可發起的已發布模板。\n </Typography>\n )\n ) : null}\n </div>\n </Section>\n </SectionGroup>\n </>\n );\n}\n\nfunction NewApprovalInstanceLoading(): ReactElement {\n return (\n <>\n <PageHeader>\n <ContentHeader\n description=\"選擇可發起的已發布模板後填寫表單內容。\"\n title=\"發起簽核\"\n />\n </PageHeader>\n\n <SectionGroup>\n <Section>\n <Typography color=\"text-neutral\" variant=\"body\">\n 載入中...\n </Typography>\n </Section>\n </SectionGroup>\n </>\n );\n}\n\nfunction readErrorMessage(error: unknown): string {\n // DataSource failures arrive as stable codes so the backend never leaks\n // upstream transport detail; translate them instead of showing the raw code.\n const dataSourceMessage = readFormDataSourceErrorMessage(error);\n\n if (dataSourceMessage) {\n return dataSourceMessage;\n }\n\n return error instanceof Error ? error.message : '發生未知錯誤';\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../../../chunks/compose-Cock_B2Q.cjs");exports.EMPTY_COMPOSE_FORM_SCHEMA=e.n,exports.EMPTY_COMPOSE_FORM_UI_SCHEMA=e.r,exports.TemplateComposeWizardView=e.t,exports.useTemplateComposeWizard=e.i;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../../../chunks/compose-DZk-SfHT.cjs");exports.EMPTY_COMPOSE_FORM_SCHEMA=e.n,exports.EMPTY_COMPOSE_FORM_UI_SCHEMA=e.r,exports.TemplateComposeWizardView=e.t,exports.useTemplateComposeWizard=e.i;
@@ -1 +1 @@
1
- export { n as EMPTY_COMPOSE_FORM_SCHEMA, r as EMPTY_COMPOSE_FORM_UI_SCHEMA, t as TemplateComposeWizardView, i as useTemplateComposeWizard } from "../../../chunks/compose-jnvnnVfN.js";
1
+ export { n as EMPTY_COMPOSE_FORM_SCHEMA, r as EMPTY_COMPOSE_FORM_UI_SCHEMA, t as TemplateComposeWizardView, i as useTemplateComposeWizard } from "../../../chunks/compose-B1GlrZW9.js";
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../../../chunks/designer-CAEFV1ve.cjs");exports.TemplateDesignerView=e.t;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../../../chunks/designer-BYYxEN9L.cjs");exports.TemplateDesignerView=e.t;
@@ -1 +1 @@
1
- export { t as TemplateDesignerView } from "../../../chunks/designer-B8Gvew_k.js";
1
+ export { t as TemplateDesignerView } from "../../../chunks/designer-BCLrjb4H.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rytass/bpm-core-react",
3
- "version": "0.17.9",
3
+ "version": "0.18.0",
4
4
  "description": "BPM approval workflow React components and views for the Rytass BPM stack. Ships AuthProvider, NotificationDrawer + bell widget, host-facing hooks (useBPMMember / useBPMLogout / useBPMRoutes), and full page-body views for inbox / instances / templates / forms / admin / settings on top of Mezzanine UI and the BPM client functions. The host owns the navigation shell — BPM does not bundle a layout.",
5
5
  "keywords": [
6
6
  "bpm",
@@ -536,8 +536,8 @@
536
536
  "@mezzanine-ui/core": ">=1.0.0",
537
537
  "@mezzanine-ui/icons": ">=1.0.0",
538
538
  "@mezzanine-ui/react": ">=1.0.0",
539
- "@rytass/bpm-core-client": "^0.17.9",
540
- "@rytass/bpm-core-shared": "^0.17.9",
539
+ "@rytass/bpm-core-client": "^0.18.0",
540
+ "@rytass/bpm-core-shared": "^0.18.0",
541
541
  "@uiw/react-codemirror": ">=4.0.0",
542
542
  "@xyflow/react": ">=12.0.0",
543
543
  "ai": ">=6.0.0",
@@ -1,3 +0,0 @@
1
- "use client";const e=require("./rolldown-runtime-BocRIvOZ.cjs"),t=require("./bpm-form-field-Bc6k4ZEO.cjs"),n=require("./FormRendererView-GpsE03np.cjs");let r=require("react"),i=require("@mezzanine-ui/react"),a=require("react/jsx-runtime"),o=require("@mezzanine-ui/core/form"),s=require("@mezzanine-ui/icons"),c=require("@rytass/bpm-core-client/form"),l=require("@rytass/bpm-core-shared/form"),u=require("@hello-pangea/dnd"),d=require("next/dynamic");d=e.t(d,1);let f=require("@codemirror/lang-json"),p=require("@codemirror/view");var m={alignItems:`center`,border:`1px solid var(--mzn-color-border-neutral)`,borderRadius:4,color:`var(--mzn-color-text-neutral)`,display:`flex`,minHeight:160,padding:12,width:`100%`},h=[(0,f.json)(),p.EditorView.lineWrapping,p.EditorView.theme({"&":{border:`1px solid var(--mzn-color-border-neutral)`,borderRadius:`4px`,fontSize:`13px`,width:`100%`},"&.cm-focused":{outline:`1px solid var(--mzn-color-border-primary)`},".cm-content":{fontFamily:`ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace`,minHeight:`100%`},".cm-editor":{width:`100%`},".cm-gutters":{borderRight:`1px solid var(--mzn-color-border-neutral)`},".cm-scroller":{fontFamily:`ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace`}})],g=(0,d.default)(()=>import(`@uiw/react-codemirror`),{loading:()=>(0,a.jsx)(`div`,{style:m,children:`載入 JSON 編輯器`}),ssr:!1});function ee({disabled:e=!1,height:t,name:n,onChange:r,placeholder:i,value:o}){return(0,a.jsx)(g,{"aria-label":n,basicSetup:{autocompletion:!0,bracketMatching:!0,closeBrackets:!0,defaultKeymap:!0,foldGutter:!0,highlightActiveLine:!0,highlightSelectionMatches:!0,lineNumbers:!0,syntaxHighlighting:!0},editable:!e,extensions:[...h],height:t,indentWithTab:!1,onChange:r,placeholder:i,readOnly:e,theme:`light`,value:o,width:`100%`})}var _=[{description:`單行文字、姓名、編號`,icon:s.AlignLeftIcon,label:`文字`,type:`text`},{description:`多行補充內容`,icon:s.FileIcon,label:`長文字`,type:`textarea`},{description:`金額、數量、分數`,icon:s.CurrencyDollarIcon,label:`數字`,type:`number`},{description:`金額與費用`,icon:s.CurrencyDollarIcon,label:`金額`,type:`money`},{description:`日期或到期日`,icon:s.CalendarIcon,label:`日期`,type:`date`},{description:`日期與時間`,icon:s.CalendarIcon,label:`日期時間`,type:`datetime`},{description:`是 / 否狀態`,icon:s.CheckedIcon,label:`開關`,type:`boolean`},{description:`固定選項擇一`,icon:s.ListIcon,label:`下拉選單`,type:`select`},{description:`可搜尋的固定選項`,icon:s.ListIcon,label:`自動完成`,type:`autocomplete`},{description:`固定選項單選`,icon:s.DotGridIcon,label:`單選`,type:`radio`},{description:`固定選項複選`,icon:s.CheckedOutlineIcon,label:`複選`,type:`checkbox`},{description:`附件或佐證資料`,icon:s.FileAttachmentIcon,label:`附件`,type:`file_upload`},{description:`從成員名單挑選一或多位人員`,icon:s.UserIcon,label:`人員選擇`,type:`member`},{description:`多列多欄明細`,icon:s.DotGridIcon,label:`表格`,type:`table`}],v=_.filter(e=>(0,l.isTableColumnFieldType)(e.type)).map(e=>({id:e.type,name:e.label})),te={alignItems:`start`,display:`flex`,flexWrap:`wrap`,gap:16},ne={flex:`0.55 1 300px`,minWidth:0},re={flex:`1.45 1 720px`,minWidth:620,paddingBottom:260},ie=240,ae={BOOLEAN:`開關`,NUMBER:`數字`,STRING:`文字或選單`,STRING_ARRAY:`多選`},oe=/^schema\.fields\[(\d+)\](?:\.columns\[(\d+)\])?\.dataSource\.bindings missing required parameter: (.+)$/u,se=/^schema\.fields\[(\d+)\](?:\.columns\[(\d+)\])?\.dataSource\.bindings unknown parameter: (.+)$/u,y={display:`grid`,gap:12},ce={display:`flex`,flexWrap:`wrap`,gap:6},le={flex:`0 0 auto`,whiteSpace:`nowrap`},ue={display:`grid`,gap:8},de={alignItems:`center`,cursor:`grab`,display:`flex`,gap:12,touchAction:`none`},fe={display:`grid`,flex:`1 1 auto`,gap:2,minWidth:0},pe={alignItems:`center`,display:`flex`,flex:`0 0 auto`,gap:4},me={alignItems:`center`,display:`flex`,gap:6},he={cursor:`pointer`,userSelect:`none`},ge={filter:`drop-shadow(0 8px 18px rgba(0, 0, 0, 0.12))`},_e={backgroundColor:`color-mix(in srgb, var(--mzn-color-primary) 8%, var(--mzn-color-bg-surface))`,boxShadow:`inset 0 0 0 1px var(--mzn-color-border-primary)`},ve={alignItems:`center`,border:`1px dashed var(--mzn-color-border-neutral)`,borderRadius:6,display:`grid`,gap:12,minHeight:240,padding:32,textAlign:`center`},ye={display:`flex`,gap:8,justifyContent:`center`},be={display:`grid`,gap:14},xe={display:`grid`,columnGap:16,gridTemplateColumns:`repeat(auto-fit, minmax(280px, 360px))`,justifyContent:`start`,maxWidth:736,rowGap:8},Se={gridColumn:`1 / -1`},Ce={alignItems:`center`,display:`flex`,gap:8,gridColumn:`1 / -1`,justifyContent:`flex-end`},b={gridColumn:`1 / -1`},we={alignItems:`start`,display:`block`,width:`100%`},Te={...we,gridColumn:`1 / -1`},Ee={minWidth:0,width:`100%`},De={minWidth:`100%`,width:`100%`},Oe={display:`grid`,gap:14},ke={alignItems:`start`,display:`block`,width:`100%`},Ae={minWidth:0,width:`100%`},je={gridColumn:`2 / -1`},Me={display:`grid`,gap:10,width:`100%`},Ne={display:`grid`,gap:8,gridTemplateColumns:`repeat(auto-fit, minmax(160px, 1fr))`},Pe={display:`inline-flex`},Fe={display:`grid`,gap:16},Ie={display:`grid`,gap:8},Le={display:`flex`,justifyContent:`flex-end`},Re={color:`var(--mzn-color-text-error)`,fontSize:`0.72em`,lineHeight:0,marginLeft:2,verticalAlign:`super`},ze={display:`grid`,gap:10,gridColumn:`1 / -1`},Be={display:`grid`,gap:2},Ve={display:`grid`,gap:8},He={display:`flex`,justifyContent:`flex-start`},Ue={display:`flex`,flexWrap:`wrap`,gap:4},We={backgroundColor:`var(--mzn-color-bg-surface-secondary)`,borderRadius:6,display:`grid`,gap:4,padding:10},Ge={...xe,gridTemplateColumns:`minmax(280px, 520px)`,padding:`4px 0 8px`},Ke={display:`grid`,gap:8,gridColumn:`1 / -1`},qe={alignItems:`center`,display:`flex`,gap:12,justifyContent:`space-between`},Je={alignItems:`baseline`,display:`flex`,gap:2},Ye={display:`grid`,gap:4};function Xe(e){e&&(e.style.width=`100%`)}var Ze={fields:[],schemaVersion:1},Qe={layout:[],schemaVersion:1},x=`__STATIC_OPTIONS__`,S=`__CONSTANT__`,C=`__ROW_FIELD__:`,w=`__UNBOUND__`,$e=[{id:x,name:`靜態選項`}],et=[{id:`single`,name:`單選`},{id:`multiple`,name:`複選`}],tt=[{id:`unset`,name:`不預設`},{id:`true`,name:`是`},{id:`false`,name:`否`}],nt=[{id:`true`,name:`是`},{id:`false`,name:`否`}],rt=[{label:`顯示`,name:`fieldVisibleWhen`,supportingText:`符合條件時才顯示這個欄位。`,target:`visibleWhen`},{label:`必填`,name:`fieldRequiredWhen`,supportingText:`符合條件時才要求填寫這個欄位。`,target:`requiredWhen`},{label:`唯讀`,name:`fieldReadonlyWhen`,supportingText:`符合條件時不允許修改這個欄位。`,target:`readonlyWhen`}];function T({onChange:e,value:d}){let f=d?.schema??Ze,p=d?.uiSchema??Qe,[m,h]=(0,r.useState)(f),[g,T]=(0,r.useState)(p),[ct,D]=(0,r.useState)(A(f)),[pt,j]=(0,r.useState)(A(p)),[St,Ct]=(0,r.useState)({}),[wt,N]=(0,r.useState)(null),[P,Tt]=(0,r.useState)(`design`),[F,I]=(0,r.useState)(null),[L,Et]=(0,r.useState)([]),[R,Dt]=(0,r.useState)(null),[Ot,kt]=(0,r.useState)(`loading`),[z,B]=(0,r.useState)(null),[At,jt]=(0,r.useState)(!1),[V,H]=(0,r.useState)(null),[Mt,U]=(0,r.useState)(null);(0,r.useEffect)(()=>{let e=!0;return(0,c.listFormDataSources)().then(t=>{e&&(Et(t),Dt(null),kt(`ready`))}).catch(t=>{e&&(Et([]),Dt(`目前無法載入 DataSource Catalog,請稍後重試。`),kt(`unavailable`))}),()=>{e=!1}},[]),(0,r.useEffect)(()=>{m.fields.some(e=>e.fieldKey===F)||I(m.fields[0]?.fieldKey??null)},[m.fields,F]),(0,r.useEffect)(()=>{Ct(e=>(0,c.buildFormRendererValues)(m.fields,e))},[m.fields]),(0,r.useEffect)(()=>{P!==`advanced`&&(D(A(m)),j(A(g)))},[P,m,g]);let W=(0,r.useMemo)(()=>m.fields.find(e=>e.fieldKey===F)??m.fields[0]??null,[m.fields,F]);(0,r.useEffect)(()=>{e?.({schema:m,uiSchema:g})},[m,g]);function G(e){let t=m.fields.length+1,n=(0,c.createFieldDefinition)(e,t);h({...m,fields:[...m.fields,n]}),T({...g,layout:[...g.layout,{fieldKey:n.fieldKey,width:e===`textarea`||e===`file_upload`||e===`table`?`FULL`:`HALF`}]}),I(n.fieldKey),Tt(`design`),N(null)}function Nt(e){let t=e;t===`advanced`&&P!==`advanced`&&(D(A(m)),j(A(g))),Tt(t)}function Pt(e){let t=m.fields.flatMap(t=>(0,l.isTableFieldDefinition)(t)?t.columns.flatMap(n=>(0,l.isFormDataSourceFieldDefinition)(n)&&(0,c.readFormDataSourceFieldDependencyKeys)(n).includes(e)?[`${t.fieldKey}.${n.fieldKey}`]:[]):(0,l.isFormDataSourceFieldDefinition)(t)&&(0,c.readFormDataSourceFieldDependencyKeys)(t).includes(e)?[t.fieldKey]:[]);t.length>0?H({affectedFieldKeys:t,fieldKey:e,kind:`remove-field`}):Ft(e)}function Ft(e){let t=m.fields.filter(t=>t.fieldKey!==e);h({...m,fields:t}),T({...g,layout:g.layout.filter(t=>t.fieldKey!==e)}),I(F===e?t[0]?.fieldKey??null:F),N(null),B(null)}function It(e){let t=e.destination;t&&e.source.index!==t.index&&(h(n=>({...n,fields:M(n.fields,e.source.index,t.index)})),T(n=>({...n,layout:M(n.layout,e.source.index,t.index)})),N(null))}function K(e){q(t=>({...t,...e}))}function q(e){if(!W)return;let t=W.fieldKey,n=e(W),r=n.fieldKey,i={...m,fields:m.fields.map(e=>e.fieldKey===t?n:e)},a=t===r?i:(0,c.renameFormDataSourceFieldBindings)(i,t,r);h(a),T({...g,layout:g.layout.map(e=>e.fieldKey===t?{...e,fieldKey:r}:e)}),I(r),N(null),B(null)}function Lt(e){q(()=>e)}function J(e,t){h(n=>({...n,fields:n.fields.map(n=>n.fieldKey===e&&(0,l.isTableFieldDefinition)(n)?t(n):n)})),N(null),B(null)}function Y(e,t,n){let r=e.columns[t]?.fieldKey;J(e.fieldKey,e=>{let i={...e,columns:e.columns.map((e,r)=>r===t?n:e)};return typeof r==`string`&&r!==n.fieldKey?(0,c.renameFormTableColumnBindings)(i,r,n.fieldKey):i})}function Rt(e){let t=(0,c.createTableColumnDefinition)(e.columns,`text`);J(e.fieldKey,e=>({...e,columns:[...e.columns,t]})),U(e.columns.length)}function zt(e,t){J(e,e=>({...e,columns:e.columns.filter((e,n)=>n!==t)})),U(e=>e===null||e<t?e:e===t?null:e-1)}function Bt(e,t,n){J(e.fieldKey,e=>({...e,columns:M(e.columns,t,n)})),U(e=>e===null?e:e===t?n:e>t&&e<=n?e-1:e<t&&e>=n?e+1:e)}function Vt(e,t,n){if(e.type!==`select`&&e.type!==`autocomplete`||(0,l.readFormFieldSelectionMode)(e)===t)return;let r=e.defaultValue,i=t===`multiple`?typeof r==`string`?[r]:r:Array.isArray(r)?r[0]:r;n(e,{...e,defaultValue:i,mode:t},`選擇模式變更可能轉換或捨棄既有預設值。`)}function Ht(e,t,n=`此變更會替換目前選項來源;既有 options、dynamic reference 或 bindings 可能失效。`){JSON.stringify(e)!==JSON.stringify(t)&&H({fieldKey:e.fieldKey,impact:n,kind:`replace-field`,nextField:t})}function Ut(e,t,n){if(!t)return;if(t===x){if(!(0,l.isFormDataSourceFieldDefinition)(e))return;let{dataSource:t,defaultValue:r,...i}=e;n({...i,options:[]});return}let r=L.find(e=>E(e)===t);if(!r)return;if((0,l.isFormDataSourceFieldDefinition)(e)){let t=new Set(r.parameters.map(e=>e.key)),i=e.dataSource.bindings.filter(e=>t.has(e.parameter));n({...e,dataSource:{bindings:i,key:r.key,version:r.version}});return}let{options:i,defaultValue:a,...o}=e;n({...o,dataSource:{bindings:[],key:r.key,version:r.version}})}function Wt(){V&&(Gt(V),H(null))}function Gt(e){e.kind===`remove-field`?Ft(e.fieldKey):e.kind===`remove-column`?zt(e.fieldKey,e.columnIndex):e.kind===`replace-column`?(J(e.fieldKey,t=>({...t,columns:t.columns.map(t=>t.fieldKey===e.columnKey?e.nextColumn:t)})),U(e.columnIndex)):(h({...m,fields:m.fields.map(t=>t.fieldKey===e.fieldKey?e.nextField:t)}),N(null),B(null))}async function Kt(){jt(!0);try{let e=await(0,c.lintFormSchema)(m,g);B(e.errors.map(qt))}catch{B([`目前無法完成 DataSource schema 驗證。`])}finally{jt(!1)}}function qt(e){let t=oe.exec(e);if(t?.[1]&&t[3])return`${Jt(t[1],t[2])}尚未指定必要參數「${Yt(t[1],t[2],t[3])}」的來源`;let n=se.exec(e);return n?.[1]&&n[3]?`${Jt(n[1],n[2])}綁定了來源沒有的參數「${n[3]}」`:(0,c.readFormSchemaLintMessage)(e)}function Jt(e,t){let n=m.fields[Number(e)];if(!n)return``;let r=n.label||n.fieldKey,i=Xt(n,t);return i?`「${r}」表格的「${i.label||i.fieldKey}」欄`:`「${r}」欄位`}function Yt(e,t,n){let r=m.fields[Number(e)];if(!r)return n;let i=Xt(r,t)??r,a=(0,l.isFormDataSourceFieldDefinition)(i)?i.dataSource:null;return(a?L.find(e=>e.key===a.key&&e.version===a.version):void 0)?.parameters.find(e=>e.key===n)?.label||n}function Xt(e,t){return typeof t==`string`&&(0,l.isTableFieldDefinition)(e)?e.columns[Number(t)]:void 0}function Zt(e){Ct(e)}function Qt(e,t){h(n=>({...n,fields:n.fields.map(n=>n.fieldKey===e?{...n,required:t}:n)})),N(null)}function $t(e){D(e);try{h(JSON.parse(e)),N(null)}catch{N(`Form Schema JSON 格式不正確`)}}function en(e){j(e);try{T(JSON.parse(e)),N(null)}catch{N(`UI Schema JSON 格式不正確`)}}return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(a.Fragment,{children:(0,a.jsx)(i.SectionGroup,{children:(0,a.jsx)(i.Section,{children:(0,a.jsxs)(`div`,{style:Fe,children:[(0,a.jsxs)(i.Tab,{activeKey:P,onChange:Nt,size:`sub`,children:[(0,a.jsx)(i.TabItem,{children:`設計`},`design`),(0,a.jsx)(i.TabItem,{children:`預覽`},`preview`),(0,a.jsx)(i.TabItem,{children:`進階`},`advanced`)]}),P===`design`?tn():null,P===`preview`?Vn():null,P===`advanced`?Hn():null]})})})}),V?(0,a.jsx)(i.Modal,{cancelText:`返回`,confirmText:`確認變更`,modalType:`standard`,onCancel:()=>H(null),onClose:()=>H(null),onConfirm:Wt,open:!0,showModalFooter:!0,showModalHeader:!0,title:dt(V),children:V.kind===`remove-field`?(0,a.jsxs)(`div`,{style:Ie,children:[(0,a.jsx)(i.Typography,{variant:`body`,children:`此欄位仍被下列 DataSource binding 使用;移除後請重新設定這些欄位。`}),(0,a.jsx)(i.Typography,{color:`text-warning`,variant:`body`,children:V.affectedFieldKeys.join(`、`)})]}):V.kind===`remove-column`?(0,a.jsxs)(i.Typography,{variant:`body`,children:[`移除欄「`,V.columnKey,`」後,既有案件仍保留原本的表單版本,但新版本的這一欄資料將不再被填寫。`]}):(0,a.jsx)(i.Typography,{variant:`body`,children:V.impact})}):null]});function tn(){return(0,a.jsxs)(`div`,{style:y,children:[(0,a.jsxs)(`div`,{style:ue,children:[(0,a.jsx)(i.Typography,{component:`h2`,variant:`label-primary`,children:`新增欄位`}),(0,a.jsx)(`div`,{style:ce,children:_.map(e=>(0,a.jsx)(i.Button,{icon:e.icon,iconType:`leading`,onClick:()=>G(e.type),size:`sub`,style:le,type:`button`,variant:`base-secondary`,children:e.label},e.type))})]}),(0,a.jsxs)(`div`,{style:te,children:[(0,a.jsxs)(`div`,{style:{...y,...ne},children:[(0,a.jsx)(i.Typography,{component:`h2`,variant:`label-primary`,children:`表單畫布`}),m.fields.length>0?(0,a.jsx)(u.DragDropContext,{onDragEnd:It,children:(0,a.jsx)(u.Droppable,{droppableId:`form-builder-fields`,children:e=>(0,a.jsxs)(`div`,{...e.droppableProps,ref:e.innerRef,style:y,children:[m.fields.map((e,t)=>(0,a.jsx)(u.Draggable,{draggableId:e.fieldKey,index:t,children:(t,n)=>zn(e,t,n.isDragging)},e.fieldKey)),e.placeholder]})})}):(0,a.jsxs)(`div`,{style:ve,children:[(0,a.jsxs)(`div`,{style:y,children:[(0,a.jsx)(i.Typography,{component:`h3`,variant:`h3`,children:`尚未建立欄位`}),(0,a.jsx)(i.Typography,{color:`text-neutral`,variant:`body`,children:`從上方新增第一個欄位,或直接建立常用文字欄位開始設計。`})]}),(0,a.jsxs)(`div`,{style:ye,children:[(0,a.jsx)(i.Button,{onClick:()=>G(`text`),variant:`base-primary`,children:`新增文字欄位`}),(0,a.jsx)(i.Button,{onClick:()=>G(`textarea`),variant:`base-secondary`,children:`新增長文字`})]})]})]}),(0,a.jsxs)(`div`,{style:{...y,...re},children:[(0,a.jsx)(i.Typography,{component:`h2`,variant:`label-primary`,children:`欄位設定`}),W?nn(W):(0,a.jsx)(i.Typography,{color:`text-neutral`,variant:`body`,children:`請先新增或選取欄位。`})]})]})]})}function nn(e){return(0,a.jsxs)(`div`,{style:be,children:[rn(e),(0,l.isTableFieldDefinition)(e)?cn(e):null,an(e)]})}function rn(e){return(0,a.jsxs)(`div`,{style:xe,children:[(0,a.jsx)(`div`,{style:Ce,children:(0,a.jsx)(i.Badge,{size:`main`,text:it(e.type),variant:`text-info`})}),$(`標題`,`fieldLabel`,(0,a.jsx)(i.Input,{onChange:e=>K({label:e.target.value}),placeholder:`例如:申請金額`,value:e.label,variant:`base`})),$(`欄位 Key`,`fieldKey`,(0,a.jsx)(i.Input,{onChange:e=>K({fieldKey:e.target.value}),placeholder:`例如:amount`,value:e.fieldKey,variant:`base`})),(0,l.isTableFieldDefinition)(e)?null:$(`提示文字`,`fieldPlaceholder`,(0,a.jsx)(i.Input,{onChange:e=>K({placeholder:e.target.value||void 0}),placeholder:`例如:請輸入申請金額`,value:e.placeholder??``,variant:`base`})),on(e,Lt,Ht),O(e)?$(`以連結顯示`,`fieldDisplayAsLink`,(0,a.jsx)(i.Toggle,{checked:e.displayAs===`link`,onChange:e=>q(t=>e.target.checked?O(t)?{...t,displayAs:`link`}:t:ht(t,`displayAs`))})):null,$(`只存不顯示(系統整合用)`,`fieldHidden`,(0,a.jsx)(i.Toggle,{checked:e.hidden===!0,onChange:e=>q(t=>e.target.checked?{...t,hidden:!0,required:!1}:ht(t,`hidden`))})),e.hidden===!0?(0,a.jsx)(i.Typography,{color:`text-neutral`,style:b,variant:`body`,children:`填寫、唯讀與重送畫面都不會顯示這個欄位,值仍會存下來; 透過 API 仍然讀得到這個值,不是權限控管。`}):null]})}function an(e){return(0,a.jsx)(i.Accordion,{defaultExpanded:gt(e),size:`sub`,title:`進階設定`,children:(0,a.jsxs)(`div`,{style:xe,children:[(0,a.jsx)(i.Typography,{component:`h3`,style:Se,variant:`label-primary`,children:`條件規則`}),(0,a.jsx)(i.Typography,{color:`text-neutral`,style:b,variant:`body`,children:`只有需要根據其他欄位改變顯示、必填或唯讀狀態時才需要設定。`}),Nn(e)]})})}function on(e,t,n,r){return O(e)?pn(e,t):(0,c.isNumberFieldDefinition)(e)?mn(e,t):(0,c.isDateFieldDefinition)(e)?hn(e,t):(0,l.isFormOptionFieldDefinition)(e)?gn(e,t,n,r):e.type===`boolean`?An(e,t):e.type===`file_upload`?Mn(e,t):(0,l.isMemberFieldDefinition)(e)?jn(e,t):(0,l.isTableFieldDefinition)(e)?sn(e):null}function sn(e){let t=(0,c.readFormTableRowBounds)(e);return(0,a.jsxs)(a.Fragment,{children:[$(`最少列數`,`fieldMinRows`,Q(e.minRows,t=>J(e.fieldKey,e=>({...e,minRows:t})),`例如:1`,{max:t.maxRows,min:0})),$(`最多列數`,`fieldMaxRows`,Q(e.maxRows,t=>J(e.fieldKey,e=>({...e,maxRows:t})),`未設定即為 ${l.FORM_TABLE_MAX_ROWS}`,{max:l.FORM_TABLE_MAX_ROWS,min:Math.max(t.minRows,1)})),$(`新增列按鈕文字`,`fieldAddRowLabel`,(0,a.jsx)(i.Input,{onChange:t=>J(e.fieldKey,e=>({...e,addRowLabel:t.target.value||void 0})),placeholder:`預設為「新增一列」`,value:e.addRowLabel??``,variant:`base`}))]})}function cn(e){return(0,a.jsxs)(`div`,{style:Ke,children:[(0,a.jsxs)(`div`,{style:qe,children:[(0,a.jsxs)(i.Typography,{component:`h3`,variant:`label-primary`,children:[`欄(`,e.columns.length,`)`]}),(0,a.jsx)(i.Button,{icon:s.PlusIcon,iconType:`leading`,onClick:()=>Rt(e),size:`sub`,type:`button`,variant:`base-secondary`,children:`新增欄`})]}),ln(e)]})}function ln(e){let t=e.columns.map((t,n)=>({fieldKey:t.fieldKey,index:n,key:`${e.fieldKey}-column-${n}`,label:t.label,type:t.type})),n=[{key:`label`,render:t=>(0,a.jsx)(i.Input,{fullWidth:!0,onChange:n=>Y(e,t.index,{...X(e,t.index),label:n.target.value}),placeholder:`例如:數量`,size:`sub`,value:t.label,variant:`base`}),title:`標題`},{key:`type`,render:t=>(0,a.jsx)(i.Select,{fullWidth:!0,clearable:!1,menuMaxHeight:ie,onChange:n=>dn(e,t.index,n?.id),options:[...v],size:`sub`,value:(0,c.readSelectOption)(v,t.type)}),title:`型別`},{key:`required`,render:t=>(0,a.jsx)(i.Toggle,{checked:X(e,t.index).required===!0,inputProps:{"aria-label":`${t.label||t.fieldKey} 必填`},onChange:n=>Y(e,t.index,{...X(e,t.index),required:n.target.checked}),size:`sub`}),title:`必填`}],r={render:t=>[{disabled:()=>e.columns.length<=1,icon:s.TrashIcon,iconType:`leading`,name:`移除此欄`,onClick:()=>H({columnIndex:t.index,columnKey:t.fieldKey,fieldKey:e.fieldKey,kind:`remove-column`}),variant:`destructive-ghost`}],width:104},o=Mt===null?void 0:t[Mt]?.key;return(0,a.jsx)(i.Table,{actions:r,columns:n,dataSource:t,draggable:{enabled:!0,onDragEnd:(t,n)=>Bt(e,n.fromIndex,n.toIndex)},expandable:{expandedRowKeys:o?[o]:[],expandedRowRender:t=>un(e,t.index),onExpand:(e,t)=>U(e?t.index:null)},fullWidth:!0,rowHeightPreset:`roomy`,showHeader:!0,size:`sub`})}function un(e,t){let n=e.columns[t];return n?(0,a.jsxs)(`div`,{style:Ge,children:[$(`欄位 Key`,`columnFieldKey`,(0,a.jsx)(i.Input,{onChange:r=>Y(e,t,{...n,fieldKey:r.target.value}),placeholder:`例如:qty`,value:n.fieldKey,variant:`base`})),$(`提示文字`,`columnPlaceholder`,(0,a.jsx)(i.Input,{onChange:r=>Y(e,t,{...n,placeholder:r.target.value||void 0}),placeholder:`例如:請輸入數量`,value:n.placeholder??``,variant:`base`})),on(n,n=>{(0,l.isTableColumnFieldType)(n.type)&&Y(e,t,n)},(n,r)=>{(0,l.isTableColumnFieldType)(r.type)&&Y(e,t,r)},e.columns)]}):null}function dn(e,t,n){let r=e.columns[t],i=v.find(e=>e.id===n)?.id;if(!r||!i||r.type===i)return;let a=mt(r,i),o=ft(r);o.length===0?(Y(e,t,a),U(t)):H({columnIndex:t,columnKey:r.fieldKey,fieldKey:e.fieldKey,impact:`「${r.label||r.fieldKey}」改為${fn(i)}後,這一欄的${o.join(`、`)}會被捨棄。`,kind:`replace-column`,nextColumn:a})}function fn(e){return v.find(t=>t.id===e)?.name??e}function X(e,t){let n=e.columns[t];if(!n)throw Error(`Table ${e.fieldKey} has no column at index ${t}.`);return n}function pn(e,t){return(0,a.jsxs)(a.Fragment,{children:[$(`預設值`,`fieldDefaultValue`,e.type===`textarea`?In({name:`fieldDefaultValue`,onChange:n=>t({...e,defaultValue:n||void 0}),placeholder:`輸入此欄位的預設文字`,rows:3,value:k(e.defaultValue)}):(0,a.jsx)(i.Input,{onChange:n=>t({...e,defaultValue:n.target.value||void 0}),placeholder:`輸入此欄位的預設文字`,value:k(e.defaultValue),variant:`base`})),$(`最小長度`,`fieldMinLength`,Q(e.minLength,n=>t({...e,minLength:n}),`例如:2`,{min:0})),$(`最大長度`,`fieldMaxLength`,Q(e.maxLength,n=>t({...e,maxLength:n}),`例如:100`,{min:1}))]})}function mn(e,t){return(0,a.jsxs)(a.Fragment,{children:[$(`預設值`,`fieldDefaultValue`,Q(typeof e.defaultValue==`number`?e.defaultValue:void 0,n=>t({...e,defaultValue:n}),e.type===`money`?`例如:1000`:`輸入預設數值`,{max:e.maximum,min:e.minimum})),$(`最小值`,`fieldMinimum`,Q(e.minimum,n=>t({...e,minimum:n}),`例如:0`)),$(`最大值`,`fieldMaximum`,Q(e.maximum,n=>t({...e,maximum:n}),`例如:999999`))]})}function hn(e,t){return $(`預設值`,`fieldDefaultValue`,Ln(e,k(e.defaultValue),n=>t({...e,defaultValue:n})))}function gn(e,t,n,r){let o=(0,c.readCompatibleFormDataSourceDescriptors)(e.type,L),s={commit:e=>t(e),rowColumns:r},u=(0,l.isFormDataSourceFieldDefinition)(e)?E(e.dataSource):x,d=(0,l.isFormDataSourceFieldDefinition)(e)?L.find(t=>t.key===e.dataSource.key&&t.version===e.dataSource.version):null,f=d?o.some(e=>e.key===d.key&&e.version===d.version):!1,p=[...$e,...o.map(ot),...(0,l.isFormDataSourceFieldDefinition)(e)&&!f?[{id:u,name:`${e.dataSource.key} v${e.dataSource.version}(目前不可用或不支援)`}]:[]],m=(0,l.readFormFieldSelectionMode)(e);return(0,a.jsxs)(a.Fragment,{children:[e.type===`select`||e.type===`autocomplete`?$(`選擇模式`,`fieldSelectionMode`,(0,a.jsx)(i.Select,{clearable:!1,onChange:t=>{(t?.id===`single`||t?.id===`multiple`)&&Vt(e,t.id,n)},options:[...et],value:(0,c.readSelectOption)(et,m)})):$(`選擇模式`,`fieldSelectionMode`,(0,a.jsx)(i.Typography,{color:`text-neutral`,variant:`body`,children:m===`multiple`?`固定複選`:`固定單選`})),$(`選項來源`,`fieldOptionSource`,(0,a.jsx)(i.Select,{clearable:!1,disabled:Ot===`loading`&&!(0,l.isFormDataSourceFieldDefinition)(e),onChange:n=>Ut(e,n?.id,t),options:p,placeholder:`選擇選項來源`,value:(0,c.readSelectOption)(p,u)})),(0,l.isFormDataSourceFieldDefinition)(e)?_n(e,o,s):kn(e,t)]})}function _n(e,t,n){let r=L.find(t=>t.key===e.dataSource.key&&t.version===e.dataSource.version),o=r&&!(0,c.isFormDataSourceDescriptorCompatible)(r,e.type);return(0,a.jsxs)(`div`,{style:ze,children:[Ot===`loading`?(0,a.jsx)(i.Typography,{color:`text-neutral`,variant:`body`,children:`正在載入可用的選項來源…`}):null,R?(0,a.jsx)(i.Typography,{color:`text-error`,variant:`body`,children:R}):null,r?null:(0,a.jsx)(i.Typography,{color:`text-warning`,variant:`body`,children:`找不到目前設定的來源版本。設定會保留,但這張表單在來源恢復前無法發布。`}),o?(0,a.jsx)(i.Typography,{color:`text-error`,variant:`body`,children:`這個來源不支援目前的控制項,請改選其他來源。`}):null,r?vn(r):null,r&&r.parameters.length>0?yn(e,r,n):null,t.length===0&&!R?(0,a.jsx)(i.Typography,{color:`text-warning`,variant:`body`,children:`沒有支援目前控制項的已註冊來源。`}):null,(0,a.jsx)(`div`,{style:He,children:(0,a.jsx)(i.Button,{disabled:At,loading:At,onClick:()=>void Kt(),size:`sub`,type:`button`,variant:`base-secondary`,children:`檢查全部動態選項設定`})}),z?(0,a.jsx)(`div`,{style:Be,children:z.length>0?z.map(e=>(0,a.jsx)(i.Typography,{color:`text-error`,variant:`caption`,children:e},e)):(0,a.jsx)(i.Typography,{color:`text-success`,variant:`caption`,children:`這張表單的動態選項設定都可以使用。`})}):null]})}function vn(e){return(0,a.jsxs)(`div`,{style:We,children:[e.description?(0,a.jsx)(i.Typography,{variant:`body`,children:e.description}):null,(0,a.jsx)(`div`,{style:Ue,children:at(e).map(e=>(0,a.jsx)(i.Tag,{label:e,readOnly:!0,size:`minor`},e))}),(0,a.jsxs)(i.Typography,{color:`text-neutral`,variant:`caption`,children:[`來源代號:`,e.key,` · v`,e.version]})]})}function yn(e,t,n){let r=t.parameters.map((e,t)=>({key:e.key,index:t,parameter:e}));return(0,a.jsxs)(`div`,{style:Ve,children:[(0,a.jsx)(i.Typography,{color:`text-neutral`,variant:`label-secondary`,children:`這個來源需要的條件`}),(0,a.jsx)(i.Table,{columns:[{key:`parameter`,render:e=>(0,a.jsxs)(`div`,{style:Je,children:[(0,a.jsx)(i.Typography,{variant:`input`,children:e.parameter.label??e.parameter.key}),e.parameter.required?(0,a.jsx)(i.Typography,{color:`text-error`,variant:`input`,children:`*`}):null]}),title:`條件`,width:100},{key:`binding`,width:268,render:t=>xn(e,t.parameter,n),title:`值從哪裡來`},{key:`constant`,width:140,render:t=>(0,c.readFormDataSourceBindingValueKind)((0,c.readFormDataSourceBinding)(e,t.parameter.key))===`CONSTANT`?Tn(e,t.parameter.key,t.parameter.type,(0,c.readFormDataSourceBinding)(e,t.parameter.key),n):(0,a.jsx)(i.Typography,{color:`text-neutral`,variant:`caption`,children:`—`}),title:`固定值`},{key:`meaning`,render:t=>(0,a.jsx)(i.Typography,{color:`text-neutral`,variant:`caption`,children:Cn((0,c.readFormDataSourceBinding)(e,t.parameter.key),t.parameter,n,bn(e,t.parameter,n))}),title:`填寫時的行為`}],dataSource:r,fullWidth:!0,showHeader:!0,size:`sub`})]})}function bn(e,t,n){return(0,c.readCompatibleFormDataSourceBindingFields)(t.type,m.fields,e.fieldKey).length+(n.rowColumns?(0,c.readCompatibleFormTableColumnBindingFields)(t.type,n.rowColumns,e.fieldKey).length:0)}function xn(e,t,n){let r=st((0,c.readFormDataSourceBinding)(e,t.key)),o=n.rowColumns?(0,c.readCompatibleFormTableColumnBindingFields)(t.type,n.rowColumns,e.fieldKey).map(e=>({id:`${C}${e.id}`,name:`同列:${e.name}`})):[],s=[...t.required?[]:[{id:w,name:`未綁定`}],...o,...(0,c.readCompatibleFormDataSourceBindingFields)(t.type,m.fields,e.fieldKey),...t.type===`STRING_ARRAY`?[]:[{id:S,name:`固定常數`}]];return(0,a.jsx)(`div`,{"data-data-source-parameter":t.key,style:Ye,children:(0,a.jsx)(i.Select,{clearable:!1,fullWidth:!0,inputProps:{"aria-label":`${t.label??t.key} 的值來源`,title:(0,c.readSelectOption)(s,r)?.name??``},onChange:r=>Dn(e,t.key,t.type,r?.id,n),options:s,placeholder:`選擇欄位或常數`,size:`sub`,value:(0,c.readSelectOption)(s,r)})})}function Sn(e){return ae[e]}function Cn(e,t,n,r){let i=(0,c.readFormDataSourceBindingValueKind)(e);return i===`CONSTANT`?`固定值,不隨填寫變動`:i===`FIELD`?`隨欄位「${wn(e,n)}」變動`:i===`ROW_FIELD`?`隨同列「${wn(e,n)}」變動`:t.required?r>0?`尚未設定,選項無法載入`:`沒有相容的${Sn(t.type)}欄位,請改用固定值`:`未設定,不做這層篩選`}function wn(e,t){let n=e?.from;if(n?.kind===`FIELD`){let e=m.fields.find(e=>e.fieldKey===n.fieldKey);return e?e.label||e.fieldKey:``}if(n?.kind===`ROW_FIELD`){let e=t.rowColumns?.find(e=>e.fieldKey===n.columnKey);return e?e.label||e.fieldKey:``}return``}function Tn(e,t,n,r,i){return(0,a.jsx)(`div`,{"data-data-source-constant":t,children:En(e,t,n,r,i)})}function En(e,t,n,r,o){let s=(0,c.readFormDataSourceBindingValue)(e,t);if(n===`BOOLEAN`){let n=[{id:`true`,name:`是`},{id:`false`,name:`否`}];return(0,a.jsx)(i.Select,{clearable:!1,fullWidth:!0,onChange:n=>On(e,t,n?.id===`true`,o),options:n,size:`sub`,value:(0,c.readSelectOption)(n,s===!0?`true`:`false`)})}return n===`STRING_ARRAY`?(0,a.jsx)(i.Typography,{color:`text-warning`,variant:`caption`,children:`這個條件要收多個值,請綁定一個複選欄位;不接受固定值。`}):(0,a.jsx)(i.Input,{onChange:r=>On(e,t,n===`NUMBER`?(0,c.parseOptionalNumberInput)(r.target.value)??0:r.target.value,o),placeholder:n===`NUMBER`?`輸入數字`:`輸入固定值`,value:lt(r,n),variant:`base`})}function Dn(e,t,n,r,i){i.commit((0,c.upsertFormDataSourceFieldBinding)(e,t,ut(t,n,r)))}function On(e,t,n,r){r.commit((0,c.upsertFormDataSourceFieldBinding)(e,t,{from:{kind:`CONSTANT`,value:n},parameter:t}))}function kn(e,t){let n=(0,l.readFormFieldSelectionMode)(e),r=Array.isArray(e.defaultValue)?e.defaultValue:[],o=e.options.map(c.readFieldOptionAsSelectOption),s=o.filter(e=>r.includes(e.id));return(0,a.jsxs)(a.Fragment,{children:[$(`預設值`,`fieldDefaultValue`,n===`multiple`?(0,a.jsx)(i.Select,{clearable:!0,mode:`multiple`,onChange:n=>t({...e,defaultValue:n.length?n.map(e=>e.id):void 0}),options:o,placeholder:`選擇一或多個預設選項`,value:s}):(0,a.jsx)(i.Select,{clearable:!0,onChange:n=>t({...e,defaultValue:n?.id||void 0}),options:o,placeholder:`選擇預設選項`,value:typeof e.defaultValue==`string`?(0,c.readSelectOption)(o,e.defaultValue):null})),$(`選項`,`fieldOptions`,Rn(e,t),!0)]})}function An(e,t){let n=typeof e.defaultValue==`boolean`?String(e.defaultValue):`unset`;return $(`預設值`,`fieldDefaultValue`,(0,a.jsx)(i.Select,{clearable:!1,onChange:n=>t({...e,defaultValue:n?.id===`true`||n?.id!==`false`&&void 0}),options:[...tt],placeholder:`選擇預設狀態`,value:(0,c.readSelectOption)(tt,n)}))}function jn(e,t){return $(`可複選`,`fieldMemberMultiple`,(0,a.jsx)(i.Toggle,{checked:e.multiple===!0,label:e.multiple===!0?`可選多位`:`只能選一位`,onChange:n=>t({...e,defaultValue:void 0,multiple:n.target.checked||void 0}),size:`sub`}))}function Mn(e,t){return(0,a.jsxs)(a.Fragment,{children:[$(`檔案數`,`fieldMaxFiles`,Q(e.maxFiles,n=>t({...e,maxFiles:n}),`例如:1`,{min:1})),$(`MIME`,`fieldAcceptedMimeTypes`,In({name:`fieldAcceptedMimeTypes`,onChange:n=>t({...e,acceptedMimeTypes:vt(n)}),placeholder:`每行一個 MIME type,例如:application/pdf`,rows:3,value:yt(e.acceptedMimeTypes)}),!1)]})}function Nn(e){let t=m.fields.filter(t=>t.fieldKey!==e.fieldKey&&!(0,l.isMemberFieldDefinition)(t));return t.length?(0,a.jsx)(a.Fragment,{children:rt.map(n=>Pn(e,n,t))}):(0,a.jsx)(i.Typography,{color:`text-neutral`,style:b,variant:`body`,children:`目前沒有其他欄位可作為條件來源。新增更多欄位後即可設定條件規則。`})}function Pn(e,t,n){let r=e[t.target],o=r?(0,c.parseConditionRule)(r):null,s=n.find(e=>e.fieldKey===o?.fieldKey),l=s??n[0],u=n.map(_t),d=(0,c.readConditionOperatorOptions)(l),f=o&&d.some(e=>e.id===o.operator)?o.operator:(0,c.readDefaultConditionOperator)(l),p=o?.value??(0,c.readDefaultConditionValue)(l),m=!!r,h=m&&(!o||!s);return $(t.label,t.name,(0,a.jsxs)(`div`,{style:Me,children:[(0,a.jsx)(i.Toggle,{checked:m,label:m?`已啟用`:`不啟用`,onChange:e=>Z(t.target,e.target.checked?(0,c.buildConditionExpression)(l,(0,c.readDefaultConditionOperator)(l),(0,c.readDefaultConditionValue)(l)):void 0),size:`sub`,supportingText:t.supportingText}),m?h?(0,a.jsx)(i.Typography,{color:`text-warning`,variant:`body`,children:`這個規則不是目前 UI 支援的格式。重新選擇條件後會取代既有規則。`}):(0,a.jsxs)(`div`,{style:Ne,children:[(0,a.jsx)(i.Select,{clearable:!1,onChange:e=>{let r=n.find(t=>t.fieldKey===e?.id)??l;Z(t.target,(0,c.buildConditionExpression)(r,(0,c.readDefaultConditionOperator)(r),(0,c.readDefaultConditionValue)(r)))},options:u,placeholder:`選擇欄位`,value:(0,c.readSelectOption)(u,l.fieldKey)}),(0,a.jsx)(i.Select,{clearable:!1,onChange:e=>Z(t.target,(0,c.buildConditionExpression)(l,(0,c.readConditionOperatorOption)(e?.id)??f,p)),options:[...d],placeholder:`判斷方式`,value:(0,c.readSelectOption)(d,f)}),Fn(l,p,e=>Z(t.target,(0,c.buildConditionExpression)(l,f,e)))]}):null]}),!0)}function Z(e,t){K({[e]:t})}function Fn(e,t,n){if(e.type===`boolean`)return(0,a.jsx)(i.Select,{clearable:!1,onChange:e=>n(e?.id??`true`),options:[...nt],placeholder:`比較值`,value:(0,c.readSelectOption)(nt,t===`false`?`false`:`true`)});if((0,c.isSelectFieldDefinition)(e)){let r=e.options.map(c.readFieldOptionAsSelectOption);return(0,a.jsx)(i.Select,{clearable:!1,onChange:e=>n(e?.id??r[0]?.id??``),options:r,placeholder:`比較值`,value:(0,c.readSelectOption)(r,t)})}return(0,c.isNumberFieldDefinition)(e)?Q((0,c.parseOptionalNumberInput)(t),e=>n(String(e??0)),`比較值`):(0,c.isDateFieldDefinition)(e)?Ln(e,t,e=>n(e??``)):(0,a.jsx)(i.Input,{onChange:e=>n(e.target.value),placeholder:`比較值`,value:t,variant:`base`})}function In({name:e,onChange:t,placeholder:n,rows:r,value:o}){return(0,a.jsx)(i.Textarea,{"aria-label":e,onChange:e=>t(e.target.value),placeholder:n,ref:Xe,resize:`vertical`,rows:r,style:De,value:o})}function Q(e,t,n,r={}){return(0,a.jsx)(i.Input,{max:r.max,min:r.min,onChange:e=>t((0,c.clampOptionalNumber)((0,c.parseOptionalNumberInput)(e.target.value),r)),placeholder:n,showSpinner:!0,step:r.step??1,value:typeof e==`number`?String(e):``,variant:`measure`})}function Ln(e,t,n){return e.type===`datetime`?(0,a.jsx)(i.DateTimePicker,{formatDate:`YYYY-MM-DD`,formatTime:`HH:mm`,hideSecond:!0,onChange:e=>n((0,c.formatDateTimePickerValue)(e)),placeholderLeft:`選擇日期`,placeholderRight:`選擇時間`,value:(0,c.readDatePickerValue)(t)}):(0,a.jsx)(i.DatePicker,{format:`YYYY-MM-DD`,onChange:e=>n((0,c.formatDatePickerValue)(e)),placeholder:`選擇日期`,value:(0,c.readDatePickerValue)(t)})}function Rn(e,t){let n=e.options.map((t,n)=>({index:n,key:`${e.fieldKey}-${n}`,label:t.label,value:t.value}));return(0,a.jsxs)(`div`,{style:Ie,children:[(0,a.jsx)(i.Table,{actions:{render:n=>[{disabled:()=>e.options.length<=1,icon:s.TrashIcon,iconType:`icon-only`,name:`移除選項`,onClick:()=>t({...e,options:e.options.filter((e,t)=>t!==n.index)}),variant:`destructive-ghost`}],width:56},columns:[{key:`label`,render:n=>(0,a.jsx)(i.Input,{onChange:r=>t({...e,options:bt(e.options,n.index,{label:r.target.value})}),placeholder:`例如:主管`,size:`sub`,value:n.label,variant:`base`}),title:`Label`},{key:`value`,render:n=>(0,a.jsx)(i.Input,{onChange:r=>t({...e,options:bt(e.options,n.index,{value:r.target.value})}),placeholder:`例如:manager`,size:`sub`,value:n.value,variant:`base`}),title:`Value`}],dataSource:n,showHeader:!0,size:`sub`}),(0,a.jsx)(`div`,{style:Le,children:(0,a.jsx)(i.Button,{icon:s.PlusIcon,iconType:`leading`,onClick:()=>t({...e,options:[...e.options,xt(e.options)]}),variant:`base-secondary`,children:`新增選項`})})]})}function zn(e,t,n){return(0,a.jsx)(`div`,{...t.draggableProps,"data-form-builder-field-key":e.fieldKey,ref:t.innerRef,style:{...he,...n?ge:null,...t.draggableProps.style},children:(0,a.jsx)(i.BaseCard,{style:e.fieldKey===W?.fieldKey?_e:void 0,children:Bn(e,t,n)})})}function $(e,n,r,i=!1){return(0,a.jsx)(`div`,{style:i?Te:we,children:(0,a.jsx)(`div`,{style:Ee,children:(0,a.jsx)(t.t,{label:e,layout:i?o.FormFieldLayout.VERTICAL:o.FormFieldLayout.STRETCH,name:n,children:r})})})}function Bn(e,t,n){return(0,a.jsxs)(`div`,{...t.dragHandleProps??{},"aria-label":`選取或拖曳排序欄位`,onClick:()=>I(e.fieldKey),style:de,title:`點擊選取,拖曳排序`,children:[(0,a.jsx)(`span`,{"aria-label":`拖曳排序`,role:`img`,style:Pe,title:`拖曳排序`,children:(0,a.jsx)(i.Icon,{icon:s.DotDragVerticalIcon,size:20})}),(0,a.jsxs)(`div`,{style:fe,children:[(0,a.jsxs)(i.Typography,{component:`span`,ellipsis:!0,variant:`label-primary`,children:[e.label,e.required?(0,a.jsx)(`sup`,{"aria-label":`必填`,style:Re,children:`*`}):null]}),(0,a.jsxs)(i.Typography,{color:`text-neutral`,component:`span`,ellipsis:!0,variant:`caption`,children:[it(e.type),` ·`,e.required?` 必填`:` 選填`,` ·`,e.fieldKey,e.hidden?` · 只存不顯示`:null]})]}),(0,a.jsxs)(`div`,{onClick:e=>e.stopPropagation(),style:pe,children:[(0,a.jsx)(`div`,{style:me,children:(0,a.jsx)(i.Toggle,{checked:!!e.required,disabled:n||e.hidden===!0,label:`必填`,onChange:t=>Qt(e.fieldKey,t.target.checked)})}),(0,a.jsx)(i.Button,{disabled:n,icon:s.TrashIcon,iconType:`icon-only`,onClick:()=>Pt(e.fieldKey),variant:`destructive-ghost`,children:`移除欄位`})]})]})}function Vn(){return(0,a.jsxs)(`div`,{style:y,children:[(0,a.jsx)(i.Typography,{component:`h2`,variant:`h3`,children:`填寫預覽`}),(0,a.jsx)(n.t,{dataSourceContext:{kind:`preview`},onChange:Zt,schema:m,uiSchema:g,value:St})]})}function Hn(){return(0,a.jsxs)(`div`,{style:y,children:[(0,a.jsx)(i.Typography,{component:`h2`,variant:`h3`,children:`Schema`}),(0,a.jsxs)(`div`,{style:Oe,children:[Un(`Form Schema`,`schemaJson`,(0,a.jsx)(ee,{height:`360px`,name:`schemaJson`,onChange:$t,placeholder:`輸入 Form Schema JSON`,value:ct})),Un(`UI Schema`,`uiSchemaJson`,(0,a.jsx)(ee,{height:`240px`,name:`uiSchemaJson`,onChange:en,placeholder:`輸入 UI Schema JSON`,value:pt})),wt?(0,a.jsx)(i.Typography,{color:`text-error`,style:je,variant:`body`,children:wt}):null]})]})}function Un(e,n,r){return(0,a.jsx)(`div`,{style:ke,children:(0,a.jsx)(`div`,{style:Ae,children:(0,a.jsx)(t.t,{label:e,name:n,children:r})})})}}function it(e){return _.find(t=>t.type===e)?.label??e}function E(e){return`${e.key}@${e.version}`}function at(e){return[e.supportsSearch?`可輸入關鍵字搜尋${e.minimumSearchLength>1?`(至少 ${e.minimumSearchLength} 字)`:``}`:`不支援搜尋`,e.paginationMode===`CURSOR`?`捲動載入更多(每次 ${e.pageSize} 筆)`:`一次載入完整清單(最多 ${e.maximumResultCount} 筆)`,e.revalidationPolicy===`ALWAYS`?`退回重送時一律重新確認`:`值與條件未變時沿用上次結果`]}function ot(e){return{id:E(e),name:e.label}}function st(e){return e?e.from.kind===`FIELD`?e.from.fieldKey:e.from.kind===`ROW_FIELD`?`${C}${e.from.columnKey}`:S:w}function ct(e){switch(e){case`BOOLEAN`:return!1;case`NUMBER`:return 0;case`STRING_ARRAY`:return``;case`STRING`:return``;default:return``}}function lt(e,t){let n=e?.from.kind===`CONSTANT`?e.from.value:``;return t===`NUMBER`?typeof n==`number`?String(n):``:typeof n==`string`?n:``}function ut(e,t,n){return!n||n===w?null:n===S?{from:{kind:`CONSTANT`,value:ct(t)},parameter:e}:n.startsWith(C)?{from:{columnKey:n.slice(14),kind:`ROW_FIELD`},parameter:e}:{from:{fieldKey:n,kind:`FIELD`},parameter:e}}function dt(e){return e.kind===`remove-field`?`確認移除 dependency 欄位`:e.kind===`remove-column`?`確認移除表格欄`:e.kind===`replace-column`?`確認變更欄型別`:`確認變更選擇模式`}var D=[{label:`選項 A`,value:`option_a`},{label:`選項 B`,value:`option_b`}];function ft(e){let t=[];return e.defaultValue!==void 0&&t.push(`預設值`),e.type===`text`&&(typeof e.minLength==`number`||typeof e.maxLength==`number`)&&t.push(`長度限制`),(e.type===`number`||e.type===`money`)&&(typeof e.minimum==`number`||typeof e.maximum==`number`)&&t.push(`數值範圍`),(0,l.isFormDataSourceFieldDefinition)(e)?t.push(`選項來源設定`):(0,l.isFormStaticOptionFieldDefinition)(e)&&!pt(e.options)&&t.push(`${e.options.length} 個選項`),(e.type===`select`||e.type===`autocomplete`)&&e.mode===`multiple`&&t.push(`選擇模式`),t}function pt(e){return e.length===D.length&&e.every((e,t)=>e.label===D[t]?.label&&e.value===D[t]?.value)}function mt(e,t){let n={fieldKey:e.fieldKey,label:e.label,required:e.required,...e.description?{description:e.description}:{},...e.placeholder?{placeholder:e.placeholder}:{}};return t===`select`||t===`autocomplete`?{...n,mode:`single`,options:[...D],type:t}:{...n,type:t}}function ht(e,t){return Object.fromEntries(Object.entries(e).filter(([e])=>e!==t))}function gt(e){return!!(e.visibleWhen||e.requiredWhen||e.readonlyWhen)}function _t(e){return{id:e.fieldKey,name:e.label}}function O(e){return e.type===`text`||e.type===`textarea`}function k(e){return typeof e==`string`?e:``}function vt(e){let t=e.split(/[\n,]/u).map(e=>e.trim()).filter(Boolean);return t.length?t:void 0}function yt(e){return e?.join(`
2
- `)??``}function A(e){return JSON.stringify(e,null,2)}function bt(e,t,n){return e.map((e,r)=>r===t?{...e,...n}:e)}function xt(e){let t=e.length+1;return{label:`選項 ${t}`,value:j(e,t)}}function j(e,t){let n=`option_${t}`;return e.some(e=>e.value===n)?j(e,t+1):n}function M(e,t,n){let r=e[t];if(!r||t===n)return[...e];let i=e.filter((e,n)=>n!==t);return[...i.slice(0,n),r,...i.slice(n)]}Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return T}});
3
- //# sourceMappingURL=FormBuilderView-CUOyS07f.cjs.map