@byline/admin 2.5.2 → 2.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (260) hide show
  1. package/dist/fields/array/array-field.d.ts +14 -0
  2. package/dist/fields/array/array-field.js +177 -0
  3. package/dist/fields/array/array-field.module.js +11 -0
  4. package/dist/fields/array/array-field_module.css +32 -0
  5. package/dist/fields/blocks/blocks-field.d.ts +13 -0
  6. package/dist/fields/blocks/blocks-field.js +245 -0
  7. package/dist/fields/blocks/blocks-field.module.js +26 -0
  8. package/dist/fields/blocks/blocks-field_module.css +107 -0
  9. package/dist/fields/checkbox/checkbox-field.d.ts +16 -0
  10. package/dist/fields/checkbox/checkbox-field.js +28 -0
  11. package/dist/fields/checkbox/checkbox-field.module.js +6 -0
  12. package/dist/fields/checkbox/checkbox-field_module.css +4 -0
  13. package/dist/fields/column-formatter.d.ts +20 -0
  14. package/dist/fields/column-formatter.js +15 -0
  15. package/dist/fields/date-time-formatter.d.ts +16 -0
  16. package/dist/fields/date-time-formatter.js +8 -0
  17. package/dist/fields/datetime/datetime-field.d.ts +16 -0
  18. package/dist/fields/datetime/datetime-field.js +37 -0
  19. package/dist/fields/datetime/datetime-field.module.js +5 -0
  20. package/dist/fields/datetime/datetime-field_module.css +4 -0
  21. package/dist/fields/draggable-context-menu.d.ts +6 -0
  22. package/dist/fields/draggable-context-menu.js +85 -0
  23. package/dist/fields/draggable-context-menu.module.js +15 -0
  24. package/dist/fields/draggable-context-menu_module.css +91 -0
  25. package/dist/fields/field-helpers.d.ts +26 -0
  26. package/dist/fields/field-helpers.js +50 -0
  27. package/dist/fields/field-renderer.d.ts +37 -0
  28. package/dist/fields/field-renderer.js +206 -0
  29. package/dist/fields/field-renderer.module.js +8 -0
  30. package/dist/fields/field-renderer_module.css +11 -0
  31. package/dist/fields/field-services-context.d.ts +16 -0
  32. package/dist/fields/field-services-context.js +13 -0
  33. package/dist/fields/field-services-types.d.ts +63 -0
  34. package/dist/fields/field-services-types.js +1 -0
  35. package/dist/fields/file/file-field.d.ts +19 -0
  36. package/dist/fields/file/file-field.js +225 -0
  37. package/dist/fields/file/file-field.module.js +18 -0
  38. package/dist/fields/file/file-field_module.css +131 -0
  39. package/dist/fields/file/file-upload-field.d.ts +21 -0
  40. package/dist/fields/file/file-upload-field.js +130 -0
  41. package/dist/fields/file/file-upload-field.module.js +15 -0
  42. package/dist/fields/file/file-upload-field_module.css +74 -0
  43. package/dist/fields/group/group-field.d.ts +15 -0
  44. package/dist/fields/group/group-field.js +59 -0
  45. package/dist/fields/group/group-field.module.js +9 -0
  46. package/dist/fields/group/group-field_module.css +27 -0
  47. package/dist/fields/image/image-field.d.ts +19 -0
  48. package/dist/fields/image/image-field.js +241 -0
  49. package/dist/fields/image/image-field.module.js +22 -0
  50. package/dist/fields/image/image-field_module.css +121 -0
  51. package/dist/fields/image/image-upload-field.d.ts +21 -0
  52. package/dist/fields/image/image-upload-field.js +190 -0
  53. package/dist/fields/image/image-upload-field.module.js +19 -0
  54. package/dist/fields/image/image-upload-field_module.css +92 -0
  55. package/dist/fields/local-date-time.d.ts +27 -0
  56. package/dist/fields/local-date-time.js +49 -0
  57. package/dist/fields/locale-badge.d.ts +18 -0
  58. package/dist/fields/locale-badge.js +10 -0
  59. package/dist/fields/locale-badge.module.js +5 -0
  60. package/dist/fields/locale-badge_module.css +27 -0
  61. package/dist/fields/numerical/numerical-field.d.ts +18 -0
  62. package/dist/fields/numerical/numerical-field.js +74 -0
  63. package/dist/fields/relation/relation-display.d.ts +40 -0
  64. package/dist/fields/relation/relation-display.js +58 -0
  65. package/dist/fields/relation/relation-display.module.js +9 -0
  66. package/dist/fields/relation/relation-display_module.css +21 -0
  67. package/dist/fields/relation/relation-field.d.ts +18 -0
  68. package/dist/fields/relation/relation-field.js +138 -0
  69. package/dist/fields/relation/relation-field.module.js +13 -0
  70. package/dist/fields/relation/relation-field_module.css +62 -0
  71. package/dist/fields/relation/relation-picker.d.ts +49 -0
  72. package/dist/fields/relation/relation-picker.js +236 -0
  73. package/dist/fields/relation/relation-picker.module.js +26 -0
  74. package/dist/fields/relation/relation-picker_module.css +124 -0
  75. package/dist/fields/relation/relation-summary.d.ts +31 -0
  76. package/dist/fields/relation/relation-summary.js +50 -0
  77. package/dist/fields/relation/relation-summary.module.js +11 -0
  78. package/dist/fields/relation/relation-summary_module.css +37 -0
  79. package/dist/fields/select/select-field.d.ts +16 -0
  80. package/dist/fields/select/select-field.js +50 -0
  81. package/dist/fields/select/select-field.module.js +5 -0
  82. package/dist/fields/select/select-field_module.css +4 -0
  83. package/dist/fields/sortable-item.d.ts +15 -0
  84. package/dist/fields/sortable-item.js +81 -0
  85. package/dist/fields/sortable-item.module.js +22 -0
  86. package/dist/fields/sortable-item_module.css +124 -0
  87. package/dist/fields/text/text-field.d.ts +20 -0
  88. package/dist/fields/text/text-field.js +104 -0
  89. package/dist/fields/text/text-field.module.js +6 -0
  90. package/dist/fields/text/text-field_module.css +5 -0
  91. package/dist/fields/text-area/text-area-field.d.ts +20 -0
  92. package/dist/fields/text-area/text-area-field.js +105 -0
  93. package/dist/fields/text-area/text-area-field.module.js +6 -0
  94. package/dist/fields/text-area/text-area-field_module.css +5 -0
  95. package/dist/fields/use-field-change-handler.d.ts +23 -0
  96. package/dist/fields/use-field-change-handler.js +52 -0
  97. package/dist/forms/document-actions.d.ts +48 -0
  98. package/dist/forms/document-actions.js +475 -0
  99. package/dist/forms/document-actions.module.js +34 -0
  100. package/dist/forms/document-actions_module.css +118 -0
  101. package/dist/forms/form-context.d.ts +89 -0
  102. package/dist/forms/form-context.js +466 -0
  103. package/dist/forms/form-renderer.d.ts +98 -0
  104. package/dist/forms/form-renderer.js +597 -0
  105. package/dist/forms/form-renderer.module.js +46 -0
  106. package/dist/forms/form-renderer_module.css +245 -0
  107. package/dist/forms/navigation-guard.d.ts +54 -0
  108. package/dist/forms/navigation-guard.js +22 -0
  109. package/dist/forms/path-widget.d.ts +36 -0
  110. package/dist/forms/path-widget.js +116 -0
  111. package/dist/forms/path-widget.module.js +8 -0
  112. package/dist/forms/path-widget_module.css +29 -0
  113. package/dist/forms/upload-executor.d.ts +57 -0
  114. package/dist/forms/upload-executor.js +94 -0
  115. package/dist/lib/translate-validation-error.d.ts +36 -0
  116. package/dist/lib/translate-validation-error.js +11 -0
  117. package/dist/modules/admin-account/commands.d.ts +2 -1
  118. package/dist/modules/admin-account/commands.js +13 -2
  119. package/dist/modules/admin-account/components/change-password.js +45 -36
  120. package/dist/modules/admin-account/components/container.js +185 -134
  121. package/dist/modules/admin-account/components/preferences.d.ts +8 -0
  122. package/dist/modules/admin-account/components/preferences.js +152 -0
  123. package/dist/modules/admin-account/components/preferences.module.js +11 -0
  124. package/dist/modules/admin-account/components/preferences_module.css +41 -0
  125. package/dist/modules/admin-account/components/update.js +50 -31
  126. package/dist/modules/admin-account/index.d.ts +3 -3
  127. package/dist/modules/admin-account/index.js +2 -2
  128. package/dist/modules/admin-account/schemas.d.ts +4 -0
  129. package/dist/modules/admin-account/schemas.js +4 -1
  130. package/dist/modules/admin-account/service.d.ts +1 -0
  131. package/dist/modules/admin-account/service.js +8 -0
  132. package/dist/modules/admin-permissions/components/inspector.js +31 -41
  133. package/dist/modules/admin-roles/components/create.js +43 -26
  134. package/dist/modules/admin-roles/components/permissions.js +26 -35
  135. package/dist/modules/admin-roles/components/update.js +26 -16
  136. package/dist/modules/admin-users/components/create.js +60 -40
  137. package/dist/modules/admin-users/components/roles.js +9 -15
  138. package/dist/modules/admin-users/components/set-password.js +30 -31
  139. package/dist/modules/admin-users/components/update.js +58 -39
  140. package/dist/modules/admin-users/dto.js +1 -0
  141. package/dist/modules/admin-users/repository.d.ts +17 -0
  142. package/dist/modules/admin-users/schemas.d.ts +4 -0
  143. package/dist/modules/admin-users/schemas.js +6 -2
  144. package/dist/modules/auth/components/sign-in-form.js +10 -8
  145. package/dist/presentation/group.d.ts +27 -0
  146. package/dist/presentation/group.js +14 -0
  147. package/dist/presentation/group.module.js +6 -0
  148. package/dist/presentation/group_module.css +19 -0
  149. package/dist/presentation/row.d.ts +25 -0
  150. package/dist/presentation/row.js +8 -0
  151. package/dist/presentation/row.module.js +5 -0
  152. package/dist/presentation/row_module.css +18 -0
  153. package/dist/presentation/tabs.d.ts +25 -0
  154. package/dist/presentation/tabs.js +39 -0
  155. package/dist/presentation/tabs.module.js +10 -0
  156. package/dist/presentation/tabs_module.css +68 -0
  157. package/dist/react.d.ts +66 -0
  158. package/dist/react.js +36 -0
  159. package/dist/services/admin-services-types.d.ts +16 -0
  160. package/dist/widgets/diff-viewer/diff-modal.d.ts +22 -0
  161. package/dist/widgets/diff-viewer/diff-modal.js +149 -0
  162. package/dist/widgets/diff-viewer/diff-modal.module.js +14 -0
  163. package/dist/widgets/diff-viewer/diff-modal_module.css +56 -0
  164. package/dist/widgets/status-badge/status-badge.d.ts +25 -0
  165. package/dist/widgets/status-badge/status-badge.js +37 -0
  166. package/dist/widgets/status-badge/status-badge.module.js +7 -0
  167. package/dist/widgets/status-badge/status-badge_module.css +20 -0
  168. package/package.json +14 -4
  169. package/src/fields/array/array-field.module.css +48 -0
  170. package/src/fields/array/array-field.tsx +267 -0
  171. package/src/fields/blocks/blocks-field.module.css +148 -0
  172. package/src/fields/blocks/blocks-field.tsx +323 -0
  173. package/src/fields/checkbox/checkbox-field.module.css +4 -0
  174. package/src/fields/checkbox/checkbox-field.tsx +54 -0
  175. package/src/fields/column-formatter.tsx +31 -0
  176. package/src/fields/date-time-formatter.tsx +22 -0
  177. package/src/fields/datetime/datetime-field.module.css +13 -0
  178. package/src/fields/datetime/datetime-field.tsx +54 -0
  179. package/src/fields/draggable-context-menu.module.css +127 -0
  180. package/src/fields/draggable-context-menu.tsx +87 -0
  181. package/src/fields/field-helpers.ts +69 -0
  182. package/src/fields/field-renderer.module.css +22 -0
  183. package/src/fields/field-renderer.tsx +288 -0
  184. package/src/fields/field-services-context.tsx +35 -0
  185. package/src/fields/field-services-types.ts +68 -0
  186. package/src/fields/file/file-field.module.css +153 -0
  187. package/src/fields/file/file-field.tsx +286 -0
  188. package/src/fields/file/file-upload-field.module.css +101 -0
  189. package/src/fields/file/file-upload-field.tsx +187 -0
  190. package/src/fields/group/group-field.module.css +43 -0
  191. package/src/fields/group/group-field.tsx +84 -0
  192. package/src/fields/image/image-field.module.css +155 -0
  193. package/src/fields/image/image-field.tsx +306 -0
  194. package/src/fields/image/image-upload-field.module.css +123 -0
  195. package/src/fields/image/image-upload-field.tsx +276 -0
  196. package/src/fields/local-date-time.tsx +88 -0
  197. package/src/fields/locale-badge.module.css +37 -0
  198. package/src/fields/locale-badge.tsx +32 -0
  199. package/src/fields/numerical/numerical-field.tsx +114 -0
  200. package/src/fields/relation/relation-display.module.css +36 -0
  201. package/src/fields/relation/relation-display.tsx +130 -0
  202. package/src/fields/relation/relation-field.module.css +83 -0
  203. package/src/fields/relation/relation-field.tsx +211 -0
  204. package/src/fields/relation/relation-picker.module.css +168 -0
  205. package/src/fields/relation/relation-picker.tsx +326 -0
  206. package/src/fields/relation/relation-summary.module.css +55 -0
  207. package/src/fields/relation/relation-summary.tsx +123 -0
  208. package/src/fields/select/select-field.module.css +13 -0
  209. package/src/fields/select/select-field.tsx +61 -0
  210. package/src/fields/sortable-item.module.css +167 -0
  211. package/src/fields/sortable-item.tsx +106 -0
  212. package/src/fields/text/text-field.module.css +13 -0
  213. package/src/fields/text/text-field.tsx +146 -0
  214. package/src/fields/text-area/text-area-field.module.css +13 -0
  215. package/src/fields/text-area/text-area-field.tsx +147 -0
  216. package/src/fields/use-field-change-handler.ts +112 -0
  217. package/src/forms/document-actions.module.css +160 -0
  218. package/src/forms/document-actions.tsx +482 -0
  219. package/src/forms/form-context.tsx +704 -0
  220. package/src/forms/form-renderer.module.css +321 -0
  221. package/src/forms/form-renderer.tsx +891 -0
  222. package/src/forms/navigation-guard.tsx +98 -0
  223. package/src/forms/path-widget.module.css +41 -0
  224. package/src/forms/path-widget.test.tsx +217 -0
  225. package/src/forms/path-widget.tsx +183 -0
  226. package/src/forms/upload-executor.ts +192 -0
  227. package/src/lib/translate-validation-error.ts +56 -0
  228. package/src/modules/admin-account/commands.ts +13 -0
  229. package/src/modules/admin-account/components/change-password.tsx +46 -31
  230. package/src/modules/admin-account/components/container.tsx +83 -38
  231. package/src/modules/admin-account/components/preferences.module.css +60 -0
  232. package/src/modules/admin-account/components/preferences.tsx +203 -0
  233. package/src/modules/admin-account/components/update.tsx +53 -27
  234. package/src/modules/admin-account/index.ts +3 -0
  235. package/src/modules/admin-account/schemas.ts +13 -0
  236. package/src/modules/admin-account/service.ts +12 -0
  237. package/src/modules/admin-permissions/components/inspector.tsx +22 -14
  238. package/src/modules/admin-roles/components/create.tsx +51 -23
  239. package/src/modules/admin-roles/components/permissions.tsx +25 -21
  240. package/src/modules/admin-roles/components/update.tsx +37 -19
  241. package/src/modules/admin-users/components/create.tsx +63 -34
  242. package/src/modules/admin-users/components/roles.tsx +9 -8
  243. package/src/modules/admin-users/components/set-password.tsx +34 -28
  244. package/src/modules/admin-users/components/update.tsx +58 -36
  245. package/src/modules/admin-users/dto.ts +1 -0
  246. package/src/modules/admin-users/repository.ts +17 -0
  247. package/src/modules/admin-users/schemas.ts +12 -0
  248. package/src/modules/auth/components/sign-in-form.tsx +14 -8
  249. package/src/presentation/group.module.css +41 -0
  250. package/src/presentation/group.tsx +40 -0
  251. package/src/presentation/row.module.css +32 -0
  252. package/src/presentation/row.tsx +33 -0
  253. package/src/presentation/tabs.module.css +107 -0
  254. package/src/presentation/tabs.tsx +84 -0
  255. package/src/react.ts +84 -0
  256. package/src/services/admin-services-types.ts +18 -0
  257. package/src/widgets/diff-viewer/diff-modal.module.css +79 -0
  258. package/src/widgets/diff-viewer/diff-modal.tsx +186 -0
  259. package/src/widgets/status-badge/status-badge.module.css +31 -0
  260. package/src/widgets/status-badge/status-badge.tsx +71 -0
