fix: can't select empty chord outputs

update dependencies
use new title popover
This commit is contained in:
2025-07-29 20:18:13 +02:00
parent 977bdf3043
commit 048dee0a6d
7 changed files with 832 additions and 660 deletions

View File

@@ -36,61 +36,61 @@
"devDependencies": {
"@codemirror/autocomplete": "^6.18.6",
"@codemirror/commands": "^6.8.1",
"@codemirror/lang-javascript": "^6.2.3",
"@codemirror/language": "^6.11.0",
"@codemirror/lang-javascript": "^6.2.4",
"@codemirror/language": "^6.11.2",
"@codemirror/state": "^6.5.2",
"@codemirror/view": "^6.36.5",
"@fontsource-variable/material-symbols-rounded": "^5.2.8",
"@fontsource-variable/noto-sans-mono": "^5.2.6",
"@codemirror/view": "^6.38.1",
"@fontsource-variable/material-symbols-rounded": "^5.2.17",
"@fontsource-variable/noto-sans-mono": "^5.2.7",
"@lezer/highlight": "^1.2.1",
"@material/material-color-utilities": "^0.3.0",
"@melt-ui/pp": "^0.3.2",
"@melt-ui/svelte": "^0.86.6",
"@modyfi/vite-plugin-yaml": "^1.1.1",
"@sveltejs/adapter-static": "^3.0.8",
"@sveltejs/kit": "^2.20.2",
"@sveltejs/vite-plugin-svelte": "^5.0.3",
"@sveltejs/kit": "^2.26.1",
"@sveltejs/vite-plugin-svelte": "^6.1.0",
"@tauri-apps/api": "^1.6.0",
"@tauri-apps/cli": "^1.6.0",
"@types/dom-view-transitions": "^1.0.6",
"@types/semver": "^7.7.0",
"@types/w3c-web-serial": "^1.0.8",
"@types/w3c-web-usb": "^1.0.10",
"@types/wicg-file-system-access": "^2023.10.5",
"@types/wicg-file-system-access": "^2023.10.6",
"@vite-pwa/sveltekit": "^1.0.0",
"autoprefixer": "^10.4.21",
"codemirror": "^6.0.1",
"cypress": "^14.2.1",
"codemirror": "^6.0.2",
"cypress": "^14.5.3",
"d3": "^7.9.0",
"esptool-js": "^0.5.4",
"flexsearch": "^0.8.147",
"esptool-js": "^0.5.6",
"flexsearch": "^0.8.205",
"fontkit": "^2.0.4",
"glob": "^11.0.1",
"jsdom": "^26.0.0",
"matrix-js-sdk": "^37.2.0",
"glob": "^11.0.3",
"jsdom": "^26.1.0",
"matrix-js-sdk": "^37.12.0",
"npm-run-all": "^4.1.5",
"prettier": "^3.5.3",
"prettier-plugin-svelte": "^3.3.3",
"prettier": "^3.6.2",
"prettier-plugin-svelte": "^3.4.0",
"rxjs": "^7.8.2",
"sass": "^1.86.0",
"sass": "^1.89.2",
"semver": "^7.7.2",
"socket.io-client": "^4.8.1",
"stylelint": "^16.17.0",
"stylelint": "^16.23.0",
"stylelint-config-clean-order": "^7.0.0",
"stylelint-config-html": "^1.1.0",
"stylelint-config-prettier-scss": "^1.0.0",
"stylelint-config-recommended-scss": "^14.1.0",
"stylelint-config-standard-scss": "^14.0.0",
"svelte": "5.25.3",
"svelte-check": "^4.1.5",
"stylelint-config-recommended-scss": "^15.0.1",
"stylelint-config-standard-scss": "^15.0.1",
"svelte": "5.37.1",
"svelte-check": "^4.3.0",
"svelte-preprocess": "^6.0.3",
"tippy.js": "^6.3.7",
"typesafe-i18n": "^5.26.2",
"typescript": "^5.8.2",
"vite": "^6.2.4",
"typescript": "^5.8.3",
"vite": "^7.0.6",
"vite-plugin-mkcert": "^1.17.8",
"vite-plugin-pwa": "^1.0.0",
"vitest": "^3.1.1",
"vite-plugin-pwa": "^1.0.2",
"vitest": "^3.2.4",
"web-serial-polyfill": "^1.0.15",
"workbox-window": "^7.3.0"
},

