What's new
diff --git a/packages/dev/codemods/src/s1-to-s2/__tests__/__snapshots__/dialog.test.ts.snap b/packages/dev/codemods/src/s1-to-s2/__tests__/__snapshots__/dialog.test.ts.snap
index 5254db8dd8d..fcc1a32b352 100644
--- a/packages/dev/codemods/src/s1-to-s2/__tests__/__snapshots__/dialog.test.ts.snap
+++ b/packages/dev/codemods/src/s1-to-s2/__tests__/__snapshots__/dialog.test.ts.snap
@@ -62,6 +62,36 @@ exports[`Moves close function from DialogTrigger to Dialog 1`] = `
"
`;
+exports[`Moves isDismissable 1`] = `
+"import { DialogTrigger, Button, Dialog, Heading, Content, Divider } from "@react-spectrum/s2";
+
+
+
+
+"
+`;
+
+exports[`Moves isDismissable from DialogContainer 1`] = `
+"import { DialogContainer, Button, Dialog, Heading, Content, Divider } from "@react-spectrum/s2";
+
+
+ {showDialog1 && }
+ {showDialog2 && }
+"
+`;
+
exports[`Removes divider 1`] = `
"import { Dialog, Heading, Content, Divider } from "@react-spectrum/s2";
@@ -90,6 +120,87 @@ exports[`Removes onDismiss and leaves a comment 1`] = `
"
`;
+exports[`Replaces type="fullscreen" with FullscreenDialog component 1`] = `
+"import { FullscreenDialog, DialogTrigger, Button, Dialog, Heading, Content, Divider } from "@react-spectrum/s2";
+
+
+
+
+ Test
+
+ Content
+
+"
+`;
+
+exports[`Replaces type="fullscreen" with FullscreenDialog component in DialogContainer 1`] = `
+"import {
+ FullscreenDialog,
+ DialogContainer,
+ Button,
+ Dialog,
+ Heading,
+ Content,
+ Divider,
+} from "@react-spectrum/s2";
+
+
+ {showDialog1 &&
+ Test
+
+ Content
+ }
+ {showDialog2 &&
+ Test
+
+ Content
+ }
+"
+`;
+
+exports[`Replaces type="fullscreenTakeover" with FullscreenDialog component 1`] = `
+"import { FullscreenDialog, DialogTrigger, Button, Dialog, Heading, Content, Divider } from "@react-spectrum/s2";
+
+
+
+
+ Test
+
+ Content
+
+"
+`;
+
+exports[`Replaces type="fullscreenTakeover" with FullscreenDialog component and close function 1`] = `
+"import { FullscreenDialog, DialogTrigger, Button, Dialog, Heading, Content, Divider } from "@react-spectrum/s2";
+
+
+
+ {(
+ {
+ close
+ }
+ ) => <>
+ Test
+
+ Content
+ >}
+"
+`;
+
+exports[`Replaces type="popover" with Popover component 1`] = `
+"import { Popover, DialogTrigger, Button, Dialog, Heading, Content, Divider } from "@react-spectrum/s2";
+
+
+
+
+ Test
+
+ Content
+
+"
+`;
+
exports[`bails when it cannot move the close function 1`] = `
"import { DialogTrigger, Button, Dialog, Heading, Content, Divider } from "@react-spectrum/s2";
diff --git a/packages/dev/codemods/src/s1-to-s2/__tests__/dialog.test.ts b/packages/dev/codemods/src/s1-to-s2/__tests__/dialog.test.ts
index 24567cff444..d6226cbf27c 100644
--- a/packages/dev/codemods/src/s1-to-s2/__tests__/dialog.test.ts
+++ b/packages/dev/codemods/src/s1-to-s2/__tests__/dialog.test.ts
@@ -110,3 +110,104 @@ import {DialogTrigger, Button, Dialog, Heading, Content, Divider} from '@adobe/r
}
`);
+
+test('Moves isDismissable', `
+import {DialogTrigger, Button, Dialog, Heading, Content, Divider} from '@adobe/react-spectrum';
+
+
+
+
+
+`);
+
+test('Replaces type="popover" with Popover component', `
+import {DialogTrigger, Button, Dialog, Heading, Content, Divider} from '@adobe/react-spectrum';
+
+
+
+
+
+`);
+
+test('Replaces type="fullscreen" with FullscreenDialog component', `
+import {DialogTrigger, Button, Dialog, Heading, Content, Divider} from '@adobe/react-spectrum';
+
+
+
+
+
+`);
+
+test('Replaces type="fullscreenTakeover" with FullscreenDialog component', `
+import {DialogTrigger, Button, Dialog, Heading, Content, Divider} from '@adobe/react-spectrum';
+
+
+
+
+
+`);
+
+test('Replaces type="fullscreenTakeover" with FullscreenDialog component and close function', `
+import {DialogTrigger, Button, Dialog, Heading, Content, Divider} from '@adobe/react-spectrum';
+
+
+
+ {(close) =>
+
+ }
+
+`);
+
+test('Moves isDismissable from DialogContainer', `
+import {DialogContainer, Button, Dialog, Heading, Content, Divider} from '@adobe/react-spectrum';
+
+
+ {showDialog1 && }
+ {showDialog2 && }
+
+`);
+
+test('Replaces type="fullscreen" with FullscreenDialog component in DialogContainer', `
+import {DialogContainer, Button, Dialog, Heading, Content, Divider} from '@adobe/react-spectrum';
+
+
+ {showDialog1 && }
+ {showDialog2 && }
+
+`);
diff --git a/packages/dev/codemods/src/s1-to-s2/src/codemods/changes.ts b/packages/dev/codemods/src/s1-to-s2/src/codemods/changes.ts
index c1e74517171..2eeb5d2e5cd 100644
--- a/packages/dev/codemods/src/s1-to-s2/src/codemods/changes.ts
+++ b/packages/dev/codemods/src/s1-to-s2/src/codemods/changes.ts
@@ -75,6 +75,10 @@ type FunctionInfo =
| {
name: 'updateLegacyLink',
args: {}
+ }
+ | {
+ name: 'updateDialogChild',
+ args: {}
};
type Change = {
@@ -428,6 +432,30 @@ export const changes: ChangesJSON = {
name: 'moveRenderPropsToChild',
args: {newChildComponent: 'Dialog'}
}
+ },
+ {
+ description: 'Rename isDismissable to isDismissible',
+ reason: 'Fixed spelling',
+ function: {name: 'updatePropName', args: {oldProp: 'isDismissable', newProp: 'isDismissible'}}
+ },
+ {
+ description: 'Update Dialog child to Popover or FullscreenDialog depending on type prop',
+ reason: 'Updated API',
+ function: {name: 'updateDialogChild', args: {}}
+ }
+ ]
+ },
+ DialogContainer: {
+ changes: [
+ {
+ description: 'Rename isDismissable to isDismissible',
+ reason: 'Fixed spelling',
+ function: {name: 'updatePropName', args: {oldProp: 'isDismissable', newProp: 'isDismissible'}}
+ },
+ {
+ description: 'Update Dialog child to Popover or FullscreenDialog depending on type prop',
+ reason: 'Updated API',
+ function: {name: 'updateDialogChild', args: {}}
}
]
},
diff --git a/packages/dev/codemods/src/s1-to-s2/src/codemods/transforms.ts b/packages/dev/codemods/src/s1-to-s2/src/codemods/transforms.ts
index d643b81394f..370e792784d 100644
--- a/packages/dev/codemods/src/s1-to-s2/src/codemods/transforms.ts
+++ b/packages/dev/codemods/src/s1-to-s2/src/codemods/transforms.ts
@@ -960,6 +960,62 @@ function updateLegacyLink(
}
}
+/**
+ * Updates DialogTrigger and DialogContainer to the new API.
+ *
+ * Example:
+ * - When `type="popover"`, replaces Dialog with `
`.
+ * - When `type="fullscreen"`, replaces Dialog with ``.
+ * - When `type="fullscreenTakeover"`, replaces Dialog with ``.
+ */
+function updateDialogChild(
+ path: NodePath
+) {
+ let typePath = path.get('openingElement').get('attributes').find((attr) => t.isJSXAttribute(attr.node) && attr.node.name.name === 'type') as NodePath | undefined;
+ let type = typePath?.node.value?.type === 'StringLiteral' ? typePath.node.value?.value : 'modal';
+ let newComponent = 'Dialog';
+ let props: t.JSXAttribute[] = [];
+ if (type === 'popover') {
+ newComponent = 'Popover';
+ } else if (type === 'fullscreen' || type === 'fullscreenTakeover') {
+ newComponent = 'FullscreenDialog';
+ if (type === 'fullscreenTakeover') {
+ props.push(t.jsxAttribute(t.jsxIdentifier('variant'), t.stringLiteral(type)));
+ }
+ }
+
+ for (let prop of ['isDismissible', 'mobileType', 'hideArrow', 'placement', 'shouldFlip', 'isKeyboardDismissDisabled', 'containerPadding', 'offset', 'crossOffset']) {
+ let attr = path.get('openingElement').get('attributes').find(attr => attr.isJSXAttribute() && attr.node.name.name === prop) as NodePath | undefined;
+ if (attr) {
+ props.push(attr.node);
+ attr.remove();
+ }
+ }
+
+ typePath?.remove();
+
+ let localName = newComponent;
+ if (newComponent !== 'Dialog' && availableComponents.has(newComponent)) {
+ let program = path.findParent((p) => t.isProgram(p.node)) as NodePath;
+ localName = addComponentImport(program, newComponent);
+ }
+
+ path.traverse({
+ JSXElement(dialog) {
+ if (!t.isJSXIdentifier(dialog.node.openingElement.name) || getName(dialog, dialog.node.openingElement.name) !== 'Dialog') {
+ return;
+ }
+
+ dialog.node.openingElement.name = t.jsxIdentifier(localName);
+ if (dialog.node.closingElement) {
+ dialog.node.closingElement.name = t.jsxIdentifier(localName);
+ }
+
+ dialog.node.openingElement.attributes.push(...props);
+ }
+ });
+}
+
export const functionMap = {
updatePropNameAndValue,
updatePropValueAndAddNewProp,
@@ -979,5 +1035,6 @@ export const functionMap = {
updatePlacementToSingleValue,
removeComponentIfWithinParent,
updateAvatarSize,
- updateLegacyLink
+ updateLegacyLink,
+ updateDialogChild
};
From 65e3a52a39696c1bd62d7c641492bd417afd8857 Mon Sep 17 00:00:00 2001
From: Daniel Lu
Date: Tue, 19 Nov 2024 16:33:39 -0800
Subject: [PATCH 5/5] Improve error message for missing Provider error (#7404)
---
packages/@react-spectrum/provider/src/Provider.tsx | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/packages/@react-spectrum/provider/src/Provider.tsx b/packages/@react-spectrum/provider/src/Provider.tsx
index f86a7f64c07..a8b97ec0d38 100644
--- a/packages/@react-spectrum/provider/src/Provider.tsx
+++ b/packages/@react-spectrum/provider/src/Provider.tsx
@@ -198,7 +198,10 @@ const ProviderWrapper = React.forwardRef(function ProviderWrapper(props: Provide
export function useProvider() {
let context = useContext(Context);
if (!context) {
- throw new Error('No root provider found.');
+ throw new Error(
+ 'No root provider found, please make sure your app is wrapped within a . ' +
+ 'Alternatively, this issue may be caused by duplicate packages, see https://github.com/adobe/react-spectrum/wiki/Frequently-Asked-Questions-(FAQs)#why-are-there-errors-after-upgrading-a-react-spectrum-package for more information.'
+ );
}
return context;
}