Replace classnames with clsx (#634)

[`clsx`](https://www.npmjs.com/package/clsx) is a drop-in replacement
for `classnames` that is a quarter of the size and is faster.
This commit is contained in:
Evan Simkowitz
2024-05-02 11:40:44 -07:00
committed by GitHub
parent e973a6ff8f
commit ea0cf62b67
45 changed files with 142 additions and 155 deletions
+1 -2
View File
@@ -26,7 +26,7 @@
"@tanstack/react-table": "^8.10.3",
"autobind-decorator": "^2.4.0",
"base64-js": "^1.5.1",
"classnames": "^2.3.1",
"clsx": "^2.1.1",
"dayjs": "^1.11.3",
"dompurify": "^3.0.2",
"electron-squirrel-startup": "^1.0.0",
@@ -70,7 +70,6 @@
"@babel/preset-typescript": "^7.17.12",
"@electron/rebuild": "^3.6.0",
"@svgr/webpack": "^8.1.0",
"@types/classnames": "^2.3.1",
"@types/electron": "^1.6.10",
"@types/node": "^20.11.0",
"@types/papaparse": "^5.3.10",
+2 -2
View File
@@ -4,7 +4,7 @@
import * as React from "react";
import * as mobxReact from "mobx-react";
import * as mobx from "mobx";
import cn from "classnames";
import { clsx } from "clsx";
import { boundMethod } from "autobind-decorator";
import { If } from "tsx-control-statements/components";
@@ -133,7 +133,7 @@ class App extends React.Component<{}, {}> {
const rightSidebarCollapsed = GlobalModel.rightSidebarModel.getCollapsed();
const activeMainView = GlobalModel.activeMainView.get();
const lightDarkClass = GlobalModel.isDarkTheme.get() ? "is-dark" : "is-light";
const mainClassName = cn(
const mainClassName = clsx(
"platform-" + platform,
{
"mainsidebar-collapsed": mainSidebarCollapsed,
+5 -5
View File
@@ -6,7 +6,7 @@ import * as mobxReact from "mobx-react";
import * as mobx from "mobx";
import { boundMethod } from "autobind-decorator";
import { If, For } from "tsx-control-statements/components";
import cn from "classnames";
import { clsx } from "clsx";
import { GlobalModel } from "@/models";
import { CmdStrCode, Markdown } from "@/common/elements";
@@ -152,11 +152,11 @@ class Bookmark extends React.Component<BookmarkProps, {}> {
return (
<div
data-bookmarkid={bm.bookmarkid}
className={cn("bookmark focus-parent is-editing", {
className={clsx("bookmark focus-parent is-editing", {
"pending-delete": model.pendingDelete.get() == bm.bookmarkid,
})}
>
<div className={cn("focus-indicator", { active: isSelected })} />
<div className={clsx("focus-indicator", { active: isSelected })} />
<div className="bookmark-edit">
<div className="field">
<label className="label">Description (markdown)</label>
@@ -198,12 +198,12 @@ class Bookmark extends React.Component<BookmarkProps, {}> {
}
return (
<div
className={cn("bookmark focus-parent", {
className={clsx("bookmark focus-parent", {
"pending-delete": model.pendingDelete.get() == bm.bookmarkid,
})}
onClick={this.handleClick}
>
<div className={cn("focus-indicator", { active: isSelected })} />
<div className={clsx("focus-indicator", { active: isSelected })} />
<div className="bookmark-id-div">{bm.bookmarkid.substr(0, 8)}</div>
<div className="bookmark-content">
<If condition={hasDesc}>
+2 -2
View File
@@ -1,6 +1,6 @@
import * as React from "react";
import { boundMethod } from "autobind-decorator";
import cn from "classnames";
import { clsx } from "clsx";
import "./button.less";
@@ -35,7 +35,7 @@ class Button extends React.Component<ButtonProps> {
return (
<button
className={cn("wave-button", { disabled }, { "term-inline": termInline }, className)}
className={clsx("wave-button", { disabled }, { "term-inline": termInline }, className)}
onClick={this.handleClick}
disabled={disabled}
style={style}
+2 -2
View File
@@ -3,7 +3,7 @@
import * as React from "react";
import * as mobx from "mobx";
import cn from "classnames";
import { clsx } from "clsx";
import "./checkbox.less";
@@ -49,7 +49,7 @@ class Checkbox extends React.Component<
const checkboxId = id || this.generatedId;
return (
<div className={cn("checkbox", className)}>
<div className={clsx("checkbox", className)}>
<input
type="checkbox"
id={checkboxId}
+2 -2
View File
@@ -3,7 +3,7 @@
import * as React from "react";
import { boundMethod } from "autobind-decorator";
import cn from "classnames";
import { clsx } from "clsx";
import { If } from "tsx-control-statements/components";
import { ReactComponent as CheckIcon } from "@/assets/icons/line/check.svg";
@@ -41,7 +41,7 @@ class CmdStrCode extends React.Component<
render() {
let { isCopied, cmdstr, fontSize, limitHeight } = this.props;
return (
<div className={cn("cmdstr-code", { "is-large": fontSize == "large" }, { "limit-height": limitHeight })}>
<div className={clsx("cmdstr-code", { "is-large": fontSize == "large" }, { "limit-height": limitHeight })}>
<If condition={isCopied}>
<div key="copied" className="copied-indicator">
<div>copied</div>
+5 -5
View File
@@ -2,7 +2,7 @@ import React, { useState, useEffect, useRef, createRef } from "react";
import * as mobx from "mobx";
import ReactDOM from "react-dom";
import dayjs from "dayjs";
import cn from "classnames";
import { clsx } from "clsx";
import { Button } from "@/elements";
import { If } from "tsx-control-statements/components";
import { GlobalModel } from "@/models";
@@ -102,7 +102,7 @@ const DatePicker: React.FC<DatePickerProps> = ({ selectedDate, format = "MM/DD/Y
return (
<div className="day-picker-header">
<div
className={cn({ fade: showYearAccordion })}
className={clsx({ fade: showYearAccordion })}
onClick={() => {
if (!showYearAccordion) {
setExpandedYear(selDate.year()); // Set expandedYear when opening accordion
@@ -111,7 +111,7 @@ const DatePicker: React.FC<DatePickerProps> = ({ selectedDate, format = "MM/DD/Y
}}
>
{selDate.format("MMMM YYYY")}
<span className={cn("dropdown-arrow", { fade: showYearAccordion })}></span>
<span className={clsx("dropdown-arrow", { fade: showYearAccordion })}></span>
</div>
<If condition={!showYearAccordion}>
<div className="arrows">
@@ -250,14 +250,14 @@ const DatePicker: React.FC<DatePickerProps> = ({ selectedDate, format = "MM/DD/Y
</div>
<If condition={expandedYear === year}>
<div
className={cn("month-container", {
className={clsx("month-container", {
expanded: expandedYear === year,
})}
>
{Array.from({ length: 12 }, (_, i) => i + 1).map((month) => (
<div
key={month}
className={cn("month", {
className={clsx("month", {
selected: year === currentYear && month === selDate.month() + 1,
})}
onClick={() => handleMonthYearSelect(month, year)}
+7 -7
View File
@@ -4,7 +4,7 @@
import * as React from "react";
import * as mobxReact from "mobx-react";
import { boundMethod } from "autobind-decorator";
import cn from "classnames";
import { clsx } from "clsx";
import { If } from "tsx-control-statements/components";
import ReactDOM from "react-dom";
import { v4 as uuidv4 } from "uuid";
@@ -239,11 +239,11 @@ class Dropdown extends React.Component<DropdownProps, DropdownState> {
const dropdownMenu = isOpen
? ReactDOM.createPortal(
<div className={cn("wave-dropdown-menu")} ref={this.menuRef} style={this.calculatePosition()}>
<div className={clsx("wave-dropdown-menu")} ref={this.menuRef} style={this.calculatePosition()}>
{options.map((option, index) => (
<div
key={option.value}
className={cn("wave-dropdown-item unselectable", {
className={clsx("wave-dropdown-item unselectable", {
"wave-dropdown-item-highlighted": index === highlightedIndex,
})}
onClick={(e) => this.handleSelect(option, e)}
@@ -265,7 +265,7 @@ class Dropdown extends React.Component<DropdownProps, DropdownState> {
}
return (
<div
className={cn("wave-dropdown", className, {
className={clsx("wave-dropdown", className, {
"wave-dropdown-error": isError,
"no-label": !label,
})}
@@ -279,7 +279,7 @@ class Dropdown extends React.Component<DropdownProps, DropdownState> {
{decoration?.startDecoration && <>{decoration.startDecoration}</>}
<If condition={label}>
<div
className={cn("wave-dropdown-label unselectable", {
className={clsx("wave-dropdown-label unselectable", {
float: shouldLabelFloat,
"offset-left": decoration?.startDecoration,
})}
@@ -288,14 +288,14 @@ class Dropdown extends React.Component<DropdownProps, DropdownState> {
</div>
</If>
<div
className={cn("wave-dropdown-display unselectable truncate", {
className={clsx("wave-dropdown-display unselectable truncate", {
"offset-left": decoration?.startDecoration,
})}
style={selectedOptionLabelStyle}
>
{selectedOptionLabel}
</div>
<div className={cn("wave-dropdown-arrow", { "wave-dropdown-arrow-rotate": isOpen })}>
<div className={clsx("wave-dropdown-arrow", { "wave-dropdown-arrow-rotate": isOpen })}>
<i className="fa-sharp fa-solid fa-chevron-down"></i>
</div>
{dropdownMenu}
@@ -5,7 +5,7 @@ import * as React from "react";
import * as mobxReact from "mobx-react";
import * as mobx from "mobx";
import { boundMethod } from "autobind-decorator";
import cn from "classnames";
import { clsx } from "clsx";
import { If } from "tsx-control-statements/components";
import { checkKeyPressed, adaptFromReactOrNativeKeyEvent } from "@/util/keyutil";
import { GlobalModel } from "@/models";
@@ -121,7 +121,7 @@ class InlineSettingsTextEdit extends React.Component<
render() {
if (this.isEditing.get()) {
return (
<div className={cn("settings-input inline-edit", "edit-active")}>
<div className={clsx("settings-input inline-edit", "edit-active")}>
<div className="field has-addons">
<div className="control">
<input
@@ -163,7 +163,7 @@ class InlineSettingsTextEdit extends React.Component<
);
} else {
return (
<div onClick={this.clickEdit} className={cn("settings-input inline-edit", "edit-not-active")}>
<div onClick={this.clickEdit} className={clsx("settings-input inline-edit", "edit-not-active")}>
{this.props.text}
<If condition={this.props.showIcon}>
<i className="fa-sharp fa-solid fa-pen" />
+2 -2
View File
@@ -3,7 +3,7 @@
import * as React from "react";
import * as mobxReact from "mobx-react";
import cn from "classnames";
import { clsx } from "clsx";
import "./inputdecoration.less";
@@ -18,7 +18,7 @@ class InputDecoration extends React.Component<InputDecorationProps, {}> {
const { children, position = "end" } = this.props;
return (
<div
className={cn("wave-input-decoration", {
className={clsx("wave-input-decoration", {
"start-position": position === "start",
"end-position": position === "end",
})}
+2 -2
View File
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
import * as React from "react";
import cn from "classnames";
import { clsx } from "clsx";
import { ButtonProps } from "./button";
interface LinkButtonProps extends ButtonProps {
@@ -16,7 +16,7 @@ class LinkButton extends React.Component<LinkButtonProps> {
const { leftIcon, rightIcon, children, className, ...rest } = this.props;
return (
<a {...rest} className={cn(`wave-button link-button`, className)}>
<a {...rest} className={clsx(`wave-button link-button`, className)}>
{leftIcon && <span className="icon-left">{leftIcon}</span>}
{children}
{rightIcon && <span className="icon-right">{rightIcon}</span>}
+2 -2
View File
@@ -3,7 +3,7 @@
import * as React from "react";
import * as mobxReact from "mobx-react";
import cn from "classnames";
import { clsx } from "clsx";
import { GlobalModel } from "@/models";
import "./mainview.less";
@@ -24,7 +24,7 @@ class MainView extends React.Component<{
const maxWidthSubtractor = sidebarModel.getCollapsed() ? 0 : sidebarModel.getWidth();
return (
<div
className={cn("mainview", this.props.className)}
className={clsx("mainview", this.props.className)}
style={{ maxWidth: `calc(100vw - ${maxWidthSubtractor}px)` }}
>
<div className="header-container">
+4 -4
View File
@@ -5,7 +5,7 @@ import * as React from "react";
import * as mobxReact from "mobx-react";
import ReactMarkdown from "react-markdown";
import remarkGfm from "remark-gfm";
import cn from "classnames";
import { clsx } from "clsx";
import { GlobalModel } from "@/models";
import { v4 as uuidv4 } from "uuid";
@@ -22,7 +22,7 @@ function LinkRenderer(props: any): any {
}
function HeaderRenderer(props: any, hnum: number): any {
return <div className={cn("title", "is-" + hnum)}>{props.children}</div>;
return <div className={clsx("title", "is-" + hnum)}>{props.children}</div>;
}
function CodeRenderer(props: any): any {
@@ -53,7 +53,7 @@ class CodeBlockMarkdown extends React.Component<
return (
<pre
ref={this.blockRef}
className={cn({ selected: selected })}
className={clsx({ selected: selected })}
onClick={(event) => clickHandler(event, this.blockIndex)}
>
{this.props.children}
@@ -110,7 +110,7 @@ class Markdown extends React.Component<
pre: (props) => this.CodeBlockRenderer(props, codeSelect, curCodeSelectIndex, this.curUuid),
};
return (
<div className={cn("markdown content", this.props.extraClassName)} style={this.props.style}>
<div className={clsx("markdown content", this.props.extraClassName)} style={this.props.style}>
<ReactMarkdown remarkPlugins={[remarkGfm]} components={markdownComponents}>
{text}
</ReactMarkdown>
+4 -4
View File
@@ -4,7 +4,7 @@
import * as React from "react";
import * as mobxReact from "mobx-react";
import { boundMethod } from "autobind-decorator";
import cn from "classnames";
import { clsx } from "clsx";
import { If } from "tsx-control-statements/components";
import { TextFieldState, TextField } from "./textfield";
@@ -48,7 +48,7 @@ class PasswordField extends TextField {
// The input should always receive the real value
const inputProps = {
className: cn("wave-textfield-inner-input", { "offset-left": decoration?.startDecoration }),
className: clsx("wave-textfield-inner-input", { "offset-left": decoration?.startDecoration }),
ref: this.inputRef,
id: label,
value: inputValue, // Always use the real value here
@@ -63,7 +63,7 @@ class PasswordField extends TextField {
return (
<div
className={cn(`wave-textfield wave-password ${className || ""}`, {
className={clsx(`wave-textfield wave-password ${className || ""}`, {
focused: focused,
error: error,
"no-label": !label,
@@ -72,7 +72,7 @@ class PasswordField extends TextField {
{decoration?.startDecoration && <>{decoration.startDecoration}</>}
<div className="wave-textfield-inner">
<label
className={cn("wave-textfield-inner-label", {
className={clsx("wave-textfield-inner-label", {
float: this.state.hasContent || this.state.focused || placeholder,
"offset-left": decoration?.startDecoration,
})}
+2 -2
View File
@@ -5,7 +5,7 @@ import * as React from "react";
import * as mobxReact from "mobx-react";
import * as mobx from "mobx";
import { boundMethod } from "autobind-decorator";
import cn from "classnames";
import { clsx } from "clsx";
import { GlobalCommandRunner, SidebarModel } from "@/models";
import { MagicLayout } from "@/app/magiclayout";
@@ -142,7 +142,7 @@ class ResizableSidebar extends React.Component<ResizableSidebarProps> {
const isCollapsed = model.getCollapsed();
return (
<div className={cn("sidebar", className, { collapsed: isCollapsed })} style={{ width, minWidth: width }}>
<div className={clsx("sidebar", className, { collapsed: isCollapsed })} style={{ width, minWidth: width }}>
<div className="sidebar-content">{children(this.toggleCollapsed)}</div>
<div
className="sidebar-handle"
+2 -2
View File
@@ -3,7 +3,7 @@
import * as React from "react";
import { isBlank } from "@/util/util";
import cn from "classnames";
import { clsx } from "clsx";
class TabIcon extends React.Component<{ icon: string; color: string }> {
render() {
@@ -20,7 +20,7 @@ class TabIcon extends React.Component<{ icon: string; color: string }> {
color = "green";
}
return (
<div className={cn("tabicon", "color-" + color)}>
<div className={clsx("tabicon", "color-" + color)}>
<i className={iconClass} />
</div>
);
+4 -4
View File
@@ -3,7 +3,7 @@
import * as React from "react";
import { boundMethod } from "autobind-decorator";
import cn from "classnames";
import { clsx } from "clsx";
import { If } from "tsx-control-statements/components";
import "./textfield.less";
@@ -140,7 +140,7 @@ class TextField extends React.Component<TextFieldProps, TextFieldState> {
return (
<div
className={cn("wave-textfield", className, {
className={clsx("wave-textfield", className, {
focused: focused,
error: error,
disabled: disabled,
@@ -154,7 +154,7 @@ class TextField extends React.Component<TextFieldProps, TextFieldState> {
<div className="wave-textfield-inner">
<If condition={label}>
<label
className={cn("wave-textfield-inner-label", {
className={clsx("wave-textfield-inner-label", {
float: this.state.hasContent || this.state.focused || placeholder,
"offset-left": decoration?.startDecoration,
})}
@@ -164,7 +164,7 @@ class TextField extends React.Component<TextFieldProps, TextFieldState> {
</label>
</If>
<input
className={cn("wave-textfield-inner-input", "wave-input", {
className={clsx("wave-textfield-inner-input", "wave-input", {
"offset-left": decoration?.startDecoration,
})}
ref={this.inputRef}
+2 -2
View File
@@ -4,7 +4,7 @@
import * as React from "react";
import * as mobxReact from "mobx-react";
import { boundMethod } from "autobind-decorator";
import cn from "classnames";
import { clsx } from "clsx";
import ReactDOM from "react-dom";
import "./tooltip.less";
@@ -63,7 +63,7 @@ class Tooltip extends React.Component<TooltipProps, TooltipState> {
const style = this.calculatePosition();
return ReactDOM.createPortal(
<div className={cn("wave-tooltip", this.props.className)} style={style}>
<div className={clsx("wave-tooltip", this.props.className)} style={style}>
{this.props.icon && <div className="wave-tooltip-icon">{this.props.icon}</div>}
<div className="wave-tooltip-message">{this.props.message}</div>
</div>,
+2 -2
View File
@@ -1,5 +1,5 @@
import React, { Component, ReactNode } from "react";
import cn from "classnames";
import { clsx } from "clsx";
interface ErrorBoundaryState {
hasError: boolean;
@@ -43,7 +43,7 @@ class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
const { plugin } = this.props;
return (
<div className={cn("load-error-text", { "view-error": !plugin })}>
<div className={clsx("load-error-text", { "view-error": !plugin })}>
<div>{`${error?.message}`}</div>
{plugin && <div>An error occurred in the {plugin} plugin</div>}
</div>
+4 -4
View File
@@ -1,5 +1,5 @@
import React from "react";
import cn from "classnames";
import { clsx } from "clsx";
import { ReactComponent as SpinnerIndicator } from "@/assets/icons/spinner-indicator.svg";
import * as appconst from "@/app/appconst";
@@ -16,7 +16,7 @@ export const FrontIcon: React.FC<PositionalIconProps> = (props) => {
return (
<div
ref={props.divRef}
className={cn("front-icon", "positional-icon", props.className)}
className={clsx("front-icon", "positional-icon", props.className)}
onClick={props.onClick}
>
<div className="positional-icon-inner">{props.children}</div>
@@ -28,7 +28,7 @@ export const CenteredIcon: React.FC<PositionalIconProps> = (props) => {
return (
<div
ref={props.divRef}
className={cn("centered-icon", "positional-icon", props.className)}
className={clsx("centered-icon", "positional-icon", props.className)}
onClick={props.onClick}
>
<div className="positional-icon-inner">{props.children}</div>
@@ -169,7 +169,7 @@ export const StatusIndicator: React.FC<StatusIndicatorProps> = (props) => {
statusIndicator = (
<CenteredIcon
divRef={iconRef}
className={cn(className, indicatorLevelClass, spinnerVisibleClass, "status-indicator")}
className={clsx(className, indicatorLevelClass, spinnerVisibleClass, "status-indicator")}
>
<SpinnerIndicator className={spinnerVisible ? "spin" : null} />
</CenteredIcon>

Some files were not shown because too many files have changed in this diff Show More