Repository navigation
Commit d3b2aaf
<!-- claude-projects-attribution: {"github_login":"os-sales"} -->
_Requested by **Sales** · [project
thread](https://claude.ai/code/project/chan_01D5bWFY3rFzgJcytD5gD4Uu?thread=cmsg_01D5bWFY3rFzgJcytD5gD4UuEHQyuPNhMoPYnP8JdznESK)_
domain:ui#5 · os-sales · session_01L6bhgVzvtWN68zb2r9z2zy
Fixes #30394
Clause-②: yes (narrowing) — `@object-ui/plugin-grid` now exports
`resolveBulkActions` and `useUndeclaredActionNamesWarning` (with the
`ActionLabelResolver`, `NamedActionDef`, `UndeclaredActionNameKey`,
`UndeclaredActionNamesAddress` and `UndeclaredActionNamesBasis` types),
so `@object-ui/plugin-list` reuses the grid's fold and warning instead
of a second copy. The warning's address gains an optional `component`,
defaulting to `ObjectGrid`, so the grid's message is byte-identical.
This PR both widens (those exports) and narrows (the non-grid bar no
longer draws an undeclared bare name), so the arm is `(narrowing)`: seat
patch round on the Check Changeset red, after claim amendment 6658495307
had written `(widening)`. Owes a `TIER_DEFAULT` review for the export
widening and a `CONTRACT_REVIEW_TIER` review for the narrowing below.
Metadata-protocol: narrowed (an undeclared bare `bulkActions` name no
longer draws in a non-grid view, matching #30387 on the grid)
Skills-docs: none owed — `skills/**` teaches no handler-only bulk action
name (searched `skills/` for `bulkActions` examples);
`content/docs/ui/**` already names only declared actions.
## 维护者速读
- 改了什么:看板、日历、画廊等非表格视图的选择栏,改成和表格同一条规则:视图 `bulkActions`
里的裸名字,只有对象声明了同名操作才画按钮,用声明的标签;删除照旧走自己的路径;没声明的名字不画,开发态控制台打一行警告点名。
- 为什么改:#30169 裁决 C 后表格已不画未声明的操作(PR
#30387),但切到看板等视图,勾选记录后仍会出现幽灵按钮(比如被禁用模块扣下的「Create Campaign」),点了只弹「不可执行」。
- 风险与回滚:plugin-list 新增对 plugin-grid 的 peer 依赖(控制台 app-shell
本来就同时装两包);plugin-grid
入口多两个导出,警告消息多一个可选的组件名字段,表格输出不变。若仓外宿主靠前端接管一个未声明的名字,非表格视图里它的按钮会消失。回滚即
revert 本 PR。
- 先看:`ui/packages/plugin-list/src/ListView.tsx`(`nonGridBulkBar`
折叠与选择栏渲染)→ `ui/packages/plugin-grid/src/undeclaredActionNames.ts`(可选
`component`)→ `ui/packages/plugin-grid/src/index.tsx`(两个新导出)。
- 两分钟验证:`pnpm --dir ui exec vitest run
packages/plugin-list/src/__tests__/ListView.nonGridBulkDeclared-30394.test.tsx`,预期
4 条全过;去掉折叠(消融)时其中 3 条转红。
- 需要你做的:无,席位落地。
## What changes
ListView draws its own selection bar for every view but the grid
(kanban, calendar, gallery, timeline, …). That bar mapped each
`bulkActions` member straight to a button labelled by the humanized
name, declared or not. #30169 (ruling C, comment 6651753071) made the
grid draw only actions the object declares; this applies the same rule
to the other bar, through the grid's own code.
- **`ListView.tsx`.** A new `nonGridBulkBar` memo folds
`permittedBulkActions` (the existing delete gate is untouched) through
plugin-grid's `resolveBulkActions`, with the canonical `delete` held out
of the fold exactly as `ObjectGrid` holds it out. The bar draws, in
authored order, `delete` (its own path, gate and per-record
`visibleWhen` subset, unchanged) and each name the served object
declares, under the declared label resolved through the app's i18n
bundle (the grid's `localizeLabel`). Any other name draws nothing. A bar
with nothing left to draw is not rendered.
`useUndeclaredActionNamesWarning` names the undrawn names once in
development, only while a non-grid view is on screen (the grid warns for
itself) and only once the object schema read has settled; with no schema
in hand (no `getObjectSchema`, or the read failed) the names are
reported as unread, never as undeclared, the grid's reading.
- **`plugin-grid/src/undeclaredActionNames.ts`.**
`UndeclaredActionNamesAddress` gains an optional `component` that heads
the message; omitted, it is `ObjectGrid`, so every grid message is
byte-identical. ListView passes `ListView` and the view on screen as
`blockType`: `[ObjectUI] ListView bulkActions: kanban (objectName:
'lead') — 1 name matches no action the object declares, …`.
- **`plugin-grid/src/index.tsx`.** Exports `resolveBulkActions`,
`useUndeclaredActionNamesWarning` and the types their signatures name.
- **`plugin-list/package.json`.** Declares `@object-ui/plugin-grid` as a
peer (`workspace:^`) and dev (`workspace:*`) dependency, following its
`@object-ui/plugin-detail` precedent. No cycle: plugin-grid does not
depend on plugin-list. plugin-list's build externalizes `@object-ui/*`,
so its dist does not bundle the grid. `pnpm-lock.yaml` moves by the
three lines that declaration adds.
- **Fixtures.** `ListView.bulkDeleteVisibleWhen.test.tsx` and
`ListView.permissions.test.tsx` used `archive` as their non-delete
control without the object declaring it; both fixtures now declare `{
name: 'archive', label: 'Archive' }`, so the control still draws (moved
pins, assertions unchanged).
## Why
Same defect as #30169, one more surface: after PR #30387 a list shown as
a grid hides a name the object does not declare (for example an action a
disabled package withholds), but the same list switched to kanban or
gallery still drew a button for it, and pressing it toasted "not
executable". The card asks for the grid's resolver to be reused rather
than copied; plugin-list could not reach it (no dependency, not
exported), measured and reported to the seat before plugin-grid was
touched.
## Tests
- New
`ui/packages/plugin-list/src/__tests__/ListView.nonGridBulkDeclared-30394.test.tsx`
(gallery view, selection stubbed the way
`ListView.bulkDeleteVisibleWhen.test.tsx` does): a declared name draws
under its declared label and dispatches by name, `delete` draws in
authored order, an undeclared name draws nothing and is named in one
`ListView` warning; all-undeclared draws no bar; no `getObjectSchema`
reports the names as unread; all-declared warns nothing.
- `ui/packages/plugin-grid/src/__tests__/undeclaredActionNames.test.ts`:
the message heads with `ObjectGrid` by default and with the address's
`component` when given.
## Acceptance notes
- Importing the plugin-grid entry (`sideEffects: true`, it registers
`object-grid` on import) did not disturb plugin-list's mocked
registrations: the full plugin-list suite is green (below), which was
the measured risk in the claim amendment's plan B.
- The non-grid bar still dispatches through the host's
`onBulkAction(name, rows)`; promoted defs' params, confirm text and
`visible` are not consulted on this bar (they never were). Unchanged by
this PR.
## Verification
Heads `38d91dbe` and `4d680aaa` change only the changeset over
`fbecf332`: the Clause-② arm (`(widening)` → `(narrowing)`), then the
summary's `!`; on it `check-changeset-no-major` (fed this body as the
event) exits 0 where the `(widening)` body exits 1 with the level-axis
contradiction, and `check-adr-0087-registration`,
`check-empty-changeset`, `check:changeset-fixed` exit 0 on `4d680aaa`.
The `(narrowing)` arm owes the full dogfood battery on the final head;
its reading goes to the seat. Everything below is on `fbecf332` unless
stated; the build closure was `pnpm exec turbo run build
--filter='@object-ui/plugin-list^...'` (53/53 tasks).
<details><summary>Package suites and type-check</summary>
- `pnpm --filter @object-ui/plugin-list test` on `85a03128` (the fix
commit; `fbecf332` changes only the changeset marker and the new test's
spy typing): `Test Files 190 passed (190)`, `Tests 1817 passed (1817)`,
lock `VERDICT command-exit 0`.
- `pnpm --filter @object-ui/plugin-grid test`: `Test Files 278 passed
(278)`, `Tests 2389 passed (2389)`, `VERDICT command-exit 0`.
- `pnpm exec vitest run
packages/plugin-list/src/__tests__/ListView.nonGridBulkDeclared-30394.test.tsx`:
`Tests 4 passed (4)`.
- `pnpm --filter @object-ui/plugin-grid --filter @object-ui/plugin-list
run type-check`: plugin-grid Done; plugin-list green after typing the
new test's spy (`fbecf332`).
- `pnpm --dir ui run check:spec-symbols` :: exit 0 (`1807 files scanned
against 5743 spec export names; ... 0 untriaged collisions`).
</details>
<details><summary>Ablation (one, on the tested behaviour)</summary>
`node scripts/ablation-replace.mjs --file
ui/packages/plugin-list/src/ListView.tsx --anchor ".filter((a) =>
a.toLowerCase() === 'delete' || labels.has(a))" --replacement
".filter(() => true /* ABLATION-30394 */)" -- …vitest run
…nonGridBulkDeclared-30394.test.tsx`
- Mutation landed: anchor 1 → 0, blob `c5b3c47fb594` → `5ddccdf4efbb`.
- Mutated run: `Tests 3 failed | 1 passed (4)`; the passing one is the
all-declared control, which the mutation cannot move.
- Restored: blob after restore `c5b3c47fb594` == HEAD, `git diff HEAD`
empty.
</details>
<details><summary>Derived gates (dispatch-gates --commands, 57
families)</summary>
- 57 derived, 57 run, 0 NOT-MEASURED (`--ran` with an exit code on every
line: "a DERIVED zero").
- Two needed a second run: `node scripts/check-adr-0087-registration.mjs
--base origin/main` :: exit 1 on `85a03128` (the `narrowed` kind
requires a disposition), exit 0 on `fbecf332` after the changeset gained
`not-required (no-migration-prescription)`; `pnpm
check:dual-build-cjs-loads` :: exit 3 (PREREQUISITE NOT MET, dists
missing) then exit 0 (`116 published require entry point(s) across 71
package(s) load`).
- Changeset families re-run on `fbecf332`: `check-changeset-no-major` 0,
`check-empty-changeset` 0, `check:changeset-fixed` 0,
`check-closing-keyword-parity` 0.
- Every other family exit 0. Families CI runs are read from this PR's
check-runs.
</details>
## Human Minimum
- [x] 1. Schemas start as Zod; `packages/spec` holds no runtime logic.
(not touched)
- [x] 2. Every name I added uses the casing for its kind.
- [x] 3. No formatter ran; `pnpm lint` is CI's.
- [x] 4. One issue, one branch off an up-to-date `main`, one pull
request.
- [x] 5. A change that publishes carries a changeset, and both
declaration lines are filled in here and in the changeset.
- [x] 6. `packages/spec` touched: n/a.
- [x] 7. No hand edits to `content/docs/references/`,
`packages/*/CHANGELOG.md` or `content/docs/releases/`.
- [x] 8. Title, body and comments are in English, except the 维护者速读
section the fleet requires.
- [x] The *Before Submitting* list in CONTRIBUTING.md is done.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01L6bhgVzvtWN68zb2r9z2zy)_
<!-- signed: domain:ui#5 · os-sales · session_01L6bhgVzvtWN68zb2r9z2zy
-->
---------
Co-authored-by: Claude <noreply@anthropic.com>
1 parent e3948ae commit d3b2aaf
10 files changed
Lines changed: 294 additions & 12 deletions
File tree
- .changeset
- ui/packages
- plugin-grid/src
- __tests__
- plugin-list
- src
- __tests__
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
59 | 59 | | |
60 | 60 | | |
61 | 61 | | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
62 | 72 | | |
63 | 73 | | |
64 | 74 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
32 | 32 | | |
33 | 33 | | |
34 | 34 | | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
35 | 40 | | |
36 | 41 | | |
37 | 42 | | |
| |||
55 | 60 | | |
56 | 61 | | |
57 | 62 | | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
58 | 69 | | |
59 | 70 | | |
60 | 71 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
46 | 46 | | |
47 | 47 | | |
48 | 48 | | |
49 | | - | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
50 | 59 | | |
51 | 60 | | |
52 | 61 | | |
| |||
67 | 76 | | |
68 | 77 | | |
69 | 78 | | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
70 | 83 | | |
71 | 84 | | |
72 | 85 | | |
| |||
92 | 105 | | |
93 | 106 | | |
94 | 107 | | |
95 | | - | |
| 108 | + | |
96 | 109 | | |
97 | 110 | | |
98 | 111 | | |
99 | 112 | | |
100 | 113 | | |
101 | | - | |
| 114 | + | |
102 | 115 | | |
103 | 116 | | |
104 | 117 | | |
| |||
141 | 154 | | |
142 | 155 | | |
143 | 156 | | |
144 | | - | |
| 157 | + | |
145 | 158 | | |
146 | 159 | | |
147 | 160 | | |
| 161 | + | |
148 | 162 | | |
149 | 163 | | |
150 | 164 | | |
151 | 165 | | |
152 | 166 | | |
153 | 167 | | |
154 | 168 | | |
155 | | - | |
| 169 | + | |
156 | 170 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
48 | 48 | | |
49 | 49 | | |
50 | 50 | | |
| 51 | + | |
51 | 52 | | |
52 | 53 | | |
53 | 54 | | |
| |||
62 | 63 | | |
63 | 64 | | |
64 | 65 | | |
| 66 | + | |
65 | 67 | | |
66 | 68 | | |
67 | 69 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
54 | 54 | | |
55 | 55 | | |
56 | 56 | | |
| 57 | + | |
57 | 58 | | |
58 | 59 | | |
59 | 60 | | |
| |||
2543 | 2544 | | |
2544 | 2545 | | |
2545 | 2546 | | |
| 2547 | + | |
| 2548 | + | |
| 2549 | + | |
| 2550 | + | |
| 2551 | + | |
| 2552 | + | |
| 2553 | + | |
| 2554 | + | |
| 2555 | + | |
| 2556 | + | |
| 2557 | + | |
| 2558 | + | |
| 2559 | + | |
| 2560 | + | |
| 2561 | + | |
| 2562 | + | |
| 2563 | + | |
| 2564 | + | |
| 2565 | + | |
| 2566 | + | |
| 2567 | + | |
| 2568 | + | |
| 2569 | + | |
| 2570 | + | |
| 2571 | + | |
| 2572 | + | |
| 2573 | + | |
| 2574 | + | |
| 2575 | + | |
| 2576 | + | |
| 2577 | + | |
| 2578 | + | |
| 2579 | + | |
| 2580 | + | |
| 2581 | + | |
| 2582 | + | |
| 2583 | + | |
| 2584 | + | |
| 2585 | + | |
| 2586 | + | |
| 2587 | + | |
| 2588 | + | |
| 2589 | + | |
| 2590 | + | |
| 2591 | + | |
2546 | 2592 | | |
2547 | 2593 | | |
2548 | 2594 | | |
| |||
7360 | 7406 | | |
7361 | 7407 | | |
7362 | 7408 | | |
7363 | | - | |
| 7409 | + | |
7364 | 7410 | | |
7365 | 7411 | | |
7366 | 7412 | | |
| |||
7372 | 7418 | | |
7373 | 7419 | | |
7374 | 7420 | | |
7375 | | - | |
7376 | | - | |
| 7421 | + | |
| 7422 | + | |
7377 | 7423 | | |
7378 | 7424 | | |
7379 | 7425 | | |
| |||
7396 | 7442 | | |
7397 | 7443 | | |
7398 | 7444 | | |
7399 | | - | |
| 7445 | + | |
7400 | 7446 | | |
7401 | 7447 | | |
7402 | 7448 | | |
| |||
7410 | 7456 | | |
7411 | 7457 | | |
7412 | 7458 | | |
7413 | | - | |
| 7459 | + | |
7414 | 7460 | | |
7415 | 7461 | | |
7416 | 7462 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
80 | 80 | | |
81 | 81 | | |
82 | 82 | | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
83 | 86 | | |
84 | 87 | | |
85 | 88 | | |
| |||
0 commit comments