@webmate-studio/builder 0.2.134 → 0.2.136

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.134",
3
+ "version": "0.2.136",
4
4
  "type": "module",
5
5
  "description": "Webmate Studio Component Builder",
6
6
  "keywords": [
@@ -13,6 +13,7 @@ import {
13
13
  BUTTON_VARIANTS,
14
14
  BUTTON_SIZES,
15
15
  calculateOnColor,
16
+ DEFAULT_SURFACE_TOKENS,
16
17
  defaultDesignTokensV2
17
18
  } from './design-tokens-v2.js';
18
19
 
@@ -142,6 +143,22 @@ function generateColorVariables(t, lines) {
142
143
  if (mapping.ring) lines.push(` --color-${world}-ring: var(--color-${world}-${mapping.ring});`);
143
144
  }
144
145
  }
146
+
147
+ // Surface, Text & Border Tokens
148
+ const surface = t.surface || DEFAULT_SURFACE_TOKENS;
149
+ lines.push(' /* surface tokens */');
150
+ if (surface.page) lines.push(` --color-surface-page: ${resolveColorRef(surface.page, t)};`);
151
+ if (surface.elevated) lines.push(` --color-surface-elevated: ${resolveColorRef(surface.elevated, t)};`);
152
+ if (surface.lifted) lines.push(` --color-surface-lifted: ${resolveColorRef(surface.lifted, t)};`);
153
+ if (surface.overlay) lines.push(` --color-surface-overlay: ${resolveColorRef(surface.overlay, t)};`);
154
+ lines.push(' /* text tokens */');
155
+ if (surface.textDefault) lines.push(` --color-text-default: ${resolveColorRef(surface.textDefault, t)};`);
156
+ if (surface.textSubtle) lines.push(` --color-text-subtle: ${resolveColorRef(surface.textSubtle, t)};`);
157
+ if (surface.textMuted) lines.push(` --color-text-muted: ${resolveColorRef(surface.textMuted, t)};`);
158
+ lines.push(' /* border tokens */');
159
+ if (surface.borderDefault) lines.push(` --color-border-default: ${resolveColorRef(surface.borderDefault, t)};`);
160
+ if (surface.borderSubtle) lines.push(` --color-border-subtle: ${resolveColorRef(surface.borderSubtle, t)};`);
161
+ if (surface.borderStrong) lines.push(` --color-border-strong: ${resolveColorRef(surface.borderStrong, t)};`);
145
162
  }
146
163
 
147
164
 
@@ -205,6 +222,42 @@ function generateColorUtilities(t) {
205
222
  }
206
223
  }
207
224
 
225
+ // Surface Utilities: bg-page, bg-elevated, bg-lifted, bg-overlay
226
+ const surfaceUtils = [
227
+ { cls: 'bg-page', prop: 'background-color', varRef: '--color-surface-page' },
228
+ { cls: 'bg-elevated', prop: 'background-color', varRef: '--color-surface-elevated' },
229
+ { cls: 'bg-lifted', prop: 'background-color', varRef: '--color-surface-lifted' },
230
+ { cls: 'bg-overlay', prop: 'background-color', varRef: '--color-surface-overlay' },
231
+ ];
232
+
233
+ for (const { cls, prop, varRef } of surfaceUtils) {
234
+ css += `\n.${cls} { ${prop}: var(${varRef}); }`;
235
+ }
236
+
237
+ // Text Utilities: text-default, text-subtle, text-muted
238
+ const textUtils = [
239
+ { cls: 'text-default', prop: 'color', varRef: '--color-text-default' },
240
+ { cls: 'text-subtle', prop: 'color', varRef: '--color-text-subtle' },
241
+ { cls: 'text-muted', prop: 'color', varRef: '--color-text-muted' },
242
+ ];
243
+
244
+ for (const { cls, prop, varRef } of textUtils) {
245
+ css += `\n.${cls} { ${prop}: var(${varRef}); }`;
246
+ css += `\n.hover\\:${cls}:hover { ${prop}: var(${varRef}); }`;
247
+ }
248
+
249
+ // Border Utilities: border-default, border-subtle, border-strong
250
+ const borderUtils = [
251
+ { cls: 'border-default', prop: 'border-color', varRef: '--color-border-default' },
252
+ { cls: 'border-subtle', prop: 'border-color', varRef: '--color-border-subtle' },
253
+ { cls: 'border-strong', prop: 'border-color', varRef: '--color-border-strong' },
254
+ ];
255
+
256
+ for (const { cls, prop, varRef } of borderUtils) {
257
+ css += `\n.${cls} { ${prop}: var(${varRef}); }`;
258
+ css += `\n.hover\\:${cls}:hover { ${prop}: var(${varRef}); }`;
259
+ }
260
+
208
261
  css += '\n}'; // Close @layer utilities
