@tomehq/theme 0.3.1 → 0.3.2

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 (57) hide show
  1. package/dist/{chunk-YXKONM3A.js → chunk-2AXAEADQ.js} +471 -138
  2. package/dist/entry.js +1 -1
  3. package/dist/index.d.ts +21 -1
  4. package/dist/index.js +1 -1
  5. package/package.json +5 -5
  6. package/src/Shell.test.tsx +183 -0
  7. package/src/Shell.tsx +231 -21
  8. package/src/entry.tsx +173 -4
  9. package/src/global.d.ts +11 -0
  10. package/dist/chunk-2APCPR2Y.js +0 -2110
  11. package/dist/chunk-37JI6XGT.js +0 -1720
  12. package/dist/chunk-3A2LPGUL.js +0 -1991
  13. package/dist/chunk-3I2QTWTW.js +0 -1948
  14. package/dist/chunk-45M5UIAB.js +0 -2110
  15. package/dist/chunk-462AGU3S.js +0 -1959
  16. package/dist/chunk-7MUTU5D4.js +0 -1720
  17. package/dist/chunk-ABNPB6BB.js +0 -2133
  18. package/dist/chunk-BZGWSKT2.js +0 -573
  19. package/dist/chunk-CMQCNCSY.js +0 -2127
  20. package/dist/chunk-CTPOZMMK.js +0 -1703
  21. package/dist/chunk-DO544M3G.js +0 -1702
  22. package/dist/chunk-DPKZBFQP.js +0 -1777
  23. package/dist/chunk-EK7PZUEB.js +0 -2147
  24. package/dist/chunk-FMOLIHQF.js +0 -2182
  25. package/dist/chunk-FWBTK5TL.js +0 -1444
  26. package/dist/chunk-GDQIBNX5.js +0 -1962
  27. package/dist/chunk-GHQ2MODM.js +0 -2127
  28. package/dist/chunk-GR2WCRGK.js +0 -2182
  29. package/dist/chunk-HNLKDQ64.js +0 -2139
  30. package/dist/chunk-INUMUXN5.js +0 -2095
  31. package/dist/chunk-IW3NHNOQ.js +0 -2187
  32. package/dist/chunk-JA4PMX6M.js +0 -1500
  33. package/dist/chunk-JSPFS7G5.js +0 -2102
  34. package/dist/chunk-JZRT4WNC.js +0 -1441
  35. package/dist/chunk-KQBY2JDB.js +0 -2112
  36. package/dist/chunk-LIMYFTPC.js +0 -1468
  37. package/dist/chunk-MEP7P6A7.js +0 -1500
  38. package/dist/chunk-NOZBIES7.js +0 -1948
  39. package/dist/chunk-O4GH3KYX.js +0 -1712
  40. package/dist/chunk-OEXM3BEC.js +0 -1702
  41. package/dist/chunk-Q7PYTVW3.js +0 -1771
  42. package/dist/chunk-QCWZYABW.js +0 -1468
  43. package/dist/chunk-RDF25WB2.js +0 -2085
  44. package/dist/chunk-RKTT3ZEX.js +0 -1500
  45. package/dist/chunk-S47BRMNQ.js +0 -1715
  46. package/dist/chunk-S4ZH5F56.js +0 -1949
  47. package/dist/chunk-SRD7NJHS.js +0 -1949
  48. package/dist/chunk-SWFYJO5H.js +0 -2187
  49. package/dist/chunk-TQDWPSTO.js +0 -2087
  50. package/dist/chunk-TTRXRPP6.js +0 -1941
  51. package/dist/chunk-UKYFJSUA.js +0 -509
  52. package/dist/chunk-VKEQHP2E.js +0 -2133
  53. package/dist/chunk-VUT2FMSI.js +0 -1937
  54. package/dist/chunk-VVCC5JHK.js +0 -1949
  55. package/dist/chunk-W732TVBK.js +0 -1944
  56. package/dist/chunk-X4VQYPKO.js +0 -1768
  57. package/dist/chunk-YZ3P3TNS.js +0 -1760
