@open-agent-toolkit/docs-theme 0.3.13 → 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 +16 -0
- package/dist/image-src.d.ts +8 -0
- package/dist/image-src.d.ts.map +1 -0
- package/dist/image-src.js +25 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/mermaid-theme.d.ts +7 -0
- package/dist/mermaid-theme.d.ts.map +1 -0
- package/dist/mermaid-theme.js +88 -0
- package/dist/mermaid.d.ts.map +1 -1
- package/dist/mermaid.js +17 -17
- package/dist/zoom-frame.d.ts +17 -0
- package/dist/zoom-frame.d.ts.map +1 -0
- package/dist/zoom-frame.js +83 -0
- package/dist/zoom-image.d.ts +11 -0
- package/dist/zoom-image.d.ts.map +1 -0
- package/dist/zoom-image.js +49 -0
- package/package.json +5 -2
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
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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
|
@@ -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
|
+
}
|
package/dist/mermaid.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mermaid.d.ts","sourceRoot":"","sources":["../src/mermaid.tsx"],"names":[],"mappings":"
|
|
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
|
-
|
|
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
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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(
|
|
39
|
-
|
|
40
|
-
|
|
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.
|
|
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
|
}
|