diff --git a/.node-version b/.node-version index 55bffd620b..3c5535cf60 100644 --- a/.node-version +++ b/.node-version @@ -1 +1 @@ -18.15.0 +18.19.1 diff --git a/.storybook/USWDS.js b/.storybook/USWDS.js index 66d99f33a5..fad91d03b5 100644 --- a/.storybook/USWDS.js +++ b/.storybook/USWDS.js @@ -1,14 +1,15 @@ -import { create } from '@storybook/theming/create'; +import { create } from '@storybook/theming/create' export default create({ brandTitle: 'U.S. Web Design System (USWDS)', brandUrl: 'https://github.com/trussworks/react-uswds', - brandImage: '/uswds.svg', + brandImage: 'uswds.svg', brandTarget: '_self', base: 'light', // Text - fontBase: "'Public Sans Web', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'", + fontBase: + "'Public Sans Web', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'", textColor: '#1b1b1b', inputTextColor: '#1b1b1b', textInverseColor: '#ffffff', @@ -22,4 +23,4 @@ export default create({ appBorderRadius: 4, inputBorder: '#5c5c5c', inputBorderRadius: 4, -}); +}) diff --git a/.storybook/custom-styles.scss b/.storybook/custom-styles.scss index 9e408a4730..f1132c2c14 100644 --- a/.storybook/custom-styles.scss +++ b/.storybook/custom-styles.scss @@ -1,4 +1,4 @@ -@forward '../src/styles/uswds-theme'; +@forward '../libSrc/styles/uswds-theme'; @use 'uswds-core' as *; // Add custom styles for storybook implementation diff --git a/.storybook/main.ts b/.storybook/main.ts index 1e8d2700ce..3244fc1d77 100644 --- a/.storybook/main.ts +++ b/.storybook/main.ts @@ -1,7 +1,10 @@ import type { StorybookConfig } from '@storybook/react-vite' const config: StorybookConfig = { - stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'], + stories: [ + '../libSrc/**/*.mdx', + '../libSrc/**/*.stories.@(js|jsx|mjs|ts|tsx)', + ], addons: [ '@storybook/addon-a11y', '@storybook/addon-docs', diff --git a/.storybook/preview.ts b/.storybook/preview.ts index 9463cf09cb..e6c2536fdb 100644 --- a/.storybook/preview.ts +++ b/.storybook/preview.ts @@ -1,12 +1,12 @@ import 'happo-plugin-storybook/register' import '@uswds/uswds/css/uswds.css' -import '../src/styles/index.scss' +import '../libSrc/styles/index.scss' import './custom-styles.scss' import { INITIAL_VIEWPORTS } from '@storybook/addon-viewport' -import { Preview } from '@storybook/react'; -import USWDS from './USWDS'; +import { Preview } from '@storybook/react' +import USWDS from './USWDS' const preview: Preview = { parameters: { @@ -20,9 +20,15 @@ const preview: Preview = { showPanel: true, storySort: { method: 'alphabetical', - order: ['Welcome', 'Design tokens', 'Page Templates', 'Components', 'Other'], + order: [ + 'Welcome', + 'Design tokens', + 'Page Templates', + 'Components', + 'Other', + ], }, }, }, } -export default preview; +export default preview diff --git a/__mocks__/fileMock.js b/__mocks__/fileMock.js deleted file mode 100644 index e509146d49..0000000000 --- a/__mocks__/fileMock.js +++ /dev/null @@ -1,3 +0,0 @@ -// __mocks__/fileMock.js - -export default 'test-file-stub' diff --git a/__mocks__/svgrMock.js b/__mocks__/svgrMock.js deleted file mode 100644 index bc85ed4df0..0000000000 --- a/__mocks__/svgrMock.js +++ /dev/null @@ -1 +0,0 @@ -export default 'svg' diff --git a/custom.d.ts b/custom.d.ts index a76b36c5ba..ad90a19f9b 100644 --- a/custom.d.ts +++ b/custom.d.ts @@ -31,3 +31,5 @@ declare namespace globalThis { MSStream: object } } + +declare module '@uswds/compile' diff --git a/gulpfile.ts b/gulpfile.ts new file mode 100644 index 0000000000..4225c90991 --- /dev/null +++ b/gulpfile.ts @@ -0,0 +1,29 @@ +import uswds from '@uswds/compile' + +uswds.settings.version = 3 +uswds.paths.dist = { + ...uswds.paths.dist, + theme: 'lib/dist/assets/uswds/sass', + img: 'lib/dist/assets/uswds/img', + fonts: 'lib/dist/assets/uswds/fonts', + js: 'lib/dist/assets/uswds/js', + css: 'lib/dist/assets/uswds/css', +} + +export { + settings, + paths, + sprite, + copyTheme, + copyFonts, + copyImages, + copyJS, + copyAssets, + copyAll, + compileSass, + compileIcons, + compile, + updateUswds, + init, + watch, +} from '@uswds/compile' diff --git a/src/components/Alert/Alert.module.scss b/libSrc/components/Alert/Alert.module.scss similarity index 100% rename from src/components/Alert/Alert.module.scss rename to libSrc/components/Alert/Alert.module.scss diff --git a/src/components/Alert/Alert.stories.tsx b/libSrc/components/Alert/Alert.stories.tsx similarity index 97% rename from src/components/Alert/Alert.stories.tsx rename to libSrc/components/Alert/Alert.stories.tsx index a794543d23..e667afd035 100644 --- a/src/components/Alert/Alert.stories.tsx +++ b/libSrc/components/Alert/Alert.stories.tsx @@ -1,7 +1,7 @@ import React from 'react' -import { Alert } from './Alert' -import { Button } from '../Button/Button' +import Alert from './Alert.js' +import Button from '../Button/ButtonForwardRef.js' export default { title: 'Components/Alert', diff --git a/src/components/Alert/Alert.test.tsx b/libSrc/components/Alert/Alert.test.tsx similarity index 95% rename from src/components/Alert/Alert.test.tsx rename to libSrc/components/Alert/Alert.test.tsx index 2e73820abb..3d7acb188d 100644 --- a/src/components/Alert/Alert.test.tsx +++ b/libSrc/components/Alert/Alert.test.tsx @@ -1,8 +1,8 @@ import React from 'react' import { render } from '@testing-library/react' -import { Alert } from './Alert' -import { HeadingLevel } from '../../types/headingLevel' +import Alert from './Alert.js' +import type { HeadingLevel } from '../../types/headingLevel.js' describe('Alert component', () => { beforeEach(() => { diff --git a/src/components/Alert/Alert.tsx b/libSrc/components/Alert/Alert.tsx similarity index 81% rename from src/components/Alert/Alert.tsx rename to libSrc/components/Alert/Alert.tsx index bacbedb9b3..5cf6e5e5cd 100644 --- a/src/components/Alert/Alert.tsx +++ b/libSrc/components/Alert/Alert.tsx @@ -1,12 +1,12 @@ import React from 'react' import classnames from 'classnames' -import { HeadingLevel } from '../../types/headingLevel' +import type { HeadingLevel } from '../../types/headingLevel.js' import styles from './Alert.module.scss' -type AlertProps = { - type: 'success' | 'warning' | 'error' | 'info' +export interface BaseAlertProps { + type?: 'success' | 'warning' | 'error' | 'info' heading?: React.ReactNode headingLevel: HeadingLevel children?: React.ReactNode @@ -16,7 +16,9 @@ type AlertProps = { validation?: boolean } -export const Alert = ({ +export type AlertProps = BaseAlertProps & JSX.IntrinsicElements['div'] + +const Alert = ({ type, heading, headingLevel, @@ -27,7 +29,7 @@ export const Alert = ({ className, validation, ...props -}: AlertProps & React.HTMLAttributes): React.ReactElement => { +}: AlertProps): React.ReactElement => { const classes = classnames( 'usa-alert', { diff --git a/src/components/Button/Button.stories.tsx b/libSrc/components/Button/Button.stories.tsx similarity index 97% rename from src/components/Button/Button.stories.tsx rename to libSrc/components/Button/Button.stories.tsx index 7140616486..5f2cd24298 100644 --- a/src/components/Button/Button.stories.tsx +++ b/libSrc/components/Button/Button.stories.tsx @@ -1,5 +1,6 @@ import React from 'react' -import { Button } from './Button' + +import Button from './Button.js' export default { title: 'Components/Button', diff --git a/src/components/Button/Button.test.tsx b/libSrc/components/Button/Button.test.tsx similarity index 86% rename from src/components/Button/Button.test.tsx rename to libSrc/components/Button/Button.test.tsx index dd5d030766..8ce3b00c24 100644 --- a/src/components/Button/Button.test.tsx +++ b/libSrc/components/Button/Button.test.tsx @@ -1,8 +1,9 @@ -import React from 'react' +import React, { createRef } from 'react' import { render, fireEvent } from '@testing-library/react' +import Button from './Button.js' + vi.mock('../../deprecation') -import { Button } from './Button' describe('Button component', () => { beforeEach(() => { @@ -14,6 +15,17 @@ describe('Button component', () => { expect(queryByTestId('button')).toBeInTheDocument() }) + it('renders ref', () => { + const testRef = createRef() + const { queryByTestId } = render( + + ) + expect(queryByTestId('button')).toBeInTheDocument() + expect(testRef.current).toBeInstanceOf(HTMLButtonElement) + }) + describe('renders uswds classes', () => { it('usa-button', () => { const { queryByTestId } = render() diff --git a/src/components/Button/Button.tsx b/libSrc/components/Button/Button.tsx similarity index 71% rename from src/components/Button/Button.tsx rename to libSrc/components/Button/Button.tsx index 28b9ca2379..1287884098 100644 --- a/src/components/Button/Button.tsx +++ b/libSrc/components/Button/Button.tsx @@ -1,8 +1,8 @@ import React from 'react' import classnames from 'classnames' -export type ButtonProps = { - type: 'button' | 'submit' | 'reset' +export interface BaseButtonProps { + type?: 'button' | 'submit' | 'reset' children: React.ReactNode secondary?: boolean base?: boolean @@ -11,10 +11,14 @@ export type ButtonProps = { inverse?: boolean size?: 'big' unstyled?: boolean + // TODO: Remove underscore, or remove property entirely if handled by new React 19 typing + _ref?: React.ForwardedRef } -export const Button = ({ - type, +export type ButtonProps = BaseButtonProps & JSX.IntrinsicElements['button'] + +function Button({ + type = 'button', children, secondary, base, @@ -23,10 +27,10 @@ export const Button = ({ inverse, size, unstyled, - onClick, className, + _ref, ...defaultProps -}: ButtonProps & JSX.IntrinsicElements['button']): React.ReactElement => { +}: ButtonProps): React.ReactElement { const classes = classnames( 'usa-button', { @@ -46,8 +50,8 @@ export const Button = ({ diff --git a/libSrc/components/Button/ButtonForwardRef.tsx b/libSrc/components/Button/ButtonForwardRef.tsx new file mode 100644 index 0000000000..44d7a087b1 --- /dev/null +++ b/libSrc/components/Button/ButtonForwardRef.tsx @@ -0,0 +1,13 @@ +import React, { forwardRef } from 'react' +import Button, { ButtonProps } from './Button.js' + +const ButtonForwardRef = forwardRef(function ButtonForwardRef( + props: ButtonProps, + ref: React.ForwardedRef +) { + return