@johnfmorton/some-shade 0.1.1-beta → 0.1.4-beta

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.
@@ -1,4 +1,4 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const _=require("lit"),l=require("lit/decorators.js");function L(e){return e.getContext("webgl",{alpha:!0,premultipliedAlpha:!1,preserveDrawingBuffer:!0})}function E(e,o,r){const a=e.createShader(o);if(!a)throw new Error("Failed to create shader");if(e.shaderSource(a,r),e.compileShader(a),!e.getShaderParameter(a,e.COMPILE_STATUS)){const t=e.getShaderInfoLog(a);throw e.deleteShader(a),new Error(`Shader compile error: ${t}`)}return a}function k(e,o,r){const a=E(e,e.VERTEX_SHADER,o),t=E(e,e.FRAGMENT_SHADER,r),n=e.createProgram();if(!n)throw new Error("Failed to create program");if(e.attachShader(n,a),e.attachShader(n,t),e.linkProgram(n),!e.getProgramParameter(n,e.LINK_STATUS)){const c=e.getProgramInfoLog(n);throw e.deleteProgram(n),new Error(`Program link error: ${c}`)}e.deleteShader(a),e.deleteShader(t);const d=new Map,h=e.getProgramParameter(n,e.ACTIVE_ATTRIBUTES);for(let c=0;c<h;c++){const f=e.getActiveAttrib(n,c);f&&d.set(f.name,e.getAttribLocation(n,f.name))}const s=new Map,g=e.getProgramParameter(n,e.ACTIVE_UNIFORMS);for(let c=0;c<g;c++){const f=e.getActiveUniform(n,c);if(f){const m=e.getUniformLocation(n,f.name);m&&s.set(f.name,m)}}return{program:n,attribLocations:d,uniformLocations:s}}function D(e,o,r){for(const[a,t]of Object.entries(r)){const n=o.uniformLocations.get(a);if(n){if(typeof t=="number")e.uniform1f(n,t);else if(Array.isArray(t))switch(t.length){case 2:e.uniform2fv(n,t);break;case 3:e.uniform3fv(n,t);break;case 4:e.uniform4fv(n,t);break}}}}function z(e,o){const r=e.createTexture();if(!r)throw new Error("Failed to create texture");return e.bindTexture(e.TEXTURE_2D,r),e.texImage2D(e.TEXTURE_2D,0,e.RGBA,e.RGBA,e.UNSIGNED_BYTE,o),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.LINEAR),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.LINEAR),{texture:r,width:o.naturalWidth,height:o.naturalHeight}}function K(e,o){const r=new Float32Array([-1,-1,0,1,1,-1,1,1,-1,1,0,0,1,1,1,0]),a=e.createBuffer();if(!a)throw new Error("Failed to create buffer");e.bindBuffer(e.ARRAY_BUFFER,a),e.bufferData(e.ARRAY_BUFFER,r,e.STATIC_DRAW);const t=4*Float32Array.BYTES_PER_ELEMENT,n=o.attribLocations.get("a_position");n!==void 0&&n!==-1&&(e.enableVertexAttribArray(n),e.vertexAttribPointer(n,2,e.FLOAT,!1,t,0));const d=o.attribLocations.get("a_texCoord");return d!==void 0&&d!==-1&&(e.enableVertexAttribArray(d),e.vertexAttribPointer(d,2,e.FLOAT,!1,t,2*Float32Array.BYTES_PER_ELEMENT)),a}function P(e){e.drawArrays(e.TRIANGLE_STRIP,0,4)}const M=`precision mediump float;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const _=require("lit"),l=require("lit/decorators.js");function k(t){return t.getContext("webgl",{alpha:!0,premultipliedAlpha:!1,preserveDrawingBuffer:!0})}function E(t,o,r){const i=t.createShader(o);if(!i)throw new Error("Failed to create shader");if(t.shaderSource(i,r),t.compileShader(i),!t.getShaderParameter(i,t.COMPILE_STATUS)){const e=t.getShaderInfoLog(i);throw t.deleteShader(i),new Error(`Shader compile error: ${e}`)}return i}function D(t,o,r){const i=E(t,t.VERTEX_SHADER,o),e=E(t,t.FRAGMENT_SHADER,r),n=t.createProgram();if(!n)throw new Error("Failed to create program");if(t.attachShader(n,i),t.attachShader(n,e),t.linkProgram(n),!t.getProgramParameter(n,t.LINK_STATUS)){const d=t.getProgramInfoLog(n);throw t.deleteProgram(n),new Error(`Program link error: ${d}`)}t.deleteShader(i),t.deleteShader(e);const c=new Map,h=t.getProgramParameter(n,t.ACTIVE_ATTRIBUTES);for(let d=0;d<h;d++){const f=t.getActiveAttrib(n,d);f&&c.set(f.name,t.getAttribLocation(n,f.name))}const s=new Map,g=t.getProgramParameter(n,t.ACTIVE_UNIFORMS);for(let d=0;d<g;d++){const f=t.getActiveUniform(n,d);if(f){const m=t.getUniformLocation(n,f.name);m&&s.set(f.name,m)}}return{program:n,attribLocations:c,uniformLocations:s}}function L(t,o,r){for(const[i,e]of Object.entries(r)){const n=o.uniformLocations.get(i);if(n){if(typeof e=="number")t.uniform1f(n,e);else if(Array.isArray(e))switch(e.length){case 2:t.uniform2fv(n,e);break;case 3:t.uniform3fv(n,e);break;case 4:t.uniform4fv(n,e);break}}}}function z(t,o){const r=t.createTexture();if(!r)throw new Error("Failed to create texture");return t.bindTexture(t.TEXTURE_2D,r),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,t.RGBA,t.UNSIGNED_BYTE,o),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MIN_FILTER,t.LINEAR),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MAG_FILTER,t.LINEAR),{texture:r,width:o.naturalWidth,height:o.naturalHeight}}function M(t,o){const r=new Float32Array([-1,-1,0,1,1,-1,1,1,-1,1,0,0,1,1,1,0]),i=t.createBuffer();if(!i)throw new Error("Failed to create buffer");t.bindBuffer(t.ARRAY_BUFFER,i),t.bufferData(t.ARRAY_BUFFER,r,t.STATIC_DRAW);const e=4*Float32Array.BYTES_PER_ELEMENT,n=o.attribLocations.get("a_position");n!==void 0&&n!==-1&&(t.enableVertexAttribArray(n),t.vertexAttribPointer(n,2,t.FLOAT,!1,e,0));const c=o.attribLocations.get("a_texCoord");return c!==void 0&&c!==-1&&(t.enableVertexAttribArray(c),t.vertexAttribPointer(c,2,t.FLOAT,!1,e,2*Float32Array.BYTES_PER_ELEMENT)),i}function P(t){t.drawArrays(t.TRIANGLE_STRIP,0,4)}const O=`precision mediump float;
2
2
 
3
3
  varying vec2 v_texCoord;
4
4
 
@@ -14,6 +14,7 @@ uniform float u_showC;
14
14
  uniform float u_showM;
15
15
  uniform float u_showY;
16
16
  uniform float u_showK;
17
+ uniform float u_intensityK;
17
18
 
18
19
  // Returns the texture-space UV of the cell center for a given rotation angle
