Skip to content
Open
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import React, {lazy, Suspense} from 'react';
import {PersistedProps, PersistenceTypes, DateRangeSliderProps} from '../types';
import dateRangeSlider from '../utils/LazyLoader/dateRangeSlider';

import './css/datesliders.css';

const RealDateRangeSlider = lazy(dateRangeSlider);

/**
* A date range slider component.
* Used for specifying a range of dates with optional disabled date indicators
* and calendar-aware stepping.
*/
export default function DateRangeSlider({
updatemode = 'mouseup',
// eslint-disable-next-line @typescript-eslint/no-unused-vars
persisted_props = [PersistedProps.value],
// eslint-disable-next-line @typescript-eslint/no-unused-vars
persistence_type = PersistenceTypes.local,
// eslint-disable-next-line no-magic-numbers
verticalHeight = 400,
allow_direct_input = true,
disabled_dates_indicator = true,
...props
}: DateRangeSliderProps) {

Check warning on line 25 in components/dash-core-components/src/components/DateRangeSlider.tsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Mark the props of the component as read-only.

See more on https://sonarcloud.io/project/issues?id=plotly_dash&issues=AZ55VHnoEMqJBb_Rbb9N&open=AZ55VHnoEMqJBb_Rbb9N&pullRequest=3802
return (
<Suspense fallback={null}>
<RealDateRangeSlider
updatemode={updatemode}
verticalHeight={verticalHeight}
allow_direct_input={allow_direct_input}
disabled_dates_indicator={disabled_dates_indicator}
{...props}
/>
</Suspense>
);
}

DateRangeSlider.dashPersistence = {
persisted_props: [PersistedProps.value],
persistence_type: PersistenceTypes.local,
};
163 changes: 163 additions & 0 deletions components/dash-core-components/src/components/DateSlider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
import React, {
lazy,
Suspense,
useCallback,
useMemo,
useRef,
useState,
} from 'react';
import {omit} from 'ramda';
import DatePickerSingle from '../components/DatePickerSingle';
import {
PersistedProps,
PersistenceTypes,
DateSliderProps,
DateRangeSliderProps,
} from '../types';
import {
strAsDate,
snapToValidDate,

Check warning on line 19 in components/dash-core-components/src/components/DateSlider.tsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this unused import of 'snapToValidDate'.

See more on https://sonarcloud.io/project/issues?id=plotly_dash&issues=AZ7r8r8RG0KwB-63oaxa&open=AZ7r8r8RG0KwB-63oaxa&pullRequest=3802

Check warning on line 19 in components/dash-core-components/src/components/DateSlider.tsx

View workflow job for this annotation

GitHub Actions / DCC Lint Tests (Python 3.8)

'snapToValidDate' is defined but never used

Check warning on line 19 in components/dash-core-components/src/components/DateSlider.tsx

View workflow job for this annotation

GitHub Actions / DCC Lint Tests (Python 3.12)

'snapToValidDate' is defined but never used
dateAsStr,

Check warning on line 20 in components/dash-core-components/src/components/DateSlider.tsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this unused import of 'dateAsStr'.

See more on https://sonarcloud.io/project/issues?id=plotly_dash&issues=AZ7r8r8RG0KwB-63oaxb&open=AZ7r8r8RG0KwB-63oaxb&pullRequest=3802

Check warning on line 20 in components/dash-core-components/src/components/DateSlider.tsx

View workflow job for this annotation

GitHub Actions / DCC Lint Tests (Python 3.8)

'dateAsStr' is defined but never used

Check warning on line 20 in components/dash-core-components/src/components/DateSlider.tsx

View workflow job for this annotation

GitHub Actions / DCC Lint Tests (Python 3.12)

'dateAsStr' is defined but never used
snapToStep,
} from '../utils/calendar/helpers';
import dateRangeSlider from '../utils/LazyLoader/dateRangeSlider';
import './css/datesliders.css';

const RealSlider = lazy(dateRangeSlider);

