@octanejs/aria 0.0.46 → 0.0.47

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.
Files changed (201) hide show
  1. package/README.md +7 -6
  2. package/UPSTREAM.md +58 -69
  3. package/package.json +11 -11
  4. package/src/calendar/useCalendarGrid.tsx +64 -62
  5. package/src/collections/Document.ts +3 -0
  6. package/src/color/useColorArea.tsx +95 -69
  7. package/src/color/useColorWheel.tsx +38 -37
  8. package/src/combobox/{useComboBox.ts → useComboBox.tsx} +239 -259
  9. package/src/components/ComboBox.ts +35 -2
  10. package/src/components/Dialog.ts +12 -1
  11. package/src/components/DropZone.tsx +3 -2
  12. package/src/components/FileTrigger.tsx +1 -0
  13. package/src/components/GridList.ts +11 -2
  14. package/src/components/ListBox.ts +1 -1
  15. package/src/components/Menu.ts +1 -0
  16. package/src/components/Meter.ts +3 -1
  17. package/src/components/Popover.ts +20 -8
  18. package/src/components/PreviewTrigger.tsx +101 -0
  19. package/src/components/ProgressBar.ts +10 -2
  20. package/src/components/Select.ts +1 -1
  21. package/src/components/Table.ts +26 -15
  22. package/src/components/TokenField.tsx +395 -0
  23. package/src/components/Tooltip.ts +4 -6
  24. package/src/components/Tree.ts +14 -7
  25. package/src/components/Virtualizer.tsx +30 -14
  26. package/src/components/index.ts +22 -0
  27. package/src/components/utils.ts +1 -1
  28. package/src/datepicker/useDateField.tsx +2 -11
  29. package/src/datepicker/useDatePickerGroup.tsx +44 -33
  30. package/src/datepicker/useDateSegment.tsx +31 -30
  31. package/src/dialog/useDialog.ts +8 -1
  32. package/src/dnd/DragManager.tsx +5 -1
  33. package/src/dnd/useDrag.tsx +2 -1
  34. package/src/focus/FocusScope.ts +2 -2
  35. package/src/grid/useGrid.ts +3 -0
  36. package/src/grid/{useGridCell.ts → useGridCell.tsx} +121 -64
  37. package/src/grid/utils.ts +1 -0
  38. package/src/gridlist/{useGridListItem.ts → useGridListItem.tsx} +152 -111
  39. package/src/index.ts +22 -0
  40. package/src/interactions/createEventHandler.ts +11 -8
  41. package/src/interactions/createKeyboardShortcutHandler.tsx +218 -0
  42. package/src/interactions/textSelection.ts +3 -3
  43. package/src/interactions/useContextMenu.tsx +125 -0
  44. package/src/interactions/useFocusVisible.ts +4 -4
  45. package/src/interactions/useKeyboard.ts +50 -2
  46. package/src/interactions/useLongPress.ts +33 -22
  47. package/src/interactions/useMove.ts +6 -6
  48. package/src/interactions/usePress.ts +8 -0
  49. package/src/interactions/utils.ts +10 -10
  50. package/src/intl/combobox/fi-FI.json +2 -2
  51. package/src/intl/previewtrigger/ar-AE.json +3 -0
  52. package/src/intl/previewtrigger/bg-BG.json +3 -0
  53. package/src/intl/previewtrigger/cs-CZ.json +3 -0
  54. package/src/intl/previewtrigger/da-DK.json +3 -0
  55. package/src/intl/previewtrigger/de-DE.json +3 -0
  56. package/src/intl/previewtrigger/el-GR.json +3 -0
  57. package/src/intl/previewtrigger/en-US.json +3 -0
  58. package/src/intl/previewtrigger/es-ES.json +3 -0
  59. package/src/intl/previewtrigger/et-EE.json +3 -0
  60. package/src/intl/previewtrigger/fi-FI.json +3 -0
  61. package/src/intl/previewtrigger/fr-FR.json +3 -0
  62. package/src/intl/previewtrigger/he-IL.json +3 -0
  63. package/src/intl/previewtrigger/hr-HR.json +3 -0
  64. package/src/intl/previewtrigger/hu-HU.json +3 -0
  65. package/src/intl/previewtrigger/index.ts +73 -0
  66. package/src/intl/previewtrigger/it-IT.json +3 -0
  67. package/src/intl/previewtrigger/ja-JP.json +3 -0
  68. package/src/intl/previewtrigger/ko-KR.json +3 -0
  69. package/src/intl/previewtrigger/lt-LT.json +3 -0
  70. package/src/intl/previewtrigger/lv-LV.json +3 -0
  71. package/src/intl/previewtrigger/nb-NO.json +3 -0
  72. package/src/intl/previewtrigger/nl-NL.json +3 -0
  73. package/src/intl/previewtrigger/pl-PL.json +3 -0
  74. package/src/intl/previewtrigger/pt-BR.json +3 -0
  75. package/src/intl/previewtrigger/pt-PT.json +3 -0
  76. package/src/intl/previewtrigger/ro-RO.json +3 -0
  77. package/src/intl/previewtrigger/ru-RU.json +3 -0
  78. package/src/intl/previewtrigger/sk-SK.json +3 -0
  79. package/src/intl/previewtrigger/sl-SI.json +3 -0
  80. package/src/intl/previewtrigger/sr-SP.json +3 -0
  81. package/src/intl/previewtrigger/sv-SE.json +3 -0
  82. package/src/intl/previewtrigger/tr-TR.json +3 -0
  83. package/src/intl/previewtrigger/uk-UA.json +3 -0
  84. package/src/intl/previewtrigger/zh-CN.json +3 -0
  85. package/src/intl/previewtrigger/zh-TW.json +3 -0
  86. package/src/intl/table/ar-AE.json +3 -3
  87. package/src/intl/table/bg-BG.json +3 -3
  88. package/src/intl/table/cs-CZ.json +3 -3
  89. package/src/intl/table/da-DK.json +3 -3
  90. package/src/intl/table/de-DE.json +3 -3
  91. package/src/intl/table/el-GR.json +3 -3
  92. package/src/intl/table/es-ES.json +3 -3
  93. package/src/intl/table/et-EE.json +3 -3
  94. package/src/intl/table/fi-FI.json +3 -3
  95. package/src/intl/table/fr-FR.json +3 -3
  96. package/src/intl/table/he-IL.json +3 -3
  97. package/src/intl/table/hr-HR.json +3 -3
  98. package/src/intl/table/hu-HU.json +3 -3
  99. package/src/intl/table/it-IT.json +3 -3
  100. package/src/intl/table/ja-JP.json +3 -3
  101. package/src/intl/table/ko-KR.json +3 -3
  102. package/src/intl/table/lt-LT.json +3 -3
  103. package/src/intl/table/lv-LV.json +3 -3
  104. package/src/intl/table/nb-NO.json +3 -3
  105. package/src/intl/table/nl-NL.json +3 -3
  106. package/src/intl/table/pl-PL.json +3 -3
  107. package/src/intl/table/pt-BR.json +3 -3
  108. package/src/intl/table/pt-PT.json +3 -3
  109. package/src/intl/table/ro-RO.json +3 -3
  110. package/src/intl/table/ru-RU.json +3 -3
  111. package/src/intl/table/sk-SK.json +3 -3
  112. package/src/intl/table/sl-SI.json +3 -3
  113. package/src/intl/table/sr-SP.json +3 -3
  114. package/src/intl/table/sv-SE.json +3 -3
  115. package/src/intl/table/tr-TR.json +3 -3
  116. package/src/intl/table/uk-UA.json +3 -3
  117. package/src/intl/table/zh-CN.json +4 -4
  118. package/src/intl/table/zh-TW.json +3 -3
  119. package/src/intl/tree/es-ES.json +1 -1
  120. package/src/link/useLink.ts +2 -0
  121. package/src/menu/useMenuItem.ts +33 -36
  122. package/src/menu/useMenuTrigger.tsx +217 -0
  123. package/src/menu/{useSubmenuTrigger.ts → useSubmenuTrigger.tsx} +112 -152
  124. package/src/numberfield/{useNumberField.ts → useNumberField.tsx} +185 -239
  125. package/src/overlays/Overlay.ts +5 -1
  126. package/src/overlays/ariaHideOutside.ts +6 -8
  127. package/src/overlays/useCloseOnScroll.ts +7 -5
  128. package/src/overlays/{useOverlay.ts → useOverlay.tsx} +72 -84
  129. package/src/overlays/usePopover.ts +10 -5
  130. package/src/overlays/usePreventScroll.ts +4 -4
  131. package/src/progress/useProgressBar.ts +2 -1
  132. package/src/radio/{useRadioGroup.ts → useRadioGroup.tsx} +83 -80
  133. package/src/searchfield/useSearchField.tsx +147 -0
  134. package/src/select/useSelect.ts +20 -20
  135. package/src/selection/useSelectableCollection.tsx +751 -0
  136. package/src/selection/useSelectableItem.ts +48 -11
  137. package/src/slider/{useSliderThumb.ts → useSliderThumb.tsx} +116 -159
  138. package/src/spinbutton/useSpinButton.tsx +330 -0
  139. package/src/stately/combobox/useComboBoxState.ts +1 -1
  140. package/src/stately/grid/useGridState.ts +9 -10
  141. package/src/stately/index.ts +11 -0
  142. package/src/stately/menu/useMenuTriggerState.ts +1 -1
  143. package/src/stately/menu/useSubmenuTriggerState.ts +2 -0
  144. package/src/stately/overlays/useOverlayTriggerState.ts +12 -1
  145. package/src/stately/radio/useRadioGroupState.ts +5 -1
  146. package/src/stately/table/TableUtils.ts +15 -1
  147. package/src/stately/table/useTableState.ts +7 -0
  148. package/src/stately/tokenfield/TokenFieldValue.tsx +440 -0
  149. package/src/stately/tokenfield/useTokenFieldState.tsx +57 -0
  150. package/src/stately/tooltip/useTooltipTriggerState.ts +16 -7
  151. package/src/stately/virtualizer/Layout.tsx +2 -0
  152. package/src/stately/virtualizer/ScrollAnchor.tsx +338 -0
  153. package/src/stately/virtualizer/Virtualizer.tsx +52 -1
  154. package/src/stately/virtualizer/types.tsx +2 -0
  155. package/src/table/useTableCell.ts +12 -0
  156. package/src/table/useTableColumnHeader.ts +8 -1
  157. package/src/table/useTableColumnResize.tsx +354 -0
  158. package/src/tag/useTag.ts +22 -15
  159. package/src/textfield/useTextField.ts +2 -0
  160. package/src/tokenfield/useToken.tsx +64 -0
  161. package/src/tokenfield/useTokenField.tsx +849 -0
  162. package/src/tooltip/usePreviewTrigger.tsx +266 -0
  163. package/src/tooltip/useSafeArea.tsx +171 -0
  164. package/src/upstream-exports/react-aria/mergeRefs.tsx +3 -0
  165. package/src/upstream-exports/react-aria/usePreviewTrigger.tsx +18 -0
  166. package/src/upstream-exports/react-aria/useTokenField.tsx +22 -0
  167. package/src/upstream-exports/react-stately/private/collections/getChildNodes.tsx +8 -0
  168. package/src/upstream-exports/react-stately/private/collections/getItemCount.tsx +2 -0
  169. package/src/upstream-exports/react-stately/private/grid/GridCollection.tsx +7 -0
  170. package/src/upstream-exports/react-stately/private/grid/useGridState.tsx +6 -0
  171. package/src/upstream-exports/react-stately/private/utils/number.tsx +2 -0
  172. package/src/upstream-exports/react-stately/useComboBoxState.tsx +23 -0
  173. package/src/upstream-exports/react-stately/useListState.tsx +15 -0
  174. package/src/upstream-exports/react-stately/useMenuTriggerState.tsx +26 -0
  175. package/src/upstream-exports/react-stately/useMultipleSelectionState.tsx +21 -0
  176. package/src/upstream-exports/react-stately/useNumberFieldState.tsx +20 -0
  177. package/src/upstream-exports/react-stately/useOverlayTriggerState.tsx +20 -0
  178. package/src/upstream-exports/react-stately/useRadioGroupState.tsx +16 -0
  179. package/src/upstream-exports/react-stately/useSearchFieldState.tsx +19 -0
  180. package/src/upstream-exports/react-stately/useSliderState.tsx +20 -0
  181. package/src/upstream-exports/react-stately/useTableState.tsx +45 -0
  182. package/src/upstream-exports/react-stately/useTokenFieldState.tsx +25 -0
  183. package/src/upstream-exports/react-stately/useTooltipTriggerState.tsx +20 -0
  184. package/src/upstream-exports/react-stately/useTreeState.tsx +14 -0
  185. package/src/utils/domHelpers.ts +74 -17
  186. package/src/utils/isVirtualEvent.ts +2 -1
  187. package/src/utils/openLink.ts +8 -3
  188. package/src/utils/platform.ts +7 -3
  189. package/src/utils/scrollIntoView.ts +4 -4
  190. package/src/utils/shadowdom/DOMFunctions.ts +42 -2
  191. package/src/utils/useId.ts +11 -2
  192. package/src/utils/useLoadMoreSentinel.ts +8 -3
  193. package/src/utils/useViewportSize.ts +3 -3
  194. package/src/virtualizer/ScrollView.tsx +13 -4
  195. package/src/virtualizer/VirtualizerItem.tsx +3 -1
  196. package/src/virtualizer/useVirtualizerItem.tsx +43 -3
  197. package/src/menu/useMenuTrigger.ts +0 -189
  198. package/src/searchfield/useSearchField.ts +0 -156
  199. package/src/selection/useSelectableCollection.ts +0 -750
  200. package/src/spinbutton/useSpinButton.ts +0 -380
  201. package/src/table/useTableColumnResize.ts +0 -374
