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