@duke333/builder-ui 0.2.4 → 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.
package/dist/index.d.ts CHANGED
@@ -8,7 +8,7 @@ export { createBuilderHooks, createBuilderKeys } from './hooks/index.js';
8
8
  import { BuilderDbTable, BuilderForm as BuilderForm$1, BuilderList, BuilderView as BuilderView$1, BuilderViewEntry, ListBuilderFormsQuery, ListBuilderFormsResponse, CreateBuilderFormInput, UpdateBuilderFormInput, ListBuilderListsQuery, ListBuilderListsResponse, CreateBuilderListInput, UpdateBuilderListInput, ListBuilderViewsQuery, ListBuilderViewsResponse, CreateBuilderViewInput, UpdateBuilderViewInput, ReplicateBuilderEntityInput, CreateBuilderViewEntryInput, CreateCompositeBuilderViewEntryInput, UpdateCompositeBuilderViewEntryInput, UpdateBuilderViewEntryInput, ListBuilderFieldOptionsQuery, ListBuilderFieldOptionsResponse, RunBuilderFieldTriggerInput, BuilderFieldTriggerEvent, BuilderFieldTriggerResponse, ListBuilderViewEntriesQuery, ListBuilderViewEntriesResponse, BuilderFileUploadRequest, BuilderFileUploadResponse, BuilderFilePresignResponse, BuilderField } from '@duke333/builder-contracts';
9
9
  import { FieldValues, Path } from 'react-hook-form';
10
10
  export { richTextToPlainText, toRichTextDocument } from './runtime/index.js';
11
- export { B as BUILDER_EDITOR_NONE_VALUE, a as BuilderAdminPageContracts, b as BuilderAdminPagesOptions, c as BuilderAdminPagesRoutes, d as BuilderDefaultEntity, e as BuilderDefaultEntityListResult, f as BuilderDefaultEntityManagerDependencies, g as BuilderDefaultEntityManagerLabels, h as BuilderDefaultEntityManagerState, i as BuilderDefaultEntityMutation, j as BuilderDefaultEntityQueryResult, k as BuilderDefaultFormEditorBodyOptions, l as BuilderDefaultListEditorBodyOptions, m as BuilderDefaultOption, n as BuilderEditorDbTable, o as BuilderEditorSelectOption, p as BuilderEditorTriggerValues, q as BuilderFormEditorBodyProps, r as BuilderFormEditorEntity, s as BuilderFormEditorFieldValues, t as BuilderFormEditorPageDependencies, u as BuilderFormEditorValues, v as BuilderListEditorBodyProps, w as BuilderListEditorColumnValues, x as BuilderListEditorEntity, y as BuilderListEditorOrderByValues, z as BuilderListEditorPageDependencies, A as BuilderListEditorValues, C as BuilderViewEditorEntity, D as BuilderViewEditorValues, E as builderEditorOptionsToText, F as builderEditorSearchFieldsToText, G as builderEditorTextToOptions, H as builderEditorTextToSearchFields, I as builderFormEditorFieldsFromTable, J as builderFormEditorInputFromValues, K as builderFormEditorValuesFromEntity, L as builderListEditorColumnsFromTable, M as builderListEditorInputFromValues, N as builderListEditorValuesFromEntity, O as builderViewEditorInputFromValues, P as builderViewEditorValuesFromEntity, Q as createBuilderAdminPages, R as createBuilderDefaultEntityManagerComponent, S as createBuilderDefaultFormEditorBody, T as createBuilderDefaultListEditorBody, U as createBuilderFormEditorPageComponent, V as createBuilderListEditorPageComponent, W as getBuilderEditorTriggerRoute } from './BuilderAdminPages-DwwdA8Dv.js';
11
+ export { B as BUILDER_EDITOR_NONE_VALUE, a as BuilderAdminPageContracts, b as BuilderAdminPagesOptions, c as BuilderAdminPagesRoutes, d as BuilderDefaultEntity, e as BuilderDefaultEntityListResult, f as BuilderDefaultEntityManagerDependencies, g as BuilderDefaultEntityManagerLabels, h as BuilderDefaultEntityManagerState, i as BuilderDefaultEntityMutation, j as BuilderDefaultEntityQueryResult, k as BuilderDefaultFormEditorBodyOptions, l as BuilderDefaultListEditorBodyOptions, m as BuilderDefaultOption, n as BuilderEditorDbTable, o as BuilderEditorSelectOption, p as BuilderEditorTriggerValues, q as BuilderFormEditorBodyProps, r as BuilderFormEditorEntity, s as BuilderFormEditorFieldValues, t as BuilderFormEditorPageDependencies, u as BuilderFormEditorValues, v as BuilderListEditorBodyProps, w as BuilderListEditorColumnValues, x as BuilderListEditorEntity, y as BuilderListEditorOrderByValues, z as BuilderListEditorPageDependencies, A as BuilderListEditorValues, C as BuilderViewEditorEntity, D as BuilderViewEditorValues, E as builderEditorOptionsToText, F as builderEditorSearchFieldsToText, G as builderEditorTextToOptions, H as builderEditorTextToSearchFields, I as builderFormEditorFieldsFromTable, J as builderFormEditorInputFromValues, K as builderFormEditorValuesFromEntity, L as builderListEditorColumnsFromTable, M as builderListEditorInputFromValues, N as builderListEditorValuesFromEntity, O as builderViewEditorInputFromValues, P as builderViewEditorValuesFromEntity, Q as createBuilderAdminPages, R as createBuilderDefaultEntityManagerComponent, S as createBuilderDefaultFormEditorBody, T as createBuilderDefaultListEditorBody, U as createBuilderFormEditorPageComponent, V as createBuilderListEditorPageComponent, W as getBuilderEditorTriggerRoute } from './BuilderAdminPages-bV-lwDOp.js';
12
12
  export { BuilderDefaultViewEditorContracts, BuilderDefaultViewEditorPageOptions, BuilderEntityDialogManagerDependencies, BuilderEntityManagerActions, BuilderEntityManagerAddButtonProps, BuilderEntityManagerDataGridProps, BuilderEntityManagerDeleteDialogProps, BuilderEntityManagerDependencies, BuilderEntityManagerDialogAddButtonProps, BuilderEntityManagerEditorDialogProps, BuilderEntityManagerEntity, BuilderEntityManagerHookResult, BuilderEntityManagerLabels, BuilderEntityManagerMutation, BuilderFormLayoutDragPayload, BuilderFormLayoutItem, BuilderViewDialogBodyProps, BuilderViewDialogDependencies, BuilderViewDialogProps, BuilderViewDialogShellProps, builderFormLayoutDragDataType, clampBuilderFormLayoutSpan, createBuilderDefaultViewEditorPage, createBuilderEntityDialogManagerComponent, createBuilderEntityManagerComponent, createBuilderViewDialogComponent, nextBuilderFormLayoutGroupId, parseBuilderFormLayoutDragPayload, serializeBuilderFormLayoutDragPayload, swapBuilderFormLayoutItems, useBuilderFormLayoutEditor } from './admin/index.js';
