@shivaedev/work-board 0.15.0 → 0.17.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 (303) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/README.md +4 -4
  3. package/assets/react.css +1 -1
  4. package/assets/react.js +52 -39
  5. package/dist/browser/views/remaining.d.ts +0 -240
  6. package/dist/browser/views/remaining.d.ts.map +1 -1
  7. package/dist/browser/views/remaining.js +0 -2
  8. package/dist/browser/views/remaining.js.map +1 -1
  9. package/dist/client/document/Mermaid.d.ts.map +1 -1
  10. package/dist/client/document/Mermaid.js +4 -10
  11. package/dist/client/document/Mermaid.js.map +1 -1
  12. package/dist/client/document/View.js +1 -1
  13. package/dist/client/document/View.js.map +1 -1
  14. package/dist/client/react/BoardShell.d.ts.map +1 -1
  15. package/dist/client/react/BoardShell.js +28 -23
  16. package/dist/client/react/BoardShell.js.map +1 -1
  17. package/dist/client/react/DocumentAttention.d.ts.map +1 -1
  18. package/dist/client/react/DocumentAttention.js +2 -3
  19. package/dist/client/react/DocumentAttention.js.map +1 -1
  20. package/dist/client/react/DocumentContext.d.ts.map +1 -1
  21. package/dist/client/react/DocumentContext.js +6 -4
  22. package/dist/client/react/DocumentContext.js.map +1 -1
  23. package/dist/client/react/LiveControls.d.ts.map +1 -1
  24. package/dist/client/react/LiveControls.js +1 -6
  25. package/dist/client/react/LiveControls.js.map +1 -1
  26. package/dist/client/react/PhoneNavigation.d.ts +3 -1
  27. package/dist/client/react/PhoneNavigation.d.ts.map +1 -1
  28. package/dist/client/react/PhoneNavigation.js +8 -13
  29. package/dist/client/react/PhoneNavigation.js.map +1 -1
  30. package/dist/client/react/ProjectionFrame.js +1 -1
  31. package/dist/client/react/ProjectionFrame.js.map +1 -1
  32. package/dist/client/react/ReadingLibrary.d.ts.map +1 -1
  33. package/dist/client/react/ReadingLibrary.js +2 -6
  34. package/dist/client/react/ReadingLibrary.js.map +1 -1
  35. package/dist/client/react/ReadingReadyContext.d.ts +6 -0
  36. package/dist/client/react/ReadingReadyContext.d.ts.map +1 -0
  37. package/dist/client/react/ReadingReadyContext.js +7 -0
  38. package/dist/client/react/ReadingReadyContext.js.map +1 -0
  39. package/dist/client/react/RemainingMain.d.ts.map +1 -1
  40. package/dist/client/react/RemainingMain.js +0 -3
  41. package/dist/client/react/RemainingMain.js.map +1 -1
  42. package/dist/client/react/ResultPage.d.ts.map +1 -1
  43. package/dist/client/react/ResultPage.js +2 -1
  44. package/dist/client/react/ResultPage.js.map +1 -1
  45. package/dist/client/react/SessionContext.d.ts +3 -0
  46. package/dist/client/react/SessionContext.d.ts.map +1 -0
  47. package/dist/client/react/SessionContext.js +3 -0
  48. package/dist/client/react/SessionContext.js.map +1 -0
  49. package/dist/client/react/ShellApi.d.ts +0 -1
  50. package/dist/client/react/ShellApi.d.ts.map +1 -1
  51. package/dist/client/react/SystemMain.d.ts.map +1 -1
  52. package/dist/client/react/SystemMain.js +3 -1
  53. package/dist/client/react/SystemMain.js.map +1 -1
  54. package/dist/client/react/ThemeContext.d.ts +2 -0
  55. package/dist/client/react/ThemeContext.d.ts.map +1 -0
  56. package/dist/client/react/ThemeContext.js +3 -0
  57. package/dist/client/react/ThemeContext.js.map +1 -0
  58. package/dist/client/react/TodayOptions.d.ts.map +1 -1
  59. package/dist/client/react/TodayOptions.js +2 -2
  60. package/dist/client/react/TodayOptions.js.map +1 -1
  61. package/dist/client/react/entry.js +1 -1
  62. package/dist/client/react/entry.js.map +1 -1
  63. package/dist/client/react/loadBoardPage.d.ts.map +1 -1
  64. package/dist/client/react/loadBoardPage.js +5 -13
  65. package/dist/client/react/loadBoardPage.js.map +1 -1
  66. package/dist/client/react/loadRemaining.d.ts +124 -364
  67. package/dist/client/react/loadRemaining.d.ts.map +1 -1
  68. package/dist/client/react/loadRemaining.js +0 -2
  69. package/dist/client/react/loadRemaining.js.map +1 -1
  70. package/dist/client/react/navigationLocation.d.ts +2 -0
  71. package/dist/client/react/navigationLocation.d.ts.map +1 -1
  72. package/dist/client/react/navigationLocation.js +10 -0
  73. package/dist/client/react/navigationLocation.js.map +1 -1
  74. package/dist/client/react/pageQueries.d.ts.map +1 -1
  75. package/dist/client/react/pageQueries.js +0 -3
  76. package/dist/client/react/pageQueries.js.map +1 -1
  77. package/dist/client/react/readerLink.js +1 -1
  78. package/dist/client/react/readerLink.js.map +1 -1
  79. package/dist/client/react/remainingRoute.d.ts +1 -1
  80. package/dist/client/react/remainingRoute.d.ts.map +1 -1
  81. package/dist/client/react/remainingRoute.js +0 -2
  82. package/dist/client/react/remainingRoute.js.map +1 -1
  83. package/dist/client/react/scheduleReading.d.ts.map +1 -1
  84. package/dist/client/react/scheduleReading.js +1 -10
  85. package/dist/client/react/scheduleReading.js.map +1 -1
  86. package/dist/client/react/useAppearance.d.ts +2 -1
  87. package/dist/client/react/useAppearance.d.ts.map +1 -1
  88. package/dist/client/react/useAppearance.js +1 -2
  89. package/dist/client/react/useAppearance.js.map +1 -1
  90. package/dist/client/react/useBoardNavigation.d.ts +1 -1
  91. package/dist/client/react/useBoardNavigation.d.ts.map +1 -1
  92. package/dist/client/react/useBoardNavigation.js +13 -17
  93. package/dist/client/react/useBoardNavigation.js.map +1 -1
  94. package/dist/client/react/useDiagnosticsPolling.d.ts +4 -1
  95. package/dist/client/react/useDiagnosticsPolling.d.ts.map +1 -1
  96. package/dist/client/react/useDiagnosticsPolling.js +9 -7
  97. package/dist/client/react/useDiagnosticsPolling.js.map +1 -1
  98. package/dist/client/react/useSidebar.d.ts.map +1 -1
  99. package/dist/client/react/useSidebar.js +5 -3
  100. package/dist/client/react/useSidebar.js.map +1 -1
  101. package/dist/render/{failed.d.ts → Failed.d.ts} +1 -1
  102. package/dist/render/Failed.d.ts.map +1 -0
  103. package/dist/render/{failed.js → Failed.js} +1 -1
  104. package/dist/render/Failed.js.map +1 -0
  105. package/dist/render/code.d.ts +2 -2
  106. package/dist/render/code.d.ts.map +1 -1
  107. package/dist/render/code.js +15 -13
  108. package/dist/render/code.js.map +1 -1
  109. package/dist/render/footnoteIds.d.ts +3 -0
  110. package/dist/render/footnoteIds.d.ts.map +1 -0
  111. package/dist/render/{footnotes.js → footnoteIds.js} +11 -9
  112. package/dist/render/footnoteIds.js.map +1 -0
  113. package/dist/responses/url.js +1 -1
  114. package/dist/responses/url.js.map +1 -1
  115. package/dist/rpc/PageUrl.d.ts.map +1 -1
  116. package/dist/rpc/PageUrl.js +0 -1
  117. package/dist/rpc/PageUrl.js.map +1 -1
  118. package/dist/rpc/contract.d.ts +25 -748
  119. package/dist/rpc/contract.d.ts.map +1 -1
  120. package/dist/rpc/contract.js +6 -9
  121. package/dist/rpc/contract.js.map +1 -1
  122. package/dist/rpc/handoffContract.d.ts +33 -33
  123. package/dist/server/{responses/service.d.ts → Responses.d.ts} +9 -21
  124. package/dist/server/Responses.d.ts.map +1 -0
  125. package/dist/server/{responses/service.js → Responses.js} +22 -22
  126. package/dist/server/Responses.js.map +1 -0
  127. package/dist/server/attention/inbox.d.ts +2 -0
  128. package/dist/server/attention/inbox.d.ts.map +1 -1
  129. package/dist/server/attention/inbox.js +1 -0
  130. package/dist/server/attention/inbox.js.map +1 -1
  131. package/dist/server/attention/projection.js +1 -1
  132. package/dist/server/attention/projection.js.map +1 -1
  133. package/dist/server/attention/requestInbox.d.ts +3 -0
  134. package/dist/server/attention/requestInbox.d.ts.map +1 -1
  135. package/dist/server/attention/requestInbox.js +1 -0
  136. package/dist/server/attention/requestInbox.js.map +1 -1
  137. package/dist/server/board.d.ts +1 -1
  138. package/dist/server/boardRuntime.d.ts +2 -2
  139. package/dist/server/boardRuntime.d.ts.map +1 -1
  140. package/dist/server/boardRuntime.js +12 -16
  141. package/dist/server/boardRuntime.js.map +1 -1
  142. package/dist/server/boardServices.d.ts +3 -4
  143. package/dist/server/boardServices.d.ts.map +1 -1
  144. package/dist/server/boardServices.js +5 -4
  145. package/dist/server/boardServices.js.map +1 -1
  146. package/dist/server/boardSocket.d.ts +1 -1
  147. package/dist/server/boardSocket.d.ts.map +1 -1
  148. package/dist/server/document/read.d.ts +4 -10
  149. package/dist/server/document/read.d.ts.map +1 -1
  150. package/dist/server/document/read.js +5 -5
  151. package/dist/server/document/read.js.map +1 -1
  152. package/dist/server/document/requests.d.ts.map +1 -1
  153. package/dist/server/document/requests.js +1 -2
  154. package/dist/server/document/requests.js.map +1 -1
  155. package/dist/server/handoffs/Service.d.ts +1 -2
  156. package/dist/server/handoffs/Service.d.ts.map +1 -1
  157. package/dist/server/handoffs/Service.js +14 -13
  158. package/dist/server/handoffs/Service.js.map +1 -1
  159. package/dist/server/http/assets.d.ts +0 -3
  160. package/dist/server/http/assets.d.ts.map +1 -1
  161. package/dist/server/http/assets.js +1 -7
  162. package/dist/server/http/assets.js.map +1 -1
  163. package/dist/server/http/boardRoutes.d.ts.map +1 -1
  164. package/dist/server/http/boardRoutes.js +3 -3
  165. package/dist/server/http/boardRoutes.js.map +1 -1
  166. package/dist/server/integration/responses.d.ts +207 -4
  167. package/dist/server/integration/responses.d.ts.map +1 -1
  168. package/dist/server/integration/responses.js +4 -2
  169. package/dist/server/integration/responses.js.map +1 -1
  170. package/dist/server/mcp/client.d.ts +1060 -1300
  171. package/dist/server/mcp/client.d.ts.map +1 -1
  172. package/dist/server/mcp/queries.d.ts +24 -744
  173. package/dist/server/mcp/queries.d.ts.map +1 -1
  174. package/dist/server/mcp/queries.js +3 -3
  175. package/dist/server/mcp/queries.js.map +1 -1
  176. package/dist/server/packageInfo.d.ts +1 -1
  177. package/dist/server/packageInfo.js +1 -1
  178. package/dist/server/render/Highlighter.d.ts +1 -1
  179. package/dist/server/render/Highlighter.js +1 -1
  180. package/dist/server/render/markdown.d.ts +1 -1
  181. package/dist/server/render/markdown.js +2 -2
  182. package/dist/server/render/markdown.js.map +1 -1
  183. package/dist/server/responses/readingActions.d.ts +10 -1
  184. package/dist/server/responses/readingActions.d.ts.map +1 -1
  185. package/dist/server/responses/readingActions.js +2 -4
  186. package/dist/server/responses/readingActions.js.map +1 -1
  187. package/dist/server/responses/registerQuestion.d.ts +2 -2
  188. package/dist/server/responses/registerQuestion.d.ts.map +1 -1
  189. package/dist/server/responses/registerQuestion.js +3 -3
  190. package/dist/server/responses/registerQuestion.js.map +1 -1
  191. package/dist/server/responses/retry.d.ts +2 -2
  192. package/dist/server/responses/retry.d.ts.map +1 -1
  193. package/dist/server/responses/retry.js +1 -1
  194. package/dist/server/responses/retry.js.map +1 -1
  195. package/dist/server/rpc/HandlerOptions.d.ts +0 -8
  196. package/dist/server/rpc/HandlerOptions.d.ts.map +1 -1
  197. package/dist/server/rpc/handlers.d.ts +1 -1
  198. package/dist/server/rpc/handlers.d.ts.map +1 -1
  199. package/dist/server/rpc/handlers.js +14 -13
  200. package/dist/server/rpc/handlers.js.map +1 -1
  201. package/dist/server/rpc/hints.d.ts +3 -5
  202. package/dist/server/rpc/hints.d.ts.map +1 -1
  203. package/dist/server/rpc/hints.js +5 -1
  204. package/dist/server/rpc/hints.js.map +1 -1
  205. package/dist/server/serve.d.ts +1 -1
  206. package/dist/server/views/fleetItems.d.ts +2 -2
  207. package/dist/server/views/fleetItems.d.ts.map +1 -1
  208. package/dist/server/views/fleetItems.js +8 -3
  209. package/dist/server/views/fleetItems.js.map +1 -1
  210. package/dist/server/views/projectionQueries.d.ts +5 -9
  211. package/dist/server/views/projectionQueries.d.ts.map +1 -1
  212. package/dist/server/views/projectionQueries.js +6 -6
  213. package/dist/server/views/projectionQueries.js.map +1 -1
  214. package/dist/server/views/remainingQueries.d.ts +4 -252
  215. package/dist/server/views/remainingQueries.d.ts.map +1 -1
  216. package/dist/server/views/remainingQueries.js +11 -19
  217. package/dist/server/views/remainingQueries.js.map +1 -1
  218. package/dist/server/workspace.d.ts +222 -0
  219. package/dist/server/workspace.d.ts.map +1 -0
  220. package/dist/server/workspace.js +25 -0
  221. package/dist/server/workspace.js.map +1 -0
  222. package/package.json +6 -37
  223. package/src/browser/views/remaining.ts +0 -3
  224. package/src/client/document/Mermaid.ts +4 -10
  225. package/src/client/document/View.ts +1 -1
  226. package/src/client/react/BoardShell.tsx +37 -24
  227. package/src/client/react/DocumentAttention.tsx +2 -3
  228. package/src/client/react/DocumentContext.tsx +6 -4
  229. package/src/client/react/LiveControls.tsx +1 -14
  230. package/src/client/react/PhoneNavigation.tsx +20 -15
  231. package/src/client/react/ProjectionFrame.tsx +1 -1
  232. package/src/client/react/ReadingLibrary.tsx +2 -6
  233. package/src/client/react/ReadingReadyContext.ts +11 -0
  234. package/src/client/react/RemainingMain.tsx +0 -10
  235. package/src/client/react/ResultPage.tsx +2 -2
  236. package/src/client/react/SessionContext.ts +4 -0
  237. package/src/client/react/ShellApi.ts +0 -1
  238. package/src/client/react/SystemMain.tsx +3 -1
  239. package/src/client/react/ThemeContext.ts +3 -0
  240. package/src/client/react/TodayOptions.tsx +2 -2
  241. package/src/client/react/entry.tsx +1 -1
  242. package/src/client/react/loadBoardPage.ts +5 -14
  243. package/src/client/react/loadRemaining.ts +0 -2
  244. package/src/client/react/navigationLocation.ts +12 -0
  245. package/src/client/react/pageQueries.ts +0 -3
  246. package/src/client/react/readerLink.ts +1 -1
  247. package/src/client/react/remainingRoute.ts +0 -2
  248. package/src/client/react/scheduleReading.ts +1 -10
  249. package/src/client/react/useAppearance.ts +2 -3
  250. package/src/client/react/useBoardNavigation.ts +13 -18
  251. package/src/client/react/useDiagnosticsPolling.ts +14 -7
  252. package/src/client/react/useSidebar.ts +5 -3
  253. package/src/render/code.ts +3 -4
  254. package/src/render/{footnotes.ts → footnoteIds.ts} +12 -10
  255. package/src/responses/url.ts +1 -1
  256. package/src/rpc/PageUrl.ts +0 -1
  257. package/src/rpc/contract.ts +6 -9
  258. package/src/server/{responses/service.ts → Responses.ts} +21 -29
  259. package/src/server/attention/inbox.ts +1 -0
  260. package/src/server/attention/projection.ts +1 -1
  261. package/src/server/attention/requestInbox.ts +1 -0
  262. package/src/server/board.ts +1 -1
  263. package/src/server/boardRuntime.ts +20 -25
  264. package/src/server/boardServices.ts +7 -7
  265. package/src/server/document/read.ts +6 -14
  266. package/src/server/document/requests.ts +1 -2
  267. package/src/server/handoffs/Service.ts +16 -19
  268. package/src/server/http/assets.ts +1 -7
  269. package/src/server/http/boardRoutes.ts +3 -3
  270. package/src/server/integration/responses.ts +5 -3
  271. package/src/server/mcp/queries.ts +3 -3
  272. package/src/server/packageInfo.ts +1 -1
  273. package/src/server/render/Highlighter.ts +1 -1
  274. package/src/server/render/markdown.ts +2 -2
  275. package/src/server/responses/readingActions.ts +3 -3
  276. package/src/server/responses/registerQuestion.ts +5 -5
  277. package/src/server/responses/retry.ts +3 -3
  278. package/src/server/rpc/HandlerOptions.ts +0 -8
  279. package/src/server/rpc/handlers.ts +17 -15
  280. package/src/server/rpc/hints.ts +6 -3
  281. package/src/server/views/fleetItems.ts +8 -4
  282. package/src/server/views/projectionQueries.ts +6 -7
  283. package/src/server/views/remainingQueries.ts +11 -31
  284. package/src/server/workspace.ts +41 -0
  285. package/assets/native.js +0 -37
  286. package/dist/client/entry.d.ts +0 -3
  287. package/dist/client/entry.d.ts.map +0 -1
  288. package/dist/client/entry.js +0 -3
  289. package/dist/client/entry.js.map +0 -1
  290. package/dist/client/react/RespondPage.d.ts +0 -5
  291. package/dist/client/react/RespondPage.d.ts.map +0 -1
  292. package/dist/client/react/RespondPage.js +0 -5
  293. package/dist/client/react/RespondPage.js.map +0 -1
  294. package/dist/render/failed.d.ts.map +0 -1
  295. package/dist/render/failed.js.map +0 -1
  296. package/dist/render/footnotes.d.ts +0 -3
  297. package/dist/render/footnotes.d.ts.map +0 -1
  298. package/dist/render/footnotes.js.map +0 -1
  299. package/dist/server/responses/service.d.ts.map +0 -1
  300. package/dist/server/responses/service.js.map +0 -1
  301. package/src/client/entry.ts +0 -3
  302. package/src/client/react/RespondPage.tsx +0 -8
  303. /package/src/render/{failed.ts → Failed.ts} +0 -0