209
262
  return css;
210
263
  }
@@ -686,8 +739,8 @@ function generateBaseStyles(t) {
686
739
  return `\n/* Global baseline styles */
687
740
  body {
688
741
  font-family: ${fontFamily};
689
- background-color: var(--color-neutral-1);
690
- color: var(--color-neutral-12);
742
+ background-color: var(--color-surface-page);
743
+ color: var(--color-text-default);
691
744
  }`;
692
745
  }
693
746
 
@@ -22,25 +22,29 @@ export function generateColorScale(baseHex) {
22
22
  if (!rgb) return null;
23
23
 
24
24
  const hsl = rgbToHsl(rgb.r, rgb.g, rgb.b);
25
+ const h = hsl.h;
26
+ const s = hsl.s;
27
+ const l = hsl.l;
25
28
 
26
29
  // Neutral-Erkennung: Basis mit niedriger Sättigung (<15%)
27
- // bekommt deutlich reduzierte Sättigung über die gesamte Skala
28
- const isNeutral = hsl.s < 15;
29
- const sFactor = isNeutral ? 0.3 : 1; // Sättigung auf 30% für Neutraltöne
30
+ const isNeutral = s < 15;
31
+ const sFactor = isNeutral ? 0.15 : 1;
32
+ // Helle Stufen: leichter Hue-Shift für natürlichere Farbverläufe
33
+ const hShift = isNeutral ? 0 : -5;
30
34
 
31
35
  return {
32
- 1: hslToHex(hsl.h, Math.max(hsl.s * 0.15 * sFactor, isNeutral ? 0 : 2), 97),
33
- 2: hslToHex(hsl.h, Math.max(hsl.s * 0.2 * sFactor, isNeutral ? 0.5 : 3), 95),
34
- 3: hslToHex(hsl.h, Math.max(hsl.s * 0.3 * sFactor, isNeutral ? 1 : 5), 91),
35
- 4: hslToHex(hsl.h, Math.max(hsl.s * 0.4 * sFactor, isNeutral ? 1.5 : 7), 86),
36
- 5: hslToHex(hsl.h, Math.max(hsl.s * 0.5 * sFactor, isNeutral ? 2 : 9), 80),
37
- 6: hslToHex(hsl.h, hsl.s * 0.65 * sFactor, 70),
38
- 7: hslToHex(hsl.h, hsl.s * 0.8 * sFactor, 58),
39
- 8: hslToHex(hsl.h, hsl.s * 0.9 * sFactor, 48),
40
- 9: baseHex,
41
- 10: hslToHex(hsl.h, Math.min(hsl.s * 1.05 * sFactor, 100), Math.max(hsl.l - 8, 10)),
42
- 11: hslToHex(hsl.h, Math.min(hsl.s * 0.9 * sFactor, 100), Math.max(hsl.l - 20, 15)),
43
- 12: hslToHex(hsl.h, Math.min(hsl.s * 0.7 * sFactor, 80), Math.max(hsl.l - 35, 8)),
36
+ 1: isNeutral ? '#ffffff' : hslToHex(h + hShift, Math.min(s * 0.85, 70), 99),
37
+ 2: hslToHex(h + hShift, Math.min(s * 0.65 * sFactor, isNeutral ? 4 : 55), 97),
38
+ 3: hslToHex(h + hShift, Math.min(s * 0.72 * sFactor, isNeutral ? 5 : 60), 94),
39
+ 4: hslToHex(h + hShift, Math.min(s * 0.7 * sFactor, isNeutral ? 5 : 58), 89),
40
+ 5: hslToHex(h + hShift, Math.min(s * 0.68 * sFactor, isNeutral ? 5 : 55), 84),
41
+ 6: hslToHex(h - 2, Math.min(s * 0.63 * sFactor, isNeutral ? 5 : 52), 77),
42
+ 7: hslToHex(h - 1, Math.min(s * 0.6 * sFactor, isNeutral ? 5 : 50), 68),
43
+ 8: hslToHex(h, Math.min(s * 0.62 * sFactor, isNeutral ? 6 : 50), 53),
44
+ 9: baseHex,
45
+ 10: hslToHex(h + 2, Math.min(s * 1.3 * sFactor, isNeutral ? 8 : 100), Math.max(l - 7, 15)),
46
+ 11: hslToHex(h + 1, Math.min(s * 1.3 * sFactor, isNeutral ? 6 : 100), Math.max(l - 11, 20)),
47
+ 12: hslToHex(h - 5, Math.min(s * 0.55 * sFactor, isNeutral ? 4 : 45), isNeutral ? 13 : Math.max(l * 0.5, 15)),
44
48
  };
45
49
  }
