@hypericon/mico 0.3.6 → 0.3.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/dialog/dialog-manager.js +2 -5
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.js +1 -0
- package/dist/components/markdown-editor/MarkdownEditor.d.ts +19 -0
- package/dist/components/markdown-editor/MarkdownEditor.js +202 -0
- package/dist/components/markdown-editor/index.d.ts +1 -0
- package/dist/components/markdown-editor/index.js +17 -0
- package/dist/components/markdown-editor/markdown-editor.state.d.ts +31 -0
- package/dist/components/markdown-editor/markdown-editor.state.js +259 -0
- package/dist/components/menu/Menu.d.ts +7 -0
- package/dist/components/menu/Menu.js +12 -4
- package/dist/components/menu/menu-manager.d.ts +2 -1
- package/dist/components/menu/menu-manager.js +2 -1
- package/dist/utils/events.d.ts +7 -0
- package/dist/utils/events.js +16 -1
- package/package.json +1 -1
|
@@ -14,6 +14,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.dialogMgr = exports.DialogManager = void 0;
|
|
16
16
|
const mithril_1 = __importDefault(require("mithril"));
|
|
17
|
+
const utils_1 = require("../../utils");
|
|
17
18
|
class DialogManager {
|
|
18
19
|
get isOpen() { return this.currentDialog !== undefined; }
|
|
19
20
|
constructor(options) {
|
|
@@ -65,11 +66,7 @@ class DialogManager {
|
|
|
65
66
|
// console.log(ev);
|
|
66
67
|
if (ev.target !== dom)
|
|
67
68
|
return;
|
|
68
|
-
const
|
|
69
|
-
const isInDialog = (ev.clientY >= dialogRect.top) &&
|
|
70
|
-
(ev.clientY <= dialogRect.bottom) &&
|
|
71
|
-
(ev.clientX >= dialogRect.left) &&
|
|
72
|
-
(ev.clientX <= dialogRect.right);
|
|
69
|
+
const isInDialog = (0, utils_1.mouseWithinElement)(ev, dom);
|
|
73
70
|
if (!isInDialog)
|
|
74
71
|
manager.close();
|
|
75
72
|
});
|
package/dist/components/index.js
CHANGED
|
@@ -23,6 +23,7 @@ __exportStar(require("./drop-target"), exports);
|
|
|
23
23
|
// export * from "./form";
|
|
24
24
|
__exportStar(require("./icon"), exports);
|
|
25
25
|
__exportStar(require("./markdown"), exports);
|
|
26
|
+
__exportStar(require("./markdown-editor"), exports);
|
|
26
27
|
__exportStar(require("./menu"), exports);
|
|
27
28
|
// export * from "./modal";
|
|
28
29
|
// export * from "./pagination";
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import m from "mithril";
|
|
2
|
+
import { MarkdownEditorState } from "./markdown-editor.state";
|
|
3
|
+
export declare const MarkdownEditor: m.Component<{
|
|
4
|
+
/** The current markdown content as a string */
|
|
5
|
+
markdown: string;
|
|
6
|
+
/** Function called whenever the markdown string is edited */
|
|
7
|
+
onEdit: (markdown: string) => any;
|
|
8
|
+
/**
|
|
9
|
+
* Attempt to highlight syntax of code blocks
|
|
10
|
+
* @default false
|
|
11
|
+
*/
|
|
12
|
+
highlight?: boolean;
|
|
13
|
+
/** @default true */
|
|
14
|
+
enableShortcuts?: boolean;
|
|
15
|
+
class?: string;
|
|
16
|
+
style?: string;
|
|
17
|
+
}, {
|
|
18
|
+
state: MarkdownEditorState;
|
|
19
|
+
}>;
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.MarkdownEditor = void 0;
|
|
27
|
+
const mithril_1 = __importStar(require("mithril"));
|
|
28
|
+
const Icon_1 = require("../icon/Icon");
|
|
29
|
+
const Markdown_1 = require("../markdown/Markdown");
|
|
30
|
+
const menu_1 = require("../menu");
|
|
31
|
+
const markdown_editor_state_1 = require("./markdown-editor.state");
|
|
32
|
+
exports.MarkdownEditor = {
|
|
33
|
+
oninit({ attrs }) {
|
|
34
|
+
this.state = new markdown_editor_state_1.MarkdownEditorState(attrs.onEdit);
|
|
35
|
+
},
|
|
36
|
+
onremove() {
|
|
37
|
+
this.state.destroy();
|
|
38
|
+
},
|
|
39
|
+
onupdate({ attrs, dom }) {
|
|
40
|
+
if (this.state.isEditing && !this.state.editorContainerEl) {
|
|
41
|
+
this.state.editorContainerEl = [...dom.getElementsByClassName("editor-container")].at(0);
|
|
42
|
+
}
|
|
43
|
+
if (this.state.isEditing && !this.state.editorEl) {
|
|
44
|
+
this.state.editorEl = [...dom.getElementsByTagName("textarea")].at(0);
|
|
45
|
+
}
|
|
46
|
+
if (this.state.isEditing && !this.state.isEditingPrevious) {
|
|
47
|
+
const editorEl = [...dom.getElementsByTagName("textarea")].at(0);
|
|
48
|
+
editorEl === null || editorEl === void 0 ? void 0 : editorEl.focus();
|
|
49
|
+
editorEl === null || editorEl === void 0 ? void 0 : editorEl.setSelectionRange(0, 0);
|
|
50
|
+
if (editorEl)
|
|
51
|
+
this.state.editorEl = editorEl;
|
|
52
|
+
this.state.editorValue = attrs.markdown;
|
|
53
|
+
this.state.editValue = attrs.onEdit;
|
|
54
|
+
this.state.setSelection(0, 0);
|
|
55
|
+
setTimeout(() => {
|
|
56
|
+
(0, mithril_1.redraw)();
|
|
57
|
+
}, 1);
|
|
58
|
+
}
|
|
59
|
+
if (this.state.requestSelection && this.state.editorEl) {
|
|
60
|
+
this.state.editorEl.setSelectionRange(this.state.requestSelection.start, this.state.requestSelection.end);
|
|
61
|
+
this.state.requestSelection = undefined;
|
|
62
|
+
(0, mithril_1.redraw)();
|
|
63
|
+
}
|
|
64
|
+
this.state.isEditingPrevious = this.state.isEditing;
|
|
65
|
+
},
|
|
66
|
+
view({ attrs }) {
|
|
67
|
+
return (0, mithril_1.default)(".mico-markdown-editor", {
|
|
68
|
+
class: attrs.class,
|
|
69
|
+
style: attrs.style,
|
|
70
|
+
}, [
|
|
71
|
+
(!this.state.isEditing) ? [
|
|
72
|
+
(0, mithril_1.default)(".render-container", {
|
|
73
|
+
tabindex: 0,
|
|
74
|
+
onclick: () => {
|
|
75
|
+
this.state.isEditing = true;
|
|
76
|
+
},
|
|
77
|
+
}, [
|
|
78
|
+
(0, mithril_1.default)(Markdown_1.Markdown, {
|
|
79
|
+
highlight: attrs.highlight,
|
|
80
|
+
markdown: attrs.markdown,
|
|
81
|
+
}),
|
|
82
|
+
]),
|
|
83
|
+
] : [
|
|
84
|
+
(0, mithril_1.default)(".editor-container", [
|
|
85
|
+
// Editor buttons
|
|
86
|
+
(0, mithril_1.default)(".editor-buttons", [
|
|
87
|
+
(0, mithril_1.default)(".editor-button-group", [
|
|
88
|
+
(0, mithril_1.default)("button", {
|
|
89
|
+
title: "Ctrl+Shift+H",
|
|
90
|
+
onclick: () => this.state.applyHeading(),
|
|
91
|
+
}, (0, mithril_1.default)(Icon_1.Icon, { fas: "heading" })),
|
|
92
|
+
(0, mithril_1.default)("button", {
|
|
93
|
+
onclick: (ev) => menu_1.menuMgr.show(ev, [
|
|
94
|
+
(0, mithril_1.default)(menu_1.MenuButton, { label: "Heading 1", onclick: () => this.state.applyHeading(1) }),
|
|
95
|
+
(0, mithril_1.default)(menu_1.MenuButton, { label: "Heading 2", onclick: () => this.state.applyHeading(2) }),
|
|
96
|
+
(0, mithril_1.default)(menu_1.MenuButton, { label: "Heading 3", onclick: () => this.state.applyHeading(3) }),
|
|
97
|
+
(0, mithril_1.default)(menu_1.MenuButton, { label: "Heading 4", onclick: () => this.state.applyHeading(4) }),
|
|
98
|
+
], {
|
|
99
|
+
noFlipH: true,
|
|
100
|
+
noFlipV: true,
|
|
101
|
+
}),
|
|
102
|
+
}, (0, mithril_1.default)(Icon_1.Icon, { fas: "caret-down" })),
|
|
103
|
+
]),
|
|
104
|
+
(0, mithril_1.default)(".editor-button-group", [
|
|
105
|
+
(0, mithril_1.default)("button", {
|
|
106
|
+
title: "Ctrl+Shift+B",
|
|
107
|
+
onclick: () => this.state.applyBold(),
|
|
108
|
+
}, (0, mithril_1.default)(Icon_1.Icon, { fas: "bold" })),
|
|
109
|
+
(0, mithril_1.default)("button", {
|
|
110
|
+
title: "Ctrl+Shift+I",
|
|
111
|
+
onclick: () => this.state.applyItalic(),
|
|
112
|
+
}, (0, mithril_1.default)(Icon_1.Icon, { fas: "italic" })),
|
|
113
|
+
(0, mithril_1.default)("button", {
|
|
114
|
+
title: "Ctrl+Shift+C",
|
|
115
|
+
onclick: () => this.state.applyCode(),
|
|
116
|
+
}, (0, mithril_1.default)(Icon_1.Icon, { fas: "code" })),
|
|
117
|
+
(0, mithril_1.default)("button", {
|
|
118
|
+
title: "Ctrl+Shift+S",
|
|
119
|
+
onclick: () => this.state.applyStrikethrough(),
|
|
120
|
+
}, (0, mithril_1.default)(Icon_1.Icon, { fas: "strikethrough" })),
|
|
121
|
+
]),
|
|
122
|
+
(0, mithril_1.default)(".editor-button-group", [
|
|
123
|
+
(0, mithril_1.default)("button", {
|
|
124
|
+
title: "Ctrl+Shift+U",
|
|
125
|
+
onclick: () => this.state.applyUnorderedList(),
|
|
126
|
+
}, (0, mithril_1.default)(Icon_1.Icon, { fas: "list-ul" })),
|
|
127
|
+
(0, mithril_1.default)("button", {
|
|
128
|
+
title: "Ctrl+Shift+O",
|
|
129
|
+
onclick: () => this.state.applyOrderedList(),
|
|
130
|
+
}, (0, mithril_1.default)(Icon_1.Icon, { fas: "list-ol" })),
|
|
131
|
+
(0, mithril_1.default)("button", {
|
|
132
|
+
title: "Ctrl+Shift+L",
|
|
133
|
+
onclick: () => this.state.applyLink(),
|
|
134
|
+
}, (0, mithril_1.default)(Icon_1.Icon, { fas: "link" })),
|
|
135
|
+
]),
|
|
136
|
+
]),
|
|
137
|
+
// Editor content
|
|
138
|
+
(0, mithril_1.default)("textarea.editor-textarea", {
|
|
139
|
+
rows: this.state.editorValue.split("\n").length + 1,
|
|
140
|
+
value: this.state.editorValue,
|
|
141
|
+
oninput: (e) => {
|
|
142
|
+
this.state.editorValue = e.target.value;
|
|
143
|
+
this.state.editValue(e.target.value);
|
|
144
|
+
},
|
|
145
|
+
onmousemove: (ev) => {
|
|
146
|
+
const textareaEl = ev.currentTarget;
|
|
147
|
+
this.state.setSelection(textareaEl.selectionStart, textareaEl.selectionEnd);
|
|
148
|
+
},
|
|
149
|
+
onkeyup: (ev) => {
|
|
150
|
+
const textareaEl = ev.currentTarget;
|
|
151
|
+
this.state.setSelection(textareaEl.selectionStart, textareaEl.selectionEnd);
|
|
152
|
+
},
|
|
153
|
+
onkeydown: (ev) => {
|
|
154
|
+
const textareaEl = ev.currentTarget;
|
|
155
|
+
this.state.setSelection(textareaEl.selectionStart, textareaEl.selectionEnd);
|
|
156
|
+
if (ev.code === "Escape")
|
|
157
|
+
this.state.isEditing = false;
|
|
158
|
+
if (ev.ctrlKey && ev.shiftKey) {
|
|
159
|
+
if (ev.key.toLowerCase() === "h") {
|
|
160
|
+
this.state.applyHeading();
|
|
161
|
+
ev.preventDefault();
|
|
162
|
+
}
|
|
163
|
+
if (ev.key.toLowerCase() === "b") {
|
|
164
|
+
this.state.applyBold();
|
|
165
|
+
ev.preventDefault();
|
|
166
|
+
}
|
|
167
|
+
if (ev.key.toLowerCase() === "i") {
|
|
168
|
+
this.state.applyItalic();
|
|
169
|
+
ev.preventDefault();
|
|
170
|
+
}
|
|
171
|
+
if (ev.key.toLowerCase() === "c") {
|
|
172
|
+
this.state.applyCode();
|
|
173
|
+
ev.preventDefault();
|
|
174
|
+
}
|
|
175
|
+
if (ev.key.toLowerCase() === "s") {
|
|
176
|
+
this.state.applyStrikethrough();
|
|
177
|
+
ev.preventDefault();
|
|
178
|
+
}
|
|
179
|
+
if (ev.key.toLowerCase() === "u") {
|
|
180
|
+
this.state.applyUnorderedList();
|
|
181
|
+
ev.preventDefault();
|
|
182
|
+
}
|
|
183
|
+
if (ev.key.toLowerCase() === "o") {
|
|
184
|
+
this.state.applyOrderedList();
|
|
185
|
+
ev.preventDefault();
|
|
186
|
+
}
|
|
187
|
+
if (ev.key.toLowerCase() === "l") {
|
|
188
|
+
this.state.applyLink();
|
|
189
|
+
ev.preventDefault();
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
if (ev.key === "Tab") {
|
|
193
|
+
this.state.applyIndent(ev.shiftKey);
|
|
194
|
+
ev.preventDefault();
|
|
195
|
+
}
|
|
196
|
+
},
|
|
197
|
+
}),
|
|
198
|
+
]),
|
|
199
|
+
],
|
|
200
|
+
]);
|
|
201
|
+
}
|
|
202
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./MarkdownEditor";
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./MarkdownEditor"), exports);
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Subscription } from "rxjs";
|
|
2
|
+
export declare class MarkdownEditorState {
|
|
3
|
+
subs: Subscription;
|
|
4
|
+
isEditing: boolean;
|
|
5
|
+
isEditingPrevious: boolean;
|
|
6
|
+
editorValue: string;
|
|
7
|
+
editorEl: HTMLTextAreaElement | undefined;
|
|
8
|
+
editorContainerEl: HTMLDivElement | undefined;
|
|
9
|
+
editValue: (markdown: string) => any;
|
|
10
|
+
selectionStart: number;
|
|
11
|
+
selectionEnd: number;
|
|
12
|
+
requestSelection: {
|
|
13
|
+
start: number;
|
|
14
|
+
end: number;
|
|
15
|
+
} | undefined;
|
|
16
|
+
constructor(editValue: (markdown: string) => any);
|
|
17
|
+
private selectedText;
|
|
18
|
+
private findSelectedLines;
|
|
19
|
+
private findSelectedWord;
|
|
20
|
+
destroy(): void;
|
|
21
|
+
setSelection(start: number, end: number): void;
|
|
22
|
+
applyHeading(level?: number): void;
|
|
23
|
+
applyBold(): void;
|
|
24
|
+
applyItalic(): void;
|
|
25
|
+
applyCode(): void;
|
|
26
|
+
applyStrikethrough(): void;
|
|
27
|
+
applyUnorderedList(): void;
|
|
28
|
+
applyOrderedList(): void;
|
|
29
|
+
applyLink(): void;
|
|
30
|
+
applyIndent(backward?: boolean): void;
|
|
31
|
+
}
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MarkdownEditorState = void 0;
|
|
4
|
+
const rxjs_1 = require("rxjs");
|
|
5
|
+
const utils_1 = require("../../utils");
|
|
6
|
+
const mithril_1 = require("mithril");
|
|
7
|
+
class MarkdownEditorState {
|
|
8
|
+
constructor(editValue) {
|
|
9
|
+
this.subs = new rxjs_1.Subscription();
|
|
10
|
+
this.isEditing = false;
|
|
11
|
+
this.isEditingPrevious = false;
|
|
12
|
+
this.editorValue = "";
|
|
13
|
+
this.editorEl = undefined;
|
|
14
|
+
this.editorContainerEl = undefined;
|
|
15
|
+
this.selectionStart = 0;
|
|
16
|
+
this.selectionEnd = 0;
|
|
17
|
+
this.editValue = editValue;
|
|
18
|
+
const onclick = (ev) => {
|
|
19
|
+
if (this.isEditing && this.editorContainerEl) {
|
|
20
|
+
if (!(0, utils_1.mouseWithinElement)(ev, this.editorContainerEl)) {
|
|
21
|
+
this.isEditing = false;
|
|
22
|
+
(0, mithril_1.redraw)();
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
document.addEventListener("click", onclick);
|
|
27
|
+
this.subs.add(() => document.removeEventListener("click", onclick));
|
|
28
|
+
}
|
|
29
|
+
selectedText() {
|
|
30
|
+
const selection = this.editorValue.slice(this.selectionStart, this.selectionEnd);
|
|
31
|
+
return selection;
|
|
32
|
+
}
|
|
33
|
+
findSelectedLines() {
|
|
34
|
+
// if (!this.editorEl) return [];
|
|
35
|
+
let linesStart = this.selectionStart;
|
|
36
|
+
let linesEnd = this.selectionEnd;
|
|
37
|
+
for (let i = this.selectionStart; i >= 0; i--) {
|
|
38
|
+
if (i > 1 && this.editorValue[i - 1] === "\n") {
|
|
39
|
+
linesStart = i;
|
|
40
|
+
break;
|
|
41
|
+
}
|
|
42
|
+
if (i === 0) {
|
|
43
|
+
linesStart = i;
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
for (let i = this.selectionEnd; i < this.editorValue.length; i++) {
|
|
48
|
+
if (this.editorValue[i] === "\n" || i === 0) {
|
|
49
|
+
linesEnd = i;
|
|
50
|
+
break;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
const selectedLinesString = this.editorValue.slice(linesStart, linesEnd);
|
|
54
|
+
// console.log("selectedLinesStr", linesStart, linesEnd, selectedLinesString);
|
|
55
|
+
let selectedLinesText = selectedLinesString.split("\n");
|
|
56
|
+
selectedLinesText = selectedLinesText.map((line, lineIndex) => {
|
|
57
|
+
return line + ((lineIndex <= (selectedLinesText.length - 2)) ? "\n" : "");
|
|
58
|
+
});
|
|
59
|
+
const lines = [];
|
|
60
|
+
let offset = linesStart;
|
|
61
|
+
for (let i = 0; i < selectedLinesText.length; i++) {
|
|
62
|
+
lines.push({
|
|
63
|
+
start: offset,
|
|
64
|
+
end: offset + selectedLinesText[i].length,
|
|
65
|
+
content: selectedLinesText[i],
|
|
66
|
+
});
|
|
67
|
+
offset = offset + selectedLinesText[i].length;
|
|
68
|
+
}
|
|
69
|
+
// console.log("lines", lines);
|
|
70
|
+
return lines;
|
|
71
|
+
}
|
|
72
|
+
findSelectedWord() {
|
|
73
|
+
let start = this.selectionStart;
|
|
74
|
+
let end = this.selectionEnd;
|
|
75
|
+
for (let i = this.selectionStart; i >= 0; i--) {
|
|
76
|
+
if (i > 1 && (this.editorValue[i - 1] === " " || this.editorValue[i - 1] === "\n")) {
|
|
77
|
+
start = i;
|
|
78
|
+
break;
|
|
79
|
+
}
|
|
80
|
+
if (i === 0) {
|
|
81
|
+
start = i;
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
for (let i = this.selectionEnd; i < this.editorValue.length; i++) {
|
|
86
|
+
if (this.editorValue[i] === "" || this.editorValue[i] === "\n" || i === 0) {
|
|
87
|
+
end = i;
|
|
88
|
+
break;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return {
|
|
92
|
+
start,
|
|
93
|
+
end,
|
|
94
|
+
content: this.editorValue.slice(start, end),
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
destroy() {
|
|
98
|
+
this.subs.unsubscribe();
|
|
99
|
+
}
|
|
100
|
+
setSelection(start, end) {
|
|
101
|
+
this.selectionStart = start;
|
|
102
|
+
this.selectionEnd = end;
|
|
103
|
+
const selection = this.editorValue.slice(start, end);
|
|
104
|
+
// console.log(start, end, selection);
|
|
105
|
+
}
|
|
106
|
+
applyHeading(level = 1) {
|
|
107
|
+
// console.log("addHeading", "selection:", this.selectionStart, this.selectionEnd);
|
|
108
|
+
let value = this.editorValue;
|
|
109
|
+
const toInsert = "#".padEnd(level, "#") + " ";
|
|
110
|
+
const lines = this.findSelectedLines();
|
|
111
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
112
|
+
value = value.slice(0, lines[i].start) + toInsert + value.slice(lines[i].start);
|
|
113
|
+
}
|
|
114
|
+
this.editorValue = value;
|
|
115
|
+
this.editValue(value);
|
|
116
|
+
const newSelection = this.selectionStart + toInsert.length;
|
|
117
|
+
this.requestSelection = { start: newSelection, end: newSelection };
|
|
118
|
+
}
|
|
119
|
+
applyBold() {
|
|
120
|
+
// console.log("addBold", "selection:", this.selectionStart, this.selectionEnd);
|
|
121
|
+
let start = this.selectionStart;
|
|
122
|
+
let end = this.selectionEnd;
|
|
123
|
+
if (start === end) {
|
|
124
|
+
const word = this.findSelectedWord();
|
|
125
|
+
start = word.start;
|
|
126
|
+
end = word.end;
|
|
127
|
+
}
|
|
128
|
+
let value = this.editorValue;
|
|
129
|
+
value = value.slice(0, end) + "**" + value.slice(end);
|
|
130
|
+
value = value.slice(0, start) + "**" + value.slice(start);
|
|
131
|
+
this.editorValue = value;
|
|
132
|
+
this.editValue(value);
|
|
133
|
+
const newSelection = start + 2;
|
|
134
|
+
this.requestSelection = { start: newSelection, end: newSelection };
|
|
135
|
+
}
|
|
136
|
+
applyItalic() {
|
|
137
|
+
// console.log("addItalic", "selection:", this.selectionStart, this.selectionEnd);
|
|
138
|
+
let start = this.selectionStart;
|
|
139
|
+
let end = this.selectionEnd;
|
|
140
|
+
if (start === end) {
|
|
141
|
+
const word = this.findSelectedWord();
|
|
142
|
+
start = word.start;
|
|
143
|
+
end = word.end;
|
|
144
|
+
}
|
|
145
|
+
let value = this.editorValue;
|
|
146
|
+
value = value.slice(0, end) + "*" + value.slice(end);
|
|
147
|
+
value = value.slice(0, start) + "*" + value.slice(start);
|
|
148
|
+
this.editorValue = value;
|
|
149
|
+
this.editValue(value);
|
|
150
|
+
const newSelection = start + 1;
|
|
151
|
+
this.requestSelection = { start: newSelection, end: newSelection };
|
|
152
|
+
}
|
|
153
|
+
applyCode() {
|
|
154
|
+
// console.log("addCode", "selection:", this.selectionStart, this.selectionEnd);
|
|
155
|
+
let start = this.selectionStart;
|
|
156
|
+
let end = this.selectionEnd;
|
|
157
|
+
if (start === end) {
|
|
158
|
+
const word = this.findSelectedWord();
|
|
159
|
+
start = word.start;
|
|
160
|
+
end = word.end;
|
|
161
|
+
}
|
|
162
|
+
let value = this.editorValue;
|
|
163
|
+
value = value.slice(0, end) + "`" + value.slice(end);
|
|
164
|
+
value = value.slice(0, start) + "`" + value.slice(start);
|
|
165
|
+
this.editorValue = value;
|
|
166
|
+
this.editValue(value);
|
|
167
|
+
const newSelection = start + 1;
|
|
168
|
+
this.requestSelection = { start: newSelection, end: newSelection };
|
|
169
|
+
}
|
|
170
|
+
applyStrikethrough() {
|
|
171
|
+
// console.log("addStrikethrough", "selection:", this.selectionStart, this.selectionEnd);
|
|
172
|
+
let start = this.selectionStart;
|
|
173
|
+
let end = this.selectionEnd;
|
|
174
|
+
if (start === end) {
|
|
175
|
+
const word = this.findSelectedWord();
|
|
176
|
+
start = word.start;
|
|
177
|
+
end = word.end;
|
|
178
|
+
}
|
|
179
|
+
let value = this.editorValue;
|
|
180
|
+
value = value.slice(0, end) + "~~" + value.slice(end);
|
|
181
|
+
value = value.slice(0, start) + "~~" + value.slice(start);
|
|
182
|
+
this.editorValue = value;
|
|
183
|
+
this.editValue(value);
|
|
184
|
+
const newSelection = start + 2;
|
|
185
|
+
this.requestSelection = { start: newSelection, end: newSelection };
|
|
186
|
+
}
|
|
187
|
+
applyUnorderedList() {
|
|
188
|
+
// console.log("addUnorderedList", "selection:", this.selectionStart, this.selectionEnd);
|
|
189
|
+
let value = this.editorValue;
|
|
190
|
+
const toInsert = "- ";
|
|
191
|
+
const lines = this.findSelectedLines();
|
|
192
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
193
|
+
value = value.slice(0, lines[i].start) + toInsert + value.slice(lines[i].start);
|
|
194
|
+
}
|
|
195
|
+
this.editorValue = value;
|
|
196
|
+
this.editValue(value);
|
|
197
|
+
const newSelection = this.selectionStart + 2;
|
|
198
|
+
this.requestSelection = { start: newSelection, end: newSelection };
|
|
199
|
+
}
|
|
200
|
+
applyOrderedList() {
|
|
201
|
+
// console.log("addOrderedList", "selection:", this.selectionStart, this.selectionEnd);
|
|
202
|
+
let value = this.editorValue;
|
|
203
|
+
const lines = this.findSelectedLines();
|
|
204
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
205
|
+
let toInsert = `${i + 1}. `;
|
|
206
|
+
value = value.slice(0, lines[i].start) + toInsert + value.slice(lines[i].start);
|
|
207
|
+
}
|
|
208
|
+
this.editorValue = value;
|
|
209
|
+
this.editValue(value);
|
|
210
|
+
const newSelection = this.selectionStart + 3;
|
|
211
|
+
this.requestSelection = { start: newSelection, end: newSelection };
|
|
212
|
+
}
|
|
213
|
+
applyLink() {
|
|
214
|
+
// console.log("addLink", "selection:", this.selectionStart, this.selectionEnd);
|
|
215
|
+
let start = this.selectionStart;
|
|
216
|
+
let end = this.selectionEnd;
|
|
217
|
+
let content = this.selectedText();
|
|
218
|
+
if (start === end) {
|
|
219
|
+
const word = this.findSelectedWord();
|
|
220
|
+
start = word.start;
|
|
221
|
+
end = word.end;
|
|
222
|
+
content = word.content;
|
|
223
|
+
}
|
|
224
|
+
const isUrl = content.startsWith("http") || content.startsWith("www");
|
|
225
|
+
let url = (Boolean(content) && isUrl) ? content : "https://example.com";
|
|
226
|
+
let value = this.editorValue;
|
|
227
|
+
value = value.slice(0, end) + `](${url})` + value.slice(end);
|
|
228
|
+
value = value.slice(0, start) + "[" + value.slice(start);
|
|
229
|
+
this.editorValue = value;
|
|
230
|
+
this.editValue(value);
|
|
231
|
+
const newSelection = start + 1;
|
|
232
|
+
this.requestSelection = { start: newSelection, end: newSelection };
|
|
233
|
+
}
|
|
234
|
+
applyIndent(backward = false) {
|
|
235
|
+
// console.log("applyIndent", "selection:", this.selectionStart, this.selectionEnd);
|
|
236
|
+
let value = this.editorValue;
|
|
237
|
+
// const toInsert = "- ";
|
|
238
|
+
const lines = this.findSelectedLines();
|
|
239
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
240
|
+
if (backward) {
|
|
241
|
+
let newContent = lines[i].content;
|
|
242
|
+
if (newContent.startsWith(" "))
|
|
243
|
+
newContent = newContent.slice(1);
|
|
244
|
+
if (newContent.startsWith(" "))
|
|
245
|
+
newContent = newContent.slice(1);
|
|
246
|
+
value = value.slice(0, lines[i].start) + newContent + value.slice(lines[i].end);
|
|
247
|
+
}
|
|
248
|
+
else {
|
|
249
|
+
value = value.slice(0, lines[i].start) + " " + value.slice(lines[i].start);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
this.editorValue = value;
|
|
253
|
+
this.editValue(value);
|
|
254
|
+
let newSelection = this.selectionStart + (backward ? -2 : 2);
|
|
255
|
+
newSelection = Math.max(newSelection, lines[0].start);
|
|
256
|
+
this.requestSelection = { start: newSelection, end: newSelection };
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
exports.MarkdownEditorState = MarkdownEditorState;
|
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
import m from "mithril";
|
|
2
|
+
export interface MenuOptions {
|
|
3
|
+
noFlipV?: boolean;
|
|
4
|
+
noFlipH?: boolean;
|
|
5
|
+
forceFlipV?: boolean;
|
|
6
|
+
forceFlipH?: boolean;
|
|
7
|
+
}
|
|
2
8
|
export declare const Menu: m.Component<{
|
|
3
9
|
x: number | undefined;
|
|
4
10
|
y: number | undefined;
|
|
11
|
+
options?: MenuOptions;
|
|
5
12
|
}, {
|
|
6
13
|
el?: HTMLDivElement;
|
|
7
14
|
}>;
|
|
@@ -18,16 +18,24 @@ exports.Menu = {
|
|
|
18
18
|
onupdate({ dom }) {
|
|
19
19
|
// if (dom) this.el = dom as HTMLDivElement;
|
|
20
20
|
},
|
|
21
|
-
view({ attrs, children
|
|
22
|
-
var _a, _b;
|
|
21
|
+
view({ attrs, children }) {
|
|
22
|
+
var _a, _b, _c, _d, _e, _f;
|
|
23
23
|
const maxWidthPx = Math.min(window.innerWidth, menu_constants_1.MENU_CONSTANTS.MAX_WIDTH_PX);
|
|
24
24
|
const maxHeightPx = window.innerHeight / 2;
|
|
25
25
|
const xPx = (_a = attrs.x) !== null && _a !== void 0 ? _a : 0;
|
|
26
26
|
const yPx = (_b = attrs.y) !== null && _b !== void 0 ? _b : 0;
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
let flipH = ((xPx + menu_constants_1.MENU_CONSTANTS.MIN_WIDTH_PX) > window.innerWidth);
|
|
28
|
+
let flipV = menu_settings_1.MENU_SETTINGS.ANCHOR === "page"
|
|
29
29
|
? ((yPx + maxHeightPx - window.scrollY) > window.innerHeight)
|
|
30
30
|
: ((yPx + maxHeightPx) > window.innerHeight);
|
|
31
|
+
if (((_c = attrs.options) === null || _c === void 0 ? void 0 : _c.noFlipH) === true)
|
|
32
|
+
flipH = false;
|
|
33
|
+
if (((_d = attrs.options) === null || _d === void 0 ? void 0 : _d.noFlipV) === true)
|
|
34
|
+
flipV = false;
|
|
35
|
+
if (((_e = attrs.options) === null || _e === void 0 ? void 0 : _e.forceFlipH) === true)
|
|
36
|
+
flipH = true;
|
|
37
|
+
if (((_f = attrs.options) === null || _f === void 0 ? void 0 : _f.forceFlipV) === true)
|
|
38
|
+
flipV = true;
|
|
31
39
|
// console.log({
|
|
32
40
|
// "yPx": yPx,
|
|
33
41
|
// "maxHeightPx": maxHeightPx,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import m from "mithril";
|
|
2
|
+
import { MenuOptions } from "./Menu";
|
|
2
3
|
export declare class MenuManager {
|
|
3
4
|
private containerEl;
|
|
4
5
|
private _menuVnode;
|
|
@@ -15,7 +16,7 @@ export declare class MenuManager {
|
|
|
15
16
|
* @param ev
|
|
16
17
|
* @param menuContents
|
|
17
18
|
*/
|
|
18
|
-
show(ev: MouseEvent | undefined, menuContents: m.ChildArrayOrPrimitive): Promise<void>;
|
|
19
|
+
show(ev: MouseEvent | undefined, menuContents: m.ChildArrayOrPrimitive, options?: MenuOptions): Promise<void>;
|
|
19
20
|
hide(): void;
|
|
20
21
|
}
|
|
21
22
|
export declare const menuMgr: MenuManager;
|
|
@@ -48,7 +48,7 @@ class MenuManager {
|
|
|
48
48
|
* @param ev
|
|
49
49
|
* @param menuContents
|
|
50
50
|
*/
|
|
51
|
-
show(ev, menuContents) {
|
|
51
|
+
show(ev, menuContents, options) {
|
|
52
52
|
return __awaiter(this, void 0, void 0, function* () {
|
|
53
53
|
ev === null || ev === void 0 ? void 0 : ev.stopPropagation();
|
|
54
54
|
if (this.isOpen) {
|
|
@@ -60,6 +60,7 @@ class MenuManager {
|
|
|
60
60
|
const menuVnode = (0, mithril_1.default)(Menu_1.Menu, {
|
|
61
61
|
x: ev === null || ev === void 0 ? void 0 : ev.clientX,
|
|
62
62
|
y: menu_settings_1.MENU_SETTINGS.ANCHOR === "page" ? ev === null || ev === void 0 ? void 0 : ev.pageY : ev === null || ev === void 0 ? void 0 : ev.clientY,
|
|
63
|
+
options,
|
|
63
64
|
}, [
|
|
64
65
|
menuContents,
|
|
65
66
|
]);
|
package/dist/utils/events.d.ts
CHANGED
|
@@ -1 +1,8 @@
|
|
|
1
1
|
export declare function dragEventFiles(ev: DragEvent): File[];
|
|
2
|
+
/**
|
|
3
|
+
* Find whether a mouse event is within a given DOM element using clientX/Y and the bounding client rect
|
|
4
|
+
* @param ev
|
|
5
|
+
* @param element
|
|
6
|
+
* @returns
|
|
7
|
+
*/
|
|
8
|
+
export declare function mouseWithinElement(ev: MouseEvent, element: Element): boolean;
|
package/dist/utils/events.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.dragEventFiles = void 0;
|
|
3
|
+
exports.mouseWithinElement = exports.dragEventFiles = void 0;
|
|
4
4
|
function dragEventFiles(ev) {
|
|
5
5
|
var _a, _b, _c;
|
|
6
6
|
const files = [];
|
|
@@ -27,3 +27,18 @@ function dragEventFiles(ev) {
|
|
|
27
27
|
return files;
|
|
28
28
|
}
|
|
29
29
|
exports.dragEventFiles = dragEventFiles;
|
|
30
|
+
/**
|
|
31
|
+
* Find whether a mouse event is within a given DOM element using clientX/Y and the bounding client rect
|
|
32
|
+
* @param ev
|
|
33
|
+
* @param element
|
|
34
|
+
* @returns
|
|
35
|
+
*/
|
|
36
|
+
function mouseWithinElement(ev, element) {
|
|
37
|
+
const elementRect = element.getBoundingClientRect();
|
|
38
|
+
const isWithin = (ev.clientY >= elementRect.top) &&
|
|
39
|
+
(ev.clientY <= elementRect.bottom) &&
|
|
40
|
+
(ev.clientX >= elementRect.left) &&
|
|
41
|
+
(ev.clientX <= elementRect.right);
|
|
42
|
+
return isWithin;
|
|
43
|
+
}
|
|
44
|
+
exports.mouseWithinElement = mouseWithinElement;
|