/**
* A slider component for selecting a single date.
* This is a wrapper around DateRangeSlider that handles date values.
*/
export default function DateSlider({
updatemode = 'mouseup',
// eslint-disable-next-line @typescript-eslint/no-unused-vars
persisted_props = [PersistedProps.value],
// eslint-disable-next-line @typescript-eslint/no-unused-vars
persistence_type = PersistenceTypes.local,
// eslint-disable-next-line no-magic-numbers
verticalHeight = 400,
allow_direct_input = true,
setProps,
value,
drag_value,
id,
vertical = false,
min,
max,
display_format,
...props
}: DateSliderProps) {

Check warning on line 50 in components/dash-core-components/src/components/DateSlider.tsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Mark the props of the component as read-only.

See more on https://sonarcloud.io/project/issues?id=plotly_dash&issues=AZ55VHkpEMqJBb_Rbb9M&open=AZ55VHkpEMqJBb_Rbb9M&pullRequest=3802
const [resetKey, setResetKey] = useState(0);
const containerRef = useRef<HTMLDivElement>(null);

// Convert single date value to array for DateRangeSlider
const mappedValue: DateRangeSliderProps['value'] = useMemo(() => {
return value ? [value] : value;
}, [value]);

// Convert single date drag value to array for DateRangeSlider
const mappedDragValue: DateRangeSliderProps['drag_value'] = useMemo(() => {
return drag_value ? [drag_value] : undefined;
}, [drag_value]);

const mappedSetProps: DateRangeSliderProps['setProps'] = useCallback(
newProps => {
const {value, drag_value} = newProps;
const mappedProps: Partial<DateSliderProps> = omit(
['value', 'drag_value', 'setProps'],
newProps
);
if ('value' in newProps) {
mappedProps.value = value ? value[0] : value;
}
if ('drag_value' in newProps) {
mappedProps.drag_value = drag_value
? drag_value[0]
: drag_value;
}
setProps(mappedProps);
},
[setProps]
);

const handleDateInputChange = useCallback(
(dateStr: `${string}-${string}-${string}` | undefined) => {
if (!dateStr) {
setProps({
value:
(min as `${string}-${string}-${string}`) ?? undefined,
});
return;
}

const inputDate = strAsDate(dateStr);
if (inputDate && props.step && props.step_unit) {
const parsedMin = strAsDate(min);
const snapped = snapToStep(
inputDate,
parsedMin ?? inputDate,
props.step,
props.step_unit
);
if (snapped.getTime() !== inputDate.getTime()) {
setResetKey(k => k + 1); // rejeitar
return;
}
}

const hasNoChange = value === dateStr;
if (hasNoChange) {
setResetKey(k => k + 1);
} else {
setProps({value: dateStr});
}
},
[value, setProps, min, props.step, props.step_unit]
);

return (
<div
ref={containerRef}
className="date-slider-container"
data-vertical={vertical}
>
<div className="dash-slider-wrapper">
<Suspense fallback={null}>
<RealSlider
key={resetKey}
id={id}
updatemode={updatemode}
verticalHeight={verticalHeight}
allow_direct_input={false}
vertical={vertical}
min={min}
max={max}
display_format={display_format}
value={mappedValue}
drag_value={mappedDragValue}
setProps={mappedSetProps}
{...props}
/>
</Suspense>
</div>
{allow_direct_input && (
<div className="dash-range-slider-min-input">
<DatePickerSingle
key={`date-input-${resetKey}`}
date={value ?? undefined}
setProps={({date}) => handleDateInputChange(date)}
min_date_allowed={min}
max_date_allowed={max}
display_format={display_format}
/>
</div>
)}
</div>
);
}

DateSlider.dashPersistence = {
persisted_props: [PersistedProps.value],
persistence_type: PersistenceTypes.local,
};
132 changes: 132 additions & 0 deletions components/dash-core-components/src/components/css/datesliders.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
.date-slider-container,
.date-range-slider-container {
display: flex;
align-items: center;
gap: 10px;
width: 100%;
container-type: inline-size;
}

.date-slider-container[data-vertical='true'],
.date-range-slider-container[data-vertical='true'] {
flex-direction: column;
align-items: stretch;
}

.dash-range-slider-max-input {
order: 1;
max-width: 140px;
}

.dash-range-slider-min-input {
text-align: center;
max-width: 140px;
}

.dash-slider-wrapper {
flex: 1;
min-width: 0;
width: 100%;
}

.dash-date-range-slider-wrapper {
position: relative;
flex: 1;
padding: 0 28px;
box-sizing: border-box;
min-width: 0;
width: 100%;
}

/* Slider */
@container (max-width: 500px) {
.date-slider-container[data-vertical='false'] .dash-range-slider-min-input {
display: none !important;
}
}

@container (max-width: 130px) {
.date-slider-container[data-vertical='true'] .dash-range-slider-min-input {
display: none !important;
}
}

/* Range Slider */
@container (max-width: 500px) {
.date-range-slider-container[data-vertical='false'] .dash-range-slider-min-input,
.date-range-slider-container[data-vertical='false'] .dash-range-slider-max-input {
display: none !important;
}
}

@container (max-width: 130px) {
.date-range-slider-container[data-vertical='true'] .dash-range-slider-min-input,
.date-range-slider-container[data-vertical='true'] .dash-range-slider-max-input {
display: none !important;
}
}

.dash-slider-tooltip {
display: none;
position: absolute;
border-radius: var(--Dash-Spacing);
padding: calc(var(--Dash-Spacing) * 3);
font-size: 12px;
line-height: 1;
box-shadow: 0 0 8px var(--Dash-Shading-Strong);
background-color: var(--Dash-Fill-Inverse-Strong);
user-select: none;
z-index: 1000;
fill: var(--Dash-Fill-Inverse-Strong);
white-space: nowrap;
}

.dash-slider-mark {
position: absolute;
font-size: 12px;
height: 12px;
line-height: 12px;
color: var(--Dash-Text-Strong);
white-space: nowrap;
pointer-events: none;
z-index: 10;
transform: translateX(
max(-50%, calc(0px - var(--dash-mark-offset, 0px)))

Check failure on line 94 in components/dash-core-components/src/components/css/datesliders.css

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Expected single space before "-" operator

See more on https://sonarcloud.io/project/issues?id=plotly_dash&issues=AZ7iF2jYFY5xOnvnN0oq&open=AZ7iF2jYFY5xOnvnN0oq&pullRequest=3802
);
}

.dash-slider-disabled-ranges-container {
position: absolute;
inset: 0;
top: 12%;
left: 34px;
width: calc(100% - 62px);
height: 4px;
pointer-events: none;
z-index: -1;
}

.dash-slider-disabled-ranges-container.vertical {
top: 0;
left: 40px;
width: 4px;
height: calc(100% - 5px);
transform: translateY(5px);
}

.dash-slider-disabled-range {
position: absolute;
background: repeating-linear-gradient(
-45deg,
#dc2626 0px,
#dc2626 2.5px,
transparent 2px,
transparent 5px
);
opacity: 1;
height: 100%;
}

.dash-datepicker {
max-width: 130px;
}
Original file line number Diff line number Diff line change
Expand Up @@ -258,4 +258,4 @@
.dash-slider-container .dash-range-slider-max-input {
display: none;
}
}
}
Loading
Loading