Skip to content
This repository has been archived by the owner on Nov 7, 2022. It is now read-only.

Commit

Permalink
refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
Darmody committed Jul 6, 2022
1 parent 575475f commit c60076d
Show file tree
Hide file tree
Showing 8 changed files with 430 additions and 323 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,63 @@ import { Editor } from '@tiptap/core'
import { Toolbar } from '../../ui/Toolbar'
import { useBubbleMenuItems } from './useBubbleMenuItems'
import { Button } from '@mashcard/design-system'
import { isTextContentSelected } from '../../../extensions/extensions/selection'
import { Base } from '../../../extensions/base'
import { BubbleMenuPlugin, BubbleMenuPluginProps } from './BubbleMenuPlugin'
import { findNodesInSelection } from '../../../helpers'
import { meta as paragraphMeta } from '../../../extensions/blocks/paragraph/meta'
import { meta as headingMeta } from '../../../extensions/blocks/heading/meta'
import { meta as listItemMeta } from '../../../extensions/blocks/listItem/meta'
import { meta as orderedListMeta } from '../../../extensions/blocks/orderedList/meta'
import { meta as bulletListMeta } from '../../../extensions/blocks/bulletList/meta'
import { meta as taskItemMeta } from '../../../extensions/blocks/taskItem/meta'
import { meta as taskListMeta } from '../../../extensions/blocks/taskList/meta'
import { meta as calloutMeta } from '../../../extensions/blocks/callout/meta'
import { meta as blockquoteMeta } from '../../../extensions/blocks/blockquote/meta'

interface BubbleMenuProps {
editor: Editor | null
}

const isTextContentSelected = ({ editor, from, to }: { editor: Editor; from: number; to: number }): boolean => {
const allowedNodeTypes = [
paragraphMeta.name,
headingMeta.name,
listItemMeta.name,
orderedListMeta.name,
bulletListMeta.name,
taskItemMeta.name,
taskListMeta.name,
calloutMeta.name,
blockquoteMeta.name
]

if (!editor.isEditable || editor.isDestroyed) return false
if (from === to) return false

const isEmpty = editor.state.doc.textBetween(from, to).length === 0

if (isEmpty) return false

let show = false

const nodes = findNodesInSelection(editor, from, to)

for (const { node } of nodes) {
if (node) {
// Text node
if (node.type.name === 'text') {
show = true
} else if (allowedNodeTypes.includes(node.type.name)) {
show = true
} else {
return false
}
}
}

return show
}

export const shouldShow: BubbleMenuPluginProps['shouldShow'] = ({ editor, from, to }) => {
const baseExtension = editor.extensionManager.extensions.find(
extension => extension.name === Base.name
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ const collaborationStyles: CSS = {

export const textSelectionClassName = 'text-selection-highlight'
export const nodeSelectionClassName = 'node-selection-highlight'
export const nodeSelectionMouseAreaClassName = 'node-selection-mouse-area-highlight'
export const nodeSelectionMouseSelectionClassName = 'node-selection-mouse-selection-highlight'

export const selectionStyles: CSS = {
[`.${nodeSelectionClassName}`]: {
Expand All @@ -189,7 +189,7 @@ export const selectionStyles: CSS = {
}

export const globalStyles = globalCss({
[`.${nodeSelectionMouseAreaClassName}`]: {
[`.${nodeSelectionMouseSelectionClassName}`]: {
...defaultSelectionStyles['::selection']
}
})
Expand Down
6 changes: 3 additions & 3 deletions packages/editor/src/editors/documentEditor/documentEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ import {
h5FontSize,
h5LienHeight,
nodeSelectionClassName,
nodeSelectionMouseAreaClassName,
nodeSelectionMouseSelectionClassName,
paragraphFontSize,
paragraphLineHeight,
textSelectionClassName
Expand Down Expand Up @@ -240,8 +240,8 @@ export function useEditor(options: EditorOptions, deps?: DependencyList): Tiptap
},
selection: {
nodeSelection: {
mouseArea: {
className: nodeSelectionMouseAreaClassName
mouseSelection: {
className: nodeSelectionMouseSelectionClassName
},
className: nodeSelectionClassName
},
Expand Down
52 changes: 52 additions & 0 deletions packages/editor/src/extensions/extensions/selection/decorations.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { Editor } from '@tiptap/core'
import { EditorState, TextSelection, NodeSelection } from 'prosemirror-state'
import { Decoration, DecorationSet } from 'prosemirror-view'
import { SelectionOptions } from './meta'
import { MultipleNodeSelection } from './MultipleNodeSelection'

const DEFAULT_TEXT_SELECTION_CLASS = 'text-selection-highlight'
const DEFAULT_NODE_SELECTION_CLASS = 'node-selection-highlight'

export function textSelectionDecoration(
editor: Editor,
options: SelectionOptions,
state: EditorState
): DecorationSet | null {
if (!editor.isEditable) return null

if (!(state.selection instanceof TextSelection)) return null

const { from, to } = state.selection
if (from === to) return null

const decorations: Decoration[] = []

const inlineDecoration = Decoration.inline(from, to, {
class: options.textSelection?.className ?? DEFAULT_TEXT_SELECTION_CLASS,
style: options.textSelection?.style
})
decorations.push(inlineDecoration)

return DecorationSet.create(editor.state.doc, decorations)
}

export function nodeSelectionDecoration(
editor: Editor,
options: SelectionOptions,
state: EditorState
): DecorationSet | null {
if (!editor.isEditable) return null
if (!(state.selection instanceof MultipleNodeSelection) && !(state.selection instanceof NodeSelection)) return null

const decorations: Decoration[] = []

state.selection.ranges.forEach(range => {
const nodeDecoration = Decoration.node(range.$from.pos, range.$to.pos, {
class: options.nodeSelection?.className ?? DEFAULT_NODE_SELECTION_CLASS,
style: options.nodeSelection?.style
})
decorations.push(nodeDecoration)
})

return DecorationSet.create(state.doc, decorations)
}

0 comments on commit c60076d

Please sign in to comment.