vendor: 9,101 bytes, lines 1-214
1import { w as createContextScope, r as reactExports, j as jsxRuntimeExports, x as useId, y as Primitive, z as composeEventHandlers, A as useComposedRefs, G as useDirection, H as useControllableState, I as useCallbackRef } from './index-CNT5CkK7.js'; 2import { c as createCollection } from './index-BEBgmBqK.js'; 3 4var ENTRY_FOCUS = "rovingFocusGroup.onEntryFocus"; 5var EVENT_OPTIONS = { bubbles: false, cancelable: true }; 6var GROUP_NAME = "RovingFocusGroup"; 7var [Collection, useCollection, createCollectionScope] = createCollection(GROUP_NAME); 8var [createRovingFocusGroupContext, createRovingFocusGroupScope] = createContextScope( 9 GROUP_NAME, 10 [createCollectionScope] 11); 12var [RovingFocusProvider, useRovingFocusContext] = createRovingFocusGroupContext(GROUP_NAME); 13var RovingFocusGroup = reactExports.forwardRef( 14 (props, forwardedRef) => { 15 return /* @__PURE__ */ jsxRuntimeExports.jsx(Collection.Provider, { scope: props.__scopeRovingFocusGroup, children: /* @__PURE__ */ jsxRuntimeExports.jsx(Collection.Slot, { scope: props.__scopeRovingFocusGroup, children: /* @__PURE__ */ jsxRuntimeExports.jsx(RovingFocusGroupImpl, { ...props, ref: forwardedRef }) }) }); 16 } 17); 18RovingFocusGroup.displayName = GROUP_NAME; 19var RovingFocusGroupImpl = reactExports.forwardRef((props, forwardedRef) => { 20 const { 21 __scopeRovingFocusGroup, 22 orientation, 23 loop = false, 24 dir, 25 currentTabStopId: currentTabStopIdProp, 26 defaultCurrentTabStopId, 27 onCurrentTabStopIdChange, 28 onEntryFocus, 29 preventScrollOnEntryFocus = false, 30 ...groupProps 31 } = props; 32 const ref = reactExports.useRef(null); 33 const composedRefs = useComposedRefs(forwardedRef, ref); 34 const direction = useDirection(dir); 35 const [currentTabStopId, setCurrentTabStopId] = useControllableState({ 36 prop: currentTabStopIdProp, 37 defaultProp: defaultCurrentTabStopId ?? null, 38 onChange: onCurrentTabStopIdChange, 39 caller: GROUP_NAME 40 }); 41 const [isTabbingBackOut, setIsTabbingBackOut] = reactExports.useState(false); 42 const handleEntryFocus = useCallbackRef(onEntryFocus); 43 const getItems = useCollection(__scopeRovingFocusGroup); 44 const isClickFocusRef = reactExports.useRef(false); 45 const [focusableItemsCount, setFocusableItemsCount] = reactExports.useState(0); 46 reactExports.useEffect(() => { 47 const node = ref.current; 48 if (node) { 49 node.addEventListener(ENTRY_FOCUS, handleEntryFocus); 50 return () => node.removeEventListener(ENTRY_FOCUS, handleEntryFocus); 51 } 52 }, [handleEntryFocus]); 53 return /* @__PURE__ */ jsxRuntimeExports.jsx( 54 RovingFocusProvider, 55 { 56 scope: __scopeRovingFocusGroup, 57 orientation, 58 dir: direction, 59 loop, 60 currentTabStopId, 61 onItemFocus: reactExports.useCallback( 62 (tabStopId) => setCurrentTabStopId(tabStopId), 63 [setCurrentTabStopId] 64 ), 65 onItemShiftTab: reactExports.useCallback(() => setIsTabbingBackOut(true), []), 66 onFocusableItemAdd: reactExports.useCallback( 67 () => setFocusableItemsCount((prevCount) => prevCount + 1), 68 [] 69 ), 70 onFocusableItemRemove: reactExports.useCallback( 71 () => setFocusableItemsCount((prevCount) => prevCount - 1), 72 [] 73 ), 74 children: /* @__PURE__ */ jsxRuntimeExports.jsx( 75 Primitive.div, 76 { 77 tabIndex: isTabbingBackOut || focusableItemsCount === 0 ? -1 : 0, 78 "data-orientation": orientation, 79 ...groupProps, 80 ref: composedRefs, 81 style: { outline: "none", ...props.style }, 82 onMouseDown: composeEventHandlers(props.onMouseDown, () => { 83 isClickFocusRef.current = true; 84 }), 85 onFocus: composeEventHandlers(props.onFocus, (event) => { 86 const isKeyboardFocus = !isClickFocusRef.current; 87 if (event.target === event.currentTarget && isKeyboardFocus && !isTabbingBackOut) { 88 const entryFocusEvent = new CustomEvent(ENTRY_FOCUS, EVENT_OPTIONS); 89 event.currentTarget.dispatchEvent(entryFocusEvent); 90 if (!entryFocusEvent.defaultPrevented) { 91 const items = getItems().filter((item) => item.focusable); 92 const activeItem = items.find((item) => item.active); 93 const currentItem = items.find((item) => item.id === currentTabStopId); 94 const candidateItems = [activeItem, currentItem, ...items].filter( 95 Boolean 96 ); 97 const candidateNodes = candidateItems.map((item) => item.ref.current); 98 focusFirst(candidateNodes, preventScrollOnEntryFocus); 99 } 100 } 101 isClickFocusRef.current = false; 102 }), 103 onBlur: composeEventHandlers(props.onBlur, () => setIsTabbingBackOut(false)) 104 } 105 ) 106 } 107 ); 108}); 109var ITEM_NAME = "RovingFocusGroupItem"; 110var RovingFocusGroupItem = reactExports.forwardRef( 111 (props, forwardedRef) => { 112 const { 113 __scopeRovingFocusGroup, 114 focusable = true, 115 active = false, 116 tabStopId, 117 children, 118 ...itemProps 119 } = props; 120 const autoId = useId(); 121 const id = tabStopId || autoId; 122 const context = useRovingFocusContext(ITEM_NAME, __scopeRovingFocusGroup); 123 const isCurrentTabStop = context.currentTabStopId === id; 124 const getItems = useCollection(__scopeRovingFocusGroup); 125 const { onFocusableItemAdd, onFocusableItemRemove, currentTabStopId } = context; 126 reactExports.useEffect(() => { 127 if (focusable) { 128 onFocusableItemAdd(); 129 return () => onFocusableItemRemove(); 130 } 131 }, [focusable, onFocusableItemAdd, onFocusableItemRemove]); 132 return /* @__PURE__ */ jsxRuntimeExports.jsx( 133 Collection.ItemSlot, 134 { 135 scope: __scopeRovingFocusGroup, 136 id, 137 focusable, 138 active, 139 children: /* @__PURE__ */ jsxRuntimeExports.jsx( 140 Primitive.span, 141 { 142 tabIndex: isCurrentTabStop ? 0 : -1, 143 "data-orientation": context.orientation, 144 ...itemProps, 145 ref: forwardedRef, 146 onMouseDown: composeEventHandlers(props.onMouseDown, (event) => { 147 if (!focusable) event.preventDefault(); 148 else context.onItemFocus(id); 149 }), 150 onFocus: composeEventHandlers(props.onFocus, () => context.onItemFocus(id)), 151 onKeyDown: composeEventHandlers(props.onKeyDown, (event) => { 152 if (event.key === "Tab" && event.shiftKey) { 153 context.onItemShiftTab(); 154 return; 155 } 156 if (event.target !== event.currentTarget) return; 157 const focusIntent = getFocusIntent(event, context.orientation, context.dir); 158 if (focusIntent !== void 0) { 159 if (event.metaKey || event.ctrlKey || event.altKey || event.shiftKey) return; 160 event.preventDefault(); 161 const items = getItems().filter((item) => item.focusable); 162 let candidateNodes = items.map((item) => item.ref.current); 163 if (focusIntent === "last") candidateNodes.reverse(); 164 else if (focusIntent === "prev" || focusIntent === "next") { 165 if (focusIntent === "prev") candidateNodes.reverse(); 166 const currentIndex = candidateNodes.indexOf(event.currentTarget); 167 candidateNodes = context.loop ? wrapArray(candidateNodes, currentIndex + 1) : candidateNodes.slice(currentIndex + 1); 168 } 169 setTimeout(() => focusFirst(candidateNodes)); 170 } 171 }), 172 children: typeof children === "function" ? children({ isCurrentTabStop, hasTabStop: currentTabStopId != null }) : children 173 } 174 ) 175 } 176 ); 177 } 178); 179RovingFocusGroupItem.displayName = ITEM_NAME; 180var MAP_KEY_TO_FOCUS_INTENT = { 181 ArrowLeft: "prev", 182 ArrowUp: "prev", 183 ArrowRight: "next", 184 ArrowDown: "next", 185 PageUp: "first", 186 Home: "first", 187 PageDown: "last", 188 End: "last" 189}; 190function getDirectionAwareKey(key, dir) { 191 if (dir !== "rtl") return key; 192 return key === "ArrowLeft" ? "ArrowRight" : key === "ArrowRight" ? "ArrowLeft" : key; 193} 194function getFocusIntent(event, orientation, dir) { 195 const key = getDirectionAwareKey(event.key, dir); 196 if (orientation === "vertical" && ["ArrowLeft", "ArrowRight"].includes(key)) return void 0; 197 if (orientation === "horizontal" && ["ArrowUp", "ArrowDown"].includes(key)) return void 0; 198 return MAP_KEY_TO_FOCUS_INTENT[key]; 199} 200function focusFirst(candidates, preventScroll = false) { 201 const PREVIOUSLY_FOCUSED_ELEMENT = document.activeElement; 202 for (const candidate of candidates) { 203 if (candidate === PREVIOUSLY_FOCUSED_ELEMENT) return; 204 candidate.focus({ preventScroll }); 205 if (document.activeElement !== PREVIOUSLY_FOCUSED_ELEMENT) return; 206 } 207} 208function wrapArray(array, startIndex) { 209 return array.map((_, index) => array[(startIndex + index) % array.length]); 210} 211var Root = RovingFocusGroup; 212var Item = RovingFocusGroupItem; 213 214export { Item as I, Root as R, createRovingFocusGroupScope as c };
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.