@webmate-studio/builder 0.2.178 → 0.2.180

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.178",
3
+ "version": "0.2.180",
4
4
  "type": "module",
5
5
  "description": "Webmate Studio Component Builder",
6
6
  "keywords": [
@@ -187,9 +187,9 @@ function generateColorUtilities(t) {
187
187
 
188
188
  for (let step = 1; step <= 12; step++) {
189
189
  const varRef = `--color-${world}-${step}`;
190
- addColorUtility(css = css, processed, `bg-${world}-${step}`, 'background-color', varRef);
191
- addColorUtility(css = css, processed, `text-${world}-${step}`, 'color', varRef);
192
- addColorUtility(css = css, processed, `border-${world}-${step}`, 'border-color', varRef);
190
+ css = addColorUtility(css, processed, `bg-${world}-${step}`, 'background-color', varRef);
191
+ css = addColorUtility(css, processed, `text-${world}-${step}`, 'color', varRef);
192
+ css = addColorUtility(css, processed, `border-${world}-${step}`, 'border-color', varRef);
193
193
 
194
194
  // Opacity-Varianten
195
195
  for (const step2 of opacitySteps) {
@@ -40,7 +40,8 @@ class TemplateEvaluator {
40
40
  case 'Fragment':
41
41
  return this.evalFragment(node, ctx);
42
42
  case 'Text':
43
- return node.value;
43
+ // Strip closing tags of built-in micro-components (they output complete HTML)
44
+ return node.value.replace(/<\/wm-button>/g, '');
44
45
  case 'Expression':
45
46
  return this.evalExpression(node, ctx);
46
47
  case 'HtmlExpression':
@@ -194,6 +195,11 @@ class TemplateEvaluator {
194
195
  return this.evalIslandTag(node, ctx);
195
196
  }
196
197
 
198
+ // Built-in micro-components
199
+ if (node.tagName === 'wm-button') {
200
+ return this.evalWmButton(node, ctx);
201
+ }
202
+
197
203
  let result = `<${node.tagName}`;
198
204
 
199
205
  // Collect all class names (static + conditional)
@@ -305,6 +311,70 @@ class TemplateEvaluator {
305
311
  return `<${kebabTag}${propsAttr}></${kebabTag}>`;
306
312
  }
307
313
 
314
+ /**
315
+ * Built-in micro-component: <wm-button settings={button}></wm-button>
316
+ *
317
+ * Transforms to semantic HTML with Design System button classes.
318
+ * Settings object: { title, link, icon, variant, size, iconPosition, openInNewTab }
319
+ *
320
+ * Size mapping: small/sm → btn-sm, medium/md → btn-md, large/lg → btn-lg
321
+ * Variant mapping: primary → btn-filled, filled/tonal/outline/ghost/text/destructive → btn-{variant}
322
+ */
323
+ evalWmButton(node, ctx) {
324
+ // Resolve the settings prop
325
+ let settings = null;
326
+ for (const attr of node.attributes) {
327
+ if (attr.name === 'settings') {
328
+ if (attr.type === 'DynamicAttribute') {
329
+ settings = this.expr.evaluate(attr.expression, ctx);
330
+ } else if (attr.type === 'StaticAttribute') {
331
+ settings = attr.value;
332
+ }
333
+ }
334
+ }
335
+
336
+ if (!settings || typeof settings !== 'object') {
337
+ return '<!-- wm-button: no settings -->';
338
+ }
339
+
340
+ const {
341
+ title = '',
342
+ link = '#',
343
+ icon = '',
344
+ variant = 'filled',
345
+ size = 'md',
346
+ iconPosition = 'left',
347
+ openInNewTab = false
348
+ } = settings;
349
+
350
+ // Map size names
351
+ const sizeMap = { small: 'sm', medium: 'md', large: 'lg', sm: 'sm', md: 'md', lg: 'lg' };
352
+ const sizeClass = `btn-${sizeMap[size] || 'md'}`;
353
+
354
+ // Map variant names (primary → filled for backward compat)
355
+ const variantMap = { primary: 'filled', secondary: 'tonal' };
356
+ const variantClass = `btn-${variantMap[variant] || variant}`;
357
+
358
+ const classes = ['btn', sizeClass, variantClass].join(' ');
359
+ const target = openInNewTab ? ' target="_blank" rel="noopener noreferrer"' : '';
360
+ const href = typeof link === 'object' ? (link.path || link.url || '#') : (link || '#');
361
+
362
+ // Build icon HTML
363
+ const iconHtml = icon ? `<iconify-icon icon="${this.escapeAttr(icon)}"></iconify-icon>` : '';
364
+
365
+ // Build content based on icon position
366
+ let content = '';
367
+ if (icon && iconPosition === 'right') {
368
+ content = `${this.escapeHtml(title)}${iconHtml ? ' ' + iconHtml : ''}`;
369
+ } else if (icon && iconPosition === 'left') {
370
+ content = `${iconHtml ? iconHtml + ' ' : ''}${this.escapeHtml(title)}`;
371
+ } else {
372
+ content = this.escapeHtml(title);
373
+ }
374
+
375
+ return `<a href="${this.escapeAttr(href)}" class="${classes}"${target}>${content}</a>`;
376
+ }
377
+
308
378
  // ========================================
309
379
  // Value resolution helpers
310
380
  // ========================================