bluedither 1.0.17 → 1.0.19

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.
@@ -18,17 +18,20 @@ import { resolve, dirname } from 'path';
18
18
  const ENDPOINT = '/__bluedither/commit';
19
19
 
20
20
  function findTokensPath() {
21
- // Search from cwd for bluedither/tokens.json
21
+ // Search from cwd prioritize public/ (Vite serves static from there)
22
22
  const cwd = process.cwd();
23
23
  const paths = [
24
- resolve(cwd, 'bluedither', 'tokens.json'),
25
24
  resolve(cwd, 'public', 'bluedither', 'tokens.json'),
25
+ resolve(cwd, 'bluedither', 'tokens.json'),
26
26
  resolve(cwd, 'theme', 'tokens.json'),
27
27
  ];
28
28
  for (const p of paths) {
29
29
  if (existsSync(p)) return p;
30
30
  }
31
- // Default to bluedither/tokens.json even if it doesn't exist yet
31
+ // Default to public/bluedither if public/ dir exists (Vite project), else bluedither/
32
+ if (existsSync(resolve(cwd, 'public'))) {
33
+ return resolve(cwd, 'public', 'bluedither', 'tokens.json');
34
+ }
32
35
  return resolve(cwd, 'bluedither', 'tokens.json');
33
36
  }
34
37
 
@@ -111,7 +111,9 @@
111
111
  if (t.shader?.scale != null) params.scale = t.shader.scale;
112
112
  if (t.shader?.size != null) params.size = t.shader.size;
113
113
  if (t.shader?.rotation != null) params.rotation = t.shader.rotation;
114
- shader.updateParams(params);
114
+ if (typeof shader.updateParams === 'function') {
115
+ shader.updateParams(params);
116
+ }
115
117
  return true;
116
118
  };
117
119
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bluedither",
3
- "version": "1.0.17",
3
+ "version": "1.0.19",
4
4
  "description": "A bold, dithered-shader hero theme for Claude Code — skill + fine-tuner",
5
5
  "type": "module",
