working on sidebar and widget context

This commit is contained in:
paul
2025-03-08 20:11:22 +05:30
parent aa54f9b0bb
commit 0f7d9944a8
5 changed files with 158 additions and 54 deletions

View File

@@ -4,7 +4,7 @@
*/
import { useEffect, useRef, useState } from 'react'
import { LayoutFilled, ProductFilled, CloudUploadOutlined, DatabaseFilled } from "@ant-design/icons"
import { LayoutFilled, ProductFilled, CloudUploadOutlined, DatabaseFilled, AlignLeftOutlined } from "@ant-design/icons"
// import { DndContext, useSensors, useSensor, PointerSensor, closestCorners, DragOverlay, rectIntersection } from '@dnd-kit/core'
// import { snapCenterToCursor } from '@dnd-kit/modifiers'
@@ -31,6 +31,8 @@ import generateTkinterCode from './frameworks/tkinter/engine/code'
import TkMainWindow from './frameworks/tkinter/widgets/mainWindow'
import CTkMainWindow from './frameworks/customtk/widgets/mainWindow'
import TreeviewContainer from './sidebar/treeviewContainer'
import { WidgetContextProvider } from './canvas/context/widgetContext'
function App() {
@@ -64,6 +66,11 @@ function App() {
icon: <ProductFilled />,
content: <PluginsContainer sidebarContent={sidebarPlugins}/>
},
{
name: "Tree view",
icon: <AlignLeftOutlined />,
content: <TreeviewContainer />
},
{
name: "Uploads",
icon: <CloudUploadOutlined />,
@@ -162,6 +169,7 @@ function App() {
const handleWidgetAddedToCanvas = (widgets) => {
setCanvasWidgets(widgets)
console.log("widget added: ", widgets)
}
const handleCodeGen = () => {
@@ -208,16 +216,19 @@ function App() {
<p>Are you sure you want to change the framework? This will clear the canvas.</p>
</Modal> */}
<DragProvider>
<div className="tw-w-full tw-h-[94vh] tw-flex">
<Sidebar tabs={sidebarTabs}/>
{/* <ActiveWidgetProvider> */}
<Canvas ref={canvasRef} widgets={canvasWidgets} onWidgetAdded={handleWidgetAddedToCanvas}/>
{/* </ActiveWidgetProvider> */}
</div>
{/* dragOverlay (dnd-kit) helps move items from one container to another */}
</DragProvider>
<WidgetContextProvider>
<DragProvider>
<div className="tw-w-full tw-h-[94vh] tw-flex">
<Sidebar tabs={sidebarTabs}/>
{/* <ActiveWidgetProvider> */}
<Canvas ref={canvasRef} widgets={canvasWidgets}
onWidgetAdded={handleWidgetAddedToCanvas}/>
{/* </ActiveWidgetProvider> */}
</div>
{/* dragOverlay (dnd-kit) helps move items from one container to another */}
</DragProvider>
</WidgetContextProvider>
</div>
)
}

View File

@@ -798,32 +798,32 @@ class Canvas extends React.Component {
__checkClosestShiftElement = ({ event, parentWidgetId, dragElementID }) => {
// NOTE: work on this more maybe even check all four corners
const parentWidget = this.findWidgetFromListById(parentWidgetId);
if (!parentWidget) return;
const parentWidget = this.findWidgetFromListById(parentWidgetId)
if (!parentWidget) return
const dropX = event.clientX;
const dropY = event.clientY;
const dropX = event.clientX
const dropY = event.clientY
let closestChild = null;
let closestIndex = parentWidget.children.length;
let minDistance = Infinity;
let closestChild = null
let closestIndex = parentWidget.children.length
let minDistance = Infinity
// Only check the first level of children
parentWidget.children.forEach((child, index) => {
if (child.id !== dragElementID) {
const childElement = this.widgetRefs[child.id]
if (!childElement) return;
if (!childElement) return
const rect = childElement.current.getBoundingRect()
const childTopRightX = rect.right
const childTopRightY = rect.top
// Compute Euclidean distance from drop position
const distance = Math.hypot(childTopRightX - dropX, childTopRightY - dropY);
const distance = Math.hypot(childTopRightX - dropX, childTopRightY - dropY)
if (distance < minDistance) {
minDistance = distance;
closestChild = child;
minDistance = distance
closestChild = child
closestIndex = index + 1
}
}
@@ -836,7 +836,7 @@ class Canvas extends React.Component {
const rect = childElement.current.getBoundingRect()
// Closest is first child, check if dropped before or after
closestIndex = dropX < rect.left ? 0 : 1;
closestIndex = dropX < rect.left ? 0 : 1
}
return {closestChild, closestIndex}

View File

@@ -1,35 +1,19 @@
import React, { createContext, Component } from 'react'
import React, { createContext, useContext, useState } from 'react';
const WidgetContext = createContext()
const widgetContext = createContext()
// NOTE: Don't use this context provider
export const useSelectedWidgetContext = () => useContext(widgetContext)
class WidgetProvider extends Component {
state = {
activeWidget: null, // Keeps track of the active widget's data
widgetMethods: null, // Function to update active widget's state
}
setActiveWidget = (widgetData, widgetMethods) => {
this.setState({
activeWidget: widgetData,
widgetMethods: widgetMethods, // Store the update function of the active widget
})
}
export const WidgetContextProvider = ({ children }) => {
const [widgets, setWidgets] = useState(null)
render() {
return (
<WidgetContext.Provider
value={{
activeWidget: this.state.activeWidget,
setActiveWidget: this.setActiveWidget,
widgetMethods: this.state.widgetMethods, // Expose the update function
}}
>
{this.props.children}
</WidgetContext.Provider>
)
}
const [widgetRef, setWidgetRef] = useState({})
// const []
return (
<widgetContext.Provider value={{ widgets, setWidgets, widgetRef, setWidgetRef }}>
{children}
</widgetContext.Provider>
)
}
export { WidgetContext, WidgetProvider }

View File

@@ -1,13 +1,15 @@
import { useEffect, useMemo, useRef } from "react"
import Draggable from "./utils/draggableDnd"
import { Button } from "antd"
import { GithubOutlined, GitlabOutlined, LinkOutlined,
AudioOutlined, FileTextOutlined,
DeleteFilled,
DeleteOutlined,
GlobalOutlined} from "@ant-design/icons"
GlobalOutlined,
EyeOutlined} from "@ant-design/icons"
import DraggableWrapper from "./draggable/draggable"
import { Button } from "antd"
export function SidebarWidgetCard({ name, img, url, license, widgetClass, innerRef}){
@@ -148,4 +150,22 @@ export function DraggableAssetCard({file, onDelete}){
</div>
)
}
export function TreeViewCard({widgetId, onDelete, title}){
return (
<div className="tw-flex tw-place-items-center tw-px-2 tw-p-1 tw-place-content-between
tw-gap-4 tw-w-full" style={{width: "100%"}}>
<div className="tw-text-sm">
{title}
</div>
<div className="tw-ml-auto tw-flex tw-gap-1">
<Button color="danger" size="small" variant="text" danger icon={<DeleteOutlined />}></Button>
<Button variant="text" size="small" icon={<EyeOutlined />}></Button>
</div>
</div>
)
}

View File

@@ -0,0 +1,89 @@
import { useEffect, useMemo, useState } from "react"
import { CloseCircleFilled, SearchOutlined } from "@ant-design/icons"
import { SidebarWidgetCard, TreeViewCard } from "../components/cards"
import ButtonWidget from "../assets/widgets/button.png"
import { filterObjectListStartingWith } from "../utils/filter"
import Widget from "../canvas/widgets/base"
import { SearchComponent } from "../components/inputs"
import { Tree } from "antd"
import { TreeNode } from "antd/es/tree-select"
/**
*
* @param {function} onWidgetsUpdate - this is a callback that will be called once the sidebar is populated with widgets
* @returns
*/
function TreeviewContainer({ sidebarContent, onWidgetsUpdate }) {
const [searchValue, setSearchValue] = useState("")
const [widgetData, setWidgetData] = useState(sidebarContent)
const treeData = [
{
title: 'Parent',
key: '0-0',
children: [
{ title: 'Child 1', key: '0-0-1' },
{ title: 'Child 2', key: '0-0-2' },
],
},
];
useEffect(() => {
setWidgetData(sidebarContent)
// if (onWidgetsUpdate){
// onWidgetsUpdate(widgets)
// }
}, [sidebarContent])
// useEffect(() => {
// if (searchValue.length > 0) {
// const searchData = filterObjectListStartingWith(sidebarContent, "name", searchValue)
// setWidgetData(searchData)
// } else {
// setWidgetData(sidebarContent)
// }
// }, [searchValue])
function onSearch(event) {
setSearchValue(event.target.value)
}
return (
<div className="tw-w-full tw-p-2 tw-gap-4 tw-flex tw-flex-col tw-overflow-x-hidden">
{/* <SearchComponent onSearch={onSearch} searchValue={searchValue}
onClear={() => setSearchValue("")} /> */}
<div className="tw-flex tw-flex-col tw-gap-2 tw-w-full tw-h-full tw-p-1">
<Tree treeData={treeData}
titleRender={(nodeData) =>
<TreeViewCard title={nodeData.title}/>
}
>
</Tree>
</div>
</div>
)
}
export default TreeviewContainer