Shared link mark update logic with color controls
This commit is contained in:
parent
bb12541179
commit
b1f5495a7f
3 changed files with 48 additions and 17 deletions
|
@ -1,6 +1,8 @@
|
||||||
import crel from "crelt"
|
import crel from "crelt"
|
||||||
import {prefix} from "./menu-utils";
|
import {prefix} from "./menu-utils";
|
||||||
import {toggleMark} from "prosemirror-commands";
|
import {TextSelection} from "prosemirror-state"
|
||||||
|
import {expandSelectionToMark} from "../util";
|
||||||
|
|
||||||
|
|
||||||
class ColorPickerGrid {
|
class ColorPickerGrid {
|
||||||
|
|
||||||
|
@ -24,8 +26,7 @@ class ColorPickerGrid {
|
||||||
wrap.addEventListener('click', event => {
|
wrap.addEventListener('click', event => {
|
||||||
if (event.target.classList.contains(prefix + "-color-grid-item")) {
|
if (event.target.classList.contains(prefix + "-color-grid-item")) {
|
||||||
const color = event.target.style.backgroundColor;
|
const color = event.target.style.backgroundColor;
|
||||||
const attrs = {[this.attrName]: color};
|
this.onColorSelect(view, color);
|
||||||
toggleMark(this.markType, attrs)(view.state, view.dispatch, view, event);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -35,6 +36,27 @@ class ColorPickerGrid {
|
||||||
|
|
||||||
return {dom: wrap, update}
|
return {dom: wrap, update}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onColorSelect(view, color) {
|
||||||
|
const attrs = {[this.attrName]: color};
|
||||||
|
const selection = view.state.selection;
|
||||||
|
const {from, to} = expandSelectionToMark(view.state, selection, this.markType);
|
||||||
|
const tr = view.state.tr;
|
||||||
|
|
||||||
|
const currentColorMarks = selection.$from.marksAcross(selection.$to) || [];
|
||||||
|
const activeRelevantMark = currentColorMarks.filter(mark => {
|
||||||
|
return mark.type === this.markType;
|
||||||
|
})[0];
|
||||||
|
const colorIsActive = activeRelevantMark && activeRelevantMark.attrs[this.attrName] === color;
|
||||||
|
|
||||||
|
tr.removeMark(from, to, this.markType);
|
||||||
|
if (!colorIsActive) {
|
||||||
|
tr.addMark(from, to, this.markType.create(attrs));
|
||||||
|
}
|
||||||
|
|
||||||
|
tr.setSelection(TextSelection.create(tr.doc, from, to));
|
||||||
|
view.dispatch(tr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ColorPickerGrid;
|
export default ColorPickerGrid;
|
|
@ -6,7 +6,7 @@ import schema from "../schema";
|
||||||
|
|
||||||
import {MenuItem} from "./menu";
|
import {MenuItem} from "./menu";
|
||||||
import {icons} from "./icons";
|
import {icons} from "./icons";
|
||||||
import {markRangeAtPosition, nullifyEmptyValues} from "../util";
|
import {expandSelectionToMark, nullifyEmptyValues} from "../util";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {PmMarkType} markType
|
* @param {PmMarkType} markType
|
||||||
|
@ -74,17 +74,7 @@ function applyLink(formData, state, dispatch) {
|
||||||
if (!dispatch) return true;
|
if (!dispatch) return true;
|
||||||
|
|
||||||
const tr = state.tr;
|
const tr = state.tr;
|
||||||
const noRange = (selection.from - selection.to === 0);
|
const {from, to} = expandSelectionToMark(state, selection, schema.marks.link);
|
||||||
let from = selection.from;
|
|
||||||
let to = selection.to;
|
|
||||||
|
|
||||||
if (noRange) {
|
|
||||||
const linkRange = markRangeAtPosition(state, schema.marks.link, selection.from);
|
|
||||||
if (linkRange.from !== -1) {
|
|
||||||
from = linkRange.from;
|
|
||||||
to = linkRange.to;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (attrs.href) {
|
if (attrs.href) {
|
||||||
tr.addMark(from, to, schema.marks.link.create(attrs));
|
tr.addMark(from, to, schema.marks.link.create(attrs));
|
||||||
|
|
|
@ -45,6 +45,25 @@ export function nullifyEmptyValues(object) {
|
||||||
return clean;
|
return clean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {PmEditorState} state
|
||||||
|
* @param {PmSelection} selection
|
||||||
|
* @param {PmMarkType} markType
|
||||||
|
* @return {{from: Number, to: Number}}
|
||||||
|
*/
|
||||||
|
export function expandSelectionToMark(state, selection, markType) {
|
||||||
|
let {from, to} = selection;
|
||||||
|
const noRange = (from === to);
|
||||||
|
if (noRange) {
|
||||||
|
const markRange = markRangeAtPosition(state, markType, from);
|
||||||
|
if (markRange.from !== -1) {
|
||||||
|
from = markRange.from;
|
||||||
|
to = markRange.to;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {from, to};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {PmEditorState} state
|
* @param {PmEditorState} state
|
||||||
* @param {PmMarkType} markType
|
* @param {PmMarkType} markType
|
||||||
|
|
Loading…
Reference in a new issue