mirror of
https://github.com/JOYCEQL/magic-resume.git
synced 2026-06-01 23:38:48 +02:00
perf: rich-text editor perf
This commit is contained in:
@@ -13,6 +13,7 @@
|
||||
"@radix-ui/react-popover": "^1.1.1",
|
||||
"@radix-ui/react-slot": "^1.0.2",
|
||||
"@radix-ui/react-tabs": "^1.0.4",
|
||||
"@radix-ui/react-tooltip": "^1.1.2",
|
||||
"@tiptap/extension-color": "^2.4.0",
|
||||
"@tiptap/extension-list-item": "^2.4.0",
|
||||
"@tiptap/extension-text-align": "^2.4.0",
|
||||
|
||||
@@ -41,7 +41,7 @@ const BasicInfo = () => {
|
||||
<Input id="email" className="w-[200px] flex-1" />
|
||||
</div>
|
||||
<div className="flex items-center flex-[48%]">
|
||||
<Label htmlFor="wechat" className="w-[80px]">
|
||||
<Label htmlFor="birthday" className="w-[80px]">
|
||||
出生日期
|
||||
</Label>
|
||||
<Popover open={isDateOpen}>
|
||||
@@ -49,6 +49,7 @@ const BasicInfo = () => {
|
||||
<div className="relative flex-1 w-[200px]">
|
||||
<CalendarIcon className="left-[10px] top-[12px] absolute h-4 w-4" />
|
||||
<Input
|
||||
id="birthday"
|
||||
className="flex-1 pl-[36px] "
|
||||
value={date ? format(date, "PPP") : "Pick a date"}
|
||||
onClick={() => setIsDateOpen(true)}
|
||||
|
||||
@@ -29,15 +29,14 @@ const ColorBar = ({ setCurrentColor }: IProps) => {
|
||||
return (
|
||||
<div
|
||||
key={index}
|
||||
className="shrink-0"
|
||||
className="shrink-0 cursor-pointer hover:scale-[1.3] transition-all"
|
||||
onClick={setCurrentColor(color)}
|
||||
style={{
|
||||
width: "20px",
|
||||
height: "20px",
|
||||
backgroundColor: color,
|
||||
margin: "5px",
|
||||
border: "1px solid #000000",
|
||||
borderRadius: "5px"
|
||||
borderRadius: "50%"
|
||||
}}
|
||||
></div>
|
||||
);
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger
|
||||
} from "@/components/ui/tooltip";
|
||||
|
||||
interface IProps {
|
||||
children: React.ReactNode;
|
||||
title: string;
|
||||
}
|
||||
|
||||
function CustomTooltip({ children, title }: IProps) {
|
||||
return (
|
||||
<TooltipProvider delayDuration={200}>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>{children}</TooltipTrigger>
|
||||
<TooltipContent>{title}</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
);
|
||||
}
|
||||
|
||||
export default CustomTooltip;
|
||||
@@ -19,6 +19,7 @@ import {
|
||||
List,
|
||||
ListOrdered,
|
||||
MessageSquareQuote,
|
||||
Palette,
|
||||
Pilcrow,
|
||||
Redo,
|
||||
Strikethrough,
|
||||
@@ -30,16 +31,18 @@ import ListItem from "@tiptap/extension-list-item";
|
||||
import TextStyle from "@tiptap/extension-text-style";
|
||||
import { EditorProvider, useCurrentEditor } from "@tiptap/react";
|
||||
import TextAlign from "@tiptap/extension-text-align";
|
||||
|
||||
import StarterKit from "@tiptap/starter-kit";
|
||||
|
||||
import {
|
||||
Popover,
|
||||
PopoverContent,
|
||||
PopoverTrigger
|
||||
} from "@/components/ui/popover";
|
||||
|
||||
import "../styles/tiptap.scss";
|
||||
import ColorBar from "./ColorBar";
|
||||
import CustomTooltip from "./CustomTooltip";
|
||||
|
||||
import "../styles/tiptap.scss";
|
||||
|
||||
const MenuBar = () => {
|
||||
const { editor } = useCurrentEditor();
|
||||
@@ -53,58 +56,33 @@ const MenuBar = () => {
|
||||
return (
|
||||
<div className="control-group">
|
||||
<div className="button-group">
|
||||
{/* <button
|
||||
onClick={() => editor.chain().focus().toggleBold().run()}
|
||||
disabled={!editor.can().chain().focus().toggleBold().run()}
|
||||
className={editor.isActive("bold") ? "is-active" : ""}
|
||||
>
|
||||
Bold
|
||||
</button> */}
|
||||
<Bold
|
||||
onClick={() => editor.chain().focus().toggleBold().run()}
|
||||
className={editor.isActive("bold") ? "is-active" : ""}
|
||||
></Bold>
|
||||
{/* <button
|
||||
onClick={() => editor.chain().focus().toggleItalic().run()}
|
||||
disabled={!editor.can().chain().focus().toggleItalic().run()}
|
||||
className={editor.isActive("italic") ? "is-active" : ""}
|
||||
>
|
||||
Italic
|
||||
</button> */}
|
||||
<Italic
|
||||
onClick={() => editor.chain().focus().toggleItalic().run()}
|
||||
className={editor.isActive("italic") ? "is-active" : ""}
|
||||
></Italic>
|
||||
{/* <button
|
||||
onClick={() => editor.chain().focus().toggleStrike().run()}
|
||||
disabled={!editor.can().chain().focus().toggleStrike().run()}
|
||||
className={editor.isActive("strike") ? "is-active" : ""}
|
||||
>
|
||||
Strike
|
||||
</button> */}
|
||||
<Strikethrough
|
||||
onClick={() => editor.chain().focus().toggleStrike().run()}
|
||||
className={editor.isActive("strike") ? "is-active" : ""}
|
||||
></Strikethrough>
|
||||
{/* <button
|
||||
onClick={() => editor.chain().focus().toggleCode().run()}
|
||||
disabled={!editor.can().chain().focus().toggleCode().run()}
|
||||
className={editor.isActive("code") ? "is-active" : ""}
|
||||
>
|
||||
Code
|
||||
</button> */}
|
||||
<CodeXml
|
||||
onClick={() => editor.chain().focus().toggleCode().run()}
|
||||
className={editor.isActive("code") ? "is-active" : ""}
|
||||
></CodeXml>
|
||||
<Eraser
|
||||
onClick={() => editor.chain().focus().clearNodes().run()}
|
||||
></Eraser>
|
||||
{/*
|
||||
<Pilcrow
|
||||
onClick={() => editor.chain().focus().setParagraph().run()}
|
||||
className={editor.isActive("paragraph") ? "is-active" : ""}
|
||||
></Pilcrow> */}
|
||||
<CustomTooltip title="加粗">
|
||||
<Bold
|
||||
onClick={() => editor.chain().focus().toggleBold().run()}
|
||||
className={editor.isActive("bold") ? "is-active" : ""}
|
||||
></Bold>
|
||||
</CustomTooltip>
|
||||
|
||||
<CustomTooltip title="斜体">
|
||||
<Italic
|
||||
onClick={() => editor.chain().focus().toggleItalic().run()}
|
||||
className={editor.isActive("italic") ? "is-active" : ""}
|
||||
></Italic>
|
||||
</CustomTooltip>
|
||||
|
||||
<CustomTooltip title="中划线">
|
||||
<Strikethrough
|
||||
onClick={() => editor.chain().focus().toggleStrike().run()}
|
||||
className={editor.isActive("strike") ? "is-active" : ""}
|
||||
></Strikethrough>
|
||||
</CustomTooltip>
|
||||
|
||||
<CustomTooltip title="行内代码">
|
||||
<CodeXml
|
||||
onClick={() => editor.chain().focus().toggleCode().run()}
|
||||
className={editor.isActive("code") ? "is-active" : ""}
|
||||
></CodeXml>
|
||||
</CustomTooltip>
|
||||
|
||||
<Heading1
|
||||
onClick={() =>
|
||||
@@ -165,11 +143,12 @@ const MenuBar = () => {
|
||||
onClick={() => editor.chain().focus().toggleOrderedList().run()}
|
||||
className={editor.isActive("orderedList") ? "is-active" : ""}
|
||||
></ListOrdered>
|
||||
|
||||
<FileCode2
|
||||
onClick={() => editor.chain().focus().toggleCodeBlock().run()}
|
||||
className={editor.isActive("codeBlock") ? "is-active" : ""}
|
||||
></FileCode2>
|
||||
<CustomTooltip title="代码块">
|
||||
<FileCode2
|
||||
onClick={() => editor.chain().focus().toggleCodeBlock().run()}
|
||||
className={editor.isActive("codeBlock") ? "is-active" : ""}
|
||||
></FileCode2>
|
||||
</CustomTooltip>
|
||||
|
||||
<MessageSquareQuote
|
||||
onClick={() => editor.chain().focus().toggleBlockquote().run()}
|
||||
@@ -194,31 +173,39 @@ const MenuBar = () => {
|
||||
Redo
|
||||
</button> */}
|
||||
<Redo onClick={() => editor.chain().focus().undo().run()}></Redo>
|
||||
<AlignLeft
|
||||
onClick={() => editor.chain().focus().setTextAlign("left").run()}
|
||||
className={editor.isActive({ textAlign: "left" }) ? "is-active" : ""}
|
||||
></AlignLeft>
|
||||
<AlignCenter
|
||||
onClick={() => editor.chain().focus().setTextAlign("center").run()}
|
||||
className={
|
||||
editor.isActive({ textAlign: "center" }) ? "is-active" : ""
|
||||
}
|
||||
></AlignCenter>
|
||||
<AlignRight
|
||||
onClick={() => editor.chain().focus().setTextAlign("right").run()}
|
||||
className={editor.isActive({ textAlign: "right" }) ? "is-active" : ""}
|
||||
></AlignRight>
|
||||
<CustomTooltip title="居左">
|
||||
<AlignLeft
|
||||
onClick={() => editor.chain().focus().setTextAlign("left").run()}
|
||||
className={
|
||||
editor.isActive({ textAlign: "left" }) ? "is-active" : ""
|
||||
}
|
||||
></AlignLeft>
|
||||
</CustomTooltip>
|
||||
|
||||
<CustomTooltip title="居中">
|
||||
<AlignCenter
|
||||
onClick={() => editor.chain().focus().setTextAlign("center").run()}
|
||||
className={
|
||||
editor.isActive({ textAlign: "center" }) ? "is-active" : ""
|
||||
}
|
||||
></AlignCenter>
|
||||
</CustomTooltip>
|
||||
|
||||
<CustomTooltip title="居右">
|
||||
<AlignRight
|
||||
onClick={() => editor.chain().focus().setTextAlign("right").run()}
|
||||
className={
|
||||
editor.isActive({ textAlign: "right" }) ? "is-active" : ""
|
||||
}
|
||||
></AlignRight>
|
||||
</CustomTooltip>
|
||||
<Popover>
|
||||
<PopoverTrigger>
|
||||
<Baseline></Baseline>
|
||||
<CustomTooltip title="文本颜色">
|
||||
<Palette></Palette>
|
||||
</CustomTooltip>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="w-80">
|
||||
{/* <div onClick={() => editor.chain().focus().setColor("blue").run()}>
|
||||
蓝色
|
||||
</div>
|
||||
<div onClick={() => editor.chain().focus().setColor("red").run()}>
|
||||
红色
|
||||
</div> */}
|
||||
<PopoverContent className="w-80 bg-[#21242a]">
|
||||
<ColorBar setCurrentColor={setCurrentColor}></ColorBar>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
import * as TooltipPrimitive from "@radix-ui/react-tooltip"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
const TooltipProvider = TooltipPrimitive.Provider
|
||||
|
||||
const Tooltip = TooltipPrimitive.Root
|
||||
|
||||
const TooltipTrigger = TooltipPrimitive.Trigger
|
||||
|
||||
const TooltipContent = React.forwardRef<
|
||||
React.ElementRef<typeof TooltipPrimitive.Content>,
|
||||
React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>
|
||||
>(({ className, sideOffset = 4, ...props }, ref) => (
|
||||
<TooltipPrimitive.Content
|
||||
ref={ref}
|
||||
sideOffset={sideOffset}
|
||||
className={cn(
|
||||
"z-50 overflow-hidden rounded-md border bg-popover px-3 py-1.5 text-sm text-popover-foreground shadow-md animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-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}
|
||||
/>
|
||||
))
|
||||
TooltipContent.displayName = TooltipPrimitive.Content.displayName
|
||||
|
||||
export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }
|
||||
@@ -114,6 +114,7 @@
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.25rem;
|
||||
padding: 4px;
|
||||
|
||||
.lucide {
|
||||
padding: 4px 6px;
|
||||
@@ -125,6 +126,10 @@
|
||||
font-weight: 700;
|
||||
color: #2ec4b6;
|
||||
}
|
||||
&:hover {
|
||||
border-radius: 4px;
|
||||
background-color: #e26d5c;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Generated
+54
@@ -104,6 +104,9 @@ importers:
|
||||
'@radix-ui/react-tabs':
|
||||
specifier: ^1.0.4
|
||||
version: 1.0.4(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1)
|
||||
'@radix-ui/react-tooltip':
|
||||
specifier: ^1.1.2
|
||||
version: 1.1.2(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1)
|
||||
'@tiptap/extension-color':
|
||||
specifier: ^2.4.0
|
||||
version: 2.4.0(@tiptap/core@2.4.0)(@tiptap/extension-text-style@2.4.0)
|
||||
@@ -1750,6 +1753,37 @@ packages:
|
||||
react-dom: 18.3.1(react@18.3.1)
|
||||
dev: false
|
||||
|
||||
/@radix-ui/react-tooltip@1.1.2(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1):
|
||||
resolution: {integrity: sha512-9XRsLwe6Yb9B/tlnYCPVUd/TFS4J7HuOZW345DCeC6vKIxQGMZdx21RK4VoZauPD5frgkXTYVS5y90L+3YBn4w==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
'@types/react-dom': '*'
|
||||
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
'@types/react-dom':
|
||||
optional: true
|
||||
dependencies:
|
||||
'@radix-ui/primitive': 1.1.0
|
||||
'@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.2)(react@18.3.1)
|
||||
'@radix-ui/react-context': 1.1.0(@types/react@18.3.2)(react@18.3.1)
|
||||
'@radix-ui/react-dismissable-layer': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1)
|
||||
'@radix-ui/react-id': 1.1.0(@types/react@18.3.2)(react@18.3.1)
|
||||
'@radix-ui/react-popper': 1.2.0(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1)
|
||||
'@radix-ui/react-portal': 1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1)
|
||||
'@radix-ui/react-presence': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1)
|
||||
'@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1)
|
||||
'@radix-ui/react-slot': 1.1.0(@types/react@18.3.2)(react@18.3.1)
|
||||
'@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.2)(react@18.3.1)
|
||||
'@radix-ui/react-visually-hidden': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1)
|
||||
'@types/react': 18.3.2
|
||||
'@types/react-dom': 18.3.0
|
||||
react: 18.3.1
|
||||
react-dom: 18.3.1(react@18.3.1)
|
||||
dev: false
|
||||
|
||||
/@radix-ui/react-use-callback-ref@1.0.1(@types/react@18.3.2)(react@18.3.1):
|
||||
resolution: {integrity: sha512-D94LjX4Sp0xJFVaoQOd3OO9k7tpBYNOXdVhkltUbGv2Qb9OXdrg/CpsjlZv7ia14Sylv398LswWBVVu5nqKzAQ==}
|
||||
peerDependencies:
|
||||
@@ -1875,6 +1909,26 @@ packages:
|
||||
react: 18.3.1
|
||||
dev: false
|
||||
|
||||
/@radix-ui/react-visually-hidden@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1):
|
||||
resolution: {integrity: sha512-N8MDZqtgCgG5S3aV60INAB475osJousYpZ4cTJ2cFbMpdHS5Y6loLTH8LPtkj2QN0x93J30HT/M3qJXM0+lyeQ==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
'@types/react-dom': '*'
|
||||
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
'@types/react-dom':
|
||||
optional: true
|
||||
dependencies:
|
||||
'@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1)
|
||||
'@types/react': 18.3.2
|
||||
'@types/react-dom': 18.3.0
|
||||
react: 18.3.1
|
||||
react-dom: 18.3.1(react@18.3.1)
|
||||
dev: false
|
||||
|
||||
/@radix-ui/rect@1.1.0:
|
||||
resolution: {integrity: sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg==}
|
||||
dev: false
|
||||
|
||||
Reference in New Issue
Block a user