mirror of
https://github.com/CharaChorder/DeviceManager.git
synced 2026-01-21 09:23:00 +00:00
improve cv2
This commit is contained in:
@@ -43,6 +43,7 @@
|
|||||||
"@codemirror/view": "^6.38.1",
|
"@codemirror/view": "^6.38.1",
|
||||||
"@fontsource-variable/material-symbols-rounded": "^5.2.17",
|
"@fontsource-variable/material-symbols-rounded": "^5.2.17",
|
||||||
"@fontsource-variable/noto-sans-mono": "^5.2.7",
|
"@fontsource-variable/noto-sans-mono": "^5.2.7",
|
||||||
|
"@lezer/common": "^1.4.0",
|
||||||
"@lezer/generator": "^1.8.0",
|
"@lezer/generator": "^1.8.0",
|
||||||
"@lezer/highlight": "^1.2.1",
|
"@lezer/highlight": "^1.2.1",
|
||||||
"@lezer/lr": "^1.4.5",
|
"@lezer/lr": "^1.4.5",
|
||||||
|
|||||||
25
pnpm-lock.yaml
generated
25
pnpm-lock.yaml
generated
@@ -35,6 +35,9 @@ importers:
|
|||||||
'@fontsource-variable/noto-sans-mono':
|
'@fontsource-variable/noto-sans-mono':
|
||||||
specifier: ^5.2.7
|
specifier: ^5.2.7
|
||||||
version: 5.2.7
|
version: 5.2.7
|
||||||
|
'@lezer/common':
|
||||||
|
specifier: ^1.4.0
|
||||||
|
version: 1.4.0
|
||||||
'@lezer/generator':
|
'@lezer/generator':
|
||||||
specifier: ^1.8.0
|
specifier: ^1.8.0
|
||||||
version: 1.8.0
|
version: 1.8.0
|
||||||
@@ -1084,8 +1087,8 @@ packages:
|
|||||||
'@keyv/serialize@1.1.0':
|
'@keyv/serialize@1.1.0':
|
||||||
resolution: {integrity: sha512-RlDgexML7Z63Q8BSaqhXdCYNBy/JQnqYIwxofUrNLGCblOMHp+xux2Q8nLMLlPpgHQPoU0Do8Z6btCpRBEqZ8g==}
|
resolution: {integrity: sha512-RlDgexML7Z63Q8BSaqhXdCYNBy/JQnqYIwxofUrNLGCblOMHp+xux2Q8nLMLlPpgHQPoU0Do8Z6btCpRBEqZ8g==}
|
||||||
|
|
||||||
'@lezer/common@1.2.1':
|
'@lezer/common@1.4.0':
|
||||||
resolution: {integrity: sha512-yemX0ZD2xS/73llMZIK6KplkjIjf2EvAHcinDi/TfJ9hS25G0388+ClHt6/3but0oOxinTcQHJLDXh6w1crzFQ==}
|
resolution: {integrity: sha512-DVeMRoGrgn/k45oQNu189BoW4SZwgZFzJ1+1TV5j2NJ/KFC83oa/enRqZSGshyeMk5cPWMhsKs9nx+8o0unwGg==}
|
||||||
|
|
||||||
'@lezer/generator@1.8.0':
|
'@lezer/generator@1.8.0':
|
||||||
resolution: {integrity: sha512-/SF4EDWowPqV1jOgoGSGTIFsE7Ezdr7ZYxyihl5eMKVO5tlnpIhFcDavgm1hHY5GEonoOAEnJ0CU0x+tvuAuUg==}
|
resolution: {integrity: sha512-/SF4EDWowPqV1jOgoGSGTIFsE7Ezdr7ZYxyihl5eMKVO5tlnpIhFcDavgm1hHY5GEonoOAEnJ0CU0x+tvuAuUg==}
|
||||||
@@ -5148,14 +5151,14 @@ snapshots:
|
|||||||
'@codemirror/language': 6.11.2
|
'@codemirror/language': 6.11.2
|
||||||
'@codemirror/state': 6.5.2
|
'@codemirror/state': 6.5.2
|
||||||
'@codemirror/view': 6.38.1
|
'@codemirror/view': 6.38.1
|
||||||
'@lezer/common': 1.2.1
|
'@lezer/common': 1.4.0
|
||||||
|
|
||||||
'@codemirror/commands@6.8.1':
|
'@codemirror/commands@6.8.1':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@codemirror/language': 6.11.2
|
'@codemirror/language': 6.11.2
|
||||||
'@codemirror/state': 6.5.2
|
'@codemirror/state': 6.5.2
|
||||||
'@codemirror/view': 6.38.1
|
'@codemirror/view': 6.38.1
|
||||||
'@lezer/common': 1.2.1
|
'@lezer/common': 1.4.0
|
||||||
|
|
||||||
'@codemirror/lang-javascript@6.2.4':
|
'@codemirror/lang-javascript@6.2.4':
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -5164,14 +5167,14 @@ snapshots:
|
|||||||
'@codemirror/lint': 6.8.1
|
'@codemirror/lint': 6.8.1
|
||||||
'@codemirror/state': 6.5.2
|
'@codemirror/state': 6.5.2
|
||||||
'@codemirror/view': 6.38.1
|
'@codemirror/view': 6.38.1
|
||||||
'@lezer/common': 1.2.1
|
'@lezer/common': 1.4.0
|
||||||
'@lezer/javascript': 1.4.17
|
'@lezer/javascript': 1.4.17
|
||||||
|
|
||||||
'@codemirror/language@6.11.2':
|
'@codemirror/language@6.11.2':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@codemirror/state': 6.5.2
|
'@codemirror/state': 6.5.2
|
||||||
'@codemirror/view': 6.38.1
|
'@codemirror/view': 6.38.1
|
||||||
'@lezer/common': 1.2.1
|
'@lezer/common': 1.4.0
|
||||||
'@lezer/highlight': 1.2.1
|
'@lezer/highlight': 1.2.1
|
||||||
'@lezer/lr': 1.4.5
|
'@lezer/lr': 1.4.5
|
||||||
style-mod: 4.1.2
|
style-mod: 4.1.2
|
||||||
@@ -5407,26 +5410,26 @@ snapshots:
|
|||||||
|
|
||||||
'@keyv/serialize@1.1.0': {}
|
'@keyv/serialize@1.1.0': {}
|
||||||
|
|
||||||
'@lezer/common@1.2.1': {}
|
'@lezer/common@1.4.0': {}
|
||||||
|
|
||||||
'@lezer/generator@1.8.0':
|
'@lezer/generator@1.8.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@lezer/common': 1.2.1
|
'@lezer/common': 1.4.0
|
||||||
'@lezer/lr': 1.4.5
|
'@lezer/lr': 1.4.5
|
||||||
|
|
||||||
'@lezer/highlight@1.2.1':
|
'@lezer/highlight@1.2.1':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@lezer/common': 1.2.1
|
'@lezer/common': 1.4.0
|
||||||
|
|
||||||
'@lezer/javascript@1.4.17':
|
'@lezer/javascript@1.4.17':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@lezer/common': 1.2.1
|
'@lezer/common': 1.4.0
|
||||||
'@lezer/highlight': 1.2.1
|
'@lezer/highlight': 1.2.1
|
||||||
'@lezer/lr': 1.4.5
|
'@lezer/lr': 1.4.5
|
||||||
|
|
||||||
'@lezer/lr@1.4.5':
|
'@lezer/lr@1.4.5':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@lezer/common': 1.2.1
|
'@lezer/common': 1.4.0
|
||||||
|
|
||||||
'@marijn/find-cluster-break@1.0.2': {}
|
'@marijn/find-cluster-break@1.0.2': {}
|
||||||
|
|
||||||
|
|||||||
54
src/lib/chord-editor/AutospaceSelector.svelte
Normal file
54
src/lib/chord-editor/AutospaceSelector.svelte
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { actionTooltip } from "$lib/title";
|
||||||
|
|
||||||
|
let {
|
||||||
|
onchange,
|
||||||
|
value,
|
||||||
|
variant,
|
||||||
|
}: {
|
||||||
|
value: boolean;
|
||||||
|
variant: "start" | "end";
|
||||||
|
onchange: (
|
||||||
|
event: Event & { currentTarget: EventTarget & HTMLInputElement },
|
||||||
|
) => void;
|
||||||
|
} = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#snippet tooltip()}
|
||||||
|
{#if value}
|
||||||
|
{#if variant === "start"}
|
||||||
|
<b>Remove</b> preceding space
|
||||||
|
{:else}
|
||||||
|
<b>Add</b> trailing space
|
||||||
|
{/if}
|
||||||
|
{:else if variant === "start"}
|
||||||
|
<b>Keep</b> preceding space
|
||||||
|
{:else}
|
||||||
|
<b>Add</b> trailing space
|
||||||
|
{/if}
|
||||||
|
{/snippet}
|
||||||
|
<label class="autospace" {@attach actionTooltip(tooltip)}
|
||||||
|
><span class="icon">space_bar</span><input
|
||||||
|
checked={!value}
|
||||||
|
{onchange}
|
||||||
|
type="checkbox"
|
||||||
|
/></label
|
||||||
|
>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
label.autospace {
|
||||||
|
display: inline-flex;
|
||||||
|
vertical-align: middle;
|
||||||
|
margin-inline: 8px;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: var(--md-sys-color-tertiary-container);
|
||||||
|
padding-inline: 0;
|
||||||
|
height: 1em;
|
||||||
|
color: var(--md-sys-color-on-tertiary-container);
|
||||||
|
font-size: 1.3em;
|
||||||
|
|
||||||
|
&:has(:checked) {
|
||||||
|
opacity: var(--auto-space-show, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -11,19 +11,12 @@ import { syntaxTree } from "@codemirror/language";
|
|||||||
import type { Range } from "@codemirror/state";
|
import type { Range } from "@codemirror/state";
|
||||||
|
|
||||||
export class ActionWidget extends WidgetType {
|
export class ActionWidget extends WidgetType {
|
||||||
component: {};
|
component?: {};
|
||||||
element: HTMLElement;
|
element?: HTMLElement;
|
||||||
|
|
||||||
constructor(readonly id: string | number) {
|
constructor(readonly id: string | number) {
|
||||||
super();
|
super();
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.element = document.createElement("span");
|
|
||||||
this.element.style.paddingInline = "2px";
|
|
||||||
|
|
||||||
this.component = mount(Action, {
|
|
||||||
target: this.element,
|
|
||||||
props: { action: id, display: "keys" },
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override eq(other: ActionWidget) {
|
override eq(other: ActionWidget) {
|
||||||
@@ -31,6 +24,15 @@ export class ActionWidget extends WidgetType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
toDOM() {
|
toDOM() {
|
||||||
|
if (!this.element) {
|
||||||
|
this.element = document.createElement("span");
|
||||||
|
this.element.style.paddingInline = "2px";
|
||||||
|
|
||||||
|
this.component = mount(Action, {
|
||||||
|
target: this.element,
|
||||||
|
props: { action: this.id, display: "keys", inText: true },
|
||||||
|
});
|
||||||
|
}
|
||||||
return this.element;
|
return this.element;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,7 +41,9 @@ export class ActionWidget extends WidgetType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override destroy() {
|
override destroy() {
|
||||||
unmount(this.component);
|
if (this.component) {
|
||||||
|
unmount(this.component);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,29 +7,71 @@ import {
|
|||||||
} from "@codemirror/view";
|
} from "@codemirror/view";
|
||||||
import { syntaxTree } from "@codemirror/language";
|
import { syntaxTree } from "@codemirror/language";
|
||||||
import type { Range } from "@codemirror/state";
|
import type { Range } from "@codemirror/state";
|
||||||
|
import { mount, unmount } from "svelte";
|
||||||
|
import Action from "../components/Action.svelte";
|
||||||
|
import type { SyntaxNodeRef } from "@lezer/common";
|
||||||
|
import classNames from "./concatenator-button.module.scss";
|
||||||
|
|
||||||
export class DelimWidget extends WidgetType {
|
export class DelimWidget extends WidgetType {
|
||||||
constructor() {
|
component?: {};
|
||||||
|
element?: HTMLElement;
|
||||||
|
|
||||||
|
constructor(readonly hasConcatenator: boolean) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
override eq(other: DelimWidget) {
|
override eq(other: DelimWidget) {
|
||||||
return true;
|
return this.hasConcatenator == other.hasConcatenator;
|
||||||
}
|
}
|
||||||
|
|
||||||
toDOM() {
|
toDOM() {
|
||||||
const element = document.createElement("span");
|
if (!this.element) {
|
||||||
element.innerHTML = " ⇛ ";
|
this.element = document.createElement("span");
|
||||||
element.style.scale = "1.8";
|
this.element.innerHTML =
|
||||||
element.style.opacity = "0.5";
|
" ⇛" + (this.hasConcatenator ? "" : " ");
|
||||||
return element;
|
this.element.style.scale = "1.8";
|
||||||
|
this.element.style.color =
|
||||||
|
"color-mix(in srgb, currentColor 50%, transparent)";
|
||||||
|
|
||||||
|
if (this.hasConcatenator) {
|
||||||
|
const button = document.createElement("button");
|
||||||
|
button.className = classNames["concatenator-button"]!;
|
||||||
|
this.component = mount(Action, {
|
||||||
|
target: button,
|
||||||
|
props: { action: 574, display: "keys", inText: true, ghost: true },
|
||||||
|
});
|
||||||
|
this.element.appendChild(button);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this.element;
|
||||||
}
|
}
|
||||||
|
|
||||||
override ignoreEvent() {
|
override ignoreEvent() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
override destroy() {}
|
override destroy() {
|
||||||
|
if (this.component) {
|
||||||
|
unmount(this.component);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getJoinNode(
|
||||||
|
view: EditorView,
|
||||||
|
phraseDelimNode: SyntaxNodeRef,
|
||||||
|
): SyntaxNodeRef | null | undefined {
|
||||||
|
const firstPhraseAction = phraseDelimNode.node.nextSibling
|
||||||
|
?.getChild("ActionString")
|
||||||
|
?.node.firstChild?.node.getChild("ExplicitAction");
|
||||||
|
const idNode = firstPhraseAction?.node.getChild("ActionId");
|
||||||
|
const actionId = idNode
|
||||||
|
? view.state.doc.sliceString(idNode.from, idNode.to)
|
||||||
|
: null;
|
||||||
|
const isJoinAction =
|
||||||
|
actionId === "JOIN" &&
|
||||||
|
!!firstPhraseAction!.node.getChild("ExplicitDelimEnd");
|
||||||
|
return isJoinAction ? firstPhraseAction : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function actionWidgets(view: EditorView) {
|
function actionWidgets(view: EditorView) {
|
||||||
@@ -40,8 +82,10 @@ function actionWidgets(view: EditorView) {
|
|||||||
to,
|
to,
|
||||||
enter: (node) => {
|
enter: (node) => {
|
||||||
if (node.name !== "PhraseDelim") return;
|
if (node.name !== "PhraseDelim") return;
|
||||||
|
const joinNode = getJoinNode(view, node);
|
||||||
|
|
||||||
let deco = Decoration.replace({
|
let deco = Decoration.replace({
|
||||||
widget: new DelimWidget(),
|
widget: new DelimWidget(!joinNode),
|
||||||
});
|
});
|
||||||
widgets.push(deco.range(node.from, node.to));
|
widgets.push(deco.range(node.from, node.to));
|
||||||
},
|
},
|
||||||
@@ -76,5 +120,38 @@ export const delimPlugin = ViewPlugin.fromClass(
|
|||||||
(view) => view.plugin(plugin)?.decorations ?? Decoration.none,
|
(view) => view.plugin(plugin)?.decorations ?? Decoration.none,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
eventHandlers: {
|
||||||
|
click: (event, view) => {
|
||||||
|
if (!(event.target instanceof HTMLElement)) return;
|
||||||
|
if (
|
||||||
|
!(
|
||||||
|
event.target instanceof HTMLButtonElement ||
|
||||||
|
(event.target as HTMLElement).parentElement instanceof
|
||||||
|
HTMLButtonElement
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const chordNode = syntaxTree(view.state).resolve(
|
||||||
|
view.posAtDOM(event.target),
|
||||||
|
);
|
||||||
|
const delimNode = (
|
||||||
|
chordNode.name === "ActionString"
|
||||||
|
? chordNode.parent?.parent
|
||||||
|
: chordNode
|
||||||
|
)?.getChild("PhraseDelim");
|
||||||
|
if (!delimNode) return;
|
||||||
|
const joinNode = getJoinNode(view, delimNode);
|
||||||
|
if (!event.target.checked && !joinNode) {
|
||||||
|
view.dispatch({
|
||||||
|
changes: {
|
||||||
|
from: delimNode.to,
|
||||||
|
insert: "<JOIN>",
|
||||||
|
},
|
||||||
|
selection: { anchor: delimNode.to + "<JOIN>".length },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
13
src/lib/chord-editor/concatenator-button.module.scss
Normal file
13
src/lib/chord-editor/concatenator-button.module.scss
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
.concatenator-button {
|
||||||
|
display: inline;
|
||||||
|
opacity: calc(var(--auto-space-show, 0) * 0.7);
|
||||||
|
margin: 0;
|
||||||
|
padding: 4px;
|
||||||
|
height: auto;
|
||||||
|
|
||||||
|
> :global(kbd) {
|
||||||
|
outline: 1px dashed var(--md-sys-color-outline);
|
||||||
|
outline-offset: -1px;
|
||||||
|
background: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,16 +2,17 @@
|
|||||||
import { KEYMAP_CODES, KEYMAP_IDS } from "$lib/serial/keymap-codes";
|
import { KEYMAP_CODES, KEYMAP_IDS } from "$lib/serial/keymap-codes";
|
||||||
import type { KeyInfo } from "$lib/serial/keymap-codes";
|
import type { KeyInfo } from "$lib/serial/keymap-codes";
|
||||||
import { osLayout } from "$lib/os-layout";
|
import { osLayout } from "$lib/os-layout";
|
||||||
import { tooltip } from "$lib/hover-popover";
|
|
||||||
import { isVerbose } from "./verbose-action";
|
import { isVerbose } from "./verbose-action";
|
||||||
import { actionTooltip } from "$lib/title";
|
import { actionTooltip } from "$lib/title";
|
||||||
|
|
||||||
let {
|
let {
|
||||||
action,
|
action,
|
||||||
display,
|
display,
|
||||||
|
inText = false,
|
||||||
}: {
|
}: {
|
||||||
action: string | number | KeyInfo;
|
action: string | number | KeyInfo;
|
||||||
display: "inline-text" | "inline-keys" | "keys" | "verbose";
|
display: "inline-keys" | "keys" | "verbose";
|
||||||
|
inText?: boolean;
|
||||||
} = $props();
|
} = $props();
|
||||||
|
|
||||||
let retrievedInfo = $derived(
|
let retrievedInfo = $derived(
|
||||||
@@ -69,6 +70,7 @@
|
|||||||
{/snippet}
|
{/snippet}
|
||||||
{#snippet kbdSnippet(withPopover = true)}
|
{#snippet kbdSnippet(withPopover = true)}
|
||||||
<kbd
|
<kbd
|
||||||
|
class:in-text={inText}
|
||||||
class:icon={!!info.icon}
|
class:icon={!!info.icon}
|
||||||
class:left={info.variant === "left"}
|
class:left={info.variant === "left"}
|
||||||
class:right={info.variant === "right"}
|
class:right={info.variant === "right"}
|
||||||
@@ -83,7 +85,7 @@
|
|||||||
{#if !info.icon && dynamicMapping?.length === 1}
|
{#if !info.icon && dynamicMapping?.length === 1}
|
||||||
<span
|
<span
|
||||||
{@attach hasPopover ? actionTooltip(popover) : null}
|
{@attach hasPopover ? actionTooltip(popover) : null}
|
||||||
class:in-text={display === "inline-text"}
|
class:in-text={inText}
|
||||||
class:error={info.code > 1023}
|
class:error={info.code > 1023}
|
||||||
class:warn={!retrievedInfo}
|
class:warn={!retrievedInfo}
|
||||||
class:left={info.variant === "left"}
|
class:left={info.variant === "left"}
|
||||||
@@ -92,7 +94,7 @@
|
|||||||
{:else if !info.icon && info.id?.length === 1}
|
{:else if !info.icon && info.id?.length === 1}
|
||||||
<span
|
<span
|
||||||
{@attach hasPopover ? actionTooltip(popover) : null}
|
{@attach hasPopover ? actionTooltip(popover) : null}
|
||||||
class:in-text={display === "inline-text"}
|
class:in-text={inText}
|
||||||
class:error={info.code > 1023}
|
class:error={info.code > 1023}
|
||||||
class:warn={!retrievedInfo}
|
class:warn={!retrievedInfo}
|
||||||
class:left={info.variant === "left"}
|
class:left={info.variant === "left"}
|
||||||
@@ -101,7 +103,7 @@
|
|||||||
{:else}
|
{:else}
|
||||||
<kbd
|
<kbd
|
||||||
class="inline-kbd"
|
class="inline-kbd"
|
||||||
class:in-text={display === "inline-text"}
|
class:in-text={inText}
|
||||||
class:left={info.variant === "left"}
|
class:left={info.variant === "left"}
|
||||||
class:right={info.variant === "right"}
|
class:right={info.variant === "right"}
|
||||||
class:icon={!!info.icon}
|
class:icon={!!info.icon}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
import { action, actionTooltip } from "$lib/title";
|
import { action, actionTooltip } from "$lib/title";
|
||||||
import semverGte from "semver/functions/gte";
|
import semverGte from "semver/functions/gte";
|
||||||
import Action from "$lib/components/Action.svelte";
|
import Action from "$lib/components/Action.svelte";
|
||||||
|
import AutospaceSelector from "$lib/chord-editor/AutospaceSelector.svelte";
|
||||||
|
|
||||||
let { chord }: { chord: ChordInfo } = $props();
|
let { chord }: { chord: ChordInfo } = $props();
|
||||||
|
|
||||||
@@ -208,36 +209,27 @@
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{#if supportsAutospace}
|
{#if supportsAutospace}
|
||||||
{#snippet tooltip()}
|
<AutospaceSelector
|
||||||
{#if chord.phrase[0] === JOIN_ACTION}
|
variant="start"
|
||||||
<b>Remove</b> preceding space
|
value={chord.phrase[0] === JOIN_ACTION}
|
||||||
{:else}
|
onchange={async (event) => {
|
||||||
<b>Keep</b> preceding space
|
const autospace = hasAutospace;
|
||||||
{/if}
|
if ((event.target as HTMLInputElement).checked) {
|
||||||
{/snippet}
|
if (chord.phrase[0] === JOIN_ACTION) {
|
||||||
<label class="auto-space-edit" {@attach actionTooltip(tooltip)}
|
deleteAction(0, 1);
|
||||||
><span class="icon">space_bar</span><input
|
await tick();
|
||||||
checked={chord.phrase[0] !== JOIN_ACTION}
|
moveCursor(cursorPosition - 1, true);
|
||||||
onchange={async (event) => {
|
|
||||||
const autospace = hasAutospace;
|
|
||||||
if ((event.target as HTMLInputElement).checked) {
|
|
||||||
if (chord.phrase[0] === JOIN_ACTION) {
|
|
||||||
deleteAction(0, 1);
|
|
||||||
await tick();
|
|
||||||
moveCursor(cursorPosition - 1, true);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (chord.phrase[0] !== JOIN_ACTION) {
|
|
||||||
insertAction(0, JOIN_ACTION);
|
|
||||||
moveCursor(cursorPosition + 1, true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
await tick();
|
} else {
|
||||||
resolveAutospace(autospace);
|
if (chord.phrase[0] !== JOIN_ACTION) {
|
||||||
}}
|
insertAction(0, JOIN_ACTION);
|
||||||
type="checkbox"
|
moveCursor(cursorPosition + 1, true);
|
||||||
/></label
|
}
|
||||||
>
|
}
|
||||||
|
await tick();
|
||||||
|
resolveAutospace(autospace);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
<div
|
<div
|
||||||
onkeydown={keypress}
|
onkeydown={keypress}
|
||||||
@@ -268,21 +260,12 @@
|
|||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
{#if supportsAutospace}
|
{#if supportsAutospace}
|
||||||
{#snippet tooltip()}
|
<AutospaceSelector
|
||||||
{#if hasAutospace}
|
variant="end"
|
||||||
<b>Add</b> trailing space
|
value={!hasAutospace}
|
||||||
{:else}
|
onchange={(event) =>
|
||||||
<b>Don't add</b> trailing space
|
resolveAutospace((event.target as HTMLInputElement).checked)}
|
||||||
{/if}
|
/>
|
||||||
{/snippet}
|
|
||||||
<label class="auto-space-edit" {@attach actionTooltip(tooltip)}
|
|
||||||
><span class="icon">space_bar</span><input
|
|
||||||
checked={hasAutospace}
|
|
||||||
onchange={(event) =>
|
|
||||||
resolveAutospace((event.target as HTMLInputElement).checked)}
|
|
||||||
type="checkbox"
|
|
||||||
/></label
|
|
||||||
>
|
|
||||||
{/if}
|
{/if}
|
||||||
<sup>•</sup>
|
<sup>•</sup>
|
||||||
</div>
|
</div>
|
||||||
@@ -330,24 +313,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.auto-space-edit {
|
|
||||||
margin-inline: 8px;
|
|
||||||
border-radius: 4px;
|
|
||||||
background: var(--md-sys-color-tertiary-container);
|
|
||||||
padding-inline: 0;
|
|
||||||
height: 1em;
|
|
||||||
color: var(--md-sys-color-on-tertiary-container);
|
|
||||||
font-size: 1.3em;
|
|
||||||
|
|
||||||
&:has(:checked) {
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.wrapper:hover .auto-space-edit {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wrapper {
|
.wrapper {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
||||||
@@ -380,8 +345,12 @@
|
|||||||
transition-duration: 250ms;
|
transition-duration: 250ms;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover::before {
|
&:hover {
|
||||||
opacity: 0.3;
|
--auto-space-show: 1;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
opacity: 0.3;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&:has(> :focus-within)::after {
|
&:has(> :focus-within)::after {
|
||||||
|
|||||||
@@ -26,15 +26,16 @@
|
|||||||
const showEdits = persistentWritable("chord-editor-show-edits", true);
|
const showEdits = persistentWritable("chord-editor-show-edits", true);
|
||||||
let originalDoc = $derived(
|
let originalDoc = $derived(
|
||||||
$chords
|
$chords
|
||||||
.map(
|
.map((chord) => {
|
||||||
(chord) =>
|
return (
|
||||||
chord.actions
|
chord.actions
|
||||||
.filter((it) => it !== 0)
|
.filter((it) => it !== 0)
|
||||||
.map((it) => actionToValue(it))
|
.map((it) => actionToValue(it))
|
||||||
.join("") +
|
.join("") +
|
||||||
"=>" +
|
"=>" +
|
||||||
chord.phrase.map((it) => actionToValue(it)).join(""),
|
chord.phrase.map((it) => actionToValue(it)).join("")
|
||||||
)
|
);
|
||||||
|
})
|
||||||
.join("\n"),
|
.join("\n"),
|
||||||
);
|
);
|
||||||
let editor: HTMLDivElement | undefined = $state(undefined);
|
let editor: HTMLDivElement | undefined = $state(undefined);
|
||||||
@@ -175,6 +176,11 @@
|
|||||||
) !important;
|
) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:global(.cm-activeLine),
|
||||||
|
:global(.cm-line:hover) {
|
||||||
|
--auto-space-show: 1;
|
||||||
|
}
|
||||||
|
|
||||||
:global(.cm-activeLine) {
|
:global(.cm-activeLine) {
|
||||||
border-bottom: 1px solid var(--md-sys-color-surface-variant);
|
border-bottom: 1px solid var(--md-sys-color-surface-variant);
|
||||||
/*background-color: color-mix(
|
/*background-color: color-mix(
|
||||||
|
|||||||
Reference in New Issue
Block a user