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:
@@ -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}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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}>
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
)}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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 (
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user