export interface Todo {
id: string;
title: string;
done: boolean;
pending: boolean;
}
'use strict';
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
function backoffDelay(attempt, baseMs, maxDelayMs) {
const exponential = baseMs * 2 ** attempt;
import * as Turbo from "@hotwired/turbo";
function metaContent(name) {
const el = document.querySelector(`meta[name="${name}"]`);
return el ? el.getAttribute("content") : null;
}
export interface Todo {
id: string;
title: string;
done: boolean;
}
import { useCallback, useEffect, useRef, useState } from "react";
export function useIntersectionObserver(options?: IntersectionObserverInit) {
const [isIntersecting, setIsIntersecting] = useState(false);
const nodeRef = useRef<Element | null>(null);
const optionsKey = JSON.stringify(options ?? {});
export class TimeoutError extends Error {
constructor(public readonly ms: number) {
super(`Request timed out after ${ms}ms`);
this.name = "TimeoutError";
}
}
export interface Page<T> {
items: T[];
nextCursor: string | null;
}
export interface Post {
import { useEffect, useState } from "react";
export function useDebouncedValue<T>(value: T, delay = 300): T {
const [debounced, setDebounced] = useState<T>(value);
useEffect(() => {
import { useEffect, useState } from 'react';
interface FetchState<T> {
data: T | null;
error: Error | null;
loading: boolean;
<%# locals: item %>
<button
type="button"
class="toggle-btn"
data-controller="toggle"
data-action="click->toggle#toggle"
const RETRYABLE_STATUS = new Set([408, 429, 500, 502, 503, 504]);
export function isRetryable(error: unknown, response?: Response): boolean {
if (response) {
return RETRYABLE_STATUS.has(response.status);
}
import { useEffect, useState } from "react";
export function useDebounce(value, delay = 300) {
const [debounced, setDebounced] = useState(value);
useEffect(() => {