feat: improve active-toolbar

This commit is contained in:
pubuzhixing8 committed 2024-10-09 09:40:41 +08:00
1 parent 4b2d964921
commit fd19725ab6
3 files changed
+167 -123

No files matched your search

+24 -24
View File
@@ -10,12 +10,12 @@
"license": "MIT",
"dependencies": {
"@floating-ui/react": "^0.26.24",
"@plait/common": "^0.66.1",
"@plait/core": "^0.66.1",
"@plait/draw": "^0.66.1",
"@plait/layouts": "^0.66.1",
"@plait/mind": "^0.66.1",
"@plait/text-plugins": "^0.66.1",
"@plait/common": "^0.67.0",
"@plait/core": "^0.67.0",
"@plait/draw": "^0.67.0",
"@plait/layouts": "^0.67.0",
"@plait/mind": "^0.67.0",
"@plait/text-plugins": "^0.67.0",
"@radix-ui/react-popover": "^1.0.3",
"ahooks": "^3.8.0",
"browser-fs-access": "^0.35.0",
@@ -3927,17 +3927,17 @@
}
},
"node_modules/@plait/common": {
"version": "0.66.1",
"resolved": "https://registry.npmjs.org/@plait/common/-/common-0.66.1.tgz",
"integrity": "sha512-nnMUsO2n1bcdcUYITV+BFR5ymcnfnDLjCQJYN04bHT/F41BQMwDhL48mqxaPGwHoS4yZKGBPIasnrFP2Dmoicw==",
"version": "0.67.0",
"resolved": "https://registry.npmjs.org/@plait/common/-/common-0.67.0.tgz",
"integrity": "sha512-rHjIxtU+OKKDZ2YdN7tk2/w6+w+dmT51NaCaYhNWJnRp6delT9WITlazpmCdhIJcHuCoVwOMSBG31CkD8HMLkA==",
"dependencies": {
"tslib": "^2.3.0"
}
},
"node_modules/@plait/core": {
"version": "0.66.1",
"resolved": "https://registry.npmjs.org/@plait/core/-/core-0.66.1.tgz",
"integrity": "sha512-ie/0SW0iy+hRJr3VuR1tZtJvvKIX6y1kVvALiraIKlZAeK1rmx2jajTvd5SQIES6giEeig/ekhUEKfN/sx5CUA==",
"version": "0.67.0",
"resolved": "https://registry.npmjs.org/@plait/core/-/core-0.67.0.tgz",
"integrity": "sha512-Yh3MczAmvATeoAmPewXDWwZKiGUklWzzEbU3RqWWN47hxsefGjweJ5TYhCLgDDWAfj3NpRD/eYMH4+KtsE4qXg==",
"dependencies": {
"tslib": "^2.3.0"
},
@@ -3950,33 +3950,33 @@
}
},
"node_modules/@plait/draw": {
"version": "0.66.1",
"resolved": "https://registry.npmjs.org/@plait/draw/-/draw-0.66.1.tgz",
"integrity": "sha512-X/wX2mtWUonXAZmQWkKE30U9FZeZYG4ixXHOMD/M2mU1U79LB/sktaqVZOGoDUB++2Ab+dXLdeyXM9OqFQR0eQ==",
"version": "0.67.0",
"resolved": "https://registry.npmjs.org/@plait/draw/-/draw-0.67.0.tgz",
"integrity": "sha512-QBq1VswNAOlszuHVs+LbaLYozOBZvsZAd8spaCjaAKkJNc745ZnQfCKUsVz5QsgkmR6thPvPU68lncMjPbskyQ==",
"dependencies": {
"tslib": "^2.3.0"
}
},
"node_modules/@plait/layouts": {
"version": "0.66.1",
"resolved": "https://registry.npmjs.org/@plait/layouts/-/layouts-0.66.1.tgz",
"integrity": "sha512-lSTzA5ipj0fQbdgdjrkKXQGjst6LCX65ZqfxT5b/lkWqTfY9+Wsl2w9vzL0VlyXX+VWUDTnWAY6cWP72gvH9SA==",
"version": "0.67.0",
"resolved": "https://registry.npmjs.org/@plait/layouts/-/layouts-0.67.0.tgz",
"integrity": "sha512-IWtiieUF1oIH3Tps+8kuJp2Dkxc8KItxtPtM1IHr79NbY23T5zfOzQGIyx0Wh77HWwKa+EIj9MYHeGSQOzcv3w==",
"dependencies": {
"tslib": "^2.3.0"
}
},
"node_modules/@plait/mind": {
"version": "0.66.1",
"resolved": "https://registry.npmjs.org/@plait/mind/-/mind-0.66.1.tgz",
"integrity": "sha512-NFSqUnH2yvYAKhwaAjB8c0w5AJt3wjBQPeS1hAGM1AK8r0I7W38CbXhj1spuC1P38Hg32hAuVLcya+/KhAhS+w==",
"version": "0.67.0",
"resolved": "https://registry.npmjs.org/@plait/mind/-/mind-0.67.0.tgz",
"integrity": "sha512-XYMobd9WuF/S5p/qMuYYDd94M4CjGeIWwsMr5DqbGAN/e/5XyUw8RMU/nsvVasoOOvxmykaXB0ri0Ptyjyp6dQ==",
"dependencies": {
"tslib": "^2.3.0"
}
},
"node_modules/@plait/text-plugins": {
"version": "0.66.1",
"resolved": "https://registry.npmjs.org/@plait/text-plugins/-/text-plugins-0.66.1.tgz",
"integrity": "sha512-A13FUCOG9OKU2alp/Zmf7MHcx3Xbm6iIVpRNVIQRp5/ko9n7eEzVS4LjkFqpBXx/77lhdTVROIiGFlyv3udOXA==",
"version": "0.67.0",
"resolved": "https://registry.npmjs.org/@plait/text-plugins/-/text-plugins-0.67.0.tgz",
"integrity": "sha512-b4k1YyNxOk4h0WlMyktEZdJUOTASA8+c1IDfBTaxXNJUA+5EwFgsAA//tNF3SEwbeCn0ZBQ3VuVl3RcyQxUosw==",
"dependencies": {
"tslib": "^2.3.0"
}
+6 -6
View File
@@ -10,12 +10,12 @@
"private": true,
"dependencies": {
"@floating-ui/react": "^0.26.24",
"@plait/common": "^0.66.1",
"@plait/core": "^0.66.1",
"@plait/draw": "^0.66.1",
"@plait/layouts": "^0.66.1",
"@plait/mind": "^0.66.1",
"@plait/text-plugins": "^0.66.1",
"@plait/common": "^0.67.0",
"@plait/core": "^0.67.0",
"@plait/draw": "^0.67.0",
"@plait/layouts": "^0.67.0",
"@plait/mind": "^0.67.0",
"@plait/text-plugins": "^0.67.0",
"@radix-ui/react-popover": "^1.0.3",
"ahooks": "^3.8.0",
"browser-fs-access": "^0.35.0",
@@ -3,6 +3,8 @@ import { BackgroundColorIcon, FontColorIcon, StrokeIcon } from '../icons';
import {
ATTACHED_ELEMENT_CLASS_NAME,
getSelectedElements,
isDragging,
isMovingElements,
isSelectionMoving,
Path,
PlaitBoard,
@@ -11,7 +13,7 @@ import {
SELECTION_RECTANGLE_CLASS_NAME,
Transforms,
} from '@plait/core';
import React, { useEffect } from 'react';
import React, { useEffect, useRef, useState } from 'react';
import { useBoard } from '@plait/react-board';
import { flip, offset, useFloating } from '@floating-ui/react';
import { Island } from '../island';
@@ -43,14 +45,14 @@ export type DrawActiveProps = {};
export const ActiveToolbar: React.FC<DrawActiveProps> = ({}) => {
const board = useBoard();
const selectedElements = getSelectedElements(board);
const isOpen = selectedElements.length > 0 && !isSelectionMoving(board);
const { viewport, selection } = board;
const [movingOrDragging, setMovingOrDragging] = useState(false);
const movingOrDraggingRef = useRef(movingOrDragging);
const open = selectedElements.length > 0 && !isSelectionMoving(board);
const { viewport, selection, children } = board;
const { refs, floatingStyles } = useFloating({
placement: 'top',
middleware: [offset(32), flip()],
});
let state: {
fill: string | undefined;
strokeColor?: string;
@@ -61,8 +63,7 @@ export const ActiveToolbar: React.FC<DrawActiveProps> = ({}) => {
} = {
fill: 'red',
};
if (isOpen) {
if (open && !movingOrDragging) {
const hasFill = selectedElements.some((value) =>
hasFillProperty(board, value)
);
@@ -71,9 +72,8 @@ export const ActiveToolbar: React.FC<DrawActiveProps> = ({}) => {
);
state = { ...getElementState(board), hasFill, hasFontColor: hasText };
}
useEffect(() => {
if (isOpen) {
if (open) {
let selectionG = PlaitBoard.getBoardContainer(board).querySelector(
`.${SELECTION_RECTANGLE_BOUNDING_CLASS_NAME}`
);
@@ -82,104 +82,148 @@ export const ActiveToolbar: React.FC<DrawActiveProps> = ({}) => {
`.${SELECTION_RECTANGLE_CLASS_NAME}`
);
}
refs.setPositionReference(selectionG);
if (selectionG) {
const rect = selectionG?.getBoundingClientRect();
refs.setPositionReference({
getBoundingClientRect() {
return {
width: rect.width,
height: rect.height,
x: rect.x,
y: rect.y,
top: rect.top,
left: rect.left,
right: rect.right,
bottom: rect.bottom,
};
},
});
}
}
}, [viewport, selection]);
}, [viewport, selection, children, movingOrDragging]);
useEffect(() => {
movingOrDraggingRef.current = movingOrDragging;
}, [movingOrDragging]);
useEffect(() => {
const { pointerUp, pointerMove } = board;
board.pointerMove = (event: PointerEvent) => {
if (
(isMovingElements(board) || isDragging(board)) &&
!movingOrDraggingRef.current
) {
setMovingOrDragging(true);
}
pointerMove(event);
};
board.pointerUp = (event: PointerEvent) => {
if (
movingOrDraggingRef.current &&
(isMovingElements(board) || isDragging(board))
) {
setMovingOrDragging(false);
}
pointerUp(event);
};
return () => {
board.pointerUp = pointerUp;
board.pointerMove = pointerMove;
};
}, [board]);
return (
<>
{isOpen && (
<div ref={refs.setFloating} style={floatingStyles}>
<Island
padding={1}
className={classNames(
'active-toolbar',
ATTACHED_ELEMENT_CLASS_NAME
)}
>
<Stack.Row gap={1}>
{state.hasFontColor && (
<ActiveFontColorToolButton
key={0}
currentColor={state.fontColor}
title={`Font Color`}
fontColorIcon={
<FontColorIcon currentColor={state.marks?.color} />
}
onSelect={(selectedColor: string) => {
TextTransforms.setTextColor(
board,
selectedColor,
undefined,
getSelectedTableCellsEditor(board)
);
}}
></ActiveFontColorToolButton>
)}
<ActiveColorToolButton
key={1}
currentColor={state.strokeColor}
title={`Stroke`}
transparentIcon={StrokeIcon}
{open && !movingOrDragging && (
<Island
padding={1}
className={classNames('active-toolbar', ATTACHED_ELEMENT_CLASS_NAME)}
ref={refs.setFloating}
style={floatingStyles}
>
<Stack.Row gap={1}>
{state.hasFontColor && (
<ActiveFontColorToolButton
key={0}
currentColor={state.fontColor}
title={`Font Color`}
fontColorIcon={
<FontColorIcon currentColor={state.marks?.color} />
}
onSelect={(selectedColor: string) => {
console.log(`selectedColor: ${selectedColor}`);
PropertyTransforms.setStrokeColor(board, selectedColor, {
TextTransforms.setTextColor(
board,
selectedColor,
undefined,
getSelectedTableCellsEditor(board)
);
}}
></ActiveFontColorToolButton>
)}
<ActiveColorToolButton
key={1}
currentColor={state.strokeColor}
title={`Stroke`}
transparentIcon={StrokeIcon}
onSelect={(selectedColor: string) => {
console.log(`selectedColor: ${selectedColor}`);
PropertyTransforms.setStrokeColor(board, selectedColor, {
getMemorizeKey,
});
}}
>
<label
className={classNames('stroke-label', 'color-label', {
'color-white': state.fill === '#FFFFFF',
})}
style={{ borderColor: state.strokeColor }}
></label>
</ActiveColorToolButton>
{state.hasFill && (
<ActiveColorToolButton
key={2}
currentColor={state.fill}
title={`Fill Color`}
transparentIcon={BackgroundColorIcon}
onSelect={(selectedColor: string) => {
PropertyTransforms.setFillColor(board, selectedColor, {
getMemorizeKey,
callback: (element: PlaitElement, path: Path) => {
const tableElement =
PlaitDrawElement.isElementByTable(element);
if (tableElement) {
DrawTransforms.setTableFill(
board,
element,
selectedColor,
path
);
} else {
if (isDrawElementClosed(element as PlaitDrawElement)) {
Transforms.setNode(
board,
{ fill: selectedColor },
path
);
}
}
},
});
}}
>
<label
className={classNames('stroke-label', 'color-label', {
className={classNames('fill-label', 'color-label', {
'color-white': state.fill === '#FFFFFF',
})}
style={{ borderColor: state.strokeColor }}
style={{ backgroundColor: state.fill }}
></label>
</ActiveColorToolButton>
{state.hasFill && (
<ActiveColorToolButton
key={2}
currentColor={state.fill}
title={`Fill Color`}
transparentIcon={BackgroundColorIcon}
onSelect={(selectedColor: string) => {
PropertyTransforms.setFillColor(board, selectedColor, {
getMemorizeKey,
callback: (element: PlaitElement, path: Path) => {
const tableElement =
PlaitDrawElement.isElementByTable(element);
if (tableElement) {
DrawTransforms.setTableFill(
board,
element,
selectedColor,
path
);
} else {
if (
isDrawElementClosed(element as PlaitDrawElement)
) {
Transforms.setNode(
board,
{ fill: selectedColor },
path
);
}
}
},
});
}}
>
<label
className={classNames('fill-label', 'color-label', {
'color-white': state.fill === '#FFFFFF',
})}
style={{ backgroundColor: state.fill }}
></label>
</ActiveColorToolButton>
)}
</Stack.Row>
</Island>
</div>
)}
</Stack.Row>
</Island>
)}
</>
);