From 839eb476e07fde4eb67fc5cd16848e3656e691f2 Mon Sep 17 00:00:00 2001 From: Nick Perez Date: Tue, 14 Jan 2025 08:33:11 +0100 Subject: [PATCH] docs: add a custom shortcuts example (#5981) --- .../Examples/EnterShortcuts/React/index.html | 0 .../EnterShortcuts/React/index.spec.js | 34 +++ .../Examples/EnterShortcuts/React/index.tsx | 88 ++++++++ .../Examples/EnterShortcuts/React/styles.scss | 91 ++++++++ .../Examples/EnterShortcuts/Vue/index.html | 0 .../Examples/EnterShortcuts/Vue/index.spec.js | 32 +++ .../src/Examples/EnterShortcuts/Vue/index.vue | 196 ++++++++++++++++++ 7 files changed, 441 insertions(+) create mode 100644 demos/src/Examples/EnterShortcuts/React/index.html create mode 100644 demos/src/Examples/EnterShortcuts/React/index.spec.js create mode 100644 demos/src/Examples/EnterShortcuts/React/index.tsx create mode 100644 demos/src/Examples/EnterShortcuts/React/styles.scss create mode 100644 demos/src/Examples/EnterShortcuts/Vue/index.html create mode 100644 demos/src/Examples/EnterShortcuts/Vue/index.spec.js create mode 100644 demos/src/Examples/EnterShortcuts/Vue/index.vue diff --git a/demos/src/Examples/EnterShortcuts/React/index.html b/demos/src/Examples/EnterShortcuts/React/index.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/demos/src/Examples/EnterShortcuts/React/index.spec.js b/demos/src/Examples/EnterShortcuts/React/index.spec.js new file mode 100644 index 0000000000..4e8359777a --- /dev/null +++ b/demos/src/Examples/EnterShortcuts/React/index.spec.js @@ -0,0 +1,34 @@ +/// + +context('/src/Examples/EnterShortcuts/React/', () => { + before(() => { + cy.visit('/src/Examples/EnterShortcuts/React/') + }) + + beforeEach(() => { + cy.get('.tiptap').then(([{ editor }]) => { + editor.commands.setContent('

Example Text

') + }) + }) + + it('should update the hint html when the keyboard shortcut is pressed', () => { + cy.get('.tiptap') + .trigger('keydown', { metaKey: true, key: 'Enter' }) + cy.get('.hint') + .should('contain', 'Meta-Enter was the last shortcut') + }) + + it('should update the hint html when the keyboard shortcut is pressed', () => { + cy.get('.tiptap') + .trigger('keydown', { shiftKey: true, key: 'Enter' }) + cy.get('.hint') + .should('contain', 'Shift-Enter was the last shortcut') + }) + + it('should update the hint html when the keyboard shortcut is pressed', () => { + cy.get('.tiptap') + .trigger('keydown', { ctrlKey: true, key: 'Enter' }) + cy.get('.hint') + .should('contain', 'Ctrl-Enter was the last shortcut') + }) +}) diff --git a/demos/src/Examples/EnterShortcuts/React/index.tsx b/demos/src/Examples/EnterShortcuts/React/index.tsx new file mode 100644 index 0000000000..5acc19e98c --- /dev/null +++ b/demos/src/Examples/EnterShortcuts/React/index.tsx @@ -0,0 +1,88 @@ +import './styles.scss' + +import { EditorContent, Extension, useEditor } from '@tiptap/react' +import StarterKit from '@tiptap/starter-kit' +import React from 'react' + +const CustomKeyboardShortcutExtension = Extension.create({ + name: 'customKeyboardShortcuts', + // Set a higher priority to make sure this extension is executed first before the default keyboard shortcuts + priority: 101, + addKeyboardShortcuts() { + return { + 'Ctrl-Enter': ctx => { + // Creates a transaction with this custom meta set + return ctx.editor.commands.setMeta('customKeyboardShortcutHandler', 'Ctrl-Enter') + }, + 'Meta-Enter': ctx => { + // Creates a transaction with this custom meta set + return ctx.editor.commands.setMeta('customKeyboardShortcutHandler', 'Meta-Enter') + }, + 'Shift-Enter': ctx => { + return ctx.editor.commands.setMeta('customKeyboardShortcutHandler', 'Shift-Enter') + }, + } + }, +}) + +export default () => { + const [lastShortcut, setLastShortcut] = React.useState(null) + const editor = useEditor({ + extensions: [StarterKit, CustomKeyboardShortcutExtension], + // Listen for the custom meta set in the transaction + onTransaction: ({ transaction }) => { + if (transaction.getMeta('customKeyboardShortcutHandler')) { + switch (transaction.getMeta('customKeyboardShortcutHandler')) { + case 'Ctrl-Enter': + setLastShortcut('Ctrl-Enter') + break + case 'Meta-Enter': + setLastShortcut('Meta-Enter') + break + case 'Shift-Enter': + setLastShortcut('Shift-Enter') + break + default: + break + } + } + }, + content: ` +

+ Hey, try to hit Shift+Enter, Ctrl+Enter or Meta+Enter. The last shortcut hit will be displayed above. +

+ `, + }) + + if (!editor) { + return null + } + + return ( + <> +
+
+ + +
+
+ {lastShortcut + ? `${lastShortcut} was the last shortcut hit, and was handled by React` + : 'No shortcut has been hit yet, use Shift+Enter to trigger a shortcut handler'} +
+
+ + + + ) +} diff --git a/demos/src/Examples/EnterShortcuts/React/styles.scss b/demos/src/Examples/EnterShortcuts/React/styles.scss new file mode 100644 index 0000000000..7694d7322a --- /dev/null +++ b/demos/src/Examples/EnterShortcuts/React/styles.scss @@ -0,0 +1,91 @@ +/* Basic editor styles */ +.tiptap { + :first-child { + margin-top: 0; + } + + /* List styles */ + ul, + ol { + padding: 0 1rem; + margin: 1.25rem 1rem 1.25rem 0.4rem; + + li p { + margin-top: 0.25em; + margin-bottom: 0.25em; + } + } + + /* Heading styles */ + h1, + h2, + h3, + h4, + h5, + h6 { + line-height: 1.1; + margin-top: 2.5rem; + text-wrap: pretty; + } + + h1, + h2 { + margin-top: 3.5rem; + margin-bottom: 1.5rem; + } + + h1 { + font-size: 1.4rem; + } + + h2 { + font-size: 1.2rem; + } + + h3 { + font-size: 1.1rem; + } + + h4, + h5, + h6 { + font-size: 1rem; + } + + /* Code and preformatted text styles */ + code { + background-color: var(--purple-light); + border-radius: 0.4rem; + color: var(--black); + font-size: 0.85rem; + padding: 0.25em 0.3em; + } + + pre { + background: var(--black); + border-radius: 0.5rem; + color: var(--white); + font-family: 'JetBrainsMono', monospace; + margin: 1.5rem 0; + padding: 0.75rem 1rem; + + code { + background: none; + color: inherit; + font-size: 0.8rem; + padding: 0; + } + } + + blockquote { + border-left: 3px solid var(--gray-3); + margin: 1.5rem 0; + padding-left: 1rem; + } + + hr { + border: none; + border-top: 1px solid var(--gray-2); + margin: 2rem 0; + } +} diff --git a/demos/src/Examples/EnterShortcuts/Vue/index.html b/demos/src/Examples/EnterShortcuts/Vue/index.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/demos/src/Examples/EnterShortcuts/Vue/index.spec.js b/demos/src/Examples/EnterShortcuts/Vue/index.spec.js new file mode 100644 index 0000000000..6e271a3bd8 --- /dev/null +++ b/demos/src/Examples/EnterShortcuts/Vue/index.spec.js @@ -0,0 +1,32 @@ +context('/src/Examples/EnterShortcuts/Vue/', () => { + before(() => { + cy.visit('/src/Examples/EnterShortcuts/Vue/') + }) + + beforeEach(() => { + cy.get('.tiptap').then(([{ editor }]) => { + editor.commands.setContent('

Example Text

') + }) + }) + + it('should update the hint html when the keyboard shortcut is pressed', () => { + cy.get('.tiptap') + .trigger('keydown', { metaKey: true, key: 'Enter' }) + cy.get('.hint') + .should('contain', 'Meta-Enter was the last shortcut') + }) + + it('should update the hint html when the keyboard shortcut is pressed', () => { + cy.get('.tiptap') + .trigger('keydown', { shiftKey: true, key: 'Enter' }) + cy.get('.hint') + .should('contain', 'Shift-Enter was the last shortcut') + }) + + it('should update the hint html when the keyboard shortcut is pressed', () => { + cy.get('.tiptap') + .trigger('keydown', { ctrlKey: true, key: 'Enter' }) + cy.get('.hint') + .should('contain', 'Ctrl-Enter was the last shortcut') + }) +}) diff --git a/demos/src/Examples/EnterShortcuts/Vue/index.vue b/demos/src/Examples/EnterShortcuts/Vue/index.vue new file mode 100644 index 0000000000..946eee6ed4 --- /dev/null +++ b/demos/src/Examples/EnterShortcuts/Vue/index.vue @@ -0,0 +1,196 @@ + + + + +