Skip to content

Commit

Permalink
Merge pull request #1019 from silx-kit/interaction-folder
Browse files Browse the repository at this point in the history
Put interaction components and utils in a dedicated folder
  • Loading branch information
loichuder authored Mar 17, 2022
2 parents 242400b + 91ad388 commit 5493f69
Show file tree
Hide file tree
Showing 30 changed files with 164 additions and 153 deletions.
2 changes: 1 addition & 1 deletion apps/storybook/src/Pan.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Pan, ResetZoomButton, VisCanvas, Zoom } from '@h5web/lib';
import type { ModifierKey as ModifierKeyType } from '@h5web/lib/src/vis/models';
import type { ModifierKey as ModifierKeyType } from '@h5web/lib';
import type { Meta, Story } from '@storybook/react';

import VisCanvasStoriesConfig from './VisCanvas.stories';
Expand Down
2 changes: 1 addition & 1 deletion apps/storybook/src/SelectToZoom.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
SelectToZoom,
ResetZoomButton,
} from '@h5web/lib';
import type { ModifierKey as ModifierKeyType } from '@h5web/lib/src/vis/models';
import type { ModifierKey as ModifierKeyType } from '@h5web/lib';
import type { Meta, Story } from '@storybook/react';
import { range } from 'lodash';

Expand Down
2 changes: 1 addition & 1 deletion apps/storybook/src/Selection.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { Selection, ModifierKey } from '@h5web/lib';
import {
Pan,
SelectionLine,
Expand All @@ -7,7 +8,6 @@ import {
Zoom,
ResetZoomButton,
} from '@h5web/lib';
import type { ModifierKey, Selection } from '@h5web/lib/src/vis/models';
import type { Meta, Story } from '@storybook/react';
import { format } from 'd3-format';
import { useState } from 'react';
Expand Down
2 changes: 1 addition & 1 deletion apps/storybook/src/XZoom.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Pan, ResetZoomButton, VisCanvas, XAxisZoom } from '@h5web/lib';
import type { ModifierKey as ModifierKeyType } from '@h5web/lib/src/vis/models';
import type { ModifierKey as ModifierKeyType } from '@h5web/lib';
import type { Meta, Story } from '@storybook/react';

import VisCanvasStoriesConfig from './VisCanvas.stories';
Expand Down
2 changes: 1 addition & 1 deletion apps/storybook/src/YZoom.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Pan, ResetZoomButton, VisCanvas, YAxisZoom } from '@h5web/lib';
import type { ModifierKey as ModifierKeyType } from '@h5web/lib/src/vis/models';
import type { ModifierKey as ModifierKeyType } from '@h5web/lib';
import type { Meta, Story } from '@storybook/react';

import VisCanvasStoriesConfig from './VisCanvas.stories';
Expand Down
2 changes: 1 addition & 1 deletion apps/storybook/src/Zoom.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Pan, ResetZoomButton, VisCanvas, Zoom } from '@h5web/lib';
import type { ModifierKey as ModifierKeyType } from '@h5web/lib/src/vis/models';
import type { ModifierKey as ModifierKeyType } from '@h5web/lib';
import type { Meta, Story } from '@storybook/react';

import VisCanvasStoriesConfig from './VisCanvas.stories';
Expand Down
30 changes: 18 additions & 12 deletions packages/lib/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,6 @@ export { default as InteractionHelp } from './toolbar/controls/InteractionHelp';
// Building blocks
export { default as VisCanvas } from './vis/shared/VisCanvas';
export type { VisCanvasProps } from './vis/shared/VisCanvas';
export { default as Pan } from './vis/shared/Pan';
export { default as Zoom } from './vis/shared/Zoom';
export { default as XAxisZoom } from './vis/shared/XAxisZoom';
export { default as YAxisZoom } from './vis/shared/YAxisZoom';
export { default as SelectToZoom } from './vis/shared/SelectToZoom';
export { default as ResetZoomButton } from './vis/shared/ResetZoomButton';
export { default as TooltipMesh } from './vis/shared/TooltipMesh';
export type { TooltipMeshProps } from './vis/shared/TooltipMesh';
export { default as VisMesh } from './vis/shared/VisMesh';
Expand All @@ -43,14 +37,22 @@ export type { HeatmapMeshProps } from './vis/heatmap/HeatmapMesh';
export { default as DataCurve } from './vis/line/DataCurve';
export { default as Html } from './vis/shared/Html';
export { default as Annotation } from './vis/shared/Annotation';
export { default as SelectionTool } from './vis/shared/SelectionTool';
export type { SelectionProps } from './vis/shared/SelectionTool';
export { default as SelectionLine } from './vis/shared/SelectionLine';
export { default as SelectionRect } from './vis/shared/SelectionRect';
export { default as TiledHeatmap } from './vis/tiles/TiledHeatmap';
export type { TiledHeatmapProps } from './vis/tiles/TiledHeatmap';
export { getLayerSizes, TilesApi } from './vis/tiles/api';

