Skip to content

Commit a1141dd

Browse files
authored
feat: improve code (#15)
1 parent f132daf commit a1141dd

File tree

4 files changed

+38
-29
lines changed

4 files changed

+38
-29
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ render(
5151
| options | Array<string \| number \| [SegmentedOption](#SegmentedOption)> | [] | options for choices |
5252
| value | string \| number | | value of segmented |
5353
| defaultValue | string \| number | | defaultValue of segmented |
54+
| value | string \| number | | currently selected value of segmented |
5455
| onChange | (e: any) => void | | defaultValue of segmented |
5556
| disabled | boolean | false | disabled status of segmented |
5657

src/index.tsx

+29-21
Original file line numberDiff line numberDiff line change
@@ -88,13 +88,20 @@ const InternalSegmentedOption: React.FC<{
8888
);
8989
};
9090

91+
interface ThumbMoveStatus {
92+
from: React.CSSProperties | null;
93+
to: React.CSSProperties | null;
94+
}
95+
9196
const Segmented = React.forwardRef<HTMLDivElement, SegmentedProps>(
9297
(props, ref) => {
9398
const {
9499
prefixCls = 'rc-segmented',
95100
direction,
96101
options,
97102
disabled,
103+
defaultValue,
104+
value,
98105
onChange,
99106
className = '',
100107
motionName = 'thumb-motion',
@@ -104,9 +111,7 @@ const Segmented = React.forwardRef<HTMLDivElement, SegmentedProps>(
104111
const containerRef = React.useRef<HTMLDivElement>(null);
105112
const mergedRef = composeRef<HTMLDivElement>(containerRef, ref);
106113

107-
const thumbMoveStyles = React.useRef<
108-
Record<'from' | 'to', React.CSSProperties | null>
109-
>({
114+
const thumbMoveStatus = React.useRef<ThumbMoveStatus>({
110115
from: null,
111116
to: null,
112117
});
@@ -115,51 +120,52 @@ const Segmented = React.forwardRef<HTMLDivElement, SegmentedProps>(
115120
return normalizeOptions(options);
116121
}, [options]);
117122

118-
const [selected, setSelected] = useMergedState(
119-
props.defaultValue || segmentedOptions[0]?.value,
120-
);
123+
const [selected, setSelected] = useMergedState(segmentedOptions[0]?.value, {
124+
value,
125+
defaultValue,
126+
});
121127

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

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

128-
const calcThumbMoveStyle = (event: React.ChangeEvent<HTMLInputElement>) => {
134+
const calcThumbMoveStatus = (
135+
event: React.ChangeEvent<HTMLInputElement>,
136+
) => {
129137
const toElement = event.target.closest(`.${prefixCls}-item`);
130138

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

135-
if (fromElement && toElement && thumbMoveStyles.current) {
136-
thumbMoveStyles.current.from = calcThumbStyle(
143+
if (fromElement && toElement && thumbMoveStatus.current) {
144+
thumbMoveStatus.current.from = calcThumbStyle(
137145
fromElement as HTMLElement,
138146
);
139-
thumbMoveStyles.current.to = calcThumbStyle(toElement as HTMLElement);
147+
thumbMoveStatus.current.to = calcThumbStyle(toElement as HTMLElement);
140148

141149
setThumbShow(true);
142150
}
143151
};
144152

145153
const handleChange = (
146154
event: React.ChangeEvent<HTMLInputElement>,
147-
value: SegmentedRawOption,
155+
val: SegmentedRawOption,
148156
) => {
149157
if (disabled) {
150158
return;
151159
}
152160

153-
if (value !== selected) {
154-
calcThumbMoveStyle(event);
155-
}
161+
calcThumbMoveStatus(event);
156162

157-
setSelected(value);
163+
setSelected(val);
158164

159165
if (onChange) {
160166
const mutatedTarget = Object.create(event.target, {
161167
value: {
162-
value,
168+
value: val,
163169
},
164170
});
165171
const mutatedEvent = Object.create(event, {
@@ -173,15 +179,15 @@ const Segmented = React.forwardRef<HTMLDivElement, SegmentedProps>(
173179

174180
// --- motion event handlers for thumb move
175181
const handleThumbEnterStart = () => {
176-
const fromStyle = thumbMoveStyles.current.from;
182+
const fromStyle = thumbMoveStatus.current.from;
177183
if (fromStyle) {
178184
setVisualSelected(undefined);
179185
return fromStyle;
180186
}
181187
};
182188

183189
const handleThumbEnterActive = () => {
184-
const toStyle = thumbMoveStyles.current.to;
190+
const toStyle = thumbMoveStatus.current.to;
185191
if (toStyle) {
186192
return toStyle;
187193
}
@@ -191,8 +197,8 @@ const Segmented = React.forwardRef<HTMLDivElement, SegmentedProps>(
191197
setThumbShow(false);
192198
setVisualSelected(selected);
193199

194-
if (thumbMoveStyles.current) {
195-
thumbMoveStyles.current = {
200+
if (thumbMoveStatus.current) {
201+
thumbMoveStatus.current = {
196202
from: null,
197203
to: null,
198204
};
@@ -251,6 +257,8 @@ const Segmented = React.forwardRef<HTMLDivElement, SegmentedProps>(
251257

252258
Segmented.displayName = 'Segmented';
253259

254-
Segmented.defaultProps = {};
260+
Segmented.defaultProps = {
261+
options: [],
262+
};
255263

256264
export default Segmented;

tests/__snapshots__/index.spec.tsx.snap

+7-7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
// Jest Snapshot v1, https://goo.gl/fbAQLP
22

3-
exports[`rc-segmented render 1`] = `
3+
exports[`rc-segmented render empty segmented 1`] = `
4+
<div
5+
class="rc-segmented"
6+
/>
7+
`;
8+
9+
exports[`rc-segmented render label with ReactNode 1`] = `
410
<div
511
class="rc-segmented"
612
>
@@ -53,12 +59,6 @@ exports[`rc-segmented render 1`] = `
5359
</div>
5460
`;
5561

56-
exports[`rc-segmented render empty segmented 1`] = `
57-
<div
58-
class="rc-segmented"
59-
/>
60-
`;
61-
6262
exports[`rc-segmented render segmented ok 1`] = `
6363
<div
6464
class="rc-segmented"

tests/index.spec.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ describe('rc-segmented', () => {
3636
).toEqual([true, false, false]);
3737
});
3838

39-
it('render', () => {
39+
it('render label with ReactNode', () => {
4040
const wrapper = mount(
4141
<Segmented
4242
options={[

0 commit comments

Comments
 (0)