Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/npm-publish.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,17 @@ jobs:

steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v5

- uses: pnpm/action-setup@v4
with:
run_install: |
args: [ --force ]

- name: Setup node
uses: actions/setup-node@v4
uses: actions/setup-node@v6
with:
node-version: '20.x'
node-version: '24'
registry-url: https://registry.npmjs.org/
scope: '@diamondlightsource'
cache: pnpm
Expand Down
8 changes: 4 additions & 4 deletions client/component/src/AxisConfigModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ interface AxisConfigModalProps<S extends ScaleType> {
domain?: Domain;
/** The custom domain for the axis (optional) */
customDomain?: CustomDomain;
/** Histogram params */
histogram?: HistogramParams;
/** Histogram params getter */
histogramGetter?: () => HistogramParams;
/** The function to call when the custom domain is updated (optional) */
setCustomDomain?: (value: CustomDomain) => void;
/** Point size for scatter plot (optional) */
Expand Down Expand Up @@ -106,15 +106,15 @@ function AxisConfigModal<S extends ScaleType>(
);

const domainSelector = props.domain &&
props.histogram &&
props.histogramGetter &&
props.customDomain &&
props.setCustomDomain && (
<DomainConfig
dataDomain={props.domain}
customDomain={props.customDomain}
scaleType={props.scaleType as ColorScaleType | undefined}
onCustomDomainChange={props.setCustomDomain}
histogram={props.histogram}
histogramGetter={props.histogramGetter}
/>
);

Expand Down
9 changes: 7 additions & 2 deletions client/component/src/DomainConfig.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ interface DomainConfigProps {
/** Handles custom domain change */
onCustomDomainChange: (domain: CustomDomain) => void;
/** Histogram params */
histogram?: HistogramParams;
histogramGetter?: () => HistogramParams;
}

/**
Expand All @@ -83,11 +83,16 @@ interface DomainConfigProps {
*/
function DomainConfig(props: DomainConfigProps) {
const { dataDomain, customDomain, scaleType } = props;
const { onCustomDomainChange, histogram } = props;
const { onCustomDomainChange, histogramGetter } = props;
const [lockDomain, setLockDomain] = useState<boolean>(false);

const visDomain = useVisDomain(customDomain, dataDomain);

const histogram = useMemo(
() => histogramGetter && histogramGetter(),
[histogramGetter]
);

const memoizedCustomDomain = useMemo(() => {
if (lockDomain) {
return customDomain;
Expand Down
25 changes: 9 additions & 16 deletions client/component/src/HeatmapPlot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
} from '@h5web/lib';

import {
calculateHistogramCounts,
createHistogramParams,
createInteractionsConfig,
InteractionModeType,
} from './utils';
Expand All @@ -20,7 +20,7 @@ import {
usePlotCustomizationContext,
} from './PlotCustomizationContext';
import { AnyToolbar } from './PlotToolbar';
import { useEffect, useMemo } from 'react';
import { useEffect } from 'react';

interface Props {
xValues?: NDT;
Expand All @@ -38,6 +38,7 @@ export function HeatmapVisCanvas({ xValues, yValues, values }: Props) {
aspect,
batonProps,
canSelect,
selectionMax,
selectionType,
updateSelection,
selections,
Expand All @@ -46,24 +47,15 @@ export function HeatmapVisCanvas({ xValues, yValues, values }: Props) {
colourMap,
invertColourMap,
dScaleType,
setHistogram,
updateHistogramGetter,
} = usePlotCustomizationContext();
const interactionsConfig = createInteractionsConfig(mode);

const histogram = useMemo(
() => calculateHistogramCounts(values.data, dDomain),
[dDomain, values]
);

useEffect(() => {
if (histogram) {
setHistogram({
...histogram,
colorMap: colourMap,
invertColorMap: invertColourMap,
});
}
}, [colourMap, invertColourMap, histogram, setHistogram]);
const hg = () =>
createHistogramParams(values.data, dDomain, colourMap, invertColourMap);
updateHistogramGetter(hg);
}, [values.data, dDomain, colourMap, invertColourMap, updateHistogramGetter]);

return (
<HeatmapVis
Expand All @@ -90,6 +82,7 @@ export function HeatmapVisCanvas({ xValues, yValues, values }: Props) {
<SelectionComponent
modifierKey={[] as ModifierKey[]}
disabled={mode !== InteractionModeType.selectRegion}
selectionMax={selectionMax}
selectionType={selectionType}
batonProps={batonProps}
updateSelection={updateSelection}
Expand Down
2 changes: 2 additions & 0 deletions client/component/src/ImagePlot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export function ImageVisCanvas({ xValues, yValues, values }: Props) {
aspect,
batonProps,
canSelect,
selectionMax,
selectionType,
updateSelection,
selections,
Expand Down Expand Up @@ -56,6 +57,7 @@ export function ImageVisCanvas({ xValues, yValues, values }: Props) {
<SelectionComponent
modifierKey={[] as ModifierKey[]}
disabled={mode !== InteractionModeType.selectRegion}
selectionMax={selectionMax}
selectionType={selectionType}
batonProps={batonProps}
updateSelection={updateSelection}
Expand Down
37 changes: 21 additions & 16 deletions client/component/src/InteractionModeToggle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ interface InteractionModeToggleProps {
onModeChange: (value: InteractionModeType) => void;
/** If client holds baton */
hasBaton: boolean;
canSelect: boolean;
}

/**
Expand All @@ -24,7 +25,7 @@ interface InteractionModeToggleProps {
* @returns {JSX.Element} The rendered component.
*/
function InteractionModeToggle(props: InteractionModeToggleProps) {
const { value, onModeChange, hasBaton } = props;
const { value, onModeChange, hasBaton, canSelect } = props;

useEffect(() => {
if (!hasBaton && value === InteractionModeType.selectRegion) {
Expand Down Expand Up @@ -54,21 +55,25 @@ function InteractionModeToggle(props: InteractionModeToggleProps) {
icon={TbZoomInArea as IIconType}
value={InteractionModeType.selectToZoom}
/>
<div // wrapper hack to add tooltip (note corners are not correctly drawn for this last child)
style={{
pointerEvents: hasBaton ? 'inherit' : 'auto',
display: 'inline-flex',
}}
title={hasBaton ? '' : 'need baton'}
>
<ToggleGroup.Btn
label="select region"
iconOnly
icon={IoShapesOutline as IIconType}
value={InteractionModeType.selectRegion}
disabled={!hasBaton}
/>
</div>
{canSelect ? (
<div // wrapper hack to add tooltip (note corners are not correctly drawn for this last child)
style={{
pointerEvents: hasBaton ? 'inherit' : 'auto',
display: 'inline-flex',
}}
title={hasBaton ? '' : 'need baton'}
>
<ToggleGroup.Btn
label="select region"
iconOnly
icon={IoShapesOutline as IIconType}
value={InteractionModeType.selectRegion}
disabled={!hasBaton}
/>
</div>
) : (
<></>
)}
</ToggleGroup>
</>
);
Expand Down
2 changes: 2 additions & 0 deletions client/component/src/LinePlot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ export function LineVisCanvas(props: Props) {
setCurrentLineKey,
batonProps,
canSelect,
selectionMax,
selectionType,
updateSelection,
selections,
Expand Down Expand Up @@ -213,6 +214,7 @@ export function LineVisCanvas(props: Props) {
modifierKey={[] as ModifierKey[]}
batonProps={batonProps}
disabled={mode !== InteractionModeType.selectRegion}
selectionMax={selectionMax}
selectionType={selectionType}
updateSelection={updateSelection}
selections={selections}
Expand Down
70 changes: 58 additions & 12 deletions client/component/src/PlotCustomizationContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,16 @@ import {

import { defaultBatonProps, type BatonProps } from './models';
import { InteractionModeType } from './utils';
import type { SelectionBase, SelectionHandler } from './selections/utils';
import { SelectionType, useSelections } from './selections/utils';
import type {
SelectionBase,
SelectionHandler,
SelectionOptions,
} from './selections/utils';
import {
SelectionType,
toSelectionType,
useSelections,
} from './selections/utils';
import { LineParams, LinePlotCustomizationProps } from './LinePlot';
import { ImagePlotCustomizationProps } from './ImagePlot';
import { HeatmapPlotCustomizationProps } from './HeatmapPlot';
Expand Down Expand Up @@ -84,6 +92,8 @@ export interface PlotCustomizationContextValue {
aspect: Aspect;
/** A function that sets the aspect value */
setAspect: (a: Aspect) => void;
/** Selection upper limit (on current type) */
selectionMax: number;
/** A selection type */
selectionType: SelectionType;
/** A function that sets the selection type */
Expand All @@ -106,6 +116,8 @@ export interface PlotCustomizationContextValue {
invertColourMap: boolean;
/** A function that toggles the color map inversion */
toggleInvertColourMap: () => void;
/** Selection options */
selectionOptions?: SelectionOptions;
/** Selections */
selections: SelectionBase[];
/** A function that sets the selections */
Expand All @@ -130,10 +142,11 @@ export interface PlotCustomizationContextValue {
showPoints: boolean;
/** A function that toggles the points */
toggleShowPoints: () => void;
/** Histogram params */
histogram?: HistogramParams;
/** Set heatmap histogram */
setHistogram: (histogram: HistogramParams) => void;
/** Get heatmap histogram */
histogramGetter?: () => HistogramParams;
/** Update heatmap histogram getter */
updateHistogramGetter: (getter: () => HistogramParams) => void;

/** Can select */
canSelect: boolean;
/** Type of plot */
Expand Down Expand Up @@ -170,8 +183,9 @@ export function PlotCustomizationContextProvider(
InteractionModeType.panAndWheelZoom
);
const [selectionType, setSelectionType] = useState<SelectionType>(
SelectionType.line
SelectionType.unknown
);
const [selectionMax, setSelectionMax] = useState<number>(0);
const [xCustomDomain, setXCustomDomain] = useState<CustomDomain>([
null,
null,
Expand Down Expand Up @@ -200,9 +214,15 @@ export function PlotCustomizationContextProvider(
new Map()
);
const [currentLineKey, setCurrentLineKey] = useState<string | null>(null);
const [histogram, setHistogram] = useState<HistogramParams>();
const [histogramGetter, setHistogramGetter] =
useState<() => HistogramParams>();
const [scatterPointSize, setScatterPointSize] = useState<number>(10);

const updateHistogramGetter = useCallback(
(g: () => HistogramParams) => setHistogramGetter(() => g),
[setHistogramGetter]
);

useEffect(() => {
if (props.plotConfig.title) setTitle(props.plotConfig.title);
}, [props.plotConfig.title, setTitle]);
Expand All @@ -218,6 +238,26 @@ export function PlotCustomizationContextProvider(
useEffect(() => {
if (props.plotConfig.yScale) setYScaleType(props.plotConfig.yScale);
}, [props.plotConfig.yScale, setYScaleType]);
useEffect(() => {
const entries = Object.entries(props.selectionOptions ?? {});
const [k, v] = entries[0] ?? [];
if (k !== undefined && v !== undefined) {
setSelectionType(toSelectionType(k));
setSelectionMax(v);
}
}, [props.selectionOptions, setSelectionType, setSelectionMax]);

const newSetSelectionType = useCallback(
(t: SelectionType) => {
setSelectionType(t);
const selectionOptions = props.selectionOptions ?? {};
const m = selectionOptions[t];
if (m !== undefined) {
setSelectionMax(m);
}
},
[setSelectionType, setSelectionMax, props.selectionOptions]
);

const batonProps = useMemo(
() => props.batonProps ?? defaultBatonProps,
Expand Down Expand Up @@ -333,9 +373,12 @@ export function PlotCustomizationContextProvider(
dDomain,
dCustomDomain,
setDCustomDomain,
selectionOptions: props.selectionOptions,
selectionMax,
selectionType,
setSelectionType,
setHistogram,
setSelectionType: newSetSelectionType,
histogramGetter,
updateHistogramGetter,
selections,
setSelections,
updateSelection: newUpdateSelection,
Expand All @@ -352,7 +395,6 @@ export function PlotCustomizationContextProvider(
setColourMap,
invertColourMap,
toggleInvertColourMap,
histogram,
scatterPointSize,
setScatterPointSize,
showPoints,
Expand All @@ -370,12 +412,16 @@ export function PlotCustomizationContextProvider(
dCustomDomain,
dDomain,
dScaleType,
histogram,
histogramGetter,
updateHistogramGetter,
invertColourMap,
mode,
newUpdateSelection,
newSetSelectionType,
plotType,
props.selectionOptions,
scatterPointSize,
selectionMax,
selectionType,
selections,
setSelections,
Expand Down
Loading