@hypericon/mico 0.3.6 → 0.3.7

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.
@@ -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 dialogRect = dom.getBoundingClientRect();
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
  });
@@ -2,5 +2,6 @@ export * from "./dialog";
2
2
  export * from "./drop-target";
3
3
  export * from "./icon";
4
4
  export * from "./markdown";
5
+ export * from "./markdown-editor";
5
6
  export * from "./menu";
6
7
  export * from "./table";
@@ -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 + 2,
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
- const flipH = ((xPx + menu_constants_1.MENU_CONSTANTS.MIN_WIDTH_PX) > window.innerWidth);
28
- const flipV = menu_settings_1.MENU_SETTINGS.ANCHOR === "page"
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
  ]);
@@ -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;
@@ -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;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hypericon/mico",
3
- "version": "0.3.6",
3
+ "version": "0.3.7",
4
4
  "description": "UI components and utilities with Mithril",
5
5
  "author": "Ed Johnson, Hypericon Ltd",
6
6
  "license": "MIT",