207 lines
5.8 KiB
TypeScript
207 lines
5.8 KiB
TypeScript
'use client';
|
|
|
|
import * as React from 'react';
|
|
|
|
import { ListStyleType, someList, toggleList } from '@platejs/list';
|
|
import {
|
|
useIndentTodoToolBarButton,
|
|
useIndentTodoToolBarButtonState,
|
|
} from '@platejs/list/react';
|
|
import { List, ListOrdered, ListTodoIcon } from 'lucide-react';
|
|
import { useEditorRef, useEditorSelector } from 'platejs/react';
|
|
|
|
import {
|
|
DropdownMenu,
|
|
DropdownMenuContent,
|
|
DropdownMenuGroup,
|
|
DropdownMenuItem,
|
|
DropdownMenuTrigger,
|
|
} from '@/components/ui/dropdown-menu';
|
|
|
|
import {
|
|
ToolbarButton,
|
|
ToolbarSplitButton,
|
|
ToolbarSplitButtonPrimary,
|
|
ToolbarSplitButtonSecondary,
|
|
} from './toolbar';
|
|
|
|
export function BulletedListToolbarButton() {
|
|
const editor = useEditorRef();
|
|
const [open, setOpen] = React.useState(false);
|
|
|
|
const pressed = useEditorSelector(
|
|
(editor) =>
|
|
someList(editor, [
|
|
ListStyleType.Disc,
|
|
ListStyleType.Circle,
|
|
ListStyleType.Square,
|
|
]),
|
|
[]
|
|
);
|
|
|
|
return (
|
|
<ToolbarSplitButton pressed={open}>
|
|
<ToolbarSplitButtonPrimary
|
|
className="data-[state=on]:bg-accent data-[state=on]:text-accent-foreground"
|
|
onClick={() => {
|
|
toggleList(editor, {
|
|
listStyleType: ListStyleType.Disc,
|
|
});
|
|
}}
|
|
data-state={pressed ? 'on' : 'off'}
|
|
>
|
|
<List className="size-4" />
|
|
</ToolbarSplitButtonPrimary>
|
|
|
|
<DropdownMenu open={open} onOpenChange={setOpen} modal={false}>
|
|
<DropdownMenuTrigger asChild>
|
|
<ToolbarSplitButtonSecondary />
|
|
</DropdownMenuTrigger>
|
|
|
|
<DropdownMenuContent align="start" alignOffset={-32}>
|
|
<DropdownMenuGroup>
|
|
<DropdownMenuItem
|
|
onClick={() =>
|
|
toggleList(editor, {
|
|
listStyleType: ListStyleType.Disc,
|
|
})
|
|
}
|
|
>
|
|
<div className="flex items-center gap-2">
|
|
<div className="size-2 rounded-full border border-current bg-current" />
|
|
Default
|
|
</div>
|
|
</DropdownMenuItem>
|
|
<DropdownMenuItem
|
|
onClick={() =>
|
|
toggleList(editor, {
|
|
listStyleType: ListStyleType.Circle,
|
|
})
|
|
}
|
|
>
|
|
<div className="flex items-center gap-2">
|
|
<div className="size-2 rounded-full border border-current" />
|
|
Circle
|
|
</div>
|
|
</DropdownMenuItem>
|
|
<DropdownMenuItem
|
|
onClick={() =>
|
|
toggleList(editor, {
|
|
listStyleType: ListStyleType.Square,
|
|
})
|
|
}
|
|
>
|
|
<div className="flex items-center gap-2">
|
|
<div className="size-2 border border-current bg-current" />
|
|
Square
|
|
</div>
|
|
</DropdownMenuItem>
|
|
</DropdownMenuGroup>
|
|
</DropdownMenuContent>
|
|
</DropdownMenu>
|
|
</ToolbarSplitButton>
|
|
);
|
|
}
|
|
|
|
export function NumberedListToolbarButton() {
|
|
const editor = useEditorRef();
|
|
const [open, setOpen] = React.useState(false);
|
|
|
|
const pressed = useEditorSelector(
|
|
(editor) =>
|
|
someList(editor, [
|
|
ListStyleType.Decimal,
|
|
ListStyleType.LowerAlpha,
|
|
ListStyleType.UpperAlpha,
|
|
ListStyleType.LowerRoman,
|
|
ListStyleType.UpperRoman,
|
|
]),
|
|
[]
|
|
);
|
|
|
|
return (
|
|
<ToolbarSplitButton pressed={open}>
|
|
<ToolbarSplitButtonPrimary
|
|
className="data-[state=on]:bg-accent data-[state=on]:text-accent-foreground"
|
|
onClick={() =>
|
|
toggleList(editor, {
|
|
listStyleType: ListStyleType.Decimal,
|
|
})
|
|
}
|
|
data-state={pressed ? 'on' : 'off'}
|
|
>
|
|
<ListOrdered className="size-4" />
|
|
</ToolbarSplitButtonPrimary>
|
|
|
|
<DropdownMenu open={open} onOpenChange={setOpen} modal={false}>
|
|
<DropdownMenuTrigger asChild>
|
|
<ToolbarSplitButtonSecondary />
|
|
</DropdownMenuTrigger>
|
|
|
|
<DropdownMenuContent align="start" alignOffset={-32}>
|
|
<DropdownMenuGroup>
|
|
<DropdownMenuItem
|
|
onSelect={() =>
|
|
toggleList(editor, {
|
|
listStyleType: ListStyleType.Decimal,
|
|
})
|
|
}
|
|
>
|
|
Decimal (1, 2, 3)
|
|
</DropdownMenuItem>
|
|
<DropdownMenuItem
|
|
onSelect={() =>
|
|
toggleList(editor, {
|
|
listStyleType: ListStyleType.LowerAlpha,
|
|
})
|
|
}
|
|
>
|
|
Lower Alpha (a, b, c)
|
|
</DropdownMenuItem>
|
|
<DropdownMenuItem
|
|
onSelect={() =>
|
|
toggleList(editor, {
|
|
listStyleType: ListStyleType.UpperAlpha,
|
|
})
|
|
}
|
|
>
|
|
Upper Alpha (A, B, C)
|
|
</DropdownMenuItem>
|
|
<DropdownMenuItem
|
|
onSelect={() =>
|
|
toggleList(editor, {
|
|
listStyleType: ListStyleType.LowerRoman,
|
|
})
|
|
}
|
|
>
|
|
Lower Roman (i, ii, iii)
|
|
</DropdownMenuItem>
|
|
<DropdownMenuItem
|
|
onSelect={() =>
|
|
toggleList(editor, {
|
|
listStyleType: ListStyleType.UpperRoman,
|
|
})
|
|
}
|
|
>
|
|
Upper Roman (I, II, III)
|
|
</DropdownMenuItem>
|
|
</DropdownMenuGroup>
|
|
</DropdownMenuContent>
|
|
</DropdownMenu>
|
|
</ToolbarSplitButton>
|
|
);
|
|
}
|
|
|
|
export function TodoListToolbarButton(
|
|
props: React.ComponentProps<typeof ToolbarButton>
|
|
) {
|
|
const state = useIndentTodoToolBarButtonState({ nodeType: 'todo' });
|
|
const { props: buttonProps } = useIndentTodoToolBarButton(state);
|
|
|
|
return (
|
|
<ToolbarButton {...props} {...buttonProps} tooltip="Todo">
|
|
<ListTodoIcon />
|
|
</ToolbarButton>
|
|
);
|
|
}
|