Drop the extra duration text box and slow mobile thumbwheels.
Duration now matches CFG as one wheel; tap the digits to type a length. Touch drags move at a quarter of the desktop rate. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="w-[6.5rem] min-w-0" :class="disabled ? 'opacity-50' : ''">
|
||||
<div class="min-w-0" :class="[disabled ? 'opacity-50' : '', unit ? 'w-[7.25rem]' : 'w-[6.5rem]']">
|
||||
<div v-if="label" class="mb-1.5 text-[10px] font-medium uppercase tracking-wider text-zinc-500">{{ label }}</div>
|
||||
<div
|
||||
class="overflow-hidden rounded-2xl border bg-zinc-950"
|
||||
@@ -7,8 +7,36 @@
|
||||
>
|
||||
<div class="flex items-stretch border-b border-white/5">
|
||||
<div class="min-w-0 flex-1">
|
||||
<SegmentDigits :value="display" />
|
||||
<input
|
||||
v-if="editing"
|
||||
ref="editInput"
|
||||
v-model="draft"
|
||||
type="text"
|
||||
inputmode="decimal"
|
||||
class="h-11 w-full bg-transparent px-2 text-center font-mono text-lg text-amber-300 outline-none"
|
||||
autocomplete="off"
|
||||
spellcheck="false"
|
||||
@blur="commitEdit"
|
||||
@keydown.enter.prevent="commitEdit"
|
||||
@keydown.escape.prevent="cancelEdit"
|
||||
@pointerdown.stop
|
||||
>
|
||||
<button
|
||||
v-else-if="editable"
|
||||
type="button"
|
||||
class="block w-full cursor-text"
|
||||
:aria-label="`Type ${dialName}`"
|
||||
@click="startEdit"
|
||||
@pointerdown.stop
|
||||
>
|
||||
<SegmentDigits :value="display" />
|
||||
</button>
|
||||
<SegmentDigits v-else :value="display" />
|
||||
</div>
|
||||
<span
|
||||
v-if="unit"
|
||||
class="flex items-end px-1.5 pb-2.5 text-[10px] font-medium uppercase tracking-wider text-zinc-500"
|
||||
>{{ unit }}</span>
|
||||
<button
|
||||
type="button"
|
||||
class="flex w-7 shrink-0 items-center justify-center border-l transition"
|
||||
@@ -82,6 +110,9 @@ const props = withDefaults(defineProps<{
|
||||
disabled?: boolean
|
||||
compact?: boolean
|
||||
digits?: number
|
||||
editable?: boolean
|
||||
unit?: string
|
||||
dragRange?: number
|
||||
}>(), {
|
||||
step: 0.1,
|
||||
fineStep: 0.1,
|
||||
@@ -91,11 +122,17 @@ const props = withDefaults(defineProps<{
|
||||
lockKey: '',
|
||||
disabled: false,
|
||||
compact: false,
|
||||
digits: 1
|
||||
digits: 1,
|
||||
editable: false,
|
||||
unit: '',
|
||||
dragRange: 0
|
||||
})
|
||||
|
||||
const model = defineModel<number>({ required: true })
|
||||
const root = ref<HTMLElement | null>(null)
|
||||
const editInput = ref<HTMLInputElement | null>(null)
|
||||
const editing = ref(false)
|
||||
const draft = ref('')
|
||||
const locked = ref(false)
|
||||
|
||||
const dialName = computed(() => props.label || props.ariaLabel || 'dial')
|
||||
@@ -170,6 +207,37 @@ function onKey(event: KeyboardEvent) {
|
||||
}
|
||||
}
|
||||
|
||||
function coarsePointer(event: PointerEvent) {
|
||||
if (event.pointerType === 'touch') return true
|
||||
if (typeof window === 'undefined' || typeof window.matchMedia !== 'function') return false
|
||||
return window.matchMedia('(pointer: coarse)').matches
|
||||
}
|
||||
|
||||
function dragGain(event: PointerEvent) {
|
||||
return coarsePointer(event) ? 0.25 : 1
|
||||
}
|
||||
|
||||
function startEdit() {
|
||||
if (!props.editable || props.disabled) return
|
||||
draft.value = format(model.value)
|
||||
editing.value = true
|
||||
nextTick(() => {
|
||||
editInput.value?.focus()
|
||||
editInput.value?.select()
|
||||
})
|
||||
}
|
||||
|
||||
function commitEdit() {
|
||||
if (!editing.value) return
|
||||
const parsed = Number.parseFloat(draft.value.replace(',', '.').trim())
|
||||
if (Number.isFinite(parsed)) model.value = clamp(parsed)
|
||||
editing.value = false
|
||||
}
|
||||
|
||||
function cancelEdit() {
|
||||
editing.value = false
|
||||
}
|
||||
|
||||
function onPointerDown(event: PointerEvent) {
|
||||
if (frozen.value || event.button !== 0) return
|
||||
const el = root.value
|
||||
@@ -179,9 +247,11 @@ function onPointerDown(event: PointerEvent) {
|
||||
const height = el.clientHeight || 1
|
||||
const startY = event.clientY
|
||||
const startValue = model.value
|
||||
const gain = dragGain(event)
|
||||
const travel = props.dragRange > 0 ? props.dragRange : span.value
|
||||
const onMove = (move: PointerEvent) => {
|
||||
const delta = startY - move.clientY
|
||||
model.value = clamp(startValue + (delta / height) * span.value)
|
||||
model.value = clamp(startValue + (delta / height) * travel * gain)
|
||||
}
|
||||
const onUp = () => {
|
||||
el.removeEventListener('pointermove', onMove)
|
||||
|
||||
Reference in New Issue
Block a user