Skip to content

Commit

Permalink
- Default stepping value for time-slider to 1 day;
Browse files Browse the repository at this point in the history
- New style on the active thumb to visually indicate that it's selected and can be moved by keyboard;
- Small style change on the label (make it a bit smaller);
- Renaming 'onValueDisplay' to 'onValueLabelFormat' to better align with 'onValueLabelFormat' that comes from Material UI and to better distinguish from 'valueLabelDisplay' (from Material UI) which has different meaning
- Disable thumb swapping and label spreading when more than 2 thumbs now native in the GeoView Slider component
  • Loading branch information
Alex-NRCan committed Oct 2, 2024
1 parent f662569 commit 3336eb9
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -166,10 +166,18 @@ export class TimeSliderEventProcessor extends AbstractEventProcessor {
? [new Date(temporalDimensionInfo.default[0]).getTime(), new Date(temporalDimensionInfo.default[1]).getTime()]
: [...minAndMax];

// If using discrete axis
let step: number | undefined;
if (nearestValues === 'discrete') {
// Try to guess the steps that should be used
step = TimeSliderEventProcessor.guessEstimatedStep(minAndMax[0], minAndMax[1]);
}

return {
range,
defaultValue,
discreteValues: nearestValues === 'discrete',
step,
minAndMax,
field,
fieldAlias,
Expand All @@ -182,6 +190,28 @@ export class TimeSliderEventProcessor extends AbstractEventProcessor {
};
}

/**
* Guesses the estimated steps that should be used by the slider, depending on the value range
* @param {number} minValue - The minimum value
* @param {number} maxValue - The maximum value
* @returns The estimated stepping value based on the min and max values
*/
static guessEstimatedStep(minValue: number, maxValue: number): number | undefined {
const day1 = 86400000; // 24h x 60m x 60s x 1000ms = 86,400,000ms in a day
const month1 = day1 * 30; // 2,592,000,000ms in 1 month
const year1 = day1 * 365; // 31,536,000,000ms in 1 year
const years2 = year1 * 2; // 63,072,000,000ms in 2 years
const years10 = year1 * 10; // 63,072,000,000ms in 2 years
const months2 = month1 * 2; // 315,360,000,000 in 10 years
const intervalDiff = maxValue - minValue;

let step: number | undefined;
if (intervalDiff > months2) step = day1; // Daily stepping
if (intervalDiff > years2) step = month1; // Monthly stepping
if (intervalDiff > years10) step = year1; // Yearly stepping
return step;
}

/**
* Sets the selected layer path
* @param {string} mapId - The map id of the state to act on
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ export interface TypeTimeSliderValues {
delay: number;
description?: string;
discreteValues: boolean;
step?: number;
field: string;
fieldAlias: string;
filtering: boolean;
Expand Down
19 changes: 19 additions & 0 deletions packages/geoview-core/src/ui/slider/slider-style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,25 @@ export const getSxClasses = (theme: Theme): any => ({
height: 30,
},
},
'& .MuiSlider-thumb:hover, .MuiSlider-thumb.Mui-focusVisible': {
boxShadow: 'rgba(1, 0, 155, 0.7) 0px 0px 0px 3px !important',
},
'& .MuiSlider-valueLabel': {
fontSize: '0.7rem',
padding: '0.25rem 0.4rem',
},
'&.MuiSlider-labelSpread .MuiSlider-thumb:nth-last-of-type(2) .MuiSlider-valueLabel.MuiSlider-valueLabelOpen': {
transform: 'translateX(-42%) translateY(-100%) scale(1)',
'&:before': {
left: 'calc(100% - 6px)',
},
},
'&.MuiSlider-labelSpread .MuiSlider-thumb:last-of-type .MuiSlider-valueLabel.MuiSlider-valueLabelOpen': {
transform: 'translateX(42%) translateY(-100%) scale(1)',
'&:before': {
left: '6px',
},
},
'& .MuiSlider-rail': {
opacity: 0.35,
color: theme.palette.geoViewColor?.grey.darken(0.9, 0.87),
Expand Down
31 changes: 14 additions & 17 deletions packages/geoview-core/src/ui/slider/slider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ type SliderProps = {
// custom onChange callback
onChange?: (value: number | number[], activeThumb: number) => void;
onChangeCommitted?: (value: number | number[]) => void;
onValueDisplay?: (value: number, index: number) => string;
onValueLabelFormat?: (value: number, index: number) => string;
onValueDisplayAriaLabel?: (value: number, index: number) => string;

// MUI optional props
Expand All @@ -51,7 +51,7 @@ type SliderProps = {
* @returns {JSX.Element} the created Slider element
*/
export function Slider(props: SliderProps): JSX.Element {
const { value: parentValue, min, max, onChange, onChangeCommitted, onValueDisplay, onValueDisplayAriaLabel, ...properties } = props;
const { value: parentValue, min, max, onChange, onChangeCommitted, onValueLabelFormat, onValueDisplayAriaLabel, ...properties } = props;
const theme = useTheme();
const sxClasses = getSxClasses(theme);

Expand All @@ -61,6 +61,12 @@ export function Slider(props: SliderProps): JSX.Element {
const [value, setValue] = useState<number[] | number>(parentValue);
const [activeThumb, setActiveThumb] = useState<number>(-1);

// If spreading the label using an offset
if (Array.isArray(value) && value.length >= 2 && (!properties.orientation || properties.orientation === 'horizontal')) {
// Dynamically add a class name to the className properties
properties.className = properties.className ? `${properties.className} MuiSlider-labelSpread` : 'MuiSlider-labelSpread';
}

// handle constant change on the slider to set active thumb and instant values
const handleChange = (event: React.SyntheticEvent | Event, newValue: number | number[], newActiveThumb: number): void => {
// Update the internal state
Expand Down Expand Up @@ -185,26 +191,17 @@ export function Slider(props: SliderProps): JSX.Element {
<MaterialSlider
{...properties}
id={containerId}
sx={{ ...(!properties.className ? sxClasses.slider : {}) }}
className={properties.className !== undefined ? properties.className : ''}
style={properties.style}
aria-labelledby={properties.ariaLabelledby}
sx={sxClasses.slider}
value={value}
min={min}
max={max}
disabled={properties.disabled}
marks={properties.marks}
track={properties.track}
orientation={properties.orientation}
step={properties.step}
size={properties.size}
disableSwap={false}
valueLabelDisplay="auto"
onChange={handleChange}
onChangeCommitted={handleChangeCommitted}
valueLabelFormat={onValueDisplay}
disableSwap
valueLabelDisplay="on"
valueLabelFormat={onValueLabelFormat}
getAriaLabel={(): string => 'To implement with translation'}
getAriaValueText={onValueDisplayAriaLabel}
onChange={handleChange}
onChangeCommitted={handleChangeCommitted}
/>
);
}
5 changes: 3 additions & 2 deletions packages/geoview-time-slider/src/time-slider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ export function TimeSlider(props: TimeSliderProps): JSX.Element {
description,
defaultValue,
discreteValues,
step,
range,
minAndMax,
field,
Expand Down Expand Up @@ -408,9 +409,9 @@ export function TimeSlider(props: TimeSliderProps): JSX.Element {
max={minAndMax[1]}
value={values}
marks={sliderMarks}
step={!discreteValues ? null : 0.1}
step={discreteValues ? step || 0.1 : null}
onChangeCommitted={handleSliderChange}
onValueDisplay={handleLabelFormat}
onValueLabelFormat={handleLabelFormat}
/>
</div>
</Grid>
Expand Down

0 comments on commit 3336eb9

Please sign in to comment.