@shivaedev/work-board 0.15.0 → 0.16.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 (119) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/assets/react.css +1 -1
  3. package/assets/react.js +17 -17
  4. package/dist/client/document/Mermaid.d.ts.map +1 -1
  5. package/dist/client/document/Mermaid.js +4 -10
  6. package/dist/client/document/Mermaid.js.map +1 -1
  7. package/dist/client/document/View.js +1 -1
  8. package/dist/client/document/View.js.map +1 -1
  9. package/dist/client/react/BoardShell.d.ts.map +1 -1
  10. package/dist/client/react/BoardShell.js +28 -23
  11. package/dist/client/react/BoardShell.js.map +1 -1
  12. package/dist/client/react/DocumentContext.d.ts.map +1 -1
  13. package/dist/client/react/DocumentContext.js +6 -4
  14. package/dist/client/react/DocumentContext.js.map +1 -1
  15. package/dist/client/react/LiveControls.d.ts.map +1 -1
  16. package/dist/client/react/LiveControls.js +1 -6
  17. package/dist/client/react/LiveControls.js.map +1 -1
  18. package/dist/client/react/PhoneNavigation.d.ts +3 -1
  19. package/dist/client/react/PhoneNavigation.d.ts.map +1 -1
  20. package/dist/client/react/PhoneNavigation.js +8 -13
  21. package/dist/client/react/PhoneNavigation.js.map +1 -1
  22. package/dist/client/react/ReadingLibrary.d.ts.map +1 -1
  23. package/dist/client/react/ReadingLibrary.js +2 -6
  24. package/dist/client/react/ReadingLibrary.js.map +1 -1
  25. package/dist/client/react/ReadingReadyContext.d.ts +6 -0
  26. package/dist/client/react/ReadingReadyContext.d.ts.map +1 -0
  27. package/dist/client/react/ReadingReadyContext.js +7 -0
  28. package/dist/client/react/ReadingReadyContext.js.map +1 -0
  29. package/dist/client/react/SessionContext.d.ts +3 -0
  30. package/dist/client/react/SessionContext.d.ts.map +1 -0
  31. package/dist/client/react/SessionContext.js +3 -0
  32. package/dist/client/react/SessionContext.js.map +1 -0
  33. package/dist/client/react/SystemMain.d.ts.map +1 -1
  34. package/dist/client/react/SystemMain.js +3 -1
  35. package/dist/client/react/SystemMain.js.map +1 -1
  36. package/dist/client/react/ThemeContext.d.ts +2 -0
  37. package/dist/client/react/ThemeContext.d.ts.map +1 -0
  38. package/dist/client/react/ThemeContext.js +3 -0
  39. package/dist/client/react/ThemeContext.js.map +1 -0
  40. package/dist/client/react/loadRemaining.d.ts +17 -17
  41. package/dist/client/react/navigationLocation.d.ts +2 -0
  42. package/dist/client/react/navigationLocation.d.ts.map +1 -1
  43. package/dist/client/react/navigationLocation.js +10 -0
  44. package/dist/client/react/navigationLocation.js.map +1 -1
  45. package/dist/client/react/scheduleReading.d.ts.map +1 -1
  46. package/dist/client/react/scheduleReading.js +1 -10
  47. package/dist/client/react/scheduleReading.js.map +1 -1
  48. package/dist/client/react/useAppearance.d.ts +2 -1
  49. package/dist/client/react/useAppearance.d.ts.map +1 -1
  50. package/dist/client/react/useAppearance.js +1 -2
  51. package/dist/client/react/useAppearance.js.map +1 -1
  52. package/dist/client/react/useBoardNavigation.d.ts +1 -1
  53. package/dist/client/react/useBoardNavigation.d.ts.map +1 -1
  54. package/dist/client/react/useBoardNavigation.js +13 -17
  55. package/dist/client/react/useBoardNavigation.js.map +1 -1
  56. package/dist/client/react/useDiagnosticsPolling.d.ts +4 -1
  57. package/dist/client/react/useDiagnosticsPolling.d.ts.map +1 -1
  58. package/dist/client/react/useDiagnosticsPolling.js +9 -7
  59. package/dist/client/react/useDiagnosticsPolling.js.map +1 -1
  60. package/dist/client/react/useSidebar.d.ts.map +1 -1
  61. package/dist/client/react/useSidebar.js +5 -3
  62. package/dist/client/react/useSidebar.js.map +1 -1
  63. package/dist/render/{failed.d.ts → Failed.d.ts} +1 -1
  64. package/dist/render/Failed.d.ts.map +1 -0
  65. package/dist/render/{failed.js → Failed.js} +1 -1
  66. package/dist/render/Failed.js.map +1 -0
  67. package/dist/render/code.d.ts +2 -2
  68. package/dist/render/code.d.ts.map +1 -1
  69. package/dist/render/code.js +15 -13
  70. package/dist/render/code.js.map +1 -1
  71. package/dist/render/footnoteIds.d.ts +3 -0
  72. package/dist/render/footnoteIds.d.ts.map +1 -0
  73. package/dist/render/{footnotes.js → footnoteIds.js} +11 -9
  74. package/dist/render/footnoteIds.js.map +1 -0
  75. package/dist/rpc/contract.d.ts +2401 -2401
  76. package/dist/rpc/contract.d.ts.map +1 -1
  77. package/dist/rpc/handoffContract.d.ts +33 -33
  78. package/dist/rpc/responseContract.d.ts +56 -56
  79. package/dist/server/board.d.ts +1 -1
  80. package/dist/server/mcp/client.d.ts +1265 -1265
  81. package/dist/server/mcp/client.d.ts.map +1 -1
  82. package/dist/server/packageInfo.d.ts +1 -1
  83. package/dist/server/packageInfo.js +1 -1
  84. package/dist/server/render/Highlighter.d.ts +1 -1
  85. package/dist/server/render/Highlighter.js +1 -1
  86. package/dist/server/render/markdown.d.ts +1 -1
  87. package/dist/server/render/markdown.js +2 -2
  88. package/dist/server/render/markdown.js.map +1 -1
  89. package/dist/server/serve.d.ts +1 -1
  90. package/package.json +5 -36
  91. package/src/client/document/Mermaid.ts +4 -10
  92. package/src/client/document/View.ts +1 -1
  93. package/src/client/react/BoardShell.tsx +37 -24
  94. package/src/client/react/DocumentContext.tsx +6 -4
  95. package/src/client/react/LiveControls.tsx +1 -14
  96. package/src/client/react/PhoneNavigation.tsx +20 -15
  97. package/src/client/react/ReadingLibrary.tsx +2 -6
  98. package/src/client/react/ReadingReadyContext.ts +11 -0
  99. package/src/client/react/SessionContext.ts +4 -0
  100. package/src/client/react/SystemMain.tsx +3 -1
  101. package/src/client/react/ThemeContext.ts +3 -0
  102. package/src/client/react/navigationLocation.ts +12 -0
  103. package/src/client/react/scheduleReading.ts +1 -10
  104. package/src/client/react/useAppearance.ts +2 -3
  105. package/src/client/react/useBoardNavigation.ts +13 -18
  106. package/src/client/react/useDiagnosticsPolling.ts +14 -7
  107. package/src/client/react/useSidebar.ts +5 -3
  108. package/src/render/code.ts +3 -4
  109. package/src/render/{footnotes.ts → footnoteIds.ts} +12 -10
  110. package/src/server/board.ts +1 -1
  111. package/src/server/packageInfo.ts +1 -1
  112. package/src/server/render/Highlighter.ts +1 -1
  113. package/src/server/render/markdown.ts +2 -2
  114. package/dist/render/failed.d.ts.map +0 -1
  115. package/dist/render/failed.js.map +0 -1
  116. package/dist/render/footnotes.d.ts +0 -3
  117. package/dist/render/footnotes.d.ts.map +0 -1
  118. package/dist/render/footnotes.js.map +0 -1
  119. /package/src/render/{failed.ts → Failed.ts} +0 -0
