@webmate-studio/builder 0.2.117 → 0.2.118

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.117",
3
+ "version": "0.2.118",
4
4
  "type": "module",
5
5
  "description": "Webmate Studio Component Builder",
6
6
  "keywords": [
@@ -7,7 +7,6 @@ function generateSemanticColorUtilities(tokens) {
7
7
  if (!tokens.colors) return '';
8
8
 
9
9
  let utilities = '\n/* Color Utilities */';
10
- utilities += '\n@layer utilities {';
11
10
 
12
11
  // Map of all colors: token name -> utility class base name
13
12
  const colorMap = {
@@ -59,7 +58,12 @@ function generateSemanticColorUtilities(tokens) {
59
58
  // Text-on-background colors
60
59
  'textOnPrimary': 'text-on-primary',
61
60
  'textOnSecondary': 'text-on-secondary',
62
- 'textOnAccent': 'text-on-accent'
61
+ 'textOnAccent': 'text-on-accent',
62
+
63
+ // Border-on-background colors (borders on colored backgrounds)
64
+ 'borderOnPrimary': 'border-on-primary',
65
+ 'borderOnSecondary': 'border-on-secondary',
66
+ 'borderOnAccent': 'border-on-accent'
63
67
  };
64
68
 
65
69
  // Collect unique class names (deduplicate)
@@ -73,55 +77,27 @@ function generateSemanticColorUtilities(tokens) {
73
77
  // Determine which type(s) of utility classes to generate based on className prefix
74
78
  // If className already has prefix (bg-, text-, border-), generate only that variant
75
79
  // Otherwise generate all three variants
80
+ // Using @utility instead of @layer utilities gives full Tailwind v4 variant support
81
+ // (hover:, focus:, sm:, md:, lg:, xl:, 2xl:, etc.)
76
82
 
77
83
  if (className.startsWith('bg-')) {
78
- // Only generate bg-* utility (with hover/focus/active variants)
79
84
  if (!processedClasses.has(className)) {
80
85
  processedClasses.add(className);
81
- // Base class
82
- utilities += `\n.${className} {`;
83
- utilities += `\n background-color: var(${colorVar});`;
84
- utilities += `\n}`;
85
- // Hover variant
86
- utilities += `\n.hover\\:${className}:hover {`;
87
- utilities += `\n background-color: var(${colorVar});`;
88
- utilities += `\n}`;
89
- // Focus variant
90
- utilities += `\n.focus\\:${className}:focus {`;
86
+ utilities += `\n@utility ${className} {`;
91
87
  utilities += `\n background-color: var(${colorVar});`;
92
88
  utilities += `\n}`;
93
89
  }
94
90
  } else if (className.startsWith('text-')) {
95
- // Only generate text-* utility (with hover/focus/active variants)
96
91
  if (!processedClasses.has(className)) {
97
92
  processedClasses.add(className);
98
- // Base class
99
- utilities += `\n.${className} {`;
100
- utilities += `\n color: var(${colorVar});`;
101
- utilities += `\n}`;
102
- // Hover variant
103
- utilities += `\n.hover\\:${className}:hover {`;
104
- utilities += `\n color: var(${colorVar});`;
105
- utilities += `\n}`;
106
- // Focus variant
107
- utilities += `\n.focus\\:${className}:focus {`;
93
+ utilities += `\n@utility ${className} {`;
108
94
  utilities += `\n color: var(${colorVar});`;
109
95
  utilities += `\n}`;
110
96
  }
111
97
  } else if (className.startsWith('border-')) {
112
- // Only generate border-* utility (with hover/focus/active variants)
113
98
  if (!processedClasses.has(className)) {
114
99
  processedClasses.add(className);
115
- // Base class
116
- utilities += `\n.${className} {`;
117
- utilities += `\n border-color: var(${colorVar});`;
118
- utilities += `\n}`;
119
- // Hover variant
120
- utilities += `\n.hover\\:${className}:hover {`;
121
- utilities += `\n border-color: var(${colorVar});`;
122
- utilities += `\n}`;
123
- // Focus variant
124
- utilities += `\n.focus\\:${className}:focus {`;
100
+ utilities += `\n@utility ${className} {`;
125
101
  utilities += `\n border-color: var(${colorVar});`;
126
102
  utilities += `\n}`;
127
103
  }
@@ -133,49 +109,62 @@ function generateSemanticColorUtilities(tokens) {
133
109
 
134
110
  if (!processedClasses.has(textClass)) {
135
111
  processedClasses.add(textClass);
136
- // Base class
137
- utilities += `\n.${textClass} {`;
138
- utilities += `\n color: var(${colorVar});`;
139
- utilities += `\n}`;
140
- // Hover variant
141
- utilities += `\n.hover\\:${textClass}:hover {`;
142
- utilities += `\n color: var(${colorVar});`;
143
- utilities += `\n}`;
144
- // Focus variant
145
- utilities += `\n.focus\\:${textClass}:focus {`;
112
+ utilities += `\n@utility ${textClass} {`;
146
113
  utilities += `\n color: var(${colorVar});`;
147
114
  utilities += `\n}`;
148
115
  }
149
116
 
150
117
  if (!processedClasses.has(bgClass)) {
151
118
  processedClasses.add(bgClass);
152
- // Base class
153
- utilities += `\n.${bgClass} {`;
154
- utilities += `\n background-color: var(${colorVar});`;
155
- utilities += `\n}`;
156
- // Hover variant
157
- utilities += `\n.hover\\:${bgClass}:hover {`;
158
- utilities += `\n background-color: var(${colorVar});`;
159
- utilities += `\n}`;
160
- // Focus variant
161
- utilities += `\n.focus\\:${bgClass}:focus {`;
119
+ utilities += `\n@utility ${bgClass} {`;
162
120
  utilities += `\n background-color: var(${colorVar});`;
163
121
  utilities += `\n}`;
164
122
  }
165
123
 
166
124
  if (!processedClasses.has(borderClass)) {
167
125
  processedClasses.add(borderClass);
168
- // Base class
169
- utilities += `\n.${borderClass} {`;
126
+ utilities += `\n@utility ${borderClass} {`;
170
127
  utilities += `\n border-color: var(${colorVar});`;
171
128
  utilities += `\n}`;
172
- // Hover variant
173
- utilities += `\n.hover\\:${borderClass}:hover {`;
174
- utilities += `\n border-color: var(${colorVar});`;
175
- utilities += `\n}`;
176
- // Focus variant
177
- utilities += `\n.focus\\:${borderClass}:focus {`;
178
- utilities += `\n border-color: var(${colorVar});`;
129
+ }
130
+ }
131
+ }
132
+
133
+ // Generate opacity variants for all color utilities using color-mix()
134
+ // These use @layer utilities (not @utility) because @utility doesn't support slash in names.
135
+ // Opacity variants don't need responsive/hover support — the base class handles that.
136
+ const opacitySteps = [10, 20, 30, 40, 50, 60, 70, 80, 90];
137
+
138
+ utilities += '\n\n/* Opacity Variants */';
139
+ utilities += '\n@layer utilities {';
140
+
141
+ for (const [tokenKey, className] of Object.entries(colorMap)) {
142
+ if (!tokens.colors[tokenKey]) continue;
143
+ const colorVar = `--color-${tokenKey.replace(/([A-Z])/g, '-$1').toLowerCase()}`;
144
+
145
+ // Determine which CSS property(ies) to use
146
+ let entries;
147
+ if (className.startsWith('bg-')) {
148
+ entries = [[className, 'background-color']];
149
+ } else if (className.startsWith('text-')) {
150
+ entries = [[className, 'color']];
151
+ } else if (className.startsWith('border-')) {
152
+ entries = [[className, 'border-color']];
153
+ } else {
154
+ entries = [
155
+ [`text-${className}`, 'color'],
156
+ [`bg-${className}`, 'background-color'],
157
+ [`border-${className}`, 'border-color']
158
+ ];
159
+ }
160
+
161
+ for (const [cls, prop] of entries) {
162
+ for (const step of opacitySteps) {
163
+ const opacityCls = `${cls}\\/${step}`;
164
+ if (processedClasses.has(opacityCls)) continue;
165
+ processedClasses.add(opacityCls);
166
+ utilities += `\n.${opacityCls} {`;
167
+ utilities += `\n ${prop}: color-mix(in srgb, var(${colorVar}) ${step}%, transparent);`;
179
168
  utilities += `\n}`;
180
169
  }
181
170
  }
@@ -252,7 +241,12 @@ export const defaultDesignTokens = {
252
241
  // Text-on-Background Colors (for text on colored backgrounds)
253
242
  textOnPrimary: '#ffffff', // Text on bg-primary
254
243
  textOnSecondary: '#ffffff', // Text on bg-secondary
255
- textOnAccent: '#ffffff' // Text on bg-accent
244
+ textOnAccent: '#ffffff', // Text on bg-accent
245
+
246
+ // Border-on-Background Colors (for borders on colored backgrounds)
247
+ borderOnPrimary: '#ffffff', // Border on bg-primary
248
+ borderOnSecondary: '#ffffff', // Border on bg-secondary
249
+ borderOnAccent: '#ffffff' // Border on bg-accent
256
250
  },
257
251
 
258
252
  typography: {
@@ -686,6 +680,11 @@ export function generateTailwindV4Theme(tokens) {
686
680
  if (tokens.colors.textOnSecondary) lines.push(` --color-text-on-secondary: ${tokens.colors.textOnSecondary};`);
687
681
  if (tokens.colors.textOnAccent) lines.push(` --color-text-on-accent: ${tokens.colors.textOnAccent};`);
688
682
 
683
+ // Border-on-background colors
684
+ if (tokens.colors.borderOnPrimary) lines.push(` --color-border-on-primary: ${tokens.colors.borderOnPrimary};`);
685
+ if (tokens.colors.borderOnSecondary) lines.push(` --color-border-on-secondary: ${tokens.colors.borderOnSecondary};`);
686
+ if (tokens.colors.borderOnAccent) lines.push(` --color-border-on-accent: ${tokens.colors.borderOnAccent};`);
687
+
689
688
  // Basic colors
690
689
  if (tokens.colors.white) lines.push(` --color-white: ${tokens.colors.white};`);
691
690
  if (tokens.colors.black) lines.push(` --color-black: ${tokens.colors.black};`);