@duke333/builder-ui 0.2.3 → 0.2.5

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.
@@ -1,5 +1,5 @@
1
1
  import { BuilderApiContracts, BuilderApiClient, BuilderApiTransport } from '../api/index.js';
2
- import { Q as createBuilderAdminPages, b as BuilderAdminPagesOptions, a as BuilderAdminPageContracts } from '../BuilderAdminPages-DrOrFyIX.js';
2
+ import { Q as createBuilderAdminPages, b as BuilderAdminPagesOptions, a as BuilderAdminPageContracts } from '../BuilderAdminPages-bV-lwDOp.js';
3
3
  import { BuilderHooks } from '../hooks/index.js';
4
4
  import 'react';
5
5
  import 'react-hook-form';
@@ -18,7 +18,8 @@ function createBuilderApiClient(rootTransport, options = {}) {
18
18
  get: (value, requestOptions) => rootTransport.get(path(value), requestOptions),
19
19
  post: (value, body, requestOptions) => rootTransport.post(path(value), body, requestOptions),
20
20
  patch: (value, body, requestOptions) => rootTransport.patch(path(value), body, requestOptions),
21
- delete: (value, requestOptions) => rootTransport.delete(path(value), requestOptions)
21
+ delete: (value, requestOptions) => rootTransport.delete(path(value), requestOptions),
22
+ upload: rootTransport.upload ? (value, body, requestOptions) => rootTransport.upload(path(value), body, requestOptions) : void 0
22
23
  };
23
24
  return {
24
25
  listBuilderForms: (query) => transport.get("/builder/forms", {
@@ -93,7 +94,23 @@ function createBuilderApiClient(rootTransport, options = {}) {
93
94
  ),
94
95
  deleteBuilderViewEntry: (viewId, id) => transport.delete(
95
96
  `/builder/runtime/views/${encodeURIComponent(viewId)}/entries/${encodeURIComponent(id)}`
96
- )
97
+ ),
98
+ presignRuntimeBuilderFile: (context, fieldKey, input) => {
99
+ const owner = context.viewId ? `views/${encodeURIComponent(context.viewId)}` : `forms/${encodeURIComponent(context.formId ?? "")}`;
100
+ return transport.post(
101
+ `/builder/runtime/${owner}/fields/${encodeURIComponent(fieldKey)}/files/presign`,
102
+ input
103
+ );
104
+ },
105
+ uploadRuntimeBuilderFile: (context, fieldKey, file) => {
106
+ if (!transport.upload) throw new Error("Builder transport server file upload \u0434\u044D\u043C\u0436\u0438\u0445\u0433\u04AF\u0439 \u0431\u0430\u0439\u043D\u0430");
107
+ const owner = context.viewId ? `views/${encodeURIComponent(context.viewId)}` : `forms/${encodeURIComponent(context.formId ?? "")}`;
108
+ return transport.upload(
109
+ `/builder/runtime/${owner}/fields/${encodeURIComponent(fieldKey)}/files/upload`,
110
+ file,
111
+ { contentType: file.type }
112
+ );
113
+ }
97
114
  };
98
115
  }
99
116
 
@@ -142,7 +159,7 @@ function clampLayoutSpan(span, columns) {
142
159
  return Math.max(1, Math.min(columns, Math.trunc(span)));
143
160
  }
144
161
  function builderFormEditorDefaultSpan(field) {
145
- if (field.type === "textarea" || field.type === "checkbox") return 12;
162
+ if (field.type === "textarea" || field.type === "richtext" || field.type === "checkbox") return 12;
146
163
  return 6;
147
164
  }
