@dxos/plugin-deck 0.6.11 → 0.6.12-main.2d19bf1

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 (40) 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 +220 -148
  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/ComplementarySidebar.d.ts +2 -2
  9. package/dist/types/src/components/DeckLayout/ComplementarySidebar.d.ts.map +1 -1
  10. package/dist/types/src/components/DeckLayout/DeckLayout.d.ts +3 -4
  11. package/dist/types/src/components/DeckLayout/DeckLayout.d.ts.map +1 -1
  12. package/dist/types/src/components/DeckLayout/NodePlankHeading.d.ts +4 -3
  13. package/dist/types/src/components/DeckLayout/NodePlankHeading.d.ts.map +1 -1
  14. package/dist/types/src/components/DeckLayout/Sidebar.d.ts +2 -3
  15. package/dist/types/src/components/DeckLayout/Sidebar.d.ts.map +1 -1
  16. package/dist/types/src/components/DeckLayout/StatusBar.d.ts +3 -1
  17. package/dist/types/src/components/DeckLayout/StatusBar.d.ts.map +1 -1
  18. package/dist/types/src/components/LayoutSettings.d.ts.map +1 -1
  19. package/dist/types/src/hooks/useNode.d.ts.map +1 -1
  20. package/dist/types/src/layout.d.ts.map +1 -1
  21. package/dist/types/src/meta.d.ts.map +1 -1
  22. package/dist/types/src/translations.d.ts +3 -1
  23. package/dist/types/src/translations.d.ts.map +1 -1
  24. package/dist/types/src/types.d.ts +1 -1
  25. package/dist/types/src/types.d.ts.map +1 -1
  26. package/package.json +29 -29
  27. package/src/DeckPlugin.tsx +81 -53
  28. package/src/components/DeckLayout/ComplementarySidebar.tsx +73 -22
  29. package/src/components/DeckLayout/DeckLayout.tsx +42 -60
  30. package/src/components/DeckLayout/NodePlankHeading.tsx +15 -15
  31. package/src/components/DeckLayout/Plank.tsx +2 -2
  32. package/src/components/DeckLayout/Sidebar.tsx +6 -5
  33. package/src/components/DeckLayout/StatusBar.tsx +10 -2
  34. package/src/components/LayoutSettings.tsx +5 -8
  35. package/src/hooks/useNode.ts +5 -1
  36. package/src/layout.ts +1 -0
  37. package/src/meta.ts +3 -1
  38. package/src/translations.ts +3 -1
  39. package/src/types.ts +1 -1
  40. package/dist/lib/browser/chunk-YVHGFQQR.mjs.map +0 -7
@@ -1,14 +1,13 @@
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
7
  import { batch, effect } 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";
13
12
  import { LocalStorageStore } from "@dxos/local-storage";
14
13
  import { log } from "@dxos/log";
@@ -18,7 +17,6 @@ import { createExtension } from "@dxos/plugin-graph";
18
17
  import { ObservabilityAction } from "@dxos/plugin-observability/meta";
19
18
  import { fullyQualifiedId } from "@dxos/react-client/echo";
20
19
  import { translations as deckTranslations } from "@dxos/react-ui-deck";
21
- import { Mosaic } from "@dxos/react-ui-mosaic";
22
20
 
23
21
  // packages/plugins/plugin-deck/src/components/DeckLayout/constants.ts
24
22
  var NAV_ID = "NavTree";
@@ -26,9 +24,10 @@ var SURFACE_PREFIX = "surface:";
26
24
 
27
25
  // packages/plugins/plugin-deck/src/components/DeckLayout/DeckLayout.tsx
28
26
  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";
27
+ import React13, { useCallback as useCallback2, useEffect as useEffect5, useMemo as useMemo3, useRef as useRef2 } from "react";
28
+ import { Surface as Surface9, firstIdInPart, usePlugin } from "@dxos/app-framework";
29
+ import { Button as Button3, Dialog, Main as Main3, Popover as Popover2, useOnTransition, useTranslation as useTranslation5 } from "@dxos/react-ui";
30
+ import { useAttended as useAttended3 } from "@dxos/react-ui-attention";
32
31
  import { Deck } from "@dxos/react-ui-deck";
33
32
  import { getSize } from "@dxos/react-ui-theme";
34
33
 
@@ -40,8 +39,11 @@ import { useGraph } from "@dxos/plugin-graph";
40
39
  // packages/plugins/plugin-deck/src/hooks/useNode.ts
41
40
  import { useEffect, useState } from "react";
