Skip to content

Commit

Permalink
feat: improve code (#15)
Browse files Browse the repository at this point in the history
  • Loading branch information
vagusX authored Mar 7, 2022
1 parent f132daf commit a1141dd
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 29 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ render(
| options | Array<string \| number \| [SegmentedOption](#SegmentedOption)> | [] | options for choices |
| value | string \| number | | value of segmented |
| defaultValue | string \| number | | defaultValue of segmented |
| value | string \| number | | currently selected value of segmented |
| onChange | (e: any) => void | | defaultValue of segmented |
| disabled | boolean | false | disabled status of segmented |

Expand Down
50 changes: 29 additions & 21 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -88,13 +88,20 @@ const InternalSegmentedOption: React.FC<{
);
};

interface ThumbMoveStatus {
from: React.CSSProperties | null;
to: React.CSSProperties | null;
}

const Segmented = React.forwardRef<HTMLDivElement, SegmentedProps>(
(props, ref) => {
const {
prefixCls = 'rc-segmented',
direction,
options,
disabled,
defaultValue,
value,
onChange,
className = '',
motionName = 'thumb-motion',
Expand All @@ -104,9 +111,7 @@ const Segmented = React.forwardRef<HTMLDivElement, SegmentedProps>(
const containerRef = React.useRef<HTMLDivElement>(null);
const mergedRef = composeRef<HTMLDivElement>(containerRef, ref);

const thumbMoveStyles = React.useRef<
Record<'from' | 'to', React.CSSProperties | null>
>({
const thumbMoveStatus = React.useRef<ThumbMoveStatus>({
from: null,
to: null,
});
Expand All @@ -115,51 +120,52 @@ const Segmented = React.forwardRef<HTMLDivElement, SegmentedProps>(
return normalizeOptions(options);
}, [options]);

const [selected, setSelected] = useMergedState(
props.defaultValue || segmentedOptions[0]?.value,
);
const [selected, setSelected] = useMergedState(segmentedOptions[0]?.value, {
value,
defaultValue,
});

const [visualSelected, setVisualSelected] = React.useState<
SegmentedRawOption | undefined
>(selected);

const [thumbShow, setThumbShow] = React.useState(false);

const calcThumbMoveStyle = (event: React.ChangeEvent<HTMLInputElement>) => {
const calcThumbMoveStatus = (
event: React.ChangeEvent<HTMLInputElement>,
) => {
const toElement = event.target.closest(`.${prefixCls}-item`);

const fromElement = containerRef.current?.querySelector(
`.${prefixCls}-item-selected`,
);

if (fromElement && toElement && thumbMoveStyles.current) {
thumbMoveStyles.current.from = calcThumbStyle(
if (fromElement && toElement && thumbMoveStatus.current) {
thumbMoveStatus.current.from = calcThumbStyle(
fromElement as HTMLElement,
);
thumbMoveStyles.current.to = calcThumbStyle(toElement as HTMLElement);
thumbMoveStatus.current.to = calcThumbStyle(toElement as HTMLElement);

setThumbShow(true);
}
};

const handleChange = (
event: React.ChangeEvent<HTMLInputElement>,
value: SegmentedRawOption,
val: SegmentedRawOption,
) => {
if (disabled) {
return;
}

if (value !== selected) {
calcThumbMoveStyle(event);
}
calcThumbMoveStatus(event);

setSelected(value);
setSelected(val);

if (onChange) {
const mutatedTarget = Object.create(event.target, {
value: {
value,
value: val,
},
});
const mutatedEvent = Object.create(event, {
Expand All @@ -173,15 +179,15 @@ const Segmented = React.forwardRef<HTMLDivElement, SegmentedProps>(

// --- motion event handlers for thumb move
const handleThumbEnterStart = () => {
const fromStyle = thumbMoveStyles.current.from;
const fromStyle = thumbMoveStatus.current.from;
if (fromStyle) {
setVisualSelected(undefined);
return fromStyle;
}
};

const handleThumbEnterActive = () => {
const toStyle = thumbMoveStyles.current.to;
const toStyle = thumbMoveStatus.current.to;
if (toStyle) {
return toStyle;
}
Expand All @@ -191,8 +197,8 @@ const Segmented = React.forwardRef<HTMLDivElement, SegmentedProps>(
setThumbShow(false);
setVisualSelected(selected);

if (thumbMoveStyles.current) {
thumbMoveStyles.current = {
if (thumbMoveStatus.current) {
thumbMoveStatus.current = {
from: null,
to: null,
};
Expand Down Expand Up @@ -251,6 +257,8 @@ const Segmented = React.forwardRef<HTMLDivElement, SegmentedProps>(

Segmented.displayName = 'Segmented';

Segmented.defaultProps = {};
Segmented.defaultProps = {
options: [],
};

export default Segmented;
14 changes: 7 additions & 7 deletions tests/__snapshots__/index.spec.tsx.snap
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`rc-segmented render 1`] = `
exports[`rc-segmented render empty segmented 1`] = `
<div
class="rc-segmented"
/>
`;

exports[`rc-segmented render label with ReactNode 1`] = `
<div
class="rc-segmented"
>
Expand Down Expand Up @@ -53,12 +59,6 @@ exports[`rc-segmented render 1`] = `
</div>
`;

exports[`rc-segmented render empty segmented 1`] = `
<div
class="rc-segmented"
/>
`;

exports[`rc-segmented render segmented ok 1`] = `
<div
class="rc-segmented"
Expand Down
2 changes: 1 addition & 1 deletion tests/index.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ describe('rc-segmented', () => {
).toEqual([true, false, false]);
});

it('render', () => {
it('render label with ReactNode', () => {
const wrapper = mount(
<Segmented
options={[
Expand Down

0 comments on commit a1141dd

Please sign in to comment.