npm package: @pshah-lab/themeswitcher
Description: Light, dark, and system theme manager with SSR-safe no-flash support
Latest version: 0.1.4

# @pshah-lab/themeswitcher

A lightweight, framework-agnostic theme manager for **light**, **dark**, and **system** modes — with **SSR-safe no-flash support**.

Designed to be:
- Minimal
- Predictable
- Copy-paste friendly
- Framework independent

---

## Features

- Light / Dark / System theme support
- Prevents flash of incorrect theme (FOUC)
- SSR-safe (works before JS bundle loads)
- No dependencies
- Fully typed (TypeScript)
- Works with plain JS, React, Vue, or any framework

---

## Installation
```bash
npm install @pshah-lab/themeswitcher
```

---

## Core Usage (Framework-agnostic)
```javascript
import { createThemeManager } from "@pshah-lab/themeswitcher";

const theme = createThemeManager();

theme.set("dark");        // "light" | "dark" | "system"
theme.toggle();           // toggle light ↔ dark
theme.get();              // resolved theme: "light" | "dark"
theme.getMode();          // selected mode
```

The theme is applied to the document using a data attribute:
```html
<html data-theme="dark">
```

Style your app using this attribute:
```css
[data-theme="dark"] {
  background: #000;
  color: #fff;
}
```

---

## React Usage

Create the hook once at module scope.
```typescript
// theme.ts
import { createUseTheme } from "@pshah-lab/themeswitcher";

export const useTheme = createUseTheme();
```

Use it anywhere in your app:
```jsx
function ThemeToggle() {
  const { theme, toggleTheme } = useTheme();

  return (
    <button onClick={toggleTheme}>
      Current theme: {theme}
    </button>
  );
}
```

⚠️ **Do not call `createUseTheme()` inside components.**  
It must be created once and reused.

---

## Prevent Theme Flash (Recommended)

When using light/dark themes, browsers may briefly render the page in the default theme before JavaScript loads. This causes a visible flash of incorrect theme.

To prevent this, add the following script inline in your HTML `<head>`, before any CSS is loaded.

### Why this is needed

- Runs before first paint
- Applies the correct theme synchronously
- Works before your JavaScript bundle loads
- Required for SSR
- Strongly recommended for all setups

### Add this to `<head>`
```html
<script>
(function () {
  try {
    var key = "theme-mode";
    var attribute = "data-theme";

    var stored = localStorage.getItem(key);
    var mode =
      stored === "light" || stored === "dark" || stored === "system"
        ? stored
        : "system";

    var isDark =
      window.matchMedia &&
      window.matchMedia("(prefers-color-scheme: dark)").matches;

    var theme =
      mode === "system"
        ? isDark
          ? "dark"
          : "light"
        : mode;

    document.documentElement.setAttribute(attribute, theme);
  } catch (e) {
    // fail silently
  }
})();
</script>
```

Place it before your CSS:
```html
<head>
  <!-- Prevent theme flash -->
  <script>/* pasted theme script */</script>

  <link rel="stylesheet" href="styles.css" />
</head>
```

### Important Notes

- Do not import this script from the package
- Do not bundle it
- Copy-paste is intentional and required for correct timing
- The script logic matches the internal theme manager

---

## Configuration
```javascript
createThemeManager({
  defaultMode: "system",        // default
  storageKey: "theme-mode",     // localStorage key
  attribute: "data-theme",      // HTML attribute
});
```

---

## API Reference

### `set(mode)`

Set the theme mode.
```javascript
theme.set("dark");
```

### `toggle()`

Toggle between light and dark.
```javascript
theme.toggle();
```

### `get()`

Get the resolved theme.
```javascript
theme.get(); // "light" | "dark"
```

### `getMode()`

Get the selected mode.
```javascript
theme.getMode(); // "light" | "dark" | "system"
```

---

## Design Philosophy

- Explicit over magical
- Copy-paste over runtime hacks
- No global side effects
- No framework lock-in
- Predictable behavior

---

## License

MIT