@dxos/plugin-navtree 0.8.4-main.3f58842 → 0.8.4-main.4a85c3132b

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 (238) hide show
  1. package/dist/lib/browser/CommandsDialogContent-A27AKTHH.mjs +111 -0
  2. package/dist/lib/browser/CommandsDialogContent-A27AKTHH.mjs.map +7 -0
  3. package/dist/lib/browser/CommandsTrigger-HBZYQCGV.mjs +33 -0
  4. package/dist/lib/browser/CommandsTrigger-HBZYQCGV.mjs.map +7 -0
  5. package/dist/lib/browser/NavTreeContainer-B5K4FUJS.mjs +12 -0
  6. package/dist/lib/browser/NavTreeContainer-B5K4FUJS.mjs.map +7 -0
  7. package/dist/lib/browser/NavTreeDocumentTitle-GEE3URWH.mjs +26 -0
  8. package/dist/lib/browser/NavTreeDocumentTitle-GEE3URWH.mjs.map +7 -0
  9. package/dist/lib/browser/app-graph-builder-XGA4GPGL.mjs +44 -0
  10. package/dist/lib/browser/app-graph-builder-XGA4GPGL.mjs.map +7 -0
  11. package/dist/lib/browser/chunk-DQCYMXEU.mjs +1426 -0
  12. package/dist/lib/browser/chunk-DQCYMXEU.mjs.map +7 -0
  13. package/dist/lib/browser/chunk-H3OJ4WLF.mjs +14 -0
  14. package/dist/lib/browser/chunk-H3OJ4WLF.mjs.map +7 -0
  15. package/dist/lib/browser/chunk-X2HDG62A.mjs +23 -0
  16. package/dist/lib/browser/chunk-X2HDG62A.mjs.map +7 -0
  17. package/dist/lib/browser/chunk-YKTYPINZ.mjs +19 -0
  18. package/dist/lib/browser/chunk-YKTYPINZ.mjs.map +7 -0
  19. package/dist/lib/browser/index.mjs +88 -96
  20. package/dist/lib/browser/index.mjs.map +4 -4
  21. package/dist/lib/browser/{keyboard-QRS6WOQH.mjs → keyboard-OJZC54PK.mjs} +22 -19
  22. package/dist/lib/browser/keyboard-OJZC54PK.mjs.map +7 -0
  23. package/dist/lib/browser/meta.json +1 -1
  24. package/dist/lib/browser/operation-resolver-BNAMYOHF.mjs +53 -0
  25. package/dist/lib/browser/operation-resolver-BNAMYOHF.mjs.map +7 -0
  26. package/dist/lib/browser/react-surface-AYHOAJ4I.mjs +59 -0
  27. package/dist/lib/browser/react-surface-AYHOAJ4I.mjs.map +7 -0
  28. package/dist/lib/browser/state-AC3EETN7.mjs +131 -0
  29. package/dist/lib/browser/state-AC3EETN7.mjs.map +7 -0
  30. package/dist/types/src/NavTreePlugin.d.ts +2 -1
  31. package/dist/types/src/NavTreePlugin.d.ts.map +1 -1
  32. package/dist/types/src/capabilities/app-graph-builder/app-graph-builder.d.ts +6 -0
  33. package/dist/types/src/capabilities/app-graph-builder/app-graph-builder.d.ts.map +1 -0
  34. package/dist/types/src/capabilities/app-graph-builder/index.d.ts +3 -0
  35. package/dist/types/src/capabilities/app-graph-builder/index.d.ts.map +1 -0
  36. package/dist/types/src/capabilities/index.d.ts +5 -105
  37. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  38. package/dist/types/src/capabilities/keyboard/index.d.ts +3 -0
  39. package/dist/types/src/capabilities/keyboard/index.d.ts.map +1 -0
  40. package/dist/types/src/capabilities/keyboard/keyboard.d.ts +5 -0
  41. package/dist/types/src/capabilities/keyboard/keyboard.d.ts.map +1 -0
  42. package/dist/types/src/capabilities/operation-resolver/index.d.ts +3 -0
  43. package/dist/types/src/capabilities/operation-resolver/index.d.ts.map +1 -0
  44. package/dist/types/src/capabilities/operation-resolver/operation-resolver.d.ts +5 -0
  45. package/dist/types/src/capabilities/operation-resolver/operation-resolver.d.ts.map +1 -0
  46. package/dist/types/src/capabilities/react-surface/index.d.ts +3 -0
  47. package/dist/types/src/capabilities/react-surface/index.d.ts.map +1 -0
  48. package/dist/types/src/capabilities/react-surface/react-surface.d.ts +5 -0
  49. package/dist/types/src/capabilities/react-surface/react-surface.d.ts.map +1 -0
  50. package/dist/types/src/capabilities/state/index.d.ts +3 -0
  51. package/dist/types/src/capabilities/state/index.d.ts.map +1 -0
  52. package/dist/types/src/capabilities/state/state.d.ts +6 -0
  53. package/dist/types/src/capabilities/state/state.d.ts.map +1 -0
  54. package/dist/types/src/components/NavTree/NavTree.d.ts +12 -5
  55. package/dist/types/src/components/NavTree/NavTree.d.ts.map +1 -1
  56. package/dist/types/src/components/NavTree/NavTree.stories.d.ts +27 -5
  57. package/dist/types/src/components/NavTree/NavTree.stories.d.ts.map +1 -1
  58. package/dist/types/src/components/NavTreeItem/NavTreeItemAction.d.ts +6 -6
  59. package/dist/types/src/components/NavTreeItem/NavTreeItemAction.d.ts.map +1 -1
  60. package/dist/types/src/components/NavTreeItem/NavTreeItemAction.stories.d.ts +33 -4
  61. package/dist/types/src/components/NavTreeItem/NavTreeItemAction.stories.d.ts.map +1 -1
  62. package/dist/types/src/components/NavTreeItem/NavTreeItemColumns.d.ts +2 -2
  63. package/dist/types/src/components/NavTreeItem/NavTreeItemColumns.d.ts.map +1 -1
  64. package/dist/types/src/components/Sidebar/L0Menu.d.ts +10 -5
  65. package/dist/types/src/components/Sidebar/L0Menu.d.ts.map +1 -1
  66. package/dist/types/src/components/Sidebar/L1Panel.d.ts +4 -8
  67. package/dist/types/src/components/Sidebar/L1Panel.d.ts.map +1 -1
  68. package/dist/types/src/components/Sidebar/L1Tabs.d.ts +13 -0
  69. package/dist/types/src/components/Sidebar/L1Tabs.d.ts.map +1 -0
  70. package/dist/types/src/components/Sidebar/index.d.ts +1 -0
  71. package/dist/types/src/components/Sidebar/index.d.ts.map +1 -1
  72. package/dist/types/src/components/UserAccountAvatar/UserAccountAvatar.d.ts.map +1 -1
  73. package/dist/types/src/components/UserAccountAvatar/UserAccountAvatar.stories.d.ts +8 -5
  74. package/dist/types/src/components/UserAccountAvatar/UserAccountAvatar.stories.d.ts.map +1 -1
  75. package/dist/types/src/components/index.d.ts +0 -3
  76. package/dist/types/src/components/index.d.ts.map +1 -1
  77. package/dist/types/src/components/types.d.ts +8 -16
  78. package/dist/types/src/components/types.d.ts.map +1 -1
  79. package/dist/types/src/containers/CommandsDialogContent/CommandsDialogContent.d.ts +6 -0
  80. package/dist/types/src/containers/CommandsDialogContent/CommandsDialogContent.d.ts.map +1 -0
  81. package/dist/types/src/containers/CommandsDialogContent/index.d.ts +3 -0
  82. package/dist/types/src/containers/CommandsDialogContent/index.d.ts.map +1 -0
  83. package/dist/types/src/containers/CommandsTrigger/CommandsTrigger.d.ts.map +1 -0
  84. package/dist/types/src/containers/CommandsTrigger/index.d.ts +3 -0
  85. package/dist/types/src/containers/CommandsTrigger/index.d.ts.map +1 -0
  86. package/dist/types/src/containers/NavTreeContainer/NavTreeContainer.d.ts +9 -0
  87. package/dist/types/src/containers/NavTreeContainer/NavTreeContainer.d.ts.map +1 -0
  88. package/dist/types/src/containers/NavTreeContainer/index.d.ts +3 -0
  89. package/dist/types/src/containers/NavTreeContainer/index.d.ts.map +1 -0
  90. package/dist/types/src/{components → containers/NavTreeDocumentTitle}/NavTreeDocumentTitle.d.ts +1 -1
  91. package/dist/types/src/containers/NavTreeDocumentTitle/NavTreeDocumentTitle.d.ts.map +1 -0
  92. package/dist/types/src/containers/NavTreeDocumentTitle/index.d.ts +3 -0
  93. package/dist/types/src/containers/NavTreeDocumentTitle/index.d.ts.map +1 -0
  94. package/dist/types/src/containers/index.d.ts +7 -0
  95. package/dist/types/src/containers/index.d.ts.map +1 -0
  96. package/dist/types/src/experimental/Tree.d.ts +1 -2
  97. package/dist/types/src/experimental/Tree.d.ts.map +1 -1
  98. package/dist/types/src/experimental/Tree.stories.d.ts +23 -6
  99. package/dist/types/src/experimental/Tree.stories.d.ts.map +1 -1
  100. package/dist/types/src/hooks/index.d.ts +5 -0
  101. package/dist/types/src/hooks/index.d.ts.map +1 -0
  102. package/dist/types/src/hooks/useActions.d.ts +7 -0
  103. package/dist/types/src/hooks/useActions.d.ts.map +1 -0
  104. package/dist/types/src/hooks/useLoadDescendents.d.ts +6 -0
  105. package/dist/types/src/hooks/useLoadDescendents.d.ts.map +1 -0
  106. package/dist/types/src/hooks/useNavTreeModel.d.ts +7 -0
  107. package/dist/types/src/hooks/useNavTreeModel.d.ts.map +1 -0
  108. package/dist/types/src/hooks/useNavTreeState.d.ts +22 -0
  109. package/dist/types/src/hooks/useNavTreeState.d.ts.map +1 -0
  110. package/dist/types/src/index.d.ts +1 -2
  111. package/dist/types/src/index.d.ts.map +1 -1
  112. package/dist/types/src/meta.d.ts +3 -4
  113. package/dist/types/src/meta.d.ts.map +1 -1
  114. package/dist/types/src/testing/app-graph-builder.d.ts +2 -3
  115. package/dist/types/src/testing/app-graph-builder.d.ts.map +1 -1
  116. package/dist/types/src/testing/generator.d.ts +5 -6
  117. package/dist/types/src/testing/generator.d.ts.map +1 -1
  118. package/dist/types/src/testing/update-state.d.ts +2 -2
  119. package/dist/types/src/testing/update-state.d.ts.map +1 -1
  120. package/dist/types/src/translations.d.ts +1 -0
  121. package/dist/types/src/translations.d.ts.map +1 -1
  122. package/dist/types/src/types/capabilities.d.ts +16 -0
  123. package/dist/types/src/types/capabilities.d.ts.map +1 -0
  124. package/dist/types/src/types/events.d.ts +5 -0
  125. package/dist/types/src/types/events.d.ts.map +1 -0
  126. package/dist/types/src/types/index.d.ts +4 -0
  127. package/dist/types/src/types/index.d.ts.map +1 -0
  128. package/dist/types/src/{types.d.ts → types/schema.d.ts} +10 -9
  129. package/dist/types/src/types/schema.d.ts.map +1 -0
  130. package/dist/types/src/util.d.ts +12 -9
  131. package/dist/types/src/util.d.ts.map +1 -1
  132. package/dist/types/tsconfig.tsbuildinfo +1 -1
  133. package/package.json +56 -53
  134. package/src/NavTreePlugin.tsx +64 -84
  135. package/src/capabilities/app-graph-builder/app-graph-builder.ts +42 -0
  136. package/src/capabilities/app-graph-builder/index.ts +7 -0
  137. package/src/capabilities/index.ts +5 -9
  138. package/src/capabilities/keyboard/index.ts +7 -0
  139. package/src/capabilities/keyboard/keyboard.ts +66 -0
  140. package/src/capabilities/operation-resolver/index.ts +7 -0
  141. package/src/capabilities/operation-resolver/operation-resolver.ts +44 -0
  142. package/src/capabilities/react-surface/index.ts +7 -0
  143. package/src/capabilities/react-surface/react-surface.tsx +53 -0
  144. package/src/capabilities/state/index.ts +7 -0
  145. package/src/capabilities/state/state.ts +149 -0
  146. package/src/components/NavTree/NavTree.stories.tsx +105 -98
  147. package/src/components/NavTree/NavTree.tsx +69 -34
  148. package/src/components/NavTreeItem/NavTreeItemAction.stories.tsx +21 -13
  149. package/src/components/NavTreeItem/NavTreeItemAction.tsx +39 -33
  150. package/src/components/NavTreeItem/NavTreeItemColumns.tsx +66 -36
  151. package/src/components/Sidebar/L0Menu.tsx +170 -179
  152. package/src/components/Sidebar/L1Panel.tsx +248 -134
  153. package/src/components/Sidebar/L1Tabs.tsx +43 -0
  154. package/src/components/Sidebar/index.ts +1 -0
  155. package/src/components/UserAccountAvatar/UserAccountAvatar.stories.tsx +9 -9
  156. package/src/components/UserAccountAvatar/UserAccountAvatar.tsx +20 -12
  157. package/src/components/index.ts +1 -3
  158. package/src/components/types.ts +15 -19
  159. package/src/containers/CommandsDialogContent/CommandsDialogContent.tsx +133 -0
  160. package/src/containers/CommandsDialogContent/index.ts +7 -0
  161. package/src/containers/CommandsTrigger/CommandsTrigger.tsx +26 -0
  162. package/src/containers/CommandsTrigger/index.ts +7 -0
  163. package/src/containers/NavTreeContainer/NavTreeContainer.tsx +270 -0
  164. package/src/containers/NavTreeContainer/index.ts +7 -0
  165. package/src/{components → containers/NavTreeDocumentTitle}/NavTreeDocumentTitle.tsx +5 -4
  166. package/src/containers/NavTreeDocumentTitle/index.ts +7 -0
  167. package/src/containers/index.ts +12 -0
  168. package/src/experimental/Tree.stories.tsx +78 -83
  169. package/src/experimental/Tree.tsx +6 -23
  170. package/src/hooks/index.ts +8 -0
  171. package/src/hooks/useActions.ts +38 -0
  172. package/src/hooks/useLoadDescendents.ts +23 -0
  173. package/src/hooks/useNavTreeModel.ts +112 -0
  174. package/src/hooks/useNavTreeState.ts +42 -0
  175. package/src/index.ts +1 -2
  176. package/src/meta.ts +11 -8
  177. package/src/testing/app-graph-builder.ts +159 -234
  178. package/src/testing/generator.ts +20 -18
  179. package/src/testing/update-state.ts +6 -6
  180. package/src/translations.ts +1 -0
  181. package/src/types/capabilities.ts +21 -0
  182. package/src/types/events.ts +12 -0
  183. package/src/types/index.ts +7 -0
  184. package/src/{types.ts → types/schema.ts} +9 -8
  185. package/src/util.ts +26 -33
  186. package/dist/lib/browser/app-graph-builder-5J4LRWDX.mjs +0 -45
  187. package/dist/lib/browser/app-graph-builder-5J4LRWDX.mjs.map +0 -7
  188. package/dist/lib/browser/chunk-ERDGQTH5.mjs +0 -16
  189. package/dist/lib/browser/chunk-ERDGQTH5.mjs.map +0 -7
  190. package/dist/lib/browser/chunk-SICQTLXC.mjs +0 -1442
  191. package/dist/lib/browser/chunk-SICQTLXC.mjs.map +0 -7
  192. package/dist/lib/browser/chunk-WCARAZ7J.mjs +0 -15
  193. package/dist/lib/browser/chunk-WCARAZ7J.mjs.map +0 -7
  194. package/dist/lib/browser/intent-resolver-3XYN2CBU.mjs +0 -47
  195. package/dist/lib/browser/intent-resolver-3XYN2CBU.mjs.map +0 -7
  196. package/dist/lib/browser/keyboard-QRS6WOQH.mjs.map +0 -7
  197. package/dist/lib/browser/react-surface-WURHCBQQ.mjs +0 -51
  198. package/dist/lib/browser/react-surface-WURHCBQQ.mjs.map +0 -7
  199. package/dist/lib/browser/state-54DY3DOY.mjs +0 -117
  200. package/dist/lib/browser/state-54DY3DOY.mjs.map +0 -7
  201. package/dist/types/src/capabilities/app-graph-builder.d.ts +0 -4
  202. package/dist/types/src/capabilities/app-graph-builder.d.ts.map +0 -1
  203. package/dist/types/src/capabilities/capabilities.d.ts +0 -21
  204. package/dist/types/src/capabilities/capabilities.d.ts.map +0 -1
  205. package/dist/types/src/capabilities/intent-resolver.d.ts +0 -4
  206. package/dist/types/src/capabilities/intent-resolver.d.ts.map +0 -1
  207. package/dist/types/src/capabilities/keyboard.d.ts +0 -4
  208. package/dist/types/src/capabilities/keyboard.d.ts.map +0 -1
  209. package/dist/types/src/capabilities/react-surface.d.ts +0 -4
  210. package/dist/types/src/capabilities/react-surface.d.ts.map +0 -1
  211. package/dist/types/src/capabilities/state.d.ts +0 -20
  212. package/dist/types/src/capabilities/state.d.ts.map +0 -1
  213. package/dist/types/src/components/CommandsDialog/CommandsDialog.d.ts +0 -5
  214. package/dist/types/src/components/CommandsDialog/CommandsDialog.d.ts.map +0 -1
  215. package/dist/types/src/components/CommandsDialog/CommandsTrigger.d.ts.map +0 -1
  216. package/dist/types/src/components/CommandsDialog/index.d.ts +0 -3
  217. package/dist/types/src/components/CommandsDialog/index.d.ts.map +0 -1
  218. package/dist/types/src/components/NavTreeContainer.d.ts +0 -9
  219. package/dist/types/src/components/NavTreeContainer.d.ts.map +0 -1
  220. package/dist/types/src/components/NavTreeDocumentTitle.d.ts.map +0 -1
  221. package/dist/types/src/events.d.ts +0 -4
  222. package/dist/types/src/events.d.ts.map +0 -1
  223. package/dist/types/src/hooks.d.ts +0 -3
  224. package/dist/types/src/hooks.d.ts.map +0 -1
  225. package/dist/types/src/types.d.ts.map +0 -1
  226. package/src/capabilities/app-graph-builder.ts +0 -52
  227. package/src/capabilities/capabilities.ts +0 -20
  228. package/src/capabilities/intent-resolver.ts +0 -37
  229. package/src/capabilities/keyboard.ts +0 -59
  230. package/src/capabilities/react-surface.tsx +0 -45
  231. package/src/capabilities/state.ts +0 -104
  232. package/src/components/CommandsDialog/CommandsDialog.tsx +0 -118
  233. package/src/components/CommandsDialog/CommandsTrigger.tsx +0 -35
  234. package/src/components/CommandsDialog/index.ts +0 -6
  235. package/src/components/NavTreeContainer.tsx +0 -313
  236. package/src/events.ts +0 -11
  237. package/src/hooks.ts +0 -21
  238. /package/dist/types/src/{components/CommandsDialog → containers/CommandsTrigger}/CommandsTrigger.d.ts +0 -0
