@webmate-studio/builder 0.2.152 → 0.2.154

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.152",
3
+ "version": "0.2.154",
4
4
  "type": "module",
5
5
  "description": "Webmate Studio Component Builder",
6
6
  "keywords": [
@@ -14,7 +14,8 @@ import {
14
14
  BUTTON_SIZES,
15
15
  calculateOnColor,
16
16
  DEFAULT_SURFACE_TOKENS,
17
- defaultDesignTokensV2
17
+ defaultDesignTokensV2,
18
+ normalizeShadowValue
18
19
  } from './design-tokens-v2.js';
19
20
 
20
21
 
@@ -567,6 +568,32 @@ function generateButtonVariables(t, lines) {
567
568
  }
568
569
  }
569
570
 
571
+ /**
572
+ * Prüft ob ein Shadow-Wert echte Daten enthält.
573
+ */
574
+ function hasShadow(val) {
575
+ if (!val || val === 'none') return false;
576
+ if (Array.isArray(val)) return val.length > 0;
577
+ return true;
578
+ }
579
+
580
+ /**
581
+ * Konvertiert strukturierte Shadow-Layer zu einem CSS box-shadow String.
582
+ */
583
+ function resolveShadowToCSS(shadowValue, t) {
584
+ const normalized = normalizeShadowValue(shadowValue);
585
+ if (normalized === 'none' || !Array.isArray(normalized) || normalized.length === 0) return 'none';
586
+
587
+ return normalized.map(layer => {
588
+ const insetStr = layer.inset ? 'inset ' : '';
589
+ const colorResolved = resolveColorRef(layer.color, t);
590
+ const colorCSS = (layer.opacity != null && layer.opacity < 100)
591
+ ? `color-mix(in srgb, ${colorResolved} ${layer.opacity}%, transparent)`
592
+ : colorResolved;
593
+ return `${insetStr}${layer.offsetX || 0}px ${layer.offsetY || 0}px ${layer.blur || 0}px ${layer.spread || 0}px ${colorCSS}`;
594
+ }).join(', ');
595
+ }
596
+
570
597
  function addButtonVariantVars(lines, prefix, variant, t) {
571
598
  if (variant.bg) lines.push(` --${prefix}-bg: ${resolveColorRef(variant.bg, t)};`);
572
599
  if (variant.bgHover) lines.push(` --${prefix}-bg-hover: ${resolveColorRef(variant.bgHover, t)};`);
@@ -574,8 +601,10 @@ function addButtonVariantVars(lines, prefix, variant, t) {
574
601
  if (variant.textHover) lines.push(` --${prefix}-text-hover: ${resolveColorRef(variant.textHover, t)};`);
575
602
  if (variant.border && variant.border !== 'none') lines.push(` --${prefix}-border: 1px solid ${resolveColorRef(variant.border, t)};`);
576
603
  if (variant.borderHover && variant.borderHover !== 'none') lines.push(` --${prefix}-border-hover: 1px solid ${resolveColorRef(variant.borderHover, t)};`);
577
- if (variant.shadow && variant.shadow !== 'none') lines.push(` --${prefix}-shadow: ${variant.shadow};`);
578
- if (variant.shadowHover && variant.shadowHover !== 'none') lines.push(` --${prefix}-shadow-hover: ${variant.shadowHover};`);
604
+ const shadowCSS = resolveShadowToCSS(variant.shadow, t);
605
+ if (shadowCSS !== 'none') lines.push(` --${prefix}-shadow: ${shadowCSS};`);
606
+ const shadowHoverCSS = resolveShadowToCSS(variant.shadowHover, t);
607
+ if (shadowHoverCSS !== 'none') lines.push(` --${prefix}-shadow-hover: ${shadowHoverCSS};`);
579
608
  if (variant.focusRingColor) lines.push(` --${prefix}-focus-ring: ${resolveColorRef(variant.focusRingColor, t)};`);
580
609
  }
581
610
 
@@ -680,7 +709,7 @@ function generateVariantNormalCSS(variant, v) {
680
709
  if (v.normal.border && v.normal.border !== 'none') {
681
710
  css += `\n border: var(--${p}-border);`;
682
711
  }
683
- if (v.normal.shadow && v.normal.shadow !== 'none') {
712
+ if (hasShadow(v.normal.shadow)) {
684
713
  css += `\n box-shadow: var(--${p}-shadow);`;
685
714
  }
686
715
  if (v.normal.textDecoration) {
@@ -697,7 +726,7 @@ function generateVariantNormalCSS(variant, v) {
697
726
  if (v.normal.borderHover && v.normal.borderHover !== 'none') {
698
727
  css += `\n border: var(--${p}-border-hover);`;
699
728
  }
700
- if (v.normal.shadowHover && v.normal.shadowHover !== 'none') {
729
+ if (hasShadow(v.normal.shadowHover)) {
701
730
  css += `\n box-shadow: var(--${p}-shadow-hover);`;
702
731
  }
703
732
  if (v.normal.textDecorationHover) {
@@ -708,9 +737,16 @@ function generateVariantNormalCSS(variant, v) {
708
737
 
709
738
  // Focus
710
739
  if (v.normal.focusRingColor) {
740
+ const g = t.buttons?.global || {};
741
+ const ringWidth = g.focusRingWidth || '2px';
742
+ const ringOffset = g.focusRingOffset || '2px';
743
+ const ringOpacity = g.focusRingOpacity;
744
+ const ringColor = (ringOpacity != null && ringOpacity < 1)
745
+ ? `color-mix(in srgb, var(--${p}-focus-ring) ${Math.round(ringOpacity * 100)}%, transparent)`
746
+ : `var(--${p}-focus-ring)`;
711
747
  css += `\n.${p}:focus-visible {
712
- outline: 2px solid var(--${p}-focus-ring);
713
- outline-offset: 2px;
748
+ outline: ${ringWidth} solid ${ringColor};
749
+ outline-offset: ${ringOffset};
714
750
  }`;
715
751
  }
716
752
 
@@ -727,6 +763,9 @@ function generateVariantOnSurfaceCSS(variant, v, t) {
727
763
  if (v.onSurface.border && v.onSurface.border !== 'none') {
728
764
  css += `\n border: var(--${osp}-border);`;
729
765
  }
766
+ if (hasShadow(v.onSurface.shadow)) {
767
+ css += `\n box-shadow: var(--${osp}-shadow);`;
768
+ }
730
769
  if (v.onSurface.textDecoration) {
731
770
  css += `\n text-decoration: ${v.onSurface.textDecoration};`;
732
771
  }
@@ -741,6 +780,9 @@ function generateVariantOnSurfaceCSS(variant, v, t) {
741
780
  if (v.onSurface.borderHover && v.onSurface.borderHover !== 'none') {
742
781
  css += `\n border: var(--${osp}-border-hover);`;
743
782
  }
783
+ if (hasShadow(v.onSurface.shadowHover)) {
784
+ css += `\n box-shadow: var(--${osp}-shadow-hover);`;
785
+ }
744
786
  if (v.onSurface.textDecorationHover) {
745
787
  css += `\n text-decoration: ${v.onSurface.textDecorationHover};`;
746
788
  }
@@ -750,9 +792,17 @@ function generateVariantOnSurfaceCSS(variant, v, t) {
750
792
  // Focus (on-surface)
751
793
  const focusColor = t.buttons.global?.onSurfaceFocusRingColor;
752
794
  if (focusColor) {
795
+ const g = t.buttons?.global || {};
796
+ const ringWidth = g.focusRingWidth || '2px';
797
+ const ringOffset = g.focusRingOffset || '2px';
798
+ const ringOpacity = g.focusRingOpacity;
799
+ const resolvedFocus = resolveColorRef(focusColor, t);
800
+ const ringColor = (ringOpacity != null && ringOpacity < 1)
801
+ ? `color-mix(in srgb, ${resolvedFocus} ${Math.round(ringOpacity * 100)}%, transparent)`
802
+ : resolvedFocus;
753
803
  css += `\n.btn-on-surface.${p}:focus-visible {
754
- outline: 2px solid ${resolveColorRef(focusColor, t)};
755
- outline-offset: 2px;
804
+ outline: ${ringWidth} solid ${ringColor};
805
+ outline-offset: ${ringOffset};
756
806
  }`;
757
807
  }
758
808
 
@@ -679,6 +679,44 @@ export const BUTTON_VARIANTS = ['filled', 'tonal', 'outline', 'ghost', 'text', '
679
679
  */
680
680
  export const BUTTON_SIZES = ['sm', 'md', 'lg'];
681
681
 
682
+ /**
683
+ * Shadow-Presets als strukturierte Layer-Arrays (Tailwind-orientiert).
684
+ */
685
+ export const SHADOW_PRESETS = {
686
+ none: 'none',
687
+ sm: [
688
+ { offsetX: 0, offsetY: 1, blur: 2, spread: 0, color: 'neutral-12', opacity: 5, inset: false }
689
+ ],
690
+ md: [
691
+ { offsetX: 0, offsetY: 4, blur: 6, spread: -1, color: 'neutral-12', opacity: 10, inset: false },
692
+ { offsetX: 0, offsetY: 2, blur: 4, spread: -2, color: 'neutral-12', opacity: 10, inset: false }
693
+ ],
694
+ lg: [
695
+ { offsetX: 0, offsetY: 10, blur: 15, spread: -3, color: 'neutral-12', opacity: 20, inset: false },
696
+ { offsetX: 0, offsetY: 4, blur: 6, spread: -4, color: 'neutral-12', opacity: 10, inset: false }
697
+ ]
698
+ };
699
+
700
+ /**
701
+ * Erzeugt eine Standard-Schattenebene.
702
+ */
703
+ export function createDefaultShadowLayer() {
704
+ return { offsetX: 0, offsetY: 4, blur: 6, spread: 0, color: 'neutral-12', opacity: 10, inset: false };
705
+ }
706
+
707
+ /**
708
+ * Normalisiert einen Shadow-Wert zu 'none' oder einem Array von Layer-Objekten.
709
+ * Akzeptiert: 'none', 'sm', 'md', 'lg', Array, null/undefined.
710
+ */
711
+ export function normalizeShadowValue(val) {
712
+ if (!val || val === 'none') return 'none';
713
+ if (Array.isArray(val)) return val;
714
+ if (typeof val === 'string' && SHADOW_PRESETS[val] && SHADOW_PRESETS[val] !== 'none') {
715
+ return structuredClone(SHADOW_PRESETS[val]);
716
+ }
717
+ return 'none';
718
+ }
719
+
682
720
 
683
721
  // ─── Default Token-Objekt ───────────────────────────────────────────────────
684
722
 
@@ -1000,6 +1038,8 @@ export const defaultDesignTokensV2 = {
1000
1038
  textHover: 'neutral-12',
1001
1039
  border: 'none',
1002
1040
  borderHover: 'none',
1041
+ shadow: 'none',
1042
+ shadowHover: 'none',
1003
1043
  customCSS: null
1004
1044
  }
1005
1045
  },
@@ -1023,6 +1063,8 @@ export const defaultDesignTokensV2 = {
1023
1063
  textHover: 'on-primary',
1024
1064
  border: 'none',
1025
1065
  borderHover: 'none',
1066
+ shadow: 'none',
1067
+ shadowHover: 'none',
1026
1068
  customCSS: null
1027
1069
  }
1028
1070
  },
@@ -1046,6 +1088,8 @@ export const defaultDesignTokensV2 = {
1046
1088
  textHover: 'on-primary',
1047
1089
  border: 'on-primary/40',
1048
1090
  borderHover: 'on-primary/70',
1091
+ shadow: 'none',
1092
+ shadowHover: 'none',
1049
1093
  customCSS: null
1050
1094
  }
1051
1095
  },
@@ -1069,6 +1113,8 @@ export const defaultDesignTokensV2 = {
1069
1113
  textHover: 'on-primary',
1070
1114
  border: 'none',
1071
1115
  borderHover: 'none',
1116
+ shadow: 'none',
1117
+ shadowHover: 'none',
1072
1118
  customCSS: null
1073
1119
  }
1074
1120
  },
@@ -1092,6 +1138,10 @@ export const defaultDesignTokensV2 = {
1092
1138
  bgHover: 'transparent',
1093
1139
  text: 'on-primary',
1094
1140
  textHover: 'on-primary',
1141
+ border: 'none',
1142
+ borderHover: 'none',
1143
+ shadow: 'none',
1144
+ shadowHover: 'none',
1095
1145
  textDecoration: 'none',
1096
1146
  textDecorationHover: 'underline',
1097
1147
  customCSS: null
@@ -1117,6 +1167,8 @@ export const defaultDesignTokensV2 = {
1117
1167
  textHover: 'on-error',
1118
1168
  border: 'none',
1119
1169
  borderHover: 'none',
1170
+ shadow: 'none',
1171
+ shadowHover: 'none',
1120
1172
  customCSS: null
1121
1173
  }
1122
1174
  }