flexdesk 0.17.17 → 0.18.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 (300) hide show
  1. package/CHANGELOG.md +70 -0
  2. package/LICENSE +0 -0
  3. package/README.md +1 -0
  4. package/THIRD_PARTY_LICENSES.md +0 -0
  5. package/canvas.js +0 -0
  6. package/charts.js +0 -0
  7. package/core.js +0 -0
  8. package/css/flexdesk.css +7499 -5851
  9. package/css/reset.css +1 -1
  10. package/css/tokens.css +23 -1
  11. package/dist/canvas.js +0 -0
  12. package/dist/canvas.js.map +0 -0
  13. package/dist/charts.js +10 -6
  14. package/dist/charts.js.map +1 -1
  15. package/dist/chunk-3PHCPZHT.js +0 -0
  16. package/dist/chunk-3PHCPZHT.js.map +0 -0
  17. package/dist/chunk-5W4EEKSK.js +778 -0
  18. package/dist/chunk-5W4EEKSK.js.map +7 -0
  19. package/dist/chunk-DNJ3N4T4.js +82 -0
  20. package/dist/chunk-DNJ3N4T4.js.map +7 -0
  21. package/dist/chunk-FOOS3T5L.js +0 -0
  22. package/dist/chunk-FOOS3T5L.js.map +0 -0
  23. package/dist/chunk-GOQLR5WR.js +0 -0
  24. package/dist/chunk-GOQLR5WR.js.map +0 -0
  25. package/dist/{chunk-JKZLNKG6.js → chunk-HKPB6OFA.js} +90 -25
  26. package/dist/{chunk-JKZLNKG6.js.map → chunk-HKPB6OFA.js.map} +2 -2
  27. package/dist/chunk-HNU6MM2B.js +0 -0
  28. package/dist/chunk-HNU6MM2B.js.map +0 -0
  29. package/dist/{chunk-REJ5HLIM.js → chunk-HYJYYEPK.js} +2 -2
  30. package/dist/chunk-JYWURG5T.js +0 -0
  31. package/dist/chunk-JYWURG5T.js.map +0 -0
  32. package/dist/{chunk-7U4IB65H.js → chunk-LLBJ2SJH.js} +5 -3
  33. package/dist/{chunk-7U4IB65H.js.map → chunk-LLBJ2SJH.js.map} +1 -1
  34. package/dist/chunk-N7HC3ADV.js +0 -0
  35. package/dist/chunk-N7HC3ADV.js.map +0 -0
  36. package/dist/{chunk-7OL6F2AM.js → chunk-P74F6I6P.js} +6 -4
  37. package/dist/{chunk-7OL6F2AM.js.map → chunk-P74F6I6P.js.map} +1 -1
  38. package/dist/chunk-PAI2ZUWV.js +260 -0
  39. package/dist/chunk-PAI2ZUWV.js.map +7 -0
  40. package/dist/chunk-Q7BALEPX.js +527 -0
  41. package/dist/chunk-Q7BALEPX.js.map +7 -0
  42. package/dist/chunk-QXAOTGCC.js +40 -0
  43. package/dist/chunk-QXAOTGCC.js.map +7 -0
  44. package/dist/{chunk-XJNADRGR.js → chunk-RKVYIXDC.js} +664 -91
  45. package/dist/chunk-RKVYIXDC.js.map +7 -0
  46. package/dist/{chunk-2Z2ENHR3.js → chunk-U5GKJUOC.js} +3 -3
  47. package/dist/{chunk-2Z2ENHR3.js.map → chunk-U5GKJUOC.js.map} +1 -1
  48. package/dist/chunk-UKP22RUG.js +219 -0
  49. package/dist/chunk-UKP22RUG.js.map +7 -0
  50. package/dist/chunk-VLOAI3HS.js +43 -0
  51. package/dist/chunk-VLOAI3HS.js.map +7 -0
  52. package/dist/{chunk-WUFLGETN.js → chunk-WVFGV5FT.js} +2 -39
  53. package/dist/{chunk-WUFLGETN.js.map → chunk-WVFGV5FT.js.map} +3 -3
  54. package/dist/{chunk-PGZ4EHSE.js → chunk-ZL3VKINP.js} +41 -390
  55. package/dist/chunk-ZL3VKINP.js.map +7 -0
  56. package/dist/editor.js +3 -2
  57. package/dist/editor.js.map +1 -1
  58. package/dist/flexdesk.css +7499 -5851
  59. package/dist/flow.js +29 -97
  60. package/dist/flow.js.map +3 -3
  61. package/dist/git.js +1356 -0
  62. package/dist/git.js.map +7 -0
  63. package/dist/host.js +0 -0
  64. package/dist/host.js.map +0 -0
  65. package/dist/reset.css +1 -1
  66. package/dist/tile_registry-6WZPTUZV.js +0 -0
  67. package/dist/tile_registry-6WZPTUZV.js.map +0 -0
  68. package/dist/tiles.js +20 -15
  69. package/dist/tiles.js.map +2 -2
  70. package/dist/tokens.css +23 -1
  71. package/dist/widgets.js +3969 -1189
  72. package/dist/widgets.js.map +4 -4
  73. package/dist/wm.js +121 -33
  74. package/dist/wm.js.map +2 -2
  75. package/docs/README.md +9 -4
  76. package/docs/best-practices.md +2 -2
  77. package/docs/components/chat-shell.md +198 -0
  78. package/docs/components/command-palette.md +0 -0
  79. package/docs/components/conversation.md +10 -0
  80. package/docs/components/data-table-grid.md +0 -0
  81. package/docs/components/data-table.md +0 -0
  82. package/docs/components/editor.md +0 -0
  83. package/docs/components/filter-builder.md +246 -0
  84. package/docs/components/flow-canvas-editor.md +0 -0
  85. package/docs/components/flow-editors.md +0 -0
  86. package/docs/components/flow-lane-editor.md +0 -0
  87. package/docs/components/flow-outline-editor.md +0 -0
  88. package/docs/components/forms-and-dialogs.md +22 -0
  89. package/docs/components/git.md +355 -0
  90. package/docs/components/input-fields.md +167 -2
  91. package/docs/components/keymap.md +8 -0
  92. package/docs/components/markdown-and-outline.md +0 -0
  93. package/docs/components/menus.md +120 -3
  94. package/docs/components/panels-and-desktops.md +16 -5
  95. package/docs/components/record-list-and-fact-table.md +0 -0
  96. package/docs/components/settings-view.md +0 -0
  97. package/docs/components/shell.md +104 -1
  98. package/docs/components/wizard.md +0 -0
  99. package/docs/components/workspace-picker.md +149 -0
  100. package/docs/concepts/building-and-packaging.md +2 -2
  101. package/docs/concepts/domain-neutrality.md +0 -0
  102. package/docs/concepts/host-port.md +0 -0
  103. package/docs/concepts/packages-and-entry-points.md +14 -13
  104. package/docs/concepts/peer-dependencies.md +0 -0
  105. package/docs/concepts/state-guard.md +3 -3
  106. package/docs/quickstart.md +1 -1
  107. package/editor.js +0 -0
  108. package/flow.js +0 -0
  109. package/git.js +13 -0
  110. package/host.js +0 -0
  111. package/package.json +6 -1
  112. package/src/canvas/canvas_adapter.js +0 -0
  113. package/src/canvas/edge_router.js +0 -0
  114. package/src/canvas/graph/connector_router.js +0 -0
  115. package/src/canvas/graph/history_service.js +0 -0
  116. package/src/canvas/graph/node_platform.js +0 -0
  117. package/src/canvas/index.js +0 -0
  118. package/src/canvas/layered_layout.js +0 -0
  119. package/src/charts/data_series_plot_window.js +0 -0
  120. package/src/charts/downsample.js +0 -0
  121. package/src/charts/plot_config.js +0 -0
  122. package/src/charts/plotly_wrapper.js +0 -0
  123. package/src/core/event_bus.js +0 -0
  124. package/src/core/logging.js +0 -0
  125. package/src/core/settings.js +0 -0
  126. package/src/core/state_guard.js +0 -0
  127. package/src/core/state_machine.js +0 -0
  128. package/src/editor/editor_pane.js +0 -0
  129. package/src/editor/monaco_editor_factory.js +0 -0
  130. package/src/editor/monaco_loader.js +0 -0
  131. package/src/editor/notebook_search.js +0 -0
  132. package/src/editor/notebook_undo_manager.js +0 -0
  133. package/src/editor/split_pane_container.js +0 -0
  134. package/src/flow/canvas_editor/connections.js +0 -0
  135. package/src/flow/canvas_editor/editor.js +0 -0
  136. package/src/flow/canvas_editor/index.js +0 -0
  137. package/src/flow/canvas_editor/layout.js +0 -0
  138. package/src/flow/canvas_editor/strings.js +0 -0
  139. package/src/flow/kit/always_before.js +0 -0
  140. package/src/flow/kit/catalogue.js +0 -0
  141. package/src/flow/kit/chip_input.js +0 -0
  142. package/src/flow/kit/dom.js +28 -119
  143. package/src/flow/kit/findings.js +0 -0
  144. package/src/flow/kit/history.js +0 -0
  145. package/src/flow/kit/index.js +0 -0
  146. package/src/flow/kit/keys.js +0 -0
  147. package/src/flow/kit/logic_graph.js +0 -0
  148. package/src/flow/kit/references.js +0 -0
  149. package/src/flow/kit/settings_panel.js +0 -0
  150. package/src/flow/kit/settings_schema.js +0 -0
  151. package/src/flow/kit/step_picker.js +1 -1
  152. package/src/flow/kit/strings.js +0 -0
  153. package/src/flow/kit/value_picker.js +1 -1
  154. package/src/flow/kit/widgets.js +0 -0
  155. package/src/flow/lanes/editor.js +0 -0
  156. package/src/flow/lanes/index.js +0 -0
  157. package/src/flow/lanes/layout.js +0 -0
  158. package/src/flow/lanes/pipeline.js +0 -0
  159. package/src/flow/lanes/preview.js +0 -0
  160. package/src/flow/lanes/strings.js +0 -0
  161. package/src/flow/outline/editor.js +0 -0
  162. package/src/flow/outline/index.js +0 -0
  163. package/src/flow/outline/mapping.js +0 -0
  164. package/src/flow/outline/menu.js +1 -1
  165. package/src/flow/outline/operations.js +0 -0
  166. package/src/flow/outline/recognise.js +0 -0
  167. package/src/flow/outline/strings.js +0 -0
  168. package/src/git/diff_viewer.js +212 -0
  169. package/src/git/diff_window.js +51 -0
  170. package/src/git/git_graph.js +401 -0
  171. package/src/git/git_ops.js +61 -0
  172. package/src/git/git_panel.js +755 -0
  173. package/src/git/index.js +9 -0
  174. package/src/git/line_diff.js +202 -0
  175. package/src/help/help_modal.js +0 -0
  176. package/src/help/help_registry.js +0 -0
  177. package/src/host/external_links.js +0 -0
  178. package/src/host/file_picker.js +0 -0
  179. package/src/host/host.js +0 -0
  180. package/src/host/photino_host.js +0 -0
  181. package/src/host/photino_host.md +0 -0
  182. package/src/host/pywebview_host.js +0 -0
  183. package/src/tiles/chart_tiles.js +0 -0
  184. package/src/tiles/config_schema.js +0 -0
  185. package/src/tiles/figure_tile.js +0 -0
  186. package/src/tiles/layout_persistence.js +0 -0
  187. package/src/tiles/list_tiles.js +0 -0
  188. package/src/tiles/scope_picker.js +0 -0
  189. package/src/tiles/tile_base.js +5 -4
  190. package/src/tiles/tile_config_form.js +0 -0
  191. package/src/tiles/tile_registry.js +0 -0
  192. package/src/tiling/bottom_panel_tabs.js +0 -0
  193. package/src/tiling/command_palette.js +0 -0
  194. package/src/tiling/content_registry.js +0 -0
  195. package/src/tiling/desktops.js +10 -8
  196. package/src/tiling/entity_sources.js +0 -0
  197. package/src/tiling/keymap.js +6 -5
  198. package/src/tiling/kind_taxonomy.js +15 -2
  199. package/src/tiling/landing_table.js +0 -0
  200. package/src/tiling/loading_overlay.js +0 -0
  201. package/src/tiling/nav_panel.js +0 -0
  202. package/src/tiling/page_factory.js +0 -0
  203. package/src/tiling/panel_availability.js +0 -0
  204. package/src/tiling/panel_keys.js +0 -0
  205. package/src/tiling/shell.js +124 -17
  206. package/src/tiling/tab_strip.js +0 -0
  207. package/src/tiling/tile_renderer.js +2 -3
  208. package/src/tiling/tile_tab_menu.js +0 -0
  209. package/src/tiling/zoom.js +0 -0
  210. package/src/ui/base/component_base.js +0 -0
  211. package/src/ui/base/controller_base.js +0 -0
  212. package/src/ui/base/page_base.js +0 -0
  213. package/src/ui/components/about_dialog.js +0 -0
  214. package/src/ui/components/action_dropdown.js +4 -78
  215. package/src/ui/components/alert_log.js +0 -0
  216. package/src/ui/components/alerts_pane.js +0 -0
  217. package/src/ui/components/anchored_layer.js +255 -0
  218. package/src/ui/components/attribute_list_editor.js +0 -0
  219. package/src/ui/components/autocomplete_field.js +0 -0
  220. package/src/ui/components/cell_editor_host.js +0 -0
  221. package/src/ui/components/cell_editors.js +0 -0
  222. package/src/ui/components/cell_grid.js +0 -0
  223. package/src/ui/components/cell_paste.js +0 -0
  224. package/src/ui/components/cell_selection.js +0 -0
  225. package/src/ui/components/chat_shell.js +920 -0
  226. package/src/ui/components/chat_state_machine.js +223 -0
  227. package/src/ui/components/choice_controls.js +45 -2
  228. package/src/ui/components/color_field.js +3 -2
  229. package/src/ui/components/color_list_field.js +3 -2
  230. package/src/ui/components/column_fit.js +0 -0
  231. package/src/ui/components/column_groups.js +0 -0
  232. package/src/ui/components/column_order.js +0 -0
  233. package/src/ui/components/combobox.js +422 -0
  234. package/src/ui/components/conversation_view.js +17 -2
  235. package/src/ui/components/crosstab.js +0 -0
  236. package/src/ui/components/data_table.js +2 -2
  237. package/src/ui/components/detail_header.js +0 -0
  238. package/src/ui/components/document_outline.js +0 -0
  239. package/src/ui/components/drag_reorder.js +0 -0
  240. package/src/ui/components/fact_table.js +0 -0
  241. package/src/ui/components/fill_handle.js +0 -0
  242. package/src/ui/components/filter_builder.js +766 -0
  243. package/src/ui/components/filter_model.js +614 -0
  244. package/src/ui/components/gallery_picker.js +0 -0
  245. package/src/ui/components/header_actions.js +0 -0
  246. package/src/ui/components/inline_renamer.js +0 -0
  247. package/src/ui/components/job_progress.js +0 -0
  248. package/src/ui/components/managed_window.js +24 -47
  249. package/src/ui/components/menu_bar.js +101 -24
  250. package/src/ui/components/modal.js +79 -109
  251. package/src/ui/components/option_list.js +160 -0
  252. package/src/ui/components/popover.js +94 -0
  253. package/src/ui/components/progress.js +0 -0
  254. package/src/ui/components/recent_items.js +169 -0
  255. package/src/ui/components/record_list.js +0 -0
  256. package/src/ui/components/row_activation.js +0 -0
  257. package/src/ui/components/section_stack.js +0 -0
  258. package/src/ui/components/select.js +322 -0
  259. package/src/ui/components/series.js +0 -0
  260. package/src/ui/components/settings_view.js +0 -0
  261. package/src/ui/components/slide_out_panel.js +0 -0
  262. package/src/ui/components/slider_field.js +0 -0
  263. package/src/ui/components/sortable_list.js +0 -0
  264. package/src/ui/components/staged_edits.js +0 -0
  265. package/src/ui/components/staged_history.js +0 -0
  266. package/src/ui/components/table_filter_chips.js +0 -0
  267. package/src/ui/components/table_state_store.js +0 -0
  268. package/src/ui/components/table_structure.js +0 -0
  269. package/src/ui/components/table_values.js +0 -0
  270. package/src/ui/components/tabs.js +0 -0
  271. package/src/ui/components/tag_input.js +77 -8
  272. package/src/ui/components/toast.js +0 -0
  273. package/src/ui/components/toggle_field.js +0 -0
  274. package/src/ui/components/tsv.js +0 -0
  275. package/src/ui/components/window_taskbar.js +0 -0
  276. package/src/ui/components/workspace_picker.js +1155 -0
  277. package/src/ui/controllers/window_chrome_controller.js +4 -1
  278. package/src/ui/utils/auto_scrollbars.js +0 -0
  279. package/src/ui/utils/fire_event.js +17 -0
  280. package/src/ui/utils/focusable.js +25 -0
  281. package/src/ui/utils/markdown.js +0 -0
  282. package/src/ui/utils/modal_host.js +27 -0
  283. package/src/ui/utils/native_context_menu.js +0 -0
  284. package/src/ui/utils/overlay_scrollbar.js +0 -0
  285. package/src/ui/utils/raf_resize_observer.js +0 -0
  286. package/src/ui/utils/scroll_lock.js +0 -0
  287. package/src/ui/utils/strip_scroll.js +0 -0
  288. package/src/ui/utils/tooltip_service.js +0 -0
  289. package/tiles.js +0 -0
  290. package/widgets.js +12 -2
  291. package/wm.js +0 -0
  292. package/css/base.css +0 -10527
  293. package/css/overrides.css +0 -2596
  294. package/dist/chunk-7JI7HHSY.js +0 -107
  295. package/dist/chunk-7JI7HHSY.js.map +0 -7
  296. package/dist/chunk-MIW7D6WC.js +0 -526
  297. package/dist/chunk-MIW7D6WC.js.map +0 -7
  298. package/dist/chunk-PGZ4EHSE.js.map +0 -7
  299. package/dist/chunk-XJNADRGR.js.map +0 -7
  300. /package/dist/{chunk-REJ5HLIM.js.map → chunk-HYJYYEPK.js.map} +0 -0