@@ -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
+ }
@@ -3,7 +3,7 @@ import { HttpRouter } from "effect/http";
3
3
  import { RpcSerialization, RpcServer } from "effect/rpc";
4
4
  import type { InternalServerError } from "@shivaedev/platform/errors/taxonomy.ts";
5
5
  import { localRpcGuard } from "@shivaedev/platform/rpc-server/local.ts";
6
- import type { RenderFailed } from "#render/failed.ts";
6
+ import type { RenderFailed } from "#render/Failed.ts";
7
7
  import { workRpcs } from "#rpc/contract.ts";
8
8
  import { boardRuntime } from "#server/boardRuntime.ts";
9
9
  import type { HomeMissing } from "#server/files/home.ts";
@@ -1,2 +1,2 @@
1
1
  export const NAME = "work-board";
2
- export const VERSION = "0.15.0";
2
+ export const VERSION = "0.16.0";
@@ -2,7 +2,7 @@ import { Effect } from "effect";
2
2
  import { createHighlighter } from "shiki";
3
3
  import { defineService } from "@shivaedev/effect-service/define-service.ts";
4
4
  import { codeBlocks, THEMES } from "#render/code.ts";
5
- import { RenderFailed } from "#render/failed.ts";
5
+ import { RenderFailed } from "#render/Failed.ts";
6
6
 