// Interactions
export { default as Pan } from './interactions/Pan';
export { default as Zoom } from './interactions/Zoom';
export { default as XAxisZoom } from './interactions/XAxisZoom';
export { default as YAxisZoom } from './interactions/YAxisZoom';
export { default as SelectToZoom } from './interactions/SelectToZoom';
export { default as ResetZoomButton } from './interactions/ResetZoomButton';
export { default as SelectionLine } from './interactions/SelectionLine';
export { default as SelectionRect } from './interactions/SelectionRect';
export { default as SelectionTool } from './interactions/SelectionTool';
export type { SelectionProps } from './interactions/SelectionTool';

// Context hook
export { useAxisSystemContext } from './vis/shared/AxisSystemContext';
export type { AxisSystemParams } from './vis/shared/AxisSystemContext';
Expand Down Expand Up @@ -82,13 +84,17 @@ export {
export { useVisDomain, useSafeDomain } from './vis/heatmap/hooks';

export { scaleGamma } from './vis/scaleGamma';
export { useCanvasEvents } from './vis/shared/hooks';
export { useCanvasEvents } from './interactions/hooks';

// Models
export { INTERPOLATORS } from './vis/heatmap/interpolators';
export { ScaleType } from '@h5web/shared';
export { CurveType } from './vis/line/models';
export type { Interaction } from './vis/models';
export type {
Interaction,
ModifierKey,
Selection,
} from './interactions/models';

export type { Domain, Dims } from '@h5web/shared';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import { useThree } from '@react-three/fiber';
import { useRef, useCallback } from 'react';
import type { Vector3 } from 'three';

import type { CanvasEvent, ModifierKey } from '../models';
import { checkModifierKey } from '../utils';
import { useCanvasEvents, useMoveCameraTo } from './hooks';
import type { CanvasEvent, ModifierKey } from './models';
import { checkModifierKey } from './utils';

interface Props {
disabled?: boolean;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@
}

.btn {
composes: btn from '../../toolbar/Toolbar.module.css';
composes: btn from '../toolbar/Toolbar.module.css';
padding: 0.5rem !important; /* FIX style ordering issue with Vite */
pointer-events: auto;
font-size: 0.875em;
}

.btnLike {
composes: btnLike from '../../toolbar/Toolbar.module.css';
composes: btnLike from '../toolbar/Toolbar.module.css';
background-color: rgba(255, 255, 255, 0.7);
box-shadow: rgba(0, 0, 0, 0.1) 0px 0px 0px 1px,
rgba(0, 0, 0, 0.1) 0px 4px 11px;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useThree } from '@react-three/fiber';

import { useFrameRendering } from '../hooks';
import Html from './Html';
import { useFrameRendering } from '../vis/hooks';
import Html from '../vis/shared/Html';
import styles from './ResetZoomButton.module.css';
import { useMoveCameraTo } from './hooks';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { useThree } from '@react-three/fiber';

import type { ModifierKey, Selection } from '../models';
import { getRatioEndPoint } from '../utils';
import { useAxisSystemContext } from './AxisSystemContext';
import { useAxisSystemContext } from '../vis/shared/AxisSystemContext';
import SelectionRect from './SelectionRect';
import SelectionTool from './SelectionTool';
import { useMoveCameraTo } from './hooks';
import type { ModifierKey, Selection } from './models';
import { getRatioEndPoint } from './utils';

interface Props {
modifierKey?: ModifierKey;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { useThree } from '@react-three/fiber';
import type { SVGProps } from 'react';
import type { Vector2 } from 'three';

import { useAxisSystemContext } from './AxisSystemContext';
import Html from './Html';
import { useAxisSystemContext } from '../vis/shared/AxisSystemContext';
import Html from '../vis/shared/Html';

interface Props extends SVGProps<SVGLineElement> {
startPoint: Vector2;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { useThree } from '@react-three/fiber';
import type { SVGProps } from 'react';
import type { Vector2 } from 'three';

import { useAxisSystemContext } from './AxisSystemContext';
import Html from './Html';
import { useAxisSystemContext } from '../vis/shared/AxisSystemContext';
import Html from '../vis/shared/Html';

interface Props extends SVGProps<SVGRectElement> {
startPoint: Vector2;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import type { ReactElement } from 'react';
import { useCallback, useState } from 'react';
import type { Vector2 } from 'three';

import type { CanvasEvent, ModifierKey, Selection } from '../models';
import { boundPointToFOV, checkModifierKey } from '../utils';
import { useAxisSystemContext } from './AxisSystemContext';
import { useAxisSystemContext } from '../vis/shared/AxisSystemContext';
import { useCanvasEvents } from './hooks';
import type { CanvasEvent, ModifierKey, Selection } from './models';
import { boundPointToFOV, checkModifierKey } from './utils';

interface Props {
onSelectionStart?: () => void;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ModifierKey } from '../models';
import { useCanvasEvents, useZoomOnWheel } from './hooks';
import type { ModifierKey } from './models';

interface Props {
disabled?: boolean;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ModifierKey } from '../models';
import { useCanvasEvents, useZoomOnWheel } from './hooks';
import type { ModifierKey } from './models';

interface Props {
disabled?: boolean;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { ModifierKey } from '../models';
import { checkModifierKey } from '../utils';
import { useCanvasEvents, useZoomOnWheel } from './hooks';
import type { ModifierKey } from './models';
import { checkModifierKey } from './utils';

interface Props {
disabled?: boolean;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@ import { clamp } from 'lodash';
import { useCallback } from 'react';
import { Vector3 } from 'three';

import { useWheelCapture } from '../hooks';
import type { CanvasEvent, CanvasEventCallbacks } from '../models';
import { getCameraFOV } from '../utils';
import { useAxisSystemContext } from './AxisSystemContext';
import { useAxisSystemContext } from '../vis/shared/AxisSystemContext';
import { getCameraFOV } from '../vis/utils';
import type { CanvasEvent, CanvasEventCallbacks } from './models';

const ZOOM_FACTOR = 0.95;

Expand Down Expand Up @@ -43,6 +42,18 @@ export function useMoveCameraTo() {
);
}

function onWheel(evt: WheelEvent) {
evt.preventDefault();
}

function useWheelCapture() {
const { domElement } = useThree((state) => state.gl);

// Handler must be registed as non-passive for `preventDefault` to have an effect
// (React's `onWheel` prop registers handlers as passive)
useEventListener(domElement, 'wheel', onWheel, { passive: false });
}

export function useZoomOnWheel(
isZoomAllowed: (sourceEvent: WheelEvent) => { x: boolean; y: boolean },
disabled?: boolean
Expand Down
25 changes: 25 additions & 0 deletions packages/lib/src/interactions/models.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import type { Vector2, Vector3 } from 'three';

export type ModifierKey = 'Alt' | 'Control' | 'Shift';

export interface Selection {
startPoint: Vector2;
endPoint: Vector2;
}

export interface CanvasEvent<T extends PointerEvent | WheelEvent> {
unprojectedPoint: Vector3;
sourceEvent: T;
}

export interface CanvasEventCallbacks {
onPointerDown?: (evt: CanvasEvent<PointerEvent>) => void;
onPointerMove?: (evt: CanvasEvent<PointerEvent>) => void;
onPointerUp?: (evt: CanvasEvent<PointerEvent>) => void;
onWheel?: (evt: CanvasEvent<WheelEvent>) => void;
}

export interface Interaction {
shortcut: string;
description: string;
}
55 changes: 55 additions & 0 deletions packages/lib/src/interactions/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import type { Camera } from '@react-three/fiber';
import { clamp } from 'lodash';
import type { Vector3 } from 'three';
import { Vector2 } from 'three';

import { getCameraFOV } from '../vis/utils';
import type { ModifierKey } from './models';

export function boundPointToFOV(
unboundedPoint: Vector2 | Vector3,
camera: Camera
): Vector2 {
const { topRight, bottomLeft } = getCameraFOV(camera);
const boundedX = clamp(unboundedPoint.x, bottomLeft.x, topRight.x);
const boundedY = clamp(unboundedPoint.y, bottomLeft.y, topRight.y);
return new Vector2(boundedX, boundedY);
}

export function checkModifierKey(
modifierKey: ModifierKey | undefined,
event: MouseEvent | KeyboardEvent
) {
if (!modifierKey) {
return !event.altKey && !event.ctrlKey && !event.shiftKey;
}

return event.getModifierState(modifierKey);
}

export function getRatioEndPoint(
startPoint: Vector2,
endPoint: Vector2,
ratio: number
) {
const widthSign = Math.sign(endPoint.x - startPoint.x);
const width = Math.abs(endPoint.x - startPoint.x);

const heightSign = Math.sign(endPoint.y - startPoint.y);
const height = Math.abs(endPoint.y - startPoint.y);

const originalRatio =
Math.abs(endPoint.x - startPoint.x) / Math.abs(endPoint.y - startPoint.y);

if (originalRatio < ratio) {
return new Vector2(
startPoint.x + widthSign * height * ratio,
startPoint.y + heightSign * height
);
}

return new Vector2(
startPoint.x + widthSign * width,
startPoint.y + (heightSign * width) / ratio
);
}
2 changes: 1 addition & 1 deletion packages/lib/src/toolbar/Toolbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { useMap, useMeasure } from '@react-hookz/web';
import type { ReactElement, ReactNode } from 'react';
import flattenChildren from 'react-keyed-flatten-children';

import type { Interaction } from '../vis/models';
import type { Interaction } from '../interactions/models';
import MeasuredControl from './MeasuredControl';
import OverflowMenu from './OverflowMenu';
import Separator from './Separator';
Expand Down
2 changes: 1 addition & 1 deletion packages/lib/src/toolbar/controls/InteractionHelp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useClickOutside, useToggle } from '@react-hookz/web';
import { useRef } from 'react';
import { FiHelpCircle } from 'react-icons/fi';

import type { Interaction } from '../../vis/models';
import type { Interaction } from '../../interactions/models';
import styles from './InteractionHelp.module.css';
import ToggleBtn from './ToggleBtn';

Expand Down
8 changes: 4 additions & 4 deletions packages/lib/src/vis/heatmap/HeatmapVis.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ import type { NdArray } from 'ndarray';
import type { ReactElement, ReactNode } from 'react';

import { XAxisZoom, YAxisZoom } from '../..';
import Pan from '../../interactions/Pan';
import ResetZoomButton from '../../interactions/ResetZoomButton';
import SelectToZoom from '../../interactions/SelectToZoom';
import Zoom from '../../interactions/Zoom';
import { useAxisDomain, useValueToIndexScale } from '../hooks';
import type { AxisParams, VisScaleType } from '../models';
import Pan from '../shared/Pan';
import ResetZoomButton from '../shared/ResetZoomButton';
import SelectToZoom from '../shared/SelectToZoom';
import TooltipMesh from '../shared/TooltipMesh';
import VisCanvas from '../shared/VisCanvas';
import Zoom from '../shared/Zoom';
import { DEFAULT_DOMAIN, formatNumType } from '../utils';
import ColorBar from './ColorBar';
import HeatmapMesh from './HeatmapMesh';
Expand Down
Loading

0 comments on commit 5493f69

Please sign in to comment.