Code Snippets

Handy code snippets I've collected and written over the years. Filter by category or language to find what you need.

Showing 3 snippets

TypeScript

cn

A zero-dep classnames builder that recursively flattens strings, arrays, and object maps, then pipes the result through tailwind-merge to resolve conflicting Tailwind utilities.

import { twMerge } from "tailwind-merge";

type ClassValue =
  | ClassArray
  | ClassObject
  | string
  | number
  | null
  | boolean
  | undefined;
type ClassObject = Record<string, any>;
type ClassArray = ClassValue[];

function toVal(mix: ClassValue): string {
  let k,
    y,
    str = "";

  if (typeof mix === "string" || typeof mix === "number") {
    str += mix;
  } else if (typeof mix === "object" && mix) {
    if (Array.isArray(mix)) {
      for (k = 0; k < mix.length; k++) {
        if (mix[k]) {
          if ((y = toVal(mix[k]))) {
            str && (str += " ");
            str += y;
          }
        }
      }
    } else {
      for (k in mix as ClassObject) {
        if ((mix as ClassObject)[k]) {
          str && (str += " ");
          str += k;
        }
      }
    }
  }

  return str;
}

export function cn(...args: ClassValue[]): string {
  let i = 0,
    tmp,
    x,
    str = "";

  while (i < args.length) {
    if ((tmp = args[i++])) {
      if ((x = toVal(tmp))) {
        str && (str += " ");
        str += x;
      }
    }
  }

  return twMerge(str);
}
Updated 2 weeks ago
TypeScript

useIntersectionObserver

A flexible IntersectionObserver wrapper supporting single or multiple targets, one-shot observation, and scroll-past-viewport detection.

type InitObserverOptions = {
  elements: Maybe<HTMLElement> | HTMLElement[] | NodeListOf<HTMLElement>;
  cb: (args: {
    obs: IntersectionObserver;
    entry: IntersectionObserverEntry;
  }) => Promise<void> | void;
  options?: IntersectionObserverInit;
  useBounding?: boolean;
  once?: boolean;
}

export function useIntersectionObserver({
  elements,
  cb,
  options,
  useBounding = false,
  once = false,
}: InitObserverOptions): IntersectionObserver {
  const targets = (
    elements instanceof HTMLElement ? [elements] : Array.from(elements ?? [])
  ).filter(Boolean);

  let remaining = targets.length;
  const observer = new IntersectionObserver((entries, obs) => {
    for (const e of entries) {
      const hit = e.isIntersecting || (useBounding && e.boundingClientRect.y < 0);
      if (hit) {
        cb({ obs, entry: e });
        if (once) {
          obs.unobserve(e.target);
          if (--remaining === 0) obs.disconnect();
        }
      }
    }
  }, options);

  for (const el of targets) observer.observe(el);
  return observer;
}
Updated 8 months ago
TypeScript

useInjectScript

Dynamically inject an external script tag into the DOM, returning a Promise that resolves once it loads.

export function useInjectScript({
  async = true,
  id,
  src,
  type = "text/javascript"
}: {
  async?: boolean
  id: string
  src: string
  type?: string
}): Promise<boolean> {
  const scriptEl = document.getElementById(id)
  
  return new Promise((resolve, reject) => {
    if (id && scriptEl) {
      return resolve(true)
    }

    const script = document.createElement('script')
    script.src = src
    script.type = type
    script.async = async
    script.id = id
    
    document.body.appendChild(script)
    
    script.onload = () => resolve(true)
    script.onerror = e => reject(e)
  })
}
Updated 8 months ago