@situaction/traquiste-docs-kit 0.0.0-stage → 1.1.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.
Files changed (68) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/README.md +356 -2
  3. package/client.d.ts +7 -0
  4. package/dist/app/ColorModeContext.d.ts +15 -0
  5. package/dist/app/ColorModeContext.d.ts.map +1 -0
  6. package/dist/app/ColorModeContext.js +58 -0
  7. package/dist/app/config.d.ts +69 -0
  8. package/dist/app/config.d.ts.map +1 -0
  9. package/dist/app/config.js +35 -0
  10. package/dist/app/createDocsApp.d.ts +9 -0
  11. package/dist/app/createDocsApp.d.ts.map +1 -0
  12. package/dist/app/createDocsApp.js +53 -0
  13. package/dist/components/Callout.d.ts +11 -0
  14. package/dist/components/Callout.d.ts.map +1 -0
  15. package/dist/components/Callout.js +28 -0
  16. package/dist/components/CodeBlock.d.ts +12 -0
  17. package/dist/components/CodeBlock.d.ts.map +1 -0
  18. package/dist/components/CodeBlock.js +60 -0
  19. package/dist/components/DeviceFrame.d.ts +17 -0
  20. package/dist/components/DeviceFrame.d.ts.map +1 -0
  21. package/dist/components/DeviceFrame.js +74 -0
  22. package/dist/components/LiveEditor.d.ts +10 -0
  23. package/dist/components/LiveEditor.d.ts.map +1 -0
  24. package/dist/components/LiveEditor.js +231 -0
  25. package/dist/components/PropsTable.d.ts +16 -0
  26. package/dist/components/PropsTable.d.ts.map +1 -0
  27. package/dist/components/PropsTable.js +60 -0
  28. package/dist/components/layout/ComponentSearch.d.ts +2 -0
  29. package/dist/components/layout/ComponentSearch.d.ts.map +1 -0
  30. package/dist/components/layout/ComponentSearch.js +156 -0
  31. package/dist/components/layout/Layout.d.ts +8 -0
  32. package/dist/components/layout/Layout.d.ts.map +1 -0
  33. package/dist/components/layout/Layout.js +109 -0
  34. package/dist/components/layout/NotFound.d.ts +2 -0
  35. package/dist/components/layout/NotFound.d.ts.map +1 -0
  36. package/dist/components/layout/NotFound.js +36 -0
  37. package/dist/components/layout/Sidebar.d.ts +2 -0
  38. package/dist/components/layout/Sidebar.d.ts.map +1 -0
  39. package/dist/components/layout/Sidebar.js +88 -0
  40. package/dist/components/layout/TableOfContents.d.ts +10 -0
  41. package/dist/components/layout/TableOfContents.d.ts.map +1 -0
  42. package/dist/components/layout/TableOfContents.js +48 -0
  43. package/dist/hooks/useCopy.d.ts +5 -0
  44. package/dist/hooks/useCopy.d.ts.map +1 -0
  45. package/dist/hooks/useCopy.js +19 -0
  46. package/dist/index.d.ts +21 -0
  47. package/dist/index.d.ts.map +1 -0
  48. package/dist/index.js +13 -0
  49. package/dist/pages/DocPage.d.ts +26 -0
  50. package/dist/pages/DocPage.d.ts.map +1 -0
  51. package/dist/pages/DocPage.js +23 -0
  52. package/dist/pages/createComponentPage.d.ts +33 -0
  53. package/dist/pages/createComponentPage.d.ts.map +1 -0
  54. package/dist/pages/createComponentPage.js +150 -0
  55. package/dist/pages/createScreenPage.d.ts +33 -0
  56. package/dist/pages/createScreenPage.d.ts.map +1 -0
  57. package/dist/pages/createScreenPage.js +124 -0
  58. package/dist/styles/docs.css +177 -0
  59. package/dist/styles/pageStyles.d.ts +45 -0
  60. package/dist/styles/pageStyles.d.ts.map +1 -0
  61. package/dist/styles/pageStyles.js +46 -0
  62. package/dist/vite/extractProps.d.ts +8 -0
  63. package/dist/vite/extractProps.d.ts.map +1 -0
  64. package/dist/vite/extractProps.js +79 -0
  65. package/dist/vite/index.d.ts +18 -0
  66. package/dist/vite/index.d.ts.map +1 -0
  67. package/dist/vite/index.js +73 -0
  68. package/package.json +111 -4
