{"_id":"@amberdaugherty/theme","_rev":"4-8aa81c8a6c2f6125b473a0f4c4c45bc4","name":"@amberdaugherty/theme","dist-tags":{"latest":"0.1.3"},"versions":{"0.1.0":{"name":"@amberdaugherty/theme","version":"0.1.0","license":"MIT","_id":"@amberdaugherty/theme@0.1.0","maintainers":[{"name":"amberdaugherty","email":"liu200111092022@gmail.com"}],"dist":{"shasum":"6bb03711d98759741dd9aca36ddb29fac2f6cee5","tarball":"https://registry.npmjs.org/@amberdaugherty/theme/-/theme-0.1.0.tgz","fileCount":4,"integrity":"sha512-vHS2KzMGACmQBY8SS8HOyHTqoOemMMV0gzVMjaIPNYgPj8uAFjLqknU5S1m/yFr9YEKZbg+isHVda63xKJtAsw==","signatures":[{"sig":"MEUCIDiExIZP0AozbGHYpE35kuzNLe8fBxnXymWy4j1DLpoFAiEAiJQMzswwzLAEz4FnsI/JyNkYbsRF8iGgPlJKHZdJQjs=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":7305},"main":"./dist/index.mjs","type":"module","types":"./dist/index.d.mts","exports":{".":{"types":"./dist/index.d.mts","import":"./dist/index.mjs"},"./style.css":"./tokens.css","./tokens.css":"./tokens.css"},"scripts":{"build":"tsdown","prepublishOnly":"npm run build"},"_npmUser":{"name":"amberdaugherty","email":"liu200111092022@gmail.com"},"_npmVersion":"11.13.0","description":"Reusable theme system: follows system theme, per-tab manual override (new tab resets), Tailwind v4 + shadcn-style tokens.","directories":{},"_nodeVersion":"24.16.0","_hasShrinkwrap":false,"devDependencies":{"react":"^19","tsdown":"^0.22.0","typescript":"^7","@types/react":"^19"},"peerDependencies":{"react":">=18"},"_npmOperationalInternal":{"tmp":"tmp/theme_0.1.0_1785173647508_0.3085040607670415","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@amberdaugherty/theme","version":"0.1.1","license":"MIT","_id":"@amberdaugherty/theme@0.1.1","maintainers":[{"name":"amberdaugherty","email":"liu200111092022@gmail.com"}],"dist":{"shasum":"522af1342f0b43a837f1c60431e1a7a2e6a96c75","tarball":"https://registry.npmjs.org/@amberdaugherty/theme/-/theme-0.1.1.tgz","fileCount":5,"integrity":"sha512-1dVkuACLojtWDMVS6WpLqF3ful0k8IZrOQWAm6FV8OGACMChVclUO0WHlGhQZ47ni2C9pS9nenm1VWSw62WuSA==","signatures":[{"sig":"MEYCIQCvjB9RPIPJysgAd5eqwwAKgo5fbiTUbIu96ve78B2gBAIhAM7MQOr56JjIsDKk10Ly8ywX/lytYQ6WoCAWzL/bLQ3J","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":10770},"main":"./dist/index.mjs","type":"module","types":"./dist/index.d.mts","exports":{".":{"types":"./dist/index.d.mts","import":"./dist/index.mjs"},"./style.css":"./tokens.css","./tokens.css":"./tokens.css"},"scripts":{"build":"tsdown","prepublishOnly":"npm run build"},"_npmUser":{"name":"amberdaugherty","email":"liu200111092022@gmail.com"},"_npmVersion":"11.13.0","description":"Reusable theme system: follows system theme, per-tab manual override (new tab resets), Tailwind v4 + shadcn-style tokens.","directories":{},"_nodeVersion":"24.16.0","_hasShrinkwrap":false,"devDependencies":{"react":"^19","tsdown":"^0.22.0","typescript":"^7","@types/react":"^19"},"peerDependencies":{"react":">=18"},"_npmOperationalInternal":{"tmp":"tmp/theme_0.1.1_1785174260005_0.22474929894779416","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"@amberdaugherty/theme","version":"0.1.2","license":"MIT","_id":"@amberdaugherty/theme@0.1.2","maintainers":[{"name":"amberdaugherty","email":"liu200111092022@gmail.com"}],"dist":{"shasum":"93b9b72abb3e73d862d8a86ba30aab4ce4855bc5","tarball":"https://registry.npmjs.org/@amberdaugherty/theme/-/theme-0.1.2.tgz","fileCount":5,"integrity":"sha512-NEEyxYkOgSii3WlsPRWdjr75ff5cu6scSCKRrrbWzlmIwMf9pAmIYqJIWAOLWrwpdEeJx3/6FrXwymZ4epGsDg==","signatures":[{"sig":"MEUCIQCzeLWF9BmxjbtvCu8u9NrtZ+C2y9OuUwExZ7TyEsp3mgIgd7mLt9bJNdHT482oryYZiD8GnSFvC1lNVN+stiIIijA=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":10878},"main":"./dist/index.mjs","type":"module","types":"./dist/index.d.mts","exports":{".":{"types":"./dist/index.d.mts","import":"./dist/index.mjs"},"./style.css":"./tokens.css","./tokens.css":"./tokens.css"},"scripts":{"build":"tsdown","prepublishOnly":"npm run build"},"_npmUser":{"name":"amberdaugherty","email":"liu200111092022@gmail.com"},"_npmVersion":"11.13.0","description":"Reusable theme system: follows system theme, per-tab manual override (new tab resets), Tailwind v4 + shadcn-style tokens.","directories":{},"_nodeVersion":"24.16.0","_hasShrinkwrap":false,"devDependencies":{"react":"^19","tsdown":"^0.22.0","typescript":"^7","@types/react":"^19"},"peerDependencies":{"react":">=18"},"_npmOperationalInternal":{"tmp":"tmp/theme_0.1.2_1785174429955_0.1345844824700979","host":"s3://npm-registry-packages-npm-production"}},"0.1.3":{"name":"@amberdaugherty/theme","version":"0.1.3","description":"Reusable theme system: follows system theme, per-tab manual override (new tab resets), Tailwind v4 + shadcn-style tokens.","type":"module","license":"MIT","exports":{".":{"types":"./dist/index.d.mts","import":"./dist/index.mjs"},"./tokens.css":"./tokens.css","./style.css":"./tokens.css"},"scripts":{"build":"tsdown","prepublishOnly":"npm run build"},"peerDependencies":{"react":">=18"},"devDependencies":{"@types/react":"^19","react":"^19","tsdown":"^0.22.0","typescript":"^7"},"main":"./dist/index.mjs","types":"./dist/index.d.mts","gitHead":"28b79c9a2a71625411171a5d4ebe06d6629472d9","_id":"@amberdaugherty/theme@0.1.3","_nodeVersion":"24.16.0","_npmVersion":"11.13.0","dist":{"integrity":"sha512-g1XjLEgzc3v6EOax+fZI+MLxcDDbkChigCvYcMg67c6fJE4wUfjm7l+Dve7zj+ECMHnimPIgHRKDegg2d8B69A==","shasum":"d2cd682f6176659e364fa368c8709bf37bd918b3","tarball":"https://registry.npmjs.org/@amberdaugherty/theme/-/theme-0.1.3.tgz","fileCount":5,"unpackedSize":12838,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCICD3zblQS7+Jq6dyhUnaupVD0Z7G/66fUqu5xnGlA4i5AiAm3PZM/YidhXNxr8BRXL4poelJOqmgpmDyZEYJjsoX8w=="}]},"_npmUser":{"name":"amberdaugherty","email":"liu200111092022@gmail.com"},"directories":{},"maintainers":[{"name":"amberdaugherty","email":"liu200111092022@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/theme_0.1.3_1785175319674_0.3639893997770052"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-27T17:34:07.350Z","modified":"2026-07-27T18:01:59.968Z","0.1.0":"2026-07-27T17:34:07.665Z","0.1.1":"2026-07-27T17:44:20.157Z","0.1.2":"2026-07-27T17:47:10.123Z","0.1.3":"2026-07-27T18:01:59.819Z"},"license":"MIT","description":"Reusable theme system: follows system theme, per-tab manual override (new tab resets), Tailwind v4 + shadcn-style tokens.","maintainers":[{"name":"amberdaugherty","email":"liu200111092022@gmail.com"}],"readme":"# @amberdaugherty/theme\n\n可复用的 React 主题系统:跟随系统主题、当前 tab 可手动切换、新开 tab 自动重置回跟随系统。Tailwind v4 + shadcn 风格 token。\n\n两种用法:\n- **完整模式**:自带 `ThemeToggle` 组件 + shadcn 风格 token(配合 Tailwind v4)。\n- **Headless 模式**:纯逻辑(`ThemeProvider` + `useTheme`),UI、样式、定位完全自定义。\n\n## 特性\n\n- 🖥️ **跟随系统**:默认读 `prefers-color-scheme`,系统切换时实时跟随\n- 🔄 **三态切换**:系统 → 浅色 → 深色 循环\n- 🗂️ **per-tab 隔离**:手动选择存在 `sessionStorage`,只影响当前 tab;**新开 tab 自动重置回跟随系统**,同 tab 刷新则保留\n- 🧩 **Headless 友好**:核心只是切 `<html>` 的 `.dark` class + 管记忆,不绑定任何样式方案\n- 🎨 **可选 shadcn 风格 token**:语义化变量 + Tailwind v4 映射(完整模式才用)\n- 🌫️ **无首屏闪烁**:模块加载即应用一次\n\n## 安装\n\n```bash\nnpm install @amberdaugherty/theme\n```\n\nReact ≥ 18。完整模式还需 `tailwindcss` + `@tailwindcss/vite`;Headless 模式无任何样式依赖。\n\n---\n\n## 用法 A:完整模式(`ThemeToggle` + token)\n\n自带切换按钮和配色,开箱即用。\n\n### 1. 主 CSS\n\n```css\n/* src/index.css */\n@import \"tailwindcss\";\n@import \"@amberdaugherty/theme/tokens.css\";\n\n/* ⚠ 必需:让 Tailwind 扫到包里 ThemeToggle 的 class(fixed/top-4 等),\n   否则这些工具类不会生成,定位/样式会失效。 */\n@source \"../node_modules/@amberdaugherty/theme\";\n```\n\n### 2. Vite 配置 Tailwind 插件\n\n```ts\n// vite.config.ts\nimport { defineConfig } from \"vite\";\nimport react from \"@vitejs/plugin-react\";\nimport tailwindcss from \"@tailwindcss/vite\";\n\nexport default defineConfig({\n  plugins: [react(), tailwindcss()],\n});\n```\n\n### 3. 入口\n\n```tsx\nimport { ThemeProvider, ThemeToggle } from \"@amberdaugherty/theme\";\nimport \"./index.css\";\n\ncreateRoot(document.getElementById(\"root\")!).render(\n  <ThemeProvider>\n    <ThemeToggle />\n    <App />\n  </ThemeProvider>,\n);\n```\n\n组件里用语义化 Tailwind class,主题自动跟随:\n\n```tsx\n<main className=\"bg-background text-foreground\">\n  <p className=\"text-muted-foreground\">跟随主题的文字</p>\n</main>\n```\n\n---\n\n## 用法 B:Headless 模式(纯逻辑,自定义 UI)\n\n只用 `ThemeProvider` + `useTheme`,**不引 `tokens.css`、不用 `ThemeToggle`、不需要 `@source`**。按钮、配色、定位全部自己写。\n\n```tsx\n// src/main.tsx —— 只包 Provider,不引任何包样式\nimport { ThemeProvider } from \"@amberdaugherty/theme\";\n\ncreateRoot(document.getElementById(\"root\")!).render(\n  <ThemeProvider>\n    <App />\n  </ThemeProvider>,\n);\n```\n\n```tsx\n// 自己的切换按钮\nimport { useTheme } from \"@amberdaugherty/theme\";\n\nexport function MyToggle() {\n  const { theme, cycle } = useTheme();\n  return (\n    <button onClick={cycle}>\n      {theme === \"dark\" ? \"🌙\" : theme === \"light\" ? \"☀️\" : \"🖥️\"}\n    </button>\n  );\n}\n```\n\n```css\n/* 自己配色:包负责切 <html> 上的 .dark class,你用它写样式即可 */\n:root { --my-bg: #fff; --my-fg: #111; }\n.dark { --my-bg: #111; --my-fg: #fff; }\nbody { background: var(--my-bg); color: var(--my-fg); }\n```\n\n> Headless 模式下,包**只**做三件事:切 `.dark` class、跟随系统、per-tab 记忆。其余一概由你决定(连 Tailwind 都不需要)。\n\n---\n\n## 什么时候需要 `tokens.css` / `@source`?\n\n| 你用到的 | `tokens.css` | `@source` |\n| --- | :---: | :---: |\n| `ThemeToggle`(包自带的组件) | ✅ 需要 | ✅ 需要 |\n| 只用 `useTheme`(Headless) | ❌ 不需要 | ❌ 不需要 |\n\n`@source` 的作用:让消费方的 Tailwind 扫描包里的 class 字符串。只有用了包里带 Tailwind class 的组件(目前是 `ThemeToggle`)才需要。纯 hook 不涉及 class,自然不需要。\n\n## API\n\n### `<ThemeProvider>`\n\n包裹在应用根部,无需 props。\n\n### `useTheme()`\n\n```tsx\nconst { theme, resolved, setTheme, cycle } = useTheme();\n```\n\n| 字段 | 类型 | 说明 |\n| --- | --- | --- |\n| `theme` | `\"system\" \\| \"light\" \\| \"dark\"` | 用户选择 |\n| `resolved` | `\"light\" \\| \"dark\"` | 实际生效值(`system` 时取系统当前值) |\n| `setTheme(t)` | `(t: Theme) => void` | 显式设置 |\n| `cycle()` | `() => void` | 循环切换:系统 → 浅 → 深 |\n\n### `<ThemeToggle />`(完整模式)\n\n三态切换按钮,默认固定右上角(`fixed top-4 right-4`)。接受可选 `className` 追加样式(如 `className=\"left-4 right-auto\"` 移到左上)。\n\n## 可用 token(完整模式)\n\n`tokens.css` 定义并通过 `@theme inline` 暴露为 Tailwind 颜色:\n\n`background` · `foreground` · `card` / `card-foreground` · `muted` / `muted-foreground` · `border` · `input` · `primary` / `primary-foreground` · `accent` / `accent-foreground` · `ring`\n\n用法:`bg-background`、`text-muted-foreground`、`border-border`、`bg-primary text-primary-foreground` 等。圆角:`rounded-lg` / `rounded-md` / `rounded-sm`。改配色只动 `tokens.css` 里 `:root` 与 `.dark` 两套变量。\n\n## 行为说明\n\n- 选择存在 **`sessionStorage`**(per-tab),**不**写 `localStorage` —— 这是「新开 tab 重置回跟随系统」的关键。\n- 暗色通过给 `<html>` 加 `.dark` class 切换。完整模式下配合 Tailwind v4 的 `@custom-variant dark`,`dark:` 变体也能用;Headless 模式下你直接用 `.dark` 选择器写自己的样式。\n\n## License\n\nMIT\n","readmeFilename":"README.md"}