19
20
  vec2 cellCenterUV(vec2 uv, float angle) {
@@ -68,6 +69,7 @@ void main() {
68
69
  float ye = yInvK > 0.001 ? (yInvK - yRgb.b) / yInvK : 0.0;
69
70
 
70
71
  float k = 1.0 - max(max(kRgb.r, kRgb.g), kRgb.b);
72
+ k = clamp(k * u_intensityK, 0.0, 1.0);
71
73
 
72
74
  // Compute halftone dots for each channel
73
75
  float cDot = halftone(uv, u_angleC, cy, u_gridSize, u_dotRadius) * u_showC;
@@ -90,7 +92,7 @@ void main() {
90
92
  gl_Position = vec4(a_position, 0.0, 1.0);
91
93
  v_texCoord = a_texCoord;
92
94
  }
93
- `,I={name:"halftone-cmyk",fragmentShader:M,vertexShader:y,uniforms:[{name:"u_dotRadius",type:"float",default:4,attribute:"dot-radius"},{name:"u_gridSize",type:"float",default:8,attribute:"grid-size"},{name:"u_angleC",type:"float",default:15,attribute:"angle-c"},{name:"u_angleM",type:"float",default:75,attribute:"angle-m"},{name:"u_angleY",type:"float",default:0,attribute:"angle-y"},{name:"u_angleK",type:"float",default:45,attribute:"angle-k"},{name:"u_showC",type:"float",default:1,attribute:"show-c"},{name:"u_showM",type:"float",default:1,attribute:"show-m"},{name:"u_showY",type:"float",default:1,attribute:"show-y"},{name:"u_showK",type:"float",default:1,attribute:"show-k"}]},O=`precision mediump float;
95
+ `,I={name:"halftone-cmyk",fragmentShader:O,vertexShader:y,uniforms:[{name:"u_dotRadius",type:"float",default:4,attribute:"dot-radius"},{name:"u_gridSize",type:"float",default:8,attribute:"grid-size"},{name:"u_angleC",type:"float",default:15,attribute:"angle-c"},{name:"u_angleM",type:"float",default:75,attribute:"angle-m"},{name:"u_angleY",type:"float",default:0,attribute:"angle-y"},{name:"u_angleK",type:"float",default:45,attribute:"angle-k"},{name:"u_showC",type:"float",default:1,attribute:"show-c"},{name:"u_showM",type:"float",default:1,attribute:"show-m"},{name:"u_showY",type:"float",default:1,attribute:"show-y"},{name:"u_showK",type:"float",default:1,attribute:"show-k"},{name:"u_intensityK",type:"float",default:1,attribute:"intensity-k"}]},V=`precision mediump float;
94
96
 
95
97
  varying vec2 v_texCoord;
96
98
 
@@ -132,7 +134,7 @@ void main() {
132
134
 
133
135
  gl_FragColor = vec4(result, color.a);
134
136
  }
135
- `,V={name:"halftone-duotone",fragmentShader:O,vertexShader:y,uniforms:[{name:"u_dotRadius",type:"float",default:4,attribute:"dot-radius"},{name:"u_gridSize",type:"float",default:8,attribute:"grid-size"},{name:"u_duotoneColor",type:"vec3",default:[0,.6,.8],attribute:"duotone-color"},{name:"u_angle",type:"float",default:0,attribute:"angle"}]},F=`precision mediump float;
137
+ `,W={name:"halftone-duotone",fragmentShader:V,vertexShader:y,uniforms:[{name:"u_dotRadius",type:"float",default:4,attribute:"dot-radius"},{name:"u_gridSize",type:"float",default:8,attribute:"grid-size"},{name:"u_duotoneColor",type:"vec3",default:[0,.6,.8],attribute:"duotone-color"},{name:"u_angle",type:"float",default:0,attribute:"angle"}]},N=`precision mediump float;
136
138
 
137
139
  varying vec2 v_texCoord;
138
140
 
@@ -188,7 +190,7 @@ void main() {
188
190
 
189
191
  gl_FragColor = vec4(result, 1.0);
190
192
  }
191
- `,N={name:"dot-grid",fragmentShader:F,vertexShader:y,uniforms:[{name:"u_dotRadius",type:"float",default:4,attribute:"dot-radius"},{name:"u_gridSize",type:"float",default:8,attribute:"grid-size"},{name:"u_dotOffset",type:"vec2",default:[.5,.5],attribute:"dot-offset"},{name:"u_bgColor",type:"vec3",default:[1,1,1],attribute:"bg-color"},{name:"u_angle",type:"float",default:0,attribute:"angle"}]},Y=`precision mediump float;
193
+ `,F={name:"dot-grid",fragmentShader:N,vertexShader:y,uniforms:[{name:"u_dotRadius",type:"float",default:4,attribute:"dot-radius"},{name:"u_gridSize",type:"float",default:8,attribute:"grid-size"},{name:"u_dotOffset",type:"vec2",default:[.5,.5],attribute:"dot-offset"},{name:"u_bgColor",type:"vec3",default:[1,1,1],attribute:"bg-color"},{name:"u_angle",type:"float",default:0,attribute:"angle"}]},B=`precision mediump float;
192
194
 
193
195
  varying vec2 v_texCoord;
194
196
 
@@ -204,6 +206,8 @@ uniform float u_showCool;
204
206
  uniform float u_showK;
205
207
  uniform vec3 u_warmColor;
206
208
  uniform vec3 u_coolColor;
209
+ uniform float u_blendMode;
210
+ uniform float u_intensityK;
207
211
 
208
212
  float halftone(vec2 uv, float angle, float channelValue, float gridSize, float dotRadius) {
209
213
  float rad = radians(angle);
@@ -230,32 +234,58 @@ void main() {
230
234
 
231
235
  // Black channel: derived from overall darkness
232
236
  float k = 1.0 - max(warmSep, coolSep);
237
+ k = clamp(k * u_intensityK, 0.0, 1.0);
233
238
 
234
239
  // Halftone dots for each channel
235
240
  float warmDot = halftone(uv, u_angleWarm, warmSep, u_gridSize, u_dotRadius) * u_showWarm;
236
241
  float coolDot = halftone(uv, u_angleCool, coolSep, u_gridSize, u_dotRadius) * u_showCool;
237
242
  float kDot = halftone(uv, u_angleK, k, u_gridSize, u_dotRadius) * u_showK;
238
243
 
239
- // Subtractive mixing: start with white paper, subtract dye layers
240
- vec3 paper = vec3(1.0);
241
- paper -= warmDot * (vec3(1.0) - u_warmColor);
242
- paper -= coolDot * (vec3(1.0) - u_coolColor);
243
- paper *= (1.0 - kDot);
244
+ // Blend modes affect how warm and cool dots combine where they overlap.
245
+ // All modes use white paper; individual dots look the same.
246
+ // Only the overlap regions differ between modes.
247
+ vec3 overlap;
248
+ if (u_blendMode < 0.5) {
249
+ // Subtractive: dye overlap absorbs more light (darker)
250
+ overlap = u_warmColor + u_coolColor - vec3(1.0);
251
+ } else if (u_blendMode < 1.5) {
252
+ // Additive: light overlap adds up (brighter)
253
+ overlap = u_warmColor + u_coolColor;
254
+ } else {
255
+ // Screen: soft additive overlap with natural clamping
256
+ overlap = vec3(1.0) - (vec3(1.0) - u_warmColor) * (vec3(1.0) - u_coolColor);
257
+ }
258
+
259
+ // Decompose into four halftone regions
260
+ float onlyWarm = warmDot * (1.0 - coolDot);
261
+ float onlyCool = coolDot * (1.0 - warmDot);
262
+ float both = warmDot * coolDot;
263
+ float neither = (1.0 - warmDot) * (1.0 - coolDot);
264
+
265
+ // Composite: white paper base, colored dots, blend-mode-dependent overlap
266
+ vec3 result = neither * vec3(1.0)
267
+ + onlyWarm * u_warmColor
268
+ + onlyCool * u_coolColor
269
+ + both * overlap;
270
+
271
+ // K channel darkening with intensity control
272
+ result *= (1.0 - kDot);
244
273
 
245
- gl_FragColor = vec4(clamp(paper, 0.0, 1.0), color.a);
274
+ gl_FragColor = vec4(clamp(result, 0.0, 1.0), color.a);
246
275
  }
247
- `,B={name:"technicolor-2strip",fragmentShader:Y,vertexShader:y,uniforms:[{name:"u_dotRadius",type:"float",default:4,attribute:"dot-radius"},{name:"u_gridSize",type:"float",default:8,attribute:"grid-size"},{name:"u_angleWarm",type:"float",default:15,attribute:"angle-warm"},{name:"u_angleCool",type:"float",default:75,attribute:"angle-cool"},{name:"u_angleK",type:"float",default:45,attribute:"angle-k"},{name:"u_showWarm",type:"float",default:1,attribute:"show-warm"},{name:"u_showCool",type:"float",default:1,attribute:"show-cool"},{name:"u_showK",type:"float",default:1,attribute:"show-k"},{name:"u_warmColor",type:"vec3",default:[.85,.25,.06],attribute:"warm-color"},{name:"u_coolColor",type:"vec3",default:[.05,.65,.6],attribute:"cool-color"}]},w=new Map;function p(e){w.set(e.name,e)}function U(e){return w.get(e)}function G(){return Array.from(w.keys())}p(I);p(V);p(N);p(B);var X=Object.defineProperty,u=(e,o,r,a)=>{for(var t=void 0,n=e.length-1,d;n>=0;n--)(d=e[n])&&(t=d(o,r,t)||t);return t&&X(o,r,t),t};const $=2;let T=Promise.resolve();function A(e){const o=T.then(e,e);return T=o,o}const q=new Set(["effect","dotRadius","gridSize","angleC","angleM","angleY","angleK","showC","showM","showY","showK","duotoneColor","angle","dotOffsetX","dotOffsetY","bgColor","angleWarm","angleCool","showWarm","showCool","warmColor","coolColor"]),R=class R extends _.LitElement{constructor(){super(...arguments),this.src="",this.effect="halftone-cmyk",this.dotRadius=4,this.gridSize=8,this.angleC=15,this.angleM=75,this.angleY=0,this.angleK=45,this.showC=1,this.showM=1,this.showY=1,this.showK=1,this.duotoneColor="#0099cc",this.angle=0,this.dotOffsetX=.5,this.dotOffsetY=.5,this.bgColor="#ffffff",this.angleWarm=15,this.angleCool=75,this.showWarm=1,this.showCool=1,this.warmColor="#d94010",this.coolColor="#0da699",this.gateWeave=0,this.loadingBlur=0,this._webglAvailable=!0,this._snapshotUrl="",this._snapshotLoaded=!1,this._image=null,this._observer=null,this._resizeObserver=null,this._lastClientWidth=0,this._visible=!1,this._needsRender=!1,this._gateWeaveRaf=0,this._gateWeaveTime=0}render(){if(!this._webglAvailable)return _.html`<img src=${this.src} alt="" />`;const o=this.loadingBlur>0?`filter: blur(${this.loadingBlur}px)`:"";return _.html`
276
+ `,Y={name:"technicolor-2strip",fragmentShader:B,vertexShader:y,uniforms:[{name:"u_dotRadius",type:"float",default:7,attribute:"dot-radius"},{name:"u_gridSize",type:"float",default:10,attribute:"grid-size"},{name:"u_angleWarm",type:"float",default:15,attribute:"angle-warm"},{name:"u_angleCool",type:"float",default:75,attribute:"angle-cool"},{name:"u_angleK",type:"float",default:45,attribute:"angle-k"},{name:"u_showWarm",type:"float",default:1,attribute:"show-warm"},{name:"u_showCool",type:"float",default:1,attribute:"show-cool"},{name:"u_showK",type:"float",default:1,attribute:"show-k"},{name:"u_warmColor",type:"vec3",default:[.85,.25,.06],attribute:"warm-color"},{name:"u_coolColor",type:"vec3",default:[.05,.65,.6],attribute:"cool-color"},{name:"u_blendMode",type:"float",default:1,attribute:"blend-mode"},{name:"u_intensityK",type:"float",default:1,attribute:"intensity-k"}]},w=new Map;function p(t){w.set(t.name,t)}function U(t){return w.get(t)}function X(){return Array.from(w.keys())}p(I);p(W);p(F);p(Y);var $=Object.defineProperty,u=(t,o,r,i)=>{for(var e=void 0,n=t.length-1,c;n>=0;n--)(c=t[n])&&(e=c(o,r,e)||e);return e&&$(o,r,e),e};const G=2;let T=Promise.resolve();function A(t){const o=T.then(t,t);return T=o,o}const H=new Set(["effect","dotRadius","gridSize","angleC","angleM","angleY","angleK","showC","showM","showY","showK","intensityK","duotoneColor","angle","dotOffsetX","dotOffsetY","bgColor","angleWarm","angleCool","showWarm","showCool","warmColor","coolColor","blendMode"]),C=class C extends _.LitElement{constructor(){super(...arguments),this.src="",this.effect="halftone-cmyk",this.dotRadius=4,this.gridSize=8,this.angleC=15,this.angleM=75,this.angleY=0,this.angleK=45,this.showC=1,this.showM=1,this.showY=1,this.showK=1,this.intensityK=1,this.duotoneColor="#0099cc",this.angle=0,this.dotOffsetX=.5,this.dotOffsetY=.5,this.bgColor="#ffffff",this.angleWarm=15,this.angleCool=75,this.showWarm=1,this.showCool=1,this.warmColor="#d94010",this.coolColor="#0da699",this.blendMode=1,this.loadingBlur=0,this._webglAvailable=!0,this._snapshotUrl="",this._snapshotLoaded=!1,this._image=null,this._observer=null,this._resizeObserver=null,this._lastClientWidth=0,this._visible=!1,this._needsRender=!1}render(){if(!this._webglAvailable)return _.html`<img src=${this.src} alt="" />`;const o=this.loadingBlur>0?`filter: blur(${this.loadingBlur}px)`:"";return _.html`
248
277
  <img src=${this.src} alt="" style=${o} />
249
278
  ${this._snapshotUrl?_.html`<img
250
279
  class="snapshot${this._snapshotLoaded?" loaded":""}"
251
280
  src=${this._snapshotUrl}
252
281
  @load=${this._onSnapshotLoad}
253
282
  alt="" />`:""}
254
- `}connectedCallback(){super.connectedCallback(),this._observer=new IntersectionObserver(o=>{var a;const r=this._visible;this._visible=((a=o[0])==null?void 0:a.isIntersecting)??!1,this._visible&&!r&&this._needsRender&&(this._needsRender=!1,A(()=>this._renderEffect()))},{rootMargin:"200px"}),this._observer.observe(this),this._resizeObserver=new ResizeObserver(()=>{if(!this._image)return;const o=this.clientWidth;o>0&&o!==this._lastClientWidth&&(this._lastClientWidth=o,this._scheduleRender())}),this._resizeObserver.observe(this)}updated(o){if(o.has("src")&&this.src){this._loadImage(this.src);return}if(!this._image)return;[...o.keys()].some(a=>q.has(a))&&this._scheduleRender(),o.has("gateWeave")&&this._updateGateWeave()}disconnectedCallback(){var o,r;super.disconnectedCallback(),(o=this._observer)==null||o.disconnect(),(r=this._resizeObserver)==null||r.disconnect(),this._stopGateWeave(),this._revokeSnapshot()}_loadImage(o){const r=new Image;r.crossOrigin="anonymous",r.onload=()=>{this._image=r,this._scheduleRender()},r.onerror=()=>{console.warn(`[some-shade] Failed to load image: ${o}`)},r.src=o}_scheduleRender(){this._visible?A(()=>this._renderEffect()):this._needsRender=!0}async _renderEffect(){var g;if(!this._image)return;const o=U(this.effect);if(!o){console.warn(`[some-shade] Unknown effect: ${this.effect}`);return}const r=Math.min(window.devicePixelRatio||1,$),a=this._image.naturalWidth,t=this._image.naturalHeight,n=this.clientWidth||a,d=Math.max(1,a/n);this._lastClientWidth=this.clientWidth;const h=document.createElement("canvas");h.width=a*r,h.height=t*r;const s=L(h);if(!s){this._webglAvailable=!1;return}try{const c=k(s,o.vertexShader,o.fragmentShader);s.useProgram(c.program);const f=z(s,this._image),m=K(s,c);s.viewport(0,0,h.width,h.height),s.clearColor(0,0,0,0),s.clear(s.COLOR_BUFFER_BIT),s.activeTexture(s.TEXTURE0),s.bindTexture(s.TEXTURE_2D,f.texture);const C=c.uniformLocations.get("u_image");C&&s.uniform1i(C,0),D(s,c,this._getUniformValues(f,r,d)),s.bindBuffer(s.ARRAY_BUFFER,m);const S=4*Float32Array.BYTES_PER_ELEMENT,v=c.attribLocations.get("a_position");v!==void 0&&v!==-1&&(s.enableVertexAttribArray(v),s.vertexAttribPointer(v,2,s.FLOAT,!1,S,0));const b=c.attribLocations.get("a_texCoord");b!==void 0&&b!==-1&&(s.enableVertexAttribArray(b),s.vertexAttribPointer(b,2,s.FLOAT,!1,S,2*Float32Array.BYTES_PER_ELEMENT)),P(s);const x=await new Promise(W=>h.toBlob(W));s.deleteTexture(f.texture),s.deleteProgram(c.program),s.deleteBuffer(m),x&&(this._snapshotLoaded=!1,this._revokeSnapshot(),this._snapshotUrl=URL.createObjectURL(x))}finally{(g=s.getExtension("WEBGL_lose_context"))==null||g.loseContext()}}_onSnapshotLoad(){this._snapshotLoaded=!0}replayTransition(o=500){this._snapshotUrl&&(this._snapshotLoaded=!1,this.updateComplete.then(()=>{setTimeout(()=>{this._snapshotLoaded=!0},o)}))}_revokeSnapshot(){this._snapshotUrl&&(URL.revokeObjectURL(this._snapshotUrl),this._snapshotUrl="")}_getUniformValues(o,r,a){const t={};return t.u_resolution=[o.width*r,o.height*r],t.u_dotRadius=this.dotRadius*a,t.u_gridSize=this.gridSize*a,this.effect==="halftone-cmyk"?(t.u_angleC=this.angleC,t.u_angleM=this.angleM,t.u_angleY=this.angleY,t.u_angleK=this.angleK,t.u_showC=this.showC,t.u_showM=this.showM,t.u_showY=this.showY,t.u_showK=this.showK):this.effect==="halftone-duotone"?(t.u_duotoneColor=this._parseHexColor(this.duotoneColor),t.u_angle=this.angle):this.effect==="dot-grid"?(t.u_dotOffset=[this.dotOffsetX,this.dotOffsetY],t.u_bgColor=this._parseHexColor(this.bgColor),t.u_angle=this.angle):this.effect==="technicolor-2strip"&&(t.u_angleWarm=this.angleWarm,t.u_angleCool=this.angleCool,t.u_angleK=this.angleK,t.u_showWarm=this.showWarm,t.u_showCool=this.showCool,t.u_showK=this.showK,t.u_warmColor=this._parseHexColor(this.warmColor),t.u_coolColor=this._parseHexColor(this.coolColor)),t}_updateGateWeave(){if(this._stopGateWeave(),this.gateWeave<=0){const a=this.renderRoot.querySelector("img.snapshot");a&&(a.style.transform="");return}const o=1e3/12,r=a=>{if(a-this._gateWeaveTime>=o){this._gateWeaveTime=a;const t=this.renderRoot.querySelector("img.snapshot");if(t){const n=(Math.random()-.5)*2*this.gateWeave,d=(Math.random()-.5)*2*this.gateWeave,h=1+this.gateWeave*.003;t.style.transform=`translate(${n}px, ${d}px) scale(${h})`}}this._gateWeaveRaf=requestAnimationFrame(r)};this._gateWeaveRaf=requestAnimationFrame(r)}_stopGateWeave(){this._gateWeaveRaf&&(cancelAnimationFrame(this._gateWeaveRaf),this._gateWeaveRaf=0)}_parseHexColor(o){const r=o.replace("#",""),a=parseInt(r.substring(0,2),16)/255,t=parseInt(r.substring(2,4),16)/255,n=parseInt(r.substring(4,6),16)/255;return[a,t,n]}};R.styles=_.css`
283
+ `}connectedCallback(){super.connectedCallback(),this._observer=new IntersectionObserver(o=>{var i;const r=this._visible;this._visible=((i=o[0])==null?void 0:i.isIntersecting)??!1,this._visible&&!r&&this._needsRender&&(this._needsRender=!1,A(()=>this._renderEffect()))},{rootMargin:"200px"}),this._observer.observe(this),this._resizeObserver=new ResizeObserver(()=>{if(!this._image)return;const o=this.clientWidth;o>0&&o!==this._lastClientWidth&&(this._lastClientWidth=o,this._scheduleRender())}),this._resizeObserver.observe(this)}updated(o){if(o.has("src")&&this.src){this._loadImage(this.src);return}if(!this._image)return;[...o.keys()].some(i=>H.has(i))&&this._scheduleRender()}disconnectedCallback(){var o,r;super.disconnectedCallback(),(o=this._observer)==null||o.disconnect(),(r=this._resizeObserver)==null||r.disconnect(),this._revokeSnapshot()}_loadImage(o){const r=new Image;r.crossOrigin="anonymous",r.onload=()=>{this._image=r,this._scheduleRender()},r.onerror=()=>{console.warn(`[some-shade] Failed to load image: ${o}`)},r.src=o}_scheduleRender(){this._visible?A(()=>this._renderEffect()):this._needsRender=!0}async _renderEffect(){var g;if(!this._image)return;const o=U(this.effect);if(!o){console.warn(`[some-shade] Unknown effect: ${this.effect}`);return}const r=Math.min(window.devicePixelRatio||1,G),i=this._image.naturalWidth,e=this._image.naturalHeight,n=this.clientWidth||i,c=Math.max(1,i/n);this._lastClientWidth=this.clientWidth;const h=document.createElement("canvas");h.width=i*r,h.height=e*r;const s=k(h);if(!s){this._webglAvailable=!1;return}try{const d=D(s,o.vertexShader,o.fragmentShader);s.useProgram(d.program);const f=z(s,this._image),m=M(s,d);s.viewport(0,0,h.width,h.height),s.clearColor(0,0,0,0),s.clear(s.COLOR_BUFFER_BIT),s.activeTexture(s.TEXTURE0),s.bindTexture(s.TEXTURE_2D,f.texture);const R=d.uniformLocations.get("u_image");R&&s.uniform1i(R,0),L(s,d,this._getUniformValues(f,r,c)),s.bindBuffer(s.ARRAY_BUFFER,m);const S=4*Float32Array.BYTES_PER_ELEMENT,b=d.attribLocations.get("a_position");b!==void 0&&b!==-1&&(s.enableVertexAttribArray(b),s.vertexAttribPointer(b,2,s.FLOAT,!1,S,0));const v=d.attribLocations.get("a_texCoord");v!==void 0&&v!==-1&&(s.enableVertexAttribArray(v),s.vertexAttribPointer(v,2,s.FLOAT,!1,S,2*Float32Array.BYTES_PER_ELEMENT)),P(s);const x=await new Promise(K=>h.toBlob(K));s.deleteTexture(f.texture),s.deleteProgram(d.program),s.deleteBuffer(m),x&&(this._snapshotLoaded=!1,this._revokeSnapshot(),this._snapshotUrl=URL.createObjectURL(x))}finally{(g=s.getExtension("WEBGL_lose_context"))==null||g.loseContext()}}_onSnapshotLoad(){this._snapshotLoaded=!0}replayTransition(o=500){this._snapshotUrl&&(this._snapshotLoaded=!1,this.updateComplete.then(()=>{setTimeout(()=>{this._snapshotLoaded=!0},o)}))}_revokeSnapshot(){this._snapshotUrl&&(URL.revokeObjectURL(this._snapshotUrl),this._snapshotUrl="")}_getUniformValues(o,r,i){const e={};return e.u_resolution=[o.width*r,o.height*r],e.u_dotRadius=this.dotRadius*i,e.u_gridSize=this.gridSize*i,this.effect==="halftone-cmyk"?(e.u_angleC=this.angleC,e.u_angleM=this.angleM,e.u_angleY=this.angleY,e.u_angleK=this.angleK,e.u_showC=this.showC,e.u_showM=this.showM,e.u_showY=this.showY,e.u_showK=this.showK,e.u_intensityK=this.intensityK):this.effect==="halftone-duotone"?(e.u_duotoneColor=this._parseHexColor(this.duotoneColor),e.u_angle=this.angle):this.effect==="dot-grid"?(e.u_dotOffset=[this.dotOffsetX,this.dotOffsetY],e.u_bgColor=this._parseHexColor(this.bgColor),e.u_angle=this.angle):this.effect==="technicolor-2strip"&&(e.u_angleWarm=this.angleWarm,e.u_angleCool=this.angleCool,e.u_angleK=this.angleK,e.u_showWarm=this.showWarm,e.u_showCool=this.showCool,e.u_showK=this.showK,e.u_warmColor=this._parseHexColor(this.warmColor),e.u_coolColor=this._parseHexColor(this.coolColor),e.u_blendMode=this.blendMode,e.u_intensityK=this.intensityK),e}_parseHexColor(o){const r=o.replace("#",""),i=parseInt(r.substring(0,2),16)/255,e=parseInt(r.substring(2,4),16)/255,n=parseInt(r.substring(4,6),16)/255;return[i,e,n]}};C.styles=_.css`
255
284
  :host {
256
285
  display: block;
257
286
  position: relative;
258
287
  overflow: hidden;
288
+ max-width: 100%;
259
289
  }
260
290
  img {
261
291
  display: block;
@@ -273,4 +303,4 @@ void main() {
273
303
  img.snapshot.loaded {
274
304
  opacity: 1;
275
305
  }
276
- `;let i=R;u([l.property()],i.prototype,"src");u([l.property()],i.prototype,"effect");u([l.property({type:Number,attribute:"dot-radius"})],i.prototype,"dotRadius");u([l.property({type:Number,attribute:"grid-size"})],i.prototype,"gridSize");u([l.property({type:Number,attribute:"angle-c"})],i.prototype,"angleC");u([l.property({type:Number,attribute:"angle-m"})],i.prototype,"angleM");u([l.property({type:Number,attribute:"angle-y"})],i.prototype,"angleY");u([l.property({type:Number,attribute:"angle-k"})],i.prototype,"angleK");u([l.property({type:Number,attribute:"show-c"})],i.prototype,"showC");u([l.property({type:Number,attribute:"show-m"})],i.prototype,"showM");u([l.property({type:Number,attribute:"show-y"})],i.prototype,"showY");u([l.property({type:Number,attribute:"show-k"})],i.prototype,"showK");u([l.property({attribute:"duotone-color"})],i.prototype,"duotoneColor");u([l.property({type:Number})],i.prototype,"angle");u([l.property({type:Number,attribute:"dot-offset-x"})],i.prototype,"dotOffsetX");u([l.property({type:Number,attribute:"dot-offset-y"})],i.prototype,"dotOffsetY");u([l.property({attribute:"bg-color"})],i.prototype,"bgColor");u([l.property({type:Number,attribute:"angle-warm"})],i.prototype,"angleWarm");u([l.property({type:Number,attribute:"angle-cool"})],i.prototype,"angleCool");u([l.property({type:Number,attribute:"show-warm"})],i.prototype,"showWarm");u([l.property({type:Number,attribute:"show-cool"})],i.prototype,"showCool");u([l.property({attribute:"warm-color"})],i.prototype,"warmColor");u([l.property({attribute:"cool-color"})],i.prototype,"coolColor");u([l.property({type:Number,attribute:"gate-weave"})],i.prototype,"gateWeave");u([l.property({type:Number,attribute:"loading-blur"})],i.prototype,"loadingBlur");u([l.state()],i.prototype,"_webglAvailable");u([l.state()],i.prototype,"_snapshotUrl");u([l.state()],i.prototype,"_snapshotLoaded");customElements.get("some-shade-image")||customElements.define("some-shade-image",i);exports.SomeShadeImage=i;exports.get=U;exports.list=G;exports.register=p;
306
+ `;let a=C;u([l.property()],a.prototype,"src");u([l.property()],a.prototype,"effect");u([l.property({type:Number,attribute:"dot-radius"})],a.prototype,"dotRadius");u([l.property({type:Number,attribute:"grid-size"})],a.prototype,"gridSize");u([l.property({type:Number,attribute:"angle-c"})],a.prototype,"angleC");u([l.property({type:Number,attribute:"angle-m"})],a.prototype,"angleM");u([l.property({type:Number,attribute:"angle-y"})],a.prototype,"angleY");u([l.property({type:Number,attribute:"angle-k"})],a.prototype,"angleK");u([l.property({type:Number,attribute:"show-c"})],a.prototype,"showC");u([l.property({type:Number,attribute:"show-m"})],a.prototype,"showM");u([l.property({type:Number,attribute:"show-y"})],a.prototype,"showY");u([l.property({type:Number,attribute:"show-k"})],a.prototype,"showK");u([l.property({type:Number,attribute:"intensity-k"})],a.prototype,"intensityK");u([l.property({attribute:"duotone-color"})],a.prototype,"duotoneColor");u([l.property({type:Number})],a.prototype,"angle");u([l.property({type:Number,attribute:"dot-offset-x"})],a.prototype,"dotOffsetX");u([l.property({type:Number,attribute:"dot-offset-y"})],a.prototype,"dotOffsetY");u([l.property({attribute:"bg-color"})],a.prototype,"bgColor");u([l.property({type:Number,attribute:"angle-warm"})],a.prototype,"angleWarm");u([l.property({type:Number,attribute:"angle-cool"})],a.prototype,"angleCool");u([l.property({type:Number,attribute:"show-warm"})],a.prototype,"showWarm");u([l.property({type:Number,attribute:"show-cool"})],a.prototype,"showCool");u([l.property({attribute:"warm-color"})],a.prototype,"warmColor");u([l.property({attribute:"cool-color"})],a.prototype,"coolColor");u([l.property({type:Number,attribute:"blend-mode"})],a.prototype,"blendMode");u([l.property({type:Number,attribute:"loading-blur"})],a.prototype,"loadingBlur");u([l.state()],a.prototype,"_webglAvailable");u([l.state()],a.prototype,"_snapshotUrl");u([l.state()],a.prototype,"_snapshotLoaded");customElements.get("some-shade-image")||customElements.define("some-shade-image",a);exports.SomeShadeImage=a;exports.get=U;exports.list=X;exports.register=p;
@@ -1,72 +1,72 @@
1
- import { LitElement as L, css as k, html as y } from "lit";
1
+ import { LitElement as k, css as D, html as y } from "lit";
2
2
  import { property as u, state as w } from "lit/decorators.js";
3
- function D(e) {
4
- return e.getContext("webgl", {
3
+ function L(t) {
4
+ return t.getContext("webgl", {
5
5
  alpha: !0,
6
6
  premultipliedAlpha: !1,
7
7
  preserveDrawingBuffer: !0
8
8
  });
9
9
  }
10
- function T(e, o, a) {
11
- const r = e.createShader(o);
12
- if (!r) throw new Error("Failed to create shader");
13
- if (e.shaderSource(r, a), e.compileShader(r), !e.getShaderParameter(r, e.COMPILE_STATUS)) {
14
- const t = e.getShaderInfoLog(r);
15
- throw e.deleteShader(r), new Error(`Shader compile error: ${t}`);
10
+ function T(t, o, n) {
11
+ const i = t.createShader(o);
12
+ if (!i) throw new Error("Failed to create shader");
13
+ if (t.shaderSource(i, n), t.compileShader(i), !t.getShaderParameter(i, t.COMPILE_STATUS)) {
14
+ const e = t.getShaderInfoLog(i);
15
+ throw t.deleteShader(i), new Error(`Shader compile error: ${e}`);
16
16
  }
17
- return r;
17
+ return i;
18
18
  }
19
- function z(e, o, a) {
20
- const r = T(e, e.VERTEX_SHADER, o), t = T(e, e.FRAGMENT_SHADER, a), n = e.createProgram();
21
- if (!n) throw new Error("Failed to create program");
22
- if (e.attachShader(n, r), e.attachShader(n, t), e.linkProgram(n), !e.getProgramParameter(n, e.LINK_STATUS)) {
23
- const c = e.getProgramInfoLog(n);
24
- throw e.deleteProgram(n), new Error(`Program link error: ${c}`);
19
+ function z(t, o, n) {
20
+ const i = T(t, t.VERTEX_SHADER, o), e = T(t, t.FRAGMENT_SHADER, n), r = t.createProgram();
21
+ if (!r) throw new Error("Failed to create program");
22
+ if (t.attachShader(r, i), t.attachShader(r, e), t.linkProgram(r), !t.getProgramParameter(r, t.LINK_STATUS)) {
23
+ const d = t.getProgramInfoLog(r);
24
+ throw t.deleteProgram(r), new Error(`Program link error: ${d}`);
25
25
  }
26
- e.deleteShader(r), e.deleteShader(t);
27
- const d = /* @__PURE__ */ new Map(), h = e.getProgramParameter(n, e.ACTIVE_ATTRIBUTES);
28
- for (let c = 0; c < h; c++) {
29
- const f = e.getActiveAttrib(n, c);
30
- f && d.set(f.name, e.getAttribLocation(n, f.name));
26
+ t.deleteShader(i), t.deleteShader(e);
27
+ const c = /* @__PURE__ */ new Map(), h = t.getProgramParameter(r, t.ACTIVE_ATTRIBUTES);
28
+ for (let d = 0; d < h; d++) {
29
+ const f = t.getActiveAttrib(r, d);
30
+ f && c.set(f.name, t.getAttribLocation(r, f.name));
31
31
  }
32
- const i = /* @__PURE__ */ new Map(), _ = e.getProgramParameter(n, e.ACTIVE_UNIFORMS);
33
- for (let c = 0; c < _; c++) {
34
- const f = e.getActiveUniform(n, c);
32
+ const s = /* @__PURE__ */ new Map(), _ = t.getProgramParameter(r, t.ACTIVE_UNIFORMS);
33
+ for (let d = 0; d < _; d++) {
34
+ const f = t.getActiveUniform(r, d);
35
35
  if (f) {
36
- const m = e.getUniformLocation(n, f.name);
37
- m && i.set(f.name, m);
36
+ const m = t.getUniformLocation(r, f.name);
37
+ m && s.set(f.name, m);
38
38
  }
39
39
  }
40
- return { program: n, attribLocations: d, uniformLocations: i };
40
+ return { program: r, attribLocations: c, uniformLocations: s };
41
41
  }
42
- function K(e, o, a) {
43
- for (const [r, t] of Object.entries(a)) {
44
- const n = o.uniformLocations.get(r);
45
- if (n) {
46
- if (typeof t == "number")
47
- e.uniform1f(n, t);
48
- else if (Array.isArray(t))
49
- switch (t.length) {
42
+ function M(t, o, n) {
43
+ for (const [i, e] of Object.entries(n)) {
44
+ const r = o.uniformLocations.get(i);
45
+ if (r) {
46
+ if (typeof e == "number")
47
+ t.uniform1f(r, e);
48
+ else if (Array.isArray(e))
49
+ switch (e.length) {
50
50
  case 2:
51
- e.uniform2fv(n, t);
51
+ t.uniform2fv(r, e);
52
52
  break;
53
53
  case 3:
54
- e.uniform3fv(n, t);
54
+ t.uniform3fv(r, e);
55
55
  break;
56
56
  case 4:
57
- e.uniform4fv(n, t);
57
+ t.uniform4fv(r, e);
58
58
  break;
59
59
  }
60
60
  }
61
61
  }
62
62
  }
63
- function P(e, o) {
64
- const a = e.createTexture();
65
- if (!a) throw new Error("Failed to create texture");
66
- return e.bindTexture(e.TEXTURE_2D, a), e.texImage2D(e.TEXTURE_2D, 0, e.RGBA, e.RGBA, e.UNSIGNED_BYTE, o), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_S, e.CLAMP_TO_EDGE), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_T, e.CLAMP_TO_EDGE), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MIN_FILTER, e.LINEAR), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MAG_FILTER, e.LINEAR), { texture: a, width: o.naturalWidth, height: o.naturalHeight };
63
+ function P(t, o) {
64
+ const n = t.createTexture();
65
+ if (!n) throw new Error("Failed to create texture");
66
+ return t.bindTexture(t.TEXTURE_2D, n), t.texImage2D(t.TEXTURE_2D, 0, t.RGBA, t.RGBA, t.UNSIGNED_BYTE, o), t.texParameteri(t.TEXTURE_2D, t.TEXTURE_WRAP_S, t.CLAMP_TO_EDGE), t.texParameteri(t.TEXTURE_2D, t.TEXTURE_WRAP_T, t.CLAMP_TO_EDGE), t.texParameteri(t.TEXTURE_2D, t.TEXTURE_MIN_FILTER, t.LINEAR), t.texParameteri(t.TEXTURE_2D, t.TEXTURE_MAG_FILTER, t.LINEAR), { texture: n, width: o.naturalWidth, height: o.naturalHeight };
67
67
  }
68
- function M(e, o) {
69
- const a = new Float32Array([
68
+ function O(t, o) {
69
+ const n = new Float32Array([
70
70
  // pos.x pos.y tex.s tex.t
71
71
  -1,
72
72
  -1,
@@ -84,18 +84,18 @@ function M(e, o) {
84
84
  1,
85
85
  1,
86
86
  0
87
- ]), r = e.createBuffer();
88
- if (!r) throw new Error("Failed to create buffer");
89
- e.bindBuffer(e.ARRAY_BUFFER, r), e.bufferData(e.ARRAY_BUFFER, a, e.STATIC_DRAW);
90
- const t = 4 * Float32Array.BYTES_PER_ELEMENT, n = o.attribLocations.get("a_position");
91
- n !== void 0 && n !== -1 && (e.enableVertexAttribArray(n), e.vertexAttribPointer(n, 2, e.FLOAT, !1, t, 0));
92
- const d = o.attribLocations.get("a_texCoord");
93
- return d !== void 0 && d !== -1 && (e.enableVertexAttribArray(d), e.vertexAttribPointer(d, 2, e.FLOAT, !1, t, 2 * Float32Array.BYTES_PER_ELEMENT)), r;
87
+ ]), i = t.createBuffer();
88
+ if (!i) throw new Error("Failed to create buffer");
89
+ t.bindBuffer(t.ARRAY_BUFFER, i), t.bufferData(t.ARRAY_BUFFER, n, t.STATIC_DRAW);
90
+ const e = 4 * Float32Array.BYTES_PER_ELEMENT, r = o.attribLocations.get("a_position");
91
+ r !== void 0 && r !== -1 && (t.enableVertexAttribArray(r), t.vertexAttribPointer(r, 2, t.FLOAT, !1, e, 0));
92
+ const c = o.attribLocations.get("a_texCoord");
93
+ return c !== void 0 && c !== -1 && (t.enableVertexAttribArray(c), t.vertexAttribPointer(c, 2, t.FLOAT, !1, e, 2 * Float32Array.BYTES_PER_ELEMENT)), i;
94
94
  }
95
- function I(e) {
96
- e.drawArrays(e.TRIANGLE_STRIP, 0, 4);
95
+ function I(t) {
96
+ t.drawArrays(t.TRIANGLE_STRIP, 0, 4);
97
97
  }
98
- const O = `precision mediump float;
98
+ const V = `precision mediump float;
99
99
 
100
100
  varying vec2 v_texCoord;
101
101
 
@@ -111,6 +111,7 @@ uniform float u_showC;
111
111
  uniform float u_showM;
112
112
  uniform float u_showY;
113
113
  uniform float u_showK;
114
+ uniform float u_intensityK;
114
115
 
115
116
  // Returns the texture-space UV of the cell center for a given rotation angle
116
117
  vec2 cellCenterUV(vec2 uv, float angle) {
@@ -165,6 +166,7 @@ void main() {
165
166
  float ye = yInvK > 0.001 ? (yInvK - yRgb.b) / yInvK : 0.0;
166
167
 
167
168
  float k = 1.0 - max(max(kRgb.r, kRgb.g), kRgb.b);
169
+ k = clamp(k * u_intensityK, 0.0, 1.0);
168
170
 
169
171
  // Compute halftone dots for each channel
170
172
  float cDot = halftone(uv, u_angleC, cy, u_gridSize, u_dotRadius) * u_showC;
@@ -179,7 +181,7 @@ void main() {
179
181
 
180
182
  gl_FragColor = vec4(outR, outG, outB, texture2D(u_image, v_texCoord).a);
181
183
  }
182
- `, v = `attribute vec2 a_position;
184
+ `, b = `attribute vec2 a_position;
183
185
  attribute vec2 a_texCoord;
184
186
  varying vec2 v_texCoord;
185
187
 
@@ -187,10 +189,10 @@ void main() {
187
189
  gl_Position = vec4(a_position, 0.0, 1.0);
188
190
  v_texCoord = a_texCoord;
189
191
  }
190
- `, V = {
192
+ `, W = {
191
193
  name: "halftone-cmyk",
192
- fragmentShader: O,
193
- vertexShader: v,
194
+ fragmentShader: V,
195
+ vertexShader: b,
194
196
  uniforms: [
195
197
  { name: "u_dotRadius", type: "float", default: 4, attribute: "dot-radius" },
196
198
  { name: "u_gridSize", type: "float", default: 8, attribute: "grid-size" },
@@ -201,9 +203,10 @@ void main() {
201
203
  { name: "u_showC", type: "float", default: 1, attribute: "show-c" },
202
204
  { name: "u_showM", type: "float", default: 1, attribute: "show-m" },
203
205
  { name: "u_showY", type: "float", default: 1, attribute: "show-y" },
204
- { name: "u_showK", type: "float", default: 1, attribute: "show-k" }
206
+ { name: "u_showK", type: "float", default: 1, attribute: "show-k" },
207
+ { name: "u_intensityK", type: "float", default: 1, attribute: "intensity-k" }
205
208
  ]
206
- }, F = `precision mediump float;
209
+ }, N = `precision mediump float;
207
210
 
208
211
  varying vec2 v_texCoord;
209
212
 
@@ -245,17 +248,17 @@ void main() {
245
248
 
246
249
  gl_FragColor = vec4(result, color.a);
247
250
  }
248
- `, N = {
251
+ `, F = {
249
252
  name: "halftone-duotone",
250
- fragmentShader: F,
251
- vertexShader: v,
253
+ fragmentShader: N,
254
+ vertexShader: b,
252
255
  uniforms: [
253
256
  { name: "u_dotRadius", type: "float", default: 4, attribute: "dot-radius" },
254
257
  { name: "u_gridSize", type: "float", default: 8, attribute: "grid-size" },
255
258
  { name: "u_duotoneColor", type: "vec3", default: [0, 0.6, 0.8], attribute: "duotone-color" },
256
259
  { name: "u_angle", type: "float", default: 0, attribute: "angle" }
257
260
  ]
258
- }, Y = `precision mediump float;
261
+ }, B = `precision mediump float;
259
262
 
260
263
  varying vec2 v_texCoord;
261
264
 
@@ -311,10 +314,10 @@ void main() {
311
314
 
312
315
  gl_FragColor = vec4(result, 1.0);
313
316
  }
314
- `, B = {
317
+ `, Y = {
315
318
  name: "dot-grid",
316
- fragmentShader: Y,
317
- vertexShader: v,
319
+ fragmentShader: B,
320
+ vertexShader: b,
318
321
  uniforms: [
319
322
  { name: "u_dotRadius", type: "float", default: 4, attribute: "dot-radius" },
320
323
  { name: "u_gridSize", type: "float", default: 8, attribute: "grid-size" },
@@ -322,7 +325,7 @@ void main() {
322
325
  { name: "u_bgColor", type: "vec3", default: [1, 1, 1], attribute: "bg-color" },
323
326
  { name: "u_angle", type: "float", default: 0, attribute: "angle" }
324
327
  ]
325
- }, G = `precision mediump float;
328
+ }, X = `precision mediump float;
326
329
 
327
330
  varying vec2 v_texCoord;
328
331
 
@@ -338,6 +341,8 @@ uniform float u_showCool;
338
341
  uniform float u_showK;
339
342
  uniform vec3 u_warmColor;
340
343
  uniform vec3 u_coolColor;
344
+ uniform float u_blendMode;
345
+ uniform float u_intensityK;
341
346
 
342
347
  float halftone(vec2 uv, float angle, float channelValue, float gridSize, float dotRadius) {
343
348
  float rad = radians(angle);
@@ -364,27 +369,52 @@ void main() {
364
369
 
365
370
  // Black channel: derived from overall darkness
366
371
  float k = 1.0 - max(warmSep, coolSep);
372
+ k = clamp(k * u_intensityK, 0.0, 1.0);
367
373
 
368
374
  // Halftone dots for each channel
369
375
  float warmDot = halftone(uv, u_angleWarm, warmSep, u_gridSize, u_dotRadius) * u_showWarm;
370
376
  float coolDot = halftone(uv, u_angleCool, coolSep, u_gridSize, u_dotRadius) * u_showCool;
371
377
  float kDot = halftone(uv, u_angleK, k, u_gridSize, u_dotRadius) * u_showK;
372
378
 
373
- // Subtractive mixing: start with white paper, subtract dye layers
374
- vec3 paper = vec3(1.0);
375
- paper -= warmDot * (vec3(1.0) - u_warmColor);
376
- paper -= coolDot * (vec3(1.0) - u_coolColor);
377
- paper *= (1.0 - kDot);
379
+ // Blend modes affect how warm and cool dots combine where they overlap.
380
+ // All modes use white paper; individual dots look the same.
381
+ // Only the overlap regions differ between modes.
382
+ vec3 overlap;
383
+ if (u_blendMode < 0.5) {
384
+ // Subtractive: dye overlap absorbs more light (darker)
385
+ overlap = u_warmColor + u_coolColor - vec3(1.0);
386
+ } else if (u_blendMode < 1.5) {
387
+ // Additive: light overlap adds up (brighter)
388
+ overlap = u_warmColor + u_coolColor;
389
+ } else {
390
+ // Screen: soft additive overlap with natural clamping
391
+ overlap = vec3(1.0) - (vec3(1.0) - u_warmColor) * (vec3(1.0) - u_coolColor);
392
+ }
393
+
394
+ // Decompose into four halftone regions
395
+ float onlyWarm = warmDot * (1.0 - coolDot);
396
+ float onlyCool = coolDot * (1.0 - warmDot);
397
+ float both = warmDot * coolDot;
398
+ float neither = (1.0 - warmDot) * (1.0 - coolDot);
399
+
400
+ // Composite: white paper base, colored dots, blend-mode-dependent overlap
401
+ vec3 result = neither * vec3(1.0)
402
+ + onlyWarm * u_warmColor
403
+ + onlyCool * u_coolColor
404
+ + both * overlap;
378
405
 
379
- gl_FragColor = vec4(clamp(paper, 0.0, 1.0), color.a);
406
+ // K channel darkening with intensity control
407
+ result *= (1.0 - kDot);
408
+
409
+ gl_FragColor = vec4(clamp(result, 0.0, 1.0), color.a);
380
410
  }
381
- `, X = {
411
+ `, $ = {
382
412
  name: "technicolor-2strip",
383
- fragmentShader: G,
384
- vertexShader: v,
413
+ fragmentShader: X,
414
+ vertexShader: b,
385
415
  uniforms: [
386
- { name: "u_dotRadius", type: "float", default: 4, attribute: "dot-radius" },
387
- { name: "u_gridSize", type: "float", default: 8, attribute: "grid-size" },
416
+ { name: "u_dotRadius", type: "float", default: 7, attribute: "dot-radius" },
417
+ { name: "u_gridSize", type: "float", default: 10, attribute: "grid-size" },
388
418
  { name: "u_angleWarm", type: "float", default: 15, attribute: "angle-warm" },
389
419
  { name: "u_angleCool", type: "float", default: 75, attribute: "angle-cool" },
390
420
  { name: "u_angleK", type: "float", default: 45, attribute: "angle-k" },
@@ -392,31 +422,33 @@ void main() {
392
422
  { name: "u_showCool", type: "float", default: 1, attribute: "show-cool" },
393
423
  { name: "u_showK", type: "float", default: 1, attribute: "show-k" },
394
424
  { name: "u_warmColor", type: "vec3", default: [0.85, 0.25, 0.06], attribute: "warm-color" },
395
- { name: "u_coolColor", type: "vec3", default: [0.05, 0.65, 0.6], attribute: "cool-color" }
425
+ { name: "u_coolColor", type: "vec3", default: [0.05, 0.65, 0.6], attribute: "cool-color" },
426
+ { name: "u_blendMode", type: "float", default: 1, attribute: "blend-mode" },
427
+ { name: "u_intensityK", type: "float", default: 1, attribute: "intensity-k" }
396
428
  ]
397
- }, R = /* @__PURE__ */ new Map();
398
- function b(e) {
399
- R.set(e.name, e);
429
+ }, C = /* @__PURE__ */ new Map();
430
+ function v(t) {
431
+ C.set(t.name, t);
400
432
  }
401
- function $(e) {
402
- return R.get(e);
433
+ function G(t) {
434
+ return C.get(t);
403
435
  }
404
436
  function Z() {
405
- return Array.from(R.keys());
437
+ return Array.from(C.keys());
406
438
  }
407
- b(V);
408
- b(N);
409
- b(B);
410
- b(X);
411
- var H = Object.defineProperty, l = (e, o, a, r) => {
412
- for (var t = void 0, n = e.length - 1, d; n >= 0; n--)
413
- (d = e[n]) && (t = d(o, a, t) || t);
414
- return t && H(o, a, t), t;
439
+ v(W);
440
+ v(F);
441
+ v(Y);
442
+ v($);
443
+ var H = Object.defineProperty, l = (t, o, n, i) => {
444
+ for (var e = void 0, r = t.length - 1, c; r >= 0; r--)
445
+ (c = t[r]) && (e = c(o, n, e) || e);
446
+ return e && H(o, n, e), e;
415
447
  };
416
448
  const q = 2;
417
449
  let A = Promise.resolve();
418
- function U(e) {
419
- const o = A.then(e, e);
450
+ function U(t) {
451
+ const o = A.then(t, t);
420
452
  return A = o, o;
421
453
  }
422
454
  const j = /* @__PURE__ */ new Set([
@@ -431,6 +463,7 @@ const j = /* @__PURE__ */ new Set([
431
463
  "showM",
432
464
  "showY",
433
465
  "showK",
466
+ "intensityK",
434
467
  "duotoneColor",
435
468
  "angle",
436
469
  "dotOffsetX",
@@ -441,10 +474,11 @@ const j = /* @__PURE__ */ new Set([
441
474
  "showWarm",
442
475
  "showCool",
443
476
  "warmColor",
444
- "coolColor"
445
- ]), C = class C extends L {
477
+ "coolColor",
478
+ "blendMode"
479
+ ]), R = class R extends k {
446
480
  constructor() {
447
- super(...arguments), this.src = "", this.effect = "halftone-cmyk", this.dotRadius = 4, this.gridSize = 8, this.angleC = 15, this.angleM = 75, this.angleY = 0, this.angleK = 45, this.showC = 1, this.showM = 1, this.showY = 1, this.showK = 1, this.duotoneColor = "#0099cc", this.angle = 0, this.dotOffsetX = 0.5, this.dotOffsetY = 0.5, this.bgColor = "#ffffff", this.angleWarm = 15, this.angleCool = 75, this.showWarm = 1, this.showCool = 1, this.warmColor = "#d94010", this.coolColor = "#0da699", this.gateWeave = 0, this.loadingBlur = 0, this._webglAvailable = !0, this._snapshotUrl = "", this._snapshotLoaded = !1, this._image = null, this._observer = null, this._resizeObserver = null, this._lastClientWidth = 0, this._visible = !1, this._needsRender = !1, this._gateWeaveRaf = 0, this._gateWeaveTime = 0;
481
+ super(...arguments), this.src = "", this.effect = "halftone-cmyk", this.dotRadius = 4, this.gridSize = 8, this.angleC = 15, this.angleM = 75, this.angleY = 0, this.angleK = 45, this.showC = 1, this.showM = 1, this.showY = 1, this.showK = 1, this.intensityK = 1, this.duotoneColor = "#0099cc", this.angle = 0, this.dotOffsetX = 0.5, this.dotOffsetY = 0.5, this.bgColor = "#ffffff", this.angleWarm = 15, this.angleCool = 75, this.showWarm = 1, this.showCool = 1, this.warmColor = "#d94010", this.coolColor = "#0da699", this.blendMode = 1, this.loadingBlur = 0, this._webglAvailable = !0, this._snapshotUrl = "", this._snapshotLoaded = !1, this._image = null, this._observer = null, this._resizeObserver = null, this._lastClientWidth = 0, this._visible = !1, this._needsRender = !1;
448
482
  }
449
483
  render() {
450
484
  if (!this._webglAvailable)
@@ -462,9 +496,9 @@ const j = /* @__PURE__ */ new Set([
462
496
  connectedCallback() {
463
497
  super.connectedCallback(), this._observer = new IntersectionObserver(
464
498
  (o) => {
465
- var r;
466
- const a = this._visible;
467
- this._visible = ((r = o[0]) == null ? void 0 : r.isIntersecting) ?? !1, this._visible && !a && this._needsRender && (this._needsRender = !1, U(() => this._renderEffect()));
499
+ var i;
500
+ const n = this._visible;
501
+ this._visible = ((i = o[0]) == null ? void 0 : i.isIntersecting) ?? !1, this._visible && !n && this._needsRender && (this._needsRender = !1, U(() => this._renderEffect()));
468
502
  },
469
503
  // Start rendering slightly before the element scrolls into view.
470
504
  { rootMargin: "200px" }
@@ -481,23 +515,23 @@ const j = /* @__PURE__ */ new Set([
481
515
  }
482
516
  if (!this._image) return;
483
517
  [...o.keys()].some(
484
- (r) => j.has(r)
485
- ) && this._scheduleRender(), o.has("gateWeave") && this._updateGateWeave();
518
+ (i) => j.has(i)
519
+ ) && this._scheduleRender();
486
520
  }
487
521
  disconnectedCallback() {
488
- var o, a;
489
- super.disconnectedCallback(), (o = this._observer) == null || o.disconnect(), (a = this._resizeObserver) == null || a.disconnect(), this._stopGateWeave(), this._revokeSnapshot();
522
+ var o, n;
523
+ super.disconnectedCallback(), (o = this._observer) == null || o.disconnect(), (n = this._resizeObserver) == null || n.disconnect(), this._revokeSnapshot();
490
524
  }
491
525
  // ---------------------------------------------------------------------------
492
526
  // Image loading
493
527
  // ---------------------------------------------------------------------------
494
528
  _loadImage(o) {
495
- const a = new Image();
496
- a.crossOrigin = "anonymous", a.onload = () => {
497
- this._image = a, this._scheduleRender();
498
- }, a.onerror = () => {
529
+ const n = new Image();
530
+ n.crossOrigin = "anonymous", n.onload = () => {
531
+ this._image = n, this._scheduleRender();
532
+ }, n.onerror = () => {
499
533
  console.warn(`[some-shade] Failed to load image: ${o}`);
500
- }, a.src = o;
534
+ }, n.src = o;
501
535
  }
502
536
  // ---------------------------------------------------------------------------
503
537
  // Render scheduling
@@ -511,52 +545,52 @@ const j = /* @__PURE__ */ new Set([
511
545
  async _renderEffect() {
512
546
  var _;
513
547
  if (!this._image) return;
514
- const o = $(this.effect);
548
+ const o = G(this.effect);
515
549
  if (!o) {
516
550
  console.warn(`[some-shade] Unknown effect: ${this.effect}`);
517
551
  return;
518
552
  }
519
- const a = Math.min(window.devicePixelRatio || 1, q), r = this._image.naturalWidth, t = this._image.naturalHeight, n = this.clientWidth || r, d = Math.max(1, r / n);
553
+ const n = Math.min(window.devicePixelRatio || 1, q), i = this._image.naturalWidth, e = this._image.naturalHeight, r = this.clientWidth || i, c = Math.max(1, i / r);
520
554
  this._lastClientWidth = this.clientWidth;
521
555
  const h = document.createElement("canvas");
522
- h.width = r * a, h.height = t * a;
523
- const i = D(h);
524
- if (!i) {
556
+ h.width = i * n, h.height = e * n;
557
+ const s = L(h);
558
+ if (!s) {
525
559
  this._webglAvailable = !1;
526
560
  return;
527
561
  }
528
562
  try {
529
- const c = z(
530
- i,
563
+ const d = z(
564
+ s,
531
565
  o.vertexShader,
532
566
  o.fragmentShader
533
567
  );
534
- i.useProgram(c.program);
535
- const f = P(i, this._image), m = M(i, c);
536
- i.viewport(0, 0, h.width, h.height), i.clearColor(0, 0, 0, 0), i.clear(i.COLOR_BUFFER_BIT), i.activeTexture(i.TEXTURE0), i.bindTexture(i.TEXTURE_2D, f.texture);
537
- const S = c.uniformLocations.get("u_image");
538
- S && i.uniform1i(S, 0), K(
539
- i,
540
- c,
541
- this._getUniformValues(f, a, d)
542
- ), i.bindBuffer(i.ARRAY_BUFFER, m);
543
- const x = 4 * Float32Array.BYTES_PER_ELEMENT, g = c.attribLocations.get("a_position");
544
- g !== void 0 && g !== -1 && (i.enableVertexAttribArray(g), i.vertexAttribPointer(g, 2, i.FLOAT, !1, x, 0));
545
- const p = c.attribLocations.get("a_texCoord");
546
- p !== void 0 && p !== -1 && (i.enableVertexAttribArray(p), i.vertexAttribPointer(
568
+ s.useProgram(d.program);
569
+ const f = P(s, this._image), m = O(s, d);
570
+ s.viewport(0, 0, h.width, h.height), s.clearColor(0, 0, 0, 0), s.clear(s.COLOR_BUFFER_BIT), s.activeTexture(s.TEXTURE0), s.bindTexture(s.TEXTURE_2D, f.texture);
571
+ const S = d.uniformLocations.get("u_image");
572
+ S && s.uniform1i(S, 0), M(
573
+ s,
574
+ d,
575
+ this._getUniformValues(f, n, c)
576
+ ), s.bindBuffer(s.ARRAY_BUFFER, m);
577
+ const x = 4 * Float32Array.BYTES_PER_ELEMENT, g = d.attribLocations.get("a_position");
578
+ g !== void 0 && g !== -1 && (s.enableVertexAttribArray(g), s.vertexAttribPointer(g, 2, s.FLOAT, !1, x, 0));
579
+ const p = d.attribLocations.get("a_texCoord");
580
+ p !== void 0 && p !== -1 && (s.enableVertexAttribArray(p), s.vertexAttribPointer(
547
581
  p,
548
582
  2,
549
- i.FLOAT,
583
+ s.FLOAT,
550
584
  !1,
551
585
  x,
552
586
  2 * Float32Array.BYTES_PER_ELEMENT
553
- )), I(i);
587
+ )), I(s);
554
588
  const E = await new Promise(
555
- (W) => h.toBlob(W)
589
+ (K) => h.toBlob(K)
556
590
  );
557
- i.deleteTexture(f.texture), i.deleteProgram(c.program), i.deleteBuffer(m), E && (this._snapshotLoaded = !1, this._revokeSnapshot(), this._snapshotUrl = URL.createObjectURL(E));
591
+ s.deleteTexture(f.texture), s.deleteProgram(d.program), s.deleteBuffer(m), E && (this._snapshotLoaded = !1, this._revokeSnapshot(), this._snapshotUrl = URL.createObjectURL(E));
558
592
  } finally {
559
- (_ = i.getExtension("WEBGL_lose_context")) == null || _.loseContext();
593
+ (_ = s.getExtension("WEBGL_lose_context")) == null || _.loseContext();
560
594
  }
561
595
  }
562
596
  // ---------------------------------------------------------------------------
@@ -577,45 +611,24 @@ const j = /* @__PURE__ */ new Set([
577
611
  _revokeSnapshot() {
578
612
  this._snapshotUrl && (URL.revokeObjectURL(this._snapshotUrl), this._snapshotUrl = "");
579
613
  }
580
- _getUniformValues(o, a, r) {
581
- const t = {};
582
- return t.u_resolution = [
583
- o.width * a,
584
- o.height * a
585
- ], t.u_dotRadius = this.dotRadius * r, t.u_gridSize = this.gridSize * r, this.effect === "halftone-cmyk" ? (t.u_angleC = this.angleC, t.u_angleM = this.angleM, t.u_angleY = this.angleY, t.u_angleK = this.angleK, t.u_showC = this.showC, t.u_showM = this.showM, t.u_showY = this.showY, t.u_showK = this.showK) : this.effect === "halftone-duotone" ? (t.u_duotoneColor = this._parseHexColor(this.duotoneColor), t.u_angle = this.angle) : this.effect === "dot-grid" ? (t.u_dotOffset = [this.dotOffsetX, this.dotOffsetY], t.u_bgColor = this._parseHexColor(this.bgColor), t.u_angle = this.angle) : this.effect === "technicolor-2strip" && (t.u_angleWarm = this.angleWarm, t.u_angleCool = this.angleCool, t.u_angleK = this.angleK, t.u_showWarm = this.showWarm, t.u_showCool = this.showCool, t.u_showK = this.showK, t.u_warmColor = this._parseHexColor(this.warmColor), t.u_coolColor = this._parseHexColor(this.coolColor)), t;
586
- }
587
- _updateGateWeave() {
588
- if (this._stopGateWeave(), this.gateWeave <= 0) {
589
- const r = this.renderRoot.querySelector("img.snapshot");
590
- r && (r.style.transform = "");
591
- return;
592
- }
593
- const o = 1e3 / 12, a = (r) => {
594
- if (r - this._gateWeaveTime >= o) {
595
- this._gateWeaveTime = r;
596
- const t = this.renderRoot.querySelector("img.snapshot");
597
- if (t) {
598
- const n = (Math.random() - 0.5) * 2 * this.gateWeave, d = (Math.random() - 0.5) * 2 * this.gateWeave, h = 1 + this.gateWeave * 3e-3;
599
- t.style.transform = `translate(${n}px, ${d}px) scale(${h})`;
600
- }
601
- }
602
- this._gateWeaveRaf = requestAnimationFrame(a);
603
- };
604
- this._gateWeaveRaf = requestAnimationFrame(a);
605
- }
606
- _stopGateWeave() {
607
- this._gateWeaveRaf && (cancelAnimationFrame(this._gateWeaveRaf), this._gateWeaveRaf = 0);
614
+ _getUniformValues(o, n, i) {
615
+ const e = {};
616
+ return e.u_resolution = [
617
+ o.width * n,
618
+ o.height * n
619
+ ], e.u_dotRadius = this.dotRadius * i, e.u_gridSize = this.gridSize * i, this.effect === "halftone-cmyk" ? (e.u_angleC = this.angleC, e.u_angleM = this.angleM, e.u_angleY = this.angleY, e.u_angleK = this.angleK, e.u_showC = this.showC, e.u_showM = this.showM, e.u_showY = this.showY, e.u_showK = this.showK, e.u_intensityK = this.intensityK) : this.effect === "halftone-duotone" ? (e.u_duotoneColor = this._parseHexColor(this.duotoneColor), e.u_angle = this.angle) : this.effect === "dot-grid" ? (e.u_dotOffset = [this.dotOffsetX, this.dotOffsetY], e.u_bgColor = this._parseHexColor(this.bgColor), e.u_angle = this.angle) : this.effect === "technicolor-2strip" && (e.u_angleWarm = this.angleWarm, e.u_angleCool = this.angleCool, e.u_angleK = this.angleK, e.u_showWarm = this.showWarm, e.u_showCool = this.showCool, e.u_showK = this.showK, e.u_warmColor = this._parseHexColor(this.warmColor), e.u_coolColor = this._parseHexColor(this.coolColor), e.u_blendMode = this.blendMode, e.u_intensityK = this.intensityK), e;
608
620
  }
609
621
  _parseHexColor(o) {
610
- const a = o.replace("#", ""), r = parseInt(a.substring(0, 2), 16) / 255, t = parseInt(a.substring(2, 4), 16) / 255, n = parseInt(a.substring(4, 6), 16) / 255;
611
- return [r, t, n];
622
+ const n = o.replace("#", ""), i = parseInt(n.substring(0, 2), 16) / 255, e = parseInt(n.substring(2, 4), 16) / 255, r = parseInt(n.substring(4, 6), 16) / 255;
623
+ return [i, e, r];
612
624
  }
613
625
  };
614
- C.styles = k`
626
+ R.styles = D`
615
627
  :host {
616
628
  display: block;
617
629
  position: relative;
618
630
  overflow: hidden;
631
+ max-width: 100%;
619
632
  }
620
633
  img {
621
634
  display: block;
@@ -634,95 +647,98 @@ C.styles = k`
634
647
  opacity: 1;
635
648
  }
636
649
  `;
637
- let s = C;
650
+ let a = R;
638
651
  l([
639
652
  u()
640
- ], s.prototype, "src");
653
+ ], a.prototype, "src");
641
654
  l([
642
655
  u()
643
- ], s.prototype, "effect");
656
+ ], a.prototype, "effect");
644
657
  l([
645
658
  u({ type: Number, attribute: "dot-radius" })
646
- ], s.prototype, "dotRadius");
659
+ ], a.prototype, "dotRadius");
647
660
  l([
648
661
  u({ type: Number, attribute: "grid-size" })
649
- ], s.prototype, "gridSize");
662
+ ], a.prototype, "gridSize");
650
663
  l([
651
664
  u({ type: Number, attribute: "angle-c" })
652
- ], s.prototype, "angleC");
665
+ ], a.prototype, "angleC");
653
666
  l([
654
667
  u({ type: Number, attribute: "angle-m" })
655
- ], s.prototype, "angleM");
668
+ ], a.prototype, "angleM");
656
669
  l([
657
670
  u({ type: Number, attribute: "angle-y" })
658
- ], s.prototype, "angleY");
671
+ ], a.prototype, "angleY");
659
672
  l([
660
673
  u({ type: Number, attribute: "angle-k" })
661
- ], s.prototype, "angleK");
674
+ ], a.prototype, "angleK");
662
675
  l([
663
676
  u({ type: Number, attribute: "show-c" })
664
- ], s.prototype, "showC");
677
+ ], a.prototype, "showC");
665
678
  l([
666
679
  u({ type: Number, attribute: "show-m" })
667
- ], s.prototype, "showM");
680
+ ], a.prototype, "showM");
668
681
  l([
669
682
  u({ type: Number, attribute: "show-y" })
670
- ], s.prototype, "showY");
683
+ ], a.prototype, "showY");
671
684
  l([
672
685
  u({ type: Number, attribute: "show-k" })
673
- ], s.prototype, "showK");
686
+ ], a.prototype, "showK");
687
+ l([
688
+ u({ type: Number, attribute: "intensity-k" })
689
+ ], a.prototype, "intensityK");
674
690
  l([
675
691
  u({ attribute: "duotone-color" })
676
- ], s.prototype, "duotoneColor");
692
+ ], a.prototype, "duotoneColor");
677
693
  l([
678
694
  u({ type: Number })
679
- ], s.prototype, "angle");
695
+ ], a.prototype, "angle");
680
696
  l([
681
697
  u({ type: Number, attribute: "dot-offset-x" })
682
- ], s.prototype, "dotOffsetX");
698
+ ], a.prototype, "dotOffsetX");
683
699
  l([
684
700
  u({ type: Number, attribute: "dot-offset-y" })
685
- ], s.prototype, "dotOffsetY");
701
+ ], a.prototype, "dotOffsetY");
686
702
  l([
687
703
  u({ attribute: "bg-color" })
688
- ], s.prototype, "bgColor");
704
+ ], a.prototype, "bgColor");
689
705
  l([
690
706
  u({ type: Number, attribute: "angle-warm" })
691
- ], s.prototype, "angleWarm");
707
+ ], a.prototype, "angleWarm");
692
708
  l([
693
709
  u({ type: Number, attribute: "angle-cool" })
694
- ], s.prototype, "angleCool");
710
+ ], a.prototype, "angleCool");
695
711
  l([
696
712
  u({ type: Number, attribute: "show-warm" })
697
- ], s.prototype, "showWarm");
713
+ ], a.prototype, "showWarm");
698
714
  l([
699
715
  u({ type: Number, attribute: "show-cool" })
700
- ], s.prototype, "showCool");
716
+ ], a.prototype, "showCool");
701
717
  l([
702
718
  u({ attribute: "warm-color" })
703
- ], s.prototype, "warmColor");
719
+ ], a.prototype, "warmColor");
704
720
  l([
705
721
  u({ attribute: "cool-color" })
706
- ], s.prototype, "coolColor");
722
+ ], a.prototype, "coolColor");
707
723
  l([
708
- u({ type: Number, attribute: "gate-weave" })
709
- ], s.prototype, "gateWeave");
724
+ u({ type: Number, attribute: "blend-mode" })
725
+ ], a.prototype, "blendMode");
710
726
  l([
711
727
  u({ type: Number, attribute: "loading-blur" })
712
- ], s.prototype, "loadingBlur");
728
+ ], a.prototype, "loadingBlur");
713
729
  l([
714
730
  w()
715
- ], s.prototype, "_webglAvailable");
731
+ ], a.prototype, "_webglAvailable");
716
732
  l([
717
733
  w()
718
- ], s.prototype, "_snapshotUrl");
734
+ ], a.prototype, "_snapshotUrl");
719
735
  l([
720
736
  w()
721
- ], s.prototype, "_snapshotLoaded");
722
- customElements.get("some-shade-image") || customElements.define("some-shade-image", s);
737
+ ], a.prototype, "_snapshotLoaded");
738
+ customElements.get("some-shade-image") || customElements.define("some-shade-image", a);
723
739
  export {
724
- s as SomeShadeImage,
725
- $ as get,
740
+ a as SomeShadeImage,
741
+ G as get,
726
742
  Z as list,
727
- b as register
743
+ v as register
728
744
  };