@@ -0,0 +1,133 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ import React, { forwardRef, useMemo, useState } from 'react';
6
+
7
+ import { useOperationInvoker } from '@dxos/app-framework/ui';
8
+ import { LayoutOperation } from '@dxos/app-toolkit';
9
+ import { useAppGraph } from '@dxos/app-toolkit/ui';
10
+ import { Keyboard, keySymbols } from '@dxos/keyboard';
11
+ import { Graph, Node, useActionRunner } from '@dxos/plugin-graph';
12
+ import { useActions } from '@dxos/plugin-graph';
13
+ import { Button, Dialog, toLocalizedString, useTranslation } from '@dxos/react-ui';
14
+ import { SearchList, useSearchListResults } from '@dxos/react-ui-searchlist';
15
+ import { osTranslations } from '@dxos/ui-theme';
16
+ import { getHostPlatform } from '@dxos/util';
17
+
18
+ import { KEY_BINDING, meta } from '../../meta';
19
+
20
+ export type CommandsDialogContentProps = {
21
+ selected?: string;
22
+ };
23
+
24
+ // TODO(wittjosiah): This probably deserves its own plugin but for now it lives here w/ other navigation UI.
25
+ export const CommandsDialogContent = forwardRef<HTMLDivElement, CommandsDialogContentProps>(
26
+ ({ selected: initial }, forwardedRef) => {
27
+ const { t } = useTranslation(meta.id);
28
+ const { invokeSync } = useOperationInvoker();
29
+ const runAction = useActionRunner();
30
+ const { graph } = useAppGraph();
31
+ const [selected, setSelected] = useState<string | undefined>(initial);
32
+
33
+ // Traverse graph.
34
+ // TODO(burdon): Factor out commonality with shortcut dialog.
35
+ const allActions = useMemo(() => {
36
+ // TODO(burdon): Get from navtree (not keyboard).
37
+ const current = Keyboard.singleton.getCurrentContext();
38
+ const actionMap = new Set<string>();
39
+ const actions: Node.ActionLike[] = [];
40
+ Graph.traverse(graph, {
41
+ relation: 'child',
42
+ visitor: (node, path) => {
43
+ if (
44
+ (Node.isAction(node) || Node.isActionGroup(node)) &&
45
+ !actionMap.has(node.id) &&
46
+ current.startsWith(path.slice(0, -1).join('/'))
47
+ ) {
48
+ actionMap.add(node.id);
49
+ actions.push(node);
50
+ }
51
+ },
52
+ });
53
+
54
+ actions.sort((a, b) => {
55
+ return toLocalizedString(a.properties.label, t)
56
+ ?.toLowerCase()
57
+ .localeCompare(toLocalizedString(b.properties.label, t)?.toLowerCase());
58
+ });
59
+
60
+ return actions;
61
+ }, [graph]);
62
+
63
+ const group = allActions.find(({ id }) => id === selected);
64
+ const groupActions = useActions(graph, group?.id);
65
+ const actions = Node.isActionGroup(group) ? groupActions : allActions;
66
+
67
+ const { results, handleSearch } = useSearchListResults({
68
+ items: actions,
69
+ extract: (action) => toLocalizedString(action.properties.label, t),
70
+ });
71
+
72
+ return (
73
+ <Dialog.Content ref={forwardedRef}>
74
+ <Dialog.Title>{t('commands dialog title', { ns: meta.id })}</Dialog.Title>
75
+ <SearchList.Root onSearch={handleSearch}>
76
+ <SearchList.Content>
77
+ <SearchList.Input placeholder={t('command list input placeholder')} />
78
+ <SearchList.Viewport>
79
+ {results.map((action) => {
80
+ const shortcut =
81
+ typeof action.properties.keyBinding === 'string'
82
+ ? action.properties.keyBinding
83
+ : action.properties.keyBinding?.[getHostPlatform()];
84
+
85
+ return (
86
+ <SearchList.Item
87
+ value={action.id}
88
+ key={action.id}
89
+ label={toLocalizedString(action.properties.label, t)}
90
+ icon={action.properties.icon}
91
+ suffix={shortcut ? keySymbols(shortcut).join('') : undefined}
92
+ onSelect={() => {
93
+ if (action.properties.disabled) {
94
+ return;
95
+ }
96
+
97
+ if (Node.isActionGroup(action)) {
98
+ setSelected(action.id);
99
+ return;
100
+ }
101
+
102
+ invokeSync(LayoutOperation.UpdateDialog, { state: false });
103
+ setTimeout(() => {
104
+ const node = Graph.getConnections(
105
+ graph,
106
+ group?.id ?? action.id,
107
+ Node.childRelation('inbound'),
108
+ )[0];
109
+ if (node && Node.isAction(action)) {
110
+ void runAction(action, { parent: node, caller: KEY_BINDING });
111
+ }
112
+ });
113
+ }}
114
+ classNames='flex items-center gap-2'
115
+ disabled={action.properties.disabled}
116
+ {...(action.properties?.testId && {
117
+ 'data-testid': action.properties.testId,
118
+ })}
119
+ />
120
+ );
121
+ })}
122
+ </SearchList.Viewport>
123
+ </SearchList.Content>
124
+ </SearchList.Root>
125
+ <div role='none' className='p-form-padding'>
126
+ <Dialog.Close asChild>
127
+ <Button classNames='w-full'>{t('close label', { ns: osTranslations })}</Button>
128
+ </Dialog.Close>
129
+ </div>
130
+ </Dialog.Content>
131
+ );
132
+ },
133
+ );
@@ -0,0 +1,7 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ import { CommandsDialogContent } from './CommandsDialogContent';
6
+
7
+ export default CommandsDialogContent;
@@ -0,0 +1,26 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import React from 'react';
6
+
7
+ import { useOperationInvoker } from '@dxos/app-framework/ui';
8
+ import { LayoutOperation } from '@dxos/app-toolkit';
9
+ import { Button, Icon, useTranslation } from '@dxos/react-ui';
10
+
11
+ import { COMMANDS_DIALOG, meta } from '../../meta';
12
+
13
+ // TODO(thure): Refactor to be handled by a more appropriate plugin.
14
+ export const CommandsTrigger = () => {
15
+ const { invokeSync } = useOperationInvoker();
16
+ const { t } = useTranslation(meta.id);
17
+ return (
18
+ <Button
19
+ classNames='m-1 px-1 lg:px-2'
20
+ onClick={() => invokeSync(LayoutOperation.UpdateDialog, { subject: COMMANDS_DIALOG, blockAlign: 'start' })}
21
+ >
22
+ <span className='text-description font-normal grow text-start'>{t('command list input placeholder')}</span>
23
+ <Icon icon='ph--magnifying-glass--regular' size={5} />
24
+ </Button>
25
+ );
26
+ };
@@ -0,0 +1,7 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import { CommandsTrigger } from './CommandsTrigger';
6
+
7
+ export default CommandsTrigger;
@@ -0,0 +1,270 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ import { monitorForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
6
+ import { type Instruction, extractInstruction } from '@atlaskit/pragmatic-drag-and-drop-hitbox/tree-item';
7
+ import React, { forwardRef, memo, useCallback, useEffect, useMemo, useRef } from 'react';
8
+
9
+ import { Surface, useOperationInvoker } from '@dxos/app-framework/ui';
10
+ import { LayoutOperation } from '@dxos/app-toolkit';
11
+ import { useAppGraph, useLayout } from '@dxos/app-toolkit/ui';
12
+ import { Graph, Node, useActionRunner } from '@dxos/plugin-graph';
13
+ import { useMediaQuery, useSidebars } from '@dxos/react-ui';
14
+ import { type TreeData, isTreeData } from '@dxos/react-ui-list';
15
+ import { arrayMove } from '@dxos/util';
16
+
17
+ import { NAV_TREE_ITEM, NavTree, NavTreeContext } from '../../components';
18
+ import { useNavTreeModel, useNavTreeState } from '../../hooks';
19
+ import { meta } from '../../meta';
20
+ import { type NavTreeItemGraphNode } from '../../types';
21
+ import { filterItems, getParent, resolveMigrationOperation } from '../../util';
22
+
23
+ // TODO(thure): Is NavTree truly authoritative in this regard?
24
+ export const NODE_TYPE = 'dxos/app-graph/node';
25
+
26
+ // TODO(wittjosiah): Avoid using Surface within the navtree, prefer declarative data flow.
27
+ const NavTreeItemEnd = ({ node, open }: { node: Node.Node; open: boolean }) => {
28
+ const data = useMemo(() => ({ id: node.id, subject: node.data, open }), [node.id, node.data, open]);
29
+ return <Surface.Surface role='navtree-item-end' data={data} limit={1} />;
30
+ };
31
+
32
+ const getItems = (graph: Graph.ReadableGraph, node?: Node.Node, disposition?: string) => {
33
+ return Graph.getConnections(graph, node?.id ?? Node.RootId, 'child').filter((node) => filterItems(node, disposition));
34
+ };
35
+
36
+ export type NavTreeContainerProps = {
37
+ popoverAnchorId?: string;
38
+ tab: string;
39
+ };
40
+
41
+ export const NavTreeContainer$ = forwardRef<HTMLDivElement, NavTreeContainerProps>(
42
+ ({ tab, popoverAnchorId }, forwardedRef) => {
43
+ const [isLg] = useMediaQuery('lg');
44
+ const { invokeSync, invokePromise } = useOperationInvoker();
45
+ const runAction = useActionRunner();
46
+ const { graph } = useAppGraph();
47
+ const { getItem, setItem } = useNavTreeState();
48
+ const layout = useLayout();
49
+ const model = useNavTreeModel(Node.RootId);
50
+ const { navigationSidebarState } = useSidebars(meta.id);
51
+ const latestRef = useRef({
52
+ tab,
53
+ activeItems: layout.active,
54
+ navigationSidebarState,
55
+ isLg,
56
+ });
57
+
58
+ useEffect(() => {
59
+ latestRef.current = {
60
+ tab,
61
+ activeItems: layout.active,
62
+ navigationSidebarState,
63
+ isLg,
64
+ };
65
+ }, [tab, layout.active, navigationSidebarState, isLg]);
66
+
67
+ const handleOpenChange = useCallback(
68
+ ({ item: { id }, path, open }: { item: Node.Node; path: string[]; open: boolean }) => {
69
+ // TODO(thure): This might become a localstorage leak; openItemIds that no longer exist should be removed from this map.
70
+ setItem(path, 'open', open);
71
+ Graph.expand(graph, id, 'child');
72
+ },
73
+ [graph, setItem],
74
+ );
75
+
76
+ const handleTabChange = useCallback(
77
+ (node: NavTreeItemGraphNode) => {
78
+ Graph.expand(graph, node.id, 'child');
79
+
80
+ const {
81
+ tab: activeTab,
82
+ activeItems,
83
+ navigationSidebarState: currentSidebarState,
84
+ isLg: latestIsLg,
85
+ } = latestRef.current;
86
+ invokeSync(LayoutOperation.UpdateSidebar, {
87
+ state:
88
+ node.id === activeTab
89
+ ? currentSidebarState === 'expanded'
90
+ ? latestIsLg
91
+ ? 'collapsed'
92
+ : 'closed'
93
+ : 'expanded'
94
+ : 'expanded',
95
+ });
96
+
97
+ invokeSync(LayoutOperation.SwitchWorkspace, { subject: node.id });
98
+
99
+ // Open the first item if the workspace is empty.
100
+ if (activeItems.length === 0) {
101
+ const [item] = getItems(graph, node).filter((node) => !Node.isActionLike(node));
102
+ if (item && item.data) {
103
+ invokeSync(LayoutOperation.Open, { subject: [item.id] });
104
+ }
105
+ }
106
+ },
107
+ [invokeSync, graph],
108
+ );
109
+
110
+ const blockInstruction = useCallback(
111
+ ({ instruction, source, target }: { instruction: Instruction; source: TreeData; target: TreeData }) => {
112
+ return target.item.properties.blockInstruction?.(source, instruction) ?? false;
113
+ },
114
+ [],
115
+ );
116
+
117
+ const canDrop = useCallback(({ source, target }: { source: TreeData; target: TreeData }) => {
118
+ return target.item.properties.canDrop?.(source) ?? false;
119
+ }, []);
120
+
121
+ const canSelect = useCallback(({ item }: { item: Node.Node }) => {
122
+ return item.properties.selectable ?? true;
123
+ }, []);
124
+
125
+ const handleSelect = useCallback(
126
+ ({ item: node, path, option }: { item: Node.Node; path: string[]; option: boolean }) => {
127
+ if (!node.data) {
128
+ return;
129
+ }
130
+
131
+ if (Node.isAction(node)) {
132
+ const [parent] = Graph.getConnections(graph, node.id, Node.childRelation('inbound'));
133
+ if (parent) {
134
+ void runAction(node, { parent, caller: NAV_TREE_ITEM });
135
+ }
136
+ return;
137
+ }
138
+
139
+ const current = getItem(path).current;
140
+ if (!current) {
141
+ invokeSync(LayoutOperation.Open, { subject: [node.id], key: node.properties.key });
142
+ } else if (option) {
143
+ invokeSync(LayoutOperation.Close, { subject: [node.id] });
144
+ } else {
145
+ void invokePromise(LayoutOperation.ScrollIntoView, { subject: node.id });
146
+ }
147
+
148
+ const defaultAction = Graph.getActions(graph, node.id).find(
149
+ (action) => action.properties?.disposition === 'default',
150
+ );
151
+ if (Node.isAction(defaultAction)) {
152
+ void runAction(defaultAction);
153
+ }
154
+
155
+ if (!isLg) {
156
+ invokeSync(LayoutOperation.UpdateSidebar, { state: 'closed' });
157
+ }
158
+ },
159
+ [graph, invokeSync, invokePromise, getItem, runAction, isLg],
160
+ );
161
+
162
+ const handleBack = useCallback(() => invokeSync(LayoutOperation.RevertWorkspace), [invokeSync]);
163
+
164
+ // TODO(wittjosiah): Factor out hook.
165
+ useEffect(() => {
166
+ return monitorForElements({
167
+ canMonitor: ({ source }) => isTreeData(source.data),
168
+ onDrop: ({ location, source }) => {
169
+ // Didn't drop on anything.
170
+ if (!location.current.dropTargets.length) {
171
+ return;
172
+ }
173
+ const target = location.current.dropTargets[0];
174
+ const instruction: Instruction | null = extractInstruction(target.data);
175
+ if (instruction !== null && instruction.type !== 'instruction-blocked') {
176
+ const sourceNode = source.data.item as NavTreeItemGraphNode;
177
+ const targetNode = target.data.item as NavTreeItemGraphNode;
178
+ const sourcePath = source.data.path as string[];
179
+ const targetPath = target.data.path as string[];
180
+ const operation =
181
+ sourcePath.slice(0, -1).join() === targetPath.slice(0, -1).join() && instruction.type !== 'make-child'
182
+ ? 'rearrange'
183
+ : resolveMigrationOperation(graph, sourceNode, targetPath, targetNode);
184
+ const sourceParent = getParent(graph, sourceNode, sourcePath);
185
+ const targetParent = getParent(graph, targetNode, targetPath);
186
+ const sourceItems = getItems(graph, sourceParent);
187
+ const targetItems = getItems(graph, targetParent);
188
+ const sourceIndex = sourceItems.findIndex(({ id }) => id === sourceNode.id);
189
+ const targetIndex = targetItems.findIndex(({ id }) => id === targetNode.id);
190
+ const migrationIndex =
191
+ instruction.type === 'make-child'
192
+ ? undefined
193
+ : instruction.type === 'reorder-below'
194
+ ? targetIndex + 1
195
+ : targetIndex;
196
+ switch (operation) {
197
+ case 'rearrange': {
198
+ const nextItems = sourceItems.map(({ data }) => data);
199
+ arrayMove(nextItems, sourceIndex, targetIndex);
200
+ void sourceNode.properties.onRearrange?.(nextItems);
201
+ break;
202
+ }
203
+ case 'copy': {
204
+ const target = instruction.type === 'make-child' ? targetNode : targetParent;
205
+ void target?.properties.onCopy?.(sourceNode, migrationIndex);
206
+ break;
207
+ }
208
+ case 'transfer': {
209
+ const target = instruction.type === 'make-child' ? targetNode : targetParent;
210
+ if (!target?.properties.onTransferStart || !sourceParent?.properties.onTransferEnd) {
211
+ break;
212
+ }
213
+ void target?.properties.onTransferStart(sourceNode, migrationIndex);
214
+ void sourceParent?.properties.onTransferEnd?.(sourceNode, target);
215
+ break;
216
+ }
217
+ }
218
+ }
219
+ },
220
+ });
221
+ }, [graph]);
222
+
223
+ const setAlternateTree = useCallback(
224
+ (path: string[], open: boolean) => {
225
+ setItem(path, 'alternateTree', open);
226
+ },
227
+ [setItem],
228
+ );
229
+
230
+ const onItemHover = useCallback(({ item }: { item: Node.Node }) => Graph.expand(graph, item.id, 'child'), [graph]);
231
+
232
+ const navTreeContextValue = useMemo(
233
+ () => ({
234
+ model,
235
+ popoverAnchorId,
236
+ renderItemEnd: NavTreeItemEnd,
237
+ blockInstruction,
238
+ canDrop,
239
+ canSelect,
240
+ setAlternateTree,
241
+ onBack: handleBack,
242
+ onOpenChange: handleOpenChange,
243
+ onSelect: handleSelect,
244
+ onTabChange: handleTabChange,
245
+ onItemHover,
246
+ }),
247
+ [
248
+ model,
249
+ popoverAnchorId,
250
+ blockInstruction,
251
+ canDrop,
252
+ canSelect,
253
+ setAlternateTree,
254
+ handleBack,
255
+ handleOpenChange,
256
+ handleSelect,
257
+ handleTabChange,
258
+ onItemHover,
259
+ ],
260
+ );
261
+
262
+ return (
263
+ <NavTreeContext.Provider value={navTreeContextValue}>
264
+ <NavTree id={Node.RootId} root={Graph.getRoot(graph)} tab={tab} open={layout.sidebarOpen} ref={forwardedRef} />
265
+ </NavTreeContext.Provider>
266
+ );
267
+ },
268
+ );
269
+
270
+ export const NavTreeContainer = memo(NavTreeContainer$);
@@ -0,0 +1,7 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ import { NavTreeContainer } from './NavTreeContainer';
6
+
7
+ export default NavTreeContainer;
@@ -5,13 +5,14 @@ import { useEffect } from 'react';
5
5
 
6
6
  import { type Node } from '@dxos/app-graph';
7
7
  import { toLocalizedString, useTranslation } from '@dxos/react-ui';
8
+ import { osTranslations } from '@dxos/ui-theme';
8
9
 
9
- import { NAVTREE_PLUGIN } from '../meta';
10
+ import { meta } from '../../meta';
10
11
 
11
- export const NavTreeDocumentTitle = ({ node }: { node?: Node }) => {
12
- const { t } = useTranslation(NAVTREE_PLUGIN);
12
+ export const NavTreeDocumentTitle = ({ node }: { node?: Node.Node }) => {
13
+ const { t } = useTranslation(meta.id);
13
14
  useEffect(() => {
14
- document.title = node ? toLocalizedString(node.properties.label, t) : t('current app name', { ns: 'appkit' });
15
+ document.title = node ? toLocalizedString(node.properties.label, t) : t('current app name', { ns: osTranslations });
15
16
  }, [node?.properties?.label]);
16
17
  return null;
17
18
  };
@@ -0,0 +1,7 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ import { NavTreeDocumentTitle } from './NavTreeDocumentTitle';
6
+
7
+ export default NavTreeDocumentTitle;
@@ -0,0 +1,12 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ import { type ComponentType, lazy } from 'react';
6
+
7
+ export { NODE_TYPE } from './NavTreeContainer/NavTreeContainer';
8
+
9
+ export const CommandsDialogContent: ComponentType<any> = lazy(() => import('./CommandsDialogContent'));
10
+ export const CommandsTrigger: ComponentType<any> = lazy(() => import('./CommandsTrigger'));
11
+ export const NavTreeContainer: ComponentType<any> = lazy(() => import('./NavTreeContainer'));
12
+ export const NavTreeDocumentTitle: ComponentType<any> = lazy(() => import('./NavTreeDocumentTitle'));