@fragments-sdk/cli 0.10.0 → 0.11.1
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/dist/bin.js +26 -8
- package/dist/bin.js.map +1 -1
- package/dist/{chunk-ZDA3PLQ6.js → chunk-5G3VZH43.js} +2 -2
- package/dist/{chunk-566BNPQZ.js → chunk-HRFUSSZI.js} +25 -6
- package/dist/chunk-HRFUSSZI.js.map +1 -0
- package/dist/{chunk-CAMXG5HJ.js → chunk-ZM4ZQZWZ.js} +2 -2
- package/dist/{generate-BGKTKO6E.js → generate-FBHSXR3D.js} +2 -2
- package/dist/index.js +2 -2
- package/dist/{init-Q53R5Q2T.js → init-UFGK5TCN.js} +77 -6
- package/dist/init-UFGK5TCN.js.map +1 -0
- package/dist/{scan-OQU7M4GH.js → scan-CJF2DOQW.js} +3 -3
- package/dist/{scan-generate-T5QNUG7N.js → scan-generate-SJAN5MVI.js} +2 -2
- package/dist/snapshot-SV2JOFZH.js +139 -0
- package/dist/snapshot-SV2JOFZH.js.map +1 -0
- package/dist/{test-2CSOSS3B.js → test-Z5LVO724.js} +2 -2
- package/dist/{tokens-DXEGYTOJ.js → tokens-CE46OTMD.js} +2 -2
- package/dist/{viewer-DBEPYM3G.js → viewer-DLLJIMCK.js} +69 -47
- package/dist/viewer-DLLJIMCK.js.map +1 -0
- package/package.json +6 -14
- package/src/bin.ts +30 -0
- package/src/commands/init.ts +76 -1
- package/src/commands/snapshot.ts +197 -0
- package/src/core/loader.ts +38 -8
- package/src/viewer/__tests__/viewer-integration.test.ts +85 -74
- package/src/viewer/server.ts +37 -22
- package/src/viewer/vite-plugin.ts +25 -9
- package/dist/chunk-566BNPQZ.js.map +0 -1
- package/dist/init-Q53R5Q2T.js.map +0 -1
- package/dist/viewer-DBEPYM3G.js.map +0 -1
- package/src/viewer/__tests__/a11y-fixes.test.ts +0 -358
- package/src/viewer/__tests__/jsx-parser.test.ts +0 -502
- package/src/viewer/__tests__/render-utils.test.ts +0 -232
- package/src/viewer/__tests__/style-utils.test.ts +0 -404
- package/src/viewer/assets/fragments-logo.ts +0 -4
- package/src/viewer/components/AccessibilityPanel.tsx +0 -1457
- package/src/viewer/components/ActionCapture.tsx +0 -172
- package/src/viewer/components/ActionsPanel.tsx +0 -332
- package/src/viewer/components/AllVariantsPreview.tsx +0 -78
- package/src/viewer/components/App.tsx +0 -582
- package/src/viewer/components/BottomPanel.tsx +0 -288
- package/src/viewer/components/CodePanel.naming.test.tsx +0 -59
- package/src/viewer/components/CodePanel.tsx +0 -118
- package/src/viewer/components/CommandPalette.tsx +0 -392
- package/src/viewer/components/ComponentDocView.tsx +0 -164
- package/src/viewer/components/ComponentGraph.tsx +0 -380
- package/src/viewer/components/ComponentHeader.tsx +0 -88
- package/src/viewer/components/ContractPanel.tsx +0 -241
- package/src/viewer/components/EmptyVariantMessage.tsx +0 -54
- package/src/viewer/components/ErrorBoundary.tsx +0 -97
- package/src/viewer/components/FigmaEmbed.tsx +0 -238
- package/src/viewer/components/FragmentEditor.tsx +0 -525
- package/src/viewer/components/FragmentRenderer.tsx +0 -61
- package/src/viewer/components/HeaderSearch.tsx +0 -24
- package/src/viewer/components/HealthDashboard.tsx +0 -441
- package/src/viewer/components/HmrStatusIndicator.tsx +0 -61
- package/src/viewer/components/Icons.tsx +0 -479
- package/src/viewer/components/InteractionsPanel.tsx +0 -757
- package/src/viewer/components/IsolatedPreviewFrame.tsx +0 -346
- package/src/viewer/components/IsolatedRender.tsx +0 -113
- package/src/viewer/components/KeyboardShortcutsHelp.tsx +0 -53
- package/src/viewer/components/LandingPage.tsx +0 -421
- package/src/viewer/components/Layout.tsx +0 -27
- package/src/viewer/components/LeftSidebar.tsx +0 -472
- package/src/viewer/components/LoadErrorMessage.tsx +0 -102
- package/src/viewer/components/MultiViewportPreview.tsx +0 -522
- package/src/viewer/components/NoVariantsMessage.tsx +0 -59
- package/src/viewer/components/PanelShell.tsx +0 -161
- package/src/viewer/components/PerformancePanel.tsx +0 -304
- package/src/viewer/components/PreviewArea.tsx +0 -472
- package/src/viewer/components/PreviewAside.tsx +0 -168
- package/src/viewer/components/PreviewFrameHost.tsx +0 -303
- package/src/viewer/components/PreviewPane.tsx +0 -149
- package/src/viewer/components/PreviewToolbar.tsx +0 -80
- package/src/viewer/components/PropsEditor.tsx +0 -506
- package/src/viewer/components/PropsTable.tsx +0 -111
- package/src/viewer/components/RelationsSection.tsx +0 -88
- package/src/viewer/components/ResizablePanel.tsx +0 -271
- package/src/viewer/components/RightSidebar.tsx +0 -102
- package/src/viewer/components/RuntimeToolsRegistrar.tsx +0 -17
- package/src/viewer/components/ScreenshotButton.tsx +0 -90
- package/src/viewer/components/Sidebar.tsx +0 -169
- package/src/viewer/components/SkeletonLoader.tsx +0 -161
- package/src/viewer/components/ThemeProvider.tsx +0 -42
- package/src/viewer/components/Toast.tsx +0 -3
- package/src/viewer/components/TokenStylePanel.tsx +0 -699
- package/src/viewer/components/TopToolbar.tsx +0 -159
- package/src/viewer/components/UsageSection.tsx +0 -95
- package/src/viewer/components/VariantMatrix.tsx +0 -388
- package/src/viewer/components/VariantRenderer.tsx +0 -131
- package/src/viewer/components/VariantTabs.tsx +0 -40
- package/src/viewer/components/ViewerHeader.tsx +0 -69
- package/src/viewer/components/ViewerStateSync.tsx +0 -52
- package/src/viewer/components/ViewportSelector.tsx +0 -172
- package/src/viewer/components/WebMCPDevTools.tsx +0 -503
- package/src/viewer/components/WebMCPIntegration.tsx +0 -47
- package/src/viewer/components/WebMCPStatusIndicator.tsx +0 -60
- package/src/viewer/components/_future/CreatePage.tsx +0 -836
- package/src/viewer/components/viewer-utils.ts +0 -16
- package/src/viewer/composition-renderer.ts +0 -381
- package/src/viewer/constants/index.ts +0 -1
- package/src/viewer/constants/ui.ts +0 -166
- package/src/viewer/entry.tsx +0 -335
- package/src/viewer/hooks/index.ts +0 -2
- package/src/viewer/hooks/useA11yCache.ts +0 -383
- package/src/viewer/hooks/useA11yService.ts +0 -364
- package/src/viewer/hooks/useActions.ts +0 -138
- package/src/viewer/hooks/useAppState.ts +0 -147
- package/src/viewer/hooks/useCompiledFragments.ts +0 -42
- package/src/viewer/hooks/useFigmaIntegration.ts +0 -132
- package/src/viewer/hooks/useHmrStatus.ts +0 -109
- package/src/viewer/hooks/useKeyboardShortcuts.ts +0 -270
- package/src/viewer/hooks/usePreviewBridge.ts +0 -347
- package/src/viewer/hooks/useScrollSpy.ts +0 -78
- package/src/viewer/hooks/useUrlState.ts +0 -318
- package/src/viewer/hooks/useViewSettings.ts +0 -111
- package/src/viewer/index.html +0 -28
- package/src/viewer/intelligence/healthReport.ts +0 -505
- package/src/viewer/intelligence/styleDrift.ts +0 -340
- package/src/viewer/intelligence/usageScanner.ts +0 -309
- package/src/viewer/jsx-parser.ts +0 -486
- package/src/viewer/preview-frame-entry.tsx +0 -25
- package/src/viewer/preview-frame.html +0 -125
- package/src/viewer/public/favicon.ico +0 -0
- package/src/viewer/render-template.html +0 -68
- package/src/viewer/styles/globals.css +0 -278
- package/src/viewer/types/a11y.ts +0 -197
- package/src/viewer/utils/a11y-fixes.ts +0 -509
- package/src/viewer/utils/actionExport.ts +0 -372
- package/src/viewer/utils/colorSchemes.ts +0 -201
- package/src/viewer/utils/detectRelationships.ts +0 -256
- package/src/viewer/vendor/shared/src/ComponentDocContent.module.scss +0 -10
- package/src/viewer/vendor/shared/src/ComponentDocContent.module.scss.d.ts +0 -2
- package/src/viewer/vendor/shared/src/ComponentDocContent.tsx +0 -274
- package/src/viewer/vendor/shared/src/DocsHeaderBar.tsx +0 -129
- package/src/viewer/vendor/shared/src/DocsPageAsideHost.tsx +0 -89
- package/src/viewer/vendor/shared/src/DocsPageShell.tsx +0 -124
- package/src/viewer/vendor/shared/src/DocsSearchCommand.tsx +0 -99
- package/src/viewer/vendor/shared/src/DocsSidebarNav.tsx +0 -66
- package/src/viewer/vendor/shared/src/PropsTable.module.scss +0 -68
- package/src/viewer/vendor/shared/src/PropsTable.module.scss.d.ts +0 -2
- package/src/viewer/vendor/shared/src/PropsTable.tsx +0 -76
- package/src/viewer/vendor/shared/src/VariantPreviewCard.module.scss +0 -114
- package/src/viewer/vendor/shared/src/VariantPreviewCard.module.scss.d.ts +0 -2
- package/src/viewer/vendor/shared/src/VariantPreviewCard.tsx +0 -134
- package/src/viewer/vendor/shared/src/docs-data/index.ts +0 -32
- package/src/viewer/vendor/shared/src/docs-data/mcp-configs.ts +0 -72
- package/src/viewer/vendor/shared/src/docs-data/palettes.ts +0 -75
- package/src/viewer/vendor/shared/src/docs-data/setup-examples.ts +0 -55
- package/src/viewer/vendor/shared/src/docs-layout.scss +0 -28
- package/src/viewer/vendor/shared/src/docs-layout.scss.d.ts +0 -2
- package/src/viewer/vendor/shared/src/index.ts +0 -34
- package/src/viewer/vendor/shared/src/types.ts +0 -53
- package/src/viewer/webmcp/__tests__/analytics.test.ts +0 -108
- package/src/viewer/webmcp/analytics.ts +0 -165
- package/src/viewer/webmcp/index.ts +0 -3
- package/src/viewer/webmcp/posthog-bridge.ts +0 -39
- package/src/viewer/webmcp/runtime-tools.ts +0 -152
- package/src/viewer/webmcp/scan-utils.ts +0 -135
- package/src/viewer/webmcp/use-tool-analytics.ts +0 -69
- package/src/viewer/webmcp/viewer-state.ts +0 -45
- /package/dist/{chunk-ZDA3PLQ6.js.map → chunk-5G3VZH43.js.map} +0 -0
- /package/dist/{chunk-CAMXG5HJ.js.map → chunk-ZM4ZQZWZ.js.map} +0 -0
- /package/dist/{generate-BGKTKO6E.js.map → generate-FBHSXR3D.js.map} +0 -0
- /package/dist/{scan-OQU7M4GH.js.map → scan-CJF2DOQW.js.map} +0 -0
- /package/dist/{scan-generate-T5QNUG7N.js.map → scan-generate-SJAN5MVI.js.map} +0 -0
- /package/dist/{test-2CSOSS3B.js.map → test-Z5LVO724.js.map} +0 -0
- /package/dist/{tokens-DXEGYTOJ.js.map → tokens-CE46OTMD.js.map} +0 -0
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import { createPortal } from 'react-dom';
|
|
4
|
-
import * as React from 'react';
|
|
5
|
-
|
|
6
|
-
interface DocsPageAsideContextValue {
|
|
7
|
-
asideVisible: boolean;
|
|
8
|
-
setAsideVisible: (visible: boolean) => void;
|
|
9
|
-
asideWidth: string;
|
|
10
|
-
setAsideWidth: (width: string) => void;
|
|
11
|
-
asideContainer: HTMLDivElement | null;
|
|
12
|
-
setAsideContainer: (container: HTMLDivElement | null) => void;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
const DocsPageAsideContext = React.createContext<DocsPageAsideContextValue | null>(null);
|
|
16
|
-
|
|
17
|
-
export function DocsPageAsideProvider({
|
|
18
|
-
children,
|
|
19
|
-
defaultWidth = '320px',
|
|
20
|
-
}: {
|
|
21
|
-
children: React.ReactNode;
|
|
22
|
-
defaultWidth?: string;
|
|
23
|
-
}) {
|
|
24
|
-
const [asideVisible, setAsideVisible] = React.useState(false);
|
|
25
|
-
const [asideWidth, setAsideWidth] = React.useState(defaultWidth);
|
|
26
|
-
const [asideContainer, setAsideContainer] = React.useState<HTMLDivElement | null>(null);
|
|
27
|
-
|
|
28
|
-
return (
|
|
29
|
-
<DocsPageAsideContext.Provider
|
|
30
|
-
value={{
|
|
31
|
-
asideVisible,
|
|
32
|
-
setAsideVisible,
|
|
33
|
-
asideWidth,
|
|
34
|
-
setAsideWidth,
|
|
35
|
-
asideContainer,
|
|
36
|
-
setAsideContainer,
|
|
37
|
-
}}
|
|
38
|
-
>
|
|
39
|
-
{children}
|
|
40
|
-
</DocsPageAsideContext.Provider>
|
|
41
|
-
);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export function useDocsPageAside() {
|
|
45
|
-
const context = React.useContext(DocsPageAsideContext);
|
|
46
|
-
if (!context) {
|
|
47
|
-
throw new Error('useDocsPageAside must be used within DocsPageAsideProvider');
|
|
48
|
-
}
|
|
49
|
-
return context;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export function DocsPageAsidePortal({ children, width = '320px' }: { children: React.ReactNode; width?: string }) {
|
|
53
|
-
const { setAsideVisible, setAsideWidth, asideContainer } = useDocsPageAside();
|
|
54
|
-
|
|
55
|
-
React.useLayoutEffect(() => {
|
|
56
|
-
setAsideVisible(true);
|
|
57
|
-
setAsideWidth(width);
|
|
58
|
-
|
|
59
|
-
return () => {
|
|
60
|
-
setAsideVisible(false);
|
|
61
|
-
};
|
|
62
|
-
}, [setAsideVisible, setAsideWidth, width]);
|
|
63
|
-
|
|
64
|
-
if (!asideContainer) {
|
|
65
|
-
return null;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
return createPortal(children, asideContainer);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
interface DocsPageAsideHostProps {
|
|
72
|
-
className?: string;
|
|
73
|
-
style?: React.CSSProperties;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
export function DocsPageAsideHost({ className, style }: DocsPageAsideHostProps) {
|
|
77
|
-
const { setAsideContainer } = useDocsPageAside();
|
|
78
|
-
|
|
79
|
-
const asideContainerCallback = React.useCallback(
|
|
80
|
-
(node: HTMLDivElement | null) => {
|
|
81
|
-
setAsideContainer(node);
|
|
82
|
-
},
|
|
83
|
-
[setAsideContainer]
|
|
84
|
-
);
|
|
85
|
-
|
|
86
|
-
return (
|
|
87
|
-
<div ref={asideContainerCallback} className={className} style={{ height: '100%', ...style }} />
|
|
88
|
-
);
|
|
89
|
-
}
|
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import { AppShell } from '@fragments-sdk/ui';
|
|
4
|
-
import type { ReactNode } from 'react';
|
|
5
|
-
import { DocsPageAsideHost, DocsPageAsideProvider, useDocsPageAside } from './DocsPageAsideHost';
|
|
6
|
-
|
|
7
|
-
type SidebarCollapsible = 'offcanvas' | 'icon' | 'none';
|
|
8
|
-
|
|
9
|
-
interface DocsPageShellProps {
|
|
10
|
-
header: ReactNode;
|
|
11
|
-
sidebar: ReactNode;
|
|
12
|
-
children: ReactNode;
|
|
13
|
-
sidebarWidth?: string;
|
|
14
|
-
sidebarCollapsible?: SidebarCollapsible;
|
|
15
|
-
sidebarDefaultCollapsed?: boolean;
|
|
16
|
-
sidebarAriaLabel?: string;
|
|
17
|
-
mainId?: string;
|
|
18
|
-
mainAriaLabel?: string;
|
|
19
|
-
mainPadding?: 'none' | 'sm' | 'md' | 'lg';
|
|
20
|
-
mainClassName?: string;
|
|
21
|
-
aside?: ReactNode;
|
|
22
|
-
asideWidth?: string;
|
|
23
|
-
useAsidePortal?: boolean;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
function DocsPageShellInner({
|
|
27
|
-
header,
|
|
28
|
-
sidebar,
|
|
29
|
-
children,
|
|
30
|
-
sidebarWidth = '260px',
|
|
31
|
-
sidebarCollapsible = 'offcanvas',
|
|
32
|
-
sidebarDefaultCollapsed,
|
|
33
|
-
sidebarAriaLabel = 'Documentation sidebar',
|
|
34
|
-
mainId = 'main-content',
|
|
35
|
-
mainAriaLabel = 'Documentation content',
|
|
36
|
-
mainPadding = 'lg',
|
|
37
|
-
mainClassName,
|
|
38
|
-
aside,
|
|
39
|
-
asideWidth = '320px',
|
|
40
|
-
useAsidePortal = false,
|
|
41
|
-
}: DocsPageShellProps) {
|
|
42
|
-
return (
|
|
43
|
-
<AppShell>
|
|
44
|
-
<AppShell.Header>{header}</AppShell.Header>
|
|
45
|
-
|
|
46
|
-
<AppShell.Sidebar
|
|
47
|
-
width={sidebarWidth}
|
|
48
|
-
collapsible={sidebarCollapsible}
|
|
49
|
-
defaultCollapsed={sidebarDefaultCollapsed}
|
|
50
|
-
aria-label={sidebarAriaLabel}
|
|
51
|
-
>
|
|
52
|
-
{sidebar}
|
|
53
|
-
</AppShell.Sidebar>
|
|
54
|
-
|
|
55
|
-
<AppShell.Main
|
|
56
|
-
id={mainId}
|
|
57
|
-
aria-label={mainAriaLabel}
|
|
58
|
-
padding={mainPadding}
|
|
59
|
-
className={mainClassName}
|
|
60
|
-
>
|
|
61
|
-
{children}
|
|
62
|
-
</AppShell.Main>
|
|
63
|
-
|
|
64
|
-
{useAsidePortal ? <DocsPageAsideHost /> : null}
|
|
65
|
-
{!useAsidePortal && aside ? <AppShell.Aside width={asideWidth}>{aside}</AppShell.Aside> : null}
|
|
66
|
-
</AppShell>
|
|
67
|
-
);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
function DocsPageShellPortalInner({
|
|
71
|
-
header,
|
|
72
|
-
sidebar,
|
|
73
|
-
children,
|
|
74
|
-
sidebarWidth = '260px',
|
|
75
|
-
sidebarCollapsible = 'offcanvas',
|
|
76
|
-
sidebarDefaultCollapsed,
|
|
77
|
-
sidebarAriaLabel = 'Documentation sidebar',
|
|
78
|
-
mainId = 'main-content',
|
|
79
|
-
mainAriaLabel = 'Documentation content',
|
|
80
|
-
mainPadding = 'lg',
|
|
81
|
-
mainClassName,
|
|
82
|
-
}: DocsPageShellProps) {
|
|
83
|
-
const { asideVisible, asideWidth } = useDocsPageAside();
|
|
84
|
-
|
|
85
|
-
return (
|
|
86
|
-
<AppShell>
|
|
87
|
-
<AppShell.Header>{header}</AppShell.Header>
|
|
88
|
-
|
|
89
|
-
<AppShell.Sidebar
|
|
90
|
-
width={sidebarWidth}
|
|
91
|
-
collapsible={sidebarCollapsible}
|
|
92
|
-
defaultCollapsed={sidebarDefaultCollapsed}
|
|
93
|
-
aria-label={sidebarAriaLabel}
|
|
94
|
-
>
|
|
95
|
-
{sidebar}
|
|
96
|
-
</AppShell.Sidebar>
|
|
97
|
-
|
|
98
|
-
<AppShell.Main
|
|
99
|
-
id={mainId}
|
|
100
|
-
aria-label={mainAriaLabel}
|
|
101
|
-
padding={mainPadding}
|
|
102
|
-
className={mainClassName}
|
|
103
|
-
>
|
|
104
|
-
{children}
|
|
105
|
-
</AppShell.Main>
|
|
106
|
-
|
|
107
|
-
<AppShell.Aside width={asideWidth} visible={asideVisible} aria-label="On-page controls">
|
|
108
|
-
<DocsPageAsideHost />
|
|
109
|
-
</AppShell.Aside>
|
|
110
|
-
</AppShell>
|
|
111
|
-
);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
export function DocsPageShell(props: DocsPageShellProps) {
|
|
115
|
-
if (props.useAsidePortal) {
|
|
116
|
-
return (
|
|
117
|
-
<DocsPageAsideProvider defaultWidth={props.asideWidth}>
|
|
118
|
-
<DocsPageShellPortalInner {...props} />
|
|
119
|
-
</DocsPageAsideProvider>
|
|
120
|
-
);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
return <DocsPageShellInner {...props} />;
|
|
124
|
-
}
|
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import { Command, Dialog, Button, Text, Stack } from '@fragments-sdk/ui';
|
|
4
|
-
import { useEffect, useMemo, useState, useCallback } from 'react';
|
|
5
|
-
import type { SearchItem } from './types';
|
|
6
|
-
|
|
7
|
-
interface DocsSearchCommandProps {
|
|
8
|
-
searchItems: SearchItem[];
|
|
9
|
-
onSelect: (item: SearchItem) => void;
|
|
10
|
-
placeholder?: string;
|
|
11
|
-
maxResults?: number;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export function DocsSearchCommand({
|
|
15
|
-
searchItems,
|
|
16
|
-
onSelect,
|
|
17
|
-
placeholder = 'Search docs...',
|
|
18
|
-
maxResults = 9999,
|
|
19
|
-
}: DocsSearchCommandProps) {
|
|
20
|
-
const [open, setOpen] = useState(false);
|
|
21
|
-
|
|
22
|
-
// Cmd+K / Ctrl+K to open
|
|
23
|
-
useEffect(() => {
|
|
24
|
-
const handleKeyDown = (event: KeyboardEvent) => {
|
|
25
|
-
if ((event.metaKey || event.ctrlKey) && event.key === 'k') {
|
|
26
|
-
event.preventDefault();
|
|
27
|
-
setOpen((prev) => !prev);
|
|
28
|
-
}
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
document.addEventListener('keydown', handleKeyDown);
|
|
32
|
-
return () => document.removeEventListener('keydown', handleKeyDown);
|
|
33
|
-
}, []);
|
|
34
|
-
|
|
35
|
-
// Group items by section
|
|
36
|
-
const grouped = useMemo(() => {
|
|
37
|
-
const map = new Map<string, SearchItem[]>();
|
|
38
|
-
for (const item of searchItems) {
|
|
39
|
-
const section = item.section || 'Navigation';
|
|
40
|
-
if (!map.has(section)) map.set(section, []);
|
|
41
|
-
map.get(section)!.push(item);
|
|
42
|
-
}
|
|
43
|
-
return map;
|
|
44
|
-
}, [searchItems]);
|
|
45
|
-
|
|
46
|
-
const handleSelect = useCallback(
|
|
47
|
-
(item: SearchItem) => {
|
|
48
|
-
setOpen(false);
|
|
49
|
-
onSelect(item);
|
|
50
|
-
},
|
|
51
|
-
[onSelect],
|
|
52
|
-
);
|
|
53
|
-
|
|
54
|
-
return (
|
|
55
|
-
<>
|
|
56
|
-
<Button
|
|
57
|
-
variant="secondary"
|
|
58
|
-
size="sm"
|
|
59
|
-
onClick={() => setOpen(true)}
|
|
60
|
-
aria-label="Search documentation"
|
|
61
|
-
style={{ minWidth: 160, justifyContent: 'space-between' }}
|
|
62
|
-
>
|
|
63
|
-
<Text size="sm" color="secondary">Search...</Text>
|
|
64
|
-
<Text size="xs" color="secondary" font="mono">⌘K</Text>
|
|
65
|
-
</Button>
|
|
66
|
-
|
|
67
|
-
<Dialog open={open} onOpenChange={setOpen}>
|
|
68
|
-
<Dialog.Content size="sm" style={{ padding: 0, overflow: 'hidden' }}>
|
|
69
|
-
<Command
|
|
70
|
-
filter={(value, search) => {
|
|
71
|
-
if (value.toLowerCase().includes(search.toLowerCase())) return 1;
|
|
72
|
-
return 0;
|
|
73
|
-
}}
|
|
74
|
-
>
|
|
75
|
-
<Command.Input placeholder={placeholder} />
|
|
76
|
-
<Command.List>
|
|
77
|
-
<Command.Empty>No results found.</Command.Empty>
|
|
78
|
-
{[...grouped.entries()].map(([section, items]) => (
|
|
79
|
-
<Command.Group key={section} heading={section}>
|
|
80
|
-
{items.slice(0, maxResults).map((item) => (
|
|
81
|
-
<Command.Item
|
|
82
|
-
key={`${item.section}:${item.href}`}
|
|
83
|
-
value={`${item.label} ${item.section}`}
|
|
84
|
-
onItemSelect={() => handleSelect(item)}
|
|
85
|
-
>
|
|
86
|
-
<Stack direction="row" align="center" justify="between" style={{ width: '100%' }}>
|
|
87
|
-
<Text size="sm">{item.label}</Text>
|
|
88
|
-
</Stack>
|
|
89
|
-
</Command.Item>
|
|
90
|
-
))}
|
|
91
|
-
</Command.Group>
|
|
92
|
-
))}
|
|
93
|
-
</Command.List>
|
|
94
|
-
</Command>
|
|
95
|
-
</Dialog.Content>
|
|
96
|
-
</Dialog>
|
|
97
|
-
</>
|
|
98
|
-
);
|
|
99
|
-
}
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import { Sidebar } from '@fragments-sdk/ui';
|
|
4
|
-
import type { ReactNode } from 'react';
|
|
5
|
-
import type { DocsNavLinkRenderer, NavSection } from './types';
|
|
6
|
-
|
|
7
|
-
interface DocsSidebarNavProps {
|
|
8
|
-
sections: NavSection[];
|
|
9
|
-
currentPath: string;
|
|
10
|
-
renderLink?: DocsNavLinkRenderer;
|
|
11
|
-
onNavigate?: () => void;
|
|
12
|
-
isActive?: (href: string, currentPath: string) => boolean;
|
|
13
|
-
footer?: ReactNode;
|
|
14
|
-
ariaLabel?: string;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
function defaultIsActive(href: string, currentPath: string): boolean {
|
|
18
|
-
return currentPath === href;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const defaultLinkRenderer: DocsNavLinkRenderer = ({ href, label, onClick }) => (
|
|
22
|
-
<a href={href} onClick={onClick}>
|
|
23
|
-
{label}
|
|
24
|
-
</a>
|
|
25
|
-
);
|
|
26
|
-
|
|
27
|
-
export function DocsSidebarNav({
|
|
28
|
-
sections,
|
|
29
|
-
currentPath,
|
|
30
|
-
renderLink = defaultLinkRenderer,
|
|
31
|
-
onNavigate,
|
|
32
|
-
isActive = defaultIsActive,
|
|
33
|
-
footer,
|
|
34
|
-
ariaLabel = 'Navigation',
|
|
35
|
-
}: DocsSidebarNavProps) {
|
|
36
|
-
return (
|
|
37
|
-
<>
|
|
38
|
-
<Sidebar.Nav aria-label={ariaLabel}>
|
|
39
|
-
{sections.map((section) => (
|
|
40
|
-
<Sidebar.Section
|
|
41
|
-
key={section.title}
|
|
42
|
-
label={section.title}
|
|
43
|
-
collapsible={section.collapsible}
|
|
44
|
-
defaultOpen={section.defaultOpen}
|
|
45
|
-
>
|
|
46
|
-
{section.items.map((item) => (
|
|
47
|
-
<Sidebar.Item
|
|
48
|
-
key={item.href}
|
|
49
|
-
active={isActive(item.href, currentPath)}
|
|
50
|
-
asChild
|
|
51
|
-
>
|
|
52
|
-
{renderLink({
|
|
53
|
-
href: item.href,
|
|
54
|
-
label: item.label,
|
|
55
|
-
onClick: onNavigate,
|
|
56
|
-
})}
|
|
57
|
-
</Sidebar.Item>
|
|
58
|
-
))}
|
|
59
|
-
</Sidebar.Section>
|
|
60
|
-
))}
|
|
61
|
-
</Sidebar.Nav>
|
|
62
|
-
|
|
63
|
-
<Sidebar.Footer>{footer}</Sidebar.Footer>
|
|
64
|
-
</>
|
|
65
|
-
);
|
|
66
|
-
}
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
.container {
|
|
2
|
-
margin: 1.5rem 0;
|
|
3
|
-
overflow-x: auto;
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
.empty {
|
|
7
|
-
color: var(--fui-text-tertiary);
|
|
8
|
-
font-style: italic;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
.table {
|
|
12
|
-
width: 100%;
|
|
13
|
-
border-collapse: collapse;
|
|
14
|
-
font-size: 0.875rem;
|
|
15
|
-
|
|
16
|
-
th, td {
|
|
17
|
-
text-align: left;
|
|
18
|
-
padding: 0.75rem;
|
|
19
|
-
border-bottom: 1px solid var(--fui-border);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
th {
|
|
23
|
-
font-weight: var(--fui-font-weight-semibold);
|
|
24
|
-
color: var(--fui-text-secondary);
|
|
25
|
-
background-color: var(--fui-bg-secondary);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
td {
|
|
29
|
-
vertical-align: top;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
.propName {
|
|
34
|
-
display: flex;
|
|
35
|
-
align-items: center;
|
|
36
|
-
gap: 0.5rem;
|
|
37
|
-
|
|
38
|
-
code {
|
|
39
|
-
font-weight: var(--fui-font-weight-semibold);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
.type {
|
|
44
|
-
display: flex;
|
|
45
|
-
flex-direction: column;
|
|
46
|
-
gap: 0.25rem;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
.values {
|
|
50
|
-
display: flex;
|
|
51
|
-
flex-wrap: wrap;
|
|
52
|
-
gap: 0.25rem;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
.value {
|
|
56
|
-
font-size: 0.75rem;
|
|
57
|
-
background-color: var(--fui-bg-tertiary);
|
|
58
|
-
padding: 0.125rem 0.375rem;
|
|
59
|
-
border-radius: var(--fui-radius-sm);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
.default {
|
|
63
|
-
color: var(--fui-color-accent);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
.noDefault {
|
|
67
|
-
color: var(--fui-text-tertiary);
|
|
68
|
-
}
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import { Badge } from '@fragments-sdk/ui';
|
|
4
|
-
import type { DocProp } from './types';
|
|
5
|
-
import styles from './PropsTable.module.scss';
|
|
6
|
-
|
|
7
|
-
/** Detect auto-generated descriptions like "variant prop" */
|
|
8
|
-
function isGenericPropDescription(name: string, description: string): boolean {
|
|
9
|
-
const lower = description.toLowerCase().trim();
|
|
10
|
-
return lower === `${name.toLowerCase()} prop` || lower === `${name.toLowerCase()} property`;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
interface PropsTableProps {
|
|
14
|
-
props: Record<string, DocProp>;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export function PropsTable({ props }: PropsTableProps) {
|
|
18
|
-
const propEntries = Object.entries(props);
|
|
19
|
-
|
|
20
|
-
if (propEntries.length === 0) {
|
|
21
|
-
return <p className={styles.empty}>No props documented</p>;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
return (
|
|
25
|
-
<div className={styles.container}>
|
|
26
|
-
<table className={styles.table}>
|
|
27
|
-
<thead>
|
|
28
|
-
<tr>
|
|
29
|
-
<th>Prop</th>
|
|
30
|
-
<th>Type</th>
|
|
31
|
-
<th>Default</th>
|
|
32
|
-
<th>Description</th>
|
|
33
|
-
</tr>
|
|
34
|
-
</thead>
|
|
35
|
-
<tbody>
|
|
36
|
-
{propEntries.map(([name, prop]) => (
|
|
37
|
-
<tr key={name}>
|
|
38
|
-
<td>
|
|
39
|
-
<span className={styles.propName}>
|
|
40
|
-
<code>{name}</code>
|
|
41
|
-
{prop.required && (
|
|
42
|
-
<Badge size="sm" variant="error">
|
|
43
|
-
Required
|
|
44
|
-
</Badge>
|
|
45
|
-
)}
|
|
46
|
-
</span>
|
|
47
|
-
</td>
|
|
48
|
-
<td>
|
|
49
|
-
<span className={styles.type}>
|
|
50
|
-
<code>{prop.type}</code>
|
|
51
|
-
{prop.values && (
|
|
52
|
-
<span className={styles.values}>
|
|
53
|
-
{prop.values.map((v) => (
|
|
54
|
-
<code key={v} className={styles.value}>
|
|
55
|
-
{v}
|
|
56
|
-
</code>
|
|
57
|
-
))}
|
|
58
|
-
</span>
|
|
59
|
-
)}
|
|
60
|
-
</span>
|
|
61
|
-
</td>
|
|
62
|
-
<td>
|
|
63
|
-
{prop.default !== undefined ? (
|
|
64
|
-
<code className={styles.default}>{String(prop.default)}</code>
|
|
65
|
-
) : (
|
|
66
|
-
<span className={styles.noDefault}>Not set</span>
|
|
67
|
-
)}
|
|
68
|
-
</td>
|
|
69
|
-
<td>{prop.description && !isGenericPropDescription(name, prop.description) ? prop.description : '—'}</td>
|
|
70
|
-
</tr>
|
|
71
|
-
))}
|
|
72
|
-
</tbody>
|
|
73
|
-
</table>
|
|
74
|
-
</div>
|
|
75
|
-
);
|
|
76
|
-
}
|
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
// Shared variant preview card — used by docs and CLI viewer
|
|
2
|
-
.card {
|
|
3
|
-
border: 1px solid var(--fui-border);
|
|
4
|
-
border-radius: var(--fui-radius-lg);
|
|
5
|
-
overflow: hidden;
|
|
6
|
-
background-color: var(--fui-bg-primary);
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
.highlighted {
|
|
10
|
-
border-color: var(--fui-color-accent);
|
|
11
|
-
box-shadow: 0 0 0 1px color-mix(in srgb, var(--fui-color-accent) 40%, transparent);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
.header {
|
|
15
|
-
display: flex;
|
|
16
|
-
align-items: center;
|
|
17
|
-
justify-content: space-between;
|
|
18
|
-
gap: var(--fui-space-4);
|
|
19
|
-
padding: var(--fui-space-2) var(--fui-space-4);
|
|
20
|
-
background-color: var(--fui-bg-primary);
|
|
21
|
-
border-bottom: 1px solid var(--fui-border);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
.headerContent {
|
|
25
|
-
flex: 1;
|
|
26
|
-
min-width: 0;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
.title {
|
|
30
|
-
font-size: var(--fui-font-size-sm);
|
|
31
|
-
font-weight: var(--fui-font-weight-semibold);
|
|
32
|
-
color: var(--fui-text-primary);
|
|
33
|
-
margin: 0;
|
|
34
|
-
line-height: 1.4;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
.description {
|
|
38
|
-
font-size: var(--fui-font-size-xs);
|
|
39
|
-
color: var(--fui-text-tertiary);
|
|
40
|
-
margin: var(--fui-space-0-5) 0 0 0;
|
|
41
|
-
line-height: 1.4;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// Preview area with subtle dotted grid pattern
|
|
45
|
-
.previewPanel {
|
|
46
|
-
position: relative;
|
|
47
|
-
padding: var(--fui-space-4);
|
|
48
|
-
display: flex;
|
|
49
|
-
flex-direction: column;
|
|
50
|
-
align-items: center;
|
|
51
|
-
justify-content: center;
|
|
52
|
-
background-color: var(--fui-bg-primary);
|
|
53
|
-
|
|
54
|
-
// Subtle dotted grid pattern
|
|
55
|
-
background-image: radial-gradient(circle, var(--fui-border) 1px, transparent 1px);
|
|
56
|
-
background-size: 24px 24px;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// Code panel
|
|
60
|
-
.codePanel {
|
|
61
|
-
background-color: var(--fui-bg-tertiary);
|
|
62
|
-
padding: 0 !important; // Override Tabs panel padding
|
|
63
|
-
|
|
64
|
-
// Override CodeBlock styles for embedded use
|
|
65
|
-
:global([class*="CodeBlock_container"]) {
|
|
66
|
-
border: none;
|
|
67
|
-
border-radius: 0;
|
|
68
|
-
margin: 0;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
:global([class*="CodeBlock_wrapper"]) {
|
|
72
|
-
border-top-left-radius: 0;
|
|
73
|
-
border-top-right-radius: 0;
|
|
74
|
-
border: none;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
:global([class*="CodeBlock_title"]) {
|
|
78
|
-
display: none;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
.placeholder {
|
|
83
|
-
color: var(--fui-text-tertiary);
|
|
84
|
-
font-style: italic;
|
|
85
|
-
font-size: var(--fui-font-size-sm);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
.headerActions {
|
|
89
|
-
display: flex;
|
|
90
|
-
align-items: center;
|
|
91
|
-
gap: var(--fui-space-2);
|
|
92
|
-
flex-shrink: 0;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// Override Tabs styling for preview cards
|
|
96
|
-
.card {
|
|
97
|
-
:global([class*="Tabs_root"]) {
|
|
98
|
-
display: flex;
|
|
99
|
-
flex-direction: column;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// Tabs list sits inline with header
|
|
103
|
-
:global([class*="Tabs_list"]) {
|
|
104
|
-
padding: 0;
|
|
105
|
-
border-bottom: none;
|
|
106
|
-
background-color: transparent;
|
|
107
|
-
flex-shrink: 0;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
:global([class*="Tabs_listPills"]) {
|
|
111
|
-
margin: 0;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
}
|