@starlove/orbit 1.4.1 → 2.0.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 (329) hide show
  1. package/Dockerfile +10 -8
  2. package/README.md +146 -164
  3. package/dist/full/csp.txt +1 -0
  4. package/dist/full/fonts/JetBrains_Mono/JetBrainsMono-subset.woff2 +0 -0
  5. package/dist/full/fonts/JetBrains_Mono/README.txt +5 -0
  6. package/dist/full/fonts/Mona_Sans/MonaSans-subset.woff2 +0 -0
  7. package/{public/fonts/Open_Sans → dist/full/fonts/Mona_Sans}/OFL.txt +93 -93
  8. package/dist/full/fonts/Mona_Sans/README.txt +10 -0
  9. package/{public/fonts/JetBrains_Mono → dist/full/fonts/Newsreader}/OFL.txt +93 -93
  10. package/dist/full/fonts/Newsreader/README.txt +8 -0
  11. package/dist/full/fonts/Newsreader/newsreader.woff2 +0 -0
  12. package/dist/full/index.html +36 -653
  13. package/dist/full/js/app.BmuponPJ.js +32 -0
  14. package/dist/full/js/app.BmuponPJ.js.map +1 -0
  15. package/dist/full/js/chunk.1fJGQGbW.js +2 -0
  16. package/dist/full/js/chunk.1fJGQGbW.js.map +1 -0
  17. package/dist/full/js/chunk.5D7JO2zp.js +2 -0
  18. package/dist/full/js/chunk.5D7JO2zp.js.map +1 -0
  19. package/dist/full/js/chunk.BrNn_D79.js +2 -0
  20. package/dist/full/js/chunk.BrNn_D79.js.map +1 -0
  21. package/dist/full/js/chunk.CokJXIqM.js +2 -0
  22. package/dist/full/js/chunk.CokJXIqM.js.map +1 -0
  23. package/dist/full/js/chunk.D_Haqy6R.js +2 -0
  24. package/dist/full/js/chunk.D_Haqy6R.js.map +1 -0
  25. package/dist/full/js/chunk.RO0jsH6I.js +15 -0
  26. package/dist/full/js/chunk.RO0jsH6I.js.map +1 -0
  27. package/dist/full/js/chunk.dqWOEtBM.js +2 -0
  28. package/dist/full/js/chunk.dqWOEtBM.js.map +1 -0
  29. package/dist/full/js/warm.f260bbbc.js +15 -0
  30. package/dist/full/orbits-favicon.png +0 -0
  31. package/dist/full/orbits-logo-bg-wide.png +0 -0
  32. package/dist/full/orbits-logo-bg.png +0 -0
  33. package/dist/full/orbits-logo.png +0 -0
  34. package/dist/full/styles.2b154ffe.css +1 -0
  35. package/dist/full/vendor/starlove-ui/theme-init.js +66 -0
  36. package/dist/full/version.json +2 -2
  37. package/docs/AGENT_GUIDE.md +114 -0
  38. package/docs/UPDATING.md +249 -64
  39. package/lib/adapters/indexeddb/blobs.d.ts +3 -0
  40. package/lib/adapters/indexeddb/blobs.js +54 -0
  41. package/lib/adapters/indexeddb/database.d.ts +60 -0
  42. package/lib/adapters/indexeddb/database.js +126 -0
  43. package/lib/adapters/indexeddb/index.d.ts +5 -0
  44. package/lib/adapters/indexeddb/index.js +3 -0
  45. package/lib/adapters/indexeddb/locks.d.ts +14 -0
  46. package/lib/adapters/indexeddb/locks.js +40 -0
  47. package/lib/adapters/indexeddb/store.d.ts +40 -0
  48. package/lib/adapters/indexeddb/store.js +424 -0
  49. package/lib/adapters/indexeddb/tables.d.ts +43 -0
  50. package/lib/adapters/indexeddb/tables.js +127 -0
  51. package/lib/adapters/memory/blobs.d.ts +3 -0
  52. package/lib/adapters/memory/blobs.js +44 -0
  53. package/lib/adapters/memory/board.d.ts +41 -0
  54. package/lib/adapters/memory/board.js +521 -0
  55. package/lib/adapters/memory/index.d.ts +2 -0
  56. package/lib/adapters/memory/index.js +2 -0
  57. package/lib/adapters/memory/search.d.ts +6 -0
  58. package/lib/adapters/memory/search.js +30 -0
  59. package/lib/adapters/memory/store.d.ts +34 -0
  60. package/lib/adapters/memory/store.js +266 -0
  61. package/lib/adapters/sqlite/backups.d.ts +53 -0
  62. package/lib/adapters/sqlite/backups.js +232 -0
  63. package/lib/adapters/sqlite/blobs.d.ts +14 -0
  64. package/lib/adapters/sqlite/blobs.js +109 -0
  65. package/lib/adapters/sqlite/board.d.ts +77 -0
  66. package/lib/adapters/sqlite/board.js +328 -0
  67. package/lib/adapters/sqlite/database.d.ts +67 -0
  68. package/lib/adapters/sqlite/database.js +285 -0
  69. package/lib/adapters/sqlite/index.d.ts +3 -0
  70. package/lib/adapters/sqlite/index.js +2 -0
  71. package/lib/adapters/sqlite/lock.d.ts +11 -0
  72. package/lib/adapters/sqlite/lock.js +34 -0
  73. package/lib/adapters/sqlite/records.d.ts +54 -0
  74. package/lib/adapters/sqlite/records.js +546 -0
  75. package/lib/adapters/sqlite/schema.d.ts +54 -0
  76. package/lib/adapters/sqlite/schema.js +276 -0
  77. package/lib/adapters/sqlite/store.d.ts +39 -0
  78. package/lib/adapters/sqlite/store.js +385 -0
  79. package/lib/browser/in-page.d.ts +31 -0
  80. package/lib/browser/in-page.js +46 -0
  81. package/lib/browser/old-preview.d.ts +13 -0
  82. package/lib/browser/old-preview.js +80 -0
  83. package/lib/browser/preview-board.d.ts +8 -0
  84. package/lib/browser/preview-board.js +69 -0
  85. package/lib/cli/main.d.ts +7 -0
  86. package/lib/cli/main.js +343 -0
  87. package/lib/cli/orbit.d.ts +8 -0
  88. package/lib/cli/orbit.js +25 -0
  89. package/lib/client/http.d.ts +38 -0
  90. package/lib/client/http.js +334 -0
  91. package/lib/client/local.d.ts +26 -0
  92. package/lib/client/local.js +190 -0
  93. package/lib/client/object-url.d.ts +8 -0
  94. package/lib/client/object-url.js +21 -0
  95. package/lib/client/types.d.ts +268 -0
  96. package/lib/client/types.js +8 -0
  97. package/lib/commands/agent-tools.d.ts +31 -0
  98. package/lib/commands/agent-tools.js +100 -0
  99. package/lib/commands/index.d.ts +56 -0
  100. package/lib/commands/index.js +298 -0
  101. package/lib/commands/parse.d.ts +73 -0
  102. package/lib/commands/parse.js +231 -0
  103. package/lib/commands/present.d.ts +134 -0
  104. package/lib/commands/present.js +198 -0
  105. package/lib/commands/session.d.ts +85 -0
  106. package/lib/commands/session.js +138 -0
  107. package/lib/commands/verbs.d.ts +35 -0
  108. package/lib/commands/verbs.js +842 -0
  109. package/lib/core/actors.d.ts +18 -0
  110. package/lib/core/actors.js +45 -0
  111. package/lib/core/agent.d.ts +128 -0
  112. package/lib/core/agent.js +323 -0
  113. package/lib/core/boards.d.ts +113 -0
  114. package/lib/core/boards.js +288 -0
  115. package/lib/core/bootstrap.d.ts +47 -0
  116. package/lib/core/bootstrap.js +100 -0
  117. package/lib/core/bytes.d.ts +10 -0
  118. package/lib/core/bytes.js +52 -0
  119. package/lib/core/card-paths.d.ts +25 -0
  120. package/lib/core/card-paths.js +44 -0
  121. package/lib/core/context.d.ts +60 -0
  122. package/lib/core/context.js +42 -0
  123. package/lib/core/cross-board.d.ts +81 -0
  124. package/lib/core/cross-board.js +228 -0
  125. package/lib/core/describe.d.ts +21 -0
  126. package/lib/core/describe.js +81 -0
  127. package/lib/core/errors.d.ts +159 -0
  128. package/lib/core/errors.js +160 -0
  129. package/lib/core/files.d.ts +79 -0
  130. package/lib/core/files.js +262 -0
  131. package/lib/core/history.d.ts +20 -0
  132. package/lib/core/history.js +53 -0
  133. package/lib/core/image-types.d.ts +16 -0
  134. package/lib/core/image-types.js +36 -0
  135. package/lib/core/model.d.ts +263 -0
  136. package/lib/core/model.js +34 -0
  137. package/lib/core/nebula-link.d.ts +14 -0
  138. package/lib/core/nebula-link.js +39 -0
  139. package/lib/core/relations.d.ts +58 -0
  140. package/lib/core/relations.js +112 -0
  141. package/lib/core/search.d.ts +38 -0
  142. package/lib/core/search.js +92 -0
  143. package/lib/core/sessions.d.ts +44 -0
  144. package/lib/core/sessions.js +158 -0
  145. package/lib/core/snapshot-schema.d.ts +295 -0
  146. package/lib/core/snapshot-schema.js +82 -0
  147. package/lib/core/snapshots.d.ts +75 -0
  148. package/lib/core/snapshots.js +409 -0
  149. package/lib/core/states.d.ts +25 -0
  150. package/lib/core/states.js +126 -0
  151. package/lib/core/text.d.ts +40 -0
  152. package/lib/core/text.js +113 -0
  153. package/lib/core/tickets.d.ts +69 -0
  154. package/lib/core/tickets.js +311 -0
  155. package/lib/core/trello.d.ts +17 -0
  156. package/lib/core/trello.js +269 -0
  157. package/lib/core/verdicts.d.ts +28 -0
  158. package/lib/core/verdicts.js +92 -0
  159. package/lib/core/views.d.ts +95 -0
  160. package/lib/core/views.js +186 -0
  161. package/lib/http/app.d.ts +46 -0
  162. package/lib/http/app.js +491 -0
  163. package/lib/mcp-server.d.ts +10 -0
  164. package/lib/mcp-server.js +120 -0
  165. package/lib/node/assets.d.ts +7 -0
  166. package/lib/node/assets.js +68 -0
  167. package/lib/node/data-folder.d.ts +21 -0
  168. package/lib/node/data-folder.js +34 -0
  169. package/lib/node/env.d.ts +38 -0
  170. package/lib/node/env.js +49 -0
  171. package/lib/node/host-check.d.ts +24 -0
  172. package/lib/node/host-check.js +53 -0
  173. package/lib/node/host-services.d.ts +9 -0
  174. package/lib/node/host-services.js +150 -0
  175. package/lib/node/local.d.ts +22 -0
  176. package/lib/node/local.js +61 -0
  177. package/lib/node/migrate.d.ts +53 -0
  178. package/lib/node/migrate.js +635 -0
  179. package/lib/node/package.d.ts +7 -0
  180. package/lib/node/package.js +14 -0
  181. package/lib/node/repo-board.d.ts +49 -0
  182. package/lib/node/repo-board.js +245 -0
  183. package/lib/node/serve.d.ts +8 -0
  184. package/lib/node/serve.js +106 -0
  185. package/lib/orbit.d.ts +47 -0
  186. package/lib/orbit.js +44 -0
  187. package/lib/quiet-sqlite-warning.d.ts +1 -0
  188. package/lib/quiet-sqlite-warning.js +18 -0
  189. package/lib/store/blob-path.d.ts +6 -0
  190. package/lib/store/blob-path.js +12 -0
  191. package/lib/store/conformance.d.ts +52 -0
  192. package/lib/store/conformance.js +1449 -0
  193. package/lib/store/search-words.d.ts +10 -0
  194. package/lib/store/search-words.js +19 -0
  195. package/lib/store/types.d.ts +452 -0
  196. package/lib/store/types.js +34 -0
  197. package/llms.txt +63 -0
  198. package/package.json +109 -25
  199. package/src/cli/orbit.js +11 -658
  200. package/src/mcp-server.js +16 -876
  201. package/SKILL-ORBIT.md +0 -151
  202. package/build.mjs +0 -210
  203. package/dist/full/js/app.4e6fbe20.js +0 -952
  204. package/dist/full/js/app.4e6fbe20.js.map +0 -7
  205. package/dist/full/styles.4e60d824.css +0 -1
  206. package/docs/AGENT_PROTOCOL.md +0 -424
  207. package/docs/MCP_SETUP.md +0 -54
  208. package/docs/ORBIT_DISPATCH.md +0 -280
  209. package/docs/SS-Orbit-Dark.png +0 -0
  210. package/docs/SS-Orbit-Light.png +0 -0
  211. package/docs/mcp-client.example.json +0 -13
  212. package/docs/setup/orbit-init-wizard.md +0 -174
  213. package/public/apple-touch-icon.png +0 -0
  214. package/public/cursors/live_arrow.cur +0 -0
  215. package/public/cursors/live_link.cur +0 -0
  216. package/public/cursors/live_move.cur +0 -0
  217. package/public/cursors/live_select.cur +0 -0
  218. package/public/cursors/live_unavail.cur +0 -0
  219. package/public/favicon-32x32.png +0 -0
  220. package/public/fonts/Chakra_Petch/ChakraPetch-Bold.ttf +0 -0
  221. package/public/fonts/Chakra_Petch/ChakraPetch-BoldItalic.ttf +0 -0
  222. package/public/fonts/Chakra_Petch/ChakraPetch-Italic.ttf +0 -0
  223. package/public/fonts/Chakra_Petch/ChakraPetch-Light.ttf +0 -0
  224. package/public/fonts/Chakra_Petch/ChakraPetch-LightItalic.ttf +0 -0
  225. package/public/fonts/Chakra_Petch/ChakraPetch-Medium.ttf +0 -0
  226. package/public/fonts/Chakra_Petch/ChakraPetch-MediumItalic.ttf +0 -0
  227. package/public/fonts/Chakra_Petch/ChakraPetch-Regular.ttf +0 -0
  228. package/public/fonts/Chakra_Petch/ChakraPetch-SemiBold.ttf +0 -0
  229. package/public/fonts/Chakra_Petch/ChakraPetch-SemiBoldItalic.ttf +0 -0
  230. package/public/fonts/Chakra_Petch/OFL.txt +0 -93
  231. package/public/fonts/Inter/Inter-Italic-VariableFont_opsz,wght.ttf +0 -0
  232. package/public/fonts/Inter/Inter-VariableFont_opsz,wght.ttf +0 -0
  233. package/public/fonts/Inter/OFL.txt +0 -93
  234. package/public/fonts/Inter/README.txt +0 -118
  235. package/public/fonts/JetBrains_Mono/JetBrainsMono-Italic-VariableFont_wght.ttf +0 -0
  236. package/public/fonts/JetBrains_Mono/JetBrainsMono-VariableFont_wght.ttf +0 -0
  237. package/public/fonts/JetBrains_Mono/README.txt +0 -79
  238. package/public/fonts/OpenRing-Regular.ttf +0 -0
  239. package/public/fonts/Open_Sans/OpenSans-Italic-VariableFont_wdth,wght.ttf +0 -0
  240. package/public/fonts/Open_Sans/OpenSans-VariableFont_wdth,wght.ttf +0 -0
  241. package/public/fonts/Open_Sans/README.txt +0 -100
  242. package/public/fonts/Orbitron/OFL.txt +0 -93
  243. package/public/fonts/Orbitron/Orbitron-VariableFont_wght.ttf +0 -0
  244. package/public/fonts/Orbitron/README.txt +0 -68
  245. package/public/fonts/Rajdhani/OFL.txt +0 -93
  246. package/public/fonts/Rajdhani/Rajdhani-Bold.ttf +0 -0
  247. package/public/fonts/Rajdhani/Rajdhani-Light.ttf +0 -0
  248. package/public/fonts/Rajdhani/Rajdhani-Medium.ttf +0 -0
  249. package/public/fonts/Rajdhani/Rajdhani-Regular.ttf +0 -0
  250. package/public/fonts/Rajdhani/Rajdhani-SemiBold.ttf +0 -0
  251. package/public/fonts/runescape-uf.ttf +0 -0
  252. package/public/index.html +0 -769
  253. package/public/js/actor-labels.js +0 -65
  254. package/public/js/api.js +0 -39
  255. package/public/js/app.js +0 -45
  256. package/public/js/artifact-drawer.js +0 -79
  257. package/public/js/board-export.js +0 -161
  258. package/public/js/board-menu.js +0 -374
  259. package/public/js/card-actions.js +0 -545
  260. package/public/js/config.js +0 -20
  261. package/public/js/create-card.js +0 -190
  262. package/public/js/dom.js +0 -19
  263. package/public/js/drawer.js +0 -273
  264. package/public/js/font-preference.js +0 -230
  265. package/public/js/format.js +0 -433
  266. package/public/js/help-menu.js +0 -31
  267. package/public/js/icons.js +0 -16
  268. package/public/js/kanban.js +0 -694
  269. package/public/js/local-backend.js +0 -1015
  270. package/public/js/main.js +0 -161
  271. package/public/js/modal.js +0 -33
  272. package/public/js/motion-preference.js +0 -64
  273. package/public/js/panel.js +0 -58
  274. package/public/js/router.js +0 -134
  275. package/public/js/search.js +0 -56
  276. package/public/js/settings-tabs.js +0 -7
  277. package/public/js/settings.js +0 -1634
  278. package/public/js/sse.js +0 -159
  279. package/public/js/starscape.js +0 -332
  280. package/public/js/state.js +0 -129
  281. package/public/js/text-editing.js +0 -128
  282. package/public/js/theme-preference.js +0 -95
  283. package/public/js/ticket-detail.js +0 -1516
  284. package/public/js/ticket-typeahead.js +0 -49
  285. package/public/js/toast.js +0 -89
  286. package/public/js/topbar-notes.js +0 -155
  287. package/public/js/transport.js +0 -22
  288. package/public/js/typeahead.js +0 -206
  289. package/public/js/unread.js +0 -121
  290. package/public/js/update-check.js +0 -58
  291. package/public/js/url-routes.js +0 -94
  292. package/public/orbits-favicon.png +0 -0
  293. package/public/orbits-logo-bg-wide.png +0 -0
  294. package/public/orbits-logo-bg.png +0 -0
  295. package/public/orbits-logo.png +0 -0
  296. package/public/styles.css +0 -7709
  297. package/src/core/agent.js +0 -387
  298. package/src/core/agents-md.js +0 -109
  299. package/src/core/artifacts.js +0 -149
  300. package/src/core/attachments.js +0 -238
  301. package/src/core/auth.js +0 -85
  302. package/src/core/backups.js +0 -142
  303. package/src/core/board.js +0 -148
  304. package/src/core/boards.js +0 -409
  305. package/src/core/bootstrap.js +0 -170
  306. package/src/core/css-bundle.js +0 -30
  307. package/src/core/db.js +0 -315
  308. package/src/core/delete-board.js +0 -163
  309. package/src/core/dispatch.js +0 -1007
  310. package/src/core/events.js +0 -314
  311. package/src/core/http.js +0 -115
  312. package/src/core/migrate.js +0 -198
  313. package/src/core/paths.js +0 -55
  314. package/src/core/provision-repo-board.js +0 -119
  315. package/src/core/queries.js +0 -246
  316. package/src/core/registry.js +0 -211
  317. package/src/core/relations.js +0 -163
  318. package/src/core/review-verdicts.js +0 -138
  319. package/src/core/router.js +0 -556
  320. package/src/core/search.js +0 -183
  321. package/src/core/seed.js +0 -234
  322. package/src/core/snapshots.js +0 -692
  323. package/src/core/states.js +0 -167
  324. package/src/core/system-picker.js +0 -109
  325. package/src/core/tickets.js +0 -400
  326. package/src/core/util.js +0 -106
  327. package/src/core/version-check.js +0 -154
  328. package/src/mcp/orbit-client.js +0 -287
  329. package/src/server.js +0 -115
