From 8ff0997f3ed17a255726b0dc8494579f08428e3e Mon Sep 17 00:00:00 2001 From: Hans Pagel Date: Wed, 3 Feb 2021 11:06:42 +0100 Subject: [PATCH] add placeholder experiment --- .../Placeholder/extension/placeholder.ts | 67 +++++++++++++++++++ .../demos/Experiments/Placeholder/index.vue | 56 ++++++++++++++++ docs/src/docPages/experiments.md | 2 +- docs/src/docPages/experiments/placeholder.md | 5 ++ 4 files changed, 129 insertions(+), 1 deletion(-) create mode 100644 docs/src/demos/Experiments/Placeholder/extension/placeholder.ts create mode 100644 docs/src/demos/Experiments/Placeholder/index.vue create mode 100644 docs/src/docPages/experiments/placeholder.md diff --git a/docs/src/demos/Experiments/Placeholder/extension/placeholder.ts b/docs/src/demos/Experiments/Placeholder/extension/placeholder.ts new file mode 100644 index 000000000..a26207e9c --- /dev/null +++ b/docs/src/demos/Experiments/Placeholder/extension/placeholder.ts @@ -0,0 +1,67 @@ +import { Extension } from '@tiptap/core' +import { Decoration, DecorationSet } from 'prosemirror-view' +import { Plugin } from 'prosemirror-state' + +export interface PlaceholderOptions { + emptyEditorClass: string, + emptyNodeClass: string, + placeholder: string | Function, + showOnlyWhenEditable: boolean, + showOnlyCurrent: boolean, +} + +export default Extension.create({ + name: 'placeholder', + + defaultOptions: { + emptyEditorClass: 'is-editor-empty', + emptyNodeClass: 'is-empty', + placeholder: 'Write something …', + showOnlyWhenEditable: true, + showOnlyCurrent: true, + }, + + addProseMirrorPlugins() { + return [ + new Plugin({ + props: { + decorations: ({ doc, selection }) => { + const active = this.editor.isEditable || !this.options.showOnlyWhenEditable + const { anchor } = selection + const decorations: Decoration[] = [] + const isEditorEmpty = doc.textContent.length === 0 + + if (!active) { + return + } + + doc.descendants((node, pos) => { + const hasAnchor = anchor >= pos && anchor <= (pos + node.nodeSize) + const isNodeEmpty = node.content.size === 0 + + if ((hasAnchor || !this.options.showOnlyCurrent) && isNodeEmpty) { + const classes = [this.options.emptyNodeClass] + + if (isEditorEmpty) { + classes.push(this.options.emptyEditorClass) + } + + const decoration = Decoration.node(pos, pos + node.nodeSize, { + class: classes.join(' '), + 'data-empty-text': typeof this.options.placeholder === 'function' + ? this.options.placeholder(node) + : this.options.placeholder, + }) + decorations.push(decoration) + } + + return false + }) + + return DecorationSet.create(doc, decorations) + }, + }, + }), + ] + }, +}) diff --git a/docs/src/demos/Experiments/Placeholder/index.vue b/docs/src/demos/Experiments/Placeholder/index.vue new file mode 100644 index 000000000..ee22bdd63 --- /dev/null +++ b/docs/src/demos/Experiments/Placeholder/index.vue @@ -0,0 +1,56 @@ + + + + + diff --git a/docs/src/docPages/experiments.md b/docs/src/docPages/experiments.md index 89d5f0902..d529d93e4 100644 --- a/docs/src/docPages/experiments.md +++ b/docs/src/docPages/experiments.md @@ -9,4 +9,4 @@ Congratulations! You’ve found our secret playground with a list of experiments * [Commands](/experiments/commands) ## Waiting for approval -– +* [Placeholder](/experiments/placeholder) diff --git a/docs/src/docPages/experiments/placeholder.md b/docs/src/docPages/experiments/placeholder.md new file mode 100644 index 000000000..fe2e669f3 --- /dev/null +++ b/docs/src/docPages/experiments/placeholder.md @@ -0,0 +1,5 @@ +# Placeholder + +⚠️ Experiment + +