@terrafirmagreg-team/ui 0.1.0 → 1.2.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 (157) hide show
  1. package/package.json +14 -14
  2. package/src/components/blocks/button/icon-button.tsx +1 -0
  3. package/src/components/blocks/canvas/chevron-edge.tsx +126 -18
  4. package/src/components/blocks/canvas/flow-canvas.tsx +4 -0
  5. package/src/components/blocks/canvas/flow-toolbar.tsx +1 -0
  6. package/src/components/blocks/canvas/flow-viewport.tsx +1 -0
  7. package/src/components/blocks/fit-box.tsx +26 -0
  8. package/src/components/blocks/git/github-info.tsx +1 -0
  9. package/src/components/blocks/lang/content.tsx +40 -10
  10. package/src/components/blocks/lang/flag.tsx +1 -0
  11. package/src/components/blocks/lang/link.tsx +1 -0
  12. package/src/components/blocks/lang/redirect.tsx +2 -1
  13. package/src/components/blocks/lang/switcher.tsx +1 -0
  14. package/src/components/blocks/lang/untranslated-callout.tsx +4 -3
  15. package/src/components/blocks/lang/untranslated-chip.tsx +53 -0
  16. package/src/components/blocks/link/link-preview.tsx +2 -1
  17. package/src/components/blocks/list/row.tsx +1 -0
  18. package/src/components/blocks/media/glb/model.tsx +1 -0
  19. package/src/components/blocks/media/glb/scene.tsx +13 -12
  20. package/src/components/blocks/media/glb/viewer.tsx +1 -0
  21. package/src/components/blocks/media/image.tsx +3 -2
  22. package/src/components/blocks/media/slideshow.tsx +4 -3
  23. package/src/components/blocks/nav/breadcrumb.tsx +1 -0
  24. package/src/components/blocks/nav/copy-menu.tsx +37 -0
  25. package/src/components/blocks/nav/link.tsx +1 -0
  26. package/src/components/blocks/nav/site-menu.tsx +1 -0
  27. package/src/components/blocks/nav/site-title.tsx +1 -0
  28. package/src/components/blocks/nav/switcher.tsx +1 -0
  29. package/src/components/blocks/page/empty-state.tsx +1 -0
  30. package/src/components/blocks/page/heading.tsx +3 -2
  31. package/src/components/blocks/page/pager.tsx +110 -2
  32. package/src/components/blocks/readability/fields.tsx +250 -0
  33. package/src/components/blocks/readability/menu.tsx +74 -258
  34. package/src/components/blocks/readability/track.tsx +2 -1
  35. package/src/components/blocks/search/command.tsx +1 -0
  36. package/src/components/blocks/search/dialog.tsx +21 -9
  37. package/src/components/blocks/search/provider.tsx +2 -1
  38. package/src/components/blocks/sidebar.tsx +5 -5
  39. package/src/components/blocks/sprite.tsx +231 -0
  40. package/src/components/blocks/text/format-text.tsx +110 -0
  41. package/src/components/blocks/theme/toggle.tsx +4 -0
  42. package/src/components/blocks/tooltip/hint.tsx +1 -0
  43. package/src/components/blocks/tooltip/lazy.tsx +41 -0
  44. package/src/components/blocks/viewer/controls.tsx +11 -6
  45. package/src/components/blocks/viewer/float-bar.tsx +1 -0
  46. package/src/components/layouts/layout.tsx +2 -1
  47. package/src/components/layouts/left-sidebar/content.tsx +1 -0
  48. package/src/components/layouts/left-sidebar/context.tsx +1 -0
  49. package/src/components/layouts/left-sidebar/expand.tsx +2 -1
  50. package/src/components/layouts/left-sidebar/footer.tsx +10 -4
  51. package/src/components/layouts/left-sidebar/index.ts +1 -0
  52. package/src/components/layouts/left-sidebar/items.tsx +2 -1
  53. package/src/components/layouts/left-sidebar/search.tsx +4 -3
  54. package/src/components/layouts/left-sidebar/sidebar.tsx +3 -2
  55. package/src/components/layouts/left-sidebar/tree.tsx +1 -0
  56. package/src/components/layouts/right-sidebar.tsx +1 -0
  57. package/src/components/layouts/tree-context.tsx +1 -0
  58. package/src/components/mdx/accordion.tsx +3 -2
  59. package/src/components/mdx/banner.tsx +15 -12
  60. package/src/components/mdx/callout.tsx +1 -0
  61. package/src/components/mdx/card.tsx +12 -5
  62. package/src/components/mdx/codeblock.tsx +5 -4
  63. package/src/components/mdx/collapsible.tsx +1 -0
  64. package/src/components/mdx/files.tsx +1 -0
  65. package/src/components/mdx/glow-header.tsx +17 -3
  66. package/src/components/mdx/gradient-text.tsx +1 -0
  67. package/src/components/mdx/icon.tsx +35 -0
  68. package/src/components/mdx/image-zoom.tsx +5 -4
  69. package/src/components/mdx/math.tsx +30 -0
  70. package/src/components/mdx/mermaid.tsx +8 -1
  71. package/src/components/mdx/multiblock.tsx +1 -0
  72. package/src/components/mdx/preview.tsx +2 -1
  73. package/src/components/mdx/steps.tsx +1 -0
  74. package/src/components/mdx/table.tsx +1 -0
  75. package/src/components/mdx/tabs.tsx +2 -1
  76. package/src/components/mdx/type-table.tsx +7 -6
  77. package/src/{provider.tsx → components/provider.tsx} +1 -3
  78. package/src/hooks/canvas/use-flow-hover.ts +1 -0
  79. package/src/hooks/canvas/use-flow-viewport-persist.ts +1 -0
  80. package/src/hooks/page/use-fit-pages.ts +1 -0
  81. package/src/hooks/page/use-location-search.ts +8 -2
  82. package/src/hooks/page/use-page-preview.ts +2 -1
  83. package/src/hooks/page/use-paged-list.ts +1 -0
  84. package/src/hooks/readability/{provider.ts → use-readability.ts} +1 -0
  85. package/src/hooks/search/{dialog.ts → use-dialog.ts} +1 -0
  86. package/src/hooks/search/use-highlight-query.ts +8 -1
  87. package/src/hooks/search/{provider.ts → use-provider.ts} +1 -0
  88. package/src/hooks/use-async-value.ts +6 -3
  89. package/src/hooks/use-close-on-scroll.ts +1 -0
  90. package/src/hooks/use-copy-button.ts +1 -0
  91. package/src/hooks/use-cycle-index.ts +1 -0
  92. package/src/hooks/use-document-title.ts +1 -0
  93. package/src/hooks/use-element-size.ts +1 -0
  94. package/src/hooks/use-external-meta.ts +2 -1
  95. package/src/hooks/use-hot-key.ts +1 -0
  96. package/src/hooks/use-hover-follow.ts +1 -0
  97. package/src/hooks/use-in-view.ts +1 -0
  98. package/src/hooks/{lang.ts → use-lang.ts} +1 -0
  99. package/src/hooks/use-last-value.ts +1 -0
  100. package/src/hooks/{layout.ts → use-layout.ts} +1 -0
  101. package/src/hooks/use-marquee.ts +1 -0
  102. package/src/hooks/use-media-query.ts +1 -0
  103. package/src/hooks/use-mobile.ts +1 -0
  104. package/src/hooks/use-modifier-keys.ts +1 -0
  105. package/src/hooks/use-on-change.ts +1 -0
  106. package/src/hooks/use-pane-keys.ts +1 -0
  107. package/src/hooks/{sidebar.ts → use-sidebar.ts} +1 -0
  108. package/src/hooks/use-swipe.ts +1 -0
  109. package/src/hooks/use-tree.ts +1 -3
  110. package/src/hooks/viewer/use-in-float-bar.ts +1 -0
  111. package/src/hooks/viewer/use-viewer-prefs.ts +1 -0
  112. package/src/lib/canvas/edge.ts +78 -49
  113. package/src/lib/canvas/geometry.ts +1 -0
  114. package/src/lib/canvas/state.ts +1 -0
  115. package/src/lib/canvas/viewport.ts +1 -0
  116. package/src/lib/canvas/xyflow.ts +1 -0
  117. package/src/lib/config.ts +25 -0
  118. package/src/lib/mdx/callout.ts +1 -0
  119. package/src/lib/mdx/gradient.ts +1 -0
  120. package/src/lib/mdx/mermaid.ts +1 -0
  121. package/src/lib/media/crop-opaque.ts +1 -0
  122. package/src/lib/media/nearby-indexes.ts +1 -0
  123. package/src/lib/media/trim-transparent.ts +1 -0
  124. package/src/lib/readability/config.ts +1 -0
  125. package/src/lib/readability/spotlight.ts +1 -0
  126. package/src/lib/readability/store.ts +1 -0
  127. package/src/lib/tree.ts +1 -3
  128. package/src/lib/utils/cn.ts +1 -0
  129. package/src/lib/utils/format.ts +3 -3
  130. package/src/lib/utils/highlight-style.ts +10 -0
  131. package/src/lib/utils/history.ts +1 -0
  132. package/src/lib/utils/merge-refs.ts +1 -0
  133. package/src/lib/utils/nav-active.ts +1 -0
  134. package/src/lib/utils/stored-value.ts +1 -0
  135. package/src/lib/utils/urls.ts +2 -1
  136. package/src/locales/en_us.json +108 -117
  137. package/src/locales/pl_pl.json +33 -35
  138. package/src/locales/ru_ru.json +108 -117
  139. package/src/locales/uk_ua.json +33 -35
  140. package/src/locales/zh_cn.json +15 -17
  141. package/src/locales/zh_tw.json +15 -17
  142. package/src/locales.ts +1 -0
  143. package/src/types/canvas.ts +6 -1
  144. package/src/types/glb.ts +1 -0
  145. package/src/types/mdx-directives.ts +106 -0
  146. package/src/types/nav.ts +1 -0
  147. package/src/types/preview.ts +7 -1
  148. package/src/types/readability.ts +1 -0
  149. package/src/types/search.ts +1 -0
  150. package/src/types/tree.ts +1 -0
  151. package/src/types/viewer.ts +1 -0
  152. package/styles/content/base.css +198 -194
  153. package/styles/content/shiki.css +107 -108
  154. package/styles/content/typography.mjs +3637 -3941
  155. package/styles/content.css +5 -7
  156. package/styles.css +430 -413
  157. package/src/lib/utils/async-cache.ts +0 -32
