@duke333/builder-ui 0.2.3 → 0.2.4

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-DwwdA8Dv.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",
@@ -291,6 +312,10 @@ function builderFormEditorFieldsFromTable(table) {
291
312
  required: !column.nullable,
292
313
  hidden: false,
293
314
  disabled: false,
315
+ storage: "s3",
316
+ contentKind: "image",
317
+ multiple: false,
318
+ maxMegabytes: 10,
294
319
  placeholder: column.label,
295
320
  optionsText: "",
296
321
  optionsMode: "static",
@@ -327,6 +352,10 @@ function builderFormEditorInputFromValues(values) {
327
352
  required: field.required,
328
353
  hidden: field.hidden,
329
354
  disabled: field.disabled,
355
+ storage: field.type === "file" ? field.storage : void 0,
356
+ contentKind: field.type === "file" ? field.contentKind : void 0,
357
+ multiple: field.type === "file" ? field.multiple : void 0,
358
+ maxBytes: field.type === "file" && typeof field.maxMegabytes === "number" && field.maxMegabytes > 0 ? Math.round(field.maxMegabytes * 1024 * 1024) : void 0,
330
359
  placeholder: field.placeholder?.trim() || field.label,
331
360
  options: field.type === "select" && field.optionsMode === "static" ? builderEditorTextToOptions(field.optionsText) : void 0,
332
361
  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 ? {
@@ -417,7 +446,7 @@ function builderViewEditorInputFromValues(values, parseTriggers) {
417
446
  }
418
447
 
419
448
  // src/admin/BuilderDefaultEditorBodies.tsx
420
- import { jsx, jsxs } from "react/jsx-runtime";
449
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
421
450
  var styles = {
422
451
  page: {
423
452
  display: "grid",
@@ -680,6 +709,30 @@ function createBuilderDefaultFormEditorBody(options) {
680
709
  /* @__PURE__ */ jsx("input", { type: "checkbox", ...form.register(`fields.${index}.disabled`) }),
681
710
  "Disabled"
682
711
  ] }),
712
+ fields[index]?.type === "file" ? /* @__PURE__ */ jsxs(Fragment, { children: [
713
+ /* @__PURE__ */ jsxs("label", { style: styles.field, children: [
714
+ /* @__PURE__ */ jsx("span", { style: styles.label, children: "Storage" }),
715
+ /* @__PURE__ */ jsxs("select", { style: styles.input, ...form.register(`fields.${index}.storage`), children: [
716
+ /* @__PURE__ */ jsx("option", { value: "s3", children: "S3" }),
717
+ /* @__PURE__ */ jsx("option", { value: "server", children: "Server" })
718
+ ] })
719
+ ] }),
720
+ /* @__PURE__ */ jsxs("label", { style: styles.field, children: [
721
+ /* @__PURE__ */ jsx("span", { style: styles.label, children: "Content type" }),
722
+ /* @__PURE__ */ jsxs("select", { style: styles.input, ...form.register(`fields.${index}.contentKind`), children: [
723
+ /* @__PURE__ */ jsx("option", { value: "image", children: "Image" }),
724
+ /* @__PURE__ */ jsx("option", { value: "file", children: "File" })
725
+ ] })
726
+ ] }),
727
+ /* @__PURE__ */ jsxs("label", { style: styles.checkboxField, children: [
728
+ /* @__PURE__ */ jsx("input", { type: "checkbox", ...form.register(`fields.${index}.multiple`) }),
729
+ "Multiple"
730
+ ] }),
731
+ /* @__PURE__ */ jsxs("label", { style: styles.field, children: [
732
+ /* @__PURE__ */ jsx("span", { style: styles.label, children: "Max size (MB)" }),
733
+ /* @__PURE__ */ jsx("input", { type: "number", min: "1", max: "100", style: styles.input, ...form.register(`fields.${index}.maxMegabytes`, { valueAsNumber: true }) })
734
+ ] })
735
+ ] }) : null,
683
736
  /* @__PURE__ */ jsxs("label", { style: styles.field, children: [
684
737
  /* @__PURE__ */ jsx("span", { style: styles.label, children: "Placeholder" }),
685
738
  /* @__PURE__ */ jsx("input", { style: styles.input, ...form.register(`fields.${index}.placeholder`) })
@@ -1290,7 +1343,7 @@ function createBuilderDefaultEntityManagerComponent(deps) {
1290
1343
  // src/admin/BuilderDefaultViewEditorPage.tsx
1291
1344
  import { useEffect } from "react";
1292
1345
  import { useForm } from "react-hook-form";
1293
- import { Fragment, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
1346
+ import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
1294
1347
  var styles3 = {
1295
1348
  page: {
1296
1349
  display: "grid",
@@ -1477,7 +1530,7 @@ function createBuilderDefaultViewEditorPage(options) {
1477
1530
  (lists.data ?? []).map((item) => /* @__PURE__ */ jsx3("option", { value: item.id, children: item.title }, item.id))
1478
1531
  ] })
1479
1532
  ] }),
1480
- showPermissions ? /* @__PURE__ */ jsxs3(Fragment, { children: [
1533
+ showPermissions ? /* @__PURE__ */ jsxs3(Fragment2, { children: [
1481
1534
  /* @__PURE__ */ jsxs3("label", { style: styles3.field, children: [
1482
1535
  /* @__PURE__ */ jsx3("span", { style: styles3.label, children: "Read permission" }),
1483
1536
  /* @__PURE__ */ jsxs3("select", { style: styles3.input, ...form.register("permissionRead"), children: [
@@ -1641,6 +1694,7 @@ import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
1641
1694
  var defaultFieldTypeOptions = [
1642
1695
  { value: "text", label: "Text" },
1643
1696
  { value: "textarea", label: "Textarea" },
1697
+ { value: "richtext", label: "Rich text" },
1644
1698
  { value: "number", label: "Number" },
1645
1699
  { value: "money", label: "Money" },
1646
1700
  { value: "select", label: "Select" },
@@ -1751,6 +1805,10 @@ function createBuilderAdminPages({
1751
1805
  required: true,
1752
1806
  hidden: false,
1753
1807
  disabled: false,
1808
+ storage: "s3",
1809
+ contentKind: "image",
1810
+ multiple: false,
1811
+ maxMegabytes: 10,
1754
1812
  placeholder: "",
1755
1813
  optionsText: "",
1756
1814
  optionsMode: "static",
@@ -2055,12 +2113,30 @@ function createBuilderKeys() {
2055
2113
  }
2056
2114
  function createBuilderHooks(client) {
2057
2115
  const builderKeys = createBuilderKeys();
2116
+ function isRuntimeEntryListCache(value) {
2117
+ return typeof value === "object" && value !== null && "items" in value && Array.isArray(value.items) && "total" in value;
2118
+ }
2119
+ function replaceCachedRuntimeViewEntry(queryClient, viewId, entry) {
2120
+ queryClient.setQueriesData(
2121
+ { queryKey: [...builderKeys.runtimeView(viewId), "entries"] },
2122
+ (current) => {
2123
+ if (!isRuntimeEntryListCache(current)) return current;
2124
+ return {
2125
+ ...current,
2126
+ items: current.items.map((item) => item.id === entry.id ? entry : item)
2127
+ };
2128
+ }
2129
+ );
2130
+ }
2058
2131
  function invalidateRuntimeViewEntries(queryClient, viewId) {
2059
2132
  return Promise.all([
2060
2133
  queryClient.invalidateQueries({ queryKey: builderKeys.runtimeView(viewId) }),
2061
2134
  queryClient.invalidateQueries({ queryKey: [...builderKeys.runtimeView(viewId), "entries"] })
2062
2135
  ]);
2063
2136
  }
2137
+ function invalidateAllRuntimeViewEntries(queryClient) {
2138
+ return queryClient.invalidateQueries({ queryKey: ["builder", "runtime", "view"] });
2139
+ }
2064
2140
  function useBuilderDbTables() {
2065
2141
  return useQuery({ queryKey: builderKeys.dbTables(), queryFn: client.listBuilderDbTables });
2066
2142
  }
@@ -2271,14 +2347,20 @@ function createBuilderHooks(client) {
2271
2347
  viewId,
2272
2348
  input
2273
2349
  ),
2274
- onSuccess: () => invalidateRuntimeViewEntries(queryClient, viewId)
2350
+ onSuccess: (entry) => {
2351
+ replaceCachedRuntimeViewEntry(queryClient, viewId, entry);
2352
+ return invalidateRuntimeViewEntries(queryClient, viewId);
2353
+ }
2275
2354
  });
2276
2355
  }
2277
2356
  function useCreateCompositeBuilderViewEntry(viewId) {
2278
2357
  const queryClient = useQueryClient();
2279
2358
  return useMutation({
2280
2359
  mutationFn: (input) => client.createCompositeBuilderViewEntry(viewId, input),
2281
- onSuccess: () => invalidateRuntimeViewEntries(queryClient, viewId)
2360
+ onSuccess: (entry) => {
2361
+ replaceCachedRuntimeViewEntry(queryClient, viewId, entry);
2362
+ return invalidateAllRuntimeViewEntries(queryClient);
2363
+ }
2282
2364
  });
2283
2365
  }
2284
2366
  function useUpdateCompositeBuilderViewEntry(viewId) {
@@ -2288,7 +2370,10 @@ function createBuilderHooks(client) {
2288
2370
  id,
2289
2371
  input
2290
2372
  }) => client.updateCompositeBuilderViewEntry(viewId, id, input),
2291
- onSuccess: () => invalidateRuntimeViewEntries(queryClient, viewId)
2373
+ onSuccess: (entry) => {
2374
+ replaceCachedRuntimeViewEntry(queryClient, viewId, entry);
2375
+ return invalidateAllRuntimeViewEntries(queryClient);
2376
+ }
2292
2377
  });
2293
2378
  }
2294
2379
  function useDeleteBuilderViewEntry(id) {