46
50
 
@@ -53,27 +57,29 @@ export function generateDarkColorScale(baseHex) {
53
57
  if (!rgb) return null;
54
58
 
55
59
  const hsl = rgbToHsl(rgb.r, rgb.g, rgb.b);
60
+ const h = hsl.h;
61
+ const s = hsl.s;
62
+ const l = hsl.l;
56
63
 
57
- // Neutral-Erkennung: gleiche Logik wie generateColorScale
58
- const isNeutral = hsl.s < 15;
59
- const sFactor = isNeutral ? 0.3 : 1;
64
+ const isNeutral = s < 15;
65
+ const sFactor = isNeutral ? 0.15 : 1;
60
66
 
61
67
  // Dark Mode: Basis etwas heller für bessere Sichtbarkeit
62
- const darkBase = hslToHex(hsl.h, Math.min(hsl.s * 1.1 * sFactor, 100), Math.min(hsl.l + 10, 65));
68
+ const darkBase = hslToHex(h, Math.min(s * 1.1 * sFactor, isNeutral ? 8 : 100), Math.min(l + 10, 65));
63
69
 
64
70
  return {
65
- 1: hslToHex(hsl.h, Math.max(hsl.s * 0.3 * sFactor, isNeutral ? 0 : 5), 8),
66
- 2: hslToHex(hsl.h, Math.max(hsl.s * 0.35 * sFactor, isNeutral ? 0.5 : 6), 12),
67
- 3: hslToHex(hsl.h, Math.max(hsl.s * 0.45 * sFactor, isNeutral ? 1 : 8), 18),
68
- 4: hslToHex(hsl.h, Math.max(hsl.s * 0.55 * sFactor, isNeutral ? 1.5 : 10), 24),
69
- 5: hslToHex(hsl.h, Math.max(hsl.s * 0.6 * sFactor, isNeutral ? 2 : 12), 30),
70
- 6: hslToHex(hsl.h, hsl.s * 0.65 * sFactor, 38),
71
- 7: hslToHex(hsl.h, hsl.s * 0.75 * sFactor, 48),
72
- 8: hslToHex(hsl.h, hsl.s * 0.85 * sFactor, 58),
73
- 9: darkBase,
74
- 10: hslToHex(hsl.h, Math.min(hsl.s * 1.0 * sFactor, 100), Math.min(hsl.l + 20, 75)),
75
- 11: hslToHex(hsl.h, Math.min(hsl.s * 0.7 * sFactor, 80), Math.min(hsl.l + 35, 85)),
76
- 12: hslToHex(hsl.h, Math.min(hsl.s * 0.4 * sFactor, 50), Math.min(hsl.l + 50, 95)),
71
+ 1: hslToHex(h, Math.min(s * 0.35 * sFactor, isNeutral ? 2 : 15), 8),
72
+ 2: hslToHex(h, Math.min(s * 0.4 * sFactor, isNeutral ? 3 : 18), 12),
73
+ 3: hslToHex(h, Math.min(s * 0.5 * sFactor, isNeutral ? 4 : 22), 18),
74
+ 4: hslToHex(h, Math.min(s * 0.55 * sFactor, isNeutral ? 4 : 28), 24),
75
+ 5: hslToHex(h, Math.min(s * 0.6 * sFactor, isNeutral ? 5 : 32), 30),
76
+ 6: hslToHex(h - 2, Math.min(s * 0.63 * sFactor, isNeutral ? 5 : 40), 38),
77
+ 7: hslToHex(h - 1, Math.min(s * 0.7 * sFactor, isNeutral ? 5 : 48), 48),
78
+ 8: hslToHex(h, Math.min(s * 0.8 * sFactor, isNeutral ? 6 : 55), 58),
79
+ 9: darkBase,
80
+ 10: hslToHex(h + 1, Math.min(s * 0.85 * sFactor, isNeutral ? 6 : 65), Math.min(l + 20, 75)),
81
+ 11: hslToHex(h + 2, Math.min(s * 0.6 * sFactor, isNeutral ? 5 : 50), Math.min(l + 35, 85)),
82
+ 12: hslToHex(h - 3, Math.min(s * 0.35 * sFactor, isNeutral ? 3 : 30), Math.min(l + 50, 95)),
77
83
  };
78
84
  }
