@dxos/plugin-deck 0.7.5-main.9d26e3a → 0.7.5-main.b19bfc8
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/dist/lib/browser/app-graph-builder-IYHAGFA3.mjs +151 -0
- package/dist/lib/browser/app-graph-builder-IYHAGFA3.mjs.map +7 -0
- package/dist/lib/browser/check-app-scheme-S3EYUPMF.mjs +33 -0
- package/dist/lib/browser/check-app-scheme-S3EYUPMF.mjs.map +7 -0
- package/dist/lib/browser/chunk-22AQ5IVX.mjs +17 -0
- package/dist/lib/browser/chunk-22AQ5IVX.mjs.map +7 -0
- package/dist/lib/browser/chunk-CYE6QZBQ.mjs +128 -0
- package/dist/lib/browser/chunk-CYE6QZBQ.mjs.map +7 -0
- package/dist/lib/browser/chunk-DIM5INBX.mjs +24 -0
- package/dist/lib/browser/chunk-DIM5INBX.mjs.map +7 -0
- package/dist/lib/browser/chunk-DIXE74SK.mjs +1097 -0
- package/dist/lib/browser/chunk-DIXE74SK.mjs.map +7 -0
- package/dist/lib/browser/chunk-KANJBSIX.mjs +97 -0
- package/dist/lib/browser/chunk-KANJBSIX.mjs.map +7 -0
- package/dist/lib/browser/{chunk-GVOGPULO.mjs → chunk-N7TEPFVR.mjs} +5 -4
- package/dist/lib/browser/chunk-N7TEPFVR.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +104 -1776
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/intent-resolver-MWUADUNI.mjs +488 -0
- package/dist/lib/browser/intent-resolver-MWUADUNI.mjs.map +7 -0
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/react-root-IELFERPV.mjs +45 -0
- package/dist/lib/browser/react-root-IELFERPV.mjs.map +7 -0
- package/dist/lib/browser/react-surface-WL45R43W.mjs +39 -0
- package/dist/lib/browser/react-surface-WL45R43W.mjs.map +7 -0
- package/dist/lib/browser/settings-YONG3QB7.mjs +28 -0
- package/dist/lib/browser/settings-YONG3QB7.mjs.map +7 -0
- package/dist/lib/browser/state-MZZL5S2D.mjs +124 -0
- package/dist/lib/browser/state-MZZL5S2D.mjs.map +7 -0
- package/dist/lib/browser/tools-5LDJNU56.mjs +51 -0
- package/dist/lib/browser/tools-5LDJNU56.mjs.map +7 -0
- package/dist/lib/browser/types.mjs +16 -4
- package/dist/lib/browser/url-handler-MVHTKUYA.mjs +72 -0
- package/dist/lib/browser/url-handler-MVHTKUYA.mjs.map +7 -0
- package/dist/types/src/DeckPlugin.d.ts +1 -5
- package/dist/types/src/DeckPlugin.d.ts.map +1 -1
- package/dist/types/src/capabilities/app-graph-builder.d.ts +181 -0
- package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -0
- package/dist/types/src/capabilities/capabilities.d.ts +142 -0
- package/dist/types/src/capabilities/capabilities.d.ts.map +1 -0
- package/dist/types/src/capabilities/check-app-scheme.d.ts +4 -0
- package/dist/types/src/capabilities/check-app-scheme.d.ts.map +1 -0
- package/dist/types/src/capabilities/index.d.ts +190 -0
- package/dist/types/src/capabilities/index.d.ts.map +1 -0
- package/dist/types/src/capabilities/intent-resolver.d.ts +4 -0
- package/dist/types/src/capabilities/intent-resolver.d.ts.map +1 -0
- package/dist/types/src/capabilities/react-root.d.ts +7 -0
- package/dist/types/src/capabilities/react-root.d.ts.map +1 -0
- package/dist/types/src/capabilities/react-surface.d.ts +4 -0
- package/dist/types/src/capabilities/react-surface.d.ts.map +1 -0
- package/dist/types/src/capabilities/settings.d.ts +4 -0
- package/dist/types/src/capabilities/settings.d.ts.map +1 -0
- package/dist/types/src/capabilities/state.d.ts +79 -0
- package/dist/types/src/capabilities/state.d.ts.map +1 -0
- package/dist/types/src/capabilities/tools.d.ts +10 -0
- package/dist/types/src/capabilities/tools.d.ts.map +1 -0
- package/dist/types/src/capabilities/url-handler.d.ts +4 -0
- package/dist/types/src/capabilities/url-handler.d.ts.map +1 -0
- package/dist/types/src/components/DeckLayout/ActiveNode.d.ts +1 -2
- package/dist/types/src/components/DeckLayout/ActiveNode.d.ts.map +1 -1
- package/dist/types/src/components/DeckLayout/Banner.d.ts +5 -0
- package/dist/types/src/components/DeckLayout/Banner.d.ts.map +1 -0
- package/dist/types/src/components/DeckLayout/ComplementarySidebar.d.ts +1 -4
- package/dist/types/src/components/DeckLayout/ComplementarySidebar.d.ts.map +1 -1
- package/dist/types/src/components/DeckLayout/ContentEmpty.d.ts +1 -2
- package/dist/types/src/components/DeckLayout/ContentEmpty.d.ts.map +1 -1
- package/dist/types/src/components/DeckLayout/DeckLayout.d.ts +2 -7
- package/dist/types/src/components/DeckLayout/DeckLayout.d.ts.map +1 -1
- package/dist/types/src/components/DeckLayout/Fallback.d.ts +1 -2
- package/dist/types/src/components/DeckLayout/Fallback.d.ts.map +1 -1
- package/dist/types/src/components/DeckLayout/Fullscreen.d.ts +1 -2
- package/dist/types/src/components/DeckLayout/Fullscreen.d.ts.map +1 -1
- package/dist/types/src/components/DeckLayout/NodePlankHeading.d.ts +3 -3
- package/dist/types/src/components/DeckLayout/NodePlankHeading.d.ts.map +1 -1
- package/dist/types/src/components/DeckLayout/Plank.d.ts +8 -6
- package/dist/types/src/components/DeckLayout/Plank.d.ts.map +1 -1
- package/dist/types/src/components/DeckLayout/PlankControls.d.ts +2 -2
- package/dist/types/src/components/DeckLayout/PlankControls.d.ts.map +1 -1
- package/dist/types/src/components/DeckLayout/PlankError.d.ts +6 -6
- package/dist/types/src/components/DeckLayout/PlankError.d.ts.map +1 -1
- package/dist/types/src/components/DeckLayout/PlankLoading.d.ts +1 -2
- package/dist/types/src/components/DeckLayout/PlankLoading.d.ts.map +1 -1
- package/dist/types/src/components/DeckLayout/Sidebar.d.ts +1 -6
- package/dist/types/src/components/DeckLayout/Sidebar.d.ts.map +1 -1
- package/dist/types/src/components/DeckLayout/SidebarButton.d.ts +7 -0
- package/dist/types/src/components/DeckLayout/SidebarButton.d.ts.map +1 -0
- package/dist/types/src/components/DeckLayout/StatusBar.d.ts +1 -2
- package/dist/types/src/components/DeckLayout/StatusBar.d.ts.map +1 -1
- package/dist/types/src/components/DeckLayout/Toast.d.ts +2 -3
- package/dist/types/src/components/DeckLayout/Toast.d.ts.map +1 -1
- package/dist/types/src/components/DeckLayout/Topbar.d.ts +2 -0
- package/dist/types/src/components/DeckLayout/Topbar.d.ts.map +1 -0
- package/dist/types/src/components/LayoutSettings.d.ts +1 -2
- package/dist/types/src/components/LayoutSettings.d.ts.map +1 -1
- package/dist/types/src/components/fragments.d.ts +4 -0
- package/dist/types/src/components/fragments.d.ts.map +1 -0
- package/dist/types/src/components/index.d.ts +0 -2
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/events.d.ts +5 -0
- package/dist/types/src/events.d.ts.map +1 -0
- package/dist/types/src/hooks/useMainSize.d.ts +2 -2
- package/dist/types/src/hooks/useNode.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +3 -2
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/layout.d.ts +5 -19
- package/dist/types/src/layout.d.ts.map +1 -1
- package/dist/types/src/meta.d.ts +4 -4
- package/dist/types/src/meta.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +4 -2
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types.d.ts +121 -20
- package/dist/types/src/types.d.ts.map +1 -1
- package/dist/types/src/util/index.d.ts +4 -2
- package/dist/types/src/util/index.d.ts.map +1 -1
- package/dist/types/src/util/layoutAppliesTopbar.d.ts +2 -0
- package/dist/types/src/util/layoutAppliesTopbar.d.ts.map +1 -0
- package/dist/types/src/util/set-active.d.ts +9 -0
- package/dist/types/src/util/set-active.d.ts.map +1 -0
- package/dist/types/src/util/useBreakpoints.d.ts +2 -0
- package/dist/types/src/util/useBreakpoints.d.ts.map +1 -0
- package/dist/types/src/util/useHoistStatusbar.d.ts +2 -0
- package/dist/types/src/util/useHoistStatusbar.d.ts.map +1 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +32 -37
- package/src/DeckPlugin.ts +87 -0
- package/src/capabilities/app-graph-builder.ts +113 -0
- package/src/capabilities/capabilities.ts +15 -0
- package/src/capabilities/check-app-scheme.ts +44 -0
- package/src/capabilities/index.ts +17 -0
- package/src/capabilities/intent-resolver.ts +368 -0
- package/src/capabilities/react-root.tsx +46 -0
- package/src/capabilities/react-surface.tsx +31 -0
- package/src/capabilities/settings.ts +21 -0
- package/src/capabilities/state.ts +107 -0
- package/src/capabilities/tools.ts +61 -0
- package/src/capabilities/url-handler.ts +65 -0
- package/src/components/DeckLayout/ActiveNode.tsx +2 -3
- package/src/components/DeckLayout/Banner.tsx +37 -0
- package/src/components/DeckLayout/ComplementarySidebar.tsx +142 -59
- package/src/components/DeckLayout/ContentEmpty.tsx +9 -4
- package/src/components/DeckLayout/DeckLayout.tsx +151 -99
- package/src/components/DeckLayout/Fullscreen.tsx +2 -3
- package/src/components/DeckLayout/NodePlankHeading.tsx +64 -77
- package/src/components/DeckLayout/Plank.tsx +35 -43
- package/src/components/DeckLayout/PlankControls.tsx +12 -11
- package/src/components/DeckLayout/PlankError.tsx +6 -5
- package/src/components/DeckLayout/Sidebar.tsx +19 -9
- package/src/components/DeckLayout/SidebarButton.tsx +68 -0
- package/src/components/DeckLayout/StatusBar.tsx +6 -12
- package/src/components/DeckLayout/Toast.tsx +2 -2
- package/src/components/DeckLayout/Topbar.tsx +11 -0
- package/src/components/LayoutSettings.tsx +8 -8
- package/src/components/fragments.ts +14 -0
- package/src/components/index.ts +0 -2
- package/src/events.ts +12 -0
- package/src/hooks/useMainSize.ts +3 -3
- package/src/hooks/useNode.ts +3 -1
- package/src/index.ts +3 -4
- package/src/layout.ts +43 -212
- package/src/meta.ts +3 -2
- package/src/translations.ts +8 -6
- package/src/types.ts +104 -36
- package/src/util/index.ts +4 -2
- package/src/util/layoutAppliesTopbar.ts +7 -0
- package/src/util/set-active.ts +47 -0
- package/src/util/useBreakpoints.ts +11 -0
- package/src/util/useHoistStatusbar.ts +20 -0
- package/dist/lib/browser/chunk-GVOGPULO.mjs.map +0 -7
- package/dist/lib/browser/chunk-ZC3K6C2W.mjs +0 -37
- package/dist/lib/browser/chunk-ZC3K6C2W.mjs.map +0 -7
- package/dist/lib/browser/meta.mjs +0 -9
- package/dist/lib/browser/meta.mjs.map +0 -7
- package/dist/types/src/components/DeckContext.d.ts +0 -8
- package/dist/types/src/components/DeckContext.d.ts.map +0 -1
- package/dist/types/src/components/LayoutContext.d.ts +0 -5
- package/dist/types/src/components/LayoutContext.d.ts.map +0 -1
- package/dist/types/src/layout.test.d.ts +0 -2
- package/dist/types/src/layout.test.d.ts.map +0 -1
- package/dist/types/src/util/check-app-scheme.d.ts +0 -2
- package/dist/types/src/util/check-app-scheme.d.ts.map +0 -1
- package/dist/types/src/util/layout-parts.d.ts +0 -7
- package/dist/types/src/util/layout-parts.d.ts.map +0 -1
- package/src/DeckPlugin.tsx +0 -623
- package/src/components/DeckContext.ts +0 -14
- package/src/components/LayoutContext.ts +0 -12
- package/src/layout.test.ts +0 -380
- package/src/util/check-app-scheme.ts +0 -21
- package/src/util/layout-parts.ts +0 -12
|
@@ -2,56 +2,61 @@
|
|
|
2
2
|
// Copyright 2023 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { Sidebar as MenuIcon } from '@phosphor-icons/react';
|
|
6
5
|
import { untracked } from '@preact/signals-core';
|
|
7
|
-
import React, { useCallback, useEffect, useMemo, useRef, type UIEvent, Fragment } from 'react';
|
|
6
|
+
import React, { useCallback, useEffect, useMemo, useRef, type UIEvent, Fragment, useState } from 'react';
|
|
8
7
|
|
|
9
|
-
import {
|
|
10
|
-
|
|
8
|
+
import {
|
|
9
|
+
LayoutAction,
|
|
10
|
+
createIntent,
|
|
11
|
+
Surface,
|
|
12
|
+
useCapability,
|
|
13
|
+
useIntentDispatcher,
|
|
14
|
+
usePluginManager,
|
|
15
|
+
} from '@dxos/app-framework';
|
|
16
|
+
import { AttentionCapabilities } from '@dxos/plugin-attention';
|
|
11
17
|
import {
|
|
12
18
|
AlertDialog,
|
|
13
|
-
Button,
|
|
14
19
|
Dialog as NaturalDialog,
|
|
15
20
|
Main,
|
|
16
21
|
Popover,
|
|
17
22
|
useOnTransition,
|
|
18
|
-
useTranslation,
|
|
19
23
|
type MainProps,
|
|
24
|
+
useMediaQuery,
|
|
20
25
|
} from '@dxos/react-ui';
|
|
21
26
|
import { Stack, StackContext, DEFAULT_HORIZONTAL_SIZE } from '@dxos/react-ui-stack';
|
|
22
|
-
import {
|
|
27
|
+
import { mainPaddingTransitions } from '@dxos/react-ui-theme';
|
|
23
28
|
|
|
24
29
|
import { ActiveNode } from './ActiveNode';
|
|
25
|
-
import { ComplementarySidebar
|
|
30
|
+
import { ComplementarySidebar } from './ComplementarySidebar';
|
|
26
31
|
import { ContentEmpty } from './ContentEmpty';
|
|
27
32
|
import { Fullscreen } from './Fullscreen';
|
|
28
33
|
import { Plank } from './Plank';
|
|
29
34
|
import { Sidebar } from './Sidebar';
|
|
35
|
+
import { ToggleComplementarySidebarButton, ToggleSidebarButton } from './SidebarButton';
|
|
30
36
|
import { StatusBar } from './StatusBar';
|
|
31
37
|
import { Toast } from './Toast';
|
|
32
|
-
import {
|
|
33
|
-
import {
|
|
34
|
-
import {
|
|
35
|
-
import {
|
|
36
|
-
import {
|
|
38
|
+
import { Topbar } from './Topbar';
|
|
39
|
+
import { DeckCapabilities } from '../../capabilities';
|
|
40
|
+
import { getMode, type Overscroll } from '../../types';
|
|
41
|
+
import { calculateOverscroll, layoutAppliesTopbar, useBreakpoints, useHoistStatusbar } from '../../util';
|
|
42
|
+
import { fixedComplementarySidebarToggleStyles, fixedSidebarToggleStyles } from '../fragments';
|
|
37
43
|
|
|
38
44
|
export type DeckLayoutProps = {
|
|
39
|
-
layoutParts: LayoutParts;
|
|
40
|
-
toasts: ToastSchema[];
|
|
41
45
|
overscroll: Overscroll;
|
|
42
46
|
showHints: boolean;
|
|
43
47
|
onDismissToast: (id: string) => void;
|
|
44
|
-
}
|
|
48
|
+
};
|
|
45
49
|
|
|
46
50
|
const PlankSeparator = ({ index }: { index: number }) =>
|
|
47
51
|
index > 0 ? <span role='separator' className='row-span-2 bg-deck is-4' style={{ gridColumn: index * 2 }} /> : null;
|
|
48
52
|
|
|
49
|
-
export const DeckLayout = ({
|
|
50
|
-
const
|
|
53
|
+
export const DeckLayout = ({ overscroll, showHints, onDismissToast }: DeckLayoutProps) => {
|
|
54
|
+
const { dispatchPromise: dispatch } = useIntentDispatcher();
|
|
55
|
+
const context = useCapability(DeckCapabilities.MutableDeckState);
|
|
51
56
|
const {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
57
|
+
sidebarState,
|
|
58
|
+
complementarySidebarState,
|
|
59
|
+
complementarySidebarPanel,
|
|
55
60
|
dialogOpen,
|
|
56
61
|
dialogContent,
|
|
57
62
|
dialogBlockAlign,
|
|
@@ -59,22 +64,33 @@ export const DeckLayout = ({ layoutParts, toasts, overscroll, showHints, panels,
|
|
|
59
64
|
popoverOpen,
|
|
60
65
|
popoverContent,
|
|
61
66
|
popoverAnchorId,
|
|
67
|
+
deck,
|
|
68
|
+
toasts,
|
|
62
69
|
} = context;
|
|
63
|
-
const {
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
const
|
|
67
|
-
const
|
|
70
|
+
const { active, fullscreen, solo, plankSizing } = deck;
|
|
71
|
+
const breakpoint = useBreakpoints();
|
|
72
|
+
const topbar = layoutAppliesTopbar(breakpoint);
|
|
73
|
+
const hoistStatusbar = useHoistStatusbar(breakpoint);
|
|
74
|
+
const pluginManager = usePluginManager();
|
|
68
75
|
|
|
69
76
|
const scrollLeftRef = useRef<number | null>();
|
|
70
77
|
const deckRef = useRef<HTMLDivElement>(null);
|
|
71
78
|
|
|
72
|
-
|
|
79
|
+
// TODO(thure): This is a workaround for the difference in `React`ion time between displaying a Popover and rendering
|
|
80
|
+
// the anchor further down the tree. Refactor to use VirtualTrigger or some other approach which does not cause a lag.
|
|
81
|
+
const [delayedPopoverVisibility, setDelayedPopoverVisibility] = useState(false);
|
|
82
|
+
useEffect(() => {
|
|
83
|
+
popoverOpen ? setTimeout(() => setDelayedPopoverVisibility(true), 40) : setDelayedPopoverVisibility(false);
|
|
84
|
+
}, [popoverOpen]);
|
|
73
85
|
|
|
74
86
|
// Ensure the first plank is attended when the deck is first rendered.
|
|
75
87
|
useEffect(() => {
|
|
76
|
-
|
|
77
|
-
const
|
|
88
|
+
// NOTE: Not `useAttended` so that the layout component is not re-rendered when the attended list changes.
|
|
89
|
+
const attended = untracked(() => {
|
|
90
|
+
const attention = pluginManager.context.requestCapability(AttentionCapabilities.Attention);
|
|
91
|
+
return attention.current;
|
|
92
|
+
});
|
|
93
|
+
const firstId = solo ?? active[0];
|
|
78
94
|
if (attended.length === 0 && firstId) {
|
|
79
95
|
// TODO(wittjosiah): Focusing the type button is a workaround.
|
|
80
96
|
// If the plank is directly focused on first load the focus ring appears.
|
|
@@ -82,6 +98,27 @@ export const DeckLayout = ({ layoutParts, toasts, overscroll, showHints, panels,
|
|
|
82
98
|
}
|
|
83
99
|
}, []);
|
|
84
100
|
|
|
101
|
+
// Not using `breakpoint` to avoid firing when breakpoint changes between tablet and desktop.
|
|
102
|
+
// `ssr: false` to avoid using fallback values and flashing into solo mode on startup.
|
|
103
|
+
const [isNotMobile] = useMediaQuery('md', { ssr: false });
|
|
104
|
+
const shouldRevert = useRef(false);
|
|
105
|
+
useEffect(() => {
|
|
106
|
+
if (!isNotMobile && getMode(deck) === 'deck') {
|
|
107
|
+
// NOTE: Not `useAttended` so that the layout component is not re-rendered when the attended list changes.
|
|
108
|
+
const attended = untracked(() => {
|
|
109
|
+
const attention = pluginManager.context.requestCapability(AttentionCapabilities.Attention);
|
|
110
|
+
return attention.current;
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
shouldRevert.current = true;
|
|
114
|
+
void dispatch(
|
|
115
|
+
createIntent(LayoutAction.SetLayoutMode, { part: 'mode', subject: attended[0], options: { mode: 'solo' } }),
|
|
116
|
+
);
|
|
117
|
+
} else if (isNotMobile && getMode(deck) === 'solo' && shouldRevert.current) {
|
|
118
|
+
void dispatch(createIntent(LayoutAction.SetLayoutMode, { part: 'mode', options: { revert: true } }));
|
|
119
|
+
}
|
|
120
|
+
}, [isNotMobile, deck, dispatch]);
|
|
121
|
+
|
|
85
122
|
/**
|
|
86
123
|
* Clear scroll restoration state if the window is resized
|
|
87
124
|
*/
|
|
@@ -100,6 +137,7 @@ export const DeckLayout = ({ layoutParts, toasts, overscroll, showHints, panels,
|
|
|
100
137
|
}
|
|
101
138
|
}, []);
|
|
102
139
|
|
|
140
|
+
const layoutMode = getMode(deck);
|
|
103
141
|
useOnTransition(layoutMode, (mode) => mode !== 'deck', 'deck', restoreScroll);
|
|
104
142
|
|
|
105
143
|
/**
|
|
@@ -107,70 +145,72 @@ export const DeckLayout = ({ layoutParts, toasts, overscroll, showHints, panels,
|
|
|
107
145
|
*/
|
|
108
146
|
const handleScroll = useCallback(
|
|
109
147
|
(event: UIEvent) => {
|
|
110
|
-
if (
|
|
148
|
+
if (!solo && event.currentTarget === event.target) {
|
|
111
149
|
scrollLeftRef.current = (event.target as HTMLDivElement).scrollLeft;
|
|
112
150
|
}
|
|
113
151
|
},
|
|
114
|
-
[
|
|
152
|
+
[solo],
|
|
115
153
|
);
|
|
116
154
|
|
|
117
|
-
const isEmpty =
|
|
155
|
+
const isEmpty = !solo && active.length === 0;
|
|
118
156
|
|
|
119
157
|
const padding = useMemo(() => {
|
|
120
|
-
if (
|
|
121
|
-
return calculateOverscroll(
|
|
158
|
+
if (!solo && overscroll === 'centering') {
|
|
159
|
+
return calculateOverscroll(active.length);
|
|
122
160
|
}
|
|
123
161
|
return {};
|
|
124
|
-
}, [
|
|
162
|
+
}, [solo, overscroll, deck]);
|
|
163
|
+
|
|
164
|
+
const mainPosition = useMemo(
|
|
165
|
+
() => [
|
|
166
|
+
'grid !block-start-[env(safe-area-inset-top)]',
|
|
167
|
+
topbar && '!block-start-[calc(env(safe-area-inset-top)+var(--rail-size))]',
|
|
168
|
+
hoistStatusbar && 'lg:block-end-[--statusbar-size]',
|
|
169
|
+
],
|
|
170
|
+
[topbar, hoistStatusbar],
|
|
171
|
+
);
|
|
125
172
|
|
|
126
173
|
const Dialog = dialogType === 'alert' ? AlertDialog : NaturalDialog;
|
|
127
174
|
|
|
175
|
+
const handlePopoverOpenChange = useCallback(
|
|
176
|
+
(nextOpen: boolean) => {
|
|
177
|
+
if (nextOpen && popoverAnchorId) {
|
|
178
|
+
context.popoverOpen = true;
|
|
179
|
+
} else {
|
|
180
|
+
context.popoverOpen = false;
|
|
181
|
+
context.popoverAnchorId = undefined;
|
|
182
|
+
context.popoverSide = undefined;
|
|
183
|
+
}
|
|
184
|
+
},
|
|
185
|
+
[context],
|
|
186
|
+
);
|
|
187
|
+
const handlePopoverClose = useCallback(() => handlePopoverOpenChange(false), [handlePopoverOpenChange]);
|
|
188
|
+
|
|
128
189
|
return (
|
|
129
|
-
<Popover.Root
|
|
130
|
-
modal
|
|
131
|
-
open={!!(popoverAnchorId && popoverOpen)}
|
|
132
|
-
onOpenChange={(nextOpen) => {
|
|
133
|
-
if (nextOpen && popoverAnchorId) {
|
|
134
|
-
context.popoverOpen = true;
|
|
135
|
-
} else {
|
|
136
|
-
context.popoverOpen = false;
|
|
137
|
-
context.popoverAnchorId = undefined;
|
|
138
|
-
}
|
|
139
|
-
}}
|
|
140
|
-
>
|
|
190
|
+
<Popover.Root modal open={!!(popoverAnchorId && delayedPopoverVisibility)} onOpenChange={handlePopoverOpenChange}>
|
|
141
191
|
<ActiveNode />
|
|
142
192
|
|
|
143
|
-
{
|
|
193
|
+
{fullscreen && <Fullscreen id={solo} />}
|
|
144
194
|
|
|
145
|
-
{
|
|
195
|
+
{!fullscreen && (
|
|
146
196
|
<Main.Root
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
197
|
+
navigationSidebarState={context.sidebarState}
|
|
198
|
+
onNavigationSidebarStateChange={(next) => (context.sidebarState = next)}
|
|
199
|
+
complementarySidebarState={context.complementarySidebarState}
|
|
200
|
+
onComplementarySidebarStateChange={(next) => (context.complementarySidebarState = next)}
|
|
151
201
|
>
|
|
152
|
-
{/* Notch */}
|
|
153
|
-
<Main.Notch classNames='z-[21]'>
|
|
154
|
-
<Surface role='notch-start' />
|
|
155
|
-
<Button onClick={() => (context.sidebarOpen = !context.sidebarOpen)} variant='ghost' classNames='p-1'>
|
|
156
|
-
<span className='sr-only'>{t('open navigation sidebar label')}</span>
|
|
157
|
-
<MenuIcon weight='light' className={getSize(5)} />
|
|
158
|
-
</Button>
|
|
159
|
-
<Surface role='notch-end' />
|
|
160
|
-
</Main.Notch>
|
|
161
|
-
|
|
162
202
|
{/* Left sidebar. */}
|
|
163
|
-
<Sidebar
|
|
203
|
+
<Sidebar />
|
|
164
204
|
|
|
165
205
|
{/* Right sidebar. */}
|
|
166
|
-
<ComplementarySidebar
|
|
206
|
+
<ComplementarySidebar current={complementarySidebarPanel} />
|
|
167
207
|
|
|
168
208
|
{/* Dialog overlay to dismiss dialogs. */}
|
|
169
209
|
<Main.Overlay />
|
|
170
210
|
|
|
171
211
|
{/* No content. */}
|
|
172
212
|
{isEmpty && (
|
|
173
|
-
<Main.Content handlesFocus>
|
|
213
|
+
<Main.Content bounce handlesFocus classNames={mainPosition}>
|
|
174
214
|
<ContentEmpty />
|
|
175
215
|
</Main.Content>
|
|
176
216
|
)}
|
|
@@ -179,72 +219,74 @@ export const DeckLayout = ({ layoutParts, toasts, overscroll, showHints, panels,
|
|
|
179
219
|
{!isEmpty && (
|
|
180
220
|
<Main.Content
|
|
181
221
|
bounce
|
|
182
|
-
classNames=
|
|
222
|
+
classNames={mainPosition}
|
|
183
223
|
handlesFocus
|
|
184
224
|
style={
|
|
185
225
|
{
|
|
186
|
-
'--dx-main-sidebarWidth':
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
226
|
+
'--dx-main-sidebarWidth':
|
|
227
|
+
sidebarState === 'expanded'
|
|
228
|
+
? 'var(--nav-sidebar-size)'
|
|
229
|
+
: sidebarState === 'collapsed'
|
|
230
|
+
? 'var(--l0-size)'
|
|
231
|
+
: '0',
|
|
232
|
+
'--dx-main-complementaryWidth':
|
|
233
|
+
complementarySidebarState === 'expanded'
|
|
234
|
+
? 'var(--complementary-sidebar-size)'
|
|
235
|
+
: complementarySidebarState === 'collapsed'
|
|
236
|
+
? 'var(--rail-size)'
|
|
237
|
+
: '0',
|
|
238
|
+
'--dx-main-contentFirstWidth': `${plankSizing[active[0] ?? 'never'] ?? DEFAULT_HORIZONTAL_SIZE}rem`,
|
|
239
|
+
'--dx-main-contentLastWidth': `${plankSizing[active[(active.length ?? 1) - 1] ?? 'never'] ?? DEFAULT_HORIZONTAL_SIZE}rem`,
|
|
192
240
|
} as MainProps['style']
|
|
193
241
|
}
|
|
194
242
|
>
|
|
195
243
|
<div
|
|
196
244
|
role='none'
|
|
197
|
-
className={!
|
|
198
|
-
{...(
|
|
245
|
+
className={!solo ? 'relative bg-deck overflow-hidden' : 'sr-only'}
|
|
246
|
+
{...(solo && { inert: '' })}
|
|
199
247
|
>
|
|
248
|
+
{!topbar && <ToggleSidebarButton classNames={fixedSidebarToggleStyles} />}
|
|
249
|
+
{!topbar && <ToggleComplementarySidebarButton classNames={fixedComplementarySidebarToggleStyles} />}
|
|
200
250
|
<Stack
|
|
201
251
|
orientation='horizontal'
|
|
202
252
|
size='contain'
|
|
203
253
|
classNames={['absolute inset-block-0 -inset-inline-px', mainPaddingTransitions]}
|
|
204
254
|
onScroll={handleScroll}
|
|
205
|
-
itemsCount={2 * (
|
|
255
|
+
itemsCount={2 * (active.length ?? 0) - 1}
|
|
206
256
|
style={padding}
|
|
207
257
|
ref={deckRef}
|
|
208
258
|
>
|
|
209
|
-
{
|
|
210
|
-
<Fragment key={
|
|
259
|
+
{active.map((entryId, index) => (
|
|
260
|
+
<Fragment key={entryId}>
|
|
211
261
|
<PlankSeparator index={index} />
|
|
212
|
-
<Plank
|
|
213
|
-
entry={layoutEntry}
|
|
214
|
-
layoutParts={layoutParts}
|
|
215
|
-
part='main'
|
|
216
|
-
layoutMode={layoutMode}
|
|
217
|
-
order={index * 2 + 1}
|
|
218
|
-
/>
|
|
262
|
+
<Plank id={entryId} part='deck' order={index * 2 + 1} active={active} layoutMode={layoutMode} />
|
|
219
263
|
</Fragment>
|
|
220
264
|
))}
|
|
221
265
|
</Stack>
|
|
222
266
|
</div>
|
|
223
267
|
<div
|
|
224
268
|
role='none'
|
|
225
|
-
className={
|
|
226
|
-
{...(!
|
|
269
|
+
className={solo ? 'relative bg-deck overflow-hidden' : 'sr-only'}
|
|
270
|
+
{...(!solo && { inert: '' })}
|
|
227
271
|
>
|
|
272
|
+
{!topbar && <ToggleSidebarButton classNames={fixedSidebarToggleStyles} />}
|
|
273
|
+
{!topbar && <ToggleComplementarySidebarButton classNames={fixedComplementarySidebarToggleStyles} />}
|
|
228
274
|
<StackContext.Provider value={{ size: 'contain', orientation: 'horizontal', rail: true }}>
|
|
229
|
-
<Plank
|
|
275
|
+
<Plank id={solo} part='solo' layoutMode={layoutMode} />
|
|
230
276
|
</StackContext.Provider>
|
|
231
277
|
</div>
|
|
232
278
|
</Main.Content>
|
|
233
279
|
)}
|
|
234
280
|
|
|
235
|
-
{/*
|
|
236
|
-
<
|
|
281
|
+
{/* Status bar. */}
|
|
282
|
+
{topbar && <Topbar />}
|
|
283
|
+
{hoistStatusbar && <StatusBar showHints={showHints} />}
|
|
237
284
|
</Main.Root>
|
|
238
285
|
)}
|
|
239
286
|
|
|
240
287
|
{/* Global popovers. */}
|
|
241
288
|
<Popover.Portal>
|
|
242
|
-
<Popover.Content
|
|
243
|
-
onEscapeKeyDown={() => {
|
|
244
|
-
context.popoverOpen = false;
|
|
245
|
-
context.popoverAnchorId = undefined;
|
|
246
|
-
}}
|
|
247
|
-
>
|
|
289
|
+
<Popover.Content side={context.popoverSide} onEscapeKeyDown={handlePopoverClose}>
|
|
248
290
|
<Popover.Viewport>
|
|
249
291
|
<Surface role='popover' data={popoverContent} limit={1} />
|
|
250
292
|
</Popover.Viewport>
|
|
@@ -253,10 +295,20 @@ export const DeckLayout = ({ layoutParts, toasts, overscroll, showHints, panels,
|
|
|
253
295
|
</Popover.Portal>
|
|
254
296
|
|
|
255
297
|
{/* Global dialog. */}
|
|
256
|
-
|
|
257
|
-
|
|
298
|
+
{/* TODO(thure): End block alignment affecting `modal` and whether the surface renders in an overlay is tailored
|
|
299
|
+
to the needs of the ambient chat dialog. As the feature matures, consider separating concerns. */}
|
|
300
|
+
<Dialog.Root
|
|
301
|
+
modal={dialogBlockAlign !== 'end'}
|
|
302
|
+
open={dialogOpen}
|
|
303
|
+
onOpenChange={(nextOpen) => (context.dialogOpen = nextOpen)}
|
|
304
|
+
>
|
|
305
|
+
{dialogBlockAlign === 'end' ? (
|
|
258
306
|
<Surface role='dialog' data={dialogContent} limit={1} />
|
|
259
|
-
|
|
307
|
+
) : (
|
|
308
|
+
<Dialog.Overlay blockAlign={dialogBlockAlign}>
|
|
309
|
+
<Surface role='dialog' data={dialogContent} limit={1} />
|
|
310
|
+
</Dialog.Overlay>
|
|
311
|
+
)}
|
|
260
312
|
</Dialog.Root>
|
|
261
313
|
|
|
262
314
|
{/* Global toasts. */}
|
|
@@ -4,8 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import React from 'react';
|
|
6
6
|
|
|
7
|
-
import { Surface } from '@dxos/app-framework';
|
|
8
|
-
import { useGraph } from '@dxos/plugin-graph';
|
|
7
|
+
import { Surface, useAppGraph } from '@dxos/app-framework';
|
|
9
8
|
import { fixedInsetFlexLayout } from '@dxos/react-ui-theme';
|
|
10
9
|
|
|
11
10
|
import { Fallback } from './Fallback';
|
|
@@ -13,7 +12,7 @@ import { SURFACE_PREFIX } from './constants';
|
|
|
13
12
|
import { useNode } from '../../hooks';
|
|
14
13
|
|
|
15
14
|
export const Fullscreen = ({ id }: { id?: string }) => {
|
|
16
|
-
const { graph } =
|
|
15
|
+
const { graph } = useAppGraph();
|
|
17
16
|
const fullScreenNode = useNode(graph, id);
|
|
18
17
|
|
|
19
18
|
return (
|
|
@@ -2,28 +2,23 @@
|
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import React, { Fragment, memo, useEffect, useMemo } from 'react';
|
|
5
|
+
import React, { Fragment, memo, useCallback, useEffect, useMemo } from 'react';
|
|
6
6
|
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
NavigationAction,
|
|
11
|
-
SLUG_PATH_SEPARATOR,
|
|
12
|
-
Surface,
|
|
13
|
-
useIntentDispatcher,
|
|
14
|
-
type LayoutCoordinate,
|
|
15
|
-
} from '@dxos/app-framework';
|
|
16
|
-
import { type Node, useGraph } from '@dxos/plugin-graph';
|
|
17
|
-
import { Icon, Popover, toLocalizedString, useMediaQuery, useTranslation, IconButton } from '@dxos/react-ui';
|
|
7
|
+
import { createIntent, LayoutAction, Surface, useAppGraph, useIntentDispatcher } from '@dxos/app-framework';
|
|
8
|
+
import { type Node } from '@dxos/plugin-graph';
|
|
9
|
+
import { Icon, Popover, toLocalizedString, useTranslation } from '@dxos/react-ui';
|
|
18
10
|
import { StackItem, type StackItemSigilAction } from '@dxos/react-ui-stack';
|
|
19
11
|
import { TextTooltip } from '@dxos/react-ui-text-tooltip';
|
|
20
12
|
|
|
21
13
|
import { PlankControls } from './PlankControls';
|
|
22
14
|
import { DECK_PLUGIN } from '../../meta';
|
|
23
|
-
import {
|
|
15
|
+
import { DeckAction, SLUG_PATH_SEPARATOR } from '../../types';
|
|
16
|
+
import { useBreakpoints } from '../../util';
|
|
17
|
+
import { soloInlinePadding } from '../fragments';
|
|
24
18
|
|
|
25
19
|
export type NodePlankHeadingProps = {
|
|
26
|
-
|
|
20
|
+
id: string;
|
|
21
|
+
part: 'solo' | 'deck' | 'complementary';
|
|
27
22
|
node?: Node;
|
|
28
23
|
canIncrementStart?: boolean;
|
|
29
24
|
canIncrementEnd?: boolean;
|
|
@@ -34,7 +29,8 @@ export type NodePlankHeadingProps = {
|
|
|
34
29
|
|
|
35
30
|
export const NodePlankHeading = memo(
|
|
36
31
|
({
|
|
37
|
-
|
|
32
|
+
id,
|
|
33
|
+
part,
|
|
38
34
|
node,
|
|
39
35
|
canIncrementStart,
|
|
40
36
|
canIncrementEnd,
|
|
@@ -42,16 +38,15 @@ export const NodePlankHeading = memo(
|
|
|
42
38
|
pending,
|
|
43
39
|
actions = [],
|
|
44
40
|
}: NodePlankHeadingProps) => {
|
|
45
|
-
const layoutContext = useLayout();
|
|
46
41
|
const { t } = useTranslation(DECK_PLUGIN);
|
|
47
|
-
const { graph } =
|
|
42
|
+
const { graph } = useAppGraph();
|
|
43
|
+
const breakpoint = useBreakpoints();
|
|
48
44
|
const icon = node?.properties?.icon ?? 'ph--placeholder--regular';
|
|
49
45
|
const label = pending
|
|
50
46
|
? t('pending heading')
|
|
51
47
|
: toLocalizedString(node?.properties?.label ?? ['plank heading fallback label', { ns: DECK_PLUGIN }], t);
|
|
52
48
|
const { dispatchPromise: dispatch } = useIntentDispatcher();
|
|
53
49
|
const ActionRoot = node && popoverAnchorId === `dxos.org/ui/${DECK_PLUGIN}/${node.id}` ? Popover.Anchor : Fragment;
|
|
54
|
-
const [isNotMobile] = useMediaQuery('md');
|
|
55
50
|
|
|
56
51
|
useEffect(() => {
|
|
57
52
|
const frame = requestAnimationFrame(() => {
|
|
@@ -62,31 +57,65 @@ export const NodePlankHeading = memo(
|
|
|
62
57
|
return () => cancelAnimationFrame(frame);
|
|
63
58
|
}, [node]);
|
|
64
59
|
|
|
65
|
-
const layoutPart = coordinate.part;
|
|
66
60
|
// NOTE(Zan): Node ids may now contain a path like `${space}:${id}~comments`
|
|
67
|
-
const attendableId =
|
|
61
|
+
const attendableId = id.split(SLUG_PATH_SEPARATOR).at(0);
|
|
68
62
|
const capabilities = useMemo(
|
|
69
63
|
() => ({
|
|
70
|
-
solo: (
|
|
64
|
+
solo: breakpoint !== 'mobile' && (part === 'solo' || part === 'deck'),
|
|
71
65
|
incrementStart: canIncrementStart,
|
|
72
66
|
incrementEnd: canIncrementEnd,
|
|
73
67
|
}),
|
|
74
|
-
[
|
|
68
|
+
[breakpoint, part, canIncrementStart, canIncrementEnd],
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
const sigilActions = useMemo(
|
|
72
|
+
() => node && [actions, graph.actions(node)].filter((a) => a.length > 0),
|
|
73
|
+
[actions, node, graph],
|
|
74
|
+
);
|
|
75
|
+
const handleAction = useCallback((action: StackItemSigilAction) => {
|
|
76
|
+
typeof action.data === 'function' && action.data?.({ node: action as Node, caller: DECK_PLUGIN });
|
|
77
|
+
}, []);
|
|
78
|
+
|
|
79
|
+
const handlePlankAction = useCallback(
|
|
80
|
+
(eventType: DeckAction.PartAdjustment) => {
|
|
81
|
+
if (eventType === 'solo') {
|
|
82
|
+
return dispatch(createIntent(DeckAction.Adjust, { type: eventType, id }));
|
|
83
|
+
} else if (eventType === 'close') {
|
|
84
|
+
if (part === 'complementary') {
|
|
85
|
+
return dispatch(
|
|
86
|
+
createIntent(LayoutAction.UpdateComplementary, {
|
|
87
|
+
part: 'complementary',
|
|
88
|
+
options: { state: 'collapsed' },
|
|
89
|
+
}),
|
|
90
|
+
);
|
|
91
|
+
} else {
|
|
92
|
+
return dispatch(
|
|
93
|
+
createIntent(LayoutAction.Close, { part: 'main', subject: [id], options: { state: false } }),
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
} else {
|
|
97
|
+
return dispatch(createIntent(DeckAction.Adjust, { type: eventType, id }));
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
[dispatch, id, part],
|
|
75
101
|
);
|
|
76
102
|
|
|
77
103
|
return (
|
|
78
|
-
<StackItem.Heading
|
|
104
|
+
<StackItem.Heading
|
|
105
|
+
classNames={[
|
|
106
|
+
'plb-1 border-be border-separator items-stretch gap-1 sticky inline-start-12 app-drag',
|
|
107
|
+
part === 'solo' ? soloInlinePadding : 'pli-1',
|
|
108
|
+
]}
|
|
109
|
+
>
|
|
79
110
|
<ActionRoot>
|
|
80
|
-
{node ? (
|
|
111
|
+
{node && sigilActions ? (
|
|
81
112
|
<StackItem.Sigil
|
|
82
113
|
icon={icon}
|
|
83
|
-
related={
|
|
114
|
+
related={part === 'complementary'}
|
|
84
115
|
attendableId={attendableId}
|
|
85
116
|
triggerLabel={t('actions menu label')}
|
|
86
|
-
actions={
|
|
87
|
-
onAction={
|
|
88
|
-
typeof action.data === 'function' && action.data?.({ node: action as Node, caller: DECK_PLUGIN })
|
|
89
|
-
}
|
|
117
|
+
actions={sigilActions}
|
|
118
|
+
onAction={handleAction}
|
|
90
119
|
>
|
|
91
120
|
<Surface role='menu-footer' data={{ subject: node.data }} />
|
|
92
121
|
</StackItem.Sigil>
|
|
@@ -100,61 +129,19 @@ export const NodePlankHeading = memo(
|
|
|
100
129
|
<TextTooltip text={label} onlyWhenTruncating>
|
|
101
130
|
<StackItem.HeadingLabel
|
|
102
131
|
attendableId={attendableId}
|
|
103
|
-
related={
|
|
132
|
+
related={part === 'complementary'}
|
|
104
133
|
{...(pending && { classNames: 'text-description' })}
|
|
105
134
|
>
|
|
106
135
|
{label}
|
|
107
136
|
</StackItem.HeadingLabel>
|
|
108
137
|
</TextTooltip>
|
|
109
|
-
{node &&
|
|
110
|
-
// TODO(Zan): What are we doing with layout coordinate here?
|
|
111
|
-
<Surface role='navbar-end' data={{ subject: node.data }} />
|
|
112
|
-
)}
|
|
113
|
-
{/* NOTE(thure): Pinning & unpinning are temporarily disabled */}
|
|
138
|
+
{node && part !== 'complementary' && <Surface role='navbar-end' data={{ subject: node.data }} />}
|
|
114
139
|
<PlankControls
|
|
115
140
|
capabilities={capabilities}
|
|
116
|
-
isSolo={
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
return;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
// TODO(Zan): Update this to use the new layout actions.
|
|
124
|
-
if (eventType === 'solo') {
|
|
125
|
-
return dispatch(
|
|
126
|
-
createIntent(NavigationAction.Adjust, {
|
|
127
|
-
type: eventType,
|
|
128
|
-
layoutCoordinate: { part: 'main', entryId: coordinate.entryId },
|
|
129
|
-
}),
|
|
130
|
-
);
|
|
131
|
-
} else if (eventType === 'close') {
|
|
132
|
-
if (layoutPart === 'complementary') {
|
|
133
|
-
return dispatch(createIntent(LayoutAction.SetLayout, { element: 'complementary', state: false }));
|
|
134
|
-
} else {
|
|
135
|
-
return dispatch(
|
|
136
|
-
createIntent(NavigationAction.Close, { activeParts: { [layoutPart]: [coordinate.entryId] } }),
|
|
137
|
-
);
|
|
138
|
-
}
|
|
139
|
-
} else {
|
|
140
|
-
return dispatch(createIntent(NavigationAction.Adjust, { type: eventType, layoutCoordinate: coordinate }));
|
|
141
|
-
}
|
|
142
|
-
}}
|
|
143
|
-
close={layoutPart === 'complementary' ? 'minify-end' : true}
|
|
144
|
-
>
|
|
145
|
-
{/* TODO(wittjosiah): This doesn't behave exactly the same as the rest of the button group. */}
|
|
146
|
-
{layoutPart !== 'complementary' && (
|
|
147
|
-
<IconButton
|
|
148
|
-
iconOnly
|
|
149
|
-
onClick={() => (layoutContext.complementarySidebarOpen = !layoutContext.complementarySidebarOpen)}
|
|
150
|
-
variant='ghost'
|
|
151
|
-
label={t('open complementary sidebar label')}
|
|
152
|
-
classNames='!pli-2 !plb-3 [&>svg]:-scale-x-100'
|
|
153
|
-
icon='ph--sidebar-simple--regular'
|
|
154
|
-
size={4}
|
|
155
|
-
/>
|
|
156
|
-
)}
|
|
157
|
-
</PlankControls>
|
|
141
|
+
isSolo={part === 'solo'}
|
|
142
|
+
onClick={handlePlankAction}
|
|
143
|
+
close={part === 'complementary' ? 'minify-end' : true}
|
|
144
|
+
/>
|
|
158
145
|
</StackItem.Heading>
|
|
159
146
|
);
|
|
160
147
|
},
|