chore: switch classnames for clsx

This commit is contained in:
ryan 2023-08-31 00:42:21 +08:00
parent d8d10f908e
commit aac4a2d14c
25 changed files with 48 additions and 56 deletions

View File

@ -15,7 +15,7 @@
".microrc.development": "jsonc"
},
"tailwindCSS.experimental.classRegex": [
["classNames\\(([^)]*)\\)", "'([^']*)'", "\"([^']*)\""],
["clsx\\(([^)]*)\\)", "'([^']*)'", "\"([^']*)\""],
[":\\s*?[\"'`]([^\"'`]*).*?,"],
["baseStyle.=.[\"'`]([^\"'`]*)"],
// Enum = 'value'

View File

@ -20,7 +20,6 @@
"@ryanke/pandora": "^0.0.9",
"@tailwindcss/typography": "^0.5.9",
"autoprefixer": "^10.4.15",
"classnames": "^2.3.2",
"clsx": "^2.0.0",
"concurrently": "^8.2.1",
"copy-to-clipboard": "^3.3.3",

View File

@ -1,5 +1,5 @@
/* eslint-disable react/no-danger */
import classNames from 'classnames';
import clsx from 'clsx';
import * as avatar from 'generate-avatar';
import type { FC } from 'react';
import { useEffect, useMemo, useRef } from 'react';
@ -10,7 +10,7 @@ export interface AvatarProps {
}
export const Avatar: FC<AvatarProps> = (props) => {
const classes = classNames('overflow-hidden rounded-full select-none', props.className);
const classes = clsx('overflow-hidden rounded-full select-none', props.className);
const containerRef = useRef<HTMLDivElement>(null);
const svg = useMemo(() => {
return avatar.generateFromString(props.userId);

View File

@ -1,5 +1,5 @@
import { Menu } from '@headlessui/react';
import classNames from 'classnames';
import clsx from 'clsx';
import type { FC, ReactNode } from 'react';
import { Fragment } from 'react';
import { Link } from '../link';
@ -13,12 +13,12 @@ export interface DropdownTabProps {
export const DropdownTab: FC<DropdownTabProps> = ({ href, className, children, onClick }) => {
const props = href ? { as: Link, href: href } : { as: Fragment };
const base = classNames('px-3 py-2 my-1 text-gray-400 transition ease-in-out border-none cursor-pointer', className);
const base = clsx('px-3 py-2 my-1 text-gray-400 transition ease-in-out border-none cursor-pointer', className);
return (
<Menu.Item {...(props as any)}>
{({ active }) => (
<div className={classNames(base, active && 'text-white bg-dark-800')} onClick={onClick}>
<div className={clsx(base, active && 'text-white bg-dark-800')} onClick={onClick}>
{children}
</div>
)}

View File

@ -1,5 +1,5 @@
import { Menu, Transition } from '@headlessui/react';
import classNames from 'classnames';
import clsx from 'clsx';
import type { FC, ReactNode } from 'react';
import React, { Fragment } from 'react';
@ -10,7 +10,7 @@ export interface DropdownProps {
}
export const Dropdown: FC<DropdownProps> = ({ trigger, children, className }) => {
const itemsClasses = classNames(
const itemsClasses = clsx(
'absolute right-0 mt-2 overflow-y-auto rounded-md shadow-2xl bg-dark-300 focus:outline-none max-h-56 min-w-[10em]',
className
);

View File

@ -1,9 +1,9 @@
import classNames from 'classnames';
import clsx from 'clsx';
import { BASE_EMBED_CLASSES, MAX_HEIGHT } from '../embed';
import type { Embeddable } from '../embeddable';
export const EmbedDefault = ({ data }: { data: Embeddable }) => {
const classes = classNames(
const classes = clsx(
'flex flex-col items-center justify-center w-full select-none h-44',
BASE_EMBED_CLASSES,
MAX_HEIGHT

View File

@ -1,12 +1,12 @@
import classNames from 'classnames';
import clsx from 'clsx';
import Head from 'next/head';
import { Fragment } from 'react';
import { BASE_EMBED_CLASSES, MAX_HEIGHT } from '../embed';
import type { Embeddable } from '../embeddable';
export const EmbedImage = ({ data }: { data: Embeddable }) => {
const imageClasses = classNames(`object-contain`, MAX_HEIGHT);
const containerClasses = classNames(
const imageClasses = clsx(`object-contain`, MAX_HEIGHT);
const containerClasses = clsx(
'flex items-center justify-center relative overflow-hidden',
BASE_EMBED_CLASSES,
MAX_HEIGHT

View File

@ -4,13 +4,13 @@ import { PageLoader } from '../../page-loader';
import { EmbedDefault } from './embed-default';
import type { Embeddable } from '../embeddable';
import { textFetcher } from '../text-fetcher';
import classNames from 'classnames';
import clsx from 'clsx';
import { BASE_EMBED_CLASSES } from '../embed';
export const EmbedMarkdown = ({ data }: { data: Embeddable }) => {
const swrContent = useSWR<string>(data.content ? null : data.paths.direct, { fetcher: textFetcher });
const content = data.content ?? swrContent;
const classes = classNames('p-4', BASE_EMBED_CLASSES);
const classes = clsx('p-4', BASE_EMBED_CLASSES);
if (content.error) {
return <EmbedDefault data={data} />;

View File

@ -1,9 +1,9 @@
import classNames from 'classnames';
import clsx from 'clsx';
import { BASE_EMBED_CLASSES, MAX_HEIGHT } from '../embed';
import type { Embeddable } from '../embeddable';
export const EmbedVideo = ({ file }: { file: Embeddable }) => {
const classes = classNames('outline-none', BASE_EMBED_CLASSES, MAX_HEIGHT);
const classes = clsx('outline-none', BASE_EMBED_CLASSES, MAX_HEIGHT);
return (
<video
controls

View File

@ -1,5 +1,5 @@
import { Button, ButtonStyle, Container, useAsync, useOnClickOutside, useToasts } from '@ryanke/pandora';
import classNames from 'classnames';
import clsx from 'clsx';
import { Fragment, memo, useRef, useState } from 'react';
import { Crop } from 'react-feather';
import { useResendVerificationEmailMutation } from '../../generated/graphql';
@ -19,7 +19,7 @@ export const Header = memo(() => {
const [email, setEmail] = useState('');
const createToast = useToasts();
const [resent, setResent] = useState(false);
const classes = classNames(
const classes = clsx(
'relative z-20 flex items-center justify-between h-16 my-auto transition',
paths.loading && 'pointer-events-none invisible'
);

View File

@ -1,4 +1,4 @@
import classNames from 'classnames';
import clsx from 'clsx';
import type { FormikContextType } from 'formik';
import { FormikContext } from 'formik';
import type { ReactNode } from 'react';
@ -41,7 +41,7 @@ export function InputContainer<T extends InputChildPropsBase>({
const formik = useContext<FormikContextType<any>>(FormikContext);
const errorMessage = !!(formik && id && formik.touched[id]) && (formik.errors[id] as string);
if (errorMessage) style = InputStyle.Error;
const childClasses = classNames(
const childClasses = clsx(
'w-full h-full px-3 py-2 rounded outline-none border transition duration-75',
maxHeight && 'max-h-[calc(2.65em-2px)]',
style,

View File

@ -1,4 +1,4 @@
import classNames from 'classnames';
import clsx from 'clsx';
import type { SelectHTMLAttributes } from 'react';
import React from 'react';
import { ChevronDown } from 'react-feather';
@ -11,7 +11,7 @@ export const Select = React.forwardRef<HTMLSelectElement, SelectProps>(({ classN
return (
<InputContainer className={className} childProps={delegated}>
{({ childClasses, ...rest }) => {
const classes = classNames(className, childClasses, 'appearance-none pr-8');
const classes = clsx(className, childClasses, 'appearance-none pr-8');
return (
<div className="relative select-none">
<select className={classes} ref={ref} {...rest}>

View File

@ -1,4 +1,4 @@
import classNames from 'classnames';
import clsx from 'clsx';
import type { TextareaHTMLAttributes } from 'react';
import React from 'react';
import type { InputChildProps } from './container';
@ -10,7 +10,7 @@ export const TextArea = React.forwardRef<HTMLTextAreaElement, TextAreaProps>(({
return (
<InputContainer className={className} maxHeight={false} childProps={delegated}>
{({ childClasses, ...rest }) => {
const classes = classNames(childClasses, 'h-[50vh]');
const classes = clsx(childClasses, 'h-[50vh]');
return <textarea {...rest} className={classes} ref={ref} />;
}}
</InputContainer>

View File

@ -1,4 +1,4 @@
import classNames from 'classnames';
import clsx from 'clsx';
import type { Language } from 'prism-react-renderer';
import { Fragment, memo } from 'react';
import ReactMarkdown from 'react-markdown';
@ -8,7 +8,7 @@ import { SyntaxHighlighter } from './syntax-highlighter/syntax-highlighter';
const LANGUAGE_REGEX = /(^| )language-(?<language>.+)$/u;
export const Markdown = memo<{ children: string; className?: string }>(({ children, className }) => {
const classes = classNames(
const classes = clsx(
'prose prose-invert max-w-none',
// remove "" quotes from blockquotes
'prose-p:before:content-none prose-p:after:content-none',

View File

@ -1,4 +1,4 @@
import classNames from 'classnames';
import clsx from 'clsx';
import type { FC } from 'react';
import { Fragment } from 'react';
import { Ping } from './ping';
@ -18,7 +18,7 @@ export const Steps: FC<StepsProps> = ({ steps, stepIndex }) => {
{index !== 0 && <div className="h-px w-8 mx-4 bg-gray-800" />}
<div className="flex items-center gap-2">
<Ping active={isActive} />
<div className={classNames(!isActive && 'text-gray-400')}>{step}</div>
<div className={clsx(!isActive && 'text-gray-400')}>{step}</div>
</div>
</Fragment>
);

View File

@ -1,4 +1,4 @@
import classNames from 'classnames';
import clsx from 'clsx';
import type { Language } from 'prism-react-renderer';
import { Highlight } from 'prism-react-renderer';
import type { HTMLProps } from 'react';
@ -21,7 +21,7 @@ export const SyntaxHighlighter = memo<SyntaxHighlighterProps>(
<Highlight theme={theme} code={trimmed} language={language}>
{({ className: highlighterClasses, style, tokens, getLineProps, getTokenProps }) => {
console.log(highlighterClasses);
const containerClasses = classNames(
const containerClasses = clsx(
'text-left overflow-x-auto h-full relative',
highlighterClasses,
additionalClasses

View File

@ -1,4 +1,4 @@
import classNames from 'classnames';
import clsx from 'clsx';
export interface ToggleOption<T = unknown> {
label: string;
@ -22,7 +22,7 @@ export function Toggle<T extends string | number | boolean>({
<div className="inline-flex items-center overflow-hidden select-none bg-black text-gray-400 rounded-full">
{options.map((item) => {
const active = item.value === selected;
const classes = classNames(
const classes = clsx(
'rounded-full px-4 py-1 text-sm cursor-pointer h-full',
active ? 'text-white' : 'hover:bg-dark-200',
active && backgroundColour

View File

@ -1,4 +1,4 @@
import classNames from 'classnames';
import clsx from 'clsx';
import type { HTMLAttributes } from 'react';
import { forwardRef } from 'react';
import { Avatar } from './avatar';
@ -10,7 +10,7 @@ export interface UserPillProps extends HTMLAttributes<HTMLDivElement> {
export const UserPill = forwardRef<HTMLDivElement, UserPillProps>(
({ userId: id, username, className, ...rest }, ref) => {
const classes = classNames(
const classes = clsx(
'flex items-center px-2 py-1 transition rounded-full shadow-lg cursor-pointer select-none align-center bg-dark-600 hover:bg-dark-900 hover:text-white',
className
);

View File

@ -1,5 +1,5 @@
import { Container, Spinner } from '@ryanke/pandora';
import classNames from 'classnames';
import clsx from 'clsx';
import { Fragment, useState } from 'react';
import { Download } from 'react-feather';
import { Section } from '../../components/section';
@ -93,7 +93,7 @@ export const ConfigGenerator = () => {
<div className="grid grid-cols-2 md:grid-cols-3 gap-2 mt-2">
{config.data.hosts.map((host) => {
const isSelected = selectedHosts.includes(host.normalised);
const classes = classNames(
const classes = clsx(
'rounded px-2 py-1 truncate transition border border-transparent',
isSelected && 'bg-purple-600 text-white',
!isSelected && 'text-gray-400 bg-dark-100 hover:bg-dark-200 hover:text-white'
@ -124,7 +124,7 @@ export const ConfigGenerator = () => {
<button
type="submit"
onClick={download}
className={classNames(
className={clsx(
'mt-8 ml-auto flex items-center gap-1',
downloadable ? 'text-purple-400 hover:underline' : 'text-gray-700 cursor-not-allowed'
)}

View File

@ -1,4 +1,4 @@
import classNames from 'classnames';
import clsx from 'clsx';
import { memo } from 'react';
import { Link } from '../../../components/link';
import { Time } from '../../../components/time';
@ -13,7 +13,7 @@ export const PasteCard = memo<PasteCardProps>(({ paste }) => {
const user = useUser();
const showUrl = !paste.encrypted && user.data;
const url = showUrl ? (paste.burn ? `${paste.urls.view}?burn_unless=${user.data.id}` : paste.urls.view) : '#';
const containerClasses = classNames(!showUrl && 'cursor-not-allowed');
const containerClasses = clsx(!showUrl && 'cursor-not-allowed');
const modifiers: string[] = [paste.type];
if (paste.burn) modifiers.push('burn');
if (paste.encrypted) modifiers.push('encrypted');

View File

@ -1,5 +1,5 @@
import { useAsync } from '@ryanke/pandora';
import classNames from 'classnames';
import clsx from 'clsx';
import { Form, Formik } from 'formik';
import { useRouter } from 'next/router';
import type { FC } from 'react';
@ -59,7 +59,7 @@ export const LoginForm: FC = () => {
login({ ...loginInfo, otp });
}}
/>
<span className={classNames(`text-xs text-center`, invalidOTP ? 'text-red-400' : 'text-gray-600')}>
<span className={clsx(`text-xs text-center`, invalidOTP ? 'text-red-400' : 'text-gray-600')}>
{invalidOTP ? 'Invalid OTP code' : 'Enter the OTP code from your authenticator app'}
</span>
</div>

View File

@ -1,5 +1,5 @@
import { Button, ButtonStyle, Container, useAsync, useToasts } from '@ryanke/pandora';
import classNames from 'classnames';
import clsx from 'clsx';
import { useRouter } from 'next/router';
import { QRCodeSVG } from 'qrcode.react';
import { Fragment, useCallback, useEffect, useMemo, useState } from 'react';
@ -146,7 +146,7 @@ export default function Generate() {
type="button"
onClick={() => setCurrentStep((prev) => prev - 1)}
disabled={currentStep === 0}
className={classNames(
className={clsx(
`text-gray-400 flex items-center gap-1 hover:underline`,
currentStep === 0 && 'opacity-0 pointer-events-none'
)}

View File

@ -1,5 +1,5 @@
import { Container, Spinner, useAsync, useToasts } from '@ryanke/pandora';
import classNames from 'classnames';
import clsx from 'clsx';
import copyToClipboard from 'copy-to-clipboard';
import type { GetServerSidePropsContext } from 'next';
import { useRouter } from 'next/router';
@ -20,7 +20,7 @@ const FileOption: FC<{ children: ReactNode; className?: string; onClick: () => v
className,
onClick,
}) => {
const classes = classNames(
const classes = clsx(
'flex items-center gap-2 shrink-0 transition-colors duration-100 hover:text-gray-300',
className
);

View File

@ -1,9 +1,9 @@
import classNames from 'classnames';
import clsx from 'clsx';
import { type FC, type ReactNode } from 'react';
import { Info } from 'react-feather';
export const Warning: FC<{ children: ReactNode; className?: string }> = ({ children, className }) => {
const classes = classNames(
const classes = clsx(
'bg-purple-400 bg-opacity-40 border border-purple-400 px-2 py-1 rounded text-sm flex items-center gap-2',
className
);

View File

@ -222,9 +222,6 @@ importers:
autoprefixer:
specifier: ^10.4.15
version: 10.4.15(postcss@8.4.29)
classnames:
specifier: ^2.3.2
version: 2.3.2
clsx:
specifier: ^2.0.0
version: 2.0.0
@ -4766,10 +4763,6 @@ packages:
validator: 13.9.0
dev: false
/classnames@2.3.2:
resolution: {integrity: sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==}
dev: false
/clean-regexp@1.0.0:
resolution: {integrity: sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==}
engines: {node: '>=4'}