@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
@@ -0,0 +1,395 @@
1
+ /** @jsxImportSource octane */
2
+ // Ported from adobe/react-spectrum@5ecb3333001313e83898cd07644227897e3bae1f (packages/react-aria-components/src/TokenField.tsx).
3
+ /*
4
+ * Copyright 2026 Adobe. All rights reserved.
5
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License. You may obtain a copy
7
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
8
+ *
9
+ * Unless required by applicable law or agreed to in writing, software distributed under
10
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
11
+ * OF ANY KIND, either express or implied. See the License for the specific language
12
+ * governing permissions and limitations under the License.
13
+ */
14
+
15
+ import { isChildrenBlock, type OctaneNode } from 'octane';
16
+ import { AriaTokenFieldProps } from '../upstream-exports/react-aria/useTokenField';
17
+ import {
18
+ ClassNameOrFunction,
19
+ ContextValue,
20
+ dom,
21
+ Provider,
22
+ RenderProps,
23
+ SlotProps,
24
+ StyleRenderProps,
25
+ useContextProps,
26
+ useRenderProps,
27
+ useSlot,
28
+ useSlottedContext,
29
+ } from './utils';
30
+ import { createHideableComponent } from '../collections/Hidden';
31
+ import { FieldInputContext } from './Autocomplete';
32
+ import { filterDOMProps } from '../upstream-exports/react-aria/filterDOMProps';
33
+ import { forwardRefType, GlobalDOMAttributes } from '@react-types/shared';
34
+ import { HoverProps, useHover } from '../upstream-exports/react-aria/useHover';
35
+ import { LabelContext } from './Label';
36
+ import { mergeProps } from '../upstream-exports/react-aria/mergeProps';
37
+ import { mergeRefs } from '../upstream-exports/react-aria/mergeRefs';
38
+ import React, {
39
+ createContext,
40
+ ForwardedRef,
41
+ forwardRef,
42
+ HTMLAttributes,
43
+ memo,
44
+ RefObject,
45
+ useContext,
46
+ useMemo,
47
+ } from '../compat/react';
48
+ import { TextContext } from './Text';
49
+ import {
50
+ TokenFieldState,
51
+ TokenFieldValue,
52
+ TokenSegment,
53
+ useTokenFieldState,
54
+ } from '../upstream-exports/react-stately/useTokenFieldState';
55
+ import { useFocusRing } from '../upstream-exports/react-aria/useFocusRing';
56
+ import { useObjectRef } from '../upstream-exports/react-aria/useObjectRef';
57
+ import { useToken, useTokenField } from '../upstream-exports/react-aria/useTokenField';
58
+
59
+ export interface TokenFieldRenderProps {
60
+ /**
61
+ * Whether the token field is disabled.
62
+ *
63
+ * @selector [data-disabled]
64
+ */
65
+ isDisabled: boolean;
66
+ /**
67
+ * Whether the token field is read only.
68
+ *
69
+ * @selector [data-readonly]
70
+ */
71
+ isReadOnly: boolean;
72
+ }
73
+
74
+ export interface TokenFieldProps<T extends TokenFieldValue = TokenFieldValue>
75
+ extends
76
+ AriaTokenFieldProps<T>,
77
+ RenderProps<TokenFieldRenderProps>,
78
+ SlotProps,
79
+ GlobalDOMAttributes<HTMLDivElement> {
80
+ /**
81
+ * The CSS [className](https://developer.mozilla.org/en-US/docs/Web/API/Element/className) for the
82
+ * element. A function may be provided to compute the class based on component state.
83
+ *
84
+ * @default 'react-aria-TokenField'
85
+ */
86
+ className?: ClassNameOrFunction<TokenFieldRenderProps>;
87
+ }
88
+
89
+ export interface TokenInputRenderProps {
90
+ /**
91
+ * Whether the token input is currently hovered with a mouse.
92
+ *
93
+ * @selector [data-hovered]
94
+ */
95
+ isHovered: boolean;
96
+ /**
97
+ * Whether the token input is focused, either via a mouse or keyboard.
98
+ *
99
+ * @selector [data-focused]
100
+ */
101
+ isFocused: boolean;
102
+ /**
103
+ * Whether the token input is keyboard focused.
104
+ *
105
+ * @selector [data-focus-visible]
106
+ */
107
+ isFocusVisible: boolean;
108
+ /**
109
+ * Whether the token input is disabled.
110
+ *
111
+ * @selector [data-disabled]
112
+ */
113
+ isDisabled: boolean;
114
+ /**
115
+ * Whether the token input is read only.
116
+ *
117
+ * @selector [data-readonly]
118
+ */
119
+ isReadOnly: boolean;
120
+ }
121
+
122
+ export interface TokenInputProps<T extends TokenFieldValue = TokenFieldValue>
123
+ extends
124
+ HoverProps,
125
+ StyleRenderProps<TokenInputRenderProps>,
126
+ SlotProps,
127
+ GlobalDOMAttributes<HTMLDivElement> {
128
+ /**
129
+ * A function that renders a token for each segment in the token field.
130
+ */
131
+ children: (segment: TokenSegment<T extends TokenFieldValue<infer V> ? V : never>) => OctaneNode;
132
+ /**
133
+ * The CSS [className](https://developer.mozilla.org/en-US/docs/Web/API/Element/className) for the
134
+ * element. A function may be provided to compute the class based on component state.
135
+ *
136
+ * @default 'react-aria-TokenInput'
137
+ */
138
+ className?: ClassNameOrFunction<TokenInputRenderProps>;
139
+ }
140
+
141
+ interface TokenInputContextValue<T extends TokenFieldValue = TokenFieldValue> {
142
+ tokenFieldProps: HTMLAttributes<HTMLDivElement>;
143
+ state: TokenFieldState<T>;
144
+ isDisabled: boolean;
145
+ isReadOnly: boolean;
146
+ autocompleteProps?: HTMLAttributes<HTMLDivElement>;
147
+ ref: RefObject<HTMLDivElement | null>;
148
+ }
149
+
150
+ export const TokenFieldContext = createContext<ContextValue<TokenFieldProps, HTMLDivElement>>(null);
151
+ const TokenInputContext = createContext<TokenInputContextValue | null>(null);
152
+
153
+ /**
154
+ * A token field allows users to enter text with inline tokens. Use it to build AI prompt fields,
155
+ * tag inputs, structured search fields, mention inputs, and multi-select comboboxes.
156
+ */
157
+ export const TokenField = /*#__PURE__*/ createHideableComponent(function TokenField<
158
+ T extends TokenFieldValue = TokenFieldValue,
159
+ >(props: TokenFieldProps<T>, ref: ForwardedRef<HTMLDivElement>) {
160
+ [props, ref] = useContextProps(props, ref, TokenFieldContext);
161
+ let [labelRef, label] = useSlot(!props['aria-label'] && !props['aria-labelledby']);
162
+
163
+ let fieldCtx = useSlottedContext(FieldInputContext, props.slot);
164
+ let {
165
+ value: _autocompleteValue,
166
+ onChange: onAutocompleteChange,
167
+ ref: autocompleteRef,
168
+ ...autocompleteProps
169
+ } = fieldCtx ?? {};
170
+ let inputRef = useObjectRef(autocompleteRef);
171
+
172
+ let isDisabled = props.isDisabled || false;
173
+ let isReadOnly = props.isReadOnly || false;
174
+
175
+ let state = useTokenFieldState<T>({
176
+ ...props,
177
+ onChange: (value: T) => {
178
+ props.onChange?.(value);
179
+ onAutocompleteChange?.(value.toString());
180
+ },
181
+ });
182
+
183
+ let { tokenFieldProps, labelProps, descriptionProps } = useTokenField(
184
+ {
185
+ ...props,
186
+ // @ts-ignore - not a public prop, used to determine if slot is present
187
+ label,
188
+ role:
189
+ props.role ||
190
+ ('role' in autocompleteProps
191
+ ? (autocompleteProps.role as 'combobox' | 'searchbox' | 'textbox')
192
+ : undefined) ||
193
+ 'textbox',
194
+ },
195
+ state,
196
+ inputRef,
197
+ );
198
+
199
+ let renderProps = useRenderProps({
200
+ ...props,
201
+ values: {
202
+ isDisabled,
203
+ isReadOnly,
204
+ },
205
+ defaultClassName: 'react-aria-TokenField',
206
+ });
207
+
208
+ let DOMProps = filterDOMProps(props, { global: true });
209
+
210
+ return (
211
+ <dom.div
212
+ {...DOMProps}
213
+ {...renderProps}
214
+ ref={ref}
215
+ slot={props.slot || undefined}
216
+ data-disabled={isDisabled || undefined}
217
+ data-readonly={isReadOnly || undefined}
218
+ >
219
+ <Provider
220
+ values={[
221
+ [LabelContext, { ...labelProps, elementType: 'span', ref: labelRef }],
222
+ [
223
+ TextContext,
224
+ {
225
+ slots: {
226
+ description: descriptionProps,
227
+ },
228
+ },
229
+ ],
230
+ [
231
+ TokenInputContext,
232
+ {
233
+ tokenFieldProps,
234
+ state: state as any,
235
+ isDisabled,
236
+ isReadOnly,
237
+ autocompleteProps: autocompleteProps as HTMLAttributes<HTMLDivElement>,
238
+ ref: inputRef as RefObject<HTMLDivElement | null>,
239
+ },
240
+ ],
241
+ ]}
242
+ >
243
+ {renderProps.children}
244
+ </Provider>
245
+ </dom.div>
246
+ );
247
+ });
248
+
249
+ /**
250
+ * A token input represents the editable area within a token field.
251
+ */
252
+ export const TokenInput = /*#__PURE__*/ (forwardRef as any)(function TokenInput<
253
+ T extends TokenFieldValue = TokenFieldValue,
254
+ >(props: TokenInputProps<T>, forwardedRef: ForwardedRef<HTMLDivElement | null>) {
255
+ let {
256
+ tokenFieldProps,
257
+ state,
258
+ isDisabled = false,
259
+ isReadOnly = false,
260
+ autocompleteProps,
261
+ ref: contextRef,
262
+ } = useContext(TokenInputContext)!;
263
+ let ref = useMemo(() => mergeRefs(contextRef, forwardedRef), [contextRef, forwardedRef]);
264
+ let { children, ...domProps } = props;
265
+
266
+ let { isHovered, hoverProps } = useHover(domProps);
267
+ let { isFocused, isFocusVisible, focusProps } = useFocusRing();
268
+
269
+ let renderProps = useRenderProps({
270
+ ...domProps,
271
+ defaultClassName: 'react-aria-TokenInput',
272
+ values: {
273
+ isHovered,
274
+ isFocused,
275
+ isFocusVisible,
276
+ isDisabled,
277
+ isReadOnly,
278
+ },
279
+ });
280
+
281
+ let DOMProps = filterDOMProps(domProps, { global: true });
282
+
283
+ return (
284
+ <dom.div
285
+ {...mergeProps(
286
+ DOMProps,
287
+ renderProps,
288
+ focusProps,
289
+ hoverProps,
290
+ tokenFieldProps,
291
+ autocompleteProps,
292
+ )}
293
+ ref={ref}
294
+ data-focused={isFocused || undefined}
295
+ data-focus-visible={isFocusVisible || undefined}
296
+ data-disabled={isDisabled || undefined}
297
+ data-readonly={isReadOnly || undefined}
298
+ style={{ ...renderProps.style, ...tokenFieldProps?.style }}
299
+ >
300
+ <CompositionRenderBlocker isComposing={state.isComposing}>
301
+ {state.value.segments.map((v, i) => {
302
+ switch (v.type) {
303
+ case 'token': {
304
+ // Compiled template children are blocks, not per-token render callbacks.
305
+ let token = isChildrenBlock(children) ? children : children(v);
306
+ return (
307
+ // Wrap tokens in zero-width spaces so the cursor is placed correctly.
308
+ <span key={i}>
309
+ {'\u200b'}
310
+ {token}
311
+ {'\u200b'}
312
+ </span>
313
+ );
314
+ }
315
+ case 'text':
316
+ return v.text;
317
+ }
318
+ })}
319
+ {/* Force cursor to the next line if the last segment ends with a newline. */}
320
+ {state.value.segments.at(-1)?.text.endsWith('\n') && <br />}
321
+ </CompositionRenderBlocker>
322
+ </dom.div>
323
+ );
324
+ });
325
+
326
+ export interface TokenRenderProps {
327
+ /**
328
+ * Whether the token is selected.
329
+ *
330
+ * @selector [data-selected]
331
+ */
332
+ isSelected: boolean;
333
+ /**
334
+ * Whether the token is disabled.
335
+ *
336
+ * @selector [data-disabled]
337
+ */
338
+ isDisabled: boolean;
339
+ }
340
+
341
+ export interface TokenProps
342
+ extends RenderProps<TokenRenderProps, 'span'>, GlobalDOMAttributes<HTMLSpanElement> {
343
+ /**
344
+ * The CSS [className](https://developer.mozilla.org/en-US/docs/Web/API/Element/className) for the
345
+ * element. A function may be provided to compute the class based on component state.
346
+ *
347
+ * @default 'react-aria-Token'
348
+ */
349
+ className?: ClassNameOrFunction<TokenRenderProps>;
350
+ }
351
+
352
+ /**
353
+ * A token represents an inline segment within a token field.
354
+ */
355
+ export const Token = forwardRef(function Token(
356
+ props: TokenProps,
357
+ ref: ForwardedRef<HTMLSpanElement>,
358
+ ) {
359
+ let { isDisabled } = useContext(TokenInputContext)!;
360
+ let objectRef = useObjectRef(ref);
361
+ let { tokenProps, isSelected } = useToken(props, {}, objectRef);
362
+
363
+ let renderProps = useRenderProps({
364
+ ...props,
365
+ defaultClassName: 'react-aria-Token',
366
+ values: {
367
+ isSelected,
368
+ isDisabled,
369
+ },
370
+ });
371
+
372
+ let DOMProps = filterDOMProps(props, { global: true });
373
+
374
+ return (
375
+ <dom.span
376
+ ref={objectRef}
377
+ {...mergeProps(DOMProps, renderProps, tokenProps)}
378
+ data-selected={isSelected || undefined}
379
+ data-disabled={isDisabled || undefined}
380
+ style={{
381
+ ...renderProps.style,
382
+ ...tokenProps.style,
383
+ }}
384
+ >
385
+ {renderProps.children}
386
+ </dom.span>
387
+ );
388
+ });
389
+
390
+ // Prevents React from re-rendering during composition events.
391
+ const CompositionRenderBlocker = memo(
392
+ ({ children }: { children: React.ReactNode; isComposing: boolean }) => children,
393
+ (prevProps, nextProps) =>
394
+ nextProps.isComposing ? true : prevProps.children === nextProps.children,
395
+ );
@@ -168,8 +168,8 @@ export function Tooltip(allProps: TooltipProps): any {
168
168
  let localState = useTooltipTriggerState(props, subSlot(slot, 'state'));
169
169
  let state =
170
170
  props.isOpen != null || props.defaultOpen != null || !contextState ? localState : contextState;
171
- let isExiting =
172
- useExitAnimation(ref, state.isOpen, subSlot(slot, 'exit')) || props.isExiting || false;
171
+ let exitAnimation = useExitAnimation(ref, state.isOpen, subSlot(slot, 'exit'));
172
+ let isExiting = props.isExiting || (!state.shouldSkipAnimation && exitAnimation) || false;
173
173
  if (!state.isOpen && !isExiting) {
174
174
  return null;
175
175
  }
@@ -205,10 +205,8 @@ function TooltipInner(
205
205
  subSlot(slot, 'position'),
206
206
  );
207
207
 
208
- let isEntering =
209
- useEnterAnimation(props.tooltipRef, !!placement, subSlot(slot, 'enter')) ||
210
- props.isEntering ||
211
- false;
208
+ let enterAnimation = useEnterAnimation(props.tooltipRef, !!placement, subSlot(slot, 'enter'));
209
+ let isEntering = props.isEntering || (!state.shouldSkipAnimation && enterAnimation) || false;
212
210
  let renderProps = useRenderProps(
213
211
  {
214
212
  ...props,
@@ -780,7 +780,7 @@ export interface TreeItemProps<T = object>
780
780
  LinkDOMProps,
781
781
  HoverEvents,
782
782
  PressEvents,
783
- Pick<AriaTreeItemOptions, 'hasChildItems'>,
783
+ Pick<AriaTreeItemOptions, 'hasChildItems' | 'focusMode' | 'allowsArrowNavigation'>,
784
784
  Omit<GlobalDOMAttributes, 'onClick'> {
785
785
  /**
786
786
  * The CSS [className](https://developer.mozilla.org/en-US/docs/Web/API/Element/className) for the
@@ -836,6 +836,8 @@ export const TreeItem: <T extends object = object>(props: TreeItemProps<T> & { r
836
836
  let { rowProps, gridCellProps, expandButtonProps, descriptionProps, ...states } = useTreeItem(
837
837
  {
838
838
  node: item!,
839
+ focusMode: props.focusMode,
840
+ allowsArrowNavigation: props.allowsArrowNavigation,
839
841
  shouldSelectOnPressUp: !!dragState,
840
842
  },
841
843
  state,
@@ -1092,6 +1094,7 @@ export const TreeItem: <T extends object = object>(props: TreeItemProps<T> & { r
1092
1094
  CheckboxContext,
1093
1095
  {
1094
1096
  slots: {
1097
+ [DEFAULT_SLOT]: {},
1095
1098
  selection: checkboxProps,
1096
1099
  },
1097
1100
  },
@@ -1100,6 +1103,7 @@ export const TreeItem: <T extends object = object>(props: TreeItemProps<T> & { r
1100
1103
  CheckboxFieldContext,
1101
1104
  {
1102
1105
  slots: {
1106
+ [DEFAULT_SLOT]: {},
1103
1107
  selection: checkboxProps,
1104
1108
  },
1105
1109
  },
@@ -1150,7 +1154,9 @@ export interface TreeLoadMoreItemRenderProps {
1150
1154
  }
1151
1155
 
1152
1156
  export interface TreeLoadMoreItemProps
1153
- extends Omit<LoadMoreSentinelProps, 'collection'>, RenderProps<TreeLoadMoreItemRenderProps> {
1157
+ extends
1158
+ Omit<LoadMoreSentinelProps, 'collection' | 'direction'>,
1159
+ RenderProps<TreeLoadMoreItemRenderProps> {
1154
1160
  /**
1155
1161
  * The CSS [className](https://developer.mozilla.org/en-US/docs/Web/API/Element/className) for the
1156
1162
  * element. A function may be provided to compute the class based on component state.
@@ -1374,17 +1380,16 @@ function RootDropIndicator(): any {
1374
1380
  });
1375
1381
  }
1376
1382
 
1377
- export interface GridListSectionProps<T>
1378
- extends SectionProps<T>, DOMRenderProps<'div', undefined> {}
1383
+ export interface TreeSectionProps<T> extends SectionProps<T>, DOMRenderProps<'div', undefined> {}
1379
1384
 
1380
1385
  /**
1381
1386
  * A TreeSection represents a section within a Tree.
1382
1387
  */
1383
1388
  export const TreeSection: <T extends object = object>(
1384
- props: GridListSectionProps<T> & { ref?: any },
1389
+ props: GridListHeaderProps & { ref?: any },
1385
1390
  ) => any = /*#__PURE__*/ createBranchComponent(SectionNode, function TreeSection<
1386
1391
  T,
1387
- >(props: GridListSectionProps<T>, forwardedRef: any, item?: Node<T>): any {
1392
+ >(props: TreeSectionProps<T>, forwardedRef: any, item?: Node<T>): any {
1388
1393
  const slot = S('TreeSection');
1389
1394
  let state = useContext(TreeStateContext)!;
1390
1395
  let { CollectionBranch } = useContext(CollectionRendererContext);
@@ -1428,7 +1433,9 @@ export const TreeSection: <T extends object = object>(
1428
1433
  });
1429
1434
  });
1430
1435
 
1431
- export const TreeHeader = (props: GridListHeaderProps): ReactNode => {
1436
+ export interface TreeHeaderProps extends GridListHeaderProps {}
1437
+
1438
+ export const TreeHeader = (props: TreeHeaderProps): ReactNode => {
1432
1439
  return createElement(GridListHeader, {
1433
1440
  className: 'react-aria-TreeHeader',
1434
1441
  ...props,
@@ -50,15 +50,17 @@ export interface VirtualizerProps<O> {
50
50
  layout: LayoutClass<O> | ILayout<O>;
51
51
  /** Options for the layout. */
52
52
  layoutOptions?: O;
53
+ shouldObserveItemSize?: boolean;
53
54
  }
54
55
 
55
- interface LayoutContextValue {
56
+ interface VirtualizerOptionsContextValue {
56
57
  layout: ILayout<any>;
57
58
  layoutOptions?: any;
59
+ shouldObserveItemSize?: boolean;
58
60
  }
59
61
 
60
62
  const VirtualizerContext = createContext<VirtualizerState<any, any> | null>(null);
61
- const LayoutContext = createContext<LayoutContextValue | null>(null);
63
+ const VirtualizerOptionsContext = createContext<VirtualizerOptionsContextValue | null>(null);
62
64
 
63
65
  /**
64
66
  * A Virtualizer renders a scrollable collection of data using customizable layouts.
@@ -66,7 +68,7 @@ const LayoutContext = createContext<LayoutContextValue | null>(null);
66
68
  * them as the user scrolls.
67
69
  */
68
70
  export function Virtualizer<O>(props: VirtualizerProps<O>): JSX.Element {
69
- let { children, layout: layoutProp, layoutOptions } = props;
71
+ let { children, layout: layoutProp, layoutOptions, shouldObserveItemSize } = props;
70
72
  let layout = useMemo(
71
73
  () => (typeof layoutProp === 'function' ? new layoutProp() : layoutProp),
72
74
  [layoutProp],
@@ -86,7 +88,9 @@ export function Virtualizer<O>(props: VirtualizerProps<O>): JSX.Element {
86
88
 
87
89
  return (
88
90
  <CollectionRendererContext.Provider value={renderer}>
89
- <LayoutContext.Provider value={{ layout, layoutOptions }}>{children}</LayoutContext.Provider>
91
+ <VirtualizerOptionsContext.Provider value={{ layout, layoutOptions, shouldObserveItemSize }}>
92
+ {children}
93
+ </VirtualizerOptionsContext.Provider>
90
94
  </CollectionRendererContext.Provider>
91
95
  );
92
96
  }
@@ -97,7 +101,7 @@ function CollectionRoot({
97
101
  scrollRef,
98
102
  renderDropIndicator,
99
103
  }: CollectionRootProps) {
100
- let { layout, layoutOptions } = useContext(LayoutContext)!;
104
+ let { layout, layoutOptions, shouldObserveItemSize } = useContext(VirtualizerOptionsContext)!;
101
105
  let layoutOptions2 = layout.useLayoutOptions?.();
102
106
  let state = useVirtualizerState({
103
107
  allowsWindowScrolling: true,
@@ -114,12 +118,13 @@ function CollectionRoot({
114
118
  }
115
119
  },
116
120
  persistedKeys,
117
- layoutOptions: useMemo(() => {
118
- if (layoutOptions && layoutOptions2) {
119
- return { ...layoutOptions, ...layoutOptions2 };
120
- }
121
- return layoutOptions || layoutOptions2;
122
- }, [layoutOptions, layoutOptions2]),
121
+ layoutOptions: useMemo(
122
+ () =>
123
+ layoutOptions && layoutOptions2
124
+ ? { ...layoutOptions, ...layoutOptions2 }
125
+ : layoutOptions || layoutOptions2,
126
+ [layoutOptions, layoutOptions2],
127
+ ),
123
128
  });
124
129
 
125
130
  let { contentProps } = useScrollView(
@@ -137,7 +142,7 @@ function CollectionRoot({
137
142
  return (
138
143
  <div {...contentProps}>
139
144
  <VirtualizerContext.Provider value={state}>
140
- {renderChildren(null, state.visibleViews, renderDropIndicator)}
145
+ {renderChildren(null, state.visibleViews, renderDropIndicator, shouldObserveItemSize)}
141
146
  </VirtualizerContext.Provider>
142
147
  </div>
143
148
  );
@@ -146,21 +151,31 @@ function CollectionRoot({
146
151
  function CollectionBranch({ parent, renderDropIndicator }: CollectionBranchProps) {
147
152
  let virtualizer = useContext(VirtualizerContext);
148
153
  let parentView = virtualizer!.virtualizer.getVisibleView(parent.key)!;
149
- return renderChildren(parentView, Array.from(parentView.children), renderDropIndicator);
154
+ let { shouldObserveItemSize } = useContext(VirtualizerOptionsContext)!;
155
+ return renderChildren(
156
+ parentView,
157
+ Array.from(parentView.children),
158
+ renderDropIndicator,
159
+ shouldObserveItemSize,
160
+ );
150
161
  }
151
162
 
152
163
  function renderChildren(
153
164
  parent: View | null,
154
165
  children: View[],
155
166
  renderDropIndicator?: (target: ItemDropTarget) => ReactNode,
167
+ shouldObserveItemSize?: boolean,
156
168
  ) {
157
- return children.map((view) => renderWrapper(parent, view, renderDropIndicator));
169
+ return children.map((view) =>
170
+ renderWrapper(parent, view, renderDropIndicator, shouldObserveItemSize),
171
+ );
158
172
  }
159
173
 
160
174
  function renderWrapper(
161
175
  parent: View | null,
162
176
  reusableView: View,
163
177
  renderDropIndicator?: (target: ItemDropTarget) => ReactNode,
178
+ shouldObserveItemSize?: boolean,
164
179
  ): ReactNode {
165
180
  let rendered = (
166
181
  <VirtualizerItem
@@ -168,6 +183,7 @@ function renderWrapper(
168
183
  layoutInfo={reusableView.layoutInfo!}
169
184
  virtualizer={reusableView.virtualizer}
170
185
  parent={parent?.layoutInfo}
186
+ shouldObserveItemSize={shouldObserveItemSize}
171
187
  >
172
188
  {reusableView.rendered}
173
189
  </VirtualizerItem>
@@ -612,3 +612,25 @@ export type {
612
612
  TableLoadMoreItemProps,
613
613
  TableFooterProps,
614
614
  } from './Table';
615
+
616
+ export { PreviewTrigger } from './PreviewTrigger';
617
+ export type { PreviewTriggerProps } from './PreviewTrigger';
618
+ export { TokenField, TokenInput, Token, TokenFieldContext } from './TokenField';
619
+ export type {
620
+ TokenFieldProps,
621
+ TokenFieldRenderProps,
622
+ TokenInputProps,
623
+ TokenInputRenderProps,
624
+ TokenProps,
625
+ TokenRenderProps,
626
+ } from './TokenField';
627
+ export { TokenFieldValue } from '../stately/tokenfield/TokenFieldValue';
628
+ export type { GridListHeaderProps } from './GridList';
629
+ export type {
630
+ DOMRenderProps,
631
+ PossibleLinkDOMRenderProps,
632
+ DOMRenderFunction,
633
+ ClassNameOrFunction,
634
+ StyleOrFunction,
635
+ ChildrenOrFunction,
636
+ } from './utils';
@@ -84,7 +84,7 @@ export interface DOMProps extends StyleProps, SharedDOMProps {
84
84
 
85
85
  export type ClassNameOrFunction<T> =
86
86
  string | ((values: T & { defaultClassName: string | undefined }) => string);
87
- type StyleOrFunction<T> =
87
+ export type StyleOrFunction<T> =
88
88
  CSSProperties | ((values: T & { defaultStyle: CSSProperties }) => CSSProperties | undefined);
89
89
 
90
90
  export interface StyleRenderProps<T, E extends string = 'div'> extends DOMRenderProps<E, T> {
@@ -18,7 +18,6 @@ import {
18
18
  DOMProps,
19
19
  GroupDOMAttributes,
20
20
  InputDOMProps,
21
- KeyboardEvent,
22
21
  RefObject,
23
22
  ValidationResult,
24
23
  } from '@react-types/shared';
@@ -225,16 +224,8 @@ export function useDateField<T extends DateValue>(
225
224
  },
226
225
  },
227
226
  fieldProps: mergeProps(domProps, fieldDOMProps, groupProps, focusWithinProps, {
228
- onKeyDown(e: KeyboardEvent) {
229
- if (props.onKeyDown) {
230
- props.onKeyDown(e);
231
- }
232
- },
233
- onKeyUp(e: KeyboardEvent) {
234
- if (props.onKeyUp) {
235
- props.onKeyUp(e);
236
- }
237
- },
227
+ onKeyDown: props.onKeyDown,
228
+ onKeyUp: props.onKeyUp,
238
229
  style: {
239
230
  unicodeBidi: 'isolate',
240
231
  },