From 3def579129df00c1a45ceaf0cbe9ce5e55a0a98a Mon Sep 17 00:00:00 2001 From: Christian Fehmer Date: Thu, 8 Jan 2026 18:13:27 +0100 Subject: [PATCH] wip --- frontend/src/ts/test/live-counter.tsx | 47 ++------------------- frontend/src/ts/types/solid-directives.d.ts | 15 +++++++ frontend/src/ts/utils/solid-visible.ts | 36 ++++++++++++++++ frontend/tsconfig.json | 1 + 4 files changed, 56 insertions(+), 43 deletions(-) create mode 100644 frontend/src/ts/types/solid-directives.d.ts create mode 100644 frontend/src/ts/utils/solid-visible.ts diff --git a/frontend/src/ts/test/live-counter.tsx b/frontend/src/ts/test/live-counter.tsx index 0e17aa130..06a65aab5 100644 --- a/frontend/src/ts/test/live-counter.tsx +++ b/frontend/src/ts/test/live-counter.tsx @@ -1,52 +1,13 @@ -import { Accessor, createEffect, JSXElement, onMount } from "solid-js"; -import { ElementWithUtils } from "../utils/dom"; -import { isFocused } from "./focus"; +import { Accessor, JSXElement } from "solid-js"; +import { VisibleDirectiveProps } from "../types/solid-directives"; export function LiveCounter(props: { value: Accessor; - visible: Accessor<{ - value: boolean; - withAnimation: boolean; - }>; + visible?: VisibleDirectiveProps; class?: string; }): JSXElement { - // oxlint-disable-next-line no-unassigned-vars - let divRef: HTMLDivElement | undefined; - let divUtil: ElementWithUtils | undefined; - - onMount(() => { - if (divRef) { - divUtil = new ElementWithUtils(divRef); - } - }); - - createEffect(() => { - if (divUtil === undefined) return; - const visibleState = props.visible(); - const focusState = isFocused(); - if (visibleState.value && focusState) { - if (visibleState.withAnimation) { - divUtil.animate({ - opacity: [0, 1], - duration: 125, - }); - } else { - divUtil.setStyle({ opacity: "1" }); - } - } else { - if (visibleState.withAnimation) { - divUtil.animate({ - opacity: [1, 0], - duration: 125, - }); - } else { - divUtil.setStyle({ opacity: "0" }); - } - } - }); - return ( -
+
{props.value()}
); diff --git a/frontend/src/ts/types/solid-directives.d.ts b/frontend/src/ts/types/solid-directives.d.ts new file mode 100644 index 000000000..4e6398249 --- /dev/null +++ b/frontend/src/ts/types/solid-directives.d.ts @@ -0,0 +1,15 @@ +import type { Accessor } from "solid-js"; + +export type VisibleDirectiveProps = Accessor<{ + value: boolean; + withAnimation: boolean; +}>; + +declare module "solid-js" { + namespace JSX { + // oxlint-disable-next-line consistent-type-definitions + interface Directives { + visible: VisibleDirectiveProps; + } + } +} diff --git a/frontend/src/ts/utils/solid-visible.ts b/frontend/src/ts/utils/solid-visible.ts new file mode 100644 index 000000000..fd6dace4d --- /dev/null +++ b/frontend/src/ts/utils/solid-visible.ts @@ -0,0 +1,36 @@ +import { createEffect } from "solid-js"; +import { ElementWithUtils } from "./dom"; +import { applyReducedMotion } from "./misc"; +import { isFocused } from "../test/focus"; +import { VisibleDirectiveProps } from "../types/solid-directives"; + +export function visible( + el: HTMLElement, + isVisible: VisibleDirectiveProps, +): void { + const divUtil = new ElementWithUtils(el); + + createEffect(() => { + const visibleState = isVisible(); + const focusState = isFocused(); + if (visibleState.value && focusState) { + if (visibleState.withAnimation) { + divUtil.animate({ + opacity: [0, 1], + duration: applyReducedMotion(1250), + }); + } else { + divUtil.setStyle({ opacity: "1" }); + } + } else { + if (visibleState.withAnimation) { + divUtil.animate({ + opacity: [1, 0], + duration: applyReducedMotion(1250), + }); + } else { + divUtil.setStyle({ opacity: "0" }); + } + } + }); +} diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json index 6c428d580..42978f58e 100644 --- a/frontend/tsconfig.json +++ b/frontend/tsconfig.json @@ -21,6 +21,7 @@ "./src/**/*.ts", "./src/**/*.tsx", "./scripts/**/*.ts", + "./src/**/*.d.ts", "vite-plugins/**/*.ts", "vite.config.ts" ],