@webmate-studio/builder 0.2.139 → 0.2.141

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webmate-studio/builder",
3
- "version": "0.2.139",
3
+ "version": "0.2.141",
4
4
  "type": "module",
5
5
  "description": "Webmate Studio Component Builder",
6
6
  "keywords": [
@@ -16,10 +16,10 @@
16
16
  * chromaScale = globaler Sättigungsmultiplikator
17
17
  */
18
18
  export const COLOR_SCALE_PRESETS = {
19
- vivid: { label: 'Leuchtend', stdDev: 40, chromaScale: 1.15 },
19
+ vivid: { label: 'Leuchtend', stdDev: 50, chromaScale: 1.2 },
20
20
  natural: { label: 'Natürlich', stdDev: 30, chromaScale: 1.0 },
21
- soft: { label: 'Pastellig', stdDev: 16, chromaScale: 0.75 },
22
- muted: { label: 'Gedämpft', stdDev: 22, chromaScale: 0.55 },
21
+ soft: { label: 'Pastellig', stdDev: 18, chromaScale: 0.7 },
22
+ muted: { label: 'Gedämpft', stdDev: 22, chromaScale: 0.5 },
23
23
  };
24
24
 
25
25
  /**
@@ -45,8 +45,12 @@ export function generateColorScale(baseHex, curve) {
45
45
  // Neutral-Erkennung: Basis mit sehr niedriger Chroma (reines Grau)
46
46
  const isPureNeutral = base.c < 0.008;
47
47
 
48
+ // Neutral-Erkennung für Rampe: getönte Grautöne (c < 0.05) brauchen
49
+ // dunkle Steps für Textfarbe und Step 1 = Weiß
50
+ const isLowChroma = base.c < 0.05;
51
+
48
52
  // Lightness-Rampe adaptiv an Base-Lightness
49
- const L = buildLightnessRamp(base.l);
53
+ const L = buildLightnessRamp(base.l, isLowChroma);
50
54
 
51
55
  // Wurde die Base-Lightness geclampt? (extrem helle/dunkle Farben)
52
56
  const baseClamped = Math.abs(L[8] - base.l) > 0.01;
@@ -76,8 +80,8 @@ export function generateColorScale(baseHex, curve) {
76
80
  scale[step] = oklchToHex(mapped.l, mapped.c, mapped.h);
77
81
  }
78
82
 
79
- // Reines Neutral Step 1 = reines Weiß
80
- if (isPureNeutral) {
83
+ // Neutraltöne: Step 1 = reines Weiß (Seitenhintergrund)
84
+ if (isLowChroma) {
81
85
  scale[1] = '#ffffff';
82
86
  }
83
87
 
@@ -222,9 +226,8 @@ function hslToHex(h, s, l) {
222
226
  * - Die Rampe wird auf den verfügbaren Bereich komprimiert
223
227
  * - Monotonie ist durch die Konstruktion garantiert
224
228
  */
225
- function buildLightnessRamp(baseL) {
229
+ function buildLightnessRamp(baseL, isLowChroma = false) {
226
230
  const topL = 0.985; // Step 1: fast Weiß
227
- const bottomL = 0.25; // Step 12: dunkelster Wert
228
231
 
229
232
  // Base clampen: min. 0.30 damit 3 dunkle Stufen Platz haben,
230
233
  // max. 0.80 damit 8 helle Stufen genug Abstand in sRGB haben
@@ -237,15 +240,30 @@ function buildLightnessRamp(baseL) {
237
240
  const range = topL - step8Target;
238
241
 
239
242
  // Feste Verteilungs-Gewichte: Steps 1-2 bleiben nahe Weiß,
240
- // dann beschleunigter Abstieg zur Base. Inspiriert von Radix' Lightness-Verteilung.
241
- const weights = [0.0, 0.04, 0.10, 0.20, 0.34, 0.50, 0.70, 0.92];
243
+ // dann gleichmäßiger Abstieg zur Base. Sprünge zwischen benachbarten Weights
244
+ // sollen möglichst gleichmäßig ansteigen (kein harter Sprung bei Step 7).
245
+ const weights = [0.0, 0.04, 0.10, 0.20, 0.34, 0.50, 0.67, 0.86];
242
246
  const lightSteps = weights.map(w => topL - w * range);
243
247
 
244
- // Steps 10-12: nach unten von Base weg
245
- const darkRange = safeBaseL - bottomL;
246
- const step10L = safeBaseL - darkRange * 0.12;
247
- const step11L = safeBaseL - darkRange * 0.55;
248
- const step12L = bottomL;
248
+ let step10L, step11L, step12L;
249
+
250
+ if (isLowChroma) {
251
+ // Neutraltöne: Step 12 muss sehr dunkel sein (Hauptschriftfarbe),
252
+ // Step 11 = Low-Contrast Text, volle Spreizung nach unten
253
+ const bottomL = 0.25;
254
+ const darkRange = safeBaseL - bottomL;
255
+ step10L = safeBaseL - darkRange * 0.12;
256
+ step11L = safeBaseL - darkRange * 0.55;
257
+ step12L = bottomL;
258
+ } else {
259
+ // Chromatische Farben: Steps 11-12 näher beieinander,
260
+ // der Farbton bleibt wichtiger als maximale Dunkelheit
261
+ const bottomL = 0.25;
262
+ const darkRange = safeBaseL - bottomL;
263
+ step10L = safeBaseL - darkRange * 0.12;
264
+ step11L = safeBaseL - darkRange * 0.30;
265
+ step12L = safeBaseL - darkRange * 0.42;
266
+ }
249
267
 
250
268
  const ramp = [
251
269
  ...lightSteps, // Steps 1-8
@@ -316,9 +334,23 @@ function buildDarkLightnessRamp(darkBaseL) {
316
334
  * sind — wie bei Radix Colors.
317
335
  */
318
336
  function computeChroma(stepL, baseL, baseC, stdDev, chromaScale) {
319
- // Gaußkurve: Peak bei baseL, flachere Flanken als vorher
337
+ // Gaußkurve mit Plateau: In der Nähe der Base bleibt Chroma nahe 100%,
338
+ // erst weiter entfernt greift die Gaußkurve richtig.
339
+ // Das verhindert den harten Sprung bei Steps 8/10 vs. Base.
320
340
  const diff = baseL - stepL;
321
- const gaussian = Math.exp((-12 / stdDev) * diff * diff);
341
+ const absDiff = Math.abs(diff);
342
+
343
+ // Plateau-Radius: Innerhalb dieses L-Abstands bleibt Chroma nahe Base-Level
344
+ const plateau = 0.08;
345
+ let gaussian;
346
+ if (absDiff <= plateau) {
347
+ // Innerhalb des Plateaus: sanfter cosinus-Übergang (1.0 → ~0.97)
348
+ gaussian = 1.0 - 0.03 * (absDiff / plateau);
349
+ } else {
350
+ // Außerhalb: Gauß ab der Plateau-Kante
351
+ const edgeDiff = absDiff - plateau;
352
+ gaussian = 0.97 * Math.exp((-12 / stdDev) * edgeDiff * edgeDiff);
353
+ }
322
354
 
323
355
  // Lightness-Begrenzung: Asymmetrisch
324
356
  // Helle Seite (L > 0.85): Chroma fällt steil auf 0 → Steps 1-2 bleiben fast weiß
@@ -326,13 +358,11 @@ function computeChroma(stepL, baseL, baseC, stdDev, chromaScale) {
326
358
  // Mitte (0.3-0.85): Nahezu volle Chroma möglich
327
359
  let lightnessLimit;
328
360
  if (stepL > 0.85) {
329
- // Steep falloff for near-white steps
330
- const t = (stepL - 0.85) / 0.15; // 0 at L=0.85, 1 at L=1.0
331
- lightnessLimit = 1.0 - t * t; // quadratic drop
361
+ const t = (stepL - 0.85) / 0.15;
362
+ lightnessLimit = 1.0 - t * t;
332
363
  } else if (stepL < 0.3) {
333
- // Moderate falloff for near-black steps
334
- const t = stepL / 0.3; // 0 at L=0, 1 at L=0.3
335
- lightnessLimit = t * t; // quadratic rise
364
+ const t = stepL / 0.3;
365
+ lightnessLimit = t * t;
336
366
  } else {
337
367
  lightnessLimit = 1.0;
338
368
  }