@dxos/plugin-navtree 0.12.0-next-73daef452f1464b62efdbca75fb0067c1066f264 → 0.13.0

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 (205) hide show
  1. package/PLUGIN.mdl +87 -16
  2. package/dist/lib/NavTreeCapabilities.mjs.map +1 -1
  3. package/dist/lib/NavTreeNode.mjs.map +1 -1
  4. package/dist/lib/capabilities.browser.mjs +59 -0
  5. package/dist/lib/capabilities.browser.mjs.map +1 -0
  6. package/dist/lib/capabilities.mjs +3 -4
  7. package/dist/lib/capabilities.mjs.map +1 -1
  8. package/dist/lib/capabilities.node.mjs +1 -4
  9. package/dist/lib/capabilities.node.mjs.map +1 -1
  10. package/dist/lib/capabilities.tauri.mjs +59 -0
  11. package/dist/lib/capabilities.tauri.mjs.map +1 -0
  12. package/dist/lib/capabilities.workerd.mjs +1 -4
  13. package/dist/lib/capabilities.workerd.mjs.map +1 -1
  14. package/dist/lib/chunk-CommandsDialogContent.mjs +30 -21
  15. package/dist/lib/chunk-CommandsDialogContent.mjs.map +1 -1
  16. package/dist/lib/chunk-CommandsTrigger.mjs +9 -7
  17. package/dist/lib/chunk-CommandsTrigger.mjs.map +1 -1
  18. package/dist/lib/chunk-NavTreeDocumentTitle.mjs +4 -3
  19. package/dist/lib/chunk-NavTreeDocumentTitle.mjs.map +1 -1
  20. package/dist/lib/chunk-PLUGIN.mjs +6 -0
  21. package/dist/lib/chunk-PLUGIN.mjs.map +1 -0
  22. package/dist/lib/chunk-app-graph-builder.mjs +1 -1
  23. package/dist/lib/chunk-expose.mjs +4 -4
  24. package/dist/lib/chunk-expose.mjs.map +1 -1
  25. package/dist/lib/chunk-keyboard.mjs +40 -22
  26. package/dist/lib/chunk-keyboard.mjs.map +1 -1
  27. package/dist/lib/chunk-react-surface.mjs +3 -3
  28. package/dist/lib/chunk-react-surface.mjs.map +1 -1
  29. package/dist/lib/chunk-state.mjs +28 -16
  30. package/dist/lib/chunk-state.mjs.map +1 -1
  31. package/dist/lib/chunk-util.mjs +11 -30
  32. package/dist/lib/chunk-util.mjs.map +1 -1
  33. package/dist/lib/components.mjs +258 -236
  34. package/dist/lib/components.mjs.map +1 -1
  35. package/dist/lib/containers.mjs +114 -63
  36. package/dist/lib/containers.mjs.map +1 -1
  37. package/dist/lib/hooks.mjs +16 -92
  38. package/dist/lib/hooks.mjs.map +1 -1
  39. package/dist/lib/index.mjs +2 -3
  40. package/dist/lib/meta.mjs.map +1 -1
  41. package/dist/lib/ns/NavTreeSurface.mjs +8 -0
  42. package/dist/lib/ns/NavTreeSurface.mjs.map +1 -0
  43. package/dist/lib/operations.mjs.map +1 -1
  44. package/dist/lib/testing.mjs +22 -12
  45. package/dist/lib/testing.mjs.map +1 -1
  46. package/dist/lib/translations.mjs +1 -0
  47. package/dist/lib/translations.mjs.map +1 -1
  48. package/dist/types/src/NavTreeSurface.d.ts +2 -0
  49. package/dist/types/src/NavTreeSurface.d.ts.map +1 -0
  50. package/dist/types/src/capabilities/gen/browser.d.ts +10 -0
  51. package/dist/types/src/capabilities/gen/browser.d.ts.map +1 -0
  52. package/dist/types/src/capabilities/gen/node.d.ts +1 -1
  53. package/dist/types/src/capabilities/gen/node.d.ts.map +1 -1
  54. package/dist/types/src/capabilities/gen/tauri.d.ts +10 -0
  55. package/dist/types/src/capabilities/gen/tauri.d.ts.map +1 -0
  56. package/dist/types/src/capabilities/gen/workerd.d.ts +1 -1
  57. package/dist/types/src/capabilities/gen/workerd.d.ts.map +1 -1
  58. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  59. package/dist/types/src/capabilities/keyboard.d.ts.map +1 -1
  60. package/dist/types/src/components/NavTree/NavTree.d.ts +3 -3
  61. package/dist/types/src/components/NavTree/NavTree.d.ts.map +1 -1
  62. package/dist/types/src/components/NavTree/NavTree.stories.d.ts +5 -0
  63. package/dist/types/src/components/NavTree/NavTree.stories.d.ts.map +1 -1
  64. package/dist/types/src/components/NavTree/index.d.ts +1 -1
  65. package/dist/types/src/components/NavTree/index.d.ts.map +1 -1
  66. package/dist/types/src/components/NavTreeContext/NavTreeContext.d.ts +1 -1
  67. package/dist/types/src/components/NavTreeContext/NavTreeContext.d.ts.map +1 -1
  68. package/dist/types/src/components/NavTreeContext/index.d.ts +1 -1
  69. package/dist/types/src/components/NavTreeContext/index.d.ts.map +1 -1
  70. package/dist/types/src/components/NavTreeItem/NavTreeItemAction.d.ts.map +1 -1
  71. package/dist/types/src/components/NavTreeItem/NavTreeItemAction.stories.d.ts +1 -1
  72. package/dist/types/src/components/NavTreeItem/NavTreeItemAction.stories.d.ts.map +1 -1
  73. package/dist/types/src/components/NavTreeItem/NavTreeItemColumns.d.ts +1 -1
  74. package/dist/types/src/components/NavTreeItem/NavTreeItemColumns.d.ts.map +1 -1
  75. package/dist/types/src/components/Sidebar/L0Menu.d.ts +2 -2
  76. package/dist/types/src/components/Sidebar/L0Menu.d.ts.map +1 -1
  77. package/dist/types/src/components/Sidebar/L0PendingAvatar.d.ts +3 -0
  78. package/dist/types/src/components/Sidebar/L0PendingAvatar.d.ts.map +1 -0
  79. package/dist/types/src/components/Sidebar/L1Panel.d.ts +3 -7
  80. package/dist/types/src/components/Sidebar/L1Panel.d.ts.map +1 -1
  81. package/dist/types/src/components/Sidebar/L1Tabs.d.ts +3 -3
  82. package/dist/types/src/components/Sidebar/L1Tabs.d.ts.map +1 -1
  83. package/dist/types/src/components/Sidebar/index.d.ts +4 -3
  84. package/dist/types/src/components/Sidebar/index.d.ts.map +1 -1
  85. package/dist/types/src/components/UserAccountAvatar/UserAccountAvatar.d.ts +7 -5
  86. package/dist/types/src/components/UserAccountAvatar/UserAccountAvatar.d.ts.map +1 -1
  87. package/dist/types/src/components/UserAccountAvatar/UserAccountAvatar.stories.d.ts +3 -1
  88. package/dist/types/src/components/UserAccountAvatar/UserAccountAvatar.stories.d.ts.map +1 -1
  89. package/dist/types/src/components/UserAccountAvatar/index.d.ts +1 -1
  90. package/dist/types/src/components/UserAccountAvatar/index.d.ts.map +1 -1
  91. package/dist/types/src/components/index.d.ts +3 -3
  92. package/dist/types/src/components/index.d.ts.map +1 -1
  93. package/dist/types/src/components/types.d.ts +3 -5
  94. package/dist/types/src/components/types.d.ts.map +1 -1
  95. package/dist/types/src/containers/CommandsDialogContent/CommandsDialogContent.d.ts.map +1 -1
  96. package/dist/types/src/containers/CommandsDialogContent/CommandsDialogContent.stories.d.ts +7 -1
  97. package/dist/types/src/containers/CommandsDialogContent/CommandsDialogContent.stories.d.ts.map +1 -1
  98. package/dist/types/src/containers/CommandsDialogContent/index.d.ts +1 -1
  99. package/dist/types/src/containers/CommandsDialogContent/index.d.ts.map +1 -1
  100. package/dist/types/src/containers/CommandsTrigger/index.d.ts +1 -1
  101. package/dist/types/src/containers/CommandsTrigger/index.d.ts.map +1 -1
  102. package/dist/types/src/containers/NavTreeContainer/NavTreeContainer.d.ts.map +1 -1
  103. package/dist/types/src/containers/NavTreeContainer/index.d.ts +2 -2
  104. package/dist/types/src/containers/NavTreeContainer/index.d.ts.map +1 -1
  105. package/dist/types/src/containers/NavTreeDocumentTitle/NavTreeDocumentTitle.d.ts.map +1 -1
  106. package/dist/types/src/containers/NavTreeDocumentTitle/index.d.ts +1 -1
  107. package/dist/types/src/containers/NavTreeDocumentTitle/index.d.ts.map +1 -1
  108. package/dist/types/src/containers/index.d.ts +1 -1
  109. package/dist/types/src/containers/index.d.ts.map +1 -1
  110. package/dist/types/src/experimental/Tree.d.ts +4 -3
  111. package/dist/types/src/experimental/Tree.d.ts.map +1 -1
  112. package/dist/types/src/experimental/Tree.stories.d.ts +1 -1
  113. package/dist/types/src/experimental/Tree.stories.d.ts.map +1 -1
  114. package/dist/types/src/experimental/visit-nodes.d.ts +1 -1
  115. package/dist/types/src/experimental/visit-nodes.d.ts.map +1 -1
  116. package/dist/types/src/hooks/index.d.ts +4 -4
  117. package/dist/types/src/hooks/index.d.ts.map +1 -1
  118. package/dist/types/src/hooks/useNavTreeModel.d.ts +1 -3
  119. package/dist/types/src/hooks/useNavTreeModel.d.ts.map +1 -1
  120. package/dist/types/src/hooks/useNavTreeState.d.ts +1 -1
  121. package/dist/types/src/hooks/useNavTreeState.d.ts.map +1 -1
  122. package/dist/types/src/index.d.ts +2 -3
  123. package/dist/types/src/index.d.ts.map +1 -1
  124. package/dist/types/src/operations/expose.d.ts.map +1 -1
  125. package/dist/types/src/plugin.browser.test.d.ts +2 -0
  126. package/dist/types/src/plugin.browser.test.d.ts.map +1 -0
  127. package/dist/types/src/testing/app-graph-builder.d.ts +5 -2
  128. package/dist/types/src/testing/app-graph-builder.d.ts.map +1 -1
  129. package/dist/types/src/testing/generator.d.ts.map +1 -1
  130. package/dist/types/src/testing/index.d.ts +3 -3
  131. package/dist/types/src/testing/index.d.ts.map +1 -1
  132. package/dist/types/src/translations.d.ts +1 -0
  133. package/dist/types/src/translations.d.ts.map +1 -1
  134. package/dist/types/src/types/NavTreeCapabilities.d.ts +1 -1
  135. package/dist/types/src/types/NavTreeCapabilities.d.ts.map +1 -1
  136. package/dist/types/src/types/NavTreeNode.d.ts +17 -6
  137. package/dist/types/src/types/NavTreeNode.d.ts.map +1 -1
  138. package/dist/types/src/types/index.d.ts +2 -2
  139. package/dist/types/src/types/index.d.ts.map +1 -1
  140. package/dist/types/src/util.d.ts +9 -3
  141. package/dist/types/src/util.d.ts.map +1 -1
  142. package/dist/types/src/util.test.d.ts +2 -0
  143. package/dist/types/src/util.test.d.ts.map +1 -0
  144. package/dist/types/tsconfig.tsbuildinfo +1 -1
  145. package/package.json +50 -48
  146. package/src/NavTreeSurface.ts +7 -0
  147. package/src/capabilities/gen/browser.ts +83 -0
  148. package/src/capabilities/gen/node.ts +4 -9
  149. package/src/capabilities/gen/tauri.ts +83 -0
  150. package/src/capabilities/gen/workerd.ts +4 -9
  151. package/src/capabilities/index.ts +11 -6
  152. package/src/capabilities/keyboard.ts +52 -27
  153. package/src/capabilities/nav-tree-view-state.test.ts +2 -2
  154. package/src/capabilities/react-surface.ts +3 -3
  155. package/src/capabilities/state.ts +40 -31
  156. package/src/components/NavTree/NavTree.stories.tsx +133 -65
  157. package/src/components/NavTree/NavTree.tsx +14 -11
  158. package/src/components/NavTree/index.ts +1 -1
  159. package/src/components/NavTreeContext/NavTreeContext.ts +1 -1
  160. package/src/components/NavTreeContext/index.ts +1 -1
  161. package/src/components/NavTreeItem/NavTreeItemAction.stories.tsx +4 -4
  162. package/src/components/NavTreeItem/NavTreeItemAction.tsx +29 -47
  163. package/src/components/NavTreeItem/NavTreeItemColumns.tsx +21 -24
  164. package/src/components/Sidebar/L0Menu.tsx +91 -77
  165. package/src/components/Sidebar/L0PendingAvatar.tsx +18 -0
  166. package/src/components/Sidebar/L1Panel.tsx +110 -96
  167. package/src/components/Sidebar/L1Tabs.tsx +6 -17
  168. package/src/components/Sidebar/index.ts +4 -3
  169. package/src/components/UserAccountAvatar/UserAccountAvatar.stories.tsx +9 -1
  170. package/src/components/UserAccountAvatar/UserAccountAvatar.tsx +25 -15
  171. package/src/components/UserAccountAvatar/index.ts +1 -1
  172. package/src/components/index.ts +3 -3
  173. package/src/components/types.ts +4 -6
  174. package/src/containers/CommandsDialogContent/CommandsDialogContent.stories.tsx +28 -7
  175. package/src/containers/CommandsDialogContent/CommandsDialogContent.tsx +36 -29
  176. package/src/containers/CommandsDialogContent/index.ts +1 -1
  177. package/src/containers/CommandsTrigger/CommandsTrigger.tsx +10 -8
  178. package/src/containers/CommandsTrigger/index.ts +1 -1
  179. package/src/containers/NavTreeContainer/NavTreeContainer.tsx +128 -71
  180. package/src/containers/NavTreeContainer/index.ts +2 -2
  181. package/src/containers/NavTreeDocumentTitle/NavTreeDocumentTitle.tsx +6 -3
  182. package/src/containers/NavTreeDocumentTitle/index.ts +1 -1
  183. package/src/containers/index.ts +5 -5
  184. package/src/experimental/Tree.stories.tsx +13 -10
  185. package/src/experimental/Tree.tsx +10 -9
  186. package/src/experimental/visit-nodes.ts +1 -1
  187. package/src/hooks/index.ts +4 -4
  188. package/src/hooks/useActions.ts +4 -4
  189. package/src/hooks/useLoadDescendents.ts +2 -2
  190. package/src/hooks/useNavTreeModel.ts +10 -108
  191. package/src/hooks/useNavTreeState.ts +4 -4
  192. package/src/index.ts +2 -3
  193. package/src/meta.ts +1 -1
  194. package/src/operations/expose.ts +4 -5
  195. package/src/operations/index.ts +1 -1
  196. package/src/plugin.browser.test.ts +174 -0
  197. package/src/testing/app-graph-builder.ts +80 -51
  198. package/src/testing/generator.ts +2 -2
  199. package/src/testing/index.ts +3 -3
  200. package/src/translations.ts +3 -2
  201. package/src/types/NavTreeCapabilities.ts +1 -1
  202. package/src/types/NavTreeNode.ts +18 -6
  203. package/src/types/index.ts +2 -2
  204. package/src/util.test.ts +82 -0
  205. package/src/util.ts +37 -40
