@specglass/theme-default 0.0.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 (141) hide show
  1. package/dist/__tests__/code-tabs.test.d.ts +2 -0
  2. package/dist/__tests__/code-tabs.test.d.ts.map +1 -0
  3. package/dist/__tests__/code-tabs.test.js +219 -0
  4. package/dist/__tests__/code-tabs.test.js.map +1 -0
  5. package/dist/__tests__/copy-button.test.d.ts +2 -0
  6. package/dist/__tests__/copy-button.test.d.ts.map +1 -0
  7. package/dist/__tests__/copy-button.test.js +116 -0
  8. package/dist/__tests__/copy-button.test.js.map +1 -0
  9. package/dist/__tests__/search-palette.test.d.ts +2 -0
  10. package/dist/__tests__/search-palette.test.d.ts.map +1 -0
  11. package/dist/__tests__/search-palette.test.js +71 -0
  12. package/dist/__tests__/search-palette.test.js.map +1 -0
  13. package/dist/__tests__/shiki.test.d.ts +2 -0
  14. package/dist/__tests__/shiki.test.d.ts.map +1 -0
  15. package/dist/__tests__/shiki.test.js +37 -0
  16. package/dist/__tests__/shiki.test.js.map +1 -0
  17. package/dist/__tests__/theme-css.test.d.ts +2 -0
  18. package/dist/__tests__/theme-css.test.d.ts.map +1 -0
  19. package/dist/__tests__/theme-css.test.js +124 -0
  20. package/dist/__tests__/theme-css.test.js.map +1 -0
  21. package/dist/__tests__/theme-helpers.test.d.ts +2 -0
  22. package/dist/__tests__/theme-helpers.test.d.ts.map +1 -0
  23. package/dist/__tests__/theme-helpers.test.js +81 -0
  24. package/dist/__tests__/theme-helpers.test.js.map +1 -0
  25. package/dist/index.d.ts +63 -0
  26. package/dist/index.d.ts.map +1 -0
  27. package/dist/index.js +13 -0
  28. package/dist/index.js.map +1 -0
  29. package/dist/islands/CodeTabs.d.ts +21 -0
  30. package/dist/islands/CodeTabs.d.ts.map +1 -0
  31. package/dist/islands/CodeTabs.js +125 -0
  32. package/dist/islands/CodeTabs.js.map +1 -0
  33. package/dist/islands/CopyButton.d.ts +16 -0
  34. package/dist/islands/CopyButton.d.ts.map +1 -0
  35. package/dist/islands/CopyButton.js +54 -0
  36. package/dist/islands/CopyButton.js.map +1 -0
  37. package/dist/islands/SearchPalette.d.ts +2 -0
  38. package/dist/islands/SearchPalette.d.ts.map +1 -0
  39. package/dist/islands/SearchPalette.js +109 -0
  40. package/dist/islands/SearchPalette.js.map +1 -0
  41. package/dist/islands/SearchResults.d.ts +2 -0
  42. package/dist/islands/SearchResults.d.ts.map +1 -0
  43. package/dist/islands/SearchResults.js +130 -0
  44. package/dist/islands/SearchResults.js.map +1 -0
  45. package/dist/islands/ThemeToggle.d.ts +12 -0
  46. package/dist/islands/ThemeToggle.d.ts.map +1 -0
  47. package/dist/islands/ThemeToggle.js +43 -0
  48. package/dist/islands/ThemeToggle.js.map +1 -0
  49. package/dist/layouts/DocPage.test.d.ts +2 -0
  50. package/dist/layouts/DocPage.test.d.ts.map +1 -0
  51. package/dist/layouts/DocPage.test.js +165 -0
  52. package/dist/layouts/DocPage.test.js.map +1 -0
  53. package/dist/lib/utils.d.ts +10 -0
  54. package/dist/lib/utils.d.ts.map +1 -0
  55. package/dist/lib/utils.js +13 -0
  56. package/dist/lib/utils.js.map +1 -0
  57. package/dist/scripts/code-block-enhancer.d.ts +16 -0
  58. package/dist/scripts/code-block-enhancer.d.ts.map +1 -0
  59. package/dist/scripts/code-block-enhancer.js +55 -0
  60. package/dist/scripts/code-block-enhancer.js.map +1 -0
  61. package/dist/ui/command.d.ts +87 -0
  62. package/dist/ui/command.d.ts.map +1 -0
  63. package/dist/ui/command.js +28 -0
  64. package/dist/ui/command.js.map +1 -0
  65. package/dist/ui/dialog.d.ts +20 -0
  66. package/dist/ui/dialog.d.ts.map +1 -0
  67. package/dist/ui/dialog.js +22 -0
  68. package/dist/ui/dialog.js.map +1 -0
  69. package/dist/utils/parse-highlight-range.d.ts +12 -0
  70. package/dist/utils/parse-highlight-range.d.ts.map +1 -0
  71. package/dist/utils/parse-highlight-range.js +40 -0
  72. package/dist/utils/parse-highlight-range.js.map +1 -0
  73. package/dist/utils/parse-highlight-range.test.d.ts +2 -0
  74. package/dist/utils/parse-highlight-range.test.d.ts.map +1 -0
  75. package/dist/utils/parse-highlight-range.test.js +32 -0
  76. package/dist/utils/parse-highlight-range.test.js.map +1 -0
  77. package/dist/utils/schema-renderer.d.ts +38 -0
  78. package/dist/utils/schema-renderer.d.ts.map +1 -0
  79. package/dist/utils/schema-renderer.js +115 -0
  80. package/dist/utils/schema-renderer.js.map +1 -0
  81. package/dist/utils/schema-renderer.test.d.ts +2 -0
  82. package/dist/utils/schema-renderer.test.d.ts.map +1 -0
  83. package/dist/utils/schema-renderer.test.js +219 -0
  84. package/dist/utils/schema-renderer.test.js.map +1 -0
  85. package/dist/utils/shiki.d.ts +20 -0
  86. package/dist/utils/shiki.d.ts.map +1 -0
  87. package/dist/utils/shiki.js +84 -0
  88. package/dist/utils/shiki.js.map +1 -0
  89. package/dist/utils/sidebar-helpers.d.ts +10 -0
  90. package/dist/utils/sidebar-helpers.d.ts.map +1 -0
  91. package/dist/utils/sidebar-helpers.js +14 -0
  92. package/dist/utils/sidebar-helpers.js.map +1 -0
  93. package/dist/utils/theme-css.d.ts +21 -0
  94. package/dist/utils/theme-css.d.ts.map +1 -0
  95. package/dist/utils/theme-css.js +77 -0
  96. package/dist/utils/theme-css.js.map +1 -0
  97. package/dist/utils/theme-helpers.d.ts +28 -0
  98. package/dist/utils/theme-helpers.d.ts.map +1 -0
  99. package/dist/utils/theme-helpers.js +55 -0
  100. package/dist/utils/theme-helpers.js.map +1 -0
  101. package/dist/utils/toc-helpers.d.ts +12 -0
  102. package/dist/utils/toc-helpers.d.ts.map +1 -0
  103. package/dist/utils/toc-helpers.js +9 -0
  104. package/dist/utils/toc-helpers.js.map +1 -0
  105. package/package.json +68 -0
  106. package/src/components/ApiAuth.astro +116 -0
  107. package/src/components/ApiEndpoint.astro +75 -0
  108. package/src/components/ApiNavigation.astro +110 -0
  109. package/src/components/ApiParameters.astro +204 -0
  110. package/src/components/ApiResponse.astro +144 -0
  111. package/src/components/Callout.astro +54 -0
  112. package/src/components/Card.astro +46 -0
  113. package/src/components/CodeBlock.astro +142 -0
  114. package/src/components/CodeBlockGroup.astro +196 -0
  115. package/src/components/CodeTabs.astro +53 -0
  116. package/src/components/Footer.astro +41 -0
  117. package/src/components/Header.astro +80 -0
  118. package/src/components/Sidebar.astro +117 -0
  119. package/src/components/TabItem.astro +24 -0
  120. package/src/components/TableOfContents.astro +111 -0
  121. package/src/components/Tabs.astro +185 -0
  122. package/src/islands/CodeTabs.tsx +212 -0
  123. package/src/islands/CopyButton.tsx +101 -0
  124. package/src/islands/SearchPalette.tsx +307 -0
  125. package/src/islands/SearchResults.tsx +301 -0
  126. package/src/islands/ThemeToggle.tsx +107 -0
  127. package/src/layouts/ApiReferencePage.astro +239 -0
  128. package/src/layouts/DocPage.astro +199 -0
  129. package/src/layouts/DocPage.test.ts +183 -0
  130. package/src/layouts/LandingPage.astro +143 -0
  131. package/src/lib/utils.ts +13 -0
  132. package/src/styles/global.css +241 -0
  133. package/src/utils/parse-highlight-range.test.ts +40 -0
  134. package/src/utils/parse-highlight-range.ts +41 -0
  135. package/src/utils/schema-renderer.test.ts +269 -0
  136. package/src/utils/schema-renderer.ts +152 -0
  137. package/src/utils/shiki.ts +99 -0
  138. package/src/utils/sidebar-helpers.ts +24 -0
  139. package/src/utils/theme-css.ts +101 -0
  140. package/src/utils/theme-helpers.ts +59 -0
  141. package/src/utils/toc-helpers.ts +11 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme-css.test.js","sourceRoot":"","sources":["../../src/__tests__/theme-css.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=theme-helpers.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme-helpers.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/theme-helpers.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,81 @@
