@likec4/diagram 1.5.0 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/dist/LikeC4Diagram.d.ts +1 -1
- package/dist/LikeC4Diagram.props.d.ts +18 -3
- package/dist/StaticLikeC4Diagram.d.ts +1 -1
- package/dist/index.mjs +3097 -3090
- package/dist/state/DiagramContext.d.ts +18 -9
- package/dist/state/diagramStore.d.ts +12 -2
- package/dist/style.css +149 -85
- package/dist/xyflow/nodes/element/ElementShapeSvg.d.ts +5 -0
- package/dist/xyflow/nodes/element/element.css.d.ts +4 -2
- package/package.json +13 -13
- package/src/LikeC4Diagram.props.ts +21 -3
- package/src/LikeC4Diagram.tsx +4 -1
- package/src/StaticLikeC4Diagram.tsx +1 -0
- package/src/state/DiagramContext.tsx +1 -1
- package/src/state/diagramStore.ts +8 -1
- package/src/ui/BackwardForwardPanel.tsx +1 -1
- package/src/xyflow/FitviewOnDiagramChange.tsx +1 -1
- package/src/xyflow/SelectEdgesOnNodeFocus.tsx +1 -1
- package/src/xyflow/SyncWithDiagram.tsx +1 -1
- package/src/xyflow/XYFlow.tsx +2 -1
- package/src/xyflow/XYFlowEvents.tsx +1 -1
- package/src/xyflow/XYFlowInner.tsx +1 -1
- package/src/xyflow/edges/RelationshipEdge.tsx +3 -3
- package/src/xyflow/edges/edges.css.ts +6 -6
- package/src/xyflow/hooks/useLayoutConstraints.ts +1 -1
- package/src/xyflow/nodes/compound/CompoundNode.tsx +1 -1
- package/src/xyflow/nodes/element/ElementLink.tsx +2 -1
- package/src/xyflow/nodes/element/ElementNode.tsx +70 -22
- package/src/xyflow/nodes/element/ElementShapeSvg.tsx +2 -2
- package/src/xyflow/nodes/element/element.css.ts +126 -54
- package/src/xyflow/nodes/shared/NavigateToBtn.tsx +1 -1
- package/dist/xyflow/nodes/element/ElementIcon.d.ts +0 -7
- package/src/xyflow/nodes/element/ElementIcon.tsx +0 -33
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@likec4/diagram",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"bugs": "https://github.com/likec4/likec4/issues",
|
|
6
6
|
"homepage": "https://likec4.dev",
|
|
@@ -48,31 +48,31 @@
|
|
|
48
48
|
"clean": "run -T rimraf -v -g 'dist/*' .tsbuildinfo"
|
|
49
49
|
},
|
|
50
50
|
"dependencies": {
|
|
51
|
-
"@likec4/core": "1.
|
|
51
|
+
"@likec4/core": "1.6.0",
|
|
52
52
|
"@react-hookz/web": "^24.0.4",
|
|
53
|
-
"@tabler/icons-react": "^3.
|
|
53
|
+
"@tabler/icons-react": "^3.11.0",
|
|
54
54
|
"@vanilla-extract/css": "^1.15.3",
|
|
55
55
|
"@vanilla-extract/css-utils": "^0.1.4",
|
|
56
56
|
"@vanilla-extract/dynamic": "^2.1.1",
|
|
57
57
|
"d3-shape": "^3.2.0",
|
|
58
58
|
"esm-env": "^1.0.0",
|
|
59
59
|
"fast-equals": "^5.0.1",
|
|
60
|
-
"framer-motion": "^11.
|
|
60
|
+
"framer-motion": "^11.3.8",
|
|
61
61
|
"remeda": "^2.3.0",
|
|
62
62
|
"zustand": "^4.5.4"
|
|
63
63
|
},
|
|
64
64
|
"peerDependencies": {
|
|
65
|
-
"@mantine/core": "^7.11.
|
|
66
|
-
"@mantine/hooks": "^7.11.
|
|
65
|
+
"@mantine/core": "^7.11.2",
|
|
66
|
+
"@mantine/hooks": "^7.11.2",
|
|
67
67
|
"react": "^18.3.1",
|
|
68
68
|
"react-dom": "^18.3.1"
|
|
69
69
|
},
|
|
70
70
|
"devDependencies": {
|
|
71
|
-
"@likec4/tsconfig": "1.
|
|
71
|
+
"@likec4/tsconfig": "1.6.0",
|
|
72
72
|
"@lume/kiwi": "^0.4.3",
|
|
73
|
-
"@mantine/core": "7.11.
|
|
74
|
-
"@mantine/hooks": "7.11.
|
|
75
|
-
"@mantine/vanilla-extract": "7.11.
|
|
73
|
+
"@mantine/core": "7.11.2",
|
|
74
|
+
"@mantine/hooks": "7.11.2",
|
|
75
|
+
"@mantine/vanilla-extract": "7.11.2",
|
|
76
76
|
"@total-typescript/ts-reset": "^0.5.1",
|
|
77
77
|
"@types/bezier-js": "^4.1.3",
|
|
78
78
|
"@types/d3-shape": "^3.1.6",
|
|
@@ -80,8 +80,8 @@
|
|
|
80
80
|
"@types/react-dom": "^18.3.0",
|
|
81
81
|
"@vanilla-extract/esbuild-plugin": "^2.3.8",
|
|
82
82
|
"@vitejs/plugin-react": "^4.3.1",
|
|
83
|
-
"@xyflow/react": "12.0.
|
|
84
|
-
"@xyflow/system": "0.0.
|
|
83
|
+
"@xyflow/react": "12.0.3",
|
|
84
|
+
"@xyflow/system": "0.0.37",
|
|
85
85
|
"bezier-js": "^6.1.4",
|
|
86
86
|
"clsx": "^2.1.1",
|
|
87
87
|
"execa": "^9.3.0",
|
|
@@ -91,7 +91,7 @@
|
|
|
91
91
|
"tilg": "^0.1.1",
|
|
92
92
|
"type-fest": "^4.21.0",
|
|
93
93
|
"typescript": "^5.5.3",
|
|
94
|
-
"vite": "5.3.
|
|
94
|
+
"vite": "5.3.4",
|
|
95
95
|
"vite-plugin-dts": "^3.9.1"
|
|
96
96
|
}
|
|
97
97
|
}
|
|
@@ -6,17 +6,29 @@ import type {
|
|
|
6
6
|
EdgeId,
|
|
7
7
|
ElementShape,
|
|
8
8
|
Fqn,
|
|
9
|
+
IconUrl,
|
|
9
10
|
NonEmptyArray,
|
|
10
11
|
ThemeColor,
|
|
11
12
|
ViewID
|
|
12
13
|
} from '@likec4/core'
|
|
13
14
|
import type { XYPosition } from '@xyflow/system'
|
|
14
|
-
import type { MouseEvent as ReactMouseEvent } from 'react'
|
|
15
|
-
import type { SetRequired, Simplify } from 'type-fest'
|
|
15
|
+
import type { MouseEvent as ReactMouseEvent, ReactNode } from 'react'
|
|
16
16
|
import type { XYFlowEdge, XYFlowNode } from './xyflow/types'
|
|
17
17
|
import type { XYBackground } from './xyflow/XYFlowBackground'
|
|
18
18
|
|
|
19
|
-
export type DiagramNodeWithNavigate =
|
|
19
|
+
export type DiagramNodeWithNavigate = Omit<DiagramNode, 'navigateTo'> & {
|
|
20
|
+
navigateTo: ViewID
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
type ElementIconNodeProps = {
|
|
24
|
+
id: string
|
|
25
|
+
title: string
|
|
26
|
+
icon?: string | undefined
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export type ElementIconRenderer = (props: {
|
|
30
|
+
node: ElementIconNodeProps
|
|
31
|
+
}) => ReactNode
|
|
20
32
|
|
|
21
33
|
export type OnNavigateTo = {
|
|
22
34
|
(
|
|
@@ -177,6 +189,12 @@ export interface LikeC4DiagramProperties {
|
|
|
177
189
|
* @default false
|
|
178
190
|
*/
|
|
179
191
|
experimentalEdgeEditing?: boolean | undefined
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Render custom icon for a node
|
|
195
|
+
* By default, if icon is http:// or https://, it will be rendered as an image
|
|
196
|
+
*/
|
|
197
|
+
renderIcon?: ElementIconRenderer | undefined
|
|
180
198
|
}
|
|
181
199
|
|
|
182
200
|
export interface LikeC4DiagramEventHandlers {
|
package/src/LikeC4Diagram.tsx
CHANGED
|
@@ -49,7 +49,8 @@ export function LikeC4Diagram({
|
|
|
49
49
|
onEdgeContextMenu,
|
|
50
50
|
onNavigateTo,
|
|
51
51
|
onNodeClick,
|
|
52
|
-
onNodeContextMenu
|
|
52
|
+
onNodeContextMenu,
|
|
53
|
+
renderIcon
|
|
53
54
|
}: LikeC4DiagramProps) {
|
|
54
55
|
DEV && useTilg()
|
|
55
56
|
const initialRef = useRef<{
|
|
@@ -70,6 +71,7 @@ export function LikeC4Diagram({
|
|
|
70
71
|
initialHeight: initialHeight ?? view.height
|
|
71
72
|
}
|
|
72
73
|
}
|
|
74
|
+
|
|
73
75
|
return (
|
|
74
76
|
<EnsureMantine>
|
|
75
77
|
<XYFlowProvider
|
|
@@ -89,6 +91,7 @@ export function LikeC4Diagram({
|
|
|
89
91
|
nodesDraggable={nodesDraggable}
|
|
90
92
|
nodesSelectable={nodesSelectable}
|
|
91
93
|
experimentalEdgeEditing={experimentalEdgeEditing}
|
|
94
|
+
renderIcon={renderIcon ?? null}
|
|
92
95
|
onCanvasClick={onCanvasClick}
|
|
93
96
|
onCanvasContextMenu={onCanvasContextMenu}
|
|
94
97
|
onEdgeClick={onEdgeClick}
|
|
@@ -2,7 +2,7 @@ import { shallowEqual } from 'fast-equals'
|
|
|
2
2
|
import { createContext, type PropsWithChildren, useEffect, useRef } from 'react'
|
|
3
3
|
import { hasSubObject, isNonNullish, pickBy } from 'remeda'
|
|
4
4
|
import { useUpdateEffect } from '../hooks'
|
|
5
|
-
import { useXYFlow, useXYStoreApi } from '../xyflow/hooks'
|
|
5
|
+
import { useXYFlow, useXYStoreApi } from '../xyflow/hooks/useXYFlow'
|
|
6
6
|
import { createDiagramStore, type DiagramInitialState } from './diagramStore'
|
|
7
7
|
|
|
8
8
|
export type DiagramZustandStore = ReturnType<typeof createDiagramStore>
|
|
@@ -10,7 +10,12 @@ import type { Exact, Except, RequiredKeysOf, Simplify } from 'type-fest'
|
|
|
10
10
|
import { devtools, subscribeWithSelector } from 'zustand/middleware'
|
|
11
11
|
import { shallow } from 'zustand/shallow'
|
|
12
12
|
import { createWithEqualityFn } from 'zustand/traditional'
|
|
13
|
-
import type {
|
|
13
|
+
import type {
|
|
14
|
+
Changes,
|
|
15
|
+
DiagramNodeWithNavigate,
|
|
16
|
+
ElementIconRenderer,
|
|
17
|
+
LikeC4DiagramEventHandlers
|
|
18
|
+
} from '../LikeC4Diagram.props'
|
|
14
19
|
import { MinZoom } from '../xyflow/const'
|
|
15
20
|
import type { XYStoreApi } from '../xyflow/hooks'
|
|
16
21
|
import type { XYFlowEdge, XYFlowInstance, XYFlowNode } from '../xyflow/types'
|
|
@@ -29,6 +34,7 @@ export type DiagramStore = {
|
|
|
29
34
|
nodesDraggable: boolean
|
|
30
35
|
nodesSelectable: boolean
|
|
31
36
|
experimentalEdgeEditing: boolean
|
|
37
|
+
renderIcon: ElementIconRenderer | null
|
|
32
38
|
// Diagram Container, see DiagramContainer.tsx
|
|
33
39
|
getContainer: () => HTMLDivElement | null
|
|
34
40
|
|
|
@@ -76,6 +82,7 @@ export type DiagramInitialState = // Required properties
|
|
|
76
82
|
& Pick<
|
|
77
83
|
DiagramStore,
|
|
78
84
|
| 'view'
|
|
85
|
+
| 'renderIcon'
|
|
79
86
|
| 'readonly'
|
|
80
87
|
| 'showElementLinks'
|
|
81
88
|
| 'fitViewEnabled'
|
|
@@ -2,7 +2,7 @@ import { ActionIcon, Group } from '@mantine/core'
|
|
|
2
2
|
import { IconChevronLeft, IconChevronRight } from '@tabler/icons-react'
|
|
3
3
|
import clsx from 'clsx'
|
|
4
4
|
import { AnimatePresence, m } from 'framer-motion'
|
|
5
|
-
import { useNavigationHistory } from '../state/
|
|
5
|
+
import { useNavigationHistory } from '../state/useNavigationHistory'
|
|
6
6
|
import * as css from './BackwardForwardPanel.css'
|
|
7
7
|
|
|
8
8
|
export function BackwardForwardPanel() {
|
|
@@ -3,7 +3,7 @@ import { useDebouncedEffect } from '@react-hookz/web'
|
|
|
3
3
|
import { shallowEqual } from 'fast-equals'
|
|
4
4
|
import { useEffect, useRef } from 'react'
|
|
5
5
|
import { type DiagramState, type DiagramStoreApi, useDiagramState, useDiagramStoreApi } from '../state/hooks'
|
|
6
|
-
import { useXYStore, useXYStoreApi, type XYStoreApi } from './hooks'
|
|
6
|
+
import { useXYStore, useXYStoreApi, type XYStoreApi } from './hooks/useXYFlow'
|
|
7
7
|
import type { XYFlowState } from './types'
|
|
8
8
|
import { toDomPrecision } from './utils'
|
|
9
9
|
|
|
@@ -2,7 +2,7 @@ import { nonNullable } from '@likec4/core'
|
|
|
2
2
|
import type { EdgeChange, NodeChange } from '@xyflow/react'
|
|
3
3
|
import { getBoundsOfRects, getViewportForBounds, nodeToRect } from '@xyflow/system'
|
|
4
4
|
import { useEffect } from 'react'
|
|
5
|
-
import { useDiagramStoreApi } from '../state/
|
|
5
|
+
import { useDiagramStoreApi } from '../state/useDiagramStore'
|
|
6
6
|
import { MinZoom } from './const'
|
|
7
7
|
import type { XYFlowEdge, XYFlowNode } from './types'
|
|
8
8
|
|
|
@@ -2,7 +2,7 @@ import { deepEqual as eq } from 'fast-equals'
|
|
|
2
2
|
|
|
3
3
|
import { useEffect } from 'react'
|
|
4
4
|
import { omit } from 'remeda'
|
|
5
|
-
import { useDiagramState, useDiagramStoreApi } from '../state/
|
|
5
|
+
import { useDiagramState, useDiagramStoreApi } from '../state/useDiagramStore'
|
|
6
6
|
import { diagramViewToXYFlowData } from './diagram-to-xyflow'
|
|
7
7
|
|
|
8
8
|
/**
|
package/src/xyflow/XYFlow.tsx
CHANGED
|
@@ -3,7 +3,8 @@ import { DEV } from 'esm-env'
|
|
|
3
3
|
import { deepEqual as eq } from 'fast-equals'
|
|
4
4
|
import { type CSSProperties, type PropsWithChildren, useCallback } from 'react'
|
|
5
5
|
import useTilg from 'tilg'
|
|
6
|
-
import {
|
|
6
|
+
import type { DiagramState } from '../state/diagramStore'
|
|
7
|
+
import { useDiagramState, useDiagramStoreApi } from '../state/useDiagramStore'
|
|
7
8
|
import { MinZoom } from './const'
|
|
8
9
|
import { RelationshipEdge } from './edges/RelationshipEdge'
|
|
9
10
|
import { useLayoutConstraints } from './hooks/useLayoutConstraints'
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ReactFlowProps } from '@xyflow/react'
|
|
2
2
|
import { useMemo, useRef } from 'react'
|
|
3
3
|
import type { Simplify } from 'type-fest'
|
|
4
|
-
import { useDiagramStoreApi } from '../state/
|
|
4
|
+
import { useDiagramStoreApi } from '../state/useDiagramStore'
|
|
5
5
|
import type { XYFlowEdge, XYFlowNode } from './types'
|
|
6
6
|
|
|
7
7
|
export type XYFlowEventHandlers = Simplify<
|
|
@@ -3,7 +3,7 @@ import { shallowEqual } from 'fast-equals'
|
|
|
3
3
|
import { memo, type PropsWithChildren } from 'react'
|
|
4
4
|
import { isNonNull } from 'remeda'
|
|
5
5
|
import type { LikeC4DiagramProperties } from '../LikeC4Diagram.props'
|
|
6
|
-
import { useDiagramState } from '../state/
|
|
6
|
+
import { useDiagramState } from '../state/useDiagramStore'
|
|
7
7
|
import { BackwardForwardPanel } from '../ui/BackwardForwardPanel'
|
|
8
8
|
import DiagramTitlePanel from '../ui/DiagramTitlePanel'
|
|
9
9
|
import { DynamicViewWalkthrough } from '../ui/DynamicViewWalkthrough'
|
|
@@ -16,10 +16,10 @@ import { curveCatmullRomOpen, line as d3line } from 'd3-shape'
|
|
|
16
16
|
import { deepEqual, deepEqual as eq } from 'fast-equals'
|
|
17
17
|
import { memo, type PointerEvent as ReactPointerEvent, useRef, useState } from 'react'
|
|
18
18
|
import { first, hasAtLeast, isArray, isTruthy, last } from 'remeda'
|
|
19
|
-
import { useDiagramState, useDiagramStoreApi } from '../../state/
|
|
19
|
+
import { useDiagramState, useDiagramStoreApi } from '../../state/useDiagramStore'
|
|
20
20
|
import { ZIndexes } from '../const'
|
|
21
21
|
import { EdgeMarkers } from '../EdgeMarkers'
|
|
22
|
-
import { useXYStoreApi } from '../hooks'
|
|
22
|
+
import { useXYStoreApi } from '../hooks/useXYFlow'
|
|
23
23
|
import { type RelationshipData, type XYFlowEdge } from '../types'
|
|
24
24
|
import { bezierControlPoints } from '../utils'
|
|
25
25
|
import * as edgesCss from './edges.css'
|
|
@@ -375,7 +375,7 @@ export const RelationshipEdge = /* @__PURE__ */ memo<EdgeProps<XYFlowEdge>>(func
|
|
|
375
375
|
selected: selected ?? false,
|
|
376
376
|
stepNum: data.stepNum,
|
|
377
377
|
label: data.label,
|
|
378
|
-
zIndex: edgeLookup.get(id)!.zIndex ?? ZIndexes.Edge,
|
|
378
|
+
zIndex: (edgeLookup.get(id)!.zIndex ?? ZIndexes.Edge) + 1,
|
|
379
379
|
isHovered,
|
|
380
380
|
isActive,
|
|
381
381
|
isStepEdge
|
|
@@ -53,7 +53,7 @@ globalStyle(`:where(${isSelected}) ${container}[data-edge-hovered='true']`, {
|
|
|
53
53
|
// })
|
|
54
54
|
|
|
55
55
|
globalStyle(`.react-flow__edges > svg`, {
|
|
56
|
-
mixBlendMode: '
|
|
56
|
+
mixBlendMode: 'plus-lighter'
|
|
57
57
|
})
|
|
58
58
|
|
|
59
59
|
// globalStyle(`:where([data-mantine-color-scheme="light"]) .react-flow__edges > svg`, {
|
|
@@ -63,7 +63,7 @@ globalStyle(`.react-flow__edges > svg`, {
|
|
|
63
63
|
export const dimmed = style({})
|
|
64
64
|
|
|
65
65
|
globalStyle(`.react-flow__edges > svg:has(${dimmed})`, {
|
|
66
|
-
opacity: 0.
|
|
66
|
+
opacity: 0.6,
|
|
67
67
|
transition: 'opacity 600ms ease-in-out, filter 600ms ease-in-out',
|
|
68
68
|
transitionDelay: '200ms',
|
|
69
69
|
filter: `grayscale(0.85) ${fallbackVar(vars.safariAnimationHook, 'blur(1px)')}`,
|
|
@@ -117,11 +117,11 @@ export const controlPoint = style({
|
|
|
117
117
|
})
|
|
118
118
|
|
|
119
119
|
export const controlDragging = style({
|
|
120
|
-
cursor: '
|
|
120
|
+
cursor: 'grab'
|
|
121
121
|
})
|
|
122
122
|
|
|
123
123
|
globalStyle(`${controlDragging} *`, {
|
|
124
|
-
cursor: '
|
|
124
|
+
cursor: 'grab'
|
|
125
125
|
})
|
|
126
126
|
|
|
127
127
|
const strokeKeyframes = keyframes({
|
|
@@ -174,7 +174,7 @@ export const edgeLabel = style({
|
|
|
174
174
|
cursor: 'pointer',
|
|
175
175
|
width: 'fit-content',
|
|
176
176
|
transformOrigin: '50% 50%',
|
|
177
|
-
mixBlendMode: '
|
|
177
|
+
mixBlendMode: 'plus-lighter',
|
|
178
178
|
color: xyvars.edge.labelColor,
|
|
179
179
|
backgroundColor: xyvars.edge.labelBgColor,
|
|
180
180
|
borderRadius: 3,
|
|
@@ -188,7 +188,7 @@ export const edgeLabel = style({
|
|
|
188
188
|
transform: `${varTranslate} scale(1.12)`
|
|
189
189
|
},
|
|
190
190
|
[`&:is(${dimmed})`]: {
|
|
191
|
-
opacity: 0.
|
|
191
|
+
opacity: 0.3,
|
|
192
192
|
transition: 'opacity 600ms ease-in-out, filter 600ms ease-in-out',
|
|
193
193
|
transitionDelay: '200ms',
|
|
194
194
|
filter: `grayscale(0.85) ${fallbackVar(vars.safariAnimationHook, 'blur(1px)')}`,
|
|
@@ -4,7 +4,7 @@ import type { InternalNode, ReactFlowProps, XYPosition } from '@xyflow/react'
|
|
|
4
4
|
import { getNodeDimensions } from '@xyflow/system'
|
|
5
5
|
import { useMemo, useRef } from 'react'
|
|
6
6
|
import { isNullish } from 'remeda'
|
|
7
|
-
import { useDiagramStoreApi } from '../../state/
|
|
7
|
+
import { useDiagramStoreApi } from '../../state/useDiagramStore'
|
|
8
8
|
import type { XYFlowInstance, XYFlowNode } from '../types'
|
|
9
9
|
import { isSamePoint } from '../utils'
|
|
10
10
|
import { useXYStoreApi, type XYStoreApi } from './useXYFlow'
|
|
@@ -5,7 +5,7 @@ import clsx from 'clsx'
|
|
|
5
5
|
import { deepEqual as eq } from 'fast-equals'
|
|
6
6
|
import { memo } from 'react'
|
|
7
7
|
import { clamp } from 'remeda'
|
|
8
|
-
import { useDiagramState } from '../../../state/
|
|
8
|
+
import { useDiagramState } from '../../../state/useDiagramStore'
|
|
9
9
|
import type { CompoundXYFlowNode } from '../../types'
|
|
10
10
|
import { NavigateToBtn } from '../shared/NavigateToBtn'
|
|
11
11
|
import * as css from './CompoundNode.css'
|
|
@@ -16,7 +16,8 @@ import { IconLink } from '@tabler/icons-react'
|
|
|
16
16
|
import clsx from 'clsx'
|
|
17
17
|
import { useId } from 'react'
|
|
18
18
|
import { clamp } from 'remeda'
|
|
19
|
-
import { type DiagramState
|
|
19
|
+
import { type DiagramState } from '../../../state/diagramStore'
|
|
20
|
+
import { useDiagramState } from '../../../state/useDiagramStore'
|
|
20
21
|
import type { XYFlowNode } from '../../types'
|
|
21
22
|
import { elementLink, trigger } from './ElementLink.css'
|
|
22
23
|
|
|
@@ -1,19 +1,23 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { DiagramNode } from '@likec4/core/types'
|
|
2
|
+
import { Text as MantineText } from '@mantine/core'
|
|
2
3
|
import { Handle, type NodeProps, Position } from '@xyflow/react'
|
|
3
4
|
import clsx from 'clsx'
|
|
4
5
|
import { deepEqual as eq } from 'fast-equals'
|
|
5
6
|
import { m, type Variants } from 'framer-motion'
|
|
6
7
|
import { memo } from 'react'
|
|
7
|
-
import { isNumber } from 'remeda'
|
|
8
|
-
import { useDiagramState } from '../../../state/
|
|
8
|
+
import { isNumber, isTruthy } from 'remeda'
|
|
9
|
+
import { useDiagramState } from '../../../state/useDiagramStore'
|
|
9
10
|
import type { ElementXYFlowNode } from '../../types'
|
|
10
11
|
import { toDomPrecision } from '../../utils'
|
|
11
12
|
import { NavigateToBtn } from '../shared/NavigateToBtn'
|
|
12
13
|
import * as css from './element.css'
|
|
13
|
-
import { ElementIcon } from './ElementIcon'
|
|
14
14
|
import { ElementLink } from './ElementLink'
|
|
15
15
|
import { ElementShapeSvg, SelectedIndicator } from './ElementShapeSvg'
|
|
16
16
|
|
|
17
|
+
const Text = MantineText.withProps({
|
|
18
|
+
component: 'div'
|
|
19
|
+
})
|
|
20
|
+
|
|
17
21
|
type ElementNodeProps = NodeProps<ElementXYFlowNode>
|
|
18
22
|
|
|
19
23
|
const selectedScale = 1.015
|
|
@@ -143,6 +147,22 @@ export const ElementNodeMemo = memo<ElementNodeProps>(function ElementNode({
|
|
|
143
147
|
whileTap: dragging ? animate : 'tap'
|
|
144
148
|
})}
|
|
145
149
|
>
|
|
150
|
+
{
|
|
151
|
+
/* <svg
|
|
152
|
+
className={clsx(
|
|
153
|
+
css.cssShapeSvgMultiple
|
|
154
|
+
)}
|
|
155
|
+
viewBox={`0 0 ${w} ${h}`}
|
|
156
|
+
width={w}
|
|
157
|
+
height={h}
|
|
158
|
+
>
|
|
159
|
+
<ElementShapeSvg
|
|
160
|
+
shape={element.shape}
|
|
161
|
+
w={w}
|
|
162
|
+
h={h}
|
|
163
|
+
/>
|
|
164
|
+
</svg> */
|
|
165
|
+
}
|
|
146
166
|
<svg
|
|
147
167
|
className={clsx(
|
|
148
168
|
css.cssShapeSvg
|
|
@@ -164,27 +184,32 @@ export const ElementNodeMemo = memo<ElementNodeProps>(function ElementNode({
|
|
|
164
184
|
h={h}
|
|
165
185
|
/>
|
|
166
186
|
</svg>
|
|
167
|
-
<div
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
{element.title}
|
|
173
|
-
</Text>
|
|
174
|
-
{element.technology && (
|
|
175
|
-
<Text
|
|
176
|
-
component="div"
|
|
177
|
-
className={clsx(css.technology, 'likec4-element-technology')}>
|
|
178
|
-
{element.technology}
|
|
179
|
-
</Text>
|
|
187
|
+
<div
|
|
188
|
+
className={clsx(
|
|
189
|
+
css.elementDataContainer,
|
|
190
|
+
isTruthy(element.icon) && css.hasIcon,
|
|
191
|
+
'likec4-element'
|
|
180
192
|
)}
|
|
181
|
-
|
|
193
|
+
>
|
|
194
|
+
{isTruthy(element.icon) && <ElementIcon node={element} />}
|
|
195
|
+
<div className={clsx(css.elementTextData, 'likec4-element-main-props')}>
|
|
182
196
|
<Text
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
{element.description}
|
|
197
|
+
className={clsx(css.title, 'likec4-element-title')}>
|
|
198
|
+
{element.title}
|
|
186
199
|
</Text>
|
|
187
|
-
|
|
200
|
+
{element.technology && (
|
|
201
|
+
<Text
|
|
202
|
+
className={clsx(css.technology, 'likec4-element-technology')}>
|
|
203
|
+
{element.technology}
|
|
204
|
+
</Text>
|
|
205
|
+
)}
|
|
206
|
+
{element.description && (
|
|
207
|
+
<Text
|
|
208
|
+
className={clsx(css.description, 'likec4-element-description')}>
|
|
209
|
+
{element.description}
|
|
210
|
+
</Text>
|
|
211
|
+
)}
|
|
212
|
+
</div>
|
|
188
213
|
</div>
|
|
189
214
|
{isHovercards && element.links && <ElementLink element={element} />}
|
|
190
215
|
{isNavigable && <NavigateToBtn xynodeId={id} className={css.cssNavigateBtn} />}
|
|
@@ -197,3 +222,26 @@ export const ElementNodeMemo = memo<ElementNodeProps>(function ElementNode({
|
|
|
197
222
|
</>
|
|
198
223
|
)
|
|
199
224
|
}, isEqualProps)
|
|
225
|
+
|
|
226
|
+
const ElementIcon = ({ node }: { node: DiagramNode }) => {
|
|
227
|
+
const RenderIcon = useDiagramState(s => s.renderIcon)
|
|
228
|
+
if (!node.icon) {
|
|
229
|
+
return null
|
|
230
|
+
}
|
|
231
|
+
if (node.icon.startsWith('http://') || node.icon.startsWith('https://')) {
|
|
232
|
+
return (
|
|
233
|
+
<div className={clsx(css.elementIcon, 'likec4-element-icon')}>
|
|
234
|
+
<img src={node.icon} alt={node.title} />
|
|
235
|
+
</div>
|
|
236
|
+
)
|
|
237
|
+
}
|
|
238
|
+
const icon = RenderIcon ? <RenderIcon node={node} /> : null
|
|
239
|
+
if (!icon) {
|
|
240
|
+
return null
|
|
241
|
+
}
|
|
242
|
+
return (
|
|
243
|
+
<div className={clsx(css.elementIcon, 'likec4-element-icon')}>
|
|
244
|
+
{icon}
|
|
245
|
+
</div>
|
|
246
|
+
)
|
|
247
|
+
}
|
|
@@ -2,7 +2,7 @@ import { type ElementShape, nonexhaustive } from '@likec4/core'
|
|
|
2
2
|
import { toDomPrecision } from '../../utils'
|
|
3
3
|
import { fillElementFill, fillMixStroke } from './element.css'
|
|
4
4
|
|
|
5
|
-
function cylinderSVGPath(diameter: number, height: number, tilt = 0.
|
|
5
|
+
export function cylinderSVGPath(diameter: number, height: number, tilt = 0.065) {
|
|
6
6
|
const radius = Math.round(diameter / 2)
|
|
7
7
|
// const tiltAdjustedHeight = height * Math.cos((tilt * Math.PI) / 2)
|
|
8
8
|
const rx = radius
|
|
@@ -25,7 +25,7 @@ function cylinderSVGPath(diameter: number, height: number, tilt = 0.0725) {
|
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
function queueSVGPath(width: number, height: number, tilt = 0.
|
|
28
|
+
function queueSVGPath(width: number, height: number, tilt = 0.185) {
|
|
29
29
|
const diameter = height
|
|
30
30
|
const radius = Math.round(diameter / 2)
|
|
31
31
|
const ry = radius
|