@descope/web-components-ui 1.0.364 → 1.0.365

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.
@@ -2614,11 +2614,57 @@ const inputEventsDispatchingMixin = (superclass) =>
2614
2614
  }
2615
2615
  };
2616
2616
 
2617
+ const getFileExtension = (path) => {
2618
+ const match = path.match(/\.([0-9a-z]+)(?:[\\?#]|$)/i);
2619
+ return match ? match[1] : null;
2620
+ };
2621
+
2622
+ const isSvg = (src) => getFileExtension(src) === 'svg' || src.indexOf('image/svg+xml') > -1;
2623
+
2624
+ const createImgEle = (src) => {
2625
+ const ele = document.createElement('img');
2626
+ ele.setAttribute('src', src);
2627
+ return ele;
2628
+ };
2629
+
2630
+ const createSvgEle = (text) => {
2631
+ const parser = new DOMParser();
2632
+ const ele = parser.parseFromString(text, 'image/svg+xml').querySelector('svg');
2633
+ return ele;
2634
+ };
2635
+
2636
+ const createIcon = async (src) => {
2637
+ try {
2638
+ let ele;
2639
+
2640
+ if (isSvg(src)) {
2641
+ const fetchedSrc = await fetch(src);
2642
+ const text = await fetchedSrc.text();
2643
+ ele = createSvgEle(text);
2644
+ } else {
2645
+ ele = createImgEle(src);
2646
+ }
2647
+
2648
+ ele.style.setProperty('width', '100%');
2649
+ ele.style.setProperty('height', '100%');
2650
+
2651
+ return ele;
2652
+ } catch {
2653
+ return null;
2654
+ }
2655
+ };
2656
+
2617
2657
  /* eslint-disable no-use-before-define */
2618
2658
 
2619
2659
  const componentName$S = getComponentName('icon');
2620
2660
 
2621
2661
  class RawIcon extends createBaseClass({ componentName: componentName$S, baseSelector: 'slot' }) {
2662
+ static get observedAttributes() {
2663
+ return ['src', 'fill-color'];
2664
+ }
2665
+
2666
+ #icon;
2667
+
2622
2668
  constructor() {
2623
2669
  super();
2624
2670
 
@@ -2629,7 +2675,7 @@ class RawIcon extends createBaseClass({ componentName: componentName$S, baseSele
2629
2675
  width: 100%;
2630
2676
  height: 100%;
2631
2677
  display: flex;
2632
- overflow: auto;
2678
+ overflow: hidden;
2633
2679
  }
2634
2680
  :host {
2635
2681
  display: inline-block;
@@ -2639,30 +2685,53 @@ class RawIcon extends createBaseClass({ componentName: componentName$S, baseSele
2639
2685
  `;
2640
2686
  }
2641
2687
 
2642
- get items() {
2643
- return this.shadowRoot.querySelector('slot').assignedNodes();
2688
+ get fillColor() {
2689
+ return this.getAttribute('fill-color') === 'true';
2644
2690
  }
2645
2691
 
2646
- #onChildrenChange() {
2647
- // force hide icon if empty.
2648
- if (this.items?.length > 0) {
2649
- this.shadowRoot.host.style.setProperty('display', 'inline-block');
2650
- } else {
2651
- this.shadowRoot.host.style.setProperty('display', 'none');
2692
+ get src() {
2693
+ return this.getAttribute('src');
2694
+ }
2695
+
2696
+ // in order to fill an SVG with `currentColor` override all of its `fill` and `path` nodes
2697
+ // with the value from the `st-fill` attribute
2698
+ updateFillColor() {
2699
+ if (this.#icon && this.fillColor) {
2700
+ const fillCssVar = (selector) => {
2701
+ this.querySelectorAll(selector).forEach((ele) =>
2702
+ ele.setAttribute(
2703
+ 'fill',
2704
+ `var(${IconClass.cssVarList.fill}, ${ele.getAttribute('fill') || "''"})`
2705
+ )
2706
+ );
2707
+ };
2708
+
2709
+ fillCssVar('*[fill]');
2710
+ fillCssVar('path');
2652
2711
  }
2712
+ }
2653
2713
 
2654
- // set fill for all inner svgs to fill var and a fallback
2655
- const elems = this.querySelectorAll('*[fill]');
2656
- elems.forEach((ele) =>
2657
- ele.setAttribute(
2658
- 'fill',
2659
- `var(${IconClass.cssVarList.fill}, ${ele.getAttribute('fill') || "''"})`
2660
- )
2661
- );
2714
+ resetIcon() {
2715
+ if (!this.#icon) return;
2716
+ this.innerHTML = '';
2717
+ this.appendChild(this.#icon.cloneNode(true));
2662
2718
  }
2663
2719
 
2664
- init() {
2665
- observeChildren(this, this.#onChildrenChange.bind(this));
2720
+ attributeChangedCallback(attrName, oldValue, newValue) {
2721
+ super.attributeChangedCallback?.(attrName, oldValue, newValue);
2722
+
2723
+ if (oldValue === newValue) return;
2724
+
2725
+ if (attrName === 'src') {
2726
+ createIcon(this.src).then((res) => {
2727
+ this.#icon = res;
2728
+ this.resetIcon();
2729
+ this.updateFillColor();
2730
+ });
2731
+ } else if (attrName === 'fill-color') {
2732
+ this.resetIcon();
2733
+ this.updateFillColor();
2734
+ }
2666
2735
  }
2667
2736
  }
2668
2737
 
@@ -2725,9 +2794,10 @@ const iconStyles = `
2725
2794
 
2726
2795
  const editorOverrides = `vaadin-button::part(label) { pointer-events: none; }`;
2727
2796
 
2728
- const { host: host$n, label: label$a } = {
2797
+ const { host: host$n, label: label$a, slottedIcon } = {
2729
2798
  host: { selector: () => ':host' },
2730
2799
  label: { selector: '::part(label)' },
2800
+ slottedIcon: { selector: () => '::slotted(descope-icon)' },
2731
2801
  };
2732
2802
 
2733
2803
  let loadingIndicatorStyles;
@@ -2768,6 +2838,11 @@ const ButtonClass = compose(
2768
2838
  labelTextDecoration: { ...label$a, property: 'text-decoration' },
2769
2839
  labelSpacing: { ...label$a, property: 'gap' },
2770
2840
  textAlign: { ...label$a, property: 'justify-content', fallback: 'center' },
2841
+
2842
+ iconSize: [
2843
+ { ...slottedIcon, property: 'width' },
2844
+ { ...slottedIcon, property: 'height' },
2845
+ ],
2771
2846
  },
2772
2847
  }),
2773
2848
  clickableMixin,
@@ -2879,6 +2954,9 @@ const button = {
2879
2954
  [compVars$5.outlineStyle]: 'solid',
2880
2955
  [compVars$5.outlineColor]: 'transparent',
2881
2956
 
2957
+ [compVars$5.iconSize]: '1.5em',
2958
+ [compVars$5.iconColor]: 'currentColor',
2959
+
2882
2960
  size: {
2883
2961
  xs: { [compVars$5.fontSize]: '12px' },
2884
2962
  sm: { [compVars$5.fontSize]: '14px' },