@tomehq/theme 0.6.4 → 0.7.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.
@@ -0,0 +1,73 @@
1
+ // src/ai-api.ts
2
+ function buildSystemPrompt(context, instruction) {
3
+ const base = instruction || "You are a helpful documentation assistant. Answer questions accurately based on the documentation provided below. If the answer isn't in the documentation, say so clearly. Keep answers concise and reference specific sections when possible.";
4
+ if (!context) return base;
5
+ const trimmed = context.length > 1e5 ? context.slice(0, 1e5) + "\n\n[Documentation truncated...]" : context;
6
+ return `${base}
7
+
8
+ Documentation:
9
+ ${trimmed}`;
10
+ }
11
+ async function callOpenAI(messages, apiKey, model, systemPrompt) {
12
+ const res = await fetch("https://api.openai.com/v1/chat/completions", {
13
+ method: "POST",
14
+ headers: {
15
+ "Content-Type": "application/json",
16
+ "Authorization": `Bearer ${apiKey}`
17
+ },
18
+ body: JSON.stringify({
19
+ model,
20
+ messages: [
21
+ { role: "system", content: systemPrompt },
22
+ ...messages.map((m) => ({ role: m.role, content: m.content }))
23
+ ]
24
+ })
25
+ });
26
+ if (!res.ok) {
27
+ const err = await res.text();
28
+ throw new Error(`OpenAI API error (${res.status}): ${err}`);
29
+ }
30
+ const data = await res.json();
31
+ return data.choices?.[0]?.message?.content || "No response.";
32
+ }
33
+ async function callAnthropic(messages, apiKey, model, systemPrompt) {
34
+ const res = await fetch("https://api.anthropic.com/v1/messages", {
35
+ method: "POST",
36
+ headers: {
37
+ "Content-Type": "application/json",
38
+ "x-api-key": apiKey,
39
+ "anthropic-version": "2023-06-01",
40
+ "anthropic-dangerous-direct-browser-access": "true"
41
+ },
42
+ body: JSON.stringify({
43
+ model,
44
+ max_tokens: 1024,
45
+ system: systemPrompt,
46
+ messages: messages.map((m) => ({ role: m.role, content: m.content }))
47
+ })
48
+ });
49
+ if (!res.ok) {
50
+ const err = await res.text();
51
+ throw new Error(`Anthropic API error (${res.status}): ${err}`);
52
+ }
53
+ const data = await res.json();
54
+ return data.content?.[0]?.text || "No response.";
55
+ }
56
+ function getDefaultModel(provider) {
57
+ if (provider === "openai") return "gpt-4o-mini";
58
+ return "claude-sonnet-4-20250514";
59
+ }
60
+ async function callAiProvider(provider, messages, apiKey, model, systemPrompt) {
61
+ if (provider === "openai") {
62
+ return callOpenAI(messages, apiKey, model, systemPrompt);
63
+ }
64
+ return callAnthropic(messages, apiKey, model, systemPrompt);
65
+ }
66
+
67
+ export {
68
+ buildSystemPrompt,
69
+ callOpenAI,
70
+ callAnthropic,
71
+ getDefaultModel,
72
+ callAiProvider
73
+ };
package/dist/entry.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  entry_default
3
- } from "./chunk-XTCRYWCB.js";
3
+ } from "./chunk-6AD5TJ6F.js";
4
+ import "./chunk-LNWYFDZ4.js";
4
5
  export {
5
6
  entry_default as default
6
7
  };
package/dist/index.d.ts CHANGED
@@ -27,6 +27,7 @@ interface ShellProps {
27
27
  };
