aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSam Wilkins <abdullah_ahmed@brown.edu>2019-04-13 19:06:18 -0400
committerSam Wilkins <abdullah_ahmed@brown.edu>2019-04-13 19:06:18 -0400
commit8c58ff299e371c70147aa8123ed9fb0ae1a9e880 (patch)
tree1592b23dc2da31e7c200cd1c4c8f01181c8bbf60 /src
parent79a0d8d66204868158849afda6518f6c641c826b (diff)
parent74411165f21b6c616fa98e0676c6f4568c2d4564 (diff)
added typesheet for full prosemirror keymap
Diffstat (limited to 'src')
-rw-r--r--src/client/util/ProsemirrorKeymap.ts100
-rw-r--r--src/client/util/TooltipTextMenu.tsx46
-rw-r--r--src/client/views/nodes/FormattedTextBox.tsx13
3 files changed, 141 insertions, 18 deletions
diff --git a/src/client/util/ProsemirrorKeymap.ts b/src/client/util/ProsemirrorKeymap.ts
new file mode 100644
index 000000000..7718b3c06
--- /dev/null
+++ b/src/client/util/ProsemirrorKeymap.ts
@@ -0,0 +1,100 @@
+import { Schema } from "prosemirror-model";
+import {
+ wrapIn, setBlockType, chainCommands, toggleMark, exitCode,
+ joinUp, joinDown, lift, selectParentNode
+} from "prosemirror-commands";
+import { wrapInList, splitListItem, liftListItem, sinkListItem } from "prosemirror-schema-list";
+import { undo, redo } from "prosemirror-history";
+import { undoInputRule } from "prosemirror-inputrules";
+import { Transaction, EditorState } from "prosemirror-state";
+
+const mac = typeof navigator !== "undefined" ? /Mac/.test(navigator.platform) : false;
+
+export type KeyMap = { [key: string]: any };
+
+export default function buildKeymap<S extends Schema<any>>(schema: S, mapKeys?: KeyMap): KeyMap {
+ let keys: { [key: string]: any } = {}, type;
+
+ function bind(key: string, cmd: any) {
+ if (mapKeys) {
+ let mapped = mapKeys[key];
+ if (mapped === false) return;
+ if (mapped) key = mapped;
+ }
+ keys[key] = cmd;
+ }
+
+ bind("Mod-z", undo);
+ bind("Shift-Mod-z", redo);
+ bind("Backspace", undoInputRule);
+
+ if (!mac) {
+ bind("Mod-y", redo);
+ }
+
+ bind("Alt-ArrowUp", joinUp);
+ bind("Alt-ArrowDown", joinDown);
+ bind("Mod-BracketLeft", lift);
+ bind("Escape", selectParentNode);
+
+ if (type = schema.marks.strong) {
+ bind("Mod-b", toggleMark(type));
+ bind("Mod-B", toggleMark(type));
+ }
+ if (type = schema.marks.em) {
+ bind("Mod-i", toggleMark(type));
+ bind("Mod-I", toggleMark(type));
+ }
+ if (type = schema.marks.code) {
+ bind("Mod-`", toggleMark(type));
+ }
+
+ if (type = schema.nodes.bullet_list) {
+ bind("Shift-Ctrl-8", wrapInList(type));
+ }
+ if (type = schema.nodes.ordered_list) {
+ bind("Shift-Ctrl-9", wrapInList(type));
+ }
+ if (type = schema.nodes.blockquote) {
+ bind("Ctrl->", wrapIn(type));
+ }
+ if (type = schema.nodes.hard_break) {
+ let br = type, cmd = chainCommands(exitCode, (state, dispatch) => {
+ if (dispatch) {
+ dispatch(state.tr.replaceSelectionWith(br.create()).scrollIntoView());
+ return true;
+ }
+ return false;
+ });
+ bind("Mod-Enter", cmd);
+ bind("Shift-Enter", cmd);
+ if (mac) {
+ bind("Ctrl-Enter", cmd);
+ }
+ }
+ if (type = schema.nodes.list_item) {
+ bind("Enter", splitListItem(type));
+ bind("Mod-[", liftListItem(type));
+ bind("Mod-]", sinkListItem(type));
+ }
+ if (type = schema.nodes.paragraph) {
+ bind("Shift-Ctrl-0", setBlockType(type));
+ }
+ if (type = schema.nodes.code_block) {
+ bind("Shift-Ctrl-\\", setBlockType(type));
+ }
+ if (type = schema.nodes.heading) {
+ for (let i = 1; i <= 6; i++) {
+ bind("Shift-Ctrl-" + i, setBlockType(type, { level: i }));
+ }
+ }
+ if (type = schema.nodes.horizontal_rule) {
+ let hr = type;
+ bind("Mod-_", (state: EditorState<S>, dispatch: (tx: Transaction<S>) => void) => {
+ dispatch(state.tr.replaceSelectionWith(hr.create()).scrollIntoView());
+ return true;
+ });
+ }
+
+ return keys;
+} \ No newline at end of file
diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx
index 19affdf97..48f835a0f 100644
--- a/src/client/util/TooltipTextMenu.tsx
+++ b/src/client/util/TooltipTextMenu.tsx
@@ -21,6 +21,7 @@ const SVG = "http://www.w3.org/2000/svg";
export class TooltipTextMenu {
private tooltip: HTMLElement;
+ private num_icons = 0;
constructor(view: EditorView) {
this.tooltip = document.createElement("div");
@@ -40,20 +41,29 @@ export class TooltipTextMenu {
{ command: toggleMark(schema.marks.strikethrough), dom: this.icon("S", "strikethrough") },
{ command: toggleMark(schema.marks.superscript), dom: this.icon("s", "superscript") },
{ command: toggleMark(schema.marks.subscript), dom: this.icon("s", "subscript") },
- //this doesn't work currently - look into notion of active block
{ command: wrapInList(schema.nodes.bullet_list), dom: this.icon(":", "bullets") },
+ { command: toggleMark(schema.marks.timesNewRoman), dom: this.icon("x", "TNR") },
+ { command: lift, dom: this.icon("<", "lift") },
];
- items.forEach(({ dom }) => this.tooltip.appendChild(dom));
+ //add menu items
+ items.forEach(({ dom, command }) => {
+ this.tooltip.appendChild(dom);
+ });
+
+ //add dropdowns
//pointer down handler to activate button effects
this.tooltip.addEventListener("pointerdown", e => {
e.preventDefault();
view.focus();
+ //update view of icons
+ this.num_icons = 0;
items.forEach(({ command, dom }) => {
- if (dom.contains(e.target as Node)) {
+ if (e.srcElement && dom.contains(e.srcElement as Node)) {
+ //let active = command(view.state, view.dispatch, view);
let active = command(view.state, view.dispatch, view);
//uncomment this if we want the bullet button to disappear if current selection is bulleted
- // dom.style.display = active ? "" : "none"
+ //dom.style.display = active ? "" : "none";
}
});
});
@@ -91,9 +101,24 @@ export class TooltipTextMenu {
//this doesn't currently work but could be used to use icons for buttons
unorderedListIcon(): HTMLSpanElement {
let span = document.createElement("span");
- let icon = document.createElement("FontAwesomeIcon");
- icon.className = "menuicon fa fa-smile-o";
- span.appendChild(icon);
+ //let icon = document.createElement("FontAwesomeIcon");
+ //icon.className = "menuicon";
+ //icon.style.color = "white";
+ //span.appendChild(<i style={{ color: "white" }} icon="list-ul" size="lg" />);
+ let i = document.createElement("i");
+ i.className = "fa falist-ul";
+ span.appendChild(i);
+ //span.appendChild(icon);
+ //return liftItem.spec.icon.sty
+
+ //let sym = document.createElementNS(SVG, "symbol")
+ // sym.id = name
+ //sym.style.color = "white";
+ //width then height
+ //sym.setAttribute("viewBox", "0 0 " + 1024 + " " + 1024);
+ //let path = sym.appendChild(document.createElementNS(SVG, "path"));
+ //path.setAttribute("d", "M219 310v329q0 7-5 12t-12 5q-8 0-13-5l-164-164q-5-5-5-13t5-13l164-164q5-5 13-5 7 0 12 5t5 12zM1024 749v109q0 7-5 12t-12 5h-987q-7 0-12-5t-5-12v-109q0-7 5-12t12-5h987q7 0 12 5t5 12zM1024 530v109q0 7-5 12t-12 5h-621q-7 0-12-5t-5-12v-109q0-7 5-12t12-5h621q7 0 12 5t5 12zM1024 310v109q0 7-5 12t-12 5h-621q-7 0-12-5t-5-12v-109q0-7 5-12t12-5h621q7 0 12 5t5 12zM1024 91v109q0 7-5 12t-12 5h-987q-7 0-12-5t-5-12v-109q0-7 5-12t12-5h987q7 0 12 5t5 12z");
+ //span.appendChild(sym);
return span;
}
@@ -128,13 +153,14 @@ export class TooltipTextMenu {
// crossing lines, end may be more to the left)
let left = Math.max((start.left + end.left) / 2, start.left + 3);
this.tooltip.style.left = (left - box.left) + "px";
- let width = Math.abs(start.left - end.left) / 2;
+ //let width = Math.abs(start.left - end.left) / 2;
+ let width = 8 * 16 + 15;
let mid = Math.min(start.left, end.left) + width;
//THIS WIDTH IS 15 * NUMBER OF ICONS + 15
- this.tooltip.style.width = 122 + "px";
+ this.tooltip.style.width = width + "px";
this.tooltip.style.bottom = (box.bottom - start.top) + "px";
}
destroy() { this.tooltip.remove(); }
-} \ No newline at end of file
+}
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index ec766e069..e872ea48b 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -16,6 +16,8 @@ import { Main } from "../Main";
import { FieldView, FieldViewProps } from "./FieldView";
import "./FormattedTextBox.scss";
import React = require("react");
+import { undoItem } from "prosemirror-menu";
+import buildKeymap from "../../util/ProsemirrorKeymap";
const { buildMenuItems } = require("prosemirror-example-setup");
const { menuBar } = require("prosemirror-menu");
@@ -64,12 +66,6 @@ export class FormattedTextBox extends React.Component<FieldViewProps> {
}
}
- undo = <S extends Schema = any>(state: EditorState<S>, dispatch?: (tr: Transaction<S>) => void): boolean => {
- console.log(state);
- console.log(dispatch);
- return true;
- }
-
get FieldDoc() { return this.props.fieldKey === KeyStore.Archives ? Main.Instance._textDoc! : this.props.Document; }
get FieldKey() { return this.props.fieldKey === KeyStore.Archives ? KeyStore.Data : this.props.fieldKey; }
@@ -79,7 +75,7 @@ export class FormattedTextBox extends React.Component<FieldViewProps> {
inpRules, //these currently don't do anything, but could eventually be helpful
plugins: [
history(),
- keymap({ "Mod-z": this.undo, "Mod-y": redo }),
+ keymap(buildKeymap(schema)),
keymap(baseKeymap),
this.tooltipMenuPlugin()
]
@@ -213,7 +209,8 @@ export class FormattedTextBox extends React.Component<FieldViewProps> {
});
}
onKeyPress(e: React.KeyboardEvent) {
- e.stopPropagation();
+ console.log(e.keyCode)
+ // e.stopPropagation();
// stop propagation doesn't seem to stop propagation of native keyboard events.
// so we set a flag on the native event that marks that the event's been handled.
// (e.nativeEvent as any).DASHFormattedTextBoxHandled = true;