personal web client for Bluesky
typescript
solidjs
bluesky
atcute
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};