Skip to content

Commit 51580d7

Browse files
committed
Merge branch 'main' of github.com:adobe/react-spectrum into loadmore_rac
2 parents 0ef52ef + d93947e commit 51580d7

File tree

275 files changed

+9284
-6725
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

275 files changed

+9284
-6725
lines changed

examples/rsp-cra-18/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
"react-aria-components": "latest",
2525
"react-dom": "^18.1.0",
2626
"react-scripts": "5.0.1",
27-
"typescript": "5.0.4",
27+
"typescript": "5.8.2",
2828
"web-vitals": "^2.1.4"
2929
},
3030
"scripts": {

lib/jestResolver.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ module.exports = (request, options) => {
3232
let files = glob.sync(request, {cwd: options.basedir});
3333
let source = '';
3434
for (let file of files) {
35-
source += `exports['${path.basename(file, '.json')}'] = require('${path.join(options.basedir, file)}');\n`;
35+
source += `exports['${path.basename(file, '.json')}'] = require('${path.join(options.basedir, file).replace(/\\/g, '\\\\')}');\n`;
3636
}
3737
let hash = crypto.createHash('md5');
3838
hash.update(source);
@@ -51,7 +51,7 @@ module.exports = (request, options) => {
5151
return pkg;
5252
}
5353
});
54-
if (/packages\/.*\/.*\/intl\/.*\.json$/.test(resolved)) {
54+
if (/packages[\/\\].*[\/\\].*[\/\\]intl[\/\\].*\.json$/.test(resolved)) {
5555
let sourceText = fs.readFileSync(resolved, 'utf8');
5656
let json = JSON.parse(sourceText);
5757
let res = compileStrings(json);

package.json

+16-17
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
"test:ssr": "cross-env STRICT_MODE=1 yarn jest --config jest.ssr.config.js",
3737
"ci-test": "cross-env STRICT_MODE=1 yarn jest --maxWorkers=2 && cross-env STRICT_MODE=1 yarn test:ssr --runInBand",
3838
"lint": "concurrently \"yarn check-types\" \"eslint packages\" \"node scripts/lint-packages.js\" \"yarn constraints\"",
39-
"jest": "node scripts/jest.js",
39+
"jest": "jest",
4040
"copyrights": "babel-node --presets @babel/env ./scripts/addHeaders.js",
4141
"build:icons": "babel-node --presets @babel/env ./scripts/buildIcons.js",
4242
"clean:icons": "babel-node --presets @babel/env ./scripts/cleanIcons.js",
@@ -87,19 +87,19 @@
8787
"@faker-js/faker": "^8.4.1",
8888
"@jdb8/eslint-plugin-monorepo": "^1.0.1",
8989
"@octokit/rest": "*",
90-
"@parcel/bundler-library": "^2.12.1",
91-
"@parcel/config-default": "^2.13.1",
92-
"@parcel/config-storybook": "^0.0.2",
93-
"@parcel/core": "^2.13.1",
94-
"@parcel/optimizer-data-url": "^2.13.1",
95-
"@parcel/optimizer-terser": "^2.13.1",
96-
"@parcel/packager-ts": "^2.13.1",
97-
"@parcel/reporter-cli": "^2.13.1",
98-
"@parcel/resolver-glob": "^2.13.1",
99-
"@parcel/transformer-inline": "^2.13.1",
100-
"@parcel/transformer-inline-string": "^2.13.1",
101-
"@parcel/transformer-svg-react": "^2.13.1",
102-
"@parcel/transformer-typescript-types": "^2.13.1",
90+
"@parcel/bundler-library": "^2.14.0",
91+
"@parcel/config-default": "^2.14.0",
92+
"@parcel/config-storybook": "0.0.2",
93+
"@parcel/core": "^2.14.0",
94+
"@parcel/optimizer-data-url": "^2.14.0",
95+
"@parcel/optimizer-terser": "^2.14.0",
96+
"@parcel/packager-ts": "^2.14.0",
97+
"@parcel/reporter-cli": "^2.14.0",
98+
"@parcel/resolver-glob": "^2.14.0",
99+
"@parcel/transformer-inline": "^2.14.0",
100+
"@parcel/transformer-inline-string": "^2.14.0",
101+
"@parcel/transformer-svg-react": "^2.14.0",
102+
"@parcel/transformer-typescript-types": "^2.14.0",
103103
"@react-spectrum/s2-icon-builder": "^0.2.0",
104104
"@spectrum-css/component-builder": "1.0.1",
105105
"@spectrum-css/vars": "^2.3.0",
@@ -125,7 +125,7 @@
125125
"@tailwindcss/postcss": "^4.0.0",
126126
"@testing-library/dom": "^10.1.0",
127127
"@testing-library/jest-dom": "^5.16.5",
128-
"@testing-library/react": "^15.0.7",
128+
"@testing-library/react": "^16.0.0",
129129
"@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",
130130
"@types/react": "npm:types-react@19.0.0-rc.0",
131131
"@types/react-dom": "npm:types-react-dom@19.0.0-rc.0",
@@ -161,7 +161,6 @@
161161
"fast-glob": "^3.1.0",
162162
"framer-motion": "^11.3.0-alpha.0",
163163
"fs-extra": "^10.0.0",
164-
"full-icu": "^1.3.0",
165164
"glob": "^8.0.3",
166165
"glob-promise": "^6.0.5",
167166
"globals": "^15.11.0",
@@ -179,7 +178,7 @@
179178
"npm-cli-login": "^1.0.0",
180179
"nyc": "^10.2.0",
181180
"p-queue": "^6.2.1",
182-
"parcel": "^2.13.1",
181+
"parcel": "^2.14.0",
183182
"parcel-optimizer-strict-mode": "workspace:^",
184183
"patch-package": "^6.2.0",
185184
"playwright": "^1.45.3",

packages/@internationalized/date/docs/Calendar.mdx

+66
Original file line numberDiff line numberDiff line change
@@ -226,3 +226,69 @@ function createCalendar(identifier) {
226226
## Interface
227227

228228
<ClassAPI links={docs.links} class={docs.exports.Calendar} />
229+
230+
## Custom calendars
231+
232+
You can create your own custom calendar system by implementing the `Calendar` interface shown above. This enables calendars that follow custom business rules. An example would be a fiscal year calendar that follows a [4-5-4 format](https://nrf.com/resources/4-5-4-calendar), where month ranges don't follow the usual Gregorian calendar.
233+
234+
To implement a calendar, either extend an existing implementation (e.g. `GregorianCalendar`) or implement the `Calendar` interface from scratch. The most important methods are `fromJulianDay` and `toJulianDay`, which convert between the calendar's year/month/day numbering system and a [Julian Day Number](https://en.wikipedia.org/wiki/Julian_day). This allows converting dates between calendar systems. Other methods such as `getDaysInMonth` and `getMonthsInYear` can be implemented to define how dates are organized in your calendar system.
235+
236+
The following code is an example of how you might implement a custom 4-5-4 calendar (though implementing a true 4-5-4 calendar would be more nuanced than this).
237+
238+
```tsx
239+
import type {AnyCalendarDate, Calendar} from '@internationalized/date';
240+
import {CalendarDate, GregorianCalendar, startOfWeek} from '@internationalized/date';
241+
242+
const weekPattern = [4, 5, 4, 4, 5, 4, 4, 5, 4, 4, 5, 4];
243+
244+
class Custom454 extends GregorianCalendar {
245+
// Months always have either 4 or 5 full weeks.
246+
getDaysInMonth(date) {
247+
return weekPattern[date.month - 1] * 7;
248+
}
249+
250+
// Enable conversion between calendar systems.
251+
fromJulianDay(jd: number): CalendarDate {
252+
let gregorian = super.fromJulianDay(jd);
253+
254+
// Start from the beginning of the first week of the gregorian year
255+
// and add weeks until we find the month.
256+
let monthStart = startOfWeek(new CalendarDate(gregorian.year, 1, 1), 'en');
257+
for (let months = 0; months < weekPattern.length; months++) {
258+
let weeksInMonth = weekPattern[months];
259+
let monthEnd = monthStart.add({weeks: weeksInMonth});
260+
if (monthEnd.compare(gregorian) > 0) {
261+
let days = gregorian.compare(monthStart);
262+
return new CalendarDate(this, monthStart.year, months + 1, days + 1);
263+
}
264+
monthStart = monthEnd;
265+
}
266+
267+
throw Error('Date is not in any month somehow!');
268+
}
269+
270+
toJulianDay(date: AnyCalendarDate): number {
271+
let monthStart = startOfWeek(new CalendarDate(date.year, 1, 1), 'en');
272+
for (let month = 1; month < date.month; month++) {
273+
monthStart = monthStart.add({weeks: weekPattern[month - 1]});
274+
}
275+
276+
let gregorian = monthStart.add({days: date.day - 1});
277+
return super.toJulianDay(gregorian);
278+
}
279+
280+
isEqual(other: Calendar) {
281+
return other instanceof Custom454;
282+
}
283+
}
284+
```
285+
286+
This enables dates to be converted between calendar systems.
287+
288+
```tsx
289+
import {GregorianCalendar, toCalendar} from '@internationalized/date';
290+
291+
let date = new CalendarDate(new Custom454(), 2024, 2, 1);
292+
let gregorianDate = toCalendar(date, new GregorianCalendar());
293+
// => new CalendarDate(new GregorianCalendar(), 2024, 1, 29);
294+
```

packages/@internationalized/date/docs/CalendarDate.mdx

+2-2
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ date.toString(); // '2022-02-03'
7272

7373
By default, `CalendarDate` uses the Gregorian calendar system, but many other calendar systems that are used around the world are supported, such as Hebrew, Indian, Islamic, Buddhist, Ethiopic, and more. A <TypeLink links={docs.links} type={docs.exports.Calendar} /> instance can be passed to the `CalendarDate` constructor to represent dates in that calendar system.
7474

75-
This example creates a date in the Buddhist calendar system, which is equivalent to April 4th, 2020 in the Gregorian calendar.
75+
This example creates a date in the Buddhist calendar system, which is equivalent to April 30th, 2020 in the Gregorian calendar.
7676

7777
```tsx
7878
import {BuddhistCalendar} from '@internationalized/date';
@@ -86,7 +86,7 @@ See the [Calendar](Calendar.html#implementations) docs for details about the sup
8686

8787
Many calendar systems have only one era, or a modern era and a pre-modern era (e.g. AD and BC in the Gregorian calendar). However, other calendar systems may have many eras. For example, the Japanese calendar has eras for the reign of each Emperor. `CalendarDate` represents eras using string identifiers, which can be passed as an additional parameter to the constructor before the year. When eras are present, years are numbered starting from 1 within the era.
8888

89-
This example creates a date in the Japanese calendar system, which is equivalent to April 4th, 2020 in the Gregorian calendar.
89+
This example creates a date in the Japanese calendar system, which is equivalent to April 30th, 2019 in the Gregorian calendar.
9090

9191
```tsx
9292
import {JapaneseCalendar} from '@internationalized/date';

packages/@internationalized/date/src/calendars/BuddhistCalendar.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
// Portions of the code in this file are based on code from ICU.
1414
// Original licensing can be found in the NOTICE file in the root directory of this source tree.
1515

16-
import {AnyCalendarDate} from '../types';
16+
import {AnyCalendarDate, CalendarIdentifier} from '../types';
1717
import {CalendarDate} from '../CalendarDate';
1818
import {fromExtendedYear, getExtendedYear, GregorianCalendar} from './GregorianCalendar';
1919

@@ -25,7 +25,7 @@ const BUDDHIST_ERA_START = -543;
2525
* era, identified as 'BE'.
2626
*/
2727
export class BuddhistCalendar extends GregorianCalendar {
28-
identifier = 'buddhist';
28+
identifier: CalendarIdentifier = 'buddhist';
2929

3030
fromJulianDay(jd: number): CalendarDate {
3131
let gregorianDate = super.fromJulianDay(jd);

packages/@internationalized/date/src/calendars/EthiopicCalendar.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
// Portions of the code in this file are based on code from ICU.
1414
// Original licensing can be found in the NOTICE file in the root directory of this source tree.
1515

16-
import {AnyCalendarDate, Calendar} from '../types';
16+
import {AnyCalendarDate, Calendar, CalendarIdentifier} from '../types';
1717
import {CalendarDate} from '../CalendarDate';
1818
import {Mutable} from '../utils';
1919

@@ -66,7 +66,7 @@ function getDaysInMonth(year: number, month: number) {
6666
* on whether it is a leap year. Two eras are supported: 'AA' and 'AM'.
6767
*/
6868
export class EthiopicCalendar implements Calendar {
69-
identifier = 'ethiopic';
69+
identifier: CalendarIdentifier = 'ethiopic';
7070

7171
fromJulianDay(jd: number): CalendarDate {
7272
let [year, month, day] = julianDayToCE(ETHIOPIC_EPOCH, jd);
@@ -117,7 +117,7 @@ export class EthiopicCalendar implements Calendar {
117117
* except years were measured from a different epoch. Only one era is supported: 'AA'.
118118
*/
119119
export class EthiopicAmeteAlemCalendar extends EthiopicCalendar {
120-
identifier = 'ethioaa'; // also known as 'ethiopic-amete-alem' in ICU
120+
identifier: CalendarIdentifier = 'ethioaa'; // also known as 'ethiopic-amete-alem' in ICU
121121

122122
fromJulianDay(jd: number): CalendarDate {
123123
let [year, month, day] = julianDayToCE(ETHIOPIC_EPOCH, jd);
@@ -141,7 +141,7 @@ export class EthiopicAmeteAlemCalendar extends EthiopicCalendar {
141141
* on whether it is a leap year. Two eras are supported: 'BCE' and 'CE'.
142142
*/
143143
export class CopticCalendar extends EthiopicCalendar {
144-
identifier = 'coptic';
144+
identifier: CalendarIdentifier = 'coptic';
145145

146146
fromJulianDay(jd: number): CalendarDate {
147147
let [year, month, day] = julianDayToCE(COPTIC_EPOCH, jd);

packages/@internationalized/date/src/calendars/GregorianCalendar.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
// Portions of the code in this file are based on code from ICU.
1414
// Original licensing can be found in the NOTICE file in the root directory of this source tree.
1515

16-
import {AnyCalendarDate, Calendar} from '../types';
16+
import {AnyCalendarDate, Calendar, CalendarIdentifier} from '../types';
1717
import {CalendarDate} from '../CalendarDate';
1818
import {mod, Mutable} from '../utils';
1919

@@ -68,7 +68,7 @@ const daysInMonth = {
6868
* Years always contain 12 months, and 365 or 366 days depending on whether it is a leap year.
6969
*/
7070
export class GregorianCalendar implements Calendar {
71-
identifier = 'gregory';
71+
identifier: CalendarIdentifier = 'gregory';
7272

7373
fromJulianDay(jd: number): CalendarDate {
7474
let jd0 = jd;

packages/@internationalized/date/src/calendars/HebrewCalendar.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
// Portions of the code in this file are based on code from ICU.
1414
// Original licensing can be found in the NOTICE file in the root directory of this source tree.
1515

16-
import {AnyCalendarDate, Calendar} from '../types';
16+
import {AnyCalendarDate, Calendar, CalendarIdentifier} from '../types';
1717
import {CalendarDate} from '../CalendarDate';
1818
import {mod, Mutable} from '../utils';
1919

@@ -128,7 +128,7 @@ function getDaysInMonth(year: number, month: number): number {
128128
* In leap years, an extra month is inserted at month 6.
129129
*/
130130
export class HebrewCalendar implements Calendar {
131-
identifier = 'hebrew';
131+
identifier: CalendarIdentifier = 'hebrew';
132132

133133
fromJulianDay(jd: number): CalendarDate {
134134
let d = jd - HEBREW_EPOCH;

packages/@internationalized/date/src/calendars/IndianCalendar.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
// Portions of the code in this file are based on code from ICU.
1414
// Original licensing can be found in the NOTICE file in the root directory of this source tree.
1515

16-
import {AnyCalendarDate} from '../types';
16+
import {AnyCalendarDate, CalendarIdentifier} from '../types';
1717
import {CalendarDate} from '../CalendarDate';
1818
import {fromExtendedYear, GregorianCalendar, gregorianToJulianDay, isLeapYear} from './GregorianCalendar';
1919

@@ -29,7 +29,7 @@ const INDIAN_YEAR_START = 80;
2929
* in each year, with either 30 or 31 days. Only one era identifier is supported: 'saka'.
3030
*/
3131
export class IndianCalendar extends GregorianCalendar {
32-
identifier = 'indian';
32+
identifier: CalendarIdentifier = 'indian';
3333

3434
fromJulianDay(jd: number): CalendarDate {
3535
// Gregorian date for Julian day

packages/@internationalized/date/src/calendars/IslamicCalendar.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
// Portions of the code in this file are based on code from ICU.
1414
// Original licensing can be found in the NOTICE file in the root directory of this source tree.
1515

16-
import {AnyCalendarDate, Calendar} from '../types';
16+
import {AnyCalendarDate, Calendar, CalendarIdentifier} from '../types';
1717
import {CalendarDate} from '../CalendarDate';
1818

1919
const CIVIL_EPOC = 1948440; // CE 622 July 16 Friday (Julian calendar) / CE 622 July 19 (Gregorian calendar)
@@ -50,7 +50,7 @@ function isLeapYear(year: number): boolean {
5050
* Learn more about the available Islamic calendars [here](https://cldr.unicode.org/development/development-process/design-proposals/islamic-calendar-types).
5151
*/
5252
export class IslamicCivilCalendar implements Calendar {
53-
identifier = 'islamic-civil';
53+
identifier: CalendarIdentifier = 'islamic-civil';
5454

5555
fromJulianDay(jd: number): CalendarDate {
5656
return julianDayToIslamic(this, CIVIL_EPOC, jd);
@@ -95,7 +95,7 @@ export class IslamicCivilCalendar implements Calendar {
9595
* Learn more about the available Islamic calendars [here](https://cldr.unicode.org/development/development-process/design-proposals/islamic-calendar-types).
9696
*/
9797
export class IslamicTabularCalendar extends IslamicCivilCalendar {
98-
identifier = 'islamic-tbla';
98+
identifier: CalendarIdentifier = 'islamic-tbla';
9999

100100
fromJulianDay(jd: number): CalendarDate {
101101
return julianDayToIslamic(this, ASTRONOMICAL_EPOC, jd);
@@ -145,7 +145,7 @@ function umalquraYearLength(year: number): number {
145145
* Learn more about the available Islamic calendars [here](https://cldr.unicode.org/development/development-process/design-proposals/islamic-calendar-types).
146146
*/
147147
export class IslamicUmalquraCalendar extends IslamicCivilCalendar {
148-
identifier = 'islamic-umalqura';
148+
identifier: CalendarIdentifier = 'islamic-umalqura';
149149

150150
constructor() {
151151
super();

packages/@internationalized/date/src/calendars/JapaneseCalendar.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
// Portions of the code in this file are based on code from the TC39 Temporal proposal.
1414
// Original licensing can be found in the NOTICE file in the root directory of this source tree.
1515

16-
import {AnyCalendarDate} from '../types';
16+
import {AnyCalendarDate, CalendarIdentifier} from '../types';
1717
import {CalendarDate} from '../CalendarDate';
1818
import {GregorianCalendar} from './GregorianCalendar';
1919
import {Mutable} from '../utils';
@@ -70,7 +70,7 @@ function toGregorian(date: AnyCalendarDate) {
7070
* Note that eras before 1868 (Gregorian) are not currently supported by this implementation.
7171
*/
7272
export class JapaneseCalendar extends GregorianCalendar {
73-
identifier = 'japanese';
73+
identifier: CalendarIdentifier = 'japanese';
7474

7575
fromJulianDay(jd: number): CalendarDate {
7676
let date = super.fromJulianDay(jd);

packages/@internationalized/date/src/calendars/PersianCalendar.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
// Portions of the code in this file are based on code from ICU.
1414
// Original licensing can be found in the NOTICE file in the root directory of this source tree.
1515

16-
import {AnyCalendarDate, Calendar} from '../types';
16+
import {AnyCalendarDate, Calendar, CalendarIdentifier} from '../types';
1717
import {CalendarDate} from '../CalendarDate';
1818
import {mod} from '../utils';
1919

@@ -42,7 +42,7 @@ const MONTH_START = [
4242
* around the March equinox.
4343
*/
4444
export class PersianCalendar implements Calendar {
45-
identifier = 'persian';
45+
identifier: CalendarIdentifier = 'persian';
4646

4747
fromJulianDay(jd: number): CalendarDate {
4848
let daysSinceEpoch = jd - PERSIAN_EPOCH;

packages/@internationalized/date/src/calendars/TaiwanCalendar.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
// Portions of the code in this file are based on code from ICU.
1414
// Original licensing can be found in the NOTICE file in the root directory of this source tree.
1515

16-
import {AnyCalendarDate} from '../types';
16+
import {AnyCalendarDate, CalendarIdentifier} from '../types';
1717
import {CalendarDate} from '../CalendarDate';
1818
import {fromExtendedYear, getExtendedYear, GregorianCalendar} from './GregorianCalendar';
1919
import {Mutable} from '../utils';
@@ -41,7 +41,7 @@ function gregorianToTaiwan(year: number): [string, number] {
4141
* 'before_minguo' and 'minguo'.
4242
*/
4343
export class TaiwanCalendar extends GregorianCalendar {
44-
identifier = 'roc'; // Republic of China
44+
identifier: CalendarIdentifier = 'roc'; // Republic of China
4545

4646
fromJulianDay(jd: number): CalendarDate {
4747
let date = super.fromJulianDay(jd);

packages/@internationalized/date/src/conversion.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import {AnyCalendarDate, AnyDateTime, AnyTime, Calendar, DateFields, Disambiguat
1717
import {CalendarDate, CalendarDateTime, Time, ZonedDateTime} from './CalendarDate';
1818
import {constrain} from './manipulation';
1919
import {getExtendedYear, GregorianCalendar} from './calendars/GregorianCalendar';
20-
import {getLocalTimeZone} from './queries';
20+
import {getLocalTimeZone, isEqualCalendar} from './queries';
2121
import {Mutable} from './utils';
2222

2323
export function epochFromDate(date: AnyDateTime): number {
@@ -260,7 +260,7 @@ export function toTime(dateTime: CalendarDateTime | ZonedDateTime): Time {
260260

261261
/** Converts a date from one calendar system to another. */
262262
export function toCalendar<T extends AnyCalendarDate>(date: T, calendar: Calendar): T {
263-
if (date.calendar.identifier === calendar.identifier) {
263+
if (isEqualCalendar(date.calendar, calendar)) {
264264
return date;
265265
}
266266

0 commit comments

Comments
 (0)