| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176 |
- import type { Editor } from '@tiptap/vue-3';
- import type { ShallowRef } from 'vue';
- import type { ToolbarAction, ToolbarMenuItem } from './types';
- import { cn } from '@vben-core/shared/utils';
- interface UseTiptapToolbarOptions {
- editable: () => boolean;
- editor: Readonly<ShallowRef<Editor | undefined>>;
- }
- export function useTiptapToolbar(options: UseTiptapToolbarOptions) {
- const getEditor = () => options.editor.value;
- function getActionIndicatorColor(action: ToolbarAction) {
- const currentEditor = getEditor();
- if (!currentEditor || !action.indicatorColor) {
- return undefined;
- }
- return action.indicatorColor(currentEditor);
- }
- function getPaletteCurrentColor(action: ToolbarAction) {
- const currentEditor = getEditor();
- if (!currentEditor || !action.palette?.currentColor) {
- return undefined;
- }
- return action.palette.currentColor(currentEditor);
- }
- function canRunAction(action: ToolbarAction) {
- const currentEditor = getEditor();
- if (!currentEditor || !options.editable()) {
- return false;
- }
- return action.can ? action.can(currentEditor) : true;
- }
- function canRunMenuItem(item: ToolbarMenuItem) {
- const currentEditor = getEditor();
- if (!currentEditor || !options.editable()) {
- return false;
- }
- return item.can ? item.can(currentEditor) : true;
- }
- function isActionActive(action: ToolbarAction) {
- const currentEditor = getEditor();
- if (!currentEditor) {
- return false;
- }
- if (action.isActive) {
- return action.isActive(currentEditor);
- }
- if (!action.active) {
- return false;
- }
- return currentEditor.isActive(action.active.name, action.active.attrs);
- }
- function isMenuItemActive(item: ToolbarMenuItem, currentEditor?: Editor) {
- const targetEditor = currentEditor ?? getEditor();
- if (!targetEditor || !item.isActive) {
- return false;
- }
- return item.isActive(targetEditor);
- }
- function runAction(action: ToolbarAction) {
- const currentEditor = getEditor();
- if (!currentEditor || !options.editable()) {
- return;
- }
- if (action.menu || action.palette) {
- return;
- }
- action.action(currentEditor);
- }
- function runMenuItem(item: ToolbarMenuItem) {
- const currentEditor = getEditor();
- if (!currentEditor || !options.editable()) {
- return;
- }
- item.action(currentEditor);
- }
- function applyPaletteColor(action: ToolbarAction, color: string) {
- const currentEditor = getEditor();
- if (!currentEditor || !action.palette) {
- return;
- }
- action.palette.apply(currentEditor, color);
- }
- function clearPaletteColor(action: ToolbarAction) {
- const currentEditor = getEditor();
- if (!currentEditor || !action.palette?.clear) {
- return;
- }
- action.palette.clear(currentEditor);
- }
- function getToolbarButtonClass(action: ToolbarAction) {
- return cn(
- 'text-muted-foreground relative rounded-[10px] border border-transparent bg-transparent shadow-none',
- 'transition-[transform,color,background-color,border-color,box-shadow] duration-200 ease-out',
- 'enabled:hover:border-border enabled:hover:-translate-y-px disabled:opacity-45',
- 'enabled:hover:bg-accent enabled:hover:text-foreground',
- isActionActive(action) &&
- 'bg-accent border-primary/30 shadow-primary text-primary',
- );
- }
- function getPaletteSwatchClass(action: ToolbarAction, color: string) {
- return cn(
- 'border-border inline-flex size-8 items-center justify-center rounded-full border',
- 'shadow-accent',
- 'transition-[transform,box-shadow,border-color] duration-200 ease-out',
- 'hover:-translate-y-px hover:scale-[1.04]',
- getPaletteCurrentColor(action) === color &&
- 'border-primary shadow-primary',
- );
- }
- function getMenuItemClass(item: ToolbarMenuItem) {
- return cn(
- 'flex items-center gap-2 rounded-lg p-2 text-left text-sm transition-colors',
- 'disabled:cursor-not-allowed disabled:opacity-45',
- isMenuItemActive(item)
- ? 'bg-accent text-foreground'
- : 'hover:bg-accent hover:text-foreground text-muted-foreground',
- );
- }
- return {
- applyPaletteColor,
- canRunAction,
- canRunMenuItem,
- clearPaletteColor,
- getActionIndicatorColor,
- getMenuItemClass,
- getPaletteCurrentColor,
- getPaletteSwatchClass,
- getToolbarButtonClass,
- isActionActive,
- isMenuItemActive,
- runAction,
- runMenuItem,
- };
- }
|