package/public/js/main.js DELETED
@@ -1,161 +0,0 @@
1
- // Application entry point. Imports `starscape.js` for its side effects
2
- // (canvas + theme toggle init), wires the topbar buttons and global
3
- // keyboard/click listeners, and kicks off the bootstrap → router activation
4
- // sequence. The reusable `load` / `render` helpers live in app.js so feature
5
- // modules can import them without creating cycles back through this entry.
6
-
7
- import "./starscape.js";
8
-
9
- import {
10
- $,
11
- boardMenuBtn,
12
- boardFlyout,
13
- drawer,
14
- drawerBackdrop,
15
- createFlyoutBackdrop,
16
- searchInput
17
- } from "./dom.js";
18
- import { state } from "./state.js";
19
- import { api, withBoardQuery } from "./api.js";
20
- import { toast, debounce } from "./toast.js";
21
- import {
22
- navigate,
23
- applyRoute,
24
- currentRoute,
25
- hasRoute,
26
- syncUrlFromState,
27
- setRouterReady
28
- } from "./router.js";
29
- import {
30
- openBoardFlyout,
31
- closeBoardFlyout,
32
- closeMenuFlyouts
33
- } from "./board-menu.js";
34
- import {
35
- openCreateFlyout,
36
- closeCreateFlyout,
37
- isCreateFlyoutOpen
38
- } from "./create-card.js";
39
- import { enableKanbanDragScroll, enableKanbanInteractions } from "./kanban.js";
40
- import { runSearch, hideSearch } from "./search.js";
41
- import { load } from "./app.js";
42
- import { edition } from "./config.js";
43
- import { openModal, wireModal } from "./modal.js";
44
- import { wireTopbarFocus } from "./topbar-notes.js";
45
- import { wireHelpMenu } from "./help-menu.js";
46
- import { checkForUpdate } from "./update-check.js";
47
- import { applyStoredFontPreferences } from "./font-preference.js";
48
-
49
- async function init() {
50
- const welcomeDialog = document.getElementById("welcomeDialog");
51
- applyStoredFontPreferences();
52
- wireModal(welcomeDialog);
53
- wireTopbarFocus();
54
- wireHelpMenu();
55
- if (edition === "preview") {
56
- openModal(welcomeDialog);
57
- }
58
-
59
- $("#settingsBtn").addEventListener("click", async () => {
60
- closeCreateFlyout();
61
- closeMenuFlyouts();
62
- navigate({
63
- boardId: state.boardId,
64
- view: "settings",
65
- tab: state.settingsTab || "lanes"
66
- });
67
- });
68
-
69
- boardMenuBtn?.addEventListener("click", (event) => {
70
- event.stopPropagation();
71
- if (!boardFlyout.hidden) {
72
- closeBoardFlyout();
73
- return;
74
- }
75
- openBoardFlyout();
76
- });
77
-
78
- $("#newTicketBtn").addEventListener("click", () => {
79
- if (isCreateFlyoutOpen()) {
80
- closeCreateFlyout();
81
- return;
82
- }
83
- openCreateFlyout("");
84
- });
85
-
86
- createFlyoutBackdrop.addEventListener("click", () => {
87
- closeCreateFlyout();
88
- });
89
-
90
- $("#drawerCloseBtn").addEventListener("click", () => {
91
- navigate({
92
- boardId: state.boardId,
93
- view: "board"
94
- });
95
- });
96
-
97
- $("#drawerArchiveBtn").addEventListener("click", async () => {
98
- const ticketId = state.selectedTicketId;
99
- if (!ticketId || state.detailMode !== "ticket") return;
100
- const ticket = state.data?.tickets?.find((t) => t.id === ticketId);
101
- const titleForToast = ticket?.title || "card";
102
- await api(withBoardQuery(`/api/tickets/${encodeURIComponent(ticketId)}/archive`), { method: "POST" });
103
- toast.removed(`Archived: ${titleForToast}`);
104
- await load();
105
- navigate({ boardId: state.boardId, view: "board" });
106
- });
107
-
108
- drawerBackdrop.addEventListener("click", () => {
109
- navigate({
110
- boardId: state.boardId,
111
- view: "board"
112
- });
113
- });
114
-
115
- document.addEventListener("keydown", (event) => {
116
- if (event.key !== "Escape") return;
117
- if (!boardFlyout.hidden) {
118
- closeMenuFlyouts();
119
- return;
120
- }
121
- if (isCreateFlyoutOpen()) {
122
- closeCreateFlyout();
123
- return;
124
- }
125
- if (!drawer.classList.contains("is-open")) return;
126
- const el = document.activeElement;
127
- if (el?.classList?.contains("inline-title-editor") || el?.classList?.contains("inline-desc-editor")) return;
128
- navigate({
129
- boardId: state.boardId,
130
- view: "board"
131
- });
132
- });
133
-
134
- searchInput.addEventListener("input", debounce(runSearch, 220));
135
- document.addEventListener("click", (event) => {
136
- if (!event.target.closest("#topbarSearch")) hideSearch();
137
- if (!event.target.closest(".topbar-menu")) closeMenuFlyouts();
138
- });
139
-
140
- enableKanbanDragScroll();
141
- enableKanbanInteractions();
142
-
143
- const initialRoute = currentRoute();
144
- if (initialRoute.boardSlug) state.boardSlug = initialRoute.boardSlug;
145
- await load();
146
-
147
- // Activate the router. If the page was loaded with a hash route, restore
148
- // that view; otherwise canonicalize the URL to reflect the current
149
- // state so the back button has a starting point.
150
- setRouterReady(true);
151
- if (hasRoute()) {
152
- await applyRoute();
153
- } else {
154
- syncUrlFromState({ replace: true });
155
- }
156
-
157
- // Best-effort, non-blocking: nudge if a newer Orbit is available.
158
- checkForUpdate();
159
- }
160
-
161
- init();
@@ -1,33 +0,0 @@
1
- // Generic <dialog> modal utility.
2
- //
3
- // Usage:
4
- // wireModal(el) — wire backdrop-click + [data-modal-close] buttons.
5
- // openModal(el) — show the dialog as a modal (focus-trapped overlay).
6
- // closeModal(el) — close it programmatically.
7
- //
8
- // Escape key is handled natively by the browser; no extra wiring needed.
9
-
10
- export function openModal(dialogEl) {
11
- if (!dialogEl) return;
12
- dialogEl.showModal();
13
- dialogEl.querySelector("[data-modal-initial-focus]")?.focus({ preventScroll: true });
14
- }
15
-
16
- export function closeModal(dialogEl) {
17
- if (dialogEl?.open) dialogEl.close();
18
- }
19
-
20
- export function wireModal(dialogEl) {
21
- if (!dialogEl) return;
22
-
23
- // Close when the user clicks the backdrop (the dialog element itself,
24
- // outside its inner content box).
25
- dialogEl.addEventListener("click", (event) => {
26
- if (event.target === dialogEl) closeModal(dialogEl);
27
- });
28
-
29
- // Close buttons: any element inside the dialog with [data-modal-close].
30
- dialogEl.querySelectorAll("[data-modal-close]").forEach((btn) => {
31
- btn.addEventListener("click", () => closeModal(dialogEl));
32
- });
33
- }
@@ -1,64 +0,0 @@
1
- export const REDUCE_MOTION_STORAGE_KEY = "mab_reduce_motion";
2
-
3
- function safeStorage(storage) {
4
- try {
5
- return storage ?? globalThis.localStorage ?? null;
6
- } catch {
7
- return null;
8
- }
9
- }
10
-
11
- function defaultMediaMatcher(query) {
12
- return typeof window !== "undefined" && typeof window.matchMedia === "function"
13
- ? window.matchMedia(query)
14
- : { matches: false };
15
- }
16
-
17
- export function storedReducedMotionPreference(storage = safeStorage()) {
18
- const store = safeStorage(storage);
19
- const value = store?.getItem?.(REDUCE_MOTION_STORAGE_KEY);
20
- if (value === "true") return true;
21
- if (value === "false") return false;
22
- return null;
23
- }
24
-
25
- export function browserPrefersReducedMotion(mediaMatcher = defaultMediaMatcher) {
26
- try {
27
- return !!mediaMatcher("(prefers-reduced-motion: reduce)")?.matches;
28
- } catch {
29
- return false;
30
- }
31
- }
32
-
33
- export function effectiveReducedMotionPreference({ storage = safeStorage(), mediaMatcher = defaultMediaMatcher } = {}) {
34
- const stored = storedReducedMotionPreference(storage);
35
- return stored ?? browserPrefersReducedMotion(mediaMatcher);
36
- }
37
-
38
- export function setReducedMotionPreference(reduce, storage = safeStorage()) {
39
- const store = safeStorage(storage);
40
- const value = reduce ? "true" : "false";
41
- store?.setItem?.(REDUCE_MOTION_STORAGE_KEY, value);
42
- return reduce;
43
- }
44
-
45
- export function applyReducedMotionPreference({
46
- doc = globalThis.document,
47
- storage = safeStorage(),
48
- mediaMatcher = defaultMediaMatcher
49
- } = {}) {
50
- // Starscape v3 `data-motion` contract (three-state; shared with the
51
- // ui-system-v3 package and ss-nebula). Replaces the legacy two-state
52
- // `data-reduced-motion="reduce|allow"`:
53
- // • stored reduce → data-motion="reduce" (always reduce)
54
- // • stored allow → data-motion="full" (ignore OS reduce)
55
- // • no stored pref → no attribute (follow OS prefers-reduced-motion)
56
- const root = doc?.documentElement;
57
- const stored = storedReducedMotionPreference(storage);
58
- if (root) {
59
- if (stored === true) root.setAttribute("data-motion", "reduce");
60
- else if (stored === false) root.setAttribute("data-motion", "full");
61
- else root.removeAttribute("data-motion");
62
- }
63
- return effectiveReducedMotionPreference({ storage, mediaMatcher });
64
- }
@@ -1,58 +0,0 @@
1
- // Reusable settings-style "panel" primitives shared by the project settings
2
- // drawer and the ticket detail drawer. A panel is a bordered card with a
3
- // tinted header strip (small-caps title) and a padded body — the same visual
4
- // language used across the Appearance / AI / Data settings tabs. The
5
- // collapsible variant turns the header into a <details>/<summary> toggle with a
6
- // chevron that flips when open, so any surface can drop in a togglable section
7
- // without re-deriving the markup. These intentionally emit the .settings-card
8
- // class family (documented in styles.css as a reusable @starlove/ui primitive).
9
-
10
- import { escapeHtml } from "./format.js";
11
-
12
- const panelChevronSvg = `<svg class="settings-card-chevron" viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6 9l6 6 6-6" /></svg>`;
13
-
14
- /**
15
- * Static panel: bordered card with a header title and a padded body.
16
- *
17
- * Options:
18
- * - title: heading text shown in the small-caps header strip.
19
- * - body: raw HTML for the card body (already escaped by the caller).
20
- * - className: extra classes appended to the .settings-card element.
21
- * - attrs: extra attributes string placed on the <section> (e.g. data-*).
22
- * - headExtra: raw HTML appended after the title inside the header (actions).
23
- */
24
- export function renderPanel({ title, body = "", className = "", attrs = "", headExtra = "" } = {}) {
25
- const classAttr = className ? ` ${className}` : "";
26
- const extraAttrs = attrs ? ` ${attrs}` : "";
27
- return `
28
- <section class="settings-card${classAttr}"${extraAttrs}>
29
- <header class="settings-card-head">
30
- <h3 class="settings-card-title">${escapeHtml(title)}</h3>
31
- ${headExtra}
32
- </header>
33
- <div class="settings-card-body">${body}</div>
34
- </section>
35
- `;
36
- }
37
-
38
- /**
39
- * Collapsible panel: same chrome as renderPanel but the header doubles as a
40
- * <details>/<summary> toggle with a flipping chevron.
41
- *
42
- * Options mirror renderPanel, plus:
43
- * - open: whether the section starts expanded.
44
- */
45
- export function renderTogglePanel({ title, body = "", open = false, className = "", attrs = "", headExtra = "" } = {}) {
46
- const classAttr = className ? ` ${className}` : "";
47
- const extraAttrs = attrs ? ` ${attrs}` : "";
48
- return `
49
- <details class="settings-card settings-card--collapsible${classAttr}"${open ? " open" : ""}${extraAttrs}>
50
- <summary class="settings-card-head">
51
- <h3 class="settings-card-title">${escapeHtml(title)}</h3>
52
- ${headExtra}
53
- ${panelChevronSvg}
54
- </summary>
55
- <div class="settings-card-body">${body}</div>
56
- </details>
57
- `;
58
- }
@@ -1,134 +0,0 @@
1
- // Hash router. Copy/share URLs use board slugs, such as
2
- // `#/b/<boardSlug>`, `#/b/<boardSlug>/t/<ticketId>`, and
3
- // `#/b/<boardSlug>/settings/<tab>`. Keeping routing in the hash lets the
4
- // preview app keep working when mounted under `/app/` or opened as static HTML.
5
-
6
- import { currentBoard, state } from "./state.js";
7
- import { normalizeSettingsTab } from "./settings-tabs.js";
8
- import { closeMenuFlyouts } from "./board-menu.js";
9
- import { closeCreateFlyout } from "./create-card.js";
10
- import {
11
- buildRoute,
12
- hasRoute,
13
- isCanonicalRouteUrl,
14
- parseRoute
15
- } from "./url-routes.js";
16
-
17
- export { buildRoute, hasRoute, parseRoute } from "./url-routes.js";
18
-
19
- function boardBySlugOrId(value) {
20
- if (!value) return null;
21
- const boards = state.data?.boards || [];
22
- return boards.find((b) => b.slug === value) || boards.find((b) => b.id === value) || null;
23
- }
24
-
25
- function routeBoardSlug(routeObj = {}) {
26
- if (routeObj.boardSlug) return routeObj.boardSlug;
27
- if (routeObj.boardId) return boardBySlugOrId(routeObj.boardId)?.slug || routeObj.boardId;
28
- return currentBoard()?.slug || state.boardSlug || "";
29
- }
30
-
31
- function normalizeRouteForUrl(routeObj = {}) {
32
- return {
33
- ...routeObj,
34
- boardSlug: routeBoardSlug(routeObj)
35
- };
36
- }
37
-
38
- function routeFromState() {
39
- let view = "board";
40
- if (state.detailMode === "ticket" && state.selectedTicketId) view = "ticket";
41
- else if (state.detailMode === "settings") view = "settings";
42
- return {
43
- boardSlug: currentBoard()?.slug || state.boardSlug,
44
- view,
45
- ticketId: state.selectedTicketId,
46
- tab: view === "settings" ? normalizeSettingsTab(state.settingsTab) : ""
47
- };
48
- }
49
-
50
- let routerReady = false;
51
-
52
- export function setRouterReady(value) {
53
- routerReady = value;
54
- }
55
-
56
- export function currentRoute() {
57
- return parseRoute(location);
58
- }
59
-
60
- export async function navigate(routeObj, { replace = false } = {}) {
61
- const route = normalizeRouteForUrl(routeObj);
62
- const url = buildRoute(route);
63
- if (isCanonicalRouteUrl(location, route)) {
64
- if (routerReady) await applyRoute();
65
- return;
66
- }
67
- if (replace) history.replaceState(null, "", url);
68
- else history.pushState(null, "", url);
69
- if (routerReady) await applyRoute();
70
- }
71
-
72
- // Push or replace the URL to match the current `state` without re-rendering.
73
- // Used after flows that already mutated state and called load()/render()
74
- // (e.g. ticket/board creation).
75
- export function syncUrlFromState({ replace = false } = {}) {
76
- const route = routeFromState();
77
- const url = buildRoute(route);
78
- if (isCanonicalRouteUrl(location, route)) return;
79
- if (replace) history.replaceState(null, "", url);
80
- else history.pushState(null, "", url);
81
- }
82
-
83
- export async function applyRoute() {
84
- const { load, renderDetailOnly } = await import("./app.js");
85
- const r = currentRoute();
86
- const urlHadRoute = hasRoute(location);
87
- const prevBoardId = state.boardId;
88
- const routeBoard = boardBySlugOrId(r.boardSlug);
89
- const fallbackBoard = routeBoard || (r.boardSlug ? currentBoard() : null);
90
-
91
- if (fallbackBoard) {
92
- state.boardId = fallbackBoard.id;
93
- state.boardSlug = fallbackBoard.slug;
94
- } else if (r.boardSlug) {
95
- state.boardSlug = r.boardSlug;
96
- }
97
-
98
- const canonicalRoute = fallbackBoard ? { ...r, boardSlug: fallbackBoard.slug } : r;
99
- if (urlHadRoute && !isCanonicalRouteUrl(location, canonicalRoute)) {
100
- history.replaceState(null, "", buildRoute(canonicalRoute));
101
- }
102
-
103
- if (r.view === "ticket") {
104
- state.selectedTicketId = r.ticketId || "";
105
- state.detailMode = r.ticketId ? "ticket" : "empty";
106
- } else if (r.view === "settings") {
107
- state.selectedTicketId = "";
108
- state.detailMode = "settings";
109
- if (r.tab) {
110
- state.settingsTab = r.tab;
111
- try {
112
- localStorage.setItem("mab_settings_tab", r.tab);
113
- } catch {
114
- /* ignore */
115
- }
116
- }
117
- } else {
118
- state.selectedTicketId = "";
119
- state.detailMode = "empty";
120
- }
121
-
122
- closeMenuFlyouts();
123
- closeCreateFlyout();
124
-
125
- if (state.boardId && state.boardId !== prevBoardId) {
126
- await load();
127
- return;
128
- }
129
- await renderDetailOnly();
130
- }
131
-
132
- window.addEventListener("popstate", () => {
133
- if (routerReady) void applyRoute();
134
- });
@@ -1,56 +0,0 @@
1
- // Topbar search. Debounced via the input handler in main.js; queries the
2
- // /api/search endpoint and renders a small results dropdown that navigates
3
- // to the chosen ticket on click.
4
-
5
- import { searchInput, searchResults } from "./dom.js";
6
- import { state, currentBoard } from "./state.js";
7
- import { api } from "./api.js";
8
- import { navigate } from "./router.js";
9
- import { escapeHtml, stateClassFor, ticketLabel } from "./format.js";
10
- import { closeCreateFlyout } from "./create-card.js";
11
-
12
- export async function runSearch() {
13
- const query = searchInput.value.trim();
14
- if (query.length < 2) {
15
- hideSearch();
16
- return;
17
- }
18
- const board = currentBoard();
19
- if (!board) return;
20
- const result = await api(`/api/search?q=${encodeURIComponent(query)}&board=${encodeURIComponent(board.slug)}`);
21
- if (result.results.length === 0) {
22
- searchResults.hidden = false;
23
- searchResults.innerHTML = `<div class="search-hit">No results</div>`;
24
- return;
25
- }
26
- searchResults.hidden = false;
27
- searchResults.innerHTML = result.results
28
- .map(
29
- (ticket) => `
30
- <div class="search-hit" data-ticket-id="${ticket.id}">
31
- <span class="search-hit-main">
32
- <strong>${escapeHtml(ticketLabel(ticket))}</strong>
33
- <span class="search-hit-title">${escapeHtml(ticket.title)}</span>
34
- </span>
35
- <span class="search-hit-state" data-variant="${escapeHtml(stateClassFor(ticket))}">${escapeHtml(ticket.state_name || "State")}</span>
36
- </div>
37
- `
38
- )
39
- .join("");
40
- searchResults.querySelectorAll("[data-ticket-id]").forEach((hit) => {
41
- hit.addEventListener("click", async () => {
42
- closeCreateFlyout();
43
- hideSearch();
44
- navigate({
45
- boardId: state.boardId,
46
- view: "ticket",
47
- ticketId: hit.dataset.ticketId
48
- });
49
- });
50
- });
51
- }
52
-
53
- export function hideSearch() {
54
- searchResults.hidden = true;
55
- searchResults.innerHTML = "";
56
- }
@@ -1,7 +0,0 @@
1
- /** Settings drawer tab ids — must match URL segments `#/b/…/settings/:tab` and `settings.js` tab config. */
2
- export const SETTINGS_TAB_IDS = new Set(["lanes", "appearance", "ai", "notes", "journal", "data", "archive"]);
3
-
4
- export function normalizeSettingsTab(raw) {
5
- if (!raw || !SETTINGS_TAB_IDS.has(raw)) return "lanes";
6
- return raw;
7
- }