@rytass/bpm-core-react 0.7.7 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +121 -0
- package/README.md +18 -2
- package/dist/chunks/FormBuilderView-BPLwAJGv.cjs +3 -0
- package/dist/chunks/FormBuilderView-BPLwAJGv.cjs.map +1 -0
- package/dist/chunks/FormBuilderView-Do9-MIAe.js +1477 -0
- package/dist/chunks/FormBuilderView-Do9-MIAe.js.map +1 -0
- package/dist/chunks/FormRendererView-C5POZbWz.js +492 -0
- package/dist/chunks/FormRendererView-C5POZbWz.js.map +1 -0
- package/dist/chunks/FormRendererView-DNtNodNl.cjs +2 -0
- package/dist/chunks/FormRendererView-DNtNodNl.cjs.map +1 -0
- package/dist/chunks/{approval-instance-list-page-YZcGGDD8.js → approval-instance-list-page-BjX2kaoF.js} +56 -54
- package/dist/chunks/approval-instance-list-page-BjX2kaoF.js.map +1 -0
- package/dist/chunks/approval-instance-list-page-C408vxE2.cjs +2 -0
- package/dist/chunks/approval-instance-list-page-C408vxE2.cjs.map +1 -0
- package/dist/chunks/{categories-DBPoSrsi.js → categories-DGlxuC6X.js} +5 -5
- package/dist/chunks/{categories-DBPoSrsi.js.map → categories-DGlxuC6X.js.map} +1 -1
- package/dist/chunks/{categories-B6QZKZRt.cjs → categories-DUfldZ_9.cjs} +2 -2
- package/dist/chunks/{categories-B6QZKZRt.cjs.map → categories-DUfldZ_9.cjs.map} +1 -1
- package/dist/chunks/compose-CULMDsLS.cjs +2 -0
- package/dist/chunks/compose-CULMDsLS.cjs.map +1 -0
- package/dist/chunks/{compose-B1quUa7y.js → compose-DJBlA5PD.js} +60 -58
- package/dist/chunks/compose-DJBlA5PD.js.map +1 -0
- package/dist/chunks/{delegations-DDEk-WI6.cjs → delegations-CGj-tZNO.cjs} +2 -2
- package/dist/chunks/{delegations-DDEk-WI6.cjs.map → delegations-CGj-tZNO.cjs.map} +1 -1
- package/dist/chunks/{delegations-iVnRi3QE.js → delegations-DLEEFBlH.js} +231 -231
- package/dist/chunks/{delegations-iVnRi3QE.js.map → delegations-DLEEFBlH.js.map} +1 -1
- package/dist/chunks/{delegations-ZNtodFaD.js → delegations-DqMpI_Nk.js} +168 -167
- package/dist/chunks/delegations-DqMpI_Nk.js.map +1 -0
- package/dist/chunks/delegations-kbMOSEif.cjs +2 -0
- package/dist/chunks/delegations-kbMOSEif.cjs.map +1 -0
- package/dist/chunks/designer-BszXJ5RO.js +3038 -0
- package/dist/chunks/designer-BszXJ5RO.js.map +1 -0
- package/dist/chunks/designer-CmqAU92b.cjs +65 -0
- package/dist/chunks/designer-CmqAU92b.cjs.map +1 -0
- package/dist/chunks/detail-CDexqBoU.cjs +2 -0
- package/dist/chunks/detail-CDexqBoU.cjs.map +1 -0
- package/dist/chunks/{detail-fg8MTwuH.js → detail-DAak2OXS.js} +737 -653
- package/dist/chunks/detail-DAak2OXS.js.map +1 -0
- package/dist/chunks/notifications--hwl-DR0.cjs +2 -0
- package/dist/chunks/{notifications-BKs4--96.cjs.map → notifications--hwl-DR0.cjs.map} +1 -1
- package/dist/chunks/{notifications-CSulztkU.js → notifications-DJ5wzCye.js} +7 -7
- package/dist/chunks/{notifications-CSulztkU.js.map → notifications-DJ5wzCye.js.map} +1 -1
- package/dist/chunks/{orgs-CrNxqlwp.js → orgs-DytLvZ_X.js} +243 -241
- package/dist/chunks/{orgs-CrNxqlwp.js.map → orgs-DytLvZ_X.js.map} +1 -1
- package/dist/chunks/orgs-Ni22buHs.cjs +2 -0
- package/dist/chunks/orgs-Ni22buHs.cjs.map +1 -0
- package/dist/chunks/providers-DEqcuXw9.js +506 -0
- package/dist/chunks/providers-DEqcuXw9.js.map +1 -0
- package/dist/chunks/providers-D_zTbkQH.cjs +2 -0
- package/dist/chunks/providers-D_zTbkQH.cjs.map +1 -0
- package/dist/chunks/{users-qghSMtLn.cjs → users-0HqlM_VQ.cjs} +2 -2
- package/dist/chunks/{users-qghSMtLn.cjs.map → users-0HqlM_VQ.cjs.map} +1 -1
- package/dist/chunks/{users-CUY139DF.js → users-FWrb3ehW.js} +5 -5
- package/dist/chunks/{users-CUY139DF.js.map → users-FWrb3ehW.js.map} +1 -1
- package/dist/components/notification-drawer.d.ts +4 -3
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +21 -428
- package/dist/index.js.map +1 -1
- package/dist/next/index.cjs +1 -1
- package/dist/next/index.cjs.map +1 -1
- package/dist/next/index.js +16 -15
- package/dist/next/index.js.map +1 -1
- package/dist/pages/admin/delegations/index.cjs +1 -1
- package/dist/pages/admin/delegations/index.js +1 -1
- package/dist/pages/admin/orgs/index.cjs +1 -1
- package/dist/pages/admin/orgs/index.js +1 -1
- package/dist/pages/admin/users/index.cjs +1 -1
- package/dist/pages/admin/users/index.js +1 -1
- package/dist/pages/delegations/index.cjs +1 -1
- package/dist/pages/delegations/index.js +1 -1
- package/dist/pages/instances/detail/index.cjs +1 -1
- package/dist/pages/instances/detail/index.js +1 -1
- package/dist/pages/settings/notifications/index.cjs +1 -1
- package/dist/pages/settings/notifications/index.js +1 -1
- package/dist/pages/templates/categories/index.cjs +1 -1
- package/dist/pages/templates/categories/index.js +1 -1
- package/dist/pages/templates/compose/index.cjs +1 -1
- package/dist/pages/templates/compose/index.js +1 -1
- package/dist/pages/templates/designer/index.cjs +1 -1
- package/dist/pages/templates/designer/index.js +1 -1
- package/dist/views/admin/delegations/index.cjs +1 -1
- package/dist/views/admin/delegations/index.js +1 -1
- package/dist/views/admin/index.cjs +1 -1
- package/dist/views/admin/index.js +3 -3
- package/dist/views/admin/orgs/index.cjs +1 -1
- package/dist/views/admin/orgs/index.js +1 -1
- package/dist/views/admin/users/index.cjs +1 -1
- package/dist/views/admin/users/index.js +1 -1
- package/dist/views/cc/index.cjs +1 -1
- package/dist/views/cc/index.js +1 -1
- package/dist/views/delegations/index.cjs +1 -1
- package/dist/views/delegations/index.js +1 -1
- package/dist/views/forms/builder/index.cjs +1 -1
- package/dist/views/forms/builder/index.js +1 -1
- package/dist/views/forms/renderer/FormRendererView.d.ts +7 -2
- package/dist/views/forms/renderer/form-data-source-field.d.ts +34 -0
- package/dist/views/forms/renderer/index.cjs +1 -1
- package/dist/views/forms/renderer/index.d.ts +1 -0
- package/dist/views/forms/renderer/index.js +2 -2
- package/dist/views/instances/detail/index.cjs +1 -1
- package/dist/views/instances/detail/index.js +1 -1
- package/dist/views/instances/detail/sections/InstanceFormSection.d.ts +4 -1
- package/dist/views/instances/detail/sections/InstanceTasksSection.d.ts +5 -1
- package/dist/views/instances/new/index.cjs +1 -1
- package/dist/views/instances/new/index.cjs.map +1 -1
- package/dist/views/instances/new/index.js +105 -86
- package/dist/views/instances/new/index.js.map +1 -1
- package/dist/views/search/index.cjs +1 -1
- package/dist/views/search/index.js +1 -1
- package/dist/views/sent/index.cjs +1 -1
- package/dist/views/sent/index.js +1 -1
- package/dist/views/settings/index.cjs +1 -1
- package/dist/views/settings/index.js +1 -1
- package/dist/views/settings/notifications/index.cjs +1 -1
- package/dist/views/settings/notifications/index.js +1 -1
- package/dist/views/templates/categories/index.cjs +1 -1
- package/dist/views/templates/categories/index.js +1 -1
- package/dist/views/templates/compose/TemplateComposeWizardView.d.ts +3 -2
- package/dist/views/templates/compose/index.cjs +1 -1
- package/dist/views/templates/compose/index.js +1 -1
- package/dist/views/templates/designer/index.cjs +1 -1
- package/dist/views/templates/designer/index.js +1 -1
- package/dist/views/templates/index.cjs +1 -1
- package/dist/views/templates/index.cjs.map +1 -1
- package/dist/views/templates/index.js +153 -112
- package/dist/views/templates/index.js.map +1 -1
- package/package.json +41 -5
- package/dist/chunks/FormBuilderView-B_KGPjlp.cjs +0 -3
- package/dist/chunks/FormBuilderView-B_KGPjlp.cjs.map +0 -1
- package/dist/chunks/FormBuilderView-D8DrQOXD.js +0 -1090
- package/dist/chunks/FormBuilderView-D8DrQOXD.js.map +0 -1
- package/dist/chunks/FormRendererView-BwVsH2eX.cjs +0 -2
- package/dist/chunks/FormRendererView-BwVsH2eX.cjs.map +0 -1
- package/dist/chunks/FormRendererView-DrHsuSVo.js +0 -220
- package/dist/chunks/FormRendererView-DrHsuSVo.js.map +0 -1
- package/dist/chunks/approval-instance-list-page-BMUKxzcz.cjs +0 -2
- package/dist/chunks/approval-instance-list-page-BMUKxzcz.cjs.map +0 -1
- package/dist/chunks/approval-instance-list-page-YZcGGDD8.js.map +0 -1
- package/dist/chunks/compose-B1quUa7y.js.map +0 -1
- package/dist/chunks/compose-B6nevcwq.cjs +0 -2
- package/dist/chunks/compose-B6nevcwq.cjs.map +0 -1
- package/dist/chunks/delegations-C2wLWsDQ.cjs +0 -2
- package/dist/chunks/delegations-C2wLWsDQ.cjs.map +0 -1
- package/dist/chunks/delegations-ZNtodFaD.js.map +0 -1
- package/dist/chunks/designer-BLfz5Dk9.js +0 -2594
- package/dist/chunks/designer-BLfz5Dk9.js.map +0 -1
- package/dist/chunks/designer-DP002lt7.cjs +0 -65
- package/dist/chunks/designer-DP002lt7.cjs.map +0 -1
- package/dist/chunks/detail-KEmfpCtt.cjs +0 -2
- package/dist/chunks/detail-KEmfpCtt.cjs.map +0 -1
- package/dist/chunks/detail-fg8MTwuH.js.map +0 -1
- package/dist/chunks/notifications-BKs4--96.cjs +0 -2
- package/dist/chunks/orgs-iNJ0QEcK.cjs +0 -2
- package/dist/chunks/orgs-iNJ0QEcK.cjs.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,60 @@
|
|
|
1
|
+
## 0.9.0 (2026-08-17)
|
|
2
|
+
|
|
3
|
+
### 🚀 Features
|
|
4
|
+
|
|
5
|
+
- **notification:** lift routing fields onto the created event ([e02270b](https://github.com/Rytass/BPMCore/commit/e02270b))
|
|
6
|
+
- **notification:** let a host observe notifications as they are created ([#21](https://github.com/Rytass/BPMCore/pull/21))
|
|
7
|
+
- **shared:** detect a quorum no approver set can ever satisfy ([5671497](https://github.com/Rytass/BPMCore/commit/5671497))
|
|
8
|
+
- **shared:** expose the decision policy to the workflow toolset ([f6152b0](https://github.com/Rytass/BPMCore/commit/f6152b0))
|
|
9
|
+
- **bpm-core-react:** let the designer configure the decision policy ([6a4caf1](https://github.com/Rytass/BPMCore/commit/6a4caf1))
|
|
10
|
+
|
|
11
|
+
### 🩹 Fixes
|
|
12
|
+
|
|
13
|
+
- ⚠️ **template:** reject deleting a referenced category ([#16](https://github.com/Rytass/BPMCore/pull/16))
|
|
14
|
+
- **template:** let a template actually change category ([#17](https://github.com/Rytass/BPMCore/pull/17))
|
|
15
|
+
- **shared:** keep an approver change from discarding a workable policy ([ea6afbe](https://github.com/Rytass/BPMCore/commit/ea6afbe))
|
|
16
|
+
- **bpm-core-react:** stop the member resolve effect looping on failure ([a0bfa66](https://github.com/Rytass/BPMCore/commit/a0bfa66))
|
|
17
|
+
- **bpm-core-react:** stop the dropped-policy notice outliving its subject ([7fddefe](https://github.com/Rytass/BPMCore/commit/7fddefe))
|
|
18
|
+
- **bpm-core-react:** re-request members left as unresolved placeholders ([567c776](https://github.com/Rytass/BPMCore/commit/567c776))
|
|
19
|
+
- **bpm-core-react:** finish the member picker's stale-response handling ([dda3692](https://github.com/Rytass/BPMCore/commit/dda3692))
|
|
20
|
+
- **bpm-core-react:** keep the dropped-policy notice on screen ([7557dc8](https://github.com/Rytass/BPMCore/commit/7557dc8))
|
|
21
|
+
- **bpm-core-react:** stop re-applying an unsatisfiable policy ([e548f14](https://github.com/Rytass/BPMCore/commit/e548f14))
|
|
22
|
+
- **bpm-core-react:** tolerate malformed stored quorum policies ([f4fcb41](https://github.com/Rytass/BPMCore/commit/f4fcb41))
|
|
23
|
+
- **bpm-core-react:** cap PERCENTAGE quorum threshold and sanitise every write ([d70528a](https://github.com/Rytass/BPMCore/commit/d70528a))
|
|
24
|
+
- **bpm-core-react:** stop member pickers offering stale or phantom rows ([f4f82c9](https://github.com/Rytass/BPMCore/commit/f4f82c9))
|
|
25
|
+
- **e2e:** poll on the expected value in the quorum threshold sanitiser spec ([099529f](https://github.com/Rytass/BPMCore/commit/099529f))
|
|
26
|
+
- **bpm-core-react:** correct decision-policy panel review findings ([ebf0337](https://github.com/Rytass/BPMCore/commit/ebf0337))
|
|
27
|
+
- **bpm-core-react:** show only the latest member search results ([9804d37](https://github.com/Rytass/BPMCore/commit/9804d37))
|
|
28
|
+
|
|
29
|
+
### ⚠️ Breaking Changes
|
|
30
|
+
|
|
31
|
+
- **template:** reject deleting a referenced category ([#16](https://github.com/Rytass/BPMCore/pull/16))
|
|
32
|
+
`deleteApprovalTemplateCategory` now throws
|
|
33
|
+
`BadRequestException` when templates still reference the category, instead
|
|
34
|
+
of deactivating it and reporting success.
|
|
35
|
+
The old behaviour substituted a different operation for the one requested
|
|
36
|
+
and returned the same entity type either way, so a caller could not tell
|
|
37
|
+
that the delete had not happened — nor that `isActive` had been flipped as
|
|
38
|
+
a side effect it never asked for. Downstream, the category vanished from
|
|
39
|
+
groupings because it was now inactive, with nothing to explain why.
|
|
40
|
+
Deactivation is not lost: `deactivateApprovalTemplateCategory(id)` has
|
|
41
|
+
always existed and is unchanged, so the fallback was never the only way to
|
|
42
|
+
reach that state.
|
|
43
|
+
The designer's category screen already wraps the call in try/catch and
|
|
44
|
+
surfaces the message, and it only closes the confirmation dialog on
|
|
45
|
+
success, so the new error reaches the author without a UI change.
|
|
46
|
+
Reported by a consumer on 0.7.0, who had to re-implement the reference
|
|
47
|
+
check ahead of the call to avoid telling users something had been deleted
|
|
48
|
+
when it had not.
|
|
49
|
+
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
|
50
|
+
|
|
51
|
+
### ❤️ Thank You
|
|
52
|
+
|
|
53
|
+
- Chia Yu Pai @fantasywind
|
|
54
|
+
- Claude Opus 5
|
|
55
|
+
- Claude Opus 5 (1M context)
|
|
56
|
+
- Kai-Chieh Yang
|
|
57
|
+
|
|
1
58
|
# Changelog
|
|
2
59
|
|
|
3
60
|
All notable changes to `@rytass/bpm-core-react` are documented in this file.
|
|
@@ -5,9 +62,73 @@ All notable changes to `@rytass/bpm-core-react` are documented in this file.
|
|
|
5
62
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)
|
|
6
63
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
64
|
|
|
65
|
+
## Unreleased
|
|
66
|
+
|
|
67
|
+
### Added
|
|
68
|
+
|
|
69
|
+
- Form builder and renderer schemas now recognize the `autocomplete` option
|
|
70
|
+
field while retaining Mezzanine controls and primitive form values.
|
|
71
|
+
- FormRenderer now supports host-bounded preview/runtime DataSource contexts,
|
|
72
|
+
snapshot hydration, async Mezzanine Select/AutoComplete controls, complete
|
|
73
|
+
list Radio/Checkbox controls, paging/search state, retry feedback, and
|
|
74
|
+
submission blocking for unresolved dynamic values.
|
|
75
|
+
- FormBuilderView now loads the host DataSource Catalog, filters sources by
|
|
76
|
+
control capability, edits field/constant bindings, preserves bindings when a
|
|
77
|
+
field key changes, and confirms source/mode changes or dependent-field
|
|
78
|
+
removal before updating the schema. DataSource schema lint is available from
|
|
79
|
+
the editor.
|
|
80
|
+
|
|
81
|
+
### Fixed
|
|
82
|
+
|
|
83
|
+
- The template designer now restores missing legacy edge data before rendering,
|
|
84
|
+
so older workflow JSON without an edge `data` object remains editable.
|
|
85
|
+
- Dynamic option failures no longer surface raw `FORM_DATA_SOURCE_*` codes.
|
|
86
|
+
Launch, resubmit, field-level, form builder lint, and template
|
|
87
|
+
designer/compose publish messages now show mapped copy, so a value that
|
|
88
|
+
expired reads as "已選取的選項已失效,請重新選擇。" instead of an error code.
|
|
89
|
+
|
|
8
90
|
Releases are managed by [`nx release`](https://nx.dev/recipes/nx-release) with
|
|
9
91
|
Conventional Commits — see `nx.json` for the release config.
|
|
10
92
|
|
|
93
|
+
## 0.8.0 — 2026-08-10
|
|
94
|
+
|
|
95
|
+
### Added
|
|
96
|
+
|
|
97
|
+
- **SLA and return-comment controls in the template designer.** The node panel
|
|
98
|
+
had no SLA fields at all, so a working-day deadline could only be set through
|
|
99
|
+
the API. It now exposes the timer the way the approver resolver already
|
|
100
|
+
works — a master toggle that progressively reveals the duration, its unit,
|
|
101
|
+
the calendar mode, the timeout action, the escalation level and the warning
|
|
102
|
+
threshold — plus a `returnBehavior.requireComment` toggle.
|
|
103
|
+
|
|
104
|
+
The deadline is entered as a number and a unit rather than a raw ISO
|
|
105
|
+
duration, so the form cannot produce a mixed `P1DT4H`; the calendar selector
|
|
106
|
+
only appears for day-based durations, since a business calendar advances
|
|
107
|
+
whole days only.
|
|
108
|
+
|
|
109
|
+
- **Required return comments in the instance view.** The return dialog marks
|
|
110
|
+
the comment required and keeps the submit button disabled until it is filled,
|
|
111
|
+
so approvers see the node's rule before the server rejects the decision.
|
|
112
|
+
|
|
113
|
+
### Fixed
|
|
114
|
+
|
|
115
|
+
- **Designer toggles were not label-clickable.** `FormField` renders
|
|
116
|
+
`<label htmlFor={name}>`, but the toggles carried no matching `id`, so those
|
|
117
|
+
labels pointed at nothing. All node-panel toggles now set `id` and `name`.
|
|
118
|
+
|
|
119
|
+
### Changed
|
|
120
|
+
|
|
121
|
+
- Widened peer dependency ranges to `^0.4.0 || ^0.5.0 || ^0.6.0 || ^0.7.0` for
|
|
122
|
+
`@rytass/bpm-core-client` and `@rytass/bpm-core-shared`. The new designer
|
|
123
|
+
controls read `SlaConfig.calendar` and `ReturnBehavior.requireComment`, which
|
|
124
|
+
only exist from 0.7.0 — on older core packages the extra fields are simply
|
|
125
|
+
absent and the panel falls back to its previous behaviour.
|
|
126
|
+
|
|
127
|
+
### Why a minor
|
|
128
|
+
|
|
129
|
+
New optional UI controls over additive contract fields; no component API or
|
|
130
|
+
existing behaviour changed.
|
|
131
|
+
|
|
11
132
|
## 0.7.7 — 2026-08-04
|
|
12
133
|
|
|
13
134
|
### Changed
|
package/README.md
CHANGED
|
@@ -4,6 +4,23 @@ React provider / hook / view components for the Rytass BPM approval workflow sta
|
|
|
4
4
|
|
|
5
5
|
This package composes [`@mezzanine-ui/react`](https://www.npmjs.com/package/@mezzanine-ui/react) primitives with the BPM domain logic in [`@rytass/bpm-core-client`](https://www.npmjs.com/package/@rytass/bpm-core-client) and [`@rytass/bpm-core-shared`](https://www.npmjs.com/package/@rytass/bpm-core-shared) so a consumer can wire up the full BPM admin UI by re-exporting page modules from their Next.js App Router.
|
|
6
6
|
|
|
7
|
+
Form views understand the additive `autocomplete` and option-source schema
|
|
8
|
+
variants while preserving primitive single-value and multiple-value payloads.
|
|
9
|
+
Dynamic registry queries and server-side validation remain behind the BPM
|
|
10
|
+
client/core runtime boundaries; React controls do not call external sources
|
|
11
|
+
directly. Pass a `dataSourceContext` with `kind: 'preview'` for designer
|
|
12
|
+
preview or a published-template/instance `kind: 'runtime'` context for an
|
|
13
|
+
editable form. Read-only instance rendering should omit the runtime context
|
|
14
|
+
and pass `optionSnapshots` so historical labels remain available without a
|
|
15
|
+
network query.
|
|
16
|
+
|
|
17
|
+
The controlled `FormBuilderView` loads only the host-registered DataSource
|
|
18
|
+
Catalog. It filters sources by control capability, supports typed field and
|
|
19
|
+
constant parameter bindings, preserves bindings when a field key is renamed,
|
|
20
|
+
and asks for confirmation before source/mode changes or removing a field used
|
|
21
|
+
by another dynamic field. The editor can send the complete schema to the
|
|
22
|
+
server-side lint contract before publishing.
|
|
23
|
+
|
|
7
24
|
## Status
|
|
8
25
|
|
|
9
26
|
`0.4.0` (breaking) — drops the bundled navigation shell. BPM views no longer wrap themselves in an `<AppLayout>` / Mezzanine `<Navigation>`; the host owns the layout chrome and mounts BPM views inside its own sidebar / top bar. New host-facing widgets ship in the root barrel: `useBPMMember`, `useBPMLogout`, `<BPMNotificationBellButton />`. See `CHANGELOG.md` for the migration walkthrough, and `docs/integration-guide.md` for a host integration recipe.
|
|
@@ -190,11 +207,10 @@ function createPrefixedRoutes(prefix: string): BPMRoutes {
|
|
|
190
207
|
? `${trim}/instances/new?templateId=${encodeURIComponent(templateId)}`
|
|
191
208
|
: `${trim}/instances/new`,
|
|
192
209
|
templates: () => `${trim}/templates`,
|
|
210
|
+
templateCompose: () => `${trim}/templates/compose`,
|
|
193
211
|
templateDesigner: (id) => `${trim}/templates/${id}/designer`,
|
|
194
212
|
templateVersions: (id) => `${trim}/templates/${id}/versions`,
|
|
195
213
|
templateCategories: () => `${trim}/templates/categories`,
|
|
196
|
-
forms: () => `${trim}/forms`,
|
|
197
|
-
formBuilder: (id) => `${trim}/forms/${id}/builder`,
|
|
198
214
|
notificationSettings: () => `${trim}/settings/notifications`,
|
|
199
215
|
adminOrgs: () => `${trim}/admin/orgs`,
|
|
200
216
|
adminUsers: () => `${trim}/admin/users`,
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
"use client";const e=require("./chunk-CMqjfN_6.cjs"),t=require("./bpm-form-field-Bc6k4ZEO.cjs"),n=require("./FormRendererView-DNtNodNl.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-BPLwAJGv.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FormBuilderView-BPLwAJGv.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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"}
|