@object-ui/react 4.7.0 → 5.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 +118 -0
- package/dist/context/DiscussionContext.d.ts +37 -0
- package/dist/context/DiscussionContext.js +34 -0
- package/dist/context/RecordContext.d.ts +21 -0
- package/dist/context/RecordContext.js +73 -0
- package/dist/context/index.d.ts +1 -0
- package/dist/context/index.js +1 -0
- package/dist/hooks/usePageAssignment.d.ts +25 -1
- package/dist/hooks/usePageAssignment.js +21 -1
- package/package.json +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,123 @@
|
|
|
1
1
|
# @object-ui/react
|
|
2
2
|
|
|
3
|
+
## 5.0.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 927187a: Phase N.1 + N.2: visual polish for record detail pages.
|
|
8
|
+
|
|
9
|
+
**N.1 — System actions on full Lightning pages.** `PageHeaderRenderer`
|
|
10
|
+
now merges `headerSystemActions` from `RecordContext` with authored
|
|
11
|
+
actions (authored wins on name/id collision), so full custom pages
|
|
12
|
+
(lead, opportunity, ...) once again show 编辑 / 分享 / 删除 alongside
|
|
13
|
+
their authored actions. `sys_share` and `sys_delete` now use the
|
|
14
|
+
`outline` variant instead of `destructive` to read better in
|
|
15
|
+
multi-button clusters.
|
|
16
|
+
|
|
17
|
+
**N.2 — Hide empty fields by default in synth detail pages.**
|
|
18
|
+
`record:details` defaults `section.hideEmpty` to `true` so synthesized
|
|
19
|
+
pages don't render label graveyards on first load. The "显示 N 个空字段"
|
|
20
|
+
reveal toggle is preserved as the user-facing escape hatch. Authors can
|
|
21
|
+
opt back into showing every field by setting `hideEmpty: false` on the
|
|
22
|
+
section schema.
|
|
23
|
+
|
|
24
|
+
- 8435860: Phase N.4b: highlight↔body dedup now works for hand-authored Lightning
|
|
25
|
+
pages too.
|
|
26
|
+
|
|
27
|
+
Adds a small `HighlightFieldsContext` registry. `record:highlights`
|
|
28
|
+
registers the field names it currently surfaces; `record:details` unions
|
|
29
|
+
that live set into its `hideFieldNames` filter so a field shown in the
|
|
30
|
+
highlight strip is never duplicated in the section grid below.
|
|
31
|
+
|
|
32
|
+
Previously the dedup only fired for synth-generated pages (via the
|
|
33
|
+
`hideFields` prop passed by `buildDefaultPageSchema`). Custom Lightning
|
|
34
|
+
pages (e.g. opportunity) showed `所属客户` both in the strip and in the
|
|
35
|
+
body. The registry-based approach covers both code paths uniformly with
|
|
36
|
+
no schema author work required.
|
|
37
|
+
|
|
38
|
+
The registry uses `useSyncExternalStore` so adding/removing highlights
|
|
39
|
+
notifies consumers without triggering the provider value identity to
|
|
40
|
+
change — avoiding the update-loop that a naive context implementation
|
|
41
|
+
would cause.
|
|
42
|
+
|
|
43
|
+
`RecordDetailView` mounts `<HighlightFieldsProvider>` once per record
|
|
44
|
+
page so the two renderers share state.
|
|
45
|
+
|
|
46
|
+
- 74962b0: feat(detail): record:discussion schema component + flush accordion variant
|
|
47
|
+
- New `record:discussion` schema type lets authors place the record
|
|
48
|
+
chatter feed anywhere in a custom Page schema. Wired through a
|
|
49
|
+
shared `DiscussionContext` provider on the `assignedPage` branch
|
|
50
|
+
of `RecordDetailView`; auto-append still applies when no explicit
|
|
51
|
+
`record:discussion` / `record:chatter` node is present.
|
|
52
|
+
- `page:accordion` gains a `variant` prop. Default `flush` strips the
|
|
53
|
+
per-item border so accordion sections no longer double-wrap inner
|
|
54
|
+
Card-bearing renderers (RelatedList, etc.). Authors who want the
|
|
55
|
+
old visual pass `variant: 'card'`.
|
|
56
|
+
- `translateLabel` now handles compound labels split by `&`, `and`,
|
|
57
|
+
or `和` (e.g. `Notes & Attachments` → `备注与附件`).
|
|
58
|
+
|
|
59
|
+
- 7213027: feat(detail): slotted record pages (Track 3 Phase I)
|
|
60
|
+
|
|
61
|
+
Introduce `kind: "slotted"` record pages that override one or more
|
|
62
|
+
named slots while letting the default-page synthesizer fill in the
|
|
63
|
+
rest. Authors no longer need to re-author the entire page just to
|
|
64
|
+
customize the header or one tab.
|
|
65
|
+
|
|
66
|
+
**Slot menu (v1):**
|
|
67
|
+
- `header` — replaces `page:header`
|
|
68
|
+
- `actions` — replaces the `record:quick_actions` action bar
|
|
69
|
+
- `highlights` — replaces the chips + chevron path strip
|
|
70
|
+
- `details` — replaces the Details tab body (other tabs stay synthesized)
|
|
71
|
+
- `tabs` — replaces the entire `page:tabs` node (wins over `details`)
|
|
72
|
+
- `discussion` — replaces the inline `record:discussion` footer
|
|
73
|
+
|
|
74
|
+
Each slot is a full replacement at the slot boundary. To compose
|
|
75
|
+
default + custom, call the corresponding `buildDefault*` sub-builder
|
|
76
|
+
(now exported from `@object-ui/plugin-detail`):
|
|
77
|
+
`buildDefaultHeader`, `buildDefaultActions`, `buildDefaultHighlights`,
|
|
78
|
+
`buildDefaultDetails`, `buildDefaultTabs`, `buildDefaultDiscussion`.
|
|
79
|
+
|
|
80
|
+
**Author shape:**
|
|
81
|
+
|
|
82
|
+
```ts
|
|
83
|
+
{
|
|
84
|
+
type: 'record',
|
|
85
|
+
object: 'account',
|
|
86
|
+
kind: 'slotted',
|
|
87
|
+
slots: {
|
|
88
|
+
header: { type: 'page:header', properties: { ... } },
|
|
89
|
+
},
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
**API changes:**
|
|
94
|
+
- `PageSchema` (in `@object-ui/types`): adds `kind?: 'full' | 'slotted'`
|
|
95
|
+
(default `'full'`) and `slots?: PageSlotMap`.
|
|
96
|
+
- `usePageAssignment` (in `@object-ui/react`): result now exposes a
|
|
97
|
+
`slots` field populated when the matched page has `kind === 'slotted'`.
|
|
98
|
+
Existing `page` field is unchanged for full pages.
|
|
99
|
+
- `buildDefaultPageSchema` (in `@object-ui/plugin-detail`): accepts an
|
|
100
|
+
`options.slots` map that overrides individual regions at synthesis time.
|
|
101
|
+
|
|
102
|
+
### Patch Changes
|
|
103
|
+
|
|
104
|
+
- Updated dependencies [8930b15]
|
|
105
|
+
- Updated dependencies [7213027]
|
|
106
|
+
- Updated dependencies [c7561a7]
|
|
107
|
+
- @object-ui/i18n@5.0.0
|
|
108
|
+
- @object-ui/types@5.0.0
|
|
109
|
+
- @object-ui/data-objectstack@5.0.0
|
|
110
|
+
- @object-ui/core@5.0.0
|
|
111
|
+
|
|
112
|
+
## 4.8.0
|
|
113
|
+
|
|
114
|
+
### Patch Changes
|
|
115
|
+
|
|
116
|
+
- @object-ui/types@4.8.0
|
|
117
|
+
- @object-ui/core@4.8.0
|
|
118
|
+
- @object-ui/i18n@4.8.0
|
|
119
|
+
- @object-ui/data-objectstack@4.8.0
|
|
120
|
+
|
|
3
121
|
## 4.7.0
|
|
4
122
|
|
|
5
123
|
### Patch Changes
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ObjectUI
|
|
3
|
+
* Copyright (c) 2024-present ObjectStack Inc.
|
|
4
|
+
*
|
|
5
|
+
* DiscussionContext — shared chatter / discussion feed for the current
|
|
6
|
+
* record. Mounted alongside RecordContext by the host record page (see
|
|
7
|
+
* `RecordDetailView` in `@object-ui/app-shell`) so that any `record:chatter`
|
|
8
|
+
* or `record:discussion` renderer placed inside the schema tree picks up
|
|
9
|
+
* the same feed items / mutation handlers without a parallel fetch.
|
|
10
|
+
*
|
|
11
|
+
* Why this is separate from RecordContext: chatter feeds are commonly
|
|
12
|
+
* absent (e.g. settings pages, dashboards), and many record pages opt in
|
|
13
|
+
* via schema rather than always paying the fetch cost. Keeping the
|
|
14
|
+
* discussion data in its own context lets non-record pages provide it
|
|
15
|
+
* cheaply and lets record pages omit it without affecting unrelated
|
|
16
|
+
* record-aware renderers.
|
|
17
|
+
*/
|
|
18
|
+
import React from 'react';
|
|
19
|
+
export interface DiscussionFeedItem {
|
|
20
|
+
id: string;
|
|
21
|
+
/** Generic discriminator — chatter renderers may switch on this. */
|
|
22
|
+
type?: string;
|
|
23
|
+
[k: string]: any;
|
|
24
|
+
}
|
|
25
|
+
export interface DiscussionContextValue {
|
|
26
|
+
items: DiscussionFeedItem[];
|
|
27
|
+
onAddComment?: (text: string, attachments?: any[]) => void | Promise<void>;
|
|
28
|
+
onAddReply?: (parentId: string, text: string) => void | Promise<void>;
|
|
29
|
+
onToggleReaction?: (itemId: string, reaction: string) => void | Promise<void>;
|
|
30
|
+
loading?: boolean;
|
|
31
|
+
error?: Error | null;
|
|
32
|
+
}
|
|
33
|
+
export interface DiscussionContextProviderProps extends DiscussionContextValue {
|
|
34
|
+
children: React.ReactNode;
|
|
35
|
+
}
|
|
36
|
+
export declare const DiscussionContextProvider: React.FC<DiscussionContextProviderProps>;
|
|
37
|
+
export declare function useDiscussionContext(): DiscussionContextValue | null;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* ObjectUI
|
|
4
|
+
* Copyright (c) 2024-present ObjectStack Inc.
|
|
5
|
+
*
|
|
6
|
+
* DiscussionContext — shared chatter / discussion feed for the current
|
|
7
|
+
* record. Mounted alongside RecordContext by the host record page (see
|
|
8
|
+
* `RecordDetailView` in `@object-ui/app-shell`) so that any `record:chatter`
|
|
9
|
+
* or `record:discussion` renderer placed inside the schema tree picks up
|
|
10
|
+
* the same feed items / mutation handlers without a parallel fetch.
|
|
11
|
+
*
|
|
12
|
+
* Why this is separate from RecordContext: chatter feeds are commonly
|
|
13
|
+
* absent (e.g. settings pages, dashboards), and many record pages opt in
|
|
14
|
+
* via schema rather than always paying the fetch cost. Keeping the
|
|
15
|
+
* discussion data in its own context lets non-record pages provide it
|
|
16
|
+
* cheaply and lets record pages omit it without affecting unrelated
|
|
17
|
+
* record-aware renderers.
|
|
18
|
+
*/
|
|
19
|
+
import React from 'react';
|
|
20
|
+
const DiscussionContext = React.createContext(null);
|
|
21
|
+
export const DiscussionContextProvider = ({ children, ...value }) => {
|
|
22
|
+
const memo = React.useMemo(() => value, [
|
|
23
|
+
value.items,
|
|
24
|
+
value.onAddComment,
|
|
25
|
+
value.onAddReply,
|
|
26
|
+
value.onToggleReaction,
|
|
27
|
+
value.loading,
|
|
28
|
+
value.error,
|
|
29
|
+
]);
|
|
30
|
+
return (_jsx(DiscussionContext.Provider, { value: memo, children: children }));
|
|
31
|
+
};
|
|
32
|
+
export function useDiscussionContext() {
|
|
33
|
+
return React.useContext(DiscussionContext);
|
|
34
|
+
}
|
|
@@ -13,6 +13,17 @@
|
|
|
13
13
|
* receive props from the schema tree.
|
|
14
14
|
*/
|
|
15
15
|
import React from 'react';
|
|
16
|
+
export declare const HighlightFieldsProvider: React.FC<{
|
|
17
|
+
children: React.ReactNode;
|
|
18
|
+
}>;
|
|
19
|
+
/** Subscribe to the live highlight-field set. Empty when no provider. */
|
|
20
|
+
export declare function useHighlightFieldNames(): ReadonlySet<string>;
|
|
21
|
+
/**
|
|
22
|
+
* Register a list of field names as currently surfaced by a
|
|
23
|
+
* `record:highlights` instance. Re-registers when the joined name list
|
|
24
|
+
* changes; unregisters on unmount.
|
|
25
|
+
*/
|
|
26
|
+
export declare function useRegisterHighlightFields(instanceId: string, names: string[]): void;
|
|
16
27
|
export interface RecordContextValue<TData = any, TObjectSchema = any> {
|
|
17
28
|
/** Object machine name, e.g. "crm_opportunity". */
|
|
18
29
|
objectName: string;
|
|
@@ -30,6 +41,16 @@ export interface RecordContextValue<TData = any, TObjectSchema = any> {
|
|
|
30
41
|
error?: Error | null;
|
|
31
42
|
/** Re-fetch the record from the source. */
|
|
32
43
|
refresh?: () => void | Promise<void>;
|
|
44
|
+
/**
|
|
45
|
+
* Optional system-level header actions (Edit / Share / Delete) that the
|
|
46
|
+
* host (e.g. RecordDetailView) wants to inject into the page header
|
|
47
|
+
* regardless of whether the page schema is synthesised or authored.
|
|
48
|
+
*
|
|
49
|
+
* `PageHeaderRenderer` appends these AFTER any authored
|
|
50
|
+
* `page:header.actions`, deduplicating by `name`. Hosts pass `undefined`
|
|
51
|
+
* to opt out entirely (e.g. embedded previews).
|
|
52
|
+
*/
|
|
53
|
+
headerSystemActions?: any[];
|
|
33
54
|
/**
|
|
34
55
|
* When true, the record is rendered inside a host overlay (drawer,
|
|
35
56
|
* modal, split-pane preview) rather than as a standalone route. Header
|
|
@@ -14,6 +14,78 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
14
14
|
* receive props from the schema tree.
|
|
15
15
|
*/
|
|
16
16
|
import React from 'react';
|
|
17
|
+
const HighlightFieldsContext = React.createContext(null);
|
|
18
|
+
export const HighlightFieldsProvider = ({ children }) => {
|
|
19
|
+
const registry = React.useMemo(() => {
|
|
20
|
+
const map = new Map();
|
|
21
|
+
let names = EMPTY_SET;
|
|
22
|
+
const listeners = new Set();
|
|
23
|
+
const recompute = () => {
|
|
24
|
+
const next = new Set();
|
|
25
|
+
for (const list of map.values())
|
|
26
|
+
for (const n of list)
|
|
27
|
+
next.add(n);
|
|
28
|
+
// Skip notify if shallow-equal to previous (avoid spurious updates).
|
|
29
|
+
if (next.size === names.size) {
|
|
30
|
+
let same = true;
|
|
31
|
+
for (const n of next)
|
|
32
|
+
if (!names.has(n)) {
|
|
33
|
+
same = false;
|
|
34
|
+
break;
|
|
35
|
+
}
|
|
36
|
+
if (same)
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
names = next;
|
|
40
|
+
listeners.forEach((l) => l());
|
|
41
|
+
};
|
|
42
|
+
return {
|
|
43
|
+
getNames: () => names,
|
|
44
|
+
subscribe: (l) => {
|
|
45
|
+
listeners.add(l);
|
|
46
|
+
return () => { listeners.delete(l); };
|
|
47
|
+
},
|
|
48
|
+
register: (id, list) => {
|
|
49
|
+
const prev = map.get(id);
|
|
50
|
+
if (prev &&
|
|
51
|
+
prev.length === list.length &&
|
|
52
|
+
prev.every((n, i) => n === list[i])) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
map.set(id, [...list]);
|
|
56
|
+
recompute();
|
|
57
|
+
},
|
|
58
|
+
unregister: (id) => {
|
|
59
|
+
if (map.delete(id))
|
|
60
|
+
recompute();
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
}, []);
|
|
64
|
+
return (_jsx(HighlightFieldsContext.Provider, { value: registry, children: children }));
|
|
65
|
+
};
|
|
66
|
+
/** Subscribe to the live highlight-field set. Empty when no provider. */
|
|
67
|
+
export function useHighlightFieldNames() {
|
|
68
|
+
const ctx = React.useContext(HighlightFieldsContext);
|
|
69
|
+
return React.useSyncExternalStore(ctx ? ctx.subscribe : NOOP_SUBSCRIBE, ctx ? ctx.getNames : GET_EMPTY, ctx ? ctx.getNames : GET_EMPTY);
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Register a list of field names as currently surfaced by a
|
|
73
|
+
* `record:highlights` instance. Re-registers when the joined name list
|
|
74
|
+
* changes; unregisters on unmount.
|
|
75
|
+
*/
|
|
76
|
+
export function useRegisterHighlightFields(instanceId, names) {
|
|
77
|
+
const ctx = React.useContext(HighlightFieldsContext);
|
|
78
|
+
const key = names.join('|');
|
|
79
|
+
React.useEffect(() => {
|
|
80
|
+
if (!ctx)
|
|
81
|
+
return;
|
|
82
|
+
ctx.register(instanceId, key.length === 0 ? [] : key.split('|'));
|
|
83
|
+
return () => ctx.unregister(instanceId);
|
|
84
|
+
}, [ctx, instanceId, key]);
|
|
85
|
+
}
|
|
86
|
+
const NOOP_SUBSCRIBE = (_) => () => { };
|
|
87
|
+
const GET_EMPTY = () => EMPTY_SET;
|
|
88
|
+
const EMPTY_SET = new Set();
|
|
17
89
|
const RecordContext = React.createContext(null);
|
|
18
90
|
export const RecordContextProvider = ({ children, ...value }) => {
|
|
19
91
|
// Memoize so consumers that rely on referential equality don't re-render
|
|
@@ -28,6 +100,7 @@ export const RecordContextProvider = ({ children, ...value }) => {
|
|
|
28
100
|
value.error,
|
|
29
101
|
value.refresh,
|
|
30
102
|
value.embedded,
|
|
103
|
+
value.headerSystemActions,
|
|
31
104
|
]);
|
|
32
105
|
return _jsx(RecordContext.Provider, { value: memo, children: children });
|
|
33
106
|
};
|
package/dist/context/index.d.ts
CHANGED
package/dist/context/index.js
CHANGED
|
@@ -10,6 +10,14 @@
|
|
|
10
10
|
* and returns the first PageSchema whose `pageType === 'record'` and `object`
|
|
11
11
|
* matches the requested name.
|
|
12
12
|
*
|
|
13
|
+
* Returns a discriminated result by `PageSchema.kind`:
|
|
14
|
+
* - `kind === 'full'` (default): the schema fully describes the page;
|
|
15
|
+
* the result populates `page` and the caller renders it as-is.
|
|
16
|
+
* - `kind === 'slotted'`: the schema only provides slot overrides;
|
|
17
|
+
* the result populates `slots` and the caller feeds them to
|
|
18
|
+
* `buildDefaultPageSchema(objectDef, { slots })` so omitted slots
|
|
19
|
+
* fall through to synthesized defaults.
|
|
20
|
+
*
|
|
13
21
|
* Future work (deferred): recordType / profile / app / formFactor filtering
|
|
14
22
|
* and priority-based selection. For now we return the first match so that
|
|
15
23
|
* callers can deterministically fall back to the auto-generated DetailView
|
|
@@ -28,8 +36,24 @@ export interface PageAssignmentOptions {
|
|
|
28
36
|
pageName?: string;
|
|
29
37
|
}
|
|
30
38
|
export interface PageAssignmentResult {
|
|
31
|
-
/**
|
|
39
|
+
/**
|
|
40
|
+
* Resolved full PageSchema, or null when none is available.
|
|
41
|
+
*
|
|
42
|
+
* Populated only when the matched page has `kind === 'full'` (the
|
|
43
|
+
* default — see `PageSchema.kind`). Slotted pages do NOT populate
|
|
44
|
+
* this field; callers should branch on `slots` instead.
|
|
45
|
+
*/
|
|
32
46
|
page: any | null;
|
|
47
|
+
/**
|
|
48
|
+
* Slot override map for the matched slotted page, or null when no
|
|
49
|
+
* slotted page matched.
|
|
50
|
+
*
|
|
51
|
+
* Populated only when the matched page has `kind === 'slotted'`.
|
|
52
|
+
* The caller is expected to feed these slots to the default-page
|
|
53
|
+
* synthesizer (`buildDefaultPageSchema(objectDef, { slots })`) so
|
|
54
|
+
* that omitted slots fall through to synthesized defaults.
|
|
55
|
+
*/
|
|
56
|
+
slots: any | null;
|
|
33
57
|
/** True while the metadata cache is still loading the `page` type. */
|
|
34
58
|
loading: boolean;
|
|
35
59
|
/** Loader error, if any. */
|
|
@@ -10,6 +10,14 @@
|
|
|
10
10
|
* and returns the first PageSchema whose `pageType === 'record'` and `object`
|
|
11
11
|
* matches the requested name.
|
|
12
12
|
*
|
|
13
|
+
* Returns a discriminated result by `PageSchema.kind`:
|
|
14
|
+
* - `kind === 'full'` (default): the schema fully describes the page;
|
|
15
|
+
* the result populates `page` and the caller renders it as-is.
|
|
16
|
+
* - `kind === 'slotted'`: the schema only provides slot overrides;
|
|
17
|
+
* the result populates `slots` and the caller feeds them to
|
|
18
|
+
* `buildDefaultPageSchema(objectDef, { slots })` so omitted slots
|
|
19
|
+
* fall through to synthesized defaults.
|
|
20
|
+
*
|
|
13
21
|
* Future work (deferred): recordType / profile / app / formFactor filtering
|
|
14
22
|
* and priority-based selection. For now we return the first match so that
|
|
15
23
|
* callers can deterministically fall back to the auto-generated DetailView
|
|
@@ -54,7 +62,7 @@ export function usePageAssignment(objectName, opts = {}) {
|
|
|
54
62
|
cancelled = true;
|
|
55
63
|
};
|
|
56
64
|
}, [meta]);
|
|
57
|
-
const
|
|
65
|
+
const matched = useMemo(() => {
|
|
58
66
|
if (!objectName && !opts.pageName)
|
|
59
67
|
return null;
|
|
60
68
|
const pages = Array.isArray(meta.pages) ? meta.pages : [];
|
|
@@ -87,8 +95,20 @@ export function usePageAssignment(objectName, opts = {}) {
|
|
|
87
95
|
candidates.sort((a, b) => (b?.priority ?? 0) - (a?.priority ?? 0));
|
|
88
96
|
return candidates[0];
|
|
89
97
|
}, [meta.pages, objectName, opts.pageName, opts.recordType, opts.profile, opts.app, opts.formFactor]);
|
|
98
|
+
// Discriminate by `kind`: full pages populate `page`, slotted pages
|
|
99
|
+
// populate `slots`. Missing `kind` defaults to 'full' for backwards
|
|
100
|
+
// compatibility with pre-Phase-I metadata.
|
|
101
|
+
const { page, slots } = useMemo(() => {
|
|
102
|
+
if (!matched)
|
|
103
|
+
return { page: null, slots: null };
|
|
104
|
+
if (matched.kind === 'slotted') {
|
|
105
|
+
return { page: null, slots: matched.slots ?? {} };
|
|
106
|
+
}
|
|
107
|
+
return { page: matched, slots: null };
|
|
108
|
+
}, [matched]);
|
|
90
109
|
return {
|
|
91
110
|
page,
|
|
111
|
+
slots,
|
|
92
112
|
loading: meta.loading || !ensured,
|
|
93
113
|
error: ensureError ?? meta.error ?? null,
|
|
94
114
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@object-ui/react",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.0.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"description": "React bindings and SchemaRenderer component for Object UI",
|
|
@@ -26,10 +26,10 @@
|
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"@objectstack/spec": "^4.0.5",
|
|
28
28
|
"react-hook-form": "^7.76.0",
|
|
29
|
-
"@object-ui/core": "
|
|
30
|
-
"@object-ui/data-objectstack": "
|
|
31
|
-
"@object-ui/i18n": "
|
|
32
|
-
"@object-ui/types": "
|
|
29
|
+
"@object-ui/core": "5.0.0",
|
|
30
|
+
"@object-ui/data-objectstack": "5.0.0",
|
|
31
|
+
"@object-ui/i18n": "5.0.0",
|
|
32
|
+
"@object-ui/types": "5.0.0"
|
|
33
33
|
},
|
|
34
34
|
"peerDependencies": {
|
|
35
35
|
"react": "^18.0.0 || ^19.0.0",
|