This repository was archived by the owner on Nov 4, 2026. It is now read-only.
Repository navigation
Commit 57dbe34
fix(app-shell): one shared object picker for Studio's object-name inputs, resolving only the chosen name (objectui#11783) (#11840)
Fixes #11783
Clause-②: no
## What this changes
Studio's object-name inputs now share one module-private picker,
`inspectors/ObjectPicker.tsx`.
- **Who renders it.** In `ObjectFieldInspector`: the Lookup's *Related
object* and the summary's *Child object*. In `FlowReferenceField`: every
flow reference of kind `object`, through one branch in
`ReferenceCombobox`. That covers the trigger's *Object*, the
time-relative *Sweep object*, the map node's *Item object*, the *Object*
of the four record nodes and the legacy action node, and the screen's
*Object form*. The trigger field reaches the picker through
`FlowNodeConfigField` and `FlowReferenceField`. `FlowNodeInspector.tsx`
is untouched.
- **When a name leaves it.** Typing stays in the input. `onCommit` runs
once, when the author chooses an option, presses Enter, or leaves the
input after typing. Escape abandons the typing. Enter and blur commit
exactly what was typed, matched or not, so a flow value that is an
expression is accepted as before.
- **What it offers.** One read per picker mount: `GET
/api/v1/meta/object?preview=draft`. The groups come in this order:
- this package's objects, where the package is Studio's `:packageId`
route parameter, else the editor URL's `?package=`;
- then the other objects;
- then every object the server marks `isSystem`, in a collapsed *System*
group. A search reaches that group without opening it, so `sys_user`
stays choosable for a Lookup.
Each option shows its label and its name. An entry served with `_draft`
carries the existing `engine.inspector.draftSuffix` marker. "System" is
read from the served `isSystem` only: no name prefix and no list.
- **`crm_lead`.** The placeholder is removed from the trigger *Object*
field, with no replacement and no locale key.
- **i18n.** Six new `engine.inspector.objectPicker.*` rows, EN and ZH,
in `metadata-admin/i18n.ts`. Loading and load failure reuse
`engine.form.loadingOptions` and `engine.form.optionsLoadFailedTitle`.
Nothing is added to the package's entry: no export, published prop,
`@object-ui/types` member or `packages/i18n` key. One module-internal
optional prop, `ariaLabel` on `ReferenceCombobox`, is added. It carries
the flow field's label to the picker, so the input has an accessible
name (the old datalist input had none). `ReferenceCombobox` is not
exported from the package.
## Why the preview list, and not the list the inputs read before
This departs from the suggested route on measurement:
- **What the draft list lacks.** `GET /meta/_drafts?type=object` answers
header rows with no label. Labelling a draft-only object from it would
take one more read per draft.
- **What the preview list carries.** `?preview=draft` serves the
draft-only object in the same single answer, with its own label, its
`_packageId` and `_draft: true`.
- **Callers without draft access.** A caller the server does not admit
to pending drafts gets the published list. That is the server's
documented behaviour (`mayReadPendingDrafts` in objectstack's runtime
meta domain); this run did not measure it.
- **One consequence, also measured.** A *published* object with a
pending draft is served `_draft: true` with its draft label, so it also
carries the draft marker.
## Measurements
**Setup.** Real Chromium at 1440×900, with this branch's console on a
dev-only Vite harness that is not committed. The backend is
`examples/app-showcase` from objectstack `bafb58bb`, run with
`objectstack dev --seed-admin --fresh`. The data is a writable package
`com.example.repairs` holding a draft-only object
`repairs_repair_ticket` and a draft flow. The author types
`repairs_repair_ticket` one key at a time into each input. Both runs
start from the same drafts.
| | before, `16cda0b` | after |
|---|---|---|
| Lookup *Related object*: per-prefix `GET /meta/object/PREFIX` while
typing | 20 | 0 |
| Lookup: object reads on commit | (one per keystroke) | 1, for the
committed name |
| Flow trigger *Object*: per-prefix `GET /meta/object/PREFIX` while
typing | 41 | 0 |
| Flow: object reads on commit | (one or two per keystroke) | 3, all for
the committed name |
| What the input offers | datalist of 109 / 108 entries, 83 named
`sys_*`, the draft as a bare name | 2 package + 27 other, then a
collapsed *System* group; the draft as *Repair Ticket* (draft) |
| Trigger placeholder | `crm_lead` | none |
All 3 reads on the flow commit are for the committed name. The inspector
holds more than one reader of the trigger object: `useFlowScope` in
`FlowNodeInspector` and the entry-condition `ConditionBuilder` are two
of them, and the third was not identified. All of them are outside this
card's files.
**H2, the served list.** `GET /api/v1/meta/object` returned 107 entries.
All 107 carry `isSystem` (80 `true`) and a `label`, and every entry
carries `_packageId`. A runtime-authored object carries no `isSystem`
key, published or draft. Its absence is the spec's declared default,
`false`. Three platform objects are served `isSystem: false`:
`sys_inbox_message`, `sys_file` and `sys_upload_session`. They are
offered up front, because the mark decides, not the prefix.
**H3, the object-name inputs in the Studio inspectors.**
- Moved onto the picker: the Lookup and summary inputs above, and every
flow reference of kind `object`. Each was a free-text datalist that
committed per keystroke.
- Left as they are, because they are not the same kind:
- the hook's *Objects*, a multi-select checkbox list;
- the action's *Object* and the page block's object, both strict selects
(each falls back to a text field only when the list is empty);
- the view variant's, dataset's and app-nav's object pickers, all
`InspectorComboField` popovers that commit on choice.
None of these fetches per keystroke. All of them still list `isSystem`
objects without grouping (see Acceptance notes).
**H4, the draft object.** `repairs_repair_ticket` is offered in *This
package*, labelled *Repair Ticket* from its draft and marked as a draft.
It is choosable from both inputs.
## Tests
New pins:
- `ObjectPicker.test.tsx` checks what the picker offers and in which
order. It checks that the served `isSystem` decides membership in
*System*: `sys_file` is offered up front and `audit_trail` is collapsed.
It checks that opening *System* or searching reaches those objects, and
that the draft is labelled and marked. It checks that typing commits
nothing, that Enter and blur commit what was typed (an expression
included), that Escape abandons, and that the catalog is read once.
- `ObjectFieldInspector.objectPicker-11783.test.tsx` runs the real
inspector with the real `useObjectFields`. Typing the name makes 0
object reads, and the commit makes 1, for that name. `sys_user` is
choosable.
- `FlowReferenceField.objectPicker-11783.test.tsx` runs the real
`FlowNodeInspector`, with the real `useFlowScope` and `useObjectFields`.
Typing makes 0 object reads, and the commit reads only the committed
name. An expression value is accepted as before (a control). The field
has no `crm_lead` placeholder.
Updated: `ObjectFieldInspector.draft-locale.test.tsx` reads the
localized draft marker on the picker. `ObjectFieldInspector.test.tsx`'s
summary case commits by leaving the input.
Gates, run locally on HEAD `8b94ce9`:
- every test file importing a touched module, 102 files, run from the
root with `pnpm exec vitest run`: exit 0, `Test Files 102 passed (102)`,
`Tests 1206 passed | 1 skipped (1207)`
- `pnpm --filter @object-ui/app-shell type-check`, which runs `tsc
--noEmit && tsc -p tsconfig.test.json` (`--listFilesOnly` confirms the
new test files are in that project): exit 0
- `check:control-bytes` · `check:new-line-citations` ·
`check:changeset-claims` · `check:pending-changeset-literals`: exit 0
- the app-shell locale checks `check:i18n-designer-parity` and
`check:i18n-dead-keys` (designer-table leg), plus `check:i18n-keys`:
exit 0
- added for this diff (new `vi.mock` doubles, a new source file, a new
`react-router-dom` import): `check:vi-mock-specifiers` ·
`check:vi-mock-inherit` · `check:vi-mock-override-shape` ·
`check:unreferenced-sources` · `check:phantom-deps` ·
`check:test-path-roots` · `check-changeset-presence.mjs`: exit 0
- `eslint --no-inline-config` over the changed files: 0 errors.
`ObjectPicker.tsx` has no warnings, and `FlowReferenceField.tsx` carries
the same 10 warnings it had at `16cda0b`.
The repo-wide `pnpm lint` and the full test farm are left to CI.
**Reverse check.** This ran on the committed fix, `3389363`. The three
source files were reverted to `16cda0b`, the two inspector-level pin
files were run, and the files were restored from `HEAD`. The restore was
proven by blob hashes equal to `HEAD` and an empty `git diff HEAD`.
Predicted and observed, 4 red and 2 green:
- the Lookup typing pin received 21 reads (20 prefixes and 1 full name)
where 0 were expected;
- the flow typing pin received 42 reads (40 prefixes and 2 full names);
- the `sys_user` pin and the placeholder pin went red;
- the two controls, the saved Lookup reference and the accepted
expression value, stayed green.
## Acceptance notes
Noted here, not filed:
- **Other flow placeholders.** `contract` (the four record nodes and the
legacy action node), `contracts` (sweep object) and `crm_account`
(screen object form) name objects the showcase does not serve.
`showcase_task` (map item object) exists only in the showcase. The view
inspector's `engine.inspector.view.objectPlaceholder` reads `e.g.
crm_lead`. This is the same class as `crm_lead`, but outside this
claim's lines.
- **Other object pickers.** The hook, action, page-block, view-variant,
dataset and app-nav pickers still list `isSystem` objects first-class
and ungrouped. The action's and page block's empty-list text-field
fallback commits per keystroke, which reaches `useObjectFields`.
- **Draft objects in the rail.** Studio's Data rail lists a draft-only
object by bare name, without its draft's label.
- **Platform objects unmarked.** `sys_inbox_message`, `sys_file` and
`sys_upload_session` are served `isSystem: false`. Whether they should
carry the mark is the platform's decision.
- **Payload.** The object list read is a full-body list, about 670 KB on
the showcase. The inputs read a list of the same size before this
change.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01DrKzdPdyLLBW3qpZ4vtk7z)_
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent 1e1f09e commit 57dbe34
11 files changed
Lines changed: 1011 additions & 127 deletions
File tree
- .changeset
- packages/app-shell/src/views/metadata-admin
- inspectors
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1142 | 1142 | | |
1143 | 1143 | | |
1144 | 1144 | | |
| 1145 | + | |
| 1146 | + | |
| 1147 | + | |
| 1148 | + | |
| 1149 | + | |
| 1150 | + | |
| 1151 | + | |
1145 | 1152 | | |
1146 | 1153 | | |
1147 | 1154 | | |
| |||
4196 | 4203 | | |
4197 | 4204 | | |
4198 | 4205 | | |
| 4206 | + | |
| 4207 | + | |
| 4208 | + | |
| 4209 | + | |
| 4210 | + | |
| 4211 | + | |
| 4212 | + | |
4199 | 4213 | | |
4200 | 4214 | | |
4201 | 4215 | | |
| |||
| 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 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
20 | 20 | | |
21 | 21 | | |
22 | 22 | | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
23 | 27 | | |
24 | 28 | | |
25 | 29 | | |
| |||
48 | 52 | | |
49 | 53 | | |
50 | 54 | | |
| 55 | + | |
51 | 56 | | |
52 | 57 | | |
53 | 58 | | |
| |||
76 | 81 | | |
77 | 82 | | |
78 | 83 | | |
| 84 | + | |
| 85 | + | |
79 | 86 | | |
80 | 87 | | |
81 | | - | |
82 | 88 | | |
83 | 89 | | |
84 | 90 | | |
| |||
626 | 632 | | |
627 | 633 | | |
628 | 634 | | |
| 635 | + | |
| 636 | + | |
| 637 | + | |
| 638 | + | |
| 639 | + | |
629 | 640 | | |
630 | 641 | | |
631 | 642 | | |
| |||
637 | 648 | | |
638 | 649 | | |
639 | 650 | | |
640 | | - | |
| 651 | + | |
641 | 652 | | |
642 | 653 | | |
643 | 654 | | |
| |||
659 | 670 | | |
660 | 671 | | |
661 | 672 | | |
662 | | - | |
| 673 | + | |
663 | 674 | | |
664 | 675 | | |
665 | 676 | | |
| |||
790 | 801 | | |
791 | 802 | | |
792 | 803 | | |
| 804 | + | |
| 805 | + | |
| 806 | + | |
| 807 | + | |
| 808 | + | |
| 809 | + | |
| 810 | + | |
| 811 | + | |
| 812 | + | |
| 813 | + | |
| 814 | + | |
| 815 | + | |
| 816 | + | |
| 817 | + | |
| 818 | + | |
| 819 | + | |
| 820 | + | |
| 821 | + | |
793 | 822 | | |
794 | 823 | | |
795 | 824 | | |
| |||
859 | 888 | | |
860 | 889 | | |
861 | 890 | | |
| 891 | + | |
862 | 892 | | |
863 | 893 | | |
864 | 894 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3 | 3 | | |
4 | 4 | | |
5 | 5 | | |
| 6 | + | |
6 | 7 | | |
7 | 8 | | |
8 | | - | |
9 | | - | |
| 9 | + | |
| 10 | + | |
10 | 11 | | |
11 | 12 | | |
12 | | - | |
13 | | - | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
14 | 19 | | |
15 | 20 | | |
16 | 21 | | |
| |||
22 | 27 | | |
23 | 28 | | |
24 | 29 | | |
25 | | - | |
| 30 | + | |
26 | 31 | | |
27 | 32 | | |
28 | 33 | | |
| |||
43 | 48 | | |
44 | 49 | | |
45 | 50 | | |
46 | | - | |
47 | | - | |
48 | | - | |
49 | | - | |
50 | | - | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
51 | 58 | | |
52 | | - | |
| 59 | + | |
53 | 60 | | |
54 | | - | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
55 | 66 | | |
56 | 67 | | |
57 | 68 | | |
58 | 69 | | |
59 | | - | |
60 | | - | |
| 70 | + | |
| 71 | + | |
61 | 72 | | |
62 | | - | |
| 73 | + | |
63 | 74 | | |
64 | | - | |
| 75 | + | |
65 | 76 | | |
66 | 77 | | |
67 | | - | |
| 78 | + | |
68 | 79 | | |
69 | 80 | | |
70 | | - | |
| 81 | + | |
71 | 82 | | |
72 | | - | |
| 83 | + | |
73 | 84 | | |
74 | 85 | | |
75 | | - | |
| 86 | + | |
76 | 87 | | |
77 | 88 | | |
78 | | - | |
79 | | - | |
80 | | - | |
81 | | - | |
82 | | - | |
83 | | - | |
84 | | - | |
85 | | - | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
86 | 93 | | |
87 | 94 | | |
88 | 95 | | |
| |||
0 commit comments