mirror of
https://github.com/mathuo/dockview
synced 2025-02-02 06:25:44 +00:00
parent
f00b3d88e1
commit
0634f4fe52
@ -667,21 +667,29 @@ export class DockviewApi implements CommonApi<SerializedDockview> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked before an overlay is shown indicating a drop target.
|
||||
*
|
||||
* Calling `event.preventDefault()` will prevent the overlay being shown and prevent
|
||||
* the any subsequent drop event.
|
||||
*/
|
||||
get onWillShowOverlay(): Event<WillShowOverlayLocationEvent> {
|
||||
return this.component.onWillShowOverlay;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked before a group is dragged. Exposed for custom Drag'n'Drop functionality.
|
||||
* Invoked before a group is dragged.
|
||||
*
|
||||
* Calling `event.nativeEvent.preventDefault()` will prevent the group drag starting.
|
||||
*
|
||||
*/
|
||||
get onWillDragGroup(): Event<GroupDragEvent> {
|
||||
return this.component.onWillDragGroup;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked before a panel is dragged. Exposed for custom Drag'n'Drop functionality.
|
||||
* Invoked before a panel is dragged.
|
||||
*
|
||||
* Calling `event.nativeEvent.preventDefault()` will prevent the panel drag starting.
|
||||
*/
|
||||
get onWillDragPanel(): Event<TabDragEvent> {
|
||||
return this.component.onWillDragPanel;
|
||||
|
@ -6,6 +6,10 @@ sidebar_position: 3
|
||||
import { DocRef } from '@site/src/components/ui/reference/docRef';
|
||||
|
||||
|
||||
:::info
|
||||
You may want to combine this with `locked={true}` to provide a locked grid with no dnd funtionality. See [Locked](/docs/core/locked) for more.
|
||||
:::
|
||||
|
||||
<FrameworkSpecific framework="JavaScript">
|
||||
<DocRef declaration="DockviewComponentOptions" methods={["disableDnd"]} />
|
||||
</FrameworkSpecific>
|
||||
|
@ -5,7 +5,6 @@ sidebar_position: 1
|
||||
|
||||
import useBaseUrl from '@docusaurus/useBaseUrl';
|
||||
import { MultiFrameworkContainer } from '@site/src/components/ui/container';
|
||||
import DndDockview from '@site/sandboxes/dnd-dockview/src/app';
|
||||
import DockviewExternalDnd from '@site/sandboxes/externaldnd-dockview/src/app';
|
||||
import LiveExample from '@site/src/components/ui/exampleFrame';
|
||||
|
||||
@ -16,7 +15,7 @@ The dock makes heavy use of drag and drop functionalities.
|
||||
<DocRef declaration="DockviewApi"
|
||||
methods={[
|
||||
'onWillDragPanel', 'onWillDragGroup',
|
||||
'onWillDrop', 'onDidDrop', 'onWillShowOverlay'
|
||||
'onWillDrop', 'onWillShowOverlay'
|
||||
]}
|
||||
/>
|
||||
|
||||
@ -79,12 +78,6 @@ return (
|
||||
);
|
||||
```
|
||||
|
||||
## Intercepting Drag Events
|
||||
|
||||
You can intercept drag events to attach your own metadata using the `onWillDragPanel` and `onWillDragGroup` api methods.
|
||||
|
||||
<MultiFrameworkContainer sandboxId="dnd-dockview" react={DndDockview} />
|
||||
|
||||
## Third Party Dnd Libraries
|
||||
|
||||
This shows a simple example of a third-party library used inside a panel that relies on drag
|
||||
|
31
packages/docs/docs/core/dnd/external.mdx
Normal file
31
packages/docs/docs/core/dnd/external.mdx
Normal file
@ -0,0 +1,31 @@
|
||||
---
|
||||
title: 'External Dnd Events'
|
||||
sidebar_position: 3
|
||||
---
|
||||
|
||||
External Dnd events can be intercepted through a number of utilities.
|
||||
|
||||
import { DocRef } from '@site/src/components/ui/reference/docRef';
|
||||
import LiveExample from '@site/src/components/ui/exampleFrame';
|
||||
|
||||
<DocRef declaration="DockviewApi"
|
||||
methods={['onDidDrop']}
|
||||
/>
|
||||
|
||||
|
||||
<FrameworkSpecific framework='React'>
|
||||
<DocRef declaration="IDockviewReactProps" methods={['showDndOverlay']} />
|
||||
</FrameworkSpecific>
|
||||
|
||||
<FrameworkSpecific framework='JavaScript'>
|
||||
<DocRef declaration="DockviewComponentOptions"
|
||||
methods={['showDndOverlay']}
|
||||
/>
|
||||
</FrameworkSpecific>
|
||||
|
||||
|
||||
## Intercepting Drag Events
|
||||
|
||||
You can intercept drag events to attach your own metadata using the `onWillDragPanel` and `onWillDragGroup` api methods.
|
||||
|
||||
<LiveExample framework='react' id="dockview/dnd-external" />
|
@ -4,11 +4,6 @@ sidebar_position: 0
|
||||
---
|
||||
|
||||
import useBaseUrl from '@docusaurus/useBaseUrl';
|
||||
import { MultiFrameworkContainer } from '@site/src/components/ui/container';
|
||||
import DndDockview from '@site/sandboxes/dnd-dockview/src/app';
|
||||
import DockviewExternalDnd from '@site/sandboxes/externaldnd-dockview/src/app';
|
||||
|
||||
import { DocRef } from '@site/src/components/ui/reference/docRef';
|
||||
|
||||
Dockview supports a wide variety of built-in Drag and Drop possibilities.
|
||||
|
||||
|
@ -9,4 +9,8 @@ import LiveExample from '@site/src/components/ui/exampleFrame';
|
||||
|
||||
This section describes how to lock the dock to prevent movement.
|
||||
|
||||
:::info
|
||||
You may want to combine this with `disableDnd={true}` to provide a locked grid with no dnd funtionality. See [Disable Dnd](/docs/core/dnd/disable) for more.
|
||||
:::
|
||||
|
||||
<LiveExample framework='react' id='dockview/locked'/>
|
||||
|
@ -3,5 +3,15 @@ title: Overview
|
||||
sidebar_position: 0
|
||||
---
|
||||
|
||||
import LiveExample from '@site/src/components/ui/exampleFrame';
|
||||
import { DocRef } from '@site/src/components/ui/reference/docRef';
|
||||
|
||||
The implementation of the dock is a collection of nested *splitview* controls forming a *gridview*
|
||||
which is exposed as a seperate component to be used independantly.
|
||||
|
||||
<DocRef declaration="IGridviewReactProps"/>
|
||||
|
||||
## Live Example
|
||||
|
||||
<LiveExample framework='react' id='gridview/simple' />
|
||||
|
||||
|
@ -2,5 +2,13 @@
|
||||
title: Overview
|
||||
sidebar_position: 0
|
||||
---
|
||||
import LiveExample from '@site/src/components/ui/exampleFrame';
|
||||
import { DocRef } from '@site/src/components/ui/reference/docRef';
|
||||
|
||||
A *splitview* control where each panel contains a header and collapsable content.
|
||||
|
||||
<DocRef declaration="IPaneviewReactProps"/>
|
||||
|
||||
## Live Example
|
||||
|
||||
<LiveExample framework='react' id='paneview/simple' />
|
||||
|
@ -5,3 +5,12 @@ sidebar_position: 0
|
||||
|
||||
The implementation of the dock is a collection of nested *splitview* controls
|
||||
which is exposed as a seperate component to be used independantly.
|
||||
|
||||
import LiveExample from '@site/src/components/ui/exampleFrame';
|
||||
import { DocRef } from '@site/src/components/ui/reference/docRef';
|
||||
|
||||
<DocRef declaration="ISplitviewReactProps"/>
|
||||
|
||||
## Live Example
|
||||
|
||||
<LiveExample framework='react' id='splitview/simple' height={200} />
|
||||
|
10
packages/docs/docs/other/tabview.mdx
Normal file
10
packages/docs/docs/other/tabview.mdx
Normal file
@ -0,0 +1,10 @@
|
||||
---
|
||||
title: Tabview
|
||||
sidebar_position: 3
|
||||
---
|
||||
|
||||
A *tabview* can be created using a dock and preventing some default behaviours.
|
||||
|
||||
import LiveExample from '@site/src/components/ui/exampleFrame';
|
||||
|
||||
<LiveExample framework='react' id='dockview/tabview' />
|
@ -35,6 +35,7 @@
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: #1c254a;
|
||||
color: white;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
outline: 1px solid #4c65d4;
|
||||
|
@ -28,7 +28,7 @@ const components = {
|
||||
position: 'relative',
|
||||
}}
|
||||
>
|
||||
<Table data={metadata} />
|
||||
{/* <Table data={metadata} /> */}
|
||||
<span
|
||||
style={{
|
||||
position: 'absolute',
|
||||
@ -68,8 +68,20 @@ const headerComponents = {
|
||||
},
|
||||
};
|
||||
|
||||
const colors = [
|
||||
'rgba(255,0,0,0.2)',
|
||||
'rgba(0,255,0,0.2)',
|
||||
'rgba(0,0,255,0.2)',
|
||||
'rgba(255,255,0,0.2)',
|
||||
'rgba(0,255,255,0.2)',
|
||||
'rgba(255,0,255,0.2)',
|
||||
];
|
||||
let count = 0;
|
||||
|
||||
const DockviewDemo = (props: { theme?: string }) => {
|
||||
const [logLines, setLogLines] = React.useState<any[]>([]);
|
||||
const [logLines, setLogLines] = React.useState<
|
||||
{ text: string; timestamp?: Date; backgroundColor?: string }[]
|
||||
>([]);
|
||||
|
||||
const [panels, setPanels] = React.useState<string[]>([]);
|
||||
const [groups, setGroups] = React.useState<string[]>([]);
|
||||
@ -78,16 +90,39 @@ const DockviewDemo = (props: { theme?: string }) => {
|
||||
const [activePanel, setActivePanel] = React.useState<string>();
|
||||
const [activeGroup, setActiveGroup] = React.useState<string>();
|
||||
|
||||
const [pending, setPending] = React.useState<
|
||||
{ text: string; timestamp?: Date }[]
|
||||
>([]);
|
||||
|
||||
const addLogLine = (message: string) => {
|
||||
setPending((line) => [
|
||||
{ text: message, timestamp: new Date() },
|
||||
...line,
|
||||
]);
|
||||
};
|
||||
|
||||
React.useLayoutEffect(() => {
|
||||
if (pending.length === 0) {
|
||||
return;
|
||||
}
|
||||
const color = colors[count++ % colors.length];
|
||||
setLogLines((lines) => [
|
||||
...pending.map((_) => ({ ..._, backgroundColor: color })),
|
||||
...lines,
|
||||
]);
|
||||
setPending([]);
|
||||
}, [pending]);
|
||||
|
||||
const onReady = (event: DockviewReadyEvent) => {
|
||||
setApi(event.api);
|
||||
|
||||
event.api.onDidAddPanel((event) => {
|
||||
setPanels((_) => [..._, event.id]);
|
||||
setLogLines((line) => [`Panel Added ${event.id}`, ...line]);
|
||||
addLogLine(`Panel Added ${event.id}`);
|
||||
});
|
||||
event.api.onDidActivePanelChange((event) => {
|
||||
setActivePanel(event?.id);
|
||||
setLogLines((line) => [`Panel Activated ${event?.id}`, ...line]);
|
||||
addLogLine(`Panel Activated ${event?.id}`);
|
||||
});
|
||||
event.api.onDidRemovePanel((event) => {
|
||||
setPanels((_) => {
|
||||
@ -99,12 +134,12 @@ const DockviewDemo = (props: { theme?: string }) => {
|
||||
|
||||
return next;
|
||||
});
|
||||
setLogLines((line) => [`Panel Removed ${event.id}`, ...line]);
|
||||
addLogLine(`Panel Removed ${event.id}`);
|
||||
});
|
||||
|
||||
event.api.onDidAddGroup((event) => {
|
||||
setGroups((_) => [..._, event.id]);
|
||||
setLogLines((line) => [`Group Added ${event.id}`, ...line]);
|
||||
addLogLine(`Group Added ${event.id}`);
|
||||
});
|
||||
|
||||
event.api.onDidRemoveGroup((event) => {
|
||||
@ -117,12 +152,12 @@ const DockviewDemo = (props: { theme?: string }) => {
|
||||
|
||||
return next;
|
||||
});
|
||||
setLogLines((line) => [`Group Removed ${event.id}`, ...line]);
|
||||
addLogLine(`Group Removed ${event.id}`);
|
||||
});
|
||||
|
||||
event.api.onDidActiveGroupChange((event) => {
|
||||
setActiveGroup(event?.id);
|
||||
setLogLines((line) => [`Group Activated ${event?.id}`, ...line]);
|
||||
addLogLine(`Group Activated ${event?.id}`);
|
||||
});
|
||||
|
||||
const state = localStorage.getItem('dv-demo-state');
|
||||
@ -146,6 +181,9 @@ const DockviewDemo = (props: { theme?: string }) => {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
flexGrow: 1,
|
||||
padding: '8px',
|
||||
backgroundColor: 'rgba(0,0,50,0.25)',
|
||||
borderRadius: '8px',
|
||||
}}
|
||||
>
|
||||
<div>
|
||||
@ -167,6 +205,7 @@ const DockviewDemo = (props: { theme?: string }) => {
|
||||
overflow: 'hidden',
|
||||
// flexBasis: 0
|
||||
height: 0,
|
||||
display: 'flex',
|
||||
}}
|
||||
>
|
||||
<DockviewReact
|
||||
@ -178,33 +217,62 @@ const DockviewDemo = (props: { theme?: string }) => {
|
||||
onReady={onReady}
|
||||
className={props.theme || 'dockview-theme-abyss'}
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
height: '200px',
|
||||
backgroundColor: 'black',
|
||||
color: 'white',
|
||||
overflow: 'auto',
|
||||
}}
|
||||
>
|
||||
{logLines.map((line, i) => {
|
||||
return (
|
||||
<div key={i}>
|
||||
<span
|
||||
<div
|
||||
style={{
|
||||
// height: '200px',
|
||||
width: '300px',
|
||||
backgroundColor: 'black',
|
||||
color: 'white',
|
||||
overflow: 'auto',
|
||||
}}
|
||||
>
|
||||
{logLines.map((line, i) => {
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
display: 'inline-block',
|
||||
width: '30px',
|
||||
color: 'gray',
|
||||
borderRight: '1px solid gray',
|
||||
marginRight: '4px',
|
||||
height: '30px',
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
whiteSpace: 'nowrap',
|
||||
fontSize: '13px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
backgroundColor: line.backgroundColor,
|
||||
}}
|
||||
key={i}
|
||||
>
|
||||
{logLines.length - i}
|
||||
</span>
|
||||
<span>{line}</span>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
<span
|
||||
style={{
|
||||
display: 'inline-block',
|
||||
width: '20px',
|
||||
color: 'gray',
|
||||
borderRight: '1px solid gray',
|
||||
marginRight: '4px',
|
||||
paddingLeft: '2px',
|
||||
height: '100%',
|
||||
}}
|
||||
>
|
||||
{logLines.length - i}
|
||||
</span>
|
||||
<span>
|
||||
{line.timestamp && (
|
||||
<span
|
||||
style={{
|
||||
fontSize: '0.7em',
|
||||
padding: '0px 2px',
|
||||
}}
|
||||
>
|
||||
{line.timestamp
|
||||
.toISOString()
|
||||
.substring(11, 23)}
|
||||
</span>
|
||||
)}
|
||||
<span>{line.text}</span>
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -11,7 +11,7 @@ export const nextId = (() => {
|
||||
export function defaultConfig(api: DockviewApi) {
|
||||
const panel1 = api.addPanel({
|
||||
id: 'panel_1',
|
||||
component: 'iframe',
|
||||
component: 'default',
|
||||
renderer: 'always',
|
||||
title: 'Panel 1',
|
||||
});
|
||||
|
@ -0,0 +1,32 @@
|
||||
{
|
||||
"name": "dockview.dnd-external",
|
||||
"description": "",
|
||||
"keywords": [
|
||||
"dockview"
|
||||
],
|
||||
"version": "1.0.0",
|
||||
"main": "src/index.tsx",
|
||||
"dependencies": {
|
||||
"dockview": "*",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^18.0.28",
|
||||
"@types/react-dom": "^18.0.11",
|
||||
"typescript": "^4.9.5",
|
||||
"react-scripts": "*"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-scripts start",
|
||||
"build": "react-scripts build",
|
||||
"test": "react-scripts test --env=jsdom",
|
||||
"eject": "react-scripts eject"
|
||||
},
|
||||
"browserslist": [
|
||||
">0.2%",
|
||||
"not dead",
|
||||
"not ie <= 11",
|
||||
"not op_mini all"
|
||||
]
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
import {
|
||||
DockviewApi,
|
||||
DockviewDndOverlayEvent,
|
||||
DockviewDropEvent,
|
||||
DockviewDidDropEvent,
|
||||
DockviewReact,
|
||||
DockviewReadyEvent,
|
||||
IDockviewPanelProps,
|
||||
@ -123,7 +123,7 @@ const DndDockview = (props: { renderVisibleOnly: boolean; theme?: string }) => {
|
||||
setApi(event.api);
|
||||
};
|
||||
|
||||
const onDidDrop = (event: DockviewDropEvent) => {
|
||||
const onDidDrop = (event: DockviewDidDropEvent) => {
|
||||
event.api.addPanel({
|
||||
id: 'test',
|
||||
component: 'default',
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "dnd-dockview",
|
||||
"name": "dockview.tabview",
|
||||
"description": "",
|
||||
"keywords": [
|
||||
"dockview"
|
82
packages/docs/sandboxes/react/dockview/tabview/src/app.tsx
Normal file
82
packages/docs/sandboxes/react/dockview/tabview/src/app.tsx
Normal file
@ -0,0 +1,82 @@
|
||||
import {
|
||||
DockviewApi,
|
||||
DockviewReact,
|
||||
DockviewReadyEvent,
|
||||
IDockviewPanelProps,
|
||||
} from 'dockview';
|
||||
import * as React from 'react';
|
||||
|
||||
const Default = (props: IDockviewPanelProps) => {
|
||||
return (
|
||||
<div style={{ height: '100%' }}>
|
||||
<div>{props.api.title}</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const components = {
|
||||
default: Default,
|
||||
};
|
||||
|
||||
const Component = (props: { theme?: string }) => {
|
||||
const [api, setApi] = React.useState<DockviewApi>();
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!api) {
|
||||
return;
|
||||
}
|
||||
|
||||
const disposables = [
|
||||
api.onWillShowOverlay((e) => {
|
||||
if (e.kind === 'header_space' || e.kind === 'tab') {
|
||||
return;
|
||||
}
|
||||
e.preventDefault();
|
||||
}),
|
||||
];
|
||||
|
||||
return () => {
|
||||
disposables.forEach((disposable) => {
|
||||
disposable.dispose();
|
||||
});
|
||||
};
|
||||
}, [api]);
|
||||
|
||||
const onReady = (event: DockviewReadyEvent) => {
|
||||
setApi(event.api);
|
||||
|
||||
event.api.addPanel({
|
||||
id: 'panel_1',
|
||||
component: 'default',
|
||||
});
|
||||
|
||||
event.api.addPanel({
|
||||
id: 'panel_2',
|
||||
component: 'default',
|
||||
});
|
||||
|
||||
event.api.addPanel({
|
||||
id: 'panel_3',
|
||||
component: 'default',
|
||||
});
|
||||
event.api.addPanel({
|
||||
id: 'panel_4',
|
||||
component: 'default',
|
||||
});
|
||||
event.api.addPanel({
|
||||
id: 'panel_5',
|
||||
component: 'default',
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<DockviewReact
|
||||
className={`${props.theme || 'dockview-theme-abyss'}`}
|
||||
onReady={onReady}
|
||||
components={components}
|
||||
disableFloatingGroups={true}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default Component;
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "simple-gridview",
|
||||
"name": "gridview.simple",
|
||||
"description": "",
|
||||
"keywords": [
|
||||
"dockview"
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "simple-paneview",
|
||||
"name": "paneview.simple",
|
||||
"description": "",
|
||||
"keywords": [
|
||||
"dockview"
|
@ -0,0 +1,44 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<meta name="theme-color" content="#000000">
|
||||
<!--
|
||||
manifest.json provides metadata used when your web app is added to the
|
||||
homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
|
||||
-->
|
||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
|
||||
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200" />
|
||||
<!--
|
||||
Notice the use of %PUBLIC_URL% in the tags above.
|
||||
It will be replaced with the URL of the `public` folder during the build.
|
||||
Only files inside the `public` folder can be referenced from the HTML.
|
||||
|
||||
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
|
||||
work correctly both with client-side routing and a non-root public URL.
|
||||
Learn how to configure a non-root public URL by running `npm run build`.
|
||||
-->
|
||||
<title>React App</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<noscript>
|
||||
You need to enable JavaScript to run this app.
|
||||
</noscript>
|
||||
<div id="root"></div>
|
||||
<!--
|
||||
This HTML file is a template.
|
||||
If you open it directly in the browser, you will see an empty page.
|
||||
|
||||
You can add webfonts, meta tags, or analytics to this file.
|
||||
The build step will place the bundled scripts into the <body> tag.
|
||||
|
||||
To begin the development, run `npm start` or `yarn start`.
|
||||
To create a production bundle, use `npm run build` or `yarn build`.
|
||||
-->
|
||||
</body>
|
||||
|
||||
</html>
|
20
packages/docs/sandboxes/react/paneview/simple/src/index.tsx
Normal file
20
packages/docs/sandboxes/react/paneview/simple/src/index.tsx
Normal file
@ -0,0 +1,20 @@
|
||||
import { StrictMode } from 'react';
|
||||
import * as ReactDOMClient from 'react-dom/client';
|
||||
import './styles.css';
|
||||
import 'dockview/dist/styles/dockview.css';
|
||||
|
||||
import App from './app';
|
||||
|
||||
const rootElement = document.getElementById('root');
|
||||
|
||||
if (rootElement) {
|
||||
const root = ReactDOMClient.createRoot(rootElement);
|
||||
|
||||
root.render(
|
||||
<StrictMode>
|
||||
<div className="app">
|
||||
<App />
|
||||
</div>
|
||||
</StrictMode>
|
||||
);
|
||||
}
|
16
packages/docs/sandboxes/react/paneview/simple/src/styles.css
Normal file
16
packages/docs/sandboxes/react/paneview/simple/src/styles.css
Normal file
@ -0,0 +1,16 @@
|
||||
body {
|
||||
margin: 0px;
|
||||
color: white;
|
||||
font-family: sans-serif;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#root {
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
}
|
||||
|
||||
.app {
|
||||
height: 100%;
|
||||
|
||||
}
|
18
packages/docs/sandboxes/react/paneview/simple/tsconfig.json
Normal file
18
packages/docs/sandboxes/react/paneview/simple/tsconfig.json
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"outDir": "build/dist",
|
||||
"module": "esnext",
|
||||
"target": "es5",
|
||||
"lib": ["es6", "dom"],
|
||||
"sourceMap": true,
|
||||
"allowJs": true,
|
||||
"jsx": "react-jsx",
|
||||
"moduleResolution": "node",
|
||||
"rootDir": "src",
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"noImplicitReturns": true,
|
||||
"noImplicitThis": true,
|
||||
"noImplicitAny": true,
|
||||
"strictNullChecks": true
|
||||
}
|
||||
}
|
32
packages/docs/sandboxes/react/splitview/simple/package.json
Normal file
32
packages/docs/sandboxes/react/splitview/simple/package.json
Normal file
@ -0,0 +1,32 @@
|
||||
{
|
||||
"name": "splitview.simple",
|
||||
"description": "",
|
||||
"keywords": [
|
||||
"dockview"
|
||||
],
|
||||
"version": "1.0.0",
|
||||
"main": "src/index.tsx",
|
||||
"dependencies": {
|
||||
"dockview": "*",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^18.0.28",
|
||||
"@types/react-dom": "^18.0.11",
|
||||
"typescript": "^4.9.5",
|
||||
"react-scripts": "*"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-scripts start",
|
||||
"build": "react-scripts build",
|
||||
"test": "react-scripts test --env=jsdom",
|
||||
"eject": "react-scripts eject"
|
||||
},
|
||||
"browserslist": [
|
||||
">0.2%",
|
||||
"not dead",
|
||||
"not ie <= 11",
|
||||
"not op_mini all"
|
||||
]
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<meta name="theme-color" content="#000000">
|
||||
<!--
|
||||
manifest.json provides metadata used when your web app is added to the
|
||||
homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
|
||||
-->
|
||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
|
||||
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200" />
|
||||
<!--
|
||||
Notice the use of %PUBLIC_URL% in the tags above.
|
||||
It will be replaced with the URL of the `public` folder during the build.
|
||||
Only files inside the `public` folder can be referenced from the HTML.
|
||||
|
||||
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
|
||||
work correctly both with client-side routing and a non-root public URL.
|
||||
Learn how to configure a non-root public URL by running `npm run build`.
|
||||
-->
|
||||
<title>React App</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<noscript>
|
||||
You need to enable JavaScript to run this app.
|
||||
</noscript>
|
||||
<div id="root"></div>
|
||||
<!--
|
||||
This HTML file is a template.
|
||||
If you open it directly in the browser, you will see an empty page.
|
||||
|
||||
You can add webfonts, meta tags, or analytics to this file.
|
||||
The build step will place the bundled scripts into the <body> tag.
|
||||
|
||||
To begin the development, run `npm start` or `yarn start`.
|
||||
To create a production bundle, use `npm run build` or `yarn build`.
|
||||
-->
|
||||
</body>
|
||||
|
||||
</html>
|
59
packages/docs/sandboxes/react/splitview/simple/src/app.tsx
Normal file
59
packages/docs/sandboxes/react/splitview/simple/src/app.tsx
Normal file
@ -0,0 +1,59 @@
|
||||
import {
|
||||
SplitviewReact,
|
||||
SplitviewReadyEvent,
|
||||
ISplitviewPanelProps,
|
||||
} from 'dockview';
|
||||
import * as React from 'react';
|
||||
|
||||
const components = {
|
||||
default: (props: ISplitviewPanelProps<{ title: string }>) => {
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
padding: '10px',
|
||||
height: '100%',
|
||||
}}
|
||||
>
|
||||
{props.params.title}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
export const App: React.FC = (props: { theme?: string }) => {
|
||||
const onReady = (event: SplitviewReadyEvent) => {
|
||||
event.api.addPanel({
|
||||
id: 'panel_1',
|
||||
component: 'default',
|
||||
params: {
|
||||
title: 'Panel 1',
|
||||
},
|
||||
});
|
||||
|
||||
event.api.addPanel({
|
||||
id: 'panel_2',
|
||||
component: 'default',
|
||||
params: {
|
||||
title: 'Panel 2',
|
||||
},
|
||||
});
|
||||
|
||||
event.api.addPanel({
|
||||
id: 'panel_3',
|
||||
component: 'default',
|
||||
params: {
|
||||
title: 'Panel 3',
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<SplitviewReact
|
||||
components={components}
|
||||
onReady={onReady}
|
||||
className={props.theme || 'dockview-theme-abyss'}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default App;
|
20
packages/docs/sandboxes/react/splitview/simple/src/index.tsx
Normal file
20
packages/docs/sandboxes/react/splitview/simple/src/index.tsx
Normal file
@ -0,0 +1,20 @@
|
||||
import { StrictMode } from 'react';
|
||||
import * as ReactDOMClient from 'react-dom/client';
|
||||
import './styles.css';
|
||||
import 'dockview/dist/styles/dockview.css';
|
||||
|
||||
import App from './app';
|
||||
|
||||
const rootElement = document.getElementById('root');
|
||||
|
||||
if (rootElement) {
|
||||
const root = ReactDOMClient.createRoot(rootElement);
|
||||
|
||||
root.render(
|
||||
<StrictMode>
|
||||
<div className="app">
|
||||
<App />
|
||||
</div>
|
||||
</StrictMode>
|
||||
);
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
body {
|
||||
margin: 0px;
|
||||
color: white;
|
||||
font-family: sans-serif;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#root {
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
}
|
||||
|
||||
.app {
|
||||
height: 100%;
|
||||
|
||||
}
|
18
packages/docs/sandboxes/react/splitview/simple/tsconfig.json
Normal file
18
packages/docs/sandboxes/react/splitview/simple/tsconfig.json
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"outDir": "build/dist",
|
||||
"module": "esnext",
|
||||
"target": "es5",
|
||||
"lib": ["es6", "dom"],
|
||||
"sourceMap": true,
|
||||
"allowJs": true,
|
||||
"jsx": "react-jsx",
|
||||
"moduleResolution": "node",
|
||||
"rootDir": "src",
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"noImplicitReturns": true,
|
||||
"noImplicitThis": true,
|
||||
"noImplicitAny": true,
|
||||
"strictNullChecks": true
|
||||
}
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
import BrowserOnly from '@docusaurus/BrowserOnly';
|
||||
import { DockviewEmitter } from 'dockview';
|
||||
import * as React from 'react';
|
||||
import { IS_PROD } from '../flags';
|
||||
|
||||
const frameworks = [
|
||||
{ value: 'JavaScript', label: 'JavaScript' },
|
||||
@ -35,7 +36,7 @@ function useActiveFramework(): [string, (value: string) => void] {
|
||||
activeFrameworkGlobal.fire(value);
|
||||
}, []);
|
||||
|
||||
return [value, setter];
|
||||
return [IS_PROD ? frameworks[1].value : value, setter];
|
||||
}
|
||||
|
||||
const FrameworkSelector1 = () => {
|
||||
@ -45,6 +46,10 @@ const FrameworkSelector1 = () => {
|
||||
setActiveFramework(event.target.value),
|
||||
];
|
||||
|
||||
if (IS_PROD) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<select onChange={onChange} value={activeFramework}>
|
||||
{frameworks.map((framework) => {
|
||||
|
@ -8,6 +8,7 @@ export interface DocRefProps {
|
||||
}
|
||||
|
||||
import docsJson_ from '../../../generated/api.output.json';
|
||||
import { ExportedTypeFile, TypeSystem, codify, firstLevel } from './types';
|
||||
const docsJson = docsJson_ as any as DocsJson;
|
||||
|
||||
type DocsContent = { kind: string; text: string; tag?: string };
|
||||
@ -16,19 +17,57 @@ type DocsComment = {
|
||||
summary?: DocsContent[];
|
||||
blockTags?: DocsTag[];
|
||||
};
|
||||
|
||||
type Piece = {
|
||||
kind: 'return' | 'paramter' | 'signature' | 'typearg' | 'typearg_default';
|
||||
value: string;
|
||||
};
|
||||
|
||||
type Doc = {
|
||||
name: string;
|
||||
code: string;
|
||||
comment?: DocsComment;
|
||||
kind: 'accessor' | 'property' | 'method';
|
||||
pieces: string[];
|
||||
pieces: Piece[];
|
||||
};
|
||||
|
||||
type DocJson = {
|
||||
kind: string;
|
||||
metadata?: Doc;
|
||||
children: Doc[];
|
||||
};
|
||||
|
||||
type DocsJson = {
|
||||
[index: string]: {
|
||||
kind: string;
|
||||
metadata?: Doc;
|
||||
children: Doc[];
|
||||
};
|
||||
[index: string]: DocJson;
|
||||
};
|
||||
|
||||
const newJson = docsJson_ as ExportedTypeFile;
|
||||
|
||||
export const DocumentRef = (props: { value: TypeSystem.Type }) => {
|
||||
const code = React.useMemo(() => {
|
||||
if (!props.value) {
|
||||
return null;
|
||||
}
|
||||
|
||||
switch (props.value.kind) {
|
||||
case 'typeAlias':
|
||||
return codify(props.value);
|
||||
case 'interface':
|
||||
return codify(props.value);
|
||||
case 'class':
|
||||
return codify(props.value);
|
||||
case 'function':
|
||||
return codify(props.value);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}, [props.value]);
|
||||
|
||||
if (!code) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return <CodeBlock language="tsx">{code}</CodeBlock>;
|
||||
};
|
||||
|
||||
export const Text = (props: { content: DocsContent[] }) => {
|
||||
@ -81,25 +120,11 @@ export const Markdown = (props: { children: string }) => {
|
||||
return <span>{props.children}</span>;
|
||||
};
|
||||
|
||||
const Piece = (props: { piece: string }) => {
|
||||
const item = docsJson[props.piece];
|
||||
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (item.kind === 'interface') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!item.metadata?.code) {
|
||||
return;
|
||||
}
|
||||
|
||||
return <CodeBlock language="tsx">{item.metadata.code}</CodeBlock>;
|
||||
};
|
||||
|
||||
const Row = (props: { doc: Doc }) => {
|
||||
const Row = (props: { doc: TypeSystem.Type }) => {
|
||||
const comment =
|
||||
props.doc.kind === 'accessor'
|
||||
? props.doc.value.comment
|
||||
: props.doc.comment;
|
||||
return (
|
||||
<tr>
|
||||
<th
|
||||
@ -151,12 +176,8 @@ const Row = (props: { doc: Doc }) => {
|
||||
<th style={{ width: '60%' }}>
|
||||
{/* <div>{'-'}</div> */}
|
||||
<div>
|
||||
<div>
|
||||
{props.doc.comment && (
|
||||
<Summary summary={props.doc.comment} />
|
||||
)}
|
||||
</div>
|
||||
<CodeBlock language="tsx">{props.doc.code}</CodeBlock>
|
||||
<div>{comment && <Summary summary={comment} />}</div>
|
||||
<CodeBlock language="tsx">{codify(props.doc)}</CodeBlock>
|
||||
</div>
|
||||
</th>
|
||||
</tr>
|
||||
@ -165,18 +186,23 @@ const Row = (props: { doc: Doc }) => {
|
||||
|
||||
export const DocRef = (props: DocRefProps) => {
|
||||
const docs = React.useMemo(
|
||||
() => (docsJson as DocsJson)[props.declaration],
|
||||
() => newJson[props.declaration],
|
||||
[props.declaration]
|
||||
);
|
||||
|
||||
const filteredDocs = React.useMemo(
|
||||
() =>
|
||||
docs?.children?.filter((child) => {
|
||||
if (props.methods && !props.methods.includes(child.name)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}),
|
||||
docs.kind === 'class' || docs.kind === 'interface'
|
||||
? docs.children.filter((child) => {
|
||||
if (
|
||||
props.methods &&
|
||||
!props.methods.includes(child.name)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
})
|
||||
: [],
|
||||
[docs]
|
||||
);
|
||||
|
||||
@ -191,6 +217,13 @@ export const DocRef = (props: DocRefProps) => {
|
||||
return (
|
||||
<>
|
||||
<Row key={i} doc={doc} />
|
||||
{/* <th colSpan={2}>
|
||||
{firstLevel(doc).map((x) => (
|
||||
<span style={{ padding: '0px 2px' }}>
|
||||
<DocumentRef value={newJson[x]} />
|
||||
</span>
|
||||
))}
|
||||
</th> */}
|
||||
{/* {doc.pieces?.map((piece) => (
|
||||
<tr>
|
||||
<th colSpan={2}>
|
||||
|
446
packages/docs/src/components/ui/reference/types.ts
Normal file
446
packages/docs/src/components/ui/reference/types.ts
Normal file
@ -0,0 +1,446 @@
|
||||
export type ExportedTypeFile = Record<string, TypeSystem.Type>;
|
||||
|
||||
export function firstLevelTypes(value: TypeDescriptor.Type | null) {
|
||||
if (!value) {
|
||||
return null;
|
||||
}
|
||||
|
||||
switch (value.type) {
|
||||
case 'array':
|
||||
return firstLevelTypes(value.value);
|
||||
case 'literal':
|
||||
return [];
|
||||
case 'intrinsic':
|
||||
return [];
|
||||
case 'or':
|
||||
return value.values.flatMap(firstLevelTypes);
|
||||
case 'intersection':
|
||||
return value.values.flatMap(firstLevelTypes);
|
||||
case 'predicate':
|
||||
return [];
|
||||
case 'reference': {
|
||||
const result = [];
|
||||
if (
|
||||
value.source.startsWith('dockview') &&
|
||||
!value.refersToTypeParameter
|
||||
) {
|
||||
result.push(value.value);
|
||||
}
|
||||
if (value.typeArguments) {
|
||||
result.push(...value.typeArguments.flatMap(firstLevelTypes));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
case 'reflection':
|
||||
return firstLevel(value.value);
|
||||
case 'tuple':
|
||||
return value.value.map(codifyType);
|
||||
default:
|
||||
throw new Error('unreachable');
|
||||
}
|
||||
}
|
||||
|
||||
export function firstLevel(value: TypeSystem.Type | null) {
|
||||
const results: string[] = [];
|
||||
|
||||
switch (value.kind) {
|
||||
case null:
|
||||
break;
|
||||
case 'property':
|
||||
results.push(...firstLevelTypes(value.type));
|
||||
break;
|
||||
case 'accessor':
|
||||
results.push(...firstLevelTypes(value.value.returnType));
|
||||
break;
|
||||
case 'method':
|
||||
results.push(...value.signature.flatMap(firstLevel));
|
||||
break;
|
||||
case 'constructor':
|
||||
break;
|
||||
case 'typeLiteral':
|
||||
if (value.properties) {
|
||||
results.push(...value.properties.flatMap(firstLevel));
|
||||
}
|
||||
if (value.signatures) {
|
||||
results.push(...value.signatures.flatMap(firstLevel));
|
||||
}
|
||||
break;
|
||||
case 'callSignature':
|
||||
results.push(
|
||||
...firstLevelTypes(value.returnType),
|
||||
...value.typeParameters.flatMap((_) => {
|
||||
return [...firstLevelTypes(_.extends)];
|
||||
}),
|
||||
...value.parameters.flatMap(firstLevel)
|
||||
);
|
||||
break;
|
||||
case 'parameter':
|
||||
results.push(...firstLevelTypes(value.type));
|
||||
break;
|
||||
default:
|
||||
console.log('test', value);
|
||||
throw new Error('unreachable');
|
||||
}
|
||||
|
||||
return Array.from(new Set(results));
|
||||
}
|
||||
|
||||
export function codifyType(value: TypeDescriptor.Type | null, tabs = 0) {
|
||||
if (!value) {
|
||||
return null;
|
||||
}
|
||||
|
||||
switch (value.type) {
|
||||
case 'array':
|
||||
return `${codifyType(value.value)}[]`;
|
||||
case 'literal':
|
||||
return `'${value.value}'`;
|
||||
case 'intrinsic':
|
||||
return value.value;
|
||||
case 'or':
|
||||
return `${value.values
|
||||
.map((_) => {
|
||||
const isComparator =
|
||||
_.type === 'or' || _.type === 'intersection';
|
||||
const code = codifyType(_);
|
||||
return isComparator ? `(${code})` : code;
|
||||
})
|
||||
.join(' | ')}`;
|
||||
case 'intersection':
|
||||
return `${value.values
|
||||
.map((_) => {
|
||||
const isComparator =
|
||||
_.type === 'or' || _.type === 'intersection';
|
||||
const code = codifyType(_);
|
||||
return isComparator ? `(${code})` : code;
|
||||
})
|
||||
.join(' & ')}`;
|
||||
case 'predicate':
|
||||
return `${value.lhs} is ${value.rhs}`;
|
||||
|
||||
case 'reference': {
|
||||
if (value.typeArguments) {
|
||||
return `${value.value}<${value.typeArguments.map(codifyType)}>`;
|
||||
}
|
||||
return `${value.value}`;
|
||||
}
|
||||
case 'reflection':
|
||||
return codify(value.value, tabs);
|
||||
case 'tuple':
|
||||
return `[${value.value.map(codifyType).join(', ')}]`;
|
||||
default:
|
||||
throw new Error('unreachable');
|
||||
}
|
||||
}
|
||||
|
||||
export function codify(value: TypeSystem.Type | null, tabs = 0) {
|
||||
if (!value) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (value.kind === 'accessor') {
|
||||
const signature = value.value;
|
||||
return `${'\t'.repeat(tabs)}${signature.name}: ${codifyType(
|
||||
signature.returnType
|
||||
)}`;
|
||||
}
|
||||
|
||||
if (value.kind === 'property') {
|
||||
let code = '\t'.repeat(tabs);
|
||||
|
||||
if (value.flags.isProtected) {
|
||||
code += 'protected ';
|
||||
}
|
||||
|
||||
if (value.flags.isReadonly) {
|
||||
code += 'readonly ';
|
||||
}
|
||||
code += value.name;
|
||||
if (value.flags.isOptional) {
|
||||
code += '?';
|
||||
}
|
||||
|
||||
code += `: ${codifyType(value.type, tabs + 1)}`;
|
||||
return code;
|
||||
}
|
||||
|
||||
if (value.kind === 'method') {
|
||||
return `${'\t'.repeat(tabs)}${value.name}${value.signature
|
||||
.map(codify)
|
||||
.join('\n')}`;
|
||||
}
|
||||
|
||||
if (value.kind === 'callSignature') {
|
||||
let code = ``;
|
||||
|
||||
if (value.typeParameters.length > 0) {
|
||||
code += '<';
|
||||
code += value.typeParameters.map((typeParameter) => {
|
||||
let typeCode = `${typeParameter.name}`;
|
||||
|
||||
if (typeParameter.extends) {
|
||||
typeCode += ' extends';
|
||||
typeCode += ` ${codifyType(typeParameter.extends)}`;
|
||||
}
|
||||
|
||||
if (typeParameter.default) {
|
||||
typeCode += ' =';
|
||||
typeCode += ` ${typeParameter.default}`;
|
||||
}
|
||||
return typeCode;
|
||||
});
|
||||
code += '>';
|
||||
}
|
||||
|
||||
code += '(';
|
||||
|
||||
code += value.parameters
|
||||
.map((parameter) => {
|
||||
return codify(parameter, tabs + 1);
|
||||
})
|
||||
.join(', ');
|
||||
|
||||
code += `): ${codifyType(value.returnType)}`;
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
if (value.kind === 'parameter') {
|
||||
return `${value.name}: ${codifyType(value.type, tabs + 1)}`;
|
||||
}
|
||||
|
||||
if (value.kind === 'typeLiteral') {
|
||||
if (value.properties) {
|
||||
return `{\n${value.properties
|
||||
.map((_) => codify(_, tabs))
|
||||
.join(',\n')}\n${'\t'.repeat(Math.max(0, tabs - 1))}}`;
|
||||
}
|
||||
if (value.signatures) {
|
||||
return value.signatures.map(codify).join('\n');
|
||||
}
|
||||
}
|
||||
|
||||
if (value.kind === 'constructor') {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (value.kind === 'interface') {
|
||||
return `interface ${value.name} {\n${value.children
|
||||
.map((_) => codify(_, tabs + 1))
|
||||
.join(';\n')};\n}`;
|
||||
}
|
||||
|
||||
if (value.kind === 'class') {
|
||||
return `interface ${value.name} {\n${value.children
|
||||
.filter((_) => _.kind !== 'constructor')
|
||||
.map((_) => codify(_, tabs + 1))
|
||||
.join(';\n')};\n}`;
|
||||
}
|
||||
|
||||
if (value.kind === 'typeAlias') {
|
||||
return `type ${value.name} = ${codifyType(value.type)}`;
|
||||
}
|
||||
|
||||
console.log('unreachable', value);
|
||||
throw new Error(`unreachable`);
|
||||
}
|
||||
|
||||
export namespace TypeSystem {
|
||||
export type Comment = any;
|
||||
|
||||
export type TypeParameter = {
|
||||
name: string;
|
||||
extends: TypeDescriptor.Type;
|
||||
default: string;
|
||||
comment?: Comment;
|
||||
};
|
||||
|
||||
export type Accessor = {
|
||||
name: string;
|
||||
kind: 'accessor';
|
||||
comment?: Comment;
|
||||
value: TypeSystem.GetSignature;
|
||||
};
|
||||
|
||||
export type GetSignature = {
|
||||
kind: 'getSignature';
|
||||
name: string;
|
||||
returnType: TypeDescriptor.Type;
|
||||
comment?: Comment;
|
||||
};
|
||||
|
||||
export type CallSignature = {
|
||||
kind: 'callSignature';
|
||||
typeParameters: TypeSystem.TypeParameter[];
|
||||
parameters: TypeSystem.Type[];
|
||||
returnType: TypeDescriptor.Type;
|
||||
name: string;
|
||||
comment?: Comment;
|
||||
};
|
||||
|
||||
export type Method = {
|
||||
name: string;
|
||||
kind: 'method';
|
||||
signature: TypeSystem.CallSignature[];
|
||||
comment?: Comment;
|
||||
};
|
||||
|
||||
export type Function = {
|
||||
name: string;
|
||||
kind: 'function';
|
||||
signature: TypeSystem.CallSignature;
|
||||
comment?: Comment;
|
||||
};
|
||||
|
||||
export type Property = {
|
||||
kind: 'property';
|
||||
name: string;
|
||||
type: TypeDescriptor.Type;
|
||||
flags: TypeDescriptor.Flags;
|
||||
comment?: Comment;
|
||||
};
|
||||
|
||||
export type TypeAlias = {
|
||||
name: string;
|
||||
kind: 'typeAlias';
|
||||
typeParameters: TypeSystem.TypeParameter[];
|
||||
type: TypeDescriptor.Type;
|
||||
comment?: Comment;
|
||||
};
|
||||
|
||||
export type Enum = {
|
||||
name: string;
|
||||
kind: 'enum';
|
||||
children: TypeSystem.EnumMember[];
|
||||
comment?: Comment;
|
||||
};
|
||||
|
||||
export type EnumMember = {
|
||||
kind: 'enumMember';
|
||||
name: string;
|
||||
comment?: Comment;
|
||||
};
|
||||
|
||||
export type Class = {
|
||||
name: string;
|
||||
kind: 'class';
|
||||
children: TypeSystem.Type[];
|
||||
comment?: Comment;
|
||||
};
|
||||
|
||||
export type Interface = {
|
||||
name: string;
|
||||
kind: 'interface';
|
||||
children: TypeSystem.Type[];
|
||||
comment?: Comment;
|
||||
};
|
||||
|
||||
export type Parameter = {
|
||||
name: string;
|
||||
kind: 'parameter';
|
||||
type: TypeDescriptor.Type;
|
||||
comment?: Comment;
|
||||
};
|
||||
|
||||
export type Constructor = {
|
||||
kind: 'constructor';
|
||||
name: string;
|
||||
comment?: Comment;
|
||||
};
|
||||
|
||||
export type ConstructorSignature = {
|
||||
kind: 'constructorSignature';
|
||||
name: string;
|
||||
comment?: Comment;
|
||||
};
|
||||
|
||||
export type TypeLiteral = {
|
||||
kind: 'typeLiteral';
|
||||
name: string;
|
||||
signatures?: (ConstructorSignature | TypeSystem.CallSignature)[];
|
||||
properties?: TypeSystem.Property[];
|
||||
comment?: Comment;
|
||||
};
|
||||
|
||||
export type Type =
|
||||
| TypeSystem.Accessor
|
||||
| TypeSystem.GetSignature
|
||||
| TypeSystem.CallSignature
|
||||
| TypeSystem.Method
|
||||
| TypeSystem.Property
|
||||
| TypeSystem.TypeAlias
|
||||
| TypeSystem.Enum
|
||||
| TypeSystem.EnumMember
|
||||
| TypeSystem.Class
|
||||
| TypeSystem.Constructor
|
||||
| TypeSystem.ConstructorSignature
|
||||
| TypeSystem.TypeLiteral
|
||||
| TypeSystem.Parameter
|
||||
| TypeSystem.Interface
|
||||
| TypeSystem.Function;
|
||||
}
|
||||
|
||||
export namespace TypeDescriptor {
|
||||
export interface Union {
|
||||
type: 'or';
|
||||
values: TypeDescriptor.Type[];
|
||||
}
|
||||
|
||||
export interface Intrinsic {
|
||||
type: 'intrinsic';
|
||||
value: string;
|
||||
}
|
||||
|
||||
export interface Literal {
|
||||
type: 'literal';
|
||||
value: string;
|
||||
}
|
||||
|
||||
export type Reflection = { type: 'reflection'; value: TypeSystem.Type };
|
||||
|
||||
export interface Reference {
|
||||
type: 'reference';
|
||||
value: string;
|
||||
source: string;
|
||||
typeArguments?: TypeDescriptor.Type[];
|
||||
refersToTypeParameter?: boolean;
|
||||
}
|
||||
|
||||
export interface Array {
|
||||
type: 'array';
|
||||
value: TypeDescriptor.Type;
|
||||
}
|
||||
|
||||
export interface Intersection {
|
||||
type: 'intersection';
|
||||
values: TypeDescriptor.Type[];
|
||||
}
|
||||
|
||||
export interface Predicate {
|
||||
type: 'predicate';
|
||||
lhs: string;
|
||||
rhs: TypeDescriptor.Type;
|
||||
}
|
||||
|
||||
export interface Tuple {
|
||||
type: 'tuple';
|
||||
value: TypeDescriptor.Type[];
|
||||
}
|
||||
|
||||
export type Type =
|
||||
| TypeDescriptor.Union
|
||||
| TypeDescriptor.Intrinsic
|
||||
| TypeDescriptor.Literal
|
||||
| TypeDescriptor.Reflection
|
||||
| TypeDescriptor.Reference
|
||||
| TypeDescriptor.Array
|
||||
| TypeDescriptor.Intersection
|
||||
| TypeDescriptor.Predicate
|
||||
| TypeDescriptor.Tuple;
|
||||
|
||||
export type Flags = {
|
||||
isReadonly?: boolean;
|
||||
isProtected?: boolean;
|
||||
isOptional?: boolean;
|
||||
};
|
||||
}
|
@ -154,6 +154,7 @@
|
||||
}
|
||||
|
||||
code {
|
||||
// white-space: pre-wrap;
|
||||
.token {
|
||||
&.maybe-class-name {
|
||||
color: #cf8cff;
|
||||
|
1
packages/docs/src/flags.ts
Normal file
1
packages/docs/src/flags.ts
Normal file
@ -0,0 +1 @@
|
||||
export const IS_PROD = true;
|
File diff suppressed because it is too large
Load Diff
@ -2,12 +2,46 @@ import React from 'react';
|
||||
import Layout from '@theme/Layout';
|
||||
import { themeConfig } from '../config/theme.config';
|
||||
import ExampleFrame from '../components/ui/exampleFrame';
|
||||
import BrowserOnly from '@docusaurus/BrowserOnly';
|
||||
|
||||
const ThemeToggle: React.FC = () => {
|
||||
const [theme, setTheme] = React.useState<string>(
|
||||
new URLSearchParams(location.search).get('theme') ?? themeConfig[3].id
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
style={{
|
||||
height: '40px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
<select
|
||||
onChange={(event) => {
|
||||
const url = new URL(window.location.href);
|
||||
url.searchParams.set('theme', event.target.value);
|
||||
window.location.href = url.toString();
|
||||
}}
|
||||
value={theme}
|
||||
>
|
||||
{themeConfig.map((theme) => {
|
||||
return <option>{theme.id}</option>;
|
||||
})}
|
||||
</select>
|
||||
</div>
|
||||
<ExampleFrame
|
||||
theme={theme}
|
||||
framework="react"
|
||||
height="100%"
|
||||
id="dockview/demo-dockview"
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default function Popout() {
|
||||
// const [theme, setTheme] = React.useState<string>(
|
||||
// new URLSearchParams(location.search).get('theme') ?? themeConfig[3].id
|
||||
// );
|
||||
|
||||
return (
|
||||
<Layout noFooter={true}>
|
||||
<div
|
||||
@ -19,33 +53,7 @@ export default function Popout() {
|
||||
flexDirection: 'column',
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
height: '40px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
<select
|
||||
onChange={(event) => {
|
||||
const url = new URL(window.location.href);
|
||||
url.searchParams.set('theme', event.target.value);
|
||||
window.location.href = url.toString();
|
||||
}}
|
||||
// value={theme}
|
||||
>
|
||||
{themeConfig.map((theme) => {
|
||||
return <option>{theme.id}</option>;
|
||||
})}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<ExampleFrame
|
||||
// theme={theme}
|
||||
framework="react"
|
||||
height="100%"
|
||||
id="dockview/demo-dockview"
|
||||
/>
|
||||
<BrowserOnly>{() => <ThemeToggle />}</BrowserOnly>
|
||||
</div>
|
||||
</Layout>
|
||||
);
|
||||
|
262
scripts/docs.mjs
262
scripts/docs.mjs
@ -105,9 +105,89 @@ function parseType(obj) {
|
||||
}
|
||||
}
|
||||
|
||||
function parseComplexType(obj) {
|
||||
switch (obj.type) {
|
||||
case 'union':
|
||||
return {
|
||||
type: 'or',
|
||||
values: obj.types.map(parseComplexType).reverse(),
|
||||
};
|
||||
case 'intrinsic':
|
||||
return { type: obj.type, value: obj.name };
|
||||
case 'literal':
|
||||
return { type: obj.type, value: obj.value };
|
||||
case 'reflection':
|
||||
return { type: obj.type, value: parse(obj.declaration) };
|
||||
case 'reference': {
|
||||
if (obj.refersToTypeParameter) {
|
||||
return {
|
||||
type: obj.type,
|
||||
value: obj.name,
|
||||
source: obj.package,
|
||||
refersToTypeParameter: true,
|
||||
};
|
||||
}
|
||||
|
||||
if (obj.qualifiedName) {
|
||||
return {
|
||||
type: obj.type,
|
||||
value: obj.qualifiedName,
|
||||
source: obj.sourceFileName
|
||||
? obj.sourceFileName.startsWith('packages/dockview')
|
||||
? 'dockview'
|
||||
: 'external'
|
||||
: obj.package,
|
||||
typeArguments: obj.typeArguments?.map(parseComplexType),
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
type: obj.type,
|
||||
value: obj.name,
|
||||
source: obj.package,
|
||||
typeArguments: obj.typeArguments?.map(parseComplexType),
|
||||
};
|
||||
}
|
||||
case 'array':
|
||||
return {
|
||||
type: obj.type,
|
||||
value: parseComplexType(obj.elementType),
|
||||
};
|
||||
case 'intersection':
|
||||
return {
|
||||
type: obj.type,
|
||||
values: obj.types.map(parseComplexType).reverse(),
|
||||
};
|
||||
case 'predicate':
|
||||
return {
|
||||
type: obj.type,
|
||||
lhs: obj.name,
|
||||
rhs: parseComplexType(obj.targetType),
|
||||
};
|
||||
case 'tuple':
|
||||
return {
|
||||
type: obj.type,
|
||||
values: obj.elements.map(parseComplexType),
|
||||
};
|
||||
default:
|
||||
throw new Error(`unhandled type ${obj.type}`);
|
||||
}
|
||||
}
|
||||
|
||||
function extractPiecesFromType(obj) {
|
||||
if (obj.type === 'reference' && obj.package?.startsWith('dockview-')) {
|
||||
return obj.name;
|
||||
let result = { name: obj.name };
|
||||
|
||||
if (Array.isArray(obj.typeArguments)) {
|
||||
const typeArgs = obj.typeArguments
|
||||
.map(extractPiecesFromType)
|
||||
.filter(Boolean);
|
||||
if (typeArgs.length > 0) {
|
||||
result.typeArgs = typeArgs;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -126,14 +206,15 @@ function parse(data) {
|
||||
|
||||
const getSignature = parse(data.getSignature);
|
||||
code += getSignature.code;
|
||||
pieces.push(...getSignature.pieces);
|
||||
// pieces.push(...getSignature.pieces);
|
||||
|
||||
return {
|
||||
name,
|
||||
code,
|
||||
kind: 'accessor',
|
||||
value: getSignature,
|
||||
comment: getSignature.comment,
|
||||
pieces,
|
||||
// pieces: pieces.filter((_) => _.value !== null),
|
||||
};
|
||||
case ReflectionKind.Method: // 2048
|
||||
const methodSignature = data.signatures.map((signature) =>
|
||||
@ -149,20 +230,25 @@ function parse(data) {
|
||||
name,
|
||||
code,
|
||||
kind: 'method',
|
||||
signature: methodSignature,
|
||||
comment: data.signatures[0].comment,
|
||||
pieces,
|
||||
// pieces: pieces.filter((_) => _.value !== null),
|
||||
};
|
||||
case ReflectionKind.Property: // 1024
|
||||
code += parseType(data.type);
|
||||
pieces.push(extractPiecesFromType(data.type));
|
||||
pieces.push({
|
||||
kind: 'property',
|
||||
value: extractPiecesFromType(data.type),
|
||||
});
|
||||
|
||||
return {
|
||||
name,
|
||||
code,
|
||||
kind: 'property',
|
||||
type: parseComplexType(data.type),
|
||||
flags,
|
||||
comment,
|
||||
pieces,
|
||||
// pieces: pieces.filter((_) => _.value !== null),
|
||||
};
|
||||
|
||||
case ReflectionKind.Parameter: // 32768
|
||||
@ -174,14 +260,21 @@ function parse(data) {
|
||||
code += ': ';
|
||||
|
||||
code += parseType(data.type);
|
||||
pieces.push(extractPiecesFromType(data.type));
|
||||
pieces.push({
|
||||
kind: 'parameter',
|
||||
value: extractPiecesFromType(data.type),
|
||||
});
|
||||
|
||||
return {
|
||||
name,
|
||||
code,
|
||||
pieces,
|
||||
type: parseComplexType(data.type),
|
||||
kind: 'parameter',
|
||||
// pieces: pieces.filter((_) => _.value !== null),
|
||||
};
|
||||
case ReflectionKind.TypeLiteral: // 65536
|
||||
let result = {};
|
||||
|
||||
if (Array.isArray(data.children)) {
|
||||
code += `{ `;
|
||||
code += data.children
|
||||
@ -192,46 +285,91 @@ function parse(data) {
|
||||
code += '?';
|
||||
}
|
||||
const childData = parse(child);
|
||||
pieces.push(...childData.pieces);
|
||||
// pieces.push(...childData.pieces);
|
||||
|
||||
code += `: ${childData.code}`;
|
||||
return code;
|
||||
})
|
||||
.join(', ');
|
||||
code += ` }`;
|
||||
|
||||
result.properties = data.children.map((_) => {
|
||||
const result = parse(_);
|
||||
|
||||
if (result.kind !== 'property') {
|
||||
throw new Error(`invalid ${result.kind}`);
|
||||
}
|
||||
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
if (Array.isArray(data.signatures)) {
|
||||
const signatures = data.signatures.map((signature) =>
|
||||
parse(signature)
|
||||
);
|
||||
const signatures = data.signatures.map((signature) => {
|
||||
const result = parse(signature);
|
||||
|
||||
if (
|
||||
result.kind !== 'callSignature' &&
|
||||
result.kind !== 'constructorSignature'
|
||||
) {
|
||||
throw new Error(`invalid ${result.kind}`);
|
||||
}
|
||||
|
||||
return result;
|
||||
});
|
||||
code += signatures
|
||||
.map((signature) => signature.code)
|
||||
.join(', ');
|
||||
pieces.push(...signatures.flatMap((_) => _.pieces));
|
||||
// pieces.push(...signatures.flatMap((_) => _.pieces));
|
||||
|
||||
if (result.type) {
|
||||
throw new Error('anc');
|
||||
}
|
||||
|
||||
result.signatures = signatures;
|
||||
}
|
||||
|
||||
return { name, code, pieces };
|
||||
return {
|
||||
name,
|
||||
code,
|
||||
// pieces,
|
||||
kind: 'typeLiteral',
|
||||
properties: result.properties,
|
||||
signatures: result.signatures,
|
||||
};
|
||||
case ReflectionKind.CallSignature: // 4096
|
||||
// don't care for constrcutors
|
||||
const typeParameters = [];
|
||||
let _parameters = [];
|
||||
|
||||
if (Array.isArray(data.typeParameter)) {
|
||||
code += `<${data.typeParameter.map((typeParameter) => {
|
||||
let type = `${typeParameter.name}`;
|
||||
|
||||
const result = { name: type };
|
||||
|
||||
if (typeParameter.type) {
|
||||
type += ` extends ${parseType(typeParameter.type)}`;
|
||||
|
||||
pieces.push(extractPiecesFromType(typeParameter.type));
|
||||
result.extends = parseComplexType(typeParameter.type);
|
||||
|
||||
pieces.push({
|
||||
kind: 'typearg',
|
||||
value: extractPiecesFromType(typeParameter.type),
|
||||
});
|
||||
}
|
||||
|
||||
if (typeParameter.default) {
|
||||
type += ` = ${typeParameter.default.name}`;
|
||||
pieces.push(
|
||||
extractPiecesFromType(typeParameter.default)
|
||||
);
|
||||
pieces.push({
|
||||
kind: 'typearg_default',
|
||||
value: extractPiecesFromType(typeParameter.default),
|
||||
});
|
||||
|
||||
result.default = typeParameter.default.name;
|
||||
}
|
||||
|
||||
typeParameters.push(result);
|
||||
|
||||
return type;
|
||||
})}>`;
|
||||
}
|
||||
@ -242,113 +380,155 @@ function parse(data) {
|
||||
const parameters = data.parameters.map((parameter) =>
|
||||
parse(parameter)
|
||||
);
|
||||
|
||||
_parameters = parameters;
|
||||
|
||||
code += `${parameters
|
||||
.map((parameter) => parameter.code)
|
||||
.join(', ')}`;
|
||||
pieces.push(...parameters.flatMap((_) => _.pieces));
|
||||
// pieces.push(...parameters.flatMap((_) => _.pieces));
|
||||
}
|
||||
|
||||
code += '): ';
|
||||
|
||||
code += parseType(data.type);
|
||||
pieces.push(extractPiecesFromType(data.type));
|
||||
pieces.push({
|
||||
kind: 'return',
|
||||
value: extractPiecesFromType(data.type),
|
||||
});
|
||||
|
||||
return {
|
||||
name,
|
||||
comment,
|
||||
typeParameters,
|
||||
parameters: _parameters,
|
||||
returnType: parseComplexType(data.type),
|
||||
code,
|
||||
pieces,
|
||||
kind: 'callSignature',
|
||||
// pieces: pieces.filter((_) => _.value !== null),
|
||||
};
|
||||
case ReflectionKind.GetSignature: // 524288
|
||||
code += parseType(data.type);
|
||||
pieces.push(extractPiecesFromType(data.type));
|
||||
pieces.push({
|
||||
kind: 'signature',
|
||||
value: extractPiecesFromType(data.type),
|
||||
});
|
||||
|
||||
return {
|
||||
name,
|
||||
comment,
|
||||
code,
|
||||
pieces,
|
||||
kind: 'getSignature',
|
||||
returnType: parseComplexType(data.type),
|
||||
// pieces: pieces.filter((_) => _.value !== null),
|
||||
};
|
||||
case ReflectionKind.Function: // 64
|
||||
if (data.signatures.length > 1) {
|
||||
throw new Error('unhandled');
|
||||
}
|
||||
const functionSignature = parse(data.signatures[0]);
|
||||
pieces.push(...functionSignature.pieces);
|
||||
// pieces.push(...functionSignature.pieces);
|
||||
|
||||
code += functionSignature.code;
|
||||
return {
|
||||
name,
|
||||
comment,
|
||||
code,
|
||||
pieces,
|
||||
signature: parse(data.signatures[0]),
|
||||
kind: 'function',
|
||||
// pieces: pieces.filter((_) => _.value !== null),
|
||||
};
|
||||
case ReflectionKind.Variable: // 32
|
||||
return {
|
||||
name,
|
||||
comment,
|
||||
code,
|
||||
pieces,
|
||||
kind: 'variable',
|
||||
// pieces: pieces.filter((_) => _.value !== null),
|
||||
};
|
||||
case ReflectionKind.EnumMember: // 16
|
||||
return {
|
||||
name,
|
||||
comment,
|
||||
code,
|
||||
pieces,
|
||||
kind: 'enumMember',
|
||||
// pieces: pieces.filter((_) => _.value !== null),
|
||||
};
|
||||
case ReflectionKind.Interface: // 16
|
||||
return {
|
||||
name,
|
||||
comment,
|
||||
code,
|
||||
pieces,
|
||||
kind: 'interface',
|
||||
// pieces: pieces.filter((_) => _.value !== null),
|
||||
};
|
||||
case ReflectionKind.ConstructorSignature: // 16384
|
||||
return {
|
||||
name,
|
||||
comment,
|
||||
code,
|
||||
pieces,
|
||||
kind: 'constructorSignature',
|
||||
// pieces: pieces.filter((_) => _.value !== null),
|
||||
};
|
||||
case ReflectionKind.Constructor: // 512
|
||||
// don't care for constrcutors
|
||||
return {
|
||||
name,
|
||||
comment,
|
||||
kind: 'constructor',
|
||||
code,
|
||||
pieces,
|
||||
// pieces: pieces.filter((_) => _.value !== null),
|
||||
};
|
||||
case ReflectionKind.TypeAlias: // 2097152
|
||||
const typeParameters1 = [];
|
||||
|
||||
if (Array.isArray(data.typeParameter)) {
|
||||
code += `<${data.typeParameter.map((typeParameter) => {
|
||||
let type = `${typeParameter.name}`;
|
||||
|
||||
const result = { name: typeParameter.name };
|
||||
|
||||
if (typeParameter.type) {
|
||||
type += ` extends ${parseType(typeParameter.type)}`;
|
||||
|
||||
pieces.push(extractPiecesFromType(typeParameter.type));
|
||||
result.extends = parseComplexType(typeParameter.type);
|
||||
|
||||
pieces.push({
|
||||
kind: 'typearg',
|
||||
value: extractPiecesFromType(typeParameter.type),
|
||||
});
|
||||
}
|
||||
|
||||
if (typeParameter.default) {
|
||||
type += ` = ${typeParameter.default.name}`;
|
||||
pieces.push(
|
||||
extractPiecesFromType(typeParameter.default)
|
||||
);
|
||||
pieces.push({
|
||||
kind: 'typearg_default',
|
||||
value: extractPiecesFromType(typeParameter.default),
|
||||
});
|
||||
|
||||
result.default = typeParameter.default.name;
|
||||
}
|
||||
|
||||
typeParameters1.push(result);
|
||||
|
||||
return type;
|
||||
})}>`;
|
||||
}
|
||||
|
||||
code += parseType(data.type);
|
||||
pieces.push(extractPiecesFromType(data.type));
|
||||
pieces.push({
|
||||
kind: 'typearg',
|
||||
value: extractPiecesFromType(data.type),
|
||||
});
|
||||
|
||||
return {
|
||||
name,
|
||||
comment,
|
||||
code,
|
||||
pieces,
|
||||
typeParameters: typeParameters1,
|
||||
type: parseComplexType(data.type),
|
||||
kind: 'typeAlias',
|
||||
// pieces: pieces.filter((_) => _.value !== null),
|
||||
};
|
||||
default:
|
||||
throw new Error(`unhandled kind ${data.kind}`);
|
||||
@ -395,11 +575,15 @@ function createDocument(declarations) {
|
||||
|
||||
documentation[name] = {
|
||||
...metadata,
|
||||
name,
|
||||
children: [],
|
||||
};
|
||||
|
||||
if (!children) {
|
||||
documentation[name].metadata = parse(declaration);
|
||||
documentation[name] = {
|
||||
...parse(declaration),
|
||||
};
|
||||
// documentation[name].metadata = parse(declaration);
|
||||
}
|
||||
|
||||
if (children) {
|
||||
@ -417,6 +601,8 @@ function createDocument(declarations) {
|
||||
output.pieces = Array.from(new Set(output.pieces))
|
||||
.filter(Boolean)
|
||||
.sort();
|
||||
delete output.pieces;
|
||||
// delete output.comment;
|
||||
|
||||
documentation[name].children.push(output);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user