@dxos/plugin-navtree 0.7.4 → 0.7.5-feature-compute.4d9d99a

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