@dxos/react-ui-canvas 0.7.5-main.9d2a38b → 0.7.5-main.b19bfc8
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/README.md +1 -3
- package/dist/lib/browser/index.mjs +114 -34
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node/index.cjs +115 -33
- package/dist/lib/node/index.cjs.map +4 -4
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +114 -34
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/types/src/components/Canvas/Canvas.d.ts +2 -2
- package/dist/types/src/components/Canvas/Canvas.d.ts.map +1 -1
- package/dist/types/src/components/Canvas/Canvas.stories.d.ts +1 -0
- package/dist/types/src/components/Canvas/Canvas.stories.d.ts.map +1 -1
- package/dist/types/src/components/FPS.d.ts +1 -2
- package/dist/types/src/components/FPS.d.ts.map +1 -1
- package/dist/types/src/components/Grid/Grid.d.ts +7 -6
- package/dist/types/src/components/Grid/Grid.d.ts.map +1 -1
- package/dist/types/src/components/Grid/Grid.stories.d.ts.map +1 -1
- package/dist/types/src/hooks/index.d.ts +1 -1
- package/dist/types/src/hooks/index.d.ts.map +1 -1
- package/dist/types/src/hooks/projection.d.ts +2 -2
- package/dist/types/src/hooks/projection.d.ts.map +1 -1
- package/dist/types/src/hooks/{useProjection.d.ts → useCanvasContext.d.ts} +3 -2
- package/dist/types/src/hooks/useCanvasContext.d.ts.map +1 -0
- package/dist/types/src/hooks/useWheel.d.ts +4 -3
- package/dist/types/src/hooks/useWheel.d.ts.map +1 -1
- package/dist/types/src/util/svg.d.ts +5 -5
- package/dist/types/src/util/svg.d.ts.map +1 -1
- package/dist/types/src/util/util.d.ts +1 -0
- package/dist/types/src/util/util.d.ts.map +1 -1
- package/package.json +15 -14
- package/src/components/Canvas/Canvas.stories.tsx +51 -24
- package/src/components/Canvas/Canvas.tsx +12 -6
- package/src/components/FPS.tsx +1 -1
- package/src/components/Grid/Grid.stories.tsx +4 -6
- package/src/components/Grid/Grid.tsx +34 -8
- package/src/hooks/index.ts +1 -1
- package/src/hooks/projection.tsx +16 -9
- package/src/hooks/{useProjection.tsx → useCanvasContext.tsx} +2 -1
- package/src/hooks/useWheel.tsx +60 -8
- package/src/util/svg.stories.tsx +1 -1
- package/src/util/svg.tsx +2 -2
- package/src/util/util.ts +11 -0
- package/dist/types/src/hooks/useProjection.d.ts.map +0 -1
package/src/hooks/useWheel.tsx
CHANGED
|
@@ -3,36 +3,54 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import { bindAll } from 'bind-event-listener';
|
|
6
|
-
import {
|
|
6
|
+
import { useEffect } from 'react';
|
|
7
7
|
|
|
8
|
-
import { getZoomTransform
|
|
8
|
+
import { getZoomTransform } from './projection';
|
|
9
|
+
import { useCanvasContext } from './useCanvasContext';
|
|
9
10
|
import { getRelativePoint } from '../util';
|
|
10
11
|
|
|
12
|
+
export type WheelOptions = {
|
|
13
|
+
zoom?: boolean;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const defaultOptions: WheelOptions = {
|
|
17
|
+
zoom: true,
|
|
18
|
+
};
|
|
19
|
+
|
|
11
20
|
/**
|
|
12
21
|
* Handle wheel events to update the transform state (zoom and offset).
|
|
13
22
|
*/
|
|
14
|
-
export const useWheel = (
|
|
23
|
+
export const useWheel = (options: WheelOptions = defaultOptions) => {
|
|
24
|
+
const { root, setProjection } = useCanvasContext();
|
|
15
25
|
useEffect(() => {
|
|
16
|
-
if (!
|
|
26
|
+
if (!root) {
|
|
17
27
|
return;
|
|
18
28
|
}
|
|
19
29
|
|
|
20
|
-
return bindAll(
|
|
30
|
+
return bindAll(root, [
|
|
21
31
|
{
|
|
22
32
|
type: 'wheel',
|
|
23
33
|
options: { capture: true, passive: false },
|
|
24
34
|
listener: (ev: WheelEvent) => {
|
|
35
|
+
const zooming = isWheelZooming(ev);
|
|
36
|
+
if (!hasFocus(root) && !zooming) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
|
|
25
40
|
ev.preventDefault();
|
|
41
|
+
if (zooming && !options.zoom) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
26
44
|
|
|
27
45
|
// Zoom or pan.
|
|
28
46
|
if (ev.ctrlKey) {
|
|
29
|
-
if (!
|
|
47
|
+
if (!root) {
|
|
30
48
|
return;
|
|
31
49
|
}
|
|
32
50
|
|
|
33
51
|
// Keep centered while zooming.
|
|
34
52
|
setProjection(({ scale, offset }) => {
|
|
35
|
-
const pos = getRelativePoint(
|
|
53
|
+
const pos = getRelativePoint(root, ev);
|
|
36
54
|
const scaleSensitivity = 0.01;
|
|
37
55
|
const newScale = scale * Math.exp(-ev.deltaY * scaleSensitivity);
|
|
38
56
|
return getZoomTransform({ scale, offset, newScale, pos });
|
|
@@ -51,5 +69,39 @@ export const useWheel = (el: HTMLDivElement | null, setProjection: Dispatch<SetS
|
|
|
51
69
|
},
|
|
52
70
|
},
|
|
53
71
|
]);
|
|
54
|
-
}, [
|
|
72
|
+
}, [root]);
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const isWheelZooming = (ev: WheelEvent): boolean => {
|
|
76
|
+
// Check for ctrl/cmd key + wheel action.
|
|
77
|
+
if (ev.ctrlKey || ev.metaKey) {
|
|
78
|
+
// Some browsers use deltaY, others deltaZ for zoom.
|
|
79
|
+
return Math.abs(ev.deltaY) > 0 || Math.abs(ev.deltaZ) > 0;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return false;
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const hasFocus = (element: HTMLElement): boolean => {
|
|
86
|
+
const activeElement = document.activeElement;
|
|
87
|
+
if (!activeElement) {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Handle shadow DOM.
|
|
92
|
+
let shadowActive = activeElement;
|
|
93
|
+
while (shadowActive?.shadowRoot?.activeElement) {
|
|
94
|
+
shadowActive = shadowActive.shadowRoot.activeElement;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Check if element or any parent has focus.
|
|
98
|
+
let current: HTMLElement | null = element;
|
|
99
|
+
while (current) {
|
|
100
|
+
if (current === activeElement || current === shadowActive) {
|
|
101
|
+
return true;
|
|
102
|
+
}
|
|
103
|
+
current = current.parentElement;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return false;
|
|
55
107
|
};
|
package/src/util/svg.stories.tsx
CHANGED
|
@@ -13,7 +13,7 @@ import { Arrow, createPath } from './svg';
|
|
|
13
13
|
import { testId } from './util';
|
|
14
14
|
|
|
15
15
|
const Render = () => (
|
|
16
|
-
<svg className='border border-neutral-500 w-[
|
|
16
|
+
<svg className='border border-neutral-500 w-[30rem] h-[400px]'>
|
|
17
17
|
<defs>
|
|
18
18
|
<Arrow id='arrow-start' classNames='fill-none stroke-red-500' dir='start' />
|
|
19
19
|
<Arrow id='arrow-end' classNames='fill-none stroke-red-500' dir='end' />
|
package/src/util/svg.tsx
CHANGED
|
@@ -28,8 +28,8 @@ export const Markers = ({ id = 'dx-marker', classNames }: ThemedClassName<{ id?:
|
|
|
28
28
|
<Arrow id={`${id}-arrow-end`} dir='end' classNames={classNames} />
|
|
29
29
|
<Arrow id={`${id}-triangle-start`} dir='start' closed classNames={classNames} />
|
|
30
30
|
<Arrow id={`${id}-triangle-end`} dir='end' closed classNames={classNames} />
|
|
31
|
-
<Marker id={`${id}-circle`} pos={{ x:
|
|
32
|
-
<circle cx={
|
|
31
|
+
<Marker id={`${id}-circle`} pos={{ x: 8, y: 8 }} size={{ width: 16, height: 16 }}>
|
|
32
|
+
<circle cx={8} cy={8} r={5} stroke={'context-stroke'} className={mx(classNames)} />
|
|
33
33
|
</Marker>
|
|
34
34
|
</>
|
|
35
35
|
);
|
package/src/util/util.ts
CHANGED
|
@@ -36,4 +36,15 @@ export const testId = <ID = string>(id: ID, inspect = false) => {
|
|
|
36
36
|
return { [DATA_TEST_ID]: id };
|
|
37
37
|
};
|
|
38
38
|
|
|
39
|
+
export const inspectElement = (el: Element) => {
|
|
40
|
+
(window as any).INSPECT = () => {
|
|
41
|
+
(window as any).inspect(el);
|
|
42
|
+
(window as any).element = el;
|
|
43
|
+
// eslint-disable-next-line no-console
|
|
44
|
+
console.log('Open storybook in expanded window;\nthen run INSPECT()');
|
|
45
|
+
// eslint-disable-next-line no-console
|
|
46
|
+
console.log(el);
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
|
|
39
50
|
export const DATA_TEST_ID = 'data-test-id';
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useProjection.d.ts","sourceRoot":"","sources":["../../../../src/hooks/useProjection.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,QAAQ,EAAE,KAAK,cAAc,EAA6B,MAAM,OAAO,CAAC;AAI1G,OAAO,EAAE,KAAK,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,cAAc,CAAC;AAErE,MAAM,MAAM,aAAa,GAAG,eAAe,GAAG;IAC5C,IAAI,EAAE,cAAc,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,aAAa,CAAC;IACtB,UAAU,EAAE,UAAU,CAAC;IACvB,aAAa,EAAE,QAAQ,CAAC,cAAc,CAAC,eAAe,CAAC,CAAC,CAAC;CAC1D,CAAC;AAQF,eAAO,MAAM,aAAa,QAAO,aAEhC,CAAC"}
|