13
13
  export { D as DynamicFormContracts, a as DynamicFormDependencies, b as DynamicFormErrorStateProps, c as DynamicFormFieldsProps, d as DynamicFormNotifications, e as DynamicFormProps, f as DynamicFormShellProps, g as DynamicFormSubmitProps, h as DynamicListContracts, i as DynamicListDataGridProps, j as DynamicListDependencies, k as DynamicListErrorStateProps, l as DynamicListProps, m as DynamicViewAddButtonProps, n as DynamicViewColumnActions, o as DynamicViewContracts, p as DynamicViewDataGridProps, q as DynamicViewDeleteDialogProps, r as DynamicViewDependencies, s as DynamicViewEntryDialogProps, t as DynamicViewErrorStateProps, u as DynamicViewInteractionEvent, v as DynamicViewProps, w as RuntimeEntryDialogActionsProps, x as RuntimeEntryDialogDependencies, y as RuntimeEntryDialogFieldsProps, z as RuntimeEntryDialogNotifications, A as RuntimeEntryDialogProps, B as RuntimeEntryDialogSaveArgs, C as RuntimeEntryDialogShellProps, E as RuntimeEntryDialogViewLike, F as createDynamicFormComponent, G as createDynamicListComponent, H as createDynamicViewComponent, I as createRuntimeEntryDialogComponent, J as shouldHandleDynamicViewRowClick } from './RuntimeEntryDialog-B4TbF8os.js';
