@dxos/plugin-deck 0.6.13 → 0.6.14-main.2b6a0f3

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.
Files changed (53) hide show
  1. package/dist/lib/browser/{chunk-YVHGFQQR.mjs → chunk-GVOGPULO.mjs} +1 -1
  2. package/dist/lib/browser/chunk-GVOGPULO.mjs.map +7 -0
  3. package/dist/lib/browser/index.mjs +331 -264
  4. package/dist/lib/browser/index.mjs.map +3 -3
  5. package/dist/lib/browser/meta.json +1 -1
  6. package/dist/lib/browser/meta.mjs +1 -1
  7. package/dist/types/src/DeckPlugin.d.ts.map +1 -1
  8. package/dist/types/src/components/DeckLayout/ActiveNode.d.ts +1 -3
  9. package/dist/types/src/components/DeckLayout/ActiveNode.d.ts.map +1 -1
  10. package/dist/types/src/components/DeckLayout/ComplementarySidebar.d.ts +2 -4
  11. package/dist/types/src/components/DeckLayout/ComplementarySidebar.d.ts.map +1 -1
  12. package/dist/types/src/components/DeckLayout/DeckLayout.d.ts +3 -4
  13. package/dist/types/src/components/DeckLayout/DeckLayout.d.ts.map +1 -1
  14. package/dist/types/src/components/DeckLayout/NodePlankHeading.d.ts +9 -7
  15. package/dist/types/src/components/DeckLayout/NodePlankHeading.d.ts.map +1 -1
  16. package/dist/types/src/components/DeckLayout/Plank.d.ts +1 -1
  17. package/dist/types/src/components/DeckLayout/Plank.d.ts.map +1 -1
  18. package/dist/types/src/components/DeckLayout/PlankError.d.ts +1 -2
  19. package/dist/types/src/components/DeckLayout/PlankError.d.ts.map +1 -1
  20. package/dist/types/src/components/DeckLayout/Sidebar.d.ts +2 -3
  21. package/dist/types/src/components/DeckLayout/Sidebar.d.ts.map +1 -1
  22. package/dist/types/src/components/DeckLayout/StatusBar.d.ts +3 -1
  23. package/dist/types/src/components/DeckLayout/StatusBar.d.ts.map +1 -1
  24. package/dist/types/src/components/DeckLayout/Toast.d.ts.map +1 -1
  25. package/dist/types/src/components/LayoutSettings.d.ts.map +1 -1
  26. package/dist/types/src/hooks/useNode.d.ts.map +1 -1
  27. package/dist/types/src/layout.d.ts.map +1 -1
  28. package/dist/types/src/meta.d.ts.map +1 -1
  29. package/dist/types/src/translations.d.ts +5 -3
  30. package/dist/types/src/translations.d.ts.map +1 -1
  31. package/dist/types/src/types.d.ts +1 -1
  32. package/dist/types/src/types.d.ts.map +1 -1
  33. package/dist/types/src/util/overscroll.d.ts +1 -1
  34. package/dist/types/src/util/overscroll.d.ts.map +1 -1
  35. package/package.json +31 -29
  36. package/src/DeckPlugin.tsx +93 -71
  37. package/src/components/DeckLayout/ActiveNode.tsx +4 -1
  38. package/src/components/DeckLayout/ComplementarySidebar.tsx +70 -28
  39. package/src/components/DeckLayout/DeckLayout.tsx +64 -96
  40. package/src/components/DeckLayout/NodePlankHeading.tsx +130 -127
  41. package/src/components/DeckLayout/Plank.tsx +31 -22
  42. package/src/components/DeckLayout/PlankError.tsx +1 -9
  43. package/src/components/DeckLayout/Sidebar.tsx +6 -5
  44. package/src/components/DeckLayout/StatusBar.tsx +12 -3
  45. package/src/components/DeckLayout/Toast.tsx +3 -3
  46. package/src/components/LayoutSettings.tsx +5 -8
  47. package/src/hooks/useNode.ts +5 -1
  48. package/src/layout.ts +1 -0
  49. package/src/meta.ts +3 -1
  50. package/src/translations.ts +7 -3
  51. package/src/types.ts +1 -1
  52. package/src/util/overscroll.ts +5 -5
  53. package/dist/lib/browser/chunk-YVHGFQQR.mjs.map +0 -7
@@ -1,15 +1,15 @@
1
1
  import {
2
2
  DECK_PLUGIN,
3
3
  meta_default
4
- } from "./chunk-YVHGFQQR.mjs";
4
+ } from "./chunk-GVOGPULO.mjs";
5
5
 
6
6
  // packages/plugins/plugin-deck/src/DeckPlugin.tsx
7
- import { ArrowsOut } from "@phosphor-icons/react";
8
- import { batch, effect } from "@preact/signals-core";
7
+ import { batch } from "@preact/signals-core";
9
8
  import { setAutoFreeze } from "immer";
10
9
  import React15 from "react";
11
- import { IntentAction, LayoutAction as LayoutAction3, NavigationAction as NavigationAction3, parseGraphPlugin, parseIntentPlugin, resolvePlugin, Toast as ToastSchema, SLUG_PATH_SEPARATOR as SLUG_PATH_SEPARATOR5, isLayoutParts, isLayoutAdjustment, isLayoutMode, openIds as openIds2 } from "@dxos/app-framework";
10
+ import { IntentAction, LayoutAction as LayoutAction3, NavigationAction as NavigationAction4, parseGraphPlugin, parseIntentPlugin, resolvePlugin, Toast as ToastSchema, SLUG_PATH_SEPARATOR as SLUG_PATH_SEPARATOR4, isLayoutParts, isLayoutAdjustment, isLayoutMode, openIds as openIds2 } from "@dxos/app-framework";
12
11
  import { create, getTypename, isReactiveObject } from "@dxos/echo-schema";
12
+ import { scheduledEffect } from "@dxos/echo-signals/core";
13
13
  import { LocalStorageStore } from "@dxos/local-storage";
14
14
  import { log } from "@dxos/log";
15
15
  import { parseAttentionPlugin } from "@dxos/plugin-attention";
@@ -18,7 +18,6 @@ import { createExtension } from "@dxos/plugin-graph";
18
18
  import { ObservabilityAction } from "@dxos/plugin-observability/meta";
19
19
  import { fullyQualifiedId } from "@dxos/react-client/echo";
20
20
  import { translations as deckTranslations } from "@dxos/react-ui-deck";
21
- import { Mosaic } from "@dxos/react-ui-mosaic";
22
21
 
23
22
  // packages/plugins/plugin-deck/src/components/DeckLayout/constants.ts
24
23
  var NAV_ID = "NavTree";
@@ -26,22 +25,27 @@ var SURFACE_PREFIX = "surface:";
26
25
 
27
26
  // packages/plugins/plugin-deck/src/components/DeckLayout/DeckLayout.tsx
28
27
  import { Sidebar as MenuIcon } from "@phosphor-icons/react";
29
- import React13, { useCallback as useCallback2, useEffect as useEffect5, useMemo as useMemo2, useRef as useRef2, useState as useState3, useLayoutEffect as useLayoutEffect2 } from "react";
30
- import { SLUG_PATH_SEPARATOR as SLUG_PATH_SEPARATOR3, Surface as Surface9, firstIdInPart, usePlugin } from "@dxos/app-framework";
31
- import { Button as Button3, Dialog, Main as Main3, Popover as Popover2, useTranslation as useTranslation5 } from "@dxos/react-ui";
28
+ import { untracked } from "@preact/signals-core";
29
+ import React13, { useCallback as useCallback2, useEffect as useEffect5, useMemo as useMemo5, useRef as useRef2 } from "react";
30
+ import { Surface as Surface9, firstIdInPart, usePlugin } from "@dxos/app-framework";
31
+ import { Button as Button3, Dialog, Main as Main3, Popover as Popover2, useOnTransition, useTranslation as useTranslation5 } from "@dxos/react-ui";
32
32
  import { Deck } from "@dxos/react-ui-deck";
33
- import { getSize } from "@dxos/react-ui-theme";
33
+ import { getSize, mainPaddingTransitions as mainPaddingTransitions2 } from "@dxos/react-ui-theme";
34
34
 
35
35
  // packages/plugins/plugin-deck/src/components/DeckLayout/ActiveNode.tsx
36
36
  import React from "react";
37
37
  import { Surface } from "@dxos/app-framework";
38
38
  import { useGraph } from "@dxos/plugin-graph";
39
+ import { useAttended } from "@dxos/react-ui-attention";
39
40
 
