Skip to content

Commit 8356f60

Browse files
committed
v0.1.2
1 parent 2489880 commit 8356f60

File tree

3 files changed

+69
-15
lines changed

3 files changed

+69
-15
lines changed

packages/react-fancy-switch/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@omit/react-fancy-switch",
33
"private": false,
4-
"version": "0.1.1",
4+
"version": "0.1.2",
55
"type": "module",
66
"license": "MIT",
77
"description": "A fancy switch component",

packages/react-fancy-switch/src/components/fancy-switch.tsx

Lines changed: 58 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
import * as React from 'react'
2-
import { FancySwitchProps, OptionObject, OptionType } from '../types'
2+
import {
3+
FancySwitchProps,
4+
OptionObject,
5+
OptionType,
6+
OptionValue
7+
} from '../types'
38

49
export const FancySwitch = React.forwardRef<HTMLDivElement, FancySwitchProps>(
510
(
@@ -17,18 +22,22 @@ export const FancySwitch = React.forwardRef<HTMLDivElement, FancySwitchProps>(
1722
ref
1823
) => {
1924
const getOptionValue = React.useCallback(
20-
(option: OptionType) =>
21-
typeof option === 'string'
22-
? option
23-
: (option as OptionObject)[valueKey],
25+
(option: OptionType): OptionValue => {
26+
if (typeof option === 'string' || typeof option === 'number') {
27+
return option
28+
}
29+
return (option as OptionObject)[valueKey] as OptionValue
30+
},
2431
[valueKey]
2532
)
2633

2734
const getOptionLabel = React.useCallback(
28-
(option: OptionType) =>
29-
typeof option === 'string'
30-
? option
31-
: (option as OptionObject)[labelKey],
35+
(option: OptionType): string => {
36+
if (typeof option === 'string' || typeof option === 'number') {
37+
return String(option)
38+
}
39+
return String((option as OptionObject)[labelKey])
40+
},
3241
[labelKey]
3342
)
3443

@@ -41,9 +50,27 @@ export const FancySwitch = React.forwardRef<HTMLDivElement, FancySwitchProps>(
4150
[options, getOptionValue, getOptionLabel]
4251
)
4352

44-
const [activeIndex, setActiveIndex] = React.useState(() =>
45-
memoizedOptions.findIndex((option) => option.value === value)
46-
)
53+
const [activeIndex, setActiveIndex] = React.useState(() => {
54+
const index = memoizedOptions.findIndex(
55+
(option) => option.value === value
56+
)
57+
if (index === -1) {
58+
console.warn(
59+
`FancySwitch: No option found for value "${value}". Defaulting to first option.`
60+
)
61+
return 0
62+
}
63+
return index
64+
})
65+
66+
React.useEffect(() => {
67+
const newIndex = memoizedOptions.findIndex(
68+
(option) => option.value === value
69+
)
70+
if (newIndex !== -1 && newIndex !== activeIndex) {
71+
setActiveIndex(newIndex)
72+
}
73+
}, [value, memoizedOptions, activeIndex])
4774

4875
const [highlighterStyle, setHighlighterStyle] = React.useState({
4976
height: 0,
@@ -158,7 +185,7 @@ export const FancySwitch = React.forwardRef<HTMLDivElement, FancySwitchProps>(
158185
return (
159186
<div
160187
role="radiogroup"
161-
aria-labelledby="fancy-switch-label"
188+
aria-label="Fancy Switch Options"
162189
{...props}
163190
ref={containerRef}
164191
>
@@ -186,10 +213,28 @@ export const FancySwitch = React.forwardRef<HTMLDivElement, FancySwitchProps>(
186213
onKeyDown={(e) => handleKeyDown(e, index)}
187214
className={radioClassName}
188215
{...(index === activeIndex ? { 'data-checked': true } : {})}
216+
aria-label={`${option.label} option`}
189217
>
190218
{option.label}
191219
</div>
192220
))}
221+
222+
<div
223+
aria-live="polite"
224+
style={{
225+
position: 'absolute',
226+
width: '1px',
227+
height: '1px',
228+
padding: 0,
229+
margin: '-1px',
230+
overflow: 'hidden',
231+
clip: 'rect(0, 0, 0, 0)',
232+
whiteSpace: 'nowrap',
233+
borderWidth: 0
234+
}}
235+
>
236+
{memoizedOptions[activeIndex]?.label} selected
237+
</div>
193238
</div>
194239
)
195240
}

website/src/App.tsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ function App() {
3939
const form = useForm<z.infer<typeof FormSchema>>({
4040
resolver: zodResolver(FormSchema),
4141
defaultValues: {
42-
orderType: 'Delivery',
42+
orderType: 'Pickup',
4343
isPublished: 0,
4444
pet: 1
4545
}
@@ -49,6 +49,14 @@ function App() {
4949
console.log(data)
5050
}
5151

52+
// wait 2 second, and change orderType to 'Shipping'
53+
useEffect(() => {
54+
setTimeout(() => {
55+
form.setValue('orderType', 'Shipping')
56+
console.log('orderType changed to Shipping')
57+
}, 2000)
58+
}, [form])
59+
5260
useEffect(() => {
5361
const handleKeyDown = (e: KeyboardEvent) => {
5462
if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {
@@ -99,6 +107,7 @@ function App() {
99107
data-testid="orderType"
100108
className="flex rounded-full bg-muted p-2"
101109
highlighterClassName="bg-primary rounded-full"
110+
aria-label="Order type"
102111
radioClassName={cn(
103112
'relative mx-2 flex h-9 cursor-pointer items-center justify-center rounded-full px-3.5 text-sm font-medium transition-colors focus:outline-none data-[checked]:text-primary-foreground'
104113
)}

0 commit comments

Comments
 (0)