Skip to content

Commit 8633f4d

Browse files
Mukesh-FNclaude
andcommitted
feat: apply React 19 / TypeScript 5 / Storybook 8 migration changes
- Fix type-only exports across all components (export type {}) for Vite/esbuild compatibility - Add import type for all type-only imports (ESLint consistent-type-imports) - Add @vite-ignore to dynamic imports in Flag.tsx and useLocaleObject.ts - Fix CSSTransition nodeRef for React 19 (Modal, Offcanvas, Banner) - Fix React 19 breaking changes: defaultProps, JSX namespace, useRef types, ReactNode functions, cloneElement typing - Migrate react-popper to @floating-ui/react for Popover and Tooltip - Update date-fns v3 locale dynamic imports - Add Husky v9 pre-commit hook - Update jscodeshift v17 codemod type casts - Add UPGRADE_PLAN.md documenting all migration phases Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 22956c4 commit 8633f4d

731 files changed

Lines changed: 1478 additions & 1642 deletions

File tree

Some content is hidden

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

.husky/pre-commit

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#!/bin/sh
2+
npm run husky:precommit

src/codemods/colors-to-css-vars.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ const replaceColorsForCssVarsInTemplateLiterals = (
7979
const expressionObject = expressionAfterQuasis.object as Identifier;
8080

8181
// Identify if it's a usage of Colors
82-
const isColorsExpression = localColorNames.includes(expressionObject.name);
82+
const isColorsExpression = localColorNames.includes(expressionObject.name as string);
8383

8484
if (isColorsExpression) {
8585
// Find the color being used
@@ -190,14 +190,14 @@ export default (file: FileInfo, api: API, options: Options) => {
190190
const waveNamedImports = waveImports.find(j.ImportSpecifier);
191191

192192
// Find Colors named imports in @freenow/wave imports
193-
const colorsImports = waveNamedImports.filter(path => path.node.imported.name === 'Colors');
193+
const colorsImports = waveNamedImports.filter(path => (path.node.imported.name as string) === 'Colors');
194194

195195
// Early return in case no Colors are imported
196196
if (colorsImports.length === 0) return file.source;
197197

198198
// Get the local Colors import names
199199
colorsImports.forEach(spec => {
200-
if (spec.node.local?.name) localColorNames.push(spec.node.local.name);
200+
if (spec.node.local?.name) localColorNames.push(spec.node.local.name as string);
201201
});
202202

203203
// Iterate over template strings

src/codemods/deprecated-icons.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -173,14 +173,14 @@ export default (file: FileInfo, api: API, options: Options) => {
173173
// Find deprecated icons named imports in @freenow/wave imports
174174
const deprecatedIconsImports = waveImports
175175
.find(j.ImportSpecifier)
176-
.filter(path => DeprecatedIconsNames.includes(path.node.imported.name));
176+
.filter(path => DeprecatedIconsNames.includes(path.node.imported.name as string));
177177

178178
// Early return if no deprecated icons are imported
179179
if (deprecatedIconsImports.length === 0) return file.source;
180180

181181
// Get the local icons import names
182182
deprecatedIconsImports.forEach(spec => {
183-
if (spec.node.local?.name) localIconsNames.push(spec.node.local.name);
183+
if (spec.node.local?.name) localIconsNames.push(spec.node.local.name as string);
184184
});
185185

186186
// Find usages of the deprecated icons

src/codemods/inverted-to-wrapper.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,26 +35,27 @@ export default (file: FileInfo, api: API, options: Options) => {
3535
// Find component named imports in @freenow/wave imports that potentially have an inverted prop
3636
const componentImports = waveImports
3737
.find(j.ImportSpecifier)
38-
.filter(path => ComponentNamesWithInvertedProp.includes(path.node.imported.name));
38+
.filter(path => ComponentNamesWithInvertedProp.includes(path.node.imported.name as string));
3939

4040
// Get the local icons import names
4141
componentImports.forEach(spec => {
42-
if (spec.node.local?.name) localComponentNames.push(spec.node.local.name);
42+
if (spec.node.local?.name) localComponentNames.push(spec.node.local.name as string);
4343
});
4444

4545
// Find declarations of styled components that use a component which has the inverted prop
4646
const styledExpressions = ast.find(j.TaggedTemplateExpression, {
4747
tag: {
4848
arguments: ([argument]) =>
49-
argument?.type === 'Identifier' && ComponentNamesWithInvertedProp.includes(argument.name)
49+
argument?.type === 'Identifier' && ComponentNamesWithInvertedProp.includes(argument.name as string)
5050
}
5151
});
5252

5353
styledExpressions.forEach(ex => {
5454
if (ex.parent?.node && ex.parent.node.type === 'VariableDeclarator') {
5555
const styledDeclaration: VariableDeclarator = ex.parent.node;
5656
// Mark the name of the declared styled component as a local component which can have the inverted prop
57-
if (styledDeclaration.id.type === 'Identifier') localComponentNames.push(styledDeclaration.id.name);
57+
if (styledDeclaration.id.type === 'Identifier')
58+
localComponentNames.push(styledDeclaration.id.name as string);
5859
}
5960
});
6061

src/codemods/semantic-colors-to-new-theme.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -263,22 +263,22 @@ export default (file: FileInfo, api: API, options: Options) => {
263263
const waveNamedImports = waveImports.find(j.ImportSpecifier);
264264

265265
// Find SemanticColors named imports in wave imports
266-
const colorsImports = waveNamedImports.filter(path => path.node.imported.name === 'SemanticColors');
266+
const colorsImports = waveNamedImports.filter(path => (path.node.imported.name as string) === 'SemanticColors');
267267

268268
// Find themeGet named imports in wave imports
269-
const themeGetImports = waveNamedImports.filter(path => path.node.imported.name === 'themeGet');
269+
const themeGetImports = waveNamedImports.filter(path => (path.node.imported.name as string) === 'themeGet');
270270

271271
// Early return in case no SemanticColors or themeGet are imported
272272
if (colorsImports.length === 0 && themeGetImports.length === 0) return file.source;
273273

274274
// Get the local SemanticColors import names
275275
colorsImports.forEach(spec => {
276-
if (spec.node.local?.name) localColorNames.push(spec.node.local.name);
276+
if (spec.node.local?.name) localColorNames.push(spec.node.local.name as string);
277277
});
278278

279279
// Get the local themeGet import names
280280
themeGetImports.forEach(spec => {
281-
if (spec.node.local?.name) localThemeGetNames.push(spec.node.local.name);
281+
if (spec.node.local?.name) localThemeGetNames.push(spec.node.local.name as string);
282282
});
283283

284284
// Find all themeGet CallExpressions (e.g. themeGet('text.primary'))

src/components/Accordion/Accordion.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
import React, { PropsWithChildren } from 'react';
1+
import React, { type PropsWithChildren } from 'react';
22
import styled from 'styled-components';
33
import { Box } from '../Box/Box';
44
import { Compact } from './components/Compact';
55
import { DefaultPanel } from './components/Default';
6-
import { AccordionProps } from './types';
6+
import { type AccordionProps } from './types';
77
import { getSemanticValue } from '../../utils/cssVariables';
88

99
const HorizontalDivider = styled(Box)`
@@ -63,4 +63,6 @@ const Accordion: React.FC<PropsWithChildren<AccordionProps>> = ({
6363
</RenderedSection>
6464
);
6565

66-
export { Accordion, AccordionProps };
66+
export { Accordion };
67+
68+
export { type AccordionProps } from './types';

src/components/Accordion/components/Compact.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
import React, { ReactElement, useState, PropsWithChildren } from 'react';
1+
import React, { type ReactElement, useState, type PropsWithChildren } from 'react';
22
import styled from 'styled-components';
33
import { Box } from '../../Box/Box';
44
import { Headline } from '../../Headline/Headline';
55
import { Header } from './Header';
66
import { ChevronUp } from './ChevronUp';
77
import { ChevronDown } from './ChevronDown';
88
import { Description } from './Description';
9-
import { AccordionProps } from '../types';
9+
import { type AccordionProps } from '../types';
1010
import { getSemanticValue } from '../../../utils/cssVariables';
1111

1212
type Props = PropsWithChildren<

src/components/Accordion/components/Default.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { PropsWithChildren, ReactElement, useState } from 'react';
1+
import React, { type PropsWithChildren, type ReactElement, useState } from 'react';
22
import styled from 'styled-components';
33
import { Text } from '../../Text/Text';
44
import { Box } from '../../Box/Box';
@@ -7,7 +7,7 @@ import { Header } from './Header';
77
import { ChevronUp } from './ChevronUp';
88
import { ChevronDown } from './ChevronDown';
99
import { Description } from './Description';
10-
import { AccordionProps } from '../types';
10+
import { type AccordionProps } from '../types';
1111
import { getSemanticValue } from '../../../utils/cssVariables';
1212

1313
const ButtonLabel = styled(Text).attrs({ as: 'p' })`

src/components/Accordion/components/Description.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import React, { ReactElement } from 'react';
2-
import { MarginProps } from 'styled-system';
1+
import React, { type ReactElement } from 'react';
2+
import { type MarginProps } from 'styled-system';
33
import { Text } from '../../Text/Text';
44

55
interface Props extends MarginProps {

src/components/Accordion/docs/Accordion.stories.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { StoryObj, Meta } from '@storybook/react';
1+
import { type StoryObj, type Meta } from '@storybook/react';
22
import { Accordion } from '../Accordion';
33

44
const meta: Meta<typeof Accordion> = {

0 commit comments

Comments
 (0)