diff --git a/src/renderer/components/dock/dock.scss b/src/renderer/components/dock/dock.scss index 6b2d90925d..8c7ab7e07d 100644 --- a/src/renderer/components/dock/dock.scss +++ b/src/renderer/components/dock/dock.scss @@ -14,10 +14,6 @@ left: 0; bottom: 0; z-index: 100; - - > .resizer { - display: none; - } } } @@ -65,24 +61,7 @@ } } - .resizer { - $height: 12px; - - position: absolute; - top: -$height / 2; - left: 0; - right: 0; - bottom: 100%; - height: $height; - cursor: row-resize; - z-index: 10; - - &.disabled { - pointer-events: none; - } - } - .AceEditor { border: none; } -} \ No newline at end of file +} diff --git a/src/renderer/components/dock/dock.store.ts b/src/renderer/components/dock/dock.store.ts index c1b70cc925..9863588e69 100644 --- a/src/renderer/components/dock/dock.store.ts +++ b/src/renderer/components/dock/dock.store.ts @@ -28,7 +28,11 @@ export class DockStore { protected storage = createStorage("dock", {}); // keep settings in localStorage public defaultTabId = this.initialTabs[0].id; - public minHeight = 100; + private _minHeight = 100; + + set minHeight(val: number) { + this._minHeight = val + } @observable isOpen = false; @observable fullSize = false; @@ -176,8 +180,8 @@ export class DockStore { } @action - setHeight(height: number) { - this.height = Math.max(0, Math.min(height, this.maxHeight)); + setHeight(height?: number) { + this.height = Math.max(0, Math.min(height || this._minHeight, this.maxHeight)); } @action diff --git a/src/renderer/components/dock/dock.tsx b/src/renderer/components/dock/dock.tsx index d384c36608..d2149ac721 100644 --- a/src/renderer/components/dock/dock.tsx +++ b/src/renderer/components/dock/dock.tsx @@ -4,7 +4,7 @@ import React, { Fragment } from "react"; import { observer } from "mobx-react"; import { Trans } from "@lingui/macro"; import { autobind, cssNames, prevDefault } from "../../utils"; -import { Draggable, DraggableState } from "../draggable"; +import { ResizingAnchor, ResizeEventData, ResizeDirection, ResizeSide } from "../resizing-anchor"; import { Icon } from "../icon"; import { Tabs } from "../tabs/tabs"; import { MenuItem } from "../menu"; @@ -30,16 +30,17 @@ interface Props { @observer export class Dock extends React.Component { onResizeStart = () => { - const { isOpen, open, setHeight, minHeight } = dockStore; + const { isOpen, open, setHeight } = dockStore; if (!isOpen) { open(); - setHeight(minHeight); + setHeight(); } } - onResize = ({ offsetY }: DraggableState) => { + onResize = ({ movementY }: ResizeEventData) => { const { isOpen, close, height, setHeight, minHeight, defaultHeight } = dockStore; - const newHeight = height + offsetY; + console.log(height, movementY) + const newHeight = height + movementY; if (height > newHeight && newHeight < minHeight) { setHeight(defaultHeight); close(); @@ -71,13 +72,13 @@ export class Dock extends React.Component { @autobind() renderTab(tab: IDockTab) { if (isTerminalTab(tab)) { - return + return } if (isCreateResourceTab(tab) || isEditResourceTab(tab)) { - return + return } if (isInstallChartTab(tab) || isUpgradeChartTab(tab)) { - return }/> + return } /> } } @@ -86,11 +87,11 @@ export class Dock extends React.Component { if (!isOpen || !tab) return; return (
- {isCreateResourceTab(tab) && } - {isEditResourceTab(tab) && } - {isInstallChartTab(tab) && } - {isUpgradeChartTab(tab) && } - {isTerminalTab(tab) && } + {isCreateResourceTab(tab) && } + {isEditResourceTab(tab) && } + {isInstallChartTab(tab) && } + {isUpgradeChartTab(tab) && } + {isTerminalTab(tab) && }
) } @@ -104,11 +105,11 @@ export class Dock extends React.Component { onKeyDown={this.onKeydown} tabIndex={-1} > -
{
New tab }} closeOnScroll={false}> createTerminalTab()}> - + Terminal session createResourceTab()}> - + Create resource @@ -133,7 +134,7 @@ export class Dock extends React.Component { {hasTabs() && ( <> Exit full size mode : Fit to window} onClick={toggleFillSize} /> diff --git a/src/renderer/components/draggable/draggable.scss b/src/renderer/components/draggable/draggable.scss deleted file mode 100644 index e99e306ce2..0000000000 --- a/src/renderer/components/draggable/draggable.scss +++ /dev/null @@ -1,5 +0,0 @@ -body.dragging { - user-select: none; - -moz-user-select: none; - -webkit-user-select: none; -} \ No newline at end of file diff --git a/src/renderer/components/draggable/draggable.tsx b/src/renderer/components/draggable/draggable.tsx deleted file mode 100644 index 12fd020929..0000000000 --- a/src/renderer/components/draggable/draggable.tsx +++ /dev/null @@ -1,119 +0,0 @@ -import "./draggable.scss"; -import React from "react"; -import { cssNames, IClassName, noop } from "../../utils"; -import throttle from "lodash/throttle"; - -export interface DraggableEventHandler { - (state: DraggableState): void; -} - -interface Props { - className?: IClassName; - vertical?: boolean; - horizontal?: boolean; - onStart?: DraggableEventHandler; - onEnter?: DraggableEventHandler; - onEnd?: DraggableEventHandler; -} - -export interface DraggableState { - inited?: boolean; - changed?: boolean; - initX?: number; - initY?: number; - pageX?: number; - pageY?: number; - offsetX?: number; - offsetY?: number; -} - -const initState: DraggableState = { - inited: false, - changed: false, - offsetX: 0, - offsetY: 0, -}; - -export class Draggable extends React.PureComponent { - public state = initState; - - static IS_DRAGGING = "dragging" - - static defaultProps: Props = { - vertical: true, - horizontal: true, - onStart: noop, - onEnter: noop, - onEnd: noop, - }; - - constructor(props: Props) { - super(props); - document.addEventListener("mousemove", this.onDrag); - document.addEventListener("mouseup", this.onDragEnd); - } - - componentWillUnmount() { - document.removeEventListener("mousemove", this.onDrag); - document.removeEventListener("mouseup", this.onDragEnd); - } - - onDragInit = (evt: React.MouseEvent) => { - document.body.classList.add(Draggable.IS_DRAGGING); - const { pageX, pageY } = evt; - this.setState({ - inited: true, - initX: pageX, - initY: pageY, - pageX: pageX, - pageY: pageY, - }) - } - - onDrag = throttle((evt: MouseEvent) => { - const { vertical, horizontal, onEnter, onStart } = this.props; - const { inited, pageX, pageY } = this.state; - const offsetX = pageX - evt.pageX; - const offsetY = pageY - evt.pageY; - let changed = false; - if (horizontal && offsetX !== 0) changed = true; - if (vertical && offsetY !== 0) changed = true; - if (inited && changed) { - const start = !this.state.changed; - const state = Object.assign({}, this.state, { - changed: true, - pageX: evt.pageX, - pageY: evt.pageY, - offsetX: offsetX, - offsetY: offsetY, - }); - if (start) onStart(state); - this.setState(state, () => onEnter(state)); - } - }, 100) - - onDragEnd = (evt: MouseEvent) => { - const { pageX, pageY } = evt; - const { inited, changed, initX, initY } = this.state; - if (inited) { - document.body.classList.remove(Draggable.IS_DRAGGING); - this.setState(initState, () => { - if (!changed) return; - const state = Object.assign({}, this.state, { - offsetX: initX - pageX, - offsetY: initY - pageY, - }); - this.props.onEnd(state); - }); - } - } - - render() { - const { className, children } = this.props; - return ( -
- {children} -
- ); - } -} \ No newline at end of file diff --git a/src/renderer/components/draggable/index.ts b/src/renderer/components/draggable/index.ts deleted file mode 100644 index 0a3b92d235..0000000000 --- a/src/renderer/components/draggable/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './draggable' \ No newline at end of file diff --git a/src/renderer/components/resizing-anchor/index.ts b/src/renderer/components/resizing-anchor/index.ts new file mode 100644 index 0000000000..6197be8d84 --- /dev/null +++ b/src/renderer/components/resizing-anchor/index.ts @@ -0,0 +1 @@ +export * from './resizing-anchor' diff --git a/src/renderer/components/resizing-anchor/resizing-anchor.scss b/src/renderer/components/resizing-anchor/resizing-anchor.scss new file mode 100644 index 0000000000..fceb3ee73d --- /dev/null +++ b/src/renderer/components/resizing-anchor/resizing-anchor.scss @@ -0,0 +1,46 @@ +body.resizing { + user-select: none; + -moz-user-select: none; + -webkit-user-select: none; +} + +.ResizingAnchor { + $prominentDimention: 12px; + + position: absolute; + z-index: 10; + + &.disabled { + display: none; + } + + &.vertical { + left: 0; + right: 0; + cursor: row-resize; + height: $prominentDimention; + + &.leading { + top: -$prominentDimention / 2; + } + + &.trailing { + bottom: -$prominentDimention / 2; + } + } + + &.horizontal { + top: 0; + bottom: 0; + cursor: col-resize; + width: $prominentDimention; + + &.leading { + left: -$prominentDimention / 2; + } + + &.trailing { + right: -$prominentDimention / 2; + } + } +} diff --git a/src/renderer/components/resizing-anchor/resizing-anchor.tsx b/src/renderer/components/resizing-anchor/resizing-anchor.tsx new file mode 100644 index 0000000000..4450cd1fd6 --- /dev/null +++ b/src/renderer/components/resizing-anchor/resizing-anchor.tsx @@ -0,0 +1,126 @@ +import "./resizing-anchor.scss"; +import React from "react"; +import { cssNames, noop } from "../../utils"; +import { action, computed, observable } from "mobx"; +import _ from "lodash" + +export enum ResizeDirection { + HORIZONTAL = "horizontal", + VERTICAL = "vertical", +} + +/** + * ResizeSide is for customizing where the area should be rendered. + * That location is determined in conjunction with the `ResizeDirection` using the following table: + * + * +----------+------------+----------+ + * | | HORIZONTAL | VERTICAL | + * +----------+------------+----------+ + * | LEADING | left | top | + * +----------+------------+----------+ + * | TRAILING | right | bottom | + * +----------+------------+----------+ + */ +export enum ResizeSide { + LEADING = "leading", + TRAILING = "trailing", +} + +interface Props { + direction: ResizeDirection; + disabled?: boolean; + placement?: ResizeSide; + onStart?: () => void; + onDrag?: (data: ResizeEventData) => void; + onEnd?: () => void; +} + +export interface ResizeEventData { + initX: number; + initY: number; + pageX: number; + pageY: number; + movementX: number; + movementY: number; +} + +const defaultProps: Partial = { + onStart: noop, + onDrag: noop, + onEnd: noop, + disabled: false, + placement: ResizeSide.LEADING, +} + +export class ResizingAnchor extends React.PureComponent { + @observable startingPosition?: { initX: number, initY: number }; + @observable lastEvent?: MouseEvent + + @computed get firstDragEvent() { + return this.lastEvent == null + } + + static defaultProps = defaultProps + static IS_RESIZING = "resizing" + + constructor(props: Props) { + super(props); + } + + componentWillUnmount() { + document.removeEventListener("mousemove", this.onDrag); + document.removeEventListener("mouseup", this.onDragEnd); + } + + @action + onDragInit = ({ pageX, pageY, buttons }: React.MouseEvent) => { + if (buttons !== 1) { + return + } + + document.addEventListener("mousemove", this.onDrag) + document.addEventListener("mouseup", this.onDragEnd) + document.body.classList.add(ResizingAnchor.IS_RESIZING) + + this.startingPosition = { + initX: pageX, + initY: pageY + } + this.lastEvent = undefined + } + + calculateMovement = (event: MouseEvent) => { + return { + movementX: this.lastEvent.pageX - event.pageX, + movementY: this.lastEvent.pageY - event.pageY + } + } + + onDrag = _.throttle((event: MouseEvent) => { + const { onDrag, onStart } = this.props + const { initX, initY } = this.startingPosition + const { pageX, pageY } = event + + if (this.firstDragEvent) onStart() + + const { movementX, movementY } = this.firstDragEvent ? event : this.calculateMovement(event) + onDrag({ movementX, movementY, pageX, pageY, initY, initX }) + + this.lastEvent = event + }, 100) + + @action + onDragEnd = (event: MouseEvent) => { + const { onEnd } = this.props; + + onEnd() + document.removeEventListener("mousemove", this.onDrag); + document.removeEventListener("mouseup", this.onDragEnd); + document.body.classList.remove(ResizingAnchor.IS_RESIZING) + } + + render() { + const { disabled, direction, placement } = this.props + return
+ } +} diff --git a/yarn.lock b/yarn.lock index 300efc58ce..f64e36b703 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8181,17 +8181,17 @@ mobx-observable-history@^1.0.3: history "^4.10.1" mobx "^5.15.4" -mobx-react-lite@2: - version "2.0.7" - resolved "https://registry.yarnpkg.com/mobx-react-lite/-/mobx-react-lite-2.0.7.tgz#1bfb3b4272668e288047cf0c7940b14e91cba284" - integrity sha512-YKAh2gThC6WooPnVZCoC+rV1bODAKFwkhxikzgH18wpBjkgTkkR9Sb0IesQAH5QrAEH/JQVmy47jcpQkf2Au3Q== +mobx-react-lite@>=2.2.0: + version "2.2.2" + resolved "https://registry.yarnpkg.com/mobx-react-lite/-/mobx-react-lite-2.2.2.tgz#87c217dc72b4e47b22493daf155daf3759f868a6" + integrity sha512-2SlXALHIkyUPDsV4VTKVR9DW7K3Ksh1aaIv3NrNJygTbhXe2A9GrcKHZ2ovIiOp/BXilOcTYemfHHZubP431dg== mobx-react@^6.2.2: - version "6.2.2" - resolved "https://registry.yarnpkg.com/mobx-react/-/mobx-react-6.2.2.tgz#45e8e7c4894cac8399bba0a91060d7cfb8ea084b" - integrity sha512-Us6V4ng/iKIRJ8pWxdbdysC6bnS53ZKLKlVGBqzHx6J+gYPYbOotWvhHZnzh/W5mhpYXxlXif4kL2cxoWJOplQ== + version "6.3.0" + resolved "https://registry.yarnpkg.com/mobx-react/-/mobx-react-6.3.0.tgz#7d11799f988bbdadc49e725081993b18baa20329" + integrity sha512-C14yya2nqEBRSEiJjPkhoWJLlV8pcCX3m2JRV7w1KivwANJqipoiPx9UMH4pm6QNMbqDdvJqoyl+LqNu9AhvEQ== dependencies: - mobx-react-lite "2" + mobx-react-lite ">=2.2.0" mobx@^5.15.4: version "5.15.4"