返回 presentation-ai
list-toolbar-button.tsx
根目录 / src / components / plate / ui / list-toolbar-button.tsx
1 "use client";
2
3 import { ListStyleType, someList, toggleList } from "@platejs/list";
4 import {
5 useIndentTodoToolBarButton,
6 useIndentTodoToolBarButtonState,
7 } from "@platejs/list/react";
8 import { List, ListOrdered, ListTodoIcon } from "lucide-react";
9 import { useEditorRef, useEditorSelector } from "platejs/react";
10 import * as React from "react";
11
12 import {
13 DropdownMenu,
14 DropdownMenuContent,
15 DropdownMenuGroup,
16 DropdownMenuItem,
17 DropdownMenuTrigger,
18 } from "@/components/plate/ui/dropdown-menu";
19 import {
20 ToolbarButton,
21 ToolbarSplitButton,
22 ToolbarSplitButtonPrimary,
23 ToolbarSplitButtonSecondary,
24 } from "./toolbar";
25
26 export function BulletedListToolbarButton() {
27 const editor = useEditorRef();
28 const [open, setOpen] = React.useState(false);
29
30 const pressed = useEditorSelector(
31 (editor) =>
32 someList(editor, [
33 ListStyleType.Disc,
34 ListStyleType.Circle,
35 ListStyleType.Square,
36 ]),
37 [],
38 );
39
40 return (
41 <ToolbarSplitButton pressed={open}>
42 <ToolbarSplitButtonPrimary
43 className="data-[state=on]:bg-accent data-[state=on]:text-accent-foreground"
44 onClick={() => {
45 toggleList(editor, {
46 listStyleType: ListStyleType.Disc,
47 });
48 }}
49 data-state={pressed ? "on" : "off"}
50 >
51 <List className="size-4" />
52 </ToolbarSplitButtonPrimary>
53
54 <DropdownMenu open={open} onOpenChange={setOpen} modal={false}>
55 <DropdownMenuTrigger asChild>
56 <ToolbarSplitButtonSecondary />
57 </DropdownMenuTrigger>
58
59 <DropdownMenuContent
60 className="ignore-click-outside/toolbar"
61 align="start"
62 alignOffset={-32}
63 >
64 <DropdownMenuGroup>
65 <DropdownMenuItem
66 onClick={() =>
67 toggleList(editor, {
68 listStyleType: ListStyleType.Disc,
69 })
70 }
71 >
72 <div className="flex items-center gap-2">
73 <div className="size-2 rounded-full border border-current bg-current" />
74 Default
75 </div>
76 </DropdownMenuItem>
77 <DropdownMenuItem
78 onClick={() =>
79 toggleList(editor, {
80 listStyleType: ListStyleType.Circle,
81 })
82 }
83 >
84 <div className="flex items-center gap-2">
85 <div className="size-2 rounded-full border border-current" />
86 Circle
87 </div>
88 </DropdownMenuItem>
89 <DropdownMenuItem
90 onClick={() =>
91 toggleList(editor, {
92 listStyleType: ListStyleType.Square,
93 })
94 }
95 >
96 <div className="flex items-center gap-2">
97 <div className="size-2 border border-current bg-current" />
98 Square
99 </div>
100 </DropdownMenuItem>
101 </DropdownMenuGroup>
102 </DropdownMenuContent>
103 </DropdownMenu>
104 </ToolbarSplitButton>
105 );
106 }
107
108 export function NumberedListToolbarButton() {
109 const editor = useEditorRef();
110 const [open, setOpen] = React.useState(false);
111
112 const pressed = useEditorSelector(
113 (editor) =>
114 someList(editor, [
115 ListStyleType.Decimal,
116 ListStyleType.LowerAlpha,
117 ListStyleType.UpperAlpha,
118 ListStyleType.LowerRoman,
119 ListStyleType.UpperRoman,
120 ]),
121 [],
122 );
123
124 return (
125 <ToolbarSplitButton pressed={open}>
126 <ToolbarSplitButtonPrimary
127 className="data-[state=on]:bg-accent data-[state=on]:text-accent-foreground"
128 onClick={() =>
129 toggleList(editor, {
130 listStyleType: ListStyleType.Decimal,
131 })
132 }
133 data-state={pressed ? "on" : "off"}
134 >
135 <ListOrdered className="size-4" />
136 </ToolbarSplitButtonPrimary>
137
138 <DropdownMenu open={open} onOpenChange={setOpen} modal={false}>
139 <DropdownMenuTrigger asChild>
140 <ToolbarSplitButtonSecondary />
141 </DropdownMenuTrigger>
142
143 <DropdownMenuContent
144 className="ignore-click-outside/toolbar"
145 align="start"
146 alignOffset={-32}
147 >
148 <DropdownMenuGroup>
149 <DropdownMenuItem
150 onSelect={() =>
151 toggleList(editor, {
152 listStyleType: ListStyleType.Decimal,
153 })
154 }
155 >
156 Decimal (1, 2, 3)
157 </DropdownMenuItem>
158 <DropdownMenuItem
159 onSelect={() =>
160 toggleList(editor, {
161 listStyleType: ListStyleType.LowerAlpha,
162 })
163 }
164 >
165 Lower Alpha (a, b, c)
166 </DropdownMenuItem>
167 <DropdownMenuItem
168 onSelect={() =>
169 toggleList(editor, {
170 listStyleType: ListStyleType.UpperAlpha,
171 })
172 }
173 >
174 Upper Alpha (A, B, C)
175 </DropdownMenuItem>
176 <DropdownMenuItem
177 onSelect={() =>
178 toggleList(editor, {
179 listStyleType: ListStyleType.LowerRoman,
180 })
181 }
182 >
183 Lower Roman (i, ii, iii)
184 </DropdownMenuItem>
185 <DropdownMenuItem
186 onSelect={() =>
187 toggleList(editor, {
188 listStyleType: ListStyleType.UpperRoman,
189 })
190 }
191 >
192 Upper Roman (I, II, III)
193 </DropdownMenuItem>
194 </DropdownMenuGroup>
195 </DropdownMenuContent>
196 </DropdownMenu>
197 </ToolbarSplitButton>
198 );
199 }
200
201 export function TodoListToolbarButton(
202 props: React.ComponentProps<typeof ToolbarButton>,
203 ) {
204 const state = useIndentTodoToolBarButtonState({ nodeType: "todo" });
205 const { props: buttonProps } = useIndentTodoToolBarButton(state);
206
207 return (
208 <ToolbarButton {...props} {...buttonProps} tooltip="Todo">
209 <ListTodoIcon />
210 </ToolbarButton>
211 );
212 }
213
213 lines Plain Text