mirror of
https://github.com/CharaChorder/DeviceManager.git
synced 2026-06-04 04:48:55 +00:00
100 lines
2.3 KiB
TypeScript
100 lines
2.3 KiB
TypeScript
import {
|
|
Decoration,
|
|
EditorView,
|
|
ViewPlugin,
|
|
ViewUpdate,
|
|
WidgetType,
|
|
} from "@codemirror/view";
|
|
import { mount, unmount } from "svelte";
|
|
import Action from "$lib/components/Action.svelte";
|
|
import type { Range } from "@codemirror/state";
|
|
import { parsedChordsField } from "./parsed-chords-plugin";
|
|
import { iterActions } from "./parse-meta";
|
|
import type { KeyInfo } from "$lib/serial/keymap-codes";
|
|
|
|
export class ActionWidget extends WidgetType {
|
|
component?: {};
|
|
|
|
constructor(readonly info: KeyInfo) {
|
|
super();
|
|
}
|
|
|
|
toDOM() {
|
|
if (this.component) {
|
|
unmount(this.component);
|
|
}
|
|
const element = document.createElement("span");
|
|
//element.style.paddingInline = "2px";
|
|
|
|
this.component = mount(Action, {
|
|
target: element,
|
|
props: {
|
|
action: this.info,
|
|
display: "keys",
|
|
inText: true,
|
|
withPopover: false,
|
|
},
|
|
});
|
|
return element;
|
|
}
|
|
|
|
override destroy() {
|
|
if (this.component) {
|
|
unmount(this.component);
|
|
}
|
|
}
|
|
|
|
override ignoreEvent() {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
function actionWidgets(view: EditorView) {
|
|
const widgets: Range<Decoration>[] = [];
|
|
for (const { from, to } of view.visibleRanges) {
|
|
for (const chord of view.state.field(parsedChordsField).chords) {
|
|
if (chord.range[1] < from || chord.range[0] > to) continue;
|
|
iterActions(chord, (action) => {
|
|
if (action.info && action.explicit) {
|
|
const deco = Decoration.replace({
|
|
widget: new ActionWidget(action.info),
|
|
});
|
|
widgets.push(deco.range(action.range[0], action.range[1]));
|
|
}
|
|
});
|
|
}
|
|
}
|
|
return Decoration.set(widgets);
|
|
}
|
|
|
|
export const actionPlugin = ViewPlugin.fromClass(
|
|
class {
|
|
decorations = Decoration.none;
|
|
|
|
constructor(view: EditorView) {
|
|
this.decorations = actionWidgets(view);
|
|
}
|
|
|
|
update(update: ViewUpdate) {
|
|
if (
|
|
update.docChanged ||
|
|
update.viewportChanged ||
|
|
update.selectionSet ||
|
|
update.startState.field(parsedChordsField) !=
|
|
update.state.field(parsedChordsField)
|
|
)
|
|
this.decorations = actionWidgets(update.view);
|
|
}
|
|
},
|
|
{
|
|
decorations(instance) {
|
|
return instance.decorations;
|
|
},
|
|
provide(plugin) {
|
|
return EditorView.atomicRanges.of(
|
|
(view) => view.plugin(plugin)?.decorations ?? Decoration.none,
|
|
);
|
|
},
|
|
},
|
|
);
|