Deploying to gh-pages from @ 55e21eacb3140bac6879375fb13e905599af1757 🚀
10
build/.editorconfig
Normal file
@ -0,0 +1,10 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
quote_type = single
|
2
build/.eslintignore
Normal file
@ -0,0 +1,2 @@
|
||||
dist/
|
||||
*.scss
|
19
build/.eslintrc.js
Normal file
@ -0,0 +1,19 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
parserOptions: {
|
||||
sourceType: 'module',
|
||||
project: ['./tsconfig.eslint.json', './packages/*/tsconfig.json'],
|
||||
tsconfigRootDir: __dirname,
|
||||
},
|
||||
plugins: ['@typescript-eslint'],
|
||||
extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended'],
|
||||
rules: {
|
||||
'no-case-declarations': 'off',
|
||||
'@typescript-eslint/no-namespace': 'off',
|
||||
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
||||
'@typescript-eslint/no-explicit-any': 'off',
|
||||
'@typescript-eslint/no-unused-vars': 'off',
|
||||
'@typescript-eslint/ban-types': 'off',
|
||||
'@typescript-eslint/no-non-null-assertion': 'off',
|
||||
},
|
||||
};
|
15
build/.gitignore
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
node_modules/
|
||||
coverage/
|
||||
dist/
|
||||
output/
|
||||
.idea/
|
||||
typedocs/
|
||||
.DS_Store
|
||||
*-debug.log
|
||||
.build
|
||||
storybook-static/
|
||||
.rollup.cache/
|
||||
test-report.xml
|
||||
*.code-workspace
|
||||
yarn-error.log
|
||||
/build
|
3
build/.prettierignore
Normal file
@ -0,0 +1,3 @@
|
||||
typedocs/
|
||||
dist/
|
||||
build/
|
6
build/.prettierrc
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"trailingComma": "es5",
|
||||
"tabWidth": 4,
|
||||
"semi": true,
|
||||
"singleQuote": true
|
||||
}
|
14
build/.vscode/extensions.json
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
// See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations.
|
||||
// Extension identifier format: ${publisher}.${name}. Example: vscode.csharp
|
||||
|
||||
// List of extensions which should be recommended for users of this workspace.
|
||||
"recommendations": [
|
||||
"esbenp.prettier-vscode",
|
||||
"redhat.vscode-yaml",
|
||||
"dbaeumer.vscode-eslint",
|
||||
"editorconfig.editorconfig"
|
||||
],
|
||||
// List of extensions recommended by VS Code that should not be recommended for users of this workspace.
|
||||
"unwantedRecommendations": []
|
||||
}
|
1
build/.vscode/settings.json
vendored
Normal file
@ -0,0 +1 @@
|
||||
{}
|
21
build/LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021 mathuo
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
52
build/README.md
Normal file
@ -0,0 +1,52 @@
|
||||
<div align="center">
|
||||
<h1>dockview</h1>
|
||||
|
||||
<p>Zero dependency layout manager supporting tabs, grids and splitviews with ReactJS support written in TypeScript</p>
|
||||
|
||||
</div>
|
||||
|
||||
---
|
||||
|
||||
[![npm version](https://badge.fury.io/js/dockview.svg)](https://www.npmjs.com/package/dockview)
|
||||
[![CI Build](https://github.com/mathuo/dockview/workflows/CI/badge.svg)](https://github.com/mathuo/dockview/actions?query=workflow%3ACI)
|
||||
[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=mathuo_dockview&metric=coverage)](https://sonarcloud.io/summary/overall?id=mathuo_dockview)
|
||||
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=mathuo_dockview&metric=alert_status)](https://sonarcloud.io/summary/overall?id=mathuo_dockview)
|
||||
[![Bundle Phobia](https://badgen.net/bundlephobia/minzip/dockview)](https://bundlephobia.com/result?p=dockview)
|
||||
|
||||
##
|
||||
|
||||
Please see the website: https://mathuo.github.io/dockview/docs
|
||||
|
||||
Want to inspect the latest deployment? Go to https://unpkg.com/browse/dockview@latest/
|
||||
|
||||
## Features
|
||||
|
||||
- Simple splitviews, nested splitviews (i.e. gridviews) supporting full layout managment with
|
||||
dockable and tabular views
|
||||
- Extensive API support at the component level and view level
|
||||
- Themable and customizable
|
||||
- Serialization / deserialization support
|
||||
- Tabular docking and Drag and Drop support
|
||||
- Documentation and examples
|
||||
|
||||
This project was inspired by many popular IDE editors. Some parts of the core resizable panelling are inspired by code found in the VSCode codebase, [splitview](https://github.com/microsoft/vscode/tree/main/src/vs/base/browser/ui/splitview) and [gridview](https://github.com/microsoft/vscode/tree/main/src/vs/base/browser/ui/grid).
|
||||
|
||||
## Quick start
|
||||
|
||||
Dockview has a peer dependency on `react >= 16.8.0` and `react-dom >= 16.8.0`. You can install dockview from [npm](https://www.npmjs.com/package/dockview). Please see the [Getting Started Guide](https://mathuo.github.io/dockview/docs/).
|
||||
|
||||
```
|
||||
npm install --save dockview
|
||||
```
|
||||
|
||||
Within your project you must import or reference the stylesheet at `dockview/dist/styles/dockview.css` and attach a theme.
|
||||
|
||||
```css
|
||||
@import '~dockview/dist/styles/dockview.css';
|
||||
```
|
||||
|
||||
You should also attach a dockview theme to an element containing your components. For example:
|
||||
|
||||
```html
|
||||
<body classname="dockview-theme-dark"></body>
|
||||
```
|
20
build/docs/.gitignore
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
# Dependencies
|
||||
/node_modules
|
||||
|
||||
# Production
|
||||
/build
|
||||
|
||||
# Generated files
|
||||
.docusaurus
|
||||
.cache-loader
|
||||
|
||||
# Misc
|
||||
.DS_Store
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
41
build/docs/README.md
Normal file
@ -0,0 +1,41 @@
|
||||
# Website
|
||||
|
||||
This website is built using [Docusaurus 2](https://docusaurus.io/), a modern static website generator.
|
||||
|
||||
### Installation
|
||||
|
||||
```
|
||||
$ yarn
|
||||
```
|
||||
|
||||
### Local Development
|
||||
|
||||
```
|
||||
$ yarn start
|
||||
```
|
||||
|
||||
This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server.
|
||||
|
||||
### Build
|
||||
|
||||
```
|
||||
$ yarn build
|
||||
```
|
||||
|
||||
This command generates static content into the `build` directory and can be served using any static contents hosting service.
|
||||
|
||||
### Deployment
|
||||
|
||||
Using SSH:
|
||||
|
||||
```
|
||||
$ USE_SSH=true yarn deploy
|
||||
```
|
||||
|
||||
Not using SSH:
|
||||
|
||||
```
|
||||
$ GIT_USER=<Your GitHub username> yarn deploy
|
||||
```
|
||||
|
||||
If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch.
|
3
build/docs/babel.config.js
Normal file
@ -0,0 +1,3 @@
|
||||
module.exports = {
|
||||
presets: [require.resolve('@docusaurus/core/lib/babel/preset')],
|
||||
};
|
24
build/docs/blog/2022-05-11-dockview-1.4.1.mdx
Normal file
@ -0,0 +1,24 @@
|
||||
---
|
||||
slug: dockview-1.4.1-release
|
||||
title: Dockview 1.4.1
|
||||
tags: [release]
|
||||
---
|
||||
|
||||
# Release Notes
|
||||
|
||||
## 🚀 Features
|
||||
|
||||
- Fix Drag and Drop issues in Dockview on Firefox [#103](https://github.com/mathuo/dockview/pull/103)
|
||||
|
||||
## 🛠 Miscs
|
||||
|
||||
- Documentation enhancements https://mathuo.github.io/dockview/docs/
|
||||
|
||||
## 🔥 Breaking changes
|
||||
|
||||
All breaking changes here are designed to simplify the library with only one way to do something.
|
||||
|
||||
- Remove `setVisible` and `setActive` from the Splitview API. You can still achieve the same behaviors through calling `setVisible` and `setActive` on the Splitview Panel API. [#105](https://github.com/mathuo/dockview/pull/105)
|
||||
- Remove `setVisible`, `setActive` and `toggleVisiblity` from Gridview API. You can still achieve the same behaviors through calling `setVisible` and `setActive` on the Gridview Panel API [#105](https://github.com/mathuo/dockview/pull/105)
|
||||
- Remove `onFocusEvent` from Panel API as this was not intended to be a public method. You can use `onDidFocusChange` instead [#105](https://github.com/mathuo/dockview/pull/105)
|
||||
- Remove HOC `<DockviewComponents.Panel\>`, `<DockviewComponents.Content>`, `<DockviewComponents.Tab>` and `<DockviewComponents.Actions>` [#105](https://github.com/mathuo/dockview/pull/105)
|
15
build/docs/blog/2022-05-16-dockview-1.4.2.mdx
Normal file
@ -0,0 +1,15 @@
|
||||
---
|
||||
slug: dockview-1.4.2-release
|
||||
title: Dockview 1.4.2
|
||||
tags: [release]
|
||||
---
|
||||
|
||||
# Release Notes
|
||||
|
||||
## 🚀 Features
|
||||
|
||||
- Fix deserialization issue where previously active panel wasn't display correctly after deserialization [#108](https://github.com/mathuo/dockview/pull/108)
|
||||
|
||||
## 🔥 Breaking changes
|
||||
|
||||
- Rename `onDidAddGroup` to `onDidAddPanel`, `onDidRemoveGroup` to `onDidRemovePanel` and `onDidActiveGroupChange` to `onDidActivePanelChange` on the Gridview API [#106](https://github.com/mathuo/dockview/pull/106)
|
23
build/docs/blog/2022-05-26-dockview-1.4.3.mdx
Normal file
@ -0,0 +1,23 @@
|
||||
---
|
||||
slug: dockview-1.4.3-release
|
||||
title: Dockview 1.4.3
|
||||
tags: [release]
|
||||
---
|
||||
|
||||
# Release Notes
|
||||
|
||||
## 🚀 Features
|
||||
|
||||
- Small adjusted to behaviours of default paneview header componnet [#116](https://github.com/mathuo/dockview/pull/116) [#120](https://github.com/mathuo/dockview/pull/120)
|
||||
- Improved support for external dnd events in the dockview component. `showDndOverlay` prop on `DockviewReact` exposes more parameters to interact with [#110](https://github.com/mathuo/dockview/pull/110)
|
||||
- Improved to underlying events exposes through all components [#114](https://github.com/mathuo/dockview/pull/114)
|
||||
- Add .clear() to the component APIs providing an easy way to clear a layout [#119](https://github.com/mathuo/dockview/pull/119)
|
||||
- Udate orientation via componnet APIs is now working correctly [#119](https://github.com/mathuo/dockview/pull/119)
|
||||
|
||||
## 🛠 Miscs
|
||||
|
||||
- Documentation enhancements https://mathuo.github.io/dockview/docs/ [#101](https://github.com/mathuo/dockview/pull/101)
|
||||
|
||||
## 🔥 Breaking changes
|
||||
|
||||
- Fix typo by renaming `onDidLayoutfromJSON` to `onDidLayoutFromJSON` in dockview component api [#112](https://github.com/mathuo/dockview/pull/112/files)
|
17
build/docs/blog/authors.yml
Normal file
@ -0,0 +1,17 @@
|
||||
endi:
|
||||
name: Endilie Yacop Sucipto
|
||||
title: Maintainer of Docusaurus
|
||||
url: https://github.com/endiliey
|
||||
image_url: https://github.com/endiliey.png
|
||||
|
||||
yangshun:
|
||||
name: Yangshun Tay
|
||||
title: Front End Engineer @ Facebook
|
||||
url: https://github.com/yangshun
|
||||
image_url: https://github.com/yangshun.png
|
||||
|
||||
slorber:
|
||||
name: Sébastien Lorber
|
||||
title: Docusaurus maintainer
|
||||
url: https://sebastienlorber.com
|
||||
image_url: https://github.com/slorber.png
|
7
build/docs/docs/api/_category_.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"label": "API",
|
||||
"position": 2,
|
||||
"link": {
|
||||
"type": "generated-index"
|
||||
}
|
||||
}
|
285
build/docs/docs/api/dockview.mdx
Normal file
@ -0,0 +1,285 @@
|
||||
import { SimpleDockview } from '../../src/components/simpleDockview';
|
||||
import {
|
||||
RenderingDockview,
|
||||
Checkbox,
|
||||
} from '../../src/components/dockview/rendering';
|
||||
import { DndDockview } from '../../src/components/dockview/dnd';
|
||||
import { EventsDockview } from '../../src/components/dockview/events';
|
||||
import Link from '@docusaurus/Link';
|
||||
|
||||
# Dockview
|
||||
|
||||
## Introduction
|
||||
|
||||
Dockview is an abstraction built on top of [Gridviews](/docs/api/gridview) where each view is a tabbed container.
|
||||
|
||||
<div
|
||||
style={{
|
||||
height: '300px',
|
||||
backgroundColor: 'rgb(30,30,30)',
|
||||
color: 'white',
|
||||
margin: '20px 0px',
|
||||
}}
|
||||
>
|
||||
<SimpleDockview />
|
||||
</div>
|
||||
|
||||
```tsx
|
||||
const panel = event.api.addPanel(...);
|
||||
const anotherPanel = event.api.getPanel('somePanelid');
|
||||
```
|
||||
|
||||
You can access the panels associated group through the `panel.group` variable.
|
||||
The group will always be defined and will change if a panel is moved into another group.
|
||||
|
||||
## DockviewReact Component
|
||||
|
||||
```tsx
|
||||
import { ReactDockview } from 'dockview';
|
||||
```
|
||||
|
||||
| Property | Type | Optional | Default | Description |
|
||||
| ------------------- | ------------------------------------ | -------- | ------- | --------------------------------------------------------------- |
|
||||
| onReady | (event: SplitviewReadyEvent) => void | No | | |
|
||||
| components | object | No | | |
|
||||
| tabComponents | object | Yes | | |
|
||||
| watermarkComponent | object | Yes | | |
|
||||
| hideBorders | boolean | Yes | false | |
|
||||
| className | string | Yes | '' | |
|
||||
| disableAutoResizing | boolean | Yes | false | See <Link to="/docs/basics/#auto-resizing">Auto Resizing</Link> |
|
||||
| onTabContextMenu | Event | Yes | false | |
|
||||
| onDidDrop | Event | Yes | false | |
|
||||
| showDndOverlay | Event | Yes | false | |
|
||||
|
||||
## Dockview API
|
||||
|
||||
```tsx
|
||||
const MyComponent = (props: IDockviewPanelProps<{ title: string }>) => {
|
||||
// props.containerApi...
|
||||
|
||||
return <div>{`My first panel has the title: ${props.params.title}`}</div>;
|
||||
};
|
||||
```
|
||||
|
||||
```tsx
|
||||
const onReady = (event: DockviewReadyEvent) => {
|
||||
// event.api...
|
||||
};
|
||||
```
|
||||
|
||||
| Property | Type | Description |
|
||||
| ---------------------- | ---------------------------------------------------- | ----------------------------------------------------------- |
|
||||
| height | `number` | Component pixel height |
|
||||
| width | `number` | Component pixel width |
|
||||
| minimumHeight | `number` | |
|
||||
| maximumHeight | `number` | |
|
||||
| maximumWidth | `number` | |
|
||||
| maximumWidth | `number` | |
|
||||
| length | `number` | Number of panels |
|
||||
| size | `number` | Number of Groups |
|
||||
| panels | `IDockviewPanel[]` | |
|
||||
| groups | `GroupPanel[]` | |
|
||||
| activePanel | `IDockviewPanel \| undefined` | |
|
||||
| activeGroup | `IDockviewPanel \| undefined` | |
|
||||
| | | |
|
||||
| onDidLayoutChange | `Event<void>` | |
|
||||
| onDidLayoutFromJSON | `Event<void>` | |
|
||||
| onDidAddGroup | `Event<GroupPanel>` | |
|
||||
| onDidRemoveGroup | `Event<GroupPanel>` | |
|
||||
| onDidActiveGroupChange | `Event<GroupPanel \| undefined>` | |
|
||||
| onDidAddPanel | `Event<IDockviewPanel>` | |
|
||||
| onDidRemovePanel | `Event<IDockviewPanel>` | |
|
||||
| onDidActivePanelChange | `Event<IDockviewPanel \| undefined>` | |
|
||||
| onDidDrop | `Event<DockviewDropEvent` | |
|
||||
| | | |
|
||||
| addPanel | `addPanel(options: AddPanelOptions): IDockviewPanel` | |
|
||||
| getPanel | `(id: string) \| IDockviewPanel \| undefined` | |
|
||||
| addEmptyGroup | `(options? AddGroupOptions): void` | |
|
||||
| closeAllGroups | `(): void` | |
|
||||
| removeGroup | `(group: GroupPanel): void` | |
|
||||
| getGroup | `(id: string): GroupPanel \| undefined` | |
|
||||
| | | |
|
||||
| getTabHeight | `(): number \| undefined` | |
|
||||
| setTabHeight | `(hegiht: number \| undefined): void` | |
|
||||
| updateOptions | `(options:SplitviewComponentUpdateOptions): void` | |
|
||||
| focus | `(): void` | |
|
||||
| layout | `(width: number, height:number): void` | <Link to="/docs/basics/#auto-resizing">Auto Resizing</Link> |
|
||||
| fromJSON | `(data: SerializedDockview): void` | <Link to="/docs/basics/#serialization">Serialization</Link> |
|
||||
| toJSON | `(): SerializedDockview` | <Link to="/docs/basics/#serialization">Serialization</Link> |
|
||||
| clear | `(): void` | Clears the current layout |
|
||||
|
||||
## Dockview Panel API
|
||||
|
||||
```tsx
|
||||
const MyComponent = (props: IDockviewPanelProps<{ title: string }>) => {
|
||||
// props.api...
|
||||
|
||||
return <div>{`My first panel has the title: ${props.params.title}`}</div>;
|
||||
};
|
||||
```
|
||||
|
||||
| Property | Type | Description |
|
||||
| ---------------------- | ----------------------------------------------------------- | --------------- |
|
||||
| id | `string` | Panel id |
|
||||
| isFocused | `boolean` | Is panel focsed |
|
||||
| isActive | `boolean` | Is panel active |
|
||||
| width | `number` | Panel width |
|
||||
| height | `number` | Panel height |
|
||||
| onDidDimensionsChange | `Event<PanelDimensionChangeEvent>` | |
|
||||
| onDidFocusChange | `Event<FocusEvent>` | |
|
||||
| onDidVisibilityChange | `Event<VisibilityEvent>` | |
|
||||
| onDidActiveChange | `Event<ActiveEvent>` | |
|
||||
| setActive | `(): void` | |
|
||||
| | | |
|
||||
| onDidConstraintsChange | `onDidConstraintsChange: Event<PanelConstraintChangeEvent>` | |
|
||||
| setConstraints | `(value: PanelConstraintChangeEvent2): void;` | |
|
||||
| setSize | `(event: SizeEvent): void` | |
|
||||
| | | |
|
||||
| group | `GroupPanel | undefined` |
|
||||
| isGroupActive | `boolean` | |
|
||||
| title | `string` | |
|
||||
| suppressClosable | `boolean` | |
|
||||
| close | `(): void` | |
|
||||
| setTitle | `(title: string): void` | |
|
||||
|
||||
## Advanced Features
|
||||
|
||||
### Locked group
|
||||
|
||||
Locking a group will disable all drop events for this group ensuring a user can not add additional panels to the group.
|
||||
You can still add groups to a locked panel programatically using the api.
|
||||
|
||||
```tsx
|
||||
panel.group.locked = true;
|
||||
```
|
||||
|
||||
### Group header
|
||||
|
||||
You may wish to hide the header section of a group. This can achieved through setting the `hidden` variable on `panel.group.header`.
|
||||
|
||||
```tsx
|
||||
panel.group.header.hidden = true;
|
||||
```
|
||||
|
||||
### Context Menu
|
||||
|
||||
import { ContextMenuDockview } from '../../src/components/dockview/contextMenu';
|
||||
|
||||
<div
|
||||
style={{
|
||||
height: '300px',
|
||||
backgroundColor: 'rgb(30,30,30)',
|
||||
color: 'white',
|
||||
margin: '20px 0px',
|
||||
}}
|
||||
>
|
||||
<ContextMenuDockview />
|
||||
</div>
|
||||
|
||||
### Rendering
|
||||
|
||||
Although `DockviewReact` will only add those tabs that are visible to the DOM all associated React Components for each tab including those that
|
||||
are not initially visible will be created.
|
||||
This will mean that any hooks in those components will run and if you running expensive operations in the tabs you may end up doing a lot of initial
|
||||
work for what are hidden tabs.
|
||||
|
||||
This is the default behaviour to ensure the greatest flexibility for the user but you can create a Higher-Order component wrapping your components that
|
||||
will ensure the component is only created if the tab is visible as below:
|
||||
|
||||
```tsx
|
||||
import { PanelApi } from 'dockview';
|
||||
import * as React from 'react';
|
||||
|
||||
function RenderWhenVisible<
|
||||
T extends { api: Pick<PanelApi, 'isVisible' | 'onDidVisibilityChange'> }
|
||||
>(component: React.FunctionComponent<T>) {
|
||||
const HigherOrderComponent = (props: T) => {
|
||||
const [visible, setVisible] = React.useState<boolean>(
|
||||
props.api.isVisible
|
||||
);
|
||||
|
||||
React.useEffect(() => {
|
||||
const disposable = props.api.onDidVisibilityChange((event) =>
|
||||
setVisible(event.isVisible)
|
||||
);
|
||||
|
||||
return () => {
|
||||
disposable.dispose();
|
||||
};
|
||||
}, [props.api]);
|
||||
|
||||
if (!visible) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return React.createElement(component, props);
|
||||
};
|
||||
return HigherOrderComponent;
|
||||
}
|
||||
```
|
||||
|
||||
```tsx
|
||||
const component = RenderWhenVisible(MyComponent);
|
||||
```
|
||||
|
||||
Through toggling the checkbox you can see that when you only render those panels which are visible the underling React component is destroyed when it becomes hidden and re-created when it becomes visible.
|
||||
|
||||
<Checkbox />
|
||||
<div
|
||||
style={{
|
||||
height: '300px',
|
||||
backgroundColor: 'rgb(30,30,30)',
|
||||
color: 'white',
|
||||
margin: '20px 0px',
|
||||
}}
|
||||
>
|
||||
<RenderingDockview renderVisibleOnly={false} />
|
||||
</div>
|
||||
|
||||
### Drag And Drop
|
||||
|
||||
The component exposes some method to help determine whether external drag events should be interacted with or not.
|
||||
|
||||
```tsx
|
||||
/**
|
||||
* called when an ondrop event which does not originate from the dockview libray and
|
||||
* passes the showDndOverlay condition occurs
|
||||
**/
|
||||
const onDidDrop = (event: DockviewDropEvent) => {
|
||||
const { group } = event;
|
||||
|
||||
event.api.addPanel({
|
||||
id: 'test',
|
||||
component: 'default',
|
||||
position: {
|
||||
referencePanel: group.activePanel.id,
|
||||
direction: 'within',
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* called for drag over events which do not originate from the dockview library
|
||||
* allowing the developer to decide where the overlay should be shown for a
|
||||
* particular drag event
|
||||
**/
|
||||
const showDndOverlay = (event: DockviewDndOverlayEvent) => {
|
||||
return true;
|
||||
};
|
||||
|
||||
return (
|
||||
<DockviewReact
|
||||
components={components}
|
||||
onReady={onReady}
|
||||
className="dockview-theme-dark"
|
||||
onDidDrop={onDidDrop}
|
||||
showDndOverlay={showDndOverlay}
|
||||
/>
|
||||
);
|
||||
```
|
||||
|
||||
<DndDockview />
|
||||
|
||||
### Events
|
||||
|
||||
<EventsDockview />
|
116
build/docs/docs/api/gridview.mdx
Normal file
@ -0,0 +1,116 @@
|
||||
import { SimpleGridview } from '../../src/components/simpleGridview';
|
||||
import { EventsGridview } from '../../src/components/gridview/events';
|
||||
import Link from '@docusaurus/Link';
|
||||
|
||||
# Gridview
|
||||
|
||||
## Introduction
|
||||
|
||||
<div
|
||||
style={{
|
||||
height: '300px',
|
||||
backgroundColor: 'rgb(30,30,30)',
|
||||
color: 'white',
|
||||
margin: '20px 0px',
|
||||
}}
|
||||
>
|
||||
<SimpleGridview />
|
||||
</div>
|
||||
|
||||
## GridviewReact Component
|
||||
|
||||
```tsx
|
||||
import { ReactGridview } from 'dockview';
|
||||
```
|
||||
|
||||
| Property | Type | Optional | Default | Description |
|
||||
| ------------------- | ------------------------------------ | -------- | ---------------------- | --------------------------------------------------------------------------- |
|
||||
| onReady | (event: SplitviewReadyEvent) => void | No | | |
|
||||
| components | object | No | | |
|
||||
| orientation | Orientation | Yes | Orientation.HORIZONTAL | |
|
||||
| proportionalLayout | boolean | Yes | true | See <Link to="/docs/basics/#proportional-layout">Proportional layout</Link> |
|
||||
| hideBorders | boolean | Yes | false | |
|
||||
| className | string | Yes | '' | |
|
||||
| disableAutoResizing | boolean | Yes | false | See <Link to="/docs/basics/#auto-resizing">Auto Resizing</Link> |
|
||||
|
||||
## Gridview API
|
||||
|
||||
```tsx
|
||||
const MyComponent = (props: IGridviewPanelProps<{ title: string }>) => {
|
||||
// props.containerApi...
|
||||
|
||||
return <div>{`My first panel has the title: ${props.params.title}`}</div>;
|
||||
};
|
||||
```
|
||||
|
||||
```tsx
|
||||
const onReady = (event: GridviewReadyEvent) => {
|
||||
// event.api...
|
||||
};
|
||||
```
|
||||
|
||||
| Property | Type | Description |
|
||||
| ---------------------- | ------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- |
|
||||
| height | `number` | Component pixel height |
|
||||
| width | `number` | Component pixel width |
|
||||
| minimumHeight | `number` | |
|
||||
| maximumHeight | `number` | |
|
||||
| maximumWidth | `number` | |
|
||||
| maximumWidth | `number` | |
|
||||
| length | `number` | Number of panels |
|
||||
| panels | `ISplitviewPanel[]` | all panels |
|
||||
| orientation | `Orientation` | |
|
||||
| | | |
|
||||
| onDidLayoutChange | `Event<void>` | Fires on layout change |
|
||||
| onDidLayoutFromJSON | `Event<void>` | Fires of layout change caused by a fromJSON deserialization call |
|
||||
| onDidAddPanel | `Event<IGridviewPanel>` | Fires when a view is added |
|
||||
| onDidRemovePanel | `Event<IGridviewPanel>` | Fires when a view is removed |
|
||||
| onDidActivePanelChange | `Event<IGridviewPanel \| undefined>` | Fires when the active group changes |
|
||||
| | | |
|
||||
| addPanel | `addPanel(options: AddComponentOptions): IGridviewPanel` | |
|
||||
| removePanel | `(panel: IGridviewPanel, sizing?: Sizing): void` | |
|
||||
| movePanel | `(panel: IGridviewPanel, options: {direction: Direction, refernece:string, size?: number}): void` | |
|
||||
| getPanel | `(id: string) \| IGridviewPanel \| undefined` | |
|
||||
| | | |
|
||||
| updateOptions | `(options:SplitviewComponentUpdateOptions): void` | |
|
||||
| focus | `(): void` | Focus the active panel, if exists |
|
||||
| layout | `(width: number, height:number): void` | <Link to="/docs/basics/#auto-resizing">Auto Resizing</Link> |
|
||||
| fromJSON | `(data: SerializedGridview): void` | <Link to="/docs/basics/#serialization">Serialization</Link> |
|
||||
| toJSON | `(): SerializedGridview` | <Link to="/docs/basics/#serialization">Serialization</Link> |
|
||||
| clear | `(): void` | Clears the current layout |
|
||||
|
||||
## Gridview Panel API
|
||||
|
||||
```tsx
|
||||
const MyComponent = (props: IGridviewPanelProps<{ title: string }>) => {
|
||||
// props.api...
|
||||
|
||||
return <div>{`My first panel has the title: ${props.params.title}`}</div>;
|
||||
};
|
||||
```
|
||||
|
||||
| Property | Type | Description |
|
||||
| ---------------------- | ----------------------------------------------------------- | ---------------- |
|
||||
| id | `string` | Panel id |
|
||||
| isFocused | `boolean` | Is panel focsed |
|
||||
| isActive | `boolean` | Is panel active |
|
||||
| isVisible | `boolean` | Is panel visible |
|
||||
| width | `number` | Panel width |
|
||||
| height | `number` | Panel height |
|
||||
| | | |
|
||||
| onDidDimensionsChange | `Event<PanelDimensionChangeEvent>` | |
|
||||
| onDidFocusChange | `Event<FocusEvent>` | |
|
||||
| onDidVisibilityChange | `Event<VisibilityEvent>` | |
|
||||
| onDidActiveChange | `Event<ActiveEvent>` | |
|
||||
| onDidConstraintsChange | `onDidConstraintsChange: Event<PanelConstraintChangeEvent>` | |
|
||||
| | | |
|
||||
| setVisible | `(isVisible: boolean): void` | |
|
||||
| setActive | `(): void` | |
|
||||
| setConstraints | `(value: PanelConstraintChangeEvent2): void;` | |
|
||||
| setSize | `(event: SizeEvent): void` | |
|
||||
|
||||
## Events
|
||||
|
||||
`GridviewReact` exposes a number of events that the developer can listen to and below is a simple example with a log panel showing those events that occur.
|
||||
|
||||
<EventsGridview />
|
185
build/docs/docs/api/paneview.mdx
Normal file
@ -0,0 +1,185 @@
|
||||
import { SimplePaneview } from '../../src/components/simplePaneview';
|
||||
import Link from '@docusaurus/Link';
|
||||
|
||||
# Paneview
|
||||
|
||||
# Introduction
|
||||
|
||||
<div
|
||||
style={{
|
||||
height: '400px',
|
||||
backgroundColor: 'rgb(30,30,30)',
|
||||
color: 'white',
|
||||
margin: '20px 0px',
|
||||
}}
|
||||
>
|
||||
<SimplePaneview />
|
||||
</div>
|
||||
|
||||
## PaneviewReact Component
|
||||
|
||||
```tsx
|
||||
import { ReactPaneview } from 'dockview';
|
||||
```
|
||||
|
||||
| Property | Type | Optional | Default | Description |
|
||||
| ------------------- | ------------------------------------ | -------- | ------- | ----------------------------------------------------------- |
|
||||
| onReady | (event: SplitviewReadyEvent) => void | No | | |
|
||||
| components | object | No | | |
|
||||
| headerComponents | object | Yes | | |
|
||||
| className | string | Yes | '' | |
|
||||
| disableAutoResizing | boolean | Yes | false | <Link to="/docs/basics/#auto-resizing">Auto Resizing</Link> |
|
||||
| disableDnd | boolean | Yes | false | |
|
||||
| onDidDrop | Event | Yes | | |
|
||||
|
||||
## Paneview API
|
||||
|
||||
```tsx
|
||||
const MyComponent = (props: IGridviewPanelProps<{ title: string }>) => {
|
||||
// props.containerApi...
|
||||
|
||||
return <div>{`My first panel has the title: ${props.params.title}`}</div>;
|
||||
};
|
||||
```
|
||||
|
||||
```tsx
|
||||
const onReady = (event: GridviewReadyEvent) => {
|
||||
// event.api...
|
||||
};
|
||||
```
|
||||
|
||||
| Property | Type | Description |
|
||||
| ------------------- | ---------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
|
||||
| height | `number` | Component pixel height |
|
||||
| width | `number` | Component pixel width |
|
||||
| minimumSize | `number` | The sum of the `minimumSize` property for each panel |
|
||||
| maximumSize | `number` | The sum of the `maximumSize` property for each panel |
|
||||
| length | `number` | Number of panels |
|
||||
| panels | `IPaneviewPanel[]` | All panels |
|
||||
| | | |
|
||||
| onDidLayoutChange | `Event<void>` | Fires on layout change |
|
||||
| onDidLayoutFromJSON | `Event<void>` | Fires of layout change caused by a fromJSON deserialization call |
|
||||
| onDidAddView | `Event<IPaneviewPanel>` | Fires when a view is added |
|
||||
| onDidRemoveView | `Event<IPaneviewPanel>` | Fires when a view is removed |
|
||||
| onDidDrop | `Event<PaneviewDropEvent` | Fires on an external drop event (See <Link to="/docs/api/paneview/#drag-and-drop">Drag and Drop</Link>) |
|
||||
| | | |
|
||||
| addPanel | `addPanel(options: AddPaneviewComponentOptions): IPaneviewPanel` | |
|
||||
| removePanel | `(panel: IPaneviewPanel): void` | |
|
||||
| movePanel | `(from: number, to: number): void` | |
|
||||
| getPanel | `(id:string): IPaneviewPanel \| undefined` | |
|
||||
| | | |
|
||||
| focus | `(): void` | Focus the active panel, if exists |
|
||||
| layout | `(width: number, height:number): void` | See <Link to="/docs/basics/#auto-resizing">Auto Resizing</Link> |
|
||||
| fromJSON | `(data: SerializedPaneview): void` | <Link to="/docs/basics/#serialization">Serialization</Link> |
|
||||
| toJSON | `(): SerializedPaneview` | <Link to="/docs/basics/#serialization">Serialization</Link> |
|
||||
| clear | `(): void` | Clears the current layout |
|
||||
|
||||
## Gridview Panel API
|
||||
|
||||
```tsx
|
||||
const MyComponent = (props: IGridviewPanelProps<{ title: string }>) => {
|
||||
// props.api...
|
||||
|
||||
return <div>{`My first panel has the title: ${props.params.title}`}</div>;
|
||||
};
|
||||
```
|
||||
|
||||
| Property | Type | Description |
|
||||
| ---------------------- | ----------------------------------------------------------- | ---------------- |
|
||||
| id | `string` | Panel id |
|
||||
| isFocused | `boolean` | Is panel focsed |
|
||||
| isActive | `boolean` | Is panel active |
|
||||
| isVisible | `boolean` | Is panel visible |
|
||||
| width | `number` | Panel width |
|
||||
| height | `number` | Panel height |
|
||||
| | |
|
||||
| onDidDimensionsChange | `Event<PanelDimensionChangeEvent>` | |
|
||||
| onDidFocusChange | `Event<FocusEvent>` | |
|
||||
| onDidVisibilityChange | `Event<VisibilityEvent>` | |
|
||||
| onDidActiveChange | `Event<ActiveEvent>` | |
|
||||
| onDidConstraintsChange | `onDidConstraintsChange: Event<PanelConstraintChangeEvent>` | |
|
||||
| | |
|
||||
| setVisible | `(isVisible: boolean): void` | |
|
||||
| setActive | `(): void` | |
|
||||
| setConstraints | `(value: PanelConstraintChangeEvent2): void;` | |
|
||||
| setSize | `(event: SizeEvent): void` | |
|
||||
|
||||
## Advanced Features
|
||||
|
||||
### Custom Header
|
||||
|
||||
The above example shows the default header and will render the `title` along with a small icon to indicate a collapsed or expanded state.
|
||||
You can provide a custom header:
|
||||
|
||||
```tsx
|
||||
const onReady = (event: PaneviewReadyEvent) => {
|
||||
event.api.addPanel({
|
||||
id: 'panel_1',
|
||||
component: 'default',
|
||||
headerComponent: 'myHeaderComponent',
|
||||
params: {
|
||||
valueA: 'A',
|
||||
},
|
||||
title: 'Panel 1',
|
||||
});
|
||||
};
|
||||
```
|
||||
|
||||
The above example shows the default header and will render the `title` along with a small icon to indicate a collapsed or expanded state.
|
||||
You can provide a custom header:
|
||||
|
||||
```tsx
|
||||
const onReady = (event: PaneviewReadyEvent) => {
|
||||
event.api.addPanel({
|
||||
id: 'panel_1',
|
||||
component: 'default',
|
||||
headerComponent: 'myHeaderComponent',
|
||||
params: {
|
||||
valueA: 'A',
|
||||
},
|
||||
title: 'Panel 1',
|
||||
});
|
||||
};
|
||||
```
|
||||
|
||||
You can define a header component and listen to the expanded state to update the component accordingly.
|
||||
|
||||
```tsx
|
||||
const CustomHeader = (props: IPaneviewPanelProps) => {
|
||||
const [expanded, setExpanded] = React.useState<boolean>(
|
||||
props.api.isExpanded
|
||||
);
|
||||
|
||||
React.useEffect(() => {
|
||||
const disposable = props.api.onDidExpansionChange((event) => {
|
||||
setExpanded(event.isExpanded);
|
||||
});
|
||||
|
||||
return () => {
|
||||
disposable.dispose();
|
||||
};
|
||||
}, []);
|
||||
|
||||
const onClick = () => {
|
||||
props.api.setExpanded(!expanded);
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<a
|
||||
onClick={onClick}
|
||||
className={expanded ? 'expanded' : 'collapsed'}
|
||||
/>
|
||||
<span>{props.params.title}</span>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
You should provide a value for the `headerComponents` React prop.
|
||||
|
||||
```tsx
|
||||
const headerComponents = { myHeaderComponent: CustomHeader };
|
||||
```
|
||||
|
||||
### Drag And Drop
|
243
build/docs/docs/api/splitview.mdx
Normal file
@ -0,0 +1,243 @@
|
||||
import { SimpleSplitview } from '../../src/components/simpleSplitview';
|
||||
import { SplitviewExample1 } from '../../src/components/splitview/active';
|
||||
import Link from '@docusaurus/Link';
|
||||
|
||||
# Splitview
|
||||
|
||||
## Introduction
|
||||
|
||||
A Splitview is a collection resizable horizontally or vertically stacked panels.
|
||||
The Splitview exposes a component level API through the `onReady` event and through the `props.containerApi` variable on the panel props.
|
||||
A panel level API is exposed on each panel through it's props as `props.api`.
|
||||
|
||||
<div
|
||||
style={{
|
||||
height: '100px',
|
||||
backgroundColor: 'rgb(30,30,30)',
|
||||
color: 'white',
|
||||
margin: '20px 0px',
|
||||
}}
|
||||
>
|
||||
<SimpleSplitview />
|
||||
</div>
|
||||
|
||||
```tsx title="Simple Splitview example"
|
||||
import {
|
||||
ISplitviewPanelProps,
|
||||
Orientation,
|
||||
SplitviewReact,
|
||||
SplitviewReadyEvent,
|
||||
} from 'dockview';
|
||||
|
||||
const components = {
|
||||
default: (props: ISplitviewPanelProps<{ title: string }>) => {
|
||||
return <div style={{ padding: '20px' }}>{props.params.title}</div>;
|
||||
},
|
||||
};
|
||||
|
||||
export const SimpleSplitview = () => {
|
||||
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}
|
||||
orientation={Orientation.HORIZONTAL}
|
||||
className="dockview-theme-dark"
|
||||
/>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
## SplitviewReact Component
|
||||
|
||||
You can create a Splitview through the use of the `ReactSplitview` component.
|
||||
|
||||
```tsx
|
||||
import { ReactSplitview } from 'dockview';
|
||||
```
|
||||
|
||||
Using the `onReady` prop you can access to the component `api` and add panels either through deserialization or indivial addition of panels.
|
||||
|
||||
| Property | Type | Optional | Default | Description |
|
||||
| ------------------- | -------------------------------------- | -------- | ------------------------ | --------------------------------------------------------------------------- |
|
||||
| onReady | `(event: SplitviewReadyEvent) => void` | No | | Function |
|
||||
| components | `Record<string, ISplitviewPanelProps>` | No | | Panel renderers |
|
||||
| orientation | `Orientation` | Yes | `Orientation.HORIZONTAL` | Orientation of the Splitview |
|
||||
| proportionalLayout | `boolean` | Yes | `true` | See <Link to="/docs/basics/#proportional-layout">Proportional layout</Link> |
|
||||
| hideBorders | `boolean` | Yes | `false` | Hide the borders between panels |
|
||||
| className | `string` | Yes | `''` | Attaches a classname |
|
||||
| disableAutoResizing | `boolean` | Yes | `false` | See <Link to="/docs/basics/#auto-resizing">Auto Resizing</Link> |
|
||||
|
||||
## Splitview API
|
||||
|
||||
The Splitview API is exposed both at the `onReady` event and on each panel through `props.containerApi`.
|
||||
|
||||
```tsx title="Splitview API via Panel component"
|
||||
const MyComponent = (props: ISplitviewPanelProps<{ title: string }>) => {
|
||||
// props.containerApi...
|
||||
|
||||
return <div>{`My first panel has the title: ${props.params.title}`}</div>;
|
||||
};
|
||||
```
|
||||
|
||||
```tsx title="Splitview API via the onReady callback"
|
||||
const onReady = (event: SplitviewReadyEvent) => {
|
||||
// event.api...
|
||||
};
|
||||
```
|
||||
|
||||
| Property | Type | Description |
|
||||
| ------------------- | ------------------------------------------------------------------ | ---------------------------------------------------------------- |
|
||||
| height | `number` | Component pixel height |
|
||||
| width | `number` | Component pixel width |
|
||||
| minimumSize | `number` | The sum of the `minimumSize` property for each panel |
|
||||
| maximumSize | `number` | The sum of the `maximumSize` property for each panel |
|
||||
| length | `number` | Number of panels |
|
||||
| panels | `ISplitviewPanel[]` | All panels |
|
||||
| | | |
|
||||
| onDidLayoutChange | `Event<void>` | Fires on layout change |
|
||||
| onDidLayoutFromJSON | `Event<void>` | Fires of layout change caused by a fromJSON deserialization call |
|
||||
| onDidAddView | `Event<IView>` | Fires when a view is added |
|
||||
| onDidRemoveView | `Event<IView>` | Fires when a view is removed |
|
||||
| | | |
|
||||
| addPanel | `addPanel(options: AddSplitviewComponentOptions): ISplitviewPanel` | |
|
||||
| removePanel | `(panel: ISplitviewPanel, sizing?: Sizing): void` | |
|
||||
| getPanel | `(id:string): ISplitviewPanel \| undefined` | |
|
||||
| movePanel | `(from: number, to: number): void` | |
|
||||
| | |
|
||||
| updateOptions | `(options: SplitviewComponentUpdateOptions): void` | |
|
||||
| focus | `(): void` | Focus the active panel, if exists |
|
||||
| layout | `(width: number, height:number): void` | See <Link to="/docs/basics/#auto-resizing">Auto Resizing</Link> |
|
||||
| fromJSON | `(data: SerializedSplitview): void` | <Link to="/docs/basics/#serialization">Serialization</Link> |
|
||||
| toJSON | `(): SerializedSplitview` | <Link to="/docs/basics/#serialization">Serialization</Link> |
|
||||
| clear | `(): void` | Clears the current layout |
|
||||
|
||||
## Splitview Panel API
|
||||
|
||||
The Splitview panel API is exposed on each panel and contains actions and variables specific to that panel.
|
||||
|
||||
```tsx title="Splitview panel API via Panel component"
|
||||
const MyComponent = (props: ISplitviewPanelProps<{ title: string }>) => {
|
||||
// props.api...
|
||||
|
||||
return <div>{`My first panel has the title: ${props.params.title}`}</div>;
|
||||
};
|
||||
```
|
||||
|
||||
| Property | Type | Description |
|
||||
| ---------------------- | ----------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
|
||||
| id | `string` | Panel id |
|
||||
| isFocused | `boolean` | Is panel focsed |
|
||||
| isActive | `boolean` | Is panel active |
|
||||
| isVisible | `boolean` | Is panel visible |
|
||||
| width | `number` | Panel width |
|
||||
| height | `number` | Panel height |
|
||||
| | | |
|
||||
| onDidDimensionsChange | `Event<PanelDimensionChangeEvent>` | Fires when panel dimensions change |
|
||||
| onDidFocusChange | `Event<FocusEvent>` | Fire when panel is focused and blurred |
|
||||
| onDidVisibilityChange | `Event<VisibilityEvent>` | Fires when the panels visiblity property is changed (see <Link to="/docs/api/splitview/#visibility">Panel Visibility</Link>) |
|
||||
| onDidActiveChange | `Event<ActiveEvent>` | Fires when the panels active property is changed (see <Link to="/docs/api/splitview/#active">Active Panel</Link>) |
|
||||
| onDidConstraintsChange | `onDidConstraintsChange: Event<PanelConstraintChangeEvent>` | Fires when the panels size contrainsts change (see <Link to="/docs/api/splitview/#contraints">Panel Constraints</Link>) |
|
||||
| | | |
|
||||
| setVisible | `(isVisible: boolean): void` | |
|
||||
| setActive | `(): void` | |
|
||||
| | | |
|
||||
| setConstraints | `(value: PanelConstraintChangeEvent2): void;` | |
|
||||
| setSize | `(event: PanelSizeEvent): void` | |
|
||||
|
||||
## Advanced Features
|
||||
|
||||
Listed below are some functionality avalaible to you through both the panel and component APIs. The live demo shows examples of these in real-time.
|
||||
|
||||
<div
|
||||
style={{
|
||||
height: '200px',
|
||||
margin: '20px 0px',
|
||||
}}
|
||||
>
|
||||
<SplitviewExample1 />
|
||||
</div>
|
||||
|
||||
### Visibility
|
||||
|
||||
A panels visibility can be controlled and monitoring through the following code.
|
||||
A panel with visibility set to `false` will remain as a part of the components list of panels but will not be rendered.
|
||||
|
||||
```tsx
|
||||
const disposable = props.api.onDidVisibilityChange(({ isVisible }) => {
|
||||
//
|
||||
});
|
||||
```
|
||||
|
||||
```tsx
|
||||
api.setVisible(true);
|
||||
```
|
||||
|
||||
### Active
|
||||
|
||||
Only one panel in the `splitview` can be the active panel at any one time.
|
||||
Setting a panel as active will set all the others as inactive.
|
||||
A focused panel is always the active panel but an active panel is not always focused.
|
||||
|
||||
```tsx
|
||||
const disposable = props.api.onDidActiveChange(({ isActive }) => {
|
||||
//
|
||||
});
|
||||
```
|
||||
|
||||
```tsx
|
||||
api.setActive();
|
||||
```
|
||||
|
||||
### Contraints
|
||||
|
||||
When adding a panel you can specify pixel size contraints
|
||||
|
||||
```tsx
|
||||
event.api.addPanel({
|
||||
id: 'panel_3',
|
||||
component: 'default',
|
||||
minimumSize: 100,
|
||||
maximumSize: 1000,
|
||||
});
|
||||
```
|
||||
|
||||
These contraints can be updated throughout the lifecycle of the `splitview` using the panel API
|
||||
|
||||
```tsx
|
||||
props.api.onDidConstraintsChange(({ maximumSize, minimumSize }) => {
|
||||
//
|
||||
});
|
||||
```
|
||||
|
||||
```tsx
|
||||
api.setConstraints({
|
||||
maximumSize: 200,
|
||||
minimumSize: 400,
|
||||
});
|
||||
```
|
117
build/docs/docs/basics.mdx
Normal file
@ -0,0 +1,117 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
import { SimpleSplitview } from '../src/components/simpleSplitview';
|
||||
import { SimpleSplitview2 } from '../src/components/simpleSplitview2';
|
||||
|
||||
# Basics
|
||||
|
||||
This section will take you through a number of concepts that can be applied to all dockview components.
|
||||
|
||||
## Panels
|
||||
|
||||
The below examples use `ReactSplitview` but the logic holds for `ReactPaneview`, `ReactGridview` and `ReactDockview` using their respective implementations and interfaces.
|
||||
All components require you to provide an `onReady` prop which you can use to build and control your component.
|
||||
|
||||
### Adding a panel with parameters
|
||||
|
||||
You can pass parameters to a panel through the `params` object
|
||||
|
||||
```tsx
|
||||
const onReady = (event: SplitviewReadyEvent) => {
|
||||
event.api.addPanel({
|
||||
id: 'panel_1',
|
||||
component: 'myComponent',
|
||||
params: {
|
||||
title: 'My Title',
|
||||
},
|
||||
});
|
||||
};
|
||||
```
|
||||
|
||||
and you can access those properties through the `props.params` object. The TypeScript interface accepts an optional generic type `T` that corresponds to the params objects type.
|
||||
|
||||
```tsx
|
||||
const MyComponent = (props: ISplitviewPanelProps<{ title: string }>) => {
|
||||
return <div>{`My first panel has the title: ${props.params.title}`}</div>;
|
||||
};
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
There are two types of API you will interact with using `dockview`.
|
||||
|
||||
- The `panel API` is accessible via `props.api` in user defined panels and via the `.api` variable found on panel instances. This API contains actions and variable related to the the individual panel.
|
||||
- The `container API` is accessible via `event.api` in the `onReady` events and `props.containerApi` in user defined panels. This API contains actions and variable related to the component as a whole.
|
||||
|
||||
```tsx
|
||||
const MyComponent = (props: ISplitviewPanelProps<{ title: string }>) => {
|
||||
React.useEffect(() => {
|
||||
const disposable = props.api.onDidActiveChange((event) => {
|
||||
console.log(`is panel active: ${event.isActive}`);
|
||||
});
|
||||
|
||||
return () => {
|
||||
disposable.dispose(); // remember to dispose of any subscriptions
|
||||
};
|
||||
}, [props.api]);
|
||||
|
||||
const addAnotherPanel = React.useCallback(() => {
|
||||
props.containerApi.addPanel({
|
||||
id: 'another_id',
|
||||
component: 'anotherComponent',
|
||||
});
|
||||
}, [props.containerApi]);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<span>{`My first panel has the title: ${props.params.title}`}</span>
|
||||
<button onClick={addAnotherPanel}>Add Panel</button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
### Serialization
|
||||
|
||||
All components support `toJSON(): T` which returns a Typed object representation of the components state. This same Typed object can be used to deserialize a view using `fromJSON(object: T): void`.
|
||||
|
||||
## Auto resizing
|
||||
|
||||
`SplitviewReact`, `GridviewReact`, `PaneviewReact` and `DockviewReact` will all automatically resize to fill the size of their parent element.
|
||||
Internally this is achieved using a [ResizeObserver](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver) which some users may need to polyfill.
|
||||
You can disable this by settings the `disableAutoResizing` prop to be `true`.
|
||||
|
||||
You can manually resize a component using the API method `layout(width: number, height: number): void`.
|
||||
An advanced case may use this in conjunction with `disableAutoResizing=true` to allow a parent component to have ultimate control over the dimensions of the component.
|
||||
|
||||
## Events
|
||||
|
||||
Many API properties can be listened on using the `Event` pattern. For example `api.onDidFocusChange(() => {...})`.
|
||||
You should dispose of any event listeners you create cleaning up any listeners you would have created.
|
||||
|
||||
```tsx
|
||||
React.useEffect(() => {
|
||||
const disposable = api.onDidFocusChange(() => {
|
||||
// write some code
|
||||
});
|
||||
|
||||
return () => {
|
||||
disposable.dispose();
|
||||
};
|
||||
}, []);
|
||||
```
|
||||
|
||||
## Proportional layout
|
||||
|
||||
The `proportionalLayout` property indicates the expected behaviour of the component as it's container resizes, should all views resize equally or should just one view expand to fill the new space. `proportionalLayout` can be set as a property on `SplitviewReact` and `GridviewReact` components.
|
||||
Although not configurable on `DockviewReact` and `PaneviewReact` these both behave as if `proportionalLayout=true` was set for them.
|
||||
|
||||
<SimpleSplitview2 proportional={false} />
|
||||
|
||||
<SimpleSplitview2 proportional={true} />
|
||||
|
||||
## Browser support
|
||||
|
||||
dockview is intended to support all major browsers. Some users may require a polyfill for [ResizeObserver](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver).
|
150
build/docs/docs/index.mdx
Normal file
@ -0,0 +1,150 @@
|
||||
---
|
||||
sidebar_position: 0
|
||||
---
|
||||
|
||||
import { SimpleSplitview } from '../src/components/simpleSplitview';
|
||||
import { SimpleGridview } from '../src/components/simpleGridview';
|
||||
import { SimplePaneview } from '../src/components/simplePaneview';
|
||||
import { SimpleDockview } from '../src/components/simpleDockview';
|
||||
|
||||
# Dockview
|
||||
|
||||
## Introduction
|
||||
|
||||
**dockview** is a zero dependency layout manager that supports tab, grids and splitviews.
|
||||
|
||||
## Features
|
||||
|
||||
- Themable and customizable
|
||||
- Support for the serialization and deserialization of layouts
|
||||
- Drag and drop support
|
||||
|
||||
## Quick start
|
||||
|
||||
`dockview` has a peer dependency on `react >= 16.8.0` and `react-dom >= 16.8.0`. To install `dockview` you can run:
|
||||
|
||||
```shell
|
||||
npm install dockview
|
||||
```
|
||||
|
||||
You must also import the dockview stylesheet found under [`dockview/dict/styles/dockview.css`](https://unpkg.com/browse/dockview@latest/dist/styles/dockview.css),
|
||||
depending on your solution this might be:
|
||||
|
||||
```css
|
||||
@import './node_modules/dockview/dist/styles/dockview.css';
|
||||
```
|
||||
|
||||
A dark and light theme are provided, one of these classes (or a custom theme) must be attached at any point above your components in the HTML tree. To cover the entire web page you might attach the class to the `body` component:
|
||||
|
||||
```html
|
||||
<body classname="dockview-theme-dark">
|
||||
...
|
||||
</body>
|
||||
<body classname="dockview-theme-light">
|
||||
...
|
||||
</body>
|
||||
```
|
||||
|
||||
There are 4 components you may want to use:
|
||||
|
||||
Splitview
|
||||
|
||||
<div
|
||||
style={{
|
||||
height: '100px',
|
||||
backgroundColor: 'rgb(30,30,30)',
|
||||
color: 'white',
|
||||
margin: '20px 0px',
|
||||
}}
|
||||
>
|
||||
<SimpleSplitview />
|
||||
</div>
|
||||
|
||||
<div
|
||||
style={{
|
||||
height: '300px',
|
||||
backgroundColor: 'rgb(30,30,30)',
|
||||
color: 'white',
|
||||
margin: '20px 0px',
|
||||
}}
|
||||
>
|
||||
<SimpleGridview />
|
||||
</div>
|
||||
|
||||
<div
|
||||
style={{
|
||||
height: '300px',
|
||||
backgroundColor: 'rgb(30,30,30)',
|
||||
color: 'white',
|
||||
margin: '20px 0px',
|
||||
}}
|
||||
>
|
||||
<SimplePaneview />
|
||||
</div>
|
||||
|
||||
<div
|
||||
style={{
|
||||
height: '300px',
|
||||
backgroundColor: 'rgb(30,30,30)',
|
||||
color: 'white',
|
||||
margin: '20px 0px',
|
||||
}}
|
||||
>
|
||||
<SimpleDockview />
|
||||
</div>
|
||||
|
||||
```tsx
|
||||
import {
|
||||
DockviewReact,
|
||||
DockviewReadyEvent,
|
||||
PanelCollection,
|
||||
IDockviewPanelProps,
|
||||
IDockviewPanelHeaderProps,
|
||||
} from 'dockview';
|
||||
|
||||
const components: PanelCollection<IDockviewPanelProps> = {
|
||||
default: (props: IDockviewPanelProps<{ someProps: string }>) => {
|
||||
return <div>{props.params.someProps}</div>;
|
||||
},
|
||||
};
|
||||
|
||||
const headers: PanelCollection<IDockviewPanelHeaderProps> = {
|
||||
customTab: (props: IDockviewPanelHeaderProps) => {
|
||||
return (
|
||||
<div>
|
||||
<span>{props.api.title}</span>
|
||||
<span onClick={() => props.api.close()}>{'[x]'}</span>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
const Component = () => {
|
||||
const onReady = (event: DockviewReadyEvent) => {
|
||||
event.api.addPanel({
|
||||
id: 'panel1',
|
||||
component: 'default',
|
||||
tabComponent: 'customTab', // optional custom header
|
||||
params: {
|
||||
someProps: 'Hello',
|
||||
},
|
||||
});
|
||||
event.api.addPanel({
|
||||
id: 'panel2',
|
||||
component: 'default',
|
||||
params: {
|
||||
someProps: 'World',
|
||||
},
|
||||
position: { referencePanel: 'panel1', direction: 'below' },
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<DockviewReact
|
||||
components={components}
|
||||
tabComponents={headers} // optional headers renderer
|
||||
onReady={onReady}
|
||||
/>
|
||||
);
|
||||
};
|
||||
```
|
80
build/docs/docs/theme.mdx
Normal file
@ -0,0 +1,80 @@
|
||||
---
|
||||
sidebar_position: 3
|
||||
---
|
||||
|
||||
import { CustomCSSDockview } from '../src/components/dockview/customCss';
|
||||
|
||||
# Theme
|
||||
|
||||
## Introduction
|
||||
|
||||
`dockview` requires some css to work correctly.
|
||||
The css is exported as one file under [`dockview/dict/styles/dockview.css`](https://unpkg.com/browse/dockview@latest/dist/styles/dockview.css)
|
||||
and depending can be imported
|
||||
|
||||
```css
|
||||
@import './node_modules/dockview/dist/styles/dockview.css';
|
||||
```
|
||||
|
||||
## Customizing Theme
|
||||
|
||||
`dockview` supports theming through the use of css properties.
|
||||
You can view the built-in themes at [`dockview/src/theme.scss`](https://github.com/mathuo/dockview/blob/master/packages/dockview/src/theme.scss)
|
||||
and are free to build your own themes based on these css properties.
|
||||
|
||||
| CSS Property | Description |
|
||||
| ---------------------------------------------------- | ----------- |
|
||||
| --dv-paneview-active-outline-color | |
|
||||
| --dv-tabs-and-actions-container-font-size | |
|
||||
| --dv-tabs-and-actions-container-height | |
|
||||
| --dv-tab-close-icon | |
|
||||
| --dv-drag-over-background-color | |
|
||||
| --dv-drag-over-border-color | |
|
||||
| --dv-tabs-container-scrollbar-color | |
|
||||
| | |
|
||||
| --dv-group-view-background-color | |
|
||||
| | |
|
||||
| --dv-tabs-and-actions-container-background-color | |
|
||||
| | |
|
||||
| --dv-activegroup-visiblepanel-tab-background-color | |
|
||||
| --dv-activegroup-hiddenpanel-tab-background-color | |
|
||||
| --dv-inactivegroup-visiblepanel-tab-background-color | |
|
||||
| --dv-inactivegroup-hiddenpanel-tab-background-color | |
|
||||
| --dv-tab-divider-color | |
|
||||
| | |
|
||||
| --dv-activegroup-visiblepanel-tab-color | |
|
||||
| --dv-activegroup-hiddenpanel-tab-color | |
|
||||
| --dv-inactivegroup-visiblepanel-tab-color | |
|
||||
| --dv-inactivegroup-hiddenpanel-tab-color | |
|
||||
| | |
|
||||
| --dv-separator-border | |
|
||||
| --dv-paneview-header-border-color | |
|
||||
|
||||
You can further customise the theme through adjusting class properties but this is up you.
|
||||
As an example if you wanted to add a bottom border to the tab container for an active group in the `DockviewReact` component you could write:
|
||||
|
||||
```css
|
||||
.groupview {
|
||||
&.active-group {
|
||||
> .tabs-and-actions-container {
|
||||
border-bottom: 2px solid var(--dv-activegroup-visiblepanel-tab-background-color);
|
||||
}
|
||||
}
|
||||
&.inactive-group {
|
||||
> .tabs-and-actions-container {
|
||||
border-bottom: 2px solid var(--dv-inactivegroup-visiblepanel-tab-background-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<div
|
||||
style={{
|
||||
height: '300px',
|
||||
backgroundColor: 'rgb(30,30,30)',
|
||||
color: 'white',
|
||||
margin: '20px 0px',
|
||||
}}
|
||||
>
|
||||
<CustomCSSDockview />
|
||||
</div>
|
170
build/docs/docusaurus.config.js
Normal file
@ -0,0 +1,170 @@
|
||||
// @ts-check
|
||||
// Note: type annotations allow type checking and IDEs autocompletion
|
||||
|
||||
const lightCodeTheme = require('prism-react-renderer/themes/github');
|
||||
const darkCodeTheme = require('prism-react-renderer/themes/dracula');
|
||||
|
||||
const path = require('path');
|
||||
|
||||
console.log(`isCI: ${process.env.CI}`);
|
||||
|
||||
/** @type {import('@docusaurus/types').Config} */
|
||||
const config = {
|
||||
title: 'Dockview',
|
||||
tagline: 'Zero dependency layout manager for React',
|
||||
url: 'https://your-docusaurus-test-site.com',
|
||||
baseUrl: process.env.CI ? `/` : '/',
|
||||
onBrokenLinks: 'throw',
|
||||
onBrokenMarkdownLinks: 'warn',
|
||||
favicon: 'img/favicon.ico',
|
||||
|
||||
// GitHub pages deployment config.
|
||||
// If you aren't using GitHub pages, you don't need these.
|
||||
organizationName: 'mathuo', // Usually your GitHub org/user name.
|
||||
projectName: 'dockview', // Usually your repo name.
|
||||
|
||||
// Even if you don't use internalization, you can use this field to set useful
|
||||
// metadata like html lang. For example, if your site is Chinese, you may want
|
||||
// to replace "en" with "zh-Hans".
|
||||
i18n: {
|
||||
defaultLocale: 'en',
|
||||
locales: ['en'],
|
||||
},
|
||||
plugins: [
|
||||
'docusaurus-plugin-sass',
|
||||
(context, options) => {
|
||||
return {
|
||||
name: 'webpack',
|
||||
configureWebpack: (config, isServer, utils) => {
|
||||
return {
|
||||
// externals: ['react', 'react-dom'],
|
||||
devtool: 'source-map',
|
||||
resolve: {
|
||||
alias: {
|
||||
react: path.join(
|
||||
__dirname,
|
||||
'node_modules',
|
||||
'react'
|
||||
),
|
||||
'react-dom': path.join(
|
||||
__dirname,
|
||||
'node_modules',
|
||||
'react-dom'
|
||||
),
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
},
|
||||
],
|
||||
presets: [
|
||||
[
|
||||
'classic',
|
||||
/** @type {import('@docusaurus/preset-classic').Options} */
|
||||
({
|
||||
docs: {
|
||||
sidebarPath: require.resolve('./sidebars.js'),
|
||||
// Please change this to your repo.
|
||||
// Remove this to remove the "edit this page" links.
|
||||
editUrl:
|
||||
'https://github.com/facebook/docusaurus/tree/main/packages/create-docusaurus/templates/shared/',
|
||||
},
|
||||
blog: {
|
||||
showReadingTime: true,
|
||||
// Please change this to your repo.
|
||||
// Remove this to remove the "edit this page" links.
|
||||
editUrl:
|
||||
'https://github.com/facebook/docusaurus/tree/main/packages/create-docusaurus/templates/shared/',
|
||||
},
|
||||
theme: {
|
||||
customCss: require.resolve('./src/css/custom.css'),
|
||||
},
|
||||
}),
|
||||
],
|
||||
],
|
||||
|
||||
themeConfig:
|
||||
/** @type {import('@docusaurus/preset-classic').ThemeConfig} */
|
||||
({
|
||||
navbar: {
|
||||
title: 'Dockview',
|
||||
logo: {
|
||||
alt: 'My Site Logo',
|
||||
src: 'img/logo.svg',
|
||||
},
|
||||
items: [
|
||||
{
|
||||
type: 'doc',
|
||||
docId: 'index',
|
||||
position: 'left',
|
||||
label: 'Docs',
|
||||
},
|
||||
{ to: '/blog', label: 'Blog', position: 'left' },
|
||||
{
|
||||
href: 'https://github.com/mathuo/dockview',
|
||||
label: 'GitHub',
|
||||
position: 'right',
|
||||
},
|
||||
],
|
||||
},
|
||||
footer: {
|
||||
style: 'dark',
|
||||
links: [
|
||||
{
|
||||
title: 'Learn',
|
||||
items: [
|
||||
{
|
||||
label: 'Docs',
|
||||
to: '/docs',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Community',
|
||||
items: [
|
||||
{
|
||||
label: 'Stack Overflow',
|
||||
href: 'https://stackoverflow.com/questions/tagged/dockview',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'More',
|
||||
items: [
|
||||
{
|
||||
label: 'Blog',
|
||||
to: '/blog',
|
||||
},
|
||||
{
|
||||
label: 'GitHub',
|
||||
href: 'https://github.com/mathuo/dockview',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
copyright: `Copyright © ${new Date().getFullYear()} Dockview, Inc. Built with Docusaurus.`,
|
||||
},
|
||||
prism: {
|
||||
theme: lightCodeTheme,
|
||||
darkTheme: darkCodeTheme,
|
||||
additionalLanguages: ['java', 'markdown', 'latex'],
|
||||
magicComments: [
|
||||
{
|
||||
className: 'theme-code-block-highlighted-line',
|
||||
line: 'highlight-next-line',
|
||||
block: {
|
||||
start: 'highlight-start',
|
||||
end: 'highlight-end',
|
||||
},
|
||||
},
|
||||
{
|
||||
className: 'code-block-error-line',
|
||||
line: 'This will error',
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
};
|
||||
|
||||
module.exports = config;
|
27
build/docs/jsexamples/dockview.html
Normal file
@ -0,0 +1,27 @@
|
||||
<!-- <!DOCTYPE html> -->
|
||||
<html>
|
||||
<head>
|
||||
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
|
||||
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
|
||||
<script crossorigin src="https://unpkg.com/dockview@latest/dist/dockview.js"></script>
|
||||
<link rel="stylesheet" href="https://unpkg.com/browse/dockview@latest/dist/styles/dockview.css">
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#root {
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
background-color: grey;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script>
|
||||
const root = document.getElementById("root")
|
||||
const dockviewComponent = new dockview.DockviewComponent(root, {})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
54
build/docs/package.json
Normal file
@ -0,0 +1,54 @@
|
||||
{
|
||||
"name": "dockview-docs",
|
||||
"version": "1.4.2",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"docusaurus": "docusaurus",
|
||||
"start": "docusaurus start",
|
||||
"build": "docusaurus build",
|
||||
"swizzle": "docusaurus swizzle",
|
||||
"deploy": "docusaurus deploy",
|
||||
"clear": "docusaurus clear",
|
||||
"serve": "docusaurus serve",
|
||||
"write-translations": "docusaurus write-translations",
|
||||
"write-heading-ids": "docusaurus write-heading-ids",
|
||||
"typecheck": "tsc",
|
||||
"deploy-docs": "node scripts/package-docs.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@docusaurus/core": "2.0.0-beta.20",
|
||||
"@docusaurus/preset-classic": "2.0.0-beta.20",
|
||||
"@mdx-js/react": "^1.6.22",
|
||||
"clsx": "^1.1.1",
|
||||
"dockview": "^1.4.2",
|
||||
"prism-react-renderer": "^1.3.1",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"recoil": "^0.7.3-alpha.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@docusaurus/module-type-aliases": "2.0.0-beta.20",
|
||||
"@tsconfig/docusaurus": "^1.0.5",
|
||||
"docusaurus-plugin-sass": "^0.2.2",
|
||||
"fs-extra": "^10.1.0",
|
||||
"install": "^0.13.0",
|
||||
"sass": "^1.52.1",
|
||||
"typescript": "^4.6.4"
|
||||
},
|
||||
"resolutions": {
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2"
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
">0.5%",
|
||||
"not dead",
|
||||
"not op_mini all"
|
||||
],
|
||||
"development": [
|
||||
"last 1 chrome version",
|
||||
"last 1 firefox version",
|
||||
"last 1 safari version"
|
||||
]
|
||||
}
|
||||
}
|
8
build/docs/scripts/package-docs.js
Normal file
@ -0,0 +1,8 @@
|
||||
const fs = require('fs-extra');
|
||||
const path = require('path');
|
||||
|
||||
const output = path.join(__dirname, '../../build');
|
||||
|
||||
const docsDir = path.join(__dirname, '../build');
|
||||
|
||||
fs.copySync(docsDir, path.join(output));
|
31
build/docs/sidebars.js
Normal file
@ -0,0 +1,31 @@
|
||||
/**
|
||||
* Creating a sidebar enables you to:
|
||||
- create an ordered group of docs
|
||||
- render a sidebar for each doc of that group
|
||||
- provide next/previous navigation
|
||||
|
||||
The sidebars can be generated from the filesystem, or explicitly defined here.
|
||||
|
||||
Create as many sidebars as you want.
|
||||
*/
|
||||
|
||||
// @ts-check
|
||||
|
||||
/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */
|
||||
const sidebars = {
|
||||
// By default, Docusaurus generates a sidebar from the docs folder structure
|
||||
tutorialSidebar: [{type: 'autogenerated', dirName: '.'}],
|
||||
|
||||
// But you can create a sidebar manually
|
||||
/*
|
||||
tutorialSidebar: [
|
||||
{
|
||||
type: 'category',
|
||||
label: 'Tutorial',
|
||||
items: ['hello'],
|
||||
},
|
||||
],
|
||||
*/
|
||||
};
|
||||
|
||||
module.exports = sidebars;
|
70
build/docs/src/components/HomepageFeatures/index.tsx
Normal file
@ -0,0 +1,70 @@
|
||||
import React from 'react';
|
||||
import clsx from 'clsx';
|
||||
import styles from './styles.module.css';
|
||||
|
||||
type FeatureItem = {
|
||||
title: string;
|
||||
Svg: React.ComponentType<React.ComponentProps<'svg'>>;
|
||||
description: JSX.Element;
|
||||
};
|
||||
|
||||
const FeatureList: FeatureItem[] = [
|
||||
{
|
||||
title: 'Easy to Use',
|
||||
Svg: require('@site/static/img/undraw_docusaurus_mountain.svg').default,
|
||||
description: (
|
||||
<>
|
||||
Docusaurus was designed from the ground up to be easily installed and
|
||||
used to get your website up and running quickly.
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: 'Focus on What Matters',
|
||||
Svg: require('@site/static/img/undraw_docusaurus_tree.svg').default,
|
||||
description: (
|
||||
<>
|
||||
Docusaurus lets you focus on your docs, and we'll do the chores. Go
|
||||
ahead and move your docs into the <code>docs</code> directory.
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: 'Powered by React',
|
||||
Svg: require('@site/static/img/undraw_docusaurus_react.svg').default,
|
||||
description: (
|
||||
<>
|
||||
Extend or customize your website layout by reusing React. Docusaurus can
|
||||
be extended while reusing the same header and footer.
|
||||
</>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
function Feature({title, Svg, description}: FeatureItem) {
|
||||
return (
|
||||
<div className={clsx('col col--4')}>
|
||||
<div className="text--center">
|
||||
<Svg className={styles.featureSvg} role="img" />
|
||||
</div>
|
||||
<div className="text--center padding-horiz--md">
|
||||
<h3>{title}</h3>
|
||||
<p>{description}</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default function HomepageFeatures(): JSX.Element {
|
||||
return (
|
||||
<section className={styles.features}>
|
||||
<div className="container">
|
||||
<div className="row">
|
||||
{FeatureList.map((props, idx) => (
|
||||
<Feature key={idx} {...props} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
11
build/docs/src/components/HomepageFeatures/styles.module.css
Normal file
@ -0,0 +1,11 @@
|
||||
.features {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 2rem 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.featureSvg {
|
||||
height: 200px;
|
||||
width: 200px;
|
||||
}
|
27
build/docs/src/components/console/console.scss
Normal file
@ -0,0 +1,27 @@
|
||||
.console-container {
|
||||
background-color: black;
|
||||
color: white;
|
||||
padding-left: 8px;
|
||||
max-height: 200px;
|
||||
overflow-y: scroll;
|
||||
overflow-x: auto;
|
||||
|
||||
.console-line {
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
font-size: 13px;
|
||||
border-bottom: 1px solid rgb(30, 30, 30);
|
||||
display: flex;
|
||||
padding-left: 4px;
|
||||
|
||||
.console-line-timestamp {
|
||||
color: lightgray;
|
||||
padding-right: 4px;
|
||||
}
|
||||
|
||||
.console-line-text {
|
||||
padding: 0px 4px;
|
||||
flex-grow: 1;
|
||||
}
|
||||
}
|
||||
}
|
52
build/docs/src/components/console/console.tsx
Normal file
@ -0,0 +1,52 @@
|
||||
import * as React from 'react';
|
||||
import './console.scss';
|
||||
|
||||
const formatTime = (now: Date) => {
|
||||
const pad = (x: number) => (x < 10 ? `0${x}` : `${x}`);
|
||||
|
||||
return `${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(
|
||||
now.getSeconds()
|
||||
)}.${now.getMilliseconds()}`;
|
||||
};
|
||||
|
||||
export interface Line {
|
||||
timestamp: Date;
|
||||
text: string;
|
||||
css?: React.CSSProperties;
|
||||
}
|
||||
|
||||
export interface IConsoleProps {
|
||||
lines: Line[];
|
||||
}
|
||||
|
||||
export const Console = (props: IConsoleProps) => {
|
||||
const ref = React.useRef<HTMLDivElement>();
|
||||
|
||||
React.useLayoutEffect(() => {
|
||||
if (!ref.current) {
|
||||
return;
|
||||
}
|
||||
|
||||
ref.current.scrollTop = Math.max(
|
||||
0,
|
||||
ref.current.scrollHeight - ref.current.clientHeight
|
||||
);
|
||||
}, [props.lines]);
|
||||
|
||||
return (
|
||||
<div ref={ref} className="console-container">
|
||||
{props.lines.map((line, i) => {
|
||||
return (
|
||||
<div key={i} className="console-line">
|
||||
<span className="console-line-timestamp">
|
||||
{formatTime(line.timestamp)}
|
||||
</span>
|
||||
<span className="console-line-text" style={line.css}>
|
||||
{line.text}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
};
|
115
build/docs/src/components/dockview/contextMenu.tsx
Normal file
@ -0,0 +1,115 @@
|
||||
import {
|
||||
DockviewReact,
|
||||
DockviewReadyEvent,
|
||||
IDockviewPanelHeaderProps,
|
||||
IDockviewPanelProps,
|
||||
} from 'dockview';
|
||||
import * as React from 'react';
|
||||
|
||||
//
|
||||
const components = {
|
||||
default: (props: IDockviewPanelProps<{ title: string }>) => {
|
||||
return <div style={{ padding: '20px' }}>{props.params.title}</div>;
|
||||
},
|
||||
};
|
||||
|
||||
const DefaultTab = (props: IDockviewPanelHeaderProps) => {
|
||||
const [active, setActive] = React.useState<boolean>(props.api.isActive);
|
||||
const [groupActive, setGroupActive] = React.useState<boolean>(
|
||||
props.api.isGroupActive
|
||||
);
|
||||
|
||||
React.useEffect(() => {
|
||||
const disposable1 = props.api.onDidActiveChange((e) => {
|
||||
setActive(e.isActive);
|
||||
});
|
||||
const disposable2 = props.containerApi.onDidActiveGroupChange((e) => {
|
||||
setGroupActive(props.api.isGroupActive);
|
||||
});
|
||||
|
||||
return () => {
|
||||
disposable1.dispose();
|
||||
disposable2.dispose();
|
||||
};
|
||||
}, [props.api]);
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
padding: '0px 8px',
|
||||
alignItems: 'center',
|
||||
height: '100%',
|
||||
}}
|
||||
>
|
||||
<span style={{ padding: '0px 8px', flexGrow: 1 }}>
|
||||
{props.api.title}
|
||||
</span>
|
||||
<span
|
||||
className=""
|
||||
onClick={() => props.api.setActive()}
|
||||
style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
paddingRight: '8px',
|
||||
}}
|
||||
>
|
||||
{'✕'}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const tabComponents = {
|
||||
default: DefaultTab,
|
||||
};
|
||||
|
||||
export const ContextMenuDockview = () => {
|
||||
const onReady = (event: DockviewReadyEvent) => {
|
||||
event.api.addPanel({
|
||||
id: 'panel_1',
|
||||
component: 'default',
|
||||
tabComponent: 'default',
|
||||
params: {
|
||||
title: 'Panel 1',
|
||||
},
|
||||
});
|
||||
|
||||
event.api.addPanel({
|
||||
id: 'panel_2',
|
||||
component: 'default',
|
||||
tabComponent: 'default',
|
||||
params: {
|
||||
title: 'Panel 2',
|
||||
},
|
||||
});
|
||||
|
||||
event.api.addPanel({
|
||||
id: 'panel_3',
|
||||
component: 'default',
|
||||
tabComponent: 'default',
|
||||
params: {
|
||||
title: 'Panel 3',
|
||||
},
|
||||
});
|
||||
|
||||
event.api.addPanel({
|
||||
id: 'panel_4',
|
||||
component: 'default',
|
||||
tabComponent: 'default',
|
||||
params: {
|
||||
title: 'Panel 4',
|
||||
},
|
||||
position: { referencePanel: 'panel_1', direction: 'right' },
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<DockviewReact
|
||||
components={components}
|
||||
tabComponents={tabComponents}
|
||||
onReady={onReady}
|
||||
className="dockview-theme-dark"
|
||||
/>
|
||||
);
|
||||
};
|
58
build/docs/src/components/dockview/customCss.tsx
Normal file
@ -0,0 +1,58 @@
|
||||
import {
|
||||
DockviewReact,
|
||||
DockviewReadyEvent,
|
||||
IDockviewPanelProps,
|
||||
} from 'dockview';
|
||||
import * as React from 'react';
|
||||
|
||||
//
|
||||
const components = {
|
||||
default: (props: IDockviewPanelProps<{ title: string }>) => {
|
||||
return <div style={{ padding: '20px' }}>{props.params.title}</div>;
|
||||
},
|
||||
};
|
||||
|
||||
export const CustomCSSDockview = () => {
|
||||
const onReady = (event: DockviewReadyEvent) => {
|
||||
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',
|
||||
},
|
||||
});
|
||||
|
||||
event.api.addPanel({
|
||||
id: 'panel_4',
|
||||
component: 'default',
|
||||
params: {
|
||||
title: 'Panel 4',
|
||||
},
|
||||
position: { referencePanel: 'panel_1', direction: 'right' },
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<DockviewReact
|
||||
components={components}
|
||||
onReady={onReady}
|
||||
className="dockview-theme-vs"
|
||||
/>
|
||||
);
|
||||
};
|
105
build/docs/src/components/dockview/dnd.tsx
Normal file
@ -0,0 +1,105 @@
|
||||
import {
|
||||
DockviewDndOverlayEvent,
|
||||
DockviewDropEvent,
|
||||
DockviewReact,
|
||||
DockviewReadyEvent,
|
||||
IDockviewPanelProps,
|
||||
} from 'dockview';
|
||||
import * as React from 'react';
|
||||
|
||||
const components = {
|
||||
default: (props: IDockviewPanelProps<{ title: string }>) => {
|
||||
return (
|
||||
<div style={{ padding: '20px' }}>
|
||||
<div>{props.params.title}</div>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
export const DndDockview = (props: { renderVisibleOnly: boolean }) => {
|
||||
const onReady = (event: DockviewReadyEvent) => {
|
||||
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',
|
||||
},
|
||||
});
|
||||
|
||||
event.api.addPanel({
|
||||
id: 'panel_4',
|
||||
component: 'default',
|
||||
params: {
|
||||
title: 'Panel 4',
|
||||
},
|
||||
position: { referencePanel: 'panel_1', direction: 'right' },
|
||||
});
|
||||
};
|
||||
|
||||
const onDidDrop = (event: DockviewDropEvent) => {
|
||||
const { group } = event;
|
||||
|
||||
event.api.addPanel({
|
||||
id: 'test',
|
||||
component: 'default',
|
||||
position: {
|
||||
referencePanel: group.activePanel.id,
|
||||
direction: 'within',
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const showDndOverlay = (event: DockviewDndOverlayEvent) => {
|
||||
return true;
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
style={{
|
||||
backgroundColor: 'orange',
|
||||
padding: '0px 8px',
|
||||
borderRadius: '4px',
|
||||
width: '100px',
|
||||
cursor: 'pointer',
|
||||
}}
|
||||
draggable={true}
|
||||
>
|
||||
Drag me
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
height: '300px',
|
||||
backgroundColor: 'rgb(30,30,30)',
|
||||
color: 'white',
|
||||
margin: '20px 0px',
|
||||
}}
|
||||
>
|
||||
<DockviewReact
|
||||
components={components}
|
||||
onReady={onReady}
|
||||
className="dockview-theme-dark"
|
||||
onDidDrop={onDidDrop}
|
||||
showDndOverlay={showDndOverlay}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
342
build/docs/src/components/dockview/events.tsx
Normal file
@ -0,0 +1,342 @@
|
||||
import {
|
||||
Orientation,
|
||||
DockviewReact,
|
||||
DockviewReadyEvent,
|
||||
DockviewApi,
|
||||
IDockviewPanelProps,
|
||||
} from 'dockview';
|
||||
import * as React from 'react';
|
||||
import { Console, Line } from '../console/console';
|
||||
|
||||
const components = {
|
||||
default: (props: IDockviewPanelProps<{ title: string }>) => {
|
||||
return <div style={{ padding: '20px' }}>{props.params.title}</div>;
|
||||
},
|
||||
};
|
||||
|
||||
export const EventsDockview = () => {
|
||||
const [lines, setLines] = React.useState<Line[]>([]);
|
||||
const [checked, setChecked] = React.useState<boolean>(false);
|
||||
|
||||
const [api, setApi] = React.useState<DockviewApi | undefined>();
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!api) {
|
||||
return () => {
|
||||
//noop
|
||||
};
|
||||
}
|
||||
|
||||
const disposables = [
|
||||
api.onDidAddPanel((panel) => {
|
||||
setLines((lines) => [
|
||||
...lines,
|
||||
{
|
||||
timestamp: new Date(),
|
||||
text: `onDidAddPanel: ${panel.id}`,
|
||||
},
|
||||
]);
|
||||
}),
|
||||
api.onDidRemovePanel((panel) => {
|
||||
setLines((lines) => [
|
||||
...lines,
|
||||
{
|
||||
timestamp: new Date(),
|
||||
text: `onDidRemovePanel: ${panel.id}`,
|
||||
},
|
||||
]);
|
||||
}),
|
||||
api.onDidActivePanelChange((panel) => {
|
||||
setLines((lines) => [
|
||||
...lines,
|
||||
{
|
||||
timestamp: new Date(),
|
||||
text: `onDidActivePanelChange: ${panel?.id}`,
|
||||
},
|
||||
]);
|
||||
}),
|
||||
api.onDidAddGroup((panel) => {
|
||||
setLines((lines) => [
|
||||
...lines,
|
||||
{
|
||||
timestamp: new Date(),
|
||||
text: `onDidAddGroup: ${panel.id}`,
|
||||
},
|
||||
]);
|
||||
}),
|
||||
api.onDidRemoveGroup((panel) => {
|
||||
setLines((lines) => [
|
||||
...lines,
|
||||
{
|
||||
timestamp: new Date(),
|
||||
text: `onDidRemoveGroup: ${panel.id}`,
|
||||
},
|
||||
]);
|
||||
}),
|
||||
api.onDidActiveGroupChange((panel) => {
|
||||
setLines((lines) => [
|
||||
...lines,
|
||||
{
|
||||
timestamp: new Date(),
|
||||
text: `onDidActiveGroupChange: ${panel?.id}`,
|
||||
},
|
||||
]);
|
||||
}),
|
||||
api.onDidLayoutChange((panel) => {
|
||||
setLines((lines) => [
|
||||
...lines,
|
||||
{ timestamp: new Date(), text: `onDidLayoutChange` },
|
||||
]);
|
||||
}),
|
||||
api.onDidLayoutFromJSON((panel) => {
|
||||
setLines((lines) => [
|
||||
...lines,
|
||||
{ timestamp: new Date(), text: `onDidLayoutFromJSON` },
|
||||
]);
|
||||
}),
|
||||
];
|
||||
|
||||
return () => {
|
||||
disposables.forEach((disposable) => disposable.dispose());
|
||||
};
|
||||
}, [api]);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!api) {
|
||||
return;
|
||||
}
|
||||
|
||||
setLines((lines) => [
|
||||
...lines,
|
||||
{
|
||||
timestamp: new Date(),
|
||||
text: `Rebuilding view fromJSON:${checked}`,
|
||||
css: { color: 'yellow', backgroundColor: 'grey' },
|
||||
},
|
||||
]);
|
||||
|
||||
if (checked) {
|
||||
api.fromJSON({
|
||||
grid: {
|
||||
root: {
|
||||
type: 'branch',
|
||||
data: [
|
||||
{
|
||||
type: 'leaf',
|
||||
data: {
|
||||
views: ['panel_1', 'panel_2', 'panel_3'],
|
||||
activeView: 'panel_3',
|
||||
id: '77',
|
||||
},
|
||||
size: 262,
|
||||
},
|
||||
{
|
||||
type: 'branch',
|
||||
data: [
|
||||
{
|
||||
type: 'leaf',
|
||||
data: {
|
||||
views: ['panel_5'],
|
||||
activeView: 'panel_5',
|
||||
id: '79',
|
||||
},
|
||||
size: 100,
|
||||
},
|
||||
{
|
||||
type: 'leaf',
|
||||
data: {
|
||||
views: ['panel_6', 'panel_8'],
|
||||
activeView: 'panel_8',
|
||||
id: '80',
|
||||
},
|
||||
size: 100,
|
||||
},
|
||||
{
|
||||
type: 'leaf',
|
||||
data: {
|
||||
views: ['panel_7'],
|
||||
activeView: 'panel_7',
|
||||
id: '81',
|
||||
},
|
||||
size: 100,
|
||||
},
|
||||
],
|
||||
size: 262,
|
||||
},
|
||||
{
|
||||
type: 'leaf',
|
||||
data: {
|
||||
views: ['panel_4'],
|
||||
activeView: 'panel_4',
|
||||
id: '78',
|
||||
},
|
||||
size: 263.75,
|
||||
},
|
||||
],
|
||||
size: 300,
|
||||
},
|
||||
width: 787.75,
|
||||
height: 300,
|
||||
orientation: Orientation.HORIZONTAL,
|
||||
},
|
||||
panels: {
|
||||
panel_1: {
|
||||
id: 'panel_1',
|
||||
view: { content: { id: 'default' } },
|
||||
params: { title: 'Panel 1' },
|
||||
title: 'panel_1',
|
||||
},
|
||||
panel_2: {
|
||||
id: 'panel_2',
|
||||
view: { content: { id: 'default' } },
|
||||
params: { title: 'Panel 2' },
|
||||
title: 'panel_2',
|
||||
},
|
||||
panel_3: {
|
||||
id: 'panel_3',
|
||||
view: { content: { id: 'default' } },
|
||||
params: { title: 'Panel 3' },
|
||||
title: 'panel_3',
|
||||
},
|
||||
panel_4: {
|
||||
id: 'panel_4',
|
||||
view: { content: { id: 'default' } },
|
||||
params: { title: 'Panel 4' },
|
||||
title: 'panel_4',
|
||||
},
|
||||
panel_5: {
|
||||
id: 'panel_5',
|
||||
view: { content: { id: 'default' } },
|
||||
params: { title: 'Panel 5' },
|
||||
title: 'panel_5',
|
||||
},
|
||||
panel_6: {
|
||||
id: 'panel_6',
|
||||
view: { content: { id: 'default' } },
|
||||
params: { title: 'Panel 6' },
|
||||
title: 'panel_6',
|
||||
},
|
||||
panel_8: {
|
||||
id: 'panel_8',
|
||||
view: { content: { id: 'default' } },
|
||||
params: { title: 'Panel 8' },
|
||||
title: 'panel_8',
|
||||
},
|
||||
panel_7: {
|
||||
id: 'panel_7',
|
||||
view: { content: { id: 'default' } },
|
||||
params: { title: 'Panel 7' },
|
||||
title: 'panel_7',
|
||||
},
|
||||
},
|
||||
activeGroup: '80',
|
||||
options: {},
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
api.clear();
|
||||
|
||||
api.addPanel({
|
||||
id: 'panel_1',
|
||||
component: 'default',
|
||||
params: {
|
||||
title: 'Panel 1',
|
||||
},
|
||||
});
|
||||
|
||||
api.addPanel({
|
||||
id: 'panel_2',
|
||||
component: 'default',
|
||||
params: {
|
||||
title: 'Panel 2',
|
||||
},
|
||||
});
|
||||
|
||||
api.addPanel({
|
||||
id: 'panel_3',
|
||||
component: 'default',
|
||||
params: {
|
||||
title: 'Panel 3',
|
||||
},
|
||||
});
|
||||
|
||||
api.addPanel({
|
||||
id: 'panel_4',
|
||||
component: 'default',
|
||||
params: {
|
||||
title: 'Panel 4',
|
||||
},
|
||||
position: { referencePanel: 'panel_1', direction: 'right' },
|
||||
});
|
||||
|
||||
api.addPanel({
|
||||
id: 'panel_5',
|
||||
component: 'default',
|
||||
params: {
|
||||
title: 'Panel 5',
|
||||
},
|
||||
position: { referencePanel: 'panel_3', direction: 'right' },
|
||||
});
|
||||
|
||||
api.addPanel({
|
||||
id: 'panel_6',
|
||||
component: 'default',
|
||||
params: {
|
||||
title: 'Panel 6',
|
||||
},
|
||||
position: { referencePanel: 'panel_5', direction: 'below' },
|
||||
});
|
||||
|
||||
api.addPanel({
|
||||
id: 'panel_7',
|
||||
component: 'default',
|
||||
params: {
|
||||
title: 'Panel 7',
|
||||
},
|
||||
position: { referencePanel: 'panel_6', direction: 'below' },
|
||||
});
|
||||
|
||||
api.addPanel({
|
||||
id: 'panel_8',
|
||||
component: 'default',
|
||||
params: {
|
||||
title: 'Panel 8',
|
||||
},
|
||||
position: { referencePanel: 'panel_6', direction: 'within' },
|
||||
});
|
||||
}, [api, checked]);
|
||||
|
||||
const onReady = (event: DockviewReadyEvent) => {
|
||||
setApi(event.api);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={checked}
|
||||
onChange={(e) => setChecked(e.target.checked)}
|
||||
/>
|
||||
<span>{'fromJSON'}</span>
|
||||
</label>
|
||||
<div
|
||||
style={{
|
||||
height: '300px',
|
||||
backgroundColor: 'rgb(30,30,30)',
|
||||
color: 'white',
|
||||
margin: '20px 0px',
|
||||
}}
|
||||
>
|
||||
<DockviewReact
|
||||
components={components}
|
||||
onReady={onReady}
|
||||
className="dockview-theme-dark"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<Console lines={lines} />
|
||||
</>
|
||||
);
|
||||
};
|
158
build/docs/src/components/dockview/rendering.tsx
Normal file
@ -0,0 +1,158 @@
|
||||
import {
|
||||
DockviewReact,
|
||||
DockviewReadyEvent,
|
||||
IDockviewPanelProps,
|
||||
PanelApi,
|
||||
} from 'dockview';
|
||||
import * as React from 'react';
|
||||
|
||||
import { atom, useRecoilState, useRecoilValue } from 'recoil';
|
||||
|
||||
const renderVisibleComponentsOnlyAtom = atom<boolean>({
|
||||
key: 'renderVisibleComponentsOnlyAtom',
|
||||
default: false,
|
||||
});
|
||||
|
||||
function RenderWhenVisible<
|
||||
T extends { api: Pick<PanelApi, 'isVisible' | 'onDidVisibilityChange'> }
|
||||
>(component: React.FunctionComponent<T>) {
|
||||
const HigherOrderComponent = (props: T) => {
|
||||
const [visible, setVisible] = React.useState<boolean>(
|
||||
props.api.isVisible
|
||||
);
|
||||
|
||||
const render = useRecoilValue(renderVisibleComponentsOnlyAtom);
|
||||
|
||||
React.useEffect(() => {
|
||||
const disposable = props.api.onDidVisibilityChange((event) =>
|
||||
setVisible(event.isVisible)
|
||||
);
|
||||
|
||||
return () => {
|
||||
disposable.dispose();
|
||||
};
|
||||
}, [props.api]);
|
||||
|
||||
if (!visible && render) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return React.createElement(component, props);
|
||||
};
|
||||
return HigherOrderComponent;
|
||||
}
|
||||
|
||||
const formatLine = (line: string) => {
|
||||
const now = new Date();
|
||||
|
||||
const pad = (x: number) => (x < 10 ? `0${x}` : `${x}`);
|
||||
|
||||
const time = `${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(
|
||||
now.getSeconds()
|
||||
)}`;
|
||||
|
||||
return `[${time}] ${line}`;
|
||||
};
|
||||
|
||||
const components = {
|
||||
default: RenderWhenVisible(
|
||||
(props: IDockviewPanelProps<{ title: string }>) => {
|
||||
const [lines, setLines] = React.useState<string[]>([
|
||||
formatLine('Component created'),
|
||||
]);
|
||||
|
||||
React.useEffect(() => {
|
||||
setLines((lines) => [
|
||||
...lines,
|
||||
formatLine('Running task for 5 seconds'),
|
||||
]);
|
||||
const timeout = setTimeout(() => {
|
||||
setLines((lines) => [
|
||||
...lines,
|
||||
formatLine('Task completed'),
|
||||
]);
|
||||
}, 5000);
|
||||
|
||||
return () => {
|
||||
clearTimeout(timeout);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div style={{ padding: '20px' }}>
|
||||
<div>{props.params.title}</div>
|
||||
{lines.map((line, i) => (
|
||||
<div key={i}>{line}</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
),
|
||||
};
|
||||
|
||||
export const RenderingDockview = (props: { renderVisibleOnly: boolean }) => {
|
||||
const [render, setRender] = useRecoilState(renderVisibleComponentsOnlyAtom);
|
||||
|
||||
React.useEffect(
|
||||
() => setRender(props.renderVisibleOnly),
|
||||
[props.renderVisibleOnly]
|
||||
);
|
||||
|
||||
const onReady = (event: DockviewReadyEvent) => {
|
||||
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',
|
||||
},
|
||||
});
|
||||
|
||||
event.api.addPanel({
|
||||
id: 'panel_4',
|
||||
component: 'default',
|
||||
params: {
|
||||
title: 'Panel 4',
|
||||
},
|
||||
position: { referencePanel: 'panel_1', direction: 'right' },
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<DockviewReact
|
||||
components={components}
|
||||
onReady={onReady}
|
||||
className="dockview-theme-dark"
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export const Checkbox = () => {
|
||||
const [render, setRender] = useRecoilState(renderVisibleComponentsOnlyAtom);
|
||||
|
||||
return (
|
||||
<label>
|
||||
Render only when visible
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={render}
|
||||
onChange={(e) => setRender(e.target.checked)}
|
||||
/>
|
||||
</label>
|
||||
);
|
||||
};
|
339
build/docs/src/components/gridview/events.tsx
Normal file
@ -0,0 +1,339 @@
|
||||
import {
|
||||
IGridviewPanelProps,
|
||||
Orientation,
|
||||
GridviewReact,
|
||||
GridviewReadyEvent,
|
||||
GridviewApi,
|
||||
} from 'dockview';
|
||||
import * as React from 'react';
|
||||
import { Console, Line } from '../console/console';
|
||||
|
||||
const components = {
|
||||
default: (props: IGridviewPanelProps<{ title: string }>) => {
|
||||
return <div style={{ padding: '20px' }}>{props.params.title}</div>;
|
||||
},
|
||||
};
|
||||
|
||||
export const EventsGridview = () => {
|
||||
const [lines, setLines] = React.useState<Line[]>([]);
|
||||
const [checked, setChecked] = React.useState<boolean>(false);
|
||||
|
||||
const [api, setApi] = React.useState<GridviewApi | undefined>();
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!api) {
|
||||
return () => {
|
||||
//noop
|
||||
};
|
||||
}
|
||||
|
||||
const disposables = [
|
||||
api.onDidAddPanel((panel) => {
|
||||
setLines((lines) => [
|
||||
...lines,
|
||||
{
|
||||
timestamp: new Date(),
|
||||
text: `onDidAddPanel: ${panel.id}`,
|
||||
},
|
||||
]);
|
||||
}),
|
||||
api.onDidRemovePanel((panel) => {
|
||||
setLines((lines) => [
|
||||
...lines,
|
||||
{
|
||||
timestamp: new Date(),
|
||||
text: `onDidRemovePanel: ${panel.id}`,
|
||||
},
|
||||
]);
|
||||
}),
|
||||
api.onDidActivePanelChange((panel) => {
|
||||
setLines((lines) => [
|
||||
...lines,
|
||||
{
|
||||
timestamp: new Date(),
|
||||
text: `onDidActivePanelChange: ${panel?.id}`,
|
||||
},
|
||||
]);
|
||||
}),
|
||||
api.onDidLayoutChange((panel) => {
|
||||
setLines((lines) => [
|
||||
...lines,
|
||||
{ timestamp: new Date(), text: `onDidLayoutChange` },
|
||||
]);
|
||||
}),
|
||||
api.onDidLayoutFromJSON((panel) => {
|
||||
setLines((lines) => [
|
||||
...lines,
|
||||
{ timestamp: new Date(), text: `onDidLayoutFromJSON` },
|
||||
]);
|
||||
}),
|
||||
];
|
||||
|
||||
return () => {
|
||||
disposables.forEach((disposable) => disposable.dispose());
|
||||
};
|
||||
}, [api]);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!api) {
|
||||
return;
|
||||
}
|
||||
|
||||
setLines((lines) => [
|
||||
...lines,
|
||||
{
|
||||
timestamp: new Date(),
|
||||
text: `Rebuilding view fromJSON:${checked}`,
|
||||
css: { color: 'yellow', backgroundColor: 'grey' },
|
||||
},
|
||||
]);
|
||||
|
||||
if (checked) {
|
||||
api.fromJSON({
|
||||
grid: {
|
||||
root: {
|
||||
type: 'branch',
|
||||
data: [
|
||||
{
|
||||
type: 'branch',
|
||||
data: [
|
||||
{
|
||||
type: 'leaf',
|
||||
data: {
|
||||
id: 'panel_3',
|
||||
component: 'default',
|
||||
params: { title: 'Panel 3' },
|
||||
snap: false,
|
||||
},
|
||||
size: 394,
|
||||
},
|
||||
{
|
||||
type: 'branch',
|
||||
data: [
|
||||
{
|
||||
type: 'leaf',
|
||||
data: {
|
||||
id: 'panel_5',
|
||||
component: 'default',
|
||||
params: {
|
||||
title: 'Panel 5',
|
||||
},
|
||||
snap: false,
|
||||
},
|
||||
size: 50,
|
||||
},
|
||||
{
|
||||
type: 'branch',
|
||||
data: [
|
||||
{
|
||||
type: 'leaf',
|
||||
data: {
|
||||
id: 'panel_6',
|
||||
component:
|
||||
'default',
|
||||
params: {
|
||||
title: 'Panel 6',
|
||||
},
|
||||
minimumWidth: 10,
|
||||
snap: false,
|
||||
},
|
||||
size: 131,
|
||||
},
|
||||
{
|
||||
type: 'leaf',
|
||||
data: {
|
||||
id: 'panel_8',
|
||||
component:
|
||||
'default',
|
||||
params: {
|
||||
title: 'Panel 8',
|
||||
},
|
||||
minimumWidth: 10,
|
||||
snap: false,
|
||||
},
|
||||
size: 131,
|
||||
},
|
||||
{
|
||||
type: 'leaf',
|
||||
data: {
|
||||
id: 'panel_7',
|
||||
component:
|
||||
'default',
|
||||
params: {
|
||||
title: 'Panel 7',
|
||||
},
|
||||
minimumWidth: 10,
|
||||
snap: false,
|
||||
},
|
||||
size: 132,
|
||||
},
|
||||
],
|
||||
size: 50,
|
||||
},
|
||||
],
|
||||
size: 394,
|
||||
},
|
||||
],
|
||||
size: 100,
|
||||
},
|
||||
{
|
||||
type: 'leaf',
|
||||
data: {
|
||||
id: 'panel_2',
|
||||
component: 'default',
|
||||
params: { title: 'Panel 2' },
|
||||
snap: false,
|
||||
},
|
||||
size: 100,
|
||||
},
|
||||
{
|
||||
type: 'branch',
|
||||
data: [
|
||||
{
|
||||
type: 'leaf',
|
||||
data: {
|
||||
id: 'panel_1',
|
||||
component: 'default',
|
||||
params: { title: 'Panel 1' },
|
||||
snap: false,
|
||||
},
|
||||
size: 394,
|
||||
},
|
||||
{
|
||||
type: 'leaf',
|
||||
data: {
|
||||
id: 'panel_4',
|
||||
component: 'default',
|
||||
params: { title: 'Panel 4' },
|
||||
snap: false,
|
||||
},
|
||||
size: 394,
|
||||
},
|
||||
],
|
||||
size: 100,
|
||||
},
|
||||
],
|
||||
size: 788,
|
||||
},
|
||||
width: 788,
|
||||
height: 300,
|
||||
orientation: Orientation.VERTICAL,
|
||||
},
|
||||
activePanel: 'panel_8',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
api.clear();
|
||||
api.orientation = Orientation.VERTICAL;
|
||||
|
||||
api.addPanel({
|
||||
id: 'panel_1',
|
||||
component: 'default',
|
||||
params: {
|
||||
title: 'Panel 1',
|
||||
},
|
||||
});
|
||||
|
||||
api.addPanel({
|
||||
id: 'panel_2',
|
||||
component: 'default',
|
||||
params: {
|
||||
title: 'Panel 2',
|
||||
},
|
||||
});
|
||||
|
||||
api.addPanel({
|
||||
id: 'panel_3',
|
||||
component: 'default',
|
||||
params: {
|
||||
title: 'Panel 3',
|
||||
},
|
||||
});
|
||||
|
||||
console.log('sdf');
|
||||
|
||||
api.addPanel({
|
||||
id: 'panel_4',
|
||||
component: 'default',
|
||||
params: {
|
||||
title: 'Panel 4',
|
||||
},
|
||||
position: { referencePanel: 'panel_1', direction: 'right' },
|
||||
});
|
||||
|
||||
api.addPanel({
|
||||
id: 'panel_5',
|
||||
component: 'default',
|
||||
params: {
|
||||
title: 'Panel 5',
|
||||
},
|
||||
position: { referencePanel: 'panel_3', direction: 'right' },
|
||||
});
|
||||
|
||||
api.addPanel({
|
||||
id: 'panel_6',
|
||||
component: 'default',
|
||||
params: {
|
||||
title: 'Panel 6',
|
||||
},
|
||||
position: { referencePanel: 'panel_5', direction: 'below' },
|
||||
minimumWidth: 10,
|
||||
});
|
||||
|
||||
api.addPanel({
|
||||
id: 'panel_7',
|
||||
component: 'default',
|
||||
params: {
|
||||
title: 'Panel 7',
|
||||
},
|
||||
position: { referencePanel: 'panel_6', direction: 'right' },
|
||||
minimumWidth: 10,
|
||||
});
|
||||
|
||||
api.addPanel({
|
||||
id: 'panel_8',
|
||||
component: 'default',
|
||||
params: {
|
||||
title: 'Panel 8',
|
||||
},
|
||||
position: { referencePanel: 'panel_6', direction: 'right' },
|
||||
minimumWidth: 10,
|
||||
});
|
||||
}, [api, checked]);
|
||||
|
||||
const onReady = (event: GridviewReadyEvent) => {
|
||||
setApi(event.api);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={checked}
|
||||
onChange={(e) => setChecked(e.target.checked)}
|
||||
/>
|
||||
<span>{'fromJSON'}</span>
|
||||
</label>
|
||||
<div
|
||||
style={{
|
||||
height: '300px',
|
||||
backgroundColor: 'rgb(30,30,30)',
|
||||
color: 'white',
|
||||
margin: '20px 0px',
|
||||
}}
|
||||
>
|
||||
<GridviewReact
|
||||
components={components}
|
||||
onReady={onReady}
|
||||
proportionalLayout={false}
|
||||
orientation={Orientation.VERTICAL}
|
||||
className="dockview-theme-dark"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<Console lines={lines} />
|
||||
</>
|
||||
);
|
||||
};
|
2
build/docs/src/components/release.tsx
Normal file
@ -0,0 +1,2 @@
|
||||
import * as React from 'react';
|
||||
const URL = 'https://api.github.com/repos/mathuo/dockview/releases';
|
116
build/docs/src/components/simpleDockview.tsx
Normal file
@ -0,0 +1,116 @@
|
||||
import {
|
||||
DockviewReact,
|
||||
DockviewReadyEvent,
|
||||
IDockviewPanelProps,
|
||||
PanelApi,
|
||||
} from 'dockview';
|
||||
import * as React from 'react';
|
||||
|
||||
const components = {
|
||||
default: (props: IDockviewPanelProps<{ title: string }>) => {
|
||||
return <div style={{ padding: '20px' }}>{props.params.title}</div>;
|
||||
},
|
||||
};
|
||||
|
||||
const RenderWhenVisible = <T,>(
|
||||
props: T & {
|
||||
children: React.FunctionComponent<T>;
|
||||
api: Pick<PanelApi, 'isVisible' | 'onDidVisibilityChange'>;
|
||||
}
|
||||
) => {
|
||||
const [visible, setVisible] = React.useState<boolean>(props.api.isVisible);
|
||||
|
||||
React.useEffect(() => {
|
||||
const disposable = props.api.onDidVisibilityChange((event) =>
|
||||
setVisible(event.isVisible)
|
||||
);
|
||||
|
||||
return () => {
|
||||
disposable.dispose();
|
||||
};
|
||||
}, [props.api]);
|
||||
|
||||
if (!visible) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return React.createElement(props.children, props);
|
||||
};
|
||||
|
||||
export const SimpleDockview = () => {
|
||||
const onReady = (event: DockviewReadyEvent) => {
|
||||
const panel = event.api.addPanel({
|
||||
id: 'panel_1',
|
||||
component: 'default',
|
||||
params: {
|
||||
title: 'Panel 1',
|
||||
},
|
||||
});
|
||||
|
||||
panel.group.locked = true;
|
||||
panel.group.header.hidden = true;
|
||||
|
||||
event.api.addPanel({
|
||||
id: 'panel_2',
|
||||
component: 'default',
|
||||
params: {
|
||||
title: 'Panel 2',
|
||||
},
|
||||
});
|
||||
|
||||
event.api.addPanel({
|
||||
id: 'panel_3',
|
||||
component: 'default',
|
||||
params: {
|
||||
title: 'Panel 3',
|
||||
},
|
||||
});
|
||||
|
||||
event.api.addPanel({
|
||||
id: 'panel_4',
|
||||
component: 'default',
|
||||
params: {
|
||||
title: 'Panel 4',
|
||||
},
|
||||
position: { referencePanel: 'panel_1', direction: 'right' },
|
||||
});
|
||||
|
||||
const panel5 = event.api.addPanel({
|
||||
id: 'panel_5',
|
||||
component: 'default',
|
||||
params: {
|
||||
title: 'Panel 5',
|
||||
},
|
||||
position: { referencePanel: 'panel_3', direction: 'right' },
|
||||
});
|
||||
|
||||
// panel5.group!.model.header.hidden = true;
|
||||
// panel5.group!.model.locked = true;
|
||||
|
||||
event.api.addPanel({
|
||||
id: 'panel_6',
|
||||
component: 'default',
|
||||
params: {
|
||||
title: 'Panel 6',
|
||||
},
|
||||
position: { referencePanel: 'panel_5', direction: 'below' },
|
||||
});
|
||||
|
||||
event.api.addPanel({
|
||||
id: 'panel_7',
|
||||
component: 'default',
|
||||
params: {
|
||||
title: 'Panel 7',
|
||||
},
|
||||
position: { referencePanel: 'panel_6', direction: 'right' },
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<DockviewReact
|
||||
components={components}
|
||||
onReady={onReady}
|
||||
className="dockview-theme-dark"
|
||||
/>
|
||||
);
|
||||
};
|
99
build/docs/src/components/simpleGridview.tsx
Normal file
@ -0,0 +1,99 @@
|
||||
import {
|
||||
IGridviewPanelProps,
|
||||
Orientation,
|
||||
GridviewReact,
|
||||
GridviewReadyEvent,
|
||||
} from 'dockview';
|
||||
import * as React from 'react';
|
||||
|
||||
const components = {
|
||||
default: (props: IGridviewPanelProps<{ title: string }>) => {
|
||||
return <div style={{ padding: '20px' }}>{props.params.title}</div>;
|
||||
},
|
||||
};
|
||||
|
||||
export const SimpleGridview = () => {
|
||||
const onReady = (event: GridviewReadyEvent) => {
|
||||
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',
|
||||
},
|
||||
});
|
||||
|
||||
event.api.addPanel({
|
||||
id: 'panel_4',
|
||||
component: 'default',
|
||||
params: {
|
||||
title: 'Panel 4',
|
||||
},
|
||||
position: { referencePanel: 'panel_1', direction: 'right' },
|
||||
});
|
||||
|
||||
event.api.addPanel({
|
||||
id: 'panel_5',
|
||||
component: 'default',
|
||||
params: {
|
||||
title: 'Panel 5',
|
||||
},
|
||||
position: { referencePanel: 'panel_3', direction: 'right' },
|
||||
});
|
||||
|
||||
event.api.addPanel({
|
||||
id: 'panel_6',
|
||||
component: 'default',
|
||||
params: {
|
||||
title: 'Panel 6',
|
||||
},
|
||||
position: { referencePanel: 'panel_5', direction: 'below' },
|
||||
minimumWidth: 10,
|
||||
});
|
||||
|
||||
event.api.addPanel({
|
||||
id: 'panel_7',
|
||||
component: 'default',
|
||||
params: {
|
||||
title: 'Panel 7',
|
||||
},
|
||||
position: { referencePanel: 'panel_6', direction: 'right' },
|
||||
minimumWidth: 10,
|
||||
});
|
||||
|
||||
event.api.addPanel({
|
||||
id: 'panel_8',
|
||||
component: 'default',
|
||||
params: {
|
||||
title: 'Panel 8',
|
||||
},
|
||||
position: { referencePanel: 'panel_6', direction: 'right' },
|
||||
minimumWidth: 10,
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<GridviewReact
|
||||
components={components}
|
||||
onReady={onReady}
|
||||
proportionalLayout={false}
|
||||
orientation={Orientation.VERTICAL}
|
||||
className="dockview-theme-dark"
|
||||
/>
|
||||
);
|
||||
};
|
102
build/docs/src/components/simplePaneview.tsx
Normal file
@ -0,0 +1,102 @@
|
||||
import {
|
||||
IPaneviewPanelProps,
|
||||
PaneviewReact,
|
||||
PaneviewReadyEvent,
|
||||
} from 'dockview';
|
||||
import * as React from 'react';
|
||||
|
||||
const components = {
|
||||
default: (props: IPaneviewPanelProps<{ title: string }>) => {
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
padding: '10px',
|
||||
height: '100%',
|
||||
backgroundColor: 'rgb(60,60,60)',
|
||||
}}
|
||||
>
|
||||
{props.params.title}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
const MyHeaderComponent = (props: IPaneviewPanelProps<{ title: string }>) => {
|
||||
const [expanded, setExpanded] = React.useState<boolean>(
|
||||
props.api.isExpanded
|
||||
);
|
||||
|
||||
React.useEffect(() => {
|
||||
const disposable = props.api.onDidExpansionChange((event) => {
|
||||
setExpanded(event.isExpanded);
|
||||
});
|
||||
|
||||
return () => {
|
||||
disposable.dispose();
|
||||
};
|
||||
}, []);
|
||||
|
||||
const onClick = () => {
|
||||
props.api.setExpanded(!expanded);
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
padding: '10px',
|
||||
height: '100%',
|
||||
backgroundColor: 'rgb(60,60,60)',
|
||||
}}
|
||||
>
|
||||
<a
|
||||
onClick={onClick}
|
||||
className={expanded ? 'expanded' : 'collapsed'}
|
||||
/>
|
||||
<span>{props.params.title}</span>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const headerComponents = {
|
||||
myHeaderComponent: MyHeaderComponent,
|
||||
};
|
||||
|
||||
export const SimplePaneview = () => {
|
||||
const onReady = (event: PaneviewReadyEvent) => {
|
||||
event.api.addPanel({
|
||||
id: 'panel_1',
|
||||
component: 'default',
|
||||
params: {
|
||||
title: 'Panel 1',
|
||||
},
|
||||
title: 'Panel 1',
|
||||
});
|
||||
|
||||
event.api.addPanel({
|
||||
id: 'panel_2',
|
||||
component: 'default',
|
||||
params: {
|
||||
title: 'Panel 2',
|
||||
},
|
||||
title: 'Panel 2',
|
||||
});
|
||||
|
||||
event.api.addPanel({
|
||||
id: 'panel_3',
|
||||
component: 'default',
|
||||
params: {
|
||||
title: 'Panel 3',
|
||||
},
|
||||
title: 'Panel 3',
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<PaneviewReact
|
||||
components={components}
|
||||
headerComponents={headerComponents}
|
||||
onReady={onReady}
|
||||
className="dockview-theme-dark"
|
||||
/>
|
||||
);
|
||||
};
|
54
build/docs/src/components/simpleSplitview.tsx
Normal file
@ -0,0 +1,54 @@
|
||||
import {
|
||||
ISplitviewPanelProps,
|
||||
Orientation,
|
||||
SplitviewReact,
|
||||
SplitviewReadyEvent,
|
||||
} from 'dockview';
|
||||
import * as React from 'react';
|
||||
|
||||
const components = {
|
||||
default: (props: ISplitviewPanelProps<{ title: string }>) => {
|
||||
return <div style={{ padding: '20px' }}>{props.params.title}</div>;
|
||||
},
|
||||
};
|
||||
|
||||
export const SimpleSplitview = (props: { proportional?: boolean }) => {
|
||||
const onReady = (event: SplitviewReadyEvent) => {
|
||||
event.api.addPanel({
|
||||
id: 'panel_1',
|
||||
component: 'default',
|
||||
params: {
|
||||
title: 'Panel 1',
|
||||
},
|
||||
minimumSize: 100,
|
||||
});
|
||||
|
||||
event.api.addPanel({
|
||||
id: 'panel_2',
|
||||
component: 'default',
|
||||
params: {
|
||||
title: 'Panel 2',
|
||||
},
|
||||
minimumSize: 100,
|
||||
});
|
||||
|
||||
event.api.addPanel({
|
||||
id: 'panel_3',
|
||||
component: 'default',
|
||||
params: {
|
||||
title: 'Panel 3',
|
||||
},
|
||||
minimumSize: 100,
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<SplitviewReact
|
||||
components={components}
|
||||
proportionalLayout={props.proportional}
|
||||
onReady={onReady}
|
||||
orientation={Orientation.HORIZONTAL}
|
||||
className="dockview-theme-dark"
|
||||
/>
|
||||
);
|
||||
};
|
60
build/docs/src/components/simpleSplitview2.tsx
Normal file
@ -0,0 +1,60 @@
|
||||
import { SimpleSplitview } from './simpleSplitview';
|
||||
import * as React from 'react';
|
||||
|
||||
export const SimpleSplitview2 = (props: { proportional?: boolean }) => {
|
||||
const [value, setValue] = React.useState<number>(50);
|
||||
|
||||
const onChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setValue(Number(event.target.value));
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
height: '100px',
|
||||
margin: '10px 0px',
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
height: '25px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
<input
|
||||
type={'range'}
|
||||
min={20}
|
||||
max={100}
|
||||
defaultValue={50}
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
/>
|
||||
<span style={{ padding: '0px 8px' }}>
|
||||
Slide to resize the splitview container
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
flexGrow: 1,
|
||||
display: 'grid',
|
||||
gridTemplateColumns: `${value}fr ${100 - value}fr`,
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
backgroundColor: 'rgb(30,30,30)',
|
||||
color: 'white',
|
||||
flexGrow: 1,
|
||||
border: '1px solid grey',
|
||||
}}
|
||||
>
|
||||
<SimpleSplitview proportional={props.proportional} />
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
161
build/docs/src/components/splitview/active.tsx
Normal file
@ -0,0 +1,161 @@
|
||||
import {
|
||||
ISplitviewPanel,
|
||||
ISplitviewPanelProps,
|
||||
Orientation,
|
||||
SplitviewReact,
|
||||
SplitviewReadyEvent,
|
||||
} from 'dockview';
|
||||
import * as React from 'react';
|
||||
|
||||
const components = {
|
||||
default: (props: ISplitviewPanelProps<{ title: string }>) => {
|
||||
const [active, setActive] = React.useState<boolean>(props.api.isActive);
|
||||
const [visible, setVisible] = React.useState<boolean>(
|
||||
props.api.isVisible
|
||||
);
|
||||
const [focused, setFocused] = React.useState<boolean>(
|
||||
props.api.isFocused
|
||||
);
|
||||
const [dimensions, setDimensions] = React.useState<{
|
||||
height: number;
|
||||
width: number;
|
||||
}>({
|
||||
height: props.api.height,
|
||||
width: props.api.width,
|
||||
});
|
||||
|
||||
React.useEffect(() => {
|
||||
const disposable1 = props.api.onDidActiveChange((event) =>
|
||||
setActive(event.isActive)
|
||||
);
|
||||
const disposable2 = props.api.onDidVisibilityChange((event) =>
|
||||
setVisible(event.isVisible)
|
||||
);
|
||||
const disposable3 = props.api.onDidFocusChange((event) =>
|
||||
setFocused(event.isFocused)
|
||||
);
|
||||
const disposable4 = props.api.onDidDimensionsChange((event) => {
|
||||
setDimensions({ height: event.height, width: event.width });
|
||||
});
|
||||
|
||||
return () => {
|
||||
disposable1.dispose();
|
||||
disposable2.dispose();
|
||||
disposable3.dispose();
|
||||
disposable4.dispose();
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
padding: '20px',
|
||||
display: 'grid',
|
||||
gridTemplateColumns: '100px 100px',
|
||||
lineHeight: '20px',
|
||||
gridTemplateRows: 'repeat(6, 20px)',
|
||||
}}
|
||||
>
|
||||
<span>{'Panel ID: '}</span>
|
||||
<span>{props.api.id}</span>
|
||||
<span>{'Height: '}</span>
|
||||
<span>{`${dimensions.height}px`}</span>
|
||||
<span>{'Width: '}</span>
|
||||
<span>{`${dimensions.width}px`}</span>
|
||||
<span>{'Focused: '}</span>
|
||||
<span style={{ color: focused ? 'green' : 'red' }}>{`${
|
||||
focused ? 'True' : 'False'
|
||||
}`}</span>
|
||||
|
||||
<span>{'Active: '}</span>
|
||||
<span style={{ color: active ? 'green' : 'red' }}>{`${
|
||||
active ? 'True' : 'False'
|
||||
}`}</span>
|
||||
|
||||
<span>{'Visible: '}</span>
|
||||
<span style={{ color: visible ? 'green' : 'red' }}>{`${
|
||||
visible ? 'True' : 'False'
|
||||
}`}</span>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
export const SplitviewExample1 = (props: { proportional?: boolean }) => {
|
||||
const [panels, setPanels] = React.useState<ISplitviewPanel[]>([]);
|
||||
|
||||
const onReady = React.useCallback((event: SplitviewReadyEvent) => {
|
||||
event.api.onDidAddView((panel) => setPanels(event.api.panels));
|
||||
event.api.onDidRemoveView((panel) => setPanels(event.api.panels));
|
||||
|
||||
event.api.addPanel({
|
||||
id: 'panel_1',
|
||||
component: 'default',
|
||||
params: {
|
||||
title: 'Panel 1',
|
||||
},
|
||||
minimumSize: 100,
|
||||
});
|
||||
|
||||
event.api.addPanel({
|
||||
id: 'panel_2',
|
||||
component: 'default',
|
||||
params: {
|
||||
title: 'Panel 2',
|
||||
},
|
||||
minimumSize: 100,
|
||||
});
|
||||
|
||||
event.api.addPanel({
|
||||
id: 'panel_3',
|
||||
component: 'default',
|
||||
params: {
|
||||
title: 'Panel 3',
|
||||
},
|
||||
minimumSize: 100,
|
||||
});
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
style={{
|
||||
height: '150px',
|
||||
backgroundColor: 'rgb(30,30,30)',
|
||||
color: 'white',
|
||||
}}
|
||||
>
|
||||
<SplitviewReact
|
||||
components={components}
|
||||
proportionalLayout={props.proportional}
|
||||
onReady={onReady}
|
||||
orientation={Orientation.HORIZONTAL}
|
||||
className="dockview-theme-dark"
|
||||
/>
|
||||
</div>
|
||||
<div style={{ height: '20px', display: 'flex' }}>
|
||||
{panels.map((panel) => {
|
||||
return (
|
||||
<div style={{ padding: '0px 20px' }}>
|
||||
<div>{panel.id}</div>
|
||||
<div>
|
||||
<button
|
||||
onClick={() =>
|
||||
panel.api.setVisible(
|
||||
!panel.api.isVisible
|
||||
)
|
||||
}
|
||||
>
|
||||
Toggle Visiblity
|
||||
</button>
|
||||
<button onClick={() => panel.api.setActive()}>
|
||||
Set Active
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
63
build/docs/src/components/splitview/math.scss
Normal file
@ -0,0 +1,63 @@
|
||||
.splitview-math-blog {
|
||||
.sash {
|
||||
background-color: orange;
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
width: 4px;
|
||||
height: 100%;
|
||||
z-index: 2;
|
||||
cursor: ew-resize;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.debug-sash-max {
|
||||
height: 10px;
|
||||
width: 1px;
|
||||
position: absolute;
|
||||
z-index: 999;
|
||||
top: -10px;
|
||||
}
|
||||
|
||||
.debug-sash-min {
|
||||
height: 10px;
|
||||
width: 1px;
|
||||
position: absolute;
|
||||
z-index: 999;
|
||||
top: 100%;
|
||||
}
|
||||
|
||||
.debug-sash-text {
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
width: 80px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
position: absolute;
|
||||
z-index: 999;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.sash-container {
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.view-container {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.view {
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
background-color: dodgerblue;
|
||||
z-index: 1;
|
||||
top: 0px;
|
||||
padding: 10px;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.sash.drag-sash {
|
||||
background-color: red;
|
||||
}
|
||||
}
|
342
build/docs/src/components/splitview/math.tsx
Normal file
@ -0,0 +1,342 @@
|
||||
import * as React from 'react';
|
||||
import './math.scss';
|
||||
|
||||
const min = 100;
|
||||
const max = 300;
|
||||
|
||||
interface IDebugResize {
|
||||
leftmin: number;
|
||||
leftmax: number;
|
||||
rightmin: number;
|
||||
rightmax: number;
|
||||
min: number;
|
||||
max: number;
|
||||
}
|
||||
|
||||
const resize = (
|
||||
index: number,
|
||||
delta: number,
|
||||
sizes: number[],
|
||||
mode: number
|
||||
) => {
|
||||
const nextSizes = [...sizes];
|
||||
|
||||
const left = nextSizes.filter((_, i) => i <= index);
|
||||
const right = nextSizes.filter((_, i) => i > index);
|
||||
|
||||
let result: IDebugResize = {
|
||||
leftmin: undefined,
|
||||
leftmax: undefined,
|
||||
rightmin: undefined,
|
||||
rightmax: undefined,
|
||||
max: undefined,
|
||||
min: undefined,
|
||||
};
|
||||
|
||||
// step 3
|
||||
if (mode > 2) {
|
||||
const leftMinimumsDelta = left
|
||||
.map((x) => min - x)
|
||||
.reduce((x, y) => x + y, 0);
|
||||
const leftMaximumsDelta = left
|
||||
.map((x) => max - x)
|
||||
.reduce((x, y) => x + y, 0);
|
||||
const rightMinimumsDelta = right
|
||||
.map((x) => x - min)
|
||||
.reduce((x, y) => x + y, 0);
|
||||
const rightMaximumsDelta = right
|
||||
.map((x) => x - max)
|
||||
.reduce((x, y) => x + y, 0);
|
||||
const _min = Math.max(leftMinimumsDelta, rightMaximumsDelta);
|
||||
const _max = Math.min(leftMaximumsDelta, rightMinimumsDelta);
|
||||
const clamp = Math.max(_min, Math.min(_max, delta));
|
||||
|
||||
result = {
|
||||
leftmin: leftMinimumsDelta,
|
||||
leftmax: leftMaximumsDelta,
|
||||
rightmin: rightMinimumsDelta,
|
||||
rightmax: rightMaximumsDelta,
|
||||
max: _max,
|
||||
min: _min,
|
||||
};
|
||||
delta = clamp;
|
||||
}
|
||||
|
||||
let usedDelta = 0;
|
||||
let remainingDelta = delta;
|
||||
|
||||
// Step 1
|
||||
for (let i = left.length - 1; i > -1; i--) {
|
||||
const x = Math.max(min, Math.min(max, left[i] + remainingDelta));
|
||||
const viewDelta = x - left[i];
|
||||
usedDelta += viewDelta;
|
||||
remainingDelta -= viewDelta;
|
||||
left[i] = x;
|
||||
}
|
||||
|
||||
// Step 2
|
||||
if (mode > 1) {
|
||||
for (let i = 0; i < right.length; i++) {
|
||||
const x = Math.max(min, Math.min(max, right[i] - usedDelta));
|
||||
const viewDelta = x - right[i];
|
||||
usedDelta += viewDelta;
|
||||
right[i] = x;
|
||||
}
|
||||
}
|
||||
|
||||
return { ...result, sizes: [...left, ...right] };
|
||||
};
|
||||
|
||||
interface ILayoutState {
|
||||
sashes: number[];
|
||||
views: number[];
|
||||
deltas: number[];
|
||||
left: number;
|
||||
right: number;
|
||||
debug: IDebugResize;
|
||||
drag: number;
|
||||
}
|
||||
|
||||
export const Splitview = (props: { mode: number; debug: boolean }) => {
|
||||
// keep the sashes and views in one state to prevent weird out-of-sync-ness
|
||||
const [layout, setLayout] = React.useState<ILayoutState>({
|
||||
sashes: [200, 400],
|
||||
views: [200, 200, 200],
|
||||
deltas: [0, 0, 0],
|
||||
left: 0,
|
||||
right: 0,
|
||||
debug: undefined,
|
||||
drag: -1,
|
||||
});
|
||||
|
||||
const ref = React.useRef<HTMLDivElement>();
|
||||
|
||||
const onMouseDown = (index: number) => (ev: React.MouseEvent) => {
|
||||
const start = ev.clientX;
|
||||
const sizes = [...layout.views];
|
||||
|
||||
const mousemove = (ev: MouseEvent) => {
|
||||
const current = ev.clientX;
|
||||
const delta = current - start;
|
||||
const {
|
||||
sizes: nextLayout,
|
||||
rightmin,
|
||||
rightmax,
|
||||
leftmin,
|
||||
leftmax,
|
||||
max,
|
||||
min,
|
||||
} = resize(index, delta, sizes, props.mode);
|
||||
const sashes = nextLayout.reduce(
|
||||
(x, y) => [...x, y + (x.length === 0 ? 0 : x[x.length - 1])],
|
||||
[]
|
||||
);
|
||||
sashes.splice(sashes.length - 1, 1);
|
||||
const deltas = sizes.map((x, i) => nextLayout[i] - x);
|
||||
|
||||
const offset = start - ref.current?.getBoundingClientRect().left;
|
||||
|
||||
setLayout({
|
||||
views: nextLayout,
|
||||
sashes,
|
||||
deltas,
|
||||
left: deltas
|
||||
.filter((_, i) => i <= index)
|
||||
.reduce((x, y) => x + y, 0),
|
||||
right: deltas
|
||||
.filter((_, i) => i > index)
|
||||
.reduce((x, y) => x + y, 0),
|
||||
debug: {
|
||||
leftmax: leftmax + offset,
|
||||
leftmin: leftmin + offset,
|
||||
rightmax: rightmax + offset,
|
||||
rightmin: rightmin + offset,
|
||||
min: min + offset,
|
||||
max: max + offset,
|
||||
},
|
||||
drag: index,
|
||||
});
|
||||
};
|
||||
|
||||
const end = (ev: MouseEvent) => {
|
||||
document.removeEventListener('mousemove', mousemove);
|
||||
document.removeEventListener('mouseup', end);
|
||||
setLayout((_) => ({
|
||||
..._,
|
||||
deltas: _.deltas.map((_) => 0),
|
||||
left: 0,
|
||||
right: 0,
|
||||
drag: -1,
|
||||
}));
|
||||
};
|
||||
|
||||
document.addEventListener('mousemove', mousemove);
|
||||
document.addEventListener('mouseup', end);
|
||||
};
|
||||
|
||||
const extras = React.useMemo(() => {
|
||||
if (!props.debug || !layout.debug || props.mode < 3) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
style={{
|
||||
left: `${layout.debug.leftmax - 40}px`,
|
||||
top: '-30px',
|
||||
}}
|
||||
className="debug-sash-text"
|
||||
>
|
||||
left-max
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
left: `${layout.debug.leftmin - 40}px`,
|
||||
top: '-30px',
|
||||
}}
|
||||
className="debug-sash-text"
|
||||
>
|
||||
left-min
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
left: `${layout.debug.rightmax - 40}px`,
|
||||
bottom: '-30px',
|
||||
}}
|
||||
className="debug-sash-text"
|
||||
>
|
||||
right-max
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
left: `${layout.debug.rightmin - 40}px`,
|
||||
bottom: '-30px',
|
||||
}}
|
||||
className="debug-sash-text"
|
||||
>
|
||||
right-min
|
||||
</div>
|
||||
<div
|
||||
className="debug-sash-max"
|
||||
style={{
|
||||
left: `${layout.debug.leftmax - 1}px`,
|
||||
border: '2px solid purple',
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
className="debug-sash-max"
|
||||
style={{
|
||||
left: `${layout.debug.leftmin - 1}px`,
|
||||
border: '2px solid green',
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
className="debug-sash-min"
|
||||
style={{
|
||||
left: `${layout.debug.rightmax - 1}px`,
|
||||
border: '2px solid cyan',
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
className="debug-sash-min"
|
||||
style={{
|
||||
left: `${layout.debug.rightmin - 1}px`,
|
||||
border: '2px solid pink',
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}, [layout.debug]);
|
||||
|
||||
return (
|
||||
<div
|
||||
className="splitview-math-blog"
|
||||
style={{
|
||||
marginBottom: '40px',
|
||||
marginTop: '30px',
|
||||
backgroundColor: 'gray',
|
||||
}}
|
||||
>
|
||||
{props.debug && (
|
||||
<div style={{ marginBottom: extras ? '25px' : '0px' }}>
|
||||
<span>{`Change to left ${layout?.left}`}</span>
|
||||
<span
|
||||
style={{
|
||||
marginLeft: '10px',
|
||||
backgroundColor:
|
||||
-layout?.right !== layout?.left ? 'red' : '',
|
||||
}}
|
||||
>{`Change to right ${layout?.right}`}</span>
|
||||
<span
|
||||
style={{ marginLeft: '10px' }}
|
||||
>{`Total size ${layout?.views.reduce(
|
||||
(x, y) => x + y,
|
||||
0
|
||||
)}`}</span>
|
||||
</div>
|
||||
)}
|
||||
<div
|
||||
ref={ref}
|
||||
style={{
|
||||
height: '100px',
|
||||
width: '100%',
|
||||
position: 'relative',
|
||||
backgroundColor: 'dimgray',
|
||||
}}
|
||||
>
|
||||
<div className="sash-container">
|
||||
{layout.sashes.map((x, i) => {
|
||||
const className =
|
||||
layout.drag === i ? 'sash drag-sash' : 'sash';
|
||||
return (
|
||||
<div
|
||||
key={i}
|
||||
onMouseDown={onMouseDown(i)}
|
||||
style={{
|
||||
left: `${x - 2}px`,
|
||||
}}
|
||||
className={className}
|
||||
></div>
|
||||
);
|
||||
})}
|
||||
{extras}
|
||||
</div>
|
||||
<div className="view-container">
|
||||
{layout.views.map((x, i) => {
|
||||
const isMax = x >= max;
|
||||
const isMin = x <= min;
|
||||
|
||||
return (
|
||||
<div
|
||||
key={i}
|
||||
style={{
|
||||
left: `${
|
||||
i === 0 ? 0 : layout.sashes[i - 1]
|
||||
}px`,
|
||||
width: `${x}px`,
|
||||
}}
|
||||
className="view"
|
||||
>
|
||||
{props.debug && (
|
||||
<>
|
||||
<div>
|
||||
{`${layout.views[i]} (${
|
||||
layout.deltas[i] > -1 ? '+' : ''
|
||||
}${layout.deltas[i]})`}
|
||||
</div>
|
||||
<div
|
||||
style={{ fontSize: '12px' }}
|
||||
>{`isMin = ${isMin}`}</div>
|
||||
<div
|
||||
style={{ fontSize: '12px' }}
|
||||
>{`isMax = ${isMax}`}</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
32
build/docs/src/css/custom.css
Normal file
@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Any CSS included here will be global. The classic template
|
||||
* bundles Infima by default. Infima is a CSS framework designed to
|
||||
* work well for content-centric websites.
|
||||
*/
|
||||
|
||||
/* You can override the default Infima variables here. */
|
||||
:root {
|
||||
--ifm-color-primary: #2e8555;
|
||||
--ifm-color-primary-dark: #29784c;
|
||||
--ifm-color-primary-darker: #277148;
|
||||
--ifm-color-primary-darkest: #205d3b;
|
||||
--ifm-color-primary-light: #33925d;
|
||||
--ifm-color-primary-lighter: #359962;
|
||||
--ifm-color-primary-lightest: #3cad6e;
|
||||
--ifm-code-font-size: 95%;
|
||||
--docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
/* For readability concerns, you should choose a lighter palette in dark mode. */
|
||||
[data-theme='dark'] {
|
||||
--ifm-color-primary: #25c2a0;
|
||||
--ifm-color-primary-dark: #21af90;
|
||||
--ifm-color-primary-darker: #1fa588;
|
||||
--ifm-color-primary-darkest: #1a8870;
|
||||
--ifm-color-primary-light: #29d5b0;
|
||||
--ifm-color-primary-lighter: #32d8b4;
|
||||
--ifm-color-primary-lightest: #4fddbf;
|
||||
--docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
@import "~dockview/dist/styles/dockview.css"
|
BIN
build/docs/src/misc/math/constraints.jpg
Normal file
After Width: | Height: | Size: 134 KiB |
378
build/docs/src/misc/math/math.mdx
Normal file
@ -0,0 +1,378 @@
|
||||
import { Splitview } from '../../src/components/splitview/math';
|
||||
|
||||
Wondering how to create a resizable split view, pane or window; whichever you may call it?
|
||||
Here's a langauge indepedant walkthrough of how to design a split view control from scratch and the simple math behind it.
|
||||
You will find links to all examples which are written using TypeScript.
|
||||
|
||||
Here's the end result and you can continue to read on to see how we got here.
|
||||
|
||||
<Splitview mode={3} debug={false} />
|
||||
|
||||
## First of all, what is a split view control?
|
||||
|
||||
Not all split view controls are born equal, but for our purposes
|
||||
|
||||
> A split view control is comprised from a number of 'views' layed out either horizontally or vertically.
|
||||
> Each view can be indepedantly resized by dragging on the edge of a particular view.
|
||||
|
||||
In order to explain how this works we are going to need some more in-depth definitions so lets start with the two
|
||||
fundamental components of this control, the <b>View</b> and the <b>Sash</b> (I will explain).
|
||||
The below assumes the split view control has <b>n</b> views, where n is positive number.
|
||||
For example if n=4 then our split view controls has 4 views. This generic approach will make it much easier to explain going forwards.
|
||||
|
||||
<div>
|
||||
<div>View</div>
|
||||
<ul style={{ marginLeft: '40px' }}>
|
||||
<li>
|
||||
The size of the n<sup>th</sup> view will be known as V<sub>n</sub>
|
||||
</li>
|
||||
<li>
|
||||
The minimum size of the n<sup>th</sup> view will be known as V
|
||||
<sup>min</sup>
|
||||
<sub>n</sub>
|
||||
</li>
|
||||
<li>
|
||||
The maximum size of the n<sup>th</sup> view will be known as V
|
||||
<sup>max</sup>
|
||||
<sub>n</sub>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
Additional by definition we can known V<sup>min</sup><sub>n</sub> <= V<sub>n</sub> <= V<sup>max</sup><sub>n</sub>
|
||||
|
||||
To be able to resize a view we need to be able to drag on the edge of a view to increase or decrease it's size.
|
||||
This can be achieved by introducing a narrow component that sits between each view acting as a 'drag handle'.
|
||||
We will call this component a <b>Sash</b> because sash is also the word for those [windows](https://en.wikipedia.org/wiki/Sash_window) with movable panels.
|
||||
|
||||
<div>
|
||||
<div>Sash</div>
|
||||
<ul style={{marginLeft: "40px"}}>
|
||||
<li>If we have n views then we will have n-1 sashes. There is no sash before V<sub>0</sub> nor after V<sub>n</sub></li>
|
||||
<li>The sash between V<sub>n</sub> and V<sub>n+1</sub> is known as S<sub>n</sub></li>
|
||||
<li>The sash is of fixed width, and it's sole purpose is to act a drag-handle for resizing views</li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
This now gives us a definition of the split view control but in additional to that, to calculate the new view sizes
|
||||
after a sash is dragged we need to know which sash is being dragged.
|
||||
We will denote the sash S<sub>i</sub> as the sash to drag going forwards we can reference the following diagram.
|
||||
|
||||
![alt txt](./visual_1.jpg)
|
||||
|
||||
If we are to drag the sash S<sub>i</sub> then we need to also know how far along the x-axis, or the horizontal-axis we have travelled.
|
||||
We can denote this as the delta, using the symbol Δ.
|
||||
Delta is only limited by how wide the screen is so for this purpose we can say it ranges from negative to positive infinity, that is -∞ < Δ < ∞ .
|
||||
|
||||
In reality as you will see we will apply a set of constraints on the value of Δ reducing it's overall set of valid values.
|
||||
|
||||
## Iteration #1 - The naive approach (aka. the accordian)
|
||||
|
||||
As I add delta I increase view sizes and as I remove delta I decrease view sizes.
|
||||
A rather naive approach but it could look something like this:
|
||||
|
||||
- as the sash moves left shrink each view to the left and as the sash moves right expand each view to left, from right-most to left-most in both caes.
|
||||
- If there is enough delta to shrink a view to it's mimimum size then move onto the next view, and if we have enough delta to expand a view to it's maximum size then again move onto the next view.
|
||||
- Shrink no more once everything to the left is at minimums and expand no more once everything to the left is at maximums
|
||||
- We don't manipulate any views to the right of the active sash S<sub>i</sub>
|
||||
|
||||
You should be able to show each of the four points above hold true for the below interactive example.
|
||||
You'll see that changes to the right will always remain at zero because we are not manipulating views to the right of the active sash.
|
||||
|
||||
<Splitview mode={1} debug={true} />
|
||||
|
||||
There are some obvious flaws with this approach but before we go into that lets put this implemenation in psuedocode using our definitions
|
||||
from above where we drag sash S<sub>i</sub> by an amount Δ
|
||||
|
||||
<div
|
||||
style={{
|
||||
display: 'inline-block',
|
||||
marginLeft: '20px',
|
||||
marginBottom: '20px',
|
||||
borderLeft: '2px solid black',
|
||||
}}
|
||||
>
|
||||
<div className="markdown-line">
|
||||
Δ<sub>remaining</sub> = Δ
|
||||
</div>
|
||||
<div className="markdown-line">
|
||||
<span style={{ fontWeight: 'bold' }}>for</span>
|
||||
<span>
|
||||
(<span style={{ fontStyle: 'italic' }}>j = i; j >= 0; i--</span>)
|
||||
</span>
|
||||
<span style={{ fontWeight: 'bold' }}> do</span>
|
||||
</div>
|
||||
<div className="markdown-line indent-1">
|
||||
<span>
|
||||
V<sup>next</sup>
|
||||
<sub>j</sub> = <span style={{ fontWeight: 'bold' }}>Min</span>(V<sup>
|
||||
max
|
||||
</sup>
|
||||
<sub>j</sub>, <span style={{ fontWeight: 'bold' }}>Max</span>(V
|
||||
<sup>min</sup>
|
||||
<sub>j</sub>, V<sub>j</sub> + Δ<sub>remaining</sub>))
|
||||
</span>
|
||||
</div>
|
||||
<div className="markdown-line indent-1">
|
||||
<span>
|
||||
V<sup>Δ</sup>
|
||||
<sub>j</sub> = V<sup>next</sup>
|
||||
<sub>j</sub> - V<sub>j</sub>
|
||||
</span>
|
||||
</div>
|
||||
<div className="markdown-line indent-1">
|
||||
<span>
|
||||
Δ<sub>remaining</sub> = Δ<sub>remaining</sub> - V<sup>Δ</sup>
|
||||
<sub>j</sub>
|
||||
</span>
|
||||
</div>
|
||||
<div className="markdown-line indent-1">
|
||||
<span>
|
||||
V<sub>j</sub> = V<sup>next</sup>
|
||||
<sub>j</sub>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
or in plain text
|
||||
|
||||
<div
|
||||
style={{
|
||||
borderLeft: '2px solid black',
|
||||
margin: '0px 20px 20px 20px',
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{ borderRight: '2px solid black', flexShrink: 0, width: '20px' }}
|
||||
>
|
||||
<div style={{ display: 'flex', justifyContent: 'center' }}>1</div>
|
||||
<div style={{ display: 'flex', justifyContent: 'center' }}>2</div>
|
||||
<div style={{ display: 'flex', justifyContent: 'center' }}>3</div>
|
||||
<div style={{ display: 'flex', justifyContent: 'center' }}>4</div>
|
||||
</div>
|
||||
<div style={{ flexGrow: 1, marginLeft: '20px' }}>
|
||||
<div>
|
||||
For each view j to the left of the sash we have dragged, from
|
||||
right-most to left-most
|
||||
</div>
|
||||
<div>
|
||||
Add the delta to the view j (clamped at either the maximum or
|
||||
minimum value)
|
||||
</div>
|
||||
<div>
|
||||
Subtract the different between the new and old size (the used delta)
|
||||
from the remaining delta
|
||||
</div>
|
||||
<div>repeat</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Going back to that obvious flaw, the width of the control does not remain constant. It flexes with Δ.
|
||||
|
||||
## Iteration #2 - Δ is added. Then Δ must be removed
|
||||
|
||||
We want a component of constant width and we dont want to think too hard.
|
||||
So If I have added Δ to the left then I should add -Δ (or remove Δ) on the right, and vice-versa; right? Nearly.
|
||||
|
||||
<Splitview mode={2} debug={true} />
|
||||
|
||||
There are some more subtle flaws with this approach; but lets describe it in psuedocode first.
|
||||
We now need another variable to track the delta we've added on the left, Δ<sub>used</sub>.
|
||||
After we've applied changes to the left side we'll substract this Δ<sub>used</sub> from the right side which should keep the width of our control at a
|
||||
constant size.
|
||||
|
||||
<div style={{display: "inline-block", marginLeft: "20px", marginBottom: "20px", borderLeft: "2px solid black"}}>
|
||||
<div className="markdown-line">
|
||||
Δ<sub>remaining</sub> = Δ
|
||||
</div>
|
||||
<div className="markdown-line markdown-highlight">
|
||||
Δ<sub>used</sub> = 0
|
||||
</div>
|
||||
<div className="markdown-line">
|
||||
<span style={{fontWeight: "bold"}}>for</span><span>(<span style={{fontStyle: "italic"}}>j = i; j >= 0; i--</span>)</span>
|
||||
<span style={{fontWeight: "bold"}}> do</span>
|
||||
</div>
|
||||
<div className="markdown-line indent-1">
|
||||
<span>
|
||||
V<sup>next</sup><sub>j</sub> = <span style={{fontWeight: "bold"}}>Min</span>(V<sup>max</sup><sub>j</sub>, <span style={{fontWeight: "bold"}}>Max</span>(V<sup>min</sup><sub>j</sub>, V<sub>j</sub> + Δ<sub>remaining</sub>))
|
||||
</span>
|
||||
</div>
|
||||
<div className="markdown-line indent-1">
|
||||
<span>
|
||||
V<sup>Δ</sup><sub>j</sub> = V<sup>next</sup><sub>j</sub> - V<sub>j</sub>
|
||||
</span>
|
||||
</div>
|
||||
<div className="markdown-line indent-1">
|
||||
<span>
|
||||
Δ<sub>remaining</sub> = Δ<sub>remaining</sub> - V<sup>Δ</sup><sub>j</sub>
|
||||
</span>
|
||||
</div>
|
||||
<div className="markdown-line indent-1 markdown-highlight">
|
||||
<span>
|
||||
Δ<sub>used</sub> = Δ<sub>used</sub> + V<sup>Δ</sup><sub>j</sub>
|
||||
</span>
|
||||
</div>
|
||||
<div className="markdown-line indent-1">
|
||||
<span>
|
||||
V<sub>j</sub> = V<sup>next</sup><sub>j</sub>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div style={{height: "0px", width: "100%", marginBottom: "20px"}}/>
|
||||
<div className="markdown-line markdown-highlight">
|
||||
<span style={{fontWeight: "bold"}}>for</span><span>(<span style={{fontStyle: "italic"}}>{"j = i+1; j < n; i++"}</span>)</span>
|
||||
<span style={{fontWeight: "bold"}}> do</span>
|
||||
</div>
|
||||
<div className="markdown-line markdown-highlight indent-1">
|
||||
<span>
|
||||
V<sup>next</sup><sub>j</sub> = <span style={{fontWeight: "bold"}}>Min</span>(V<sup>max</sup><sub>j</sub>, <span style={{fontWeight: "bold"}}>Max</span>(V<sup>min</sup><sub>j</sub>,V<sub>j</sub> - Δ<sub>used</sub>))
|
||||
</span>
|
||||
</div>
|
||||
<div className="markdown-line markdown-highlight indent-1">
|
||||
<span>
|
||||
V<sup>Δ</sup><sub>j</sub> = V<sup>next</sup><sub>j</sub> - V<sub>j</sub>
|
||||
</span>
|
||||
</div>
|
||||
<div className="markdown-line markdown-highlight indent-1">
|
||||
<span>
|
||||
Δ<sub>used</sub> = Δ<sub>used</sub> + V<sup>Δ</sup><sub>j</sub>
|
||||
</span>
|
||||
</div>
|
||||
<div style={{marginBottom: "20px"}} className="markdown-line markdown-highlight indent-1">
|
||||
<span>
|
||||
V<sub>j</sub> = V<sup>next</sup><sub>j</sub>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Go back and try to minimise or maximise every view in the container. The width is no longer preserved, you can see at some point the change to the left
|
||||
is not longer eqaul to the change on the right, which causes the container to once again flex.
|
||||
|
||||
## Iteration #3 - Constraining the values of Δ
|
||||
|
||||
In the cases where iteration #2 is not working correctly this can be explained as either adding or removing too much delta.
|
||||
Fortunately it turns out there are a few constraints we can define on delta to help with this.
|
||||
For a sash S<sub>i</sub> lets think about the minimum and maximum amount of delta we can use.
|
||||
Try to follow the explainations first and then we will use another interactive example and diagram to reinforce the explaination.
|
||||
|
||||
> S<sub>i</sub> can go no further left that the sum of the minimum sizes of the views to the left, and can go no further right than the sum of the
|
||||
> minimum sizes of the views to the right; because otherwise you would end up with at least one view that is smaller than it's specified minimum.
|
||||
|
||||
> Another less obvious condition on S<sub>i</sub> is that it can go no further left that the sum of the maximum sizes of the views to the right, and can go no further
|
||||
> right than the sum of maximum sizes to the left; because otherwise you would end up with at least one view that is larger than it's specified maximum.
|
||||
|
||||
This leaves us with 4 constraints we need to apply on Δ; but since Δ is relative to S<sub>i</sub> first of all we need these
|
||||
constraints relative to S<sub>i</sub>. That is to say what amount of Δ is equivalent to the constraints we just described.
|
||||
|
||||
When the views to the left of S<sub>i</sub> are all at minimum size we will call the distance between here and Δ to be Δ<sup>min</sup><sub>left</sub>.
|
||||
This distance would be the sum of the differences between
|
||||
V<sup>min</sup><sub>j</sub> and V<sub>j</sub> for each view, or in more format notation we could write this as
|
||||
|
||||
<div style={{ margin: '20px' }}>
|
||||
<span>
|
||||
Δ<sup>min</sup>
|
||||
<sub>left</sub> = Σ V<sup>min</sup>
|
||||
<sub>j</sub> - V<sub>j</sub>
|
||||
</span>
|
||||
<span style={{ marginLeft: '20px' }}>j = i,...0</span>
|
||||
</div>
|
||||
|
||||
Similarly we can work out the distance between S<sub>i</sub> and the point at each every view to the left is at its
|
||||
maximum size as the sum of differences between V<sup>max</sup><sub>j</sub> an V<sub>j</sub>
|
||||
|
||||
<div style={{ margin: '20px' }}>
|
||||
<span>
|
||||
Δ<sup>max</sup>
|
||||
<sub>left</sub> = Σ V<sup>max</sup>
|
||||
<sub>j</sub> - V<sub>j</sub>
|
||||
</span>
|
||||
<span style={{ marginLeft: '20px' }}>j = i,...0</span>
|
||||
</div>
|
||||
|
||||
The same logic can be applied to work out those values for Δ<sup>min</sup><sub>right</sub> and Δ<sup>max</sup><sub>right</sub>
|
||||
|
||||
<div style={{ margin: '20px' }}>
|
||||
<div style={{ marginBottom: '10px' }}>
|
||||
<span>
|
||||
Δ<sup>min</sup>
|
||||
<sub>right</sub> = Σ V<sub>j</sub> - V<sup>min</sup>
|
||||
<sub>j</sub>
|
||||
</span>
|
||||
<span style={{ marginLeft: '20px' }}>j = i+1...n</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>
|
||||
Δ<sup>max</sup>
|
||||
<sub>right</sub> = Σ V<sub>j</sub> - V<sup>min</sup>
|
||||
<sub>j</sub>
|
||||
</span>
|
||||
<span style={{ marginLeft: '20px' }}>j = i+1...n</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
We now have two minimum constraints which are V<sup>min</sup><sub>left</sub> and V<sup>max</sup><sub>right</sub> and two maximum
|
||||
constraints V<sup>max</sup><sub>left</sub> and V<sup>min</sup><sub>right</sub>.
|
||||
To get one minimum and maximum value for the Δ we should take the maximum of the two minimums and the minimum of the two maximums which will
|
||||
ensure all four constraints will hold true.
|
||||
|
||||
<div style={{ margin: '20px' }}>
|
||||
<div style={{ marginBottom: '10px' }}>
|
||||
Δ<sub>min</sub> = MAX ( V<sup>min</sup>
|
||||
<sub>left</sub> , V<sup>max</sup>
|
||||
<sub>right</sub> )
|
||||
</div>
|
||||
<div>
|
||||
Δ<sub>max</sub> = MIN ( V<sup>max</sup>
|
||||
<sub>left</sub> , V<sup>min</sup>
|
||||
<sub>right</sub> )
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Finally we must clamp our Δ to be within this minimum and maxium boundary.
|
||||
This clamped delta can be used in place of delta in the pseudocode from iteration #2.
|
||||
|
||||
<div style={{ margin: '20px' }}>
|
||||
Δ<sub>clamped</sub> = MIN ( V<sub>max</sub> , MAX ( V<sub>min</sub> , Δ ) )
|
||||
</div>
|
||||
|
||||
You can see how this works in this interactive example which also shows the current values of our four constraints for each sash drag event.
|
||||
|
||||
<Splitview mode={3} debug={true} />
|
||||
|
||||
Additionally you can see in the below diagram how all of our above calculations come together to give a minimum and maximum constraints on Δ.
|
||||
|
||||
![alt txt](./constraints.jpg)
|
||||
|
||||
## Appendix
|
||||
|
||||
### The clamp function
|
||||
|
||||
To clamp a value is to say given a value, a minimum and a maximum return
|
||||
|
||||
- the minimum, if value < minimum
|
||||
- the maximum if value > maximum
|
||||
- otherwise returning the value
|
||||
|
||||
In otherwords we have 'clamped' the value to be within our defined minimum and maximum values. Mathematically we can write this as
|
||||
|
||||
<div style={{ marginBottom: '20px' }} className="markdown-line">
|
||||
<b>f</b>(value, value<sub>min</sub>, value<sub>max</sub>) = <b>MIN</b>(value
|
||||
<sub>max</sub>, <b>MAX</b>(value<sub>min</sub>, value))
|
||||
</div>
|
||||
|
||||
with some examples
|
||||
|
||||
<div style={{ marginLeft: '20px', marginBottom: '20px' }}>
|
||||
<div className="markdown-small-line">
|
||||
<b>f</b>(10, 20, 30) = 20
|
||||
</div>
|
||||
<div className="markdown-small-line">
|
||||
<b>f</b>(40, 20, 30) = 30
|
||||
</div>
|
||||
<div className="markdown-small-line">
|
||||
<b>f</b>(25, 20, 30) = 25
|
||||
</div>
|
||||
</div>
|
BIN
build/docs/src/misc/math/visual_1.jpg
Normal file
After Width: | Height: | Size: 35 KiB |
23
build/docs/src/pages/index.module.css
Normal file
@ -0,0 +1,23 @@
|
||||
/**
|
||||
* CSS files with the .module.css suffix will be treated as CSS modules
|
||||
* and scoped locally.
|
||||
*/
|
||||
|
||||
.heroBanner {
|
||||
padding: 4rem 0;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 996px) {
|
||||
.heroBanner {
|
||||
padding: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
.buttons {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
46
build/docs/src/pages/index.tsx
Normal file
@ -0,0 +1,46 @@
|
||||
import React from 'react';
|
||||
import clsx from 'clsx';
|
||||
import Layout from '@theme/Layout';
|
||||
import Link from '@docusaurus/Link';
|
||||
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
||||
import styles from './index.module.css';
|
||||
import HomepageFeatures from '@site/src/components/HomepageFeatures';
|
||||
import { SimpleDockview } from '../components/simpleDockview';
|
||||
|
||||
function HomepageHeader() {
|
||||
const { siteConfig } = useDocusaurusContext();
|
||||
return (
|
||||
<header className={clsx('hero hero--primary', styles.heroBanner)}>
|
||||
<div className="container">
|
||||
<h1 className="hero__title">{siteConfig.title}</h1>
|
||||
<p className="hero__subtitle">{siteConfig.tagline}</p>
|
||||
<div className={styles.buttons}>
|
||||
<Link
|
||||
className="button button--secondary button--lg"
|
||||
to="/docs"
|
||||
>
|
||||
Get Started
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
);
|
||||
}
|
||||
|
||||
export default function Home(): JSX.Element {
|
||||
const { siteConfig } = useDocusaurusContext();
|
||||
return (
|
||||
<Layout
|
||||
title={`Hello from ${siteConfig.title}`}
|
||||
description="Description will go into a meta tag in <head />"
|
||||
>
|
||||
<HomepageHeader />
|
||||
<main className="container">
|
||||
<div style={{ height: '500px', padding: '20px 0px' }}>
|
||||
<SimpleDockview />
|
||||
</div>
|
||||
{/* <HomepageFeatures /> */}
|
||||
</main>
|
||||
</Layout>
|
||||
);
|
||||
}
|
7
build/docs/src/pages/markdown-page.md
Normal file
@ -0,0 +1,7 @@
|
||||
---
|
||||
title: Markdown page example
|
||||
---
|
||||
|
||||
# Markdown page example
|
||||
|
||||
You don't need React to write simple standalone pages.
|
7
build/docs/src/theme/Root.tsx
Normal file
@ -0,0 +1,7 @@
|
||||
import React from 'react';
|
||||
import { RecoilRoot } from 'recoil';
|
||||
|
||||
// Default implementation, that you can customize
|
||||
export default function Root({ children }) {
|
||||
return <RecoilRoot>{children}</RecoilRoot>;
|
||||
}
|
BIN
build/docs/static/img/docusaurus.png
vendored
Normal file
After Width: | Height: | Size: 5.0 KiB |
BIN
build/docs/static/img/favicon.ico
vendored
Normal file
After Width: | Height: | Size: 3.5 KiB |
1
build/docs/static/img/logo.svg
vendored
Normal file
After Width: | Height: | Size: 6.3 KiB |
171
build/docs/static/img/undraw_docusaurus_mountain.svg
vendored
Normal file
@ -0,0 +1,171 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1088" height="687.962" viewBox="0 0 1088 687.962">
|
||||
<title>Easy to Use</title>
|
||||
<g id="Group_12" data-name="Group 12" transform="translate(-57 -56)">
|
||||
<g id="Group_11" data-name="Group 11" transform="translate(57 56)">
|
||||
<path id="Path_83" data-name="Path 83" d="M1017.81,560.461c-5.27,45.15-16.22,81.4-31.25,110.31-20,38.52-54.21,54.04-84.77,70.28a193.275,193.275,0,0,1-27.46,11.94c-55.61,19.3-117.85,14.18-166.74,3.99a657.282,657.282,0,0,0-104.09-13.16q-14.97-.675-29.97-.67c-15.42.02-293.07,5.29-360.67-131.57-16.69-33.76-28.13-75-32.24-125.27-11.63-142.12,52.29-235.46,134.74-296.47,155.97-115.41,369.76-110.57,523.43,7.88C941.15,276.621,1036.99,396.031,1017.81,560.461Z" transform="translate(-56 -106.019)" fill="#3f3d56"/>
|
||||
<path id="Path_84" data-name="Path 84" d="M986.56,670.771c-20,38.52-47.21,64.04-77.77,80.28a193.272,193.272,0,0,1-27.46,11.94c-55.61,19.3-117.85,14.18-166.74,3.99a657.3,657.3,0,0,0-104.09-13.16q-14.97-.675-29.97-.67-23.13.03-46.25,1.72c-100.17,7.36-253.82-6.43-321.42-143.29L382,283.981,444.95,445.6l20.09,51.59,55.37-75.98L549,381.981l130.2,149.27,36.8-81.27L970.78,657.9l14.21,11.59Z" transform="translate(-56 -106.019)" fill="#f2f2f2"/>
|
||||
<path id="Path_85" data-name="Path 85" d="M302,282.962l26-57,36,83-31-60Z" opacity="0.1"/>
|
||||
<path id="Path_86" data-name="Path 86" d="M610.5,753.821q-14.97-.675-29.97-.67L465.04,497.191Z" transform="translate(-56 -106.019)" opacity="0.1"/>
|
||||
<path id="Path_87" data-name="Path 87" d="M464.411,315.191,493,292.962l130,150-132-128Z" opacity="0.1"/>
|
||||
<path id="Path_88" data-name="Path 88" d="M908.79,751.051a193.265,193.265,0,0,1-27.46,11.94L679.2,531.251Z" transform="translate(-56 -106.019)" opacity="0.1"/>
|
||||
<circle id="Ellipse_11" data-name="Ellipse 11" cx="3" cy="3" r="3" transform="translate(479 98.962)" fill="#f2f2f2"/>
|
||||
<circle id="Ellipse_12" data-name="Ellipse 12" cx="3" cy="3" r="3" transform="translate(396 201.962)" fill="#f2f2f2"/>
|
||||
<circle id="Ellipse_13" data-name="Ellipse 13" cx="2" cy="2" r="2" transform="translate(600 220.962)" fill="#f2f2f2"/>
|
||||
<circle id="Ellipse_14" data-name="Ellipse 14" cx="2" cy="2" r="2" transform="translate(180 265.962)" fill="#f2f2f2"/>
|
||||
<circle id="Ellipse_15" data-name="Ellipse 15" cx="2" cy="2" r="2" transform="translate(612 96.962)" fill="#f2f2f2"/>
|
||||
<circle id="Ellipse_16" data-name="Ellipse 16" cx="2" cy="2" r="2" transform="translate(736 192.962)" fill="#f2f2f2"/>
|
||||
<circle id="Ellipse_17" data-name="Ellipse 17" cx="2" cy="2" r="2" transform="translate(858 344.962)" fill="#f2f2f2"/>
|
||||
<path id="Path_89" data-name="Path 89" d="M306,121.222h-2.76v-2.76h-1.48v2.76H299V122.7h2.76v2.759h1.48V122.7H306Z" fill="#f2f2f2"/>
|
||||
<path id="Path_90" data-name="Path 90" d="M848,424.222h-2.76v-2.76h-1.48v2.76H841V425.7h2.76v2.759h1.48V425.7H848Z" fill="#f2f2f2"/>
|
||||
<path id="Path_91" data-name="Path 91" d="M1144,719.981c0,16.569-243.557,74-544,74s-544-57.431-544-74,243.557,14,544,14S1144,703.413,1144,719.981Z" transform="translate(-56 -106.019)" fill="#3f3d56"/>
|
||||
<path id="Path_92" data-name="Path 92" d="M1144,719.981c0,16.569-243.557,74-544,74s-544-57.431-544-74,243.557,14,544,14S1144,703.413,1144,719.981Z" transform="translate(-56 -106.019)" opacity="0.1"/>
|
||||
<ellipse id="Ellipse_18" data-name="Ellipse 18" cx="544" cy="30" rx="544" ry="30" transform="translate(0 583.962)" fill="#3f3d56"/>
|
||||
<path id="Path_93" data-name="Path 93" d="M624,677.981c0,33.137-14.775,24-33,24s-33,9.137-33-24,33-96,33-96S624,644.844,624,677.981Z" transform="translate(-56 -106.019)" fill="#ff6584"/>
|
||||
<path id="Path_94" data-name="Path 94" d="M606,690.66c0,15.062-6.716,10.909-15,10.909s-15,4.153-15-10.909,15-43.636,15-43.636S606,675.6,606,690.66Z" transform="translate(-56 -106.019)" opacity="0.1"/>
|
||||
<rect id="Rectangle_97" data-name="Rectangle 97" width="92" height="18" rx="9" transform="translate(489 604.962)" fill="#2f2e41"/>
|
||||
<rect id="Rectangle_98" data-name="Rectangle 98" width="92" height="18" rx="9" transform="translate(489 586.962)" fill="#2f2e41"/>
|
||||
<path id="Path_95" data-name="Path 95" d="M193,596.547c0,55.343,34.719,100.126,77.626,100.126" transform="translate(-56 -106.019)" fill="#3f3d56"/>
|
||||
<path id="Path_96" data-name="Path 96" d="M270.626,696.673c0-55.965,38.745-101.251,86.626-101.251" transform="translate(-56 -106.019)" fill="#6c63ff"/>
|
||||
<path id="Path_97" data-name="Path 97" d="M221.125,601.564c0,52.57,22.14,95.109,49.5,95.109" transform="translate(-56 -106.019)" fill="#6c63ff"/>
|
||||
<path id="Path_98" data-name="Path 98" d="M270.626,696.673c0-71.511,44.783-129.377,100.126-129.377" transform="translate(-56 -106.019)" fill="#3f3d56"/>
|
||||
<path id="Path_99" data-name="Path 99" d="M254.3,697.379s11.009-.339,14.326-2.7,16.934-5.183,17.757-1.395,16.544,18.844,4.115,18.945-28.879-1.936-32.19-3.953S254.3,697.379,254.3,697.379Z" transform="translate(-56 -106.019)" fill="#a8a8a8"/>
|
||||
<path id="Path_100" data-name="Path 100" d="M290.716,710.909c-12.429.1-28.879-1.936-32.19-3.953-2.522-1.536-3.527-7.048-3.863-9.591l-.368.014s.7,8.879,4.009,10.9,19.761,4.053,32.19,3.953c3.588-.029,4.827-1.305,4.759-3.2C294.755,710.174,293.386,710.887,290.716,710.909Z" transform="translate(-56 -106.019)" opacity="0.2"/>
|
||||
<path id="Path_101" data-name="Path 101" d="M777.429,633.081c0,38.029,23.857,68.8,53.341,68.8" transform="translate(-56 -106.019)" fill="#3f3d56"/>
|
||||
<path id="Path_102" data-name="Path 102" d="M830.769,701.882c0-38.456,26.623-69.575,59.525-69.575" transform="translate(-56 -106.019)" fill="#6c63ff"/>
|
||||
<path id="Path_103" data-name="Path 103" d="M796.755,636.528c0,36.124,15.213,65.354,34.014,65.354" transform="translate(-56 -106.019)" fill="#6c63ff"/>
|
||||
<path id="Path_104" data-name="Path 104" d="M830.769,701.882c0-49.139,30.773-88.9,68.8-88.9" transform="translate(-56 -106.019)" fill="#3f3d56"/>
|
||||
<path id="Path_105" data-name="Path 105" d="M819.548,702.367s7.565-.233,9.844-1.856,11.636-3.562,12.2-.958,11.368,12.949,2.828,13.018-19.844-1.33-22.119-2.716S819.548,702.367,819.548,702.367Z" transform="translate(-56 -106.019)" fill="#a8a8a8"/>
|
||||
<path id="Path_106" data-name="Path 106" d="M844.574,711.664c-8.54.069-19.844-1.33-22.119-2.716-1.733-1.056-2.423-4.843-2.654-6.59l-.253.01s.479,6.1,2.755,7.487,13.579,2.785,22.119,2.716c2.465-.02,3.317-.9,3.27-2.2C847.349,711.159,846.409,711.649,844.574,711.664Z" transform="translate(-56 -106.019)" opacity="0.2"/>
|
||||
<path id="Path_107" data-name="Path 107" d="M949.813,724.718s11.36-1.729,14.5-4.591,16.89-7.488,18.217-3.667,19.494,17.447,6.633,19.107-30.153,1.609-33.835-.065S949.813,724.718,949.813,724.718Z" transform="translate(-56 -106.019)" fill="#a8a8a8"/>
|
||||
<path id="Path_108" data-name="Path 108" d="M989.228,734.173c-12.86,1.659-30.153,1.609-33.835-.065-2.8-1.275-4.535-6.858-5.2-9.45l-.379.061s1.833,9.109,5.516,10.783,20.975,1.725,33.835.065c3.712-.479,4.836-1.956,4.529-3.906C993.319,732.907,991.991,733.817,989.228,734.173Z" transform="translate(-56 -106.019)" opacity="0.2"/>
|
||||
<path id="Path_109" data-name="Path 109" d="M670.26,723.9s9.587-1.459,12.237-3.875,14.255-6.32,15.374-3.095,16.452,14.725,5.6,16.125-25.448,1.358-28.555-.055S670.26,723.9,670.26,723.9Z" transform="translate(-56 -106.019)" fill="#a8a8a8"/>
|
||||
<path id="Path_110" data-name="Path 110" d="M703.524,731.875c-10.853,1.4-25.448,1.358-28.555-.055-2.367-1.076-3.827-5.788-4.39-7.976l-.32.051s1.547,7.687,4.655,9.1,17.7,1.456,28.555.055c3.133-.4,4.081-1.651,3.822-3.3C706.977,730.807,705.856,731.575,703.524,731.875Z" transform="translate(-56 -106.019)" opacity="0.2"/>
|
||||
<path id="Path_111" data-name="Path 111" d="M178.389,719.109s7.463-1.136,9.527-3.016,11.1-4.92,11.969-2.409,12.808,11.463,4.358,12.553-19.811,1.057-22.23-.043S178.389,719.109,178.389,719.109Z" transform="translate(-56 -106.019)" fill="#a8a8a8"/>
|
||||
<path id="Path_112" data-name="Path 112" d="M204.285,725.321c-8.449,1.09-19.811,1.057-22.23-.043-1.842-.838-2.979-4.506-3.417-6.209l-.249.04s1.2,5.984,3.624,7.085,13.781,1.133,22.23.043c2.439-.315,3.177-1.285,2.976-2.566C206.973,724.489,206.1,725.087,204.285,725.321Z" transform="translate(-56 -106.019)" opacity="0.2"/>
|
||||
<path id="Path_113" data-name="Path 113" d="M439.7,707.337c0,30.22-42.124,20.873-93.7,20.873s-93.074,9.347-93.074-20.873,42.118-36.793,93.694-36.793S439.7,677.117,439.7,707.337Z" transform="translate(-56 -106.019)" opacity="0.1"/>
|
||||
<path id="Path_114" data-name="Path 114" d="M439.7,699.9c0,30.22-42.124,20.873-93.7,20.873s-93.074,9.347-93.074-20.873S295.04,663.1,346.616,663.1,439.7,669.676,439.7,699.9Z" transform="translate(-56 -106.019)" fill="#3f3d56"/>
|
||||
</g>
|
||||
<g id="docusaurus_keytar" transform="translate(312.271 493.733)">
|
||||
<path id="Path_40" data-name="Path 40" d="M99,52h91.791V89.153H99Z" transform="translate(5.904 -14.001)" fill="#fff" fill-rule="evenodd"/>
|
||||
<path id="Path_41" data-name="Path 41" d="M24.855,163.927A21.828,21.828,0,0,1,5.947,153a21.829,21.829,0,0,0,18.908,32.782H46.71V163.927Z" transform="translate(-3 -4.634)" fill="#3ecc5f" fill-rule="evenodd"/>
|
||||
<path id="Path_42" data-name="Path 42" d="M121.861,61.1l76.514-4.782V45.39A21.854,21.854,0,0,0,176.52,23.535H78.173L75.441,18.8a3.154,3.154,0,0,0-5.464,0l-2.732,4.732L64.513,18.8a3.154,3.154,0,0,0-5.464,0l-2.732,4.732L53.586,18.8a3.154,3.154,0,0,0-5.464,0L45.39,23.535c-.024,0-.046,0-.071,0l-4.526-4.525a3.153,3.153,0,0,0-5.276,1.414l-1.5,5.577-5.674-1.521a3.154,3.154,0,0,0-3.863,3.864L26,34.023l-5.575,1.494a3.155,3.155,0,0,0-1.416,5.278l4.526,4.526c0,.023,0,.046,0,.07L18.8,48.122a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,59.05a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,69.977a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,80.9a3.154,3.154,0,0,0,0,5.464L23.535,89.1,18.8,91.832a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,102.76a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,113.687a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,124.615a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,135.542a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,146.469a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,157.4a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,168.324a3.154,3.154,0,0,0,0,5.464l4.732,2.732A21.854,21.854,0,0,0,45.39,198.375H176.52a21.854,21.854,0,0,0,21.855-21.855V89.1l-76.514-4.782a11.632,11.632,0,0,1,0-23.219" transform="translate(-1.681 -17.226)" fill="#3ecc5f" fill-rule="evenodd"/>
|
||||
<path id="Path_43" data-name="Path 43" d="M143,186.71h32.782V143H143Z" transform="translate(9.984 -5.561)" fill="#3ecc5f" fill-rule="evenodd"/>
|
||||
<path id="Path_44" data-name="Path 44" d="M196.71,159.855a5.438,5.438,0,0,0-.7.07c-.042-.164-.081-.329-.127-.493a5.457,5.457,0,1,0-5.4-9.372q-.181-.185-.366-.367a5.454,5.454,0,1,0-9.384-5.4c-.162-.046-.325-.084-.486-.126a5.467,5.467,0,1,0-10.788,0c-.162.042-.325.08-.486.126a5.457,5.457,0,1,0-9.384,5.4,21.843,21.843,0,1,0,36.421,21.02,5.452,5.452,0,1,0,.7-10.858" transform="translate(10.912 -6.025)" fill="#44d860" fill-rule="evenodd"/>
|
||||
<path id="Path_45" data-name="Path 45" d="M153,124.855h32.782V103H153Z" transform="translate(10.912 -9.271)" fill="#3ecc5f" fill-rule="evenodd"/>
|
||||
<path id="Path_46" data-name="Path 46" d="M194.855,116.765a2.732,2.732,0,1,0,0-5.464,2.811,2.811,0,0,0-.349.035c-.022-.082-.04-.164-.063-.246a2.733,2.733,0,0,0-1.052-5.253,2.7,2.7,0,0,0-1.648.566q-.09-.093-.184-.184a2.7,2.7,0,0,0,.553-1.633,2.732,2.732,0,0,0-5.245-1.07,10.928,10.928,0,1,0,0,21.031,2.732,2.732,0,0,0,5.245-1.07,2.7,2.7,0,0,0-.553-1.633q.093-.09.184-.184a2.7,2.7,0,0,0,1.648.566,2.732,2.732,0,0,0,1.052-5.253c.023-.081.042-.164.063-.246a2.814,2.814,0,0,0,.349.035" transform="translate(12.767 -9.377)" fill="#44d860" fill-rule="evenodd"/>
|
||||
<path id="Path_47" data-name="Path 47" d="M65.087,56.891a2.732,2.732,0,0,1-2.732-2.732,8.2,8.2,0,0,0-16.391,0,2.732,2.732,0,0,1-5.464,0,13.659,13.659,0,0,1,27.319,0,2.732,2.732,0,0,1-2.732,2.732" transform="translate(0.478 -15.068)" fill-rule="evenodd"/>
|
||||
<path id="Path_48" data-name="Path 48" d="M103,191.347h65.565a21.854,21.854,0,0,0,21.855-21.855V93H124.855A21.854,21.854,0,0,0,103,114.855Z" transform="translate(6.275 -10.199)" fill="#ffff50" fill-rule="evenodd"/>
|
||||
<path id="Path_49" data-name="Path 49" d="M173.216,129.787H118.535a1.093,1.093,0,1,1,0-2.185h54.681a1.093,1.093,0,0,1,0,2.185m0,21.855H118.535a1.093,1.093,0,1,1,0-2.186h54.681a1.093,1.093,0,0,1,0,2.186m0,21.855H118.535a1.093,1.093,0,1,1,0-2.185h54.681a1.093,1.093,0,0,1,0,2.185m0-54.434H118.535a1.093,1.093,0,1,1,0-2.185h54.681a1.093,1.093,0,0,1,0,2.185m0,21.652H118.535a1.093,1.093,0,1,1,0-2.186h54.681a1.093,1.093,0,0,1,0,2.186m0,21.855H118.535a1.093,1.093,0,1,1,0-2.186h54.681a1.093,1.093,0,0,1,0,2.186M189.585,61.611c-.013,0-.024-.007-.037-.005-3.377.115-4.974,3.492-6.384,6.472-1.471,3.114-2.608,5.139-4.473,5.078-2.064-.074-3.244-2.406-4.494-4.874-1.436-2.835-3.075-6.049-6.516-5.929-3.329.114-4.932,3.053-6.346,5.646-1.5,2.762-2.529,4.442-4.5,4.364-2.106-.076-3.225-1.972-4.52-4.167-1.444-2.443-3.112-5.191-6.487-5.1-3.272.113-4.879,2.606-6.3,4.808-1.5,2.328-2.552,3.746-4.551,3.662-2.156-.076-3.27-1.65-4.558-3.472-1.447-2.047-3.077-4.363-6.442-4.251-3.2.109-4.807,2.153-6.224,3.954-1.346,1.709-2.4,3.062-4.621,2.977a1.093,1.093,0,0,0-.079,2.186c3.3.11,4.967-1.967,6.417-3.81,1.286-1.635,2.4-3.045,4.582-3.12,2.1-.09,3.091,1.218,4.584,3.327,1.417,2,3.026,4.277,6.263,4.394,3.391.114,5.022-2.42,6.467-4.663,1.292-2,2.406-3.734,4.535-3.807,1.959-.073,3.026,1.475,4.529,4.022,1.417,2.4,3.023,5.121,6.324,5.241,3.415.118,5.064-2.863,6.5-5.5,1.245-2.282,2.419-4.437,4.5-4.509,1.959-.046,2.981,1.743,4.492,4.732,1.412,2.79,3.013,5.95,6.365,6.071l.185,0c3.348,0,4.937-3.36,6.343-6.331,1.245-2.634,2.423-5.114,4.444-5.216Z" transform="translate(7.109 -13.11)" fill-rule="evenodd"/>
|
||||
<path id="Path_50" data-name="Path 50" d="M83,186.71h43.71V143H83Z" transform="translate(4.42 -5.561)" fill="#3ecc5f" fill-rule="evenodd"/>
|
||||
<g id="Group_8" data-name="Group 8" transform="matrix(0.966, -0.259, 0.259, 0.966, 109.327, 91.085)">
|
||||
<rect id="Rectangle_3" data-name="Rectangle 3" width="92.361" height="36.462" rx="2" transform="translate(0 0)" fill="#d8d8d8"/>
|
||||
<g id="Group_2" data-name="Group 2" transform="translate(1.531 23.03)">
|
||||
<rect id="Rectangle_4" data-name="Rectangle 4" width="5.336" height="5.336" rx="1" transform="translate(16.797 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_5" data-name="Rectangle 5" width="5.336" height="5.336" rx="1" transform="translate(23.12 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_6" data-name="Rectangle 6" width="5.336" height="5.336" rx="1" transform="translate(29.444 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_7" data-name="Rectangle 7" width="5.336" height="5.336" rx="1" transform="translate(35.768 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_8" data-name="Rectangle 8" width="5.336" height="5.336" rx="1" transform="translate(42.091 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_9" data-name="Rectangle 9" width="5.336" height="5.336" rx="1" transform="translate(48.415 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_10" data-name="Rectangle 10" width="5.336" height="5.336" rx="1" transform="translate(54.739 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_11" data-name="Rectangle 11" width="5.336" height="5.336" rx="1" transform="translate(61.063 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_12" data-name="Rectangle 12" width="5.336" height="5.336" rx="1" transform="translate(67.386 0)" fill="#4a4a4a"/>
|
||||
<path id="Path_51" data-name="Path 51" d="M1.093,0H14.518a1.093,1.093,0,0,1,1.093,1.093V4.243a1.093,1.093,0,0,1-1.093,1.093H1.093A1.093,1.093,0,0,1,0,4.243V1.093A1.093,1.093,0,0,1,1.093,0ZM75,0H88.426a1.093,1.093,0,0,1,1.093,1.093V4.243a1.093,1.093,0,0,1-1.093,1.093H75a1.093,1.093,0,0,1-1.093-1.093V1.093A1.093,1.093,0,0,1,75,0Z" transform="translate(0 0)" fill="#4a4a4a" fill-rule="evenodd"/>
|
||||
</g>
|
||||
<g id="Group_3" data-name="Group 3" transform="translate(1.531 10.261)">
|
||||
<path id="Path_52" data-name="Path 52" d="M1.093,0H6.218A1.093,1.093,0,0,1,7.31,1.093V4.242A1.093,1.093,0,0,1,6.218,5.335H1.093A1.093,1.093,0,0,1,0,4.242V1.093A1.093,1.093,0,0,1,1.093,0Z" transform="translate(0 0)" fill="#4a4a4a" fill-rule="evenodd"/>
|
||||
<rect id="Rectangle_13" data-name="Rectangle 13" width="5.336" height="5.336" rx="1" transform="translate(8.299 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_14" data-name="Rectangle 14" width="5.336" height="5.336" rx="1" transform="translate(14.623 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_15" data-name="Rectangle 15" width="5.336" height="5.336" rx="1" transform="translate(20.947 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_16" data-name="Rectangle 16" width="5.336" height="5.336" rx="1" transform="translate(27.271 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_17" data-name="Rectangle 17" width="5.336" height="5.336" rx="1" transform="translate(33.594 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_18" data-name="Rectangle 18" width="5.336" height="5.336" rx="1" transform="translate(39.918 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_19" data-name="Rectangle 19" width="5.336" height="5.336" rx="1" transform="translate(46.242 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_20" data-name="Rectangle 20" width="5.336" height="5.336" rx="1" transform="translate(52.565 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_21" data-name="Rectangle 21" width="5.336" height="5.336" rx="1" transform="translate(58.888 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_22" data-name="Rectangle 22" width="5.336" height="5.336" rx="1" transform="translate(65.212 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_23" data-name="Rectangle 23" width="5.336" height="5.336" rx="1" transform="translate(71.536 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_24" data-name="Rectangle 24" width="5.336" height="5.336" rx="1" transform="translate(77.859 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_25" data-name="Rectangle 25" width="5.336" height="5.336" rx="1" transform="translate(84.183 0)" fill="#4a4a4a"/>
|
||||
</g>
|
||||
<g id="Group_4" data-name="Group 4" transform="translate(91.05 9.546) rotate(180)">
|
||||
<path id="Path_53" data-name="Path 53" d="M1.093,0H6.219A1.093,1.093,0,0,1,7.312,1.093v3.15A1.093,1.093,0,0,1,6.219,5.336H1.093A1.093,1.093,0,0,1,0,4.243V1.093A1.093,1.093,0,0,1,1.093,0Z" transform="translate(0 0)" fill="#4a4a4a" fill-rule="evenodd"/>
|
||||
<rect id="Rectangle_26" data-name="Rectangle 26" width="5.336" height="5.336" rx="1" transform="translate(8.299 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_27" data-name="Rectangle 27" width="5.336" height="5.336" rx="1" transform="translate(14.623 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_28" data-name="Rectangle 28" width="5.336" height="5.336" rx="1" transform="translate(20.947 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_29" data-name="Rectangle 29" width="5.336" height="5.336" rx="1" transform="translate(27.271 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_30" data-name="Rectangle 30" width="5.336" height="5.336" rx="1" transform="translate(33.594 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_31" data-name="Rectangle 31" width="5.336" height="5.336" rx="1" transform="translate(39.918 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_32" data-name="Rectangle 32" width="5.336" height="5.336" rx="1" transform="translate(46.242 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_33" data-name="Rectangle 33" width="5.336" height="5.336" rx="1" transform="translate(52.565 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_34" data-name="Rectangle 34" width="5.336" height="5.336" rx="1" transform="translate(58.889 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_35" data-name="Rectangle 35" width="5.336" height="5.336" rx="1" transform="translate(65.213 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_36" data-name="Rectangle 36" width="5.336" height="5.336" rx="1" transform="translate(71.537 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_37" data-name="Rectangle 37" width="5.336" height="5.336" rx="1" transform="translate(77.86 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_38" data-name="Rectangle 38" width="5.336" height="5.336" rx="1" transform="translate(84.183 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_39" data-name="Rectangle 39" width="5.336" height="5.336" rx="1" transform="translate(8.299 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_40" data-name="Rectangle 40" width="5.336" height="5.336" rx="1" transform="translate(14.623 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_41" data-name="Rectangle 41" width="5.336" height="5.336" rx="1" transform="translate(20.947 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_42" data-name="Rectangle 42" width="5.336" height="5.336" rx="1" transform="translate(27.271 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_43" data-name="Rectangle 43" width="5.336" height="5.336" rx="1" transform="translate(33.594 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_44" data-name="Rectangle 44" width="5.336" height="5.336" rx="1" transform="translate(39.918 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_45" data-name="Rectangle 45" width="5.336" height="5.336" rx="1" transform="translate(46.242 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_46" data-name="Rectangle 46" width="5.336" height="5.336" rx="1" transform="translate(52.565 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_47" data-name="Rectangle 47" width="5.336" height="5.336" rx="1" transform="translate(58.889 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_48" data-name="Rectangle 48" width="5.336" height="5.336" rx="1" transform="translate(65.213 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_49" data-name="Rectangle 49" width="5.336" height="5.336" rx="1" transform="translate(71.537 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_50" data-name="Rectangle 50" width="5.336" height="5.336" rx="1" transform="translate(77.86 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_51" data-name="Rectangle 51" width="5.336" height="5.336" rx="1" transform="translate(84.183 0)" fill="#4a4a4a"/>
|
||||
</g>
|
||||
<g id="Group_6" data-name="Group 6" transform="translate(1.531 16.584)">
|
||||
<path id="Path_54" data-name="Path 54" d="M1.093,0h7.3A1.093,1.093,0,0,1,9.485,1.093v3.15A1.093,1.093,0,0,1,8.392,5.336h-7.3A1.093,1.093,0,0,1,0,4.243V1.094A1.093,1.093,0,0,1,1.093,0Z" transform="translate(0 0)" fill="#4a4a4a" fill-rule="evenodd"/>
|
||||
<g id="Group_5" data-name="Group 5" transform="translate(10.671 0)">
|
||||
<rect id="Rectangle_52" data-name="Rectangle 52" width="5.336" height="5.336" rx="1" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_53" data-name="Rectangle 53" width="5.336" height="5.336" rx="1" transform="translate(6.324 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_54" data-name="Rectangle 54" width="5.336" height="5.336" rx="1" transform="translate(12.647 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_55" data-name="Rectangle 55" width="5.336" height="5.336" rx="1" transform="translate(18.971 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_56" data-name="Rectangle 56" width="5.336" height="5.336" rx="1" transform="translate(25.295 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_57" data-name="Rectangle 57" width="5.336" height="5.336" rx="1" transform="translate(31.619 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_58" data-name="Rectangle 58" width="5.336" height="5.336" rx="1" transform="translate(37.942 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_59" data-name="Rectangle 59" width="5.336" height="5.336" rx="1" transform="translate(44.265 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_60" data-name="Rectangle 60" width="5.336" height="5.336" rx="1" transform="translate(50.589 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_61" data-name="Rectangle 61" width="5.336" height="5.336" rx="1" transform="translate(56.912 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_62" data-name="Rectangle 62" width="5.336" height="5.336" rx="1" transform="translate(63.236 0)" fill="#4a4a4a"/>
|
||||
</g>
|
||||
<path id="Path_55" data-name="Path 55" d="M1.094,0H8A1.093,1.093,0,0,1,9.091,1.093v3.15A1.093,1.093,0,0,1,8,5.336H1.093A1.093,1.093,0,0,1,0,4.243V1.094A1.093,1.093,0,0,1,1.093,0Z" transform="translate(80.428 0)" fill="#4a4a4a" fill-rule="evenodd"/>
|
||||
</g>
|
||||
<g id="Group_7" data-name="Group 7" transform="translate(1.531 29.627)">
|
||||
<rect id="Rectangle_63" data-name="Rectangle 63" width="5.336" height="5.336" rx="1" transform="translate(0 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_64" data-name="Rectangle 64" width="5.336" height="5.336" rx="1" transform="translate(6.324 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_65" data-name="Rectangle 65" width="5.336" height="5.336" rx="1" transform="translate(12.647 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_66" data-name="Rectangle 66" width="5.336" height="5.336" rx="1" transform="translate(18.971 0)" fill="#4a4a4a"/>
|
||||
<path id="Path_56" data-name="Path 56" d="M1.093,0H31.515a1.093,1.093,0,0,1,1.093,1.093V4.244a1.093,1.093,0,0,1-1.093,1.093H1.093A1.093,1.093,0,0,1,0,4.244V1.093A1.093,1.093,0,0,1,1.093,0ZM34.687,0h3.942a1.093,1.093,0,0,1,1.093,1.093V4.244a1.093,1.093,0,0,1-1.093,1.093H34.687a1.093,1.093,0,0,1-1.093-1.093V1.093A1.093,1.093,0,0,1,34.687,0Z" transform="translate(25.294 0)" fill="#4a4a4a" fill-rule="evenodd"/>
|
||||
<rect id="Rectangle_67" data-name="Rectangle 67" width="5.336" height="5.336" rx="1" transform="translate(66.003 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_68" data-name="Rectangle 68" width="5.336" height="5.336" rx="1" transform="translate(72.327 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_69" data-name="Rectangle 69" width="5.336" height="5.336" rx="1" transform="translate(84.183 0)" fill="#4a4a4a"/>
|
||||
<path id="Path_57" data-name="Path 57" d="M5.336,0V1.18A1.093,1.093,0,0,1,4.243,2.273H1.093A1.093,1.093,0,0,1,0,1.18V0Z" transform="translate(83.59 2.273) rotate(180)" fill="#4a4a4a"/>
|
||||
<path id="Path_58" data-name="Path 58" d="M5.336,0V1.18A1.093,1.093,0,0,1,4.243,2.273H1.093A1.093,1.093,0,0,1,0,1.18V0Z" transform="translate(78.255 3.063)" fill="#4a4a4a"/>
|
||||
</g>
|
||||
<rect id="Rectangle_70" data-name="Rectangle 70" width="88.927" height="2.371" rx="1.085" transform="translate(1.925 1.17)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_71" data-name="Rectangle 71" width="4.986" height="1.581" rx="0.723" transform="translate(4.1 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_72" data-name="Rectangle 72" width="4.986" height="1.581" rx="0.723" transform="translate(10.923 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_73" data-name="Rectangle 73" width="4.986" height="1.581" rx="0.723" transform="translate(16.173 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_74" data-name="Rectangle 74" width="4.986" height="1.581" rx="0.723" transform="translate(21.421 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_75" data-name="Rectangle 75" width="4.986" height="1.581" rx="0.723" transform="translate(26.671 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_76" data-name="Rectangle 76" width="4.986" height="1.581" rx="0.723" transform="translate(33.232 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_77" data-name="Rectangle 77" width="4.986" height="1.581" rx="0.723" transform="translate(38.48 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_78" data-name="Rectangle 78" width="4.986" height="1.581" rx="0.723" transform="translate(43.73 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_79" data-name="Rectangle 79" width="4.986" height="1.581" rx="0.723" transform="translate(48.978 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_80" data-name="Rectangle 80" width="4.986" height="1.581" rx="0.723" transform="translate(55.54 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_81" data-name="Rectangle 81" width="4.986" height="1.581" rx="0.723" transform="translate(60.788 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_82" data-name="Rectangle 82" width="4.986" height="1.581" rx="0.723" transform="translate(66.038 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_83" data-name="Rectangle 83" width="4.986" height="1.581" rx="0.723" transform="translate(72.599 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_84" data-name="Rectangle 84" width="4.986" height="1.581" rx="0.723" transform="translate(77.847 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_85" data-name="Rectangle 85" width="4.986" height="1.581" rx="0.723" transform="translate(83.097 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
||||
</g>
|
||||
<path id="Path_59" data-name="Path 59" d="M146.71,159.855a5.439,5.439,0,0,0-.7.07c-.042-.164-.081-.329-.127-.493a5.457,5.457,0,1,0-5.4-9.372q-.181-.185-.366-.367a5.454,5.454,0,1,0-9.384-5.4c-.162-.046-.325-.084-.486-.126a5.467,5.467,0,1,0-10.788,0c-.162.042-.325.08-.486.126a5.457,5.457,0,1,0-9.384,5.4,21.843,21.843,0,1,0,36.421,21.02,5.452,5.452,0,1,0,.7-10.858" transform="translate(6.275 -6.025)" fill="#44d860" fill-rule="evenodd"/>
|
||||
<path id="Path_60" data-name="Path 60" d="M83,124.855h43.71V103H83Z" transform="translate(4.42 -9.271)" fill="#3ecc5f" fill-rule="evenodd"/>
|
||||
<path id="Path_61" data-name="Path 61" d="M134.855,116.765a2.732,2.732,0,1,0,0-5.464,2.811,2.811,0,0,0-.349.035c-.022-.082-.04-.164-.063-.246a2.733,2.733,0,0,0-1.052-5.253,2.7,2.7,0,0,0-1.648.566q-.09-.093-.184-.184a2.7,2.7,0,0,0,.553-1.633,2.732,2.732,0,0,0-5.245-1.07,10.928,10.928,0,1,0,0,21.031,2.732,2.732,0,0,0,5.245-1.07,2.7,2.7,0,0,0-.553-1.633q.093-.09.184-.184a2.7,2.7,0,0,0,1.648.566,2.732,2.732,0,0,0,1.052-5.253c.023-.081.042-.164.063-.246a2.811,2.811,0,0,0,.349.035" transform="translate(7.202 -9.377)" fill="#44d860" fill-rule="evenodd"/>
|
||||
<path id="Path_62" data-name="Path 62" d="M143.232,42.33a2.967,2.967,0,0,1-.535-.055,2.754,2.754,0,0,1-.514-.153,2.838,2.838,0,0,1-.471-.251,4.139,4.139,0,0,1-.415-.339,3.2,3.2,0,0,1-.338-.415A2.7,2.7,0,0,1,140.5,39.6a2.968,2.968,0,0,1,.055-.535,3.152,3.152,0,0,1,.152-.514,2.874,2.874,0,0,1,.252-.47,2.633,2.633,0,0,1,.753-.754,2.837,2.837,0,0,1,.471-.251,2.753,2.753,0,0,1,.514-.153,2.527,2.527,0,0,1,1.071,0,2.654,2.654,0,0,1,.983.4,4.139,4.139,0,0,1,.415.339,4.019,4.019,0,0,1,.339.415,2.786,2.786,0,0,1,.251.47,2.864,2.864,0,0,1,.208,1.049,2.77,2.77,0,0,1-.8,1.934,4.139,4.139,0,0,1-.415.339,2.722,2.722,0,0,1-1.519.459m21.855-1.366a2.789,2.789,0,0,1-1.935-.8,4.162,4.162,0,0,1-.338-.415,2.7,2.7,0,0,1-.459-1.519,2.789,2.789,0,0,1,.8-1.934,4.139,4.139,0,0,1,.415-.339,2.838,2.838,0,0,1,.471-.251,2.752,2.752,0,0,1,.514-.153,2.527,2.527,0,0,1,1.071,0,2.654,2.654,0,0,1,.983.4,4.139,4.139,0,0,1,.415.339,2.79,2.79,0,0,1,.8,1.934,3.069,3.069,0,0,1-.055.535,2.779,2.779,0,0,1-.153.514,3.885,3.885,0,0,1-.251.47,4.02,4.02,0,0,1-.339.415,4.138,4.138,0,0,1-.415.339,2.722,2.722,0,0,1-1.519.459" transform="translate(9.753 -15.532)" fill-rule="evenodd"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 31 KiB |
170
build/docs/static/img/undraw_docusaurus_react.svg
vendored
Normal file
@ -0,0 +1,170 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1041.277" height="554.141" viewBox="0 0 1041.277 554.141">
|
||||
<title>Powered by React</title>
|
||||
<g id="Group_24" data-name="Group 24" transform="translate(-440 -263)">
|
||||
<g id="Group_23" data-name="Group 23" transform="translate(439.989 262.965)">
|
||||
<path id="Path_299" data-name="Path 299" d="M1040.82,611.12q-1.74,3.75-3.47,7.4-2.7,5.67-5.33,11.12c-.78,1.61-1.56,3.19-2.32,4.77-8.6,17.57-16.63,33.11-23.45,45.89A73.21,73.21,0,0,1,942.44,719l-151.65,1.65h-1.6l-13,.14-11.12.12-34.1.37h-1.38l-17.36.19h-.53l-107,1.16-95.51,1-11.11.12-69,.75H429l-44.75.48h-.48l-141.5,1.53-42.33.46a87.991,87.991,0,0,1-10.79-.54h0c-1.22-.14-2.44-.3-3.65-.49a87.38,87.38,0,0,1-51.29-27.54C116,678.37,102.75,655,93.85,629.64q-1.93-5.49-3.6-11.12C59.44,514.37,97,380,164.6,290.08q4.25-5.64,8.64-11l.07-.08c20.79-25.52,44.1-46.84,68.93-62,44-26.91,92.75-34.49,140.7-11.9,40.57,19.12,78.45,28.11,115.17,30.55,3.71.24,7.42.42,11.11.53,84.23,2.65,163.17-27.7,255.87-47.29,3.69-.78,7.39-1.55,11.12-2.28,66.13-13.16,139.49-20.1,226.73-5.51a189.089,189.089,0,0,1,26.76,6.4q5.77,1.86,11.12,4c41.64,16.94,64.35,48.24,74,87.46q1.37,5.46,2.37,11.11C1134.3,384.41,1084.19,518.23,1040.82,611.12Z" transform="translate(-79.34 -172.91)" fill="#f2f2f2"/>
|
||||
<path id="Path_300" data-name="Path 300" d="M576.36,618.52a95.21,95.21,0,0,1-1.87,11.12h93.7V618.52Zm-78.25,62.81,11.11-.09V653.77c-3.81-.17-7.52-.34-11.11-.52ZM265.19,618.52v11.12h198.5V618.52ZM1114.87,279h-74V191.51q-5.35-2.17-11.12-4V279H776.21V186.58c-3.73.73-7.43,1.5-11.12,2.28V279H509.22V236.15c-3.69-.11-7.4-.29-11.11-.53V279H242.24V217c-24.83,15.16-48.14,36.48-68.93,62h-.07v.08q-4.4,5.4-8.64,11h8.64V618.52h-83q1.66,5.63,3.6,11.12h79.39v93.62a87,87,0,0,0,12.2,2.79c1.21.19,2.43.35,3.65.49h0a87.991,87.991,0,0,0,10.79.54l42.33-.46v-97H498.11v94.21l11.11-.12V629.64H765.09V721l11.12-.12V629.64H1029.7v4.77c.76-1.58,1.54-3.16,2.32-4.77q2.63-5.45,5.33-11.12,1.73-3.64,3.47-7.4v-321h76.42Q1116.23,284.43,1114.87,279ZM242.24,618.52V290.08H498.11V618.52Zm267,0V290.08H765.09V618.52Zm520.48,0H776.21V290.08H1029.7Z" transform="translate(-79.34 -172.91)" opacity="0.1"/>
|
||||
<path id="Path_301" data-name="Path 301" d="M863.09,533.65v13l-151.92,1.4-1.62.03-57.74.53-1.38.02-17.55.15h-.52l-106.98.99L349.77,551.4h-.15l-44.65.42-.48.01-198.4,1.82v-15l46.65-28,93.6-.78,2-.01.66-.01,2-.03,44.94-.37,2.01-.01.64-.01,2-.01L315,509.3l.38-.01,35.55-.3h.29l277.4-2.34,6.79-.05h.68l5.18-.05,37.65-.31,2-.03,1.85-.02h.96l11.71-.09,2.32-.03,3.11-.02,9.75-.09,15.47-.13,2-.02,3.48-.02h.65l74.71-.64Z" fill="#65617d"/>
|
||||
<path id="Path_302" data-name="Path 302" d="M863.09,533.65v13l-151.92,1.4-1.62.03-57.74.53-1.38.02-17.55.15h-.52l-106.98.99L349.77,551.4h-.15l-44.65.42-.48.01-198.4,1.82v-15l46.65-28,93.6-.78,2-.01.66-.01,2-.03,44.94-.37,2.01-.01.64-.01,2-.01L315,509.3l.38-.01,35.55-.3h.29l277.4-2.34,6.79-.05h.68l5.18-.05,37.65-.31,2-.03,1.85-.02h.96l11.71-.09,2.32-.03,3.11-.02,9.75-.09,15.47-.13,2-.02,3.48-.02h.65l74.71-.64Z" opacity="0.2"/>
|
||||
<path id="Path_303" data-name="Path 303" d="M375.44,656.57v24.49a6.13,6.13,0,0,1-3.5,5.54,6,6,0,0,1-2.5.6l-34.9.74a6,6,0,0,1-2.7-.57,6.12,6.12,0,0,1-3.57-5.57V656.57Z" transform="translate(-79.34 -172.91)" fill="#3f3d56"/>
|
||||
<path id="Path_304" data-name="Path 304" d="M375.44,656.57v24.49a6.13,6.13,0,0,1-3.5,5.54,6,6,0,0,1-2.5.6l-34.9.74a6,6,0,0,1-2.7-.57,6.12,6.12,0,0,1-3.57-5.57V656.57Z" transform="translate(-79.34 -172.91)" opacity="0.1"/>
|
||||
<path id="Path_305" data-name="Path 305" d="M377.44,656.57v24.49a6.13,6.13,0,0,1-3.5,5.54,6,6,0,0,1-2.5.6l-34.9.74a6,6,0,0,1-2.7-.57,6.12,6.12,0,0,1-3.57-5.57V656.57Z" transform="translate(-79.34 -172.91)" fill="#3f3d56"/>
|
||||
<rect id="Rectangle_137" data-name="Rectangle 137" width="47.17" height="31.5" transform="translate(680.92 483.65)" fill="#3f3d56"/>
|
||||
<rect id="Rectangle_138" data-name="Rectangle 138" width="47.17" height="31.5" transform="translate(680.92 483.65)" opacity="0.1"/>
|
||||
<rect id="Rectangle_139" data-name="Rectangle 139" width="47.17" height="31.5" transform="translate(678.92 483.65)" fill="#3f3d56"/>
|
||||
<path id="Path_306" data-name="Path 306" d="M298.09,483.65v4.97l-47.17,1.26v-6.23Z" opacity="0.1"/>
|
||||
<path id="Path_307" data-name="Path 307" d="M460.69,485.27v168.2a4,4,0,0,1-3.85,3.95l-191.65,5.1h-.05a4,4,0,0,1-3.95-3.95V485.27a4,4,0,0,1,3.95-3.95h191.6a4,4,0,0,1,3.95,3.95Z" transform="translate(-79.34 -172.91)" fill="#65617d"/>
|
||||
<path id="Path_308" data-name="Path 308" d="M265.19,481.32v181.2h-.05a4,4,0,0,1-3.95-3.95V485.27a4,4,0,0,1,3.95-3.95Z" transform="translate(-79.34 -172.91)" opacity="0.1"/>
|
||||
<path id="Path_309" data-name="Path 309" d="M194.59,319.15h177.5V467.4l-177.5,4Z" fill="#39374d"/>
|
||||
<path id="Path_310" data-name="Path 310" d="M726.09,483.65v6.41l-47.17-1.26v-5.15Z" opacity="0.1"/>
|
||||
<path id="Path_311" data-name="Path 311" d="M867.69,485.27v173.3a4,4,0,0,1-4,3.95h0L672,657.42a4,4,0,0,1-3.85-3.95V485.27a4,4,0,0,1,3.95-3.95H863.7a4,4,0,0,1,3.99,3.95Z" transform="translate(-79.34 -172.91)" fill="#65617d"/>
|
||||
<path id="Path_312" data-name="Path 312" d="M867.69,485.27v173.3a4,4,0,0,1-4,3.95h0V481.32h0a4,4,0,0,1,4,3.95Z" transform="translate(-79.34 -172.91)" opacity="0.1"/>
|
||||
<path id="Path_313" data-name="Path 313" d="M775.59,319.15H598.09V467.4l177.5,4Z" fill="#39374d"/>
|
||||
<path id="Path_314" data-name="Path 314" d="M663.19,485.27v168.2a4,4,0,0,1-3.85,3.95l-191.65,5.1h0a4,4,0,0,1-4-3.95V485.27a4,4,0,0,1,3.95-3.95h191.6A4,4,0,0,1,663.19,485.27Z" transform="translate(-79.34 -172.91)" fill="#65617d"/>
|
||||
<path id="Path_315" data-name="Path 315" d="M397.09,319.15h177.5V467.4l-177.5,4Z" fill="#4267b2"/>
|
||||
<path id="Path_316" data-name="Path 316" d="M863.09,533.65v13l-151.92,1.4-1.62.03-57.74.53-1.38.02-17.55.15h-.52l-106.98.99L349.77,551.4h-.15l-44.65.42-.48.01-198.4,1.82v-15l202.51-1.33h.48l40.99-.28h.19l283.08-1.87h.29l.17-.01h.47l4.79-.03h1.46l74.49-.5,4.4-.02.98-.01Z" opacity="0.1"/>
|
||||
<circle id="Ellipse_111" data-name="Ellipse 111" cx="51.33" cy="51.33" r="51.33" transform="translate(435.93 246.82)" fill="#fbbebe"/>
|
||||
<path id="Path_317" data-name="Path 317" d="M617.94,550.07s-99.5,12-90,0c3.44-4.34,4.39-17.2,4.2-31.85-.06-4.45-.22-9.06-.45-13.65-1.1-22-3.75-43.5-3.75-43.5s87-41,77-8.5c-4,13.13-2.69,31.57.35,48.88.89,5.05,1.92,10,3,14.7a344.66,344.66,0,0,0,9.65,33.92Z" transform="translate(-79.34 -172.91)" fill="#fbbebe"/>
|
||||
<path id="Path_318" data-name="Path 318" d="M585.47,546c11.51-2.13,23.7-6,34.53-1.54,2.85,1.17,5.47,2.88,8.39,3.86s6.12,1.22,9.16,1.91c10.68,2.42,19.34,10.55,24.9,20s8.44,20.14,11.26,30.72l6.9,25.83c6,22.45,12,45.09,13.39,68.3a2437.506,2437.506,0,0,1-250.84,1.43c5.44-10.34,11-21.31,10.54-33s-7.19-23.22-4.76-34.74c1.55-7.34,6.57-13.39,9.64-20.22,8.75-19.52,1.94-45.79,17.32-60.65,6.92-6.68,17-9.21,26.63-8.89,12.28.41,24.85,4.24,37,6.11C555.09,547.48,569.79,548.88,585.47,546Z" transform="translate(-79.34 -172.91)" fill="#ff6584"/>
|
||||
<path id="Path_319" data-name="Path 319" d="M716.37,657.17l-.1,1.43v.1l-.17,2.3-1.33,18.51-1.61,22.3-.46,6.28-1,13.44v.17l-107,1-175.59,1.9v.84h-.14v-1.12l.45-14.36.86-28.06.74-23.79.07-2.37a10.53,10.53,0,0,1,11.42-10.17c4.72.4,10.85.89,18.18,1.41l3,.22c42.33,2.94,120.56,6.74,199.5,2,1.66-.09,3.33-.19,5-.31,12.24-.77,24.47-1.76,36.58-3a10.53,10.53,0,0,1,11.6,11.23Z" transform="translate(-79.34 -172.91)" opacity="0.1"/>
|
||||
<path id="Path_320" data-name="Path 320" d="M429.08,725.44v-.84l175.62-1.91,107-1h.3v-.17l1-13.44.43-6,1.64-22.61,1.29-17.9v-.44a10.617,10.617,0,0,0-.11-2.47.3.3,0,0,0,0-.1,10.391,10.391,0,0,0-2-4.64,10.54,10.54,0,0,0-9.42-4c-12.11,1.24-24.34,2.23-36.58,3-1.67.12-3.34.22-5,.31-78.94,4.69-157.17.89-199.5-2l-3-.22c-7.33-.52-13.46-1-18.18-1.41a10.54,10.54,0,0,0-11.24,8.53,11,11,0,0,0-.18,1.64l-.68,22.16L429.54,710l-.44,14.36v1.12Z" transform="translate(-79.34 -172.91)" fill="#3f3d56"/>
|
||||
<path id="Path_321" data-name="Path 321" d="M716.67,664.18l-1.23,15.33-1.83,22.85-.46,5.72-1,12.81-.06.64v.17h0l-.15,1.48.11-1.48h-.29l-107,1-175.65,1.9v-.28l.49-14.36,1-28.06.64-18.65A6.36,6.36,0,0,1,434.3,658a6.25,6.25,0,0,1,3.78-.9c2.1.17,4.68.37,7.69.59,4.89.36,10.92.78,17.94,1.22,13,.82,29.31,1.7,48,2.42,52,2,122.2,2.67,188.88-3.17,3-.26,6.1-.55,9.13-.84a6.26,6.26,0,0,1,3.48.66,5.159,5.159,0,0,1,.86.54,6.14,6.14,0,0,1,2,2.46,3.564,3.564,0,0,1,.25.61A6.279,6.279,0,0,1,716.67,664.18Z" transform="translate(-79.34 -172.91)" opacity="0.1"/>
|
||||
<path id="Path_322" data-name="Path 322" d="M377.44,677.87v3.19a6.13,6.13,0,0,1-3.5,5.54l-40.1.77a6.12,6.12,0,0,1-3.57-5.57v-3Z" transform="translate(-79.34 -172.91)" opacity="0.1"/>
|
||||
<path id="Path_323" data-name="Path 323" d="M298.59,515.57l-52.25,1V507.9l52.25-1Z" fill="#3f3d56"/>
|
||||
<path id="Path_324" data-name="Path 324" d="M298.59,515.57l-52.25,1V507.9l52.25-1Z" opacity="0.1"/>
|
||||
<path id="Path_325" data-name="Path 325" d="M300.59,515.57l-52.25,1V507.9l52.25-1Z" fill="#3f3d56"/>
|
||||
<path id="Path_326" data-name="Path 326" d="M758.56,679.87v3.19a6.13,6.13,0,0,0,3.5,5.54l40.1.77a6.12,6.12,0,0,0,3.57-5.57v-3Z" transform="translate(-79.34 -172.91)" opacity="0.1"/>
|
||||
<path id="Path_327" data-name="Path 327" d="M678.72,517.57l52.25,1V509.9l-52.25-1Z" opacity="0.1"/>
|
||||
<path id="Path_328" data-name="Path 328" d="M676.72,517.57l52.25,1V509.9l-52.25-1Z" fill="#3f3d56"/>
|
||||
<path id="Path_329" data-name="Path 329" d="M534.13,486.79c.08,7-3.16,13.6-5.91,20.07a163.491,163.491,0,0,0-12.66,74.71c.73,11,2.58,22,.73,32.9s-8.43,21.77-19,24.9c17.53,10.45,41.26,9.35,57.76-2.66,8.79-6.4,15.34-15.33,21.75-24.11a97.86,97.86,0,0,1-13.31,44.75A103.43,103.43,0,0,0,637,616.53c4.31-5.81,8.06-12.19,9.72-19.23,3.09-13-1.22-26.51-4.51-39.5a266.055,266.055,0,0,1-6.17-33c-.43-3.56-.78-7.22.1-10.7,1-4.07,3.67-7.51,5.64-11.22,5.6-10.54,5.73-23.3,2.86-34.88s-8.49-22.26-14.06-32.81c-4.46-8.46-9.3-17.31-17.46-22.28-5.1-3.1-11-4.39-16.88-5.64l-25.37-5.43c-5.55-1.19-11.26-2.38-16.87-1.51-9.47,1.48-16.14,8.32-22,15.34-4.59,5.46-15.81,15.71-16.6,22.86-.72,6.59,5.1,17.63,6.09,24.58,1.3,9,2.22,6,7.3,11.52C532,478.05,534.07,482,534.13,486.79Z" transform="translate(-79.34 -172.91)" fill="#3f3d56"/>
|
||||
</g>
|
||||
<g id="docusaurus_keytar" transform="translate(670.271 615.768)">
|
||||
<path id="Path_40" data-name="Path 40" d="M99,52h43.635V69.662H99Z" transform="translate(-49.132 -33.936)" fill="#fff" fill-rule="evenodd"/>
|
||||
<path id="Path_41" data-name="Path 41" d="M13.389,158.195A10.377,10.377,0,0,1,4.4,153a10.377,10.377,0,0,0,8.988,15.584H23.779V158.195Z" transform="translate(-3 -82.47)" fill="#3ecc5f" fill-rule="evenodd"/>
|
||||
<path id="Path_42" data-name="Path 42" d="M66.967,38.083l36.373-2.273V30.615A10.389,10.389,0,0,0,92.95,20.226H46.2l-1.3-2.249a1.5,1.5,0,0,0-2.6,0L41,20.226l-1.3-2.249a1.5,1.5,0,0,0-2.6,0l-1.3,2.249-1.3-2.249a1.5,1.5,0,0,0-2.6,0l-1.3,2.249-.034,0-2.152-2.151a1.5,1.5,0,0,0-2.508.672L25.21,21.4l-2.7-.723a1.5,1.5,0,0,0-1.836,1.837l.722,2.7-2.65.71a1.5,1.5,0,0,0-.673,2.509l2.152,2.152c0,.011,0,.022,0,.033l-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6L20.226,41l-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3A10.389,10.389,0,0,0,30.615,103.34H92.95A10.389,10.389,0,0,0,103.34,92.95V51.393L66.967,49.12a5.53,5.53,0,0,1,0-11.038" transform="translate(-9.836 -17.226)" fill="#3ecc5f" fill-rule="evenodd"/>
|
||||
<path id="Path_43" data-name="Path 43" d="M143,163.779h15.584V143H143Z" transform="translate(-70.275 -77.665)" fill="#3ecc5f" fill-rule="evenodd"/>
|
||||
<path id="Path_44" data-name="Path 44" d="M173.779,148.389a2.582,2.582,0,0,0-.332.033c-.02-.078-.038-.156-.06-.234a2.594,2.594,0,1,0-2.567-4.455q-.086-.088-.174-.175a2.593,2.593,0,1,0-4.461-2.569c-.077-.022-.154-.04-.231-.06a2.6,2.6,0,1,0-5.128,0c-.077.02-.154.038-.231.06a2.594,2.594,0,1,0-4.461,2.569,10.384,10.384,0,1,0,17.314,9.992,2.592,2.592,0,1,0,.332-5.161" transform="translate(-75.08 -75.262)" fill="#44d860" fill-rule="evenodd"/>
|
||||
<path id="Path_45" data-name="Path 45" d="M153,113.389h15.584V103H153Z" transform="translate(-75.08 -58.444)" fill="#3ecc5f" fill-rule="evenodd"/>
|
||||
<path id="Path_46" data-name="Path 46" d="M183.389,108.944a1.3,1.3,0,1,0,0-2.6,1.336,1.336,0,0,0-.166.017c-.01-.039-.019-.078-.03-.117a1.3,1.3,0,0,0-.5-2.5,1.285,1.285,0,0,0-.783.269q-.043-.044-.087-.087a1.285,1.285,0,0,0,.263-.776,1.3,1.3,0,0,0-2.493-.509,5.195,5.195,0,1,0,0,10,1.3,1.3,0,0,0,2.493-.509,1.285,1.285,0,0,0-.263-.776q.044-.043.087-.087a1.285,1.285,0,0,0,.783.269,1.3,1.3,0,0,0,.5-2.5c.011-.038.02-.078.03-.117a1.337,1.337,0,0,0,.166.017" transform="translate(-84.691 -57.894)" fill="#44d860" fill-rule="evenodd"/>
|
||||
<path id="Path_47" data-name="Path 47" d="M52.188,48.292a1.3,1.3,0,0,1-1.3-1.3,3.9,3.9,0,0,0-7.792,0,1.3,1.3,0,1,1-2.6,0,6.493,6.493,0,0,1,12.987,0,1.3,1.3,0,0,1-1.3,1.3" transform="translate(-21.02 -28.41)" fill-rule="evenodd"/>
|
||||
<path id="Path_48" data-name="Path 48" d="M103,139.752h31.168a10.389,10.389,0,0,0,10.389-10.389V93H113.389A10.389,10.389,0,0,0,103,103.389Z" transform="translate(-51.054 -53.638)" fill="#ffff50" fill-rule="evenodd"/>
|
||||
<path id="Path_49" data-name="Path 49" d="M141.1,94.017H115.106a.519.519,0,1,1,0-1.039H141.1a.519.519,0,0,1,0,1.039m0,10.389H115.106a.519.519,0,1,1,0-1.039H141.1a.519.519,0,0,1,0,1.039m0,10.389H115.106a.519.519,0,1,1,0-1.039H141.1a.519.519,0,0,1,0,1.039m0-25.877H115.106a.519.519,0,1,1,0-1.039H141.1a.519.519,0,0,1,0,1.039m0,10.293H115.106a.519.519,0,1,1,0-1.039H141.1a.519.519,0,0,1,0,1.039m0,10.389H115.106a.519.519,0,1,1,0-1.039H141.1a.519.519,0,0,1,0,1.039m7.782-47.993c-.006,0-.011,0-.018,0-1.605.055-2.365,1.66-3.035,3.077-.7,1.48-1.24,2.443-2.126,2.414-.981-.035-1.542-1.144-2.137-2.317-.683-1.347-1.462-2.876-3.1-2.819-1.582.054-2.344,1.451-3.017,2.684-.715,1.313-1.2,2.112-2.141,2.075-1-.036-1.533-.938-2.149-1.981-.686-1.162-1.479-2.467-3.084-2.423-1.555.053-2.319,1.239-2.994,2.286-.713,1.106-1.213,1.781-2.164,1.741-1.025-.036-1.554-.784-2.167-1.65-.688-.973-1.463-2.074-3.062-2.021a3.815,3.815,0,0,0-2.959,1.879c-.64.812-1.14,1.456-2.2,1.415a.52.52,0,0,0-.037,1.039,3.588,3.588,0,0,0,3.05-1.811c.611-.777,1.139-1.448,2.178-1.483,1-.043,1.47.579,2.179,1.582.674.953,1.438,2.033,2.977,2.089,1.612.054,2.387-1.151,3.074-2.217.614-.953,1.144-1.775,2.156-1.81.931-.035,1.438.7,2.153,1.912.674,1.141,1.437,2.434,3.006,2.491,1.623.056,2.407-1.361,3.09-2.616.592-1.085,1.15-2.109,2.14-2.143.931-.022,1.417.829,2.135,2.249.671,1.326,1.432,2.828,3.026,2.886l.088,0c1.592,0,2.347-1.6,3.015-3.01.592-1.252,1.152-2.431,2.113-2.479Z" transform="translate(-55.378 -38.552)" fill-rule="evenodd"/>
|
||||
<path id="Path_50" data-name="Path 50" d="M83,163.779h20.779V143H83Z" transform="translate(-41.443 -77.665)" fill="#3ecc5f" fill-rule="evenodd"/>
|
||||
<g id="Group_8" data-name="Group 8" transform="matrix(0.966, -0.259, 0.259, 0.966, 51.971, 43.3)">
|
||||
<rect id="Rectangle_3" data-name="Rectangle 3" width="43.906" height="17.333" rx="2" transform="translate(0 0)" fill="#d8d8d8"/>
|
||||
<g id="Group_2" data-name="Group 2" transform="translate(0.728 10.948)">
|
||||
<rect id="Rectangle_4" data-name="Rectangle 4" width="2.537" height="2.537" rx="1" transform="translate(7.985 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_5" data-name="Rectangle 5" width="2.537" height="2.537" rx="1" transform="translate(10.991 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_6" data-name="Rectangle 6" width="2.537" height="2.537" rx="1" transform="translate(13.997 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_7" data-name="Rectangle 7" width="2.537" height="2.537" rx="1" transform="translate(17.003 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_8" data-name="Rectangle 8" width="2.537" height="2.537" rx="1" transform="translate(20.009 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_9" data-name="Rectangle 9" width="2.537" height="2.537" rx="1" transform="translate(23.015 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_10" data-name="Rectangle 10" width="2.537" height="2.537" rx="1" transform="translate(26.021 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_11" data-name="Rectangle 11" width="2.537" height="2.537" rx="1" transform="translate(29.028 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_12" data-name="Rectangle 12" width="2.537" height="2.537" rx="1" transform="translate(32.034 0)" fill="#4a4a4a"/>
|
||||
<path id="Path_51" data-name="Path 51" d="M.519,0H6.9A.519.519,0,0,1,7.421.52v1.5a.519.519,0,0,1-.519.519H.519A.519.519,0,0,1,0,2.017V.519A.519.519,0,0,1,.519,0ZM35.653,0h6.383a.519.519,0,0,1,.519.519v1.5a.519.519,0,0,1-.519.519H35.652a.519.519,0,0,1-.519-.519V.519A.519.519,0,0,1,35.652,0Z" transform="translate(0 0)" fill="#4a4a4a" fill-rule="evenodd"/>
|
||||
</g>
|
||||
<g id="Group_3" data-name="Group 3" transform="translate(0.728 4.878)">
|
||||
<path id="Path_52" data-name="Path 52" d="M.519,0H2.956a.519.519,0,0,1,.519.519v1.5a.519.519,0,0,1-.519.519H.519A.519.519,0,0,1,0,2.017V.519A.519.519,0,0,1,.519,0Z" transform="translate(0 0)" fill="#4a4a4a" fill-rule="evenodd"/>
|
||||
<rect id="Rectangle_13" data-name="Rectangle 13" width="2.537" height="2.537" rx="1" transform="translate(3.945 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_14" data-name="Rectangle 14" width="2.537" height="2.537" rx="1" transform="translate(6.951 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_15" data-name="Rectangle 15" width="2.537" height="2.537" rx="1" transform="translate(9.958 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_16" data-name="Rectangle 16" width="2.537" height="2.537" rx="1" transform="translate(12.964 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_17" data-name="Rectangle 17" width="2.537" height="2.537" rx="1" transform="translate(15.97 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_18" data-name="Rectangle 18" width="2.537" height="2.537" rx="1" transform="translate(18.976 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_19" data-name="Rectangle 19" width="2.537" height="2.537" rx="1" transform="translate(21.982 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_20" data-name="Rectangle 20" width="2.537" height="2.537" rx="1" transform="translate(24.988 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_21" data-name="Rectangle 21" width="2.537" height="2.537" rx="1" transform="translate(27.994 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_22" data-name="Rectangle 22" width="2.537" height="2.537" rx="1" transform="translate(31 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_23" data-name="Rectangle 23" width="2.537" height="2.537" rx="1" transform="translate(34.006 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_24" data-name="Rectangle 24" width="2.537" height="2.537" rx="1" transform="translate(37.012 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_25" data-name="Rectangle 25" width="2.537" height="2.537" rx="1" transform="translate(40.018 0)" fill="#4a4a4a"/>
|
||||
</g>
|
||||
<g id="Group_4" data-name="Group 4" transform="translate(43.283 4.538) rotate(180)">
|
||||
<path id="Path_53" data-name="Path 53" d="M.519,0H2.956a.519.519,0,0,1,.519.519v1.5a.519.519,0,0,1-.519.519H.519A.519.519,0,0,1,0,2.017V.519A.519.519,0,0,1,.519,0Z" transform="translate(0 0)" fill="#4a4a4a" fill-rule="evenodd"/>
|
||||
<rect id="Rectangle_26" data-name="Rectangle 26" width="2.537" height="2.537" rx="1" transform="translate(3.945 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_27" data-name="Rectangle 27" width="2.537" height="2.537" rx="1" transform="translate(6.951 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_28" data-name="Rectangle 28" width="2.537" height="2.537" rx="1" transform="translate(9.958 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_29" data-name="Rectangle 29" width="2.537" height="2.537" rx="1" transform="translate(12.964 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_30" data-name="Rectangle 30" width="2.537" height="2.537" rx="1" transform="translate(15.97 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_31" data-name="Rectangle 31" width="2.537" height="2.537" rx="1" transform="translate(18.976 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_32" data-name="Rectangle 32" width="2.537" height="2.537" rx="1" transform="translate(21.982 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_33" data-name="Rectangle 33" width="2.537" height="2.537" rx="1" transform="translate(24.988 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_34" data-name="Rectangle 34" width="2.537" height="2.537" rx="1" transform="translate(27.994 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_35" data-name="Rectangle 35" width="2.537" height="2.537" rx="1" transform="translate(31.001 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_36" data-name="Rectangle 36" width="2.537" height="2.537" rx="1" transform="translate(34.007 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_37" data-name="Rectangle 37" width="2.537" height="2.537" rx="1" transform="translate(37.013 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_38" data-name="Rectangle 38" width="2.537" height="2.537" rx="1" transform="translate(40.018 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_39" data-name="Rectangle 39" width="2.537" height="2.537" rx="1" transform="translate(3.945 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_40" data-name="Rectangle 40" width="2.537" height="2.537" rx="1" transform="translate(6.951 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_41" data-name="Rectangle 41" width="2.537" height="2.537" rx="1" transform="translate(9.958 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_42" data-name="Rectangle 42" width="2.537" height="2.537" rx="1" transform="translate(12.964 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_43" data-name="Rectangle 43" width="2.537" height="2.537" rx="1" transform="translate(15.97 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_44" data-name="Rectangle 44" width="2.537" height="2.537" rx="1" transform="translate(18.976 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_45" data-name="Rectangle 45" width="2.537" height="2.537" rx="1" transform="translate(21.982 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_46" data-name="Rectangle 46" width="2.537" height="2.537" rx="1" transform="translate(24.988 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_47" data-name="Rectangle 47" width="2.537" height="2.537" rx="1" transform="translate(27.994 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_48" data-name="Rectangle 48" width="2.537" height="2.537" rx="1" transform="translate(31.001 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_49" data-name="Rectangle 49" width="2.537" height="2.537" rx="1" transform="translate(34.007 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_50" data-name="Rectangle 50" width="2.537" height="2.537" rx="1" transform="translate(37.013 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_51" data-name="Rectangle 51" width="2.537" height="2.537" rx="1" transform="translate(40.018 0)" fill="#4a4a4a"/>
|
||||
</g>
|
||||
<g id="Group_6" data-name="Group 6" transform="translate(0.728 7.883)">
|
||||
<path id="Path_54" data-name="Path 54" d="M.519,0h3.47a.519.519,0,0,1,.519.519v1.5a.519.519,0,0,1-.519.519H.519A.519.519,0,0,1,0,2.017V.52A.519.519,0,0,1,.519,0Z" transform="translate(0 0)" fill="#4a4a4a" fill-rule="evenodd"/>
|
||||
<g id="Group_5" data-name="Group 5" transform="translate(5.073 0)">
|
||||
<rect id="Rectangle_52" data-name="Rectangle 52" width="2.537" height="2.537" rx="1" transform="translate(0 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_53" data-name="Rectangle 53" width="2.537" height="2.537" rx="1" transform="translate(3.006 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_54" data-name="Rectangle 54" width="2.537" height="2.537" rx="1" transform="translate(6.012 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_55" data-name="Rectangle 55" width="2.537" height="2.537" rx="1" transform="translate(9.018 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_56" data-name="Rectangle 56" width="2.537" height="2.537" rx="1" transform="translate(12.025 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_57" data-name="Rectangle 57" width="2.537" height="2.537" rx="1" transform="translate(15.031 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_58" data-name="Rectangle 58" width="2.537" height="2.537" rx="1" transform="translate(18.037 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_59" data-name="Rectangle 59" width="2.537" height="2.537" rx="1" transform="translate(21.042 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_60" data-name="Rectangle 60" width="2.537" height="2.537" rx="1" transform="translate(24.049 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_61" data-name="Rectangle 61" width="2.537" height="2.537" rx="1" transform="translate(27.055 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_62" data-name="Rectangle 62" width="2.537" height="2.537" rx="1" transform="translate(30.061 0)" fill="#4a4a4a"/>
|
||||
</g>
|
||||
<path id="Path_55" data-name="Path 55" d="M.52,0H3.8a.519.519,0,0,1,.519.519v1.5a.519.519,0,0,1-.519.519H.519A.519.519,0,0,1,0,2.017V.52A.519.519,0,0,1,.519,0Z" transform="translate(38.234 0)" fill="#4a4a4a" fill-rule="evenodd"/>
|
||||
</g>
|
||||
<g id="Group_7" data-name="Group 7" transform="translate(0.728 14.084)">
|
||||
<rect id="Rectangle_63" data-name="Rectangle 63" width="2.537" height="2.537" rx="1" transform="translate(0 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_64" data-name="Rectangle 64" width="2.537" height="2.537" rx="1" transform="translate(3.006 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_65" data-name="Rectangle 65" width="2.537" height="2.537" rx="1" transform="translate(6.012 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_66" data-name="Rectangle 66" width="2.537" height="2.537" rx="1" transform="translate(9.018 0)" fill="#4a4a4a"/>
|
||||
<path id="Path_56" data-name="Path 56" d="M.519,0H14.981A.519.519,0,0,1,15.5.519v1.5a.519.519,0,0,1-.519.519H.519A.519.519,0,0,1,0,2.018V.519A.519.519,0,0,1,.519,0Zm15.97,0h1.874a.519.519,0,0,1,.519.519v1.5a.519.519,0,0,1-.519.519H16.489a.519.519,0,0,1-.519-.519V.519A.519.519,0,0,1,16.489,0Z" transform="translate(12.024 0)" fill="#4a4a4a" fill-rule="evenodd"/>
|
||||
<rect id="Rectangle_67" data-name="Rectangle 67" width="2.537" height="2.537" rx="1" transform="translate(31.376 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_68" data-name="Rectangle 68" width="2.537" height="2.537" rx="1" transform="translate(34.382 0)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_69" data-name="Rectangle 69" width="2.537" height="2.537" rx="1" transform="translate(40.018 0)" fill="#4a4a4a"/>
|
||||
<path id="Path_57" data-name="Path 57" d="M2.537,0V.561a.519.519,0,0,1-.519.519H.519A.519.519,0,0,1,0,.561V0Z" transform="translate(39.736 1.08) rotate(180)" fill="#4a4a4a"/>
|
||||
<path id="Path_58" data-name="Path 58" d="M2.537,0V.561a.519.519,0,0,1-.519.519H.519A.519.519,0,0,1,0,.561V0Z" transform="translate(37.2 1.456)" fill="#4a4a4a"/>
|
||||
</g>
|
||||
<rect id="Rectangle_70" data-name="Rectangle 70" width="42.273" height="1.127" rx="0.564" transform="translate(0.915 0.556)" fill="#4a4a4a"/>
|
||||
<rect id="Rectangle_71" data-name="Rectangle 71" width="2.37" height="0.752" rx="0.376" transform="translate(1.949 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_72" data-name="Rectangle 72" width="2.37" height="0.752" rx="0.376" transform="translate(5.193 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_73" data-name="Rectangle 73" width="2.37" height="0.752" rx="0.376" transform="translate(7.688 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_74" data-name="Rectangle 74" width="2.37" height="0.752" rx="0.376" transform="translate(10.183 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_75" data-name="Rectangle 75" width="2.37" height="0.752" rx="0.376" transform="translate(12.679 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_76" data-name="Rectangle 76" width="2.37" height="0.752" rx="0.376" transform="translate(15.797 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_77" data-name="Rectangle 77" width="2.37" height="0.752" rx="0.376" transform="translate(18.292 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_78" data-name="Rectangle 78" width="2.37" height="0.752" rx="0.376" transform="translate(20.788 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_79" data-name="Rectangle 79" width="2.37" height="0.752" rx="0.376" transform="translate(23.283 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_80" data-name="Rectangle 80" width="2.37" height="0.752" rx="0.376" transform="translate(26.402 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_81" data-name="Rectangle 81" width="2.37" height="0.752" rx="0.376" transform="translate(28.897 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_82" data-name="Rectangle 82" width="2.37" height="0.752" rx="0.376" transform="translate(31.393 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_83" data-name="Rectangle 83" width="2.37" height="0.752" rx="0.376" transform="translate(34.512 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_84" data-name="Rectangle 84" width="2.37" height="0.752" rx="0.376" transform="translate(37.007 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
||||
<rect id="Rectangle_85" data-name="Rectangle 85" width="2.37" height="0.752" rx="0.376" transform="translate(39.502 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
||||
</g>
|
||||
<path id="Path_59" data-name="Path 59" d="M123.779,148.389a2.583,2.583,0,0,0-.332.033c-.02-.078-.038-.156-.06-.234a2.594,2.594,0,1,0-2.567-4.455q-.086-.088-.174-.175a2.593,2.593,0,1,0-4.461-2.569c-.077-.022-.154-.04-.231-.06a2.6,2.6,0,1,0-5.128,0c-.077.02-.154.038-.231.06a2.594,2.594,0,1,0-4.461,2.569,10.384,10.384,0,1,0,17.314,9.992,2.592,2.592,0,1,0,.332-5.161" transform="translate(-51.054 -75.262)" fill="#44d860" fill-rule="evenodd"/>
|
||||
<path id="Path_60" data-name="Path 60" d="M83,113.389h20.779V103H83Z" transform="translate(-41.443 -58.444)" fill="#3ecc5f" fill-rule="evenodd"/>
|
||||
<path id="Path_61" data-name="Path 61" d="M123.389,108.944a1.3,1.3,0,1,0,0-2.6,1.338,1.338,0,0,0-.166.017c-.01-.039-.019-.078-.03-.117a1.3,1.3,0,0,0-.5-2.5,1.285,1.285,0,0,0-.783.269q-.043-.044-.087-.087a1.285,1.285,0,0,0,.263-.776,1.3,1.3,0,0,0-2.493-.509,5.195,5.195,0,1,0,0,10,1.3,1.3,0,0,0,2.493-.509,1.285,1.285,0,0,0-.263-.776q.044-.043.087-.087a1.285,1.285,0,0,0,.783.269,1.3,1.3,0,0,0,.5-2.5c.011-.038.02-.078.03-.117a1.335,1.335,0,0,0,.166.017" transform="translate(-55.859 -57.894)" fill="#44d860" fill-rule="evenodd"/>
|
||||
<path id="Path_62" data-name="Path 62" d="M141.8,38.745a1.41,1.41,0,0,1-.255-.026,1.309,1.309,0,0,1-.244-.073,1.349,1.349,0,0,1-.224-.119,1.967,1.967,0,0,1-.2-.161,1.52,1.52,0,0,1-.161-.2,1.282,1.282,0,0,1-.218-.722,1.41,1.41,0,0,1,.026-.255,1.5,1.5,0,0,1,.072-.244,1.364,1.364,0,0,1,.12-.223,1.252,1.252,0,0,1,.358-.358,1.349,1.349,0,0,1,.224-.119,1.309,1.309,0,0,1,.244-.073,1.2,1.2,0,0,1,.509,0,1.262,1.262,0,0,1,.468.192,1.968,1.968,0,0,1,.2.161,1.908,1.908,0,0,1,.161.2,1.322,1.322,0,0,1,.12.223,1.361,1.361,0,0,1,.1.5,1.317,1.317,0,0,1-.379.919,1.968,1.968,0,0,1-.2.161,1.346,1.346,0,0,1-.223.119,1.332,1.332,0,0,1-.5.1m10.389-.649a1.326,1.326,0,0,1-.92-.379,1.979,1.979,0,0,1-.161-.2,1.282,1.282,0,0,1-.218-.722,1.326,1.326,0,0,1,.379-.919,1.967,1.967,0,0,1,.2-.161,1.351,1.351,0,0,1,.224-.119,1.308,1.308,0,0,1,.244-.073,1.2,1.2,0,0,1,.509,0,1.262,1.262,0,0,1,.468.192,1.967,1.967,0,0,1,.2.161,1.326,1.326,0,0,1,.379.919,1.461,1.461,0,0,1-.026.255,1.323,1.323,0,0,1-.073.244,1.847,1.847,0,0,1-.119.223,1.911,1.911,0,0,1-.161.2,1.967,1.967,0,0,1-.2.161,1.294,1.294,0,0,1-.722.218" transform="translate(-69.074 -26.006)" fill-rule="evenodd"/>
|
||||
</g>
|
||||
<g id="React-icon" transform="translate(906.3 541.56)">
|
||||
<path id="Path_330" data-name="Path 330" d="M263.668,117.179c0-5.827-7.3-11.35-18.487-14.775,2.582-11.4,1.434-20.477-3.622-23.382a7.861,7.861,0,0,0-4.016-1v4a4.152,4.152,0,0,1,2.044.466c2.439,1.4,3.5,6.724,2.672,13.574-.2,1.685-.52,3.461-.914,5.272a86.9,86.9,0,0,0-11.386-1.954,87.469,87.469,0,0,0-7.459-8.965c5.845-5.433,11.332-8.41,15.062-8.41V78h0c-4.931,0-11.386,3.514-17.913,9.611-6.527-6.061-12.982-9.539-17.913-9.539v4c3.712,0,9.216,2.959,15.062,8.356a84.687,84.687,0,0,0-7.405,8.947,83.732,83.732,0,0,0-11.4,1.972c-.412-1.793-.717-3.532-.932-5.2-.843-6.85.2-12.175,2.618-13.592a3.991,3.991,0,0,1,2.062-.466v-4h0a8,8,0,0,0-4.052,1c-5.039,2.9-6.168,11.96-3.568,23.328-11.153,3.443-18.415,8.947-18.415,14.757,0,5.828,7.3,11.35,18.487,14.775-2.582,11.4-1.434,20.477,3.622,23.382a7.882,7.882,0,0,0,4.034,1c4.931,0,11.386-3.514,17.913-9.611,6.527,6.061,12.982,9.539,17.913,9.539a8,8,0,0,0,4.052-1c5.039-2.9,6.168-11.96,3.568-23.328C256.406,128.511,263.668,122.988,263.668,117.179Zm-23.346-11.96c-.663,2.313-1.488,4.7-2.421,7.083-.735-1.434-1.506-2.869-2.349-4.3-.825-1.434-1.7-2.833-2.582-4.2C235.517,104.179,237.974,104.645,240.323,105.219Zm-8.212,19.1c-1.4,2.421-2.833,4.716-4.321,6.85-2.672.233-5.379.359-8.1.359-2.708,0-5.415-.126-8.069-.341q-2.232-3.2-4.339-6.814-2.044-3.523-3.73-7.136c1.112-2.4,2.367-4.805,3.712-7.154,1.4-2.421,2.833-4.716,4.321-6.85,2.672-.233,5.379-.359,8.1-.359,2.708,0,5.415.126,8.069.341q2.232,3.2,4.339,6.814,2.044,3.523,3.73,7.136C234.692,119.564,233.455,121.966,232.11,124.315Zm5.792-2.331c.968,2.4,1.793,4.805,2.474,7.136-2.349.574-4.823,1.058-7.387,1.434.879-1.381,1.757-2.8,2.582-4.25C236.4,124.871,237.167,123.419,237.9,121.984ZM219.72,141.116a73.921,73.921,0,0,1-4.985-5.738c1.614.072,3.263.126,4.931.126,1.685,0,3.353-.036,4.985-.126A69.993,69.993,0,0,1,219.72,141.116ZM206.38,130.555c-2.546-.377-5-.843-7.352-1.417.663-2.313,1.488-4.7,2.421-7.083.735,1.434,1.506,2.869,2.349,4.3S205.5,129.192,206.38,130.555ZM219.63,93.241a73.924,73.924,0,0,1,4.985,5.738c-1.614-.072-3.263-.126-4.931-.126-1.686,0-3.353.036-4.985.126A69.993,69.993,0,0,1,219.63,93.241ZM206.362,103.8c-.879,1.381-1.757,2.8-2.582,4.25-.825,1.434-1.6,2.869-2.331,4.3-.968-2.4-1.793-4.805-2.474-7.136C201.323,104.663,203.8,104.179,206.362,103.8Zm-16.227,22.449c-6.348-2.708-10.454-6.258-10.454-9.073s4.106-6.383,10.454-9.073c1.542-.663,3.228-1.255,4.967-1.811a86.122,86.122,0,0,0,4.034,10.92,84.9,84.9,0,0,0-3.981,10.866C193.38,127.525,191.694,126.915,190.134,126.252Zm9.647,25.623c-2.439-1.4-3.5-6.724-2.672-13.574.2-1.686.52-3.461.914-5.272a86.9,86.9,0,0,0,11.386,1.954,87.465,87.465,0,0,0,7.459,8.965c-5.845,5.433-11.332,8.41-15.062,8.41A4.279,4.279,0,0,1,199.781,151.875Zm42.532-13.663c.843,6.85-.2,12.175-2.618,13.592a3.99,3.99,0,0,1-2.062.466c-3.712,0-9.216-2.959-15.062-8.356a84.689,84.689,0,0,0,7.405-8.947,83.731,83.731,0,0,0,11.4-1.972A50.194,50.194,0,0,1,242.313,138.212Zm6.9-11.96c-1.542.663-3.228,1.255-4.967,1.811a86.12,86.12,0,0,0-4.034-10.92,84.9,84.9,0,0,0,3.981-10.866c1.775.556,3.461,1.165,5.039,1.829,6.348,2.708,10.454,6.258,10.454,9.073C259.67,119.994,255.564,123.562,249.216,126.252Z" fill="#61dafb"/>
|
||||
<path id="Path_331" data-name="Path 331" d="M320.8,78.4Z" transform="translate(-119.082 -0.328)" fill="#61dafb"/>
|
||||
<circle id="Ellipse_112" data-name="Ellipse 112" cx="8.194" cy="8.194" r="8.194" transform="translate(211.472 108.984)" fill="#61dafb"/>
|
||||
<path id="Path_332" data-name="Path 332" d="M520.5,78.1Z" transform="translate(-282.975 -0.082)" fill="#61dafb"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 35 KiB |
40
build/docs/static/img/undraw_docusaurus_tree.svg
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1129" height="663" viewBox="0 0 1129 663">
|
||||
<title>Focus on What Matters</title>
|
||||
<circle cx="321" cy="321" r="321" fill="#f2f2f2" />
|
||||
<ellipse cx="559" cy="635.49998" rx="514" ry="27.50002" fill="#3f3d56" />
|
||||
<ellipse cx="558" cy="627" rx="460" ry="22" opacity="0.2" />
|
||||
<rect x="131" y="152.5" width="840" height="50" fill="#3f3d56" />
|
||||
<path d="M166.5,727.3299A21.67009,21.67009,0,0,0,188.1701,749H984.8299A21.67009,21.67009,0,0,0,1006.5,727.3299V296h-840Z" transform="translate(-35.5 -118.5)" fill="#3f3d56" />
|
||||
<path d="M984.8299,236H188.1701A21.67009,21.67009,0,0,0,166.5,257.6701V296h840V257.6701A21.67009,21.67009,0,0,0,984.8299,236Z" transform="translate(-35.5 -118.5)" fill="#3f3d56" />
|
||||
<path d="M984.8299,236H188.1701A21.67009,21.67009,0,0,0,166.5,257.6701V296h840V257.6701A21.67009,21.67009,0,0,0,984.8299,236Z" transform="translate(-35.5 -118.5)" opacity="0.2" />
|
||||
<circle cx="181" cy="147.5" r="13" fill="#3f3d56" />
|
||||
<circle cx="217" cy="147.5" r="13" fill="#3f3d56" />
|
||||
<circle cx="253" cy="147.5" r="13" fill="#3f3d56" />
|
||||
<rect x="168" y="213.5" width="337" height="386" rx="5.33505" fill="#606060" />
|
||||
<rect x="603" y="272.5" width="284" height="22" rx="5.47638" fill="#2e8555" />
|
||||
<rect x="537" y="352.5" width="416" height="15" rx="5.47638" fill="#2e8555" />
|
||||
<rect x="537" y="396.5" width="416" height="15" rx="5.47638" fill="#2e8555" />
|
||||
<rect x="537" y="440.5" width="416" height="15" rx="5.47638" fill="#2e8555" />
|
||||
<rect x="537" y="484.5" width="416" height="15" rx="5.47638" fill="#2e8555" />
|
||||
<rect x="865" y="552.5" width="88" height="26" rx="7.02756" fill="#3ecc5f" />
|
||||
<path d="M1088.60287,624.61594a30.11371,30.11371,0,0,0,3.98291-15.266c0-13.79652-8.54358-24.98081-19.08256-24.98081s-19.08256,11.18429-19.08256,24.98081a30.11411,30.11411,0,0,0,3.98291,15.266,31.248,31.248,0,0,0,0,30.53213,31.248,31.248,0,0,0,0,30.53208,31.248,31.248,0,0,0,0,30.53208,30.11408,30.11408,0,0,0-3.98291,15.266c0,13.79652,8.54353,24.98081,19.08256,24.98081s19.08256-11.18429,19.08256-24.98081a30.11368,30.11368,0,0,0-3.98291-15.266,31.248,31.248,0,0,0,0-30.53208,31.248,31.248,0,0,0,0-30.53208,31.248,31.248,0,0,0,0-30.53213Z" transform="translate(-35.5 -118.5)" fill="#3f3d56" />
|
||||
<ellipse cx="1038.00321" cy="460.31783" rx="19.08256" ry="24.9808" fill="#3f3d56" />
|
||||
<ellipse cx="1038.00321" cy="429.78574" rx="19.08256" ry="24.9808" fill="#3f3d56" />
|
||||
<path d="M1144.93871,339.34489a91.61081,91.61081,0,0,0,7.10658-10.46092l-50.141-8.23491,54.22885.4033a91.566,91.566,0,0,0,1.74556-72.42605l-72.75449,37.74139,67.09658-49.32086a91.41255,91.41255,0,1,0-150.971,102.29805,91.45842,91.45842,0,0,0-10.42451,16.66946l65.0866,33.81447-69.40046-23.292a91.46011,91.46011,0,0,0,14.73837,85.83669,91.40575,91.40575,0,1,0,143.68892,0,91.41808,91.41808,0,0,0,0-113.02862Z" transform="translate(-35.5 -118.5)" fill="#3ecc5f" fill-rule="evenodd" />
|
||||
<path d="M981.6885,395.8592a91.01343,91.01343,0,0,0,19.56129,56.51431,91.40575,91.40575,0,1,0,143.68892,0C1157.18982,436.82067,981.6885,385.60008,981.6885,395.8592Z" transform="translate(-35.5 -118.5)" opacity="0.1" />
|
||||
<path d="M365.62,461.43628H477.094v45.12043H365.62Z" transform="translate(-35.5 -118.5)" fill="#fff" fill-rule="evenodd" />
|
||||
<path d="M264.76252,608.74122a26.50931,26.50931,0,0,1-22.96231-13.27072,26.50976,26.50976,0,0,0,22.96231,39.81215H291.304V608.74122Z" transform="translate(-35.5 -118.5)" fill="#3ecc5f" fill-rule="evenodd" />
|
||||
<path d="M384.17242,468.57061l92.92155-5.80726V449.49263a26.54091,26.54091,0,0,0-26.54143-26.54143H331.1161l-3.31768-5.74622a3.83043,3.83043,0,0,0-6.63536,0l-3.31768,5.74622-3.31767-5.74622a3.83043,3.83043,0,0,0-6.63536,0l-3.31768,5.74622L301.257,417.205a3.83043,3.83043,0,0,0-6.63536,0L291.304,422.9512c-.02919,0-.05573.004-.08625.004l-5.49674-5.49541a3.8293,3.8293,0,0,0-6.4071,1.71723l-1.81676,6.77338L270.607,424.1031a3.82993,3.82993,0,0,0-4.6912,4.69253l1.84463,6.89148-6.77072,1.81411a3.8315,3.8315,0,0,0-1.71988,6.40975l5.49673,5.49673c0,.02787-.004.05574-.004.08493l-5.74622,3.31768a3.83043,3.83043,0,0,0,0,6.63536l5.74621,3.31768L259.0163,466.081a3.83043,3.83043,0,0,0,0,6.63536l5.74622,3.31768-5.74622,3.31767a3.83043,3.83043,0,0,0,0,6.63536l5.74622,3.31768-5.74622,3.31768a3.83043,3.83043,0,0,0,0,6.63536l5.74622,3.31768-5.74622,3.31767a3.83043,3.83043,0,0,0,0,6.63536l5.74622,3.31768-5.74622,3.31768a3.83043,3.83043,0,0,0,0,6.63536l5.74622,3.31768-5.74622,3.31768a3.83042,3.83042,0,0,0,0,6.63535l5.74622,3.31768-5.74622,3.31768a3.83043,3.83043,0,0,0,0,6.63536l5.74622,3.31768L259.0163,558.976a3.83042,3.83042,0,0,0,0,6.63535l5.74622,3.31768-5.74622,3.31768a3.83043,3.83043,0,0,0,0,6.63536l5.74622,3.31768-5.74622,3.31768a3.83042,3.83042,0,0,0,0,6.63535l5.74622,3.31768-5.74622,3.31768a3.83043,3.83043,0,0,0,0,6.63536l5.74622,3.31768A26.54091,26.54091,0,0,0,291.304,635.28265H450.55254A26.5409,26.5409,0,0,0,477.094,608.74122V502.5755l-92.92155-5.80727a14.12639,14.12639,0,0,1,0-28.19762" transform="translate(-35.5 -118.5)" fill="#3ecc5f" fill-rule="evenodd" />
|
||||
<path d="M424.01111,635.28265h39.81214V582.19979H424.01111Z" transform="translate(-35.5 -118.5)" fill="#3ecc5f" fill-rule="evenodd" />
|
||||
<path d="M490.36468,602.10586a6.60242,6.60242,0,0,0-.848.08493c-.05042-.19906-.09821-.39945-.15393-.59852A6.62668,6.62668,0,1,0,482.80568,590.21q-.2203-.22491-.44457-.44589a6.62391,6.62391,0,1,0-11.39689-6.56369c-.1964-.05575-.39414-.10218-.59056-.15262a6.63957,6.63957,0,1,0-13.10086,0c-.1964.05042-.39414.09687-.59056.15262a6.62767,6.62767,0,1,0-11.39688,6.56369,26.52754,26.52754,0,1,0,44.23127,25.52756,6.6211,6.6211,0,1,0,.848-13.18579" transform="translate(-35.5 -118.5)" fill="#44d860" fill-rule="evenodd" />
|
||||
<path d="M437.28182,555.65836H477.094V529.11693H437.28182Z" transform="translate(-35.5 -118.5)" fill="#3ecc5f" fill-rule="evenodd" />
|
||||
<path d="M490.36468,545.70532a3.31768,3.31768,0,0,0,0-6.63536,3.41133,3.41133,0,0,0-.42333.04247c-.02655-.09953-.04911-.19907-.077-.29859a3.319,3.319,0,0,0-1.278-6.37923,3.28174,3.28174,0,0,0-2.00122.68742q-.10947-.11346-.22294-.22295a3.282,3.282,0,0,0,.67149-1.98265,3.31768,3.31768,0,0,0-6.37-1.2992,13.27078,13.27078,0,1,0,0,25.54082,3.31768,3.31768,0,0,0,6.37-1.2992,3.282,3.282,0,0,0-.67149-1.98265q.11347-.10947.22294-.22294a3.28174,3.28174,0,0,0,2.00122.68742,3.31768,3.31768,0,0,0,1.278-6.37923c.02786-.0982.05042-.19907.077-.29859a3.41325,3.41325,0,0,0,.42333.04246" transform="translate(-35.5 -118.5)" fill="#44d860" fill-rule="evenodd" />
|
||||
<path d="M317.84538,466.081a3.31768,3.31768,0,0,1-3.31767-3.31768,9.953,9.953,0,1,0-19.90608,0,3.31768,3.31768,0,1,1-6.63535,0,16.58839,16.58839,0,1,1,33.17678,0,3.31768,3.31768,0,0,1-3.31768,3.31768" transform="translate(-35.5 -118.5)" fill-rule="evenodd" />
|
||||
<path d="M370.92825,635.28265h79.62429A26.5409,26.5409,0,0,0,477.094,608.74122v-92.895H397.46968a26.54091,26.54091,0,0,0-26.54143,26.54143Z" transform="translate(-35.5 -118.5)" fill="#ffff50" fill-rule="evenodd" />
|
||||
<path d="M457.21444,556.98543H390.80778a1.32707,1.32707,0,0,1,0-2.65414h66.40666a1.32707,1.32707,0,0,1,0,2.65414m0,26.54143H390.80778a1.32707,1.32707,0,1,1,0-2.65414h66.40666a1.32707,1.32707,0,0,1,0,2.65414m0,26.54143H390.80778a1.32707,1.32707,0,1,1,0-2.65414h66.40666a1.32707,1.32707,0,0,1,0,2.65414m0-66.10674H390.80778a1.32707,1.32707,0,0,1,0-2.65414h66.40666a1.32707,1.32707,0,0,1,0,2.65414m0,26.29459H390.80778a1.32707,1.32707,0,0,1,0-2.65414h66.40666a1.32707,1.32707,0,0,1,0,2.65414m0,26.54143H390.80778a1.32707,1.32707,0,0,1,0-2.65414h66.40666a1.32707,1.32707,0,0,1,0,2.65414M477.094,474.19076c-.01592,0-.0292-.008-.04512-.00663-4.10064.13934-6.04083,4.24132-7.75274,7.86024-1.78623,3.78215-3.16771,6.24122-5.43171,6.16691-2.50685-.09024-3.94007-2.92222-5.45825-5.91874-1.74377-3.44243-3.73438-7.34667-7.91333-7.20069-4.04227.138-5.98907,3.70784-7.70631,6.857-1.82738,3.35484-3.07084,5.39455-5.46887,5.30033-2.55727-.09289-3.91619-2.39536-5.48877-5.06013-1.75306-2.96733-3.77951-6.30359-7.8775-6.18946-3.97326.13669-5.92537,3.16507-7.64791,5.83912-1.82207,2.82666-3.09872,4.5492-5.52725,4.447-2.61832-.09289-3.9706-2.00388-5.53522-4.21611-1.757-2.4856-3.737-5.299-7.82308-5.16231-3.88567.13271-5.83779,2.61434-7.559,4.80135-1.635,2.07555-2.9116,3.71846-5.61218,3.615a1.32793,1.32793,0,1,0-.09555,2.65414c4.00377.134,6.03154-2.38873,7.79257-4.6275,1.562-1.9853,2.91027-3.69855,5.56441-3.78879,2.55594-.10882,3.75429,1.47968,5.56707,4.04093,1.7212,2.43385,3.67465,5.19416,7.60545,5.33616,4.11789.138,6.09921-2.93946,7.8536-5.66261,1.56861-2.43385,2.92221-4.53461,5.50734-4.62352,2.37944-.08892,3.67466,1.79154,5.50072,4.885,1.72121,2.91557,3.67069,6.21865,7.67977,6.36463,4.14709.14332,6.14965-3.47693,7.89475-6.68181,1.51155-2.77092,2.93814-5.38791,5.46621-5.4755,2.37944-.05573,3.62025,2.11668,5.45558,5.74622,1.71459,3.388,3.65875,7.22591,7.73019,7.37321l.22429.004c4.06614,0,5.99571-4.08074,7.70364-7.68905,1.51154-3.19825,2.94211-6.21069,5.3972-6.33411Z" transform="translate(-35.5 -118.5)" fill-rule="evenodd" />
|
||||
<path d="M344.38682,635.28265h53.08286V582.19979H344.38682Z" transform="translate(-35.5 -118.5)" fill="#3ecc5f" fill-rule="evenodd" />
|
||||
<path d="M424.01111,602.10586a6.60242,6.60242,0,0,0-.848.08493c-.05042-.19906-.09821-.39945-.15394-.59852A6.62667,6.62667,0,1,0,416.45211,590.21q-.2203-.22491-.44458-.44589a6.62391,6.62391,0,1,0-11.39689-6.56369c-.1964-.05575-.39413-.10218-.59054-.15262a6.63957,6.63957,0,1,0-13.10084,0c-.19641.05042-.39414.09687-.59055.15262a6.62767,6.62767,0,1,0-11.39689,6.56369,26.52755,26.52755,0,1,0,44.2313,25.52756,6.6211,6.6211,0,1,0,.848-13.18579" transform="translate(-35.5 -118.5)" fill="#44d860" fill-rule="evenodd" />
|
||||
<path d="M344.38682,555.65836h53.08286V529.11693H344.38682Z" transform="translate(-35.5 -118.5)" fill="#3ecc5f" fill-rule="evenodd" />
|
||||
<path d="M410.74039,545.70532a3.31768,3.31768,0,1,0,0-6.63536,3.41133,3.41133,0,0,0-.42333.04247c-.02655-.09953-.04911-.19907-.077-.29859a3.319,3.319,0,0,0-1.278-6.37923,3.28174,3.28174,0,0,0-2.00122.68742q-.10947-.11346-.22294-.22295a3.282,3.282,0,0,0,.67149-1.98265,3.31768,3.31768,0,0,0-6.37-1.2992,13.27078,13.27078,0,1,0,0,25.54082,3.31768,3.31768,0,0,0,6.37-1.2992,3.282,3.282,0,0,0-.67149-1.98265q.11347-.10947.22294-.22294a3.28174,3.28174,0,0,0,2.00122.68742,3.31768,3.31768,0,0,0,1.278-6.37923c.02786-.0982.05042-.19907.077-.29859a3.41325,3.41325,0,0,0,.42333.04246" transform="translate(-35.5 -118.5)" fill="#44d860" fill-rule="evenodd" />
|
||||
<path d="M424.01111,447.8338a3.60349,3.60349,0,0,1-.65028-.06636,3.34415,3.34415,0,0,1-.62372-.18579,3.44679,3.44679,0,0,1-.572-.30522,5.02708,5.02708,0,0,1-.50429-.4114,3.88726,3.88726,0,0,1-.41007-.50428,3.27532,3.27532,0,0,1-.55737-1.84463,3.60248,3.60248,0,0,1,.06636-.65027,3.82638,3.82638,0,0,1,.18447-.62373,3.48858,3.48858,0,0,1,.30656-.57064,3.197,3.197,0,0,1,.91436-.91568,3.44685,3.44685,0,0,1,.572-.30523,3.344,3.344,0,0,1,.62372-.18578,3.06907,3.06907,0,0,1,1.30053,0,3.22332,3.22332,0,0,1,1.19436.491,5.02835,5.02835,0,0,1,.50429.41139,4.8801,4.8801,0,0,1,.41139.50429,3.38246,3.38246,0,0,1,.30522.57064,3.47806,3.47806,0,0,1,.25215,1.274A3.36394,3.36394,0,0,1,426.36,446.865a5.02708,5.02708,0,0,1-.50429.4114,3.3057,3.3057,0,0,1-1.84463.55737m26.54143-1.65884a3.38754,3.38754,0,0,1-2.35024-.96877,5.04185,5.04185,0,0,1-.41007-.50428,3.27532,3.27532,0,0,1-.55737-1.84463,3.38659,3.38659,0,0,1,.96744-2.34892,5.02559,5.02559,0,0,1,.50429-.41139,3.44685,3.44685,0,0,1,.572-.30523,3.3432,3.3432,0,0,1,.62373-.18579,3.06952,3.06952,0,0,1,1.30052,0,3.22356,3.22356,0,0,1,1.19436.491,5.02559,5.02559,0,0,1,.50429.41139,3.38792,3.38792,0,0,1,.96876,2.34892,3.72635,3.72635,0,0,1-.06636.65026,3.37387,3.37387,0,0,1-.18579.62373,4.71469,4.71469,0,0,1-.30522.57064,4.8801,4.8801,0,0,1-.41139.50429,5.02559,5.02559,0,0,1-.50429.41139,3.30547,3.30547,0,0,1-1.84463.55737" transform="translate(-35.5 -118.5)" fill-rule="evenodd" />
|
||||
</svg>
|
After Width: | Height: | Size: 12 KiB |
7
build/docs/tsconfig.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
// This file is not used in compilation. It is here just for a nice editor experience.
|
||||
"extends": "@tsconfig/docusaurus/tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"baseUrl": "."
|
||||
}
|
||||
}
|
7764
build/docs/yarn.lock
Normal file
20
build/jest.config.base.js
Normal file
@ -0,0 +1,20 @@
|
||||
const {join, normalize} = require("path");
|
||||
|
||||
const tsconfig = normalize(join(__dirname, "tsconfig.test.json"))
|
||||
|
||||
module.exports = {
|
||||
displayName: { name: "root" },
|
||||
preset: "ts-jest",
|
||||
projects: ["<rootDir>/packages/*/jest.config.js"],
|
||||
transform: {
|
||||
"^.+\\.tsx?$":"ts-jest"
|
||||
},
|
||||
moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json"],
|
||||
globals: {
|
||||
"ts-jest": {
|
||||
tsconfig,
|
||||
experimental: true,
|
||||
compilerHost: true
|
||||
}
|
||||
}
|
||||
}
|
17
build/jest.config.js
Normal file
@ -0,0 +1,17 @@
|
||||
const baseConfig = require("./jest.config.base");
|
||||
|
||||
module.exports = {
|
||||
...baseConfig,
|
||||
displayName: { name: "root", color: "blue" },
|
||||
projects: ["<rootDir>/packages/*/jest.config.js"],
|
||||
collectCoverage: true,
|
||||
collectCoverageFrom:[
|
||||
"<rootDir>/packages/*/src/**/*.{js,jsx,ts,tsx}",
|
||||
],
|
||||
coveragePathIgnorePatterns: [
|
||||
"/node_modules/",
|
||||
"<rootDir>packages/*/src/__tests__/",
|
||||
],
|
||||
coverageDirectory: "coverage",
|
||||
testResultsProcessor: 'jest-sonar-reporter',
|
||||
};
|
13
build/lerna.json
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"packages": [
|
||||
"packages/*"
|
||||
],
|
||||
"version": "1.4.2",
|
||||
"npmClient": "yarn",
|
||||
"useWorkspaces": true,
|
||||
"command": {
|
||||
"publish": {
|
||||
"message": "chore(release): publish %s"
|
||||
}
|
||||
}
|
||||
}
|
24
build/module-build/tsconfig.esm.json
Normal file
@ -0,0 +1,24 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "ES2020",
|
||||
"declaration": true,
|
||||
"target": "es6",
|
||||
"moduleResolution": "node",
|
||||
"esModuleInterop": true,
|
||||
"downlevelIteration": true,
|
||||
"incremental": true,
|
||||
"noImplicitReturns": true,
|
||||
"noImplicitAny": true,
|
||||
"allowUnreachableCode": false,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"strict": true,
|
||||
"lib": [
|
||||
"ES2015",
|
||||
"ES2016.Array.Include",
|
||||
"ES2017.String",
|
||||
"ES2018.Promise",
|
||||
"ES2019",
|
||||
"DOM",
|
||||
]
|
||||
}
|
||||
}
|
24
build/module-build/tsconfig.json
Normal file
@ -0,0 +1,24 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"declaration": true,
|
||||
"target": "es5",
|
||||
"esModuleInterop": true,
|
||||
"downlevelIteration": true,
|
||||
"incremental": true,
|
||||
"sourceMap": true,
|
||||
"noImplicitReturns": true,
|
||||
"noImplicitAny": true,
|
||||
"allowUnreachableCode": false,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"strict": true,
|
||||
"lib": [
|
||||
"ES2015",
|
||||
"ES2016.Array.Include",
|
||||
"ES2017.String",
|
||||
"ES2018.Promise",
|
||||
"ES2019",
|
||||
"DOM",
|
||||
]
|
||||
}
|
||||
}
|
63
build/package.json
Normal file
@ -0,0 +1,63 @@
|
||||
{
|
||||
"name": "dockview-monorepo-root",
|
||||
"private": true,
|
||||
"description": "Monorepo for https://github.com/mathuo/dockview",
|
||||
"workspaces": [
|
||||
"packages/*"
|
||||
],
|
||||
"scripts": {
|
||||
"test": "jest",
|
||||
"lint": "eslint packages/**/src/** --ext .ts,.tsx,.js,.jsx",
|
||||
"package": "node scripts/package.js",
|
||||
"package-all": "npm run build-demo && npm run docs && node scripts/package.js",
|
||||
"build": "lerna run build --scope dockview",
|
||||
"build-demo": "lerna run build --scope dockview-demo",
|
||||
"docs": "lerna run docs --scope dockview",
|
||||
"clean": "lerna run clean",
|
||||
"bootstrap": "lerna bootstrap",
|
||||
"test:cov": "jest --coverage",
|
||||
"version-beta-build": "lerna version prerelease --preid beta",
|
||||
"publish-app": "lerna publish"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/mathuo/dockview.git"
|
||||
},
|
||||
"author": "https://github.com/mathuo",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/mathuo/dockview/issues"
|
||||
},
|
||||
"homepage": "https://github.com/mathuo/dockview#readme",
|
||||
"devDependencies": {
|
||||
"@testing-library/dom": "^8.13.0",
|
||||
"@types/jest": "^27.5.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.22.0",
|
||||
"@typescript-eslint/parser": "^5.22.0",
|
||||
"codecov": "^3.8.3",
|
||||
"cross-env": "^7.0.3",
|
||||
"css-loader": "^6.7.1",
|
||||
"eslint": "^8.15.0",
|
||||
"fs-extra": "^10.1.0",
|
||||
"gulp": "^4.0.2",
|
||||
"gulp-concat": "^2.6.1",
|
||||
"gulp-dart-sass": "^1.0.2",
|
||||
"jest": "^28.1.0",
|
||||
"jest-environment-jsdom": "^28.1.0",
|
||||
"jest-sonar-reporter": "^2.0.0",
|
||||
"jsdom": "^19.0.0",
|
||||
"lerna": "^4.0.0",
|
||||
"merge2": "^1.4.1",
|
||||
"rimraf": "^3.0.2",
|
||||
"sass": "^1.51.0",
|
||||
"sass-loader": "^12.6.0",
|
||||
"style-loader": "^3.3.1",
|
||||
"ts-jest": "^28.0.2",
|
||||
"ts-loader": "^9.3.0",
|
||||
"tslib": "^2.4.0",
|
||||
"typescript": "^4.6.4",
|
||||
"webpack": "^5.72.0",
|
||||
"webpack-cli": "^4.9.2",
|
||||
"webpack-dev-server": "^4.9.0"
|
||||
}
|
||||
}
|
8
build/packages/dockview-demo/.eslintrc
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": [
|
||||
"../../.eslintrc"
|
||||
],
|
||||
"rules": {
|
||||
"@typescript-eslint/no-var-requires": "off"
|
||||
}
|
||||
}
|
23
build/packages/dockview-demo/.storybook/main.js
Normal file
@ -0,0 +1,23 @@
|
||||
module.exports = {
|
||||
stories: [
|
||||
"../src/**/*.stories.mdx",
|
||||
"../src/**/*.stories.@(js|jsx|ts|tsx)"
|
||||
],
|
||||
addons: [
|
||||
{
|
||||
name: '@storybook/addon-docs',
|
||||
options: {
|
||||
sourceLoaderOptions: {
|
||||
injectStoryParameters: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
"@storybook/addon-storysource",
|
||||
"@storybook/addon-links",
|
||||
"@storybook/addon-essentials",
|
||||
"@storybook/addon-controls"
|
||||
],
|
||||
core: {
|
||||
builder: "webpack5"
|
||||
}
|
||||
}
|
5
build/packages/dockview-demo/.storybook/preview.js
Normal file
@ -0,0 +1,5 @@
|
||||
import '!style-loader!css-loader!sass-loader!../node_modules/dockview/dist/styles/dockview.css';
|
||||
|
||||
export const parameters = {
|
||||
actions: { argTypesRegex: "^on[A-Z].*" },
|
||||
}
|
51
build/packages/dockview-demo/package.json
Normal file
@ -0,0 +1,51 @@
|
||||
{
|
||||
"name": "dockview-demo",
|
||||
"private": true,
|
||||
"version": "1.4.2",
|
||||
"description": "Demo project for https://github.com/mathuo/dockview",
|
||||
"scripts": {
|
||||
"build": "npm run build-webpack",
|
||||
"build-webpack": "cross-env ../../node_modules/.bin/webpack --config webpack.config.js",
|
||||
"start": "cross-env ../../node_modules/.bin/webpack serve --config webpack.config.js",
|
||||
"clean": "rimraf dist/ .build/",
|
||||
"storybook": "start-storybook -p 6006",
|
||||
"build-storybook": "build-storybook"
|
||||
},
|
||||
"author": "https://github.com/mathuo",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@mdx-js/react": "^2.1.1",
|
||||
"dockview": "^1.4.2",
|
||||
"react": "^18.1.0",
|
||||
"react-dom": "^18.1.0",
|
||||
"recoil": "^0.7.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.17.10",
|
||||
"@storybook/addon-actions": "^6.5.0-beta.0",
|
||||
"@storybook/addon-controls": "^6.5.0-beta.0",
|
||||
"@storybook/addon-docs": "^6.5.0-beta.0",
|
||||
"@storybook/addon-essentials": "^6.5.0-beta.0",
|
||||
"@storybook/addon-links": "^6.5.0-beta.0",
|
||||
"@storybook/addon-storysource": "^6.5.0-beta.0",
|
||||
"@storybook/builder-webpack5": "^6.5.0-beta.0",
|
||||
"@storybook/manager-webpack5": "^6.5.0-beta.0",
|
||||
"@storybook/react": "^6.5.0-beta.0",
|
||||
"@types/react": "^18.0.9",
|
||||
"@types/react-dom": "^18.0.3",
|
||||
"babel-loader": "^8.2.5",
|
||||
"cross-env": "^7.0.3",
|
||||
"rimraf": "^3.0.2",
|
||||
"source-map-loader": "^3.0.1"
|
||||
},
|
||||
"resolutions": {
|
||||
"webpack": "^5.0.0",
|
||||
"css-loader": "^5.0.0",
|
||||
"dotenv-webpack": "^6.0.0",
|
||||
"html-webpack-plugin": "^5.0.0",
|
||||
"style-loader": "^2.0.0",
|
||||
"terser-webpack-plugin": "^5.0.0",
|
||||
"webpack-dev-middleware": "^4.1.0",
|
||||
"webpack-virtual-modules": "^0.4.2"
|
||||
}
|
||||
}
|
14
build/packages/dockview-demo/public/index.html
Normal file
@ -0,0 +1,14 @@
|
||||
<!-- <!DOCTYPE html> -->
|
||||
<html>
|
||||
<head>
|
||||
<link href="https://fonts.googleapis.com/icon?family=Material+Icons+Outlined" rel="stylesheet">
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=swap" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<div id="anchor"></div>
|
||||
<script src="/dist/bundle.js"></script>
|
||||
</body>
|
||||
</html>
|
13
build/packages/dockview-demo/src/dom.ts
Normal file
@ -0,0 +1,13 @@
|
||||
export const toggleClass = (
|
||||
element: HTMLElement,
|
||||
className: string,
|
||||
isToggled: boolean
|
||||
) => {
|
||||
const hasClass = element.classList.contains(className);
|
||||
if (isToggled && !hasClass) {
|
||||
element.classList.add(className);
|
||||
}
|
||||
if (!isToggled && hasClass) {
|
||||
element.classList.remove(className);
|
||||
}
|
||||
};
|
122
build/packages/dockview-demo/src/events.ts
Normal file
@ -0,0 +1,122 @@
|
||||
import { IDisposable } from './lifecycle';
|
||||
|
||||
export interface Event<T> {
|
||||
(listener: (e: T) => any): IDisposable;
|
||||
}
|
||||
|
||||
export interface EmitterOptions {
|
||||
replay?: boolean;
|
||||
}
|
||||
|
||||
export namespace Event {
|
||||
export const any = <T>(...children: Event<T>[]): Event<T> => {
|
||||
return (listener: (e: T) => void) => {
|
||||
const disposables = children.map((child) => child(listener));
|
||||
|
||||
return {
|
||||
dispose: () => {
|
||||
disposables.forEach((d) => {
|
||||
d.dispose();
|
||||
});
|
||||
},
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
// dumb event emitter with better typings than nodes event emitter
|
||||
// https://github.com/microsoft/vscode/blob/master/src/vs/base/common/event.ts
|
||||
export class Emitter<T> implements IDisposable {
|
||||
private _event?: Event<T>;
|
||||
|
||||
private _last?: T;
|
||||
private _listeners: Array<(e: T) => any> = [];
|
||||
private _disposed = false;
|
||||
|
||||
constructor(private readonly options?: EmitterOptions) {}
|
||||
|
||||
get event() {
|
||||
if (!this._event) {
|
||||
this._event = (listener: (e: T) => void): IDisposable => {
|
||||
if (this.options?.replay && this._last !== undefined) {
|
||||
listener(this._last);
|
||||
}
|
||||
|
||||
this._listeners.push(listener);
|
||||
|
||||
return {
|
||||
dispose: () => {
|
||||
const index = this._listeners.indexOf(listener);
|
||||
if (index > -1) {
|
||||
this._listeners.splice(index, 1);
|
||||
}
|
||||
},
|
||||
};
|
||||
};
|
||||
}
|
||||
return this._event;
|
||||
}
|
||||
|
||||
public fire(e: T) {
|
||||
this._last = e;
|
||||
for (const listener of this._listeners) {
|
||||
listener(e);
|
||||
}
|
||||
}
|
||||
|
||||
public dispose() {
|
||||
this._listeners = [];
|
||||
this._disposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
export function addDisposableWindowListener<K extends keyof WindowEventMap>(
|
||||
element: Window,
|
||||
type: K,
|
||||
listener: (this: Window, ev: WindowEventMap[K]) => any,
|
||||
options?: boolean | AddEventListenerOptions
|
||||
): IDisposable {
|
||||
element.addEventListener(type, listener, options);
|
||||
|
||||
return {
|
||||
dispose: () => {
|
||||
element.removeEventListener(type, listener);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function addDisposableListener<K extends keyof HTMLElementEventMap>(
|
||||
element: HTMLElement,
|
||||
type: K,
|
||||
listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any,
|
||||
options?: boolean | AddEventListenerOptions
|
||||
): IDisposable {
|
||||
element.addEventListener(type, listener, options);
|
||||
|
||||
return {
|
||||
dispose: () => {
|
||||
element.removeEventListener(type, listener);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export class TickDelayedEvent implements IDisposable {
|
||||
private timer: any;
|
||||
|
||||
private readonly _onFired = new Emitter<void>();
|
||||
readonly onEvent = this._onFired.event;
|
||||
|
||||
fire(): void {
|
||||
if (this.timer) {
|
||||
clearTimeout(this.timer);
|
||||
}
|
||||
this.timer = setTimeout(() => {
|
||||
this._onFired.fire();
|
||||
clearTimeout(this.timer);
|
||||
});
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this._onFired.dispose();
|
||||
}
|
||||
}
|
66
build/packages/dockview-demo/src/index.scss
Normal file
@ -0,0 +1,66 @@
|
||||
@import '~dockview/dist/styles/dockview.css';
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: 'Roboto', sans-serif;
|
||||
overflow: hidden;
|
||||
color: rgb(204, 204, 204);
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
height: 8px;
|
||||
width: 8px;
|
||||
}
|
||||
|
||||
/* Track */
|
||||
::-webkit-scrollbar-track {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
/* Handle */
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: var(--dv-tabs-container-scrollbar-color);
|
||||
}
|
||||
|
||||
// *,
|
||||
// *::after,
|
||||
// *::before {
|
||||
// -webkit-user-drag: none;
|
||||
// -webkit-app-region: no-drag;
|
||||
// -webkit-user-select: none;
|
||||
// }
|
||||
|
||||
.close-action {
|
||||
&:active {
|
||||
-webkit-mask-size: 100% 100% !important;
|
||||
mask-size: 100% 100% !important;
|
||||
}
|
||||
|
||||
background-color: white;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
display: block;
|
||||
-webkit-mask: var(--dv-tab-close-icon) 50% 50% / 90% 90% no-repeat;
|
||||
mask: var(--dv-tab-close-icon) 50% 50% / 90% 90% no-repeat;
|
||||
margin-right: '0.5em';
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
button {
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
border: none;
|
||||
background-color: rgb(14, 99, 156);
|
||||
color: white;
|
||||
font-family: inherit;
|
||||
outline: none;
|
||||
padding: 2px 14px;
|
||||
margin: 2px 0px;
|
||||
|
||||
&:hover {
|
||||
background-color: rgb(17, 119, 187);
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
15
build/packages/dockview-demo/src/index.tsx
Normal file
@ -0,0 +1,15 @@
|
||||
import * as React from 'react';
|
||||
import * as ReactDOM from 'react-dom/client';
|
||||
import { Application } from './layout-grid/application';
|
||||
import { RecoilRoot } from 'recoil';
|
||||
import './index.scss';
|
||||
|
||||
document.getElementById('app').classList.add('dockview-theme-dark');
|
||||
|
||||
const root = ReactDOM.createRoot(document.getElementById('app'));
|
||||
|
||||
root.render(
|
||||
<RecoilRoot>
|
||||
<Application />
|
||||
</RecoilRoot>
|
||||
);
|
@ -0,0 +1,34 @@
|
||||
.activity-bar {
|
||||
height: 100%;
|
||||
background-color: rgb(51, 51, 51);
|
||||
|
||||
.activity-bar-item {
|
||||
width: 100%;
|
||||
padding-bottom: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(90, 90, 90, 0.5);
|
||||
}
|
||||
|
||||
.activity-bar-item-image {
|
||||
-webkit-mask-size: 65% 65%;
|
||||
mask-size: 65% 65%;
|
||||
-webkit-mask-position: 50% 50%;
|
||||
mask-position: 50% 50%;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
mask-repeat: no-repeat;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
display: block;
|
||||
background-color: gray;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
}
|
||||
}
|
71
build/packages/dockview-demo/src/layout-grid/activitybar.tsx
Normal file
@ -0,0 +1,71 @@
|
||||
import * as React from 'react';
|
||||
import { GridviewApi, IGridviewPanelProps } from 'dockview';
|
||||
import './activitybar.scss';
|
||||
import { useLayoutRegistry } from './registry';
|
||||
import { CompositeDisposable } from '../lifecycle';
|
||||
|
||||
const ActivitybarImage = (props: { url: string }) => (
|
||||
<a
|
||||
style={{
|
||||
WebkitMaskImage: `url(${props.url})`,
|
||||
maskImage: `url(${props.url})`,
|
||||
}}
|
||||
className="activity-bar-item-image"
|
||||
/>
|
||||
);
|
||||
|
||||
export const Activitybar = (props: IGridviewPanelProps) => {
|
||||
const registry = useLayoutRegistry();
|
||||
const [isActive, setActive] = React.useState<boolean>();
|
||||
|
||||
const onOpenSidebar = (event: React.MouseEvent<HTMLDivElement>) => {
|
||||
const api = registry.get<GridviewApi>('gridview');
|
||||
|
||||
const sidebarPanel = api.getPanel('sidebar');
|
||||
if (sidebarPanel.api.isVisible) {
|
||||
sidebarPanel.api.setVisible(false);
|
||||
} else {
|
||||
event.preventDefault(); // prevent focus
|
||||
sidebarPanel.api.setVisible(true);
|
||||
sidebarPanel.focus();
|
||||
}
|
||||
};
|
||||
|
||||
React.useEffect(() => {
|
||||
const disposable = new CompositeDisposable(
|
||||
props.api.onDidActiveChange((event) => {
|
||||
setActive(event.isActive);
|
||||
})
|
||||
);
|
||||
|
||||
return () => {
|
||||
disposable.dispose();
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="activity-bar" onClick={onOpenSidebar}>
|
||||
<div className="activity-bar-item">
|
||||
<ActivitybarImage
|
||||
url={
|
||||
'https://fonts.gstatic.com/s/i/materialicons/search/v7/24px.svg'
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div className="activity-bar-item">
|
||||
<ActivitybarImage
|
||||
url={
|
||||
'https://fonts.gstatic.com/s/i/materialicons/search/v7/24px.svg'
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div className="activity-bar-item">
|
||||
<ActivitybarImage
|
||||
url={
|
||||
'https://fonts.gstatic.com/s/i/materialicons/search/v7/24px.svg'
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
108
build/packages/dockview-demo/src/layout-grid/application.tsx
Normal file
@ -0,0 +1,108 @@
|
||||
import * as React from 'react';
|
||||
import {
|
||||
Orientation,
|
||||
GridviewReact,
|
||||
LayoutPriority,
|
||||
GridviewReadyEvent,
|
||||
IGridviewPanelProps,
|
||||
SerializedGridview,
|
||||
GridviewApi,
|
||||
} from 'dockview';
|
||||
import { Activitybar } from '../services/widgets';
|
||||
import { Footer } from './footer';
|
||||
import { Panel } from './panel';
|
||||
import { TestGrid } from './layoutGrid';
|
||||
import { useLayoutRegistry } from './registry';
|
||||
import { Sidebar } from '../services/widgets';
|
||||
|
||||
const rootcomponents: {
|
||||
[index: string]: React.FunctionComponent<IGridviewPanelProps>;
|
||||
} = {
|
||||
sidebar: Sidebar,
|
||||
activitybar: Activitybar,
|
||||
editor: TestGrid,
|
||||
footer: Footer,
|
||||
panel: Panel,
|
||||
};
|
||||
|
||||
export const Application = () => {
|
||||
const api = React.useRef<GridviewApi>();
|
||||
const registry = useLayoutRegistry();
|
||||
|
||||
const onReady = (event: GridviewReadyEvent) => {
|
||||
api.current = event.api;
|
||||
registry.register('gridview', event.api);
|
||||
|
||||
let success = false;
|
||||
const state = localStorage.getItem('dockview-layout');
|
||||
|
||||
if (state) {
|
||||
try {
|
||||
event.api.fromJSON(JSON.parse(state));
|
||||
success = true;
|
||||
} catch (err) {
|
||||
console.error('failed to load layout', err);
|
||||
}
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
event.api.addPanel({
|
||||
id: 'i',
|
||||
component: 'activitybar',
|
||||
minimumWidth: 48,
|
||||
maximumWidth: 48,
|
||||
location: [0],
|
||||
});
|
||||
|
||||
event.api.addPanel({
|
||||
id: 'footer',
|
||||
component: 'footer',
|
||||
location: [1],
|
||||
maximumHeight: 22,
|
||||
minimumHeight: 22,
|
||||
});
|
||||
|
||||
event.api.addPanel({
|
||||
id: 'editor',
|
||||
component: 'editor',
|
||||
snap: true,
|
||||
location: [0, 1],
|
||||
priority: LayoutPriority.High,
|
||||
});
|
||||
|
||||
event.api.addPanel({
|
||||
id: 'sidebar',
|
||||
component: 'sidebar',
|
||||
snap: true,
|
||||
position: { referencePanel: 'editor', direction: 'left' },
|
||||
minimumWidth: 170,
|
||||
size: 100,
|
||||
});
|
||||
|
||||
event.api.addPanel({
|
||||
id: 'panel',
|
||||
component: 'panel',
|
||||
position: { referencePanel: 'editor', direction: 'below' },
|
||||
size: 200,
|
||||
snap: true,
|
||||
});
|
||||
}
|
||||
|
||||
event.api.onDidLayoutChange(() => {
|
||||
localStorage.setItem(
|
||||
'dockview-layout',
|
||||
JSON.stringify(event.api.toJSON())
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<GridviewReact
|
||||
components={rootcomponents}
|
||||
onReady={onReady}
|
||||
orientation={Orientation.VERTICAL}
|
||||
hideBorders={true}
|
||||
proportionalLayout={true}
|
||||
/>
|
||||
);
|
||||
};
|
@ -0,0 +1,30 @@
|
||||
.control-center {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
padding: 4px 8px;
|
||||
box-sizing: border-box;
|
||||
|
||||
.control-center-row {
|
||||
height: 25px;
|
||||
box-sizing: border-box;
|
||||
|
||||
button {
|
||||
width: 175px;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
border: none;
|
||||
background-color: rgb(14, 99, 156);
|
||||
color: white;
|
||||
font-family: inherit;
|
||||
outline: none;
|
||||
padding: 2px 14px;
|
||||
margin: 2px 0px;
|
||||
|
||||
&:hover {
|
||||
background-color: rgb(17, 119, 187);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
150
build/packages/dockview-demo/src/layout-grid/controlCenter.tsx
Normal file
@ -0,0 +1,150 @@
|
||||
import * as React from 'react';
|
||||
import { DockviewApi, GridviewApi, SplitviewApi } from 'dockview';
|
||||
import { useLayoutRegistry } from './registry';
|
||||
import './controlCenter.scss';
|
||||
|
||||
export const ControlCenter = () => {
|
||||
const registry = useLayoutRegistry();
|
||||
|
||||
const onAdd = () => {
|
||||
const api = registry.get<DockviewApi>('dockview');
|
||||
const _id = Date.now();
|
||||
const id = `${_id}`;
|
||||
|
||||
api.addPanel({
|
||||
component: 'test_component',
|
||||
id,
|
||||
title: `Item ${id}`,
|
||||
});
|
||||
};
|
||||
|
||||
const onAddTheSamePanel = () => {
|
||||
const api = registry.get<DockviewApi>('dockview');
|
||||
const id = `duplicate_panel`;
|
||||
|
||||
const panel = api.getPanel(id);
|
||||
if (panel) {
|
||||
panel.api.setActive();
|
||||
return;
|
||||
}
|
||||
api.addPanel({
|
||||
component: 'test_component',
|
||||
id,
|
||||
title: `Item ${id}`,
|
||||
});
|
||||
};
|
||||
|
||||
const onAddEmpty = () => {
|
||||
const api = registry.get<DockviewApi>('dockview');
|
||||
api.addEmptyGroup();
|
||||
};
|
||||
|
||||
const nextPanel = (ev: React.MouseEvent<HTMLButtonElement>) => {
|
||||
ev.preventDefault();
|
||||
const api = registry.get<DockviewApi>('dockview');
|
||||
api.moveToNext({ includePanel: true });
|
||||
};
|
||||
const nextGroup = (ev: React.MouseEvent<HTMLButtonElement>) => {
|
||||
ev.preventDefault();
|
||||
const api = registry.get<DockviewApi>('dockview');
|
||||
api.moveToNext();
|
||||
};
|
||||
const previousPanel = (ev: React.MouseEvent<HTMLButtonElement>) => {
|
||||
ev.preventDefault();
|
||||
const api = registry.get<DockviewApi>('dockview');
|
||||
api.moveToPrevious({ includePanel: true });
|
||||
};
|
||||
const previousGroup = (ev: React.MouseEvent<HTMLButtonElement>) => {
|
||||
ev.preventDefault();
|
||||
const api = registry.get<DockviewApi>('dockview');
|
||||
api.moveToNext();
|
||||
};
|
||||
|
||||
const onConfig = () => {
|
||||
const api = registry.get<DockviewApi>('dockview');
|
||||
const data = api.toJSON();
|
||||
const stringData = JSON.stringify(data, null, 4);
|
||||
console.log(stringData);
|
||||
localStorage.setItem('layout', stringData);
|
||||
};
|
||||
|
||||
const onLoad = async () => {
|
||||
const api = registry.get<DockviewApi>('dockview');
|
||||
api.closeAllGroups();
|
||||
|
||||
const data = localStorage.getItem('layout');
|
||||
if (data) {
|
||||
const jsonData = JSON.parse(data);
|
||||
api.fromJSON(jsonData);
|
||||
}
|
||||
};
|
||||
|
||||
const onClear = () => {
|
||||
const api = registry.get<DockviewApi>('dockview');
|
||||
api.closeAllGroups();
|
||||
};
|
||||
|
||||
const saveApplicationLayout = () => {
|
||||
const api = registry.get<GridviewApi>('dockview');
|
||||
console.log(JSON.stringify(api.toJSON(), null, 4));
|
||||
};
|
||||
|
||||
const onAddSettings = () => {
|
||||
const api = registry.get<DockviewApi>('dockview');
|
||||
|
||||
const settingsPanel = api.getPanel('settings');
|
||||
if (settingsPanel) {
|
||||
settingsPanel.api.setActive();
|
||||
return;
|
||||
}
|
||||
|
||||
api.addPanel({
|
||||
id: 'settings',
|
||||
component: 'settings',
|
||||
title: 'Settings',
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="control-center">
|
||||
<div className="control-center-row">
|
||||
<button onMouseDown={onAdd}>Add new</button>
|
||||
</div>
|
||||
<div className="control-center-row">
|
||||
<button onMouseDown={onAddTheSamePanel}>Add identical</button>
|
||||
</div>
|
||||
<div className="control-center-row">
|
||||
<button onMouseDown={onAddSettings}>Settings</button>
|
||||
</div>
|
||||
<div className="control-center-row">
|
||||
<button onMouseDown={onAddEmpty}>Add empty</button>
|
||||
</div>
|
||||
<div className="control-center-row">
|
||||
<button onMouseDown={nextPanel}>Next panel</button>
|
||||
</div>
|
||||
<div className="control-center-row">
|
||||
<button onMouseDown={nextGroup}>Next Group</button>
|
||||
</div>
|
||||
<div className="control-center-row">
|
||||
<button onMouseDown={previousPanel}>Previous Panel</button>
|
||||
</div>
|
||||
<div className="control-center-row">
|
||||
<button onMouseDown={previousGroup}>Previous Group</button>
|
||||
</div>
|
||||
<div className="control-center-row">
|
||||
<button onClick={onConfig}>Save</button>
|
||||
</div>
|
||||
<div className="control-center-row">
|
||||
<button onClick={onLoad}>Load</button>
|
||||
</div>
|
||||
<div className="control-center-row">
|
||||
<button onClick={onClear}>Clear</button>
|
||||
</div>
|
||||
<div className="control-center-row">
|
||||
<button onClick={saveApplicationLayout}>
|
||||
Save application layout
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
@ -0,0 +1,6 @@
|
||||
import * as React from 'react';
|
||||
import { IGroupPanelBaseProps } from 'dockview';
|
||||
|
||||
export const CustomTab = (props: IGroupPanelBaseProps) => {
|
||||
return <div>hello</div>;
|
||||
};
|
27
build/packages/dockview-demo/src/layout-grid/footer.tsx
Normal file
@ -0,0 +1,27 @@
|
||||
import * as React from 'react';
|
||||
import { IGridviewPanelProps } from 'dockview';
|
||||
import { atom, useRecoilValue } from 'recoil';
|
||||
|
||||
export const selectedPanelAtom = atom<string>({
|
||||
key: 'selectedPanelAtom',
|
||||
default: '',
|
||||
});
|
||||
|
||||
export const Footer = (props: IGridviewPanelProps) => {
|
||||
const selectedPanel = useRecoilValue(selectedPanelAtom);
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
height: '22px',
|
||||
backgroundColor: 'dodgerblue',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
padding: '0px 8px',
|
||||
}}
|
||||
>
|
||||
<span style={{ flexGrow: 1 }} />
|
||||
<span>{selectedPanel}</span>
|
||||
</div>
|
||||
);
|
||||
};
|
@ -0,0 +1,101 @@
|
||||
{
|
||||
"grid": {
|
||||
"root": {
|
||||
"type": "branch",
|
||||
"data": [
|
||||
{
|
||||
"type": "leaf",
|
||||
"data": {
|
||||
"id": "group_1",
|
||||
"views": [
|
||||
"split_panel"
|
||||
],
|
||||
"activeView": "split_panel"
|
||||
},
|
||||
"size": 371
|
||||
},
|
||||
{
|
||||
"type": "branch",
|
||||
"data": [
|
||||
{
|
||||
"type": "leaf",
|
||||
"data": {
|
||||
"id": "group_2",
|
||||
"views": [
|
||||
"item2"
|
||||
],
|
||||
"activeView": "item2"
|
||||
},
|
||||
"size": 792
|
||||
},
|
||||
{
|
||||
"type": "leaf",
|
||||
"data": {
|
||||
"id": "group_3",
|
||||
"views": [
|
||||
"panel_2"
|
||||
],
|
||||
"activeView": "panel_2"
|
||||
},
|
||||
"size": 792
|
||||
}
|
||||
],
|
||||
"size": 371
|
||||
},
|
||||
{
|
||||
"type": "leaf",
|
||||
"data": {
|
||||
"id": "group_4",
|
||||
"views": [
|
||||
"panel_0"
|
||||
],
|
||||
"activeView": "panel_0"
|
||||
},
|
||||
"size": 372
|
||||
}
|
||||
],
|
||||
"size": 1584
|
||||
},
|
||||
"height": 1114,
|
||||
"width": 1584,
|
||||
"orientation": "HORIZONTAL"
|
||||
},
|
||||
"panels": {
|
||||
"panel_0": {
|
||||
"id": "panel_0",
|
||||
"contentId": "test_component",
|
||||
"tabId": "__DEFAULT_TAB__",
|
||||
"props": {
|
||||
"text": "how low?"
|
||||
},
|
||||
"title": "Item 1",
|
||||
"state": {}
|
||||
},
|
||||
"item2": {
|
||||
"id": "item2",
|
||||
"contentId": "test_component",
|
||||
"tabId": "__DEFAULT_TAB__",
|
||||
"props": {},
|
||||
"title": "Item 2",
|
||||
"state": {}
|
||||
},
|
||||
"split_panel": {
|
||||
"id": "split_panel",
|
||||
"contentId": "split_panel",
|
||||
"tabId": "__DEFAULT_TAB__",
|
||||
"props": {},
|
||||
"title": "Item 3 with a long title",
|
||||
"state": {}
|
||||
},
|
||||
"panel_2": {
|
||||
"id": "panel_2",
|
||||
"contentId": "test_component",
|
||||
"tabId": "__DEFAULT_TAB__",
|
||||
"props": {},
|
||||
"title": "Item 3",
|
||||
"suppressClosable": true,
|
||||
"state": {}
|
||||
}
|
||||
},
|
||||
"activeGroup": "group_2"
|
||||
}
|
22
build/packages/dockview-demo/src/layout-grid/layoutGrid.scss
Normal file
@ -0,0 +1,22 @@
|
||||
.context-menu {
|
||||
position: absolute;
|
||||
height: 100px;
|
||||
width: 170px;
|
||||
font-size: 13px;
|
||||
z-index: 999;
|
||||
color: rgb(204, 204, 204);
|
||||
background: rgb(37, 37, 38);
|
||||
box-shadow: rgb(0, 0, 0) 0px 2px 4px;
|
||||
padding: 10px 0px;
|
||||
|
||||
.context-action {
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
padding: 2px 10px;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
background-color: rgb(51, 51, 51);
|
||||
}
|
||||
}
|
||||
}
|
334
build/packages/dockview-demo/src/layout-grid/layoutGrid.tsx
Normal file
@ -0,0 +1,334 @@
|
||||
import * as React from 'react';
|
||||
import * as ReactDOM from 'react-dom';
|
||||
import {
|
||||
IDockviewPanelProps,
|
||||
IGridviewPanelProps,
|
||||
TabContextMenuEvent,
|
||||
DockviewReadyEvent,
|
||||
DockviewReact,
|
||||
DockviewApi,
|
||||
IWatermarkPanelProps,
|
||||
IDockviewPanel,
|
||||
PanelCollection,
|
||||
} from 'dockview';
|
||||
import { CustomTab } from './customTab';
|
||||
import { Settings } from './settingsPanel';
|
||||
import { useLayoutRegistry } from './registry';
|
||||
import { SplitPanel } from './splitPanel';
|
||||
import './layoutGrid.scss';
|
||||
import { WelcomePanel } from '../panels/welcome/welcome';
|
||||
import { SplitviewPanel } from '../panels/splitview/splitview';
|
||||
import { GridviewDemoPanel } from '../panels/gridview/gridview';
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
import { selectedPanelAtom } from './footer';
|
||||
import { ExampleFunctions } from './panels/exampleFunctions';
|
||||
import { CompositeDisposable } from '../lifecycle';
|
||||
|
||||
const WatermarkComponent = () => {
|
||||
return (
|
||||
<div style={{ backgroundColor: 'black', color: 'white' }}>
|
||||
Watermark component
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const Test = (props: IDockviewPanelProps) => {
|
||||
const [counter, setCounter] = React.useState<number>(0);
|
||||
|
||||
React.useEffect(() => {
|
||||
const interval = setInterval(() => {
|
||||
setCounter((_) => _ + 1);
|
||||
}, 2000);
|
||||
|
||||
return () => {
|
||||
clearInterval(interval);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div>{`custom body ${counter}`}</div>
|
||||
<button>Toggle</button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const components: PanelCollection<IDockviewPanelProps> = {
|
||||
test: Test,
|
||||
welcome: WelcomePanel,
|
||||
splitview: SplitviewPanel,
|
||||
gridview: GridviewDemoPanel,
|
||||
inner_component: (props: IDockviewPanelProps) => {
|
||||
const _api = React.useRef<DockviewApi>();
|
||||
|
||||
const onReady = (event: DockviewReadyEvent) => {
|
||||
_api.current = event.api;
|
||||
|
||||
event.api.addPanel({
|
||||
component: 'test_component',
|
||||
id: 'inner-1',
|
||||
title: 'inner-1',
|
||||
});
|
||||
event.api.addPanel({
|
||||
component: 'test_component',
|
||||
id: 'inner-2',
|
||||
title: 'inner-2',
|
||||
});
|
||||
event.api.addPanel({
|
||||
component: 'test_component',
|
||||
id: nextGuid(),
|
||||
title: 'inner-3',
|
||||
position: {
|
||||
direction: 'within',
|
||||
referencePanel: 'inner-1',
|
||||
},
|
||||
});
|
||||
event.api.addPanel({
|
||||
component: 'test_component',
|
||||
id: nextGuid(),
|
||||
title: 'inner-4',
|
||||
position: {
|
||||
direction: 'within',
|
||||
referencePanel: 'inner-2',
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
boxSizing: 'border-box',
|
||||
// borderTop: "1px solid var(--dv-separator-border)",
|
||||
}}
|
||||
>
|
||||
<DockviewReact
|
||||
onReady={onReady}
|
||||
components={components}
|
||||
watermarkComponent={WatermarkComponent}
|
||||
tabHeight={20}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
test_component: ExampleFunctions,
|
||||
settings: Settings,
|
||||
split_panel: SplitPanel,
|
||||
};
|
||||
|
||||
const tabComponents = {
|
||||
default: CustomTab,
|
||||
};
|
||||
|
||||
export const nextGuid = (() => {
|
||||
let counter = 0;
|
||||
return () => 'panel_' + (counter++).toString();
|
||||
})();
|
||||
|
||||
export const TestGrid = (props: IGridviewPanelProps) => {
|
||||
const [api, setApi] = React.useState<DockviewApi>();
|
||||
const registry = useLayoutRegistry();
|
||||
|
||||
const onReady = (event: DockviewReadyEvent) => {
|
||||
const api = event.api;
|
||||
setApi(api);
|
||||
registry.register('dockview', api);
|
||||
};
|
||||
|
||||
const setSelectedPanel = useRecoilCallback(
|
||||
({ set }) =>
|
||||
(value: string) =>
|
||||
set(selectedPanelAtom, value),
|
||||
[]
|
||||
);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!api) {
|
||||
return () => {
|
||||
//
|
||||
};
|
||||
}
|
||||
props.api.setConstraints({
|
||||
minimumWidth: () => api.minimumWidth,
|
||||
minimumHeight: () => api.minimumHeight,
|
||||
});
|
||||
|
||||
const disposable = new CompositeDisposable(
|
||||
api.onDidLayoutChange(() => {
|
||||
const state = api.toJSON();
|
||||
localStorage.setItem('dockview', JSON.stringify(state));
|
||||
}),
|
||||
api.onDidActivePanelChange((e) => {
|
||||
setSelectedPanel(e?.id || '');
|
||||
})
|
||||
);
|
||||
|
||||
const state = localStorage.getItem('dockview');
|
||||
let success = false;
|
||||
if (state) {
|
||||
try {
|
||||
api.fromJSON(JSON.parse(state));
|
||||
success = true;
|
||||
} catch (err) {
|
||||
console.error('failed to load layout', err);
|
||||
}
|
||||
}
|
||||
|
||||
const welcomePanel = api.getPanel('welcome');
|
||||
|
||||
if (!welcomePanel) {
|
||||
api.addPanel({
|
||||
component: 'welcome',
|
||||
id: 'welcome',
|
||||
title: 'Welcome',
|
||||
suppressClosable: true,
|
||||
});
|
||||
}
|
||||
|
||||
return () => {
|
||||
disposable.dispose();
|
||||
};
|
||||
}, [api]);
|
||||
|
||||
const [coord, setCoord] =
|
||||
React.useState<{
|
||||
x: number;
|
||||
y: number;
|
||||
panel: IDockviewPanel;
|
||||
}>(undefined);
|
||||
|
||||
const onTabContextMenu = React.useMemo(
|
||||
() => (event: TabContextMenuEvent) => {
|
||||
event.event.preventDefault();
|
||||
console.log(event.panel);
|
||||
const cb = (event: MouseEvent) => {
|
||||
let element: HTMLElement = event.target as HTMLElement;
|
||||
|
||||
while (element) {
|
||||
if (element.classList.contains('context-menu')) {
|
||||
return;
|
||||
}
|
||||
element = element.parentElement;
|
||||
}
|
||||
|
||||
window.removeEventListener('mousedown', cb);
|
||||
setCoord(undefined);
|
||||
};
|
||||
window.addEventListener('mousedown', cb);
|
||||
setCoord({
|
||||
x: event.event.clientX,
|
||||
y: event.event.clientY,
|
||||
panel: event.panel,
|
||||
});
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
const onClose = () => {
|
||||
setCoord(undefined);
|
||||
coord.panel.api.close();
|
||||
};
|
||||
|
||||
const onChangeName = () => {
|
||||
setCoord(undefined);
|
||||
coord.panel.api.setTitle('This looks new?');
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{coord &&
|
||||
ReactDOM.createPortal(
|
||||
<div
|
||||
className="context-menu"
|
||||
style={{
|
||||
left: `${coord.x}px`,
|
||||
top: `${coord.y}px`,
|
||||
}}
|
||||
>
|
||||
<div className="context-action" onClick={onClose}>
|
||||
Close
|
||||
</div>
|
||||
<div className="context-action" onClick={onChangeName}>
|
||||
Rename
|
||||
</div>
|
||||
</div>,
|
||||
document.getElementById('anchor')
|
||||
)}
|
||||
<DockviewReact
|
||||
onReady={onReady}
|
||||
components={components}
|
||||
tabComponents={tabComponents}
|
||||
onTabContextMenu={onTabContextMenu}
|
||||
watermarkComponent={Watermark}
|
||||
showDndOverlay={(ev) => {
|
||||
return true;
|
||||
}}
|
||||
onDidDrop={(ev) => {
|
||||
console.log('onDidDrop', ev);
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const Watermark = (props: IWatermarkPanelProps) => {
|
||||
const [groups, setGroups] = React.useState<number>(props.containerApi.size);
|
||||
React.useEffect(() => {
|
||||
const disposable = new CompositeDisposable(
|
||||
props.containerApi.onDidLayoutChange(() => {
|
||||
console.log(`groups2 ${props.containerApi.size}`);
|
||||
setGroups(props.containerApi.size);
|
||||
})
|
||||
);
|
||||
|
||||
return () => {
|
||||
disposable.dispose();
|
||||
};
|
||||
}, []);
|
||||
|
||||
const onClick = () => {
|
||||
props.close();
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
width: '100%',
|
||||
flexGrow: 1,
|
||||
height: '100%',
|
||||
flexDirection: 'column',
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
height: '35px',
|
||||
display: 'flex',
|
||||
width: '100%',
|
||||
}}
|
||||
>
|
||||
<span style={{ flexGrow: 1 }} />
|
||||
{groups > 1 && (
|
||||
<span
|
||||
onClick={onClick}
|
||||
style={{
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
<a className="close-action"></a>
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
flexGrow: 1,
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
}}
|
||||
>
|
||||
<span>Watermark component</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
67
build/packages/dockview-demo/src/layout-grid/panel.tsx
Normal file
@ -0,0 +1,67 @@
|
||||
import * as React from 'react';
|
||||
import { IGridviewPanelProps } from 'dockview';
|
||||
import { CompositeDisposable } from '../lifecycle';
|
||||
|
||||
export const Panel = (props: IGridviewPanelProps) => {
|
||||
const [active, setActive] = React.useState<boolean>();
|
||||
const [focused, setFocused] = React.useState<boolean>();
|
||||
|
||||
React.useEffect(() => {
|
||||
const disposable = new CompositeDisposable(
|
||||
props.api.onDidActiveChange((event) => {
|
||||
setActive(event.isActive);
|
||||
}),
|
||||
props.api.onDidFocusChange((event) => {
|
||||
setFocused(event.isFocused);
|
||||
})
|
||||
);
|
||||
|
||||
return () => {
|
||||
disposable.dispose();
|
||||
};
|
||||
}, []);
|
||||
|
||||
const onToggle = () => {
|
||||
const editorPanel = props.containerApi.getPanel('editor');
|
||||
editorPanel.api.setVisible(!editorPanel.api.isVisible);
|
||||
};
|
||||
|
||||
const onClose = () => {
|
||||
const editorPanel = props.containerApi.getPanel('editor');
|
||||
|
||||
editorPanel.api.setVisible(true);
|
||||
props.api.setVisible(false);
|
||||
};
|
||||
|
||||
const onMove = () => {
|
||||
const thisPanel = props.containerApi.getPanel('panel');
|
||||
const editor = props.containerApi.getPanel('editor');
|
||||
|
||||
props.containerApi.movePanel(thisPanel, {
|
||||
direction: 'left',
|
||||
reference: editor.id,
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
borderTop: `1px solid var(--dv-separator-border)`,
|
||||
boxSizing: 'border-box',
|
||||
backgroundColor: 'rgb(30,30,30)',
|
||||
height: '100%',
|
||||
}}
|
||||
>
|
||||
<div style={{ display: 'flex', padding: '5px' }}>
|
||||
<span>This panel is outside of the dockable layer</span>
|
||||
<span style={{ flexGrow: 1 }} />
|
||||
{/* <button onClick={onMove}>Move</button> */}
|
||||
<button onClick={onToggle}>Resize</button>
|
||||
<button onClick={onClose}>Close</button>
|
||||
</div>
|
||||
<div style={{ padding: '0px 5px' }}>
|
||||
<div>{`isPanelActive: ${active} isPanelFocused: ${focused}`}</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
@ -0,0 +1,14 @@
|
||||
.example-functions-panel {
|
||||
padding: 5px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.example-functions-panel-header-bar {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.example-functions-panel-section {
|
||||
padding: 8px 0px;
|
||||
}
|
||||
}
|
@ -0,0 +1,102 @@
|
||||
import { IDockviewPanelProps } from 'dockview';
|
||||
import * as React from 'react';
|
||||
import { CompositeDisposable } from '../../lifecycle';
|
||||
import './exampleFunctions.scss';
|
||||
|
||||
export const ExampleFunctions = (
|
||||
props: IDockviewPanelProps & { [key: string]: any }
|
||||
) => {
|
||||
const [panelState, setPanelState] = React.useState<{
|
||||
isGroupActive: boolean;
|
||||
isPanelVisible: boolean;
|
||||
}>({
|
||||
isGroupActive: props.api.isActive,
|
||||
isPanelVisible: props.api.isVisible,
|
||||
});
|
||||
const [panelName, setPanelName] = React.useState<string>();
|
||||
const input = React.useRef<HTMLInputElement>();
|
||||
|
||||
React.useEffect(() => {
|
||||
const disposable = new CompositeDisposable(
|
||||
props.api.onDidActiveChange((event) => {
|
||||
setPanelState((_) => ({
|
||||
..._,
|
||||
isGroupActive: event.isActive,
|
||||
}));
|
||||
}),
|
||||
props.api.onDidVisibilityChange((x) => {
|
||||
setPanelState((_) => ({
|
||||
..._,
|
||||
isPanelVisible: x.isVisible,
|
||||
}));
|
||||
}),
|
||||
props.api.onDidFocusChange(({ isFocused }) => {
|
||||
if (isFocused) {
|
||||
input.current.focus();
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
return () => {
|
||||
disposable.dispose();
|
||||
};
|
||||
}, []);
|
||||
|
||||
const onRename = () => {
|
||||
props.api.setTitle(panelName);
|
||||
};
|
||||
|
||||
const onClose = () => {
|
||||
props.api.close();
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="example-functions-panel">
|
||||
<div className="example-functions-panel-header-bar">
|
||||
<span style={{ padding: '0px 8px' }}>
|
||||
<span>{'isGroupActive: '}</span>
|
||||
<span
|
||||
style={{
|
||||
color: panelState.isGroupActive
|
||||
? '#23d16f'
|
||||
: '#cd312b',
|
||||
}}
|
||||
>
|
||||
{`${panelState.isGroupActive}`}
|
||||
</span>
|
||||
</span>
|
||||
<span style={{ padding: '0px 8px' }}>
|
||||
<span>{'isPanelVisible: '}</span>
|
||||
<span
|
||||
style={{
|
||||
color: panelState.isPanelVisible
|
||||
? '#23d16f'
|
||||
: '#cd312b',
|
||||
}}
|
||||
>
|
||||
{`${panelState.isPanelVisible}`}
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div className="example-functions-panel-section">
|
||||
<input
|
||||
value={panelName}
|
||||
placeholder="New Panel Name"
|
||||
type="text"
|
||||
onChange={(event) => setPanelName(event.target.value)}
|
||||
/>
|
||||
<button onClick={onRename}>Rename</button>
|
||||
</div>
|
||||
|
||||
<input
|
||||
style={{ width: '175px' }}
|
||||
ref={input}
|
||||
placeholder="This is focused by the panel"
|
||||
/>
|
||||
<input
|
||||
style={{ width: '175px' }}
|
||||
placeholder="This is also focusable"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
25
build/packages/dockview-demo/src/layout-grid/registry.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import * as React from 'react';
|
||||
|
||||
export interface IRegistry {
|
||||
register<T>(name: string, value: T): void;
|
||||
get<T>(name: string): T;
|
||||
}
|
||||
|
||||
class Registry implements IRegistry {
|
||||
private cache = new Map<string, any>();
|
||||
|
||||
register<T>(name: string, value: T) {
|
||||
this.cache.set(name, value);
|
||||
}
|
||||
|
||||
get<T>(name: string) {
|
||||
return this.cache.get(name) as T;
|
||||
}
|
||||
}
|
||||
|
||||
const RegistryInstance = new Registry();
|
||||
|
||||
export const useLayoutRegistry = (): IRegistry => {
|
||||
const ref = React.useRef<IRegistry>(RegistryInstance);
|
||||
return ref.current;
|
||||
};
|
@ -0,0 +1,38 @@
|
||||
import * as React from 'react';
|
||||
import { IDockviewPanelProps } from 'dockview';
|
||||
|
||||
export const Settings = (props: IDockviewPanelProps) => {
|
||||
const [tabHeight, setTabHeight] = React.useState<number>(
|
||||
props.containerApi.getTabHeight()
|
||||
);
|
||||
|
||||
const onTabHeightChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const value = Number(event.target.value);
|
||||
if (!Number.isNaN(value)) {
|
||||
setTabHeight(value);
|
||||
}
|
||||
};
|
||||
|
||||
const onClick = () => {
|
||||
props.containerApi.setTabHeight(tabHeight);
|
||||
};
|
||||
|
||||
const onRemove = () => {
|
||||
props.containerApi.setTabHeight(undefined);
|
||||
};
|
||||
|
||||
return (
|
||||
<div style={{ height: '100%', color: 'white' }}>
|
||||
<label>
|
||||
Tab height
|
||||
<input
|
||||
onChange={onTabHeightChange}
|
||||
value={tabHeight}
|
||||
type="number"
|
||||
/>
|
||||
<button onClick={onClick}>Apply</button>
|
||||
<button onClick={onRemove}>Remove</button>
|
||||
</label>
|
||||
</div>
|
||||
);
|
||||
};
|
@ -0,0 +1,57 @@
|
||||
{
|
||||
"views": [
|
||||
{
|
||||
"size": 22,
|
||||
"data": {
|
||||
"id": "1",
|
||||
"component": "controlCenter",
|
||||
|
||||
"props": {},
|
||||
"title": "Control Center",
|
||||
"state": {}
|
||||
},
|
||||
"minimumSize": 120
|
||||
},
|
||||
{
|
||||
"size": 508,
|
||||
"data": {
|
||||
"id": "2",
|
||||
"component": "default",
|
||||
|
||||
"props": {},
|
||||
"title": "Panel 1",
|
||||
"state": {}
|
||||
},
|
||||
"minimumSize": 120,
|
||||
"expanded": true
|
||||
},
|
||||
{
|
||||
"size": 248,
|
||||
"data": {
|
||||
"id": "3",
|
||||
"component": "default",
|
||||
|
||||
"props": {},
|
||||
"title": "Panel 2",
|
||||
"state": {}
|
||||
},
|
||||
"minimumSize": 120,
|
||||
"expanded": true
|
||||
},
|
||||
{
|
||||
"size": 22,
|
||||
"data": {
|
||||
"id": "4",
|
||||
"component": "default",
|
||||
|
||||
"props": {},
|
||||
"title": "Panel 3",
|
||||
"state": {}
|
||||
},
|
||||
"minimumSize": 120,
|
||||
"expanded": false
|
||||
}
|
||||
],
|
||||
"size": 800,
|
||||
"orientation": "VERTICAL"
|
||||
}
|
18
build/packages/dockview-demo/src/layout-grid/sidebar.scss
Normal file
@ -0,0 +1,18 @@
|
||||
.pane-header {
|
||||
.my-header {
|
||||
.actions {
|
||||
display: none;
|
||||
}
|
||||
&.within {
|
||||
.actions {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:focus {
|
||||
.actions {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
}
|
97
build/packages/dockview-demo/src/layout-grid/sidebar.tsx
Normal file
@ -0,0 +1,97 @@
|
||||
import * as React from 'react';
|
||||
import {
|
||||
IGridviewPanelProps,
|
||||
PaneviewReact,
|
||||
PaneviewReadyEvent,
|
||||
IPaneviewPanelProps,
|
||||
PaneviewApi,
|
||||
PaneviewDropEvent,
|
||||
} from 'dockview';
|
||||
import { ControlCenter } from './controlCenter';
|
||||
import './sidebar.scss';
|
||||
import { CompositeDisposable } from '../lifecycle';
|
||||
|
||||
const components = {
|
||||
default: (props: IPaneviewPanelProps) => {
|
||||
return <div style={{ height: '100%' }}>This is an example panel</div>;
|
||||
},
|
||||
controlCenter: ControlCenter,
|
||||
};
|
||||
|
||||
export const Sidebar = (props: IGridviewPanelProps) => {
|
||||
const api = React.useRef<PaneviewApi>();
|
||||
|
||||
const onReady = (event: PaneviewReadyEvent) => {
|
||||
api.current = event.api;
|
||||
|
||||
console.log(props.api.width, props.api.height);
|
||||
|
||||
event.api.fromJSON(require('./sidebar.layout.json'));
|
||||
|
||||
return;
|
||||
|
||||
event.api.addPanel({
|
||||
id: '1',
|
||||
component: 'controlCenter',
|
||||
title: 'Control Center',
|
||||
});
|
||||
event.api.addPanel({
|
||||
id: '2',
|
||||
component: 'default',
|
||||
title: 'Panel 1',
|
||||
});
|
||||
event.api.addPanel({
|
||||
id: '3',
|
||||
component: 'default',
|
||||
title: 'Panel 2',
|
||||
});
|
||||
event.api.addPanel({
|
||||
id: '4',
|
||||
component: 'default',
|
||||
title: 'Panel 3',
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
console.log(JSON.stringify(event.api.toJSON(), null, 4));
|
||||
}, 10000);
|
||||
};
|
||||
|
||||
React.useEffect(() => {
|
||||
const disposable = new CompositeDisposable(
|
||||
props.api.onDidDimensionsChange((ev) => {
|
||||
api.current.layout(ev.width, ev.height);
|
||||
}),
|
||||
props.api.onDidVisibilityChange((event) => {
|
||||
console.log(event);
|
||||
}),
|
||||
props.api.onDidFocusChange(({ isFocused }) => {
|
||||
if (isFocused) {
|
||||
api.current.focus();
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
return () => {
|
||||
disposable.dispose();
|
||||
};
|
||||
}, []);
|
||||
|
||||
const onDidDrop = React.useCallback((event: PaneviewDropEvent) => {
|
||||
console.log('drop', event);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
backgroundColor: 'rgb(37,37,38)',
|
||||
height: '100%',
|
||||
}}
|
||||
>
|
||||
<PaneviewReact
|
||||
components={components}
|
||||
onReady={onReady}
|
||||
onDidDrop={onDidDrop}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
145
build/packages/dockview-demo/src/layout-grid/splitPanel.tsx
Normal file
@ -0,0 +1,145 @@
|
||||
import * as React from 'react';
|
||||
import {
|
||||
ISplitviewPanelProps,
|
||||
Orientation,
|
||||
SplitviewReadyEvent,
|
||||
SplitviewReact,
|
||||
SplitviewApi,
|
||||
IDockviewPanelProps,
|
||||
} from 'dockview';
|
||||
import { useLayoutRegistry } from './registry';
|
||||
import './splitPanel.scss';
|
||||
import { CompositeDisposable } from '../lifecycle';
|
||||
|
||||
const components = {
|
||||
default1: (props: ISplitviewPanelProps) => {
|
||||
const ref = React.useRef<HTMLInputElement>();
|
||||
const [focused, setFocused] = React.useState<boolean>(false);
|
||||
const [active, setActive] = React.useState<boolean>(false);
|
||||
|
||||
const onClick = (ev: React.MouseEvent<HTMLButtonElement>) => {
|
||||
props.api.setSize({ size: 300 });
|
||||
};
|
||||
|
||||
React.useEffect(() => {
|
||||
const disposable = new CompositeDisposable(
|
||||
props.api.onDidFocusChange((event) => {
|
||||
setFocused(event.isFocused);
|
||||
}),
|
||||
props.api.onDidActiveChange((event) => {
|
||||
setActive(event.isActive);
|
||||
}),
|
||||
props.api.onDidFocusChange(({ isFocused }) => {
|
||||
if (isFocused) {
|
||||
ref.current.focus();
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
return () => {
|
||||
disposable.dispose();
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div style={{ height: '100%' }}>
|
||||
<div style={{ display: 'flex', padding: '5px' }}>
|
||||
<div>This is a splitview panel inside a dockable panel</div>
|
||||
<span style={{ flexGrow: 1 }} />
|
||||
<button onClick={onClick}>resize</button>
|
||||
</div>
|
||||
<div style={{ padding: '0px 5px' }}>
|
||||
<div>{`isPanelActive: ${active} isPanelFocused: ${focused}`}</div>
|
||||
<input ref={ref} type="text" placeholder="focus test" />
|
||||
<span>{(props as any).text}</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
export const SplitPanel = (props: IDockviewPanelProps) => {
|
||||
const api = React.useRef<SplitviewApi>();
|
||||
const registry = useLayoutRegistry();
|
||||
|
||||
React.useEffect(() => {
|
||||
const disposable = new CompositeDisposable(
|
||||
props.api.onDidDimensionsChange((event) => {
|
||||
api.current?.layout(event.width, event.height - 25);
|
||||
}),
|
||||
props.api.onDidFocusChange(({ isFocused }) => {
|
||||
if (isFocused) {
|
||||
api.current.focus();
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
return () => {
|
||||
disposable.dispose();
|
||||
};
|
||||
}, []);
|
||||
|
||||
const onReady = (event: SplitviewReadyEvent) => {
|
||||
api.current = event.api;
|
||||
|
||||
registry.register('splitview', event.api);
|
||||
|
||||
event.api.fromJSON(require('./splitpanel.layout.json'));
|
||||
return;
|
||||
event.api.addPanel({
|
||||
id: '1',
|
||||
component: 'default1',
|
||||
snap: true,
|
||||
params: {
|
||||
text: 'hiya',
|
||||
},
|
||||
});
|
||||
event.api.addPanel({ id: '2', component: 'default1' });
|
||||
};
|
||||
|
||||
const onUpdateProps = () => {
|
||||
const panel = api.current.getPanel('1');
|
||||
panel.update({ params: { text: Date.now().toString() } });
|
||||
};
|
||||
|
||||
const onAdd = () => {
|
||||
api.current.addPanel({
|
||||
id: `${Date.now()}`,
|
||||
component: 'default1',
|
||||
snap: true,
|
||||
params: {
|
||||
text: 'hiya',
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const onRemove = () => {
|
||||
const panels = api.current.panels;
|
||||
if (panels.length === 0) {
|
||||
return;
|
||||
}
|
||||
api.current.removePanel(panels[panels.length - 1]);
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
height: '100%',
|
||||
color: 'white',
|
||||
}}
|
||||
>
|
||||
<div style={{ height: '25px' }}>
|
||||
<button onClick={onUpdateProps}>Update props</button>
|
||||
<button onClick={onAdd}>Add</button>
|
||||
<button onClick={onRemove}>Remove</button>
|
||||
</div>
|
||||
<SplitviewReact
|
||||
components={components}
|
||||
onReady={onReady}
|
||||
orientation={Orientation.VERTICAL}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|