Skip to content

Commit 7ec2f97

Browse files
authored
Merge pull request #15 from yWorks/dev
3.0.0 - yFiles for HTML 3.0
2 parents 86a5da6 + b89aaeb commit 7ec2f97

26 files changed

+375
-742
lines changed

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@yworks/react-yfiles-core",
3-
"version": "2.0.1",
3+
"version": "3.0.0",
44
"author": {
55
"name": "yFiles for HTML team @ yWorks GmbH",
66
"email": "[email protected]"
@@ -33,7 +33,7 @@
3333
"peerDependencies": {
3434
"react": ">=18",
3535
"react-dom": ">=18",
36-
"yfiles": ">=26"
36+
"@yfiles/yfiles": ">=30"
3737
},
3838
"devDependencies": {
3939
"@types/react": "^18.2.15",

src/context-menu/ContextMenu.tsx

Lines changed: 12 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,8 @@ import {
66
useLayoutEffect,
77
useState
88
} from 'react'
9-
import {
10-
GraphComponent,
11-
GraphViewerInputMode,
12-
IModelItem,
13-
Point,
14-
PopulateItemContextMenuEventArgs,
15-
TouchEventArgs
16-
} from 'yfiles'
9+
import { GraphViewerInputMode, IModelItem, PopulateItemContextMenuEventArgs } from '@yfiles/yfiles'
1710
import { useGraphComponent } from '../graph-component/GraphComponentProvider.tsx'
18-
import { BrowserDetection } from '../utils/BrowserDetection.ts'
1911
import './ContextMenu.css'
2012
import { DefaultRenderMenu } from './DefaultRenderMenu.tsx'
2113

@@ -95,19 +87,6 @@ export function ContextMenu<TDataItem>({
9587

9688
const graphComponent = useGraphComponent()!
9789

98-
const openContextMenu = useCallback(
99-
(worldLocation: Point) => {
100-
const showMenu = (
101-
graphComponent.inputMode as GraphViewerInputMode
102-
).contextMenuInputMode.shouldOpenMenu(worldLocation)
103-
if (showMenu) {
104-
setMenuVisible(true)
105-
setMenuLocation(graphComponent.toViewCoordinates(worldLocation))
106-
}
107-
},
108-
[graphComponent]
109-
)
110-
11190
const populateContextMenu = useCallback(
11291
(args: PopulateItemContextMenuEventArgs<IModelItem>) => {
11392
const modelItem = args.item
@@ -123,77 +102,33 @@ export function ContextMenu<TDataItem>({
123102
* Registers the context menu listeners.
124103
*/
125104
useLayoutEffect(() => {
126-
const componentDiv = graphComponent.div
127-
const contextMenuListener = (evt: MouseEvent) => {
128-
evt.preventDefault()
129-
openContextMenu(graphComponent.toWorldFromPage({ x: evt.pageX, y: evt.pageY }))
130-
}
131-
132-
// Listen for the contextmenu event
133-
// Note: On Linux based systems (e.g. Ubuntu), the contextmenu event is fired on mouse down
134-
// which triggers the ContextMenuInputMode before the ClickInputMode. Therefore, handling the
135-
// event, will prevent the ItemRightClicked event from firing.
136-
// For more information, see https://docs.yworks.com/yfileshtml/#/kb/article/780/
137-
componentDiv.addEventListener('contextmenu', contextMenuListener, false)
138-
139-
let touchDownListener: (_: GraphComponent, evt: TouchEventArgs) => void | null
140-
let touchUpListener: (_: GraphComponent, evt: TouchEventArgs) => void | null
141-
if (BrowserDetection.safariVersion > 0 || BrowserDetection.iOSVersion > 0) {
142-
// Additionally add a long press listener especially for iOS, since it does not fire the contextmenu event.
143-
let contextMenuTimer: ReturnType<typeof setTimeout> | undefined
144-
touchDownListener = (_: GraphComponent, evt: TouchEventArgs) => {
145-
contextMenuTimer = setTimeout(() => {
146-
openContextMenu(evt.location)
147-
}, 500)
148-
}
149-
graphComponent.addTouchDownListener(touchDownListener)
150-
touchUpListener = () => {
151-
clearTimeout(contextMenuTimer!)
152-
}
153-
graphComponent.addTouchUpListener(touchUpListener)
154-
}
155-
156-
// Listen to the context menu key to make it work in Chrome
157-
const contextMenuKeyListener = (evt: KeyboardEvent) => {
158-
if (evt.key === 'ContextMenu') {
159-
evt.preventDefault()
160-
openContextMenu(graphComponent.toWorldFromPage(getCenterInPage(componentDiv)))
161-
}
162-
}
163-
componentDiv.addEventListener('keyup', contextMenuKeyListener)
164-
165105
// register the close listener
166106
const closeMenuListener = () => {
167107
setMenuVisible(false)
168108
}
169109
const inputMode = graphComponent.inputMode as GraphViewerInputMode
170-
inputMode.contextMenuInputMode.addCloseMenuListener(closeMenuListener)
110+
inputMode.contextMenuInputMode.addEventListener('menu-closed', closeMenuListener)
171111

172112
// register populate items listener
173-
const populateContextMenuListener = (
174-
_: GraphViewerInputMode,
175-
args: PopulateItemContextMenuEventArgs<IModelItem>
176-
) => {
113+
const populateContextMenuListener = (event: PopulateItemContextMenuEventArgs<IModelItem>) => {
177114
// select the item
178-
if (args.item) {
115+
if (event.item) {
179116
graphComponent.selection.clear()
180-
graphComponent.selection.setSelected(args.item, true)
117+
graphComponent.selection.add(event.item)
181118
}
119+
setMenuVisible(true)
120+
setMenuLocation(graphComponent.worldToViewCoordinates(event.queryLocation))
182121
// populate the menu
183-
populateContextMenu(args)
122+
populateContextMenu(event)
184123
}
185-
inputMode.addPopulateItemContextMenuListener(populateContextMenuListener)
124+
inputMode.addEventListener('populate-item-context-menu', populateContextMenuListener)
186125

187126
return () => {
188127
// cleanup
189-
componentDiv.removeEventListener('contextmenu', contextMenuListener)
190-
componentDiv.removeEventListener('keyup', contextMenuKeyListener)
191-
inputMode.contextMenuInputMode.removeCloseMenuListener(closeMenuListener)
192-
inputMode.removePopulateItemContextMenuListener(populateContextMenuListener)
193-
touchDownListener && graphComponent.removeTouchDownListener(touchDownListener)
194-
touchUpListener && graphComponent.removeTouchUpListener(touchUpListener)
128+
inputMode.contextMenuInputMode.removeEventListener('menu-closed', closeMenuListener)
129+
inputMode.removeEventListener('populate-item-context-menu', populateContextMenuListener)
195130
}
196-
}, [graphComponent, openContextMenu, populateContextMenu])
131+
}, [graphComponent, populateContextMenu])
197132

198133
return (
199134
<>
@@ -249,17 +184,3 @@ function ContextMenuCore<TDataItem>({
249184
)
250185
)
251186
}
252-
253-
/**
254-
* Helper function to determine the page's center location.
255-
*/
256-
function getCenterInPage(element: HTMLElement): { x: number; y: number } {
257-
let left = element.clientWidth / 2.0
258-
let top = element.clientHeight / 2.0
259-
while (element.offsetParent) {
260-
left += element.offsetLeft
261-
top += element.offsetTop
262-
element = element.offsetParent as HTMLElement
263-
}
264-
return { x: left, y: top }
265-
}

src/controls/DefaultControlButtons.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { ControlButton } from './Controls.tsx'
22
import { useGraphComponent } from '../graph-component/GraphComponentProvider.tsx'
3-
import { ICommand } from 'yfiles'
3+
import { Command } from '@yfiles/yfiles'
44

55
/**
66
* A function returning the default control buttons to be used in {@link ControlsProps.buttons}.
@@ -14,22 +14,22 @@ export function DefaultControlButtons(): ControlButton[] {
1414

1515
const items: ControlButton[] = []
1616
items.push({
17-
action: () => ICommand.INCREASE_ZOOM.execute(null, graphComponent),
17+
action: () => graphComponent.executeCommand(Command.INCREASE_ZOOM, null),
1818
className: 'yfiles-react-controls__button--zoom-in',
1919
tooltip: 'Increase zoom'
2020
})
2121
items.push({
22-
action: () => ICommand.ZOOM.execute(1.0, graphComponent),
22+
action: () => graphComponent.executeCommand(Command.ZOOM, 1.0),
2323
className: 'yfiles-react-controls__button--zoom-original',
2424
tooltip: 'Zoom to original size'
2525
})
2626
items.push({
27-
action: () => ICommand.DECREASE_ZOOM.execute(null, graphComponent),
27+
action: () => graphComponent.executeCommand(Command.DECREASE_ZOOM, null),
2828
className: 'yfiles-react-controls__button--zoom-out',
2929
tooltip: 'Decrease zoom'
3030
})
3131
items.push({
32-
action: () => ICommand.FIT_GRAPH_BOUNDS.execute(null, graphComponent),
32+
action: () => graphComponent.executeCommand(Command.FIT_GRAPH_BOUNDS, null),
3333
className: 'yfiles-react-controls__button--zoom-fit',
3434
tooltip: 'Fit content'
3535
})

src/graph-component/EdgeStyles.ts

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Arrow as YArrow, ArrowType, IArrow, PolylineEdgeStyle, Stroke } from 'yfiles'
1+
import { Arrow as YArrow, ArrowType, IArrow, PolylineEdgeStyle, Stroke } from '@yfiles/yfiles'
22

33
/**
44
* A connection style configuration.
@@ -37,7 +37,17 @@ export interface Arrow {
3737
/**
3838
* The shape of the arrow.
3939
*/
40-
type?: 'circle' | 'cross' | 'default' | 'diamond' | 'none' | 'short' | 'simple' | 'triangle'
40+
type?:
41+
| 'ellipse'
42+
| 'cross'
43+
| 'stealth'
44+
| 'diamond'
45+
| 'none'
46+
| 'open'
47+
| 'triangle'
48+
| 'deltoid'
49+
| 'kite'
50+
| 'chevron'
4151
}
4252

4353
/**
@@ -62,12 +72,12 @@ export function convertToPolylineEdgeStyle(style: EdgeStyle) {
6272
function convertArrow(style: EdgeStyle, isSource = false): IArrow {
6373
const arrow = isSource ? style.sourceArrow : style.targetArrow
6474
if (!arrow) {
65-
return IArrow.NONE
75+
return new YArrow(ArrowType.NONE)
6676
}
6777
const arrowColor = arrow.color ?? (style.className ? 'currentColor' : 'black')
6878
return new YArrow({
6979
stroke: `${(style.thickness ?? 1) * 0.5}px ${arrowColor}`,
7080
fill: arrowColor,
71-
type: arrow.type ? ArrowType.from(arrow.type) : 'default'
81+
type: arrow.type ?? 'stealth'
7282
})
7383
}

src/graph-component/GraphComponentProvider.tsx

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import React, {
55
useLayoutEffect,
66
useMemo
77
} from 'react'
8-
import { GraphComponent, ScrollBarVisibility } from 'yfiles'
8+
import { GraphComponent, ScrollBarVisibility } from '@yfiles/yfiles'
99

1010
const GraphComponentContext = createContext<GraphComponent | null>(null)
1111

@@ -34,13 +34,13 @@ export function withGraphComponentProvider<
3434
return (props: React.ComponentProps<T>) => {
3535
const graphComponent = useMemo(() => {
3636
const graphComponent = new GraphComponent()
37-
graphComponent.div.style.width = '100%'
38-
graphComponent.div.style.height = '100%'
39-
graphComponent.div.style.minWidth = '400px'
40-
graphComponent.div.style.minHeight = '400px'
37+
graphComponent.htmlElement.style.width = '100%'
38+
graphComponent.htmlElement.style.height = '100%'
39+
graphComponent.htmlElement.style.minWidth = '400px'
40+
graphComponent.htmlElement.style.minHeight = '400px'
4141
// scrollbar styling
42-
graphComponent.horizontalScrollBarPolicy = ScrollBarVisibility.AS_NEEDED_DYNAMIC
43-
graphComponent.verticalScrollBarPolicy = ScrollBarVisibility.AS_NEEDED_DYNAMIC
42+
graphComponent.horizontalScrollBarPolicy = ScrollBarVisibility.AUTO
43+
graphComponent.verticalScrollBarPolicy = ScrollBarVisibility.AUTO
4444
return graphComponent
4545
}, [])
4646

@@ -64,14 +64,14 @@ export function useAddGraphComponent(
6464
if (parentRef.current) {
6565
const firstChild = parentRef.current.firstChild
6666
if (firstChild) {
67-
parentRef.current.insertBefore(graphComponent.div, firstChild)
67+
parentRef.current.insertBefore(graphComponent.htmlElement, firstChild)
6868
} else {
69-
parentRef.current.appendChild(graphComponent.div)
69+
parentRef.current.appendChild(graphComponent.htmlElement)
7070
}
7171
}
7272
return () => {
7373
if (parentRef.current) {
74-
parentRef.current.removeChild(graphComponent.div)
74+
parentRef.current.removeChild(graphComponent.htmlElement)
7575
}
7676
}
7777
}, [])

src/graph-component/ReactComponentHtmlGroupNodeStyle.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { ComponentType, Dispatch, SetStateAction } from 'react'
2-
import type { GraphComponent, INode, IRenderContext } from 'yfiles'
2+
import type { GraphComponent, INode, IRenderContext } from '@yfiles/yfiles'
33
import {
44
defaultTagProvider,
55
NodeRenderInfo,

src/graph-component/ReactComponentHtmlNodeStyle.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ import type {
55
IRenderContext,
66
TypedHtmlVisual,
77
Visual
8-
} from 'yfiles'
9-
import { HtmlVisual, NodeStyleBase } from 'yfiles'
8+
} from '@yfiles/yfiles'
9+
import { HtmlVisual, NodeStyleBase } from '@yfiles/yfiles'
1010
import { ComponentType, Dispatch, memo, SetStateAction } from 'react'
1111

1212
/**
@@ -119,7 +119,7 @@ export class ReactComponentHtmlNodeStyle<TDataItem> extends NodeStyleBase<
119119
const graphComponent = context.canvasComponent as GraphComponent
120120
const inputMode = graphComponent.inputMode as GraphInputMode
121121
return {
122-
selected: graphComponent.selection.isSelected(node),
122+
selected: graphComponent.selection.includes(node),
123123
hovered: inputMode?.itemHoverInputMode.currentHoverItem === node,
124124
focused: graphComponent.currentItem === node,
125125
width: node.layout.width,

src/graph-component/ReactNodeRendering.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {
1111
useRef,
1212
useState
1313
} from 'react'
14-
import { FilteredGraphWrapper, GraphComponent, IGraph, INode, Rect } from 'yfiles'
14+
import { FilteredGraphWrapper, GraphComponent, IGraph, INode, Rect } from '@yfiles/yfiles'
1515
import {
1616
NodeRenderInfo,
1717
ReactComponentHtmlNodeStyle,

0 commit comments

Comments
 (0)