@radix-ui/react-roving-focus 1.0.5-rc.9 → 1.1.0-rc.2

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/dist/index.js.map CHANGED
@@ -1 +1,7 @@
1
- {"mappings":"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","sources":["packages/react/roving-focus/src/index.ts","packages/react/roving-focus/src/RovingFocusGroup.tsx"],"sourcesContent":["export {\n createRovingFocusGroupScope,\n //\n RovingFocusGroup,\n RovingFocusGroupItem,\n //\n Root,\n Item,\n} from './RovingFocusGroup';\nexport type { RovingFocusGroupProps, RovingFocusItemProps } from './RovingFocusGroup';\n","import * as React from 'react';\nimport { composeEventHandlers } from '@radix-ui/primitive';\nimport { createCollection } from '@radix-ui/react-collection';\nimport { useComposedRefs } from '@radix-ui/react-compose-refs';\nimport { createContextScope } from '@radix-ui/react-context';\nimport { useId } from '@radix-ui/react-id';\nimport { Primitive } from '@radix-ui/react-primitive';\nimport { useCallbackRef } from '@radix-ui/react-use-callback-ref';\nimport { useControllableState } from '@radix-ui/react-use-controllable-state';\nimport { useDirection } from '@radix-ui/react-direction';\n\nimport type * as Radix from '@radix-ui/react-primitive';\nimport type { Scope } from '@radix-ui/react-context';\n\nconst ENTRY_FOCUS = 'rovingFocusGroup.onEntryFocus';\nconst EVENT_OPTIONS = { bubbles: false, cancelable: true };\n\n/* -------------------------------------------------------------------------------------------------\n * RovingFocusGroup\n * -----------------------------------------------------------------------------------------------*/\n\nconst GROUP_NAME = 'RovingFocusGroup';\n\ntype ItemData = { id: string; focusable: boolean; active: boolean };\nconst [Collection, useCollection, createCollectionScope] = createCollection<\n HTMLSpanElement,\n ItemData\n>(GROUP_NAME);\n\ntype ScopedProps<P> = P & { __scopeRovingFocusGroup?: Scope };\nconst [createRovingFocusGroupContext, createRovingFocusGroupScope] = createContextScope(\n GROUP_NAME,\n [createCollectionScope]\n);\n\ntype Orientation = React.AriaAttributes['aria-orientation'];\ntype Direction = 'ltr' | 'rtl';\n\ninterface RovingFocusGroupOptions {\n /**\n * The orientation of the group.\n * Mainly so arrow navigation is done accordingly (left & right vs. up & down)\n */\n orientation?: Orientation;\n /**\n * The direction of navigation between items.\n */\n dir?: Direction;\n /**\n * Whether keyboard navigation should loop around\n * @defaultValue false\n */\n loop?: boolean;\n}\n\ntype RovingContextValue = RovingFocusGroupOptions & {\n currentTabStopId: string | null;\n onItemFocus(tabStopId: string): void;\n onItemShiftTab(): void;\n onFocusableItemAdd(): void;\n onFocusableItemRemove(): void;\n};\n\nconst [RovingFocusProvider, useRovingFocusContext] =\n createRovingFocusGroupContext<RovingContextValue>(GROUP_NAME);\n\ntype RovingFocusGroupElement = RovingFocusGroupImplElement;\ninterface RovingFocusGroupProps extends RovingFocusGroupImplProps {}\n\nconst RovingFocusGroup = React.forwardRef<RovingFocusGroupElement, RovingFocusGroupProps>(\n (props: ScopedProps<RovingFocusGroupProps>, forwardedRef) => {\n return (\n <Collection.Provider scope={props.__scopeRovingFocusGroup}>\n <Collection.Slot scope={props.__scopeRovingFocusGroup}>\n <RovingFocusGroupImpl {...props} ref={forwardedRef} />\n </Collection.Slot>\n </Collection.Provider>\n );\n }\n);\n\nRovingFocusGroup.displayName = GROUP_NAME;\n\n/* -----------------------------------------------------------------------------------------------*/\n\ntype RovingFocusGroupImplElement = React.ElementRef<typeof Primitive.div>;\ntype PrimitiveDivProps = Radix.ComponentPropsWithoutRef<typeof Primitive.div>;\ninterface RovingFocusGroupImplProps\n extends Omit<PrimitiveDivProps, 'dir'>,\n RovingFocusGroupOptions {\n currentTabStopId?: string | null;\n defaultCurrentTabStopId?: string;\n onCurrentTabStopIdChange?: (tabStopId: string | null) => void;\n onEntryFocus?: (event: Event) => void;\n preventScrollOnEntryFocus?: boolean;\n}\n\nconst RovingFocusGroupImpl = React.forwardRef<\n RovingFocusGroupImplElement,\n RovingFocusGroupImplProps\n>((props: ScopedProps<RovingFocusGroupImplProps>, forwardedRef) => {\n const {\n __scopeRovingFocusGroup,\n orientation,\n loop = false,\n dir,\n currentTabStopId: currentTabStopIdProp,\n defaultCurrentTabStopId,\n onCurrentTabStopIdChange,\n onEntryFocus,\n preventScrollOnEntryFocus = false,\n ...groupProps\n } = props;\n const ref = React.useRef<RovingFocusGroupImplElement>(null);\n const composedRefs = useComposedRefs(forwardedRef, ref);\n const direction = useDirection(dir);\n const [currentTabStopId = null, setCurrentTabStopId] = useControllableState({\n prop: currentTabStopIdProp,\n defaultProp: defaultCurrentTabStopId,\n onChange: onCurrentTabStopIdChange,\n });\n const [isTabbingBackOut, setIsTabbingBackOut] = React.useState(false);\n const handleEntryFocus = useCallbackRef(onEntryFocus);\n const getItems = useCollection(__scopeRovingFocusGroup);\n const isClickFocusRef = React.useRef(false);\n const [focusableItemsCount, setFocusableItemsCount] = React.useState(0);\n\n React.useEffect(() => {\n const node = ref.current;\n if (node) {\n node.addEventListener(ENTRY_FOCUS, handleEntryFocus);\n return () => node.removeEventListener(ENTRY_FOCUS, handleEntryFocus);\n }\n }, [handleEntryFocus]);\n\n return (\n <RovingFocusProvider\n scope={__scopeRovingFocusGroup}\n orientation={orientation}\n dir={direction}\n loop={loop}\n currentTabStopId={currentTabStopId}\n onItemFocus={React.useCallback(\n (tabStopId) => setCurrentTabStopId(tabStopId),\n [setCurrentTabStopId]\n )}\n onItemShiftTab={React.useCallback(() => setIsTabbingBackOut(true), [])}\n onFocusableItemAdd={React.useCallback(\n () => setFocusableItemsCount((prevCount) => prevCount + 1),\n []\n )}\n onFocusableItemRemove={React.useCallback(\n () => setFocusableItemsCount((prevCount) => prevCount - 1),\n []\n )}\n >\n <Primitive.div\n tabIndex={isTabbingBackOut || focusableItemsCount === 0 ? -1 : 0}\n data-orientation={orientation}\n {...groupProps}\n ref={composedRefs}\n style={{ outline: 'none', ...props.style }}\n onMouseDown={composeEventHandlers(props.onMouseDown, () => {\n isClickFocusRef.current = true;\n })}\n onFocus={composeEventHandlers(props.onFocus, (event) => {\n // We normally wouldn't need this check, because we already check\n // that the focus is on the current target and not bubbling to it.\n // We do this because Safari doesn't focus buttons when clicked, and\n // instead, the wrapper will get focused and not through a bubbling event.\n const isKeyboardFocus = !isClickFocusRef.current;\n\n if (event.target === event.currentTarget && isKeyboardFocus && !isTabbingBackOut) {\n const entryFocusEvent = new CustomEvent(ENTRY_FOCUS, EVENT_OPTIONS);\n event.currentTarget.dispatchEvent(entryFocusEvent);\n\n if (!entryFocusEvent.defaultPrevented) {\n const items = getItems().filter((item) => item.focusable);\n const activeItem = items.find((item) => item.active);\n const currentItem = items.find((item) => item.id === currentTabStopId);\n const candidateItems = [activeItem, currentItem, ...items].filter(\n Boolean\n ) as typeof items;\n const candidateNodes = candidateItems.map((item) => item.ref.current!);\n focusFirst(candidateNodes, preventScrollOnEntryFocus);\n }\n }\n\n isClickFocusRef.current = false;\n })}\n onBlur={composeEventHandlers(props.onBlur, () => setIsTabbingBackOut(false))}\n />\n </RovingFocusProvider>\n );\n});\n\n/* -------------------------------------------------------------------------------------------------\n * RovingFocusGroupItem\n * -----------------------------------------------------------------------------------------------*/\n\nconst ITEM_NAME = 'RovingFocusGroupItem';\n\ntype RovingFocusItemElement = React.ElementRef<typeof Primitive.span>;\ntype PrimitiveSpanProps = Radix.ComponentPropsWithoutRef<typeof Primitive.span>;\ninterface RovingFocusItemProps extends PrimitiveSpanProps {\n tabStopId?: string;\n focusable?: boolean;\n active?: boolean;\n}\n\nconst RovingFocusGroupItem = React.forwardRef<RovingFocusItemElement, RovingFocusItemProps>(\n (props: ScopedProps<RovingFocusItemProps>, forwardedRef) => {\n const {\n __scopeRovingFocusGroup,\n focusable = true,\n active = false,\n tabStopId,\n ...itemProps\n } = props;\n const autoId = useId();\n const id = tabStopId || autoId;\n const context = useRovingFocusContext(ITEM_NAME, __scopeRovingFocusGroup);\n const isCurrentTabStop = context.currentTabStopId === id;\n const getItems = useCollection(__scopeRovingFocusGroup);\n\n const { onFocusableItemAdd, onFocusableItemRemove } = context;\n\n React.useEffect(() => {\n if (focusable) {\n onFocusableItemAdd();\n return () => onFocusableItemRemove();\n }\n }, [focusable, onFocusableItemAdd, onFocusableItemRemove]);\n\n return (\n <Collection.ItemSlot\n scope={__scopeRovingFocusGroup}\n id={id}\n focusable={focusable}\n active={active}\n >\n <Primitive.span\n tabIndex={isCurrentTabStop ? 0 : -1}\n data-orientation={context.orientation}\n {...itemProps}\n ref={forwardedRef}\n onMouseDown={composeEventHandlers(props.onMouseDown, (event) => {\n // We prevent focusing non-focusable items on `mousedown`.\n // Even though the item has tabIndex={-1}, that only means take it out of the tab order.\n if (!focusable) event.preventDefault();\n // Safari doesn't focus a button when clicked so we run our logic on mousedown also\n else context.onItemFocus(id);\n })}\n onFocus={composeEventHandlers(props.onFocus, () => context.onItemFocus(id))}\n onKeyDown={composeEventHandlers(props.onKeyDown, (event) => {\n if (event.key === 'Tab' && event.shiftKey) {\n context.onItemShiftTab();\n return;\n }\n\n if (event.target !== event.currentTarget) return;\n\n const focusIntent = getFocusIntent(event, context.orientation, context.dir);\n\n if (focusIntent !== undefined) {\n if (event.metaKey || event.ctrlKey || event.altKey || event.shiftKey) return;\n event.preventDefault();\n const items = getItems().filter((item) => item.focusable);\n let candidateNodes = items.map((item) => item.ref.current!);\n\n if (focusIntent === 'last') candidateNodes.reverse();\n else if (focusIntent === 'prev' || focusIntent === 'next') {\n if (focusIntent === 'prev') candidateNodes.reverse();\n const currentIndex = candidateNodes.indexOf(event.currentTarget);\n candidateNodes = context.loop\n ? wrapArray(candidateNodes, currentIndex + 1)\n : candidateNodes.slice(currentIndex + 1);\n }\n\n /**\n * Imperative focus during keydown is risky so we prevent React's batching updates\n * to avoid potential bugs. See: https://github.com/facebook/react/issues/20332\n */\n setTimeout(() => focusFirst(candidateNodes));\n }\n })}\n />\n </Collection.ItemSlot>\n );\n }\n);\n\nRovingFocusGroupItem.displayName = ITEM_NAME;\n\n/* -----------------------------------------------------------------------------------------------*/\n\n// prettier-ignore\nconst MAP_KEY_TO_FOCUS_INTENT: Record<string, FocusIntent> = {\n ArrowLeft: 'prev', ArrowUp: 'prev',\n ArrowRight: 'next', ArrowDown: 'next',\n PageUp: 'first', Home: 'first',\n PageDown: 'last', End: 'last',\n};\n\nfunction getDirectionAwareKey(key: string, dir?: Direction) {\n if (dir !== 'rtl') return key;\n return key === 'ArrowLeft' ? 'ArrowRight' : key === 'ArrowRight' ? 'ArrowLeft' : key;\n}\n\ntype FocusIntent = 'first' | 'last' | 'prev' | 'next';\n\nfunction getFocusIntent(event: React.KeyboardEvent, orientation?: Orientation, dir?: Direction) {\n const key = getDirectionAwareKey(event.key, dir);\n if (orientation === 'vertical' && ['ArrowLeft', 'ArrowRight'].includes(key)) return undefined;\n if (orientation === 'horizontal' && ['ArrowUp', 'ArrowDown'].includes(key)) return undefined;\n return MAP_KEY_TO_FOCUS_INTENT[key];\n}\n\nfunction focusFirst(candidates: HTMLElement[], preventScroll = false) {\n const PREVIOUSLY_FOCUSED_ELEMENT = document.activeElement;\n for (const candidate of candidates) {\n // if focus is already where we want to go, we don't want to keep going through the candidates\n if (candidate === PREVIOUSLY_FOCUSED_ELEMENT) return;\n candidate.focus({ preventScroll });\n if (document.activeElement !== PREVIOUSLY_FOCUSED_ELEMENT) return;\n }\n}\n\n/**\n * Wraps an array around itself at a given start index\n * Example: `wrapArray(['a', 'b', 'c', 'd'], 2) === ['c', 'd', 'a', 'b']`\n */\nfunction wrapArray<T>(array: T[], startIndex: number) {\n return array.map((_, index) => array[(startIndex + index) % array.length]);\n}\n\nconst Root = RovingFocusGroup;\nconst Item = RovingFocusGroupItem;\n\nexport {\n createRovingFocusGroupScope,\n //\n RovingFocusGroup,\n RovingFocusGroupItem,\n //\n Root,\n Item,\n};\nexport type { RovingFocusGroupProps, RovingFocusItemProps };\n"],"names":["createRovingFocusGroupScope","RovingFocusGroup","RovingFocusGroupItem","Root","Item","React","composeEventHandlers","createCollection","useComposedRefs","createContextScope","useId","Primitive","useCallbackRef","useControllableState","useDirection","ENTRY_FOCUS","EVENT_OPTIONS","bubbles","cancelable","GROUP_NAME","Collection","useCollection","createCollectionScope","createRovingFocusGroupContext","RovingFocusProvider","useRovingFocusContext","forwardRef","props","forwardedRef","__scopeRovingFocusGroup","RovingFocusGroupImpl","orientation","loop","dir","currentTabStopId","currentTabStopIdProp","defaultCurrentTabStopId","onCurrentTabStopIdChange","onEntryFocus","preventScrollOnEntryFocus","groupProps","ref","useRef","composedRefs","direction","setCurrentTabStopId","prop","defaultProp","onChange","isTabbingBackOut","setIsTabbingBackOut","useState","handleEntryFocus","getItems","isClickFocusRef","focusableItemsCount","setFocusableItemsCount","useEffect","node","current","addEventListener","removeEventListener","useCallback","tabStopId","prevCount","outline","style","onMouseDown","onFocus","event","isKeyboardFocus","target","currentTarget","entryFocusEvent","CustomEvent","dispatchEvent","defaultPrevented","items","filter","item","focusable","activeItem","find","active","currentItem","id","candidateItems","Boolean","candidateNodes","map","focusFirst","onBlur","ITEM_NAME","itemProps","autoId","context","isCurrentTabStop","onFocusableItemAdd","onFocusableItemRemove","preventDefault","onItemFocus","onKeyDown","key","shiftKey","onItemShiftTab","focusIntent","getFocusIntent","undefined","metaKey","ctrlKey","altKey","reverse","currentIndex","indexOf","wrapArray","slice","setTimeout","MAP_KEY_TO_FOCUS_INTENT","ArrowLeft","ArrowUp","ArrowRight","ArrowDown","PageUp","Home","PageDown","End","getDirectionAwareKey","includes","candidates","preventScroll","PREVIOUSLY_FOCUSED_ELEMENT","document","activeElement","candidate","focus","array","startIndex","_","index","length"],"version":3,"file":"index.js.map"}
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/RovingFocusGroup.tsx"],
4
+ "sourcesContent": ["import * as React from 'react';\nimport { composeEventHandlers } from '@radix-ui/primitive';\nimport { createCollection } from '@radix-ui/react-collection';\nimport { useComposedRefs } from '@radix-ui/react-compose-refs';\nimport { createContextScope } from '@radix-ui/react-context';\nimport { useId } from '@radix-ui/react-id';\nimport { Primitive } from '@radix-ui/react-primitive';\nimport { useCallbackRef } from '@radix-ui/react-use-callback-ref';\nimport { useControllableState } from '@radix-ui/react-use-controllable-state';\nimport { useDirection } from '@radix-ui/react-direction';\n\nimport type * as Radix from '@radix-ui/react-primitive';\nimport type { Scope } from '@radix-ui/react-context';\n\nconst ENTRY_FOCUS = 'rovingFocusGroup.onEntryFocus';\nconst EVENT_OPTIONS = { bubbles: false, cancelable: true };\n\n/* -------------------------------------------------------------------------------------------------\n * RovingFocusGroup\n * -----------------------------------------------------------------------------------------------*/\n\nconst GROUP_NAME = 'RovingFocusGroup';\n\ntype ItemData = { id: string; focusable: boolean; active: boolean };\nconst [Collection, useCollection, createCollectionScope] = createCollection<\n HTMLSpanElement,\n ItemData\n>(GROUP_NAME);\n\ntype ScopedProps<P> = P & { __scopeRovingFocusGroup?: Scope };\nconst [createRovingFocusGroupContext, createRovingFocusGroupScope] = createContextScope(\n GROUP_NAME,\n [createCollectionScope]\n);\n\ntype Orientation = React.AriaAttributes['aria-orientation'];\ntype Direction = 'ltr' | 'rtl';\n\ninterface RovingFocusGroupOptions {\n /**\n * The orientation of the group.\n * Mainly so arrow navigation is done accordingly (left & right vs. up & down)\n */\n orientation?: Orientation;\n /**\n * The direction of navigation between items.\n */\n dir?: Direction;\n /**\n * Whether keyboard navigation should loop around\n * @defaultValue false\n */\n loop?: boolean;\n}\n\ntype RovingContextValue = RovingFocusGroupOptions & {\n currentTabStopId: string | null;\n onItemFocus(tabStopId: string): void;\n onItemShiftTab(): void;\n onFocusableItemAdd(): void;\n onFocusableItemRemove(): void;\n};\n\nconst [RovingFocusProvider, useRovingFocusContext] =\n createRovingFocusGroupContext<RovingContextValue>(GROUP_NAME);\n\ntype RovingFocusGroupElement = RovingFocusGroupImplElement;\ninterface RovingFocusGroupProps extends RovingFocusGroupImplProps {}\n\nconst RovingFocusGroup = React.forwardRef<RovingFocusGroupElement, RovingFocusGroupProps>(\n (props: ScopedProps<RovingFocusGroupProps>, forwardedRef) => {\n return (\n <Collection.Provider scope={props.__scopeRovingFocusGroup}>\n <Collection.Slot scope={props.__scopeRovingFocusGroup}>\n <RovingFocusGroupImpl {...props} ref={forwardedRef} />\n </Collection.Slot>\n </Collection.Provider>\n );\n }\n);\n\nRovingFocusGroup.displayName = GROUP_NAME;\n\n/* -----------------------------------------------------------------------------------------------*/\n\ntype RovingFocusGroupImplElement = React.ElementRef<typeof Primitive.div>;\ntype PrimitiveDivProps = Radix.ComponentPropsWithoutRef<typeof Primitive.div>;\ninterface RovingFocusGroupImplProps\n extends Omit<PrimitiveDivProps, 'dir'>,\n RovingFocusGroupOptions {\n currentTabStopId?: string | null;\n defaultCurrentTabStopId?: string;\n onCurrentTabStopIdChange?: (tabStopId: string | null) => void;\n onEntryFocus?: (event: Event) => void;\n preventScrollOnEntryFocus?: boolean;\n}\n\nconst RovingFocusGroupImpl = React.forwardRef<\n RovingFocusGroupImplElement,\n RovingFocusGroupImplProps\n>((props: ScopedProps<RovingFocusGroupImplProps>, forwardedRef) => {\n const {\n __scopeRovingFocusGroup,\n orientation,\n loop = false,\n dir,\n currentTabStopId: currentTabStopIdProp,\n defaultCurrentTabStopId,\n onCurrentTabStopIdChange,\n onEntryFocus,\n preventScrollOnEntryFocus = false,\n ...groupProps\n } = props;\n const ref = React.useRef<RovingFocusGroupImplElement>(null);\n const composedRefs = useComposedRefs(forwardedRef, ref);\n const direction = useDirection(dir);\n const [currentTabStopId = null, setCurrentTabStopId] = useControllableState({\n prop: currentTabStopIdProp,\n defaultProp: defaultCurrentTabStopId,\n onChange: onCurrentTabStopIdChange,\n });\n const [isTabbingBackOut, setIsTabbingBackOut] = React.useState(false);\n const handleEntryFocus = useCallbackRef(onEntryFocus);\n const getItems = useCollection(__scopeRovingFocusGroup);\n const isClickFocusRef = React.useRef(false);\n const [focusableItemsCount, setFocusableItemsCount] = React.useState(0);\n\n React.useEffect(() => {\n const node = ref.current;\n if (node) {\n node.addEventListener(ENTRY_FOCUS, handleEntryFocus);\n return () => node.removeEventListener(ENTRY_FOCUS, handleEntryFocus);\n }\n }, [handleEntryFocus]);\n\n return (\n <RovingFocusProvider\n scope={__scopeRovingFocusGroup}\n orientation={orientation}\n dir={direction}\n loop={loop}\n currentTabStopId={currentTabStopId}\n onItemFocus={React.useCallback(\n (tabStopId) => setCurrentTabStopId(tabStopId),\n [setCurrentTabStopId]\n )}\n onItemShiftTab={React.useCallback(() => setIsTabbingBackOut(true), [])}\n onFocusableItemAdd={React.useCallback(\n () => setFocusableItemsCount((prevCount) => prevCount + 1),\n []\n )}\n onFocusableItemRemove={React.useCallback(\n () => setFocusableItemsCount((prevCount) => prevCount - 1),\n []\n )}\n >\n <Primitive.div\n tabIndex={isTabbingBackOut || focusableItemsCount === 0 ? -1 : 0}\n data-orientation={orientation}\n {...groupProps}\n ref={composedRefs}\n style={{ outline: 'none', ...props.style }}\n onMouseDown={composeEventHandlers(props.onMouseDown, () => {\n isClickFocusRef.current = true;\n })}\n onFocus={composeEventHandlers(props.onFocus, (event) => {\n // We normally wouldn't need this check, because we already check\n // that the focus is on the current target and not bubbling to it.\n // We do this because Safari doesn't focus buttons when clicked, and\n // instead, the wrapper will get focused and not through a bubbling event.\n const isKeyboardFocus = !isClickFocusRef.current;\n\n if (event.target === event.currentTarget && isKeyboardFocus && !isTabbingBackOut) {\n const entryFocusEvent = new CustomEvent(ENTRY_FOCUS, EVENT_OPTIONS);\n event.currentTarget.dispatchEvent(entryFocusEvent);\n\n if (!entryFocusEvent.defaultPrevented) {\n const items = getItems().filter((item) => item.focusable);\n const activeItem = items.find((item) => item.active);\n const currentItem = items.find((item) => item.id === currentTabStopId);\n const candidateItems = [activeItem, currentItem, ...items].filter(\n Boolean\n ) as typeof items;\n const candidateNodes = candidateItems.map((item) => item.ref.current!);\n focusFirst(candidateNodes, preventScrollOnEntryFocus);\n }\n }\n\n isClickFocusRef.current = false;\n })}\n onBlur={composeEventHandlers(props.onBlur, () => setIsTabbingBackOut(false))}\n />\n </RovingFocusProvider>\n );\n});\n\n/* -------------------------------------------------------------------------------------------------\n * RovingFocusGroupItem\n * -----------------------------------------------------------------------------------------------*/\n\nconst ITEM_NAME = 'RovingFocusGroupItem';\n\ntype RovingFocusItemElement = React.ElementRef<typeof Primitive.span>;\ntype PrimitiveSpanProps = Radix.ComponentPropsWithoutRef<typeof Primitive.span>;\ninterface RovingFocusItemProps extends PrimitiveSpanProps {\n tabStopId?: string;\n focusable?: boolean;\n active?: boolean;\n}\n\nconst RovingFocusGroupItem = React.forwardRef<RovingFocusItemElement, RovingFocusItemProps>(\n (props: ScopedProps<RovingFocusItemProps>, forwardedRef) => {\n const {\n __scopeRovingFocusGroup,\n focusable = true,\n active = false,\n tabStopId,\n ...itemProps\n } = props;\n const autoId = useId();\n const id = tabStopId || autoId;\n const context = useRovingFocusContext(ITEM_NAME, __scopeRovingFocusGroup);\n const isCurrentTabStop = context.currentTabStopId === id;\n const getItems = useCollection(__scopeRovingFocusGroup);\n\n const { onFocusableItemAdd, onFocusableItemRemove } = context;\n\n React.useEffect(() => {\n if (focusable) {\n onFocusableItemAdd();\n return () => onFocusableItemRemove();\n }\n }, [focusable, onFocusableItemAdd, onFocusableItemRemove]);\n\n return (\n <Collection.ItemSlot\n scope={__scopeRovingFocusGroup}\n id={id}\n focusable={focusable}\n active={active}\n >\n <Primitive.span\n tabIndex={isCurrentTabStop ? 0 : -1}\n data-orientation={context.orientation}\n {...itemProps}\n ref={forwardedRef}\n onMouseDown={composeEventHandlers(props.onMouseDown, (event) => {\n // We prevent focusing non-focusable items on `mousedown`.\n // Even though the item has tabIndex={-1}, that only means take it out of the tab order.\n if (!focusable) event.preventDefault();\n // Safari doesn't focus a button when clicked so we run our logic on mousedown also\n else context.onItemFocus(id);\n })}\n onFocus={composeEventHandlers(props.onFocus, () => context.onItemFocus(id))}\n onKeyDown={composeEventHandlers(props.onKeyDown, (event) => {\n if (event.key === 'Tab' && event.shiftKey) {\n context.onItemShiftTab();\n return;\n }\n\n if (event.target !== event.currentTarget) return;\n\n const focusIntent = getFocusIntent(event, context.orientation, context.dir);\n\n if (focusIntent !== undefined) {\n if (event.metaKey || event.ctrlKey || event.altKey || event.shiftKey) return;\n event.preventDefault();\n const items = getItems().filter((item) => item.focusable);\n let candidateNodes = items.map((item) => item.ref.current!);\n\n if (focusIntent === 'last') candidateNodes.reverse();\n else if (focusIntent === 'prev' || focusIntent === 'next') {\n if (focusIntent === 'prev') candidateNodes.reverse();\n const currentIndex = candidateNodes.indexOf(event.currentTarget);\n candidateNodes = context.loop\n ? wrapArray(candidateNodes, currentIndex + 1)\n : candidateNodes.slice(currentIndex + 1);\n }\n\n /**\n * Imperative focus during keydown is risky so we prevent React's batching updates\n * to avoid potential bugs. See: https://github.com/facebook/react/issues/20332\n */\n setTimeout(() => focusFirst(candidateNodes));\n }\n })}\n />\n </Collection.ItemSlot>\n );\n }\n);\n\nRovingFocusGroupItem.displayName = ITEM_NAME;\n\n/* -----------------------------------------------------------------------------------------------*/\n\n// prettier-ignore\nconst MAP_KEY_TO_FOCUS_INTENT: Record<string, FocusIntent> = {\n ArrowLeft: 'prev', ArrowUp: 'prev',\n ArrowRight: 'next', ArrowDown: 'next',\n PageUp: 'first', Home: 'first',\n PageDown: 'last', End: 'last',\n};\n\nfunction getDirectionAwareKey(key: string, dir?: Direction) {\n if (dir !== 'rtl') return key;\n return key === 'ArrowLeft' ? 'ArrowRight' : key === 'ArrowRight' ? 'ArrowLeft' : key;\n}\n\ntype FocusIntent = 'first' | 'last' | 'prev' | 'next';\n\nfunction getFocusIntent(event: React.KeyboardEvent, orientation?: Orientation, dir?: Direction) {\n const key = getDirectionAwareKey(event.key, dir);\n if (orientation === 'vertical' && ['ArrowLeft', 'ArrowRight'].includes(key)) return undefined;\n if (orientation === 'horizontal' && ['ArrowUp', 'ArrowDown'].includes(key)) return undefined;\n return MAP_KEY_TO_FOCUS_INTENT[key];\n}\n\nfunction focusFirst(candidates: HTMLElement[], preventScroll = false) {\n const PREVIOUSLY_FOCUSED_ELEMENT = document.activeElement;\n for (const candidate of candidates) {\n // if focus is already where we want to go, we don't want to keep going through the candidates\n if (candidate === PREVIOUSLY_FOCUSED_ELEMENT) return;\n candidate.focus({ preventScroll });\n if (document.activeElement !== PREVIOUSLY_FOCUSED_ELEMENT) return;\n }\n}\n\n/**\n * Wraps an array around itself at a given start index\n * Example: `wrapArray(['a', 'b', 'c', 'd'], 2) === ['c', 'd', 'a', 'b']`\n */\nfunction wrapArray<T>(array: T[], startIndex: number) {\n return array.map((_, index) => array[(startIndex + index) % array.length]);\n}\n\nconst Root = RovingFocusGroup;\nconst Item = RovingFocusGroupItem;\n\nexport {\n createRovingFocusGroupScope,\n //\n RovingFocusGroup,\n RovingFocusGroupItem,\n //\n Root,\n Item,\n};\nexport type { RovingFocusGroupProps, RovingFocusItemProps };\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
package/dist/index.mjs CHANGED
@@ -1,260 +1,228 @@
1
- import $98Iye$babelruntimehelpersesmextends from "@babel/runtime/helpers/esm/extends";
2
- import {forwardRef as $98Iye$forwardRef, createElement as $98Iye$createElement, useRef as $98Iye$useRef, useState as $98Iye$useState, useEffect as $98Iye$useEffect, useCallback as $98Iye$useCallback} from "react";
3
- import {composeEventHandlers as $98Iye$composeEventHandlers} from "@radix-ui/primitive";
4
- import {createCollection as $98Iye$createCollection} from "@radix-ui/react-collection";
5
- import {useComposedRefs as $98Iye$useComposedRefs} from "@radix-ui/react-compose-refs";
6
- import {createContextScope as $98Iye$createContextScope} from "@radix-ui/react-context";
7
- import {useId as $98Iye$useId} from "@radix-ui/react-id";
8
- import {Primitive as $98Iye$Primitive} from "@radix-ui/react-primitive";
9
- import {useCallbackRef as $98Iye$useCallbackRef} from "@radix-ui/react-use-callback-ref";
10
- import {useControllableState as $98Iye$useControllableState} from "@radix-ui/react-use-controllable-state";
11
- import {useDirection as $98Iye$useDirection} from "@radix-ui/react-direction";
12
-
13
-
14
-
15
-
16
-
17
-
18
-
19
-
20
-
21
-
22
-
23
-
24
- const $d7bdfb9eb0fdf311$var$ENTRY_FOCUS = 'rovingFocusGroup.onEntryFocus';
25
- const $d7bdfb9eb0fdf311$var$EVENT_OPTIONS = {
26
- bubbles: false,
27
- cancelable: true
28
- };
29
- /* -------------------------------------------------------------------------------------------------
30
- * RovingFocusGroup
31
- * -----------------------------------------------------------------------------------------------*/ const $d7bdfb9eb0fdf311$var$GROUP_NAME = 'RovingFocusGroup';
32
- const [$d7bdfb9eb0fdf311$var$Collection, $d7bdfb9eb0fdf311$var$useCollection, $d7bdfb9eb0fdf311$var$createCollectionScope] = $98Iye$createCollection($d7bdfb9eb0fdf311$var$GROUP_NAME);
33
- const [$d7bdfb9eb0fdf311$var$createRovingFocusGroupContext, $d7bdfb9eb0fdf311$export$c7109489551a4f4] = $98Iye$createContextScope($d7bdfb9eb0fdf311$var$GROUP_NAME, [
34
- $d7bdfb9eb0fdf311$var$createCollectionScope
35
- ]);
36
- const [$d7bdfb9eb0fdf311$var$RovingFocusProvider, $d7bdfb9eb0fdf311$var$useRovingFocusContext] = $d7bdfb9eb0fdf311$var$createRovingFocusGroupContext($d7bdfb9eb0fdf311$var$GROUP_NAME);
37
- const $d7bdfb9eb0fdf311$export$8699f7c8af148338 = /*#__PURE__*/ $98Iye$forwardRef((props, forwardedRef)=>{
38
- return /*#__PURE__*/ $98Iye$createElement($d7bdfb9eb0fdf311$var$Collection.Provider, {
39
- scope: props.__scopeRovingFocusGroup
40
- }, /*#__PURE__*/ $98Iye$createElement($d7bdfb9eb0fdf311$var$Collection.Slot, {
41
- scope: props.__scopeRovingFocusGroup
42
- }, /*#__PURE__*/ $98Iye$createElement($d7bdfb9eb0fdf311$var$RovingFocusGroupImpl, $98Iye$babelruntimehelpersesmextends({}, props, {
43
- ref: forwardedRef
44
- }))));
45
- });
46
- /*#__PURE__*/ Object.assign($d7bdfb9eb0fdf311$export$8699f7c8af148338, {
47
- displayName: $d7bdfb9eb0fdf311$var$GROUP_NAME
48
- });
49
- /* -----------------------------------------------------------------------------------------------*/ const $d7bdfb9eb0fdf311$var$RovingFocusGroupImpl = /*#__PURE__*/ $98Iye$forwardRef((props, forwardedRef)=>{
50
- const { __scopeRovingFocusGroup: __scopeRovingFocusGroup , orientation: orientation , loop: loop = false , dir: dir , currentTabStopId: currentTabStopIdProp , defaultCurrentTabStopId: defaultCurrentTabStopId , onCurrentTabStopIdChange: onCurrentTabStopIdChange , onEntryFocus: onEntryFocus , preventScrollOnEntryFocus: preventScrollOnEntryFocus = false , ...groupProps } = props;
51
- const ref = $98Iye$useRef(null);
52
- const composedRefs = $98Iye$useComposedRefs(forwardedRef, ref);
53
- const direction = $98Iye$useDirection(dir);
54
- const [currentTabStopId = null, setCurrentTabStopId] = $98Iye$useControllableState({
55
- prop: currentTabStopIdProp,
56
- defaultProp: defaultCurrentTabStopId,
57
- onChange: onCurrentTabStopIdChange
58
- });
59
- const [isTabbingBackOut, setIsTabbingBackOut] = $98Iye$useState(false);
60
- const handleEntryFocus = $98Iye$useCallbackRef(onEntryFocus);
61
- const getItems = $d7bdfb9eb0fdf311$var$useCollection(__scopeRovingFocusGroup);
62
- const isClickFocusRef = $98Iye$useRef(false);
63
- const [focusableItemsCount, setFocusableItemsCount] = $98Iye$useState(0);
64
- $98Iye$useEffect(()=>{
65
- const node = ref.current;
66
- if (node) {
67
- node.addEventListener($d7bdfb9eb0fdf311$var$ENTRY_FOCUS, handleEntryFocus);
68
- return ()=>node.removeEventListener($d7bdfb9eb0fdf311$var$ENTRY_FOCUS, handleEntryFocus)
69
- ;
70
- }
71
- }, [
72
- handleEntryFocus
73
- ]);
74
- return /*#__PURE__*/ $98Iye$createElement($d7bdfb9eb0fdf311$var$RovingFocusProvider, {
75
- scope: __scopeRovingFocusGroup,
76
- orientation: orientation,
77
- dir: direction,
78
- loop: loop,
79
- currentTabStopId: currentTabStopId,
80
- onItemFocus: $98Iye$useCallback((tabStopId)=>setCurrentTabStopId(tabStopId)
81
- , [
82
- setCurrentTabStopId
83
- ]),
84
- onItemShiftTab: $98Iye$useCallback(()=>setIsTabbingBackOut(true)
85
- , []),
86
- onFocusableItemAdd: $98Iye$useCallback(()=>setFocusableItemsCount((prevCount)=>prevCount + 1
87
- )
88
- , []),
89
- onFocusableItemRemove: $98Iye$useCallback(()=>setFocusableItemsCount((prevCount)=>prevCount - 1
90
- )
91
- , [])
92
- }, /*#__PURE__*/ $98Iye$createElement($98Iye$Primitive.div, $98Iye$babelruntimehelpersesmextends({
93
- tabIndex: isTabbingBackOut || focusableItemsCount === 0 ? -1 : 0,
94
- "data-orientation": orientation
95
- }, groupProps, {
96
- ref: composedRefs,
97
- style: {
98
- outline: 'none',
99
- ...props.style
100
- },
101
- onMouseDown: $98Iye$composeEventHandlers(props.onMouseDown, ()=>{
1
+ "use client";
2
+
3
+ // packages/react/roving-focus/src/RovingFocusGroup.tsx
4
+ import * as React from "react";
5
+ import { composeEventHandlers } from "@radix-ui/primitive";
6
+ import { createCollection } from "@radix-ui/react-collection";
7
+ import { useComposedRefs } from "@radix-ui/react-compose-refs";
8
+ import { createContextScope } from "@radix-ui/react-context";
9
+ import { useId } from "@radix-ui/react-id";
10
+ import { Primitive } from "@radix-ui/react-primitive";
11
+ import { useCallbackRef } from "@radix-ui/react-use-callback-ref";
12
+ import { useControllableState } from "@radix-ui/react-use-controllable-state";
13
+ import { useDirection } from "@radix-ui/react-direction";
14
+ import { jsx } from "react/jsx-runtime";
15
+ var ENTRY_FOCUS = "rovingFocusGroup.onEntryFocus";
16
+ var EVENT_OPTIONS = { bubbles: false, cancelable: true };
17
+ var GROUP_NAME = "RovingFocusGroup";
18
+ var [Collection, useCollection, createCollectionScope] = createCollection(GROUP_NAME);
19
+ var [createRovingFocusGroupContext, createRovingFocusGroupScope] = createContextScope(
20
+ GROUP_NAME,
21
+ [createCollectionScope]
22
+ );
23
+ var [RovingFocusProvider, useRovingFocusContext] = createRovingFocusGroupContext(GROUP_NAME);
24
+ var RovingFocusGroup = React.forwardRef(
25
+ (props, forwardedRef) => {
26
+ return /* @__PURE__ */ jsx(Collection.Provider, { scope: props.__scopeRovingFocusGroup, children: /* @__PURE__ */ jsx(Collection.Slot, { scope: props.__scopeRovingFocusGroup, children: /* @__PURE__ */ jsx(RovingFocusGroupImpl, { ...props, ref: forwardedRef }) }) });
27
+ }
28
+ );
29
+ RovingFocusGroup.displayName = GROUP_NAME;
30
+ var RovingFocusGroupImpl = React.forwardRef((props, forwardedRef) => {
31
+ const {
32
+ __scopeRovingFocusGroup,
33
+ orientation,
34
+ loop = false,
35
+ dir,
36
+ currentTabStopId: currentTabStopIdProp,
37
+ defaultCurrentTabStopId,
38
+ onCurrentTabStopIdChange,
39
+ onEntryFocus,
40
+ preventScrollOnEntryFocus = false,
41
+ ...groupProps
42
+ } = props;
43
+ const ref = React.useRef(null);
44
+ const composedRefs = useComposedRefs(forwardedRef, ref);
45
+ const direction = useDirection(dir);
46
+ const [currentTabStopId = null, setCurrentTabStopId] = useControllableState({
47
+ prop: currentTabStopIdProp,
48
+ defaultProp: defaultCurrentTabStopId,
49
+ onChange: onCurrentTabStopIdChange
50
+ });
51
+ const [isTabbingBackOut, setIsTabbingBackOut] = React.useState(false);
52
+ const handleEntryFocus = useCallbackRef(onEntryFocus);
53
+ const getItems = useCollection(__scopeRovingFocusGroup);
54
+ const isClickFocusRef = React.useRef(false);
55
+ const [focusableItemsCount, setFocusableItemsCount] = React.useState(0);
56
+ React.useEffect(() => {
57
+ const node = ref.current;
58
+ if (node) {
59
+ node.addEventListener(ENTRY_FOCUS, handleEntryFocus);
60
+ return () => node.removeEventListener(ENTRY_FOCUS, handleEntryFocus);
61
+ }
62
+ }, [handleEntryFocus]);
63
+ return /* @__PURE__ */ jsx(
64
+ RovingFocusProvider,
65
+ {
66
+ scope: __scopeRovingFocusGroup,
67
+ orientation,
68
+ dir: direction,
69
+ loop,
70
+ currentTabStopId,
71
+ onItemFocus: React.useCallback(
72
+ (tabStopId) => setCurrentTabStopId(tabStopId),
73
+ [setCurrentTabStopId]
74
+ ),
75
+ onItemShiftTab: React.useCallback(() => setIsTabbingBackOut(true), []),
76
+ onFocusableItemAdd: React.useCallback(
77
+ () => setFocusableItemsCount((prevCount) => prevCount + 1),
78
+ []
79
+ ),
80
+ onFocusableItemRemove: React.useCallback(
81
+ () => setFocusableItemsCount((prevCount) => prevCount - 1),
82
+ []
83
+ ),
84
+ children: /* @__PURE__ */ jsx(
85
+ Primitive.div,
86
+ {
87
+ tabIndex: isTabbingBackOut || focusableItemsCount === 0 ? -1 : 0,
88
+ "data-orientation": orientation,
89
+ ...groupProps,
90
+ ref: composedRefs,
91
+ style: { outline: "none", ...props.style },
92
+ onMouseDown: composeEventHandlers(props.onMouseDown, () => {
102
93
  isClickFocusRef.current = true;
103
- }),
104
- onFocus: $98Iye$composeEventHandlers(props.onFocus, (event)=>{
105
- // We normally wouldn't need this check, because we already check
106
- // that the focus is on the current target and not bubbling to it.
107
- // We do this because Safari doesn't focus buttons when clicked, and
108
- // instead, the wrapper will get focused and not through a bubbling event.
94
+ }),
95
+ onFocus: composeEventHandlers(props.onFocus, (event) => {
109
96
  const isKeyboardFocus = !isClickFocusRef.current;
110
97
  if (event.target === event.currentTarget && isKeyboardFocus && !isTabbingBackOut) {
111
- const entryFocusEvent = new CustomEvent($d7bdfb9eb0fdf311$var$ENTRY_FOCUS, $d7bdfb9eb0fdf311$var$EVENT_OPTIONS);
112
- event.currentTarget.dispatchEvent(entryFocusEvent);
113
- if (!entryFocusEvent.defaultPrevented) {
114
- const items = getItems().filter((item)=>item.focusable
115
- );
116
- const activeItem = items.find((item)=>item.active
117
- );
118
- const currentItem = items.find((item)=>item.id === currentTabStopId
119
- );
120
- const candidateItems = [
121
- activeItem,
122
- currentItem,
123
- ...items
124
- ].filter(Boolean);
125
- const candidateNodes = candidateItems.map((item)=>item.ref.current
126
- );
127
- $d7bdfb9eb0fdf311$var$focusFirst(candidateNodes, preventScrollOnEntryFocus);
128
- }
98
+ const entryFocusEvent = new CustomEvent(ENTRY_FOCUS, EVENT_OPTIONS);
99
+ event.currentTarget.dispatchEvent(entryFocusEvent);
100
+ if (!entryFocusEvent.defaultPrevented) {
101
+ const items = getItems().filter((item) => item.focusable);
102
+ const activeItem = items.find((item) => item.active);
103
+ const currentItem = items.find((item) => item.id === currentTabStopId);
104
+ const candidateItems = [activeItem, currentItem, ...items].filter(
105
+ Boolean
106
+ );
107
+ const candidateNodes = candidateItems.map((item) => item.ref.current);
108
+ focusFirst(candidateNodes, preventScrollOnEntryFocus);
109
+ }
129
110
  }
130
111
  isClickFocusRef.current = false;
131
- }),
132
- onBlur: $98Iye$composeEventHandlers(props.onBlur, ()=>setIsTabbingBackOut(false)
133
- )
134
- })));
112
+ }),
113
+ onBlur: composeEventHandlers(props.onBlur, () => setIsTabbingBackOut(false))
114
+ }
115
+ )
116
+ }
117
+ );
135
118
  });
136
- /* -------------------------------------------------------------------------------------------------
137
- * RovingFocusGroupItem
138
- * -----------------------------------------------------------------------------------------------*/ const $d7bdfb9eb0fdf311$var$ITEM_NAME = 'RovingFocusGroupItem';
139
- const $d7bdfb9eb0fdf311$export$ab9df7c53fe8454 = /*#__PURE__*/ $98Iye$forwardRef((props, forwardedRef)=>{
140
- const { __scopeRovingFocusGroup: __scopeRovingFocusGroup , focusable: focusable = true , active: active = false , tabStopId: tabStopId , ...itemProps } = props;
141
- const autoId = $98Iye$useId();
119
+ var ITEM_NAME = "RovingFocusGroupItem";
120
+ var RovingFocusGroupItem = React.forwardRef(
121
+ (props, forwardedRef) => {
122
+ const {
123
+ __scopeRovingFocusGroup,
124
+ focusable = true,
125
+ active = false,
126
+ tabStopId,
127
+ ...itemProps
128
+ } = props;
129
+ const autoId = useId();
142
130
  const id = tabStopId || autoId;
143
- const context = $d7bdfb9eb0fdf311$var$useRovingFocusContext($d7bdfb9eb0fdf311$var$ITEM_NAME, __scopeRovingFocusGroup);
131
+ const context = useRovingFocusContext(ITEM_NAME, __scopeRovingFocusGroup);
144
132
  const isCurrentTabStop = context.currentTabStopId === id;
145
- const getItems = $d7bdfb9eb0fdf311$var$useCollection(__scopeRovingFocusGroup);
146
- const { onFocusableItemAdd: onFocusableItemAdd , onFocusableItemRemove: onFocusableItemRemove } = context;
147
- $98Iye$useEffect(()=>{
148
- if (focusable) {
149
- onFocusableItemAdd();
150
- return ()=>onFocusableItemRemove()
151
- ;
152
- }
153
- }, [
154
- focusable,
155
- onFocusableItemAdd,
156
- onFocusableItemRemove
157
- ]);
158
- return /*#__PURE__*/ $98Iye$createElement($d7bdfb9eb0fdf311$var$Collection.ItemSlot, {
133
+ const getItems = useCollection(__scopeRovingFocusGroup);
134
+ const { onFocusableItemAdd, onFocusableItemRemove } = context;
135
+ React.useEffect(() => {
136
+ if (focusable) {
137
+ onFocusableItemAdd();
138
+ return () => onFocusableItemRemove();
139
+ }
140
+ }, [focusable, onFocusableItemAdd, onFocusableItemRemove]);
141
+ return /* @__PURE__ */ jsx(
142
+ Collection.ItemSlot,
143
+ {
159
144
  scope: __scopeRovingFocusGroup,
160
- id: id,
161
- focusable: focusable,
162
- active: active
163
- }, /*#__PURE__*/ $98Iye$createElement($98Iye$Primitive.span, $98Iye$babelruntimehelpersesmextends({
164
- tabIndex: isCurrentTabStop ? 0 : -1,
165
- "data-orientation": context.orientation
166
- }, itemProps, {
167
- ref: forwardedRef,
168
- onMouseDown: $98Iye$composeEventHandlers(props.onMouseDown, (event)=>{
169
- // We prevent focusing non-focusable items on `mousedown`.
170
- // Even though the item has tabIndex={-1}, that only means take it out of the tab order.
171
- if (!focusable) event.preventDefault(); // Safari doesn't focus a button when clicked so we run our logic on mousedown also
172
- else context.onItemFocus(id);
173
- }),
174
- onFocus: $98Iye$composeEventHandlers(props.onFocus, ()=>context.onItemFocus(id)
175
- ),
176
- onKeyDown: $98Iye$composeEventHandlers(props.onKeyDown, (event)=>{
177
- if (event.key === 'Tab' && event.shiftKey) {
145
+ id,
146
+ focusable,
147
+ active,
148
+ children: /* @__PURE__ */ jsx(
149
+ Primitive.span,
150
+ {
151
+ tabIndex: isCurrentTabStop ? 0 : -1,
152
+ "data-orientation": context.orientation,
153
+ ...itemProps,
154
+ ref: forwardedRef,
155
+ onMouseDown: composeEventHandlers(props.onMouseDown, (event) => {
156
+ if (!focusable) event.preventDefault();
157
+ else context.onItemFocus(id);
158
+ }),
159
+ onFocus: composeEventHandlers(props.onFocus, () => context.onItemFocus(id)),
160
+ onKeyDown: composeEventHandlers(props.onKeyDown, (event) => {
161
+ if (event.key === "Tab" && event.shiftKey) {
178
162
  context.onItemShiftTab();
179
163
  return;
180
- }
181
- if (event.target !== event.currentTarget) return;
182
- const focusIntent = $d7bdfb9eb0fdf311$var$getFocusIntent(event, context.orientation, context.dir);
183
- if (focusIntent !== undefined) {
164
+ }
165
+ if (event.target !== event.currentTarget) return;
166
+ const focusIntent = getFocusIntent(event, context.orientation, context.dir);
167
+ if (focusIntent !== void 0) {
184
168
  if (event.metaKey || event.ctrlKey || event.altKey || event.shiftKey) return;
185
169
  event.preventDefault();
186
- const items = getItems().filter((item)=>item.focusable
187
- );
188
- let candidateNodes = items.map((item)=>item.ref.current
189
- );
190
- if (focusIntent === 'last') candidateNodes.reverse();
191
- else if (focusIntent === 'prev' || focusIntent === 'next') {
192
- if (focusIntent === 'prev') candidateNodes.reverse();
193
- const currentIndex = candidateNodes.indexOf(event.currentTarget);
194
- candidateNodes = context.loop ? $d7bdfb9eb0fdf311$var$wrapArray(candidateNodes, currentIndex + 1) : candidateNodes.slice(currentIndex + 1);
170
+ const items = getItems().filter((item) => item.focusable);
171
+ let candidateNodes = items.map((item) => item.ref.current);
172
+ if (focusIntent === "last") candidateNodes.reverse();
173
+ else if (focusIntent === "prev" || focusIntent === "next") {
174
+ if (focusIntent === "prev") candidateNodes.reverse();
175
+ const currentIndex = candidateNodes.indexOf(event.currentTarget);
176
+ candidateNodes = context.loop ? wrapArray(candidateNodes, currentIndex + 1) : candidateNodes.slice(currentIndex + 1);
195
177
  }
196
- /**
197
- * Imperative focus during keydown is risky so we prevent React's batching updates
198
- * to avoid potential bugs. See: https://github.com/facebook/react/issues/20332
199
- */ setTimeout(()=>$d7bdfb9eb0fdf311$var$focusFirst(candidateNodes)
200
- );
201
- }
202
- })
203
- })));
204
- });
205
- /*#__PURE__*/ Object.assign($d7bdfb9eb0fdf311$export$ab9df7c53fe8454, {
206
- displayName: $d7bdfb9eb0fdf311$var$ITEM_NAME
207
- });
208
- /* -----------------------------------------------------------------------------------------------*/ // prettier-ignore
209
- const $d7bdfb9eb0fdf311$var$MAP_KEY_TO_FOCUS_INTENT = {
210
- ArrowLeft: 'prev',
211
- ArrowUp: 'prev',
212
- ArrowRight: 'next',
213
- ArrowDown: 'next',
214
- PageUp: 'first',
215
- Home: 'first',
216
- PageDown: 'last',
217
- End: 'last'
178
+ setTimeout(() => focusFirst(candidateNodes));
179
+ }
180
+ })
181
+ }
182
+ )
183
+ }
184
+ );
185
+ }
186
+ );
187
+ RovingFocusGroupItem.displayName = ITEM_NAME;
188
+ var MAP_KEY_TO_FOCUS_INTENT = {
189
+ ArrowLeft: "prev",
190
+ ArrowUp: "prev",
191
+ ArrowRight: "next",
192
+ ArrowDown: "next",
193
+ PageUp: "first",
194
+ Home: "first",
195
+ PageDown: "last",
196
+ End: "last"
218
197
  };
219
- function $d7bdfb9eb0fdf311$var$getDirectionAwareKey(key, dir) {
220
- if (dir !== 'rtl') return key;
221
- return key === 'ArrowLeft' ? 'ArrowRight' : key === 'ArrowRight' ? 'ArrowLeft' : key;
198
+ function getDirectionAwareKey(key, dir) {
199
+ if (dir !== "rtl") return key;
200
+ return key === "ArrowLeft" ? "ArrowRight" : key === "ArrowRight" ? "ArrowLeft" : key;
222
201
  }
223
- function $d7bdfb9eb0fdf311$var$getFocusIntent(event, orientation, dir) {
224
- const key = $d7bdfb9eb0fdf311$var$getDirectionAwareKey(event.key, dir);
225
- if (orientation === 'vertical' && [
226
- 'ArrowLeft',
227
- 'ArrowRight'
228
- ].includes(key)) return undefined;
229
- if (orientation === 'horizontal' && [
230
- 'ArrowUp',
231
- 'ArrowDown'
232
- ].includes(key)) return undefined;
233
- return $d7bdfb9eb0fdf311$var$MAP_KEY_TO_FOCUS_INTENT[key];
202
+ function getFocusIntent(event, orientation, dir) {
203
+ const key = getDirectionAwareKey(event.key, dir);
204
+ if (orientation === "vertical" && ["ArrowLeft", "ArrowRight"].includes(key)) return void 0;
205
+ if (orientation === "horizontal" && ["ArrowUp", "ArrowDown"].includes(key)) return void 0;
206
+ return MAP_KEY_TO_FOCUS_INTENT[key];
234
207
  }
235
- function $d7bdfb9eb0fdf311$var$focusFirst(candidates, preventScroll = false) {
236
- const PREVIOUSLY_FOCUSED_ELEMENT = document.activeElement;
237
- for (const candidate of candidates){
238
- // if focus is already where we want to go, we don't want to keep going through the candidates
239
- if (candidate === PREVIOUSLY_FOCUSED_ELEMENT) return;
240
- candidate.focus({
241
- preventScroll: preventScroll
242
- });
243
- if (document.activeElement !== PREVIOUSLY_FOCUSED_ELEMENT) return;
244
- }
208
+ function focusFirst(candidates, preventScroll = false) {
209
+ const PREVIOUSLY_FOCUSED_ELEMENT = document.activeElement;
210
+ for (const candidate of candidates) {
211
+ if (candidate === PREVIOUSLY_FOCUSED_ELEMENT) return;
212
+ candidate.focus({ preventScroll });
213
+ if (document.activeElement !== PREVIOUSLY_FOCUSED_ELEMENT) return;
214
+ }
245
215
  }
246
- /**
247
- * Wraps an array around itself at a given start index
248
- * Example: `wrapArray(['a', 'b', 'c', 'd'], 2) === ['c', 'd', 'a', 'b']`
249
- */ function $d7bdfb9eb0fdf311$var$wrapArray(array, startIndex) {
250
- return array.map((_, index)=>array[(startIndex + index) % array.length]
251
- );
216
+ function wrapArray(array, startIndex) {
217
+ return array.map((_, index) => array[(startIndex + index) % array.length]);
252
218
  }
253
- const $d7bdfb9eb0fdf311$export$be92b6f5f03c0fe9 = $d7bdfb9eb0fdf311$export$8699f7c8af148338;
254
- const $d7bdfb9eb0fdf311$export$6d08773d2e66f8f2 = $d7bdfb9eb0fdf311$export$ab9df7c53fe8454;
255
-
256
-
257
-
258
-
259
- export {$d7bdfb9eb0fdf311$export$c7109489551a4f4 as createRovingFocusGroupScope, $d7bdfb9eb0fdf311$export$8699f7c8af148338 as RovingFocusGroup, $d7bdfb9eb0fdf311$export$ab9df7c53fe8454 as RovingFocusGroupItem, $d7bdfb9eb0fdf311$export$be92b6f5f03c0fe9 as Root, $d7bdfb9eb0fdf311$export$6d08773d2e66f8f2 as Item};
219
+ var Root = RovingFocusGroup;
220
+ var Item = RovingFocusGroupItem;
221
+ export {
222
+ Item,
223
+ Root,
224
+ RovingFocusGroup,
225
+ RovingFocusGroupItem,
226
+ createRovingFocusGroupScope
227
+ };
260
228
  //# sourceMappingURL=index.mjs.map