chore(frontend): fix clsx

pull/4339/head
johnnyjoy 3 months ago
parent 57014e392f
commit 0b85cb567e

@ -1,11 +1,10 @@
import { Tooltip } from "@mui/joy";
import clsx from "clsx";
import dayjs from "dayjs";
import { useWorkspaceSettingStore } from "@/store/v1";
import { WorkspaceGeneralSetting } from "@/types/proto/api/v1/workspace_setting_service";
import { WorkspaceSettingKey } from "@/types/proto/store/workspace_setting";
import { cn } from "@/utils";
import { useTranslate } from "@/utils/i18n";
import { cn } from "@/utils/utils";
interface Props {
month: string; // Format: 2021-1
@ -66,9 +65,9 @@ const ActivityCalendar = (props: Props) => {
}
return (
<div className={clsx("w-full h-auto shrink-0 grid grid-cols-7 grid-flow-row gap-1")}>
<div className={cn("w-full h-auto shrink-0 grid grid-cols-7 grid-flow-row gap-1")}>
{weekDays.map((day, index) => (
<div key={index} className={clsx("w-6 h-5 text-xs flex justify-center items-center cursor-default opacity-60")}>
<div key={index} className={cn("w-6 h-5 text-xs flex justify-center items-center cursor-default opacity-60")}>
{day}
</div>
))}

@ -1,5 +1,4 @@
import { CssVarsProvider } from "@mui/joy";
import clsx from "clsx";
import { useEffect, useRef } from "react";
import { createRoot } from "react-dom/client";
import { Provider } from "react-redux";
@ -7,6 +6,7 @@ import CommonContextProvider from "@/layouts/CommonContextProvider";
import store from "@/store";
import { useDialogStore } from "@/store/module";
import theme from "@/theme";
import { cn } from "@/utils";
import "@/less/base-dialog.less";
interface DialogConfig {
@ -56,8 +56,8 @@ const BaseDialog: React.FC<Props> = (props: Props) => {
};
return (
<div className={clsx("dialog-wrapper", className)} onMouseDown={handleSpaceClicked}>
<div ref={dialogContainerRef} className={clsx("dialog-container")} onMouseDown={(e) => e.stopPropagation()}>
<div className={cn("dialog-wrapper", className)} onMouseDown={handleSpaceClicked}>
<div ref={dialogContainerRef} className={cn("dialog-container")} onMouseDown={(e) => e.stopPropagation()}>
{children}
</div>
</div>

@ -1,7 +1,7 @@
import clsx from "clsx";
import useDebounce from "react-use/lib/useDebounce";
import SearchBar from "@/components/SearchBar";
import { useUserStatsStore } from "@/store/v1";
import { cn } from "@/utils";
import TagsSection from "../HomeSidebar/TagsSection";
import StatisticsView from "../StatisticsView";
@ -22,7 +22,7 @@ const ExploreSidebar = (props: Props) => {
return (
<aside
className={clsx(
className={cn(
"relative w-full h-auto max-h-screen overflow-auto hide-scrollbar flex flex-col justify-start items-start",
props.className,
)}

@ -1,9 +1,9 @@
import clsx from "clsx";
import useDebounce from "react-use/lib/useDebounce";
import SearchBar from "@/components/SearchBar";
import StatisticsView from "@/components/StatisticsView";
import useCurrentUser from "@/hooks/useCurrentUser";
import { useMemoList, useUserStatsStore } from "@/store/v1";
import { cn } from "@/utils";
import TagsSection from "./TagsSection";
interface Props {
@ -25,7 +25,7 @@ const HomeSidebar = (props: Props) => {
return (
<aside
className={clsx(
className={cn(
"relative w-full h-auto max-h-screen overflow-auto hide-scrollbar flex flex-col justify-start items-start",
props.className,
)}

@ -1,10 +1,10 @@
import { Dropdown, Menu, MenuButton, MenuItem, Switch } from "@mui/joy";
import clsx from "clsx";
import { Edit3Icon, HashIcon, MoreVerticalIcon, TagsIcon, TrashIcon } from "lucide-react";
import toast from "react-hot-toast";
import useLocalStorage from "react-use/lib/useLocalStorage";
import { memoServiceClient } from "@/grpcweb";
import { useMemoFilterStore, useUserStatsStore, useUserStatsTags } from "@/store/v1";
import { cn } from "@/utils";
import { useTranslate } from "@/utils/i18n";
import showRenameTagDialog from "../RenameTagDialog";
import TagTree from "../TagTree";
@ -94,7 +94,7 @@ const TagsSection = (props: Props) => {
</Menu>
</Dropdown>
<div
className={clsx("inline-flex flex-nowrap ml-0.5 gap-0.5 cursor-pointer max-w-[calc(100%-16px)]")}
className={cn("inline-flex flex-nowrap ml-0.5 gap-0.5 cursor-pointer max-w-[calc(100%-16px)]")}
onClick={() => handleTagClick(tag)}
>
<span className="truncate dark:opacity-80">{tag}</span>

@ -1,5 +1,4 @@
import { Tooltip } from "@mui/joy";
import clsx from "clsx";
import { InboxIcon, LoaderIcon, MessageCircleIcon } from "lucide-react";
import { useState } from "react";
import toast from "react-hot-toast";
@ -10,6 +9,7 @@ import { activityNamePrefix, useInboxStore, useMemoStore, useUserStore } from "@
import { Inbox, Inbox_Status } from "@/types/proto/api/v1/inbox_service";
import { Memo } from "@/types/proto/api/v1/memo_service";
import { User } from "@/types/proto/api/v1/user_service";
import { cn } from "@/utils";
import { useTranslate } from "@/utils/i18n";
import { memoLink } from "@/utils/memo";
@ -74,7 +74,7 @@ const MemoCommentMessage = ({ inbox }: Props) => {
return (
<div className="w-full flex flex-row justify-start items-start gap-3">
<div
className={clsx(
className={cn(
"shrink-0 mt-2 p-2 rounded-full border",
inbox.status === Inbox_Status.UNREAD
? "border-blue-600 text-blue-600 bg-blue-50 dark:bg-zinc-800"
@ -86,7 +86,7 @@ const MemoCommentMessage = ({ inbox }: Props) => {
</Tooltip>
</div>
<div
className={clsx(
className={cn(
"border w-full p-2 px-3 rounded-lg flex flex-col justify-start items-start gap-1 dark:border-zinc-700 hover:bg-gray-100 dark:hover:bg-zinc-700",
inbox.status !== Inbox_Status.UNREAD && "opacity-60",
)}

@ -1,5 +1,4 @@
import { Tooltip } from "@mui/joy";
import clsx from "clsx";
import { ArrowUpIcon, InboxIcon } from "lucide-react";
import { useEffect, useState } from "react";
import toast from "react-hot-toast";
@ -7,6 +6,7 @@ import { activityServiceClient } from "@/grpcweb";
import { activityNamePrefix, useInboxStore } from "@/store/v1";
import { Activity } from "@/types/proto/api/v1/activity_service";
import { Inbox, Inbox_Status } from "@/types/proto/api/v1/inbox_service";
import { cn } from "@/utils";
import { useTranslate } from "@/utils/i18n";
interface Props {
@ -58,7 +58,7 @@ const VersionUpdateMessage = ({ inbox }: Props) => {
return (
<div className="w-full flex flex-row justify-start items-start gap-3">
<div
className={clsx(
className={cn(
"shrink-0 mt-2 p-2 rounded-full border",
inbox.status === Inbox_Status.UNREAD
? "border-blue-600 text-blue-600 bg-blue-50 dark:bg-zinc-800"
@ -70,7 +70,7 @@ const VersionUpdateMessage = ({ inbox }: Props) => {
</Tooltip>
</div>
<div
className={clsx(
className={cn(
"border w-full p-2 px-3 rounded-lg flex flex-col justify-start items-start gap-1 dark:border-zinc-700 hover:bg-gray-100 dark:hover:bg-zinc-700",
inbox.status !== Inbox_Status.UNREAD && "opacity-60",
)}

@ -1,5 +1,4 @@
import { Dropdown, Menu, MenuButton, MenuItem } from "@mui/joy";
import clsx from "clsx";
import copy from "copy-to-clipboard";
import {
ArchiveIcon,
@ -20,6 +19,7 @@ import { useMemoStore, useUserStatsStore } from "@/store/v1";
import { State } from "@/types/proto/api/v1/common";
import { NodeType } from "@/types/proto/api/v1/markdown_service";
import { Memo } from "@/types/proto/api/v1/memo_service";
import { cn } from "@/utils";
import { useTranslate } from "@/utils/i18n";
import { memoLink } from "@/utils/memo";
@ -166,7 +166,7 @@ const MemoActionMenu = (props: Props) => {
return (
<Dropdown>
<MenuButton slots={{ root: "div" }}>
<span className={clsx("flex justify-center items-center rounded-full hover:opacity-70", props.className)}>
<span className={cn("flex justify-center items-center rounded-full hover:opacity-70", props.className)}>
<MoreVerticalIcon className="w-4 h-4 mx-auto text-gray-500 dark:text-gray-400" />
</span>
</MenuButton>

@ -1,9 +1,9 @@
import clsx from "clsx";
import copy from "copy-to-clipboard";
import hljs from "highlight.js";
import { CopyIcon } from "lucide-react";
import { useCallback, useMemo } from "react";
import toast from "react-hot-toast";
import { cn } from "@/utils";
import MermaidBlock from "./MermaidBlock";
import { BaseProps } from "./types";
@ -66,9 +66,9 @@ const CodeBlock: React.FC<Props> = ({ language, content }: Props) => {
</div>
<div className="overflow-auto">
<pre className={clsx("no-wrap overflow-auto", "w-full p-2 bg-amber-50 dark:bg-zinc-700 relative")}>
<pre className={cn("no-wrap overflow-auto", "w-full p-2 bg-amber-50 dark:bg-zinc-700 relative")}>
<code
className={clsx(`language-${formatedLanguage}`, "block text-sm leading-5")}
className={cn(`language-${formatedLanguage}`, "block text-sm leading-5")}
dangerouslySetInnerHTML={{ __html: highlightedCode }}
></code>
</pre>

@ -1,4 +1,3 @@
import clsx from "clsx";
import copy from "copy-to-clipboard";
import { ArrowUpRightIcon } from "lucide-react";
import { useContext, useEffect } from "react";
@ -7,6 +6,7 @@ import { Link } from "react-router-dom";
import MemoResourceListView from "@/components/MemoResourceListView";
import useLoading from "@/hooks/useLoading";
import { extractMemoIdFromName, useMemoStore } from "@/store/v1";
import { cn } from "@/utils";
import { memoLink } from "@/utils/memo";
import MemoContent from "..";
import { RendererContext } from "../types";
@ -45,7 +45,7 @@ const EmbeddedMemo = ({ resourceId: uid, params: paramsStr }: Props) => {
// Add the memo to the set of embedded memos. This is used to prevent infinite loops when a memo embeds itself.
context.embeddedMemos.add(memoName);
const contentNode = useSnippet ? (
<div className={clsx("text-gray-800 dark:text-gray-400", inlineMode ? "" : "line-clamp-3")}>{memo.snippet}</div>
<div className={cn("text-gray-800 dark:text-gray-400", inlineMode ? "" : "line-clamp-3")}>{memo.snippet}</div>
) : (
<>
<MemoContent

@ -1,8 +1,8 @@
import clsx from "clsx";
import { useEffect } from "react";
import MemoResourceListView from "@/components/MemoResourceListView";
import useLoading from "@/hooks/useLoading";
import { useResourceStore } from "@/store/v1";
import { cn } from "@/utils";
import Error from "./Error";
interface Props {
@ -53,7 +53,7 @@ const EmbeddedResource = ({ resourceId: uid, params: paramsStr }: Props) => {
}
return (
<div className={clsx("max-w-full", getAdditionalClassNameWithParams(params))}>
<div className={cn("max-w-full", getAdditionalClassNameWithParams(params))}>
<MemoResourceListView resources={[resource]} />
</div>
);

@ -1,7 +1,7 @@
import clsx from "clsx";
import { head } from "lodash-es";
import React from "react";
import { ListNode_Kind, Node, NodeType } from "@/types/proto/api/v1/markdown_service";
import { cn } from "@/utils";
import Renderer from "./Renderer";
interface Props {
@ -43,7 +43,7 @@ const List: React.FC<Props> = ({ kind, indent, children }: Props) => {
return React.createElement(
getListContainer(),
{
className: clsx(
className: cn(
`list-inside ${kind === ListNode_Kind.ORDERED ? "list-decimal" : kind === ListNode_Kind.UNORDERED ? "list-disc" : "list-none"}`,
indent > 0 ? `pl-${2 * indent}` : "",
),

@ -1,6 +1,6 @@
import TeX from "@matejmazur/react-katex";
import clsx from "clsx";
import "katex/dist/katex.min.css";
import { cn } from "@/utils";
interface Props {
content: string;
@ -8,7 +8,7 @@ interface Props {
}
const Math: React.FC<Props> = ({ content, block }: Props) => {
return <TeX className={clsx("max-w-full", block ? "w-full block" : "inline text-sm")} block={block} math={content}></TeX>;
return <TeX className={cn("max-w-full", block ? "w-full block" : "inline text-sm")} block={block} math={content}></TeX>;
};
export default Math;

@ -1,5 +1,5 @@
import clsx from "clsx";
import { useState } from "react";
import { cn } from "@/utils";
interface Props {
content: string;
@ -10,10 +10,10 @@ const Spoiler: React.FC<Props> = ({ content }: Props) => {
return (
<span
className={clsx("inline cursor-pointer select-none", isRevealed ? "" : "bg-gray-200 dark:bg-zinc-700")}
className={cn("inline cursor-pointer select-none", isRevealed ? "" : "bg-gray-200 dark:bg-zinc-700")}
onClick={() => setIsRevealed(!isRevealed)}
>
<span className={clsx(isRevealed ? "opacity-100" : "opacity-0")}>{content}</span>
<span className={cn(isRevealed ? "opacity-100" : "opacity-0")}>{content}</span>
</span>
);
};

@ -1,9 +1,9 @@
import clsx from "clsx";
import { useContext } from "react";
import { useLocation } from "react-router-dom";
import useNavigateTo from "@/hooks/useNavigateTo";
import { Routes } from "@/router";
import { stringifyFilters, useMemoFilterStore } from "@/store/v1";
import { cn } from "@/utils";
import { RendererContext } from "./types";
interface Props {
@ -44,10 +44,7 @@ const Tag: React.FC<Props> = ({ content }: Props) => {
return (
<span
className={clsx(
"inline-block w-auto text-blue-600 dark:text-blue-400",
context.disableFilter ? "" : "cursor-pointer hover:opacity-80",
)}
className={cn("inline-block w-auto text-blue-600 dark:text-blue-400", context.disableFilter ? "" : "cursor-pointer hover:opacity-80")}
onClick={handleTagClick}
>
#{content}

@ -1,9 +1,9 @@
import { Checkbox } from "@usememos/mui";
import clsx from "clsx";
import { useContext, useState } from "react";
import { markdownServiceClient } from "@/grpcweb";
import { useMemoStore } from "@/store/v1";
import { Node, TaskListItemNode } from "@/types/proto/api/v1/markdown_service";
import { cn } from "@/utils";
import Renderer from "./Renderer";
import { RendererContext } from "./types";
@ -39,11 +39,11 @@ const TaskListItem: React.FC<Props> = ({ node, complete, children }: Props) => {
};
return (
<li className={clsx("w-full grid grid-cols-[24px_1fr]")}>
<li className={cn("w-full grid grid-cols-[24px_1fr]")}>
<span className="w-6 h-6 flex justify-start items-center">
<Checkbox size="sm" checked={checked} disabled={context.readonly} onChange={(e) => handleCheckboxChange(e.target.checked)} />
</span>
<p className={clsx(complete && "line-through opacity-80")}>
<p className={cn(complete && "line-through opacity-80")}>
{children.map((child, index) => (
<Renderer key={`${child.type}-${index}`} index={String(index)} node={child} />
))}

@ -1,8 +1,8 @@
import clsx from "clsx";
import { memo, useEffect, useRef, useState } from "react";
import useCurrentUser from "@/hooks/useCurrentUser";
import { useMemoStore } from "@/store/v1";
import { Node, NodeType } from "@/types/proto/api/v1/markdown_service";
import { cn } from "@/utils";
import { useTranslate } from "@/utils/i18n";
import { isSuperUser } from "@/utils/user";
import Renderer from "./Renderer";
@ -86,7 +86,7 @@ const MemoContent: React.FC<Props> = (props: Props) => {
<div className={`w-full flex flex-col justify-start items-start text-gray-800 dark:text-gray-400 ${className || ""}`}>
<div
ref={memoContentContainerRef}
className={clsx(
className={cn(
"relative w-full max-w-full word-break text-base leading-snug space-y-2 whitespace-pre-wrap",
showCompactMode == "ALL" && "line-clamp-6 max-h-60",
contentClassName,

@ -1,8 +1,8 @@
import clsx from "clsx";
import { isEqual } from "lodash-es";
import { CheckCircleIcon, Code2Icon, HashIcon, LinkIcon } from "lucide-react";
import { MemoRelation_Type } from "@/types/proto/api/v1/memo_relation_service";
import { Memo, MemoProperty } from "@/types/proto/api/v1/memo_service";
import { cn } from "@/utils";
import { useTranslate } from "@/utils/i18n";
import MemoRelationForceGraph from "../MemoRelationForceGraph";
@ -20,10 +20,7 @@ const MemoDetailSidebar = ({ memo, className, parentPage }: Props) => {
return (
<aside
className={clsx(
"relative w-full h-auto max-h-screen overflow-auto hide-scrollbar flex flex-col justify-start items-start",
className,
)}
className={cn("relative w-full h-auto max-h-screen overflow-auto hide-scrollbar flex flex-col justify-start items-start", className)}
>
<div className="flex flex-col justify-start items-start w-full px-1 gap-2 h-auto shrink-0 flex-nowrap hide-scrollbar">
{shouldShowRelationGraph && (
@ -95,7 +92,7 @@ const MemoDetailSidebar = ({ memo, className, parentPage }: Props) => {
className="shrink-0 w-auto max-w-full text-sm rounded-md leading-6 flex flex-row justify-start items-center select-none hover:opacity-80 text-gray-600 dark:text-gray-400 dark:border-zinc-800"
>
<HashIcon className="group-hover:hidden w-4 h-auto shrink-0 opacity-40" />
<div className={clsx("inline-flex flex-nowrap ml-0.5 gap-0.5 cursor-pointer max-w-[calc(100%-16px)]")}>
<div className={cn("inline-flex flex-nowrap ml-0.5 gap-0.5 cursor-pointer max-w-[calc(100%-16px)]")}>
<span className="truncate dark:opacity-80">{tag}</span>
</div>
</div>

@ -1,7 +1,7 @@
import { Option, Select } from "@mui/joy";
import clsx from "clsx";
import { Settings2Icon } from "lucide-react";
import { useMemoFilterStore } from "@/store/v1";
import { cn } from "@/utils";
import { useTranslate } from "@/utils/i18n";
import { Popover, PopoverContent, PopoverTrigger } from "./ui/Popover";
@ -17,7 +17,7 @@ const MemoDisplaySettingMenu = ({ className }: Props) => {
return (
<Popover>
<PopoverTrigger
className={clsx(className, isApplying ? "text-teal-600 bg-teal-50 dark:text-teal-500 dark:bg-teal-900 rounded-sm" : "opacity-40")}
className={cn(className, isApplying ? "text-teal-600 bg-teal-50 dark:text-teal-500 dark:bg-teal-900 rounded-sm" : "opacity-40")}
>
<Settings2Icon className="w-4 h-auto shrink-0" />
</PopoverTrigger>

@ -1,9 +1,9 @@
import clsx from "clsx";
import Fuse from "fuse.js";
import { useEffect, useRef, useState } from "react";
import getCaretCoordinates from "textarea-caret";
import OverflowTip from "@/components/kit/OverflowTip";
import { useUserStatsTags } from "@/store/v1";
import { cn } from "@/utils";
import { EditorRefActions } from ".";
type Props = {
@ -110,7 +110,7 @@ const TagSuggestions = ({ editorRef, editorActions }: Props) => {
<div
key={tag}
onMouseDown={() => autocomplete(tag)}
className={clsx(
className={cn(
"rounded p-1 px-2 w-full truncate text-sm dark:text-gray-300 cursor-pointer hover:bg-zinc-200 dark:hover:bg-zinc-800",
i === selected ? "bg-zinc-300 dark:bg-zinc-600" : "",
)}

@ -1,8 +1,8 @@
import clsx from "clsx";
import { last } from "lodash-es";
import { forwardRef, ReactNode, useCallback, useEffect, useImperativeHandle, useRef, useState } from "react";
import { markdownServiceClient } from "@/grpcweb";
import { NodeType, OrderedListItemNode, TaskListItemNode, UnorderedListItemNode } from "@/types/proto/api/v1/markdown_service";
import { cn } from "@/utils";
import TagSuggestions from "./TagSuggestions";
export interface EditorRefActions {
@ -187,10 +187,7 @@ const Editor = forwardRef(function Editor(props: Props, ref: React.ForwardedRef<
return (
<div
className={clsx(
"flex flex-col justify-start items-start relative w-full h-auto max-h-[50vh] bg-inherit dark:text-gray-300",
className,
)}
className={cn("flex flex-col justify-start items-start relative w-full h-auto max-h-[50vh] bg-inherit dark:text-gray-300", className)}
>
<textarea
className="w-full h-full my-1 text-base resize-none overflow-x-hidden overflow-y-auto bg-transparent outline-none whitespace-pre-wrap word-break"

@ -75,15 +75,15 @@ const MemoFilters = () => {
return (
<div className="w-full mb-2 flex flex-row justify-start items-start gap-2">
<span className="flex flex-row items-center gap-0.5 text-gray-500 text-sm leading-6 border border-transparent">
<span className="flex flex-row items-center gap-0.5 text-gray-500 text-sm leading-7 border border-transparent">
<FilterIcon className="w-4 h-auto opacity-60 inline" />
{t("memo.filters")}
</span>
<div className="flex flex-row justify-start items-center flex-wrap gap-2 leading-6 h-6">
<div className="flex flex-row justify-start items-center flex-wrap gap-x-2 gap-y-1 leading-7 h-7">
{filters.map((filter) => (
<div
key={getMemoFilterKey(filter)}
className="flex flex-row items-center gap-1 bg-white dark:bg-zinc-800 border dark:border-zinc-700 pl-1.5 pr-1 rounded-md hover:line-through cursor-pointer"
className="w-auto h-full flex flex-row items-center gap-1 bg-white dark:bg-zinc-800 border dark:border-zinc-700 pl-1.5 pr-1 rounded-md hover:line-through cursor-pointer"
onClick={() => memoFilterStore.removeFilter((f) => isEqual(f, filter))}
>
<FactorIcon className="w-4 h-auto text-gray-500 dark:text-gray-400 opacity-60" factor={filter.factor} />

@ -1,10 +1,10 @@
import { useColorScheme } from "@mui/joy";
import clsx from "clsx";
import { useEffect, useRef, useState } from "react";
import ForceGraph2D, { ForceGraphMethods, LinkObject, NodeObject } from "react-force-graph-2d";
import useNavigateTo from "@/hooks/useNavigateTo";
import { MemoRelation_Type } from "@/types/proto/api/v1/memo_relation_service";
import { Memo } from "@/types/proto/api/v1/memo_service";
import { cn } from "@/utils";
import { memoLink } from "@/utils/memo";
import { LinkType, NodeType } from "./types";
import { convertMemoRelationsToGraphData } from "./utils";
@ -40,7 +40,7 @@ const MemoRelationForceGraph = ({ className, memo, parentPage }: Props) => {
};
return (
<div ref={containerRef} className={clsx("dark:opacity-80", className)}>
<div ref={containerRef} className={cn("dark:opacity-80", className)}>
<ForceGraph2D
ref={graphRef}
width={graphSize.width}

@ -1,9 +1,9 @@
import clsx from "clsx";
import { LinkIcon, MilestoneIcon } from "lucide-react";
import { memo, useState } from "react";
import { Link } from "react-router-dom";
import { MemoRelation } from "@/types/proto/api/v1/memo_relation_service";
import { Memo } from "@/types/proto/api/v1/memo_service";
import { cn } from "@/utils";
interface Props {
memo: Memo;
@ -32,7 +32,7 @@ const MemoRelationListView = (props: Props) => {
<div className="w-full flex flex-row justify-start items-center mb-1 gap-3 opacity-60">
{referencingMemoList.length > 0 && (
<button
className={clsx(
className={cn(
"w-auto flex flex-row justify-start items-center text-xs gap-0.5 text-gray-500",
selectedTab === "referencing" && "text-gray-800 dark:text-gray-400",
)}
@ -45,7 +45,7 @@ const MemoRelationListView = (props: Props) => {
)}
{referencedMemoList.length > 0 && (
<button
className={clsx(
className={cn(
"w-auto flex flex-row justify-start items-center text-xs gap-0.5 text-gray-500",
selectedTab === "referenced" && "text-gray-800 dark:text-gray-400",
)}

@ -1,5 +1,4 @@
import { Tooltip } from "@mui/joy";
import clsx from "clsx";
import { BookmarkIcon, MessageCircleMoreIcon } from "lucide-react";
import { memo, useCallback, useRef, useState } from "react";
import { Link, useLocation } from "react-router-dom";
@ -12,6 +11,7 @@ import { MemoRelation_Type } from "@/types/proto/api/v1/memo_relation_service";
import { Memo, Visibility } from "@/types/proto/api/v1/memo_service";
import { WorkspaceMemoRelatedSetting } from "@/types/proto/api/v1/workspace_setting_service";
import { WorkspaceSettingKey } from "@/types/proto/store/workspace_setting";
import { cn } from "@/utils";
import { useTranslate } from "@/utils/i18n";
import { convertVisibilityToString, memoLink } from "@/utils/memo";
import { isSuperUser } from "@/utils/user";
@ -125,7 +125,7 @@ const MemoView: React.FC<Props> = (props: Props) => {
return (
<div
className={clsx(
className={cn(
"group relative flex flex-col justify-start items-start w-full px-4 py-3 mb-2 gap-2 bg-white dark:bg-zinc-800 rounded-lg border border-white dark:border-zinc-800 hover:border-gray-200 dark:hover:border-zinc-700",
props.showPinned && memo.pinned && "border-gray-200 border dark:border-zinc-700",
className,
@ -188,7 +188,7 @@ const MemoView: React.FC<Props> = (props: Props) => {
</div>
{!isInMemoDetailPage && (workspaceMemoRelatedSetting.enableComment || commentAmount > 0) && (
<Link
className={clsx(
className={cn(
"flex flex-row justify-start items-center hover:opacity-70",
commentAmount === 0 && "invisible group-hover:visible",
)}

@ -1,9 +1,9 @@
import clsx from "clsx";
import useWindowScroll from "react-use/lib/useWindowScroll";
import useResponsiveWidth from "@/hooks/useResponsiveWidth";
import { useWorkspaceSettingStore } from "@/store/v1";
import { WorkspaceGeneralSetting } from "@/types/proto/api/v1/workspace_setting_service";
import { WorkspaceSettingKey } from "@/types/proto/store/workspace_setting";
import { cn } from "@/utils";
import NavigationDrawer from "./NavigationDrawer";
interface Props {
@ -21,7 +21,7 @@ const MobileHeader = (props: Props) => {
return (
<div
className={clsx(
className={cn(
"sticky top-0 pt-3 pb-2 sm:pt-2 px-4 sm:px-6 sm:mb-1 bg-zinc-100 dark:bg-zinc-900 bg-opacity-80 backdrop-blur-lg flex md:hidden flex-row justify-between items-center w-full h-auto flex-nowrap shrink-0 z-1",
offsetTop > 0 && "shadow-md",
className,

@ -1,5 +1,4 @@
import { Tooltip } from "@mui/joy";
import clsx from "clsx";
import { ArchiveIcon, BellIcon, Globe2Icon, HomeIcon, LogInIcon, PaperclipIcon, SettingsIcon, SmileIcon, User2Icon } from "lucide-react";
import { useEffect } from "react";
import { NavLink } from "react-router-dom";
@ -7,6 +6,7 @@ import useCurrentUser from "@/hooks/useCurrentUser";
import { Routes } from "@/router";
import { useInboxStore } from "@/store/v1";
import { Inbox_Status } from "@/types/proto/api/v1/inbox_service";
import { cn } from "@/utils";
import { useTranslate } from "@/utils/i18n";
import UserBanner from "./UserBanner";
@ -116,14 +116,14 @@ const Navigation = (props: Props) => {
return (
<header
className={clsx("w-full h-full overflow-auto flex flex-col justify-start items-start py-4 md:pt-6 z-30 hide-scrollbar", className)}
className={cn("w-full h-full overflow-auto flex flex-col justify-start items-start py-4 md:pt-6 z-30 hide-scrollbar", className)}
>
<UserBanner collapsed={collapsed} />
<div className="w-full px-1 py-2 flex flex-col justify-start items-start shrink-0 space-y-2">
{navLinks.map((navLink) => (
<NavLink
className={({ isActive }) =>
clsx(
cn(
"px-2 py-2 rounded-2xl border flex flex-row items-center text-lg text-gray-800 dark:text-gray-400 hover:bg-white hover:border-gray-200 dark:hover:border-zinc-700 dark:hover:bg-zinc-800",
collapsed ? "" : "w-full px-4",
isActive ? "bg-white drop-shadow-sm dark:bg-zinc-800 border-gray-200 dark:border-zinc-700" : "border-transparent",

@ -1,5 +1,4 @@
import { Dropdown, Menu, MenuButton } from "@mui/joy";
import clsx from "clsx";
import { SmilePlusIcon } from "lucide-react";
import { useRef, useState } from "react";
import useClickAway from "react-use/lib/useClickAway";
@ -9,6 +8,7 @@ import { useMemoStore, useWorkspaceSettingStore } from "@/store/v1";
import { Memo } from "@/types/proto/api/v1/memo_service";
import { WorkspaceMemoRelatedSetting } from "@/types/proto/api/v1/workspace_setting_service";
import { WorkspaceSettingKey } from "@/types/proto/store/workspace_setting";
import { cn } from "@/utils";
interface Props {
memo: Memo;
@ -63,7 +63,7 @@ const ReactionSelector = (props: Props) => {
<Dropdown open={open} onOpenChange={(_, isOpen) => setOpen(isOpen)}>
<MenuButton slots={{ root: "div" }}>
<span
className={clsx("h-7 w-7 flex justify-center items-center rounded-full border dark:border-zinc-700 hover:opacity-70", className)}
className={cn("h-7 w-7 flex justify-center items-center rounded-full border dark:border-zinc-700 hover:opacity-70", className)}
>
<SmilePlusIcon className="w-4 h-4 mx-auto text-gray-500 dark:text-gray-400" />
</span>
@ -75,7 +75,7 @@ const ReactionSelector = (props: Props) => {
return (
<span
key={reactionType}
className={clsx(
className={cn(
"inline-flex w-auto text-base cursor-pointer rounded px-1 text-gray-500 dark:text-gray-400 hover:opacity-80",
hasReacted(reactionType) && "bg-blue-100 dark:bg-zinc-800",
)}

@ -1,11 +1,11 @@
import { Tooltip } from "@mui/joy";
import clsx from "clsx";
import { memoServiceClient } from "@/grpcweb";
import useCurrentUser from "@/hooks/useCurrentUser";
import { useMemoStore } from "@/store/v1";
import { State } from "@/types/proto/api/v1/common";
import { Memo } from "@/types/proto/api/v1/memo_service";
import { User } from "@/types/proto/api/v1/user_service";
import { cn } from "@/utils";
interface Props {
memo: Memo;
@ -67,7 +67,7 @@ const ReactionView = (props: Props) => {
return (
<Tooltip title={stringifyUsers(users, reactionType)} placement="top">
<div
className={clsx(
className={cn(
"h-7 border px-2 py-0.5 rounded-full flex flex-row justify-center items-center gap-1 dark:border-zinc-700",
"text-sm text-gray-600 dark:text-gray-400",
currentUser && !readonly && "cursor-pointer",

@ -1,4 +1,3 @@
import clsx from "clsx";
import {
BinaryIcon,
BookIcon,
@ -12,6 +11,7 @@ import {
} from "lucide-react";
import React from "react";
import { Resource } from "@/types/proto/api/v1/resource_service";
import { cn } from "@/utils";
import { getResourceType, getResourceUrl } from "@/utils/resource";
import showPreviewImageDialog from "./PreviewImageDialog";
import SquareDiv from "./kit/SquareDiv";
@ -26,7 +26,7 @@ const ResourceIcon = (props: Props) => {
const { resource } = props;
const resourceType = getResourceType(resource);
const resourceUrl = getResourceUrl(resource);
const className = clsx("w-full h-auto", props.className);
const className = cn("w-full h-auto", props.className);
const strokeWidth = props.strokeWidth;
const previewResource = () => {
@ -35,7 +35,7 @@ const ResourceIcon = (props: Props) => {
if (resourceType === "image/*") {
return (
<SquareDiv className={clsx(className, "flex items-center justify-center overflow-clip")}>
<SquareDiv className={cn(className, "flex items-center justify-center overflow-clip")}>
<img
className="min-w-full min-h-full object-cover"
src={resource.externalLink ? resourceUrl : resourceUrl + "?thumbnail=true"}
@ -73,7 +73,7 @@ const ResourceIcon = (props: Props) => {
};
return (
<div onClick={previewResource} className={clsx(className, "max-w-[4rem] opacity-50")}>
<div onClick={previewResource} className={cn(className, "max-w-[4rem] opacity-50")}>
{getResourceIcon()}
</div>
);

@ -1,5 +1,4 @@
import { Tooltip } from "@mui/joy";
import clsx from "clsx";
import dayjs from "dayjs";
import { countBy } from "lodash-es";
import { CheckCircleIcon, ChevronDownIcon, ChevronUpIcon, Code2Icon, LinkIcon, ListTodoIcon } from "lucide-react";
@ -8,6 +7,7 @@ import useAsyncEffect from "@/hooks/useAsyncEffect";
import i18n from "@/i18n";
import { useMemoFilterStore, useUserStatsStore } from "@/store/v1";
import { UserStats_MemoTypeStats } from "@/types/proto/api/v1/user_service";
import { cn } from "@/utils";
import { useTranslate } from "@/utils/i18n";
import ActivityCalendar from "./ActivityCalendar";
@ -42,7 +42,7 @@ const StatisticsView = () => {
};
return (
<div className="group w-full mt-2 py-2 space-y-1 text-gray-500 dark:text-gray-400">
<div className="group w-full mt-4 space-y-1 text-gray-500 dark:text-gray-400">
<div className="w-full mb-1 flex flex-row justify-between items-center gap-1">
<div className="relative text-sm font-medium inline-flex flex-row items-center w-auto dark:text-gray-400 truncate">
<span className="truncate">
@ -74,7 +74,7 @@ const StatisticsView = () => {
</div>
<div className="pt-1 w-full flex flex-row justify-start items-center gap-x-2 gap-y-1 flex-wrap">
<div
className={clsx("w-auto border dark:border-zinc-800 pl-1 pr-1.5 rounded-md flex justify-between items-center")}
className={cn("w-auto border dark:border-zinc-800 pl-1.5 pr-2 py-0.5 rounded-md flex justify-between items-center")}
onClick={() => memoFilterStore.addFilter({ factor: "property.hasLink", value: "" })}
>
<div className="w-auto flex justify-start items-center mr-1">
@ -84,7 +84,7 @@ const StatisticsView = () => {
<span className="text-sm truncate">{memoTypeStats.linkCount}</span>
</div>
<div
className={clsx("w-auto border dark:border-zinc-800 pl-1 pr-1.5 rounded-md flex justify-between items-center")}
className={cn("w-auto border dark:border-zinc-800 pl-1.5 pr-2 py-0.5 rounded-md flex justify-between items-center")}
onClick={() => memoFilterStore.addFilter({ factor: "property.hasTaskList", value: "" })}
>
<div className="w-auto flex justify-start items-center mr-1">
@ -104,7 +104,7 @@ const StatisticsView = () => {
)}
</div>
<div
className={clsx("w-auto border dark:border-zinc-800 pl-1 pr-1.5 rounded-md flex justify-between items-center")}
className={cn("w-auto border dark:border-zinc-800 pl-1.5 pr-2 py-0.5 rounded-md flex justify-between items-center")}
onClick={() => memoFilterStore.addFilter({ factor: "property.hasCode", value: "" })}
>
<div className="w-auto flex justify-start items-center mr-1">

@ -1,4 +1,4 @@
import clsx from "clsx";
import { cn } from "@/utils";
interface Props {
avatarUrl?: string;
@ -8,7 +8,7 @@ interface Props {
const UserAvatar = (props: Props) => {
const { avatarUrl, className } = props;
return (
<div className={clsx(`w-8 h-8 overflow-clip rounded-xl`, className)}>
<div className={cn(`w-8 h-8 overflow-clip rounded-xl`, className)}>
<img
className="w-full h-auto shadow min-w-full min-h-full object-cover dark:opacity-80"
src={avatarUrl || "/full-logo.webp"}

@ -1,5 +1,4 @@
import { Dropdown, Menu, MenuButton, MenuItem } from "@mui/joy";
import clsx from "clsx";
import { LogOutIcon, SmileIcon } from "lucide-react";
import { authServiceClient } from "@/grpcweb";
import useCurrentUser from "@/hooks/useCurrentUser";
@ -8,6 +7,7 @@ import { Routes } from "@/router";
import { useWorkspaceSettingStore } from "@/store/v1";
import { WorkspaceGeneralSetting } from "@/types/proto/api/v1/workspace_setting_service";
import { WorkspaceSettingKey } from "@/types/proto/store/workspace_setting";
import { cn } from "@/utils";
import { useTranslate } from "@/utils/i18n";
import UserAvatar from "./UserAvatar";
@ -36,7 +36,7 @@ const UserBanner = (props: Props) => {
<Dropdown>
<MenuButton disabled={!user} slots={{ root: "div" }}>
<div
className={clsx(
className={cn(
"py-1 my-1 w-auto flex flex-row justify-start items-center cursor-pointer text-gray-800 dark:text-gray-400",
collapsed ? "px-1" : "px-3",
)}

@ -1,6 +1,6 @@
import clsx from "clsx";
import { Globe2Icon, LockIcon, UsersIcon } from "lucide-react";
import { Visibility } from "@/types/proto/api/v1/memo_service";
import { cn } from "@/utils";
interface Props {
visibility: Visibility;
@ -21,7 +21,7 @@ const VisibilityIcon = (props: Props) => {
return null;
}
return <VIcon className={clsx("w-4 h-auto text-gray-500 dark:text-gray-400")} />;
return <VIcon className={cn("w-4 h-auto text-gray-500 dark:text-gray-400")} />;
};
export default VisibilityIcon;

@ -1,6 +1,6 @@
import { Tooltip } from "@mui/joy";
import clsx from "clsx";
import { useRef, useState, useEffect } from "react";
import { cn } from "@/utils";
interface Props {
children: React.ReactNode;
@ -21,7 +21,7 @@ const OverflowTip = ({ children, className }: Props) => {
return (
<Tooltip title={children} placement="top" arrow disableHoverListener={!isOverflowed}>
<div ref={textElementRef} className={clsx("truncate", className)}>
<div ref={textElementRef} className={cn("truncate", className)}>
{children}
</div>
</Tooltip>

@ -1,6 +1,6 @@
import * as PopoverPrimitive from "@radix-ui/react-popover";
import clsx from "clsx";
import * as React from "react";
import { cn } from "@/utils";
const Popover = PopoverPrimitive.Root;
@ -16,8 +16,8 @@ const PopoverContent = React.forwardRef<
ref={ref}
align={align}
sideOffset={sideOffset}
className={clsx(
"z-[2000] w-auto rounded-md bg-white dark:bg-zinc-900 border dark:border-zinc-800 bg-popover p-2 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
className={cn(
"z-[2000] w-auto rounded-md bg-white dark:bg-zinc-900 border dark:border-zinc-800 p-2 shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
className,
)}
{...props}

@ -1,6 +1,5 @@
import { Tooltip } from "@mui/joy";
import { Button } from "@usememos/mui";
import clsx from "clsx";
import { ChevronLeftIcon, ChevronRightIcon } from "lucide-react";
import { Suspense, useEffect, useMemo, useState } from "react";
import { Outlet, useLocation, useSearchParams } from "react-router-dom";
@ -12,6 +11,7 @@ import useResponsiveWidth from "@/hooks/useResponsiveWidth";
import Loading from "@/pages/Loading";
import { Routes } from "@/router";
import { useMemoFilterStore } from "@/store/v1";
import { cn } from "@/utils";
import { useTranslate } from "@/utils/i18n";
const RootLayout = () => {
@ -47,18 +47,18 @@ const RootLayout = () => {
<Loading />
) : (
<div className="w-full min-h-full">
<div className={clsx("w-full transition-all mx-auto flex flex-row justify-center items-start", collapsed ? "sm:pl-16" : "sm:pl-56")}>
<div className={cn("w-full transition-all mx-auto flex flex-row justify-center items-start", collapsed ? "sm:pl-16" : "sm:pl-56")}>
{sm && (
<div
className={clsx(
className={cn(
"group flex flex-col justify-start items-start fixed top-0 left-0 select-none border-r dark:border-zinc-800 h-full bg-zinc-50 dark:bg-zinc-800 dark:bg-opacity-40 transition-all hover:shadow-xl z-2",
collapsed ? "w-16 px-2" : "w-56 px-4",
)}
>
<Navigation className="!h-auto" collapsed={collapsed} />
<div className={clsx("w-full grow h-auto flex flex-col justify-end", collapsed ? "items-center" : "items-start")}>
<div className={cn("w-full grow h-auto flex flex-col justify-end", collapsed ? "items-center" : "items-start")}>
<div
className={clsx("hidden py-3 group-hover:flex flex-col justify-center items-center")}
className={cn("hidden py-3 group-hover:flex flex-col justify-center items-center")}
onClick={() => setCollapsed(!collapsed)}
>
{!collapsed ? (

@ -354,8 +354,8 @@
"workspace-section": {
"disallow-user-registration": "Disallow user registration",
"disallow-password-auth": "Disallow password auth",
"disallow-change-username": "Disallow Change Username",
"disallow-change-nickname": "Disallow Change Nickname",
"disallow-change-username": "Disallow changing username",
"disallow-change-nickname": "Disallow changing nickname",
"week-start-day": "Week start day",
"saturday": "Saturday",
"sunday": "Sunday",
@ -391,4 +391,4 @@
"blogs": "Blogs",
"documents": "Documents"
}
}
}

@ -1,4 +1,3 @@
import clsx from "clsx";
import dayjs from "dayjs";
import { useMemo } from "react";
import { ExploreSidebar, ExploreSidebarDrawer } from "@/components/ExploreSidebar";
@ -11,6 +10,7 @@ import useResponsiveWidth from "@/hooks/useResponsiveWidth";
import { useMemoFilterStore } from "@/store/v1";
import { State } from "@/types/proto/api/v1/common";
import { Memo } from "@/types/proto/api/v1/memo_service";
import { cn } from "@/utils";
const Explore = () => {
const { md } = useResponsiveWidth();
@ -59,8 +59,8 @@ const Explore = () => {
<ExploreSidebarDrawer />
</MobileHeader>
)}
<div className={clsx("w-full flex flex-row justify-start items-start px-4 sm:px-6 gap-4")}>
<div className={clsx(md ? "w-[calc(100%-15rem)]" : "w-full")}>
<div className={cn("w-full flex flex-row justify-start items-start px-4 sm:px-6 gap-4")}>
<div className={cn(md ? "w-[calc(100%-15rem)]" : "w-full")}>
<MemoFilters />
<div className="flex flex-col justify-start items-start w-full max-w-full">
<PagedMemoList

@ -1,4 +1,3 @@
import clsx from "clsx";
import dayjs from "dayjs";
import { useMemo } from "react";
import { HomeSidebar, HomeSidebarDrawer } from "@/components/HomeSidebar";
@ -12,6 +11,7 @@ import useResponsiveWidth from "@/hooks/useResponsiveWidth";
import { useMemoFilterStore } from "@/store/v1";
import { State } from "@/types/proto/api/v1/common";
import { Memo } from "@/types/proto/api/v1/memo_service";
import { cn } from "@/utils";
const Home = () => {
const { md } = useResponsiveWidth();
@ -60,8 +60,8 @@ const Home = () => {
<HomeSidebarDrawer />
</MobileHeader>
)}
<div className={clsx("w-full flex flex-row justify-start items-start px-4 sm:px-6 gap-4")}>
<div className={clsx(md ? "w-[calc(100%-15rem)]" : "w-full")}>
<div className={cn("w-full flex flex-row justify-start items-start px-4 sm:px-6 gap-4")}>
<div className={cn(md ? "w-[calc(100%-15rem)]" : "w-full")}>
<MemoEditor className="mb-2" cacheKey="home-memo-editor" />
<MemoFilters />
<div className="flex flex-col justify-start items-start w-full max-w-full">

@ -1,5 +1,4 @@
import { Button } from "@usememos/mui";
import clsx from "clsx";
import { ArrowUpLeftFromCircleIcon, MessageCircleIcon } from "lucide-react";
import { ClientError } from "nice-grpc-web";
import { useEffect, useState } from "react";
@ -16,6 +15,7 @@ import { memoNamePrefix, useMemoStore, useWorkspaceSettingStore } from "@/store/
import { MemoRelation_Type } from "@/types/proto/api/v1/memo_relation_service";
import { Memo } from "@/types/proto/api/v1/memo_service";
import { WorkspaceMemoRelatedSetting, WorkspaceSettingKey } from "@/types/proto/store/workspace_setting";
import { cn } from "@/utils";
import { useTranslate } from "@/utils/i18n";
import { memoLink } from "@/utils/memo";
@ -92,8 +92,8 @@ const MemoDetail = () => {
<MemoDetailSidebarDrawer memo={memo} parentPage={locationState?.from} />
</MobileHeader>
)}
<div className={clsx("w-full flex flex-row justify-start items-start px-4 sm:px-6 gap-4")}>
<div className={clsx(md ? "w-[calc(100%-15rem)]" : "w-full")}>
<div className={cn("w-full flex flex-row justify-start items-start px-4 sm:px-6 gap-4")}>
<div className={cn(md ? "w-[calc(100%-15rem)]" : "w-full")}>
{parentMemo && (
<div className="w-auto inline-block mb-2">
<Link

@ -0,0 +1 @@
export * from "./utils";

@ -1,6 +1,6 @@
import { type ClassValue, clsx } from "clsx";
import { twMerge } from "tailwind-merge";
export function cn(...inputs: ClassValue[]) {
export const cn = (...inputs: ClassValue[]) => {
return twMerge(clsx(inputs));
}
};

Loading…
Cancel
Save