diff --git a/.yarn/patches/@types-node-npm-20.14.13-41f92d384c.patch b/.yarn/patches/@types-node-npm-20.14.13-41f92d384c.patch new file mode 100644 index 00000000000..7afc48f1b36 --- /dev/null +++ b/.yarn/patches/@types-node-npm-20.14.13-41f92d384c.patch @@ -0,0 +1,13 @@ +diff --git a/buffer.d.ts b/buffer.d.ts +index 5d6c97d6b5d47fd189f795498aefd6b8d7713b7d..b9a22c4634fa6308006ae17d3527ff3c518a789d 100644 +--- a/buffer.d.ts ++++ b/buffer.d.ts +@@ -629,7 +629,7 @@ declare module "buffer" { + */ + poolSize: number; + } +- interface Buffer extends Uint8Array { ++ interface Buffer extends Uint8Array { + /** + * Writes `string` to `buf` at `offset` according to the character encoding in`encoding`. The `length` parameter is the number of bytes to write. If `buf` did + * not contain enough space to fit the entire string, only part of `string` will be diff --git a/package.json b/package.json index 37f0c41ab60..f9801e7ba8b 100644 --- a/package.json +++ b/package.json @@ -235,7 +235,10 @@ "recast": "0.23.6", "ast-types": "0.16.1", "svgo": "^3", - "@testing-library/user-event": "patch:@testing-library/user-event@npm%3A14.6.1#~/.yarn/patches/@testing-library-user-event-npm-14.6.1-5da7e1d4e2.patch" + "@testing-library/user-event": "patch:@testing-library/user-event@npm%3A14.6.1#~/.yarn/patches/@testing-library-user-event-npm-14.6.1-5da7e1d4e2.patch", + "@types/node@npm:*": "patch:@types/node@npm%3A20.14.13#~/.yarn/patches/@types-node-npm-20.14.13-41f92d384c.patch", + "@types/node@npm:^18.0.0": "patch:@types/node@npm%3A20.14.13#~/.yarn/patches/@types-node-npm-20.14.13-41f92d384c.patch", + "@types/node@npm:>= 8": "patch:@types/node@npm%3A20.14.13#~/.yarn/patches/@types-node-npm-20.14.13-41f92d384c.patch" }, "@parcel/transformer-css": { "cssModules": { diff --git a/packages/@react-spectrum/calendar/stories/Calendar.stories.tsx b/packages/@react-spectrum/calendar/stories/Calendar.stories.tsx index 649ff4962e7..0921ebea351 100644 --- a/packages/@react-spectrum/calendar/stories/Calendar.stories.tsx +++ b/packages/@react-spectrum/calendar/stories/Calendar.stories.tsx @@ -203,7 +203,7 @@ const calendars = [ function Example(props) { let [locale, setLocale] = React.useState(''); - let [calendar, setCalendar] = React.useState(calendars[0].key); + let [calendar, setCalendar] = React.useState(calendars[0].key); let {locale: defaultLocale} = useLocale(); let pref = preferences.find(p => p.locale === locale)!; diff --git a/packages/@react-spectrum/datepicker/stories/DateField.stories.tsx b/packages/@react-spectrum/datepicker/stories/DateField.stories.tsx index 682e5484224..3a495dd5ba6 100644 --- a/packages/@react-spectrum/datepicker/stories/DateField.stories.tsx +++ b/packages/@react-spectrum/datepicker/stories/DateField.stories.tsx @@ -212,7 +212,7 @@ export const IsDateUnavailable: DateFieldStory = { ...Default, args: { isDateUnavailable: (date) => { - return date.compare(new CalendarDate(1980, 1, 1)) >= 0 + return date.compare(new CalendarDate(1980, 1, 1)) >= 0 && date.compare(new CalendarDate(1980, 1, 8)) <= 0; }, errorMessage: 'Date unavailable.', @@ -310,7 +310,7 @@ const calendars = [ function Example(props) { let [locale, setLocale] = React.useState(''); - let [calendar, setCalendar] = React.useState(calendars[0].key); + let [calendar, setCalendar] = React.useState(calendars[0].key); let {locale: defaultLocale} = useLocale(); let pref = preferences.find(p => p.locale === locale); diff --git a/packages/@react-spectrum/datepicker/stories/DatePicker.stories.tsx b/packages/@react-spectrum/datepicker/stories/DatePicker.stories.tsx index 7af1d82c90d..0aef66b5449 100644 --- a/packages/@react-spectrum/datepicker/stories/DatePicker.stories.tsx +++ b/packages/@react-spectrum/datepicker/stories/DatePicker.stories.tsx @@ -332,7 +332,7 @@ const calendars = [ function Example(props) { let [locale, setLocale] = React.useState(''); - let [calendar, setCalendar] = React.useState(calendars[0].key); + let [calendar, setCalendar] = React.useState(calendars[0].key); let {locale: defaultLocale} = useLocale(); let pref = preferences.find(p => p.locale === locale); diff --git a/packages/@react-spectrum/datepicker/stories/DateRangePicker.stories.tsx b/packages/@react-spectrum/datepicker/stories/DateRangePicker.stories.tsx index db97cd19936..dd4ffe8c687 100644 --- a/packages/@react-spectrum/datepicker/stories/DateRangePicker.stories.tsx +++ b/packages/@react-spectrum/datepicker/stories/DateRangePicker.stories.tsx @@ -235,7 +235,7 @@ const calendars = [ function Example(props) { let [locale, setLocale] = React.useState(''); - let [calendar, setCalendar] = React.useState(calendars[0].key); + let [calendar, setCalendar] = React.useState(calendars[0].key); let {locale: defaultLocale} = useLocale(); let pref = preferences.find(p => p.locale === locale); diff --git a/packages/@react-spectrum/form/stories/Form.stories.tsx b/packages/@react-spectrum/form/stories/Form.stories.tsx index 131f5592b4f..e154e5efad7 100644 --- a/packages/@react-spectrum/form/stories/Form.stories.tsx +++ b/packages/@react-spectrum/form/stories/Form.stories.tsx @@ -482,7 +482,7 @@ function FormWithControls(props: any = {}) { let [firstName, setFirstName] = useState('hello'); let [isHunter, setIsHunter] = useState(true); let [favoritePet, setFavoritePet] = useState('cats'); - let [favoriteColor, setFavoriteColor] = useState('green' as Key); + let [favoriteColor, setFavoriteColor] = useState('green'); let [howIFeel, setHowIFeel] = useState('I feel good, o I feel so good!'); let [birthday, setBirthday] = useState(new CalendarDate(1732, 2, 22)); let [money, setMoney] = useState(50); diff --git a/packages/@react-spectrum/s2/src/Breadcrumbs.tsx b/packages/@react-spectrum/s2/src/Breadcrumbs.tsx index 003db5edfee..97cfd3d22dd 100644 --- a/packages/@react-spectrum/s2/src/Breadcrumbs.tsx +++ b/packages/@react-spectrum/s2/src/Breadcrumbs.tsx @@ -20,6 +20,7 @@ import { DefaultCollectionRenderer, HeadingContext, Link, + LinkRenderProps, Provider, Breadcrumbs as RACBreadcrumbs } from 'react-aria-components'; @@ -97,7 +98,7 @@ const wrapper = style({ const InternalBreadcrumbsContext = createContext>>({}); -/** Breadcrumbs show hierarchy and navigational context for a user’s location within an application. */ +/** Breadcrumbs show hierarchy and navigational context for a user's location within an application. */ export const Breadcrumbs = /*#__PURE__*/ (forwardRef as forwardRefType)(function Breadcrumbs(props: BreadcrumbsProps, ref: DOMRef) { [props, ref] = useSpectrumContextProps(props, ref, BreadcrumbsContext); let domRef = useDOMRef(ref); @@ -200,7 +201,7 @@ let HiddenBreadcrumbs = function (props: {listRef: RefObject({ display: 'flex', alignItems: 'center', justifyContent: 'start', @@ -245,7 +246,7 @@ const chevronStyles = style({ } }); -const linkStyles = style({ +const linkStyles = style({ ...focusRing(), borderRadius: 'sm', font: 'control', @@ -255,7 +256,8 @@ const linkStyles = style({ isCurrent: 'neutral', forcedColors: { default: 'LinkText', - isDisabled: 'GrayText' + isDisabled: 'GrayText', + isCurrent: 'GrayText' } }, transition: 'default', @@ -337,7 +339,7 @@ export const Breadcrumb = /*#__PURE__*/ (forwardRef as forwardRefType)(function ping={ping} referrerPolicy={referrerPolicy} isDisabled={isDisabled || isCurrent} - className={({isFocused, isFocusVisible, isHovered, isDisabled, isPressed}) => linkStyles({isFocused, isFocusVisible, isHovered, isDisabled, size, isPressed})}> + className={({isFocused, isFocusVisible, isHovered, isDisabled, isPressed}) => linkStyles({isFocused, isFocusVisible, isHovered, isDisabled, size, isPressed, isCurrent})}> {children} ({ ...focusRing(), ...staticColor(), display: 'flex', diff --git a/packages/@react-spectrum/s2/src/ComboBox.tsx b/packages/@react-spectrum/s2/src/ComboBox.tsx index 68377b20bac..05c11651982 100644 --- a/packages/@react-spectrum/s2/src/ComboBox.tsx +++ b/packages/@react-spectrum/s2/src/ComboBox.tsx @@ -16,6 +16,7 @@ import { ListBoxSection as AriaListBoxSection, PopoverProps as AriaPopoverProps, Button, + ButtonRenderProps, ContextValue, InputContext, ListBox, @@ -95,7 +96,7 @@ export interface ComboBoxProps extends export const ComboBoxContext = createContext>, TextFieldRef>>(null); -const inputButton = style({ +const inputButton = style({ display: 'flex', outlineStyle: 'none', textAlign: 'center', diff --git a/packages/@react-spectrum/s2/src/Menu.tsx b/packages/@react-spectrum/s2/src/Menu.tsx index caac551d223..e6f31a90529 100644 --- a/packages/@react-spectrum/s2/src/Menu.tsx +++ b/packages/@react-spectrum/s2/src/Menu.tsx @@ -23,6 +23,7 @@ import { SubmenuTriggerProps as AriaSubmenuTriggerProps, ContextValue, DEFAULT_SLOT, + MenuItemRenderProps, Provider, Separator, SeparatorProps @@ -146,7 +147,7 @@ export let sectionHeading = style({ margin: 0 }); -export let menuitem = style({ +export let menuitem = style & {isFocused: boolean, size: 'S' | 'M' | 'L' | 'XL', isLink?: boolean, hasSubmenu?: boolean, isOpen?: boolean}>({ ...focusRing(), boxSizing: 'border-box', borderRadius: 'control', @@ -293,7 +294,7 @@ let value = style({ marginStart: 8 }); -let keyboard = style({ +let keyboard = style<{size: 'S' | 'M' | 'L' | 'XL', isDisabled: boolean}>({ gridArea: 'keyboard', marginStart: 8, font: 'ui', @@ -305,7 +306,7 @@ let keyboard = style({ isDisabled: 'GrayText' } }, - background: 'gray-25', + backgroundColor: 'gray-25', unicodeBidi: 'plaintext' }); diff --git a/packages/@react-spectrum/s2/src/NumberField.tsx b/packages/@react-spectrum/s2/src/NumberField.tsx index a18f70ac951..2fedbe7b270 100644 --- a/packages/@react-spectrum/s2/src/NumberField.tsx +++ b/packages/@react-spectrum/s2/src/NumberField.tsx @@ -16,6 +16,7 @@ import { NumberField as AriaNumberField, NumberFieldProps as AriaNumberFieldProps, ButtonContext, + ButtonRenderProps, ContextValue, InputContext, Text, @@ -56,7 +57,7 @@ export interface NumberFieldProps extends export const NumberFieldContext = createContext, TextFieldRef>>(null); -const inputButton = style({ +const inputButton = style({ display: 'flex', outlineStyle: 'none', textAlign: 'center', @@ -71,7 +72,7 @@ const inputButton = style({ } }, type: { - decrementStep: 'none' + decrement: 'none' } }, borderBottomRadius: { @@ -84,7 +85,7 @@ const inputButton = style({ } }, type: { - incrementStep: 'none' + increment: 'none' } }, alignItems: 'center', diff --git a/packages/@react-spectrum/s2/src/SegmentedControl.tsx b/packages/@react-spectrum/s2/src/SegmentedControl.tsx index 32bcedcc707..d412b098404 100644 --- a/packages/@react-spectrum/s2/src/SegmentedControl.tsx +++ b/packages/@react-spectrum/s2/src/SegmentedControl.tsx @@ -12,7 +12,7 @@ import {AriaLabelingProps, DOMRef, DOMRefValue, FocusableRef, Key} from '@react-types/shared'; import {centerBaseline} from './CenterBaseline'; -import {ContextValue, DEFAULT_SLOT, Provider, TextContext as RACTextContext, SlotProps, ToggleButton, ToggleButtonGroup, ToggleGroupStateContext} from 'react-aria-components'; +import {ContextValue, DEFAULT_SLOT, Provider, TextContext as RACTextContext, SlotProps, ToggleButton, ToggleButtonGroup, ToggleButtonRenderProps, ToggleGroupStateContext} from 'react-aria-components'; import {createContext, forwardRef, ReactNode, RefObject, useCallback, useContext, useRef} from 'react'; import {focusRing, space, style} from '../style' with {type: 'macro'}; import {getAllowedOverrides, StyleProps} from './style-utils' with {type: 'macro'}; @@ -62,7 +62,7 @@ const segmentedControl = style({ width: 'fit' }, getAllowedOverrides()); -const controlItem = style({ +const controlItem = style({ ...focusRing(), position: 'relative', display: 'flex', @@ -107,7 +107,7 @@ const controlItem = style({ } }, getAllowedOverrides()); -const slider = style({ +const slider = style<{isDisabled: boolean}>({ backgroundColor: { default: 'gray-25', forcedColors: { diff --git a/packages/@react-spectrum/s2/src/Slider.tsx b/packages/@react-spectrum/s2/src/Slider.tsx index c921b43bc6a..3b5c52062c9 100644 --- a/packages/@react-spectrum/s2/src/Slider.tsx +++ b/packages/@react-spectrum/s2/src/Slider.tsx @@ -16,6 +16,7 @@ import { ContextValue, SliderOutput, SliderThumb, + SliderThumbRenderProps, SliderTrack } from 'react-aria-components'; import {clamp} from '@react-aria/utils'; @@ -199,7 +200,7 @@ export let thumbHitArea = style({ } }); -export let thumb = style({ +export let thumb = style({ ...focusRing(), display: 'inline-block', boxSizing: 'border-box', @@ -271,7 +272,7 @@ const trackStyling = { } } as const; -export let upperTrack = style({ +export let upperTrack = style<{isDisabled?: boolean, trackStyle: 'thin' | 'thick'}>({ ...trackStyling, position: 'absolute', backgroundColor: { @@ -292,7 +293,7 @@ export let upperTrack = style({ } }); -export let filledTrack = style({ +export let filledTrack = style<{isDisabled?: boolean, isEmphasized?: boolean, trackStyle: 'thin' | 'thick'}>({ ...trackStyling, position: 'absolute', backgroundColor: { diff --git a/packages/@react-spectrum/s2/src/TableView.tsx b/packages/@react-spectrum/s2/src/TableView.tsx index 16db0821306..5ed61e71fad 100644 --- a/packages/@react-spectrum/s2/src/TableView.tsx +++ b/packages/@react-spectrum/s2/src/TableView.tsx @@ -642,14 +642,13 @@ const resizerHandleContainer = style({ } }); -const resizerHandle = style({ +const resizerHandle = style<{isFocusVisible: boolean, isResizing: boolean}>({ backgroundColor: { default: 'gray-300', isFocusVisible: lightDark('informative-900', 'informative-700'), // --spectrum-informative-background-color-default, can't use `informative` because that will use the focusVisible version isResizing: lightDark('informative-900', 'informative-700'), forcedColors: { default: 'Background', - isHovered: 'ButtonBorder', isFocusVisible: 'Highlight', isResizing: 'Highlight' } @@ -787,7 +786,7 @@ function ResizableColumnContents(props: ResizableColumnContentProps) { resizerHandleContainer({resizableDirection, isResizing, isInResizeMode})}> {({isFocusVisible, isResizing}) => ( <> - + {(isFocusVisible || isInResizeMode) && isResizing &&
} )} @@ -797,9 +796,9 @@ function ResizableColumnContents(props: ResizableColumnContentProps) { ); } -function ResizerIndicator({isFocusVisible, isResizing, isInResizeMode}) { +function ResizerIndicator({isFocusVisible, isResizing}) { return ( -
+
); } diff --git a/packages/@react-spectrum/s2/src/Tabs.tsx b/packages/@react-spectrum/s2/src/Tabs.tsx index cdfd3d28f07..6448bf38ca0 100644 --- a/packages/@react-spectrum/s2/src/Tabs.tsx +++ b/packages/@react-spectrum/s2/src/Tabs.tsx @@ -22,7 +22,8 @@ import { Tab as RACTab, TabList as RACTabList, Tabs as RACTabs, - TabListStateContext + TabListStateContext, + TabRenderProps } from 'react-aria-components'; import {centerBaseline} from './CenterBaseline'; import {Collection, DOMRef, DOMRefValue, Key, Node, Orientation, RefObject} from '@react-types/shared'; @@ -233,7 +234,7 @@ interface TabLineProps { density?: 'compact' | 'regular' } -const selectedIndicator = style({ +const selectedIndicator = style<{isDisabled: boolean, orientation?: Orientation}>({ position: 'absolute', backgroundColor: { default: 'neutral', @@ -320,7 +321,7 @@ function TabLine(props: TabLineProps) { ); } -const tab = style({ +const tab = style({ ...focusRing(), display: 'flex', color: { @@ -520,7 +521,12 @@ let HiddenTabs = function (props: { let TabsMenu = (props: {valueId: string, items: Array>, onSelectionChange: TabsProps['onSelectionChange']} & Omit) => { let {id, items, 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy, valueId} = props; - let {density, onSelectionChange, selectedKey, isDisabled, disabledKeys, labelBehavior} = useContext(InternalTabsContext); + let {density, onSelectionChange: _onSelectionChange, selectedKey, isDisabled, disabledKeys, labelBehavior} = useContext(InternalTabsContext); + let onSelectionChange = useCallback((key: Key | null) => { + if (key != null) { + _onSelectionChange?.(key); + } + }, [_onSelectionChange]); let state = useContext(TabListStateContext); let allKeysDisabled = useMemo(() => { return isAllTabsDisabled(state?.collection, disabledKeys ? new Set(disabledKeys) : new Set()); diff --git a/packages/@react-spectrum/s2/src/TabsPicker.tsx b/packages/@react-spectrum/s2/src/TabsPicker.tsx index f93f6ed92d7..4e558ff28e3 100644 --- a/packages/@react-spectrum/s2/src/TabsPicker.tsx +++ b/packages/@react-spectrum/s2/src/TabsPicker.tsx @@ -281,7 +281,7 @@ let _Picker = /*#__PURE__*/ (forwardRef as forwardRefType)(Picker); export {_Picker as Picker}; -const selectedIndicator = style({ +const selectedIndicator = style<{isDisabled?: boolean}>({ backgroundColor: { default: 'neutral', isDisabled: 'disabled', @@ -297,7 +297,7 @@ const selectedIndicator = style({ transitionDuration: 130, transitionTimingFunction: 'in-out' }); -function TabLine(props) { +function TabLine(props: {isDisabled?: boolean}) { return
; } diff --git a/packages/@react-spectrum/s2/src/TagGroup.tsx b/packages/@react-spectrum/s2/src/TagGroup.tsx index 93fe47d3e94..b2aa19e19be 100644 --- a/packages/@react-spectrum/s2/src/TagGroup.tsx +++ b/packages/@react-spectrum/s2/src/TagGroup.tsx @@ -23,6 +23,7 @@ import { TextContext as RACTextContext, TagList, TagListProps, + TagRenderProps, useLocale, useSlottedContext } from 'react-aria-components'; @@ -437,7 +438,7 @@ function ActionGroup(props) { ); } -const tagStyles = style({ +const tagStyles = style({ ...focusRing(), display: 'inline-flex', boxSizing: 'border-box', diff --git a/packages/@react-spectrum/s2/style/spectrum-theme.ts b/packages/@react-spectrum/s2/style/spectrum-theme.ts index 38ff6ce7b1a..c045b5c976d 100644 --- a/packages/@react-spectrum/s2/style/spectrum-theme.ts +++ b/packages/@react-spectrum/s2/style/spectrum-theme.ts @@ -967,7 +967,8 @@ export const style = createTheme({ // eslint-disable-next-line @typescript-eslint/no-unused-vars disableTapHighlight: createArbitraryProperty((_value: true) => ({ '-webkit-tap-highlight-color': 'rgba(0,0,0,0)' - })) + })), + unicodeBidi: ['normal', 'embed', 'bidi-override', 'isolate', 'isolate-override', 'plaintext'] as const }, shorthands: { padding: ['paddingTop', 'paddingBottom', 'paddingStart', 'paddingEnd'] as const, diff --git a/packages/@react-spectrum/steplist/stories/StepList.stories.tsx b/packages/@react-spectrum/steplist/stories/StepList.stories.tsx index a3c2a55ae19..e18c57d3e08 100644 --- a/packages/@react-spectrum/steplist/stories/StepList.stories.tsx +++ b/packages/@react-spectrum/steplist/stories/StepList.stories.tsx @@ -219,8 +219,8 @@ export const ControlledStory: StepListStory = { }; function Controlled(args) { - const [lastCompletedStep, setLastCompletedStep] = useState(args.lastCompletedStep); - const [selectedKey, setSelectedKey] = useState(args.selectedKey); + const [lastCompletedStep, setLastCompletedStep] = useState(args.lastCompletedStep); + const [selectedKey, setSelectedKey] = useState(args.selectedKey); return ( diff --git a/packages/@react-spectrum/tabs/src/Tabs.tsx b/packages/@react-spectrum/tabs/src/Tabs.tsx index 2b8263f1dfb..b7731a8b22d 100644 --- a/packages/@react-spectrum/tabs/src/Tabs.tsx +++ b/packages/@react-spectrum/tabs/src/Tabs.tsx @@ -377,12 +377,13 @@ function TabPanel(props: TabPanelProps) { ); } -interface TabPickerProps extends Omit, 'children'> { +interface TabPickerProps extends Omit, 'children' | 'onSelectionChange'> { density?: 'compact' | 'regular', isEmphasized?: boolean, state: TabListState, className?: string, - visible: boolean + visible: boolean, + onSelectionChange?: (key: Key) => void } function TabPicker(props: TabPickerProps) { @@ -450,7 +451,11 @@ function TabPicker(props: TabPickerProps) { isDisabled={!visible || isDisabled} selectedKey={state.selectedKey} disabledKeys={state.disabledKeys} - onSelectionChange={state.setSelectedKey} + onSelectionChange={key => { + if (key != null) { + state.setSelectedKey(key); + } + }} UNSAFE_className={classNames(styles, 'spectrum-Tabs-picker')}> {item => {item.rendered}} diff --git a/packages/@react-spectrum/tabs/stories/Tabs.stories.tsx b/packages/@react-spectrum/tabs/stories/Tabs.stories.tsx index 66b2c374313..ebc359adeea 100644 --- a/packages/@react-spectrum/tabs/stories/Tabs.stories.tsx +++ b/packages/@react-spectrum/tabs/stories/Tabs.stories.tsx @@ -20,7 +20,7 @@ import Dashboard from '@spectrum-icons/workflow/Dashboard'; import {Item, TabList, TabPanels, Tabs} from '..'; import {Key} from '@react-types/shared'; import {Picker} from '@react-spectrum/picker'; -import React, {ReactNode, useState} from 'react'; +import React, {ReactNode, useCallback, useState} from 'react'; import {RouterProvider} from '@react-aria/utils'; import {SpectrumTabsProps} from '@react-types/tabs'; import {TextField} from '@react-spectrum/textfield'; @@ -907,7 +907,12 @@ let DynamicTabsWithDecoration = (props = {}) => { }; let ControlledSelection = () => { - let [selectedKey, setSelectedKey] = useState('Tab 1'); + let [selectedKey, _setSelectedKey] = useState('Tab 1'); + let setSelectedKey = useCallback((key: Key | null) => { + if (key != null) { + _setSelectedKey(key); + } + }, [_setSelectedKey]); return (
diff --git a/packages/@react-stately/tabs/src/useTabListState.ts b/packages/@react-stately/tabs/src/useTabListState.ts index c9bc6c3c23d..116e39b059f 100644 --- a/packages/@react-stately/tabs/src/useTabListState.ts +++ b/packages/@react-stately/tabs/src/useTabListState.ts @@ -29,6 +29,11 @@ export interface TabListState extends SingleSelectListState { export function useTabListState(props: TabListStateOptions): TabListState { let state = useSingleSelectListState({ ...props, + onSelectionChange: props.onSelectionChange ? (key => { + if (key != null) { + props.onSelectionChange?.(key); + } + }) : undefined, suppressTextValueWarning: true, defaultSelectedKey: props.defaultSelectedKey ?? findDefaultSelectedKey(props.collection, props.disabledKeys ? new Set(props.disabledKeys) : new Set()) ?? undefined }); diff --git a/packages/@react-types/tabs/src/index.d.ts b/packages/@react-types/tabs/src/index.d.ts index ebd96c99934..e760d2596a1 100644 --- a/packages/@react-types/tabs/src/index.d.ts +++ b/packages/@react-types/tabs/src/index.d.ts @@ -30,12 +30,14 @@ export interface AriaTabProps extends AriaLabelingProps { shouldSelectOnPressUp?: boolean } -export interface TabListProps extends CollectionBase, Omit { +export interface TabListProps extends CollectionBase, Omit { /** * Whether the TabList is disabled. * Shows that a selection exists, but is not available in that circumstance. */ - isDisabled?: boolean + isDisabled?: boolean, + /** Handler that is called when the selection changes. */ + onSelectionChange?: (key: Key) => void } interface AriaTabListBase extends AriaLabelingProps { @@ -55,7 +57,7 @@ export interface AriaTabListProps extends TabListProps, AriaTabListBase, D export interface AriaTabPanelProps extends DOMProps, AriaLabelingProps {} -export interface SpectrumTabsProps extends AriaTabListBase, SingleSelection, DOMProps, StyleProps { +export interface SpectrumTabsProps extends AriaTabListBase, Omit, DOMProps, StyleProps { /** The children of the `` element. Should include `` and `` elements. */ children: ReactNode, /** The item objects for each tab, for dynamic collections. */ @@ -69,7 +71,9 @@ export interface SpectrumTabsProps extends AriaTabListBase, SingleSelection, /** Whether the tabs are displayed in an emphasized style. */ isEmphasized?: boolean, /** The amount of space between the tabs. */ - density?: 'compact' | 'regular' + density?: 'compact' | 'regular', + /** Handler that is called when the selection changes. */ + onSelectionChange?: (key: Key) => void } export interface SpectrumTabListProps extends DOMProps, StyleProps { diff --git a/packages/dev/codemods/package.json b/packages/dev/codemods/package.json index bd0bc1c0295..158eb643860 100644 --- a/packages/dev/codemods/package.json +++ b/packages/dev/codemods/package.json @@ -26,7 +26,7 @@ "@babel/types": "^7.24.5", "@react-spectrum/s2": "^0.7.0", "@react-types/shared": "^3.28.0", - "@types/node": "^20", + "@types/node": "patch:@types/node@npm%3A20.14.13#~/.yarn/patches/@types-node-npm-20.14.13-41f92d384c.patch", "boxen": "^5.1.2", "build": "^0.1.4", "chalk": "^4.0.0", diff --git a/packages/dev/docs/pages/react-aria/home/A11y.tsx b/packages/dev/docs/pages/react-aria/home/A11y.tsx index 73a14913dd5..d9e9820dfbe 100644 --- a/packages/dev/docs/pages/react-aria/home/A11y.tsx +++ b/packages/dev/docs/pages/react-aria/home/A11y.tsx @@ -66,7 +66,7 @@ export function A11y() { let [fingerPos, setFingerPos] = useState(null); let [isOpen, setOpen] = useState(false); let [caption, setCaption] = useState(''); - let [selectedKey, setSelectedKey] = useState('read'); + let [selectedKey, setSelectedKey] = useState('read'); useIntersectionObserver(ref, useCallback(() => { let button: HTMLButtonElement | null = null; let listbox: HTMLElement | null = null; diff --git a/packages/react-aria-components/docs/Checkbox.mdx b/packages/react-aria-components/docs/Checkbox.mdx index 6fe342d7d97..0df45705d92 100644 --- a/packages/react-aria-components/docs/Checkbox.mdx +++ b/packages/react-aria-components/docs/Checkbox.mdx @@ -167,7 +167,7 @@ This example wraps `Checkbox` and all of its children together into a single com ```tsx example export=true import type {CheckboxProps} from 'react-aria-components'; -export function MyCheckbox({children, ...props}: CheckboxProps) { +export function MyCheckbox({children, ...props}: Omit & {children?: React.ReactNode}) { return ( {({isIndeterminate}) => <> diff --git a/packages/react-aria-components/docs/GridList.mdx b/packages/react-aria-components/docs/GridList.mdx index 7d5483a0cb5..b00bc9796c8 100644 --- a/packages/react-aria-components/docs/GridList.mdx +++ b/packages/react-aria-components/docs/GridList.mdx @@ -318,7 +318,7 @@ export function MyGridList({children, ...props}: GridListProps ); } -export function MyItem({children, ...props}: GridListItemProps) { +export function MyItem({children, ...props}: Omit & {children?: React.ReactNode}) { let textValue = typeof children === 'string' ? children : undefined; return ( diff --git a/packages/react-aria-components/docs/Menu.mdx b/packages/react-aria-components/docs/Menu.mdx index 2001d15b9fc..1589abefabd 100644 --- a/packages/react-aria-components/docs/Menu.mdx +++ b/packages/react-aria-components/docs/Menu.mdx @@ -227,7 +227,7 @@ function MyMenuButton({label, children, ...props}: MyMenuButto ); } -export function MyItem(props: MenuItemProps) { +export function MyItem(props: Omit & {children?: React.ReactNode}) { let textValue = props.textValue || (typeof props.children === 'string' ? props.children : undefined); return ( & {children?: React.ReactNode}) { return ( {({allowsSorting, sortDirection}) => <> diff --git a/packages/react-aria-components/docs/TagGroup.mdx b/packages/react-aria-components/docs/TagGroup.mdx index 0868156df51..79d8e5765cb 100644 --- a/packages/react-aria-components/docs/TagGroup.mdx +++ b/packages/react-aria-components/docs/TagGroup.mdx @@ -228,7 +228,7 @@ function MyTagGroup({label, description, errorMessage, items, ); } -function MyTag({children, ...props}: TagProps) { +function MyTag({children, ...props}: Omit & {children?: React.ReactNode}) { let textValue = typeof children === 'string' ? children : undefined; return ( diff --git a/packages/react-aria-components/docs/Tree.mdx b/packages/react-aria-components/docs/Tree.mdx index 7b7c51b4251..8bbcad5db69 100644 --- a/packages/react-aria-components/docs/Tree.mdx +++ b/packages/react-aria-components/docs/Tree.mdx @@ -350,7 +350,7 @@ If you will use a Tree in multiple places in your app, you can wrap all of the p import type {TreeItemContentProps, TreeItemContentRenderProps} from 'react-aria-components'; import {Button} from 'react-aria-components'; -function MyTreeItemContent(props: TreeItemContentProps) { +function MyTreeItemContent(props: Omit & {children?: React.ReactNode}) { return ( {({hasChildItems, selectionBehavior, selectionMode}: TreeItemContentRenderProps) => ( diff --git a/scripts/extractExamples.mjs b/scripts/extractExamples.mjs index 1757dc4d6cb..137b3d6f174 100644 --- a/scripts/extractExamples.mjs +++ b/scripts/extractExamples.mjs @@ -108,7 +108,6 @@ import ReactDOM from 'react-dom/client'; fs.copyFileSync('lib/svg.d.ts', `${distDir}/svg.d.ts`); fs.copyFileSync('lib/css.d.ts', `${distDir}/css.d.ts`); -fs.copyFileSync('lib/viewTransitions.d.ts', `${distDir}/viewTransitions.d.ts`); fs.writeFileSync(`${distDir}/tsconfig.json`, `{ "compilerOptions": { "target": "es2018", diff --git a/tsconfig.json b/tsconfig.json index b05da2d90c7..d7d52a600cf 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -46,7 +46,6 @@ "include": [ "packages", "lib/svg.d.ts", - "lib/viewTransitions.d.ts", "lib/css.d.ts" ], "exclude": [ diff --git a/yarn.lock b/yarn.lock index 9a164279dc4..c02d0abe522 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7140,7 +7140,7 @@ __metadata: "@react-spectrum/s2": "npm:^0.7.0" "@react-types/shared": "npm:^3.28.0" "@types/jscodeshift": "npm:^0.11.11" - "@types/node": "npm:^20" + "@types/node": "patch:@types/node@npm%3A20.14.13#~/.yarn/patches/@types-node-npm-20.14.13-41f92d384c.patch" boxen: "npm:^5.1.2" build: "npm:^0.1.4" chalk: "npm:^4.0.0" @@ -11370,7 +11370,7 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:*, @types/node@npm:>= 8, @types/node@npm:^20": +"@types/node@npm:20.14.13": version: 20.14.13 resolution: "@types/node@npm:20.14.13" dependencies: @@ -11379,12 +11379,12 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:^18.0.0": - version: 18.19.31 - resolution: "@types/node@npm:18.19.31" +"@types/node@patch:@types/node@npm%3A20.14.13#~/.yarn/patches/@types-node-npm-20.14.13-41f92d384c.patch": + version: 20.14.13 + resolution: "@types/node@patch:@types/node@npm%3A20.14.13#~/.yarn/patches/@types-node-npm-20.14.13-41f92d384c.patch::version=20.14.13&hash=24fda2" dependencies: undici-types: "npm:~5.26.4" - checksum: 10c0/bfebae8389220c0188492c82eaf328f4ba15e6e9b4abee33d6bf36d3b13f188c2f53eb695d427feb882fff09834f467405e2ed9be6aeb6ad4705509822d2ea08 + checksum: 10c0/1bbbadf2732c27a8f1bc7b20be41bf7faa50436461c1af6e67398c2003a8bde9893e04f762d55b231ef818d4567ec6bcb6bcdf28748f73a715a11dd7df88e9f5 languageName: node linkType: hard