148
165
  function builderFormEditorDefaultLayoutGroups(fields, subforms = []) {
@@ -209,6 +226,10 @@ function builderFormEditorValuesFromEntity(form, emptyValues) {
209
226
  required: field.required,
210
227
  hidden: field.hidden ?? false,
211
228
  disabled: field.disabled ?? false,
229
+ storage: field.storage ?? "s3",
230
+ contentKind: field.contentKind ?? "image",
231
+ multiple: field.multiple ?? false,
232
+ maxMegabytes: field.maxBytes ? field.maxBytes / (1024 * 1024) : 10,
212
233
  placeholder: field.placeholder ?? "",
213
234
  optionsText: builderEditorOptionsToText(field.options),
214
235
  optionsMode: field.optionsSource?.type === "dbTable" ? "table" : "static",
@@ -238,6 +259,7 @@ function builderFormEditorValuesFromEntity(form, emptyValues) {
238
259
  sourceTable: source?.type === "dbTable" ? source.tableName : BUILDER_EDITOR_NONE_VALUE,
239
260
  apiBasePath: source?.type === "apiEndpoint" ? source.basePath : "",
240
261
  fields,
262
+ layoutPresentation: form.schema.layout?.presentation ?? "stacked",
241
263
  layoutGroups: normalizeBuilderFormEditorLayoutGroups(
242
264
  form.schema.layout?.groups,
243
265
  fields,
@@ -291,6 +313,10 @@ function builderFormEditorFieldsFromTable(table) {
291
313
  required: !column.nullable,
292
314
  hidden: false,
293
315
  disabled: false,
316
+ storage: "s3",
317
+ contentKind: "image",
318
+ multiple: false,
319
+ maxMegabytes: 10,
294
320
  placeholder: column.label,
295
321
  optionsText: "",
296
322
  optionsMode: "static",
@@ -327,6 +353,10 @@ function builderFormEditorInputFromValues(values) {
327
353
  required: field.required,
328
354
  hidden: field.hidden,
329
355
  disabled: field.disabled,
356
+ storage: field.type === "file" ? field.storage : void 0,
357
+ contentKind: field.type === "file" ? field.contentKind : void 0,
358
+ multiple: field.type === "file" ? field.multiple : void 0,
359
+ maxBytes: field.type === "file" && typeof field.maxMegabytes === "number" && field.maxMegabytes > 0 ? Math.round(field.maxMegabytes * 1024 * 1024) : void 0,
330
360
  placeholder: field.placeholder?.trim() || field.label,
331
361
  options: field.type === "select" && field.optionsMode === "static" ? builderEditorTextToOptions(field.optionsText) : void 0,
332
362
  optionsSource: field.type === "select" && field.optionsMode === "table" && field.optionsTable !== BUILDER_EDITOR_NONE_VALUE && field.optionsValueField !== BUILDER_EDITOR_NONE_VALUE && field.optionsLabelField !== BUILDER_EDITOR_NONE_VALUE ? {
@@ -349,6 +379,7 @@ function builderFormEditorInputFromValues(values) {
349
379
  }))
350
380
  })),
351
381
  layout: {
382
+ presentation: values.layoutPresentation,
352
383
  groups: normalizeBuilderFormEditorLayoutGroups(
353
384
  values.layoutGroups,
354
385
  values.fields,
@@ -417,7 +448,7 @@ function builderViewEditorInputFromValues(values, parseTriggers) {
417
448
  }
418
449
 
419
450
  // src/admin/BuilderDefaultEditorBodies.tsx
420
- import { jsx, jsxs } from "react/jsx-runtime";
451
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
421
452
  var styles = {
422
453
  page: {
423
454
  display: "grid",
@@ -680,6 +711,30 @@ function createBuilderDefaultFormEditorBody(options) {
680
711
  /* @__PURE__ */ jsx("input", { type: "checkbox", ...form.register(`fields.${index}.disabled`) }),
681
712
  "Disabled"
682
713
  ] }),
714
+ fields[index]?.type === "file" ? /* @__PURE__ */ jsxs(Fragment, { children: [
715
+ /* @__PURE__ */ jsxs("label", { style: styles.field, children: [
716
+ /* @__PURE__ */ jsx("span", { style: styles.label, children: "Storage" }),
717
+ /* @__PURE__ */ jsxs("select", { style: styles.input, ...form.register(`fields.${index}.storage`), children: [
718
+ /* @__PURE__ */ jsx("option", { value: "s3", children: "S3" }),
719
+ /* @__PURE__ */ jsx("option", { value: "server", children: "Server" })
720
+ ] })
721
+ ] }),
722
+ /* @__PURE__ */ jsxs("label", { style: styles.field, children: [
723
+ /* @__PURE__ */ jsx("span", { style: styles.label, children: "Content type" }),
724
+ /* @__PURE__ */ jsxs("select", { style: styles.input, ...form.register(`fields.${index}.contentKind`), children: [
725
+ /* @__PURE__ */ jsx("option", { value: "image", children: "Image" }),
726
+ /* @__PURE__ */ jsx("option", { value: "file", children: "File" })
727
+ ] })
728
+ ] }),
729
+ /* @__PURE__ */ jsxs("label", { style: styles.checkboxField, children: [
730
+ /* @__PURE__ */ jsx("input", { type: "checkbox", ...form.register(`fields.${index}.multiple`) }),
731
+ "Multiple"
732
+ ] }),
733
+ /* @__PURE__ */ jsxs("label", { style: styles.field, children: [
734
+ /* @__PURE__ */ jsx("span", { style: styles.label, children: "Max size (MB)" }),
735
+ /* @__PURE__ */ jsx("input", { type: "number", min: "1", max: "100", style: styles.input, ...form.register(`fields.${index}.maxMegabytes`, { valueAsNumber: true }) })
736
+ ] })
737
+ ] }) : null,
683
738
  /* @__PURE__ */ jsxs("label", { style: styles.field, children: [
684
739
  /* @__PURE__ */ jsx("span", { style: styles.label, children: "Placeholder" }),
685
740
  /* @__PURE__ */ jsx("input", { style: styles.input, ...form.register(`fields.${index}.placeholder`) })
@@ -718,6 +773,13 @@ function createBuilderDefaultFormEditorBody(options) {
718
773
  }
719
774
  )
720
775
  ] }),
776
+ /* @__PURE__ */ jsx("div", { style: styles.grid, children: /* @__PURE__ */ jsxs("label", { style: styles.field, children: [
777
+ /* @__PURE__ */ jsx("span", { style: styles.label, children: "Group presentation" }),
778
+ /* @__PURE__ */ jsxs("select", { style: styles.input, ...form.register("layoutPresentation"), children: [
779
+ /* @__PURE__ */ jsx("option", { value: "stacked", children: "Stacked sections" }),
780
+ /* @__PURE__ */ jsx("option", { value: "tabs", children: "Tabs" })
781
+ ] })
782
+ ] }) }),
721
783
  form.watch("layoutGroups").map((group, groupIndex) => /* @__PURE__ */ jsxs("div", { style: styles.row, children: [
722
784
  /* @__PURE__ */ jsxs("label", { style: styles.field, children: [
723
785
  /* @__PURE__ */ jsx("span", { style: styles.label, children: "Group title" }),
@@ -1290,7 +1352,7 @@ function createBuilderDefaultEntityManagerComponent(deps) {
1290
1352
  // src/admin/BuilderDefaultViewEditorPage.tsx
1291
1353
  import { useEffect } from "react";
1292
1354
  import { useForm } from "react-hook-form";
1293
- import { Fragment, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
1355
+ import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
1294
1356
  var styles3 = {
1295
1357
  page: {
1296
1358
  display: "grid",
@@ -1477,7 +1539,7 @@ function createBuilderDefaultViewEditorPage(options) {
1477
1539
  (lists.data ?? []).map((item) => /* @__PURE__ */ jsx3("option", { value: item.id, children: item.title }, item.id))
1478
1540
  ] })
1479
1541
  ] }),
1480
- showPermissions ? /* @__PURE__ */ jsxs3(Fragment, { children: [
1542
+ showPermissions ? /* @__PURE__ */ jsxs3(Fragment2, { children: [
1481
1543
  /* @__PURE__ */ jsxs3("label", { style: styles3.field, children: [
1482
1544
  /* @__PURE__ */ jsx3("span", { style: styles3.label, children: "Read permission" }),
1483
1545
  /* @__PURE__ */ jsxs3("select", { style: styles3.input, ...form.register("permissionRead"), children: [
@@ -1641,6 +1703,7 @@ import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
1641
1703
  var defaultFieldTypeOptions = [
1642
1704
  { value: "text", label: "Text" },
1643
1705
  { value: "textarea", label: "Textarea" },
1706
+ { value: "richtext", label: "Rich text" },
1644
1707
  { value: "number", label: "Number" },
1645
1708
  { value: "money", label: "Money" },
1646
1709
  { value: "select", label: "Select" },
@@ -1751,6 +1814,10 @@ function createBuilderAdminPages({
1751
1814
  required: true,
1752
1815
  hidden: false,
1753
1816
  disabled: false,
1817
+ storage: "s3",
1818
+ contentKind: "image",
1819
+ multiple: false,
1820
+ maxMegabytes: 10,
1754
1821
  placeholder: "",
1755
1822
  optionsText: "",
1756
1823
  optionsMode: "static",
@@ -1770,6 +1837,7 @@ function createBuilderAdminPages({
1770
1837
  sourceTable: BUILDER_EDITOR_NONE_VALUE,
1771
1838
  apiBasePath: "",
1772
1839
  fields: [emptyField],
1840
+ layoutPresentation: "stacked",
1773
1841
  layoutGroups: builderFormEditorDefaultLayoutGroups([emptyField]),
1774
1842
  subforms: [],
1775
1843
  triggers: [],
@@ -2055,12 +2123,30 @@ function createBuilderKeys() {
2055
2123
  }
2056
2124
  function createBuilderHooks(client) {
2057
2125
  const builderKeys = createBuilderKeys();
2126
+ function isRuntimeEntryListCache(value) {
2127
+ return typeof value === "object" && value !== null && "items" in value && Array.isArray(value.items) && "total" in value;
2128
+ }
2129
+ function replaceCachedRuntimeViewEntry(queryClient, viewId, entry) {
2130
+ queryClient.setQueriesData(
2131
+ { queryKey: [...builderKeys.runtimeView(viewId), "entries"] },
2132
+ (current) => {
2133
+ if (!isRuntimeEntryListCache(current)) return current;
2134
+ return {
2135
+ ...current,
2136
+ items: current.items.map((item) => item.id === entry.id ? entry : item)
2137
+ };
2138
+ }
2139
+ );
2140
+ }
2058
2141
  function invalidateRuntimeViewEntries(queryClient, viewId) {
2059
2142
  return Promise.all([
2060
2143
  queryClient.invalidateQueries({ queryKey: builderKeys.runtimeView(viewId) }),
2061
2144
  queryClient.invalidateQueries({ queryKey: [...builderKeys.runtimeView(viewId), "entries"] })
2062
2145
  ]);
2063
2146
  }
2147
+ function invalidateAllRuntimeViewEntries(queryClient) {
2148
+ return queryClient.invalidateQueries({ queryKey: ["builder", "runtime", "view"] });
2149
+ }
2064
2150
  function useBuilderDbTables() {
2065
2151
  return useQuery({ queryKey: builderKeys.dbTables(), queryFn: client.listBuilderDbTables });
2066
2152
  }
@@ -2271,14 +2357,20 @@ function createBuilderHooks(client) {
2271
2357
  viewId,
2272
2358
  input
2273
2359
  ),
2274
- onSuccess: () => invalidateRuntimeViewEntries(queryClient, viewId)
2360
+ onSuccess: (entry) => {
2361
+ replaceCachedRuntimeViewEntry(queryClient, viewId, entry);
2362
+ return invalidateRuntimeViewEntries(queryClient, viewId);
2363
+ }
2275
2364
  });
2276
2365
  }
2277
2366
  function useCreateCompositeBuilderViewEntry(viewId) {
2278
2367
  const queryClient = useQueryClient();
2279
2368
  return useMutation({
2280
2369
  mutationFn: (input) => client.createCompositeBuilderViewEntry(viewId, input),
2281
- onSuccess: () => invalidateRuntimeViewEntries(queryClient, viewId)
2370
+ onSuccess: (entry) => {
2371
+ replaceCachedRuntimeViewEntry(queryClient, viewId, entry);
2372
+ return invalidateAllRuntimeViewEntries(queryClient);
2373
+ }
2282
2374
  });
2283
2375
  }
2284
2376
  function useUpdateCompositeBuilderViewEntry(viewId) {
@@ -2288,7 +2380,10 @@ function createBuilderHooks(client) {
2288
2380
  id,
2289
2381
  input
2290
2382
  }) => client.updateCompositeBuilderViewEntry(viewId, id, input),
2291
- onSuccess: () => invalidateRuntimeViewEntries(queryClient, viewId)
2383
+ onSuccess: (entry) => {
2384
+ replaceCachedRuntimeViewEntry(queryClient, viewId, entry);
2385
+ return invalidateAllRuntimeViewEntries(queryClient);
2386
+ }
2292
2387
  });
2293
2388
  }
2294
2389
  function useDeleteBuilderViewEntry(id) {