14
14
  export { b as BuilderRuntimeEntryLike, c as BuilderRuntimeEntryValues, f as BuilderRuntimeFieldLike, a as BuilderRuntimeFormSchemaLike, d as BuilderRuntimeFormValues, B as BuilderRuntimePresentation, e as BuilderRuntimeViewLike, g as createBuilderEntryDefaultValues, h as createBuilderFormDefaultValues, i as formatBuilderRuntimeValue } from './runtimeUtils-CCtLyIf1.js';
@@ -149,6 +149,7 @@ declare function createBuilderClient({ transport, apiBasePath }: CreateBuilderCl
149
149
  icon?: string | undefined;
150
150
  }[];
151
151
  layout?: {
152
+ presentation: "stacked" | "tabs";
152
153
  groups: {
153
154
  id: string;
154
155
  columns: 8 | 6 | 12;
@@ -263,6 +264,7 @@ declare function createBuilderClient({ transport, apiBasePath }: CreateBuilderCl
263
264
  icon?: string | undefined;
264
265
  }[];
265
266
  layout?: {
267
+ presentation: "stacked" | "tabs";
266
268
  groups: {
267
269
  id: string;
268
270
  columns: 8 | 6 | 12;
@@ -353,6 +355,7 @@ declare function createBuilderClient({ transport, apiBasePath }: CreateBuilderCl
353
355
  icon?: string | undefined;
354
356
  }[];
355
357
  layout?: {
358
+ presentation: "stacked" | "tabs";
356
359
  groups: {
357
360
  id: string;
358
361
  columns: 8 | 6 | 12;
@@ -424,6 +427,7 @@ declare function createBuilderClient({ transport, apiBasePath }: CreateBuilderCl
424
427
  icon?: string | undefined;
425
428
  }[];
426
429
  layout?: {
430
+ presentation: "stacked" | "tabs";
427
431
  groups: {
428
432
  id: string;
429
433
  columns: 8 | 6 | 12;
@@ -525,6 +529,7 @@ declare function createBuilderClient({ transport, apiBasePath }: CreateBuilderCl
525
529
  icon?: string | undefined;
526
530
  }[];
527
531
  layout?: {
532
+ presentation: "stacked" | "tabs";
528
533
  groups: {
529
534
  id: string;
530
535
  columns: 8 | 6 | 12;
@@ -596,6 +601,7 @@ declare function createBuilderClient({ transport, apiBasePath }: CreateBuilderCl
596
601
  icon?: string | undefined;
597
602
  }[];
598
603
  layout?: {
604
+ presentation: "stacked" | "tabs";
599
605
  groups: {
600
606
  id: string;
601
607
  columns: 8 | 6 | 12;
@@ -698,6 +704,7 @@ declare function createBuilderClient({ transport, apiBasePath }: CreateBuilderCl
698
704
  icon?: string | undefined;
699
705
  }[];
700
706
  layout?: {
707
+ presentation: "stacked" | "tabs";
701
708
  groups: {
702
709
  id: string;
703
710
  columns: 8 | 6 | 12;
@@ -790,6 +797,7 @@ declare function createBuilderClient({ transport, apiBasePath }: CreateBuilderCl
790
797
  icon?: string | undefined;
791
798
  }[];
792
799
  layout?: {
800
+ presentation: "stacked" | "tabs";
793
801
  groups: {
794
802
  id: string;
795
803
  columns: 8 | 6 | 12;
@@ -1233,6 +1241,7 @@ declare function createBuilderClient({ transport, apiBasePath }: CreateBuilderCl
1233
1241
  icon?: string | undefined;
1234
1242
  }[];
1235
1243
  layout?: {
1244
+ presentation: "stacked" | "tabs";
1236
1245
  groups: {
1237
1246
  id: string;
1238
1247
  columns: 8 | 6 | 12;
@@ -1386,6 +1395,7 @@ declare function createBuilderClient({ transport, apiBasePath }: CreateBuilderCl
1386
1395
  icon?: string | undefined;
1387
1396
  }[];
1388
1397
  layout?: {
1398
+ presentation: "stacked" | "tabs";
1389
1399
  groups: {
1390
1400
  id: string;
1391
1401
  columns: 8 | 6 | 12;
@@ -1549,6 +1559,7 @@ declare function createBuilderClient({ transport, apiBasePath }: CreateBuilderCl
1549
1559
  icon?: string | undefined;
1550
1560
  }[];
1551
1561
  layout?: {
1562
+ presentation: "stacked" | "tabs";
1552
1563
  groups: {
1553
1564
  id: string;
1554
1565
  columns: 8 | 6 | 12;
@@ -1713,6 +1724,7 @@ declare function createBuilderClient({ transport, apiBasePath }: CreateBuilderCl
1713
1724
  icon?: string | undefined;
1714
1725
  }[];
1715
1726
  layout?: {
1727
+ presentation: "stacked" | "tabs";
1716
1728
  groups: {
1717
1729
  id: string;
1718
1730
  columns: 8 | 6 | 12;
@@ -1864,6 +1876,7 @@ declare function createBuilderClient({ transport, apiBasePath }: CreateBuilderCl
1864
1876
  icon?: string | undefined;
1865
1877
  }[];
1866
1878
  layout?: {
1879
+ presentation: "stacked" | "tabs";
1867
1880
  groups: {
1868
1881
  id: string;
1869
1882
  columns: 8 | 6 | 12;
@@ -1998,6 +2011,7 @@ declare function createBuilderClient({ transport, apiBasePath }: CreateBuilderCl
1998
2011
  icon?: string | undefined;
1999
2012
  }[];
2000
2013
  layout?: {
2014
+ presentation: "stacked" | "tabs";
2001
2015
  groups: {
2002
2016
  id: string;
2003
2017
  columns: 8 | 6 | 12;
@@ -2204,6 +2218,7 @@ declare function createBuilderClient({ transport, apiBasePath }: CreateBuilderCl
2204
2218
  icon?: string | undefined;
2205
2219
  }[];
2206
2220
  layout?: {
2221
+ presentation: "stacked" | "tabs";
2207
2222
  groups: {
2208
2223
  id: string;
2209
2224
  columns: 8 | 6 | 12;
@@ -2419,7 +2434,7 @@ declare function RichTextContent({ className, value }: RichTextContentProps): re
2419
2434
 
2420
2435
  declare const builderUiPackage: {
2421
2436
  readonly name: "@duke333/builder-ui";
2422
- readonly version: "0.2.4";
2437
+ readonly version: "0.2.5";
2423
2438
  };
2424
2439
 
2425
2440
  export { BuilderApiClient, BuilderApiContracts, BuilderApiTransport, type BuilderClient, BuilderFieldOptionsQuery, BuilderForm, type BuilderFormProps, BuilderGrid, type BuilderGridProps, BuilderHooks, type BuilderNotification, BuilderProvider, type BuilderProviderProps, type BuilderRuntimeComponents, BuilderView, type BuilderViewProps, type CreateBuilderClientOptions, type ReadyBuilderContracts, ReadyFileField, ReadyRichTextField, RichTextContent, type RichTextContentProps, builderErrorMessage, builderUiPackage, createBuilderClient, useBuilderRuntime };
package/dist/index.js CHANGED
@@ -514,7 +514,7 @@ function builderErrorMessage(error, fallback) {
514
514
  }
515
515
 
516
516
  // src/ready/BuilderRuntimeComponents.tsx
517
- import { useMemo as useMemo4, useRef as useRef7, useState as useState6 } from "react";
517
+ import { useMemo as useMemo4, useRef as useRef7, useState as useState7 } from "react";
518
518
  import { FormProvider as FormProvider2, useForm as useForm2 } from "react-hook-form";
519
519
 
520
520
  // src/richText.ts
@@ -582,7 +582,7 @@ function formatBuilderRuntimeValue(value, locale = "mn-MN") {
582
582
  }
583
583
 
584
584
  // src/ready/ReadyFields.tsx
585
- import { useRef as useRef4 } from "react";
585
+ import { useId as useId2, useRef as useRef4, useState as useState3 } from "react";
586
586
  import { useFormContext as useFormContext3, useWatch as useWatch3 } from "react-hook-form";
587
587
 
588
588
  // src/ready/ReadyFileField.tsx
@@ -931,15 +931,57 @@ function ReadyFields({
931
931
  }) {
932
932
  const fields = new Map(schema.fields.map((field) => [field.key, field]));
933
933
  const rendered = /* @__PURE__ */ new Set();
934
+ const groups = schema.layout?.groups ?? [];
935
+ const tabsId = useId2();
936
+ const [selectedGroupId, setSelectedGroupId] = useState3(groups[0]?.id ?? "");
937
+ const activeGroupId = groups.some((group) => group.id === selectedGroupId) ? selectedGroupId : groups[0]?.id ?? "";
938
+ const renderGroupFields = (group) => /* @__PURE__ */ jsx4("div", { className: "builder-form-grid", children: group.fields.map((item) => {
939
+ const field = fields.get(item.key);
940
+ if (!field) return null;
941
+ rendered.add(field.key);
942
+ return /* @__PURE__ */ jsx4("div", { style: { gridColumn: `span ${item.span}` }, children: /* @__PURE__ */ jsx4(
943
+ ReadyField,
944
+ {
945
+ field,
946
+ formId,
947
+ viewId,
948
+ parentValues
949
+ }
950
+ ) }, field.key);
951
+ }) });
934
952
  return /* @__PURE__ */ jsxs4("div", { className: "builder-form-fields", children: [
935
- schema.layout?.groups.map((group) => /* @__PURE__ */ jsxs4("fieldset", { className: "builder-fieldset", children: [
953
+ schema.layout?.presentation === "tabs" && groups.length > 0 ? /* @__PURE__ */ jsxs4("div", { className: "builder-form-tabs", children: [
954
+ /* @__PURE__ */ jsx4("div", { "aria-label": "Form sections", className: "builder-form-tabs__list", role: "tablist", children: groups.map((group, index) => {
955
+ const isActive = group.id === activeGroupId;
956
+ return /* @__PURE__ */ jsx4(
957
+ "button",
958
+ {
959
+ "aria-controls": `${tabsId}-panel-${group.id}`,
960
+ "aria-selected": isActive,
961
+ className: "builder-form-tabs__trigger",
962
+ id: `${tabsId}-tab-${group.id}`,
963
+ onClick: () => setSelectedGroupId(group.id),
964
+ role: "tab",
965
+ type: "button",
966
+ children: group.title ?? `Group ${index + 1}`
967
+ },
968
+ group.id
969
+ );
970
+ }) }),
971
+ groups.map((group) => /* @__PURE__ */ jsx4(
972
+ "div",
973
+ {
974
+ "aria-labelledby": `${tabsId}-tab-${group.id}`,
975
+ hidden: group.id !== activeGroupId,
976
+ id: `${tabsId}-panel-${group.id}`,
977
+ role: "tabpanel",
978
+ children: renderGroupFields(group)
979
+ },
980
+ group.id
981
+ ))
982
+ ] }) : groups.map((group) => /* @__PURE__ */ jsxs4("fieldset", { className: "builder-fieldset", children: [
936
983
  group.title ? /* @__PURE__ */ jsx4("legend", { children: group.title }) : null,
937
- /* @__PURE__ */ jsx4("div", { className: "builder-form-grid", children: group.fields.map((item) => {
938
- const field = fields.get(item.key);
939
- if (!field) return null;
940
- rendered.add(field.key);
941
- return /* @__PURE__ */ jsx4("div", { style: { gridColumn: `span ${item.span}` }, children: /* @__PURE__ */ jsx4(ReadyField, { field, formId, viewId, parentValues }) }, field.key);
942
- }) })
984
+ renderGroupFields(group)
943
985
  ] }, group.id)),
944
986
  /* @__PURE__ */ jsx4("div", { className: "builder-form-grid", children: schema.fields.filter((field) => !rendered.has(field.key)).map((field) => /* @__PURE__ */ jsx4("div", { style: { gridColumn: "span 12" }, children: /* @__PURE__ */ jsx4(ReadyField, { field, formId, viewId, parentValues }) }, field.key)) }),
945
987
  extraItems.map((item) => /* @__PURE__ */ jsx4("div", { children: item.render() }, item.key))
@@ -947,7 +989,7 @@ function ReadyFields({
947
989
  }
948
990
 
949
991
  // src/ready/ReadyOverlay.tsx
950
- import { useEffect as useEffect2, useId as useId2, useRef as useRef5, useState as useState3 } from "react";
992
+ import { useEffect as useEffect2, useId as useId3, useRef as useRef5, useState as useState4 } from "react";
951
993
  import { createPortal } from "react-dom";
952
994
  import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
953
995
  function ReadyOverlay({
@@ -960,9 +1002,9 @@ function ReadyOverlay({
960
1002
  }) {
961
1003
  const panelRef = useRef5(null);
962
1004
  const onCloseRef = useRef5(onClose);
963
- const [portalRoot, setPortalRoot] = useState3(null);
1005
+ const [portalRoot, setPortalRoot] = useState4(null);
964
1006
  onCloseRef.current = onClose;
965
- const titleId = useId2();
1007
+ const titleId = useId3();
966
1008
  useEffect2(() => {
967
1009
  setPortalRoot(document.body);
968
1010
  }, []);
@@ -1046,16 +1088,16 @@ function ReadyErrorState({ title, description }) {
1046
1088
  }
1047
1089
 
1048
1090
  // src/ready/ReadySubform.tsx
1049
- import { useEffect as useEffect3, useMemo as useMemo3, useRef as useRef6, useState as useState5 } from "react";
1091
+ import { useEffect as useEffect3, useMemo as useMemo3, useRef as useRef6, useState as useState6 } from "react";
1050
1092
  import { FormProvider, useForm, useFormContext as useFormContext4, useWatch as useWatch4 } from "react-hook-form";
1051
1093
 
1052
1094
  // src/ready/ReadyTable.tsx
1053
- import { useMemo as useMemo2, useState as useState4 } from "react";
1095
+ import { useMemo as useMemo2, useState as useState5 } from "react";
1054
1096
  import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
1055
1097
  function useReadyTableState({ pageSize = 20 } = {}) {
1056
- const [page, setPage] = useState4(1);
1057
- const [search, setSearchValue] = useState4("");
1058
- const [sort, setSort] = useState4();
1098
+ const [page, setPage] = useState5(1);
1099
+ const [search, setSearchValue] = useState5("");
1100
+ const [sort, setSort] = useState5();
1059
1101
  return {
1060
1102
  query: { page, pageSize, search: search || void 0, sort },
1061
1103
  page,
@@ -1074,7 +1116,7 @@ function useReadyTableState({ pageSize = 20 } = {}) {
1074
1116
  };
1075
1117
  }
1076
1118
  function useReadyTable(args) {
1077
- const [selectedIds, setSelectedIds] = useState4([]);
1119
+ const [selectedIds, setSelectedIds] = useState5([]);
1078
1120
  return useMemo2(
1079
1121
  () => ({
1080
1122
  ...args,
@@ -1210,8 +1252,8 @@ function ReadySubform({ subform, parentEntry, rows, onRowsChange }) {
1210
1252
  const parentForm = useFormContext4();
1211
1253
  const watchedParentValues = useWatch4({ control: parentForm.control, name: "values" });
1212
1254
  const parentValues = watchedParentValues && typeof watchedParentValues === "object" && !Array.isArray(watchedParentValues) ? watchedParentValues : void 0;
1213
- const [open, setOpen] = useState5(false);
1214
- const [editing, setEditing] = useState5(null);
1255
+ const [open, setOpen] = useState6(false);
1256
+ const [editing, setEditing] = useState6(null);
1215
1257
  const initialized = useRef6(false);
1216
1258
  const parentValue = linkedValue(parentEntry, subform.parentField);
1217
1259
  const viewQuery = hooks.useRuntimeBuilderView(subform.viewId, Boolean(subform.viewId));
@@ -1380,7 +1422,7 @@ function changedSubformPayloads(rows, includeIdentity) {
1380
1422
  }
1381
1423
  function BuilderEntryEditor({ view, editing, open, onClose }) {
1382
1424
  const { hooks, notify } = useBuilderRuntime();
1383
- const [subforms, setSubforms] = useState6({});
1425
+ const [subforms, setSubforms] = useState7({});
1384
1426
  const isSubmittingRef = useRef7(false);
1385
1427
  const save = hooks.useSaveBuilderViewEntry(view.id);
1386
1428
  const createComposite = hooks.useCreateCompositeBuilderViewEntry(view.id);
@@ -1428,9 +1470,9 @@ function BuilderEntryEditor({ view, editing, open, onClose }) {
1428
1470
  }
1429
1471
  function DefaultBuilderView({ viewId }) {
1430
1472
  const { hooks, notify } = useBuilderRuntime();
1431
- const [editing, setEditing] = useState6(null);
1432
- const [editorOpen, setEditorOpen] = useState6(false);
1433
- const [pendingDelete, setPendingDelete] = useState6(null);
1473
+ const [editing, setEditing] = useState7(null);
1474
+ const [editorOpen, setEditorOpen] = useState7(false);
1475
+ const [pendingDelete, setPendingDelete] = useState7(null);
1434
1476
  const viewQuery = hooks.useRuntimeBuilderView(viewId);
1435
1477
  const state = useReadyTableState();
1436
1478
  const entriesQuery = hooks.useBuilderViewEntries(viewId, state.query);
@@ -1698,6 +1740,7 @@ function builderFormEditorValuesFromEntity(form, emptyValues) {
1698
1740
  sourceTable: source?.type === "dbTable" ? source.tableName : BUILDER_EDITOR_NONE_VALUE,
1699
1741
  apiBasePath: source?.type === "apiEndpoint" ? source.basePath : "",
1700
1742
  fields,
1743
+ layoutPresentation: form.schema.layout?.presentation ?? "stacked",
1701
1744
  layoutGroups: normalizeBuilderFormEditorLayoutGroups(
1702
1745
  form.schema.layout?.groups,
1703
1746
  fields,
@@ -1817,6 +1860,7 @@ function builderFormEditorInputFromValues(values) {
1817
1860
  }))
1818
1861
  })),
1819
1862
  layout: {
1863
+ presentation: values.layoutPresentation,
1820
1864
  groups: normalizeBuilderFormEditorLayoutGroups(
1821
1865
  values.layoutGroups,
1822
1866
  values.fields,
@@ -2210,6 +2254,13 @@ function createBuilderDefaultFormEditorBody(options) {
2210
2254
  }
2211
2255
  )
2212
2256
  ] }),
2257
+ /* @__PURE__ */ jsx10("div", { style: styles.grid, children: /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2258
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Group presentation" }),
2259
+ /* @__PURE__ */ jsxs9("select", { style: styles.input, ...form.register("layoutPresentation"), children: [
2260
+ /* @__PURE__ */ jsx10("option", { value: "stacked", children: "Stacked sections" }),
2261
+ /* @__PURE__ */ jsx10("option", { value: "tabs", children: "Tabs" })
2262
+ ] })
2263
+ ] }) }),
2213
2264
  form.watch("layoutGroups").map((group, groupIndex) => /* @__PURE__ */ jsxs9("div", { style: styles.row, children: [
2214
2265
  /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2215
2266
  /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Group title" }),
@@ -2596,7 +2647,7 @@ function createBuilderDefaultListEditorBody(options) {
2596
2647
  }
2597
2648
 
2598
2649
  // src/admin/BuilderDefaultEntityManager.tsx
2599
- import { useMemo as useMemo5, useState as useState7 } from "react";
2650
+ import { useMemo as useMemo5, useState as useState8 } from "react";
2600
2651
  import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
2601
2652
  var styles2 = {
2602
2653
  page: {
@@ -2693,7 +2744,7 @@ var styles2 = {
2693
2744
  };
2694
2745
  function createBuilderDefaultEntityManagerComponent(deps) {
2695
2746
  return function BuilderDefaultEntityManager() {
2696
- const [state, setState] = useState7({
2747
+ const [state, setState] = useState8({
2697
2748
  page: 1,
2698
2749
  pageSize: 20,
2699
2750
  search: ""
@@ -3267,6 +3318,7 @@ function createBuilderAdminPages({
3267
3318
  sourceTable: BUILDER_EDITOR_NONE_VALUE,
3268
3319
  apiBasePath: "",
3269
3320
  fields: [emptyField],
3321
+ layoutPresentation: "stacked",
3270
3322
  layoutGroups: builderFormEditorDefaultLayoutGroups([emptyField]),
3271
3323
  subforms: [],
3272
3324
  triggers: [],
@@ -3525,11 +3577,11 @@ function createBuilderAdminPages({
3525
3577
  }
3526
3578
 
3527
3579
  // src/admin/BuilderEntityManager.tsx
3528
- import { useCallback as useCallback2, useMemo as useMemo6, useState as useState8 } from "react";
3580
+ import { useCallback as useCallback2, useMemo as useMemo6, useState as useState9 } from "react";
3529
3581
  import { jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
3530
3582
  function createBuilderEntityManagerComponent(deps) {
3531
3583
  return function BuilderEntityManager() {
3532
- const [pendingDelete, setPendingDelete] = useState8(null);
3584
+ const [pendingDelete, setPendingDelete] = useState9(null);
3533
3585
  const state = deps.useDataTableState({ pageSize: 20 });
3534
3586
  const query = deps.hooks.useEntities(state.query);
3535
3587
  const remove = deps.hooks.useDelete();
@@ -3589,9 +3641,9 @@ function createBuilderEntityManagerComponent(deps) {
3589
3641
  }
3590
3642
  function createBuilderEntityDialogManagerComponent(deps) {
3591
3643
  return function BuilderEntityDialogManager() {
3592
- const [editing, setEditing] = useState8(null);
3593
- const [isEditorOpen, setEditorOpen] = useState8(false);
3594
- const [pendingDelete, setPendingDelete] = useState8(null);
3644
+ const [editing, setEditing] = useState9(null);
3645
+ const [isEditorOpen, setEditorOpen] = useState9(false);
3646
+ const [pendingDelete, setPendingDelete] = useState9(null);
3595
3647
  const state = deps.useDataTableState({ pageSize: 20 });
3596
3648
  const query = deps.hooks.useEntities(state.query);
3597
3649
  const remove = deps.hooks.useDelete();
@@ -3961,7 +4013,7 @@ function createDynamicListComponent(deps) {
3961
4013
  }
3962
4014
 
3963
4015
  // src/components/DynamicView.tsx
3964
- import { useMemo as useMemo10, useState as useState9 } from "react";
4016
+ import { useMemo as useMemo10, useState as useState10 } from "react";
3965
4017
  import { jsx as jsx19, jsxs as jsxs15 } from "react/jsx-runtime";
3966
4018
  var interactiveRowTargetSelector = "button,a,input,select,textarea,[role='button'],[role='menuitem'],[data-builder-row-action]";
3967
4019
  function hasClosest(target) {
@@ -3974,9 +4026,9 @@ function shouldHandleDynamicViewRowClick(event) {
3974
4026
  }
3975
4027
  function createDynamicViewComponent(deps) {
3976
4028
  return function DynamicView({ viewId }) {
3977
- const [editing, setEditing] = useState9(null);
3978
- const [isDialogOpen, setDialogOpen] = useState9(false);
3979
- const [pendingDelete, setPendingDelete] = useState9(null);
4029
+ const [editing, setEditing] = useState10(null);
4030
+ const [isDialogOpen, setDialogOpen] = useState10(false);
4031
+ const [pendingDelete, setPendingDelete] = useState10(null);
3980
4032
  const viewQuery = deps.hooks.useRuntimeBuilderView(viewId);
3981
4033
  const state = deps.useDataTableState({ pageSize: 20 });
3982
4034
  const entriesQuery = deps.hooks.useBuilderViewEntries(viewId, state.query);
@@ -4070,7 +4122,7 @@ function createDynamicViewComponent(deps) {
4070
4122
  }
4071
4123
 
4072
4124
  // src/components/RuntimeEntryDialog.tsx
4073
- import { useEffect as useEffect7, useMemo as useMemo11, useRef as useRef8, useState as useState10 } from "react";
4125
+ import { useEffect as useEffect7, useMemo as useMemo11, useRef as useRef8, useState as useState11 } from "react";
4074
4126
  import { FormProvider as FormProvider6, useForm as useForm7 } from "react-hook-form";
4075
4127
  import { jsx as jsx20, jsxs as jsxs16 } from "react/jsx-runtime";
4076
4128
  function isDbTableSource(source) {
@@ -4111,7 +4163,7 @@ function createRuntimeEntryDialogComponent(deps) {
4111
4163
  onSave,
4112
4164
  isSaving
4113
4165
  }) {
4114
- const [draftSubforms, setDraftSubforms] = useState10({});
4166
+ const [draftSubforms, setDraftSubforms] = useState11({});
4115
4167
  const isSubmittingRef = useRef8(false);
4116
4168
  const compositeCreate = deps.useCreateCompositeEntry?.(view.id);
4117
4169
  const compositeUpdate = deps.useUpdateCompositeEntry?.(view.id);
@@ -4302,7 +4354,7 @@ function validateBuilderFrontendSetup(config) {
4302
4354
  // src/index.ts
4303
4355
  var builderUiPackage = {
4304
4356
  name: "@duke333/builder-ui",
4305
- version: "0.2.4"
4357
+ version: "0.2.5"
4306
4358
  };
4307
4359
  export {
4308
4360
  BUILDER_EDITOR_NONE_VALUE,