package/dist/wm.js CHANGED
@@ -1,27 +1,29 @@
1
1
  import {
2
2
  HelpModal,
3
3
  createMenuBar
4
- } from "./chunk-JKZLNKG6.js";
4
+ } from "./chunk-HKPB6OFA.js";
5
5
  import {
6
6
  TAB_LEVELS,
7
7
  createTabs
8
- } from "./chunk-REJ5HLIM.js";
8
+ } from "./chunk-HYJYYEPK.js";
9
9
  import {
10
+ openForm,
10
11
  showContextMenu
11
- } from "./chunk-7JI7HHSY.js";
12
+ } from "./chunk-RKVYIXDC.js";
12
13
  import {
13
- openForm
14
- } from "./chunk-XJNADRGR.js";
15
- import {
16
- ManagedWindow,
17
14
  isRowActivation
18
- } from "./chunk-PGZ4EHSE.js";
15
+ } from "./chunk-VLOAI3HS.js";
16
+ import {
17
+ ManagedWindow
18
+ } from "./chunk-ZL3VKINP.js";
19
+ import "./chunk-Q7BALEPX.js";
19
20
  import "./chunk-HNU6MM2B.js";
20
21
  import {
21
22
  NotebookTabBar
22
- } from "./chunk-7U4IB65H.js";
23
+ } from "./chunk-LLBJ2SJH.js";
23
24
  import "./chunk-N7HC3ADV.js";