28
28
  search?: {
29
29
  provider?: string;
30
+ ai?: boolean;
30
31
  appId?: string;
31
32
  apiKey?: string;
32
33
  indexName?: string;
@@ -50,6 +51,13 @@ interface ShellProps {
50
51
  link?: string;
51
52
  dismissible?: boolean;
52
53
  };
54
+ branding?: {
55
+ powered?: boolean;
56
+ };
57
+ feedback?: {
58
+ enabled?: boolean;
59
+ textInput?: boolean;
60
+ };
53
61
  socialLinks?: Array<{
54
62
  platform: string;
55
63
  url: string;
@@ -97,6 +105,7 @@ interface ShellProps {
97
105
  }>;
98
106
  }>;
99
107
  apiManifest?: any;
108
+ asyncApiManifest?: any;
100
109
  apiBaseUrl?: string;
101
110
  apiPlayground?: boolean;
102
111
  apiAuth?: {
@@ -112,6 +121,9 @@ interface ShellProps {
112
121
  header?: string;
113
122
  };
114
123
  }>;
124
+ AsyncApiReferenceComponent?: React.ComponentType<{
125
+ manifest: any;
126
+ }>;
115
127
  onNavigate: (id: string) => void;
116
128
  allPages: Array<{
117
129
  id: string;
@@ -138,7 +150,7 @@ interface ShellProps {
138
150
  PageFooter?: React.ComponentType<any>;
139
151
  };
140
152
  }
141
- declare function Shell({ config, navigation, currentPageId, pageHtml, pageComponent, mdxComponents, pageTitle, pageDescription, headings, tocEnabled, editUrl, lastUpdated, changelogEntries, apiManifest, apiBaseUrl, apiPlayground, apiAuth, ApiReferenceComponent, onNavigate, allPages, versioning, currentVersion, i18n, currentLocale, docContext, basePath, isDraft, dir: dirProp, overrides, }: ShellProps): react_jsx_runtime.JSX.Element;
153
+ declare function Shell({ config, navigation, currentPageId, pageHtml, pageComponent, mdxComponents, pageTitle, pageDescription, headings, tocEnabled, editUrl, lastUpdated, changelogEntries, apiManifest, asyncApiManifest, apiBaseUrl, apiPlayground, apiAuth, ApiReferenceComponent, AsyncApiReferenceComponent, onNavigate, allPages, versioning, currentVersion, i18n, currentLocale, docContext, basePath, isDraft, dir: dirProp, overrides, }: ShellProps): react_jsx_runtime.JSX.Element;
142
154
 
143
155
  interface AiChatProps {
144
156
  provider: "openai" | "anthropic" | "custom";
@@ -260,7 +272,7 @@ declare const THEME_PRESETS: {
260
272
  readonly bd: "#1a1a25";
261
273
  readonly tx: "#d4ff00";
262
274
  readonly tx2: "#8a90a0";
263
- readonly txM: "#6a7080";
275
+ readonly txM: "#7e8494";
264
276
  readonly ac: "#6666ff";
265
277
  readonly acD: "rgba(102,102,255,0.10)";
266
278
  readonly acT: "#8080ff";
@@ -276,7 +288,7 @@ declare const THEME_PRESETS: {
276
288
  readonly bd: "#d0d4db";
277
289
  readonly tx: "#0f1219";
278
290
  readonly tx2: "#4a5060";
279
- readonly txM: "#6a7080";
291
+ readonly txM: "#5c6272";
280
292
  readonly ac: "#2020cc";
281
293
  readonly acD: "rgba(32,32,204,0.08)";
282
294
  readonly acT: "#1a1aa8";
@@ -299,7 +311,7 @@ declare const THEME_PRESETS: {
299
311
  readonly bd: "#21262d";
300
312
  readonly tx: "#e6edf3";
301
313
  readonly tx2: "#8b949e";
302
- readonly txM: "#6e7681";
314
+ readonly txM: "#7d858f";
303
315
  readonly ac: "#0ea371";
304
316
  readonly acD: "rgba(14,163,113,0.10)";
305
317
  readonly acT: "#2dd4a0";
@@ -330,6 +342,240 @@ declare const THEME_PRESETS: {
330
342
  readonly code: "Fira Code";
331
343
  };
332
344
  };
345
+ readonly ocean: {
346
+ readonly dark: {
347
+ readonly bg: "#0a1628";
348
+ readonly sf: "#0f1d33";
349
+ readonly sfH: "#142540";
350
+ readonly bd: "#1a2e50";
351
+ readonly tx: "#e0e8f0";
352
+ readonly tx2: "#8ca0b8";
353
+ readonly txM: "#7b92aa";
354
+ readonly ac: "#0ea5e9";
355
+ readonly acD: "rgba(14,165,233,0.10)";
356
+ readonly acT: "#38bdf8";
357
+ readonly cdBg: "#081320";
358
+ readonly cdTx: "#94b4d0";
359
+ readonly sbBg: "#0a1628";
360
+ readonly hdBg: "rgba(10,22,40,0.90)";
361
+ };
362
+ readonly light: {
363
+ readonly bg: "#f0f7ff";
364
+ readonly sf: "#ffffff";
365
+ readonly sfH: "#e8f0fa";
366
+ readonly bd: "#ccdcef";
367
+ readonly tx: "#0c1929";
368
+ readonly tx2: "#3d5a78";
369
+ readonly txM: "#4a6a88";
370
+ readonly ac: "#0369a1";
371
+ readonly acD: "rgba(3,105,161,0.07)";
372
+ readonly acT: "#025e8f";
373
+ readonly cdBg: "#e4edf7";
374
+ readonly cdTx: "#1a3050";
375
+ readonly sbBg: "#eef4fc";
376
+ readonly hdBg: "rgba(240,247,255,0.92)";
377
+ };
378
+ readonly fonts: {
379
+ readonly heading: "Outfit";
380
+ readonly body: "Inter";
381
+ readonly code: "JetBrains Mono";
382
+ };
383
+ };
384
+ readonly rose: {
385
+ readonly dark: {
386
+ readonly bg: "#0f0a10";
387
+ readonly sf: "#171118";
388
+ readonly sfH: "#1e1620";
389
+ readonly bd: "#2a1f2c";
390
+ readonly tx: "#f0e4f0";
391
+ readonly tx2: "#b09ab0";
392
+ readonly txM: "#8a7890";
393
+ readonly ac: "#f43f5e";
394
+ readonly acD: "rgba(244,63,94,0.10)";
395
+ readonly acT: "#fb7185";
396
+ readonly cdBg: "#0d080e";
397
+ readonly cdTx: "#c8aec8";
398
+ readonly sbBg: "#0f0a10";
399
+ readonly hdBg: "rgba(15,10,16,0.88)";
400
+ };
401
+ readonly light: {
402
+ readonly bg: "#fef7f7";
403
+ readonly sf: "#ffffff";
404
+ readonly sfH: "#fceef0";
405
+ readonly bd: "#f0d4d8";
406
+ readonly tx: "#1a0f12";
407
+ readonly tx2: "#6b4048";
408
+ readonly txM: "#8a5a64";
409
+ readonly ac: "#c81e3e";
410
+ readonly acD: "rgba(200,30,62,0.06)";
411
+ readonly acT: "#a81835";
412
+ readonly cdBg: "#f8eaec";
413
+ readonly cdTx: "#3a1a22";
414
+ readonly sbBg: "#fdf2f4";
415
+ readonly hdBg: "rgba(254,247,247,0.92)";
416
+ };
417
+ readonly fonts: {
418
+ readonly heading: "Playfair Display";
419
+ readonly body: "Source Sans 3";
420
+ readonly code: "Fira Code";
421
+ };
422
+ };
423
+ readonly forest: {
424
+ readonly dark: {
425
+ readonly bg: "#091209";
426
+ readonly sf: "#0f1a0f";
427
+ readonly sfH: "#152215";
428
+ readonly bd: "#1e2e1e";
429
+ readonly tx: "#e0f0e0";
430
+ readonly tx2: "#8aaa8a";
431
+ readonly txM: "#6a8a6a";
432
+ readonly ac: "#22c55e";
433
+ readonly acD: "rgba(34,197,94,0.10)";
434
+ readonly acT: "#4ade80";
435
+ readonly cdBg: "#070e07";
436
+ readonly cdTx: "#a0c4a0";
437
+ readonly sbBg: "#091209";
438
+ readonly hdBg: "rgba(9,18,9,0.90)";
439
+ };
440
+ readonly light: {
441
+ readonly bg: "#f4faf4";
442
+ readonly sf: "#ffffff";
443
+ readonly sfH: "#e8f4e8";
444
+ readonly bd: "#c8e0c8";
445
+ readonly tx: "#0a1a0a";
446
+ readonly tx2: "#3a5a3a";
447
+ readonly txM: "#5a7a5a";
448
+ readonly ac: "#15803d";
449
+ readonly acD: "rgba(21,128,61,0.07)";
450
+ readonly acT: "#116d34";
451
+ readonly cdBg: "#e4f2e4";
452
+ readonly cdTx: "#1a3a1a";
453
+ readonly sbBg: "#eef6ee";
454
+ readonly hdBg: "rgba(244,250,244,0.92)";
455
+ };
456
+ readonly fonts: {
457
+ readonly heading: "Merriweather";
458
+ readonly body: "Nunito Sans";
459
+ readonly code: "Source Code Pro";
460
+ };
461
+ };
462
+ readonly slate: {
463
+ readonly dark: {
464
+ readonly bg: "#0f1115";
465
+ readonly sf: "#16181e";
466
+ readonly sfH: "#1c1f26";
467
+ readonly bd: "#24272e";
468
+ readonly tx: "#e2e4e8";
469
+ readonly tx2: "#9498a0";
470
+ readonly txM: "#808690";
471
+ readonly ac: "#94a3b8";
472
+ readonly acD: "rgba(148,163,184,0.10)";
473
+ readonly acT: "#b0bec8";
474
+ readonly cdBg: "#0c0e12";
475
+ readonly cdTx: "#a8acb4";
476
+ readonly sbBg: "#0f1115";
477
+ readonly hdBg: "rgba(15,17,21,0.88)";
478
+ };
479
+ readonly light: {
480
+ readonly bg: "#f8fafc";
481
+ readonly sf: "#ffffff";
482
+ readonly sfH: "#f1f5f9";
483
+ readonly bd: "#d8dfe7";
484
+ readonly tx: "#0f172a";
485
+ readonly tx2: "#475569";
486
+ readonly txM: "#64748b";
487
+ readonly ac: "#475569";
488
+ readonly acD: "rgba(71,85,105,0.07)";
489
+ readonly acT: "#3a4a5c";
490
+ readonly cdBg: "#f0f4f8";
491
+ readonly cdTx: "#1e293b";
492
+ readonly sbBg: "#f5f7fa";
493
+ readonly hdBg: "rgba(248,250,252,0.92)";
494
+ };
495
+ readonly fonts: {
496
+ readonly heading: "Inter";
497
+ readonly body: "Inter";
498
+ readonly code: "JetBrains Mono";
499
+ };
500
+ };
501
+ readonly sunset: {
502
+ readonly dark: {
503
+ readonly bg: "#120c06";
504
+ readonly sf: "#1a1208";
505
+ readonly sfH: "#22180c";
506
+ readonly bd: "#2e2010";
507
+ readonly tx: "#f0e4d4";
508
+ readonly tx2: "#b0986a";
509
+ readonly txM: "#907850";
510
+ readonly ac: "#f97316";
511
+ readonly acD: "rgba(249,115,22,0.10)";
512
+ readonly acT: "#fb923c";
513
+ readonly cdBg: "#0e0a05";
514
+ readonly cdTx: "#c8aa78";
515
+ readonly sbBg: "#120c06";
516
+ readonly hdBg: "rgba(18,12,6,0.90)";
517
+ };
518
+ readonly light: {
519
+ readonly bg: "#fffbf5";
520
+ readonly sf: "#ffffff";
521
+ readonly sfH: "#fef3e6";
522
+ readonly bd: "#f0d8b8";
523
+ readonly tx: "#1a1008";
524
+ readonly tx2: "#6a5030";
525
+ readonly txM: "#8a6840";
526
+ readonly ac: "#c2410c";
527
+ readonly acD: "rgba(194,65,12,0.06)";
528
+ readonly acT: "#a63a0a";
529
+ readonly cdBg: "#faf0e2";
530
+ readonly cdTx: "#3a2810";
531
+ readonly sbBg: "#fdf6ec";
532
+ readonly hdBg: "rgba(255,251,245,0.92)";
533
+ };
534
+ readonly fonts: {
535
+ readonly heading: "Sora";
536
+ readonly body: "DM Sans";
537
+ readonly code: "Fira Code";
538
+ };
539
+ };
540
+ readonly carbon: {
541
+ readonly dark: {
542
+ readonly bg: "#080808";
543
+ readonly sf: "#101010";
544
+ readonly sfH: "#171717";
545
+ readonly bd: "#1f1f1f";
546
+ readonly tx: "#d4d4d4";
547
+ readonly tx2: "#888888";
548
+ readonly txM: "#787878";
549
+ readonly ac: "#e4e4e4";
550
+ readonly acD: "rgba(228,228,228,0.08)";
551
+ readonly acT: "#f0f0f0";
552
+ readonly cdBg: "#0a0a0a";
553
+ readonly cdTx: "#a0a0a0";
554
+ readonly sbBg: "#080808";
555
+ readonly hdBg: "rgba(8,8,8,0.90)";
556
+ };
557
+ readonly light: {
558
+ readonly bg: "#f5f5f5";
559
+ readonly sf: "#ffffff";
560
+ readonly sfH: "#ebebeb";
561
+ readonly bd: "#d4d4d4";
562
+ readonly tx: "#171717";
563
+ readonly tx2: "#525252";
564
+ readonly txM: "#6b6b6b";
565
+ readonly ac: "#262626";
566
+ readonly acD: "rgba(38,38,38,0.06)";
567
+ readonly acT: "#1a1a1a";
568
+ readonly cdBg: "#eaeaea";
569
+ readonly cdTx: "#1a1a1a";
570
+ readonly sbBg: "#f0f0f0";
571
+ readonly hdBg: "rgba(245,245,245,0.92)";
572
+ };
573
+ readonly fonts: {
574
+ readonly heading: "Geist";
575
+ readonly body: "Geist";
576
+ readonly code: "Geist Mono";
577
+ };
578
+ };
333
579
  };
334
580
  type PresetName = keyof typeof THEME_PRESETS;
335
581
 
package/dist/index.js CHANGED
@@ -3,7 +3,8 @@ import {
3
3
  Shell,
4
4
  THEME_PRESETS,
5
5
  entry_default
6
- } from "./chunk-XTCRYWCB.js";
6
+ } from "./chunk-6AD5TJ6F.js";
7
+ import "./chunk-LNWYFDZ4.js";
7
8
  export {
8
9
  AiChat,
9
10
  entry_default as App,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tomehq/theme",
3
- "version": "0.6.4",
3
+ "version": "0.7.0",
4
4
  "description": "Tome default theme and React app shell",
5
5
  "type": "module",
6
6
  "main": "./src/index.tsx",
@@ -9,8 +9,8 @@
9
9
  "./entry": "./src/entry.tsx"
10
10
  },
11
11
  "dependencies": {
12
- "@tomehq/components": "0.6.4",
13
- "@tomehq/core": "0.6.4"
12
+ "@tomehq/components": "0.7.0",
13
+ "@tomehq/core": "0.7.0"
14
14
  },
15
15
  "peerDependencies": {
16
16
  "react": "^18.0.0 || ^19.0.0",
package/src/AiChat.tsx CHANGED
@@ -35,78 +35,14 @@ const SendIcon = () => (
35
35
  </svg>
36
36
  );
37
37
 
38
- // ── API HELPERS ──────────────────────────────────────────
39
- function buildSystemPrompt(context?: string): string {
40
- let prompt = "You are a helpful documentation assistant. Answer questions accurately based on the documentation provided below. If the answer isn't in the documentation, say so clearly. Keep answers concise and reference specific sections when possible.";
41
- if (context) {
42
- // Truncate context to stay within token limits (~100K chars ≈ 25K tokens)
43
- const trimmed = context.length > 100000 ? context.slice(0, 100000) + "\n\n[Documentation truncated...]" : context;
44
- prompt += `\n\nDocumentation:\n${trimmed}`;
45
- }
46
- return prompt;
47
- }
48
-
49
- async function callOpenAI(
50
- messages: Message[],
51
- apiKey: string,
52
- model: string,
53
- context?: string,
54
- ): Promise<string> {
55
- const res = await fetch("https://api.openai.com/v1/chat/completions", {
56
- method: "POST",
57
- headers: {
58
- "Content-Type": "application/json",
59
- "Authorization": `Bearer ${apiKey}`,
60
- },
61
- body: JSON.stringify({
62
- model,
63
- messages: [
64
- { role: "system", content: buildSystemPrompt(context) },
65
- ...messages.map((m) => ({ role: m.role, content: m.content })),
66
- ],
67
- }),
68
- });
69
- if (!res.ok) {
70
- const err = await res.text();
71
- throw new Error(`OpenAI API error (${res.status}): ${err}`);
72
- }
73
- const data = await res.json();
74
- return data.choices?.[0]?.message?.content || "No response.";
75
- }
76
-
77
- async function callAnthropic(
78
- messages: Message[],
79
- apiKey: string,
80
- model: string,
81
- context?: string,
82
- ): Promise<string> {
83
- const res = await fetch("https://api.anthropic.com/v1/messages", {
84
- method: "POST",
85
- headers: {
86
- "Content-Type": "application/json",
87
- "x-api-key": apiKey,
88
- "anthropic-version": "2023-06-01",
89
- "anthropic-dangerous-direct-browser-access": "true",
90
- },
91
- body: JSON.stringify({
92
- model,
93
- max_tokens: 1024,
94
- system: buildSystemPrompt(context),
95
- messages: messages.map((m) => ({ role: m.role, content: m.content })),
96
- }),
97
- });
98
- if (!res.ok) {
99
- const err = await res.text();
100
- throw new Error(`Anthropic API error (${res.status}): ${err}`);
101
- }
102
- const data = await res.json();
103
- return data.content?.[0]?.text || "No response.";
104
- }
105
-
106
- function getDefaultModel(provider: string): string {
107
- if (provider === "openai") return "gpt-4o-mini";
108
- return "claude-sonnet-4-20250514";
109
- }
38
+ // ── API HELPERS (shared with AI search) ─────────────────
39
+ import {
40
+ buildSystemPrompt,
41
+ callOpenAI,
42
+ callAnthropic,
43
+ getDefaultModel,
44
+ type AiMessage,
45
+ } from "./ai-api.js";
110
46
 
111
47
  // ── COMPONENT ───────────────────────────────────────────
112
48
  export function AiChat({ provider, model, apiKey, context }: AiChatProps) {
@@ -147,10 +83,11 @@ export function AiChat({ provider, model, apiKey, context }: AiChatProps) {
147
83
 
148
84
  try {
149
85
  let response: string;
86
+ const sysPrompt = buildSystemPrompt(context);
150
87
  if (provider === "openai") {
151
- response = await callOpenAI(updatedMessages, resolvedKey, resolvedModel, context);
88
+ response = await callOpenAI(updatedMessages as AiMessage[], resolvedKey, resolvedModel, sysPrompt);
152
89
  } else {
153
- response = await callAnthropic(updatedMessages, resolvedKey, resolvedModel, context);
90
+ response = await callAnthropic(updatedMessages as AiMessage[], resolvedKey, resolvedModel, sysPrompt);
154
91
  }
155
92
  setMessages((prev) => [...prev, { role: "assistant", content: response }]);
156
93
  } catch (err) {