@webmate-studio/builder 0.2.65 → 0.2.67

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.65",
3
+ "version": "0.2.67",
4
4
  "type": "module",
5
5
  "description": "Webmate Studio Component Builder",
6
6
  "keywords": [
@@ -1,3 +1,71 @@
1
+ /**
2
+ * Generate color utility classes (bg-*, text-*, border-*)
3
+ * ALL colors are available in ALL variants (text, bg, border)
4
+ * Used by both generateTailwindV4Theme and generateCSSFromTokens
5
+ */
6
+ function generateSemanticColorUtilities(tokens) {
7
+ if (!tokens.colors) return '';
8
+
9
+ let utilities = '\n/* Color Utilities */';
10
+
11
+ // Map of all colors: token name -> utility class base name
12
+ const colorMap = {
13
+ // Brand colors
14
+ 'primary': 'primary',
15
+ 'secondary': 'secondary',
16
+
17
+ // Base semantic colors
18
+ 'bgBase': 'default',
19
+ 'bgElevated': 'elevated',
20
+ 'bgLifted': 'lifted',
21
+ 'textBase': 'default',
22
+ 'textSubtle': 'subtle',
23
+ 'textMuted': 'muted',
24
+ 'borderBase': 'default',
25
+ 'borderSubtle': 'subtle',
26
+ 'borderMuted': 'muted',
27
+
28
+ // Accent colors
29
+ 'bgAccentBase': 'accent-default',
30
+ 'bgAccentElevated': 'accent-elevated',
31
+ 'bgAccentLifted': 'accent-lifted',
32
+ 'textAccentBase': 'accent-default',
33
+ 'textAccentSubtle': 'accent-subtle',
34
+ 'textAccentMuted': 'accent-muted',
35
+ 'borderAccentBase': 'accent-default',
36
+ 'borderAccentSubtle': 'accent-subtle',
37
+ 'borderAccentMuted': 'accent-muted'
38
+ };
39
+
40
+ // Collect unique base names (deduplicate)
41
+ const processedNames = new Set();
42
+
43
+ for (const [tokenKey, baseName] of Object.entries(colorMap)) {
44
+ if (!tokens.colors[tokenKey]) continue;
45
+
46
+ // Skip if we already processed this base name
47
+ if (processedNames.has(baseName)) continue;
48
+ processedNames.add(baseName);
49
+
50
+ const colorVar = `--color-${tokenKey.replace(/([A-Z])/g, '-$1').toLowerCase()}`;
51
+
52
+ // Generate all three variants for every color
53
+ utilities += `\n.text-${baseName} {`;
54
+ utilities += `\n color: var(${colorVar});`;
55
+ utilities += `\n}`;
56
+
57
+ utilities += `\n.bg-${baseName} {`;
58
+ utilities += `\n background-color: var(${colorVar});`;
59
+ utilities += `\n}`;
60
+
61
+ utilities += `\n.border-${baseName} {`;
62
+ utilities += `\n border-color: var(${colorVar});`;
63
+ utilities += `\n}`;
64
+ }
65
+
66
+ return utilities;
67
+ }
68
+
1
69
  /**
2
70
  * Default Design Tokens für Website-Design
3
71
  * Tailwind v4 kompatibel - verwendet Base-Values wo möglich
@@ -49,7 +117,12 @@ export const defaultDesignTokens = {
49
117
  // Border Colors (Semantic)
50
118
  borderBase: '#d1d5db', // slate-300 - Standard Border
51
119
  borderSubtle: '#e5e7eb', // slate-200 - Dezenter Border
52
- borderMuted: '#f3f4f6' // slate-100 - Sehr dezenter Border
120
+ borderMuted: '#f3f4f6', // slate-100 - Sehr dezenter Border
121
+
122
+ // Border Colors (Accent)
123
+ borderAccentBase: '#8b5cf6', // violet-500
124
+ borderAccentSubtle: '#a78bfa', // violet-400
125
+ borderAccentMuted: '#c4b5fd' // violet-300
53
126
  },
54
127
 
55
128
  typography: {
@@ -441,7 +514,7 @@ export function generateTailwindV4Theme(tokens) {
441
514
  // Text Styles - Generate CSS variables for each style (with responsive support)
442
515
  if (tokens.textStyles) {
443
516
  for (const [styleName, style] of Object.entries(tokens.textStyles)) {
444
- const kebabName = styleName.replace(/([A-Z])/g, '-$1').toLowerCase();
517
+ const kebabName = styleName.replace(/([A-Z0-9])/g, '-$1').toLowerCase();
445
518
 
446
519
  // Font family (not responsive)
447
520
  if (style.fontFamily) {
@@ -581,7 +654,7 @@ body {
581
654
  if (tokens.textStyles) {
582
655
  globalStyles += '\n\n/* Text Style Utilities */';
583
656
  for (const [styleName, style] of Object.entries(tokens.textStyles)) {
584
- const kebabName = styleName.replace(/([A-Z])/g, '-$1').toLowerCase();
657
+ const kebabName = styleName.replace(/([A-Z0-9])/g, '-$1').toLowerCase();
585
658
  const className = `text-${kebabName}`;
586
659
 
587
660
  globalStyles += `\n.${className} {`;
@@ -627,12 +700,16 @@ body {
627
700
  // Size classes
628
701
  if (tokens.buttons.sizes) {
629
702
  for (const sizeName of Object.keys(tokens.buttons.sizes)) {
703
+ const size = tokens.buttons.sizes[sizeName];
704
+ // Calculate unitless line-height (lineHeight in px / fontSize in px)
705
+ const lineHeightRatio = size.lineHeight / size.fontSize;
706
+
630
707
  globalStyles += `\n.btn-${sizeName} {
631
- padding: var(--button-${sizeName}-padding-y) var(--button-${sizeName}-padding-x);
632
- font-size: var(--button-${sizeName}-font-size);
633
- line-height: var(--button-${sizeName}-line-height);
634
- border-radius: var(--button-${sizeName}-border-radius);
635
- gap: var(--button-${sizeName}-gap);
708
+ padding: ${size.paddingY}px ${size.paddingX}px;
709
+ font-size: ${size.fontSize}px;
710
+ line-height: ${lineHeightRatio};
711
+ border-radius: ${size.borderRadius}px;
712
+ gap: ${size.gap}px;
636
713
  }`;
637
714
  }
638
715
  }
@@ -667,7 +744,7 @@ body {
667
744
  const mediaQueryLines = [];
668
745
 
669
746
  for (const [styleName, style] of Object.entries(tokens.textStyles)) {
670
- const kebabName = styleName.replace(/([A-Z])/g, '-$1').toLowerCase();
747
+ const kebabName = styleName.replace(/([A-Z0-9])/g, '-$1').toLowerCase();
671
748
 
672
749
  // Font size
673
750
  if (style.fontSize && typeof style.fontSize === 'object' && style.fontSize[bp]) {
@@ -693,6 +770,9 @@ body {
693
770
  }
694
771
  }
695
772
 
773
+ // Add semantic color utilities
774
+ globalStyles += generateSemanticColorUtilities(tokens);
775
+
696
776
  return { themeVars, globalStyles };
697
777
  }
698
778
 
@@ -867,7 +947,7 @@ export function generateCSSFromTokens(tokens) {
867
947
  lines.push('');
868
948
  lines.push('/* Text Style Utilities */');
869
949
  for (const [styleName, style] of Object.entries(tokens.textStyles)) {
870
- const kebabName = styleName.replace(/([A-Z])/g, '-$1').toLowerCase();
950
+ const kebabName = styleName.replace(/([A-Z0-9])/g, '-$1').toLowerCase();
871
951
  const className = `text-${kebabName}`;
872
952
 
873
953
  lines.push(`.${className} {`);
@@ -913,7 +993,7 @@ export function generateCSSFromTokens(tokens) {
913
993
  const mediaQueryLines = [];
914
994
 
915
995
  for (const [styleName, style] of Object.entries(tokens.textStyles)) {
916
- const kebabName = styleName.replace(/([A-Z])/g, '-$1').toLowerCase();
996
+ const kebabName = styleName.replace(/([A-Z0-9])/g, '-$1').toLowerCase();
917
997
  const className = `text-${kebabName}`;
918
998
  const hasResponsive = (
919
999
  (style.fontSize && typeof style.fontSize === 'object' && style.fontSize[bp]) ||
@@ -1109,57 +1189,10 @@ export function generateCSSFromTokens(tokens) {
1109
1189
  }
1110
1190
  }
1111
1191
 
1112
- // Generate utility classes for semantic colors
1113
- if (tokens.colors) {
1114
- lines.push('');
1115
- lines.push('/* Semantic Color Utilities */');
1116
-
1117
- // Background colors
1118
- const bgColors = [
1119
- 'bgBase', 'bgElevated', 'bgLifted',
1120
- 'bgAccentBase', 'bgAccentElevated', 'bgAccentLifted'
1121
- ];
1122
- for (const colorKey of bgColors) {
1123
- if (tokens.colors[colorKey]) {
1124
- const kebabName = colorKey.replace(/([A-Z])/g, '-$1').toLowerCase().replace('bg-', '');
1125
- const className = `bg-${kebabName}`;
1126
- const colorVar = `--color-${colorKey.replace(/([A-Z])/g, '-$1').toLowerCase()}`;
1127
- lines.push(`.${className} {`);
1128
- lines.push(` background-color: var(${colorVar});`);
1129
- lines.push('}');
1130
- }
1131
- }
1132
-
1133
- // Text colors
1134
- const textColors = [
1135
- 'textBase', 'textSubtle', 'textMuted',
1136
- 'textAccentBase', 'textAccentSubtle', 'textAccentMuted'
1137
- ];
1138
- for (const colorKey of textColors) {
1139
- if (tokens.colors[colorKey]) {
1140
- const kebabName = colorKey.replace(/([A-Z])/g, '-$1').toLowerCase().replace('text-', '');
1141
- const className = `text-${kebabName}`;
1142
- const colorVar = `--color-${colorKey.replace(/([A-Z])/g, '-$1').toLowerCase()}`;
1143
- lines.push(`.${className} {`);
1144
- lines.push(` color: var(${colorVar});`);
1145
- lines.push('}');
1146
- }
1147
- }
1148
-
1149
- // Border colors
1150
- const borderColors = [
1151
- 'borderBase', 'borderSubtle', 'borderMuted'
1152
- ];
1153
- for (const colorKey of borderColors) {
1154
- if (tokens.colors[colorKey]) {
1155
- const kebabName = colorKey.replace(/([A-Z])/g, '-$1').toLowerCase().replace('border-', '');
1156
- const className = `border-${kebabName}`;
1157
- const colorVar = `--color-${colorKey.replace(/([A-Z])/g, '-$1').toLowerCase()}`;
1158
- lines.push(`.${className} {`);
1159
- lines.push(` border-color: var(${colorVar});`);
1160
- lines.push('}');
1161
- }
1162
- }
1192
+ // Add semantic color utilities
1193
+ const semanticUtilities = generateSemanticColorUtilities(tokens);
1194
+ if (semanticUtilities) {
1195
+ lines.push(semanticUtilities);
1163
1196
  }
1164
1197
 
1165
1198
  return lines.join('\n');