colorsbymax 0.2.1 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,12 @@
2
2
 
3
3
  What changed in each colorsbymax release. Update with `npm install colorsbymax@latest`.
4
4
 
5
+ ## 0.2.2 (2026-09-25)
6
+
7
+ - **MCP server for AI agents.** [colorsbymax-mcp](mcp/) lets Claude Code, Cursor, VS Code Copilot and other agents set colorsbymax up in a project (with the right edits for Vite, Next.js, Remix, Astro, Nuxt, SvelteKit, plain HTML and more), find themes, build one from brand colours, check contrast and finish. Add it with `claude mcp add colorsbymax -- npx -y colorsbymax-mcp`.
8
+ - **A new README** with colour-coded sections and navigation, and a full guide to using colorsbymax with Claude Code, Cursor, VS Code Copilot, Claude Desktop, Windsurf, Cline and Codex, with or without the MCP server.
9
+ - Fixed: on sites whose body text is a warm or tinted dark (such as dark brown), re-colouring could take the text colour for the brand colour, so brand areas came out far too light or garish. The text colour is no longer a brand candidate.
10
+
5
11
  ## 0.2.1 (2026-09-25)
6
12
 
7
13
  - **Smarter colours when re-colouring a site.** After swapping, text and icons are only adjusted to undo harm the swap did: a pair that reads as well as the site's original design did is left alone (so deliberately soft icons stay soft), and a fix keeps the design's intent, so white icons on a coloured pill stay white, using the nearest theme colour that works. Icon-only buttons are judged as icons (3:1), not text (4.5:1). Across 59 themes on a test site, nothing reads worse than the original design.
package/README.md CHANGED
@@ -1,10 +1,31 @@
1
- # colorsbymax™
2
-
3
- **by mrmaxdesigns**
1
+ <p align="center">
2
+ <img src="https://raw.githubusercontent.com/MaxMuyalwa/colorsbymax/main/docs/readme/hero.svg" alt="colorsbymax by mrmaxdesigns: re-colour any website, live." width="880">
3
+ </p>
4
+
5
+ <p align="center">
6
+ <a href="https://www.npmjs.com/package/colorsbymax"><img src="https://img.shields.io/npm/v/colorsbymax?style=flat-square&color=0d6b84&label=colorsbymax" alt="colorsbymax on npm"></a>
7
+ <a href="https://www.npmjs.com/package/colorsbymax-mcp"><img src="https://img.shields.io/npm/v/colorsbymax-mcp?style=flat-square&color=7c3aed&label=colorsbymax-mcp" alt="colorsbymax-mcp on npm"></a>
8
+ <img src="https://img.shields.io/badge/React-18%20%7C%2019-be185d?style=flat-square" alt="React 18 or 19">
9
+ <img src="https://img.shields.io/badge/types-included-15803d?style=flat-square" alt="TypeScript types included">
10
+ <a href="LICENSE"><img src="https://img.shields.io/badge/licence-MIT-c2410c?style=flat-square" alt="MIT licence"></a>
11
+ </p>
4
12
 
