solved bugs(while use backspace key and escape key) and added the groupnames correctly
This commit is contained in:
@@ -68,7 +68,7 @@ const TreeNode: React.FC<TreeNodeProps> = ({
|
|||||||
const [isVisible, setIsVisible] = useState(item.isVisible ?? true);
|
const [isVisible, setIsVisible] = useState(item.isVisible ?? true);
|
||||||
const [isLocked, setIsLocked] = useState(item.isLocked ?? false);
|
const [isLocked, setIsLocked] = useState(item.isLocked ?? false);
|
||||||
const [isEditing, setIsEditing] = useState(false);
|
const [isEditing, setIsEditing] = useState(false);
|
||||||
const [name, setName] = useState(isGroupNode ? item.groupName : item.modelName);
|
const [name, setName] = useState(item.groupName || item.modelName);
|
||||||
|
|
||||||
const handleDragStart = (e: React.DragEvent) => {
|
const handleDragStart = (e: React.DragEvent) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
@@ -108,10 +108,11 @@ const TreeNode: React.FC<TreeNodeProps> = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleDivKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {
|
const handleDivKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {
|
||||||
// support Enter and Space for accessibility
|
if (e.key === "Enter") {
|
||||||
if (e.key === "Enter" || e.key === " ") {
|
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
toggleSelect();
|
toggleSelect();
|
||||||
|
} else if (e.key === "Escape") {
|
||||||
|
setIsEditing(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -122,7 +123,6 @@ const TreeNode: React.FC<TreeNodeProps> = ({
|
|||||||
return (
|
return (
|
||||||
<div className="tree-node">
|
<div className="tree-node">
|
||||||
<div
|
<div
|
||||||
tabIndex={0}
|
|
||||||
onKeyDown={handleDivKeyDown}
|
onKeyDown={handleDivKeyDown}
|
||||||
onTouchStart={handleTouchStart}
|
onTouchStart={handleTouchStart}
|
||||||
className={clsx("tree-node-content", {
|
className={clsx("tree-node-content", {
|
||||||
@@ -140,7 +140,7 @@ const TreeNode: React.FC<TreeNodeProps> = ({
|
|||||||
id={item.modelUuid || item.groupUuid}
|
id={item.modelUuid || item.groupUuid}
|
||||||
onClick={toggleSelect}
|
onClick={toggleSelect}
|
||||||
>
|
>
|
||||||
<div className="node-wrapper" style={{ paddingLeft: `${level * 25 + 8}px` }}>
|
<div className="node-wrapper" style={{ paddingLeft: `${level * 6 + 1}px` }}>
|
||||||
{isGroupNode && (
|
{isGroupNode && (
|
||||||
<button
|
<button
|
||||||
className="expand-button"
|
className="expand-button"
|
||||||
@@ -217,7 +217,7 @@ const TreeNode: React.FC<TreeNodeProps> = ({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{isExpanded && item.children?.length ? (
|
{isExpanded && item.children?.length ? (
|
||||||
<div className="tree-children">
|
<div className="tree-children" style={{ paddingLeft: "10px" }}>
|
||||||
{item.children.map((child) => (
|
{item.children.map((child) => (
|
||||||
<TreeNode
|
<TreeNode
|
||||||
key={child.groupUuid || child.modelUuid}
|
key={child.groupUuid || child.modelUuid}
|
||||||
@@ -301,8 +301,6 @@ export const OutlineList: React.FC<OutlinePanelProps> = ({
|
|||||||
if (!insertItemByAction(draggedItem, targetId, action, updatedHierarchy)) {
|
if (!insertItemByAction(draggedItem, targetId, action, updatedHierarchy)) {
|
||||||
updatedHierarchy.push(draggedItem);
|
updatedHierarchy.push(draggedItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Commit changes
|
|
||||||
setGroupHierarchy(updatedHierarchy);
|
setGroupHierarchy(updatedHierarchy);
|
||||||
setDraggingItem(null);
|
setDraggingItem(null);
|
||||||
hoveredDiv.style.borderTop = "none";
|
hoveredDiv.style.borderTop = "none";
|
||||||
@@ -404,7 +402,6 @@ export const OutlineList: React.FC<OutlinePanelProps> = ({
|
|||||||
const hoveredDiv = document.getElementById(targetId);
|
const hoveredDiv = document.getElementById(targetId);
|
||||||
if (!hoveredDiv) return;
|
if (!hoveredDiv) return;
|
||||||
|
|
||||||
// Remove previous outlines before applying new one
|
|
||||||
hoveredDiv.style.outline = "none";
|
hoveredDiv.style.outline = "none";
|
||||||
hoveredDiv.style.borderTop = "none";
|
hoveredDiv.style.borderTop = "none";
|
||||||
hoveredDiv.style.borderBottom = "none";
|
hoveredDiv.style.borderBottom = "none";
|
||||||
@@ -412,21 +409,13 @@ export const OutlineList: React.FC<OutlinePanelProps> = ({
|
|||||||
const rect = hoveredDiv.getBoundingClientRect();
|
const rect = hoveredDiv.getBoundingClientRect();
|
||||||
const y = (event as any).clientY - rect.top;
|
const y = (event as any).clientY - rect.top;
|
||||||
|
|
||||||
// Determine where the user is hovering
|
|
||||||
if (y >= 0 && y < 7) {
|
if (y >= 0 && y < 7) {
|
||||||
// Top region
|
|
||||||
console.log("Top: ");
|
|
||||||
|
|
||||||
hoveredDiv.style.borderTop = "2px solid purple";
|
hoveredDiv.style.borderTop = "2px solid purple";
|
||||||
return "above";
|
return "above";
|
||||||
} else if (y >= 19 && y < 32) {
|
} else if (y >= 19 && y < 32) {
|
||||||
// Bottom region
|
|
||||||
console.log("Bottom: ");
|
|
||||||
hoveredDiv.style.borderBottom = "2px solid purple";
|
hoveredDiv.style.borderBottom = "2px solid purple";
|
||||||
return "below";
|
return "below";
|
||||||
} else {
|
} else {
|
||||||
// Middle region (child)
|
|
||||||
console.log("Middle: ");
|
|
||||||
hoveredDiv.style.outline = "2px solid #b188ff";
|
hoveredDiv.style.outline = "2px solid #b188ff";
|
||||||
return "child";
|
return "child";
|
||||||
}
|
}
|
||||||
@@ -475,8 +464,8 @@ export const OutlineList: React.FC<OutlinePanelProps> = ({
|
|||||||
onDrop={handleDrop}
|
onDrop={handleDrop}
|
||||||
onDragOver={handleDragOver}
|
onDragOver={handleDragOver}
|
||||||
draggingItem={draggingItem}
|
draggingItem={draggingItem}
|
||||||
selectedObject={selectedObject} // pass UUID
|
selectedObject={selectedObject}
|
||||||
setSelectedObject={setSelectedObject} // pass setter
|
setSelectedObject={setSelectedObject}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,321 +1,3 @@
|
|||||||
// .outline-overlay {
|
|
||||||
// padding: 0 4px;
|
|
||||||
// font-family: "Segoe UI", sans-serif;
|
|
||||||
// display: flex;
|
|
||||||
// position: absolute;
|
|
||||||
// top: 0;
|
|
||||||
// bottom: 0;
|
|
||||||
// width: 100vw;
|
|
||||||
// pointer-events: none;
|
|
||||||
// .outline-card {
|
|
||||||
// pointer-events: all;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// .outline-header {
|
|
||||||
// display: flex;
|
|
||||||
// align-items: center;
|
|
||||||
// justify-content: space-between;
|
|
||||||
// padding: 10px 16px;
|
|
||||||
// border-bottom: 1px solid #2e2e3e;
|
|
||||||
|
|
||||||
// .header-title {
|
|
||||||
// p {
|
|
||||||
// margin: 0;
|
|
||||||
// font-weight: 600;
|
|
||||||
// font-size: 14px;
|
|
||||||
// color: #ffffff;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// .outline-toolbar {
|
|
||||||
// display: flex;
|
|
||||||
// gap: 8px;
|
|
||||||
|
|
||||||
// .toolbar-button {
|
|
||||||
// background: none;
|
|
||||||
// border: none;
|
|
||||||
// color: #aaa;
|
|
||||||
// cursor: pointer;
|
|
||||||
// width: 24px;
|
|
||||||
// height: 24px;
|
|
||||||
// border-radius: 4px;
|
|
||||||
// transition: background 0.3s;
|
|
||||||
|
|
||||||
// &:hover {
|
|
||||||
// background-color: rgba(255, 255, 255, 0.1);
|
|
||||||
// color: #a855f7;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// svg {
|
|
||||||
// width: 100%;
|
|
||||||
// height: 100%;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// .close-button {
|
|
||||||
// background: none;
|
|
||||||
// border: none;
|
|
||||||
// color: #aaa;
|
|
||||||
// cursor: pointer;
|
|
||||||
// width: 24px;
|
|
||||||
// height: 24px;
|
|
||||||
// border-radius: 4px;
|
|
||||||
// transition: transform 0.3s ease;
|
|
||||||
|
|
||||||
// &:hover {
|
|
||||||
// background-color: rgba(255, 255, 255, 0.1);
|
|
||||||
// transform: rotate(-90deg);
|
|
||||||
// color: #a855f7;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// svg {
|
|
||||||
// width: 100%;
|
|
||||||
// height: 100%;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// .outline-content {
|
|
||||||
// max-height: 52vh;
|
|
||||||
// overflow-y: auto;
|
|
||||||
// padding: 8px 0;
|
|
||||||
|
|
||||||
// &::-webkit-scrollbar {
|
|
||||||
// width: 6px;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// &::-webkit-scrollbar-thumb {
|
|
||||||
// background: #a855f7;
|
|
||||||
// border-radius: 10px;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// .tree-node {
|
|
||||||
// display: flex;
|
|
||||||
// flex-direction: column;
|
|
||||||
// width: 100%;
|
|
||||||
// outline: 2px solid transparent;
|
|
||||||
// transition: all 0.3s ease;
|
|
||||||
|
|
||||||
// .tree-node-content {
|
|
||||||
// display: flex;
|
|
||||||
// align-items: center;
|
|
||||||
// width: 100%;
|
|
||||||
// padding: 6px 10px;
|
|
||||||
// border-radius: 8px;
|
|
||||||
// background: transparent;
|
|
||||||
// transition: background 0.2s ease, outline 0.2s ease;
|
|
||||||
// box-sizing: border-box;
|
|
||||||
// position: relative;
|
|
||||||
|
|
||||||
// &:hover {
|
|
||||||
// background: rgba(255, 255, 255, 0.05);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// &.selected {
|
|
||||||
// background: var(--background-color-accent, #6f42c1);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// &.multi-selected {
|
|
||||||
// background: rgba(167, 139, 250, 0.2);
|
|
||||||
// border-left: 3px solid var(--highlight-secondary-color, #a855f7);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// .expand-button {
|
|
||||||
// background: none;
|
|
||||||
// border: none;
|
|
||||||
// color: #aaa;
|
|
||||||
// cursor: pointer;
|
|
||||||
// width: 18px;
|
|
||||||
// height: 18px;
|
|
||||||
// flex-shrink: 0;
|
|
||||||
// display: flex;
|
|
||||||
// align-items: center;
|
|
||||||
// justify-content: center;
|
|
||||||
|
|
||||||
// &:hover {
|
|
||||||
// color: #a855f7;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// .node-wrapper {
|
|
||||||
// display: flex;
|
|
||||||
// align-items: center;
|
|
||||||
// flex: 1;
|
|
||||||
// min-width: 0;
|
|
||||||
// gap: 8px;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// .node-icon {
|
|
||||||
// color: #a855f7;
|
|
||||||
// flex-shrink: 0;
|
|
||||||
// width: 16px;
|
|
||||||
// height: 16px;
|
|
||||||
// display: flex;
|
|
||||||
// align-items: center;
|
|
||||||
// justify-content: center;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// .rename-input {
|
|
||||||
// flex: 1;
|
|
||||||
// min-width: 0;
|
|
||||||
// overflow: hidden;
|
|
||||||
// white-space: nowrap;
|
|
||||||
// text-overflow: ellipsis;
|
|
||||||
// font-size: 14px;
|
|
||||||
// color: #fff;
|
|
||||||
|
|
||||||
// input.renaming {
|
|
||||||
// width: 100%;
|
|
||||||
// border: none;
|
|
||||||
// outline: none;
|
|
||||||
// border-radius: 6px;
|
|
||||||
// background: rgba(255, 255, 255, 0.1);
|
|
||||||
// color: #fff;
|
|
||||||
// padding: 3px 6px;
|
|
||||||
// font-size: 14px;
|
|
||||||
// box-sizing: border-box;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// .node-controls {
|
|
||||||
// display: flex;
|
|
||||||
// align-items: center;
|
|
||||||
// gap: 4px;
|
|
||||||
// flex-shrink: 0;
|
|
||||||
|
|
||||||
// .control-button {
|
|
||||||
// background: none;
|
|
||||||
// border: none;
|
|
||||||
// color: #aaa;
|
|
||||||
// cursor: pointer;
|
|
||||||
// border-radius: 4px;
|
|
||||||
// padding: 4px;
|
|
||||||
// display: flex;
|
|
||||||
// align-items: center;
|
|
||||||
// justify-content: center;
|
|
||||||
|
|
||||||
// &:hover {
|
|
||||||
// background: rgba(255, 255, 255, 0.1);
|
|
||||||
// color: #a855f7;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// svg {
|
|
||||||
// width: 14px;
|
|
||||||
// height: 14px;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// .tree-children {
|
|
||||||
// padding-left: 16px;
|
|
||||||
// border-left: 1px dashed rgba(255, 255, 255, 0.1);
|
|
||||||
// margin-left: 6px;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // .tree-node {
|
|
||||||
// // display: flex;
|
|
||||||
// // flex-direction: column;
|
|
||||||
// // outline: 2px solid transparent;
|
|
||||||
// // transition: background 0.3s;
|
|
||||||
|
|
||||||
// // .tree-node-content {
|
|
||||||
// // display: flex;
|
|
||||||
// // align-items: center;
|
|
||||||
// // padding: 8px 9px;
|
|
||||||
// // gap: 6px;
|
|
||||||
// // transition: background 0.2s ease;
|
|
||||||
// // position: relative;
|
|
||||||
// // &.selected {
|
|
||||||
// // background: #6f42c1;
|
|
||||||
// // border-radius: 45px;
|
|
||||||
// // }
|
|
||||||
|
|
||||||
// // &:hover {
|
|
||||||
// // outline: 1px solid pink;
|
|
||||||
// // border-radius: 80px;
|
|
||||||
// // }
|
|
||||||
// // .node-wrapper {
|
|
||||||
// // display: flex;
|
|
||||||
// // gap: 40px;
|
|
||||||
// // }
|
|
||||||
|
|
||||||
// // .expand-button {
|
|
||||||
// // background: none;
|
|
||||||
// // border: none;
|
|
||||||
// // cursor: pointer;
|
|
||||||
// // width: 20px;
|
|
||||||
// // height: 20px;
|
|
||||||
// // padding: 0;
|
|
||||||
// // color: #aaa;
|
|
||||||
|
|
||||||
// // &:hover {
|
|
||||||
// // color: #a855f7;
|
|
||||||
// // }
|
|
||||||
// // }
|
|
||||||
|
|
||||||
// // .node-icon {
|
|
||||||
// // color: white;
|
|
||||||
// // width: 18px;
|
|
||||||
// // flex-shrink: 0;
|
|
||||||
// // }
|
|
||||||
|
|
||||||
// // .rename-input {
|
|
||||||
// // background: transparent;
|
|
||||||
// // border: none;
|
|
||||||
// // color: #fff;
|
|
||||||
// // font-size: 14px;
|
|
||||||
// // flex: 1;
|
|
||||||
// // outline: none;
|
|
||||||
// // padding: 2px 4px;
|
|
||||||
// // &:focus {
|
|
||||||
// // border-bottom: 1px solid #a855f7;
|
|
||||||
// // }
|
|
||||||
// // .renaming {
|
|
||||||
// // outline: none;
|
|
||||||
// // border: none;
|
|
||||||
// // border-radius: 15px;
|
|
||||||
// // height: 20px;
|
|
||||||
// // }
|
|
||||||
// // }
|
|
||||||
|
|
||||||
// // .node-controls {
|
|
||||||
// // display: flex;
|
|
||||||
// // gap: 6px;
|
|
||||||
|
|
||||||
// // .control-button {
|
|
||||||
// // background: none;
|
|
||||||
// // border: none;
|
|
||||||
// // color: #888;
|
|
||||||
// // cursor: pointer;
|
|
||||||
// // // padding: 4px;
|
|
||||||
// // border-radius: 4px;
|
|
||||||
|
|
||||||
// // &:hover {
|
|
||||||
// // background-color: rgba(255, 255, 255, 0.1);
|
|
||||||
// // color: #a855f7;
|
|
||||||
// // }
|
|
||||||
|
|
||||||
// // svg {
|
|
||||||
// // width: 16px;
|
|
||||||
// // height: 16px;
|
|
||||||
// // }
|
|
||||||
// // }
|
|
||||||
// // }
|
|
||||||
// // }
|
|
||||||
// // }
|
|
||||||
|
|
||||||
// // .tree-children {
|
|
||||||
// // padding-left: 16px;
|
|
||||||
// // border-left: 1px dashed rgba(255, 255, 255, 0.05);
|
|
||||||
// // }
|
|
||||||
|
|
||||||
// Outline Component Styles
|
|
||||||
// Professional tree/hierarchy view with drag-and-drop support
|
|
||||||
|
|
||||||
.outline-overlay {
|
.outline-overlay {
|
||||||
padding: 0 4px;
|
padding: 0 4px;
|
||||||
font-family: "Segoe UI", sans-serif;
|
font-family: "Segoe UI", sans-serif;
|
||||||
@@ -434,14 +116,13 @@
|
|||||||
.tree-node-content {
|
.tree-node-content {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 8px 12px;
|
padding: 3px 8px;
|
||||||
|
margin: 2px 2px;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
transition: background 0.2s ease;
|
transition: background 0.2s ease;
|
||||||
position: relative;
|
position: relative;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
margin: 2px 8px;
|
|
||||||
|
|
||||||
&.selected {
|
&.selected {
|
||||||
background: #6f42c1;
|
background: #6f42c1;
|
||||||
border-radius: 50px;
|
border-radius: 50px;
|
||||||
@@ -560,7 +241,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.tree-children {
|
.tree-children {
|
||||||
padding-left: 16px;
|
|
||||||
border-left: 1px dashed rgba(255, 255, 255, 0.05);
|
border-left: 1px dashed rgba(255, 255, 255, 0.05);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user