Skip to content

Commit 1c16a2d

Browse files
committed
Merge remote-tracking branch 'origin/main' into useDrag-custom-offset
2 parents b2657eb + 8891825 commit 1c16a2d

File tree

28 files changed

+761
-124
lines changed

28 files changed

+761
-124
lines changed

package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -129,8 +129,8 @@
129129
"@testing-library/jest-dom": "^5.16.5",
130130
"@testing-library/react": "^16.0.0",
131131
"@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",
132-
"@types/react": "npm:types-react@19.0.0-rc.0",
133-
"@types/react-dom": "npm:types-react-dom@19.0.0-rc.0",
132+
"@types/react": "^19.0.0",
133+
"@types/react-dom": "^19.0.0",
134134
"@yarnpkg/types": "^4.0.0",
135135
"autoprefixer": "^9.6.0",
136136
"axe-core": "^4.6.3",
@@ -231,8 +231,8 @@
231231
"react-refresh": "0.9.0",
232232
"browserslist": "4.24.0",
233233
"caniuse-lite": "1.0.30001563",
234-
"@types/react": "npm:types-react@19.0.0-rc.0",
235-
"@types/react-dom": "npm:types-react-dom@19.0.0-rc.0",
234+
"@types/react": "19.1.8",
235+
"@types/react-dom": "19.1.6",
236236
"recast": "0.23.6",
237237
"ast-types": "0.16.1",
238238
"svgo": "^3",

