Skip to content

Instantly share code, notes, and snippets.

@tlux
tlux / context.ts
Created March 15, 2023 12:59
Simple TypeScript wrapper to set and get Svelte contexts
import { getContext, setContext } from "svelte";
/**
* The context object.
*/
export interface Context<T> {
get: () => T;
set: (ctx: T) => T;
}
@tlux
tlux / usePreferredColorScheme.ts
Created December 14, 2025 16:04
Hook to detect the preferred color scheme from the user agent
'use client';
import { useEffect, useState } from 'react';
type ColorScheme = 'light' | 'dark';
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
function getPreferredColorScheme(matches: boolean): ColorScheme {
return matches ? 'dark' : 'light';
@tlux
tlux / portal.tsx
Last active August 6, 2025 19:57
React Portal that is mounted as soon as the target element appears in the DOM
import { type PropsWithChildren, useEffect, useState } from 'react';
import { createPortal } from 'react-dom';
type PortalProps = PropsWithChildren & { targetId: string };
export function Portal({ children, targetId }: PortalProps) {
const [targetElement, setTargetElement] = useState<HTMLElement | null>(null);
useEffect(() => {
const updateTargetElement = () => {
@tlux
tlux / useDistinct.ts
Created May 20, 2025 08:45
Hook that checks if a passed value has changed based on the provided equality function and returns the old instance of the * value if it has not changed
import { isEqual } from 'lodash-es';
import { useEffect, useRef, useState } from 'react';
/**
* Checks if a passed value has changed based on the provided equality function and returns the old instance of the
* value if it has not changed.
*
* @param value The value that is compared.
* @param equalFn A function that compares the old and the new value. Defaults to `lodash.isEqual`.
*/
@tlux
tlux / useScroll.ts
Last active April 5, 2025 16:13
React hook to track and set scroll position of an element
import { RefObject, useCallback, useEffect, useState } from 'react';
export interface ScrollToOptions {
x?: number;
y?: number;
behavior?: ScrollBehavior;
}
export interface UseScrollOptions {
disabled?: boolean;
@tlux
tlux / FlowDedup.kt
Last active February 18, 2025 15:19
Kotlin Flow Dedup Extension Functions
package io.redigital.rebased.ext.flow
import arrow.core.None
import arrow.core.Option
import arrow.core.some
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.transform
fun <T> Flow<T>.dedup(): Flow<T> = dedupBy { it }
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.channelFlow
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import kotlin.time.Duration
@tlux
tlux / use-has-overflow.ts
Created January 3, 2025 18:05
React hook to detect overflow on a ref
import { type RefObject, useEffect, useState } from 'react';
function checkOverflow(el: HTMLElement | null): boolean {
if (!el) return false;
return el.offsetHeight < el.scrollHeight || el.offsetWidth < el.scrollWidth;
}
export function useHasOverflow(ref: RefObject<HTMLElement | null>) {
const [overflow, setOverflow] = useState(false);
@tlux
tlux / use-file.ts
Created December 17, 2024 20:46
React hook to trigger file selection dialog
import { useCallback, useEffect, useRef, useState } from 'react';
function wrapArray<T>(value: T | T[]): T[] {
return Array.isArray(value) ? value : [value];
}
type UseFileOnSelectCallbackArg<TMultiple extends boolean | undefined> =
TMultiple extends true ? FileList : File;
type UseFileOnSelectCallback<TMultiple extends boolean | undefined = false> = (
@tlux
tlux / use-download.ts
Created December 17, 2024 20:26
React hook to trigger a download of a Blob/File or MediaSource
import { useCallback } from 'react';
export function useDownload() {
return useCallback((obj: Blob | MediaSource, filename: string) => {
const url = URL.createObjectURL(obj);
const link = document.createElement('a');
link.href = url;
if (filename) {