personal web client for Bluesky
typescript solidjs bluesky atcute
at trunk 1.6 kB view raw
1import { createEffect, createRenderEffect } from 'solid-js'; 2 3import type { CreateMutationResult } from '@mary/solid-query'; 4 5type FocusableElement = HTMLButtonElement | HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement; 6type TextInput = HTMLInputElement | HTMLTextAreaElement; 7 8export const autofocusOnMutation = ( 9 node: FocusableElement, 10 mutation: CreateMutationResult<any, any, any, any>, 11 first = true, 12) => { 13 // Render effects are not affected by <Suspense> 14 createRenderEffect((first: boolean) => { 15 if (mutation.isError || first) { 16 setTimeout(() => node.focus(), 0); 17 } 18 19 return false; 20 }, first); 21}; 22 23export const autofocusNode = (node: FocusableElement) => { 24 setTimeout(() => node.focus(), 0); 25}; 26 27export const autofocusIfEnabled = (node: FocusableElement, enabled: () => boolean) => { 28 // Render effects are not affected by <Suspense> 29 createRenderEffect(() => { 30 if (enabled()) { 31 setTimeout(() => node.focus(), 0); 32 } 33 }); 34}; 35 36export const modelText = (node: TextInput, getter: () => string, setter: (next: string) => void) => { 37 let current: string | undefined; 38 39 createEffect(() => { 40 if (current !== (current = getter())) { 41 node.value = current; 42 } 43 }); 44 45 node.addEventListener('input', (_ev) => { 46 setter((current = node.value)); 47 }); 48}; 49 50export const modelChecked = ( 51 node: HTMLInputElement, 52 getter: () => boolean, 53 setter: (next: boolean) => void, 54) => { 55 let current: boolean | undefined; 56 57 createEffect(() => { 58 if (current !== (current = getter())) { 59 node.checked = current; 60 } 61 }); 62 63 node.addEventListener('input', (_ev) => { 64 setter((current = node.checked)); 65 }); 66};