79
85
 
@@ -204,6 +210,45 @@ export const DEFAULT_SEMANTIC_MAPPINGS = {
204
210
  };
205
211
 
206
212
 
213
+ // ─── Surface & Text Tokens ─────────────────────────────────────────────────
214
+
215
+ /**
216
+ * Globale Surface-, Text- und Border-Aliase.
217
+ * Mappen semantische Konzepte (page, elevated, default, muted)
218
+ * auf Neutral-Stufen. Damit braucht der User kein Radix-Insiderwissen.
219
+ */
220
+ export const DEFAULT_SURFACE_TOKENS = {
221
+ page: 'neutral-1',
222
+ elevated: 'neutral-2',
223
+ lifted: 'neutral-3',
224
+ overlay: 'neutral-1/80',
225
+
226
+ textDefault: 'neutral-12',
227
+ textSubtle: 'neutral-11',
228
+ textMuted: 'neutral-8',
229
+
230
+ borderDefault: 'neutral-6',
231
+ borderSubtle: 'neutral-4',
232
+ borderStrong: 'neutral-7'
233
+ };
234
+
235
+ /**
236
+ * Labels und Beschreibungen für den Editor.
237
+ */
238
+ export const SURFACE_TOKEN_META = {
239
+ page: { label: 'Page', desc: 'Seitenhintergrund (body)', group: 'surface' },
240
+ elevated: { label: 'Elevated', desc: 'Karten, Modals, Panels', group: 'surface' },
241
+ lifted: { label: 'Lifted', desc: 'Element auf erhöhter Fläche', group: 'surface' },
242
+ overlay: { label: 'Overlay', desc: 'Backdrop / Overlay', group: 'surface' },
243
+ textDefault: { label: 'Default', desc: 'Standard-Textfarbe', group: 'text' },
244
+ textSubtle: { label: 'Subtle', desc: 'Sekundärer Text', group: 'text' },
245
+ textMuted: { label: 'Muted', desc: 'Platzhalter, deaktiviert', group: 'text' },
246
+ borderDefault: { label: 'Default', desc: 'Standard-Rahmen', group: 'border' },
247
+ borderSubtle: { label: 'Subtle', desc: 'Dezenter Rahmen', group: 'border' },
248
+ borderStrong: { label: 'Strong', desc: 'Starker Rahmen (Inputs)', group: 'border' }
249
+ };
250
+
251
+
207
252
  // ─── Typografie ─────────────────────────────────────────────────────────────
208
253
 
209
254
  /**
@@ -299,6 +344,8 @@ export const defaultDesignTokensV2 = {
299
344
  info: { ...DEFAULT_SEMANTIC_MAPPINGS }
300
345
  },
301
346
 
347
+ surface: { ...DEFAULT_SURFACE_TOKENS },
348
+
302
349
  darkMode: {
303
350
  enabled: false,
304
351
  colors: null, // Wird bei Aktivierung auto-generiert