@dxos/plugin-navtree 0.6.13 → 0.6.14-main.1366248

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 (63) hide show
  1. package/dist/lib/browser/{chunk-U7MTKDFQ.mjs → chunk-PSVCPL4T.mjs} +1 -1
  2. package/dist/lib/browser/chunk-PSVCPL4T.mjs.map +7 -0
  3. package/dist/lib/browser/index.mjs +611 -398
  4. package/dist/lib/browser/index.mjs.map +4 -4
  5. package/dist/lib/browser/meta.json +1 -1
  6. package/dist/lib/browser/meta.mjs +1 -1
  7. package/dist/types/src/NavTreePlugin.d.ts.map +1 -1
  8. package/dist/types/src/components/CommandsDialog.d.ts.map +1 -1
  9. package/dist/types/src/components/HaloButton.stories.d.ts +5 -9
  10. package/dist/types/src/components/HaloButton.stories.d.ts.map +1 -1
  11. package/dist/types/src/components/NavBarStart.d.ts.map +1 -1
  12. package/dist/types/src/components/NavTree.d.ts +20 -0
  13. package/dist/types/src/components/NavTree.d.ts.map +1 -0
  14. package/dist/types/src/components/NavTree.stories.d.ts +7 -0
  15. package/dist/types/src/components/NavTree.stories.d.ts.map +1 -0
  16. package/dist/types/src/components/NavTreeContainer.d.ts +8 -8
  17. package/dist/types/src/components/NavTreeContainer.d.ts.map +1 -1
  18. package/dist/types/src/components/NavTreeItemAction.d.ts +23 -0
  19. package/dist/types/src/components/NavTreeItemAction.d.ts.map +1 -0
  20. package/dist/types/src/components/NavTreeItemAction.stories.d.ts +45 -0
  21. package/dist/types/src/components/NavTreeItemAction.stories.d.ts.map +1 -0
  22. package/dist/types/src/components/index.d.ts +1 -0
  23. package/dist/types/src/components/index.d.ts.map +1 -1
  24. package/dist/types/src/experimental/Tree.stories.d.ts +3 -7
  25. package/dist/types/src/experimental/Tree.stories.d.ts.map +1 -1
  26. package/dist/types/src/meta.d.ts.map +1 -1
  27. package/dist/types/src/stories/Graph.stories.d.ts +4 -12
  28. package/dist/types/src/stories/Graph.stories.d.ts.map +1 -1
  29. package/dist/types/src/testing/generator.d.ts +86 -0
  30. package/dist/types/src/testing/generator.d.ts.map +1 -0
  31. package/dist/types/src/testing/index.d.ts +3 -0
  32. package/dist/types/src/testing/index.d.ts.map +1 -0
  33. package/dist/types/src/testing/visitor.d.ts +18 -0
  34. package/dist/types/src/testing/visitor.d.ts.map +1 -0
  35. package/dist/types/src/translations.d.ts +5 -10
  36. package/dist/types/src/translations.d.ts.map +1 -1
  37. package/dist/types/src/types.d.ts +41 -0
  38. package/dist/types/src/types.d.ts.map +1 -0
  39. package/dist/types/src/util.d.ts +8 -9
  40. package/dist/types/src/util.d.ts.map +1 -1
  41. package/package.json +39 -34
  42. package/src/NavTreePlugin.tsx +99 -41
  43. package/src/components/CommandsDialog.tsx +2 -4
  44. package/src/components/HaloButton.stories.tsx +8 -6
  45. package/src/components/NavBarStart.tsx +2 -4
  46. package/src/components/NavTree.stories.tsx +104 -0
  47. package/src/components/NavTree.tsx +127 -0
  48. package/src/components/NavTreeContainer.tsx +132 -302
  49. package/src/components/NavTreeFooter.tsx +1 -1
  50. package/src/components/NavTreeItemAction.stories.tsx +57 -0
  51. package/src/components/NavTreeItemAction.tsx +367 -0
  52. package/src/components/index.ts +1 -0
  53. package/src/experimental/Tree.stories.tsx +11 -8
  54. package/src/experimental/Tree.tsx +2 -2
  55. package/src/meta.ts +3 -1
  56. package/src/stories/Graph.stories.tsx +111 -102
  57. package/src/testing/generator.ts +199 -0
  58. package/src/testing/index.ts +6 -0
  59. package/src/testing/visitor.ts +152 -0
  60. package/src/translations.ts +3 -3
  61. package/src/types.ts +50 -0
  62. package/src/util.ts +52 -63
  63. package/dist/lib/browser/chunk-U7MTKDFQ.mjs.map +0 -7
@@ -2,26 +2,26 @@ import {
2
2
  KEY_BINDING,
3
3
  NAVTREE_PLUGIN,
4
4
  meta_default
5
- } from "./chunk-U7MTKDFQ.mjs";
5
+ } from "./chunk-PSVCPL4T.mjs";
6
6
 
7
7
  // packages/plugins/plugin-navtree/src/NavTreePlugin.tsx
8
- import { MagnifyingGlass as MagnifyingGlass2 } from "@phosphor-icons/react";
9
- import React8 from "react";
10
- import { resolvePlugin, parseIntentPlugin, LayoutAction as LayoutAction4, parseGraphPlugin, NavigationAction as NavigationAction2 } from "@dxos/app-framework";
11
- import { createExtension, isAction as isAction4, isGraphNode } from "@dxos/app-graph";
8
+ import React10 from "react";
9
+ import { resolvePlugin, parseIntentPlugin, LayoutAction as LayoutAction3, parseGraphPlugin, NavigationAction as NavigationAction2, parseNavigationPlugin as parseNavigationPlugin2 } from "@dxos/app-framework";
10
+ import { createExtension, isAction as isAction5, isGraphNode } from "@dxos/app-graph";
11
+ import { invariant } from "@dxos/invariant";
12
12
  import { Keyboard as Keyboard2 } from "@dxos/keyboard";
13
13
  import { LocalStorageStore } from "@dxos/local-storage";
14
- import { Path as Path3 } from "@dxos/react-ui-mosaic";
15
- import { getHostPlatform as getHostPlatform2 } from "@dxos/util";
14
+ import { Path as Path2 } from "@dxos/react-ui-mosaic";
15
+ import { mx as mx5 } from "@dxos/react-ui-theme";
16
+ import { getHostPlatform as getHostPlatform3 } from "@dxos/util";
16
17
 
17
18
  // packages/plugins/plugin-navtree/src/components/CommandsDialog.tsx
18
- import { DotOutline } from "@phosphor-icons/react";
19
19
  import React, { useMemo, useState } from "react";
20
20
  import { useIntentDispatcher, LayoutAction } from "@dxos/app-framework";
21
21
  import { isActionGroup, isAction } from "@dxos/app-graph";
22
22
  import { Keyboard, keySymbols } from "@dxos/keyboard";
23
23
  import { useGraph } from "@dxos/plugin-graph";
24
- import { Button, Dialog, useTranslation, toLocalizedString } from "@dxos/react-ui";
24
+ import { Button, Dialog, Icon, useTranslation, toLocalizedString } from "@dxos/react-ui";
25
25
  import { SearchList } from "@dxos/react-ui-searchlist";
26
26
  import { descriptionText, mx } from "@dxos/react-ui-theme";
27
27
  import { getHostPlatform } from "@dxos/util";
