blixify-ui-web-mcp 0.1.19 → 0.1.20

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.
Files changed (37) hide show
  1. package/lib/components/action/iconButton/iconButton.stories.tsx +11 -2
  2. package/lib/components/chart/statsCard/README.md +24 -0
  3. package/lib/components/chart/statsCard/statsCard.stories.tsx +68 -0
  4. package/lib/components/chat/chatBase/chatBase.stories.tsx +1 -1
  5. package/lib/components/data/dataGraph/dataGraph.stories.tsx +5 -5
  6. package/lib/components/data/dataTemplate/README.md +112 -82
  7. package/lib/components/data/dataTemplate/dataTemplate.stories.tsx +307 -295
  8. package/lib/components/data/dataWrapper/README.md +109 -22
  9. package/lib/components/data/dataWrapper/dataWrapper.bareHooks.stories.tsx +951 -0
  10. package/lib/components/data/dataWrapper/dataWrapper.edit.stories.tsx +156 -5
  11. package/lib/components/data/dataWrapper/dataWrapper.view.stories.tsx +79 -5
  12. package/lib/components/display/calendar/calendar.stories.tsx +1 -1
  13. package/lib/components/display/detailList/README.md +11 -10
  14. package/lib/components/display/detailList/detailList.stories.tsx +16 -3
  15. package/lib/components/display/feeds/README.md +3 -3
  16. package/lib/components/display/feeds/feeds.stories.tsx +3 -3
  17. package/lib/components/display/filePreview/filePreview.stories.tsx +111 -0
  18. package/lib/components/display/modal/README.md +3 -0
  19. package/lib/components/display/modal/modal.stories.tsx +50 -1
  20. package/lib/components/display/newCalendar/newCalendar.stories.tsx +1 -1
  21. package/lib/components/display/newFeeds/newFeeds.stories.tsx +3 -3
  22. package/lib/components/display/newTable/newTable.stories.tsx +34 -9
  23. package/lib/components/input/markdown/markdown.stories.tsx +3 -1
  24. package/lib/components/navigation/leftNav/leftNav.stories.tsx +175 -0
  25. package/lib/components/navigation/tabs/tabs.stories.tsx +23 -0
  26. package/lib/components/template/calendarView/calendarView.stories.tsx +4 -4
  27. package/lib/components/template/chatDashboard/chatDashboard.stories.tsx +2 -2
  28. package/lib/mcp/tools/getBackendComponent.d.ts.map +1 -1
  29. package/lib/mcp/tools/getBackendComponent.js +7 -3
  30. package/lib/mcp/tools/getBackendComponent.js.map +1 -1
  31. package/lib/mcp/tools/suggestTemplate.js +3 -3
  32. package/lib/mcp/tools/suggestTemplate.js.map +1 -1
  33. package/package.json +1 -1
  34. package/lib/components/data/dataTemplate/dataModule.stories.tsx +0 -191
  35. package/lib/components/data/dataWrapper/dataWrapper.consumer.stories.tsx +0 -2125
  36. package/lib/components/data/dataWrapper/dataWrapper.utils.stories.tsx +0 -576
  37. package/lib/components/data/flexFilter/flexFilter.stories.tsx +0 -171
@@ -5,7 +5,6 @@ import { IconButton as IconButtonImpl } from ".";
5
5
  const meta = { title: "Action/Icon Button" };
6
6
  export default meta;
7
7
 
8
-
9
8
  export const IconButton = () => {
10
9
  return (
11
10
  <IconButtonImpl
@@ -13,4 +12,14 @@ export const IconButton = () => {
13
12
  onClick={() => {}}
14
13
  />
15
14
  );
16
- }
15
+ };
16
+
17
+ export const SquareIconButton = () => {
18
+ return (
19
+ <IconButtonImpl
20
+ icon={<Bars3Icon className="h-5 w-5" />}
21
+ className="h-10 w-10"
22
+ onClick={() => {}}
23
+ />
24
+ );
25
+ };
@@ -43,6 +43,12 @@ With date range picker:
43
43
  />
44
44
  ```
45
45
 
46
+ Compact (mobile KPI grid):
47
+
48
+ ```jsx
49
+ <StatsCard stats={stats} size="compact" gridSize={3} />
50
+ ```
51
+
46
52
  Dark mode:
47
53
 
48
54
  ```jsx
@@ -66,6 +72,7 @@ Dark mode:
66
72
  | ------------------ | --------------------------------------- | --------------- | --------------------------------------------------------------------------------------------------------------------------- |
67
73
  | `gridSize` | `1 \| 2 \| 3` | — | Max columns in the grid. `1` = 1-col, `2` = 2-col, `3` = 2-col md / 3-col lg. When omitted, defaults to 2-col md / 4-col lg |
68
74
  | `minGridSize` | `2` | — | Forces a 2-column minimum on small screens. Only `2` is supported |
