@object-ui/react 4.5.0 → 4.6.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
|
@@ -30,6 +30,14 @@ export interface RecordContextValue<TData = any, TObjectSchema = any> {
|
|
|
30
30
|
error?: Error | null;
|
|
31
31
|
/** Re-fetch the record from the source. */
|
|
32
32
|
refresh?: () => void | Promise<void>;
|
|
33
|
+
/**
|
|
34
|
+
* When true, the record is rendered inside a host overlay (drawer,
|
|
35
|
+
* modal, split-pane preview) rather than as a standalone route. Header
|
|
36
|
+
* affordances such as the auto "back to list" button should suppress
|
|
37
|
+
* themselves in this mode because the user already has Close / Expand
|
|
38
|
+
* controls in the overlay chrome.
|
|
39
|
+
*/
|
|
40
|
+
embedded?: boolean;
|
|
33
41
|
}
|
|
34
42
|
export interface RecordContextProviderProps extends RecordContextValue {
|
|
35
43
|
children: React.ReactNode;
|
|
@@ -28,6 +28,19 @@ export interface UseNavigationOverlayOptions {
|
|
|
28
28
|
/** External onRowClick callback — if set, takes full priority */
|
|
29
29
|
onRowClick?: (record: Record<string, unknown>) => void;
|
|
30
30
|
}
|
|
31
|
+
/**
|
|
32
|
+
* Optional event-like payload accepted by `handleClick`. We don't depend on
|
|
33
|
+
* React's synthetic event type to keep this hook framework-agnostic — only
|
|
34
|
+
* the few fields needed for modifier detection are read.
|
|
35
|
+
*/
|
|
36
|
+
export interface HandleClickModifiers {
|
|
37
|
+
/** macOS Command key — open in new tab when held */
|
|
38
|
+
metaKey?: boolean;
|
|
39
|
+
/** Windows/Linux Control key — open in new tab when held */
|
|
40
|
+
ctrlKey?: boolean;
|
|
41
|
+
/** Mouse button — 1 = middle click (treated as new tab) */
|
|
42
|
+
button?: number;
|
|
43
|
+
}
|
|
31
44
|
export interface NavigationOverlayState {
|
|
32
45
|
/** Whether the overlay (drawer/modal/split/popover) is open */
|
|
33
46
|
isOpen: boolean;
|
|
@@ -41,8 +54,15 @@ export interface NavigationOverlayState {
|
|
|
41
54
|
open: (record: Record<string, unknown>) => void;
|
|
42
55
|
/** Set the open state (for controlled Sheet/Dialog `onOpenChange`) */
|
|
43
56
|
setIsOpen: (open: boolean) => void;
|
|
44
|
-
/**
|
|
45
|
-
|
|
57
|
+
/**
|
|
58
|
+
* The click handler to attach to rows/items.
|
|
59
|
+
*
|
|
60
|
+
* Accepts an optional event (or any object with `metaKey`/`ctrlKey`/`button`)
|
|
61
|
+
* to detect modifier clicks. When `Cmd`/`Ctrl`/middle-click is detected, the
|
|
62
|
+
* record opens in a new browser tab as a full page regardless of the
|
|
63
|
+
* configured mode — matches Linear / Notion / Airtable convention.
|
|
64
|
+
*/
|
|
65
|
+
handleClick: (record: Record<string, unknown>, event?: HandleClickModifiers) => void;
|
|
46
66
|
/** The width from NavigationConfig (for drawer/modal/split sizing) */
|
|
47
67
|
width: string | number | undefined;
|
|
48
68
|
/** Whether navigation is an overlay mode (drawer/modal/split/popover) */
|
|
@@ -59,12 +59,26 @@ export function useNavigationOverlay(options) {
|
|
|
59
59
|
setSelectedRecord(record);
|
|
60
60
|
setIsOpen(true);
|
|
61
61
|
}, []);
|
|
62
|
-
const handleClick = useCallback((record) => {
|
|
63
|
-
// External onRowClick takes full priority
|
|
62
|
+
const handleClick = useCallback((record, event) => {
|
|
63
|
+
// External onRowClick takes full priority. Forward the modifier event
|
|
64
|
+
// so parent handlers (e.g. ObjectView) can still implement Cmd/Ctrl/
|
|
65
|
+
// middle-click → open in new tab.
|
|
64
66
|
if (onRowClick) {
|
|
65
|
-
onRowClick(record);
|
|
67
|
+
onRowClick(record, event);
|
|
66
68
|
return;
|
|
67
69
|
}
|
|
70
|
+
// Modifier / middle-click → always open in a new browser tab as a full
|
|
71
|
+
// page. Mirrors browser link convention (Cmd/Ctrl+Click, middle-click)
|
|
72
|
+
// so users can fan out multiple records into tabs from any list/board/
|
|
73
|
+
// gallery, regardless of the configured navigation mode.
|
|
74
|
+
const isModifierClick = !!(event && (event.metaKey || event.ctrlKey || event.button === 1));
|
|
75
|
+
if (isModifierClick) {
|
|
76
|
+
const recordId = record.id || record._id;
|
|
77
|
+
if (onNavigate && recordId != null) {
|
|
78
|
+
onNavigate(recordId, 'new_window');
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
68
82
|
// No navigation config — default to page navigation
|
|
69
83
|
if (!navigation) {
|
|
70
84
|
const recordId = record.id || record._id;
|
|
@@ -104,7 +118,7 @@ export function useNavigationOverlay(options) {
|
|
|
104
118
|
setIsOpen(true);
|
|
105
119
|
return;
|
|
106
120
|
}
|
|
107
|
-
}, [onRowClick, navigation, mode, objectName, onNavigate, isOverlay]);
|
|
121
|
+
}, [onRowClick, navigation, mode, objectName, onNavigate, isOverlay, view]);
|
|
108
122
|
return useMemo(() => ({
|
|
109
123
|
isOpen,
|
|
110
124
|
selectedRecord,
|
|
@@ -67,8 +67,13 @@ export function usePageAssignment(objectName, opts = {}) {
|
|
|
67
67
|
const candidates = pages.filter(p => {
|
|
68
68
|
if (!p)
|
|
69
69
|
return false;
|
|
70
|
-
|
|
71
|
-
|
|
70
|
+
// Only `pageType: 'record'` (or bare `type: 'record'`) is a
|
|
71
|
+
// user-facing record-detail page. `pageType: 'record_detail'` is a
|
|
72
|
+
// distinct concept used by the metadata designer page schemas
|
|
73
|
+
// (`buildObjectDetailPageSchema`) and must NOT be picked up here —
|
|
74
|
+
// otherwise opening any record would render the designer widget.
|
|
75
|
+
const pt = p.pageType ?? (p.type === 'record' ? 'record' : undefined);
|
|
76
|
+
const isRecord = pt === 'record';
|
|
72
77
|
if (!isRecord)
|
|
73
78
|
return false;
|
|
74
79
|
if (p.object !== objectName)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@object-ui/react",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.6.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": "4.
|
|
30
|
-
"@object-ui/data-objectstack": "4.
|
|
31
|
-
"@object-ui/i18n": "4.
|
|
32
|
-
"@object-ui/types": "4.
|
|
29
|
+
"@object-ui/core": "4.6.0",
|
|
30
|
+
"@object-ui/data-objectstack": "4.6.0",
|
|
31
|
+
"@object-ui/i18n": "4.6.0",
|
|
32
|
+
"@object-ui/types": "4.6.0"
|
|
33
33
|
},
|
|
34
34
|
"peerDependencies": {
|
|
35
35
|
"react": "^18.0.0 || ^19.0.0",
|