mirror of
https://github.com/CharaChorder/DeviceManager.git
synced 2026-01-22 09:52:50 +00:00
feat: settings wip
This commit is contained in:
89
src/lib/components/layout/Layout.svelte
Normal file
89
src/lib/components/layout/Layout.svelte
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
<script>
|
||||||
|
import {serialPort} from "$lib/serial/connection"
|
||||||
|
import LayoutCC1 from "$lib/components/layout/LayoutCC1.svelte"
|
||||||
|
|
||||||
|
$: device = $serialPort?.device ?? "ONE"
|
||||||
|
let activeLayer = 0
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<select bind:value={device}>
|
||||||
|
<option value="ONE">CC1</option>
|
||||||
|
<option value="LITE">Lite</option>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<fieldset>
|
||||||
|
{#each [["Numeric Layer", "123", 1], ["Primary Layer", "abc", 0], ["Function Layer", "function", 2]] as [title, icon, value]}
|
||||||
|
<button
|
||||||
|
{title}
|
||||||
|
class="icon"
|
||||||
|
on:click={() => (activeLayer = value)}
|
||||||
|
class:active={activeLayer === value}
|
||||||
|
>
|
||||||
|
{icon}
|
||||||
|
</button>
|
||||||
|
{/each}
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
{#if device === "ONE"}
|
||||||
|
<LayoutCC1 bind:activeLayer />
|
||||||
|
{:else}
|
||||||
|
<p>Unsupported device ({$serialPort?.device})</p>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
fieldset {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
margin-block-end: -36px;
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
button.icon {
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
z-index: 1;
|
||||||
|
|
||||||
|
font-size: 24px;
|
||||||
|
color: var(--md-sys-color-on-surface-variant);
|
||||||
|
|
||||||
|
background: var(--md-sys-color-surface-variant);
|
||||||
|
border: none;
|
||||||
|
|
||||||
|
transition: all 250ms ease;
|
||||||
|
|
||||||
|
&:nth-child(2) {
|
||||||
|
z-index: 2;
|
||||||
|
|
||||||
|
aspect-ratio: 1;
|
||||||
|
|
||||||
|
font-size: 32px;
|
||||||
|
|
||||||
|
border-radius: 50%;
|
||||||
|
outline: 8px solid var(--md-sys-color-background);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:first-child {
|
||||||
|
padding-inline-end: 16px;
|
||||||
|
border-radius: 16px 0 0 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
padding-inline-start: 16px;
|
||||||
|
border-radius: 0 16px 16px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
font-weight: 900;
|
||||||
|
color: var(--md-sys-color-on-tertiary);
|
||||||
|
background: var(--md-sys-color-tertiary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,24 +1,10 @@
|
|||||||
<script>
|
<script>
|
||||||
import RingInput from "$lib/components/layout/RingInput.svelte"
|
import RingInput from "$lib/components/layout/RingInput.svelte"
|
||||||
|
|
||||||
let activeLayer = 0
|
export let activeLayer = 0
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div>
|
<div class="col layout" style="gap: 0">
|
||||||
<fieldset>
|
|
||||||
{#each [["Numeric Layer", "123", 1], ["Primary Layer", "abc", 0], ["Function Layer", "function", 2]] as [title, icon, value]}
|
|
||||||
<button
|
|
||||||
{title}
|
|
||||||
class="icon"
|
|
||||||
on:click={() => (activeLayer = value)}
|
|
||||||
class:active={activeLayer === value}
|
|
||||||
>
|
|
||||||
{icon}
|
|
||||||
</button>
|
|
||||||
{/each}
|
|
||||||
</fieldset>
|
|
||||||
|
|
||||||
<div class="col layout" style="gap: 0">
|
|
||||||
<div class="row" style="gap: 156px">
|
<div class="row" style="gap: 156px">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<RingInput {activeLayer} keys={{d: 30, e: 31, n: 32, w: 33, s: 34}} type="tertiary" />
|
<RingInput {activeLayer} keys={{d: 30, e: 31, n: 32, w: 33, s: 34}} type="tertiary" />
|
||||||
@@ -58,64 +44,9 @@
|
|||||||
<RingInput {activeLayer} keys={{d: 0, e: 1, n: 2, w: 3, s: 4}} type="secondary" />
|
<RingInput {activeLayer} keys={{d: 0, e: 1, n: 2, w: 3, s: 4}} type="secondary" />
|
||||||
<RingInput {activeLayer} keys={{d: 45, w: 46, n: 47, e: 48, s: 49}} type="secondary" />
|
<RingInput {activeLayer} keys={{d: 45, w: 46, n: 47, e: 48, s: 49}} type="secondary" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
fieldset {
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
margin-block-end: -36px;
|
|
||||||
padding: 0;
|
|
||||||
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
button.icon {
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
z-index: 1;
|
|
||||||
|
|
||||||
font-size: 24px;
|
|
||||||
color: var(--md-sys-color-on-surface-variant);
|
|
||||||
|
|
||||||
background: var(--md-sys-color-surface-variant);
|
|
||||||
border: none;
|
|
||||||
|
|
||||||
transition: all 250ms ease;
|
|
||||||
|
|
||||||
&:nth-child(2) {
|
|
||||||
z-index: 2;
|
|
||||||
|
|
||||||
aspect-ratio: 1;
|
|
||||||
|
|
||||||
font-size: 32px;
|
|
||||||
|
|
||||||
border-radius: 50%;
|
|
||||||
outline: 8px solid var(--md-sys-color-background);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:first-child {
|
|
||||||
padding-inline-end: 16px;
|
|
||||||
border-radius: 16px 0 0 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:last-child {
|
|
||||||
padding-inline-start: 16px;
|
|
||||||
border-radius: 0 16px 16px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.active {
|
|
||||||
font-weight: 900;
|
|
||||||
color: var(--md-sys-color-on-tertiary);
|
|
||||||
background: var(--md-sys-color-tertiary);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.row,
|
.row,
|
||||||
.col {
|
.col {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import {LineBreakTransformer} from "$lib/serial/line-break-transformer"
|
|||||||
import {serialLog} from "$lib/serial/connection"
|
import {serialLog} from "$lib/serial/connection"
|
||||||
import type {Chord} from "$lib/serial/chord"
|
import type {Chord} from "$lib/serial/chord"
|
||||||
import {parseChordActions, parsePhrase, stringifyChordActions, stringifyPhrase} from "$lib/serial/chord"
|
import {parseChordActions, parsePhrase, stringifyChordActions, stringifyPhrase} from "$lib/serial/chord"
|
||||||
|
import {dev} from "$app/environment"
|
||||||
|
|
||||||
export const VENDOR_ID = 0x239a
|
export const VENDOR_ID = 0x239a
|
||||||
|
|
||||||
@@ -24,8 +25,10 @@ export class CharaDevice {
|
|||||||
|
|
||||||
private lock?: Promise<true>
|
private lock?: Promise<true>
|
||||||
|
|
||||||
version!: string
|
version!: [number, number, number]
|
||||||
deviceId!: string
|
company!: "CHARACHORDER"
|
||||||
|
device!: "ONE" | "LITE"
|
||||||
|
chipset!: "M0" | "S2"
|
||||||
|
|
||||||
constructor(private readonly baudRate = 115200) {}
|
constructor(private readonly baudRate = 115200) {}
|
||||||
|
|
||||||
@@ -58,8 +61,12 @@ export class CharaDevice {
|
|||||||
})
|
})
|
||||||
.getReader()
|
.getReader()
|
||||||
|
|
||||||
this.version = await this.send("VERSION").then(it => it[0])
|
const [version] = await this.send("VERSION")
|
||||||
this.deviceId = await this.send("ID").then(it => it[0])
|
this.version = version.split(".").map(Number) as [number, number, number]
|
||||||
|
const [company, device, chipset] = await this.send("ID")
|
||||||
|
this.company = company as "CHARACHORDER"
|
||||||
|
this.device = device as "ONE" | "LITE"
|
||||||
|
this.chipset = chipset as "M0" | "S2"
|
||||||
}
|
}
|
||||||
|
|
||||||
private async internalRead() {
|
private async internalRead() {
|
||||||
|
|||||||
@@ -1,41 +0,0 @@
|
|||||||
export interface DeviceSettings {
|
|
||||||
enableSerialLog: boolean
|
|
||||||
enableSerialRaw: boolean
|
|
||||||
enableSerialChord: boolean
|
|
||||||
enableSerialKeyboard: boolean
|
|
||||||
enableSerialMouse: boolean
|
|
||||||
enableSerialDebug: boolean
|
|
||||||
enableSerialHeader: boolean
|
|
||||||
enableHidKeyboard: boolean
|
|
||||||
pressThreshold: number
|
|
||||||
releaseThreshold: number
|
|
||||||
enableHidMouse: number
|
|
||||||
scrollDelay: number
|
|
||||||
enableSpurring: boolean
|
|
||||||
spurKillerToggle: number
|
|
||||||
spurKiller: number
|
|
||||||
enableChording: boolean
|
|
||||||
charKillerToggle: number
|
|
||||||
charCounterKiller: number
|
|
||||||
}
|
|
||||||
|
|
||||||
export const SETTING_IDS: Record<keyof DeviceSettings, number> = {
|
|
||||||
enableSerialLog: 0x01,
|
|
||||||
enableSerialRaw: 0x02,
|
|
||||||
enableSerialChord: 0x03,
|
|
||||||
enableSerialKeyboard: 0x04,
|
|
||||||
enableSerialMouse: 0x05,
|
|
||||||
enableSerialDebug: 0x06,
|
|
||||||
enableSerialHeader: 0x07,
|
|
||||||
enableHidKeyboard: 0x0a,
|
|
||||||
pressThreshold: 0x0b,
|
|
||||||
releaseThreshold: 0x0c,
|
|
||||||
enableHidMouse: 0x14,
|
|
||||||
scrollDelay: 0x15,
|
|
||||||
enableSpurring: 0x1e,
|
|
||||||
spurKillerToggle: 0x1f,
|
|
||||||
spurKiller: 0x20,
|
|
||||||
enableChording: 0x28,
|
|
||||||
charKillerToggle: 0x29,
|
|
||||||
charCounterKiller: 0x2a,
|
|
||||||
}
|
|
||||||
@@ -4,6 +4,7 @@ $height: 1.5em;
|
|||||||
|
|
||||||
label:has(input[type="checkbox"]) {
|
label:has(input[type="checkbox"]) {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
user-select: none;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: $padding;
|
gap: $padding;
|
||||||
@@ -12,7 +13,7 @@ label:has(input[type="checkbox"]) {
|
|||||||
|
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
|
|
||||||
input {
|
input[type="checkbox"] {
|
||||||
$width: calc($height * (5 / 3));
|
$width: calc($height * (5 / 3));
|
||||||
$diameter: calc($height - ((2 * $padding) + (2 * $border)));
|
$diameter: calc($height - ((2 * $padding) + (2 * $border)));
|
||||||
$radius: calc($diameter / 2);
|
$radius: calc($diameter / 2);
|
||||||
|
|||||||
@@ -65,6 +65,8 @@
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|
||||||
|
width: min-content;
|
||||||
}
|
}
|
||||||
|
|
||||||
.disclaimer {
|
.disclaimer {
|
||||||
@@ -91,6 +93,7 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|
||||||
|
width: max-content;
|
||||||
height: 48px;
|
height: 48px;
|
||||||
padding-block: 8px;
|
padding-block: 8px;
|
||||||
padding-inline: 16px;
|
padding-inline: 16px;
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import {initSerial, serialPort} from "$lib/serial/connection"
|
import {initSerial, serialPort} from "$lib/serial/connection"
|
||||||
import {browser} from "$app/environment"
|
import {browser} from "$app/environment"
|
||||||
import {slide, fade, fly} from "svelte/transition"
|
import {slide, fade} from "svelte/transition"
|
||||||
import {preference} from "$lib/preferences"
|
import {preference} from "$lib/preferences"
|
||||||
import Terminal from "$lib/components/Terminal.svelte"
|
|
||||||
|
|
||||||
let terminal = false
|
let terminal = false
|
||||||
let powerDialog = false
|
let powerDialog = false
|
||||||
@@ -17,9 +16,11 @@
|
|||||||
|
|
||||||
{#if $serialPort}
|
{#if $serialPort}
|
||||||
<p transition:slide>
|
<p transition:slide>
|
||||||
{$serialPort.deviceId}
|
{$serialPort.company}
|
||||||
|
{$serialPort.device}
|
||||||
|
{$serialPort.chipset}
|
||||||
<br />
|
<br />
|
||||||
Version {$serialPort.version}
|
Version {$serialPort.version.map(it => it.toString()).join(".")}
|
||||||
</p>
|
</p>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
import type {Chord} from "$lib/serial/chord"
|
import type {Chord} from "$lib/serial/chord"
|
||||||
import tippy from "tippy.js"
|
import tippy from "tippy.js"
|
||||||
import {calculateChordCoverage} from "$lib/chords/coverage"
|
import {calculateChordCoverage} from "$lib/chords/coverage"
|
||||||
import {SETTING_IDS} from "$lib/serial/settings"
|
|
||||||
|
|
||||||
$: searchIndex = $chords?.length > 0 ? buildIndex($chords) : undefined
|
$: searchIndex = $chords?.length > 0 ? buildIndex($chords) : undefined
|
||||||
|
|
||||||
@@ -45,11 +44,6 @@
|
|||||||
{/if}
|
{/if}
|
||||||
<button class="icon" on:click={sort}>sort</button>
|
<button class="icon" on:click={sort}>sort</button>
|
||||||
<button class="icon">filter_list</button>
|
<button class="icon">filter_list</button>
|
||||||
{#if $serialPort}
|
|
||||||
{#await $serialPort.getSetting(SETTING_IDS.enableChording) then enableChording}
|
|
||||||
<label><input type="checkbox" checked={enableChording !== 0} /> Enable Chording</label>
|
|
||||||
{/await}
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
<table>
|
<table>
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import LayoutCC1 from "$lib/components/layout/LayoutCC1.svelte"
|
|
||||||
import {share} from "$lib/share"
|
import {share} from "$lib/share"
|
||||||
import {layout} from "$lib/serial/connection"
|
import {layout} from "$lib/serial/connection"
|
||||||
import tippy from "tippy.js"
|
import tippy from "tippy.js"
|
||||||
import {onMount} from "svelte"
|
import {onMount} from "svelte"
|
||||||
import {layoutAsUrlComponent, layoutFromUrlComponent} from "$lib/serialization/layout"
|
import {layoutAsUrlComponent, layoutFromUrlComponent} from "$lib/serialization/layout"
|
||||||
|
import Layout from "$lib/components/layout/Layout.svelte"
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
const url = new URL(window.location.href)
|
const url = new URL(window.location.href)
|
||||||
@@ -30,7 +30,7 @@
|
|||||||
<svelte:window use:share={shareLayout} />
|
<svelte:window use:share={shareLayout} />
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
<LayoutCC1 />
|
<Layout />
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
|||||||
@@ -1,4 +1,193 @@
|
|||||||
<script>
|
<script>
|
||||||
|
import {serialPort} from "$lib/serial/connection"
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<label><input type="checkbox" />Serial Log</label>
|
{#if $serialPort}
|
||||||
|
<form>
|
||||||
|
<fieldset>
|
||||||
|
<legend><label><input type="checkbox" />Spurring</label></legend>
|
||||||
|
<p>
|
||||||
|
"Chording only" mode which tells your device to output chords on a press rather than a press &
|
||||||
|
release. It also enables you to jump from one chord to another without releasing everything and can be
|
||||||
|
activated in GTM or by chording both mirror keys. It can provide significant speed gains with
|
||||||
|
chording, but also takes away the flexibility of character entry.
|
||||||
|
</p>
|
||||||
|
<p>Spurring also helps new users learn how to chord by eliminating the need to focus on timing.</p>
|
||||||
|
<p>Spurring is toggled by chording both of the 'mirror' keys together.</p>
|
||||||
|
<label
|
||||||
|
>Character Counter Timeout<span class="unit"
|
||||||
|
><input type="number" step="0.1" min="0" max="25.5" />s</span
|
||||||
|
></label
|
||||||
|
>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<fieldset>
|
||||||
|
<legend><label><input type="checkbox" />Arpeggiates</label></legend>
|
||||||
|
<p>
|
||||||
|
A quick, single key press and release used to indicate a suffix, prefix, or modifier to be associated
|
||||||
|
with a chord.
|
||||||
|
</p>
|
||||||
|
<label>Tolerance<span class="unit"><input type="number" step="1" />ms</span></label>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<fieldset>
|
||||||
|
<legend><label><input type="checkbox" />Character Entry</label></legend>
|
||||||
|
<label>Swap Keymap 0 and 1<input type="checkbox" /></label>
|
||||||
|
<label>Key Scan Rate<span class="unit"><input type="number" />Hz</span></label>
|
||||||
|
<label>Key Debounce Press<span class="unit"><input type="number" />ms</span></label>
|
||||||
|
<label>Key Debounce Release<span class="unit"><input type="number" />ms</span></label>
|
||||||
|
<label>Output Character Delay<span class="unit"><input type="number" />µs</span></label>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<fieldset>
|
||||||
|
<legend><label><input type="checkbox" />Mouse</label></legend>
|
||||||
|
<label>Mouse Speed<input type="number" /><input type="number" /></label>
|
||||||
|
<label>Scroll Speed<input type="number" /></label>
|
||||||
|
<label title="Bounces mouse by 1px every 60s if enabled">Active Mouse<input type="checkbox" /></label>
|
||||||
|
<label>Poll Rate<span class="unit"><input type="number" />Hz</span></label>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<fieldset>
|
||||||
|
<legend><label><input type="checkbox" />Chording</label></legend>
|
||||||
|
<label
|
||||||
|
>Character Timeout <span class="unit"><input type="number" min="0" max="25.5" step="0.1" />s</span
|
||||||
|
></label
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
>Detection Tolerance<span class="unit"><input type="number" min="1" max="50" step="1" />ms</span
|
||||||
|
></label
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
>Release Tolerance<span class="unit"><input type="number" min="1" max="50" step="1" />ms</span></label
|
||||||
|
>
|
||||||
|
<label>Compound Chording<input type="checkbox" /></label>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<fieldset>
|
||||||
|
<legend><label>Device</label></legend>
|
||||||
|
<label>Boot message<input type="checkbox" /></label>
|
||||||
|
<label>Realtime Feedback<input type="checkbox" /></label>
|
||||||
|
<label>
|
||||||
|
Operating System
|
||||||
|
<select>
|
||||||
|
<option value="0">Windows</option>
|
||||||
|
<option value="1">MacOS</option>
|
||||||
|
<option value="2">Linux</option>
|
||||||
|
<option value="3">iOS</option>
|
||||||
|
<option value="4">Android</option>
|
||||||
|
<option value="255">Unknown</option>
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
{#if $serialPort.device === "LITE"}
|
||||||
|
<fieldset>
|
||||||
|
<legend><label><input type="checkbox" />RGB</label></legend>
|
||||||
|
<label>Brightness<input type="range" min="0" max="50" step="1" /></label>
|
||||||
|
<label>Color</label>
|
||||||
|
<label>Reactive Keys<input type="checkbox" /></label>
|
||||||
|
</fieldset>
|
||||||
|
{/if}
|
||||||
|
</form>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
form {
|
||||||
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
flex-flow: row wrap;
|
||||||
|
gap: 16px;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
max-width: 30cm;
|
||||||
|
margin-block: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
legend,
|
||||||
|
legend > label {
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: bold;
|
||||||
|
|
||||||
|
> input {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldset {
|
||||||
|
max-width: 400px;
|
||||||
|
border: 1px solid var(--md-sys-color-outline);
|
||||||
|
border-radius: 24px;
|
||||||
|
|
||||||
|
> label {
|
||||||
|
display: flex;
|
||||||
|
gap: 16px;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
margin-block: 4px;
|
||||||
|
|
||||||
|
font-size: 14px;
|
||||||
|
|
||||||
|
&:has(input[type="number"]) {
|
||||||
|
cursor: text;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
filter: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="checkbox"] {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.unit {
|
||||||
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
gap: 4px;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-start;
|
||||||
|
|
||||||
|
width: 67px;
|
||||||
|
padding-inline-end: auto;
|
||||||
|
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: bold;
|
||||||
|
|
||||||
|
background: var(--md-sys-color-secondary-container);
|
||||||
|
border-radius: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="number"] {
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
width: 5ch;
|
||||||
|
height: 100%;
|
||||||
|
padding-block: 4px;
|
||||||
|
|
||||||
|
font-family: "Noto Sans Mono", monospace;
|
||||||
|
color: var(--md-sys-color-on-secondary);
|
||||||
|
text-align: end;
|
||||||
|
|
||||||
|
background: var(--md-sys-color-secondary);
|
||||||
|
border: none;
|
||||||
|
|
||||||
|
&::-webkit-inner-spin-button {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: "bleh";
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
filter: brightness(120%);
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
font-size: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user