diff --git a/.storybook-s2/docs/Migrating.jsx b/.storybook-s2/docs/Migrating.jsx
index 96fdecb712b..f819f96d16e 100644
--- a/.storybook-s2/docs/Migrating.jsx
+++ b/.storybook-s2/docs/Migrating.jsx
@@ -114,6 +114,9 @@ export function Migrating() {
No updates needed.
+ No updates needed.
+
No updates needed.
@@ -158,6 +161,27 @@ export function Migrating() {
No updates needed.
+
No updates needed.
diff --git a/packages/@react-aria/dnd/src/DragManager.ts b/packages/@react-aria/dnd/src/DragManager.ts
index 9e0773ed230..2128797ffb4 100644
--- a/packages/@react-aria/dnd/src/DragManager.ts
+++ b/packages/@react-aria/dnd/src/DragManager.ts
@@ -410,7 +410,7 @@ class DragSession {
...visibleDropTargets.flatMap(target => target.activateButtonRef?.current ? [target.element, target.activateButtonRef?.current] : [target.element])
], {shouldUseInert: true});
- this.mutationObserver.observe(document.body, {subtree: true, attributes: true, attributeFilter: ['aria-hidden']});
+ this.mutationObserver.observe(document.body, {subtree: true, attributes: true, attributeFilter: ['aria-hidden', 'inert']});
}
next(): void {
@@ -437,7 +437,7 @@ class DragSession {
// If we've reached the end of the valid drop targets, cycle back to the original drag target.
// This lets the user cancel the drag in case they don't have an Escape key (e.g. iPad keyboard case).
if (index === this.validDropTargets.length - 1) {
- if (!this.dragTarget.element.closest('[aria-hidden="true"]')) {
+ if (!this.dragTarget.element.closest('[aria-hidden="true"], [inert]')) {
this.setCurrentDropTarget(null);
this.dragTarget.element.focus();
} else {
@@ -472,7 +472,7 @@ class DragSession {
// If we've reached the start of the valid drop targets, cycle back to the original drag target.
// This lets the user cancel the drag in case they don't have an Escape key (e.g. iPad keyboard case).
if (index === 0) {
- if (!this.dragTarget.element.closest('[aria-hidden="true"]')) {
+ if (!this.dragTarget.element.closest('[aria-hidden="true"], [inert]')) {
this.setCurrentDropTarget(null);
this.dragTarget.element.focus();
} else {
@@ -579,7 +579,7 @@ class DragSession {
cancel(): void {
this.setCurrentDropTarget(null);
this.end();
- if (!this.dragTarget.element.closest('[aria-hidden="true"]')) {
+ if (!this.dragTarget.element.closest('[aria-hidden="true"], [inert]')) {
this.dragTarget.element.focus();
}
@@ -640,7 +640,7 @@ class DragSession {
function findValidDropTargets(options: DragTarget) {
let types = getTypes(options.items);
return [...dropTargets.values()].filter(target => {
- if (target.element.closest('[aria-hidden="true"]')) {
+ if (target.element.closest('[aria-hidden="true"], [inert]')) {
return false;
}
diff --git a/packages/@react-spectrum/s2/src/DateRangePicker.tsx b/packages/@react-spectrum/s2/src/DateRangePicker.tsx
index b2113effdc8..6132469899a 100644
--- a/packages/@react-spectrum/s2/src/DateRangePicker.tsx
+++ b/packages/@react-spectrum/s2/src/DateRangePicker.tsx
@@ -150,7 +150,7 @@ export const DateRangePicker = /*#__PURE__*/ (forwardRef as forwardRefType)(func
isDateUnavailable={isDateUnavailable}
pageBehavior={pageBehavior} />
{showTimeField && (
-
+
-
+
+
+
+
+
+
"
`;
+
+exports[`changes validationState to isInvalid or nothing 1`] = `
+"import { DateField } from "@react-spectrum/s2";
+ let validationState = 'invalid';
+ let props = {validationState: 'invalid'};
+
+
+
+
+
+
"
+`;
diff --git a/packages/dev/codemods/src/s1-to-s2/__tests__/__snapshots__/datepicker.test.ts.snap b/packages/dev/codemods/src/s1-to-s2/__tests__/__snapshots__/datepicker.test.ts.snap
index 5d59549159a..48e9c869956 100644
--- a/packages/dev/codemods/src/s1-to-s2/__tests__/__snapshots__/datepicker.test.ts.snap
+++ b/packages/dev/codemods/src/s1-to-s2/__tests__/__snapshots__/datepicker.test.ts.snap
@@ -1,9 +1,30 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`Does nothing 1`] = `
+exports[`Removes isQuiet 1`] = `
"import { DatePicker } from "@react-spectrum/s2";
-
+let isQuiet = true;
+let props = {isQuiet: true};
-
+
+
+
+
+
+
"
`;
+
+exports[`changes validationState to isInvalid or nothing 1`] = `
+"import { DatePicker } from "@react-spectrum/s2";
+ let validationState = 'invalid';
+ let props = {validationState: 'invalid'};
+
+
+
+
+
+
"
+`;
diff --git a/packages/dev/codemods/src/s1-to-s2/__tests__/__snapshots__/daterangepicker.test.ts.snap b/packages/dev/codemods/src/s1-to-s2/__tests__/__snapshots__/daterangepicker.test.ts.snap
index 7162dc296c1..eac94a75277 100644
--- a/packages/dev/codemods/src/s1-to-s2/__tests__/__snapshots__/daterangepicker.test.ts.snap
+++ b/packages/dev/codemods/src/s1-to-s2/__tests__/__snapshots__/daterangepicker.test.ts.snap
@@ -1,9 +1,30 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`Does nothing 1`] = `
+exports[`Removes isQuiet 1`] = `
"import { DateRangePicker } from "@react-spectrum/s2";
-
+let isQuiet = true;
+let props = {isQuiet: true};
-
+
+
+
+
+
+
"
`;
+
+exports[`changes validationState to isInvalid or nothing 1`] = `
+"import { DateRangePicker } from "@react-spectrum/s2";
+ let validationState = 'invalid';
+ let props = {validationState: 'invalid'};
+
+
+
+
+
+
"
+`;
diff --git a/packages/dev/codemods/src/s1-to-s2/__tests__/__snapshots__/timefield.test.ts.snap b/packages/dev/codemods/src/s1-to-s2/__tests__/__snapshots__/timefield.test.ts.snap
index 4a845dc25b8..66d69951a4b 100644
--- a/packages/dev/codemods/src/s1-to-s2/__tests__/__snapshots__/timefield.test.ts.snap
+++ b/packages/dev/codemods/src/s1-to-s2/__tests__/__snapshots__/timefield.test.ts.snap
@@ -1,8 +1,30 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`Renames variants 1`] = `
-"// import {Button} from '@adobe/react-spectrum';
-
+exports[`Removes isQuiet 1`] = `
+"import { TimeField } from "@react-spectrum/s2";
+let isQuiet = true;
+let props = {isQuiet: true};
+
+
+
+
+
+
"
`;
+
+exports[`changes validationState to isInvalid or nothing 1`] = `
+"import { TimeField } from "@react-spectrum/s2";
+ let validationState = 'invalid';
+ let props = {validationState: 'invalid'};
+
+
+
+
+
+
"
+`;
diff --git a/packages/dev/codemods/src/s1-to-s2/__tests__/datefield.test.ts b/packages/dev/codemods/src/s1-to-s2/__tests__/datefield.test.ts
index 48ff6f6254e..85bdd1554b6 100644
--- a/packages/dev/codemods/src/s1-to-s2/__tests__/datefield.test.ts
+++ b/packages/dev/codemods/src/s1-to-s2/__tests__/datefield.test.ts
@@ -6,10 +6,30 @@ const test = (name: string, input: string) => {
defineSnapshotTest(transform, {}, input, name);
};
-test('Does nothing', `
-import {DateField} from '@adobe/react-spectrum';
+test('Removes isQuiet', `
+import {DateField} from '@adobe/react-spectrum';
+let isQuiet = true;
+let props = {isQuiet: true};
-
+
+
+
+
+
+
`);
+
+
+test('changes validationState to isInvalid or nothing', `
+ import {DateField} from '@adobe/react-spectrum';
+ let validationState = 'invalid';
+ let props = {validationState: 'invalid'};
+
+
+
+
+
+
+`);
diff --git a/packages/dev/codemods/src/s1-to-s2/__tests__/datepicker.test.ts b/packages/dev/codemods/src/s1-to-s2/__tests__/datepicker.test.ts
index f6e8c413206..cd8191a9b94 100644
--- a/packages/dev/codemods/src/s1-to-s2/__tests__/datepicker.test.ts
+++ b/packages/dev/codemods/src/s1-to-s2/__tests__/datepicker.test.ts
@@ -6,10 +6,30 @@ const test = (name: string, input: string) => {
defineSnapshotTest(transform, {}, input, name);
};
-test('Does nothing', `
-import {DatePicker} from '@adobe/react-spectrum';
+test('Removes isQuiet', `
+import {DatePicker} from '@adobe/react-spectrum';
+let isQuiet = true;
+let props = {isQuiet: true};
-
+
+
+
+
+
+
`);
+
+
+test('changes validationState to isInvalid or nothing', `
+ import {DatePicker} from '@adobe/react-spectrum';
+ let validationState = 'invalid';
+ let props = {validationState: 'invalid'};
+
+
+
+
+
+
+`);
diff --git a/packages/dev/codemods/src/s1-to-s2/__tests__/daterangepicker.test.ts b/packages/dev/codemods/src/s1-to-s2/__tests__/daterangepicker.test.ts
index 8c8191602f0..33da5d45c6c 100644
--- a/packages/dev/codemods/src/s1-to-s2/__tests__/daterangepicker.test.ts
+++ b/packages/dev/codemods/src/s1-to-s2/__tests__/daterangepicker.test.ts
@@ -6,10 +6,30 @@ const test = (name: string, input: string) => {
defineSnapshotTest(transform, {}, input, name);
};
-test('Does nothing', `
-import {DateRangePicker} from '@adobe/react-spectrum';
+test('Removes isQuiet', `
+import {DateRangePicker} from '@adobe/react-spectrum';
+let isQuiet = true;
+let props = {isQuiet: true};
-
+
+
+
+
+
+
`);
+
+
+test('changes validationState to isInvalid or nothing', `
+ import {DateRangePicker} from '@adobe/react-spectrum';
+ let validationState = 'invalid';
+ let props = {validationState: 'invalid'};
+
+
+
+
+
+
+`);
diff --git a/packages/dev/codemods/src/s1-to-s2/__tests__/timefield.test.ts b/packages/dev/codemods/src/s1-to-s2/__tests__/timefield.test.ts
index a7b16598b27..f14b1b3d450 100644
--- a/packages/dev/codemods/src/s1-to-s2/__tests__/timefield.test.ts
+++ b/packages/dev/codemods/src/s1-to-s2/__tests__/timefield.test.ts
@@ -6,9 +6,30 @@ const test = (name: string, input: string) => {
defineSnapshotTest(transform, {}, input, name);
};
-test('Renames variants', `
-// import {Button} from '@adobe/react-spectrum';
+test('Removes isQuiet', `
+import {TimeField} from '@adobe/react-spectrum';
+let isQuiet = true;
+let props = {isQuiet: true};
+
+
+
+
+
+
`);
+
+
+test('changes validationState to isInvalid or nothing', `
+ import {TimeField} from '@adobe/react-spectrum';
+ let validationState = 'invalid';
+ let props = {validationState: 'invalid'};
+
+
+
+
+
+
+`);
diff --git a/packages/dev/codemods/src/s1-to-s2/src/codemods/components/DateField/transform.ts b/packages/dev/codemods/src/s1-to-s2/src/codemods/components/DateField/transform.ts
new file mode 100644
index 00000000000..0cf1f9173b0
--- /dev/null
+++ b/packages/dev/codemods/src/s1-to-s2/src/codemods/components/DateField/transform.ts
@@ -0,0 +1,28 @@
+import {NodePath} from '@babel/traverse';
+import {
+ removeProp,
+ updatePropNameAndValue
+} from '../../shared/transforms';
+import * as t from '@babel/types';
+
+/**
+ * Transforms DateField:
+ * - Remove isQuiet (it is no longer supported in Spectrum 2).
+ * - Change validationState="invalid" to isInvalid.
+ * - Remove validationState="valid" (it is no longer supported in Spectrum 2).
+ */
+export default function transformDateField(path: NodePath
): void {
+ // Change validationState="invalid" to isInvalid
+ updatePropNameAndValue(path, {
+ oldPropName: 'validationState',
+ oldPropValue: 'invalid',
+ newPropName: 'isInvalid',
+ newPropValue: true
+ });
+
+ // Remove validationState="valid"
+ removeProp(path, {propName: 'validationState', propValue: 'valid'});
+
+ // Remove isQuiet
+ removeProp(path, {propName: 'isQuiet'});
+}
diff --git a/packages/dev/codemods/src/s1-to-s2/src/codemods/components/DatePicker/transform.ts b/packages/dev/codemods/src/s1-to-s2/src/codemods/components/DatePicker/transform.ts
new file mode 100644
index 00000000000..566d918ee96
--- /dev/null
+++ b/packages/dev/codemods/src/s1-to-s2/src/codemods/components/DatePicker/transform.ts
@@ -0,0 +1,28 @@
+import {NodePath} from '@babel/traverse';
+import {
+ removeProp,
+ updatePropNameAndValue
+} from '../../shared/transforms';
+import * as t from '@babel/types';
+
+/**
+ * Transforms DatePicker:
+ * - Remove isQuiet (it is no longer supported in Spectrum 2).
+ * - Change validationState="invalid" to isInvalid.
+ * - Remove validationState="valid" (it is no longer supported in Spectrum 2).
+ */
+export default function transformDatePicker(path: NodePath): void {
+ // Change validationState="invalid" to isInvalid
+ updatePropNameAndValue(path, {
+ oldPropName: 'validationState',
+ oldPropValue: 'invalid',
+ newPropName: 'isInvalid',
+ newPropValue: true
+ });
+
+ // Remove validationState="valid"
+ removeProp(path, {propName: 'validationState', propValue: 'valid'});
+
+ // Remove isQuiet
+ removeProp(path, {propName: 'isQuiet'});
+}
diff --git a/packages/dev/codemods/src/s1-to-s2/src/codemods/components/DateRangePicker/transform.ts b/packages/dev/codemods/src/s1-to-s2/src/codemods/components/DateRangePicker/transform.ts
new file mode 100644
index 00000000000..725815a0c88
--- /dev/null
+++ b/packages/dev/codemods/src/s1-to-s2/src/codemods/components/DateRangePicker/transform.ts
@@ -0,0 +1,28 @@
+import {NodePath} from '@babel/traverse';
+import {
+ removeProp,
+ updatePropNameAndValue
+} from '../../shared/transforms';
+import * as t from '@babel/types';
+
+/**
+ * Transforms DateRangePicker:
+ * - Remove isQuiet (it is no longer supported in Spectrum 2).
+ * - Change validationState="invalid" to isInvalid.
+ * - Remove validationState="valid" (it is no longer supported in Spectrum 2).
+ */
+export default function transformDateRangePicker(path: NodePath): void {
+ // Change validationState="invalid" to isInvalid
+ updatePropNameAndValue(path, {
+ oldPropName: 'validationState',
+ oldPropValue: 'invalid',
+ newPropName: 'isInvalid',
+ newPropValue: true
+ });
+
+ // Remove validationState="valid"
+ removeProp(path, {propName: 'validationState', propValue: 'valid'});
+
+ // Remove isQuiet
+ removeProp(path, {propName: 'isQuiet'});
+}
diff --git a/packages/dev/codemods/src/s1-to-s2/src/codemods/components/TimeField/transform.ts b/packages/dev/codemods/src/s1-to-s2/src/codemods/components/TimeField/transform.ts
new file mode 100644
index 00000000000..8e2bed6f1f2
--- /dev/null
+++ b/packages/dev/codemods/src/s1-to-s2/src/codemods/components/TimeField/transform.ts
@@ -0,0 +1,28 @@
+import {NodePath} from '@babel/traverse';
+import {
+ removeProp,
+ updatePropNameAndValue
+} from '../../shared/transforms';
+import * as t from '@babel/types';
+
+/**
+ * Transforms TimeField:
+ * - Remove isQuiet (it is no longer supported in Spectrum 2).
+ * - Change validationState="invalid" to isInvalid.
+ * - Remove validationState="valid" (it is no longer supported in Spectrum 2).
+ */
+export default function transformTimeField(path: NodePath): void {
+ // Change validationState="invalid" to isInvalid
+ updatePropNameAndValue(path, {
+ oldPropName: 'validationState',
+ oldPropValue: 'invalid',
+ newPropName: 'isInvalid',
+ newPropValue: true
+ });
+
+ // Remove validationState="valid"
+ removeProp(path, {propName: 'validationState', propValue: 'valid'});
+
+ // Remove isQuiet
+ removeProp(path, {propName: 'isQuiet'});
+}
diff --git a/packages/react-aria-components/src/TreeDropTargetDelegate.ts b/packages/react-aria-components/src/TreeDropTargetDelegate.ts
index daee51861ed..ba3d952d1e9 100644
--- a/packages/react-aria-components/src/TreeDropTargetDelegate.ts
+++ b/packages/react-aria-components/src/TreeDropTargetDelegate.ts
@@ -84,11 +84,15 @@ export class TreeDropTargetDelegate {
if (target.dropPosition === 'before') {
let keyBefore = this.state!.collection.getKeyBefore(target.key);
if (keyBefore != null) {
- target = {
+ let convertedTarget = {
type: 'item',
key: keyBefore,
dropPosition: 'after'
} as const;
+
+ if (isValidDropTarget(convertedTarget)) {
+ target = convertedTarget;
+ }
}
}