blixify-ui-web-mcp 0.1.3 → 0.1.19
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/lib/components/action/button/README.md +12 -11
- package/lib/components/action/button/button.stories.tsx +38 -27
- package/lib/components/action/buttonGroup/buttonGroup.stories.tsx +82 -16
- package/lib/components/action/iconButton/README.md +1 -0
- package/lib/components/action/iconButton/iconButton.stories.tsx +6 -12
- package/lib/components/action/radioList/radioList.stories.tsx +10 -16
- package/lib/components/action/slider/slider.stories.tsx +9 -15
- package/lib/components/action/textButton/textButton.stories.tsx +6 -12
- package/lib/components/action/toggle/toggle.stories.tsx +6 -12
- package/lib/components/advanced/collapse/collapse.stories.tsx +240 -24
- package/lib/components/advanced/infoWindow/infoWindow.stories.tsx +10 -16
- package/lib/components/advanced/popUp/README.md +33 -7
- package/lib/components/advanced/popUp/popUp.stories.tsx +9 -15
- package/lib/components/auth/bareSignIn/bareSignIn.stories.tsx +36 -16
- package/lib/components/auth/bareSignUp/bareSignUp.stories.tsx +7 -13
- package/lib/components/auth/signIn/signIn.stories.tsx +4 -10
- package/lib/components/auth/signUp/signUp.stories.tsx +4 -10
- package/lib/components/chart/areaChart/areaChart.stories.tsx +12 -18
- package/lib/components/chart/barChart/barChart.stories.tsx +12 -18
- package/lib/components/chart/boxPlotChart/boxPlotChart.stories.tsx +11 -17
- package/lib/components/chart/bubbleChart/bubbleChart.stories.tsx +11 -17
- package/lib/components/chart/card/card.stories.tsx +172 -38
- package/lib/components/chart/ganttChart/ganttChart.stories.tsx +10 -16
- package/lib/components/chart/heatmapChart/heatmapChart.stories.tsx +11 -17
- package/lib/components/chart/lineChart/lineChart.stories.tsx +8 -14
- package/lib/components/chart/pieChart/pieChart.stories.tsx +11 -17
- package/lib/components/chart/polarAreaChart/polarAreaChart.stories.tsx +11 -17
- package/lib/components/chart/radarChart/radarChart.stories.tsx +6 -12
- package/lib/components/chart/radialBar/radialChart.stories.tsx +4 -10
- package/lib/components/chart/rangeBarChart/rangeBarChart.stories.tsx +8 -14
- package/lib/components/chart/statsCard/statsCard.stories.tsx +12 -18
- package/lib/components/chart/treemapChart/treemapChart.stories.tsx +11 -17
- package/lib/components/chat/chatAnchor/README.md +7 -0
- package/lib/components/chat/chatAnchor/chatAnchor.stories.tsx +15 -21
- package/lib/components/chat/chatBase/README.md +103 -22
- package/lib/components/chat/chatBase/chatBase.stories.tsx +657 -57
- package/lib/components/chat/chatDashboard/README.md +17 -15
- package/lib/components/chat/chatDashboard/chatDashboard.stories.tsx +358 -46
- package/lib/components/data/dataGraph/dataGraph.stories.tsx +8 -14
- package/lib/components/data/dataReference/dataReference.stories.tsx +9 -15
- package/lib/components/data/dataTemplate/README.md +443 -129
- package/lib/components/data/dataTemplate/dataModule.stories.tsx +10 -15
- package/lib/components/data/dataTemplate/dataTemplate.stories.tsx +20 -34
- package/lib/components/data/dataWrapper/README.md +207 -84
- package/lib/components/data/dataWrapper/dataWrapper.consumer.stories.tsx +2125 -0
- package/lib/components/data/dataWrapper/dataWrapper.edit.stories.tsx +607 -0
- package/lib/components/data/dataWrapper/dataWrapper.utils.stories.tsx +576 -0
- package/lib/components/data/dataWrapper/dataWrapper.view.stories.tsx +1273 -0
- package/lib/components/data/flexFilter/flexFilter.stories.tsx +171 -0
- package/lib/components/data/queryForm/queryForm.stories.tsx +6 -12
- package/lib/components/data/readQuery/readQuery.stories.tsx +6 -11
- package/lib/components/data/readQueryHoc/readQueryHoc.stories.tsx +6 -12
- package/lib/components/data/writeQuery/README.md +21 -10
- package/lib/components/data/writeQuery/writeQuery.stories.tsx +6 -10
- package/lib/components/design/actionSection/actionSection.stories.tsx +10 -14
- package/lib/components/design/banner/banner.stories.tsx +6 -12
- package/lib/components/design/bannerAction/bannerAction.stories.tsx +100 -21
- package/lib/components/design/blogSection/blogSection.stories.tsx +6 -12
- package/lib/components/design/carouselSection/carouselSection.stories.tsx +6 -12
- package/lib/components/design/designList/designList.stories.tsx +6 -12
- package/lib/components/design/faq/faq.stories.tsx +53 -31
- package/lib/components/design/fileGrid/fileGrid.stories.tsx +10 -16
- package/lib/components/design/fileViewer/fileViewer.stories.tsx +6 -12
- package/lib/components/design/footerSection/footerSection.stories.tsx +6 -12
- package/lib/components/design/googleReview/googleReview.stories.tsx +6 -12
- package/lib/components/design/heroSection/heroSection.stories.tsx +10 -16
- package/lib/components/design/iconList/iconList.stories.tsx +6 -12
- package/lib/components/design/imageGallery/imageGallery.stories.tsx +6 -12
- package/lib/components/design/imageZoom/imageZoom.stories.tsx +6 -12
- package/lib/components/design/leftContent/leftContent.stories.tsx +6 -12
- package/lib/components/design/logoCloud/logoCloud.stories.tsx +6 -12
- package/lib/components/design/onboarding/onboarding.stories.tsx +8 -14
- package/lib/components/design/pricing/pricing.stories.tsx +6 -12
- package/lib/components/design/rightContent/rightContent.stories.tsx +6 -12
- package/lib/components/design/sectionList/sectionList.stories.tsx +6 -12
- package/lib/components/design/teams/teams.stories.tsx +6 -12
- package/lib/components/display/alert/alert.stories.tsx +8 -14
- package/lib/components/display/calendar/README.md +49 -0
- package/lib/components/display/calendar/calendar.stories.tsx +78 -35
- package/lib/components/display/clipboard/clipboard.stories.tsx +6 -12
- package/lib/components/display/detailList/detailList.stories.tsx +172 -48
- package/lib/components/display/drawer/README.md +44 -11
- package/lib/components/display/drawer/drawer.stories.tsx +71 -16
- package/lib/components/display/emptyState/emptyState.stories.tsx +47 -15
- package/lib/components/display/feeds/feeds.stories.tsx +6 -12
- package/lib/components/display/flexTable/README.md +11 -7
- package/lib/components/display/flexTable/flexTable.stories.tsx +318 -20
- package/lib/components/display/grid/README.md +29 -30
- package/lib/components/display/grid/grid.stories.tsx +16 -23
- package/lib/components/display/kanban/kanban.stories.tsx +17 -23
- package/lib/components/display/list/README.md +30 -29
- package/lib/components/display/list/list.stories.tsx +11 -17
- package/lib/components/display/loading/loading.stories.tsx +7 -12
- package/lib/components/display/mapView/mapView.stories.tsx +9 -15
- package/lib/components/display/modal/modal.stories.tsx +6 -13
- package/lib/components/display/newCalendar/README.md +163 -0
- package/lib/components/display/newCalendar/newCalendar.stories.tsx +292 -0
- package/lib/components/display/newFeeds/README.md +53 -0
- package/lib/components/display/newFeeds/newFeeds.stories.tsx +104 -0
- package/lib/components/display/newKanban/README.md +25 -0
- package/lib/components/display/newKanban/newKanban.stories.tsx +131 -0
- package/lib/components/display/newList/README.md +30 -0
- package/lib/components/display/newList/newList.stories.tsx +231 -0
- package/lib/components/display/newPagination/README.md +15 -0
- package/lib/components/display/newTable/README.md +121 -0
- package/lib/components/display/newTable/newTable.stories.tsx +551 -0
- package/lib/components/display/notification/notification.stories.tsx +6 -12
- package/lib/components/display/progress/progress.stories.tsx +7 -12
- package/lib/components/display/stepper/README.md +4 -0
- package/lib/components/display/stepper/stepper.stories.tsx +70 -23
- package/lib/components/display/table/README.md +38 -37
- package/lib/components/display/table/table.stories.tsx +34 -36
- package/lib/components/display/tag/tag.stories.tsx +34 -40
- package/lib/components/input/address/address.stories.tsx +12 -18
- package/lib/components/input/canvas/canvas.stories.tsx +12 -18
- package/lib/components/input/checkbox/checkbox.stories.tsx +7 -13
- package/lib/components/input/datePicker/datePicker.stories.tsx +41 -11
- package/lib/components/input/form/form.stories.tsx +11 -17
- package/lib/components/input/markdown/README.md +80 -2
- package/lib/components/input/markdown/markdown.stories.tsx +83 -32
- package/lib/components/input/monthYearPicker/monthYearPicker.stories.tsx +52 -24
- package/lib/components/input/netPromoterScore/netPromoterScore.stories.tsx +6 -12
- package/lib/components/input/rating/rating.stories.tsx +6 -12
- package/lib/components/input/select/README.md +31 -29
- package/lib/components/input/select/select.stories.tsx +33 -39
- package/lib/components/input/signature/signature.stories.tsx +12 -18
- package/lib/components/input/textArea/textArea.stories.tsx +6 -12
- package/lib/components/input/textInput/textinput.stories.tsx +14 -20
- package/lib/components/input/uploadInput/uploadInput.stories.tsx +143 -19
- package/lib/components/navigation/bars/README.md +27 -0
- package/lib/components/navigation/bars/bars.stories.tsx +56 -19
- package/lib/components/navigation/bottomTab/bottomTab.stories.tsx +7 -12
- package/lib/components/navigation/breadcrumb/breadcrumb.stories.tsx +8 -14
- package/lib/components/navigation/header/header.stories.tsx +33 -21
- package/lib/components/navigation/leftNav/leftNav.stories.tsx +10 -16
- package/lib/components/navigation/tabs/tabs.stories.tsx +10 -16
- package/lib/components/structure/column/column.stories.tsx +10 -15
- package/lib/components/structure/container/container.stories.tsx +8 -13
- package/lib/components/structure/link/link.stories.tsx +11 -17
- package/lib/components/structure/text/text.stories.tsx +12 -17
- package/lib/components/template/authPage/authPage.stories.tsx +6 -5
- package/lib/components/template/calendarView/calendarView.stories.tsx +726 -0
- package/lib/components/template/chatDashboard/chatDashboard.stories.tsx +497 -0
- package/lib/components/template/landingPage/landingPage.stories.tsx +10 -7
- package/lib/components/template/mapLayout/mapLayout.stories.tsx +519 -0
- package/lib/components/template/productListing/productListing.stories.tsx +7 -13
- package/lib/components/template/productOverview/productOverview.stories.tsx +5 -11
- package/lib/components/template/shoppingCart/shoppingCart.stories.tsx +6 -12
- package/lib/components/template/userHomePage/userHomePage.stories.tsx +384 -524
- package/lib/components/template/userRankingDashboard/userRankingDashboard.stories.tsx +145 -75
- package/lib/mcp/tools/componentsRoot.d.ts +2 -0
- package/lib/mcp/tools/componentsRoot.d.ts.map +1 -0
- package/lib/mcp/tools/componentsRoot.js +59 -0
- package/lib/mcp/tools/componentsRoot.js.map +1 -0
- package/lib/mcp/tools/getBackendComponent.d.ts.map +1 -1
- package/lib/mcp/tools/getBackendComponent.js +2 -5
- package/lib/mcp/tools/getBackendComponent.js.map +1 -1
- package/lib/mcp/tools/getComponent.d.ts.map +1 -1
- package/lib/mcp/tools/getComponent.js +2 -5
- package/lib/mcp/tools/getComponent.js.map +1 -1
- package/lib/mcp/tools/listComponents.d.ts.map +1 -1
- package/lib/mcp/tools/listComponents.js +15 -10
- package/lib/mcp/tools/listComponents.js.map +1 -1
- package/lib/mcp/tools/suggestTemplate.d.ts.map +1 -1
- package/lib/mcp/tools/suggestTemplate.js +107 -21
- package/lib/mcp/tools/suggestTemplate.js.map +1 -1
- package/package.json +1 -1
- package/lib/components/data/dataWrapper/dataWrapper.stories.tsx +0 -831
|
@@ -40,6 +40,177 @@ The `model` prop defines the columns/fields. You can build it manually as a `Dat
|
|
|
40
40
|
|
|
41
41
|
---
|
|
42
42
|
|
|
43
|
+
### Layout: tabs, sections and extended tabs
|
|
44
|
+
|
|
45
|
+
Three schema-level settings shape how a record is laid out. They nest in one fixed order:
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
Tab (DataStructure.tabId) ← tab bar across the top of the read + update views
|
|
49
|
+
└─ Section (DataStructure.groupId) ← titled card inside the tab; collapsible in the form
|
|
50
|
+
└─ fields ← an object / listObject field renders as a nested
|
|
51
|
+
block or table INSIDE its section — it is a field,
|
|
52
|
+
not a further structural level
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
- Columns with a `tabId` but no `groupId` sit directly under the tab; columns with
|
|
56
|
+
neither land in an automatic **Others** tab. Order follows the schema.
|
|
57
|
+
- `extendedTabs` is a different thing: extra **list** views (grid / calendar / kanban /
|
|
58
|
+
map / report / iframe) rendered as tabs next to the main list — see Extended Tab below.
|
|
59
|
+
It never appears on a single record.
|
|
60
|
+
- `organise.groupBy` is different again: it splits the **list** into one table per value
|
|
61
|
+
of a column ("Group By X"), and has nothing to do with `groupId`.
|
|
62
|
+
|
|
63
|
+
**How a tabbed form is dressed** (`tabAlign: "left"`):
|
|
64
|
+
|
|
65
|
+
- The rail is a numbered `Stepper` (`variant="checklist"`) — the active step is a filled primary block, and a
|
|
66
|
+
step whose required fields are all filled shows a tick instead of its number.
|
|
67
|
+
- Each tab's fields open with the tab name and, when `organise.tabDescriptions[tabId]`
|
|
68
|
+
is set, a one-line description. A horizontal stepper (`tabAlign: "stepper"`) shows
|
|
69
|
+
`organise.tabShortLabels[tabId]` under each dot on a phone (the tab id itself stays the
|
|
70
|
+
only key); without short labels only the active step keeps its name there. Each section is a white card with its title and, when
|
|
71
|
+
`organise.groupDescriptions[groupId]` is set, its own description. The library never
|
|
72
|
+
paints the page background — the host does (Space uses grey), the cards sit on it.
|
|
73
|
+
- **Every update form and every read view** ends in a sticky, single-row floating bar
|
|
74
|
+
carrying its actions — Save · Submit on the form, Update (or the app's own component),
|
|
75
|
+
Export PDF and Log on the read view; a tabbed form adds the navigation cluster to it.
|
|
76
|
+
The bar's left is reserved for the step navigation; the actions group on the right,
|
|
77
|
+
Delete first (an icon on phones), then Save · Submit / Export PDF · Log · Update. The
|
|
78
|
+
header keeps only the title. Success toasts clear themselves after 4 s and, on phones,
|
|
79
|
+
appear at the bottom lifted above the bar. It is the form's only action bar —
|
|
80
|
+
a floating pill (rounded, shadow, lifted off the bottom edge, stretched into the page
|
|
81
|
+
margin on phones), 60 px tall on desktop and phone. Left cluster is navigation —
|
|
82
|
+
`‹ Previous · Step x of y · Next ›` (icons and `x/y` on a phone); Next moves to the
|
|
83
|
+
next tab, saving a draft silently first when `bareSaveOnTabChange` is on, and is
|
|
84
|
+
disabled on the last tab. Right cluster is actions — `Save · Submit`; Submit is
|
|
85
|
+
reachable on every step and is the one filled (primary) button. The header row keeps only Delete. `bareUpdateActionComponent`, when
|
|
86
|
+
set, takes the place of Save / Submit (navigation stays); return an empty fragment to
|
|
87
|
+
hide the library's buttons — the bar is then dropped on a plain form and keeps only its
|
|
88
|
+
navigation on a tabbed one. `bareUpdateActionBottom` swaps the pill for a plain
|
|
89
|
+
right-aligned row (same buttons, no border / shadow / sticky) — use it for short forms
|
|
90
|
+
inside a `Modal`, where the pill would be a card inside a card. Inside a `Modal` without
|
|
91
|
+
`overflowScroll` the panel is `overflow-hidden`, so the pill sits at the end of the form
|
|
92
|
+
instead of floating.
|
|
93
|
+
- `listObject` tables inside the form render their inputs in cell mode (16 px text,
|
|
94
|
+
low padding) so a checklist row is ~44 px, the same as an editable list row.
|
|
95
|
+
|
|
96
|
+
**Saving: create, update, drafts, auto-save**
|
|
97
|
+
|
|
98
|
+
- `id="new"` (or no id) → **create**; any other id → **update** of that record. The toast says
|
|
99
|
+
"Created Successfully" / "Updated Successfully"; with `enableUpdateDraft` a draft save
|
|
100
|
+
says "Draft Saved" instead.
|
|
101
|
+
- `edit.enableUpdateDraft: true` adds **Save** (draft, `baseDraft: true`) next to Submit.
|
|
102
|
+
- `bareSettings.bareSaveOnTabChange: true` is the **auto-save**: Next / Previous write a draft
|
|
103
|
+
before moving, silently. Only an explicit Save or Submit shows a toast.
|
|
104
|
+
- `bareSettings.bareUpsertPartialUpdate: true` turns the update into an upsert by id that sends
|
|
105
|
+
only the changed fields, and **skips the write when nothing changed** — so a Next on an
|
|
106
|
+
untouched tab costs no request. Without it every save writes the full record and toasts,
|
|
107
|
+
changed or not.
|
|
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
|
|
110
|
+
on elsewhere.
|
|
111
|
+
|
|
112
|
+
**Offline mode** (`bareOffline`, the Meraque work-order checklist pattern)
|
|
113
|
+
|
|
114
|
+
```
|
|
115
|
+
mount (online) ─▶ prefetch latest N docs + bareOfflineReferences ─▶ IndexedDB store "local"
|
|
116
|
+
key = collectionId
|
|
117
|
+
save ─▶ online → server (with bareOfflineNetworkListener)
|
|
118
|
+
─▶ offline → IndexedDB, stamped { baseOnline:false, syncStatus:"pending", dirtySections }
|
|
119
|
+
ref.handleUploadOfflineData() ─▶ every pending doc → server (diffed against the baseline it was
|
|
120
|
+
loaded with, 300 ms apart) ─▶ marked synced
|
|
121
|
+
```
|
|
122
|
+
|
|
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`
|
|
125
|
+
state, shows a banner ("Going offline? Sync data required…" / "You're in offline mode." /
|
|
126
|
+
"Data synced. Ready for offline."), passes `bareOffline: offline`, and calls
|
|
127
|
+
`dtwRef.current.handleUploadOfflineData()` when the connection is back.
|
|
128
|
+
- Prefetch never overwrites pending local edits — pending docs win over the server copy of the
|
|
129
|
+
same id. Reference collections listed in `bareOfflineReferences` are what make reference
|
|
130
|
+
fields (team, pilot, robot…) selectable with no network.
|
|
131
|
+
- Story: `Data / Data Wrapper / Consumer Fixtures / Meraque · Work Order (Offline)` — prefetch,
|
|
132
|
+
an offline toggle, an offline save and Sync now, all mocked in the page.
|
|
133
|
+
- This is a feature, not a test harness — stories fake the server with `axios-mock-adapter`
|
|
134
|
+
instead (see the Consumer Fixtures file).
|
|
135
|
+
|
|
136
|
+
**Dark mode** — `organise.darkMode: true` darkens everything DataTemplate renders: list
|
|
137
|
+
chrome, tables and lists, the update form's section cards and **every input's field** (not
|
|
138
|
+
just its label — text, textarea, select and its dropdown, date, checkbox and radio boxes),
|
|
139
|
+
the read view's cards, modals, the drawer, toasts and the floating action bar. Pass
|
|
140
|
+
`organise.darkModeBg` with the class your page already uses (`"bg-neutral-900"`) and those
|
|
141
|
+
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
|
+
|
|
144
|
+
**Wide tables** — every table scrolls inside a `ScrollShadow`: a soft fade on the edge
|
|
145
|
+
that still hides columns, gone at the end of the scroll, over a thin always-visible
|
|
146
|
+
scrollbar. `listObject` tables inside a form also pin their first column
|
|
147
|
+
(`FlexTable pinColumns`, the same `{ left, right }` shape as `NewTable`) so the row label stays put.
|
|
148
|
+
|
|
149
|
+
**Sheet habits in `NewTable`** (`bareNewDTW`):
|
|
150
|
+
|
|
151
|
+
- A `list` column with `listSelectionColour` paints the whole cell in the value's
|
|
152
|
+
colour with contrasting text; in an editable table one tap on it enters the row's inline
|
|
153
|
+
edit and opens that cell's ordinary `Select`, its options in the same colours — picking one
|
|
154
|
+
commits a single update. Colour keys are the Tag palette (`red`, `blue`, `green`, `yellow`, `indigo`,
|
|
155
|
+
`dark`, `default`).
|
|
156
|
+
In a read-only table (`listEditable` off — the wrapper default) that cell is the same
|
|
157
|
+
filled `Select` an editable table shows, just disabled, so it looks identical in both modes
|
|
158
|
+
and the row click still opens the record.
|
|
159
|
+
- `organise.groupBy` keeps rows in **one** table: each group is a tinted, collapsible band
|
|
160
|
+
(chevron, title, count) in the grouping column's colour, and its rows carry the same
|
|
161
|
+
colour as a bar down their left edge. Legacy `Table` keeps the separate-tables layout.
|
|
162
|
+
- Row selection gains **Shift-click** (extend from the last clicked row), **drag** down
|
|
163
|
+
the checkbox column (paint a range), **Esc** (clear), and a **Copy** action on the
|
|
164
|
+
floating bar that writes the selected rows' visible columns as TSV to the clipboard
|
|
165
|
+
(`enableCopy={false}` hides it).
|
|
166
|
+
|
|
167
|
+
**Field polish** — a `list` shown as radios (`listView: "radioview"`) with more than six
|
|
168
|
+
options lays out in two columns; a `boolean` with `enableRadioButtons` renders as
|
|
169
|
+
Yes / No pills; `TextInput` / `TextArea` show a character counter whenever `maxLength`
|
|
170
|
+
is set.
|
|
171
|
+
|
|
172
|
+
None of these carry a colour of their own. Everything coloured follows the theme's
|
|
173
|
+
primary: the active tab's underline (`border-primary-500 text-primary-600`) and, in the
|
|
174
|
+
update form only, the light `bg-primary-50` tint behind a collapsible section. Read-view
|
|
175
|
+
section cards are plain white. Per-value colour exists only on `list` / `multipleList`
|
|
176
|
+
columns via `listSelectionColour`.
|
|
177
|
+
|
|
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
|
|
181
|
+
as a nested table inside the _Applicants' Details_ section.
|
|
182
|
+
|
|
183
|
+
## View Settings
|
|
184
|
+
|
|
185
|
+
One panel behind the sliders icon carries every list-view setting — it replaces the old
|
|
186
|
+
Slice Data, Model Overview and Sort modals and the desktop-only header drag.
|
|
187
|
+
|
|
188
|
+
| Section | What it does |
|
|
189
|
+
| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
190
|
+
| Columns | search the column list, drag a handle to reorder, eye / eye-slash to hide. The last visible column stays locked so the table always has a header |
|
|
191
|
+
| Sort | pick the column and the direction — the only sort UI on a phone, where the table renders cards with no headers |
|
|
192
|
+
| Rows per page | 10 / 25 / 50 / 100, persisted with the rest of the view state |
|
|
193
|
+
|
|
194
|
+
The column list is the only scrolling region (capped height with a `ScrollShadow`), so Sort
|
|
195
|
+
and Rows per page stay in view on a collection with dozens of fields. Desktop opens a
|
|
196
|
+
popover; a phone opens a modal, since the popover cannot fit the panel inside the viewport.
|
|
197
|
+
|
|
198
|
+
The panel is standard under `bareNewDTW`; `bareSettings.bareViewSettings` opts a legacy or bare
|
|
199
|
+
DTW into it. There are no separate sort / filter / drag flags — the feature carries all three,
|
|
200
|
+
and per-column filtering comes from `bareFlexFilters`.
|
|
201
|
+
|
|
202
|
+
The table header carries the same actions for the column you are pointing at: sort, and a hide
|
|
203
|
+
button revealed on hover so a wide header stays clean (the sort icon stays visible because it
|
|
204
|
+
also reports the current sort). Reordering has no icon — the header shows a grab cursor and
|
|
205
|
+
the panel carries an explicit handle. Both run the same
|
|
206
|
+
reorder and hide as the panel, so the result persists identically whichever one is used. The
|
|
207
|
+
panel remains the only surface on a phone, where the card view has no headers.
|
|
208
|
+
|
|
209
|
+
Hide and reorder are **per user** by default, kept in `persistViewState`. Wire
|
|
210
|
+
`organise.onChangeHide` / `organise.onChangeDrag` and the panel switches to **schema mode**:
|
|
211
|
+
the change is written to the model and handed to the consumer to persist for everyone — which
|
|
212
|
+
is what a Space-backed DTW wants.
|
|
213
|
+
|
|
43
214
|
## Step-by-Step Setup
|
|
44
215
|
|
|
45
216
|
**1. Install peer dependencies**
|
|
@@ -98,7 +269,7 @@ Or derive it from a Workspace object:
|
|
|
98
269
|
import { parseWorkspaceSettings } from "blixify-ui-web/data/utils";
|
|
99
270
|
const devSettings = parseWorkspaceSettings(
|
|
100
271
|
{ dbEndpoint, imageEndpoint, uploadEndpoint },
|
|
101
|
-
workspaceObject
|
|
272
|
+
workspaceObject,
|
|
102
273
|
);
|
|
103
274
|
```
|
|
104
275
|
|
|
@@ -108,7 +279,7 @@ const devSettings = parseWorkspaceSettings(
|
|
|
108
279
|
const handleNavigate = (
|
|
109
280
|
nextType: string,
|
|
110
281
|
selectedId?: string,
|
|
111
|
-
nextViewId?: string
|
|
282
|
+
nextViewId?: string,
|
|
112
283
|
) => {
|
|
113
284
|
setType(nextType);
|
|
114
285
|
if (selectedId !== undefined) setId(selectedId);
|
|
@@ -241,6 +412,8 @@ Set `organise.viewId="calendar"` and add an `extendedTabs` entry with `calendarS
|
|
|
241
412
|
|
|
242
413
|
### Grid view
|
|
243
414
|
|
|
415
|
+
Under `bareNewDTW` the grid hides `Grid`'s own page buttons and renders the same `NewPagination` footer as the table and list views.
|
|
416
|
+
|
|
244
417
|
Set `organise.viewId="grid"` (or add an `extendedTabs` entry with `viewType="grid"`) to render records as image cards. Use `bareSettings.bareListGridComponent` to fully customise each card, or use the built-in grid with `viewImage` pointing to an image column.
|
|
245
418
|
|
|
246
419
|
```tsx
|
|
@@ -335,6 +508,8 @@ Set `organise.viewId="list"` to render records as a vertical list instead of a t
|
|
|
335
508
|
|
|
336
509
|
### Kanban view
|
|
337
510
|
|
|
511
|
+
On phones (`bareListMobileView`) the columns become a tab rail with one column visible; the first column is selected as soon as data arrives, and cards move by long-press onto another tab. Cards, rail and columns follow `organise.darkMode`.
|
|
512
|
+
|
|
338
513
|
Set `viewType="kanban"` on an `extendedTabs` entry and configure `kanbanSettings` to define which column drives the board columns. `title` is the column ID shown on each card; `groupCluster` maps column names to the list-selection values that belong in that column.
|
|
339
514
|
|
|
340
515
|
```tsx
|
|
@@ -536,6 +711,27 @@ Enable `organise.exportSettings.enableExportReadPDF` to add a PDF export button
|
|
|
536
711
|
|
|
537
712
|
---
|
|
538
713
|
|
|
714
|
+
## Stacking (z-index) Layers
|
|
715
|
+
|
|
716
|
+
The layers every DataTemplate surface stacks in, lowest to highest. Anything that floats
|
|
717
|
+
must sit above the sticky action bar (`z-20`) and below overlays/modals.
|
|
718
|
+
|
|
719
|
+
| Layer | Components |
|
|
720
|
+
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
721
|
+
| `z-0` – `z-10` | In-flow accents: sticky table headers / pinned columns (`z-10`–`z-20` in FlexTable), stepper rail, grid/list image overlays, modal sticky title (`z-10`) |
|
|
722
|
+
| `z-20` | **DataTemplate sticky action bar** (form + read view), stepper connectors, date-picker mobile overlay |
|
|
723
|
+
| `z-30` | Floating pieces that must clear the action bar: **Select option list**, `PopUp` panels (filters, ⋮ menu, select-all), drawer root, page `Header` / `BottomTab` / `LeftNav`, legacy list/table popovers |
|
|
724
|
+
| `z-[35]` | Drawer sticky header (above its own content, below a Modal) |
|
|
725
|
+
| `z-40` | **Modal** (overlay + panel) — deliberately above the drawer (`z-30`) so a modal opened from a drawer wins |
|
|
726
|
+
| `z-50` | Toasts (**Notification**), calendar day popup, kanban drag ghost, row hover tooltips, markdown editor menus, onboarding |
|
|
727
|
+
| `z-[51]` | Stepper description popover (above toasts so it stays readable) |
|
|
728
|
+
| `z-[100]` | DataTemplate fixed utilities: offline sync badge, scroll-to-top |
|
|
729
|
+
| `z-[9999]` | App-level attention layers: `Bars` celebration overlay, `InfoWindow` |
|
|
730
|
+
|
|
731
|
+
Rules of thumb: a dropdown or popover opened from inside the form → `z-30`; anything modal →
|
|
732
|
+
`z-40`; transient feedback (toast, drag ghost, tooltip) → `z-50`; never introduce a new value
|
|
733
|
+
without placing it in this table.
|
|
734
|
+
|
|
539
735
|
## Utility Functions
|
|
540
736
|
|
|
541
737
|
### `parseSpaceToDataStructure(space: Space): DataStructure[]`
|
|
@@ -562,7 +758,7 @@ const devSettings = parseWorkspaceSettings(
|
|
|
562
758
|
imageEndpoint: process.env.IMAGE_ENDPOINT,
|
|
563
759
|
uploadEndpoint: process.env.UPLOAD_ENDPOINT,
|
|
564
760
|
},
|
|
565
|
-
workspaceObject // optional — overrides defaults when provided
|
|
761
|
+
workspaceObject, // optional — overrides defaults when provided
|
|
566
762
|
);
|
|
567
763
|
```
|
|
568
764
|
|
|
@@ -572,7 +768,8 @@ const devSettings = parseWorkspaceSettings(
|
|
|
572
768
|
|
|
573
769
|
| Method | Description |
|
|
574
770
|
| ---------------------------------- | ----------------------------------------------------------------- |
|
|
575
|
-
| `handleRefresh()` | Re-fetches the current list data
|
|
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 |
|
|
576
773
|
| `handleFormSubmit()` | Programmatically submits the update/create form |
|
|
577
774
|
| `handleFormCheck()` | Validates the form without submitting |
|
|
578
775
|
| `handlePopUpModal()` | Opens the create/update modal |
|
|
@@ -595,26 +792,27 @@ const devSettings = parseWorkspaceSettings(
|
|
|
595
792
|
|
|
596
793
|
### Optional props
|
|
597
794
|
|
|
598
|
-
| Name | Type | Default
|
|
599
|
-
| ---------------- | --------------------------------------- |
|
|
600
|
-
| `id` | `string` | `""`
|
|
601
|
-
| `limit` | `number` | `10`
|
|
602
|
-
| `space` | `Space` | —
|
|
603
|
-
| `edit` | `Edit` | —
|
|
604
|
-
| `organise` | `Organise` | —
|
|
605
|
-
| `bareSettings` | `BareSettings` | —
|
|
606
|
-
| `renderSettings` | `RenderSettings` | —
|
|
607
|
-
| `roles` | `string[]` | —
|
|
608
|
-
| `darkMode` | `boolean` | —
|
|
609
|
-
| `
|
|
610
|
-
| `
|
|
611
|
-
| `
|
|
612
|
-
| `
|
|
613
|
-
| `
|
|
614
|
-
| `
|
|
615
|
-
| `
|
|
616
|
-
| `
|
|
617
|
-
| `
|
|
795
|
+
| Name | Type | Default | Description |
|
|
796
|
+
| ---------------- | --------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
|
|
797
|
+
| `id` | `string` | `""` | Selected record ID. Pass `"new"` to open a blank create form |
|
|
798
|
+
| `limit` | `number` | `10` | Records per page in list view |
|
|
799
|
+
| `space` | `Space` | — | Full Space object from Blixify Space — enables extended features like tabs, sort, and additional queries |
|
|
800
|
+
| `edit` | `Edit` | — | Controls create/update/delete permissions — see Edit below |
|
|
801
|
+
| `organise` | `Organise` | — | Controls view, sort, filter, tabs, export, and navigation — see Organise below |
|
|
802
|
+
| `bareSettings` | `BareSettings` | — | Injects custom React components and callbacks into list/read/update views — see BareSettings below |
|
|
803
|
+
| `renderSettings` | `RenderSettings` | — | Overrides the entire list UI or loading UI with custom renderers |
|
|
804
|
+
| `roles` | `string[]` | — | Role strings (reserved for future permission checks) |
|
|
805
|
+
| `darkMode` | `boolean` | — | Applies dark colour scheme |
|
|
806
|
+
| `darkModeBg` | `string` | The app's own dark surface class (e.g. `"bg-neutral-900"`). With `darkMode`, every panel DataTemplate paints — modals, tables, lists, section cards, read-view cards, the drawer, the floating action bar — uses it instead of the default `bg-gray-900`, so nothing comes out navy on a black page |
|
|
807
|
+
| `uniqueLabel` | `string` | — | Unique label appended to internal query keys to avoid collisions |
|
|
808
|
+
| `groupId` | `string` | — | Groups list results by this field. Grouped items are returned with a `children` array |
|
|
809
|
+
| `defaultTab` | `any` | — | Pre-selects a tab on mount |
|
|
810
|
+
| `workspaceId` | `string` | — | Workspace ID (used for workspace-scoped operations) |
|
|
811
|
+
| `newTabUrl` | `{ default?: string; addons?: string }` | — | URL config for row links. `default` is the base URL; `addons` is appended after the record id |
|
|
812
|
+
| `lib` | `LibSettings` | — | External library instances — see lib below |
|
|
813
|
+
| `linkProps` | `LinkProps` | — | Refer to Link component documentation |
|
|
814
|
+
| `onComplete` | `(id: string) => void` | — | Called after a create/update operation completes |
|
|
815
|
+
| `onLoadIframe` | `() => void` | — | Called when an iframe tab finishes loading |
|
|
618
816
|
|
|
619
817
|
### lib
|
|
620
818
|
|
|
@@ -668,6 +866,36 @@ const devSettings = parseWorkspaceSettings(
|
|
|
668
866
|
| `disabledTabsDeleteBtn` | `boolean` | Disables the delete button inside extended tabs |
|
|
669
867
|
| `activityLog` | `ActivityLog` | See ActivityLog below |
|
|
670
868
|
|
|
869
|
+
#### Inline editability matrix (`listEditable`)
|
|
870
|
+
|
|
871
|
+
Which field types can be edited from the list table, and how. Types not listed under
|
|
872
|
+
"Never rendered" appear as read-only cells when they are not editable.
|
|
873
|
+
|
|
874
|
+
| Edited **in the cell** | Edited **in a modal** (cell click opens it) | Read-only in list | Never rendered as a list column |
|
|
875
|
+
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------- | ----------------------------- | ------------------------------- |
|
|
876
|
+
| `string`, `contact`, `email`, `textArea`, `number`, `boolean` (checkbox and radio commit on select), `date`, `list`, `multipleList`, `person`, `listPerson`, `roles`, `reference`, `listReference`, `referenceSelection` | `image`, `multipleImage`, `address`, `object`, `listObject`, `markdown`, `signature`, `file`, `multipleFile`, `listAddress` | `math` (computed), `password` | `canvas`, `ganttchart` |
|
|
877
|
+
|
|
878
|
+
- **Why some types edit in a modal:** their editor is bigger than one line. An
|
|
879
|
+
`address` is a Places autocomplete plus a map with a draggable pin plus
|
|
880
|
+
country/state/district fields; `image` / `multipleImage` are an upload area
|
|
881
|
+
with previews; `object` / `listObject` are a nested form. None of that fits a
|
|
882
|
+
table cell, so the cell shows the value (or `Add`) and a click opens the same
|
|
883
|
+
editor the update view uses. Keep them there — an inline variant would have to
|
|
884
|
+
drop the map / previews / nested fields to fit.
|
|
885
|
+
- Inline commits fire **one single-column update on blur**, and only when the value
|
|
886
|
+
actually changed — an untouched blur fires nothing.
|
|
887
|
+
- `reference` / `listReference` options load with **one call per cell focus** (the
|
|
888
|
+
select's own fetch — the table adds none of its own); typing searches
|
|
889
|
+
server-side, debounced.
|
|
890
|
+
- Reference labels — top-level **and** nested inside `object` / `listObject` —
|
|
891
|
+
are resolved once at list load, one query per referenced collection, and seed
|
|
892
|
+
both the inline cell and the object editor; nothing is fetched on open.
|
|
893
|
+
- An `object` cell prints every readable field joined with `·`
|
|
894
|
+
(`Blixify Sdn Bhd · Admin`), with nested reference ids already swapped for labels.
|
|
895
|
+
- Modal saves go through the same single-column update; Cancel and no-change saves
|
|
896
|
+
fire nothing.
|
|
897
|
+
- See the `DTW Inline Edit Matrix` story for a live fixture with every type.
|
|
898
|
+
|
|
671
899
|
### ActivityLog
|
|
672
900
|
|
|
673
901
|
| Name | Type | Description |
|
|
@@ -683,57 +911,55 @@ const devSettings = parseWorkspaceSettings(
|
|
|
683
911
|
|
|
684
912
|
### Organise
|
|
685
913
|
|
|
686
|
-
| Name | Type | Description
|
|
687
|
-
| ----------------------------- | --------------------------------------------------------------------------- |
|
|
688
|
-
| `sort` | `Sort` | Default sort applied to list queries
|
|
689
|
-
| `pageIndex` | `number` | Initial page index
|
|
690
|
-
| `viewId` | `string` | Active view type: `"general"`, `"calendar"`, `"grid"`, `"list"`, `"feeds"`, `"kanban"`, etc.
|
|
691
|
-
| `idField` | `string` | DataStructure column ID whose value becomes the new record's ID on creation
|
|
692
|
-
| `extendedTabs` | `ExtendedTabs[]` | Additional tabs rendered alongside the main view — see Extended Tab below
|
|
693
|
-
| `additionalQuery` | `AdditionalQuery[]` | Filter/search controls rendered above the list — see Additional Query below
|
|
694
|
-
| `darkMode` | `boolean` | Applies dark colour scheme to the organise bar
|
|
695
|
-
| `hideSearch` | `boolean` | Hides the search input
|
|
696
|
-
| `hidePagination` | `boolean` | Hides pagination on Table, List, Grid, and Feeds views
|
|
697
|
-
| `hideNewTabs` | `boolean` | Hides the new-tab creation button
|
|
698
|
-
| `splitView` | `boolean` | Renders a split list/detail layout in read mode
|
|
699
|
-
| `listObjectTableView` | `boolean` | Shows list objects in table view during read and update
|
|
700
|
-
| `disableMulti` | `boolean` | Disables multi-row selection
|
|
701
|
-
| `disableSelectFullData` | `{ table?: boolean; list?: boolean }` | Disables "select all pages" for table and/or list views
|
|
702
|
-
| `disabledOnEnter` | `boolean` | Prevents Enter key from submitting forms
|
|
703
|
-
| `breadcrumbType` | `"button" \| "hidden"` | `"button"` shows a back button; `"hidden"` hides the breadcrumb entirely
|
|
704
|
-
| `breadcrumbAttributeId` | `string` | Column ID whose value is used as the breadcrumb label in read view
|
|
705
|
-
| `tabAlign` | `"top" \| "left" \| "stepper"` | Tab layout direction
|
|
706
|
-
| `groupRead` | `"groupId"` | Groups and separates read view sections by DataStructure `groupId`
|
|
707
|
-
| `showCollapsibleTab` | `boolean` | Renders tabs as collapsible sections
|
|
708
|
-
| `showBaseUpdatedAt` | `boolean` | Shows the `baseUpdatedAt` timestamp in Table, Grid, List, and Kanban views
|
|
709
|
-
| `showGroupByFeature` | `boolean` | Shows the group-by selector in the toolbar
|
|
710
|
-
| `showReadFloatingNav` | `boolean` | Shows a floating section navigator in read view
|
|
711
|
-
| `showExport` | `boolean` | Shows import/export options (default `true`)
|
|
712
|
-
| `disableEllipsisOnLongWord` | `boolean` | Wraps long text instead of truncating with ellipsis
|
|
713
|
-
| `fixedPagination` | `boolean` | Fixes the pagination bar to the bottom of the viewport
|
|
714
|
-
| `filterComponentNewRow` | `boolean` | Renders each filter component on its own row
|
|
715
|
-
| `addColumnEnabled` | `boolean` | Shows an add-column button in the table header
|
|
716
|
-
| `
|
|
717
|
-
| `
|
|
718
|
-
| `
|
|
719
|
-
| `
|
|
720
|
-
| `
|
|
721
|
-
| `
|
|
722
|
-
| `
|
|
723
|
-
| `
|
|
724
|
-
| `
|
|
725
|
-
| `
|
|
726
|
-
| `
|
|
727
|
-
| `
|
|
728
|
-
| `
|
|
729
|
-
| `
|
|
730
|
-
| `
|
|
731
|
-
| `
|
|
732
|
-
| `
|
|
733
|
-
| `
|
|
734
|
-
| `
|
|
735
|
-
| `renderReferenceSpaceOptions` | `() => Option[]` | Returns space options for reference space selectors |
|
|
736
|
-
| `renderGroupByOptions` | `() => Option[]` | Returns custom options for the group-by selector |
|
|
914
|
+
| Name | Type | Description |
|
|
915
|
+
| ----------------------------- | --------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
916
|
+
| `sort` | `Sort` | Default sort applied to list queries |
|
|
917
|
+
| `pageIndex` | `number` | Initial page index |
|
|
918
|
+
| `viewId` | `string` | Active view type: `"general"`, `"calendar"`, `"grid"`, `"list"`, `"feeds"`, `"kanban"`, etc. |
|
|
919
|
+
| `idField` | `string` | DataStructure column ID whose value becomes the new record's ID on creation |
|
|
920
|
+
| `extendedTabs` | `ExtendedTabs[]` | Additional tabs rendered alongside the main view — see Extended Tab below |
|
|
921
|
+
| `additionalQuery` | `AdditionalQuery[]` | Filter/search controls rendered above the list — see Additional Query below |
|
|
922
|
+
| `darkMode` | `boolean` | Applies dark colour scheme to the organise bar |
|
|
923
|
+
| `hideSearch` | `boolean` | Hides the search input |
|
|
924
|
+
| `hidePagination` | `boolean` | Hides pagination on Table, List, Grid, and Feeds views |
|
|
925
|
+
| `hideNewTabs` | `boolean` | Hides the new-tab creation button |
|
|
926
|
+
| `splitView` | `boolean` | Renders a split list/detail layout in read mode |
|
|
927
|
+
| `listObjectTableView` | `boolean` | Shows list objects in table view during read and update |
|
|
928
|
+
| `disableMulti` | `boolean` | Disables multi-row selection |
|
|
929
|
+
| `disableSelectFullData` | `{ table?: boolean; list?: boolean }` | Disables "select all pages" for table and/or list views |
|
|
930
|
+
| `disabledOnEnter` | `boolean` | Prevents Enter key from submitting forms |
|
|
931
|
+
| `breadcrumbType` | `"button" \| "hidden"` | `"button"` shows a back button; `"hidden"` hides the breadcrumb entirely |
|
|
932
|
+
| `breadcrumbAttributeId` | `string` | Column ID whose value is used as the breadcrumb label in read view |
|
|
933
|
+
| `tabAlign` | `"top" \| "left" \| "stepper"` | Tab layout direction |
|
|
934
|
+
| `groupRead` | `"groupId"` | Groups and separates read view sections by DataStructure `groupId` |
|
|
935
|
+
| `showCollapsibleTab` | `boolean` | Renders tabs as collapsible sections |
|
|
936
|
+
| `showBaseUpdatedAt` | `boolean` | Shows the `baseUpdatedAt` timestamp in Table, Grid, List, and Kanban views |
|
|
937
|
+
| `showGroupByFeature` | `boolean` | Shows the group-by selector in the toolbar |
|
|
938
|
+
| `showReadFloatingNav` | `boolean` | Shows a floating section navigator in read view |
|
|
939
|
+
| `showExport` | `boolean` | Shows import/export options (default `true`) |
|
|
940
|
+
| `disableEllipsisOnLongWord` | `boolean` | Wraps long text instead of truncating with ellipsis |
|
|
941
|
+
| `fixedPagination` | `boolean` | Fixes the pagination bar to the bottom of the viewport |
|
|
942
|
+
| `filterComponentNewRow` | `boolean` | Renders each filter component on its own row |
|
|
943
|
+
| `addColumnEnabled` | `boolean` | Shows an add-column button in the table header |
|
|
944
|
+
| `persistViewState` | `"session" \| "local"` | Remembers the list's sort, filters, hidden columns, page and search in `sessionStorage` / `localStorage` per collection, so a Back navigation lands where the user left |
|
|
945
|
+
| `groupBy` | `string` | Column ID to group list results by |
|
|
946
|
+
| `groupIdCollapsible` | `{ [key: string]: boolean }` | Initial collapsed/expanded state per group ID |
|
|
947
|
+
| `sortGroupByAlphabetically` | `boolean` | Sorts group-by values alphabetically |
|
|
948
|
+
| `unionCollections` | `any[]` | Additional collections to union-query alongside the main collection |
|
|
949
|
+
| `moreSettings` | `{ text: string; onClick: () => void }[]` | Extra items appended to the "more" dropdown menu |
|
|
950
|
+
| `exportSettings` | `ExportSettings` | See Export Settings below |
|
|
951
|
+
| `onChangeSort` | `(value: Sort) => void` | Called when the user changes the sort |
|
|
952
|
+
| `onChangeHide` | `(value: DataStructure[]) => void` | Called when a column is hidden from the view settings panel. Providing it switches the panel to schema mode — the hide is written to the model for everyone instead of being this user's own |
|
|
953
|
+
| `onChangeDrag` | `(dragId: string, dropId: string, newHeader: TableHeader[]) => void` | Called after a column is reordered in the view settings panel, so the consumer can persist the order |
|
|
954
|
+
| `onChangeTabs` | `(value: ExtendedTabs[]) => void` | Called when tabs are added/removed/reordered |
|
|
955
|
+
| `onChangePagination` | `(page: number) => void` | Called when the page changes |
|
|
956
|
+
| `customPaginationCount` | `(pageDataCount: number) => void` | Called after each data fetch with the actual record count. Use this to override the count shown in the pagination bar — store the value in your own state and pass it back via `customPaginationSize` on `Table`, `Grid`, `List`, or `Pagination` if needed, or use it to display a custom count elsewhere in your UI |
|
|
957
|
+
| `onAddColumns` | `(model: DataStructure[]) => void` | Called when a new column is added |
|
|
958
|
+
| `handleNavigate` | `(type: string, selectedId?: string, viewId?: string) => void` | Called when the component needs to navigate (e.g. row click → read view) |
|
|
959
|
+
| `handleCustomDownloadFile` | `(url: string, fileName?: string) => void` | Overrides the default file download behaviour |
|
|
960
|
+
| `renderReferenceLabelOptions` | `(spaceId?: string, includeReference?: boolean, type?: string) => Option[]` | Returns column options for reference label selectors |
|
|
961
|
+
| `renderReferenceSpaceOptions` | `() => Option[]` | Returns space options for reference space selectors |
|
|
962
|
+
| `renderGroupByOptions` | `() => Option[]` | Returns custom options for the group-by selector |
|
|
737
963
|
|
|
738
964
|
### Export Settings
|
|
739
965
|
|
|
@@ -789,50 +1015,62 @@ const devSettings = parseWorkspaceSettings(
|
|
|
789
1015
|
|
|
790
1016
|
Injects custom React components and callbacks into the list, read, and update views.
|
|
791
1017
|
|
|
792
|
-
| Name | Type | Description
|
|
793
|
-
| ---------------------------------------- | ------------------------------------------------------------------------------------- |
|
|
794
|
-
| `
|
|
795
|
-
| `
|
|
796
|
-
| `
|
|
797
|
-
| `
|
|
798
|
-
| `
|
|
799
|
-
| `
|
|
800
|
-
| `
|
|
801
|
-
| `
|
|
802
|
-
| `
|
|
803
|
-
| `
|
|
804
|
-
| `
|
|
805
|
-
| `
|
|
806
|
-
| `
|
|
807
|
-
| `
|
|
808
|
-
| `
|
|
809
|
-
| `
|
|
810
|
-
| `
|
|
811
|
-
| `
|
|
812
|
-
| `
|
|
813
|
-
| `
|
|
814
|
-
| `
|
|
815
|
-
| `
|
|
816
|
-
| `
|
|
817
|
-
| `
|
|
818
|
-
| `
|
|
819
|
-
| `
|
|
820
|
-
| `
|
|
821
|
-
| `
|
|
822
|
-
| `
|
|
823
|
-
| `
|
|
824
|
-
| `
|
|
825
|
-
| `
|
|
826
|
-
| `
|
|
827
|
-
| `
|
|
828
|
-
| `
|
|
829
|
-
| `
|
|
830
|
-
| `
|
|
831
|
-
| `
|
|
832
|
-
| `
|
|
833
|
-
| `
|
|
834
|
-
| `
|
|
835
|
-
| `
|
|
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 |
|
|
836
1074
|
|
|
837
1075
|
### Extended Tab
|
|
838
1076
|
|
|
@@ -863,19 +1101,81 @@ Injects custom React components and callbacks into the list, read, and update vi
|
|
|
863
1101
|
|
|
864
1102
|
### Calendar Settings
|
|
865
1103
|
|
|
866
|
-
| Name | Type
|
|
867
|
-
| ------------------ |
|
|
868
|
-
| `title` | `string`
|
|
869
|
-
| `startDate` | `string`
|
|
870
|
-
| `endDate` | `string`
|
|
871
|
-
| `defaultStartDate` | `Date`
|
|
872
|
-
| `customView` | `CalendarCustomView`
|
|
873
|
-
| `groupId` | `string`
|
|
874
|
-
| `groupColor` | `Color[]`
|
|
875
|
-
| `customHeader` | `string`
|
|
1104
|
+
| Name | Type | Description |
|
|
1105
|
+
| ------------------ | -------------------------- | --------------------------------------------------------------------------------------------------------- |
|
|
1106
|
+
| `title` | `string` | Column ID for event title |
|
|
1107
|
+
| `startDate` | `string` | Column ID for event start date |
|
|
1108
|
+
| `endDate` | `string` | Column ID for event end date |
|
|
1109
|
+
| `defaultStartDate` | `Date` | Default calendar start date |
|
|
1110
|
+
| `customView` | `CalendarCustomView` | Custom calendar view config |
|
|
1111
|
+
| `groupId` | `string` | Column ID — events with the same value share a background colour |
|
|
1112
|
+
| `groupColor` | `Color[]` | Background colours for groups |
|
|
1113
|
+
| `customHeader` | `string` | Custom title replacing the default calendar header |
|
|
1114
|
+
| `eventColorRules` | `CalendarEventColorRule[]` | Maps a field+value on each event to an explicit color. Takes priority over `groupId` coloring. See below. |
|
|
1115
|
+
|
|
1116
|
+
### CalendarEventColorRule
|
|
1117
|
+
|
|
1118
|
+
| Name | Type | Required | Description |
|
|
1119
|
+
| ------------ | -------- | -------- | -------------------------------------------------------------------- |
|
|
1120
|
+
| `field` | `string` | yes | Column ID on the event data to match against (e.g. `"status"`) |
|
|
1121
|
+
| `value` | `any` | yes | The value to match (e.g. `"Approved"`) |
|
|
1122
|
+
| `color` | `string` | yes | Tailwind bg class for the event pill, e.g. `"bg-green-500"` |
|
|
1123
|
+
| `hoverColor` | `string` | no | Tailwind hover class for the event pill, e.g. `"hover:bg-green-700"` |
|
|
1124
|
+
| `textColor` | `string` | no | Tailwind text class for the event pill, e.g. `"text-white"` |
|
|
1125
|
+
|
|
1126
|
+
Example — color events by status:
|
|
1127
|
+
|
|
1128
|
+
```tsx
|
|
1129
|
+
calendarSettings: {
|
|
1130
|
+
title: "name",
|
|
1131
|
+
startDate: "startAt",
|
|
1132
|
+
endDate: "endAt",
|
|
1133
|
+
eventColorRules: [
|
|
1134
|
+
{ field: "status", value: "Approved", color: "bg-green-500", hoverColor: "hover:bg-green-700", textColor: "text-white" },
|
|
1135
|
+
{ field: "status", value: "Pending", color: "bg-yellow-400", hoverColor: "hover:bg-yellow-600", textColor: "text-white" },
|
|
1136
|
+
{ field: "status", value: "Rejected", color: "bg-red-500", hoverColor: "hover:bg-red-700", textColor: "text-white" },
|
|
1137
|
+
],
|
|
1138
|
+
}
|
|
1139
|
+
```
|
|
1140
|
+
|
|
1141
|
+
### List / MultipleList Field Settings
|
|
1142
|
+
|
|
1143
|
+
Properties specific to `type: "list"` and `type: "multipleList"` fields in the DataStructure schema.
|
|
1144
|
+
|
|
1145
|
+
| Name | Type | Default | Description |
|
|
1146
|
+
| ------------------------ | ----------------------------------- | ----------- | ---------------------------------------------------------------------------------------------------------------------- |
|
|
1147
|
+
| `listSelection` | `string[]` | — | Available options for the select field |
|
|
1148
|
+
| `listSelectionLabel` | `string[]` | — | Display labels for each option (matched by index). When omitted, the key itself is shown |
|
|
1149
|
+
| `listSelectionColour` | `string[]` | — | Colour for each option (matched by index). Supports named colours or hex values starting with `#` |
|
|
1150
|
+
| `listView` | `"radioview" \| "modal" \| "chips"` | `undefined` | Render style. `undefined` = dropdown. `"chips"` renders options as inline toggleable chips |
|
|
1151
|
+
| `listNewValue` | `boolean` | `false` | Allows users to add values not in `listSelection`. In chips mode, shows a `+ Add` chip that expands to an inline input |
|
|
1152
|
+
| `listNewValueLabel` | `string` | `"+ Add"` | Custom label for the add-new-value chip (only applies when `listView: "chips"` and `listNewValue: true`) |
|
|
1153
|
+
| `disabledAutoSelect` | `boolean` | `false` | When `true`, no option is pre-selected. The field starts empty |
|
|
1154
|
+
| `disabledKeyboardSearch` | `boolean` | `false` | Disables typeahead filtering in the dropdown |
|
|
1155
|
+
| `showTagSelections` | `boolean` | `false` | Shows selected values as removable tags below the dropdown input |
|
|
1156
|
+
| `closeOnClickOutside` | `boolean` | `false` | For `multipleList` dropdown, closes the options panel when clicking outside |
|
|
1157
|
+
|
|
1158
|
+
#### Chips example
|
|
1159
|
+
|
|
1160
|
+
```tsx
|
|
1161
|
+
{
|
|
1162
|
+
id: "weather",
|
|
1163
|
+
name: "Weather",
|
|
1164
|
+
type: "multipleList",
|
|
1165
|
+
listView: "chips",
|
|
1166
|
+
listSelection: ["Sunny", "Cloudy", "Drizzle", "Rainy", "Thunderstorm"],
|
|
1167
|
+
listNewValue: true,
|
|
1168
|
+
listNewValueLabel: "+ Other",
|
|
1169
|
+
disabledAutoSelect: true,
|
|
1170
|
+
}
|
|
1171
|
+
```
|
|
1172
|
+
|
|
1173
|
+
This renders all weather options as toggleable chips. Users can select multiple and also add custom values via the `+ Other` chip.
|
|
876
1174
|
|
|
877
1175
|
### Feeds Settings
|
|
878
1176
|
|
|
1177
|
+
Under `bareNewDTW` the feeds tab renders `NewFeeds` (timeline card that matches NewList's row geometry) with the shared `NewPagination` footer; tapping a row opens the record's read view, the pencil / trash actions stay in the row. Without the flag the legacy `Feeds` renders as before.
|
|
1178
|
+
|
|
879
1179
|
| Name | Type | Description |
|
|
880
1180
|
| ----------------- | ------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- |
|
|
881
1181
|
| `title` | `string` | Column ID for feed item title |
|
|
@@ -901,3 +1201,17 @@ Injects custom React components and callbacks into the list, read, and update vi
|
|
|
901
1201
|
| `title` | `string` | Column ID for map marker info window title |
|
|
902
1202
|
| `address` | `string` | Column ID for marker coordinates |
|
|
903
1203
|
| `group` | `string` | Column ID to group markers by colour |
|
|
1204
|
+
|
|
1205
|
+
**Stories** — four groups under `Data / Data Wrapper`: **View** (list, read, drawer, grouped
|
|
1206
|
+
sections, scroll paging), **Edit** (CRUD, inline-edit matrix), **Utils** (flex filters, hidden
|
|
1207
|
+
columns, persisted view state, SSE live) and **Consumer Fixtures** below.
|
|
1208
|
+
Every story mocks its own API and opens without a server.
|
|
1209
|
+
|
|
1210
|
+
**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
|
|
1215
|
+
the update form under the three things `bareUpdateActionComponent` can return (undefined /
|
|
1216
|
+
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.
|