Skip to content

Commit

Permalink
fix(extensions): disable commands that cannot be used in certain oper…
Browse files Browse the repository at this point in the history
…ations
  • Loading branch information
yikoyu committed Jan 20, 2024
1 parent d33c67a commit 7432b7e
Show file tree
Hide file tree
Showing 28 changed files with 60 additions and 5 deletions.
8 changes: 7 additions & 1 deletion src/components/BubbleMenu.vue
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,13 @@ const items = computed(() => {
<!-- Divider -->
<VDivider v-if="item.type === 'divider'" vertical class="mx-1 me-2" />
<!-- Buttons -->
<component :is="item.component" v-else v-bind="item.componentProps" :editor="editor" :disabled="disabled">
<component
:is="item.component"
v-else
v-bind="item.componentProps"
:editor="editor"
:disabled="disabled || item.componentProps?.disabled"
>
<template v-for="(element, slotName, i) in item.componentSlots" :key="i" #[`${slotName}`]="values">
<component :is="element" v-bind="values?.props" />
</template>
Expand Down
7 changes: 6 additions & 1 deletion src/components/TiptapToolbar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,12 @@ const items = computed(() => {
<!-- Spacer -->
<VSpacer v-if="item.spacer" />
<!-- Buttons -->
<component :is="item.button.component" v-bind="item.button.componentProps" :editor="editor" :disabled="disabled">
<component
:is="item.button.component"
v-bind="item.button.componentProps"
:editor="editor"
:disabled="disabled || item.button.componentProps?.disabled"
>
<template v-for="(element, slotName, i) in item.button.componentSlots" :key="i" #[`${slotName}`]="values">
<component :is="element" v-bind="values?.props" />
</template>
Expand Down
1 change: 1 addition & 0 deletions src/extensions/blockquote.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export const Blockquote = /* @__PURE__*/ TiptapBlockquote.extend<BlockquoteOptio
componentProps: {
action: () => editor.commands.toggleBlockquote(),
isActive: () => editor.isActive('blockquote') || false,
disabled: !editor.can().toggleBlockquote(),
icon: 'blockquote',
tooltip: t('editor.blockquote.tooltip')
}
Expand Down
1 change: 1 addition & 0 deletions src/extensions/bold.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export const Bold = /* @__PURE__*/ TiptapBold.extend<BoldOptions>({
componentProps: {
action: () => editor.commands.toggleBold(),
isActive: () => editor.isActive('bold') || false,
disabled: !editor.can().toggleBold(),
icon: 'bold',
tooltip: t('editor.bold.tooltip')
}
Expand Down
1 change: 1 addition & 0 deletions src/extensions/bullet-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export const BulletList = /* @__PURE__*/ TiptapBulletList.extend<BulletListOptio
componentProps: {
action: () => editor.commands.toggleBulletList(),
isActive: () => editor.isActive('bulletList') || false,
disabled: !editor.can().toggleBulletList(),
icon: 'bulletList',
tooltip: t('editor.bulletlist.tooltip')
}
Expand Down
1 change: 1 addition & 0 deletions src/extensions/clear.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export const Clear = /* @__PURE__*/ Node.create<ClearOptions>({
component: ActionButton,
componentProps: {
action: () => editor.chain().focus().clearNodes().unsetAllMarks().run(),
disabled: !editor.can().chain().focus().clearNodes().unsetAllMarks().run(),
icon: 'clear',
tooltip: t('editor.clear.tooltip')
}
Expand Down
1 change: 1 addition & 0 deletions src/extensions/code-block.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export const CodeBlock = /* @__PURE__*/ TiptapCodeBlock.extend<CodeBlockOptions>
componentProps: {
action: () => editor.commands.toggleCodeBlock(),
isActive: () => editor.isActive('codeBlock') || false,
disabled: !editor.can().toggleCodeBlock(),
icon: 'codeBlock',
tooltip: t('editor.codeblock.tooltip')
}
Expand Down
1 change: 1 addition & 0 deletions src/extensions/code.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export const Code = /* @__PURE__*/ TiptapCode.extend<CodeOptions>({
componentProps: {
action: () => editor.commands.toggleCode(),
isActive: () => editor.isActive('code') || false,
disabled: !editor.can().toggleCode(),
icon: 'code',
tooltip: t('editor.code.tooltip')
}
Expand Down
1 change: 1 addition & 0 deletions src/extensions/color.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export const Color = /* @__PURE__*/ TiptapColor.extend<ColorOptions>({
if (!color) return false
return editor.isActive({ color }) || false
},
disabled: !editor.can().setColor(''),
icon: 'color',
tooltip: t('editor.color.tooltip')
}
Expand Down
3 changes: 2 additions & 1 deletion src/extensions/components/ActionMenuButton.vue
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export interface Item {
isActive: NonNullable<ButtonViewReturnComponentProps['isActive']>
action?: ButtonViewReturnComponentProps['action']
style?: StyleValue
disabled?: boolean
divider?: boolean
default?: boolean
}
Expand Down Expand Up @@ -73,7 +74,7 @@ interface Props {
<VMenu v-model="menu" activator="parent">
<VList density="compact" :max-height="maxHeight">
<template v-for="(item, i) in items" :key="i">
<VListItem :active="item.isActive()" @click="item.action">
<VListItem :active="item.isActive()" :disabled="item.disabled" @click="item.action">
<template #prepend>
<VIcon v-if="item.icon" :icon="getIcon(item.icon)" />
</template>
Expand Down
4 changes: 4 additions & 0 deletions src/extensions/font-family.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,16 +41,20 @@ export const FontFamily = /* @__PURE__*/ TiptapFontFamily.extend<FontFamilyOptio

editor.commands.setFontFamily(k.value)
},
disabled: !editor.can().setFontFamily(k.value),
style: { fontFamily: k.value },
divider: k.divider ?? false,
default: k.default ?? false
}))

const disabled = items.filter(k => k.disabled).length === items.length

return {
component: ActionMenuButton,
componentProps: {
icon: 'fontFamily',
tooltip: t('editor.fontFamily.tooltip'),
disabled,
items,
maxHeight: 280
}
Expand Down
4 changes: 4 additions & 0 deletions src/extensions/font-size.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,19 @@ export const FontSize = /* @__PURE__*/ Extension.create<FontSizeOptions>({

editor.commands.setFontSize(String(k))
},
disabled: !editor.can().setFontSize(String(k)),
divider: k === DEFAULT_FONT_SIZE_VALUUE ?? false,
default: k === DEFAULT_FONT_SIZE_VALUUE ?? false
}))

const disabled = items.filter(k => k.disabled).length === items.length

return {
component: ActionMenuButton,
componentProps: {
icon: 'fontSize',
tooltip: t('editor.fontSize.tooltip'),
disabled,
items,
maxHeight: 280
}
Expand Down
5 changes: 5 additions & 0 deletions src/extensions/heading.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export const Heading = /* @__PURE__*/ TiptapHeading.extend<HeadingOptions>({
const items: Item[] = levels.map(level => ({
action: () => editor.commands.toggleHeading({ level }),
isActive: () => editor.isActive('heading', { level }) || false,
disabled: !editor.can().toggleHeading({ level }),
icon: `h${level}`,
title: t(`editor.heading.h${level}.tooltip`)
}))
Expand All @@ -33,17 +34,21 @@ export const Heading = /* @__PURE__*/ TiptapHeading.extend<HeadingOptions>({
items.unshift({
action: () => editor.commands.setParagraph(),
isActive: () => editor.isActive('paragraph') || false,
disabled: !editor.can().setParagraph(),
icon: 'p',
title: t('editor.paragraph.tooltip'),
divider: true
})
}

const disabled = items.filter(k => k.disabled).length === items.length

return {
component: ActionMenuButton,
componentProps: {
icon: 'heading',
tooltip: t('editor.heading.tooltip'),
disabled,
items
}
}
Expand Down
1 change: 1 addition & 0 deletions src/extensions/highlight.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export const Highlight = /* @__PURE__*/ TiptapHighlight.extend<HighlightOptions>
if (typeof color === 'string') editor.commands.setHighlight({ color })
},
isActive: () => editor.isActive('highlight') || false,
disabled: !editor.can().setHighlight(),
icon: 'highlight',
tooltip: t('editor.highlight.tooltip')
}
Expand Down
1 change: 1 addition & 0 deletions src/extensions/history.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export const History = /* @__PURE__*/ TiptapHistory.extend<HistoryOptions>({
if (item === 'undo') editor.commands.undo()
if (item === 'redo') editor.commands.redo()
},
disabled: !editor.can()[item](),
icon: item,
tooltip: t(`editor.${item}.tooltip`)
}
Expand Down
1 change: 1 addition & 0 deletions src/extensions/horizontal-rule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export const HorizontalRule = /* @__PURE__*/ TiptapHorizontalRule.extend<Horizon
component: ActionButton,
componentProps: {
action: () => editor.commands.setHorizontalRule(),
disabled: !editor.can().setHorizontalRule(),
icon: 'horizontalRule',
tooltip: t('editor.horizontalrule.tooltip')
}
Expand Down
1 change: 1 addition & 0 deletions src/extensions/image.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ export const Image = /* @__PURE__*/ TiptapImage.extend<ImageOptions>({
imageTabs,
hiddenTabs,
isActive: () => editor.isActive('image') || false,
disabled: !editor.can().setImage({}),
icon: 'image',
tooltip: t('editor.image.tooltip')
},
Expand Down
5 changes: 5 additions & 0 deletions src/extensions/indent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ export const Indent = /* @__PURE__*/ Extension.create<IndentOptions>({
spacer: false,
button: ({ editor, t }) => {
const items: ['indent', 'outdent'] = ['indent', 'outdent']
const commands = {
indent: 'sinkListItem',
outdent: 'liftListItem'
} as const

return items.map(item => ({
component: ActionButton,
Expand All @@ -24,6 +28,7 @@ export const Indent = /* @__PURE__*/ Extension.create<IndentOptions>({
if (item === 'indent') editor.commands.sinkListItem('listItem')
if (item === 'outdent') editor.commands.liftListItem('listItem')
},
disabled: !editor.can()[commands[item]]('listItem'),
icon: item,
tooltip: t(`editor.${item}.tooltip`)
}
Expand Down
1 change: 1 addition & 0 deletions src/extensions/italic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export const Italic = /* @__PURE__*/ TiptapItalic.extend<ItalicOptions>({
componentProps: {
action: () => editor.commands.toggleItalic(),
isActive: () => editor.isActive('italic') || false,
disabled: !editor.can().toggleItalic(),
icon: 'italic',
tooltip: t('editor.italic.tooltip')
}
Expand Down
1 change: 1 addition & 0 deletions src/extensions/link.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export const Link = /* @__PURE__*/ TiptapLink.extend<LinkOptions>({
component: LinkActionButton,
componentProps: {
isActive: () => editor.isActive('link') || false,
disabled: !editor.can().setLink({ href: '' }),
icon: 'link',
tooltip: t('editor.link.tooltip')
},
Expand Down
1 change: 1 addition & 0 deletions src/extensions/ordered-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export const OrderedList = /* @__PURE__*/ TiptapOrderedList.extend<OrderedListOp
componentProps: {
action: () => editor.commands.toggleOrderedList(),
isActive: () => editor.isActive('orderedList') || false,
disabled: !editor.can().toggleOrderedList(),
icon: 'orderedList',
tooltip: t('editor.orderedlist.tooltip')
}
Expand Down
1 change: 1 addition & 0 deletions src/extensions/strike.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export const Strike = /* @__PURE__*/ TiptapStrike.extend<StrikeOptions>({
componentProps: {
action: () => editor.commands.toggleStrike(),
isActive: () => editor.isActive('strike') || false,
disabled: !editor.can().toggleStrike(),
icon: 'strike',
tooltip: t('editor.strike.tooltip')
}
Expand Down
2 changes: 2 additions & 0 deletions src/extensions/subscript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export const SubAndSuperScript = /* @__PURE__*/ Extension.create<SubAndSuperScri
componentProps: {
action: () => editor.commands.toggleSubscript(),
isActive: () => editor.isActive('subscript') || false,
disabled: !editor.can().toggleSubscript(),
icon: 'subscript',
tooltip: t('editor.subscript.tooltip')
}
Expand All @@ -40,6 +41,7 @@ export const SubAndSuperScript = /* @__PURE__*/ Extension.create<SubAndSuperScri
componentProps: {
action: () => editor.commands.toggleSuperscript(),
isActive: () => editor.isActive('superscript') || false,
disabled: !editor.can().toggleSuperscript(),
icon: 'superscript',
tooltip: t('editor.superscript.tooltip')
}
Expand Down
1 change: 1 addition & 0 deletions src/extensions/table.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export const Table = /* @__PURE__*/ TiptapTable.extend<TableOptions>({
component: TableActionButton,
componentProps: {
isActive: () => editor.isActive('table') || false,
disabled: !editor.can().insertTable(),
icon: 'table',
tooltip: t('editor.table.tooltip')
}
Expand Down
1 change: 1 addition & 0 deletions src/extensions/task-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export const TaskList = /* @__PURE__*/ TiptapTaskList.extend<TaskListOptions>({
componentProps: {
action: () => editor.commands.toggleTaskList(),
isActive: () => editor.isActive('taskList') || false,
disabled: !editor.can().toggleTaskList(),
icon: 'taskList',
tooltip: t('editor.tasklist.tooltip')
}
Expand Down
6 changes: 5 additions & 1 deletion src/extensions/text-align.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,18 @@ export const TextAlign = /* @__PURE__*/ TiptapTextAlign.extend<TextAlignOptions>
title: t(`editor.textalign.${k}.tooltip`),
icon: k,
isActive: () => editor.isActive({ textAlign: k }) || false,
action: () => editor.commands.setTextAlign(k)
action: () => editor.commands.setTextAlign(k),
disabled: !editor.can().setTextAlign(k)
}))

const disabled = items.filter(k => k.disabled).length === items.length

return {
component: ActionMenuButton,
componentProps: {
icon: 'center',
tooltip: t('editor.textalign.tooltip'),
disabled,
items
}
}
Expand Down
1 change: 1 addition & 0 deletions src/extensions/underline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export const Underline = /* @__PURE__*/ TiptapUnderline.extend<UnderlineOptions>
componentProps: {
action: () => editor.commands.toggleUnderline(),
isActive: () => editor.isActive('underline') || false,
disabled: !editor.can().toggleUnderline(),
icon: 'underline',
tooltip: t('editor.underline.tooltip')
}
Expand Down
3 changes: 2 additions & 1 deletion src/extensions/video.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,8 @@ export const Video = /* @__PURE__*/ Node.create<VideoOptions>({
},
componentSlots: {
dialog: dialogComponent()
}
},
disabled: !editor.can().setVideo({})
}
}
}
Expand Down

0 comments on commit 7432b7e

Please sign in to comment.