Improve text-printing UI

- UI elements are now inside a form
- ctrl+enter on textarea submits the form
- UI becomes greyed-out while printing, as visual feedback
This commit is contained in:
Joscha 2025-03-03 01:45:06 +01:00
parent 0dd973c5d6
commit fe906d9242

View file

@ -1,11 +1,37 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref } from "vue"; import { computed, ref, type StyleValue, useTemplateRef } from "vue";
const form = useTemplateRef<HTMLFormElement>("form");
const disabled = ref(false);
const text = ref(""); const text = ref("");
const forceWrap = ref(false); const forceWrap = ref(false);
const feed = ref(true); const feed = ref(true);
// Emulate how typst is wrapping text.
const textareaStyle = computed<StyleValue>(() =>
forceWrap.value ? { wordBreak: "break-all" } : { overflowWrap: "normal" },
);
// Ctrl+Enter in textarea should submit form.
function textareaKeypress(ev: KeyboardEvent): void {
if (ev.ctrlKey && ev.key === "Enter") {
form.value?.requestSubmit();
}
}
async function waitAtLeast(duration: number, since: number): Promise<void> {
const now = Date.now();
const wait = duration - (now - since);
if (wait > 0) {
await new Promise((resolve) => setTimeout(resolve, wait));
}
}
async function submit(): Promise<void> { async function submit(): Promise<void> {
const start = Date.now();
disabled.value = true;
try { try {
const data = new URLSearchParams(); const data = new URLSearchParams();
data.append("text", text.value); data.append("text", text.value);
@ -16,28 +42,51 @@ async function submit(): Promise<void> {
} catch (err) { } catch (err) {
console.log("POST failed:", err); console.log("POST failed:", err);
} }
await waitAtLeast(500, start);
disabled.value = false;
} }
</script> </script>
<template> <template>
<section> <form ref="form" @submit.prevent="submit">
<h2>Text</h2> <h2>Text</h2>
<textarea v-model="text" rows="10"></textarea> <!-- For some reason one col = 2 characters. -->
<textarea
v-model="text"
rows="10"
cols="24"
:style="textareaStyle"
:disabled
@keypress="textareaKeypress"
></textarea>
<fieldset> <fieldset>
<label><input v-model="forceWrap" type="checkbox" /> Force-Wrap</label> <label>
<label><input v-model="feed" type="checkbox" /> Feed</label> <input v-model="forceWrap" type="checkbox" :disabled />
Force-Wrap
</label>
<label><input v-model="feed" type="checkbox" :disabled /> Feed</label>
</fieldset> </fieldset>
<button @click="submit">Print</button> <button :disabled>Print</button>
</section> </form>
</template> </template>
<style scoped> <style scoped>
section { form {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 16px; gap: 16px;
} }
textarea {
align-self: center;
width: fit-content;
/* Prevent manual resizing from changing the width. */
min-width: fit-content;
max-width: fit-content;
}
fieldset { fieldset {
display: flex; display: flex;
flex-direction: column; flex-direction: column;