@situaction/traquiste-docs-kit 0.0.0-stage → 1.0.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.
- package/CHANGELOG.md +18 -0
- package/README.md +252 -2
- package/client.d.ts +7 -0
- package/dist/app/ColorModeContext.d.ts +15 -0
- package/dist/app/ColorModeContext.d.ts.map +1 -0
- package/dist/app/ColorModeContext.js +58 -0
- package/dist/app/config.d.ts +69 -0
- package/dist/app/config.d.ts.map +1 -0
- package/dist/app/config.js +35 -0
- package/dist/app/createDocsApp.d.ts +9 -0
- package/dist/app/createDocsApp.d.ts.map +1 -0
- package/dist/app/createDocsApp.js +53 -0
- package/dist/components/Callout.d.ts +11 -0
- package/dist/components/Callout.d.ts.map +1 -0
- package/dist/components/Callout.js +28 -0
- package/dist/components/CodeBlock.d.ts +12 -0
- package/dist/components/CodeBlock.d.ts.map +1 -0
- package/dist/components/CodeBlock.js +60 -0
- package/dist/components/DeviceFrame.d.ts +17 -0
- package/dist/components/DeviceFrame.d.ts.map +1 -0
- package/dist/components/DeviceFrame.js +74 -0
- package/dist/components/LiveEditor.d.ts +10 -0
- package/dist/components/LiveEditor.d.ts.map +1 -0
- package/dist/components/LiveEditor.js +231 -0
- package/dist/components/PropsTable.d.ts +16 -0
- package/dist/components/PropsTable.d.ts.map +1 -0
- package/dist/components/PropsTable.js +60 -0
- package/dist/components/layout/ComponentSearch.d.ts +2 -0
- package/dist/components/layout/ComponentSearch.d.ts.map +1 -0
- package/dist/components/layout/ComponentSearch.js +156 -0
- package/dist/components/layout/Layout.d.ts +8 -0
- package/dist/components/layout/Layout.d.ts.map +1 -0
- package/dist/components/layout/Layout.js +109 -0
- package/dist/components/layout/NotFound.d.ts +2 -0
- package/dist/components/layout/NotFound.d.ts.map +1 -0
- package/dist/components/layout/NotFound.js +36 -0
- package/dist/components/layout/Sidebar.d.ts +2 -0
- package/dist/components/layout/Sidebar.d.ts.map +1 -0
- package/dist/components/layout/Sidebar.js +88 -0
- package/dist/components/layout/TableOfContents.d.ts +10 -0
- package/dist/components/layout/TableOfContents.d.ts.map +1 -0
- package/dist/components/layout/TableOfContents.js +48 -0
- package/dist/hooks/useCopy.d.ts +5 -0
- package/dist/hooks/useCopy.d.ts.map +1 -0
- package/dist/hooks/useCopy.js +19 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/pages/DocPage.d.ts +26 -0
- package/dist/pages/DocPage.d.ts.map +1 -0
- package/dist/pages/DocPage.js +23 -0
- package/dist/pages/createComponentPage.d.ts +32 -0
- package/dist/pages/createComponentPage.d.ts.map +1 -0
- package/dist/pages/createComponentPage.js +149 -0
- package/dist/pages/createScreenPage.d.ts +33 -0
- package/dist/pages/createScreenPage.d.ts.map +1 -0
- package/dist/pages/createScreenPage.js +124 -0
- package/dist/styles/docs.css +177 -0
- package/dist/styles/pageStyles.d.ts +45 -0
- package/dist/styles/pageStyles.d.ts.map +1 -0
- package/dist/styles/pageStyles.js +46 -0
- package/dist/vite/extractProps.d.ts +8 -0
- package/dist/vite/extractProps.d.ts.map +1 -0
- package/dist/vite/extractProps.js +79 -0
- package/dist/vite/index.d.ts +18 -0
- package/dist/vite/index.d.ts.map +1 -0
- package/dist/vite/index.js +73 -0
- package/package.json +111 -4
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/** Static code block with a copy button — no syntax highlighting */
|
|
3
|
+
import { useCopy } from '../hooks/useCopy';
|
|
4
|
+
const S = {
|
|
5
|
+
wrapper: {
|
|
6
|
+
backgroundColor: '#0d1117',
|
|
7
|
+
border: '1px solid var(--docs-border)',
|
|
8
|
+
borderRadius: 8,
|
|
9
|
+
margin: '0 0 20px',
|
|
10
|
+
overflow: 'hidden',
|
|
11
|
+
},
|
|
12
|
+
header: {
|
|
13
|
+
display: 'flex',
|
|
14
|
+
alignItems: 'center',
|
|
15
|
+
justifyContent: 'space-between',
|
|
16
|
+
gap: 12,
|
|
17
|
+
padding: '6px 10px 6px 16px',
|
|
18
|
+
borderBottom: '1px solid #21262d',
|
|
19
|
+
},
|
|
20
|
+
label: {
|
|
21
|
+
fontFamily: 'ui-monospace, Consolas, monospace',
|
|
22
|
+
fontSize: 11,
|
|
23
|
+
color: '#8b949e',
|
|
24
|
+
letterSpacing: '0.02em',
|
|
25
|
+
},
|
|
26
|
+
button: (copied) => ({
|
|
27
|
+
fontSize: 11,
|
|
28
|
+
fontWeight: 500,
|
|
29
|
+
padding: '3px 8px',
|
|
30
|
+
border: `1px solid ${copied ? '#238636' : '#30363d'}`,
|
|
31
|
+
borderRadius: 5,
|
|
32
|
+
cursor: 'pointer',
|
|
33
|
+
backgroundColor: copied ? '#0d1117' : '#21262d',
|
|
34
|
+
color: copied ? '#3fb950' : '#8b949e',
|
|
35
|
+
fontFamily: 'inherit',
|
|
36
|
+
whiteSpace: 'nowrap',
|
|
37
|
+
}),
|
|
38
|
+
pre: {
|
|
39
|
+
margin: 0,
|
|
40
|
+
padding: '14px 16px',
|
|
41
|
+
overflowX: 'auto',
|
|
42
|
+
fontFamily: 'ui-monospace, Consolas, monospace',
|
|
43
|
+
fontSize: 13,
|
|
44
|
+
lineHeight: 1.6,
|
|
45
|
+
color: '#e6edf3',
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
/** Removes surrounding blank lines and the indentation shared by all lines (template literals in JSX) */
|
|
49
|
+
export function dedent(code) {
|
|
50
|
+
const lines = code.replace(/^\s*\n/, '').replace(/\n\s*$/, '').split('\n');
|
|
51
|
+
const indents = lines.filter((l) => l.trim()).map((l) => l.match(/^\s*/)[0].length);
|
|
52
|
+
const min = indents.length ? Math.min(...indents) : 0;
|
|
53
|
+
return lines.map((l) => l.slice(min)).join('\n');
|
|
54
|
+
}
|
|
55
|
+
export function CodeBlock({ children, language, title }) {
|
|
56
|
+
const { copied, copy } = useCopy();
|
|
57
|
+
const code = dedent(children);
|
|
58
|
+
const label = title ?? language;
|
|
59
|
+
return (_jsxs("div", { style: S.wrapper, children: [_jsxs("div", { style: { ...S.header, justifyContent: label ? 'space-between' : 'flex-end' }, children: [label && _jsx("span", { style: S.label, children: label }), _jsx("button", { type: "button", style: S.button(copied), onClick: () => copy(code), "aria-label": "Copier le code", children: copied ? '✓ Copié' : 'Copier' })] }), _jsx("pre", { style: S.pre, children: _jsx("code", { children: code }) })] }));
|
|
60
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/** Device mock-ups around demos and full screens: a phone (mobile library) or a browser window (web library) */
|
|
2
|
+
import type { ReactNode } from 'react';
|
|
3
|
+
export type DeviceType = 'phone' | 'browser';
|
|
4
|
+
export interface DeviceFrameProps {
|
|
5
|
+
/** Mock-up to draw (default 'phone') */
|
|
6
|
+
device?: DeviceType;
|
|
7
|
+
/** Screen width in px — phone 390, browser 1024 by default; never wider than the page */
|
|
8
|
+
width?: number;
|
|
9
|
+
/** Screen height in px — omit to fit the content (demos); set it for full screens, which then scroll inside */
|
|
10
|
+
height?: number;
|
|
11
|
+
/** Address shown in the browser bar */
|
|
12
|
+
url?: string;
|
|
13
|
+
children: ReactNode;
|
|
14
|
+
}
|
|
15
|
+
/** Phone or browser mock-up — follows the docs' light / dark mode */
|
|
16
|
+
export declare function DeviceFrame({ device, ...props }: DeviceFrameProps): import("react").JSX.Element;
|
|
17
|
+
//# sourceMappingURL=DeviceFrame.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DeviceFrame.d.ts","sourceRoot":"","sources":["../../src/components/DeviceFrame.tsx"],"names":[],"mappings":"AAAA,gHAAgH;AAChH,OAAO,KAAK,EAAiB,SAAS,EAAE,MAAM,OAAO,CAAA;AAGrD,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,SAAS,CAAA;AAE5C,MAAM,WAAW,gBAAgB;IAC/B,wCAAwC;IACxC,MAAM,CAAC,EAAE,UAAU,CAAA;IACnB,yFAAyF;IACzF,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,+GAA+G;IAC/G,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,uCAAuC;IACvC,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,SAAS,CAAA;CACpB;AAsHD,qEAAqE;AACrE,wBAAgB,WAAW,CAAC,EAAE,MAAgB,EAAE,GAAG,KAAK,EAAE,EAAE,gBAAgB,+BAE3E"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useColorMode } from '../app/ColorModeContext';
|
|
3
|
+
const PHONE_WIDTH = 390;
|
|
4
|
+
const BROWSER_WIDTH = 1024;
|
|
5
|
+
/** Screen area: fixed height scrolls like a real device, otherwise grows with the content */
|
|
6
|
+
function screenStyle(height, background) {
|
|
7
|
+
return height
|
|
8
|
+
? {
|
|
9
|
+
height,
|
|
10
|
+
overflowY: 'auto',
|
|
11
|
+
display: 'flex',
|
|
12
|
+
flexDirection: 'column',
|
|
13
|
+
position: 'relative',
|
|
14
|
+
backgroundColor: background,
|
|
15
|
+
}
|
|
16
|
+
: { position: 'relative', overflow: 'hidden', backgroundColor: background };
|
|
17
|
+
}
|
|
18
|
+
function PhoneFrame({ width, height, children }) {
|
|
19
|
+
const isDark = useColorMode().mode === 'dark';
|
|
20
|
+
const chrome = isDark ? '#000' : '#f2f2f2';
|
|
21
|
+
return (_jsx("div", { "data-device": "phone", style: { position: 'relative', width: width ?? PHONE_WIDTH, maxWidth: '100%' }, children: _jsxs("div", { style: {
|
|
22
|
+
position: 'relative',
|
|
23
|
+
borderRadius: 48,
|
|
24
|
+
border: `8px solid ${isDark ? '#2a2a2a' : '#1a1a1a'}`,
|
|
25
|
+
boxShadow: isDark
|
|
26
|
+
? '0 24px 64px rgba(0,0,0,0.6), inset 0 0 0 1px rgba(255,255,255,0.05)'
|
|
27
|
+
: '0 24px 64px rgba(0,0,0,0.25), inset 0 0 0 1px rgba(255,255,255,0.1)',
|
|
28
|
+
backgroundColor: chrome,
|
|
29
|
+
overflow: 'hidden',
|
|
30
|
+
}, children: [_jsx("div", { style: { height: 44, backgroundColor: chrome, display: 'flex', alignItems: 'center', justifyContent: 'center' }, children: _jsx("div", { style: { width: 120, height: 34, borderRadius: 20, backgroundColor: '#1a1a1a' } }) }), _jsx("div", { style: screenStyle(height, chrome), children: children }), _jsx("div", { style: { height: 34, backgroundColor: chrome, display: 'flex', alignItems: 'center', justifyContent: 'center' }, children: _jsx("div", { style: {
|
|
31
|
+
width: 134,
|
|
32
|
+
height: 5,
|
|
33
|
+
borderRadius: 3,
|
|
34
|
+
backgroundColor: isDark ? 'rgba(255,255,255,0.3)' : 'rgba(0,0,0,0.2)',
|
|
35
|
+
} }) })] }) }));
|
|
36
|
+
}
|
|
37
|
+
function BrowserFrame({ width, height, url, children }) {
|
|
38
|
+
const isDark = useColorMode().mode === 'dark';
|
|
39
|
+
return (_jsxs("div", { "data-device": "browser", style: {
|
|
40
|
+
width: width ?? BROWSER_WIDTH,
|
|
41
|
+
maxWidth: '100%',
|
|
42
|
+
borderRadius: 10,
|
|
43
|
+
border: `1px solid ${isDark ? '#3f3f46' : '#d4d4d8'}`,
|
|
44
|
+
boxShadow: isDark ? '0 24px 64px rgba(0,0,0,0.6)' : '0 24px 64px rgba(0,0,0,0.18)',
|
|
45
|
+
overflow: 'hidden',
|
|
46
|
+
}, children: [_jsxs("div", { style: {
|
|
47
|
+
height: 40,
|
|
48
|
+
display: 'flex',
|
|
49
|
+
alignItems: 'center',
|
|
50
|
+
gap: 12,
|
|
51
|
+
padding: '0 14px',
|
|
52
|
+
backgroundColor: isDark ? '#1f1f23' : '#e9e9ec',
|
|
53
|
+
borderBottom: `1px solid ${isDark ? '#3f3f46' : '#d4d4d8'}`,
|
|
54
|
+
}, children: [_jsx("div", { style: { display: 'flex', gap: 7 }, "aria-hidden": true, children: ['#ff5f57', '#febc2e', '#28c840'].map((color) => (_jsx("span", { style: { width: 11, height: 11, borderRadius: '50%', backgroundColor: color } }, color))) }), _jsx("div", { style: {
|
|
55
|
+
flex: 1,
|
|
56
|
+
maxWidth: 480,
|
|
57
|
+
margin: '0 auto',
|
|
58
|
+
height: 24,
|
|
59
|
+
borderRadius: 6,
|
|
60
|
+
display: 'flex',
|
|
61
|
+
alignItems: 'center',
|
|
62
|
+
justifyContent: 'center',
|
|
63
|
+
fontSize: 12,
|
|
64
|
+
color: isDark ? '#a1a1aa' : '#71717a',
|
|
65
|
+
backgroundColor: isDark ? '#2a2a2e' : '#ffffff',
|
|
66
|
+
overflow: 'hidden',
|
|
67
|
+
whiteSpace: 'nowrap',
|
|
68
|
+
textOverflow: 'ellipsis',
|
|
69
|
+
}, children: url }), _jsx("div", { style: { width: 47 }, "aria-hidden": true })] }), _jsx("div", { style: screenStyle(height, isDark ? '#0f0f10' : '#ffffff'), children: children })] }));
|
|
70
|
+
}
|
|
71
|
+
/** Phone or browser mock-up — follows the docs' light / dark mode */
|
|
72
|
+
export function DeviceFrame({ device = 'phone', ...props }) {
|
|
73
|
+
return device === 'browser' ? _jsx(BrowserFrame, { ...props }) : _jsx(PhoneFrame, { ...props });
|
|
74
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import ReactForScope from 'react';
|
|
2
|
+
interface LiveEditorProps {
|
|
3
|
+
title: string;
|
|
4
|
+
initialCode: string;
|
|
5
|
+
scope: Record<string, unknown>;
|
|
6
|
+
phoneFrame?: boolean;
|
|
7
|
+
}
|
|
8
|
+
export default function LiveEditor({ title, initialCode, scope, phoneFrame }: LiveEditorProps): ReactForScope.JSX.Element;
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=LiveEditor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LiveEditor.d.ts","sourceRoot":"","sources":["../../src/components/LiveEditor.tsx"],"names":[],"mappings":"AAGA,OAAO,aAAa,MAAM,OAAO,CAAA;AAsBjC,UAAU,eAAe;IACvB,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,CAAA;IACnB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC9B,UAAU,CAAC,EAAE,OAAO,CAAA;CACrB;AAsGD,MAAM,CAAC,OAAO,UAAU,UAAU,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,eAAe,6BA8M5F"}
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/** Demo card: live-editable preview powered by @babel/standalone */
|
|
3
|
+
import { Component, useState, useEffect, useLayoutEffect, useRef, useCallback } from 'react';
|
|
4
|
+
import ReactForScope from 'react';
|
|
5
|
+
import Editor from '@monaco-editor/react';
|
|
6
|
+
import { useDocsConfig } from '../app/config';
|
|
7
|
+
import { DeviceFrame } from './DeviceFrame';
|
|
8
|
+
import { useColorMode } from '../app/ColorModeContext';
|
|
9
|
+
let babelCache = null;
|
|
10
|
+
let babelLoading = null;
|
|
11
|
+
function loadBabel() {
|
|
12
|
+
if (babelCache)
|
|
13
|
+
return Promise.resolve(babelCache);
|
|
14
|
+
if (!babelLoading) {
|
|
15
|
+
babelLoading = import('@babel/standalone').then((m) => {
|
|
16
|
+
babelCache = m;
|
|
17
|
+
return m;
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
return babelLoading;
|
|
21
|
+
}
|
|
22
|
+
const S = {
|
|
23
|
+
card: {
|
|
24
|
+
border: '1px solid var(--docs-border)',
|
|
25
|
+
borderRadius: 12,
|
|
26
|
+
overflow: 'hidden',
|
|
27
|
+
marginBottom: 20,
|
|
28
|
+
boxShadow: 'var(--docs-shadow-sm)',
|
|
29
|
+
},
|
|
30
|
+
header: {
|
|
31
|
+
padding: '10px 14px',
|
|
32
|
+
borderBottom: '1px solid var(--docs-border)',
|
|
33
|
+
backgroundColor: 'var(--docs-surface)',
|
|
34
|
+
display: 'flex',
|
|
35
|
+
justifyContent: 'space-between',
|
|
36
|
+
alignItems: 'center',
|
|
37
|
+
gap: 8,
|
|
38
|
+
},
|
|
39
|
+
title: {
|
|
40
|
+
fontSize: 12,
|
|
41
|
+
fontWeight: 600,
|
|
42
|
+
color: 'var(--docs-text-muted)',
|
|
43
|
+
letterSpacing: '0.03em',
|
|
44
|
+
textTransform: 'uppercase',
|
|
45
|
+
flex: 1,
|
|
46
|
+
},
|
|
47
|
+
actions: { display: 'flex', gap: 6, alignItems: 'center' },
|
|
48
|
+
btn: {
|
|
49
|
+
fontSize: 12,
|
|
50
|
+
fontWeight: 500,
|
|
51
|
+
padding: '4px 10px',
|
|
52
|
+
border: '1px solid var(--docs-border)',
|
|
53
|
+
borderRadius: 6,
|
|
54
|
+
cursor: 'pointer',
|
|
55
|
+
backgroundColor: 'var(--docs-bg)',
|
|
56
|
+
color: 'var(--docs-text-secondary)',
|
|
57
|
+
fontFamily: 'inherit',
|
|
58
|
+
whiteSpace: 'nowrap',
|
|
59
|
+
},
|
|
60
|
+
btnCopied: {
|
|
61
|
+
color: 'var(--docs-badge-default-color)',
|
|
62
|
+
borderColor: 'var(--docs-badge-default-bg)',
|
|
63
|
+
backgroundColor: 'var(--docs-badge-default-bg)',
|
|
64
|
+
},
|
|
65
|
+
loading: { fontSize: 13, color: 'var(--docs-text-disabled)', fontStyle: 'italic' },
|
|
66
|
+
error: {
|
|
67
|
+
color: 'var(--docs-badge-name-color)',
|
|
68
|
+
fontSize: 12,
|
|
69
|
+
fontFamily: 'ui-monospace, Consolas, monospace',
|
|
70
|
+
whiteSpace: 'pre-wrap',
|
|
71
|
+
margin: 0,
|
|
72
|
+
maxWidth: '100%',
|
|
73
|
+
overflowX: 'auto',
|
|
74
|
+
lineHeight: 1.6,
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
/**
|
|
78
|
+
* Keeps a broken demo inside its own card.
|
|
79
|
+
*
|
|
80
|
+
* `evalCode` only catches what throws while the snippet is *evaluated*; anything that throws while
|
|
81
|
+
* React renders the returned element escapes it, and with no boundary in the tree that unmounts the
|
|
82
|
+
* whole docs app — a single bad component reads as "the docs crashed" instead of pointing at itself.
|
|
83
|
+
*
|
|
84
|
+
* Keyed on the source in `LiveEditor` below, so editing the code clears a previous failure.
|
|
85
|
+
*/
|
|
86
|
+
class DemoBoundary extends Component {
|
|
87
|
+
state = { message: null };
|
|
88
|
+
static getDerivedStateFromError(error) {
|
|
89
|
+
return { message: error instanceof Error ? error.message : String(error) };
|
|
90
|
+
}
|
|
91
|
+
componentDidCatch(error, info) {
|
|
92
|
+
// Kept on the console: the stack is what actually locates the faulty component
|
|
93
|
+
console.error('[docs] demo render failed', error, info.componentStack);
|
|
94
|
+
}
|
|
95
|
+
render() {
|
|
96
|
+
if (this.state.message !== null) {
|
|
97
|
+
return _jsx("pre", { style: S.error, children: `Erreur de rendu\n${this.state.message}` });
|
|
98
|
+
}
|
|
99
|
+
return this.props.children;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/** 6-dot drag indicator (2 cols × 3 rows) */
|
|
103
|
+
function DragDots({ active }) {
|
|
104
|
+
const color = active ? 'var(--docs-accent)' : 'var(--docs-text-muted)';
|
|
105
|
+
const dot = { width: 2, height: 2, borderRadius: '50%', backgroundColor: color };
|
|
106
|
+
return (_jsx("div", { style: { display: 'flex', flexDirection: 'column', gap: 3 }, children: [0, 1, 2].map((i) => (_jsxs("div", { style: { display: 'flex', gap: 3 }, children: [_jsx("div", { style: dot }), _jsx("div", { style: dot })] }, i))) }));
|
|
107
|
+
}
|
|
108
|
+
export default function LiveEditor({ title, initialCode, scope, phoneFrame }) {
|
|
109
|
+
const Wrapper = useDocsConfig().wrapper;
|
|
110
|
+
const [code, setCode] = useState(initialCode);
|
|
111
|
+
const [showCode, setShowCode] = useState(false);
|
|
112
|
+
const [preview, setPreview] = useState(null);
|
|
113
|
+
const [error, setError] = useState(null);
|
|
114
|
+
const [copied, setCopied] = useState(false);
|
|
115
|
+
const [previewWidth, setPreviewWidth] = useState(null);
|
|
116
|
+
const [isDragging, setIsDragging] = useState(false);
|
|
117
|
+
const { mode } = useColorMode();
|
|
118
|
+
const wrapperRef = useRef(null);
|
|
119
|
+
const scopeRef = useRef(scope);
|
|
120
|
+
// Latest scope for the debounced compile, synced before any timer can fire
|
|
121
|
+
useLayoutEffect(() => {
|
|
122
|
+
scopeRef.current = scope;
|
|
123
|
+
}, [scope]);
|
|
124
|
+
const debounceRef = useRef(undefined);
|
|
125
|
+
function handleMouseDown(e) {
|
|
126
|
+
e.preventDefault();
|
|
127
|
+
const startX = e.clientX;
|
|
128
|
+
const startWidth = wrapperRef.current?.offsetWidth ?? 600;
|
|
129
|
+
setIsDragging(true);
|
|
130
|
+
function onMouseMove(ev) {
|
|
131
|
+
const next = Math.max(280, Math.min(1000, startWidth + (ev.clientX - startX)));
|
|
132
|
+
setPreviewWidth(next);
|
|
133
|
+
}
|
|
134
|
+
function onMouseUp() {
|
|
135
|
+
setIsDragging(false);
|
|
136
|
+
window.removeEventListener('mousemove', onMouseMove);
|
|
137
|
+
window.removeEventListener('mouseup', onMouseUp);
|
|
138
|
+
}
|
|
139
|
+
window.addEventListener('mousemove', onMouseMove);
|
|
140
|
+
window.addEventListener('mouseup', onMouseUp);
|
|
141
|
+
}
|
|
142
|
+
const evalCode = useCallback((src) => {
|
|
143
|
+
loadBabel()
|
|
144
|
+
.then((Babel) => {
|
|
145
|
+
const fullScope = { React: ReactForScope, ...scopeRef.current };
|
|
146
|
+
const keys = Object.keys(fullScope);
|
|
147
|
+
const wrapped = `const { ${keys.join(', ')} } = __scope__;\nreturn (${src});`;
|
|
148
|
+
const result = Babel.transform(wrapped, {
|
|
149
|
+
presets: ['react'],
|
|
150
|
+
filename: 'preview.jsx',
|
|
151
|
+
parserOpts: { allowReturnOutsideFunction: true },
|
|
152
|
+
});
|
|
153
|
+
if (!result.code)
|
|
154
|
+
throw new Error('Transpilation failed');
|
|
155
|
+
const fn = new Function('__scope__', result.code);
|
|
156
|
+
setPreview(fn(fullScope));
|
|
157
|
+
setError(null);
|
|
158
|
+
})
|
|
159
|
+
.catch((e) => {
|
|
160
|
+
setError(e instanceof Error ? e.message : String(e));
|
|
161
|
+
});
|
|
162
|
+
}, []);
|
|
163
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
164
|
+
useEffect(() => { evalCode(initialCode); }, []);
|
|
165
|
+
function handleChange(value) {
|
|
166
|
+
const src = value ?? '';
|
|
167
|
+
setCode(src);
|
|
168
|
+
clearTimeout(debounceRef.current);
|
|
169
|
+
debounceRef.current = setTimeout(() => evalCode(src), 300);
|
|
170
|
+
}
|
|
171
|
+
function handleCopy() {
|
|
172
|
+
navigator.clipboard.writeText(code).then(() => {
|
|
173
|
+
setCopied(true);
|
|
174
|
+
setTimeout(() => setCopied(false), 2000);
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
function handleReset() {
|
|
178
|
+
setCode(initialCode);
|
|
179
|
+
evalCode(initialCode);
|
|
180
|
+
}
|
|
181
|
+
const editorHeight = Math.max(80, code.split('\n').length * 19 + 24);
|
|
182
|
+
return (_jsxs("div", { style: { ...S.card, userSelect: isDragging ? 'none' : undefined }, children: [_jsxs("div", { style: S.header, children: [_jsx("span", { style: S.title, children: title }), _jsxs("div", { style: S.actions, children: [code !== initialCode && (_jsx("button", { style: S.btn, onClick: handleReset, children: "\u21BA Reset" })), _jsx("button", { style: { ...S.btn, ...(copied ? S.btnCopied : {}) }, onClick: handleCopy, children: copied ? '✓ Copié' : 'Copier' }), _jsx("button", { style: S.btn, onClick: () => setShowCode((v) => !v), children: showCode ? 'Masquer' : '<> Code' })] })] }), _jsxs("div", { style: {
|
|
183
|
+
backgroundColor: 'var(--docs-bg-subtle)',
|
|
184
|
+
display: 'flex',
|
|
185
|
+
justifyContent: 'center',
|
|
186
|
+
minHeight: 140,
|
|
187
|
+
position: 'relative',
|
|
188
|
+
transition: 'background 0.2s',
|
|
189
|
+
}, children: [_jsxs("div", { ref: wrapperRef, style: {
|
|
190
|
+
display: 'flex',
|
|
191
|
+
alignItems: 'stretch',
|
|
192
|
+
width: previewWidth ? `${previewWidth}px` : '100%',
|
|
193
|
+
maxWidth: '100%',
|
|
194
|
+
}, children: [_jsx("div", { className: "docs-demo", style: {
|
|
195
|
+
flex: 1,
|
|
196
|
+
padding: phoneFrame ? '32px 24px' : '48px 32px',
|
|
197
|
+
display: 'flex',
|
|
198
|
+
alignItems: 'center',
|
|
199
|
+
justifyContent: 'center',
|
|
200
|
+
}, children: _jsx(Wrapper, { mode: mode, children: error ? (_jsx("pre", { style: S.error, children: error })) : (_jsx(DemoBoundary, { children: phoneFrame ? (_jsx(DeviceFrame, { device: "phone", children: preview ?? _jsx("span", { style: S.loading, children: "Chargement\u2026" }) })) : (preview ?? _jsx("span", { style: S.loading, children: "Chargement\u2026" })) }, `${code}|${mode}`)) }) }), _jsx("div", { onMouseDown: handleMouseDown, onDoubleClick: () => setPreviewWidth(null), title: "Glisser pour redimensionner \u00B7 Double-clic pour r\u00E9initialiser", style: {
|
|
201
|
+
width: 20,
|
|
202
|
+
flexShrink: 0,
|
|
203
|
+
cursor: 'ew-resize',
|
|
204
|
+
display: 'flex',
|
|
205
|
+
alignItems: 'center',
|
|
206
|
+
justifyContent: 'center',
|
|
207
|
+
borderLeft: '1px solid var(--docs-border)',
|
|
208
|
+
backgroundColor: isDragging ? 'var(--docs-accent-subtle)' : 'transparent',
|
|
209
|
+
transition: 'background 0.15s',
|
|
210
|
+
}, children: _jsx(DragDots, { active: isDragging }) })] }), previewWidth && (_jsxs("span", { style: {
|
|
211
|
+
position: 'absolute',
|
|
212
|
+
bottom: 6,
|
|
213
|
+
left: '50%',
|
|
214
|
+
transform: 'translateX(-50%)',
|
|
215
|
+
fontSize: 11,
|
|
216
|
+
fontFamily: 'ui-monospace, Consolas, monospace',
|
|
217
|
+
color: 'var(--docs-text-muted)',
|
|
218
|
+
backgroundColor: 'var(--docs-surface)',
|
|
219
|
+
border: '1px solid var(--docs-border)',
|
|
220
|
+
borderRadius: 4,
|
|
221
|
+
padding: '2px 6px',
|
|
222
|
+
pointerEvents: 'none',
|
|
223
|
+
}, children: [previewWidth, "px"] }))] }), showCode && (_jsx(Editor, { height: editorHeight, language: "jsx", theme: "vs-dark", value: code, onChange: handleChange, options: {
|
|
224
|
+
minimap: { enabled: false },
|
|
225
|
+
scrollBeyondLastLine: false,
|
|
226
|
+
fontSize: 13,
|
|
227
|
+
lineNumbers: 'off',
|
|
228
|
+
padding: { top: 14, bottom: 14 },
|
|
229
|
+
fontFamily: 'ui-monospace, Consolas, monospace',
|
|
230
|
+
} }))] }));
|
|
231
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/** Typed props API table — one row per prop */
|
|
2
|
+
export interface PropDef {
|
|
3
|
+
name: string;
|
|
4
|
+
type: string;
|
|
5
|
+
required: boolean;
|
|
6
|
+
default?: string;
|
|
7
|
+
description: string;
|
|
8
|
+
}
|
|
9
|
+
/** Props of every documented component, keyed by component name — produced by the docgen Vite plugin */
|
|
10
|
+
export type ComponentProps = Record<string, PropDef[]>;
|
|
11
|
+
interface PropsTableProps {
|
|
12
|
+
props: PropDef[];
|
|
13
|
+
}
|
|
14
|
+
export default function PropsTable({ props }: PropsTableProps): import("react").JSX.Element;
|
|
15
|
+
export {};
|
|
16
|
+
//# sourceMappingURL=PropsTable.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PropsTable.d.ts","sourceRoot":"","sources":["../../src/components/PropsTable.tsx"],"names":[],"mappings":"AAAA,+CAA+C;AAC/C,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,OAAO,CAAA;IACjB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,WAAW,EAAE,MAAM,CAAA;CACpB;AAED,wGAAwG;AACxG,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAA;AAEtD,UAAU,eAAe;IACvB,KAAK,EAAE,OAAO,EAAE,CAAA;CACjB;AAwDD,MAAM,CAAC,OAAO,UAAU,UAAU,CAAC,EAAE,KAAK,EAAE,EAAE,eAAe,+BAmC5D"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
const S = {
|
|
3
|
+
table: {
|
|
4
|
+
width: '100%',
|
|
5
|
+
borderCollapse: 'collapse',
|
|
6
|
+
fontSize: 14,
|
|
7
|
+
marginTop: 16,
|
|
8
|
+
},
|
|
9
|
+
th: {
|
|
10
|
+
textAlign: 'left',
|
|
11
|
+
padding: '10px 12px',
|
|
12
|
+
backgroundColor: 'var(--docs-surface)',
|
|
13
|
+
borderBottom: '2px solid var(--docs-border)',
|
|
14
|
+
fontWeight: 600,
|
|
15
|
+
color: 'var(--docs-text-primary)',
|
|
16
|
+
fontSize: 13,
|
|
17
|
+
},
|
|
18
|
+
td: {
|
|
19
|
+
padding: '10px 12px',
|
|
20
|
+
borderBottom: '1px solid var(--docs-border)',
|
|
21
|
+
verticalAlign: 'top',
|
|
22
|
+
color: 'var(--docs-text-secondary)',
|
|
23
|
+
lineHeight: 1.5,
|
|
24
|
+
},
|
|
25
|
+
nameMono: {
|
|
26
|
+
fontFamily: 'ui-monospace, Consolas, monospace',
|
|
27
|
+
fontSize: 13,
|
|
28
|
+
color: 'var(--docs-badge-name-color)',
|
|
29
|
+
backgroundColor: 'var(--docs-badge-name-bg)',
|
|
30
|
+
padding: '2px 5px',
|
|
31
|
+
borderRadius: 3,
|
|
32
|
+
},
|
|
33
|
+
typeMono: {
|
|
34
|
+
fontFamily: 'ui-monospace, Consolas, monospace',
|
|
35
|
+
fontSize: 13,
|
|
36
|
+
color: 'var(--docs-badge-type-color)',
|
|
37
|
+
backgroundColor: 'var(--docs-badge-type-bg)',
|
|
38
|
+
padding: '2px 5px',
|
|
39
|
+
borderRadius: 3,
|
|
40
|
+
},
|
|
41
|
+
defaultMono: {
|
|
42
|
+
fontFamily: 'ui-monospace, Consolas, monospace',
|
|
43
|
+
fontSize: 13,
|
|
44
|
+
color: 'var(--docs-badge-default-color)',
|
|
45
|
+
backgroundColor: 'var(--docs-badge-default-bg)',
|
|
46
|
+
padding: '2px 5px',
|
|
47
|
+
borderRadius: 3,
|
|
48
|
+
},
|
|
49
|
+
required: { color: 'var(--docs-badge-name-color)', fontSize: 12, marginLeft: 4 },
|
|
50
|
+
empty: { color: 'var(--docs-text-disabled)' },
|
|
51
|
+
noProps: { color: 'var(--docs-text-secondary)', marginTop: 16 },
|
|
52
|
+
};
|
|
53
|
+
const HEADERS = ['Nom', 'Type', 'Défaut', 'Description'];
|
|
54
|
+
export default function PropsTable({ props }) {
|
|
55
|
+
if (props.length === 0)
|
|
56
|
+
return _jsx("p", { style: S.noProps, children: "Ce composant n'a pas de props." });
|
|
57
|
+
return (_jsxs("table", { style: S.table, children: [_jsx("thead", { children: _jsx("tr", { children: HEADERS.map((h) => (_jsx("th", { style: S.th, children: h }, h))) }) }), _jsx("tbody", { children: props.map((prop, i) => (_jsxs("tr", { style: { backgroundColor: i % 2 === 0 ? 'var(--docs-bg)' : 'var(--docs-bg-subtle)' }, children: [_jsxs("td", { style: S.td, children: [_jsx("code", { style: S.nameMono, children: prop.name }), prop.required && _jsx("span", { style: S.required, children: "*" })] }), _jsx("td", { style: S.td, children: _jsx("code", { style: S.typeMono, children: prop.type }) }), _jsx("td", { style: S.td, children: prop.default
|
|
58
|
+
? _jsx("code", { style: S.defaultMono, children: prop.default })
|
|
59
|
+
: _jsx("span", { style: S.empty, children: "\u2014" }) }), _jsx("td", { style: S.td, children: prop.description })] }, prop.name))) })] }));
|
|
60
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ComponentSearch.d.ts","sourceRoot":"","sources":["../../../src/components/layout/ComponentSearch.tsx"],"names":[],"mappings":"AA6EA,MAAM,CAAC,OAAO,UAAU,eAAe,gCAyItC"}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/** Top bar search — filters the docs navigation and jumps to the selected page (⌘K / Ctrl+K) */
|
|
3
|
+
import { useEffect, useMemo, useRef, useState } from 'react';
|
|
4
|
+
import { useNavigate } from 'react-router-dom';
|
|
5
|
+
import { MagnifyingGlass } from '@phosphor-icons/react';
|
|
6
|
+
import { useNav } from '../../app/config';
|
|
7
|
+
const IS_MAC = typeof navigator !== 'undefined' && /Mac|iPhone|iPad/.test(navigator.platform);
|
|
8
|
+
const S = {
|
|
9
|
+
wrapper: { position: 'relative', width: 280 },
|
|
10
|
+
field: (focused) => ({
|
|
11
|
+
display: 'flex',
|
|
12
|
+
alignItems: 'center',
|
|
13
|
+
gap: 8,
|
|
14
|
+
height: 34,
|
|
15
|
+
padding: '0 10px',
|
|
16
|
+
backgroundColor: 'var(--docs-surface)',
|
|
17
|
+
border: `1px solid ${focused ? 'var(--docs-accent)' : 'var(--docs-border)'}`,
|
|
18
|
+
borderRadius: 8,
|
|
19
|
+
transition: 'border-color 0.15s',
|
|
20
|
+
}),
|
|
21
|
+
icon: { color: 'var(--docs-text-muted)', flexShrink: 0 },
|
|
22
|
+
input: {
|
|
23
|
+
flex: 1,
|
|
24
|
+
minWidth: 0,
|
|
25
|
+
border: 'none',
|
|
26
|
+
background: 'transparent',
|
|
27
|
+
outline: 'none',
|
|
28
|
+
fontFamily: 'inherit',
|
|
29
|
+
fontSize: 13,
|
|
30
|
+
color: 'var(--docs-text-primary)',
|
|
31
|
+
},
|
|
32
|
+
kbd: {
|
|
33
|
+
fontFamily: 'inherit',
|
|
34
|
+
fontSize: 11,
|
|
35
|
+
color: 'var(--docs-text-muted)',
|
|
36
|
+
border: '1px solid var(--docs-border)',
|
|
37
|
+
borderRadius: 4,
|
|
38
|
+
padding: '0 5px',
|
|
39
|
+
lineHeight: '18px',
|
|
40
|
+
flexShrink: 0,
|
|
41
|
+
},
|
|
42
|
+
dropdown: {
|
|
43
|
+
position: 'absolute',
|
|
44
|
+
top: 'calc(100% + 6px)',
|
|
45
|
+
left: 0,
|
|
46
|
+
right: 0,
|
|
47
|
+
maxHeight: 360,
|
|
48
|
+
overflowY: 'auto',
|
|
49
|
+
backgroundColor: 'var(--docs-bg)',
|
|
50
|
+
border: '1px solid var(--docs-border)',
|
|
51
|
+
borderRadius: 8,
|
|
52
|
+
boxShadow: 'var(--docs-shadow-md)',
|
|
53
|
+
padding: 4,
|
|
54
|
+
listStyle: 'none',
|
|
55
|
+
},
|
|
56
|
+
option: (active) => ({
|
|
57
|
+
display: 'flex',
|
|
58
|
+
alignItems: 'center',
|
|
59
|
+
justifyContent: 'space-between',
|
|
60
|
+
gap: 8,
|
|
61
|
+
padding: '7px 10px',
|
|
62
|
+
borderRadius: 6,
|
|
63
|
+
cursor: 'pointer',
|
|
64
|
+
fontSize: 13,
|
|
65
|
+
color: active ? 'var(--docs-accent)' : 'var(--docs-text-primary)',
|
|
66
|
+
backgroundColor: active ? 'var(--docs-accent-subtle)' : 'transparent',
|
|
67
|
+
}),
|
|
68
|
+
optionGroup: { fontSize: 11, color: 'var(--docs-text-muted)' },
|
|
69
|
+
empty: { padding: '10px', fontSize: 13, color: 'var(--docs-text-muted)' },
|
|
70
|
+
};
|
|
71
|
+
export default function ComponentSearch() {
|
|
72
|
+
const navigate = useNavigate();
|
|
73
|
+
const inputRef = useRef(null);
|
|
74
|
+
const wrapperRef = useRef(null);
|
|
75
|
+
const listRef = useRef(null);
|
|
76
|
+
const [query, setQuery] = useState('');
|
|
77
|
+
const [open, setOpen] = useState(false);
|
|
78
|
+
const [focused, setFocused] = useState(false);
|
|
79
|
+
const [activeIndex, setActiveIndex] = useState(0);
|
|
80
|
+
const nav = useNav();
|
|
81
|
+
const allItems = useMemo(() => nav.flatMap(({ group, items }) => items.map((item) => ({ ...item, group }))), [nav]);
|
|
82
|
+
const results = useMemo(() => {
|
|
83
|
+
const q = query.trim().toLowerCase();
|
|
84
|
+
if (!q)
|
|
85
|
+
return allItems;
|
|
86
|
+
// Prefix matches first, then substring matches
|
|
87
|
+
const matches = allItems.filter((item) => item.label.toLowerCase().includes(q));
|
|
88
|
+
return matches.sort((a, b) => Number(!a.label.toLowerCase().startsWith(q)) - Number(!b.label.toLowerCase().startsWith(q)));
|
|
89
|
+
}, [query, allItems]);
|
|
90
|
+
// Global ⌘K / Ctrl+K shortcut focuses the search
|
|
91
|
+
useEffect(() => {
|
|
92
|
+
const onKeyDown = (e) => {
|
|
93
|
+
if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === 'k') {
|
|
94
|
+
e.preventDefault();
|
|
95
|
+
inputRef.current?.focus();
|
|
96
|
+
inputRef.current?.select();
|
|
97
|
+
setOpen(true);
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
window.addEventListener('keydown', onKeyDown);
|
|
101
|
+
return () => window.removeEventListener('keydown', onKeyDown);
|
|
102
|
+
}, []);
|
|
103
|
+
// Close the dropdown on outside click
|
|
104
|
+
useEffect(() => {
|
|
105
|
+
const onMouseDown = (e) => {
|
|
106
|
+
if (!wrapperRef.current?.contains(e.target))
|
|
107
|
+
setOpen(false);
|
|
108
|
+
};
|
|
109
|
+
document.addEventListener('mousedown', onMouseDown);
|
|
110
|
+
return () => document.removeEventListener('mousedown', onMouseDown);
|
|
111
|
+
}, []);
|
|
112
|
+
// Keep the highlighted option visible while navigating with arrows
|
|
113
|
+
useEffect(() => {
|
|
114
|
+
const el = listRef.current?.children[activeIndex];
|
|
115
|
+
el?.scrollIntoView({ block: 'nearest' });
|
|
116
|
+
}, [activeIndex]);
|
|
117
|
+
const select = (item) => {
|
|
118
|
+
navigate(item.path);
|
|
119
|
+
setQuery('');
|
|
120
|
+
setOpen(false);
|
|
121
|
+
inputRef.current?.blur();
|
|
122
|
+
};
|
|
123
|
+
const onKeyDown = (e) => {
|
|
124
|
+
if (e.key === 'ArrowDown') {
|
|
125
|
+
e.preventDefault();
|
|
126
|
+
setOpen(true);
|
|
127
|
+
setActiveIndex((i) => Math.min(i + 1, results.length - 1));
|
|
128
|
+
}
|
|
129
|
+
else if (e.key === 'ArrowUp') {
|
|
130
|
+
e.preventDefault();
|
|
131
|
+
setActiveIndex((i) => Math.max(i - 1, 0));
|
|
132
|
+
}
|
|
133
|
+
else if (e.key === 'Enter') {
|
|
134
|
+
const item = results[activeIndex];
|
|
135
|
+
if (item)
|
|
136
|
+
select(item);
|
|
137
|
+
}
|
|
138
|
+
else if (e.key === 'Escape') {
|
|
139
|
+
setOpen(false);
|
|
140
|
+
inputRef.current?.blur();
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
return (_jsxs("div", { ref: wrapperRef, style: S.wrapper, children: [_jsxs("div", { style: S.field(focused), onClick: () => inputRef.current?.focus(), children: [_jsx(MagnifyingGlass, { size: 15, style: S.icon }), _jsx("input", { ref: inputRef, type: "text", value: query, placeholder: "Rechercher un composant\u2026", "aria-label": "Rechercher un composant", role: "combobox", "aria-expanded": open, "aria-controls": "component-search-results", "aria-activedescendant": open && results[activeIndex] ? `search-opt-${activeIndex}` : undefined, style: S.input, onChange: (e) => {
|
|
144
|
+
setQuery(e.target.value);
|
|
145
|
+
setActiveIndex(0);
|
|
146
|
+
setOpen(true);
|
|
147
|
+
}, onFocus: () => {
|
|
148
|
+
setFocused(true);
|
|
149
|
+
setOpen(true);
|
|
150
|
+
}, onBlur: () => setFocused(false), onKeyDown: onKeyDown }), !focused && _jsx("kbd", { style: S.kbd, children: IS_MAC ? '⌘K' : 'Ctrl K' })] }), open && (_jsx("ul", { id: "component-search-results", role: "listbox", ref: listRef, style: S.dropdown, children: results.length === 0 ? (_jsx("li", { style: S.empty, children: "Aucun r\u00E9sultat" })) : (results.map((item, i) => (_jsxs("li", { id: `search-opt-${i}`, role: "option", "aria-selected": i === activeIndex, style: S.option(i === activeIndex), onMouseEnter: () => setActiveIndex(i),
|
|
151
|
+
// mousedown instead of click so the input blur doesn't swallow the selection
|
|
152
|
+
onMouseDown: (e) => {
|
|
153
|
+
e.preventDefault();
|
|
154
|
+
select(item);
|
|
155
|
+
}, children: [_jsx("span", { children: item.label }), _jsx("span", { style: S.optionGroup, children: item.group })] }, item.path)))) }))] }));
|
|
156
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** Doc site shell: fixed sidebar + glassmorphism top bar + main content */
|
|
2
|
+
import type { ReactNode } from 'react';
|
|
3
|
+
interface LayoutProps {
|
|
4
|
+
children: ReactNode;
|
|
5
|
+
}
|
|
6
|
+
export default function Layout({ children }: LayoutProps): import("react").JSX.Element;
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=Layout.d.ts.map
|