75
+ | `size` | `"default" \| "compact"` | `"default"` | `compact` renders a stat-first card — small muted label, stat as the hero, icon and action tucked right. Starts 2-up on mobile and drops the `divide-*` rules, since each compact card carries its own border. Roughly halves the grid on mobile; see Choosing a size |
69
76
  | `icon` | `ReactElement` | — | Small icon rendered in the top-right corner of the card group |
70
77
  | `darkMode` | `boolean` | `false` | Switches cards to a dark theme |
71
78
  | `darkModeBg` | `string` | `"bg-gray-900"` | Tailwind classes for the dark mode card background |
@@ -86,6 +93,23 @@ Dark mode:
86
93
  | `actionIcon` | `ReactElement` | no | Icon rendered in the top-right of the individual card |
87
94
  | `onActionIconClick` | `() => void` | no | Click handler for `actionIcon` |
88
95
 
96
+ ##### Choosing a size
97
+
98
+ | | `default` | `compact` |
99
+ | --- | --- | --- |
100
+ | Padding | `p-5` | `p-3` |
101
+ | Label | `text-base`, primary text colour | `text-xs`, muted |
102
+ | Stat | `text-2xl` | `text-lg` |
103
+ | Mobile grid | 1-up (2-up with `minGridSize={2}`) | 2-up |
104
+ | Seams | `divide-y` / `md:divide-x` | per-card border |
105
+ | Icon | rendered inline at the caller's own size | pinned to `h-4 w-4`, chipped right |
106
+
107
+ `gridSize` still applies at `md` and above in both sizes, so a 4-up desktop dashboard collapses to a readable 2-up on mobile. An explicit `gridSize={1}` stays one column at every breakpoint.
108
+
109
+ The saving is in the grid, not the card. Measured at 390px with four stats, the grid drops from 495px to 247px — because compact is 2-up, not because the card shrank. At equal card width the compact card is only marginally shorter (118px vs 125px), and at mobile width it is slightly taller, since compact stacks label, stat, previous and badge vertically while default puts the stat and badge on one baseline row.
110
+
111
+ > Not to be confused with `bareCompactMode` — that is a `DataTemplate` `bareSettings` flag that switches `DetailList` to its compact row layout in the read view. Same word, unrelated component.
112
+
89
113
  ##### RangeInterface
90
114
 
91
115
  | Name | Type | Description |
