@dxos/plugin-deck 0.6.13 → 0.6.14-main.69511f5

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 +340 -288
  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 +35 -33
  36. package/src/DeckPlugin.tsx +89 -79
  37. package/src/components/DeckLayout/ActiveNode.tsx +4 -1
  38. package/src/components/DeckLayout/ComplementarySidebar.tsx +72 -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 +7 -8
  44. package/src/components/DeckLayout/StatusBar.tsx +12 -3
  45. package/src/components/DeckLayout/Toast.tsx +3 -3
  46. package/src/components/LayoutSettings.tsx +17 -20
  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,91 @@ 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 overflow-x-hidden overflow-y-scroll"
395
+ }, node && /* @__PURE__ */ React5.createElement(Surface3, {
396
+ key: id,
397
+ role: `complementary--${part}`,
335
398
  data: {
336
- subject: node.data,
337
- part: "complementary",
399
+ id,
400
+ subject: node.properties.object ?? node.properties.space,
338
401
  popoverAnchorId
339
402
  },
340
- 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
@@ -400,12 +462,12 @@ var Fullscreen = ({ id }) => {
400
462
 
401
463
  // packages/plugins/plugin-deck/src/components/DeckLayout/Plank.tsx
402
464
  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";
465
+ import React9, { memo as memo2, useCallback, useLayoutEffect, useMemo as useMemo3, useRef } from "react";
466
+ import { LayoutAction as LayoutAction2, NavigationAction as NavigationAction3, Surface as Surface6, useIntentDispatcher as useIntentDispatcher3, indexInPart, partLength } 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
 
@@ -416,20 +478,27 @@ var DeckContext = createContext2(null);
416
478
  var useDeckContext = () => useContext2(DeckContext) ?? raise2(new Error("Missing DeckContext"));
417
479
 
418
480
  // packages/plugins/plugin-deck/src/components/DeckLayout/Plank.tsx
419
- var Plank = ({ entry, layoutParts, part, flatDeck, searchEnabled, layoutMode }) => {
481
+ var Plank = /* @__PURE__ */ memo2(({ 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);
429
- const coordinate = {
490
+ const attendableAttrs = useAttendableAttributes(entry.id);
491
+ const coordinate = useMemo3(() => ({
430
492
  part,
431
493
  entryId: entry.id
432
- };
494
+ }), [
495
+ entry.id,
496
+ part
497
+ ]);
498
+ const index = indexInPart(layoutParts, coordinate);
499
+ const length = partLength(layoutParts, part);
500
+ const canIncrementStart = part === "main" && index !== void 0 && index > 0 && length !== void 0 && length > 1;
501
+ const canIncrementEnd = part === "main" && index !== void 0 && index < length - 1 && length !== void 0;
433
502
  const size = plankSizing?.[entry.id];
434
503
  const setSize = useCallback(debounce((newSize) => {
435
504
  void dispatch({
@@ -463,8 +532,21 @@ var Plank = ({ entry, layoutParts, part, flatDeck, searchEnabled, layoutMode })
463
532
  layoutMode
464
533
  ]);
465
534
  const isSolo = layoutMode === "solo" && part === "solo";
466
- const isSuppressed = layoutMode === "solo" && part !== "solo";
535
+ const isSuppressed = layoutMode === "solo" && part !== "solo" || layoutMode === "deck" && part === "solo";
467
536
  const sizeAttrs = useMainSize();
537
+ const data = useMemo3(() => node && {
538
+ ...entry.path ? {
539
+ subject: node.data,
540
+ path: entry.path
541
+ } : {
542
+ object: node.data
543
+ },
544
+ coordinate,
545
+ popoverAnchorId
546
+ }, [
547
+ node
548
+ ]);
549
+ const placeholder = useMemo3(() => /* @__PURE__ */ React9.createElement(PlankLoading, null), []);
468
550
  return /* @__PURE__ */ React9.createElement(NaturalPlank.Root, {
469
551
  size,
470
552
  setSize,
@@ -487,30 +569,20 @@ var Plank = ({ entry, layoutParts, part, flatDeck, searchEnabled, layoutMode })
487
569
  inlineSize: ""
488
570
  } : {}
489
571
  }, node ? /* @__PURE__ */ React9.createElement(React9.Fragment, null, /* @__PURE__ */ React9.createElement(NodePlankHeading, {
490
- id: entry.id,
572
+ coordinate,
491
573
  node,
492
- layoutPart: coordinate.part,
493
- layoutParts,
574
+ canIncrementStart,
575
+ canIncrementEnd,
494
576
  popoverAnchorId,
495
577
  flatDeck
496
578
  }), /* @__PURE__ */ React9.createElement(Surface6, {
497
579
  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
- },
580
+ data,
508
581
  limit: 1,
509
582
  fallback: PlankContentError,
510
- placeholder: /* @__PURE__ */ React9.createElement(PlankLoading, null)
583
+ placeholder
511
584
  })) : /* @__PURE__ */ React9.createElement(PlankError, {
512
585
  layoutCoordinate: coordinate,
513
- id: entry.id,
514
586
  flatDeck
515
587
  })), searchEnabled && resizeable ? /* @__PURE__ */ React9.createElement("div", {
516
588
  role: "none",
@@ -529,7 +601,7 @@ var Plank = ({ entry, layoutParts, part, flatDeck, searchEnabled, layoutMode })
529
601
  component: "dxos.org/plugin/search/Dialog",
530
602
  dialogBlockAlign: "start",
531
603
  subject: {
532
- action: NavigationAction2.SET,
604
+ action: NavigationAction3.SET,
533
605
  position: "add-after",
534
606
  coordinate
535
607
  }
@@ -546,33 +618,31 @@ var Plank = ({ entry, layoutParts, part, flatDeck, searchEnabled, layoutMode })
546
618
  })) : resizeable ? /* @__PURE__ */ React9.createElement(NaturalPlank.ResizeHandle, {
547
619
  classNames: "row-span-3"
548
620
  }) : null);
549
- };
621
+ });
550
622
 
551
623
  // packages/plugins/plugin-deck/src/components/DeckLayout/Sidebar.tsx
552
- import React10, { useMemo } from "react";
624
+ import React10, { useMemo as useMemo4 } from "react";
553
625
  import { openIds, Surface as Surface7 } from "@dxos/app-framework";
554
626
  import { Main as Main2 } from "@dxos/react-ui";
555
- var Sidebar = ({ attention, layoutParts }) => {
627
+ var Sidebar = ({ layoutParts }) => {
556
628
  const { layoutMode, popoverAnchorId } = useLayout();
557
- const activeIds = useMemo(() => {
629
+ const activeIds = useMemo4(() => {
558
630
  if (layoutMode === "solo") {
559
- return new Set(layoutParts?.solo?.map((e) => e.id) ?? []);
631
+ return Array.from(new Set(layoutParts?.solo?.map((e) => e.id) ?? []));
560
632
  } else if (layoutMode === "deck") {
561
- return new Set(layoutParts?.main?.map((e) => e.id) ?? []);
633
+ return Array.from(new Set(layoutParts?.main?.map((e) => e.id) ?? []));
562
634
  }
563
- return new Set(openIds(layoutParts));
635
+ return Array.from(new Set(openIds(layoutParts)));
564
636
  }, [
565
637
  layoutParts,
566
638
  layoutMode
567
639
  ]);
568
- const navigationData = useMemo(() => ({
640
+ const navigationData = useMemo4(() => ({
569
641
  popoverAnchorId,
570
- activeIds,
571
- attended: attention.attended
642
+ activeIds
572
643
  }), [
573
644
  popoverAnchorId,
574
- activeIds,
575
- attention.attended
645
+ activeIds
576
646
  ]);
577
647
  return /* @__PURE__ */ React10.createElement(Main2.NavigationSidebar, null, /* @__PURE__ */ React10.createElement(Surface7, {
578
648
  role: "navigation",
@@ -586,14 +656,19 @@ var Sidebar = ({ attention, layoutParts }) => {
586
656
  // packages/plugins/plugin-deck/src/components/DeckLayout/StatusBar.tsx
587
657
  import React11 from "react";
588
658
  import { Surface as Surface8 } from "@dxos/app-framework";
589
- import { mainPadding, mx as mx4 } from "@dxos/react-ui-theme";
590
- var StatusBar = () => {
659
+ import { mainPadding, mainPaddingTransitions, mx as mx4 } from "@dxos/react-ui-theme";
660
+ var StatusBar = ({ showHints }) => {
591
661
  const sizeAttrs = useMainSize();
592
662
  return /* @__PURE__ */ React11.createElement("div", {
593
663
  role: "none",
594
664
  ...sizeAttrs,
595
- className: mx4("fixed block-end-0 inset-inline-0 z-[2]", mainPadding)
596
- }, /* @__PURE__ */ React11.createElement(Surface8, {
665
+ className: mx4("fixed flex justify-between block-end-0 inset-inline-0 items-center border-bs border-separator z-[2]", mainPadding, mainPaddingTransitions)
666
+ }, /* @__PURE__ */ React11.createElement("div", {
667
+ role: "none"
668
+ }, showHints && /* @__PURE__ */ React11.createElement(Surface8, {
669
+ role: "hints",
670
+ limit: 1
671
+ })), /* @__PURE__ */ React11.createElement(Surface8, {
597
672
  role: "status-bar",
598
673
  limit: 1
599
674
  }));
@@ -601,15 +676,19 @@ var StatusBar = () => {
601
676
 
602
677
  // packages/plugins/plugin-deck/src/components/DeckLayout/Toast.tsx
603
678
  import React12 from "react";
604
- import { Button as Button2, Toast as NaturalToast } from "@dxos/react-ui";
679
+ import { Button as Button2, Icon as Icon2, Toast as NaturalToast } from "@dxos/react-ui";
605
680
  var Toast = ({ id, title, description, icon, duration, actionLabel, actionAlt, closeLabel, onAction, onOpenChange }) => {
606
681
  return /* @__PURE__ */ React12.createElement(NaturalToast.Root, {
607
682
  "data-testid": id,
608
683
  defaultOpen: true,
609
684
  duration,
610
685
  onOpenChange
611
- }, /* @__PURE__ */ React12.createElement(NaturalToast.Body, null, /* @__PURE__ */ React12.createElement(NaturalToast.Title, null, icon?.({
612
- className: "inline mr-1"
686
+ }, /* @__PURE__ */ React12.createElement(NaturalToast.Body, null, /* @__PURE__ */ React12.createElement(NaturalToast.Title, {
687
+ classNames: "items-center"
688
+ }, /* @__PURE__ */ React12.createElement(Icon2, {
689
+ icon,
690
+ size: 5,
691
+ classNames: "inline mr-1"
613
692
  }), /* @__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
693
  altText: actionAlt,
615
694
  asChild: true
@@ -646,7 +725,10 @@ var getEffectivePart = (partName, layoutMode) => layoutMode === "solo" && partNa
646
725
  import { PLANK_DEFAULTS } from "@dxos/react-ui-deck";
647
726
  var calculateOverscroll = (planks, plankSizing, sidebarOpen, complementarySidebarOpen) => {
648
727
  if (!planks?.length) {
649
- return;
728
+ return {
729
+ paddingInlineStart: 0,
730
+ paddingInlineEnd: 0
731
+ };
650
732
  }
651
733
  const sidebarWidth = sidebarOpen ? "270px" : "0px";
652
734
  const complementarySidebarWidth = complementarySidebarOpen ? "360px" : "0px";
@@ -656,8 +738,8 @@ var calculateOverscroll = (planks, plankSizing, sidebarOpen, complementarySideba
656
738
  const plankSize = getPlankSize(plank.id);
657
739
  const overscrollPadding = `max(0px, calc(((100dvw - ${sidebarWidth} - ${complementarySidebarWidth} - (${plankSize} + 20px)) / 2)))`;
658
740
  return {
659
- paddingLeft: overscrollPadding,
660
- paddingRight: overscrollPadding
741
+ paddingInlineStart: overscrollPadding,
742
+ paddingInlineEnd: overscrollPadding
661
743
  };
662
744
  } else {
663
745
  const first = planks[0];
@@ -665,27 +747,34 @@ var calculateOverscroll = (planks, plankSizing, sidebarOpen, complementarySideba
665
747
  const last = planks[planks.length - 1];
666
748
  const lastSize = getPlankSize(last.id);
667
749
  return {
668
- paddingLeft: `max(0px, calc(((100dvw - (${firstSize} + 20px)) / 2) - ${sidebarWidth}))`,
669
- paddingRight: `max(0px, calc(((100dvw - (${lastSize} + 20px)) / 2) - ${complementarySidebarWidth}))`
750
+ paddingInlineStart: `max(0px, calc(((100dvw - (${firstSize} + 20px)) / 2) - ${sidebarWidth}))`,
751
+ paddingInlineEnd: `max(0px, calc(((100dvw - (${lastSize} + 20px)) / 2) - ${complementarySidebarWidth}))`
670
752
  };
671
753
  }
672
754
  };
673
755
 
674
756
  // packages/plugins/plugin-deck/src/components/DeckLayout/DeckLayout.tsx
675
- var DeckLayout = ({ layoutParts, attention, toasts, flatDeck, overscroll, showHintsFooter, slots, onDismissToast }) => {
757
+ var DeckLayout = ({ layoutParts, toasts, flatDeck, overscroll, showHints, slots, onDismissToast }) => {
676
758
  const context = useLayout();
677
759
  const { layoutMode, sidebarOpen, complementarySidebarOpen, dialogOpen, dialogContent, dialogBlockAlign, popoverOpen, popoverContent, popoverAnchorId } = context;
678
760
  const { t } = useTranslation5(DECK_PLUGIN);
679
761
  const { plankSizing } = useDeckContext();
762
+ const attentionPlugin = usePlugin("dxos.org/plugin/attention");
680
763
  const searchPlugin = usePlugin("dxos.org/plugin/search");
681
- const fullScreenSlug = useMemo2(() => firstIdInPart(layoutParts, "fullScreen"), [
764
+ const fullScreenSlug = useMemo5(() => firstIdInPart(layoutParts, "fullScreen"), [
682
765
  layoutParts
683
766
  ]);
684
- const [scrollLeft, setScrollLeft] = useState3(null);
767
+ const scrollLeftRef = useRef2();
685
768
  const deckRef = useRef2(null);
686
- const restoreScrollRef = useRef2(false);
769
+ useEffect5(() => {
770
+ const attended = untracked(() => attentionPlugin?.provides.attention.attended ?? []);
771
+ const firstId = layoutMode === "solo" ? firstIdInPart(layoutParts, "solo") : firstIdInPart(layoutParts, "main");
772
+ if (attended.length === 0 && firstId) {
773
+ document.querySelector(`article[data-attendable-id="${firstId}"] button`)?.focus();
774
+ }
775
+ }, []);
687
776
  const handleResize = useCallback2(() => {
688
- setScrollLeft(null);
777
+ scrollLeftRef.current = null;
689
778
  }, []);
690
779
  useEffect5(() => {
691
780
  window.addEventListener("resize", handleResize);
@@ -693,58 +782,33 @@ var DeckLayout = ({ layoutParts, attention, toasts, flatDeck, overscroll, showHi
693
782
  }, [
694
783
  handleResize
695
784
  ]);
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;
785
+ const restoreScroll = useCallback2(() => {
786
+ if (deckRef.current && scrollLeftRef.current != null) {
787
+ deckRef.current.scrollLeft = scrollLeftRef.current;
702
788
  }
703
- }, [
704
- layoutMode,
705
- deckRef.current,
706
- scrollLeft
707
- ]);
789
+ }, []);
790
+ useOnTransition(layoutMode, (mode) => mode !== "deck", "deck", restoreScroll);
708
791
  const handleScroll = useCallback2((event) => {
709
792
  if (layoutMode === "deck" && event.currentTarget === event.target) {
710
- setScrollLeft(event.target.scrollLeft);
793
+ scrollLeftRef.current = event.target.scrollLeft;
711
794
  }
712
795
  }, [
713
796
  layoutMode
714
797
  ]);
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) {
798
+ const isEmpty = layoutParts.main?.length === 0 && layoutParts.solo?.length === 0;
799
+ const padding = useMemo5(() => {
800
+ if (layoutMode === "deck" && overscroll === "centering") {
801
+ return calculateOverscroll(layoutParts.main, plankSizing, sidebarOpen, complementarySidebarOpen);
728
802
  }
803
+ return {};
729
804
  }, [
730
805
  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
- }, [
806
+ overscroll,
744
807
  layoutParts.main,
745
- layoutParts.solo
808
+ plankSizing,
809
+ sidebarOpen,
810
+ complementarySidebarOpen
746
811
  ]);
747
- const padding = layoutMode === "deck" && overscroll === "centering" ? calculateOverscroll(layoutParts.main, plankSizing, sidebarOpen, complementarySidebarOpen) : {};
748
812
  if (layoutMode === "fullscreen") {
749
813
  return /* @__PURE__ */ React13.createElement(Fullscreen, {
750
814
  id: fullScreenSlug
@@ -761,24 +825,16 @@ var DeckLayout = ({ layoutParts, attention, toasts, flatDeck, overscroll, showHi
761
825
  context.popoverAnchorId = void 0;
762
826
  }
763
827
  }
764
- }, /* @__PURE__ */ React13.createElement(ActiveNode, {
765
- id: firstAttendedId
766
- }), /* @__PURE__ */ React13.createElement(Main3.Root, {
828
+ }, /* @__PURE__ */ React13.createElement(ActiveNode, null), /* @__PURE__ */ React13.createElement(Main3.Root, {
767
829
  navigationSidebarOpen: context.sidebarOpen,
768
830
  onNavigationSidebarOpenChange: (next) => context.sidebarOpen = next,
769
- ...complementarySidebarOpen !== null && {
770
- complementarySidebarOpen: (
771
- /* complementaryAvailable && */
772
- context.complementarySidebarOpen
773
- ),
774
- onComplementarySidebarOpenChange: (next) => context.complementarySidebarOpen = next
775
- }
831
+ complementarySidebarOpen: context.complementarySidebarOpen,
832
+ onComplementarySidebarOpenChange: (next) => context.complementarySidebarOpen = next
776
833
  }, /* @__PURE__ */ React13.createElement(Main3.Notch, {
777
834
  classNames: "z-[21]"
778
835
  }, /* @__PURE__ */ React13.createElement(Surface9, {
779
836
  role: "notch-start"
780
837
  }), /* @__PURE__ */ React13.createElement(Button3, {
781
- // disabled={!sidebarAvailable}
782
838
  onClick: () => context.sidebarOpen = !context.sidebarOpen,
783
839
  variant: "ghost",
784
840
  classNames: "p-1"
@@ -788,7 +844,6 @@ var DeckLayout = ({ layoutParts, attention, toasts, flatDeck, overscroll, showHi
788
844
  weight: "light",
789
845
  className: getSize(5)
790
846
  })), /* @__PURE__ */ React13.createElement(Button3, {
791
- // disabled={!complementaryAvailable}
792
847
  onClick: () => context.complementarySidebarOpen = !context.complementarySidebarOpen,
793
848
  variant: "ghost",
794
849
  classNames: "p-1"
@@ -801,15 +856,13 @@ var DeckLayout = ({ layoutParts, attention, toasts, flatDeck, overscroll, showHi
801
856
  })), /* @__PURE__ */ React13.createElement(Surface9, {
802
857
  role: "notch-end"
803
858
  })), /* @__PURE__ */ React13.createElement(Sidebar, {
804
- attention,
805
859
  layoutParts
806
860
  }), /* @__PURE__ */ React13.createElement(ComplementarySidebar, {
807
- id: complementarySlug,
808
- layoutParts,
861
+ panel: layoutParts.complementary?.[0].id,
809
862
  flatDeck
810
- }), /* @__PURE__ */ React13.createElement(Main3.Overlay, null), parts.length === 0 && /* @__PURE__ */ React13.createElement(Main3.Content, {
863
+ }), /* @__PURE__ */ React13.createElement(Main3.Overlay, null), isEmpty && /* @__PURE__ */ React13.createElement(Main3.Content, {
811
864
  handlesFocus: true
812
- }, /* @__PURE__ */ React13.createElement(ContentEmpty, null)), parts.length !== 0 && /* @__PURE__ */ React13.createElement(Main3.Content, {
865
+ }, /* @__PURE__ */ React13.createElement(ContentEmpty, null)), !isEmpty && /* @__PURE__ */ React13.createElement(Main3.Content, {
813
866
  bounce: true,
814
867
  classNames: "grid block-end-[--statusbar-size]",
815
868
  handlesFocus: true
@@ -820,26 +873,33 @@ var DeckLayout = ({ layoutParts, attention, toasts, flatDeck, overscroll, showHi
820
873
  style: padding,
821
874
  classNames: [
822
875
  !flatDeck && "bg-deck",
876
+ mainPaddingTransitions2,
823
877
  "absolute inset-0",
824
878
  slots?.wallpaper?.classNames
825
879
  ],
826
880
  solo: layoutMode === "solo",
827
881
  onScroll: handleScroll,
828
882
  ref: deckRef
829
- }, parts.map((layoutEntry) => /* @__PURE__ */ React13.createElement(Plank, {
883
+ }, /* @__PURE__ */ React13.createElement(Plank, {
884
+ entry: layoutParts.solo?.[0] ?? {
885
+ id: "unknown-solo"
886
+ },
887
+ layoutParts,
888
+ part: "solo",
889
+ layoutMode,
890
+ flatDeck,
891
+ searchEnabled: !!searchPlugin
892
+ }), layoutParts.main?.map((layoutEntry) => /* @__PURE__ */ React13.createElement(Plank, {
830
893
  key: layoutEntry.id,
831
894
  entry: layoutEntry,
832
895
  layoutParts,
833
- part: layoutMode === "solo" && layoutEntry.id === layoutParts.solo?.[0]?.id ? "solo" : "main",
896
+ part: "main",
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;
@@ -870,8 +930,8 @@ var DeckLayout = ({ layoutParts, attention, toasts, flatDeck, overscroll, showHi
870
930
 
871
931
  // packages/plugins/plugin-deck/src/components/LayoutSettings.tsx
872
932
  import React14 from "react";
873
- import { SettingsValue } from "@dxos/plugin-settings";
874
933
  import { Input, Select, useTranslation as useTranslation6 } from "@dxos/react-ui";
934
+ import { FormInput } from "@dxos/react-ui-data";
875
935
 
876
936
  // packages/plugins/plugin-deck/src/types.ts
877
937
  var NewPlankPositions = [
@@ -887,7 +947,7 @@ var OverscrollOptions = [
887
947
  var isSocket = !!globalThis.__args;
888
948
  var LayoutSettings = ({ settings }) => {
889
949
  const { t } = useTranslation6(DECK_PLUGIN);
890
- return /* @__PURE__ */ React14.createElement(React14.Fragment, null, /* @__PURE__ */ React14.createElement(SettingsValue, {
950
+ return /* @__PURE__ */ React14.createElement(React14.Fragment, null, /* @__PURE__ */ React14.createElement(FormInput, {
891
951
  label: t("select new plank positioning label")
892
952
  }, /* @__PURE__ */ React14.createElement(Select.Root, {
893
953
  value: settings.newPlankPositioning ?? "start",
@@ -897,7 +957,7 @@ var LayoutSettings = ({ settings }) => {
897
957
  }), /* @__PURE__ */ React14.createElement(Select.Portal, null, /* @__PURE__ */ React14.createElement(Select.Content, null, /* @__PURE__ */ React14.createElement(Select.Viewport, null, NewPlankPositions.map((position) => /* @__PURE__ */ React14.createElement(Select.Option, {
898
958
  key: position,
899
959
  value: position
900
- }, t(`settings new plank position ${position} label`)))))))), /* @__PURE__ */ React14.createElement(SettingsValue, {
960
+ }, t(`settings new plank position ${position} label`)))))))), /* @__PURE__ */ React14.createElement(FormInput, {
901
961
  label: t("settings overscroll label")
902
962
  }, /* @__PURE__ */ React14.createElement(Select.Root, {
903
963
  value: settings.overscroll ?? "none",
@@ -907,32 +967,32 @@ var LayoutSettings = ({ settings }) => {
907
967
  }), /* @__PURE__ */ React14.createElement(Select.Portal, null, /* @__PURE__ */ React14.createElement(Select.Content, null, /* @__PURE__ */ React14.createElement(Select.Viewport, null, OverscrollOptions.map((option) => /* @__PURE__ */ React14.createElement(Select.Option, {
908
968
  key: option,
909
969
  value: option
910
- }, t(`settings overscroll ${option} label`)))))))), /* @__PURE__ */ React14.createElement(SettingsValue, {
911
- label: t("settings show footer label")
970
+ }, t(`settings overscroll ${option} label`)))))))), /* @__PURE__ */ React14.createElement(FormInput, {
971
+ label: t("settings show hints label")
912
972
  }, /* @__PURE__ */ React14.createElement(Input.Switch, {
913
- checked: settings.showFooter,
914
- onCheckedChange: (checked) => settings.showFooter = !!checked
915
- })), !isSocket && /* @__PURE__ */ React14.createElement(SettingsValue, {
973
+ checked: settings.showHints,
974
+ onCheckedChange: (checked) => settings.showHints = checked
975
+ })), !isSocket && /* @__PURE__ */ React14.createElement(FormInput, {
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
920
- })), /* @__PURE__ */ React14.createElement(SettingsValue, {
979
+ onCheckedChange: (checked) => settings.enableNativeRedirect = checked
980
+ })), /* @__PURE__ */ React14.createElement(FormInput, {
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
925
- })), /* @__PURE__ */ React14.createElement(SettingsValue, {
984
+ onCheckedChange: (checked) => settings.customSlots = checked
985
+ })), /* @__PURE__ */ React14.createElement(FormInput, {
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
@@ -1083,12 +1143,11 @@ var translations_default = [
1083
1143
  "main header label": "Main header",
1084
1144
  "open navigation sidebar label": "Open navigation sidebar.",
1085
1145
  "open complementary sidebar label": "Open complementary sidebar.",
1086
- "open settings label": "Show settings",
1087
1146
  "plugin error message": "Content failed to render.",
1088
1147
  "content fallback message": "Unsupported",
1089
1148
  "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
1149
  "toggle fullscreen label": "Toggle fullscreen",
1091
- "settings show footer label": "Show footer (experimental)",
1150
+ "settings show hints label": "Show hints",
1092
1151
  "settings native redirect label": "Enable native url redirect (experimental)",
1093
1152
  "settings custom slots": "Theme option (experimental)",
1094
1153
  "settings new plank position start label": "Start",
@@ -1099,7 +1158,6 @@ var translations_default = [
1099
1158
  "undo action label": "Undo",
1100
1159
  "undo action alt": "Undo previous action",
1101
1160
  "undo close label": "Dismiss",
1102
- "open comments label": "Open comments",
1103
1161
  "error fallback message": "Unable to open this item",
1104
1162
  "plank heading fallback label": "Untitled",
1105
1163
  "actions menu label": "Options",
@@ -1112,7 +1170,12 @@ var translations_default = [
1112
1170
  "select overscroll placeholder": "Select plank overscrolling behavior",
1113
1171
  "settings overscroll centering label": "Centering",
1114
1172
  "settings overscroll none label": "None",
1115
- "settings flat deck": "Flatten deck appearance"
1173
+ "settings flat deck": "Flatten deck appearance",
1174
+ // ComplementarySidebar
1175
+ "open settings label": "Show settings",
1176
+ "open comments label": "Show Comments",
1177
+ "open automation label": "Show Automation",
1178
+ "open debug label": "Show Debug"
1116
1179
  }
1117
1180
  }
1118
1181
  }
@@ -1142,7 +1205,7 @@ var DeckPlugin = ({ observability } = {}) => {
1142
1205
  let currentUndoId;
1143
1206
  let handleNavigation;
1144
1207
  const settings = new LocalStorageStore("dxos.org/settings/layout", {
1145
- showFooter: false,
1208
+ showHints: false,
1146
1209
  customSlots: false,
1147
1210
  flatDeck: false,
1148
1211
  enableNativeRedirect: false,
@@ -1227,6 +1290,22 @@ var DeckPlugin = ({ observability } = {}) => {
1227
1290
  }
1228
1291
  }
1229
1292
  };
1293
+ const handleSetLocation = (next) => {
1294
+ if (attentionPlugin) {
1295
+ const attended = attentionPlugin.provides.attention.attended;
1296
+ const [attendedId] = Array.from(attended);
1297
+ const ids = (layout.values.layoutMode === "deck" ? next.main : next.solo)?.map(({ id }) => id) ?? [];
1298
+ const isAttendedAvailable = !!attendedId && ids.includes(attendedId);
1299
+ if (!isAttendedAvailable) {
1300
+ requestAnimationFrame(() => {
1301
+ const nextAttended = layout.values.layoutMode === "solo" ? next.solo?.[0].id : next.main?.[0]?.id;
1302
+ const article = document.querySelector(`article[data-attendable-id="${nextAttended}"]`);
1303
+ article?.focus();
1304
+ });
1305
+ }
1306
+ }
1307
+ location.values.active = next;
1308
+ };
1230
1309
  return {
1231
1310
  meta: meta_default,
1232
1311
  ready: async (plugins) => {
@@ -1236,29 +1315,23 @@ var DeckPlugin = ({ observability } = {}) => {
1236
1315
  clientPlugin = resolvePlugin(plugins, parseClientPlugin);
1237
1316
  layout.prop({
1238
1317
  key: "layoutMode",
1239
- storageKey: "layout-mode",
1240
1318
  type: LocalStorageStore.enum()
1241
1319
  }).prop({
1242
1320
  key: "sidebarOpen",
1243
- storageKey: "sidebar-open",
1244
1321
  type: LocalStorageStore.bool()
1245
1322
  }).prop({
1246
1323
  key: "complementarySidebarOpen",
1247
- storageKey: "complementary-sidebar-open",
1248
1324
  type: LocalStorageStore.bool()
1249
1325
  });
1250
1326
  deck.prop({
1251
1327
  key: "plankSizing",
1252
- storageKey: "plank-sizing",
1253
1328
  type: LocalStorageStore.json()
1254
1329
  });
1255
1330
  location.prop({
1256
1331
  key: "active",
1257
- storageKey: "active",
1258
1332
  type: LocalStorageStore.json()
1259
1333
  }).prop({
1260
1334
  key: "closed",
1261
- storageKey: "closed",
1262
1335
  type: LocalStorageStore.json()
1263
1336
  });
1264
1337
  unsubscriptionCallbacks.push(clientPlugin?.provides.client.shell.onReset(() => {
@@ -1267,32 +1340,25 @@ var DeckPlugin = ({ observability } = {}) => {
1267
1340
  deck.expunge();
1268
1341
  }));
1269
1342
  settings.prop({
1270
- key: "showFooter",
1271
- storageKey: "show-footer",
1343
+ key: "showHints",
1272
1344
  type: LocalStorageStore.bool()
1273
1345
  }).prop({
1274
1346
  key: "customSlots",
1275
- storageKey: "customSlots",
1276
1347
  type: LocalStorageStore.bool()
1277
1348
  }).prop({
1278
1349
  key: "flatDeck",
1279
- storageKey: "flatDeck",
1280
1350
  type: LocalStorageStore.bool()
1281
1351
  }).prop({
1282
1352
  key: "enableNativeRedirect",
1283
- storageKey: "enable-native-redirect",
1284
1353
  type: LocalStorageStore.bool()
1285
1354
  }).prop({
1286
1355
  key: "disableDeck",
1287
- storageKey: "disable-deck",
1288
1356
  type: LocalStorageStore.bool()
1289
1357
  }).prop({
1290
1358
  key: "newPlankPositioning",
1291
- storageKey: "newPlankPositioning",
1292
1359
  type: LocalStorageStore.enum()
1293
1360
  }).prop({
1294
1361
  key: "overscroll",
1295
- storageKey: "overscroll",
1296
1362
  type: LocalStorageStore.enum()
1297
1363
  });
1298
1364
  if (!isSocket2 && settings.values.enableNativeRedirect) {
@@ -1301,13 +1367,13 @@ var DeckPlugin = ({ observability } = {}) => {
1301
1367
  handleNavigation = async () => {
1302
1368
  const pathname = window.location.pathname;
1303
1369
  if (pathname === "/reset") {
1304
- location.values.active = {
1370
+ handleSetLocation({
1305
1371
  sidebar: [
1306
1372
  {
1307
1373
  id: NAV_ID
1308
1374
  }
1309
1375
  ]
1310
- };
1376
+ });
1311
1377
  location.values.closed = [];
1312
1378
  layout.values.layoutMode = "solo";
1313
1379
  window.location.pathname = "/";
@@ -1318,26 +1384,16 @@ var DeckPlugin = ({ observability } = {}) => {
1318
1384
  return;
1319
1385
  }
1320
1386
  const startingLayout = removePart(location.values.active, "solo");
1321
- location.values.active = mergeLayoutParts(layoutFromUri, startingLayout);
1387
+ handleSetLocation(mergeLayoutParts(layoutFromUri, startingLayout));
1322
1388
  layout.values.layoutMode = "solo";
1323
1389
  };
1324
1390
  await handleNavigation();
1325
1391
  window.addEventListener("popstate", handleNavigation);
1326
- unsubscriptionCallbacks.push(effect(() => {
1327
- const selectedPath = soloPartToUri(location.values.active);
1392
+ unsubscriptionCallbacks.push(scheduledEffect(() => ({
1393
+ selectedPath: soloPartToUri(location.values.active)
1394
+ }), ({ selectedPath }) => {
1328
1395
  history.pushState(null, "", `/${selectedPath}${window.location.search}`);
1329
1396
  }));
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
1397
  layoutModeHistory.values.push(`${layout.values.layoutMode}`);
1342
1398
  },
1343
1399
  unload: async () => {
@@ -1380,8 +1436,7 @@ var DeckPlugin = ({ observability } = {}) => {
1380
1436
  ns: DECK_PLUGIN
1381
1437
  }
1382
1438
  ],
1383
- icon: (props) => /* @__PURE__ */ React15.createElement(ArrowsOut, props),
1384
- iconSymbol: "ph--arrows-out--regular",
1439
+ icon: "ph--arrows-out--regular",
1385
1440
  keyBinding: {
1386
1441
  macos: "ctrl+meta+f",
1387
1442
  windows: "shift+ctrl+f"
@@ -1398,12 +1453,9 @@ var DeckPlugin = ({ observability } = {}) => {
1398
1453
  value: deck.values
1399
1454
  }, props.children)),
1400
1455
  root: () => {
1401
- return /* @__PURE__ */ React15.createElement(Mosaic.Root, null, /* @__PURE__ */ React15.createElement(DeckLayout, {
1402
- attention: attentionPlugin?.provides.attention ?? {
1403
- attended: /* @__PURE__ */ new Set()
1404
- },
1456
+ return /* @__PURE__ */ React15.createElement(DeckLayout, {
1405
1457
  layoutParts: location.values.active,
1406
- showHintsFooter: settings.values.showFooter,
1458
+ showHints: settings.values.showHints,
1407
1459
  overscroll: settings.values.overscroll,
1408
1460
  flatDeck: settings.values.flatDeck,
1409
1461
  slots: settings.values.customSlots ? customSlots : void 0,
@@ -1419,7 +1471,7 @@ var DeckPlugin = ({ observability } = {}) => {
1419
1471
  }, 1e3);
1420
1472
  }
1421
1473
  }
1422
- }), /* @__PURE__ */ React15.createElement(Mosaic.DragOverlay, null));
1474
+ });
1423
1475
  },
1424
1476
  surface: {
1425
1477
  component: ({ data, role }) => {
@@ -1455,7 +1507,7 @@ var DeckPlugin = ({ observability } = {}) => {
1455
1507
  } else {
1456
1508
  log.warn("Invalid layout mode", intent?.data?.layoutMode, {
1457
1509
  F: __dxlog_file,
1458
- L: 390,
1510
+ L: 392,
1459
1511
  S: void 0,
1460
1512
  C: (f, a) => f(...a)
1461
1513
  });
@@ -1501,7 +1553,7 @@ var DeckPlugin = ({ observability } = {}) => {
1501
1553
  data: true
1502
1554
  };
1503
1555
  }
1504
- case NavigationAction3.OPEN: {
1556
+ case NavigationAction4.OPEN: {
1505
1557
  const previouslyOpenIds = new Set(openIds2(location.values.active));
1506
1558
  const layoutMode = layout.values.layoutMode;
1507
1559
  batch(() => {
@@ -1510,7 +1562,7 @@ var DeckPlugin = ({ observability } = {}) => {
1510
1562
  }
1511
1563
  const processLayoutEntry = (partName, entryString, currentLayout) => {
1512
1564
  const toggle = true;
1513
- const [id, path] = entryString.split(SLUG_PATH_SEPARATOR5);
1565
+ const [id, path] = entryString.split(SLUG_PATH_SEPARATOR4);
1514
1566
  const layoutEntry = {
1515
1567
  id,
1516
1568
  ...path ? {
@@ -1539,7 +1591,7 @@ var DeckPlugin = ({ observability } = {}) => {
1539
1591
  newLayout = processLayoutEntry(partName, layoutEntries, newLayout);
1540
1592
  }
1541
1593
  });
1542
- location.values.active = newLayout;
1594
+ handleSetLocation(newLayout);
1543
1595
  });
1544
1596
  const ids = openIds2(location.values.active);
1545
1597
  const newlyOpen = ids.filter((i) => !previouslyOpenIds.has(i));
@@ -1558,7 +1610,7 @@ var DeckPlugin = ({ observability } = {}) => {
1558
1610
  ] : [],
1559
1611
  intent.data?.object ? [
1560
1612
  {
1561
- action: NavigationAction3.EXPOSE,
1613
+ action: NavigationAction4.EXPOSE,
1562
1614
  data: {
1563
1615
  id: fullyQualifiedId(intent.data.object)
1564
1616
  }
@@ -1581,16 +1633,16 @@ var DeckPlugin = ({ observability } = {}) => {
1581
1633
  ]
1582
1634
  };
1583
1635
  }
1584
- case NavigationAction3.ADD_TO_ACTIVE: {
1636
+ case NavigationAction4.ADD_TO_ACTIVE: {
1585
1637
  const data = intent.data;
1586
1638
  const layoutEntry = {
1587
1639
  id: data.id
1588
1640
  };
1589
1641
  const effectivePart = getEffectivePart(data.part, layout.values.layoutMode);
1590
- location.values.active = openEntry(location.values.active, effectivePart, layoutEntry, {
1642
+ handleSetLocation(openEntry(location.values.active, effectivePart, layoutEntry, {
1591
1643
  positioning: data.positioning ?? settings.values.newPlankPositioning,
1592
1644
  pivotId: data.pivotId
1593
- });
1645
+ }));
1594
1646
  const intents = [];
1595
1647
  if (data.scrollIntoView && layout.values.layoutMode === "deck") {
1596
1648
  intents.push([
@@ -1607,7 +1659,7 @@ var DeckPlugin = ({ observability } = {}) => {
1607
1659
  intents
1608
1660
  };
1609
1661
  }
1610
- case NavigationAction3.CLOSE: {
1662
+ case NavigationAction4.CLOSE: {
1611
1663
  return batch(() => {
1612
1664
  if (!intent.data) {
1613
1665
  return;
@@ -1632,32 +1684,32 @@ var DeckPlugin = ({ observability } = {}) => {
1632
1684
  });
1633
1685
  }
1634
1686
  });
1635
- location.values.active = newLayout;
1687
+ handleSetLocation(newLayout);
1636
1688
  return {
1637
1689
  data: true
1638
1690
  };
1639
1691
  });
1640
1692
  }
1641
1693
  // TODO(wittjosiah): Factor out.
1642
- case NavigationAction3.SET: {
1694
+ case NavigationAction4.SET: {
1643
1695
  return batch(() => {
1644
1696
  if (isLayoutParts(intent.data?.activeParts)) {
1645
- location.values.active = intent.data.activeParts;
1697
+ handleSetLocation(intent.data.activeParts);
1646
1698
  }
1647
1699
  return {
1648
1700
  data: true
1649
1701
  };
1650
1702
  });
1651
1703
  }
1652
- case NavigationAction3.ADJUST: {
1704
+ case NavigationAction4.ADJUST: {
1653
1705
  return batch(() => {
1654
1706
  if (isLayoutAdjustment(intent.data)) {
1655
1707
  const adjustment = intent.data;
1656
1708
  if (adjustment.type === "increment-end" || adjustment.type === "increment-start") {
1657
- location.values.active = incrementPlank(location.values.active, {
1709
+ handleSetLocation(incrementPlank(location.values.active, {
1658
1710
  type: adjustment.type,
1659
1711
  layoutCoordinate: adjustment.layoutCoordinate
1660
- });
1712
+ }));
1661
1713
  }
1662
1714
  if (adjustment.type === "solo") {
1663
1715
  const entryId = adjustment.layoutCoordinate.entryId;
@@ -1673,7 +1725,7 @@ var DeckPlugin = ({ observability } = {}) => {
1673
1725
  }
1674
1726
  },
1675
1727
  {
1676
- action: NavigationAction3.OPEN,
1728
+ action: NavigationAction4.OPEN,
1677
1729
  data: {
1678
1730
  activeParts: {
1679
1731
  solo: [
@@ -1697,7 +1749,7 @@ var DeckPlugin = ({ observability } = {}) => {
1697
1749
  }
1698
1750
  },
1699
1751
  {
1700
- action: NavigationAction3.CLOSE,
1752
+ action: NavigationAction4.CLOSE,
1701
1753
  data: {
1702
1754
  activeParts: {
1703
1755
  solo: [
@@ -1707,7 +1759,7 @@ var DeckPlugin = ({ observability } = {}) => {
1707
1759
  }
1708
1760
  },
1709
1761
  {
1710
- action: NavigationAction3.OPEN,
1762
+ action: NavigationAction4.OPEN,
1711
1763
  data: {
1712
1764
  noToggle: true,
1713
1765
  activeParts: {