@object-ui/layout 17.7.0 → 18.0.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 CHANGED
@@ -1,5 +1,324 @@
1
1
  # @object-ui/layout
2
2
 
3
+ ## 18.0.0
4
+
5
+ ### Dependency floors
6
+
7
+ Computed from `.objectstack-sha` `06cab4849a8a`: the earliest published `@objectstack/spec` that contains it is `18.0.0`.
8
+
9
+ - `@objectstack/spec` (`dependencies`): `^18.0.0-next.1` → `^18.0.0`
10
+
11
+ ### Major Changes
12
+
13
+ - 6f3299f: objectui moves to major 18, following `@objectstack/*` from 17 to 18 (objectui#12334). objectui's major is not a count of its own breaking changes: it tracks the major of the `@objectstack/spec` its packages depend on, so that the same major means compatible across the two projects. These packages already declare `@objectstack/*` on the 18 line (objectui#12030), so every package in the fixed release group crosses to 18 together. It is the one `major` that rule admits: objectui's own breaking changes ship as `minor`, described in their entries.
14
+
15
+ The 18 line is released from Changesets pre mode on the `next` tag (`.changeset/pre.json`), as `@objectstack/*` 18 is: these releases are `18.0.0-next.N` on the npm `next` dist-tag, and they do not move `latest`. The first `18.0.0` on `latest` comes when `@objectstack` 18 is generally available and this repository leaves pre mode.
16
+
17
+ What a consumer must do to take it is in the `@objectstack/*` 18 entry of this release (objectui#12030): move its own `@objectstack/*` packages to the 18 line at the same time.
18
+
19
+ ### Minor Changes
20
+
21
+ - 9fc68aa: Screen readers can name and reach the controls of the view tab bar, the settings form, the sidebar menus, the table's selection column and the percent cell (objectui#11690). axe-core (wcag2a + wcag2aa) on an object list page and on a Setup settings page reported the faults below; each is fixed where it is produced and pinned by an axe run on that component.
22
+
23
+ - **View tab bar (`ViewTabBar`).** The "+" add-view button is named, through the existing `view.addView` key, and its tooltip reads the same translated words instead of a hard-coded "Add View". Each view is now a `<button>`; the current one carries `aria-current="true"`. The views were `role="tab"` elements with no `tablist`, and the active view's actions button sat inside its tab, so it was a control inside a control. That button is now the view button's sibling, still named "View actions for …" and still one Tab stop away. Tab roles could not hold it: a tab's content is presentational and a tablist may contain only tabs. These views never had the tabs keyboard model (arrow keys, a tab panel) either. Every view stays its own Tab stop. When the bar is not reorderable, as the console renders it, Enter or Space switches to the focused view. With drag-to-reorder on, Enter or Space on a view starts a keyboard drag instead, as it did before this change, so a view is switched to by click. The rename box is now outside the view button and is named through `view.rename`. With drag-to-reorder on, the sortable attributes describe the view as a button. Breaking for anything that queried the bar by `role="tab"` or `aria-selected`: query `data-testid="view-tab-ID"` or `aria-current` instead.
24
+ - **Settings form (`@object-ui/console`).** Each row's label is bound to its control, so text, number, password, textarea, JSON, colour, switch and select controls are named by it. Clicking a label now focuses or toggles its control. A radio group and a multiselect checkbox group are named by the row label too.
25
+ - **Sidebar menus (`NavigationRenderer`).** With drag-to-reorder on (the desktop default), every row was wrapped in a `<div>` between the menu's `<ul>` and its `<li>`. The sortable node is now the row's own `<li>`. A separator and a nested group inside a menu are now list items too: the separator's item is hidden from assistive tech, and a top-level group is unchanged.
26
+ - **Table selection column (`data-table`).** The select-all checkbox and each row's checkbox are named through the existing `table.selectAllRows` and `table.selectRow` keys.
27
+ - **Percent cell (`PercentCellRenderer`).** The progress bar is named by the formatted value beside it (`aria-labelledby`), so the name is in the viewer's locale.
28
+
29
+ No language-pack key, export or prop is added; every new name reads a key the packs already carried.
30
+ - c5406c2: Depend on the `@objectstack/*` 18 prerelease line (objectui#12030).
31
+
32
+ Every `@objectstack/*` range these packages declare in `dependencies` or `peerDependencies` moves from `^17.x` to `^18.0.0-next.0`, the `next` prerelease of `@objectstack/*` 18 (raised to `^18.0.0-next.1` by objectui#12370 before release).
33
+
34
+ **Breaking for consumers:** an install that resolves `@objectstack/spec` (or `@objectstack/client`, `@objectstack/formula`, `@objectstack/lint`) 17.x no longer satisfies these ranges. A consumer must move its own `@objectstack/*` packages to the 18 line, starting with `18.0.0-next.1` (objectui#12370), at the same time as it takes this release.
35
+
36
+ **objectui's own surface moves with it:**
37
+
38
+ - `element:record_picker`'s registration stops publishing the `object`, `filter`, `sort` and `limit` inputs, which spec 18 retires; a JSX page that writes one now gets `unknown-prop`.
39
+ - The `CapabilityMultiSelectField` widget's curated capability set (`@object-ui/fields`) follows spec 18: `manage_mailboxes` in, `manage_org_presentation` out.
40
+ - `element:number` and `element:repeater` nodes that bind no object are accepted, as spec 18's row and `PageComponentSchema` accept them; the two `ELEMENT_*_OBJECT_REQUIRED` refusals are gone.
41
+
42
+ **Retired with the spec:** `@objectstack/spec` 18 tombstones `object-grid`'s `defaultFilters` and refuses it by name, and `ObjectGrid` and `ObjectView` stop reading it (`table.defaultFilters` on an `object-view` included). A view that still carries it renders unfiltered: rename the key to `filter`, whose value is the same rule array.
43
+ - 8a55f0c: The console sidebar no longer lets a user drag the app's menu into a private order; the Pinned section is now the one place a user orders entries (objectui#12059). Arranging an app's navigation is Studio's job: the menu is drawn in the order authored for the app, and every user sees that order. This reverses objectui#11626, which had extended menu drag-to-reorder to grouped menus.
44
+
45
+ **`@object-ui/layout` (breaking, declared `minor` per the version policy).** `NavigationRenderer` retires `enableReorder` and `onReorder`, and with them every sortable path through the menu: no menu row draws a grip or carries a sortable role. `AppSchemaRenderer` retires the same two props, which only handed them through. Two props are added for the pinned section: `pinnedOrder` (the pinned entry ids in the user's order; the section draws in that order, an unnamed pinned entry following in menu order) and `onPinnedReorder` (makes the pinned rows sortable and receives the drawn ids in their new order). A pinned row is dragged by the row itself: no grip at rest, a grab cursor, and a line marking where the row will land. From the keyboard, with the row's link focused, Space picks it up, the arrow keys move it, Space drops it and Escape cancels; Enter still follows the link. The row's link stays a link and the row's one focus stop. The click a pointer drag ends with is not followed.
46
+
47
+ **`@object-ui/app-shell`.** The sidebar no longer reads or writes the per-user menu order it kept in localStorage (`objectui-nav-order-APP`); a key left from before is ignored. The pinned order is stored with the pins, in the `UserDataAdapter`-backed favorites, so it syncs across devices the way the pins do: it is the order of the `type: 'nav'` entries in the stored list. A new pin now joins the end of that order (a content favorite still goes first), and an unpin leaves the others in order. `useFavorites()` gains `reorderNavPins(navIds)`, which puts the named pins in a new order in the places they already hold, so a pin another app's sidebar draws and every content favorite stay put; `useNavPins()` gains `reorderPins(orderedIds)` over it, and its `pinnedIds` lists the pins in the user's order. At the nav-pin cap a new pin still joins the end and the earliest-pinned one rolls off. Pins made before this change are now drawn in their stored order, which is newest first (a pin used to be put at the front of the list), rather than in menu order, until the user drags them.
48
+
49
+ **`@object-ui/i18n` (breaking, declared `minor`).** `console.nav.dragToReorder`, the label of the retired menu grip, is removed from all ten packs. `view.dragToReorder` is a different key and stays.
50
+
51
+ **Clause-②: yes.** Published surface changes: `NavigationRendererProps` loses `enableReorder` / `onReorder` and gains `pinnedOrder` / `onPinnedReorder`; `AppSchemaRendererProps` loses `enableReorder` / `onReorder`; the return of `useFavorites()` gains `reorderNavPins`; the return of `useNavPins()` gains `reorderPins`; the `console.nav.dragToReorder` pack key leaves.
52
+ - ff9df88: Depend on `@objectstack/*` `18.0.0-next.1` (objectui#12370).
53
+
54
+ Every `@objectstack/*` range these packages declare moves from `^18.0.0-next.0` to `^18.0.0-next.1`; the console and the runner bundle `18.0.0-next.1`. A consumer moves its own `@objectstack/*` packages to `18.0.0-next.1` with this release.
55
+
56
+ **Accept sets that narrow with it.** `@object-ui/types` validates page action rows and view data bindings through the spec's own rows, so its faces (`safeValidateSchema` and `StrictAnyComponentSchema`) now refuse what `18.0.0-next.1` refuses. Each was accepted on `18.0.0-next.0`:
57
+
58
+ - `onSuccess` on an `action:button` / `action:icon` row, or an `action:group` / `action:menu` member, whose executor is the `url`, `navigation`, `modal`, `flow` or `form` built-in, or that has no executor at all. Write the hop on an `api` or `script` action (or a host handler name), or drop it.
59
+ - `onSuccess` beside `operation: 'update'`, and an `onSuccess` block carrying a key outside `{ navigate, openIn }`.
60
+ - `actionType: 'navigation'` on a row (and `type: 'navigation'` on a container member): write `'url'`.
61
+ - A `url` executor's `target` that is not openable, judged on the executor the runner runs, including a row whose `name` selects it.
62
+ - A view `data` binding with `provider: 'api'`: bind the object or static rows; an API call is the page element's binding.
63
+ - a8e5b73: Console sidebar: one Favorites section at the top, and one ⋯ menu on every entry (objectui#12427).
64
+
65
+ - **The ⋯ menu replaces the pin icon.** When you hover a navigation entry it shows one ⋯ trigger, and a right-click on the row opens the same menu. There is no pin icon any more. The menu's entries depend on what the entry is:
66
+ - Add to favorites / Remove from favorites always comes first. It writes the same pin as before, so the entry lands in the Favorites section at the top.
67
+ - Open in new tab and Copy link appear for an entry that goes somewhere. They use the address the row's own link renders, so a console served under a basename opens and copies a working link, and a URL off the console is used as it is.
68
+ - Design appears for an `object`, `dashboard` or `page` entry. It opens that target's designer on the metadata-admin route (`/apps/APP/metadata/TYPE/NAME`, which is where a page's Edit in studio button already goes). Only a workspace admin whose session may author metadata sees it.
69
+ - On a phone, navigation entries show no trigger, as they showed no pin icon before.
70
+ - **One Favorites section, at the top.** Favorites that are not navigation entries, such as an object or a record you starred, used to be a group after Recent, below the fold on a long menu. They are now rows of the Favorites section at the top, after the pinned entries. Each row shows its stored label and type icon and carries the same ⋯ menu, whose favorites entry removes it. Design shows for object, dashboard and page favorites, never for a record. Existing favorites appear there as stored: nothing in the favorites store changes and nothing is migrated. The console-home Starred group and the Home page are unchanged.
71
+ - **The page header's favorites entry is in its overflow menu.**
72
+ - The object list header no longer has a star. Its last control is now an icon-only ⋯ button ("More actions") whose menu holds Add to favorites / Remove from favorites. When the current app's navigation has an entry that opens this list, the entry pins that navigation entry, the same action as the sidebar's own menu. It writes one `nav:` favorite that lands in the Favorites section, and no second `object:` favorite. For an object the app does not list, it keeps an `object:` favorite.
73
+ - On a record page the same entry leads the header's ⋯ overflow, ahead of Share, and toggles the record favorite.
74
+ - **`NavigationRenderer` (`@object-ui/layout`) gets two additive props.**
75
+ - `renderItemAction(item, context)` is a host control drawn on every leaf and action row, in place of the pin action. `context` carries the row's `href`, `external`, `label` and `basePath` (type `NavItemActionContext`).
76
+ - `extraFavorites` takes host rows that are appended to the Favorites section after the pinned entries. The section renders when either kind of row is there.
77
+ - A host that passes neither keeps the pin action and a section of pinned entries only, with the pinned drag order unchanged.
78
+ - **Language packs.** Six new `console.nav` keys in all ten packs: `itemMenu`, `openInNewTab`, `copyLink`, `linkCopied`, `linkCopyFailed` and `design`. The list header's ⋯ button is named by `detail.moreActions`, the name the record header's ⋯ already has. The favorites entry reuses `common.addToFavorites` / `common.removeFromFavorites`. `sidebar.favorites`, the title of the removed group, is no longer read and leaves all ten packs.
79
+ - dcd1041: The console top bar is 48 px (`h-12`) in every frame, the height both approved console artboards draw (objectui#12639). It was 56 px (`h-14`).
80
+
81
+ - **One height everywhere.** `AppShell`'s header (inside every app), Home, the organization list and an organization's pages, the full-page assistant at `/ai` and the `/studio` landing all draw the same bar, so it no longer changes height on the way from Home into an app or onto an organization page. Studio's package builder keeps its own header, which was already 48 px from `sm` up.
82
+ - **The app sidebar follows the bar.** On desktop its column starts 48 px down and is the viewport's height less 48 px, so no gap opens between the bar and the sidebar.
83
+ - **The bar's contents are unchanged.** Its controls (the product mark, the app pill, the preview chip, the search field, the bell, help and the avatar) are 32 px or shorter, so each keeps its size.
84
+
85
+ No export, prop or type is added, removed or renamed. A host that renders `@object-ui/layout`'s `AppShell` gets the 48 px header too.
86
+ - 1b94d50: A navigation entry's API `dataSource` is read, and its `visible` sees the selected value as `data` (objectui#13029).
87
+
88
+ The spec lets a navigation entry declare `dataSource: { provider: 'api', read: { url }, path? }` (`BaseNavItemSchema.dataSource`). Only the entry's `visible` reads the value, as `data` (for example `data.total == 1`). The label, the target and `children` do not.
89
+
90
+ - `@object-ui/layout`: `VisibilityEvaluator` takes an optional second argument, the entry whose `visible` it judges. The item guard passes it on every path it serves: the rows, the derived area visibility and the Favorites section. The default evaluator reads no binding, so it hides an entry that declares one. An entry without the key renders as before.
91
+ - `@object-ui/app-shell`: the sidebar, the `nav:menu` block and the command palette share one `visible` evaluator. It reads each binding the app's navigation declares through the page element's reader (`readElementApi`, with the host's signed-in `apiFetch`). The entry is hidden while the read is pending, after it fails, when `path` selects nothing, or when the spec refuses the binding. An entry without the key is evaluated as before, with no request and no wait.
92
+ - `@object-ui/types`: the `dataSource` describe and doc on the navigation item now state what the console does with it. The accept set is unchanged.
93
+ - df71568: A navigation item's `visible` now takes `@objectstack/spec`'s `EvaluatedExpressionInputSchema` by reference, beside the boolean it already took (objectui#13075).
94
+
95
+ The spec types every navigation entry's `visible` as an evaluated expression input: a non-blank CEL string, or the `{ dialect, source }` envelope the spec's own parse produces. objectui's `NavigationItemSchema` typed it as `boolean | string`, so the two disagreed both ways. This changes what `NavigationItemSchema` (and so `objectui validate`) accepts:
96
+
97
+ - **Widened: the envelope is accepted.** `visible: { dialect: 'cel', source: "'org_admin' in current_user.positions" }` used to be refused. It parses now and is kept as written. The TypeScript type `NavigationItem['visible']` is `boolean | EvaluatedExpressionInput` (the spec's input type), so a typed literal can carry the envelope too.
98
+ - **Narrowed (breaking): a blank string is refused.** `visible: ''` and a whitespace-only string used to pass. They are refused now with the spec's own code (`invalid_union` at `visible`) and sentence. A blank `source` inside an envelope is refused at `visible.source`, as the spec refuses it. To show an entry to everyone, omit `visible`.
99
+
100
+ Unchanged: a non-blank string is still accepted and kept as a string (the validator does not rewrite it into an envelope), and `visible: true` / `false` are still accepted. The boolean is the one stated divergence from the spec on this key.
101
+
102
+ Code that reads `NavigationItem['visible']` and passes it on as `string | boolean` no longer compiles: widen that parameter to `NavigationItem['visible']`.
103
+
104
+ `@object-ui/layout` (minor): the exported `VisibilityEvaluator` type now takes `NavigationItem['visible']` instead of `string | boolean | undefined`, so an evaluator receives the envelope as authored. An evaluator a host passes in whose parameter is the old, narrower type no longer type-checks; widen it the same way. The runtime is unchanged: `NavigationRenderer` already handed the value through.
105
+
106
+ `@object-ui/app-shell` (patch): the shell's navigation gates (`useNavMemberGates` and the `nav:menu` block) take the widened type internally. No exported type changes, and the runtime is unchanged: `evaluateNavigationVisibility` already evaluated the envelope.
107
+
108
+ ### Patch Changes
109
+
110
+ - b88937b: Drag-to-reorder of a grouped sidebar menu, within each level (objectui#11626), was retired before it was released. objectui#12059 removed every drag-to-reorder of the sidebar menu: an app's menu order is authored in Studio, and every user sees that order. Nothing of objectui#11626 ships, because objectui#12059 retires the menu reorder whole: `NavigationRenderer`'s `enableReorder` / `onReorder`, the menu drag grip, and the sidebar's per-user menu order in localStorage (`objectui-nav-order-APP`), each of which predates objectui#11626, are gone. The objectui#12059 changeset describes what replaced them: the pinned section is the one place a user orders entries.
111
+ - f114263: In the collapsed (icon-mode) sidebar, a click on an icon reaches its row again. Before, a hidden group label could take the click instead (objectui#12744).
112
+
113
+ The `SidebarGroupLabel` primitive hides a label in icon mode with `opacity-0` and `-mt-8` only. The invisible label stayed hit-testable and lay over the lower half of the row just above its group. A centre click on that row's icon landed on the label. A collapsible group's label toggled its group, the Recent label toggled Recent, and the row did not navigate.
114
+
115
+ The labels that sit below a row now take no pointer events while the primitive hides them. The condition is the primitive's own `group-data-[state=collapsed]:group-data-[collapsible=icon]:` variant:
116
+
117
+ - `@object-ui/layout`: `NavigationRenderer`'s collapsible group label, and its Favorites label (it sits below the Area switcher in a multi-area app);
118
+ - `@object-ui/app-shell`: `UnifiedSidebar`'s Recent label.
119
+
120
+ In the expanded sidebar nothing changes. A group's label still toggles its group by mouse and keyboard, and the Recent label still opens and closes Recent. The primitive itself is a Shadcn-synced file and is not edited: the class rides on the `className` each call site passes. Nothing is added to either package entry: no export, prop or type member.
121
+ - e43a162: In the collapsed (icon-mode) sidebar, a hidden group label is no longer a keyboard focus stop, and screen readers no longer announce it (objectui#12795). Before, Tab from the row above a collapsible group landed on the group's invisible label button, and Enter toggled a group the user could not see.
122
+
123
+ The `SidebarGroupLabel` primitive hides a label there by fading it to `opacity-0`, which left it in the tab order and the accessibility tree. `NavigationRenderer`'s collapsible group and Favorites labels, `AppSchemaRenderer`'s Area label and `SidebarNav`'s group labels now also take `visibility: hidden` under the primitive's own icon-mode condition. The label still fades out before it is hidden. Tab now moves from a group's last row straight to the next group's first row.
124
+
125
+ In the expanded sidebar and the mobile sheet nothing changes: every group label that took focus still does, and Enter still opens and closes its group. The primitive itself is a Shadcn-synced file and is not edited, and no export, prop or type member is added.
126
+ - d758f2f: Doc comment only. The `PageHeaderComponentProps` comment no longer says `@object-ui/app-shell` shares the name: the console's header props are now `ConsolePageHeaderProps`, so this package is the one authority for `PageHeaderComponentProps` (objectui#6349, batch 8). The type and its members are unchanged.
127
+
128
+ No runtime behaviour changes.
129
+ - Updated dependencies [18d7b48]
130
+ - Updated dependencies [172acc3]
131
+ - Updated dependencies [f0496bd]
132
+ - Updated dependencies [c4c506b]
133
+ - Updated dependencies [9db9ff3]
134
+ - Updated dependencies [c096f03]
135
+ - Updated dependencies [92f4e2b]
136
+ - Updated dependencies [b10c68e]
137
+ - Updated dependencies [bdc9049]
138
+ - Updated dependencies [2e818d0]
139
+ - Updated dependencies [fd060f0]
140
+ - Updated dependencies [8b14aec]
141
+ - Updated dependencies [2abec3a]
142
+ - Updated dependencies [9dfaca6]
143
+ - Updated dependencies [c000398]
144
+ - Updated dependencies [73b5d77]
145
+ - Updated dependencies [e6dcd85]
146
+ - Updated dependencies [96fcf30]
147
+ - Updated dependencies [7a2c60b]
148
+ - Updated dependencies [9fc68aa]
149
+ - Updated dependencies [d50f724]
150
+ - Updated dependencies [17acfbb]
151
+ - Updated dependencies [89cc738]
152
+ - Updated dependencies [c0862c1]
153
+ - Updated dependencies [c0862c1]
154
+ - Updated dependencies [c0862c1]
155
+ - Updated dependencies [c0862c1]
156
+ - Updated dependencies [c0862c1]
157
+ - Updated dependencies [4c0de52]
158
+ - Updated dependencies [a80fef7]
159
+ - Updated dependencies [e06365c]
160
+ - Updated dependencies [1e1f09e]
161
+ - Updated dependencies [455c646]
162
+ - Updated dependencies [f34e877]
163
+ - Updated dependencies [f34e877]
164
+ - Updated dependencies [9844bbf]
165
+ - Updated dependencies [cef0eee]
166
+ - Updated dependencies [7241a81]
167
+ - Updated dependencies [74add0c]
168
+ - Updated dependencies [aaba865]
169
+ - Updated dependencies [45d5853]
170
+ - Updated dependencies [4f4fc03]
171
+ - Updated dependencies [2312bd9]
172
+ - Updated dependencies [c5406c2]
173
+ - Updated dependencies [d99b731]
174
+ - Updated dependencies [2a48bd4]
175
+ - Updated dependencies [c7b30bd]
176
+ - Updated dependencies [69bca0a]
177
+ - Updated dependencies [023f00d]
178
+ - Updated dependencies [158c75d]
179
+ - Updated dependencies [7525045]
180
+ - Updated dependencies [5af42db]
181
+ - Updated dependencies [ce991bd]
182
+ - Updated dependencies [5f75cfa]
183
+ - Updated dependencies [b7cd5c8]
184
+ - Updated dependencies [5330038]
185
+ - Updated dependencies [c9fc10b]
186
+ - Updated dependencies [dc6d28e]
187
+ - Updated dependencies [c0c2f79]
188
+ - Updated dependencies [0665c3b]
189
+ - Updated dependencies [d2500d8]
190
+ - Updated dependencies [e723f58]
191
+ - Updated dependencies [f3d5408]
192
+ - Updated dependencies [b231607]
193
+ - Updated dependencies [466a219]
194
+ - Updated dependencies [6fb281d]
195
+ - Updated dependencies [334f0cf]
196
+ - Updated dependencies [c08c933]
197
+ - Updated dependencies [92f979d]
198
+ - Updated dependencies [c4dd707]
199
+ - Updated dependencies [c4dd707]
200
+ - Updated dependencies [923504f]
201
+ - Updated dependencies [5c2982a]
202
+ - Updated dependencies [97e7d4e]
203
+ - Updated dependencies [10aba37]
204
+ - Updated dependencies [5d3f437]
205
+ - Updated dependencies [7af0ab3]
206
+ - Updated dependencies [b434f5f]
207
+ - Updated dependencies [fd4872f]
208
+ - Updated dependencies [f0532d8]
209
+ - Updated dependencies [3092aca]
210
+ - Updated dependencies [82e5f53]
211
+ - Updated dependencies [d81e460]
212
+ - Updated dependencies [8106db1]
213
+ - Updated dependencies [093d55b]
214
+ - Updated dependencies [a8051d6]
215
+ - Updated dependencies [72594f2]
216
+ - Updated dependencies [524136e]
217
+ - Updated dependencies [6f3299f]
218
+ - Updated dependencies [f2b17c6]
219
+ - Updated dependencies [52d6194]
220
+ - Updated dependencies [23bf859]
221
+ - Updated dependencies [1c72d77]
222
+ - Updated dependencies [2b4d3f1]
223
+ - Updated dependencies [d75f212]
224
+ - Updated dependencies [ff9df88]
225
+ - Updated dependencies [70e843f]
226
+ - Updated dependencies [a2225f9]
227
+ - Updated dependencies [5c4deb5]
228
+ - Updated dependencies [c950345]
229
+ - Updated dependencies [21f9577]
230
+ - Updated dependencies [044f231]
231
+ - Updated dependencies [f8267df]
232
+ - Updated dependencies [3eb3ec1]
233
+ - Updated dependencies [1ffd6a2]
234
+ - Updated dependencies [5f8ecf6]
235
+ - Updated dependencies [726d8c9]
236
+ - Updated dependencies [ef71a09]
237
+ - Updated dependencies [619e3f7]
238
+ - Updated dependencies [c9e6742]
239
+ - Updated dependencies [f62b6ff]
240
+ - Updated dependencies [608033b]
241
+ - Updated dependencies [611566b]
242
+ - Updated dependencies [d66d7e8]
243
+ - Updated dependencies [15d8ca6]
244
+ - Updated dependencies [378896d]
245
+ - Updated dependencies [71243db]
246
+ - Updated dependencies [a8add5c]
247
+ - Updated dependencies [33ee9de]
248
+ - Updated dependencies [4839f5c]
249
+ - Updated dependencies [c7462e7]
250
+ - Updated dependencies [e058d76]
251
+ - Updated dependencies [c999d4c]
252
+ - Updated dependencies [8df2608]
253
+ - Updated dependencies [5483297]
254
+ - Updated dependencies [ed43c79]
255
+ - Updated dependencies [260ef71]
256
+ - Updated dependencies [655e897]
257
+ - Updated dependencies [655e897]
258
+ - Updated dependencies [69a408f]
259
+ - Updated dependencies [d2b21a1]
260
+ - Updated dependencies [5ff64ef]
261
+ - Updated dependencies [26323c4]
262
+ - Updated dependencies [9753811]
263
+ - Updated dependencies [bc281f4]
264
+ - Updated dependencies [d637be3]
265
+ - Updated dependencies [2cfdc99]
266
+ - Updated dependencies [1e6d83b]
267
+ - Updated dependencies [c219165]
268
+ - Updated dependencies [a7ae252]
269
+ - Updated dependencies [fb501bc]
270
+ - Updated dependencies [30083da]
271
+ - Updated dependencies [025130c]
272
+ - Updated dependencies [8aa8e3e]
273
+ - Updated dependencies [024b7b6]
274
+ - Updated dependencies [909c64e]
275
+ - Updated dependencies [9e7e1a5]
276
+ - Updated dependencies [2493e85]
277
+ - Updated dependencies [d0b9648]
278
+ - Updated dependencies [46dbf32]
279
+ - Updated dependencies [a928aaa]
280
+ - Updated dependencies [61ed5ad]
281
+ - Updated dependencies [1b94d50]
282
+ - Updated dependencies [988aa9f]
283
+ - Updated dependencies [fb85637]
284
+ - Updated dependencies [9f1dd79]
285
+ - Updated dependencies [df71568]
286
+ - Updated dependencies [d11174a]
287
+ - Updated dependencies [2d8a8b7]
288
+ - Updated dependencies [cbac9d7]
289
+ - Updated dependencies [616df65]
290
+ - Updated dependencies [4b92c5a]
291
+ - Updated dependencies [3650d94]
292
+ - Updated dependencies [8cd4db4]
293
+ - Updated dependencies [daeb77f]
294
+ - Updated dependencies [eb4552e]
295
+ - Updated dependencies [3c3115e]
296
+ - Updated dependencies [55e90fd]
297
+ - Updated dependencies [9b75509]
298
+ - Updated dependencies [b13ea3c]
299
+ - Updated dependencies [d7e9e9a]
300
+ - Updated dependencies [cf62edf]
301
+ - Updated dependencies [0253416]
302
+ - Updated dependencies [5d77c09]
303
+ - Updated dependencies [3fd8625]
304
+ - Updated dependencies [1473757]
305
+ - Updated dependencies [d73d987]
306
+ - Updated dependencies [12ff256]
307
+ - Updated dependencies [26b0bd2]
308
+ - Updated dependencies [26b0bd2]
309
+ - Updated dependencies [d328698]
310
+ - Updated dependencies [d328698]
311
+ - Updated dependencies [b4e0787]
312
+ - Updated dependencies [088e0f7]
313
+ - Updated dependencies [78b07f4]
314
+ - Updated dependencies [b403bb3]
315
+ - Updated dependencies [4016370]
316
+ - Updated dependencies [12dc7b4]
317
+ - @object-ui/types@18.0.0
318
+ - @object-ui/components@18.0.0
319
+ - @object-ui/core@18.0.0
320
+ - @object-ui/react@18.0.0
321
+
3
322
  ## 17.7.0
4
323
 
5
324
  ### Minor Changes
@@ -58,10 +58,6 @@ export interface AppSchemaRendererProps {
58
58
  enablePinning?: boolean;
59
59
  /** Called when a navigation item is pinned or unpinned */
60
60
  onPinToggle?: (itemId: string, pinned: boolean, item?: NavigationItem, basePath?: string) => void;
61
- /** Enable drag-to-reorder for navigation items */
62
- enableReorder?: boolean;
63
- /** Called when navigation items are reordered via drag */
64
- onReorder?: (reorderedItems: NavigationItem[]) => void;
65
61
  }
66
62
  /**
67
63
  * Renders a complete application shell from an `AppSchema` JSON document.
@@ -89,4 +85,4 @@ export interface AppSchemaRendererProps {
89
85
  * </AppSchemaRenderer>
90
86
  * ```
91
87
  */
92
- export declare function AppSchemaRenderer({ schema, basePath, mobileNavMode, evaluateVisibility: evalVisProp, checkPermission: checkPermProp, checkCapability: checkCapProp, checkDocTarget, onAction, navbar, sidebarHeader, sidebarFooter, sidebarExtra, children, className, defaultOpen, enableSearch, enablePinning, onPinToggle, enableReorder, onReorder, }: AppSchemaRendererProps): React.JSX.Element;
88
+ export declare function AppSchemaRenderer({ schema, basePath, mobileNavMode, evaluateVisibility: evalVisProp, checkPermission: checkPermProp, checkCapability: checkCapProp, checkDocTarget, onAction, navbar, sidebarHeader, sidebarFooter, sidebarExtra, children, className, defaultOpen, enableSearch, enablePinning, onPinToggle, }: AppSchemaRendererProps): React.JSX.Element;
@@ -4,8 +4,20 @@ import { NavigationItem, KeyedI18nLabel } from '@object-ui/types';
4
4
  * Callback to evaluate a visibility expression.
5
5
  * Return `true` if the item should be visible.
6
6
  * When not provided, all items default to visible.
7
+ *
8
+ * The parameter is the item's own `visible` type, so the spec's
9
+ * `{ dialect, source }` envelope reaches the evaluator as authored
10
+ * (objectui#13075).
11
+ *
12
+ * `entry` is the navigation entry whose `visible` this is (objectui#13029).
13
+ * The item guard always passes it. An entry may declare the spec's API
14
+ * `dataSource` (`{ provider: 'api', read: { url }, path? }`), whose selected
15
+ * value its `visible` reads as `data`; reading that binding is the host's job,
16
+ * so an evaluator that answers such an entry reads it through `entry`. The
17
+ * default evaluator reads no binding, so it hides an entry that declares one:
18
+ * a value nobody read is unknown, and an unknown navigation gate is closed.
7
19
  */
8
- export type VisibilityEvaluator = (expression: string | boolean | undefined) => boolean;
20
+ export type VisibilityEvaluator = (expression: NavigationItem['visible'], entry?: NavigationItem) => boolean;
9
21
  /**
10
22
  * Callback to check whether the current user satisfies **all** of the
11
23
  * given permission strings. Each string is opaque — the consumer decides
@@ -80,6 +92,24 @@ export type NavLabelTarget = {
80
92
  * an unlabelled entry falls through to its target's machine name.
81
93
  */
82
94
  export type NavTargetLabelResolver = (target: NavLabelTarget) => string | undefined;
95
+ /**
96
+ * What a host's per-entry control is told about the row it sits in
97
+ * (objectui#12427, {@link NavigationRendererProps.renderItemAction}).
98
+ */
99
+ export interface NavItemActionContext {
100
+ /**
101
+ * The row's href, as its link renders it ({@link resolveHref}). Absent for an
102
+ * `action` entry, which runs something and navigates nowhere, and for an
103
+ * entry whose target resolves to no address (`#`).
104
+ */
105
+ href?: string;
106
+ /** `href` leaves the console: the row opens it in a new tab. */
107
+ external: boolean;
108
+ /** The text the row shows ({@link resolveNavItemLabel}). */
109
+ label: string;
110
+ /** The renderer's `basePath`. */
111
+ basePath: string;
112
+ }
83
113
  export interface NavigationRendererProps {
84
114
  /** Navigation items to render */
85
115
  items: NavigationItem[];
@@ -122,10 +152,46 @@ export interface NavigationRendererProps {
122
152
  * working unchanged.
123
153
  */
124
154
  onPinToggle?: (itemId: string, pinned: boolean, item?: NavigationItem, basePath?: string) => void;
125
- /** Enable drag-to-reorder for navigation items */
126
- enableReorder?: boolean;
127
- /** Called when navigation items are reordered via drag */
128
- onReorder?: (reorderedItems: NavigationItem[]) => void;
155
+ /**
156
+ * The host's control for one entry (objectui#12427), drawn on every leaf and
157
+ * `action` row where the pin action sits, IN PLACE of it: a row this fills
158
+ * draws no pin action, so the host's control owns pinning (the console's ⋯
159
+ * menu offers Add to / Remove from favorites, through the same pin store).
160
+ * The control is a `SidebarMenuAction` (or renders one), so it sits where the
161
+ * pin action sat and follows the row's hover.
162
+ *
163
+ * Drawn whatever `enablePinning` says, which keeps deciding the Favorites
164
+ * section alone: a host that wants no control on a screen (a phone) does not
165
+ * pass this there. Omitted ⇒ the pin action under `enablePinning` +
166
+ * `onPinToggle`, as before. Groups and separators get none.
167
+ */
168
+ renderItemAction?: (item: NavigationItem, context: NavItemActionContext) => React.ReactNode;
169
+ /**
170
+ * Rows the host appends to the Favorites section, after the pinned entries
171
+ * (objectui#12427): favorites that are not navigation entries, such as a
172
+ * record. Each row is a `SidebarMenuItem`; the renderer lists them in a
173
+ * `SidebarMenu` of their own, outside the pinned entries' drag order. The
174
+ * section renders when it has a pinned entry (under `enablePinning`) or one
175
+ * of these rows; `null`, `false` and an empty array are no rows. Omitted ⇒
176
+ * the section holds pinned entries only, as before.
177
+ */
178
+ extraFavorites?: React.ReactNode;
179
+ /**
180
+ * The ids of the pinned entries in the user's order (objectui#12059). The
181
+ * pinned section draws its entries in this order; a pinned entry it does not
182
+ * name follows, in menu order. Omitted ⇒ the pinned section follows the menu.
183
+ */
184
+ pinnedOrder?: string[];
185
+ /**
186
+ * Makes the pinned section reorderable (objectui#12059): a pinned row is
187
+ * dragged by the row itself, with no grip at rest (`cursor: grab`, and an
188
+ * insertion line while dragging), or from the keyboard with dnd-kit's
189
+ * keyboard sensor (Space picks the focused row up, the arrow keys move it,
190
+ * Space drops it, Escape cancels). Called on a drop with the ids of the rows
191
+ * the section draws, in their new order. Only the pinned section reorders;
192
+ * the menu itself never does.
193
+ */
194
+ onPinnedReorder?: (pinnedIds: string[]) => void;
129
195
  /**
130
196
  * The viewer's locale (a BCP-47 tag such as `zh-CN`), for a PRESENT label
131
197
  * written as an inline locale map (`{ en: 'Accounts', 'zh-CN': '客户' }`,
@@ -352,8 +418,11 @@ export declare function filterNavigationItems(items: NavigationItem[], query: st
352
418
  * - RBAC permission guards
353
419
  * - Active-route highlighting
354
420
  * - Search filtering across navigation tree
355
- * - Pin/favorite items with dedicated "Favorites" section
356
- * - Drag-to-reorder navigation items
421
+ * - Pin/favorite items with dedicated "Favorites" section, in the user's
422
+ * order and reorderable by dragging a pinned row (objectui#12059)
423
+ * - A host control on every entry in place of the pin action
424
+ * (`renderItemAction`), and host rows after the pinned ones in the Favorites
425
+ * section (`extraFavorites`) (objectui#12427)
357
426
  *
358
427
  * @example
359
428
  * ```tsx
@@ -365,9 +434,9 @@ export declare function filterNavigationItems(items: NavigationItem[], query: st
365
434
  * searchQuery={searchTerm}
366
435
  * enablePinning
367
436
  * onPinToggle={(id, pinned) => updatePin(id, pinned)}
368
- * enableReorder
369
- * onReorder={(items) => saveOrder(items)}
437
+ * pinnedOrder={pinnedIds}
438
+ * onPinnedReorder={(ids) => savePinOrder(ids)}
370
439
  * />
371
440
  * ```
372
441
  */
373
- export declare function NavigationRenderer({ items, basePath, evaluateVisibility: evalVis, checkPermission: checkPerm, checkCapability: checkCap, checkDocTarget, onAction, searchQuery, enablePinning, onPinToggle, enableReorder, onReorder, resolveTargetLabel, locale, t: tProp, templateContext, }: NavigationRendererProps): React.JSX.Element;
442
+ export declare function NavigationRenderer({ items, basePath, evaluateVisibility: evalVis, checkPermission: checkPerm, checkCapability: checkCap, checkDocTarget, onAction, searchQuery, enablePinning, onPinToggle, renderItemAction, extraFavorites, pinnedOrder, onPinnedReorder, resolveTargetLabel, locale, t: tProp, templateContext, }: NavigationRendererProps): React.JSX.Element;
@@ -3,10 +3,11 @@ import { default as React } from 'react';
3
3
  * Props of this package's `<PageHeader>` React component.
4
4
  *
5
5
  * Named `PageHeaderComponentProps`, not `PageHeaderProps` (objectui#3161,
6
- * objectstack#4115 ledger batch 7) — the same name `@object-ui/app-shell`
7
- * settled on for its own header props in objectui#3169, deliberately reused
8
- * rather than re-invented, so one concept does not end up with two dialect
9
- * names one package apart.
6
+ * objectstack#4115 ledger batch 7). `@object-ui/app-shell` once used this
7
+ * name for its own console header (objectui#3169). That header is a different
8
+ * component, with rendered-node `title`, `subtitle` and `actions`, so since
9
+ * objectui#6349 (batch 8) it is `ConsolePageHeaderProps`, and this package is
10
+ * the one authority for this name.
10
11
  *
11
12
  * `@objectstack/spec/ui` owns `PageHeaderProps` for the AUTHORED `page:header`
12
13
  * node: a zod object of `title: string`, `subtitle`, an icon NAME, `breadcrumb`
@@ -17,7 +18,7 @@ import { default as React } from 'react';
17
18
  * prop rides along. Authored layer vs rendered layer, which is exactly the
18
19
  * one-name-two-layers failure objectstack#4115 exists to end.
19
20
  *
20
- * Pinned by `__tests__/spec-symbol-batch7.test.tsx`, which fails if the spec
21
+ * Pinned by `__tests__/spec-symbol-batch7.test.ts`, which fails if the spec
21
22
  * stops owning `PageHeaderProps` (then this can take the plain name back) or
22
23
  * starts owning `PageHeaderComponentProps`.
23
24
  */