@duke333/builder-ui 0.1.4 → 0.2.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/dist/index.js CHANGED
@@ -1,138 +1,1257 @@
1
- // src/admin/editorState.ts
2
- var BUILDER_EDITOR_NONE_VALUE = "__none";
3
- function builderEditorOptionsToText(options) {
4
- return (options ?? []).map((option) => `${option.label}:${option.value}`).join("\n");
5
- }
6
- function builderEditorTextToOptions(value) {
7
- const rows = (value ?? "").split("\n").map((line) => line.trim()).filter(Boolean);
8
- if (rows.length === 0) return void 0;
9
- return rows.map((line) => {
10
- const [label, ...rest] = line.split(":");
11
- return { label: label.trim(), value: rest.join(":").trim() || label.trim() };
12
- });
13
- }
14
- function builderEditorSearchFieldsToText(fields) {
15
- return (fields ?? []).join("\n");
16
- }
17
- function builderEditorTextToSearchFields(value) {
18
- const fields = (value ?? "").split("\n").map((line) => line.trim()).filter(Boolean);
19
- return fields.length > 0 ? fields : void 0;
20
- }
21
- function getBuilderEditorTriggerRoute(config) {
22
- const route = config.route ?? config.path ?? config.url;
23
- return typeof route === "string" ? route : "";
24
- }
25
- function valuesFromTriggers(triggers) {
26
- return triggers.filter((trigger) => trigger.action === "callApi" || trigger.action === "webhook").map((trigger) => ({
27
- event: trigger.event,
28
- route: getBuilderEditorTriggerRoute(trigger.config),
29
- enabled: trigger.enabled,
30
- blocking: trigger.blocking
31
- })).filter((trigger) => trigger.route);
32
- }
33
- function valuesFromFieldTriggers(triggers) {
34
- return (triggers ?? []).map((trigger) => ({
35
- event: trigger.event,
36
- action: trigger.action,
37
- enabled: trigger.enabled,
38
- debounceMs: trigger.debounceMs
39
- }));
1
+ // src/ready/BuilderProvider.tsx
2
+ import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
3
+ import {
4
+ createContext,
5
+ useCallback,
6
+ useContext,
7
+ useMemo,
8
+ useRef,
9
+ useState
10
+ } from "react";
11
+
12
+ // src/api/createBuilderApiClient.ts
13
+ function queryParams(query) {
14
+ return { ...query };
40
15
  }
41
- function clampLayoutSpan(span, columns) {
42
- if (!span || Number.isNaN(span)) return columns;
43
- return Math.max(1, Math.min(columns, Math.trunc(span)));
16
+ function fieldOptionsQueryParams(query) {
17
+ const flatQuery = { search: query.search };
18
+ for (const [key, value] of Object.entries(query.depends ?? {})) {
19
+ flatQuery[`depends.${key}`] = value;
20
+ }
21
+ return flatQuery;
44
22
  }
45
- function builderFormEditorDefaultSpan(field) {
46
- if (field.type === "textarea" || field.type === "checkbox") return 12;
47
- return 6;
23
+ function createBuilderApiClient(rootTransport, options = {}) {
24
+ const basePath = options.apiBasePath?.trim().replace(/\/+$/g, "") ?? "";
25
+ const path = (value) => `${basePath}${value}`;
26
+ const transport = {
27
+ get: (value, requestOptions) => rootTransport.get(path(value), requestOptions),
28
+ post: (value, body, requestOptions) => rootTransport.post(path(value), body, requestOptions),
29
+ patch: (value, body, requestOptions) => rootTransport.patch(path(value), body, requestOptions),
30
+ delete: (value, requestOptions) => rootTransport.delete(path(value), requestOptions)
31
+ };
32
+ return {
33
+ listBuilderForms: (query) => transport.get("/builder/forms", {
34
+ query: queryParams(query)
35
+ }),
36
+ listBuilderDbTables: () => transport.get("/builder/datasources/tables"),
37
+ listBuilderFormOptions: () => transport.get("/builder/forms/options"),
38
+ getBuilderForm: (id) => transport.get(`/builder/forms/${encodeURIComponent(id)}`),
39
+ createBuilderForm: (input) => transport.post("/builder/forms", input),
40
+ updateBuilderForm: (id, input) => transport.patch(`/builder/forms/${encodeURIComponent(id)}`, input),
41
+ replicateBuilderForm: (id, input) => transport.post(`/builder/forms/${encodeURIComponent(id)}/replicate`, input),
42
+ deleteBuilderForm: (id) => transport.delete(`/builder/forms/${encodeURIComponent(id)}`),
43
+ listBuilderLists: (query) => transport.get("/builder/lists", {
44
+ query: queryParams(query)
45
+ }),
46
+ listBuilderListOptions: () => transport.get("/builder/lists/options"),
47
+ getBuilderList: (id) => transport.get(`/builder/lists/${encodeURIComponent(id)}`),
48
+ createBuilderList: (input) => transport.post("/builder/lists", input),
49
+ updateBuilderList: (id, input) => transport.patch(`/builder/lists/${encodeURIComponent(id)}`, input),
50
+ replicateBuilderList: (id, input) => transport.post(`/builder/lists/${encodeURIComponent(id)}/replicate`, input),
51
+ deleteBuilderList: (id) => transport.delete(`/builder/lists/${encodeURIComponent(id)}`),
52
+ listBuilderViews: (query) => transport.get("/builder/views", {
53
+ query: queryParams(query)
54
+ }),
55
+ getBuilderView: (id) => transport.get(`/builder/views/${encodeURIComponent(id)}`),
56
+ createBuilderView: (input) => transport.post("/builder/views", input),
57
+ updateBuilderView: (id, input) => transport.patch(`/builder/views/${encodeURIComponent(id)}`, input),
58
+ replicateBuilderView: (id, input) => transport.post(`/builder/views/${encodeURIComponent(id)}/replicate`, input),
59
+ deleteBuilderView: (id) => transport.delete(`/builder/views/${encodeURIComponent(id)}`),
60
+ getRuntimeBuilderForm: (id) => transport.get(`/builder/runtime/forms/${encodeURIComponent(id)}`),
61
+ createRuntimeBuilderFormEntry: (formId, input) => transport.post(
62
+ `/builder/runtime/forms/${encodeURIComponent(formId)}/entries`,
63
+ input
64
+ ),
65
+ listRuntimeBuilderFormFieldOptions: (formId, fieldKey, query) => transport.get(
66
+ `/builder/runtime/forms/${encodeURIComponent(formId)}/fields/${encodeURIComponent(fieldKey)}/options`,
67
+ { query: fieldOptionsQueryParams(query) }
68
+ ),
69
+ runRuntimeBuilderFormFieldTrigger: (formId, fieldKey, event, input) => transport.post(
70
+ `/builder/runtime/forms/${encodeURIComponent(formId)}/fields/${encodeURIComponent(fieldKey)}/triggers/${encodeURIComponent(event)}`,
71
+ input
72
+ ),
73
+ getRuntimeBuilderList: (id) => transport.get(`/builder/runtime/lists/${encodeURIComponent(id)}`),
74
+ listRuntimeBuilderListEntries: (listId, query) => transport.get(
75
+ `/builder/runtime/lists/${encodeURIComponent(listId)}/entries`,
76
+ { query: queryParams(query) }
77
+ ),
78
+ getRuntimeBuilderView: (id) => transport.get(`/builder/runtime/views/${encodeURIComponent(id)}`),
79
+ runRuntimeBuilderViewFieldTrigger: (viewId, fieldKey, event, input) => transport.post(
80
+ `/builder/runtime/views/${encodeURIComponent(viewId)}/fields/${encodeURIComponent(fieldKey)}/triggers/${encodeURIComponent(event)}`,
81
+ input
82
+ ),
83
+ listBuilderViewEntries: (viewId, query) => transport.get(
84
+ `/builder/runtime/views/${encodeURIComponent(viewId)}/entries`,
85
+ { query: queryParams(query) }
86
+ ),
87
+ createBuilderViewEntry: (viewId, input) => transport.post(
88
+ `/builder/runtime/views/${encodeURIComponent(viewId)}/entries`,
89
+ input
90
+ ),
91
+ createCompositeBuilderViewEntry: (viewId, input) => transport.post(
92
+ `/builder/runtime/views/${encodeURIComponent(viewId)}/composite-entries`,
93
+ input
94
+ ),
95
+ updateCompositeBuilderViewEntry: (viewId, id, input) => transport.patch(
96
+ `/builder/runtime/views/${encodeURIComponent(viewId)}/composite-entries/${encodeURIComponent(id)}`,
97
+ input
98
+ ),
99
+ updateBuilderViewEntry: (viewId, id, input) => transport.patch(
100
+ `/builder/runtime/views/${encodeURIComponent(viewId)}/entries/${encodeURIComponent(id)}`,
101
+ input
102
+ ),
103
+ deleteBuilderViewEntry: (viewId, id) => transport.delete(
104
+ `/builder/runtime/views/${encodeURIComponent(viewId)}/entries/${encodeURIComponent(id)}`
105
+ )
106
+ };
48
107
  }
49
- function builderFormEditorDefaultLayoutGroups(fields, subforms = []) {
50
- return [
51
- {
52
- id: "main",
53
- title: "\u04AE\u043D\u0434\u0441\u044D\u043D",
54
- columns: 12,
55
- fields: [
56
- ...fields.map((field) => ({
57
- key: field.key,
58
- span: builderFormEditorDefaultSpan(field)
59
- })),
60
- ...subforms.map((subform) => ({ key: subform.key, span: 12 }))
61
- ]
62
- }
63
- ];
108
+
109
+ // src/hooks/createBuilderHooks.ts
110
+ import { keepPreviousData, useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
111
+ function createBuilderKeys() {
112
+ const builderKeys = {
113
+ forms: ["builder", "forms"],
114
+ dbTables: () => ["builder", "datasources", "tables"],
115
+ formList: (query) => [...builderKeys.forms, "list", query],
116
+ form: (id) => [...builderKeys.forms, "detail", id],
117
+ formOptions: () => [...builderKeys.forms, "options"],
118
+ lists: ["builder", "lists"],
119
+ listList: (query) => [...builderKeys.lists, "list", query],
120
+ list: (id) => [...builderKeys.lists, "detail", id],
121
+ listOptions: () => [...builderKeys.lists, "options"],
122
+ views: ["builder", "views"],
123
+ viewList: (query) => [...builderKeys.views, "list", query],
124
+ view: (id) => [...builderKeys.views, "detail", id],
125
+ runtimeForm: (id) => ["builder", "runtime", "form", id],
126
+ runtimeFieldOptions: (formId, fieldKey, query) => [...builderKeys.runtimeForm(formId), "fields", fieldKey, "options", query],
127
+ runtimeFormEntries: (id) => [...builderKeys.runtimeForm(id), "entries"],
128
+ runtimeList: (id) => ["builder", "runtime", "list", id],
129
+ runtimeListEntries: (id, query) => [...builderKeys.runtimeList(id), "entries", query],
130
+ runtimeView: (id) => ["builder", "runtime", "view", id],
131
+ entries: (id, query) => [...builderKeys.runtimeView(id), "entries", query]
132
+ };
133
+ return builderKeys;
64
134
  }
65
- function normalizeBuilderFormEditorLayoutGroups(groups, fields, subforms = []) {
66
- if (fields.length === 0 && subforms.length === 0) return [];
67
- const layoutItems = [
68
- ...fields.map((field) => ({
69
- key: field.key,
70
- span: builderFormEditorDefaultSpan(field)
71
- })),
72
- ...subforms.map((subform) => ({ key: subform.key, span: 12 }))
73
- ];
74
- const itemKeys = new Set(layoutItems.map((item) => item.key));
75
- const usedKeys = /* @__PURE__ */ new Set();
76
- const normalized = (groups ?? []).map((group, index) => {
77
- const columns = group.columns === 6 || group.columns === 8 ? group.columns : 12;
78
- const groupFields = (group.fields ?? []).filter((field) => itemKeys.has(field.key) && !usedKeys.has(field.key)).map((field) => {
79
- usedKeys.add(field.key);
80
- return { key: field.key, span: clampLayoutSpan(field.span, columns) };
135
+ function createBuilderHooks(client) {
136
+ const builderKeys = createBuilderKeys();
137
+ function invalidateRuntimeViewEntries(queryClient, viewId) {
138
+ return Promise.all([
139
+ queryClient.invalidateQueries({ queryKey: builderKeys.runtimeView(viewId) }),
140
+ queryClient.invalidateQueries({ queryKey: [...builderKeys.runtimeView(viewId), "entries"] })
141
+ ]);
142
+ }
143
+ function useBuilderDbTables() {
144
+ return useQuery({ queryKey: builderKeys.dbTables(), queryFn: client.listBuilderDbTables });
145
+ }
146
+ function useBuilderForms(query) {
147
+ return useQuery({
148
+ queryKey: builderKeys.formList(query),
149
+ queryFn: () => client.listBuilderForms(query),
150
+ placeholderData: keepPreviousData
81
151
  });
82
- return {
83
- id: group.id || `group${index + 1}`,
84
- title: group.title || `Group ${index + 1}`,
85
- columns,
86
- fields: groupFields
87
- };
88
- }).filter((group) => group.fields.length > 0 || group.title.trim());
89
- const missingFields = layoutItems.filter((item) => !usedKeys.has(item.key));
90
- if (normalized.length === 0) {
91
- return builderFormEditorDefaultLayoutGroups(fields, subforms);
92
152
  }
93
- if (missingFields.length > 0) {
94
- normalized.push({
95
- id: "ungrouped",
96
- title: "\u0411\u0443\u0441\u0430\u0434",
97
- columns: 12,
98
- fields: missingFields
153
+ function useBuilderFormOptions() {
154
+ return useQuery({
155
+ queryKey: builderKeys.formOptions(),
156
+ queryFn: client.listBuilderFormOptions
99
157
  });
100
158
  }
101
- return normalized;
102
- }
103
- function builderFormEditorValuesFromEntity(form, emptyValues) {
104
- if (!form) return emptyValues;
105
- const source = form.source;
106
- const fields = form.schema.fields.map((field) => ({
107
- key: field.key,
108
- label: field.label,
109
- type: field.type,
110
- required: field.required,
111
- hidden: field.hidden ?? false,
112
- disabled: field.disabled ?? false,
113
- placeholder: field.placeholder ?? "",
114
- optionsText: builderEditorOptionsToText(field.options),
115
- optionsMode: field.optionsSource?.type === "dbTable" ? "table" : "static",
116
- optionsTable: field.optionsSource?.type === "dbTable" ? field.optionsSource.tableName : BUILDER_EDITOR_NONE_VALUE,
117
- optionsValueField: field.optionsSource?.type === "dbTable" ? field.optionsSource.valueField : BUILDER_EDITOR_NONE_VALUE,
118
- optionsLabelField: field.optionsSource?.type === "dbTable" ? field.optionsSource.labelField : BUILDER_EDITOR_NONE_VALUE,
119
- optionsSearchFieldsText: field.optionsSource?.type === "dbTable" ? builderEditorSearchFieldsToText(field.optionsSource.searchFields) : "",
120
- optionsDependsOn: field.optionsSource?.type === "dbTable" ? field.optionsSource.filterBy?.valueFromField ?? "" : "",
121
- optionsFilterField: field.optionsSource?.type === "dbTable" ? field.optionsSource.filterBy?.field ?? "" : "",
122
- triggers: valuesFromFieldTriggers(field.triggers)
123
- }));
124
- const subforms = (form.schema.subforms ?? []).map((subform) => ({
125
- key: subform.key,
126
- label: subform.label,
127
- viewId: subform.viewId,
128
- parentField: subform.parentField,
129
- childField: subform.childField,
130
- buttonLabel: subform.buttonLabel ?? "",
131
- icon: subform.icon ?? ""
132
- }));
159
+ function useBuilderForm(id) {
160
+ return useQuery({
161
+ queryKey: builderKeys.form(id ?? ""),
162
+ queryFn: () => client.getBuilderForm(id ?? ""),
163
+ enabled: Boolean(id)
164
+ });
165
+ }
166
+ function useSaveBuilderForm() {
167
+ const queryClient = useQueryClient();
168
+ return useMutation({
169
+ mutationFn: ({ id, input }) => id ? client.updateBuilderForm(id, input) : client.createBuilderForm(input),
170
+ onSuccess: (form) => {
171
+ queryClient.invalidateQueries({ queryKey: builderKeys.forms });
172
+ queryClient.invalidateQueries({ queryKey: builderKeys.form(form.id) });
173
+ queryClient.invalidateQueries({ queryKey: builderKeys.runtimeForm(form.id) });
174
+ }
175
+ });
176
+ }
177
+ function useReplicateBuilderForm() {
178
+ const queryClient = useQueryClient();
179
+ return useMutation({
180
+ mutationFn: ({ id, input }) => client.replicateBuilderForm(id, input),
181
+ onSuccess: () => queryClient.invalidateQueries({ queryKey: builderKeys.forms })
182
+ });
183
+ }
184
+ function useDeleteBuilderForm() {
185
+ const queryClient = useQueryClient();
186
+ return useMutation({
187
+ mutationFn: client.deleteBuilderForm,
188
+ onSuccess: () => queryClient.invalidateQueries({ queryKey: builderKeys.forms })
189
+ });
190
+ }
191
+ function useBuilderLists(query) {
192
+ return useQuery({
193
+ queryKey: builderKeys.listList(query),
194
+ queryFn: () => client.listBuilderLists(query),
195
+ placeholderData: keepPreviousData
196
+ });
197
+ }
198
+ function useBuilderListOptions() {
199
+ return useQuery({
200
+ queryKey: builderKeys.listOptions(),
201
+ queryFn: client.listBuilderListOptions
202
+ });
203
+ }
204
+ function useBuilderList(id) {
205
+ return useQuery({
206
+ queryKey: builderKeys.list(id ?? ""),
207
+ queryFn: () => client.getBuilderList(id ?? ""),
208
+ enabled: Boolean(id)
209
+ });
210
+ }
211
+ function useSaveBuilderList() {
212
+ const queryClient = useQueryClient();
213
+ return useMutation({
214
+ mutationFn: ({ id, input }) => id ? client.updateBuilderList(id, input) : client.createBuilderList(input),
215
+ onSuccess: (list) => {
216
+ queryClient.invalidateQueries({ queryKey: builderKeys.lists });
217
+ queryClient.invalidateQueries({ queryKey: builderKeys.list(list.id) });
218
+ queryClient.invalidateQueries({ queryKey: builderKeys.runtimeList(list.id) });
219
+ }
220
+ });
221
+ }
222
+ function useReplicateBuilderList() {
223
+ const queryClient = useQueryClient();
224
+ return useMutation({
225
+ mutationFn: ({ id, input }) => client.replicateBuilderList(id, input),
226
+ onSuccess: () => queryClient.invalidateQueries({ queryKey: builderKeys.lists })
227
+ });
228
+ }
229
+ function useDeleteBuilderList() {
230
+ const queryClient = useQueryClient();
231
+ return useMutation({
232
+ mutationFn: client.deleteBuilderList,
233
+ onSuccess: () => queryClient.invalidateQueries({ queryKey: builderKeys.lists })
234
+ });
235
+ }
236
+ function useBuilderViews(query) {
237
+ return useQuery({
238
+ queryKey: builderKeys.viewList(query),
239
+ queryFn: () => client.listBuilderViews(query),
240
+ placeholderData: keepPreviousData
241
+ });
242
+ }
243
+ function useBuilderView(id) {
244
+ return useQuery({
245
+ queryKey: builderKeys.view(id ?? ""),
246
+ queryFn: () => client.getBuilderView(id ?? ""),
247
+ enabled: Boolean(id)
248
+ });
249
+ }
250
+ function useSaveBuilderView() {
251
+ const queryClient = useQueryClient();
252
+ return useMutation({
253
+ mutationFn: ({ id, input }) => id ? client.updateBuilderView(id, input) : client.createBuilderView(input),
254
+ onSuccess: () => queryClient.invalidateQueries({ queryKey: builderKeys.views })
255
+ });
256
+ }
257
+ function useReplicateBuilderView() {
258
+ const queryClient = useQueryClient();
259
+ return useMutation({
260
+ mutationFn: ({ id, input }) => client.replicateBuilderView(id, input),
261
+ onSuccess: () => queryClient.invalidateQueries({ queryKey: builderKeys.views })
262
+ });
263
+ }
264
+ function useDeleteBuilderView() {
265
+ const queryClient = useQueryClient();
266
+ return useMutation({
267
+ mutationFn: client.deleteBuilderView,
268
+ onSuccess: () => queryClient.invalidateQueries({ queryKey: builderKeys.views })
269
+ });
270
+ }
271
+ function useRuntimeBuilderForm(id) {
272
+ return useQuery({
273
+ queryKey: builderKeys.runtimeForm(id),
274
+ queryFn: () => client.getRuntimeBuilderForm(id)
275
+ });
276
+ }
277
+ function useRuntimeBuilderFormFieldOptions(formId, fieldKey, query, enabled = true) {
278
+ return useQuery({
279
+ queryKey: builderKeys.runtimeFieldOptions(formId ?? "", fieldKey, query),
280
+ queryFn: () => client.listRuntimeBuilderFormFieldOptions(formId ?? "", fieldKey, query),
281
+ enabled: Boolean(formId) && enabled
282
+ });
283
+ }
284
+ function useRunRuntimeBuilderFieldTrigger() {
285
+ return useMutation({
286
+ mutationFn: (args) => {
287
+ if (args.viewId) {
288
+ return client.runRuntimeBuilderViewFieldTrigger(
289
+ args.viewId,
290
+ args.fieldKey,
291
+ args.event,
292
+ args.input
293
+ );
294
+ }
295
+ if (args.formId) {
296
+ return client.runRuntimeBuilderFormFieldTrigger(
297
+ args.formId,
298
+ args.fieldKey,
299
+ args.event,
300
+ args.input
301
+ );
302
+ }
303
+ throw new Error("formId \u044D\u0441\u0432\u044D\u043B viewId \u0448\u0430\u0430\u0440\u0434\u043B\u0430\u0433\u0430\u0442\u0430\u0439");
304
+ }
305
+ });
306
+ }
307
+ function useRuntimeBuilderList(id) {
308
+ return useQuery({
309
+ queryKey: builderKeys.runtimeList(id),
310
+ queryFn: () => client.getRuntimeBuilderList(id)
311
+ });
312
+ }
313
+ function useRuntimeBuilderListEntries(id, query) {
314
+ return useQuery({
315
+ queryKey: builderKeys.runtimeListEntries(id, query),
316
+ queryFn: () => client.listRuntimeBuilderListEntries(id, query),
317
+ placeholderData: keepPreviousData
318
+ });
319
+ }
320
+ function useSaveRuntimeBuilderFormEntry(formId) {
321
+ const queryClient = useQueryClient();
322
+ return useMutation({
323
+ mutationFn: (input) => client.createRuntimeBuilderFormEntry(formId, input),
324
+ onSuccess: () => {
325
+ queryClient.invalidateQueries({ queryKey: builderKeys.runtimeFormEntries(formId) });
326
+ queryClient.invalidateQueries({ queryKey: builderKeys.runtimeForm(formId) });
327
+ queryClient.invalidateQueries({ queryKey: ["builder", "runtime", "list"] });
328
+ }
329
+ });
330
+ }
331
+ function useRuntimeBuilderView(id, enabled = true) {
332
+ return useQuery({
333
+ queryKey: builderKeys.runtimeView(id),
334
+ queryFn: () => client.getRuntimeBuilderView(id),
335
+ enabled: Boolean(id) && enabled
336
+ });
337
+ }
338
+ function useBuilderViewEntries(id, query, enabled = true) {
339
+ return useQuery({
340
+ queryKey: builderKeys.entries(id, query),
341
+ queryFn: () => client.listBuilderViewEntries(id, query),
342
+ placeholderData: keepPreviousData,
343
+ enabled: Boolean(id) && enabled
344
+ });
345
+ }
346
+ function useSaveBuilderViewEntry(viewId) {
347
+ const queryClient = useQueryClient();
348
+ return useMutation({
349
+ mutationFn: ({ id, input }) => id ? client.updateBuilderViewEntry(viewId, id, input) : client.createBuilderViewEntry(
350
+ viewId,
351
+ input
352
+ ),
353
+ onSuccess: () => invalidateRuntimeViewEntries(queryClient, viewId)
354
+ });
355
+ }
356
+ function useCreateCompositeBuilderViewEntry(viewId) {
357
+ const queryClient = useQueryClient();
358
+ return useMutation({
359
+ mutationFn: (input) => client.createCompositeBuilderViewEntry(viewId, input),
360
+ onSuccess: () => invalidateRuntimeViewEntries(queryClient, viewId)
361
+ });
362
+ }
363
+ function useUpdateCompositeBuilderViewEntry(viewId) {
364
+ const queryClient = useQueryClient();
365
+ return useMutation({
366
+ mutationFn: ({
367
+ id,
368
+ input
369
+ }) => client.updateCompositeBuilderViewEntry(viewId, id, input),
370
+ onSuccess: () => invalidateRuntimeViewEntries(queryClient, viewId)
371
+ });
372
+ }
373
+ function useDeleteBuilderViewEntry(id) {
374
+ const queryClient = useQueryClient();
375
+ return useMutation({
376
+ mutationFn: (entryId) => client.deleteBuilderViewEntry(id, entryId),
377
+ onSuccess: () => invalidateRuntimeViewEntries(queryClient, id)
378
+ });
379
+ }
380
+ return {
381
+ builderKeys,
382
+ useBuilderDbTables,
383
+ useBuilderForm,
384
+ useBuilderFormOptions,
385
+ useBuilderForms,
386
+ useBuilderList,
387
+ useBuilderListOptions,
388
+ useBuilderLists,
389
+ useBuilderViewEntries,
390
+ useBuilderView,
391
+ useBuilderViews,
392
+ useDeleteBuilderForm,
393
+ useDeleteBuilderList,
394
+ useDeleteBuilderView,
395
+ useDeleteBuilderViewEntry,
396
+ useCreateCompositeBuilderViewEntry,
397
+ useReplicateBuilderForm,
398
+ useReplicateBuilderList,
399
+ useReplicateBuilderView,
400
+ useRuntimeBuilderForm,
401
+ useRuntimeBuilderFormFieldOptions,
402
+ useRuntimeBuilderList,
403
+ useRuntimeBuilderListEntries,
404
+ useRuntimeBuilderView,
405
+ useRunRuntimeBuilderFieldTrigger,
406
+ useSaveBuilderForm,
407
+ useSaveBuilderList,
408
+ useSaveBuilderView,
409
+ useSaveBuilderViewEntry,
410
+ useSaveRuntimeBuilderFormEntry,
411
+ useUpdateCompositeBuilderViewEntry
412
+ };
413
+ }
414
+
415
+ // src/ready/BuilderProvider.tsx
416
+ import { jsx, jsxs } from "react/jsx-runtime";
417
+ function createBuilderClient({ transport, apiBasePath }) {
418
+ return createBuilderApiClient(transport, { apiBasePath });
419
+ }
420
+ var BuilderContext = createContext(null);
421
+ function BuilderProvider({
422
+ children,
423
+ client: configuredClient,
424
+ transport,
425
+ apiBasePath,
426
+ queryClient,
427
+ onNotify
428
+ }) {
429
+ if (!configuredClient && !transport) {
430
+ throw new Error("BuilderProvider-\u0434 client \u044D\u0441\u0432\u044D\u043B transport \u04E9\u0433\u043D\u04E9 \u04AF\u04AF.");
431
+ }
432
+ const internalClient = useMemo(
433
+ () => configuredClient ?? createBuilderClient({ transport, apiBasePath }),
434
+ [apiBasePath, configuredClient, transport]
435
+ );
436
+ const hooks = useMemo(() => createBuilderHooks(internalClient), [internalClient]);
437
+ const [notifications, setNotifications] = useState([]);
438
+ const notificationId = useRef(0);
439
+ const notify = useCallback((notification) => {
440
+ const id = ++notificationId.current;
441
+ setNotifications((current) => [...current.slice(-2), { ...notification, id }]);
442
+ onNotify?.(notification);
443
+ }, [onNotify]);
444
+ const internalQueryClient = useRef(null);
445
+ if (!internalQueryClient.current) internalQueryClient.current = queryClient ?? new QueryClient();
446
+ const value = useMemo(
447
+ () => ({ client: internalClient, hooks, notify }),
448
+ [hooks, internalClient, notify]
449
+ );
450
+ return /* @__PURE__ */ jsx(QueryClientProvider, { client: internalQueryClient.current, children: /* @__PURE__ */ jsxs(BuilderContext.Provider, { value, children: [
451
+ children,
452
+ /* @__PURE__ */ jsx("div", { className: "builder-notifications", "aria-live": "polite", "aria-atomic": "true", children: notifications.map((notification) => /* @__PURE__ */ jsxs("div", { className: `builder-notification builder-notification--${notification.type}`, children: [
453
+ /* @__PURE__ */ jsx("span", { children: notification.message }),
454
+ /* @__PURE__ */ jsx("button", { type: "button", "aria-label": "\u041C\u044D\u0434\u044D\u0433\u0434\u044D\u043B \u0445\u0430\u0430\u0445", onClick: () => setNotifications((current) => current.filter((item) => item.id !== notification.id)), children: "\xD7" })
455
+ ] }, notification.id)) })
456
+ ] }) });
457
+ }
458
+ function useBuilderRuntime() {
459
+ const context = useContext(BuilderContext);
460
+ if (!context) throw new Error("Builder component-\u0438\u0439\u0433 BuilderProvider \u0434\u043E\u0442\u043E\u0440 render \u0445\u0438\u0439\u043D\u044D \u04AF\u04AF.");
461
+ return context;
462
+ }
463
+ function builderErrorMessage(error, fallback) {
464
+ if (error instanceof Error && error.message.trim()) return error.message;
465
+ return fallback;
466
+ }
467
+
468
+ // src/ready/BuilderRuntimeComponents.tsx
469
+ import { useMemo as useMemo4, useState as useState4 } from "react";
470
+ import { FormProvider as FormProvider2, useForm as useForm2 } from "react-hook-form";
471
+
472
+ // src/runtime/runtimeUtils.ts
473
+ function emptyFieldValue(field) {
474
+ return field.type === "checkbox" ? false : "";
475
+ }
476
+ function createBuilderFormDefaultValues(schema) {
477
+ const values = {};
478
+ for (const field of schema?.fields ?? []) {
479
+ values[field.key] = emptyFieldValue(field);
480
+ }
481
+ return { values };
482
+ }
483
+ function createBuilderEntryDefaultValues(view, editing) {
484
+ const values = {};
485
+ for (const field of view.form?.schema.fields ?? []) {
486
+ const existing = editing?.values[field.key];
487
+ values[field.key] = existing === void 0 ? emptyFieldValue(field) : existing;
488
+ }
489
+ return { values, version: editing?.version ?? 0 };
490
+ }
491
+ function formatBuilderRuntimeValue(value, locale = "mn-MN") {
492
+ if (value === null || value === void 0 || value === "") return "\u2014";
493
+ if (typeof value === "boolean") return value ? "\u0422\u0438\u0439\u043C" : "\u04AE\u0433\u04AF\u0439";
494
+ if (typeof value === "number") return new Intl.NumberFormat(locale).format(value);
495
+ return String(value);
496
+ }
497
+
498
+ // src/ready/ReadyFields.tsx
499
+ import { useRef as useRef2 } from "react";
500
+ import { useFormContext, useWatch } from "react-hook-form";
501
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
502
+ function inputType(field) {
503
+ if (field.type === "date") return "date";
504
+ if (field.type === "number" || field.type === "money") return "number";
505
+ return "text";
506
+ }
507
+ function ReadyField({ field, formId, viewId }) {
508
+ const { hooks, notify } = useBuilderRuntime();
509
+ const form = useFormContext();
510
+ const values = useWatch({ control: form.control, name: "values" }) ?? {};
511
+ const timer = useRef2(null);
512
+ const source = field.optionsSource;
513
+ const dependencyValue = source?.filterBy ? values[source.filterBy.valueFromField] : void 0;
514
+ const depends = source?.filterBy && dependencyValue != null ? { [source.filterBy.valueFromField]: String(dependencyValue) } : void 0;
515
+ const optionsQuery = hooks.useRuntimeBuilderFormFieldOptions(
516
+ formId,
517
+ field.key,
518
+ { depends },
519
+ Boolean(source)
520
+ );
521
+ const trigger = hooks.useRunRuntimeBuilderFieldTrigger();
522
+ const name = `values.${field.key}`;
523
+ if (field.hidden) return null;
524
+ const runTrigger = (event, value) => {
525
+ const definition = field.triggers.find((item) => item.enabled && item.event === event);
526
+ if (!definition) return;
527
+ const execute = async () => {
528
+ try {
529
+ const response = await trigger.mutateAsync({
530
+ formId,
531
+ viewId,
532
+ fieldKey: field.key,
533
+ event,
534
+ input: { value, values: form.getValues("values") }
535
+ });
536
+ for (const [key, patchedValue] of Object.entries(response.valuesPatch)) {
537
+ form.setValue(`values.${key}`, patchedValue, { shouldDirty: true, shouldValidate: true });
538
+ }
539
+ for (const [key, message] of Object.entries(response.fieldErrors)) {
540
+ form.setError(`values.${key}`, { message });
541
+ }
542
+ if (response.toast?.message) notify(response.toast);
543
+ } catch (error2) {
544
+ notify({ type: "error", message: builderErrorMessage(error2, "Field action \u0430\u0436\u0438\u043B\u043B\u0430\u0441\u0430\u043D\u0433\u04AF\u0439") });
545
+ }
546
+ };
547
+ if (event === "onChange" && definition.debounceMs > 0) {
548
+ if (timer.current) clearTimeout(timer.current);
549
+ timer.current = setTimeout(() => void execute(), definition.debounceMs);
550
+ } else {
551
+ void execute();
552
+ }
553
+ };
554
+ const registration = form.register(name, {
555
+ required: field.required ? `${field.label} \u0448\u0430\u0430\u0440\u0434\u043B\u0430\u0433\u0430\u0442\u0430\u0439` : false,
556
+ setValueAs: field.type === "number" || field.type === "money" ? (value) => value === "" ? "" : Number(value) : void 0,
557
+ onChange: (event) => runTrigger("onChange", event.target.type === "checkbox" ? event.target.checked : event.target.value),
558
+ onBlur: (event) => runTrigger("onBlur", event.target.value)
559
+ });
560
+ const error = form.formState.errors.values?.[field.key];
561
+ const options = source ? optionsQuery.data ?? [] : field.options ?? [];
562
+ return /* @__PURE__ */ jsxs2("label", { className: "builder-field", children: [
563
+ /* @__PURE__ */ jsxs2("span", { className: "builder-field__label", children: [
564
+ field.label,
565
+ field.required ? /* @__PURE__ */ jsx2("span", { "aria-hidden": "true", children: " *" }) : null
566
+ ] }),
567
+ field.type === "textarea" ? /* @__PURE__ */ jsx2("textarea", { className: "builder-input builder-textarea", placeholder: field.placeholder, disabled: field.disabled, ...registration }) : field.type === "select" ? /* @__PURE__ */ jsxs2("select", { className: "builder-input", disabled: field.disabled || optionsQuery.isPending, ...registration, children: [
568
+ /* @__PURE__ */ jsx2("option", { value: "", children: field.placeholder ?? "\u0421\u043E\u043D\u0433\u043E\u0445" }),
569
+ options.map((option) => /* @__PURE__ */ jsx2("option", { value: option.value, children: option.label }, option.value))
570
+ ] }) : field.type === "checkbox" ? /* @__PURE__ */ jsx2("input", { className: "builder-checkbox", type: "checkbox", disabled: field.disabled, ...registration }) : /* @__PURE__ */ jsx2("input", { className: "builder-input", type: inputType(field), placeholder: field.placeholder, disabled: field.disabled, ...registration }),
571
+ field.description ? /* @__PURE__ */ jsx2("small", { className: "builder-field__description", children: field.description }) : null,
572
+ typeof error?.message === "string" ? /* @__PURE__ */ jsx2("small", { className: "builder-field__error", children: error.message }) : null
573
+ ] });
574
+ }
575
+ function ReadyFields({ formId, viewId, schema, extraItems = [] }) {
576
+ const fields = new Map(schema.fields.map((field) => [field.key, field]));
577
+ const rendered = /* @__PURE__ */ new Set();
578
+ return /* @__PURE__ */ jsxs2("div", { className: "builder-form-fields", children: [
579
+ schema.layout?.groups.map((group) => /* @__PURE__ */ jsxs2("fieldset", { className: "builder-fieldset", children: [
580
+ group.title ? /* @__PURE__ */ jsx2("legend", { children: group.title }) : null,
581
+ /* @__PURE__ */ jsx2("div", { className: "builder-form-grid", children: group.fields.map((item) => {
582
+ const field = fields.get(item.key);
583
+ if (!field) return null;
584
+ rendered.add(field.key);
585
+ return /* @__PURE__ */ jsx2("div", { style: { gridColumn: `span ${item.span}` }, children: /* @__PURE__ */ jsx2(ReadyField, { field, formId, viewId }) }, field.key);
586
+ }) })
587
+ ] }, group.id)),
588
+ /* @__PURE__ */ jsx2("div", { className: "builder-form-grid", children: schema.fields.filter((field) => !rendered.has(field.key)).map((field) => /* @__PURE__ */ jsx2("div", { style: { gridColumn: "span 12" }, children: /* @__PURE__ */ jsx2(ReadyField, { field, formId, viewId }) }, field.key)) }),
589
+ extraItems.map((item) => /* @__PURE__ */ jsx2("div", { children: item.render() }, item.key))
590
+ ] });
591
+ }
592
+
593
+ // src/ready/ReadyOverlay.tsx
594
+ import { useEffect, useId, useRef as useRef3 } from "react";
595
+ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
596
+ function ReadyOverlay({
597
+ open,
598
+ presentation = "dialog",
599
+ title,
600
+ description,
601
+ onClose,
602
+ children
603
+ }) {
604
+ const panelRef = useRef3(null);
605
+ const onCloseRef = useRef3(onClose);
606
+ onCloseRef.current = onClose;
607
+ const titleId = useId();
608
+ useEffect(() => {
609
+ if (!open) return;
610
+ const previous = document.activeElement;
611
+ panelRef.current?.focus();
612
+ const onKeyDown = (event) => {
613
+ if (event.key === "Escape") onCloseRef.current();
614
+ if (event.key === "Tab") {
615
+ const focusable = Array.from(
616
+ panelRef.current?.querySelectorAll(
617
+ "button:not([disabled]),a[href],input:not([disabled]),select:not([disabled]),textarea:not([disabled]),[tabindex]:not([tabindex='-1'])"
618
+ ) ?? []
619
+ );
620
+ const first = focusable[0];
621
+ const last = focusable.at(-1);
622
+ if (event.shiftKey && document.activeElement === first && last) {
623
+ event.preventDefault();
624
+ last.focus();
625
+ } else if (!event.shiftKey && document.activeElement === last && first) {
626
+ event.preventDefault();
627
+ first.focus();
628
+ }
629
+ }
630
+ };
631
+ document.addEventListener("keydown", onKeyDown);
632
+ const overflow = document.body.style.overflow;
633
+ document.body.style.overflow = "hidden";
634
+ return () => {
635
+ document.removeEventListener("keydown", onKeyDown);
636
+ document.body.style.overflow = overflow;
637
+ previous?.focus();
638
+ };
639
+ }, [open]);
640
+ if (!open) return null;
641
+ return /* @__PURE__ */ jsx3("div", { className: "builder-overlay", role: "presentation", onMouseDown: (event) => event.target === event.currentTarget && onClose(), children: /* @__PURE__ */ jsxs3(
642
+ "div",
643
+ {
644
+ ref: panelRef,
645
+ className: `builder-overlay__panel builder-overlay__panel--${presentation}`,
646
+ role: "dialog",
647
+ "aria-modal": "true",
648
+ "aria-labelledby": titleId,
649
+ tabIndex: -1,
650
+ children: [
651
+ /* @__PURE__ */ jsxs3("header", { className: "builder-overlay__header", children: [
652
+ /* @__PURE__ */ jsxs3("div", { children: [
653
+ /* @__PURE__ */ jsx3("h2", { id: titleId, className: "builder-title", children: title }),
654
+ description ? /* @__PURE__ */ jsx3("p", { className: "builder-description", children: description }) : null
655
+ ] }),
656
+ /* @__PURE__ */ jsx3("button", { type: "button", className: "builder-icon-button", "aria-label": "\u0425\u0430\u0430\u0445", onClick: onClose, children: "\xD7" })
657
+ ] }),
658
+ /* @__PURE__ */ jsx3("div", { className: "builder-overlay__body", children })
659
+ ]
660
+ }
661
+ ) });
662
+ }
663
+ function ReadyConfirmDialog({
664
+ open,
665
+ title,
666
+ description,
667
+ confirmLabel = "\u0423\u0441\u0442\u0433\u0430\u0445",
668
+ isPending,
669
+ onClose,
670
+ onConfirm
671
+ }) {
672
+ return /* @__PURE__ */ jsx3(ReadyOverlay, { open, title, description, onClose, children: /* @__PURE__ */ jsxs3("div", { className: "builder-actions", children: [
673
+ /* @__PURE__ */ jsx3("button", { type: "button", className: "builder-button builder-button--ghost", onClick: onClose, children: "\u0411\u043E\u043B\u0438\u0445" }),
674
+ /* @__PURE__ */ jsx3("button", { type: "button", className: "builder-button builder-button--danger", disabled: isPending, onClick: onConfirm, children: isPending ? "\u0422\u04AF\u0440 \u0445\u04AF\u043B\u044D\u044D\u043D\u044D \u04AF\u04AF\u2026" : confirmLabel })
675
+ ] }) });
676
+ }
677
+ function ReadyErrorState({ title, description }) {
678
+ return /* @__PURE__ */ jsxs3("div", { className: "builder-state builder-state--error", role: "alert", children: [
679
+ /* @__PURE__ */ jsx3("strong", { children: title }),
680
+ /* @__PURE__ */ jsx3("span", { children: description })
681
+ ] });
682
+ }
683
+
684
+ // src/ready/ReadySubform.tsx
685
+ import { useEffect as useEffect2, useMemo as useMemo3, useRef as useRef4, useState as useState3 } from "react";
686
+ import { FormProvider, useForm } from "react-hook-form";
687
+
688
+ // src/ready/ReadyTable.tsx
689
+ import { useMemo as useMemo2, useState as useState2 } from "react";
690
+ import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
691
+ function useReadyTableState({ pageSize = 20 } = {}) {
692
+ const [page, setPage] = useState2(1);
693
+ const [search, setSearchValue] = useState2("");
694
+ const [sort, setSort] = useState2();
695
+ return {
696
+ query: { page, pageSize, search: search || void 0, sort },
697
+ page,
698
+ pageSize,
699
+ search,
700
+ sort,
701
+ setPage,
702
+ setSearch(searchValue) {
703
+ setSearchValue(searchValue);
704
+ setPage(1);
705
+ },
706
+ toggleSort(key) {
707
+ setSort((current) => current === key ? `-${key}` : key);
708
+ setPage(1);
709
+ }
710
+ };
711
+ }
712
+ function useReadyTable(args) {
713
+ const [selectedIds, setSelectedIds] = useState2([]);
714
+ return useMemo2(
715
+ () => ({
716
+ ...args,
717
+ selectedIds,
718
+ toggleSelected(id) {
719
+ setSelectedIds(
720
+ (current) => current.includes(id) ? current.filter((value) => value !== id) : [...current, id]
721
+ );
722
+ },
723
+ clearSelection() {
724
+ setSelectedIds([]);
725
+ }
726
+ }),
727
+ [args.columns, args.data, args.rowCount, args.state, selectedIds]
728
+ );
729
+ }
730
+ function cellValue(entry, column) {
731
+ if (column.render) return column.render(entry);
732
+ return formatBuilderRuntimeValue(entry.values[column.key]);
733
+ }
734
+ function ReadyDataGrid({
735
+ title,
736
+ description,
737
+ controller,
738
+ isLoading,
739
+ searchPlaceholder = "\u0425\u0430\u0439\u0445...",
740
+ emptyTitle = "\u041C\u044D\u0434\u044D\u044D\u043B\u044D\u043B \u0430\u043B\u0433\u0430",
741
+ emptyDescription,
742
+ onRowClick,
743
+ toolbarExtra,
744
+ selectable = false
745
+ }) {
746
+ const totalPages = Math.max(1, Math.ceil(controller.rowCount / controller.state.pageSize));
747
+ return /* @__PURE__ */ jsxs4("section", { className: "builder-card builder-grid", "aria-busy": isLoading || void 0, children: [
748
+ /* @__PURE__ */ jsxs4("header", { className: "builder-grid__header", children: [
749
+ /* @__PURE__ */ jsxs4("div", { children: [
750
+ title ? /* @__PURE__ */ jsx4("h2", { className: "builder-title", children: title }) : null,
751
+ description ? /* @__PURE__ */ jsx4("p", { className: "builder-description", children: description }) : null
752
+ ] }),
753
+ /* @__PURE__ */ jsxs4("div", { className: "builder-grid__toolbar", children: [
754
+ /* @__PURE__ */ jsx4(
755
+ "input",
756
+ {
757
+ className: "builder-input builder-grid__search",
758
+ type: "search",
759
+ value: controller.state.search,
760
+ placeholder: searchPlaceholder,
761
+ "aria-label": searchPlaceholder,
762
+ onChange: (event) => controller.state.setSearch(event.target.value)
763
+ }
764
+ ),
765
+ toolbarExtra
766
+ ] })
767
+ ] }),
768
+ /* @__PURE__ */ jsxs4("div", { className: "builder-table-wrap", children: [
769
+ /* @__PURE__ */ jsxs4("table", { className: "builder-table", children: [
770
+ /* @__PURE__ */ jsx4("thead", { children: /* @__PURE__ */ jsxs4("tr", { children: [
771
+ selectable ? /* @__PURE__ */ jsx4("th", { "aria-label": "\u0421\u043E\u043D\u0433\u043E\u043B\u0442" }) : null,
772
+ controller.columns.map((column) => /* @__PURE__ */ jsx4("th", { className: `builder-align-${column.align}`, children: column.sortable ? /* @__PURE__ */ jsx4("button", { type: "button", className: "builder-sort", onClick: () => controller.state.toggleSort(column.key), children: column.label }) : column.label }, column.key))
773
+ ] }) }),
774
+ /* @__PURE__ */ jsx4("tbody", { children: controller.data.map((entry) => /* @__PURE__ */ jsxs4(
775
+ "tr",
776
+ {
777
+ className: onRowClick ? "builder-row-clickable" : void 0,
778
+ onClick: (event) => onRowClick?.(entry, event),
779
+ children: [
780
+ selectable ? /* @__PURE__ */ jsx4("td", { children: /* @__PURE__ */ jsx4(
781
+ "input",
782
+ {
783
+ type: "checkbox",
784
+ checked: controller.selectedIds.includes(entry.id),
785
+ "aria-label": "\u041C\u04E9\u0440 \u0441\u043E\u043D\u0433\u043E\u0445",
786
+ onClick: (event) => event.stopPropagation(),
787
+ onChange: () => controller.toggleSelected(entry.id)
788
+ }
789
+ ) }) : null,
790
+ controller.columns.map((column) => /* @__PURE__ */ jsx4("td", { className: `builder-align-${column.align}`, children: cellValue(entry, column) }, column.key))
791
+ ]
792
+ },
793
+ entry.id
794
+ )) })
795
+ ] }),
796
+ isLoading ? /* @__PURE__ */ jsx4("div", { className: "builder-state", children: "\u0423\u043D\u0448\u0438\u0436 \u0431\u0430\u0439\u043D\u0430\u2026" }) : null,
797
+ !isLoading && controller.data.length === 0 ? /* @__PURE__ */ jsxs4("div", { className: "builder-state", children: [
798
+ /* @__PURE__ */ jsx4("strong", { children: emptyTitle }),
799
+ emptyDescription ? /* @__PURE__ */ jsx4("span", { children: emptyDescription }) : null
800
+ ] }) : null
801
+ ] }),
802
+ /* @__PURE__ */ jsxs4("footer", { className: "builder-pagination", children: [
803
+ /* @__PURE__ */ jsxs4("span", { children: [
804
+ controller.rowCount,
805
+ " \u043C\u04E9\u0440"
806
+ ] }),
807
+ /* @__PURE__ */ jsxs4("div", { children: [
808
+ /* @__PURE__ */ jsx4("button", { type: "button", className: "builder-button builder-button--ghost", disabled: controller.state.page <= 1, onClick: () => controller.state.setPage(controller.state.page - 1), children: "\u04E8\u043C\u043D\u04E9\u0445" }),
809
+ /* @__PURE__ */ jsxs4("span", { children: [
810
+ controller.state.page,
811
+ " / ",
812
+ totalPages
813
+ ] }),
814
+ /* @__PURE__ */ jsx4("button", { type: "button", className: "builder-button builder-button--ghost", disabled: controller.state.page >= totalPages, onClick: () => controller.state.setPage(controller.state.page + 1), children: "\u0414\u0430\u0440\u0430\u0430\u0445" })
815
+ ] })
816
+ ] })
817
+ ] });
818
+ }
819
+ function readyColumns(columns) {
820
+ return columns.map((column) => ({ ...column }));
821
+ }
822
+
823
+ // src/ready/ReadySubform.tsx
824
+ import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
825
+ function linkedValue(entry, field) {
826
+ if (!entry) return void 0;
827
+ const value = field === "id" ? entry.id : entry.values[field];
828
+ return typeof value === "string" || typeof value === "number" ? String(value) : void 0;
829
+ }
830
+ function dataKey(viewId, tableName) {
831
+ return tableName?.trim() || viewId;
832
+ }
833
+ function makeDraftEntry(viewId, values, editing) {
834
+ const now = (/* @__PURE__ */ new Date()).toISOString();
835
+ return {
836
+ id: editing?.id ?? (globalThis.crypto?.randomUUID?.() ?? `draft-${Date.now()}`),
837
+ viewId,
838
+ values: editing ? values.values : { ...values.values, _draftNew: true },
839
+ version: editing?.version ?? 0,
840
+ createdAt: editing?.createdAt ?? now,
841
+ updatedAt: now
842
+ };
843
+ }
844
+ function ReadySubform({ subform, parentEntry, rows, onRowsChange }) {
845
+ const { hooks, notify } = useBuilderRuntime();
846
+ const [open, setOpen] = useState3(false);
847
+ const [editing, setEditing] = useState3(null);
848
+ const initialized = useRef4(false);
849
+ const parentValue = linkedValue(parentEntry, subform.parentField);
850
+ const viewQuery = hooks.useRuntimeBuilderView(subform.viewId, Boolean(subform.viewId));
851
+ const tableState = useReadyTableState({ pageSize: 100 });
852
+ const filterQuery = useMemo3(
853
+ () => ({ ...tableState.query, filterField: subform.childField, filterValue: parentValue ?? "" }),
854
+ [parentValue, subform.childField, tableState.query]
855
+ );
856
+ const entriesQuery = hooks.useBuilderViewEntries(subform.viewId, filterQuery, Boolean(parentValue));
857
+ const view = viewQuery.data;
858
+ const source = view?.list?.source?.type === "dbTable" ? view.list.source.tableName : void 0;
859
+ useEffect2(() => {
860
+ if (initialized.current || !view || !entriesQuery.data || !parentValue) return;
861
+ initialized.current = true;
862
+ onRowsChange({ key: subform.key, dataKey: dataKey(view.id, source), rows: entriesQuery.data.items });
863
+ }, [entriesQuery.data, onRowsChange, parentValue, source, subform.key, view]);
864
+ const visibleRows = rows.filter((row) => row.values._delete !== true);
865
+ const removeRow = (row) => {
866
+ initialized.current = true;
867
+ const nextRows = row.values._draftNew === true ? rows.filter((item) => item.id !== row.id) : rows.map((item) => item.id === row.id ? { ...item, values: { ...item.values, _delete: true } } : item);
868
+ onRowsChange({ key: subform.key, dataKey: dataKey(view?.id ?? subform.viewId, source), rows: nextRows });
869
+ notify({ type: "info", message: "Subform \u043C\u04E9\u0440 \u0443\u0441\u0442\u0433\u0430\u0445\u0430\u0430\u0440 \u0442\u044D\u043C\u0434\u044D\u0433\u043B\u044D\u0433\u0434\u043B\u044D\u044D" });
870
+ };
871
+ const columns = useMemo3(() => [
872
+ ...readyColumns(view?.list?.schema.columns ?? []),
873
+ {
874
+ key: "_actions",
875
+ label: "\u04AE\u0439\u043B\u0434\u044D\u043B",
876
+ sortable: false,
877
+ align: "right",
878
+ render: (row) => /* @__PURE__ */ jsx5("button", { type: "button", className: "builder-link builder-link--danger", onClick: (event) => {
879
+ event.stopPropagation();
880
+ removeRow(row);
881
+ }, children: "\u0423\u0441\u0442\u0433\u0430\u0445" })
882
+ }
883
+ ], [rows, source, subform.key, subform.viewId, view]);
884
+ const table = useReadyTable({
885
+ columns,
886
+ data: visibleRows,
887
+ rowCount: visibleRows.length,
888
+ state: tableState,
889
+ getRowId: (row) => row.id
890
+ });
891
+ const form = useForm({
892
+ defaultValues: createBuilderEntryDefaultValues(view ?? {}, editing),
893
+ values: open ? createBuilderEntryDefaultValues(view ?? {}, editing) : void 0
894
+ });
895
+ const close = () => {
896
+ setOpen(false);
897
+ setEditing(null);
898
+ };
899
+ const save = form.handleSubmit((values) => {
900
+ if (!view) return;
901
+ if (parentValue) values.values[subform.childField] = parentValue;
902
+ const next = makeDraftEntry(view.id, values, editing);
903
+ initialized.current = true;
904
+ onRowsChange({
905
+ key: subform.key,
906
+ dataKey: dataKey(view.id, source),
907
+ rows: editing ? rows.map((row) => row.id === editing.id ? next : row) : [...rows, next]
908
+ });
909
+ close();
910
+ });
911
+ if (viewQuery.isError) {
912
+ return /* @__PURE__ */ jsx5("div", { className: "builder-state builder-state--error", children: builderErrorMessage(viewQuery.error, `${subform.label} \u043D\u044D\u044D\u0433\u0434\u0441\u044D\u043D\u0433\u04AF\u0439`) });
913
+ }
914
+ return /* @__PURE__ */ jsxs5("section", { className: "builder-subform", children: [
915
+ /* @__PURE__ */ jsxs5("div", { className: "builder-subform__header", children: [
916
+ /* @__PURE__ */ jsx5("strong", { children: subform.label }),
917
+ /* @__PURE__ */ jsxs5("button", { type: "button", className: "builder-button builder-button--secondary", disabled: !view?.form, onClick: () => {
918
+ setEditing(null);
919
+ setOpen(true);
920
+ }, children: [
921
+ "+ ",
922
+ subform.buttonLabel ?? "\u041D\u044D\u043C\u044D\u0445"
923
+ ] })
924
+ ] }),
925
+ visibleRows.length > 0 || Boolean(parentValue) && entriesQuery.isPending ? /* @__PURE__ */ jsx5(
926
+ ReadyDataGrid,
927
+ {
928
+ controller: table,
929
+ isLoading: Boolean(parentValue) && entriesQuery.isPending,
930
+ onRowClick: (row) => {
931
+ setEditing(row);
932
+ setOpen(true);
933
+ },
934
+ emptyTitle: "\u041C\u04E9\u0440 \u0430\u043B\u0433\u0430"
935
+ }
936
+ ) : null,
937
+ view?.form ? /* @__PURE__ */ jsx5(ReadyOverlay, { open, presentation: subform.presentation, title: subform.label, description: view.title, onClose: close, children: /* @__PURE__ */ jsx5(FormProvider, { ...form, children: /* @__PURE__ */ jsxs5("form", { className: "builder-form", onSubmit: save, noValidate: true, children: [
938
+ /* @__PURE__ */ jsx5(ReadyFields, { formId: view.form.id, viewId: view.id, schema: view.form.schema }),
939
+ /* @__PURE__ */ jsxs5("div", { className: "builder-actions", children: [
940
+ /* @__PURE__ */ jsx5("button", { type: "button", className: "builder-button builder-button--ghost", onClick: close, children: "\u0411\u043E\u043B\u0438\u0445" }),
941
+ /* @__PURE__ */ jsx5("button", { type: "submit", className: "builder-button builder-button--primary", children: "\u0425\u0430\u0434\u0433\u0430\u043B\u0430\u0445" })
942
+ ] })
943
+ ] }) }) }) : null
944
+ ] });
945
+ }
946
+
947
+ // src/ready/BuilderRuntimeComponents.tsx
948
+ import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
949
+ function BuilderForm({ formId }) {
950
+ const { hooks, notify } = useBuilderRuntime();
951
+ const query = hooks.useRuntimeBuilderForm(formId);
952
+ const save = hooks.useSaveRuntimeBuilderFormEntry(formId);
953
+ const defaults = useMemo4(() => createBuilderFormDefaultValues(query.data?.schema), [query.data]);
954
+ const form = useForm2({ defaultValues: defaults, values: query.data ? defaults : void 0 });
955
+ if (query.isError) return /* @__PURE__ */ jsx6(ReadyErrorState, { title: "Form \u043D\u044D\u044D\u0433\u0434\u0441\u044D\u043D\u0433\u04AF\u0439", description: builderErrorMessage(query.error, `\xAB${formId}\xBB form \u043E\u043B\u0434\u0441\u043E\u043D\u0433\u04AF\u0439`) });
956
+ if (!query.data) return /* @__PURE__ */ jsx6("div", { className: "builder-state", children: "Form \u0443\u043D\u0448\u0438\u0436 \u0431\u0430\u0439\u043D\u0430\u2026" });
957
+ const submit = form.handleSubmit(async (input) => {
958
+ try {
959
+ await save.mutateAsync(input);
960
+ form.reset(defaults);
961
+ notify({ type: "success", message: "Form \u0445\u0430\u0434\u0433\u0430\u043B\u0430\u0433\u0434\u043B\u0430\u0430" });
962
+ } catch (error) {
963
+ notify({ type: "error", message: builderErrorMessage(error, "\u0425\u0430\u0434\u0433\u0430\u043B\u0430\u0445\u0430\u0434 \u0430\u043B\u0434\u0430\u0430 \u0433\u0430\u0440\u043B\u0430\u0430") });
964
+ }
965
+ });
966
+ return /* @__PURE__ */ jsxs6("section", { className: "builder-card", children: [
967
+ /* @__PURE__ */ jsx6("h2", { className: "builder-title", children: query.data.title }),
968
+ query.data.description ? /* @__PURE__ */ jsx6("p", { className: "builder-description", children: query.data.description }) : null,
969
+ /* @__PURE__ */ jsx6(FormProvider2, { ...form, children: /* @__PURE__ */ jsxs6("form", { className: "builder-form", onSubmit: submit, noValidate: true, children: [
970
+ /* @__PURE__ */ jsx6(ReadyFields, { formId, schema: query.data.schema }),
971
+ /* @__PURE__ */ jsx6("div", { className: "builder-actions", children: /* @__PURE__ */ jsx6("button", { className: "builder-button builder-button--primary", type: "submit", disabled: save.isPending, children: save.isPending ? "\u0425\u0430\u0434\u0433\u0430\u043B\u0436 \u0431\u0430\u0439\u043D\u0430\u2026" : "\u0425\u0430\u0434\u0433\u0430\u043B\u0430\u0445" }) })
972
+ ] }) })
973
+ ] });
974
+ }
975
+ function BuilderGrid({ listId }) {
976
+ const { hooks } = useBuilderRuntime();
977
+ const listQuery = hooks.useRuntimeBuilderList(listId);
978
+ const state = useReadyTableState();
979
+ const entriesQuery = hooks.useRuntimeBuilderListEntries(listId, state.query);
980
+ const table = useReadyTable({
981
+ columns: readyColumns(listQuery.data?.schema.columns ?? []),
982
+ data: entriesQuery.data?.items ?? [],
983
+ rowCount: entriesQuery.data?.total ?? 0,
984
+ state,
985
+ getRowId: (row) => row.id
986
+ });
987
+ if (listQuery.isError) return /* @__PURE__ */ jsx6(ReadyErrorState, { title: "Grid \u043D\u044D\u044D\u0433\u0434\u0441\u044D\u043D\u0433\u04AF\u0439", description: builderErrorMessage(listQuery.error, `\xAB${listId}\xBB list \u043E\u043B\u0434\u0441\u043E\u043D\u0433\u04AF\u0439`) });
988
+ return /* @__PURE__ */ jsx6(ReadyDataGrid, { title: listQuery.data?.title ?? "Grid", description: listQuery.data?.description, controller: table, isLoading: listQuery.isPending || entriesQuery.isPending });
989
+ }
990
+ function dbTableName(view) {
991
+ if (view.list?.source?.type === "dbTable") return view.list.source.tableName;
992
+ if (view.form?.source?.type === "dbTable") return view.form.source.tableName;
993
+ return void 0;
994
+ }
995
+ function childPayload(row, includeIdentity) {
996
+ const values = Object.fromEntries(Object.entries(row.values).filter(([key]) => key === "_delete" || !key.startsWith("_")));
997
+ return includeIdentity && row.values._draftNew !== true ? { id: row.id, version: row.version, ...values } : values;
998
+ }
999
+ function BuilderEntryEditor({ view, editing, open, onClose }) {
1000
+ const { hooks, notify } = useBuilderRuntime();
1001
+ const [subforms, setSubforms] = useState4({});
1002
+ const save = hooks.useSaveBuilderViewEntry(view.id);
1003
+ const createComposite = hooks.useCreateCompositeBuilderViewEntry(view.id);
1004
+ const updateComposite = hooks.useUpdateCompositeBuilderViewEntry(view.id);
1005
+ const defaults = useMemo4(() => createBuilderEntryDefaultValues(view, editing), [editing, view]);
1006
+ const form = useForm2({ defaultValues: defaults, values: open ? defaults : void 0 });
1007
+ const close = () => {
1008
+ setSubforms({});
1009
+ onClose();
1010
+ };
1011
+ const submit = form.handleSubmit(async (input) => {
1012
+ try {
1013
+ const mainKey = dbTableName(view);
1014
+ const hasSubformRows = Object.values(subforms).some((item) => item.rows.length > 0);
1015
+ if (hasSubformRows && mainKey) {
1016
+ const children = Object.fromEntries(Object.values(subforms).map((item) => [item.dataKey, item.rows.map((row) => childPayload(row, Boolean(editing)))]));
1017
+ if (editing) {
1018
+ await updateComposite.mutateAsync({ id: editing.id, input: { data: { [mainKey]: { id: editing.id, version: input.version, ...input.values }, ...children } } });
1019
+ } else {
1020
+ await createComposite.mutateAsync({ data: { [mainKey]: input.values, ...children } });
1021
+ }
1022
+ } else {
1023
+ await save.mutateAsync({ id: editing?.id, input });
1024
+ }
1025
+ notify({ type: "success", message: editing ? "\u041C\u04E9\u0440 \u0445\u0430\u0434\u0433\u0430\u043B\u0430\u0433\u0434\u043B\u0430\u0430" : "\u041C\u04E9\u0440 \u043D\u044D\u043C\u044D\u0433\u0434\u043B\u044D\u044D" });
1026
+ close();
1027
+ } catch (error) {
1028
+ notify({ type: "error", message: builderErrorMessage(error, "\u0425\u0430\u0434\u0433\u0430\u043B\u0430\u0445\u0430\u0434 \u0430\u043B\u0434\u0430\u0430 \u0433\u0430\u0440\u043B\u0430\u0430") });
1029
+ }
1030
+ });
1031
+ const saving = save.isPending || createComposite.isPending || updateComposite.isPending;
1032
+ const updateRows = ({ key, dataKey: dataKey2, rows }) => setSubforms((current) => ({ ...current, [key]: { dataKey: dataKey2, rows } }));
1033
+ return /* @__PURE__ */ jsx6(ReadyOverlay, { open, presentation: view.form?.schema.presentation, title: editing ? "\u041C\u04E9\u0440 \u0437\u0430\u0441\u0430\u0445" : "\u041C\u04E9\u0440 \u043D\u044D\u043C\u044D\u0445", description: view.title, onClose: close, children: view.form ? /* @__PURE__ */ jsx6(FormProvider2, { ...form, children: /* @__PURE__ */ jsxs6("form", { className: "builder-form", onSubmit: submit, noValidate: true, children: [
1034
+ /* @__PURE__ */ jsx6(ReadyFields, { formId: view.form.id, viewId: view.id, schema: view.form.schema }),
1035
+ view.form.schema.subforms.map((subform) => /* @__PURE__ */ jsx6(ReadySubform, { subform, parentEntry: editing, rows: subforms[subform.key]?.rows ?? [], onRowsChange: updateRows }, subform.key)),
1036
+ /* @__PURE__ */ jsxs6("div", { className: "builder-actions builder-actions--sticky", children: [
1037
+ /* @__PURE__ */ jsx6("button", { type: "button", className: "builder-button builder-button--ghost", onClick: close, children: "\u0411\u043E\u043B\u0438\u0445" }),
1038
+ /* @__PURE__ */ jsx6("button", { type: "submit", className: "builder-button builder-button--primary", disabled: saving, children: saving ? "\u0425\u0430\u0434\u0433\u0430\u043B\u0436 \u0431\u0430\u0439\u043D\u0430\u2026" : "\u0425\u0430\u0434\u0433\u0430\u043B\u0430\u0445" })
1039
+ ] })
1040
+ ] }) }) : /* @__PURE__ */ jsx6(ReadyErrorState, { title: "Form \u0445\u043E\u043B\u0431\u043E\u043E\u0433\u04AF\u0439", description: "\u042D\u043D\u044D view-\u0434 form \u0442\u043E\u0445\u0438\u0440\u0443\u0443\u043B\u0430\u0430\u0433\u04AF\u0439 \u0431\u0430\u0439\u043D\u0430." }) });
1041
+ }
1042
+ function BuilderView({ viewId }) {
1043
+ const { hooks, notify } = useBuilderRuntime();
1044
+ const [editing, setEditing] = useState4(null);
1045
+ const [editorOpen, setEditorOpen] = useState4(false);
1046
+ const [pendingDelete, setPendingDelete] = useState4(null);
1047
+ const viewQuery = hooks.useRuntimeBuilderView(viewId);
1048
+ const state = useReadyTableState();
1049
+ const entriesQuery = hooks.useBuilderViewEntries(viewId, state.query);
1050
+ const remove = hooks.useDeleteBuilderViewEntry(viewId);
1051
+ const view = viewQuery.data;
1052
+ const columns = useMemo4(() => {
1053
+ const result = readyColumns(view?.list?.schema.columns ?? []);
1054
+ if (!view) return result;
1055
+ result.push({
1056
+ key: "_actions",
1057
+ label: "\u04AE\u0439\u043B\u0434\u044D\u043B",
1058
+ sortable: false,
1059
+ align: "right",
1060
+ render: (entry) => /* @__PURE__ */ jsxs6("div", { className: "builder-row-actions", "data-builder-row-action": true, children: [
1061
+ /* @__PURE__ */ jsx6("button", { type: "button", className: "builder-button builder-button--ghost", onClick: (event) => {
1062
+ event.stopPropagation();
1063
+ setEditing(entry);
1064
+ setEditorOpen(true);
1065
+ }, children: "\u0417\u0430\u0441\u0430\u0445" }),
1066
+ /* @__PURE__ */ jsx6("button", { type: "button", className: "builder-button builder-button--danger", onClick: (event) => {
1067
+ event.stopPropagation();
1068
+ setPendingDelete(entry);
1069
+ }, children: "\u0423\u0441\u0442\u0433\u0430\u0445" })
1070
+ ] })
1071
+ });
1072
+ return result;
1073
+ }, [view]);
1074
+ const table = useReadyTable({ columns, data: entriesQuery.data?.items ?? [], rowCount: entriesQuery.data?.total ?? 0, state, getRowId: (row) => row.id });
1075
+ if (viewQuery.isError) return /* @__PURE__ */ jsx6(ReadyErrorState, { title: "View \u043D\u044D\u044D\u0433\u0434\u0441\u044D\u043D\u0433\u04AF\u0439", description: builderErrorMessage(viewQuery.error, `\xAB${viewId}\xBB view \u043E\u043B\u0434\u0441\u043E\u043D\u0433\u04AF\u0439`) });
1076
+ return /* @__PURE__ */ jsxs6("div", { className: "builder-runtime", children: [
1077
+ /* @__PURE__ */ jsx6(
1078
+ ReadyDataGrid,
1079
+ {
1080
+ title: view?.title ?? "View",
1081
+ description: view?.description,
1082
+ controller: table,
1083
+ isLoading: viewQuery.isPending || entriesQuery.isPending,
1084
+ onRowClick: (entry) => {
1085
+ setEditing(entry);
1086
+ setEditorOpen(true);
1087
+ },
1088
+ toolbarExtra: /* @__PURE__ */ jsx6("button", { type: "button", className: "builder-button builder-button--primary", disabled: !view?.form, onClick: () => {
1089
+ setEditing(null);
1090
+ setEditorOpen(true);
1091
+ }, children: "+ \u041D\u044D\u043C\u044D\u0445" })
1092
+ }
1093
+ ),
1094
+ view ? /* @__PURE__ */ jsx6(BuilderEntryEditor, { view, editing, open: editorOpen, onClose: () => setEditorOpen(false) }) : null,
1095
+ /* @__PURE__ */ jsx6(
1096
+ ReadyConfirmDialog,
1097
+ {
1098
+ open: Boolean(pendingDelete),
1099
+ title: "\u041C\u04E9\u0440 \u0443\u0441\u0442\u0433\u0430\u0445 \u0443\u0443?",
1100
+ description: "\u042D\u043D\u044D \u04AF\u0439\u043B\u0434\u043B\u0438\u0439\u0433 \u0431\u0443\u0446\u0430\u0430\u0445 \u0431\u043E\u043B\u043E\u043C\u0436\u0433\u04AF\u0439.",
1101
+ isPending: remove.isPending,
1102
+ onClose: () => setPendingDelete(null),
1103
+ onConfirm: () => {
1104
+ if (!pendingDelete) return;
1105
+ remove.mutate(pendingDelete.id, {
1106
+ onSuccess: () => {
1107
+ setPendingDelete(null);
1108
+ notify({ type: "success", message: "\u041C\u04E9\u0440 \u0443\u0441\u0442\u0433\u0430\u0433\u0434\u043B\u0430\u0430" });
1109
+ },
1110
+ onError: (error) => notify({ type: "error", message: builderErrorMessage(error, "\u0423\u0441\u0442\u0433\u0430\u0445\u0430\u0434 \u0430\u043B\u0434\u0430\u0430 \u0433\u0430\u0440\u043B\u0430\u0430") })
1111
+ });
1112
+ }
1113
+ }
1114
+ )
1115
+ ] });
1116
+ }
1117
+
1118
+ // src/admin/editorState.ts
1119
+ var BUILDER_EDITOR_NONE_VALUE = "__none";
1120
+ function builderEditorOptionsToText(options) {
1121
+ return (options ?? []).map((option) => `${option.label}:${option.value}`).join("\n");
1122
+ }
1123
+ function builderEditorTextToOptions(value) {
1124
+ const rows = (value ?? "").split("\n").map((line) => line.trim()).filter(Boolean);
1125
+ if (rows.length === 0) return void 0;
1126
+ return rows.map((line) => {
1127
+ const [label, ...rest] = line.split(":");
1128
+ return { label: label.trim(), value: rest.join(":").trim() || label.trim() };
1129
+ });
1130
+ }
1131
+ function builderEditorSearchFieldsToText(fields) {
1132
+ return (fields ?? []).join("\n");
1133
+ }
1134
+ function builderEditorTextToSearchFields(value) {
1135
+ const fields = (value ?? "").split("\n").map((line) => line.trim()).filter(Boolean);
1136
+ return fields.length > 0 ? fields : void 0;
1137
+ }
1138
+ function getBuilderEditorTriggerRoute(config) {
1139
+ const route = config.route ?? config.path ?? config.url;
1140
+ return typeof route === "string" ? route : "";
1141
+ }
1142
+ function valuesFromTriggers(triggers) {
1143
+ return triggers.filter((trigger) => trigger.action === "callApi" || trigger.action === "webhook").map((trigger) => ({
1144
+ event: trigger.event,
1145
+ route: getBuilderEditorTriggerRoute(trigger.config),
1146
+ enabled: trigger.enabled,
1147
+ blocking: trigger.blocking
1148
+ })).filter((trigger) => trigger.route);
1149
+ }
1150
+ function valuesFromFieldTriggers(triggers) {
1151
+ return (triggers ?? []).map((trigger) => ({
1152
+ event: trigger.event,
1153
+ action: trigger.action,
1154
+ enabled: trigger.enabled,
1155
+ debounceMs: trigger.debounceMs
1156
+ }));
1157
+ }
1158
+ function clampLayoutSpan(span, columns) {
1159
+ if (!span || Number.isNaN(span)) return columns;
1160
+ return Math.max(1, Math.min(columns, Math.trunc(span)));
1161
+ }
1162
+ function builderFormEditorDefaultSpan(field) {
1163
+ if (field.type === "textarea" || field.type === "checkbox") return 12;
1164
+ return 6;
1165
+ }
1166
+ function builderFormEditorDefaultLayoutGroups(fields, subforms = []) {
1167
+ return [
1168
+ {
1169
+ id: "main",
1170
+ title: "\u04AE\u043D\u0434\u0441\u044D\u043D",
1171
+ columns: 12,
1172
+ fields: [
1173
+ ...fields.map((field) => ({
1174
+ key: field.key,
1175
+ span: builderFormEditorDefaultSpan(field)
1176
+ })),
1177
+ ...subforms.map((subform) => ({ key: subform.key, span: 12 }))
1178
+ ]
1179
+ }
1180
+ ];
1181
+ }
1182
+ function normalizeBuilderFormEditorLayoutGroups(groups, fields, subforms = []) {
1183
+ if (fields.length === 0 && subforms.length === 0) return [];
1184
+ const layoutItems = [
1185
+ ...fields.map((field) => ({
1186
+ key: field.key,
1187
+ span: builderFormEditorDefaultSpan(field)
1188
+ })),
1189
+ ...subforms.map((subform) => ({ key: subform.key, span: 12 }))
1190
+ ];
1191
+ const itemKeys = new Set(layoutItems.map((item) => item.key));
1192
+ const usedKeys = /* @__PURE__ */ new Set();
1193
+ const normalized = (groups ?? []).map((group, index) => {
1194
+ const columns = group.columns === 6 || group.columns === 8 ? group.columns : 12;
1195
+ const groupFields = (group.fields ?? []).filter((field) => itemKeys.has(field.key) && !usedKeys.has(field.key)).map((field) => {
1196
+ usedKeys.add(field.key);
1197
+ return { key: field.key, span: clampLayoutSpan(field.span, columns) };
1198
+ });
1199
+ return {
1200
+ id: group.id || `group${index + 1}`,
1201
+ title: group.title || `Group ${index + 1}`,
1202
+ columns,
1203
+ fields: groupFields
1204
+ };
1205
+ }).filter((group) => group.fields.length > 0 || group.title.trim());
1206
+ const missingFields = layoutItems.filter((item) => !usedKeys.has(item.key));
1207
+ if (normalized.length === 0) {
1208
+ return builderFormEditorDefaultLayoutGroups(fields, subforms);
1209
+ }
1210
+ if (missingFields.length > 0) {
1211
+ normalized.push({
1212
+ id: "ungrouped",
1213
+ title: "\u0411\u0443\u0441\u0430\u0434",
1214
+ columns: 12,
1215
+ fields: missingFields
1216
+ });
1217
+ }
1218
+ return normalized;
1219
+ }
1220
+ function builderFormEditorValuesFromEntity(form, emptyValues) {
1221
+ if (!form) return emptyValues;
1222
+ const source = form.source;
1223
+ const fields = form.schema.fields.map((field) => ({
1224
+ key: field.key,
1225
+ label: field.label,
1226
+ type: field.type,
1227
+ required: field.required,
1228
+ hidden: field.hidden ?? false,
1229
+ disabled: field.disabled ?? false,
1230
+ placeholder: field.placeholder ?? "",
1231
+ optionsText: builderEditorOptionsToText(field.options),
1232
+ optionsMode: field.optionsSource?.type === "dbTable" ? "table" : "static",
1233
+ optionsTable: field.optionsSource?.type === "dbTable" ? field.optionsSource.tableName : BUILDER_EDITOR_NONE_VALUE,
1234
+ optionsValueField: field.optionsSource?.type === "dbTable" ? field.optionsSource.valueField : BUILDER_EDITOR_NONE_VALUE,
1235
+ optionsLabelField: field.optionsSource?.type === "dbTable" ? field.optionsSource.labelField : BUILDER_EDITOR_NONE_VALUE,
1236
+ optionsSearchFieldsText: field.optionsSource?.type === "dbTable" ? builderEditorSearchFieldsToText(field.optionsSource.searchFields) : "",
1237
+ optionsDependsOn: field.optionsSource?.type === "dbTable" ? field.optionsSource.filterBy?.valueFromField ?? "" : "",
1238
+ optionsFilterField: field.optionsSource?.type === "dbTable" ? field.optionsSource.filterBy?.field ?? "" : "",
1239
+ triggers: valuesFromFieldTriggers(field.triggers)
1240
+ }));
1241
+ const subforms = (form.schema.subforms ?? []).map((subform) => ({
1242
+ key: subform.key,
1243
+ label: subform.label,
1244
+ viewId: subform.viewId,
1245
+ parentField: subform.parentField,
1246
+ childField: subform.childField,
1247
+ buttonLabel: subform.buttonLabel ?? "",
1248
+ icon: subform.icon ?? "",
1249
+ presentation: subform.presentation ?? "dialog"
1250
+ }));
133
1251
  return {
134
1252
  title: form.title,
135
1253
  description: form.description ?? "",
1254
+ presentation: form.schema.presentation ?? "dialog",
136
1255
  sourceType: source?.type ?? "none",
137
1256
  sourceTable: source?.type === "dbTable" ? source.tableName : BUILDER_EDITOR_NONE_VALUE,
138
1257
  apiBasePath: source?.type === "apiEndpoint" ? source.basePath : "",
@@ -214,6 +1333,7 @@ function builderFormEditorInputFromValues(values) {
214
1333
  description: values.description || null,
215
1334
  source,
216
1335
  schema: {
1336
+ presentation: values.presentation ?? "dialog",
217
1337
  fields: values.fields.map((field) => ({
218
1338
  key: field.key,
219
1339
  label: field.label,
@@ -258,7 +1378,8 @@ function builderFormEditorInputFromValues(values) {
258
1378
  parentField: subform.parentField,
259
1379
  childField: subform.childField,
260
1380
  buttonLabel: subform.buttonLabel?.trim() || void 0,
261
- icon: subform.icon?.trim() || void 0
1381
+ icon: subform.icon?.trim() || void 0,
1382
+ presentation: subform.presentation ?? "dialog"
262
1383
  }))
263
1384
  },
264
1385
  triggers: values.triggers.map((trigger) => ({
@@ -302,7 +1423,7 @@ function builderViewEditorInputFromValues(values, parseTriggers) {
302
1423
  }
303
1424
 
304
1425
  // src/admin/BuilderDefaultEditorBodies.tsx
305
- import { jsx, jsxs } from "react/jsx-runtime";
1426
+ import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
306
1427
  var styles = {
307
1428
  page: {
308
1429
  display: "grid",
@@ -423,7 +1544,7 @@ var styles = {
423
1544
  }
424
1545
  };
425
1546
  function optionItems(options) {
426
- return options.map((option) => /* @__PURE__ */ jsx("option", { value: option.value, children: option.label }, option.value));
1547
+ return options.map((option) => /* @__PURE__ */ jsx7("option", { value: option.value, children: option.label }, option.value));
427
1548
  }
428
1549
  function createBuilderDefaultFormEditorBody(options) {
429
1550
  return function BuilderDefaultFormEditorBody({
@@ -441,48 +1562,55 @@ function createBuilderDefaultFormEditorBody(options) {
441
1562
  isSaving,
442
1563
  importFieldsFromTable
443
1564
  }) {
444
- return /* @__PURE__ */ jsxs("div", { style: styles.page, children: [
445
- /* @__PURE__ */ jsxs("div", { style: styles.header, children: [
446
- /* @__PURE__ */ jsxs("div", { children: [
447
- /* @__PURE__ */ jsx("h1", { style: styles.title, children: formId ? "Edit Dynamic Form" : "New Dynamic Form" }),
448
- /* @__PURE__ */ jsx("p", { style: styles.description, children: "Configure fields, source mapping, layout, and triggers." })
1565
+ return /* @__PURE__ */ jsxs7("div", { style: styles.page, children: [
1566
+ /* @__PURE__ */ jsxs7("div", { style: styles.header, children: [
1567
+ /* @__PURE__ */ jsxs7("div", { children: [
1568
+ /* @__PURE__ */ jsx7("h1", { style: styles.title, children: formId ? "Edit Dynamic Form" : "New Dynamic Form" }),
1569
+ /* @__PURE__ */ jsx7("p", { style: styles.description, children: "Configure fields, source mapping, layout, and triggers." })
449
1570
  ] }),
450
- /* @__PURE__ */ jsxs("div", { style: styles.actions, children: [
451
- /* @__PURE__ */ jsx("a", { href: options.backHref, style: styles.button, children: "Cancel" }),
452
- /* @__PURE__ */ jsx("button", { type: "submit", disabled: isSaving, style: styles.primaryButton, children: isSaving ? "Saving..." : "Save" })
1571
+ /* @__PURE__ */ jsxs7("div", { style: styles.actions, children: [
1572
+ /* @__PURE__ */ jsx7("a", { href: options.backHref, style: styles.button, children: "Cancel" }),
1573
+ /* @__PURE__ */ jsx7("button", { type: "submit", disabled: isSaving, style: styles.primaryButton, children: isSaving ? "Saving..." : "Save" })
453
1574
  ] })
454
1575
  ] }),
455
- /* @__PURE__ */ jsxs("section", { style: styles.section, children: [
456
- /* @__PURE__ */ jsx("div", { style: styles.sectionHeader, children: /* @__PURE__ */ jsx("h2", { style: styles.sectionTitle, children: "Details" }) }),
457
- /* @__PURE__ */ jsxs("div", { style: { ...styles.grid, ...styles.twoColumn }, children: [
458
- /* @__PURE__ */ jsxs("label", { style: styles.field, children: [
459
- /* @__PURE__ */ jsx("span", { style: styles.label, children: "Title" }),
460
- /* @__PURE__ */ jsx("input", { style: styles.input, ...form.register("title", { required: true }) })
1576
+ /* @__PURE__ */ jsxs7("section", { style: styles.section, children: [
1577
+ /* @__PURE__ */ jsx7("div", { style: styles.sectionHeader, children: /* @__PURE__ */ jsx7("h2", { style: styles.sectionTitle, children: "Details" }) }),
1578
+ /* @__PURE__ */ jsxs7("div", { style: { ...styles.grid, ...styles.twoColumn }, children: [
1579
+ /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1580
+ /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Title" }),
1581
+ /* @__PURE__ */ jsx7("input", { style: styles.input, ...form.register("title", { required: true }) })
461
1582
  ] }),
462
- /* @__PURE__ */ jsxs("label", { style: styles.field, children: [
463
- /* @__PURE__ */ jsx("span", { style: styles.label, children: "Description" }),
464
- /* @__PURE__ */ jsx("input", { style: styles.input, ...form.register("description") })
1583
+ /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1584
+ /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Description" }),
1585
+ /* @__PURE__ */ jsx7("input", { style: styles.input, ...form.register("description") })
465
1586
  ] }),
466
- /* @__PURE__ */ jsxs("label", { style: styles.field, children: [
467
- /* @__PURE__ */ jsx("span", { style: styles.label, children: "Datasource" }),
468
- /* @__PURE__ */ jsxs("select", { style: styles.input, ...form.register("sourceType"), children: [
469
- /* @__PURE__ */ jsx("option", { value: "none", children: "None" }),
470
- /* @__PURE__ */ jsx("option", { value: "dbTable", children: "DB table" }),
471
- /* @__PURE__ */ jsx("option", { value: "apiEndpoint", children: "API endpoint" })
1587
+ /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1588
+ /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Presentation" }),
1589
+ /* @__PURE__ */ jsxs7("select", { style: styles.input, ...form.register("presentation"), children: [
1590
+ /* @__PURE__ */ jsx7("option", { value: "dialog", children: "Dialog" }),
1591
+ /* @__PURE__ */ jsx7("option", { value: "drawer", children: "Drawer" })
472
1592
  ] })
473
1593
  ] }),
474
- sourceType === "dbTable" ? /* @__PURE__ */ jsxs("label", { style: styles.field, children: [
475
- /* @__PURE__ */ jsx("span", { style: styles.label, children: "Table" }),
476
- /* @__PURE__ */ jsxs("select", { style: styles.input, ...form.register("sourceTable"), children: [
477
- /* @__PURE__ */ jsx("option", { value: BUILDER_EDITOR_NONE_VALUE, children: "Select table" }),
478
- tables.map((table) => /* @__PURE__ */ jsx("option", { value: table.name, children: table.label ?? table.name }, table.name))
1594
+ /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1595
+ /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Datasource" }),
1596
+ /* @__PURE__ */ jsxs7("select", { style: styles.input, ...form.register("sourceType"), children: [
1597
+ /* @__PURE__ */ jsx7("option", { value: "none", children: "None" }),
1598
+ /* @__PURE__ */ jsx7("option", { value: "dbTable", children: "DB table" }),
1599
+ /* @__PURE__ */ jsx7("option", { value: "apiEndpoint", children: "API endpoint" })
1600
+ ] })
1601
+ ] }),
1602
+ sourceType === "dbTable" ? /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1603
+ /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Table" }),
1604
+ /* @__PURE__ */ jsxs7("select", { style: styles.input, ...form.register("sourceTable"), children: [
1605
+ /* @__PURE__ */ jsx7("option", { value: BUILDER_EDITOR_NONE_VALUE, children: "Select table" }),
1606
+ tables.map((table) => /* @__PURE__ */ jsx7("option", { value: table.name, children: table.label ?? table.name }, table.name))
479
1607
  ] })
480
1608
  ] }) : null,
481
- sourceType === "apiEndpoint" ? /* @__PURE__ */ jsxs("label", { style: styles.field, children: [
482
- /* @__PURE__ */ jsx("span", { style: styles.label, children: "API base path" }),
483
- /* @__PURE__ */ jsx("input", { style: styles.input, ...form.register("apiBasePath") })
1609
+ sourceType === "apiEndpoint" ? /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1610
+ /* @__PURE__ */ jsx7("span", { style: styles.label, children: "API base path" }),
1611
+ /* @__PURE__ */ jsx7("input", { style: styles.input, ...form.register("apiBasePath") })
484
1612
  ] }) : null,
485
- sourceType === "dbTable" ? /* @__PURE__ */ jsx("div", { style: { ...styles.field, justifyContent: "end" }, children: /* @__PURE__ */ jsx(
1613
+ sourceType === "dbTable" ? /* @__PURE__ */ jsx7("div", { style: { ...styles.field, justifyContent: "end" }, children: /* @__PURE__ */ jsx7(
486
1614
  "button",
487
1615
  {
488
1616
  type: "button",
@@ -494,13 +1622,13 @@ function createBuilderDefaultFormEditorBody(options) {
494
1622
  ) }) : null
495
1623
  ] })
496
1624
  ] }),
497
- /* @__PURE__ */ jsxs("section", { style: styles.section, children: [
498
- /* @__PURE__ */ jsxs("div", { style: styles.sectionHeader, children: [
499
- /* @__PURE__ */ jsxs("div", { children: [
500
- /* @__PURE__ */ jsx("h2", { style: styles.sectionTitle, children: "Fields" }),
501
- /* @__PURE__ */ jsx("p", { style: styles.description, children: "Runtime form inputs." })
1625
+ /* @__PURE__ */ jsxs7("section", { style: styles.section, children: [
1626
+ /* @__PURE__ */ jsxs7("div", { style: styles.sectionHeader, children: [
1627
+ /* @__PURE__ */ jsxs7("div", { children: [
1628
+ /* @__PURE__ */ jsx7("h2", { style: styles.sectionTitle, children: "Fields" }),
1629
+ /* @__PURE__ */ jsx7("p", { style: styles.description, children: "Runtime form inputs." })
502
1630
  ] }),
503
- /* @__PURE__ */ jsx(
1631
+ /* @__PURE__ */ jsx7(
504
1632
  "button",
505
1633
  {
506
1634
  type: "button",
@@ -518,18 +1646,18 @@ function createBuilderDefaultFormEditorBody(options) {
518
1646
  }
519
1647
  )
520
1648
  ] }),
521
- fieldArray.fields.map((field, index) => /* @__PURE__ */ jsxs("div", { style: styles.row, children: [
522
- /* @__PURE__ */ jsxs("label", { style: styles.field, children: [
523
- /* @__PURE__ */ jsx("span", { style: styles.label, children: "Key" }),
524
- /* @__PURE__ */ jsx("input", { style: styles.input, ...form.register(`fields.${index}.key`) })
1649
+ fieldArray.fields.map((field, index) => /* @__PURE__ */ jsxs7("div", { style: styles.row, children: [
1650
+ /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1651
+ /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Key" }),
1652
+ /* @__PURE__ */ jsx7("input", { style: styles.input, ...form.register(`fields.${index}.key`) })
525
1653
  ] }),
526
- /* @__PURE__ */ jsxs("label", { style: styles.field, children: [
527
- /* @__PURE__ */ jsx("span", { style: styles.label, children: "Label" }),
528
- /* @__PURE__ */ jsx("input", { style: styles.input, ...form.register(`fields.${index}.label`) })
1654
+ /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1655
+ /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Label" }),
1656
+ /* @__PURE__ */ jsx7("input", { style: styles.input, ...form.register(`fields.${index}.label`) })
529
1657
  ] }),
530
- /* @__PURE__ */ jsxs("label", { style: styles.field, children: [
531
- /* @__PURE__ */ jsx("span", { style: styles.label, children: "Type" }),
532
- /* @__PURE__ */ jsx(
1658
+ /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1659
+ /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Type" }),
1660
+ /* @__PURE__ */ jsx7(
533
1661
  "select",
534
1662
  {
535
1663
  style: styles.input,
@@ -538,27 +1666,27 @@ function createBuilderDefaultFormEditorBody(options) {
538
1666
  }
539
1667
  )
540
1668
  ] }),
541
- /* @__PURE__ */ jsxs("label", { style: styles.checkboxField, children: [
542
- /* @__PURE__ */ jsx("input", { type: "checkbox", ...form.register(`fields.${index}.required`) }),
1669
+ /* @__PURE__ */ jsxs7("label", { style: styles.checkboxField, children: [
1670
+ /* @__PURE__ */ jsx7("input", { type: "checkbox", ...form.register(`fields.${index}.required`) }),
543
1671
  "Required"
544
1672
  ] }),
545
- /* @__PURE__ */ jsxs("label", { style: styles.checkboxField, children: [
546
- /* @__PURE__ */ jsx("input", { type: "checkbox", ...form.register(`fields.${index}.hidden`) }),
1673
+ /* @__PURE__ */ jsxs7("label", { style: styles.checkboxField, children: [
1674
+ /* @__PURE__ */ jsx7("input", { type: "checkbox", ...form.register(`fields.${index}.hidden`) }),
547
1675
  "Hidden"
548
1676
  ] }),
549
- /* @__PURE__ */ jsxs("label", { style: styles.checkboxField, children: [
550
- /* @__PURE__ */ jsx("input", { type: "checkbox", ...form.register(`fields.${index}.disabled`) }),
1677
+ /* @__PURE__ */ jsxs7("label", { style: styles.checkboxField, children: [
1678
+ /* @__PURE__ */ jsx7("input", { type: "checkbox", ...form.register(`fields.${index}.disabled`) }),
551
1679
  "Disabled"
552
1680
  ] }),
553
- /* @__PURE__ */ jsxs("label", { style: styles.field, children: [
554
- /* @__PURE__ */ jsx("span", { style: styles.label, children: "Placeholder" }),
555
- /* @__PURE__ */ jsx("input", { style: styles.input, ...form.register(`fields.${index}.placeholder`) })
1681
+ /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1682
+ /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Placeholder" }),
1683
+ /* @__PURE__ */ jsx7("input", { style: styles.input, ...form.register(`fields.${index}.placeholder`) })
556
1684
  ] }),
557
- /* @__PURE__ */ jsxs("label", { style: styles.field, children: [
558
- /* @__PURE__ */ jsx("span", { style: styles.label, children: "Static options" }),
559
- /* @__PURE__ */ jsx("textarea", { style: styles.textarea, ...form.register(`fields.${index}.optionsText`) })
1685
+ /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1686
+ /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Static options" }),
1687
+ /* @__PURE__ */ jsx7("textarea", { style: styles.textarea, ...form.register(`fields.${index}.optionsText`) })
560
1688
  ] }),
561
- /* @__PURE__ */ jsx("div", { style: styles.actions, children: /* @__PURE__ */ jsx(
1689
+ /* @__PURE__ */ jsx7("div", { style: styles.actions, children: /* @__PURE__ */ jsx7(
562
1690
  "button",
563
1691
  {
564
1692
  type: "button",
@@ -570,13 +1698,13 @@ function createBuilderDefaultFormEditorBody(options) {
570
1698
  ) })
571
1699
  ] }, field.id))
572
1700
  ] }),
573
- /* @__PURE__ */ jsxs("section", { style: styles.section, children: [
574
- /* @__PURE__ */ jsxs("div", { style: styles.sectionHeader, children: [
575
- /* @__PURE__ */ jsxs("div", { children: [
576
- /* @__PURE__ */ jsx("h2", { style: styles.sectionTitle, children: "Layout" }),
577
- /* @__PURE__ */ jsx("p", { style: styles.description, children: "Default layout can be regenerated from current fields." })
1701
+ /* @__PURE__ */ jsxs7("section", { style: styles.section, children: [
1702
+ /* @__PURE__ */ jsxs7("div", { style: styles.sectionHeader, children: [
1703
+ /* @__PURE__ */ jsxs7("div", { children: [
1704
+ /* @__PURE__ */ jsx7("h2", { style: styles.sectionTitle, children: "Layout" }),
1705
+ /* @__PURE__ */ jsx7("p", { style: styles.description, children: "Default layout can be regenerated from current fields." })
578
1706
  ] }),
579
- /* @__PURE__ */ jsx(
1707
+ /* @__PURE__ */ jsx7(
580
1708
  "button",
581
1709
  {
582
1710
  type: "button",
@@ -588,14 +1716,14 @@ function createBuilderDefaultFormEditorBody(options) {
588
1716
  }
589
1717
  )
590
1718
  ] }),
591
- form.watch("layoutGroups").map((group, groupIndex) => /* @__PURE__ */ jsxs("div", { style: styles.row, children: [
592
- /* @__PURE__ */ jsxs("label", { style: styles.field, children: [
593
- /* @__PURE__ */ jsx("span", { style: styles.label, children: "Group title" }),
594
- /* @__PURE__ */ jsx("input", { style: styles.input, ...form.register(`layoutGroups.${groupIndex}.title`) })
1719
+ form.watch("layoutGroups").map((group, groupIndex) => /* @__PURE__ */ jsxs7("div", { style: styles.row, children: [
1720
+ /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1721
+ /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Group title" }),
1722
+ /* @__PURE__ */ jsx7("input", { style: styles.input, ...form.register(`layoutGroups.${groupIndex}.title`) })
595
1723
  ] }),
596
- /* @__PURE__ */ jsxs("label", { style: styles.field, children: [
597
- /* @__PURE__ */ jsx("span", { style: styles.label, children: "Columns" }),
598
- /* @__PURE__ */ jsxs(
1724
+ /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1725
+ /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Columns" }),
1726
+ /* @__PURE__ */ jsxs7(
599
1727
  "select",
600
1728
  {
601
1729
  style: styles.input,
@@ -606,16 +1734,16 @@ function createBuilderDefaultFormEditorBody(options) {
606
1734
  { shouldDirty: true }
607
1735
  ),
608
1736
  children: [
609
- /* @__PURE__ */ jsx("option", { value: 6, children: "6" }),
610
- /* @__PURE__ */ jsx("option", { value: 8, children: "8" }),
611
- /* @__PURE__ */ jsx("option", { value: 12, children: "12" })
1737
+ /* @__PURE__ */ jsx7("option", { value: 6, children: "6" }),
1738
+ /* @__PURE__ */ jsx7("option", { value: 8, children: "8" }),
1739
+ /* @__PURE__ */ jsx7("option", { value: 12, children: "12" })
612
1740
  ]
613
1741
  }
614
1742
  )
615
1743
  ] }),
616
- /* @__PURE__ */ jsxs("label", { style: styles.field, children: [
617
- /* @__PURE__ */ jsx("span", { style: styles.label, children: "Fields" }),
618
- /* @__PURE__ */ jsx(
1744
+ /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1745
+ /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Fields" }),
1746
+ /* @__PURE__ */ jsx7(
619
1747
  "input",
620
1748
  {
621
1749
  style: styles.input,
@@ -626,13 +1754,13 @@ function createBuilderDefaultFormEditorBody(options) {
626
1754
  ] })
627
1755
  ] }, group.id))
628
1756
  ] }),
629
- /* @__PURE__ */ jsxs("section", { style: styles.section, children: [
630
- /* @__PURE__ */ jsxs("div", { style: styles.sectionHeader, children: [
631
- /* @__PURE__ */ jsxs("div", { children: [
632
- /* @__PURE__ */ jsx("h2", { style: styles.sectionTitle, children: "Subforms" }),
633
- /* @__PURE__ */ jsx("p", { style: styles.description, children: "Optional nested runtime view bindings." })
1757
+ /* @__PURE__ */ jsxs7("section", { style: styles.section, children: [
1758
+ /* @__PURE__ */ jsxs7("div", { style: styles.sectionHeader, children: [
1759
+ /* @__PURE__ */ jsxs7("div", { children: [
1760
+ /* @__PURE__ */ jsx7("h2", { style: styles.sectionTitle, children: "Subforms" }),
1761
+ /* @__PURE__ */ jsx7("p", { style: styles.description, children: "Optional nested runtime view bindings." })
634
1762
  ] }),
635
- /* @__PURE__ */ jsx(
1763
+ /* @__PURE__ */ jsx7(
636
1764
  "button",
637
1765
  {
638
1766
  type: "button",
@@ -644,48 +1772,63 @@ function createBuilderDefaultFormEditorBody(options) {
644
1772
  parentField: "id",
645
1773
  childField: "parentId",
646
1774
  buttonLabel: "",
647
- icon: ""
1775
+ icon: "",
1776
+ presentation: "dialog"
648
1777
  }),
649
1778
  children: "Add subform"
650
1779
  }
651
1780
  )
652
1781
  ] }),
653
- subformArray.fields.map((subform, index) => /* @__PURE__ */ jsxs("div", { style: styles.row, children: [
654
- /* @__PURE__ */ jsxs("label", { style: styles.field, children: [
655
- /* @__PURE__ */ jsx("span", { style: styles.label, children: "Key" }),
656
- /* @__PURE__ */ jsx("input", { style: styles.input, ...form.register(`subforms.${index}.key`) })
1782
+ subformArray.fields.map((subform, index) => /* @__PURE__ */ jsxs7("div", { style: styles.row, children: [
1783
+ /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1784
+ /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Key" }),
1785
+ /* @__PURE__ */ jsx7("input", { style: styles.input, ...form.register(`subforms.${index}.key`) })
657
1786
  ] }),
658
- /* @__PURE__ */ jsxs("label", { style: styles.field, children: [
659
- /* @__PURE__ */ jsx("span", { style: styles.label, children: "Label" }),
660
- /* @__PURE__ */ jsx("input", { style: styles.input, ...form.register(`subforms.${index}.label`) })
1787
+ /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1788
+ /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Label" }),
1789
+ /* @__PURE__ */ jsx7("input", { style: styles.input, ...form.register(`subforms.${index}.label`) })
661
1790
  ] }),
662
- /* @__PURE__ */ jsxs("label", { style: styles.field, children: [
663
- /* @__PURE__ */ jsx("span", { style: styles.label, children: "View ID" }),
664
- /* @__PURE__ */ jsx("input", { style: styles.input, ...form.register(`subforms.${index}.viewId`) })
1791
+ /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1792
+ /* @__PURE__ */ jsx7("span", { style: styles.label, children: "View ID" }),
1793
+ /* @__PURE__ */ jsx7("input", { style: styles.input, ...form.register(`subforms.${index}.viewId`) })
665
1794
  ] }),
666
- /* @__PURE__ */ jsxs("label", { style: styles.field, children: [
667
- /* @__PURE__ */ jsx("span", { style: styles.label, children: "Parent field" }),
668
- /* @__PURE__ */ jsx("input", { style: styles.input, ...form.register(`subforms.${index}.parentField`) })
1795
+ /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1796
+ /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Parent field" }),
1797
+ /* @__PURE__ */ jsx7("input", { style: styles.input, ...form.register(`subforms.${index}.parentField`) })
669
1798
  ] }),
670
- /* @__PURE__ */ jsxs("label", { style: styles.field, children: [
671
- /* @__PURE__ */ jsx("span", { style: styles.label, children: "Child field" }),
672
- /* @__PURE__ */ jsx("input", { style: styles.input, ...form.register(`subforms.${index}.childField`) })
1799
+ /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1800
+ /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Child field" }),
1801
+ /* @__PURE__ */ jsx7("input", { style: styles.input, ...form.register(`subforms.${index}.childField`) })
1802
+ ] }),
1803
+ /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1804
+ /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Presentation" }),
1805
+ /* @__PURE__ */ jsxs7(
1806
+ "select",
1807
+ {
1808
+ style: styles.input,
1809
+ ...form.register(`subforms.${index}.presentation`),
1810
+ children: [
1811
+ /* @__PURE__ */ jsx7("option", { value: "dialog", children: "Dialog" }),
1812
+ /* @__PURE__ */ jsx7("option", { value: "drawer", children: "Drawer" })
1813
+ ]
1814
+ }
1815
+ )
673
1816
  ] }),
674
- /* @__PURE__ */ jsx("button", { type: "button", style: styles.button, onClick: () => subformArray.remove(index), children: "Remove" })
1817
+ /* @__PURE__ */ jsx7("button", { type: "button", style: styles.button, onClick: () => subformArray.remove(index), children: "Remove" })
675
1818
  ] }, subform.id))
676
1819
  ] }),
677
- /* @__PURE__ */ jsxs("section", { style: styles.section, children: [
678
- /* @__PURE__ */ jsxs("div", { style: styles.sectionHeader, children: [
679
- /* @__PURE__ */ jsxs("div", { children: [
680
- /* @__PURE__ */ jsx("h2", { style: styles.sectionTitle, children: "Form Triggers" }),
681
- /* @__PURE__ */ jsx("p", { style: styles.description, children: "Optional API callbacks for lifecycle events." })
1820
+ /* @__PURE__ */ jsxs7("section", { style: styles.section, children: [
1821
+ /* @__PURE__ */ jsxs7("div", { style: styles.sectionHeader, children: [
1822
+ /* @__PURE__ */ jsxs7("div", { children: [
1823
+ /* @__PURE__ */ jsx7("h2", { style: styles.sectionTitle, children: "Form Triggers" }),
1824
+ /* @__PURE__ */ jsx7("p", { style: styles.description, children: "Optional API callbacks for lifecycle events." })
682
1825
  ] }),
683
- /* @__PURE__ */ jsx("button", { type: "button", style: styles.button, onClick: () => triggerArray.append(emptyTrigger), children: "Add trigger" })
1826
+ /* @__PURE__ */ jsx7("button", { type: "button", style: styles.button, onClick: () => triggerArray.append(emptyTrigger), children: "Add trigger" })
684
1827
  ] }),
685
- triggerArray.fields.map((trigger, index) => /* @__PURE__ */ jsxs("div", { style: styles.row, children: [
686
- /* @__PURE__ */ jsxs("label", { style: styles.field, children: [
687
- /* @__PURE__ */ jsx("span", { style: styles.label, children: "Event" }),
688
- /* @__PURE__ */ jsx(
1828
+ triggerArray.fields.map((trigger, index) => /* @__PURE__ */ jsxs7("div", { style: styles.row, children: [
1829
+ /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1830
+ /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Event" }),
1831
+ /* @__PURE__ */ jsx7(
689
1832
  "select",
690
1833
  {
691
1834
  style: styles.input,
@@ -696,19 +1839,19 @@ function createBuilderDefaultFormEditorBody(options) {
696
1839
  }
697
1840
  )
698
1841
  ] }),
699
- /* @__PURE__ */ jsxs("label", { style: styles.field, children: [
700
- /* @__PURE__ */ jsx("span", { style: styles.label, children: "Route" }),
701
- /* @__PURE__ */ jsx("input", { style: styles.input, ...form.register(`triggers.${index}.route`) })
1842
+ /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1843
+ /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Route" }),
1844
+ /* @__PURE__ */ jsx7("input", { style: styles.input, ...form.register(`triggers.${index}.route`) })
702
1845
  ] }),
703
- /* @__PURE__ */ jsxs("label", { style: styles.checkboxField, children: [
704
- /* @__PURE__ */ jsx("input", { type: "checkbox", ...form.register(`triggers.${index}.enabled`) }),
1846
+ /* @__PURE__ */ jsxs7("label", { style: styles.checkboxField, children: [
1847
+ /* @__PURE__ */ jsx7("input", { type: "checkbox", ...form.register(`triggers.${index}.enabled`) }),
705
1848
  "Enabled"
706
1849
  ] }),
707
- /* @__PURE__ */ jsxs("label", { style: styles.checkboxField, children: [
708
- /* @__PURE__ */ jsx("input", { type: "checkbox", ...form.register(`triggers.${index}.blocking`) }),
1850
+ /* @__PURE__ */ jsxs7("label", { style: styles.checkboxField, children: [
1851
+ /* @__PURE__ */ jsx7("input", { type: "checkbox", ...form.register(`triggers.${index}.blocking`) }),
709
1852
  "Blocking"
710
1853
  ] }),
711
- /* @__PURE__ */ jsx("button", { type: "button", style: styles.button, onClick: () => triggerArray.remove(index), children: "Remove" })
1854
+ /* @__PURE__ */ jsx7("button", { type: "button", style: styles.button, onClick: () => triggerArray.remove(index), children: "Remove" })
712
1855
  ] }, trigger.id))
713
1856
  ] })
714
1857
  ] });
@@ -728,48 +1871,48 @@ function createBuilderDefaultListEditorBody(options) {
728
1871
  isSaving,
729
1872
  importColumnsFromTable
730
1873
  }) {
731
- return /* @__PURE__ */ jsxs("div", { style: styles.page, children: [
732
- /* @__PURE__ */ jsxs("div", { style: styles.header, children: [
733
- /* @__PURE__ */ jsxs("div", { children: [
734
- /* @__PURE__ */ jsx("h1", { style: styles.title, children: listId ? "Edit Dynamic List" : "New Dynamic List" }),
735
- /* @__PURE__ */ jsx("p", { style: styles.description, children: "Configure list columns, source mapping, and triggers." })
1874
+ return /* @__PURE__ */ jsxs7("div", { style: styles.page, children: [
1875
+ /* @__PURE__ */ jsxs7("div", { style: styles.header, children: [
1876
+ /* @__PURE__ */ jsxs7("div", { children: [
1877
+ /* @__PURE__ */ jsx7("h1", { style: styles.title, children: listId ? "Edit Dynamic List" : "New Dynamic List" }),
1878
+ /* @__PURE__ */ jsx7("p", { style: styles.description, children: "Configure list columns, source mapping, and triggers." })
736
1879
  ] }),
737
- /* @__PURE__ */ jsxs("div", { style: styles.actions, children: [
738
- /* @__PURE__ */ jsx("a", { href: options.backHref, style: styles.button, children: "Cancel" }),
739
- /* @__PURE__ */ jsx("button", { type: "submit", disabled: isSaving, style: styles.primaryButton, children: isSaving ? "Saving..." : "Save" })
1880
+ /* @__PURE__ */ jsxs7("div", { style: styles.actions, children: [
1881
+ /* @__PURE__ */ jsx7("a", { href: options.backHref, style: styles.button, children: "Cancel" }),
1882
+ /* @__PURE__ */ jsx7("button", { type: "submit", disabled: isSaving, style: styles.primaryButton, children: isSaving ? "Saving..." : "Save" })
740
1883
  ] })
741
1884
  ] }),
742
- /* @__PURE__ */ jsxs("section", { style: styles.section, children: [
743
- /* @__PURE__ */ jsx("div", { style: styles.sectionHeader, children: /* @__PURE__ */ jsx("h2", { style: styles.sectionTitle, children: "Details" }) }),
744
- /* @__PURE__ */ jsxs("div", { style: { ...styles.grid, ...styles.twoColumn }, children: [
745
- /* @__PURE__ */ jsxs("label", { style: styles.field, children: [
746
- /* @__PURE__ */ jsx("span", { style: styles.label, children: "Title" }),
747
- /* @__PURE__ */ jsx("input", { style: styles.input, ...form.register("title", { required: true }) })
1885
+ /* @__PURE__ */ jsxs7("section", { style: styles.section, children: [
1886
+ /* @__PURE__ */ jsx7("div", { style: styles.sectionHeader, children: /* @__PURE__ */ jsx7("h2", { style: styles.sectionTitle, children: "Details" }) }),
1887
+ /* @__PURE__ */ jsxs7("div", { style: { ...styles.grid, ...styles.twoColumn }, children: [
1888
+ /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1889
+ /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Title" }),
1890
+ /* @__PURE__ */ jsx7("input", { style: styles.input, ...form.register("title", { required: true }) })
748
1891
  ] }),
749
- /* @__PURE__ */ jsxs("label", { style: styles.field, children: [
750
- /* @__PURE__ */ jsx("span", { style: styles.label, children: "Description" }),
751
- /* @__PURE__ */ jsx("input", { style: styles.input, ...form.register("description") })
1892
+ /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1893
+ /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Description" }),
1894
+ /* @__PURE__ */ jsx7("input", { style: styles.input, ...form.register("description") })
752
1895
  ] }),
753
- /* @__PURE__ */ jsxs("label", { style: styles.field, children: [
754
- /* @__PURE__ */ jsx("span", { style: styles.label, children: "Datasource" }),
755
- /* @__PURE__ */ jsxs("select", { style: styles.input, ...form.register("sourceType"), children: [
756
- /* @__PURE__ */ jsx("option", { value: "none", children: "None" }),
757
- /* @__PURE__ */ jsx("option", { value: "dbTable", children: "DB table" }),
758
- /* @__PURE__ */ jsx("option", { value: "apiEndpoint", children: "API endpoint" })
1896
+ /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1897
+ /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Datasource" }),
1898
+ /* @__PURE__ */ jsxs7("select", { style: styles.input, ...form.register("sourceType"), children: [
1899
+ /* @__PURE__ */ jsx7("option", { value: "none", children: "None" }),
1900
+ /* @__PURE__ */ jsx7("option", { value: "dbTable", children: "DB table" }),
1901
+ /* @__PURE__ */ jsx7("option", { value: "apiEndpoint", children: "API endpoint" })
759
1902
  ] })
760
1903
  ] }),
761
- sourceType === "dbTable" ? /* @__PURE__ */ jsxs("label", { style: styles.field, children: [
762
- /* @__PURE__ */ jsx("span", { style: styles.label, children: "Table" }),
763
- /* @__PURE__ */ jsxs("select", { style: styles.input, ...form.register("sourceTable"), children: [
764
- /* @__PURE__ */ jsx("option", { value: BUILDER_EDITOR_NONE_VALUE, children: "Select table" }),
765
- tables.map((table) => /* @__PURE__ */ jsx("option", { value: table.name, children: table.label ?? table.name }, table.name))
1904
+ sourceType === "dbTable" ? /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1905
+ /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Table" }),
1906
+ /* @__PURE__ */ jsxs7("select", { style: styles.input, ...form.register("sourceTable"), children: [
1907
+ /* @__PURE__ */ jsx7("option", { value: BUILDER_EDITOR_NONE_VALUE, children: "Select table" }),
1908
+ tables.map((table) => /* @__PURE__ */ jsx7("option", { value: table.name, children: table.label ?? table.name }, table.name))
766
1909
  ] })
767
1910
  ] }) : null,
768
- sourceType === "apiEndpoint" ? /* @__PURE__ */ jsxs("label", { style: styles.field, children: [
769
- /* @__PURE__ */ jsx("span", { style: styles.label, children: "API base path" }),
770
- /* @__PURE__ */ jsx("input", { style: styles.input, ...form.register("apiBasePath") })
1911
+ sourceType === "apiEndpoint" ? /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1912
+ /* @__PURE__ */ jsx7("span", { style: styles.label, children: "API base path" }),
1913
+ /* @__PURE__ */ jsx7("input", { style: styles.input, ...form.register("apiBasePath") })
771
1914
  ] }) : null,
772
- sourceType === "dbTable" ? /* @__PURE__ */ jsx("div", { style: { ...styles.field, justifyContent: "end" }, children: /* @__PURE__ */ jsx(
1915
+ sourceType === "dbTable" ? /* @__PURE__ */ jsx7("div", { style: { ...styles.field, justifyContent: "end" }, children: /* @__PURE__ */ jsx7(
773
1916
  "button",
774
1917
  {
775
1918
  type: "button",
@@ -781,13 +1924,13 @@ function createBuilderDefaultListEditorBody(options) {
781
1924
  ) }) : null
782
1925
  ] })
783
1926
  ] }),
784
- /* @__PURE__ */ jsxs("section", { style: styles.section, children: [
785
- /* @__PURE__ */ jsxs("div", { style: styles.sectionHeader, children: [
786
- /* @__PURE__ */ jsxs("div", { children: [
787
- /* @__PURE__ */ jsx("h2", { style: styles.sectionTitle, children: "Columns" }),
788
- /* @__PURE__ */ jsx("p", { style: styles.description, children: "Runtime list columns." })
1927
+ /* @__PURE__ */ jsxs7("section", { style: styles.section, children: [
1928
+ /* @__PURE__ */ jsxs7("div", { style: styles.sectionHeader, children: [
1929
+ /* @__PURE__ */ jsxs7("div", { children: [
1930
+ /* @__PURE__ */ jsx7("h2", { style: styles.sectionTitle, children: "Columns" }),
1931
+ /* @__PURE__ */ jsx7("p", { style: styles.description, children: "Runtime list columns." })
789
1932
  ] }),
790
- /* @__PURE__ */ jsx(
1933
+ /* @__PURE__ */ jsx7(
791
1934
  "button",
792
1935
  {
793
1936
  type: "button",
@@ -801,27 +1944,27 @@ function createBuilderDefaultListEditorBody(options) {
801
1944
  }
802
1945
  )
803
1946
  ] }),
804
- columnArray.fields.map((column, index) => /* @__PURE__ */ jsxs("div", { style: styles.row, children: [
805
- /* @__PURE__ */ jsxs("label", { style: styles.field, children: [
806
- /* @__PURE__ */ jsx("span", { style: styles.label, children: "Key" }),
807
- /* @__PURE__ */ jsx("input", { style: styles.input, ...form.register(`columns.${index}.key`) })
1947
+ columnArray.fields.map((column, index) => /* @__PURE__ */ jsxs7("div", { style: styles.row, children: [
1948
+ /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1949
+ /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Key" }),
1950
+ /* @__PURE__ */ jsx7("input", { style: styles.input, ...form.register(`columns.${index}.key`) })
808
1951
  ] }),
809
- /* @__PURE__ */ jsxs("label", { style: styles.field, children: [
810
- /* @__PURE__ */ jsx("span", { style: styles.label, children: "Label" }),
811
- /* @__PURE__ */ jsx("input", { style: styles.input, ...form.register(`columns.${index}.label`) })
1952
+ /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1953
+ /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Label" }),
1954
+ /* @__PURE__ */ jsx7("input", { style: styles.input, ...form.register(`columns.${index}.label`) })
812
1955
  ] }),
813
- /* @__PURE__ */ jsxs("label", { style: styles.field, children: [
814
- /* @__PURE__ */ jsx("span", { style: styles.label, children: "Align" }),
815
- /* @__PURE__ */ jsxs("select", { style: styles.input, ...form.register(`columns.${index}.align`), children: [
816
- /* @__PURE__ */ jsx("option", { value: "left", children: "Left" }),
817
- /* @__PURE__ */ jsx("option", { value: "right", children: "Right" })
1956
+ /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1957
+ /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Align" }),
1958
+ /* @__PURE__ */ jsxs7("select", { style: styles.input, ...form.register(`columns.${index}.align`), children: [
1959
+ /* @__PURE__ */ jsx7("option", { value: "left", children: "Left" }),
1960
+ /* @__PURE__ */ jsx7("option", { value: "right", children: "Right" })
818
1961
  ] })
819
1962
  ] }),
820
- /* @__PURE__ */ jsxs("label", { style: styles.checkboxField, children: [
821
- /* @__PURE__ */ jsx("input", { type: "checkbox", ...form.register(`columns.${index}.sortable`) }),
1963
+ /* @__PURE__ */ jsxs7("label", { style: styles.checkboxField, children: [
1964
+ /* @__PURE__ */ jsx7("input", { type: "checkbox", ...form.register(`columns.${index}.sortable`) }),
822
1965
  "Sortable"
823
1966
  ] }),
824
- /* @__PURE__ */ jsx(
1967
+ /* @__PURE__ */ jsx7(
825
1968
  "button",
826
1969
  {
827
1970
  type: "button",
@@ -833,18 +1976,18 @@ function createBuilderDefaultListEditorBody(options) {
833
1976
  )
834
1977
  ] }, column.id))
835
1978
  ] }),
836
- /* @__PURE__ */ jsxs("section", { style: styles.section, children: [
837
- /* @__PURE__ */ jsxs("div", { style: styles.sectionHeader, children: [
838
- /* @__PURE__ */ jsxs("div", { children: [
839
- /* @__PURE__ */ jsx("h2", { style: styles.sectionTitle, children: "List Triggers" }),
840
- /* @__PURE__ */ jsx("p", { style: styles.description, children: "Optional API callbacks for list lifecycle events." })
1979
+ /* @__PURE__ */ jsxs7("section", { style: styles.section, children: [
1980
+ /* @__PURE__ */ jsxs7("div", { style: styles.sectionHeader, children: [
1981
+ /* @__PURE__ */ jsxs7("div", { children: [
1982
+ /* @__PURE__ */ jsx7("h2", { style: styles.sectionTitle, children: "List Triggers" }),
1983
+ /* @__PURE__ */ jsx7("p", { style: styles.description, children: "Optional API callbacks for list lifecycle events." })
841
1984
  ] }),
842
- /* @__PURE__ */ jsx("button", { type: "button", style: styles.button, onClick: () => triggerArray.append(emptyTrigger), children: "Add trigger" })
1985
+ /* @__PURE__ */ jsx7("button", { type: "button", style: styles.button, onClick: () => triggerArray.append(emptyTrigger), children: "Add trigger" })
843
1986
  ] }),
844
- triggerArray.fields.map((trigger, index) => /* @__PURE__ */ jsxs("div", { style: styles.row, children: [
845
- /* @__PURE__ */ jsxs("label", { style: styles.field, children: [
846
- /* @__PURE__ */ jsx("span", { style: styles.label, children: "Event" }),
847
- /* @__PURE__ */ jsx(
1987
+ triggerArray.fields.map((trigger, index) => /* @__PURE__ */ jsxs7("div", { style: styles.row, children: [
1988
+ /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1989
+ /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Event" }),
1990
+ /* @__PURE__ */ jsx7(
848
1991
  "select",
849
1992
  {
850
1993
  style: styles.input,
@@ -855,19 +1998,19 @@ function createBuilderDefaultListEditorBody(options) {
855
1998
  }
856
1999
  )
857
2000
  ] }),
858
- /* @__PURE__ */ jsxs("label", { style: styles.field, children: [
859
- /* @__PURE__ */ jsx("span", { style: styles.label, children: "Route" }),
860
- /* @__PURE__ */ jsx("input", { style: styles.input, ...form.register(`triggers.${index}.route`) })
2001
+ /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
2002
+ /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Route" }),
2003
+ /* @__PURE__ */ jsx7("input", { style: styles.input, ...form.register(`triggers.${index}.route`) })
861
2004
  ] }),
862
- /* @__PURE__ */ jsxs("label", { style: styles.checkboxField, children: [
863
- /* @__PURE__ */ jsx("input", { type: "checkbox", ...form.register(`triggers.${index}.enabled`) }),
2005
+ /* @__PURE__ */ jsxs7("label", { style: styles.checkboxField, children: [
2006
+ /* @__PURE__ */ jsx7("input", { type: "checkbox", ...form.register(`triggers.${index}.enabled`) }),
864
2007
  "Enabled"
865
2008
  ] }),
866
- /* @__PURE__ */ jsxs("label", { style: styles.checkboxField, children: [
867
- /* @__PURE__ */ jsx("input", { type: "checkbox", ...form.register(`triggers.${index}.blocking`) }),
2009
+ /* @__PURE__ */ jsxs7("label", { style: styles.checkboxField, children: [
2010
+ /* @__PURE__ */ jsx7("input", { type: "checkbox", ...form.register(`triggers.${index}.blocking`) }),
868
2011
  "Blocking"
869
2012
  ] }),
870
- /* @__PURE__ */ jsx("button", { type: "button", style: styles.button, onClick: () => triggerArray.remove(index), children: "Remove" })
2013
+ /* @__PURE__ */ jsx7("button", { type: "button", style: styles.button, onClick: () => triggerArray.remove(index), children: "Remove" })
871
2014
  ] }, trigger.id))
872
2015
  ] })
873
2016
  ] });
@@ -875,8 +2018,8 @@ function createBuilderDefaultListEditorBody(options) {
875
2018
  }
876
2019
 
877
2020
  // src/admin/BuilderDefaultEntityManager.tsx
878
- import { useMemo, useState } from "react";
879
- import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
2021
+ import { useMemo as useMemo5, useState as useState5 } from "react";
2022
+ import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
880
2023
  var styles2 = {
881
2024
  page: {
882
2025
  display: "grid",
@@ -972,12 +2115,12 @@ var styles2 = {
972
2115
  };
973
2116
  function createBuilderDefaultEntityManagerComponent(deps) {
974
2117
  return function BuilderDefaultEntityManager() {
975
- const [state, setState] = useState({
2118
+ const [state, setState] = useState5({
976
2119
  page: 1,
977
2120
  pageSize: 20,
978
2121
  search: ""
979
2122
  });
980
- const query = deps.hooks.useEntities(useMemo(() => deps.buildQuery(state), [state]));
2123
+ const query = deps.hooks.useEntities(useMemo5(() => deps.buildQuery(state), [state]));
981
2124
  const remove = deps.hooks.useDelete();
982
2125
  const replicate = deps.hooks.useReplicate();
983
2126
  const items = query.data?.items ?? [];
@@ -993,16 +2136,16 @@ function createBuilderDefaultEntityManagerComponent(deps) {
993
2136
  if (!window.confirm(deps.labels.deleteConfirm(entity))) return;
994
2137
  await remove.mutateAsync(entity.id);
995
2138
  };
996
- return /* @__PURE__ */ jsxs2("section", { style: styles2.page, children: [
997
- /* @__PURE__ */ jsxs2("div", { style: styles2.header, children: [
998
- /* @__PURE__ */ jsxs2("div", { children: [
999
- /* @__PURE__ */ jsx2("h1", { style: styles2.title, children: deps.labels.title }),
1000
- /* @__PURE__ */ jsx2("p", { style: styles2.description, children: deps.labels.description })
2139
+ return /* @__PURE__ */ jsxs8("section", { style: styles2.page, children: [
2140
+ /* @__PURE__ */ jsxs8("div", { style: styles2.header, children: [
2141
+ /* @__PURE__ */ jsxs8("div", { children: [
2142
+ /* @__PURE__ */ jsx8("h1", { style: styles2.title, children: deps.labels.title }),
2143
+ /* @__PURE__ */ jsx8("p", { style: styles2.description, children: deps.labels.description })
1001
2144
  ] }),
1002
- deps.createHref ? /* @__PURE__ */ jsx2("a", { href: deps.createHref, style: styles2.primaryButton, children: deps.labels.addLabel }) : null
2145
+ deps.createHref ? /* @__PURE__ */ jsx8("a", { href: deps.createHref, style: styles2.primaryButton, children: deps.labels.addLabel }) : null
1003
2146
  ] }),
1004
- /* @__PURE__ */ jsxs2("div", { style: styles2.card, children: [
1005
- /* @__PURE__ */ jsx2("div", { style: styles2.toolbar, children: /* @__PURE__ */ jsx2(
2147
+ /* @__PURE__ */ jsxs8("div", { style: styles2.card, children: [
2148
+ /* @__PURE__ */ jsx8("div", { style: styles2.toolbar, children: /* @__PURE__ */ jsx8(
1006
2149
  "input",
1007
2150
  {
1008
2151
  style: styles2.input,
@@ -1011,21 +2154,21 @@ function createBuilderDefaultEntityManagerComponent(deps) {
1011
2154
  onChange: (event) => setState((current) => ({ ...current, page: 1, search: event.target.value }))
1012
2155
  }
1013
2156
  ) }),
1014
- /* @__PURE__ */ jsx2("div", { style: styles2.tableWrap, children: /* @__PURE__ */ jsxs2("table", { style: styles2.table, children: [
1015
- /* @__PURE__ */ jsx2("thead", { children: /* @__PURE__ */ jsxs2("tr", { children: [
1016
- /* @__PURE__ */ jsx2("th", { style: styles2.th, children: deps.labels.title }),
1017
- /* @__PURE__ */ jsx2("th", { style: styles2.th, children: "Detail" }),
1018
- /* @__PURE__ */ jsx2("th", { style: styles2.th, children: "Description" }),
1019
- /* @__PURE__ */ jsx2("th", { style: { ...styles2.th, textAlign: "right" }, children: "Actions" })
2157
+ /* @__PURE__ */ jsx8("div", { style: styles2.tableWrap, children: /* @__PURE__ */ jsxs8("table", { style: styles2.table, children: [
2158
+ /* @__PURE__ */ jsx8("thead", { children: /* @__PURE__ */ jsxs8("tr", { children: [
2159
+ /* @__PURE__ */ jsx8("th", { style: styles2.th, children: deps.labels.title }),
2160
+ /* @__PURE__ */ jsx8("th", { style: styles2.th, children: "Detail" }),
2161
+ /* @__PURE__ */ jsx8("th", { style: styles2.th, children: "Description" }),
2162
+ /* @__PURE__ */ jsx8("th", { style: { ...styles2.th, textAlign: "right" }, children: "Actions" })
1020
2163
  ] }) }),
1021
- /* @__PURE__ */ jsx2("tbody", { children: items.map((entity) => /* @__PURE__ */ jsxs2("tr", { children: [
1022
- /* @__PURE__ */ jsx2("td", { style: styles2.td, children: /* @__PURE__ */ jsx2("a", { href: deps.editHref(entity), children: entity.title }) }),
1023
- /* @__PURE__ */ jsx2("td", { style: styles2.td, children: deps.getDetail?.(entity) ?? "-" }),
1024
- /* @__PURE__ */ jsx2("td", { style: styles2.td, children: entity.description || "-" }),
1025
- /* @__PURE__ */ jsx2("td", { style: styles2.td, children: /* @__PURE__ */ jsxs2("div", { style: styles2.actions, children: [
1026
- deps.runtimeHref ? /* @__PURE__ */ jsx2("a", { href: deps.runtimeHref(entity), style: styles2.button, children: deps.labels.runtimeLabel }) : null,
1027
- /* @__PURE__ */ jsx2("a", { href: deps.editHref(entity), style: styles2.button, children: deps.labels.editLabel }),
1028
- /* @__PURE__ */ jsx2(
2164
+ /* @__PURE__ */ jsx8("tbody", { children: items.map((entity) => /* @__PURE__ */ jsxs8("tr", { children: [
2165
+ /* @__PURE__ */ jsx8("td", { style: styles2.td, children: /* @__PURE__ */ jsx8("a", { href: deps.editHref(entity), children: entity.title }) }),
2166
+ /* @__PURE__ */ jsx8("td", { style: styles2.td, children: deps.getDetail?.(entity) ?? "-" }),
2167
+ /* @__PURE__ */ jsx8("td", { style: styles2.td, children: entity.description || "-" }),
2168
+ /* @__PURE__ */ jsx8("td", { style: styles2.td, children: /* @__PURE__ */ jsxs8("div", { style: styles2.actions, children: [
2169
+ deps.runtimeHref ? /* @__PURE__ */ jsx8("a", { href: deps.runtimeHref(entity), style: styles2.button, children: deps.labels.runtimeLabel }) : null,
2170
+ /* @__PURE__ */ jsx8("a", { href: deps.editHref(entity), style: styles2.button, children: deps.labels.editLabel }),
2171
+ /* @__PURE__ */ jsx8(
1029
2172
  "button",
1030
2173
  {
1031
2174
  type: "button",
@@ -1034,7 +2177,7 @@ function createBuilderDefaultEntityManagerComponent(deps) {
1034
2177
  children: deps.labels.replicateLabel
1035
2178
  }
1036
2179
  ),
1037
- /* @__PURE__ */ jsx2(
2180
+ /* @__PURE__ */ jsx8(
1038
2181
  "button",
1039
2182
  {
1040
2183
  type: "button",
@@ -1047,11 +2190,11 @@ function createBuilderDefaultEntityManagerComponent(deps) {
1047
2190
  ] }) })
1048
2191
  ] }, entity.id)) })
1049
2192
  ] }) }),
1050
- query.isPending ? /* @__PURE__ */ jsx2("div", { style: styles2.empty, children: "Loading..." }) : null,
1051
- query.isError ? /* @__PURE__ */ jsx2("div", { style: styles2.empty, children: "Failed to load." }) : null,
1052
- !query.isPending && !query.isError && items.length === 0 ? /* @__PURE__ */ jsxs2("div", { style: styles2.empty, children: [
1053
- /* @__PURE__ */ jsx2("strong", { children: deps.labels.emptyTitle }),
1054
- /* @__PURE__ */ jsx2("div", { children: deps.labels.emptyDescription })
2193
+ query.isPending ? /* @__PURE__ */ jsx8("div", { style: styles2.empty, children: "Loading..." }) : null,
2194
+ query.isError ? /* @__PURE__ */ jsx8("div", { style: styles2.empty, children: "Failed to load." }) : null,
2195
+ !query.isPending && !query.isError && items.length === 0 ? /* @__PURE__ */ jsxs8("div", { style: styles2.empty, children: [
2196
+ /* @__PURE__ */ jsx8("strong", { children: deps.labels.emptyTitle }),
2197
+ /* @__PURE__ */ jsx8("div", { children: deps.labels.emptyDescription })
1055
2198
  ] }) : null
1056
2199
  ] })
1057
2200
  ] });
@@ -1059,9 +2202,9 @@ function createBuilderDefaultEntityManagerComponent(deps) {
1059
2202
  }
1060
2203
 
1061
2204
  // src/admin/BuilderDefaultViewEditorPage.tsx
1062
- import { useEffect } from "react";
1063
- import { useForm } from "react-hook-form";
1064
- import { Fragment, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
2205
+ import { useEffect as useEffect3 } from "react";
2206
+ import { useForm as useForm3 } from "react-hook-form";
2207
+ import { Fragment, jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
1065
2208
  var styles3 = {
1066
2209
  page: {
1067
2210
  display: "grid",
@@ -1171,14 +2314,14 @@ function createBuilderDefaultViewEditorPage(options) {
1171
2314
  const forms = options.hooks.useBuilderFormOptions();
1172
2315
  const lists = options.hooks.useBuilderListOptions();
1173
2316
  const save = options.hooks.useSaveBuilderView();
1174
- const form = useForm({
2317
+ const form = useForm3({
1175
2318
  defaultValues: {
1176
2319
  ...defaultEmptyValues,
1177
2320
  permissionRead: defaultPermission,
1178
2321
  permissionWrite: defaultPermission
1179
2322
  }
1180
2323
  });
1181
- useEffect(() => {
2324
+ useEffect3(() => {
1182
2325
  if (viewId && !view.data) return;
1183
2326
  form.reset(
1184
2327
  builderViewEditorValuesFromEntity(
@@ -1209,64 +2352,64 @@ function createBuilderDefaultViewEditorPage(options) {
1209
2352
  }
1210
2353
  });
1211
2354
  if (viewId && view.isPending) {
1212
- return /* @__PURE__ */ jsx3("div", { style: styles3.state, children: "Loading..." });
2355
+ return /* @__PURE__ */ jsx9("div", { style: styles3.state, children: "Loading..." });
1213
2356
  }
1214
2357
  if (viewId && view.isError) {
1215
- return /* @__PURE__ */ jsx3("div", { style: styles3.state, children: "Failed to load view." });
2358
+ return /* @__PURE__ */ jsx9("div", { style: styles3.state, children: "Failed to load view." });
1216
2359
  }
1217
- return /* @__PURE__ */ jsxs3("form", { onSubmit, noValidate: true, style: styles3.page, children: [
1218
- /* @__PURE__ */ jsxs3("div", { style: styles3.header, children: [
1219
- /* @__PURE__ */ jsxs3("div", { children: [
1220
- /* @__PURE__ */ jsx3("h1", { style: styles3.title, children: viewId ? "Edit Dynamic View" : "New Dynamic View" }),
1221
- /* @__PURE__ */ jsx3("p", { style: styles3.description, children: "Connect a form and list into a runtime screen." })
2360
+ return /* @__PURE__ */ jsxs9("form", { onSubmit, noValidate: true, style: styles3.page, children: [
2361
+ /* @__PURE__ */ jsxs9("div", { style: styles3.header, children: [
2362
+ /* @__PURE__ */ jsxs9("div", { children: [
2363
+ /* @__PURE__ */ jsx9("h1", { style: styles3.title, children: viewId ? "Edit Dynamic View" : "New Dynamic View" }),
2364
+ /* @__PURE__ */ jsx9("p", { style: styles3.description, children: "Connect a form and list into a runtime screen." })
1222
2365
  ] }),
1223
- /* @__PURE__ */ jsxs3("div", { style: styles3.actions, children: [
1224
- /* @__PURE__ */ jsx3("a", { href: options.backHref, style: styles3.button, children: "Cancel" }),
1225
- /* @__PURE__ */ jsx3("button", { type: "submit", disabled: save.isPending, style: styles3.primaryButton, children: save.isPending ? "Saving..." : "Save" })
2366
+ /* @__PURE__ */ jsxs9("div", { style: styles3.actions, children: [
2367
+ /* @__PURE__ */ jsx9("a", { href: options.backHref, style: styles3.button, children: "Cancel" }),
2368
+ /* @__PURE__ */ jsx9("button", { type: "submit", disabled: save.isPending, style: styles3.primaryButton, children: save.isPending ? "Saving..." : "Save" })
1226
2369
  ] })
1227
2370
  ] }),
1228
- /* @__PURE__ */ jsx3("section", { style: styles3.section, children: /* @__PURE__ */ jsxs3("div", { style: styles3.grid, children: [
1229
- /* @__PURE__ */ jsxs3("label", { style: styles3.field, children: [
1230
- /* @__PURE__ */ jsx3("span", { style: styles3.label, children: "Title" }),
1231
- /* @__PURE__ */ jsx3("input", { style: styles3.input, ...form.register("title", { required: true }) })
2371
+ /* @__PURE__ */ jsx9("section", { style: styles3.section, children: /* @__PURE__ */ jsxs9("div", { style: styles3.grid, children: [
2372
+ /* @__PURE__ */ jsxs9("label", { style: styles3.field, children: [
2373
+ /* @__PURE__ */ jsx9("span", { style: styles3.label, children: "Title" }),
2374
+ /* @__PURE__ */ jsx9("input", { style: styles3.input, ...form.register("title", { required: true }) })
1232
2375
  ] }),
1233
- /* @__PURE__ */ jsxs3("label", { style: styles3.field, children: [
1234
- /* @__PURE__ */ jsx3("span", { style: styles3.label, children: "Description" }),
1235
- /* @__PURE__ */ jsx3("input", { style: styles3.input, ...form.register("description") })
2376
+ /* @__PURE__ */ jsxs9("label", { style: styles3.field, children: [
2377
+ /* @__PURE__ */ jsx9("span", { style: styles3.label, children: "Description" }),
2378
+ /* @__PURE__ */ jsx9("input", { style: styles3.input, ...form.register("description") })
1236
2379
  ] }),
1237
- /* @__PURE__ */ jsxs3("label", { style: styles3.field, children: [
1238
- /* @__PURE__ */ jsx3("span", { style: styles3.label, children: "Form" }),
1239
- /* @__PURE__ */ jsxs3("select", { style: styles3.input, ...form.register("formId"), children: [
1240
- /* @__PURE__ */ jsx3("option", { value: BUILDER_EDITOR_NONE_VALUE, children: "No form" }),
1241
- (forms.data ?? []).map((item) => /* @__PURE__ */ jsx3("option", { value: item.id, children: item.title }, item.id))
2380
+ /* @__PURE__ */ jsxs9("label", { style: styles3.field, children: [
2381
+ /* @__PURE__ */ jsx9("span", { style: styles3.label, children: "Form" }),
2382
+ /* @__PURE__ */ jsxs9("select", { style: styles3.input, ...form.register("formId"), children: [
2383
+ /* @__PURE__ */ jsx9("option", { value: BUILDER_EDITOR_NONE_VALUE, children: "No form" }),
2384
+ (forms.data ?? []).map((item) => /* @__PURE__ */ jsx9("option", { value: item.id, children: item.title }, item.id))
1242
2385
  ] })
1243
2386
  ] }),
1244
- /* @__PURE__ */ jsxs3("label", { style: styles3.field, children: [
1245
- /* @__PURE__ */ jsx3("span", { style: styles3.label, children: "List" }),
1246
- /* @__PURE__ */ jsxs3("select", { style: styles3.input, ...form.register("listId"), children: [
1247
- /* @__PURE__ */ jsx3("option", { value: BUILDER_EDITOR_NONE_VALUE, children: "No list" }),
1248
- (lists.data ?? []).map((item) => /* @__PURE__ */ jsx3("option", { value: item.id, children: item.title }, item.id))
2387
+ /* @__PURE__ */ jsxs9("label", { style: styles3.field, children: [
2388
+ /* @__PURE__ */ jsx9("span", { style: styles3.label, children: "List" }),
2389
+ /* @__PURE__ */ jsxs9("select", { style: styles3.input, ...form.register("listId"), children: [
2390
+ /* @__PURE__ */ jsx9("option", { value: BUILDER_EDITOR_NONE_VALUE, children: "No list" }),
2391
+ (lists.data ?? []).map((item) => /* @__PURE__ */ jsx9("option", { value: item.id, children: item.title }, item.id))
1249
2392
  ] })
1250
2393
  ] }),
1251
- showPermissions ? /* @__PURE__ */ jsxs3(Fragment, { children: [
1252
- /* @__PURE__ */ jsxs3("label", { style: styles3.field, children: [
1253
- /* @__PURE__ */ jsx3("span", { style: styles3.label, children: "Read permission" }),
1254
- /* @__PURE__ */ jsxs3("select", { style: styles3.input, ...form.register("permissionRead"), children: [
1255
- /* @__PURE__ */ jsx3("option", { value: "", children: "Authenticated users" }),
1256
- options.permissionOptions.map((permission) => /* @__PURE__ */ jsx3("option", { value: permission.value, children: permission.label }, permission.value))
2394
+ showPermissions ? /* @__PURE__ */ jsxs9(Fragment, { children: [
2395
+ /* @__PURE__ */ jsxs9("label", { style: styles3.field, children: [
2396
+ /* @__PURE__ */ jsx9("span", { style: styles3.label, children: "Read permission" }),
2397
+ /* @__PURE__ */ jsxs9("select", { style: styles3.input, ...form.register("permissionRead"), children: [
2398
+ /* @__PURE__ */ jsx9("option", { value: "", children: "Authenticated users" }),
2399
+ options.permissionOptions.map((permission) => /* @__PURE__ */ jsx9("option", { value: permission.value, children: permission.label }, permission.value))
1257
2400
  ] })
1258
2401
  ] }),
1259
- /* @__PURE__ */ jsxs3("label", { style: styles3.field, children: [
1260
- /* @__PURE__ */ jsx3("span", { style: styles3.label, children: "Write permission" }),
1261
- /* @__PURE__ */ jsxs3("select", { style: styles3.input, ...form.register("permissionWrite"), children: [
1262
- /* @__PURE__ */ jsx3("option", { value: "", children: "Authenticated users" }),
1263
- options.permissionOptions.map((permission) => /* @__PURE__ */ jsx3("option", { value: permission.value, children: permission.label }, permission.value))
2402
+ /* @__PURE__ */ jsxs9("label", { style: styles3.field, children: [
2403
+ /* @__PURE__ */ jsx9("span", { style: styles3.label, children: "Write permission" }),
2404
+ /* @__PURE__ */ jsxs9("select", { style: styles3.input, ...form.register("permissionWrite"), children: [
2405
+ /* @__PURE__ */ jsx9("option", { value: "", children: "Authenticated users" }),
2406
+ options.permissionOptions.map((permission) => /* @__PURE__ */ jsx9("option", { value: permission.value, children: permission.label }, permission.value))
1264
2407
  ] })
1265
2408
  ] })
1266
2409
  ] }) : null,
1267
- /* @__PURE__ */ jsxs3("label", { style: { ...styles3.field, gridColumn: "1 / -1" }, children: [
1268
- /* @__PURE__ */ jsx3("span", { style: styles3.label, children: "Triggers JSON" }),
1269
- /* @__PURE__ */ jsx3("textarea", { style: styles3.textarea, ...form.register("triggersText") })
2410
+ /* @__PURE__ */ jsxs9("label", { style: { ...styles3.field, gridColumn: "1 / -1" }, children: [
2411
+ /* @__PURE__ */ jsx9("span", { style: styles3.label, children: "Triggers JSON" }),
2412
+ /* @__PURE__ */ jsx9("textarea", { style: styles3.textarea, ...form.register("triggersText") })
1270
2413
  ] })
1271
2414
  ] }) })
1272
2415
  ] });
@@ -1274,32 +2417,32 @@ function createBuilderDefaultViewEditorPage(options) {
1274
2417
  }
1275
2418
 
1276
2419
  // src/admin/BuilderEditorPage.tsx
1277
- import { useEffect as useEffect2 } from "react";
2420
+ import { useEffect as useEffect4 } from "react";
1278
2421
  import {
1279
- FormProvider,
2422
+ FormProvider as FormProvider3,
1280
2423
  useFieldArray,
1281
- useForm as useForm2,
1282
- useWatch
2424
+ useForm as useForm4,
2425
+ useWatch as useWatch2
1283
2426
  } from "react-hook-form";
1284
- import { jsx as jsx4 } from "react/jsx-runtime";
2427
+ import { jsx as jsx10 } from "react/jsx-runtime";
1285
2428
  function createBuilderFormEditorPageComponent(deps) {
1286
2429
  return function BuilderFormEditorPage({ formId }) {
1287
2430
  const Body = deps.Body;
1288
2431
  const entityQuery = deps.hooks.useEntity(formId);
1289
2432
  const tables = deps.hooks.useTables();
1290
2433
  const save = deps.hooks.useSave();
1291
- const form = useForm2({
2434
+ const form = useForm4({
1292
2435
  resolver: deps.resolver,
1293
2436
  defaultValues: deps.emptyValues
1294
2437
  });
1295
2438
  const fieldArray = useFieldArray({ control: form.control, name: "fields" });
1296
2439
  const subformArray = useFieldArray({ control: form.control, name: "subforms" });
1297
2440
  const triggerArray = useFieldArray({ control: form.control, name: "triggers" });
1298
- const fields = useWatch({ control: form.control, name: "fields" }) ?? [];
1299
- const subforms = useWatch({ control: form.control, name: "subforms" }) ?? [];
1300
- const sourceType = useWatch({ control: form.control, name: "sourceType" });
1301
- const sourceTable = useWatch({ control: form.control, name: "sourceTable" });
1302
- useEffect2(() => {
2441
+ const fields = useWatch2({ control: form.control, name: "fields" }) ?? [];
2442
+ const subforms = useWatch2({ control: form.control, name: "subforms" }) ?? [];
2443
+ const sourceType = useWatch2({ control: form.control, name: "sourceType" });
2444
+ const sourceTable = useWatch2({ control: form.control, name: "sourceTable" });
2445
+ useEffect4(() => {
1303
2446
  if (formId && !entityQuery.data) return;
1304
2447
  form.reset(builderFormEditorValuesFromEntity(entityQuery.data ?? null, deps.emptyValues));
1305
2448
  }, [entityQuery.data, form, formId]);
@@ -1322,12 +2465,12 @@ function createBuilderFormEditorPageComponent(deps) {
1322
2465
  }
1323
2466
  });
1324
2467
  if (formId && entityQuery.isPending) {
1325
- return /* @__PURE__ */ jsx4("div", { className: "text-muted-foreground text-sm", children: deps.states.loading });
2468
+ return /* @__PURE__ */ jsx10("div", { className: "text-muted-foreground text-sm", children: deps.states.loading });
1326
2469
  }
1327
2470
  if (formId && entityQuery.isError) {
1328
- return /* @__PURE__ */ jsx4("div", { className: "text-destructive text-sm", children: deps.states.error });
2471
+ return /* @__PURE__ */ jsx10("div", { className: "text-destructive text-sm", children: deps.states.error });
1329
2472
  }
1330
- return /* @__PURE__ */ jsx4(FormProvider, { ...form, children: /* @__PURE__ */ jsx4("form", { onSubmit, noValidate: true, className: "space-y-6", children: /* @__PURE__ */ jsx4(
2473
+ return /* @__PURE__ */ jsx10(FormProvider3, { ...form, children: /* @__PURE__ */ jsx10("form", { onSubmit, noValidate: true, className: "space-y-6", children: /* @__PURE__ */ jsx10(
1331
2474
  Body,
1332
2475
  {
1333
2476
  formId,
@@ -1354,15 +2497,15 @@ function createBuilderListEditorPageComponent(deps) {
1354
2497
  const entityQuery = deps.hooks.useEntity(listId);
1355
2498
  const tables = deps.hooks.useTables();
1356
2499
  const save = deps.hooks.useSave();
1357
- const form = useForm2({
2500
+ const form = useForm4({
1358
2501
  resolver: deps.resolver,
1359
2502
  defaultValues: deps.emptyValues
1360
2503
  });
1361
2504
  const columnArray = useFieldArray({ control: form.control, name: "columns" });
1362
2505
  const triggerArray = useFieldArray({ control: form.control, name: "triggers" });
1363
- const sourceType = useWatch({ control: form.control, name: "sourceType" });
1364
- const sourceTable = useWatch({ control: form.control, name: "sourceTable" });
1365
- useEffect2(() => {
2506
+ const sourceType = useWatch2({ control: form.control, name: "sourceType" });
2507
+ const sourceTable = useWatch2({ control: form.control, name: "sourceTable" });
2508
+ useEffect4(() => {
1366
2509
  if (listId && !entityQuery.data) return;
1367
2510
  form.reset(builderListEditorValuesFromEntity(entityQuery.data ?? null, deps.emptyValues));
1368
2511
  }, [entityQuery.data, form, listId]);
@@ -1381,12 +2524,12 @@ function createBuilderListEditorPageComponent(deps) {
1381
2524
  }
1382
2525
  });
1383
2526
  if (listId && entityQuery.isPending) {
1384
- return /* @__PURE__ */ jsx4("div", { className: "text-muted-foreground text-sm", children: deps.states.loading });
2527
+ return /* @__PURE__ */ jsx10("div", { className: "text-muted-foreground text-sm", children: deps.states.loading });
1385
2528
  }
1386
2529
  if (listId && entityQuery.isError) {
1387
- return /* @__PURE__ */ jsx4("div", { className: "text-destructive text-sm", children: deps.states.error });
2530
+ return /* @__PURE__ */ jsx10("div", { className: "text-destructive text-sm", children: deps.states.error });
1388
2531
  }
1389
- return /* @__PURE__ */ jsx4(FormProvider, { ...form, children: /* @__PURE__ */ jsx4("form", { onSubmit, noValidate: true, className: "space-y-6", children: /* @__PURE__ */ jsx4(
2532
+ return /* @__PURE__ */ jsx10(FormProvider3, { ...form, children: /* @__PURE__ */ jsx10("form", { onSubmit, noValidate: true, className: "space-y-6", children: /* @__PURE__ */ jsx10(
1390
2533
  Body,
1391
2534
  {
1392
2535
  listId,
@@ -1406,7 +2549,7 @@ function createBuilderListEditorPageComponent(deps) {
1406
2549
  }
1407
2550
 
1408
2551
  // src/admin/BuilderAdminPages.tsx
1409
- import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
2552
+ import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
1410
2553
  var defaultFieldTypeOptions = [
1411
2554
  { value: "text", label: "Text" },
1412
2555
  { value: "textarea", label: "Textarea" },
@@ -1534,6 +2677,7 @@ function createBuilderAdminPages({
1534
2677
  const emptyFormValues = {
1535
2678
  title: "",
1536
2679
  description: "",
2680
+ presentation: "dialog",
1537
2681
  sourceType: "none",
1538
2682
  sourceTable: BUILDER_EDITOR_NONE_VALUE,
1539
2683
  apiBasePath: "",
@@ -1663,14 +2807,14 @@ function createBuilderAdminPages({
1663
2807
  href: viewsPath
1664
2808
  }
1665
2809
  ];
1666
- return /* @__PURE__ */ jsxs4("section", { style: homeStyles.page, children: [
1667
- /* @__PURE__ */ jsxs4("div", { children: [
1668
- /* @__PURE__ */ jsx5("h1", { style: homeStyles.headerTitle, children: "Builder" }),
1669
- /* @__PURE__ */ jsx5("p", { style: homeStyles.description, children: "Manage dynamic forms, lists, and views." })
2810
+ return /* @__PURE__ */ jsxs10("section", { style: homeStyles.page, children: [
2811
+ /* @__PURE__ */ jsxs10("div", { children: [
2812
+ /* @__PURE__ */ jsx11("h1", { style: homeStyles.headerTitle, children: "Builder" }),
2813
+ /* @__PURE__ */ jsx11("p", { style: homeStyles.description, children: "Manage dynamic forms, lists, and views." })
1670
2814
  ] }),
1671
- /* @__PURE__ */ jsx5("div", { style: homeStyles.grid, children: items.map((item) => /* @__PURE__ */ jsxs4("a", { href: item.href, style: homeStyles.card, children: [
1672
- /* @__PURE__ */ jsx5("h2", { style: homeStyles.cardTitle, children: item.title }),
1673
- /* @__PURE__ */ jsx5("p", { style: homeStyles.description, children: item.description })
2815
+ /* @__PURE__ */ jsx11("div", { style: homeStyles.grid, children: items.map((item) => /* @__PURE__ */ jsxs10("a", { href: item.href, style: homeStyles.card, children: [
2816
+ /* @__PURE__ */ jsx11("h2", { style: homeStyles.cardTitle, children: item.title }),
2817
+ /* @__PURE__ */ jsx11("p", { style: homeStyles.description, children: item.description })
1674
2818
  ] }, item.href)) })
1675
2819
  ] });
1676
2820
  };
@@ -1759,24 +2903,24 @@ function createBuilderAdminPages({
1759
2903
  AdminHomePage,
1760
2904
  AdminFormsPage,
1761
2905
  AdminNewFormPage: function BuilderAdminNewFormPage() {
1762
- return /* @__PURE__ */ jsx5(FormEditorPage, {});
2906
+ return /* @__PURE__ */ jsx11(FormEditorPage, {});
1763
2907
  },
1764
2908
  AdminEditFormPage: function BuilderAdminEditFormPage({ formId }) {
1765
- return /* @__PURE__ */ jsx5(FormEditorPage, { formId });
2909
+ return /* @__PURE__ */ jsx11(FormEditorPage, { formId });
1766
2910
  },
1767
2911
  AdminListsPage,
1768
2912
  AdminNewListPage: function BuilderAdminNewListPage() {
1769
- return /* @__PURE__ */ jsx5(ListEditorPage, {});
2913
+ return /* @__PURE__ */ jsx11(ListEditorPage, {});
1770
2914
  },
1771
2915
  AdminEditListPage: function BuilderAdminEditListPage({ listId }) {
1772
- return /* @__PURE__ */ jsx5(ListEditorPage, { listId });
2916
+ return /* @__PURE__ */ jsx11(ListEditorPage, { listId });
1773
2917
  },
1774
2918
  AdminViewsPage,
1775
2919
  AdminNewViewPage: function BuilderAdminNewViewPage() {
1776
- return /* @__PURE__ */ jsx5(ViewEditorPage, {});
2920
+ return /* @__PURE__ */ jsx11(ViewEditorPage, {});
1777
2921
  },
1778
2922
  AdminEditViewPage: function BuilderAdminEditViewPage({ viewId }) {
1779
- return /* @__PURE__ */ jsx5(ViewEditorPage, { viewId });
2923
+ return /* @__PURE__ */ jsx11(ViewEditorPage, { viewId });
1780
2924
  },
1781
2925
  routes: {
1782
2926
  adminBasePath,
@@ -1794,16 +2938,16 @@ function createBuilderAdminPages({
1794
2938
  }
1795
2939
 
1796
2940
  // src/admin/BuilderEntityManager.tsx
1797
- import { useCallback, useMemo as useMemo2, useState as useState2 } from "react";
1798
- import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
2941
+ import { useCallback as useCallback2, useMemo as useMemo6, useState as useState6 } from "react";
2942
+ import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
1799
2943
  function createBuilderEntityManagerComponent(deps) {
1800
2944
  return function BuilderEntityManager() {
1801
- const [pendingDelete, setPendingDelete] = useState2(null);
2945
+ const [pendingDelete, setPendingDelete] = useState6(null);
1802
2946
  const state = deps.useDataTableState({ pageSize: 20 });
1803
2947
  const query = deps.hooks.useEntities(state.query);
1804
2948
  const remove = deps.hooks.useDelete();
1805
2949
  const replicate = deps.hooks.useReplicate();
1806
- const columns = useMemo2(
2950
+ const columns = useMemo6(
1807
2951
  () => deps.buildColumns({
1808
2952
  onEdit: deps.navigateToEdit,
1809
2953
  onReplicate: async (entity) => {
@@ -1823,8 +2967,8 @@ function createBuilderEntityManagerComponent(deps) {
1823
2967
  state,
1824
2968
  getRowId: (row) => row.id
1825
2969
  });
1826
- return /* @__PURE__ */ jsxs5("div", { className: "space-y-6", children: [
1827
- /* @__PURE__ */ jsx6(
2970
+ return /* @__PURE__ */ jsxs11("div", { className: "space-y-6", children: [
2971
+ /* @__PURE__ */ jsx12(
1828
2972
  deps.DataGrid,
1829
2973
  {
1830
2974
  title: deps.labels.title,
@@ -1835,10 +2979,10 @@ function createBuilderEntityManagerComponent(deps) {
1835
2979
  emptyTitle: deps.labels.emptyTitle,
1836
2980
  emptyDescription: deps.labels.emptyDescription,
1837
2981
  onRowClick: deps.navigateToEdit,
1838
- toolbarExtra: /* @__PURE__ */ jsx6(deps.AddButton, { href: deps.createHref, label: deps.labels.addLabel })
2982
+ toolbarExtra: /* @__PURE__ */ jsx12(deps.AddButton, { href: deps.createHref, label: deps.labels.addLabel })
1839
2983
  }
1840
2984
  ),
1841
- /* @__PURE__ */ jsx6(
2985
+ /* @__PURE__ */ jsx12(
1842
2986
  deps.DeleteDialog,
1843
2987
  {
1844
2988
  entity: pendingDelete,
@@ -1858,18 +3002,18 @@ function createBuilderEntityManagerComponent(deps) {
1858
3002
  }
1859
3003
  function createBuilderEntityDialogManagerComponent(deps) {
1860
3004
  return function BuilderEntityDialogManager() {
1861
- const [editing, setEditing] = useState2(null);
1862
- const [isEditorOpen, setEditorOpen] = useState2(false);
1863
- const [pendingDelete, setPendingDelete] = useState2(null);
3005
+ const [editing, setEditing] = useState6(null);
3006
+ const [isEditorOpen, setEditorOpen] = useState6(false);
3007
+ const [pendingDelete, setPendingDelete] = useState6(null);
1864
3008
  const state = deps.useDataTableState({ pageSize: 20 });
1865
3009
  const query = deps.hooks.useEntities(state.query);
1866
3010
  const remove = deps.hooks.useDelete();
1867
3011
  const replicate = deps.hooks.useReplicate();
1868
- const openEditor = useCallback((entity) => {
3012
+ const openEditor = useCallback2((entity) => {
1869
3013
  setEditing(entity);
1870
3014
  setEditorOpen(true);
1871
3015
  }, []);
1872
- const columns = useMemo2(
3016
+ const columns = useMemo6(
1873
3017
  () => deps.buildColumns({
1874
3018
  onEdit: (entity) => openEditor(entity),
1875
3019
  onReplicate: async (entity) => {
@@ -1889,8 +3033,8 @@ function createBuilderEntityDialogManagerComponent(deps) {
1889
3033
  state,
1890
3034
  getRowId: (row) => row.id
1891
3035
  });
1892
- return /* @__PURE__ */ jsxs5("div", { className: "space-y-6", children: [
1893
- /* @__PURE__ */ jsx6(
3036
+ return /* @__PURE__ */ jsxs11("div", { className: "space-y-6", children: [
3037
+ /* @__PURE__ */ jsx12(
1894
3038
  deps.DataGrid,
1895
3039
  {
1896
3040
  title: deps.labels.title,
@@ -1901,10 +3045,10 @@ function createBuilderEntityDialogManagerComponent(deps) {
1901
3045
  emptyTitle: deps.labels.emptyTitle,
1902
3046
  emptyDescription: deps.labels.emptyDescription,
1903
3047
  onRowClick: openEditor,
1904
- toolbarExtra: /* @__PURE__ */ jsx6(deps.AddButton, { label: deps.labels.addLabel, onAdd: () => openEditor(null) })
3048
+ toolbarExtra: /* @__PURE__ */ jsx12(deps.AddButton, { label: deps.labels.addLabel, onAdd: () => openEditor(null) })
1905
3049
  }
1906
3050
  ),
1907
- /* @__PURE__ */ jsx6(
3051
+ /* @__PURE__ */ jsx12(
1908
3052
  deps.EditorDialog,
1909
3053
  {
1910
3054
  open: isEditorOpen,
@@ -1912,7 +3056,7 @@ function createBuilderEntityDialogManagerComponent(deps) {
1912
3056
  onClose: () => setEditorOpen(false)
1913
3057
  }
1914
3058
  ),
1915
- /* @__PURE__ */ jsx6(
3059
+ /* @__PURE__ */ jsx12(
1916
3060
  deps.DeleteDialog,
1917
3061
  {
1918
3062
  entity: pendingDelete,
@@ -1932,9 +3076,9 @@ function createBuilderEntityDialogManagerComponent(deps) {
1932
3076
  }
1933
3077
 
1934
3078
  // src/admin/BuilderViewDialog.tsx
1935
- import { useEffect as useEffect3 } from "react";
1936
- import { FormProvider as FormProvider2, useForm as useForm3 } from "react-hook-form";
1937
- import { jsx as jsx7 } from "react/jsx-runtime";
3079
+ import { useEffect as useEffect5 } from "react";
3080
+ import { FormProvider as FormProvider4, useForm as useForm5 } from "react-hook-form";
3081
+ import { jsx as jsx13 } from "react/jsx-runtime";
1938
3082
  function createBuilderViewDialogComponent(deps) {
1939
3083
  return function BuilderViewDialog({
1940
3084
  open,
@@ -1945,11 +3089,11 @@ function createBuilderViewDialogComponent(deps) {
1945
3089
  onSave,
1946
3090
  isSaving
1947
3091
  }) {
1948
- const form = useForm3({
3092
+ const form = useForm5({
1949
3093
  resolver: deps.resolver,
1950
3094
  defaultValues: deps.emptyValues
1951
3095
  });
1952
- useEffect3(() => {
3096
+ useEffect5(() => {
1953
3097
  if (!open) return;
1954
3098
  form.reset(
1955
3099
  builderViewEditorValuesFromEntity(editing, deps.emptyValues, deps.defaultPermission)
@@ -1964,7 +3108,7 @@ function createBuilderViewDialogComponent(deps) {
1964
3108
  deps.notifications.error(error);
1965
3109
  }
1966
3110
  });
1967
- return /* @__PURE__ */ jsx7(deps.Shell, { open, editing, onClose, children: /* @__PURE__ */ jsx7(FormProvider2, { ...form, children: /* @__PURE__ */ jsx7("form", { onSubmit, noValidate: true, children: deps.Body({
3111
+ return /* @__PURE__ */ jsx13(deps.Shell, { open, editing, onClose, children: /* @__PURE__ */ jsx13(FormProvider4, { ...form, children: /* @__PURE__ */ jsx13("form", { onSubmit, noValidate: true, children: deps.Body({
1968
3112
  form,
1969
3113
  editing,
1970
3114
  forms,
@@ -1978,8 +3122,8 @@ function createBuilderViewDialogComponent(deps) {
1978
3122
  }
1979
3123
 
1980
3124
  // src/admin/formLayoutEditorState.ts
1981
- import { useMemo as useMemo3 } from "react";
1982
- import { useWatch as useWatch2 } from "react-hook-form";
3125
+ import { useMemo as useMemo7 } from "react";
3126
+ import { useWatch as useWatch3 } from "react-hook-form";
1983
3127
  var builderFormLayoutDragDataType = "application/x-winu-builder-layout-field";
1984
3128
  function clampBuilderFormLayoutSpan(span, columns) {
1985
3129
  return Math.max(1, Math.min(columns, span));
@@ -2026,8 +3170,8 @@ function parseBuilderFormLayoutDragPayload(raw) {
2026
3170
  }
2027
3171
  }
2028
3172
  function useBuilderFormLayoutEditor({ form, fields, subforms = [] }) {
2029
- const layoutGroups = useWatch2({ control: form.control, name: "layoutGroups" }) ?? [];
2030
- const layoutItems = useMemo3(
3173
+ const layoutGroups = useWatch3({ control: form.control, name: "layoutGroups" }) ?? [];
3174
+ const layoutItems = useMemo7(
2031
3175
  () => [
2032
3176
  ...fields.map((field) => ({
2033
3177
  key: field.key,
@@ -2044,11 +3188,11 @@ function useBuilderFormLayoutEditor({ form, fields, subforms = [] }) {
2044
3188
  ],
2045
3189
  [fields, subforms]
2046
3190
  );
2047
- const assignedKeys = useMemo3(
3191
+ const assignedKeys = useMemo7(
2048
3192
  () => new Set(layoutGroups.flatMap((group) => group.fields.map((field) => field.key))),
2049
3193
  [layoutGroups]
2050
3194
  );
2051
- const unassignedItems = useMemo3(
3195
+ const unassignedItems = useMemo7(
2052
3196
  () => layoutItems.filter((item) => !assignedKeys.has(item.key)),
2053
3197
  [assignedKeys, layoutItems]
2054
3198
  );
@@ -2133,149 +3277,32 @@ function useBuilderFormLayoutEditor({ form, fields, subforms = [] }) {
2133
3277
  return {
2134
3278
  assignedKeys,
2135
3279
  layoutGroups,
2136
- layoutItems,
2137
- unassignedItems,
2138
- addGroup,
2139
- addItemToGroup,
2140
- addItemToNewGroup,
2141
- applyDragPayload,
2142
- resetDefaultLayout,
2143
- setGroups,
2144
- updateGroup,
2145
- updateGroupFields
2146
- };
2147
- }
2148
-
2149
- // src/api/createBuilderApiClient.ts
2150
- function queryParams(query) {
2151
- return { ...query };
2152
- }
2153
- function fieldOptionsQueryParams(query) {
2154
- const flatQuery = { search: query.search };
2155
- for (const [key, value] of Object.entries(query.depends ?? {})) {
2156
- flatQuery[`depends.${key}`] = value;
2157
- }
2158
- return flatQuery;
2159
- }
2160
- function createBuilderApiClient(transport) {
2161
- return {
2162
- listBuilderForms: (query) => transport.get("/builder/forms", {
2163
- query: queryParams(query)
2164
- }),
2165
- listBuilderDbTables: () => transport.get("/builder/datasources/tables"),
2166
- listBuilderFormOptions: () => transport.get("/builder/forms/options"),
2167
- getBuilderForm: (id) => transport.get(`/builder/forms/${encodeURIComponent(id)}`),
2168
- createBuilderForm: (input) => transport.post("/builder/forms", input),
2169
- updateBuilderForm: (id, input) => transport.patch(`/builder/forms/${encodeURIComponent(id)}`, input),
2170
- replicateBuilderForm: (id, input) => transport.post(`/builder/forms/${encodeURIComponent(id)}/replicate`, input),
2171
- deleteBuilderForm: (id) => transport.delete(`/builder/forms/${encodeURIComponent(id)}`),
2172
- listBuilderLists: (query) => transport.get("/builder/lists", {
2173
- query: queryParams(query)
2174
- }),
2175
- listBuilderListOptions: () => transport.get("/builder/lists/options"),
2176
- getBuilderList: (id) => transport.get(`/builder/lists/${encodeURIComponent(id)}`),
2177
- createBuilderList: (input) => transport.post("/builder/lists", input),
2178
- updateBuilderList: (id, input) => transport.patch(`/builder/lists/${encodeURIComponent(id)}`, input),
2179
- replicateBuilderList: (id, input) => transport.post(`/builder/lists/${encodeURIComponent(id)}/replicate`, input),
2180
- deleteBuilderList: (id) => transport.delete(`/builder/lists/${encodeURIComponent(id)}`),
2181
- listBuilderViews: (query) => transport.get("/builder/views", {
2182
- query: queryParams(query)
2183
- }),
2184
- getBuilderView: (id) => transport.get(`/builder/views/${encodeURIComponent(id)}`),
2185
- createBuilderView: (input) => transport.post("/builder/views", input),
2186
- updateBuilderView: (id, input) => transport.patch(`/builder/views/${encodeURIComponent(id)}`, input),
2187
- replicateBuilderView: (id, input) => transport.post(`/builder/views/${encodeURIComponent(id)}/replicate`, input),
2188
- deleteBuilderView: (id) => transport.delete(`/builder/views/${encodeURIComponent(id)}`),
2189
- getRuntimeBuilderForm: (id) => transport.get(`/builder/runtime/forms/${encodeURIComponent(id)}`),
2190
- createRuntimeBuilderFormEntry: (formId, input) => transport.post(
2191
- `/builder/runtime/forms/${encodeURIComponent(formId)}/entries`,
2192
- input
2193
- ),
2194
- listRuntimeBuilderFormFieldOptions: (formId, fieldKey, query) => transport.get(
2195
- `/builder/runtime/forms/${encodeURIComponent(formId)}/fields/${encodeURIComponent(fieldKey)}/options`,
2196
- { query: fieldOptionsQueryParams(query) }
2197
- ),
2198
- runRuntimeBuilderFormFieldTrigger: (formId, fieldKey, event, input) => transport.post(
2199
- `/builder/runtime/forms/${encodeURIComponent(formId)}/fields/${encodeURIComponent(fieldKey)}/triggers/${encodeURIComponent(event)}`,
2200
- input
2201
- ),
2202
- getRuntimeBuilderList: (id) => transport.get(`/builder/runtime/lists/${encodeURIComponent(id)}`),
2203
- listRuntimeBuilderListEntries: (listId, query) => transport.get(
2204
- `/builder/runtime/lists/${encodeURIComponent(listId)}/entries`,
2205
- { query: queryParams(query) }
2206
- ),
2207
- getRuntimeBuilderView: (id) => transport.get(`/builder/runtime/views/${encodeURIComponent(id)}`),
2208
- runRuntimeBuilderViewFieldTrigger: (viewId, fieldKey, event, input) => transport.post(
2209
- `/builder/runtime/views/${encodeURIComponent(viewId)}/fields/${encodeURIComponent(fieldKey)}/triggers/${encodeURIComponent(event)}`,
2210
- input
2211
- ),
2212
- listBuilderViewEntries: (viewId, query) => transport.get(
2213
- `/builder/runtime/views/${encodeURIComponent(viewId)}/entries`,
2214
- { query: queryParams(query) }
2215
- ),
2216
- createBuilderViewEntry: (viewId, input) => transport.post(
2217
- `/builder/runtime/views/${encodeURIComponent(viewId)}/entries`,
2218
- input
2219
- ),
2220
- createCompositeBuilderViewEntry: (viewId, input) => transport.post(
2221
- `/builder/runtime/views/${encodeURIComponent(viewId)}/composite-entries`,
2222
- input
2223
- ),
2224
- updateCompositeBuilderViewEntry: (viewId, id, input) => transport.patch(
2225
- `/builder/runtime/views/${encodeURIComponent(viewId)}/composite-entries/${encodeURIComponent(id)}`,
2226
- input
2227
- ),
2228
- updateBuilderViewEntry: (viewId, id, input) => transport.patch(
2229
- `/builder/runtime/views/${encodeURIComponent(viewId)}/entries/${encodeURIComponent(id)}`,
2230
- input
2231
- ),
2232
- deleteBuilderViewEntry: (viewId, id) => transport.delete(
2233
- `/builder/runtime/views/${encodeURIComponent(viewId)}/entries/${encodeURIComponent(id)}`
2234
- )
3280
+ layoutItems,
3281
+ unassignedItems,
3282
+ addGroup,
3283
+ addItemToGroup,
3284
+ addItemToNewGroup,
3285
+ applyDragPayload,
3286
+ resetDefaultLayout,
3287
+ setGroups,
3288
+ updateGroup,
3289
+ updateGroupFields
2235
3290
  };
2236
3291
  }
2237
3292
 
2238
3293
  // src/components/DynamicForm.tsx
2239
- import { useMemo as useMemo4 } from "react";
2240
- import { FormProvider as FormProvider3, useForm as useForm4 } from "react-hook-form";
2241
-
2242
- // src/runtime/runtimeUtils.ts
2243
- function emptyFieldValue(field) {
2244
- return field.type === "checkbox" ? false : "";
2245
- }
2246
- function createBuilderFormDefaultValues(schema) {
2247
- const values = {};
2248
- for (const field of schema?.fields ?? []) {
2249
- values[field.key] = emptyFieldValue(field);
2250
- }
2251
- return { values };
2252
- }
2253
- function createBuilderEntryDefaultValues(view, editing) {
2254
- const values = {};
2255
- for (const field of view.form?.schema.fields ?? []) {
2256
- const existing = editing?.values[field.key];
2257
- values[field.key] = existing === void 0 ? emptyFieldValue(field) : existing;
2258
- }
2259
- return { values, version: editing?.version ?? 0 };
2260
- }
2261
- function formatBuilderRuntimeValue(value, locale = "mn-MN") {
2262
- if (value === null || value === void 0 || value === "") return "\u2014";
2263
- if (typeof value === "boolean") return value ? "\u0422\u0438\u0439\u043C" : "\u04AE\u0433\u04AF\u0439";
2264
- if (typeof value === "number") return new Intl.NumberFormat(locale).format(value);
2265
- return String(value);
2266
- }
2267
-
2268
- // src/components/DynamicForm.tsx
2269
- import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
3294
+ import { useMemo as useMemo8 } from "react";
3295
+ import { FormProvider as FormProvider5, useForm as useForm6 } from "react-hook-form";
3296
+ import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
2270
3297
  function createDynamicFormComponent(deps) {
2271
3298
  return function DynamicForm({ formId }) {
2272
3299
  const query = deps.hooks.useRuntimeBuilderForm(formId);
2273
3300
  const save = deps.hooks.useSaveRuntimeBuilderFormEntry(formId);
2274
- const formValues = useMemo4(
3301
+ const formValues = useMemo8(
2275
3302
  () => query.data ? createBuilderFormDefaultValues(query.data.schema) : void 0,
2276
3303
  [query.data]
2277
3304
  );
2278
- const form = useForm4({
3305
+ const form = useForm6({
2279
3306
  defaultValues: createBuilderFormDefaultValues(query.data?.schema),
2280
3307
  values: formValues
2281
3308
  });
@@ -2289,7 +3316,7 @@ function createDynamicFormComponent(deps) {
2289
3316
  }
2290
3317
  });
2291
3318
  if (query.isError) {
2292
- return /* @__PURE__ */ jsx8(
3319
+ return /* @__PURE__ */ jsx14(
2293
3320
  deps.ErrorState,
2294
3321
  {
2295
3322
  title: "Form \u043D\u044D\u044D\u0433\u0434\u0441\u044D\u043D\u0433\u04AF\u0439",
@@ -2298,22 +3325,22 @@ function createDynamicFormComponent(deps) {
2298
3325
  );
2299
3326
  }
2300
3327
  if (!query.data) return null;
2301
- return /* @__PURE__ */ jsx8(deps.FormShell, { title: query.data.title, children: /* @__PURE__ */ jsx8(FormProvider3, { ...form, children: /* @__PURE__ */ jsxs6("form", { onSubmit, noValidate: true, className: "space-y-6", children: [
2302
- /* @__PURE__ */ jsx8(deps.FormFields, { formId, schema: query.data.schema, namePrefix: "values" }),
2303
- /* @__PURE__ */ jsx8(deps.SubmitButton, { isSaving: save.isPending })
3328
+ return /* @__PURE__ */ jsx14(deps.FormShell, { title: query.data.title, children: /* @__PURE__ */ jsx14(FormProvider5, { ...form, children: /* @__PURE__ */ jsxs12("form", { onSubmit, noValidate: true, className: "space-y-6", children: [
3329
+ /* @__PURE__ */ jsx14(deps.FormFields, { formId, schema: query.data.schema, namePrefix: "values" }),
3330
+ /* @__PURE__ */ jsx14(deps.SubmitButton, { isSaving: save.isPending })
2304
3331
  ] }) }) });
2305
3332
  };
2306
3333
  }
2307
3334
 
2308
3335
  // src/components/DynamicList.tsx
2309
- import { useMemo as useMemo5 } from "react";
2310
- import { jsx as jsx9 } from "react/jsx-runtime";
3336
+ import { useMemo as useMemo9 } from "react";
3337
+ import { jsx as jsx15 } from "react/jsx-runtime";
2311
3338
  function createDynamicListComponent(deps) {
2312
3339
  return function DynamicList({ listId }) {
2313
3340
  const query = deps.hooks.useRuntimeBuilderList(listId);
2314
3341
  const state = deps.useDataTableState({ pageSize: 20 });
2315
3342
  const entriesQuery = deps.hooks.useRuntimeBuilderListEntries(listId, state.query);
2316
- const columns = useMemo5(() => query.data ? deps.buildColumns(query.data) : [], [query.data]);
3343
+ const columns = useMemo9(() => query.data ? deps.buildColumns(query.data) : [], [query.data]);
2317
3344
  const entries = entriesQuery.data?.items ?? [];
2318
3345
  const controller = deps.useDataTable({
2319
3346
  columns,
@@ -2323,7 +3350,7 @@ function createDynamicListComponent(deps) {
2323
3350
  getRowId: (row) => row.id
2324
3351
  });
2325
3352
  if (query.isError) {
2326
- return /* @__PURE__ */ jsx9(
3353
+ return /* @__PURE__ */ jsx15(
2327
3354
  deps.ErrorState,
2328
3355
  {
2329
3356
  title: "List \u043D\u044D\u044D\u0433\u0434\u0441\u044D\u043D\u0433\u04AF\u0439",
@@ -2331,560 +3358,269 @@ function createDynamicListComponent(deps) {
2331
3358
  }
2332
3359
  );
2333
3360
  }
2334
- return /* @__PURE__ */ jsx9(
3361
+ return /* @__PURE__ */ jsx15(
2335
3362
  deps.DataGrid,
2336
3363
  {
2337
3364
  title: query.data?.title ?? "Dynamic List",
2338
- description: query.data?.description ?? `/winu/list?id=${listId}`,
2339
- controller,
2340
- isLoading: query.isPending || entriesQuery.isPending,
2341
- searchPlaceholder: "\u041C\u04E9\u0440 \u0445\u0430\u0439\u0445...",
2342
- emptyTitle: "\u041C\u04E9\u0440 \u0430\u043B\u0433\u0430",
2343
- emptyDescription: "\u042D\u043D\u044D list-\u0438\u0439\u043D datasource \u0434\u044D\u044D\u0440 \u043C\u04E9\u0440 \u0430\u043B\u0433\u0430."
2344
- }
2345
- );
2346
- };
2347
- }
2348
-
2349
- // src/components/DynamicView.tsx
2350
- import { useMemo as useMemo6, useState as useState3 } from "react";
2351
- import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
2352
- function createDynamicViewComponent(deps) {
2353
- return function DynamicView({ viewId }) {
2354
- const [editing, setEditing] = useState3(null);
2355
- const [isDialogOpen, setDialogOpen] = useState3(false);
2356
- const [pendingDelete, setPendingDelete] = useState3(null);
2357
- const viewQuery = deps.hooks.useRuntimeBuilderView(viewId);
2358
- const state = deps.useDataTableState({ pageSize: 20 });
2359
- const entriesQuery = deps.hooks.useBuilderViewEntries(viewId, state.query);
2360
- const save = deps.hooks.useSaveBuilderViewEntry(viewId);
2361
- const remove = deps.hooks.useDeleteBuilderViewEntry(viewId);
2362
- const view = viewQuery.data;
2363
- const columns = useMemo6(
2364
- () => view ? deps.buildColumns(view, {
2365
- onEdit: (entry) => {
2366
- setEditing(entry);
2367
- setDialogOpen(true);
2368
- },
2369
- onDelete: setPendingDelete
2370
- }) : [],
2371
- [view]
2372
- );
2373
- const controller = deps.useDataTable({
2374
- columns,
2375
- data: entriesQuery.data?.items ?? [],
2376
- rowCount: entriesQuery.data?.total ?? 0,
2377
- state,
2378
- getRowId: (row) => row.id
2379
- });
2380
- if (viewQuery.isError) {
2381
- return /* @__PURE__ */ jsx10(
2382
- deps.ErrorState,
2383
- {
2384
- title: "View \u043D\u044D\u044D\u0433\u0434\u0441\u044D\u043D\u0433\u04AF\u0439",
2385
- description: `\xAB${viewId}\xBB id-\u0442\u0430\u0439 view \u043E\u043B\u0434\u0441\u043E\u043D\u0433\u04AF\u0439.`
2386
- }
2387
- );
2388
- }
2389
- return /* @__PURE__ */ jsxs7("div", { className: "space-y-6", children: [
2390
- /* @__PURE__ */ jsx10(
2391
- deps.DataGrid,
2392
- {
2393
- title: view?.title ?? "Dynamic View",
2394
- description: view?.description ?? `/winu/view?id=${viewId}`,
2395
- controller,
2396
- isLoading: viewQuery.isPending || entriesQuery.isPending,
2397
- searchPlaceholder: "\u041C\u04E9\u0440 \u0445\u0430\u0439\u0445...",
2398
- emptyTitle: "\u041C\u04E9\u0440 \u0430\u043B\u0433\u0430",
2399
- emptyDescription: "\u042D\u043D\u044D view \u0434\u044D\u044D\u0440 \u044D\u0445\u043D\u0438\u0439 \u043C\u04E9\u0440\u04E9\u04E9 \u043D\u044D\u043C\u044D\u044D\u0440\u044D\u0439.",
2400
- onRowClick: (entry) => {
2401
- setEditing(entry);
2402
- setDialogOpen(true);
2403
- },
2404
- toolbarExtra: /* @__PURE__ */ jsx10(
2405
- deps.AddButton,
2406
- {
2407
- disabled: !view?.form,
2408
- onAdd: () => {
2409
- setEditing(null);
2410
- setDialogOpen(true);
2411
- }
2412
- }
2413
- )
2414
- }
2415
- ),
2416
- view ? /* @__PURE__ */ jsx10(
2417
- deps.EntryDialog,
2418
- {
2419
- open: isDialogOpen,
2420
- view,
2421
- editing,
2422
- onClose: () => setDialogOpen(false),
2423
- onSave: save.mutateAsync,
2424
- isSaving: save.isPending
2425
- }
2426
- ) : null,
2427
- /* @__PURE__ */ jsx10(
2428
- deps.DeleteDialog,
2429
- {
2430
- entry: pendingDelete,
2431
- isDeleting: remove.isPending,
2432
- onClose: () => setPendingDelete(null),
2433
- onConfirm: async () => {
2434
- if (!pendingDelete) return;
2435
- await remove.mutateAsync(pendingDelete.id);
2436
- setPendingDelete(null);
2437
- }
2438
- }
2439
- )
2440
- ] });
2441
- };
2442
- }
2443
-
2444
- // src/components/RuntimeEntryDialog.tsx
2445
- import { useEffect as useEffect4, useMemo as useMemo7, useState as useState4 } from "react";
2446
- import { FormProvider as FormProvider4, useForm as useForm5 } from "react-hook-form";
2447
- import { jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
2448
- function isDbTableSource(source) {
2449
- return source?.type === "dbTable" && "tableName" in source;
2450
- }
2451
- function runtimeViewTableName(view) {
2452
- const listSource = view.list?.source;
2453
- if (isDbTableSource(listSource)) return listSource.tableName;
2454
- const formSource = view.form?.source;
2455
- return isDbTableSource(formSource) ? formSource.tableName : void 0;
2456
- }
2457
- function cleanRowValues(values) {
2458
- return Object.fromEntries(
2459
- Object.entries(values).filter(([key]) => key === "_delete" || !key.startsWith("_"))
2460
- );
2461
- }
2462
- function childRowPayload(row, includeIdentity) {
2463
- const values = cleanRowValues(row.values);
2464
- if (!includeIdentity || row.values._draftNew === true) return values;
2465
- return {
2466
- id: row.id,
2467
- version: row.version,
2468
- ...values
2469
- };
2470
- }
2471
- function createRuntimeEntryDialogComponent(deps) {
2472
- return function RuntimeEntryDialog({
2473
- open,
2474
- view,
2475
- editing,
2476
- onClose,
2477
- onSave,
2478
- isSaving
2479
- }) {
2480
- const [draftSubforms, setDraftSubforms] = useState4({});
2481
- const compositeCreate = deps.useCreateCompositeEntry?.(view.id);
2482
- const compositeUpdate = deps.useUpdateCompositeEntry?.(view.id);
2483
- const form = useForm5({
2484
- defaultValues: createBuilderEntryDefaultValues(view, editing),
2485
- values: open ? createBuilderEntryDefaultValues(view, editing) : void 0
2486
- });
2487
- const mainTableName = runtimeViewTableName(view);
2488
- const hasDraftRows = useMemo7(
2489
- () => Object.values(draftSubforms).some((draft) => draft.rows.length > 0),
2490
- [draftSubforms]
2491
- );
2492
- useEffect4(() => {
2493
- if (open) setDraftSubforms({});
2494
- }, [open]);
2495
- const onSubmit = form.handleSubmit(async (values) => {
2496
- try {
2497
- if (!editing && hasDraftRows) {
2498
- if (!mainTableName) throw new Error("Main form datasource table \u043E\u043B\u0434\u0441\u043E\u043D\u0433\u04AF\u0439");
2499
- if (!compositeCreate) throw new Error("Composite create handler \u0442\u043E\u0445\u0438\u0440\u0443\u0443\u043B\u0430\u0433\u0434\u0430\u0430\u0433\u04AF\u0439 \u0431\u0430\u0439\u043D\u0430");
2500
- await compositeCreate.mutateAsync({
2501
- data: {
2502
- [mainTableName]: values.values,
2503
- ...Object.fromEntries(
2504
- Object.values(draftSubforms).map((draft) => [
2505
- draft.dataKey,
2506
- draft.rows.filter((row) => row.values._delete !== true).map((row) => childRowPayload(row, false))
2507
- ])
2508
- )
2509
- }
2510
- });
2511
- } else if (editing && hasDraftRows) {
2512
- if (!mainTableName) throw new Error("Main form datasource table \u043E\u043B\u0434\u0441\u043E\u043D\u0433\u04AF\u0439");
2513
- if (!compositeUpdate) throw new Error("Composite update handler \u0442\u043E\u0445\u0438\u0440\u0443\u0443\u043B\u0430\u0433\u0434\u0430\u0430\u0433\u04AF\u0439 \u0431\u0430\u0439\u043D\u0430");
2514
- await compositeUpdate.mutateAsync({
2515
- id: editing.id,
2516
- input: {
2517
- data: {
2518
- [mainTableName]: {
2519
- id: editing.id,
2520
- version: values.version,
2521
- ...values.values
2522
- },
2523
- ...Object.fromEntries(
2524
- Object.values(draftSubforms).map((draft) => [
2525
- draft.dataKey,
2526
- draft.rows.map((row) => childRowPayload(row, true))
2527
- ])
2528
- )
2529
- }
2530
- }
2531
- });
2532
- } else {
2533
- await onSave({ id: editing?.id, input: values });
2534
- }
2535
- onClose();
2536
- deps.notifications.success(editing ? "\u041C\u04E9\u0440 \u0445\u0430\u0434\u0433\u0430\u043B\u0430\u0433\u0434\u043B\u0430\u0430" : "\u041C\u04E9\u0440 \u043D\u044D\u043C\u044D\u0433\u0434\u043B\u044D\u044D");
2537
- } catch (error) {
2538
- deps.notifications.error(deps.notifications.errorMessage(error, "\u0425\u0430\u0434\u0433\u0430\u043B\u0430\u0445\u0430\u0434 \u0430\u043B\u0434\u0430\u0430 \u0433\u0430\u0440\u043B\u0430\u0430"));
2539
- }
2540
- });
2541
- const saving = isSaving || Boolean(compositeCreate?.isPending || compositeUpdate?.isPending);
2542
- const extraItems = deps.SubformField && view.form?.schema.subforms?.length ? view.form.schema.subforms.map((subform) => ({
2543
- key: subform.key,
2544
- render: () => deps.SubformField ? /* @__PURE__ */ jsx11(
2545
- deps.SubformField,
2546
- {
2547
- subform,
2548
- parentEntry: editing,
2549
- draftRows: draftSubforms[subform.key]?.rows ?? [],
2550
- onDraftRowsChange: ({ subformKey, dataKey, rows }) => {
2551
- setDraftSubforms((current) => ({
2552
- ...current,
2553
- [subformKey]: { dataKey, rows }
2554
- }));
2555
- }
2556
- }
2557
- ) : null
2558
- })) : void 0;
2559
- return /* @__PURE__ */ jsx11(
2560
- deps.DialogShell,
2561
- {
2562
- open,
2563
- title: editing ? "\u041C\u04E9\u0440 \u0437\u0430\u0441\u0430\u0445" : "\u041C\u04E9\u0440 \u043D\u044D\u043C\u044D\u0445",
2564
- description: view.title,
2565
- onClose,
2566
- children: /* @__PURE__ */ jsx11(FormProvider4, { ...form, children: /* @__PURE__ */ jsxs8("form", { onSubmit, noValidate: true, className: deps.formClassName, children: [
2567
- view.form ? /* @__PURE__ */ jsx11(
2568
- deps.FormFields,
2569
- {
2570
- formId: view.form.id,
2571
- viewId: view.id,
2572
- entry: editing,
2573
- schema: view.form.schema,
2574
- namePrefix: "values",
2575
- extraItems
2576
- }
2577
- ) : null,
2578
- /* @__PURE__ */ jsx11(deps.Actions, { isSaving: saving, onClose })
2579
- ] }) })
3365
+ description: query.data?.description ?? `/winu/list?id=${listId}`,
3366
+ controller,
3367
+ isLoading: query.isPending || entriesQuery.isPending,
3368
+ searchPlaceholder: "\u041C\u04E9\u0440 \u0445\u0430\u0439\u0445...",
3369
+ emptyTitle: "\u041C\u04E9\u0440 \u0430\u043B\u0433\u0430",
3370
+ emptyDescription: "\u042D\u043D\u044D list-\u0438\u0439\u043D datasource \u0434\u044D\u044D\u0440 \u043C\u04E9\u0440 \u0430\u043B\u0433\u0430."
2580
3371
  }
2581
3372
  );
2582
3373
  };
2583
3374
  }
2584
3375
 
2585
- // src/hooks/createBuilderHooks.ts
2586
- import { keepPreviousData, useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
2587
- function createBuilderKeys() {
2588
- const builderKeys = {
2589
- forms: ["builder", "forms"],
2590
- dbTables: () => ["builder", "datasources", "tables"],
2591
- formList: (query) => [...builderKeys.forms, "list", query],
2592
- form: (id) => [...builderKeys.forms, "detail", id],
2593
- formOptions: () => [...builderKeys.forms, "options"],
2594
- lists: ["builder", "lists"],
2595
- listList: (query) => [...builderKeys.lists, "list", query],
2596
- list: (id) => [...builderKeys.lists, "detail", id],
2597
- listOptions: () => [...builderKeys.lists, "options"],
2598
- views: ["builder", "views"],
2599
- viewList: (query) => [...builderKeys.views, "list", query],
2600
- view: (id) => [...builderKeys.views, "detail", id],
2601
- runtimeForm: (id) => ["builder", "runtime", "form", id],
2602
- runtimeFieldOptions: (formId, fieldKey, query) => [...builderKeys.runtimeForm(formId), "fields", fieldKey, "options", query],
2603
- runtimeFormEntries: (id) => [...builderKeys.runtimeForm(id), "entries"],
2604
- runtimeList: (id) => ["builder", "runtime", "list", id],
2605
- runtimeListEntries: (id, query) => [...builderKeys.runtimeList(id), "entries", query],
2606
- runtimeView: (id) => ["builder", "runtime", "view", id],
2607
- entries: (id, query) => [...builderKeys.runtimeView(id), "entries", query]
2608
- };
2609
- return builderKeys;
3376
+ // src/components/DynamicView.tsx
3377
+ import { useMemo as useMemo10, useState as useState7 } from "react";
3378
+ import { jsx as jsx16, jsxs as jsxs13 } from "react/jsx-runtime";
3379
+ var interactiveRowTargetSelector = "button,a,input,select,textarea,[role='button'],[role='menuitem'],[data-builder-row-action]";
3380
+ function hasClosest(target) {
3381
+ return typeof target === "object" && target !== null && "closest" in target && typeof target.closest === "function";
2610
3382
  }
2611
- function createBuilderHooks(client) {
2612
- const builderKeys = createBuilderKeys();
2613
- function invalidateRuntimeViewEntries(queryClient, viewId) {
2614
- return Promise.all([
2615
- queryClient.invalidateQueries({ queryKey: builderKeys.runtimeView(viewId) }),
2616
- queryClient.invalidateQueries({ queryKey: [...builderKeys.runtimeView(viewId), "entries"] })
2617
- ]);
2618
- }
2619
- function useBuilderDbTables() {
2620
- return useQuery({ queryKey: builderKeys.dbTables(), queryFn: client.listBuilderDbTables });
2621
- }
2622
- function useBuilderForms(query) {
2623
- return useQuery({
2624
- queryKey: builderKeys.formList(query),
2625
- queryFn: () => client.listBuilderForms(query),
2626
- placeholderData: keepPreviousData
2627
- });
2628
- }
2629
- function useBuilderFormOptions() {
2630
- return useQuery({
2631
- queryKey: builderKeys.formOptions(),
2632
- queryFn: client.listBuilderFormOptions
2633
- });
2634
- }
2635
- function useBuilderForm(id) {
2636
- return useQuery({
2637
- queryKey: builderKeys.form(id ?? ""),
2638
- queryFn: () => client.getBuilderForm(id ?? ""),
2639
- enabled: Boolean(id)
2640
- });
2641
- }
2642
- function useSaveBuilderForm() {
2643
- const queryClient = useQueryClient();
2644
- return useMutation({
2645
- mutationFn: ({ id, input }) => id ? client.updateBuilderForm(id, input) : client.createBuilderForm(input),
2646
- onSuccess: (form) => {
2647
- queryClient.invalidateQueries({ queryKey: builderKeys.forms });
2648
- queryClient.invalidateQueries({ queryKey: builderKeys.form(form.id) });
2649
- queryClient.invalidateQueries({ queryKey: builderKeys.runtimeForm(form.id) });
2650
- }
2651
- });
2652
- }
2653
- function useReplicateBuilderForm() {
2654
- const queryClient = useQueryClient();
2655
- return useMutation({
2656
- mutationFn: ({ id, input }) => client.replicateBuilderForm(id, input),
2657
- onSuccess: () => queryClient.invalidateQueries({ queryKey: builderKeys.forms })
2658
- });
2659
- }
2660
- function useDeleteBuilderForm() {
2661
- const queryClient = useQueryClient();
2662
- return useMutation({
2663
- mutationFn: client.deleteBuilderForm,
2664
- onSuccess: () => queryClient.invalidateQueries({ queryKey: builderKeys.forms })
2665
- });
2666
- }
2667
- function useBuilderLists(query) {
2668
- return useQuery({
2669
- queryKey: builderKeys.listList(query),
2670
- queryFn: () => client.listBuilderLists(query),
2671
- placeholderData: keepPreviousData
2672
- });
2673
- }
2674
- function useBuilderListOptions() {
2675
- return useQuery({
2676
- queryKey: builderKeys.listOptions(),
2677
- queryFn: client.listBuilderListOptions
2678
- });
2679
- }
2680
- function useBuilderList(id) {
2681
- return useQuery({
2682
- queryKey: builderKeys.list(id ?? ""),
2683
- queryFn: () => client.getBuilderList(id ?? ""),
2684
- enabled: Boolean(id)
2685
- });
2686
- }
2687
- function useSaveBuilderList() {
2688
- const queryClient = useQueryClient();
2689
- return useMutation({
2690
- mutationFn: ({ id, input }) => id ? client.updateBuilderList(id, input) : client.createBuilderList(input),
2691
- onSuccess: (list) => {
2692
- queryClient.invalidateQueries({ queryKey: builderKeys.lists });
2693
- queryClient.invalidateQueries({ queryKey: builderKeys.list(list.id) });
2694
- queryClient.invalidateQueries({ queryKey: builderKeys.runtimeList(list.id) });
2695
- }
2696
- });
2697
- }
2698
- function useReplicateBuilderList() {
2699
- const queryClient = useQueryClient();
2700
- return useMutation({
2701
- mutationFn: ({ id, input }) => client.replicateBuilderList(id, input),
2702
- onSuccess: () => queryClient.invalidateQueries({ queryKey: builderKeys.lists })
2703
- });
2704
- }
2705
- function useDeleteBuilderList() {
2706
- const queryClient = useQueryClient();
2707
- return useMutation({
2708
- mutationFn: client.deleteBuilderList,
2709
- onSuccess: () => queryClient.invalidateQueries({ queryKey: builderKeys.lists })
2710
- });
2711
- }
2712
- function useBuilderViews(query) {
2713
- return useQuery({
2714
- queryKey: builderKeys.viewList(query),
2715
- queryFn: () => client.listBuilderViews(query),
2716
- placeholderData: keepPreviousData
2717
- });
2718
- }
2719
- function useBuilderView(id) {
2720
- return useQuery({
2721
- queryKey: builderKeys.view(id ?? ""),
2722
- queryFn: () => client.getBuilderView(id ?? ""),
2723
- enabled: Boolean(id)
2724
- });
2725
- }
2726
- function useSaveBuilderView() {
2727
- const queryClient = useQueryClient();
2728
- return useMutation({
2729
- mutationFn: ({ id, input }) => id ? client.updateBuilderView(id, input) : client.createBuilderView(input),
2730
- onSuccess: () => queryClient.invalidateQueries({ queryKey: builderKeys.views })
2731
- });
2732
- }
2733
- function useReplicateBuilderView() {
2734
- const queryClient = useQueryClient();
2735
- return useMutation({
2736
- mutationFn: ({ id, input }) => client.replicateBuilderView(id, input),
2737
- onSuccess: () => queryClient.invalidateQueries({ queryKey: builderKeys.views })
2738
- });
2739
- }
2740
- function useDeleteBuilderView() {
2741
- const queryClient = useQueryClient();
2742
- return useMutation({
2743
- mutationFn: client.deleteBuilderView,
2744
- onSuccess: () => queryClient.invalidateQueries({ queryKey: builderKeys.views })
2745
- });
2746
- }
2747
- function useRuntimeBuilderForm(id) {
2748
- return useQuery({
2749
- queryKey: builderKeys.runtimeForm(id),
2750
- queryFn: () => client.getRuntimeBuilderForm(id)
2751
- });
2752
- }
2753
- function useRuntimeBuilderFormFieldOptions(formId, fieldKey, query, enabled = true) {
2754
- return useQuery({
2755
- queryKey: builderKeys.runtimeFieldOptions(formId ?? "", fieldKey, query),
2756
- queryFn: () => client.listRuntimeBuilderFormFieldOptions(formId ?? "", fieldKey, query),
2757
- enabled: Boolean(formId) && enabled
3383
+ function shouldHandleDynamicViewRowClick(event) {
3384
+ if (!event) return true;
3385
+ if (event.defaultPrevented) return false;
3386
+ return !hasClosest(event.target) || !event.target.closest(interactiveRowTargetSelector);
3387
+ }
3388
+ function createDynamicViewComponent(deps) {
3389
+ return function DynamicView({ viewId }) {
3390
+ const [editing, setEditing] = useState7(null);
3391
+ const [isDialogOpen, setDialogOpen] = useState7(false);
3392
+ const [pendingDelete, setPendingDelete] = useState7(null);
3393
+ const viewQuery = deps.hooks.useRuntimeBuilderView(viewId);
3394
+ const state = deps.useDataTableState({ pageSize: 20 });
3395
+ const entriesQuery = deps.hooks.useBuilderViewEntries(viewId, state.query);
3396
+ const save = deps.hooks.useSaveBuilderViewEntry(viewId);
3397
+ const remove = deps.hooks.useDeleteBuilderViewEntry(viewId);
3398
+ const view = viewQuery.data;
3399
+ const columns = useMemo10(
3400
+ () => view ? deps.buildColumns(view, {
3401
+ onEdit: (entry, event) => {
3402
+ event?.stopPropagation?.();
3403
+ setEditing(entry);
3404
+ setDialogOpen(true);
3405
+ },
3406
+ onDelete: (entry, event) => {
3407
+ event?.stopPropagation?.();
3408
+ setPendingDelete(entry);
3409
+ }
3410
+ }) : [],
3411
+ [view]
3412
+ );
3413
+ const controller = deps.useDataTable({
3414
+ columns,
3415
+ data: entriesQuery.data?.items ?? [],
3416
+ rowCount: entriesQuery.data?.total ?? 0,
3417
+ state,
3418
+ getRowId: (row) => row.id
2758
3419
  });
2759
- }
2760
- function useRunRuntimeBuilderFieldTrigger() {
2761
- return useMutation({
2762
- mutationFn: (args) => {
2763
- if (args.viewId) {
2764
- return client.runRuntimeBuilderViewFieldTrigger(
2765
- args.viewId,
2766
- args.fieldKey,
2767
- args.event,
2768
- args.input
2769
- );
3420
+ if (viewQuery.isError) {
3421
+ return /* @__PURE__ */ jsx16(
3422
+ deps.ErrorState,
3423
+ {
3424
+ title: "View \u043D\u044D\u044D\u0433\u0434\u0441\u044D\u043D\u0433\u04AF\u0439",
3425
+ description: `\xAB${viewId}\xBB id-\u0442\u0430\u0439 view \u043E\u043B\u0434\u0441\u043E\u043D\u0433\u04AF\u0439.`
3426
+ }
3427
+ );
3428
+ }
3429
+ return /* @__PURE__ */ jsxs13("div", { className: "space-y-6", children: [
3430
+ /* @__PURE__ */ jsx16(
3431
+ deps.DataGrid,
3432
+ {
3433
+ title: view?.title ?? "Dynamic View",
3434
+ description: view?.description ?? `/winu/view?id=${viewId}`,
3435
+ controller,
3436
+ isLoading: viewQuery.isPending || entriesQuery.isPending,
3437
+ searchPlaceholder: "\u041C\u04E9\u0440 \u0445\u0430\u0439\u0445...",
3438
+ emptyTitle: "\u041C\u04E9\u0440 \u0430\u043B\u0433\u0430",
3439
+ emptyDescription: "\u042D\u043D\u044D view \u0434\u044D\u044D\u0440 \u044D\u0445\u043D\u0438\u0439 \u043C\u04E9\u0440\u04E9\u04E9 \u043D\u044D\u043C\u044D\u044D\u0440\u044D\u0439.",
3440
+ onRowClick: (entry, event) => {
3441
+ if (!shouldHandleDynamicViewRowClick(event)) return;
3442
+ setEditing(entry);
3443
+ setDialogOpen(true);
3444
+ },
3445
+ toolbarExtra: /* @__PURE__ */ jsx16(
3446
+ deps.AddButton,
3447
+ {
3448
+ disabled: !view?.form,
3449
+ onAdd: () => {
3450
+ setEditing(null);
3451
+ setDialogOpen(true);
3452
+ }
3453
+ }
3454
+ )
3455
+ }
3456
+ ),
3457
+ view ? /* @__PURE__ */ jsx16(
3458
+ deps.EntryDialog,
3459
+ {
3460
+ open: isDialogOpen,
3461
+ view,
3462
+ editing,
3463
+ onClose: () => setDialogOpen(false),
3464
+ onSave: save.mutateAsync,
3465
+ isSaving: save.isPending
3466
+ }
3467
+ ) : null,
3468
+ /* @__PURE__ */ jsx16(
3469
+ deps.DeleteDialog,
3470
+ {
3471
+ entry: pendingDelete,
3472
+ isDeleting: remove.isPending,
3473
+ onClose: () => setPendingDelete(null),
3474
+ onConfirm: async () => {
3475
+ if (!pendingDelete) return;
3476
+ await remove.mutateAsync(pendingDelete.id);
3477
+ setPendingDelete(null);
3478
+ }
2770
3479
  }
2771
- if (args.formId) {
2772
- return client.runRuntimeBuilderFormFieldTrigger(
2773
- args.formId,
2774
- args.fieldKey,
2775
- args.event,
2776
- args.input
2777
- );
3480
+ )
3481
+ ] });
3482
+ };
3483
+ }
3484
+
3485
+ // src/components/RuntimeEntryDialog.tsx
3486
+ import { useEffect as useEffect6, useMemo as useMemo11, useState as useState8 } from "react";
3487
+ import { FormProvider as FormProvider6, useForm as useForm7 } from "react-hook-form";
3488
+ import { jsx as jsx17, jsxs as jsxs14 } from "react/jsx-runtime";
3489
+ function isDbTableSource(source) {
3490
+ return source?.type === "dbTable" && "tableName" in source;
3491
+ }
3492
+ function runtimeViewTableName(view) {
3493
+ const listSource = view.list?.source;
3494
+ if (isDbTableSource(listSource)) return listSource.tableName;
3495
+ const formSource = view.form?.source;
3496
+ return isDbTableSource(formSource) ? formSource.tableName : void 0;
3497
+ }
3498
+ function cleanRowValues(values) {
3499
+ return Object.fromEntries(
3500
+ Object.entries(values).filter(([key]) => key === "_delete" || !key.startsWith("_"))
3501
+ );
3502
+ }
3503
+ function childRowPayload(row, includeIdentity) {
3504
+ const values = cleanRowValues(row.values);
3505
+ if (!includeIdentity || row.values._draftNew === true) return values;
3506
+ return {
3507
+ id: row.id,
3508
+ version: row.version,
3509
+ ...values
3510
+ };
3511
+ }
3512
+ function createRuntimeEntryDialogComponent(deps) {
3513
+ return function RuntimeEntryDialog({
3514
+ open,
3515
+ view,
3516
+ editing,
3517
+ onClose,
3518
+ onSave,
3519
+ isSaving
3520
+ }) {
3521
+ const [draftSubforms, setDraftSubforms] = useState8({});
3522
+ const compositeCreate = deps.useCreateCompositeEntry?.(view.id);
3523
+ const compositeUpdate = deps.useUpdateCompositeEntry?.(view.id);
3524
+ const form = useForm7({
3525
+ defaultValues: createBuilderEntryDefaultValues(view, editing),
3526
+ values: open ? createBuilderEntryDefaultValues(view, editing) : void 0
3527
+ });
3528
+ const mainTableName = runtimeViewTableName(view);
3529
+ const hasDraftRows = useMemo11(
3530
+ () => Object.values(draftSubforms).some((draft) => draft.rows.length > 0),
3531
+ [draftSubforms]
3532
+ );
3533
+ useEffect6(() => {
3534
+ if (open) setDraftSubforms({});
3535
+ }, [open]);
3536
+ const onSubmit = form.handleSubmit(async (values) => {
3537
+ try {
3538
+ if (!editing && hasDraftRows) {
3539
+ if (!mainTableName) throw new Error("Main form datasource table \u043E\u043B\u0434\u0441\u043E\u043D\u0433\u04AF\u0439");
3540
+ if (!compositeCreate) throw new Error("Composite create handler \u0442\u043E\u0445\u0438\u0440\u0443\u0443\u043B\u0430\u0433\u0434\u0430\u0430\u0433\u04AF\u0439 \u0431\u0430\u0439\u043D\u0430");
3541
+ await compositeCreate.mutateAsync({
3542
+ data: {
3543
+ [mainTableName]: values.values,
3544
+ ...Object.fromEntries(
3545
+ Object.values(draftSubforms).map((draft) => [
3546
+ draft.dataKey,
3547
+ draft.rows.filter((row) => row.values._delete !== true).map((row) => childRowPayload(row, false))
3548
+ ])
3549
+ )
3550
+ }
3551
+ });
3552
+ } else if (editing && hasDraftRows) {
3553
+ if (!mainTableName) throw new Error("Main form datasource table \u043E\u043B\u0434\u0441\u043E\u043D\u0433\u04AF\u0439");
3554
+ if (!compositeUpdate) throw new Error("Composite update handler \u0442\u043E\u0445\u0438\u0440\u0443\u0443\u043B\u0430\u0433\u0434\u0430\u0430\u0433\u04AF\u0439 \u0431\u0430\u0439\u043D\u0430");
3555
+ await compositeUpdate.mutateAsync({
3556
+ id: editing.id,
3557
+ input: {
3558
+ data: {
3559
+ [mainTableName]: {
3560
+ id: editing.id,
3561
+ version: values.version,
3562
+ ...values.values
3563
+ },
3564
+ ...Object.fromEntries(
3565
+ Object.values(draftSubforms).map((draft) => [
3566
+ draft.dataKey,
3567
+ draft.rows.map((row) => childRowPayload(row, true))
3568
+ ])
3569
+ )
3570
+ }
3571
+ }
3572
+ });
3573
+ } else {
3574
+ await onSave({ id: editing?.id, input: values });
2778
3575
  }
2779
- throw new Error("formId \u044D\u0441\u0432\u044D\u043B viewId \u0448\u0430\u0430\u0440\u0434\u043B\u0430\u0433\u0430\u0442\u0430\u0439");
3576
+ onClose();
3577
+ deps.notifications.success(editing ? "\u041C\u04E9\u0440 \u0445\u0430\u0434\u0433\u0430\u043B\u0430\u0433\u0434\u043B\u0430\u0430" : "\u041C\u04E9\u0440 \u043D\u044D\u043C\u044D\u0433\u0434\u043B\u044D\u044D");
3578
+ } catch (error) {
3579
+ deps.notifications.error(deps.notifications.errorMessage(error, "\u0425\u0430\u0434\u0433\u0430\u043B\u0430\u0445\u0430\u0434 \u0430\u043B\u0434\u0430\u0430 \u0433\u0430\u0440\u043B\u0430\u0430"));
2780
3580
  }
2781
3581
  });
2782
- }
2783
- function useRuntimeBuilderList(id) {
2784
- return useQuery({
2785
- queryKey: builderKeys.runtimeList(id),
2786
- queryFn: () => client.getRuntimeBuilderList(id)
2787
- });
2788
- }
2789
- function useRuntimeBuilderListEntries(id, query) {
2790
- return useQuery({
2791
- queryKey: builderKeys.runtimeListEntries(id, query),
2792
- queryFn: () => client.listRuntimeBuilderListEntries(id, query),
2793
- placeholderData: keepPreviousData
2794
- });
2795
- }
2796
- function useSaveRuntimeBuilderFormEntry(formId) {
2797
- const queryClient = useQueryClient();
2798
- return useMutation({
2799
- mutationFn: (input) => client.createRuntimeBuilderFormEntry(formId, input),
2800
- onSuccess: () => {
2801
- queryClient.invalidateQueries({ queryKey: builderKeys.runtimeFormEntries(formId) });
2802
- queryClient.invalidateQueries({ queryKey: builderKeys.runtimeForm(formId) });
2803
- queryClient.invalidateQueries({ queryKey: ["builder", "runtime", "list"] });
3582
+ const saving = isSaving || Boolean(compositeCreate?.isPending || compositeUpdate?.isPending);
3583
+ const extraItems = deps.SubformField && view.form?.schema.subforms?.length ? view.form.schema.subforms.map((subform) => ({
3584
+ key: subform.key,
3585
+ render: () => deps.SubformField ? /* @__PURE__ */ jsx17(
3586
+ deps.SubformField,
3587
+ {
3588
+ subform,
3589
+ parentEntry: editing,
3590
+ draftRows: draftSubforms[subform.key]?.rows ?? [],
3591
+ onDraftRowsChange: ({ subformKey, dataKey: dataKey2, rows }) => {
3592
+ setDraftSubforms((current) => ({
3593
+ ...current,
3594
+ [subformKey]: { dataKey: dataKey2, rows }
3595
+ }));
3596
+ }
3597
+ }
3598
+ ) : null
3599
+ })) : void 0;
3600
+ return /* @__PURE__ */ jsx17(
3601
+ deps.DialogShell,
3602
+ {
3603
+ open,
3604
+ presentation: view.form?.schema.presentation ?? "dialog",
3605
+ title: editing ? "\u041C\u04E9\u0440 \u0437\u0430\u0441\u0430\u0445" : "\u041C\u04E9\u0440 \u043D\u044D\u043C\u044D\u0445",
3606
+ description: view.title,
3607
+ onClose,
3608
+ children: /* @__PURE__ */ jsx17(FormProvider6, { ...form, children: /* @__PURE__ */ jsxs14("form", { onSubmit, noValidate: true, className: deps.formClassName, children: [
3609
+ view.form ? /* @__PURE__ */ jsx17(
3610
+ deps.FormFields,
3611
+ {
3612
+ formId: view.form.id,
3613
+ viewId: view.id,
3614
+ entry: editing,
3615
+ schema: view.form.schema,
3616
+ namePrefix: "values",
3617
+ extraItems
3618
+ }
3619
+ ) : null,
3620
+ /* @__PURE__ */ jsx17(deps.Actions, { isSaving: saving, onClose })
3621
+ ] }) })
2804
3622
  }
2805
- });
2806
- }
2807
- function useRuntimeBuilderView(id, enabled = true) {
2808
- return useQuery({
2809
- queryKey: builderKeys.runtimeView(id),
2810
- queryFn: () => client.getRuntimeBuilderView(id),
2811
- enabled: Boolean(id) && enabled
2812
- });
2813
- }
2814
- function useBuilderViewEntries(id, query, enabled = true) {
2815
- return useQuery({
2816
- queryKey: builderKeys.entries(id, query),
2817
- queryFn: () => client.listBuilderViewEntries(id, query),
2818
- placeholderData: keepPreviousData,
2819
- enabled: Boolean(id) && enabled
2820
- });
2821
- }
2822
- function useSaveBuilderViewEntry(viewId) {
2823
- const queryClient = useQueryClient();
2824
- return useMutation({
2825
- mutationFn: ({ id, input }) => id ? client.updateBuilderViewEntry(viewId, id, input) : client.createBuilderViewEntry(
2826
- viewId,
2827
- input
2828
- ),
2829
- onSuccess: () => invalidateRuntimeViewEntries(queryClient, viewId)
2830
- });
2831
- }
2832
- function useCreateCompositeBuilderViewEntry(viewId) {
2833
- const queryClient = useQueryClient();
2834
- return useMutation({
2835
- mutationFn: (input) => client.createCompositeBuilderViewEntry(viewId, input),
2836
- onSuccess: () => invalidateRuntimeViewEntries(queryClient, viewId)
2837
- });
2838
- }
2839
- function useUpdateCompositeBuilderViewEntry(viewId) {
2840
- const queryClient = useQueryClient();
2841
- return useMutation({
2842
- mutationFn: ({
2843
- id,
2844
- input
2845
- }) => client.updateCompositeBuilderViewEntry(viewId, id, input),
2846
- onSuccess: () => invalidateRuntimeViewEntries(queryClient, viewId)
2847
- });
2848
- }
2849
- function useDeleteBuilderViewEntry(id) {
2850
- const queryClient = useQueryClient();
2851
- return useMutation({
2852
- mutationFn: (entryId) => client.deleteBuilderViewEntry(id, entryId),
2853
- onSuccess: () => invalidateRuntimeViewEntries(queryClient, id)
2854
- });
2855
- }
2856
- return {
2857
- builderKeys,
2858
- useBuilderDbTables,
2859
- useBuilderForm,
2860
- useBuilderFormOptions,
2861
- useBuilderForms,
2862
- useBuilderList,
2863
- useBuilderListOptions,
2864
- useBuilderLists,
2865
- useBuilderViewEntries,
2866
- useBuilderView,
2867
- useBuilderViews,
2868
- useDeleteBuilderForm,
2869
- useDeleteBuilderList,
2870
- useDeleteBuilderView,
2871
- useDeleteBuilderViewEntry,
2872
- useCreateCompositeBuilderViewEntry,
2873
- useReplicateBuilderForm,
2874
- useReplicateBuilderList,
2875
- useReplicateBuilderView,
2876
- useRuntimeBuilderForm,
2877
- useRuntimeBuilderFormFieldOptions,
2878
- useRuntimeBuilderList,
2879
- useRuntimeBuilderListEntries,
2880
- useRuntimeBuilderView,
2881
- useRunRuntimeBuilderFieldTrigger,
2882
- useSaveBuilderForm,
2883
- useSaveBuilderList,
2884
- useSaveBuilderView,
2885
- useSaveBuilderViewEntry,
2886
- useSaveRuntimeBuilderFormEntry,
2887
- useUpdateCompositeBuilderViewEntry
3623
+ );
2888
3624
  };
2889
3625
  }
2890
3626
 
@@ -2905,7 +3641,7 @@ function withQuery(path, query) {
2905
3641
  function createBuilderIntegration(config) {
2906
3642
  const adminBasePath = normalizeBasePath(config.adminBasePath ?? "/admin/dev/builder");
2907
3643
  const runtimeBasePath = normalizeBasePath(config.runtimeBasePath ?? "/admin/winu");
2908
- const api = createBuilderApiClient(config.transport);
3644
+ const api = createBuilderApiClient(config.transport, { apiBasePath: config.apiBasePath });
2909
3645
  const hooks = createBuilderHooks(api);
2910
3646
  const formsPath = `${adminBasePath}/forms`;
2911
3647
  const listsPath = `${adminBasePath}/lists`;
@@ -2936,18 +3672,51 @@ function createBuilderIntegration(config) {
2936
3672
  adminPages
2937
3673
  };
2938
3674
  }
3675
+ function createBuilderPortalIntegration(config) {
3676
+ return createBuilderIntegration(config);
3677
+ }
3678
+ function validateBuilderFrontendSetup(config) {
3679
+ const checks = [
3680
+ {
3681
+ name: "adminBasePath",
3682
+ ok: Boolean(config.adminBasePath && normalizeBasePath(config.adminBasePath).startsWith("/")),
3683
+ message: "adminBasePath must be an absolute route path."
3684
+ },
3685
+ {
3686
+ name: "runtimeBasePath",
3687
+ ok: Boolean(config.runtimeBasePath && normalizeBasePath(config.runtimeBasePath).startsWith("/")),
3688
+ message: "runtimeBasePath must be an absolute route path."
3689
+ },
3690
+ {
3691
+ name: "transport",
3692
+ ok: Boolean(config.transport),
3693
+ message: "API transport is required."
3694
+ },
3695
+ {
3696
+ name: "apiBasePath",
3697
+ ok: config.apiBasePath === void 0 || normalizeBasePath(config.apiBasePath).startsWith("/"),
3698
+ message: "apiBasePath must be an absolute API path."
3699
+ }
3700
+ ].map((check) => check.ok ? { name: check.name, ok: true } : check);
3701
+ return { ok: checks.every((check) => check.ok), checks };
3702
+ }
2939
3703
 
2940
3704
  // src/index.ts
2941
3705
  var builderUiPackage = {
2942
3706
  name: "@duke333/builder-ui",
2943
- version: "0.1.1"
3707
+ version: "0.2.0"
2944
3708
  };
2945
3709
  export {
2946
3710
  BUILDER_EDITOR_NONE_VALUE,
3711
+ BuilderForm,
3712
+ BuilderGrid,
3713
+ BuilderProvider,
3714
+ BuilderView,
2947
3715
  builderEditorOptionsToText,
2948
3716
  builderEditorSearchFieldsToText,
2949
3717
  builderEditorTextToOptions,
2950
3718
  builderEditorTextToSearchFields,
3719
+ builderErrorMessage,
2951
3720
  builderFormEditorFieldsFromTable,
2952
3721
  builderFormEditorInputFromValues,
2953
3722
  builderFormEditorValuesFromEntity,
@@ -2961,6 +3730,7 @@ export {
2961
3730
  clampBuilderFormLayoutSpan,
2962
3731
  createBuilderAdminPages,
2963
3732
  createBuilderApiClient,
3733
+ createBuilderClient,
2964
3734
  createBuilderDefaultEntityManagerComponent,
2965
3735
  createBuilderDefaultFormEditorBody,
2966
3736
  createBuilderDefaultListEditorBody,
@@ -2974,6 +3744,7 @@ export {
2974
3744
  createBuilderIntegration,
2975
3745
  createBuilderKeys,
2976
3746
  createBuilderListEditorPageComponent,
3747
+ createBuilderPortalIntegration,
2977
3748
  createBuilderViewDialogComponent,
2978
3749
  createDynamicFormComponent,
2979
3750
  createDynamicListComponent,
@@ -2984,7 +3755,10 @@ export {
2984
3755
  nextBuilderFormLayoutGroupId,
2985
3756
  parseBuilderFormLayoutDragPayload,
2986
3757
  serializeBuilderFormLayoutDragPayload,
3758
+ shouldHandleDynamicViewRowClick,
2987
3759
  swapBuilderFormLayoutItems,
2988
- useBuilderFormLayoutEditor
3760
+ useBuilderFormLayoutEditor,
3761
+ useBuilderRuntime,
3762
+ validateBuilderFrontendSetup
2989
3763
  };
2990
3764
  //# sourceMappingURL=index.js.map