@@ -0,0 +1,11 @@
1
+ import type { ReactNode } from 'react';
2
+ export type CalloutType = 'info' | 'tip' | 'warning' | 'danger';
3
+ export interface CalloutProps {
4
+ /** Tone of the note (default 'info') */
5
+ type?: CalloutType;
6
+ /** Heading — defaults to the type label (Info, Conseil, Attention, Danger) */
7
+ title?: string;
8
+ children: ReactNode;
9
+ }
10
+ export declare function Callout({ type, title, children }: CalloutProps): import("react").JSX.Element;
11
+ //# sourceMappingURL=Callout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Callout.d.ts","sourceRoot":"","sources":["../../src/components/Callout.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAEtC,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,KAAK,GAAG,SAAS,GAAG,QAAQ,CAAA;AAE/D,MAAM,WAAW,YAAY;IAC3B,wCAAwC;IACxC,IAAI,CAAC,EAAE,WAAW,CAAA;IAClB,8EAA8E;IAC9E,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,SAAS,CAAA;CACpB;AASD,wBAAgB,OAAO,CAAC,EAAE,IAAa,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,YAAY,+BAgCvE"}
@@ -0,0 +1,28 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /** Highlighted note in a guide page: info, tip, warning or danger */
3
+ import { Info, Lightbulb, Warning, WarningOctagon } from '@phosphor-icons/react';
4
+ const TYPES = {
5
+ info: { label: 'Info', Icon: Info },
6
+ tip: { label: 'Conseil', Icon: Lightbulb },
7
+ warning: { label: 'Attention', Icon: Warning },
8
+ danger: { label: 'Danger', Icon: WarningOctagon },
9
+ };
10
+ export function Callout({ type = 'info', title, children }) {
11
+ const { label, Icon } = TYPES[type];
12
+ // Colors come from --docs-callout-<type>-* so they follow the light / dark theme
13
+ const color = (part) => `var(--docs-callout-${type}-${part})`;
14
+ const heading = title ?? label;
15
+ return (_jsxs("div", { role: "note", "aria-label": heading, className: "docs-callout", style: {
16
+ display: 'flex',
17
+ gap: 12,
18
+ padding: '12px 16px',
19
+ margin: '0 0 20px',
20
+ backgroundColor: color('bg'),
21
+ border: `1px solid ${color('border')}`,
22
+ borderLeft: `4px solid ${color('accent')}`,
23
+ borderRadius: 8,
24
+ fontSize: 14,
25
+ lineHeight: 1.6,
26
+ color: 'var(--docs-text-primary)',
27
+ }, children: [_jsx(Icon, { size: 18, weight: "fill", color: color('accent'), style: { flexShrink: 0, marginTop: 2 }, "aria-hidden": true }), _jsxs("div", { style: { minWidth: 0 }, children: [_jsx("strong", { style: { display: 'block', fontWeight: 600, marginBottom: 2 }, children: heading }), _jsx("div", { className: "docs-callout-body", children: children })] })] }));
28
+ }
@@ -0,0 +1,12 @@
1
+ export interface CodeBlockProps {
2
+ /** Code to show — indentation common to all lines is removed */
3
+ children: string;
4
+ /** Language label shown in the header, e.g. 'bash', 'tsx' */
5
+ language?: string;
6
+ /** Header label, e.g. a file name — wins over `language` */
7
+ title?: string;
8
+ }
9
+ /** Removes surrounding blank lines and the indentation shared by all lines (template literals in JSX) */
10
+ export declare function dedent(code: string): string;
11
+ export declare function CodeBlock({ children, language, title }: CodeBlockProps): import("react").JSX.Element;
12
+ //# sourceMappingURL=CodeBlock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CodeBlock.d.ts","sourceRoot":"","sources":["../../src/components/CodeBlock.tsx"],"names":[],"mappings":"AAGA,MAAM,WAAW,cAAc;IAC7B,gEAAgE;IAChE,QAAQ,EAAE,MAAM,CAAA;IAChB,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,4DAA4D;IAC5D,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AA+CD,yGAAyG;AACzG,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAK3C;AAED,wBAAgB,SAAS,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,cAAc,+BAkBtE"}
@@ -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,2 @@
1
+ export default function ComponentSearch(): import("react").JSX.Element;
2
+ //# sourceMappingURL=ComponentSearch.d.ts.map
@@ -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"}