@open-agent-toolkit/docs-theme 0.3.14 → 0.3.15

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.
package/README.md CHANGED
@@ -49,6 +49,22 @@ export function Page({ toc, chart }) {
49
49
  - `Mermaid`
50
50
  - `Tab`
51
51
  - `Tabs`
52
+ - `ZoomImage`: Markdown image renderer. Map it as `img` in your MDX
53
+ components.
54
+ - SVG images open in a full-screen view that renders them at least 900px
55
+ wide, so diagram text stays legible on a phone; the reader pans to see the
56
+ rest. Other images open in Fumadocs `ImageZoom`.
57
+ - Root-relative paths such as `/diagrams/x.svg` get the site base path
58
+ (`NEXT_PUBLIC_BASE_PATH`, which `@open-agent-toolkit/docs-config` sets
59
+ from `basePath`).
60
+ - Files named `<name>-light.<ext>` / `<name>-dark.<ext>` show only in the
61
+ matching theme. Add
62
+ `@source '../node_modules/@open-agent-toolkit/docs-theme/dist/**/*.js';`
63
+ to your Tailwind CSS so those theme classes are generated.
64
+
65
+ `Mermaid` diagrams take their colors from the site's Fumadocs color tokens
66
+ (`--color-fd-*`) in light and dark mode, and open in the same full-screen view
67
+ when clicked.
52
68
 
53
69
  ## Docs
54
70
 
@@ -0,0 +1,8 @@
1
+ export type ImageThemeVariant = 'light' | 'dark';
2
+ /** Which site theme an image file is for, from its `-light`/`-dark` name. */
3
+ export declare function themeVariantOf(src: string | undefined): ImageThemeVariant | null;
4
+ /** Prefix a root-relative public asset path with the site's base path. */
5
+ export declare function withBasePath(src: string, basePath: string): string;
6
+ /** Whether an image file is an SVG (diagrams are authored as SVG). */
7
+ export declare function isSvgSource(src: string | undefined): boolean;
8
+ //# sourceMappingURL=image-src.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image-src.d.ts","sourceRoot":"","sources":["../src/image-src.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,iBAAiB,GAAG,OAAO,GAAG,MAAM,CAAC;AAQjD,6EAA6E;AAC7E,wBAAgB,cAAc,CAC5B,GAAG,EAAE,MAAM,GAAG,SAAS,GACtB,iBAAiB,GAAG,IAAI,CAK1B;AAED,0EAA0E;AAC1E,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAIlE;AAED,sEAAsE;AACtE,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAE5D"}
@@ -0,0 +1,25 @@
1
+ // A file named `<name>-light.<ext>` or `<name>-dark.<ext>` is shown only in
2
+ // that site theme. The optional middle segment covers the content hash the
3
+ // bundler adds to imported assets (`<name>-dark.4f3a2b1c.svg`).
4
+ const THEME_VARIANT_PATTERN = /-(light|dark)(?:\.[\w-]+)?\.(?:svg|png|jpe?g|gif|webp|avif)(?:[?#].*)?$/i;
5
+ /** Which site theme an image file is for, from its `-light`/`-dark` name. */
6
+ export function themeVariantOf(src) {
7
+ if (!src)
8
+ return null;
9
+ const match = THEME_VARIANT_PATTERN.exec(src);
10
+ if (!match)
11
+ return null;
12
+ return match[1].toLowerCase();
13
+ }
14
+ /** Prefix a root-relative public asset path with the site's base path. */
15
+ export function withBasePath(src, basePath) {
16
+ if (!basePath || !src.startsWith('/') || src.startsWith('//'))
17
+ return src;
18
+ if (src === basePath || src.startsWith(`${basePath}/`))
19
+ return src;
20
+ return `${basePath}${src}`;
21
+ }
22
+ /** Whether an image file is an SVG (diagrams are authored as SVG). */
23
+ export function isSvgSource(src) {
24
+ return !!src && /\.svg(?:[?#].*)?$/i.test(src);
25
+ }
package/dist/index.d.ts CHANGED
@@ -2,5 +2,6 @@ export { DocsLayout } from './docs-layout.js';
2
2
  export { DocsPage } from './docs-page.js';
3
3
  export { Mermaid } from './mermaid.js';
4
4
  export { Tab, Tabs } from './tabs.js';
5
+ export { ZoomImage } from './zoom-image.js';
5
6
  export type { BrandingConfig } from './types.js';
6
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACtC,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC"}
package/dist/index.js CHANGED
@@ -2,3 +2,4 @@ export { DocsLayout } from './docs-layout.js';
2
2
  export { DocsPage } from './docs-page.js';
3
3
  export { Mermaid } from './mermaid.js';
4
4
  export { Tab, Tabs } from './tabs.js';
5
+ export { ZoomImage } from './zoom-image.js';
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Mermaid theme variables for the current page, or `undefined` when the site
3
+ * does not define the Fumadocs color tokens (Mermaid then uses its stock
4
+ * theme).
5
+ */
6
+ export declare function siteMermaidThemeVariables(dark: boolean): Record<string, string | boolean> | undefined;
7
+ //# sourceMappingURL=mermaid-theme.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mermaid-theme.d.ts","sourceRoot":"","sources":["../src/mermaid-theme.ts"],"names":[],"mappings":"AAiCA;;;;GAIG;AACH,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,OAAO,GACZ,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,SAAS,CAqD9C"}
@@ -0,0 +1,88 @@
1
+ // Builds Mermaid `base` theme variables from the site's Fumadocs color tokens
2
+ // so diagrams follow the docs site's palette in light and dark mode.
3
+ const TOKENS = {
4
+ background: '--color-fd-background',
5
+ card: '--color-fd-card',
6
+ foreground: '--color-fd-foreground',
7
+ mutedForeground: '--color-fd-muted-foreground',
8
+ muted: '--color-fd-muted',
9
+ secondary: '--color-fd-secondary',
10
+ border: '--color-fd-border',
11
+ primary: '--color-fd-primary',
12
+ };
13
+ // Mermaid derives shades from its theme variables and only understands sRGB
14
+ // hex/rgb input, while sites may define tokens in any CSS color space. Paint
15
+ // the color into a 1x1 canvas and read the sRGB pixel back.
16
+ function toHex(color, ctx) {
17
+ if (!color)
18
+ return undefined;
19
+ ctx.clearRect(0, 0, 1, 1);
20
+ ctx.fillStyle = '#000';
21
+ ctx.fillStyle = color;
22
+ ctx.fillRect(0, 0, 1, 1);
23
+ const [r, g, b, a] = ctx.getImageData(0, 0, 1, 1).data;
24
+ if (a === 0)
25
+ return undefined;
26
+ return `#${[r, g, b].map((n) => n.toString(16).padStart(2, '0')).join('')}`;
27
+ }
28
+ /**
29
+ * Mermaid theme variables for the current page, or `undefined` when the site
30
+ * does not define the Fumadocs color tokens (Mermaid then uses its stock
31
+ * theme).
32
+ */
33
+ export function siteMermaidThemeVariables(dark) {
34
+ if (typeof document === 'undefined')
35
+ return undefined;
36
+ const ctx = document
37
+ .createElement('canvas')
38
+ .getContext('2d', { willReadFrequently: true });
39
+ if (!ctx)
40
+ return undefined;
41
+ const style = getComputedStyle(document.documentElement);
42
+ const c = {};
43
+ for (const [name, prop] of Object.entries(TOKENS)) {
44
+ const hex = toHex(style.getPropertyValue(prop).trim(), ctx);
45
+ if (!hex)
46
+ return undefined;
47
+ c[name] = hex;
48
+ }
49
+ return {
50
+ darkMode: dark,
51
+ fontFamily: getComputedStyle(document.body).fontFamily,
52
+ background: c.card,
53
+ textColor: c.foreground,
54
+ titleColor: c.foreground,
55
+ lineColor: c.mutedForeground,
56
+ primaryColor: c.secondary,
57
+ primaryTextColor: c.foreground,
58
+ primaryBorderColor: c.primary,
59
+ secondaryColor: c.muted,
60
+ secondaryTextColor: c.foreground,
61
+ secondaryBorderColor: c.border,
62
+ tertiaryColor: c.card,
63
+ tertiaryTextColor: c.foreground,
64
+ tertiaryBorderColor: c.border,
65
+ mainBkg: c.secondary,
66
+ nodeBorder: c.primary,
67
+ nodeTextColor: c.foreground,
68
+ clusterBkg: c.muted,
69
+ clusterBorder: c.border,
70
+ edgeLabelBackground: c.card,
71
+ noteBkgColor: c.muted,
72
+ noteTextColor: c.foreground,
73
+ noteBorderColor: c.border,
74
+ actorBkg: c.secondary,
75
+ actorBorder: c.primary,
76
+ actorTextColor: c.foreground,
77
+ actorLineColor: c.mutedForeground,
78
+ signalColor: c.foreground,
79
+ signalTextColor: c.foreground,
80
+ labelBoxBkgColor: c.secondary,
81
+ labelBoxBorderColor: c.border,
82
+ labelTextColor: c.foreground,
83
+ loopTextColor: c.foreground,
84
+ activationBkgColor: c.muted,
85
+ activationBorderColor: c.primary,
86
+ sequenceNumberColor: c.card,
87
+ };
88
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"mermaid.d.ts","sourceRoot":"","sources":["../src/mermaid.tsx"],"names":[],"mappings":"AAKA,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;CACf;AAID,wBAAgB,OAAO,CAAC,EAAE,KAAK,EAAE,EAAE,YAAY,2CA+C9C"}
1
+ {"version":3,"file":"mermaid.d.ts","sourceRoot":"","sources":["../src/mermaid.tsx"],"names":[],"mappings":"AAQA,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,OAAO,CAAC,EAAE,KAAK,EAAE,EAAE,YAAY,2CA4D9C"}
package/dist/mermaid.js CHANGED
@@ -2,7 +2,8 @@
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
3
  import { useTheme } from 'next-themes';
4
4
  import { useEffect, useRef, useState } from 'react';
5
- let mermaidInitialized = false;
5
+ import { siteMermaidThemeVariables } from './mermaid-theme.js';
6
+ import { ZoomFrame } from './zoom-frame.js';
6
7
  export function Mermaid({ chart }) {
7
8
  const containerRef = useRef(null);
8
9
  const [svg, setSvg] = useState('');
@@ -11,19 +12,14 @@ export function Mermaid({ chart }) {
11
12
  let cancelled = false;
12
13
  async function render() {
13
14
  const mermaid = (await import('mermaid')).default;
14
- if (!mermaidInitialized) {
15
- mermaid.initialize({
16
- startOnLoad: false,
17
- theme: resolvedTheme === 'dark' ? 'dark' : 'default',
18
- });
19
- mermaidInitialized = true;
20
- }
21
- else {
22
- mermaid.initialize({
23
- startOnLoad: false,
24
- theme: resolvedTheme === 'dark' ? 'dark' : 'default',
25
- });
26
- }
15
+ const dark = resolvedTheme === 'dark';
16
+ const themeVariables = siteMermaidThemeVariables(dark);
17
+ mermaid.initialize({
18
+ startOnLoad: false,
19
+ ...(themeVariables
20
+ ? { theme: 'base', themeVariables }
21
+ : { theme: dark ? 'dark' : 'default' }),
22
+ });
27
23
  const id = `mermaid-${Math.random().toString(36).slice(2, 9)}`;
28
24
  const { svg: rendered } = await mermaid.render(id, chart);
29
25
  if (!cancelled) {
@@ -35,7 +31,11 @@ export function Mermaid({ chart }) {
35
31
  cancelled = true;
36
32
  };
37
33
  }, [chart, resolvedTheme]);
38
- return (_jsx("div", { ref: containerRef, className: 'mermaid',
39
- // oxlint-disable-next-line react/no-danger -- mermaid renders SVG from trusted chart definitions
40
- dangerouslySetInnerHTML: { __html: svg } }));
34
+ return (_jsx(ZoomFrame, { label: 'Diagram', disabled: !svg, zoomed: _jsx("div", { className: 'mermaid',
35
+ // oxlint-disable-next-line react/no-danger -- same trusted SVG as above
36
+ dangerouslySetInnerHTML: {
37
+ __html: svg.replace(/<svg\b([^>]*?)\sstyle="[^"]*"/, '<svg$1 style="width:100%;height:auto;max-width:none"'),
38
+ } }), children: _jsx("div", { ref: containerRef, className: 'mermaid',
39
+ // oxlint-disable-next-line react/no-danger -- mermaid renders SVG from trusted chart definitions
40
+ dangerouslySetInnerHTML: { __html: svg } }) }));
41
41
  }
@@ -0,0 +1,17 @@
1
+ import { type ReactNode } from 'react';
2
+ export interface ZoomFrameProps {
3
+ /** Accessible name for the enlarge control, e.g. the diagram's alt text. */
4
+ label: string;
5
+ /** The inline, column-width rendering. */
6
+ children: ReactNode;
7
+ /** What to show in the full-screen view. */
8
+ zoomed: ReactNode;
9
+ disabled?: boolean;
10
+ }
11
+ /**
12
+ * Click-to-enlarge wrapper for diagrams. The inline view fits the column; the
13
+ * full-screen view is a native modal dialog that scrolls in both directions
14
+ * and closes on Escape, the close button, or a click.
15
+ */
16
+ export declare function ZoomFrame({ label, children, zoomed, disabled, }: ZoomFrameProps): import("react/jsx-runtime").JSX.Element;
17
+ //# sourceMappingURL=zoom-frame.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"zoom-frame.d.ts","sourceRoot":"","sources":["../src/zoom-frame.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,SAAS,EAA+B,MAAM,OAAO,CAAC;AAGpE,MAAM,WAAW,cAAc;IAC7B,4EAA4E;IAC5E,KAAK,EAAE,MAAM,CAAC;IACd,0CAA0C;IAC1C,QAAQ,EAAE,SAAS,CAAC;IACpB,4CAA4C;IAC5C,MAAM,EAAE,SAAS,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAQD;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,EACxB,KAAK,EACL,QAAQ,EACR,MAAM,EACN,QAAQ,GACT,EAAE,cAAc,2CAiHhB"}
@@ -0,0 +1,83 @@
1
+ 'use client';
2
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useEffect, useRef, useState } from 'react';
4
+ import { createPortal } from 'react-dom';
5
+ // The full-screen view renders the diagram at least this wide, so labels stay
6
+ // legible on a phone; the reader pans to see the rest. Wider screens fit the
7
+ // diagram to the window, up to the maximum.
8
+ const ZOOMED_MIN_WIDTH = 900;
9
+ const ZOOMED_MAX_WIDTH = 1400;
10
+ /**
11
+ * Click-to-enlarge wrapper for diagrams. The inline view fits the column; the
12
+ * full-screen view is a native modal dialog that scrolls in both directions
13
+ * and closes on Escape, the close button, or a click.
14
+ */
15
+ export function ZoomFrame({ label, children, zoomed, disabled, }) {
16
+ const dialogRef = useRef(null);
17
+ // The dialog lives in a portal on <body>: rendered in place it would sit
18
+ // inside a Markdown <p>, which the HTML parser splits, breaking hydration.
19
+ const [mounted, setMounted] = useState(false);
20
+ useEffect(() => setMounted(true), []);
21
+ const open = () => {
22
+ const dialog = dialogRef.current;
23
+ if (!dialog || disabled)
24
+ return;
25
+ dialog.showModal();
26
+ dialog.scrollLeft = (dialog.scrollWidth - dialog.clientWidth) / 2;
27
+ dialog.scrollTop = 0;
28
+ };
29
+ const close = () => dialogRef.current?.close();
30
+ return (_jsxs(_Fragment, { children: [_jsxs("button", { type: 'button', onClick: open, disabled: disabled, "aria-label": `Enlarge: ${label}`, title: 'Enlarge', style: {
31
+ position: 'relative',
32
+ display: 'block',
33
+ width: '100%',
34
+ padding: 0,
35
+ border: 0,
36
+ background: 'none',
37
+ color: 'inherit',
38
+ font: 'inherit',
39
+ textAlign: 'inherit',
40
+ cursor: disabled ? 'default' : 'zoom-in',
41
+ }, children: [children, !disabled && (_jsx("span", { "aria-hidden": 'true', style: {
42
+ position: 'absolute',
43
+ top: '0.5rem',
44
+ right: '0.5rem',
45
+ padding: '0.15rem 0.5rem',
46
+ borderRadius: '9999px',
47
+ border: '1px solid var(--color-fd-border, #ccc)',
48
+ background: 'var(--color-fd-card, #fff)',
49
+ color: 'var(--color-fd-muted-foreground, #555)',
50
+ fontSize: '0.75rem',
51
+ lineHeight: 1.4,
52
+ }, children: "\u2922 Enlarge" }))] }), mounted &&
53
+ createPortal(_jsxs("dialog", { ref: dialogRef, "aria-label": label, onClick: close, style: {
54
+ width: '100vw',
55
+ maxWidth: '100vw',
56
+ height: '100dvh',
57
+ maxHeight: '100dvh',
58
+ margin: 0,
59
+ padding: '3rem 1rem 1rem',
60
+ border: 0,
61
+ background: 'var(--color-fd-background, #fff)',
62
+ color: 'inherit',
63
+ overflow: 'auto',
64
+ cursor: 'zoom-out',
65
+ }, children: [_jsx("button", { type: 'button', onClick: close, "aria-label": 'Close enlarged view', style: {
66
+ position: 'fixed',
67
+ top: '0.75rem',
68
+ right: '0.75rem',
69
+ width: '2.25rem',
70
+ height: '2.25rem',
71
+ borderRadius: '9999px',
72
+ border: '1px solid var(--color-fd-border, #ccc)',
73
+ background: 'var(--color-fd-card, #fff)',
74
+ color: 'inherit',
75
+ fontSize: '1.25rem',
76
+ lineHeight: 1,
77
+ cursor: 'pointer',
78
+ }, children: "\u00D7" }), _jsx("div", { style: {
79
+ width: `max(100%, ${ZOOMED_MIN_WIDTH}px)`,
80
+ maxWidth: `${ZOOMED_MAX_WIDTH}px`,
81
+ margin: '0 auto',
82
+ }, children: zoomed })] }), document.body)] }));
83
+ }
@@ -0,0 +1,11 @@
1
+ import type { ComponentProps } from 'react';
2
+ type ZoomImageProps = ComponentProps<'img'>;
3
+ /**
4
+ * Markdown image renderer; map it as `img` in the MDX components. SVG
5
+ * diagrams open in a full-screen view that pans on small screens, other
6
+ * images use Fumadocs ImageZoom, and a `-light` / `-dark` file pair shows only
7
+ * the file that matches the site theme.
8
+ */
9
+ export declare function ZoomImage(props: ZoomImageProps): import("react/jsx-runtime").JSX.Element;
10
+ export {};
11
+ //# sourceMappingURL=zoom-image.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"zoom-image.d.ts","sourceRoot":"","sources":["../src/zoom-image.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAa,MAAM,OAAO,CAAC;AAcvD,KAAK,cAAc,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;AAoB5C;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,2CA0C9C"}
@@ -0,0 +1,49 @@
1
+ 'use client';
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { ImageZoom } from 'fumadocs-ui/components/image-zoom';
4
+ import { isSvgSource, themeVariantOf, withBasePath, } from './image-src.js';
5
+ import { ZoomFrame } from './zoom-frame.js';
6
+ // Set by `@open-agent-toolkit/docs-config` when the site has a basePath.
7
+ const BASE_PATH = process.env.NEXT_PUBLIC_BASE_PATH ?? '';
8
+ function srcToString(src) {
9
+ if (typeof src === 'string')
10
+ return src;
11
+ if (src && typeof src === 'object') {
12
+ if ('default' in src)
13
+ return src.default.src;
14
+ if ('src' in src)
15
+ return src.src;
16
+ }
17
+ return undefined;
18
+ }
19
+ const VARIANT_CLASS = {
20
+ light: 'block dark:hidden',
21
+ dark: 'hidden dark:block',
22
+ };
23
+ /**
24
+ * Markdown image renderer; map it as `img` in the MDX components. SVG
25
+ * diagrams open in a full-screen view that pans on small screens, other
26
+ * images use Fumadocs ImageZoom, and a `-light` / `-dark` file pair shows only
27
+ * the file that matches the site theme.
28
+ */
29
+ export function ZoomImage(props) {
30
+ const raw = srcToString(props.src);
31
+ const variant = themeVariantOf(raw);
32
+ const src = typeof props.src === 'string'
33
+ ? withBasePath(props.src, BASE_PATH)
34
+ : props.src;
35
+ let node;
36
+ if (isSvgSource(raw)) {
37
+ // Diagrams use the full-screen pannable view; ImageZoom only scales an
38
+ // image to the viewport, which leaves diagram text unreadable on a phone.
39
+ const url = srcToString(src) ?? '';
40
+ const { src: _src, alt = '', className, ...rest } = props;
41
+ node = (_jsx(ZoomFrame, { label: alt || 'Diagram', zoomed: _jsx("img", { src: url, alt: alt, style: { display: 'block', width: '100%' } }), children: _jsx("img", { ...rest, src: url, alt: alt, className: className, style: { display: 'block', width: '100%', height: 'auto' } }) }));
42
+ }
43
+ else {
44
+ node = _jsx(ImageZoom, { ...{ ...props, src } });
45
+ }
46
+ if (!variant)
47
+ return node;
48
+ return (_jsx("span", { className: VARIANT_CLASS[variant], "data-theme-variant": variant, children: node }));
49
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-agent-toolkit/docs-theme",
3
- "version": "0.3.14",
3
+ "version": "0.3.15",
4
4
  "private": false,
5
5
  "description": "Theme components for OAT documentation sites",
6
6
  "homepage": "https://github.com/voxmedia/open-agent-toolkit/tree/main/packages/docs-theme",
@@ -43,7 +43,8 @@
43
43
  "react": "^19.1.0",
44
44
  "react-dom": "^19.1.0",
45
45
  "typescript": "npm:@typescript/typescript6@^6.0.2",
46
- "typescript-7": "npm:typescript@^7.0.2"
46
+ "typescript-7": "npm:typescript@^7.0.2",
47
+ "vitest": "^4.0.18"
47
48
  },
48
49
  "peerDependencies": {
49
50
  "fumadocs-core": ">=16.0.0",
@@ -64,6 +65,8 @@
64
65
  "format:fix": "oxfmt .",
65
66
  "lint": "oxlint . && oxlint --type-aware -A all -D typescript/no-floating-promises -D typescript/no-misused-promises --ignore-pattern '**/*.test.ts' --ignore-pattern '**/*.spec.ts' .",
66
67
  "lint:fix": "oxlint --fix . && oxlint --type-aware -A all -D typescript/no-floating-promises -D typescript/no-misused-promises --ignore-pattern '**/*.test.ts' --ignore-pattern '**/*.spec.ts' .",
68
+ "test": "vitest run",
69
+ "test:watch": "vitest",
67
70
  "type-check": "tsc --noEmit"
68
71
  }
69
72
  }