Skip to content

Commit

Permalink
histogram: allow passing custom drag button via prop
Browse files Browse the repository at this point in the history
  • Loading branch information
zlatanpham committed Feb 15, 2019
1 parent 37e6c97 commit 0e9b988
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 25 deletions.
6 changes: 6 additions & 0 deletions src/components/HistogramSlider/HistogramSlider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ interface HistogramSliderProps {
| ((
props: { value: [number, number]; min: number; max: number }
) => JSX.Element);
/** Custom component for render drag button UI, pass `null` if you don't want to show the part */
ButtonRenderComponent?:
| null
| ((props: { focused?: boolean }) => JSX.Element);
/** Showing an `apply` & `reset` button if a function was passed to the prop*/
onApply?: (value: [number, number]) => void;
/** Callback function while the range changed */
Expand Down Expand Up @@ -150,6 +154,7 @@ export class HistogramSlider extends Component<
data,
widthPx,
InfoRenderComponent,
ButtonRenderComponent,
...rangeSliderProps
} = this.props;

Expand All @@ -176,6 +181,7 @@ export class HistogramSlider extends Component<
colors={this.props.colors!}
value={this.state.value}
onChange={this.handleSliderChange}
ButtonRenderComponent={ButtonRenderComponent}
/>

<div className={css({ marginTop: "20px" })}>
Expand Down
97 changes: 72 additions & 25 deletions src/components/HistogramSlider/RangeSlider/RangeSlider.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { Component } from "react";
import React, { Component, PureComponent } from "react";
import { css } from "emotion";

interface RangeSliderProps {
Expand All @@ -8,6 +8,9 @@ interface RangeSliderProps {
value: [number, number];
distance: number;
onChange: (value: [number, number]) => void;
ButtonRenderComponent?:
| null
| ((props: { focused?: boolean }) => JSX.Element);
colors: {
in: string;
out: string;
Expand Down Expand Up @@ -264,16 +267,23 @@ export class RangeSlider extends Component<RangeSliderProps> {
this.clearDocumentEvents();
}

preventDefaultClick = (e: React.MouseEvent<HTMLElement>) => {
e.preventDefault();
};

render() {
const range = this.getRange();
const {
min,
max,
colors,
value: [minState, maxState]
value: [minState, maxState],
ButtonRenderComponent
} = this.props;
const right = 100 - ((maxState - min) * 100) / range;
const left = ((minState - min) * 100) / range;
const ButtonInnerComponent =
ButtonRenderComponent || DefaultRenderButtonComponent;

return (
<div
Expand Down Expand Up @@ -310,57 +320,67 @@ export class RangeSlider extends Component<RangeSliderProps> {
<Button
className={css({
position: "absolute",
top: "-13px",
left: "-10px",
width: "28px",
height: "28px",
borderRadius: "9999px",
backgroundColor: "#ffffff",
boxShadow: "rgb(235, 235, 235) 0px 2px 2px",
border: "1px solid #d9d9d9"
top: "0",
left: "0",
border: "none",
backgroundColor: "transparent",
transform: "translate(-50%, -50%)",
padding: "0"
})}
onClick={e => e.preventDefault()}
onClick={this.preventDefaultClick}
role="slider"
tabIndex={0}
aria-valuenow={minState}
aria-valuemax={max}
aria-valuemin={min}
aria-disabled="false"
aria-disabled={false}
onMouseDown={this.triggerMouseMin}
onKeyDown={this.handleMinKeydown}
onTouchStart={this.triggerTouchMin}
ButtonRenderComponent={ButtonInnerComponent}
/>
<Button
className={css({
position: "absolute",
top: "-13px",
right: "-10px",
width: "28px",
height: "28px",
borderRadius: "9999px",
backgroundColor: "#ffffff",
boxShadow: "rgb(235, 235, 235) 0px 2px 2px",
border: "1px solid #d9d9d9"
top: "50%",
right: "0",
transform: "translate(50%, -50%)",
border: "none",
backgroundColor: "transparent",
padding: "0"
})}
onClick={e => e.preventDefault()}
onClick={this.preventDefaultClick}
role="slider"
tabIndex={0}
aria-valuenow={maxState}
aria-valuemax={max}
aria-valuemin={min}
aria-disabled="false"
aria-disabled={false}
onKeyDown={this.handleMaxKeydown}
onMouseDown={this.triggerMouseMax}
onTouchStart={this.triggerTouchMax}
ButtonRenderComponent={ButtonInnerComponent}
/>
</div>
</div>
);
}
}

const Button = (props: React.HTMLAttributes<HTMLButtonElement>) => (
<button {...props}>
const DefaultRenderButtonComponent = () => (
<span
className={css({
width: "28px",
display: "flex",
alignItems: "center",
justifyContent: "center",
height: "28px",
borderRadius: "9999px",
backgroundColor: "#ffffff",
boxShadow: "rgb(235, 235, 235) 0px 2px 2px",
border: "1px solid #d9d9d9"
})}
>
{[1, 2, 3].map(index => (
<span
key={index}
Expand All @@ -374,5 +394,32 @@ const Button = (props: React.HTMLAttributes<HTMLButtonElement>) => (
})}
/>
))}
</button>
</span>
);

class Button extends React.PureComponent<
{
ButtonRenderComponent: ((props: { focused?: boolean }) => JSX.Element);
} & React.HTMLAttributes<HTMLButtonElement>
> {
state = {
focused: false
};

handleFocus = () => {
this.setState({ focused: true });
};

handleBlur = () => {
this.setState({ focused: false });
};

render() {
const { ButtonRenderComponent, ...rest } = this.props;
return (
<button {...rest} onFocus={this.handleFocus} onBlur={this.handleBlur}>
<ButtonRenderComponent focused={this.state.focused} />
</button>
);
}
}

0 comments on commit 0e9b988

Please sign in to comment.