diff --git a/packages/@react-spectrum/color/test/ColorArea.test.tsx b/packages/@react-spectrum/color/test/ColorArea.test.tsx index 913e6514322..f166cd180ac 100644 --- a/packages/@react-spectrum/color/test/ColorArea.test.tsx +++ b/packages/@react-spectrum/color/test/ColorArea.test.tsx @@ -14,6 +14,7 @@ import {ColorArea} from '../'; import {composeStories} from '@storybook/react'; import {fireEvent, installMouseEvent, installPointerEvent, pointerMap, renderv3 as render} from '@react-spectrum/test-utils-internal'; import {parseColor} from '@react-stately/color'; +import {ProviderProps} from '@react-spectrum/provider'; import React from 'react'; import * as stories from '../stories/ColorArea.stories'; import userEvent from '@testing-library/user-event'; @@ -209,7 +210,7 @@ describe('ColorArea', () => { {...props} onChange={onChangeSpy} onChangeEnd={onChangeEndSpy} /> - , undefined, {locale: 'ar-AE'}); + , undefined, {locale: 'ar-AE'} as ProviderProps); let [xSlider, ySlider] = getAllByRole('slider', {hidden: true}); expect(xSlider.getAttribute('aria-valuetext')).toBe([ diff --git a/packages/@react-spectrum/form/stories/Form.stories.tsx b/packages/@react-spectrum/form/stories/Form.stories.tsx index e154e5efad7..ded882d8e99 100644 --- a/packages/@react-spectrum/form/stories/Form.stories.tsx +++ b/packages/@react-spectrum/form/stories/Form.stories.tsx @@ -18,12 +18,13 @@ import {chain} from '@react-aria/utils'; import {Checkbox, CheckboxGroup} from '@react-spectrum/checkbox'; import {ColorField} from '@react-spectrum/color'; import {ComboBox} from '@react-spectrum/combobox'; +import {ComponentMeta, ComponentStoryObj} from '@storybook/react'; import {Content, Header} from '@react-spectrum/view'; import {ContextualHelp} from '@react-spectrum/contextualhelp'; import {countries, states} from './data'; import {DateField, DatePicker, DateRangePicker, TimeField} from '@react-spectrum/datepicker'; import {Flex} from '@react-spectrum/layout'; -import {Form} from '../'; +import {Form, SpectrumFormProps} from '../'; import {FormTranslatedText} from './../chromatic/FormLanguages.stories'; import {Heading} from '@react-spectrum/text'; import {InlineAlert} from '@react-spectrum/inlinealert'; @@ -44,74 +45,92 @@ import {Well} from '@react-spectrum/well'; export default { title: 'Form', + component: Form, providerSwitcher: {status: 'positive'} -}; +} as ComponentMeta; -export const Default = () => render({}); -export const LabelPositionSide = () => render({labelPosition: 'side'}); +export type FormStory = ComponentStoryObj; -LabelPositionSide.story = { - name: 'labelPosition: side' +export const Default: FormStory = { + render: () => }; -export const CustomWidth = () => render({width: 400}); +export const LabelPositionSide: FormStory = { + render: (args) => , + args: { + labelPosition: 'side' + }, + name: 'labelPosition: side' +}; -CustomWidth.story = { +export const CustomWidth: FormStory = { + render: (args) => , + args: { + width: 400 + }, name: 'custom width' }; -export const CustomWidthLabelPositionSide = () => render({width: 400, labelPosition: 'side'}); - -CustomWidthLabelPositionSide.story = { +export const CustomWidthLabelPositionSide: FormStory = { + render: (args) => , + args: { + width: 400, + labelPosition: 'side' + }, name: 'custom width, labelPosition: side' }; -export const LabelAlignEnd = () => render({width: 400, labelAlign: 'end'}); - -LabelAlignEnd.story = { +export const LabelAlignEnd: FormStory = { + render: (args) => , + args: { + width: 400, + labelAlign: 'end' + }, name: 'labelAlign: end' }; -export const LabelPositionSideLabelAlignEnd = () => - render({width: 400, labelPosition: 'side', labelAlign: 'end'}); - -LabelPositionSideLabelAlignEnd.story = { +export const LabelPositionSideLabelAlignEnd: FormStory = { + render: (args) => , + args: { + width: 400, + labelPosition: 'side', + labelAlign: 'end' + }, name: 'labelPosition: side, labelAlign: end' }; -export const FieldsNextToEachOther = () => ( -
- - - - - - - - - {(item) => {item.name}} - - - - -); - -FieldsNextToEachOther.story = { +export const FieldsNextToEachOther: FormStory = { + render: (args) => ( +
+ + + + + + + + + {(item) => {item.name}} + + + + + ), name: 'fields next to each other' }; -export const FieldsWithAutoCompleteProperty = () => { +const FieldsWithAutoCompletePropertyRender = (props: SpectrumFormProps) => { const [checked, setChecked] = useState(true); return ( -
+

Billing address @@ -286,122 +305,140 @@ export const FieldsWithAutoCompleteProperty = () => { ); }; - -FieldsWithAutoCompleteProperty.story = { +export const FieldsWithAutoCompleteProperty: FormStory = { + render: (args) => , name: 'fields with autoComplete property' }; -export const IsRequiredTrue = () => render({isRequired: true}); - -IsRequiredTrue.story = { +export const IsRequiredTrue: FormStory = { + render: (args) => , + args: { + isRequired: true + }, name: 'isRequired: true' }; -export const IsRequiredTrueNecessityIndicatorLabel = () => - render({isRequired: true, necessityIndicator: 'label'}); - -IsRequiredTrueNecessityIndicatorLabel.story = { +export const IsRequiredTrueNecessityIndicatorLabel: FormStory = { + render: (args) => , + args: { + isRequired: true, + necessityIndicator: 'label' + }, name: 'isRequired: true, necessityIndicator: label' }; -export const IsRequiredFalseNecessityIndicatorLabel = () => - render({isRequired: false, necessityIndicator: 'label'}); - -IsRequiredFalseNecessityIndicatorLabel.story = { +export const IsRequiredFalseNecessityIndicatorLabel: FormStory = { + render: (args) => , + args: { + isRequired: false, + necessityIndicator: 'label' + }, name: 'isRequired: false, necessityIndicator: label' }; -export const IsDisabled = () => render({isDisabled: true}); - -IsDisabled.story = { +export const IsDisabled: FormStory = { + render: (args) => , + args: { + isDisabled: true + }, name: 'isDisabled' }; -export const IsQuiet = () => render({isQuiet: true}); - -IsQuiet.story = { +export const IsQuiet: FormStory = { + render: (args) => , + args: { + isQuiet: true + }, name: 'isQuiet' }; -export const IsQuietLabelPositionSide = () => render({isQuiet: true, labelPosition: 'side'}); - -IsQuietLabelPositionSide.story = { +export const IsQuietLabelPositionSide: FormStory = { + render: (args) => , + args: { + isQuiet: true, + labelPosition: 'side' + }, name: 'isQuiet, labelPosition: side' }; -export const IsEmphasized = () => render({isEmphasized: true}); - -IsEmphasized.story = { +export const IsEmphasized: FormStory = { + render: (args) => , + args: { + isEmphasized: true + }, name: 'isEmphasized' }; -export const ValidationStateInvalid = () => render({validationState: 'invalid'}); - -ValidationStateInvalid.story = { +export const ValidationStateInvalid: FormStory = { + render: (args) => , + args: { + validationState: 'invalid' + }, name: 'validationState: invalid' }; -export const ValidationStateValid = () => render({validationState: 'valid'}); - -ValidationStateValid.story = { +export const ValidationStateValid: FormStory = { + render: (args) => , + args: { + validationState: 'valid' + }, name: 'validationState: valid' }; -export const ValidationStateInvalidIsQuietTrue = () => - render({validationState: 'invalid', isQuiet: true}); - -ValidationStateInvalidIsQuietTrue.story = { +export const ValidationStateInvalidIsQuietTrue: FormStory = { + render: (args) => , + args: { + validationState: 'invalid', + isQuiet: true + }, name: 'validationState: invalid, isQuiet: true' }; -export const ValidationStateValidIsQuietTrue = () => - render({validationState: 'valid', isQuiet: true}); - -ValidationStateValidIsQuietTrue.story = { +export const ValidationStateValidIsQuietTrue: FormStory = { + render: (args) => , + args: { + validationState: 'valid', + isQuiet: true + }, name: 'validationState: valid, isQuiet: true' }; -export const FormWithReset = () => ; - -FormWithReset.story = { +export const FormWithReset: FormStory = { + render: () => , name: 'form with reset' }; - -export const _FormWithSubmit = () => ; - -_FormWithSubmit.story = { +export const _FormWithSubmit: FormStory = { + render: () => , name: 'form with submit' }; -export const FormWithNumberfieldAndLocaleArAe = () => ( - - -
- - -
- - -
- - - -
-); - -FormWithNumberfieldAndLocaleArAe.story = { +export const FormWithNumberfieldAndLocaleArAe: FormStory = { + render: () => ( + + +
+ + +
+ + +
+ + + +
+ ), name: 'form with numberfield and locale=ar-AE' }; -export const WithTranslations = () => ; - -WithTranslations.story = { +export const WithTranslations: FormStory = { + render: () => , name: 'with translations', parameters: {description: {data: 'Translations included for: Arabic, English, Hebrew, Japanese, Korean, Simplified Chinese, and Traditional Chinese.'}} }; -function render(props: any = {}) { +function Render(props: any = {}) { return (
v.includes('dogs') ? 'No dogs' : null}> @@ -709,21 +746,22 @@ function FormWithSubmit() { ); } -export const NativeValidation = () => render({ - isRequired: true, - validationBehavior: 'native', - showSubmit: true, - onSubmit: (e) => { - e.preventDefault(); - action('onSubmit')(Object.fromEntries(new FormData(e.target as HTMLFormElement).entries())); - } -}); - -NativeValidation.story = { +export const NativeValidation: FormStory = { + render: (args) => , + args: { + isRequired: true, + validationBehavior: 'native', + // @ts-ignore + showSubmit: true, + onSubmit: (e) => { + e.preventDefault(); + action('onSubmit')(Object.fromEntries(new FormData(e.target as HTMLFormElement).entries())); + } + }, parameters: {description: {data: 'This story is to test that client validation occurs on form submit and updates when the user commits changes to a field value (e.g. on blur).'}} }; -export function ServerValidation() { +const ServerValidationRender = () => { let [serverErrors, setServerErrors] = useState({}); let onSubmit = async (e) => { e.preventDefault(); @@ -734,19 +772,22 @@ export function ServerValidation() { setServerErrors(errors); }; - return render({ - validationBehavior: 'native', - onSubmit, - validationErrors: serverErrors, - showSubmit: true - }); -} + return ( + + ); +}; -ServerValidation.story = { +export const ServerValidation: FormStory = { + render: () => , parameters: {description: {data: 'This story is to test that server errors appear after submission, and are cleared when a field is modified.'}} }; -export let NumberFieldFormSubmit = { +export const NumberFieldFormSubmit: FormStory = { render: () => { return ( ; } ` diff --git a/packages/@spectrum-icons/express/scripts/generateIcons.cjs b/packages/@spectrum-icons/express/scripts/generateIcons.cjs index 0b0173b6fae..e1067463a36 100644 --- a/packages/@spectrum-icons/express/scripts/generateIcons.cjs +++ b/packages/@spectrum-icons/express/scripts/generateIcons.cjs @@ -30,11 +30,11 @@ for (let file of fs.readdirSync(dir)) { let jsx = compileSVG(path.join(dir, file)); let wrapper = `import {Icon, IconPropsWithoutChildren} from '@react-spectrum/icon'; -import React from 'react'; +import React, {JSX} from 'react'; ${jsx} -export default function ${componentName}(props: IconPropsWithoutChildren) { +export default function ${componentName}(props: IconPropsWithoutChildren): JSX.Element { return ; } `; diff --git a/packages/@spectrum-icons/illustrations/src/Error.tsx b/packages/@spectrum-icons/illustrations/src/Error.tsx index 014a2854932..8899311a1d6 100644 --- a/packages/@spectrum-icons/illustrations/src/Error.tsx +++ b/packages/@spectrum-icons/illustrations/src/Error.tsx @@ -1,7 +1,7 @@ import {Illustration, IllustrationPropsWithoutChildren} from '@react-spectrum/icon'; -import React from 'react'; +import React, {JSX} from 'react'; -export default function Error500(props: IllustrationPropsWithoutChildren) { +export default function Error500(props: IllustrationPropsWithoutChildren): JSX.Element { return ( diff --git a/packages/@spectrum-icons/illustrations/src/File.tsx b/packages/@spectrum-icons/illustrations/src/File.tsx index fb582915d3c..6672b436294 100644 --- a/packages/@spectrum-icons/illustrations/src/File.tsx +++ b/packages/@spectrum-icons/illustrations/src/File.tsx @@ -1,7 +1,7 @@ import {Illustration, IllustrationPropsWithoutChildren} from '@react-spectrum/icon'; -import React from 'react'; +import React, {JSX} from 'react'; -export default function File(props: IllustrationPropsWithoutChildren) { +export default function File(props: IllustrationPropsWithoutChildren): JSX.Element { return ( diff --git a/packages/@spectrum-icons/illustrations/src/Folder.tsx b/packages/@spectrum-icons/illustrations/src/Folder.tsx index b622b6a186c..8aac3d22b72 100644 --- a/packages/@spectrum-icons/illustrations/src/Folder.tsx +++ b/packages/@spectrum-icons/illustrations/src/Folder.tsx @@ -1,7 +1,7 @@ import {Illustration, IllustrationPropsWithoutChildren} from '@react-spectrum/icon'; -import React from 'react'; +import React, {JSX} from 'react'; -export default function File(props: IllustrationPropsWithoutChildren) { +export default function File(props: IllustrationPropsWithoutChildren): JSX.Element { return ( diff --git a/packages/@spectrum-icons/illustrations/src/NoSearchResults.tsx b/packages/@spectrum-icons/illustrations/src/NoSearchResults.tsx index b9fcd2ce537..0376782a4a6 100644 --- a/packages/@spectrum-icons/illustrations/src/NoSearchResults.tsx +++ b/packages/@spectrum-icons/illustrations/src/NoSearchResults.tsx @@ -1,7 +1,7 @@ import {Illustration, IllustrationPropsWithoutChildren} from "@react-spectrum/icon"; -import React from "react"; +import React, {JSX} from "react"; -export default function NoSearchResults(props: IllustrationPropsWithoutChildren) { +export default function NoSearchResults(props: IllustrationPropsWithoutChildren): JSX.Element { return ( diff --git a/packages/@spectrum-icons/illustrations/src/NotFound.tsx b/packages/@spectrum-icons/illustrations/src/NotFound.tsx index caf1537f5b1..f0904063f25 100644 --- a/packages/@spectrum-icons/illustrations/src/NotFound.tsx +++ b/packages/@spectrum-icons/illustrations/src/NotFound.tsx @@ -1,7 +1,7 @@ import {Illustration, IllustrationPropsWithoutChildren} from '@react-spectrum/icon'; -import React from 'react'; +import React, {JSX} from 'react'; -export default function Error404(props: IllustrationPropsWithoutChildren) { +export default function Error404(props: IllustrationPropsWithoutChildren): JSX.Element { return ( diff --git a/packages/@spectrum-icons/illustrations/src/Timeout.tsx b/packages/@spectrum-icons/illustrations/src/Timeout.tsx index 165ad33ee95..f991ed972e9 100644 --- a/packages/@spectrum-icons/illustrations/src/Timeout.tsx +++ b/packages/@spectrum-icons/illustrations/src/Timeout.tsx @@ -1,7 +1,7 @@ import {Illustration, IllustrationPropsWithoutChildren} from '@react-spectrum/icon'; -import React from 'react'; +import React, {JSX} from 'react'; -export default function Error504(props: IllustrationPropsWithoutChildren) { +export default function Error504(props: IllustrationPropsWithoutChildren): JSX.Element { return ( diff --git a/packages/@spectrum-icons/illustrations/src/Unauthorized.tsx b/packages/@spectrum-icons/illustrations/src/Unauthorized.tsx index d2ed20b34b2..ba7c1f3d078 100644 --- a/packages/@spectrum-icons/illustrations/src/Unauthorized.tsx +++ b/packages/@spectrum-icons/illustrations/src/Unauthorized.tsx @@ -1,7 +1,7 @@ import {Illustration, IllustrationPropsWithoutChildren} from '@react-spectrum/icon'; -import React from 'react'; +import React, {JSX} from 'react'; -export default function Error403(props: IllustrationPropsWithoutChildren) { +export default function Error403(props: IllustrationPropsWithoutChildren): JSX.Element { return ( diff --git a/packages/@spectrum-icons/illustrations/src/Unavailable.tsx b/packages/@spectrum-icons/illustrations/src/Unavailable.tsx index 614fc17cf23..4c98d7a8ef5 100644 --- a/packages/@spectrum-icons/illustrations/src/Unavailable.tsx +++ b/packages/@spectrum-icons/illustrations/src/Unavailable.tsx @@ -1,7 +1,7 @@ import {Illustration, IllustrationPropsWithoutChildren} from '@react-spectrum/icon'; -import React from 'react'; +import React, {JSX} from 'react'; -export default function Error503(props: IllustrationPropsWithoutChildren) { +export default function Error503(props: IllustrationPropsWithoutChildren): JSX.Element { return ( diff --git a/packages/@spectrum-icons/illustrations/src/Upload.tsx b/packages/@spectrum-icons/illustrations/src/Upload.tsx index cafeb7fef5d..fcb51b561f2 100644 --- a/packages/@spectrum-icons/illustrations/src/Upload.tsx +++ b/packages/@spectrum-icons/illustrations/src/Upload.tsx @@ -1,7 +1,7 @@ import {Illustration, IllustrationPropsWithoutChildren} from '@react-spectrum/icon'; -import React from 'react'; +import React, {JSX} from 'react'; -export default function Error504(props: IllustrationPropsWithoutChildren) { +export default function Error504(props: IllustrationPropsWithoutChildren): JSX.Element { return ( diff --git a/packages/@spectrum-icons/ui/scripts/generateIcons.cjs b/packages/@spectrum-icons/ui/scripts/generateIcons.cjs index 6d7822853af..ccf6eeb3a9d 100644 --- a/packages/@spectrum-icons/ui/scripts/generateIcons.cjs +++ b/packages/@spectrum-icons/ui/scripts/generateIcons.cjs @@ -39,13 +39,13 @@ function template(iconName) { `import {${iconName} as IconComponent} from '@adobe/react-spectrum-ui/dist/${iconName}.js'; import {UIIcon, UIIconPropsWithoutChildren} from '@react-spectrum/icon'; import {useProvider} from '@react-spectrum/provider'; -import React from 'react'; +import React, {JSX} from 'react'; ${jsx} ExpressIcon.displayName = IconComponent.displayName; -export default function ${iconName}(props: UIIconPropsWithoutChildren) { +export default function ${iconName}(props: UIIconPropsWithoutChildren): JSX.Element { let provider; try { provider = useProvider(); @@ -61,9 +61,9 @@ export default function ${iconName}(props: UIIconPropsWithoutChildren) { return ( `import {${iconName} as IconComponent} from '@adobe/react-spectrum-ui/dist/${iconName}.js'; import {UIIcon, UIIconPropsWithoutChildren} from '@react-spectrum/icon'; -import React from 'react'; +import React, {JSX} from 'react'; -export default function ${iconName}(props: UIIconPropsWithoutChildren) { +export default function ${iconName}(props: UIIconPropsWithoutChildren): JSX.Element { return ; } ` diff --git a/packages/@spectrum-icons/workflow/scripts/generateIcons.cjs b/packages/@spectrum-icons/workflow/scripts/generateIcons.cjs index c8311efafa1..0bbed3c8157 100644 --- a/packages/@spectrum-icons/workflow/scripts/generateIcons.cjs +++ b/packages/@spectrum-icons/workflow/scripts/generateIcons.cjs @@ -24,9 +24,9 @@ function template(iconName) { return ( `import {${iconName} as IconComponent} from '@adobe/react-spectrum-workflow/dist/${importName}.js'; import {Icon, IconPropsWithoutChildren} from '@react-spectrum/icon'; -import React from 'react'; +import React, {JSX} from 'react'; -export default function ${iconRename}(props: IconPropsWithoutChildren) { +export default function ${iconRename}(props: IconPropsWithoutChildren): JSX.Element { return ; } ` diff --git a/packages/dev/docs/pages/react-aria/home/ExampleApp.tsx b/packages/dev/docs/pages/react-aria/home/ExampleApp.tsx index 0ecd739b676..39085048daf 100644 --- a/packages/dev/docs/pages/react-aria/home/ExampleApp.tsx +++ b/packages/dev/docs/pages/react-aria/home/ExampleApp.tsx @@ -23,7 +23,7 @@ import {getLocalTimeZone, today} from '@internationalized/date'; import {GridList, GridListItem} from 'tailwind-starter/GridList'; import {Menu, MenuItem} from 'tailwind-starter/Menu'; import {Modal} from 'tailwind-starter/Modal'; -import plants from './plants'; +import plants, {Plant} from './plants'; import {Popover} from 'tailwind-starter/Popover'; import React, {ReactElement, UIEvent, useCallback, useEffect, useMemo, useRef, useState} from 'react'; import {SearchField} from 'tailwind-starter/SearchField'; @@ -35,8 +35,6 @@ import {tv} from 'tailwind-variants'; import {useCollator, useFilter, VisuallyHidden} from 'react-aria'; import {useMediaQuery} from '@react-spectrum/utils'; -type Plant = typeof plants[0] & {isFavorite: boolean}; - const allColumns: ColumnProps[] = [ {id: 'favorite', children: Favorite, width: 40, minWidth: 40}, {id: 'common_name', children: 'Name', minWidth: 150, allowsSorting: true}, @@ -48,13 +46,13 @@ const allColumns: ColumnProps[] = [ let hideOnScroll = document.getElementById('hideOnScroll'); -export function ExampleApp() { +export function ExampleApp(): React.ReactNode { let [sortDescriptor, setSortDescriptor] = useState({ column: 'common_name', direction: 'ascending' }); - let [allItems, setAllItems] = useState(() => plants.map(p => ({...p, isFavorite: false}))); + let [allItems, setAllItems] = useState(() => plants.map(p => ({...p, isFavorite: false}))); let [search, setSearch] = useState(''); let [favorite, setFavorite] = useState(false); let [cycles, setCycles] = useState(new Set()); diff --git a/packages/dev/docs/pages/react-aria/home/plants.js b/packages/dev/docs/pages/react-aria/home/plants.ts similarity index 96% rename from packages/dev/docs/pages/react-aria/home/plants.js rename to packages/dev/docs/pages/react-aria/home/plants.ts index f2dc5080720..65be38efb0c 100644 --- a/packages/dev/docs/pages/react-aria/home/plants.js +++ b/packages/dev/docs/pages/react-aria/home/plants.ts @@ -9,6 +9,20 @@ * OF ANY KIND, either express or implied. See the License for the specific language * governing permissions and limitations under the License. */ + +export interface Plant { + id: number, + common_name: string, + scientific_name: string[], + watering: string, + sunlight: string[], + cycle: string, + default_image: { + thumbnail: string + }, + isFavorite?: boolean +} + export default [ { id: 1, @@ -230,4 +244,4 @@ export default [ thumbnail: new URL('plants/nasturtium.jpg?as=webp', import.meta.url).toString() } } -]; +] as Plant[]; diff --git a/packages/dev/test-utils/src/renderOverride.js b/packages/dev/test-utils/src/renderOverride.tsx similarity index 55% rename from packages/dev/test-utils/src/renderOverride.js rename to packages/dev/test-utils/src/renderOverride.tsx index 574548a94fb..16992acf2c8 100644 --- a/packages/dev/test-utils/src/renderOverride.js +++ b/packages/dev/test-utils/src/renderOverride.tsx @@ -10,34 +10,41 @@ * governing permissions and limitations under the License. */ -import {Provider} from '@react-spectrum/provider'; +import {act as originalAct, renderHook as originalRenderHook, render} from '@testing-library/react'; +import {Provider, ProviderProps} from '@react-spectrum/provider'; import React from 'react'; -import {render} from '@testing-library/react'; import {StrictModeWrapper} from './StrictModeWrapper'; import {theme} from '@react-spectrum/theme-default'; -let reactTestingLibrary = require('@testing-library/react'); +export {act, fireEvent, within, screen, waitFor, getAllByRole, createEvent, waitForElementToBeRemoved} from '@testing-library/react'; -// export everything -export * from '@testing-library/react'; +function customRender(ui: Parameters[0], options?: Parameters[1] | undefined): ReturnType { + return render(ui, {wrapper: StrictModeWrapper, ...options}); +} +let reactTestingLibrary = require('@testing-library/react'); // export renderHook and actHook from testing-library/react-hooks library if they don't exist in @testing-library/react // (i.e. renderHook is only in v13+ of testing library) -export let renderHook = reactTestingLibrary.renderHook; -export let actHook = reactTestingLibrary.act; +export let renderHook = reactTestingLibrary.renderHook as typeof originalRenderHook; +export let actHook = reactTestingLibrary.act as typeof originalAct; if (!renderHook) { let rhtl = require('@testing-library/react-hooks'); renderHook = rhtl.renderHook; actHook = rhtl.act; } -function customRender(ui, options) { - return render(ui, {wrapper: StrictModeWrapper, ...options}); -} - // override render method with export {customRender as render}; -export function renderv3(ui, options, providerProps) { - return render(ui, {wrapper: (props) => , ...options}); +export function renderv3(ui: Parameters[0], options?: Parameters[1] | undefined, providerProps?: ProviderProps | undefined): ReturnType { + return render(ui, { + wrapper: (props: React.PropsWithChildren) => ( + + + + ), + ...options + }); } diff --git a/packages/dev/test-utils/src/shadowDOM.js b/packages/dev/test-utils/src/shadowDOM.ts similarity index 79% rename from packages/dev/test-utils/src/shadowDOM.js rename to packages/dev/test-utils/src/shadowDOM.ts index 84a2b06746e..ee41da0f5d0 100644 --- a/packages/dev/test-utils/src/shadowDOM.js +++ b/packages/dev/test-utils/src/shadowDOM.ts @@ -10,7 +10,13 @@ * governing permissions and limitations under the License. */ -export function createShadowRoot(attachTo = document.body) { +interface ShadowRootReturnValue { + shadowHost: HTMLElement, + shadowRoot: ShadowRoot, + cleanup: () => void +} + +export function createShadowRoot(attachTo: HTMLElement = document.body): ShadowRootReturnValue { const div = document.createElement('div'); attachTo.appendChild(div); const shadowRoot = div.attachShadow({mode: 'open'}); diff --git a/packages/dev/test-utils/src/testSSR.js b/packages/dev/test-utils/src/testSSR.tsx similarity index 90% rename from packages/dev/test-utils/src/testSSR.js rename to packages/dev/test-utils/src/testSSR.tsx index 77da5f71b8a..0695dd99e14 100644 --- a/packages/dev/test-utils/src/testSSR.js +++ b/packages/dev/test-utils/src/testSSR.tsx @@ -30,7 +30,7 @@ try { // ignore. } -export async function testSSR(filename, source, runAfterServer) { +export async function testSSR(filename: string, source: string, runAfterServer?: () => void): Promise { // Transform the code with babel so JSX becomes JS. source = babel.transformSync(source, {filename, plugins: ['@babel/plugin-syntax-import-attributes']}).code; @@ -58,7 +58,7 @@ export async function testSSR(filename, source, runAfterServer) { } // Capture React errors/warning and make them fail the tests. - let errors = []; + let errors: string[] = []; console.error = console.warn = (...messages) => { errors.push(util.format(...messages)); }; @@ -72,9 +72,9 @@ export async function testSSR(filename, source, runAfterServer) { if (ReactDOMClient) { act(() => ReactDOMClient.hydrateRoot(container, {element})); } else { - act(() => {ReactDOM.hydrate({element}, container);}); + act(() => {(ReactDOM as any).hydrate({element}, container);}); } - } catch (err) { + } catch (err: any) { errors.push(err.stack); } diff --git a/scripts/generateS2IconIndex.js b/scripts/generateS2IconIndex.js index a7af51f6e37..392ce5b3786 100644 --- a/scripts/generateS2IconIndex.js +++ b/scripts/generateS2IconIndex.js @@ -66,7 +66,8 @@ function generate(dir) { } let relative = path.relative(dir, 'packages/@react-spectrum/s2/src/Icon'); - let typeImport = dir.includes('ui-icons') ? "import {ReactNode, SVGProps} from 'react';" : `import {IconProps, IllustrationContext} from '${relative}';`; + let typeImport = dir.includes('ui-icons') ? "import {ReactNode, SVGProps} from 'react';" : `import {ReactNode} from 'react'; +import {IconProps, IllustrationContext} from '${relative}';`; let ctx = dir.includes('spectrum-illustrations') ? '[props] = useContextProps(props, null, IllustrationContext);\n ' : ''; let type = dir.includes('ui-icons') ? 'SVGProps' : 'IconProps'; let isIllustration = dir.includes('spectrum-illustrations'); @@ -124,7 +125,7 @@ let styles = style({ } src += ` -export default function ${importName}(props: ${type} & {size?: ${Object.keys(sizes).map(s => `'${s}'`).join(' | ')}})${isIllustration ? '' : ': ReactNode'} { +export default function ${importName}(props: ${type} & {size?: ${Object.keys(sizes).map(s => `'${s}'`).join(' | ')}}): ReactNode { ${ctx}let {size = 'M', ...otherProps} = props; switch (size) {${Object.keys(sizes).map(size => ` case '${size}':