diff --git a/.eslintignore b/.eslintignore index d80f693b1d1..22928b0b72c 100644 --- a/.eslintignore +++ b/.eslintignore @@ -11,4 +11,5 @@ config/superblocks.js web/** docs/**/*.md tools/ui-components/dist/** -playwright.config.ts \ No newline at end of file +playwright.config.ts +tools/ui-components/types/** diff --git a/.prettierignore b/.prettierignore index caf1d943ab9..d4364b4ada7 100644 --- a/.prettierignore +++ b/.prettierignore @@ -25,3 +25,4 @@ curriculum-server/data/curriculum.json docs/**/*.md client/src/components/Donation/types.js tools/ui-components/dist +tools/ui-components/types diff --git a/tools/ui-components/.gitignore b/tools/ui-components/.gitignore new file mode 100644 index 00000000000..f7232374e1c --- /dev/null +++ b/tools/ui-components/.gitignore @@ -0,0 +1,2 @@ +types/ +dist/ diff --git a/tools/ui-components/package.json b/tools/ui-components/package.json index a5e14a892d0..71955858b8a 100644 --- a/tools/ui-components/package.json +++ b/tools/ui-components/package.json @@ -7,6 +7,7 @@ "main": "dist/bundle.js", "module": "dist/bundle.es.js", "style": "dist/base.css", + "types": "types/src/index.d.ts", "files": [ "dist" ], @@ -71,7 +72,7 @@ "storybook": "start-storybook -p 6006", "storybook:theming": "pnpm run storybook --no-manager-cache", "build-storybook": "build-storybook", - "build": "pnpm run build:css && pnpm run build:js", + "build": "pnpm run build:css && pnpm run build:js && tsc", "build:js": "cross-env NODE_ENV=production rollup -c", "build:css": "pnpm dlx tailwindcss -i ./src/base.css -o ./dist/base.css --minify", "dev:js": "cross-env NODE_ENV=development rollup -c -w ", diff --git a/tools/ui-components/rollup.config.js b/tools/ui-components/rollup.config.js index 7a0eec37562..1722f4d881f 100644 --- a/tools/ui-components/rollup.config.js +++ b/tools/ui-components/rollup.config.js @@ -24,7 +24,7 @@ const config = { plugins: [ postcss(), resolve(), - typescript({ sourceMap: false }), + typescript({ sourceMap: false, declaration: false }), babel({ babelHelpers: 'bundled' }), commonjs(), production && terser() diff --git a/tools/ui-components/src/drop-down/drop-down.tsx b/tools/ui-components/src/drop-down/drop-down.tsx index a20dfb30f4e..59603d5b28c 100644 --- a/tools/ui-components/src/drop-down/drop-down.tsx +++ b/tools/ui-components/src/drop-down/drop-down.tsx @@ -2,14 +2,45 @@ import React, { createContext, useContext, useRef } from 'react'; import { Menu } from '@headlessui/react'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faCaretDown, faCaretUp } from '@fortawesome/free-solid-svg-icons'; +import { Props } from '@headlessui/react/dist/types'; -type MenuItemsProps = React.ComponentPropsWithoutRef; +type MenuTag = React.ExoticComponent<{ + children?: React.ReactNode; +}>; -export type DropdownProps = React.ComponentPropsWithoutRef & { +interface MenuRenderPropArg { + open: boolean; + close: () => void; +} + +type DropdownMenuProps = Props< + MenuTag, + MenuRenderPropArg, + never, + { + // eslint-disable-next-line @typescript-eslint/naming-convention + __demoMode?: boolean; + } +>; + +export type DropdownProps = DropdownMenuProps & { dropup?: boolean; }; -type DropDownButtonProps = React.ComponentPropsWithoutRef; +export interface ButtonRenderPropArg { + open: boolean; +} + +type ButtonPropsWeControl = 'aria-controls' | 'aria-expanded' | 'aria-haspopup'; + +type DropDownButtonProps = Props< + 'button', + ButtonRenderPropArg, + ButtonPropsWeControl, + { + disabled?: boolean; + } +>; type DropDownContextProps = DropdownProps & { menuButtonRef: React.MutableRefObject; @@ -24,30 +55,29 @@ const dropUpItems = dropDownItems + ' transform -translate-y-full top-0'; const toggleClassNames = 'cursor-pointer border-3 border-solid w-full block text-center touch-manipulation bg-background-quaternary text-foreground-secondary px-3 py-1.5 relative hover:bg-foreground-secondary hover:text-background-secondary btn-block border-foreground-secondary'; -export const MenuItems = React.forwardRef< - React.ElementRef, - MenuItemsProps ->(({ children, className }, ref) => { - const { dropup, menuButtonRef } = useContext(DropDownContext); +export const MenuItems = React.forwardRef( + ({ children, className }, ref): JSX.Element => { + const { dropup, menuButtonRef } = useContext(DropDownContext); - const handleClick = () => { - menuButtonRef.current?.focus(); - }; + const handleClick = () => { + menuButtonRef.current?.focus(); + }; - const itemsClasses = dropup ? dropUpItems : dropDownItems; - const buttonClass: string = [className, itemsClasses].join(' '); - return ( - - {children} - - ); -}); + const itemsClasses = dropup ? dropUpItems : dropDownItems; + const buttonClass: string = [className, itemsClasses].join(' '); + return ( + + {children} + + ); + } +); const DropDownButton = ({ children, className, ...rest -}: DropDownButtonProps) => { +}: DropDownButtonProps): JSX.Element => { const { dropup, menuButtonRef } = useContext(DropDownContext); const classes = [className, toggleClassNames].join(' '); diff --git a/tools/ui-components/tsconfig.json b/tools/ui-components/tsconfig.json index 895b3d66aa3..f4a6f84e4b8 100644 --- a/tools/ui-components/tsconfig.json +++ b/tools/ui-components/tsconfig.json @@ -8,8 +8,11 @@ "esModuleInterop": true, "moduleResolution": "node", "strict": true, - "noEmit": true + "emitDeclarationOnly": true, + "declaration": true, + "declarationDir": "types" }, + "exclude": ["node_modules", "dist", "types"], "ts-node": { "compilerOptions": { "module": "commonjs"