1323
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +1,8 @@
<script lang="ts">
import { KEYMAP_CODES } from "$lib/serial/keymap-codes";
import type { KeyInfo } from "$lib/serial/keymap-codes";
import { action as title } from "$lib/title";
import { osLayout } from "$lib/os-layout";
import { tooltip } from "$lib/hover-popover";
let {
action,
@@ -16,42 +16,49 @@
);
let dynamicMapping = $derived(info.keyCode && $osLayout.get(info.keyCode));
let tooltip = $derived(
`&lt;${info.id ?? `0x${info.code.toString(16)}`}&gt; ` +
(info.title ?? "") +
(info.variant === "left"
? " (left)"
: info.variant === "right"
? " (right)"
: ""),
);
let popover: HTMLElement | undefined = $state(undefined);
</script>
{#snippet popoverSnippet()}
<div bind:this={popover} popover="hint">
&lt;{info.id ?? `0x${info.code.toString(16)}`}&gt;
{#if info.title}
{info.title}
{/if}
{#if info.variant === "left"}
(Left)
{:else if info.variant === "right"}
(Right)
{/if}
</div>
{/snippet}
{#if display === "keys"}
<kbd
class:icon={!!info.icon}
class:left={info.variant === "left"}
class:right={info.variant === "right"}
use:title={{ title: tooltip }}
{@attach tooltip(popover)}
>
{dynamicMapping ??
info.icon ??
info.display ??
info.id ??
`0x${info.code.toString(16)}`}
{@render popoverSnippet()}
</kbd>
{:else if display === "inline-keys"}
{#if !info.icon && dynamicMapping?.length === 1}
<span
use:title={{ title: tooltip }}
{@attach tooltip(popover)}
class:left={info.variant === "left"}
class:right={info.variant === "right"}>{dynamicMapping}</span
class:right={info.variant === "right"}>{dynamicMapping}{@render popoverSnippet()}</span
>
{:else if !info.icon && info.id?.length === 1}
<span
use:title={{ title: tooltip }}
{@attach tooltip(popover)}
class:left={info.variant === "left"}
class:right={info.variant === "right"}>{info.id}</span
class:right={info.variant === "right"}>{info.id}{@render popoverSnippet()}</span
>
{:else}
<kbd
@@ -59,13 +66,13 @@
class:left={info.variant === "left"}
class:right={info.variant === "right"}
class:icon={!!info.icon}
use:title={{ title: tooltip }}
{@attach tooltip(popover)}
>
{dynamicMapping ??
info.icon ??
info.display ??
info.id ??
`0x${info.code.toString(16)}`}</kbd
`0x${info.code.toString(16)}`}{@render popoverSnippet()}</kbd
>
{/if}
{/if}

39
src/lib/hover-popover.ts Normal file
View File

@@ -0,0 +1,39 @@
import type { Attachment } from "svelte/attachments";
export const hotkeys = new Map<string, HTMLElement>();
export function tooltip(
target: HTMLElement | undefined,
shortcut?: string,
): Attachment<HTMLElement> {
return (node: HTMLElement) => {
function show() {
if (!target) return;
target.showPopover({ source: node });
}
function hide() {
if (!target) return;
target.hidePopover();
}
node.addEventListener("mouseenter", show);
node.addEventListener("focus", show);
node.addEventListener("mouseout", hide);
node.addEventListener("blur", hide);
if (shortcut && node instanceof HTMLElement) {
hotkeys.set(shortcut, node);
}
return () => {
node.removeEventListener("mouseenter", show);
node.removeEventListener("focus", show);
node.removeEventListener("mouseout", hide);
node.removeEventListener("blur", hide);
if (shortcut && node instanceof HTMLElement) {
hotkeys.delete(shortcut);
}
};
};
}

View File

@@ -4,13 +4,15 @@ $translate: translateY(8px);
[popover] {
position: absolute;
inset: unset;
transform: $translate;
margin: 0;
padding: 8px;
border: 1px solid var(--md-sys-color-outline);
border-radius: 8px;
font-family: "Noto Sans Mono", monospace;
font-size: initial;
font-weight: initial;
color: var(--md-sys-color-on-surface);
opacity: 0;
@@ -18,12 +20,14 @@ $translate: translateY(8px);
transition:
transform $animation-duration ease,
opacity $animation-duration ease,
opacity $animation-duration linear,
overlay $animation-duration allow-discrete,
display $animation-duration allow-discrete;
position-area: bottom span-right;
position-area: bottom span-all;
position-try-fallbacks:
top span-all,
bottom span-right,
top span-right,
bottom span-left,
top span-left;
@@ -43,9 +47,21 @@ $translate: translateY(8px);
}
}
[popover="auto"] {
transform: $translate;
}
[popover="hint"] {
margin-top: 0.5rem;
font-size: 0.9rem;
}
@starting-style {
[popover]:popover-open {
transform: $translate;
opacity: 0;
}
[popover="auto"] {
transform: $translate;
}
}

View File

@@ -5,6 +5,9 @@ import Tooltip from "$lib/components/Tooltip.svelte";
export const hotkeys = new Map<string, HTMLElement>();
/**
* @deprecated Use `tooltip` instead.
*/
export const action: Action<Element, { title?: string; shortcut?: string }> = (
node: Element,
{ title, shortcut },

View File

@@ -183,7 +183,13 @@
);
</script>
<div class="wrapper" class:edited={!chord.deleted && chord.phraseChanged}>
<div
class="wrapper"
class:edited={!chord.deleted && chord.phraseChanged}
onclick={() => {
box.focus();
}}
>
{#if supportsAutospace}
<label
class="auto-space-edit"