@@ -6,3 +6,4 @@ export const UntranslatedContext = createContext(false);
6
6
  export function useUntranslated(): boolean {
7
7
  return useContext(UntranslatedContext);
8
8
  }
9
+
@@ -13,3 +13,4 @@ export function useLastValue<T>(
13
13
  }
14
14
  return value ?? (stale ? undefined : held?.value);
15
15
  }
16
+
@@ -16,3 +16,4 @@ export function useLayout() {
16
16
  throw new Error('Missing LayoutContext, expected under <Layout />.');
17
17
  return context;
18
18
  }
19
+
@@ -49,3 +49,4 @@ export function useMarquee<T extends HTMLElement>(): RefObject<T | null> {
49
49
 
50
50
  return ref;
51
51
  }
52
+
@@ -12,3 +12,4 @@ export function useMediaQuery(query: string): boolean {
12
12
  () => false,
13
13
  );
14
14
  }
15
+
@@ -17,3 +17,4 @@ export function useIsMobile() {
17
17
 
18
18
  return !!isMobile
19
19
  }
20
+
@@ -29,3 +29,4 @@ export function useModifierKeys(active = true): ModifierKeys {
29
29
  }, [active]);
30
30
  return keys;
31
31
  }
32
+
@@ -33,3 +33,4 @@ export function useOnChange<T>(
33
33
  setPrev(value);
34
34
  }
