SPB Git
1.7 KB · 51 lines tsx
1'use client';23import { createContext, useCallback, useContext, useEffect, useMemo, useState, type ReactNode } from 'react';4import { formatTime, type TimeMode, type TimeStyle } from './format';56interface TimeCtx {7  mode: TimeMode;8  setMode: (m: TimeMode) => void;9  format: (ts: string | number | Date | null | undefined, style?: TimeStyle) => string;10}1112const Ctx = createContext<TimeCtx>({ mode: 'utc', setMode: () => {}, format: (ts, style) => formatTime(ts, 'utc', style) });13const KEY = 'ip.time-mode';1415export function TimeProvider({ children }: { children: ReactNode }) {16  // UTC on the server and on first paint; the stored preference is applied after hydration (no mismatch).17  const [mode, setModeState] = useState<TimeMode>('utc');18  useEffect(() => {19    try {20      const v = window.localStorage.getItem(KEY);21      if (v === 'local' || v === 'utc') setModeState(v);22    } catch {23      /* private mode */24    }25  }, []);26  const setMode = useCallback((m: TimeMode) => {27    setModeState(m);28    try {29      window.localStorage.setItem(KEY, m);30    } catch {31      /* ignore */32    }33  }, []);34  const value = useMemo<TimeCtx>(() => ({ mode, setMode, format: (ts, style) => formatTime(ts, mode, style) }), [mode, setMode]);35  return <Ctx.Provider value={value}>{children}</Ctx.Provider>;36}3738export function useTime() {39  return useContext(Ctx);40}4142/** Inline timestamp that follows the UTC/local toggle. */43export function Time({ ts, style = 'short', className }: { ts: string | number | Date | null | undefined; style?: TimeStyle; className?: string }) {44  const { format } = useTime();45  return (46    <time dateTime={ts ? new Date(ts).toISOString() : undefined} className={className} suppressHydrationWarning>47      {format(ts, style)}48    </time>49  );50}51
Files · be6a3c4c9e1838cf98ba8aa0b95cc0ee163b31bc
Menu

Theme