@@ -1,5 +1,6 @@
1
+ import { useRouter } from "@tanstack/react-router";
1
2
  import { CalendarDays, Ellipsis, Flag, Search, Zap } from "lucide-react";
2
- import { useEffect, useState } from "react";
3
+ import { useEffect } from "react";
3
4
  import { Button } from "#client/react/components/ui/Button.tsx";
4
5
  import { Modal } from "./Modal.tsx";
5
6
  import type { MainLocation } from "./mainLocation.ts";
@@ -11,21 +12,25 @@ const icons = [CalendarDays, Flag, Zap];
11
12
  const TAB_CLASS =
12
13
  "flex min-h-12 min-w-0 flex-col items-center justify-center gap-1 rounded-md border-0 bg-transparent p-0 text-foreground text-xs no-underline aria-[current=page]:bg-accent aria-[current=page]:text-primary";
13
14
 
14
- export function PhoneNavigation({ main, openSearch }: { readonly main: MainLocation; readonly openSearch: () => void }) {
15
- const [more, setMore] = useState(false);
15
+ export function PhoneNavigation({
16
+ main,
17
+ more,
18
+ onMoreChange,
19
+ openSearch,
20
+ }: {
21
+ readonly main: MainLocation;
22
+ readonly more: boolean;
23
+ readonly onMoreChange: (open: boolean) => void;
24
+ readonly openSearch: () => void;
25
+ }) {
26
+ const router = useRouter();
16
27
  const narrow = useMedia("(max-width: 767px)");
17
28
  useEffect(() => {
18
29
  if (!narrow) {
19
- setMore(false);
30
+ onMoreChange(false);
20
31
  }
21
- }, [narrow]);
22
- useEffect(() => {
23
- function close() {
24
- setMore(false);
25
- }
26
- document.addEventListener("board-navigate", close);
27
- return () => document.removeEventListener("board-navigate", close);
28
- }, []);
32
+ }, [narrow, onMoreChange]);
33
+ useEffect(() => router.subscribe("onBeforeNavigate", () => onMoreChange(false)), [router, onMoreChange]);
29
34
  return (
30
35
  <>
31
36
  <nav
@@ -50,19 +55,19 @@ export function PhoneNavigation({ main, openSearch }: { readonly main: MainLocat
50
55
  aria-expanded={more}
51
56
  aria-haspopup="dialog"
52
57
  className={TAB_CLASS}
53
- onClick={() => setMore(true)}
58
+ onClick={() => onMoreChange(true)}
54
59
  type="button"
55
60
  >
56
61
  <Ellipsis aria-hidden="true" className="size-5" />
57
62
  More
58
63
  </button>
59
64
  </nav>
60
- <Modal className="phone-more" close={() => setMore(false)} id={shellIds.phoneMore} open={more} title={shellIds.phoneMoreTitle}>
65
+ <Modal className="phone-more" close={() => onMoreChange(false)} id={shellIds.phoneMore} open={more} title={shellIds.phoneMoreTitle}>
61
66
  <div className="mb-3 flex items-center justify-between">
62
67
  <h2 className="font-semibold" id={shellIds.phoneMoreTitle}>
63
68
  More
64
69
  </h2>
65
- <Button onClick={() => setMore(false)} variant="ghost">
70
+ <Button onClick={() => onMoreChange(false)} variant="ghost">
66
71
  Close
67
72
  </Button>
68
73
  </div>
@@ -130,7 +130,7 @@ function projectionView(route: ProjectionRoute | RemainingRoute) {
130
130
  if (route === "board") {
131
131
  return "";
132
132
  }
133
- return route === "respond" ? "response" : route;
133
+ return route;
134
134
  }
135
135
 
136
136
  function failureStatus(missing: boolean, conflict: boolean) {
@@ -1,4 +1,4 @@
1
- import { type ReactNode, useCallback, useEffect, useRef, useState } from "react";
1
+ import { type ReactNode, useCallback, useLayoutEffect, useRef, useState } from "react";
2
2
  import { LibraryContext, restoreLibrary } from "#client/react/LibraryContext.ts";
3
3
  import { useMainLocation } from "./MainLocationContext.ts";
4
4
  import { Modal } from "./Modal.tsx";
@@ -36,7 +36,7 @@ export function ReadingLibrary({
36
36
  },
37
37
  [key],
38
38
  );
39
- useEffect(() => {
39
+ useLayoutEffect(() => {
40
40
  function sync() {
41
41
  if (!page.route) {
42
42
  return;
@@ -55,10 +55,6 @@ export function ReadingLibrary({
55
55
  }
56
56
  }
57
57
  sync();
58
- document.addEventListener("board-index-change", sync);
59
- return () => {
60
- document.removeEventListener("board-index-change", sync);
61
- };
62
58
  }, [save, page]);
63
59
 
64
60
  return (
@@ -0,0 +1,11 @@
1
+ import { createContext } from "react";
2
+
3
+ export const ReadingReadyContext = createContext<{
4
+ readonly element: HTMLElement | null;
5
+ readonly report: (element: HTMLElement, ready: boolean) => void;
6
+ }>({ element: null, report: () => undefined });
7
+
8
+ export function readingReady(doc: HTMLElement, element: HTMLElement | null) {
9
+ const context = doc.querySelector(".item-context");
10
+ return !context || context === element;
11
+ }
@@ -4,7 +4,6 @@ import { HandoffPage } from "./HandoffPage.tsx";
4
4
  import { LibraryMain } from "./LibraryMain.tsx";
5
5
  import type { MainLocation } from "./mainLocation.ts";
6
6
  import { ProjectionFrame } from "./ProjectionFrame.tsx";
7
- import { RespondPage } from "./RespondPage.tsx";
8
7
  import { ResultPage } from "./ResultPage.tsx";
9
8
  import type { RemainingRoute } from "./remainingRoute.ts";
10
9
  import type { ShellApi } from "./ShellApi.ts";
@@ -45,15 +44,6 @@ export function RemainingMain({
45
44
  );
46
45
  case "system":
47
46
  return <SystemMain api={api} onPage={onPage} url={url} />;
48
- case "respond":
49
- return (
50
- <ProjectionFrame
51
- {...options}
52
- atom={api.respond.query({ url }, routeQueryOptions)}
53
- location={() => ({ file: "Respond", status: 200, view: "response" })}
54
- render={(data) => <RespondPage data={data} />}
55
- />
56
- );
57
47
  case "handoff":
58
48
  return (
59
49
  <ProjectionFrame
@@ -1,5 +1,6 @@
1
1
  import type { ResultProjection } from "#browser/views/ResultProjection.ts";
2
2
  import { fileUrl } from "#files/url.ts";
3
+ import { responseUrl } from "#responses/url.ts";
3
4
  import { DocumentMetadata } from "./DocumentMetadata.tsx";
4
5
  import { ReadingPanel } from "./ReadingPanel.tsx";
5
6
  import { ResponseMarkdown } from "./ResponseMarkdown.tsx";
@@ -14,8 +15,7 @@ export function ResultPage({ data }: { readonly data: ResultProjection }) {
14
15
  );
15
16
  const links = actions.map((entry) => (
16
17
  <li key={entry.id}>
17
- <a href={`/_board/respond?item=${encodeURIComponent(document.identity ?? "")}&request=${encodeURIComponent(entry.id)}`}>Review {entry.id}</a> —{" "}
18
- {entry.reason}
18
+ <a href={responseUrl(document.identity ?? "", entry.id)}>Review {entry.id}</a> — {entry.reason}
19
19
  </li>
20
20
  ));
21
21
  return (
@@ -0,0 +1,4 @@
1
+ import { createContext } from "react";
2
+ import type { BrowserClient } from "#client/client.ts";
3
+
4
+ export const SessionContext = createContext<BrowserClient | undefined>(undefined);
@@ -9,7 +9,6 @@ export interface ShellApi {
9
9
  readonly inbox: Pick<BrowserClient["api"]["inbox"], "query">;
10
10
  readonly library: Pick<BrowserClient["api"]["library"], "query">;
11
11
  readonly navigation: Pick<BrowserClient["api"]["navigation"], "query">;
12
- readonly respond: Pick<BrowserClient["api"]["respond"], "query">;
13
12
  readonly result: Pick<BrowserClient["api"]["result"], "query">;
14
13
  readonly search: Pick<BrowserClient["api"]["search"], "query">;
15
14
  readonly start: Pick<BrowserClient["api"]["start"], "query">;
@@ -1,6 +1,8 @@
1
+ import { useContext } from "react";
1
2
  import { routeQueryOptions } from "#client/page/routeQuery.ts";
2
3
  import type { MainLocation } from "./mainLocation.ts";
3
4
  import { ProjectionFrame } from "./ProjectionFrame.tsx";
5
+ import { SessionContext } from "./SessionContext.ts";
4
6
  import type { ShellApi } from "./ShellApi.ts";
5
7
  import { SystemPage } from "./SystemPage.tsx";
6
8
  import { useDiagnosticsPolling } from "./useDiagnosticsPolling.ts";
@@ -15,7 +17,7 @@ export function SystemMain({
15
17
  readonly url: string;
16
18
  }) {
17
19
  const atom = api.diagnostics.query(undefined, routeQueryOptions);
18
- useDiagnosticsPolling(atom, api.fleetItems.query(undefined, routeQueryOptions));
20
+ useDiagnosticsPolling(useContext(SessionContext), atom, api.fleetItems.query(undefined, routeQueryOptions));
19
21
  return (
20
22
  <ProjectionFrame
21
23
  atom={atom}
@@ -0,0 +1,3 @@
1
+ import { createContext } from "react";
2
+
3
+ export const ThemeContext = createContext("light");
@@ -12,6 +12,7 @@ import { Popover } from "#client/react/components/ui/Popover.tsx";
12
12
  import { authorLabel } from "#client/responses/authorLabel.ts";
13
13
  import { saveFailure } from "#client/saveFailure.ts";
14
14
  import { fileUrl } from "#files/url.ts";
15
+ import { responseUrl } from "#responses/url.ts";
15
16
  import { createResponse } from "./createResponse.ts";
16
17
  import { useFormClient } from "./FormContext.ts";
17
18
  import type { ShellApi } from "./ShellApi.ts";
@@ -19,8 +20,7 @@ import type { ShellApi } from "./ShellApi.ts";
19
20
  export function TodayOptions({ api, item }: { readonly api: ShellApi; readonly item: InboxProjection["you"][number] }) {
20
21
  const query = useQuery(documentQuery(api, fileUrl(item.file)), { keepPreviousData: true });
21
22
  const data = Option.getOrUndefined(query.data);
22
- const requestId = new URL(item.href, "http://127.0.0.1").searchParams.get("request");
23
- const request = data?.requests.find((entry) => entry.id === requestId && entry.open);
23
+ const request = data?.requests.find((entry) => entry.open && responseUrl(data.metadata.id ?? "", entry.id) === item.href);
24
24
  return data
25
25
  && !item.problem
26
26
  && request?.preview
@@ -1,4 +1,4 @@
1
- import { session } from "#client/entry.ts";
1
+ import { session } from "#client/session.ts";
2
2
  import { mountBoard } from "./mountBoard.tsx";
3
3
  import "#client/react/entry.css";
4
4
 
@@ -17,7 +17,7 @@ export async function loadBoardPage({
17
17
  location,
18
18
  abortController,
19
19
  }: Pick<LoaderFnContext, "location" | "abortController"> & { readonly context: { readonly shell?: RouterShell } }) {
20
- redirectRetired(location.pathname);
20
+ redirectLegacy(location.pathname, location.searchStr);
21
21
  if (!shell) {
22
22
  return undefined;
23
23
  }
@@ -25,7 +25,6 @@ export async function loadBoardPage({
25
25
  const url = location.pathname + location.searchStr;
26
26
  try {
27
27
  const navigation = await loadQuery(registry, navigationQuery(api), { abortController });
28
- await redirectResponse(shell, url, location.pathname, abortController);
29
28
  const projection = projectionRoute(location.pathname, navigation.home);
30
29
  if (projection) {
31
30
  await loadProjection(registry, api, projection, url, abortController);
@@ -55,22 +54,14 @@ export async function loadBoardPage({
55
54
  }
56
55
  }
57
56
 
58
- async function redirectResponse({ api, registry }: RouterShell, url: string, pathname: string, abortController: AbortController) {
59
- if (pathname !== "/_board/respond") {
60
- return;
61
- }
62
- const response = await loadRemaining(registry, api, "respond", url, abortController);
63
- if (response && "request" in response) {
64
- const item = response.document.identity ?? response.request.preview?.item ?? "";
65
- throw redirect({ href: `/_board/item/${encodeURIComponent(item)}/#answer-card-${encodeURIComponent(response.request.id)}`, replace: true });
66
- }
67
- }
68
-
69
57
  function mustRethrow(controller: AbortController, error: unknown) {
70
58
  return controller.signal.aborted || isRedirect(error);
71
59
  }
72
60
 
73
- function redirectRetired(pathname: string) {
61
+ function redirectLegacy(pathname: string, search: string) {
62
+ if (pathname === "/_board/respond") {
63
+ throw redirect({ href: pathname + search, reloadDocument: true });
64
+ }
74
65
  const retired: Readonly<Record<string, string>> = {
75
66
  "/_board/changes": "/_board/library?view=recently-changed",
76
67
  "/_board/diagnostics": "/_board/system",
@@ -22,8 +22,6 @@ export function loadRemaining(
22
22
  loadQuery(registry, api.diagnostics.query(undefined, routeQueryOptions), { abortController }),
23
23
  loadQuery(registry, api.fleetItems.query(undefined, routeQueryOptions), { abortController }),
24
24
  ]);
25
- case "respond":
26
- return loadQuery(registry, api.respond.query({ url }, routeQueryOptions), { abortController });
27
25
  case "handoff":
28
26
  return loadQuery(registry, api.handoff.query({ url }, routeQueryOptions), { abortController });
29
27
  case "result":
@@ -1,3 +1,4 @@
1
+ import type { AnyRouter } from "@tanstack/react-router";
1
2
  import { readingEntry } from "#client/react/storedReadings.ts";
2
3
 
3
4
  export function navigationFailure(status: number) {
@@ -25,3 +26,14 @@ export function sameReadingLocation(
25
26
  ) {
26
27
  return previous.route === next.route && previous.id === next.id && previous.hash === next.hash;
27
28
  }
29
+
30
+ export function recordEntry(router: AnyRouter, route: string, id: string, native: boolean) {
31
+ if (!native) {
32
+ return;
33
+ }
34
+ router.history.flush?.();
35
+ if (window.location.pathname + window.location.search !== route || window.history.state?.workBoard?.id === id) {
36
+ return;
37
+ }
38
+ window.history.replaceState({ ...window.history.state, workBoard: { id } }, "");
39
+ }
@@ -29,9 +29,6 @@ export function pageQueries(api: ShellApi, kind: string, url: string): readonly
29
29
  if (kind === "board") {
30
30
  return [api.board.query({ url }, routeQueryOptions)];
31
31
  }
32
- if (kind === "respond") {
33
- return [api.respond.query({ url }, routeQueryOptions)];
34
- }
35
32
  if (kind === "handoff") {
36
33
  return [api.handoff.query({ url }, routeQueryOptions)];
37
34
  }
@@ -2,7 +2,7 @@ export function readerLink(target: URL) {
2
2
  return (
3
3
  target.origin === location.origin
4
4
  && (target.pathname === "/"
5
- || /^\/_board\/(?:library|goals|system|diagnostics|handoff|result|respond|start|changes|inbox|overview|work)$/u.test(target.pathname)
5
+ || /^\/_board\/(?:library|goals|system|diagnostics|handoff|result|start|changes|inbox|overview|work)$/u.test(target.pathname)
6
6
  || target.pathname.startsWith("/_board/item/")
7
7
  || /\.md$/iu.test(target.pathname))
8
8
  );
@@ -8,8 +8,6 @@ export function remainingRoute(pathname: string) {
8
8
  return "system";
9
9
  case "/_board/start":
10
10
  return "start";
11
- case "/_board/respond":
12
- return "respond";
13
11
  case "/_board/handoff":
14
12
  return "handoff";
15
13
  case "/_board/result":
@@ -9,18 +9,10 @@ export function scheduleReading(
9
9
  setStatus: (status: string) => void,
10
10
  focus: boolean,
11
11
  ) {
12
- let restored = false;
13
12
  function restore() {
14
- if (restored || !active()) {
15
- document.removeEventListener("board-reading-ready", restore);
13
+ if (!active()) {
16
14
  return;
17
15
  }
18
- const context = doc.querySelector<HTMLElement>(".item-context");
19
- if (context && context.dataset.readingReady !== "true") {
20
- return;
21
- }
22
- restored = true;
23
- document.removeEventListener("board-reading-ready", restore);
24
16
  if (focus && !document.activeElement?.closest("[data-response-form], #response-form, #handoff-form")) {
25
17
  doc.focus({ preventScroll: true });
26
18
  }
@@ -41,6 +33,5 @@ export function scheduleReading(
41
33
  }
42
34
  });
43
35
  }
44
- document.addEventListener("board-reading-ready", restore);
45
36
  requestAnimationFrame(restore);
46
37
  }
@@ -37,7 +37,6 @@ export function useAppearance() {
37
37
  if (doc) {
38
38
  doc.dataset.scheme = scheme;
39
39
  }
40
- document.dispatchEvent(new Event("board-theme"));
41
40
  }, [value.theme, value.density, scheme]);
42
41
  function change(next: Partial<Pick<typeof value, "closed" | "density" | "theme">>) {
43
42
  const appearance = { closed: valueRef.current.closed, density: valueRef.current.density, theme: valueRef.current.theme, ...next };
@@ -50,6 +49,6 @@ export function useAppearance() {
50
49
  valueRef.current = { ...appearance, notice };
51
50
  setValue(valueRef.current);
52
51
  }
53
- return { ...value, change };
52
+ return { ...value, change, scheme };
54
53
  }
55
- export type AppearanceControls = ReturnType<typeof useAppearance>;
54
+ export type AppearanceControls = Omit<ReturnType<typeof useAppearance>, "scheme">;
@@ -1,23 +1,27 @@
1
1
  import { useRouter } from "@tanstack/react-router";
2
- import { useEffect, useRef, useState } from "react";
2
+ import { useContext, useEffect, useRef, useState } from "react";
3
3
  import type { RouterShell } from "#client/react/loadBoardPage.ts";
4
4
  import { useMainLocation } from "#client/react/MainLocationContext.ts";
5
- import { currentEntry, navigationFailure, readingKey, sameReadingLocation } from "#client/react/navigationLocation.ts";
5
+ import { currentEntry, navigationFailure, readingKey, recordEntry, sameReadingLocation } from "#client/react/navigationLocation.ts";
6
+ import { ReadingReadyContext, readingReady } from "#client/react/ReadingReadyContext.ts";
6
7
  import { readerLink } from "#client/react/readerLink.ts";
7
8
  import { captureReading } from "#client/react/readingState.ts";
8
9
  import { retryPage } from "#client/react/retryPage.ts";
9
10
  import { scheduleReading } from "#client/react/scheduleReading.ts";
10
11
  import { readingEntry, storedReadings } from "#client/react/storedReadings.ts";
11
12
 
12
- export function useBoardNavigation(shell: RouterShell) {
13
+ export function useBoardNavigation(shell: RouterShell, onCurrentDestination?: () => void) {
13
14
  const router = useRouter();
14
15
  const main = useMainLocation();
16
+ const { element } = useContext(ReadingReadyContext);
17
+ const readyRef = useRef(element);
15
18
  const mainRef = useRef(main);
16
19
  const pageRef = useRef<(() => void) | undefined>(undefined);
17
20
  useEffect(() => {
18
21
  mainRef.current = main;
22
+ readyRef.current = element;
19
23
  pageRef.current?.();
20
- }, [main]);
24
+ }, [main, element]);
21
25
  const [status, setStatus] = useState("");
22
26
  useEffect(() => {
23
27
  const readings = storedReadings();
@@ -42,7 +46,7 @@ export function useBoardNavigation(shell: RouterShell) {
42
46
  const location = router.state.resolvedLocation ?? router.state.location;
43
47
  const nextRoute = location.pathname + location.searchStr;
44
48
  const doc = document.getElementById("doc");
45
- if (!doc || mainRef.current.route !== nextRoute) {
49
+ if (!doc || mainRef.current.route !== nextRoute || !readingReady(doc, readyRef.current)) {
46
50
  return;
47
51
  }
48
52
  const previousFailure = failure;
@@ -69,8 +73,10 @@ export function useBoardNavigation(shell: RouterShell) {
69
73
  }
70
74
  async function open(target: URL) {
71
75
  save();
72
- document.dispatchEvent(new Event("board-navigate"));
73
76
  const url = target.pathname + target.search + target.hash;
77
+ if (url === router.state.location.href) {
78
+ onCurrentDestination?.();
79
+ }
74
80
  if (
75
81
  url === router.state.location.href
76
82
  && mainRef.current.route === target.pathname + target.search
@@ -130,17 +136,6 @@ export function useBoardNavigation(shell: RouterShell) {
130
136
  pageRef.current = undefined;
131
137
  window.removeEventListener("pagehide", save);
132
138
  };
133
- }, [router, shell.api, shell.registry, shell.reading, shell.client]);
139
+ }, [router, shell.api, shell.registry, shell.reading, shell.client, onCurrentDestination]);
134
140
  return status;
135
141
  }
136
-
137
- function recordEntry(router: ReturnType<typeof useRouter>, route: string, id: string, native: boolean) {
138
- if (!native) {
139
- return;
140
- }
141
- router.history.flush?.();
142
- if (window.location.pathname + window.location.search !== route || window.history.state?.workBoard?.id === id) {
143
- return;
144
- }
145
- window.history.replaceState({ ...window.history.state, workBoard: { id } }, "");
146
- }
@@ -1,14 +1,17 @@
1
1
  import { RegistryContext } from "@effect/atom-react";
2
2
  import type * as Atom from "effect/reactivity/Atom";
3
3
  import { useContext, useEffect } from "react";
4
- import { session } from "#client/entry.ts";
4
+ import type { BrowserClient } from "#client/client.ts";
5
5
 
6
- export function useDiagnosticsPolling<A, TFleet>(atom: Atom.Atom<A>, fleet?: Atom.Atom<TFleet>) {
6
+ export function useDiagnosticsPolling<A, TFleet>(
7
+ client: (Pick<BrowserClient, "registry"> & { readonly updates: Pick<BrowserClient["updates"], "paused"> }) | undefined,
8
+ atom: Atom.Atom<A>,
9
+ fleet?: Atom.Atom<TFleet>,
10
+ ) {
7
11
  const registry = useContext(RegistryContext);
8
12
  useEffect(() => {
9
13
  function refresh() {
10
- const native = session(window);
11
- if (!(document.hidden || native.registry.get(native.updates.paused))) {
14
+ if (!(document.hidden || client?.registry.get(client.updates.paused))) {
12
15
  registry.refresh(atom);
13
16
  if (fleet) {
14
17
  registry.refresh(fleet);
@@ -16,12 +19,16 @@ export function useDiagnosticsPolling<A, TFleet>(atom: Atom.Atom<A>, fleet?: Ato
16
19
  }
17
20
  }
18
21
  const timer = setInterval(refresh, 15_000);
19
- document.addEventListener("board-updates-resumed", refresh);
22
+ const resumed = client?.registry.subscribe(client.updates.paused, (paused) => {
23
+ if (!paused) {
24
+ refresh();
25
+ }
26
+ });
20
27
  document.addEventListener("visibilitychange", refresh);
21
28
  return () => {
22
29
  clearInterval(timer);
23
- document.removeEventListener("board-updates-resumed", refresh);
30
+ resumed?.();
24
31
  document.removeEventListener("visibilitychange", refresh);
25
32
  };
26
- }, [atom, fleet, registry]);
33
+ }, [atom, fleet, registry, client]);
27
34
  }
@@ -1,8 +1,10 @@
1
+ import { useRouter } from "@tanstack/react-router";
1
2
  import { useCallback, useEffect, useLayoutEffect, useRef, useState } from "react";
2
3
  import type { AppearanceControls } from "./useAppearance.ts";
3
4
  import { useMedia } from "./useMedia.ts";
4
5
 
5
6
  export function useSidebar(appearance: AppearanceControls) {
7
+ const router = useRouter();
6
8
  const narrow = useMedia("(max-width: 767px)");
7
9
  const [drawer, setDrawer] = useState(false);
8
10
  const open = narrow ? drawer : !appearance.closed;
@@ -55,12 +57,12 @@ export function useSidebar(appearance: AppearanceControls) {
55
57
  trapTab(event);
56
58
  }
57
59
  document.addEventListener("keydown", key);
58
- document.addEventListener("board-navigate", close);
60
+ const unsubscribe = router.subscribe("onBeforeNavigate", close);
59
61
  return () => {
60
62
  document.removeEventListener("keydown", key);
61
- document.removeEventListener("board-navigate", close);
63
+ unsubscribe();
62
64
  };
63
- }, [narrow, open, close]);
65
+ }, [narrow, open, close, router]);
64
66
  return { close, narrow, open, toggle };
65
67
  }
66
68
  export type SidebarControls = ReturnType<typeof useSidebar>;
@@ -50,10 +50,8 @@ async function renderedCode(highlighter: Shiki, pre: Element, diagrams: boolean)
50
50
  return language === undefined ? undefined : await highlighted(highlighter, source, language);
51
51
  }
52
52
 
53
- export const codeBlocks =
54
- (highlighter: Shiki, { diagrams = true }: { readonly diagrams?: boolean } = {}) =>
55
- () =>
56
- async (tree: Root) => {
53
+ export function codeBlocks(highlighter: Shiki, { diagrams = true }: { readonly diagrams?: boolean } = {}) {
54
+ return () => async (tree: Root) => {
57
55
  const work: Promise<void>[] = [];
58
56
  visitElements(tree, "element", (pre, index, parent) => {
59
57
  if (pre.tagName !== "pre" || index === undefined || parent === undefined) {
@@ -69,3 +67,4 @@ export const codeBlocks =
69
67
  });
70
68
  await Promise.all(work);
71
69
  };
70
+ }
@@ -17,13 +17,15 @@ function scoped(prefix: string, value: Value): Value {
17
17
  return Array.isArray(value) ? value.map((each) => (typeof each === "string" ? String(scoped(prefix, each)) : each)) : value;
18
18
  }
19
19
 
20
- export const footnoteIds = (prefix: string) => () => (tree: Root) => {
21
- visitElements(tree, "element", (element) => {
22
- if (!["a", "h2", "li"].includes(element.tagName)) {
23
- return;
24
- }
25
- element.properties = Object.fromEntries(
26
- Object.entries(element.properties).map(([name, value]) => [name, SCOPED.has(name) ? scoped(prefix, value) : value]),
27
- );
28
- });
29
- };
20
+ export function footnoteIds(prefix: string) {
21
+ return () => (tree: Root) => {
22
+ visitElements(tree, "element", (element) => {
23
+ if (!["a", "h2", "li"].includes(element.tagName)) {
24
+ return;
25
+ }
26
+ element.properties = Object.fromEntries(
27
+ Object.entries(element.properties).map(([name, value]) => [name, SCOPED.has(name) ? scoped(prefix, value) : value]),
28
+ );
29
+ });
30
+ };
31
+ }
@@ -1,3 +1,3 @@
1
1
  export function responseUrl(item: string, request: string): string {
2
- return `/_board/respond?item=${encodeURIComponent(item)}&request=${encodeURIComponent(request)}`;
2
+ return `/_board/item/${encodeURIComponent(item)}/#${encodeURIComponent(`answer-card-${request}`)}`;
3
3
  }
@@ -17,7 +17,6 @@ export const PageUrl = Schema.String.check(
17
17
  "/_board/overview",
18
18
  "/_board/changes",
19
19
  "/_board/start",
20
- "/_board/respond",
21
20
  "/_board/handoff",
22
21
  "/_board/result",
23
22
  ].includes(path)
@@ -10,7 +10,7 @@ import { Library, LibraryInput } from "#browser/navigation/library.ts";
10
10
  import { FleetItemsProjection } from "#browser/views/FleetItemsProjection.ts";
11
11
  import { GoalsProjection } from "#browser/views/GoalsProjection.ts";
12
12
  import { ResultProjection } from "#browser/views/ResultProjection.ts";
13
- import { DiagnosticsProjection, HandoffProjection, RespondProjection, StartProjection } from "#browser/views/remaining.ts";
13
+ import { DiagnosticsProjection, HandoffProjection, StartProjection } from "#browser/views/remaining.ts";
14
14
  import { BoardProjection, InboxProjection, WorkProjection } from "#browser/views/schema.ts";
15
15
  import { handoffContract } from "#rpc/handoffContract.ts";
16
16
  import { responseContract } from "#rpc/responseContract.ts";
@@ -53,15 +53,13 @@ const ReadWork = query("work", {
53
53
  const ReadInbox = query("inbox", { reads: () => [workspace.list, index.list], rejections: { InternalServerError }, success: InboxProjection });
54
54
  const ReadServer = query("server", { reads: () => [], rejections: { ServiceUnavailable }, success: Server });
55
55
  const ReadDiagnostics = query("diagnostics", { reads: () => [workspace.list], rejections: { InternalServerError }, success: DiagnosticsProjection });
56
- const ReadFleetItems = query("fleetItems", { reads: () => [workspace.list, index.list], success: FleetItemsProjection });
56
+ const ReadFleetItems = query("fleetItems", {
57
+ reads: () => [workspace.list, index.list],
58
+ rejections: { InternalServerError },
59
+ success: FleetItemsProjection,
60
+ });
57
61
  const ReadGoals = query("goals", { reads: () => [workspace.list, index.list], rejections: { InternalServerError }, success: GoalsProjection });
58
62
  const ReadStart = query("start", { reads: () => [workspace.list, index.list], rejections: { InternalServerError }, success: StartProjection });
59
- const ReadRespond = query("respond", {
60
- payload: { url: PageUrl },
61
- reads: ({ url }) => [...pageKeys(url), index.list],
62
- rejections: documentRejections,
63
- success: RespondProjection,
64
- });
65
63
  const ReadHandoff = query("handoff", {
66
64
  payload: { url: PageUrl },
67
65
  reads: () => [workspace.list, index.list],
@@ -109,7 +107,6 @@ export const workContract = contract("work-board", {
109
107
  ReadFleetItems,
110
108
  ReadGoals,
111
109
  ReadStart,
112
- ReadRespond,
113
110
  ReadHandoff,
114
111
  ReadResult,
115
112
  ReadNavigation,