@quazardous/qdadm 1.19.3

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 (291) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +111 -0
  3. package/package.json +101 -0
  4. package/src/assets/logo.svg +6 -0
  5. package/src/auth/SessionAuthAdapter.ts +459 -0
  6. package/src/auth/index.ts +15 -0
  7. package/src/chain/ActiveStack.ts +154 -0
  8. package/src/chain/StackHydrator.ts +292 -0
  9. package/src/chain/index.ts +25 -0
  10. package/src/chain/useActiveStack.ts +120 -0
  11. package/src/chain/useStackHydrator.ts +155 -0
  12. package/src/components/BoolCell.vue +34 -0
  13. package/src/components/InfoBanner.vue +73 -0
  14. package/src/components/QdadmRoot.vue +52 -0
  15. package/src/components/SeverityTag.vue +86 -0
  16. package/src/components/dialogs/BulkStatusDialog.vue +60 -0
  17. package/src/components/dialogs/MultiStepDialog.vue +331 -0
  18. package/src/components/dialogs/SimpleDialog.vue +122 -0
  19. package/src/components/dialogs/UnsavedChangesDialog.vue +80 -0
  20. package/src/components/display/BannerZone.vue +65 -0
  21. package/src/components/display/CardsGrid.vue +72 -0
  22. package/src/components/display/CopyableId.vue +84 -0
  23. package/src/components/display/EmptyState.vue +62 -0
  24. package/src/components/display/IntensityBar.vue +190 -0
  25. package/src/components/display/RichCardsGrid.vue +101 -0
  26. package/src/components/edit/FormActions.vue +78 -0
  27. package/src/components/edit/FormField.vue +82 -0
  28. package/src/components/edit/FormInput.vue +158 -0
  29. package/src/components/edit/FormPage.vue +260 -0
  30. package/src/components/edit/FormTab.vue +217 -0
  31. package/src/components/edit/FormTabs.vue +120 -0
  32. package/src/components/edit/LookupField.vue +406 -0
  33. package/src/components/edit/LookupPickerDialog.vue +230 -0
  34. package/src/components/editors/JsonEditorFoldable.vue +470 -0
  35. package/src/components/editors/JsonStructuredField.vue +264 -0
  36. package/src/components/editors/JsonViewer.vue +51 -0
  37. package/src/components/editors/KeyValueEditor.vue +314 -0
  38. package/src/components/editors/LanguageEditor.vue +259 -0
  39. package/src/components/editors/PermissionEditor.vue +558 -0
  40. package/src/components/editors/ScopeEditor.vue +372 -0
  41. package/src/components/editors/VanillaJsonEditor.vue +183 -0
  42. package/src/components/index.ts +83 -0
  43. package/src/components/item/FieldGroups.vue +392 -0
  44. package/src/components/layout/AppLayout.vue +1032 -0
  45. package/src/components/layout/BaseLayout.vue +190 -0
  46. package/src/components/layout/Breadcrumb.vue +55 -0
  47. package/src/components/layout/DashboardLayout.vue +104 -0
  48. package/src/components/layout/FormLayout.vue +256 -0
  49. package/src/components/layout/ListLayout.vue +278 -0
  50. package/src/components/layout/PageHeader.vue +156 -0
  51. package/src/components/layout/PageLayout.vue +126 -0
  52. package/src/components/layout/PageNav.vue +192 -0
  53. package/src/components/layout/SidebarBox.vue +87 -0
  54. package/src/components/layout/Zone.vue +182 -0
  55. package/src/components/layout/defaults/DefaultBreadcrumb.vue +149 -0
  56. package/src/components/layout/defaults/DefaultFooter.vue +89 -0
  57. package/src/components/layout/defaults/DefaultFormActions.vue +67 -0
  58. package/src/components/layout/defaults/DefaultHeader.vue +78 -0
  59. package/src/components/layout/defaults/DefaultMenu.vue +188 -0
  60. package/src/components/layout/defaults/DefaultPagination.vue +75 -0
  61. package/src/components/layout/defaults/DefaultTable.vue +137 -0
  62. package/src/components/layout/defaults/DefaultUserInfo.vue +111 -0
  63. package/src/components/layout/defaults/index.ts +16 -0
  64. package/src/components/lists/ActionButtons.vue +49 -0
  65. package/src/components/lists/ActionColumn.vue +40 -0
  66. package/src/components/lists/FilterBar.vue +54 -0
  67. package/src/components/lists/ListPage.vue +467 -0
  68. package/src/components/pages/LoginPage.vue +334 -0
  69. package/src/components/pages/NotFoundPage.vue +98 -0
  70. package/src/components/show/ShowDisplay.vue +343 -0
  71. package/src/components/show/ShowField.vue +67 -0
  72. package/src/components/show/ShowPage.vue +431 -0
  73. package/src/composables/index.ts +155 -0
  74. package/src/composables/useApp.ts +67 -0
  75. package/src/composables/useAuth.ts +98 -0
  76. package/src/composables/useBareForm.ts +319 -0
  77. package/src/composables/useBreadcrumb.ts +252 -0
  78. package/src/composables/useChildPage.ts +113 -0
  79. package/src/composables/useCurrentEntity.ts +60 -0
  80. package/src/composables/useDeferred.ts +94 -0
  81. package/src/composables/useDirtyState.ts +138 -0
  82. package/src/composables/useEntityItemFormPage.ts +942 -0
  83. package/src/composables/useEntityItemFormPage.types.ts +451 -0
  84. package/src/composables/useEntityItemPage.ts +438 -0
  85. package/src/composables/useEntityItemShowPage.ts +722 -0
  86. package/src/composables/useFieldManager.ts +692 -0
  87. package/src/composables/useForm.ts +544 -0
  88. package/src/composables/useGuardStore.ts +53 -0
  89. package/src/composables/useHooks.ts +56 -0
  90. package/src/composables/useInfoBanner.ts +217 -0
  91. package/src/composables/useJsonSyntax.ts +122 -0
  92. package/src/composables/useLayoutResolver.ts +329 -0
  93. package/src/composables/useListPage.ts +1535 -0
  94. package/src/composables/useListPage.types.ts +437 -0
  95. package/src/composables/useListPage.utils.ts +101 -0
  96. package/src/composables/useNavContext.ts +439 -0
  97. package/src/composables/useNavigation.ts +216 -0
  98. package/src/composables/useOptionsLookup.ts +323 -0
  99. package/src/composables/usePageTitle.ts +84 -0
  100. package/src/composables/useSSEBridge.ts +142 -0
  101. package/src/composables/useSemanticBreadcrumb.ts +222 -0
  102. package/src/composables/useSidebarState.ts +24 -0
  103. package/src/composables/useSignals.ts +52 -0
  104. package/src/composables/useUnsavedChangesGuard.ts +155 -0
  105. package/src/composables/useUserImpersonator.ts +317 -0
  106. package/src/composables/useZoneRegistry.ts +252 -0
  107. package/src/core/bundles.ts +558 -0
  108. package/src/core/decorator.ts +420 -0
  109. package/src/core/extension.ts +470 -0
  110. package/src/core/index.ts +59 -0
  111. package/src/deferred/DeferredRegistry.ts +353 -0
  112. package/src/deferred/index.ts +15 -0
  113. package/src/editors/index.ts +12 -0
  114. package/src/entity/EntityManager.cache.ts +530 -0
  115. package/src/entity/EntityManager.crud.ts +615 -0
  116. package/src/entity/EntityManager.interface.ts +78 -0
  117. package/src/entity/EntityManager.query.ts +221 -0
  118. package/src/entity/EntityManager.relations.ts +151 -0
  119. package/src/entity/EntityManager.ts +944 -0
  120. package/src/entity/EntityManager.types.ts +288 -0
  121. package/src/entity/auth/CompositeAuthAdapter.ts +194 -0
  122. package/src/entity/auth/EntityAuthAdapter.ts +119 -0
  123. package/src/entity/auth/PermissiveAdapter.ts +43 -0
  124. package/src/entity/auth/RoleHierarchy.ts +128 -0
  125. package/src/entity/auth/SecurityChecker.ts +202 -0
  126. package/src/entity/auth/factory.ts +203 -0
  127. package/src/entity/auth/index.ts +47 -0
  128. package/src/entity/factory.test.js +189 -0
  129. package/src/entity/factory.ts +146 -0
  130. package/src/entity/index.ts +49 -0
  131. package/src/entity/storage/ApiStorage.ts +228 -0
  132. package/src/entity/storage/IStorage.ts +100 -0
  133. package/src/entity/storage/LocalStorage.ts +200 -0
  134. package/src/entity/storage/MemoryStorage.ts +184 -0
  135. package/src/entity/storage/MockApiStorage.ts +318 -0
  136. package/src/entity/storage/SdkStorage.ts +377 -0
  137. package/src/entity/storage/factory.test.js +159 -0
  138. package/src/entity/storage/factory.ts +209 -0
  139. package/src/entity/storage/index.ts +75 -0
  140. package/src/gen/FieldMapper.ts +122 -0
  141. package/src/gen/StorageProfileFactory.ts +93 -0
  142. package/src/gen/connectors/BaseConnector.ts +150 -0
  143. package/src/gen/connectors/ManualConnector.test.js +499 -0
  144. package/src/gen/connectors/ManualConnector.ts +414 -0
  145. package/src/gen/connectors/OpenAPIConnector.test.js +836 -0
  146. package/src/gen/connectors/OpenAPIConnector.ts +693 -0
  147. package/src/gen/connectors/__fixtures__/sample-openapi.json +311 -0
  148. package/src/gen/connectors/index.ts +27 -0
  149. package/src/gen/createManagers.ts +245 -0
  150. package/src/gen/decorators.ts +134 -0
  151. package/src/gen/generateManagers.test.js +540 -0
  152. package/src/gen/generateManagers.ts +398 -0
  153. package/src/gen/index.ts +66 -0
  154. package/src/gen/schema.ts +248 -0
  155. package/src/gen/vite-plugin.ts +114 -0
  156. package/src/generated/managers/testManager.js +45 -0
  157. package/src/generated/managers/testManager.ts +46 -0
  158. package/src/hooks/HookRegistry.ts +16 -0
  159. package/src/hooks/index.ts +15 -0
  160. package/src/i18n/I18n.ts +344 -0
  161. package/src/i18n/IncrementalDomainProvider.ts +153 -0
  162. package/src/i18n/InlineTranslationProvider.ts +4 -0
  163. package/src/i18n/LazyTranslationProvider.ts +102 -0
  164. package/src/i18n/MessagesRegistry.ts +4 -0
  165. package/src/i18n/Resolver.ts +4 -0
  166. package/src/i18n/__tests__/I18n.test.ts +169 -0
  167. package/src/i18n/__tests__/IncrementalDomainProvider.test.ts +146 -0
  168. package/src/i18n/__tests__/LazyTranslationProvider.test.ts +100 -0
  169. package/src/i18n/__tests__/Resolver.test.ts +271 -0
  170. package/src/i18n/defaults/DefaultCoreProvider.ts +28 -0
  171. package/src/i18n/defaults/core.en.yml +55 -0
  172. package/src/i18n/defaults/core.fr.yml +55 -0
  173. package/src/i18n/index.ts +55 -0
  174. package/src/i18n/loaders/raw-modules.d.ts +15 -0
  175. package/src/i18n/loaders/yaml.ts +35 -0
  176. package/src/i18n/strategies.ts +4 -0
  177. package/src/i18n/types.ts +34 -0
  178. package/src/i18n/useI18n.ts +34 -0
  179. package/src/index.ts +453 -0
  180. package/src/kernel/EventRouter.ts +23 -0
  181. package/src/kernel/Kernel.api.ts +79 -0
  182. package/src/kernel/Kernel.auth.ts +120 -0
  183. package/src/kernel/Kernel.i18n.ts +29 -0
  184. package/src/kernel/Kernel.modules.ts +170 -0
  185. package/src/kernel/Kernel.registries.ts +237 -0
  186. package/src/kernel/Kernel.routing.ts +334 -0
  187. package/src/kernel/Kernel.ts +460 -0
  188. package/src/kernel/Kernel.types.ts +263 -0
  189. package/src/kernel/Kernel.vue.ts +304 -0
  190. package/src/kernel/KernelContext.entities.ts +80 -0
  191. package/src/kernel/KernelContext.events.ts +57 -0
  192. package/src/kernel/KernelContext.i18n.ts +37 -0
  193. package/src/kernel/KernelContext.permissions.ts +38 -0
  194. package/src/kernel/KernelContext.routing.ts +280 -0
  195. package/src/kernel/KernelContext.ts +252 -0
  196. package/src/kernel/KernelContext.types.ts +173 -0
  197. package/src/kernel/KernelContext.zones.ts +54 -0
  198. package/src/kernel/Module.ts +169 -0
  199. package/src/kernel/ModuleLoader.ts +645 -0
  200. package/src/kernel/SSEBridge.ts +11 -0
  201. package/src/kernel/SignalBus.ts +48 -0
  202. package/src/kernel/index.ts +56 -0
  203. package/src/module/index.ts +33 -0
  204. package/src/module/moduleRegistry.ts +492 -0
  205. package/src/modules/debug/AuthCollector.ts +501 -0
  206. package/src/modules/debug/Collector.ts +20 -0
  207. package/src/modules/debug/DebugBridge.ts +14 -0
  208. package/src/modules/debug/DebugModule.ts +220 -0
  209. package/src/modules/debug/EntitiesCollector.ts +839 -0
  210. package/src/modules/debug/ErrorCollector.ts +4 -0
  211. package/src/modules/debug/I18nCollector.ts +9 -0
  212. package/src/modules/debug/LocalStorageAdapter.ts +7 -0
  213. package/src/modules/debug/RouterCollector.ts +449 -0
  214. package/src/modules/debug/SignalCollector.ts +4 -0
  215. package/src/modules/debug/ToastCollector.ts +4 -0
  216. package/src/modules/debug/ZonesCollector.ts +447 -0
  217. package/src/modules/debug/components/DebugBar.vue +31 -0
  218. package/src/modules/debug/components/adminPanelsConfig.ts +42 -0
  219. package/src/modules/debug/components/index.ts +9 -0
  220. package/src/modules/debug/components/panels/AuthPanel.vue +267 -0
  221. package/src/modules/debug/components/panels/EntitiesPanel.vue +572 -0
  222. package/src/modules/debug/components/panels/I18nPanel.vue +738 -0
  223. package/src/modules/debug/components/panels/RouterPanel.vue +440 -0
  224. package/src/modules/debug/components/panels/ZonesPanel.vue +133 -0
  225. package/src/modules/debug/components/panels/index.ts +16 -0
  226. package/src/modules/debug/index.ts +58 -0
  227. package/src/modules/debug/styles.scss +2671 -0
  228. package/src/notifications/NotificationBadge.vue +35 -0
  229. package/src/notifications/NotificationListener.vue +71 -0
  230. package/src/notifications/NotificationModule.ts +76 -0
  231. package/src/notifications/NotificationPanel.vue +478 -0
  232. package/src/notifications/NotificationStore.ts +288 -0
  233. package/src/notifications/index.ts +42 -0
  234. package/src/notifications/styles.scss +32 -0
  235. package/src/orchestrator/Orchestrator.ts +427 -0
  236. package/src/orchestrator/index.ts +8 -0
  237. package/src/orchestrator/useOrchestrator.ts +80 -0
  238. package/src/plugin.ts +251 -0
  239. package/src/query/FilterQuery.ts +306 -0
  240. package/src/query/QueryExecutor.ts +341 -0
  241. package/src/query/index.ts +16 -0
  242. package/src/security/EntityRolesProvider.ts +385 -0
  243. package/src/security/PermissionMatcher.ts +152 -0
  244. package/src/security/PermissionRegistry.ts +273 -0
  245. package/src/security/PersistableRolesProvider.ts +584 -0
  246. package/src/security/RolesManager.ts +136 -0
  247. package/src/security/RolesProvider.ts +167 -0
  248. package/src/security/RolesProviderStorage.ts +211 -0
  249. package/src/security/SecurityModule.ts +94 -0
  250. package/src/security/StaticRolesProvider.ts +117 -0
  251. package/src/security/UsersManager.ts +163 -0
  252. package/src/security/index.ts +77 -0
  253. package/src/security/pages/RoleForm.vue +276 -0
  254. package/src/security/pages/RoleList.vue +123 -0
  255. package/src/styles/_alerts.scss +95 -0
  256. package/src/styles/_buttons.scss +391 -0
  257. package/src/styles/_cards.scss +241 -0
  258. package/src/styles/_code.scss +78 -0
  259. package/src/styles/_dialogs.scss +55 -0
  260. package/src/styles/_filter-bar.scss +70 -0
  261. package/src/styles/_forms.scss +434 -0
  262. package/src/styles/_helpers.scss +153 -0
  263. package/src/styles/_lists.scss +225 -0
  264. package/src/styles/_main.scss +356 -0
  265. package/src/styles/_markdown.scss +88 -0
  266. package/src/styles/_responsive.scss +255 -0
  267. package/src/styles/_show-pages.scss +186 -0
  268. package/src/styles/_sidebar.scss +380 -0
  269. package/src/styles/_states.scss +115 -0
  270. package/src/styles/_stats.scss +47 -0
  271. package/src/styles/_variables.scss +224 -0
  272. package/src/styles/index.scss +38 -0
  273. package/src/styles/theme/_components.scss +331 -0
  274. package/src/styles/theme/_index.scss +10 -0
  275. package/src/styles/theme/_tokens.scss +147 -0
  276. package/src/styles/theme/_utilities.scss +175 -0
  277. package/src/toast/ToastBridgeModule.ts +68 -0
  278. package/src/toast/ToastListener.vue +55 -0
  279. package/src/toast/index.ts +26 -0
  280. package/src/toast/useSignalToast.ts +154 -0
  281. package/src/types/index.ts +285 -0
  282. package/src/types/pluralize.d.ts +19 -0
  283. package/src/types/quarkernel.d.ts +50 -0
  284. package/src/utils/formatters.ts +174 -0
  285. package/src/utils/index.ts +35 -0
  286. package/src/utils/transformers.ts +131 -0
  287. package/src/vite/qdadmDebugPlugin.ts +401 -0
  288. package/src/vite-env.d.ts +50 -0
  289. package/src/zones/ZoneRegistry.ts +934 -0
  290. package/src/zones/index.ts +29 -0
  291. package/src/zones/zones.ts +191 -0
