@dxos/plugin-navtree 0.6.8-main.046e6cf

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 (64) hide show
  1. package/LICENSE +8 -0
  2. package/README.md +15 -0
  3. package/dist/lib/browser/chunk-U7MTKDFQ.mjs +13 -0
  4. package/dist/lib/browser/chunk-U7MTKDFQ.mjs.map +7 -0
  5. package/dist/lib/browser/index.mjs +1055 -0
  6. package/dist/lib/browser/index.mjs.map +7 -0
  7. package/dist/lib/browser/meta.json +1 -0
  8. package/dist/lib/browser/meta.mjs +11 -0
  9. package/dist/lib/browser/meta.mjs.map +7 -0
  10. package/dist/types/src/NavTreePlugin.d.ts +4 -0
  11. package/dist/types/src/NavTreePlugin.d.ts.map +1 -0
  12. package/dist/types/src/components/CommandsDialog.d.ts +5 -0
  13. package/dist/types/src/components/CommandsDialog.d.ts.map +1 -0
  14. package/dist/types/src/components/CommandsTrigger.d.ts +3 -0
  15. package/dist/types/src/components/CommandsTrigger.d.ts.map +1 -0
  16. package/dist/types/src/components/HaloButton.d.ts +12 -0
  17. package/dist/types/src/components/HaloButton.d.ts.map +1 -0
  18. package/dist/types/src/components/HaloButton.stories.d.ts +12 -0
  19. package/dist/types/src/components/HaloButton.stories.d.ts.map +1 -0
  20. package/dist/types/src/components/NavBarStart.d.ts +7 -0
  21. package/dist/types/src/components/NavBarStart.d.ts.map +1 -0
  22. package/dist/types/src/components/NavTreeContainer.d.ts +12 -0
  23. package/dist/types/src/components/NavTreeContainer.d.ts.map +1 -0
  24. package/dist/types/src/components/NavTreeDocumentTitle.d.ts +5 -0
  25. package/dist/types/src/components/NavTreeDocumentTitle.d.ts.map +1 -0
  26. package/dist/types/src/components/NavTreeFooter.d.ts +6 -0
  27. package/dist/types/src/components/NavTreeFooter.d.ts.map +1 -0
  28. package/dist/types/src/components/NotchStart.d.ts +3 -0
  29. package/dist/types/src/components/NotchStart.d.ts.map +1 -0
  30. package/dist/types/src/components/index.d.ts +6 -0
  31. package/dist/types/src/components/index.d.ts.map +1 -0
  32. package/dist/types/src/experimental/Tree.d.ts +56 -0
  33. package/dist/types/src/experimental/Tree.d.ts.map +1 -0
  34. package/dist/types/src/experimental/Tree.stories.d.ts +12 -0
  35. package/dist/types/src/experimental/Tree.stories.d.ts.map +1 -0
  36. package/dist/types/src/index.d.ts +5 -0
  37. package/dist/types/src/index.d.ts.map +1 -0
  38. package/dist/types/src/meta.d.ts +7 -0
  39. package/dist/types/src/meta.d.ts.map +1 -0
  40. package/dist/types/src/stories/Graph.stories.d.ts +17 -0
  41. package/dist/types/src/stories/Graph.stories.d.ts.map +1 -0
  42. package/dist/types/src/translations.d.ts +27 -0
  43. package/dist/types/src/translations.d.ts.map +1 -0
  44. package/dist/types/src/util.d.ts +32 -0
  45. package/dist/types/src/util.d.ts.map +1 -0
  46. package/package.json +77 -0
  47. package/src/NavTreePlugin.tsx +262 -0
  48. package/src/components/CommandsDialog.tsx +114 -0
  49. package/src/components/CommandsTrigger.tsx +34 -0
  50. package/src/components/HaloButton.stories.tsx +19 -0
  51. package/src/components/HaloButton.tsx +41 -0
  52. package/src/components/NavBarStart.tsx +48 -0
  53. package/src/components/NavTreeContainer.tsx +375 -0
  54. package/src/components/NavTreeDocumentTitle.tsx +17 -0
  55. package/src/components/NavTreeFooter.tsx +155 -0
  56. package/src/components/NotchStart.tsx +29 -0
  57. package/src/components/index.ts +9 -0
  58. package/src/experimental/Tree.stories.tsx +229 -0
  59. package/src/experimental/Tree.tsx +282 -0
  60. package/src/index.ts +10 -0
  61. package/src/meta.ts +12 -0
  62. package/src/stories/Graph.stories.tsx +162 -0
  63. package/src/translations.ts +28 -0
  64. package/src/util.ts +231 -0
