Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
mj12albert committed Dec 25, 2024
1 parent ea9c877 commit 9e8b591
Show file tree
Hide file tree
Showing 18 changed files with 327 additions and 164 deletions.
1 change: 0 additions & 1 deletion packages/react/src/slider/control/SliderControl.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ const testRootContext: SliderRootContext = {
dirty: false,
touched: false,
},
percentageValues: [0],
registerSliderControl: NOOP,
setActive: NOOP,
setDragging: NOOP,
Expand Down
14 changes: 7 additions & 7 deletions packages/react/src/slider/control/SliderControl.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,32 +24,32 @@ const SliderControl = React.forwardRef(function SliderControl(
disabled,
dragging,
getFingerState,
setValue,
minStepsBetweenValues,
minimumAdjacentDifference,
onValueCommitted,
state,
percentageValues,
registerSliderControl,
setActive,
setDragging,
setValue,
state,
step,
thumbRefs,
values,
} = useSliderRootContext();

const { getRootProps } = useSliderControl({
disabled,
dragging,
getFingerState,
setValue,
minStepsBetweenValues,
minimumAdjacentDifference,
onValueCommitted,
percentageValues,
registerSliderControl,
rootRef: forwardedRef,
setActive,
setDragging,
setValue,
step,
thumbRefs,
values,
});

const { renderElement } = useComponentRenderer({
Expand Down
23 changes: 11 additions & 12 deletions packages/react/src/slider/control/useSliderControl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ export function useSliderControl(
getFingerState,
setValue,
onValueCommitted,
minStepsBetweenValues,
percentageValues,
minimumAdjacentDifference,
values,
registerSliderControl,
rootRef: externalRef,
setActive,
Expand Down Expand Up @@ -68,19 +68,19 @@ export function useSliderControl(
}

const finger = getFingerState(fingerPosition, false, offsetRef.current);

// console.log(finger);
if (finger == null) {
return;
}

focusThumb(finger.closestThumbIndex, controlRef, setActive);

if (validateMinimumDistance(finger.value, step, minStepsBetweenValues)) {
if (validateMinimumDistance(finger.valueUnwrapped, minimumAdjacentDifference)) {
if (!dragging && moveCountRef.current > INTENTIONAL_DRAG_COUNT_THRESHOLD) {
setDragging(true);
}

setValue(finger.value, finger.closestThumbIndex, nativeEvent);
setValue(finger.percentageValue, finger.closestThumbIndex, nativeEvent);
}
});

Expand Down Expand Up @@ -132,7 +132,7 @@ export function useSliderControl(

focusThumb(finger.closestThumbIndex, controlRef, setActive);

setValue(finger.value, finger.closestThumbIndex, nativeEvent);
setValue(finger.percentageValue, finger.closestThumbIndex, nativeEvent);
}

moveCountRef.current = 0;
Expand Down Expand Up @@ -211,12 +211,11 @@ export function useSliderControl(
if (thumbRefs.current.includes(event.target as HTMLElement)) {
const targetThumbIndex = (event.target as HTMLElement).getAttribute('data-index');

const offset =
percentageValues[Number(targetThumbIndex)] / 100 - finger.percentageValue;
const offset = values[Number(targetThumbIndex)] - finger.percentageValue;

offsetRef.current = offset;
} else {
setValue(finger.value, finger.closestThumbIndex, event.nativeEvent);
setValue(finger.percentageValue, finger.closestThumbIndex, event.nativeEvent);
}
}

Expand All @@ -235,7 +234,7 @@ export function useSliderControl(
handleTouchMove,
handleTouchEnd,
setValue,
percentageValues,
values,
setActive,
thumbRefs,
],
Expand All @@ -257,9 +256,9 @@ export namespace useSliderControl {
| 'dragging'
| 'getFingerState'
| 'setValue'
| 'minStepsBetweenValues'
| 'minimumAdjacentDifference'
| 'onValueCommitted'
| 'percentageValues'
| 'values'
| 'registerSliderControl'
| 'setActive'
| 'setDragging'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ const testRootContext: SliderRootContext = {
dirty: false,
touched: false,
},
percentageValues: [0],
registerSliderControl: NOOP,
setActive: NOOP,
setDragging: NOOP,
Expand Down
4 changes: 2 additions & 2 deletions packages/react/src/slider/indicator/SliderIndicator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@ const SliderIndicator = React.forwardRef(function SliderIndicator(
) {
const { render, className, ...otherProps } = props;

const { direction, disabled, orientation, state, percentageValues } = useSliderRootContext();
const { direction, disabled, orientation, state, values } = useSliderRootContext();

const { getRootProps } = useSliderIndicator({
direction,
disabled,
orientation,
percentageValues,
values,
});

const { renderElement } = useComponentRenderer({
Expand Down
17 changes: 7 additions & 10 deletions packages/react/src/slider/indicator/useSliderIndicator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,25 +25,25 @@ function getRangeStyles(orientation: useSliderRoot.Orientation, offset: number,
export function useSliderIndicator(
parameters: useSliderIndicator.Parameters,
): useSliderIndicator.ReturnValue {
const { orientation, percentageValues } = parameters;
const { orientation, values } = parameters;

let internalStyles;

if (percentageValues.length > 1) {
const trackOffset = percentageValues[0];
const trackLeap = percentageValues[percentageValues.length - 1] - trackOffset;
if (values.length > 1) {
const trackOffset = values[0] * 100;
const trackLeap = values[values.length - 1] * 100 - trackOffset;

internalStyles = getRangeStyles(orientation, trackOffset, trackLeap);
} else if (orientation === 'vertical') {
internalStyles = {
bottom: 0,
height: `${percentageValues[0]}%`,
height: `${values[0] * 100}%`,
width: 'inherit',
};
} else {
internalStyles = {
insetInlineStart: 0,
width: `${percentageValues[0]}%`,
width: `${values[0] * 100}%`,
height: 'inherit',
};
}
Expand All @@ -67,10 +67,7 @@ export function useSliderIndicator(

export namespace useSliderIndicator {
export interface Parameters
extends Pick<
useSliderRoot.ReturnValue,
'direction' | 'disabled' | 'orientation' | 'percentageValues'
> {}
extends Pick<useSliderRoot.ReturnValue, 'direction' | 'disabled' | 'orientation' | 'values'> {}

export interface ReturnValue {
getRootProps: (externalProps?: GenericHTMLProps) => GenericHTMLProps;
Expand Down
43 changes: 39 additions & 4 deletions packages/react/src/slider/root/SliderRoot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { NOOP } from '../../utils/noop';
import type { BaseUIComponentProps } from '../../utils/types';
import { useBaseUiId } from '../../utils/useBaseUiId';
import { useComponentRenderer } from '../../utils/useComponentRenderer';
import { valueToPercent } from '../../utils/valueToPercent';
import type { FieldRoot } from '../../field/root/FieldRoot';
import { CompositeList } from '../../composite/list/CompositeList';
import { useDirection } from '../../direction-provider/DirectionContext';
Expand All @@ -26,7 +27,7 @@ const SliderRoot = React.forwardRef(function SliderRoot(
const {
'aria-labelledby': ariaLabelledby,
className,
defaultValue,
defaultValue: defaultValueProp,
disabled: disabledProp = false,
id: idProp,
format,
Expand All @@ -41,7 +42,7 @@ const SliderRoot = React.forwardRef(function SliderRoot(
orientation = 'horizontal',
step = 1,
tabIndex: externalTabIndex,
value,
value: valueProp,
...otherProps
} = props;

Expand All @@ -51,6 +52,40 @@ const SliderRoot = React.forwardRef(function SliderRoot(
const { labelId, state: fieldState, disabled: fieldDisabled } = useFieldRootContext();
const disabled = fieldDisabled || disabledProp;

const defaultValue = React.useMemo(() => {
if (valueProp === undefined) {
if (Array.isArray(defaultValueProp)) {
const percentages = [];
for (let i = 0; i < defaultValueProp.length; i += 1) {
percentages.push(valueToPercent(defaultValueProp[i], min, max) / 100);
}
return percentages;
}
if (defaultValueProp !== undefined) {
return valueToPercent(defaultValueProp, min, max) / 100;
}
}

return undefined;
}, [defaultValueProp, valueProp, min, max]);

const value = React.useMemo(() => {
if (defaultValueProp === undefined) {
if (Array.isArray(valueProp)) {
const percentages = [];
for (let i = 0; i < valueProp.length; i += 1) {
percentages.push(valueToPercent(valueProp[i], min, max));
}
return percentages;
}
if (valueProp !== undefined) {
return valueToPercent(valueProp, min, max);
}
}

return undefined;
}, [defaultValueProp, valueProp, min, max]);

const { getRootProps, ...slider } = useSliderRoot({
'aria-labelledby': ariaLabelledby ?? labelId ?? '',
defaultValue,
Expand Down Expand Up @@ -182,7 +217,7 @@ export namespace SliderRoot {
*
* To render a controlled slider, use the `value` prop instead.
*/
defaultValue?: number | ReadonlyArray<number>;
defaultValue?: number | number[];
/**
* Whether the component should ignore user interaction.
* @default false
Expand All @@ -200,7 +235,7 @@ export namespace SliderRoot {
* The value of the slider.
* For ranged sliders, provide an array with two values.
*/
value?: number | ReadonlyArray<number>;
value?: number | number[];
}
}

Expand Down
Loading

0 comments on commit 9e8b591

Please sign in to comment.