@@ -97,6 +97,74 @@ export const StatsCard = () => {
97
97
 
98
98
  return (
99
99
  <>
100
+ <StorySection
101
+ title="size=&quot;compact&quot; — 2-Up KPI Grid"
102
+ description="Stat-first compact layout. Label small and muted, stat is the hero, icon and action tucked right. Starts 2-up on mobile instead of the default 1-up — which roughly halves the grid height there — and drops the divide rules since each card carries its own border."
103
+ >
104
+ <div className="w-full">
105
+ <StatsCardImpl stats={baseStats} size="compact" />
106
+ </div>
107
+ </StorySection>
108
+
109
+ <StorySection
110
+ title="size=&quot;compact&quot; — 4-Up Dashboard Glance"
111
+ description="Compact honours gridSize at md and above, so a 4-up desktop dashboard collapses to a readable 2-up on mobile. Resize the frame to see the grid step down."
112
+ >
113
+ <div className="w-full">
114
+ <StatsCardImpl
115
+ stats={[
116
+ ...baseStats,
117
+ {
118
+ name: "Active Users",
119
+ stats: "3,240",
120
+ previousStats: "3,100",
121
+ change: "4.5%",
122
+ changeType: "increase",
123
+ icon: <UserGroupIcon className="w-6 h-6 text-gray-600" />,
124
+ },
125
+ ]}
126
+ size="compact"
127
+ />
128
+ </div>
129
+ </StorySection>
130
+
131
+ <StorySection
132
+ title="size=&quot;compact&quot; — gridSize=1"
133
+ description="An explicit gridSize of 1 stays a single column at every breakpoint. Compact's 2-up mobile default used to override it, which put MORE columns on the narrow screen than the wide one — resize the frame and this should never split into two."
134
+ >
135
+ <div className="w-full">
136
+ <StatsCardImpl stats={baseStats} size="compact" gridSize={1} />
137
+ </div>
138
+ </StorySection>
139
+
140
+ <StorySection
141
+ title="size=&quot;compact&quot; — With DateRange Picker"
142
+ description="dateRangeVisible renders below the compact grid exactly as it does for the default size."
143
+ >
144
+ <div className="w-full">
145
+ <StatsCardImpl
146
+ stats={seriesData}
147
+ size="compact"
148
+ dateRangeVisible={true}
149
+ onChangeDate={handleSetData}
150
+ />
151
+ </div>
152
+ </StorySection>
153
+
154
+ <StorySection
155
+ title="size=&quot;compact&quot; — Dark Mode"
156
+ description="Compact cards swap to a gray-900 surface with a gray-700 border and a gray-800 icon chip."
157
+ dark
158
+ >
159
+ <div className="w-full">
160
+ <StatsCardImpl
161
+ stats={baseStats}
162
+ size="compact"
163
+ darkMode={true}
164
+ />
165
+ </div>
166
+ </StorySection>
167
+
100
168
  <StorySection
101
169
  title="Default (4-column grid)"
102
170
  description="When gridSize is omitted the component defaults to a 4-column grid on large screens. Each card shows a name, stat value, optional previous stat, and an optional change badge."
@@ -237,7 +237,7 @@ export const ChatBase = () => {
237
237
  sender: botUser,
238
238
  messageBody: {
239
239
  fileName:
240
- "https://firebasestorage.googleapis.com/v0/b/verdant-solar-dev.appspot.com/o/preCheckList%2F0184b7ee-8bb0-4a48-992c-ac8d37f8e833%2FPre-Checklist.pdf?alt=media&token=1de8eafb-27c4-4ff7-91a3-e640e4ef07cf",
240
+ "https://firebasestorage.googleapis.com/v0/b/demo-bucket.appspot.com/o/files%2FPre-Checklist.pdf?alt=media",
241
241
  token: "sample-document.pdf",
242
242
  type: "application/pdf",
243
243
  } as any,
@@ -26,7 +26,7 @@ export const DataGraph = () => {
26
26
  type: "card",
27
27
  title: "Total Products",
28
28
  description: "All products in catalogue",
29
- spaceId: "esh-products",
29
+ spaceId: "products",
30
30
  query: [],
31
31
  queryBaseType: "count",
32
32
  },
@@ -35,7 +35,7 @@ export const DataGraph = () => {
35
35
  type: "card",
36
36
  title: "Total Revenue",
37
37
  description: "Sum of all order prices",
38
- spaceId: "esh-products",
38
+ spaceId: "products",
39
39
  query: [],
40
40
  queryBaseType: "sum",
41
41
  queryAttributeId: ["price"],
@@ -60,7 +60,7 @@ export const DataGraph = () => {
60
60
  type: "card",
61
61
  title: "All Products",
62
62
  description: "Total product count",
63
- spaceId: "esh-products",
63
+ spaceId: "products",
64
64
  query: [],
65
65
  queryBaseType: "count",
66
66
  },
@@ -69,7 +69,7 @@ export const DataGraph = () => {
69
69
  type: "card",
70
70
  title: "Total Price",
71
71
  description: "Sum of all prices",
72
- spaceId: "esh-products",
72
+ spaceId: "products",
73
73
  query: [],
74
74
  queryBaseType: "sum",
75
75
  queryAttributeId: ["price"],
@@ -78,7 +78,7 @@ export const DataGraph = () => {
78
78
  gridSize: 2,
79
79
  type: "bar",
80
80
  title: "Price per Code",
81
- spaceId: "esh-products",
81
+ spaceId: "products",
82
82
  query: [
83
83
  { type: "=", queryId: "code", value: "P001" },
84
84
  { type: "=", queryId: "code", value: "N001" },
@@ -106,10 +106,10 @@ Tab (DataStructure.tabId) ← tab bar across the top of the read
106
106
  untouched tab costs no request. Without it every save writes the full record and toasts,
107
107
  changed or not.
108
108
  The API behind the collection must accept a partial document (an upsert by id that
109
- `$set`s only the sent fields) — Verdant's `mongoData` route does; check before turning it
109
+ `$set`s only the sent fields) — a `mongoData`-style upsert route does; check before turning it
110
110
  on elsewhere.
111
111
 
112
- **Offline mode** (`bareOffline`, the Meraque work-order checklist pattern)
112
+ **Offline mode** (`bareOffline`, the offline work-order checklist pattern)
113
113
 
114
114
  ```
115
115
  mount (online) ─▶ prefetch latest N docs + bareOfflineReferences ─▶ IndexedDB store "local"
@@ -121,14 +121,15 @@ ref.handleUploadOfflineData() ─▶ every pending doc → server (diffed agains
121
121
  ```
122
122
 
123
123
  - The DTW does the prefetch, the local reads, the local writes and the upload; the app owns the
124
- _policy_: when to go offline, when to sync, what to tell the user. Meraque keeps an `offline`
124
+ _policy_: when to go offline, when to sync, what to tell the user. A typical app keeps an `offline`
125
125
  state, shows a banner ("Going offline? Sync data required…" / "You're in offline mode." /
126
126
  "Data synced. Ready for offline."), passes `bareOffline: offline`, and calls
127
127
  `dtwRef.current.handleUploadOfflineData()` when the connection is back.
128
128
  - Prefetch never overwrites pending local edits — pending docs win over the server copy of the
129
129
  same id. Reference collections listed in `bareOfflineReferences` are what make reference
130
130
  fields (team, pilot, robot…) selectable with no network.
131
- - Story: `Data / Data Wrapper / Consumer Fixtures / Meraque · Work Order (Offline)` — prefetch,
131
+ - Story: the offline work-order fixture under `Data / Data Wrapper / Consumer Fixtures`, in the local
132
+ Storybook only (client fixtures are not shipped in the MCP package) — prefetch,
132
133
  an offline toggle, an offline save and Sync now, all mocked in the page.
133
134
  - This is a feature, not a test harness — stories fake the server with `axios-mock-adapter`
134
135
  instead (see the Consumer Fixtures file).
@@ -139,7 +140,7 @@ just its label — text, textarea, select and its dropdown, date, checkbox and r
139
140
  the read view's cards, modals, the drawer, toasts and the floating action bar. Pass
140
141
  `organise.darkModeBg` with the class your page already uses (`"bg-neutral-900"`) and those
141
142
  surfaces adopt it; without it they fall back to `bg-gray-900`. Story: `Consumer Fixtures /
142
- Dark Mode` (Sales Leads list + KPJ form on a Meraque-style page).
143
+ Dark Mode` (a sales-leads list and a long grant form on a black page).
143
144
 
144
145
  **Wide tables** — every table scrolls inside a `ScrollShadow`: a soft fade on the edge
145
146
  that still hides columns, gone at the end of the scroll, over a thin always-visible
@@ -175,9 +176,9 @@ update form only, the light `bg-primary-50` tint behind a collapsible section. R
175
176
  section cards are plain white. Per-value colour exists only on `list` / `multipleList`
176
177
  columns via `listSelectionColour`.
177
178
 
178
- A worked example is Blixify Space's KPJ **Projects** space: every column carries a lettered
179
- `tabId` (`A. Research Identification` … `P. Applicant Endorsement`) plus a `groupId`
180
- (`Research Details`, `Application Details`, …), and its `kpjuResearchers` listObject shows
179
+ A worked example is a long grant-application space: every column carries a lettered
180
+ `tabId` (`A. Overview` … `P. Endorsement`) plus a `groupId`
181
+ (`Details`, `Application`, …), and a `researchers` listObject shows
181
182
  as a nested table inside the _Applicants' Details_ section.
182
183
 
183
184
  ## View Settings
@@ -766,17 +767,19 @@ const devSettings = parseWorkspaceSettings(
766
767
 
767
768
  ### Ref Methods
768
769
 
769
- | Method | Description |
770
- | ---------------------------------- | ----------------------------------------------------------------- |
771
- | `handleRefresh()` | Re-fetches the current list data, resetting pagination to page 1 |
772
- | `handleRefreshCurrentPage()` | Re-fetches in place, keeping page index, cursor, and filters |
773
- | `handleFormSubmit()` | Programmatically submits the update/create form |
774
- | `handleFormCheck()` | Validates the form without submitting |
775
- | `handlePopUpModal()` | Opens the create/update modal |
776
- | `handleDeleteModal()` | Opens the delete confirmation modal |
777
- | `handleUpdateSelectedData(fields)` | Prefills form fields. `fields` is `{ key: string; value: any }[]` |
778
- | `handleExportReadPDF()` | Triggers a PDF export of the current read view |
779
- | `handleUploadOfflineData()` | Uploads any locally cached offline data |
770
+ | Method | Description |
771
+ | ------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
772
+ | `handleRefresh()` | Re-fetches the current list data, resetting pagination to page 1 |
773
+ | `handleRefreshCurrentPage()` | Re-fetches in place, keeping page index, cursor, and filters |
774
+ | `handleFormSubmit()` | Programmatically submits the update/create form |
775
+ | `handleFormCheck()` | Validates the form without submitting |
776
+ | `handlePopUpModal()` | Opens the create/update modal |
777
+ | `handleDeleteModal()` | Opens the delete confirmation modal |
778
+ | `handleUpdateSelectedData(fields)` | Prefills form fields. `fields` is `{ key: string; value: any }[]` |
779
+ | `handleExportReadPDF()` | Triggers a PDF export of the current read view |
780
+ | `handleUploadOfflineData()` | Uploads any locally cached offline data |
781
+ | `handleApplyFlexFilters(filters)` | Applies flex filters, merged by `columnId` (incoming replaces same-column rows; others preserved). `filters` is `FlexFilterData[]`. Requires `bareFlexFilters` |
782
+ | `handleClearFlexFilters(columnIds?)` | Clears flex filters by `columnId` (others preserved), or all when called with no args. Requires `bareFlexFilters` |
780
783
 
781
784
  ### Required props
782
785
 
@@ -855,17 +858,43 @@ const devSettings = parseWorkspaceSettings(
855
858
 
856
859
  | Name | Type | Description |
857
860
  | ----------------------- | ------------- | -------------------------------------------------------- |
858
- | `allEditable` | `boolean` | Enables add, update, and delete |
861
+ | `allEditable` | `boolean` | Enables add and update, and gates inline/drag writes |
859
862
  | `listAddable` | `boolean` | Enables adding rows inline in list view |
860
863
  | `listEditable` | `boolean` | Enables inline cell editing in list view |
861
864
  | `createBtn` | `boolean` | Shows a create button even when `allEditable` is `false` |
862
- | `deleteBtn` | `boolean` | Enables delete and batch delete |
865
+ | `deleteBtn` | `boolean` | Enables delete and batch delete, independent of `allEditable` |
863
866
  | `disabledUpdate` | `boolean` | Disables update and batch update |
864
867
  | `disableBatchUpdate` | `boolean` | Disables batch update only |
865
868
  | `enableUpdateDraft` | `boolean` | Enables save-as-draft on the update form |
866
869
  | `disabledTabsDeleteBtn` | `boolean` | Disables the delete button inside extended tabs |
867
870
  | `activityLog` | `ActivityLog` | See ActivityLog below |
868
871
 
872
+ #### Write permission matrix
873
+
874
+ Reader-reachable controls are gated by these rules. A control that is off is not
875
+ rendered, and its underlying write is refused even if the callback is reached.
876
+
877
+ | Control | Requires |
878
+ | -------------------------------------------------- | --------------------------------------- |
879
+ | Kanban drag/drop and its update write | `allEditable && !disabledUpdate` |
880
+ | Inline cell edit, Kanban boolean checkbox | `listEditable && !disabledUpdate` |
881
+ | Read-view Update button, list Update column | `allEditable && !disabledUpdate` |
882
+ | Batch update, clone, change-to-draft | `allEditable && !disabledUpdate && !disableBatchUpdate` |
883
+ | Delete button, batch delete, map delete | `deleteBtn` (independent of `allEditable`) |
884
+ | Map polygon select | batch-update or delete permission |
885
+
886
+ > `deleteBtn` no longer requires `allEditable`. An `edit` of
887
+ > `{ allEditable: false, deleteBtn: true }` renders Delete in the read and update
888
+ > action bars, where it was previously hidden. Grant `deleteBtn` per role rather
889
+ > than unconditionally.
890
+
891
+ The imperative API is **not** gated by these rules. `handleFormSubmit`,
892
+ `handleFormSaveDraft`, `handleDeleteModal` and `handleUploadOfflineData` are only
893
+ reachable from consumer code, and `DataTemplateWrapper` defaults `edit` to
894
+ `disabledUpdate: true, deleteBtn: false` — gating them would break every consumer
895
+ that drives its own form without passing an `edit` prop. A consumer that does not
896
+ want a write path should not render it.
897
+
869
898
  #### Inline editability matrix (`listEditable`)
870
899
 
871
900
  Which field types can be edited from the list table, and how. Types not listed under
@@ -1015,62 +1044,63 @@ Which field types can be edited from the list table, and how. Types not listed u
1015
1044
 
1016
1045
  Injects custom React components and callbacks into the list, read, and update views.
1017
1046
 
1018
- | Name | Type | Description |
1019
- | ---------------------------------------- | ------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1020
- | `bareViewSettings` | `boolean` | Turns on the view settings feature — the panel (columns hide / reorder / search, sort, rows per page) and the hide, drag and sort controls in the table header. Always on under `bareNewDTW` |
1021
- | `bareReadComponent` | `(data: any) => any` | Custom component rendered in read view |
1022
- | `bareReadComponentPos` | `"top"` | Renders `bareReadComponent` above the default read content |
1023
- | `bareReadComponentHide` | `boolean` | Hides the default read content (shows only `bareReadComponent`) |
1024
- | `bareReadReferenceView` | `(dataId, collectionId, attributeId) => boolean \| void` | Controls whether a reference field opens a view |
1025
- | `bareReadDescription` | `(key: string, value: any) => any` | Custom renderer for read view field values |
1026
- | `bareReadHandleData` | `(data: any) => void` | Called when read view data is loaded |
1027
- | `bareReadListTabs` | `boolean` | Shows list-style tabs in read view |
1028
- | `bareListComponent` | `(data, prettierData, loading, pageIndex) => any` | Fully replaces the list UI with a custom component |
1029
- | `bareListActionBtns` | `(data: any) => ReactElement[]` | Extra icon buttons rendered on each list row |
1030
- | `bareListMultipleSelectAddtionalActions` | `{ text: string; className?: string; onClick: (ids, selectAll, query) => void }[]` | Extra bulk-action buttons shown when rows are selected |
1031
- | `bareListGridComponent` | `(data: any) => any` | Custom card renderer for grid view |
1032
- | `bareListGridColClassName` | `string` | Tailwind class for grid column width |
1033
- | `bareListGridTags` | `(data: any) => string[]` | Returns tag strings shown on grid cards |
1034
- | `bareListGridFallbackImg` | `(data: any) => string \| ReactElement` | Fallback image/element for grid cards without an image |
1035
- | `bareListGridRibbonText` | `(data: any) => string` | Text shown as a ribbon on grid cards |
1036
- | `bareListHandleData` | `(data, prettierData) => void` | Called when list data is loaded |
1037
- | `bareListHandleSelection` | `(selectAll, selectedIds, query?) => void` | Called when row selection changes |
1038
- | `bareListHandleFilter` | `(search, select, date, reference) => void` | Called when any filter changes |
1039
- | `bareListFilterSelected` | `(filterSearchParams, filterSelection, filterReference, filterReferenceDate) => void` | Called with the current filter state whenever it changes |
1040
- | `bareListDescription` | `(key: string, value: any) => any` | Custom renderer for list view field values |
1041
- | `bareListFilterQuery` | `Query[]` | Additional queries always applied to list fetches |
1042
- | `bareListFilterAddComponent` | `ReactElement[]` | Extra filter components rendered in the filter bar |
1043
- | `bareListPipeline` | `PipeLine[]` | Additional pipeline stages appended to list queries |
1044
- | `bareListObjectHandleData` | `(type: "read" \| "update" \| "new", data: any) => void` | Called when a list-object row is opened |
1045
- | `bareUpdatePrefill` | `(data: any) => { key: string; value: any }[]` | Returns prefill values for the update form based on existing data |
1046
- | `bareUpdateComponent` | `(data: any) => any` | Custom component rendered inside the update form |
1047
- | `bareUpdateComponentAbove` | `boolean` | Renders `bareUpdateComponent` above the default form fields |
1048
- | `bareSaveOnTabChange` | `boolean` | Auto-save: every Next / Previous on a tabbed update form writes a draft first, silently (no toast). Pair with `edit.enableUpdateDraft` |
1049
- | `bareUpsertPartialUpdate` | `boolean` | Upsert by `props.id` and send only the fields that changed since load; a save with no changes skips the write. Makes auto-save safe across devices |
1050
- | `bareUpdateActionComponent` | `(data: any, formRef?: any) => any` | Custom action buttons rendered in the update form footer |
1051
- | `bareFlexFilters` | `boolean` | Funnel icon opens the Filters builder (column · condition · value, values from the schema) — replaces hand-rolled page filters; new table only |
1052
- | `bareListFilterAsPopup` | `boolean` | Shows the list's filter inputs in a popup instead of the header row |
1053
- | `bareListTablePinColumns` | `{ left?: string[]; right?: string[] }` | Columns kept sticky at the edges while the table scrolls sideways (`"update"` is the actions column); new table only |
1054
- | `bareListMobileView` | `boolean` | Phone card list instead of the table (the app passes its own isMobile) |
1055
- | `bareListMobileFloatingSearch` | `boolean` | Floating search bar at the bottom on phones; the list reserves room under its last row for it |
1056
- | `bareListMaxSelectedCount` | `number` | Caps how many rows the checkbox column may select at once |
1057
- | `bareUpdateHandleData` | `(data: any, changedAttributeIds?: string[]) => void` | Called on every form field change with the current data and changed field IDs |
1058
- | `bareUpdateHandlePreComplete` | `(data: any) => Promise<boolean>` | Called before save — return `false` to cancel |
1059
- | `bareUpdateHandleComplete` | `(data: any) => Promise<any>` | Called after save completes |
1060
- | `bareUpdateHandlePostComplete` | `(data: any) => Promise<any>` | Called after post-save operations complete |
1061
- | `bareUpdateColumnType` | `"one" \| "two" \| "four"` | Form column layout: `"one"` = 2-col grid, `"two"` = 4-col grid (default), `"four"` = 4-col grid |
1062
- | `bareUpdateTabComponent` | `(tabIds: string[]) => { tabId: string; icon?: ReactElement; skip?: boolean }[]` | Custom icons/skip flags for form tabs |
1063
- | `bareUpdateActionBottom` | `boolean` | Plain right-aligned action row instead of the floating pill — for short forms inside a `Modal` |
1064
- | `bareUpdateTabId` | `(tabId: string) => void` | Called when the active form tab changes |
1065
- | `bareUpdateIndividualComponent` | `(columnId, ref, selectedData, setSelectedData) => ReactElement \| null` | Replaces a specific form field with a custom component |
1066
- | `bareUpdateMobileView` | `boolean` | Renders the update form in mobile-optimised layout |
1067
- | `bareOffline` | `boolean` | Enables offline data caching via IndexedDB |
1068
- | `bareOfflineNetworkListener` | `boolean` | With `bareOffline`: follow `navigator.onLine` — saves go to the server while online and to IndexedDB only when the network is down. Without it every save goes to IndexedDB until `handleUploadOfflineData()` |
1069
- | `bareOfflinePrefetchLimit` | `number` | With `bareOffline`: how many of the collection's latest docs to download into IndexedDB on mount (default 10) |
1070
- | `bareOfflineReferences` | `Array<{ collectionId: string; limit?: number }>` | With `bareOffline`: reference collections to download on mount so reference dropdowns keep working offline |
1071
- | `bareCSVImportEndpoint` | `string` | Custom CSV import endpoint |
1072
- | `bareCSVExportEndpoint` | `string` | Custom CSV export endpoint |
1073
- | `bareHideTableExtraMultipleAction` | `boolean` | Hides the extra multiple-action button in table view |
1047
+ | Name | Type | Description |
1048
+ | ---------------------------------------- | ------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1049
+ | `bareViewSettings` | `boolean` | Turns on the view settings feature — the panel (columns hide / reorder / search, sort, rows per page) and the hide, drag and sort controls in the table header. Always on under `bareNewDTW` |
1050
+ | `bareReadComponent` | `(data: any, rawData?: any) => any` | Custom component rendered in read view. `data` is display data (labels + elements); `rawData` is the untouched DB doc |
1051
+ | `bareReadComponentPos` | `"top"` | Renders `bareReadComponent` above the default read content |
1052
+ | `bareReadComponentHide` | `boolean` | Hides the default read content (shows only `bareReadComponent`) |
1053
+ | `bareReadReferenceView` | `(dataId, collectionId, attributeId) => boolean \| void` | Controls whether a reference field opens a view |
1054
+ | `bareReadDescription` | `(key: string, value: any) => any` | Custom renderer for read view field values |
1055
+ | `bareReadHandleData` | `(data: any, rawData?: any) => void` | Called when read view data is loaded. `data` is display data (labels + elements); `rawData` is the untouched DB doc |
1056
+ | `bareReadListTabs` | `boolean` | Shows list-style tabs in read view |
1057
+ | `bareListComponent` | `(data, prettierData, loading, pageIndex) => any` | Fully replaces the list UI with a custom component |
1058
+ | `bareListActionBtns` | `(data: any) => ReactElement[]` | Extra icon buttons rendered on each list row |
1059
+ | `bareListMultipleSelectAddtionalActions` | `{ text: string; className?: string; onClick: (ids, selectAll, query) => void }[]` | Extra bulk-action buttons shown when rows are selected |
1060
+ | `bareListGridComponent` | `(data: any) => any` | Custom card renderer for grid view |
1061
+ | `bareListGridColClassName` | `string` | Tailwind class for grid column width |
1062
+ | `bareListGridTags` | `(data: any) => string[]` | Returns tag strings shown on grid cards |
1063
+ | `bareListGridFallbackImg` | `(data: any) => string \| ReactElement` | Fallback image/element for grid cards without an image |
1064
+ | `bareListGridRibbonText` | `(data: any) => string` | Text shown as a ribbon on grid cards |
1065
+ | `bareListHandleData` | `(data, prettierData) => void` | Called when list data is loaded |
1066
+ | `bareListHandleSelection` | `(selectAll, selectedIds, query?) => void` | Called when row selection changes |
1067
+ | `bareListHandleFilter` | `(search, select, date, reference) => void` | Called when any filter changes |
1068
+ | `bareListFilterSelected` | `(filterSearchParams, filterSelection, filterReference, filterReferenceDate) => void` | Called with the current filter state whenever it changes |
1069
+ | `bareListDescription` | `(key: string, value: any) => any` | Custom renderer for list view field values |
1070
+ | `bareListFilterQuery` | `Query[]` | Additional queries always applied to list fetches |
1071
+ | `bareListFilterAddComponent` | `ReactElement[]` | Extra filter components rendered in the filter bar |
1072
+ | `bareListPipeline` | `PipeLine[]` | Additional pipeline stages appended to list queries |
1073
+ | `bareListObjectHandleData` | `(type: "read" \| "update" \| "new", data: any) => void` | Called when a list-object row is opened |
1074
+ | `bareUpdatePrefill` | `(data: any) => { key: string; value: any }[]` | Returns prefill values for the update form based on existing data |
1075
+ | `bareUpdateComponent` | `(data: any) => any` | Custom component rendered inside the update form |
1076
+ | `bareUpdateComponentAbove` | `boolean` | Renders `bareUpdateComponent` above the default form fields |
1077
+ | `bareSaveOnTabChange` | `boolean` | Auto-save: every Next / Previous on a tabbed update form writes a draft first, silently (no toast). Pair with `edit.enableUpdateDraft` |
1078
+ | `bareUpsertPartialUpdate` | `boolean` | Upsert by `props.id` and send only the fields that changed since load; a save with no changes skips the write. Makes auto-save safe across devices |
1079
+ | `bareUpdateActionComponent` | `(data: any, formRef?: any) => any` | Custom action buttons rendered in the update form footer |
1080
+ | `bareFlexFilters` | `boolean` | Funnel icon opens the Filters builder (column · condition · value, values from the schema) — replaces hand-rolled page filters; new table only |
1081
+ | `bareOnFlexFiltersChange` | `(flexFilters: FlexFilterData[]) => void` | Fires when the applied (debounced) flex filters change — from user panel edits or programmatic `handleApplyFlexFilters` / `handleClearFlexFilters`. Lets a parent observe live filter state. Needs `bareFlexFilters` |
1082
+ | `bareListFilterAsPopup` | `boolean` | Shows the list's filter inputs in a popup instead of the header row |
1083
+ | `bareListTablePinColumns` | `{ left?: string[]; right?: string[] }` | Columns kept sticky at the edges while the table scrolls sideways (`"update"` is the actions column); new table only |
1084
+ | `bareListMobileView` | `boolean` | Phone card list instead of the table (the app passes its own isMobile) |
1085
+ | `bareListMobileFloatingSearch` | `boolean` | Floating search bar at the bottom on phones; the list reserves room under its last row for it |
1086
+ | `bareListMaxSelectedCount` | `number` | Caps how many rows the checkbox column may select at once |
1087
+ | `bareUpdateHandleData` | `(data: any, changedAttributeIds?: string[]) => void` | Called on every form field change with the current data and changed field IDs |
1088
+ | `bareUpdateHandlePreComplete` | `(data: any) => Promise<boolean>` | Called before save — return `false` to cancel |
1089
+ | `bareUpdateHandleComplete` | `(data: any) => Promise<any>` | Called after save completes |
1090
+ | `bareUpdateHandlePostComplete` | `(data: any) => Promise<any>` | Called after post-save operations complete |
1091
+ | `bareUpdateColumnType` | `"one" \| "two" \| "four"` | Form column layout: `"one"` = 2-col grid, `"two"` = 4-col grid (default), `"four"` = 4-col grid |
1092
+ | `bareUpdateTabComponent` | `(tabIds: string[]) => { tabId: string; icon?: ReactElement; skip?: boolean }[]` | Custom icons/skip flags for form tabs |
1093
+ | `bareUpdateActionBottom` | `boolean` | Plain right-aligned action row instead of the floating pill — for short forms inside a `Modal` |
1094
+ | `bareUpdateTabId` | `(tabId: string) => void` | Called when the active form tab changes |
1095
+ | `bareUpdateIndividualComponent` | `(columnId, ref, selectedData, setSelectedData) => ReactElement \| null` | Replaces a specific form field with a custom component |
1096
+ | `bareUpdateMobileView` | `boolean` | Renders the update form in mobile-optimised layout |
1097
+ | `bareOffline` | `boolean` | Enables offline data caching via IndexedDB |
1098
+ | `bareOfflineNetworkListener` | `boolean` | With `bareOffline`: follow `navigator.onLine` — saves go to the server while online and to IndexedDB only when the network is down. Without it every save goes to IndexedDB until `handleUploadOfflineData()` |
1099
+ | `bareOfflinePrefetchLimit` | `number` | With `bareOffline`: how many of the collection's latest docs to download into IndexedDB on mount (default 10) |
1100
+ | `bareOfflineReferences` | `Array<{ collectionId: string; limit?: number }>` | With `bareOffline`: reference collections to download on mount so reference dropdowns keep working offline |
1101
+ | `bareCSVImportEndpoint` | `string` | Custom CSV import endpoint |
1102
+ | `bareCSVExportEndpoint` | `string` | Custom CSV export endpoint |
1103
+ | `bareHideTableExtraMultipleAction` | `boolean` | Hides the extra multiple-action button in table view |
1074
1104
 
1075
1105
  ### Extended Tab
1076
1106
 
@@ -1208,10 +1238,10 @@ columns, persisted view state, SSE live) and **Consumer Fixtures** below.
1208
1238
  Every story mocks its own API and opens without a server.
1209
1239
 
1210
1240
  **Consumer fixtures** — `Data / Data Wrapper / Consumer Fixtures` holds the DataTemplateWrapper
1211
- configurations the apps run in production, copied field for field and self-mocked (no
1212
- server): the KPJ grant proposal form (Blixify Space's kpj-projects shape), Verdant's
1213
- installer pre- and post-installation checklists, its Sales Leads list and its simulator
1214
- proposal form, Meraque's offline work order, and an **Action Component Cases** story showing
1241
+ configurations taken from production apps and self-mocked (no server): a long
1242
+ grant-application form, installer pre- and post-installation checklists, a sales-leads list,
1243
+ a simulator proposal form, an offline work order, and an **Action Component Cases** story showing
1215
1244
  the update form under the three things `bareUpdateActionComponent` can return (undefined /
1216
1245
  own buttons / an empty fragment). Open them on a phone and a desktop before bumping the app — what changes
1217
- there is what changes in the app.
1246
+ there is what changes in the app. These fixtures mirror client projects, so they stay in
1247
+ the local Storybook and are excluded from the published MCP package.