42
41
  var useNode = (graph, id, timeout) => {
43
- const [nodeState, setNodeState] = useState(id ? graph.findNode(id) : void 0);
42
+ const [nodeState, setNodeState] = useState(id ? graph.findNode(id, false) : void 0);
44
43
  useEffect(() => {
44
+ if (!id && nodeState) {
45
+ setNodeState(void 0);
46
+ }
45
47
  if (nodeState?.id === id || !id) {
46
48
  return;
47
49
  }
@@ -113,36 +115,25 @@ var ActiveNode = ({ id }) => {
113
115
  };
114
116
 
115
117
  // 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";
118
+ import React5, { useMemo } from "react";
119
+ import { NavigationAction as NavigationAction2, SLUG_PATH_SEPARATOR as SLUG_PATH_SEPARATOR2, Surface as Surface3, useIntentDispatcher as useIntentDispatcher2 } from "@dxos/app-framework";
118
120
  import { useGraph as useGraph3 } from "@dxos/plugin-graph";
119
121
  import { Main } from "@dxos/react-ui";
120
- import { createAttendableAttributes } from "@dxos/react-ui-attention";
122
+ import { useAttended } from "@dxos/react-ui-attention";
121
123
  import { deckGrid } from "@dxos/react-ui-deck";
122
124
  import { mx as mx2 } from "@dxos/react-ui-theme";
123
125
 
124
126
  // packages/plugins/plugin-deck/src/components/DeckLayout/NodePlankHeading.tsx
125
- import { Placeholder } from "@phosphor-icons/react";
126
127
  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";
128
+ import { LayoutAction, NavigationAction, SLUG_PATH_SEPARATOR, Surface as Surface2, useIntentDispatcher, indexInPart, partLength } from "@dxos/app-framework";
128
129
  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";
130
+ import { Icon, Popover, toLocalizedString, useMediaQuery, useTranslation } from "@dxos/react-ui";
131
+ import { PlankHeading } from "@dxos/react-ui-deck";
131
132
  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
- }) => {
133
+ var NodePlankHeading = ({ node, id, layoutParts, layoutPart, popoverAnchorId, pending, flatDeck, actions = [] }) => {
143
134
  const { t } = useTranslation(DECK_PLUGIN);
144
135
  const { graph } = useGraph2();
145
- const Icon = node?.properties?.icon ?? Placeholder;
136
+ const icon = node?.properties?.icon ?? "ph--placeholder--regular";
146
137
  const label = pending ? t("pending heading") : toLocalizedString(node?.properties?.label ?? [
147
138
  "plank heading fallback label",
148
139
  {
@@ -172,10 +163,14 @@ var NodePlankHeading = ({
172
163
  return /* @__PURE__ */ React2.createElement(PlankHeading.Root, (layoutPart !== "main" || !flatDeck) && {
173
164
  classNames: "pie-1 border-b border-separator"
174
165
  }, /* @__PURE__ */ React2.createElement(ActionRoot, null, node ? /* @__PURE__ */ React2.createElement(PlankHeading.ActionsMenu, {
175
- Icon,
166
+ icon,
167
+ related: layoutPart === "complementary",
176
168
  attendableId,
177
169
  triggerLabel: t("actions menu label"),
178
- actions: graph.actions(node),
170
+ actions: [
171
+ actions,
172
+ graph.actions(node)
173
+ ].filter((a) => a.length > 0),
179
174
  onAction: (action) => typeof action.data === "function" && action.data?.({
180
175
  node: action,
181
176
  caller: DECK_PLUGIN
@@ -187,11 +182,15 @@ var NodePlankHeading = ({
187
182
  }
188
183
  })) : /* @__PURE__ */ React2.createElement(PlankHeading.Button, null, /* @__PURE__ */ React2.createElement("span", {
189
184
  className: "sr-only"
190
- }, label), /* @__PURE__ */ React2.createElement(Icon, plankHeadingIconProps))), /* @__PURE__ */ React2.createElement(TextTooltip, {
185
+ }, label), /* @__PURE__ */ React2.createElement(Icon, {
186
+ icon,
187
+ size: 5
188
+ }))), /* @__PURE__ */ React2.createElement(TextTooltip, {
191
189
  text: label,
192
190
  onlyWhenTruncating: true
193
191
  }, /* @__PURE__ */ React2.createElement(PlankHeading.Label, {
194
- attendableId: node?.id,
192
+ attendableId,
193
+ related: layoutPart === "complementary",
195
194
  ...pending && {
196
195
  classNames: "text-description"
197
196
  }
@@ -237,9 +236,6 @@ var NodePlankHeading = ({
237
236
  action: NavigationAction.CLOSE,
238
237
  data: {
239
238
  activeParts: {
240
- complementary: [
241
- `${id}${SLUG_PATH_SEPARATOR}comments${SLUG_COLLECTION_INDICATOR}`
242
- ],
243
239
  [layoutPart]: [
244
240
  id
245
241
  ]
@@ -253,7 +249,7 @@ var NodePlankHeading = ({
253
249
  }
254
250
  });
255
251
  },
256
- close: layoutCoordinate?.part === "complementary" ? "minify-end" : true
252
+ close: layoutPart === "complementary" ? "minify-end" : true
257
253
  }));
258
254
  };
259
255
 
@@ -314,13 +310,79 @@ var LayoutContext = createContext(null);
314
310
  var useLayout = () => useContext(LayoutContext) ?? raise(new Error("Missing LayoutContext"));
315
311
 
316
312
  // packages/plugins/plugin-deck/src/components/DeckLayout/ComplementarySidebar.tsx
317
- var ComplementarySidebar = ({ id, layoutParts, flatDeck }) => {
313
+ var panels = [
314
+ "comments",
315
+ "settings"
316
+ ];
317
+ var getPanel = (part) => {
318
+ if (part && panels.findIndex((panel) => panel === part) !== -1) {
319
+ return part;
320
+ } else {
321
+ return "settings";
322
+ }
323
+ };
324
+ var ComplementarySidebar = ({ layoutParts, flatDeck }) => {
318
325
  const { popoverAnchorId } = useLayout();
326
+ const attended = useAttended();
327
+ const part = getPanel(layoutParts.complementary?.[0].id);
328
+ const id = attended[0] ? `${attended[0]}${SLUG_PATH_SEPARATOR2}${part}` : void 0;
319
329
  const { graph } = useGraph3();
320
330
  const node = useNode(graph, id);
321
- const complementaryAttrs = createAttendableAttributes(id?.split(SLUG_PATH_SEPARATOR2)[0] ?? "never");
331
+ const dispatch = useIntentDispatcher2();
322
332
  useNodeActionExpander(node);
323
- return /* @__PURE__ */ React5.createElement(Main.ComplementarySidebar, complementaryAttrs, node ? /* @__PURE__ */ React5.createElement("div", {
333
+ const actions = useMemo(() => [
334
+ {
335
+ id: "complementary-settings",
336
+ data: () => {
337
+ void dispatch({
338
+ action: NavigationAction2.OPEN,
339
+ data: {
340
+ activeParts: {
341
+ complementary: "settings"
342
+ }
343
+ }
344
+ });
345
+ },
346
+ properties: {
347
+ label: [
348
+ "settings label",
349
+ {
350
+ ns: DECK_PLUGIN
351
+ }
352
+ ],
353
+ icon: "ph--gear--regular",
354
+ menuItemType: "toggle",
355
+ isChecked: part === "settings"
356
+ }
357
+ },
358
+ {
359
+ id: "complementary-comments",
360
+ data: () => {
361
+ void dispatch({
362
+ action: NavigationAction2.OPEN,
363
+ data: {
364
+ activeParts: {
365
+ complementary: "comments"
366
+ }
367
+ }
368
+ });
369
+ },
370
+ properties: {
371
+ label: [
372
+ "comments label",
373
+ {
374
+ ns: DECK_PLUGIN
375
+ }
376
+ ],
377
+ icon: "ph--chat-text--regular",
378
+ menuItemType: "toggle",
379
+ isChecked: part === "comments"
380
+ }
381
+ }
382
+ ], [
383
+ part
384
+ ]);
385
+ return /* @__PURE__ */ React5.createElement(Main.ComplementarySidebar, null, /* @__PURE__ */ React5.createElement("div", {
324
386
  role: "none",
325
387
  className: mx2(deckGrid, "grid-cols-1 bs-full")
326
388
  }, /* @__PURE__ */ React5.createElement(NodePlankHeading, {
@@ -329,18 +391,18 @@ var ComplementarySidebar = ({ id, layoutParts, flatDeck }) => {
329
391
  layoutParts,
330
392
  layoutPart: "complementary",
331
393
  popoverAnchorId,
332
- flatDeck
333
- }), /* @__PURE__ */ React5.createElement(Surface3, {
334
- role: "article",
394
+ flatDeck,
395
+ actions
396
+ }), node && /* @__PURE__ */ React5.createElement(Surface3, {
397
+ role: `complementary--${part}`,
335
398
  data: {
336
- subject: node.data,
337
- part: "complementary",
399
+ subject: node.properties.object,
338
400
  popoverAnchorId
339
401
  },
340
402
  limit: 1,
341
403
  fallback: PlankContentError,
342
404
  placeholder: /* @__PURE__ */ React5.createElement(PlankLoading, null)
343
- })) : null);
405
+ })));
344
406
  };
345
407
 
346
408
  // packages/plugins/plugin-deck/src/components/DeckLayout/ContentEmpty.tsx
@@ -401,11 +463,11 @@ var Fullscreen = ({ id }) => {
401
463
  // packages/plugins/plugin-deck/src/components/DeckLayout/Plank.tsx
402
464
  import { Plus } from "@phosphor-icons/react";
403
465
  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";
466
+ import { LayoutAction as LayoutAction2, NavigationAction as NavigationAction3, Surface as Surface6, useIntentDispatcher as useIntentDispatcher3 } from "@dxos/app-framework";
405
467
  import { debounce } from "@dxos/async";
406
468
  import { useGraph as useGraph5 } from "@dxos/plugin-graph";
407
469
  import { Button, Tooltip, useTranslation as useTranslation4 } from "@dxos/react-ui";
408
- import { createAttendableAttributes as createAttendableAttributes2 } from "@dxos/react-ui-attention";
470
+ import { useAttendableAttributes } from "@dxos/react-ui-attention";
409
471
  import { Plank as NaturalPlank } from "@dxos/react-ui-deck";
410
472
  import { mainIntrinsicSize } from "@dxos/react-ui-theme";
411
473
 
@@ -418,14 +480,14 @@ var useDeckContext = () => useContext2(DeckContext) ?? raise2(new Error("Missing
418
480
  // packages/plugins/plugin-deck/src/components/DeckLayout/Plank.tsx
419
481
  var Plank = ({ entry, layoutParts, part, flatDeck, searchEnabled, layoutMode }) => {
420
482
  const { t } = useTranslation4(DECK_PLUGIN);
421
- const dispatch = useIntentDispatcher2();
483
+ const dispatch = useIntentDispatcher3();
422
484
  const { popoverAnchorId, scrollIntoView } = useLayout();
423
485
  const { plankSizing } = useDeckContext();
424
486
  const { graph } = useGraph5();
425
487
  const node = useNode(graph, entry.id);
426
488
  const rootElement = useRef(null);
427
489
  const resizeable = layoutMode === "deck";
428
- const attendableAttrs = createAttendableAttributes2(entry.id);
490
+ const attendableAttrs = useAttendableAttributes(entry.id);
429
491
  const coordinate = {
430
492
  part,
431
493
  entryId: entry.id
@@ -529,7 +591,7 @@ var Plank = ({ entry, layoutParts, part, flatDeck, searchEnabled, layoutMode })
529
591
  component: "dxos.org/plugin/search/Dialog",
530
592
  dialogBlockAlign: "start",
531
593
  subject: {
532
- action: NavigationAction2.SET,
594
+ action: NavigationAction3.SET,
533
595
  position: "add-after",
534
596
  coordinate
535
597
  }
@@ -549,12 +611,14 @@ var Plank = ({ entry, layoutParts, part, flatDeck, searchEnabled, layoutMode })
549
611
  };
550
612
 
551
613
  // packages/plugins/plugin-deck/src/components/DeckLayout/Sidebar.tsx
552
- import React10, { useMemo } from "react";
614
+ import React10, { useMemo as useMemo2 } from "react";
553
615
  import { openIds, Surface as Surface7 } from "@dxos/app-framework";
554
616
  import { Main as Main2 } from "@dxos/react-ui";
555
- var Sidebar = ({ attention, layoutParts }) => {
617
+ import { useAttended as useAttended2 } from "@dxos/react-ui-attention";
618
+ var Sidebar = ({ layoutParts }) => {
556
619
  const { layoutMode, popoverAnchorId } = useLayout();
557
- const activeIds = useMemo(() => {
620
+ const attended = useAttended2();
621
+ const activeIds = useMemo2(() => {
558
622
  if (layoutMode === "solo") {
559
623
  return new Set(layoutParts?.solo?.map((e) => e.id) ?? []);
560
624
  } else if (layoutMode === "deck") {
@@ -565,14 +629,14 @@ var Sidebar = ({ attention, layoutParts }) => {
565
629
  layoutParts,
566
630
  layoutMode
567
631
  ]);
568
- const navigationData = useMemo(() => ({
632
+ const navigationData = useMemo2(() => ({
569
633
  popoverAnchorId,
570
634
  activeIds,
571
- attended: attention.attended
635
+ attended
572
636
  }), [
573
637
  popoverAnchorId,
574
638
  activeIds,
575
- attention.attended
639
+ attended
576
640
  ]);
577
641
  return /* @__PURE__ */ React10.createElement(Main2.NavigationSidebar, null, /* @__PURE__ */ React10.createElement(Surface7, {
578
642
  role: "navigation",
@@ -587,13 +651,18 @@ var Sidebar = ({ attention, layoutParts }) => {
587
651
  import React11 from "react";
588
652
  import { Surface as Surface8 } from "@dxos/app-framework";
589
653
  import { mainPadding, mx as mx4 } from "@dxos/react-ui-theme";
590
- var StatusBar = () => {
654
+ var StatusBar = ({ showHints }) => {
591
655
  const sizeAttrs = useMainSize();
592
656
  return /* @__PURE__ */ React11.createElement("div", {
593
657
  role: "none",
594
658
  ...sizeAttrs,
595
- className: mx4("fixed block-end-0 inset-inline-0 z-[2]", mainPadding)
596
- }, /* @__PURE__ */ React11.createElement(Surface8, {
659
+ className: mx4("fixed flex justify-between block-end-0 inset-inline-0 items-center border-bs border-separator z-[2]", mainPadding)
660
+ }, /* @__PURE__ */ React11.createElement("div", {
661
+ role: "none"
662
+ }, showHints && /* @__PURE__ */ React11.createElement(Surface8, {
663
+ role: "hints",
664
+ limit: 1
665
+ })), /* @__PURE__ */ React11.createElement(Surface8, {
597
666
  role: "status-bar",
598
667
  limit: 1
599
668
  }));
@@ -672,20 +741,26 @@ var calculateOverscroll = (planks, plankSizing, sidebarOpen, complementarySideba
672
741
  };
673
742
 
674
743
  // packages/plugins/plugin-deck/src/components/DeckLayout/DeckLayout.tsx
675
- var DeckLayout = ({ layoutParts, attention, toasts, flatDeck, overscroll, showHintsFooter, slots, onDismissToast }) => {
744
+ var DeckLayout = ({ layoutParts, toasts, flatDeck, overscroll, showHints, slots, onDismissToast }) => {
676
745
  const context = useLayout();
677
746
  const { layoutMode, sidebarOpen, complementarySidebarOpen, dialogOpen, dialogContent, dialogBlockAlign, popoverOpen, popoverContent, popoverAnchorId } = context;
678
747
  const { t } = useTranslation5(DECK_PLUGIN);
679
748
  const { plankSizing } = useDeckContext();
749
+ const attended = useAttended3();
680
750
  const searchPlugin = usePlugin("dxos.org/plugin/search");
681
- const fullScreenSlug = useMemo2(() => firstIdInPart(layoutParts, "fullScreen"), [
751
+ const fullScreenSlug = useMemo3(() => firstIdInPart(layoutParts, "fullScreen"), [
682
752
  layoutParts
683
753
  ]);
684
- const [scrollLeft, setScrollLeft] = useState3(null);
754
+ const scrollLeftRef = useRef2();
685
755
  const deckRef = useRef2(null);
686
- const restoreScrollRef = useRef2(false);
756
+ useEffect5(() => {
757
+ const firstId = layoutMode === "solo" ? firstIdInPart(layoutParts, "solo") : firstIdInPart(layoutParts, "main");
758
+ if (attended.length === 0 && firstId) {
759
+ document.querySelector(`article[data-attendable-id="${firstId}"] button`)?.focus();
760
+ }
761
+ }, []);
687
762
  const handleResize = useCallback2(() => {
688
- setScrollLeft(null);
763
+ scrollLeftRef.current = null;
689
764
  }, []);
690
765
  useEffect5(() => {
691
766
  window.addEventListener("resize", handleResize);
@@ -693,36 +768,20 @@ var DeckLayout = ({ layoutParts, attention, toasts, flatDeck, overscroll, showHi
693
768
  }, [
694
769
  handleResize
695
770
  ]);
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;
771
+ const restoreScroll = useCallback2(() => {
772
+ if (deckRef.current && scrollLeftRef.current != null) {
773
+ deckRef.current.scrollLeft = scrollLeftRef.current;
702
774
  }
703
- }, [
704
- layoutMode,
705
- deckRef.current,
706
- scrollLeft
707
- ]);
775
+ }, []);
776
+ useOnTransition(layoutMode, (mode) => mode !== "deck", "deck", restoreScroll);
708
777
  const handleScroll = useCallback2((event) => {
709
778
  if (layoutMode === "deck" && event.currentTarget === event.target) {
710
- setScrollLeft(event.target.scrollLeft);
779
+ scrollLeftRef.current = event.target.scrollLeft;
711
780
  }
712
781
  }, [
713
782
  layoutMode
714
783
  ]);
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
- ]);
784
+ const firstAttendedId = attended[0];
726
785
  useEffect5(() => {
727
786
  if (layoutMode === "deck" && firstAttendedId) {
728
787
  }
@@ -730,7 +789,7 @@ var DeckLayout = ({ layoutParts, attention, toasts, flatDeck, overscroll, showHi
730
789
  layoutMode,
731
790
  firstAttendedId
732
791
  ]);
733
- const parts = useMemo2(() => {
792
+ const parts = useMemo3(() => {
734
793
  const parts2 = [
735
794
  ...layoutParts.main ?? []
736
795
  ];
@@ -744,7 +803,19 @@ var DeckLayout = ({ layoutParts, attention, toasts, flatDeck, overscroll, showHi
744
803
  layoutParts.main,
745
804
  layoutParts.solo
746
805
  ]);
747
- const padding = layoutMode === "deck" && overscroll === "centering" ? calculateOverscroll(layoutParts.main, plankSizing, sidebarOpen, complementarySidebarOpen) : {};
806
+ const padding = useMemo3(() => {
807
+ if (layoutMode === "deck" && overscroll === "centering") {
808
+ return calculateOverscroll(layoutParts.main, plankSizing, sidebarOpen, complementarySidebarOpen);
809
+ }
810
+ return {};
811
+ }, [
812
+ layoutMode,
813
+ overscroll,
814
+ layoutParts.main,
815
+ plankSizing,
816
+ sidebarOpen,
817
+ complementarySidebarOpen
818
+ ]);
748
819
  if (layoutMode === "fullscreen") {
749
820
  return /* @__PURE__ */ React13.createElement(Fullscreen, {
750
821
  id: fullScreenSlug
@@ -766,19 +837,13 @@ var DeckLayout = ({ layoutParts, attention, toasts, flatDeck, overscroll, showHi
766
837
  }), /* @__PURE__ */ React13.createElement(Main3.Root, {
767
838
  navigationSidebarOpen: context.sidebarOpen,
768
839
  onNavigationSidebarOpenChange: (next) => context.sidebarOpen = next,
769
- ...complementarySidebarOpen !== null && {
770
- complementarySidebarOpen: (
771
- /* complementaryAvailable && */
772
- context.complementarySidebarOpen
773
- ),
774
- onComplementarySidebarOpenChange: (next) => context.complementarySidebarOpen = next
775
- }
840
+ complementarySidebarOpen: context.complementarySidebarOpen,
841
+ onComplementarySidebarOpenChange: (next) => context.complementarySidebarOpen = next
776
842
  }, /* @__PURE__ */ React13.createElement(Main3.Notch, {
777
843
  classNames: "z-[21]"
778
844
  }, /* @__PURE__ */ React13.createElement(Surface9, {
779
845
  role: "notch-start"
780
846
  }), /* @__PURE__ */ React13.createElement(Button3, {
781
- // disabled={!sidebarAvailable}
782
847
  onClick: () => context.sidebarOpen = !context.sidebarOpen,
783
848
  variant: "ghost",
784
849
  classNames: "p-1"
@@ -788,7 +853,6 @@ var DeckLayout = ({ layoutParts, attention, toasts, flatDeck, overscroll, showHi
788
853
  weight: "light",
789
854
  className: getSize(5)
790
855
  })), /* @__PURE__ */ React13.createElement(Button3, {
791
- // disabled={!complementaryAvailable}
792
856
  onClick: () => context.complementarySidebarOpen = !context.complementarySidebarOpen,
793
857
  variant: "ghost",
794
858
  classNames: "p-1"
@@ -801,10 +865,9 @@ var DeckLayout = ({ layoutParts, attention, toasts, flatDeck, overscroll, showHi
801
865
  })), /* @__PURE__ */ React13.createElement(Surface9, {
802
866
  role: "notch-end"
803
867
  })), /* @__PURE__ */ React13.createElement(Sidebar, {
804
- attention,
805
868
  layoutParts
806
869
  }), /* @__PURE__ */ React13.createElement(ComplementarySidebar, {
807
- id: complementarySlug,
870
+ context: "comments",
808
871
  layoutParts,
809
872
  flatDeck
810
873
  }), /* @__PURE__ */ React13.createElement(Main3.Overlay, null), parts.length === 0 && /* @__PURE__ */ React13.createElement(Main3.Content, {
@@ -834,12 +897,9 @@ var DeckLayout = ({ layoutParts, attention, toasts, flatDeck, overscroll, showHi
834
897
  layoutMode,
835
898
  flatDeck,
836
899
  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, {
900
+ }))))), /* @__PURE__ */ React13.createElement(StatusBar, {
901
+ showHints
902
+ }), /* @__PURE__ */ React13.createElement(Popover2.Portal, null, /* @__PURE__ */ React13.createElement(Popover2.Content, {
843
903
  classNames: "z-[60]",
844
904
  onEscapeKeyDown: () => {
845
905
  context.popoverOpen = false;
@@ -908,31 +968,31 @@ var LayoutSettings = ({ settings }) => {
908
968
  key: option,
909
969
  value: option
910
970
  }, t(`settings overscroll ${option} label`)))))))), /* @__PURE__ */ React14.createElement(SettingsValue, {
911
- label: t("settings show footer label")
971
+ label: t("settings show hints label")
912
972
  }, /* @__PURE__ */ React14.createElement(Input.Switch, {
913
- checked: settings.showFooter,
914
- onCheckedChange: (checked) => settings.showFooter = !!checked
973
+ checked: settings.showHints,
974
+ onCheckedChange: (checked) => settings.showHints = checked
915
975
  })), !isSocket && /* @__PURE__ */ React14.createElement(SettingsValue, {
916
976
  label: t("settings native redirect label")
917
977
  }, /* @__PURE__ */ React14.createElement(Input.Switch, {
918
978
  checked: settings.enableNativeRedirect,
919
- onCheckedChange: (checked) => settings.enableNativeRedirect = !!checked
979
+ onCheckedChange: (checked) => settings.enableNativeRedirect = checked
920
980
  })), /* @__PURE__ */ React14.createElement(SettingsValue, {
921
981
  label: t("settings custom slots")
922
982
  }, /* @__PURE__ */ React14.createElement(Input.Switch, {
923
983
  checked: settings.customSlots,
924
- onCheckedChange: (checked) => settings.customSlots = !!checked
984
+ onCheckedChange: (checked) => settings.customSlots = checked
925
985
  })), /* @__PURE__ */ React14.createElement(SettingsValue, {
926
986
  label: t("settings flat deck")
927
987
  }, /* @__PURE__ */ React14.createElement(Input.Switch, {
928
988
  checked: settings.flatDeck,
929
- onCheckedChange: (checked) => settings.flatDeck = !!checked
989
+ onCheckedChange: (checked) => settings.flatDeck = checked
930
990
  })));
931
991
  };
932
992
 
933
993
  // packages/plugins/plugin-deck/src/layout.ts
934
994
  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";
995
+ import { SLUG_ENTRY_SEPARATOR, SLUG_KEY_VALUE_SEPARATOR, SLUG_LIST_SEPARATOR, SLUG_PATH_SEPARATOR as SLUG_PATH_SEPARATOR3 } from "@dxos/app-framework";
936
996
  var partsThatSupportIncrement = [
937
997
  "main"
938
998
  ];
@@ -1045,7 +1105,7 @@ var mergeLayoutParts = (...layoutParts) => {
1045
1105
  }), {});
1046
1106
  };
1047
1107
  var parseLayoutEntry = (itemString) => {
1048
- const [id, path] = itemString.split(SLUG_PATH_SEPARATOR4);
1108
+ const [id, path] = itemString.split(SLUG_PATH_SEPARATOR3);
1049
1109
  const entry = {
1050
1110
  id
1051
1111
  };
@@ -1072,7 +1132,7 @@ var soloPartToUri = (layout) => {
1072
1132
  return "";
1073
1133
  }
1074
1134
  const entry = soloPart[0];
1075
- return `${entry.id}${entry.path ? SLUG_PATH_SEPARATOR4 + entry.path : ""}`;
1135
+ return `${entry.id}${entry.path ? SLUG_PATH_SEPARATOR3 + entry.path : ""}`;
1076
1136
  };
1077
1137
 
1078
1138
  // packages/plugins/plugin-deck/src/translations.ts
@@ -1088,7 +1148,7 @@ var translations_default = [
1088
1148
  "content fallback message": "Unsupported",
1089
1149
  "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
1150
  "toggle fullscreen label": "Toggle fullscreen",
1091
- "settings show footer label": "Show footer (experimental)",
1151
+ "settings show hints label": "Show hints",
1092
1152
  "settings native redirect label": "Enable native url redirect (experimental)",
1093
1153
  "settings custom slots": "Theme option (experimental)",
1094
1154
  "settings new plank position start label": "Start",
@@ -1112,7 +1172,9 @@ 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
+ "comments label": "Show Comments",
1177
+ "settings label": "Show Settings"
1116
1178
  }
1117
1179
  }
1118
1180
  }
@@ -1142,7 +1204,7 @@ var DeckPlugin = ({ observability } = {}) => {
1142
1204
  let currentUndoId;
1143
1205
  let handleNavigation;
1144
1206
  const settings = new LocalStorageStore("dxos.org/settings/layout", {
1145
- showFooter: false,
1207
+ showHints: true,
1146
1208
  customSlots: false,
1147
1209
  flatDeck: false,
1148
1210
  enableNativeRedirect: false,
@@ -1227,6 +1289,20 @@ var DeckPlugin = ({ observability } = {}) => {
1227
1289
  }
1228
1290
  }
1229
1291
  };
1292
+ const handleSetLocation = (next) => {
1293
+ if (attentionPlugin) {
1294
+ const attended = attentionPlugin.provides.attention.attended;
1295
+ const [attendedId] = Array.from(attended);
1296
+ const ids = (layout.values.layoutMode === "deck" ? next.main : next.solo)?.map(({ id }) => id) ?? [];
1297
+ const isAttendedAvailable = !!attendedId && ids.includes(attendedId);
1298
+ if (!isAttendedAvailable) {
1299
+ const nextAttended = next.main?.[0]?.id;
1300
+ const article = document.querySelector(`article[data-attendable-id="${nextAttended}"]`);
1301
+ article?.focus();
1302
+ }
1303
+ }
1304
+ location.values.active = next;
1305
+ };
1230
1306
  return {
1231
1307
  meta: meta_default,
1232
1308
  ready: async (plugins) => {
@@ -1267,8 +1343,8 @@ var DeckPlugin = ({ observability } = {}) => {
1267
1343
  deck.expunge();
1268
1344
  }));
1269
1345
  settings.prop({
1270
- key: "showFooter",
1271
- storageKey: "show-footer",
1346
+ key: "showHints",
1347
+ storageKey: "show-hints",
1272
1348
  type: LocalStorageStore.bool()
1273
1349
  }).prop({
1274
1350
  key: "customSlots",
@@ -1301,13 +1377,13 @@ var DeckPlugin = ({ observability } = {}) => {
1301
1377
  handleNavigation = async () => {
1302
1378
  const pathname = window.location.pathname;
1303
1379
  if (pathname === "/reset") {
1304
- location.values.active = {
1380
+ handleSetLocation({
1305
1381
  sidebar: [
1306
1382
  {
1307
1383
  id: NAV_ID
1308
1384
  }
1309
1385
  ]
1310
- };
1386
+ });
1311
1387
  location.values.closed = [];
1312
1388
  layout.values.layoutMode = "solo";
1313
1389
  window.location.pathname = "/";
@@ -1318,7 +1394,7 @@ var DeckPlugin = ({ observability } = {}) => {
1318
1394
  return;
1319
1395
  }
1320
1396
  const startingLayout = removePart(location.values.active, "solo");
1321
- location.values.active = mergeLayoutParts(layoutFromUri, startingLayout);
1397
+ handleSetLocation(mergeLayoutParts(layoutFromUri, startingLayout));
1322
1398
  layout.values.layoutMode = "solo";
1323
1399
  };
1324
1400
  await handleNavigation();
@@ -1380,8 +1456,7 @@ var DeckPlugin = ({ observability } = {}) => {
1380
1456
  ns: DECK_PLUGIN
1381
1457
  }
1382
1458
  ],
1383
- icon: (props) => /* @__PURE__ */ React15.createElement(ArrowsOut, props),
1384
- iconSymbol: "ph--arrows-out--regular",
1459
+ icon: "ph--arrows-out--regular",
1385
1460
  keyBinding: {
1386
1461
  macos: "ctrl+meta+f",
1387
1462
  windows: "shift+ctrl+f"
@@ -1398,12 +1473,9 @@ var DeckPlugin = ({ observability } = {}) => {
1398
1473
  value: deck.values
1399
1474
  }, props.children)),
1400
1475
  root: () => {
1401
- return /* @__PURE__ */ React15.createElement(Mosaic.Root, null, /* @__PURE__ */ React15.createElement(DeckLayout, {
1402
- attention: attentionPlugin?.provides.attention ?? {
1403
- attended: /* @__PURE__ */ new Set()
1404
- },
1476
+ return /* @__PURE__ */ React15.createElement(DeckLayout, {
1405
1477
  layoutParts: location.values.active,
1406
- showHintsFooter: settings.values.showFooter,
1478
+ showHints: settings.values.showHints,
1407
1479
  overscroll: settings.values.overscroll,
1408
1480
  flatDeck: settings.values.flatDeck,
1409
1481
  slots: settings.values.customSlots ? customSlots : void 0,
@@ -1419,7 +1491,7 @@ var DeckPlugin = ({ observability } = {}) => {
1419
1491
  }, 1e3);
1420
1492
  }
1421
1493
  }
1422
- }), /* @__PURE__ */ React15.createElement(Mosaic.DragOverlay, null));
1494
+ });
1423
1495
  },
1424
1496
  surface: {
1425
1497
  component: ({ data, role }) => {
@@ -1455,7 +1527,7 @@ var DeckPlugin = ({ observability } = {}) => {
1455
1527
  } else {
1456
1528
  log.warn("Invalid layout mode", intent?.data?.layoutMode, {
1457
1529
  F: __dxlog_file,
1458
- L: 390,
1530
+ L: 410,
1459
1531
  S: void 0,
1460
1532
  C: (f, a) => f(...a)
1461
1533
  });
@@ -1501,7 +1573,7 @@ var DeckPlugin = ({ observability } = {}) => {
1501
1573
  data: true
1502
1574
  };
1503
1575
  }
1504
- case NavigationAction3.OPEN: {
1576
+ case NavigationAction4.OPEN: {
1505
1577
  const previouslyOpenIds = new Set(openIds2(location.values.active));
1506
1578
  const layoutMode = layout.values.layoutMode;
1507
1579
  batch(() => {
@@ -1510,7 +1582,7 @@ var DeckPlugin = ({ observability } = {}) => {
1510
1582
  }
1511
1583
  const processLayoutEntry = (partName, entryString, currentLayout) => {
1512
1584
  const toggle = true;
1513
- const [id, path] = entryString.split(SLUG_PATH_SEPARATOR5);
1585
+ const [id, path] = entryString.split(SLUG_PATH_SEPARATOR4);
1514
1586
  const layoutEntry = {
1515
1587
  id,
1516
1588
  ...path ? {
@@ -1539,7 +1611,7 @@ var DeckPlugin = ({ observability } = {}) => {
1539
1611
  newLayout = processLayoutEntry(partName, layoutEntries, newLayout);
1540
1612
  }
1541
1613
  });
1542
- location.values.active = newLayout;
1614
+ handleSetLocation(newLayout);
1543
1615
  });
1544
1616
  const ids = openIds2(location.values.active);
1545
1617
  const newlyOpen = ids.filter((i) => !previouslyOpenIds.has(i));
@@ -1558,7 +1630,7 @@ var DeckPlugin = ({ observability } = {}) => {
1558
1630
  ] : [],
1559
1631
  intent.data?.object ? [
1560
1632
  {
1561
- action: NavigationAction3.EXPOSE,
1633
+ action: NavigationAction4.EXPOSE,
1562
1634
  data: {
1563
1635
  id: fullyQualifiedId(intent.data.object)
1564
1636
  }
@@ -1581,16 +1653,16 @@ var DeckPlugin = ({ observability } = {}) => {
1581
1653
  ]
1582
1654
  };
1583
1655
  }
1584
- case NavigationAction3.ADD_TO_ACTIVE: {
1656
+ case NavigationAction4.ADD_TO_ACTIVE: {
1585
1657
  const data = intent.data;
1586
1658
  const layoutEntry = {
1587
1659
  id: data.id
1588
1660
  };
1589
1661
  const effectivePart = getEffectivePart(data.part, layout.values.layoutMode);
1590
- location.values.active = openEntry(location.values.active, effectivePart, layoutEntry, {
1662
+ handleSetLocation(openEntry(location.values.active, effectivePart, layoutEntry, {
1591
1663
  positioning: data.positioning ?? settings.values.newPlankPositioning,
1592
1664
  pivotId: data.pivotId
1593
- });
1665
+ }));
1594
1666
  const intents = [];
1595
1667
  if (data.scrollIntoView && layout.values.layoutMode === "deck") {
1596
1668
  intents.push([
@@ -1607,7 +1679,7 @@ var DeckPlugin = ({ observability } = {}) => {
1607
1679
  intents
1608
1680
  };
1609
1681
  }
1610
- case NavigationAction3.CLOSE: {
1682
+ case NavigationAction4.CLOSE: {
1611
1683
  return batch(() => {
1612
1684
  if (!intent.data) {
1613
1685
  return;
@@ -1632,32 +1704,32 @@ var DeckPlugin = ({ observability } = {}) => {
1632
1704
  });
1633
1705
  }
1634
1706
  });
1635
- location.values.active = newLayout;
1707
+ handleSetLocation(newLayout);
1636
1708
  return {
1637
1709
  data: true
1638
1710
  };
1639
1711
  });
1640
1712
  }
1641
1713
  // TODO(wittjosiah): Factor out.
1642
- case NavigationAction3.SET: {
1714
+ case NavigationAction4.SET: {
1643
1715
  return batch(() => {
1644
1716
  if (isLayoutParts(intent.data?.activeParts)) {
1645
- location.values.active = intent.data.activeParts;
1717
+ handleSetLocation(intent.data.activeParts);
1646
1718
  }
1647
1719
  return {
1648
1720
  data: true
1649
1721
  };
1650
1722
  });
1651
1723
  }
1652
- case NavigationAction3.ADJUST: {
1724
+ case NavigationAction4.ADJUST: {
1653
1725
  return batch(() => {
1654
1726
  if (isLayoutAdjustment(intent.data)) {
1655
1727
  const adjustment = intent.data;
1656
1728
  if (adjustment.type === "increment-end" || adjustment.type === "increment-start") {
1657
- location.values.active = incrementPlank(location.values.active, {
1729
+ handleSetLocation(incrementPlank(location.values.active, {
1658
1730
  type: adjustment.type,
1659
1731
  layoutCoordinate: adjustment.layoutCoordinate
1660
- });
1732
+ }));
1661
1733
  }
1662
1734
  if (adjustment.type === "solo") {
1663
1735
  const entryId = adjustment.layoutCoordinate.entryId;
@@ -1673,7 +1745,7 @@ var DeckPlugin = ({ observability } = {}) => {
1673
1745
  }
1674
1746
  },
1675
1747
  {
1676
- action: NavigationAction3.OPEN,
1748
+ action: NavigationAction4.OPEN,
1677
1749
  data: {
1678
1750
  activeParts: {
1679
1751
  solo: [
@@ -1697,7 +1769,7 @@ var DeckPlugin = ({ observability } = {}) => {
1697
1769
  }
1698
1770
  },
1699
1771
  {
1700
- action: NavigationAction3.CLOSE,
1772
+ action: NavigationAction4.CLOSE,
1701
1773
  data: {
1702
1774
  activeParts: {
1703
1775
  solo: [
@@ -1707,7 +1779,7 @@ var DeckPlugin = ({ observability } = {}) => {
1707
1779
  }
1708
1780
  },
1709
1781
  {
1710
- action: NavigationAction3.OPEN,
1782
+ action: NavigationAction4.OPEN,
1711
1783
  data: {
1712
1784
  noToggle: true,
1713
1785
  activeParts: {