anki/ts/editable/ContentEditable.svelte
Henrik Giesel 2778b9220c
Mathjax editor improvements (#1502)
* Remove unnecessary stopPropagation of mathjax-overlay events

* Use CodeMirror component for MathjaxHandle

* Refactor ResizeObserver code in MathjaxHandle

* Wrap setRange in CodeMirror in try/catch

* Add Mathjax Editor bottom margin

* Add custom Enter and Shift+Enter shortcuts for the MathjaxHandle

* Format

* Move placeCaretAfter to domlib

* Move focus back to field after editing Mathjax

* Put Cursor after Mathjax after accepting

* Add delete button for Mathjax

* Change border color of mathjax menu

* Refactor into MathjaxMenu

* Put caretKeyword in variable

* Use one ResizeObserver for all Mathjax images

* Add minmimum width for Mathjax editor

* is still smaller than minimal window width

* Add bazel directories to .prettierignore and format from root

* exclude ftl/usage (dae)

the json files that live there are output from our tooling, and
formatting them means an extra step each time we want to update them

also exclude .mypy_cache, which is output by scripts/mypy*

* minor ftl tweak: newline -> new line  (dae)
2021-11-23 10:27:32 +10:00

97 lines
2.4 KiB
Svelte

<!--
Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
-->
<script lang="ts">
import type { Writable } from "svelte/store";
import { updateAllState } from "../components/WithState.svelte";
import { saveSelection, restoreSelection } from "../domlib/location";
import { on, preventDefault } from "../lib/events";
import { registerShortcut } from "../lib/shortcuts";
export let nodes: Writable<DocumentFragment>;
export let resolve: (editable: HTMLElement) => void;
export let mirror: (
editable: HTMLElement,
params: { store: Writable<DocumentFragment> },
) => void;
export let inputManager: (editable: HTMLElement) => void;
let removeOnFocus: () => void;
let removeOnPointerdown: () => void;
function onBlur(): void {
const location = saveSelection(editable);
removeOnFocus = on(
editable,
"focus",
() => {
if (location) {
restoreSelection(editable, location);
}
},
{ once: true },
);
removeOnPointerdown = on(editable, "pointerdown", () => removeOnFocus?.(), {
once: true,
});
}
/* must execute before DOMMirror */
function saveLocation(editable: HTMLElement) {
const removeOnBlur = on(editable, "blur", onBlur);
return {
destroy() {
removeOnBlur();
removeOnFocus?.();
removeOnPointerdown?.();
},
};
}
let editable: HTMLElement;
$: if (editable) {
for (const keyCombination of [
"Control+B",
"Control+U",
"Control+I",
"Control+R",
]) {
registerShortcut(preventDefault, keyCombination, editable);
}
}
</script>
<anki-editable
contenteditable="true"
bind:this={editable}
use:resolve
use:saveLocation
use:mirror={{ store: nodes }}
use:inputManager
on:focus
on:blur
on:click={updateAllState}
on:keyup={updateAllState}
/>
<style lang="scss">
anki-editable {
display: block;
overflow-wrap: break-word;
overflow: auto;
padding: 6px;
&:focus {
outline: none;
}
}
/* editable-base.scss contains styling targeting user HTML */
</style>