2 MenuItem, Dropdown, DropdownSubmenu, renderGrouped, joinUpItem, liftItem, selectParentNodeItem,
3 undoItem, redoItem, wrapItem, blockTypeItem, setAttrItem, insertBlockBeforeItem,
5 import {icons} from "./icons";
6 import ColorPickerGrid from "./ColorPickerGrid";
7 import DialogBox from "./DialogBox";
8 import {toggleMark} from "prosemirror-commands";
9 import {menuBar} from "./menubar"
10 import schema from "../schema";
11 import {removeMarks} from "../commands";
12 import DialogForm from "./DialogForm";
13 import DialogInput from "./DialogInput";
16 function cmdItem(cmd, options) {
17 const passedOptions = {
21 for (const prop in options) {
22 passedOptions[prop] = options[prop];
24 if ((!options.enable || options.enable === true) && !options.select) {
25 passedOptions[options.enable ? "enable" : "select"] = function (state) {
30 return new MenuItem(passedOptions)
33 function markActive(state, type) {
34 const ref = state.selection;
35 const from = ref.from;
36 const $from = ref.$from;
38 const empty = ref.empty;
40 return type.isInSet(state.storedMarks || $from.marks())
42 return state.doc.rangeHasMark(from, to, type)
46 function markItem(markType, options) {
47 const passedOptions = {
48 active: function active(state) {
49 return markActive(state, markType)
53 for (const prop in options) {
54 passedOptions[prop] = options[prop];
57 return cmdItem(toggleMark(markType, passedOptions.attrs), passedOptions)
60 const inlineStyles = [
61 markItem(schema.marks.strong, {title: "Bold", icon: icons.strong}),
62 markItem(schema.marks.em, {title: "Italic", icon: icons.em}),
63 markItem(schema.marks.underline, {title: "Underline", icon: icons.underline}),
64 markItem(schema.marks.strike, {title: "Strikethrough", icon: icons.strike}),
65 markItem(schema.marks.superscript, {title: "Superscript", icon: icons.superscript}),
66 markItem(schema.marks.subscript, {title: "Subscript", icon: icons.subscript}),
70 blockTypeItem(schema.nodes.heading, {
71 label: "Header Large",
74 blockTypeItem(schema.nodes.heading, {
75 label: "Header Medium",
78 blockTypeItem(schema.nodes.heading, {
79 label: "Header Small",
82 blockTypeItem(schema.nodes.heading, {
86 blockTypeItem(schema.nodes.paragraph, {
90 markItem(schema.marks.code, {
95 blockTypeItem(schema.nodes.callout, {
96 label: "Info Callout",
99 blockTypeItem(schema.nodes.callout, {
100 label: "Danger Callout",
101 attrs: {type: 'danger'}
103 blockTypeItem(schema.nodes.callout, {
104 label: "Success Callout",
105 attrs: {type: 'success'}
107 blockTypeItem(schema.nodes.callout, {
108 label: "Warning Callout",
109 attrs: {type: 'warning'}
111 ], { label: 'Callouts' }),
115 setAttrItem('align', 'left', {
116 icon: icons.align_left
118 setAttrItem('align', 'center', {
119 icon: icons.align_center
121 setAttrItem('align', 'right', {
122 icon: icons.align_right
124 setAttrItem('align', 'justify', {
125 icon: icons.align_justify
129 const colorOptions = ["#000000","#993300","#333300","#003300","#003366","#000080","#333399","#333333","#800000","#FF6600","#808000","#008000","#008080","#0000FF","#666699","#808080","#FF0000","#FF9900","#99CC00","#339966","#33CCCC","#3366FF","#800080","#999999","#FF00FF","#FFCC00","#FFFF00","#00FF00","#00FFFF","#00CCFF","#993366","#FFFFFF","#FF99CC","#FFCC99","#FFFF99","#CCFFCC","#CCFFFF","#99CCFF","#CC99FF"];
132 new DropdownSubmenu([
133 new ColorPickerGrid(schema.marks.text_color, 'color', colorOptions),
134 ], {icon: icons.text_color}),
135 new DropdownSubmenu([
136 new ColorPickerGrid(schema.marks.background_color, 'color', colorOptions),
137 ], {icon: icons.background_color}),
141 wrapItem(schema.nodes.bullet_list, {
142 title: "Bullet List",
143 icon: icons.bullet_list,
145 wrapItem(schema.nodes.ordered_list, {
146 title: "Ordered List",
147 icon: icons.ordered_list,
152 insertBlockBeforeItem(schema.nodes.horizontal_rule, {
153 title: "Horizontal Rule",
154 icon: icons.horizontal_rule,
160 title: 'Clear Formatting',
161 icon: icons.format_clear,
163 enable: state => true,
167 function getMarkAttribute(markType, attribute) {
168 return function(state) {
169 const marks = state.selection.$head.marks();
170 for (const mark of marks) {
171 if (mark.type === markType) {
172 return mark.attrs[attribute];
180 let box = new DialogBox([
185 value: getMarkAttribute(schema.marks.link, 'href'),
190 value: getMarkAttribute(schema.marks.link, 'title'),
193 canceler: () => box.close(),
194 action: (data) => console.log('submit', data),
196 ], {label: 'Insert Link', closer: () => {console.log('close')}});
198 const menu = menuBar({
201 [undoItem, redoItem],
202 [new DropdownSubmenu(formats, { label: 'Formats' })],
215 // !! This module defines a number of building blocks for ProseMirror
216 // menus, along with a [menu bar](#menu.menuBar) implementation.
218 // MenuElement:: interface
219 // The types defined in this module aren't the only thing you can
220 // display in your menu. Anything that conforms to this interface can
221 // be put into a menu structure.
223 // render:: (pm: EditorView) → {dom: dom.Node, update: (EditorState) → bool}
224 // Render the element for display in the menu. Must return a DOM
225 // element and a function that can be used to update the element to
226 // a new state. The `update` function will return false if the
227 // update hid the entire element.