package/src/entry.tsx CHANGED
@@ -13,11 +13,13 @@ import {
13
13
  // @ts-ignore — resolved by vite-plugin-tome
14
14
  import config from "virtual:tome/config";
15
15
  // @ts-ignore — resolved by vite-plugin-tome
16
- import { routes, navigation, versions } from "virtual:tome/routes";
16
+ import { routes, navigation, versions, i18n } from "virtual:tome/routes";
17
17
  // @ts-ignore — resolved by vite-plugin-tome
18
18
  import loadPageModule from "virtual:tome/page-loader";
19
19
  // @ts-ignore — resolved by vite-plugin-tome
20
20
  import docContext from "virtual:tome/doc-context";
21
+ // @ts-ignore — resolved by vite-plugin-tome
22
+ import overrides from "virtual:tome/overrides";
21
23
 
22
24
  // TOM-8: Built-in MDX components from @tomehq/components
23
25
  // These are injected into every MDX page automatically
@@ -32,6 +34,9 @@ import {
32
34
  PackageManager,
33
35
  TypeTable,
34
36
  FileTree,
37
+ CodeSamples,
38
+ LinkCard,
39
+ CardGrid,
35
40
  } from "@tomehq/components";
36
41
 
37
42
  const MDX_COMPONENTS: Record<string, React.ComponentType<any>> = {
@@ -45,6 +50,9 @@ const MDX_COMPONENTS: Record<string, React.ComponentType<any>> = {
45
50
  PackageManager,
46
51
  TypeTable,
47
52
  FileTree, // Sub-components accessible as <FileTree.File /> and <FileTree.Folder /> in MDX
53
+ CodeSamples,
54
+ LinkCard,
55
+ CardGrid,
48
56
  };
49
57
 
50
58
  // ── CONTENT STYLES ───────────────────────────────────────
@@ -60,15 +68,15 @@ const contentStyles = `
60
68
  .tome-content a { color: var(--ac); text-decoration: none; }
61
69
  .tome-content a:hover { text-decoration: underline; }
62
70
  .tome-content .heading-anchor { display: none; }
63
- .tome-content ul, .tome-content ol { color: var(--tx2); padding-left: 1.5em; margin-bottom: 1em; }
71
+ .tome-content ul, .tome-content ol { color: var(--tx2); padding-inline-start: 1.5em; margin-bottom: 1em; }
64
72
  .tome-content li { margin-bottom: 0.3em; line-height: 1.7; }
65
73
  .tome-content code { font-family: var(--font-code); font-size: 0.88em; background: var(--cdBg); padding: 0.15em 0.4em; border-radius: 2px; color: var(--ac); }
66
74
  .tome-content pre { margin-bottom: 1.2em; border-radius: 2px; overflow-x: auto; border: 1px solid var(--bd); }
67
75
  .tome-content pre code { background: none; padding: 1em 1.2em; display: block; font-size: 12.5px; line-height: 1.7; color: var(--cdTx); }
68
- .tome-content blockquote { border-left: 3px solid var(--ac); padding: 0.5em 1em; margin: 1em 0; background: var(--acD); border-radius: 0 2px 2px 0; }
76
+ .tome-content blockquote { border-inline-start: 3px solid var(--ac); padding: 0.5em 1em; margin: 1em 0; background: var(--acD); border-radius: 0 2px 2px 0; }
69
77
  .tome-content blockquote p { color: var(--tx2); margin: 0; }
70
78
  .tome-content table { width: 100%; border-collapse: collapse; margin-bottom: 1em; }
71
- .tome-content th, .tome-content td { padding: 0.5em 0.8em; border: 1px solid var(--bd); text-align: left; font-size: 0.9em; }
79
+ .tome-content th, .tome-content td { padding: 0.5em 0.8em; border: 1px solid var(--bd); text-align: start; font-size: 0.9em; }
72
80
  .tome-content th { background: var(--sf); font-weight: 600; }
73
81
  .tome-content img { max-width: 100%; border-radius: 2px; cursor: zoom-in; }
74
82
  .tome-content hr { border: none; border-top: 1px solid var(--bd); margin: 2em 0; }
@@ -122,6 +130,74 @@ const contentStyles = `
122
130
  background-repeat: repeat; background-size: 256px;
123
131
  }
124
132
 
133
+ /* ── Expressive code blocks ───────────────────────────── */
134
+
135
+ /* Code block wrapper (for titled blocks) */
136
+ .tome-code-block-wrapper { position: relative; margin-bottom: 1.2em; border: 1px solid var(--bd); border-radius: 2px; overflow: hidden; }
137
+ .tome-code-block-wrapper pre { margin-bottom: 0; border: none; border-radius: 0; }
138
+ .tome-code-title {
139
+ font-family: var(--font-code); font-size: 12px; color: var(--tx2);
140
+ background: var(--sf); padding: 6px 12px; border-bottom: 1px solid var(--bd);
141
+ letter-spacing: 0.01em; font-weight: 500;
142
+ }
143
+
144
+ /* Line highlighting */
145
+ .tome-content pre .line.tome-line-highlight {
146
+ background: rgba(139, 148, 158, 0.1);
147
+ display: inline-block; width: 100%; margin: 0 -1.2em; padding: 0 1.2em;
148
+ }
149
+ html.dark .tome-content pre .line.tome-line-highlight {
150
+ background: rgba(200, 210, 220, 0.08);
151
+ }
152
+
153
+ /* Diff lines */
154
+ .tome-content pre .line.tome-line-added {
155
+ background: rgba(34, 197, 94, 0.12);
156
+ display: inline-block; width: 100%; margin: 0 -1.2em; padding: 0 1.2em;
157
+ }
158
+ .tome-content pre .line.tome-line-removed {
159
+ background: rgba(239, 68, 68, 0.12);
160
+ display: inline-block; width: 100%; margin: 0 -1.2em; padding: 0 1.2em;
161
+ }
162
+ html.dark .tome-content pre .line.tome-line-added { background: rgba(34, 197, 94, 0.15); }
163
+ html.dark .tome-content pre .line.tome-line-removed { background: rgba(239, 68, 68, 0.15); }
164
+
165
+ /* Line numbers (CSS counter) */
166
+ .tome-content pre[data-line-numbers] code {
167
+ counter-reset: line;
168
+ }
169
+ .tome-content pre[data-line-numbers] .line::before {
170
+ counter-increment: line;
171
+ content: counter(line);
172
+ display: inline-block; width: 2.5em; margin-inline-end: 1em;
173
+ text-align: end; color: var(--txM); opacity: 0.4;
174
+ font-size: 0.85em; user-select: none;
175
+ border-inline-end: 1px solid var(--bd); padding-inline-end: 0.8em; margin-inline-end: 0.8em;
176
+ }
177
+
178
+ /* Word highlighting */
179
+ .tome-word-highlight {
180
+ background: rgba(139, 148, 158, 0.2); border-radius: 2px;
181
+ padding: 1px 3px; margin: 0 -1px;
182
+ }
183
+ html.dark .tome-word-highlight {
184
+ background: rgba(200, 210, 220, 0.15);
185
+ }
186
+
187
+ /* Copy button */
188
+ .tome-content pre { position: relative; }
189
+ .tome-copy-btn {
190
+ position: absolute; top: 8px; inset-inline-end: 8px;
191
+ font-family: var(--font-code); font-size: 11px;
192
+ color: var(--tx2); background: var(--sf); border: 1px solid var(--bd);
193
+ padding: 3px 8px; border-radius: 2px; cursor: pointer;
194
+ opacity: 0; transition: opacity 0.15s;
195
+ z-index: 2; line-height: 1.4;
196
+ }
197
+ .tome-content pre:hover .tome-copy-btn,
198
+ .tome-copy-btn:focus { opacity: 1; }
199
+ .tome-copy-btn:hover { background: var(--sfH); }
200
+
125
201
  /* Shiki dual-theme support */
126
202
  .shiki { background: var(--cdBg) !important; }
127
203
 
@@ -143,6 +219,57 @@ const contentStyles = `
143
219
  html:not(.dark) .shiki span[style*="color:#22863A"] { color: #1a6e2e !important; }
144
220
  html:not(.dark) .shiki span[style*="color:#D73A49"] { color: #b62324 !important; }
145
221
  html:not(.dark) .shiki span[style*="color:#005CC5"] { color: #0349b4 !important; }
222
+
223
+ /* ── Twoslash type hover tooltips ───────────────────── */
224
+ .twoslash-hover {
225
+ position: relative;
226
+ border-bottom: 1px dotted var(--tx2);
227
+ cursor: help;
228
+ }
229
+ .twoslash-popup-container {
230
+ position: absolute;
231
+ opacity: 0;
232
+ display: none;
233
+ z-index: 10;
234
+ left: 0;
235
+ top: 100%;
236
+ margin-top: 4px;
237
+ padding: 6px 10px;
238
+ background: var(--sf);
239
+ border: 1px solid var(--bd);
240
+ border-radius: 6px;
241
+ font-size: 12px;
242
+ font-family: var(--font-code);
243
+ color: var(--tx);
244
+ white-space: pre-wrap;
245
+ max-width: 500px;
246
+ box-shadow: 0 4px 12px rgba(0,0,0,0.15);
247
+ pointer-events: none;
248
+ }
249
+ .twoslash-hover:hover .twoslash-popup-container {
250
+ opacity: 1;
251
+ display: block;
252
+ }
253
+ /* Twoslash error/warning underlines */
254
+ .twoslash-error {
255
+ position: relative;
256
+ background: rgba(239, 68, 68, 0.1);
257
+ border-bottom: 2px wavy rgba(239, 68, 68, 0.6);
258
+ }
259
+ /* Twoslash highlighted identifiers */
260
+ .twoslash-highlighted {
261
+ background: rgba(139, 148, 158, 0.15);
262
+ border-radius: 2px;
263
+ padding: 1px 2px;
264
+ }
265
+ /* Twoslash type annotation line (^?) */
266
+ .twoslash-popup-code .shiki { background: transparent !important; padding: 0; margin: 0; }
267
+ .twoslash-popup-code .shiki code { padding: 0; font-size: 12px; }
268
+ html.dark .twoslash-popup-container {
269
+ background: var(--sf);
270
+ border-color: var(--bd);
271
+ box-shadow: 0 4px 12px rgba(0,0,0,0.3);
272
+ }
146
273
  `;
147
274
 
148
275
  // ── ROUTING HELPERS ──────────────────────────────────────
@@ -309,6 +436,39 @@ function App() {
309
436
  return () => { cancelled = true; };
310
437
  }, [pageData, loading, mermaidTheme]);
