@dxos/plugin-deck 0.6.14-main.f49f251 → 0.6.14-staging.4b6f9cf
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/chunk-NIRHDTX4.mjs +17 -0
- package/dist/lib/browser/chunk-NIRHDTX4.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +387 -379
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/types.mjs +11 -0
- package/dist/lib/browser/types.mjs.map +7 -0
- package/dist/types/src/DeckPlugin.d.ts.map +1 -1
- package/dist/types/src/components/DeckLayout/ComplementarySidebar.d.ts +4 -3
- package/dist/types/src/components/DeckLayout/ComplementarySidebar.d.ts.map +1 -1
- package/dist/types/src/components/DeckLayout/DeckLayout.d.ts +3 -8
- package/dist/types/src/components/DeckLayout/DeckLayout.d.ts.map +1 -1
- package/dist/types/src/components/DeckLayout/NodePlankHeading.d.ts +3 -4
- package/dist/types/src/components/DeckLayout/NodePlankHeading.d.ts.map +1 -1
- package/dist/types/src/components/DeckLayout/Plank.d.ts +4 -4
- package/dist/types/src/components/DeckLayout/Plank.d.ts.map +1 -1
- package/dist/types/src/components/DeckLayout/PlankControls.d.ts +19 -0
- package/dist/types/src/components/DeckLayout/PlankControls.d.ts.map +1 -0
- 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/translations.d.ts +7 -4
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types.d.ts +13 -1
- package/dist/types/src/types.d.ts.map +1 -1
- package/dist/types/src/util/overscroll.d.ts +1 -2
- package/dist/types/src/util/overscroll.d.ts.map +1 -1
- package/package.json +34 -27
- package/src/DeckPlugin.tsx +18 -32
- package/src/components/DeckLayout/ComplementarySidebar.tsx +27 -45
- package/src/components/DeckLayout/DeckLayout.tsx +141 -137
- package/src/components/DeckLayout/NodePlankHeading.tsx +30 -17
- package/src/components/DeckLayout/Plank.tsx +62 -96
- package/src/components/DeckLayout/PlankControls.tsx +133 -0
- package/src/components/DeckLayout/PlankError.tsx +6 -8
- package/src/components/DeckLayout/PlankLoading.tsx +1 -1
- package/src/components/DeckLayout/Toast.tsx +1 -1
- package/src/components/LayoutSettings.tsx +13 -13
- package/src/translations.ts +11 -9
- package/src/types.ts +15 -0
- package/src/util/overscroll.ts +9 -30
|
@@ -13,11 +13,13 @@ import {
|
|
|
13
13
|
type LayoutCoordinate,
|
|
14
14
|
} from '@dxos/app-framework';
|
|
15
15
|
import { type Node, useGraph } from '@dxos/plugin-graph';
|
|
16
|
-
import { Icon, Popover, toLocalizedString, useMediaQuery, useTranslation } from '@dxos/react-ui';
|
|
17
|
-
import {
|
|
16
|
+
import { Icon, Popover, toLocalizedString, useMediaQuery, useTranslation, IconButton } from '@dxos/react-ui';
|
|
17
|
+
import { StackItem, type StackItemSigilAction } from '@dxos/react-ui-stack';
|
|
18
18
|
import { TextTooltip } from '@dxos/react-ui-text-tooltip';
|
|
19
19
|
|
|
20
|
+
import { PlankControls } from './PlankControls';
|
|
20
21
|
import { DECK_PLUGIN } from '../../meta';
|
|
22
|
+
import { useLayout } from '../LayoutContext';
|
|
21
23
|
|
|
22
24
|
export type NodePlankHeadingProps = {
|
|
23
25
|
coordinate: LayoutCoordinate;
|
|
@@ -26,8 +28,7 @@ export type NodePlankHeadingProps = {
|
|
|
26
28
|
canIncrementEnd?: boolean;
|
|
27
29
|
popoverAnchorId?: string;
|
|
28
30
|
pending?: boolean;
|
|
29
|
-
|
|
30
|
-
actions?: PlankHeadingAction[];
|
|
31
|
+
actions?: StackItemSigilAction[];
|
|
31
32
|
};
|
|
32
33
|
|
|
33
34
|
export const NodePlankHeading = memo(
|
|
@@ -38,9 +39,9 @@ export const NodePlankHeading = memo(
|
|
|
38
39
|
canIncrementEnd,
|
|
39
40
|
popoverAnchorId,
|
|
40
41
|
pending,
|
|
41
|
-
flatDeck,
|
|
42
42
|
actions = [],
|
|
43
43
|
}: NodePlankHeadingProps) => {
|
|
44
|
+
const layoutContext = useLayout();
|
|
44
45
|
const { t } = useTranslation(DECK_PLUGIN);
|
|
45
46
|
const { graph } = useGraph();
|
|
46
47
|
const icon = node?.properties?.icon ?? 'ph--placeholder--regular';
|
|
@@ -73,12 +74,10 @@ export const NodePlankHeading = memo(
|
|
|
73
74
|
);
|
|
74
75
|
|
|
75
76
|
return (
|
|
76
|
-
<
|
|
77
|
-
{...((layoutPart !== 'main' || !flatDeck) && { classNames: 'pie-1 border-b border-separator' })}
|
|
78
|
-
>
|
|
77
|
+
<StackItem.Heading classNames='pie-1'>
|
|
79
78
|
<ActionRoot>
|
|
80
79
|
{node ? (
|
|
81
|
-
<
|
|
80
|
+
<StackItem.Sigil
|
|
82
81
|
icon={icon}
|
|
83
82
|
related={layoutPart === 'complementary'}
|
|
84
83
|
attendableId={attendableId}
|
|
@@ -89,31 +88,32 @@ export const NodePlankHeading = memo(
|
|
|
89
88
|
}
|
|
90
89
|
>
|
|
91
90
|
<Surface role='menu-footer' data={{ object: node.data }} />
|
|
92
|
-
</
|
|
91
|
+
</StackItem.Sigil>
|
|
93
92
|
) : (
|
|
94
|
-
<
|
|
93
|
+
<StackItem.SigilButton>
|
|
95
94
|
<span className='sr-only'>{label}</span>
|
|
96
95
|
<Icon icon={icon} size={5} />
|
|
97
|
-
</
|
|
96
|
+
</StackItem.SigilButton>
|
|
98
97
|
)}
|
|
99
98
|
</ActionRoot>
|
|
100
99
|
<TextTooltip text={label} onlyWhenTruncating>
|
|
101
|
-
<
|
|
100
|
+
<StackItem.HeadingLabel
|
|
102
101
|
attendableId={attendableId}
|
|
103
102
|
related={layoutPart === 'complementary'}
|
|
104
103
|
{...(pending && { classNames: 'text-description' })}
|
|
105
104
|
>
|
|
106
105
|
{label}
|
|
107
|
-
</
|
|
106
|
+
</StackItem.HeadingLabel>
|
|
108
107
|
</TextTooltip>
|
|
109
108
|
{node && layoutPart !== 'complementary' && (
|
|
110
109
|
// TODO(Zan): What are we doing with layout coordinate here?
|
|
111
110
|
<Surface role='navbar-end' direction='inline-reverse' data={{ object: node.data }} />
|
|
112
111
|
)}
|
|
113
112
|
{/* NOTE(thure): Pinning & unpinning are temporarily disabled */}
|
|
114
|
-
<
|
|
113
|
+
<PlankControls
|
|
115
114
|
capabilities={capabilities}
|
|
116
115
|
isSolo={layoutPart === 'solo'}
|
|
116
|
+
classNames='mx-1'
|
|
117
117
|
onClick={(eventType) => {
|
|
118
118
|
if (!layoutPart) {
|
|
119
119
|
return;
|
|
@@ -154,8 +154,21 @@ export const NodePlankHeading = memo(
|
|
|
154
154
|
}
|
|
155
155
|
}}
|
|
156
156
|
close={layoutPart === 'complementary' ? 'minify-end' : true}
|
|
157
|
-
|
|
158
|
-
|
|
157
|
+
>
|
|
158
|
+
{/* TODO(wittjosiah): This doesn't behave exactly the same as the rest of the button group. */}
|
|
159
|
+
{layoutPart !== 'complementary' && (
|
|
160
|
+
<IconButton
|
|
161
|
+
iconOnly
|
|
162
|
+
onClick={() => (layoutContext.complementarySidebarOpen = !layoutContext.complementarySidebarOpen)}
|
|
163
|
+
variant='ghost'
|
|
164
|
+
label={t('open complementary sidebar label')}
|
|
165
|
+
classNames='!p-1 -scale-x-100'
|
|
166
|
+
icon='ph--sidebar--regular'
|
|
167
|
+
tooltipZIndex='70'
|
|
168
|
+
/>
|
|
169
|
+
)}
|
|
170
|
+
</PlankControls>
|
|
171
|
+
</StackItem.Heading>
|
|
159
172
|
);
|
|
160
173
|
},
|
|
161
174
|
);
|
|
@@ -2,16 +2,13 @@
|
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { Plus } from '@phosphor-icons/react';
|
|
6
5
|
import React, { type KeyboardEvent, memo, useCallback, useLayoutEffect, useMemo, useRef } from 'react';
|
|
7
6
|
|
|
8
7
|
import {
|
|
9
|
-
LayoutAction,
|
|
10
8
|
type LayoutCoordinate,
|
|
11
9
|
type LayoutEntry,
|
|
12
10
|
type LayoutPart,
|
|
13
11
|
type LayoutParts,
|
|
14
|
-
NavigationAction,
|
|
15
12
|
Surface,
|
|
16
13
|
useIntentDispatcher,
|
|
17
14
|
type Layout,
|
|
@@ -20,53 +17,53 @@ import {
|
|
|
20
17
|
} from '@dxos/app-framework';
|
|
21
18
|
import { debounce } from '@dxos/async';
|
|
22
19
|
import { useGraph } from '@dxos/plugin-graph';
|
|
23
|
-
import { Button, Tooltip, useTranslation } from '@dxos/react-ui';
|
|
24
20
|
import { useAttendableAttributes } from '@dxos/react-ui-attention';
|
|
25
|
-
import {
|
|
26
|
-
import { mainIntrinsicSize } from '@dxos/react-ui-theme';
|
|
21
|
+
import { StackItem, railGridHorizontal } from '@dxos/react-ui-stack';
|
|
22
|
+
import { mainIntrinsicSize, mx } from '@dxos/react-ui-theme';
|
|
27
23
|
|
|
28
24
|
import { NodePlankHeading } from './NodePlankHeading';
|
|
29
25
|
import { PlankContentError, PlankError } from './PlankError';
|
|
30
26
|
import { PlankLoading } from './PlankLoading';
|
|
31
27
|
import { DeckAction } from '../../DeckPlugin';
|
|
32
28
|
import { useNode, useMainSize } from '../../hooks';
|
|
33
|
-
import { DECK_PLUGIN } from '../../meta';
|
|
34
29
|
import { useDeckContext } from '../DeckContext';
|
|
35
30
|
import { useLayout } from '../LayoutContext';
|
|
36
31
|
|
|
32
|
+
const UNKNOWN_ID = 'unknown_id';
|
|
33
|
+
|
|
37
34
|
export type PlankProps = {
|
|
38
|
-
entry
|
|
35
|
+
entry?: LayoutEntry;
|
|
39
36
|
layoutParts: LayoutParts;
|
|
40
|
-
// TODO(wittjosiah): Remove.
|
|
37
|
+
// TODO(wittjosiah): Remove. Pass in LayoutCoordinate instead of LayoutEntry.
|
|
41
38
|
part: LayoutPart;
|
|
42
39
|
layoutMode: Layout['layoutMode'];
|
|
43
|
-
|
|
44
|
-
|
|
40
|
+
order?: number;
|
|
41
|
+
last?: boolean;
|
|
45
42
|
};
|
|
46
43
|
|
|
47
|
-
export const Plank = memo(({ entry, layoutParts, part,
|
|
48
|
-
const { t } = useTranslation(DECK_PLUGIN);
|
|
44
|
+
export const Plank = memo(({ entry, layoutParts, part, layoutMode, order, last }: PlankProps) => {
|
|
49
45
|
const dispatch = useIntentDispatcher();
|
|
46
|
+
const coordinate: LayoutCoordinate = useMemo(() => ({ part, entryId: entry?.id ?? UNKNOWN_ID }), [entry?.id, part]);
|
|
50
47
|
const { popoverAnchorId, scrollIntoView } = useLayout();
|
|
51
48
|
const { plankSizing } = useDeckContext();
|
|
52
49
|
const { graph } = useGraph();
|
|
53
|
-
const node = useNode(graph, entry
|
|
50
|
+
const node = useNode(graph, entry?.id);
|
|
54
51
|
const rootElement = useRef<HTMLDivElement | null>(null);
|
|
55
|
-
const
|
|
52
|
+
const canResize = layoutMode === 'deck';
|
|
53
|
+
const Root = part === 'solo' ? 'article' : StackItem.Root;
|
|
56
54
|
|
|
57
|
-
const attendableAttrs = useAttendableAttributes(
|
|
58
|
-
const coordinate: LayoutCoordinate = useMemo(() => ({ part, entryId: entry.id }), [entry.id, part]);
|
|
55
|
+
const attendableAttrs = useAttendableAttributes(coordinate.entryId);
|
|
59
56
|
const index = indexInPart(layoutParts, coordinate);
|
|
60
57
|
const length = partLength(layoutParts, part);
|
|
61
58
|
const canIncrementStart = part === 'main' && index !== undefined && index > 0 && length !== undefined && length > 1;
|
|
62
59
|
const canIncrementEnd = part === 'main' && index !== undefined && index < length - 1 && length !== undefined;
|
|
63
60
|
|
|
64
|
-
const size = plankSizing?.[
|
|
61
|
+
const size = plankSizing?.[coordinate.entryId] as number | undefined;
|
|
65
62
|
const setSize = useCallback(
|
|
66
|
-
debounce((
|
|
67
|
-
|
|
63
|
+
debounce((nextSize: number) => {
|
|
64
|
+
return dispatch({ action: DeckAction.UPDATE_PLANK_SIZE, data: { id: coordinate.entryId, size: nextSize } });
|
|
68
65
|
}, 200),
|
|
69
|
-
[dispatch,
|
|
66
|
+
[dispatch, coordinate.entryId],
|
|
70
67
|
);
|
|
71
68
|
|
|
72
69
|
// TODO(thure): Tabster’s focus group should handle moving focus to Main, but something is blocking it.
|
|
@@ -77,102 +74,71 @@ export const Plank = memo(({ entry, layoutParts, part, flatDeck, searchEnabled,
|
|
|
77
74
|
}, []);
|
|
78
75
|
|
|
79
76
|
useLayoutEffect(() => {
|
|
80
|
-
if (scrollIntoView ===
|
|
77
|
+
if (scrollIntoView === coordinate.entryId) {
|
|
81
78
|
rootElement.current?.focus({ preventScroll: true });
|
|
82
79
|
layoutMode === 'deck' && rootElement.current?.scrollIntoView({ behavior: 'smooth', inline: 'center' });
|
|
83
80
|
}
|
|
84
|
-
}, [scrollIntoView, layoutMode]);
|
|
81
|
+
}, [coordinate.entryId, scrollIntoView, layoutMode]);
|
|
85
82
|
|
|
86
83
|
const isSolo = layoutMode === 'solo' && part === 'solo';
|
|
87
|
-
const
|
|
84
|
+
const isAttendable = isSolo || (layoutMode === 'deck' && part === 'main');
|
|
88
85
|
|
|
89
86
|
const sizeAttrs = useMainSize();
|
|
90
87
|
|
|
91
88
|
const data = useMemo(
|
|
92
89
|
() =>
|
|
93
90
|
node && {
|
|
94
|
-
...(entry
|
|
91
|
+
...(entry?.path ? { subject: node.data, path: entry.path } : { object: node.data }),
|
|
95
92
|
coordinate,
|
|
96
93
|
popoverAnchorId,
|
|
97
94
|
},
|
|
98
|
-
[node],
|
|
95
|
+
[node, node?.data, entry?.path, coordinate, popoverAnchorId],
|
|
99
96
|
);
|
|
100
97
|
|
|
101
98
|
// TODO(wittjosiah): Change prop to accept a component.
|
|
102
99
|
const placeholder = useMemo(() => <PlankLoading />, []);
|
|
103
100
|
|
|
101
|
+
const className = mx(
|
|
102
|
+
'attention-surface relative',
|
|
103
|
+
isSolo && mainIntrinsicSize,
|
|
104
|
+
isSolo && railGridHorizontal,
|
|
105
|
+
isSolo && 'grid absolute inset-0 divide-separator divide-y',
|
|
106
|
+
last && '!border-li border-separator',
|
|
107
|
+
);
|
|
108
|
+
|
|
104
109
|
return (
|
|
105
|
-
<
|
|
106
|
-
size={size}
|
|
107
|
-
setSize={setSize}
|
|
108
|
-
classNames={[isSuppressed && '!sr-only']}
|
|
109
|
-
{...attendableAttrs}
|
|
110
|
-
{...(isSuppressed && { inert: '' })}
|
|
111
|
-
onKeyDown={handleKeyDown}
|
|
110
|
+
<Root
|
|
112
111
|
ref={rootElement}
|
|
112
|
+
data-testid='deck.plank'
|
|
113
|
+
tabIndex={0}
|
|
114
|
+
{...(part === 'solo'
|
|
115
|
+
? ({ ...sizeAttrs, className } as any)
|
|
116
|
+
: {
|
|
117
|
+
item: { id: entry?.id ?? 'never' },
|
|
118
|
+
size,
|
|
119
|
+
onSizeChange: setSize,
|
|
120
|
+
classNames: className,
|
|
121
|
+
order,
|
|
122
|
+
role: 'article',
|
|
123
|
+
})}
|
|
124
|
+
{...(isAttendable ? attendableAttrs : {})}
|
|
125
|
+
onKeyDown={handleKeyDown}
|
|
113
126
|
>
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
</>
|
|
131
|
-
) : (
|
|
132
|
-
<PlankError layoutCoordinate={coordinate} flatDeck={flatDeck} />
|
|
133
|
-
)}
|
|
134
|
-
</NaturalPlank.Content>
|
|
135
|
-
{searchEnabled && resizeable ? (
|
|
136
|
-
<div role='none' className='grid grid-rows-subgrid row-span-3'>
|
|
137
|
-
<Tooltip.Root>
|
|
138
|
-
<Tooltip.Trigger asChild>
|
|
139
|
-
<Button
|
|
140
|
-
data-testid='plankHeading.open'
|
|
141
|
-
variant='ghost'
|
|
142
|
-
classNames='p-1 w-fit'
|
|
143
|
-
onClick={() =>
|
|
144
|
-
dispatch([
|
|
145
|
-
{
|
|
146
|
-
action: LayoutAction.SET_LAYOUT,
|
|
147
|
-
data: {
|
|
148
|
-
element: 'dialog',
|
|
149
|
-
component: 'dxos.org/plugin/search/Dialog',
|
|
150
|
-
dialogBlockAlign: 'start',
|
|
151
|
-
subject: {
|
|
152
|
-
action: NavigationAction.SET,
|
|
153
|
-
position: 'add-after',
|
|
154
|
-
coordinate,
|
|
155
|
-
},
|
|
156
|
-
},
|
|
157
|
-
},
|
|
158
|
-
])
|
|
159
|
-
}
|
|
160
|
-
>
|
|
161
|
-
<span className='sr-only'>{t('insert plank label')}</span>
|
|
162
|
-
<Plus />
|
|
163
|
-
</Button>
|
|
164
|
-
</Tooltip.Trigger>
|
|
165
|
-
<Tooltip.Portal>
|
|
166
|
-
<Tooltip.Content side='bottom' classNames='z-[70]'>
|
|
167
|
-
{t('insert plank label')}
|
|
168
|
-
</Tooltip.Content>
|
|
169
|
-
</Tooltip.Portal>
|
|
170
|
-
</Tooltip.Root>
|
|
171
|
-
<NaturalPlank.ResizeHandle classNames='row-start-[toolbar-start] row-end-[content-end]' />
|
|
172
|
-
</div>
|
|
173
|
-
) : resizeable ? (
|
|
174
|
-
<NaturalPlank.ResizeHandle classNames='row-span-3' />
|
|
175
|
-
) : null}
|
|
176
|
-
</NaturalPlank.Root>
|
|
127
|
+
{node ? (
|
|
128
|
+
<>
|
|
129
|
+
<NodePlankHeading
|
|
130
|
+
coordinate={coordinate}
|
|
131
|
+
node={node}
|
|
132
|
+
canIncrementStart={canIncrementStart}
|
|
133
|
+
canIncrementEnd={canIncrementEnd}
|
|
134
|
+
popoverAnchorId={popoverAnchorId}
|
|
135
|
+
/>
|
|
136
|
+
<Surface role='article' data={data} limit={1} fallback={PlankContentError} placeholder={placeholder} />
|
|
137
|
+
</>
|
|
138
|
+
) : (
|
|
139
|
+
<PlankError layoutCoordinate={coordinate} />
|
|
140
|
+
)}
|
|
141
|
+
{canResize && <StackItem.ResizeHandle />}
|
|
142
|
+
</Root>
|
|
177
143
|
);
|
|
178
144
|
});
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2024 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import React, { forwardRef } from 'react';
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
Button,
|
|
9
|
+
ButtonGroup,
|
|
10
|
+
type ButtonGroupProps,
|
|
11
|
+
type ButtonProps,
|
|
12
|
+
Icon,
|
|
13
|
+
Tooltip,
|
|
14
|
+
useTranslation,
|
|
15
|
+
} from '@dxos/react-ui';
|
|
16
|
+
|
|
17
|
+
import { DECK_PLUGIN } from '../../meta';
|
|
18
|
+
|
|
19
|
+
export type PlankControlEvent = 'solo' | 'close' | `${'pin' | 'increment'}-${'start' | 'end'}`;
|
|
20
|
+
export type PlankControlHandler = (event: PlankControlEvent) => void;
|
|
21
|
+
|
|
22
|
+
export type PlankCapabilities = {
|
|
23
|
+
incrementStart?: boolean;
|
|
24
|
+
incrementEnd?: boolean;
|
|
25
|
+
solo?: boolean;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export type PlankControlsProps = Omit<ButtonGroupProps, 'onClick'> & {
|
|
29
|
+
onClick?: PlankControlHandler;
|
|
30
|
+
variant?: 'hide-disabled' | 'default';
|
|
31
|
+
close?: boolean | 'minify-start' | 'minify-end';
|
|
32
|
+
capabilities: PlankCapabilities;
|
|
33
|
+
isSolo?: boolean;
|
|
34
|
+
pin?: 'start' | 'end' | 'both';
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const PlankControl = ({ icon, label, ...props }: Omit<ButtonProps, 'children'> & { label: string; icon: string }) => {
|
|
38
|
+
return (
|
|
39
|
+
<Tooltip.Root>
|
|
40
|
+
<Tooltip.Trigger asChild>
|
|
41
|
+
<Button variant='ghost' {...props}>
|
|
42
|
+
<span className='sr-only'>{label}</span>
|
|
43
|
+
<Icon icon={icon} />
|
|
44
|
+
</Button>
|
|
45
|
+
</Tooltip.Trigger>
|
|
46
|
+
<Tooltip.Portal>
|
|
47
|
+
<Tooltip.Content side='bottom' classNames='z-[70]'>
|
|
48
|
+
{label}
|
|
49
|
+
</Tooltip.Content>
|
|
50
|
+
</Tooltip.Portal>
|
|
51
|
+
</Tooltip.Root>
|
|
52
|
+
);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
// TODO(wittjosiah): Duplicate of stack LayoutControls?
|
|
56
|
+
// Translations were to be duplicated between packages.
|
|
57
|
+
export const PlankControls = forwardRef<HTMLDivElement, PlankControlsProps>(
|
|
58
|
+
(
|
|
59
|
+
{ onClick, variant = 'default', capabilities: can, isSolo, pin, close = false, children, ...props },
|
|
60
|
+
forwardedRef,
|
|
61
|
+
) => {
|
|
62
|
+
const { t } = useTranslation(DECK_PLUGIN);
|
|
63
|
+
const buttonClassNames = variant === 'hide-disabled' ? 'disabled:hidden !p-1' : '!p-1';
|
|
64
|
+
|
|
65
|
+
return (
|
|
66
|
+
<ButtonGroup {...props} ref={forwardedRef}>
|
|
67
|
+
{pin && !isSolo && ['both', 'start'].includes(pin) && (
|
|
68
|
+
<PlankControl
|
|
69
|
+
label={t('pin start label')}
|
|
70
|
+
variant='ghost'
|
|
71
|
+
classNames={buttonClassNames}
|
|
72
|
+
onClick={() => onClick?.('pin-start')}
|
|
73
|
+
icon='ph--caret-line-left--regular'
|
|
74
|
+
/>
|
|
75
|
+
)}
|
|
76
|
+
|
|
77
|
+
{can.solo && (
|
|
78
|
+
<PlankControl
|
|
79
|
+
label={t('solo plank label')}
|
|
80
|
+
classNames={buttonClassNames}
|
|
81
|
+
onClick={() => onClick?.('solo')}
|
|
82
|
+
icon={isSolo ? 'ph--arrows-in--regular' : 'ph--arrows-out--regular'}
|
|
83
|
+
/>
|
|
84
|
+
)}
|
|
85
|
+
|
|
86
|
+
{!isSolo && can.solo && (
|
|
87
|
+
<>
|
|
88
|
+
<PlankControl
|
|
89
|
+
label={t('increment start label')}
|
|
90
|
+
disabled={!can.incrementStart}
|
|
91
|
+
classNames={buttonClassNames}
|
|
92
|
+
onClick={() => onClick?.('increment-start')}
|
|
93
|
+
icon='ph--caret-left--regular'
|
|
94
|
+
/>
|
|
95
|
+
<PlankControl
|
|
96
|
+
label={t('increment end label')}
|
|
97
|
+
disabled={!can.incrementEnd}
|
|
98
|
+
classNames={buttonClassNames}
|
|
99
|
+
onClick={() => onClick?.('increment-end')}
|
|
100
|
+
icon='ph--caret-right--regular'
|
|
101
|
+
/>
|
|
102
|
+
</>
|
|
103
|
+
)}
|
|
104
|
+
|
|
105
|
+
{pin && !isSolo && ['both', 'end'].includes(pin) && (
|
|
106
|
+
<PlankControl
|
|
107
|
+
label={t('pin end label')}
|
|
108
|
+
classNames={buttonClassNames}
|
|
109
|
+
onClick={() => onClick?.('pin-end')}
|
|
110
|
+
icon='ph--caret-line-right--regular'
|
|
111
|
+
/>
|
|
112
|
+
)}
|
|
113
|
+
|
|
114
|
+
{close && !isSolo && (
|
|
115
|
+
<PlankControl
|
|
116
|
+
label={t(`${typeof close === 'string' ? 'minify' : 'close'} label`)}
|
|
117
|
+
classNames={buttonClassNames}
|
|
118
|
+
onClick={() => onClick?.('close')}
|
|
119
|
+
data-testid='plankHeading.close'
|
|
120
|
+
icon={
|
|
121
|
+
close === 'minify-start'
|
|
122
|
+
? 'ph--caret-line-left--regular'
|
|
123
|
+
: close === 'minify-end'
|
|
124
|
+
? 'ph--caret-line-right--regular'
|
|
125
|
+
: 'ph--minus--regular'
|
|
126
|
+
}
|
|
127
|
+
/>
|
|
128
|
+
)}
|
|
129
|
+
{children}
|
|
130
|
+
</ButtonGroup>
|
|
131
|
+
);
|
|
132
|
+
},
|
|
133
|
+
);
|
|
@@ -15,18 +15,18 @@ import { DECK_PLUGIN } from '../../meta';
|
|
|
15
15
|
|
|
16
16
|
export const PlankContentError = ({ error }: { error?: Error }) => {
|
|
17
17
|
const { t } = useTranslation(DECK_PLUGIN);
|
|
18
|
+
const errorString = error?.toString() ?? '';
|
|
18
19
|
return (
|
|
19
|
-
<div role='none' className='grid place-items-center
|
|
20
|
+
<div role='none' className='overflow-auto p-8 attention-surface grid place-items-center'>
|
|
20
21
|
<p
|
|
21
22
|
role='alert'
|
|
22
23
|
className={mx(
|
|
23
24
|
descriptionText,
|
|
24
|
-
|
|
25
|
-
'
|
|
26
|
-
'place-self-center border border-dashed border-neutral-400/50 rounded-lg text-center p-8 font-normal text-lg',
|
|
25
|
+
'break-words border border-dashed border-separator rounded-lg p-8',
|
|
26
|
+
errorString.length < 256 && 'text-lg',
|
|
27
27
|
)}
|
|
28
28
|
>
|
|
29
|
-
{error ?
|
|
29
|
+
{error ? errorString : t('error fallback message')}
|
|
30
30
|
</p>
|
|
31
31
|
</div>
|
|
32
32
|
);
|
|
@@ -36,12 +36,10 @@ export const PlankError = ({
|
|
|
36
36
|
layoutCoordinate,
|
|
37
37
|
node,
|
|
38
38
|
error,
|
|
39
|
-
flatDeck,
|
|
40
39
|
}: {
|
|
41
40
|
layoutCoordinate: LayoutCoordinate;
|
|
42
41
|
node?: Node;
|
|
43
42
|
error?: Error;
|
|
44
|
-
flatDeck?: boolean;
|
|
45
43
|
}) => {
|
|
46
44
|
const [timedOut, setTimedOut] = useState(false);
|
|
47
45
|
useEffect(() => {
|
|
@@ -49,7 +47,7 @@ export const PlankError = ({
|
|
|
49
47
|
}, []);
|
|
50
48
|
return (
|
|
51
49
|
<>
|
|
52
|
-
<NodePlankHeading coordinate={layoutCoordinate} node={node} pending={!timedOut}
|
|
50
|
+
<NodePlankHeading coordinate={layoutCoordinate} node={node} pending={!timedOut} />
|
|
53
51
|
{timedOut ? <PlankContentError error={error} /> : <PlankLoading />}
|
|
54
52
|
</>
|
|
55
53
|
);
|
|
@@ -8,7 +8,7 @@ import { Status } from '@dxos/react-ui';
|
|
|
8
8
|
|
|
9
9
|
export const PlankLoading = () => {
|
|
10
10
|
return (
|
|
11
|
-
<div role='none' className='grid
|
|
11
|
+
<div role='none' className='grid place-items-center attention-surface'>
|
|
12
12
|
<Status indeterminate aria-label='Initializing' />
|
|
13
13
|
</div>
|
|
14
14
|
);
|
|
@@ -24,7 +24,7 @@ export const Toast = ({
|
|
|
24
24
|
<NaturalToast.Root data-testid={id} defaultOpen duration={duration} onOpenChange={onOpenChange}>
|
|
25
25
|
<NaturalToast.Body>
|
|
26
26
|
<NaturalToast.Title classNames='items-center'>
|
|
27
|
-
<Icon icon={icon} size={5} classNames='inline mr-1' />
|
|
27
|
+
{icon && <Icon icon={icon} size={5} classNames='inline mr-1' />}
|
|
28
28
|
<span>{title}</span>
|
|
29
29
|
</NaturalToast.Title>
|
|
30
30
|
{description && <NaturalToast.Description>{description}</NaturalToast.Description>}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import React from 'react';
|
|
6
6
|
|
|
7
7
|
import { Input, Select, useTranslation } from '@dxos/react-ui';
|
|
8
|
-
import {
|
|
8
|
+
import { DeprecatedFormInput } 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
|
+
<DeprecatedFormInput 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
|
+
</DeprecatedFormInput>
|
|
45
|
+
<DeprecatedFormInput 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
|
+
</DeprecatedFormInput>
|
|
64
|
+
<DeprecatedFormInput label={t('settings show hints label')}>
|
|
65
65
|
<Input.Switch checked={settings.showHints} onCheckedChange={(checked) => (settings.showHints = checked)} />
|
|
66
|
-
</
|
|
66
|
+
</DeprecatedFormInput>
|
|
67
67
|
{!isSocket && (
|
|
68
|
-
<
|
|
68
|
+
<DeprecatedFormInput 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
|
+
</DeprecatedFormInput>
|
|
74
74
|
)}
|
|
75
|
-
<
|
|
75
|
+
<DeprecatedFormInput label={t('settings custom slots')}>
|
|
76
76
|
<Input.Switch checked={settings.customSlots} onCheckedChange={(checked) => (settings.customSlots = checked)} />
|
|
77
|
-
</
|
|
78
|
-
<
|
|
77
|
+
</DeprecatedFormInput>
|
|
78
|
+
<DeprecatedFormInput label={t('settings flat deck')}>
|
|
79
79
|
<Input.Switch checked={settings.flatDeck} onCheckedChange={(checked) => (settings.flatDeck = checked)} />
|
|
80
|
-
</
|
|
80
|
+
</DeprecatedFormInput>
|
|
81
81
|
</>
|
|
82
82
|
);
|
|
83
83
|
};
|
package/src/translations.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
//
|
|
2
2
|
// Copyright 2023 DXOS.org
|
|
3
3
|
//
|
|
4
|
+
|
|
4
5
|
import { DECK_PLUGIN } from './meta';
|
|
5
6
|
|
|
6
7
|
export default [
|
|
@@ -8,8 +9,8 @@ export default [
|
|
|
8
9
|
'en-US': {
|
|
9
10
|
[DECK_PLUGIN]: {
|
|
10
11
|
'main header label': 'Main header',
|
|
11
|
-
'open navigation sidebar label': 'Open navigation sidebar
|
|
12
|
-
'open complementary sidebar label': 'Open complementary sidebar
|
|
12
|
+
'open navigation sidebar label': 'Open navigation sidebar',
|
|
13
|
+
'open complementary sidebar label': 'Open complementary sidebar',
|
|
13
14
|
'plugin error message': 'Content failed to render.',
|
|
14
15
|
'content fallback message': 'Unsupported',
|
|
15
16
|
'content fallback description':
|
|
@@ -33,18 +34,19 @@ export default [
|
|
|
33
34
|
'reload required message': 'Reload required.',
|
|
34
35
|
'pending heading': 'Loading…',
|
|
35
36
|
'insert plank label': 'Open',
|
|
36
|
-
'
|
|
37
|
+
'resize label': 'Drag to resize',
|
|
38
|
+
'pin start label': 'Pin to the left sidebar',
|
|
39
|
+
'pin end label': 'Pin to the right sidebar',
|
|
40
|
+
'increment start label': 'Move to the left',
|
|
41
|
+
'increment end label': 'Move to the right',
|
|
42
|
+
'solo plank label': 'Toggle solo mode',
|
|
43
|
+
'close label': 'Close',
|
|
44
|
+
'minify label': 'Minify',
|
|
37
45
|
'settings overscroll label': 'Plank Overscrolling',
|
|
38
46
|
'select overscroll placeholder': 'Select plank overscrolling behavior',
|
|
39
47
|
'settings overscroll centering label': 'Centering',
|
|
40
48
|
'settings overscroll none label': 'None',
|
|
41
49
|
'settings flat deck': 'Flatten deck appearance',
|
|
42
|
-
|
|
43
|
-
// ComplementarySidebar
|
|
44
|
-
'open settings label': 'Show settings',
|
|
45
|
-
'open comments label': 'Show Comments',
|
|
46
|
-
'open automation label': 'Show Automation',
|
|
47
|
-
'open debug label': 'Show Debug',
|
|
48
50
|
},
|
|
49
51
|
},
|
|
50
52
|
},
|