@ai-matrx/records-ui 0.84.7 → 0.85.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +358 -15
- package/dist/index.cjs +8550 -4375
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +484 -177
- package/dist/index.d.ts +484 -177
- package/dist/index.js +8606 -4361
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,363 @@
|
|
|
1
1
|
# Changelog — @ai-matrx/records-ui
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## Unreleased — lane DATA-V2-FACE (2026-09-24)
|
|
4
|
+
|
|
5
|
+
* **A table opens the way it was designated, and its face is one row.** `TablePage` draws, above the
|
|
6
|
+
records, only the saved-views bar (when the table has two or more views, or the person asked for it),
|
|
7
|
+
and on the right ONE cluster: the layout chooser (only when nothing is designated; in the menu on a
|
|
8
|
+
phone), the view's filter (absent over a host layout, which reads its own records), New record on a
|
|
9
|
+
board, whatever the menu opened (pressed; pressing it closes it), Share, and the table menu. The menu
|
|
10
|
+
holds everything that was fourteen buttons in a row: Add field, Dashboards, Archived, Forms, Bookings,
|
|
11
|
+
Checklists, Notifications, Portals, Inbox, Import, Export (now a rail), Settings, the other layouts
|
|
12
|
+
when one is designated, and the saved views. Owner, 2026-09-24: "not confusing with 1,000 options…
|
|
13
|
+
just shows them the way it should in the default view."
|
|
14
|
+
* **Designation** (`designatedLayoutOf`, `tableOpening`, `SavedView.designatedLayout`): the default view
|
|
15
|
+
names a layout the host draws (`layout: "sheet"`), or is the older table's own default view the mover
|
|
16
|
+
carried in (`moved_from.kind = "default_view"`), which reads as the Sheet and as the table's default
|
|
17
|
+
(no second "All records" is seeded beside it). A package layout (`grid`, `kanban`…) never designates,
|
|
18
|
+
because a click writes those; on a designated table a layout picked from the menu is for the visit and
|
|
19
|
+
is never written over the designation.
|
|
20
|
+
* `ViewSwitcher` takes `chooser={false}` (the page draws the choice) and `openExport`; a host layout's
|
|
21
|
+
`render` receives `openExport`, so the Sheet's "Export this table…" opens the page's own export.
|
|
22
|
+
`ViewBar` takes `quietWhenAlone` and `onViews`.
|
|
23
|
+
* Tests: `a-table-opens-the-way-it-was-designated.test.tsx` (RED 3/3 against the pre-lane page, GREEN
|
|
24
|
+
8/8); `every-table-can-reach-its-archive.test.tsx` now reaches Archived through the menu.
|
|
25
|
+
|
|
26
|
+
## Unreleased — lane SC-1-TAILS (2026-09-24)
|
|
27
|
+
|
|
28
|
+
* **`WhereItLives`** — the one chip for "Lives in <organization>" and moving a table, moved here from matrx-frontend
|
|
29
|
+
so every host (and `TablesHome`) mounts the same builder. The consequence is said in the panel before "Move it";
|
|
30
|
+
a refusal shows the store's sentence and says nothing moved. Needs the unreleased `@ai-matrx/records`
|
|
31
|
+
`tableHome` / `tableMove`.
|
|
32
|
+
* **`TablesHome`**: what the app keeps for itself sits behind one **Show everything** control that says how many
|
|
33
|
+
there are, each kept table carries the store's `keeper_says`, and every row carries a quiet organization chip
|
|
34
|
+
(new optional `organizationName` prop; absent, the list asks the store once).
|
|
35
|
+
* **Consumer action:** matrx-frontend passes `organizationName` to `TablesHome` in `OrganizationHub.tsx` and swaps
|
|
36
|
+
its three `WhereItLives` call sites to this export.
|
|
37
|
+
|
|
38
|
+
## 0.85.4 (2026-09-24 — published by PUBLISH-SWEEP-5; folds every section below down to 0.84.8)
|
|
39
|
+
|
|
40
|
+
**0.85.3 never reached npm** (the release run's automatic tag, run 36064683447): every test passed
|
|
41
|
+
and vitest exited red on unhandled rejections again, this time from `TableSettings.hooks.test.tsx`,
|
|
42
|
+
whose double never answered `row_actions` (GRID-TAILS' section) or `table_decorations` (the one
|
|
43
|
+
colour resolver). It now answers both with what the live store says for a table without actions or
|
|
44
|
+
colours. The gate was proven with zero unhandled errors on an origin/main export before this tag.
|
|
45
|
+
|
|
46
|
+
**Needs `@ai-matrx/design-system` 0.39.0** (S4's `toggleSelection`). 0.85.2's tag (run 35969941639)
|
|
47
|
+
passed every test and failed the packed-consumer canary because the board imports
|
|
48
|
+
`toggleSelection`, which design-system 0.38.1 does not export; 0.39.0 was published first this time.
|
|
49
|
+
|
|
50
|
+
**0.85.1 was tagged and never reached npm either** (run 35967872646): every test passed, and vitest
|
|
51
|
+
still exited red on 15 unhandled rejections. The grid and the board began asking
|
|
52
|
+
`custom.table_decorations`, `custom.grid_layout` and `custom.row_actions`, which the deterministic
|
|
53
|
+
gate's recordings never held, and S4's `many-at-once` double never modelled `table_decorations`. The
|
|
54
|
+
recordings now carry the live store's answers for those three doors (read as test@test.com), and the
|
|
55
|
+
double answers an undecorated table (`7b4d49b3ad`). Nothing in the shipped code changed.
|
|
56
|
+
|
|
57
|
+
**0.85.0 was tagged and never reached npm** (run 35966710984): the publish gate lost a race in
|
|
58
|
+
`a-table-can-start-from-a-real-example.test.tsx`, which counted the example cards after 20
|
|
59
|
+
zero-delay ticks while they still loaded; it now waits for the cards (`5da1344ffc`). 0.85.1 also
|
|
60
|
+
carries DEFAULT-GRID-PARITY's export fix (`3443eb823e`, an export writes a relation's words).
|
|
61
|
+
|
|
62
|
+
**Needs `@ai-matrx/records` 0.58.0** (published first). One publish carries everything since 0.84.8:
|
|
63
|
+
source versions 0.84.9 and 0.84.10 were never published on their own and are folded below, and
|
|
64
|
+
"0.84.11" in UI-QUICK-1's correction line is this release. Also in it without a section of their
|
|
65
|
+
own: S0 ONE-SAVED-VIEW (the view bar reads and writes `platform.saved_view`, `5367edd12e`) and
|
|
66
|
+
S2-PRIME FILTER-GROUPS (nested conditions in the one condition builder and a view's own
|
|
67
|
+
`definition.where`, `0efe199849` / `1ef813282e` / `54a23e5608`; S1-PRIME's `c58088eecc` stops a
|
|
68
|
+
table's saved views being re-read many times a second). Some of these bytes reached main through the
|
|
69
|
+
integrator's sweeps (`79b505cfa5`, `9a6618f2d0`, `452e363c2e`) rather than their lanes' own commits.
|
|
70
|
+
|
|
71
|
+
### Lane GRID-TAILS (2026-09-24)
|
|
72
|
+
|
|
73
|
+
* **An owner writes the table's own buttons (TABLE-PARITY M4).** Table settings gains a "Row actions"
|
|
74
|
+
section (`RowActionsEditor.tsx`, `RowActionsSection`): list the table's actions in its order with a
|
|
75
|
+
plain sentence each, add one ("Changes the record" with its column changes — set to, clear, work out
|
|
76
|
+
from a formula — or "Asks an agent" with the words to ask), edit, move up and down, and retire (the
|
|
77
|
+
consequence is named first; "Put it back" restores it at the same place with the same id). Start
|
|
78
|
+
from a record turns a real record's values into the changes; the before-and-after preview shows the
|
|
79
|
+
chosen record column by column, and a worked-out column says it is worked out when the action runs.
|
|
80
|
+
Every change is one `custom.action_declare` with the whole list; a store refusal is shown under the
|
|
81
|
+
form and what was typed stays. Same controls as the field panel. Suite
|
|
82
|
+
`an-owner-writes-the-tables-own-buttons.test.tsx`: RED 6 on the bytes without the section, GREEN 8.
|
|
83
|
+
* **A button declared in settings appears on the grid beside it without a reload.** `rowActionsChanged(tableId)`
|
|
84
|
+
(gridActions.tsx): every mounted `useTableActions` of that table reads `custom.row_actions` again after a
|
|
85
|
+
declare. Test RED without the listener, GREEN with it.
|
|
86
|
+
|
|
87
|
+
### Lane S1-PRIME VIEW-KEYS (2026-09-24)
|
|
88
|
+
|
|
89
|
+
* **Every per-view setting is a declared key of the one saved view.** `viewKeys.ts`: `VIEW_KEYS` mirrors
|
|
90
|
+
the store's registry `custom.view_keys()` (path, shape, the layouts that read it, who writes it);
|
|
91
|
+
`viewSettings(definition)` is THE reader `viewFromRow` goes through; `viewSettingsFor(view, layout)`
|
|
92
|
+
hands a layout only the keys it reads; `viewSettingsPatch` is the writer's shape `saveViewPatch` sends.
|
|
93
|
+
* `SavedViewSpec` gains `swimlaneField` (board swimlanes) and `collapsedColumns` (board columns kept shut);
|
|
94
|
+
`GridGrouping` gains `then` (up to two sub-group levels) and keeps it when the look is written back whole
|
|
95
|
+
— a colour change no longer erases sub-groups.
|
|
96
|
+
* **A page open never writes.** `ViewBar`'s default seed is a read, then a declare only on absence: a table
|
|
97
|
+
with a default view of any name (a renamed "All records") is opened without a write, and the loader no
|
|
98
|
+
longer re-runs on every parent render (a host passing `seed={[…]}` inline re-read the views in a loop).
|
|
99
|
+
Exported `seedIsSatisfied`.
|
|
100
|
+
|
|
101
|
+
### Lane S4 BATCH-DOORS (2026-09-24)
|
|
102
|
+
|
|
103
|
+
* **The board takes many cards at once.** `PipelineBoard`: cmd/ctrl-click takes one card, shift-click
|
|
104
|
+
takes the run (the data table's own `toggleSelection` rule, now in `@ai-matrx/design-system`), `x`
|
|
105
|
+
takes the focused card, shift+arrow extends, Esc clears. A bulk bar says "N cards selected" with
|
|
106
|
+
"Move N to…" and one menu item per stage ("Move 6 to Scheduled"); it sends each card's loaded version
|
|
107
|
+
in ONE call and paints each refused card with its own sentence (needs a column, changed since loaded,
|
|
108
|
+
no right). A Viewer can select nothing, so a Viewer never sees the bar.
|
|
109
|
+
* **The inbox decides many at once.** `ActionInbox`: a checkbox per actionable item, shift-click for a
|
|
110
|
+
run, "Approve N" / "Decline N" in the same bar; `x` selects, `a`/`d` act on the selection. One call,
|
|
111
|
+
one sentence back ("6 approved."), and each item that was not decided says why.
|
|
112
|
+
* Headless two-seat walk on the dev clone: `demo/batch-doors-walk.mjs` (serve with
|
|
113
|
+
`demo/vite.walk.config.ts` so a peer's save does not reload the page mid-walk).
|
|
114
|
+
|
|
115
|
+
### Lane S6 PORTAL-BRANDING (2026-09-24)
|
|
116
|
+
|
|
117
|
+
**A portal carries the business's own look and its forms** (UI-CHAMPIONS rows 45, 46, 55; champions
|
|
118
|
+
Softr's branded portal and the Stripe customer portal).
|
|
119
|
+
|
|
120
|
+
* **`PortalLookEditor`** (new export), shown inside every portal card in `PortalsPanel`: the name
|
|
121
|
+
clients see (empty = the organization's), a welcome line, a logo chosen from the organization's
|
|
122
|
+
own PUBLIC pictures (`card.logo_candidates`), a colour from the design system's seven names (the
|
|
123
|
+
same swatches the table highlights use), footer links (`https://`, `mailto:`, `tel:`), and every
|
|
124
|
+
form on the tables the portal shows — tick to offer it, optional button words, Up/Down order. Saved
|
|
125
|
+
through `portalDeclare({ …, config })`, re-stating the portal exactly as the card read it; the
|
|
126
|
+
store's refusal is drawn by `RefusalNotice`.
|
|
127
|
+
* **`PortalCardViewProps.look`** — the slot the editor renders in (absent = none offered).
|
|
128
|
+
|
|
129
|
+
**Consumer action:** needs `@ai-matrx/records` with `PortalCard.config/style/forms/accents/logo_candidates`
|
|
130
|
+
and `portalDeclare({ config })` (aidream `4bf803c452`), and the S6 store doors on the database.
|
|
131
|
+
|
|
132
|
+
### Lane SC-R (2026-09-24; landed by DEFAULT-GRID-PARITY)
|
|
133
|
+
|
|
134
|
+
* `EntityReferenceControl` (chips of what an entity-reference value names, withheld words said,
|
|
135
|
+
take-off, no add control until the store has a search door), `EntityReferenceKindPicker`,
|
|
136
|
+
`entityReferenceSpec`, `whatIsMissingForEntityReference`; an entity-reference cell reads as its
|
|
137
|
+
words instead of `[object Object]`.
|
|
138
|
+
* The field panel asks an entity-reference column which kinds it points at, sends
|
|
139
|
+
`allowed_types`, and shows an existing column's kinds locked. The menu entry "Points at
|
|
140
|
+
something else on the platform" is drawn only once `custom.field_kinds()` publishes
|
|
141
|
+
`entity_reference` (after the chair's apply and `pnpm records:generate`).
|
|
142
|
+
|
|
143
|
+
### Lane DEFAULT-GRID-PARITY (2026-09-24)
|
|
144
|
+
|
|
145
|
+
**The default grid shows what the store holds** (TABLE-PARITY, "in the store but not shown by the
|
|
146
|
+
default grid"). Each item is read through the store's own door and drawn through the data table's
|
|
147
|
+
own seams (`rowActions`, `selection`, `defaultSort`, `footerRows`, `rowHeight`, `copy`), with no
|
|
148
|
+
second table. A control the store cannot serve for a table is absent, never dead.
|
|
149
|
+
|
|
150
|
+
* **Row actions (M1–M3).** A table's own actions (`custom.row_actions`) are one-click buttons on
|
|
151
|
+
every row, and on the selection bar for the ticked rows. One press is ONE `custom.action_run`,
|
|
152
|
+
and it asks first when the action says to. A refusal names the record and the column. Undo writes
|
|
153
|
+
back what each row held. An `agent` action hands the row and its prompt to the new optional host
|
|
154
|
+
port `runAgentAction`, and is absent when the host does not bind it. Readers get no buttons.
|
|
155
|
+
* **The table's default sort (S2).** `data.default_sort` (`[{field, direction}]`; older spellings
|
|
156
|
+
also read) is where the grid opens.
|
|
157
|
+
* **Summary bar (F1).** Under each column, a summary the view keeps (`presentation.summaries`),
|
|
158
|
+
worked out by `custom.record_aggregate` over the whole table. It offers only the measures
|
|
159
|
+
`custom.agg_operations` lists that mean something for that column.
|
|
160
|
+
* **Layout knob (D1 D5 D6).** Row height, freeze first column, wrap and fit/scroll are read from the
|
|
161
|
+
organization's `custom/grid_layout`, and the view's own choice wins (`presentation.wrap`, `fit`,
|
|
162
|
+
`freezeFirst`). A Layout menu says where each choice came from.
|
|
163
|
+
* **Formula columns (K1 K2).** A worked-out column's header carries an `fx` mark with what it is
|
|
164
|
+
worked out from. The field panel writes a formula in the language a person types
|
|
165
|
+
(`formula_text`, checked live by `custom.formula_parse`) and can re-aim an existing one.
|
|
166
|
+
* **System columns (H2 H3).** The field menu offers Record number, Created time and Last changed
|
|
167
|
+
time (the store's `autonumber` / `created_time` / `modified_time` words). A new record-number
|
|
168
|
+
column numbers the records already there through `custom.autonumber_backfill`, and says so if it
|
|
169
|
+
was refused.
|
|
170
|
+
* **Duplicate a row (A7)**: the typed values only, never the worked-out ones.
|
|
171
|
+
* **A reference for a prompt (R3)**, beside Copy: named by the row label, carrying the table and
|
|
172
|
+
row ids.
|
|
173
|
+
* **Webhooks in the Notifications rail (N3)**: list, delivery health, start one (the signing
|
|
174
|
+
secret is shown once), archive. A reader gets no controls.
|
|
175
|
+
* **Start from an example (P2)** on the tables home: builds a registered real use case through
|
|
176
|
+
`custom.table_from_example`.
|
|
177
|
+
* **A row opens its record (VERIFIER-17).** An editable grid's cells are each their own control, so
|
|
178
|
+
a row click never fired and nothing opened the record. The first cell of every row now carries an
|
|
179
|
+
Open control, named for the record and always reachable by keyboard and touch. Space on any
|
|
180
|
+
focused cell opens that row's record, and Enter still edits. Absent when the host cannot open a
|
|
181
|
+
record (`onOpenRecord`). Kanban, calendar and gallery cards already opened on click.
|
|
182
|
+
* **An export writes what the grid shows (GRID-PORT finding).** CSV and XLSX used to write a
|
|
183
|
+
relation's stored record id. They now write the words the grid draws for it: the same resolver
|
|
184
|
+
(`useRecordLabels`), and `relation_words_many` for any id no cell on screen has drawn yet. An id
|
|
185
|
+
nobody can resolve stays the id rather than a blank. Choice cells carry their labels, and a
|
|
186
|
+
worked-out column carries the store's value.
|
|
187
|
+
* **No machine "…ss" plurals (VERIFIER-16/17 M3).** `realPlural` and `pluralNoun` (`names.ts`): a
|
|
188
|
+
`label_plural` that is only the name with an "s" appended ("Customerss", "Status optionss") is
|
|
189
|
+
never shown, and a sentence's noun never doubles a final "s". The stored values come from the
|
|
190
|
+
store's `name || 's'` fallback. That root is the store's to fix.
|
|
191
|
+
|
|
192
|
+
### Lane S3 (2026-09-24)
|
|
193
|
+
|
|
194
|
+
**Period comparison, date grain and targets on the dashboard canvas** (UI-CHAMPIONS-PLAN rows 17,
|
|
195
|
+
18, 20). Needs `@ai-matrx/records` with `recordAggregate({compare})` / `dashboardRun({compare,
|
|
196
|
+
grain})` and the store's `uichamp_s3_*` files; on a store without them nothing new is drawn.
|
|
197
|
+
|
|
198
|
+
* **A number tile shows the trend and the target.** A block the store compared (`block.compare`)
|
|
199
|
+
shows its total with an arrow and signed percent against the prior window ("16,930 ▼ -7.9% —
|
|
200
|
+
September 2026 · 18,380 in August 2026"), and a block with a `target` draws a progress ring
|
|
201
|
+
("Monthly target 25,000 · 68%"). The arrow is coloured only when the block declares a target (the
|
|
202
|
+
one declared fact that says up is good); otherwise it is the neutral tone.
|
|
203
|
+
* **A compared chart draws the prior period behind the current one** in the palette's new
|
|
204
|
+
comparison tone (`COMPARISON_COLOR`, `--muted-foreground`), with a legend naming both windows and a
|
|
205
|
+
dashed goal line (`GOAL_COLOR`) at the target's pace per bucket. A quiet week inside the window is
|
|
206
|
+
dated ("Week of Sep 27"); only a position past the window's last bucket is named by its place.
|
|
207
|
+
* **A date-grain picker on the canvas** ("By the saved grain" / day / week / month / quarter / year),
|
|
208
|
+
shown only when a block runs along a date; it re-cuts every bucketed block through
|
|
209
|
+
`dashboard_run(p_grain)`, in the organization's own time zone and week start.
|
|
210
|
+
* **Buckets are named in the organization's calendar** (`bucketName`, `windowName`,
|
|
211
|
+
`positionBucket`), read from the store's local ISO moment and never from the browser's clock.
|
|
212
|
+
* **Drill-through on a bucket opens that period of its date Field** (`bucketWindow`) — it used to ask
|
|
213
|
+
for a Field called `completed_on_week`, which matched nothing — and a compared block opens its
|
|
214
|
+
current window only.
|
|
215
|
+
* Harness: `RECORDS_UI_DEMO_TABLE` opens every page on an existing Table and writes nothing of its
|
|
216
|
+
own into that organization; `demo/walk-s3-periods.mjs` walks the canvas headless from two seats.
|
|
217
|
+
|
|
218
|
+
**Added at publish (S3's lines, owed because the file held another lane's uncommitted edits):**
|
|
219
|
+
|
|
220
|
+
* **The owner's canvas is the owner's from its first frame.** `DashboardCanvas` shows its skeleton
|
|
221
|
+
until the rights answer (`custom.my_levels`) is in, instead of drawing the blocks first with no
|
|
222
|
+
controls.
|
|
223
|
+
* **Per-block compare and target editor** in each block's settings row (the same `Select` /
|
|
224
|
+
`BasicInput` as the grouping picker): no comparison / the period before / the same period last
|
|
225
|
+
year, the period, and no target / a target number / a goal column (number, money and percent
|
|
226
|
+
columns only). Absent on a list that does not move and, for compare, on a table with no date column.
|
|
227
|
+
* **A target read from a goal column** (`target {field, op: sum|avg|min|max}`): a reader who may not
|
|
228
|
+
read that column sees the store's sentence in place of the target and the block still draws its number.
|
|
229
|
+
|
|
230
|
+
### Also in this release
|
|
231
|
+
|
|
232
|
+
**Lane S7-PRIME — a stranger starts from a link that already knows something, stops, comes back
|
|
233
|
+
on another device, and leaves by the owner's door (UI-CHAMPIONS-PLAN rows 34, 35, 40).**
|
|
234
|
+
|
|
235
|
+
* **Prefill.** `FormRunner` takes `initialAnswers`: the form starts with those answers in their
|
|
236
|
+
questions, changeable, and hands them to `whichAsked` like typed answers, so a question that
|
|
237
|
+
depends on a prefilled one branches exactly as if the person had typed it.
|
|
238
|
+
* **Keep my place.** `FormRunner` takes `onAnswersChange` — every change to the answers after the
|
|
239
|
+
first paint, for the host to keep (the public page saves it through `custom.form_draft_save`).
|
|
240
|
+
A form resumed part-way opens on the first question still waiting for an answer.
|
|
241
|
+
* **The thank-you screen leaves by the owner's door.** `FormSpec.thankYou` is now `FormThankYou`
|
|
242
|
+
(`title`, `body`, `redirectUrl`, each optional); the runner shows the message, then goes on to
|
|
243
|
+
`redirectUrl` a moment later with a "Go now" link beside it (a preview never leaves and says
|
|
244
|
+
where the live form would go). The store judges the address — a secure page on the
|
|
245
|
+
organization's own sites — so the runner never does. `formPresentation` / `formFromSummary`
|
|
246
|
+
carry it as `presentation.thank_you.redirect_url` through `thankYouDocument` /
|
|
247
|
+
`thankYouFromDocument`; an empty thank-you is `null`.
|
|
248
|
+
* **`FormBuilder`** gains an "After somebody sends it" section beside the notify editor: title,
|
|
249
|
+
message and "Then go to (optional)". A foreign address is refused on Save in the store's words,
|
|
250
|
+
naming the sites it may use.
|
|
251
|
+
|
|
252
|
+
**Consumer action:** matrx-frontend's `PublicFormRunner` hands `whichAsked`, `initialAnswers` and
|
|
253
|
+
`onAnswersChange` through a spread and casts the spec so it compiles on 0.84.8; on adopting this
|
|
254
|
+
version, import `FormAsked`, pass the three ports by name and drop the cast.
|
|
255
|
+
|
|
256
|
+
**Added at publish (S7-PRIME's lines, owed for `ec860af7ac` and `cd33e86359`):**
|
|
257
|
+
|
|
258
|
+
* `resumed`: only a saved place being resumed opens on its first unanswered question; a link that
|
|
259
|
+
only prefills opens on question one with the prefilled answer in place.
|
|
260
|
+
* FormBuilder: a write the store refuses (Save, publish, notify choice, New form) shows the store's
|
|
261
|
+
words above the builder with Keep editing / Discard; only a failed load replaces the screen.
|
|
262
|
+
|
|
263
|
+
### Lane UI-QUICK-1 (TABLE-PARITY review)
|
|
264
|
+
|
|
265
|
+
**The class 0.84.9 left open.**
|
|
266
|
+
|
|
267
|
+
* **A table colored at the TABLE level now paints everywhere, not just wherever a view redecorated
|
|
268
|
+
it.** 0.84.9 wired `Card` and `Grid` to a view's own `presentation.style`; it never read G1's
|
|
269
|
+
table-level decorations (`custom.table_decorations` / `client.tableDecorations`) at all, so a
|
|
270
|
+
table whose colors are a `color_by` and a set of rules stored on the TABLE — never on any one
|
|
271
|
+
view — drew nothing on the default grid, the kanban, the calendar or the gallery alike (Arman's
|
|
272
|
+
Coding Accounts table: colored by Account Type, with a MAXED/NEAR rule, no view has ever set its
|
|
273
|
+
own look). New `styleFromDecorations` (`presentation.ts`) translates G1's Field-id-addressed
|
|
274
|
+
decorations into the Field-key-addressed `TableStyle` every reader already understands; new
|
|
275
|
+
`resolveTableStyle` is the ONE presentation resolver — it layers the view's own style over the
|
|
276
|
+
table's decorations piece by piece (a view that set only a manual highlight still inherits the
|
|
277
|
+
table's `colorBy`/`rules`; a view that set its own `colorBy` AND `rules` is not haunted by the
|
|
278
|
+
table's). `Grid` and `ViewSwitcher`'s `Board` (feeding `Kanban`/`Calendar`/`Gallery`/`Card`) both
|
|
279
|
+
fetch the table's decorations once (new `useTableDecorations` hook,
|
|
280
|
+
`tableDecorations.ts`) and both call the same resolver — no second color logic anywhere in this
|
|
281
|
+
package. A table with no decorations and no view style resolves to nothing, exactly as before.
|
|
282
|
+
* Corrects the 0.84.9 changelog entry above, which overclaimed "the table's own colors" when it
|
|
283
|
+
had only wired the view's.
|
|
284
|
+
|
|
285
|
+
### Folded from source version 0.84.10
|
|
286
|
+
|
|
287
|
+
**Lane FORMS-FIX-1 — two screens that lied about forms (UI-BENCH-FORMS gap 1 and its cheapest correctness win).**
|
|
288
|
+
|
|
289
|
+
* **A public form branches the way its owner set it.** `FormRunner`'s public arm had no evaluator,
|
|
290
|
+
so every "ask this only when …" question was shown to every stranger. It now takes a
|
|
291
|
+
`whichAsked` port — the host's server asks the STORE (`custom.form_public_asks`, the same Rule
|
|
292
|
+
through the same `custom.rule_eval`) with the answers so far — and hides exactly what the store
|
|
293
|
+
says to hide, a quarter-second after typing stops. Undecided shows; a condition the store could
|
|
294
|
+
not work out shows WITH the store's sentence. A public mount with no port still says out loud
|
|
295
|
+
that it cannot branch. New exported type `FormAsked`.
|
|
296
|
+
* **"Tell me when somebody answers" is on the form builder.** `notifyRuleId` round-tripped and
|
|
297
|
+
`custom.form_notify` delivered through it, but nothing on the builder could set it. `FormBuilder`
|
|
298
|
+
now mounts `NotifyRuleEditor` beside the link, in a new CHOOSE MODE (`chosenRuleId` /
|
|
299
|
+
`onChoose`): pick a subscription or make one and the form is re-declared with it at once — the
|
|
300
|
+
whole form, so its accept Rule rides back. A table with no saved view offers "Watch every
|
|
301
|
+
record" through the store's own `custom.view_declare`.
|
|
302
|
+
* `NotifyRuleEditor` reads saved views from the store's own `custom.views` door when the host binds
|
|
303
|
+
no `savedViews` port, instead of printing a dead end.
|
|
304
|
+
* **The owner's preview branches too.** The signed-in arm of `FormRunner` (the builder's live
|
|
305
|
+
preview) used to call `custom.rule_eval` from the browser — an internal evaluator no client may
|
|
306
|
+
call — so it printed "You do not have access to this" and never hid a question. It now builds its
|
|
307
|
+
`whichAsked` port from `client.formPreviewAsks` (`custom.form_preview_asks`: the same store loop
|
|
308
|
+
as the public door, behind the organization wall and the person's own rung on the Table), over
|
|
309
|
+
the DRAFT's own questions. The `evaluate` path is gone: one port, one store loop, both arms.
|
|
310
|
+
`FormAsked`'s refusal may carry the store's own `error`. **Needs `@ai-matrx/records` with
|
|
311
|
+
`formPreviewAsks`** (FORMS-FIX-1); until the door is regenerated into `STORE_DOORS` the preview
|
|
312
|
+
shows every question with the store's `door_absent` sentence.
|
|
313
|
+
|
|
314
|
+
**Consumer action:** matrx-frontend's `PublicFormRunner` already hands `whichAsked` through a spread
|
|
315
|
+
so it compiled on 0.84.8; on adopting this version, import `FormAsked` and pass `whichAsked` by
|
|
316
|
+
name.
|
|
317
|
+
|
|
318
|
+
### Folded from source version 0.84.9
|
|
319
|
+
|
|
320
|
+
**Lane UI-QUICK-1 — two gaps from the CALENDAR-GALLERY bench, both cheap wins by design.**
|
|
321
|
+
|
|
322
|
+
* **Every kanban, calendar and gallery card now paints its VIEW's own colors.** `Grid` has
|
|
323
|
+
colored rows (`presentation.style`'s `color_by`, ordered rules, hand highlights) since this
|
|
324
|
+
package's own view-presentation work; the shared `Card` component that draws all three other
|
|
325
|
+
layouts never called the resolver. `Card` now takes an optional `style: TableStyle` and resolves
|
|
326
|
+
it through `resolveRowColor` + `ROW_TINT_CLASS` — the SAME primitive and the SAME class map the
|
|
327
|
+
grid uses, not a second color scheme. `ViewSwitcher` threads `view.presentation?.style` down to
|
|
328
|
+
`Kanban`, `Calendar` and `Gallery`. A table nobody has ever colored, or a `Card` given no `style`
|
|
329
|
+
at all, looks exactly as it did before this version. **Correction (see Unreleased, lane UI-QUICK-1):** this line
|
|
330
|
+
overclaimed — it wired the VIEW's own look only; a table colored at the TABLE level through G1's
|
|
331
|
+
`custom.table_decorations`, with no view ever setting its own `presentation.style` (Arman's
|
|
332
|
+
Coding Accounts table is exactly this shape), still drew nothing here. The Unreleased entry above closes that.
|
|
333
|
+
* **Gallery gets lazy images, a real placeholder, a card-size control and configurable fields.**
|
|
334
|
+
Cover images now carry `loading="lazy"` inside a fixed-height placeholder (`GALLERY_SIZE`), so a
|
|
335
|
+
gallery of hundreds only fetches what scrolls into view and mixed image/no-image records no
|
|
336
|
+
longer jump the grid. A small/medium/large size control is saved on the view as
|
|
337
|
+
`presentation.gallerySize`, the same pattern as the grid's own `rowHeight`. Fields shown are no
|
|
338
|
+
longer hardcoded to the first four — they read `presentation.hiddenFields`, the SAME hidden-
|
|
339
|
+
column set the grid's own column picker holds, so hiding a column anywhere hides it everywhere.
|
|
340
|
+
* `GridPresentation` gains `hiddenFields?: string[]` and `gallerySize?: "small" | "medium" |
|
|
341
|
+
"large"`, parsed and round-tripped the same tolerant way as every other field in
|
|
342
|
+
`parseGridPresentation`/`presentationDocument`.
|
|
343
|
+
|
|
344
|
+
## 0.84.8
|
|
345
|
+
|
|
346
|
+
(lane GRID-PORT `5cb9bcbd99`; published by PUBLISH-SWEEP-4.)
|
|
347
|
+
|
|
348
|
+
**A host can draw a layout beside the package's own four, on the one table page.**
|
|
349
|
+
`RecordsUiHost.layouts?: HostLayout[]` — `{ id, label, render({ tableId, filter }) }`. Each
|
|
350
|
+
appears as a button in `ViewSwitcher`'s layout row after Grid / Kanban / Calendar / Gallery, and
|
|
351
|
+
`?view=<id>` opens it (`openingHostLayout`); `TablePage.onViewChanged` is called with the id.
|
|
352
|
+
Page-level, never written onto the view record (the store's layout words stay the four). A host
|
|
353
|
+
id equal to one of `PAGE_VIEWS` (or a spelling of one) is ignored, so `?view=grid` is always the
|
|
354
|
+
package's Grid. Why: the owner's ruling (2026-09-23) — AI Matrx's ported /data grid is the
|
|
355
|
+
"Sheet" layout of `/data-v2/<table>`, not a second page for the same table.
|
|
356
|
+
|
|
357
|
+
Consumer action: `onViewChanged` now receives `PageView | string`; widen a handler typed
|
|
358
|
+
`(view: PageView) => void`.
|
|
359
|
+
|
|
360
|
+
## 0.84.7 (needs @ai-matrx/records 0.57.3)
|
|
4
361
|
|
|
5
362
|
* **The suite is green again (386/386), and the class is gone rather than patched.** 0.84.5's
|
|
6
363
|
publish gate went red in 15 files because records 0.57.2 made every table list ask
|
|
@@ -1638,9 +1995,6 @@ A table that is not a pipeline draws the plain kanban exactly as before; the
|
|
|
1638
1995
|
decision is the Table's own `stage_field`, asked once, never guessed from the shape
|
|
1639
1996
|
of a Choice column.
|
|
1640
1997
|
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
1998
|
## 0.38.0 — 2026-09-20
|
|
1645
1999
|
|
|
1646
2000
|
**0.37.0's gate went red on the tarball, not on this package.** The packed
|
|
@@ -1650,7 +2004,6 @@ call. That is the tarball canary doing exactly its job: green in the monorepo,
|
|
|
1650
2004
|
absent for an npm consumer. `@ai-matrx/records` 0.26.0 carries it, and this
|
|
1651
2005
|
release is the first that can resolve against it.
|
|
1652
2006
|
|
|
1653
|
-
|
|
1654
2007
|
## 0.37.0 — 2026-09-20
|
|
1655
2008
|
|
|
1656
2009
|
**Three unhandled rejections were failing the release gate while every test
|
|
@@ -1662,7 +2015,6 @@ rejection, so vitest reported `12 passed / 79 passed` and exited non-zero, and
|
|
|
1662
2015
|
0.36.0 never reached npm. The fixtures are re-recorded against the live store;
|
|
1663
2016
|
the suite is now 12 files / 79 tests with no errors.
|
|
1664
2017
|
|
|
1665
|
-
|
|
1666
2018
|
## 0.37.0 — 2026-09-20
|
|
1667
2019
|
|
|
1668
2020
|
**The capture sheet, run on a phone, with or without a signal (PRODUCTS row 15).**
|
|
@@ -1712,7 +2064,6 @@ costs somebody a text and never robs the real Monday summary of a week of news.
|
|
|
1712
2064
|
|
|
1713
2065
|
Needs `@ai-matrx/records` ≥ 0.26.0.
|
|
1714
2066
|
|
|
1715
|
-
|
|
1716
2067
|
## 0.36.0 — 2026-09-20
|
|
1717
2068
|
|
|
1718
2069
|
**0.35.0 never reached npm: the demo harness asked the store for ten thousand
|
|
@@ -1742,7 +2093,6 @@ Also in this release, from 0.34.0/0.35.0 and this lane:
|
|
|
1742
2093
|
`FieldHistoryPanel`, so a screen that is green in the monorepo and absent from
|
|
1743
2094
|
an npm consumer's tarball is caught at the gate.
|
|
1744
2095
|
|
|
1745
|
-
|
|
1746
2096
|
## 0.35.0
|
|
1747
2097
|
|
|
1748
2098
|
**Per-record AI enrichment: the badge on every agent-owned cell, and the panel behind it.**
|
|
@@ -1794,7 +2144,6 @@ question to ask, and `GridCell` takes `editing: GridEditing | null` — a null
|
|
|
1794
2144
|
session means no editor, and nothing else. `src/who-changed.test.tsx` covers
|
|
1795
2145
|
it; its load-bearing clause fails on the old gate.
|
|
1796
2146
|
|
|
1797
|
-
|
|
1798
2147
|
## 0.32.0
|
|
1799
2148
|
|
|
1800
2149
|
**The import wizard, rebuilt on the store's own import doors (SCR-10 / SCR-N-7).**
|
|
@@ -2182,7 +2531,6 @@ through the field panel.
|
|
|
2182
2531
|
|
|
2183
2532
|
None. `presentation` is optional and its absence is today's behavior.
|
|
2184
2533
|
|
|
2185
|
-
|
|
2186
2534
|
## 0.19.1
|
|
2187
2535
|
|
|
2188
2536
|
**The progress bar and the count beside it said different things.** One question
|
|
@@ -2193,7 +2541,6 @@ form, not by reading it. Typeform's bar advances as you move through the form,
|
|
|
2193
2541
|
and now so does this one. On a single page there is no position, so it keeps
|
|
2194
2542
|
measuring what it can: how much is answered.
|
|
2195
2543
|
|
|
2196
|
-
|
|
2197
2544
|
## 0.19.0
|
|
2198
2545
|
|
|
2199
2546
|
**The choice picker reads a document from any era, and writes the contract.**
|
|
@@ -2210,7 +2557,6 @@ falls through and renders as itself.
|
|
|
2210
2557
|
|
|
2211
2558
|
**Consumer action:** none beyond taking 0.19.0 with `@ai-matrx/records` 0.13.0.
|
|
2212
2559
|
|
|
2213
|
-
|
|
2214
2560
|
## 0.18.0
|
|
2215
2561
|
|
|
2216
2562
|
**A person can switch off a notification an agent switched on.** "Make me an
|
|
@@ -2231,7 +2577,6 @@ never say a subscription is off while it keeps firing.
|
|
|
2231
2577
|
None — `TablePage` grew the rail. Needs `@ai-matrx/records` 0.12.0 or above for
|
|
2232
2578
|
`client.subscriptions` and `client.subscriptionMute`.
|
|
2233
2579
|
|
|
2234
|
-
|
|
2235
2580
|
## 0.17.0
|
|
2236
2581
|
|
|
2237
2582
|
**There is one Form object, and it is the one with the link.** `FormBuilder` kept
|
|
@@ -2582,7 +2927,6 @@ import { recordStoreShare } from "@/features/sharing/components/RecordStoreShare
|
|
|
2582
2927
|
Leave it out and nothing changes — the screens render exactly as they did in
|
|
2583
2928
|
0.8.0, with no Share button.
|
|
2584
2929
|
|
|
2585
|
-
|
|
2586
2930
|
## 0.8.0
|
|
2587
2931
|
|
|
2588
2932
|
**The worst finding of the 19 September verdict: "Add field" opened a proper
|
|
@@ -2633,7 +2977,6 @@ A table made with the product's own button had exactly one column.
|
|
|
2633
2977
|
drawing values outside `RecordsMount` should render `<RecordValue>` (or wrap in
|
|
2634
2978
|
`RecordLabelProvider`) so ids resolve to names.
|
|
2635
2979
|
|
|
2636
|
-
|
|
2637
2980
|
## 0.7.0
|
|
2638
2981
|
|
|
2639
2982
|
What the first headless walk of 0.6.0 through a real browser found, in the same
|