-
8cde8b0: feat(COMPT-30): add state & storage hooks — useDebounce, useLocalStorage, useSessionStorage
First batch of production-ready hooks for HooksKit (epic COMPT-2).
New hooks:
useDebounce<T>(value, delay)— returns debounced value; resets timer on value or delay changeuseLocalStorage<T>(key, initial)— syncs withlocalStorage, SSR-safe, JSON serialization, parse-error fallbackuseSessionStorage<T>(key, initial)— same pattern forsessionStorage
Implementation details:
- Shared
storage.tshelper (readStorageValue/writeStorageValue) encapsulates SSR guard (typeof window === 'undefined') and JSON parse fallback - Generics inferred at call site — no manual type params required
- Zero runtime dependencies
tsc --noEmitpasses, ESLint passes (0 warnings), 13/13 tests pass, coverage ≥ 91%- All three hooks exported from
src/index.ts
-
788fe7e: feat(COMPT-31): add DOM & event hooks — useMediaQuery, useWindowSize, useClickOutside, useIntersectionObserver
Second batch of production-ready hooks for HooksKit (epic COMPT-2).
New hooks:
useMediaQuery(query)— tracksmatchMedia, updates on change viauseSyncExternalStore, SSR-safe (server snapshot returnsfalse)useWindowSize()— returns{ width, height }, debounced 100ms on resize, SSR-safe (returns{ 0, 0 })useClickOutside(ref, handler)— fires onmousedownortouchstartoutside ref element, handler updated via ref pattern to avoid stale closuresuseIntersectionObserver(ref, options?)— returns latestIntersectionObserverEntry | null, disconnects observer on unmount
Implementation details:
- All listeners registered in
useEffectand removed in cleanup return - All SSR-safe:
typeof window === 'undefined'guards in every hook useMediaQueryusesuseSyncExternalStore(React 18) — nosetStatein effects- Zero runtime dependencies
tsc --noEmitpasses, ESLint passes (0 warnings), 26/26 tests pass, coverage ≥ 95%- All four hooks exported from
src/index.ts
-
0117305: feat(COMPT-32): add async & lifecycle hooks — usePrevious, useToggle, useInterval, useTimeout, useIsFirstRender
Third and final batch of production-ready hooks for HooksKit (epic COMPT-2). Completes the 12-hook surface.
New hooks:
usePrevious<T>(value)— returns previous render value via state derivation;undefinedon first renderuseToggle(initial?)— toggles boolean state with stableuseCallbackreferenceuseInterval(callback, delay | null)— runs callback on interval; stops immediately whendelayisnull; always uses latest callback via refuseTimeout(callback, delay | null)— fires callback once after delay; cancels whendelayisnullor on unmount; always uses latest callback via refuseIsFirstRender()— returnstrueonly on first render,falseon all subsequent renders
Implementation details:
usePrevioususes React state-derivation pattern (no ref read during render) to satisfy strict lint rulesuseIsFirstRenderuses ref-based approach with scopedeslint-disable(only valid alternative; cannot use setState-in-effect or ref-read-in-render rules)- All timer cleanup in
useEffectreturn — verified under React StrictMode - Zero runtime dependencies
tsc --noEmitpasses, ESLint passes (0 warnings), 25/25 tests pass, hooks coverage ≥ 98%- All five hooks exported from
src/index.ts
-
feat(COMPT-34): README documentation and v0.1.0 publish
- Full README with installation, SSR compatibility note, and one usage example per hook (12 total) with param and return types
- Remove __hooks_placeholder export from hooks barrel
- All 12 hooks importable from @ciscode/hooks-kit package root
- Bump to v0.1.0 — first public release
- 1eeeaaa: test(COMPT-33): full test suite for all 12 hooks
- Consolidate all hook tests under src/hooks/tests/
- Cover all 12 hooks: useDebounce, useLocalStorage, useSessionStorage, useMediaQuery, useWindowSize, useClickOutside, useIntersectionObserver, usePrevious, useToggle, useInterval, useTimeout, useIsFirstRender
- Use vitest fake timers for useDebounce, useInterval, useTimeout, useWindowSize
- Verify all acceptance criteria per COMPT-33 definition of done
- Coverage ≥ 85% lines across all hooks