返回 presentation-ai
editor.tsx
根目录 / src / components / plate / ui / editor.tsx
1 "use client";
2
3 import { cva, type VariantProps } from "class-variance-authority";
4 import {
5 PlateContainer,
6 PlateContent,
7 type PlateContentProps,
8 } from "platejs/react";
9 import type * as React from "react";
10
11 import { cn } from "@/lib/utils";
12
13 const editorContainerVariants = cva(
14 "relative w-full cursor-text caret-primary select-text selection:bg-brand/25 focus-visible:outline-hidden [&_.slate-selection-area]:z-50 [&_.slate-selection-area]:border [&_.slate-selection-area]:border-brand/25 [&_.slate-selection-area]:bg-brand/15",
15 {
16 defaultVariants: {
17 variant: "default",
18 },
19 variants: {
20 variant: {
21 comment: cn(
22 "flex flex-wrap justify-between gap-1 px-1.5 py-1 text-sm",
23 "rounded-lg border border-transparent bg-transparent",
24 "has-[[data-slate-editor]:focus]:border-border/50 has-[[data-slate-editor]:focus]:bg-muted/20",
25 "has-aria-disabled:border-input has-aria-disabled:bg-muted",
26 ),
27 default: "h-full overflow-y-auto",
28 demo: "h-162.5 overflow-y-auto",
29 // Notes variant: no overflow, let parent handle scrolling
30 notes: "",
31 select: cn(
32 "group rounded-md border border-input ring-offset-background focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2",
33 "has-data-readonly:w-fit has-data-readonly:cursor-default has-data-readonly:border-transparent has-data-readonly:focus-within:[box-shadow:none]",
34 ),
35 },
36 },
37 },
38 );
39
40 export function EditorContainer({
41 className,
42 variant,
43 ...props
44 }: React.ComponentProps<"div"> & VariantProps<typeof editorContainerVariants>) {
45 return (
46 <PlateContainer
47 data-print-editor-surface="true"
48 className={cn(
49 // "ignore-click-outside/toolbar",
50 editorContainerVariants({ variant }),
51 className,
52 )}
53 {...props}
54 />
55 );
56 }
57
58 const editorVariants = cva(
59 cn(
60 "group/editor",
61 "relative w-full cursor-text overflow-x-hidden wrap-break-word whitespace-pre-wrap select-text",
62 "rounded-md ring-offset-background focus-visible:outline-hidden",
63 "placeholder:text-muted-foreground/80 data-slate-placeholder:**:top-[auto_!important] data-slate-placeholder:**:text-muted-foreground/80 data-slate-placeholder:**:opacity-100!",
64 "[&_strong]:font-bold",
65 ),
66 {
67 defaultVariants: {
68 variant: "default",
69 },
70 variants: {
71 disabled: {
72 true: "cursor-not-allowed opacity-50",
73 },
74 focused: {
75 true: "ring-2 ring-ring ring-offset-2",
76 },
77 variant: {
78 ghost: "",
79 allweone: "size-full pt-4 pb-72 text-base",
80 ai: "w-full px-0 text-base md:text-sm",
81 aiChat:
82 "max-h-[min(70vh,320px)] w-full max-w-175 overflow-y-auto px-3 py-2 text-base md:text-sm",
83 comment: cn("rounded-none border-none bg-transparent text-sm"),
84 default:
85 "size-full px-16 pt-4 pb-72 text-base sm:px-[max(64px,calc(50%-350px))]",
86 demo: "size-full px-16 pt-4 pb-72 text-base sm:px-[max(64px,calc(50%-350px))]",
87 fullWidth: "size-full px-16 pt-4 pb-72 text-base sm:px-24",
88 none: "",
89 select: "px-3 py-2 text-base data-readonly:w-fit",
90 },
91 },
92 },
93 );
94
95 export type EditorProps = PlateContentProps &
96 VariantProps<typeof editorVariants>;
97
98 export const Editor = ({
99 className,
100 disabled,
101 focused,
102 variant,
103 ref,
104 ...props
105 }: EditorProps & React.RefAttributes<HTMLDivElement>) => {
106 return (
107 <PlateContent
108 ref={ref}
109 className={cn(
110 editorVariants({
111 disabled,
112 focused,
113 variant,
114 }),
115 className,
116 )}
117 disabled={disabled}
118 disableDefaultStyles
119 {...props}
120 />
121 );
122 };
123
124 Editor.displayName = "Editor";
125
125 lines Plain Text