@@ -24,6 +24,7 @@ import { focusSafely } from '../interactions/focusSafely';
24
24
  import { getActiveElement, getEventTarget } from '../utils/shadowdom/DOMFunctions';
25
25
  import { getCollectionId, isNonContiguousSelectionModifier } from './utils';
26
26
  import { isCtrlKeyPressed } from '../utils/keyboard';
27
+ import { isTabbable } from '../utils/isFocusable';
27
28
  import { mergeProps } from '../utils/mergeProps';
28
29
  import { moveVirtualFocus } from '../focus/virtualFocus';
29
30
  import type { MultipleSelectionManager } from '../stately/selection/types';
@@ -380,7 +381,8 @@ export function useSelectableItem(...args: any[]): SelectableItemAria {
380
381
  };
381
382
  }
382
383
 
383
- itemProps['data-collection'] = getCollectionId(manager.collection);
384
+ let collectionId = getCollectionId(manager.collection);
385
+ itemProps['data-collection'] = collectionId;
384
386
  itemProps['data-key'] = key;
385
387
  itemPressProps.preventFocusOnPress = shouldUseVirtualFocus;
386
388
 
@@ -470,17 +472,52 @@ export function useSelectableItem(...args: any[]): SelectableItemAria {
470
472
  }
471
473
  : undefined;
