@hypericon/mico 0.3.5 → 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.
- package/README.md +54 -0
- package/dist/components/dialog/dialog-manager.js +2 -5
- package/dist/components/drop-target/DropTarget.d.ts +24 -0
- package/dist/components/drop-target/DropTarget.js +62 -0
- package/dist/components/drop-target/drop-target.state.d.ts +9 -0
- package/dist/components/drop-target/drop-target.state.js +77 -0
- package/dist/components/drop-target/index.d.ts +1 -0
- package/dist/components/drop-target/index.js +17 -0
- package/dist/components/index.d.ts +2 -0
- package/dist/components/index.js +2 -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 +8 -0
- package/dist/utils/events.js +44 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -12,3 +12,57 @@ UI components and utilities built with Mithril.
|
|
|
12
12
|
```sh
|
|
13
13
|
$ npm i @hypericon/mico
|
|
14
14
|
```
|
|
15
|
+
|
|
16
|
+
## Usage
|
|
17
|
+
|
|
18
|
+
**[View the usage and examples documentation here.](https://hypericon-mico.netlify.app)**
|
|
19
|
+
|
|
20
|
+
### Example
|
|
21
|
+
|
|
22
|
+
Import the components from the package. Some components may also export functions to build typed versions. Components that have customisable styles have their CSS classes of config attributes documented on the documentation site
|
|
23
|
+
|
|
24
|
+
```ts
|
|
25
|
+
import m from "mithril";
|
|
26
|
+
import { typedTable } from "@hypericon/mico";
|
|
27
|
+
import { Widget } from "../interfaces"; // Example
|
|
28
|
+
import { WidgetService } from "../services"; // Example
|
|
29
|
+
import { WidgetStatusIcon } from "../components"; // Example
|
|
30
|
+
|
|
31
|
+
const WidgetTable = typedTable<Widget>();
|
|
32
|
+
|
|
33
|
+
const ExamplePage: m.Component = {
|
|
34
|
+
view() {
|
|
35
|
+
return m("", [
|
|
36
|
+
m("h1", "Widgets"),
|
|
37
|
+
m(WidgetTable, {
|
|
38
|
+
data: WidgetService.widgets,
|
|
39
|
+
columns: [
|
|
40
|
+
WidgetTable.col("Position", (w, i) => i + 1), // Row index is supplied
|
|
41
|
+
WidgetTable.col("Name", w => w.name), // Type checking on row object properties
|
|
42
|
+
WidgetTable.col("Price", w => `£${w.price}`),
|
|
43
|
+
WidgetTable.col("Status", w => m(WidgetStatusIcon, { widget: w })),
|
|
44
|
+
// etc.
|
|
45
|
+
],
|
|
46
|
+
}),
|
|
47
|
+
]);
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Development
|
|
53
|
+
|
|
54
|
+
Start a hot-reloading dev server serving the documentation and example site with
|
|
55
|
+
|
|
56
|
+
```sh
|
|
57
|
+
$ npm run dev
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Publish the updated package and deploy the latest version of the docs site with
|
|
61
|
+
|
|
62
|
+
```sh
|
|
63
|
+
$ npm run publish-deploy
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## License
|
|
67
|
+
|
|
68
|
+
MIT
|
|
@@ -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
|
});
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import m from "mithril";
|
|
2
|
+
import { DropTargetState } from "./drop-target.state";
|
|
3
|
+
export declare const DropTarget: m.Component<{
|
|
4
|
+
/**
|
|
5
|
+
* Function called when the user drops one or more files onto the drop target
|
|
6
|
+
* @param result
|
|
7
|
+
* @returns
|
|
8
|
+
*/
|
|
9
|
+
onDropFiles: (result: {
|
|
10
|
+
files: File[];
|
|
11
|
+
ev: DragEvent;
|
|
12
|
+
}) => any;
|
|
13
|
+
/** The message to display in the drop target */
|
|
14
|
+
dropMessage?: string | m.Children;
|
|
15
|
+
/**
|
|
16
|
+
* Whether to automatically set the height of the drop target baed on the height of the wrapped elements
|
|
17
|
+
* @default true
|
|
18
|
+
*/
|
|
19
|
+
autoHeight?: boolean;
|
|
20
|
+
class?: string;
|
|
21
|
+
style?: string;
|
|
22
|
+
}, {
|
|
23
|
+
state: DropTargetState;
|
|
24
|
+
}>;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.DropTarget = void 0;
|
|
7
|
+
const mithril_1 = __importDefault(require("mithril"));
|
|
8
|
+
const drop_target_state_1 = require("./drop-target.state");
|
|
9
|
+
const utils_1 = require("../../utils");
|
|
10
|
+
exports.DropTarget = {
|
|
11
|
+
oninit() {
|
|
12
|
+
this.state = new drop_target_state_1.DropTargetState();
|
|
13
|
+
},
|
|
14
|
+
oncreate({ dom }) {
|
|
15
|
+
this.state.lastHeight = dom.clientHeight;
|
|
16
|
+
},
|
|
17
|
+
onupdate({ dom }) {
|
|
18
|
+
if (!this.state.isDragging) {
|
|
19
|
+
this.state.lastHeight = dom.clientHeight;
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
view({ attrs, children }) {
|
|
23
|
+
const autoHeightStr = (attrs.autoHeight !== false) ? `height: ${this.state.lastHeight}px;` : "";
|
|
24
|
+
return (0, mithril_1.default)(".mico-drop-container", {
|
|
25
|
+
class: attrs.class,
|
|
26
|
+
style: attrs.style,
|
|
27
|
+
}, [
|
|
28
|
+
this.state.isDragging ? [
|
|
29
|
+
(0, mithril_1.default)("", {
|
|
30
|
+
class: `mico-drop-target ${this.state.isOver ? "highlighted" : ""}`,
|
|
31
|
+
style: `${autoHeightStr} display: flex; flex-direction: column; align-items: center; justify-content: center;`,
|
|
32
|
+
ondragover: (ev) => {
|
|
33
|
+
this.state.isOver = true;
|
|
34
|
+
},
|
|
35
|
+
ondragleave: (ev) => {
|
|
36
|
+
const containsNewTarget = ev.currentTarget.contains(ev.relatedTarget);
|
|
37
|
+
if (!containsNewTarget) {
|
|
38
|
+
this.state.isOver = false;
|
|
39
|
+
}
|
|
40
|
+
ev.preventDefault();
|
|
41
|
+
return false;
|
|
42
|
+
},
|
|
43
|
+
ondrop: (ev) => {
|
|
44
|
+
// console.log("ondrop", ev);
|
|
45
|
+
this.state.isOver = false;
|
|
46
|
+
ev.preventDefault();
|
|
47
|
+
const files = (0, utils_1.dragEventFiles)(ev);
|
|
48
|
+
if (files.length > 0) {
|
|
49
|
+
attrs.onDropFiles({ ev, files });
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
}, [
|
|
53
|
+
(attrs.dropMessage && typeof attrs.dropMessage === "object")
|
|
54
|
+
? attrs.dropMessage
|
|
55
|
+
: (0, mithril_1.default)("span.mico-drop-target-message", attrs.dropMessage || "Drop files here"),
|
|
56
|
+
]),
|
|
57
|
+
] : [
|
|
58
|
+
children,
|
|
59
|
+
],
|
|
60
|
+
]);
|
|
61
|
+
}
|
|
62
|
+
};
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DropTargetState = void 0;
|
|
4
|
+
const mithril_1 = require("mithril");
|
|
5
|
+
const rxjs_1 = require("rxjs");
|
|
6
|
+
class DropTargetState {
|
|
7
|
+
constructor() {
|
|
8
|
+
this.subs = new rxjs_1.Subscription();
|
|
9
|
+
this.isDragging = false;
|
|
10
|
+
this.isOver = false;
|
|
11
|
+
this.lastHeight = 100;
|
|
12
|
+
this.initialise();
|
|
13
|
+
}
|
|
14
|
+
initialise() {
|
|
15
|
+
this.destroy();
|
|
16
|
+
this.subs = new rxjs_1.Subscription();
|
|
17
|
+
this.isDragging = false;
|
|
18
|
+
this.isOver = false;
|
|
19
|
+
const onclick = () => {
|
|
20
|
+
this.isDragging = false;
|
|
21
|
+
(0, mithril_1.redraw)();
|
|
22
|
+
};
|
|
23
|
+
const ondragstart = (ev) => {
|
|
24
|
+
ev.preventDefault();
|
|
25
|
+
};
|
|
26
|
+
const ondragend = (ev) => {
|
|
27
|
+
this.isDragging = false;
|
|
28
|
+
(0, mithril_1.redraw)();
|
|
29
|
+
ev.preventDefault();
|
|
30
|
+
};
|
|
31
|
+
const ondragenter = (ev) => {
|
|
32
|
+
this.isDragging = true;
|
|
33
|
+
(0, mithril_1.redraw)();
|
|
34
|
+
ev.preventDefault();
|
|
35
|
+
};
|
|
36
|
+
const ondragover = (ev) => {
|
|
37
|
+
ev.preventDefault();
|
|
38
|
+
};
|
|
39
|
+
const ondragleave = (ev) => {
|
|
40
|
+
// if the drag moved from the element to outside the element
|
|
41
|
+
const containsTarget = ev.currentTarget.contains(ev.relatedTarget);
|
|
42
|
+
if (!containsTarget) {
|
|
43
|
+
// console.log("page ondragleave, isDragging=false")
|
|
44
|
+
this.isDragging = false;
|
|
45
|
+
(0, mithril_1.redraw)();
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
const ondrag = (ev) => {
|
|
49
|
+
ev.preventDefault();
|
|
50
|
+
};
|
|
51
|
+
const ondrop = (ev) => {
|
|
52
|
+
this.isDragging = false;
|
|
53
|
+
(0, mithril_1.redraw)();
|
|
54
|
+
ev.preventDefault();
|
|
55
|
+
};
|
|
56
|
+
document.addEventListener("click", onclick);
|
|
57
|
+
this.subs.add(() => document.removeEventListener("click", onclick));
|
|
58
|
+
document.addEventListener("dragstart", ondragstart);
|
|
59
|
+
this.subs.add(() => document.removeEventListener("dragstart", ondragstart));
|
|
60
|
+
document.addEventListener("dragend", ondragend);
|
|
61
|
+
this.subs.add(() => document.removeEventListener("dragend", ondragend));
|
|
62
|
+
document.addEventListener("dragenter", ondragenter);
|
|
63
|
+
this.subs.add(() => document.removeEventListener("dragenter", ondragenter));
|
|
64
|
+
document.addEventListener("dragover", ondragover);
|
|
65
|
+
this.subs.add(() => document.removeEventListener("dragover", ondragover));
|
|
66
|
+
document.addEventListener("dragleave", ondragleave);
|
|
67
|
+
this.subs.add(() => document.removeEventListener("dragleave", ondragleave));
|
|
68
|
+
document.addEventListener("drag", ondrag);
|
|
69
|
+
this.subs.add(() => document.removeEventListener("drag", ondrag));
|
|
70
|
+
document.addEventListener("drop", ondrop);
|
|
71
|
+
this.subs.add(() => document.removeEventListener("drop", ondrop));
|
|
72
|
+
}
|
|
73
|
+
destroy() {
|
|
74
|
+
this.subs.unsubscribe();
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
exports.DropTargetState = DropTargetState;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./DropTarget";
|
|
@@ -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("./DropTarget"), exports);
|
package/dist/components/index.js
CHANGED
|
@@ -19,9 +19,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
19
19
|
// export * from "./data-table";
|
|
20
20
|
__exportStar(require("./dialog"), exports);
|
|
21
21
|
// export * from "./drawer";
|
|
22
|
+
__exportStar(require("./drop-target"), exports);
|
|
22
23
|
// export * from "./form";
|
|
23
24
|
__exportStar(require("./icon"), exports);
|
|
24
25
|
__exportStar(require("./markdown"), exports);
|
|
26
|
+
__exportStar(require("./markdown-editor"), exports);
|
|
25
27
|
__exportStar(require("./menu"), exports);
|
|
26
28
|
// export * from "./modal";
|
|
27
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
|
-
|
|
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
|
]);
|
|
@@ -0,0 +1,8 @@
|
|
|
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;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.mouseWithinElement = exports.dragEventFiles = void 0;
|
|
4
|
+
function dragEventFiles(ev) {
|
|
5
|
+
var _a, _b, _c;
|
|
6
|
+
const files = [];
|
|
7
|
+
if ((_a = ev.dataTransfer) === null || _a === void 0 ? void 0 : _a.items) {
|
|
8
|
+
// Use DataTransferItemList interface to access the file(s)
|
|
9
|
+
[...ev.dataTransfer.items].forEach((item, i) => {
|
|
10
|
+
// If dropped items aren't files, reject them
|
|
11
|
+
if (item.kind === "file") {
|
|
12
|
+
const file = item.getAsFile();
|
|
13
|
+
if (file) {
|
|
14
|
+
// console.log(`… file[${i}].name = ${file.name}`);
|
|
15
|
+
files.push(file);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
// Use DataTransfer interface to access the file(s)
|
|
22
|
+
[...(_c = (_b = ev.dataTransfer) === null || _b === void 0 ? void 0 : _b.files) !== null && _c !== void 0 ? _c : []].forEach((file, i) => {
|
|
23
|
+
// console.log(`… file[${i}].name = ${file.name}`);
|
|
24
|
+
files.push(file);
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
return files;
|
|
28
|
+
}
|
|
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/dist/utils/index.d.ts
CHANGED
package/dist/utils/index.js
CHANGED