package/PLUGIN.mdl CHANGED
@@ -15,9 +15,11 @@ Each extension is defined in the Appendix or resolved via its URI.
15
15
  |-------------|--------------------------------|
16
16
  | `type` | `org.dxos.mdl.type@1.0` |
17
17
  | `feat` | `org.dxos.mdl.feat@1.0` |
18
- | `test` | `org.dxos.mdl.test@1.0` |
18
+ | `scenario` | `org.dxos.mdl.scenario@1.0` |
19
19
  | `component` | `org.dxos.mdl.component@1.0` |
20
- | `op` | `org.dxos.mdl.op@1.0` |
20
+ | `op` | `org.dxos.mdl.op@1.1` |
21
+ | `test` | `org.dxos.mdl.test@1.0` |
22
+ | `step` | `org.dxos.mdl.step@1.0` |
21
23
 
22
24
  ## Types
23
25
 
@@ -150,6 +152,7 @@ component CommandsTrigger
150
152
 
151
153
  ```mdl
152
154
  op expose
155
+ key: org.dxos.operation.appToolkit.expose
153
156
  desc: Expands tree nodes along the path to a subject and marks each as open so the item becomes visible in the NavTree.
154
157
  input:
155
158
  subject: string # attendable DXN or node id
@@ -217,19 +220,22 @@ feat F-3: Item Selection
217
220
  feat F-4: Drag and Drop
218
221
 
219
222
  req F-4.1: NavTree items can be dragged to rearrange within the same parent.
220
- req F-4.2: NavTree items can be dragged to copy or transfer to a different parent.
223
+ req F-4.2: NavTree items can be dragged to a different parent, moving within a shared move scope and linking elsewhere when the target accepts links.
221
224
  req F-4.3:
222
225
  when: drop instruction is rearrange
223
226
  then: onRearrange callback on the parent node is called with the new order
224
227
  req F-4.4:
225
- when: drop instruction is copy
226
- then: onCopy callback on the target node is called
228
+ when: the source's parent and the target share a move scope
229
+ then: onMoveOut is called on the source's parent, then onMoveIn on the target
227
230
  req F-4.5:
228
- when: drop instruction is transfer
229
- then: onTransferStart and onTransferEnd callbacks are called on source and target parents
231
+ when: the drop crosses a move scope and the target accepts links
232
+ then: onLink callback on the target is called and the source's parent is left alone
230
233
  req F-4.6:
231
- when: target node reports blockInstruction for an instruction type
234
+ when: target node's blockInstruction returns true for an instruction
232
235
  then: that instruction is blocked and the drop is not applied
236
+ req F-4.7:
237
+ when: the dropped item would only be listed at the target, its parent elsewhere
238
+ then: the drop indicator is dashed
233
239
  ```
234
240
 
235
241
  ```mdl
@@ -257,7 +263,7 @@ feat F-6: State Persistence
257
263
  ## Acceptance
258
264
 
259
265
  ```mdl
260
- test T-1: Workspace tab switch
266
+ scenario T-1: Workspace tab switch
261
267
  given: two workspace tabs exist in the graph
262
268
  when: user clicks the second workspace tab
263
269
  then:
@@ -267,7 +273,7 @@ test T-1: Workspace tab switch
267
273
  ```
268
274
 
269
275
  ```mdl
270
- test T-2: Tree node expand persists
276
+ scenario T-2: Tree node expand persists
271
277
  given: NavTree is rendered with a collapsed folder node
272
278
  when: user expands the folder
273
279
  then:
@@ -277,7 +283,7 @@ test T-2: Tree node expand persists
277
283
  ```
278
284
 
279
285
  ```mdl
280
- test T-3: Expose navigates to nested item
286
+ scenario T-3: Expose navigates to nested item
281
287
  given: a deeply nested object id is active in the layout
282
288
  when: op:expose is called with that object id
283
289
  then:
@@ -286,7 +292,7 @@ test T-3: Expose navigates to nested item
286
292
  ```
287
293
 
288
294
  ```mdl
289
- test T-4: Select item
295
+ scenario T-4: Select item
290
296
  given: item not currently active
291
297
  when: user selects a tree item
292
298
  then: LayoutOperation.Open is invoked with the item id, disposition 'solo' and the shift modifier
@@ -294,7 +300,7 @@ test T-4: Select item
294
300
  ```
295
301
 
296
302
  ```mdl
297
- test T-5: Command palette opens on keyboard shortcut
303
+ scenario T-5: Command palette opens on keyboard shortcut
298
304
  given: NavTree is active
299
305
  when: user presses ⇧⌘K (macOS) or Ctrl+Shift+K (Windows)
300
306
  then:
@@ -303,7 +309,7 @@ test T-5: Command palette opens on keyboard shortcut
303
309
  ```
304
310
 
305
311
  ```mdl
306
- test T-6: Drag-and-drop rearrange
312
+ scenario T-6: Drag-and-drop rearrange
307
313
  given: two sibling items in the same folder
308
314
  when: user drags the first item below the second
309
315
  then:
@@ -313,6 +319,71 @@ test T-6: Drag-and-drop rearrange
313
319
 
314
320
  ---
315
321
 
322
+ ## QA
323
+
324
+ Executable tests. Each step carries a human instruction (`do`) and, where the step maps to an
325
+ invocable operation, an agent binding (`invoke`). Report failures by test and step number.
326
+
327
+ ```mdl
328
+ test QA-1: Expose a nested document and select it
329
+ desc: |
330
+ NavTree itself is system-tagged and force-enabled (never a user-facing toggle — see
331
+ `getCorePlugins` in `plugin-defs.core.tsx`). Its own `expose` op resolves to
332
+ `LayoutOperation.Expose`, owned by `app-toolkit` and keyed
333
+ `org.dxos.operation.appToolkit.expose` — the same namespace `plugin-markdown`'s worked
334
+ example uses for `open`. The core round-trip: collapse the tree, create a document nested two
335
+ levels deep, then expose it and confirm every ancestor expands and the row becomes visible.
336
+ actors: both
337
+ covers: [F-2.4, F-3.1, T-3, T-4]
338
+ status: unverified
339
+ given:
340
+ - an identity exists
341
+ - space: a space is open
342
+ - collection: a top-level collection in that space
343
+ - subcollection: a second collection nested inside `collection`
344
+ - the navtree is fully collapsed — no descendant of `collection` is currently open
345
+ - no document named "QA Exposed" exists — ABORT rather than deleting one this test did not create
346
+ steps:
347
+ - name: Create a nested document
348
+ do: In the navtree, click + on the nested subcollection and choose Markdown. Name it "QA Exposed".
349
+ invoke: org.dxos.operation.markdown.createDraft { name: "QA Exposed", content: "# QA Exposed\n" }
350
+ capture: created
351
+ expect: a Document named "QA Exposed" now exists
352
+ assert: return !!$created.object
353
+ - name: Place it in the subcollection
354
+ do: (the navtree create action places it for you)
355
+ invoke: org.dxos.operation.space.addObject { object: $created.object, target: $given.subcollection }
356
+ expect: "QA Exposed" is a row under the subcollection, but the subcollection itself is still collapsed since we did not expand it
357
+ assert: |
358
+ return $given.subcollection.objects.some((ref) => ref.target?.id === $created.object.id);
359
+ - name: Expose the document
360
+ id: expose
361
+ do: (no direct gesture — `expose` is invoked internally when e.g. following a search result or a deep link to this document)
362
+ invoke: org.dxos.operation.appToolkit.expose { subject: $created.object.id }
363
+ expect: the top-level collection AND the nested subcollection are both now expanded, and the "QA Exposed" row is visible in the navtree
364
+ assert: |
365
+ return Array.from(document.querySelectorAll('[data-testid="navtree.treeItem"]'))
366
+ .some((el) => el.textContent?.includes('QA Exposed'));
367
+ note: |
368
+ Per Execution Rule 2, the `expose` handler expands each ancestor and marks it open in
369
+ `NavTreeCapabilities.State` — verify by re-reading the DOM after invocation rather than
370
+ the op's `void` return value.
371
+ - name: Select it
372
+ do: Click "QA Exposed" in the now-visible navtree row.
373
+ invoke: org.dxos.operation.appToolkit.open { subject: ["root/$given.space.id/content/collections/$created.object.id"] }
374
+ expect: the document opens in the editor and its navtree row is marked current/selected
375
+ assert: |
376
+ return Array.from(document.querySelectorAll('[aria-current], [aria-selected="true"]'))
377
+ .some((el) => el.textContent?.includes('QA Exposed'));
378
+ after:
379
+ - name: Delete the document
380
+ do: Right-click "QA Exposed" in the navtree and choose Delete.
381
+ invoke: org.dxos.operation.space.removeObjects { objects: [$created.object], target: $given.subcollection }
382
+ expect: the row leaves the navtree and its plank closes
383
+ ```
384
+
385
+ ---
386
+
316
387
  ## Appendix: Extension Definitions
317
388
 
318
389
  ```mdl
@@ -337,8 +408,8 @@ ext feat
337
408
  ```
338
409
 
