feat: enable TS strict mode (#168)

* feat: enable TS strict mode

* fix: strict TS errors

* fix: strict TS errors

* fix: strict TS errors

* fix: strict TS errors

* fix: strict TS errors

* fix: strict TS errors

* fix: strict TS errors

* fix: strict TS errors

* fix: colors bug with default

* fix: strict TS errors

* fix: strict TS errors

* fix: strict TS errors

* fix: strict TS errors

* fix: strict TS errors

* fix: strict TS errors

* fix: strict TS errors

* fix: strict TS errors

* fix: strict TS errors

* fix: strict TS errors

* fix: strict TS errors

* fix: text type errors

* fix: strict TS errors

* fix: strict TS errors

* fix: strict TS errors - add definite assignment assertion

* fix: strict TS errors - add definite assignment assertion

* fix: strict TS errors

* fix: strict TS errors

* fix: strict TS errors

* fix: strict TS errors

* fix: strict TS errors

* fix: strict TS errors

* fix(ESLint): error on no-explicit-any

* fix: type annotations for any types

* fix: strict TS errors

* fix: strict TS errors

* fix: strict TS errors

* fix: strict TS errors (and remove packages)

* fix: strict TS errors

* fix: strict TS errors

* fix: strict TS errors

* fix: strict TS errors

* fix: strict TS errors

* fix: strict TS errors

* fix: strict TS errors

* feat: enable React.StrictMode

* fix: strict TS errors (done!)

* fix: build error

* fix: replace no-explicit-any assertions

* refactor: cleanup

* refactor: more cleanup

* style: prettier

---------

Co-authored-by: Lukas Zenick <lukas@utexas.edu>
Co-authored-by: Razboy20 <razboy20@gmail.com>
This commit is contained in:
doprz
2024-03-21 13:19:40 -05:00
committed by GitHub
parent 0c76052478
commit efed1c0edb
61 changed files with 562 additions and 1309 deletions

View File

@@ -63,7 +63,7 @@ export function Button({
disabled={disabled}
onClick={disabled ? undefined : onClick}
>
{icon && <Icon className='h-6 w-6' />}
{Icon && <Icon className='h-6 w-6' />}
{!isIconOnly && (
<Text variant='h4' className='translate-y-0.08'>
{children}

View File

@@ -9,7 +9,7 @@ import styles from './Card.module.scss';
export type Props = {
style?: React.CSSProperties;
className?: string;
onClick?: (...args) => void;
onClick?: (...args: unknown[]) => void;
children?: React.ReactNode;
testId?: string;
};

View File

@@ -31,7 +31,7 @@ export function Chip({ label }: React.PropsWithChildren<Props>): JSX.Element {
style={{
backgroundColor: '#FFD600',
}}
title={Object.keys(flagMap).find(key => flagMap[key] === label)}
title={Object.entries(flagMap).find(([full, short]) => short === label)![0]}
>
{label}
</Text>

View File

@@ -6,7 +6,7 @@ import React, { Fragment } from 'react';
import ExtensionRoot from '../ExtensionRoot/ExtensionRoot';
interface _DialogProps {
export interface _DialogProps {
className?: string;
title?: JSX.Element;
description?: JSX.Element;
@@ -21,7 +21,7 @@ export type DialogProps = _DialogProps & Omit<TransitionRootProps<typeof HDialog
* A reusable popup component that can be used to display content on the page
*/
export default function Dialog(props: PropsWithChildren<DialogProps>): JSX.Element {
const { children, className, open, onTransitionEnd, ...rest } = props;
const { children, className, open, ...rest } = props;
return (
<Transition show={open} as={HDialog} {...rest}>

View File

@@ -34,8 +34,10 @@ export default function ExtensionRoot(props: React.PropsWithChildren<Props>): JS
}, []);
return (
<div className={clsx(styles.extensionRoot, props.className)} data-testid={props.testId}>
{props.children}
</div>
<React.StrictMode>
<div className={clsx(styles.extensionRoot, props.className)} data-testid={props.testId}>
{props.children}
</div>
</React.StrictMode>
);
}

View File

@@ -1,11 +0,0 @@
.link {
font-family: 'Inter', sans-serif;
text-decoration: underline;
cursor: pointer;
}
.disabled {
cursor: not-allowed !important;
text-decoration: none !important;
color: #999999 !important;
}

View File

@@ -5,8 +5,6 @@ import clsx from 'clsx';
import type { PropsWithChildren } from 'react';
import React from 'react';
import styles from './Link.module.scss';
type Props = TextProps<'a'> & {
href?: string;
disabled?: boolean;
@@ -19,7 +17,10 @@ export default function Link(props: PropsWithChildren<Props>): JSX.Element {
let { className, href, ...passedProps } = props;
if (href && !props.onClick) {
passedProps.onClick = () => background.openNewTab({ url: href });
passedProps.onClick = e => {
e.preventDefault();
background.openNewTab({ url: href });
};
}
const isDisabled = props.disabled || (!href && !props.onClick);
@@ -28,11 +29,13 @@ export default function Link(props: PropsWithChildren<Props>): JSX.Element {
color='bluebonnet'
{...passedProps}
as='a'
aria-disabled={isDisabled}
href={!isDisabled ? href : undefined}
tabIndex={isDisabled ? -1 : 0}
className={clsx(
styles.link,
{
[styles.disabled]: isDisabled,
'underline cursor-pointer': !isDisabled,
'cursor-not-allowed color-ut-gray': isDisabled,
},
props.className
)}

View File

@@ -31,7 +31,10 @@ function reorder<T>(list: T[], startIndex: number, endIndex: number) {
const listCopy = [...list];
const [removed] = listCopy.splice(startIndex, 1);
listCopy.splice(endIndex, 0, removed);
if (removed) {
listCopy.splice(endIndex, 0, removed);
}
return listCopy;
}
@@ -78,7 +81,7 @@ function List<T>({ draggables, itemKey, children, onReordered, gap }: ListProps<
// check if the draggables content has *actually* changed
if (
draggables.length === items.length &&
draggables.every((element, index) => itemKey(element) === items[index].id)
draggables.every((element, index) => itemKey(element) === items[index]?.id)
) {
return;
}
@@ -86,12 +89,12 @@ function List<T>({ draggables, itemKey, children, onReordered, gap }: ListProps<
}, [draggables, itemKey, items]);
const onDragEnd: OnDragEndResponder = useCallback(
result => {
if (!result.destination) return;
if (result.source.index === result.destination.index) return;
({ destination, source }) => {
if (!destination) return;
if (source.index === destination.index) return;
// will reorder in place
const reordered = reorder(items, result.source.index, result.destination.index);
const reordered = reorder(items, source.index, destination.index);
setItems(reordered);
onReordered(reordered.map(item => item.content));
@@ -125,7 +128,7 @@ function List<T>({ draggables, itemKey, children, onReordered, gap }: ListProps<
}}
>
<ExtensionRoot>
{transformFunction(items[rubric.source.index].content, provided.dragHandleProps)}
{transformFunction(items[rubric.source.index]!.content, provided.dragHandleProps!)}
</ExtensionRoot>
</Item>
);
@@ -135,17 +138,22 @@ function List<T>({ draggables, itemKey, children, onReordered, gap }: ListProps<
<div {...provided.droppableProps} ref={provided.innerRef} style={{ marginBottom: `-${gap}px` }}>
{items.map((item, index) => (
<Draggable key={item.id} draggableId={item.id.toString()} index={index}>
{draggableProvided => (
{({ innerRef, draggableProps, dragHandleProps }) => (
<div
ref={draggableProvided.innerRef}
{...draggableProvided.draggableProps}
ref={innerRef}
{...draggableProps}
style={{
...draggableProvided.draggableProps.style,
...draggableProps.style,
// if last item, don't add margin
marginBottom: `${gap}px`,
}}
>
{transformFunction(item.content, draggableProvided.dragHandleProps)}
{
transformFunction(
item.content,
dragHandleProps!
) /* always exists; only doesn't when "isDragDisabled" is set */
}
</div>
)}
</Draggable>

View File

@@ -1,3 +1,4 @@
import type { DraggableProvidedDragHandleProps } from '@hello-pangea/dnd';
import { background } from '@shared/messages';
import type { Course } from '@shared/types/Course';
import { Status } from '@shared/types/Course';
@@ -17,7 +18,7 @@ export interface PopupCourseBlockProps {
className?: string;
course: Course;
colors: CourseColors;
dragHandleProps?: any;
dragHandleProps?: DraggableProvidedDragHandleProps;
}
/**

View File

@@ -9,7 +9,7 @@ import DropdownArrowUp from '~icons/material-symbols/arrow-drop-up';
/**
* Props for the Dropdown component.
*/
export type Props = {
export type ScheduleDropdownProps = {
defaultOpen?: boolean;
children: React.ReactNode;
};
@@ -17,7 +17,7 @@ export type Props = {
/**
* This is a reusable dropdown component that can be used to toggle the visiblity of information
*/
export default function ScheduleDropdown(props: Props) {
export default function ScheduleDropdown(props: ScheduleDropdownProps) {
const [activeSchedule] = useSchedules();
return (

View File

@@ -59,7 +59,7 @@ export default function ScheduleListItem({ schedule, dragHandleProps, onClick }:
<div className='group flex flex-1 items-center overflow-x-hidden'>
<div
className='flex flex-grow items-center gap-1.5 overflow-x-hidden'
onClick={(...e) => !isEditing && onClick(...e)}
onClick={(...e) => !isEditing && onClick?.(...e)}
>
<div
className={clsx(

View File

@@ -16,7 +16,9 @@ type OurProps<TTag extends ReactTag> = {
ref?: React.ForwardedRef<React.ElementRef<TTag>>;
};
type AsProps<TTag extends ReactTag, TOverrides = {}> = CleanProps<TTag, keyof TOverrides> & OurProps<TTag> & TOverrides;
type AsProps<TTag extends ReactTag, TOverrides = object> = CleanProps<TTag, keyof TOverrides> &
OurProps<TTag> &
TOverrides;
const variants = ['mini', 'small', 'p', 'h4', 'h3-course', 'h3', 'h2-course', 'h2', 'h1-course', 'h1'] as const;
@@ -25,14 +27,15 @@ type Variant = (typeof variants)[number];
/**
* Props for the Text component.
*/
export type TextProps<TTag extends ElementType = 'span'> = PropsOf<TTag>['className'] extends string
? AsProps<
TTag,
{
variant?: Variant;
}
>
: never;
export type TextProps<TTag extends ElementType = 'span'> =
NonNullable<PropsOf<TTag>['className']> extends string
? AsProps<
TTag,
{
variant?: Variant;
}
>
: never;
/**
* A reusable Text component with props that build on top of the design system for the extension
@@ -47,4 +50,4 @@ function Text<TTag extends ElementType = 'span'>(
return <Comp className={mergedClassName} {...rest} ref={ref} />;
}
export default React.forwardRef(Text) as typeof Text;
export default React.forwardRef(Text) as <TTag extends ElementType = 'span'>(props: TextProps<TTag>) => JSX.Element;