packages/@react-aria/datepicker/src/useDateSegment.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,8 @@ export function useDateSegment(segment: DateSegment, state: DateFieldState, ref:
256256
if (shouldSetValue) {
257257
focusManager.focusNext();
258258
}
259-
} else {
259+
} else if (shouldSetValue) {
260+
// Don't accept leading zeros except for fields that accept 0 as a entire value (aka 00 for minutes/seconds/etc)
260261
enteredKeys.current = newValue;
261262
}
262263
break;
@@ -325,7 +326,6 @@ export function useDateSegment(segment: DateSegment, state: DateFieldState, ref:
325326
if (ref.current) {
326327
ref.current.textContent = compositionRef.current;
327328
}
328-
329329
// Android sometimes fires key presses of letters as composition events. Need to handle am/pm keys here too.
330330
// Can also happen e.g. with Pinyin keyboard on iOS.
331331
if (data != null && (startsWith(am, data) || startsWith(pm, data))) {
@@ -387,9 +387,9 @@ export function useDateSegment(segment: DateSegment, state: DateFieldState, ref:
387387

388388
let segmentStyle: CSSProperties = {caretColor: 'transparent'};
389389
if (direction === 'rtl') {
390-
// While the bidirectional algorithm seems to work properly on inline elements with actual values, it returns different results for placeholder strings.
390+
// While the bidirectional algorithm seems to work properly on inline elements with actual values, it returns different results for placeholder strings.
391391
// To ensure placeholder render in correct format, we apply the CSS equivalent of LRE (left-to-right embedding). See https://www.unicode.org/reports/tr9/#Explicit_Directional_Embeddings.
392-
// However, we apply this to both placeholders and date segments with an actual value because the date segments will shift around when deleting otherwise.
392+
// However, we apply this to both placeholders and date segments with an actual value because the date segments will shift around when deleting otherwise.
393393
segmentStyle.unicodeBidi = 'embed';
394394
let format = options[segment.type];
395395
if (format === 'numeric' || format === '2-digit') {

packages/@react-aria/utils/src/platform.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,9 @@ function testUserAgent(re: RegExp) {
1414
if (typeof window === 'undefined' || window.navigator == null) {
1515
return false;
1616
}
17-
return (
18-
window.navigator['userAgentData']?.brands.some((brand: {brand: string, version: string}) => re.test(brand.brand))
19-
) ||
20-
re.test(window.navigator.userAgent);
17+
let brands = window.navigator['userAgentData']?.brands;
18+
return Array.isArray(brands) && brands.some((brand: {brand: string, version: string}) => re.test(brand.brand)) ||
19+
re.test(window.navigator.userAgent);
2120
}
2221

2322
function testPlatform(re: RegExp) {

packages/@react-spectrum/badge/src/Badge.tsx

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
* governing permissions and limitations under the License.
1111
*/
1212

13-
import {classNames, SlotProvider, useDOMRef, useStyleProps} from '@react-spectrum/utils';
13+
import {classNames, ClearSlots, SlotProvider, useDOMRef, useStyleProps} from '@react-spectrum/utils';
1414
import {DOMRef} from '@react-types/shared';
1515
import {filterDOMProps} from '@react-aria/utils';
1616
import React, {forwardRef} from 'react';
@@ -47,23 +47,25 @@ export const Badge = forwardRef(function Badge(props: SpectrumBadgeProps, ref: D
4747
styleProps.className
4848
)}
4949
ref={domRef}>
50-
<SlotProvider
51-
slots={{
52-
icon: {
53-
size: 'S',
54-
UNSAFE_className: classNames(styles, 'spectrum-Badge-icon')
55-
},
56-
text: {
57-
UNSAFE_className: classNames(styles, 'spectrum-Badge-label')
58-
}
59-
}}>
50+
<ClearSlots>
51+
<SlotProvider
52+
slots={{
53+
icon: {
54+
size: 'S',
55+
UNSAFE_className: classNames(styles, 'spectrum-Badge-icon')
56+
},
57+
text: {
58+
UNSAFE_className: classNames(styles, 'spectrum-Badge-label')
59+
}
60+
}}>
6061

61-
{
62-
typeof children === 'string' || isTextOnly
63-
? <Text>{children}</Text>
64-
: children
65-
}
66-
</SlotProvider>
62+
{
63+
typeof children === 'string' || isTextOnly
64+
? <Text>{children}</Text>
65+
: children
66+
}
67+
</SlotProvider>
68+
</ClearSlots>
6769
</span>
6870
);
6971
});

packages/@react-spectrum/datepicker/test/DateField.test.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,11 @@ describe('DateField', function () {
235235
errorMessage="Date unavailable." />
236236
);
237237
await user.tab();
238-
await user.keyboard('01011980');
238+
await user.keyboard('1');
239+
await user.keyboard('[ArrowRight]');
240+
await user.keyboard('1');
241+
await user.keyboard('[ArrowRight]');
242+
await user.keyboard('1980');
239243
expect(tree.getByText('Date unavailable.')).toBeInTheDocument();
240244
});
241245

@@ -245,7 +249,7 @@ describe('DateField', function () {
245249
<DateField label="Date" showFormatHelpText />
246250
</Provider>
247251
);
248-
252+
249253
let segments = Array.from(getByRole('group').querySelectorAll('[data-testid]'));
250254
let segmentTypes = segments.map(s => s.getAttribute('data-testid'));
251255
expect(segmentTypes).toEqual(['year', 'month', 'day']);

packages/@react-spectrum/datepicker/test/DatePicker.test.js

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1426,7 +1426,8 @@ describe('DatePicker', function () {
14261426

14271427
it('should support typing into the month segment', function () {
14281428
testInput('month,', new CalendarDate(2019, 2, 3), '1', new CalendarDate(2019, 1, 3), false);
1429-
testInput('month,', new CalendarDate(2019, 2, 3), '01', new CalendarDate(2019, 1, 3), true);
1429+
testInput('month,', new CalendarDate(2019, 2, 3), '01', new CalendarDate(2019, 1, 3), false);
1430+
testInput('month,', new CalendarDate(2019, 2, 3), '012', new CalendarDate(2019, 12, 3), true);
14301431
testInput('month,', new CalendarDate(2019, 2, 3), '12', new CalendarDate(2019, 12, 3), true);
14311432
testInput('month,', new CalendarDate(2019, 2, 3), '4', new CalendarDate(2019, 4, 3), true);
14321433
testIgnored('month,', new CalendarDate(2019, 2, 3), '0');
@@ -1435,7 +1436,8 @@ describe('DatePicker', function () {
14351436

14361437
it('should support typing into the day segment', function () {
14371438
testInput('day,', new CalendarDate(2019, 2, 3), '1', new CalendarDate(2019, 2, 1), false);
1438-
testInput('day,', new CalendarDate(2019, 2, 3), '01', new CalendarDate(2019, 2, 1), true);
1439+
testInput('day,', new CalendarDate(2019, 2, 3), '01', new CalendarDate(2019, 2, 1), false);
1440+
testInput('day,', new CalendarDate(2019, 2, 3), '012', new CalendarDate(2019, 2, 12), true);
14391441
testInput('day,', new CalendarDate(2019, 2, 3), '12', new CalendarDate(2019, 2, 12), true);
14401442
testInput('day,', new CalendarDate(2019, 2, 3), '4', new CalendarDate(2019, 2, 4), true);
14411443
testIgnored('day,', new CalendarDate(2019, 2, 3), '0');
@@ -1444,22 +1446,28 @@ describe('DatePicker', function () {
14441446

14451447
it('should support typing into the year segment', function () {
14461448
testInput('year,', new CalendarDate(2019, 2, 3), '1993', new CalendarDate(1993, 2, 3), false);
1449+
testInput('year,', new CalendarDate(2019, 2, 3), '0199', new CalendarDate(199, 2, 3), false);
1450+
testInput('year,', new CalendarDate(2019, 2, 3), '01993', new CalendarDate(1993, 2, 3), false);
1451+
testInput('year,', new CalendarDateTime(2019, 2, 3, 8), '0199', new CalendarDateTime(199, 2, 3, 8), false);
14471452
testInput('year,', new CalendarDateTime(2019, 2, 3, 8), '1993', new CalendarDateTime(1993, 2, 3, 8), true);
1453+
testInput('year,', new CalendarDateTime(2019, 2, 3, 8), '01993', new CalendarDateTime(1993, 2, 3, 8), true);
14481454
testIgnored('year,', new CalendarDate(2019, 2, 3), '0');
14491455
});
14501456

14511457
it('should support typing into the hour segment in 12 hour time', function () {
14521458
// AM
14531459
testInput('hour,', new CalendarDateTime(2019, 2, 3, 8), '1', new CalendarDateTime(2019, 2, 3, 1), false);
1454-
testInput('hour,', new CalendarDateTime(2019, 2, 3, 8), '01', new CalendarDateTime(2019, 2, 3, 1), true);
1460+
testInput('hour,', new CalendarDateTime(2019, 2, 3, 8), '01', new CalendarDateTime(2019, 2, 3, 1), false);
1461+
testInput('hour,', new CalendarDateTime(2019, 2, 3, 8), '011', new CalendarDateTime(2019, 2, 3, 11), true);
14551462
testInput('hour,', new CalendarDateTime(2019, 2, 3, 8), '11', new CalendarDateTime(2019, 2, 3, 11), true);
14561463
testInput('hour,', new CalendarDateTime(2019, 2, 3, 8), '12', new CalendarDateTime(2019, 2, 3, 0), true);
14571464
testInput('hour,', new CalendarDateTime(2019, 2, 3, 8), '4', new CalendarDateTime(2019, 2, 3, 4), true);
14581465
testIgnored('hour,', new CalendarDateTime(2019, 2, 3, 8), '0');
14591466

14601467
// PM
14611468
testInput('hour,', new CalendarDateTime(2019, 2, 3, 20), '1', new CalendarDateTime(2019, 2, 3, 13), false);
1462-
testInput('hour,', new CalendarDateTime(2019, 2, 3, 20), '01', new CalendarDateTime(2019, 2, 3, 13), true);
1469+
testInput('hour,', new CalendarDateTime(2019, 2, 3, 20), '01', new CalendarDateTime(2019, 2, 3, 13), false);
1470+
testInput('hour,', new CalendarDateTime(2019, 2, 3, 20), '011', new CalendarDateTime(2019, 2, 3, 23), true);
14631471
testInput('hour,', new CalendarDateTime(2019, 2, 3, 20), '11', new CalendarDateTime(2019, 2, 3, 23), true);
14641472
testInput('hour,', new CalendarDateTime(2019, 2, 3, 20), '12', new CalendarDateTime(2019, 2, 3, 12), true);
14651473
testInput('hour,', new CalendarDateTime(2019, 2, 3, 20), '4', new CalendarDateTime(2019, 2, 3, 16), true);

packages/@react-spectrum/list/stories/ListView.stories.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import {action} from '@storybook/addon-actions';
22
import {ActionBar, ActionBarContainer} from '@react-spectrum/actionbar';
33
import {ActionButton, Button} from '@react-spectrum/button';
44
import {ActionGroup} from '@react-spectrum/actiongroup';
5+
import {Badge} from '@react-spectrum/badge';
56
import {Content} from '@react-spectrum/view';
67
import Copy from '@spectrum-icons/workflow/Copy';
78
import Delete from '@spectrum-icons/workflow/Delete';
@@ -144,7 +145,7 @@ export type ListViewStory = StoryObj<typeof ListView>;
144145
export const Default: ListViewStory = {
145146
render: (args) => (
146147
<ListView disabledKeys={['3']} width="250px" aria-label="default ListView" {...args}>
147-
<Item key="1" textValue="Adobe Photoshop">Adobe Photoshop</Item>
148+
<Item key="1" textValue="Adobe Photoshop"><Badge variant="neutral">2</Badge>Adobe Photoshop</Item>
148149
<Item key="2" textValue="Adobe Illustrator">Adobe Illustrator</Item>
149150
<Item key="3" textValue="Adobe XD">Adobe XD</Item>
150151
</ListView>

packages/@react-spectrum/s2/chromatic/Tabs.stories.tsx

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import type {Meta} from '@storybook/react';
1717
import {style} from '../style/spectrum-theme' with { type: 'macro' };
1818
import {Tab, TabList, TabPanel, Tabs} from '../src/Tabs';
1919
import {Text} from '@react-spectrum/s2';
20+
import {userEvent} from '@storybook/test';
2021

2122
const meta: Meta<typeof Tabs> = {
2223
component: Tabs,
@@ -97,3 +98,28 @@ export const Icons = {
9798
</Tabs>
9899
)
99100
};
101+
102+
export const Collasped = {
103+
render: (args: any) => (
104+
<Tabs {...args} aria-label="Settings" styles={style({width: 200, height: 144})}>
105+
<TabList>
106+
<Tab id="Mouse">Mouse settings</Tab>
107+
<Tab id="Keyboard">Keyboard settings</Tab>
108+
<Tab id="Gamepad">Gamepad settings</Tab>
109+
</TabList>
110+
<TabPanel id="Mouse">
111+
Adjust the sensitivity and speed of your mouse
112+
</TabPanel>
113+
<TabPanel id="Keyboard">
114+
Customize the layout and function of your keyboard.
115+
</TabPanel>
116+
<TabPanel id="Gamepad">
117+
Configure the buttons and triggers on your gamepad.
118+
</TabPanel>
119+
</Tabs>
120+
),
121+
play: async () => {
122+
await userEvent.tab();
123+
await userEvent.keyboard('{Enter}');
124+
}
125+
};

packages/@react-spectrum/s2/src/ActionButton.tsx

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ export const btnStyles = style<ButtonRenderProps & ActionButtonStyleProps & Togg
6767
...focusRing(),
6868
...staticColor(),
6969
...controlStyle,
70+
display: 'grid',
7071
justifyContent: 'center',
7172
flexShrink: {
7273
default: 1,
@@ -79,9 +80,21 @@ export const btnStyles = style<ButtonRenderProps & ActionButtonStyleProps & Togg
7980
isJustified: 0
8081
},
8182
fontWeight: 'medium',
83+
width: 'fit',
8284
userSelect: 'none',
8385
transition: 'default',
8486
forcedColorAdjust: 'none',
87+
position: 'relative',
88+
gridTemplateAreas: {
89+
default: ['icon text'],
90+
[iconOnly]: ['icon'],
91+
[textOnly]: ['text']
92+
},
93+
gridTemplateColumns: {
94+
default: ['auto', 'auto'],
95+
[iconOnly]: ['auto'],
96+
[textOnly]: ['auto']
97+
},
8598
backgroundColor: {
8699
default: {
87100
...baseColor('gray-100'),
@@ -223,8 +236,7 @@ export const btnStyles = style<ButtonRenderProps & ActionButtonStyleProps & Togg
223236
'--badgePosition': {
224237
type: 'width',
225238
value: {
226-
default: 'calc(self(paddingStart) + var(--iconWidth))',
227-
[iconOnly]: 'calc(self(minWidth)/2 + var(--iconWidth)/2)',
239+
default: '--iconWidth',
228240
[textOnly]: 'full'
229241
}
230242
},
@@ -289,10 +301,10 @@ export const ActionButton = forwardRef(function ActionButton(props: ActionButton
289301
<Provider
290302
values={[
291303
[SkeletonContext, null],
292-
[TextContext, {styles: style({order: 1, truncate: true})}],
304+
[TextContext, {styles: style({truncate: true, gridArea: 'text'})}],
293305
[IconContext, {
294-
render: centerBaseline({slot: 'icon', styles: style({order: 0})}),
295-
styles: style({size: fontRelative(20), marginStart: '--iconMargin', flexShrink: 0})
306+
render: centerBaseline({slot: 'icon', styles: style({gridArea: 'icon'})}),
307+
styles: style({size: fontRelative(20), marginStart: '--iconMargin'})
296308
}],
297309
[AvatarContext, {
298310
size: avatarSize[size],
@@ -301,15 +313,14 @@ export const ActionButton = forwardRef(function ActionButton(props: ActionButton
301313
default: '--iconMargin',
302314
':last-child': 0
303315
},
304-
flexShrink: 0,
305-
order: 0
316+
gridArea: 'icon'
306317
})
307318
}],
308319
[NotificationBadgeContext, {
309320
staticColor: staticColor,
310321
size: props.size === 'XS' ? undefined : props.size,
311322
isDisabled: props.isDisabled,
312-
styles: style({position: 'absolute', top: '--badgeTop', insetStart: '--badgePosition', marginTop: 'calc((self(height) * -1)/2)', marginStart: 'calc((self(height) * -1)/2)'})
323+
styles: style({position: 'absolute', top: '--badgeTop', marginTop: 'calc((self(height) * -1)/2)', marginStart: 'calc(var(--iconMargin) * 2 + (self(height) * -1)/4)', gridColumnStart: 1, insetStart: '--badgePosition'})
313324
}]
314325
]}>
315326
{typeof props.children === 'string' ? <Text>{props.children}</Text> : props.children}

packages/@react-spectrum/s2/src/Tabs.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -458,7 +458,8 @@ export function TabPanel(props: TabPanelProps): ReactNode | null {
458458
}
459459

460460
function CollapsedTabPanel(props: TabPanelProps) {
461-
let {UNSAFE_style, UNSAFE_className = '', ...otherProps} = props;
461+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
462+
let {UNSAFE_style, UNSAFE_className = '', id, ...otherProps} = props;
462463
let {menuId, valueId} = useContext(CollapseContext);
463464
let ref = useRef(null);
464465
let tabIndex = useHasTabbableChild(ref) ? undefined : 0;

0 commit comments

Comments
 (0)