35
35
  }
36
+
@@ -26,3 +26,4 @@ export function usePaneKeys<T extends string>(
26
26
  return () => window.removeEventListener('keydown', onKey);
27
27
  }, [r, u, t, onSelect]);
28
28
  }
29
+
@@ -61,3 +61,4 @@ export function useAutoScroll(
61
61
  });
62
62
  }, [active, mode, ref]);
63
63
  }
64
+
@@ -24,3 +24,4 @@ export function useSwipe(onSwipe: (dir: -1 | 1) => void) {
24
24
  },
25
25
  };
26
26
  }
27
+
@@ -18,7 +18,6 @@ export function useTreeContext(): TreeContextValue {
18
18
  return ctx;
19
19
  }
20
20
 
21
-
22
21
  export function useTabsGroups(tabs: TabOption[]): {
23
22
  active?: PageTree.Folder;
24
23
  options: TabOption[];
@@ -52,7 +51,6 @@ export function useTabsGroups(tabs: TabOption[]): {
52
51
  }, [tabs, tree, path]);
53
52
  }
54
53
 
55
-
56
54
  function collectTabs(
57
55
  scope: PageTree.Node[],
58
56
  active: PageTree.Folder,
@@ -80,7 +78,6 @@ function collectTabs(
80
78
 
81
79
  const footerCache = new WeakMap<PageTree.Root | PageTree.Folder, PageTree.Item[]>();
82
80
 
83
-
84
81
  export function useFooterItems(): PageTree.Item[] {
85
82
  const { root } = useTreeContext();
86
83
  const cached = footerCache.get(root);
@@ -100,3 +97,4 @@ export function useFooterItems(): PageTree.Item[] {
100
97
  footerCache.set(root, list);
101
98
  return list;
102
99
  }
100
+
@@ -4,3 +4,4 @@ import { createContext, useContext } from 'react';
4
4
  export const FloatBarContext = createContext(false);
5
5
 
6
6
  export const useInFloatBar = () => useContext(FloatBarContext);
7
+
@@ -75,3 +75,4 @@ export function useViewerPrefs() {
75
75
  setSceneHeight,
76
76
  };
77
77
  }
78
+
@@ -3,65 +3,31 @@ import type {
3
3
  FlowPoint,
4
4
  } from '@terrafirmagreg-team/ui/types/canvas';
5
5
 
6
- const CHEVRON_SPACING = 10;
6
+ export const CHEVRON_SPACING = 10;
7
7
  const CHEVRON_SIZE = 3.5;
8
8
 
9
- const RUN_COS = Math.cos(Math.PI / 7);
9
+ export const CHEVRON_GLYPH = `M${-CHEVRON_SIZE * 0.45} ${-CHEVRON_SIZE * 0.9}L${CHEVRON_SIZE} 0L${-CHEVRON_SIZE * 0.45} ${CHEVRON_SIZE * 0.9}`;
10
10
 
11
- export type ChevronRun = { d: string; shiftX: number; shiftY: number };
12
-
13
- export function chevronTicksAlongPath(
14
- points: readonly FlowPoint[],
15
- ): ChevronRun[] {
16
- if (points.length < 2) return [];
17
- const lens: number[] = [];
11
+ export function chevronTicksAlongPath(points: readonly FlowPoint[]): {
12
+ offsets: number[];
13
+ total: number;
14
+ } {
18
15
  let total = 0;
19
16
  for (let i = 0; i + 1 < points.length; i += 1) {
20
- const len = Math.hypot(
17
+ total += Math.hypot(
21
18
  points[i + 1]!.x - points[i]!.x,
22
19
  points[i + 1]!.y - points[i]!.y,
23
20
  );
24
- lens.push(len);
25
- total += len;
26
21
  }
27
- if (total < 2) return [];
28
- const size = CHEVRON_SIZE;
29
- const back = size * 0.45;
30
- const wing = size * 0.9;
31
- const runs: { ux: number; uy: number; parts: string[] }[] = [];
32
- let run: (typeof runs)[0] | null = null;
33
- let seg = 0;
34
- let segStart = 0;
35
- for (let d = CHEVRON_SPACING; d <= total; d += CHEVRON_SPACING) {
36
- while (seg < lens.length && segStart + lens[seg]! < d) {
37
- segStart += lens[seg]!;
38
- seg += 1;
39
- }
40
- if (seg >= lens.length) break;
41
- const len = lens[seg]!;
42
- if (len < 0.001) continue;
43
- const p0 = points[seg]!;
44
- const p1 = points[seg + 1]!;
45
- const t = (d - segStart) / len;
46
- const ux = (p1.x - p0.x) / len;
47
- const uy = (p1.y - p0.y) / len;
48
- const cx = p0.x + (p1.x - p0.x) * t;
49
- const cy = p0.y + (p1.y - p0.y) * t;
50
- if (!run || ux * run.ux + uy * run.uy < RUN_COS) {
51
- run = { ux, uy, parts: [] };
52
- runs.push(run);
53
- }
54
- const px = -uy;
55
- const py = ux;
56
- run.parts.push(
57
- `M${cx - ux * back + px * wing} ${cy - uy * back + py * wing}L${cx + ux * size} ${cy + uy * size}L${cx - ux * back - px * wing} ${cy - uy * back - py * wing}`,
58
- );
22
+ const offsets: number[] = [];
23
+ for (
24
+ let d = CHEVRON_SPACING;
25
+ d <= total - CHEVRON_SPACING / 2;
26
+ d += CHEVRON_SPACING
27
+ ) {
28
+ offsets.push(d);
59
29
  }
60
- return runs.map((entry) => ({
61
- d: entry.parts.join(''),
62
- shiftX: entry.ux * CHEVRON_SPACING,
63
- shiftY: entry.uy * CHEVRON_SPACING,
64
- }));
30
+ return { offsets, total };
65
31
  }
66
32
 
67
33
  export function svgPathToPoints(d: string, samples = 12): FlowPoint[] {
@@ -155,6 +121,66 @@ export function chamferedPolylinePath(
155
121
  return `${d}L${last.x} ${last.y}`;
156
122
  }
157
123
 
124
+ export function roundedPolylinePath(
125
+ points: readonly FlowPoint[],
126
+ radius = 10,
127
+ ): string {
128
+ if (!points.length) return '';
129
+ if (points.length < 3) {
130
+ return `M${points[0]!.x} ${points[0]!.y}${points
131
+ .slice(1)
132
+ .map((p) => `L${p.x} ${p.y}`)
133
+ .join('')}`;
134
+ }
135
+ let d = `M${points[0]!.x} ${points[0]!.y}`;
136
+ let cursor = points[0]!;
137
+ for (let i = 1; i + 1 < points.length; i += 1) {
138
+ const corner = points[i]!;
139
+ const next = points[i + 1]!;
140
+ const inLen = Math.hypot(corner.x - cursor.x, corner.y - cursor.y);
141
+ const outLen = Math.hypot(next.x - corner.x, next.y - corner.y);
142
+ const take = Math.min(radius, inLen / 2, outLen / 2);
143
+ if (take < 0.5) {
144
+ d += `L${corner.x} ${corner.y}`;
145
+ cursor = corner;
146
+ continue;
147
+ }
148
+ const ax = corner.x - ((corner.x - cursor.x) / inLen) * take;
149
+ const ay = corner.y - ((corner.y - cursor.y) / inLen) * take;
150
+ const bx = corner.x + ((next.x - corner.x) / outLen) * take;
151
+ const by = corner.y + ((next.y - corner.y) / outLen) * take;
152
+ d += `L${ax} ${ay}Q${corner.x} ${corner.y} ${bx} ${by}`;
153
+ cursor = { x: bx, y: by };
154
+ }
155
+ const last = points[points.length - 1]!;
156
+ return `${d}L${last.x} ${last.y}`;
157
+ }
158
+
159
+ export function nearestPointOnPolyline(
160
+ points: readonly FlowPoint[],
161
+ p: FlowPoint,
162
+ ): FlowPoint {
163
+ let best = points[0]!;
164
+ let bestD = Infinity;
165
+ for (let i = 1; i < points.length; i += 1) {
166
+ const a = points[i - 1]!;
167
+ const b = points[i]!;
168
+ const dx = b.x - a.x;
169
+ const dy = b.y - a.y;
170
+ const len2 = dx * dx + dy * dy;
171
+ const t = len2
172
+ ? Math.max(0, Math.min(1, ((p.x - a.x) * dx + (p.y - a.y) * dy) / len2))
173
+ : 0;
174
+ const q = { x: a.x + dx * t, y: a.y + dy * t };
175
+ const d = (q.x - p.x) ** 2 + (q.y - p.y) ** 2;
176
+ if (d < bestD) {
177
+ bestD = d;
178
+ best = q;
179
+ }
180
+ }
181
+ return best;
182
+ }
183
+
158
184
  export function chevronHighlightClass(
159
185
  highlight: ChevronEdgeHighlight,
160
186
  ): string {
@@ -163,6 +189,8 @@ export function chevronHighlightClass(
163
189
  return 'chevron-edge--incoming';
164
190
  case 'outgoing':
165
191
  return 'chevron-edge--outgoing';
192
+ case 'dim':
193
+ return 'chevron-edge--dim';
166
194
  case undefined:
167
195
  return '';
168
196
  default: {
@@ -171,3 +199,4 @@ export function chevronHighlightClass(
171
199
  }
172
200
  }
173
201
  }
202
+
@@ -51,3 +51,4 @@ export function zoomToFitBox(
51
51
  );
52
52
  return Math.min(maxZoom, Math.max(minZoom, zoom));
53
53
  }
54
+
@@ -45,3 +45,4 @@ export function decorateFlowEdges<E extends Edge>(
45
45
  return { ...edge, data: { hidden, highlight } };
46
46
  });
47
47
  }
48
+
@@ -35,3 +35,4 @@ export function writeStoredViewport(
35
35
 
36
36
  }
37
37
  }
38
+
@@ -1 +1,2 @@
1
1
  export * from '@xyflow/react';
2
+
package/src/lib/config.ts CHANGED
@@ -22,6 +22,22 @@ export const DEFAULT_EXTERNAL_META_PROVIDERS: ExternalMetaProvider[] = [
22
22
  description: 'description',
23
23
  replace: [[/_/g, ' ']],
24
24
  },
25
+ {
26
+ host: /^github\.com$/i,
27
+ path: /^\/([^/]+)\/([^/?#]+)\/releases\/tag\/([^/?#]+)\/?$/,
28
+ url: 'https://api.github.com/repos/{1}/{2}/releases/tags/{3}',
29
+ kind: 'json',
30
+ title: 'name',
31
+ description: 'body',
32
+ },
33
+ {
34
+ host: /^github\.com$/i,
35
+ path: /^\/([^/]+)\/([^/?#]+)\/(?:issues|pull)\/([^/?#]+)\/?$/,
36
+ url: 'https://api.github.com/repos/{1}/{2}/issues/{3}',
37
+ kind: 'json',
38
+ title: 'title',
39
+ description: 'body',
40
+ },
25
41
  {
26
42
  host: /^github\.com$/i,
27
43
  path: /^\/([^/]+)\/([^/?#]+)\/?$/,
@@ -30,6 +46,14 @@ export const DEFAULT_EXTERNAL_META_PROVIDERS: ExternalMetaProvider[] = [
30
46
  title: 'full_name',
31
47
  description: 'description',
32
48
  },
49
+ {
50
+ host: /^github\.com$/i,
51
+ path: /^\/([^/?#]+)\/?$/,
52
+ url: 'https://api.github.com/users/{1}',
53
+ kind: 'json',
54
+ title: 'name',
55
+ description: 'bio',
56
+ },
33
57
  {
34
58
  host: /.*/,
35
59
  url: 'https://api.allorigins.win/raw?url={href}',
@@ -79,3 +103,4 @@ const { register: registerUiConfig, get: uiConfig } =
79
103
  createConfigRegistry<UiConfig>();
80
104
 
81
105
  export { registerUiConfig, uiConfig };
106
+
@@ -18,3 +18,4 @@ export function calloutStyle(
18
18
  ): CSSProperties {
19
19
  return { '--callout-color': COLORS[type] ?? COLORS.info, ...style } as CSSProperties;
20
20
  }
21
+
@@ -13,3 +13,4 @@ export function gradientImage({
13
13
  }: GradientProps): string {
14
14
  return image ?? `linear-gradient(${dir}, ${from}, ${to})`;
15
15
  }
16
+
@@ -12,3 +12,4 @@ export function renderMermaidChart(chart: string): string | null {
12
12
  return null;
13
13
  }
14
14
  }
15
+
@@ -74,3 +74,4 @@ export function cropOpaqueImageDataUrl(
74
74
  );
75
75
  return out.toDataURL('image/png');
76
76
  }
77
+
@@ -4,3 +4,4 @@ export function nearbyIndexes(selected: number, length: number): number[] {
4
4
  const prev = (selected - 1 + length) % length;
5
5
  return next === prev ? [selected, next] : [selected, next, prev];
6
6
  }
7
+
@@ -115,3 +115,4 @@ export function trimTransparent(src: string): Promise<string> {
115
115
  image.src = src;
116
116
  });
117
117
  }
118
+
@@ -8,3 +8,4 @@ const { register: registerReadabilityConfig, get: readabilityConfig } =
8
8
  createConfigRegistry<ReadabilityConfig>();
9
9
 
10
10
  export { registerReadabilityConfig, readabilityConfig };
11
+
@@ -184,3 +184,4 @@ export function rowBand(
184
184
  const pr = parent.getBoundingClientRect();
185
185
  return { top, left: pr.left, width: pr.width, height: bottom - top };
186
186
  }
187
+
@@ -144,3 +144,4 @@ export function clearState() {
144
144
  root.style.removeProperty('--page-width');
145
145
  root.style.removeProperty('--content-width');
146
146
  }
147
+
package/src/lib/tree.ts CHANGED
@@ -7,7 +7,6 @@ export function normalizeUrl(url: string): string {
7
7
  return url;
8
8
  }
9
9
 
10
-
11
10
  export function findPath(
12
11
  nodes: PageTree.Node[],
13
12
  matcher: (node: PageTree.Node) => boolean,
@@ -45,7 +44,6 @@ export function findPath(
45
44
  return run(nodes) ?? null;
46
45
  }
47
46
 
48
-
49
47
  export function searchPath(
50
48
  nodes: PageTree.Node[],
51
49
  url: string,
@@ -57,7 +55,6 @@ export function searchPath(
57
55
  );
58
56
  }
59
57
 
60
-
61
58
  export function findProjection(
62
59
  from: PageTree.Folder,
63
60
  to: PageTree.Folder,
@@ -90,3 +87,4 @@ export function findProjection(
90
87
  }
91
88
  return projection;
92
89
  }
90
+
@@ -1 +1,2 @@
1
1
  export { cn } from 'cn';
2
+
@@ -1,8 +1,7 @@
1
-
2
- export function formatCount(value: number): string {
1
+ export function formatCount(value: number, roundAt = 10_000): string {
3
2
  if (!Number.isFinite(value)) return String(value);
4
3
  const abs = Math.abs(value);
5
- if (abs < 10_000) return String(Math.trunc(value));
4
+ if (abs < roundAt) return String(Math.trunc(value));
6
5
  const units: [number, string][] = [
7
6
  [1_000_000_000, 'B'],
8
7
  [1_000_000, 'M'],
@@ -20,3 +19,4 @@ export function formatCount(value: number): string {
20
19
  }
21
20
  return String(value);
22
21
  }
22
+
@@ -0,0 +1,10 @@
1
+ const injected = new Set<string>();
2
+
3
+ export function injectHighlightStyle(name: string, css: string): void {
4
+ if (injected.has(name) || typeof document === 'undefined') return;
5
+ injected.add(name);
6
+ const style = document.createElement('style');
7
+ style.textContent = `::highlight(${name}){${css}}`;
8
+ document.head.appendChild(style);
9
+ }
10
+
@@ -7,3 +7,4 @@ export function replaceUrlState(href: string) {
7
7
  export function pushUrlState(href: string) {
8
8
  window.history.pushState(null, '', href);
9
9
  }
10
+
@@ -11,3 +11,4 @@ export function mergeRefs<T>(...refs: (React.Ref<T> | undefined)[]): React.RefCa
11
11
  });
12
12
  };
13
13
  }
14
+
@@ -56,3 +56,4 @@ export function langScopeKey(
56
56
  id = id?.replaceAll(`:${lang}`, '').replaceAll(`/${lang}`, '');
57
57
  return id;
58
58
  }
59
+
@@ -134,3 +134,4 @@ export function numberCodec(
134
134
  write: (value) => String(clamp(value)),
135
135
  };
136
136
  }
137
+
@@ -1,5 +1,5 @@
1
1
  export function safeURL(value?: string): string | undefined {
2
- // oxlint-disable-next-line no-control-regex
2
+
3
3
  if (!value || /[\u0000-\u0020\\]/.test(value)) return undefined;
4
4
  return /^(https?:\/\/|\/(?!\/)|#)/i.test(value) ? value : undefined;
5
5
  }
@@ -15,3 +15,4 @@ export function isActive(href: string, pathname: string, nested = false): boolea
15
15
 
16
16
  return href === pathname || (nested && pathname.startsWith(`${href}/`));
17
17
  }
18
+