feat: refactor all components in common
This commit is contained in:
@@ -3,6 +3,7 @@ import { getThemeColorHexByName, getThemeColorRgbByName } from '@shared/util/the
|
|||||||
import Text from '@views/components/common/Text/Text';
|
import Text from '@views/components/common/Text/Text';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { satisfies } from 'semver';
|
||||||
|
|
||||||
import type IconComponent from '~icons/material-symbols';
|
import type IconComponent from '~icons/material-symbols';
|
||||||
|
|
||||||
@@ -44,7 +45,7 @@ export function Button({
|
|||||||
...style,
|
...style,
|
||||||
color: colorHex,
|
color: colorHex,
|
||||||
backgroundColor: `rgb(${colorRgb} / var(--un-bg-opacity)`,
|
backgroundColor: `rgb(${colorRgb} / var(--un-bg-opacity)`,
|
||||||
} as React.CSSProperties
|
} satisfies React.CSSProperties
|
||||||
}
|
}
|
||||||
className={clsx(
|
className={clsx(
|
||||||
'btn',
|
'btn',
|
||||||
|
|||||||
@@ -5,14 +5,14 @@ import React from 'react';
|
|||||||
* A type that represents the flags that a course can have.
|
* A type that represents the flags that a course can have.
|
||||||
*/
|
*/
|
||||||
export type Flag = 'WR' | 'QR' | 'GC' | 'CD' | 'E' | 'II';
|
export type Flag = 'WR' | 'QR' | 'GC' | 'CD' | 'E' | 'II';
|
||||||
export const flagMap: Record<string, Flag> = {
|
export const flagMap = {
|
||||||
Writing: 'WR',
|
Writing: 'WR',
|
||||||
'Quantitative Reasoning': 'QR',
|
'Quantitative Reasoning': 'QR',
|
||||||
'Global Cultures': 'GC',
|
'Global Cultures': 'GC',
|
||||||
'Cultural Diversity in the United States': 'CD',
|
'Cultural Diversity in the United States': 'CD',
|
||||||
Ethics: 'E',
|
Ethics: 'E',
|
||||||
'Independent Inquiry': 'II',
|
'Independent Inquiry': 'II',
|
||||||
};
|
} as const satisfies Record<string, Flag>;
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
label: Flag;
|
label: Flag;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
import type { ThemeColor } from '@shared/util/themeColors';
|
||||||
import { Button } from '@views/components/common/Button/Button';
|
import { Button } from '@views/components/common/Button/Button';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import type { ThemeColor } from 'src/shared/util/themeColors';
|
|
||||||
|
|
||||||
import CheckIcon from '~icons/material-symbols/check';
|
import CheckIcon from '~icons/material-symbols/check';
|
||||||
|
|
||||||
@@ -24,12 +24,12 @@ interface ColorPatchProps {
|
|||||||
* is passed from the parent and updates the necessary parent state when this color patch is selected.
|
* is passed from the parent and updates the necessary parent state when this color patch is selected.
|
||||||
* @returns {JSX.Element} - the color patch component
|
* @returns {JSX.Element} - the color patch component
|
||||||
*/
|
*/
|
||||||
const ColorPatch: React.FC<ColorPatchProps> = ({
|
export default function ColorPatch({
|
||||||
color,
|
color,
|
||||||
index,
|
index,
|
||||||
selectedColor,
|
selectedColor,
|
||||||
handleSetSelectedColorPatch,
|
handleSetSelectedColorPatch,
|
||||||
}: ColorPatchProps): JSX.Element => {
|
}: ColorPatchProps): JSX.Element {
|
||||||
const isSelected = selectedColor === index;
|
const isSelected = selectedColor === index;
|
||||||
const handleClick = () => {
|
const handleClick = () => {
|
||||||
handleSetSelectedColorPatch(isSelected ? -1 : index);
|
handleSetSelectedColorPatch(isSelected ? -1 : index);
|
||||||
@@ -45,6 +45,4 @@ const ColorPatch: React.FC<ColorPatchProps> = ({
|
|||||||
{isSelected && <CheckIcon className='h-[20px] w-[20px]' />}
|
{isSelected && <CheckIcon className='h-[20px] w-[20px]' />}
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
|
|
||||||
export default ColorPatch;
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
|
import type { ThemeColor } from '@shared/util/themeColors';
|
||||||
|
import { getThemeColorHexByName } from '@shared/util/themeColors';
|
||||||
import { Button } from '@views/components/common/Button/Button';
|
import { Button } from '@views/components/common/Button/Button';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import type { ThemeColor } from 'src/shared/util/themeColors';
|
|
||||||
import { getThemeColorHexByName } from 'src/shared/util/themeColors';
|
|
||||||
|
|
||||||
import InvertColorsOffIcon from '~icons/material-symbols/invert-colors-off';
|
import InvertColorsOffIcon from '~icons/material-symbols/invert-colors-off';
|
||||||
|
|
||||||
@@ -16,228 +16,229 @@ interface Color {
|
|||||||
shades: ThemeColor[];
|
shades: ThemeColor[];
|
||||||
}
|
}
|
||||||
|
|
||||||
const colorPatches: Color[] = [
|
// TODO: Replace with UnoCSS theme
|
||||||
{
|
// const colorPatches: Color[] = [
|
||||||
baseColor: 'palette-slateBase',
|
// {
|
||||||
shades: [
|
// baseColor: 'palette-slateBase',
|
||||||
'palette-slate200',
|
// shades: [
|
||||||
'palette-slate300',
|
// 'palette-slate200',
|
||||||
'palette-slate400',
|
// 'palette-slate300',
|
||||||
'palette-slateBase',
|
// 'palette-slate400',
|
||||||
'palette-slate600',
|
// 'palette-slateBase',
|
||||||
'palette-slate700',
|
// 'palette-slate600',
|
||||||
],
|
// 'palette-slate700',
|
||||||
},
|
// ],
|
||||||
{
|
// },
|
||||||
baseColor: 'palette-grayBase',
|
// {
|
||||||
shades: [
|
// baseColor: 'palette-grayBase',
|
||||||
'palette-gray200',
|
// shades: [
|
||||||
'palette-gray300',
|
// 'palette-gray200',
|
||||||
'palette-gray400',
|
// 'palette-gray300',
|
||||||
'palette-grayBase',
|
// 'palette-gray400',
|
||||||
'palette-gray600',
|
// 'palette-grayBase',
|
||||||
'palette-gray700',
|
// 'palette-gray600',
|
||||||
],
|
// 'palette-gray700',
|
||||||
},
|
// ],
|
||||||
{
|
// },
|
||||||
baseColor: 'palette-stoneBase',
|
// {
|
||||||
shades: [
|
// baseColor: 'palette-stoneBase',
|
||||||
'palette-stone200',
|
// shades: [
|
||||||
'palette-stone300',
|
// 'palette-stone200',
|
||||||
'palette-stone400',
|
// 'palette-stone300',
|
||||||
'palette-stoneBase',
|
// 'palette-stone400',
|
||||||
'palette-stone600',
|
// 'palette-stoneBase',
|
||||||
'palette-stone700',
|
// 'palette-stone600',
|
||||||
],
|
// 'palette-stone700',
|
||||||
},
|
// ],
|
||||||
{
|
// },
|
||||||
baseColor: 'palette-redBase',
|
// {
|
||||||
shades: [
|
// baseColor: 'palette-redBase',
|
||||||
'palette-red200',
|
// shades: [
|
||||||
'palette-red300',
|
// 'palette-red200',
|
||||||
'palette-red400',
|
// 'palette-red300',
|
||||||
'palette-redBase',
|
// 'palette-red400',
|
||||||
'palette-red600',
|
// 'palette-redBase',
|
||||||
'palette-red700',
|
// 'palette-red600',
|
||||||
],
|
// 'palette-red700',
|
||||||
},
|
// ],
|
||||||
{
|
// },
|
||||||
baseColor: 'palette-orangeBase',
|
// {
|
||||||
shades: [
|
// baseColor: 'palette-orangeBase',
|
||||||
'palette-orange200',
|
// shades: [
|
||||||
'palette-orange300',
|
// 'palette-orange200',
|
||||||
'palette-orange400',
|
// 'palette-orange300',
|
||||||
'palette-orangeBase',
|
// 'palette-orange400',
|
||||||
'palette-orange600',
|
// 'palette-orangeBase',
|
||||||
'palette-orange700',
|
// 'palette-orange600',
|
||||||
],
|
// 'palette-orange700',
|
||||||
},
|
// ],
|
||||||
{
|
// },
|
||||||
baseColor: 'palette-amberBase',
|
// {
|
||||||
shades: [
|
// baseColor: 'palette-amberBase',
|
||||||
'palette-amber200',
|
// shades: [
|
||||||
'palette-amber300',
|
// 'palette-amber200',
|
||||||
'palette-amber400',
|
// 'palette-amber300',
|
||||||
'palette-amberBase',
|
// 'palette-amber400',
|
||||||
'palette-amber600',
|
// 'palette-amberBase',
|
||||||
'palette-amber700',
|
// 'palette-amber600',
|
||||||
],
|
// 'palette-amber700',
|
||||||
},
|
// ],
|
||||||
{
|
// },
|
||||||
baseColor: 'palette-yellowBase',
|
// {
|
||||||
shades: [
|
// baseColor: 'palette-yellowBase',
|
||||||
'palette-yellow200',
|
// shades: [
|
||||||
'palette-yellow300',
|
// 'palette-yellow200',
|
||||||
'palette-yellow400',
|
// 'palette-yellow300',
|
||||||
'palette-yellowBase',
|
// 'palette-yellow400',
|
||||||
'palette-yellow600',
|
// 'palette-yellowBase',
|
||||||
'palette-yellow700',
|
// 'palette-yellow600',
|
||||||
],
|
// 'palette-yellow700',
|
||||||
},
|
// ],
|
||||||
{
|
// },
|
||||||
baseColor: 'palette-limeBase',
|
// {
|
||||||
shades: [
|
// baseColor: 'palette-limeBase',
|
||||||
'palette-lime200',
|
// shades: [
|
||||||
'palette-lime300',
|
// 'palette-lime200',
|
||||||
'palette-lime400',
|
// 'palette-lime300',
|
||||||
'palette-limeBase',
|
// 'palette-lime400',
|
||||||
'palette-lime600',
|
// 'palette-limeBase',
|
||||||
'palette-lime700',
|
// 'palette-lime600',
|
||||||
],
|
// 'palette-lime700',
|
||||||
},
|
// ],
|
||||||
{
|
// },
|
||||||
baseColor: 'palette-greenBase',
|
// {
|
||||||
shades: [
|
// baseColor: 'palette-greenBase',
|
||||||
'palette-green200',
|
// shades: [
|
||||||
'palette-green300',
|
// 'palette-green200',
|
||||||
'palette-green400',
|
// 'palette-green300',
|
||||||
'palette-greenBase',
|
// 'palette-green400',
|
||||||
'palette-green600',
|
// 'palette-greenBase',
|
||||||
'palette-green700',
|
// 'palette-green600',
|
||||||
],
|
// 'palette-green700',
|
||||||
},
|
// ],
|
||||||
{
|
// },
|
||||||
baseColor: 'palette-emeraldBase',
|
// {
|
||||||
shades: [
|
// baseColor: 'palette-emeraldBase',
|
||||||
'palette-emerald200',
|
// shades: [
|
||||||
'palette-emerald300',
|
// 'palette-emerald200',
|
||||||
'palette-emerald400',
|
// 'palette-emerald300',
|
||||||
'palette-emeraldBase',
|
// 'palette-emerald400',
|
||||||
'palette-emerald600',
|
// 'palette-emeraldBase',
|
||||||
'palette-emerald700',
|
// 'palette-emerald600',
|
||||||
],
|
// 'palette-emerald700',
|
||||||
},
|
// ],
|
||||||
{
|
// },
|
||||||
baseColor: 'palette-tealBase',
|
// {
|
||||||
shades: [
|
// baseColor: 'palette-tealBase',
|
||||||
'palette-teal200',
|
// shades: [
|
||||||
'palette-teal300',
|
// 'palette-teal200',
|
||||||
'palette-teal400',
|
// 'palette-teal300',
|
||||||
'palette-tealBase',
|
// 'palette-teal400',
|
||||||
'palette-teal600',
|
// 'palette-tealBase',
|
||||||
'palette-teal700',
|
// 'palette-teal600',
|
||||||
],
|
// 'palette-teal700',
|
||||||
},
|
// ],
|
||||||
{
|
// },
|
||||||
baseColor: 'palette-cyanBase',
|
// {
|
||||||
shades: [
|
// baseColor: 'palette-cyanBase',
|
||||||
'palette-cyan200',
|
// shades: [
|
||||||
'palette-cyan300',
|
// 'palette-cyan200',
|
||||||
'palette-cyan400',
|
// 'palette-cyan300',
|
||||||
'palette-cyanBase',
|
// 'palette-cyan400',
|
||||||
'palette-cyan600',
|
// 'palette-cyanBase',
|
||||||
'palette-cyan700',
|
// 'palette-cyan600',
|
||||||
],
|
// 'palette-cyan700',
|
||||||
},
|
// ],
|
||||||
{
|
// },
|
||||||
baseColor: 'palette-skyBase',
|
// {
|
||||||
shades: [
|
// baseColor: 'palette-skyBase',
|
||||||
'palette-sky200',
|
// shades: [
|
||||||
'palette-sky300',
|
// 'palette-sky200',
|
||||||
'palette-sky400',
|
// 'palette-sky300',
|
||||||
'palette-skyBase',
|
// 'palette-sky400',
|
||||||
'palette-sky600',
|
// 'palette-skyBase',
|
||||||
'palette-sky700',
|
// 'palette-sky600',
|
||||||
],
|
// 'palette-sky700',
|
||||||
},
|
// ],
|
||||||
{
|
// },
|
||||||
baseColor: 'palette-blueBase',
|
// {
|
||||||
shades: [
|
// baseColor: 'palette-blueBase',
|
||||||
'palette-blue200',
|
// shades: [
|
||||||
'palette-blue300',
|
// 'palette-blue200',
|
||||||
'palette-blue400',
|
// 'palette-blue300',
|
||||||
'palette-blueBase',
|
// 'palette-blue400',
|
||||||
'palette-blue600',
|
// 'palette-blueBase',
|
||||||
'palette-blue700',
|
// 'palette-blue600',
|
||||||
],
|
// 'palette-blue700',
|
||||||
},
|
// ],
|
||||||
{
|
// },
|
||||||
baseColor: 'palette-indigoBase',
|
// {
|
||||||
shades: [
|
// baseColor: 'palette-indigoBase',
|
||||||
'palette-indigo200',
|
// shades: [
|
||||||
'palette-indigo300',
|
// 'palette-indigo200',
|
||||||
'palette-indigo400',
|
// 'palette-indigo300',
|
||||||
'palette-indigoBase',
|
// 'palette-indigo400',
|
||||||
'palette-indigo600',
|
// 'palette-indigoBase',
|
||||||
'palette-indigo700',
|
// 'palette-indigo600',
|
||||||
],
|
// 'palette-indigo700',
|
||||||
},
|
// ],
|
||||||
{
|
// },
|
||||||
baseColor: 'palette-violetBase',
|
// {
|
||||||
shades: [
|
// baseColor: 'palette-violetBase',
|
||||||
'palette-violet200',
|
// shades: [
|
||||||
'palette-violet300',
|
// 'palette-violet200',
|
||||||
'palette-violet400',
|
// 'palette-violet300',
|
||||||
'palette-violetBase',
|
// 'palette-violet400',
|
||||||
'palette-violet600',
|
// 'palette-violetBase',
|
||||||
'palette-violet700',
|
// 'palette-violet600',
|
||||||
],
|
// 'palette-violet700',
|
||||||
},
|
// ],
|
||||||
{
|
// },
|
||||||
baseColor: 'palette-purpleBase',
|
// {
|
||||||
shades: [
|
// baseColor: 'palette-purpleBase',
|
||||||
'palette-purple200',
|
// shades: [
|
||||||
'palette-purple300',
|
// 'palette-purple200',
|
||||||
'palette-purple400',
|
// 'palette-purple300',
|
||||||
'palette-purpleBase',
|
// 'palette-purple400',
|
||||||
'palette-purple600',
|
// 'palette-purpleBase',
|
||||||
'palette-purple700',
|
// 'palette-purple600',
|
||||||
],
|
// 'palette-purple700',
|
||||||
},
|
// ],
|
||||||
{
|
// },
|
||||||
baseColor: 'palette-fuschiaBase',
|
// {
|
||||||
shades: [
|
// baseColor: 'palette-fuschiaBase',
|
||||||
'palette-fuschia200',
|
// shades: [
|
||||||
'palette-fuschia300',
|
// 'palette-fuschia200',
|
||||||
'palette-fuschia400',
|
// 'palette-fuschia300',
|
||||||
'palette-fuschiaBase',
|
// 'palette-fuschia400',
|
||||||
'palette-fuschia600',
|
// 'palette-fuschiaBase',
|
||||||
'palette-fuschia700',
|
// 'palette-fuschia600',
|
||||||
],
|
// 'palette-fuschia700',
|
||||||
},
|
// ],
|
||||||
{
|
// },
|
||||||
baseColor: 'palette-pinkBase',
|
// {
|
||||||
shades: [
|
// baseColor: 'palette-pinkBase',
|
||||||
'palette-pink200',
|
// shades: [
|
||||||
'palette-pink300',
|
// 'palette-pink200',
|
||||||
'palette-pink400',
|
// 'palette-pink300',
|
||||||
'palette-pinkBase',
|
// 'palette-pink400',
|
||||||
'palette-pink600',
|
// 'palette-pinkBase',
|
||||||
'palette-pink700',
|
// 'palette-pink600',
|
||||||
],
|
// 'palette-pink700',
|
||||||
},
|
// ],
|
||||||
{
|
// },
|
||||||
baseColor: 'palette-roseBase',
|
// {
|
||||||
shades: [
|
// baseColor: 'palette-roseBase',
|
||||||
'palette-rose200',
|
// shades: [
|
||||||
'palette-rose300',
|
// 'palette-rose200',
|
||||||
'palette-rose400',
|
// 'palette-rose300',
|
||||||
'palette-roseBase',
|
// 'palette-rose400',
|
||||||
'palette-rose600',
|
// 'palette-roseBase',
|
||||||
'palette-rose700',
|
// 'palette-rose600',
|
||||||
],
|
// 'palette-rose700',
|
||||||
},
|
// ],
|
||||||
];
|
// },
|
||||||
|
// ];
|
||||||
|
|
||||||
const hexCodeToBaseColorPatchIndex = new Map(
|
const hexCodeToBaseColorPatchIndex = new Map(
|
||||||
colorPatches.map((color: Color, index: number) => [getThemeColorHexByName(color.baseColor), index])
|
colorPatches.map((color: Color, index: number) => [getThemeColorHexByName(color.baseColor), index])
|
||||||
@@ -278,9 +279,9 @@ export interface CourseCellColorPickerProps {
|
|||||||
* This component is available when a user hovers over a course cell in their calendar to
|
* This component is available when a user hovers over a course cell in their calendar to
|
||||||
* color for the course cell. The user can set any valid hex color they want.
|
* color for the course cell. The user can set any valid hex color they want.
|
||||||
*/
|
*/
|
||||||
const CourseCellColorPicker: React.FC<CourseCellColorPickerProps> = ({
|
export default function CourseCellColorPicker({
|
||||||
setSelectedColor: setFinalColor,
|
setSelectedColor: setFinalColor,
|
||||||
}: CourseCellColorPickerProps): JSX.Element => {
|
}: CourseCellColorPickerProps): JSX.Element {
|
||||||
const [selectedBaseColorPatch, setSelectedBaseColorPatch] = React.useState<number>(-1);
|
const [selectedBaseColorPatch, setSelectedBaseColorPatch] = React.useState<number>(-1);
|
||||||
const [selectedShadeColorPatch, setSelectShadeColorPatch] = React.useState<number>(-1);
|
const [selectedShadeColorPatch, setSelectShadeColorPatch] = React.useState<number>(-1);
|
||||||
const [hexCode, setHexCode] = React.useState<string>('');
|
const [hexCode, setHexCode] = React.useState<string>('');
|
||||||
@@ -387,7 +388,4 @@ const CourseCellColorPicker: React.FC<CourseCellColorPickerProps> = ({
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
}
|
||||||
};
|
|
||||||
|
|
||||||
export default CourseCellColorPicker;
|
|
||||||
@@ -15,8 +15,6 @@ interface ItemWrapperProps {
|
|||||||
* @param {React.ReactNode} props.children - the children to be wrapped in the div
|
* @param {React.ReactNode} props.children - the children to be wrapped in the div
|
||||||
* @returns {JSX.Element} - the div wrapper component
|
* @returns {JSX.Element} - the div wrapper component
|
||||||
*/
|
*/
|
||||||
const DivWrapper: React.FC<ItemWrapperProps> = ({ children }: ItemWrapperProps) => (
|
export default function DivWrapper({ children }: ItemWrapperProps): JSX.Element {
|
||||||
<div className='h-[26px] w-[26px] flex items-center justify-center p-[2px]'>{children}</div>
|
return <div className='h-[26px] w-[26px] flex items-center justify-center p-[2px]'>{children}</div>;
|
||||||
);
|
}
|
||||||
|
|
||||||
export default DivWrapper;
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
import { getThemeColorHexByName } from '@shared/util/themeColors';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { getThemeColorHexByName } from 'src/shared/util/themeColors';
|
|
||||||
|
|
||||||
import TagIcon from '~icons/material-symbols/tag';
|
import TagIcon from '~icons/material-symbols/tag';
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@ export interface HexColorEditorProps {
|
|||||||
* @param {React.Dispatch<React.SetStateAction<string>>} props.setHexCode - set state fn to control the hex color code from parent
|
* @param {React.Dispatch<React.SetStateAction<string>>} props.setHexCode - set state fn to control the hex color code from parent
|
||||||
* @returns {JSX.Element} - the hex color editor component
|
* @returns {JSX.Element} - the hex color editor component
|
||||||
*/
|
*/
|
||||||
const HexColorEditor: React.FC<HexColorEditorProps> = ({ hexCode, setHexCode }: HexColorEditorProps): JSX.Element => {
|
export default function HexColorEditor({ hexCode, setHexCode }: HexColorEditorProps): JSX.Element {
|
||||||
const baseColor = React.useMemo(() => getThemeColorHexByName('ut-gray'), []);
|
const baseColor = React.useMemo(() => getThemeColorHexByName('ut-gray'), []);
|
||||||
const previewColor = hexCode.length === 6 ? `#${hexCode}` : baseColor;
|
const previewColor = hexCode.length === 6 ? `#${hexCode}` : baseColor;
|
||||||
|
|
||||||
@@ -43,6 +43,4 @@ const HexColorEditor: React.FC<HexColorEditorProps> = ({ hexCode, setHexCode }:
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
|
|
||||||
export default HexColorEditor;
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
import type { ThemeColor } from '@shared/util/themeColors';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import type { ThemeColor } from 'src/shared/util/themeColors';
|
|
||||||
|
|
||||||
import ColorPatch from './ColorPatch';
|
import ColorPatch from './ColorPatch';
|
||||||
import DivWrapper from './DivWrapper';
|
import DivWrapper from './DivWrapper';
|
||||||
@@ -22,11 +22,7 @@ interface HuePickerProps {
|
|||||||
* @param {React.Dispatch<React.SetStateAction<number>>} props.setSelectedColor - set state fn to control the selected color patch from parent
|
* @param {React.Dispatch<React.SetStateAction<number>>} props.setSelectedColor - set state fn to control the selected color patch from parent
|
||||||
* @returns {JSX.Element} - the hue picker component
|
* @returns {JSX.Element} - the hue picker component
|
||||||
*/
|
*/
|
||||||
const HuePicker: React.FC<HuePickerProps> = ({
|
export default function HuePicker({ shades, selectedColor, setSelectedColor }: HuePickerProps): JSX.Element {
|
||||||
shades,
|
|
||||||
selectedColor,
|
|
||||||
setSelectedColor,
|
|
||||||
}: HuePickerProps): JSX.Element => {
|
|
||||||
const numColumns = 6;
|
const numColumns = 6;
|
||||||
return (
|
return (
|
||||||
<div className='flex gap-0 flex-content-between'>
|
<div className='flex gap-0 flex-content-between'>
|
||||||
@@ -42,6 +38,4 @@ const HuePicker: React.FC<HuePickerProps> = ({
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
|
|
||||||
export default HuePicker;
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import type { Color } from '@views/styles/colors.module.scss';
|
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
@@ -32,7 +31,7 @@ export type DividerProps = {
|
|||||||
* <Divider size="19px" orientation="horizontal" />
|
* <Divider size="19px" orientation="horizontal" />
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
export default function Divider({ className, testId, size, orientation }: DividerProps) {
|
export default function Divider({ className, testId, size, orientation }: DividerProps): JSX.Element {
|
||||||
const style: React.CSSProperties =
|
const style: React.CSSProperties =
|
||||||
orientation === 'horizontal'
|
orientation === 'horizontal'
|
||||||
? { width: size, borderBottomWidth: '1px' }
|
? { width: size, borderBottomWidth: '1px' }
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ export default function Dropdown(props: Props) {
|
|||||||
|
|
||||||
const schedules = props.dummySchedules;
|
const schedules = props.dummySchedules;
|
||||||
if (schedules == null) {
|
if (schedules == null) {
|
||||||
|
// TODO
|
||||||
// if no dummy values passed in
|
// if no dummy values passed in
|
||||||
// useSchedules hook here
|
// useSchedules hook here
|
||||||
}
|
}
|
||||||
@@ -40,6 +41,7 @@ export default function Dropdown(props: Props) {
|
|||||||
toggle(!expanded);
|
toggle(!expanded);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO
|
||||||
// WIP function to swap schedules. Prefer to use the hook when in production
|
// WIP function to swap schedules. Prefer to use the hook when in production
|
||||||
const switchSchedule = (index: number) => {
|
const switchSchedule = (index: number) => {
|
||||||
const scheduleToSwitchTo = schedules[index];
|
const scheduleToSwitchTo = schedules[index];
|
||||||
@@ -91,12 +93,8 @@ export default function Dropdown(props: Props) {
|
|||||||
leave='transition duration-75 ease-out'
|
leave='transition duration-75 ease-out'
|
||||||
leaveFrom='transform scale-100 opacity-100'
|
leaveFrom='transform scale-100 opacity-100'
|
||||||
leaveTo='transform scale-95 opacity-0'
|
leaveTo='transform scale-95 opacity-0'
|
||||||
beforeEnter={() => {
|
beforeEnter={toggleSwitch}
|
||||||
toggleSwitch();
|
afterLeave={toggleSwitch}
|
||||||
}}
|
|
||||||
afterLeave={() => {
|
|
||||||
toggleSwitch();
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<Disclosure.Panel>
|
<Disclosure.Panel>
|
||||||
<List
|
<List
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ interface Props {
|
|||||||
/**
|
/**
|
||||||
* A wrapper component for the extension elements that adds some basic styling to them
|
* A wrapper component for the extension elements that adds some basic styling to them
|
||||||
*/
|
*/
|
||||||
export default function ExtensionRoot(props: React.PropsWithChildren<Props>) {
|
export default function ExtensionRoot(props: React.PropsWithChildren<Props>): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<div className={styles.extensionRoot} data-testid={props.testId}>
|
<div className={styles.extensionRoot} data-testid={props.testId}>
|
||||||
{props.children}
|
{props.children}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import styles from './Icon.module.scss';
|
|||||||
import type { MaterialIconCode } from './MaterialIcons';
|
import type { MaterialIconCode } from './MaterialIcons';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Props for the Icon component.
|
||||||
*/
|
*/
|
||||||
export type Props = {
|
export type Props = {
|
||||||
name: MaterialIconCode;
|
name: MaterialIconCode;
|
||||||
@@ -27,7 +27,7 @@ export type Props = {
|
|||||||
* This is a reusable Icon component that uses the Material Icons Round font internally
|
* This is a reusable Icon component that uses the Material Icons Round font internally
|
||||||
* You can find the list of icons here: https://fonts.google.com/icons?selected=Material+Icons+Round
|
* You can find the list of icons here: https://fonts.google.com/icons?selected=Material+Icons+Round
|
||||||
*/
|
*/
|
||||||
export default function Icon(props: Props) {
|
export default function Icon(props: Props): JSX.Element {
|
||||||
const style = props.style || {};
|
const style = props.style || {};
|
||||||
|
|
||||||
style.color ??= colors?.[props.color ?? 'charcoal'];
|
style.color ??= colors?.[props.color ?? 'charcoal'];
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ interface Props {
|
|||||||
* A maybe reusable InfoCard component that follows the design system of the extension.
|
* A maybe reusable InfoCard component that follows the design system of the extension.
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export function InfoCard({ titleText, bodyText }: React.PropsWithChildren<Props>): JSX.Element {
|
export default function InfoCard({ titleText, bodyText }: React.PropsWithChildren<Props>): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className='w-50 flex flex-col items-start justify-center border rounded p-4'
|
className='w-50 flex flex-col items-start justify-center border rounded p-4'
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ type Props = Omit<TextProps, 'span'> & {
|
|||||||
/**
|
/**
|
||||||
* A reusable Text component with props that build on top of the design system for the extension
|
* A reusable Text component with props that build on top of the design system for the extension
|
||||||
*/
|
*/
|
||||||
export default function Link(props: PropsWithChildren<Props>) {
|
export default function Link(props: PropsWithChildren<Props>): JSX.Element {
|
||||||
let passedProps = {
|
let passedProps = {
|
||||||
...props,
|
...props,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { DragDropContext, Draggable, Droppable } from '@hello-pangea/dnd';
|
import { DragDropContext, Draggable, Droppable } from '@hello-pangea/dnd';
|
||||||
import type { ReactElement } from 'react';
|
import type { ReactElement } from 'react';
|
||||||
import React, { useCallback, useEffect, useState } from 'react';
|
import React, { useCallback, useEffect, useState } from 'react';
|
||||||
|
import { satisfies } from 'semver';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Ctrl + f dragHandleProps on PopupCourseBlock.tsx for example implementation of drag handle (two lines of code)
|
* Ctrl + f dragHandleProps on PopupCourseBlock.tsx for example implementation of drag handle (two lines of code)
|
||||||
@@ -11,7 +12,7 @@ import React, { useCallback, useEffect, useState } from 'react';
|
|||||||
* Props for the List component.
|
* Props for the List component.
|
||||||
*/
|
*/
|
||||||
export interface ListProps {
|
export interface ListProps {
|
||||||
draggableElements: any[]; // Will later define draggableElements based on what types
|
draggableElements: any[]; // TODO: Will later define draggableElements based on what types
|
||||||
// of components are draggable.
|
// of components are draggable.
|
||||||
itemHeight: number;
|
itemHeight: number;
|
||||||
listHeight: number;
|
listHeight: number;
|
||||||
@@ -82,7 +83,13 @@ const Row: React.FC<RowProps> = React.memo(({ data: { items, gap }, index, style
|
|||||||
* @example
|
* @example
|
||||||
* <List draggableElements={elements} />
|
* <List draggableElements={elements} />
|
||||||
*/
|
*/
|
||||||
const List: React.FC<ListProps> = ({ draggableElements, itemHeight, listHeight, listWidth, gap = 12 }: ListProps) => {
|
export default function List({
|
||||||
|
draggableElements,
|
||||||
|
itemHeight,
|
||||||
|
listHeight,
|
||||||
|
listWidth,
|
||||||
|
gap = 12,
|
||||||
|
}: ListProps): JSX.Element {
|
||||||
const [items, setItems] = useState(() => initial(0, draggableElements));
|
const [items, setItems] = useState(() => initial(0, draggableElements));
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -105,7 +112,7 @@ const List: React.FC<ListProps> = ({ draggableElements, itemHeight, listHeight,
|
|||||||
|
|
||||||
const newItems = reorder(items, result.source.index, result.destination.index);
|
const newItems = reorder(items, result.source.index, result.destination.index);
|
||||||
|
|
||||||
setItems(newItems as { id: string; content: React.ReactElement }[]);
|
setItems(newItems satisfies { id: string; content: React.ReactElement }[]);
|
||||||
},
|
},
|
||||||
[items]
|
[items]
|
||||||
);
|
);
|
||||||
@@ -170,6 +177,4 @@ const List: React.FC<ListProps> = ({ draggableElements, itemHeight, listHeight,
|
|||||||
</DragDropContext>
|
</DragDropContext>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
|
|
||||||
export default List;
|
|
||||||
|
|||||||
@@ -15,9 +15,15 @@ interface Props {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* A reusable popup component that can be used to display content on the page
|
* A reusable popup component that can be used to display content on the page
|
||||||
* @returns
|
|
||||||
*/
|
*/
|
||||||
export default function Popup({ onClose, children, className, style, testId, overlay }: PropsWithChildren<Props>) {
|
export default function Popup({
|
||||||
|
onClose,
|
||||||
|
children,
|
||||||
|
className,
|
||||||
|
style,
|
||||||
|
testId,
|
||||||
|
overlay,
|
||||||
|
}: PropsWithChildren<Props>): JSX.Element {
|
||||||
const containerRef = React.useRef<HTMLDivElement>(null);
|
const containerRef = React.useRef<HTMLDivElement>(null);
|
||||||
const bodyRef = React.useRef<HTMLDivElement>(null);
|
const bodyRef = React.useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
|
|||||||
@@ -18,11 +18,9 @@ export type Props = {
|
|||||||
/**
|
/**
|
||||||
* This is a reusable dropdown component that can be used to toggle the visiblity of information
|
* This is a reusable dropdown component that can be used to toggle the visiblity of information
|
||||||
*/
|
*/
|
||||||
export default function ScheduleListItem(props: Props) {
|
export default function ScheduleListItem({ style, active, name, dragHandleProps, onClick }: Props): JSX.Element {
|
||||||
const { dragHandleProps, onClick } = props;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{ ...props.style }} className='items-center'>
|
<div style={{ ...style }} className='items-center'>
|
||||||
<li className='w-100% flex cursor-pointer items-center self-stretch justify-left text-ut-burntorange'>
|
<li className='w-100% flex cursor-pointer items-center self-stretch justify-left text-ut-burntorange'>
|
||||||
<div className='group flex justify-center'>
|
<div className='group flex justify-center'>
|
||||||
<div
|
<div
|
||||||
@@ -40,12 +38,12 @@ export default function ScheduleListItem(props: Props) {
|
|||||||
className={clsx(
|
className={clsx(
|
||||||
'bg-current h-3 w-3 rounded-full transition tansform scale-100 ease-out-expo duration-250',
|
'bg-current h-3 w-3 rounded-full transition tansform scale-100 ease-out-expo duration-250',
|
||||||
{
|
{
|
||||||
'scale-0! opacity-0 ease-in-out! duration-200!': !props.active,
|
'scale-0! opacity-0 ease-in-out! duration-200!': !active,
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<Text variant='p'>{props.name}</Text>
|
<Text variant='p'>{name}</Text>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
@@ -12,6 +12,6 @@ type Props = {
|
|||||||
/**
|
/**
|
||||||
* A simple spinner component that can be used to indicate loading.
|
* A simple spinner component that can be used to indicate loading.
|
||||||
*/
|
*/
|
||||||
export default function Spinner({ className, testId, style }: Props) {
|
export default function Spinner({ className, testId, style }: Props): JSX.Element {
|
||||||
return <div data-testid={testId} style={style} className={clsx(styles.spinner, className)} />;
|
return <div data-testid={testId} style={style} className={clsx(styles.spinner, className)} />;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import React from 'react';
|
|||||||
import styles from './Text.module.scss';
|
import styles from './Text.module.scss';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Props for the Text component.
|
||||||
*/
|
*/
|
||||||
export type TextProps = {
|
export type TextProps = {
|
||||||
variant?: Variant;
|
variant?: Variant;
|
||||||
@@ -21,7 +21,7 @@ type Variant = (typeof variants)[number];
|
|||||||
/**
|
/**
|
||||||
* A reusable Text component with props that build on top of the design system for the extension
|
* A reusable Text component with props that build on top of the design system for the extension
|
||||||
*/
|
*/
|
||||||
export default function Text({ variant, as, className, ...props }: PropsWithChildren<TextProps>) {
|
export default function Text({ variant, as, className, ...props }: PropsWithChildren<TextProps>): JSX.Element {
|
||||||
const mergedClassName = clsx(styles.text, styles[variant], className);
|
const mergedClassName = clsx(styles.text, styles[variant], className);
|
||||||
|
|
||||||
if (as === 'div') return <div className={mergedClassName} {...props} />;
|
if (as === 'div') return <div className={mergedClassName} {...props} />;
|
||||||
|
|||||||
Reference in New Issue
Block a user