339
410
  ```mdl
340
- ext test
341
- uri: org.dxos.mdl.test@1.0
411
+ ext scenario
412
+ uri: org.dxos.mdl.scenario@1.0
342
413
  desc: An acceptance scenario expressed as given / when / then steps.
343
414
  fields:
344
415
  given?: Step | Step[]
@@ -1 +1 @@
1
- {"version":3,"file":"NavTreeCapabilities.mjs","names":[],"sources":["../../src/types/NavTreeCapabilities.ts"],"sourcesContent":["//\n// Copyright 2025 DXOS.org\n//\n\n// @import-as-namespace\n\nimport type * as Atom from 'effect/unstable/reactivity/Atom';\n\nimport * as Capability from '@dxos/app-framework/Capability';\n\nimport { meta } from '#meta';\n\nexport type NavTreeItemState = { open: boolean; current: boolean };\n\nexport type NavTreeStateStore = {\n getItem: (path: string[]) => NavTreeItemState;\n getItemAtom: (path: string[]) => Atom.Atom<NavTreeItemState>;\n setItem: (path: string[], key: 'open' | 'current', next: boolean) => void;\n};\n\nexport const State = Capability.makeSingleton<NavTreeStateStore>()(`${meta.profile.key}.capability.state`);\n"],"mappings":";;;;;AAoBA,IAAa,QAAQ,WAAW,cAAiC,CAAC,CAAC,GAAG,KAAK,QAAQ,IAAI,kBAAkB"}
1
+ {"version":3,"file":"NavTreeCapabilities.mjs","names":[],"sources":["../../src/types/NavTreeCapabilities.ts"],"sourcesContent":["//\n// Copyright 2025 DXOS.org\n//\n\n// @import-as-namespace\n\nimport type * as Atom from 'effect/reactivity/Atom';\n\nimport * as Capability from '@dxos/app-framework/Capability';\n\nimport { meta } from '#meta';\n\nexport type NavTreeItemState = { open: boolean; current: boolean };\n\nexport type NavTreeStateStore = {\n getItem: (path: string[]) => NavTreeItemState;\n getItemAtom: (path: string[]) => Atom.Atom<NavTreeItemState>;\n setItem: (path: string[], key: 'open' | 'current', next: boolean) => void;\n};\n\nexport const State = Capability.makeSingleton<NavTreeStateStore>()(`${meta.profile.key}.capability.state`);\n"],"mappings":";;;;;AAoBA,IAAa,QAAQ,WAAW,cAAiC,CAAC,CAAC,GAAG,KAAK,QAAQ,IAAI,kBAAkB"}
@@ -1 +1 @@
1
- {"version":3,"file":"NavTreeNode.mjs","names":[],"sources":["../../src/types/NavTreeNode.ts"],"sourcesContent":["//\n// Copyright 2023 DXOS.org\n//\n\nimport type * as AppGraphNode from '@dxos/app-graph/AppGraphNode';\nimport { type Label } from '@dxos/react-ui';\nimport { type MaybePromise, type Position } from '@dxos/util';\n\nexport type NavTreeItemGraphNode = AppGraphNode.Node<\n any,\n Partial<\n NodeProperties & {\n persistenceClass: string;\n persistenceKey: string;\n acceptPersistenceClass: Set<string>;\n acceptPersistenceKey: Set<string>;\n onRearrange: (nextOrder: unknown[]) => MaybePromise<void>;\n onCopy: (activeNode: NavTreeItemGraphNode, index?: number) => MaybePromise<void>;\n onTransferStart: (activeNode: NavTreeItemGraphNode, index?: number) => MaybePromise<void>;\n onTransferEnd: (activeNode: NavTreeItemGraphNode, destinationParent: NavTreeItemGraphNode) => MaybePromise<void>;\n }\n >\n>;\n\nexport type FlattenedActions = {\n actions: AppGraphNode.ActionLike[];\n groupedActions: Record<string, AppGraphNode.Action[]>;\n};\n\ntype SharedProperties = {\n testId?: string;\n disabled?: boolean;\n position?: Position.Position;\n label: Label;\n className?: string;\n headingClassName?: string;\n icon?: string;\n iconHue?: string;\n};\n\nexport type NodeProperties = SharedProperties & {\n role?: string;\n error?: string;\n modified?: boolean;\n palette?: string;\n /** Optional item count rendered as a neutral badge after the label. */\n count?: number;\n /** Optional count of new/modified items; when greater than zero it shows as a rose badge in place of `count`. */\n modifiedCount?: number;\n};\n\nexport type ActionProperties = SharedProperties & {\n disposition?: string | string[];\n hidden?: boolean;\n caller?: string;\n menuType?: 'dropdown';\n keyBinding?: string | KeyBinding;\n};\n\n/**\n * Platform-specific key binding.\n */\nexport type KeyBinding = {\n // NOTE: Keys come from `getHostPlatform` in `@dxos/util`.\n // TODO(thure): Dedupe with the other platform key-binding definitions.\n windows?: string;\n macos?: string;\n ios?: string;\n linux?: string;\n unknown?: string;\n};\n"],"mappings":""}
1
+ {"version":3,"file":"NavTreeNode.mjs","names":[],"sources":["../../src/types/NavTreeNode.ts"],"sourcesContent":["//\n// Copyright 2023 DXOS.org\n//\n\nimport type { Instruction } from '@atlaskit/pragmatic-drag-and-drop-hitbox/tree-item';\n\nimport type * as AppGraphNode from '@dxos/app-graph/AppGraphNode';\nimport { type TreeData } from '@dxos/react-ui-list';\nimport type * as Theme from '@dxos/react-ui/Theme';\nimport { type MaybePromise } from '@dxos/util';\nimport type * as Position from '@dxos/util/Position';\n\nexport type NavTreeItemGraphNode = AppGraphNode.Node<\n any,\n Partial<\n NodeProperties & {\n persistenceClass: string;\n persistenceKey: string;\n acceptPersistenceClass: Set<string>;\n acceptPersistenceKey: Set<string>;\n /** Parents sharing a scope move items between them; a drop from outside it links instead. */\n moveScope: string;\n canDrop: (source: TreeData) => boolean;\n blockInstruction: (source: TreeData, instruction: Instruction) => boolean;\n /** Whether an item added here would only be listed, its parent elsewhere; `from` is the parent it moves out of. */\n isLink: (activeNode: NavTreeItemGraphNode, from?: NavTreeItemGraphNode) => boolean;\n onRearrange: (nextOrder: unknown[]) => MaybePromise<void>;\n /** An item is moving from here to `destinationParent`; called before the destination's `onMoveIn`. */\n onMoveOut: (activeNode: NavTreeItemGraphNode, destinationParent: NavTreeItemGraphNode) => MaybePromise<void>;\n /** An item is moving here from another parent; `index` is its position among this node's children. */\n onMoveIn: (activeNode: NavTreeItemGraphNode, index?: number) => MaybePromise<void>;\n onLink: (activeNode: NavTreeItemGraphNode, index?: number) => MaybePromise<void>;\n }\n >\n>;\n\nexport type FlattenedActions = {\n actions: AppGraphNode.ActionLike[];\n groupedActions: Record<string, AppGraphNode.Action[]>;\n};\n\ntype SharedProperties = {\n testId?: string;\n disabled?: boolean;\n position?: Position.Position;\n label: Theme.Label;\n className?: string;\n headingClassName?: string;\n icon?: string;\n iconHue?: string;\n};\n\nexport type NodeProperties = SharedProperties & {\n role?: string;\n error?: string;\n modified?: boolean;\n palette?: string;\n /** Optional item count rendered as a neutral badge after the label. */\n count?: number;\n /** Optional count of new/modified items; when greater than zero it shows as a rose badge in place of `count`. */\n modifiedCount?: number;\n};\n\nexport type ActionProperties = SharedProperties & {\n disposition?: string | string[];\n hidden?: boolean;\n caller?: string;\n menuType?: 'dropdown';\n keyBinding?: string | KeyBinding;\n};\n\n/**\n * Platform-specific key binding.\n */\nexport type KeyBinding = {\n // NOTE: Keys come from `getHostPlatform` in `@dxos/util`.\n // TODO(thure): Dedupe with the other platform key-binding definitions.\n windows?: string;\n macos?: string;\n ios?: string;\n linux?: string;\n unknown?: string;\n};\n"],"mappings":""}
@@ -0,0 +1,59 @@
1
+ import { t as PLUGIN_default } from "./chunk-PLUGIN.mjs";
2
+ import * as Effect from "effect/Effect";
3
+ import * as Capabilities from "@dxos/app-framework/Capabilities";
4
+ import * as Capability from "@dxos/app-framework/Capability";
5
+ import * as AppGraph from "@dxos/app-graph/AppGraph";
6
+ import * as AppCapabilities from "@dxos/app-toolkit/AppCapabilities";
7
+ import * as AppCapability from "@dxos/app-toolkit/AppCapability";
8
+ import * as LayoutOperation from "@dxos/app-toolkit/LayoutOperation";
9
+ import * as AttentionCapabilities from "@dxos/plugin-attention/AttentionCapabilities";
10
+ import { translations } from "#translations";
11
+ import { NavTreeCapabilities } from "#types";
12
+ import { meta } from "#meta";
13
+ //#region src/capabilities/gen/browser.ts
14
+ var AppGraphBuilder = AppCapability.appGraphBuilder(() => import("./chunk-app-graph-builder.mjs"));
15
+ var Expose = Capability.inlineModule("expose", {
16
+ requires: [
17
+ AppCapabilities.AppGraph,
18
+ AppCapabilities.Layout,
19
+ Capabilities.OperationInvoker
20
+ ],
21
+ provides: []
22
+ }, Effect.fnUntraced(function* () {
23
+ const layout = yield* Capabilities.getAtomValue(AppCapabilities.Layout);
24
+ const { invokePromise } = yield* Capabilities.OperationInvoker;
25
+ const { graph } = yield* AppCapabilities.AppGraph;
26
+ if (invokePromise && layout.active.length === 1) AppGraph.waitForPath(graph, { target: layout.active[0] }, { timeout: 3e4 }).then(() => invokePromise(LayoutOperation.Expose, { subject: layout.active[0] })).catch(() => {});
27
+ return [];
28
+ }));
29
+ var Keyboard = Capability.lazyModule("Keyboard", {
30
+ requires: [AppCapabilities.AppGraph, Capabilities.OperationInvoker],
31
+ provides: [],
32
+ environments: ["browser", "tauri"]
33
+ }, () => import("./chunk-keyboard.mjs"));
34
+ var OperationHandler = AppCapability.operationHandler(() => import("./chunk-operation-handler.mjs"));
35
+ var PluginAsset = AppCapability.pluginAsset({
36
+ pluginId: meta.profile.key,
37
+ path: "PLUGIN.mdl",
38
+ content: PLUGIN_default,
39
+ mimeType: "application/x-mdl"
40
+ });
41
+ var ReactSurface = AppCapability.surface(() => import("./chunk-react-surface.mjs"), { roles: [
42
+ "org.dxos.role.dialog",
43
+ "org.dxos.role.documentTitle",
44
+ "org.dxos.role.navigation",
45
+ "org.dxos.role.searchInput"
46
+ ] });
47
+ var State = Capability.lazyModule("State", {
48
+ requires: [
49
+ Capabilities.AtomRegistry,
50
+ AppCapabilities.Layout,
51
+ AttentionCapabilities.ViewState
52
+ ],
53
+ provides: [NavTreeCapabilities.State]
54
+ }, () => import("./chunk-state.mjs"));
55
+ var Translations = AppCapability.translations(translations);
56
+ //#endregion
57
+ export { AppGraphBuilder, Expose, Keyboard, OperationHandler, PluginAsset, ReactSurface, State, Translations };
58
+
59
+ //# sourceMappingURL=capabilities.browser.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capabilities.browser.mjs","names":[],"sources":["../../src/capabilities/gen/browser.ts"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\n// GENERATED by dx-plugin — do not edit. Sliced from ../index.ts for the 'browser' condition.\n\nimport * as Effect from 'effect/Effect';\n\nimport * as Capabilities from '@dxos/app-framework/Capabilities';\nimport * as Capability from '@dxos/app-framework/Capability';\nimport * as AppGraph from '@dxos/app-graph/AppGraph';\nimport * as AppCapabilities from '@dxos/app-toolkit/AppCapabilities';\nimport * as AppCapability from '@dxos/app-toolkit/AppCapability';\nimport * as LayoutOperation from '@dxos/app-toolkit/LayoutOperation';\nimport * as AttentionCapabilities from '@dxos/plugin-attention/AttentionCapabilities';\n\nimport { meta } from '#meta';\nimport { translations } from '#translations';\nimport { NavTreeCapabilities } from '#types';\n\nimport pluginSpec from '../../../PLUGIN.mdl?raw';\n\nexport const AppGraphBuilder = AppCapability.appGraphBuilder(() => import('../app-graph-builder.ts'));\n\nexport const Expose = Capability.inlineModule(\n 'expose',\n { requires: [AppCapabilities.AppGraph, AppCapabilities.Layout, Capabilities.OperationInvoker], provides: [] },\n Effect.fnUntraced(function* () {\n const layout = yield* Capabilities.getAtomValue(AppCapabilities.Layout);\n const { invokePromise } = yield* Capabilities.OperationInvoker;\n const { graph } = yield* AppCapabilities.AppGraph;\n if (invokePromise && layout.active.length === 1) {\n // TODO(wittjosiah): This should really be fired once the navtree renders for the first time.\n // That is the point at which the graph is expanded and the path should be available.\n void AppGraph.waitForPath(graph, { target: layout.active[0] }, { timeout: 30_000 })\n .then(() => invokePromise(LayoutOperation.Expose, { subject: layout.active[0] }))\n .catch(() => {});\n }\n\n return [];\n }),\n);\n\nexport const Keyboard = Capability.lazyModule(\n 'Keyboard',\n // Listens on `document`, which node and workerd lack.\n {\n requires: [AppCapabilities.AppGraph, Capabilities.OperationInvoker],\n provides: [],\n environments: ['browser', 'tauri'],\n },\n () => import('../keyboard.ts'),\n);\n\nexport const OperationHandler = AppCapability.operationHandler(() => import('../operation-handler.ts'));\n\nexport const PluginAsset = AppCapability.pluginAsset({\n pluginId: meta.profile.key,\n path: 'PLUGIN.mdl',\n content: pluginSpec,\n mimeType: 'application/x-mdl',\n});\n\nexport const ReactSurface = AppCapability.surface(() => import('../react-surface.ts'), {\n roles: [\n 'org.dxos.role.dialog',\n 'org.dxos.role.documentTitle',\n 'org.dxos.role.navigation',\n 'org.dxos.role.searchInput',\n ],\n});\n\nexport const State = Capability.lazyModule(\n 'State',\n {\n // ViewState is the persistence backend for per-path expansion.\n requires: [Capabilities.AtomRegistry, AppCapabilities.Layout, AttentionCapabilities.ViewState],\n provides: [NavTreeCapabilities.State],\n },\n () => import('../state.ts'),\n);\n\nexport const Translations = AppCapability.translations(translations);\n"],"mappings":";;;;;;;;;;;;;AAsBA,IAAa,kBAAkB,cAAc,sBAAsB,OAAO,gCAA0B;AAEpG,IAAa,SAAS,WAAW,aAC/B,UACA;CAAE,UAAU;EAAC,gBAAgB;EAAU,gBAAgB;EAAQ,aAAa;CAAgB;CAAG,UAAU,CAAC;AAAE,GAC5G,OAAO,WAAW,aAAa;CAC7B,MAAM,SAAS,OAAO,aAAa,aAAa,gBAAgB,MAAM;CACtE,MAAM,EAAE,kBAAkB,OAAO,aAAa;CAC9C,MAAM,EAAE,UAAU,OAAO,gBAAgB;CACzC,IAAI,iBAAiB,OAAO,OAAO,WAAW,GAG5C,SAAc,YAAY,OAAO,EAAE,QAAQ,OAAO,OAAO,GAAG,GAAG,EAAE,SAAS,IAAO,CAAC,CAAA,CAC/E,WAAW,cAAc,gBAAgB,QAAQ,EAAE,SAAS,OAAO,OAAO,GAAG,CAAC,CAAC,CAAA,CAC/E,YAAY,CAAC,CAAC;CAGnB,OAAO,CAAC;AACV,CAAC,CACH;AAEA,IAAa,WAAW,WAAW,WACjC,YAEA;CACE,UAAU,CAAC,gBAAgB,UAAU,aAAa,gBAAgB;CAClE,UAAU,CAAC;CACX,cAAc,CAAC,WAAW,OAAO;AACnC,SACM,OAAO,uBACf;AAEA,IAAa,mBAAmB,cAAc,uBAAuB,OAAO,gCAA0B;AAEtG,IAAa,cAAc,cAAc,YAAY;CACnD,UAAU,KAAK,QAAQ;CACvB,MAAM;CACN,SAAS;CACT,UAAU;AACZ,CAAC;AAED,IAAa,eAAe,cAAc,cAAc,OAAO,8BAAwB,EACrF,OAAO;CACL;CACA;CACA;CACA;AACF,EACF,CAAC;AAED,IAAa,QAAQ,WAAW,WAC9B,SACA;CAEE,UAAU;EAAC,aAAa;EAAc,gBAAgB;EAAQ,sBAAsB;CAAS;CAC7F,UAAU,CAAC,oBAAoB,KAAK;AACtC,SACM,OAAO,oBACf;AAEA,IAAa,eAAe,cAAc,aAAa,YAAY"}
@@ -1,3 +1,4 @@
1
+ import { t as PLUGIN_default } from "./chunk-PLUGIN.mjs";
1
2
  import * as Effect from "effect/Effect";
2
3
  import * as Capabilities from "@dxos/app-framework/Capabilities";
3
4
  import * as Capability from "@dxos/app-framework/Capability";
@@ -9,9 +10,6 @@ import * as AttentionCapabilities from "@dxos/plugin-attention/AttentionCapabili
9
10
  import { translations } from "#translations";
10
11
  import { NavTreeCapabilities } from "#types";
11
12
  import { meta } from "#meta";
12
- //#region PLUGIN.mdl?raw
13
- var PLUGIN_default = "---\nid: org.dxos.plugin.navtree\nname: NavTreePlugin\nversion: 0.1.0\n---\n\nHierarchical navigation sidebar for `DXOS` Composer — renders the application graph as a collapsible tree, manages workspace tabs, exposes keyboard-driven command search, and handles drag-and-drop rearrangement of spaces, folders, and objects.\n\n## Extensions\n\nThe following extension dialects are used in this document.\nEach extension is defined in the Appendix or resolved via its URI.\n\n| Term | URI |\n|-------------|--------------------------------|\n| `type` | `org.dxos.mdl.type@1.0` |\n| `feat` | `org.dxos.mdl.feat@1.0` |\n| `test` | `org.dxos.mdl.test@1.0` |\n| `component` | `org.dxos.mdl.component@1.0` |\n| `op` | `org.dxos.mdl.op@1.0` |\n\n## Types\n\n```mdl\ntype NavTreeItemState\n fields:\n open: boolean # whether the tree node is expanded\n current: boolean # whether the node is in the active layout\n```\n\n```mdl\ntype KeyBinding\n fields:\n macos?: string\n windows?: string\n linux?: string\n ios?: string\n unknown?: string\n```\n\n```mdl\ntype NodeProperties\n fields:\n label: Label\n icon?: string\n iconHue?: string\n role?: string\n error?: string\n modified?: boolean\n palette?: string\n disabled?: boolean\n testId?: string\n position?: Position\n className?: string\n keyBinding?: string | KeyBinding\n persistenceClass?: string\n persistenceKey?: string\n```\n\n## Components\n\n```mdl\ncomponent NavTree\n desc: Root navigation tree that renders workspace tabs at the top level and a collapsible subtree for the active workspace.\n props:\n id: string # root node id (Node.RootId)\n root: Node # root of the application graph\n tab: string # currently active workspace tab id\n open: boolean # whether the navigation sidebar is open\n state:\n model: NavTreeModel # live tree model built from graph connections\n slots:\n itemEnd?: ReactNode # per-item trailing content (e.g. action badges)\n actions:\n openChange(item: Node, path: string[], open: boolean)\n tabChange(node: Node)\n select(item: Node, path: string[], option: boolean, shift: boolean)\n back()\n itemHover(item: Node)\n layout: |\n ┌─────────────────────────┐\n │ workspace tabs │\n │ [tab] [tab] [tab] │\n ├─────────────────────────┤\n │ collapsible tree │\n │ ▾ Space │\n │ ▾ Folder │\n │ • Object │\n │ • Object │\n │ • Object │\n └─────────────────────────┘\n```\n\n```mdl\ncomponent NavTreeContainer\n desc: Smart container that wires the NavTree to the app graph, layout state, and drag-and-drop monitor.\n props:\n tab: string\n popoverAnchorId?: string\n state:\n layout: LayoutState # active items, sidebar open/closed, mode\n model: NavTreeModel\n actions:\n handleSelect(item: Node, path: string[], option: boolean, shift: boolean)\n handleOpenChange(item: Node, path: string[], open: boolean)\n handleTabChange(node: Node)\n handleBack()\n handleDrop(source: TreeData, target: TreeData, instruction: Instruction)\n emits:\n onNavigate(subject: string | string[])\n layout: |\n ┌──────────────────────────┐\n │ NavTreeContext.Provider │\n │ └─ NavTree │\n └──────────────────────────┘\n```\n\n```mdl\ncomponent CommandsDialogContent\n desc: Full-screen command palette dialog — surfaces all graph actions, searchable by label.\n props:\n onClose?: () => void\n state:\n query: string\n results: Node[]\n actions:\n search(query: string) → Node[]\n execute(node: Node)\n layout: |\n ┌──────────────────────────┐\n │ [search input] │\n ├──────────────────────────┤\n │ result list │\n │ icon label shortcut │\n │ icon label │\n │ … │\n └──────────────────────────┘\n```\n\n```mdl\ncomponent CommandsTrigger\n desc: Search-input surface slot component — opens the commands dialog on click or ⇧⌘K / Ctrl+Shift+K.\n slots:\n (none)\n actions:\n openCommandsDialog()\n```\n\n## Operations\n\n```mdl\nop expose\n desc: Expands tree nodes along the path to a subject and marks each as open so the item becomes visible in the NavTree.\n input:\n subject: string # attendable DXN or node id\n output: void\n effects: [echo:read]\n note: |\n Resolves the full ancestor path via expandAttendableId, calls Graph.expand per node,\n then sets each path segment open in NavTreeCapabilities.State.\n```\n\n## Features\n\n```mdl\nfeat F-1: Sidebar Navigation\n\n req F-1.1: NavTree renders all root-level graph connections as workspace tabs.\n req F-1.2:\n when: user selects a workspace tab\n then: LayoutOperation.SwitchWorkspace is invoked; subtree for that workspace is expanded\n req F-1.3:\n when: sidebar is closed and user selects a workspace tab\n then: sidebar opens (state transitions to expanded)\n req F-1.4:\n when: same active tab is clicked while sidebar is expanded\n then: sidebar collapses (state transitions to collapsed or closed on mobile)\n```\n\n```mdl\nfeat F-2: Tree Expand / Collapse\n\n req F-2.1: Tree items with children show an expand/collapse toggle.\n req F-2.2:\n when: user expands a node\n then: open state persisted to localStorage keyed by path; Graph.expand called for the node\n req F-2.3:\n when: plugin initialises after layout is ready\n then: all paths previously marked open are re-expanded from localStorage\n req F-2.4:\n when: op:expose is called\n then: all ancestors of the subject are expanded and marked open\n```\n\n```mdl\nfeat F-3: Item Selection\n\n req F-3.1:\n when: user selects a non-current item\n then: LayoutOperation.Open is invoked with disposition 'solo' and the shift modifier forwarded\n (the Open handler upgrades any disposition to 'add' when shift is held)\n req F-3.2:\n when: user option-clicks a currently active item\n then: LayoutOperation.Close is invoked for that item\n req F-3.3:\n when: user clicks a currently active item without option key\n then: LayoutOperation.ScrollIntoView is invoked\n req F-3.4:\n when: item has a default disposition action\n then: that action is run after navigation\n req F-3.5:\n when: navigation succeeds on mobile\n then: sidebar is closed automatically\n```\n\n```mdl\nfeat F-4: Drag and Drop\n\n req F-4.1: NavTree items can be dragged to rearrange within the same parent.\n req F-4.2: NavTree items can be dragged to copy or transfer to a different parent.\n req F-4.3:\n when: drop instruction is rearrange\n then: onRearrange callback on the parent node is called with the new order\n req F-4.4:\n when: drop instruction is copy\n then: onCopy callback on the target node is called\n req F-4.5:\n when: drop instruction is transfer\n then: onTransferStart and onTransferEnd callbacks are called on source and target parents\n req F-4.6:\n when: target node reports blockInstruction for an instruction type\n then: that instruction is blocked and the drop is not applied\n```\n\n```mdl\nfeat F-5: Keyboard Shortcuts\n\n req F-5.1: NavTree plugin registers keyboard shortcuts for all graph actions that declare a keyBinding property.\n req F-5.2: Graph is traversed on change (debounced 500 ms) to bind newly added shortcuts.\n req F-5.3: The commands dialog is opened via ⇧⌘K (macOS) / Ctrl+Shift+K (Windows/Linux).\n req F-5.4:\n when: plugin deactivates\n then: Keyboard.singleton is destroyed and all shortcuts are unregistered\n```\n\n```mdl\nfeat F-6: State Persistence\n\n req F-6.1: Per-path open/current state is stored in an atom family keyed by path string.\n req F-6.2: Open state (not current) is persisted to localStorage on every change.\n req F-6.3: Current state reflects active layout items and is never persisted.\n req F-6.4:\n when: layout.active changes\n then: removed items are marked not-current; newly active items are marked current\n```\n\n## Acceptance\n\n```mdl\ntest T-1: Workspace tab switch\n given: two workspace tabs exist in the graph\n when: user clicks the second workspace tab\n then:\n - LayoutOperation.SwitchWorkspace is invoked with the tab's node id\n - sidebar transitions to expanded\n - subtree for the selected workspace is expanded\n```\n\n```mdl\ntest T-2: Tree node expand persists\n given: NavTree is rendered with a collapsed folder node\n when: user expands the folder\n then:\n - folder node state.open === true\n - localStorage entry updated for the folder's path\n - Graph.expand called for the folder node id\n```\n\n```mdl\ntest T-3: Expose navigates to nested item\n given: a deeply nested object id is active in the layout\n when: op:expose is called with that object id\n then:\n - all ancestor paths are marked open\n - Graph.expand is called for each ancestor\n```\n\n```mdl\ntest T-4: Select item\n given: item not currently active\n when: user selects a tree item\n then: LayoutOperation.Open is invoked with the item id, disposition 'solo' and the shift modifier\n forwarded (shift-click therefore adds a plank instead of navigating)\n```\n\n```mdl\ntest T-5: Command palette opens on keyboard shortcut\n given: NavTree is active\n when: user presses ⇧⌘K (macOS) or Ctrl+Shift+K (Windows)\n then:\n - CommandsDialogContent is shown in the layout dialog slot\n - search input is focused\n```\n\n```mdl\ntest T-6: Drag-and-drop rearrange\n given: two sibling items in the same folder\n when: user drags the first item below the second\n then:\n - onRearrange callback is called with the reordered array\n - tree re-renders with the new order\n```\n\n---\n\n## Appendix: Extension Definitions\n\n```mdl\next type\n uri: org.dxos.mdl.type@1.0\n desc: A named data structure with typed fields and optional literals.\n fields:\n desc?: Prose\n fields?: FieldMap\n literals?: UnionList\n extends?: TypeRef[]\n```\n\n```mdl\next feat\n uri: org.dxos.mdl.feat@1.0\n desc: A named feature grouping one or more requirements.\n fields:\n desc?: Prose\n req: RequirementList\n nesting: self\n```\n\n```mdl\next test\n uri: org.dxos.mdl.test@1.0\n desc: An acceptance scenario expressed as given / when / then steps.\n fields:\n given?: Step | Step[]\n when?: Step | Step[]\n then: Step | Step[]\n tags?: TagList\n```\n\n```mdl\next component\n uri: org.dxos.mdl.component@1.0\n desc: A UI component with props, internal state, slots, actions, and events.\n fields:\n desc?: Prose\n props?: FieldMap\n state?: FieldMap\n slots?: FieldMap\n actions?: ActionMap\n emits?: EventMap\n layout?: CodeBlock\n```\n\n```mdl\next op\n uri: org.dxos.mdl.op@1.0\n desc: |\n A named operation with typed inputs, outputs, and declared errors.\n Pure ops have no effects or requires. Effectful ops declare both.\n fields:\n desc?: Prose\n input?: FieldMap\n output?: TypeExpr\n errors?: ErrorMap\n effects?: EffectList\n requires?: ServiceList\n note?: Prose\n```\n";
14
- //#endregion
15
13
  //#region src/capabilities/index.ts
