@dxos/plugin-deck 0.6.14-main.7bd9c89 → 0.6.14-staging.934c9de
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/index.mjs +123 -127
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/meta.json +1 -1
- package/dist/types/src/DeckPlugin.d.ts.map +1 -1
- package/dist/types/src/components/DeckLayout/ActiveNode.d.ts +1 -3
- package/dist/types/src/components/DeckLayout/ActiveNode.d.ts.map +1 -1
- package/dist/types/src/components/DeckLayout/ComplementarySidebar.d.ts +2 -4
- package/dist/types/src/components/DeckLayout/ComplementarySidebar.d.ts.map +1 -1
- package/dist/types/src/components/DeckLayout/DeckLayout.d.ts.map +1 -1
- package/dist/types/src/components/DeckLayout/NodePlankHeading.d.ts +7 -6
- package/dist/types/src/components/DeckLayout/NodePlankHeading.d.ts.map +1 -1
- package/dist/types/src/components/DeckLayout/Plank.d.ts +1 -1
- package/dist/types/src/components/DeckLayout/Plank.d.ts.map +1 -1
- package/dist/types/src/components/DeckLayout/PlankError.d.ts +1 -2
- package/dist/types/src/components/DeckLayout/PlankError.d.ts.map +1 -1
- package/dist/types/src/components/DeckLayout/Sidebar.d.ts.map +1 -1
- package/package.json +32 -31
- package/src/DeckPlugin.tsx +13 -25
- package/src/components/DeckLayout/ActiveNode.tsx +4 -1
- package/src/components/DeckLayout/ComplementarySidebar.tsx +12 -10
- package/src/components/DeckLayout/DeckLayout.tsx +7 -18
- package/src/components/DeckLayout/NodePlankHeading.tsx +127 -124
- package/src/components/DeckLayout/Plank.tsx +28 -19
- package/src/components/DeckLayout/PlankError.tsx +1 -9
- package/src/components/DeckLayout/Sidebar.tsx +5 -7
- package/src/components/LayoutSettings.tsx +13 -13
|
@@ -3,11 +3,12 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import { Sidebar as MenuIcon } from '@phosphor-icons/react';
|
|
6
|
+
import { untracked } from '@preact/signals-core';
|
|
6
7
|
import React, { useCallback, useEffect, useMemo, useRef, type UIEvent } from 'react';
|
|
7
8
|
|
|
8
9
|
import { type LayoutParts, Surface, type Toast as ToastSchema, firstIdInPart, usePlugin } from '@dxos/app-framework';
|
|
10
|
+
import { type AttentionPluginProvides } from '@dxos/plugin-attention';
|
|
9
11
|
import { Button, Dialog, Main, Popover, useOnTransition, useTranslation } from '@dxos/react-ui';
|
|
10
|
-
import { useAttended } from '@dxos/react-ui-attention';
|
|
11
12
|
import { Deck } from '@dxos/react-ui-deck';
|
|
12
13
|
import { getSize, mainPaddingTransitions } from '@dxos/react-ui-theme';
|
|
13
14
|
|
|
@@ -60,7 +61,8 @@ export const DeckLayout = ({
|
|
|
60
61
|
} = context;
|
|
61
62
|
const { t } = useTranslation(DECK_PLUGIN);
|
|
62
63
|
const { plankSizing } = useDeckContext();
|
|
63
|
-
|
|
64
|
+
// NOTE: Not `useAttended` so that the layout component is not re-rendered when the attended list changes.
|
|
65
|
+
const attentionPlugin = usePlugin<AttentionPluginProvides>('dxos.org/plugin/attention');
|
|
64
66
|
const searchPlugin = usePlugin('dxos.org/plugin/search');
|
|
65
67
|
const fullScreenSlug = useMemo(() => firstIdInPart(layoutParts, 'fullScreen'), [layoutParts]);
|
|
66
68
|
|
|
@@ -69,6 +71,7 @@ export const DeckLayout = ({
|
|
|
69
71
|
|
|
70
72
|
// Ensure the first plank is attended when the deck is first rendered.
|
|
71
73
|
useEffect(() => {
|
|
74
|
+
const attended = untracked(() => attentionPlugin?.provides.attention.attended ?? []);
|
|
72
75
|
const firstId = layoutMode === 'solo' ? firstIdInPart(layoutParts, 'solo') : firstIdInPart(layoutParts, 'main');
|
|
73
76
|
if (attended.length === 0 && firstId) {
|
|
74
77
|
// TODO(wittjosiah): Focusing the type button is a workaround.
|
|
@@ -109,18 +112,6 @@ export const DeckLayout = ({
|
|
|
109
112
|
[layoutMode],
|
|
110
113
|
);
|
|
111
114
|
|
|
112
|
-
const firstAttendedId = attended[0];
|
|
113
|
-
useEffect(() => {
|
|
114
|
-
// TODO(burdon): Can we prevent the need to re-scroll since the planks are preserved?
|
|
115
|
-
// E.g., hide the deck and just move the solo article?
|
|
116
|
-
if (layoutMode === 'deck' && firstAttendedId) {
|
|
117
|
-
// setTimeout(() => {
|
|
118
|
-
// const el = deckRef.current?.querySelector(`article[data-attendable-id="${firstAttendedId}"]`);
|
|
119
|
-
// el?.scrollIntoView({ behavior: 'smooth', inline: 'center' });
|
|
120
|
-
// }, 0);
|
|
121
|
-
}
|
|
122
|
-
}, [layoutMode, firstAttendedId]);
|
|
123
|
-
|
|
124
115
|
const isEmpty = layoutParts.main?.length === 0 && layoutParts.solo?.length === 0;
|
|
125
116
|
|
|
126
117
|
const padding = useMemo(() => {
|
|
@@ -147,8 +138,7 @@ export const DeckLayout = ({
|
|
|
147
138
|
}
|
|
148
139
|
}}
|
|
149
140
|
>
|
|
150
|
-
|
|
151
|
-
<ActiveNode id={firstAttendedId} />
|
|
141
|
+
<ActiveNode />
|
|
152
142
|
|
|
153
143
|
<Main.Root
|
|
154
144
|
navigationSidebarOpen={context.sidebarOpen}
|
|
@@ -178,8 +168,7 @@ export const DeckLayout = ({
|
|
|
178
168
|
<Sidebar layoutParts={layoutParts} />
|
|
179
169
|
|
|
180
170
|
{/* Right sidebar. */}
|
|
181
|
-
{
|
|
182
|
-
<ComplementarySidebar context='comments' layoutParts={layoutParts} flatDeck={flatDeck} />
|
|
171
|
+
<ComplementarySidebar panel={layoutParts.complementary?.[0].id} flatDeck={flatDeck} />
|
|
183
172
|
|
|
184
173
|
{/* Dialog overlay to dismiss dialogs. */}
|
|
185
174
|
<Main.Overlay />
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import React, { Fragment, useEffect } from 'react';
|
|
5
|
+
import React, { Fragment, memo, useEffect, useMemo } from 'react';
|
|
6
6
|
|
|
7
7
|
import {
|
|
8
8
|
LayoutAction,
|
|
@@ -10,10 +10,7 @@ import {
|
|
|
10
10
|
SLUG_PATH_SEPARATOR,
|
|
11
11
|
Surface,
|
|
12
12
|
useIntentDispatcher,
|
|
13
|
-
|
|
14
|
-
partLength,
|
|
15
|
-
type LayoutParts,
|
|
16
|
-
type LayoutPart,
|
|
13
|
+
type LayoutCoordinate,
|
|
17
14
|
} from '@dxos/app-framework';
|
|
18
15
|
import { type Node, useGraph } from '@dxos/plugin-graph';
|
|
19
16
|
import { Icon, Popover, toLocalizedString, useMediaQuery, useTranslation } from '@dxos/react-ui';
|
|
@@ -22,137 +19,143 @@ import { TextTooltip } from '@dxos/react-ui-text-tooltip';
|
|
|
22
19
|
|
|
23
20
|
import { DECK_PLUGIN } from '../../meta';
|
|
24
21
|
|
|
25
|
-
export
|
|
26
|
-
|
|
27
|
-
id,
|
|
28
|
-
layoutParts,
|
|
29
|
-
layoutPart,
|
|
30
|
-
popoverAnchorId,
|
|
31
|
-
pending,
|
|
32
|
-
flatDeck,
|
|
33
|
-
actions = [],
|
|
34
|
-
}: {
|
|
22
|
+
export type NodePlankHeadingProps = {
|
|
23
|
+
coordinate: LayoutCoordinate;
|
|
35
24
|
node?: Node;
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
layoutPart?: LayoutPart;
|
|
25
|
+
canIncrementStart?: boolean;
|
|
26
|
+
canIncrementEnd?: boolean;
|
|
39
27
|
popoverAnchorId?: string;
|
|
40
28
|
pending?: boolean;
|
|
41
29
|
flatDeck?: boolean;
|
|
42
30
|
actions?: PlankHeadingAction[];
|
|
43
|
-
}
|
|
44
|
-
const { t } = useTranslation(DECK_PLUGIN);
|
|
45
|
-
const { graph } = useGraph();
|
|
46
|
-
const icon = node?.properties?.icon ?? 'ph--placeholder--regular';
|
|
47
|
-
const label = pending
|
|
48
|
-
? t('pending heading')
|
|
49
|
-
: toLocalizedString(node?.properties?.label ?? ['plank heading fallback label', { ns: DECK_PLUGIN }], t);
|
|
50
|
-
const dispatch = useIntentDispatcher();
|
|
51
|
-
const ActionRoot = node && popoverAnchorId === `dxos.org/ui/${DECK_PLUGIN}/${node.id}` ? Popover.Anchor : Fragment;
|
|
52
|
-
const [isNotMobile] = useMediaQuery('md');
|
|
53
|
-
|
|
54
|
-
useEffect(() => {
|
|
55
|
-
const frame = requestAnimationFrame(() => {
|
|
56
|
-
// Load actions for the node.
|
|
57
|
-
node && graph.actions(node);
|
|
58
|
-
});
|
|
31
|
+
};
|
|
59
32
|
|
|
60
|
-
|
|
61
|
-
|
|
33
|
+
export const NodePlankHeading = memo(
|
|
34
|
+
({
|
|
35
|
+
coordinate,
|
|
36
|
+
node,
|
|
37
|
+
canIncrementStart,
|
|
38
|
+
canIncrementEnd,
|
|
39
|
+
popoverAnchorId,
|
|
40
|
+
pending,
|
|
41
|
+
flatDeck,
|
|
42
|
+
actions = [],
|
|
43
|
+
}: NodePlankHeadingProps) => {
|
|
44
|
+
const { t } = useTranslation(DECK_PLUGIN);
|
|
45
|
+
const { graph } = useGraph();
|
|
46
|
+
const icon = node?.properties?.icon ?? 'ph--placeholder--regular';
|
|
47
|
+
const label = pending
|
|
48
|
+
? t('pending heading')
|
|
49
|
+
: toLocalizedString(node?.properties?.label ?? ['plank heading fallback label', { ns: DECK_PLUGIN }], t);
|
|
50
|
+
const dispatch = useIntentDispatcher();
|
|
51
|
+
const ActionRoot = node && popoverAnchorId === `dxos.org/ui/${DECK_PLUGIN}/${node.id}` ? Popover.Anchor : Fragment;
|
|
52
|
+
const [isNotMobile] = useMediaQuery('md');
|
|
62
53
|
|
|
63
|
-
|
|
64
|
-
|
|
54
|
+
useEffect(() => {
|
|
55
|
+
const frame = requestAnimationFrame(() => {
|
|
56
|
+
// Load actions for the node.
|
|
57
|
+
node && graph.actions(node);
|
|
58
|
+
});
|
|
65
59
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
const length = partLength(layoutParts, layoutPart);
|
|
60
|
+
return () => cancelAnimationFrame(frame);
|
|
61
|
+
}, [node]);
|
|
69
62
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
63
|
+
const layoutPart = coordinate.part;
|
|
64
|
+
// NOTE(Zan): Node ids may now contain a path like `${space}:${id}~comments`
|
|
65
|
+
const attendableId = coordinate.entryId.split(SLUG_PATH_SEPARATOR).at(0);
|
|
66
|
+
const capabilities = useMemo(
|
|
67
|
+
() => ({
|
|
68
|
+
solo: (layoutPart === 'solo' || layoutPart === 'main') && isNotMobile,
|
|
69
|
+
incrementStart: canIncrementStart,
|
|
70
|
+
incrementEnd: canIncrementEnd,
|
|
71
|
+
}),
|
|
72
|
+
[isNotMobile, layoutPart, canIncrementStart, canIncrementEnd],
|
|
73
|
+
);
|
|
73
74
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
75
|
+
return (
|
|
76
|
+
<PlankHeading.Root
|
|
77
|
+
{...((layoutPart !== 'main' || !flatDeck) && { classNames: 'pie-1 border-b border-separator' })}
|
|
78
|
+
>
|
|
79
|
+
<ActionRoot>
|
|
80
|
+
{node ? (
|
|
81
|
+
<PlankHeading.ActionsMenu
|
|
82
|
+
icon={icon}
|
|
83
|
+
related={layoutPart === 'complementary'}
|
|
84
|
+
attendableId={attendableId}
|
|
85
|
+
triggerLabel={t('actions menu label')}
|
|
86
|
+
actions={[actions, graph.actions(node)].filter((a) => a.length > 0)}
|
|
87
|
+
onAction={(action) =>
|
|
88
|
+
typeof action.data === 'function' && action.data?.({ node: action as Node, caller: DECK_PLUGIN })
|
|
89
|
+
}
|
|
90
|
+
>
|
|
91
|
+
<Surface role='menu-footer' data={{ object: node.data }} />
|
|
92
|
+
</PlankHeading.ActionsMenu>
|
|
93
|
+
) : (
|
|
94
|
+
<PlankHeading.Button>
|
|
95
|
+
<span className='sr-only'>{label}</span>
|
|
96
|
+
<Icon icon={icon} size={5} />
|
|
97
|
+
</PlankHeading.Button>
|
|
98
|
+
)}
|
|
99
|
+
</ActionRoot>
|
|
100
|
+
<TextTooltip text={label} onlyWhenTruncating>
|
|
101
|
+
<PlankHeading.Label
|
|
81
102
|
attendableId={attendableId}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
onAction={(action) =>
|
|
85
|
-
typeof action.data === 'function' && action.data?.({ node: action as Node, caller: DECK_PLUGIN })
|
|
86
|
-
}
|
|
103
|
+
related={layoutPart === 'complementary'}
|
|
104
|
+
{...(pending && { classNames: 'text-description' })}
|
|
87
105
|
>
|
|
88
|
-
|
|
89
|
-
</PlankHeading.
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
</PlankHeading.Button>
|
|
106
|
+
{label}
|
|
107
|
+
</PlankHeading.Label>
|
|
108
|
+
</TextTooltip>
|
|
109
|
+
{node && layoutPart !== 'complementary' && (
|
|
110
|
+
// TODO(Zan): What are we doing with layout coordinate here?
|
|
111
|
+
<Surface role='navbar-end' direction='inline-reverse' data={{ object: node.data }} />
|
|
95
112
|
)}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
</PlankHeading.Label>
|
|
105
|
-
</TextTooltip>
|
|
106
|
-
{node && layoutPart !== 'complementary' && (
|
|
107
|
-
// TODO(Zan): What are we doing with layout coordinate here?
|
|
108
|
-
<Surface role='navbar-end' direction='inline-reverse' data={{ object: node.data }} />
|
|
109
|
-
)}
|
|
110
|
-
{/* NOTE(thure): Pinning & unpinning are temporarily disabled */}
|
|
111
|
-
<PlankHeading.Controls
|
|
112
|
-
capabilities={{
|
|
113
|
-
solo: (layoutPart === 'solo' || layoutPart === 'main') && isNotMobile,
|
|
114
|
-
incrementStart: canIncrementStart,
|
|
115
|
-
incrementEnd: canIncrementEnd,
|
|
116
|
-
}}
|
|
117
|
-
isSolo={layoutPart === 'solo'}
|
|
118
|
-
onClick={(eventType) => {
|
|
119
|
-
if (!layoutPart) {
|
|
120
|
-
return;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
if (eventType === 'solo') {
|
|
124
|
-
return dispatch([
|
|
125
|
-
{
|
|
126
|
-
action: NavigationAction.ADJUST,
|
|
127
|
-
data: { type: eventType, layoutCoordinate: { part: 'main', entryId: id } },
|
|
128
|
-
},
|
|
129
|
-
]);
|
|
130
|
-
}
|
|
113
|
+
{/* NOTE(thure): Pinning & unpinning are temporarily disabled */}
|
|
114
|
+
<PlankHeading.Controls
|
|
115
|
+
capabilities={capabilities}
|
|
116
|
+
isSolo={layoutPart === 'solo'}
|
|
117
|
+
onClick={(eventType) => {
|
|
118
|
+
if (!layoutPart) {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
131
121
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
122
|
+
// TODO(Zan): Update this to use the new layout actions.
|
|
123
|
+
if (eventType === 'solo') {
|
|
124
|
+
return dispatch([
|
|
125
|
+
{
|
|
126
|
+
action: NavigationAction.ADJUST,
|
|
127
|
+
data: { type: eventType, layoutCoordinate: { part: 'main', entryId: coordinate.entryId } },
|
|
128
|
+
},
|
|
129
|
+
]);
|
|
130
|
+
} else if (eventType === 'close') {
|
|
131
|
+
if (layoutPart === 'complementary') {
|
|
132
|
+
return dispatch({
|
|
133
|
+
action: LayoutAction.SET_LAYOUT,
|
|
134
|
+
data: {
|
|
135
|
+
element: 'complementary',
|
|
136
|
+
state: false,
|
|
137
|
+
},
|
|
138
|
+
});
|
|
139
|
+
} else {
|
|
140
|
+
return dispatch({
|
|
141
|
+
action: NavigationAction.CLOSE,
|
|
142
|
+
data: {
|
|
143
|
+
activeParts: {
|
|
144
|
+
[layoutPart]: [coordinate.entryId],
|
|
149
145
|
},
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
}
|
|
146
|
+
},
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
} else {
|
|
150
|
+
return dispatch({
|
|
151
|
+
action: NavigationAction.ADJUST,
|
|
152
|
+
data: { type: eventType, layoutCoordinate: coordinate },
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
}}
|
|
156
|
+
close={layoutPart === 'complementary' ? 'minify-end' : true}
|
|
157
|
+
/>
|
|
158
|
+
</PlankHeading.Root>
|
|
159
|
+
);
|
|
160
|
+
},
|
|
161
|
+
);
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import { Plus } from '@phosphor-icons/react';
|
|
6
|
-
import React, { type KeyboardEvent, useCallback, useLayoutEffect, useRef } from 'react';
|
|
6
|
+
import React, { type KeyboardEvent, memo, useCallback, useLayoutEffect, useMemo, useRef } from 'react';
|
|
7
7
|
|
|
8
8
|
import {
|
|
9
9
|
LayoutAction,
|
|
@@ -15,6 +15,8 @@ import {
|
|
|
15
15
|
Surface,
|
|
16
16
|
useIntentDispatcher,
|
|
17
17
|
type Layout,
|
|
18
|
+
indexInPart,
|
|
19
|
+
partLength,
|
|
18
20
|
} from '@dxos/app-framework';
|
|
19
21
|
import { debounce } from '@dxos/async';
|
|
20
22
|
import { useGraph } from '@dxos/plugin-graph';
|
|
@@ -42,7 +44,7 @@ export type PlankProps = {
|
|
|
42
44
|
searchEnabled?: boolean;
|
|
43
45
|
};
|
|
44
46
|
|
|
45
|
-
export const Plank = ({ entry, layoutParts, part, flatDeck, searchEnabled, layoutMode }: PlankProps) => {
|
|
47
|
+
export const Plank = memo(({ entry, layoutParts, part, flatDeck, searchEnabled, layoutMode }: PlankProps) => {
|
|
46
48
|
const { t } = useTranslation(DECK_PLUGIN);
|
|
47
49
|
const dispatch = useIntentDispatcher();
|
|
48
50
|
const { popoverAnchorId, scrollIntoView } = useLayout();
|
|
@@ -53,7 +55,11 @@ export const Plank = ({ entry, layoutParts, part, flatDeck, searchEnabled, layou
|
|
|
53
55
|
const resizeable = layoutMode === 'deck';
|
|
54
56
|
|
|
55
57
|
const attendableAttrs = useAttendableAttributes(entry.id);
|
|
56
|
-
const coordinate: LayoutCoordinate = { part, entryId: entry.id };
|
|
58
|
+
const coordinate: LayoutCoordinate = useMemo(() => ({ part, entryId: entry.id }), [entry.id, part]);
|
|
59
|
+
const index = indexInPart(layoutParts, coordinate);
|
|
60
|
+
const length = partLength(layoutParts, part);
|
|
61
|
+
const canIncrementStart = part === 'main' && index !== undefined && index > 0 && length !== undefined && length > 1;
|
|
62
|
+
const canIncrementEnd = part === 'main' && index !== undefined && index < length - 1 && length !== undefined;
|
|
57
63
|
|
|
58
64
|
const size = plankSizing?.[entry.id] as number | undefined;
|
|
59
65
|
const setSize = useCallback(
|
|
@@ -82,6 +88,19 @@ export const Plank = ({ entry, layoutParts, part, flatDeck, searchEnabled, layou
|
|
|
82
88
|
|
|
83
89
|
const sizeAttrs = useMainSize();
|
|
84
90
|
|
|
91
|
+
const data = useMemo(
|
|
92
|
+
() =>
|
|
93
|
+
node && {
|
|
94
|
+
...(entry.path ? { subject: node.data, path: entry.path } : { object: node.data }),
|
|
95
|
+
coordinate,
|
|
96
|
+
popoverAnchorId,
|
|
97
|
+
},
|
|
98
|
+
[node],
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
// TODO(wittjosiah): Change prop to accept a component.
|
|
102
|
+
const placeholder = useMemo(() => <PlankLoading />, []);
|
|
103
|
+
|
|
85
104
|
return (
|
|
86
105
|
<NaturalPlank.Root
|
|
87
106
|
size={size}
|
|
@@ -100,27 +119,17 @@ export const Plank = ({ entry, layoutParts, part, flatDeck, searchEnabled, layou
|
|
|
100
119
|
{node ? (
|
|
101
120
|
<>
|
|
102
121
|
<NodePlankHeading
|
|
103
|
-
|
|
122
|
+
coordinate={coordinate}
|
|
104
123
|
node={node}
|
|
105
|
-
|
|
106
|
-
|
|
124
|
+
canIncrementStart={canIncrementStart}
|
|
125
|
+
canIncrementEnd={canIncrementEnd}
|
|
107
126
|
popoverAnchorId={popoverAnchorId}
|
|
108
127
|
flatDeck={flatDeck}
|
|
109
128
|
/>
|
|
110
|
-
<Surface
|
|
111
|
-
role='article'
|
|
112
|
-
data={{
|
|
113
|
-
...(entry.path ? { subject: node.data, path: entry.path } : { object: node.data }),
|
|
114
|
-
coordinate,
|
|
115
|
-
popoverAnchorId,
|
|
116
|
-
}}
|
|
117
|
-
limit={1}
|
|
118
|
-
fallback={PlankContentError}
|
|
119
|
-
placeholder={<PlankLoading />}
|
|
120
|
-
/>
|
|
129
|
+
<Surface role='article' data={data} limit={1} fallback={PlankContentError} placeholder={placeholder} />
|
|
121
130
|
</>
|
|
122
131
|
) : (
|
|
123
|
-
<PlankError layoutCoordinate={coordinate}
|
|
132
|
+
<PlankError layoutCoordinate={coordinate} flatDeck={flatDeck} />
|
|
124
133
|
)}
|
|
125
134
|
</NaturalPlank.Content>
|
|
126
135
|
{searchEnabled && resizeable ? (
|
|
@@ -166,4 +175,4 @@ export const Plank = ({ entry, layoutParts, part, flatDeck, searchEnabled, layou
|
|
|
166
175
|
) : null}
|
|
167
176
|
</NaturalPlank.Root>
|
|
168
177
|
);
|
|
169
|
-
};
|
|
178
|
+
});
|
|
@@ -34,13 +34,11 @@ export const PlankContentError = ({ error }: { error?: Error }) => {
|
|
|
34
34
|
|
|
35
35
|
export const PlankError = ({
|
|
36
36
|
layoutCoordinate,
|
|
37
|
-
id,
|
|
38
37
|
node,
|
|
39
38
|
error,
|
|
40
39
|
flatDeck,
|
|
41
40
|
}: {
|
|
42
41
|
layoutCoordinate: LayoutCoordinate;
|
|
43
|
-
id: string;
|
|
44
42
|
node?: Node;
|
|
45
43
|
error?: Error;
|
|
46
44
|
flatDeck?: boolean;
|
|
@@ -51,13 +49,7 @@ export const PlankError = ({
|
|
|
51
49
|
}, []);
|
|
52
50
|
return (
|
|
53
51
|
<>
|
|
54
|
-
<NodePlankHeading
|
|
55
|
-
node={node}
|
|
56
|
-
id={id}
|
|
57
|
-
layoutPart={layoutCoordinate.part}
|
|
58
|
-
pending={!timedOut}
|
|
59
|
-
flatDeck={flatDeck}
|
|
60
|
-
/>
|
|
52
|
+
<NodePlankHeading coordinate={layoutCoordinate} node={node} pending={!timedOut} flatDeck={flatDeck} />
|
|
61
53
|
{timedOut ? <PlankContentError error={error} /> : <PlankLoading />}
|
|
62
54
|
</>
|
|
63
55
|
);
|
|
@@ -6,7 +6,6 @@ import React, { useMemo } from 'react';
|
|
|
6
6
|
|
|
7
7
|
import { type LayoutParts, openIds, Surface } from '@dxos/app-framework';
|
|
8
8
|
import { Main } from '@dxos/react-ui';
|
|
9
|
-
import { useAttended } from '@dxos/react-ui-attention';
|
|
10
9
|
|
|
11
10
|
import { useLayout } from '../LayoutContext';
|
|
12
11
|
|
|
@@ -16,25 +15,24 @@ export type SidebarProps = {
|
|
|
16
15
|
|
|
17
16
|
export const Sidebar = ({ layoutParts }: SidebarProps) => {
|
|
18
17
|
const { layoutMode, popoverAnchorId } = useLayout();
|
|
19
|
-
const attended = useAttended();
|
|
20
18
|
|
|
19
|
+
// TODO(wittjosiah): The activeIds should be path-based to avoid conflicts.
|
|
21
20
|
const activeIds = useMemo(() => {
|
|
22
21
|
if (layoutMode === 'solo') {
|
|
23
|
-
return new Set<string>(layoutParts?.solo?.map((e) => e.id) ?? []);
|
|
22
|
+
return Array.from(new Set<string>(layoutParts?.solo?.map((e) => e.id) ?? []));
|
|
24
23
|
} else if (layoutMode === 'deck') {
|
|
25
|
-
return new Set<string>(layoutParts?.main?.map((e) => e.id) ?? []);
|
|
24
|
+
return Array.from(new Set<string>(layoutParts?.main?.map((e) => e.id) ?? []));
|
|
26
25
|
}
|
|
27
26
|
|
|
28
|
-
return new Set<string>(openIds(layoutParts));
|
|
27
|
+
return Array.from(new Set<string>(openIds(layoutParts)));
|
|
29
28
|
}, [layoutParts, layoutMode]);
|
|
30
29
|
|
|
31
30
|
const navigationData = useMemo(
|
|
32
31
|
() => ({
|
|
33
32
|
popoverAnchorId,
|
|
34
33
|
activeIds,
|
|
35
|
-
attended,
|
|
36
34
|
}),
|
|
37
|
-
[popoverAnchorId, activeIds
|
|
35
|
+
[popoverAnchorId, activeIds],
|
|
38
36
|
);
|
|
39
37
|
return (
|
|
40
38
|
<Main.NavigationSidebar>
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
import React from 'react';
|
|
6
6
|
|
|
7
|
-
import { SettingsValue } from '@dxos/plugin-settings';
|
|
8
7
|
import { Input, Select, useTranslation } from '@dxos/react-ui';
|
|
8
|
+
import { FormInput } from '@dxos/react-ui-data';
|
|
9
9
|
|
|
10
10
|
import { DECK_PLUGIN } from '../meta';
|
|
11
11
|
import {
|
|
@@ -23,7 +23,7 @@ export const LayoutSettings = ({ settings }: { settings: DeckSettingsProps }) =>
|
|
|
23
23
|
|
|
24
24
|
return (
|
|
25
25
|
<>
|
|
26
|
-
<
|
|
26
|
+
<FormInput label={t('select new plank positioning label')}>
|
|
27
27
|
<Select.Root
|
|
28
28
|
value={settings.newPlankPositioning ?? 'start'}
|
|
29
29
|
onValueChange={(value) => (settings.newPlankPositioning = value as NewPlankPositioning)}
|
|
@@ -41,8 +41,8 @@ export const LayoutSettings = ({ settings }: { settings: DeckSettingsProps }) =>
|
|
|
41
41
|
</Select.Content>
|
|
42
42
|
</Select.Portal>
|
|
43
43
|
</Select.Root>
|
|
44
|
-
</
|
|
45
|
-
<
|
|
44
|
+
</FormInput>
|
|
45
|
+
<FormInput label={t('settings overscroll label')}>
|
|
46
46
|
<Select.Root
|
|
47
47
|
value={settings.overscroll ?? 'none'}
|
|
48
48
|
onValueChange={(value) => (settings.overscroll = value as Overscroll)}
|
|
@@ -60,24 +60,24 @@ export const LayoutSettings = ({ settings }: { settings: DeckSettingsProps }) =>
|
|
|
60
60
|
</Select.Content>
|
|
61
61
|
</Select.Portal>
|
|
62
62
|
</Select.Root>
|
|
63
|
-
</
|
|
64
|
-
<
|
|
63
|
+
</FormInput>
|
|
64
|
+
<FormInput label={t('settings show hints label')}>
|
|
65
65
|
<Input.Switch checked={settings.showHints} onCheckedChange={(checked) => (settings.showHints = checked)} />
|
|
66
|
-
</
|
|
66
|
+
</FormInput>
|
|
67
67
|
{!isSocket && (
|
|
68
|
-
<
|
|
68
|
+
<FormInput label={t('settings native redirect label')}>
|
|
69
69
|
<Input.Switch
|
|
70
70
|
checked={settings.enableNativeRedirect}
|
|
71
71
|
onCheckedChange={(checked) => (settings.enableNativeRedirect = checked)}
|
|
72
72
|
/>
|
|
73
|
-
</
|
|
73
|
+
</FormInput>
|
|
74
74
|
)}
|
|
75
|
-
<
|
|
75
|
+
<FormInput label={t('settings custom slots')}>
|
|
76
76
|
<Input.Switch checked={settings.customSlots} onCheckedChange={(checked) => (settings.customSlots = checked)} />
|
|
77
|
-
</
|
|
78
|
-
<
|
|
77
|
+
</FormInput>
|
|
78
|
+
<FormInput label={t('settings flat deck')}>
|
|
79
79
|
<Input.Switch checked={settings.flatDeck} onCheckedChange={(checked) => (settings.flatDeck = checked)} />
|
|
80
|
-
</
|
|
80
|
+
</FormInput>
|
|
81
81
|
</>
|
|
82
82
|
);
|
|
83
83
|
};
|