40
41
  // packages/plugins/plugin-deck/src/hooks/useNode.ts
41
42
  import { useEffect, useState } from "react";
42
43
  var useNode = (graph, id, timeout) => {
43
- const [nodeState, setNodeState] = useState(id ? graph.findNode(id) : void 0);
44
+ const [nodeState, setNodeState] = useState(id ? graph.findNode(id, false) : void 0);
44
45
  useEffect(() => {
46
+ if (!id && nodeState) {
47
+ setNodeState(void 0);
48
+ }
45
49
  if (nodeState?.id === id || !id) {
46
50
  return;
47
51
  }
@@ -96,7 +100,8 @@ var useMainSize = () => {
96
100
  };
97
101
 
98
102
  // packages/plugins/plugin-deck/src/components/DeckLayout/ActiveNode.tsx
99
- var ActiveNode = ({ id }) => {
103
+ var ActiveNode = () => {
104
+ const [id] = useAttended();
100
105
  const { graph } = useGraph();
101
106
  const activeNode = useNode(graph, id);
102
107
  useNodeActionExpander(activeNode);
@@ -113,36 +118,25 @@ var ActiveNode = ({ id }) => {
113
118
  };
114
119
 
115
120
  // packages/plugins/plugin-deck/src/components/DeckLayout/ComplementarySidebar.tsx
116
- import React5 from "react";
117
- import { SLUG_PATH_SEPARATOR as SLUG_PATH_SEPARATOR2, Surface as Surface3 } from "@dxos/app-framework";
121
+ import React5, { useMemo as useMemo2 } from "react";
122
+ import { NavigationAction as NavigationAction2, SLUG_PATH_SEPARATOR as SLUG_PATH_SEPARATOR2, Surface as Surface3, useIntentDispatcher as useIntentDispatcher2 } from "@dxos/app-framework";
118
123
  import { useGraph as useGraph3 } from "@dxos/plugin-graph";
119
124
  import { Main } from "@dxos/react-ui";
120
- import { createAttendableAttributes } from "@dxos/react-ui-attention";
125
+ import { useAttended as useAttended2 } from "@dxos/react-ui-attention";
121
126
  import { deckGrid } from "@dxos/react-ui-deck";
122
127
  import { mx as mx2 } from "@dxos/react-ui-theme";
123
128
 
124
129
  // packages/plugins/plugin-deck/src/components/DeckLayout/NodePlankHeading.tsx
125
- import { Placeholder } from "@phosphor-icons/react";
126
- import React2, { Fragment, useEffect as useEffect3 } from "react";
127
- import { LayoutAction, NavigationAction, SLUG_COLLECTION_INDICATOR, SLUG_PATH_SEPARATOR, Surface as Surface2, useIntentDispatcher, indexInPart, partLength } from "@dxos/app-framework";
130
+ import React2, { Fragment, memo, useEffect as useEffect3, useMemo } from "react";
131
+ import { LayoutAction, NavigationAction, SLUG_PATH_SEPARATOR, Surface as Surface2, useIntentDispatcher } from "@dxos/app-framework";
128
132
  import { useGraph as useGraph2 } from "@dxos/plugin-graph";
129
- import { Popover, toLocalizedString, useMediaQuery, useTranslation } from "@dxos/react-ui";
130
- import { PlankHeading, plankHeadingIconProps } from "@dxos/react-ui-deck";
133
+ import { Icon, Popover, toLocalizedString, useMediaQuery, useTranslation } from "@dxos/react-ui";
134
+ import { PlankHeading } from "@dxos/react-ui-deck";
131
135
  import { TextTooltip } from "@dxos/react-ui-text-tooltip";
132
- var NodePlankHeading = ({
133
- node,
134
- id,
135
- layoutParts,
136
- layoutPart,
137
- // TODO(wittjosiah): Unused?
138
- layoutEntry,
139
- popoverAnchorId,
140
- pending,
141
- flatDeck
142
- }) => {
136
+ var NodePlankHeading = /* @__PURE__ */ memo(({ coordinate, node, canIncrementStart, canIncrementEnd, popoverAnchorId, pending, flatDeck, actions = [] }) => {
143
137
  const { t } = useTranslation(DECK_PLUGIN);
144
138
  const { graph } = useGraph2();
145
- const Icon = node?.properties?.icon ?? Placeholder;
139
+ const icon = node?.properties?.icon ?? "ph--placeholder--regular";
146
140
  const label = pending ? t("pending heading") : toLocalizedString(node?.properties?.label ?? [
147
141
  "plank heading fallback label",
148
142
  {
@@ -160,22 +154,29 @@ var NodePlankHeading = ({
160
154
  }, [
161
155
  node
162
156
  ]);
163
- const attendableId = id?.split(SLUG_PATH_SEPARATOR).at(0);
164
- const layoutCoordinate = layoutPart !== void 0 && id !== void 0 ? {
165
- part: layoutPart,
166
- entryId: id
167
- } : void 0;
168
- const index = indexInPart(layoutParts, layoutCoordinate);
169
- const length = partLength(layoutParts, layoutPart);
170
- const canIncrementStart = layoutPart === "main" && index !== void 0 && index > 0 && length !== void 0 && length > 1;
171
- const canIncrementEnd = layoutPart === "main" && index !== void 0 && index < length - 1 && length !== void 0;
157
+ const layoutPart = coordinate.part;
158
+ const attendableId = coordinate.entryId.split(SLUG_PATH_SEPARATOR).at(0);
159
+ const capabilities = useMemo(() => ({
160
+ solo: (layoutPart === "solo" || layoutPart === "main") && isNotMobile,
161
+ incrementStart: canIncrementStart,
162
+ incrementEnd: canIncrementEnd
163
+ }), [
164
+ isNotMobile,
165
+ layoutPart,
166
+ canIncrementStart,
167
+ canIncrementEnd
168
+ ]);
172
169
  return /* @__PURE__ */ React2.createElement(PlankHeading.Root, (layoutPart !== "main" || !flatDeck) && {
173
170
  classNames: "pie-1 border-b border-separator"
174
171
  }, /* @__PURE__ */ React2.createElement(ActionRoot, null, node ? /* @__PURE__ */ React2.createElement(PlankHeading.ActionsMenu, {
175
- Icon,
172
+ icon,
173
+ related: layoutPart === "complementary",
176
174
  attendableId,
177
175
  triggerLabel: t("actions menu label"),
178
- actions: graph.actions(node),
176
+ actions: [
177
+ actions,
178
+ graph.actions(node)
179
+ ].filter((a) => a.length > 0),
179
180
  onAction: (action) => typeof action.data === "function" && action.data?.({
180
181
  node: action,
181
182
  caller: DECK_PLUGIN
@@ -187,11 +188,15 @@ var NodePlankHeading = ({
187
188
  }
188
189
  })) : /* @__PURE__ */ React2.createElement(PlankHeading.Button, null, /* @__PURE__ */ React2.createElement("span", {
189
190
  className: "sr-only"
190
- }, label), /* @__PURE__ */ React2.createElement(Icon, plankHeadingIconProps))), /* @__PURE__ */ React2.createElement(TextTooltip, {
191
+ }, label), /* @__PURE__ */ React2.createElement(Icon, {
192
+ icon,
193
+ size: 5
194
+ }))), /* @__PURE__ */ React2.createElement(TextTooltip, {
191
195
  text: label,
192
196
  onlyWhenTruncating: true
193
197
  }, /* @__PURE__ */ React2.createElement(PlankHeading.Label, {
194
- attendableId: node?.id,
198
+ attendableId,
199
+ related: layoutPart === "complementary",
195
200
  ...pending && {
196
201
  classNames: "text-description"
197
202
  }
@@ -203,11 +208,7 @@ var NodePlankHeading = ({
203
208
  object: node.data
204
209
  }
205
210
  }), /* @__PURE__ */ React2.createElement(PlankHeading.Controls, {
206
- capabilities: {
207
- solo: (layoutPart === "solo" || layoutPart === "main") && isNotMobile,
208
- incrementStart: canIncrementStart,
209
- incrementEnd: canIncrementEnd
210
- },
211
+ capabilities,
211
212
  isSolo: layoutPart === "solo",
212
213
  onClick: (eventType) => {
213
214
  if (!layoutPart) {
@@ -221,41 +222,45 @@ var NodePlankHeading = ({
221
222
  type: eventType,
222
223
  layoutCoordinate: {
223
224
  part: "main",
224
- entryId: id
225
+ entryId: coordinate.entryId
225
226
  }
226
227
  }
227
228
  }
228
229
  ]);
229
- }
230
- return dispatch(eventType === "close" ? layoutPart === "complementary" ? {
231
- action: LayoutAction.SET_LAYOUT,
232
- data: {
233
- element: "complementary",
234
- state: false
230
+ } else if (eventType === "close") {
231
+ if (layoutPart === "complementary") {
232
+ return dispatch({
233
+ action: LayoutAction.SET_LAYOUT,
234
+ data: {
235
+ element: "complementary",
236
+ state: false
237
+ }
238
+ });
239
+ } else {
240
+ return dispatch({
241
+ action: NavigationAction.CLOSE,
242
+ data: {
243
+ activeParts: {
244
+ [layoutPart]: [
245
+ coordinate.entryId
246
+ ]
247
+ }
248
+ }
249
+ });
235
250
  }
236
- } : {
237
- action: NavigationAction.CLOSE,
238
- data: {
239
- activeParts: {
240
- complementary: [
241
- `${id}${SLUG_PATH_SEPARATOR}comments${SLUG_COLLECTION_INDICATOR}`
242
- ],
243
- [layoutPart]: [
244
- id
245
- ]
251
+ } else {
252
+ return dispatch({
253
+ action: NavigationAction.ADJUST,
254
+ data: {
255
+ type: eventType,
256
+ layoutCoordinate: coordinate
246
257
  }
247
- }
248
- } : {
249
- action: NavigationAction.ADJUST,
250
- data: {
251
- type: eventType,
252
- layoutCoordinate
253
- }
254
- });
258
+ });
259
+ }
255
260
  },
256
- close: layoutCoordinate?.part === "complementary" ? "minify-end" : true
261
+ close: layoutPart === "complementary" ? "minify-end" : true
257
262
  }));
258
- };
263
+ });
259
264
 
260
265
  // packages/plugins/plugin-deck/src/components/DeckLayout/PlankError.tsx
261
266
  import React4, { useEffect as useEffect4, useState as useState2 } from "react";
@@ -291,15 +296,14 @@ var PlankContentError = ({ error }) => {
291
296
  )
292
297
  }, error ? error.toString() : t("error fallback message")));
293
298
  };
294
- var PlankError = ({ layoutCoordinate, id, node, error, flatDeck }) => {
299
+ var PlankError = ({ layoutCoordinate, node, error, flatDeck }) => {
295
300
  const [timedOut, setTimedOut] = useState2(false);
296
301
  useEffect4(() => {
297
302
  setTimeout(() => setTimedOut(true), 5e3);
298
303
  }, []);
299
304
  return /* @__PURE__ */ React4.createElement(React4.Fragment, null, /* @__PURE__ */ React4.createElement(NodePlankHeading, {
305
+ coordinate: layoutCoordinate,
300
306
  node,
301
- id,
302
- layoutPart: layoutCoordinate.part,
303
307
  pending: !timedOut,
304
308
  flatDeck
305
309
  }), timedOut ? /* @__PURE__ */ React4.createElement(PlankContentError, {
@@ -314,33 +318,89 @@ var LayoutContext = createContext(null);
314
318
  var useLayout = () => useContext(LayoutContext) ?? raise(new Error("Missing LayoutContext"));
315
319
 
316
320
  // packages/plugins/plugin-deck/src/components/DeckLayout/ComplementarySidebar.tsx
317
- var ComplementarySidebar = ({ id, layoutParts, flatDeck }) => {
321
+ var panels = [
322
+ {
323
+ id: "settings",
324
+ icon: "ph--gear--regular"
325
+ },
326
+ {
327
+ id: "comments",
328
+ icon: "ph--chat-text--regular"
329
+ },
330
+ {
331
+ id: "automation",
332
+ icon: "ph--atom--regular"
333
+ },
334
+ {
335
+ id: "debug",
336
+ icon: "ph--bug--regular"
337
+ }
338
+ ];
339
+ var getPanel = (id) => {
340
+ const panel = panels.find((p) => p.id === id) ?? panels[0];
341
+ return panel.id;
342
+ };
343
+ var ComplementarySidebar = ({ panel, flatDeck }) => {
318
344
  const { popoverAnchorId } = useLayout();
345
+ const attended = useAttended2();
346
+ const part = getPanel(panel);
347
+ const id = attended[0] ? `${attended[0]}${SLUG_PATH_SEPARATOR2}${part}` : void 0;
319
348
  const { graph } = useGraph3();
320
349
  const node = useNode(graph, id);
321
- const complementaryAttrs = createAttendableAttributes(id?.split(SLUG_PATH_SEPARATOR2)[0] ?? "never");
350
+ const dispatch = useIntentDispatcher2();
322
351
  useNodeActionExpander(node);
323
- return /* @__PURE__ */ React5.createElement(Main.ComplementarySidebar, complementaryAttrs, node ? /* @__PURE__ */ React5.createElement("div", {
352
+ const actions = useMemo2(() => panels.map(({ id: id2, icon }) => ({
353
+ id: `complementary-${id2}`,
354
+ data: () => {
355
+ void dispatch({
356
+ action: NavigationAction2.OPEN,
357
+ data: {
358
+ activeParts: {
359
+ complementary: id2
360
+ }
361
+ }
362
+ });
363
+ },
364
+ properties: {
365
+ label: [
366
+ `open ${id2} label`,
367
+ {
368
+ ns: DECK_PLUGIN
369
+ }
370
+ ],
371
+ icon,
372
+ menuItemType: "toggle",
373
+ isChecked: part === id2
374
+ }
375
+ })), [
376
+ part
377
+ ]);
378
+ const coordinate = useMemo2(() => ({
379
+ entryId: id ?? "unknown",
380
+ part: "complementary"
381
+ }), [
382
+ id
383
+ ]);
384
+ return /* @__PURE__ */ React5.createElement(Main.ComplementarySidebar, null, /* @__PURE__ */ React5.createElement("div", {
324
385
  role: "none",
325
386
  className: mx2(deckGrid, "grid-cols-1 bs-full")
326
387
  }, /* @__PURE__ */ React5.createElement(NodePlankHeading, {
388
+ coordinate,
327
389
  node,
328
- id,
329
- layoutParts,
330
- layoutPart: "complementary",
331
390
  popoverAnchorId,
332
- flatDeck
333
- }), /* @__PURE__ */ React5.createElement(Surface3, {
334
- role: "article",
391
+ flatDeck,
392
+ actions
393
+ }), /* @__PURE__ */ React5.createElement("div", {
394
+ className: "row-span-2 divide-y divide-separator"
395
+ }, node && /* @__PURE__ */ React5.createElement(Surface3, {
396
+ role: `complementary--${part}`,
335
397
  data: {
336
- subject: node.data,
337
- part: "complementary",
398
+ subject: node.properties.object,
338
399
  popoverAnchorId
339
400
  },
340
- limit: 1,
341
401
  fallback: PlankContentError,
342
402
  placeholder: /* @__PURE__ */ React5.createElement(PlankLoading, null)
343
- })) : null);
403
+ }))));
344
404
  };
345
405
 
346
406
  // packages/plugins/plugin-deck/src/components/DeckLayout/ContentEmpty.tsx
@@ -400,12 +460,12 @@ var Fullscreen = ({ id }) => {
400
460
 
401
461
  // packages/plugins/plugin-deck/src/components/DeckLayout/Plank.tsx
402
462
  import { Plus } from "@phosphor-icons/react";
403
- import React9, { useCallback, useLayoutEffect, useRef } from "react";
404
- import { LayoutAction as LayoutAction2, NavigationAction as NavigationAction2, Surface as Surface6, useIntentDispatcher as useIntentDispatcher2 } from "@dxos/app-framework";
463
+ import React9, { memo as memo2, useCallback, useLayoutEffect, useMemo as useMemo3, useRef } from "react";
464
+ import { LayoutAction as LayoutAction2, NavigationAction as NavigationAction3, Surface as Surface6, useIntentDispatcher as useIntentDispatcher3, indexInPart, partLength } from "@dxos/app-framework";
405
465
  import { debounce } from "@dxos/async";
406
466
  import { useGraph as useGraph5 } from "@dxos/plugin-graph";
407
467
  import { Button, Tooltip, useTranslation as useTranslation4 } from "@dxos/react-ui";
408
- import { createAttendableAttributes as createAttendableAttributes2 } from "@dxos/react-ui-attention";
468
+ import { useAttendableAttributes } from "@dxos/react-ui-attention";
409
469
  import { Plank as NaturalPlank } from "@dxos/react-ui-deck";
410
470
  import { mainIntrinsicSize } from "@dxos/react-ui-theme";
411
471
 
@@ -416,20 +476,27 @@ var DeckContext = createContext2(null);
416
476
  var useDeckContext = () => useContext2(DeckContext) ?? raise2(new Error("Missing DeckContext"));
417
477
 
418
478
  // packages/plugins/plugin-deck/src/components/DeckLayout/Plank.tsx
419
- var Plank = ({ entry, layoutParts, part, flatDeck, searchEnabled, layoutMode }) => {
479
+ var Plank = /* @__PURE__ */ memo2(({ entry, layoutParts, part, flatDeck, searchEnabled, layoutMode }) => {
420
480
  const { t } = useTranslation4(DECK_PLUGIN);
421
- const dispatch = useIntentDispatcher2();
481
+ const dispatch = useIntentDispatcher3();
422
482
  const { popoverAnchorId, scrollIntoView } = useLayout();
423
483
  const { plankSizing } = useDeckContext();
424
484
  const { graph } = useGraph5();
425
485
  const node = useNode(graph, entry.id);
426
486
  const rootElement = useRef(null);
427
487
  const resizeable = layoutMode === "deck";
428
- const attendableAttrs = createAttendableAttributes2(entry.id);
429
- const coordinate = {
488
+ const attendableAttrs = useAttendableAttributes(entry.id);
489
+ const coordinate = useMemo3(() => ({
430
490
  part,
431
491
  entryId: entry.id
432
- };
492
+ }), [
493
+ entry.id,
494
+ part
495
+ ]);
496
+ const index = indexInPart(layoutParts, coordinate);
497
+ const length = partLength(layoutParts, part);
498
+ const canIncrementStart = part === "main" && index !== void 0 && index > 0 && length !== void 0 && length > 1;
499
+ const canIncrementEnd = part === "main" && index !== void 0 && index < length - 1 && length !== void 0;
433
500
  const size = plankSizing?.[entry.id];
434
501
  const setSize = useCallback(debounce((newSize) => {
435
502
  void dispatch({
@@ -463,8 +530,21 @@ var Plank = ({ entry, layoutParts, part, flatDeck, searchEnabled, layoutMode })
463
530
  layoutMode
464
531
  ]);
465
532
  const isSolo = layoutMode === "solo" && part === "solo";
466
- const isSuppressed = layoutMode === "solo" && part !== "solo";
533
+ const isSuppressed = layoutMode === "solo" && part !== "solo" || layoutMode === "deck" && part === "solo";
467
534
  const sizeAttrs = useMainSize();
535
+ const data = useMemo3(() => node && {
536
+ ...entry.path ? {
537
+ subject: node.data,
538
+ path: entry.path
539
+ } : {
540
+ object: node.data
541
+ },
542
+ coordinate,
543
+ popoverAnchorId
544
+ }, [
545
+ node
546
+ ]);
547
+ const placeholder = useMemo3(() => /* @__PURE__ */ React9.createElement(PlankLoading, null), []);
468
548
  return /* @__PURE__ */ React9.createElement(NaturalPlank.Root, {
469
549
  size,
470
550
  setSize,
@@ -487,30 +567,20 @@ var Plank = ({ entry, layoutParts, part, flatDeck, searchEnabled, layoutMode })
487
567
  inlineSize: ""
488
568
  } : {}
489
569
  }, node ? /* @__PURE__ */ React9.createElement(React9.Fragment, null, /* @__PURE__ */ React9.createElement(NodePlankHeading, {
490
- id: entry.id,
570
+ coordinate,
491
571
  node,
492
- layoutPart: coordinate.part,
493
- layoutParts,
572
+ canIncrementStart,
573
+ canIncrementEnd,
494
574
  popoverAnchorId,
495
575
  flatDeck
496
576
  }), /* @__PURE__ */ React9.createElement(Surface6, {
497
577
  role: "article",
498
- data: {
499
- ...entry.path ? {
500
- subject: node.data,
501
- path: entry.path
502
- } : {
503
- object: node.data
504
- },
505
- coordinate,
506
- popoverAnchorId
507
- },
578
+ data,
508
579
  limit: 1,
509
580
  fallback: PlankContentError,
510
- placeholder: /* @__PURE__ */ React9.createElement(PlankLoading, null)
581
+ placeholder
511
582
  })) : /* @__PURE__ */ React9.createElement(PlankError, {
512
583
  layoutCoordinate: coordinate,
513
- id: entry.id,
514
584
  flatDeck
515
585
  })), searchEnabled && resizeable ? /* @__PURE__ */ React9.createElement("div", {
516
586
  role: "none",
@@ -529,7 +599,7 @@ var Plank = ({ entry, layoutParts, part, flatDeck, searchEnabled, layoutMode })
529
599
  component: "dxos.org/plugin/search/Dialog",
530
600
  dialogBlockAlign: "start",
531
601
  subject: {
532
- action: NavigationAction2.SET,
602
+ action: NavigationAction3.SET,
533
603
  position: "add-after",
534
604
  coordinate
535
605
  }
@@ -546,15 +616,17 @@ var Plank = ({ entry, layoutParts, part, flatDeck, searchEnabled, layoutMode })
546
616
  })) : resizeable ? /* @__PURE__ */ React9.createElement(NaturalPlank.ResizeHandle, {
547
617
  classNames: "row-span-3"
548
618
  }) : null);
549
- };
619
+ });
550
620
 
551
621
  // packages/plugins/plugin-deck/src/components/DeckLayout/Sidebar.tsx
552
- import React10, { useMemo } from "react";
622
+ import React10, { useMemo as useMemo4 } from "react";
553
623
  import { openIds, Surface as Surface7 } from "@dxos/app-framework";
554
624
  import { Main as Main2 } from "@dxos/react-ui";
555
- var Sidebar = ({ attention, layoutParts }) => {
625
+ import { useAttended as useAttended3 } from "@dxos/react-ui-attention";
626
+ var Sidebar = ({ layoutParts }) => {
556
627
  const { layoutMode, popoverAnchorId } = useLayout();
557
- const activeIds = useMemo(() => {
628
+ const attended = useAttended3();
629
+ const activeIds = useMemo4(() => {
558
630
  if (layoutMode === "solo") {
559
631
  return new Set(layoutParts?.solo?.map((e) => e.id) ?? []);
560
632
  } else if (layoutMode === "deck") {
@@ -565,14 +637,14 @@ var Sidebar = ({ attention, layoutParts }) => {
565
637
  layoutParts,
566
638
  layoutMode
567
639
  ]);
568
- const navigationData = useMemo(() => ({
640
+ const navigationData = useMemo4(() => ({
569
641
  popoverAnchorId,
570
642
  activeIds,
571
- attended: attention.attended
643
+ attended
572
644
  }), [
573
645
  popoverAnchorId,
574
646
  activeIds,
575
- attention.attended
647
+ attended
576
648
  ]);
577
649
  return /* @__PURE__ */ React10.createElement(Main2.NavigationSidebar, null, /* @__PURE__ */ React10.createElement(Surface7, {
578
650
  role: "navigation",
@@ -586,14 +658,19 @@ var Sidebar = ({ attention, layoutParts }) => {
586
658
  // packages/plugins/plugin-deck/src/components/DeckLayout/StatusBar.tsx
587
659
  import React11 from "react";
588
660
  import { Surface as Surface8 } from "@dxos/app-framework";
589
- import { mainPadding, mx as mx4 } from "@dxos/react-ui-theme";
590
- var StatusBar = () => {
661
+ import { mainPadding, mainPaddingTransitions, mx as mx4 } from "@dxos/react-ui-theme";
662
+ var StatusBar = ({ showHints }) => {
591
663
  const sizeAttrs = useMainSize();
592
664
  return /* @__PURE__ */ React11.createElement("div", {
593
665
  role: "none",
594
666
  ...sizeAttrs,
595
- className: mx4("fixed block-end-0 inset-inline-0 z-[2]", mainPadding)
596
- }, /* @__PURE__ */ React11.createElement(Surface8, {
667
+ className: mx4("fixed flex justify-between block-end-0 inset-inline-0 items-center border-bs border-separator z-[2]", mainPadding, mainPaddingTransitions)
668
+ }, /* @__PURE__ */ React11.createElement("div", {
669
+ role: "none"
670
+ }, showHints && /* @__PURE__ */ React11.createElement(Surface8, {
671
+ role: "hints",
672
+ limit: 1
673
+ })), /* @__PURE__ */ React11.createElement(Surface8, {
597
674
  role: "status-bar",
598
675
  limit: 1
599
676
  }));
@@ -601,15 +678,19 @@ var StatusBar = () => {
601
678
 
602
679
  // packages/plugins/plugin-deck/src/components/DeckLayout/Toast.tsx
603
680
  import React12 from "react";
604
- import { Button as Button2, Toast as NaturalToast } from "@dxos/react-ui";
681
+ import { Button as Button2, Icon as Icon2, Toast as NaturalToast } from "@dxos/react-ui";
605
682
  var Toast = ({ id, title, description, icon, duration, actionLabel, actionAlt, closeLabel, onAction, onOpenChange }) => {
606
683
  return /* @__PURE__ */ React12.createElement(NaturalToast.Root, {
607
684
  "data-testid": id,
608
685
  defaultOpen: true,
609
686
  duration,
610
687
  onOpenChange
611
- }, /* @__PURE__ */ React12.createElement(NaturalToast.Body, null, /* @__PURE__ */ React12.createElement(NaturalToast.Title, null, icon?.({
612
- className: "inline mr-1"
688
+ }, /* @__PURE__ */ React12.createElement(NaturalToast.Body, null, /* @__PURE__ */ React12.createElement(NaturalToast.Title, {
689
+ classNames: "items-center"
690
+ }, /* @__PURE__ */ React12.createElement(Icon2, {
691
+ icon,
692
+ size: 5,
693
+ classNames: "inline mr-1"
613
694
  }), /* @__PURE__ */ React12.createElement("span", null, title)), description && /* @__PURE__ */ React12.createElement(NaturalToast.Description, null, description)), /* @__PURE__ */ React12.createElement(NaturalToast.Actions, null, onAction && actionAlt && actionLabel && /* @__PURE__ */ React12.createElement(NaturalToast.Action, {
614
695
  altText: actionAlt,
615
696
  asChild: true
@@ -646,7 +727,10 @@ var getEffectivePart = (partName, layoutMode) => layoutMode === "solo" && partNa
646
727
  import { PLANK_DEFAULTS } from "@dxos/react-ui-deck";
647
728
  var calculateOverscroll = (planks, plankSizing, sidebarOpen, complementarySidebarOpen) => {
648
729
  if (!planks?.length) {
649
- return;
730
+ return {
731
+ paddingInlineStart: 0,
732
+ paddingInlineEnd: 0
733
+ };
650
734
  }
651
735
  const sidebarWidth = sidebarOpen ? "270px" : "0px";
652
736
  const complementarySidebarWidth = complementarySidebarOpen ? "360px" : "0px";
@@ -656,8 +740,8 @@ var calculateOverscroll = (planks, plankSizing, sidebarOpen, complementarySideba
656
740
  const plankSize = getPlankSize(plank.id);
657
741
  const overscrollPadding = `max(0px, calc(((100dvw - ${sidebarWidth} - ${complementarySidebarWidth} - (${plankSize} + 20px)) / 2)))`;
658
742
  return {
659
- paddingLeft: overscrollPadding,
660
- paddingRight: overscrollPadding
743
+ paddingInlineStart: overscrollPadding,
744
+ paddingInlineEnd: overscrollPadding
661
745
  };
662
746
  } else {
663
747
  const first = planks[0];
@@ -665,27 +749,34 @@ var calculateOverscroll = (planks, plankSizing, sidebarOpen, complementarySideba
665
749
  const last = planks[planks.length - 1];
666
750
  const lastSize = getPlankSize(last.id);
667
751
  return {
668
- paddingLeft: `max(0px, calc(((100dvw - (${firstSize} + 20px)) / 2) - ${sidebarWidth}))`,
669
- paddingRight: `max(0px, calc(((100dvw - (${lastSize} + 20px)) / 2) - ${complementarySidebarWidth}))`
752
+ paddingInlineStart: `max(0px, calc(((100dvw - (${firstSize} + 20px)) / 2) - ${sidebarWidth}))`,
753
+ paddingInlineEnd: `max(0px, calc(((100dvw - (${lastSize} + 20px)) / 2) - ${complementarySidebarWidth}))`
670
754
  };
671
755
  }
672
756
  };
673
757
 
674
758
  // packages/plugins/plugin-deck/src/components/DeckLayout/DeckLayout.tsx
675
- var DeckLayout = ({ layoutParts, attention, toasts, flatDeck, overscroll, showHintsFooter, slots, onDismissToast }) => {
759
+ var DeckLayout = ({ layoutParts, toasts, flatDeck, overscroll, showHints, slots, onDismissToast }) => {
676
760
  const context = useLayout();
677
761
  const { layoutMode, sidebarOpen, complementarySidebarOpen, dialogOpen, dialogContent, dialogBlockAlign, popoverOpen, popoverContent, popoverAnchorId } = context;
678
762
  const { t } = useTranslation5(DECK_PLUGIN);
679
763
  const { plankSizing } = useDeckContext();
764
+ const attentionPlugin = usePlugin("dxos.org/plugin/attention");
680
765
  const searchPlugin = usePlugin("dxos.org/plugin/search");
681
- const fullScreenSlug = useMemo2(() => firstIdInPart(layoutParts, "fullScreen"), [
766
+ const fullScreenSlug = useMemo5(() => firstIdInPart(layoutParts, "fullScreen"), [
682
767
  layoutParts
683
768
  ]);
684
- const [scrollLeft, setScrollLeft] = useState3(null);
769
+ const scrollLeftRef = useRef2();
685
770
  const deckRef = useRef2(null);
686
- const restoreScrollRef = useRef2(false);
771
+ useEffect5(() => {
772
+ const attended = untracked(() => attentionPlugin?.provides.attention.attended ?? []);
773
+ const firstId = layoutMode === "solo" ? firstIdInPart(layoutParts, "solo") : firstIdInPart(layoutParts, "main");
774
+ if (attended.length === 0 && firstId) {
775
+ document.querySelector(`article[data-attendable-id="${firstId}"] button`)?.focus();
776
+ }
777
+ }, []);
687
778
  const handleResize = useCallback2(() => {
688
- setScrollLeft(null);
779
+ scrollLeftRef.current = null;
689
780
  }, []);
690
781
  useEffect5(() => {
691
782
  window.addEventListener("resize", handleResize);
@@ -693,58 +784,33 @@ var DeckLayout = ({ layoutParts, attention, toasts, flatDeck, overscroll, showHi
693
784
  }, [
694
785
  handleResize
695
786
  ]);
696
- useLayoutEffect2(() => {
697
- if (layoutMode !== "deck") {
698
- restoreScrollRef.current = true;
699
- } else if (restoreScrollRef.current && deckRef.current && scrollLeft) {
700
- deckRef.current.scrollLeft = scrollLeft;
701
- restoreScrollRef.current = false;
787
+ const restoreScroll = useCallback2(() => {
788
+ if (deckRef.current && scrollLeftRef.current != null) {
789
+ deckRef.current.scrollLeft = scrollLeftRef.current;
702
790
  }
703
- }, [
704
- layoutMode,
705
- deckRef.current,
706
- scrollLeft
707
- ]);
791
+ }, []);
792
+ useOnTransition(layoutMode, (mode) => mode !== "deck", "deck", restoreScroll);
708
793
  const handleScroll = useCallback2((event) => {
709
794
  if (layoutMode === "deck" && event.currentTarget === event.target) {
710
- setScrollLeft(event.target.scrollLeft);
795
+ scrollLeftRef.current = event.target.scrollLeft;
711
796
  }
712
797
  }, [
713
798
  layoutMode
714
799
  ]);
715
- const complementarySlug = useMemo2(() => {
716
- const entry = layoutParts.complementary?.at(0);
717
- if (entry) {
718
- return entry.path ? `${entry.id}${SLUG_PATH_SEPARATOR3}${entry.path}` : entry.id;
719
- }
720
- }, [
721
- layoutParts
722
- ]);
723
- const firstAttendedId = useMemo2(() => Array.from(attention.attended ?? [])[0], [
724
- attention.attended
725
- ]);
726
- useEffect5(() => {
727
- if (layoutMode === "deck" && firstAttendedId) {
800
+ const isEmpty = layoutParts.main?.length === 0 && layoutParts.solo?.length === 0;
801
+ const padding = useMemo5(() => {
802
+ if (layoutMode === "deck" && overscroll === "centering") {
803
+ return calculateOverscroll(layoutParts.main, plankSizing, sidebarOpen, complementarySidebarOpen);
728
804
  }
805
+ return {};
729
806
  }, [
730
807
  layoutMode,
731
- firstAttendedId
732
- ]);
733
- const parts = useMemo2(() => {
734
- const parts2 = [
735
- ...layoutParts.main ?? []
736
- ];
737
- for (const part of layoutParts.solo ?? []) {
738
- if (!parts2.find((entry) => entry.id === part.id)) {
739
- parts2.push(part);
740
- }
741
- }
742
- return parts2;
743
- }, [
808
+ overscroll,
744
809
  layoutParts.main,
745
- layoutParts.solo
810
+ plankSizing,
811
+ sidebarOpen,
812
+ complementarySidebarOpen
746
813
  ]);
747
- const padding = layoutMode === "deck" && overscroll === "centering" ? calculateOverscroll(layoutParts.main, plankSizing, sidebarOpen, complementarySidebarOpen) : {};
748
814
  if (layoutMode === "fullscreen") {
749
815
  return /* @__PURE__ */ React13.createElement(Fullscreen, {
750
816
  id: fullScreenSlug
@@ -761,24 +827,16 @@ var DeckLayout = ({ layoutParts, attention, toasts, flatDeck, overscroll, showHi
761
827
  context.popoverAnchorId = void 0;
762
828
  }
763
829
  }
764
- }, /* @__PURE__ */ React13.createElement(ActiveNode, {
765
- id: firstAttendedId
766
- }), /* @__PURE__ */ React13.createElement(Main3.Root, {
830
+ }, /* @__PURE__ */ React13.createElement(ActiveNode, null), /* @__PURE__ */ React13.createElement(Main3.Root, {
767
831
  navigationSidebarOpen: context.sidebarOpen,
768
832
  onNavigationSidebarOpenChange: (next) => context.sidebarOpen = next,
769
- ...complementarySidebarOpen !== null && {
770
- complementarySidebarOpen: (
771
- /* complementaryAvailable && */
772
- context.complementarySidebarOpen
773
- ),
774
- onComplementarySidebarOpenChange: (next) => context.complementarySidebarOpen = next
775
- }
833
+ complementarySidebarOpen: context.complementarySidebarOpen,
834
+ onComplementarySidebarOpenChange: (next) => context.complementarySidebarOpen = next
776
835
  }, /* @__PURE__ */ React13.createElement(Main3.Notch, {
777
836
  classNames: "z-[21]"
778
837
  }, /* @__PURE__ */ React13.createElement(Surface9, {
779
838
  role: "notch-start"
780
839
  }), /* @__PURE__ */ React13.createElement(Button3, {
781
- // disabled={!sidebarAvailable}
782
840
  onClick: () => context.sidebarOpen = !context.sidebarOpen,
783
841
  variant: "ghost",
784
842
  classNames: "p-1"
@@ -788,7 +846,6 @@ var DeckLayout = ({ layoutParts, attention, toasts, flatDeck, overscroll, showHi
788
846
  weight: "light",
789
847
  className: getSize(5)
790
848
  })), /* @__PURE__ */ React13.createElement(Button3, {
791
- // disabled={!complementaryAvailable}
792
849
  onClick: () => context.complementarySidebarOpen = !context.complementarySidebarOpen,
793
850
  variant: "ghost",
794
851
  classNames: "p-1"
@@ -801,15 +858,13 @@ var DeckLayout = ({ layoutParts, attention, toasts, flatDeck, overscroll, showHi
801
858
  })), /* @__PURE__ */ React13.createElement(Surface9, {
802
859
  role: "notch-end"
803
860
  })), /* @__PURE__ */ React13.createElement(Sidebar, {
804
- attention,
805
861
  layoutParts
806
862
  }), /* @__PURE__ */ React13.createElement(ComplementarySidebar, {
807
- id: complementarySlug,
808
- layoutParts,
863
+ panel: layoutParts.complementary?.[0].id,
809
864
  flatDeck
810
- }), /* @__PURE__ */ React13.createElement(Main3.Overlay, null), parts.length === 0 && /* @__PURE__ */ React13.createElement(Main3.Content, {
865
+ }), /* @__PURE__ */ React13.createElement(Main3.Overlay, null), isEmpty && /* @__PURE__ */ React13.createElement(Main3.Content, {
811
866
  handlesFocus: true
812
- }, /* @__PURE__ */ React13.createElement(ContentEmpty, null)), parts.length !== 0 && /* @__PURE__ */ React13.createElement(Main3.Content, {
867
+ }, /* @__PURE__ */ React13.createElement(ContentEmpty, null)), !isEmpty && /* @__PURE__ */ React13.createElement(Main3.Content, {
813
868
  bounce: true,
814
869
  classNames: "grid block-end-[--statusbar-size]",
815
870
  handlesFocus: true
@@ -820,26 +875,33 @@ var DeckLayout = ({ layoutParts, attention, toasts, flatDeck, overscroll, showHi
820
875
  style: padding,
821
876
  classNames: [
822
877
  !flatDeck && "bg-deck",
878
+ mainPaddingTransitions2,
823
879
  "absolute inset-0",
824
880
  slots?.wallpaper?.classNames
825
881
  ],
826
882
  solo: layoutMode === "solo",
827
883
  onScroll: handleScroll,
828
884
  ref: deckRef
829
- }, parts.map((layoutEntry) => /* @__PURE__ */ React13.createElement(Plank, {
885
+ }, /* @__PURE__ */ React13.createElement(Plank, {
886
+ entry: layoutParts.solo?.[0] ?? {
887
+ id: "unknown-solo"
888
+ },
889
+ layoutParts,
890
+ part: "solo",
891
+ layoutMode,
892
+ flatDeck,
893
+ searchEnabled: !!searchPlugin
894
+ }), layoutParts.main?.map((layoutEntry) => /* @__PURE__ */ React13.createElement(Plank, {
830
895
  key: layoutEntry.id,
831
896
  entry: layoutEntry,
832
897
  layoutParts,
833
- part: layoutMode === "solo" && layoutEntry.id === layoutParts.solo?.[0]?.id ? "solo" : "main",
898
+ part: "main",
834
899
  layoutMode,
835
900
  flatDeck,
836
901
  searchEnabled: !!searchPlugin
837
- }))))), /* @__PURE__ */ React13.createElement(StatusBar, null), showHintsFooter && /* @__PURE__ */ React13.createElement("div", {
838
- className: "fixed bottom-0 left-0 right-0 h-[32px] z-[1] flex justify-center"
839
- }, /* @__PURE__ */ React13.createElement(Surface9, {
840
- role: "hints",
841
- limit: 1
842
- })), /* @__PURE__ */ React13.createElement(Popover2.Portal, null, /* @__PURE__ */ React13.createElement(Popover2.Content, {
902
+ }))))), /* @__PURE__ */ React13.createElement(StatusBar, {
903
+ showHints
904
+ }), /* @__PURE__ */ React13.createElement(Popover2.Portal, null, /* @__PURE__ */ React13.createElement(Popover2.Content, {
843
905
  classNames: "z-[60]",
844
906
  onEscapeKeyDown: () => {
845
907
  context.popoverOpen = false;
@@ -908,31 +970,31 @@ var LayoutSettings = ({ settings }) => {
908
970
  key: option,
909
971
  value: option
910
972
  }, t(`settings overscroll ${option} label`)))))))), /* @__PURE__ */ React14.createElement(SettingsValue, {
911
- label: t("settings show footer label")
973
+ label: t("settings show hints label")
912
974
  }, /* @__PURE__ */ React14.createElement(Input.Switch, {
913
- checked: settings.showFooter,
914
- onCheckedChange: (checked) => settings.showFooter = !!checked
975
+ checked: settings.showHints,
976
+ onCheckedChange: (checked) => settings.showHints = checked
915
977
  })), !isSocket && /* @__PURE__ */ React14.createElement(SettingsValue, {
916
978
  label: t("settings native redirect label")
917
979
  }, /* @__PURE__ */ React14.createElement(Input.Switch, {
918
980
  checked: settings.enableNativeRedirect,
919
- onCheckedChange: (checked) => settings.enableNativeRedirect = !!checked
981
+ onCheckedChange: (checked) => settings.enableNativeRedirect = checked
920
982
  })), /* @__PURE__ */ React14.createElement(SettingsValue, {
921
983
  label: t("settings custom slots")
922
984
  }, /* @__PURE__ */ React14.createElement(Input.Switch, {
923
985
  checked: settings.customSlots,
924
- onCheckedChange: (checked) => settings.customSlots = !!checked
986
+ onCheckedChange: (checked) => settings.customSlots = checked
925
987
  })), /* @__PURE__ */ React14.createElement(SettingsValue, {
926
988
  label: t("settings flat deck")
927
989
  }, /* @__PURE__ */ React14.createElement(Input.Switch, {
928
990
  checked: settings.flatDeck,
929
- onCheckedChange: (checked) => settings.flatDeck = !!checked
991
+ onCheckedChange: (checked) => settings.flatDeck = checked
930
992
  })));
931
993
  };
932
994
 
933
995
  // packages/plugins/plugin-deck/src/layout.ts
934
996
  import { produce } from "immer";
935
- import { SLUG_ENTRY_SEPARATOR, SLUG_KEY_VALUE_SEPARATOR, SLUG_LIST_SEPARATOR, SLUG_PATH_SEPARATOR as SLUG_PATH_SEPARATOR4 } from "@dxos/app-framework";
997
+ import { SLUG_ENTRY_SEPARATOR, SLUG_KEY_VALUE_SEPARATOR, SLUG_LIST_SEPARATOR, SLUG_PATH_SEPARATOR as SLUG_PATH_SEPARATOR3 } from "@dxos/app-framework";
936
998
  var partsThatSupportIncrement = [
937
999
  "main"
938
1000
  ];
@@ -1045,7 +1107,7 @@ var mergeLayoutParts = (...layoutParts) => {
1045
1107
  }), {});
1046
1108
  };
1047
1109
  var parseLayoutEntry = (itemString) => {
1048
- const [id, path] = itemString.split(SLUG_PATH_SEPARATOR4);
1110
+ const [id, path] = itemString.split(SLUG_PATH_SEPARATOR3);
1049
1111
  const entry = {
1050
1112
  id
1051
1113
  };
@@ -1072,7 +1134,7 @@ var soloPartToUri = (layout) => {
1072
1134
  return "";
1073
1135
  }
1074
1136
  const entry = soloPart[0];
1075
- return `${entry.id}${entry.path ? SLUG_PATH_SEPARATOR4 + entry.path : ""}`;
1137
+ return `${entry.id}${entry.path ? SLUG_PATH_SEPARATOR3 + entry.path : ""}`;
1076
1138
  };
1077
1139
 
1078
1140
  // packages/plugins/plugin-deck/src/translations.ts
@@ -1083,12 +1145,11 @@ var translations_default = [
1083
1145
  "main header label": "Main header",
1084
1146
  "open navigation sidebar label": "Open navigation sidebar.",
1085
1147
  "open complementary sidebar label": "Open complementary sidebar.",
1086
- "open settings label": "Show settings",
1087
1148
  "plugin error message": "Content failed to render.",
1088
1149
  "content fallback message": "Unsupported",
1089
1150
  "content fallback description": "No plugin had a response for the address you navigated\xA0to. Double-check the URL, and ensure you\u2019ve enabled a plugin that supports the\xA0object.",
1090
1151
  "toggle fullscreen label": "Toggle fullscreen",
1091
- "settings show footer label": "Show footer (experimental)",
1152
+ "settings show hints label": "Show hints",
1092
1153
  "settings native redirect label": "Enable native url redirect (experimental)",
1093
1154
  "settings custom slots": "Theme option (experimental)",
1094
1155
  "settings new plank position start label": "Start",
@@ -1099,7 +1160,6 @@ var translations_default = [
1099
1160
  "undo action label": "Undo",
1100
1161
  "undo action alt": "Undo previous action",
1101
1162
  "undo close label": "Dismiss",
1102
- "open comments label": "Open comments",
1103
1163
  "error fallback message": "Unable to open this item",
1104
1164
  "plank heading fallback label": "Untitled",
1105
1165
  "actions menu label": "Options",
@@ -1112,7 +1172,12 @@ var translations_default = [
1112
1172
  "select overscroll placeholder": "Select plank overscrolling behavior",
1113
1173
  "settings overscroll centering label": "Centering",
1114
1174
  "settings overscroll none label": "None",
1115
- "settings flat deck": "Flatten deck appearance"
1175
+ "settings flat deck": "Flatten deck appearance",
1176
+ // ComplementarySidebar
1177
+ "open settings label": "Show settings",
1178
+ "open comments label": "Show Comments",
1179
+ "open automation label": "Show Automation",
1180
+ "open debug label": "Show Debug"
1116
1181
  }
1117
1182
  }
1118
1183
  }
@@ -1142,7 +1207,7 @@ var DeckPlugin = ({ observability } = {}) => {
1142
1207
  let currentUndoId;
1143
1208
  let handleNavigation;
1144
1209
  const settings = new LocalStorageStore("dxos.org/settings/layout", {
1145
- showFooter: false,
1210
+ showHints: false,
1146
1211
  customSlots: false,
1147
1212
  flatDeck: false,
1148
1213
  enableNativeRedirect: false,
@@ -1227,6 +1292,22 @@ var DeckPlugin = ({ observability } = {}) => {
1227
1292
  }
1228
1293
  }
1229
1294
  };
1295
+ const handleSetLocation = (next) => {
1296
+ if (attentionPlugin) {
1297
+ const attended = attentionPlugin.provides.attention.attended;
1298
+ const [attendedId] = Array.from(attended);
1299
+ const ids = (layout.values.layoutMode === "deck" ? next.main : next.solo)?.map(({ id }) => id) ?? [];
1300
+ const isAttendedAvailable = !!attendedId && ids.includes(attendedId);
1301
+ if (!isAttendedAvailable) {
1302
+ requestAnimationFrame(() => {
1303
+ const nextAttended = layout.values.layoutMode === "solo" ? next.solo?.[0].id : next.main?.[0]?.id;
1304
+ const article = document.querySelector(`article[data-attendable-id="${nextAttended}"]`);
1305
+ article?.focus();
1306
+ });
1307
+ }
1308
+ }
1309
+ location.values.active = next;
1310
+ };
1230
1311
  return {
1231
1312
  meta: meta_default,
1232
1313
  ready: async (plugins) => {
@@ -1267,8 +1348,8 @@ var DeckPlugin = ({ observability } = {}) => {
1267
1348
  deck.expunge();
1268
1349
  }));
1269
1350
  settings.prop({
1270
- key: "showFooter",
1271
- storageKey: "show-footer",
1351
+ key: "showHints",
1352
+ storageKey: "show-hints",
1272
1353
  type: LocalStorageStore.bool()
1273
1354
  }).prop({
1274
1355
  key: "customSlots",
@@ -1301,13 +1382,13 @@ var DeckPlugin = ({ observability } = {}) => {
1301
1382
  handleNavigation = async () => {
1302
1383
  const pathname = window.location.pathname;
1303
1384
  if (pathname === "/reset") {
1304
- location.values.active = {
1385
+ handleSetLocation({
1305
1386
  sidebar: [
1306
1387
  {
1307
1388
  id: NAV_ID
1308
1389
  }
1309
1390
  ]
1310
- };
1391
+ });
1311
1392
  location.values.closed = [];
1312
1393
  layout.values.layoutMode = "solo";
1313
1394
  window.location.pathname = "/";
@@ -1318,26 +1399,16 @@ var DeckPlugin = ({ observability } = {}) => {
1318
1399
  return;
1319
1400
  }
1320
1401
  const startingLayout = removePart(location.values.active, "solo");
1321
- location.values.active = mergeLayoutParts(layoutFromUri, startingLayout);
1402
+ handleSetLocation(mergeLayoutParts(layoutFromUri, startingLayout));
1322
1403
  layout.values.layoutMode = "solo";
1323
1404
  };
1324
1405
  await handleNavigation();
1325
1406
  window.addEventListener("popstate", handleNavigation);
1326
- unsubscriptionCallbacks.push(effect(() => {
1327
- const selectedPath = soloPartToUri(location.values.active);
1407
+ unsubscriptionCallbacks.push(scheduledEffect(() => ({
1408
+ selectedPath: soloPartToUri(location.values.active)
1409
+ }), ({ selectedPath }) => {
1328
1410
  history.pushState(null, "", `/${selectedPath}${window.location.search}`);
1329
1411
  }));
1330
- unsubscriptionCallbacks.push(effect(() => {
1331
- const soloId = location.values.active.solo?.[0].id;
1332
- if (layout.values.layoutMode === "solo" && soloId && layout.values.scrollIntoView !== soloId) {
1333
- void intentPlugin?.provides.intent.dispatch({
1334
- action: LayoutAction3.SCROLL_INTO_VIEW,
1335
- data: {
1336
- id: soloId
1337
- }
1338
- });
1339
- }
1340
- }));
1341
1412
  layoutModeHistory.values.push(`${layout.values.layoutMode}`);
1342
1413
  },
1343
1414
  unload: async () => {
@@ -1380,8 +1451,7 @@ var DeckPlugin = ({ observability } = {}) => {
1380
1451
  ns: DECK_PLUGIN
1381
1452
  }
1382
1453
  ],
1383
- icon: (props) => /* @__PURE__ */ React15.createElement(ArrowsOut, props),
1384
- iconSymbol: "ph--arrows-out--regular",
1454
+ icon: "ph--arrows-out--regular",
1385
1455
  keyBinding: {
1386
1456
  macos: "ctrl+meta+f",
1387
1457
  windows: "shift+ctrl+f"
@@ -1398,12 +1468,9 @@ var DeckPlugin = ({ observability } = {}) => {
1398
1468
  value: deck.values
1399
1469
  }, props.children)),
1400
1470
  root: () => {
1401
- return /* @__PURE__ */ React15.createElement(Mosaic.Root, null, /* @__PURE__ */ React15.createElement(DeckLayout, {
1402
- attention: attentionPlugin?.provides.attention ?? {
1403
- attended: /* @__PURE__ */ new Set()
1404
- },
1471
+ return /* @__PURE__ */ React15.createElement(DeckLayout, {
1405
1472
  layoutParts: location.values.active,
1406
- showHintsFooter: settings.values.showFooter,
1473
+ showHints: settings.values.showHints,
1407
1474
  overscroll: settings.values.overscroll,
1408
1475
  flatDeck: settings.values.flatDeck,
1409
1476
  slots: settings.values.customSlots ? customSlots : void 0,
@@ -1419,7 +1486,7 @@ var DeckPlugin = ({ observability } = {}) => {
1419
1486
  }, 1e3);
1420
1487
  }
1421
1488
  }
1422
- }), /* @__PURE__ */ React15.createElement(Mosaic.DragOverlay, null));
1489
+ });
1423
1490
  },
1424
1491
  surface: {
1425
1492
  component: ({ data, role }) => {
@@ -1455,7 +1522,7 @@ var DeckPlugin = ({ observability } = {}) => {
1455
1522
  } else {
1456
1523
  log.warn("Invalid layout mode", intent?.data?.layoutMode, {
1457
1524
  F: __dxlog_file,
1458
- L: 390,
1525
+ L: 404,
1459
1526
  S: void 0,
1460
1527
  C: (f, a) => f(...a)
1461
1528
  });
@@ -1501,7 +1568,7 @@ var DeckPlugin = ({ observability } = {}) => {
1501
1568
  data: true
1502
1569
  };
1503
1570
  }
1504
- case NavigationAction3.OPEN: {
1571
+ case NavigationAction4.OPEN: {
1505
1572
  const previouslyOpenIds = new Set(openIds2(location.values.active));
1506
1573
  const layoutMode = layout.values.layoutMode;
1507
1574
  batch(() => {
@@ -1510,7 +1577,7 @@ var DeckPlugin = ({ observability } = {}) => {
1510
1577
  }
1511
1578
  const processLayoutEntry = (partName, entryString, currentLayout) => {
1512
1579
  const toggle = true;
1513
- const [id, path] = entryString.split(SLUG_PATH_SEPARATOR5);
1580
+ const [id, path] = entryString.split(SLUG_PATH_SEPARATOR4);
1514
1581
  const layoutEntry = {
1515
1582
  id,
1516
1583
  ...path ? {
@@ -1539,7 +1606,7 @@ var DeckPlugin = ({ observability } = {}) => {
1539
1606
  newLayout = processLayoutEntry(partName, layoutEntries, newLayout);
1540
1607
  }
1541
1608
  });
1542
- location.values.active = newLayout;
1609
+ handleSetLocation(newLayout);
1543
1610
  });
1544
1611
  const ids = openIds2(location.values.active);
1545
1612
  const newlyOpen = ids.filter((i) => !previouslyOpenIds.has(i));
@@ -1558,7 +1625,7 @@ var DeckPlugin = ({ observability } = {}) => {
1558
1625
  ] : [],
1559
1626
  intent.data?.object ? [
1560
1627
  {
1561
- action: NavigationAction3.EXPOSE,
1628
+ action: NavigationAction4.EXPOSE,
1562
1629
  data: {
1563
1630
  id: fullyQualifiedId(intent.data.object)
1564
1631
  }
@@ -1581,16 +1648,16 @@ var DeckPlugin = ({ observability } = {}) => {
1581
1648
  ]
1582
1649
  };
1583
1650
  }
1584
- case NavigationAction3.ADD_TO_ACTIVE: {
1651
+ case NavigationAction4.ADD_TO_ACTIVE: {
1585
1652
  const data = intent.data;
1586
1653
  const layoutEntry = {
1587
1654
  id: data.id
1588
1655
  };
1589
1656
  const effectivePart = getEffectivePart(data.part, layout.values.layoutMode);
1590
- location.values.active = openEntry(location.values.active, effectivePart, layoutEntry, {
1657
+ handleSetLocation(openEntry(location.values.active, effectivePart, layoutEntry, {
1591
1658
  positioning: data.positioning ?? settings.values.newPlankPositioning,
1592
1659
  pivotId: data.pivotId
1593
- });
1660
+ }));
1594
1661
  const intents = [];
1595
1662
  if (data.scrollIntoView && layout.values.layoutMode === "deck") {
1596
1663
  intents.push([
@@ -1607,7 +1674,7 @@ var DeckPlugin = ({ observability } = {}) => {
1607
1674
  intents
1608
1675
  };
1609
1676
  }
1610
- case NavigationAction3.CLOSE: {
1677
+ case NavigationAction4.CLOSE: {
1611
1678
  return batch(() => {
1612
1679
  if (!intent.data) {
1613
1680
  return;
@@ -1632,32 +1699,32 @@ var DeckPlugin = ({ observability } = {}) => {
1632
1699
  });
1633
1700
  }
1634
1701
  });
1635
- location.values.active = newLayout;
1702
+ handleSetLocation(newLayout);
1636
1703
  return {
1637
1704
  data: true
1638
1705
  };
1639
1706
  });
1640
1707
  }
1641
1708
  // TODO(wittjosiah): Factor out.
1642
- case NavigationAction3.SET: {
1709
+ case NavigationAction4.SET: {
1643
1710
  return batch(() => {
1644
1711
  if (isLayoutParts(intent.data?.activeParts)) {
1645
- location.values.active = intent.data.activeParts;
1712
+ handleSetLocation(intent.data.activeParts);
1646
1713
  }
1647
1714
  return {
1648
1715
  data: true
1649
1716
  };
1650
1717
  });
1651
1718
  }
1652
- case NavigationAction3.ADJUST: {
1719
+ case NavigationAction4.ADJUST: {
1653
1720
  return batch(() => {
1654
1721
  if (isLayoutAdjustment(intent.data)) {
1655
1722
  const adjustment = intent.data;
1656
1723
  if (adjustment.type === "increment-end" || adjustment.type === "increment-start") {
1657
- location.values.active = incrementPlank(location.values.active, {
1724
+ handleSetLocation(incrementPlank(location.values.active, {
1658
1725
  type: adjustment.type,
1659
1726
  layoutCoordinate: adjustment.layoutCoordinate
1660
- });
1727
+ }));
1661
1728
  }
1662
1729
  if (adjustment.type === "solo") {
1663
1730
  const entryId = adjustment.layoutCoordinate.entryId;
@@ -1673,7 +1740,7 @@ var DeckPlugin = ({ observability } = {}) => {
1673
1740
  }
1674
1741
  },
1675
1742
  {
1676
- action: NavigationAction3.OPEN,
1743
+ action: NavigationAction4.OPEN,
1677
1744
  data: {
1678
1745
  activeParts: {
1679
1746
  solo: [
@@ -1697,7 +1764,7 @@ var DeckPlugin = ({ observability } = {}) => {
1697
1764
  }
1698
1765
  },
1699
1766
  {
1700
- action: NavigationAction3.CLOSE,
1767
+ action: NavigationAction4.CLOSE,
1701
1768
  data: {
1702
1769
  activeParts: {
1703
1770
  solo: [
@@ -1707,7 +1774,7 @@ var DeckPlugin = ({ observability } = {}) => {
1707
1774
  }
1708
1775
  },
1709
1776
  {
1710
- action: NavigationAction3.OPEN,
1777
+ action: NavigationAction4.OPEN,
1711
1778
  data: {
1712
1779
  noToggle: true,
1713
1780
  activeParts: {