472
474
 
475
+ let mergedItemProps = mergeProps(
476
+ itemProps,
477
+ allowsSelection || hasPrimaryAction || (shouldUseVirtualFocus && !isDisabled) ? pressProps : {},
478
+ longPressEnabled ? longPressProps : {},
479
+ { onDoubleClick, onDragStartCapture, onClick, id },
480
+ // Prevent DOM focus from moving on mouse down when using virtual focus
481
+ shouldUseVirtualFocus ? { onMouseDown: (e: MouseEvent) => e.preventDefault() } : undefined,
482
+ );
483
+
484
+ // Guard against presses triggering selection when they happen on interactive children or collection items from different collections
485
+ // will need to trigger selection if the target is itself a collection item belonging to the same collection parent (aka a cell in a row) but
486
+ // not if the target is a child of a different collections aka taggroup in table cell.
487
+ let isChildInteraction = (target: Element) => {
488
+ let el: Element | null = target;
489
+ while (el && el !== ref.current) {
490
+ let elCollection = el.getAttribute('data-collection');
491
+ if (elCollection != null) {
492
+ return elCollection !== collectionId;
493
+ }
494
+ el = el.parentElement;
495
+ }
496
+ return isTabbable(target);
497
+ };
498
+
499
+ let baseOnPointerDown = mergedItemProps.onPointerDown;
500
+ mergedItemProps.onPointerDown = (e: PointerEvent) => {
501
+ let target = getEventTarget(e) as Element | null;
502
+ if (target && target !== ref.current && isChildInteraction(target)) {
503
+ e.stopPropagation();
504
+ return;
505
+ }
506
+ baseOnPointerDown?.(e);
507
+ };
508
+
509
+ let baseOnMouseDown = mergedItemProps.onMouseDown;
510
+ mergedItemProps.onMouseDown = (e) => {
511
+ let target = getEventTarget(e) as Element | null;
512
+ if (target && target !== ref.current && isChildInteraction(target)) {
513
+ e.stopPropagation();
514
+ return;
515
+ }
516
+ baseOnMouseDown?.(e);
517
+ };
518
+
473
519
  return {
474
- itemProps: mergeProps(
475
- itemProps,
476
- allowsSelection || hasPrimaryAction || (shouldUseVirtualFocus && !isDisabled)
477
- ? pressProps
478
- : {},
479
- longPressEnabled ? longPressProps : {},
480
- { onDoubleClick, onDragStartCapture, onClick, id },
481
- // Prevent DOM focus from moving on mouse down when using virtual focus
482
- shouldUseVirtualFocus ? { onMouseDown: (e: MouseEvent) => e.preventDefault() } : undefined,
483
- ),
520
+ itemProps: mergedItemProps,
484
521
  isPressed,
485
522
  isSelected: manager.isSelected(key),
486
523
  isFocused: manager.isFocused && manager.focusedKey === key,
@@ -1,16 +1,7 @@
1
- // Ported from react-aria (source: .react-spectrum/packages/react-aria/src/slider/useSliderThumb.ts).
2
- // octane adaptations:
3
- // - Handlers receive NATIVE events. The visually-hidden range input's value listener is
4
- // `onInput` (octane has no synthetic onChange; for range inputs React's onChange fires
5
- // on the native `input` event, so the timing is identical — this mirrors how the browser
6
- // reports native keyboard/drag stepping of a range input).
7
- // - React's InputHTMLAttributes/LabelHTMLAttributes element types collapse to the local
8
- // structural `DOMAttributes` prop bag; mouse/pointer/touch handler params are native.
9
- // - `clamp` comes from the ported stately number utils; `SliderState` from the ported
10
- // stately slider hook.
11
- // - Public-hook slot threading (splitSlot/subSlot); explicit dependency arrays are kept
12
- // verbatim.
13
- import type {
1
+ /** @jsxImportSource octane */
2
+ type DOMAttributes = Record<string, any>;
3
+ // Ported from adobe/react-spectrum@5ecb3333001313e83898cd07644227897e3bae1f (packages/react-aria/src/slider/useSliderThumb.ts).
4
+ import {
14
5
  AriaLabelingProps,
15
6
  AriaValidationProps,
16
7
  DOMProps,
@@ -21,15 +12,21 @@ import type {
21
12
  RefObject,
22
13
  ValidationState,
23
14
  } from '@react-types/shared';
24
- // octane adaptation: FocusableProps is the ported native-event version.
25
15
  import type { FocusableProps } from '../interactions/useFocusable';
26
- import { clamp } from '../stately/utils/number';
16
+ import { clamp } from '../upstream-exports/react-stately/private/utils/number';
27
17
  import { focusWithoutScrolling } from '../utils/focusWithoutScrolling';
28
18
  import { getEventTarget } from '../utils/shadowdom/DOMFunctions';
29
19
  import { getSliderThumbId, sliderData } from './utils';
30
20
  import { mergeProps } from '../utils/mergeProps';
31
- import { useCallback, useEffect, useRef } from 'octane';
32
- import type { SliderState } from '../stately/slider/useSliderState';
21
+ import React, {
22
+ ChangeEvent,
23
+ InputHTMLAttributes,
24
+ LabelHTMLAttributes,
25
+ useCallback,
26
+ useEffect,
27
+ useRef,
28
+ } from '../compat/react';
29
+ import { SliderState } from '../upstream-exports/react-stately/useSliderState';
33
30
  import { useFocusable } from '../interactions/useFocusable';
34
31
  import { useFormReset } from '../utils/useFormReset';
35
32
  import { useGlobalListeners } from '../utils/useGlobalListeners';
@@ -38,12 +35,6 @@ import { useLabel } from '../label/useLabel';
38
35
  import { useLocale } from '../i18n/I18nProvider';
39
36
  import { useMove } from '../interactions/useMove';
40
37
 
41
- import { S, splitSlot, subSlot } from '../internal';
42
-
43
- // octane adaptation: minimal structural DOMAttributes (upstream's drags React's synthetic
44
- // handler types along).
45
- type DOMAttributes = Record<string, any>;
46
-
47
38
  export interface SliderThumbProps extends FocusableProps, LabelableProps {
48
39
  /**
49
40
  * The orientation of the Slider.
@@ -82,10 +73,10 @@ export interface SliderThumbAria {
82
73
  thumbProps: DOMAttributes;
83
74
 
84
75
  /** Props for the visually hidden range input element. */
85
- inputProps: DOMAttributes;
76
+ inputProps: InputHTMLAttributes<HTMLInputElement>;
86
77
 
87
78
  /** Props for the label element for this thumb (optional). */
88
- labelProps: DOMAttributes;
79
+ labelProps: LabelHTMLAttributes<HTMLLabelElement>;
89
80
 
90
81
  /** Whether this thumb is currently being dragged. */
91
82
  isDragging: boolean;
@@ -108,19 +99,11 @@ export interface AriaSliderThumbOptions extends AriaSliderThumbProps {
108
99
  * @param opts Options for this Slider thumb.
109
100
  * @param state Slider state, created via `useSliderState`.
110
101
  */
111
- export function useSliderThumb(opts: AriaSliderThumbOptions, state: SliderState): SliderThumbAria;
112
- // Slot-threading form: sibling ported hooks pass their derived sub-slot as the trailing arg.
113
102
  export function useSliderThumb(
114
103
  opts: AriaSliderThumbOptions,
115
104
  state: SliderState,
116
- slot: symbol | undefined,
117
- ): SliderThumbAria;
118
- export function useSliderThumb(...args: any[]): SliderThumbAria {
119
- const [user, slotArg] = splitSlot(args);
120
- const slot = slotArg ?? S('useSliderThumb');
121
- const opts = user[0] as AriaSliderThumbOptions;
122
- const state = user[1] as SliderState;
123
-
105
+ _slot?: symbol,
106
+ ): SliderThumbAria {
124
107
  let {
125
108
  index = 0,
126
109
  isRequired,
@@ -136,129 +119,105 @@ export function useSliderThumb(...args: any[]): SliderThumbAria {
136
119
  let isDisabled = opts.isDisabled || state.isDisabled;
137
120
  let isVertical = orientation === 'vertical';
138
121
 
139
- let { direction } = useLocale(subSlot(slot, 'locale'));
140
- let { addGlobalListener, removeGlobalListener } = useGlobalListeners(
141
- subSlot(slot, 'globalListeners'),
142
- );
122
+ let { direction } = useLocale();
123
+ let { addGlobalListener, removeGlobalListener } = useGlobalListeners();
143
124
 
144
125
  let data = sliderData.get(state)!;
145
- const { labelProps, fieldProps } = useLabel(
146
- {
147
- ...opts,
148
- id: getSliderThumbId(state, index),
149
- 'aria-labelledby': `${data.id} ${opts['aria-labelledby'] ?? ''}`.trim(),
150
- },
151
- subSlot(slot, 'label'),
152
- );
126
+ const { labelProps, fieldProps } = useLabel({
127
+ ...opts,
128
+ id: getSliderThumbId(state, index),
129
+ 'aria-labelledby': `${data.id} ${opts['aria-labelledby'] ?? ''}`.trim(),
130
+ });
153
131
 
154
132
  const value = state.values[index];
155
133
 
156
- const focusInput = useCallback(
157
- () => {
158
- if (inputRef.current) {
159
- focusWithoutScrolling(inputRef.current);
160
- }
161
- },
162
- [inputRef],
163
- subSlot(slot, 'focusInput'),
164
- );
134
+ const focusInput = useCallback(() => {
135
+ if (inputRef.current) {
136
+ focusWithoutScrolling(inputRef.current);
137
+ }
138
+ }, [inputRef]);
165
139
 
166
140
  const isFocused = state.focusedThumb === index;
167
141
 
168
- useEffect(
169
- () => {
170
- if (isFocused) {
171
- focusInput();
172
- }
173
- },
174
- [isFocused, focusInput],
175
- subSlot(slot, 'focusFx'),
176
- );
142
+ useEffect(() => {
143
+ if (isFocused) {
144
+ focusInput();
145
+ }
146
+ }, [isFocused, focusInput]);
177
147
 
178
148
  let reverseX = direction === 'rtl';
179
- let currentPosition = useRef<number | null>(null, subSlot(slot, 'position'));
149
+ let currentPosition = useRef<number | null>(null);
180
150
 
181
- let { keyboardProps } = useKeyboard(
182
- {
183
- onKeyDown(e) {
184
- let {
185
- getThumbMaxValue,
186
- getThumbMinValue,
187
- decrementThumb,
188
- incrementThumb,
189
- setThumbValue,
190
- setThumbDragging,
191
- pageSize,
192
- } = state;
193
- // these are the cases that useMove or useSlider don't handle
194
- if (!/^(PageUp|PageDown|Home|End)$/.test(e.key)) {
195
- e.continuePropagation();
196
- return;
197
- }
198
- // same handling as useMove, stopPropagation to prevent useSlider from handling the event as well.
199
- e.preventDefault();
200
- // remember to set this so that onChangeEnd is fired
201
- setThumbDragging(index, true);
202
- switch (e.key) {
203
- case 'PageUp':
204
- incrementThumb(index, pageSize);
205
- break;
206
- case 'PageDown':
207
- decrementThumb(index, pageSize);
208
- break;
209
- case 'Home':
210
- setThumbValue(index, getThumbMinValue(index));
211
- break;
212
- case 'End':
213
- setThumbValue(index, getThumbMaxValue(index));
214
- break;
215
- }
216
- setThumbDragging(index, false);
151
+ let keyboardUpdate = (cb: () => void) => {
152
+ // remember to set this so that onChangeEnd is fired
153
+ state.setThumbDragging(index, true);
154
+ cb();
155
+ state.setThumbDragging(index, false);
156
+ };
157
+
158
+ let { keyboardProps } = useKeyboard({
159
+ shortcuts: {
160
+ PageUp: () => {
161
+ return keyboardUpdate(() => {
162
+ state.incrementThumb(index, state.pageSize);
163
+ });
164
+ },
165
+ PageDown: () => {
166
+ return keyboardUpdate(() => {
167
+ state.decrementThumb(index, state.pageSize);
168
+ });
169
+ },
170
+ Home: () => {
171
+ return keyboardUpdate(() => {
172
+ state.setThumbValue(index, state.getThumbMinValue(index));
173
+ });
174
+ },
175
+ End: () => {
176
+ return keyboardUpdate(() => {
177
+ state.setThumbValue(index, state.getThumbMaxValue(index));
178
+ });
217
179
  },
218
180
  },
219
- subSlot(slot, 'keyboard'),
220
- );
181
+ allowRepeats: true,
182
+ });
221
183
 
222
- let { moveProps } = useMove(
223
- {
224
- onMoveStart() {
225
- currentPosition.current = null;
226
- state.setThumbDragging(index, true);
227
- },
228
- onMove({ deltaX, deltaY, pointerType, shiftKey }) {
229
- const { getThumbPercent, setThumbPercent, decrementThumb, incrementThumb, step, pageSize } =
230
- state;
231
- if (!trackRef.current) {
232
- return;
233
- }
234
- let { width, height } = trackRef.current.getBoundingClientRect();
235
- let size = isVertical ? height : width;
184
+ let { moveProps } = useMove({
185
+ onMoveStart() {
186
+ currentPosition.current = null;
187
+ state.setThumbDragging(index, true);
188
+ },
189
+ onMove({ deltaX, deltaY, pointerType, shiftKey }: import('@react-types/shared').MoveMoveEvent) {
190
+ const { getThumbPercent, setThumbPercent, decrementThumb, incrementThumb, step, pageSize } =
191
+ state;
192
+ if (!trackRef.current) {
193
+ return;
194
+ }
195
+ let { width, height } = trackRef.current.getBoundingClientRect();
196
+ let size = isVertical ? height : width;
236
197
 
237
- if (currentPosition.current == null) {
238
- currentPosition.current = getThumbPercent(index) * size;
239
- }
240
- if (pointerType === 'keyboard') {
241
- if ((deltaX > 0 && reverseX) || (deltaX < 0 && !reverseX) || deltaY > 0) {
242
- decrementThumb(index, shiftKey ? pageSize : step);
243
- } else {
244
- incrementThumb(index, shiftKey ? pageSize : step);
245
- }
198
+ if (currentPosition.current == null) {
199
+ currentPosition.current = getThumbPercent(index) * size;
200
+ }
201
+ if (pointerType === 'keyboard') {
202
+ if ((deltaX > 0 && reverseX) || (deltaX < 0 && !reverseX) || deltaY > 0) {
203
+ decrementThumb(index, shiftKey ? pageSize : step);
246
204
  } else {
247
- let delta = isVertical ? deltaY : deltaX;
248
- if (isVertical || reverseX) {
249
- delta = -delta;
250
- }
251
-
252
- currentPosition.current += delta;
253
- setThumbPercent(index, clamp(currentPosition.current / size, 0, 1));
205
+ incrementThumb(index, shiftKey ? pageSize : step);
254
206
  }
255
- },
256
- onMoveEnd() {
257
- state.setThumbDragging(index, false);
258
- },
207
+ } else {
208
+ let delta = isVertical ? deltaY : deltaX;
209
+ if (isVertical || reverseX) {
210
+ delta = -delta;
211
+ }
212
+
213
+ currentPosition.current += delta;
214
+ setThumbPercent(index, clamp(currentPosition.current / size, 0, 1));
215
+ }
259
216
  },
260
- subSlot(slot, 'move'),
261
- );
217
+ onMoveEnd() {
218
+ state.setThumbDragging(index, false);
219
+ },
220
+ });
262
221
 
263
222
  // Immediately register editability with the state
264
223
  state.setThumbEditable(index, !isDisabled);
@@ -269,10 +228,9 @@ export function useSliderThumb(...args: any[]): SliderThumbAria {
269
228
  onBlur: () => state.setFocusedThumb(undefined),
270
229
  }),
271
230
  inputRef,
272
- subSlot(slot, 'focusable'),
273
231
  );
274
232
 
275
- let currentPointer = useRef<number | undefined>(undefined, subSlot(slot, 'pointer'));
233
+ let currentPointer = useRef<number | undefined>(undefined);
276
234
  let onDown = (id?: number) => {
277
235
  focusInput();
278
236
  currentPointer.current = id;
@@ -283,8 +241,13 @@ export function useSliderThumb(...args: any[]): SliderThumbAria {
283
241
  addGlobalListener(window, 'pointerup', onUp, false);
284
242
  };
285
243
 
286
- let onUp = (e: any) => {
287
- let id = e.pointerId ?? e.changedTouches?.[0].identifier;
244
+ let onUp = (e: globalThis.PointerEvent | globalThis.TouchEvent | globalThis.MouseEvent) => {
245
+ let id =
246
+ 'pointerId' in e
247
+ ? e.pointerId
248
+ : 'changedTouches' in e
249
+ ? e.changedTouches[0]?.identifier
250
+ : undefined;
288
251
  if (id === currentPointer.current) {
289
252
  focusInput();
290
253
  state.setThumbDragging(index, false);
@@ -300,38 +263,34 @@ export function useSliderThumb(...args: any[]): SliderThumbAria {
300
263
  }
301
264
 
302
265
  let interactions = !isDisabled
303
- ? mergeProps(keyboardProps, moveProps, {
304
- onMouseDown: (e: MouseEvent) => {
266
+ ? // oxlint-disable-next-line react/react-compiler
267
+ mergeProps(keyboardProps, moveProps, {
268
+ onMouseDown: (e: React.MouseEvent) => {
305
269
  if (e.button !== 0 || e.altKey || e.ctrlKey || e.metaKey) {
306
270
  return;
307
271
  }
308
272
  onDown();
309
273
  },
310
- onPointerDown: (e: PointerEvent) => {
274
+ onPointerDown: (e: React.PointerEvent) => {
311
275
  if (e.button !== 0 || e.altKey || e.ctrlKey || e.metaKey) {
312
276
  return;
313
277
  }
314
278
  onDown(e.pointerId);
315
279
  },
316
- onTouchStart: (e: TouchEvent) => {
280
+ onTouchStart: (e: React.TouchEvent) => {
317
281
  onDown(e.changedTouches[0].identifier);
318
282
  },
319
283
  })
320
284
  : {};
321
285
 
322
- useFormReset(
323
- inputRef,
324
- state.defaultValues[index],
325
- (v) => {
326
- state.setThumbValue(index, v);
327
- },
328
- subSlot(slot, 'reset'),
329
- );
286
+ useFormReset(inputRef, state.defaultValues[index], (v) => {
287
+ state.setThumbValue(index, v);
288
+ });
330
289
 
331
290
  // We install mouse handlers for the drag motion on the thumb div, but
332
291
  // not the key handler for moving the thumb with the slider. Instead,
333
292
  // we focus the range input, and let the browser handle the keyboard
334
- // interactions; we then listen to input's native `input` event to update state.
293
+ // interactions; we then listen to input's onChange to update state.
335
294
  return {
336
295
  inputProps: mergeProps(focusableProps, fieldProps, {
337
296
  type: 'range',
@@ -352,8 +311,6 @@ export function useSliderThumb(...args: any[]): SliderThumbAria {
352
311
  .filter(Boolean)
353
312
  .join(' '),
354
313
  'aria-details': [data['aria-details'], opts['aria-details']].filter(Boolean).join(' '),
355
- // octane adaptation: React's synthetic onChange for range inputs rides the
356
- // native `input` event — onInput is the direct equivalent.
357
314
  onInput: (e: Event) => {
358
315
  state.setThumbValue(index, parseFloat((getEventTarget(e) as HTMLInputElement).value));
359
316
  },