diff --git a/packages/client/package.json b/packages/client/package.json index 36114bcd..8daf2837 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -59,7 +59,6 @@ "copy-to-clipboard": "^3.3.1", "deep-equal": "^2.0.5", "dompurify": "^2.3.5", - "interactjs": "^1.10.11", "katex": "^0.15.2", "kity": "^2.0.4", "lib0": "^0.2.47", @@ -75,6 +74,7 @@ "prosemirror-tables": "^1.1.1", "prosemirror-utils": "^0.9.6", "prosemirror-view": "^1.23.6", + "re-resizable": "^6.9.9", "react": "17.0.2", "react-countdown": "^2.3.2", "react-dom": "17.0.2", diff --git a/packages/client/src/components/resizeable/resizeable.tsx b/packages/client/src/components/resizeable/resizeable.tsx index 2e5ea505..5c326158 100644 --- a/packages/client/src/components/resizeable/resizeable.tsx +++ b/packages/client/src/components/resizeable/resizeable.tsx @@ -1,9 +1,9 @@ -import React, { useRef, useEffect } from 'react'; +import React, { useCallback, useState } from 'react'; import cls from 'classnames'; -import { useClickOutside } from 'hooks/use-click-outside'; -import interact from 'interactjs'; import styles from './style.module.scss'; +import { Resizable } from 're-resizable'; + interface IProps { width: number; height: number; @@ -15,71 +15,37 @@ interface IProps { const MIN_WIDTH = 50; const MIN_HEIGHT = 50; -export const Resizeable: React.FC = ({ width, height, className, onChange, onChangeEnd, children }) => { - const $container = useRef(null); - const $topLeft = useRef(null); - const $topRight = useRef(null); - const $bottomLeft = useRef(null); - const $bottomRight = useRef(null); +export const Resizeable: React.FC = ({ + width: defaultWidth, + height: defaultHeight, + className, + onChange, + onChangeEnd, + children, +}) => { + const [width, setWidth] = useState(defaultWidth); + const [height, setHeight] = useState(defaultHeight); - useClickOutside($container, { - in: () => $container.current.classList.add(styles.isActive), - out: () => $container.current.classList.remove(styles.isActive), - }); - - useEffect(() => { - interact($container.current).resizable({ - edges: { - top: true, - right: true, - bottom: true, - left: true, - }, - listeners: { - move: function (event) { - let { x, y } = event.target.dataset; - x = (parseFloat(x) || 0) + event.deltaRect.left; - y = (parseFloat(y) || 0) + event.deltaRect.top; - - let { width, height } = event.rect; - width = width < MIN_WIDTH ? MIN_WIDTH : width; - height = height < MIN_HEIGHT ? MIN_HEIGHT : height; - - Object.assign(event.target.style, { - width: `${width}px`, - height: `${height}px`, - // transform: `translate(${x}px, ${y}px)`, - }); - Object.assign(event.target.dataset, { x, y }); - onChange && onChange({ width, height }); - }, - end: function (event) { - let { width, height } = event.rect; - onChangeEnd && onChangeEnd({ width, height }); - }, - }, - }); - }, []); - - useEffect(() => { - Object.assign($container.current.style, { - width: `${width}px`, - height: `${height}px`, - }); - }, [width, height]); + const onResizeStop = useCallback( + (e, direction, ref, d) => { + const nextWidth = width + d.width; + const nextHeight = height + d.height; + setWidth(nextWidth); + setHeight(nextHeight); + onChangeEnd({ width: nextWidth, height: nextHeight }); + }, + [width, height] + ); return ( -
- - - - {children} -
+ ); }; diff --git a/packages/client/src/components/resizeable/style.module.scss b/packages/client/src/components/resizeable/style.module.scss index 40f499b7..64232ffa 100644 --- a/packages/client/src/components/resizeable/style.module.scss +++ b/packages/client/src/components/resizeable/style.module.scss @@ -4,47 +4,8 @@ width: 100px; height: 100px; max-width: 100%; - box-sizing: border-box; - - .resizer { - position: absolute; - z-index: 9999; - width: 10px; - height: 10px; - background: white; - border: 3px solid #4286f4; - border-radius: 50%; - opacity: 0; - box-sizing: border-box; - } - - .resizer.topLeft { - top: -5px; - left: -5px; - cursor: nwse-resize; - } - - .resizer.topRight { - top: -5px; - right: -5px; - cursor: nesw-resize; - } - - .resizer.bottomLeft { - bottom: -5px; - left: -5px; - cursor: nesw-resize; - } - - .resizer.bottomRight { - right: -5px; - bottom: -5px; - cursor: nwse-resize; - } &.isActive { - outline: 1px solid #4286f4; - .resizer { opacity: 1; } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f45e86d6..3aebd212 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -89,7 +89,6 @@ importers: copy-to-clipboard: ^3.3.1 deep-equal: ^2.0.5 dompurify: ^2.3.5 - interactjs: ^1.10.11 katex: ^0.15.2 kity: ^2.0.4 lib0: ^0.2.47 @@ -105,6 +104,7 @@ importers: prosemirror-tables: ^1.1.1 prosemirror-utils: ^0.9.6 prosemirror-view: ^1.23.6 + re-resizable: ^6.9.9 react: 17.0.2 react-countdown: ^2.3.2 react-dom: 17.0.2 @@ -172,7 +172,6 @@ importers: copy-to-clipboard: 3.3.1 deep-equal: 2.0.5 dompurify: 2.3.5 - interactjs: 1.10.11 katex: 0.15.2 kity: 2.0.4 lib0: 0.2.47 @@ -188,6 +187,7 @@ importers: prosemirror-tables: 1.1.1 prosemirror-utils: 0.9.6_prosemirror-tables@1.1.1 prosemirror-view: 1.23.6 + re-resizable: 6.9.9_react-dom@17.0.2+react@17.0.2 react: 17.0.2 react-countdown: 2.3.2_react-dom@17.0.2+react@17.0.2 react-dom: 17.0.2_react@17.0.2 @@ -955,10 +955,6 @@ packages: - y-protocols dev: false - /@interactjs/types/1.10.11: - resolution: {integrity: sha512-YRsVFWjL8Gkkvlx3qnjeaxW4fnibSJ9791g8BA7Pv5ANByI64WmtR1vU7A2rXcrOn8XvyCEfY0ss1s8NhZP+MA==} - dev: false - /@ioredis/commands/1.1.1: resolution: {integrity: sha512-fsR4P/ROllzf/7lXYyElUJCheWdTJVJvOTps8v9IWKFATxR61ANOlnoPqhH099xYLrJGpc2ZQ28B3rMeUt5VQg==} dev: false @@ -4468,12 +4464,6 @@ packages: through: 2.3.8 dev: true - /interactjs/1.10.11: - resolution: {integrity: sha512-VPUWsGAOPmrZe1YF7Fq/4AIBBZ+3FikZRS8bpzT6VsAfUuhxl/CKJY73IAiZHd3fz9p174CXErn0Qs81XEFICA==} - dependencies: - '@interactjs/types': 1.10.11 - dev: false - /internal-slot/1.0.3: resolution: {integrity: sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==} engines: {node: '>= 0.4'} @@ -6707,6 +6697,16 @@ packages: unpipe: 1.0.0 dev: false + /re-resizable/6.9.9_react-dom@17.0.2+react@17.0.2: + resolution: {integrity: sha512-l+MBlKZffv/SicxDySKEEh42hR6m5bAHfNu3Tvxks2c4Ah+ldnWjfnVRwxo/nxF27SsUsxDS0raAzFuJNKABXA==} + peerDependencies: + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 + dependencies: + react: 17.0.2 + react-dom: 17.0.2_react@17.0.2 + dev: false + /react-countdown/2.3.2_react-dom@17.0.2+react@17.0.2: resolution: {integrity: sha512-Q4SADotHtgOxNWhDdvgupmKVL0pMB9DvoFcxv5AzjsxVhzOVxnttMbAywgqeOdruwEAmnPhOhNv/awAgkwru2w==} peerDependencies: