├── .github ├── FUNDING.yml └── workflows │ └── build_ghpages.yml ├── .gitignore ├── .gitignore.ghpages ├── README.md ├── dist ├── Container.d.ts ├── Container.jsx ├── Container.jsx.map ├── Panel.d.ts ├── Panel.jsx ├── Panel.jsx.map ├── global.d.ts ├── global.js ├── global.js.map ├── index.d.ts ├── index.js ├── index.js.map ├── rect.d.ts ├── rect.js ├── rect.js.map ├── refState.d.ts ├── refState.js ├── refState.js.map ├── state.d.ts ├── state.js └── state.js.map ├── example.gif ├── example ├── Clock.tsx ├── Counter.tsx ├── TextEditor.tsx └── main.tsx ├── index.html ├── package-lock.json ├── package.json ├── src ├── Container.tsx ├── Panel.tsx ├── global.ts ├── index.ts ├── rect.ts ├── refState.ts └── state.ts ├── tsconfig.json └── webpack.config.cjs /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | patreon: hlorenzi 2 | ko_fi: hlorenzi -------------------------------------------------------------------------------- /.github/workflows/build_ghpages.yml: -------------------------------------------------------------------------------- 1 | name: Build GitHub Pages 2 | 3 | on: 4 | push: 5 | branches: ["main"] 6 | 7 | jobs: 8 | build: 9 | 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - name: Checkout code 14 | uses: actions/checkout@master 15 | with: 16 | fetch-depth: 0 17 | 18 | - name: Use Node.js 15.x 19 | uses: actions/setup-node@v1 20 | with: 21 | node-version: 15.x 22 | 23 | - run: git branch -D ghpages 24 | continue-on-error: true 25 | 26 | - run: git checkout -b ghpages 27 | - run: rm .gitignore 28 | - run: mv .gitignore.ghpages .gitignore 29 | - run: npm ci 30 | - run: npm run build2 31 | - run: git config user.name github-actions 32 | - run: git config user.email github-actions@github.com 33 | - run: git add -A 34 | - run: git commit -m "build GitHub Pages" 35 | - run: git push -f origin ghpages -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules/ 2 | /build/ -------------------------------------------------------------------------------- /.gitignore.ghpages: -------------------------------------------------------------------------------- 1 | /node_modules/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-dockable 2 | 3 | ![react-dockable example video](example.gif) 4 | 5 | An easy-to-use dockable window manager for React, 6 | fully embracing hooks! 7 | 8 | [Try it right now!](https://hlorenzi.github.io/react-dockable/) 9 | 10 | Your custom content's lifecycle hooks are respected, 11 | so `useState`, `useEffect`, etc. work out of the box, 12 | and state carries over even if the user rearranges 13 | their panels. 14 | 15 | [![npm][badge-npm-img]][badge-npm-url] 16 | 17 | [![Discord][badge-discord-img]][badge-discord-url] 18 | 19 | [badge-discord-img]: https://img.shields.io/discord/394999035540275222?label=Join%20the%20Discord%20server!&logo=discord 20 | [badge-discord-url]: https://discord.com/invite/pXeDXGD 21 | 22 | [badge-npm-img]: https://img.shields.io/npm/v/@hlorenzi/react-dockable 23 | [badge-npm-url]: https://www.npmjs.com/package/@hlorenzi/react-dockable 24 | 25 | ## Installation 26 | 27 | ``` 28 | npm install @hlorenzi/react-dockable 29 | ``` 30 | 31 | ## Example 32 | 33 | ```tsx 34 | import * as React from "react" 35 | import * as Dockable from "@hlorenzi/react-dockable" 36 | 37 | function App() 38 | { 39 | // Create the base state, 40 | // and set up initial content 41 | const state = Dockable.useDockable((state) => 42 | { 43 | Dockable.createDockedPanel( 44 | state, state.rootPanel, Dockable.DockMode.Full, 45 | ) 46 | }) 47 | 48 | // Render the root Container element, 49 | // which handles all interactions on your behalf 50 | return
54 | 55 | 56 | 57 |
58 | } 59 | 60 | // Your custom element! 61 | function Counter() 62 | { 63 | const [value, setValue] = React.useState(0) 64 | const countUp = () => setValue(value + 1) 65 | 66 | const ctx = Dockable.useContentContext() 67 | ctx.setTitle(`Count: ${ value }`) 68 | ctx.setPreferredSize(300, 250) 69 | 70 | return
71 | { value } 72 | 73 |
74 | } 75 | ``` 76 | -------------------------------------------------------------------------------- /dist/Container.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | import * as Dockable from "./index.js"; 3 | export declare function Container(props: { 4 | state: Dockable.RefState; 5 | anchorSize?: number; 6 | resizeHandleSize?: number; 7 | dividerSize?: number; 8 | tabHeight?: number; 9 | }): JSX.Element; 10 | -------------------------------------------------------------------------------- /dist/Container.jsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import * as Dockable from "./index.js"; 3 | import styled from "styled-components"; 4 | const StyledContainer = styled.div ` 5 | --dockable-voidBkg: #252525; 6 | --dockable-panelBkg: #1e1e1e; 7 | --dockable-panelInactiveBorder: #393939; 8 | --dockable-panelActiveBorder: #777777; 9 | --dockable-panelTabBkg: #2d2d2d; 10 | --dockable-panelTabTextColor: #ffffff; 11 | --dockable-overlayColor: #00aaff44; 12 | --dockable-anchorColor: #00aaff; 13 | --dockable-buttonHoverBkg: #323232; 14 | --dockable-scrollbarColor: #777777; 15 | 16 | width: 100%; 17 | height: 100%; 18 | background-color: var(--dockable-voidBkg); 19 | `; 20 | const StyledContentRoot = styled.div ` 21 | display: ${props => props.isCurrentTab ? "grid" : "none"}; 22 | grid-template: 100% / 100%; 23 | 24 | position: absolute; 25 | box-sizing: border-box; 26 | contain: strict; 27 | 28 | color: #fff; 29 | text-align: left; 30 | 31 | background-color: transparent; 32 | overflow: hidden; 33 | `; 34 | const StyledContentInner = styled.div ` 35 | grid-row: 1; 36 | grid-column: 1; 37 | width: 100%; 38 | height: 100%; 39 | `; 40 | const StyledBottomRightResizeHandle = styled.div ` 41 | width: ${props => props.size}px; 42 | height: ${props => props.size}px; 43 | 44 | grid-row: 1; 45 | grid-column: 1; 46 | align-self: end; 47 | justify-self: end; 48 | 49 | cursor: nwse-resize; 50 | z-index: 1; 51 | 52 | &:hover 53 | { 54 | background-color: var(--dockable-overlayColor); 55 | } 56 | `; 57 | const StyledDivider = styled.div ` 58 | &:hover 59 | { 60 | background-color: var(--dockable-overlayColor); 61 | } 62 | `; 63 | export function Container(props) { 64 | const [rect, setRect] = React.useState(new Dockable.Rect(0, 0, 0, 0)); 65 | const rootRef = React.useRef(null); 66 | const anchorSize = props.anchorSize ?? 5; 67 | const resizeHandleSize = props.anchorSize ?? 10; 68 | const dividerSize = props.anchorSize ?? 6; 69 | const tabHeight = props.anchorSize ?? 25; 70 | React.useLayoutEffect(() => { 71 | const onResize = () => { 72 | if (!rootRef.current) 73 | return; 74 | const elemRect = rootRef.current.getBoundingClientRect(); 75 | setRect(new Dockable.Rect(elemRect.x, elemRect.y, elemRect.width, elemRect.height)); 76 | }; 77 | onResize(); 78 | window.addEventListener("resize", onResize); 79 | return () => window.removeEventListener("resize", onResize); 80 | }, []); 81 | const rectRef = React.useRef(null); 82 | rectRef.current = rect; 83 | const layoutRef = React.useRef(null); 84 | layoutRef.current = React.useMemo(() => { 85 | return Dockable.getLayout(props.state.ref.current, new Dockable.Rect(rect.x, rect.y, rect.w - 1, rect.h - 1)); 86 | }, [rect, props.state.updateToken]); 87 | const setTitle = (layoutContent, title) => { 88 | if (layoutContent.content.title != title) { 89 | window.requestAnimationFrame(() => { 90 | layoutContent.content.title = title; 91 | props.state.commit(); 92 | }); 93 | } 94 | }; 95 | const setPreferredSize = (layoutContent, width, height) => { 96 | if (layoutContent.tabIndex == layoutContent.panel.currentTabIndex && 97 | (width != layoutContent.panel.preferredWidth || 98 | height != layoutContent.panel.preferredHeight)) { 99 | window.requestAnimationFrame(() => { 100 | layoutContent.panel.preferredWidth = width; 101 | layoutContent.panel.preferredHeight = height; 102 | layoutContent.panel.rect = new Dockable.Rect(layoutContent.panel.rect.x, layoutContent.panel.rect.y, width, height); 103 | props.state.commit(); 104 | }); 105 | } 106 | }; 107 | return 108 | 109 | {layoutRef.current.panelRects.map(panelRect => handleClickedPanel(props.state, panelRect.panel, null)} onClickTab={(tabNumber) => handleClickedPanel(props.state, panelRect.panel, tabNumber)} onCloseTab={(ev, tabNumber) => handleClosedTab(ev, props.state, panelRect.panel, tabNumber)} onDragHeader={(ev, tabNumber) => handleDraggedHeader(ev, props.state, layoutRef, rectRef, panelRect.panel, tabNumber)}/>)} 110 | 111 | {layoutRef.current.content.map(layoutContent => handleClickedPanel(props.state, layoutContent.panel, null)} style={{ 112 | left: (layoutContent.layoutPanel.rect.x) + "px", 113 | top: (layoutContent.layoutPanel.rect.y + tabHeight) + "px", 114 | width: (layoutContent.layoutPanel.rect.w) + "px", 115 | height: (layoutContent.layoutPanel.rect.h - tabHeight) + "px", 116 | zIndex: layoutContent.layoutPanel.zIndex * 3 + 1, 117 | }}> 118 | setTitle(layoutContent, title), 121 | setPreferredSize: (w, h) => setPreferredSize(layoutContent, w, h), 122 | }}> 123 | 124 | {layoutContent.content.element} 125 | 126 | 127 | 128 | {layoutContent.panel.floating && 129 | { 130 | handleClickedPanel(props.state, layoutContent.panel, null); 131 | handleDraggedEdge(ev, props.state, layoutRef, layoutContent.panel); 132 | }}/>} 133 | )} 134 | 135 | {layoutRef.current.dividers.map((divider, i) => handleDraggedDivider(ev, props.state, divider)} style={{ 136 | width: (divider.rect.w || dividerSize) + "px", 137 | height: (divider.rect.h || dividerSize) + "px", 138 | position: "absolute", 139 | left: (divider.rect.x - (!divider.vertical ? dividerSize / 2 : 0)) + "px", 140 | top: (divider.rect.y - (divider.vertical ? dividerSize / 2 : 0)) + "px", 141 | cursor: !divider.vertical ? 142 | "ew-resize" : 143 | "ns-resize", 144 | zIndex: 1, 145 | userSelect: "none", 146 | }}/>)} 147 | 148 | {props.state.ref.current.previewAnchor && 149 |
} 158 | 159 | {props.state.ref.current.showAnchors && 160 | layoutRef.current.anchors.map((anchor, i) => props.state.ref.current.draggedPanel !== anchor.panel && 161 |
)} 173 | 174 | ; 175 | } 176 | function handleDraggedDivider(ev, state, divider) { 177 | ev.preventDefault(); 178 | const onMouseMove = (ev) => { 179 | const mouseX = ev.pageX; 180 | const mouseY = ev.pageY; 181 | divider.panel.splitSize = 182 | Math.max(0.05, Math.min(0.95, ((divider.vertical ? mouseY : mouseX) - divider.resizeMin) / 183 | (divider.resizeMax - divider.resizeMin))); 184 | state.commit(); 185 | }; 186 | const onMouseUp = () => { 187 | window.removeEventListener("mousemove", onMouseMove); 188 | window.removeEventListener("mouseup", onMouseUp); 189 | }; 190 | window.addEventListener("mousemove", onMouseMove); 191 | window.addEventListener("mouseup", onMouseUp); 192 | } 193 | function handleDraggedEdge(ev, state, layout, panel) { 194 | ev.preventDefault(); 195 | ev.stopPropagation(); 196 | const startMouseX = ev.pageX; 197 | const startMouseY = ev.pageY; 198 | const layoutPanel = layout.current.panelRects.find(p => p.panel === panel); 199 | const startPanelRect = layoutPanel.rect; 200 | const onMouseMove = (ev) => { 201 | const mouseX = ev.pageX; 202 | const mouseY = ev.pageY; 203 | panel.rect = new Dockable.Rect(startPanelRect.x, startPanelRect.y, Math.max(150, startPanelRect.w + mouseX - startMouseX), Math.max(50, startPanelRect.h + mouseY - startMouseY)); 204 | state.commit(); 205 | }; 206 | const onMouseUp = () => { 207 | window.removeEventListener("mousemove", onMouseMove); 208 | window.removeEventListener("mouseup", onMouseUp); 209 | }; 210 | window.addEventListener("mousemove", onMouseMove); 211 | window.addEventListener("mouseup", onMouseUp); 212 | } 213 | function handleDraggedHeader(ev, state, layout, containerRect, draggedPanel, draggedTabIndex) { 214 | ev.preventDefault(); 215 | ev.stopPropagation(); 216 | const startMouseX = ev.pageX; 217 | const startMouseY = ev.pageY; 218 | const layoutPanel = layout.current.panelRects.find(p => p.panel === draggedPanel); 219 | let startPanelRect = layoutPanel.rect; 220 | let dragLocked = true; 221 | const onMouseMove = (ev) => { 222 | const mouseX = ev.pageX; 223 | const mouseY = ev.pageY; 224 | // Start dragging only when mouse moves far enough, and 225 | // undock panel at this moment if originally docked 226 | if (Math.abs(mouseX - startMouseX) > 10 || 227 | Math.abs(mouseY - startMouseY) > 10) { 228 | dragLocked = false; 229 | const floatingRect = new Dockable.Rect(mouseX - Math.min(draggedPanel.preferredWidth / 2, mouseX - startPanelRect.x), mouseY - (mouseY - startPanelRect.y), draggedPanel.preferredWidth, draggedPanel.preferredHeight); 230 | if (draggedTabIndex !== null && draggedPanel.contentList.length > 1) { 231 | // Remove single tab content from original panel and 232 | // transfer it to a new floating panel 233 | const content = draggedPanel.contentList[draggedTabIndex]; 234 | Dockable.removeContent(state.ref.current, draggedPanel, content.contentId); 235 | draggedPanel = Dockable.makePanel(state.ref.current); 236 | Dockable.addContent(state.ref.current, draggedPanel, content); 237 | Dockable.coallesceEmptyPanels(state.ref.current); 238 | draggedPanel.rect = startPanelRect = floatingRect; 239 | } 240 | else if (!draggedPanel.floating) { 241 | // Remove original docked panel and 242 | // transfer all content to a new floating panel 243 | const contents = [...draggedPanel.contentList]; 244 | const originalTabIndex = draggedPanel.currentTabIndex; 245 | for (const content of contents) 246 | Dockable.removeContent(state.ref.current, draggedPanel, content.contentId); 247 | draggedPanel = Dockable.makePanel(state.ref.current); 248 | for (const content of contents) 249 | Dockable.addContent(state.ref.current, draggedPanel, content); 250 | draggedPanel.currentTabIndex = originalTabIndex; 251 | Dockable.coallesceEmptyPanels(state.ref.current); 252 | draggedPanel.rect = startPanelRect = floatingRect; 253 | } 254 | state.ref.current.draggedPanel = draggedPanel; 255 | state.ref.current.showAnchors = true; 256 | state.commit(); 257 | } 258 | // Handle actual dragging 259 | if (!dragLocked) { 260 | // Move panel rect 261 | draggedPanel.rect = startPanelRect.displace(mouseX - startMouseX, mouseY - startMouseY); 262 | // Find nearest anchor 263 | let nearestDistSqr = 50 * 50; 264 | state.ref.current.previewAnchor = null; 265 | for (const anchor of layout.current.anchors) { 266 | if (anchor.panel === draggedPanel) 267 | continue; 268 | const xx = anchor.x - mouseX; 269 | const yy = anchor.y - mouseY; 270 | const distSqr = xx * xx + yy * yy; 271 | if (distSqr < nearestDistSqr) { 272 | nearestDistSqr = distSqr; 273 | state.ref.current.previewAnchor = anchor; 274 | } 275 | } 276 | state.commit(); 277 | } 278 | }; 279 | const onMouseUp = () => { 280 | window.removeEventListener("mousemove", onMouseMove); 281 | window.removeEventListener("mouseup", onMouseUp); 282 | // Dock dragged panel if near an anchor 283 | if (state.ref.current.previewAnchor) { 284 | Dockable.dock(state.ref.current, draggedPanel, state.ref.current.previewAnchor.panel, state.ref.current.previewAnchor.mode); 285 | } 286 | Dockable.clampFloatingPanels(state.ref.current, containerRect.current); 287 | state.ref.current.draggedPanel = null; 288 | state.ref.current.showAnchors = false; 289 | state.ref.current.previewAnchor = null; 290 | state.commit(); 291 | }; 292 | window.addEventListener("mousemove", onMouseMove); 293 | window.addEventListener("mouseup", onMouseUp); 294 | } 295 | function handleClickedPanel(state, clickedPanel, tabNumber) { 296 | if (tabNumber !== null) { 297 | clickedPanel.currentTabIndex = tabNumber; 298 | } 299 | Dockable.setPanelActiveAndBringToFront(state.ref.current, clickedPanel); 300 | state.commit(); 301 | } 302 | function handleClosedTab(ev, state, panel, tabNumber) { 303 | ev.preventDefault(); 304 | const content = panel.contentList[tabNumber]; 305 | Dockable.removeContent(state.ref.current, panel, content.contentId); 306 | Dockable.coallesceEmptyPanels(state.ref.current); 307 | state.commit(); 308 | } 309 | //# sourceMappingURL=Container.jsx.map -------------------------------------------------------------------------------- /dist/Container.jsx.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"Container.jsx","sourceRoot":"","sources":["../src/Container.tsx"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /dist/Panel.d.ts: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import * as Dockable from "./index.js"; 3 | export declare function ContainerPanel(props: { 4 | state: Dockable.RefState; 5 | panelRect: Dockable.LayoutPanel; 6 | tabHeight: number; 7 | onClickPanel: () => void; 8 | onClickTab: (tabNumber: number) => void; 9 | onCloseTab: (ev: React.MouseEvent, tabNumber: number) => void; 10 | onDragHeader: (ev: React.MouseEvent, tabNumber: number | null) => void; 11 | }): JSX.Element; 12 | -------------------------------------------------------------------------------- /dist/Panel.jsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import styled from "styled-components"; 3 | const StyledPanelRoot = styled.div ` 4 | position: absolute; 5 | box-sizing: border-box; 6 | contain: strict; 7 | `; 8 | const StyledTabRow = styled.div ` 9 | background-color: var(--dockable-panelBkg); 10 | box-sizing: border-box; 11 | width: 100%; 12 | height: 100%; 13 | 14 | display: grid; 15 | grid-template: auto 1fr / 1fr; 16 | overflow: hidden; 17 | 18 | border: 1px solid var(--dockable-panelInactiveBorder); 19 | 20 | &.active 21 | { 22 | border: 1px solid var(--dockable-panelActiveBorder); 23 | } 24 | `; 25 | const StyledTabRowInner = styled.div ` 26 | background-color: var(--dockable-voidBkg); 27 | text-align: left; 28 | grid-row: 1; 29 | grid-column: 1; 30 | 31 | display: grid; 32 | grid-template: ${props => props.tabHeight}px / repeat(${props => props.tabCount}, auto) 1fr; 33 | grid-auto-flow: column; 34 | 35 | height: ${props => props.tabHeight}px; 36 | 37 | overflow-x: auto; 38 | overflow-y: hidden; 39 | user-select: none; 40 | 41 | &::-webkit-scrollbar 42 | { 43 | width: 4px; 44 | height: 4px; 45 | } 46 | 47 | &::-webkit-scrollbar-track 48 | { 49 | background: var(--dockable-panelBkg); 50 | } 51 | 52 | &::-webkit-scrollbar-thumb 53 | { 54 | background-color: var(--dockable-scrollbarColor); 55 | border-radius: 0; 56 | border: 0; 57 | } 58 | `; 59 | const StyledTab = styled.div ` 60 | grid-row: 1; 61 | grid-column: ${props => props.tabNumber + 1}; 62 | 63 | display: grid; 64 | grid-template: auto / auto auto; 65 | justify-items: start; 66 | align-items: center; 67 | 68 | min-width: max-content; 69 | height: 100%; 70 | box-sizing: border-box; 71 | margin-right: 1px; 72 | padding-left: 0.75em; 73 | padding-right: 0.5em; 74 | user-select: none; 75 | 76 | color: var(--dockable-panelTabTextColor); 77 | background-color: ${props => props.isCurrentTab ? 78 | "var(--dockable-panelBkg)" : 79 | "var(--dockable-panelTabBkg)"}; 80 | `; 81 | const StyledCloseButton = styled.button ` 82 | pointer-events: auto; 83 | border: 0; 84 | border-radius: 0.25em; 85 | background-color: transparent; 86 | padding: 0.1em 0.3em; 87 | cursor: pointer; 88 | margin-left: 0.25em; 89 | width: 1.5em; 90 | height: 1.5em; 91 | 92 | color: ${props => props.isCurrentTab ? "var(--dockable-panelTabTextColor)" : "transparent"}; 93 | 94 | &:hover 95 | { 96 | background-color: var(--dockable-buttonHoverBkg); 97 | color: var(--dockable-panelTabTextColor); 98 | } 99 | 100 | &:active 101 | { 102 | background-color: var(--dockable-buttonHoverBkg); 103 | color: var(--dockable-panelTabTextColor); 104 | } 105 | `; 106 | const StyledTabRowEmptySpace = styled.div ` 107 | min-width: 2em; 108 | pointer-events: none; 109 | `; 110 | export function ContainerPanel(props) { 111 | const panelRect = props.panelRect; 112 | const isActivePanel = props.state.ref.current.activePanel === panelRect.panel; 113 | return 120 | 121 | { 122 | props.onClickPanel(); 123 | props.onDragHeader(ev, null); 124 | }}> 125 | 126 | {panelRect.panel.contentList.map((content, tabNumber) => { 127 | props.onClickTab(tabNumber); 128 | props.onDragHeader(ev, tabNumber); 129 | }}> 130 | {content.title || `Content ${content.contentId}`} 131 | { 132 | props.onClickTab(tabNumber); 133 | props.onCloseTab(ev, tabNumber); 134 | }}> 135 | × 136 | 137 | )} 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | ; 146 | } 147 | //# sourceMappingURL=Panel.jsx.map -------------------------------------------------------------------------------- /dist/Panel.jsx.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"Panel.jsx","sourceRoot":"","sources":["../src/Panel.tsx"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /dist/global.d.ts: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import * as Dockable from "./index.js"; 3 | export declare function useDockable(init?: (state: Dockable.State) => void): Dockable.RefState; 4 | interface MousePos { 5 | x: number; 6 | y: number; 7 | } 8 | export declare const mousePos: MousePos; 9 | export declare function spawnFloating(state: Dockable.RefState, elem: JSX.Element): Dockable.Panel; 10 | export declare function spawnFloatingEphemeral(state: Dockable.RefState, elem: JSX.Element): Dockable.Panel; 11 | export interface ContentContextProps { 12 | layoutContent: Dockable.LayoutContent; 13 | setTitle: (title: string) => void; 14 | setPreferredSize: (w: number, h: number) => void; 15 | } 16 | export declare const ContentContext: React.Context; 17 | export declare function useContentContext(): ContentContextProps; 18 | export {}; 19 | -------------------------------------------------------------------------------- /dist/global.js: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import * as Dockable from "./index.js"; 3 | export function useDockable(init) { 4 | return Dockable.useRefState(() => { 5 | const state = Dockable.makeState(); 6 | if (init) 7 | init(state); 8 | return state; 9 | }); 10 | } 11 | export const mousePos = { 12 | x: 0, 13 | y: 0, 14 | }; 15 | window.addEventListener("mousemove", (ev) => { 16 | mousePos.x = ev.pageX; 17 | mousePos.y = ev.pageY; 18 | }); 19 | export function spawnFloating(state, elem) { 20 | const panel = Dockable.makePanel(state.ref.current); 21 | Dockable.addNewContent(state.ref.current, panel, elem); 22 | panel.rect = new Dockable.Rect(mousePos.x, mousePos.y, 500, 300); 23 | state.ref.current.activePanel = panel; 24 | state.commit(); 25 | return panel; 26 | } 27 | export function spawnFloatingEphemeral(state, elem) { 28 | const panel = spawnFloating(state, elem); 29 | Dockable.removeEphemerals(state.ref.current); 30 | panel.ephemeral = true; 31 | state.commit(); 32 | return panel; 33 | } 34 | export const ContentContext = React.createContext(null); 35 | export function useContentContext() { 36 | return React.useContext(ContentContext); 37 | } 38 | //# sourceMappingURL=global.js.map -------------------------------------------------------------------------------- /dist/global.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"global.js","sourceRoot":"","sources":["../src/global.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,KAAK,QAAQ,MAAM,YAAY,CAAA;AAGtC,MAAM,UAAU,WAAW,CACvB,IAAsC;IAGtC,OAAO,QAAQ,CAAC,WAAW,CAAC,GAAG,EAAE;QAE7B,MAAM,KAAK,GAAG,QAAQ,CAAC,SAAS,EAAE,CAAA;QAElC,IAAI,IAAI;YACJ,IAAI,CAAC,KAAK,CAAC,CAAA;QAEf,OAAO,KAAK,CAAA;IAChB,CAAC,CAAC,CAAA;AACN,CAAC;AAUD,MAAM,CAAC,MAAM,QAAQ,GACrB;IACI,CAAC,EAAE,CAAC;IACJ,CAAC,EAAE,CAAC;CACP,CAAA;AAGD,MAAM,CAAC,gBAAgB,CAAC,WAAW,EAAE,CAAC,EAAc,EAAE,EAAE;IAEpD,QAAQ,CAAC,CAAC,GAAG,EAAE,CAAC,KAAK,CAAA;IACrB,QAAQ,CAAC,CAAC,GAAG,EAAE,CAAC,KAAK,CAAA;AACzB,CAAC,CAAC,CAAA;AAGF,MAAM,UAAU,aAAa,CACzB,KAAwC,EACxC,IAAiB;IAGjB,MAAM,KAAK,GAAG,QAAQ,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;IACnD,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,CAAA;IACtD,KAAK,CAAC,IAAI,GAAG,IAAI,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,CAAA;IAEhE,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,WAAW,GAAG,KAAK,CAAA;IACrC,KAAK,CAAC,MAAM,EAAE,CAAA;IACd,OAAO,KAAK,CAAA;AAChB,CAAC;AAGD,MAAM,UAAU,sBAAsB,CAClC,KAAwC,EACxC,IAAiB;IAGjB,MAAM,KAAK,GAAG,aAAa,CAAC,KAAK,EAAE,IAAI,CAAC,CAAA;IACxC,QAAQ,CAAC,gBAAgB,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;IAC5C,KAAK,CAAC,SAAS,GAAG,IAAI,CAAA;IACtB,KAAK,CAAC,MAAM,EAAE,CAAA;IACd,OAAO,KAAK,CAAA;AAChB,CAAC;AAYD,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,CAAC,aAAa,CAAsB,IAAK,CAAC,CAAA;AAG7E,MAAM,UAAU,iBAAiB;IAE7B,OAAO,KAAK,CAAC,UAAU,CAAC,cAAc,CAAC,CAAA;AAC3C,CAAC"} -------------------------------------------------------------------------------- /dist/index.d.ts: -------------------------------------------------------------------------------- 1 | export * from "./global.js"; 2 | export * from "./state.js"; 3 | export * from "./Container.jsx"; 4 | export * from "./Panel.jsx"; 5 | export * from "./rect.js"; 6 | export * from "./refState.js"; 7 | -------------------------------------------------------------------------------- /dist/index.js: -------------------------------------------------------------------------------- 1 | export * from "./global.js"; 2 | export * from "./state.js"; 3 | export * from "./Container.jsx"; 4 | export * from "./Panel.jsx"; 5 | export * from "./rect.js"; 6 | export * from "./refState.js"; 7 | //# sourceMappingURL=index.js.map -------------------------------------------------------------------------------- /dist/index.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAA;AAC3B,cAAc,YAAY,CAAA;AAC1B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,aAAa,CAAA;AAC3B,cAAc,WAAW,CAAA;AACzB,cAAc,eAAe,CAAA"} -------------------------------------------------------------------------------- /dist/rect.d.ts: -------------------------------------------------------------------------------- 1 | export declare class Rect { 2 | x: number; 3 | y: number; 4 | w: number; 5 | h: number; 6 | constructor(x: number, y: number, w: number, h: number); 7 | static fromVertices(x1: number, y1: number, x2: number, y2: number): Rect; 8 | static fromElement(elem: HTMLElement): Rect; 9 | clone(): Rect; 10 | get x1(): number; 11 | get y1(): number; 12 | get x2(): number; 13 | get y2(): number; 14 | get xCenter(): number; 15 | get yCenter(): number; 16 | withX(value: number): Rect; 17 | withY(value: number): Rect; 18 | withW(value: number): Rect; 19 | withH(value: number): Rect; 20 | withX1(value: number): Rect; 21 | withY1(value: number): Rect; 22 | withX2(value: number): Rect; 23 | withY2(value: number): Rect; 24 | displace(x: number, y: number): Rect; 25 | expand(amount: number): Rect; 26 | expandW(amount: number): Rect; 27 | contains(p: { 28 | x: number; 29 | y: number; 30 | }): boolean; 31 | overlaps(other: Rect): boolean; 32 | } 33 | -------------------------------------------------------------------------------- /dist/rect.js: -------------------------------------------------------------------------------- 1 | export class Rect { 2 | x; 3 | y; 4 | w; 5 | h; 6 | constructor(x, y, w, h) { 7 | this.x = x; 8 | this.y = y; 9 | this.w = w; 10 | this.h = h; 11 | } 12 | static fromVertices(x1, y1, x2, y2) { 13 | return new Rect(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x2 - x1), Math.abs(y2 - y1)); 14 | } 15 | static fromElement(elem) { 16 | const clientRect = elem.getBoundingClientRect(); 17 | return new Rect(clientRect.left, clientRect.top, clientRect.width, clientRect.height); 18 | } 19 | clone() { 20 | return new Rect(this.x, this.y, this.w, this.h); 21 | } 22 | get x1() { 23 | return this.x; 24 | } 25 | get y1() { 26 | return this.y; 27 | } 28 | get x2() { 29 | return this.x + this.w; 30 | } 31 | get y2() { 32 | return this.y + this.h; 33 | } 34 | get xCenter() { 35 | return (this.x1 + this.x2) / 2; 36 | } 37 | get yCenter() { 38 | return (this.y1 + this.y2) / 2; 39 | } 40 | withX(value) { 41 | return new Rect(value, this.y, this.w, this.h); 42 | } 43 | withY(value) { 44 | return new Rect(this.x, value, this.w, this.h); 45 | } 46 | withW(value) { 47 | return new Rect(this.x, this.y, value, this.h); 48 | } 49 | withH(value) { 50 | return new Rect(this.x, this.y, this.w, value); 51 | } 52 | withX1(value) { 53 | return Rect.fromVertices(value, this.y1, this.x2, this.y2); 54 | } 55 | withY1(value) { 56 | return Rect.fromVertices(this.x1, value, this.x2, this.y2); 57 | } 58 | withX2(value) { 59 | return Rect.fromVertices(this.x1, this.y1, value, this.y2); 60 | } 61 | withY2(value) { 62 | return Rect.fromVertices(this.x1, this.y1, this.x2, value); 63 | } 64 | displace(x, y) { 65 | return new Rect(this.x + x, this.y + y, this.w, this.h); 66 | } 67 | expand(amount) { 68 | return Rect.fromVertices(this.x1 - amount, this.y1 - amount, this.x2 + amount, this.y2 + amount); 69 | } 70 | expandW(amount) { 71 | return Rect.fromVertices(this.x1 - amount, this.y1, this.x2 + amount, this.y2); 72 | } 73 | contains(p) { 74 | return p.x >= this.x && 75 | p.x < this.x2 && 76 | p.y >= this.y && 77 | p.y < this.y2; 78 | } 79 | overlaps(other) { 80 | return this.x2 >= other.x && 81 | this.x < other.x2 && 82 | this.y2 >= other.y && 83 | this.y < other.y2; 84 | } 85 | } 86 | //# sourceMappingURL=rect.js.map -------------------------------------------------------------------------------- /dist/rect.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"rect.js","sourceRoot":"","sources":["../src/rect.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /dist/refState.d.ts: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | export interface RefState { 3 | ref: React.MutableRefObject; 4 | updateToken: number; 5 | commit: () => void; 6 | } 7 | export declare function useRefState(initializer: () => T): RefState; 8 | -------------------------------------------------------------------------------- /dist/refState.js: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | export function useRefState(initializer) { 3 | const [updateToken, setUpdateToken] = React.useState(0); 4 | const ref = React.useRef(null); 5 | if (ref.current === null) 6 | ref.current = initializer(); 7 | return { 8 | ref, 9 | updateToken, 10 | commit: () => setUpdateToken(n => (n + 1) % 1000000) 11 | }; 12 | } 13 | //# sourceMappingURL=refState.js.map -------------------------------------------------------------------------------- /dist/refState.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"refState.js","sourceRoot":"","sources":["../src/refState.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAW9B,MAAM,UAAU,WAAW,CAAI,WAAoB;IAE/C,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAA;IAEvD,MAAM,GAAG,GAAG,KAAK,CAAC,MAAM,CAAI,IAAK,CAAC,CAAA;IAClC,IAAI,GAAG,CAAC,OAAO,KAAK,IAAI;QACpB,GAAG,CAAC,OAAO,GAAG,WAAW,EAAE,CAAA;IAE/B,OAAO;QACH,GAAG;QACH,WAAW;QACX,MAAM,EAAE,GAAG,EAAE,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,OAAO,CAAC;KACvD,CAAA;AACL,CAAC"} -------------------------------------------------------------------------------- /dist/state.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | import { Rect } from "./rect.js"; 3 | export declare type PanelId = number; 4 | export declare type ContentId = number; 5 | export declare type ContentElement = JSX.Element; 6 | export interface State { 7 | idNext: number; 8 | rootPanel: Panel; 9 | floatingPanels: Panel[]; 10 | activePanel: Panel | null; 11 | draggedPanel: Panel | null; 12 | showAnchors: boolean; 13 | previewAnchor: Anchor | null; 14 | } 15 | export declare enum SplitMode { 16 | LeftRight = 0, 17 | TopBottom = 1 18 | } 19 | export declare enum DockMode { 20 | Full = 0, 21 | Left = 1, 22 | Right = 2, 23 | Top = 3, 24 | Bottom = 4 25 | } 26 | export interface Panel { 27 | id: PanelId; 28 | floating: boolean; 29 | rect: Rect; 30 | contentList: Content[]; 31 | currentTabIndex: number; 32 | splitPanels: Panel[]; 33 | splitMode: SplitMode; 34 | splitSize: number; 35 | preferredWidth: number; 36 | preferredHeight: number; 37 | ephemeral: boolean; 38 | } 39 | export interface Content { 40 | contentId: ContentId; 41 | title: string; 42 | element: JSX.Element; 43 | } 44 | export interface Divider { 45 | panel: Panel; 46 | vertical: boolean; 47 | rect: Rect; 48 | resizeMin: number; 49 | resizeMax: number; 50 | } 51 | export interface Anchor { 52 | panel: Panel; 53 | x: number; 54 | y: number; 55 | mode: DockMode; 56 | previewRect: Rect; 57 | } 58 | export interface Layout { 59 | panelRects: LayoutPanel[]; 60 | content: LayoutContent[]; 61 | dividers: Divider[]; 62 | anchors: Anchor[]; 63 | } 64 | export interface LayoutPanel { 65 | panel: Panel; 66 | rect: Rect; 67 | floating: boolean; 68 | zIndex: number; 69 | } 70 | export interface LayoutContent { 71 | content: Content; 72 | tabIndex: number; 73 | panel: Panel; 74 | layoutPanel: LayoutPanel; 75 | } 76 | export declare function makeState(): State; 77 | export declare function makePanel(state: State): Panel; 78 | export declare function createDockedPanel(state: State, dockIntoPanel: Panel, mode: DockMode, content: ContentElement): Panel; 79 | export declare function detachPanel(state: State, panel: Panel): void; 80 | export declare function addNewContent(state: State, toPanel: Panel, element: ContentElement): void; 81 | export declare function addContent(state: State, toPanel: Panel, content: Content): void; 82 | export declare function removeContent(state: State, fromPanel: Panel, contentId: ContentId): void; 83 | export declare function removeEphemerals(state: State): void; 84 | export declare function removeEphemeralsRecursive(state: State, fromPanel: Panel): void; 85 | export declare function coallesceEmptyPanels(state: State): void; 86 | export declare function coallesceEmptyPanelsRecursive(state: State, fromPanel: Panel): void; 87 | export declare function dock(state: State, panel: Panel, dockIntoPanel: Panel, mode: DockMode): void; 88 | export declare function setPanelActiveAndBringToFront(state: State, panel: Panel): void; 89 | export declare function clampFloatingPanels(state: State, rect: Rect): void; 90 | export declare function clampFloatingPanelStrictly(state: State, panel: Panel, rect: Rect): void; 91 | export declare function traverseLayout(panel: Panel, rect: Rect, layout: Layout): void; 92 | export declare function getLayout(state: State, rect: Rect): Layout; 93 | export declare function getContentRect(state: State, rect: Rect, contentId: ContentId): Rect | undefined; 94 | -------------------------------------------------------------------------------- /dist/state.js: -------------------------------------------------------------------------------- 1 | import { Rect } from "./rect.js"; 2 | export var SplitMode; 3 | (function (SplitMode) { 4 | SplitMode[SplitMode["LeftRight"] = 0] = "LeftRight"; 5 | SplitMode[SplitMode["TopBottom"] = 1] = "TopBottom"; 6 | })(SplitMode || (SplitMode = {})); 7 | export var DockMode; 8 | (function (DockMode) { 9 | DockMode[DockMode["Full"] = 0] = "Full"; 10 | DockMode[DockMode["Left"] = 1] = "Left"; 11 | DockMode[DockMode["Right"] = 2] = "Right"; 12 | DockMode[DockMode["Top"] = 3] = "Top"; 13 | DockMode[DockMode["Bottom"] = 4] = "Bottom"; 14 | })(DockMode || (DockMode = {})); 15 | export function makeState() { 16 | return { 17 | idNext: 2, 18 | rootPanel: { 19 | id: 1, 20 | floating: false, 21 | rect: new Rect(0, 0, 0, 0), 22 | contentList: [], 23 | currentTabIndex: 0, 24 | splitPanels: [], 25 | splitMode: SplitMode.LeftRight, 26 | splitSize: 0.5, 27 | preferredWidth: 300, 28 | preferredHeight: 250, 29 | ephemeral: false, 30 | }, 31 | floatingPanels: [], 32 | activePanel: null, 33 | draggedPanel: null, 34 | showAnchors: false, 35 | previewAnchor: null, 36 | }; 37 | } 38 | export function makePanel(state) { 39 | const id = state.idNext++; 40 | const panel = { 41 | id, 42 | floating: true, 43 | rect: new Rect(0, 0, 0, 0), 44 | contentList: [], 45 | currentTabIndex: 0, 46 | splitPanels: [], 47 | splitMode: SplitMode.LeftRight, 48 | splitSize: 0.5, 49 | preferredWidth: 300, 50 | preferredHeight: 250, 51 | ephemeral: false, 52 | }; 53 | state.floatingPanels.push(panel); 54 | return panel; 55 | } 56 | export function createDockedPanel(state, dockIntoPanel, mode, content) { 57 | const panel = makePanel(state); 58 | addNewContent(state, panel, content); 59 | dock(state, panel, dockIntoPanel, mode); 60 | return panel; 61 | } 62 | export function detachPanel(state, panel) { 63 | if (!panel.floating) { 64 | panel.floating = true; 65 | state.activePanel = panel; 66 | state.floatingPanels.push(panel); 67 | } 68 | } 69 | export function addNewContent(state, toPanel, element) { 70 | const id = state.idNext++; 71 | toPanel.contentList.push({ 72 | contentId: id, 73 | title: "", 74 | element, 75 | }); 76 | toPanel.currentTabIndex = toPanel.contentList.length - 1; 77 | toPanel.ephemeral = false; 78 | } 79 | export function addContent(state, toPanel, content) { 80 | const id = state.idNext++; 81 | toPanel.contentList.push(content); 82 | toPanel.currentTabIndex = toPanel.contentList.length - 1; 83 | toPanel.ephemeral = false; 84 | } 85 | export function removeContent(state, fromPanel, contentId) { 86 | const index = fromPanel.contentList.findIndex(w => w.contentId === contentId); 87 | if (index < 0) 88 | return; 89 | fromPanel.contentList.splice(index, 1); 90 | fromPanel.currentTabIndex = 91 | Math.max(0, Math.min(fromPanel.contentList.length - 1, fromPanel.currentTabIndex)); 92 | } 93 | export function removeEphemerals(state) { 94 | for (var i = 0; i < state.floatingPanels.length; i++) 95 | removeEphemeralsRecursive(state, state.floatingPanels[i]); 96 | coallesceEmptyPanels(state); 97 | } 98 | export function removeEphemeralsRecursive(state, fromPanel) { 99 | for (var i = 0; i < fromPanel.splitPanels.length; i++) 100 | coallesceEmptyPanelsRecursive(state, fromPanel.splitPanels[i]); 101 | if (fromPanel.ephemeral) { 102 | fromPanel.contentList = []; 103 | fromPanel.currentTabIndex = 0; 104 | } 105 | } 106 | export function coallesceEmptyPanels(state) { 107 | coallesceEmptyPanelsRecursive(state, state.rootPanel); 108 | for (var i = 0; i < state.floatingPanels.length; i++) 109 | coallesceEmptyPanelsRecursive(state, state.floatingPanels[i]); 110 | state.floatingPanels = state.floatingPanels.filter(p => p.contentList.length != 0 || p.splitPanels.length != 0); 111 | } 112 | export function coallesceEmptyPanelsRecursive(state, fromPanel) { 113 | for (var i = 0; i < fromPanel.splitPanels.length; i++) 114 | coallesceEmptyPanelsRecursive(state, fromPanel.splitPanels[i]); 115 | fromPanel.splitPanels = fromPanel.splitPanels.filter(p => p.contentList.length != 0 || p.splitPanels.length != 0); 116 | if (fromPanel.splitPanels.length == 1) 117 | Object.assign(fromPanel, fromPanel.splitPanels[0]); 118 | } 119 | export function dock(state, panel, dockIntoPanel, mode) { 120 | if (mode == DockMode.Full || 121 | (dockIntoPanel.contentList.length == 0 && dockIntoPanel.splitPanels.length == 0)) { 122 | if (dockIntoPanel.splitPanels.length > 0) 123 | throw "invalid full docking into subdivided panel"; 124 | for (const window of panel.contentList) 125 | addContent(state, dockIntoPanel, window); 126 | detachPanel(state, panel); 127 | panel.contentList = []; 128 | state.floatingPanels = state.floatingPanels.filter(p => p !== panel); 129 | state.activePanel = dockIntoPanel; 130 | } 131 | else if (mode == DockMode.Right || 132 | mode == DockMode.Left || 133 | mode == DockMode.Top || 134 | mode == DockMode.Bottom) { 135 | const subdivMode = (mode == DockMode.Right || mode == DockMode.Left) ? 136 | SplitMode.LeftRight : 137 | SplitMode.TopBottom; 138 | const subdivOriginalFirst = (mode == DockMode.Bottom || mode == DockMode.Right); 139 | const newSubpanels = [panel]; 140 | const newSubpanel = makePanel(state); 141 | newSubpanel.contentList = dockIntoPanel.contentList; 142 | newSubpanel.currentTabIndex = dockIntoPanel.currentTabIndex; 143 | newSubpanel.splitMode = dockIntoPanel.splitMode; 144 | newSubpanel.splitPanels = dockIntoPanel.splitPanels; 145 | newSubpanel.splitSize = dockIntoPanel.splitSize; 146 | dockIntoPanel.contentList = []; 147 | dockIntoPanel.splitPanels = newSubpanels; 148 | dockIntoPanel.splitMode = subdivMode; 149 | dockIntoPanel.splitSize = subdivOriginalFirst ? 0.75 : 0.25; 150 | if (subdivOriginalFirst) 151 | newSubpanels.unshift(newSubpanel); 152 | else 153 | newSubpanels.push(newSubpanel); 154 | panel.floating = false; 155 | dockIntoPanel.floating = false; 156 | newSubpanel.floating = false; 157 | state.activePanel = panel; 158 | state.floatingPanels = state.floatingPanels.filter(p => p !== panel && p !== newSubpanel); 159 | } 160 | else { 161 | throw "invalid docking"; 162 | } 163 | } 164 | export function setPanelActiveAndBringToFront(state, panel) { 165 | if (panel.contentList.length != 0) 166 | state.activePanel = panel; 167 | if (!panel.floating) 168 | return; 169 | state.floatingPanels = state.floatingPanels.filter(p => p !== panel); 170 | state.floatingPanels.push(panel); 171 | if (!panel.ephemeral) 172 | removeEphemerals(state); 173 | } 174 | export function clampFloatingPanels(state, rect) { 175 | const margin = 10; 176 | for (const panel of state.floatingPanels) { 177 | panel.rect.x = 178 | Math.max(rect.x + margin - panel.rect.w / 2, Math.min(rect.x2 - margin - panel.rect.w / 2, panel.rect.x)); 179 | panel.rect.y = 180 | Math.max(rect.y + margin, Math.min(rect.y2 - margin - panel.rect.h / 2, panel.rect.y)); 181 | } 182 | } 183 | export function clampFloatingPanelStrictly(state, panel, rect) { 184 | const margin = 10; 185 | panel.rect.x = 186 | Math.max(rect.x + margin, Math.min(rect.x2 - margin - panel.rect.w, panel.rect.x)); 187 | panel.rect.y = 188 | Math.max(rect.y + margin, Math.min(rect.y2 - margin - panel.rect.h, panel.rect.y)); 189 | } 190 | export function traverseLayout(panel, rect, layout) { 191 | const xMid = (rect.x1 + rect.x2) / 2; 192 | const yMid = (rect.y1 + rect.y2) / 2; 193 | if (panel.splitPanels.length == 2) { 194 | if (panel.splitMode == SplitMode.LeftRight) { 195 | const xSplit = rect.x1 + Math.round((rect.x2 - rect.x1) * panel.splitSize); 196 | const rect1 = rect.withX2(xSplit); 197 | const rect2 = rect.withX1(xSplit); 198 | const rectDivider = rect.withX1(xSplit).withX2(xSplit); 199 | traverseLayout(panel.splitPanels[0], rect1, layout); 200 | traverseLayout(panel.splitPanels[1], rect2, layout); 201 | layout.dividers.push({ 202 | panel, 203 | vertical: false, 204 | rect: rectDivider, 205 | resizeMin: rect.x1, 206 | resizeMax: rect.x2, 207 | }); 208 | } 209 | else if (panel.splitMode == SplitMode.TopBottom) { 210 | const ySplit = rect.y1 + Math.round((rect.y2 - rect.y1) * panel.splitSize); 211 | const rect1 = rect.withY2(ySplit); 212 | const rect2 = rect.withY1(ySplit); 213 | const rectDivider = rect.withY1(ySplit).withY2(ySplit); 214 | traverseLayout(panel.splitPanels[0], rect1, layout); 215 | traverseLayout(panel.splitPanels[1], rect2, layout); 216 | layout.dividers.push({ 217 | panel, 218 | vertical: true, 219 | rect: rectDivider, 220 | resizeMin: rect.y1, 221 | resizeMax: rect.y2, 222 | }); 223 | } 224 | } 225 | else { 226 | const panelRect = { 227 | panel, 228 | rect, 229 | floating: false, 230 | zIndex: 0, 231 | }; 232 | for (let w = 0; w < panel.contentList.length; w++) { 233 | layout.content.push({ 234 | content: panel.contentList[w], 235 | tabIndex: w, 236 | panel, 237 | layoutPanel: panelRect, 238 | }); 239 | } 240 | layout.panelRects.push(panelRect); 241 | layout.anchors.push({ 242 | panel, 243 | x: xMid, 244 | y: yMid, 245 | mode: DockMode.Full, 246 | previewRect: rect, 247 | }); 248 | } 249 | layout.anchors.push({ 250 | panel, 251 | x: rect.x2 - 10, 252 | y: yMid, 253 | mode: DockMode.Right, 254 | previewRect: rect.withX1(rect.x1 + (rect.x2 - rect.x1) * 3 / 4), 255 | }); 256 | layout.anchors.push({ 257 | panel, 258 | x: rect.x1 + 10, 259 | y: yMid, 260 | mode: DockMode.Left, 261 | previewRect: rect.withX2(rect.x1 + (rect.x2 - rect.x1) / 4), 262 | }); 263 | layout.anchors.push({ 264 | panel, 265 | x: xMid, 266 | y: rect.y2 - 10, 267 | mode: DockMode.Bottom, 268 | previewRect: rect.withY1(rect.y1 + (rect.y2 - rect.y1) * 3 / 4), 269 | }); 270 | layout.anchors.push({ 271 | panel, 272 | x: xMid, 273 | y: rect.y1 + 10, 274 | mode: DockMode.Top, 275 | previewRect: rect.withY2(rect.y1 + (rect.y2 - rect.y1) / 4), 276 | }); 277 | } 278 | export function getLayout(state, rect) { 279 | const layout = { 280 | panelRects: [], 281 | content: [], 282 | dividers: [], 283 | anchors: [], 284 | }; 285 | traverseLayout(state.rootPanel, rect, layout); 286 | for (let fp = 0; fp < state.floatingPanels.length; fp++) { 287 | const floatingPanel = state.floatingPanels[fp]; 288 | const panelRect = { 289 | panel: floatingPanel, 290 | rect: floatingPanel.rect, 291 | floating: true, 292 | zIndex: fp + 1, 293 | }; 294 | for (let w = 0; w < floatingPanel.contentList.length; w++) { 295 | layout.content.push({ 296 | content: floatingPanel.contentList[w], 297 | tabIndex: w, 298 | panel: floatingPanel, 299 | layoutPanel: panelRect, 300 | }); 301 | } 302 | layout.panelRects.push(panelRect); 303 | layout.anchors.push({ 304 | panel: floatingPanel, 305 | x: floatingPanel.rect.xCenter, 306 | y: floatingPanel.rect.yCenter, 307 | mode: DockMode.Full, 308 | previewRect: floatingPanel.rect, 309 | }); 310 | } 311 | return layout; 312 | } 313 | export function getContentRect(state, rect, contentId) { 314 | const layout = getLayout(state, rect); 315 | return layout.panelRects.find(p => p.panel.contentList.some(c => c.contentId === contentId)).rect; 316 | } 317 | //# sourceMappingURL=state.js.map -------------------------------------------------------------------------------- /dist/state.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"state.js","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /example.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hlorenzi/react-dockable/0d0ac9503ca7e8dbb1ac0f667267d73f1fce6d84/example.gif -------------------------------------------------------------------------------- /example/Clock.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | import * as Dockable from "@hlorenzi/react-dockable" 3 | 4 | 5 | export function Clock() 6 | { 7 | const [value, setValue] = React.useState(Date.now()) 8 | 9 | React.useEffect(() => 10 | { 11 | const interval = setInterval(() => setValue(Date.now()), 1000) 12 | return () => clearInterval(interval) 13 | }) 14 | 15 | 16 | const ctx = Dockable.useContentContext() 17 | ctx.setTitle(`Clock`) 18 | ctx.setPreferredSize(450, 250) 19 | 20 | 21 | return
33 | { new Date(value).toLocaleString() } 34 |
35 | } -------------------------------------------------------------------------------- /example/Counter.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | import * as Dockable from "@hlorenzi/react-dockable" 3 | 4 | 5 | export function Counter() 6 | { 7 | const [value, setValue] = React.useState(0) 8 | const countUp = () => setValue(value + 1) 9 | 10 | 11 | const ctx = Dockable.useContentContext() 12 | ctx.setTitle(`Count: ${ value }`) 13 | ctx.setPreferredSize(300, 250) 14 | 15 | 16 | return
28 | { value } 29 | 30 | 36 |
37 | } -------------------------------------------------------------------------------- /example/TextEditor.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | import * as Dockable from "@hlorenzi/react-dockable" 3 | 4 | 5 | export function TextEditor(props: { 6 | initialValue: string, 7 | }) 8 | { 9 | const [value, setValue] = React.useState(props.initialValue) 10 | const [edited, setEdited] = React.useState(false) 11 | 12 | const onEdit = (newValue: string) => 13 | { 14 | setEdited(true) 15 | setValue(newValue) 16 | } 17 | 18 | 19 | const ctx = Dockable.useContentContext() 20 | ctx.setTitle(`Text Editor${ edited ? " [edited]" : "" }`) 21 | ctx.setPreferredSize(300, 250) 22 | 23 | 24 | return
38 | 43 | 44 |