@webmate-studio/builder 0.2.137 → 0.2.140

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.137",
3
+ "version": "0.2.140",
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: 28, chromaScale: 1.0 },
20
- natural: { label: 'Natürlich', stdDev: 20, chromaScale: 0.85 },
21
- soft: { label: 'Pastellig', stdDev: 13, chromaScale: 0.7 },
22
- muted: { label: 'Gedämpft', stdDev: 18, chromaScale: 0.5 },
19
+ vivid: { label: 'Leuchtend', stdDev: 50, chromaScale: 1.2 },
20
+ natural: { label: 'Natürlich', stdDev: 30, chromaScale: 1.0 },
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
  /**
@@ -42,8 +42,8 @@ export function generateColorScale(baseHex, curve) {
42
42
  const stdDev = curve?.preset === 'custom' ? (curve.stdDev ?? 20) : (preset?.stdDev ?? 20);
43
43
  const chromaScale = curve?.preset === 'custom' ? (curve.chromaScale ?? 0.85) : (preset?.chromaScale ?? 0.85);
44
44
 
45
- // Neutral-Erkennung: Basis mit niedriger Chroma
46
- const isNeutral = base.c < 0.04;
45
+ // Neutral-Erkennung: Basis mit sehr niedriger Chroma (reines Grau)
46
+ const isPureNeutral = base.c < 0.008;
47
47
 
48
48
  // Lightness-Rampe adaptiv an Base-Lightness
49
49
  const L = buildLightnessRamp(base.l);
@@ -62,7 +62,8 @@ export function generateColorScale(baseHex, curve) {
62
62
 
63
63
  // Chroma über Gaußkurve berechnen
64
64
  let c;
65
- if (isNeutral) {
65
+ if (isPureNeutral) {
66
+ // Reines Grau: minimale Chroma, Step 1 wird weiß
66
67
  c = base.c * 0.3;
67
68
  } else if (step === 9) {
68
69
  // Geclampt: volle Base-Chroma bei korrigierter Lightness
@@ -75,8 +76,8 @@ export function generateColorScale(baseHex, curve) {
75
76
  scale[step] = oklchToHex(mapped.l, mapped.c, mapped.h);
76
77
  }
77
78
 
78
- // Neutral Step 1 = reines Weiß
79
- if (isNeutral) {
79
+ // Reines Neutral Step 1 = reines Weiß
80
+ if (isPureNeutral) {
80
81
  scale[1] = '#ffffff';
81
82
  }
82
83
 
@@ -96,7 +97,7 @@ export function generateDarkColorScale(baseHex, curve) {
96
97
  const stdDev = curve?.preset === 'custom' ? (curve.stdDev ?? 20) : (preset?.stdDev ?? 20);
97
98
  const chromaScale = curve?.preset === 'custom' ? (curve.chromaScale ?? 0.85) : (preset?.chromaScale ?? 0.85);
98
99
 
99
- const isNeutral = base.c < 0.04;
100
+ const isPureNeutral = base.c < 0.008;
100
101
 
101
102
  // Dark Mode: Base etwas heller für bessere Sichtbarkeit
102
103
  const darkBaseL = Math.min(base.l + 0.08, 0.65);
@@ -108,7 +109,7 @@ export function generateDarkColorScale(baseHex, curve) {
108
109
  for (let i = 0; i < 12; i++) {
109
110
  const step = i + 1;
110
111
  let c;
111
- if (isNeutral) {
112
+ if (isPureNeutral) {
112
113
  c = base.c * 0.3;
113
114
  } else {
114
115
  c = computeChroma(L[i], L[8], base.c, stdDev, chromaScale);
@@ -315,14 +316,38 @@ function buildDarkLightnessRamp(darkBaseL) {
315
316
  * sind — wie bei Radix Colors.
316
317
  */
317
318
  function computeChroma(stepL, baseL, baseC, stdDev, chromaScale) {
318
- // Gaußkurve: Peak bei baseL
319
+ // Gaußkurve mit Plateau: In der Nähe der Base bleibt Chroma nahe 100%,
320
+ // erst weiter entfernt greift die Gaußkurve richtig.
321
+ // Das verhindert den harten Sprung bei Steps 8/10 vs. Base.
319
322
  const diff = baseL - stepL;
320
- const gaussian = Math.exp((-25 / stdDev) * diff * diff);
323
+ const absDiff = Math.abs(diff);
324
+
325
+ // Plateau-Radius: Innerhalb dieses L-Abstands bleibt Chroma nahe Base-Level
326
+ const plateau = 0.08;
327
+ let gaussian;
328
+ if (absDiff <= plateau) {
329
+ // Innerhalb des Plateaus: sanfter cosinus-Übergang (1.0 → ~0.97)
330
+ gaussian = 1.0 - 0.03 * (absDiff / plateau);
331
+ } else {
332
+ // Außerhalb: Gauß ab der Plateau-Kante
333
+ const edgeDiff = absDiff - plateau;
334
+ gaussian = 0.97 * Math.exp((-12 / stdDev) * edgeDiff * edgeDiff);
335
+ }
321
336
 
322
- // Lightness-Begrenzung: Wie viel Chroma ist bei dieser Lightness sinnvoll?
323
- // Bei L=0 oder L=1 0, bei L≈0.5-0.7 Maximum
324
- // Formel: sin-artige Kurve die bei L=0 und L=1 null ist
325
- const lightnessLimit = Math.pow(Math.sin(stepL * Math.PI), 1.2);
337
+ // Lightness-Begrenzung: Asymmetrisch
338
+ // Helle Seite (L > 0.85): Chroma fällt steil auf 0 Steps 1-2 bleiben fast weiß
339
+ // Dunkle Seite (L < 0.3): Chroma fällt moderat Steps 11-12 behalten Farbton
340
+ // Mitte (0.3-0.85): Nahezu volle Chroma möglich
341
+ let lightnessLimit;
342
+ if (stepL > 0.85) {
343
+ const t = (stepL - 0.85) / 0.15;
344
+ lightnessLimit = 1.0 - t * t;
345
+ } else if (stepL < 0.3) {
346
+ const t = stepL / 0.3;
347
+ lightnessLimit = t * t;
348
+ } else {
349
+ lightnessLimit = 1.0;
350
+ }
326
351
 
327
352
  return baseC * gaussian * lightnessLimit * chromaScale;
328
353
  }