7
7
  export const Highlighter = defineService({
8
8
  id: "WorkBoard/Highlighter",
@@ -7,8 +7,8 @@ import type { PluggableList } from "unified";
7
7
  import type { documentHeadings } from "#render/documentHeadings.ts";
8
8
  import { documentLinks } from "#render/documentLinks.ts";
9
9
  import { documentPlugins } from "#render/documentPlugins.ts";
10
- import { RenderFailed } from "#render/failed.ts";
11
- import { footnoteIds } from "#render/footnotes.ts";
10
+ import { RenderFailed } from "#render/Failed.ts";
11
+ import { footnoteIds } from "#render/footnoteIds.ts";
12
12
  import { Highlighter } from "./Highlighter.ts";
13
13
 
14
14
  export interface RenderOptions {
@@ -1 +0,0 @@
1
- {"version":3,"file":"failed.d.ts","sourceRoot":"","sources":["../../src/render/failed.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;;;;AAEhC,qBAAa,YAAa,SAAQ,iBAA6E;IAC9G,IAAa,OAAO,WAEnB;CACD"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"failed.js","sourceRoot":"","sources":["../../src/render/failed.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,MAAM,OAAO,YAAa,SAAQ,MAAM,CAAC,WAAW,EAAgB,CAAC,cAAc,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC;IAC9G,IAAa,OAAO;QACnB,OAAO,uHAAuH,CAAC;IAChI,CAAC;CACD"}
@@ -1,3 +0,0 @@
1
- import type { Root } from "hast";
2
- export declare const footnoteIds: (prefix: string) => () => (tree: Root) => void;
3
- //# sourceMappingURL=footnotes.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"footnotes.d.ts","sourceRoot":"","sources":["../../src/render/footnotes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAW,IAAI,EAAE,MAAM,MAAM,CAAC;AAmB1C,eAAO,MAAM,WAAW,WAAY,MAAM,kBAAkB,IAAI,SAS/D,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"footnotes.js","sourceRoot":"","sources":["../../src/render/footnotes.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,IAAI,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAE1D,MAAM,YAAY,GAAG,sCAAsC,CAAC;AAI5D,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAAC;AAE1D,SAAS,MAAM,CAAC,MAAc,EAAE,KAAY;IAC3C,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAC3D,OAAO,GAAG,MAAM,GAAG,KAAK,EAAE,CAAC;IAC5B,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7F,OAAO,IAAI,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IACtC,CAAC;IACD,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;AAC7H,CAAC;AAED,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,MAAc,EAAE,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC,IAAU,EAAE,EAAE;IACnE,aAAa,CAAC,IAAI,EAAE,SAAS,EAAE,CAAC,OAAO,EAAE,EAAE;QAC1C,IAAI,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YAClD,OAAO;QACR,CAAC;QACD,OAAO,CAAC,UAAU,GAAG,MAAM,CAAC,WAAW,CACtC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CACnH,CAAC;IACH,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC"}
File without changes