16
14
  var AppGraphBuilder = AppCapability.appGraphBuilder(() => import("./chunk-app-graph-builder.mjs"));
17
15
  var Expose = Capability.inlineModule("expose", {
@@ -30,7 +28,8 @@ var Expose = Capability.inlineModule("expose", {
30
28
  }));
31
29
  var Keyboard = Capability.lazyModule("Keyboard", {
32
30
  requires: [AppCapabilities.AppGraph, Capabilities.OperationInvoker],
33
- provides: []
31
+ provides: [],
32
+ environments: ["browser", "tauri"]
34
33
  }, () => import("./chunk-keyboard.mjs"));
35
34
  var OperationHandler = AppCapability.operationHandler(() => import("./chunk-operation-handler.mjs"));
36
35
  var PluginAsset = AppCapability.pluginAsset({
@@ -1 +1 @@
1
- {"version":3,"file":"capabilities.mjs","names":[],"sources":["../../src/capabilities/index.ts"],"sourcesContent":["//\n// Copyright 2025 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\n\nimport * as Capabilities from '@dxos/app-framework/Capabilities';\nimport * as Capability from '@dxos/app-framework/Capability';\nimport * as AppGraph from '@dxos/app-graph/AppGraph';\nimport * as AppCapabilities from '@dxos/app-toolkit/AppCapabilities';\nimport * as AppCapability from '@dxos/app-toolkit/AppCapability';\nimport * as LayoutOperation from '@dxos/app-toolkit/LayoutOperation';\nimport * as AttentionCapabilities from '@dxos/plugin-attention/AttentionCapabilities';\n\nimport { meta } from '#meta';\nimport { translations } from '#translations';\nimport { NavTreeCapabilities } from '#types';\n\n// eslint-disable-next-line import/no-relative-packages\nimport pluginSpec from '../../PLUGIN.mdl?raw';\n\nexport const AppGraphBuilder = AppCapability.appGraphBuilder(() => import('./app-graph-builder'));\nexport const Expose = Capability.inlineModule(\n 'expose',\n { requires: [AppCapabilities.AppGraph, AppCapabilities.Layout, Capabilities.OperationInvoker], provides: [] },\n Effect.fnUntraced(function* () {\n const layout = yield* Capabilities.getAtomValue(AppCapabilities.Layout);\n const { invokePromise } = yield* Capabilities.OperationInvoker;\n const { graph } = yield* AppCapabilities.AppGraph;\n if (invokePromise && layout.active.length === 1) {\n // TODO(wittjosiah): This should really be fired once the navtree renders for the first time.\n // That is the point at which the graph is expanded and the path should be available.\n void AppGraph.waitForPath(graph, { target: layout.active[0] }, { timeout: 30_000 })\n .then(() => invokePromise(LayoutOperation.Expose, { subject: layout.active[0] }))\n .catch(() => {});\n }\n\n return [];\n }),\n);\nexport const Keyboard = Capability.lazyModule(\n 'Keyboard',\n { requires: [AppCapabilities.AppGraph, Capabilities.OperationInvoker], provides: [] },\n () => import('./keyboard'),\n);\nexport const OperationHandler = AppCapability.operationHandler(() => import('./operation-handler'));\nexport const PluginAsset = AppCapability.pluginAsset({\n pluginId: meta.profile.key,\n path: 'PLUGIN.mdl',\n content: pluginSpec,\n mimeType: 'application/x-mdl',\n});\nexport const ReactSurface = AppCapability.surface(() => import('./react-surface'), {\n roles: [\n 'org.dxos.role.dialog',\n 'org.dxos.role.documentTitle',\n 'org.dxos.role.navigation',\n 'org.dxos.role.searchInput',\n ],\n});\nexport const State = Capability.lazyModule(\n 'State',\n {\n // ViewState is the persistence backend for per-path expansion.\n requires: [Capabilities.AtomRegistry, AppCapabilities.Layout, AttentionCapabilities.ViewState],\n provides: [NavTreeCapabilities.State],\n },\n () => import('./state'),\n);\nexport const Translations = AppCapability.translations(translations);\n"],"mappings":";;;;;;;;;;;;;;;AAqBA,IAAa,kBAAkB,cAAc,sBAAsB,OAAO,gCAAsB;AAChG,IAAa,SAAS,WAAW,aAC/B,UACA;CAAE,UAAU;EAAC,gBAAgB;EAAU,gBAAgB;EAAQ,aAAa;CAAgB;CAAG,UAAU,CAAC;AAAE,GAC5G,OAAO,WAAW,aAAa;CAC7B,MAAM,SAAS,OAAO,aAAa,aAAa,gBAAgB,MAAM;CACtE,MAAM,EAAE,kBAAkB,OAAO,aAAa;CAC9C,MAAM,EAAE,UAAU,OAAO,gBAAgB;CACzC,IAAI,iBAAiB,OAAO,OAAO,WAAW,GAG5C,SAAc,YAAY,OAAO,EAAE,QAAQ,OAAO,OAAO,GAAG,GAAG,EAAE,SAAS,IAAO,CAAC,CAAA,CAC/E,WAAW,cAAc,gBAAgB,QAAQ,EAAE,SAAS,OAAO,OAAO,GAAG,CAAC,CAAC,CAAA,CAC/E,YAAY,CAAC,CAAC;CAGnB,OAAO,CAAC;AACV,CAAC,CACH;AACA,IAAa,WAAW,WAAW,WACjC,YACA;CAAE,UAAU,CAAC,gBAAgB,UAAU,aAAa,gBAAgB;CAAG,UAAU,CAAC;AAAE,SAC9E,OAAO,uBACf;AACA,IAAa,mBAAmB,cAAc,uBAAuB,OAAO,gCAAsB;AAClG,IAAa,cAAc,cAAc,YAAY;CACnD,UAAU,KAAK,QAAQ;CACvB,MAAM;CACN,SAAS;CACT,UAAU;AACZ,CAAC;AACD,IAAa,eAAe,cAAc,cAAc,OAAO,8BAAoB,EACjF,OAAO;CACL;CACA;CACA;CACA;AACF,EACF,CAAC;AACD,IAAa,QAAQ,WAAW,WAC9B,SACA;CAEE,UAAU;EAAC,aAAa;EAAc,gBAAgB;EAAQ,sBAAsB;CAAS;CAC7F,UAAU,CAAC,oBAAoB,KAAK;AACtC,SACM,OAAO,oBACf;AACA,IAAa,eAAe,cAAc,aAAa,YAAY"}
1
+ {"version":3,"file":"capabilities.mjs","names":[],"sources":["../../src/capabilities/index.ts"],"sourcesContent":["//\n// Copyright 2025 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\n\nimport * as Capabilities from '@dxos/app-framework/Capabilities';\nimport * as Capability from '@dxos/app-framework/Capability';\nimport * as AppGraph from '@dxos/app-graph/AppGraph';\nimport * as AppCapabilities from '@dxos/app-toolkit/AppCapabilities';\nimport * as AppCapability from '@dxos/app-toolkit/AppCapability';\nimport * as LayoutOperation from '@dxos/app-toolkit/LayoutOperation';\nimport * as AttentionCapabilities from '@dxos/plugin-attention/AttentionCapabilities';\n\nimport { meta } from '#meta';\nimport { translations } from '#translations';\nimport { NavTreeCapabilities } from '#types';\n\n// eslint-disable-next-line import/no-relative-packages\nimport pluginSpec from '../../PLUGIN.mdl?raw';\n\nexport const AppGraphBuilder = AppCapability.appGraphBuilder(() => import('./app-graph-builder.ts'));\nexport const Expose = Capability.inlineModule(\n 'expose',\n { requires: [AppCapabilities.AppGraph, AppCapabilities.Layout, Capabilities.OperationInvoker], provides: [] },\n Effect.fnUntraced(function* () {\n const layout = yield* Capabilities.getAtomValue(AppCapabilities.Layout);\n const { invokePromise } = yield* Capabilities.OperationInvoker;\n const { graph } = yield* AppCapabilities.AppGraph;\n if (invokePromise && layout.active.length === 1) {\n // TODO(wittjosiah): This should really be fired once the navtree renders for the first time.\n // That is the point at which the graph is expanded and the path should be available.\n void AppGraph.waitForPath(graph, { target: layout.active[0] }, { timeout: 30_000 })\n .then(() => invokePromise(LayoutOperation.Expose, { subject: layout.active[0] }))\n .catch(() => {});\n }\n\n return [];\n }),\n);\nexport const Keyboard = Capability.lazyModule(\n 'Keyboard',\n // Listens on `document`, which node and workerd lack.\n {\n requires: [AppCapabilities.AppGraph, Capabilities.OperationInvoker],\n provides: [],\n environments: ['browser', 'tauri'],\n },\n () => import('./keyboard.ts'),\n);\nexport const OperationHandler = AppCapability.operationHandler(() => import('./operation-handler.ts'));\nexport const PluginAsset = AppCapability.pluginAsset({\n pluginId: meta.profile.key,\n path: 'PLUGIN.mdl',\n content: pluginSpec,\n mimeType: 'application/x-mdl',\n});\nexport const ReactSurface = AppCapability.surface(() => import('./react-surface.ts'), {\n roles: [\n 'org.dxos.role.dialog',\n 'org.dxos.role.documentTitle',\n 'org.dxos.role.navigation',\n 'org.dxos.role.searchInput',\n ],\n});\nexport const State = Capability.lazyModule(\n 'State',\n {\n // ViewState is the persistence backend for per-path expansion.\n requires: [Capabilities.AtomRegistry, AppCapabilities.Layout, AttentionCapabilities.ViewState],\n provides: [NavTreeCapabilities.State],\n },\n () => import('./state.ts'),\n);\nexport const Translations = AppCapability.translations(translations);\n"],"mappings":";;;;;;;;;;;;;AAqBA,IAAa,kBAAkB,cAAc,sBAAsB,OAAO,gCAAyB;AACnG,IAAa,SAAS,WAAW,aAC/B,UACA;CAAE,UAAU;EAAC,gBAAgB;EAAU,gBAAgB;EAAQ,aAAa;CAAgB;CAAG,UAAU,CAAC;AAAE,GAC5G,OAAO,WAAW,aAAa;CAC7B,MAAM,SAAS,OAAO,aAAa,aAAa,gBAAgB,MAAM;CACtE,MAAM,EAAE,kBAAkB,OAAO,aAAa;CAC9C,MAAM,EAAE,UAAU,OAAO,gBAAgB;CACzC,IAAI,iBAAiB,OAAO,OAAO,WAAW,GAG5C,SAAc,YAAY,OAAO,EAAE,QAAQ,OAAO,OAAO,GAAG,GAAG,EAAE,SAAS,IAAO,CAAC,CAAA,CAC/E,WAAW,cAAc,gBAAgB,QAAQ,EAAE,SAAS,OAAO,OAAO,GAAG,CAAC,CAAC,CAAA,CAC/E,YAAY,CAAC,CAAC;CAGnB,OAAO,CAAC;AACV,CAAC,CACH;AACA,IAAa,WAAW,WAAW,WACjC,YAEA;CACE,UAAU,CAAC,gBAAgB,UAAU,aAAa,gBAAgB;CAClE,UAAU,CAAC;CACX,cAAc,CAAC,WAAW,OAAO;AACnC,SACM,OAAO,uBACf;AACA,IAAa,mBAAmB,cAAc,uBAAuB,OAAO,gCAAyB;AACrG,IAAa,cAAc,cAAc,YAAY;CACnD,UAAU,KAAK,QAAQ;CACvB,MAAM;CACN,SAAS;CACT,UAAU;AACZ,CAAC;AACD,IAAa,eAAe,cAAc,cAAc,OAAO,8BAAuB,EACpF,OAAO;CACL;CACA;CACA;CACA;AACF,EACF,CAAC;AACD,IAAa,QAAQ,WAAW,WAC9B,SACA;CAEE,UAAU;EAAC,aAAa;EAAc,gBAAgB;EAAQ,sBAAsB;CAAS;CAC7F,UAAU,CAAC,oBAAoB,KAAK;AACtC,SACM,OAAO,oBACf;AACA,IAAa,eAAe,cAAc,aAAa,YAAY"}
@@ -24,10 +24,6 @@ var Expose = Capability.inlineModule("expose", {
24
24
  if (invokePromise && layout.active.length === 1) AppGraph.waitForPath(graph, { target: layout.active[0] }, { timeout: 3e4 }).then(() => invokePromise(LayoutOperation.Expose, { subject: layout.active[0] })).catch(() => {});
25
25
  return [];
26
26
  }));
27
- var Keyboard = Capability.lazyModule("Keyboard", {
28
- requires: [AppCapabilities.AppGraph, Capabilities.OperationInvoker],
29
- provides: []
30
- }, () => import("./chunk-keyboard.mjs"));
31
27
  var OperationHandler = AppCapability.operationHandler(() => import("./chunk-operation-handler.mjs"));
32
28
  var State = Capability.lazyModule("State", {
33
29
  requires: [
@@ -38,6 +34,7 @@ var State = Capability.lazyModule("State", {
38
34
  provides: [NavTreeCapabilities.State]
39
35
  }, () => import("./chunk-state.mjs"));
40
36
  var Translations = AppCapability.translations(translations);
37
+ var Keyboard = void 0;
41
38
  var PluginAsset = void 0;
42
39
  var ReactSurface = void 0;
43
40
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"capabilities.node.mjs","names":[],"sources":["../../src/capabilities/gen/node.ts"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\n// GENERATED by dx-plugin — do not edit. Sliced from ../index.ts for the 'node' condition.\n\nimport * as Effect from 'effect/Effect';\n\nimport * as Capabilities from '@dxos/app-framework/Capabilities';\nimport * as Capability from '@dxos/app-framework/Capability';\nimport * as AppGraph from '@dxos/app-graph/AppGraph';\nimport * as AppCapabilities from '@dxos/app-toolkit/AppCapabilities';\nimport * as AppCapability from '@dxos/app-toolkit/AppCapability';\nimport * as LayoutOperation from '@dxos/app-toolkit/LayoutOperation';\nimport * as AttentionCapabilities from '@dxos/plugin-attention/AttentionCapabilities';\n\nimport { translations } from '#translations';\nimport { NavTreeCapabilities } from '#types';\n\nexport const AppGraphBuilder = AppCapability.appGraphBuilder(() => import('../app-graph-builder'));\n\nexport const Expose = Capability.inlineModule(\n 'expose',\n { requires: [AppCapabilities.AppGraph, AppCapabilities.Layout, Capabilities.OperationInvoker], provides: [] },\n Effect.fnUntraced(function* () {\n const layout = yield* Capabilities.getAtomValue(AppCapabilities.Layout);\n const { invokePromise } = yield* Capabilities.OperationInvoker;\n const { graph } = yield* AppCapabilities.AppGraph;\n if (invokePromise && layout.active.length === 1) {\n // TODO(wittjosiah): This should really be fired once the navtree renders for the first time.\n // That is the point at which the graph is expanded and the path should be available.\n void AppGraph.waitForPath(graph, { target: layout.active[0] }, { timeout: 30_000 })\n .then(() => invokePromise(LayoutOperation.Expose, { subject: layout.active[0] }))\n .catch(() => {});\n }\n\n return [];\n }),\n);\n\nexport const Keyboard = Capability.lazyModule(\n 'Keyboard',\n { requires: [AppCapabilities.AppGraph, Capabilities.OperationInvoker], provides: [] },\n () => import('../keyboard'),\n);\n\nexport const OperationHandler = AppCapability.operationHandler(() => import('../operation-handler'));\n\nexport const State = Capability.lazyModule(\n 'State',\n {\n // ViewState is the persistence backend for per-path expansion.\n requires: [Capabilities.AtomRegistry, AppCapabilities.Layout, AttentionCapabilities.ViewState],\n provides: [NavTreeCapabilities.State],\n },\n () => import('../state'),\n);\n\nexport const Translations = AppCapability.translations(translations);\n\nexport const PluginAsset = undefined;\nexport const ReactSurface = undefined;\n"],"mappings":";;;;;;;;;;;AAmBA,IAAa,kBAAkB,cAAc,sBAAsB,OAAO,gCAAuB;AAEjG,IAAa,SAAS,WAAW,aAC/B,UACA;CAAE,UAAU;EAAC,gBAAgB;EAAU,gBAAgB;EAAQ,aAAa;CAAgB;CAAG,UAAU,CAAC;AAAE,GAC5G,OAAO,WAAW,aAAa;CAC7B,MAAM,SAAS,OAAO,aAAa,aAAa,gBAAgB,MAAM;CACtE,MAAM,EAAE,kBAAkB,OAAO,aAAa;CAC9C,MAAM,EAAE,UAAU,OAAO,gBAAgB;CACzC,IAAI,iBAAiB,OAAO,OAAO,WAAW,GAG5C,SAAc,YAAY,OAAO,EAAE,QAAQ,OAAO,OAAO,GAAG,GAAG,EAAE,SAAS,IAAO,CAAC,CAAA,CAC/E,WAAW,cAAc,gBAAgB,QAAQ,EAAE,SAAS,OAAO,OAAO,GAAG,CAAC,CAAC,CAAA,CAC/E,YAAY,CAAC,CAAC;CAGnB,OAAO,CAAC;AACV,CAAC,CACH;AAEA,IAAa,WAAW,WAAW,WACjC,YACA;CAAE,UAAU,CAAC,gBAAgB,UAAU,aAAa,gBAAgB;CAAG,UAAU,CAAC;AAAE,SAC9E,OAAO,uBACf;AAEA,IAAa,mBAAmB,cAAc,uBAAuB,OAAO,gCAAuB;AAEnG,IAAa,QAAQ,WAAW,WAC9B,SACA;CAEE,UAAU;EAAC,aAAa;EAAc,gBAAgB;EAAQ,sBAAsB;CAAS;CAC7F,UAAU,CAAC,oBAAoB,KAAK;AACtC,SACM,OAAO,oBACf;AAEA,IAAa,eAAe,cAAc,aAAa,YAAY;AAEnE,IAAa,cAAc,KAAA;AAC3B,IAAa,eAAe,KAAA"}
1
+ {"version":3,"file":"capabilities.node.mjs","names":[],"sources":["../../src/capabilities/gen/node.ts"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\n// GENERATED by dx-plugin — do not edit. Sliced from ../index.ts for the 'node' condition.\n\nimport * as Effect from 'effect/Effect';\n\nimport * as Capabilities from '@dxos/app-framework/Capabilities';\nimport * as Capability from '@dxos/app-framework/Capability';\nimport * as AppGraph from '@dxos/app-graph/AppGraph';\nimport * as AppCapabilities from '@dxos/app-toolkit/AppCapabilities';\nimport * as AppCapability from '@dxos/app-toolkit/AppCapability';\nimport * as LayoutOperation from '@dxos/app-toolkit/LayoutOperation';\nimport * as AttentionCapabilities from '@dxos/plugin-attention/AttentionCapabilities';\n\nimport { translations } from '#translations';\nimport { NavTreeCapabilities } from '#types';\n\nexport const AppGraphBuilder = AppCapability.appGraphBuilder(() => import('../app-graph-builder.ts'));\n\nexport const Expose = Capability.inlineModule(\n 'expose',\n { requires: [AppCapabilities.AppGraph, AppCapabilities.Layout, Capabilities.OperationInvoker], provides: [] },\n Effect.fnUntraced(function* () {\n const layout = yield* Capabilities.getAtomValue(AppCapabilities.Layout);\n const { invokePromise } = yield* Capabilities.OperationInvoker;\n const { graph } = yield* AppCapabilities.AppGraph;\n if (invokePromise && layout.active.length === 1) {\n // TODO(wittjosiah): This should really be fired once the navtree renders for the first time.\n // That is the point at which the graph is expanded and the path should be available.\n void AppGraph.waitForPath(graph, { target: layout.active[0] }, { timeout: 30_000 })\n .then(() => invokePromise(LayoutOperation.Expose, { subject: layout.active[0] }))\n .catch(() => {});\n }\n\n return [];\n }),\n);\n\nexport const OperationHandler = AppCapability.operationHandler(() => import('../operation-handler.ts'));\n\nexport const State = Capability.lazyModule(\n 'State',\n {\n // ViewState is the persistence backend for per-path expansion.\n requires: [Capabilities.AtomRegistry, AppCapabilities.Layout, AttentionCapabilities.ViewState],\n provides: [NavTreeCapabilities.State],\n },\n () => import('../state.ts'),\n);\n\nexport const Translations = AppCapability.translations(translations);\n\nexport const Keyboard = undefined;\nexport const PluginAsset = undefined;\nexport const ReactSurface = undefined;\n"],"mappings":";;;;;;;;;;;AAmBA,IAAa,kBAAkB,cAAc,sBAAsB,OAAO,gCAA0B;AAEpG,IAAa,SAAS,WAAW,aAC/B,UACA;CAAE,UAAU;EAAC,gBAAgB;EAAU,gBAAgB;EAAQ,aAAa;CAAgB;CAAG,UAAU,CAAC;AAAE,GAC5G,OAAO,WAAW,aAAa;CAC7B,MAAM,SAAS,OAAO,aAAa,aAAa,gBAAgB,MAAM;CACtE,MAAM,EAAE,kBAAkB,OAAO,aAAa;CAC9C,MAAM,EAAE,UAAU,OAAO,gBAAgB;CACzC,IAAI,iBAAiB,OAAO,OAAO,WAAW,GAG5C,SAAc,YAAY,OAAO,EAAE,QAAQ,OAAO,OAAO,GAAG,GAAG,EAAE,SAAS,IAAO,CAAC,CAAA,CAC/E,WAAW,cAAc,gBAAgB,QAAQ,EAAE,SAAS,OAAO,OAAO,GAAG,CAAC,CAAC,CAAA,CAC/E,YAAY,CAAC,CAAC;CAGnB,OAAO,CAAC;AACV,CAAC,CACH;AAEA,IAAa,mBAAmB,cAAc,uBAAuB,OAAO,gCAA0B;AAEtG,IAAa,QAAQ,WAAW,WAC9B,SACA;CAEE,UAAU;EAAC,aAAa;EAAc,gBAAgB;EAAQ,sBAAsB;CAAS;CAC7F,UAAU,CAAC,oBAAoB,KAAK;AACtC,SACM,OAAO,oBACf;AAEA,IAAa,eAAe,cAAc,aAAa,YAAY;AAEnE,IAAa,WAAW,KAAA;AACxB,IAAa,cAAc,KAAA;AAC3B,IAAa,eAAe,KAAA"}
@@ -0,0 +1,59 @@
1
+ import { t as PLUGIN_default } from "./chunk-PLUGIN.mjs";
2
+ import * as Effect from "effect/Effect";
3
+ import * as Capabilities from "@dxos/app-framework/Capabilities";
4
+ import * as Capability from "@dxos/app-framework/Capability";
5
+ import * as AppGraph from "@dxos/app-graph/AppGraph";
6
+ import * as AppCapabilities from "@dxos/app-toolkit/AppCapabilities";
7
+ import * as AppCapability from "@dxos/app-toolkit/AppCapability";
8
+ import * as LayoutOperation from "@dxos/app-toolkit/LayoutOperation";
9
+ import * as AttentionCapabilities from "@dxos/plugin-attention/AttentionCapabilities";
10
+ import { translations } from "#translations";
11
+ import { NavTreeCapabilities } from "#types";
12
+ import { meta } from "#meta";
13
+ //#region src/capabilities/gen/tauri.ts
14
+ var AppGraphBuilder = AppCapability.appGraphBuilder(() => import("./chunk-app-graph-builder.mjs"));
15
+ var Expose = Capability.inlineModule("expose", {
16
+ requires: [
17
+ AppCapabilities.AppGraph,
18
+ AppCapabilities.Layout,
19
+ Capabilities.OperationInvoker
20
+ ],
21
+ provides: []
22
+ }, Effect.fnUntraced(function* () {
23
+ const layout = yield* Capabilities.getAtomValue(AppCapabilities.Layout);
24
+ const { invokePromise } = yield* Capabilities.OperationInvoker;
25
+ const { graph } = yield* AppCapabilities.AppGraph;
26
+ if (invokePromise && layout.active.length === 1) AppGraph.waitForPath(graph, { target: layout.active[0] }, { timeout: 3e4 }).then(() => invokePromise(LayoutOperation.Expose, { subject: layout.active[0] })).catch(() => {});
27
+ return [];
28
+ }));
29
+ var Keyboard = Capability.lazyModule("Keyboard", {
30
+ requires: [AppCapabilities.AppGraph, Capabilities.OperationInvoker],
31
+ provides: [],
32
+ environments: ["browser", "tauri"]
33
+ }, () => import("./chunk-keyboard.mjs"));
34
+ var OperationHandler = AppCapability.operationHandler(() => import("./chunk-operation-handler.mjs"));
35
+ var PluginAsset = AppCapability.pluginAsset({
36
+ pluginId: meta.profile.key,
37
+ path: "PLUGIN.mdl",
38
+ content: PLUGIN_default,
39
+ mimeType: "application/x-mdl"
40
+ });
41
+ var ReactSurface = AppCapability.surface(() => import("./chunk-react-surface.mjs"), { roles: [
42
+ "org.dxos.role.dialog",
43
+ "org.dxos.role.documentTitle",
44
+ "org.dxos.role.navigation",
45
+ "org.dxos.role.searchInput"
46
+ ] });
47
+ var State = Capability.lazyModule("State", {
48
+ requires: [
49
+ Capabilities.AtomRegistry,
50
+ AppCapabilities.Layout,
51
+ AttentionCapabilities.ViewState
52
+ ],
53
+ provides: [NavTreeCapabilities.State]
54
+ }, () => import("./chunk-state.mjs"));
55
+ var Translations = AppCapability.translations(translations);
56
+ //#endregion
57
+ export { AppGraphBuilder, Expose, Keyboard, OperationHandler, PluginAsset, ReactSurface, State, Translations };
58
+
59
+ //# sourceMappingURL=capabilities.tauri.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capabilities.tauri.mjs","names":[],"sources":["../../src/capabilities/gen/tauri.ts"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\n// GENERATED by dx-plugin — do not edit. Sliced from ../index.ts for the 'tauri' condition.\n\nimport * as Effect from 'effect/Effect';\n\nimport * as Capabilities from '@dxos/app-framework/Capabilities';\nimport * as Capability from '@dxos/app-framework/Capability';\nimport * as AppGraph from '@dxos/app-graph/AppGraph';\nimport * as AppCapabilities from '@dxos/app-toolkit/AppCapabilities';\nimport * as AppCapability from '@dxos/app-toolkit/AppCapability';\nimport * as LayoutOperation from '@dxos/app-toolkit/LayoutOperation';\nimport * as AttentionCapabilities from '@dxos/plugin-attention/AttentionCapabilities';\n\nimport { meta } from '#meta';\nimport { translations } from '#translations';\nimport { NavTreeCapabilities } from '#types';\n\nimport pluginSpec from '../../../PLUGIN.mdl?raw';\n\nexport const AppGraphBuilder = AppCapability.appGraphBuilder(() => import('../app-graph-builder.ts'));\n\nexport const Expose = Capability.inlineModule(\n 'expose',\n { requires: [AppCapabilities.AppGraph, AppCapabilities.Layout, Capabilities.OperationInvoker], provides: [] },\n Effect.fnUntraced(function* () {\n const layout = yield* Capabilities.getAtomValue(AppCapabilities.Layout);\n const { invokePromise } = yield* Capabilities.OperationInvoker;\n const { graph } = yield* AppCapabilities.AppGraph;\n if (invokePromise && layout.active.length === 1) {\n // TODO(wittjosiah): This should really be fired once the navtree renders for the first time.\n // That is the point at which the graph is expanded and the path should be available.\n void AppGraph.waitForPath(graph, { target: layout.active[0] }, { timeout: 30_000 })\n .then(() => invokePromise(LayoutOperation.Expose, { subject: layout.active[0] }))\n .catch(() => {});\n }\n\n return [];\n }),\n);\n\nexport const Keyboard = Capability.lazyModule(\n 'Keyboard',\n // Listens on `document`, which node and workerd lack.\n {\n requires: [AppCapabilities.AppGraph, Capabilities.OperationInvoker],\n provides: [],\n environments: ['browser', 'tauri'],\n },\n () => import('../keyboard.ts'),\n);\n\nexport const OperationHandler = AppCapability.operationHandler(() => import('../operation-handler.ts'));\n\nexport const PluginAsset = AppCapability.pluginAsset({\n pluginId: meta.profile.key,\n path: 'PLUGIN.mdl',\n content: pluginSpec,\n mimeType: 'application/x-mdl',\n});\n\nexport const ReactSurface = AppCapability.surface(() => import('../react-surface.ts'), {\n roles: [\n 'org.dxos.role.dialog',\n 'org.dxos.role.documentTitle',\n 'org.dxos.role.navigation',\n 'org.dxos.role.searchInput',\n ],\n});\n\nexport const State = Capability.lazyModule(\n 'State',\n {\n // ViewState is the persistence backend for per-path expansion.\n requires: [Capabilities.AtomRegistry, AppCapabilities.Layout, AttentionCapabilities.ViewState],\n provides: [NavTreeCapabilities.State],\n },\n () => import('../state.ts'),\n);\n\nexport const Translations = AppCapability.translations(translations);\n"],"mappings":";;;;;;;;;;;;;AAsBA,IAAa,kBAAkB,cAAc,sBAAsB,OAAO,gCAA0B;AAEpG,IAAa,SAAS,WAAW,aAC/B,UACA;CAAE,UAAU;EAAC,gBAAgB;EAAU,gBAAgB;EAAQ,aAAa;CAAgB;CAAG,UAAU,CAAC;AAAE,GAC5G,OAAO,WAAW,aAAa;CAC7B,MAAM,SAAS,OAAO,aAAa,aAAa,gBAAgB,MAAM;CACtE,MAAM,EAAE,kBAAkB,OAAO,aAAa;CAC9C,MAAM,EAAE,UAAU,OAAO,gBAAgB;CACzC,IAAI,iBAAiB,OAAO,OAAO,WAAW,GAG5C,SAAc,YAAY,OAAO,EAAE,QAAQ,OAAO,OAAO,GAAG,GAAG,EAAE,SAAS,IAAO,CAAC,CAAA,CAC/E,WAAW,cAAc,gBAAgB,QAAQ,EAAE,SAAS,OAAO,OAAO,GAAG,CAAC,CAAC,CAAA,CAC/E,YAAY,CAAC,CAAC;CAGnB,OAAO,CAAC;AACV,CAAC,CACH;AAEA,IAAa,WAAW,WAAW,WACjC,YAEA;CACE,UAAU,CAAC,gBAAgB,UAAU,aAAa,gBAAgB;CAClE,UAAU,CAAC;CACX,cAAc,CAAC,WAAW,OAAO;AACnC,SACM,OAAO,uBACf;AAEA,IAAa,mBAAmB,cAAc,uBAAuB,OAAO,gCAA0B;AAEtG,IAAa,cAAc,cAAc,YAAY;CACnD,UAAU,KAAK,QAAQ;CACvB,MAAM;CACN,SAAS;CACT,UAAU;AACZ,CAAC;AAED,IAAa,eAAe,cAAc,cAAc,OAAO,8BAAwB,EACrF,OAAO;CACL;CACA;CACA;CACA;AACF,EACF,CAAC;AAED,IAAa,QAAQ,WAAW,WAC9B,SACA;CAEE,UAAU;EAAC,aAAa;EAAc,gBAAgB;EAAQ,sBAAsB;CAAS;CAC7F,UAAU,CAAC,oBAAoB,KAAK;AACtC,SACM,OAAO,oBACf;AAEA,IAAa,eAAe,cAAc,aAAa,YAAY"}
@@ -24,10 +24,6 @@ var Expose = Capability.inlineModule("expose", {
24
24
  if (invokePromise && layout.active.length === 1) AppGraph.waitForPath(graph, { target: layout.active[0] }, { timeout: 3e4 }).then(() => invokePromise(LayoutOperation.Expose, { subject: layout.active[0] })).catch(() => {});
25
25
  return [];
26
26
  }));
27
- var Keyboard = Capability.lazyModule("Keyboard", {
28
- requires: [AppCapabilities.AppGraph, Capabilities.OperationInvoker],
29
- provides: []
30
- }, () => import("./chunk-keyboard.mjs"));
31
27
  var OperationHandler = AppCapability.operationHandler(() => import("./chunk-operation-handler.mjs"));
32
28
  var State = Capability.lazyModule("State", {
33
29
  requires: [
@@ -38,6 +34,7 @@ var State = Capability.lazyModule("State", {
38
34
  provides: [NavTreeCapabilities.State]
39
35
  }, () => import("./chunk-state.mjs"));
40
36
  var Translations = AppCapability.translations(translations);
37
+ var Keyboard = void 0;
41
38
  var PluginAsset = void 0;
42
39
  var ReactSurface = void 0;
43
40
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"capabilities.workerd.mjs","names":[],"sources":["../../src/capabilities/gen/workerd.ts"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\n// GENERATED by dx-plugin — do not edit. Sliced from ../index.ts for the 'workerd' condition.\n\nimport * as Effect from 'effect/Effect';\n\nimport * as Capabilities from '@dxos/app-framework/Capabilities';\nimport * as Capability from '@dxos/app-framework/Capability';\nimport * as AppGraph from '@dxos/app-graph/AppGraph';\nimport * as AppCapabilities from '@dxos/app-toolkit/AppCapabilities';\nimport * as AppCapability from '@dxos/app-toolkit/AppCapability';\nimport * as LayoutOperation from '@dxos/app-toolkit/LayoutOperation';\nimport * as AttentionCapabilities from '@dxos/plugin-attention/AttentionCapabilities';\n\nimport { translations } from '#translations';\nimport { NavTreeCapabilities } from '#types';\n\nexport const AppGraphBuilder = AppCapability.appGraphBuilder(() => import('../app-graph-builder'));\n\nexport const Expose = Capability.inlineModule(\n 'expose',\n { requires: [AppCapabilities.AppGraph, AppCapabilities.Layout, Capabilities.OperationInvoker], provides: [] },\n Effect.fnUntraced(function* () {\n const layout = yield* Capabilities.getAtomValue(AppCapabilities.Layout);\n const { invokePromise } = yield* Capabilities.OperationInvoker;\n const { graph } = yield* AppCapabilities.AppGraph;\n if (invokePromise && layout.active.length === 1) {\n // TODO(wittjosiah): This should really be fired once the navtree renders for the first time.\n // That is the point at which the graph is expanded and the path should be available.\n void AppGraph.waitForPath(graph, { target: layout.active[0] }, { timeout: 30_000 })\n .then(() => invokePromise(LayoutOperation.Expose, { subject: layout.active[0] }))\n .catch(() => {});\n }\n\n return [];\n }),\n);\n\nexport const Keyboard = Capability.lazyModule(\n 'Keyboard',\n { requires: [AppCapabilities.AppGraph, Capabilities.OperationInvoker], provides: [] },\n () => import('../keyboard'),\n);\n\nexport const OperationHandler = AppCapability.operationHandler(() => import('../operation-handler'));\n\nexport const State = Capability.lazyModule(\n 'State',\n {\n // ViewState is the persistence backend for per-path expansion.\n requires: [Capabilities.AtomRegistry, AppCapabilities.Layout, AttentionCapabilities.ViewState],\n provides: [NavTreeCapabilities.State],\n },\n () => import('../state'),\n);\n\nexport const Translations = AppCapability.translations(translations);\n\nexport const PluginAsset = undefined;\nexport const ReactSurface = undefined;\n"],"mappings":";;;;;;;;;;;AAmBA,IAAa,kBAAkB,cAAc,sBAAsB,OAAO,gCAAuB;AAEjG,IAAa,SAAS,WAAW,aAC/B,UACA;CAAE,UAAU;EAAC,gBAAgB;EAAU,gBAAgB;EAAQ,aAAa;CAAgB;CAAG,UAAU,CAAC;AAAE,GAC5G,OAAO,WAAW,aAAa;CAC7B,MAAM,SAAS,OAAO,aAAa,aAAa,gBAAgB,MAAM;CACtE,MAAM,EAAE,kBAAkB,OAAO,aAAa;CAC9C,MAAM,EAAE,UAAU,OAAO,gBAAgB;CACzC,IAAI,iBAAiB,OAAO,OAAO,WAAW,GAG5C,SAAc,YAAY,OAAO,EAAE,QAAQ,OAAO,OAAO,GAAG,GAAG,EAAE,SAAS,IAAO,CAAC,CAAA,CAC/E,WAAW,cAAc,gBAAgB,QAAQ,EAAE,SAAS,OAAO,OAAO,GAAG,CAAC,CAAC,CAAA,CAC/E,YAAY,CAAC,CAAC;CAGnB,OAAO,CAAC;AACV,CAAC,CACH;AAEA,IAAa,WAAW,WAAW,WACjC,YACA;CAAE,UAAU,CAAC,gBAAgB,UAAU,aAAa,gBAAgB;CAAG,UAAU,CAAC;AAAE,SAC9E,OAAO,uBACf;AAEA,IAAa,mBAAmB,cAAc,uBAAuB,OAAO,gCAAuB;AAEnG,IAAa,QAAQ,WAAW,WAC9B,SACA;CAEE,UAAU;EAAC,aAAa;EAAc,gBAAgB;EAAQ,sBAAsB;CAAS;CAC7F,UAAU,CAAC,oBAAoB,KAAK;AACtC,SACM,OAAO,oBACf;AAEA,IAAa,eAAe,cAAc,aAAa,YAAY;AAEnE,IAAa,cAAc,KAAA;AAC3B,IAAa,eAAe,KAAA"}
1
+ {"version":3,"file":"capabilities.workerd.mjs","names":[],"sources":["../../src/capabilities/gen/workerd.ts"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\n// GENERATED by dx-plugin — do not edit. Sliced from ../index.ts for the 'workerd' condition.\n\nimport * as Effect from 'effect/Effect';\n\nimport * as Capabilities from '@dxos/app-framework/Capabilities';\nimport * as Capability from '@dxos/app-framework/Capability';\nimport * as AppGraph from '@dxos/app-graph/AppGraph';\nimport * as AppCapabilities from '@dxos/app-toolkit/AppCapabilities';\nimport * as AppCapability from '@dxos/app-toolkit/AppCapability';\nimport * as LayoutOperation from '@dxos/app-toolkit/LayoutOperation';\nimport * as AttentionCapabilities from '@dxos/plugin-attention/AttentionCapabilities';\n\nimport { translations } from '#translations';\nimport { NavTreeCapabilities } from '#types';\n\nexport const AppGraphBuilder = AppCapability.appGraphBuilder(() => import('../app-graph-builder.ts'));\n\nexport const Expose = Capability.inlineModule(\n 'expose',\n { requires: [AppCapabilities.AppGraph, AppCapabilities.Layout, Capabilities.OperationInvoker], provides: [] },\n Effect.fnUntraced(function* () {\n const layout = yield* Capabilities.getAtomValue(AppCapabilities.Layout);\n const { invokePromise } = yield* Capabilities.OperationInvoker;\n const { graph } = yield* AppCapabilities.AppGraph;\n if (invokePromise && layout.active.length === 1) {\n // TODO(wittjosiah): This should really be fired once the navtree renders for the first time.\n // That is the point at which the graph is expanded and the path should be available.\n void AppGraph.waitForPath(graph, { target: layout.active[0] }, { timeout: 30_000 })\n .then(() => invokePromise(LayoutOperation.Expose, { subject: layout.active[0] }))\n .catch(() => {});\n }\n\n return [];\n }),\n);\n\nexport const OperationHandler = AppCapability.operationHandler(() => import('../operation-handler.ts'));\n\nexport const State = Capability.lazyModule(\n 'State',\n {\n // ViewState is the persistence backend for per-path expansion.\n requires: [Capabilities.AtomRegistry, AppCapabilities.Layout, AttentionCapabilities.ViewState],\n provides: [NavTreeCapabilities.State],\n },\n () => import('../state.ts'),\n);\n\nexport const Translations = AppCapability.translations(translations);\n\nexport const Keyboard = undefined;\nexport const PluginAsset = undefined;\nexport const ReactSurface = undefined;\n"],"mappings":";;;;;;;;;;;AAmBA,IAAa,kBAAkB,cAAc,sBAAsB,OAAO,gCAA0B;AAEpG,IAAa,SAAS,WAAW,aAC/B,UACA;CAAE,UAAU;EAAC,gBAAgB;EAAU,gBAAgB;EAAQ,aAAa;CAAgB;CAAG,UAAU,CAAC;AAAE,GAC5G,OAAO,WAAW,aAAa;CAC7B,MAAM,SAAS,OAAO,aAAa,aAAa,gBAAgB,MAAM;CACtE,MAAM,EAAE,kBAAkB,OAAO,aAAa;CAC9C,MAAM,EAAE,UAAU,OAAO,gBAAgB;CACzC,IAAI,iBAAiB,OAAO,OAAO,WAAW,GAG5C,SAAc,YAAY,OAAO,EAAE,QAAQ,OAAO,OAAO,GAAG,GAAG,EAAE,SAAS,IAAO,CAAC,CAAA,CAC/E,WAAW,cAAc,gBAAgB,QAAQ,EAAE,SAAS,OAAO,OAAO,GAAG,CAAC,CAAC,CAAA,CAC/E,YAAY,CAAC,CAAC;CAGnB,OAAO,CAAC;AACV,CAAC,CACH;AAEA,IAAa,mBAAmB,cAAc,uBAAuB,OAAO,gCAA0B;AAEtG,IAAa,QAAQ,WAAW,WAC9B,SACA;CAEE,UAAU;EAAC,aAAa;EAAc,gBAAgB;EAAQ,sBAAsB;CAAS;CAC7F,UAAU,CAAC,oBAAoB,KAAK;AACtC,SACM,OAAO,oBACf;AAEA,IAAa,eAAe,cAAc,aAAa,YAAY;AAEnE,IAAa,WAAW,KAAA;AACxB,IAAa,cAAc,KAAA;AAC3B,IAAa,eAAe,KAAA"}
@@ -1,26 +1,29 @@
1
1
  import * as AppGraph from "@dxos/app-graph/AppGraph";
2
2
  import * as LayoutOperation from "@dxos/app-toolkit/LayoutOperation";
3
3
  import { KEY_BINDING, meta } from "#meta";
4
- import * as AppGraphNode from "@dxos/app-graph/AppGraphNode";
5
- import { getHostPlatform } from "@dxos/util";
6
4
  import { forwardRef, useMemo, useState } from "react";
7
- import { useAppGraph } from "@dxos/app-toolkit/ui";
8
- import { useActionRunner, useActions } from "@dxos/plugin-graph/hooks";
9
- import { Button, Dialog, toLocalizedString, useTranslation } from "@dxos/react-ui";
5
+ import * as AppGraphNode from "@dxos/app-graph/AppGraphNode";
6
+ import * as ToolkitHooks from "@dxos/app-toolkit/Hooks";
7
+ import * as GraphHooks from "@dxos/plugin-graph/Hooks";
8
+ import * as Button from "@dxos/react-ui/Button";
9
+ import * as UiHooks from "@dxos/react-ui/Hooks";
10
+ import * as Theme from "@dxos/react-ui/Theme";
10
11
  import { osTranslations } from "@dxos/ui-theme";
12
+ import { resolveKeyBinding } from "@dxos/util";
11
13
  import { jsx, jsxs } from "react/jsx-runtime";
12
- import { useOperationInvoker } from "@dxos/app-framework/ui";
13
- import { Keyboard, keySymbols } from "@dxos/keyboard";
14
+ import * as Hooks from "@dxos/app-framework/Hooks";
15
+ import { getHotkeyScope, keySymbols } from "@dxos/react-focus";
14
16
  import { SearchList, useSearchListResults } from "@dxos/react-ui-search";
17
+ import * as Dialog from "@dxos/react-ui/Dialog";
15
18
  //#region src/containers/CommandsDialogContent/CommandsDialogContent.tsx
16
19
  var CommandsDialogContent = forwardRef(({ selected: initial }, forwardedRef) => {
17
- const { t } = useTranslation(meta.profile.key);
18
- const { invokePromise } = useOperationInvoker();
19
- const runAction = useActionRunner();
20
- const { graph } = useAppGraph();
20
+ const { t } = UiHooks.useTranslation(meta.profile.key);
21
+ const { invokePromise } = Hooks.useOperationInvoker();
22
+ const runAction = GraphHooks.useActionRunner();
23
+ const { graph } = ToolkitHooks.useAppGraph();
21
24
  const [selected, setSelected] = useState(initial);
22
25
  const allActions = useMemo(() => {
23
- const current = Keyboard.singleton.getCurrentContext();
26
+ const current = getHotkeyScope() ?? "";
24
27
  const actionMap = /* @__PURE__ */ new Set();
25
28
  const actions = [];
26
29
  AppGraph.traverse(graph, {
@@ -36,16 +39,16 @@ var CommandsDialogContent = forwardRef(({ selected: initial }, forwardedRef) =>
36
39
  }
37
40
  });
38
41
  actions.sort((a, b) => {
39
- return toLocalizedString(a.properties.label, t)?.toLowerCase().localeCompare(toLocalizedString(b.properties.label, t)?.toLowerCase());
42
+ return Theme.toLocalizedString(a.properties.label, t)?.toLowerCase().localeCompare(Theme.toLocalizedString(b.properties.label, t)?.toLowerCase());
40
43
  });
41
44
  return actions;
42
45
  }, [graph]);
43
46
  const group = allActions.find(({ id }) => id === selected);
44
- const groupActions = useActions(graph, group?.id);
47
+ const groupActions = GraphHooks.useActions(graph, group?.id);
45
48
  const actions = AppGraphNode.isActionGroup(group) ? groupActions : allActions;
46
49
  const { results, handleSearch } = useSearchListResults({
47
50
  items: actions,
48
- extract: (action) => toLocalizedString(action.properties.label, t)
51
+ extract: (action) => Theme.toLocalizedString(action.properties.label, t)
49
52
  });
50
53
  return /* @__PURE__ */ jsxs(Dialog.Content, {
51
54
  ref: forwardedRef,
@@ -56,11 +59,17 @@ var CommandsDialogContent = forwardRef(({ selected: initial }, forwardedRef) =>
56
59
  }),
57
60
  /* @__PURE__ */ jsx(Dialog.Body, { children: /* @__PURE__ */ jsxs(SearchList.Root, {
58
61
  onSearch: handleSearch,
59
- children: [/* @__PURE__ */ jsx(SearchList.Input, { placeholder: t("command-list-input.placeholder") }), /* @__PURE__ */ jsx(SearchList.Viewport, { children: results.map((action) => {
60
- const shortcut = typeof action.properties.keyBinding === "string" ? action.properties.keyBinding : action.properties.keyBinding?.[getHostPlatform()];
62
+ resetSelectionOnChange: true,
63
+ children: [/* @__PURE__ */ jsx(SearchList.Input, {
64
+ autoFocus: true,
65
+ placeholder: t("command-list-input.placeholder"),
66
+ escapeBehavior: "dismiss",
67
+ [Dialog.DIALOG_AUTOFOCUS_ATTRIBUTE]: ""
68
+ }), /* @__PURE__ */ jsx(SearchList.Viewport, { children: results.map((action) => {
69
+ const shortcut = resolveKeyBinding(action.properties.keyBinding);
61
70
  return /* @__PURE__ */ jsx(SearchList.Item, {
62
71
  value: action.id,
63
- label: toLocalizedString(action.properties.label, t),
72
+ label: Theme.toLocalizedString(action.properties.label, t),
64
73
  icon: action.properties.icon,
65
74
  suffix: shortcut ? keySymbols(shortcut).join("") : void 0,
66
75
  onSelect: () => {
@@ -72,7 +81,7 @@ var CommandsDialogContent = forwardRef(({ selected: initial }, forwardedRef) =>
72
81
  invokePromise(LayoutOperation.UpdateDialog, { state: false });
73
82
  setTimeout(() => {
74
83
  const lookupId = group?.id ?? action.id;
75
- const node = AppGraph.getConnections(graph, lookupId, AppGraphNode.actionRelation("inbound"))[0];
84
+ const node = AppGraph.getConnections(graph, lookupId, AppGraph.inverseRelation(AppGraphNode.action))[0];
76
85
  if (node && AppGraphNode.isAction(action)) runAction(action, {
77
86
  parent: node,
78
87
  caller: KEY_BINDING
@@ -85,9 +94,9 @@ var CommandsDialogContent = forwardRef(({ selected: initial }, forwardedRef) =>
85
94
  }, action.id);
86
95
  }) })]
87
96
  }) }),
88
- /* @__PURE__ */ jsx(Dialog.ActionBar, { children: /* @__PURE__ */ jsx(Dialog.Close, {
97
+ /* @__PURE__ */ jsx(Dialog.Footer, { children: /* @__PURE__ */ jsx(Dialog.CloseTrigger, {
89
98
  asChild: true,
90
- children: /* @__PURE__ */ jsx(Button, {
99
+ children: /* @__PURE__ */ jsx(Button.Root, {
91
100
  classNames: "w-full",
92
101
  children: t("close.label", { ns: osTranslations })
93
102
  })