6
6
  "bin": {
@@ -2,6 +2,40 @@
2
2
 
3
3
  When the target project uses **React** (detected via `react` in package.json dependencies), follow these patterns.
4
4
 
5
+ ## CRITICAL: File Placement Rules
6
+
7
+ **In `src/` (importable source files):**
8
+ - All `.jsx`/`.tsx` component files
9
+ - `bluedither.css` — CSS custom properties + rules
10
+ - `paper-shaders-bundle.js` — copied from `bluedither/shaders/`
11
+ - Any other JS modules that are `import`-ed
12
+
13
+ **In `public/bluedither/` (static assets loaded at runtime):**
14
+ - `bluedither-tuner.js` — tuner panel
15
+ - `bluedither-tuner.css` — tuner styles
16
+ - `bluedither-tuner-inject.js` — tuner loader
17
+ - `tokens.json` — design tokens (read at runtime by tuner)
18
+ - `tokens.defaults.json` — default tokens
19
+ - `dev-middleware.js` — Vite commit endpoint
20
+
21
+ **NEVER import JS files from `public/` — Vite will error.** Shader files MUST be in `src/`.
22
+
23
+ Copy shader files during generation:
24
+ ```bash
25
+ cp bluedither/shaders/paper-shaders-bundle.js src/paper-shaders-bundle.js
26
+ ```
27
+
28
+ Copy tuner assets to public:
29
+ ```bash
30
+ mkdir -p public/bluedither
31
+ cp bluedither/bluedither-tuner.js public/bluedither/
32
+ cp bluedither/bluedither-tuner.css public/bluedither/
33
+ cp bluedither/bluedither-tuner-inject.js public/bluedither/
34
+ cp bluedither/tokens.json public/bluedither/
35
+ cp bluedither/tokens.defaults.json public/bluedither/
36
+ cp bluedither/dev-middleware.js public/bluedither/
37
+ ```
38
+
5
39
  ## Detection
6
40
 
7
41
  React is detected when `package.json` contains `react` in `dependencies` or `devDependencies`. Also check for:
@@ -11,76 +45,110 @@ React is detected when `package.json` contains `react` in `dependencies` or `dev
11
45
 
12
46
  ## Component Structure
13
47
 
14
- Generate separate component files matching `structure.json` nodes:
48
+ Generate all component files in `src/`:
15
49
 
16
- ### `BlueDitherTheme.jsx` (or `.tsx`)
17
- Root component wrapping the full layout. Imports and composes child components.
50
+ ### `src/App.jsx` (or modify existing)
51
+ Root component wrapping the full layout. Imports shader, CSS, and loads tuner in dev mode.
18
52
 
19
53
  ```jsx
20
- import { BlueDitherHeader } from './BlueDitherHeader';
21
- import { BlueDitherHero } from './BlueDitherHero';
54
+ import { useEffect, useRef } from 'react';
55
+ import { ShaderMount, ditheringFragmentShader, DitheringShapes, DitheringTypes, getShaderColorFromString } from './paper-shaders-bundle.js';
22
56
  import './bluedither.css';
23
57
 
24
- export function BlueDitherTheme() {
58
+ // Content from tokens.json content section
59
+ const CONTENT = { /* ... */ };
60
+
61
+ // Shader params from tokens.json shader + colors sections
62
+ const SHADER_PARAMS = { /* ... */ };
63
+
64
+ function App() {
65
+ const shaderRef = useRef(null);
66
+
67
+ // Initialize shader
68
+ useEffect(() => {
69
+ if (!shaderRef.current) return;
70
+ const mount = new ShaderMount(shaderRef.current, ditheringFragmentShader, {
71
+ u_colorFront: getShaderColorFromString(SHADER_PARAMS.colorFront),
72
+ u_colorBack: getShaderColorFromString(SHADER_PARAMS.colorBack),
73
+ u_shape: DitheringShapes[SHADER_PARAMS.shape] ?? DitheringShapes.warp,
74
+ u_type: DitheringTypes[SHADER_PARAMS.type] ?? DitheringTypes['2x2'],
75
+ u_pxSize: SHADER_PARAMS.size,
76
+ u_scale: SHADER_PARAMS.scale,
77
+ u_rotation: SHADER_PARAMS.rotation,
78
+ u_originX: 0.5, u_originY: 0.5,
79
+ u_worldWidth: 0, u_worldHeight: 0,
80
+ u_fit: 0, u_offsetX: 0, u_offsetY: 0,
81
+ }, { alpha: true, premultipliedAlpha: false }, SHADER_PARAMS.speed, 0, 2);
82
+
83
+ // CRITICAL: expose wrapper with updateParams for the tuner
84
+ window.__BD_SHADER__ = {
85
+ updateParams(params) {
86
+ const uniforms = {};
87
+ if (params.colorFront !== undefined) uniforms.u_colorFront = getShaderColorFromString(params.colorFront);
88
+ if (params.colorBack !== undefined) uniforms.u_colorBack = getShaderColorFromString(params.colorBack);
89
+ if (params.shape !== undefined) uniforms.u_shape = DitheringShapes[params.shape] ?? DitheringShapes.warp;
90
+ if (params.type !== undefined) uniforms.u_type = DitheringTypes[params.type] ?? DitheringTypes['2x2'];
91
+ if (params.size !== undefined) uniforms.u_pxSize = params.size;
92
+ if (params.scale !== undefined) uniforms.u_scale = params.scale;
93
+ if (params.rotation !== undefined) uniforms.u_rotation = parseFloat(params.rotation) || 180;
94
+ if (Object.keys(uniforms).length > 0) mount.setUniforms(uniforms);
95
+ if (params.speed !== undefined) mount.setSpeed(params.speed);
96
+ },
97
+ dispose() { mount.dispose(); },
98
+ };
99
+ return () => { window.__BD_SHADER__.dispose(); window.__BD_SHADER__ = null; };
100
+ }, []);
101
+
102
+ // Load tuner in dev mode only
103
+ useEffect(() => {
104
+ if (import.meta.env.DEV) {
105
+ const s = document.createElement('script');
106
+ s.src = '/bluedither/bluedither-tuner-inject.js';
107
+ document.body.appendChild(s);
108
+ return () => s.remove();
109
+ }
110
+ }, []);
111
+
25
112
  return (
26
113
  <div className="bd-root">
27
- <BlueDitherHero />
28
- <BlueDitherHeader />
114
+ <div className="bd-hero">
115
+ <div className="bd-hero-inner">
116
+ <div className="bd-shader-layer" ref={shaderRef} />
117
+ {/* hero content */}
118
+ </div>
119
+ </div>
120
+ <header className="bd-header">
121
+ {/* header content */}
122
+ </header>
29
123
  </div>
30
124
  );
31
125
  }
32
126
  ```
33
127
 
34
- ### `BlueDitherHeader.jsx`
35
- Navbar component with logo, nav items, and CTA.
128
+ Note: The shader uses `ShaderMount` directly from `paper-shaders-bundle.js` — do NOT create a separate shader wrapper module. Import `ShaderMount`, `ditheringFragmentShader`, `DitheringShapes`, `DitheringTypes`, and `getShaderColorFromString` directly.
36
129
 
37
- - Nav items come from `content.navItems` token array
38
- - Use `<nav>` with `<a>` elements for nav items
39
- - CTA is an `<a>` or `<button>` element
130
+ The `window.__BD_SHADER__` assignment is **required** — the tuner calls `updateParams()` on it for live shader editing. The ShaderMount instance has `setUniforms()` and `setSpeed()` methods. The tuner's `updateParams` maps token names to uniform names (e.g., `colorFront` → `u_colorFront`).
40
131
 
41
- ### `BlueDitherHero.jsx`
42
- Hero section with shader and text content.
132
+ ### `src/bluedither.css`
133
+ All CSS custom properties and `.bd-*` class rules.
43
134
 
44
- - **Shader initialization**: Use `useEffect` + `useRef` for the shader parent div. **CRITICAL**: Assign the mount to `window.__BD_SHADER__` so the tuner can update shader params live:
45
- ```jsx
46
- import { useEffect, useRef } from 'react';
47
-
48
- const shaderRef = useRef(null);
135
+ ## Vite Config
49
136
 
50
- useEffect(() => {
51
- // Dynamic import to avoid SSR issues
52
- import('./paper-shaders-bundle.js').then(({ ShaderMount, ditheringFragmentShader, getShaderColorFromString }) => {
53
- const mount = new ShaderMount(shaderRef.current, ditheringFragmentShader, uniforms, opts, speed, 0, 2);
54
- window.__BD_SHADER__ = mount;
55
- return () => { mount.dispose(); window.__BD_SHADER__ = null; };
56
- });
57
- }, []);
137
+ The `npx bluedither install` command auto-wires the Vite plugin. If it wasn't auto-wired, add manually:
138
+ ```js
139
+ import { bluedither } from './bluedither/dev-middleware.js'
140
+ export default defineConfig({ plugins: [react(), bluedither()] })
58
141
  ```
59
142
 
60
- ### `bluedither.css`
61
- All CSS custom properties and `.bd-*` class rules, identical to the vanilla `<style>` block but as an external file.
62
-
63
143
  ## TypeScript
64
144
 
65
145
  If TypeScript is detected, use `.tsx` extensions and add minimal type annotations:
66
- - Props interfaces where components accept props
67
146
  - `useRef<HTMLDivElement>(null)` for refs
68
147
 
69
148
  ## Next.js
70
149
 
71
150
  If Next.js is detected:
72
151
  - Add `"use client"` at the top of components that use `useEffect` or `useRef`
73
- - The CSS file can be imported directly in the component
74
-
75
- ## File Output
76
-
77
- | File | Contents |
78
- |------|----------|
79
- | `BlueDitherTheme.jsx/tsx` | Root layout component |
80
- | `BlueDitherHeader.jsx/tsx` | Navbar component |
81
- | `BlueDitherHero.jsx/tsx` | Hero + shader component |
82
- | `bluedither.css` | CSS custom properties + rules |
83
- | `paper-shaders-bundle.js` | Shader library (copied) |
84
152
 
85
153
  ## Content Handling
86
154