@@ -0,0 +1,597 @@
1
+ "use client";
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
4
+ import { useTranslation } from "@byline/i18n/react";
5
+ import { Alert, Button, ComboButton, Modal } from "@byline/ui/react";
6
+ import classnames from "classnames";
7
+ import { FieldRenderer } from "../fields/field-renderer.js";
8
+ import { useBylineFieldServices } from "../fields/field-services-context.js";
9
+ import { LocalDateTime } from "../fields/local-date-time.js";
10
+ import { AdminGroup } from "../presentation/group.js";
11
+ import { AdminRow } from "../presentation/row.js";
12
+ import { AdminTabs } from "../presentation/tabs.js";
13
+ import { DocumentActions } from "./document-actions.js";
14
+ import { FormProvider, useFieldValue, useFormContext } from "./form-context.js";
15
+ import form_renderer_module from "./form-renderer.module.js";
16
+ import { useNavigationGuardAdapter } from "./navigation-guard.js";
17
+ import { PathWidget } from "./path-widget.js";
18
+ import { executeUploadsWithProgress } from "./upload-executor.js";
19
+ const FormStatusDisplay = ({ initialData, workflowStatuses, publishedVersion, onUnpublish })=>{
20
+ const { t } = useTranslation('byline-admin');
21
+ const statusCode = initialData?.status;
22
+ const statusLabel = workflowStatuses?.find((s)=>s.name === statusCode)?.label ?? statusCode;
23
+ const showStatusCell = (workflowStatuses?.length ?? 0) > 1;
24
+ return /*#__PURE__*/ jsxs("div", {
25
+ className: classnames('byline-form-status', form_renderer_module.status),
26
+ children: [
27
+ /*#__PURE__*/ jsxs("div", {
28
+ className: classnames('byline-form-status-meta', form_renderer_module["status-meta"]),
29
+ children: [
30
+ showStatusCell && /*#__PURE__*/ jsxs("div", {
31
+ className: classnames('byline-form-status-cell', form_renderer_module["status-cell"]),
32
+ children: [
33
+ /*#__PURE__*/ jsx("span", {
34
+ className: classnames('byline-form-status-muted', form_renderer_module["status-muted"]),
35
+ children: t('forms.status.label')
36
+ }),
37
+ /*#__PURE__*/ jsx("span", {
38
+ className: classnames('byline-form-status-trunc', form_renderer_module["status-trunc"]),
39
+ children: statusLabel
40
+ })
41
+ ]
42
+ }),
43
+ initialData?.updatedAt != null && /*#__PURE__*/ jsxs("div", {
44
+ className: classnames('byline-form-status-cell', form_renderer_module["status-cell"]),
45
+ children: [
46
+ /*#__PURE__*/ jsx("span", {
47
+ className: classnames('byline-form-status-muted', form_renderer_module["status-muted"]),
48
+ children: t('forms.status.lastModified')
49
+ }),
50
+ /*#__PURE__*/ jsx("span", {
51
+ className: classnames('byline-form-status-trunc', form_renderer_module["status-trunc"]),
52
+ children: /*#__PURE__*/ jsx(LocalDateTime, {
53
+ value: initialData.updatedAt
54
+ })
55
+ })
56
+ ]
57
+ }),
58
+ initialData?.createdAt != null && /*#__PURE__*/ jsxs("div", {
59
+ className: classnames('byline-form-status-cell', form_renderer_module["status-cell"]),
60
+ children: [
61
+ /*#__PURE__*/ jsx("span", {
62
+ className: classnames('byline-form-status-muted', form_renderer_module["status-muted"]),
63
+ children: t('forms.status.created')
64
+ }),
65
+ /*#__PURE__*/ jsx("span", {
66
+ className: classnames('byline-form-status-trunc', form_renderer_module["status-trunc"]),
67
+ children: /*#__PURE__*/ jsx(LocalDateTime, {
68
+ value: initialData.createdAt
69
+ })
70
+ })
71
+ ]
72
+ })
73
+ ]
74
+ }),
75
+ null != publishedVersion && /*#__PURE__*/ jsxs("div", {
76
+ className: classnames('byline-form-status-published', form_renderer_module["status-published"]),
77
+ children: [
78
+ /*#__PURE__*/ jsxs("span", {
79
+ className: classnames('byline-form-status-muted', form_renderer_module["status-muted"]),
80
+ children: [
81
+ t('forms.status.publishedLive'),
82
+ ' ',
83
+ publishedVersion.updatedAt ? /*#__PURE__*/ jsx("span", {
84
+ children: t('forms.status.publishedOn', {
85
+ date: new Date(publishedVersion.updatedAt)
86
+ })
87
+ }) : ''
88
+ ]
89
+ }),
90
+ onUnpublish && /*#__PURE__*/ jsxs(Fragment, {
91
+ children: [
92
+ ' ',
93
+ /*#__PURE__*/ jsx("button", {
94
+ type: "button",
95
+ onClick: onUnpublish,
96
+ className: classnames('byline-form-status-unpublish', form_renderer_module["status-unpublish"]),
97
+ children: t('common.actions.unpublish')
98
+ })
99
+ ]
100
+ })
101
+ ]
102
+ })
103
+ ]
104
+ });
105
+ };
106
+ function computeStatusTransitions(currentStatus, workflowStatuses, nextStatus) {
107
+ if (!workflowStatuses || 0 === workflowStatuses.length || !currentStatus) return {
108
+ primaryStatus: nextStatus,
109
+ secondaryStatuses: [],
110
+ isTerminal: false
111
+ };
112
+ if (workflowStatuses.length <= 1) return {
113
+ primaryStatus: void 0,
114
+ secondaryStatuses: [],
115
+ isTerminal: false
116
+ };
117
+ const currentIndex = workflowStatuses.findIndex((s)=>s.name === currentStatus);
118
+ if (-1 === currentIndex) return {
119
+ primaryStatus: nextStatus,
120
+ secondaryStatuses: [],
121
+ isTerminal: false
122
+ };
123
+ const isAtEnd = currentIndex === workflowStatuses.length - 1;
124
+ const isAtStart = 0 === currentIndex;
125
+ const availableTargets = [];
126
+ if (!isAtStart && workflowStatuses[0]) availableTargets.push(workflowStatuses[0]);
127
+ const prev = workflowStatuses[currentIndex - 1];
128
+ if (currentIndex > 1 && prev) availableTargets.push(prev);
129
+ const next = workflowStatuses[currentIndex + 1];
130
+ if (!isAtEnd && next) availableTargets.push(next);
131
+ if (isAtEnd) return {
132
+ primaryStatus: workflowStatuses[currentIndex],
133
+ secondaryStatuses: availableTargets,
134
+ isTerminal: true
135
+ };
136
+ return {
137
+ primaryStatus: nextStatus,
138
+ secondaryStatuses: availableTargets.filter((s)=>s.name !== nextStatus?.name),
139
+ isTerminal: false
140
+ };
141
+ }
142
+ const FormContent = ({ mode, fields, onSubmit, onCancel, onStatusChange, onUnpublish, onDelete, onDuplicate, onCopyToLocale, contentLocales, nextStatus, workflowStatuses, publishedVersion, initialData, adminConfig, useAsTitle, useAsPath, headingLabel, headerSlot, collectionPath, initialLocale, onLocaleChange, defaultLocale = 'en', useNavigationGuard: useNavigationGuardProp, restoreWarnings, _activeTabBySet, _onTabChange })=>{
143
+ const { getFieldValues, runFieldHooks, validateForm, errors: initialErrors, hasChanges: hasChangesFn, resetHasChanges, getPatches, getSystemPath, subscribeErrors, subscribeMeta, setFieldValue, setFieldError, getPendingUploads, clearPendingUploads, setFieldUploading } = useFormContext();
144
+ const { t } = useTranslation('byline-admin');
145
+ const [errors, setErrors] = useState(initialErrors);
146
+ const [hasChanges, setHasChanges] = useState(hasChangesFn());
147
+ const [statusBusy, setStatusBusy] = useState(false);
148
+ const [isUploading, setIsUploading] = useState(false);
149
+ const [contentLocale, setContentLocale] = useState(initialLocale ?? defaultLocale);
150
+ const { uploadField } = useBylineFieldServices();
151
+ useEffect(()=>{
152
+ if (initialLocale) setContentLocale(initialLocale);
153
+ }, [
154
+ initialLocale
155
+ ]);
156
+ const fieldByName = useMemo(()=>{
157
+ const map = new Map();
158
+ for (const field of fields)if ('name' in field) map.set(field.name, field);
159
+ return map;
160
+ }, [
161
+ fields
162
+ ]);
163
+ const tabSetByName = useMemo(()=>{
164
+ const map = new Map();
165
+ for (const set of adminConfig?.tabSets ?? [])map.set(set.name, set);
166
+ return map;
167
+ }, [
168
+ adminConfig
169
+ ]);
170
+ const rowByName = useMemo(()=>{
171
+ const map = new Map();
172
+ for (const row of adminConfig?.rows ?? [])map.set(row.name, row);
173
+ return map;
174
+ }, [
175
+ adminConfig
176
+ ]);
177
+ const groupByName = useMemo(()=>{
178
+ const map = new Map();
179
+ for (const group of adminConfig?.groups ?? [])map.set(group.name, group);
180
+ return map;
181
+ }, [
182
+ adminConfig
183
+ ]);
184
+ const layout = useMemo(()=>{
185
+ if (adminConfig?.layout) return adminConfig.layout;
186
+ return {
187
+ main: fields.filter((f)=>'name' in f).map((f)=>f.name)
188
+ };
189
+ }, [
190
+ adminConfig,
191
+ fields
192
+ ]);
193
+ const fieldToTabPath = useMemo(()=>{
194
+ const map = new Map();
195
+ const visit = (names, tabSetName, tabName, seen)=>{
196
+ for (const name of names)if (fieldByName.has(name)) map.set(name, {
197
+ tabSetName,
198
+ tabName
199
+ });
200
+ else if (seen.has(name)) ;
201
+ else if (rowByName.has(name)) {
202
+ const row = rowByName.get(name);
203
+ const next = new Set(seen).add(name);
204
+ visit(row.fields, tabSetName, tabName, next);
205
+ } else if (groupByName.has(name)) {
206
+ const group = groupByName.get(name);
207
+ const next = new Set(seen).add(name);
208
+ visit(group.fields, tabSetName, tabName, next);
209
+ }
210
+ };
211
+ for (const set of adminConfig?.tabSets ?? [])for (const tab of set.tabs)visit(tab.fields, set.name, tab.name, new Set());
212
+ return map;
213
+ }, [
214
+ adminConfig,
215
+ fieldByName,
216
+ rowByName,
217
+ groupByName
218
+ ]);
219
+ const tabSets = adminConfig?.tabSets ?? [];
220
+ const initialActiveTabBySet = useMemo(()=>{
221
+ const result = {};
222
+ for (const set of tabSets){
223
+ const saved = _activeTabBySet?.[set.name];
224
+ if (saved && set.tabs.some((t)=>t.name === saved)) result[set.name] = saved;
225
+ else result[set.name] = set.tabs[0]?.name ?? '';
226
+ }
227
+ return result;
228
+ }, [
229
+ tabSets,
230
+ _activeTabBySet
231
+ ]);
232
+ const [activeTabBySet, setActiveTabBySet] = useState(initialActiveTabBySet);
233
+ const handleTabChange = useCallback((tabSetName, tabName)=>{
234
+ setActiveTabBySet((prev)=>({
235
+ ...prev,
236
+ [tabSetName]: tabName
237
+ }));
238
+ _onTabChange?.(tabSetName, tabName);
239
+ }, [
240
+ _onTabChange
241
+ ]);
242
+ const [formData, setFormData] = useState(()=>getFieldValues());
243
+ const liveTitle = useFieldValue(useAsTitle ?? '');
244
+ const heading = liveTitle || (headingLabel ? 'create' === mode ? t('forms.heading.createLabel', {
245
+ label: headingLabel
246
+ }) : t('forms.heading.editLabel', {
247
+ label: headingLabel
248
+ }) : 'create' === mode ? t('forms.heading.create') : t('forms.heading.edit'));
249
+ const guardFromContext = useNavigationGuardAdapter();
250
+ const useGuard = useNavigationGuardProp ?? guardFromContext;
251
+ const guard = useGuard(hasChanges);
252
+ const currentStatus = initialData?.status;
253
+ const { primaryStatus, secondaryStatuses, isTerminal } = computeStatusTransitions(currentStatus, workflowStatuses, nextStatus);
254
+ useEffect(()=>subscribeErrors((newErrors)=>setErrors(newErrors)), [
255
+ subscribeErrors
256
+ ]);
257
+ useEffect(()=>subscribeMeta(()=>setHasChanges(hasChangesFn())), [
258
+ subscribeMeta,
259
+ hasChangesFn
260
+ ]);
261
+ useEffect(()=>subscribeMeta(()=>setFormData(getFieldValues())), [
262
+ subscribeMeta,
263
+ getFieldValues
264
+ ]);
265
+ const handleCancel = ()=>{
266
+ if (onCancel && 'function' == typeof onCancel) onCancel();
267
+ };
268
+ const handleSubmit = (e)=>{
269
+ e.preventDefault();
270
+ (async ()=>{
271
+ const hookErrors = await runFieldHooks(fields);
272
+ const formErrors = validateForm(fields);
273
+ const allErrors = [
274
+ ...hookErrors,
275
+ ...formErrors
276
+ ];
277
+ if (allErrors.length > 0) return void console.error('Form validation failed:', allErrors);
278
+ const pendingUploads = getPendingUploads();
279
+ if (pendingUploads.size > 0) {
280
+ setIsUploading(true);
281
+ try {
282
+ const uploadResult = await executeUploadsWithProgress(pendingUploads, uploadField, ({ fieldPath, status })=>{
283
+ setFieldUploading(fieldPath, 'uploading' === status);
284
+ });
285
+ if (!uploadResult.allSucceeded) {
286
+ for (const [fieldPath, errorMessage] of uploadResult.errors.entries())setFieldError(fieldPath, t('forms.uploadFailedFieldError', {
287
+ message: errorMessage
288
+ }));
289
+ console.error('One or more uploads failed:', uploadResult.errors);
290
+ setIsUploading(false);
291
+ return;
292
+ }
293
+ for (const [fieldPath, storedFile] of uploadResult.successful.entries())setFieldValue(fieldPath, storedFile);
294
+ clearPendingUploads();
295
+ } catch (err) {
296
+ console.error('Upload execution error:', err);
297
+ setIsUploading(false);
298
+ return;
299
+ }
300
+ setIsUploading(false);
301
+ }
302
+ const data = getFieldValues();
303
+ const patches = getPatches();
304
+ const systemPath = getSystemPath();
305
+ if (onSubmit && 'function' == typeof onSubmit) {
306
+ onSubmit({
307
+ data,
308
+ patches,
309
+ systemPath
310
+ });
311
+ resetHasChanges();
312
+ }
313
+ })();
314
+ };
315
+ const tabErrorCountsBySet = useMemo(()=>{
316
+ const result = {};
317
+ for (const err of errors){
318
+ const path = fieldToTabPath.get(err.field);
319
+ if (path) {
320
+ result[path.tabSetName] ??= {};
321
+ result[path.tabSetName][path.tabName] = (result[path.tabSetName]?.[path.tabName] ?? 0) + 1;
322
+ }
323
+ }
324
+ return result;
325
+ }, [
326
+ errors,
327
+ fieldToTabPath
328
+ ]);
329
+ const renderField = (fieldName)=>{
330
+ const field = fieldByName.get(fieldName);
331
+ if (!field) return null;
332
+ return /*#__PURE__*/ jsx(FieldRenderer, {
333
+ field: field,
334
+ defaultValue: initialData?.fields?.[field.name],
335
+ collectionPath: collectionPath,
336
+ contentLocale: contentLocale,
337
+ components: adminConfig?.fields?.[field.name]?.components,
338
+ editor: adminConfig?.fields?.[field.name]?.editor
339
+ }, field.name);
340
+ };
341
+ const renderItem = (name)=>{
342
+ const tabSet = tabSetByName.get(name);
343
+ if (tabSet) return renderTabSet(tabSet);
344
+ const group = groupByName.get(name);
345
+ if (group) return renderGroup(group);
346
+ const row = rowByName.get(name);
347
+ if (row) return renderRow(row);
348
+ return renderField(name);
349
+ };
350
+ const renderRow = (row)=>/*#__PURE__*/ jsx(AdminRow, {
351
+ children: row.fields.map((name)=>renderField(name))
352
+ }, `row:${row.name}`);
353
+ const renderGroup = (group)=>/*#__PURE__*/ jsx(AdminGroup, {
354
+ label: group.label,
355
+ children: group.fields.map((name)=>renderItem(name))
356
+ }, `group:${group.name}`);
357
+ const renderTabSet = (set)=>{
358
+ const visibleTabs = set.tabs.filter((tab)=>!tab.condition || tab.condition(formData));
359
+ const requested = activeTabBySet[set.name] ?? '';
360
+ const resolvedActive = visibleTabs.length > 0 && !visibleTabs.some((t)=>t.name === requested) ? visibleTabs[0]?.name ?? requested : requested;
361
+ const activeTab = visibleTabs.find((t)=>t.name === resolvedActive);
362
+ return /*#__PURE__*/ jsxs("div", {
363
+ className: classnames('byline-form-tabset', form_renderer_module.tabset),
364
+ children: [
365
+ visibleTabs.length > 0 && /*#__PURE__*/ jsx(AdminTabs, {
366
+ tabs: visibleTabs,
367
+ activeTab: resolvedActive,
368
+ onChange: (tabName)=>handleTabChange(set.name, tabName),
369
+ errorCounts: tabErrorCountsBySet[set.name],
370
+ className: classnames('byline-form-tabset-tabs', form_renderer_module["tabset-tabs"])
371
+ }),
372
+ activeTab && /*#__PURE__*/ jsx("div", {
373
+ className: classnames('byline-form-tabset-fields', form_renderer_module["tabset-fields"]),
374
+ children: activeTab.fields.map((name)=>renderItem(name))
375
+ })
376
+ ]
377
+ }, `tabset:${set.name}`);
378
+ };
379
+ return /*#__PURE__*/ jsxs("form", {
380
+ noValidate: true,
381
+ onSubmit: handleSubmit,
382
+ className: classnames('byline-form', form_renderer_module.form),
383
+ children: [
384
+ /*#__PURE__*/ jsxs("div", {
385
+ className: classnames('byline-form-heading-row', form_renderer_module["heading-row"]),
386
+ children: [
387
+ /*#__PURE__*/ jsx("h1", {
388
+ className: classnames('byline-form-heading', form_renderer_module.heading),
389
+ children: heading
390
+ }),
391
+ headerSlot
392
+ ]
393
+ }),
394
+ /*#__PURE__*/ jsxs("div", {
395
+ className: classnames('byline-form-status-bar', form_renderer_module["status-bar"]),
396
+ children: [
397
+ /*#__PURE__*/ jsx(FormStatusDisplay, {
398
+ initialData: initialData,
399
+ workflowStatuses: workflowStatuses,
400
+ publishedVersion: publishedVersion,
401
+ onUnpublish: onUnpublish
402
+ }),
403
+ /*#__PURE__*/ jsxs("div", {
404
+ className: classnames('byline-form-actions', form_renderer_module.actions),
405
+ children: [
406
+ /*#__PURE__*/ jsx(Button, {
407
+ className: classnames('byline-form-actions-button', form_renderer_module["actions-button"]),
408
+ size: "sm",
409
+ intent: "noeffect",
410
+ type: "button",
411
+ onClick: handleCancel,
412
+ children: false === hasChanges ? t('common.actions.close') : t('common.actions.cancel')
413
+ }),
414
+ /*#__PURE__*/ jsx(Button, {
415
+ className: classnames('byline-form-actions-button', form_renderer_module["actions-button"]),
416
+ size: "sm",
417
+ type: "submit",
418
+ disabled: false === hasChanges || isUploading,
419
+ children: isUploading ? t('forms.actions.uploading') : t('common.actions.save')
420
+ }),
421
+ primaryStatus && onStatusChange && /*#__PURE__*/ jsx("div", {
422
+ className: classnames('byline-form-actions-status-wrap', form_renderer_module["actions-status-wrap"]),
423
+ children: /*#__PURE__*/ jsx(ComboButton, {
424
+ buttonClassName: classnames('byline-form-actions-combo-button', form_renderer_module["actions-combo-button"]),
425
+ triggerClassName: classnames('byline-form-actions-combo-trigger', form_renderer_module["actions-combo-trigger"]),
426
+ options: secondaryStatuses.map((s)=>({
427
+ label: isTerminal ? t('forms.actions.revertTo', {
428
+ label: s.label ?? s.name
429
+ }) : s.verb ?? s.label ?? s.name,
430
+ value: s.name
431
+ })),
432
+ sideOffset: 5,
433
+ size: "sm",
434
+ type: "button",
435
+ intent: isTerminal ? 'info' : 'success',
436
+ disabled: statusBusy,
437
+ onOptionSelect: async (value)=>{
438
+ setStatusBusy(true);
439
+ try {
440
+ await onStatusChange(value);
441
+ } finally{
442
+ setStatusBusy(false);
443
+ }
444
+ },
445
+ onButtonClick: isTerminal ? void 0 : async ()=>{
446
+ setStatusBusy(true);
447
+ try {
448
+ await onStatusChange(primaryStatus.name);
449
+ } finally{
450
+ setStatusBusy(false);
451
+ }
452
+ },
453
+ children: statusBusy ? '...' : isTerminal ? primaryStatus.label ?? primaryStatus.name : primaryStatus.verb ?? primaryStatus.label ?? primaryStatus.name
454
+ })
455
+ }),
456
+ /*#__PURE__*/ jsx(DocumentActions, {
457
+ publishedVersion: publishedVersion,
458
+ onUnpublish: onUnpublish,
459
+ onDelete: onDelete,
460
+ onDuplicate: onDuplicate,
461
+ sourceTitle: null != useAsTitle && null != initialData ? initialData[useAsTitle] : null,
462
+ onCopyToLocale: onCopyToLocale,
463
+ sourceLocale: contentLocale,
464
+ contentLocales: contentLocales
465
+ })
466
+ ]
467
+ })
468
+ ]
469
+ }),
470
+ restoreWarnings && restoreWarnings.length > 0 && /*#__PURE__*/ jsxs(Alert, {
471
+ className: "m-0 mt-4",
472
+ intent: "warning",
473
+ icon: true,
474
+ close: false,
475
+ title: t('forms.restoreWarnings.title'),
476
+ children: [
477
+ /*#__PURE__*/ jsx("p", {
478
+ children: t('forms.restoreWarnings.body', {
479
+ count: restoreWarnings.length
480
+ })
481
+ }),
482
+ /*#__PURE__*/ jsx("ul", {
483
+ children: restoreWarnings.map((w)=>/*#__PURE__*/ jsx("li", {
484
+ children: w
485
+ }, w))
486
+ })
487
+ ]
488
+ }),
489
+ /*#__PURE__*/ jsxs("div", {
490
+ className: classnames('byline-form-layout', form_renderer_module.layout),
491
+ children: [
492
+ /*#__PURE__*/ jsx("div", {
493
+ className: classnames('byline-form-content', form_renderer_module.content),
494
+ children: layout.main.map((name)=>renderItem(name))
495
+ }),
496
+ /*#__PURE__*/ jsxs("div", {
497
+ className: classnames('byline-form-sidebar', form_renderer_module.sidebar),
498
+ children: [
499
+ (useAsPath || 'string' == typeof initialData?.path && initialData.path.length > 0) && /*#__PURE__*/ jsx(PathWidget, {
500
+ useAsPath: useAsPath,
501
+ collectionPath: collectionPath ?? '',
502
+ defaultLocale: defaultLocale,
503
+ activeLocale: contentLocale,
504
+ mode: mode
505
+ }),
506
+ (layout.sidebar ?? []).map((name)=>renderItem(name))
507
+ ]
508
+ })
509
+ ]
510
+ }),
511
+ guard.isBlocked && /*#__PURE__*/ jsx(Modal, {
512
+ isOpen: true,
513
+ closeOnOverlayClick: false,
514
+ onDismiss: guard.stay,
515
+ children: /*#__PURE__*/ jsxs(Modal.Container, {
516
+ style: {
517
+ maxWidth: '460px'
518
+ },
519
+ children: [
520
+ /*#__PURE__*/ jsx(Modal.Header, {
521
+ className: classnames('byline-form-guard-modal-head', form_renderer_module["guard-modal-head"]),
522
+ children: /*#__PURE__*/ jsx("h3", {
523
+ className: classnames('byline-form-guard-modal-title', form_renderer_module["guard-modal-title"]),
524
+ children: t('forms.navigationGuard.title')
525
+ })
526
+ }),
527
+ /*#__PURE__*/ jsx(Modal.Content, {
528
+ children: /*#__PURE__*/ jsx("p", {
529
+ className: classnames('byline-form-guard-modal-text', form_renderer_module["guard-modal-text"]),
530
+ children: t('forms.navigationGuard.message')
531
+ })
532
+ }),
533
+ /*#__PURE__*/ jsxs(Modal.Actions, {
534
+ children: [
535
+ /*#__PURE__*/ jsx(Button, {
536
+ size: "sm",
537
+ intent: "noeffect",
538
+ type: "button",
539
+ onClick: guard.stay,
540
+ children: t('forms.navigationGuard.stayButton')
541
+ }),
542
+ /*#__PURE__*/ jsx(Button, {
543
+ size: "sm",
544
+ intent: "danger",
545
+ type: "button",
546
+ onClick: guard.proceed,
547
+ children: t('forms.navigationGuard.leaveButton')
548
+ })
549
+ ]
550
+ })
551
+ ]
552
+ })
553
+ })
554
+ ]
555
+ });
556
+ };
557
+ const FormRenderer = ({ mode, fields, onSubmit, onCancel, onStatusChange, onUnpublish, onDelete, onDuplicate, onCopyToLocale, contentLocales, nextStatus, workflowStatuses, publishedVersion, initialData, adminConfig, useAsTitle, useAsPath, headingLabel, headerSlot, collectionPath, initialLocale, onLocaleChange, defaultLocale, useNavigationGuard, restoreWarnings })=>{
558
+ const savedTabsRef = useRef({});
559
+ return /*#__PURE__*/ jsx(FormProvider, {
560
+ initialData: initialData,
561
+ children: /*#__PURE__*/ jsx(FormContent, {
562
+ mode: mode,
563
+ fields: fields,
564
+ onSubmit: onSubmit,
565
+ onCancel: onCancel,
566
+ onStatusChange: onStatusChange,
567
+ onUnpublish: onUnpublish,
568
+ onDelete: onDelete,
569
+ onDuplicate: onDuplicate,
570
+ onCopyToLocale: onCopyToLocale,
571
+ contentLocales: contentLocales,
572
+ nextStatus: nextStatus,
573
+ workflowStatuses: workflowStatuses,
574
+ publishedVersion: publishedVersion,
575
+ initialData: initialData,
576
+ adminConfig: adminConfig,
577
+ useAsTitle: useAsTitle,
578
+ useAsPath: useAsPath,
579
+ headingLabel: headingLabel,
580
+ headerSlot: headerSlot,
581
+ collectionPath: collectionPath,
582
+ initialLocale: initialLocale,
583
+ onLocaleChange: onLocaleChange,
584
+ defaultLocale: defaultLocale,
585
+ useNavigationGuard: useNavigationGuard,
586
+ restoreWarnings: restoreWarnings,
587
+ _activeTabBySet: savedTabsRef.current,
588
+ _onTabChange: (tabSetName, tabName)=>{
589
+ savedTabsRef.current = {
590
+ ...savedTabsRef.current,
591
+ [tabSetName]: tabName
592
+ };
593
+ }
594
+ })
595
+ }, `${initialLocale ?? 'default'}-${initialData?.versionId ?? ''}`);
596
+ };
597
+ export { FormRenderer };
@@ -0,0 +1,46 @@
1
+ import "./form-renderer_module.css";
2
+ const form_renderer_module = {
3
+ form: "form-MVxxVb",
4
+ "heading-row": "heading-row-qw_UYh",
5
+ headingRow: "heading-row-qw_UYh",
6
+ heading: "heading-wnLlb_",
7
+ "status-bar": "status-bar-kQCXLT",
8
+ statusBar: "status-bar-kQCXLT",
9
+ status: "status-XbhkJR",
10
+ "status-meta": "status-meta-gppNXX",
11
+ statusMeta: "status-meta-gppNXX",
12
+ "status-cell": "status-cell-Tr3QHl",
13
+ statusCell: "status-cell-Tr3QHl",
14
+ "status-muted": "status-muted-vHn34O",
15
+ statusMuted: "status-muted-vHn34O",
16
+ "status-trunc": "status-trunc-jGiHWf",
17
+ statusTrunc: "status-trunc-jGiHWf",
18
+ "status-published": "status-published-hqosWb",
19
+ statusPublished: "status-published-hqosWb",
20
+ "status-unpublish": "status-unpublish-DiCNI0",
21
+ statusUnpublish: "status-unpublish-DiCNI0",
22
+ actions: "actions-AZBIdR",
23
+ "actions-button": "actions-button-VIwbST",
24
+ actionsButton: "actions-button-VIwbST",
25
+ "actions-status-wrap": "actions-status-wrap-hSvlps",
26
+ actionsStatusWrap: "actions-status-wrap-hSvlps",
27
+ "actions-combo-button": "actions-combo-button-XvqHCC",
28
+ actionsComboButton: "actions-combo-button-XvqHCC",
29
+ "actions-combo-trigger": "actions-combo-trigger-bmXUzc",
30
+ actionsComboTrigger: "actions-combo-trigger-bmXUzc",
31
+ layout: "layout-WTbLYr",
32
+ content: "content-_P5cdJ",
33
+ sidebar: "sidebar-WsxX88",
34
+ tabset: "tabset-xfaMkP",
35
+ "tabset-tabs": "tabset-tabs-jZpqd_",
36
+ tabsetTabs: "tabset-tabs-jZpqd_",
37
+ "tabset-fields": "tabset-fields-JJefdw",
38
+ tabsetFields: "tabset-fields-JJefdw",
39
+ "guard-modal-head": "guard-modal-head-r2TApi",
40
+ guardModalHead: "guard-modal-head-r2TApi",
41
+ "guard-modal-title": "guard-modal-title-p9dFJ9",
42
+ guardModalTitle: "guard-modal-title-p9dFJ9",
43
+ "guard-modal-text": "guard-modal-text-uW56HS",
44
+ guardModalText: "guard-modal-text-uW56HS"
45
+ };
46
+ export default form_renderer_module;