5
13
  A floating theme switcher for websites. Visitors (or the site's owner) can re-colour the whole site instantly: pick one of the site's own themes, a hand-tuned pick, or one of 715 library themes in 14 categories; build and share custom palettes; or override single colours. Every theme is checked against the Web Content Accessibility Guidelines (WCAG) contrast rules, with one-click fixes.
6
14
 
7
- **At a glance**
15
+ <p align="center">
16
+ <a href="#at-a-glance"><img src="https://raw.githubusercontent.com/MaxMuyalwa/colorsbymax/main/docs/readme/nav-start.svg" alt="1. Get started" height="36"></a>
17
+ <a href="#coding-agents-mcp"><img src="https://raw.githubusercontent.com/MaxMuyalwa/colorsbymax/main/docs/readme/nav-agents.svg" alt="2. Coding agents" height="36"></a>
18
+ <a href="#features"><img src="https://raw.githubusercontent.com/MaxMuyalwa/colorsbymax/main/docs/readme/nav-inside.svg" alt="3. Features" height="36"></a>
19
+ <a href="#add-it-to-a-site"><img src="https://raw.githubusercontent.com/MaxMuyalwa/colorsbymax/main/docs/readme/nav-control.svg" alt="4. Full control" height="36"></a>
20
+ <a href="#finished-keep-your-colours-and-hide-the-switcher"><img src="https://raw.githubusercontent.com/MaxMuyalwa/colorsbymax/main/docs/readme/nav-ship.svg" alt="5. Ship it" height="36"></a>
21
+ <a href="#building-the-package"><img src="https://raw.githubusercontent.com/MaxMuyalwa/colorsbymax/main/docs/readme/nav-hood.svg" alt="6. Under the hood" height="36"></a>
22
+ </p>
23
+
24
+ <br>
25
+
26
+ <img src="https://raw.githubusercontent.com/MaxMuyalwa/colorsbymax/main/docs/readme/section-start.svg" alt="01 · Get started: two steps to a live colour switcher" width="100%">
27
+
28
+ ## At a glance
8
29
 
9
30
  - **Two steps.** `npm install colorsbymax`, then `import 'colorsbymax/auto'` once. The colour button appears and visitors can re-colour the site, even if its colours are hard-coded (see [Quick start](#quick-start)).
10
31
  - **React 18 or 19.**
@@ -14,40 +35,6 @@ A floating theme switcher for websites. Visitors (or the site's owner) can re-co
14
35
  - **ESM only.** Import it from a bundler or `import()`; `require('colorsbymax')` from CommonJS isn't supported.
15
36
  - **The colour tools work on their own too.** `contrastRatio`, `checkTheme`, `suggestFix`, `fixAll`, `themeFromPalette`, `darkTokens` and the rest are plain functions with no UI.
16
37
 
17
- ## Features
18
-
19
- - **Site themes first.** The panel opens on a group named after the site, holding its own colours. If those fail contrast, an accessible version is generated automatically.
20
- - **Scan the site.** Press "Scan site" and colorsbymax reads the colours actually painted on the page (ignoring any theme it has applied, and including gradients). It works out the page background, surfaces, text and brand colours, then adds themes named after the site: Scanned (as found), Accessible, Soft, Bold, Complementary, and the closest library matches. Scans run only when asked, and the results are remembered.
21
- - **Max’s picks and library.** 5 hand-tuned picks, plus 715 library themes (Bright, Fun, Pastel, Earth tones, Summer, Autumn, Winter, Spring, Ocean, Warm, Nature, Moody, Monochrome, Eclectic) with search and "Surprise me". The library loads only when the panel opens.
22
- - **Custom palettes, single-colour overrides, JSON import/export.**
23
- - **Palettes from images and PDFs.** In Import / export, upload or drop a mood board, screenshot or photo. colorsbymax picks out its main colours, lets you leave any out, previews the palette it builds around them and saves it as a custom palette. Nothing leaves the browser. PDFs, such as brand guides, work where the site [turns them on](#pdf-uploads); hex codes written in a PDF take priority.
24
- - **Contrast checks.** Problems show as a badge on the theme; the breakdown offers per-item fixes or "Fix all automatically", which changes lightness only.
25
- - **No flash on reload.** An inline pre-paint script applies the saved theme before the page draws.
26
- - **Works on any site.** The panel carries its own stylesheet inside a shadow root, so it needs no Tailwind or other CSS from the site, and the site's CSS can't restyle it.
27
- - **Movable colour button.** The floating button starts in the corner; visitors can drag it anywhere (mouse or touch; a tooltip says so on hover, and the panel closes while it moves) and it stays there, remembered across reloads. The panel then opens beside it, on whichever side has room. Its dot cycles through the current theme's colours.
28
- - **Light and dark mode.** Every built-in theme is designed light; dark mode lists a generated dark twin of each (dark surfaces, light text, brand colours lifted to read on dark, then contrast-fixed) and switches the current theme to its twin. The panel turns dark with it. Custom palettes stay as they were made.
29
- - **Visitor settings.** The gear in the panel header opens settings: theme mode (Light, Dark, Auto), panel size (Compact, Standard, Large), which groups and sections to show, whether the button can be dragged or its dot animates, and moving the button back to its corner. Saved per site.
30
- - **Resizable panel.** Drag the panel's free edges or corner (the ones away from the colour button) to any size, or pick a size in settings; double-click an edge to reset it. The layout follows the panel's width, so a large panel shows three theme cards a row.
31
- - **Audit the page.** The **Audit** button in the panel header looks at the page in the chosen colours and pins notes to what won't look right: a logo that disappears against its background (with a one-click "Colour the logo", or tips when it's a picture colorsbymax can't re-colour, plus "Preview inverted"), pictures whose solid background shows as a box, and text or icons too faint to read. The notes stay on the page as you scroll; **Re-check** after a fix (it also re-checks when the colours change) and close it from its bar.
32
- - **Clear groups and feedback.** The site's own group (globe), Max’s picks (paintbrush) and Yours (person) sit in their own row, apart from the library's categories. Toasts confirm what just happened; saving, importing or building a palette says it went to Yours and offers "Show" to jump straight to it. Tooltips are drawn in the panel's colours.
33
- - **Themed scrollbars.** The page's scrollbars and the panel's slim one take the selected theme's primary colour. Turn the page's off with `scrollbars: false`.
34
- - **Accessible panel.** A labelled dialog with focus trap, Escape, the colour button or an outside click to close, keyboard operable, and reduced-motion support.
35
-
36
- ## How it works
37
-
38
- Every colour is one of 35 tokens (`primary`, `surface`, `ink`, `data-1`…), exposed as `--color-<token>` CSS variables. Applying a theme just sets those variables on `<html>`, so anything the site paints with `var(--color-primary)` (directly, or through Tailwind CSS v4 utilities like `bg-primary`) changes instantly. There's no rebuild and no re-render.
39
-
40
- The switcher renders into a `<colorsbymax-root>` element on `<body>` with its own shadow root and stylesheet. Only the `--color-*` variables cross into it. With reduced motion, the colour button's dot holds still on the theme's primary colour.
41
-
42
- ## Try the demo
43
-
44
- ```bash
45
- npm install
46
- npm run dev
47
- ```
48
-
49
- This serves `demo/`: colorsbymax's own landing page, built with Tailwind, where every colour is a token (it uses every token group, and a strip shows the live values); `/plain.html`, a plain-CSS bakery site with deliberately careless global styles to show they don't reach the panel; and `/unwired.html`, a coffee shop with only hard-coded colours whose whole setup is `import 'colorsbymax/auto'`.
50
-
51
38
  ## Quick start
52
39
 
53
40
  ```bash
@@ -75,6 +62,133 @@ That's all. The colour button appears in the bottom-right corner once the page h
75
62
 
76
63
  Already installed it? Get the newest version with `npm install colorsbymax@latest` (see [Updating](#updating)).
77
64
 
65
+ ## Try the demo
66
+
67
+ ```bash
68
+ npm install
69
+ npm run dev
70
+ ```
71
+
72
+ This serves `demo/`: colorsbymax's own landing page, built with Tailwind, where every colour is a token (it uses every token group, and a strip shows the live values); `/plain.html`, a plain-CSS bakery site with deliberately careless global styles to show they don't reach the panel; and `/unwired.html`, a coffee shop with only hard-coded colours whose whole setup is `import 'colorsbymax/auto'`.
73
+
74
+ <br>
75
+
76
+ <img src="https://raw.githubusercontent.com/MaxMuyalwa/colorsbymax/main/docs/readme/section-agents.svg" alt="02 · Coding agents: let Claude, Cursor or Copilot do it" width="100%">
77
+
78
+ ## Coding agents (MCP)
79
+
80
+ Your coding agent can set colorsbymax up and use it for you. [colorsbymax-mcp](mcp/) is an [MCP](https://modelcontextprotocol.io) server that gives Claude Code, Cursor, VS Code Copilot, Claude Desktop, Windsurf, Codex and other agents colorsbymax's own tools:
81
+
82
+ | The agent can… | Tool |
83
+ | --- | --- |
84
+ | Look at your project and add colorsbymax the right way for its framework: Vite, Next.js, Remix, Gatsby, Astro, Nuxt, SvelteKit, Vue, Svelte or plain HTML | `setup_plan` |
85
+ | Find themes by mood, category or closeness to your brand colour, in light or dark | `find_themes`, `get_theme` |
86
+ | Build a complete, accessible theme around your brand colours | `theme_from_colours` |
87
+ | Check contrast and suggest the smallest fixes | `check_contrast` |
88
+ | Make your chosen colours the default and hide the switcher in production, or remove colorsbymax and keep them | `finish` |
89
+ | Read these docs and the full TypeScript API | `docs` |
90
+
91
+ It reads your project but never changes it: the agent makes the edits, so you review them as usual. It runs with `npx`, so there's nothing to install first (Node 18 or later).
92
+
93
+ ### Claude Code
94
+
95
+ ```bash
96
+ claude mcp add colorsbymax -- npx -y colorsbymax-mcp
97
+ ```
98
+
99
+ That adds it for you in this project. Add `--scope user` to have it in every project, or `--scope project` to share it with your team through a `.mcp.json` file. Check it with `/mcp` inside Claude Code.
100
+
101
+ ### Cursor
102
+
103
+ Add this to `.cursor/mcp.json` in your project, or to `~/.cursor/mcp.json` for every project:
104
+
105
+ ```json
106
+ {
107
+ "mcpServers": {
108
+ "colorsbymax": { "command": "npx", "args": ["-y", "colorsbymax-mcp"] }
109
+ }
110
+ }
111
+ ```
112
+
113
+ It then shows under **Settings → MCP**, and Cursor's agent uses it when you ask about colours or themes.
114
+
115
+ ### VS Code (GitHub Copilot)
116
+
117
+ Add this to `.vscode/mcp.json`, then use it from Copilot Chat in **Agent** mode:
118
+
119
+ ```json
120
+ {
121
+ "servers": {
122
+ "colorsbymax": { "command": "npx", "args": ["-y", "colorsbymax-mcp"] }
123
+ }
124
+ }
125
+ ```
126
+
127
+ ### Claude Desktop
128
+
129
+ Open **Settings → Developer → Edit Config**, add the same `mcpServers` entry as Cursor to `claude_desktop_config.json`, and restart Claude Desktop.
130
+
131
+ ### Windsurf, Cline, Codex and others
132
+
133
+ Most agents take the same `mcpServers` entry as Cursor: Windsurf in `~/.codeium/windsurf/mcp_config.json`, and Cline under **MCP Servers → Configure**. For the Codex CLI, add this to `~/.codex/config.toml`:
134
+
135
+ ```toml
136
+ [mcp_servers.colorsbymax]
137
+ command = "npx"
138
+ args = ["-y", "colorsbymax-mcp"]
139
+ ```
140
+
141
+ On Windows, if an editor can't start `npx`, use `"command": "cmd"` with `"args": ["/c", "npx", "-y", "colorsbymax-mcp"]`.
142
+
143
+ ### What to ask
144
+
145
+ - *"Add colorsbymax to this project."*
146
+ - *"Find me a calm ocean theme that also works in dark mode."*
147
+ - *"Build a theme around our brand colours #e63946 and #1d3557, and check its contrast."*
148
+ - *"Does white text pass on #f59e0b?"*
149
+ - *"I've picked my colours in the panel. Make them the default and hide the switcher in production."* Paste the theme from the panel's **Import / export**, or name the theme.
150
+
151
+ ### Without MCP
152
+
153
+ Any coding agent can still do it from a prompt. Paste this into Claude, Cursor, Copilot or another agent:
154
+
155
+ > Install the colorsbymax npm package in this project and add `import 'colorsbymax/auto'` to the app's entry file, so the colorsbymax colour button appears on every page. For Next.js, Remix or other server-rendered apps, load it in the browser only, with `import('colorsbymax/auto')` inside a `useEffect`. Follow https://github.com/MaxMuyalwa/colorsbymax#quick-start and don't change anything else.
156
+
157
+ When you're done choosing colours, the panel's **I'm done** button gives you ready-made prompts for keeping your colours, hiding the switcher or removing it (see [Finished?](#finished-keep-your-colours-and-hide-the-switcher)).
158
+
159
+ <br>
160
+
161
+ <img src="https://raw.githubusercontent.com/MaxMuyalwa/colorsbymax/main/docs/readme/section-inside.svg" alt="03 · What's inside: everything in the panel" width="100%">
162
+
163
+ ## Features
164
+
165
+ - **Site themes first.** The panel opens on a group named after the site, holding its own colours. If those fail contrast, an accessible version is generated automatically.
166
+ - **Scan the site.** Press "Scan site" and colorsbymax reads the colours actually painted on the page (ignoring any theme it has applied, and including gradients). It works out the page background, surfaces, text and brand colours, then adds themes named after the site: Scanned (as found), Accessible, Soft, Bold, Complementary, and the closest library matches. Scans run only when asked, and the results are remembered.
167
+ - **Max’s picks and library.** 5 hand-tuned picks, plus 715 library themes (Bright, Fun, Pastel, Earth tones, Summer, Autumn, Winter, Spring, Ocean, Warm, Nature, Moody, Monochrome, Eclectic) with search and "Surprise me". The library loads only when the panel opens.
168
+ - **Custom palettes, single-colour overrides, JSON import/export.**
169
+ - **Palettes from images and PDFs.** In Import / export, upload or drop a mood board, screenshot or photo. colorsbymax picks out its main colours, lets you leave any out, previews the palette it builds around them and saves it as a custom palette. Nothing leaves the browser. PDFs, such as brand guides, work where the site [turns them on](#pdf-uploads); hex codes written in a PDF take priority.
170
+ - **Contrast checks.** Problems show as a badge on the theme; the breakdown offers per-item fixes or "Fix all automatically", which changes lightness only.
171
+ - **No flash on reload.** An inline pre-paint script applies the saved theme before the page draws.
172
+ - **Works on any site.** The panel carries its own stylesheet inside a shadow root, so it needs no Tailwind or other CSS from the site, and the site's CSS can't restyle it.
173
+ - **Movable colour button.** The floating button starts in the corner; visitors can drag it anywhere (mouse or touch; a tooltip says so on hover, and the panel closes while it moves) and it stays there, remembered across reloads. The panel then opens beside it, on whichever side has room. Its dot cycles through the current theme's colours.
174
+ - **Light and dark mode.** Every built-in theme is designed light; dark mode lists a generated dark twin of each (dark surfaces, light text, brand colours lifted to read on dark, then contrast-fixed) and switches the current theme to its twin. The panel turns dark with it. Custom palettes stay as they were made.
175
+ - **Visitor settings.** The gear in the panel header opens settings: theme mode (Light, Dark, Auto), panel size (Compact, Standard, Large), which groups and sections to show, whether the button can be dragged or its dot animates, and moving the button back to its corner. Saved per site.
176
+ - **Resizable panel.** Drag the panel's free edges or corner (the ones away from the colour button) to any size, or pick a size in settings; double-click an edge to reset it. The layout follows the panel's width, so a large panel shows three theme cards a row.
177
+ - **Audit the page.** The **Audit** button in the panel header looks at the page in the chosen colours and pins notes to what won't look right: a logo that disappears against its background (with a one-click "Colour the logo", or tips when it's a picture colorsbymax can't re-colour, plus "Preview inverted"), pictures whose solid background shows as a box, and text or icons too faint to read. The notes stay on the page as you scroll; **Re-check** after a fix (it also re-checks when the colours change) and close it from its bar.
178
+ - **Clear groups and feedback.** The site's own group (globe), Max’s picks (paintbrush) and Yours (person) sit in their own row, apart from the library's categories. Toasts confirm what just happened; saving, importing or building a palette says it went to Yours and offers "Show" to jump straight to it. Tooltips are drawn in the panel's colours.
179
+ - **Themed scrollbars.** The page's scrollbars and the panel's slim one take the selected theme's primary colour. Turn the page's off with `scrollbars: false`.
180
+ - **Accessible panel.** A labelled dialog with focus trap, Escape, the colour button or an outside click to close, keyboard operable, and reduced-motion support.
181
+
182
+ ## How it works
183
+
184
+ Every colour is one of 35 tokens (`primary`, `surface`, `ink`, `data-1`…), exposed as `--color-<token>` CSS variables. Applying a theme just sets those variables on `<html>`, so anything the site paints with `var(--color-primary)` (directly, or through Tailwind CSS v4 utilities like `bg-primary`) changes instantly. There's no rebuild and no re-render.
185
+
186
+ The switcher renders into a `<colorsbymax-root>` element on `<body>` with its own shadow root and stylesheet. Only the `--color-*` variables cross into it. With reduced motion, the colour button's dot holds still on the theme's primary colour.
187
+
188
+ <br>
189
+
190
+ <img src="https://raw.githubusercontent.com/MaxMuyalwa/colorsbymax/main/docs/readme/section-control.svg" alt="04 · Full control: paint with colour tokens" width="100%">
191
+
78
192
  ## Add it to a site
79
193
 
80
194
  This is the full setup, for sites that want exact control over which colour goes where. colorsbymax needs React 18 or 19, and ships as plain JavaScript with TypeScript types, so Vite, Next.js, webpack and other bundlers use it without extra setup:
@@ -157,6 +271,10 @@ PDF.js still downloads only when a visitor picks a PDF. Sites that don't opt in
157
271
 
158
272
  `examples/tsungi.config.js` is a complete example for tsungi.online, the first site to use colorsbymax.
159
273
 
274
+ <br>
275
+
276
+ <img src="https://raw.githubusercontent.com/MaxMuyalwa/colorsbymax/main/docs/readme/section-ship.svg" alt="05 · Ship it: keep your colours and go live" width="100%">
277
+
160
278
  ## Finished? Keep your colours and hide the switcher
161
279
 
162
280
  The colours you pick in the panel are saved only in your own browser. When you're happy with them, press **I'm done** at the bottom of the panel. It shows your colours and three ways to finish, each with code to copy and a prompt you can paste into Claude, Cursor, Copilot or any AI editor. **Cancel, keep using colorsbymax** takes you back without changing anything.
@@ -209,6 +327,10 @@ npm install colorsbymax@latest --prefer-online
209
327
 
210
328
  What changed in each release, and anything you need to do when upgrading, is in [CHANGELOG.md](CHANGELOG.md).
211
329
 
330
+ <br>
331
+
332
+ <img src="https://raw.githubusercontent.com/MaxMuyalwa/colorsbymax/main/docs/readme/section-hood.svg" alt="06 · Under the hood: build, regenerate, contribute" width="100%">
333
+
212
334
  ## Building the package
213
335
 
214
336
  `src/` is the source; `dist/` is what sites install: plain JavaScript with the JSX compiled away. `types/` holds the hand-written TypeScript declarations; `npm run typecheck` compiles `types/check.tsx` against them and checks they match the built exports. The panel's icons are copied from Lucide into `src/icons.jsx` by `npm run icons`. `dist/` is committed so installs straight from GitHub work even when npm skips install scripts, so rebuild it before committing changes to `src/`. `npm publish` also rebuilds it first:
@@ -217,6 +339,14 @@ What changed in each release, and anything you need to do when upgrading, is in
217
339
  npm run build
218
340
  ```
219
341
 
342
+ ## README artwork
343
+
344
+ The hero, the section banners and the navigation chips are SVGs in `docs/readme/`, drawn by `scripts/make-readme-art.mjs` from colorsbymax's own themes:
345
+
346
+ ```bash
347
+ node scripts/make-readme-art.mjs
348
+ ```
349
+
220
350
  ## Panel styles
221
351
 
222
352
  The panel is styled with Tailwind classes in `src/ThemePanel.jsx` and `src/ThemeSwitcher.jsx`. `scripts/build-css.mjs` compiles them, with `src/panel.css`, into `src/panel-css.generated.js`. The demo server does this automatically as you edit; otherwise run:
@@ -1170,7 +1170,7 @@ function inferRoles(colors) {
1170
1170
  const readable = (c, min) => contrastRatio(c.hex, background) >= min;
1171
1171
  const ink = (byText.find((c) => readable(c, 4.5)) ?? byText[0])?.hex ?? "#1f2937";
1172
1172
  const inkSecondary = byText.find((c) => c.hex !== ink && deltaE(c.hex, ink) > 8 && readable(c, 3))?.hex;
1173
- const accents = colors.map((c) => {
1173
+ const accents = colors.filter((c) => c.hex !== ink && c.hex !== inkSecondary).map((c) => {
1174
1174
  const [h, s, l] = toHsl(c.hex);
1175
1175
  const share = c.bg / BG + c.text / TEXT + c.border / BORDER * .5;
1176
1176
  return {
@@ -2501,6 +2501,26 @@ function themeFromPalette(colours) {
2501
2501
  };
2502
2502
  }
2503
2503
  //#endregion
2504
+ //#region src/finish.js
2505
+ /** The production check for Vite projects; other bundlers use NODE_ENV. */
2506
+ var VITE_PROD = "import.meta.env.PROD";
2507
+ var NODE_PROD = "process.env.NODE_ENV === 'production'";
2508
+ var tokenLines = (tokens, indent) => TOKEN_KEYS.map((k) => `${indent}'${k}': '${tokens[k]}',`).join("\n");
2509
+ /**
2510
+ * Code that makes the chosen colours the site's default and hides the switcher in production.
2511
+ * @param {'auto' | 'provider'} kind the one-line setup (autoMount) or ThemeProvider
2512
+ */
2513
+ function keepSnippet(kind, name, tokens, prod = VITE_PROD) {
2514
+ const theme = `defaultTheme: {\n name: ${JSON.stringify(name)},\n tokens: {\n${tokenLines(tokens, " ")}\n },\n },\n // Hides the colour button in production; set to false to bring it back.\n hidden: ${prod},`;
2515
+ if (kind === "auto") return `// Replace \`import 'colorsbymax/auto'\` with:\nimport { autoMount } from 'colorsbymax/auto'\n\nautoMount({\n ${theme}\n})`;
2516
+ return `// Add to the config you pass to <ThemeProvider>:\n<ThemeProvider config={{\n ...config,\n ${theme}\n}}>`;
2517
+ }
2518
+ /** The theme as `--color-*` variables on :root. */
2519
+ var cssSnippet = (tokens) => `:root {\n${TOKEN_KEYS.map((k) => ` --color-${k}: ${tokens[k]};`).join("\n")}\n}`;
2520
+ var keepPrompt = (name, tokens) => `Update my colorsbymax setup so the colours I chose become my site's default and the colour switcher is hidden in production. In the colorsbymax config (the autoMount({...}) call, or the config passed to <ThemeProvider>), set defaultTheme to { name: ${JSON.stringify(name)}, tokens: ${JSON.stringify(tokens)} } and set hidden: ${VITE_PROD} (use ${NODE_PROD} if this isn't a Vite project). If the site uses import 'colorsbymax/auto', replace it with import { autoMount } from 'colorsbymax/auto' and an autoMount({...}) call with that config. Don't change anything else.`;
2521
+ /** @param {boolean} recolouring true when colorsbymax was swapping the site's hard-coded colours */
2522
+ var removePrompt = (tokens, recolouring) => recolouring ? `Remove colorsbymax from this project but keep the colours it currently shows. The site's CSS uses hard-coded colours that colorsbymax was swapping at runtime, so update the site's own CSS to use this palette instead (primary is the main brand colour, background the page, ink the text): ${JSON.stringify(tokens)}. Then uninstall the colorsbymax package and delete its import (import 'colorsbymax/auto', autoMount, ThemeProvider or ThemeSwitcher) and any colorsbymax pre-paint script in index.html.` : `Remove colorsbymax from this project but keep my colours: add these CSS variables to my global stylesheet, replacing any existing --color-* values: ${cssSnippet(tokens)} Then uninstall the colorsbymax package and delete its usage (ThemeProvider, ThemeSwitcher, autoMount or import 'colorsbymax/auto') and any colorsbymax pre-paint script in index.html. Keep colorsbymax/tokens.css only if nothing else needs it.`;
2523
+ //#endregion
2504
2524
  //#region src/settings.js
2505
2525
  /**
2506
2526
  * @typedef {Object} PanelSettings
@@ -2862,18 +2882,6 @@ function Toast({ toast, onDismiss }) {
2862
2882
  ]
2863
2883
  });
2864
2884
  }
2865
- var PROD = "import.meta.env.PROD";
2866
- var tokenLines = (tokens, indent) => TOKEN_KEYS.map((k) => `${indent}'${k}': '${tokens[k]}',`).join("\n");
2867
- /** Code that makes the chosen colours the site's default and hides the switcher in production. */
2868
- function keepSnippet(kind, name, tokens) {
2869
- const theme = `defaultTheme: {\n name: ${JSON.stringify(name)},\n tokens: {\n${tokenLines(tokens, " ")}\n },\n },\n // Hides the colour button in production; set to false to bring it back.\n hidden: ${PROD},`;
2870
- if (kind === "auto") return `// Replace \`import 'colorsbymax/auto'\` with:\nimport { autoMount } from 'colorsbymax/auto'\n\nautoMount({\n ${theme}\n})`;
2871
- return `// Add to the config you pass to <ThemeProvider>:\n<ThemeProvider config={{\n ...config,\n ${theme}\n}}>`;
2872
- }
2873
- var cssSnippet = (tokens) => `:root {\n${TOKEN_KEYS.map((k) => ` --color-${k}: ${tokens[k]};`).join("\n")}\n}`;
2874
- var keepPrompt = (name, tokens) => `Update my colorsbymax setup so the colours I chose become my site's default and the colour switcher is hidden in production. In the colorsbymax config (the autoMount({...}) call, or the config passed to <ThemeProvider>), set defaultTheme to { name: ${JSON.stringify(name)}, tokens: ${JSON.stringify(tokens)} } and set hidden: ${PROD} (use process.env.NODE_ENV === 'production' if this isn't a Vite project). If the site uses import 'colorsbymax/auto', replace it with import { autoMount } from 'colorsbymax/auto' and an autoMount({...}) call with that config. Don't change anything else.`;
2875
- var BRING_BACK_PROMPT = "Show the colorsbymax colour switcher again in production: in its config (the autoMount({...}) call or the config passed to <ThemeProvider>), set hidden to false or remove the hidden line. Don't change anything else.";
2876
- var removePrompt = (tokens, recolouring) => recolouring ? `Remove colorsbymax from this project but keep the colours it currently shows. The site's CSS uses hard-coded colours that colorsbymax was swapping at runtime, so update the site's own CSS to use this palette instead (primary is the main brand colour, background the page, ink the text): ${JSON.stringify(tokens)}. Then uninstall the colorsbymax package and delete its import (import 'colorsbymax/auto', autoMount, ThemeProvider or ThemeSwitcher) and any colorsbymax pre-paint script in index.html.` : `Remove colorsbymax from this project but keep my colours: add these CSS variables to my global stylesheet, replacing any existing --color-* values: ${cssSnippet(tokens)} Then uninstall the colorsbymax package and delete its usage (ThemeProvider, ThemeSwitcher, autoMount or import 'colorsbymax/auto') and any colorsbymax pre-paint script in index.html. Keep colorsbymax/tokens.css only if nothing else needs it.`;
2877
2885
  /** Shows code with a copy button. */
2878
2886
  function CopyBlock({ label, text, copyLabel = "Copy" }) {
2879
2887
  const { toast } = usePanel();
@@ -3028,7 +3036,7 @@ function FinishView({ onBack }) {
3028
3036
  " instead of ",
3029
3037
  /* @__PURE__ */ jsx("code", {
3030
3038
  className: "font-mono",
3031
- children: PROD
3039
+ children: "import.meta.env.PROD"
3032
3040
  }),
3033
3041
  " (Next.js, webpack)."
3034
3042
  ]
@@ -3053,7 +3061,7 @@ function FinishView({ onBack }) {
3053
3061
  "."
3054
3062
  ] }), /* @__PURE__ */ jsx(CopyBlock, {
3055
3063
  label: "Prompt to bring it back",
3056
- text: BRING_BACK_PROMPT,
3064
+ text: "Show the colorsbymax colour switcher again in production: in its config (the autoMount({...}) call or the config passed to <ThemeProvider>), set hidden to false or remove the hidden line. Don't change anything else.",
3057
3065
  copyLabel: "Copy prompt"
3058
3066
  })]
3059
3067
  })
package/dist/auto.js CHANGED
@@ -1,4 +1,4 @@
1
- import { s as ThemeProvider, t as ThemeSwitcher } from "./ThemeSwitcher-C0SSJ-oR.js";
1
+ import { s as ThemeProvider, t as ThemeSwitcher } from "./ThemeSwitcher-L1GXY55E.js";
2
2
  import { createElement } from "react";
3
3
  import { createRoot } from "react-dom/client";
4
4
  //#region src/auto.js
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- import { A as PAIRINGS, C as TOKEN_KEYS, D as MIN_CONTRAST_NON_TEXT, E as MIN_CONTRAST_LARGE_TEXT, F as contrastRatio, I as normalizeHex, M as checkTheme, N as fixAll, O as MIN_CONTRAST_TEXT, P as suggestFix, S as TOKEN_GROUPS, T as deriveAppTokens, _ as darkTokens, a as rolesFromPalette, b as BASE_TOKENS, c as applyTokens, d as prePaintScript, f as collectColors, g as themeFromRoles, h as suggestThemes, i as dominantColours, j as checkRamp, k as MIN_RAMP_STEP_DELTA_E, l as useTheme, m as inferRoles, n as DEFAULT_SETTINGS, o as themeFromPalette, p as detectSiteName, r as coloursFromFile, s as ThemeProvider, t as ThemeSwitcher, u as DEFAULT_STORAGE_KEY, v as isDarkTheme, w as completeTokens, x as PRESETS, y as toDark } from "./ThemeSwitcher-C0SSJ-oR.js";
1
+ import { A as PAIRINGS, C as TOKEN_KEYS, D as MIN_CONTRAST_NON_TEXT, E as MIN_CONTRAST_LARGE_TEXT, F as contrastRatio, I as normalizeHex, M as checkTheme, N as fixAll, O as MIN_CONTRAST_TEXT, P as suggestFix, S as TOKEN_GROUPS, T as deriveAppTokens, _ as darkTokens, a as rolesFromPalette, b as BASE_TOKENS, c as applyTokens, d as prePaintScript, f as collectColors, g as themeFromRoles, h as suggestThemes, i as dominantColours, j as checkRamp, k as MIN_RAMP_STEP_DELTA_E, l as useTheme, m as inferRoles, n as DEFAULT_SETTINGS, o as themeFromPalette, p as detectSiteName, r as coloursFromFile, s as ThemeProvider, t as ThemeSwitcher, u as DEFAULT_STORAGE_KEY, v as isDarkTheme, w as completeTokens, x as PRESETS, y as toDark } from "./ThemeSwitcher-L1GXY55E.js";
2
2
  export { BASE_TOKENS, DEFAULT_SETTINGS, DEFAULT_STORAGE_KEY, MIN_CONTRAST_LARGE_TEXT, MIN_CONTRAST_NON_TEXT, MIN_CONTRAST_TEXT, MIN_RAMP_STEP_DELTA_E, PAIRINGS, PRESETS, TOKEN_GROUPS, TOKEN_KEYS, ThemeProvider, ThemeSwitcher, applyTokens, checkRamp, checkTheme, collectColors, coloursFromFile, completeTokens, contrastRatio, darkTokens, deriveAppTokens, detectSiteName, dominantColours, fixAll, inferRoles, isDarkTheme, normalizeHex, prePaintScript, rolesFromPalette, suggestFix, suggestThemes, themeFromPalette, themeFromRoles, toDark, useTheme };
package/package.json CHANGED
@@ -1,112 +1,113 @@
1
- {
2
- "name": "colorsbymax",
3
- "version": "0.2.1",
4
- "description": "A live theme switcher for any website: site themes, 700+ palettes, for light/dark modes and WCAG contrast checks.",
5
- "keywords": [
6
- "theme",
7
- "theme-switcher",
8
- "colors",
9
- "colours",
10
- "palette",
11
- "dark-mode",
12
- "accessibility",
13
- "wcag",
14
- "contrast",
15
- "react",
16
- "tailwind"
17
- ],
18
- "author": "Max Muyalwa (mrmaxdesigns)",
19
- "homepage": "https://github.com/MaxMuyalwa/colorsbymax#readme",
20
- "repository": {
21
- "type": "git",
22
- "url": "git+https://github.com/MaxMuyalwa/colorsbymax.git"
23
- },
24
- "bugs": {
25
- "url": "https://github.com/MaxMuyalwa/colorsbymax/issues"
26
- },
27
- "type": "module",
28
- "main": "./dist/index.js",
29
- "module": "./dist/index.js",
30
- "types": "./types/index.d.ts",
31
- "typesVersions": {
32
- "*": {
33
- "pdf": [
34
- "./types/pdf.d.ts"
35
- ],
36
- "auto": [
37
- "./types/auto.d.ts"
38
- ]
39
- }
40
- },
41
- "exports": {
42
- ".": {
43
- "types": "./types/index.d.ts",
44
- "import": "./dist/index.js",
45
- "default": "./dist/index.js"
46
- },
47
- "./auto": {
48
- "types": "./types/auto.d.ts",
49
- "import": "./dist/auto.js",
50
- "default": "./dist/auto.js"
51
- },
52
- "./pdf": {
53
- "types": "./types/pdf.d.ts",
54
- "import": "./dist/pdf.js",
55
- "default": "./dist/pdf.js"
56
- },
57
- "./tokens.css": "./src/tokens.css",
58
- "./package.json": "./package.json"
59
- },
60
- "sideEffects": [
61
- "./dist/auto.js"
62
- ],
63
- "engines": {
64
- "node": ">=18"
65
- },
66
- "files": [
67
- "dist",
68
- "types/index.d.ts",
69
- "types/auto.d.ts",
70
- "types/pdf.d.ts",
71
- "src/tokens.css",
72
- "LICENSE",
73
- "THIRD_PARTY_NOTICES.md",
74
- "CHANGELOG.md"
75
- ],
76
- "scripts": {
77
- "dev": "vite",
78
- "build": "node scripts/build-css.mjs && vite build --config vite.lib.config.js",
79
- "typecheck": "tsc -p types && node scripts/check-types.mjs",
80
- "prepublishOnly": "npm run build && npm run typecheck",
81
- "build:demo": "vite build",
82
- "css": "node scripts/build-css.mjs",
83
- "icons": "node scripts/build-icons.mjs",
84
- "presets": "node scripts/generate-presets.mjs"
85
- },
86
- "peerDependencies": {
87
- "react": "^18.2.0 || ^19.0.0",
88
- "react-dom": "^18.2.0 || ^19.0.0",
89
- "pdfjs-dist": ">=4"
90
- },
91
- "peerDependenciesMeta": {
92
- "pdfjs-dist": {
93
- "optional": true
94
- }
95
- },
96
- "devDependencies": {
97
- "@tailwindcss/cli": "^4.3.3",
98
- "@tailwindcss/vite": "^4.3.3",
99
- "@types/react": "^19.3.0",
100
- "@types/react-dom": "^19.3.0",
101
- "@vitejs/plugin-react": "^6.1.1",
102
- "lucide-react": "^1.48.0",
103
- "nice-color-palettes": "^4.0.0",
104
- "pdfjs-dist": "^6.3.289",
105
- "react": "^19.3.0",
106
- "react-dom": "^19.3.0",
107
- "tailwindcss": "^4.3.3",
108
- "typescript": "^5.9.3",
109
- "vite": "^8.3.1"
110
- },
111
- "license": "MIT"
112
- }
1
+ {
2
+ "name": "colorsbymax",
3
+ "version": "0.2.2",
4
+ "description": "A live theme switcher for any website: site themes, 700+ palettes, for light/dark modes and WCAG contrast checks.",
5
+ "keywords": [
6
+ "theme",
7
+ "theme-switcher",
8
+ "colors",
9
+ "colours",
10
+ "palette",
11
+ "dark-mode",
12
+ "accessibility",
13
+ "wcag",
14
+ "contrast",
15
+ "react",
16
+ "tailwind"
17
+ ],
18
+ "author": "Max Muyalwa (mrmaxdesigns)",
19
+ "homepage": "https://github.com/MaxMuyalwa/colorsbymax#readme",
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "git+https://github.com/MaxMuyalwa/colorsbymax.git"
23
+ },
24
+ "bugs": {
25
+ "url": "https://github.com/MaxMuyalwa/colorsbymax/issues"
26
+ },
27
+ "type": "module",
28
+ "main": "./dist/index.js",
29
+ "module": "./dist/index.js",
30
+ "types": "./types/index.d.ts",
31
+ "typesVersions": {
32
+ "*": {
33
+ "pdf": [
34
+ "./types/pdf.d.ts"
35
+ ],
36
+ "auto": [
37
+ "./types/auto.d.ts"
38
+ ]
39
+ }
40
+ },
41
+ "exports": {
42
+ ".": {
43
+ "types": "./types/index.d.ts",
44
+ "import": "./dist/index.js",
45
+ "default": "./dist/index.js"
46
+ },
47
+ "./auto": {
48
+ "types": "./types/auto.d.ts",
49
+ "import": "./dist/auto.js",
50
+ "default": "./dist/auto.js"
51
+ },
52
+ "./pdf": {
53
+ "types": "./types/pdf.d.ts",
54
+ "import": "./dist/pdf.js",
55
+ "default": "./dist/pdf.js"
56
+ },
57
+ "./tokens.css": "./src/tokens.css",
58
+ "./package.json": "./package.json"
59
+ },
60
+ "sideEffects": [
61
+ "./dist/auto.js"
62
+ ],
63
+ "engines": {
64
+ "node": ">=18"
65
+ },
66
+ "files": [
67
+ "dist",
68
+ "types/index.d.ts",
69
+ "types/auto.d.ts",
70
+ "types/pdf.d.ts",
71
+ "src/tokens.css",
72
+ "LICENSE",
73
+ "THIRD_PARTY_NOTICES.md",
74
+ "CHANGELOG.md"
75
+ ],
76
+ "scripts": {
77
+ "dev": "vite",
78
+ "build": "node scripts/build-css.mjs && vite build --config vite.lib.config.js",
79
+ "typecheck": "tsc -p types && node scripts/check-types.mjs",
80
+ "prepublishOnly": "npm run build && npm run typecheck",
81
+ "build:demo": "vite build",
82
+ "build:mcp": "vite build --config mcp/vite.config.js",
83
+ "css": "node scripts/build-css.mjs",
84
+ "icons": "node scripts/build-icons.mjs",
85
+ "presets": "node scripts/generate-presets.mjs"
86
+ },
87
+ "peerDependencies": {
88
+ "react": "^18.2.0 || ^19.0.0",
89
+ "react-dom": "^18.2.0 || ^19.0.0",
90
+ "pdfjs-dist": ">=4"
91
+ },
92
+ "peerDependenciesMeta": {
93
+ "pdfjs-dist": {
94
+ "optional": true
95
+ }
96
+ },
97
+ "devDependencies": {
98
+ "@tailwindcss/cli": "^4.3.3",
99
+ "@tailwindcss/vite": "^4.3.3",
100
+ "@types/react": "^19.3.0",
101
+ "@types/react-dom": "^19.3.0",
102
+ "@vitejs/plugin-react": "^6.1.1",
103
+ "lucide-react": "^1.48.0",
104
+ "nice-color-palettes": "^4.0.0",
105
+ "pdfjs-dist": "^6.3.289",
106
+ "react": "^19.3.0",
107
+ "react-dom": "^19.3.0",
108
+ "tailwindcss": "^4.3.3",
109
+ "typescript": "^5.9.3",
110
+ "vite": "^8.3.1"
111
+ },
112
+ "license": "MIT"
113
+ }