@@ -0,0 +1,451 @@
1
+ /**
2
+ * useEntityItemFormPage - Type definitions
3
+ *
4
+ * Extracted from useEntityItemFormPage.ts for maintainability.
5
+ */
6
+ import type { Ref, ComputedRef } from 'vue'
7
+ import type { RouteLocationNormalizedLoaded, Router } from 'vue-router'
8
+ import type { GuardDialogState } from './useUnsavedChangesGuard'
9
+ import type { BreadcrumbDisplayItem } from './useBreadcrumb'
10
+ import type { ParentConfig, EntityManager } from './useEntityItemPage'
11
+ import type { FieldGroup, GroupDefinition, GroupOptions, MoveFieldPosition } from './useFieldManager'
12
+ import type { StackHydratorReturn } from '../chain/useStackHydrator'
13
+
14
+ /**
15
+ * Orchestrator interface
16
+ */
17
+ export interface Orchestrator {
18
+ get: (entityName: string) => EntityManager
19
+ toast?: {
20
+ success: (summary: string, detail?: string, emitter?: unknown) => void
21
+ error: (summary: string, detail?: string, emitter?: unknown) => void
22
+ warn: (summary: string, detail?: string, emitter?: unknown) => void
23
+ info: (summary: string, detail?: string, emitter?: unknown) => void
24
+ [key: string]: ((summary: string, detail?: string, emitter?: unknown) => void) | undefined
25
+ }
26
+ }
27
+
28
+ /**
29
+ * Field definition from EntityManager schema
30
+ */
31
+ export interface FieldDefinition {
32
+ name: string
33
+ type?: string
34
+ schemaType?: string
35
+ label?: string
36
+ required?: boolean
37
+ default?: unknown
38
+ options?: unknown[]
39
+ optionLabel?: string
40
+ optionValue?: string
41
+ placeholder?: string
42
+ disabled?: boolean
43
+ readonly?: boolean
44
+ editable?: boolean
45
+ reference?: string
46
+ validate?: (value: unknown, formData: unknown) => boolean | string | null | undefined
47
+ [key: string]: unknown
48
+ }
49
+
50
+ /**
51
+ * Resolved field configuration for form rendering
52
+ */
53
+ export interface ResolvedFieldConfig extends FieldDefinition {
54
+ name: string
55
+ type: string
56
+ schemaType: string
57
+ label: string
58
+ group?: string
59
+ }
60
+
61
+ /**
62
+ * Toast helper interface
63
+ */
64
+ export interface ToastHelper {
65
+ add: (options: {
66
+ severity: 'success' | 'error' | 'warn' | 'info'
67
+ summary: string
68
+ detail?: string
69
+ emitter?: unknown
70
+ life?: number
71
+ }) => void
72
+ }
73
+
74
+ /**
75
+ * Action configuration
76
+ */
77
+ export interface ActionConfig {
78
+ name: string
79
+ label: string
80
+ icon?: string
81
+ severity?: string
82
+ onClick: () => void | Promise<void>
83
+ visible?: (ctx: { isEdit: boolean; dirty: boolean }) => boolean
84
+ disabled?: (ctx: { dirty: boolean; saving: boolean }) => boolean
85
+ loading?: () => boolean
86
+ }
87
+
88
+ /**
89
+ * Resolved action for rendering
90
+ */
91
+ export interface ResolvedAction extends ActionConfig {
92
+ isLoading: boolean
93
+ isDisabled: boolean
94
+ }
95
+
96
+ /**
97
+ * Error summary item
98
+ */
99
+ export interface ErrorSummaryItem {
100
+ field: string
101
+ label: string
102
+ message: string
103
+ }
104
+
105
+ /**
106
+ * Page title parts for PageHeader
107
+ */
108
+ export interface PageTitleParts {
109
+ action: string
110
+ entityName: string | undefined
111
+ entityLabel: string | undefined
112
+ }
113
+
114
+ /**
115
+ * Form props for FormPage component
116
+ */
117
+ export interface FormPageProps {
118
+ isEdit: boolean
119
+ mode: 'create' | 'edit'
120
+ loading: boolean
121
+ saving: boolean
122
+ dirty: boolean
123
+ title: string
124
+ titleParts: PageTitleParts
125
+ fields: ResolvedFieldConfig[]
126
+ groups: FieldGroup<ResolvedFieldConfig>[]
127
+ actions: ResolvedAction[]
128
+ canSave: boolean
129
+ canDelete: boolean
130
+ errors: Record<string, string>
131
+ hasErrors: boolean
132
+ errorSummary: ErrorSummaryItem[] | null
133
+ submitted: boolean
134
+ guardDialog: GuardDialogState | null
135
+ }
136
+
137
+ /**
138
+ * Form events for FormPage component
139
+ */
140
+ export interface FormPageEvents {
141
+ save: () => Promise<unknown>
142
+ saveAndClose: () => Promise<unknown>
143
+ cancel: () => void
144
+ delete: () => void
145
+ }
146
+
147
+ /**
148
+ * Axios-like error interface
149
+ */
150
+ export interface AxiosError {
151
+ response?: {
152
+ data?: {
153
+ detail?: string
154
+ }
155
+ }
156
+ message?: string
157
+ }
158
+
159
+ /**
160
+ * PrimeVue confirm service interface
161
+ */
162
+ export interface ConfirmService {
163
+ require: (options: {
164
+ message: string
165
+ header: string
166
+ icon: string
167
+ acceptClass?: string
168
+ accept: () => void
169
+ }) => void
170
+ }
171
+
172
+ /**
173
+ * Options for useEntityItemFormPage
174
+ */
175
+ export interface UseEntityItemFormPageOptions<T extends Record<string, unknown> = Record<string, unknown>> {
176
+ /** Entity name for EntityManager */
177
+ entity: string
178
+ /** Custom function to extract ID from route */
179
+ getId?: (() => string | number | null) | null
180
+ /** Route name suffix for create mode (default: 'create') */
181
+ createRouteSuffix?: string
182
+ /** Route name suffix for edit mode (default: 'edit') */
183
+ editRouteSuffix?: string
184
+ /** Auto-load entity on mount (default: true) */
185
+ loadOnMount?: boolean
186
+ /** Enable unsaved changes guard (default: true) */
187
+ enableGuard?: boolean
188
+ /** Use PATCH instead of PUT for updates (default: false) */
189
+ usePatch?: boolean
190
+ /** Transform loaded data before setting form */
191
+ transformLoad?: (data: unknown) => T
192
+ /** Transform form data before saving */
193
+ transformSave?: (data: unknown) => unknown
194
+ /** Callback on successful load */
195
+ onLoadSuccess?: ((data: T) => Promise<void> | void) | null
196
+ /** Callback on successful save */
197
+ onSaveSuccess?: ((data: unknown, andClose: boolean) => Promise<void> | void) | null
198
+ /** Callback on successful delete */
199
+ onDeleteSuccess?: (() => Promise<void> | void) | null
200
+ /** Validate field on blur (default: true) */
201
+ validateOnBlur?: boolean
202
+ /** Validate all fields before submit (default: true) */
203
+ validateOnSubmit?: boolean
204
+ /** Show error summary at top of form (default: false) */
205
+ showErrorSummary?: boolean
206
+ /** Auto-generate fields from manager schema (default: true) */
207
+ generateFormFields?: boolean
208
+ /** Custom dirty state getter */
209
+ getDirtyState?: (() => Record<string, unknown>) | null
210
+ /** Override manager.entityName */
211
+ entityName?: string
212
+ /** Override manager.routePrefix */
213
+ routePrefix?: string
214
+ /** Override manager.getInitialData() */
215
+ initialData?: Record<string, unknown>
216
+ }
217
+
218
+ /**
219
+ * Options for generateFields
220
+ */
221
+ export interface GenerateFieldsOptions {
222
+ /** Only include these fields */
223
+ only?: string[] | null
224
+ /** Exclude these fields (merged with excludeField calls) */
225
+ exclude?: string[]
226
+ }
227
+
228
+ /**
229
+ * Options for addField
230
+ */
231
+ export interface AddFieldOptions {
232
+ /** Insert after this field */
233
+ after?: string | null
234
+ /** Insert before this field */
235
+ before?: string | null
236
+ }
237
+
238
+ /**
239
+ * Options for addSaveAction
240
+ */
241
+ export interface AddSaveActionOptions {
242
+ /** Custom label */
243
+ label?: string
244
+ /** Close after save (default: true) */
245
+ andClose?: boolean
246
+ }
247
+
248
+ /**
249
+ * Options for addDeleteAction
250
+ */
251
+ export interface AddDeleteActionOptions {
252
+ /** Custom label (default: 'Delete') */
253
+ label?: string
254
+ }
255
+
256
+ /**
257
+ * Options for addCancelAction
258
+ */
259
+ export interface AddCancelActionOptions {
260
+ /** Custom label (default: 'Cancel') */
261
+ label?: string
262
+ }
263
+
264
+ /**
265
+ * Return type for useEntityItemFormPage
266
+ */
267
+ export interface UseEntityItemFormPageReturn<T extends Record<string, unknown> = Record<string, unknown>> {
268
+ // Manager access
269
+ manager: EntityManager
270
+
271
+ // Mode
272
+ mode: ComputedRef<'create' | 'edit'>
273
+ isEdit: ComputedRef<boolean>
274
+ isCreate: ComputedRef<boolean>
275
+ entityId: ComputedRef<string | number | null>
276
+
277
+ // Parent chain (from route.meta.parent, supports N-level nesting)
278
+ parentConfig: ComputedRef<ParentConfig | null>
279
+ parentId: ComputedRef<string | number | null>
280
+ parentData: ComputedRef<unknown | null>
281
+ parentChain: Ref<Map<number, unknown>>
282
+ getChainDepth: (config?: ParentConfig | null) => number
283
+
284
+ // State
285
+ data: Ref<T>
286
+ loading: Ref<boolean>
287
+ saving: Ref<boolean>
288
+ dirty: Ref<boolean>
289
+ dirtyFields: Ref<string[]>
290
+ originalData: Ref<unknown>
291
+
292
+ // Actions
293
+ load: () => Promise<void>
294
+ submit: (andClose?: boolean) => Promise<unknown>
295
+ cancel: () => void
296
+ remove: () => Promise<void>
297
+ confirmDelete: () => void
298
+ reset: () => void
299
+ goToList: () => void
300
+ findListRoute: () => { name: string; params?: Record<string, unknown> }
301
+
302
+ // Dirty tracking
303
+ takeSnapshot: () => void
304
+ checkDirty: () => void
305
+ isFieldDirty: (fieldPath: string) => boolean
306
+
307
+ // Field management
308
+ fields: ComputedRef<ResolvedFieldConfig[]>
309
+ generateFields: (options?: GenerateFieldsOptions) => UseEntityItemFormPageReturn<T>
310
+ resolveReferences: () => Promise<void>
311
+ addField: (
312
+ name: string,
313
+ fieldConfig: Partial<FieldDefinition>,
314
+ options?: AddFieldOptions
315
+ ) => UseEntityItemFormPageReturn<T>
316
+ updateField: (name: string, fieldConfig: Partial<FieldDefinition>) => UseEntityItemFormPageReturn<T>
317
+ removeField: (name: string) => UseEntityItemFormPageReturn<T>
318
+ excludeField: (name: string) => UseEntityItemFormPageReturn<T>
319
+ getFieldConfig: (name: string) => ResolvedFieldConfig | undefined
320
+ getFields: () => ResolvedFieldConfig[]
321
+ setFieldOrder: (order: string[]) => UseEntityItemFormPageReturn<T>
322
+ moveField: (name: string, position: MoveFieldPosition) => UseEntityItemFormPageReturn<T>
323
+
324
+ // Group management
325
+ groups: ComputedRef<FieldGroup<ResolvedFieldConfig>[]>
326
+ group: (name: string, fieldsOrOptions?: string[] | GroupOptions, options?: GroupOptions) => UseEntityItemFormPageReturn<T>
327
+ defineGroups: (definitions: Record<string, GroupDefinition>) => UseEntityItemFormPageReturn<T>
328
+ getGroup: (name: string) => FieldGroup<ResolvedFieldConfig> | undefined
329
+ getFieldsByGroup: (groupName: string) => ResolvedFieldConfig[]
330
+ getUngroupedFields: () => ResolvedFieldConfig[]
331
+
332
+ // Validation
333
+ errors: Ref<Record<string, string>>
334
+ hasErrors: ComputedRef<boolean>
335
+ errorSummary: ComputedRef<ErrorSummaryItem[]>
336
+ submitted: Ref<boolean>
337
+ validate: () => boolean
338
+ validateField: (name: string) => string | null
339
+ clearErrors: () => void
340
+ clearFieldError: (name: string) => void
341
+ getFieldError: (name: string) => string | null
342
+ handleFieldBlur: (name: string) => void
343
+
344
+ // Action management
345
+ actions: ComputedRef<ResolvedAction[]>
346
+ addAction: (name: string, actionConfig: Omit<ActionConfig, 'name'>) => void
347
+ removeAction: (name: string) => void
348
+ getActions: () => ResolvedAction[]
349
+ addSaveAction: (options?: AddSaveActionOptions) => void
350
+ addDeleteAction: (options?: AddDeleteActionOptions) => void
351
+ addCancelAction: (options?: AddCancelActionOptions) => void
352
+
353
+ // Permissions
354
+ canSave: ComputedRef<boolean>
355
+ canDeleteRecord: ComputedRef<boolean>
356
+
357
+ // Breadcrumb
358
+ breadcrumb: ComputedRef<BreadcrumbDisplayItem[]>
359
+
360
+ // Guard dialog (for UnsavedChangesDialog - pass to PageLayout)
361
+ guardDialog: GuardDialogState | null
362
+
363
+ // Title helpers
364
+ entityLabel: ComputedRef<string>
365
+ pageTitle: ComputedRef<string>
366
+ pageTitleParts: ComputedRef<PageTitleParts>
367
+
368
+ // Utilities
369
+ toast: ToastHelper
370
+ confirm: ConfirmService
371
+ router: Router
372
+ route: RouteLocationNormalizedLoaded
373
+
374
+ // FormPage integration
375
+ props: ComputedRef<FormPageProps>
376
+ events: FormPageEvents
377
+
378
+ // Stack hydrator (for setting entity data on navigation context)
379
+ hydrator: StackHydratorReturn
380
+ }
381
+
382
+ /**
383
+ * Type mapping from schema types to input component types
384
+ */
385
+ export const TYPE_MAPPINGS: Record<string, string> = {
386
+ text: 'text',
387
+ string: 'text',
388
+ email: 'email',
389
+ password: 'password',
390
+ number: 'number',
391
+ integer: 'number',
392
+ float: 'number',
393
+ boolean: 'boolean',
394
+ checkbox: 'boolean',
395
+ select: 'select',
396
+ dropdown: 'select',
397
+ date: 'date',
398
+ datetime: 'datetime',
399
+ textarea: 'textarea',
400
+ array: 'array',
401
+ object: 'object',
402
+ }
403
+
404
+ /**
405
+ * Built-in validators by type
406
+ */
407
+ export const TYPE_VALIDATORS: Record<string, (value: unknown) => boolean | string> = {
408
+ email: (value) => {
409
+ if (!value) return true // Empty handled by required
410
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
411
+ return emailRegex.test(value as string) || 'Invalid email address'
412
+ },
413
+ number: (value) => {
414
+ if (value === null || value === undefined || value === '') return true
415
+ return !isNaN(Number(value)) || 'Must be a number'
416
+ },
417
+ integer: (value) => {
418
+ if (value === null || value === undefined || value === '') return true
419
+ return Number.isInteger(Number(value)) || 'Must be an integer'
420
+ },
421
+ url: (value) => {
422
+ if (!value) return true
423
+ try {
424
+ new URL(value as string)
425
+ return true
426
+ } catch {
427
+ return 'Invalid URL'
428
+ }
429
+ },
430
+ }
431
+
432
+ /**
433
+ * Helper: Convert snake_case to Title Case
434
+ */
435
+ export function snakeCaseToTitle(str: string): string {
436
+ if (!str) return ''
437
+ return str
438
+ .split('_')
439
+ .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
440
+ .join(' ')
441
+ }
442
+
443
+ /**
444
+ * Check if a value is "empty" for required validation
445
+ */
446
+ export function isEmpty(value: unknown): boolean {
447
+ if (value === null || value === undefined) return true
448
+ if (typeof value === 'string') return value.trim() === ''
449
+ if (Array.isArray(value)) return value.length === 0
450
+ return false
451
+ }