From 41bf7500de9e4fd8696545ef78edd595a3dc6ebb Mon Sep 17 00:00:00 2001 From: egenerse Date: Sat, 28 Dec 2024 11:02:22 +0100 Subject: [PATCH 01/14] feat: move class svg into svg folder and create sidebar with svg elements --- library/lib/App.tsx | 26 +++-- library/lib/components/Sidebar.tsx | 111 ++++++++++++++++++++ library/lib/components/index.ts | 1 + library/lib/nodes/classDiagram/Class.tsx | 92 +++-------------- library/lib/nodes/index.ts | 1 + library/lib/nodes/types.ts | 8 ++ library/lib/svgs/classDiagram/ClassSVG.tsx | 112 +++++++++++++++++++++ library/lib/svgs/classDiagram/index.ts | 1 + library/lib/svgs/index.ts | 1 + library/lib/types/index.ts | 17 ++++ library/package.json | 3 +- package-lock.json | 16 ++- standalone/webapp/src/LibraryView.tsx | 2 +- 13 files changed, 298 insertions(+), 93 deletions(-) create mode 100644 library/lib/components/Sidebar.tsx create mode 100644 library/lib/nodes/types.ts create mode 100644 library/lib/svgs/classDiagram/ClassSVG.tsx create mode 100644 library/lib/svgs/classDiagram/index.ts create mode 100644 library/lib/svgs/index.ts create mode 100644 library/lib/types/index.ts diff --git a/library/lib/App.tsx b/library/lib/App.tsx index 54f92fb..472d4ff 100644 --- a/library/lib/App.tsx +++ b/library/lib/App.tsx @@ -6,7 +6,6 @@ import { Controls, MiniMap, DefaultEdgeOptions, - type NodeTypes, MarkerType, ConnectionLineType, ConnectionMode, @@ -17,13 +16,8 @@ import "@xyflow/react/dist/style.css" import { MAX_SCALE_TO_ZOOM_IN, MIN_SCALE_TO_ZOOM_OUT } from "./contants" import { defaultEdges, defaultNodes } from "./initialElements" import "@/styles/app.css" -import { Class, Package, ColorDescription } from "./nodes" - -const nodeTypes: NodeTypes = { - package: Package, - class: Class, - colorDescription: ColorDescription, -} +import { nodeTypes } from "./nodes/types" +import { Sidebar } from "./components" const defaultEdgeOptions: DefaultEdgeOptions = { type: "smoothstep", @@ -37,7 +31,19 @@ interface AppProps { function App({ onReactFlowInit }: AppProps) { return ( -
+
+
+ +
- +
) diff --git a/library/lib/components/Sidebar.tsx b/library/lib/components/Sidebar.tsx new file mode 100644 index 0000000..413af61 --- /dev/null +++ b/library/lib/components/Sidebar.tsx @@ -0,0 +1,111 @@ +import { DragEvent } from "react" + +import { v4 as uuidv4 } from "uuid" +import { ClassType, DropNodeData } from "@/types" +import { ClassSVG } from "@/svgs" + +const onDragStart = (event: DragEvent, { type, data }: DropNodeData) => { + event.dataTransfer.setData("text/plain", JSON.stringify({ type, data })) + event.dataTransfer.effectAllowed = "move" +} + +export const Sidebar = () => { + return ( + + ) +} diff --git a/library/lib/components/index.ts b/library/lib/components/index.ts index c15b28f..8f93351 100644 --- a/library/lib/components/index.ts +++ b/library/lib/components/index.ts @@ -1,2 +1,3 @@ export * from "./Text" export * from "./ThemedElements" +export * from "./Sidebar" diff --git a/library/lib/nodes/classDiagram/Class.tsx b/library/lib/nodes/classDiagram/Class.tsx index e9f534a..eb3c0fa 100644 --- a/library/lib/nodes/classDiagram/Class.tsx +++ b/library/lib/nodes/classDiagram/Class.tsx @@ -1,7 +1,7 @@ -import { ThemedRect } from "@/components/ThemedElements" import { NodeProps, type Node } from "@xyflow/react" -import { Text } from "@/components/Text" -import { DefaultNodeWrapper } from "../wrappers" +import { DefaultNodeWrapper } from "@/nodes/wrappers" +import { ClassSVG } from "@/svgs" +import { ClassType } from "@/types" export type ExtraElements = { id: string @@ -11,7 +11,7 @@ export type ExtraElements = { type Props = Node<{ methods: ExtraElements[] attributes: ExtraElements[] - stereotype?: string + stereotype?: ClassType name: string }> @@ -24,84 +24,16 @@ export function Class({ return null } - const headerHeight = 50 - const attributeHeight = 30 - const totalAttributesHeight = attributes.length * attributeHeight - const totalMethodsHeight = methods.length * attributeHeight - - const totalHeight = headerHeight + totalAttributesHeight + totalMethodsHeight return ( - - - {/* Outer Rectangle */} - - - {/* Header Section */} - - - - {stereotype && ( - - {`«${stereotype}»`} - - )} - - {name} - - - - - {/* Attributes Section */} - {attributes.length > 0 && ( - - {/* Single Rect for all attributes */} - - {attributes.map((attribute, index) => ( - - {attribute.name} - - ))} - - )} - - {/* Methods Section */} - {methods.length > 0 && ( - - {/* Single Rect for all methods */} - - {methods.map((method, index) => ( - - {method.name} - - ))} - - )} - - + ) } diff --git a/library/lib/nodes/index.ts b/library/lib/nodes/index.ts index 8feed3a..0a276c8 100644 --- a/library/lib/nodes/index.ts +++ b/library/lib/nodes/index.ts @@ -1 +1,2 @@ export * from "./classDiagram" +export * from "./types" diff --git a/library/lib/nodes/types.ts b/library/lib/nodes/types.ts new file mode 100644 index 0000000..8c4dc8a --- /dev/null +++ b/library/lib/nodes/types.ts @@ -0,0 +1,8 @@ +import { NodeTypes } from "@xyflow/react" +import { Class, ColorDescription, Package } from "./classDiagram" + +export const nodeTypes: NodeTypes = { + package: Package, + class: Class, + colorDescription: ColorDescription, +} diff --git a/library/lib/svgs/classDiagram/ClassSVG.tsx b/library/lib/svgs/classDiagram/ClassSVG.tsx new file mode 100644 index 0000000..02a0e5d --- /dev/null +++ b/library/lib/svgs/classDiagram/ClassSVG.tsx @@ -0,0 +1,112 @@ +import { ThemedRect } from "@/components/ThemedElements" +import { Text } from "@/components/Text" +import { ClassType, ExtraElements } from "@/types" +import { SVGAttributes } from "react" + +type Props = { + width: number + height: number + methods: ExtraElements[] + attributes: ExtraElements[] + stereotype?: ClassType + name: string + svgAttributes?: SVGAttributes +} + +export function ClassSVG({ + width, + height, + methods, + attributes, + stereotype, + name, + svgAttributes, +}: Props) { + if (!width || !height) { + return null + } + + const headerHeight = 50 + const attributeHeight = 30 + const totalAttributesHeight = attributes.length * attributeHeight + const totalMethodsHeight = methods.length * attributeHeight + + const totalHeight = headerHeight + totalAttributesHeight + totalMethodsHeight + return ( + + + {/* Outer Rectangle */} + + + {/* Header Section */} + + + + {stereotype && ( + + {`«${stereotype}»`} + + )} + + {name} + + + + + {/* Attributes Section */} + {attributes.length > 0 && ( + + {/* Single Rect for all attributes */} + + {attributes.map((attribute, index) => ( + + {attribute.name} + + ))} + + )} + + {/* Methods Section */} + {methods.length > 0 && ( + + {/* Single Rect for all methods */} + + {methods.map((method, index) => ( + + {method.name} + + ))} + + )} + + + ) +} diff --git a/library/lib/svgs/classDiagram/index.ts b/library/lib/svgs/classDiagram/index.ts new file mode 100644 index 0000000..2442fbc --- /dev/null +++ b/library/lib/svgs/classDiagram/index.ts @@ -0,0 +1 @@ +export * from "./ClassSVG" diff --git a/library/lib/svgs/index.ts b/library/lib/svgs/index.ts new file mode 100644 index 0000000..8feed3a --- /dev/null +++ b/library/lib/svgs/index.ts @@ -0,0 +1 @@ +export * from "./classDiagram" diff --git a/library/lib/types/index.ts b/library/lib/types/index.ts new file mode 100644 index 0000000..da09baa --- /dev/null +++ b/library/lib/types/index.ts @@ -0,0 +1,17 @@ +import { nodeTypes } from "@/nodes" + +export interface DropNodeData { + type: keyof typeof nodeTypes + data?: Record +} + +export enum ClassType { + Abstract = "Abstract", + Interface = "Interface", + Enumeration = "Enumeration", +} + +export type ExtraElements = { + id: string + name: string +} diff --git a/library/package.json b/library/package.json index b3e0170..f39bb89 100644 --- a/library/package.json +++ b/library/package.json @@ -19,7 +19,8 @@ }, "dependencies": { "@xyflow/react": "12.3.6", - "styled-components": "5.3.11" + "styled-components": "5.3.11", + "uuid": "11.0.3" }, "peerDependencies": { "react": "18.3.1", diff --git a/package-lock.json b/package-lock.json index 2f75e5c..8cabb1a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,7 +28,8 @@ "version": "0.0.1", "dependencies": { "@xyflow/react": "12.3.6", - "styled-components": "5.3.11" + "styled-components": "5.3.11", + "uuid": "^11.0.3" }, "devDependencies": { "@eslint/js": "9.17.0", @@ -7893,6 +7894,19 @@ "node": ">= 0.4.0" } }, + "node_modules/uuid": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.0.3.tgz", + "integrity": "sha512-d0z310fCWv5dJwnX1Y/MncBAqGMKEzlBb1AOf7z9K8ALnd0utBX/msg/fA0+sbyN1ihbMsLhrBlnl1ak7Wa0rg==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/esm/bin/uuid" + } + }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", diff --git a/standalone/webapp/src/LibraryView.tsx b/standalone/webapp/src/LibraryView.tsx index d295d55..ba223be 100644 --- a/standalone/webapp/src/LibraryView.tsx +++ b/standalone/webapp/src/LibraryView.tsx @@ -30,7 +30,7 @@ export function LibraryView() { <> From c1c998959c965391274aff36c5d72a1d8e5f254e Mon Sep 17 00:00:00 2001 From: egenerse Date: Sun, 29 Dec 2024 22:22:51 +0100 Subject: [PATCH 02/14] feat: sidebar styling and reusablity --- library/lib/App.tsx | 13 +-- library/lib/components/Sidebar.tsx | 155 ++++++++++++----------------- 2 files changed, 63 insertions(+), 105 deletions(-) diff --git a/library/lib/App.tsx b/library/lib/App.tsx index 472d4ff..ce8ceb1 100644 --- a/library/lib/App.tsx +++ b/library/lib/App.tsx @@ -32,18 +32,7 @@ interface AppProps { function App({ onReactFlowInit }: AppProps) { return (
-
- -
+ { event.dataTransfer.setData("text/plain", JSON.stringify({ type, data })) event.dataTransfer.effectAllowed = "move" } +// Common configuration for sidebar elements +const sideBarElements = [ + { + name: "Class", + type: "class", + stereotype: undefined, + }, + { + name: "Abstract", + type: "class", + stereotype: ClassType.Abstract, + }, + { + name: "Enumeration", + type: "class", + stereotype: ClassType.Enumeration, + }, + { + name: "Interface", + type: "class", + stereotype: ClassType.Interface, + }, +] + export const Sidebar = () => { return ( - ) diff --git a/library/lib/nodes/classDiagram/ColorDescription.tsx b/library/lib/nodes/classDiagram/ColorDescription.tsx index b975f07..d88b9d9 100644 --- a/library/lib/nodes/classDiagram/ColorDescription.tsx +++ b/library/lib/nodes/classDiagram/ColorDescription.tsx @@ -1,7 +1,6 @@ -import { ThemedPath } from "@/components/ThemedElements" import { NodeProps, type Node } from "@xyflow/react" import { DefaultNodeWrapper } from "../wrappers" -import { Text } from "@/components" +import { ColorDescriptionSVG } from "@/svgs" type Props = Node<{ description: string @@ -18,27 +17,11 @@ export function ColorDescription({ return ( - - - - - {/* */} - {description} - - + ) } diff --git a/library/lib/svgs/classDiagram/ColorDescriptionSVG.tsx b/library/lib/svgs/classDiagram/ColorDescriptionSVG.tsx new file mode 100644 index 0000000..1b52cd6 --- /dev/null +++ b/library/lib/svgs/classDiagram/ColorDescriptionSVG.tsx @@ -0,0 +1,45 @@ +import { ThemedPath } from "@/components/ThemedElements" +import { Text } from "@/components/Text" +import { SVGAttributes } from "react" + +export type ColorDescriptionSVGProps = { + width: number + height: number + description: string + svgAttributes?: SVGAttributes +} + +export function ColorDescriptionSVG({ + width, + height, + description, + svgAttributes, +}: ColorDescriptionSVGProps) { + return ( + + + + + {description} + + + ) +} diff --git a/library/lib/svgs/classDiagram/index.ts b/library/lib/svgs/classDiagram/index.ts index 26a0fe6..93f4aa3 100644 --- a/library/lib/svgs/classDiagram/index.ts +++ b/library/lib/svgs/classDiagram/index.ts @@ -1,2 +1,3 @@ export * from "./ClassSVG" export * from "./PackageSVG" +export * from "./ColorDescriptionSVG" From 5ed8e4720d2fbd2b376ab85acb15a40b08feb851 Mon Sep 17 00:00:00 2001 From: egenerse Date: Tue, 31 Dec 2024 11:49:09 +0100 Subject: [PATCH 07/14] feat: make sidebar width with scalible and handle drag and drop --- library/lib/App.tsx | 4 +- library/lib/components/Divider.tsx | 18 +++ library/lib/components/Sidebar.tsx | 133 +++++------------- library/lib/components/index.ts | 1 + library/lib/constant/index.tsx | 86 +++++++++++ library/lib/hooks/useDragDrop.ts | 22 +-- library/lib/nodes/types.ts | 8 +- library/lib/svgs/classDiagram/ClassSVG.tsx | 9 +- .../svgs/classDiagram/ColorDescriptionSVG.tsx | 8 +- library/lib/svgs/classDiagram/PackageSVG.tsx | 8 +- library/lib/types/index.ts | 4 +- 11 files changed, 184 insertions(+), 117 deletions(-) create mode 100644 library/lib/components/Divider.tsx create mode 100644 library/lib/constant/index.tsx diff --git a/library/lib/App.tsx b/library/lib/App.tsx index 661f30e..cb24f21 100644 --- a/library/lib/App.tsx +++ b/library/lib/App.tsx @@ -21,7 +21,7 @@ import { defaultEdges, defaultNodes } from "./initialElements" import "@/styles/app.css" import { Sidebar } from "@/components" import { useCallback } from "react" -import { nodeTypes } from "./nodes" +import { diagramNodeTypes } from "./nodes" import { useDragDrop } from "./hooks" const defaultEdgeOptions: DefaultEdgeOptions = { @@ -47,7 +47,7 @@ function App({ onReactFlowInit }: AppProps) {
= ({ style }) => { + return ( +
+ ) +} diff --git a/library/lib/components/Sidebar.tsx b/library/lib/components/Sidebar.tsx index 16a3423..6a43a0d 100644 --- a/library/lib/components/Sidebar.tsx +++ b/library/lib/components/Sidebar.tsx @@ -1,41 +1,13 @@ -import { DragEvent } from "react" -import { v4 as uuidv4 } from "uuid" -import { ClassType, DropNodeData } from "@/types" -import { ClassSVG, ColorDescriptionSVG, PackageSVG } from "@/svgs" - -const SideBarElementWidth = 128 -const SideBarElementHeight = 88 -const SideBarElementScale = 0.8 +import React, { DragEvent } from "react" +import { dropElementConfig, transformScale } from "@/constant" +import { Divider } from "./Divider" +import { DropNodeData } from "@/types" const onDragStart = (event: DragEvent, { type, data }: DropNodeData) => { event.dataTransfer.setData("text/plain", JSON.stringify({ type, data })) event.dataTransfer.effectAllowed = "move" } -// Common configuration for sidebar elements -const sideBarElements = [ - { - name: "Class", - type: "class", - stereotype: undefined, - }, - { - name: "Abstract", - type: "class", - stereotype: ClassType.Abstract, - }, - { - name: "Enumeration", - type: "class", - stereotype: ClassType.Enumeration, - }, - { - name: "Interface", - type: "class", - stereotype: ClassType.Interface, - }, -] - export const Sidebar = () => { return ( ) diff --git a/library/lib/components/index.ts b/library/lib/components/index.ts index 8f93351..62e5e6c 100644 --- a/library/lib/components/index.ts +++ b/library/lib/components/index.ts @@ -1,3 +1,4 @@ export * from "./Text" export * from "./ThemedElements" export * from "./Sidebar" +export * from "./Divider" diff --git a/library/lib/constant/index.tsx b/library/lib/constant/index.tsx new file mode 100644 index 0000000..e84373a --- /dev/null +++ b/library/lib/constant/index.tsx @@ -0,0 +1,86 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { ClassSVG, PackageSVG, ColorDescriptionSVG } from "@/svgs" +import { generateUUID } from "@/utils" +import { ClassType } from "@/types" +import { DiagramNodeTypeKeys } from "@/nodes" + +export const transformScale = 0.8 +const droppedElementWidth = 160 +const droppedElementHeight = 110 + +export const dropElementConfig: { + type: DiagramNodeTypeKeys + name: string + width: number + height: number + defaultData: Record + svg: React.FC +}[] = [ + { + type: "package", + name: "Package", + width: droppedElementWidth, + height: droppedElementHeight, + defaultData: { name: "Package" }, + svg: (props) => , + }, + { + type: "class", + name: "Class", + width: droppedElementWidth, + height: droppedElementHeight, + defaultData: { + name: "Class", + methods: [{ id: generateUUID(), name: "+ method()" }], + attributes: [{ id: generateUUID(), name: "+ attribute: Type" }], + }, + svg: (props) => , + }, + { + type: "class", + name: "Abstract", + width: droppedElementWidth, + height: droppedElementHeight, + defaultData: { + name: "Abstract", + stereotype: ClassType.Abstract, + methods: [{ id: generateUUID(), name: "+ method()" }], + attributes: [{ id: generateUUID(), name: "+ attribute: Type" }], + }, + svg: (props) => , + }, + { + type: "class", + name: "Enumeration", + width: droppedElementWidth, + height: droppedElementHeight, + defaultData: { + name: "Enumeration", + stereotype: ClassType.Enumeration, + methods: [{ id: generateUUID(), name: "+ method()" }], + attributes: [{ id: generateUUID(), name: "+ attribute: Type" }], + }, + svg: (props) => , + }, + { + type: "class", + name: "Interface", + width: droppedElementWidth, + height: droppedElementHeight, + defaultData: { + name: "Interface", + stereotype: ClassType.Interface, + methods: [{ id: generateUUID(), name: "+ method()" }], + attributes: [{ id: generateUUID(), name: "+ attribute: Type" }], + }, + svg: (props) => , + }, + { + type: "colorDescription", + name: "Color Description", + width: droppedElementWidth, + height: 48, + defaultData: { description: "Color Description" }, + svg: (props) => , + }, +] diff --git a/library/lib/hooks/useDragDrop.ts b/library/lib/hooks/useDragDrop.ts index 88e5190..6fb9c2e 100644 --- a/library/lib/hooks/useDragDrop.ts +++ b/library/lib/hooks/useDragDrop.ts @@ -1,3 +1,4 @@ +import { dropElementConfig } from "@/constant" import { DropNodeData } from "@/types" import { generateUUID } from "@/utils" import { useReactFlow, type Node } from "@xyflow/react" @@ -9,12 +10,16 @@ export const useDragDrop = () => { const onDrop = useCallback( (event: DragEvent) => { event.preventDefault() - const data = JSON.parse( + const dropData = JSON.parse( event.dataTransfer.getData("text/plain") ) as DropNodeData - // check if the dropped element is valid - if (!data.type) { + const config = dropElementConfig.find( + (config) => config.type === dropData.type + ) + // Validate the dropped element type + if (!config) { + console.warn(`Unknown drop element type: ${dropData.type}`) return } @@ -22,18 +27,19 @@ export const useDragDrop = () => { x: event.clientX, y: event.clientY, }) + const newNode: Node = { - width: 200, - height: 110, + width: config.width, + height: config.height, id: generateUUID(), - type: data.type, + type: dropData.type, position, - data: data.data, + data: { ...config.defaultData, ...dropData.data }, } setNodes((nds) => nds.concat(newNode)) }, - [screenToFlowPosition] + [screenToFlowPosition, setNodes] ) const onDragOver = useCallback((event: DragEvent) => { diff --git a/library/lib/nodes/types.ts b/library/lib/nodes/types.ts index 8c4dc8a..e09622f 100644 --- a/library/lib/nodes/types.ts +++ b/library/lib/nodes/types.ts @@ -1,8 +1,10 @@ -import { NodeTypes } from "@xyflow/react" +import { NodeTypes } from "@xyflow/react" // Explicitly differentiate imported type import { Class, ColorDescription, Package } from "./classDiagram" -export const nodeTypes: NodeTypes = { +export const diagramNodeTypes = { package: Package, class: Class, colorDescription: ColorDescription, -} +} satisfies NodeTypes + +export type DiagramNodeTypeKeys = keyof typeof diagramNodeTypes diff --git a/library/lib/svgs/classDiagram/ClassSVG.tsx b/library/lib/svgs/classDiagram/ClassSVG.tsx index 5c35725..6049b52 100644 --- a/library/lib/svgs/classDiagram/ClassSVG.tsx +++ b/library/lib/svgs/classDiagram/ClassSVG.tsx @@ -10,6 +10,7 @@ export type ClassSVGProps = { attributes: ExtraElements[] stereotype?: ClassType name: string + transformScale?: number svgAttributes?: SVGAttributes } @@ -20,6 +21,7 @@ export function ClassSVG({ attributes, stereotype, name, + transformScale, svgAttributes, }: ClassSVGProps) { const headerHeight = 50 @@ -32,7 +34,12 @@ export function ClassSVG({ diff --git a/library/lib/svgs/classDiagram/ColorDescriptionSVG.tsx b/library/lib/svgs/classDiagram/ColorDescriptionSVG.tsx index 1b52cd6..fb1d7bc 100644 --- a/library/lib/svgs/classDiagram/ColorDescriptionSVG.tsx +++ b/library/lib/svgs/classDiagram/ColorDescriptionSVG.tsx @@ -6,6 +6,7 @@ export type ColorDescriptionSVGProps = { width: number height: number description: string + transformScale?: number svgAttributes?: SVGAttributes } @@ -14,12 +15,17 @@ export function ColorDescriptionSVG({ height, description, svgAttributes, + transformScale, }: ColorDescriptionSVGProps) { return ( diff --git a/library/lib/svgs/classDiagram/PackageSVG.tsx b/library/lib/svgs/classDiagram/PackageSVG.tsx index caeb241..5408b27 100644 --- a/library/lib/svgs/classDiagram/PackageSVG.tsx +++ b/library/lib/svgs/classDiagram/PackageSVG.tsx @@ -5,6 +5,7 @@ export type PackageSVGProps = { width: number height: number name: string + transformScale?: number svgAttributes?: SVGAttributes } @@ -13,12 +14,17 @@ export const PackageSVG = ({ height, name, svgAttributes, + transformScale, }: PackageSVGProps) => { return ( diff --git a/library/lib/types/index.ts b/library/lib/types/index.ts index 2bbccba..caff77a 100644 --- a/library/lib/types/index.ts +++ b/library/lib/types/index.ts @@ -1,7 +1,7 @@ -import { nodeTypes } from "@/nodes" +import { DiagramNodeTypeKeys } from "@/nodes" export interface DropNodeData { - type: keyof typeof nodeTypes + type: DiagramNodeTypeKeys data: Record } From 893d678c86c1dc9cea513d11191c0214f26fe432 Mon Sep 17 00:00:00 2001 From: egenerse Date: Sun, 5 Jan 2025 09:57:03 +0100 Subject: [PATCH 08/14] feat: title desctiption svg is added for testing --- library/lib/constant/index.tsx | 1 + library/lib/initialElements.ts | 13 +++ library/lib/nodes/TitleAndDescriptionNode.tsx | 31 ++++++ library/lib/nodes/classDiagram/Class.tsx | 7 +- library/lib/nodes/index.ts | 1 + library/lib/nodes/types.ts | 2 + .../SvgWithTitleAndDescription.tsx | 101 ++++++++++++++++++ library/lib/svgs/classDiagram/index.ts | 1 + 8 files changed, 151 insertions(+), 6 deletions(-) create mode 100644 library/lib/nodes/TitleAndDescriptionNode.tsx create mode 100644 library/lib/svgs/classDiagram/SvgWithTitleAndDescription.tsx diff --git a/library/lib/constant/index.tsx b/library/lib/constant/index.tsx index e84373a..ad59845 100644 --- a/library/lib/constant/index.tsx +++ b/library/lib/constant/index.tsx @@ -33,6 +33,7 @@ export const dropElementConfig: { name: "Class", methods: [{ id: generateUUID(), name: "+ method()" }], attributes: [{ id: generateUUID(), name: "+ attribute: Type" }], + // strokeWidth: 1, }, svg: (props) => , }, diff --git a/library/lib/initialElements.ts b/library/lib/initialElements.ts index ca29ad2..c1f696e 100644 --- a/library/lib/initialElements.ts +++ b/library/lib/initialElements.ts @@ -100,6 +100,19 @@ export const defaultNodes: Node[] = [ description: "Color description", }, }, + { + id: "7", + type: "titleAndDesctiption", + position: { x: -100, y: 100 }, + width: 160, + height: 50, + selected: false, + data: { + title: "Title", + description: + "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.", + }, + }, ] export const defaultEdges: Edge[] = [ diff --git a/library/lib/nodes/TitleAndDescriptionNode.tsx b/library/lib/nodes/TitleAndDescriptionNode.tsx new file mode 100644 index 0000000..73623b2 --- /dev/null +++ b/library/lib/nodes/TitleAndDescriptionNode.tsx @@ -0,0 +1,31 @@ +import { NodeProps, NodeResizer, type Node } from "@xyflow/react" +import { DefaultNodeWrapper } from "@/nodes/wrappers" +import { SvgWithTitleAndDescription } from "@/svgs" + +type Props = Node<{ + description?: string + title: string +}> + +export function TitleAndDesctiption({ + selected, + width, + height, + data: { description, title }, +}: NodeProps) { + if (!width || !height) { + return null + } + + return ( + + + + + ) +} diff --git a/library/lib/nodes/classDiagram/Class.tsx b/library/lib/nodes/classDiagram/Class.tsx index eb3c0fa..dfb172d 100644 --- a/library/lib/nodes/classDiagram/Class.tsx +++ b/library/lib/nodes/classDiagram/Class.tsx @@ -1,12 +1,7 @@ import { NodeProps, type Node } from "@xyflow/react" import { DefaultNodeWrapper } from "@/nodes/wrappers" import { ClassSVG } from "@/svgs" -import { ClassType } from "@/types" - -export type ExtraElements = { - id: string - name: string -} +import { ClassType, ExtraElements } from "@/types" type Props = Node<{ methods: ExtraElements[] diff --git a/library/lib/nodes/index.ts b/library/lib/nodes/index.ts index 0a276c8..2c21305 100644 --- a/library/lib/nodes/index.ts +++ b/library/lib/nodes/index.ts @@ -1,2 +1,3 @@ export * from "./classDiagram" export * from "./types" +export * from "./TitleAndDescriptionNode" diff --git a/library/lib/nodes/types.ts b/library/lib/nodes/types.ts index e09622f..fd3480d 100644 --- a/library/lib/nodes/types.ts +++ b/library/lib/nodes/types.ts @@ -1,10 +1,12 @@ import { NodeTypes } from "@xyflow/react" // Explicitly differentiate imported type import { Class, ColorDescription, Package } from "./classDiagram" +import { TitleAndDesctiption } from "./TitleAndDescriptionNode" export const diagramNodeTypes = { package: Package, class: Class, colorDescription: ColorDescription, + titleAndDesctiption: TitleAndDesctiption, } satisfies NodeTypes export type DiagramNodeTypeKeys = keyof typeof diagramNodeTypes diff --git a/library/lib/svgs/classDiagram/SvgWithTitleAndDescription.tsx b/library/lib/svgs/classDiagram/SvgWithTitleAndDescription.tsx new file mode 100644 index 0000000..78171db --- /dev/null +++ b/library/lib/svgs/classDiagram/SvgWithTitleAndDescription.tsx @@ -0,0 +1,101 @@ +import React, { useMemo, useCallback } from "react" + +interface SvgWithTitleAndDescriptionProps { + width: number + height: number + title: string + description: string +} + +export const SvgWithTitleAndDescription: React.FC< + SvgWithTitleAndDescriptionProps +> = ({ width, height, title, description }) => { + const padding = 10 // Padding inside the SVG + const titleHeight = 30 // Fixed height for the title + const separatorHeight = 1 // Height of the separator line + const descriptionStartY = padding + titleHeight + separatorHeight + 10 // Space for description + + // Memoized wrapText function + const wrapText = useCallback((text: string, maxWidth: number): string[] => { + const words = text.split(" ") + const lines: string[] = [] + let currentLine = "" + + words.forEach((word) => { + const testLine = currentLine ? `${currentLine} ${word}` : word + const lineWidth = testLine.length * 7 // Approximation for font size 14px + if (lineWidth < maxWidth) { + currentLine = testLine + } else { + lines.push(currentLine) + currentLine = word + } + }) + + if (currentLine) { + lines.push(currentLine) + } + + return lines + }, []) + + const maxTextWidth = width - 2 * padding + + // Memoized description lines calculation + const descriptionLines = useMemo( + () => wrapText(description, maxTextWidth), + [description, maxTextWidth, wrapText] + ) + + return ( + + {/* Outer Border */} + + + {/* Title */} + + {title} + + + {/* Separator Line */} + + + {/* Description */} + {descriptionLines.map((line, index) => ( + + {line} + + ))} + + ) +} diff --git a/library/lib/svgs/classDiagram/index.ts b/library/lib/svgs/classDiagram/index.ts index 93f4aa3..8e9453f 100644 --- a/library/lib/svgs/classDiagram/index.ts +++ b/library/lib/svgs/classDiagram/index.ts @@ -1,3 +1,4 @@ export * from "./ClassSVG" export * from "./PackageSVG" export * from "./ColorDescriptionSVG" +export * from "./SvgWithTitleAndDescription" From bcb8e2ae734f1503672d0cf1f37d582a710f4e83 Mon Sep 17 00:00:00 2001 From: egenerse Date: Sun, 5 Jan 2025 10:01:34 +0100 Subject: [PATCH 09/14] feat: adding testing title and description node with min height resizer --- library/lib/App.tsx | 6 ++-- library/lib/initialElements.ts | 32 ++++++++++--------- library/lib/nodes/TitleAndDescriptionNode.tsx | 2 +- .../SvgWithTitleAndDescription.tsx | 21 +++++++++--- 4 files changed, 37 insertions(+), 24 deletions(-) diff --git a/library/lib/App.tsx b/library/lib/App.tsx index cb24f21..ade789b 100644 --- a/library/lib/App.tsx +++ b/library/lib/App.tsx @@ -17,7 +17,7 @@ import { } from "@xyflow/react" import "@xyflow/react/dist/style.css" import { MAX_SCALE_TO_ZOOM_IN, MIN_SCALE_TO_ZOOM_OUT } from "./contants" -import { defaultEdges, defaultNodes } from "./initialElements" +import { initialEdges, initialNodes } from "./initialElements" import "@/styles/app.css" import { Sidebar } from "@/components" import { useCallback } from "react" @@ -35,8 +35,8 @@ interface AppProps { } function App({ onReactFlowInit }: AppProps) { - const [nodes, , onNodesChange] = useNodesState(defaultNodes) - const [edges, setEdges, onEdgesChange] = useEdgesState(defaultEdges) + const [nodes, , onNodesChange] = useNodesState(initialNodes) + const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges) const { onDrop, onDragOver } = useDragDrop() const onConnect = useCallback( (params: Connection) => setEdges((eds) => addEdge(params, eds)), diff --git a/library/lib/initialElements.ts b/library/lib/initialElements.ts index c1f696e..41a2199 100644 --- a/library/lib/initialElements.ts +++ b/library/lib/initialElements.ts @@ -1,6 +1,6 @@ import { type Edge, type Node } from "@xyflow/react" -export const defaultNodes: Node[] = [ +export const initialNodes: Node[] = [ { id: "1", type: "package", @@ -100,22 +100,24 @@ export const defaultNodes: Node[] = [ description: "Color description", }, }, - { - id: "7", - type: "titleAndDesctiption", - position: { x: -100, y: 100 }, - width: 160, - height: 50, - selected: false, - data: { - title: "Title", - description: - "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.", - }, - }, + + // Testing TitleAndDescription + // { + // id: "99", + // type: "titleAndDesctiption", + // position: { x: -100, y: 100 }, + // width: 160, + // height: 200, + // selected: false, + // data: { + // title: "Title", + // description: + // "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.", + // }, + // }, ] -export const defaultEdges: Edge[] = [ +export const initialEdges: Edge[] = [ { id: "1->2", source: "1", diff --git a/library/lib/nodes/TitleAndDescriptionNode.tsx b/library/lib/nodes/TitleAndDescriptionNode.tsx index 73623b2..214e9ce 100644 --- a/library/lib/nodes/TitleAndDescriptionNode.tsx +++ b/library/lib/nodes/TitleAndDescriptionNode.tsx @@ -25,7 +25,7 @@ export function TitleAndDesctiption({ title={title} description={description || ""} /> - + ) } diff --git a/library/lib/svgs/classDiagram/SvgWithTitleAndDescription.tsx b/library/lib/svgs/classDiagram/SvgWithTitleAndDescription.tsx index 78171db..5d15aab 100644 --- a/library/lib/svgs/classDiagram/SvgWithTitleAndDescription.tsx +++ b/library/lib/svgs/classDiagram/SvgWithTitleAndDescription.tsx @@ -13,7 +13,9 @@ export const SvgWithTitleAndDescription: React.FC< const padding = 10 // Padding inside the SVG const titleHeight = 30 // Fixed height for the title const separatorHeight = 1 // Height of the separator line + const lineHeight = 18 // Line height for description const descriptionStartY = padding + titleHeight + separatorHeight + 10 // Space for description + const maxDescriptionHeight = height - descriptionStartY - padding // Max height for description // Memoized wrapText function const wrapText = useCallback((text: string, maxWidth: number): string[] => { @@ -42,10 +44,19 @@ export const SvgWithTitleAndDescription: React.FC< const maxTextWidth = width - 2 * padding // Memoized description lines calculation - const descriptionLines = useMemo( - () => wrapText(description, maxTextWidth), - [description, maxTextWidth, wrapText] - ) + const descriptionLines = useMemo(() => { + const wrappedLines = wrapText(description, maxTextWidth) + const maxLines = Math.floor(maxDescriptionHeight / lineHeight) + + if (wrappedLines.length > maxLines) { + const truncatedLines = wrappedLines.slice(0, maxLines) + // Add ellipsis to the last line if the text is truncated + truncatedLines[truncatedLines.length - 1] += " ..." + return truncatedLines + } + + return wrappedLines + }, [description, maxTextWidth, maxDescriptionHeight, lineHeight, wrapText]) return ( @@ -88,7 +99,7 @@ export const SvgWithTitleAndDescription: React.FC< Date: Sun, 5 Jan 2025 10:03:07 +0100 Subject: [PATCH 10/14] chore: rename title and description svg --- library/lib/nodes/TitleAndDescriptionNode.tsx | 4 ++-- ...eAndDescription.tsx => TitleAndDescriptionSVG.tsx} | 11 +++++++---- library/lib/svgs/classDiagram/index.ts | 2 +- 3 files changed, 10 insertions(+), 7 deletions(-) rename library/lib/svgs/classDiagram/{SvgWithTitleAndDescription.tsx => TitleAndDescriptionSVG.tsx} (94%) diff --git a/library/lib/nodes/TitleAndDescriptionNode.tsx b/library/lib/nodes/TitleAndDescriptionNode.tsx index 214e9ce..6ed0f4b 100644 --- a/library/lib/nodes/TitleAndDescriptionNode.tsx +++ b/library/lib/nodes/TitleAndDescriptionNode.tsx @@ -1,6 +1,6 @@ import { NodeProps, NodeResizer, type Node } from "@xyflow/react" import { DefaultNodeWrapper } from "@/nodes/wrappers" -import { SvgWithTitleAndDescription } from "@/svgs" +import { TitleAndDescriptionSVG } from "@/svgs" type Props = Node<{ description?: string @@ -19,7 +19,7 @@ export function TitleAndDesctiption({ return ( - = ({ width, height, title, description }) => { +export const TitleAndDescriptionSVG: React.FC = ({ + width, + height, + title, + description, +}) => { const padding = 10 // Padding inside the SVG const titleHeight = 30 // Fixed height for the title const separatorHeight = 1 // Height of the separator line diff --git a/library/lib/svgs/classDiagram/index.ts b/library/lib/svgs/classDiagram/index.ts index 8e9453f..ac72120 100644 --- a/library/lib/svgs/classDiagram/index.ts +++ b/library/lib/svgs/classDiagram/index.ts @@ -1,4 +1,4 @@ export * from "./ClassSVG" export * from "./PackageSVG" export * from "./ColorDescriptionSVG" -export * from "./SvgWithTitleAndDescription" +export * from "./TitleAndDescriptionSVG" From fed785116d194dbe3445f2b1e26f98b5f92e4361 Mon Sep 17 00:00:00 2001 From: egenerse Date: Sun, 5 Jan 2025 10:17:24 +0100 Subject: [PATCH 11/14] fix: class svg border line fix --- library/lib/svgs/classDiagram/ClassSVG.tsx | 100 ++++++++++++++++----- 1 file changed, 76 insertions(+), 24 deletions(-) diff --git a/library/lib/svgs/classDiagram/ClassSVG.tsx b/library/lib/svgs/classDiagram/ClassSVG.tsx index 6049b52..6787f76 100644 --- a/library/lib/svgs/classDiagram/ClassSVG.tsx +++ b/library/lib/svgs/classDiagram/ClassSVG.tsx @@ -1,7 +1,7 @@ import { ThemedRect } from "@/components/ThemedElements" import { Text } from "@/components/Text" import { ClassType, ExtraElements } from "@/types" -import { SVGAttributes } from "react" +import { SVGAttributes, useMemo } from "react" export type ClassSVGProps = { width: number @@ -26,14 +26,51 @@ export function ClassSVG({ }: ClassSVGProps) { const headerHeight = 50 const attributeHeight = 30 - const totalAttributesHeight = attributes.length * attributeHeight - const totalMethodsHeight = methods.length * attributeHeight + const methodHeight = 30 + + const padding = 10 // Padding inside the SVG + const maxTextWidth = width - 2 * padding // Maximum width for text + + // Helper function to truncate individual lines + const truncateText = (text: string, maxWidth: number): string => { + const approxCharWidth = 7 // Approximation for character width in font size 14px + const maxChars = Math.floor(maxWidth / approxCharWidth) + + if (text.length > maxChars) { + return `${text.slice(0, maxChars - 3)}...` // Truncate and add ellipsis + } + return text + } + + // Memoized truncated attributes + const truncatedAttributes = useMemo( + () => + attributes.map((attribute) => ({ + ...attribute, + truncatedName: truncateText(attribute.name, maxTextWidth), + })), + [attributes, maxTextWidth] + ) + + // Memoized truncated methods + const truncatedMethods = useMemo( + () => + methods.map((method) => ({ + ...method, + truncatedName: truncateText(method.name, maxTextWidth), + })), + [methods, maxTextWidth] + ) + + const totalHeight = + headerHeight + + truncatedAttributes.length * attributeHeight + + truncatedMethods.length * methodHeight - const totalHeight = headerHeight + totalAttributesHeight + totalMethodsHeight return ( {/* Header Section */} - {stereotype && ( @@ -66,16 +102,20 @@ export function ClassSVG({ + {/* Separation Line After Header */} + + {/* Attributes Section */} - {attributes.length > 0 && ( + {truncatedAttributes.length > 0 && ( - {/* Single Rect for all attributes */} - - {attributes.map((attribute, index) => ( + {truncatedAttributes.map((attribute, index) => ( - {attribute.name} + {attribute.truncatedName} ))} )} + {/* Separation Line After Attributes */} + {truncatedAttributes.length > 0 && ( + + )} + {/* Methods Section */} - {methods.length > 0 && ( + {truncatedMethods.length > 0 && ( - {/* Single Rect for all methods */} - - {methods.map((method, index) => ( + {truncatedMethods.map((method, index) => ( - {method.name} + {method.truncatedName} ))} From 57c9e8c40e3a742f65bde73d2116ee2d252599b5 Mon Sep 17 00:00:00 2001 From: egenerse Date: Sun, 5 Jan 2025 10:21:47 +0100 Subject: [PATCH 12/14] fix: package svg border fix with padding --- library/lib/svgs/classDiagram/PackageSVG.tsx | 39 +++++++++++++++++--- 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/library/lib/svgs/classDiagram/PackageSVG.tsx b/library/lib/svgs/classDiagram/PackageSVG.tsx index 5408b27..41444a7 100644 --- a/library/lib/svgs/classDiagram/PackageSVG.tsx +++ b/library/lib/svgs/classDiagram/PackageSVG.tsx @@ -16,10 +16,15 @@ export const PackageSVG = ({ svgAttributes, transformScale, }: PackageSVGProps) => { + const padding = 5 // Padding inside the SVG content + const headerHeight = 10 // Height of the top path + const innerWidth = width - 2 * padding // Adjusted content width + const innerHeight = height - 2 * padding // Adjusted content height + return ( - - - - + + {/* Top Path */} + + {/* Main Rectangle */} + + {/* Name Text */} + {name} From 82959ed97e0b171a43c376b5838f9c61eb407e54 Mon Sep 17 00:00:00 2001 From: egenerse Date: Sun, 5 Jan 2025 10:33:02 +0100 Subject: [PATCH 13/14] fix: drag and drop offset --- library/lib/components/Sidebar.tsx | 12 +++++++++++- library/lib/hooks/useDragDrop.ts | 10 ++++++++-- library/lib/types/index.ts | 2 ++ 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/library/lib/components/Sidebar.tsx b/library/lib/components/Sidebar.tsx index 6a43a0d..02852e7 100644 --- a/library/lib/components/Sidebar.tsx +++ b/library/lib/components/Sidebar.tsx @@ -4,7 +4,15 @@ import { Divider } from "./Divider" import { DropNodeData } from "@/types" const onDragStart = (event: DragEvent, { type, data }: DropNodeData) => { - event.dataTransfer.setData("text/plain", JSON.stringify({ type, data })) + const rect = (event.target as HTMLElement).getBoundingClientRect() + const offsetX = (event.clientX - rect.left) / transformScale // Cursor offset from the element's left + const offsetY = (event.clientY - rect.top) / transformScale // Cursor offset from the element's top + + // Pass the offset along with the type and data + event.dataTransfer.setData( + "text/plain", + JSON.stringify({ type, data, offsetX, offsetY }) + ) event.dataTransfer.effectAllowed = "move" } @@ -37,6 +45,8 @@ export const Sidebar = () => { onDragStart(event, { type: config.type, data: config.defaultData, + offsetX: 0, + offsetY: 0, }) } > diff --git a/library/lib/hooks/useDragDrop.ts b/library/lib/hooks/useDragDrop.ts index 6fb9c2e..a0cda5d 100644 --- a/library/lib/hooks/useDragDrop.ts +++ b/library/lib/hooks/useDragDrop.ts @@ -22,12 +22,18 @@ export const useDragDrop = () => { console.warn(`Unknown drop element type: ${dropData.type}`) return } - - const position = screenToFlowPosition({ + // Convert the drop position to the flow position + const dropPosition = screenToFlowPosition({ x: event.clientX, y: event.clientY, }) + // Adjust position by subtracting the offset + const position = { + x: dropPosition.x - dropData.offsetX, + y: dropPosition.y - dropData.offsetY, + } + const newNode: Node = { width: config.width, height: config.height, diff --git a/library/lib/types/index.ts b/library/lib/types/index.ts index caff77a..10e2ead 100644 --- a/library/lib/types/index.ts +++ b/library/lib/types/index.ts @@ -3,6 +3,8 @@ import { DiagramNodeTypeKeys } from "@/nodes" export interface DropNodeData { type: DiagramNodeTypeKeys data: Record + offsetX: number + offsetY: number } export enum ClassType { From 69975f8c563749f1e147bf7fd0ce60da8b3bfe3f Mon Sep 17 00:00:00 2001 From: egenerse Date: Sun, 5 Jan 2025 12:15:47 +0100 Subject: [PATCH 14/14] fix: add margin and use inner heights in svgs --- library/lib/svgs/classDiagram/ClassSVG.tsx | 58 ++++++++++--------- .../svgs/classDiagram/ColorDescriptionSVG.tsx | 32 +++++++--- library/lib/svgs/classDiagram/PackageSVG.tsx | 9 +-- 3 files changed, 59 insertions(+), 40 deletions(-) diff --git a/library/lib/svgs/classDiagram/ClassSVG.tsx b/library/lib/svgs/classDiagram/ClassSVG.tsx index 6787f76..32b12b1 100644 --- a/library/lib/svgs/classDiagram/ClassSVG.tsx +++ b/library/lib/svgs/classDiagram/ClassSVG.tsx @@ -24,25 +24,20 @@ export function ClassSVG({ transformScale, svgAttributes, }: ClassSVGProps) { - const headerHeight = 50 - const attributeHeight = 30 - const methodHeight = 30 + const margin = 2 // Padding inside the SVG content + const headerHeight = 50 // Height of the header section + const attributeHeight = 30 // Height per attribute + const methodHeight = 30 // Height per method + const innerWidth = width - 2 * margin // Adjusted content width + const padding = 10 // Inner padding for text + const maxTextWidth = innerWidth - 2 * padding // Maximum width for text - const padding = 10 // Padding inside the SVG - const maxTextWidth = width - 2 * padding // Maximum width for text - - // Helper function to truncate individual lines const truncateText = (text: string, maxWidth: number): string => { - const approxCharWidth = 7 // Approximation for character width in font size 14px + const approxCharWidth = 7 // Approximate width of a character in font size 14px const maxChars = Math.floor(maxWidth / approxCharWidth) - - if (text.length > maxChars) { - return `${text.slice(0, maxChars - 3)}...` // Truncate and add ellipsis - } - return text + return text.length > maxChars ? `${text.slice(0, maxChars - 3)}...` : text } - // Memoized truncated attributes const truncatedAttributes = useMemo( () => attributes.map((attribute) => ({ @@ -52,7 +47,6 @@ export function ClassSVG({ [attributes, maxTextWidth] ) - // Memoized truncated methods const truncatedMethods = useMemo( () => methods.map((method) => ({ @@ -71,32 +65,42 @@ export function ClassSVG({ - + {/* Outer Rectangle */} {/* Header Section */} - + {stereotype && ( - + {`«${stereotype}»`} )} - + {name} @@ -105,7 +109,7 @@ export function ClassSVG({ {/* Separation Line After Header */} ( 0 && ( ( - + + {/* Main Path */} + {/* Small Path for Top-Right Corner */} - {description} + {/* Description Text */} + + {description} + ) diff --git a/library/lib/svgs/classDiagram/PackageSVG.tsx b/library/lib/svgs/classDiagram/PackageSVG.tsx index 41444a7..6a7b933 100644 --- a/library/lib/svgs/classDiagram/PackageSVG.tsx +++ b/library/lib/svgs/classDiagram/PackageSVG.tsx @@ -16,10 +16,11 @@ export const PackageSVG = ({ svgAttributes, transformScale, }: PackageSVGProps) => { - const padding = 5 // Padding inside the SVG content + const margin = 2 // Padding inside the SVG content const headerHeight = 10 // Height of the top path - const innerWidth = width - 2 * padding // Adjusted content width - const innerHeight = height - 2 * padding // Adjusted content height + const innerWidth = width - 2 * margin // Adjusted content width + const innerHeight = height - 2 * margin // Adjusted content height + const padding = 5 return ( - + {/* Top Path */}