@@ -1,4 +1,4 @@
1
- (function(c,p){typeof exports=="object"&&typeof module<"u"?p(exports,require("lit"),require("lit/decorators.js")):typeof define=="function"&&define.amd?define(["exports","lit","lit/decorators.js"],p):(c=typeof globalThis<"u"?globalThis:c||self,p(c.SomeShade={},c.Lit,c.LitDecorators))})(this,(function(c,p,l){"use strict";function W(e){return e.getContext("webgl",{alpha:!0,premultipliedAlpha:!1,preserveDrawingBuffer:!0})}function S(e,o,a){const r=e.createShader(o);if(!r)throw new Error("Failed to create shader");if(e.shaderSource(r,a),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){const t=e.getShaderInfoLog(r);throw e.deleteShader(r),new Error(`Shader compile error: ${t}`)}return r}function k(e,o,a){const r=S(e,e.VERTEX_SHADER,o),t=S(e,e.FRAGMENT_SHADER,a),n=e.createProgram();if(!n)throw new Error("Failed to create program");if(e.attachShader(n,r),e.attachShader(n,t),e.linkProgram(n),!e.getProgramParameter(n,e.LINK_STATUS)){const f=e.getProgramInfoLog(n);throw e.deleteProgram(n),new Error(`Program link error: ${f}`)}e.deleteShader(r),e.deleteShader(t);const d=new Map,m=e.getProgramParameter(n,e.ACTIVE_ATTRIBUTES);for(let f=0;f<m;f++){const h=e.getActiveAttrib(n,f);h&&d.set(h.name,e.getAttribLocation(n,h.name))}const s=new Map,b=e.getProgramParameter(n,e.ACTIVE_UNIFORMS);for(let f=0;f<b;f++){const h=e.getActiveUniform(n,f);if(h){const _=e.getUniformLocation(n,h.name);_&&s.set(h.name,_)}}return{program:n,attribLocations:d,uniformLocations:s}}function D(e,o,a){for(const[r,t]of Object.entries(a)){const n=o.uniformLocations.get(r);if(n){if(typeof t=="number")e.uniform1f(n,t);else if(Array.isArray(t))switch(t.length){case 2:e.uniform2fv(n,t);break;case 3:e.uniform3fv(n,t);break;case 4:e.uniform4fv(n,t);break}}}}function z(e,o){const a=e.createTexture();if(!a)throw new Error("Failed to create texture");return e.bindTexture(e.TEXTURE_2D,a),e.texImage2D(e.TEXTURE_2D,0,e.RGBA,e.RGBA,e.UNSIGNED_BYTE,o),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.LINEAR),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.LINEAR),{texture:a,width:o.naturalWidth,height:o.naturalHeight}}function K(e,o){const a=new Float32Array([-1,-1,0,1,1,-1,1,1,-1,1,0,0,1,1,1,0]),r=e.createBuffer();if(!r)throw new Error("Failed to create buffer");e.bindBuffer(e.ARRAY_BUFFER,r),e.bufferData(e.ARRAY_BUFFER,a,e.STATIC_DRAW);const t=4*Float32Array.BYTES_PER_ELEMENT,n=o.attribLocations.get("a_position");n!==void 0&&n!==-1&&(e.enableVertexAttribArray(n),e.vertexAttribPointer(n,2,e.FLOAT,!1,t,0));const d=o.attribLocations.get("a_texCoord");return d!==void 0&&d!==-1&&(e.enableVertexAttribArray(d),e.vertexAttribPointer(d,2,e.FLOAT,!1,t,2*Float32Array.BYTES_PER_ELEMENT)),r}function P(e){e.drawArrays(e.TRIANGLE_STRIP,0,4)}const M=`precision mediump float;
1
+ (function(c,m){typeof exports=="object"&&typeof module<"u"?m(exports,require("lit"),require("lit/decorators.js")):typeof define=="function"&&define.amd?define(["exports","lit","lit/decorators.js"],m):(c=typeof globalThis<"u"?globalThis:c||self,m(c.SomeShade={},c.Lit,c.LitDecorators))})(this,(function(c,m,l){"use strict";function k(e){return e.getContext("webgl",{alpha:!0,premultipliedAlpha:!1,preserveDrawingBuffer:!0})}function S(e,o,n){const i=e.createShader(o);if(!i)throw new Error("Failed to create shader");if(e.shaderSource(i,n),e.compileShader(i),!e.getShaderParameter(i,e.COMPILE_STATUS)){const t=e.getShaderInfoLog(i);throw e.deleteShader(i),new Error(`Shader compile error: ${t}`)}return i}function D(e,o,n){const i=S(e,e.VERTEX_SHADER,o),t=S(e,e.FRAGMENT_SHADER,n),a=e.createProgram();if(!a)throw new Error("Failed to create program");if(e.attachShader(a,i),e.attachShader(a,t),e.linkProgram(a),!e.getProgramParameter(a,e.LINK_STATUS)){const d=e.getProgramInfoLog(a);throw e.deleteProgram(a),new Error(`Program link error: ${d}`)}e.deleteShader(i),e.deleteShader(t);const f=new Map,p=e.getProgramParameter(a,e.ACTIVE_ATTRIBUTES);for(let d=0;d<p;d++){const h=e.getActiveAttrib(a,d);h&&f.set(h.name,e.getAttribLocation(a,h.name))}const s=new Map,v=e.getProgramParameter(a,e.ACTIVE_UNIFORMS);for(let d=0;d<v;d++){const h=e.getActiveUniform(a,d);if(h){const g=e.getUniformLocation(a,h.name);g&&s.set(h.name,g)}}return{program:a,attribLocations:f,uniformLocations:s}}function L(e,o,n){for(const[i,t]of Object.entries(n)){const a=o.uniformLocations.get(i);if(a){if(typeof t=="number")e.uniform1f(a,t);else if(Array.isArray(t))switch(t.length){case 2:e.uniform2fv(a,t);break;case 3:e.uniform3fv(a,t);break;case 4:e.uniform4fv(a,t);break}}}}function z(e,o){const n=e.createTexture();if(!n)throw new Error("Failed to create texture");return e.bindTexture(e.TEXTURE_2D,n),e.texImage2D(e.TEXTURE_2D,0,e.RGBA,e.RGBA,e.UNSIGNED_BYTE,o),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.LINEAR),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.LINEAR),{texture:n,width:o.naturalWidth,height:o.naturalHeight}}function M(e,o){const n=new Float32Array([-1,-1,0,1,1,-1,1,1,-1,1,0,0,1,1,1,0]),i=e.createBuffer();if(!i)throw new Error("Failed to create buffer");e.bindBuffer(e.ARRAY_BUFFER,i),e.bufferData(e.ARRAY_BUFFER,n,e.STATIC_DRAW);const t=4*Float32Array.BYTES_PER_ELEMENT,a=o.attribLocations.get("a_position");a!==void 0&&a!==-1&&(e.enableVertexAttribArray(a),e.vertexAttribPointer(a,2,e.FLOAT,!1,t,0));const f=o.attribLocations.get("a_texCoord");return f!==void 0&&f!==-1&&(e.enableVertexAttribArray(f),e.vertexAttribPointer(f,2,e.FLOAT,!1,t,2*Float32Array.BYTES_PER_ELEMENT)),i}function P(e){e.drawArrays(e.TRIANGLE_STRIP,0,4)}const O=`precision mediump float;
2
2
 
3
3
  varying vec2 v_texCoord;
4
4
 
@@ -14,6 +14,7 @@ uniform float u_showC;
14
14
  uniform float u_showM;
15
15
  uniform float u_showY;
16
16
  uniform float u_showK;
17
+ uniform float u_intensityK;
17
18
 
18
19
  // Returns the texture-space UV of the cell center for a given rotation angle
19
20
  vec2 cellCenterUV(vec2 uv, float angle) {
@@ -68,6 +69,7 @@ void main() {
68
69
  float ye = yInvK > 0.001 ? (yInvK - yRgb.b) / yInvK : 0.0;
69
70
 
70
71
  float k = 1.0 - max(max(kRgb.r, kRgb.g), kRgb.b);
72
+ k = clamp(k * u_intensityK, 0.0, 1.0);
71
73
 
72
74
  // Compute halftone dots for each channel
73
75
  float cDot = halftone(uv, u_angleC, cy, u_gridSize, u_dotRadius) * u_showC;
@@ -82,7 +84,7 @@ void main() {
82
84
 
83
85
  gl_FragColor = vec4(outR, outG, outB, texture2D(u_image, v_texCoord).a);
84
86
  }
85
- `,v=`attribute vec2 a_position;
87
+ `,b=`attribute vec2 a_position;
86
88
  attribute vec2 a_texCoord;
87
89
  varying vec2 v_texCoord;
88
90
 
@@ -90,7 +92,7 @@ void main() {
90
92
  gl_Position = vec4(a_position, 0.0, 1.0);
91
93
  v_texCoord = a_texCoord;
92
94
  }
93
- `,I={name:"halftone-cmyk",fragmentShader:M,vertexShader:v,uniforms:[{name:"u_dotRadius",type:"float",default:4,attribute:"dot-radius"},{name:"u_gridSize",type:"float",default:8,attribute:"grid-size"},{name:"u_angleC",type:"float",default:15,attribute:"angle-c"},{name:"u_angleM",type:"float",default:75,attribute:"angle-m"},{name:"u_angleY",type:"float",default:0,attribute:"angle-y"},{name:"u_angleK",type:"float",default:45,attribute:"angle-k"},{name:"u_showC",type:"float",default:1,attribute:"show-c"},{name:"u_showM",type:"float",default:1,attribute:"show-m"},{name:"u_showY",type:"float",default:1,attribute:"show-y"},{name:"u_showK",type:"float",default:1,attribute:"show-k"}]},O={name:"halftone-duotone",fragmentShader:`precision mediump float;
95
+ `,I={name:"halftone-cmyk",fragmentShader:O,vertexShader:b,uniforms:[{name:"u_dotRadius",type:"float",default:4,attribute:"dot-radius"},{name:"u_gridSize",type:"float",default:8,attribute:"grid-size"},{name:"u_angleC",type:"float",default:15,attribute:"angle-c"},{name:"u_angleM",type:"float",default:75,attribute:"angle-m"},{name:"u_angleY",type:"float",default:0,attribute:"angle-y"},{name:"u_angleK",type:"float",default:45,attribute:"angle-k"},{name:"u_showC",type:"float",default:1,attribute:"show-c"},{name:"u_showM",type:"float",default:1,attribute:"show-m"},{name:"u_showY",type:"float",default:1,attribute:"show-y"},{name:"u_showK",type:"float",default:1,attribute:"show-k"},{name:"u_intensityK",type:"float",default:1,attribute:"intensity-k"}]},V={name:"halftone-duotone",fragmentShader:`precision mediump float;
94
96
 
95
97
  varying vec2 v_texCoord;
96
98
 
@@ -132,7 +134,7 @@ void main() {
132
134
 
133
135
  gl_FragColor = vec4(result, color.a);
134
136
  }
135
- `,vertexShader:v,uniforms:[{name:"u_dotRadius",type:"float",default:4,attribute:"dot-radius"},{name:"u_gridSize",type:"float",default:8,attribute:"grid-size"},{name:"u_duotoneColor",type:"vec3",default:[0,.6,.8],attribute:"duotone-color"},{name:"u_angle",type:"float",default:0,attribute:"angle"}]},V={name:"dot-grid",fragmentShader:`precision mediump float;
137
+ `,vertexShader:b,uniforms:[{name:"u_dotRadius",type:"float",default:4,attribute:"dot-radius"},{name:"u_gridSize",type:"float",default:8,attribute:"grid-size"},{name:"u_duotoneColor",type:"vec3",default:[0,.6,.8],attribute:"duotone-color"},{name:"u_angle",type:"float",default:0,attribute:"angle"}]},W={name:"dot-grid",fragmentShader:`precision mediump float;
136
138
 
137
139
  varying vec2 v_texCoord;
138
140
 
@@ -188,7 +190,7 @@ void main() {
188
190
 
189
191
  gl_FragColor = vec4(result, 1.0);
190
192
  }
191
- `,vertexShader:v,uniforms:[{name:"u_dotRadius",type:"float",default:4,attribute:"dot-radius"},{name:"u_gridSize",type:"float",default:8,attribute:"grid-size"},{name:"u_dotOffset",type:"vec2",default:[.5,.5],attribute:"dot-offset"},{name:"u_bgColor",type:"vec3",default:[1,1,1],attribute:"bg-color"},{name:"u_angle",type:"float",default:0,attribute:"angle"}]},F={name:"technicolor-2strip",fragmentShader:`precision mediump float;
193
+ `,vertexShader:b,uniforms:[{name:"u_dotRadius",type:"float",default:4,attribute:"dot-radius"},{name:"u_gridSize",type:"float",default:8,attribute:"grid-size"},{name:"u_dotOffset",type:"vec2",default:[.5,.5],attribute:"dot-offset"},{name:"u_bgColor",type:"vec3",default:[1,1,1],attribute:"bg-color"},{name:"u_angle",type:"float",default:0,attribute:"angle"}]},N={name:"technicolor-2strip",fragmentShader:`precision mediump float;
192
194
 
193
195
  varying vec2 v_texCoord;
194
196
 
@@ -204,6 +206,8 @@ uniform float u_showCool;
204
206
  uniform float u_showK;
205
207
  uniform vec3 u_warmColor;
206
208
  uniform vec3 u_coolColor;
209
+ uniform float u_blendMode;
210
+ uniform float u_intensityK;
207
211
 
208
212
  float halftone(vec2 uv, float angle, float channelValue, float gridSize, float dotRadius) {
209
213
  float rad = radians(angle);
@@ -230,32 +234,58 @@ void main() {
230
234
 
231
235
  // Black channel: derived from overall darkness
232
236
  float k = 1.0 - max(warmSep, coolSep);
237
+ k = clamp(k * u_intensityK, 0.0, 1.0);
233
238
 
234
239
  // Halftone dots for each channel
235
240
  float warmDot = halftone(uv, u_angleWarm, warmSep, u_gridSize, u_dotRadius) * u_showWarm;
236
241
  float coolDot = halftone(uv, u_angleCool, coolSep, u_gridSize, u_dotRadius) * u_showCool;
237
242
  float kDot = halftone(uv, u_angleK, k, u_gridSize, u_dotRadius) * u_showK;
238
243
 
239
- // Subtractive mixing: start with white paper, subtract dye layers
240
- vec3 paper = vec3(1.0);
241
- paper -= warmDot * (vec3(1.0) - u_warmColor);
242
- paper -= coolDot * (vec3(1.0) - u_coolColor);
243
- paper *= (1.0 - kDot);
244
+ // Blend modes affect how warm and cool dots combine where they overlap.
245
+ // All modes use white paper; individual dots look the same.
246
+ // Only the overlap regions differ between modes.
247
+ vec3 overlap;
248
+ if (u_blendMode < 0.5) {
249
+ // Subtractive: dye overlap absorbs more light (darker)
250
+ overlap = u_warmColor + u_coolColor - vec3(1.0);
251
+ } else if (u_blendMode < 1.5) {
252
+ // Additive: light overlap adds up (brighter)
253
+ overlap = u_warmColor + u_coolColor;
254
+ } else {
255
+ // Screen: soft additive overlap with natural clamping
256
+ overlap = vec3(1.0) - (vec3(1.0) - u_warmColor) * (vec3(1.0) - u_coolColor);
257
+ }
258
+
259
+ // Decompose into four halftone regions
260
+ float onlyWarm = warmDot * (1.0 - coolDot);
261
+ float onlyCool = coolDot * (1.0 - warmDot);
262
+ float both = warmDot * coolDot;
263
+ float neither = (1.0 - warmDot) * (1.0 - coolDot);
264
+
265
+ // Composite: white paper base, colored dots, blend-mode-dependent overlap
266
+ vec3 result = neither * vec3(1.0)
267
+ + onlyWarm * u_warmColor
268
+ + onlyCool * u_coolColor
269
+ + both * overlap;
270
+
271
+ // K channel darkening with intensity control
272
+ result *= (1.0 - kDot);
244
273
 
245
- gl_FragColor = vec4(clamp(paper, 0.0, 1.0), color.a);
274
+ gl_FragColor = vec4(clamp(result, 0.0, 1.0), color.a);
246
275
  }
247
- `,vertexShader:v,uniforms:[{name:"u_dotRadius",type:"float",default:4,attribute:"dot-radius"},{name:"u_gridSize",type:"float",default:8,attribute:"grid-size"},{name:"u_angleWarm",type:"float",default:15,attribute:"angle-warm"},{name:"u_angleCool",type:"float",default:75,attribute:"angle-cool"},{name:"u_angleK",type:"float",default:45,attribute:"angle-k"},{name:"u_showWarm",type:"float",default:1,attribute:"show-warm"},{name:"u_showCool",type:"float",default:1,attribute:"show-cool"},{name:"u_showK",type:"float",default:1,attribute:"show-k"},{name:"u_warmColor",type:"vec3",default:[.85,.25,.06],attribute:"warm-color"},{name:"u_coolColor",type:"vec3",default:[.05,.65,.6],attribute:"cool-color"}]},R=new Map;function g(e){R.set(e.name,e)}function x(e){return R.get(e)}function N(){return Array.from(R.keys())}g(I),g(O),g(V),g(F);var Y=Object.defineProperty,u=(e,o,a,r)=>{for(var t=void 0,n=e.length-1,d;n>=0;n--)(d=e[n])&&(t=d(o,a,t)||t);return t&&Y(o,a,t),t};const B=2;let E=Promise.resolve();function T(e){const o=E.then(e,e);return E=o,o}const $=new Set(["effect","dotRadius","gridSize","angleC","angleM","angleY","angleK","showC","showM","showY","showK","duotoneColor","angle","dotOffsetX","dotOffsetY","bgColor","angleWarm","angleCool","showWarm","showCool","warmColor","coolColor"]),C=class C extends p.LitElement{constructor(){super(...arguments),this.src="",this.effect="halftone-cmyk",this.dotRadius=4,this.gridSize=8,this.angleC=15,this.angleM=75,this.angleY=0,this.angleK=45,this.showC=1,this.showM=1,this.showY=1,this.showK=1,this.duotoneColor="#0099cc",this.angle=0,this.dotOffsetX=.5,this.dotOffsetY=.5,this.bgColor="#ffffff",this.angleWarm=15,this.angleCool=75,this.showWarm=1,this.showCool=1,this.warmColor="#d94010",this.coolColor="#0da699",this.gateWeave=0,this.loadingBlur=0,this._webglAvailable=!0,this._snapshotUrl="",this._snapshotLoaded=!1,this._image=null,this._observer=null,this._resizeObserver=null,this._lastClientWidth=0,this._visible=!1,this._needsRender=!1,this._gateWeaveRaf=0,this._gateWeaveTime=0}render(){if(!this._webglAvailable)return p.html`<img src=${this.src} alt="" />`;const o=this.loadingBlur>0?`filter: blur(${this.loadingBlur}px)`:"";return p.html`
276
+ `,vertexShader:b,uniforms:[{name:"u_dotRadius",type:"float",default:7,attribute:"dot-radius"},{name:"u_gridSize",type:"float",default:10,attribute:"grid-size"},{name:"u_angleWarm",type:"float",default:15,attribute:"angle-warm"},{name:"u_angleCool",type:"float",default:75,attribute:"angle-cool"},{name:"u_angleK",type:"float",default:45,attribute:"angle-k"},{name:"u_showWarm",type:"float",default:1,attribute:"show-warm"},{name:"u_showCool",type:"float",default:1,attribute:"show-cool"},{name:"u_showK",type:"float",default:1,attribute:"show-k"},{name:"u_warmColor",type:"vec3",default:[.85,.25,.06],attribute:"warm-color"},{name:"u_coolColor",type:"vec3",default:[.05,.65,.6],attribute:"cool-color"},{name:"u_blendMode",type:"float",default:1,attribute:"blend-mode"},{name:"u_intensityK",type:"float",default:1,attribute:"intensity-k"}]},C=new Map;function _(e){C.set(e.name,e)}function x(e){return C.get(e)}function F(){return Array.from(C.keys())}_(I),_(V),_(W),_(N);var B=Object.defineProperty,u=(e,o,n,i)=>{for(var t=void 0,a=e.length-1,f;a>=0;a--)(f=e[a])&&(t=f(o,n,t)||t);return t&&B(o,n,t),t};const Y=2;let E=Promise.resolve();function T(e){const o=E.then(e,e);return E=o,o}const X=new Set(["effect","dotRadius","gridSize","angleC","angleM","angleY","angleK","showC","showM","showY","showK","intensityK","duotoneColor","angle","dotOffsetX","dotOffsetY","bgColor","angleWarm","angleCool","showWarm","showCool","warmColor","coolColor","blendMode"]),R=class R extends m.LitElement{constructor(){super(...arguments),this.src="",this.effect="halftone-cmyk",this.dotRadius=4,this.gridSize=8,this.angleC=15,this.angleM=75,this.angleY=0,this.angleK=45,this.showC=1,this.showM=1,this.showY=1,this.showK=1,this.intensityK=1,this.duotoneColor="#0099cc",this.angle=0,this.dotOffsetX=.5,this.dotOffsetY=.5,this.bgColor="#ffffff",this.angleWarm=15,this.angleCool=75,this.showWarm=1,this.showCool=1,this.warmColor="#d94010",this.coolColor="#0da699",this.blendMode=1,this.loadingBlur=0,this._webglAvailable=!0,this._snapshotUrl="",this._snapshotLoaded=!1,this._image=null,this._observer=null,this._resizeObserver=null,this._lastClientWidth=0,this._visible=!1,this._needsRender=!1}render(){if(!this._webglAvailable)return m.html`<img src=${this.src} alt="" />`;const o=this.loadingBlur>0?`filter: blur(${this.loadingBlur}px)`:"";return m.html`
248
277
  <img src=${this.src} alt="" style=${o} />
249
- ${this._snapshotUrl?p.html`<img
278
+ ${this._snapshotUrl?m.html`<img
250
279
  class="snapshot${this._snapshotLoaded?" loaded":""}"
251
280
  src=${this._snapshotUrl}
252
281
  @load=${this._onSnapshotLoad}
253
282
  alt="" />`:""}
254
- `}connectedCallback(){super.connectedCallback(),this._observer=new IntersectionObserver(o=>{var r;const a=this._visible;this._visible=((r=o[0])==null?void 0:r.isIntersecting)??!1,this._visible&&!a&&this._needsRender&&(this._needsRender=!1,T(()=>this._renderEffect()))},{rootMargin:"200px"}),this._observer.observe(this),this._resizeObserver=new ResizeObserver(()=>{if(!this._image)return;const o=this.clientWidth;o>0&&o!==this._lastClientWidth&&(this._lastClientWidth=o,this._scheduleRender())}),this._resizeObserver.observe(this)}updated(o){if(o.has("src")&&this.src){this._loadImage(this.src);return}if(!this._image)return;[...o.keys()].some(r=>$.has(r))&&this._scheduleRender(),o.has("gateWeave")&&this._updateGateWeave()}disconnectedCallback(){var o,a;super.disconnectedCallback(),(o=this._observer)==null||o.disconnect(),(a=this._resizeObserver)==null||a.disconnect(),this._stopGateWeave(),this._revokeSnapshot()}_loadImage(o){const a=new Image;a.crossOrigin="anonymous",a.onload=()=>{this._image=a,this._scheduleRender()},a.onerror=()=>{console.warn(`[some-shade] Failed to load image: ${o}`)},a.src=o}_scheduleRender(){this._visible?T(()=>this._renderEffect()):this._needsRender=!0}async _renderEffect(){var b;if(!this._image)return;const o=x(this.effect);if(!o){console.warn(`[some-shade] Unknown effect: ${this.effect}`);return}const a=Math.min(window.devicePixelRatio||1,B),r=this._image.naturalWidth,t=this._image.naturalHeight,n=this.clientWidth||r,d=Math.max(1,r/n);this._lastClientWidth=this.clientWidth;const m=document.createElement("canvas");m.width=r*a,m.height=t*a;const s=W(m);if(!s){this._webglAvailable=!1;return}try{const f=k(s,o.vertexShader,o.fragmentShader);s.useProgram(f.program);const h=z(s,this._image),_=K(s,f);s.viewport(0,0,m.width,m.height),s.clearColor(0,0,0,0),s.clear(s.COLOR_BUFFER_BIT),s.activeTexture(s.TEXTURE0),s.bindTexture(s.TEXTURE_2D,h.texture);const A=f.uniformLocations.get("u_image");A&&s.uniform1i(A,0),D(s,f,this._getUniformValues(h,a,d)),s.bindBuffer(s.ARRAY_BUFFER,_);const U=4*Float32Array.BYTES_PER_ELEMENT,y=f.attribLocations.get("a_position");y!==void 0&&y!==-1&&(s.enableVertexAttribArray(y),s.vertexAttribPointer(y,2,s.FLOAT,!1,U,0));const w=f.attribLocations.get("a_texCoord");w!==void 0&&w!==-1&&(s.enableVertexAttribArray(w),s.vertexAttribPointer(w,2,s.FLOAT,!1,U,2*Float32Array.BYTES_PER_ELEMENT)),P(s);const L=await new Promise(G=>m.toBlob(G));s.deleteTexture(h.texture),s.deleteProgram(f.program),s.deleteBuffer(_),L&&(this._snapshotLoaded=!1,this._revokeSnapshot(),this._snapshotUrl=URL.createObjectURL(L))}finally{(b=s.getExtension("WEBGL_lose_context"))==null||b.loseContext()}}_onSnapshotLoad(){this._snapshotLoaded=!0}replayTransition(o=500){this._snapshotUrl&&(this._snapshotLoaded=!1,this.updateComplete.then(()=>{setTimeout(()=>{this._snapshotLoaded=!0},o)}))}_revokeSnapshot(){this._snapshotUrl&&(URL.revokeObjectURL(this._snapshotUrl),this._snapshotUrl="")}_getUniformValues(o,a,r){const t={};return t.u_resolution=[o.width*a,o.height*a],t.u_dotRadius=this.dotRadius*r,t.u_gridSize=this.gridSize*r,this.effect==="halftone-cmyk"?(t.u_angleC=this.angleC,t.u_angleM=this.angleM,t.u_angleY=this.angleY,t.u_angleK=this.angleK,t.u_showC=this.showC,t.u_showM=this.showM,t.u_showY=this.showY,t.u_showK=this.showK):this.effect==="halftone-duotone"?(t.u_duotoneColor=this._parseHexColor(this.duotoneColor),t.u_angle=this.angle):this.effect==="dot-grid"?(t.u_dotOffset=[this.dotOffsetX,this.dotOffsetY],t.u_bgColor=this._parseHexColor(this.bgColor),t.u_angle=this.angle):this.effect==="technicolor-2strip"&&(t.u_angleWarm=this.angleWarm,t.u_angleCool=this.angleCool,t.u_angleK=this.angleK,t.u_showWarm=this.showWarm,t.u_showCool=this.showCool,t.u_showK=this.showK,t.u_warmColor=this._parseHexColor(this.warmColor),t.u_coolColor=this._parseHexColor(this.coolColor)),t}_updateGateWeave(){if(this._stopGateWeave(),this.gateWeave<=0){const r=this.renderRoot.querySelector("img.snapshot");r&&(r.style.transform="");return}const o=1e3/12,a=r=>{if(r-this._gateWeaveTime>=o){this._gateWeaveTime=r;const t=this.renderRoot.querySelector("img.snapshot");if(t){const n=(Math.random()-.5)*2*this.gateWeave,d=(Math.random()-.5)*2*this.gateWeave,m=1+this.gateWeave*.003;t.style.transform=`translate(${n}px, ${d}px) scale(${m})`}}this._gateWeaveRaf=requestAnimationFrame(a)};this._gateWeaveRaf=requestAnimationFrame(a)}_stopGateWeave(){this._gateWeaveRaf&&(cancelAnimationFrame(this._gateWeaveRaf),this._gateWeaveRaf=0)}_parseHexColor(o){const a=o.replace("#",""),r=parseInt(a.substring(0,2),16)/255,t=parseInt(a.substring(2,4),16)/255,n=parseInt(a.substring(4,6),16)/255;return[r,t,n]}};C.styles=p.css`
283
+ `}connectedCallback(){super.connectedCallback(),this._observer=new IntersectionObserver(o=>{var i;const n=this._visible;this._visible=((i=o[0])==null?void 0:i.isIntersecting)??!1,this._visible&&!n&&this._needsRender&&(this._needsRender=!1,T(()=>this._renderEffect()))},{rootMargin:"200px"}),this._observer.observe(this),this._resizeObserver=new ResizeObserver(()=>{if(!this._image)return;const o=this.clientWidth;o>0&&o!==this._lastClientWidth&&(this._lastClientWidth=o,this._scheduleRender())}),this._resizeObserver.observe(this)}updated(o){if(o.has("src")&&this.src){this._loadImage(this.src);return}if(!this._image)return;[...o.keys()].some(i=>X.has(i))&&this._scheduleRender()}disconnectedCallback(){var o,n;super.disconnectedCallback(),(o=this._observer)==null||o.disconnect(),(n=this._resizeObserver)==null||n.disconnect(),this._revokeSnapshot()}_loadImage(o){const n=new Image;n.crossOrigin="anonymous",n.onload=()=>{this._image=n,this._scheduleRender()},n.onerror=()=>{console.warn(`[some-shade] Failed to load image: ${o}`)},n.src=o}_scheduleRender(){this._visible?T(()=>this._renderEffect()):this._needsRender=!0}async _renderEffect(){var v;if(!this._image)return;const o=x(this.effect);if(!o){console.warn(`[some-shade] Unknown effect: ${this.effect}`);return}const n=Math.min(window.devicePixelRatio||1,Y),i=this._image.naturalWidth,t=this._image.naturalHeight,a=this.clientWidth||i,f=Math.max(1,i/a);this._lastClientWidth=this.clientWidth;const p=document.createElement("canvas");p.width=i*n,p.height=t*n;const s=k(p);if(!s){this._webglAvailable=!1;return}try{const d=D(s,o.vertexShader,o.fragmentShader);s.useProgram(d.program);const h=z(s,this._image),g=M(s,d);s.viewport(0,0,p.width,p.height),s.clearColor(0,0,0,0),s.clear(s.COLOR_BUFFER_BIT),s.activeTexture(s.TEXTURE0),s.bindTexture(s.TEXTURE_2D,h.texture);const A=d.uniformLocations.get("u_image");A&&s.uniform1i(A,0),L(s,d,this._getUniformValues(h,n,f)),s.bindBuffer(s.ARRAY_BUFFER,g);const U=4*Float32Array.BYTES_PER_ELEMENT,y=d.attribLocations.get("a_position");y!==void 0&&y!==-1&&(s.enableVertexAttribArray(y),s.vertexAttribPointer(y,2,s.FLOAT,!1,U,0));const w=d.attribLocations.get("a_texCoord");w!==void 0&&w!==-1&&(s.enableVertexAttribArray(w),s.vertexAttribPointer(w,2,s.FLOAT,!1,U,2*Float32Array.BYTES_PER_ELEMENT)),P(s);const K=await new Promise($=>p.toBlob($));s.deleteTexture(h.texture),s.deleteProgram(d.program),s.deleteBuffer(g),K&&(this._snapshotLoaded=!1,this._revokeSnapshot(),this._snapshotUrl=URL.createObjectURL(K))}finally{(v=s.getExtension("WEBGL_lose_context"))==null||v.loseContext()}}_onSnapshotLoad(){this._snapshotLoaded=!0}replayTransition(o=500){this._snapshotUrl&&(this._snapshotLoaded=!1,this.updateComplete.then(()=>{setTimeout(()=>{this._snapshotLoaded=!0},o)}))}_revokeSnapshot(){this._snapshotUrl&&(URL.revokeObjectURL(this._snapshotUrl),this._snapshotUrl="")}_getUniformValues(o,n,i){const t={};return t.u_resolution=[o.width*n,o.height*n],t.u_dotRadius=this.dotRadius*i,t.u_gridSize=this.gridSize*i,this.effect==="halftone-cmyk"?(t.u_angleC=this.angleC,t.u_angleM=this.angleM,t.u_angleY=this.angleY,t.u_angleK=this.angleK,t.u_showC=this.showC,t.u_showM=this.showM,t.u_showY=this.showY,t.u_showK=this.showK,t.u_intensityK=this.intensityK):this.effect==="halftone-duotone"?(t.u_duotoneColor=this._parseHexColor(this.duotoneColor),t.u_angle=this.angle):this.effect==="dot-grid"?(t.u_dotOffset=[this.dotOffsetX,this.dotOffsetY],t.u_bgColor=this._parseHexColor(this.bgColor),t.u_angle=this.angle):this.effect==="technicolor-2strip"&&(t.u_angleWarm=this.angleWarm,t.u_angleCool=this.angleCool,t.u_angleK=this.angleK,t.u_showWarm=this.showWarm,t.u_showCool=this.showCool,t.u_showK=this.showK,t.u_warmColor=this._parseHexColor(this.warmColor),t.u_coolColor=this._parseHexColor(this.coolColor),t.u_blendMode=this.blendMode,t.u_intensityK=this.intensityK),t}_parseHexColor(o){const n=o.replace("#",""),i=parseInt(n.substring(0,2),16)/255,t=parseInt(n.substring(2,4),16)/255,a=parseInt(n.substring(4,6),16)/255;return[i,t,a]}};R.styles=m.css`
255
284
  :host {
256
285
  display: block;
257
286
  position: relative;
258
287
  overflow: hidden;
288
+ max-width: 100%;
259
289
  }
260
290
  img {
261
291
  display: block;
@@ -273,4 +303,4 @@ void main() {
273
303
  img.snapshot.loaded {
274
304
  opacity: 1;
275
305
  }
276
- `;let i=C;u([l.property()],i.prototype,"src"),u([l.property()],i.prototype,"effect"),u([l.property({type:Number,attribute:"dot-radius"})],i.prototype,"dotRadius"),u([l.property({type:Number,attribute:"grid-size"})],i.prototype,"gridSize"),u([l.property({type:Number,attribute:"angle-c"})],i.prototype,"angleC"),u([l.property({type:Number,attribute:"angle-m"})],i.prototype,"angleM"),u([l.property({type:Number,attribute:"angle-y"})],i.prototype,"angleY"),u([l.property({type:Number,attribute:"angle-k"})],i.prototype,"angleK"),u([l.property({type:Number,attribute:"show-c"})],i.prototype,"showC"),u([l.property({type:Number,attribute:"show-m"})],i.prototype,"showM"),u([l.property({type:Number,attribute:"show-y"})],i.prototype,"showY"),u([l.property({type:Number,attribute:"show-k"})],i.prototype,"showK"),u([l.property({attribute:"duotone-color"})],i.prototype,"duotoneColor"),u([l.property({type:Number})],i.prototype,"angle"),u([l.property({type:Number,attribute:"dot-offset-x"})],i.prototype,"dotOffsetX"),u([l.property({type:Number,attribute:"dot-offset-y"})],i.prototype,"dotOffsetY"),u([l.property({attribute:"bg-color"})],i.prototype,"bgColor"),u([l.property({type:Number,attribute:"angle-warm"})],i.prototype,"angleWarm"),u([l.property({type:Number,attribute:"angle-cool"})],i.prototype,"angleCool"),u([l.property({type:Number,attribute:"show-warm"})],i.prototype,"showWarm"),u([l.property({type:Number,attribute:"show-cool"})],i.prototype,"showCool"),u([l.property({attribute:"warm-color"})],i.prototype,"warmColor"),u([l.property({attribute:"cool-color"})],i.prototype,"coolColor"),u([l.property({type:Number,attribute:"gate-weave"})],i.prototype,"gateWeave"),u([l.property({type:Number,attribute:"loading-blur"})],i.prototype,"loadingBlur"),u([l.state()],i.prototype,"_webglAvailable"),u([l.state()],i.prototype,"_snapshotUrl"),u([l.state()],i.prototype,"_snapshotLoaded"),customElements.get("some-shade-image")||customElements.define("some-shade-image",i),c.SomeShadeImage=i,c.get=x,c.list=N,c.register=g,Object.defineProperty(c,Symbol.toStringTag,{value:"Module"})}));
306
+ `;let r=R;u([l.property()],r.prototype,"src"),u([l.property()],r.prototype,"effect"),u([l.property({type:Number,attribute:"dot-radius"})],r.prototype,"dotRadius"),u([l.property({type:Number,attribute:"grid-size"})],r.prototype,"gridSize"),u([l.property({type:Number,attribute:"angle-c"})],r.prototype,"angleC"),u([l.property({type:Number,attribute:"angle-m"})],r.prototype,"angleM"),u([l.property({type:Number,attribute:"angle-y"})],r.prototype,"angleY"),u([l.property({type:Number,attribute:"angle-k"})],r.prototype,"angleK"),u([l.property({type:Number,attribute:"show-c"})],r.prototype,"showC"),u([l.property({type:Number,attribute:"show-m"})],r.prototype,"showM"),u([l.property({type:Number,attribute:"show-y"})],r.prototype,"showY"),u([l.property({type:Number,attribute:"show-k"})],r.prototype,"showK"),u([l.property({type:Number,attribute:"intensity-k"})],r.prototype,"intensityK"),u([l.property({attribute:"duotone-color"})],r.prototype,"duotoneColor"),u([l.property({type:Number})],r.prototype,"angle"),u([l.property({type:Number,attribute:"dot-offset-x"})],r.prototype,"dotOffsetX"),u([l.property({type:Number,attribute:"dot-offset-y"})],r.prototype,"dotOffsetY"),u([l.property({attribute:"bg-color"})],r.prototype,"bgColor"),u([l.property({type:Number,attribute:"angle-warm"})],r.prototype,"angleWarm"),u([l.property({type:Number,attribute:"angle-cool"})],r.prototype,"angleCool"),u([l.property({type:Number,attribute:"show-warm"})],r.prototype,"showWarm"),u([l.property({type:Number,attribute:"show-cool"})],r.prototype,"showCool"),u([l.property({attribute:"warm-color"})],r.prototype,"warmColor"),u([l.property({attribute:"cool-color"})],r.prototype,"coolColor"),u([l.property({type:Number,attribute:"blend-mode"})],r.prototype,"blendMode"),u([l.property({type:Number,attribute:"loading-blur"})],r.prototype,"loadingBlur"),u([l.state()],r.prototype,"_webglAvailable"),u([l.state()],r.prototype,"_snapshotUrl"),u([l.state()],r.prototype,"_snapshotLoaded"),customElements.get("some-shade-image")||customElements.define("some-shade-image",r),c.SomeShadeImage=r,c.get=x,c.list=F,c.register=_,Object.defineProperty(c,Symbol.toStringTag,{value:"Module"})}));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@johnfmorton/some-shade",
3
- "version": "0.1.1-beta",
3
+ "version": "0.1.4-beta",
4
4
  "license": "ISC",
5
5
  "homepage": "https://johnfmorton.github.io/some-shade-web-component/",
6
6
  "repository": {
package/dist/index.d.ts DELETED
@@ -1,82 +0,0 @@
1
- import { CSSResult } from 'lit';
2
- import { LitElement } from 'lit';
3
- import { PropertyValues } from 'lit';
4
- import { TemplateResult } from 'lit';
5
-
6
- export declare interface EffectDefinition {
7
- name: string;
8
- fragmentShader: string;
9
- vertexShader: string;
10
- uniforms: UniformDefinition[];
11
- }
12
-
13
- export declare function get(name: string): EffectDefinition | undefined;
14
-
15
- export declare function list(): string[];
16
-
17
- export declare function register(effect: EffectDefinition): void;
18
-
19
- export declare class SomeShadeImage extends LitElement {
20
- static styles: CSSResult;
21
- src: string;
22
- effect: string;
23
- dotRadius: number;
24
- gridSize: number;
25
- angleC: number;
26
- angleM: number;
27
- angleY: number;
28
- angleK: number;
29
- showC: number;
30
- showM: number;
31
- showY: number;
32
- showK: number;
33
- duotoneColor: string;
34
- angle: number;
35
- dotOffsetX: number;
36
- dotOffsetY: number;
37
- bgColor: string;
38
- angleWarm: number;
39
- angleCool: number;
40
- showWarm: number;
41
- showCool: number;
42
- warmColor: string;
43
- coolColor: string;
44
- gateWeave: number;
45
- loadingBlur: number;
46
- private _webglAvailable;
47
- private _snapshotUrl;
48
- private _snapshotLoaded;
49
- private _image;
50
- private _observer;
51
- private _resizeObserver;
52
- private _lastClientWidth;
53
- private _visible;
54
- private _needsRender;
55
- private _gateWeaveRaf;
56
- private _gateWeaveTime;
57
- render(): TemplateResult<1>;
58
- connectedCallback(): void;
59
- updated(changed: PropertyValues): void;
60
- disconnectedCallback(): void;
61
- private _loadImage;
62
- private _scheduleRender;
63
- private _renderEffect;
64
- private _onSnapshotLoad;
65
- /** Hide the rendered snapshot momentarily, then fade it back in.
66
- * Useful for previewing the loading-blur transition. */
67
- replayTransition(delay?: number): void;
68
- private _revokeSnapshot;
69
- private _getUniformValues;
70
- private _updateGateWeave;
71
- private _stopGateWeave;
72
- private _parseHexColor;
73
- }
74
-
75
- export declare interface UniformDefinition {
76
- name: string;
77
- type: 'float' | 'vec2' | 'vec3' | 'vec4';
78
- default: number | number[];
79
- attribute?: string;
80
- }
81
-
82
- export { }