@jongh/cli 1.0.11 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.lintstagedrc.json +4 -0
- package/CHANGELOG.md +7 -0
- package/dist/components/Accordion/Accordion.tsx +21 -14
- package/dist/components/Accordion/useAccordionHeight.ts +13 -16
- package/dist/components/Button/index.tsx +11 -45
- package/dist/components/Primitive/index.tsx +58 -0
- package/dist/components/RovingIndex/RovingItem.tsx +47 -0
- package/dist/components/RovingIndex/RovingTabIndexRoot.tsx +92 -0
- package/dist/components/RovingIndex/index.ts +3 -0
- package/dist/components/RovingIndex/useRovingTabIndex.tsx +76 -0
- package/dist/components/Select/index.tsx +231 -0
- package/dist/components/Slider/index.tsx +141 -0
- package/dist/components/Slider/style.ts +28 -41
- package/dist/components/{Tab → Tabs}/Tab.tsx +11 -7
- package/dist/components/{Tab → Tabs}/TabContent.tsx +4 -2
- package/dist/components/Tabs/TabIndicator.tsx +6 -0
- package/dist/components/{Tab → Tabs}/TabList.tsx +20 -21
- package/dist/components/Tabs/index.ts +43 -0
- package/dist/components/{Tab → Tabs}/useRovingTabIndex.tsx +0 -1
- package/dist/components/index.ts +3 -3
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/src/{fetchComponent.ts → copyComponent.ts} +0 -1
- package/src/getConfig.ts +7 -4
- package/src/index.ts +2 -2
- package/dist/components/Slider/Slider.tsx +0 -140
- package/dist/components/Tab/TabIndicator.tsx +0 -19
- package/dist/components/Tab/index.ts +0 -4
- package/dist/components/Tab/style.ts +0 -9
- package/park-ui.json +0 -3
- /package/dist/components/{Tab → Tabs}/useTabContext.ts +0 -0
package/CHANGELOG.md
ADDED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import * as React from "react"
|
|
2
2
|
import { createContext } from "../../hooks/createContext"
|
|
3
3
|
import { useControlledState } from "../../hooks/useControllableState"
|
|
4
|
-
import { useAccordionHeight } from "./useAccordionHeight"
|
|
5
4
|
import { useKeyboardEvent } from "../../hooks/useKeyboardEvent"
|
|
6
5
|
import { Slot } from "@radix-ui/react-slot"
|
|
7
6
|
import { composeRefs } from "src/hooks/useComposedRefs"
|
|
@@ -227,15 +226,14 @@ export const AccordionTrigger = ({
|
|
|
227
226
|
}: AccordionTriggerProps) => {
|
|
228
227
|
const { onToggle, isOpen, value } = useAccordionItemProvider("accordionItem")
|
|
229
228
|
return (
|
|
230
|
-
<h3 data-state={isOpen ? "open" : "close"} {...props}>
|
|
231
|
-
<
|
|
232
|
-
onClick={onToggle}
|
|
229
|
+
<h3 data-state={isOpen ? "open" : "close"} onClick={onToggle} {...props}>
|
|
230
|
+
<button
|
|
233
231
|
aria-expanded={isOpen ? "true" : "false"}
|
|
234
232
|
aria-controls={`content-${value}`}
|
|
235
233
|
id={`trigger-${value}`}
|
|
236
234
|
>
|
|
237
|
-
|
|
238
|
-
</
|
|
235
|
+
{children}
|
|
236
|
+
</button>
|
|
239
237
|
</h3>
|
|
240
238
|
)
|
|
241
239
|
}
|
|
@@ -244,31 +242,40 @@ export interface AccordionContentProps extends React.PropsWithChildren {
|
|
|
244
242
|
duration?: number
|
|
245
243
|
asChild?: boolean
|
|
246
244
|
}
|
|
245
|
+
|
|
247
246
|
export const AccordionContent = ({
|
|
248
247
|
children,
|
|
249
|
-
duration = 150,
|
|
250
248
|
asChild,
|
|
251
249
|
...props
|
|
252
250
|
}: AccordionContentProps) => {
|
|
253
251
|
const Comp = asChild ? Slot : "div"
|
|
254
252
|
const { isOpen, value } = useAccordionItemProvider("accordionItem")
|
|
253
|
+
const contentRef = React.useRef<HTMLDivElement>(null)
|
|
255
254
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
255
|
+
React.useEffect(() => {
|
|
256
|
+
if (contentRef.current) {
|
|
257
|
+
const element = contentRef.current
|
|
258
|
+
if (isOpen) {
|
|
259
|
+
element.style.setProperty(
|
|
260
|
+
"--accordion-height",
|
|
261
|
+
`${element.scrollHeight}px`,
|
|
262
|
+
)
|
|
263
|
+
} else {
|
|
264
|
+
element.style.setProperty("--accordion-height", "0px")
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}, [isOpen])
|
|
261
268
|
|
|
262
269
|
return (
|
|
263
270
|
<Comp
|
|
271
|
+
ref={contentRef}
|
|
264
272
|
data-state={isOpen ? "open" : "close"}
|
|
265
273
|
id={`content-${value}`}
|
|
266
274
|
aria-labelledby={`trigger-${value}`}
|
|
267
275
|
role="region"
|
|
268
|
-
ref={contentRef}
|
|
269
276
|
{...props}
|
|
270
277
|
>
|
|
271
|
-
{children}
|
|
278
|
+
{isOpen && children}
|
|
272
279
|
</Comp>
|
|
273
280
|
)
|
|
274
281
|
}
|
|
@@ -1,28 +1,25 @@
|
|
|
1
1
|
import { useEffect, useRef } from "react"
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
) => {
|
|
2
|
+
|
|
3
|
+
const ACCORDION_HEIGHT = "--accordion-height"
|
|
4
|
+
|
|
5
|
+
export const useAccordionHeight = <T extends HTMLElement>(isOpen: boolean) => {
|
|
7
6
|
const ref = useRef<T>(null)
|
|
8
7
|
|
|
9
8
|
useEffect(() => {
|
|
10
9
|
const element = ref.current
|
|
11
|
-
if (element
|
|
12
|
-
return
|
|
13
|
-
}
|
|
10
|
+
if (!element) return
|
|
14
11
|
|
|
15
12
|
if (isOpen) {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
}
|
|
13
|
+
// 열릴 때 높이를 scrollHeight로 설정
|
|
14
|
+
const newHeight = element.scrollHeight
|
|
15
|
+
element.style.setProperty(ACCORDION_HEIGHT, `${newHeight}px`)
|
|
16
|
+
element.style.height = `${newHeight}px`
|
|
20
17
|
} else {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
18
|
+
// 닫힐 때 높이를 0으로 설정
|
|
19
|
+
element.style.setProperty(ACCORDION_HEIGHT, `0px`)
|
|
20
|
+
element.style.height = "0px"
|
|
24
21
|
}
|
|
25
|
-
}, [isOpen
|
|
22
|
+
}, [isOpen])
|
|
26
23
|
|
|
27
24
|
return ref
|
|
28
25
|
}
|
|
@@ -1,50 +1,19 @@
|
|
|
1
|
-
import {
|
|
2
|
-
forwardRef,
|
|
3
|
-
ComponentPropsWithoutRef,
|
|
4
|
-
isValidElement,
|
|
5
|
-
cloneElement,
|
|
6
|
-
type ReactElement,
|
|
7
|
-
type MouseEventHandler,
|
|
8
|
-
} from "react"
|
|
1
|
+
import { forwardRef, ComponentPropsWithoutRef, type ReactNode } from "react"
|
|
9
2
|
import { button, type ButtonVariant } from "@styled-system/recipes"
|
|
10
3
|
import { Slot } from "@radix-ui/react-slot"
|
|
4
|
+
import { cx } from "@styled-system/css"
|
|
11
5
|
|
|
12
|
-
type ButtonProps =
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
rightIcon?: ReactElement
|
|
18
|
-
}
|
|
6
|
+
export type ButtonProps = ComponentPropsWithoutRef<"button"> & {
|
|
7
|
+
children: ReactNode
|
|
8
|
+
as?: boolean
|
|
9
|
+
disabled?: boolean
|
|
10
|
+
} & Partial<ButtonVariant>
|
|
19
11
|
|
|
20
12
|
export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
|
|
21
|
-
(
|
|
22
|
-
|
|
23
|
-
as,
|
|
24
|
-
id,
|
|
25
|
-
className,
|
|
26
|
-
children,
|
|
27
|
-
disabled = false,
|
|
28
|
-
leftIcon,
|
|
29
|
-
rightIcon,
|
|
30
|
-
onClick,
|
|
31
|
-
...rest
|
|
32
|
-
},
|
|
33
|
-
ref,
|
|
34
|
-
) => {
|
|
35
|
-
const Comp = as ? Slot : "button"
|
|
13
|
+
({ as, disabled, id, onClick, children, ...rest }, ref) => {
|
|
14
|
+
const [buttonProps] = button.splitVariantProps(rest)
|
|
36
15
|
|
|
37
|
-
const
|
|
38
|
-
if (isValidElement(icon)) {
|
|
39
|
-
const { onClick: onClickIcon } = icon.props
|
|
40
|
-
return cloneElement(icon, {
|
|
41
|
-
onClick: (e: React.MouseEvent<HTMLButtonElement>) => {
|
|
42
|
-
e.stopPropagation()
|
|
43
|
-
onClickIcon ? onClickIcon(e) : onClick?.(e)
|
|
44
|
-
},
|
|
45
|
-
})
|
|
46
|
-
}
|
|
47
|
-
}
|
|
16
|
+
const Comp = as ? Slot : "button"
|
|
48
17
|
|
|
49
18
|
return (
|
|
50
19
|
<Comp
|
|
@@ -52,14 +21,11 @@ export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
|
|
|
52
21
|
ref={ref}
|
|
53
22
|
disabled={disabled}
|
|
54
23
|
id={id}
|
|
55
|
-
data-testid={id}
|
|
56
24
|
onClick={onClick}
|
|
57
|
-
className={button(
|
|
25
|
+
className={cx(button(buttonProps))}
|
|
58
26
|
{...rest}
|
|
59
27
|
>
|
|
60
|
-
{leftIcon && <span>{wrapIcon(leftIcon)}</span>}
|
|
61
28
|
{children}
|
|
62
|
-
{rightIcon && <span>{wrapIcon(rightIcon)}</span>}
|
|
63
29
|
</Comp>
|
|
64
30
|
)
|
|
65
31
|
},
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
//radix ui Primitive를 참고하여 작성한 코드
|
|
3
|
+
import * as React from "react"
|
|
4
|
+
import { Slot } from "@radix-ui/react-slot"
|
|
5
|
+
|
|
6
|
+
const NODES = [
|
|
7
|
+
"a",
|
|
8
|
+
"button",
|
|
9
|
+
"div",
|
|
10
|
+
"form",
|
|
11
|
+
"h2",
|
|
12
|
+
"h3",
|
|
13
|
+
"img",
|
|
14
|
+
"input",
|
|
15
|
+
"label",
|
|
16
|
+
"li",
|
|
17
|
+
"nav",
|
|
18
|
+
"ol",
|
|
19
|
+
"p",
|
|
20
|
+
"span",
|
|
21
|
+
"svg",
|
|
22
|
+
"ul",
|
|
23
|
+
] as const
|
|
24
|
+
|
|
25
|
+
type Primitives = {
|
|
26
|
+
[E in (typeof NODES)[number]]: PrimitiveForwardRefComponent<E>
|
|
27
|
+
}
|
|
28
|
+
type PrimitivePropsWithRef<E extends React.ElementType> =
|
|
29
|
+
React.ComponentPropsWithRef<E> & {
|
|
30
|
+
asChild?: boolean
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
interface PrimitiveForwardRefComponent<E extends React.ElementType>
|
|
34
|
+
extends React.ForwardRefExoticComponent<PrimitivePropsWithRef<E>> {}
|
|
35
|
+
|
|
36
|
+
/* -------------------------------------------------------------------------------------------------
|
|
37
|
+
* Primitive
|
|
38
|
+
* -----------------------------------------------------------------------------------------------*/
|
|
39
|
+
|
|
40
|
+
const Primitive = NODES.reduce((primitive, node) => {
|
|
41
|
+
const Node = React.forwardRef(
|
|
42
|
+
(props: PrimitivePropsWithRef<typeof node>, forwardedRef: any) => {
|
|
43
|
+
const { asChild, ...primitiveProps } = props
|
|
44
|
+
const Comp: any = asChild ? Slot : node
|
|
45
|
+
|
|
46
|
+
return <Comp {...primitiveProps} ref={forwardedRef} />
|
|
47
|
+
},
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
Node.displayName = `Primitive.${node}`
|
|
51
|
+
|
|
52
|
+
return { ...primitive, [node]: Node }
|
|
53
|
+
}, {} as Primitives)
|
|
54
|
+
|
|
55
|
+
const Root = Primitive
|
|
56
|
+
|
|
57
|
+
export { Primitive, Root }
|
|
58
|
+
export type { PrimitivePropsWithRef }
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { ReactElement } from "react"
|
|
2
|
+
import { useRovingTabIndex } from "./useRovingTabIndex"
|
|
3
|
+
import { Slot } from "@radix-ui/react-slot"
|
|
4
|
+
import isHotkey from "is-hotkey"
|
|
5
|
+
import {
|
|
6
|
+
getNextFocusableId,
|
|
7
|
+
getPrevFocusableId,
|
|
8
|
+
} from "../../utils/getFocusableId"
|
|
9
|
+
|
|
10
|
+
export const RovingItem = ({
|
|
11
|
+
value,
|
|
12
|
+
children,
|
|
13
|
+
}: {
|
|
14
|
+
value: string
|
|
15
|
+
children: ReactElement
|
|
16
|
+
}) => {
|
|
17
|
+
const { getOrderedItems, getRovingProps, dir } = useRovingTabIndex(value)
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<Slot
|
|
21
|
+
{...getRovingProps<"button">({
|
|
22
|
+
onKeyDown: (e) => {
|
|
23
|
+
const items = getOrderedItems()
|
|
24
|
+
let nextItem
|
|
25
|
+
if (dir === "horizontal") {
|
|
26
|
+
if (isHotkey("right", e)) {
|
|
27
|
+
nextItem = getNextFocusableId(items, value)
|
|
28
|
+
} else if (isHotkey("left", e)) {
|
|
29
|
+
nextItem = getPrevFocusableId(items, value)
|
|
30
|
+
}
|
|
31
|
+
nextItem?.element.focus()
|
|
32
|
+
}
|
|
33
|
+
if (dir === "vertical") {
|
|
34
|
+
if (e.key === "ArrowDown") {
|
|
35
|
+
nextItem = getNextFocusableId(items, value)
|
|
36
|
+
} else if (e.key === "ArrowUp") {
|
|
37
|
+
nextItem = getPrevFocusableId(items, value)
|
|
38
|
+
}
|
|
39
|
+
nextItem?.element.focus()
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
})}
|
|
43
|
+
>
|
|
44
|
+
{children}
|
|
45
|
+
</Slot>
|
|
46
|
+
)
|
|
47
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { ReactNode, useCallback, useRef, useState } from "react"
|
|
2
|
+
import { useControlledState } from "../../hooks/useControllableState"
|
|
3
|
+
import { RovingTabIndexProvider } from "./useRovingTabIndex"
|
|
4
|
+
import { Slot } from "@radix-ui/react-slot"
|
|
5
|
+
|
|
6
|
+
export const NODE_SELECTOR = "data-roving-tabindex-node"
|
|
7
|
+
const ROOT_SELECTOR = "data-roving-tabindex-root"
|
|
8
|
+
const NOT_FOCUSABLE_SELECTOR = "data-roving-tabindex-not-focusable"
|
|
9
|
+
const SELECTOR_ACTIVE = `:where([${NODE_SELECTOR}=true]):not(:where([${NOT_FOCUSABLE_SELECTOR}=true] *))`
|
|
10
|
+
|
|
11
|
+
type RovingTabIndexRootBaseProps = {
|
|
12
|
+
children: ReactNode | ReactNode[]
|
|
13
|
+
active?: string
|
|
14
|
+
setActive?: (value: string) => void
|
|
15
|
+
asChild?: boolean
|
|
16
|
+
dir?: "horizontal" | "vertical"
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
type RovingTabIndexRootProps = RovingTabIndexRootBaseProps
|
|
20
|
+
|
|
21
|
+
function onFocusFirst(candidates: HTMLElement[]) {
|
|
22
|
+
const previousFocus = document.activeElement
|
|
23
|
+
while (document.activeElement === previousFocus && candidates.length > 0) {
|
|
24
|
+
candidates.shift()?.focus()
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export const RovingTabIndexRoot = ({
|
|
29
|
+
children,
|
|
30
|
+
active,
|
|
31
|
+
setActive,
|
|
32
|
+
asChild,
|
|
33
|
+
dir = "horizontal",
|
|
34
|
+
...props
|
|
35
|
+
}: RovingTabIndexRootProps) => {
|
|
36
|
+
const [isShiftTabbing, setIsShiftTabbing] = useState(false)
|
|
37
|
+
|
|
38
|
+
const [value = null, setValue] = useControlledState({
|
|
39
|
+
prop: active,
|
|
40
|
+
onChange: setActive,
|
|
41
|
+
})
|
|
42
|
+
const rootRef = useRef<HTMLDivElement | null>(null)
|
|
43
|
+
const elementsRef = useRef<Map<string, HTMLElement>>(new Map())
|
|
44
|
+
const getOrderedItems = useCallback(() => {
|
|
45
|
+
if (!rootRef.current) return []
|
|
46
|
+
const activeElements = Array.from(
|
|
47
|
+
rootRef.current.querySelectorAll(SELECTOR_ACTIVE),
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
return Array.from(elementsRef.current)
|
|
51
|
+
.sort(
|
|
52
|
+
(a, b) => activeElements.indexOf(a[1]) - activeElements.indexOf(b[1]),
|
|
53
|
+
)
|
|
54
|
+
.map(([value, element]) => ({ value, element }))
|
|
55
|
+
}, [])
|
|
56
|
+
|
|
57
|
+
return (
|
|
58
|
+
<RovingTabIndexProvider
|
|
59
|
+
setFocusableId={(value: string) => {
|
|
60
|
+
setValue(value)
|
|
61
|
+
}}
|
|
62
|
+
onShiftTab={() => {
|
|
63
|
+
setIsShiftTabbing(true)
|
|
64
|
+
}}
|
|
65
|
+
currentFocusedValue={value}
|
|
66
|
+
getOrderedItems={getOrderedItems}
|
|
67
|
+
elements={elementsRef}
|
|
68
|
+
dir={dir}
|
|
69
|
+
>
|
|
70
|
+
<Slot
|
|
71
|
+
{...{ [ROOT_SELECTOR]: true }}
|
|
72
|
+
tabIndex={isShiftTabbing ? -1 : 0}
|
|
73
|
+
onFocus={(e) => {
|
|
74
|
+
if (e.target !== e.currentTarget) return
|
|
75
|
+
if (isShiftTabbing) return
|
|
76
|
+
const orderedItems = getOrderedItems()
|
|
77
|
+
if (orderedItems.length === 0) return
|
|
78
|
+
const candidates = [
|
|
79
|
+
elementsRef.current.get(value ?? ""),
|
|
80
|
+
...orderedItems.map((i) => i.element),
|
|
81
|
+
].filter((element): element is HTMLElement => element != null)
|
|
82
|
+
onFocusFirst(candidates)
|
|
83
|
+
}}
|
|
84
|
+
onBlur={() => setIsShiftTabbing(false)}
|
|
85
|
+
ref={rootRef}
|
|
86
|
+
{...props}
|
|
87
|
+
>
|
|
88
|
+
{children}
|
|
89
|
+
</Slot>
|
|
90
|
+
</RovingTabIndexProvider>
|
|
91
|
+
)
|
|
92
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import {
|
|
2
|
+
FocusEvent,
|
|
3
|
+
MouseEvent,
|
|
4
|
+
KeyboardEvent,
|
|
5
|
+
ComponentPropsWithoutRef,
|
|
6
|
+
ElementType,
|
|
7
|
+
MutableRefObject,
|
|
8
|
+
} from "react"
|
|
9
|
+
import { createContext } from "../../hooks/createContext"
|
|
10
|
+
import { NODE_SELECTOR } from "./RovingTabIndexRoot"
|
|
11
|
+
|
|
12
|
+
export type RovingTabIndexItem = {
|
|
13
|
+
value: string
|
|
14
|
+
element: HTMLElement
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
type RovingTabIndexContext = {
|
|
18
|
+
currentFocusedValue: string | null
|
|
19
|
+
setFocusableId: (id: string) => void
|
|
20
|
+
onShiftTab: () => void
|
|
21
|
+
getOrderedItems: () => RovingTabIndexItem[]
|
|
22
|
+
elements: MutableRefObject<Map<string, HTMLElement>>
|
|
23
|
+
dir?: "horizontal" | "vertical"
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export const [RovingTabIndexProvider, useRovingTabIndexContext] =
|
|
27
|
+
createContext<RovingTabIndexContext>("rovingTabIndex")
|
|
28
|
+
|
|
29
|
+
export const useRovingTabIndex = (value: string) => {
|
|
30
|
+
const {
|
|
31
|
+
currentFocusedValue,
|
|
32
|
+
setFocusableId,
|
|
33
|
+
onShiftTab,
|
|
34
|
+
getOrderedItems,
|
|
35
|
+
elements,
|
|
36
|
+
dir,
|
|
37
|
+
} = useRovingTabIndexContext("rovingTabIndex")
|
|
38
|
+
|
|
39
|
+
return {
|
|
40
|
+
getOrderedItems,
|
|
41
|
+
dir,
|
|
42
|
+
isFocusable: currentFocusedValue === value,
|
|
43
|
+
getRovingProps: <T extends ElementType>(
|
|
44
|
+
props?: ComponentPropsWithoutRef<T>,
|
|
45
|
+
) => ({
|
|
46
|
+
...props,
|
|
47
|
+
ref: (element: HTMLElement | null) => {
|
|
48
|
+
if (element) {
|
|
49
|
+
elements.current.set(value, element)
|
|
50
|
+
} else {
|
|
51
|
+
elements.current.delete(value)
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
onMouseDown: (e: MouseEvent) => {
|
|
55
|
+
props?.onMouseDown?.(e)
|
|
56
|
+
if (e.target !== e.currentTarget) return
|
|
57
|
+
setFocusableId(value)
|
|
58
|
+
},
|
|
59
|
+
onKeyDown: (e: KeyboardEvent) => {
|
|
60
|
+
props?.onKeyDown?.(e)
|
|
61
|
+
if (e.target !== e.currentTarget) return
|
|
62
|
+
if (e.shiftKey && e.key === "Tab") {
|
|
63
|
+
onShiftTab()
|
|
64
|
+
return
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
onFocus: (e: FocusEvent) => {
|
|
68
|
+
props?.onFocus?.(e)
|
|
69
|
+
if (e.target !== e.currentTarget) return
|
|
70
|
+
setFocusableId(value)
|
|
71
|
+
},
|
|
72
|
+
[NODE_SELECTOR]: true,
|
|
73
|
+
tabIndex: currentFocusedValue === value ? 0 : -1,
|
|
74
|
+
}),
|
|
75
|
+
}
|
|
76
|
+
}
|