UNPKG

@portabletext/editor

Version:

Portable Text Editor made in React

85 lines (74 loc) 2.28 kB
import type {EditorSchema} from '../editor/editor-schema' import {looksLikeUrl} from '../internal-utils/looks-like-url' import * as selectors from '../selectors' import {execute} from './behavior.types.action' import {defineBehavior} from './behavior.types.behavior' /** * @beta */ export type LinkBehaviorsConfig = { linkAnnotation?: (context: { schema: EditorSchema url: string }) => {name: string; value: {[prop: string]: unknown}} | undefined } /** * @beta */ export function createLinkBehaviors(config: LinkBehaviorsConfig) { const pasteLinkOnSelection = defineBehavior({ on: 'clipboard.paste', guard: ({snapshot, event}) => { const selectionCollapsed = selectors.isSelectionCollapsed(snapshot) const text = event.originEvent.dataTransfer.getData('text/plain') const url = looksLikeUrl(text) ? text : undefined const annotation = url !== undefined ? config.linkAnnotation?.({url, schema: snapshot.context.schema}) : undefined if (annotation && !selectionCollapsed) { return {annotation} } return false }, actions: [ (_, {annotation}) => [ execute({ type: 'annotation.add', annotation, }), ], ], }) const pasteLinkAtCaret = defineBehavior({ on: 'clipboard.paste', guard: ({snapshot, event}) => { const focusSpan = selectors.getFocusSpan(snapshot) const selectionCollapsed = selectors.isSelectionCollapsed(snapshot) if (!focusSpan || !selectionCollapsed) { return false } const text = event.originEvent.dataTransfer.getData('text/plain') const url = looksLikeUrl(text) ? text : undefined const annotation = url !== undefined ? config.linkAnnotation?.({url, schema: snapshot.context.schema}) : undefined if (url && annotation && selectionCollapsed) { return {focusSpan, annotation, url} } return false }, actions: [ (_, {annotation, url}) => [ execute({ type: 'insert.span', text: url, annotations: [annotation], }), ], ], }) const linkBehaviors = [pasteLinkOnSelection, pasteLinkAtCaret] return linkBehaviors }