24
- import "./chunk-WUFLGETN.js";
25
+ import "./chunk-WVFGV5FT.js";
26
+ import "./chunk-QXAOTGCC.js";
25
27
  import "./chunk-JYWURG5T.js";
26
28
 
27
29
  // src/tiling/bottom_panel_tabs.js
@@ -166,7 +168,7 @@ function keyboardShortcutsTopic(shortcuts = KEYMAP_SHORTCUTS) {
166
168
  html: `<table class="help-shortcuts"><thead><tr><th>Keys</th><th>Action</th></tr></thead><tbody>${rows}</tbody></table>`
167
169
  };
168
170
  }
169
- var DEFAULT_NAV_SELECTOR = ".twm-global-top-bar .twm-bar-center.twm-top-nav .twm-top-nav__btn";
171
+ var DEFAULT_NAV_SELECTOR = ".twm-global-top-bar .twm-bar-center.twm-top-nav .twm-top-nav__btn, .twm-fl-bar .twm-fl-item[data-kind]";
170
172
  var DIRS = ["left", "right", "up", "down"];
171
173
  var _where = (d) => d === "up" || d === "down" ? d : `on the ${d}`;
172
174
  var ACTIONS = {
@@ -242,10 +244,10 @@ function _action(name) {
242
244
  if (m[1] === "nav") {
243
245
  return {
244
246
  label: `Jump to top-nav page ${n + 1}`,
245
- // The selector is a CONFIG option, not a constant. An embedder that
246
- // moves its sections out of the top bar — into an icon rail, say —
247
- // would otherwise find F1..F8 silently doing nothing. Passing
248
- // `navSelector` is how such an embedder keeps the keys.
247
+ // The default finds the top bar's buttons and the page rail's. An
248
+ // embedder that draws its page buttons in markup of its own would
249
+ // otherwise find F1..F8 silently doing nothing. Passing `navSelector`
250
+ // is how such an embedder keeps the keys.
249
251
  run: ({ navSelector }) => {
250
252
  const btns = document.querySelectorAll(navSelector || DEFAULT_NAV_SELECTOR);
251
253
  if (n >= btns.length) return false;
@@ -2393,11 +2395,11 @@ var DesktopManager = class _DesktopManager {
2393
2395
  * nothing, and an app can put almost anything in a title.
2394
2396
  *
2395
2397
  * And strict is not hostile to an old blob. A key the loader has always given
2396
- * a default may be absent: a desktop's `id`, `label` and `panels`, the keys
2397
- * later releases added (`panelShares`, `group`, `fixed`), and a leaf's `tabs`
2398
- * and `pageTabs`. What `serialize()` has always written and the loader cannot
2399
- * do without (`desktops`, a desktop's `tree`, a split's `dir`, `children` and
2400
- * `sizes`) may not.
2398
+ * a default may be absent: a desktop's `id`, `label`, `tree` and `panels`, the
2399
+ * keys later releases added (`panelShares`, `group`, `fixed`), and a leaf's
2400
+ * `tabs` and `pageTabs`. What `serialize()` has always written and the loader
2401
+ * cannot do without (`desktops`, a split's `dir`, `children` and `sizes`) may
2402
+ * not.
2401
2403
  */
2402
2404
  static deserialize(blob, { seed, panelDefaults = null } = {}) {
2403
2405
  const m = new _DesktopManager({ seed, panelDefaults });
@@ -2412,7 +2414,7 @@ var DesktopManager = class _DesktopManager {
2412
2414
  const at = `desktops[${i}]`;
2413
2415
  _expect2(_isRecord2(raw), at, "a desktop, an object", raw);
2414
2416
  _expect2(
2415
- raw.tree === null || _isRecord2(raw.tree) && _isRecord2(raw.tree.root),
2417
+ raw.tree == null || _isRecord2(raw.tree) && _isRecord2(raw.tree.root),
2416
2418
  `${at}.tree`,
2417
2419
  "{ root }, or null for an empty desktop",
2418
2420
  raw.tree
@@ -2626,6 +2628,14 @@ function createTaxonomy({ kinds, root } = {}) {
2626
2628
  `createTaxonomy: '${kind}' is both a top-nav kind and owned by one`
2627
2629
  );
2628
2630
  }
2631
+ if (def.railPin !== void 0) {
2632
+ if (def.railPin !== "bottom") {
2633
+ throw new TypeError(`createTaxonomy: '${kind}'.railPin must be 'bottom'`);
2634
+ }
2635
+ if (!def.isTopNav) {
2636
+ throw new Error(`createTaxonomy: '${kind}' has a railPin but is not a top-nav kind`);
2637
+ }
2638
+ }
2629
2639
  if (def.panels !== void 0) {
2630
2640
  if (!def.panels || typeof def.panels !== "object" || Array.isArray(def.panels)) {
2631
2641
  throw new TypeError(`createTaxonomy: '${kind}'.panels must be an object`);
@@ -2729,7 +2739,8 @@ function createTaxonomy({ kinds, root } = {}) {
2729
2739
  kind,
2730
2740
  label: m.shortLabel || m.label,
2731
2741
  longLabel: m.label,
2732
- icon: m.icon
2742
+ icon: m.icon,
2743
+ railPin: m.railPin ?? null
2733
2744
  }));
2734
2745
  const isSingle = (kind) => {
2735
2746
  const s = _kinds[kind]?.single;
@@ -4945,7 +4956,7 @@ var TileRenderer = class {
4945
4956
  /** The rectangle a release would fill.
4946
4957
  *
4947
4958
  * IT IS THE WINDOW DROP'S OWN PREVIEW ELEMENT — same two classes, same
4948
- * stylesheet rules (`css/base.css`, `.twm-snap-preview`) — so a tab drop
4959
+ * stylesheet rules (`css/flexdesk.css`, `.twm-snap-preview`) — so a tab drop
4949
4960
  * and a window drop cannot come to disagree about what a drop looks like.
4950
4961
  * `--viewport` is what makes `position: fixed` apply, and that is required
4951
4962
  * rather than cosmetic: the rectangle came from `getBoundingClientRect` on
@@ -9683,9 +9694,9 @@ async function createShell({
9683
9694
  desktopBar = {},
9684
9695
  menuBar: menuBarCfg = null,
9685
9696
  chrome = {},
9686
- // An embedder that moved its sections out of the top bar — into an icon
9687
- // rail, say — passes the selector its own buttons match, and F1..F8 keep
9688
- // working. Omitted, the default top-bar selector applies.
9697
+ // An embedder that draws its page buttons in markup of its own passes the
9698
+ // selector they match, and F1..F8 keep working. Omitted, the default finds
9699
+ // `chrome.topNav`'s buttons and `chrome.rail`'s.
9689
9700
  navSelector = null,
9690
9701
  keymap = null
9691
9702
  } = {}) {
@@ -9694,6 +9705,9 @@ async function createShell({
9694
9705
  }
9695
9706
  if (!taxonomy) throw new Error("createShell: a taxonomy is required");
9696
9707
  if (!entities) throw new Error("createShell: an entity catalog is required");
9708
+ if (chrome.topNav && chrome.rail) {
9709
+ throw new TypeError("createShell: `chrome.topNav` and `chrome.rail` both paint the pages; give one");
9710
+ }
9697
9711
  if (chrome.menuBar && !menuBarCfg?.menus) {
9698
9712
  throw new TypeError("createShell: `chrome.menuBar` needs `menuBar: { menus }`");
9699
9713
  }
@@ -9717,6 +9731,7 @@ async function createShell({
9717
9731
  const registry = createContentRegistry(content);
9718
9732
  let wm = null;
9719
9733
  let topNavEl = null;
9734
+ let rail = null;
9720
9735
  let desktopsEl = null;
9721
9736
  let toggles = null;
9722
9737
  const syncChrome = () => {
@@ -9724,6 +9739,7 @@ async function createShell({
9724
9739
  syncPanelToggles(toggles, wm);
9725
9740
  syncDesktopBar(desktopsEl, wm);
9726
9741
  syncTopNav(topNavEl, wm);
9742
+ rail?.sync();
9727
9743
  };
9728
9744
  wm = new WindowManager({
9729
9745
  rootEl: root,
@@ -9776,7 +9792,9 @@ async function createShell({
9776
9792
  });
9777
9793
  const disposeKeymap = installKeymap({ wm, palette, navSelector, bindings, logger });
9778
9794
  const paletteBtn = mountPaletteButton(chrome.paletteButton, palette);
9779
- topNavEl = mountTopNav(chrome.topNav, taxonomy, wm);
9795
+ const topNav = mountTopNav(chrome.topNav, taxonomy, wm);
9796
+ topNavEl = topNav?.el ?? null;
9797
+ rail = chrome.rail ? mountPageRail(chrome.rail, { wm }) : null;
9780
9798
  desktopsEl = mountDesktopBar(chrome.desktops, wm, desktopBar || {});
9781
9799
  const zoom = mountZoomControl(chrome.zoom, { root, host });
9782
9800
  if (zoom) await zoom.ready;
@@ -9795,6 +9813,7 @@ async function createShell({
9795
9813
  chrome: Object.freeze({
9796
9814
  paletteButtonEl: paletteBtn,
9797
9815
  topNavEl,
9816
+ railEl: rail?.el ?? null,
9798
9817
  desktopsEl,
9799
9818
  panelToggles: toggles,
9800
9819
  // `get`/`set` so an embedder can drive the zoom from its own settings
@@ -9834,6 +9853,14 @@ async function createShell({
9834
9853
  desktopsEl?.remove();
9835
9854
  } catch {
9836
9855
  }
9856
+ try {
9857
+ rail?.dispose();
9858
+ } catch {
9859
+ }
9860
+ try {
9861
+ topNav?.dispose();
9862
+ } catch {
9863
+ }
9837
9864
  try {
9838
9865
  menuBar?.dispose();
9839
9866
  } catch {
@@ -9858,23 +9885,83 @@ function mountTopNav(hostEl, taxonomy, wm) {
9858
9885
  `;
9859
9886
  hostEl.appendChild(btn);
9860
9887
  }
9861
- hostEl.addEventListener("click", (e) => {
9888
+ const onClick = (e) => {
9862
9889
  const btn = e.target.closest("[data-kind]");
9863
9890
  if (!btn) return;
9864
9891
  wm.openInPrimary(btn.dataset.kind);
9865
- });
9866
- return hostEl;
9892
+ };
9893
+ hostEl.addEventListener("click", onClick);
9894
+ return {
9895
+ el: hostEl,
9896
+ dispose: () => {
9897
+ hostEl.removeEventListener("click", onClick);
9898
+ hostEl.replaceChildren();
9899
+ }
9900
+ };
9867
9901
  }
9868
- function syncTopNav(hostEl, wm) {
9869
- if (!hostEl) return;
9902
+ function activePageKind(wm) {
9870
9903
  const tree = wm.desktops.active().tree;
9871
9904
  const primaryId = tree.primaryLeafId();
9872
9905
  const primaryKind = primaryId ? tree.get(primaryId)?.content?.kind : null;
9873
- const topNavKind = wm.taxonomy.topNavFor(primaryKind) || primaryKind;
9906
+ return wm.taxonomy.topNavFor(primaryKind) || primaryKind;
9907
+ }
9908
+ function syncTopNav(hostEl, wm) {
9909
+ if (!hostEl) return;
9910
+ const topNavKind = activePageKind(wm);
9874
9911
  hostEl.querySelectorAll("[data-kind]").forEach((b) => {
9875
9912
  b.classList.toggle("twm-top-nav__btn--on", b.dataset.kind === topNavKind);
9876
9913
  });
9877
9914
  }
9915
+ function mountPageRail(hostEl, { wm, activeKind = activePageKind, decorate = null } = {}) {
9916
+ if (!hostEl || typeof hostEl.appendChild !== "function") {
9917
+ throw new TypeError("mountPageRail: `hostEl` must be an element");
9918
+ }
9919
+ if (!wm) throw new TypeError("mountPageRail: `wm` is required");
9920
+ hostEl.classList.add("twm-fl-bar");
9921
+ if (!hostEl.hasAttribute("aria-label")) hostEl.setAttribute("aria-label", "Pages");
9922
+ const entries = wm.taxonomy.topNavEntries();
9923
+ const buttons = [
9924
+ ...entries.filter((k) => k.railPin !== "bottom"),
9925
+ ...entries.filter((k) => k.railPin === "bottom")
9926
+ ].map((k) => {
9927
+ const btn = document.createElement("button");
9928
+ btn.type = "button";
9929
+ btn.className = "twm-fl-item twm-has-tooltip";
9930
+ btn.classList.toggle("twm-fl-item--bottom", k.railPin === "bottom");
9931
+ btn.dataset.kind = k.kind;
9932
+ btn.dataset.tooltip = k.longLabel;
9933
+ btn.setAttribute("aria-label", k.longLabel);
9934
+ const glyph = document.createElement("span");
9935
+ glyph.className = "material-symbols-outlined";
9936
+ glyph.setAttribute("aria-hidden", "true");
9937
+ glyph.textContent = k.icon;
9938
+ btn.appendChild(glyph);
9939
+ decorate?.(btn, k);
9940
+ return btn;
9941
+ });
9942
+ hostEl.replaceChildren(...buttons);
9943
+ const onClick = (e) => {
9944
+ const btn = e.target.closest("[data-kind]");
9945
+ if (btn) wm.openInPrimary(btn.dataset.kind);
9946
+ };
9947
+ hostEl.addEventListener("click", onClick);
9948
+ return Object.freeze({
9949
+ el: hostEl,
9950
+ sync: () => {
9951
+ const active = activeKind(wm);
9952
+ for (const btn of buttons) {
9953
+ const on = btn.dataset.kind === active;
9954
+ btn.classList.toggle("twm-fl-item--on", on);
9955
+ if (on) btn.setAttribute("aria-current", "page");
9956
+ else btn.removeAttribute("aria-current");
9957
+ }
9958
+ },
9959
+ dispose: () => {
9960
+ hostEl.removeEventListener("click", onClick);
9961
+ hostEl.replaceChildren();
9962
+ }
9963
+ });
9964
+ }
9878
9965
  function mountPaletteButton(hostEl, palette) {
9879
9966
  if (!hostEl) return null;
9880
9967
  hostEl.querySelector("#twm-palette-btn")?.remove();
@@ -10220,6 +10307,7 @@ export {
10220
10307
  mountLandingActions,
10221
10308
  mountLandingShell,
10222
10309
  mountNavPanel,
10310
+ mountPageRail,
10223
10311
  mountTileBreadcrumb,
10224
10312
  mountZoomControl,
10225
10313
  openTileTabMenu,