feat: article editor core

This commit is contained in:
fsylvain committed 2026-09-27 02:11:38 +02:00
1 parent d493a181e1
commit a4734b2c91
55 files changed
+4186 -496

No files matched your search

+36 -10
View File
@@ -70,7 +70,9 @@ const passwordShown = ref(false)
const loginSubmitting = ref(false)
const loginAlert = ref<AlertState | null>(null)
const shellTitle = computed(() => (state.value === 'noSession' ? 'Log in to finish verifying' : ''))
const shellTitle = computed(() =>
state.value === 'noSession' ? 'Log in to finish verifying' : '',
)
const shellDescription = computed(() =>
state.value === 'noSession'
? "You opened this link somewhere you're not logged in. Log in here and we'll verify your account right after."
@@ -80,7 +82,9 @@ const shellDescription = computed(() =>
const usernameError = ref('')
const passwordError = ref('')
const loginSubmitDisabled = computed(() => loginSubmitting.value || retryAfter.active.value)
const loginSubmitDisabled = computed(
() => loginSubmitting.value || retryAfter.active.value,
)
const loginSubmitLabel = computed(() => {
if (loginSubmitting.value) {
@@ -95,7 +99,11 @@ const loginSubmitLabel = computed(() => {
async function focusPassword() {
await nextTick()
await nextTick()
document.querySelector<HTMLInputElement>('input[autocomplete="current-password"]')?.focus()
document
.querySelector<HTMLInputElement>(
'input[autocomplete="current-password"]',
)
?.focus()
}
async function performVerify(code: string) {
@@ -152,8 +160,10 @@ function handleLoginError(error: unknown) {
}
function validateLogin() {
usernameError.value = username.value.trim().length < 3 ? 'Use at least 3 characters.' : ''
passwordError.value = password.value.length === 0 ? 'Enter your password.' : ''
usernameError.value =
username.value.trim().length < 3 ? 'Use at least 3 characters.' : ''
passwordError.value =
password.value.length === 0 ? 'Enter your password.' : ''
return !usernameError.value && !passwordError.value
}
@@ -170,7 +180,10 @@ async function onLoginSubmit() {
await api.request('/v1/auth/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username: username.value, password: password.value }),
body: JSON.stringify({
username: username.value,
password: password.value,
}),
})
const code = typeof route.query.c === 'string' ? route.query.c : ''
await retryVerifying(code)
@@ -281,8 +294,13 @@ onMounted(() => {
role="status"
class="flex flex-col items-center gap-4 py-10 text-center"
>
<UIcon name="i-lucide-loader-2" class="size-8 animate-spin text-highlighted" />
<p class="text-xl/7 font-semibold text-highlighted">Verifying your account…</p>
<UIcon
name="i-lucide-loader-2"
class="size-8 animate-spin text-highlighted"
/>
<p class="text-xl/7 font-semibold text-highlighted">
Verifying your account…
</p>
<p class="text-base text-muted">This only takes a moment.</p>
</div>
@@ -384,13 +402,21 @@ onMounted(() => {
>
<template #trailing>
<UButton
:icon="passwordShown ? 'i-lucide-eye-off' : 'i-lucide-eye'"
:icon="
passwordShown
? 'i-lucide-eye-off'
: 'i-lucide-eye'
"
variant="ghost"
color="neutral"
size="sm"
square
class="size-8 justify-center text-toned"
:aria-label="passwordShown ? 'Hide password' : 'Show password'"
:aria-label="
passwordShown
? 'Hide password'
: 'Show password'
"
:aria-pressed="passwordShown"
@click="passwordShown = !passwordShown"
/>