1
+ // @vitest-environment jsdom
2
+ import { describe, it, expect, beforeEach, vi } from "vitest";
3
+ import { getStoredTheme, getEffectiveTheme, applyTheme, THEME_STORAGE_KEY, DEFAULT_THEME, } from "../utils/theme-helpers";
4
+ describe("theme-helpers", () => {
5
+ describe("constants", () => {
6
+ it("has correct storage key", () => {
7
+ expect(THEME_STORAGE_KEY).toBe("specglass-theme");
8
+ });
9
+ it("defaults to dark theme", () => {
10
+ expect(DEFAULT_THEME).toBe("dark");
11
+ });
12
+ });
13
+ describe("getStoredTheme", () => {
14
+ beforeEach(() => {
15
+ localStorage.clear();
16
+ });
17
+ it("returns null when no preference stored", () => {
18
+ expect(getStoredTheme()).toBeNull();
19
+ });
20
+ it("returns 'dark' when stored preference is dark", () => {
21
+ localStorage.setItem(THEME_STORAGE_KEY, "dark");
22
+ expect(getStoredTheme()).toBe("dark");
23
+ });
24
+ it("returns 'light' when stored preference is light", () => {
25
+ localStorage.setItem(THEME_STORAGE_KEY, "light");
26
+ expect(getStoredTheme()).toBe("light");
27
+ });
28
+ it("returns null for invalid stored value", () => {
29
+ localStorage.setItem(THEME_STORAGE_KEY, "auto");
30
+ expect(getStoredTheme()).toBeNull();
31
+ });
32
+ it("returns null when localStorage throws", () => {
33
+ vi.spyOn(Storage.prototype, "getItem").mockImplementation(() => {
34
+ throw new Error("SecurityError");
35
+ });
36
+ expect(getStoredTheme()).toBeNull();
37
+ vi.restoreAllMocks();
38
+ });
39
+ });
40
+ describe("getEffectiveTheme", () => {
41
+ it("returns stored theme when provided", () => {
42
+ expect(getEffectiveTheme("light")).toBe("light");
43
+ expect(getEffectiveTheme("dark")).toBe("dark");
44
+ });
45
+ it("falls back to default (dark) when stored is null", () => {
46
+ expect(getEffectiveTheme(null)).toBe("dark");
47
+ });
48
+ });
49
+ describe("applyTheme", () => {
50
+ beforeEach(() => {
51
+ localStorage.clear();
52
+ document.documentElement.classList.remove("dark");
53
+ });
54
+ it("adds .dark class for dark theme", () => {
55
+ applyTheme("dark");
56
+ expect(document.documentElement.classList.contains("dark")).toBe(true);
57
+ });
58
+ it("removes .dark class for light theme", () => {
59
+ document.documentElement.classList.add("dark");
60
+ applyTheme("light");
61
+ expect(document.documentElement.classList.contains("dark")).toBe(false);
62
+ });
63
+ it("persists theme to localStorage", () => {
64
+ applyTheme("light");
65
+ expect(localStorage.getItem(THEME_STORAGE_KEY)).toBe("light");
66
+ applyTheme("dark");
67
+ expect(localStorage.getItem(THEME_STORAGE_KEY)).toBe("dark");
68
+ });
69
+ it("handles localStorage errors gracefully", () => {
70
+ vi.spyOn(Storage.prototype, "setItem").mockImplementation(() => {
71
+ throw new Error("QuotaExceeded");
72
+ });
73
+ // Should not throw
74
+ expect(() => applyTheme("dark")).not.toThrow();
75
+ // Class should still be applied
76
+ expect(document.documentElement.classList.contains("dark")).toBe(true);
77
+ vi.restoreAllMocks();
78
+ });
79
+ });
80
+ });
81
+ //# sourceMappingURL=theme-helpers.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme-helpers.test.js","sourceRoot":"","sources":["../../src/__tests__/theme-helpers.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,63 @@
1
+ /** Callout type variants */
2
+ export type CalloutType = "info" | "warning" | "danger" | "tip";
3
+ /** Props for the Callout component */
4
+ export interface CalloutProps {
5
+ type?: CalloutType;
6
+ }
7
+ /** Props for the TabItem component */
8
+ export interface TabItemProps {
9
+ label: string;
10
+ }
11
+ /** Props for the CodeBlock component */
12
+ export interface CodeBlockProps {
13
+ lang?: string;
14
+ title?: string;
15
+ highlight?: string;
16
+ code?: string;
17
+ }
18
+ /** Props for the Card component */
19
+ export interface CardProps {
20
+ title?: string;
21
+ icon?: string;
22
+ href?: string;
23
+ }
24
+ export { parseHighlightRange } from "./utils/parse-highlight-range.js";
25
+ export { filterVisibleItems, isActiveOrAncestor, } from "./utils/sidebar-helpers.js";
26
+ export { filterTocHeadings } from "./utils/toc-helpers.js";
27
+ export type { Heading } from "./utils/toc-helpers.js";
28
+ export { getStoredTheme, getEffectiveTheme, applyTheme, THEME_STORAGE_KEY, DEFAULT_THEME, } from "./utils/theme-helpers.js";
29
+ export type { Theme } from "./utils/theme-helpers.js";
30
+ export { ThemeToggle } from "./islands/ThemeToggle.js";
31
+ export { CopyButton } from "./islands/CopyButton.js";
32
+ export type { CopyButtonProps } from "./islands/CopyButton.js";
33
+ export { CodeTabs } from "./islands/CodeTabs.js";
34
+ export type { CodeTab, CodeTabsProps } from "./islands/CodeTabs.js";
35
+ import type { NavigationTree } from "@specglass/core";
36
+ /** Props accepted by the DocPage layout */
37
+ export interface DocPageProps {
38
+ title: string;
39
+ description?: string;
40
+ frontmatter: Record<string, unknown>;
41
+ navigation: NavigationTree;
42
+ headings: Array<{
43
+ depth: number;
44
+ slug: string;
45
+ text: string;
46
+ }>;
47
+ currentSlug: string;
48
+ }
49
+ /** Props accepted by the Sidebar component */
50
+ export interface SidebarProps {
51
+ items: import("@specglass/core").NavItem[];
52
+ currentSlug: string;
53
+ depth?: number;
54
+ }
55
+ /** Props accepted by the TableOfContents component */
56
+ export interface TableOfContentsProps {
57
+ headings: Array<{
58
+ depth: number;
59
+ slug: string;
60
+ text: string;
61
+ }>;
62
+ }
63
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAQA,4BAA4B;AAC5B,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,SAAS,GAAG,QAAQ,GAAG,KAAK,CAAC;AAEhE,sCAAsC;AACtC,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,EAAE,WAAW,CAAC;CACpB;AAED,sCAAsC;AACtC,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;CACf;AAED,wCAAwC;AACxC,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,mCAAmC;AACnC,MAAM,WAAW,SAAS;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAGD,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAGvE,OAAO,EACL,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,YAAY,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAGtD,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,UAAU,EACV,iBAAiB,EACjB,aAAa,GACd,MAAM,0BAA0B,CAAC;AAClC,YAAY,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAC;AAGtD,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,YAAY,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,YAAY,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAGpE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEtD,2CAA2C;AAC3C,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,UAAU,EAAE,cAAc,CAAC;IAC3B,QAAQ,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/D,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,8CAA8C;AAC9C,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,OAAO,iBAAiB,EAAE,OAAO,EAAE,CAAC;IAC3C,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,sDAAsD;AACtD,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAChE"}
package/dist/index.js ADDED
@@ -0,0 +1,13 @@
1
+ // @specglass/theme-default — Theme entry point
2
+ // Utilities
3
+ export { parseHighlightRange } from "./utils/parse-highlight-range.js";
4
+ // Sidebar / ToC utilities (shared between components and tests)
5
+ export { filterVisibleItems, isActiveOrAncestor, } from "./utils/sidebar-helpers.js";
6
+ export { filterTocHeadings } from "./utils/toc-helpers.js";
7
+ // Theme utilities
8
+ export { getStoredTheme, getEffectiveTheme, applyTheme, THEME_STORAGE_KEY, DEFAULT_THEME, } from "./utils/theme-helpers.js";
9
+ // React islands
10
+ export { ThemeToggle } from "./islands/ThemeToggle.js";
11
+ export { CopyButton } from "./islands/CopyButton.js";
12
+ export { CodeTabs } from "./islands/CodeTabs.js";
13
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,+CAA+C;AAoC/C,YAAY;AACZ,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAEvE,gEAAgE;AAChE,OAAO,EACL,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAG3D,kBAAkB;AAClB,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,UAAU,EACV,iBAAiB,EACjB,aAAa,GACd,MAAM,0BAA0B,CAAC;AAGlC,gBAAgB;AAChB,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAErD,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1,21 @@
1
+ /** A single tab definition */
2
+ interface CodeTab {
3
+ /** Display label (e.g., "Python", "Node.js", "cURL") */
4
+ label: string;
5
+ /** Language key for sync/persistence (e.g., "python", "nodejs", "curl") */
6
+ language: string;
7
+ /** Pre-rendered HTML content (from Shiki or MDX) */
8
+ content: string;
9
+ }
10
+ interface CodeTabsProps {
11
+ /** Array of tab definitions */
12
+ tabs: CodeTab[];
13
+ /** Sync key — all CodeTabs with same key share selection. Default: "sdk-language" */
14
+ syncKey?: string;
15
+ /** Custom ARIA label for the tablist. Default: "SDK language tabs" */
16
+ ariaLabel?: string;
17
+ }
18
+ declare function CodeTabs({ tabs, syncKey, ariaLabel }: CodeTabsProps): import("react/jsx-runtime").JSX.Element | null;
19
+ export { CodeTabs };
20
+ export type { CodeTab, CodeTabsProps };
21
+ //# sourceMappingURL=CodeTabs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CodeTabs.d.ts","sourceRoot":"","sources":["../../src/islands/CodeTabs.tsx"],"names":[],"mappings":"AA+BA,8BAA8B;AAC9B,UAAU,OAAO;IACf,wDAAwD;IACxD,KAAK,EAAE,MAAM,CAAC;IACd,2EAA2E;IAC3E,QAAQ,EAAE,MAAM,CAAC;IACjB,oDAAoD;IACpD,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,UAAU,aAAa;IACrB,+BAA+B;IAC/B,IAAI,EAAE,OAAO,EAAE,CAAC;IAChB,qFAAqF;IACrF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,sEAAsE;IACtE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA6ED,iBAAS,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAwB,EAAE,SAA+B,EAAE,EAAE,aAAa,kDAmFnG;AAED,OAAO,EAAE,QAAQ,EAAE,CAAC;AACpB,YAAY,EAAE,OAAO,EAAE,aAAa,EAAE,CAAC"}
@@ -0,0 +1,125 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState, useEffect, useCallback, useRef, useMemo, useId } from "react";
3
+ import { cn } from "../lib/utils";
4
+ /**
5
+ * CodeTabs — React island for SDK/language code tabs with persistent preference.
6
+ *
7
+ * Features:
8
+ * - Tab switching with keyboard navigation (ArrowLeft/Right, Home/End)
9
+ * - localStorage persistence of preferred language
10
+ * - Cross-group sync via CustomEvent broadcast
11
+ * - Configurable syncKey for independent tab groups
12
+ *
13
+ * Designed for `client:idle` hydration in Astro islands.
14
+ *
15
+ * @see architecture.md FR32 (SDK tab switching), FR33 (persistent preference)
16
+ */
17
+ // ---------------------------------------------------------------------------
18
+ // Constants
19
+ // ---------------------------------------------------------------------------
20
+ const LANGUAGE_CHANGE_EVENT = "ndocs-language-change";
21
+ function getStorageKey(syncKey) {
22
+ return `ndocs-preferred-${syncKey}`;
23
+ }
24
+ // ---------------------------------------------------------------------------
25
+ // Hook — useCodeTabs
26
+ // SYNC: If changing this hook, update code-tabs.test.ts mirror copy
27
+ // ---------------------------------------------------------------------------
28
+ function useCodeTabs(languages, syncKey) {
29
+ const storageKey = getStorageKey(syncKey);
30
+ // Always start at index 0 — SSR-safe. Stored preference is restored in useEffect
31
+ // to avoid hydration mismatch (server has no localStorage → renders index 0,
32
+ // but client reads a different index → React can't reconcile → multiple panels visible).
33
+ const [activeIndex, setActiveIndex] = useState(0);
34
+ const isInternalChange = useRef(false);
35
+ // Restore stored preference after hydration
36
+ useEffect(() => {
37
+ try {
38
+ const stored = localStorage.getItem(storageKey);
39
+ if (stored) {
40
+ const idx = languages.indexOf(stored);
41
+ if (idx !== -1 && idx !== 0) {
42
+ setActiveIndex(idx);
43
+ }
44
+ }
45
+ }
46
+ catch {
47
+ // localStorage unavailable
48
+ }
49
+ }, [storageKey, languages]);
50
+ const setTab = useCallback((index) => {
51
+ if (index < 0 || index >= languages.length)
52
+ return;
53
+ setActiveIndex(index);
54
+ const language = languages[index];
55
+ if (language) {
56
+ try {
57
+ localStorage.setItem(storageKey, language);
58
+ }
59
+ catch {
60
+ // localStorage unavailable
61
+ }
62
+ isInternalChange.current = true;
63
+ window.dispatchEvent(new CustomEvent(LANGUAGE_CHANGE_EVENT, {
64
+ detail: { syncKey, language },
65
+ }));
66
+ isInternalChange.current = false;
67
+ }
68
+ }, [languages, storageKey, syncKey]);
69
+ // Listen for external language change events (from other CodeTabs instances)
70
+ useEffect(() => {
71
+ const handler = (e) => {
72
+ if (isInternalChange.current)
73
+ return;
74
+ const detail = e.detail;
75
+ if (detail?.syncKey === syncKey) {
76
+ const idx = languages.indexOf(detail.language);
77
+ if (idx !== -1) {
78
+ setActiveIndex(idx);
79
+ }
80
+ }
81
+ };
82
+ window.addEventListener(LANGUAGE_CHANGE_EVENT, handler);
83
+ return () => window.removeEventListener(LANGUAGE_CHANGE_EVENT, handler);
84
+ }, [languages, syncKey]);
85
+ return { activeIndex, setTab };
86
+ }
87
+ // ---------------------------------------------------------------------------
88
+ // Component
89
+ // ---------------------------------------------------------------------------
90
+ function CodeTabs({ tabs, syncKey = "sdk-language", ariaLabel = "SDK language tabs" }) {
91
+ // Memoize languages to prevent useEffect re-subscription on every render (H1 fix)
92
+ const languageKey = tabs.map((t) => t.language).join(",");
93
+ const languages = useMemo(() => tabs.map((t) => t.language), [languageKey]);
94
+ const { activeIndex, setTab } = useCodeTabs(languages, syncKey);
95
+ // Stable unique ID per instance via React's useId (HMR-safe)
96
+ const groupId = useId();
97
+ // Keyboard navigation
98
+ const handleKeyDown = useCallback((e) => {
99
+ let nextIndex = null;
100
+ if (e.key === "ArrowRight") {
101
+ nextIndex = (activeIndex + 1) % tabs.length;
102
+ }
103
+ else if (e.key === "ArrowLeft") {
104
+ nextIndex = (activeIndex - 1 + tabs.length) % tabs.length;
105
+ }
106
+ else if (e.key === "Home") {
107
+ nextIndex = 0;
108
+ }
109
+ else if (e.key === "End") {
110
+ nextIndex = tabs.length - 1;
111
+ }
112
+ if (nextIndex !== null) {
113
+ e.preventDefault();
114
+ setTab(nextIndex);
115
+ // Focus the newly active tab button
116
+ const btn = document.getElementById(`${groupId}-tab-${nextIndex}`);
117
+ btn?.focus();
118
+ }
119
+ }, [activeIndex, tabs.length, setTab, groupId]);
120
+ if (tabs.length === 0)
121
+ return null;
122
+ return (_jsxs("div", { className: "my-6 border border-border rounded-lg overflow-hidden", children: [_jsx("div", { role: "tablist", "aria-label": ariaLabel, className: "flex border-b border-border bg-surface-raised", onKeyDown: handleKeyDown, children: tabs.map((tab, i) => (_jsx("button", { id: `${groupId}-tab-${i}`, role: "tab", "aria-selected": i === activeIndex, "aria-controls": `${groupId}-panel-${i}`, tabIndex: i === activeIndex ? 0 : -1, className: cn("px-4 py-2 border-b-2 border-transparent text-[0.8125rem] font-medium font-mono", "text-text-muted cursor-pointer whitespace-nowrap bg-transparent", "transition-colors duration-150 hover:text-text", "focus-visible:outline-2 focus-visible:outline-primary focus-visible:-outline-offset-2", i === activeIndex && "text-text border-b-primary"), onClick: () => setTab(i), children: tab.label }, tab.language))) }), tabs.map((tab, i) => (_jsx("div", { id: `${groupId}-panel-${i}`, role: "tabpanel", "aria-labelledby": `${groupId}-tab-${i}`, tabIndex: 0, className: "code-tabs-panel", style: { display: i === activeIndex ? undefined : "none" }, dangerouslySetInnerHTML: { __html: tab.content } }, tab.language)))] }));
123
+ }
124
+ export { CodeTabs };
125
+ //# sourceMappingURL=CodeTabs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CodeTabs.js","sourceRoot":"","sources":["../../src/islands/CodeTabs.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * CopyButton island — copies code to clipboard with visual feedback.
3
+ *
4
+ * Renders a small button with a copy icon that, on click, copies the
5
+ * provided `code` string to the clipboard. Shows a checkmark for 2s
6
+ * after a successful copy, then reverts to the copy icon.
7
+ *
8
+ * Architecture: React island in `islands/` — hydrated with `client:idle`.
9
+ * Uses inline SVGs (no icon library) following the ThemeToggle pattern.
10
+ */
11
+ export interface CopyButtonProps {
12
+ /** The raw code text to copy to clipboard */
13
+ code: string;
14
+ }
15
+ export declare function CopyButton({ code }: CopyButtonProps): import("react/jsx-runtime").JSX.Element;
16
+ //# sourceMappingURL=CopyButton.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CopyButton.d.ts","sourceRoot":"","sources":["../../src/islands/CopyButton.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,MAAM,WAAW,eAAe;IAC9B,6CAA6C;IAC7C,IAAI,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,UAAU,CAAC,EAAE,IAAI,EAAE,EAAE,eAAe,2CAkFnD"}
@@ -0,0 +1,54 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * CopyButton island — copies code to clipboard with visual feedback.
4
+ *
5
+ * Renders a small button with a copy icon that, on click, copies the
6
+ * provided `code` string to the clipboard. Shows a checkmark for 2s
7
+ * after a successful copy, then reverts to the copy icon.
8
+ *
9
+ * Architecture: React island in `islands/` — hydrated with `client:idle`.
10
+ * Uses inline SVGs (no icon library) following the ThemeToggle pattern.
11
+ */
12
+ import { useState, useCallback, useRef } from "react";
13
+ export function CopyButton({ code }) {
14
+ const [copied, setCopied] = useState(false);
15
+ const timeoutRef = useRef(null);
16
+ const handleCopy = useCallback(() => {
17
+ // Clear any existing timeout to avoid stale state
18
+ if (timeoutRef.current) {
19
+ clearTimeout(timeoutRef.current);
20
+ }
21
+ navigator.clipboard.writeText(code).then(() => {
22
+ setCopied(true);
23
+ timeoutRef.current = setTimeout(() => {
24
+ setCopied(false);
25
+ timeoutRef.current = null;
26
+ }, 2000);
27
+ }).catch(() => {
28
+ // Clipboard API unavailable — silent fail for MVP
29
+ console.warn("[CopyButton] Clipboard API unavailable");
30
+ });
31
+ }, [code]);
32
+ return (_jsx("button", { type: "button", onClick: handleCopy, "aria-label": copied ? "Copied!" : "Copy code", title: copied ? "Copied!" : "Copy code", className: "sg-copy-btn", style: {
33
+ position: "absolute",
34
+ top: "0.5rem",
35
+ right: "0.5rem",
36
+ display: "flex",
37
+ alignItems: "center",
38
+ justifyContent: "center",
39
+ width: "2rem",
40
+ height: "2rem",
41
+ borderRadius: "0.375rem",
42
+ border: "1px solid var(--color-border, #e5e7eb)",
43
+ backgroundColor: "var(--color-surface, #ffffff)",
44
+ color: "var(--color-text-muted, #6b7280)",
45
+ cursor: "pointer",
46
+ opacity: copied ? 1 : 0,
47
+ transition: "opacity 150ms ease, background-color 150ms ease, color 150ms ease",
48
+ }, children: copied ? (
49
+ /* Checkmark icon */
50
+ _jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", style: { color: "#22c55e" }, children: _jsx("polyline", { points: "20 6 9 17 4 12" }) })) : (
51
+ /* Copy icon */
52
+ _jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2", ry: "2" }), _jsx("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" })] })) }));
53
+ }
54
+ //# sourceMappingURL=CopyButton.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CopyButton.js","sourceRoot":"","sources":["../../src/islands/CopyButton.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function SearchPalette(): import("react/jsx-runtime").JSX.Element;
2
+ //# sourceMappingURL=SearchPalette.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SearchPalette.d.ts","sourceRoot":"","sources":["../../src/islands/SearchPalette.tsx"],"names":[],"mappings":"AAqDA,wBAAgB,aAAa,4CA6P5B"}
@@ -0,0 +1,109 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState, useCallback, useEffect, useRef } from "react";
3
+ import { cn } from "../lib/utils";
4
+ import { CommandDialog, CommandInput, CommandList, CommandEmpty, CommandItem, } from "../ui/command";
5
+ const DEBOUNCE_MS = 150;
6
+ const MAX_RESULTS = 8;
7
+ export function SearchPalette() {
8
+ const [open, setOpen] = useState(false);
9
+ const [query, setQuery] = useState("");
10
+ const [results, setResults] = useState([]);
11
+ const [isLoading, setIsLoading] = useState(false);
12
+ const [isUnavailable, setIsUnavailable] = useState(false);
13
+ const pagefindRef = useRef(null);
14
+ const debounceRef = useRef(null);
15
+ // Load Pagefind JS lazily on palette open
16
+ const loadPagefind = useCallback(async () => {
17
+ if (pagefindRef.current)
18
+ return;
19
+ try {
20
+ const pagefindPath = `/pagefind/pagefind.js`;
21
+ const pf = await import(/* @vite-ignore */ pagefindPath);
22
+ await pf.init();
23
+ pagefindRef.current = pf;
24
+ }
25
+ catch {
26
+ setIsUnavailable(true);
27
+ }
28
+ }, []);
29
+ // Perform search
30
+ const performSearch = useCallback(async (searchQuery) => {
31
+ if (!searchQuery.trim()) {
32
+ setResults([]);
33
+ return;
34
+ }
35
+ if (!pagefindRef.current) {
36
+ await loadPagefind();
37
+ if (!pagefindRef.current)
38
+ return;
39
+ }
40
+ setIsLoading(true);
41
+ try {
42
+ const response = await pagefindRef.current.search(searchQuery);
43
+ const loaded = await Promise.all(response.results.slice(0, MAX_RESULTS).map((r) => r.data()));
44
+ setResults(loaded);
45
+ }
46
+ catch {
47
+ setResults([]);
48
+ }
49
+ finally {
50
+ setIsLoading(false);
51
+ }
52
+ }, [loadPagefind]);
53
+ // Handle input changes with debounce
54
+ const handleValueChange = useCallback((value) => {
55
+ setQuery(value);
56
+ if (debounceRef.current) {
57
+ clearTimeout(debounceRef.current);
58
+ }
59
+ debounceRef.current = setTimeout(() => {
60
+ performSearch(value);
61
+ }, DEBOUNCE_MS);
62
+ }, [performSearch]);
63
+ // Global Cmd+K / Ctrl+K keyboard shortcut
64
+ useEffect(() => {
65
+ const handleKeyDown = (e) => {
66
+ if ((e.metaKey || e.ctrlKey) && e.key === "k") {
67
+ e.preventDefault();
68
+ setOpen((prev) => !prev);
69
+ }
70
+ };
71
+ document.addEventListener("keydown", handleKeyDown);
72
+ return () => document.removeEventListener("keydown", handleKeyDown);
73
+ }, []);
74
+ // Load Pagefind when palette opens
75
+ useEffect(() => {
76
+ if (open) {
77
+ loadPagefind();
78
+ }
79
+ }, [open, loadPagefind]);
80
+ // Reset state when closing
81
+ const handleOpenChange = useCallback((isOpen) => {
82
+ setOpen(isOpen);
83
+ if (!isOpen) {
84
+ setTimeout(() => {
85
+ setQuery("");
86
+ setResults([]);
87
+ }, 150);
88
+ }
89
+ }, []);
90
+ // Navigate to a search result
91
+ const handleSelect = useCallback((url) => {
92
+ handleOpenChange(false);
93
+ window.location.href = url;
94
+ }, [handleOpenChange]);
95
+ // Cleanup debounce on unmount
96
+ useEffect(() => {
97
+ return () => {
98
+ if (debounceRef.current) {
99
+ clearTimeout(debounceRef.current);
100
+ }
101
+ };
102
+ }, []);
103
+ return (_jsxs("div", { "data-pagefind-ignore": "", children: [_jsxs("button", { type: "button", onClick: () => setOpen(true), className: cn("inline-flex items-center gap-2 px-3 py-1.5 text-sm rounded-md", "border border-border bg-surface text-text-muted", "hover:bg-hover-bg hover:text-text transition-colors", "focus:outline-none focus-visible:ring-2 focus-visible:ring-primary"), "aria-label": "Search documentation (\u2318K)", children: [_jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", className: "shrink-0", children: [_jsx("circle", { cx: "11", cy: "11", r: "8" }), _jsx("path", { d: "m21 21-4.3-4.3" })] }), _jsx("span", { className: "hidden sm:inline", children: "Search\u2026" }), _jsx("kbd", { className: cn("hidden sm:inline-flex items-center gap-0.5", "rounded border border-border bg-surface-raised px-1.5 py-0.5", "font-mono text-[10px] text-text-muted"), children: "\u2318K" })] }), _jsxs(CommandDialog, { open: open, onOpenChange: handleOpenChange, shouldFilter: false, dialogTitle: "Search documentation", children: [_jsx(CommandInput, { value: query, onValueChange: handleValueChange, placeholder: "Search documentation\u2026" }), _jsxs(CommandList, { children: [isUnavailable && (_jsxs("div", { className: "px-4 py-6 text-center text-sm text-text-muted", children: [_jsx("p", { className: "mb-1", children: "Search available after build" }), _jsxs("p", { className: "text-xs opacity-70", children: ["Run ", _jsx("code", { className: "bg-surface-raised px-1 rounded", children: "npx turbo build" }), " to generate the search index"] })] })), isLoading && !isUnavailable && (_jsx("div", { className: "px-4 py-6 text-center text-sm text-text-muted", children: "Searching\u2026" })), !isLoading && !isUnavailable && query.trim().length > 0 && (_jsxs(CommandEmpty, { children: ["No results found for \u201C", query, "\u201D"] })), !isUnavailable && !isLoading && query.trim().length === 0 && results.length === 0 && (_jsx("div", { className: "px-4 py-6 text-center text-sm text-text-muted", children: "Type to search documentation\u2026" })), !isUnavailable &&
104
+ results.map((result) => (_jsxs(CommandItem, { value: result.id, onSelect: () => handleSelect(result.url), className: "flex flex-col items-start gap-1 px-3 py-2.5", children: [_jsx("div", { className: "font-medium text-text", children: result.meta?.title ?? "Untitled" }), result.sub_results?.[0]?.title &&
105
+ result.sub_results[0].title !== result.meta?.title && (_jsx("div", { className: "text-xs text-text-muted", children: result.sub_results[0].title })), _jsx("div", { className: "text-xs text-text-muted line-clamp-2 [&_mark]:bg-primary/20 [&_mark]:text-text [&_mark]:rounded-sm [&_mark]:px-0.5", dangerouslySetInnerHTML: {
106
+ __html: result.sub_results?.[0]?.excerpt ?? result.excerpt ?? "",
107
+ } })] }, result.id)))] }), (results.length > 0 || query.trim().length > 0) && !isUnavailable && (_jsx("div", { className: "flex items-center justify-between border-t border-border px-3 py-2 text-xs text-text-muted", children: _jsxs("div", { className: "flex items-center gap-3", children: [_jsxs("span", { className: "inline-flex items-center gap-1", children: [_jsx("kbd", { className: "rounded border border-border bg-surface-raised px-1 py-0.5 font-mono text-[10px]", children: "\u2191\u2193" }), "navigate"] }), _jsxs("span", { className: "inline-flex items-center gap-1", children: [_jsx("kbd", { className: "rounded border border-border bg-surface-raised px-1 py-0.5 font-mono text-[10px]", children: "\u21B5" }), "open"] }), _jsxs("span", { className: "inline-flex items-center gap-1", children: [_jsx("kbd", { className: "rounded border border-border bg-surface-raised px-1 py-0.5 font-mono text-[10px]", children: "esc" }), "close"] })] }) }))] })] }));
108
+ }
109
+ //# sourceMappingURL=SearchPalette.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SearchPalette.js","sourceRoot":"","sources":["../../src/islands/SearchPalette.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function SearchResults(): import("react/jsx-runtime").JSX.Element;
2
+ //# sourceMappingURL=SearchResults.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SearchResults.d.ts","sourceRoot":"","sources":["../../src/islands/SearchResults.tsx"],"names":[],"mappings":"AA+CA,wBAAgB,aAAa,4CA6P5B"}