@@ -0,0 +1,28 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ import { translations as navtreeTranslations } from '@dxos/react-ui-navtree';
6
+
7
+ import { NAVTREE_PLUGIN } from './meta';
8
+
9
+ export default [
10
+ {
11
+ 'en-US': {
12
+ [NAVTREE_PLUGIN]: {
13
+ 'open settings label': 'Settings',
14
+ 'open commands label': 'Search commands',
15
+ 'commands dialog title': 'Commands',
16
+ 'command list input placeholder': 'Search for commands…',
17
+ 'node actions menu invoker label': 'More options',
18
+ 'warning title': 'WARNING',
19
+ 'technology preview message': 'Composer is still in technology preview.',
20
+ 'learn more label': 'Learn more',
21
+ 'released message': 'This version released {{released}}.',
22
+ 'see release label': 'See release on GitHub',
23
+ 'powered by dxos message': 'Powered by <dxos>DXOS</dxos>',
24
+ },
25
+ },
26
+ },
27
+ ...navtreeTranslations,
28
+ ];
package/src/util.ts ADDED
@@ -0,0 +1,231 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ import {
6
+ type Action,
7
+ type Node,
8
+ type NodeFilter,
9
+ type Graph,
10
+ ACTION_TYPE,
11
+ ACTION_GROUP_TYPE,
12
+ isAction,
13
+ } from '@dxos/app-graph';
14
+ import { Path } from '@dxos/react-ui-mosaic';
15
+ import {
16
+ type NavTreeActionNode,
17
+ type NavTreeItemActions,
18
+ type NavTreeItemNode,
19
+ type NavTreeItemNodeProperties,
20
+ type OpenItemIds,
21
+ } from '@dxos/react-ui-navtree';
22
+ import { type MaybePromise, nonNullable } from '@dxos/util';
23
+
24
+ export type NavTreeItemGraphNode = Node<
25
+ any,
26
+ NavTreeItemNodeProperties &
27
+ Partial<{
28
+ persistenceClass: string;
29
+ persistenceKey: string;
30
+ acceptPersistenceClass: Set<string>;
31
+ acceptPersistenceKey: Set<string>;
32
+ onRearrangeChildren: (nextOrder: NavTreeItemGraphNode[]) => MaybePromise<void>;
33
+ onCopy: (activeNode: NavTreeItemGraphNode, index?: number) => MaybePromise<void>;
34
+ onTransferStart: (activeNode: NavTreeItemGraphNode, index?: number) => MaybePromise<void>;
35
+ onTransferEnd: (activeNode: NavTreeItemGraphNode, destinationParent: NavTreeItemGraphNode) => MaybePromise<void>;
36
+ }>
37
+ >;
38
+ export type NavTreeItem = NavTreeItemNode<NavTreeItemGraphNode>;
39
+
40
+ export const getParent = (
41
+ graph: Graph,
42
+ node: NavTreeItemGraphNode,
43
+ path: string[],
44
+ ): NavTreeItemGraphNode | undefined => {
45
+ const parentId = path[path.length - 2];
46
+ return graph.nodes(node, { relation: 'inbound' }).find((n) => n.id === parentId) as NavTreeItemGraphNode | undefined;
47
+ };
48
+
49
+ export const getPersistenceParent = (
50
+ graph: Graph,
51
+ node: NavTreeItemGraphNode,
52
+ path: string[],
53
+ persistenceClass: string,
54
+ ): NavTreeItemGraphNode | null => {
55
+ if (node.properties.acceptPersistenceClass?.has(persistenceClass)) {
56
+ return node;
57
+ } else {
58
+ const parent = getParent(graph, node, path);
59
+ return parent ? getPersistenceParent(graph, parent, path.slice(0, path.length - 1), persistenceClass) : null;
60
+ }
61
+ };
62
+
63
+ export const resolveMigrationOperation = (
64
+ graph: Graph,
65
+ activeNode: NavTreeItemGraphNode,
66
+ destinationPath: string[],
67
+ destinationRelatedNode?: NavTreeItemGraphNode,
68
+ ): 'transfer' | 'copy' | 'reject' => {
69
+ const activeClass = activeNode.properties.persistenceClass;
70
+ if (destinationRelatedNode && activeClass) {
71
+ const persistenceParent = getPersistenceParent(graph, destinationRelatedNode, destinationPath, activeClass);
72
+ if (persistenceParent) {
73
+ const activeKey = activeNode.properties.persistenceKey;
74
+ if (activeKey && persistenceParent?.properties.acceptPersistenceKey) {
75
+ return persistenceParent.properties.acceptPersistenceKey.has(activeKey) &&
76
+ destinationRelatedNode.properties.onTransferStart
77
+ ? 'transfer'
78
+ : destinationRelatedNode.properties.onCopy
79
+ ? 'copy'
80
+ : 'reject';
81
+ } else {
82
+ return 'reject';
83
+ }
84
+ } else {
85
+ return 'reject';
86
+ }
87
+ } else {
88
+ return 'reject';
89
+ }
90
+ };
91
+
92
+ // TODO(wittjosiah): Move into node implementation?
93
+ export const sortActions = (actions: Action[]): Action[] =>
94
+ actions.sort((a, b) => {
95
+ if (a.properties.disposition === b.properties.disposition) {
96
+ return 0;
97
+ }
98
+
99
+ if (a.properties.disposition === 'toolbar') {
100
+ return -1;
101
+ }
102
+
103
+ return 1;
104
+ });
105
+
106
+ export const getTreeItemNode = (treeItems: NavTreeItemNode[], path?: string[]): NavTreeItemNode | undefined => {
107
+ if (!path) {
108
+ return undefined;
109
+ }
110
+
111
+ return treeItems.find((treeItem) => {
112
+ return treeItem.path && !treeItem.path.find((id, index) => path[index] !== id);
113
+ });
114
+ };
115
+
116
+ export const getChildren = (
117
+ graph: Graph,
118
+ node: NavTreeItemGraphNode,
119
+ filter?: NodeFilter,
120
+ path: string[] = [],
121
+ ): NavTreeItemGraphNode[] => {
122
+ return graph
123
+ .nodes(node, { relation: 'outbound', filter })
124
+ .map((n) => {
125
+ // Break cycles.
126
+ const nextPath = [...path, node.id];
127
+ return nextPath.includes(n.id) ? undefined : (n as NavTreeItemGraphNode);
128
+ })
129
+ .filter(nonNullable) as NavTreeItemGraphNode[];
130
+ };
131
+
132
+ type FlattenedActions = Required<Pick<NavTreeItemNode, 'actions' | 'groupedActions'>>;
133
+
134
+ export const getActions = (graph: Graph, node: NavTreeItemGraphNode): FlattenedActions => {
135
+ return graph.actions(node).reduce(
136
+ (acc: FlattenedActions, arg) => {
137
+ acc.actions.push(arg as unknown as NavTreeItemActions[number]);
138
+ if (!isAction(arg)) {
139
+ const actionGroup = graph.actions(arg);
140
+ acc.groupedActions[arg.id] = actionGroup as unknown as NavTreeActionNode[];
141
+ }
142
+ return acc;
143
+ },
144
+ { actions: [], groupedActions: {} },
145
+ );
146
+ };
147
+
148
+ export const expandChildrenAndActions = (graph: Graph, node: Node) => {
149
+ return Promise.all([expandChildren(graph, node), expandActions(graph, node)]);
150
+ };
151
+
152
+ export const expandChildren = (graph: Graph, node: Node) => {
153
+ return graph.expand(node, 'outbound');
154
+ };
155
+
156
+ export const expandActions = (graph: Graph, node: Node) => {
157
+ return Promise.all([graph.expand(node, 'outbound', ACTION_TYPE), graph.expand(node, 'outbound', ACTION_GROUP_TYPE)]);
158
+ };
159
+
160
+ function* navTreeItemVisitor(
161
+ graph: Graph,
162
+ node: NavTreeItemGraphNode,
163
+ openItemIds: OpenItemIds,
164
+ path: string[] = [],
165
+ filter?: NodeFilter,
166
+ ): Generator<NavTreeItem> {
167
+ const l0Children = getChildren(graph, node, filter, path);
168
+ const { actions: l0Actions, groupedActions: l0GroupedActions } = getActions(graph, node);
169
+
170
+ const stack: NavTreeItem[] = [
171
+ {
172
+ id: node.id,
173
+ node,
174
+ path: [],
175
+ parentOf: (l0Children ?? []).map(({ id }) => id),
176
+ actions: l0Actions,
177
+ groupedActions: l0GroupedActions,
178
+ },
179
+ ];
180
+
181
+ while (stack.length > 0) {
182
+ const nextItem = stack.pop()!;
183
+ if ((nextItem.path?.length ?? 0) > 0) {
184
+ yield nextItem;
185
+ }
186
+ const { id, node, path } = nextItem;
187
+ const children = getChildren(graph, node, filter, path);
188
+ if (path?.length === 0 || (id ?? 'never') in openItemIds) {
189
+ for (let i = children.length - 1; i >= 0; i--) {
190
+ const child = children[i] as NavTreeItemGraphNode;
191
+ const childPath = path ? [...path, child.id] : [child.id];
192
+ const childChildren = getChildren(graph, child, filter, childPath);
193
+ const { actions: childActions, groupedActions: childGroupedActions } = getActions(graph, child);
194
+ stack.push({
195
+ id: Path.create(...childPath),
196
+ node: child,
197
+ path: childPath,
198
+ ...((childChildren?.length ?? 0) > 0 && {
199
+ parentOf: childChildren!.map(({ id }) => Path.create(...childPath, id)),
200
+ }),
201
+ actions: childActions,
202
+ groupedActions: childGroupedActions,
203
+ });
204
+ }
205
+ }
206
+ }
207
+ }
208
+
209
+ /**
210
+ * Get a reactive tree node from a graph node.
211
+ */
212
+ export const treeItemsFromRootNode = (
213
+ graph: Graph,
214
+ rootNode: NavTreeItemGraphNode,
215
+ openItemIds: OpenItemIds,
216
+ path: string[] = [],
217
+ filter?: NodeFilter,
218
+ ): NavTreeItem[] => {
219
+ return Array.from(navTreeItemVisitor(graph, rootNode, openItemIds, path, filter));
220
+ };
221
+
222
+ export const expandOpenGraphNodes = (graph: Graph, openItemIds: OpenItemIds) => {
223
+ return Promise.all(
224
+ Object.keys(openItemIds)
225
+ .map((openItemId) => {
226
+ const node = graph.findNode(Path.last(openItemId));
227
+ return node && expandChildrenAndActions(graph, node as NavTreeItemGraphNode);
228
+ })
229
+ .filter(nonNullable),
230
+ );
231
+ };