@ai-matrx/records-ui 0.30.0 → 0.38.0
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 +255 -0
- package/README.md +3 -3
- package/dist/index.cjs +3834 -2242
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +205 -29
- package/dist/index.d.ts +205 -29
- package/dist/index.js +3829 -2208
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,260 @@
|
|
|
1
1
|
# Changelog — @ai-matrx/records-ui
|
|
2
2
|
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
## 0.38.0 — 2026-09-20
|
|
6
|
+
|
|
7
|
+
**0.37.0's gate went red on the tarball, not on this package.** The packed
|
|
8
|
+
consumer imports `@ai-matrx/records` from npm, and the published copy did not
|
|
9
|
+
yet carry `openCaptureQueue` — a door the offline capture screens here already
|
|
10
|
+
call. That is the tarball canary doing exactly its job: green in the monorepo,
|
|
11
|
+
absent for an npm consumer. `@ai-matrx/records` 0.26.0 carries it, and this
|
|
12
|
+
release is the first that can resolve against it.
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
## 0.37.0 — 2026-09-20
|
|
16
|
+
|
|
17
|
+
**Three unhandled rejections were failing the release gate while every test
|
|
18
|
+
passed.** `demo/fixtures/doors.json` had no recorded answer for
|
|
19
|
+
`custom.enrich_cells`, a door the Enrich screens started calling — and the
|
|
20
|
+
recorded-doors fake deliberately REFUSES to invent one, because an empty answer
|
|
21
|
+
there would be a green test about nothing. That refusal arrived as an unhandled
|
|
22
|
+
rejection, so vitest reported `12 passed / 79 passed` and exited non-zero, and
|
|
23
|
+
0.36.0 never reached npm. The fixtures are re-recorded against the live store;
|
|
24
|
+
the suite is now 12 files / 79 tests with no errors.
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
## 0.37.0 — 2026-09-20
|
|
28
|
+
|
|
29
|
+
**The capture sheet, run on a phone, with or without a signal (PRODUCTS row 15).**
|
|
30
|
+
|
|
31
|
+
* `CaptureRun` — a DECLARED capture sheet, one question at a time, big targets,
|
|
32
|
+
the camera and the microphone through `accept`/`capture` (which is what opens
|
|
33
|
+
them on a phone rather than a file browser), and the durable queue from
|
|
34
|
+
`@ai-matrx/records@0.25.0` underneath. The whole sheet is fetched ONCE by
|
|
35
|
+
`custom.capture_open` and everything after that happens on the phone: a
|
|
36
|
+
validation that needs a round trip does not exist in a basement. It never says
|
|
37
|
+
*saved* when it means *queued* — the thank-you screen says which, the waiting
|
|
38
|
+
count is on screen the whole time, and "last synced" is a real moment read from
|
|
39
|
+
the queue. A member who may only look is told in words on the FIRST screen,
|
|
40
|
+
because `may_capture` comes from the door with a sentence attached.
|
|
41
|
+
* `CaptureSheet` gains `sheetId` and delegates to `CaptureRun` when it is given.
|
|
42
|
+
One component, two modes: with a sheet it runs what somebody DECLARED (the crew
|
|
43
|
+
case — twelve people, one round, the same questions); without one it stays the
|
|
44
|
+
ad-hoc capture that guesses which Field a reading goes in, which is right for a
|
|
45
|
+
one-off and wrong for a crew. No second capture component.
|
|
46
|
+
|
|
47
|
+
## 0.36.0
|
|
48
|
+
|
|
49
|
+
**"Not between ten at night and seven in the morning" — the two settings the notify
|
|
50
|
+
editor could not offer, and the summary you can ask to see.**
|
|
51
|
+
|
|
52
|
+
`NotifyRuleEditor` could say WHICH view and, out of a two-word vocabulary, roughly
|
|
53
|
+
how often. There was no way to say "Monday at eight" and no way at all to say when
|
|
54
|
+
NOT to be told, so a subscription that texts on a new lead texted at 03:00. It now
|
|
55
|
+
asks for the cadence (from the store's own catalogue — a picker can never offer a
|
|
56
|
+
word the runner does not act on), the channel, the schedule, and both ends of a
|
|
57
|
+
quiet-hours block, and it says plainly that a send inside those hours is HELD until
|
|
58
|
+
they end rather than dropped.
|
|
59
|
+
|
|
60
|
+
It also stops assembling the Rule itself and writes through `subscriptionDeclare`.
|
|
61
|
+
The store is the one place that knows which cadences the runner honours and which
|
|
62
|
+
quiet hours it can parse, and it refuses the rest by name — so the sentence a person
|
|
63
|
+
reads on a refusal is the store's own.
|
|
64
|
+
|
|
65
|
+
`SubscriptionsPanel` gained the two answers anybody looking at a notifications list
|
|
66
|
+
actually wants: **when the next summary is due** (computed by the same store
|
|
67
|
+
functions the runner uses, so the screen and the runner cannot drift — and absent
|
|
68
|
+
rather than wrong on a muted subscription) and when it last told you anything. Plus
|
|
69
|
+
**"Send me a preview now"**, which renders the summary it would send at this moment
|
|
70
|
+
with what arrived, what left and what changed NAMED. It assembles only: nothing is
|
|
71
|
+
delivered, nothing is recorded and the watermark does not move, so pressing it never
|
|
72
|
+
costs somebody a text and never robs the real Monday summary of a week of news.
|
|
73
|
+
|
|
74
|
+
Needs `@ai-matrx/records` ≥ 0.26.0.
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
## 0.36.0 — 2026-09-20
|
|
78
|
+
|
|
79
|
+
**0.35.0 never reached npm: the demo harness asked the store for ten thousand
|
|
80
|
+
rows in one page.**
|
|
81
|
+
|
|
82
|
+
`custom.read_records` serves at most a thousand rows in one page and now REFUSES
|
|
83
|
+
a bigger ask outright (`22023`, `PAGE-1`) rather than quietly serving fewer —
|
|
84
|
+
which is the right behaviour and exactly the kind of honesty this package is
|
|
85
|
+
built on. The harness's reset asked for 10,000, so it read nothing, threw, and
|
|
86
|
+
took the whole release gate down with it. It pages now, a thousand at a time,
|
|
87
|
+
until a short page says it is done. The ceiling is the store's to raise
|
|
88
|
+
(`custom/page_size_ceiling`); a caller's job is to page.
|
|
89
|
+
|
|
90
|
+
Proven against the LIVE store with the demo server up: `demo/live-smoke.test.tsx`
|
|
91
|
+
green, 1 passed.
|
|
92
|
+
|
|
93
|
+
Also in this release, from 0.34.0/0.35.0 and this lane:
|
|
94
|
+
|
|
95
|
+
- **"Who changed this?" is drawn for a person who cannot edit the cell.**
|
|
96
|
+
`columnForField` chose between the cell shell and a plain value on whether
|
|
97
|
+
there was an EDIT SESSION, and the grid passes `null` there whenever the table
|
|
98
|
+
is not this person's to write — so on a viewer, a portal and every read-only
|
|
99
|
+
embed the control vanished, while `gridEditing.tsx` promised it in its own
|
|
100
|
+
comments. `GridCell` now takes `editing: GridEditing | null`; a null session
|
|
101
|
+
means no editor, and nothing else.
|
|
102
|
+
- The tarball canary names `HistoryPanel`, `CommentThread` and
|
|
103
|
+
`FieldHistoryPanel`, so a screen that is green in the monorepo and absent from
|
|
104
|
+
an npm consumer's tarball is caught at the gate.
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
## 0.35.0
|
|
108
|
+
|
|
109
|
+
**Per-record AI enrichment: the badge on every agent-owned cell, and the panel behind it.**
|
|
110
|
+
|
|
111
|
+
`EnrichBadge` is drawn beside every value a model owns, always — not on hover and
|
|
112
|
+
not behind a toggle, because a value a machine guessed and a value a person typed
|
|
113
|
+
are different facts and the difference has to survive onto the screen. Hovering it
|
|
114
|
+
gives the rest: who, when, what was read, how sure the model was, what it nearly
|
|
115
|
+
said instead, and the one control that matters — taking the cell back. `stale`
|
|
116
|
+
rides beside it as a second WORD rather than a colour, because "this is six weeks
|
|
117
|
+
old" is a sentence and a hue has to be explained every time.
|
|
118
|
+
|
|
119
|
+
`useEnrichCells` fetches a whole page's provenance in ONE `custom.enrich_cells`,
|
|
120
|
+
and `Grid` uses it for the ids it is actually drawing.
|
|
121
|
+
|
|
122
|
+
`EnrichPanel` is rewritten. It was a per-record "refill these fields" button over a
|
|
123
|
+
port nothing bound; it is now the whole of an enrichment in one screen, in the
|
|
124
|
+
order somebody thinks in: what should go in this column · what it may look at ·
|
|
125
|
+
how often to check it again · what it has cost, per run and per row · SEE IT ON
|
|
126
|
+
FIVE ROWS · and only then, turn it on. Setting one up from a column's own menu
|
|
127
|
+
lands here too, so "Let AI fill" is not a button that leads nowhere.
|
|
128
|
+
|
|
129
|
+
`TableSettings` gains that menu entry beside Edit and Remove, and marks a column a
|
|
130
|
+
model already fills in.
|
|
131
|
+
|
|
132
|
+
**BREAKING:** `EnrichPanel` no longer takes `recordId`. It is a panel about a
|
|
133
|
+
COLUMN and its whole Table, which is what "keep this filled in" is about; the old
|
|
134
|
+
signature could only ever refill one record.
|
|
135
|
+
|
|
136
|
+
The package's own gate now resolves `@ai-matrx/records` to the workspace SOURCE
|
|
137
|
+
rather than the last published tarball — before that, a suite could only exercise
|
|
138
|
+
doors already on npm, so every new door arrived untested through the one gate meant
|
|
139
|
+
to catch it.
|
|
140
|
+
|
|
141
|
+
## 0.34.0
|
|
142
|
+
## 0.33.0 — 2026-09-20
|
|
143
|
+
|
|
144
|
+
**"Who changed this?" rendered zero controls for the person most likely to ask
|
|
145
|
+
it.**
|
|
146
|
+
|
|
147
|
+
`gridEditing.tsx` says in its own comments that the cell's history control is
|
|
148
|
+
offered at VIEWER too — "a person who may not edit a cell is exactly the person
|
|
149
|
+
who wants to know who did". `columnForField` did not agree: it chose between the
|
|
150
|
+
cell shell and a plain value on whether there was an EDIT SESSION, and the grid
|
|
151
|
+
passes `null` there whenever the table is not this person's to write. So on a
|
|
152
|
+
viewer, a portal and every read-only embed the shell vanished and took the
|
|
153
|
+
control with it. The shell is now drawn whenever there is an editor OR a
|
|
154
|
+
question to ask, and `GridCell` takes `editing: GridEditing | null` — a null
|
|
155
|
+
session means no editor, and nothing else. `src/who-changed.test.tsx` covers
|
|
156
|
+
it; its load-bearing clause fails on the old gate.
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
## 0.32.0
|
|
160
|
+
|
|
161
|
+
**The import wizard, rebuilt on the store's own import doors (SCR-10 / SCR-N-7).**
|
|
162
|
+
|
|
163
|
+
`ImportWizard` parsed a file and then called `recordWrite` **once per row**. At
|
|
164
|
+
the five thousand rows a real spreadsheet holds that is five thousand HTTP round
|
|
165
|
+
trips; there was no duplicate check, so importing a corrected file made a second
|
|
166
|
+
copy of everything; nothing recorded that a value came from a file; and a
|
|
167
|
+
refusal carried a row NUMBER into a file the screen no longer had, so "row 3,184
|
|
168
|
+
was refused" was information nobody could act on. `onProposeField` handed a
|
|
169
|
+
header to a callback and the platform forgot about it.
|
|
170
|
+
|
|
171
|
+
The bytes are still parsed here — Postgres cannot unzip a workbook — and
|
|
172
|
+
**everything after the parse is the store's**:
|
|
173
|
+
|
|
174
|
+
- **The plan, before anything is written.** `importPlan` answers what each
|
|
175
|
+
column is, reading the parity map AND this organization, and the screen shows
|
|
176
|
+
the kind, the store's own sentence saying why, and the first values. Every
|
|
177
|
+
column's destination is a dropdown a person can change, and what they change
|
|
178
|
+
is what the store is sent.
|
|
179
|
+
- **A duplicate key, chosen on the screen** ("same row means the same …"), with
|
|
180
|
+
"leave it alone" or "bring it up to date".
|
|
181
|
+
- **Batches of 250** through `importRows`, with a live count, and **one outcome
|
|
182
|
+
per row**: landed, already here, or refused **with the store's own sentence
|
|
183
|
+
and the row from the person's own file** beside it. The outcome table filters
|
|
184
|
+
to refused / already-here and is the click-through SCR-10 asks for.
|
|
185
|
+
- **The same file twice writes nothing.** The file's sha-256 is the run's
|
|
186
|
+
identity; the screen shows when it ran and what landed, and never sends a row.
|
|
187
|
+
Where Web Crypto is genuinely absent the screen SAYS it cannot recognise the
|
|
188
|
+
file again rather than inventing a hash.
|
|
189
|
+
- **Columns this table does not have go to the ONE approvals inbox** by default,
|
|
190
|
+
and the screen says so on the control itself. "Add them straight away" is
|
|
191
|
+
offered only to an admin and is **absent, not disabled,** for anybody else —
|
|
192
|
+
who are not stuck, because the default still files their column.
|
|
193
|
+
- **One word per type, everywhere.** The wizard reads `FIELD_TYPE_CHOICES`, the
|
|
194
|
+
same list the "Add field" panel offers, so a column is "Money" in both places.
|
|
195
|
+
|
|
196
|
+
`ImportWizardProps.onProposeField` is **gone**: the offer is now a real change
|
|
197
|
+
waiting in a real queue, not a callback the host had to invent a home for. Both
|
|
198
|
+
existing call sites (`TablesHome`, `TablePage`) already pass only `tableId` and
|
|
199
|
+
`onDone`.
|
|
200
|
+
|
|
201
|
+
New in the blocking gate: `src/import-wizard.test.tsx`, five clauses against
|
|
202
|
+
door answers recorded from the live store. Its red twin is `demo/import.red.tsx`
|
|
203
|
+
(the screen as it was), which fails on all three arms.
|
|
204
|
+
|
|
205
|
+
Requires `@ai-matrx/records` >= 0.19.0.
|
|
206
|
+
## 0.31.0
|
|
207
|
+
|
|
208
|
+
**A record's past is a list of VERSIONS, and an agent names the person it acted for.**
|
|
209
|
+
|
|
210
|
+
`HistoryPanel` listed each field's LATEST value with the author of the last
|
|
211
|
+
write beside it. Useful, and not a history: it could not say what a price was
|
|
212
|
+
before, when it changed, what else changed with it, or put any of it back. It
|
|
213
|
+
reads `custom.record_history` now — one line per VERSION, newest first, each
|
|
214
|
+
naming who, when, the operation in the word somebody used, and every field that
|
|
215
|
+
moved with its before and its after, the Rule version that produced a derived
|
|
216
|
+
value and the evidence behind it. Keyboard-first: Up and Down walk the versions,
|
|
217
|
+
Enter opens one, R starts a restore.
|
|
218
|
+
|
|
219
|
+
**The put-it-back action names what will change before it does.** Pressing
|
|
220
|
+
Restore asks the store what the write would do and shows it — *"Price 1,100 →
|
|
221
|
+
1,200, Notes cleared"* — and only the second press writes. It says out loud that
|
|
222
|
+
the write is a new version and nothing in the chain is erased, which is the
|
|
223
|
+
thing people are afraid of about an undo button.
|
|
224
|
+
|
|
225
|
+
**`FieldHistoryPanel` is new: "who changed this?", asked of a CELL.** Every grid
|
|
226
|
+
cell now carries the question (a quiet control on hover or focus, and `H` from
|
|
227
|
+
the keyboard at viewer too — a person who may not edit a cell is exactly the
|
|
228
|
+
person who wants to know who did), and the answer is that COLUMN's history
|
|
229
|
+
across the whole Table, with "put this one back" on each row.
|
|
230
|
+
|
|
231
|
+
**`CommentThread` stops keeping its own store.** It declared a package-owned
|
|
232
|
+
system Table called `records_ui_comment` into whichever organization opened the
|
|
233
|
+
screen — the same second store lane FORMS removed for forms and lane DASHBOARDS
|
|
234
|
+
removed for dashboards — and here the rung was wrong in BOTH directions: a
|
|
235
|
+
`commenter` could not comment at all, and anybody with write on the package's
|
|
236
|
+
comment Table could comment on a record they may not open. It reads
|
|
237
|
+
`custom.comment_thread` and writes `custom.comment_write` now, with the people
|
|
238
|
+
NAMED, a comment anchored to one Field, resolve and re-open, and an `@` mention
|
|
239
|
+
picked from the organization's own roster. Whether this person may comment is
|
|
240
|
+
the STORE'S answer, in the same call that answers the thread.
|
|
241
|
+
|
|
242
|
+
**Two defects the SCREENSHOTS found**, neither visible to a test, a type or a
|
|
243
|
+
door: a version's timestamp rendered `9/20/2026, 7:12:37 AM` and wrapped onto two
|
|
244
|
+
lines, doubling the height of every row — it is a relative time now (`12 minutes
|
|
245
|
+
ago`, `Tue 14:12`, then a date) with the exact moment on hover, which is what
|
|
246
|
+
Linear and Notion do and is also what fits. And the cell's "who changed this?"
|
|
247
|
+
control was `display:none` until hover, so it was unreachable by the keyboard
|
|
248
|
+
and invisible to anything driving the screen; it is `opacity-0` now and appears
|
|
249
|
+
on hover OR focus.
|
|
250
|
+
|
|
251
|
+
**Consumer action:** `COMMENT_TABLE` is gone — it described a store that no
|
|
252
|
+
longer exists and nothing outside this package used it. `HistoryPanel` gains an
|
|
253
|
+
optional `onAskAboutField`, `CommentThread` an optional `fieldKey`, and `Grid`,
|
|
254
|
+
`ViewSwitcher` and `columnForField` an optional `onAskWhoChanged`; every one is
|
|
255
|
+
additive and absent means the control is not drawn. Needs
|
|
256
|
+
`@ai-matrx/records` >= 0.18.0.
|
|
257
|
+
|
|
3
258
|
## 0.30.0
|
|
4
259
|
|
|
5
260
|
**The notification editor stops asking for the notifier's own reader.**
|
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# @ai-matrx/records-ui
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
The platform's primary record UI components. Every component here reads and
|
|
4
|
+
writes ONLY through [`@ai-matrx/records`](../records/README.md), renders with
|
|
5
|
+
`@ai-matrx/design-system`'s own primitives and data table, and carries
|
|
6
6
|
`@ai-matrx/alchemy`'s menu where a person reaches for one.
|
|
7
7
|
|
|
8
8
|
There is no bespoke per-feature record UI in this platform. A feature that needs
|