311
438
 
439
+ // Add copy buttons to all pre blocks (expressive code blocks)
440
+ useEffect(() => {
441
+ if (loading) return;
442
+ const preBlocks = document.querySelectorAll(".tome-content pre");
443
+ const buttons: HTMLButtonElement[] = [];
444
+ preBlocks.forEach((pre) => {
445
+ // Skip if already has a copy button
446
+ if (pre.querySelector(".tome-copy-btn")) return;
447
+ const btn = document.createElement("button");
448
+ btn.className = "tome-copy-btn";
449
+ btn.textContent = "Copy";
450
+ btn.addEventListener("click", async () => {
451
+ const code = pre.querySelector("code");
452
+ if (code) {
453
+ try {
454
+ await navigator.clipboard.writeText(code.textContent || "");
455
+ btn.textContent = "Copied!";
456
+ setTimeout(() => { btn.textContent = "Copy"; }, 2000);
457
+ } catch {
458
+ // Fallback for non-HTTPS contexts
459
+ btn.textContent = "Failed";
460
+ setTimeout(() => { btn.textContent = "Copy"; }, 2000);
461
+ }
462
+ }
463
+ });
464
+ pre.appendChild(btn);
465
+ buttons.push(btn);
466
+ });
467
+ return () => {
468
+ buttons.forEach((btn) => btn.remove());
469
+ };
470
+ }, [pageData, loading]);
471
+
312
472
  const allPages = routes.map((r: any) => ({
313
473
  id: r.id,
314
474
  title: r.frontmatter.title,
@@ -320,6 +480,10 @@ function App() {
320
480
  const currentVersion = detectCurrentVersion(currentRoute, versions);
321
481
  const editUrl = computeEditUrl(config.editLink, currentRoute?.filePath);
322
482
 
483
+ // RTL: detect current locale and compute text direction
484
+ const currentLocale = currentRoute?.locale || i18n?.defaultLocale || "en";
485
+ const dir: "ltr" | "rtl" = i18n?.localeDirs?.[currentLocale] || "ltr";
486
+
323
487
  // KaTeX CSS: inject stylesheet when math is enabled or math placeholders exist
324
488
  useEffect(() => {
325
489
  const hasMathPlaceholders = document.querySelectorAll(".tome-math[data-math]").length > 0;
@@ -391,6 +555,11 @@ function App() {
391
555
  versioning={versions || undefined}
392
556
  currentVersion={currentVersion}
393
557
  basePath={basePath}
558
+ isDraft={currentRoute?.frontmatter?.draft === true}
559
+ dir={dir}
560
+ i18n={i18n || undefined}
561
+ currentLocale={currentLocale}
562
+ overrides={overrides}
394
563
  />
395
564
  </>
396
565
  );
package/src/global.d.ts CHANGED
@@ -21,3 +21,14 @@ declare module "virtual:tome/doc-context" {
21
21
  const docContext: Array<{ id: string; title: string; content: string }>;
22
22
  export default docContext;
23
23
  }
24
+
25
+ declare module "virtual:tome/overrides" {
26
+ const overrides: {
27
+ Header?: React.ComponentType<any>;
28
+ Footer?: React.ComponentType<any>;
29
+ Sidebar?: React.ComponentType<any>;
30
+ Toc?: React.ComponentType<any>;
31
+ PageFooter?: React.ComponentType<any>;
32
+ };
33
+ export default overrides;
34
+ }