@duke333/builder-ui 0.2.2 → 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 { P as createBuilderAdminPages, b as BuilderAdminPagesOptions, a as BuilderAdminPageContracts } from '../BuilderAdminPages-C-jaMLOa.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",
@@ -251,16 +272,19 @@ function builderFormEditorValuesFromEntity(form, emptyValues) {
251
272
  function builderListEditorValuesFromEntity(list, emptyValues) {
252
273
  if (!list) return emptyValues;
253
274
  const source = list.source;
275
+ const orderBy = list.schema.orderBy ? Array.isArray(list.schema.orderBy) ? list.schema.orderBy : [list.schema.orderBy] : [];
254
276
  return {
255
277
  title: list.title,
256
278
  description: list.description ?? "",
257
279
  sourceType: source?.type ?? "none",
258
280
  sourceTable: source?.type === "dbTable" ? source.tableName : BUILDER_EDITOR_NONE_VALUE,
259
281
  apiBasePath: source?.type === "apiEndpoint" ? source.basePath : "",
282
+ orderBy,
260
283
  columns: list.schema.columns.map((column) => ({
261
284
  key: column.key,
262
285
  label: column.label,
263
286
  sortable: column.sortable,
287
+ hidden: column.hidden ?? false,
264
288
  align: column.align
265
289
  })),
266
290
  triggers: valuesFromTriggers(list.triggers),
@@ -288,6 +312,10 @@ function builderFormEditorFieldsFromTable(table) {
288
312
  required: !column.nullable,
289
313
  hidden: false,
290
314
  disabled: false,
315
+ storage: "s3",
316
+ contentKind: "image",
317
+ multiple: false,
318
+ maxMegabytes: 10,
291
319
  placeholder: column.label,
292
320
  optionsText: "",
293
321
  optionsMode: "static",
@@ -305,6 +333,7 @@ function builderListEditorColumnsFromTable(table) {
305
333
  key: column.name,
306
334
  label: column.label,
307
335
  sortable: column.sortable,
336
+ hidden: false,
308
337
  align: column.fieldType === "number" || column.fieldType === "money" ? "right" : "left"
309
338
  }));
310
339
  }
@@ -323,6 +352,10 @@ function builderFormEditorInputFromValues(values) {
323
352
  required: field.required,
324
353
  hidden: field.hidden,
325
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,
326
359
  placeholder: field.placeholder?.trim() || field.label,
327
360
  options: field.type === "select" && field.optionsMode === "static" ? builderEditorTextToOptions(field.optionsText) : void 0,
328
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 ? {
@@ -376,11 +409,19 @@ function builderFormEditorInputFromValues(values) {
376
409
  }
377
410
  function builderListEditorInputFromValues(values) {
378
411
  const source = values.sourceType === "dbTable" && values.sourceTable !== BUILDER_EDITOR_NONE_VALUE ? { type: "dbTable", tableName: values.sourceTable } : values.sourceType === "apiEndpoint" && values.apiBasePath ? { type: "apiEndpoint", basePath: values.apiBasePath } : null;
412
+ const orderBy = Array.from(
413
+ new Map(
414
+ values.orderBy.filter((rule) => rule.field && rule.field !== BUILDER_EDITOR_NONE_VALUE).map((rule) => [rule.field, rule])
415
+ ).values()
416
+ );
379
417
  return {
380
418
  title: values.title,
381
419
  description: values.description || null,
382
420
  source,
383
- schema: { columns: values.columns },
421
+ schema: {
422
+ columns: values.columns,
423
+ ...source && orderBy.length > 0 ? { orderBy } : {}
424
+ },
384
425
  triggers: values.triggers.map((trigger) => ({
385
426
  event: trigger.event,
386
427
  action: "callApi",
@@ -405,7 +446,7 @@ function builderViewEditorInputFromValues(values, parseTriggers) {
405
446
  }
406
447
 
407
448
  // src/admin/BuilderDefaultEditorBodies.tsx
408
- import { jsx, jsxs } from "react/jsx-runtime";
449
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
409
450
  var styles = {
410
451
  page: {
411
452
  display: "grid",
@@ -583,10 +624,18 @@ function createBuilderDefaultFormEditorBody(options) {
583
624
  ] }),
584
625
  sourceType === "dbTable" ? /* @__PURE__ */ jsxs("label", { style: styles.field, children: [
585
626
  /* @__PURE__ */ jsx("span", { style: styles.label, children: "Table" }),
586
- /* @__PURE__ */ jsxs("select", { style: styles.input, ...form.register("sourceTable"), children: [
587
- /* @__PURE__ */ jsx("option", { value: BUILDER_EDITOR_NONE_VALUE, children: "Select table" }),
588
- tables.map((table) => /* @__PURE__ */ jsx("option", { value: table.name, children: table.label ?? table.name }, table.name))
589
- ] })
627
+ /* @__PURE__ */ jsxs(
628
+ "select",
629
+ {
630
+ style: styles.input,
631
+ value: sourceTable,
632
+ ...form.register("sourceTable"),
633
+ children: [
634
+ /* @__PURE__ */ jsx("option", { value: BUILDER_EDITOR_NONE_VALUE, children: "Select table" }),
635
+ tables.map((table) => /* @__PURE__ */ jsx("option", { value: table.name, children: table.label ?? table.name }, table.name))
636
+ ]
637
+ }
638
+ )
590
639
  ] }) : null,
591
640
  sourceType === "apiEndpoint" ? /* @__PURE__ */ jsxs("label", { style: styles.field, children: [
592
641
  /* @__PURE__ */ jsx("span", { style: styles.label, children: "API base path" }),
@@ -660,6 +709,30 @@ function createBuilderDefaultFormEditorBody(options) {
660
709
  /* @__PURE__ */ jsx("input", { type: "checkbox", ...form.register(`fields.${index}.disabled`) }),
661
710
  "Disabled"
662
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,
663
736
  /* @__PURE__ */ jsxs("label", { style: styles.field, children: [
664
737
  /* @__PURE__ */ jsx("span", { style: styles.label, children: "Placeholder" }),
665
738
  /* @__PURE__ */ jsx("input", { style: styles.input, ...form.register(`fields.${index}.placeholder`) })
@@ -844,6 +917,7 @@ function createBuilderDefaultListEditorBody(options) {
844
917
  listId,
845
918
  form,
846
919
  columnArray,
920
+ orderByArray,
847
921
  triggerArray,
848
922
  sourceType,
849
923
  sourceTable,
@@ -853,6 +927,8 @@ function createBuilderDefaultListEditorBody(options) {
853
927
  isSaving,
854
928
  importColumnsFromTable
855
929
  }) {
930
+ const selectedTable = tables.find((table) => table.name === sourceTable);
931
+ const orderByColumns = selectedTable?.columns.filter((column) => column.sortable) ?? [];
856
932
  return /* @__PURE__ */ jsxs("div", { style: styles.page, children: [
857
933
  /* @__PURE__ */ jsxs("div", { style: styles.header, children: [
858
934
  /* @__PURE__ */ jsxs("div", { children: [
@@ -885,10 +961,18 @@ function createBuilderDefaultListEditorBody(options) {
885
961
  ] }),
886
962
  sourceType === "dbTable" ? /* @__PURE__ */ jsxs("label", { style: styles.field, children: [
887
963
  /* @__PURE__ */ jsx("span", { style: styles.label, children: "Table" }),
888
- /* @__PURE__ */ jsxs("select", { style: styles.input, ...form.register("sourceTable"), children: [
889
- /* @__PURE__ */ jsx("option", { value: BUILDER_EDITOR_NONE_VALUE, children: "Select table" }),
890
- tables.map((table) => /* @__PURE__ */ jsx("option", { value: table.name, children: table.label ?? table.name }, table.name))
891
- ] })
964
+ /* @__PURE__ */ jsxs(
965
+ "select",
966
+ {
967
+ style: styles.input,
968
+ value: sourceTable,
969
+ ...form.register("sourceTable"),
970
+ children: [
971
+ /* @__PURE__ */ jsx("option", { value: BUILDER_EDITOR_NONE_VALUE, children: "Select table" }),
972
+ tables.map((table) => /* @__PURE__ */ jsx("option", { value: table.name, children: table.label ?? table.name }, table.name))
973
+ ]
974
+ }
975
+ )
892
976
  ] }) : null,
893
977
  sourceType === "apiEndpoint" ? /* @__PURE__ */ jsxs("label", { style: styles.field, children: [
894
978
  /* @__PURE__ */ jsx("span", { style: styles.label, children: "API base path" }),
@@ -906,6 +990,85 @@ function createBuilderDefaultListEditorBody(options) {
906
990
  ) }) : null
907
991
  ] })
908
992
  ] }),
993
+ /* @__PURE__ */ jsxs("section", { style: styles.section, children: [
994
+ /* @__PURE__ */ jsxs("div", { style: styles.sectionHeader, children: [
995
+ /* @__PURE__ */ jsxs("div", { children: [
996
+ /* @__PURE__ */ jsx("h2", { style: styles.sectionTitle, children: "Default ordering" }),
997
+ /* @__PURE__ */ jsx("p", { style: styles.description, children: "Rules are applied from top to bottom." })
998
+ ] }),
999
+ /* @__PURE__ */ jsx(
1000
+ "button",
1001
+ {
1002
+ type: "button",
1003
+ style: styles.button,
1004
+ disabled: sourceType === "none" || orderByArray.fields.length >= 8,
1005
+ onClick: () => orderByArray.append({
1006
+ field: sourceType === "dbTable" ? orderByColumns[0]?.name ?? BUILDER_EDITOR_NONE_VALUE : "",
1007
+ direction: "desc"
1008
+ }),
1009
+ children: "Add ordering"
1010
+ }
1011
+ )
1012
+ ] }),
1013
+ orderByArray.fields.length === 0 ? /* @__PURE__ */ jsx("div", { style: styles.grid, children: /* @__PURE__ */ jsx("p", { style: styles.description, children: "Automatic ordering is used." }) }) : null,
1014
+ orderByArray.fields.map((rule, index) => /* @__PURE__ */ jsxs("div", { style: styles.row, children: [
1015
+ sourceType === "dbTable" ? /* @__PURE__ */ jsxs("label", { style: styles.field, children: [
1016
+ /* @__PURE__ */ jsx("span", { style: styles.label, children: "Order by field" }),
1017
+ /* @__PURE__ */ jsxs("select", { style: styles.input, ...form.register(`orderBy.${index}.field`), children: [
1018
+ /* @__PURE__ */ jsx("option", { value: BUILDER_EDITOR_NONE_VALUE, children: "Select field" }),
1019
+ orderByColumns.map((column) => /* @__PURE__ */ jsx("option", { value: column.name, children: column.label }, column.name))
1020
+ ] })
1021
+ ] }) : /* @__PURE__ */ jsxs("label", { style: styles.field, children: [
1022
+ /* @__PURE__ */ jsx("span", { style: styles.label, children: "Order by field" }),
1023
+ /* @__PURE__ */ jsx(
1024
+ "input",
1025
+ {
1026
+ style: styles.input,
1027
+ placeholder: "createdAt",
1028
+ ...form.register(`orderBy.${index}.field`)
1029
+ }
1030
+ )
1031
+ ] }),
1032
+ /* @__PURE__ */ jsxs("label", { style: styles.field, children: [
1033
+ /* @__PURE__ */ jsx("span", { style: styles.label, children: "Direction" }),
1034
+ /* @__PURE__ */ jsxs("select", { style: styles.input, ...form.register(`orderBy.${index}.direction`), children: [
1035
+ /* @__PURE__ */ jsx("option", { value: "asc", children: "Ascending" }),
1036
+ /* @__PURE__ */ jsx("option", { value: "desc", children: "Descending" })
1037
+ ] })
1038
+ ] }),
1039
+ /* @__PURE__ */ jsxs("div", { style: styles.actions, children: [
1040
+ /* @__PURE__ */ jsx(
1041
+ "button",
1042
+ {
1043
+ type: "button",
1044
+ style: styles.button,
1045
+ disabled: index === 0,
1046
+ onClick: () => orderByArray.move(index, index - 1),
1047
+ children: "Move up"
1048
+ }
1049
+ ),
1050
+ /* @__PURE__ */ jsx(
1051
+ "button",
1052
+ {
1053
+ type: "button",
1054
+ style: styles.button,
1055
+ disabled: index === orderByArray.fields.length - 1,
1056
+ onClick: () => orderByArray.move(index, index + 1),
1057
+ children: "Move down"
1058
+ }
1059
+ ),
1060
+ /* @__PURE__ */ jsx(
1061
+ "button",
1062
+ {
1063
+ type: "button",
1064
+ style: styles.button,
1065
+ onClick: () => orderByArray.remove(index),
1066
+ children: "Remove"
1067
+ }
1068
+ )
1069
+ ] })
1070
+ ] }, rule.id))
1071
+ ] }),
909
1072
  /* @__PURE__ */ jsxs("section", { style: styles.section, children: [
910
1073
  /* @__PURE__ */ jsxs("div", { style: styles.sectionHeader, children: [
911
1074
  /* @__PURE__ */ jsxs("div", { children: [
@@ -946,16 +1109,10 @@ function createBuilderDefaultListEditorBody(options) {
946
1109
  /* @__PURE__ */ jsx("input", { type: "checkbox", ...form.register(`columns.${index}.sortable`) }),
947
1110
  "Sortable"
948
1111
  ] }),
949
- /* @__PURE__ */ jsx(
950
- "button",
951
- {
952
- type: "button",
953
- style: styles.button,
954
- onClick: () => columnArray.remove(index),
955
- disabled: columnArray.fields.length <= 1,
956
- children: "Remove"
957
- }
958
- )
1112
+ /* @__PURE__ */ jsxs("label", { style: styles.checkboxField, children: [
1113
+ /* @__PURE__ */ jsx("input", { type: "checkbox", ...form.register(`columns.${index}.hidden`) }),
1114
+ "Hidden"
1115
+ ] })
959
1116
  ] }, column.id))
960
1117
  ] }),
961
1118
  /* @__PURE__ */ jsxs("section", { style: styles.section, children: [
@@ -1186,7 +1343,7 @@ function createBuilderDefaultEntityManagerComponent(deps) {
1186
1343
  // src/admin/BuilderDefaultViewEditorPage.tsx
1187
1344
  import { useEffect } from "react";
1188
1345
  import { useForm } from "react-hook-form";
1189
- 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";
1190
1347
  var styles3 = {
1191
1348
  page: {
1192
1349
  display: "grid",
@@ -1373,7 +1530,7 @@ function createBuilderDefaultViewEditorPage(options) {
1373
1530
  (lists.data ?? []).map((item) => /* @__PURE__ */ jsx3("option", { value: item.id, children: item.title }, item.id))
1374
1531
  ] })
1375
1532
  ] }),
1376
- showPermissions ? /* @__PURE__ */ jsxs3(Fragment, { children: [
1533
+ showPermissions ? /* @__PURE__ */ jsxs3(Fragment2, { children: [
1377
1534
  /* @__PURE__ */ jsxs3("label", { style: styles3.field, children: [
1378
1535
  /* @__PURE__ */ jsx3("span", { style: styles3.label, children: "Read permission" }),
1379
1536
  /* @__PURE__ */ jsxs3("select", { style: styles3.input, ...form.register("permissionRead"), children: [
@@ -1484,6 +1641,7 @@ function createBuilderListEditorPageComponent(deps) {
1484
1641
  defaultValues: deps.emptyValues
1485
1642
  });
1486
1643
  const columnArray = useFieldArray({ control: form.control, name: "columns" });
1644
+ const orderByArray = useFieldArray({ control: form.control, name: "orderBy" });
1487
1645
  const triggerArray = useFieldArray({ control: form.control, name: "triggers" });
1488
1646
  const sourceType = useWatch({ control: form.control, name: "sourceType" });
1489
1647
  const sourceTable = useWatch({ control: form.control, name: "sourceTable" });
@@ -1517,6 +1675,7 @@ function createBuilderListEditorPageComponent(deps) {
1517
1675
  listId,
1518
1676
  form,
1519
1677
  columnArray,
1678
+ orderByArray,
1520
1679
  triggerArray,
1521
1680
  sourceType,
1522
1681
  sourceTable,
@@ -1535,6 +1694,7 @@ import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
1535
1694
  var defaultFieldTypeOptions = [
1536
1695
  { value: "text", label: "Text" },
1537
1696
  { value: "textarea", label: "Textarea" },
1697
+ { value: "richtext", label: "Rich text" },
1538
1698
  { value: "number", label: "Number" },
1539
1699
  { value: "money", label: "Money" },
1540
1700
  { value: "select", label: "Select" },
@@ -1645,6 +1805,10 @@ function createBuilderAdminPages({
1645
1805
  required: true,
1646
1806
  hidden: false,
1647
1807
  disabled: false,
1808
+ storage: "s3",
1809
+ contentKind: "image",
1810
+ multiple: false,
1811
+ maxMegabytes: 10,
1648
1812
  placeholder: "",
1649
1813
  optionsText: "",
1650
1814
  optionsMode: "static",
@@ -1679,6 +1843,7 @@ function createBuilderAdminPages({
1679
1843
  key: "name",
1680
1844
  label: "Name",
1681
1845
  sortable: true,
1846
+ hidden: false,
1682
1847
  align: "left"
1683
1848
  };
1684
1849
  const emptyListValues = {
@@ -1687,6 +1852,7 @@ function createBuilderAdminPages({
1687
1852
  sourceType: "none",
1688
1853
  sourceTable: BUILDER_EDITOR_NONE_VALUE,
1689
1854
  apiBasePath: "",
1855
+ orderBy: [],
1690
1856
  columns: [emptyColumn],
1691
1857
  triggers: [],
1692
1858
  version: 0
@@ -1947,12 +2113,30 @@ function createBuilderKeys() {
1947
2113
  }
1948
2114
  function createBuilderHooks(client) {
1949
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
+ }
1950
2131
  function invalidateRuntimeViewEntries(queryClient, viewId) {
1951
2132
  return Promise.all([
1952
2133
  queryClient.invalidateQueries({ queryKey: builderKeys.runtimeView(viewId) }),
1953
2134
  queryClient.invalidateQueries({ queryKey: [...builderKeys.runtimeView(viewId), "entries"] })
1954
2135
  ]);
1955
2136
  }
2137
+ function invalidateAllRuntimeViewEntries(queryClient) {
2138
+ return queryClient.invalidateQueries({ queryKey: ["builder", "runtime", "view"] });
2139
+ }
1956
2140
  function useBuilderDbTables() {
1957
2141
  return useQuery({ queryKey: builderKeys.dbTables(), queryFn: client.listBuilderDbTables });
1958
2142
  }
@@ -2163,14 +2347,20 @@ function createBuilderHooks(client) {
2163
2347
  viewId,
2164
2348
  input
2165
2349
  ),
2166
- onSuccess: () => invalidateRuntimeViewEntries(queryClient, viewId)
2350
+ onSuccess: (entry) => {
2351
+ replaceCachedRuntimeViewEntry(queryClient, viewId, entry);
2352
+ return invalidateRuntimeViewEntries(queryClient, viewId);
2353
+ }
2167
2354
  });
2168
2355
  }
2169
2356
  function useCreateCompositeBuilderViewEntry(viewId) {
2170
2357
  const queryClient = useQueryClient();
2171
2358
  return useMutation({
2172
2359
  mutationFn: (input) => client.createCompositeBuilderViewEntry(viewId, input),
2173
- onSuccess: () => invalidateRuntimeViewEntries(queryClient, viewId)
2360
+ onSuccess: (entry) => {
2361
+ replaceCachedRuntimeViewEntry(queryClient, viewId, entry);
2362
+ return invalidateAllRuntimeViewEntries(queryClient);
2363
+ }
2174
2364
  });
2175
2365
  }
2176
2366
  function useUpdateCompositeBuilderViewEntry(viewId) {
@@ -2180,7 +2370,10 @@ function createBuilderHooks(client) {
2180
2370
  id,
2181
2371
  input
2182
2372
  }) => client.updateCompositeBuilderViewEntry(viewId, id, input),
2183
- onSuccess: () => invalidateRuntimeViewEntries(queryClient, viewId)
2373
+ onSuccess: (entry) => {
2374
+ replaceCachedRuntimeViewEntry(queryClient, viewId, entry);
2375
+ return invalidateAllRuntimeViewEntries(queryClient);
2376
+ }
2184
2377
  });
2185
2378
  }
2186
2379
  function useDeleteBuilderViewEntry(id) {