@@ -68,7 +68,6 @@ var CommandsDialogContent = ({ selected: initial }) => {
68
68
  }, actions?.map((action) => {
69
69
  const label = toLocalizedString(action.properties.label, t);
70
70
  const shortcut = typeof action.properties.keyBinding === "string" ? action.properties.keyBinding : action.properties.keyBinding?.[getHostPlatform()];
71
- const Icon = action.properties.icon ?? DotOutline;
72
71
  return /* @__PURE__ */ React.createElement(SearchList.Item, {
73
72
  value: label,
74
73
  key: action.id,
@@ -103,8 +102,8 @@ var CommandsDialogContent = ({ selected: initial }) => {
103
102
  "data-testid": action.properties.testId
104
103
  }
105
104
  }, /* @__PURE__ */ React.createElement(Icon, {
106
- size: 4,
107
- className: mx(!action.properties.icon && "invisible")
105
+ icon: action.properties.icon,
106
+ size: 4
108
107
  }), /* @__PURE__ */ React.createElement("span", {
109
108
  className: "grow truncate"
110
109
  }, label), shortcut && /* @__PURE__ */ React.createElement("span", {
@@ -121,7 +120,6 @@ var CommandsDialogContent = ({ selected: initial }) => {
121
120
  };
122
121
 
123
122
  // packages/plugins/plugin-navtree/src/components/NavBarStart.tsx
124
- import { DotsThreeVertical } from "@phosphor-icons/react";
125
123
  import React2, { Fragment } from "react";
126
124
  import { getGraph } from "@dxos/app-graph";
127
125
  import { Popover, toLocalizedString as toLocalizedString2, useTranslation as useTranslation2 } from "@dxos/react-ui";
@@ -130,16 +128,17 @@ var TREE_ITEM_MAIN_HEADING = "TreeItemMainHeading";
130
128
  var NavBarStart = ({ activeNode, popoverAnchorId }) => {
131
129
  const { t } = useTranslation2(NAVTREE_PLUGIN);
132
130
  const ActionRoot = popoverAnchorId === `dxos.org/ui/${TREE_ITEM_MAIN_HEADING}/${activeNode.id}` || popoverAnchorId === `dxos.org/ui/${KEY_BINDING}/${activeNode.id}` ? Popover.Anchor : Fragment;
133
- const Icon = activeNode.properties?.icon ?? DotsThreeVertical;
134
131
  const graph = getGraph(activeNode);
135
132
  const actions = graph.actions(activeNode);
136
133
  const label = toLocalizedString2(activeNode.properties?.label, t);
137
134
  const menuTriggerLabel = t("node actions menu invoker label");
138
135
  return /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(ActionRoot, null, /* @__PURE__ */ React2.createElement(PlankHeading.ActionsMenu, {
139
- Icon,
136
+ icon: activeNode.properties?.icon ?? "ph--dots-three-vertical--regular",
140
137
  attendableId: activeNode.id,
141
138
  triggerLabel: menuTriggerLabel,
142
- actions,
139
+ actions: [
140
+ actions
141
+ ],
143
142
  onAction: (action) => typeof action.data === "function" && action.data({
144
143
  node: action,
145
144
  caller: TREE_ITEM_MAIN_HEADING
@@ -149,94 +148,412 @@ var NavBarStart = ({ activeNode, popoverAnchorId }) => {
149
148
  }, label));
150
149
  };
151
150
 
151
+ // packages/plugins/plugin-navtree/src/components/NavTree.tsx
152
+ import React4, { Fragment as Fragment2, useCallback, useEffect } from "react";
153
+ import { isAction as isAction2 } from "@dxos/app-graph";
154
+ import { Popover as Popover2, toLocalizedString as toLocalizedString4, Treegrid, useTranslation as useTranslation4 } from "@dxos/react-ui";
155
+ import { Tree } from "@dxos/react-ui-list";
156
+
157
+ // packages/plugins/plugin-navtree/src/components/NavTreeItemAction.tsx
158
+ import { useControllableState } from "@radix-ui/react-use-controllable-state";
159
+ import React3, { useRef, useState as useState2 } from "react";
160
+ import { keySymbols as keySymbols2 } from "@dxos/keyboard";
161
+ import { Button as Button2, Dialog as Dialog2, DropdownMenu, ContextMenu, Tooltip, useTranslation as useTranslation3, toLocalizedString as toLocalizedString3, Icon as Icon2 } from "@dxos/react-ui";
162
+ import { SearchList as SearchList2 } from "@dxos/react-ui-searchlist";
163
+ import { descriptionText as descriptionText2, hoverableControlItem, hoverableOpenControlItem, mx as mx2 } from "@dxos/react-ui-theme";
164
+ import { getHostPlatform as getHostPlatform2 } from "@dxos/util";
165
+ var getShortcut = (action) => {
166
+ return typeof action.properties?.keyBinding === "string" ? action.properties.keyBinding : action.properties?.keyBinding?.[getHostPlatform2()];
167
+ };
168
+ var fallbackIcon = "ph--placeholder--regular";
169
+ var NavTreeItemActionDropdownMenu = ({ label, icon, testId, defaultMenuOpen, menuActions, menuOpen, suppressNextTooltip, onChangeMenuOpen, onAction }) => {
170
+ const { t } = useTranslation3(NAVTREE_PLUGIN);
171
+ const [optionsMenuOpen, setOptionsMenuOpen] = useControllableState({
172
+ prop: menuOpen,
173
+ defaultProp: defaultMenuOpen,
174
+ onChange: onChangeMenuOpen
175
+ });
176
+ return /* @__PURE__ */ React3.createElement(DropdownMenu.Root, {
177
+ open: optionsMenuOpen,
178
+ onOpenChange: (nextOpen) => {
179
+ if (!nextOpen && suppressNextTooltip) {
180
+ suppressNextTooltip.current = true;
181
+ }
182
+ return setOptionsMenuOpen(nextOpen);
183
+ }
184
+ }, /* @__PURE__ */ React3.createElement(Tooltip.Trigger, {
185
+ asChild: true
186
+ }, /* @__PURE__ */ React3.createElement(DropdownMenu.Trigger, {
187
+ asChild: true
188
+ }, /* @__PURE__ */ React3.createElement(Button2, {
189
+ variant: "ghost",
190
+ density: "fine",
191
+ classNames: mx2("shrink-0 !pli-2 pointer-fine:!pli-1", hoverableControlItem, hoverableOpenControlItem),
192
+ "data-testid": testId,
193
+ "aria-label": t("tree item actions label")
194
+ }, /* @__PURE__ */ React3.createElement("span", {
195
+ className: "sr-only"
196
+ }, toLocalizedString3(label, t)), /* @__PURE__ */ React3.createElement(Icon2, {
197
+ icon: icon ?? fallbackIcon,
198
+ size: 4
199
+ })))), /* @__PURE__ */ React3.createElement(DropdownMenu.Portal, null, /* @__PURE__ */ React3.createElement(DropdownMenu.Content, {
200
+ classNames: "z-[31]"
201
+ }, /* @__PURE__ */ React3.createElement(DropdownMenu.Viewport, null, menuActions?.map((action) => {
202
+ const shortcut = getShortcut(action);
203
+ return /* @__PURE__ */ React3.createElement(DropdownMenu.Item, {
204
+ key: action.id,
205
+ onClick: (event) => {
206
+ if (action.properties?.disabled) {
207
+ return;
208
+ }
209
+ event.stopPropagation();
210
+ if (suppressNextTooltip) {
211
+ suppressNextTooltip.current = true;
212
+ }
213
+ setOptionsMenuOpen(false);
214
+ onAction?.(action);
215
+ },
216
+ classNames: "gap-2",
217
+ disabled: action.properties?.disabled,
218
+ ...action.properties?.testId && {
219
+ "data-testid": action.properties.testId
220
+ }
221
+ }, action.properties?.icon && /* @__PURE__ */ React3.createElement(Icon2, {
222
+ icon: action.properties.icon,
223
+ size: 4
224
+ }), /* @__PURE__ */ React3.createElement("span", {
225
+ className: "grow truncate"
226
+ }, toLocalizedString3(action.properties.label, t)), shortcut && /* @__PURE__ */ React3.createElement("span", {
227
+ className: mx2("shrink-0", descriptionText2)
228
+ }, keySymbols2(shortcut).join("")));
229
+ })), /* @__PURE__ */ React3.createElement(DropdownMenu.Arrow, null))));
230
+ };
231
+ var NavTreeItemActionSearchList = ({ menuActions, icon, label, testId, suppressNextTooltip, onAction }) => {
232
+ const { t } = useTranslation3(NAVTREE_PLUGIN);
233
+ const [optionsMenuOpen, setOptionsMenuOpen] = useState2(false);
234
+ const button = useRef(null);
235
+ const sortedActions = menuActions?.sort(({ properties: p1 }, { properties: p2 }) => {
236
+ const t1 = toLocalizedString3(p1.label, t).toLowerCase();
237
+ const t2 = toLocalizedString3(p2.label, t).toLowerCase();
238
+ return t1.localeCompare(t2);
239
+ });
240
+ return /* @__PURE__ */ React3.createElement(Dialog2.Root, {
241
+ open: optionsMenuOpen,
242
+ onOpenChange: (nextOpen) => {
243
+ if (!nextOpen && suppressNextTooltip) {
244
+ suppressNextTooltip.current = true;
245
+ }
246
+ return setOptionsMenuOpen(nextOpen);
247
+ }
248
+ }, /* @__PURE__ */ React3.createElement(Tooltip.Trigger, {
249
+ asChild: true
250
+ }, /* @__PURE__ */ React3.createElement(Dialog2.Trigger, {
251
+ asChild: true
252
+ }, /* @__PURE__ */ React3.createElement(Button2, {
253
+ variant: "ghost",
254
+ density: "fine",
255
+ classNames: mx2("shrink-0 !pli-2 pointer-fine:!pli-1", hoverableControlItem, hoverableOpenControlItem),
256
+ "data-testid": testId,
257
+ onKeyDownCapture: (event) => {
258
+ if (button.current && button.current === event.target) {
259
+ switch (event.key) {
260
+ case "Enter":
261
+ case " ":
262
+ event.stopPropagation();
263
+ setOptionsMenuOpen(true);
264
+ break;
265
+ default:
266
+ }
267
+ }
268
+ },
269
+ ref: button
270
+ }, /* @__PURE__ */ React3.createElement(Icon2, {
271
+ icon: icon ?? fallbackIcon,
272
+ size: 4
273
+ })))), /* @__PURE__ */ React3.createElement(Dialog2.Portal, null, /* @__PURE__ */ React3.createElement(Dialog2.Overlay, null, /* @__PURE__ */ React3.createElement(Dialog2.Content, {
274
+ classNames: "z-[31] is-full max-is-[24rem] pli-2 plb-1"
275
+ }, /* @__PURE__ */ React3.createElement(SearchList2.Root, {
276
+ label: t("tree item searchlist input placeholder")
277
+ }, /* @__PURE__ */ React3.createElement(SearchList2.Input, {
278
+ placeholder: t("tree item searchlist input placeholder"),
279
+ classNames: "pli-3"
280
+ }), /* @__PURE__ */ React3.createElement(SearchList2.Content, {
281
+ classNames: "min-bs-[12rem] bs-[50dvh] max-bs-[30rem] overflow-auto"
282
+ }, sortedActions?.map((action) => {
283
+ const label2 = toLocalizedString3(action.properties.label, t);
284
+ const shortcut = getShortcut(action);
285
+ return /* @__PURE__ */ React3.createElement(SearchList2.Item, {
286
+ // TODO(burdon): Value should be id since label is not unique.
287
+ value: label2,
288
+ key: action.id,
289
+ onSelect: () => {
290
+ if (action.properties?.disabled) {
291
+ return;
292
+ }
293
+ if (suppressNextTooltip) {
294
+ suppressNextTooltip.current = true;
295
+ }
296
+ setOptionsMenuOpen(false);
297
+ onAction?.(action);
298
+ },
299
+ classNames: "flex items-center gap-2 pli-2",
300
+ disabled: action.properties?.disabled,
301
+ ...action.properties?.testId && {
302
+ "data-testid": action.properties.testId
303
+ }
304
+ }, action.properties?.icon && /* @__PURE__ */ React3.createElement(Icon2, {
305
+ icon: action.properties?.icon,
306
+ size: 4
307
+ }), /* @__PURE__ */ React3.createElement("span", {
308
+ className: "grow truncate"
309
+ }, label2), shortcut && /* @__PURE__ */ React3.createElement("span", {
310
+ className: mx2("shrink-0", descriptionText2)
311
+ }, keySymbols2(shortcut).join("")));
312
+ })), /* @__PURE__ */ React3.createElement("div", {
313
+ role: "none",
314
+ className: "flex items-center plb-2 pli-3"
315
+ }, /* @__PURE__ */ React3.createElement("span", {
316
+ className: descriptionText2
317
+ }, toLocalizedString3(label, t))))))));
318
+ };
319
+ var NavTreeItemMonolithicAction = ({ parent, properties: { disabled, caller, testId, label, icon } = {
320
+ label: "never"
321
+ }, data: invoke }) => {
322
+ const { t } = useTranslation3(NAVTREE_PLUGIN);
323
+ return /* @__PURE__ */ React3.createElement(Tooltip.Trigger, {
324
+ asChild: true
325
+ }, /* @__PURE__ */ React3.createElement(Button2, {
326
+ variant: "ghost",
327
+ density: "fine",
328
+ classNames: mx2("shrink-0 !pli-2 pointer-fine:!pli-1", hoverableControlItem, hoverableOpenControlItem),
329
+ disabled,
330
+ onClick: (event) => {
331
+ if (disabled) {
332
+ return;
333
+ }
334
+ event.stopPropagation();
335
+ void invoke?.(caller ? {
336
+ node: parent,
337
+ caller
338
+ } : {
339
+ node: parent
340
+ });
341
+ },
342
+ "data-testid": testId
343
+ }, /* @__PURE__ */ React3.createElement("span", {
344
+ className: "sr-only"
345
+ }, toLocalizedString3(label, t)), /* @__PURE__ */ React3.createElement(Icon2, {
346
+ icon: icon ?? fallbackIcon,
347
+ size: 4
348
+ })));
349
+ };
350
+ var NavTreeItemAction = ({ monolithic, menuActions, parent: node, ...props }) => {
351
+ const { t } = useTranslation3(NAVTREE_PLUGIN);
352
+ const suppressNextTooltip = useRef(false);
353
+ const [triggerTooltipOpen, setTriggerTooltipOpen] = useState2(false);
354
+ const monolithicAction = menuActions?.length === 1 && menuActions[0];
355
+ const baseLabel = toLocalizedString3(monolithicAction ? monolithicAction.properties.label : props.label, t);
356
+ return /* @__PURE__ */ React3.createElement(Tooltip.Root, {
357
+ open: triggerTooltipOpen,
358
+ onOpenChange: (nextOpen) => {
359
+ if (suppressNextTooltip.current) {
360
+ setTriggerTooltipOpen(false);
361
+ suppressNextTooltip.current = false;
362
+ } else {
363
+ setTriggerTooltipOpen(nextOpen);
364
+ }
365
+ }
366
+ }, baseLabel && /* @__PURE__ */ React3.createElement(Tooltip.Portal, null, /* @__PURE__ */ React3.createElement(Tooltip.Content, {
367
+ classNames: "z-[31]",
368
+ side: "bottom"
369
+ }, baseLabel, /* @__PURE__ */ React3.createElement(Tooltip.Arrow, null))), monolithic && menuActions?.length === 1 ? /* @__PURE__ */ React3.createElement(NavTreeItemMonolithicAction, {
370
+ parent: node,
371
+ ...menuActions[0]
372
+ }) : props.menuType === "searchList" ? /* @__PURE__ */ React3.createElement(NavTreeItemActionSearchList, {
373
+ ...props,
374
+ menuActions,
375
+ suppressNextTooltip,
376
+ onAction: (action) => action.data?.(props.caller ? {
377
+ node,
378
+ caller: props.caller
379
+ } : {
380
+ node
381
+ })
382
+ }) : /* @__PURE__ */ React3.createElement(NavTreeItemActionDropdownMenu, {
383
+ ...props,
384
+ parent: node,
385
+ menuActions,
386
+ suppressNextTooltip,
387
+ onAction: (action) => action.data?.(props.caller ? {
388
+ node,
389
+ caller: props.caller
390
+ } : {
391
+ node
392
+ })
393
+ }));
394
+ };
395
+
396
+ // packages/plugins/plugin-navtree/src/components/NavTree.tsx
397
+ var NAV_TREE_ITEM = "NavTreeItem";
398
+ var NavTree = ({ loadDescendents, renderPresence: renderPresence2, popoverAnchorId, ...props }) => {
399
+ const renderColumns = useCallback(({ item, menuOpen, setMenuOpen }) => {
400
+ return /* @__PURE__ */ React4.createElement(NavTreeColumns, {
401
+ item,
402
+ menuOpen,
403
+ setMenuOpen,
404
+ loadDescendents,
405
+ renderPresence: renderPresence2,
406
+ popoverAnchorId
407
+ });
408
+ }, [
409
+ renderPresence2,
410
+ popoverAnchorId,
411
+ loadDescendents
412
+ ]);
413
+ return /* @__PURE__ */ React4.createElement(Tree, {
414
+ ...props,
415
+ draggable: true,
416
+ gridTemplateColumns: "[tree-row-start] 1fr min-content min-content min-content [tree-row-end]",
417
+ classNames: "pbs-1",
418
+ renderColumns
419
+ });
420
+ };
421
+ var NavTreeColumns = ({ item, menuOpen, setMenuOpen, loadDescendents, renderPresence: Presence, popoverAnchorId }) => {
422
+ const { t } = useTranslation4(NAVTREE_PLUGIN);
423
+ const level = item.path.length - 2;
424
+ const [primaryAction, ...secondaryActions] = item.actions.toSorted((a, b) => a.properties?.disposition === "toolbar" ? -1 : 1);
425
+ const actions = (primaryAction?.properties?.disposition === "toolbar" ? secondaryActions : item.actions).flatMap((action) => isAction2(action) ? [
426
+ action
427
+ ] : []).filter((action) => !action.properties?.hidden);
428
+ const ActionRoot = popoverAnchorId === `dxos.org/ui/${NAV_TREE_ITEM}/${item.id}` ? Popover2.Anchor : Fragment2;
429
+ useEffect(() => {
430
+ const frame = requestAnimationFrame(() => {
431
+ void loadDescendents?.(item.node);
432
+ if (primaryAction && !isAction2(primaryAction)) {
433
+ void loadDescendents?.(primaryAction);
434
+ }
435
+ });
436
+ return () => cancelAnimationFrame(frame);
437
+ }, [
438
+ primaryAction
439
+ ]);
440
+ return /* @__PURE__ */ React4.createElement(React4.Fragment, null, primaryAction?.properties?.disposition === "toolbar" ? /* @__PURE__ */ React4.createElement(NavTreeItemAction, {
441
+ testId: primaryAction.properties?.testId,
442
+ label: toLocalizedString4(primaryAction.properties?.label, t),
443
+ icon: primaryAction.properties?.icon ?? "ph--placeholder--regular",
444
+ parent: item.node,
445
+ monolithic: isAction2(primaryAction),
446
+ menuActions: isAction2(primaryAction) ? [
447
+ primaryAction
448
+ ] : item.groupedActions[primaryAction.id],
449
+ menuType: primaryAction.properties?.menuType,
450
+ caller: NAV_TREE_ITEM
451
+ }) : /* @__PURE__ */ React4.createElement(Treegrid.Cell, null), /* @__PURE__ */ React4.createElement(ActionRoot, null, actions.length > 0 ? /* @__PURE__ */ React4.createElement(NavTreeItemAction, {
452
+ testId: `navtree.treeItem.actionsLevel${level}`,
453
+ label: t("tree item actions label"),
454
+ icon: "ph--dots-three-vertical--regular",
455
+ parent: item.node,
456
+ menuActions: actions,
457
+ menuType: "dropdown",
458
+ caller: NAV_TREE_ITEM,
459
+ menuOpen,
460
+ onChangeMenuOpen: setMenuOpen
461
+ }) : /* @__PURE__ */ React4.createElement(Treegrid.Cell, null)), Presence && /* @__PURE__ */ React4.createElement(Presence, {
462
+ item
463
+ }));
464
+ };
465
+
152
466
  // packages/plugins/plugin-navtree/src/components/NavTreeContainer.tsx
153
- import React4, { useCallback, useMemo as useMemo2 } from "react";
154
- import { NavigationAction, LayoutAction as LayoutAction2, Surface, SLUG_PATH_SEPARATOR, SLUG_COLLECTION_INDICATOR, useIntentDispatcher as useIntentDispatcher3 } from "@dxos/app-framework";
155
- import { getGraph as getGraph2, isAction as isAction3, isActionLike } from "@dxos/app-graph";
467
+ import { monitorForElements } from "@atlaskit/pragmatic-drag-and-drop/element/adapter";
468
+ import { extractInstruction } from "@atlaskit/pragmatic-drag-and-drop-hitbox/tree-item";
469
+ import React6, { useCallback as useCallback2, useEffect as useEffect2 } from "react";
470
+ import { NavigationAction, Surface, useIntentDispatcher as useIntentDispatcher3 } from "@dxos/app-framework";
471
+ import { isAction as isAction4, isActionLike } from "@dxos/app-graph";
472
+ import { useGraph as useGraph2 } from "@dxos/plugin-graph";
473
+ import { isEchoObject, isSpace } from "@dxos/react-client/echo";
156
474
  import { ElevationProvider, useMediaQuery, useSidebars as useSidebars2 } from "@dxos/react-ui";
157
- import { Path as Path2 } from "@dxos/react-ui-mosaic";
158
- import { NavTree, getLevel } from "@dxos/react-ui-navtree";
475
+ import { isItem } from "@dxos/react-ui-list";
159
476
  import { arrayMove } from "@dxos/util";
160
477
 
161
478
  // packages/plugins/plugin-navtree/src/components/NavTreeFooter.tsx
162
479
  import { ArrowSquareOut, GearSix, Warning } from "@phosphor-icons/react";
163
480
  import { formatDistance } from "date-fns/formatDistance";
164
- import React3 from "react";
481
+ import React5 from "react";
165
482
  import { SettingsAction, useResolvePlugin, parseNavigationPlugin, useIntentDispatcher as useIntentDispatcher2 } from "@dxos/app-framework";
166
483
  import { useConfig } from "@dxos/react-client";
167
- import { Button as Button2, Tooltip, Popover as Popover2, useSidebars, useTranslation as useTranslation3, Link, Message, Trans, useDefaultValue } from "@dxos/react-ui";
484
+ import { Button as Button3, Tooltip as Tooltip2, Popover as Popover3, useSidebars, useTranslation as useTranslation5, Link, Message, Trans, useDefaultValue } from "@dxos/react-ui";
168
485
  import { PlankHeading as PlankHeading2 } from "@dxos/react-ui-deck";
169
- import { getSize, mx as mx2 } from "@dxos/react-ui-theme";
486
+ import { getSize, mx as mx3 } from "@dxos/react-ui-theme";
170
487
  var buttonStyles = "pli-1.5 text-xs font-normal";
171
488
  var repo = "https://github.com/dxos/dxos";
172
489
  var NavTreeFooter = (props) => {
173
- const layoutPart = useDefaultValue(props.layoutPart, "sidebar");
490
+ const layoutPart = useDefaultValue(props.layoutPart, () => "sidebar");
174
491
  const config = useConfig();
175
- const { t } = useTranslation3(NAVTREE_PLUGIN);
492
+ const { t } = useTranslation5(NAVTREE_PLUGIN);
176
493
  const { navigationSidebarOpen } = useSidebars(NAVTREE_PLUGIN);
177
494
  const dispatch = useIntentDispatcher2();
178
495
  const { version, timestamp, commitHash } = config.values.runtime?.app?.build ?? {};
179
496
  const navigationPlugin = useResolvePlugin(parseNavigationPlugin);
180
497
  const releaseUrl = config.values.runtime?.app?.env?.DX_ENVIRONMENT === "production" ? `${repo}/releases/tag/v${version}` : `${repo}/commit/${commitHash}`;
181
498
  const previewUrl = "https://docs.dxos.org/composer#technology-preview";
182
- return /* @__PURE__ */ React3.createElement("div", {
499
+ return /* @__PURE__ */ React5.createElement("div", {
183
500
  role: "none",
184
- className: mx2("bs-[--rail-size] pbe-[env(safe-area-inset-bottom)] box-content border-separator border-bs pli-1 flex justify-end", layoutPart === "complementary" && "md:justify-end flex-row-reverse")
185
- }, /* @__PURE__ */ React3.createElement(Popover2.Root, null, /* @__PURE__ */ React3.createElement(Popover2.Trigger, {
501
+ className: mx3("bs-[--rail-size] pbe-[env(safe-area-inset-bottom)] box-content border-separator border-bs pli-1 flex justify-end", layoutPart === "complementary" && "md:justify-end flex-row-reverse")
502
+ }, /* @__PURE__ */ React5.createElement(Popover3.Root, null, /* @__PURE__ */ React5.createElement(Popover3.Trigger, {
186
503
  asChild: true
187
- }, /* @__PURE__ */ React3.createElement(Button2, {
504
+ }, /* @__PURE__ */ React5.createElement(Button3, {
188
505
  variant: "ghost",
189
506
  classNames: buttonStyles,
190
507
  ...!navigationSidebarOpen && {
191
508
  tabIndex: -1
192
509
  }
193
- }, "v", version)), /* @__PURE__ */ React3.createElement(Popover2.Portal, null, /* @__PURE__ */ React3.createElement(Popover2.Content, {
510
+ }, "v", version)), /* @__PURE__ */ React5.createElement(Popover3.Portal, null, /* @__PURE__ */ React5.createElement(Popover3.Content, {
194
511
  side: "top",
195
512
  role: "message",
196
513
  classNames: "z-[12] bg-warning-500 max-is-[min(calc(100vw-16px),40ch)]"
197
- }, /* @__PURE__ */ React3.createElement(Message.Root, {
514
+ }, /* @__PURE__ */ React5.createElement(Message.Root, {
198
515
  valence: "warning",
199
516
  className: "rounded-be-none p-5"
200
- }, /* @__PURE__ */ React3.createElement(Message.Title, null, /* @__PURE__ */ React3.createElement(Warning, {
517
+ }, /* @__PURE__ */ React5.createElement(Message.Title, null, /* @__PURE__ */ React5.createElement(Warning, {
201
518
  weight: "duotone",
202
519
  className: "inline mie-2 is-6 bs-6"
203
- }), /* @__PURE__ */ React3.createElement("span", null, t("warning title"))), /* @__PURE__ */ React3.createElement(Message.Body, null, t("technology preview message"), /* @__PURE__ */ React3.createElement("br", null), /* @__PURE__ */ React3.createElement(Link, {
520
+ }), /* @__PURE__ */ React5.createElement("span", null, t("warning title"))), /* @__PURE__ */ React5.createElement(Message.Body, null, t("technology preview message"), /* @__PURE__ */ React5.createElement("br", null), /* @__PURE__ */ React5.createElement(Link, {
204
521
  href: previewUrl,
205
522
  target: "_blank",
206
523
  rel: "noreferrer",
207
524
  variant: "neutral"
208
- }, t("learn more label"), /* @__PURE__ */ React3.createElement(ArrowSquareOut, {
525
+ }, t("learn more label"), /* @__PURE__ */ React5.createElement(ArrowSquareOut, {
209
526
  className: "inline mis-1",
210
527
  weight: "bold"
211
- })))), /* @__PURE__ */ React3.createElement("div", {
528
+ })))), /* @__PURE__ */ React5.createElement("div", {
212
529
  role: "none",
213
530
  className: "plb-4 pli-5 space-b-2 text-baseText"
214
- }, timestamp && /* @__PURE__ */ React3.createElement("p", null, t("released message", {
531
+ }, timestamp && /* @__PURE__ */ React5.createElement("p", null, t("released message", {
215
532
  released: formatDistance(new Date(timestamp), /* @__PURE__ */ new Date(), {
216
533
  addSuffix: true
217
534
  })
218
- }), /* @__PURE__ */ React3.createElement("br", null), /* @__PURE__ */ React3.createElement(Link, {
535
+ }), /* @__PURE__ */ React5.createElement("br", null), /* @__PURE__ */ React5.createElement(Link, {
219
536
  href: releaseUrl,
220
537
  target: "_blank",
221
538
  rel: "noreferrer",
222
539
  variant: "neutral"
223
- }, t("see release label"), /* @__PURE__ */ React3.createElement(ArrowSquareOut, {
540
+ }, t("see release label"), /* @__PURE__ */ React5.createElement(ArrowSquareOut, {
224
541
  className: "inline mis-1",
225
542
  weight: "bold"
226
- }))), /* @__PURE__ */ React3.createElement("p", null, /* @__PURE__ */ React3.createElement(Trans, {
543
+ }))), /* @__PURE__ */ React5.createElement("p", null, /* @__PURE__ */ React5.createElement(Trans, {
227
544
  t,
228
545
  i18nKey: "powered by dxos message",
229
546
  components: {
230
- dxos: /* @__PURE__ */ React3.createElement(Link, {
547
+ dxos: /* @__PURE__ */ React5.createElement(Link, {
231
548
  href: "https://dxos.org",
232
549
  target: "_blank",
233
550
  rel: "noreferrer",
234
551
  variant: "neutral"
235
552
  })
236
553
  }
237
- }))), /* @__PURE__ */ React3.createElement(Popover2.Arrow, null)))), /* @__PURE__ */ React3.createElement(Tooltip.Root, null, /* @__PURE__ */ React3.createElement(Tooltip.Trigger, {
554
+ }))), /* @__PURE__ */ React5.createElement(Popover3.Arrow, null)))), /* @__PURE__ */ React5.createElement(Tooltip2.Root, null, /* @__PURE__ */ React5.createElement(Tooltip2.Trigger, {
238
555
  asChild: true
239
- }, /* @__PURE__ */ React3.createElement(Button2, {
556
+ }, /* @__PURE__ */ React5.createElement(Button3, {
240
557
  variant: "ghost",
241
558
  classNames: buttonStyles,
242
559
  "data-testid": "treeView.openSettings",
@@ -247,13 +564,13 @@ var NavTreeFooter = (props) => {
247
564
  onClick: () => dispatch({
248
565
  action: SettingsAction.OPEN
249
566
  })
250
- }, /* @__PURE__ */ React3.createElement("span", {
567
+ }, /* @__PURE__ */ React5.createElement("span", {
251
568
  className: "sr-only"
252
- }, t("open settings label")), /* @__PURE__ */ React3.createElement(GearSix, {
253
- className: mx2(getSize(4), "rotate-90")
254
- }))), /* @__PURE__ */ React3.createElement(Tooltip.Portal, null, /* @__PURE__ */ React3.createElement(Tooltip.Content, {
569
+ }, t("open settings label")), /* @__PURE__ */ React5.createElement(GearSix, {
570
+ className: mx3(getSize(4), "rotate-90")
571
+ }))), /* @__PURE__ */ React5.createElement(Tooltip2.Portal, null, /* @__PURE__ */ React5.createElement(Tooltip2.Content, {
255
572
  classNames: "z-[12]"
256
- }, t("open settings label"), /* @__PURE__ */ React3.createElement(Tooltip.Arrow, null)))), navigationPlugin?.meta.id === "dxos.org/plugin/deck" && /* @__PURE__ */ React3.createElement(PlankHeading2.Controls, {
573
+ }, t("open settings label"), /* @__PURE__ */ React5.createElement(Tooltip2.Arrow, null)))), navigationPlugin?.meta.id === "dxos.org/plugin/deck" && /* @__PURE__ */ React5.createElement(PlankHeading2.Controls, {
257
574
  variant: "hide-disabled",
258
575
  capabilities: {
259
576
  incrementStart: false,
@@ -265,7 +582,7 @@ var NavTreeFooter = (props) => {
265
582
  };
266
583
 
267
584
  // packages/plugins/plugin-navtree/src/util.ts
268
- import { ACTION_TYPE, ACTION_GROUP_TYPE, isAction as isAction2 } from "@dxos/app-graph";
585
+ import { ACTION_TYPE, ACTION_GROUP_TYPE, isAction as isAction3 } from "@dxos/app-graph";
269
586
  import { Path } from "@dxos/react-ui-mosaic";
270
587
  import { nonNullable } from "@dxos/util";
271
588
  var getParent = (graph, node, path) => {
@@ -289,7 +606,7 @@ var resolveMigrationOperation = (graph, activeNode, destinationPath, destination
289
606
  if (persistenceParent) {
290
607
  const activeKey = activeNode.properties.persistenceKey;
291
608
  if (activeKey && persistenceParent?.properties.acceptPersistenceKey) {
292
- return persistenceParent.properties.acceptPersistenceKey.has(activeKey) && destinationRelatedNode.properties.onTransferStart ? "transfer" : destinationRelatedNode.properties.onCopy ? "copy" : "reject";
609
+ return persistenceParent.properties.acceptPersistenceKey.has(activeKey) && persistenceParent.properties.onTransferStart ? "transfer" : persistenceParent.properties.onCopy ? "copy" : "reject";
293
610
  } else {
294
611
  return "reject";
295
612
  }
@@ -331,8 +648,11 @@ var getChildren = (graph, node, filter, path = []) => {
331
648
  };
332
649
  var getActions = (graph, node) => {
333
650
  return graph.actions(node).reduce((acc, arg) => {
651
+ if (arg.properties.disposition === "item") {
652
+ return acc;
653
+ }
334
654
  acc.actions.push(arg);
335
- if (!isAction2(arg)) {
655
+ if (!isAction3(arg)) {
336
656
  const actionGroup = graph.actions(arg);
337
657
  acc.groupedActions[arg.id] = actionGroup;
338
658
  }
@@ -357,80 +677,65 @@ var expandActions = (graph, node) => {
357
677
  graph.expand(node, "outbound", ACTION_GROUP_TYPE)
358
678
  ]);
359
679
  };
360
- function* navTreeItemVisitor(graph, node, openItemIds, path = [], filter) {
361
- const l0Children = getChildren(graph, node, filter, path);
362
- const { actions: l0Actions, groupedActions: l0GroupedActions } = getActions(graph, node);
680
+ function* navTreeItemVisitor({ graph, node, open, getItem, path = [], filter }) {
363
681
  const stack = [
364
- {
365
- id: node.id,
366
- node,
367
- path: [],
368
- parentOf: (l0Children ?? []).map(({ id }) => id),
369
- actions: l0Actions,
370
- groupedActions: l0GroupedActions
371
- }
682
+ getItem(node, path, filter)
372
683
  ];
373
684
  while (stack.length > 0) {
374
685
  const nextItem = stack.pop();
375
- if ((nextItem.path?.length ?? 0) > 0) {
686
+ if (nextItem.path.length > 1) {
376
687
  yield nextItem;
377
688
  }
378
- const { id, node: node2, path: path2 } = nextItem;
689
+ const { node: node2, path: path2 } = nextItem;
379
690
  const children = getChildren(graph, node2, filter, path2);
380
- if (path2?.length === 0 || (id ?? "never") in openItemIds) {
691
+ const actions = graph.actions(node2);
692
+ if (path2.length === 1 || open.includes(Path.create(...path2))) {
693
+ for (let i = actions.length - 1; i >= 0; i--) {
694
+ if (actions[i].properties.disposition === "item") {
695
+ stack.push(getItem(actions[i], path2, filter));
696
+ }
697
+ }
381
698
  for (let i = children.length - 1; i >= 0; i--) {
382
699
  const child = children[i];
383
- const childPath = path2 ? [
384
- ...path2,
385
- child.id
386
- ] : [
387
- child.id
388
- ];
389
- const childChildren = getChildren(graph, child, filter, childPath);
390
- const { actions: childActions, groupedActions: childGroupedActions } = getActions(graph, child);
391
- stack.push({
392
- id: Path.create(...childPath),
393
- node: child,
394
- path: childPath,
395
- ...(childChildren?.length ?? 0) > 0 && {
396
- parentOf: childChildren.map(({ id: id2 }) => Path.create(...childPath, id2))
397
- },
398
- actions: childActions,
399
- groupedActions: childGroupedActions
400
- });
700
+ stack.push(getItem(child, path2, filter));
401
701
  }
402
702
  }
403
703
  }
404
704
  }
405
- var treeItemsFromRootNode = (graph, rootNode, openItemIds, path = [], filter) => {
406
- return Array.from(navTreeItemVisitor(graph, rootNode, openItemIds, path, filter));
705
+ var treeItemsFromRootNode = (graph, rootNode, open, getItem, path, filter) => {
706
+ return Array.from(navTreeItemVisitor({
707
+ graph,
708
+ node: rootNode,
709
+ open,
710
+ getItem,
711
+ path,
712
+ filter
713
+ }));
407
714
  };
408
- var expandOpenGraphNodes = (graph, openItemIds) => {
409
- return Promise.all(Object.keys(openItemIds).map((openItemId) => {
410
- const node = graph.findNode(Path.last(openItemId));
715
+ var expandOpenGraphNodes = (graph, open) => {
716
+ return Promise.all(open.map((id) => {
717
+ const node = graph.findNode(Path.last(id));
411
718
  return node && expandChildrenAndActions(graph, node);
412
719
  }).filter(nonNullable));
413
720
  };
414
721
 
415
722
  // packages/plugins/plugin-navtree/src/components/NavTreeContainer.tsx
416
723
  var NODE_TYPE = "dxos/app-graph/node";
417
- var renderPresence = (node) => /* @__PURE__ */ React4.createElement(Surface, {
724
+ var renderPresence = ({ item }) => /* @__PURE__ */ React6.createElement(Surface, {
418
725
  role: "presence--glyph",
419
726
  data: {
420
- object: node.data
727
+ object: item.node.data,
728
+ id: item.node.id
421
729
  }
422
730
  });
423
- var NavTreeContainer = ({ root, activeIds, openItemIds, onOpenItemIdsChange, attended, popoverAnchorId }) => {
731
+ var NavTreeContainer = ({ items, current, open, popoverAnchorId, ...props }) => {
424
732
  const { closeNavigationSidebar } = useSidebars2(NAVTREE_PLUGIN);
425
733
  const [isLg] = useMediaQuery("lg", {
426
734
  ssr: false
427
735
  });
428
736
  const dispatch = useIntentDispatcher3();
429
- const graph = useMemo2(() => getGraph2(root), [
430
- root
431
- ]);
432
- const items = treeItemsFromRootNode(graph, root, openItemIds);
433
- const loadDescendents = useCallback((node) => {
737
+ const { graph } = useGraph2();
738
+ const loadDescendents = useCallback2((node) => {
434
739
  void expandActions(graph, node);
435
740
  if (!isActionLike(node)) {
436
741
  void expandChildren(graph, node).then(() => (
@@ -444,279 +749,130 @@ var NavTreeContainer = ({ root, activeIds, openItemIds, onOpenItemIdsChange, att
444
749
  }, [
445
750
  graph
446
751
  ]);
447
- const handleNavigate = async ({ node, actions }) => {
752
+ const canDrop = useCallback2((source, target) => {
753
+ if (isSpace(target.node.data)) {
754
+ return isEchoObject(source.node.data) || isSpace(source.node.data);
755
+ } else if (isEchoObject(target.node.data)) {
756
+ return isEchoObject(source.node.data);
757
+ } else {
758
+ return false;
759
+ }
760
+ }, []);
761
+ const handleSelect = useCallback2(({ node, actions, path }) => {
448
762
  if (!node.data) {
449
763
  return;
450
764
  }
451
- await dispatch({
765
+ if (isAction4(node)) {
766
+ const [parentId] = path.slice(1);
767
+ const parent = items.find(({ id }) => id === parentId)?.node;
768
+ void (parent && node.data({
769
+ node: parent,
770
+ caller: NAV_TREE_ITEM
771
+ }));
772
+ return;
773
+ }
774
+ void dispatch({
452
775
  action: NavigationAction.OPEN,
453
776
  data: {
454
- activeParts: node.data?.comments ? {
455
- main: [
456
- node.id
457
- ],
458
- complementary: [
459
- `${node.id}${SLUG_PATH_SEPARATOR}comments${SLUG_COLLECTION_INDICATOR}`
460
- ]
461
- } : {
777
+ activeParts: {
462
778
  main: [
463
779
  node.id
464
780
  ]
465
781
  }
466
782
  }
467
783
  });
468
- await dispatch({
469
- action: LayoutAction2.SCROLL_INTO_VIEW,
470
- data: {
471
- id: node.id
472
- }
473
- });
474
784
  const defaultAction = actions?.find((action) => action.properties?.disposition === "default");
475
- if (isAction3(defaultAction)) {
785
+ if (isAction4(defaultAction)) {
476
786
  void defaultAction.data();
477
787
  }
478
788
  if (!isLg) {
479
789
  closeNavigationSidebar();
480
790
  }
481
- };
482
- const handleItemOpenChange = ({ id, actions, path }, nextOpen) => {
483
- if (path) {
484
- if (nextOpen) {
485
- onOpenItemIdsChange({
486
- ...openItemIds,
487
- [id]: true
488
- });
489
- } else {
490
- const { [id]: _, ...nextOpenItemIds } = openItemIds;
491
- onOpenItemIdsChange(nextOpenItemIds);
492
- }
493
- }
494
- const defaultAction = actions?.find((action) => action.properties?.disposition === "default");
495
- if (isAction3(defaultAction)) {
496
- void defaultAction.data();
497
- }
498
- };
499
- const resolveItemLevel = useCallback((overPosition, activeId, levelOffset) => {
500
- if (!(typeof overPosition === "number" && activeId)) {
501
- return 1;
502
- } else {
503
- const nextItems = arrayMove(items, items.findIndex(({ id }) => id === activeId), overPosition);
504
- const previousItem = nextItems[overPosition - 1];
505
- const nextItem = nextItems[overPosition + 1];
506
- return Math.min(previousItem ? getLevel(previousItem?.path) + 1 : 1, Math.max(nextItem ? getLevel(nextItem?.path) : 1, getLevel(nextItems[overPosition].path) + levelOffset));
507
- }
508
791
  }, [
509
- items
792
+ items,
793
+ dispatch,
794
+ isLg,
795
+ closeNavigationSidebar
510
796
  ]);
511
- const handleMove = useCallback(({ active, over, details }) => {
512
- const levelOffset = Math.floor((details?.delta?.x ?? 0) / 16);
513
- const overPosition = over.position ?? 0;
514
- const nextItems = arrayMove(items, items.findIndex(({ id }) => id === active.item.id), overPosition);
515
- const previousItem = nextItems[overPosition - 1];
516
- const nextItem = nextItems[overPosition + 1];
517
- const activeNode = "node" in active.item ? active.item.node : void 0;
518
- if (!activeNode || !previousItem || !previousItem.path) {
519
- return {
520
- operation: "reject",
521
- details: {
522
- levelOffset
797
+ useEffect2(() => {
798
+ return monitorForElements({
799
+ canMonitor: ({ source }) => isItem(source.data),
800
+ onDrop: ({ location, source }) => {
801
+ if (!location.current.dropTargets.length) {
802
+ return;
523
803
  }
524
- };
525
- }
526
- const overLevel = resolveItemLevel(overPosition, active.item.id, levelOffset);
527
- const previousLevel = getLevel(previousItem.path);
528
- if (previousLevel === overLevel - 1) {
529
- if (Path2.hasChild(previousItem.id, active.item.id)) {
530
- const operation = previousItem.node.properties.onRearrangeChildren ? "rearrange" : "reject";
531
- return {
532
- operation,
533
- details: {
534
- levelOffset
535
- }
536
- };
537
- } else {
538
- const operation = resolveMigrationOperation(graph, activeNode, previousItem.path, previousItem.node);
539
- return {
540
- operation,
541
- details: {
542
- levelOffset
543
- }
544
- };
545
- }
546
- } else if (previousLevel === overLevel) {
547
- const parent = getParent(graph, previousItem.node, previousItem.path);
548
- const parentPath = previousItem.path.slice(0, previousItem.path.length - 1);
549
- if (Path2.siblings(previousItem.id, active.item.id)) {
550
- const operation = parent?.properties.onRearrangeChildren ? "rearrange" : "reject";
551
- return {
552
- operation,
553
- details: {
554
- levelOffset
555
- }
556
- };
557
- } else {
558
- const operation = resolveMigrationOperation(graph, activeNode, parentPath, parent);
559
- return {
560
- operation,
561
- details: {
562
- levelOffset
563
- }
564
- };
565
- }
566
- } else if (nextItem && nextItem.path) {
567
- const nextLevel = getLevel(nextItem.path);
568
- if (nextLevel === overLevel) {
569
- const parent = getParent(graph, nextItem.node, nextItem.path);
570
- const parentPath = nextItem.path.slice(0, nextItem.path.length - 1);
571
- if (Path2.siblings(nextItem.id, active.item.id)) {
572
- const operation = parent?.properties.onRearrangeChildren ? "rearrange" : "reject";
573
- return {
574
- operation,
575
- details: {
576
- levelOffset
804
+ const target = location.current.dropTargets[0];
805
+ const instruction = extractInstruction(target.data);
806
+ if (instruction !== null && instruction.type !== "instruction-blocked") {
807
+ const sourceNode = source.data.node;
808
+ const targetNode = target.data.node;
809
+ const sourcePath = source.data.path;
810
+ const targetPath = target.data.path;
811
+ const nextItems = instruction.type.startsWith("reorder") ? items.filter((item) => item.path.slice(0, -1).join() === targetPath.slice(0, -1).join()) : items.filter((item) => item.path.slice(0, -1).join() === targetPath.join());
812
+ const operation = sourcePath.slice(0, -1).join() === targetPath.slice(0, -1).join() && instruction.type !== "make-child" ? "rearrange" : resolveMigrationOperation(graph, sourceNode, targetPath, targetNode);
813
+ const sourceParent = getParent(graph, sourceNode, sourcePath);
814
+ const targetParent = getParent(graph, targetNode, targetPath);
815
+ const sourceIndex = nextItems.findIndex(({ id }) => id === sourceNode.id);
816
+ const targetIndex = nextItems.findIndex(({ id }) => id === targetNode.id);
817
+ const migrationIndex = instruction.type === "make-child" ? nextItems.length > 0 ? nextItems.length - 1 : 0 : instruction.type === "reorder-below" ? targetIndex + 1 : targetIndex;
818
+ switch (operation) {
819
+ case "rearrange": {
820
+ arrayMove(nextItems, sourceIndex, targetIndex);
821
+ void sourceParent?.properties.onRearrangeChildren?.(nextItems.map((item) => item.node.data));
822
+ break;
577
823
  }
578
- };
579
- } else {
580
- const operation = resolveMigrationOperation(graph, activeNode, parentPath, parent);
581
- return {
582
- operation,
583
- details: {
584
- levelOffset
824
+ case "copy": {
825
+ const target2 = instruction.type === "make-child" ? targetNode : targetParent;
826
+ void target2?.properties.onCopy?.(sourceNode, migrationIndex);
827
+ break;
828
+ }
829
+ case "transfer": {
830
+ const target2 = instruction.type === "make-child" ? targetNode : targetParent;
831
+ if (!target2?.properties.onTransferStart || !sourceParent?.properties.onTransferEnd) {
832
+ break;
833
+ }
834
+ void target2?.properties.onTransferStart(sourceNode, migrationIndex);
835
+ void sourceParent?.properties.onTransferEnd?.(sourceNode, target2);
836
+ break;
585
837
  }
586
- };
587
- }
588
- } else {
589
- return {
590
- operation: "reject",
591
- details: {
592
- levelOffset
593
- }
594
- };
595
- }
596
- } else {
597
- return {
598
- operation: "reject",
599
- details: {
600
- levelOffset
601
- }
602
- };
603
- }
604
- }, [
605
- root,
606
- items
607
- ]);
608
- const handleDrop = useCallback(({ operation, active, over, details = {} }) => {
609
- if (Path2.first(over.path) !== root.id) {
610
- return void 0;
611
- }
612
- const { levelOffset = 0 } = details;
613
- const overPosition = over.position ?? 0;
614
- const nextItems = arrayMove(items, items.findIndex(({ id }) => id === active.item.id), overPosition);
615
- const activeNode = "node" in active.item ? active.item.node : void 0;
616
- const activeParentId = Path2.parent(active.item.id);
617
- if (!activeNode) {
618
- return void 0;
619
- }
620
- const activeParent = getParent(graph, activeNode, active.item.path ?? []);
621
- if (operation === "rearrange") {
622
- void activeParent?.properties.onRearrangeChildren?.(nextItems.filter(({ id }) => Path2.hasChild(activeParentId, id)).map(({ node }) => node.data));
623
- return null;
624
- } else {
625
- const previousItem = nextItems[overPosition - 1];
626
- const nextItem = nextItems[overPosition + 1];
627
- const overLevel = resolveItemLevel(overPosition, active.item.id, levelOffset);
628
- const previousLevel = getLevel(previousItem.path);
629
- if (operation === "copy") {
630
- if (previousLevel === overLevel - 1) {
631
- void previousItem.node.properties.onCopy?.(activeNode, 0);
632
- return null;
633
- } else if (previousLevel === overLevel) {
634
- const parent = getParent(graph, previousItem.node, previousItem.path ?? []);
635
- void parent?.properties.onCopy?.(activeNode, getChildren(graph, parent).findIndex(({ id }) => id === previousItem.node.id) + 1);
636
- return null;
637
- } else if (nextItem && nextItem.path) {
638
- const parent = getParent(graph, nextItem.node, nextItem.path ?? []);
639
- void parent?.properties.onCopy?.(activeNode, getChildren(graph, parent).findIndex(({ id }) => id === nextItem.node.id));
640
- return null;
641
- }
642
- } else if (operation === "transfer") {
643
- const onTransferEnd = activeParent?.properties.onTransferEnd;
644
- if (!onTransferEnd) {
645
- return void 0;
646
- } else if (previousLevel === overLevel - 1) {
647
- const onTransferStart = previousItem.node.properties.onTransferStart;
648
- if (onTransferStart) {
649
- void onTransferEnd(activeNode, previousItem.node);
650
- void onTransferStart(activeNode, 0);
651
- return null;
652
- }
653
- } else if (previousLevel === overLevel && previousItem.path) {
654
- const parent = getParent(graph, previousItem.node, previousItem.path);
655
- if (parent?.properties.onTransferStart) {
656
- void onTransferEnd(activeNode, previousItem.node);
657
- void parent.properties.onTransferStart(activeNode, getChildren(graph, parent).findIndex(({ id }) => id === previousItem.node.id) + 1);
658
- return null;
659
- }
660
- } else if (nextItem && nextItem.path) {
661
- const parent = getParent(graph, nextItem.node, nextItem.path);
662
- if (parent?.properties.onTransferStart) {
663
- void onTransferEnd(activeNode, previousItem.node);
664
- void parent.properties.onTransferStart(activeNode, getChildren(graph, parent).findIndex(({ id }) => id === nextItem.node.id));
665
- return null;
666
838
  }
667
839
  }
668
840
  }
669
- }
670
- return void 0;
671
- }, [
672
- root,
673
- items
674
- ]);
675
- const handleDragEnd = useCallback(() => {
676
- onOpenItemIdsChange({
677
- ...openItemIds
678
841
  });
679
842
  }, [
680
- onOpenItemIdsChange,
681
- openItemIds
843
+ items
682
844
  ]);
683
- return /* @__PURE__ */ React4.createElement(ElevationProvider, {
845
+ return /* @__PURE__ */ React6.createElement(ElevationProvider, {
684
846
  elevation: "chrome"
685
- }, /* @__PURE__ */ React4.createElement("div", {
847
+ }, /* @__PURE__ */ React6.createElement("div", {
686
848
  role: "none",
687
849
  className: "bs-full overflow-hidden row-span-3 grid grid-cols-1 grid-rows-[min-content_1fr_min-content]"
688
- }, /* @__PURE__ */ React4.createElement(Surface, {
850
+ }, /* @__PURE__ */ React6.createElement(Surface, {
689
851
  role: "search-input",
690
852
  limit: 1
691
- }), /* @__PURE__ */ React4.createElement("div", {
853
+ }), /* @__PURE__ */ React6.createElement("div", {
692
854
  role: "none",
693
855
  className: "!overflow-y-auto"
694
- }, /* @__PURE__ */ React4.createElement(NavTree, {
695
- id: root.id,
856
+ }, /* @__PURE__ */ React6.createElement(NavTree, {
696
857
  items,
697
- current: activeIds,
698
- attended,
699
- type: NODE_TYPE,
700
- open: openItemIds,
701
- onNavigate: handleNavigate,
702
- onItemOpenChange: handleItemOpenChange,
703
- onMove: handleMove,
704
- onDrop: handleDrop,
705
- onDragEnd: handleDragEnd,
706
- popoverAnchorId,
858
+ open,
859
+ current,
860
+ loadDescendents,
707
861
  renderPresence,
708
- resolveItemLevel,
709
- loadDescendents
710
- })), /* @__PURE__ */ React4.createElement(NavTreeFooter, null)));
862
+ popoverAnchorId,
863
+ canDrop,
864
+ onSelect: handleSelect,
865
+ ...props
866
+ })), /* @__PURE__ */ React6.createElement(NavTreeFooter, null)));
711
867
  };
712
868
 
713
869
  // packages/plugins/plugin-navtree/src/components/NavTreeDocumentTitle.tsx
714
- import { useEffect } from "react";
715
- import { toLocalizedString as toLocalizedString3, useTranslation as useTranslation4 } from "@dxos/react-ui";
870
+ import { useEffect as useEffect3 } from "react";
871
+ import { toLocalizedString as toLocalizedString5, useTranslation as useTranslation6 } from "@dxos/react-ui";
716
872
  var NavTreeDocumentTitle = ({ node }) => {
717
- const { t } = useTranslation4(NAVTREE_PLUGIN);
718
- useEffect(() => {
719
- document.title = node ? toLocalizedString3(node.properties.label, t) : t("current app name", {
873
+ const { t } = useTranslation6(NAVTREE_PLUGIN);
874
+ useEffect3(() => {
875
+ document.title = node ? toLocalizedString5(node.properties.label, t) : t("current app name", {
720
876
  ns: "appkit"
721
877
  });
722
878
  }, [
@@ -726,37 +882,37 @@ var NavTreeDocumentTitle = ({ node }) => {
726
882
  };
727
883
 
728
884
  // packages/plugins/plugin-navtree/src/components/NotchStart.tsx
729
- import React6 from "react";
885
+ import React8 from "react";
730
886
  import { useIntentDispatcher as useIntentDispatcher4, useResolvePlugin as useResolvePlugin2 } from "@dxos/app-framework";
731
887
  import { ClientAction } from "@dxos/plugin-client/meta";
732
888
  import { parseObservabilityPlugin } from "@dxos/plugin-observability";
733
889
  import { useIdentity } from "@dxos/react-client/halo";
734
890
 
735
891
  // packages/plugins/plugin-navtree/src/components/HaloButton.tsx
736
- import React5 from "react";
892
+ import React7 from "react";
737
893
  import { ConnectionState, useNetworkStatus } from "@dxos/react-client/mesh";
738
894
  import { Avatar } from "@dxos/react-ui";
739
- import { focusRing, mx as mx3 } from "@dxos/react-ui-theme";
895
+ import { focusRing, mx as mx4 } from "@dxos/react-ui-theme";
740
896
  import { hexToFallback } from "@dxos/util";
741
897
  var INTERNAL = "https://avatars.githubusercontent.com/u/57182821";
742
898
  var HaloButton = (props) => {
743
899
  const { onClick, identityKey, internal, size = 8 } = props;
744
900
  const fallbackValue = hexToFallback(identityKey ?? "0");
745
901
  const { swarm: connectionState } = useNetworkStatus();
746
- return /* @__PURE__ */ React5.createElement("button", {
747
- className: mx3(focusRing, "rounded grid place-items-center"),
902
+ return /* @__PURE__ */ React7.createElement("button", {
903
+ className: mx4(focusRing, "rounded grid place-items-center"),
748
904
  onClick
749
- }, /* @__PURE__ */ React5.createElement(Avatar.Root, {
905
+ }, /* @__PURE__ */ React7.createElement(Avatar.Root, {
750
906
  size,
751
907
  variant: "circle",
752
908
  status: connectionState === ConnectionState.OFFLINE ? "error" : internal ? "internal" : "active",
753
909
  hue: props.hue || fallbackValue.hue
754
- }, /* @__PURE__ */ React5.createElement(Avatar.Frame, {
910
+ }, /* @__PURE__ */ React7.createElement(Avatar.Frame, {
755
911
  "data-testid": "treeView.haloButton",
756
912
  "data-joyride": "welcome/halo"
757
- }, internal ? /* @__PURE__ */ React5.createElement(Avatar.Image, {
913
+ }, internal ? /* @__PURE__ */ React7.createElement(Avatar.Image, {
758
914
  href: INTERNAL
759
- }) : /* @__PURE__ */ React5.createElement(Avatar.Fallback, {
915
+ }) : /* @__PURE__ */ React7.createElement(Avatar.Fallback, {
760
916
  text: props.emoji || fallbackValue.emoji
761
917
  }))));
762
918
  };
@@ -766,7 +922,7 @@ var NotchStart = () => {
766
922
  const identity = useIdentity();
767
923
  const observabilityPlugin = useResolvePlugin2(parseObservabilityPlugin);
768
924
  const dispatch = useIntentDispatcher4();
769
- return /* @__PURE__ */ React6.createElement(HaloButton, {
925
+ return /* @__PURE__ */ React8.createElement(HaloButton, {
770
926
  size: 8,
771
927
  identityKey: identity?.identityKey.toHex(),
772
928
  hue: identity?.profile?.data?.hue,
@@ -780,32 +936,31 @@ var NotchStart = () => {
780
936
 
781
937
  // packages/plugins/plugin-navtree/src/components/CommandsTrigger.tsx
782
938
  import { MagnifyingGlass } from "@phosphor-icons/react";
783
- import React7 from "react";
784
- import { LayoutAction as LayoutAction3, useIntent } from "@dxos/app-framework";
785
- import { Button as Button3, useTranslation as useTranslation5 } from "@dxos/react-ui";
939
+ import React9 from "react";
940
+ import { LayoutAction as LayoutAction2, useIntent } from "@dxos/app-framework";
941
+ import { Button as Button4, useTranslation as useTranslation7 } from "@dxos/react-ui";
786
942
  import { getSize as getSize2 } from "@dxos/react-ui-theme";
787
943
  var CommandsTrigger = () => {
788
944
  const { dispatch } = useIntent();
789
- const { t } = useTranslation5(NAVTREE_PLUGIN);
790
- return /* @__PURE__ */ React7.createElement(Button3, {
945
+ const { t } = useTranslation7(NAVTREE_PLUGIN);
946
+ return /* @__PURE__ */ React9.createElement(Button4, {
791
947
  classNames: "pis-3 pie-2 gap-2 mli-1 mbs-1 min-bs-0 bs-[--rail-action] justify-start",
792
948
  onClick: () => dispatch({
793
- action: LayoutAction3.SET_LAYOUT,
949
+ action: LayoutAction2.SET_LAYOUT,
794
950
  data: {
795
951
  element: "dialog",
796
952
  component: `${NAVTREE_PLUGIN}/Commands`,
797
953
  dialogBlockAlign: "start"
798
954
  }
799
955
  })
800
- }, /* @__PURE__ */ React7.createElement("span", {
956
+ }, /* @__PURE__ */ React9.createElement("span", {
801
957
  className: "text-description font-normal grow text-start"
802
- }, t("command list input placeholder")), /* @__PURE__ */ React7.createElement(MagnifyingGlass, {
958
+ }, t("command list input placeholder")), /* @__PURE__ */ React9.createElement(MagnifyingGlass, {
803
959
  className: getSize2(5)
804
960
  }));
805
961
  };
806
962
 
807
963
  // packages/plugins/plugin-navtree/src/translations.ts
808
- import { translations as navtreeTranslations } from "@dxos/react-ui-navtree";
809
964
  var translations_default = [
810
965
  {
811
966
  "en-US": {
@@ -820,59 +975,125 @@ var translations_default = [
820
975
  "learn more label": "Learn more",
821
976
  "released message": "This version released {{released}}.",
822
977
  "see release label": "See release on GitHub",
823
- "powered by dxos message": "Powered by <dxos>DXOS</dxos>"
978
+ "powered by dxos message": "Powered by <dxos>DXOS</dxos>",
979
+ "tree item actions label": "More actions",
980
+ "tree item searchlist input placeholder": "Search for actions\u2026",
981
+ "empty branch message": "\xA0"
824
982
  }
825
983
  }
826
- },
827
- ...navtreeTranslations
984
+ }
828
985
  ];
829
986
 
830
987
  // packages/plugins/plugin-navtree/src/NavTreePlugin.tsx
988
+ var __dxlog_file = "/home/runner/work/dxos/dxos/packages/plugins/plugin-navtree/src/NavTreePlugin.tsx";
831
989
  var NavTreePlugin = () => {
990
+ let graphPlugin;
991
+ let graph;
992
+ const itemCache = /* @__PURE__ */ new Map();
832
993
  const state = new LocalStorageStore("dxos.org/settings/navtree", {
994
+ root: void 0,
995
+ get flatTree() {
996
+ if (!this.root || !graph) {
997
+ return [];
998
+ }
999
+ return treeItemsFromRootNode(graph, this.root, this.open, getItem);
1000
+ },
833
1001
  // TODO(thure): Do this dynamically.
834
- openItemIds: {
835
- root: true,
836
- "dxos.org/plugin/space-spaces": true,
837
- "dxos.org/plugin/files": true
838
- }
1002
+ open: [
1003
+ "root",
1004
+ "root~dxos.org/plugin/space-spaces",
1005
+ "root~dxos.org/plugin/files"
1006
+ ]
839
1007
  });
840
- let graphPlugin;
841
- let graph;
842
- const handleOpenItemIdsChange = (nextOpenItemIds) => {
843
- state.values.openItemIds = nextOpenItemIds;
1008
+ const getItem = (node, parent, filter) => {
1009
+ invariant(graph, void 0, {
1010
+ F: __dxlog_file,
1011
+ L: 82,
1012
+ S: void 0,
1013
+ A: [
1014
+ "graph",
1015
+ ""
1016
+ ]
1017
+ });
1018
+ const path = [
1019
+ ...parent,
1020
+ node.id
1021
+ ];
1022
+ const { actions, groupedActions } = getActions(graph, node);
1023
+ const children = getChildren(graph, node, filter, path);
1024
+ const parentOf = children.length > 0 ? children.map(({ id }) => id) : node.properties.role === "branch" ? [] : void 0;
1025
+ const item = {
1026
+ id: node.id,
1027
+ label: node.properties.label ?? node.id,
1028
+ icon: node.properties.icon,
1029
+ disabled: node.properties.disabled,
1030
+ testId: node.properties.testId,
1031
+ className: mx5(node.properties.modified && "italic", node.properties.className),
1032
+ headingClassName: node.properties.headingClassName,
1033
+ path,
1034
+ parentOf,
1035
+ node,
1036
+ actions,
1037
+ groupedActions
1038
+ };
1039
+ const cachedItem = itemCache.get(node.id);
1040
+ if (cachedItem && JSON.stringify(item) === JSON.stringify(cachedItem)) {
1041
+ return cachedItem;
1042
+ } else {
1043
+ itemCache.set(node.id, item);
1044
+ return item;
1045
+ }
1046
+ };
1047
+ const handleOpenChange = (item, open) => {
1048
+ const path = Path2.create(...item.path);
1049
+ if (open) {
1050
+ state.values.open.push(path);
1051
+ } else {
1052
+ const index = state.values.open.indexOf(path);
1053
+ if (index > -1) {
1054
+ state.values.open.splice(index, 1);
1055
+ }
1056
+ }
844
1057
  if (graph) {
845
- void expandOpenGraphNodes(graph, nextOpenItemIds);
1058
+ void expandOpenGraphNodes(graph, state.values.open);
846
1059
  }
847
1060
  };
848
1061
  return {
849
1062
  meta: meta_default,
850
1063
  ready: async (plugins) => {
1064
+ state.prop({
1065
+ key: "open",
1066
+ type: LocalStorageStore.json()
1067
+ });
851
1068
  graphPlugin = resolvePlugin(plugins, parseGraphPlugin);
852
1069
  graph = graphPlugin?.provides.graph;
853
1070
  if (!graph) {
854
1071
  return;
855
1072
  }
1073
+ const dispatch = resolvePlugin(plugins, parseIntentPlugin)?.provides.intent.dispatch;
1074
+ const soloPart = resolvePlugin(plugins, parseNavigationPlugin2)?.provides.location.active.solo?.[0];
1075
+ if (dispatch && soloPart) {
1076
+ void dispatch({
1077
+ plugin: NAVTREE_PLUGIN,
1078
+ action: NavigationAction2.EXPOSE,
1079
+ data: {
1080
+ id: soloPart.id
1081
+ }
1082
+ });
1083
+ }
856
1084
  state.values.root = graph.root;
857
- getChildren(graph, state.values.root);
858
- getActions(graph, state.values.root);
859
- state.prop({
860
- key: "openItemIds",
861
- storageKey: "openItemIds",
862
- type: LocalStorageStore.json()
863
- });
864
- void expandOpenGraphNodes(graph, state.values.openItemIds);
1085
+ void expandOpenGraphNodes(graph, state.values.open);
865
1086
  graph.subscribeTraverse({
866
1087
  visitor: (node, path) => {
867
1088
  let shortcut;
868
1089
  if (typeof node.properties.keyBinding === "object") {
869
1090
  const availablePlatforms = Object.keys(node.properties.keyBinding);
870
- const platform = getHostPlatform2();
1091
+ const platform = getHostPlatform3();
871
1092
  shortcut = availablePlatforms.includes(platform) ? node.properties.keyBinding[platform] : platform === "ios" ? node.properties.keyBinding.macos : platform === "linux" || platform === "unknown" ? node.properties.keyBinding.windows : void 0;
872
1093
  } else {
873
1094
  shortcut = node.properties.keyBinding;
874
1095
  }
875
- if (shortcut && isAction4(node)) {
1096
+ if (shortcut && isAction5(node)) {
876
1097
  Keyboard2.singleton.getContext(path.slice(0, -1).join("/")).bind({
877
1098
  shortcut,
878
1099
  handler: () => {
@@ -917,33 +1138,29 @@ var NavTreePlugin = () => {
917
1138
  switch (data.component) {
918
1139
  case `${NAVTREE_PLUGIN}/Commands`: {
919
1140
  const selected = typeof data.subject === "string" ? data.subject : void 0;
920
- return /* @__PURE__ */ React8.createElement(CommandsDialogContent, {
1141
+ return /* @__PURE__ */ React10.createElement(CommandsDialogContent, {
921
1142
  selected
922
1143
  });
923
1144
  }
924
1145
  }
925
1146
  switch (role) {
926
1147
  case "navigation":
927
- if (state.values.root && state.values.openItemIds) {
928
- return /* @__PURE__ */ React8.createElement(NavTreeContainer, {
929
- root: state.values.root,
930
- activeIds: data.activeIds,
931
- openItemIds: state.values.openItemIds,
932
- onOpenItemIdsChange: handleOpenItemIdsChange,
933
- attended: data.attended,
934
- popoverAnchorId: data.popoverAnchorId
935
- });
936
- }
937
- break;
1148
+ return /* @__PURE__ */ React10.createElement(NavTreeContainer, {
1149
+ items: state.values.flatTree,
1150
+ current: data.activeIds,
1151
+ open: state.values.open,
1152
+ onOpenChange: handleOpenChange,
1153
+ popoverAnchorId: data.popoverAnchorId
1154
+ });
938
1155
  case "document-title": {
939
- return /* @__PURE__ */ React8.createElement(NavTreeDocumentTitle, {
1156
+ return /* @__PURE__ */ React10.createElement(NavTreeDocumentTitle, {
940
1157
  node: isGraphNode(data.activeNode) ? data.activeNode : void 0
941
1158
  });
942
1159
  }
943
1160
  case "navbar-start": {
944
1161
  if (state.values.root && data.activeNode) {
945
1162
  return {
946
- node: /* @__PURE__ */ React8.createElement(NavBarStart, {
1163
+ node: /* @__PURE__ */ React10.createElement(NavBarStart, {
947
1164
  activeNode: data.activeNode,
948
1165
  popoverAnchorId: data.popoverAnchorId
949
1166
  }),
@@ -953,10 +1170,10 @@ var NavTreePlugin = () => {
953
1170
  break;
954
1171
  }
955
1172
  case "notch-start":
956
- return /* @__PURE__ */ React8.createElement(NotchStart, null);
1173
+ return /* @__PURE__ */ React10.createElement(NotchStart, null);
957
1174
  case "search-input":
958
1175
  return {
959
- node: /* @__PURE__ */ React8.createElement(CommandsTrigger, null),
1176
+ node: /* @__PURE__ */ React10.createElement(CommandsTrigger, null),
960
1177
  disposition: "fallback"
961
1178
  };
962
1179
  }
@@ -973,18 +1190,15 @@ var NavTreePlugin = () => {
973
1190
  });
974
1191
  if (Array.isArray(path)) {
975
1192
  const additionalOpenItems = [
976
- ...Array(path.length - 1)
1193
+ ...Array(path.length)
977
1194
  ].reduce((acc, _, index) => {
978
- const itemId = Path3.create(...path.slice(1, index + 1));
979
- if (itemId.length > 0) {
980
- acc[itemId] = true;
1195
+ const itemId = Path2.create(...path.slice(0, index));
1196
+ if (itemId.length > 0 && !state.values.open.includes(itemId)) {
1197
+ acc.push(itemId);
981
1198
  }
982
1199
  return acc;
983
- }, {});
984
- state.values.openItemIds = {
985
- ...additionalOpenItems,
986
- ...state.values.openItemIds
987
- };
1200
+ }, []);
1201
+ state.values.open.push(...additionalOpenItems);
988
1202
  }
989
1203
  }
990
1204
  break;
@@ -1004,7 +1218,7 @@ var NavTreePlugin = () => {
1004
1218
  id: "dxos.org/plugin/navtree/open-commands",
1005
1219
  data: async () => {
1006
1220
  await intentPlugin?.provides.intent.dispatch({
1007
- action: LayoutAction4.SET_LAYOUT,
1221
+ action: LayoutAction3.SET_LAYOUT,
1008
1222
  data: {
1009
1223
  element: "dialog",
1010
1224
  component: `${NAVTREE_PLUGIN}/Commands`,
@@ -1019,8 +1233,7 @@ var NavTreePlugin = () => {
1019
1233
  ns: NAVTREE_PLUGIN
1020
1234
  }
1021
1235
  ],
1022
- icon: (props) => /* @__PURE__ */ React8.createElement(MagnifyingGlass2, props),
1023
- iconSymbol: "ph--magnifying-glass--regular",
1236
+ icon: "ph--magnifying-glass--regular",
1024
1237
  keyBinding: {
1025
1238
  macos: "meta+k",
1026
1239
  windows: "ctrl+k"