@object-ui/layout 17.1.0 → 17.3.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 +363 -0
- package/README.md +11 -7
- package/dist/AppSchemaRenderer.d.ts +3 -1
- package/dist/NavigationRenderer.d.ts +53 -1
- package/dist/PageHeader.d.ts +24 -2
- package/dist/index.d.ts +0 -1
- package/dist/index.js +278 -280
- package/dist/index.umd.cjs +1 -1
- package/package.json +13 -11
- package/dist/Page.d.ts +0 -8
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,368 @@
|
|
|
1
1
|
# @object-ui/layout
|
|
2
2
|
|
|
3
|
+
## 17.3.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 608669e: `AppSchemaRenderer` now derives area visibility from the items inside the
|
|
8
|
+
area, closing the visible-but-empty regression the spec 17.0.0 area-key
|
|
9
|
+
retirement left behind (objectui#3311, option C of the recorded ruling).
|
|
10
|
+
|
|
11
|
+
Spec 17.0.0 retired the authorable area-level `visible` /
|
|
12
|
+
`requiredPermissions` (`AREA_VISIBLE_RETIRED` /
|
|
13
|
+
`AREA_REQUIRED_PERMISSIONS_RETIRED`) — an area is a layout grouping, not an
|
|
14
|
+
access boundary — and objectui followed in #3315 by deleting the area
|
|
15
|
+
switcher's filter. Correct on the contract, but it changed the navigation
|
|
16
|
+
surface: an area whose items are **all** gated away used to disappear from
|
|
17
|
+
the switcher and instead rendered as a selectable, empty area.
|
|
18
|
+
|
|
19
|
+
## What changed
|
|
20
|
+
- **Area visibility is now derived, not authored.** An area appears in the
|
|
21
|
+
switcher iff at least one of its navigation items survives the exact
|
|
22
|
+
item-level guards `NavigationRenderer` applies: the `visible` expression,
|
|
23
|
+
`requiredPermissions`, the `requiresObject` / `requiresService` runtime
|
|
24
|
+
capability gates, and — for `action` items — the presence of an `onAction`
|
|
25
|
+
dispatcher (framework#4509: without one they are not rendered, so they
|
|
26
|
+
cannot carry an area either). Separators never count; a `group` counts only
|
|
27
|
+
through its children.
|
|
28
|
+
- **The active area is elected among visible areas only.** A fully gated
|
|
29
|
+
first area is no longer auto-activated, and when a gating change hides the
|
|
30
|
+
currently active area the shell re-elects the first visible one. A gating
|
|
31
|
+
change that merely _reveals_ an area never yanks the user away from where
|
|
32
|
+
they are.
|
|
33
|
+
- **An area with no items at all derives the same way**: no visible item →
|
|
34
|
+
hidden. (Boundary recorded in objectui#3311.)
|
|
35
|
+
- New export `hasVisibleNavigationItems(items, options)` from
|
|
36
|
+
`@object-ui/layout` — the predicate behind the derivation, usable by other
|
|
37
|
+
shells that render their own area switchers.
|
|
38
|
+
|
|
39
|
+
No authorable key is involved anywhere: the platform's `.strict()` area
|
|
40
|
+
object still rejects the retired keys, and the derivation — computed from the
|
|
41
|
+
same guards that decide what renders — cannot disagree with the rendered
|
|
42
|
+
navigation, so there is nothing for a metadata author to get wrong.
|
|
43
|
+
|
|
44
|
+
- d22ae31: Track `@objectstack/spec` 17.0.0-rc.2 (objectui#3235, #3208, #3287, #3264).
|
|
45
|
+
|
|
46
|
+
The pin moves from `^17.0.0-rc.1` to `^17.0.0-rc.2` across the workspace, and
|
|
47
|
+
the sibling `@objectstack/*` packages (`client` / `core` / `formula` / `lint`)
|
|
48
|
+
move with it — they pin `@objectstack/spec` **exactly**, so leaving them behind
|
|
49
|
+
kept a second copy of the spec in the tree and would have had `@objectstack/lint`
|
|
50
|
+
validating against rc.1 schemas that still accept keys rc.2 retires.
|
|
51
|
+
|
|
52
|
+
Breaking semantics, in FROM → TO form:
|
|
53
|
+
|
|
54
|
+
- **`app.homePageId` is retired — an app's landing page is now its first
|
|
55
|
+
navigation item.** An app that pinned a landing page with `homePageId` will
|
|
56
|
+
open on the first reachable navigation entry (by `order`) instead; the root
|
|
57
|
+
landing still follows `isDefault`. To restore a specific landing page, reorder
|
|
58
|
+
`navigation` so the intended entry comes first. Stored metadata is migrated by
|
|
59
|
+
`os migrate meta --from 16`. The key is a hard error now, not a stripped one:
|
|
60
|
+
the spec ships a tombstone that names the migration.
|
|
61
|
+
Upstream retired it because of its SHAPE, not its usage — it was an ID
|
|
62
|
+
cross-reference with no referential integrity, so a `homePageId` that pointed
|
|
63
|
+
at nothing silently fell back to the first navigation item anyway
|
|
64
|
+
(objectstack#4667, premise corrected in #4709). If the capability returns, it
|
|
65
|
+
returns as a flag on the navigation item itself, which cannot dangle.
|
|
66
|
+
- **`@object-ui/types`' `HttpMethod` now resolves to the spec's
|
|
67
|
+
`HttpMethodType`.** Shape is verbatim identical — the same 5-value UI subset —
|
|
68
|
+
and `@object-ui/types` still exports it as `HttpMethod`, so no consumer
|
|
69
|
+
changes. The spec renamed its `./ui` export because `HttpMethod` named two
|
|
70
|
+
different types depending on the import path (`./shared` / `./api` carry a
|
|
71
|
+
7-value enum including `HEAD` / `OPTIONS`); objectui deliberately keeps the
|
|
72
|
+
5-value one (objectstack#4691).
|
|
73
|
+
- **`AppContextSelector.includeAll` / `placement` are gone.** Neither ever did
|
|
74
|
+
anything in this renderer: context selectors are mandatory-scope, so no "All"
|
|
75
|
+
row was ever rendered, and `placement: 'topbar'` put nothing in the topbar.
|
|
76
|
+
Both carried schema defaults, which is why the liveness lint structurally
|
|
77
|
+
could not flag them — removal was the only channel that reaches an author
|
|
78
|
+
(framework#4509).
|
|
79
|
+
- **`NavigationArea.visible` / `order` / `requiredPermissions` are gone.** An
|
|
80
|
+
area is a layout grouping, not an access boundary. Gating moved down to the
|
|
81
|
+
navigation ITEM, where `visible` and `requiredPermissions` are unchanged and
|
|
82
|
+
still enforced. `AppSchemaRenderer`'s area switcher no longer hides an area, so
|
|
83
|
+
an area whose items are all gated away renders as visible-but-empty rather
|
|
84
|
+
than disappearing.
|
|
85
|
+
- **`@object-ui/core` no longer exports `NotificationProtocol`**
|
|
86
|
+
(`resolveNotificationConfig`, `specNotificationToToast`, `mapSeverityToVariant`,
|
|
87
|
+
`mapPosition`, `ToastNotification`). It bridged `@objectstack/spec/ui`'s
|
|
88
|
+
`Notification` / `NotificationConfig`, which objectstack#4610 deleted with no
|
|
89
|
+
successor. Use `resolveNotificationConfig` from `@object-ui/react`
|
|
90
|
+
(`NotificationContext`), which owns the live `NotificationSystemConfig` and is
|
|
91
|
+
what every notification surface already read. Note that the spec's _other_
|
|
92
|
+
`Notification` — `@objectstack/spec/api` — is the REST inbox row, a different
|
|
93
|
+
contract, and is deliberately NOT aliased in as a replacement.
|
|
94
|
+
- **The `email_template` client-side validator now uses
|
|
95
|
+
`EmailTemplateDefinitionSchema`.** It was pointing at the removed
|
|
96
|
+
`EmailTemplateSchema`, so authored templates were being checked against the
|
|
97
|
+
wrong contract: the live one is keyed `name` + `locale` (not `id`) and splits
|
|
98
|
+
the body into `bodyHtml` / `bodyText` (not `body` + `bodyType`)
|
|
99
|
+
(objectstack#4616 / #4807).
|
|
100
|
+
|
|
101
|
+
Fixes that are not breaking, but were only found because rc.2 stopped being
|
|
102
|
+
lenient — each had been passing vacuously:
|
|
103
|
+
|
|
104
|
+
- **`view` drafts are actually validated now.** The client validator named the
|
|
105
|
+
aggregated container schema while this admin authors first-class `ViewItem`s,
|
|
106
|
+
and the container used to strip `viewKind` / `config` in silence — so no view
|
|
107
|
+
draft ever had one of its own keys checked. It now validates each shape
|
|
108
|
+
against its own schema (objectui#3312).
|
|
109
|
+
- **The console's worked examples were wrong**, and being stripped rather than
|
|
110
|
+
refused: `view.list.object` (the container root already declares it),
|
|
111
|
+
`job.concurrency` / `job.timeoutMs` (no such keys; the spelling is `timeout`,
|
|
112
|
+
already in ms), `email_template.from` / `.to` (a template is not a send —
|
|
113
|
+
the sender override is `fromOverride`, an object), and
|
|
114
|
+
`datasource.capabilities` / `.healthCheck` (objectstack#4583 removed the
|
|
115
|
+
former; the latter was never a datasource key). These are the drafts an
|
|
116
|
+
author — or a model generating metadata — copies.
|
|
117
|
+
- Action key inventory re-derived: `ActionSchema` gained the package-lock
|
|
118
|
+
envelope (`_lock*` / `_package*` / `_provenance`), so a packaged action no
|
|
119
|
+
longer reports them as unknown keys.
|
|
120
|
+
- The schema-diff panel labels the new `default_mismatch` finding.
|
|
121
|
+
- Test fixtures pinning the retired `managedBy: 'system'` bucket now use
|
|
122
|
+
`engine-owned`. Protocol 17 split that value (objectstack#3355), so it
|
|
123
|
+
resolved to the default-writable fallback and a batch of "stays locked"
|
|
124
|
+
assertions had quietly stopped asserting anything.
|
|
125
|
+
|
|
126
|
+
### Patch Changes
|
|
127
|
+
|
|
128
|
+
- d2363e7: The legacy `page-header` alias stops advertising `description` as an authorable
|
|
129
|
+
key (objectui#3226).
|
|
130
|
+
|
|
131
|
+
FROM: `registerLayout()` declared `inputs: [title, description]`. TO:
|
|
132
|
+
`inputs: [title, subtitle]` — the key `@objectstack/spec/ui`'s `PageHeaderProps`
|
|
133
|
+
declares, and the one the canonical `page:header` renderer in
|
|
134
|
+
`@object-ui/components` already declares.
|
|
135
|
+
|
|
136
|
+
`inputs` is a DECLARATION surface, not documentation: the designer builds its
|
|
137
|
+
property palette from it, and the framework's `check:react-declaration-parity`
|
|
138
|
+
diffs it against the spec schemas. Declaring `description` therefore did not
|
|
139
|
+
merely tolerate a legacy spelling — it published a second dialect for the one
|
|
140
|
+
concept the protocol calls `subtitle`, and told authors (an AI author most
|
|
141
|
+
readily, since the registry is what it reads to learn the shape) that the
|
|
142
|
+
non-spec key was legal. Metadata that took the offer renders a subtitle under
|
|
143
|
+
`page-header` and silently loses it under `page:header`: same JSON, two results,
|
|
144
|
+
which is the outcome a single contract exists to prevent.
|
|
145
|
+
|
|
146
|
+
No runtime behaviour changes. `PageHeader` still reads `subtitle ?? description`,
|
|
147
|
+
deliberately: this alias exists for out-of-repo consumer schemas, so "no in-repo
|
|
148
|
+
author writes `description`" (verified — zero hits) is not evidence that nobody
|
|
149
|
+
does, and dropping the read today would delete an external page's second line
|
|
150
|
+
while its title kept rendering, the least reportable failure mode there is. That
|
|
151
|
+
read is retired together with an ADR-0087 D2 conversion entry
|
|
152
|
+
(`page-header-subtitle-alias`, `description` → `subtitle` rewritten at load
|
|
153
|
+
time), which lives in the framework repo and is tracked separately. Narrowing the
|
|
154
|
+
declaration did not need to wait on it and breaks no consumer; leaving the
|
|
155
|
+
declaration wrong in the meantime keeps minting the metadata the conversion would
|
|
156
|
+
then have to absorb.
|
|
157
|
+
|
|
158
|
+
New tests pin both halves so neither can drift back: the registration may not
|
|
159
|
+
declare `description`, must declare `subtitle`, and — checked against the spec's
|
|
160
|
+
own shape rather than a hand-written allowlist — may declare nothing
|
|
161
|
+
`@objectstack/spec` does not; while the runtime fallback is pinned as a sequencing
|
|
162
|
+
guard, to be deleted in the same change that lands the conversion entry.
|
|
163
|
+
|
|
164
|
+
- Updated dependencies [18cd432]
|
|
165
|
+
- Updated dependencies [532cf8b]
|
|
166
|
+
- Updated dependencies [680080a]
|
|
167
|
+
- Updated dependencies [a7651e6]
|
|
168
|
+
- Updated dependencies [d915c47]
|
|
169
|
+
- Updated dependencies [b71fc92]
|
|
170
|
+
- Updated dependencies [34595eb]
|
|
171
|
+
- Updated dependencies [3889ffb]
|
|
172
|
+
- Updated dependencies [5781fb1]
|
|
173
|
+
- Updated dependencies [9e9e9a9]
|
|
174
|
+
- Updated dependencies [56409c2]
|
|
175
|
+
- Updated dependencies [042e09d]
|
|
176
|
+
- Updated dependencies [9cbcbf4]
|
|
177
|
+
- Updated dependencies [85c4c9c]
|
|
178
|
+
- Updated dependencies [fd54c3e]
|
|
179
|
+
- Updated dependencies [4eeb932]
|
|
180
|
+
- Updated dependencies [23018cc]
|
|
181
|
+
- Updated dependencies [53811d1]
|
|
182
|
+
- Updated dependencies [d915c47]
|
|
183
|
+
- Updated dependencies [f44d872]
|
|
184
|
+
- Updated dependencies [509104a]
|
|
185
|
+
- Updated dependencies [825bbe3]
|
|
186
|
+
- Updated dependencies [5dd0127]
|
|
187
|
+
- Updated dependencies [06632e9]
|
|
188
|
+
- Updated dependencies [a4cff5b]
|
|
189
|
+
- Updated dependencies [175bd79]
|
|
190
|
+
- Updated dependencies [f833d3a]
|
|
191
|
+
- Updated dependencies [2a9513d]
|
|
192
|
+
- Updated dependencies [71be406]
|
|
193
|
+
- Updated dependencies [d22ae31]
|
|
194
|
+
- Updated dependencies [8d8094a]
|
|
195
|
+
- @object-ui/core@17.3.0
|
|
196
|
+
- @object-ui/components@17.3.0
|
|
197
|
+
- @object-ui/types@17.3.0
|
|
198
|
+
- @object-ui/react@17.3.0
|
|
199
|
+
|
|
200
|
+
## 17.2.0
|
|
201
|
+
|
|
202
|
+
### Minor Changes
|
|
203
|
+
|
|
204
|
+
- 4a51e77: Stop declaring 14 symbols across ten packages under names `@objectstack/spec`
|
|
205
|
+
owns (objectui#3161, objectstack#4115 batch 7 — the long tail, one or two
|
|
206
|
+
entries per package). All ten packages leave the ledger, which drops from 17
|
|
207
|
+
collisions across 11 packages to 3 across 1.
|
|
208
|
+
|
|
209
|
+
**Renamed exports** — in every case the spec exports the same name for a
|
|
210
|
+
_different_ thing, so the old name was a mis-description rather than a dialect:
|
|
211
|
+
|
|
212
|
+
| package | was | now | what the spec's same-named export is |
|
|
213
|
+
| :------------------------- | :--------------------------------- | :--------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------- |
|
|
214
|
+
| `@object-ui/fields` | `FieldWidgetProps` | `FieldWidgetComponentProps` | the DECLARED field-widget plugin props contract (a zod object; `field.type` is the `FieldType` enum, `readonly`/`required` carry defaults) |
|
|
215
|
+
| `@object-ui/layout` | `PageHeaderProps` | `PageHeaderComponentProps` | the authored `page:header` node — a zod schema of `title`, `subtitle`, an icon NAME, `breadcrumb`, `actions: string[]` |
|
|
216
|
+
| `@object-ui/layout` | `Page` | `PageNodeRenderer` | the authored page metadata DOCUMENT (`name`, `label`, `type`, `regions`) |
|
|
217
|
+
| `@object-ui/plugin-detail` | `ObjectFieldLike` | `ObjectDefFieldLike` | the i18n duck type `translateObject` walks (`help`/`description`, plus `[key: string]: any`) |
|
|
218
|
+
| `@object-ui/plugin-grid` | `ColumnSummaryConfig` | `ColumnSummarySetting` | the OBJECT form of `ListColumn.summary` **only** — the local one was the whole union, shorthand included |
|
|
219
|
+
| `@object-ui/plugin-grid` | `isMultiValueField` | `hasMultiValueShape` | the spec's classifier, which requires a def with a `type`; the local one is called with `undefined` |
|
|
220
|
+
| `@object-ui/collaboration` | `RealtimeConfig` | `RealtimeSubscriptionConfig` | the app's realtime DECLARATION (`enabled`, `transport`, `subscriptions[]`) |
|
|
221
|
+
| `@object-ui/plugin-charts` | `ChartConfig` | `ChartContainerConfig` | the authored chart document (`type`, `xAxis`, `series`, `showLegend`, …) |
|
|
222
|
+
| `@object-ui/plugin-form` | `FormSection` / `FormSectionProps` | `FormSectionContainer` / `FormSectionContainerProps` | the authored form-section metadata (`name`, `pane`, `visibleWhen`, `fields`) |
|
|
223
|
+
| `@object-ui/providers` | `Theme` | `ThemePreference` | a whole theme DOCUMENT (`name`, `label`, `colors`, `typography`) |
|
|
224
|
+
| `@object-ui/runner` | `App` (default export) | `RunnerApp` | the authored application metadata type **and** the `App.create()` builder |
|
|
225
|
+
| `@object-ui/sdui-parser` | `ValidationResult` | `ManifestValidationResult` | plugin-manifest validation (`{ valid, errors?, warnings? }`), exported from both `kernel` and `contracts` |
|
|
226
|
+
|
|
227
|
+
`ManifestValidationResult` follows the `<what was validated>Validation<Error|Result>`
|
|
228
|
+
convention registered on objectstack#4115 (`@object-ui/core` took
|
|
229
|
+
`SchemaNodeValidationResult` in batch 4). `PageHeaderComponentProps` deliberately
|
|
230
|
+
reuses the name `@object-ui/app-shell` already chose for its own header props in
|
|
231
|
+
batch 3, so one concept does not acquire two dialect names one package apart.
|
|
232
|
+
|
|
233
|
+
**Now derived from the spec instead of hand-written:**
|
|
234
|
+
|
|
235
|
+
- `@object-ui/fields` — `isFileIdToken` is re-exported from
|
|
236
|
+
`@objectstack/spec/data`. The local copy was character-for-character identical
|
|
237
|
+
to the spec's function while its comment said it "mirrors" it, so every
|
|
238
|
+
behaviour test passed and only reference identity could tell the two apart.
|
|
239
|
+
The regex is a wire decision: widening it server-side while a copy here kept
|
|
240
|
+
the old bound would make every new id read as "not a reference", and the
|
|
241
|
+
widget would submit the legacy inline blob to a backend expecting a reference.
|
|
242
|
+
- `@object-ui/plugin-detail` — `FeedFilterMode` is re-exported from
|
|
243
|
+
`@objectstack/spec/data`, in a file that already imported the sibling
|
|
244
|
+
`FeedItemType` from the spec.
|
|
245
|
+
- `@object-ui/plugin-grid` — the eleven-member aggregation union is now the
|
|
246
|
+
spec's `ColumnSummary` enum, so the total `Record<ColumnSummaryType, string>`
|
|
247
|
+
label map turns a member the spec adds into a compile error instead of a
|
|
248
|
+
blank footer cell. `ColumnSummarySetting` is `NonNullable<ListColumn['summary']>`,
|
|
249
|
+
i.e. whatever forms the spec itself accepts. `hasMultiValueShape` delegates to
|
|
250
|
+
the spec's `isMultiValueField` rather than re-deriving it from
|
|
251
|
+
`MULTI_OPTION_TYPES` / `MULTI_CAPABLE_TYPES`.
|
|
252
|
+
- `@object-ui/providers` — `ThemePreference` is the spec's `ThemeMode` union
|
|
253
|
+
plus the one legacy `'system'` spelling this provider still honours for stored
|
|
254
|
+
preferences, read off the schema's own `_zod` carrier so the package takes no
|
|
255
|
+
zod dependency.
|
|
256
|
+
|
|
257
|
+
`@objectstack/spec` moves from `devDependencies` to `dependencies` in
|
|
258
|
+
`@object-ui/fields` (it re-exports a runtime function) and `@object-ui/providers`
|
|
259
|
+
(its public `.d.ts` now references the spec).
|
|
260
|
+
|
|
261
|
+
Scored `minor`, not `major`, per this repo's fixed-group rule — objectui's major
|
|
262
|
+
tracks `@objectstack`, so breaking changes of our own ship as minor with the
|
|
263
|
+
semantics spelled out above (see AGENTS.md §版本号策略). A `major` here would carry
|
|
264
|
+
all 39 packages of the fixed group to `18.0.0` and off objectstack's 17.x line.
|
|
265
|
+
|
|
266
|
+
- 07de7be: Navigation `action` items actually run now (framework#4509).
|
|
267
|
+
|
|
268
|
+
A `type: 'action'` nav item rendered, gated like any other item, and did
|
|
269
|
+
**nothing** when clicked. `NavigationRenderer` dispatches such a click to an
|
|
270
|
+
`onAction` prop it expects the host shell to supply — it deliberately never
|
|
271
|
+
reads `item.actionDef` itself — and no shipped sidebar supplied that prop. So
|
|
272
|
+
`actionDef.actionName` reached no dispatcher: an author could put an action in
|
|
273
|
+
the menu, watch it render with its icon and label, and never find out that
|
|
274
|
+
clicking it was a no-op. The framework's liveness ledger recorded this as the
|
|
275
|
+
single gap in the AppSchema navigation surface.
|
|
276
|
+
|
|
277
|
+
**New `useNavActionDispatch`** (`@object-ui/app-shell`) resolves the nav item's
|
|
278
|
+
`actionName` against `action` metadata at click time — the same source
|
|
279
|
+
`DeclaredActionsBar` reads for a record toolbar — and dispatches the resolved
|
|
280
|
+
definition through `useAction()`. `UnifiedSidebar` now passes it. No new
|
|
281
|
+
provider is involved: the sidebar already renders inside `ConsoleShell`'s
|
|
282
|
+
`GlobalActionRuntimeProvider`, so nav actions get the fully-wired console runner
|
|
283
|
+
including the confirm, param-collection, result and navigate dialogs. A declared
|
|
284
|
+
`params` array becomes the runner's param-dialog input, and the nav item's own
|
|
285
|
+
`actionDef.params` is passed as the value bag, so a menu entry can pre-fill the
|
|
286
|
+
action it launches.
|
|
287
|
+
|
|
288
|
+
Nav actions are inherently **global**: `ActionNavItemSchema` is strict with
|
|
289
|
+
exactly `{ actionName, params? }` and carries no `objectName`, so resolution is
|
|
290
|
+
by name alone and no record context rides along.
|
|
291
|
+
|
|
292
|
+
**Behaviour change:** a shell that passes no `onAction` no longer renders
|
|
293
|
+
`action` items at all, instead of rendering them dead. This mirrors the existing
|
|
294
|
+
capability guards — an item the host cannot serve is hidden — and it makes the
|
|
295
|
+
omission diagnosable: a missing prop now shows up as "my action item is gone",
|
|
296
|
+
which leads to the prop, rather than "clicking does nothing", which for three
|
|
297
|
+
releases led nowhere. Every failure at dispatch time (an unnamed item, an
|
|
298
|
+
unresolvable action, a throwing action) warns and toasts instead of returning
|
|
299
|
+
silently.
|
|
300
|
+
|
|
301
|
+
- 6d868e1: Remove `PageNodeRenderer`, the dead page-node renderer (objectui#3223, ADR-0049
|
|
302
|
+
enforce-or-remove).
|
|
303
|
+
|
|
304
|
+
**Removed:** the `PageNodeRenderer` export and its `./Page` module. It was
|
|
305
|
+
registered under no component key and imported by nothing — a whole-repo grep
|
|
306
|
+
found zero call sites — so it reached consumers only through
|
|
307
|
+
`export * from './Page'` in the package barrel. `registerLayout()` was already
|
|
308
|
+
saying so in a note that told the next reader _not_ to register it. Its props
|
|
309
|
+
were also `{ schema: PageNodeSchema; … } & any`, and an intersection with `any`
|
|
310
|
+
absorbs the whole type, so the signature asserted nothing beyond "there is a
|
|
311
|
+
schema".
|
|
312
|
+
|
|
313
|
+
**Migration:** there is nothing to re-point in a working app — an unregistered
|
|
314
|
+
renderer had no call site to migrate. If you imported the symbol directly:
|
|
315
|
+
|
|
316
|
+
```diff
|
|
317
|
+
-import { PageNodeRenderer } from '@object-ui/layout';
|
|
318
|
+
+import { PageRenderer } from '@object-ui/components';
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
`PageRenderer` in `@object-ui/components` is, and remains, the renderer for the
|
|
322
|
+
`page` component key. It is the one that supports page types
|
|
323
|
+
(record/home/app/utility), named regions and `PageVariablesProvider` — the
|
|
324
|
+
deleted one rendered a header plus children and nothing else. Schema-driven
|
|
325
|
+
consumers are unaffected: a `{ type: 'page' }` node has always resolved through
|
|
326
|
+
the registry to `PageRenderer`, never to this export.
|
|
327
|
+
|
|
328
|
+
Also note: this supersedes the `Page` → `PageNodeRenderer` rename shipped for
|
|
329
|
+
this package in the batch 7 symbol burn-down — the renamed symbol is gone rather
|
|
330
|
+
than renamed again. `PageHeaderProps` → `PageHeaderComponentProps` from that same
|
|
331
|
+
batch is unaffected.
|
|
332
|
+
|
|
333
|
+
Scored `minor`, not `major`, per this repo's fixed-group rule — objectui's major
|
|
334
|
+
tracks `@objectstack`, so breaking changes of our own ship as minor with the
|
|
335
|
+
semantics spelled out above (see AGENTS.md §版本号策略). A `major` here would carry
|
|
336
|
+
all 39 packages of the fixed group to `18.0.0` and off objectstack's 17.x line.
|
|
337
|
+
|
|
338
|
+
### Patch Changes
|
|
339
|
+
|
|
340
|
+
- Updated dependencies [4ae0ac4]
|
|
341
|
+
- Updated dependencies [696e3c1]
|
|
342
|
+
- Updated dependencies [bca45cc]
|
|
343
|
+
- Updated dependencies [a889e31]
|
|
344
|
+
- Updated dependencies [09d30a4]
|
|
345
|
+
- Updated dependencies [4bf612c]
|
|
346
|
+
- Updated dependencies [335041c]
|
|
347
|
+
- Updated dependencies [b414983]
|
|
348
|
+
- Updated dependencies [256f8cc]
|
|
349
|
+
- Updated dependencies [d9668a7]
|
|
350
|
+
- Updated dependencies [cb82705]
|
|
351
|
+
- Updated dependencies [f572849]
|
|
352
|
+
- Updated dependencies [f6e8d78]
|
|
353
|
+
- Updated dependencies [ea96284]
|
|
354
|
+
- Updated dependencies [d3584c6]
|
|
355
|
+
- Updated dependencies [a8ad6c0]
|
|
356
|
+
- Updated dependencies [444457c]
|
|
357
|
+
- Updated dependencies [850033c]
|
|
358
|
+
- Updated dependencies [022e4c3]
|
|
359
|
+
- Updated dependencies [009e25d]
|
|
360
|
+
- Updated dependencies [726b89c]
|
|
361
|
+
- @object-ui/types@17.2.0
|
|
362
|
+
- @object-ui/components@17.2.0
|
|
363
|
+
- @object-ui/core@17.2.0
|
|
364
|
+
- @object-ui/react@17.2.0
|
|
365
|
+
|
|
3
366
|
## 17.1.0
|
|
4
367
|
|
|
5
368
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -38,19 +38,23 @@ import { AppShell } from '@object-ui/layout';
|
|
|
38
38
|
</AppShell>
|
|
39
39
|
```
|
|
40
40
|
|
|
41
|
-
###
|
|
41
|
+
### PageHeader
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
Page title block with an optional description, used at the top of a page's
|
|
44
|
+
content area.
|
|
44
45
|
|
|
45
46
|
```typescript
|
|
46
|
-
import {
|
|
47
|
+
import { PageHeader } from '@object-ui/layout';
|
|
47
48
|
|
|
48
|
-
<
|
|
49
|
-
<PageHeader title="Dashboard" description="View your metrics" />
|
|
50
|
-
<div>Page Content</div>
|
|
51
|
-
</Page>
|
|
49
|
+
<PageHeader title="Dashboard" description="View your metrics" />
|
|
52
50
|
```
|
|
53
51
|
|
|
52
|
+
> **Rendering a whole `page` node?** That belongs to `PageRenderer` in
|
|
53
|
+
> `@object-ui/components`, which is what the `page` component key resolves to —
|
|
54
|
+
> it handles page types (record/home/app/utility), named regions and page
|
|
55
|
+
> variables. This package deliberately does not register or export a second
|
|
56
|
+
> renderer for that key (objectui#3223).
|
|
57
|
+
|
|
54
58
|
### SidebarNav
|
|
55
59
|
|
|
56
60
|
Navigation sidebar component with React Router integration.
|
|
@@ -49,7 +49,9 @@ export interface AppSchemaRendererProps {
|
|
|
49
49
|
* Responsibilities:
|
|
50
50
|
* - Reads `name`, `title`, `description`, `logo`, `favicon` for branding
|
|
51
51
|
* - Renders sidebar navigation from `navigation` or `areas[].navigation`
|
|
52
|
-
* - Area switcher when multiple
|
|
52
|
+
* - Area switcher when multiple areas are VISIBLE — area visibility is
|
|
53
|
+
* derived from the items inside, not authored (objectui#3311): an area
|
|
54
|
+
* whose items are all gated away is hidden and never auto-activated
|
|
53
55
|
* - Mobile modes: `drawer` (sheet overlay, default), `bottom_nav` (fixed
|
|
54
56
|
* bottom bar), `hamburger` (collapsed sidebar)
|
|
55
57
|
* - Evaluates `visible` expressions and `requiredPermissions` on every item
|
|
@@ -41,7 +41,19 @@ export interface NavigationRendererProps {
|
|
|
41
41
|
checkPermission?: PermissionChecker;
|
|
42
42
|
/** Optional runtime-capability checker for `requiresObject` / `requiresService` */
|
|
43
43
|
checkCapability?: CapabilityChecker;
|
|
44
|
-
/**
|
|
44
|
+
/**
|
|
45
|
+
* Called when an `action`-type item is clicked.
|
|
46
|
+
*
|
|
47
|
+
* A shell that renders `action` items MUST supply this: the renderer has no
|
|
48
|
+
* dispatcher of its own and never reads `item.actionDef` — unpacking
|
|
49
|
+
* `actionName` / `params` and invoking the action is the host's job (see
|
|
50
|
+
* `useNavActionDispatch` in `@objectstack/app-shell`). Omitting it does not
|
|
51
|
+
* degrade to an inert button; action items are **not rendered at all**,
|
|
52
|
+
* because a nav entry that looks clickable and silently does nothing is worse
|
|
53
|
+
* than an absent one (framework#4509 — every shipped sidebar omitted this
|
|
54
|
+
* prop, so `actionDef.actionName` reached no dispatcher and every such item
|
|
55
|
+
* dead-clicked).
|
|
56
|
+
*/
|
|
45
57
|
onAction?: (item: NavigationItem) => void;
|
|
46
58
|
/** Search query to filter navigation items by label */
|
|
47
59
|
searchQuery?: string;
|
|
@@ -137,6 +149,46 @@ export declare function resolveLabel(label: string | {
|
|
|
137
149
|
defaultValue?: string;
|
|
138
150
|
params?: Record<string, any>;
|
|
139
151
|
}, t?: (key: string, options?: any) => string): string;
|
|
152
|
+
/** Guard callbacks for {@link hasVisibleNavigationItems}. */
|
|
153
|
+
export interface NavigationVisibilityOptions {
|
|
154
|
+
/** Evaluator for item `visible` expressions. Defaults to always-visible. */
|
|
155
|
+
evaluateVisibility?: VisibilityEvaluator;
|
|
156
|
+
/** Checker for item `requiredPermissions`. Defaults to always-permitted. */
|
|
157
|
+
checkPermission?: PermissionChecker;
|
|
158
|
+
/** Checker for `requiresObject` / `requiresService`. Defaults to pass. */
|
|
159
|
+
checkCapability?: CapabilityChecker;
|
|
160
|
+
/**
|
|
161
|
+
* Whether the host wires an `onAction` dispatcher. Without one, `action`
|
|
162
|
+
* items are not rendered at all (framework#4509 — a nav entry that looks
|
|
163
|
+
* clickable and silently does nothing is worse than an absent one), so
|
|
164
|
+
* they cannot carry an area's visibility either. Defaults to `false`,
|
|
165
|
+
* matching a renderer with no `onAction` prop.
|
|
166
|
+
*/
|
|
167
|
+
hasActionHandler?: boolean;
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Whether a navigation tree contains at least one item that would actually
|
|
171
|
+
* render under the given guards — the exact guards `NavigationItemRenderer`
|
|
172
|
+
* applies per item: the `visible` expression, `requiredPermissions`, the
|
|
173
|
+
* `requiresObject` / `requiresService` runtime-capability gates, and (for
|
|
174
|
+
* `action` items) the presence of an action dispatcher.
|
|
175
|
+
*
|
|
176
|
+
* Non-content nodes never count: a `separator` is a visual divider, and a
|
|
177
|
+
* `group` counts only through its children — a group whose children are all
|
|
178
|
+
* gated away contributes nothing a user can navigate to.
|
|
179
|
+
*
|
|
180
|
+
* This is the predicate behind DERIVED area visibility (objectui#3311).
|
|
181
|
+
* `@objectstack/spec` 17.0.0 retired the authorable area-level `visible` /
|
|
182
|
+
* `requiredPermissions` (`AREA_VISIBLE_RETIRED` /
|
|
183
|
+
* `AREA_REQUIRED_PERMISSIONS_RETIRED`): an area is a layout grouping, not an
|
|
184
|
+
* access boundary. What replaces those keys is not a new key but this
|
|
185
|
+
* derivation: an area is visible iff something inside it is. Because it is
|
|
186
|
+
* computed from the same guards that decide what renders, it can never
|
|
187
|
+
* disagree with the rendered navigation — and there is nothing for a
|
|
188
|
+
* metadata author to get wrong. An area with no items at all derives the
|
|
189
|
+
* same way (no visible item → hidden).
|
|
190
|
+
*/
|
|
191
|
+
export declare function hasVisibleNavigationItems(items: NavigationItem[], options?: NavigationVisibilityOptions): boolean;
|
|
140
192
|
/**
|
|
141
193
|
* Lightweight template-variable context for nav items that target a
|
|
142
194
|
* specific record / org. The shell injects the signed-in user id and
|
package/dist/PageHeader.d.ts
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
import { default as React } from 'react';
|
|
2
|
-
|
|
2
|
+
/**
|
|
3
|
+
* Props of this package's `<PageHeader>` React component.
|
|
4
|
+
*
|
|
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.
|
|
10
|
+
*
|
|
11
|
+
* `@objectstack/spec/ui` owns `PageHeaderProps` for the AUTHORED `page:header`
|
|
12
|
+
* node: a zod object of `title: string`, `subtitle`, an icon NAME, `breadcrumb`
|
|
13
|
+
* and `actions: string[]` (action IDs). This interface is the rendered layer of
|
|
14
|
+
* that same element — `icon` accepts a React node as well as a name, `actions`
|
|
15
|
+
* is a list of action definitions the `record:quick_actions` widget renders,
|
|
16
|
+
* `schema` carries the raw node, and it extends `HTMLAttributes` so every DOM
|
|
17
|
+
* prop rides along. Authored layer vs rendered layer, which is exactly the
|
|
18
|
+
* one-name-two-layers failure objectstack#4115 exists to end.
|
|
19
|
+
*
|
|
20
|
+
* Pinned by `__tests__/spec-symbol-batch7.test.tsx`, which fails if the spec
|
|
21
|
+
* stops owning `PageHeaderProps` (then this can take the plain name back) or
|
|
22
|
+
* starts owning `PageHeaderComponentProps`.
|
|
23
|
+
*/
|
|
24
|
+
export interface PageHeaderComponentProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
3
25
|
title: string;
|
|
4
26
|
/**
|
|
5
27
|
* Optional secondary line under the title. Spec schemas use `subtitle`,
|
|
@@ -44,4 +66,4 @@ export interface PageHeaderProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
|
44
66
|
};
|
|
45
67
|
};
|
|
46
68
|
}
|
|
47
|
-
export declare function PageHeader({ title, subtitle, description, icon, action, actions, showBack, schema, className, children, ...props }:
|
|
69
|
+
export declare function PageHeader({ title, subtitle, description, icon, action, actions, showBack, schema, className, children, ...props }: PageHeaderComponentProps): React.JSX.Element;
|