@rytass/bpm-core-react 0.10.0 → 0.12.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 (177) hide show
  1. package/CHANGELOG.md +55 -0
  2. package/dist/chunks/FormBuilderView-CLFlfDGe.cjs +3 -0
  3. package/dist/chunks/FormBuilderView-CLFlfDGe.cjs.map +1 -0
  4. package/dist/chunks/FormBuilderView-D4xIuPYB.js +1960 -0
  5. package/dist/chunks/FormBuilderView-D4xIuPYB.js.map +1 -0
  6. package/dist/chunks/FormRendererView-BxGT16z0.cjs +2 -0
  7. package/dist/chunks/FormRendererView-BxGT16z0.cjs.map +1 -0
  8. package/dist/chunks/FormRendererView-DUceSOXe.js +798 -0
  9. package/dist/chunks/FormRendererView-DUceSOXe.js.map +1 -0
  10. package/dist/chunks/admin-pickers-Btvij1at.cjs.map +1 -1
  11. package/dist/chunks/admin-pickers-DLlG_1du.js.map +1 -1
  12. package/dist/chunks/approval-instance-list-page-BjX2kaoF.js.map +1 -1
  13. package/dist/chunks/approval-instance-list-page-CWiQvnfE.cjs +2 -0
  14. package/dist/chunks/{approval-instance-list-page-C408vxE2.cjs.map → approval-instance-list-page-CWiQvnfE.cjs.map} +1 -1
  15. package/dist/chunks/auth-provider-4BeCw7cI.cjs.map +1 -1
  16. package/dist/chunks/auth-provider-B5oPmvk2.js.map +1 -1
  17. package/dist/chunks/bpm-form-field-Bc6k4ZEO.cjs.map +1 -1
  18. package/dist/chunks/categories-DGlxuC6X.js.map +1 -1
  19. package/dist/chunks/categories-Yid05WAX.cjs +2 -0
  20. package/dist/chunks/{categories-DUfldZ_9.cjs.map → categories-Yid05WAX.cjs.map} +1 -1
  21. package/dist/chunks/{compose-D-OS-Ngs.js → compose-Bb-REfoB.js} +4 -4
  22. package/dist/chunks/{compose-D-OS-Ngs.js.map → compose-Bb-REfoB.js.map} +1 -1
  23. package/dist/chunks/compose-DzRYZcqe.cjs +2 -0
  24. package/dist/chunks/{compose-CODnd9-2.cjs.map → compose-DzRYZcqe.cjs.map} +1 -1
  25. package/dist/chunks/dashboard-page-CH87L5nx.cjs +2 -0
  26. package/dist/chunks/{dashboard-page-DwHQY6Ki.cjs.map → dashboard-page-CH87L5nx.cjs.map} +1 -1
  27. package/dist/chunks/dashboard-page-DJ9vOPga.js.map +1 -1
  28. package/dist/chunks/{delegations-DLEEFBlH.js → delegations-0MbJ7CWj.js} +3 -2
  29. package/dist/chunks/{delegations-DLEEFBlH.js.map → delegations-0MbJ7CWj.js.map} +1 -1
  30. package/dist/chunks/delegations-Bc9psOZ3.cjs +2 -0
  31. package/dist/chunks/{delegations-CGj-tZNO.cjs.map → delegations-Bc9psOZ3.cjs.map} +1 -1
  32. package/dist/chunks/{delegations-DqMpI_Nk.js → delegations-DyMGIDpp.js} +3 -2
  33. package/dist/chunks/{delegations-DqMpI_Nk.js.map → delegations-DyMGIDpp.js.map} +1 -1
  34. package/dist/chunks/delegations-vpLtus9g.cjs +2 -0
  35. package/dist/chunks/{delegations-kbMOSEif.cjs.map → delegations-vpLtus9g.cjs.map} +1 -1
  36. package/dist/chunks/{designer-DDSxwtjV.js → designer-C6oIO9Kq.js} +39 -30
  37. package/dist/chunks/{designer-DDSxwtjV.js.map → designer-C6oIO9Kq.js.map} +1 -1
  38. package/dist/chunks/designer-gFUdImeZ.cjs +65 -0
  39. package/dist/chunks/{designer-Cdn10NNl.cjs.map → designer-gFUdImeZ.cjs.map} +1 -1
  40. package/dist/chunks/{detail-DAPz2qyn.js → detail-BgKgMvYx.js} +392 -391
  41. package/dist/chunks/{detail-DAPz2qyn.js.map → detail-BgKgMvYx.js.map} +1 -1
  42. package/dist/chunks/detail-Dnz5aaI-.cjs +2 -0
  43. package/dist/chunks/{detail-CtVu5NTi.cjs.map → detail-Dnz5aaI-.cjs.map} +1 -1
  44. package/dist/chunks/format-date-time-CB-LxzqT.js.map +1 -1
  45. package/dist/chunks/format-date-time-D-cx5M8z.cjs +2 -0
  46. package/dist/chunks/{format-date-time-XxBzF0F5.cjs.map → format-date-time-D-cx5M8z.cjs.map} +1 -1
  47. package/dist/chunks/login-9bCXyjbX.cjs.map +1 -1
  48. package/dist/chunks/login-BKxpLibd.js.map +1 -1
  49. package/dist/chunks/notifications-Bc4mgSds.cjs +2 -0
  50. package/dist/chunks/{notifications--hwl-DR0.cjs.map → notifications-Bc4mgSds.cjs.map} +1 -1
  51. package/dist/chunks/notifications-DJ5wzCye.js.map +1 -1
  52. package/dist/chunks/{orgs-DytLvZ_X.js → orgs-B930facb.js} +11 -10
  53. package/dist/chunks/{orgs-DytLvZ_X.js.map → orgs-B930facb.js.map} +1 -1
  54. package/dist/chunks/orgs-BefGgeyc.cjs +2 -0
  55. package/dist/chunks/{orgs-Ni22buHs.cjs.map → orgs-BefGgeyc.cjs.map} +1 -1
  56. package/dist/chunks/providers-BsEn3ikK.cjs +2 -0
  57. package/dist/chunks/{providers-D_zTbkQH.cjs.map → providers-BsEn3ikK.cjs.map} +1 -1
  58. package/dist/chunks/{providers-DEqcuXw9.js → providers-DjLh4oLY.js} +3 -3
  59. package/dist/chunks/{providers-DEqcuXw9.js.map → providers-DjLh4oLY.js.map} +1 -1
  60. package/dist/chunks/{chunk-CMqjfN_6.cjs → rolldown-runtime-BocRIvOZ.cjs} +1 -1
  61. package/dist/chunks/router-adapter--gYs13E8.cjs.map +1 -1
  62. package/dist/chunks/routes-config-fDVHmvXi.cjs.map +1 -1
  63. package/dist/chunks/users-C9LA-Rd7.cjs +2 -0
  64. package/dist/chunks/{users-0HqlM_VQ.cjs.map → users-C9LA-Rd7.cjs.map} +1 -1
  65. package/dist/chunks/users-FWrb3ehW.js.map +1 -1
  66. package/dist/index.cjs +1 -1
  67. package/dist/index.cjs.map +1 -1
  68. package/dist/index.js +1 -1
  69. package/dist/index.js.map +1 -1
  70. package/dist/next/index.cjs +1 -1
  71. package/dist/next/index.cjs.map +1 -1
  72. package/dist/next/index.js +9 -9
  73. package/dist/next/index.js.map +1 -1
  74. package/dist/next/workflow-chat-route.cjs +1 -1
  75. package/dist/next/workflow-chat-route.cjs.map +1 -1
  76. package/dist/next/workflow-chat-route.js +2 -1
  77. package/dist/next/workflow-chat-route.js.map +1 -1
  78. package/dist/pages/admin/delegations/index.cjs +1 -1
  79. package/dist/pages/admin/delegations/index.cjs.map +1 -1
  80. package/dist/pages/admin/delegations/index.js +1 -1
  81. package/dist/pages/admin/orgs/index.cjs +1 -1
  82. package/dist/pages/admin/orgs/index.cjs.map +1 -1
  83. package/dist/pages/admin/orgs/index.js +1 -1
  84. package/dist/pages/admin/users/index.cjs +1 -1
  85. package/dist/pages/admin/users/index.cjs.map +1 -1
  86. package/dist/pages/cc/index.cjs.map +1 -1
  87. package/dist/pages/dashboard/index.cjs.map +1 -1
  88. package/dist/pages/delegations/index.cjs +1 -1
  89. package/dist/pages/delegations/index.cjs.map +1 -1
  90. package/dist/pages/delegations/index.js +1 -1
  91. package/dist/pages/inbox/index.cjs.map +1 -1
  92. package/dist/pages/instances/detail/index.cjs +1 -1
  93. package/dist/pages/instances/detail/index.cjs.map +1 -1
  94. package/dist/pages/instances/detail/index.js +1 -1
  95. package/dist/pages/instances/new/index.cjs.map +1 -1
  96. package/dist/pages/login/index.cjs.map +1 -1
  97. package/dist/pages/root/index.cjs.map +1 -1
  98. package/dist/pages/search/index.cjs.map +1 -1
  99. package/dist/pages/sent/index.cjs.map +1 -1
  100. package/dist/pages/settings/notifications/index.cjs +1 -1
  101. package/dist/pages/settings/notifications/index.cjs.map +1 -1
  102. package/dist/pages/templates/categories/index.cjs +1 -1
  103. package/dist/pages/templates/categories/index.cjs.map +1 -1
  104. package/dist/pages/templates/compose/index.cjs +1 -1
  105. package/dist/pages/templates/compose/index.cjs.map +1 -1
  106. package/dist/pages/templates/compose/index.js +1 -1
  107. package/dist/pages/templates/designer/index.cjs +1 -1
  108. package/dist/pages/templates/designer/index.cjs.map +1 -1
  109. package/dist/pages/templates/designer/index.js +1 -1
  110. package/dist/pages/templates/index.cjs.map +1 -1
  111. package/dist/pages/templates/versions/index.cjs.map +1 -1
  112. package/dist/views/admin/delegations/index.cjs +1 -1
  113. package/dist/views/admin/delegations/index.js +1 -1
  114. package/dist/views/admin/index.cjs +1 -1
  115. package/dist/views/admin/index.js +2 -2
  116. package/dist/views/admin/orgs/index.cjs +1 -1
  117. package/dist/views/admin/orgs/index.js +1 -1
  118. package/dist/views/admin/users/index.cjs +1 -1
  119. package/dist/views/cc/index.cjs +1 -1
  120. package/dist/views/cc/index.cjs.map +1 -1
  121. package/dist/views/dashboard/index.cjs +1 -1
  122. package/dist/views/dashboard/index.cjs.map +1 -1
  123. package/dist/views/delegations/index.cjs +1 -1
  124. package/dist/views/delegations/index.js +1 -1
  125. package/dist/views/forms/builder/index.cjs +1 -1
  126. package/dist/views/forms/builder/index.js +1 -1
  127. package/dist/views/forms/renderer/form-data-source-field.d.ts +16 -0
  128. package/dist/views/forms/renderer/index.cjs +1 -1
  129. package/dist/views/forms/renderer/index.js +1 -1
  130. package/dist/views/inbox/index.cjs +1 -1
  131. package/dist/views/inbox/index.cjs.map +1 -1
  132. package/dist/views/inbox/index.js.map +1 -1
  133. package/dist/views/instances/detail/index.cjs +1 -1
  134. package/dist/views/instances/detail/index.js +1 -1
  135. package/dist/views/instances/new/index.cjs +1 -1
  136. package/dist/views/instances/new/index.cjs.map +1 -1
  137. package/dist/views/instances/new/index.js +48 -48
  138. package/dist/views/instances/new/index.js.map +1 -1
  139. package/dist/views/search/index.cjs +1 -1
  140. package/dist/views/search/index.cjs.map +1 -1
  141. package/dist/views/sent/index.cjs +1 -1
  142. package/dist/views/sent/index.cjs.map +1 -1
  143. package/dist/views/settings/index.cjs +1 -1
  144. package/dist/views/settings/notifications/index.cjs +1 -1
  145. package/dist/views/templates/categories/index.cjs +1 -1
  146. package/dist/views/templates/compose/index.cjs +1 -1
  147. package/dist/views/templates/compose/index.js +1 -1
  148. package/dist/views/templates/designer/index.cjs +1 -1
  149. package/dist/views/templates/designer/index.js +1 -1
  150. package/dist/views/templates/index.cjs +1 -1
  151. package/dist/views/templates/index.cjs.map +1 -1
  152. package/dist/views/templates/index.js.map +1 -1
  153. package/dist/views/templates/versions/index.cjs +1 -1
  154. package/dist/views/templates/versions/index.cjs.map +1 -1
  155. package/dist/views/templates/versions/index.js.map +1 -1
  156. package/package.json +3 -3
  157. package/dist/chunks/FormBuilderView-D6baVqBY.cjs +0 -3
  158. package/dist/chunks/FormBuilderView-D6baVqBY.cjs.map +0 -1
  159. package/dist/chunks/FormBuilderView-QtREqV4j.js +0 -1477
  160. package/dist/chunks/FormBuilderView-QtREqV4j.js.map +0 -1
  161. package/dist/chunks/FormRendererView-Cw9LiidV.cjs +0 -2
  162. package/dist/chunks/FormRendererView-Cw9LiidV.cjs.map +0 -1
  163. package/dist/chunks/FormRendererView-D8QHLvd0.js +0 -577
  164. package/dist/chunks/FormRendererView-D8QHLvd0.js.map +0 -1
  165. package/dist/chunks/approval-instance-list-page-C408vxE2.cjs +0 -2
  166. package/dist/chunks/categories-DUfldZ_9.cjs +0 -2
  167. package/dist/chunks/compose-CODnd9-2.cjs +0 -2
  168. package/dist/chunks/dashboard-page-DwHQY6Ki.cjs +0 -2
  169. package/dist/chunks/delegations-CGj-tZNO.cjs +0 -2
  170. package/dist/chunks/delegations-kbMOSEif.cjs +0 -2
  171. package/dist/chunks/designer-Cdn10NNl.cjs +0 -65
  172. package/dist/chunks/detail-CtVu5NTi.cjs +0 -2
  173. package/dist/chunks/format-date-time-XxBzF0F5.cjs +0 -2
  174. package/dist/chunks/notifications--hwl-DR0.cjs +0 -2
  175. package/dist/chunks/orgs-Ni22buHs.cjs +0 -2
  176. package/dist/chunks/providers-D_zTbkQH.cjs +0 -2
  177. package/dist/chunks/users-0HqlM_VQ.cjs +0 -2
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../src/views/templates/TemplatesView.tsx"],"sourcesContent":["'use client';\n\nimport type { ChangeEvent, Key, ReactElement } from 'react';\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport {\n Badge,\n Button,\n Filter,\n FilterArea,\n FilterLine,\n FormField,\n Input,\n PageHeader,\n Section,\n SectionGroup,\n Select,\n Tab,\n TabItem,\n Table,\n Typography,\n} from '@mezzanine-ui/react';\nimport ContentHeader from '@mezzanine-ui/react/ContentHeader';\nimport { PlusIcon } from '@mezzanine-ui/icons';\nimport { FormFieldLayout } from '@mezzanine-ui/core/form';\nimport type { TableActions, TableColumn } from '@mezzanine-ui/core/table';\nimport styles from './templates.module.scss';\nimport { formatDateTime } from '../../lib/format-date-time';\nimport { useRouterAdapter } from '../../lib/router-adapter';\nimport { useBPMRoutes } from '../../lib/routes-config';\nimport {\n ApprovalTemplateListStatus,\n ApprovalTemplateRecord,\n ApprovalTemplateCategoryRecord,\n activateApprovalTemplate,\n deactivateApprovalTemplate,\n listApprovalTemplateCategoriesPage,\n listApprovalTemplatesPage,\n} from '@rytass/bpm-core-client/template';\nimport { listLaunchableTemplates } from '@rytass/bpm-core-client/workflow';\n\nconst TEMPLATE_PAGE_SIZE_OPTIONS = [10, 20, 50];\nconst TEMPLATE_STATUS_TABS: readonly {\n readonly key: TemplateStatusTabKey;\n readonly label: string;\n}[] = [\n { key: 'ALL', label: '全部' },\n { key: 'PUBLISHED', label: '已發布' },\n { key: 'DRAFT', label: '草稿' },\n];\n\nconst TEMPLATE_CATEGORY_PAGE_SIZE = 100;\n\nexport interface TemplateCategoryOption {\n readonly categoryId: string | null;\n readonly id: string;\n readonly name: string;\n}\n\ntype TemplateStatusTabKey = 'ALL' | ApprovalTemplateListStatus;\n\ntype TemplateRow = Readonly<\n Record<string, unknown> &\n ApprovalTemplateRecord & {\n categoryLabel: string;\n key: string;\n status: ApprovalTemplateListStatus;\n }\n>;\n\nexport function TemplatesView(): ReactElement {\n const router = useRouterAdapter();\n const routes = useBPMRoutes();\n const [templates, setTemplates] = useState<readonly ApprovalTemplateRecord[]>(\n [],\n );\n const [categoryFilter, setCategoryFilter] = useState<TemplateCategoryOption>(\n UNCATEGORIZED_TEMPLATE_FILTER_OPTION,\n );\n const [categoryOptions, setCategoryOptions] = useState<\n readonly TemplateCategoryOption[]\n >([]);\n const [launchableTemplateIds, setLaunchableTemplateIds] = useState<\n ReadonlySet<string>\n >(new Set());\n const [error, setError] = useState<string | null>(null);\n const [loading, setLoading] = useState(true);\n const [templatePage, setTemplatePage] = useState(1);\n const [templatePageSize, setTemplatePageSize] = useState(10);\n const [templateSearchText, setTemplateSearchText] = useState('');\n const [templateStatus, setTemplateStatus] =\n useState<TemplateStatusTabKey>('ALL');\n const [templateTotalCount, setTemplateTotalCount] = useState(0);\n const [activationPendingTemplateId, setActivationPendingTemplateId] =\n useState<string | null>(null);\n const refreshRequestIdRef = useRef(0);\n\n const refreshTemplates = useCallback(async (): Promise<void> => {\n const requestId = refreshRequestIdRef.current + 1;\n refreshRequestIdRef.current = requestId;\n setLoading(true);\n setError(null);\n setLaunchableTemplateIds(new Set());\n\n void listLaunchableTemplates()\n .then((nextLaunchableTemplates): void => {\n if (requestId !== refreshRequestIdRef.current) {\n return;\n }\n\n setLaunchableTemplateIds(\n new Set(nextLaunchableTemplates.map((template) => template.id)),\n );\n })\n .catch((): void => {\n if (requestId === refreshRequestIdRef.current) {\n setLaunchableTemplateIds(new Set());\n }\n });\n\n try {\n const [templatePageResult, activeCategoryPageResult] = await Promise.all([\n listApprovalTemplatesPage({\n categoryId: categoryFilter.categoryId,\n page: templatePage,\n pageSize: templatePageSize,\n searchText: templateSearchText,\n status: templateStatus === 'ALL' ? null : templateStatus,\n }),\n listApprovalTemplateCategoriesPage({\n page: 1,\n pageSize: TEMPLATE_CATEGORY_PAGE_SIZE,\n searchText: '',\n status: 'ACTIVE',\n }),\n ]);\n\n if (requestId !== refreshRequestIdRef.current) {\n return;\n }\n\n setCategoryOptions([\n ...activeCategoryPageResult.categories.map(readCategoryOption),\n ]);\n setTemplates(templatePageResult.templates);\n setTemplateTotalCount(templatePageResult.totalCount);\n } catch (requestError: unknown) {\n if (requestId === refreshRequestIdRef.current) {\n setError(readErrorMessage(requestError));\n }\n } finally {\n if (requestId === refreshRequestIdRef.current) {\n setLoading(false);\n }\n }\n }, [\n categoryFilter,\n templatePage,\n templatePageSize,\n templateSearchText,\n templateStatus,\n ]);\n\n useEffect((): void => {\n void refreshTemplates();\n }, [refreshTemplates]);\n\n const toggleTemplateActivation = useCallback(\n async (template: ApprovalTemplateRecord): Promise<void> => {\n setActivationPendingTemplateId(template.id);\n setError(null);\n\n try {\n await (template.isActive\n ? deactivateApprovalTemplate(template.id)\n : activateApprovalTemplate(template.id));\n await refreshTemplates();\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setActivationPendingTemplateId(null);\n }\n },\n [refreshTemplates],\n );\n\n const rows = useMemo(\n (): TemplateRow[] =>\n templates.map((template) => ({\n ...template,\n categoryLabel: readTemplateCategoryLabel(template),\n key: template.id,\n status: template.currentVersionId ? 'PUBLISHED' : 'DRAFT',\n updatedAt: formatDateTime(template.updatedAt),\n })),\n [templates],\n );\n const columns = useMemo(\n (): TableColumn<TemplateRow>[] => [\n { dataIndex: 'name', key: 'name', title: '模板名稱', width: 220 },\n {\n key: 'status',\n render: (record: TemplateRow): ReactElement => (\n <TemplateStatusBadge status={record.status} />\n ),\n title: '狀態',\n width: 120,\n },\n {\n key: 'isActive',\n render: (record: TemplateRow): ReactElement => (\n <TemplateActivationBadge isActive={record.isActive} />\n ),\n title: '服務狀態',\n width: 120,\n },\n {\n key: 'category',\n render: (record: TemplateRow): ReactElement => (\n <TemplateCategoryLabel record={record} />\n ),\n title: '分類',\n width: 160,\n },\n {\n dataIndex: 'updatedAt',\n key: 'updatedAt',\n title: '更新時間',\n width: 220,\n },\n ],\n [],\n );\n const tableActions = useMemo(\n (): TableActions<TemplateRow> => ({\n render: (record): ReturnType<TableActions<TemplateRow>['render']> => [\n {\n disabled: (template): boolean =>\n !launchableTemplateIds.has(template.id),\n name: '發起',\n onClick: (): void => router.push(routes.caseNew(record.id)),\n variant: 'base-primary',\n },\n {\n name: '設計',\n onClick: (): void => router.push(routes.templateDesigner(record.id)),\n },\n {\n name: '版本',\n onClick: (): void => router.push(routes.templateVersions(record.id)),\n },\n {\n disabled: (template): boolean =>\n activationPendingTemplateId === template.id,\n name: record.isActive ? '停用' : '啟用',\n onClick: (template): void => {\n void toggleTemplateActivation(template);\n },\n variant: record.isActive ? 'destructive-secondary' : 'base-secondary',\n },\n ],\n variant: 'base-secondary',\n width: 264,\n }),\n [\n activationPendingTemplateId,\n launchableTemplateIds,\n router,\n toggleTemplateActivation,\n ],\n );\n\n return (\n <>\n <>\n <PageHeader>\n <ContentHeader\n description=\"建立流程模板、維護草稿與發布版本。\"\n title=\"簽核模板\"\n >\n <Button\n icon={PlusIcon}\n iconType=\"leading\"\n onClick={(): void => router.push(routes.templateCompose())}\n variant=\"base-primary\"\n >\n 建立模板\n </Button>\n </ContentHeader>\n </PageHeader>\n\n <SectionGroup>\n <Section\n filterArea={\n <FilterArea className={styles.templateFilterArea} size=\"sub\">\n <FilterLine>\n <Filter span={3}>\n <FormField\n fullWidth\n layout={FormFieldLayout.VERTICAL}\n name=\"templateSearchText\"\n >\n <Input\n fullWidth\n onChange={(\n event: ChangeEvent<HTMLInputElement>,\n ): void => {\n setTemplateSearchText(event.target.value);\n setTemplatePage(1);\n }}\n placeholder=\"關鍵字:搜尋模板名稱、分類或描述\"\n size=\"sub\"\n value={templateSearchText}\n variant=\"base\"\n />\n </FormField>\n </Filter>\n <Filter span={2}>\n <FormField\n fullWidth\n layout={FormFieldLayout.VERTICAL}\n name=\"templateCategoryFilter\"\n >\n <Select\n clearable={false}\n fullWidth\n onChange={(option): void => {\n setCategoryFilter(\n readCategoryFilterOption(option, categoryOptions),\n );\n setTemplatePage(1);\n }}\n options={[\n UNCATEGORIZED_TEMPLATE_FILTER_OPTION,\n ...categoryOptions,\n ]}\n placeholder=\"分類\"\n renderValue={(value): string =>\n `分類:${readTemplateCategoryFilterLabel(value)}`\n }\n size=\"sub\"\n value={categoryFilter}\n />\n </FormField>\n </Filter>\n </FilterLine>\n </FilterArea>\n }\n tab={\n <Tab\n activeKey={templateStatus}\n onChange={(activeKey): void => {\n setTemplateStatus(readTemplateStatusTabKey(activeKey));\n setTemplatePage(1);\n }}\n >\n {TEMPLATE_STATUS_TABS.map((statusTab) => (\n <TabItem key={statusTab.key}>{statusTab.label}</TabItem>\n ))}\n </Tab>\n }\n >\n {error ? (\n <Typography color=\"text-error\" variant=\"body\">\n {error}\n </Typography>\n ) : null}\n <Table\n actions={tableActions}\n columns={columns}\n dataSource={rows}\n fullWidth\n loading={loading}\n pagination={{\n current: templatePage,\n onChange: (page): void => {\n setTemplatePage(page);\n },\n onChangePageSize: (pageSize): void => {\n setTemplatePage(1);\n setTemplatePageSize(pageSize);\n },\n pageSize: templatePageSize,\n pageSizeLabel: '每頁筆數',\n pageSizeOptions: TEMPLATE_PAGE_SIZE_OPTIONS,\n renderResultSummary: (from, to, total): string =>\n `顯示 ${from}-${to} 筆,共 ${total} 筆`,\n showPageSizeOptions: true,\n total: templateTotalCount,\n }}\n />\n </Section>\n </SectionGroup>\n </>\n </>\n );\n}\n\nfunction readErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : '發生未知錯誤';\n}\n\nfunction readTemplateStatusTabKey(activeKey: Key): TemplateStatusTabKey {\n if (activeKey === 'PUBLISHED' || activeKey === 'DRAFT') {\n return activeKey;\n }\n\n return 'ALL';\n}\n\nfunction TemplateStatusBadge({\n status,\n}: {\n readonly status: ApprovalTemplateListStatus;\n}): ReactElement {\n if (status === 'PUBLISHED') {\n return <Badge size=\"sub\" text=\"已發布\" variant=\"dot-success\" />;\n }\n\n return <Badge size=\"sub\" text=\"草稿\" variant=\"dot-inactive\" />;\n}\n\nfunction TemplateActivationBadge({\n isActive,\n}: {\n readonly isActive: boolean;\n}): ReactElement {\n if (isActive) {\n return <Badge size=\"sub\" text=\"啟用中\" variant=\"dot-success\" />;\n }\n\n return <Badge size=\"sub\" text=\"已停用\" variant=\"dot-inactive\" />;\n}\n\nfunction TemplateCategoryLabel({\n record,\n}: {\n readonly record: TemplateRow;\n}): ReactElement {\n if (record.categoryDetail?.isActive === false) {\n return (\n <Badge\n size=\"sub\"\n text={`${record.categoryLabel}(停用)`}\n variant=\"dot-inactive\"\n />\n );\n }\n\n return (\n <Typography component=\"span\" variant=\"body\">\n {record.categoryLabel}\n </Typography>\n );\n}\n\nconst UNCATEGORIZED_TEMPLATE_FILTER_OPTION: TemplateCategoryOption = {\n categoryId: null,\n id: 'ALL_CATEGORIES',\n name: '全部分類',\n};\n\nfunction readCategoryOption(\n category: ApprovalTemplateCategoryRecord,\n): TemplateCategoryOption {\n return {\n categoryId: category.id,\n id: category.id,\n name: category.name,\n };\n}\n\nfunction readCategoryFilterOption(\n value: unknown,\n options: readonly TemplateCategoryOption[],\n): TemplateCategoryOption {\n if (!isRecord(value)) {\n return UNCATEGORIZED_TEMPLATE_FILTER_OPTION;\n }\n\n const id = typeof value.id === 'string' ? value.id : null;\n\n if (id === UNCATEGORIZED_TEMPLATE_FILTER_OPTION.id) {\n return UNCATEGORIZED_TEMPLATE_FILTER_OPTION;\n }\n\n return (\n options.find((option) => option.id === id) ??\n UNCATEGORIZED_TEMPLATE_FILTER_OPTION\n );\n}\n\nfunction readTemplateCategoryFilterLabel(value: unknown): string {\n if (Array.isArray(value)) {\n return UNCATEGORIZED_TEMPLATE_FILTER_OPTION.name;\n }\n\n if (!isRecord(value)) {\n return UNCATEGORIZED_TEMPLATE_FILTER_OPTION.name;\n }\n\n return typeof value.name === 'string'\n ? value.name\n : UNCATEGORIZED_TEMPLATE_FILTER_OPTION.name;\n}\n\nfunction readTemplateCategoryLabel(template: ApprovalTemplateRecord): string {\n return template.categoryDetail?.name ?? template.category ?? '未分類';\n}\n\nfunction isRecord(value: unknown): value is Readonly<Record<string, unknown>> {\n return typeof value === 'object' && value !== null;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../src/views/templates/TemplatesView.tsx"],"sourcesContent":["'use client';\n\nimport type { ChangeEvent, Key, ReactElement } from 'react';\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport {\n Badge,\n Button,\n Filter,\n FilterArea,\n FilterLine,\n FormField,\n Input,\n PageHeader,\n Section,\n SectionGroup,\n Select,\n Tab,\n TabItem,\n Table,\n Typography,\n} from '@mezzanine-ui/react';\nimport ContentHeader from '@mezzanine-ui/react/ContentHeader';\nimport { PlusIcon } from '@mezzanine-ui/icons';\nimport { FormFieldLayout } from '@mezzanine-ui/core/form';\nimport type { TableActions, TableColumn } from '@mezzanine-ui/core/table';\nimport styles from './templates.module.scss';\nimport { formatDateTime } from '../../lib/format-date-time';\nimport { useRouterAdapter } from '../../lib/router-adapter';\nimport { useBPMRoutes } from '../../lib/routes-config';\nimport {\n ApprovalTemplateListStatus,\n ApprovalTemplateRecord,\n ApprovalTemplateCategoryRecord,\n activateApprovalTemplate,\n deactivateApprovalTemplate,\n listApprovalTemplateCategoriesPage,\n listApprovalTemplatesPage,\n} from '@rytass/bpm-core-client/template';\nimport { listLaunchableTemplates } from '@rytass/bpm-core-client/workflow';\n\nconst TEMPLATE_PAGE_SIZE_OPTIONS = [10, 20, 50];\nconst TEMPLATE_STATUS_TABS: readonly {\n readonly key: TemplateStatusTabKey;\n readonly label: string;\n}[] = [\n { key: 'ALL', label: '全部' },\n { key: 'PUBLISHED', label: '已發布' },\n { key: 'DRAFT', label: '草稿' },\n];\n\nconst TEMPLATE_CATEGORY_PAGE_SIZE = 100;\n\nexport interface TemplateCategoryOption {\n readonly categoryId: string | null;\n readonly id: string;\n readonly name: string;\n}\n\ntype TemplateStatusTabKey = 'ALL' | ApprovalTemplateListStatus;\n\ntype TemplateRow = Readonly<\n Record<string, unknown> &\n ApprovalTemplateRecord & {\n categoryLabel: string;\n key: string;\n status: ApprovalTemplateListStatus;\n }\n>;\n\nexport function TemplatesView(): ReactElement {\n const router = useRouterAdapter();\n const routes = useBPMRoutes();\n const [templates, setTemplates] = useState<readonly ApprovalTemplateRecord[]>(\n [],\n );\n const [categoryFilter, setCategoryFilter] = useState<TemplateCategoryOption>(\n UNCATEGORIZED_TEMPLATE_FILTER_OPTION,\n );\n const [categoryOptions, setCategoryOptions] = useState<\n readonly TemplateCategoryOption[]\n >([]);\n const [launchableTemplateIds, setLaunchableTemplateIds] = useState<\n ReadonlySet<string>\n >(new Set());\n const [error, setError] = useState<string | null>(null);\n const [loading, setLoading] = useState(true);\n const [templatePage, setTemplatePage] = useState(1);\n const [templatePageSize, setTemplatePageSize] = useState(10);\n const [templateSearchText, setTemplateSearchText] = useState('');\n const [templateStatus, setTemplateStatus] =\n useState<TemplateStatusTabKey>('ALL');\n const [templateTotalCount, setTemplateTotalCount] = useState(0);\n const [activationPendingTemplateId, setActivationPendingTemplateId] =\n useState<string | null>(null);\n const refreshRequestIdRef = useRef(0);\n\n const refreshTemplates = useCallback(async (): Promise<void> => {\n const requestId = refreshRequestIdRef.current + 1;\n refreshRequestIdRef.current = requestId;\n setLoading(true);\n setError(null);\n setLaunchableTemplateIds(new Set());\n\n void listLaunchableTemplates()\n .then((nextLaunchableTemplates): void => {\n if (requestId !== refreshRequestIdRef.current) {\n return;\n }\n\n setLaunchableTemplateIds(\n new Set(nextLaunchableTemplates.map((template) => template.id)),\n );\n })\n .catch((): void => {\n if (requestId === refreshRequestIdRef.current) {\n setLaunchableTemplateIds(new Set());\n }\n });\n\n try {\n const [templatePageResult, activeCategoryPageResult] = await Promise.all([\n listApprovalTemplatesPage({\n categoryId: categoryFilter.categoryId,\n page: templatePage,\n pageSize: templatePageSize,\n searchText: templateSearchText,\n status: templateStatus === 'ALL' ? null : templateStatus,\n }),\n listApprovalTemplateCategoriesPage({\n page: 1,\n pageSize: TEMPLATE_CATEGORY_PAGE_SIZE,\n searchText: '',\n status: 'ACTIVE',\n }),\n ]);\n\n if (requestId !== refreshRequestIdRef.current) {\n return;\n }\n\n setCategoryOptions([\n ...activeCategoryPageResult.categories.map(readCategoryOption),\n ]);\n setTemplates(templatePageResult.templates);\n setTemplateTotalCount(templatePageResult.totalCount);\n } catch (requestError: unknown) {\n if (requestId === refreshRequestIdRef.current) {\n setError(readErrorMessage(requestError));\n }\n } finally {\n if (requestId === refreshRequestIdRef.current) {\n setLoading(false);\n }\n }\n }, [\n categoryFilter,\n templatePage,\n templatePageSize,\n templateSearchText,\n templateStatus,\n ]);\n\n useEffect((): void => {\n void refreshTemplates();\n }, [refreshTemplates]);\n\n const toggleTemplateActivation = useCallback(\n async (template: ApprovalTemplateRecord): Promise<void> => {\n setActivationPendingTemplateId(template.id);\n setError(null);\n\n try {\n await (template.isActive\n ? deactivateApprovalTemplate(template.id)\n : activateApprovalTemplate(template.id));\n await refreshTemplates();\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setActivationPendingTemplateId(null);\n }\n },\n [refreshTemplates],\n );\n\n const rows = useMemo(\n (): TemplateRow[] =>\n templates.map((template) => ({\n ...template,\n categoryLabel: readTemplateCategoryLabel(template),\n key: template.id,\n status: template.currentVersionId ? 'PUBLISHED' : 'DRAFT',\n updatedAt: formatDateTime(template.updatedAt),\n })),\n [templates],\n );\n const columns = useMemo(\n (): TableColumn<TemplateRow>[] => [\n { dataIndex: 'name', key: 'name', title: '模板名稱', width: 220 },\n {\n key: 'status',\n render: (record: TemplateRow): ReactElement => (\n <TemplateStatusBadge status={record.status} />\n ),\n title: '狀態',\n width: 120,\n },\n {\n key: 'isActive',\n render: (record: TemplateRow): ReactElement => (\n <TemplateActivationBadge isActive={record.isActive} />\n ),\n title: '服務狀態',\n width: 120,\n },\n {\n key: 'category',\n render: (record: TemplateRow): ReactElement => (\n <TemplateCategoryLabel record={record} />\n ),\n title: '分類',\n width: 160,\n },\n {\n dataIndex: 'updatedAt',\n key: 'updatedAt',\n title: '更新時間',\n width: 220,\n },\n ],\n [],\n );\n const tableActions = useMemo(\n (): TableActions<TemplateRow> => ({\n render: (record): ReturnType<TableActions<TemplateRow>['render']> => [\n {\n disabled: (template): boolean =>\n !launchableTemplateIds.has(template.id),\n name: '發起',\n onClick: (): void => router.push(routes.caseNew(record.id)),\n variant: 'base-primary',\n },\n {\n name: '設計',\n onClick: (): void => router.push(routes.templateDesigner(record.id)),\n },\n {\n name: '版本',\n onClick: (): void => router.push(routes.templateVersions(record.id)),\n },\n {\n disabled: (template): boolean =>\n activationPendingTemplateId === template.id,\n name: record.isActive ? '停用' : '啟用',\n onClick: (template): void => {\n void toggleTemplateActivation(template);\n },\n variant: record.isActive ? 'destructive-secondary' : 'base-secondary',\n },\n ],\n variant: 'base-secondary',\n width: 264,\n }),\n [\n activationPendingTemplateId,\n launchableTemplateIds,\n router,\n toggleTemplateActivation,\n ],\n );\n\n return (\n <>\n <>\n <PageHeader>\n <ContentHeader\n description=\"建立流程模板、維護草稿與發布版本。\"\n title=\"簽核模板\"\n >\n <Button\n icon={PlusIcon}\n iconType=\"leading\"\n onClick={(): void => router.push(routes.templateCompose())}\n variant=\"base-primary\"\n >\n 建立模板\n </Button>\n </ContentHeader>\n </PageHeader>\n\n <SectionGroup>\n <Section\n filterArea={\n <FilterArea className={styles.templateFilterArea} size=\"sub\">\n <FilterLine>\n <Filter span={3}>\n <FormField\n fullWidth\n layout={FormFieldLayout.VERTICAL}\n name=\"templateSearchText\"\n >\n <Input\n fullWidth\n onChange={(\n event: ChangeEvent<HTMLInputElement>,\n ): void => {\n setTemplateSearchText(event.target.value);\n setTemplatePage(1);\n }}\n placeholder=\"關鍵字:搜尋模板名稱、分類或描述\"\n size=\"sub\"\n value={templateSearchText}\n variant=\"base\"\n />\n </FormField>\n </Filter>\n <Filter span={2}>\n <FormField\n fullWidth\n layout={FormFieldLayout.VERTICAL}\n name=\"templateCategoryFilter\"\n >\n <Select\n clearable={false}\n fullWidth\n onChange={(option): void => {\n setCategoryFilter(\n readCategoryFilterOption(option, categoryOptions),\n );\n setTemplatePage(1);\n }}\n options={[\n UNCATEGORIZED_TEMPLATE_FILTER_OPTION,\n ...categoryOptions,\n ]}\n placeholder=\"分類\"\n renderValue={(value): string =>\n `分類:${readTemplateCategoryFilterLabel(value)}`\n }\n size=\"sub\"\n value={categoryFilter}\n />\n </FormField>\n </Filter>\n </FilterLine>\n </FilterArea>\n }\n tab={\n <Tab\n activeKey={templateStatus}\n onChange={(activeKey): void => {\n setTemplateStatus(readTemplateStatusTabKey(activeKey));\n setTemplatePage(1);\n }}\n >\n {TEMPLATE_STATUS_TABS.map((statusTab) => (\n <TabItem key={statusTab.key}>{statusTab.label}</TabItem>\n ))}\n </Tab>\n }\n >\n {error ? (\n <Typography color=\"text-error\" variant=\"body\">\n {error}\n </Typography>\n ) : null}\n <Table\n actions={tableActions}\n columns={columns}\n dataSource={rows}\n fullWidth\n loading={loading}\n pagination={{\n current: templatePage,\n onChange: (page): void => {\n setTemplatePage(page);\n },\n onChangePageSize: (pageSize): void => {\n setTemplatePage(1);\n setTemplatePageSize(pageSize);\n },\n pageSize: templatePageSize,\n pageSizeLabel: '每頁筆數',\n pageSizeOptions: TEMPLATE_PAGE_SIZE_OPTIONS,\n renderResultSummary: (from, to, total): string =>\n `顯示 ${from}-${to} 筆,共 ${total} 筆`,\n showPageSizeOptions: true,\n total: templateTotalCount,\n }}\n />\n </Section>\n </SectionGroup>\n </>\n </>\n );\n}\n\nfunction readErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : '發生未知錯誤';\n}\n\nfunction readTemplateStatusTabKey(activeKey: Key): TemplateStatusTabKey {\n if (activeKey === 'PUBLISHED' || activeKey === 'DRAFT') {\n return activeKey;\n }\n\n return 'ALL';\n}\n\nfunction TemplateStatusBadge({\n status,\n}: {\n readonly status: ApprovalTemplateListStatus;\n}): ReactElement {\n if (status === 'PUBLISHED') {\n return <Badge size=\"sub\" text=\"已發布\" variant=\"dot-success\" />;\n }\n\n return <Badge size=\"sub\" text=\"草稿\" variant=\"dot-inactive\" />;\n}\n\nfunction TemplateActivationBadge({\n isActive,\n}: {\n readonly isActive: boolean;\n}): ReactElement {\n if (isActive) {\n return <Badge size=\"sub\" text=\"啟用中\" variant=\"dot-success\" />;\n }\n\n return <Badge size=\"sub\" text=\"已停用\" variant=\"dot-inactive\" />;\n}\n\nfunction TemplateCategoryLabel({\n record,\n}: {\n readonly record: TemplateRow;\n}): ReactElement {\n if (record.categoryDetail?.isActive === false) {\n return (\n <Badge\n size=\"sub\"\n text={`${record.categoryLabel}(停用)`}\n variant=\"dot-inactive\"\n />\n );\n }\n\n return (\n <Typography component=\"span\" variant=\"body\">\n {record.categoryLabel}\n </Typography>\n );\n}\n\nconst UNCATEGORIZED_TEMPLATE_FILTER_OPTION: TemplateCategoryOption = {\n categoryId: null,\n id: 'ALL_CATEGORIES',\n name: '全部分類',\n};\n\nfunction readCategoryOption(\n category: ApprovalTemplateCategoryRecord,\n): TemplateCategoryOption {\n return {\n categoryId: category.id,\n id: category.id,\n name: category.name,\n };\n}\n\nfunction readCategoryFilterOption(\n value: unknown,\n options: readonly TemplateCategoryOption[],\n): TemplateCategoryOption {\n if (!isRecord(value)) {\n return UNCATEGORIZED_TEMPLATE_FILTER_OPTION;\n }\n\n const id = typeof value.id === 'string' ? value.id : null;\n\n if (id === UNCATEGORIZED_TEMPLATE_FILTER_OPTION.id) {\n return UNCATEGORIZED_TEMPLATE_FILTER_OPTION;\n }\n\n return (\n options.find((option) => option.id === id) ??\n UNCATEGORIZED_TEMPLATE_FILTER_OPTION\n );\n}\n\nfunction readTemplateCategoryFilterLabel(value: unknown): string {\n if (Array.isArray(value)) {\n return UNCATEGORIZED_TEMPLATE_FILTER_OPTION.name;\n }\n\n if (!isRecord(value)) {\n return UNCATEGORIZED_TEMPLATE_FILTER_OPTION.name;\n }\n\n return typeof value.name === 'string'\n ? value.name\n : UNCATEGORIZED_TEMPLATE_FILTER_OPTION.name;\n}\n\nfunction readTemplateCategoryLabel(template: ApprovalTemplateRecord): string {\n return template.categoryDetail?.name ?? template.category ?? '未分類';\n}\n\nfunction isRecord(value: unknown): value is Readonly<Record<string, unknown>> {\n return typeof value === 'object' && value !== null;\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use client";Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../../../chunks/chunk-CMqjfN_6.cjs"),t=require("../../../chunks/router-adapter--gYs13E8.cjs"),n=require("../../../chunks/format-date-time-XxBzF0F5.cjs"),r=require("../../../chunks/routes-config-fDVHmvXi.cjs");let i=require("react"),a=require("@mezzanine-ui/react"),o=require("react/jsx-runtime"),s=require("@mezzanine-ui/react/ContentHeader");s=e.t(s,1);let c=require("@rytass/bpm-core-client/template");function l({templateId:e}){let l=t.r(),d=r.r(),[f,p]=(0,i.useState)(null),[m,h]=(0,i.useState)(null),[g,_]=(0,i.useState)(!0),[v,y]=(0,i.useState)(!1);(0,i.useEffect)(()=>{C()},[e]);let b=(0,i.useMemo)(()=>(f?.versions??[]).map(e=>({formVersion:f?.formVersions.find(t=>t.id===e.formDefinitionVersionId)?.label??`未綁定`,key:e.id,publishedAt:n.t(e.publishedAt),status:e.status,updatedAt:n.t(e.updatedAt),version:`v${e.version}`,versionId:e.id})),[f]),x=(0,i.useMemo)(()=>[{dataIndex:`version`,key:`version`,title:`版本`,width:100},{dataIndex:`status`,key:`status`,title:`狀態`,width:140},{dataIndex:`formVersion`,key:`formVersion`,title:`表單版本`,width:220},{dataIndex:`publishedAt`,key:`publishedAt`,title:`發布時間`,width:200},{dataIndex:`updatedAt`,key:`updatedAt`,title:`更新時間`,width:200}],[]),S=(0,i.useMemo)(()=>({render:e=>[{disabled:()=>v||e.status===`DRAFT`,name:`Rollback`,onClick:()=>void w(e.versionId)}],variant:`base-secondary`,width:104}),[v]);async function C(){_(!0),h(null);try{p(await(0,c.readTemplateDesigner)(e))}catch(e){h(u(e))}finally{_(!1)}}async function w(e){y(!0),h(null);try{await(0,c.rollbackApprovalTemplateVersion)(e),await C()}catch(e){h(u(e))}finally{y(!1)}}return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(a.PageHeader,{children:(0,o.jsx)(s.default,{description:`查看發布、歸檔與 rollback 狀態。`,onBackClick:()=>l.push(d.templates()),title:f?.template.name??`模板版本`})}),(0,o.jsx)(a.SectionGroup,{children:(0,o.jsxs)(a.Section,{children:[m?(0,o.jsx)(a.Typography,{color:`text-error`,variant:`body`,children:m}):null,(0,o.jsx)(a.Table,{actions:S,columns:x,dataSource:b,fullWidth:!0,loading:g})]})})]})}function u(e){return e instanceof Error?e.message:`發生未知錯誤`}exports.TemplateVersionsView=l;
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/format-date-time-D-cx5M8z.cjs"),r=require("../../../chunks/routes-config-fDVHmvXi.cjs");let i=require("react"),a=require("@mezzanine-ui/react"),o=require("react/jsx-runtime"),s=require("@mezzanine-ui/react/ContentHeader");s=e.t(s,1);let c=require("@rytass/bpm-core-client/template");function l({templateId:e}){let l=t.r(),d=r.r(),[f,p]=(0,i.useState)(null),[m,h]=(0,i.useState)(null),[g,_]=(0,i.useState)(!0),[v,y]=(0,i.useState)(!1);(0,i.useEffect)(()=>{C()},[e]);let b=(0,i.useMemo)(()=>(f?.versions??[]).map(e=>({formVersion:f?.formVersions.find(t=>t.id===e.formDefinitionVersionId)?.label??`未綁定`,key:e.id,publishedAt:n.t(e.publishedAt),status:e.status,updatedAt:n.t(e.updatedAt),version:`v${e.version}`,versionId:e.id})),[f]),x=(0,i.useMemo)(()=>[{dataIndex:`version`,key:`version`,title:`版本`,width:100},{dataIndex:`status`,key:`status`,title:`狀態`,width:140},{dataIndex:`formVersion`,key:`formVersion`,title:`表單版本`,width:220},{dataIndex:`publishedAt`,key:`publishedAt`,title:`發布時間`,width:200},{dataIndex:`updatedAt`,key:`updatedAt`,title:`更新時間`,width:200}],[]),S=(0,i.useMemo)(()=>({render:e=>[{disabled:()=>v||e.status===`DRAFT`,name:`Rollback`,onClick:()=>void w(e.versionId)}],variant:`base-secondary`,width:104}),[v]);async function C(){_(!0),h(null);try{p(await(0,c.readTemplateDesigner)(e))}catch(e){h(u(e))}finally{_(!1)}}async function w(e){y(!0),h(null);try{await(0,c.rollbackApprovalTemplateVersion)(e),await C()}catch(e){h(u(e))}finally{y(!1)}}return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(a.PageHeader,{children:(0,o.jsx)(s.default,{description:`查看發布、歸檔與 rollback 狀態。`,onBackClick:()=>l.push(d.templates()),title:f?.template.name??`模板版本`})}),(0,o.jsx)(a.SectionGroup,{children:(0,o.jsxs)(a.Section,{children:[m?(0,o.jsx)(a.Typography,{color:`text-error`,variant:`body`,children:m}):null,(0,o.jsx)(a.Table,{actions:S,columns:x,dataSource:b,fullWidth:!0,loading:g})]})})]})}function u(e){return e instanceof Error?e.message:`發生未知錯誤`}exports.TemplateVersionsView=l;
2
2
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":[],"sources":["../../../../src/views/templates/versions/TemplateVersionsView.tsx"],"sourcesContent":["'use client';\n\nimport { ReactElement, useEffect, useMemo, useState } from 'react';\nimport {\n PageHeader,\n Section,\n SectionGroup,\n Table,\n Typography,\n} from '@mezzanine-ui/react';\nimport ContentHeader from '@mezzanine-ui/react/ContentHeader';\nimport type { TableActions, TableColumn } from '@mezzanine-ui/core/table';\nimport { useRouterAdapter } from '../../../lib/router-adapter';\nimport { useBPMRoutes } from '../../../lib/routes-config';\nimport {\n readTemplateDesigner,\n rollbackApprovalTemplateVersion,\n TemplateDesignerRecord,\n} from '@rytass/bpm-core-client/template';\nimport { formatDateTime } from '../../../lib/format-date-time';\n\ntype VersionRow = Readonly<\n Record<string, unknown> & {\n formVersion: string;\n key: string;\n publishedAt: string;\n status: string;\n updatedAt: string;\n version: string;\n versionId: string;\n }\n>;\n\nexport interface TemplateVersionsViewProps {\n readonly templateId: string;\n}\n\nexport function TemplateVersionsView({\n templateId,\n}: TemplateVersionsViewProps): ReactElement {\n const router = useRouterAdapter();\n const routes = useBPMRoutes();\n const [record, setRecord] = useState<TemplateDesignerRecord | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [loading, setLoading] = useState(true);\n const [rollingBack, setRollingBack] = useState(false);\n\n useEffect((): void => {\n void refreshVersions();\n }, [templateId]);\n\n const rows = useMemo(\n (): VersionRow[] =>\n (record?.versions ?? []).map((version) => ({\n formVersion:\n record?.formVersions.find(\n (formVersion) => formVersion.id === version.formDefinitionVersionId,\n )?.label ?? '未綁定',\n key: version.id,\n publishedAt: formatDateTime(version.publishedAt),\n status: version.status,\n updatedAt: formatDateTime(version.updatedAt),\n version: `v${version.version}`,\n versionId: version.id,\n })),\n [record],\n );\n const columns = useMemo(\n (): TableColumn<VersionRow>[] => [\n { dataIndex: 'version', key: 'version', title: '版本', width: 100 },\n { dataIndex: 'status', key: 'status', title: '狀態', width: 140 },\n {\n dataIndex: 'formVersion',\n key: 'formVersion',\n title: '表單版本',\n width: 220,\n },\n {\n dataIndex: 'publishedAt',\n key: 'publishedAt',\n title: '發布時間',\n width: 200,\n },\n {\n dataIndex: 'updatedAt',\n key: 'updatedAt',\n title: '更新時間',\n width: 200,\n },\n ],\n [],\n );\n const actions = useMemo(\n (): TableActions<VersionRow> => ({\n render: (row): ReturnType<TableActions<VersionRow>['render']> => [\n {\n disabled: (): boolean => rollingBack || row.status === 'DRAFT',\n name: 'Rollback',\n onClick: (): void => void handleRollback(row.versionId),\n },\n ],\n variant: 'base-secondary',\n width: 104,\n }),\n [rollingBack],\n );\n\n async function refreshVersions(): Promise<void> {\n setLoading(true);\n setError(null);\n\n try {\n setRecord(await readTemplateDesigner(templateId));\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setLoading(false);\n }\n }\n\n async function handleRollback(versionId: string): Promise<void> {\n setRollingBack(true);\n setError(null);\n\n try {\n await rollbackApprovalTemplateVersion(versionId);\n await refreshVersions();\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setRollingBack(false);\n }\n }\n\n return (\n <>\n <PageHeader>\n <ContentHeader\n description=\"查看發布、歸檔與 rollback 狀態。\"\n onBackClick={(): void => router.push(routes.templates())}\n title={record?.template.name ?? '模板版本'}\n />\n </PageHeader>\n\n <SectionGroup>\n <Section>\n {error ? (\n <Typography color=\"text-error\" variant=\"body\">\n {error}\n </Typography>\n ) : null}\n <Table\n actions={actions}\n columns={columns}\n dataSource={rows}\n fullWidth\n loading={loading}\n />\n </Section>\n </SectionGroup>\n </>\n );\n}\n\nfunction readErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : '發生未知錯誤';\n}\n"],"mappings":"qfAqCA,SAAgB,EAAqB,CACnC,cAC0C,CAC1C,IAAM,EAAS,EAAA,EAAiB,EAC1B,EAAS,EAAA,EAAa,EACtB,CAAC,EAAQ,IAAA,EAAA,EAAA,UAAqD,IAAI,EAClE,CAAC,EAAO,IAAA,EAAA,EAAA,UAAoC,IAAI,EAChD,CAAC,EAAS,IAAA,EAAA,EAAA,UAAuB,EAAI,EACrC,CAAC,EAAa,IAAA,EAAA,EAAA,UAA2B,EAAK,GAEpD,EAAA,EAAA,eAAsB,CACpB,EAAqB,CACvB,EAAG,CAAC,CAAU,CAAC,EAEf,IAAM,GAAA,EAAA,EAAA,cAED,GAAQ,UAAY,CAAC,GAAG,IAAK,IAAa,CACzC,YACE,GAAQ,aAAa,KAClB,GAAgB,EAAY,KAAO,EAAQ,uBAC9C,GAAG,OAAS,MACd,IAAK,EAAQ,GACb,YAAa,EAAA,EAAe,EAAQ,WAAW,EAC/C,OAAQ,EAAQ,OAChB,UAAW,EAAA,EAAe,EAAQ,SAAS,EAC3C,QAAS,IAAI,EAAQ,UACrB,UAAW,EAAQ,EACrB,EAAE,EACJ,CAAC,CAAM,CACT,EACM,GAAA,EAAA,EAAA,aAC6B,CAC/B,CAAE,UAAW,UAAW,IAAK,UAAW,MAAO,KAAM,MAAO,GAAI,EAChE,CAAE,UAAW,SAAU,IAAK,SAAU,MAAO,KAAM,MAAO,GAAI,EAC9D,CACE,UAAW,cACX,IAAK,cACL,MAAO,OACP,MAAO,GACT,EACA,CACE,UAAW,cACX,IAAK,cACL,MAAO,OACP,MAAO,GACT,EACA,CACE,UAAW,YACX,IAAK,YACL,MAAO,OACP,MAAO,GACT,CACF,EACA,CAAC,CACH,EACM,GAAA,EAAA,EAAA,cAC6B,CAC/B,OAAS,GAAwD,CAC/D,CACE,aAAyB,GAAe,EAAI,SAAW,QACvD,KAAM,WACN,YAAqB,KAAK,EAAe,EAAI,SAAS,CACxD,CACF,EACA,QAAS,iBACT,MAAO,GACT,GACA,CAAC,CAAW,CACd,EAEA,eAAe,GAAiC,CAC9C,EAAW,EAAI,EACf,EAAS,IAAI,EAEb,GAAI,CACF,EAAU,MAAA,EAAA,EAAA,sBAA2B,CAAU,CAAC,CAClD,OAAS,EAAuB,CAC9B,EAAS,EAAiB,CAAY,CAAC,CACzC,QAAU,CACR,EAAW,EAAK,CAClB,CACF,CAEA,eAAe,EAAe,EAAkC,CAC9D,EAAe,EAAI,EACnB,EAAS,IAAI,EAEb,GAAI,CACF,MAAA,EAAA,EAAA,iCAAsC,CAAS,EAC/C,MAAM,EAAgB,CACxB,OAAS,EAAuB,CAC9B,EAAS,EAAiB,CAAY,CAAC,CACzC,QAAU,CACR,EAAe,EAAK,CACtB,CACF,CAEA,OACE,EAAA,EAAA,MAAA,EAAA,SAAA,CAAA,SAAA,EACI,EAAA,EAAA,KAAC,EAAA,WAAD,CAAA,UACE,EAAA,EAAA,KAAC,EAAA,QAAD,CACE,YAAY,wBACZ,gBAAyB,EAAO,KAAK,EAAO,UAAU,CAAC,EACvD,MAAO,GAAQ,SAAS,MAAQ,MACjC,CAAA,CACS,CAAA,GAEZ,EAAA,EAAA,KAAC,EAAA,aAAD,CAAA,UACE,EAAA,EAAA,MAAC,EAAA,QAAD,CAAA,SAAA,CACG,GACC,EAAA,EAAA,KAAC,EAAA,WAAD,CAAY,MAAM,aAAa,QAAQ,gBACpC,CACS,CAAA,EACV,MACJ,EAAA,EAAA,KAAC,EAAA,MAAD,CACW,UACA,UACT,WAAY,EACZ,UAAA,GACS,SACV,CAAA,CACM,CAAA,CAAA,CACG,CAAA,CACd,CAAA,CAAA,CAER,CAEA,SAAS,EAAiB,EAAwB,CAChD,OAAO,aAAiB,MAAQ,EAAM,QAAU,QAClD"}
1
+ {"version":3,"file":"index.cjs","names":[],"sources":["../../../../src/views/templates/versions/TemplateVersionsView.tsx"],"sourcesContent":["'use client';\n\nimport { ReactElement, useEffect, useMemo, useState } from 'react';\nimport {\n PageHeader,\n Section,\n SectionGroup,\n Table,\n Typography,\n} from '@mezzanine-ui/react';\nimport ContentHeader from '@mezzanine-ui/react/ContentHeader';\nimport type { TableActions, TableColumn } from '@mezzanine-ui/core/table';\nimport { useRouterAdapter } from '../../../lib/router-adapter';\nimport { useBPMRoutes } from '../../../lib/routes-config';\nimport {\n readTemplateDesigner,\n rollbackApprovalTemplateVersion,\n TemplateDesignerRecord,\n} from '@rytass/bpm-core-client/template';\nimport { formatDateTime } from '../../../lib/format-date-time';\n\ntype VersionRow = Readonly<\n Record<string, unknown> & {\n formVersion: string;\n key: string;\n publishedAt: string;\n status: string;\n updatedAt: string;\n version: string;\n versionId: string;\n }\n>;\n\nexport interface TemplateVersionsViewProps {\n readonly templateId: string;\n}\n\nexport function TemplateVersionsView({\n templateId,\n}: TemplateVersionsViewProps): ReactElement {\n const router = useRouterAdapter();\n const routes = useBPMRoutes();\n const [record, setRecord] = useState<TemplateDesignerRecord | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [loading, setLoading] = useState(true);\n const [rollingBack, setRollingBack] = useState(false);\n\n useEffect((): void => {\n void refreshVersions();\n }, [templateId]);\n\n const rows = useMemo(\n (): VersionRow[] =>\n (record?.versions ?? []).map((version) => ({\n formVersion:\n record?.formVersions.find(\n (formVersion) => formVersion.id === version.formDefinitionVersionId,\n )?.label ?? '未綁定',\n key: version.id,\n publishedAt: formatDateTime(version.publishedAt),\n status: version.status,\n updatedAt: formatDateTime(version.updatedAt),\n version: `v${version.version}`,\n versionId: version.id,\n })),\n [record],\n );\n const columns = useMemo(\n (): TableColumn<VersionRow>[] => [\n { dataIndex: 'version', key: 'version', title: '版本', width: 100 },\n { dataIndex: 'status', key: 'status', title: '狀態', width: 140 },\n {\n dataIndex: 'formVersion',\n key: 'formVersion',\n title: '表單版本',\n width: 220,\n },\n {\n dataIndex: 'publishedAt',\n key: 'publishedAt',\n title: '發布時間',\n width: 200,\n },\n {\n dataIndex: 'updatedAt',\n key: 'updatedAt',\n title: '更新時間',\n width: 200,\n },\n ],\n [],\n );\n const actions = useMemo(\n (): TableActions<VersionRow> => ({\n render: (row): ReturnType<TableActions<VersionRow>['render']> => [\n {\n disabled: (): boolean => rollingBack || row.status === 'DRAFT',\n name: 'Rollback',\n onClick: (): void => void handleRollback(row.versionId),\n },\n ],\n variant: 'base-secondary',\n width: 104,\n }),\n [rollingBack],\n );\n\n async function refreshVersions(): Promise<void> {\n setLoading(true);\n setError(null);\n\n try {\n setRecord(await readTemplateDesigner(templateId));\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setLoading(false);\n }\n }\n\n async function handleRollback(versionId: string): Promise<void> {\n setRollingBack(true);\n setError(null);\n\n try {\n await rollbackApprovalTemplateVersion(versionId);\n await refreshVersions();\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setRollingBack(false);\n }\n }\n\n return (\n <>\n <PageHeader>\n <ContentHeader\n description=\"查看發布、歸檔與 rollback 狀態。\"\n onBackClick={(): void => router.push(routes.templates())}\n title={record?.template.name ?? '模板版本'}\n />\n </PageHeader>\n\n <SectionGroup>\n <Section>\n {error ? (\n <Typography color=\"text-error\" variant=\"body\">\n {error}\n </Typography>\n ) : null}\n <Table\n actions={actions}\n columns={columns}\n dataSource={rows}\n fullWidth\n loading={loading}\n />\n </Section>\n </SectionGroup>\n </>\n );\n}\n\nfunction readErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : '發生未知錯誤';\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../../src/views/templates/versions/TemplateVersionsView.tsx"],"sourcesContent":["'use client';\n\nimport { ReactElement, useEffect, useMemo, useState } from 'react';\nimport {\n PageHeader,\n Section,\n SectionGroup,\n Table,\n Typography,\n} from '@mezzanine-ui/react';\nimport ContentHeader from '@mezzanine-ui/react/ContentHeader';\nimport type { TableActions, TableColumn } from '@mezzanine-ui/core/table';\nimport { useRouterAdapter } from '../../../lib/router-adapter';\nimport { useBPMRoutes } from '../../../lib/routes-config';\nimport {\n readTemplateDesigner,\n rollbackApprovalTemplateVersion,\n TemplateDesignerRecord,\n} from '@rytass/bpm-core-client/template';\nimport { formatDateTime } from '../../../lib/format-date-time';\n\ntype VersionRow = Readonly<\n Record<string, unknown> & {\n formVersion: string;\n key: string;\n publishedAt: string;\n status: string;\n updatedAt: string;\n version: string;\n versionId: string;\n }\n>;\n\nexport interface TemplateVersionsViewProps {\n readonly templateId: string;\n}\n\nexport function TemplateVersionsView({\n templateId,\n}: TemplateVersionsViewProps): ReactElement {\n const router = useRouterAdapter();\n const routes = useBPMRoutes();\n const [record, setRecord] = useState<TemplateDesignerRecord | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [loading, setLoading] = useState(true);\n const [rollingBack, setRollingBack] = useState(false);\n\n useEffect((): void => {\n void refreshVersions();\n }, [templateId]);\n\n const rows = useMemo(\n (): VersionRow[] =>\n (record?.versions ?? []).map((version) => ({\n formVersion:\n record?.formVersions.find(\n (formVersion) => formVersion.id === version.formDefinitionVersionId,\n )?.label ?? '未綁定',\n key: version.id,\n publishedAt: formatDateTime(version.publishedAt),\n status: version.status,\n updatedAt: formatDateTime(version.updatedAt),\n version: `v${version.version}`,\n versionId: version.id,\n })),\n [record],\n );\n const columns = useMemo(\n (): TableColumn<VersionRow>[] => [\n { dataIndex: 'version', key: 'version', title: '版本', width: 100 },\n { dataIndex: 'status', key: 'status', title: '狀態', width: 140 },\n {\n dataIndex: 'formVersion',\n key: 'formVersion',\n title: '表單版本',\n width: 220,\n },\n {\n dataIndex: 'publishedAt',\n key: 'publishedAt',\n title: '發布時間',\n width: 200,\n },\n {\n dataIndex: 'updatedAt',\n key: 'updatedAt',\n title: '更新時間',\n width: 200,\n },\n ],\n [],\n );\n const actions = useMemo(\n (): TableActions<VersionRow> => ({\n render: (row): ReturnType<TableActions<VersionRow>['render']> => [\n {\n disabled: (): boolean => rollingBack || row.status === 'DRAFT',\n name: 'Rollback',\n onClick: (): void => void handleRollback(row.versionId),\n },\n ],\n variant: 'base-secondary',\n width: 104,\n }),\n [rollingBack],\n );\n\n async function refreshVersions(): Promise<void> {\n setLoading(true);\n setError(null);\n\n try {\n setRecord(await readTemplateDesigner(templateId));\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setLoading(false);\n }\n }\n\n async function handleRollback(versionId: string): Promise<void> {\n setRollingBack(true);\n setError(null);\n\n try {\n await rollbackApprovalTemplateVersion(versionId);\n await refreshVersions();\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setRollingBack(false);\n }\n }\n\n return (\n <>\n <PageHeader>\n <ContentHeader\n description=\"查看發布、歸檔與 rollback 狀態。\"\n onBackClick={(): void => router.push(routes.templates())}\n title={record?.template.name ?? '模板版本'}\n />\n </PageHeader>\n\n <SectionGroup>\n <Section>\n {error ? (\n <Typography color=\"text-error\" variant=\"body\">\n {error}\n </Typography>\n ) : null}\n <Table\n actions={actions}\n columns={columns}\n dataSource={rows}\n fullWidth\n loading={loading}\n />\n </Section>\n </SectionGroup>\n </>\n );\n}\n\nfunction readErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : '發生未知錯誤';\n}\n"],"mappings":";;;;;;;;;;AAqCA,SAAgB,EAAqB,EACnC,iBAC0C;CAC1C,IAAM,IAAS,EAAiB,GAC1B,IAAS,EAAa,GACtB,CAAC,GAAQ,KAAa,EAAwC,IAAI,GAClE,CAAC,GAAO,KAAY,EAAwB,IAAI,GAChD,CAAC,GAAS,KAAc,EAAS,EAAI,GACrC,CAAC,GAAa,KAAkB,EAAS,EAAK;CAEpD,QAAsB;EACpB,EAAqB;CACvB,GAAG,CAAC,CAAU,CAAC;CAEf,IAAM,IAAO,SAER,GAAQ,YAAY,CAAC,GAAG,KAAK,OAAa;EACzC,aACE,GAAQ,aAAa,MAClB,MAAgB,EAAY,OAAO,EAAQ,uBAC9C,GAAG,SAAS;EACd,KAAK,EAAQ;EACb,aAAa,EAAe,EAAQ,WAAW;EAC/C,QAAQ,EAAQ;EAChB,WAAW,EAAe,EAAQ,SAAS;EAC3C,SAAS,IAAI,EAAQ;EACrB,WAAW,EAAQ;CACrB,EAAE,GACJ,CAAC,CAAM,CACT,GACM,IAAU,QACmB;EAC/B;GAAE,WAAW;GAAW,KAAK;GAAW,OAAO;GAAM,OAAO;EAAI;EAChE;GAAE,WAAW;GAAU,KAAK;GAAU,OAAO;GAAM,OAAO;EAAI;EAC9D;GACE,WAAW;GACX,KAAK;GACL,OAAO;GACP,OAAO;EACT;EACA;GACE,WAAW;GACX,KAAK;GACL,OAAO;GACP,OAAO;EACT;EACA;GACE,WAAW;GACX,KAAK;GACL,OAAO;GACP,OAAO;EACT;CACF,GACA,CAAC,CACH,GACM,IAAU,SACmB;EAC/B,SAAS,MAAwD,CAC/D;GACE,gBAAyB,KAAe,EAAI,WAAW;GACvD,MAAM;GACN,eAAqB,KAAK,EAAe,EAAI,SAAS;EACxD,CACF;EACA,SAAS;EACT,OAAO;CACT,IACA,CAAC,CAAW,CACd;CAEA,eAAe,IAAiC;EAE9C,AADA,EAAW,EAAI,GACf,EAAS,IAAI;EAEb,IAAI;GACF,EAAU,MAAM,EAAqB,CAAU,CAAC;EAClD,SAAS,GAAuB;GAC9B,EAAS,EAAiB,CAAY,CAAC;EACzC,UAAU;GACR,EAAW,EAAK;EAClB;CACF;CAEA,eAAe,EAAe,GAAkC;EAE9D,AADA,EAAe,EAAI,GACnB,EAAS,IAAI;EAEb,IAAI;GAEF,AADA,MAAM,EAAgC,CAAS,GAC/C,MAAM,EAAgB;EACxB,SAAS,GAAuB;GAC9B,EAAS,EAAiB,CAAY,CAAC;EACzC,UAAU;GACR,EAAe,EAAK;EACtB;CACF;CAEA,OACE,kBAAA,GAAA,EAAA,UAAA,CACI,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;EACE,aAAY;EACZ,mBAAyB,EAAO,KAAK,EAAO,UAAU,CAAC;EACvD,OAAO,GAAQ,SAAS,QAAQ;CACjC,CAAA,EACS,CAAA,GAEZ,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD,EAAA,UAAA,CACG,IACC,kBAAC,GAAD;EAAY,OAAM;EAAa,SAAQ;YACpC;CACS,CAAA,IACV,MACJ,kBAAC,GAAD;EACW;EACA;EACT,YAAY;EACZ,WAAA;EACS;CACV,CAAA,CACM,EAAA,CAAA,EACG,CAAA,CACd,EAAA,CAAA;AAER;AAEA,SAAS,EAAiB,GAAwB;CAChD,OAAO,aAAiB,QAAQ,EAAM,UAAU;AAClD"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../../src/views/templates/versions/TemplateVersionsView.tsx"],"sourcesContent":["'use client';\n\nimport { ReactElement, useEffect, useMemo, useState } from 'react';\nimport {\n PageHeader,\n Section,\n SectionGroup,\n Table,\n Typography,\n} from '@mezzanine-ui/react';\nimport ContentHeader from '@mezzanine-ui/react/ContentHeader';\nimport type { TableActions, TableColumn } from '@mezzanine-ui/core/table';\nimport { useRouterAdapter } from '../../../lib/router-adapter';\nimport { useBPMRoutes } from '../../../lib/routes-config';\nimport {\n readTemplateDesigner,\n rollbackApprovalTemplateVersion,\n TemplateDesignerRecord,\n} from '@rytass/bpm-core-client/template';\nimport { formatDateTime } from '../../../lib/format-date-time';\n\ntype VersionRow = Readonly<\n Record<string, unknown> & {\n formVersion: string;\n key: string;\n publishedAt: string;\n status: string;\n updatedAt: string;\n version: string;\n versionId: string;\n }\n>;\n\nexport interface TemplateVersionsViewProps {\n readonly templateId: string;\n}\n\nexport function TemplateVersionsView({\n templateId,\n}: TemplateVersionsViewProps): ReactElement {\n const router = useRouterAdapter();\n const routes = useBPMRoutes();\n const [record, setRecord] = useState<TemplateDesignerRecord | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [loading, setLoading] = useState(true);\n const [rollingBack, setRollingBack] = useState(false);\n\n useEffect((): void => {\n void refreshVersions();\n }, [templateId]);\n\n const rows = useMemo(\n (): VersionRow[] =>\n (record?.versions ?? []).map((version) => ({\n formVersion:\n record?.formVersions.find(\n (formVersion) => formVersion.id === version.formDefinitionVersionId,\n )?.label ?? '未綁定',\n key: version.id,\n publishedAt: formatDateTime(version.publishedAt),\n status: version.status,\n updatedAt: formatDateTime(version.updatedAt),\n version: `v${version.version}`,\n versionId: version.id,\n })),\n [record],\n );\n const columns = useMemo(\n (): TableColumn<VersionRow>[] => [\n { dataIndex: 'version', key: 'version', title: '版本', width: 100 },\n { dataIndex: 'status', key: 'status', title: '狀態', width: 140 },\n {\n dataIndex: 'formVersion',\n key: 'formVersion',\n title: '表單版本',\n width: 220,\n },\n {\n dataIndex: 'publishedAt',\n key: 'publishedAt',\n title: '發布時間',\n width: 200,\n },\n {\n dataIndex: 'updatedAt',\n key: 'updatedAt',\n title: '更新時間',\n width: 200,\n },\n ],\n [],\n );\n const actions = useMemo(\n (): TableActions<VersionRow> => ({\n render: (row): ReturnType<TableActions<VersionRow>['render']> => [\n {\n disabled: (): boolean => rollingBack || row.status === 'DRAFT',\n name: 'Rollback',\n onClick: (): void => void handleRollback(row.versionId),\n },\n ],\n variant: 'base-secondary',\n width: 104,\n }),\n [rollingBack],\n );\n\n async function refreshVersions(): Promise<void> {\n setLoading(true);\n setError(null);\n\n try {\n setRecord(await readTemplateDesigner(templateId));\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setLoading(false);\n }\n }\n\n async function handleRollback(versionId: string): Promise<void> {\n setRollingBack(true);\n setError(null);\n\n try {\n await rollbackApprovalTemplateVersion(versionId);\n await refreshVersions();\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setRollingBack(false);\n }\n }\n\n return (\n <>\n <PageHeader>\n <ContentHeader\n description=\"查看發布、歸檔與 rollback 狀態。\"\n onBackClick={(): void => router.push(routes.templates())}\n title={record?.template.name ?? '模板版本'}\n />\n </PageHeader>\n\n <SectionGroup>\n <Section>\n {error ? (\n <Typography color=\"text-error\" variant=\"body\">\n {error}\n </Typography>\n ) : null}\n <Table\n actions={actions}\n columns={columns}\n dataSource={rows}\n fullWidth\n loading={loading}\n />\n </Section>\n </SectionGroup>\n </>\n );\n}\n\nfunction readErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : '發生未知錯誤';\n}\n"],"mappings":";;;;;;;;;;AAqCA,SAAgB,EAAqB,EACnC,iBAC0C;CAC1C,IAAM,IAAS,EAAiB,GAC1B,IAAS,EAAa,GACtB,CAAC,GAAQ,KAAa,EAAwC,IAAI,GAClE,CAAC,GAAO,KAAY,EAAwB,IAAI,GAChD,CAAC,GAAS,KAAc,EAAS,EAAI,GACrC,CAAC,GAAa,KAAkB,EAAS,EAAK;CAEpD,QAAsB;EACpB,EAAqB;CACvB,GAAG,CAAC,CAAU,CAAC;CAEf,IAAM,IAAO,SAER,GAAQ,YAAY,CAAC,EAAA,CAAG,KAAK,OAAa;EACzC,aACE,GAAQ,aAAa,MAClB,MAAgB,EAAY,OAAO,EAAQ,uBAC9C,CAAC,EAAE,SAAS;EACd,KAAK,EAAQ;EACb,aAAa,EAAe,EAAQ,WAAW;EAC/C,QAAQ,EAAQ;EAChB,WAAW,EAAe,EAAQ,SAAS;EAC3C,SAAS,IAAI,EAAQ;EACrB,WAAW,EAAQ;CACrB,EAAE,GACJ,CAAC,CAAM,CACT,GACM,IAAU,QACmB;EAC/B;GAAE,WAAW;GAAW,KAAK;GAAW,OAAO;GAAM,OAAO;EAAI;EAChE;GAAE,WAAW;GAAU,KAAK;GAAU,OAAO;GAAM,OAAO;EAAI;EAC9D;GACE,WAAW;GACX,KAAK;GACL,OAAO;GACP,OAAO;EACT;EACA;GACE,WAAW;GACX,KAAK;GACL,OAAO;GACP,OAAO;EACT;EACA;GACE,WAAW;GACX,KAAK;GACL,OAAO;GACP,OAAO;EACT;CACF,GACA,CAAC,CACH,GACM,IAAU,SACmB;EAC/B,SAAS,MAAwD,CAC/D;GACE,gBAAyB,KAAe,EAAI,WAAW;GACvD,MAAM;GACN,eAAqB,KAAK,EAAe,EAAI,SAAS;EACxD,CACF;EACA,SAAS;EACT,OAAO;CACT,IACA,CAAC,CAAW,CACd;CAEA,eAAe,IAAiC;EAE9C,AADA,EAAW,EAAI,GACf,EAAS,IAAI;EAEb,IAAI;GACF,EAAU,MAAM,EAAqB,CAAU,CAAC;EAClD,SAAS,GAAuB;GAC9B,EAAS,EAAiB,CAAY,CAAC;EACzC,UAAU;GACR,EAAW,EAAK;EAClB;CACF;CAEA,eAAe,EAAe,GAAkC;EAE9D,AADA,EAAe,EAAI,GACnB,EAAS,IAAI;EAEb,IAAI;GAEF,AADA,MAAM,EAAgC,CAAS,GAC/C,MAAM,EAAgB;EACxB,SAAS,GAAuB;GAC9B,EAAS,EAAiB,CAAY,CAAC;EACzC,UAAU;GACR,EAAe,EAAK;EACtB;CACF;CAEA,OACE,kBAAA,GAAA,EAAA,UAAA,CACI,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;EACE,aAAY;EACZ,mBAAyB,EAAO,KAAK,EAAO,UAAU,CAAC;EACvD,OAAO,GAAQ,SAAS,QAAQ;CACjC,CAAA,EACS,CAAA,GAEZ,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD,EAAA,UAAA,CACG,IACC,kBAAC,GAAD;EAAY,OAAM;EAAa,SAAQ;EACpC,UAAA;CACS,CAAA,IACV,MACJ,kBAAC,GAAD;EACW;EACA;EACT,YAAY;EACZ,WAAA;EACS;CACV,CAAA,CACM,EAAA,CAAA,EACG,CAAA,CACd,EAAA,CAAA;AAER;AAEA,SAAS,EAAiB,GAAwB;CAChD,OAAO,aAAiB,QAAQ,EAAM,UAAU;AAClD"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rytass/bpm-core-react",
3
- "version": "0.10.0",
3
+ "version": "0.12.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",
@@ -286,8 +286,8 @@
286
286
  "@mezzanine-ui/core": ">=1.0.0",
287
287
  "@mezzanine-ui/icons": ">=1.0.0",
288
288
  "@mezzanine-ui/react": ">=1.0.0",
289
- "@rytass/bpm-core-client": "^0.10.0",
290
- "@rytass/bpm-core-shared": "^0.10.0",
289
+ "@rytass/bpm-core-client": "^0.12.0",
290
+ "@rytass/bpm-core-shared": "^0.12.0",
291
291
  "@uiw/react-codemirror": ">=4.0.0",
292
292
  "@xyflow/react": ">=12.0.0",
293
293
  "ai": ">=6.0.0",
@@ -1,3 +0,0 @@
1
- "use client";const e=require("./chunk-CMqjfN_6.cjs"),t=require("./bpm-form-field-Bc6k4ZEO.cjs"),n=require("./FormRendererView-Cw9LiidV.cjs");let r=require("react"),i=require("@mezzanine-ui/react"),a=require("react/jsx-runtime"),o=require("@mezzanine-ui/icons"),s=require("@rytass/bpm-core-client/form"),c=require("@rytass/bpm-core-shared/form"),l=require("@hello-pangea/dnd"),u=require("next/dynamic");u=e.t(u,1);let d=require("@codemirror/lang-json"),f=require("@codemirror/view");var p={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%`},m=[(0,d.json)(),f.EditorView.lineWrapping,f.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`}})],h=(0,u.default)(()=>import(`@uiw/react-codemirror`),{loading:()=>(0,a.jsx)(`div`,{style:p,children:`載入 JSON 編輯器`}),ssr:!1});function ee({disabled:e=!1,height:t,name:n,onChange:r,placeholder:i,value:o}){return(0,a.jsx)(h,{"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:[...m],height:t,indentWithTab:!1,onChange:r,placeholder:i,readOnly:e,theme:`light`,value:o,width:`100%`})}var g=[{description:`單行文字、姓名、編號`,icon:o.AlignLeftIcon,label:`文字`,type:`text`},{description:`多行補充內容`,icon:o.FileIcon,label:`長文字`,type:`textarea`},{description:`金額、數量、分數`,icon:o.CurrencyDollarIcon,label:`數字`,type:`number`},{description:`金額與費用`,icon:o.CurrencyDollarIcon,label:`金額`,type:`money`},{description:`日期或到期日`,icon:o.CalendarIcon,label:`日期`,type:`date`},{description:`日期與時間`,icon:o.CalendarIcon,label:`日期時間`,type:`datetime`},{description:`是 / 否狀態`,icon:o.CheckedIcon,label:`開關`,type:`boolean`},{description:`固定選項擇一`,icon:o.ListIcon,label:`下拉選單`,type:`select`},{description:`可搜尋的固定選項`,icon:o.ListIcon,label:`自動完成`,type:`autocomplete`},{description:`固定選項單選`,icon:o.DotGridIcon,label:`單選`,type:`radio`},{description:`固定選項複選`,icon:o.CheckedOutlineIcon,label:`複選`,type:`checkbox`},{description:`附件或佐證資料`,icon:o.FileAttachmentIcon,label:`附件`,type:`file_upload`}],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},_={display:`grid`,gap:12},ie={display:`flex`,flexWrap:`wrap`,gap:6},ae={flex:`0 0 auto`,whiteSpace:`nowrap`},oe={display:`grid`,gap:8},se={alignItems:`center`,cursor:`grab`,display:`flex`,gap:12,touchAction:`none`},ce={display:`grid`,flex:`1 1 auto`,gap:2,minWidth:0},le={alignItems:`center`,display:`flex`,flex:`0 0 auto`,gap:4},ue={alignItems:`center`,display:`flex`,gap:6},de={cursor:`pointer`,userSelect:`none`},fe={filter:`drop-shadow(0 8px 18px rgba(0, 0, 0, 0.12))`},pe={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)`},me={alignItems:`center`,border:`1px dashed var(--mzn-color-border-neutral)`,borderRadius:6,display:`grid`,gap:12,minHeight:240,padding:32,textAlign:`center`},he={display:`flex`,gap:8,justifyContent:`center`},ge={display:`grid`,gap:14},_e={display:`grid`,columnGap:16,gridTemplateColumns:`repeat(auto-fit, minmax(280px, 1fr))`,rowGap:8},ve={gridColumn:`1 / -1`},ye={alignItems:`center`,display:`flex`,gap:8,gridColumn:`1 / -1`,justifyContent:`flex-end`},be={gridColumn:`1 / -1`},xe={alignItems:`start`,display:`block`,width:`100%`},Se={...xe,gridColumn:`1 / -1`},Ce={minWidth:0,width:`100%`},we={minWidth:`100%`,width:`100%`},Te={display:`grid`,gap:14},Ee={alignItems:`start`,display:`block`,width:`100%`},De={minWidth:0,width:`100%`},Oe={gridColumn:`2 / -1`},ke={display:`grid`,gap:10,width:`100%`},Ae={display:`grid`,gap:8,gridTemplateColumns:`repeat(auto-fit, minmax(160px, 1fr))`},je={display:`inline-flex`},Me={display:`grid`,gap:16},v={display:`grid`,gap:8},y={display:`flex`,justifyContent:`flex-end`},Ne={color:`var(--mzn-color-text-error)`,fontSize:`0.72em`,lineHeight:0,marginLeft:2,verticalAlign:`super`},Pe={display:`grid`,gap:10,gridColumn:`1 / -1`},Fe={backgroundColor:`var(--mzn-color-bg-surface-secondary)`,borderRadius:6,display:`grid`,gap:4,padding:10},Ie={display:`grid`,gap:8,gridTemplateColumns:`minmax(180px, 0.7fr) minmax(220px, 1.3fr)`};function Le(e){e&&(e.style.width=`100%`)}var Re={fields:[],schemaVersion:1},ze={layout:[],schemaVersion:1},b=`__STATIC_OPTIONS__`,x=`__CONSTANT__`,S=`__UNBOUND__`,Be=[{id:b,name:`靜態選項`}],C=[{id:`single`,name:`單選`},{id:`multiple`,name:`複選`}],Ve=[{id:`unset`,name:`不預設`},{id:`true`,name:`是`},{id:`false`,name:`否`}],He=[{id:`true`,name:`是`},{id:`false`,name:`否`}],Ue=[{label:`顯示`,name:`fieldVisibleWhen`,supportingText:`符合條件時才顯示這個欄位。`,target:`visibleWhen`},{label:`必填`,name:`fieldRequiredWhen`,supportingText:`符合條件時才要求填寫這個欄位。`,target:`requiredWhen`},{label:`唯讀`,name:`fieldReadonlyWhen`,supportingText:`符合條件時不允許修改這個欄位。`,target:`readonlyWhen`}];function w({onChange:e,value:u}){let d=u?.schema??Re,f=u?.uiSchema??ze,[p,m]=(0,r.useState)(d),[h,w]=(0,r.useState)(f),[O,k]=(0,r.useState)(D(d)),[rt,A]=(0,r.useState)(D(f)),[it,at]=(0,r.useState)({}),[ot,j]=(0,r.useState)(null),[M,N]=(0,r.useState)(`design`),[P,F]=(0,r.useState)(null),[I,st]=(0,r.useState)([]),[L,ct]=(0,r.useState)(null),[lt,ut]=(0,r.useState)(`loading`),[R,z]=(0,r.useState)(null),[dt,ft]=(0,r.useState)(!1),[B,V]=(0,r.useState)(null);(0,r.useEffect)(()=>{let e=!0;return(0,s.listFormDataSources)().then(t=>{e&&(st(t),ct(null),ut(`ready`))}).catch(t=>{e&&(st([]),ct(`目前無法載入 DataSource Catalog,請稍後重試。`),ut(`unavailable`))}),()=>{e=!1}},[]),(0,r.useEffect)(()=>{p.fields.some(e=>e.fieldKey===P)||F(p.fields[0]?.fieldKey??null)},[p.fields,P]),(0,r.useEffect)(()=>{at(e=>(0,s.buildFormRendererValues)(p.fields,e))},[p.fields]),(0,r.useEffect)(()=>{M!==`advanced`&&(k(D(p)),A(D(h)))},[M,p,h]);let H=(0,r.useMemo)(()=>p.fields.find(e=>e.fieldKey===P)??p.fields[0]??null,[p.fields,P]);(0,r.useEffect)(()=>{e?.({schema:p,uiSchema:h})},[p,h]);function U(e){let t=(0,s.createFieldDefinition)(e,p.fields.length+1);m({...p,fields:[...p.fields,t]}),w({...h,layout:[...h.layout,{fieldKey:t.fieldKey,width:e===`textarea`||e===`file_upload`?`FULL`:`HALF`}]}),F(t.fieldKey),N(`design`),j(null)}function pt(e){let t=e;t===`advanced`&&M!==`advanced`&&(k(D(p)),A(D(h))),N(t)}function mt(e){let t=p.fields.flatMap(t=>(0,c.isFormDataSourceFieldDefinition)(t)&&(0,s.readFormDataSourceFieldDependencyKeys)(t).includes(e)?[t.fieldKey]:[]);if(t.length>0){V({affectedFieldKeys:t,fieldKey:e,kind:`remove-field`});return}ht(e)}function ht(e){let t=p.fields.filter(t=>t.fieldKey!==e);m({...p,fields:t}),w({...h,layout:h.layout.filter(t=>t.fieldKey!==e)}),F(P===e?t[0]?.fieldKey??null:P),j(null),z(null)}function gt(e){let t=e.destination;t&&e.source.index!==t.index&&(m(n=>({...n,fields:nt(n.fields,e.source.index,t.index)})),w(n=>({...n,layout:nt(n.layout,e.source.index,t.index)})),j(null))}function W(e){G(t=>({...t,...e}))}function G(e){if(!H)return;let t=H.fieldKey,n=e(H),r=n.fieldKey,i={...p,fields:p.fields.map(e=>e.fieldKey===t?n:e)};m(t===r?i:(0,s.renameFormDataSourceFieldBindings)(i,t,r)),w({...h,layout:h.layout.map(e=>e.fieldKey===t?{...e,fieldKey:r}:e)}),F(r),j(null),z(null)}function K(e){G(t=>Ze(t)?{...t,...e}:t)}function q(e){G(t=>(0,s.isNumberFieldDefinition)(t)?{...t,...e}:t)}function _t(e){G(t=>(0,s.isDateFieldDefinition)(t)?{...t,...e}:t)}function J(e){G(t=>(0,s.isSelectFieldDefinition)(t)?{...t,...e}:t)}function vt(e){if(!H||H.type!==`select`&&H.type!==`autocomplete`||(0,c.readFormFieldSelectionMode)(H)===e)return;let t=H.defaultValue,n=e===`multiple`?typeof t==`string`?[t]:t:Array.isArray(t)?t[0]:t;Y(H,{...H,defaultValue:n,mode:e},`選擇模式變更可能轉換或捨棄既有預設值。`)}function Y(e,t,n=`此變更會替換目前選項來源;既有 options、dynamic reference 或 bindings 可能失效。`){JSON.stringify(e)!==JSON.stringify(t)&&V({fieldKey:e.fieldKey,impact:n,kind:`replace-field`,nextField:t})}function yt(e,t){if(!t)return;if(t===b){if(!(0,c.isFormDataSourceFieldDefinition)(e))return;let{dataSource:t,defaultValue:n,...r}=e;Y(e,{...r,options:[]});return}let n=I.find(e=>T(e)===t);if(!n)return;if((0,c.isFormDataSourceFieldDefinition)(e)){let t=new Set(n.parameters.map(e=>e.key)),r=e.dataSource.bindings.filter(e=>t.has(e.parameter));Y(e,{...e,dataSource:{bindings:r,key:n.key,version:n.version}});return}let{options:r,defaultValue:i,...a}=e;Y(e,{...a,dataSource:{bindings:[],key:n.key,version:n.version}})}function bt(){B&&(B.kind===`remove-field`?ht(B.fieldKey):(m({...p,fields:p.fields.map(e=>e.fieldKey===B.fieldKey?B.nextField:e)}),j(null),z(null)),V(null))}async function xt(){ft(!0);try{z((await(0,s.lintFormSchema)(p,h)).errors.map(s.readFormSchemaLintMessage))}catch{z([`目前無法完成 DataSource schema 驗證。`])}finally{ft(!1)}}function St(e){G(t=>t.type===`boolean`?{...t,...e}:t)}function Ct(e){G(t=>t.type===`file_upload`?{...t,...e}:t)}function wt(e){at(e)}function Tt(e,t){m(n=>({...n,fields:n.fields.map(n=>n.fieldKey===e?{...n,required:t}:n)})),j(null)}function Et(e){k(e);try{m(JSON.parse(e)),j(null)}catch{j(`Form Schema JSON 格式不正確`)}}function Dt(e){A(e);try{w(JSON.parse(e)),j(null)}catch{j(`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:Me,children:[(0,a.jsxs)(i.Tab,{activeKey:M,onChange:pt,size:`sub`,children:[(0,a.jsx)(i.TabItem,{children:`設計`},`design`),(0,a.jsx)(i.TabItem,{children:`預覽`},`preview`),(0,a.jsx)(i.TabItem,{children:`進階`},`advanced`)]}),M===`design`?Ot():null,M===`preview`?en():null,M===`advanced`?tn():null]})})})}),B?(0,a.jsx)(i.Modal,{cancelText:`返回`,confirmText:`確認變更`,modalType:`standard`,onCancel:()=>V(null),onClose:()=>V(null),onConfirm:bt,open:!0,showModalFooter:!0,showModalHeader:!0,title:B.kind===`remove-field`?`確認移除 dependency 欄位`:`確認替換選項來源`,children:B.kind===`remove-field`?(0,a.jsxs)(`div`,{style:v,children:[(0,a.jsx)(i.Typography,{variant:`body`,children:`此欄位仍被下列 DataSource binding 使用;移除後請重新設定這些欄位。`}),(0,a.jsx)(i.Typography,{color:`text-warning`,variant:`body`,children:B.affectedFieldKeys.join(`、`)})]}):(0,a.jsxs)(i.Typography,{variant:`body`,children:[B.impact,`確認後才會寫入 schema。`]})}):null]});function Ot(){return(0,a.jsxs)(`div`,{style:_,children:[(0,a.jsxs)(`div`,{style:oe,children:[(0,a.jsx)(i.Typography,{component:`h2`,variant:`label-primary`,children:`新增欄位`}),(0,a.jsx)(`div`,{style:ie,children:g.map(e=>(0,a.jsx)(i.Button,{icon:e.icon,iconType:`leading`,onClick:()=>U(e.type),size:`sub`,style:ae,type:`button`,variant:`base-secondary`,children:e.label},e.type))})]}),(0,a.jsxs)(`div`,{style:te,children:[(0,a.jsxs)(`div`,{style:{..._,...ne},children:[(0,a.jsx)(i.Typography,{component:`h2`,variant:`label-primary`,children:`表單畫布`}),p.fields.length>0?(0,a.jsx)(l.DragDropContext,{onDragEnd:gt,children:(0,a.jsx)(l.Droppable,{droppableId:`form-builder-fields`,children:e=>(0,a.jsxs)(`div`,{...e.droppableProps,ref:e.innerRef,style:_,children:[p.fields.map((e,t)=>(0,a.jsx)(l.Draggable,{draggableId:e.fieldKey,index:t,children:(t,n)=>Qt(e,t,n.isDragging)},e.fieldKey)),e.placeholder]})})}):(0,a.jsxs)(`div`,{style:me,children:[(0,a.jsxs)(`div`,{style:_,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:he,children:[(0,a.jsx)(i.Button,{onClick:()=>U(`text`),variant:`base-primary`,children:`新增文字欄位`}),(0,a.jsx)(i.Button,{onClick:()=>U(`textarea`),variant:`base-secondary`,children:`新增長文字`})]})]})]}),(0,a.jsxs)(`div`,{style:{..._,...re},children:[(0,a.jsx)(i.Typography,{component:`h2`,variant:`label-primary`,children:`欄位設定`}),H?kt(H):(0,a.jsx)(i.Typography,{color:`text-neutral`,variant:`body`,children:`請先新增或選取欄位。`})]})]})]})}function kt(e){return(0,a.jsxs)(`div`,{style:ge,children:[At(e),jt(e)]})}function At(e){return(0,a.jsxs)(`div`,{style:_e,children:[(0,a.jsx)(`div`,{style:ye,children:(0,a.jsx)(i.Badge,{size:`main`,text:We(e.type),variant:`text-info`})}),Q(`標題`,`fieldLabel`,(0,a.jsx)(i.Input,{onChange:e=>W({label:e.target.value}),placeholder:`例如:申請金額`,value:e.label,variant:`base`})),Q(`欄位 Key`,`fieldKey`,(0,a.jsx)(i.Input,{onChange:e=>W({fieldKey:e.target.value}),placeholder:`例如:amount`,value:e.fieldKey,variant:`base`})),Q(`提示文字`,`fieldPlaceholder`,(0,a.jsx)(i.Input,{onChange:e=>W({placeholder:e.target.value||void 0}),placeholder:`例如:請輸入申請金額`,value:e.placeholder??``,variant:`base`})),Mt(e)]})}function jt(e){return(0,a.jsx)(i.Accordion,{defaultExpanded:Ye(e),size:`sub`,title:`進階設定`,children:(0,a.jsxs)(`div`,{style:_e,children:[(0,a.jsx)(i.Typography,{component:`h3`,style:ve,variant:`label-primary`,children:`條件規則`}),(0,a.jsx)(i.Typography,{color:`text-neutral`,style:be,variant:`body`,children:`只有需要根據其他欄位改變顯示、必填或唯讀狀態時才需要設定。`}),Kt(e)]})})}function Mt(e){return Ze(e)?Nt(e):(0,s.isNumberFieldDefinition)(e)?Pt(e):(0,s.isDateFieldDefinition)(e)?Ft(e):(0,c.isFormOptionFieldDefinition)(e)?It(e):e.type===`boolean`?Wt(e):Gt(e)}function Nt(e){return(0,a.jsxs)(a.Fragment,{children:[Q(`預設值`,`fieldDefaultValue`,e.type===`textarea`?Yt({name:`fieldDefaultValue`,onChange:e=>K({defaultValue:e||void 0}),placeholder:`輸入此欄位的預設文字`,rows:3,value:E(e.defaultValue)}):(0,a.jsx)(i.Input,{onChange:e=>K({defaultValue:e.target.value||void 0}),placeholder:`輸入此欄位的預設文字`,value:E(e.defaultValue),variant:`base`})),Q(`最小長度`,`fieldMinLength`,Z(e.minLength,e=>K({minLength:e}),`例如:2`,{min:0})),Q(`最大長度`,`fieldMaxLength`,Z(e.maxLength,e=>K({maxLength:e}),`例如:100`,{min:1}))]})}function Pt(e){return(0,a.jsxs)(a.Fragment,{children:[Q(`預設值`,`fieldDefaultValue`,Z(typeof e.defaultValue==`number`?e.defaultValue:void 0,e=>q({defaultValue:e}),e.type===`money`?`例如:1000`:`輸入預設數值`,{max:e.maximum,min:e.minimum})),Q(`最小值`,`fieldMinimum`,Z(e.minimum,e=>q({minimum:e}),`例如:0`)),Q(`最大值`,`fieldMaximum`,Z(e.maximum,e=>q({maximum:e}),`例如:999999`))]})}function Ft(e){return Q(`預設值`,`fieldDefaultValue`,Xt(e,E(e.defaultValue),e=>_t({defaultValue:e})))}function It(e){let t=(0,s.readCompatibleFormDataSourceDescriptors)(e.type,I),n=(0,c.isFormDataSourceFieldDefinition)(e)?T(e.dataSource):b,r=(0,c.isFormDataSourceFieldDefinition)(e)?I.find(t=>t.key===e.dataSource.key&&t.version===e.dataSource.version):null,o=r?t.some(e=>e.key===r.key&&e.version===r.version):!1,l=[...Be,...t.map(Ge),...(0,c.isFormDataSourceFieldDefinition)(e)&&!o?[{id:n,name:`${e.dataSource.key} v${e.dataSource.version}(目前不可用或不支援)`}]:[]],u=(0,c.readFormFieldSelectionMode)(e);return(0,a.jsxs)(a.Fragment,{children:[e.type===`select`||e.type===`autocomplete`?Q(`選擇模式`,`fieldSelectionMode`,(0,a.jsx)(i.Select,{clearable:!1,onChange:e=>{(e?.id===`single`||e?.id===`multiple`)&&vt(e.id)},options:[...C],value:(0,s.readSelectOption)(C,u)})):Q(`選擇模式`,`fieldSelectionMode`,(0,a.jsx)(i.Typography,{color:`text-neutral`,variant:`body`,children:u===`multiple`?`固定複選`:`固定單選`})),Q(`選項來源`,`fieldOptionSource`,(0,a.jsx)(i.Select,{clearable:!1,disabled:lt===`loading`&&!(0,c.isFormDataSourceFieldDefinition)(e),onChange:t=>yt(e,t?.id),options:l,placeholder:`選擇選項來源`,value:(0,s.readSelectOption)(l,n)})),(0,c.isFormDataSourceFieldDefinition)(e)?Lt(e,t):Ut(e)]})}function Lt(e,t){let n=I.find(t=>t.key===e.dataSource.key&&t.version===e.dataSource.version),r=n&&!(0,s.isFormDataSourceDescriptorCompatible)(n,e.type);return(0,a.jsxs)(`div`,{style:Pe,children:[lt===`loading`?(0,a.jsx)(i.Typography,{color:`text-neutral`,variant:`body`,children:`正在載入可用的 DataSource Catalog…`}):null,L?(0,a.jsx)(i.Typography,{color:`text-error`,variant:`body`,children:L}):null,n?null:(0,a.jsx)(i.Typography,{color:`text-warning`,variant:`body`,children:`目前來源版本未出現在 Catalog;會保留原設定,但在環境 lint 通過前不可發布。`}),r?(0,a.jsx)(i.Typography,{color:`text-error`,variant:`body`,children:`目前來源不支援此控制項或超出 bounded list 限制,請選擇其他版本。`}):null,n?Rt(n):null,n?n.parameters.map(t=>zt(e,t)):null,t.length===0&&!L?(0,a.jsx)(i.Typography,{color:`text-warning`,variant:`body`,children:`沒有符合目前控制項能力的已註冊來源。`}):null,(0,a.jsx)(`div`,{style:y,children:(0,a.jsx)(i.Button,{disabled:dt,onClick:()=>void xt(),size:`sub`,type:`button`,variant:`base-secondary`,children:dt?`驗證中…`:`驗證 DataSource 設定`})}),R?(0,a.jsx)(i.Typography,{color:R.length>0?`text-error`:`text-success`,variant:`caption`,children:R.length>0?R.join(`;`):`DataSource schema 與目前環境均通過驗證。`}):null]})}function Rt(e){return(0,a.jsxs)(`div`,{style:Fe,children:[(0,a.jsxs)(i.Typography,{variant:`label-primary`,children:[e.label,` · v`,e.version]}),e.description?(0,a.jsx)(i.Typography,{color:`text-neutral`,variant:`caption`,children:e.description}):null,(0,a.jsxs)(i.Typography,{color:`text-neutral`,variant:`caption`,children:[`支援:`,e.supportedControls.join(`、`),`;`,e.supportsSearch?`支援搜尋`:`不支援搜尋`,`;`,e.paginationMode===`CURSOR`?`支援分頁`:`完整清單`,`; policy:`,e.revalidationPolicy]})]})}function zt(e,n){let r=(0,s.readFormDataSourceBinding)(e,n.key),o=Ke(r),c=(0,s.readCompatibleFormDataSourceBindingFields)(n.type,p.fields,e.fieldKey),l=[...n.required?[]:[{id:S,name:`未綁定`}],...c,...n.type===`STRING_ARRAY`?[]:[{id:x,name:`固定常數`}]];return(0,a.jsxs)(`div`,{style:Ie,children:[(0,a.jsx)(t.t,{label:`${n.label??n.key}${n.required?`(必填)`:`(選填)`}`,name:`dataSourceParameter_${n.key}`,children:(0,a.jsx)(i.Select,{clearable:!1,onChange:t=>Vt(e,n.key,n.type,t?.id),options:l,placeholder:`選擇欄位或常數`,value:(0,s.readSelectOption)(l,o)})}),(0,s.readFormDataSourceBindingValueKind)(r)===`CONSTANT`?Bt(e,n.key,n.type,r):(0,s.readFormDataSourceBindingValueKind)(r)===`FIELD`?(0,a.jsxs)(i.Typography,{color:`text-neutral`,variant:`caption`,children:[`使用表單欄位「`,r?.from.kind===`FIELD`?r.from.fieldKey:``,`」的目前值。`]}):(0,a.jsx)(i.Typography,{color:`text-neutral`,variant:`caption`,children:n.required?c.length>0?`請選擇相容的表單欄位或固定常數。`:`目前沒有型別相容的表單欄位,請先建立 dependency。`:`此參數可不綁定。`})]},n.key)}function Bt(e,t,n,r){let o=(0,s.readFormDataSourceBindingValue)(e,t);if(n===`BOOLEAN`){let e=[{id:`true`,name:`是`},{id:`false`,name:`否`}];return(0,a.jsx)(i.Select,{clearable:!1,onChange:e=>Ht(t,e?.id===`true`),options:e,value:(0,s.readSelectOption)(e,o===!0?`true`:`false`)})}return n===`STRING_ARRAY`?(0,a.jsx)(i.Typography,{color:`text-warning`,variant:`caption`,children:`STRING_ARRAY 參數請綁定複選欄位;目前不接受固定常數。`}):(0,a.jsx)(i.Input,{onChange:e=>Ht(t,n===`NUMBER`?(0,s.parseOptionalNumberInput)(e.target.value)??0:e.target.value),placeholder:n===`NUMBER`?`輸入數字`:`輸入固定值`,value:Je(r,n),variant:`base`})}function Vt(e,t,n,r){if(!r||r===S){G(e=>(0,c.isFormDataSourceFieldDefinition)(e)?(0,s.upsertFormDataSourceFieldBinding)(e,t,null):e);return}if(r===x){G(e=>(0,c.isFormDataSourceFieldDefinition)(e)?(0,s.upsertFormDataSourceFieldBinding)(e,t,{from:{kind:`CONSTANT`,value:qe(n)},parameter:t}):e);return}G(e=>(0,c.isFormDataSourceFieldDefinition)(e)?(0,s.upsertFormDataSourceFieldBinding)(e,t,{from:{fieldKey:r,kind:`FIELD`},parameter:t}):e)}function Ht(e,t){G(n=>(0,c.isFormDataSourceFieldDefinition)(n)?(0,s.upsertFormDataSourceFieldBinding)(n,e,{from:{kind:`CONSTANT`,value:t},parameter:e}):n)}function Ut(e){let t=(0,c.readFormFieldSelectionMode)(e),n=Array.isArray(e.defaultValue)?e.defaultValue:[],r=e.options.map(s.readFieldOptionAsSelectOption),o=r.filter(e=>n.includes(e.id));return(0,a.jsxs)(a.Fragment,{children:[Q(`預設值`,`fieldDefaultValue`,t===`multiple`?(0,a.jsx)(i.Select,{clearable:!0,mode:`multiple`,onChange:e=>J({defaultValue:e.length?e.map(e=>e.id):void 0}),options:r,placeholder:`選擇一或多個預設選項`,value:o}):(0,a.jsx)(i.Select,{clearable:!0,onChange:e=>J({defaultValue:e?.id||void 0}),options:r,placeholder:`選擇預設選項`,value:typeof e.defaultValue==`string`?(0,s.readSelectOption)(r,e.defaultValue):null})),Q(`選項`,`fieldOptions`,Zt(e),!0)]})}function Wt(e){let t=typeof e.defaultValue==`boolean`?String(e.defaultValue):`unset`;return Q(`預設值`,`fieldDefaultValue`,(0,a.jsx)(i.Select,{clearable:!1,onChange:e=>St({defaultValue:e?.id===`true`?!0:e?.id===`false`?!1:void 0}),options:[...Ve],placeholder:`選擇預設狀態`,value:(0,s.readSelectOption)(Ve,t)}))}function Gt(e){return(0,a.jsxs)(a.Fragment,{children:[Q(`檔案數`,`fieldMaxFiles`,Z(e.maxFiles,e=>Ct({maxFiles:e}),`例如:1`,{min:1})),Q(`MIME`,`fieldAcceptedMimeTypes`,Yt({name:`fieldAcceptedMimeTypes`,onChange:e=>Ct({acceptedMimeTypes:Qe(e)}),placeholder:`每行一個 MIME type,例如:application/pdf`,rows:3,value:$e(e.acceptedMimeTypes)}),!1)]})}function Kt(e){let t=p.fields.filter(t=>t.fieldKey!==e.fieldKey);return t.length?(0,a.jsx)(a.Fragment,{children:Ue.map(n=>qt(e,n,t))}):(0,a.jsx)(i.Typography,{color:`text-neutral`,style:be,variant:`body`,children:`目前沒有其他欄位可作為條件來源。新增更多欄位後即可設定條件規則。`})}function qt(e,t,n){let r=e[t.target],o=r?(0,s.parseConditionRule)(r):null,c=n.find(e=>e.fieldKey===o?.fieldKey),l=c??n[0],u=n.map(Xe),d=(0,s.readConditionOperatorOptions)(l),f=o&&d.some(e=>e.id===o.operator)?o.operator:(0,s.readDefaultConditionOperator)(l),p=o?.value??(0,s.readDefaultConditionValue)(l),m=!!r,h=m&&(!o||!c);return Q(t.label,t.name,(0,a.jsxs)(`div`,{style:ke,children:[(0,a.jsx)(i.Toggle,{checked:m,label:m?`已啟用`:`不啟用`,onChange:e=>X(t.target,e.target.checked?(0,s.buildConditionExpression)(l,(0,s.readDefaultConditionOperator)(l),(0,s.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:Ae,children:[(0,a.jsx)(i.Select,{clearable:!1,onChange:e=>{let r=n.find(t=>t.fieldKey===e?.id)??l;X(t.target,(0,s.buildConditionExpression)(r,(0,s.readDefaultConditionOperator)(r),(0,s.readDefaultConditionValue)(r)))},options:u,placeholder:`選擇欄位`,value:(0,s.readSelectOption)(u,l.fieldKey)}),(0,a.jsx)(i.Select,{clearable:!1,onChange:e=>X(t.target,(0,s.buildConditionExpression)(l,(0,s.readConditionOperatorOption)(e?.id)??f,p)),options:[...d],placeholder:`判斷方式`,value:(0,s.readSelectOption)(d,f)}),Jt(l,p,e=>X(t.target,(0,s.buildConditionExpression)(l,f,e)))]}):null]}),!0)}function X(e,t){W({[e]:t})}function Jt(e,t,n){if(e.type===`boolean`)return(0,a.jsx)(i.Select,{clearable:!1,onChange:e=>n(e?.id??`true`),options:[...He],placeholder:`比較值`,value:(0,s.readSelectOption)(He,t===`false`?`false`:`true`)});if((0,s.isSelectFieldDefinition)(e)){let r=e.options.map(s.readFieldOptionAsSelectOption);return(0,a.jsx)(i.Select,{clearable:!1,onChange:e=>n(e?.id??r[0]?.id??``),options:r,placeholder:`比較值`,value:(0,s.readSelectOption)(r,t)})}return(0,s.isNumberFieldDefinition)(e)?Z((0,s.parseOptionalNumberInput)(t),e=>n(String(e??0)),`比較值`):(0,s.isDateFieldDefinition)(e)?Xt(e,t,e=>n(e??``)):(0,a.jsx)(i.Input,{onChange:e=>n(e.target.value),placeholder:`比較值`,value:t,variant:`base`})}function Yt({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:Le,resize:`vertical`,rows:r,style:we,value:o})}function Z(e,t,n,r={}){return(0,a.jsx)(i.Input,{max:r.max,min:r.min,onChange:e=>t((0,s.clampOptionalNumber)((0,s.parseOptionalNumberInput)(e.target.value),r)),placeholder:n,showSpinner:!0,step:r.step??1,value:typeof e==`number`?String(e):``,variant:`measure`})}function Xt(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,s.formatDateTimePickerValue)(e)),placeholderLeft:`選擇日期`,placeholderRight:`選擇時間`,value:(0,s.readDatePickerValue)(t)}):(0,a.jsx)(i.DatePicker,{format:`YYYY-MM-DD`,onChange:e=>n((0,s.formatDatePickerValue)(e)),placeholder:`選擇日期`,value:(0,s.readDatePickerValue)(t)})}function Zt(e){return(0,a.jsxs)(`div`,{style:v,children:[(0,a.jsx)(i.Table,{actions:{render:t=>[{disabled:()=>e.options.length<=1,icon:o.TrashIcon,iconType:`icon-only`,name:`移除選項`,onClick:()=>J({options:e.options.filter((e,n)=>n!==t.index)}),variant:`destructive-ghost`}],width:56},columns:[{key:`label`,render:t=>(0,a.jsx)(i.Input,{onChange:n=>J({options:et(e.options,t.index,{label:n.target.value})}),placeholder:`例如:主管`,size:`sub`,value:t.label,variant:`base`}),title:`Label`},{key:`value`,render:t=>(0,a.jsx)(i.Input,{onChange:n=>J({options:et(e.options,t.index,{value:n.target.value})}),placeholder:`例如:manager`,size:`sub`,value:t.value,variant:`base`}),title:`Value`}],dataSource:e.options.map((t,n)=>({index:n,key:`${e.fieldKey}-${n}`,label:t.label,value:t.value})),showHeader:!0,size:`sub`}),(0,a.jsx)(`div`,{style:y,children:(0,a.jsx)(i.Button,{icon:o.PlusIcon,iconType:`leading`,onClick:()=>J({options:[...e.options,tt(e.options)]}),variant:`base-secondary`,children:`新增選項`})})]})}function Qt(e,t,n){return(0,a.jsx)(`div`,{...t.draggableProps,"data-form-builder-field-key":e.fieldKey,ref:t.innerRef,style:{...de,...n?fe:null,...t.draggableProps.style},children:(0,a.jsx)(i.BaseCard,{style:e.fieldKey===H?.fieldKey?pe:void 0,children:$t(e,t,n)})})}function Q(e,n,r,i=!1){return(0,a.jsx)(`div`,{style:i?Se:xe,children:(0,a.jsx)(`div`,{style:Ce,children:(0,a.jsx)(t.t,{label:e,name:n,children:r})})})}function $t(e,t,n){return(0,a.jsxs)(`div`,{...t.dragHandleProps??{},"aria-label":`選取或拖曳排序欄位`,onClick:()=>F(e.fieldKey),style:se,title:`點擊選取,拖曳排序`,children:[(0,a.jsx)(`span`,{"aria-label":`拖曳排序`,role:`img`,style:je,title:`拖曳排序`,children:(0,a.jsx)(i.Icon,{icon:o.DotDragVerticalIcon,size:20})}),(0,a.jsxs)(`div`,{style:ce,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:Ne,children:`*`}):null]}),(0,a.jsxs)(i.Typography,{color:`text-neutral`,component:`span`,ellipsis:!0,variant:`caption`,children:[We(e.type),` ·`,e.required?` 必填`:` 選填`,` ·`,e.fieldKey]})]}),(0,a.jsxs)(`div`,{onClick:e=>e.stopPropagation(),style:le,children:[(0,a.jsx)(`div`,{style:ue,children:(0,a.jsx)(i.Toggle,{checked:!!e.required,disabled:n,label:`必填`,onChange:t=>Tt(e.fieldKey,t.target.checked)})}),(0,a.jsx)(i.Button,{disabled:n,icon:o.TrashIcon,iconType:`icon-only`,onClick:()=>mt(e.fieldKey),variant:`destructive-ghost`,children:`移除欄位`})]})]})}function en(){return(0,a.jsxs)(`div`,{style:_,children:[(0,a.jsx)(i.Typography,{component:`h2`,variant:`h3`,children:`填寫預覽`}),(0,a.jsx)(n.t,{dataSourceContext:{kind:`preview`},onChange:wt,schema:p,uiSchema:h,value:it})]})}function tn(){return(0,a.jsxs)(`div`,{style:_,children:[(0,a.jsx)(i.Typography,{component:`h2`,variant:`h3`,children:`Schema`}),(0,a.jsxs)(`div`,{style:Te,children:[$(`Form Schema`,`schemaJson`,(0,a.jsx)(ee,{height:`360px`,name:`schemaJson`,onChange:Et,placeholder:`輸入 Form Schema JSON`,value:O})),$(`UI Schema`,`uiSchemaJson`,(0,a.jsx)(ee,{height:`240px`,name:`uiSchemaJson`,onChange:Dt,placeholder:`輸入 UI Schema JSON`,value:rt})),ot?(0,a.jsx)(i.Typography,{color:`text-error`,style:Oe,variant:`body`,children:ot}):null]})]})}function $(e,n,r){return(0,a.jsx)(`div`,{style:Ee,children:(0,a.jsx)(`div`,{style:De,children:(0,a.jsx)(t.t,{label:e,name:n,children:r})})})}}function We(e){return g.find(t=>t.type===e)?.label??e}function T(e){return`${e.key}@${e.version}`}function Ge(e){return{id:T(e),name:`${e.label} · ${e.key} v${e.version}`}}function Ke(e){return e?e.from.kind===`FIELD`?e.from.fieldKey:x:S}function qe(e){switch(e){case`BOOLEAN`:return!1;case`NUMBER`:return 0;case`STRING_ARRAY`:return``;case`STRING`:return``;default:return``}}function Je(e,t){let n=e?.from.kind===`CONSTANT`?e.from.value:``;return t===`NUMBER`?typeof n==`number`?String(n):``:typeof n==`string`?n:``}function Ye(e){return!!(e.visibleWhen||e.requiredWhen||e.readonlyWhen)}function Xe(e){return{id:e.fieldKey,name:e.label}}function Ze(e){return e.type===`text`||e.type===`textarea`}function E(e){return typeof e==`string`?e:``}function Qe(e){let t=e.split(/[\n,]/u).map(e=>e.trim()).filter(Boolean);return t.length?t:void 0}function $e(e){return e?.join(`
2
- `)??``}function D(e){return JSON.stringify(e,null,2)}function et(e,t,n){return e.map((e,r)=>r===t?{...e,...n}:e)}function tt(e){let t=e.length+1;return{label:`選項 ${t}`,value:O(e,t)}}function O(e,t){let n=`option_${t}`;return e.some(e=>e.value===n)?O(e,t+1):n}function nt(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 w}});
3
- //# sourceMappingURL=FormBuilderView-D6baVqBY.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"FormBuilderView-D6baVqBY.cjs","names":[],"sources":["../../src/views/forms/builder/json-code-editor.tsx","../../src/views/forms/builder/FormBuilderView.tsx"],"sourcesContent":["'use client';\n\nimport { CSSProperties, ReactElement } from 'react';\nimport dynamic from 'next/dynamic';\nimport { json } from '@codemirror/lang-json';\nimport { EditorView } from '@codemirror/view';\nimport type { Extension, ReactCodeMirrorProps } from '@uiw/react-codemirror';\n\nconst EDITOR_FALLBACK_STYLE: CSSProperties = {\n alignItems: 'center',\n border: '1px solid var(--mzn-color-border-neutral)',\n borderRadius: 4,\n color: 'var(--mzn-color-text-neutral)',\n display: 'flex',\n minHeight: 160,\n padding: 12,\n width: '100%',\n};\n\nconst JSON_EDITOR_EXTENSIONS: readonly Extension[] = [\n json(),\n EditorView.lineWrapping,\n EditorView.theme({\n '&': {\n border: '1px solid var(--mzn-color-border-neutral)',\n borderRadius: '4px',\n fontSize: '13px',\n width: '100%',\n },\n '&.cm-focused': {\n outline: '1px solid var(--mzn-color-border-primary)',\n },\n '.cm-content': {\n fontFamily:\n 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", monospace',\n minHeight: '100%',\n },\n '.cm-editor': {\n width: '100%',\n },\n '.cm-gutters': {\n borderRight: '1px solid var(--mzn-color-border-neutral)',\n },\n '.cm-scroller': {\n fontFamily:\n 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", monospace',\n },\n }),\n];\n\nconst CodeMirror = dynamic<ReactCodeMirrorProps>(\n () => import('@uiw/react-codemirror'),\n {\n loading: (): ReactElement => (\n <div style={EDITOR_FALLBACK_STYLE}>載入 JSON 編輯器</div>\n ),\n ssr: false,\n },\n);\n\ninterface JsonCodeEditorProps {\n readonly disabled?: boolean;\n readonly height: string;\n readonly name: string;\n readonly onChange: (value: string) => void;\n readonly placeholder: string;\n readonly value: string;\n}\n\nexport function JsonCodeEditor({\n disabled = false,\n height,\n name,\n onChange,\n placeholder,\n value,\n}: JsonCodeEditorProps): ReactElement {\n return (\n <CodeMirror\n aria-label={name}\n basicSetup={{\n autocompletion: true,\n bracketMatching: true,\n closeBrackets: true,\n defaultKeymap: true,\n foldGutter: true,\n highlightActiveLine: true,\n highlightSelectionMatches: true,\n lineNumbers: true,\n syntaxHighlighting: true,\n }}\n editable={!disabled}\n extensions={[...JSON_EDITOR_EXTENSIONS]}\n height={height}\n indentWithTab={false}\n onChange={onChange}\n placeholder={placeholder}\n readOnly={disabled}\n theme=\"light\"\n value={value}\n width=\"100%\"\n />\n );\n}\n","'use client';\n\nimport {\n ChangeEvent,\n CSSProperties,\n Key,\n MouseEvent,\n ReactElement,\n useEffect,\n useMemo,\n useState,\n} from 'react';\nimport {\n DragDropContext,\n Draggable,\n DraggableProvided,\n Droppable,\n DropResult,\n} from '@hello-pangea/dnd';\nimport {\n Accordion,\n BaseCard,\n Badge,\n Button,\n DatePicker,\n DateTimePicker,\n Icon,\n Input,\n Modal,\n Section,\n SectionGroup,\n Select,\n Tab,\n TabItem,\n Table,\n Textarea,\n Toggle,\n Typography,\n} from '@mezzanine-ui/react';\nimport {\n AlignLeftIcon,\n CalendarIcon,\n CheckedIcon,\n CheckedOutlineIcon,\n CurrencyDollarIcon,\n DotDragVerticalIcon,\n DotGridIcon,\n FileAttachmentIcon,\n FileIcon,\n ListIcon,\n PlusIcon,\n TrashIcon,\n} from '@mezzanine-ui/icons';\nimport type { IconDefinition } from '@mezzanine-ui/icons';\nimport type { TableActions, TableColumn } from '@mezzanine-ui/core/table';\nimport {\n BooleanFieldDefinition,\n DateFieldDefinition,\n FormDataSourceBinding,\n FormDataSourceOptionFieldDefinition,\n FileUploadFieldDefinition,\n FormDefinitionSchema,\n FormFieldDefinition,\n FormFieldOption,\n FormOptionFieldDefinition,\n FormStaticOptionFieldDefinition,\n FormUiSchema,\n NumberFieldDefinition,\n TextFieldDefinition,\n isFormDataSourceFieldDefinition,\n isFormOptionFieldDefinition,\n readFormFieldSelectionMode,\n} from '@rytass/bpm-core-shared/form';\nimport {\n createFieldDefinition,\n isFormDataSourceDescriptorCompatible,\n lintFormSchema,\n listFormDataSources,\n readCompatibleFormDataSourceBindingFields,\n readCompatibleFormDataSourceDescriptors,\n readFormDataSourceBinding,\n readFormDataSourceBindingValue,\n readFormSchemaLintMessage,\n readFormDataSourceBindingValueKind,\n readFormDataSourceFieldDependencyKeys,\n renameFormDataSourceFieldBindings,\n upsertFormDataSourceFieldBinding,\n type FormDataSourceDescriptorRecord,\n type FormDataSourceParameterType,\n} from '@rytass/bpm-core-client/form';\nimport {\n buildConditionExpression,\n buildFormRendererValues,\n clampOptionalNumber,\n formatDatePickerValue,\n formatDateTimePickerValue,\n FormRendererValues,\n isDateFieldDefinition,\n isNumberFieldDefinition,\n isSelectFieldDefinition,\n parseConditionRule,\n parseOptionalNumberInput,\n readConditionOperatorOption,\n readConditionOperatorOptions,\n readDatePickerValue,\n readDefaultConditionOperator,\n readDefaultConditionValue,\n readFieldOptionAsSelectOption,\n readSelectOption,\n} from '@rytass/bpm-core-client/form';\nimport { BPMFormField } from '../../../components/bpm-form-field';\nimport { FormRenderer } from '../renderer/FormRendererView';\nimport { JsonCodeEditor } from './json-code-editor';\n\ntype FieldType = FormFieldDefinition['type'];\ntype BuilderTabKey = 'design' | 'preview' | 'advanced';\ntype FieldOptionRow = Readonly<\n Record<string, unknown> & {\n index: number;\n key: string;\n label: string;\n value: string;\n }\n>;\n\ntype FieldTypeOption = Readonly<{\n description: string;\n icon: IconDefinition;\n label: string;\n type: FieldType;\n}>;\n\ntype ConditionRuleTarget = 'readonlyWhen' | 'requiredWhen' | 'visibleWhen';\n\ntype ConditionRuleConfig = Readonly<{\n label: string;\n name: string;\n supportingText: string;\n target: ConditionRuleTarget;\n}>;\n\ntype DataSourceCatalogState = 'loading' | 'ready' | 'unavailable';\ntype FormDataSourceConstantValue = string | number | boolean | null;\n\ntype PendingBuilderConfirmation =\n | Readonly<{\n affectedFieldKeys: readonly string[];\n kind: 'remove-field';\n fieldKey: string;\n }>\n | Readonly<{\n fieldKey: string;\n impact: string;\n kind: 'replace-field';\n nextField: FormFieldDefinition;\n }>;\n\nconst FIELD_TYPE_OPTIONS: readonly FieldTypeOption[] = [\n {\n description: '單行文字、姓名、編號',\n icon: AlignLeftIcon,\n label: '文字',\n type: 'text',\n },\n {\n description: '多行補充內容',\n icon: FileIcon,\n label: '長文字',\n type: 'textarea',\n },\n {\n description: '金額、數量、分數',\n icon: CurrencyDollarIcon,\n label: '數字',\n type: 'number',\n },\n {\n description: '金額與費用',\n icon: CurrencyDollarIcon,\n label: '金額',\n type: 'money',\n },\n {\n description: '日期或到期日',\n icon: CalendarIcon,\n label: '日期',\n type: 'date',\n },\n {\n description: '日期與時間',\n icon: CalendarIcon,\n label: '日期時間',\n type: 'datetime',\n },\n {\n description: '是 / 否狀態',\n icon: CheckedIcon,\n label: '開關',\n type: 'boolean',\n },\n {\n description: '固定選項擇一',\n icon: ListIcon,\n label: '下拉選單',\n type: 'select',\n },\n {\n description: '可搜尋的固定選項',\n icon: ListIcon,\n label: '自動完成',\n type: 'autocomplete',\n },\n {\n description: '固定選項單選',\n icon: DotGridIcon,\n label: '單選',\n type: 'radio',\n },\n {\n description: '固定選項複選',\n icon: CheckedOutlineIcon,\n label: '複選',\n type: 'checkbox',\n },\n {\n description: '附件或佐證資料',\n icon: FileAttachmentIcon,\n label: '附件',\n type: 'file_upload',\n },\n];\n\nconst WORKSPACE_GRID_STYLE: CSSProperties = {\n alignItems: 'start',\n display: 'flex',\n flexWrap: 'wrap',\n gap: 16,\n};\n\nconst CANVAS_COLUMN_STYLE: CSSProperties = {\n flex: '0.55 1 300px',\n minWidth: 0,\n};\n\nconst SETTINGS_COLUMN_STYLE: CSSProperties = {\n flex: '1.45 1 720px',\n minWidth: 620,\n};\n\nconst STACK_STYLE: CSSProperties = {\n display: 'grid',\n gap: 12,\n};\n\nconst FIELD_LIBRARY_STYLE: CSSProperties = {\n display: 'flex',\n flexWrap: 'wrap',\n gap: 6,\n};\n\nconst FIELD_LIBRARY_BUTTON_STYLE: CSSProperties = {\n flex: '0 0 auto',\n whiteSpace: 'nowrap',\n};\n\nconst FIELD_LIBRARY_HEADER_STYLE: CSSProperties = {\n display: 'grid',\n gap: 8,\n};\n\nconst FIELD_BLOCK_ROW_STYLE: CSSProperties = {\n alignItems: 'center',\n cursor: 'grab',\n display: 'flex',\n gap: 12,\n touchAction: 'none',\n};\n\nconst FIELD_BLOCK_TEXT_STYLE: CSSProperties = {\n display: 'grid',\n flex: '1 1 auto',\n gap: 2,\n minWidth: 0,\n};\n\nconst FIELD_BLOCK_ACTIONS_STYLE: CSSProperties = {\n alignItems: 'center',\n display: 'flex',\n flex: '0 0 auto',\n gap: 4,\n};\n\nconst FIELD_BLOCK_REQUIRED_STYLE: CSSProperties = {\n alignItems: 'center',\n display: 'flex',\n gap: 6,\n};\n\nconst FIELD_BLOCK_STYLE: CSSProperties = {\n cursor: 'pointer',\n userSelect: 'none',\n};\n\nconst FIELD_BLOCK_DRAGGING_STYLE: CSSProperties = {\n filter: 'drop-shadow(0 8px 18px rgba(0, 0, 0, 0.12))',\n};\n\n// Selected field: tint the whole card with a light brand fill over the surface\n// so the active row is obvious without relying on the (removed) edit button.\nconst FIELD_BLOCK_SELECTED_CARD_STYLE: CSSProperties = {\n backgroundColor:\n 'color-mix(in srgb, var(--mzn-color-primary) 8%, var(--mzn-color-bg-surface))',\n boxShadow: 'inset 0 0 0 1px var(--mzn-color-border-primary)',\n};\n\nconst EMPTY_CANVAS_STYLE: CSSProperties = {\n alignItems: 'center',\n border: '1px dashed var(--mzn-color-border-neutral)',\n borderRadius: 6,\n display: 'grid',\n gap: 12,\n minHeight: 240,\n padding: 32,\n textAlign: 'center',\n};\n\nconst EMPTY_CANVAS_ACTIONS_STYLE: CSSProperties = {\n display: 'flex',\n gap: 8,\n justifyContent: 'center',\n};\n\nconst FIELD_SETTINGS_FORM_STYLE: CSSProperties = {\n display: 'grid',\n gap: 14,\n};\n\nconst FIELD_SETTINGS_SECTION_STYLE: CSSProperties = {\n display: 'grid',\n columnGap: 16,\n gridTemplateColumns: 'repeat(auto-fit, minmax(280px, 1fr))',\n rowGap: 8,\n};\n\nconst FIELD_SETTINGS_SECTION_TITLE_STYLE: CSSProperties = {\n gridColumn: '1 / -1',\n};\n\nconst FIELD_SETTINGS_BADGE_ROW_STYLE: CSSProperties = {\n alignItems: 'center',\n display: 'flex',\n gap: 8,\n gridColumn: '1 / -1',\n justifyContent: 'flex-end',\n};\n\nconst FIELD_SETTINGS_HINT_STYLE: CSSProperties = {\n gridColumn: '1 / -1',\n};\n\nconst FIELD_SETTINGS_ROW_STYLE: CSSProperties = {\n alignItems: 'start',\n display: 'block',\n width: '100%',\n};\n\nconst FIELD_SETTINGS_ROW_WIDE_STYLE: CSSProperties = {\n ...FIELD_SETTINGS_ROW_STYLE,\n gridColumn: '1 / -1',\n};\n\nconst FIELD_SETTINGS_VALUE_STYLE: CSSProperties = {\n minWidth: 0,\n width: '100%',\n};\n\nconst FIELD_SETTINGS_TEXTAREA_STYLE: CSSProperties = {\n minWidth: '100%',\n width: '100%',\n};\n\nconst ADVANCED_SCHEMA_FORM_STYLE: CSSProperties = {\n display: 'grid',\n gap: 14,\n};\n\nconst ADVANCED_SCHEMA_ROW_STYLE: CSSProperties = {\n alignItems: 'start',\n display: 'block',\n width: '100%',\n};\n\nconst ADVANCED_SCHEMA_VALUE_STYLE: CSSProperties = {\n minWidth: 0,\n width: '100%',\n};\n\nconst ADVANCED_SCHEMA_MESSAGE_STYLE: CSSProperties = {\n gridColumn: '2 / -1',\n};\n\nconst CONDITION_RULE_CONTROL_STYLE: CSSProperties = {\n display: 'grid',\n gap: 10,\n width: '100%',\n};\n\nconst CONDITION_RULE_GRID_STYLE: CSSProperties = {\n display: 'grid',\n gap: 8,\n gridTemplateColumns: 'repeat(auto-fit, minmax(160px, 1fr))',\n};\n\nconst DRAG_HANDLE_STYLE: CSSProperties = {\n display: 'inline-flex',\n};\n\nconst WORKBENCH_STYLE: CSSProperties = {\n display: 'grid',\n gap: 16,\n};\n\nconst COMPACT_STACK_STYLE: CSSProperties = {\n display: 'grid',\n gap: 8,\n};\n\nconst OPTION_ACTIONS_STYLE: CSSProperties = {\n display: 'flex',\n justifyContent: 'flex-end',\n};\n\nconst REQUIRED_ASTERISK_STYLE: CSSProperties = {\n color: 'var(--mzn-color-text-error)',\n fontSize: '0.72em',\n lineHeight: 0,\n marginLeft: 2,\n verticalAlign: 'super',\n};\n\nconst DATA_SOURCE_SETTINGS_STYLE: CSSProperties = {\n display: 'grid',\n gap: 10,\n gridColumn: '1 / -1',\n};\n\nconst DATA_SOURCE_SUMMARY_STYLE: CSSProperties = {\n backgroundColor: 'var(--mzn-color-bg-surface-secondary)',\n borderRadius: 6,\n display: 'grid',\n gap: 4,\n padding: 10,\n};\n\nconst DATA_SOURCE_PARAMETER_GRID_STYLE: CSSProperties = {\n display: 'grid',\n gap: 8,\n gridTemplateColumns: 'minmax(180px, 0.7fr) minmax(220px, 1.3fr)',\n};\n\nfunction applyFullWidthTextareaHost(element: HTMLDivElement | null): void {\n if (!element) {\n return;\n }\n\n element.style.width = '100%';\n}\n\nconst EMPTY_SCHEMA: FormDefinitionSchema = {\n fields: [],\n schemaVersion: 1,\n};\n\nconst EMPTY_UI_SCHEMA: FormUiSchema = {\n layout: [],\n schemaVersion: 1,\n};\n\nconst STATIC_OPTION_SOURCE_ID = '__STATIC_OPTIONS__';\nconst CONSTANT_BINDING_ID = '__CONSTANT__';\nconst UNBOUND_BINDING_ID = '__UNBOUND__';\n\nconst OPTION_SOURCE_KIND_OPTIONS: readonly {\n readonly id: string;\n readonly name: string;\n}[] = [\n { id: STATIC_OPTION_SOURCE_ID, name: '靜態選項' },\n];\n\nconst OPTION_MODE_OPTIONS: readonly {\n readonly id: 'multiple' | 'single';\n readonly name: string;\n}[] = [\n { id: 'single', name: '單選' },\n { id: 'multiple', name: '複選' },\n];\n\nconst BOOLEAN_DEFAULT_OPTIONS: readonly {\n readonly id: string;\n readonly name: string;\n}[] = [\n { id: 'unset', name: '不預設' },\n { id: 'true', name: '是' },\n { id: 'false', name: '否' },\n];\n\nconst BOOLEAN_CONDITION_VALUE_OPTIONS: readonly {\n readonly id: string;\n readonly name: string;\n}[] = [\n { id: 'true', name: '是' },\n { id: 'false', name: '否' },\n];\n\nconst CONDITION_RULE_CONFIGS: readonly ConditionRuleConfig[] = [\n {\n label: '顯示',\n name: 'fieldVisibleWhen',\n supportingText: '符合條件時才顯示這個欄位。',\n target: 'visibleWhen',\n },\n {\n label: '必填',\n name: 'fieldRequiredWhen',\n supportingText: '符合條件時才要求填寫這個欄位。',\n target: 'requiredWhen',\n },\n {\n label: '唯讀',\n name: 'fieldReadonlyWhen',\n supportingText: '符合條件時不允許修改這個欄位。',\n target: 'readonlyWhen',\n },\n];\n\nexport interface FormBuilderViewProps {\n /**\n * Initial (or controlled) schema value.\n * If omitted, the builder starts with empty schema / uiSchema.\n */\n readonly value?: {\n readonly schema: FormDefinitionSchema;\n readonly uiSchema: FormUiSchema;\n };\n\n /** Called whenever the schema or uiSchema changes. */\n readonly onChange?: (next: {\n readonly schema: FormDefinitionSchema;\n readonly uiSchema: FormUiSchema;\n }) => void;\n}\n\nexport function FormBuilderView({\n onChange,\n value,\n}: FormBuilderViewProps): ReactElement {\n const initialSchema = value?.schema ?? EMPTY_SCHEMA;\n const initialUiSchema = value?.uiSchema ?? EMPTY_UI_SCHEMA;\n const [schema, setSchema] = useState<FormDefinitionSchema>(initialSchema);\n const [uiSchema, setUiSchema] = useState<FormUiSchema>(initialUiSchema);\n const [schemaJsonText, setSchemaJsonText] = useState(\n stringifyJson(initialSchema),\n );\n const [uiSchemaJsonText, setUiSchemaJsonText] = useState(\n stringifyJson(initialUiSchema),\n );\n const [previewValues, setPreviewValues] = useState<FormRendererValues>({});\n const [advancedSchemaMessage, setAdvancedSchemaMessage] = useState<\n string | null\n >(null);\n const [activeTab, setActiveTab] = useState<BuilderTabKey>('design');\n const [selectedFieldKey, setSelectedFieldKey] = useState<string | null>(null);\n const [dataSourceCatalog, setDataSourceCatalog] = useState<\n readonly FormDataSourceDescriptorRecord[]\n >([]);\n const [dataSourceCatalogError, setDataSourceCatalogError] = useState<\n string | null\n >(null);\n const [dataSourceCatalogState, setDataSourceCatalogState] =\n useState<DataSourceCatalogState>('loading');\n const [dataSourceLint, setDataSourceLint] = useState<\n readonly string[] | null\n >(null);\n const [dataSourceLintLoading, setDataSourceLintLoading] = useState(false);\n const [pendingBuilderConfirmation, setPendingBuilderConfirmation] =\n useState<PendingBuilderConfirmation | null>(null);\n\n useEffect((): (() => void) => {\n let active = true;\n\n void listFormDataSources()\n .then((descriptors): void => {\n if (!active) {\n return;\n }\n\n setDataSourceCatalog(descriptors);\n setDataSourceCatalogError(null);\n setDataSourceCatalogState('ready');\n })\n .catch((requestError: unknown): void => {\n if (!active) {\n return;\n }\n\n setDataSourceCatalog([]);\n void requestError;\n setDataSourceCatalogError('目前無法載入 DataSource Catalog,請稍後重試。');\n setDataSourceCatalogState('unavailable');\n });\n\n return (): void => {\n active = false;\n };\n }, []);\n useEffect((): void => {\n const hasSelectedField = schema.fields.some(\n (field) => field.fieldKey === selectedFieldKey,\n );\n\n if (hasSelectedField) {\n return;\n }\n\n setSelectedFieldKey(schema.fields[0]?.fieldKey ?? null);\n }, [schema.fields, selectedFieldKey]);\n\n useEffect((): void => {\n setPreviewValues((currentValues) =>\n buildFormRendererValues(schema.fields, currentValues),\n );\n }, [schema.fields]);\n\n useEffect((): void => {\n if (activeTab === 'advanced') {\n return;\n }\n\n setSchemaJsonText(stringifyJson(schema));\n setUiSchemaJsonText(stringifyJson(uiSchema));\n }, [activeTab, schema, uiSchema]);\n\n const selectedField = useMemo(\n (): FormFieldDefinition | null =>\n schema.fields.find((field) => field.fieldKey === selectedFieldKey) ??\n schema.fields[0] ??\n null,\n [schema.fields, selectedFieldKey],\n );\n useEffect((): void => {\n onChange?.({ schema, uiSchema });\n }, [schema, uiSchema]);\n\n function handleAddField(type: FieldType): void {\n const nextIndex = schema.fields.length + 1;\n const field = createFieldDefinition(type, nextIndex);\n\n setSchema({\n ...schema,\n fields: [...schema.fields, field],\n });\n setUiSchema({\n ...uiSchema,\n layout: [\n ...uiSchema.layout,\n {\n fieldKey: field.fieldKey,\n width:\n type === 'textarea' || type === 'file_upload' ? 'FULL' : 'HALF',\n },\n ],\n });\n setSelectedFieldKey(field.fieldKey);\n setActiveTab('design');\n setAdvancedSchemaMessage(null);\n }\n\n function handleTabChange(activeKey: Key): void {\n const nextTab = activeKey as BuilderTabKey;\n\n if (nextTab === 'advanced' && activeTab !== 'advanced') {\n setSchemaJsonText(stringifyJson(schema));\n setUiSchemaJsonText(stringifyJson(uiSchema));\n }\n\n setActiveTab(nextTab);\n }\n\n function handleRemoveField(fieldKey: string): void {\n const affectedFieldKeys = schema.fields.flatMap((field) =>\n isFormDataSourceFieldDefinition(field) &&\n readFormDataSourceFieldDependencyKeys(field).includes(fieldKey)\n ? [field.fieldKey]\n : [],\n );\n\n if (affectedFieldKeys.length > 0) {\n setPendingBuilderConfirmation({\n affectedFieldKeys,\n fieldKey,\n kind: 'remove-field',\n });\n\n return;\n }\n\n applyRemoveField(fieldKey);\n }\n\n function applyRemoveField(fieldKey: string): void {\n const remainingFields = schema.fields.filter(\n (field) => field.fieldKey !== fieldKey,\n );\n\n setSchema({\n ...schema,\n fields: remainingFields,\n });\n setUiSchema({\n ...uiSchema,\n layout: uiSchema.layout.filter((item) => item.fieldKey !== fieldKey),\n });\n setSelectedFieldKey(\n selectedFieldKey === fieldKey\n ? (remainingFields[0]?.fieldKey ?? null)\n : selectedFieldKey,\n );\n setAdvancedSchemaMessage(null);\n setDataSourceLint(null);\n }\n\n function handleFieldDragEnd(result: DropResult): void {\n const destination = result.destination;\n\n if (!destination) {\n return;\n }\n\n if (result.source.index === destination.index) {\n return;\n }\n\n setSchema((currentSchema) => ({\n ...currentSchema,\n fields: moveItemByIndex(\n currentSchema.fields,\n result.source.index,\n destination.index,\n ),\n }));\n setUiSchema((currentUiSchema) => ({\n ...currentUiSchema,\n layout: moveItemByIndex(\n currentUiSchema.layout,\n result.source.index,\n destination.index,\n ),\n }));\n setAdvancedSchemaMessage(null);\n }\n\n function updateSelectedField(\n patch: Partial<\n Pick<\n FormFieldDefinition,\n | 'defaultValue'\n | 'fieldKey'\n | 'label'\n | 'placeholder'\n | 'readonlyWhen'\n | 'required'\n | 'requiredWhen'\n | 'visibleWhen'\n >\n >,\n ): void {\n updateSelectedFieldWith(\n (field) => ({ ...field, ...patch }) as FormFieldDefinition,\n );\n }\n\n function updateSelectedFieldWith(\n updater: (field: FormFieldDefinition) => FormFieldDefinition,\n ): void {\n if (!selectedField) {\n return;\n }\n\n const previousFieldKey = selectedField.fieldKey;\n const nextField = updater(selectedField);\n const nextFieldKey = nextField.fieldKey;\n\n const updatedSchema = {\n ...schema,\n fields: schema.fields.map(\n (field): FormFieldDefinition =>\n field.fieldKey === previousFieldKey ? nextField : field,\n ),\n };\n const nextSchema =\n previousFieldKey === nextFieldKey\n ? updatedSchema\n : renameFormDataSourceFieldBindings(\n updatedSchema,\n previousFieldKey,\n nextFieldKey,\n );\n\n setSchema(nextSchema);\n setUiSchema({\n ...uiSchema,\n layout: uiSchema.layout.map((item) =>\n item.fieldKey === previousFieldKey\n ? { ...item, fieldKey: nextFieldKey }\n : item,\n ),\n });\n setSelectedFieldKey(nextFieldKey);\n setAdvancedSchemaMessage(null);\n setDataSourceLint(null);\n }\n\n function updateSelectedTextField(\n patch: Partial<\n Pick<TextFieldDefinition, 'defaultValue' | 'maxLength' | 'minLength'>\n >,\n ): void {\n updateSelectedFieldWith((field) =>\n isTextFieldDefinition(field) ? { ...field, ...patch } : field,\n );\n }\n\n function updateSelectedNumberField(\n patch: Partial<\n Pick<NumberFieldDefinition, 'defaultValue' | 'maximum' | 'minimum'>\n >,\n ): void {\n updateSelectedFieldWith((field) =>\n isNumberFieldDefinition(field) ? { ...field, ...patch } : field,\n );\n }\n\n function updateSelectedDateField(\n patch: Partial<Pick<DateFieldDefinition, 'defaultValue'>>,\n ): void {\n updateSelectedFieldWith((field) =>\n isDateFieldDefinition(field) ? { ...field, ...patch } : field,\n );\n }\n\n function updateSelectedSelectField(\n patch: Partial<\n Pick<FormOptionFieldDefinition, 'defaultValue' | 'options'>\n >,\n ): void {\n updateSelectedFieldWith((field) =>\n isSelectFieldDefinition(field) ? { ...field, ...patch } : field,\n );\n }\n\n function updateSelectedOptionMode(mode: 'multiple' | 'single'): void {\n if (\n !selectedField ||\n (selectedField.type !== 'select' && selectedField.type !== 'autocomplete')\n ) {\n return;\n }\n\n const currentMode = readFormFieldSelectionMode(selectedField);\n\n if (currentMode === mode) {\n return;\n }\n\n const currentDefaultValue = selectedField.defaultValue;\n const defaultValue =\n mode === 'multiple'\n ? typeof currentDefaultValue === 'string'\n ? [currentDefaultValue]\n : currentDefaultValue\n : Array.isArray(currentDefaultValue)\n ? currentDefaultValue[0]\n : currentDefaultValue;\n\n requestDataSourceFieldChange(\n selectedField,\n {\n ...selectedField,\n defaultValue,\n mode,\n },\n '選擇模式變更可能轉換或捨棄既有預設值。',\n );\n }\n\n function requestDataSourceFieldChange(\n field: FormOptionFieldDefinition,\n nextField: FormFieldDefinition,\n impact = '此變更會替換目前選項來源;既有 options、dynamic reference 或 bindings 可能失效。',\n ): void {\n if (JSON.stringify(field) === JSON.stringify(nextField)) {\n return;\n }\n\n setPendingBuilderConfirmation({\n fieldKey: field.fieldKey,\n impact,\n kind: 'replace-field',\n nextField,\n });\n }\n\n function handleOptionSourceChange(\n field: FormOptionFieldDefinition,\n optionId: string | undefined,\n ): void {\n if (!optionId) {\n return;\n }\n\n if (optionId === STATIC_OPTION_SOURCE_ID) {\n if (!isFormDataSourceFieldDefinition(field)) {\n return;\n }\n\n const { dataSource, defaultValue, ...baseField } = field;\n void dataSource;\n void defaultValue;\n requestDataSourceFieldChange(field, {\n ...baseField,\n options: [],\n } as FormFieldDefinition);\n\n return;\n }\n\n const descriptor = dataSourceCatalog.find(\n (candidate) => readDataSourceDescriptorOptionId(candidate) === optionId,\n );\n\n if (!descriptor) {\n return;\n }\n\n if (isFormDataSourceFieldDefinition(field)) {\n const parameterKeys = new Set(\n descriptor.parameters.map((parameter) => parameter.key),\n );\n const nextBindings = field.dataSource.bindings.filter((binding) =>\n parameterKeys.has(binding.parameter),\n );\n\n requestDataSourceFieldChange(field, {\n ...field,\n dataSource: {\n bindings: nextBindings,\n key: descriptor.key,\n version: descriptor.version,\n },\n });\n\n return;\n }\n\n const { options, defaultValue, ...baseField } = field;\n void options;\n void defaultValue;\n requestDataSourceFieldChange(field, {\n ...baseField,\n dataSource: {\n bindings: [],\n key: descriptor.key,\n version: descriptor.version,\n },\n } as FormDataSourceOptionFieldDefinition);\n }\n\n function handleConfirmBuilderChange(): void {\n if (!pendingBuilderConfirmation) {\n return;\n }\n\n if (pendingBuilderConfirmation.kind === 'remove-field') {\n applyRemoveField(pendingBuilderConfirmation.fieldKey);\n } else {\n setSchema({\n ...schema,\n fields: schema.fields.map((field) =>\n field.fieldKey === pendingBuilderConfirmation.fieldKey\n ? pendingBuilderConfirmation.nextField\n : field,\n ),\n });\n setAdvancedSchemaMessage(null);\n setDataSourceLint(null);\n }\n\n setPendingBuilderConfirmation(null);\n }\n\n async function handleLintDataSourceSchema(): Promise<void> {\n setDataSourceLintLoading(true);\n\n try {\n const result = await lintFormSchema(schema, uiSchema);\n // Lint lines carry stable `FORM_DATA_SOURCE_*` codes; show the designer\n // readable copy while keeping the field path.\n setDataSourceLint(result.errors.map(readFormSchemaLintMessage));\n } catch {\n setDataSourceLint(['目前無法完成 DataSource schema 驗證。']);\n } finally {\n setDataSourceLintLoading(false);\n }\n }\n\n function updateSelectedBooleanField(\n patch: Partial<Pick<BooleanFieldDefinition, 'defaultValue'>>,\n ): void {\n updateSelectedFieldWith((field) =>\n field.type === 'boolean' ? { ...field, ...patch } : field,\n );\n }\n\n function updateSelectedFileUploadField(\n patch: Partial<\n Pick<\n FileUploadFieldDefinition,\n 'acceptedMimeTypes' | 'defaultValue' | 'maxFiles'\n >\n >,\n ): void {\n updateSelectedFieldWith((field) =>\n field.type === 'file_upload' ? { ...field, ...patch } : field,\n );\n }\n\n function updatePreviewValues(values: FormRendererValues): void {\n setPreviewValues(values);\n }\n\n function updateFieldRequired(fieldKey: string, required: boolean): void {\n setSchema((currentSchema) => ({\n ...currentSchema,\n fields: currentSchema.fields.map(\n (field): FormFieldDefinition =>\n field.fieldKey === fieldKey\n ? ({ ...field, required } as FormFieldDefinition)\n : field,\n ),\n }));\n setAdvancedSchemaMessage(null);\n }\n\n function updateSchemaJson(value: string): void {\n setSchemaJsonText(value);\n\n try {\n setSchema(JSON.parse(value) as FormDefinitionSchema);\n setAdvancedSchemaMessage(null);\n } catch {\n setAdvancedSchemaMessage('Form Schema JSON 格式不正確');\n }\n }\n\n function updateUiSchemaJson(value: string): void {\n setUiSchemaJsonText(value);\n\n try {\n setUiSchema(JSON.parse(value) as FormUiSchema);\n setAdvancedSchemaMessage(null);\n } catch {\n setAdvancedSchemaMessage('UI Schema JSON 格式不正確');\n }\n }\n\n return (\n <>\n <>\n <SectionGroup>\n <Section>\n <div style={WORKBENCH_STYLE}>\n <Tab\n activeKey={activeTab}\n onChange={handleTabChange}\n size=\"sub\"\n >\n <TabItem key=\"design\">設計</TabItem>\n <TabItem key=\"preview\">預覽</TabItem>\n <TabItem key=\"advanced\">進階</TabItem>\n </Tab>\n\n {activeTab === 'design' ? renderDesignTab() : null}\n {activeTab === 'preview' ? renderPreviewTab() : null}\n {activeTab === 'advanced' ? renderAdvancedTab() : null}\n </div>\n </Section>\n </SectionGroup>\n </>\n {pendingBuilderConfirmation ? (\n <Modal\n cancelText=\"返回\"\n confirmText=\"確認變更\"\n modalType=\"standard\"\n onCancel={(): void => setPendingBuilderConfirmation(null)}\n onClose={(): void => setPendingBuilderConfirmation(null)}\n onConfirm={handleConfirmBuilderChange}\n open\n showModalFooter\n showModalHeader\n title={\n pendingBuilderConfirmation.kind === 'remove-field'\n ? '確認移除 dependency 欄位'\n : '確認替換選項來源'\n }\n >\n {pendingBuilderConfirmation.kind === 'remove-field' ? (\n <div style={COMPACT_STACK_STYLE}>\n <Typography variant=\"body\">\n 此欄位仍被下列 DataSource binding 使用;移除後請重新設定這些欄位。\n </Typography>\n <Typography color=\"text-warning\" variant=\"body\">\n {pendingBuilderConfirmation.affectedFieldKeys.join('、')}\n </Typography>\n </div>\n ) : (\n <Typography variant=\"body\">\n {pendingBuilderConfirmation.impact}確認後才會寫入 schema。\n </Typography>\n )}\n </Modal>\n ) : null}\n </>\n );\n\n function renderDesignTab(): ReactElement {\n return (\n <div style={STACK_STYLE}>\n <div style={FIELD_LIBRARY_HEADER_STYLE}>\n <Typography component=\"h2\" variant=\"label-primary\">\n 新增欄位\n </Typography>\n <div style={FIELD_LIBRARY_STYLE}>\n {FIELD_TYPE_OPTIONS.map((option) => (\n <Button\n icon={option.icon}\n iconType=\"leading\"\n key={option.type}\n onClick={(): void => handleAddField(option.type)}\n size=\"sub\"\n style={FIELD_LIBRARY_BUTTON_STYLE}\n type=\"button\"\n variant=\"base-secondary\"\n >\n {option.label}\n </Button>\n ))}\n </div>\n </div>\n\n <div style={WORKSPACE_GRID_STYLE}>\n <div style={{ ...STACK_STYLE, ...CANVAS_COLUMN_STYLE }}>\n <Typography component=\"h2\" variant=\"label-primary\">\n 表單畫布\n </Typography>\n {schema.fields.length > 0 ? (\n <DragDropContext onDragEnd={handleFieldDragEnd}>\n <Droppable droppableId=\"form-builder-fields\">\n {(droppableProvided): ReactElement => (\n <div\n {...droppableProvided.droppableProps}\n ref={droppableProvided.innerRef}\n style={STACK_STYLE}\n >\n {schema.fields.map((field, index) => (\n <Draggable\n draggableId={field.fieldKey}\n index={index}\n key={field.fieldKey}\n >\n {(draggableProvided, snapshot): ReactElement =>\n renderFieldBlock(\n field,\n draggableProvided,\n snapshot.isDragging,\n )\n }\n </Draggable>\n ))}\n {droppableProvided.placeholder}\n </div>\n )}\n </Droppable>\n </DragDropContext>\n ) : (\n <div style={EMPTY_CANVAS_STYLE}>\n <div style={STACK_STYLE}>\n <Typography component=\"h3\" variant=\"h3\">\n 尚未建立欄位\n </Typography>\n <Typography color=\"text-neutral\" variant=\"body\">\n 從上方新增第一個欄位,或直接建立常用文字欄位開始設計。\n </Typography>\n </div>\n <div style={EMPTY_CANVAS_ACTIONS_STYLE}>\n <Button\n onClick={(): void => handleAddField('text')}\n variant=\"base-primary\"\n >\n 新增文字欄位\n </Button>\n <Button\n onClick={(): void => handleAddField('textarea')}\n variant=\"base-secondary\"\n >\n 新增長文字\n </Button>\n </div>\n </div>\n )}\n </div>\n\n <div style={{ ...STACK_STYLE, ...SETTINGS_COLUMN_STYLE }}>\n <Typography component=\"h2\" variant=\"label-primary\">\n 欄位設定\n </Typography>\n {selectedField ? (\n renderFieldSettings(selectedField)\n ) : (\n <Typography color=\"text-neutral\" variant=\"body\">\n 請先新增或選取欄位。\n </Typography>\n )}\n </div>\n </div>\n </div>\n );\n }\n\n function renderFieldSettings(field: FormFieldDefinition): ReactElement {\n return (\n <div style={FIELD_SETTINGS_FORM_STYLE}>\n {renderMainFieldSettings(field)}\n {renderAdvancedFieldSettings(field)}\n </div>\n );\n }\n\n function renderMainFieldSettings(field: FormFieldDefinition): ReactElement {\n return (\n <div style={FIELD_SETTINGS_SECTION_STYLE}>\n <div style={FIELD_SETTINGS_BADGE_ROW_STYLE}>\n <Badge\n size=\"main\"\n text={readFieldTypeLabel(field.type)}\n variant=\"text-info\"\n />\n </div>\n {renderSettingsFormRow(\n '標題',\n 'fieldLabel',\n <Input\n onChange={(event: ChangeEvent<HTMLInputElement>): void =>\n updateSelectedField({ label: event.target.value })\n }\n placeholder=\"例如:申請金額\"\n value={field.label}\n variant=\"base\"\n />,\n )}\n {renderSettingsFormRow(\n '欄位 Key',\n 'fieldKey',\n <Input\n onChange={(event: ChangeEvent<HTMLInputElement>): void =>\n updateSelectedField({ fieldKey: event.target.value })\n }\n placeholder=\"例如:amount\"\n value={field.fieldKey}\n variant=\"base\"\n />,\n )}\n {renderSettingsFormRow(\n '提示文字',\n 'fieldPlaceholder',\n <Input\n onChange={(event: ChangeEvent<HTMLInputElement>): void =>\n updateSelectedField({\n placeholder: event.target.value || undefined,\n })\n }\n placeholder=\"例如:請輸入申請金額\"\n value={field.placeholder ?? ''}\n variant=\"base\"\n />,\n )}\n {renderTypeSpecificSettings(field)}\n </div>\n );\n }\n\n function renderAdvancedFieldSettings(\n field: FormFieldDefinition,\n ): ReactElement {\n return (\n <Accordion\n defaultExpanded={hasConditionRules(field)}\n size=\"sub\"\n title=\"進階設定\"\n >\n <div style={FIELD_SETTINGS_SECTION_STYLE}>\n <Typography\n component=\"h3\"\n style={FIELD_SETTINGS_SECTION_TITLE_STYLE}\n variant=\"label-primary\"\n >\n 條件規則\n </Typography>\n <Typography\n color=\"text-neutral\"\n style={FIELD_SETTINGS_HINT_STYLE}\n variant=\"body\"\n >\n 只有需要根據其他欄位改變顯示、必填或唯讀狀態時才需要設定。\n </Typography>\n {renderConditionSettings(field)}\n </div>\n </Accordion>\n );\n }\n\n function renderTypeSpecificSettings(\n field: FormFieldDefinition,\n ): ReactElement {\n if (isTextFieldDefinition(field)) {\n return renderTextFieldSettings(field);\n }\n\n if (isNumberFieldDefinition(field)) {\n return renderNumberFieldSettings(field);\n }\n\n if (isDateFieldDefinition(field)) {\n return renderDateFieldSettings(field);\n }\n\n if (isFormOptionFieldDefinition(field)) {\n return renderOptionFieldSettings(field);\n }\n\n if (field.type === 'boolean') {\n return renderBooleanFieldSettings(field);\n }\n\n return renderFileUploadFieldSettings(field);\n }\n\n function renderTextFieldSettings(field: TextFieldDefinition): ReactElement {\n return (\n <>\n {renderSettingsFormRow(\n '預設值',\n 'fieldDefaultValue',\n field.type === 'textarea' ? (\n renderSettingsTextarea({\n name: 'fieldDefaultValue',\n onChange: (value): void =>\n updateSelectedTextField({ defaultValue: value || undefined }),\n placeholder: '輸入此欄位的預設文字',\n rows: 3,\n value: readStringDefaultValue(field.defaultValue),\n })\n ) : (\n <Input\n onChange={(event: ChangeEvent<HTMLInputElement>): void =>\n updateSelectedTextField({\n defaultValue: event.target.value || undefined,\n })\n }\n placeholder=\"輸入此欄位的預設文字\"\n value={readStringDefaultValue(field.defaultValue)}\n variant=\"base\"\n />\n ),\n )}\n {renderSettingsFormRow(\n '最小長度',\n 'fieldMinLength',\n renderNumberInput(\n field.minLength,\n (value): void => updateSelectedTextField({ minLength: value }),\n '例如:2',\n { min: 0 },\n ),\n )}\n {renderSettingsFormRow(\n '最大長度',\n 'fieldMaxLength',\n renderNumberInput(\n field.maxLength,\n (value): void => updateSelectedTextField({ maxLength: value }),\n '例如:100',\n { min: 1 },\n ),\n )}\n </>\n );\n }\n\n function renderNumberFieldSettings(\n field: NumberFieldDefinition,\n ): ReactElement {\n return (\n <>\n {renderSettingsFormRow(\n '預設值',\n 'fieldDefaultValue',\n renderNumberInput(\n typeof field.defaultValue === 'number'\n ? field.defaultValue\n : undefined,\n (value): void => updateSelectedNumberField({ defaultValue: value }),\n field.type === 'money' ? '例如:1000' : '輸入預設數值',\n { max: field.maximum, min: field.minimum },\n ),\n )}\n {renderSettingsFormRow(\n '最小值',\n 'fieldMinimum',\n renderNumberInput(\n field.minimum,\n (value): void => updateSelectedNumberField({ minimum: value }),\n '例如:0',\n ),\n )}\n {renderSettingsFormRow(\n '最大值',\n 'fieldMaximum',\n renderNumberInput(\n field.maximum,\n (value): void => updateSelectedNumberField({ maximum: value }),\n '例如:999999',\n ),\n )}\n </>\n );\n }\n\n function renderDateFieldSettings(field: DateFieldDefinition): ReactElement {\n return renderSettingsFormRow(\n '預設值',\n 'fieldDefaultValue',\n renderDateValuePicker(\n field,\n readStringDefaultValue(field.defaultValue),\n (value): void => updateSelectedDateField({ defaultValue: value }),\n ),\n );\n }\n\n function renderOptionFieldSettings(\n field: FormOptionFieldDefinition,\n ): ReactElement {\n const compatibleDescriptors = readCompatibleFormDataSourceDescriptors(\n field.type,\n dataSourceCatalog,\n );\n const currentSourceId = isFormDataSourceFieldDefinition(field)\n ? readDataSourceDescriptorOptionId(field.dataSource)\n : STATIC_OPTION_SOURCE_ID;\n const currentDescriptor = isFormDataSourceFieldDefinition(field)\n ? dataSourceCatalog.find(\n (descriptor) =>\n descriptor.key === field.dataSource.key &&\n descriptor.version === field.dataSource.version,\n )\n : null;\n const currentDescriptorIsCompatible = currentDescriptor\n ? compatibleDescriptors.some(\n (descriptor) =>\n descriptor.key === currentDescriptor.key &&\n descriptor.version === currentDescriptor.version,\n )\n : false;\n const sourceOptions = [\n ...OPTION_SOURCE_KIND_OPTIONS,\n ...compatibleDescriptors.map(readDataSourceDescriptorOption),\n ...(isFormDataSourceFieldDefinition(field) &&\n !currentDescriptorIsCompatible\n ? [\n {\n id: currentSourceId,\n name: `${field.dataSource.key} v${field.dataSource.version}(目前不可用或不支援)`,\n },\n ]\n : []),\n ];\n const mode = readFormFieldSelectionMode(field);\n\n return (\n <>\n {field.type === 'select' || field.type === 'autocomplete'\n ? renderSettingsFormRow(\n '選擇模式',\n 'fieldSelectionMode',\n <Select\n clearable={false}\n onChange={(option): void => {\n if (option?.id === 'single' || option?.id === 'multiple') {\n updateSelectedOptionMode(option.id);\n }\n }}\n options={[...OPTION_MODE_OPTIONS]}\n value={readSelectOption(OPTION_MODE_OPTIONS, mode)}\n />,\n )\n : renderSettingsFormRow(\n '選擇模式',\n 'fieldSelectionMode',\n <Typography color=\"text-neutral\" variant=\"body\">\n {mode === 'multiple' ? '固定複選' : '固定單選'}\n </Typography>,\n )}\n {renderSettingsFormRow(\n '選項來源',\n 'fieldOptionSource',\n <Select\n clearable={false}\n disabled={\n dataSourceCatalogState === 'loading' &&\n !isFormDataSourceFieldDefinition(field)\n }\n onChange={(option): void =>\n handleOptionSourceChange(field, option?.id)\n }\n options={sourceOptions}\n placeholder=\"選擇選項來源\"\n value={readSelectOption(sourceOptions, currentSourceId)}\n />,\n )}\n {isFormDataSourceFieldDefinition(field)\n ? renderDataSourceFieldSettings(field, compatibleDescriptors)\n : renderStaticOptionFieldSettings(field)}\n </>\n );\n }\n\n function renderDataSourceFieldSettings(\n field: FormDataSourceOptionFieldDefinition,\n compatibleDescriptors: readonly FormDataSourceDescriptorRecord[],\n ): ReactElement {\n const descriptor = dataSourceCatalog.find(\n (candidate) =>\n candidate.key === field.dataSource.key &&\n candidate.version === field.dataSource.version,\n );\n const unsupportedCurrentSource =\n descriptor && !isFormDataSourceDescriptorCompatible(descriptor, field.type);\n\n return (\n <div style={DATA_SOURCE_SETTINGS_STYLE}>\n {dataSourceCatalogState === 'loading' ? (\n <Typography color=\"text-neutral\" variant=\"body\">\n 正在載入可用的 DataSource Catalog…\n </Typography>\n ) : null}\n {dataSourceCatalogError ? (\n <Typography color=\"text-error\" variant=\"body\">\n {dataSourceCatalogError}\n </Typography>\n ) : null}\n {!descriptor ? (\n <Typography color=\"text-warning\" variant=\"body\">\n 目前來源版本未出現在 Catalog;會保留原設定,但在環境 lint 通過前不可發布。\n </Typography>\n ) : null}\n {unsupportedCurrentSource ? (\n <Typography color=\"text-error\" variant=\"body\">\n 目前來源不支援此控制項或超出 bounded list 限制,請選擇其他版本。\n </Typography>\n ) : null}\n {descriptor ? renderDataSourceDescriptorSummary(descriptor) : null}\n {descriptor\n ? descriptor.parameters.map((parameter) =>\n renderDataSourceParameterBinding(field, parameter),\n )\n : null}\n {compatibleDescriptors.length === 0 && !dataSourceCatalogError ? (\n <Typography color=\"text-warning\" variant=\"body\">\n 沒有符合目前控制項能力的已註冊來源。\n </Typography>\n ) : null}\n <div style={OPTION_ACTIONS_STYLE}>\n <Button\n disabled={dataSourceLintLoading}\n onClick={(): void => void handleLintDataSourceSchema()}\n size=\"sub\"\n type=\"button\"\n variant=\"base-secondary\"\n >\n {dataSourceLintLoading ? '驗證中…' : '驗證 DataSource 設定'}\n </Button>\n </div>\n {dataSourceLint ? (\n <Typography\n color={dataSourceLint.length > 0 ? 'text-error' : 'text-success'}\n variant=\"caption\"\n >\n {dataSourceLint.length > 0\n ? dataSourceLint.join(';')\n : 'DataSource schema 與目前環境均通過驗證。'}\n </Typography>\n ) : null}\n </div>\n );\n }\n\n function renderDataSourceDescriptorSummary(\n descriptor: FormDataSourceDescriptorRecord,\n ): ReactElement {\n return (\n <div style={DATA_SOURCE_SUMMARY_STYLE}>\n <Typography variant=\"label-primary\">\n {descriptor.label} · v{descriptor.version}\n </Typography>\n {descriptor.description ? (\n <Typography color=\"text-neutral\" variant=\"caption\">\n {descriptor.description}\n </Typography>\n ) : null}\n <Typography color=\"text-neutral\" variant=\"caption\">\n 支援:{descriptor.supportedControls.join('、')};\n {descriptor.supportsSearch ? '支援搜尋' : '不支援搜尋'};\n {descriptor.paginationMode === 'CURSOR' ? '支援分頁' : '完整清單'};\n policy:{descriptor.revalidationPolicy}\n </Typography>\n </div>\n );\n }\n\n function renderDataSourceParameterBinding(\n field: FormDataSourceOptionFieldDefinition,\n parameter: FormDataSourceDescriptorRecord['parameters'][number],\n ): ReactElement {\n const binding = readFormDataSourceBinding(field, parameter.key);\n const bindingId = readDataSourceBindingOptionId(binding);\n const fieldOptions = readCompatibleFormDataSourceBindingFields(\n parameter.type,\n schema.fields,\n field.fieldKey,\n );\n const bindingOptions = [\n ...(parameter.required\n ? []\n : [{ id: UNBOUND_BINDING_ID, name: '未綁定' }]),\n ...fieldOptions,\n ...(parameter.type === 'STRING_ARRAY'\n ? []\n : [{ id: CONSTANT_BINDING_ID, name: '固定常數' }]),\n ];\n\n return (\n <div key={parameter.key} style={DATA_SOURCE_PARAMETER_GRID_STYLE}>\n <BPMFormField\n label={`${parameter.label ?? parameter.key}${parameter.required ? '(必填)' : '(選填)'}`}\n name={`dataSourceParameter_${parameter.key}`}\n >\n <Select\n clearable={false}\n onChange={(option): void =>\n handleDataSourceBindingChange(\n field,\n parameter.key,\n parameter.type,\n option?.id,\n )\n }\n options={bindingOptions}\n placeholder=\"選擇欄位或常數\"\n value={readSelectOption(bindingOptions, bindingId)}\n />\n </BPMFormField>\n {readFormDataSourceBindingValueKind(binding) === 'CONSTANT'\n ? renderDataSourceConstantEditor(field, parameter.key, parameter.type, binding)\n : readFormDataSourceBindingValueKind(binding) === 'FIELD'\n ? (\n <Typography color=\"text-neutral\" variant=\"caption\">\n 使用表單欄位「{binding?.from.kind === 'FIELD' ? binding.from.fieldKey : ''}」的目前值。\n </Typography>\n )\n : (\n <Typography color=\"text-neutral\" variant=\"caption\">\n {parameter.required\n ? fieldOptions.length > 0\n ? '請選擇相容的表單欄位或固定常數。'\n : '目前沒有型別相容的表單欄位,請先建立 dependency。'\n : '此參數可不綁定。'}\n </Typography>\n )}\n </div>\n );\n }\n\n function renderDataSourceConstantEditor(\n field: FormDataSourceOptionFieldDefinition,\n parameterKey: string,\n parameterType: FormDataSourceParameterType,\n binding: FormDataSourceBinding | null,\n ): ReactElement {\n const value = readFormDataSourceBindingValue(field, parameterKey);\n\n if (parameterType === 'BOOLEAN') {\n const options = [\n { id: 'true', name: '是' },\n { id: 'false', name: '否' },\n ];\n\n return (\n <Select\n clearable={false}\n onChange={(option): void =>\n updateDataSourceConstant(\n parameterKey,\n option?.id === 'true',\n )\n }\n options={options}\n value={readSelectOption(\n options,\n value === true ? 'true' : 'false',\n )}\n />\n );\n }\n\n if (parameterType === 'STRING_ARRAY') {\n return (\n <Typography color=\"text-warning\" variant=\"caption\">\n STRING_ARRAY 參數請綁定複選欄位;目前不接受固定常數。\n </Typography>\n );\n }\n\n return (\n <Input\n onChange={(event: ChangeEvent<HTMLInputElement>): void =>\n updateDataSourceConstant(\n parameterKey,\n parameterType === 'NUMBER'\n ? parseOptionalNumberInput(event.target.value) ?? 0\n : event.target.value,\n )\n }\n placeholder={parameterType === 'NUMBER' ? '輸入數字' : '輸入固定值'}\n value={readDataSourceConstantInputValue(binding, parameterType)}\n variant=\"base\"\n />\n );\n }\n\n function handleDataSourceBindingChange(\n field: FormDataSourceOptionFieldDefinition,\n parameterKey: string,\n parameterType: FormDataSourceParameterType,\n optionId: string | undefined,\n ): void {\n if (!optionId || optionId === UNBOUND_BINDING_ID) {\n updateSelectedFieldWith((currentField) =>\n isFormDataSourceFieldDefinition(currentField)\n ? upsertFormDataSourceFieldBinding(currentField, parameterKey, null)\n : currentField,\n );\n\n return;\n }\n\n if (optionId === CONSTANT_BINDING_ID) {\n updateSelectedFieldWith((currentField) =>\n isFormDataSourceFieldDefinition(currentField)\n ? upsertFormDataSourceFieldBinding(\n currentField,\n parameterKey,\n {\n from: {\n kind: 'CONSTANT',\n value: readDefaultDataSourceConstant(parameterType),\n },\n parameter: parameterKey,\n },\n )\n : currentField,\n );\n\n return;\n }\n\n updateSelectedFieldWith((currentField) =>\n isFormDataSourceFieldDefinition(currentField)\n ? upsertFormDataSourceFieldBinding(currentField, parameterKey, {\n from: { fieldKey: optionId, kind: 'FIELD' },\n parameter: parameterKey,\n })\n : currentField,\n );\n }\n\n function updateDataSourceConstant(\n parameterKey: string,\n value: FormDataSourceConstantValue,\n ): void {\n updateSelectedFieldWith((currentField) =>\n isFormDataSourceFieldDefinition(currentField)\n ? upsertFormDataSourceFieldBinding(currentField, parameterKey, {\n from: { kind: 'CONSTANT', value },\n parameter: parameterKey,\n })\n : currentField,\n );\n }\n\n function renderStaticOptionFieldSettings(\n field: FormStaticOptionFieldDefinition,\n ): ReactElement {\n const mode = readFormFieldSelectionMode(field);\n const defaultValues = Array.isArray(field.defaultValue)\n ? field.defaultValue\n : [];\n const options = field.options.map(readFieldOptionAsSelectOption);\n const selectedValues = options.filter((option) =>\n defaultValues.includes(option.id),\n );\n\n return (\n <>\n {renderSettingsFormRow(\n '預設值',\n 'fieldDefaultValue',\n mode === 'multiple' ? (\n <Select\n clearable\n mode=\"multiple\"\n onChange={(nextOptions): void =>\n updateSelectedSelectField({\n defaultValue: nextOptions.length\n ? nextOptions.map((option) => option.id)\n : undefined,\n })\n }\n options={options}\n placeholder=\"選擇一或多個預設選項\"\n value={selectedValues}\n />\n ) : (\n <Select\n clearable\n onChange={(option): void =>\n updateSelectedSelectField({\n defaultValue: option?.id || undefined,\n })\n }\n options={options}\n placeholder=\"選擇預設選項\"\n value={\n typeof field.defaultValue === 'string'\n ? readSelectOption(options, field.defaultValue)\n : null\n }\n />\n ),\n )}\n {renderSettingsFormRow(\n '選項',\n 'fieldOptions',\n renderFieldOptionsTable(field),\n true,\n )}\n </>\n );\n }\n\n function renderBooleanFieldSettings(\n field: BooleanFieldDefinition,\n ): ReactElement {\n const defaultValue =\n typeof field.defaultValue === 'boolean'\n ? String(field.defaultValue)\n : 'unset';\n\n return renderSettingsFormRow(\n '預設值',\n 'fieldDefaultValue',\n <Select\n clearable={false}\n onChange={(option): void =>\n updateSelectedBooleanField({\n defaultValue:\n option?.id === 'true'\n ? true\n : option?.id === 'false'\n ? false\n : undefined,\n })\n }\n options={[...BOOLEAN_DEFAULT_OPTIONS]}\n placeholder=\"選擇預設狀態\"\n value={readSelectOption(BOOLEAN_DEFAULT_OPTIONS, defaultValue)}\n />,\n );\n }\n\n function renderFileUploadFieldSettings(\n field: FileUploadFieldDefinition,\n ): ReactElement {\n return (\n <>\n {renderSettingsFormRow(\n '檔案數',\n 'fieldMaxFiles',\n renderNumberInput(\n field.maxFiles,\n (value): void => updateSelectedFileUploadField({ maxFiles: value }),\n '例如:1',\n { min: 1 },\n ),\n )}\n {renderSettingsFormRow(\n 'MIME',\n 'fieldAcceptedMimeTypes',\n renderSettingsTextarea({\n name: 'fieldAcceptedMimeTypes',\n onChange: (value): void =>\n updateSelectedFileUploadField({\n acceptedMimeTypes: parseStringList(value),\n }),\n placeholder: '每行一個 MIME type,例如:application/pdf',\n rows: 3,\n value: readStringListInput(field.acceptedMimeTypes),\n }),\n false,\n )}\n </>\n );\n }\n\n function renderConditionSettings(field: FormFieldDefinition): ReactElement {\n const conditionFieldOptions = schema.fields.filter(\n (schemaField) => schemaField.fieldKey !== field.fieldKey,\n );\n\n if (!conditionFieldOptions.length) {\n return (\n <Typography\n color=\"text-neutral\"\n style={FIELD_SETTINGS_HINT_STYLE}\n variant=\"body\"\n >\n 目前沒有其他欄位可作為條件來源。新增更多欄位後即可設定條件規則。\n </Typography>\n );\n }\n\n return (\n <>\n {CONDITION_RULE_CONFIGS.map((config) =>\n renderConditionRule(field, config, conditionFieldOptions),\n )}\n </>\n );\n }\n\n function renderConditionRule(\n field: FormFieldDefinition,\n config: ConditionRuleConfig,\n conditionFieldOptions: readonly FormFieldDefinition[],\n ): ReactElement {\n const expression = field[config.target];\n const parsedRule = expression ? parseConditionRule(expression) : null;\n const parsedConditionField = conditionFieldOptions.find(\n (conditionField) => conditionField.fieldKey === parsedRule?.fieldKey,\n );\n const selectedConditionField =\n parsedConditionField ?? conditionFieldOptions[0];\n const conditionFieldSelectOptions = conditionFieldOptions.map(\n readFieldAsConditionSelectOption,\n );\n const conditionOperatorOptions = readConditionOperatorOptions(\n selectedConditionField,\n );\n const selectedOperator =\n parsedRule &&\n conditionOperatorOptions.some(\n (option) => option.id === parsedRule.operator,\n )\n ? parsedRule.operator\n : readDefaultConditionOperator(selectedConditionField);\n const selectedValue =\n parsedRule?.value ?? readDefaultConditionValue(selectedConditionField);\n const enabled = Boolean(expression);\n const unsupportedRule = enabled && (!parsedRule || !parsedConditionField);\n\n return renderSettingsFormRow(\n config.label,\n config.name,\n <div style={CONDITION_RULE_CONTROL_STYLE}>\n <Toggle\n checked={enabled}\n label={enabled ? '已啟用' : '不啟用'}\n onChange={(event: ChangeEvent<HTMLInputElement>): void =>\n updateSelectedConditionRule(\n config.target,\n event.target.checked\n ? buildConditionExpression(\n selectedConditionField,\n readDefaultConditionOperator(selectedConditionField),\n readDefaultConditionValue(selectedConditionField),\n )\n : undefined,\n )\n }\n size=\"sub\"\n supportingText={config.supportingText}\n />\n {enabled ? (\n unsupportedRule ? (\n <Typography color=\"text-warning\" variant=\"body\">\n 這個規則不是目前 UI 支援的格式。重新選擇條件後會取代既有規則。\n </Typography>\n ) : (\n <div style={CONDITION_RULE_GRID_STYLE}>\n <Select\n clearable={false}\n onChange={(option): void => {\n const nextField =\n conditionFieldOptions.find(\n (conditionField) =>\n conditionField.fieldKey === option?.id,\n ) ?? selectedConditionField;\n\n updateSelectedConditionRule(\n config.target,\n buildConditionExpression(\n nextField,\n readDefaultConditionOperator(nextField),\n readDefaultConditionValue(nextField),\n ),\n );\n }}\n options={conditionFieldSelectOptions}\n placeholder=\"選擇欄位\"\n value={readSelectOption(\n conditionFieldSelectOptions,\n selectedConditionField.fieldKey,\n )}\n />\n <Select\n clearable={false}\n onChange={(option): void =>\n updateSelectedConditionRule(\n config.target,\n buildConditionExpression(\n selectedConditionField,\n readConditionOperatorOption(option?.id) ??\n selectedOperator,\n selectedValue,\n ),\n )\n }\n options={[...conditionOperatorOptions]}\n placeholder=\"判斷方式\"\n value={readSelectOption(\n conditionOperatorOptions,\n selectedOperator,\n )}\n />\n {renderConditionValueControl(\n selectedConditionField,\n selectedValue,\n (nextValue): void =>\n updateSelectedConditionRule(\n config.target,\n buildConditionExpression(\n selectedConditionField,\n selectedOperator,\n nextValue,\n ),\n ),\n )}\n </div>\n )\n ) : null}\n </div>,\n true,\n );\n }\n\n function updateSelectedConditionRule(\n target: ConditionRuleTarget,\n expression: string | undefined,\n ): void {\n updateSelectedField({ [target]: expression });\n }\n\n function renderConditionValueControl(\n conditionField: FormFieldDefinition,\n value: string,\n onChange: (value: string) => void,\n ): ReactElement {\n if (conditionField.type === 'boolean') {\n return (\n <Select\n clearable={false}\n onChange={(option): void => onChange(option?.id ?? 'true')}\n options={[...BOOLEAN_CONDITION_VALUE_OPTIONS]}\n placeholder=\"比較值\"\n value={readSelectOption(\n BOOLEAN_CONDITION_VALUE_OPTIONS,\n value === 'false' ? 'false' : 'true',\n )}\n />\n );\n }\n\n if (isSelectFieldDefinition(conditionField)) {\n const options = conditionField.options.map(readFieldOptionAsSelectOption);\n\n return (\n <Select\n clearable={false}\n onChange={(option): void =>\n onChange(option?.id ?? options[0]?.id ?? '')\n }\n options={options}\n placeholder=\"比較值\"\n value={readSelectOption(options, value)}\n />\n );\n }\n\n if (isNumberFieldDefinition(conditionField)) {\n return renderNumberInput(\n parseOptionalNumberInput(value),\n (nextValue): void => onChange(String(nextValue ?? 0)),\n '比較值',\n );\n }\n\n if (isDateFieldDefinition(conditionField)) {\n return renderDateValuePicker(conditionField, value, (nextValue): void =>\n onChange(nextValue ?? ''),\n );\n }\n\n return (\n <Input\n onChange={(event: ChangeEvent<HTMLInputElement>): void =>\n onChange(event.target.value)\n }\n placeholder=\"比較值\"\n value={value}\n variant=\"base\"\n />\n );\n }\n\n function renderSettingsTextarea({\n name,\n onChange,\n placeholder,\n rows,\n value,\n }: {\n readonly name: string;\n readonly onChange: (value: string) => void;\n readonly placeholder: string;\n readonly rows: number;\n readonly value: string;\n }): ReactElement {\n return (\n <Textarea\n aria-label={name}\n onChange={(event: ChangeEvent<HTMLTextAreaElement>): void =>\n onChange(event.target.value)\n }\n placeholder={placeholder}\n ref={applyFullWidthTextareaHost}\n resize=\"vertical\"\n rows={rows}\n style={FIELD_SETTINGS_TEXTAREA_STYLE}\n value={value}\n />\n );\n }\n\n function renderNumberInput(\n value: number | undefined,\n onChange: (value: number | undefined) => void,\n placeholder: string,\n options: {\n readonly max?: number;\n readonly min?: number;\n readonly step?: number;\n } = {},\n ): ReactElement {\n return (\n <Input\n max={options.max}\n min={options.min}\n onChange={(event: ChangeEvent<HTMLInputElement>): void =>\n onChange(\n clampOptionalNumber(\n parseOptionalNumberInput(event.target.value),\n options,\n ),\n )\n }\n placeholder={placeholder}\n showSpinner\n step={options.step ?? 1}\n value={typeof value === 'number' ? String(value) : ''}\n variant=\"measure\"\n />\n );\n }\n\n function renderDateValuePicker(\n field: DateFieldDefinition,\n value: string,\n onChange: (value: string | undefined) => void,\n ): ReactElement {\n if (field.type === 'datetime') {\n return (\n <DateTimePicker\n formatDate=\"YYYY-MM-DD\"\n formatTime=\"HH:mm\"\n hideSecond\n onChange={(nextValue): void =>\n onChange(formatDateTimePickerValue(nextValue))\n }\n placeholderLeft=\"選擇日期\"\n placeholderRight=\"選擇時間\"\n value={readDatePickerValue(value)}\n />\n );\n }\n\n return (\n <DatePicker\n format=\"YYYY-MM-DD\"\n onChange={(nextValue): void =>\n onChange(formatDatePickerValue(nextValue))\n }\n placeholder=\"選擇日期\"\n value={readDatePickerValue(value)}\n />\n );\n }\n\n function renderFieldOptionsTable(\n field: FormStaticOptionFieldDefinition,\n ): ReactElement {\n const optionRows: FieldOptionRow[] = field.options.map((option, index) => ({\n index,\n key: `${field.fieldKey}-${index}`,\n label: option.label,\n value: option.value,\n }));\n const optionColumns: TableColumn<FieldOptionRow>[] = [\n {\n key: 'label',\n render: (row): ReactElement => (\n <Input\n onChange={(event: ChangeEvent<HTMLInputElement>): void =>\n updateSelectedSelectField({\n options: updateFieldOption(field.options, row.index, {\n label: event.target.value,\n }),\n })\n }\n placeholder=\"例如:主管\"\n size=\"sub\"\n value={row.label}\n variant=\"base\"\n />\n ),\n title: 'Label',\n },\n {\n key: 'value',\n render: (row): ReactElement => (\n <Input\n onChange={(event: ChangeEvent<HTMLInputElement>): void =>\n updateSelectedSelectField({\n options: updateFieldOption(field.options, row.index, {\n value: event.target.value,\n }),\n })\n }\n placeholder=\"例如:manager\"\n size=\"sub\"\n value={row.value}\n variant=\"base\"\n />\n ),\n title: 'Value',\n },\n ];\n const optionActions: TableActions<FieldOptionRow> = {\n render: (row): ReturnType<TableActions<FieldOptionRow>['render']> => [\n {\n disabled: (): boolean => field.options.length <= 1,\n icon: TrashIcon,\n iconType: 'icon-only',\n name: '移除選項',\n onClick: (): void =>\n updateSelectedSelectField({\n options: field.options.filter((_, index) => index !== row.index),\n }),\n variant: 'destructive-ghost',\n },\n ],\n width: 56,\n };\n\n return (\n <div style={COMPACT_STACK_STYLE}>\n <Table\n actions={optionActions}\n columns={optionColumns}\n dataSource={optionRows}\n showHeader\n size=\"sub\"\n />\n <div style={OPTION_ACTIONS_STYLE}>\n <Button\n icon={PlusIcon}\n iconType=\"leading\"\n onClick={(): void =>\n updateSelectedSelectField({\n options: [\n ...field.options,\n createNextFieldOption(field.options),\n ],\n })\n }\n variant=\"base-secondary\"\n >\n 新增選項\n </Button>\n </div>\n </div>\n );\n }\n\n function renderFieldBlock(\n field: FormFieldDefinition,\n draggableProvided: DraggableProvided,\n isDragging: boolean,\n ): ReactElement {\n return (\n <div\n {...draggableProvided.draggableProps}\n data-form-builder-field-key={field.fieldKey}\n ref={draggableProvided.innerRef}\n style={{\n ...FIELD_BLOCK_STYLE,\n ...(isDragging ? FIELD_BLOCK_DRAGGING_STYLE : null),\n ...draggableProvided.draggableProps.style,\n }}\n >\n <BaseCard\n style={\n field.fieldKey === selectedField?.fieldKey\n ? FIELD_BLOCK_SELECTED_CARD_STYLE\n : undefined\n }\n >\n {renderFieldBlockContent(field, draggableProvided, isDragging)}\n </BaseCard>\n </div>\n );\n }\n\n function renderSettingsFormRow(\n label: string,\n name: string,\n control: ReactElement,\n wide = false,\n ): ReactElement {\n return (\n <div\n style={wide ? FIELD_SETTINGS_ROW_WIDE_STYLE : FIELD_SETTINGS_ROW_STYLE}\n >\n <div style={FIELD_SETTINGS_VALUE_STYLE}>\n <BPMFormField label={label} name={name}>\n {control}\n </BPMFormField>\n </div>\n </div>\n );\n }\n\n function renderFieldBlockContent(\n field: FormFieldDefinition,\n draggableProvided: DraggableProvided,\n isDragging: boolean,\n ): ReactElement {\n return (\n <div\n {...(draggableProvided.dragHandleProps ?? {})}\n aria-label=\"選取或拖曳排序欄位\"\n onClick={(): void => setSelectedFieldKey(field.fieldKey)}\n style={FIELD_BLOCK_ROW_STYLE}\n title=\"點擊選取,拖曳排序\"\n >\n <span\n aria-label=\"拖曳排序\"\n role=\"img\"\n style={DRAG_HANDLE_STYLE}\n title=\"拖曳排序\"\n >\n <Icon icon={DotDragVerticalIcon} size={20} />\n </span>\n <div style={FIELD_BLOCK_TEXT_STYLE}>\n <Typography component=\"span\" ellipsis variant=\"label-primary\">\n {field.label}\n {field.required ? (\n <sup aria-label=\"必填\" style={REQUIRED_ASTERISK_STYLE}>\n *\n </sup>\n ) : null}\n </Typography>\n <Typography\n color=\"text-neutral\"\n component=\"span\"\n ellipsis\n variant=\"caption\"\n >\n {readFieldTypeLabel(field.type)} ·\n {field.required ? ' 必填' : ' 選填'} ·{field.fieldKey}\n </Typography>\n </div>\n <div\n onClick={(event: MouseEvent<HTMLDivElement>): void =>\n event.stopPropagation()\n }\n style={FIELD_BLOCK_ACTIONS_STYLE}\n >\n <div style={FIELD_BLOCK_REQUIRED_STYLE}>\n <Toggle\n checked={Boolean(field.required)}\n disabled={isDragging}\n label=\"必填\"\n onChange={(event: ChangeEvent<HTMLInputElement>): void =>\n updateFieldRequired(field.fieldKey, event.target.checked)\n }\n />\n </div>\n <Button\n disabled={isDragging}\n icon={TrashIcon}\n iconType=\"icon-only\"\n onClick={(): void => handleRemoveField(field.fieldKey)}\n variant=\"destructive-ghost\"\n >\n 移除欄位\n </Button>\n </div>\n </div>\n );\n }\n\n function renderPreviewTab(): ReactElement {\n return (\n <div style={STACK_STYLE}>\n <Typography component=\"h2\" variant=\"h3\">\n 填寫預覽\n </Typography>\n <FormRenderer\n dataSourceContext={{ kind: 'preview' }}\n onChange={updatePreviewValues}\n schema={schema}\n uiSchema={uiSchema}\n value={previewValues}\n />\n </div>\n );\n }\n\n function renderAdvancedTab(): ReactElement {\n return (\n <div style={STACK_STYLE}>\n <Typography component=\"h2\" variant=\"h3\">\n Schema\n </Typography>\n <div style={ADVANCED_SCHEMA_FORM_STYLE}>\n {renderAdvancedSchemaRow(\n 'Form Schema',\n 'schemaJson',\n <JsonCodeEditor\n height=\"360px\"\n name=\"schemaJson\"\n onChange={updateSchemaJson}\n placeholder=\"輸入 Form Schema JSON\"\n value={schemaJsonText}\n />,\n )}\n {renderAdvancedSchemaRow(\n 'UI Schema',\n 'uiSchemaJson',\n <JsonCodeEditor\n height=\"240px\"\n name=\"uiSchemaJson\"\n onChange={updateUiSchemaJson}\n placeholder=\"輸入 UI Schema JSON\"\n value={uiSchemaJsonText}\n />,\n )}\n {advancedSchemaMessage ? (\n <Typography\n color=\"text-error\"\n style={ADVANCED_SCHEMA_MESSAGE_STYLE}\n variant=\"body\"\n >\n {advancedSchemaMessage}\n </Typography>\n ) : null}\n </div>\n </div>\n );\n }\n\n function renderAdvancedSchemaRow(\n label: string,\n name: string,\n control: ReactElement,\n ): ReactElement {\n return (\n <div style={ADVANCED_SCHEMA_ROW_STYLE}>\n <div style={ADVANCED_SCHEMA_VALUE_STYLE}>\n <BPMFormField label={label} name={name}>\n {control}\n </BPMFormField>\n </div>\n </div>\n );\n }\n}\n\nfunction readFieldTypeLabel(type: FieldType): string {\n return (\n FIELD_TYPE_OPTIONS.find((option) => option.type === type)?.label ?? type\n );\n}\n\nfunction readDataSourceDescriptorOptionId(value: {\n readonly key: string;\n readonly version: number;\n}): string {\n return `${value.key}@${value.version}`;\n}\n\nfunction readDataSourceDescriptorOption(\n descriptor: FormDataSourceDescriptorRecord,\n): { readonly id: string; readonly name: string } {\n return {\n id: readDataSourceDescriptorOptionId(descriptor),\n name: `${descriptor.label} · ${descriptor.key} v${descriptor.version}`,\n };\n}\n\nfunction readDataSourceBindingOptionId(\n binding: FormDataSourceBinding | null,\n): string {\n if (!binding) {\n return UNBOUND_BINDING_ID;\n }\n\n return binding.from.kind === 'FIELD'\n ? binding.from.fieldKey\n : CONSTANT_BINDING_ID;\n}\n\nfunction readDefaultDataSourceConstant(\n parameterType: FormDataSourceParameterType,\n): FormDataSourceConstantValue {\n switch (parameterType) {\n case 'BOOLEAN':\n return false;\n case 'NUMBER':\n return 0;\n case 'STRING_ARRAY':\n return '';\n case 'STRING':\n return '';\n default:\n return '';\n }\n}\n\nfunction readDataSourceConstantInputValue(\n binding: FormDataSourceBinding | null,\n parameterType: FormDataSourceParameterType,\n): string {\n const value = binding?.from.kind === 'CONSTANT' ? binding.from.value : '';\n\n if (parameterType === 'NUMBER') {\n return typeof value === 'number' ? String(value) : '';\n }\n\n return typeof value === 'string' ? value : '';\n}\n\nfunction hasConditionRules(field: FormFieldDefinition): boolean {\n return Boolean(field.visibleWhen || field.requiredWhen || field.readonlyWhen);\n}\n\nfunction readFieldAsConditionSelectOption(field: FormFieldDefinition): {\n readonly id: string;\n readonly name: string;\n} {\n return {\n id: field.fieldKey,\n name: field.label,\n };\n}\n\nfunction isTextFieldDefinition(\n field: FormFieldDefinition,\n): field is TextFieldDefinition {\n return field.type === 'text' || field.type === 'textarea';\n}\n\nfunction readStringDefaultValue(\n value: FormFieldDefinition['defaultValue'],\n): string {\n return typeof value === 'string' ? value : '';\n}\n\nfunction parseStringList(value: string): readonly string[] | undefined {\n const values = value\n .split(/[\\n,]/u)\n .map((item) => item.trim())\n .filter(Boolean);\n\n return values.length ? values : undefined;\n}\n\nfunction readStringListInput(value: readonly string[] | undefined): string {\n return value?.join('\\n') ?? '';\n}\n\nfunction stringifyJson(value: unknown): string {\n return JSON.stringify(value, null, 2);\n}\n\nfunction updateFieldOption(\n options: readonly FormFieldOption[],\n targetIndex: number,\n patch: Partial<FormFieldOption>,\n): readonly FormFieldOption[] {\n return options.map((option, index) =>\n index === targetIndex ? { ...option, ...patch } : option,\n );\n}\n\nfunction createNextFieldOption(\n options: readonly FormFieldOption[],\n): FormFieldOption {\n const nextIndex = options.length + 1;\n\n return {\n label: `選項 ${nextIndex}`,\n value: readNextOptionValue(options, nextIndex),\n };\n}\n\nfunction readNextOptionValue(\n options: readonly FormFieldOption[],\n index: number,\n): string {\n const value = `option_${index}`;\n\n return options.some((option) => option.value === value)\n ? readNextOptionValue(options, index + 1)\n : value;\n}\n\nfunction moveItemByIndex<TItem>(\n items: readonly TItem[],\n sourceIndex: number,\n destinationIndex: number,\n): TItem[] {\n const sourceItem = items[sourceIndex];\n\n if (!sourceItem || sourceIndex === destinationIndex) {\n return [...items];\n }\n\n const remainingItems = items.filter((_, index) => index !== sourceIndex);\n\n return [\n ...remainingItems.slice(0, destinationIndex),\n sourceItem,\n ...remainingItems.slice(destinationIndex),\n ];\n}\n"],"mappings":"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"}