working on toolbar
This commit is contained in:
@@ -43,7 +43,7 @@ function App() {
|
||||
content: <WidgetsContainer onWidgetsUpdate={(widgets) => setSidebarWidgets(widgets)}/>
|
||||
},
|
||||
{
|
||||
name: "Extensions",
|
||||
name: "Plugins",
|
||||
icon: <ProductFilled />,
|
||||
content: <></>
|
||||
},
|
||||
|
||||
@@ -10,6 +10,7 @@ import Widget from "./widgets/base"
|
||||
import Cursor from "./constants/cursor"
|
||||
import { UID } from "../utils/uid"
|
||||
import { removeDuplicateObjects } from "../utils/common"
|
||||
import CanvasToolBar from "./toolbar"
|
||||
|
||||
|
||||
const CanvasModes = {
|
||||
@@ -50,10 +51,11 @@ class Canvas extends React.Component {
|
||||
isPanning: false,
|
||||
currentTranslate: { x: 0, y: 0 },
|
||||
canvasSize: { width: 500, height: 500 },
|
||||
contextMenuItems: []
|
||||
}
|
||||
contextMenuItems: [],
|
||||
toolbarOpen: true,
|
||||
|
||||
this.selectedWidgets = []
|
||||
selectedWidgets: []
|
||||
}
|
||||
|
||||
this._onWidgetListUpdated = onWidgetListUpdated // a function callback when the widget is added to the canvas
|
||||
|
||||
@@ -118,12 +120,6 @@ class Canvas extends React.Component {
|
||||
this.canvasContainerRef.current.addEventListener("mouseup", this.mouseUpEvent)
|
||||
this.canvasContainerRef.current.addEventListener("mousemove", this.mouseMoveEvent)
|
||||
|
||||
|
||||
// this.canvasRef.current.addEventListener("selection:created", () => {
|
||||
// console.log("selected")
|
||||
// this.currentMode = Modes.DEFAULT
|
||||
// })
|
||||
|
||||
this.canvasContainerRef.current.addEventListener('wheel', (event) => {
|
||||
this.wheelZoom(event)
|
||||
})
|
||||
@@ -163,15 +159,20 @@ class Canvas extends React.Component {
|
||||
// if the widget is selected don't pan, instead move the widget
|
||||
if (!selectedWidget._disableSelection){
|
||||
|
||||
const selectedLength = this.selectedWidgets.length
|
||||
const selectedLength = this.state.selectedWidgets.length
|
||||
|
||||
if (selectedLength === 0 || (selectedLength === 1 && selectedWidget.__id !== this.selectedWidgets[0].__id)){
|
||||
this.selectedWidgets[0]?.deSelect() // deselect the previous widget before adding the new one
|
||||
this.selectedWidgets[0]?.setZIndex(0)
|
||||
if (selectedLength === 0 || (selectedLength === 1 && selectedWidget.__id !== this.state.selectedWidgets[0].__id)){
|
||||
this.state.selectedWidgets[0]?.deSelect() // deselect the previous widget before adding the new one
|
||||
this.state.selectedWidgets[0]?.setZIndex(0)
|
||||
|
||||
selectedWidget.setZIndex(1000)
|
||||
selectedWidget.select()
|
||||
this.selectedWidgets[0] = selectedWidget
|
||||
|
||||
this.setState({
|
||||
selectedWidgets: [selectedWidget]
|
||||
})
|
||||
|
||||
console.log("selected")
|
||||
}
|
||||
this.currentMode = CanvasModes.MOVE_WIDGET
|
||||
}
|
||||
@@ -187,7 +188,8 @@ class Canvas extends React.Component {
|
||||
}
|
||||
|
||||
this.setState({
|
||||
contextMenuItems: []
|
||||
contextMenuItems: [],
|
||||
toolbarOpen: true
|
||||
})
|
||||
// this.setState({
|
||||
// showContextMenu: false
|
||||
@@ -195,13 +197,16 @@ class Canvas extends React.Component {
|
||||
}else if (event.button === 2){
|
||||
//right click
|
||||
|
||||
if (this.selectedWidgets.length > 0 && this.selectedWidgets[0].__id !== selectedWidget.__id){
|
||||
if (this.state.selectedWidgets.length > 0 && this.state.selectedWidgets[0].__id !== selectedWidget.__id){
|
||||
this.clearSelections()
|
||||
}
|
||||
|
||||
if (selectedWidget)
|
||||
this.selectedWidgets[0] = selectedWidget
|
||||
console.log("renaming: ", selectedWidget)
|
||||
|
||||
this.setState({
|
||||
selectedWidget: [selectedWidget]
|
||||
})
|
||||
|
||||
this.setState({
|
||||
contextMenuItems: [
|
||||
{
|
||||
@@ -229,8 +234,7 @@ class Canvas extends React.Component {
|
||||
const deltaX = event.clientX - this.mousePos.x
|
||||
const deltaY = event.clientY - this.mousePos.y
|
||||
|
||||
|
||||
if (this.selectedWidgets.length === 0){
|
||||
if (this.state.selectedWidgets.length === 0){
|
||||
// if there aren't any selected widgets, then pan the canvas
|
||||
this.setState(prevState => ({
|
||||
currentTranslate: {
|
||||
@@ -241,7 +245,7 @@ class Canvas extends React.Component {
|
||||
|
||||
}else{
|
||||
// update the widgets position
|
||||
this.selectedWidgets.forEach(widget => {
|
||||
this.state.selectedWidgets.forEach(widget => {
|
||||
const {x, y} = widget.getPos()
|
||||
|
||||
const newPosX = x + (deltaX/this.state.zoom) // account for the zoom, since the widget is relative to canvas
|
||||
@@ -363,7 +367,11 @@ class Canvas extends React.Component {
|
||||
this.getActiveObjects().forEach(widget => {
|
||||
widget.current?.deSelect()
|
||||
})
|
||||
this.selectedWidgets = []
|
||||
|
||||
this.setState({
|
||||
selectedWidgets: []
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -420,11 +428,11 @@ class Canvas extends React.Component {
|
||||
return {id, widgetRef}
|
||||
}
|
||||
|
||||
deleteSelectedWidgets(widgets){
|
||||
deleteSelectedWidgets(widgets=[]){
|
||||
|
||||
|
||||
let activeWidgets = removeDuplicateObjects([...widgets, ...this.selectedWidgets], "__id")
|
||||
console.log("active widget: ", widgets, activeWidgets)
|
||||
let activeWidgets = removeDuplicateObjects([...widgets, ...this.state.selectedWidgets], "__id")
|
||||
|
||||
const widgetIds = activeWidgets.map(widget => widget.__id)
|
||||
|
||||
for (let widgetId of widgetIds){
|
||||
@@ -489,30 +497,32 @@ class Canvas extends React.Component {
|
||||
<Tooltip title="Reset viewport">
|
||||
<Button icon={<ReloadOutlined />} onClick={this.resetTransforms} />
|
||||
</Tooltip>
|
||||
<Tooltip title="Reset viewport">
|
||||
<Tooltip title="Clear canvas">
|
||||
<Button icon={<CloseOutlined />} onClick={this.clearCanvas} />
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
||||
<Droppable id="canvas-droppable" className="tw-w-full tw-h-full">
|
||||
<Dropdown trigger={['contextMenu']} mouseLeaveDelay={0} menu={{items: this.state.contextMenuItems, }}>
|
||||
<div className="tw-w-full tw-h-full tw-flex tw-relative tw-bg-black tw-overflow-hidden"
|
||||
ref={this.canvasContainerRef}
|
||||
style={{transition: " transform 0.3s ease-in-out"}}
|
||||
>
|
||||
{/* Canvas */}
|
||||
<div data-canvas className="tw-w-full tw-h-full tw-absolute tw-top-0 tw-select-none
|
||||
t tw-bg-green-300"
|
||||
ref={this.canvasRef}>
|
||||
<div className="tw-relative tw-w-full tw-h-full">
|
||||
{
|
||||
this.state.widgets.map(this.renderWidget)
|
||||
}
|
||||
</div>
|
||||
<Droppable id="canvas-droppable" className="tw-w-full tw-h-full">
|
||||
<Dropdown trigger={['contextMenu']} mouseLeaveDelay={0} menu={{items: this.state.contextMenuItems, }}>
|
||||
<div className="tw-w-full tw-h-full tw-flex tw-relative tw-bg-black tw-overflow-hidden"
|
||||
ref={this.canvasContainerRef}
|
||||
style={{transition: " transform 0.3s ease-in-out"}}
|
||||
>
|
||||
{/* Canvas */}
|
||||
<div data-canvas className="tw-w-full tw-h-full tw-absolute tw-top-0 tw-select-none
|
||||
t tw-bg-green-300"
|
||||
ref={this.canvasRef}>
|
||||
<div className="tw-relative tw-w-full tw-h-full">
|
||||
{
|
||||
this.state.widgets.map(this.renderWidget)
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</Dropdown>
|
||||
</Droppable>
|
||||
</div>
|
||||
</Dropdown>
|
||||
</Droppable>
|
||||
|
||||
<CanvasToolBar isOpen={this.state.toolbarOpen} activeWidget={this.state.selectedWidgets[0]}/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { useCallback, useRef, useEffect, useMemo } from "react"
|
||||
import * as fabric from 'fabric'
|
||||
|
||||
/**
|
||||
*
|
||||
* @deprecated
|
||||
* This is a functional based component of the canvas which was discarded because it makes code
|
||||
* ugly and hard to interface with fabric.js, Fabric 6 has breaking changes such as dispose, is async
|
||||
* which interferes wih useEffect
|
||||
39
src/canvas/toolbar.js
Normal file
39
src/canvas/toolbar.js
Normal file
@@ -0,0 +1,39 @@
|
||||
import { useEffect, useState } from "react"
|
||||
import { capitalize } from "../utils/common"
|
||||
|
||||
|
||||
function CanvasToolBar({isOpen, activeWidget}){
|
||||
|
||||
const [toolbarOpen, setToolbarOpen] = useState(isOpen)
|
||||
|
||||
const [widget, setWidget] = useState(activeWidget)
|
||||
|
||||
useEffect(() => {
|
||||
setToolbarOpen(isOpen)
|
||||
}, [isOpen])
|
||||
|
||||
useEffect(() => {
|
||||
setWidget(activeWidget)
|
||||
}, [activeWidget])
|
||||
|
||||
console.log("Widget type: ", widget?.getWidgetType())
|
||||
return (
|
||||
<div className={`tw-absolute tw-top-20 tw-right-5 tw-bg-white ${toolbarOpen ? "tw-w-[320px]": "tw-w-0"}
|
||||
tw-px-4 tw-p-2 tw-h-[600px] tw-rounded-md tw-z-20 tw-shadow-lg
|
||||
tw-transition-transform tw-duration-75
|
||||
tw-flex tw-flex-col
|
||||
`}
|
||||
>
|
||||
|
||||
<h3 className="tw-text-2xl tw-text-center">
|
||||
{capitalize(`${widget?.getWidgetType() || ""}`)}
|
||||
</h3>
|
||||
|
||||
</div>
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
export default CanvasToolBar
|
||||
@@ -92,6 +92,8 @@ class Widget extends React.Component{
|
||||
this.getElement = this.getElement.bind(this)
|
||||
this.getBoundingRect = this.getBoundingRect.bind(this)
|
||||
|
||||
this.getWidgetName = this.getWidgetName.bind(this)
|
||||
this.getWidgetType = this.getWidgetType.bind(this)
|
||||
// this.openRenaming = this.openRenaming.bind(this)
|
||||
|
||||
this.isSelected = this.isSelected.bind(this)
|
||||
@@ -129,6 +131,14 @@ class Widget extends React.Component{
|
||||
return toSnakeCase(this.state.widgetName)
|
||||
}
|
||||
|
||||
getWidgetName(){
|
||||
return this.state.widgetName
|
||||
}
|
||||
|
||||
getWidgetType(){
|
||||
return this.constructor.widgetType
|
||||
}
|
||||
|
||||
/**
|
||||
* removes the element/widget
|
||||
*/
|
||||
|
||||
@@ -45,14 +45,15 @@ function Sidebar({tabs}){
|
||||
return (
|
||||
<div className={`tw-relative tw-duration-[0.3s] tw-transition-all
|
||||
tw-max-w-[400px] tw-flex tw-h-full tw-z-10
|
||||
${sidebarOpen ? "tw-bg-white tw-min-w-[400px] tw-w-[400px] tw-shadow-lg": "tw-bg-primaryBg tw-min-w-[80px] tw-w-[80px]"}
|
||||
${sidebarOpen ? "tw-bg-white tw-min-w-[400px] tw-w-[400px] tw-shadow-lg":
|
||||
"tw-bg-primaryBg tw-min-w-[80px] tw-w-[80px]"}
|
||||
`}
|
||||
ref={sideBarRef}
|
||||
onMouseLeave={hideOnMouseLeave}
|
||||
>
|
||||
|
||||
|
||||
<div className="tw-w-full tw-max-w-[80px] tw-h-full tw-flex tw-flex-col tw-gap-4 tw-p-3 tw-place-items-center">
|
||||
<div className="tw-min-w-[80px] tw-w-[80px] tw-h-full tw-flex tw-flex-col tw-gap-4 tw-p-3 tw-place-items-center">
|
||||
{
|
||||
sidebarTabs.map((tab, index) => {
|
||||
return (
|
||||
|
||||
@@ -11,4 +11,15 @@ export function removeDuplicateObjects(array, key) {
|
||||
}
|
||||
return false
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* capitalize the first letter
|
||||
* @param {string} str
|
||||
* @returns
|
||||
*/
|
||||
export function capitalize(str) {
|
||||
console.log("Text: ", str)
|
||||
return str.charAt(0).toUpperCase() + str.slice(1)
|
||||
}
|
||||
Reference in New Issue
Block a user