@descope/web-components-ui 1.0.369 → 1.0.371

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,6 +2,7 @@
2
2
 
3
3
  var merge = require('lodash.merge');
4
4
  var Color = require('color');
5
+ var DOMPurify = require('dompurify');
5
6
  var MarkdownIt = require('markdown-it');
6
7
  require('lodash.debounce');
7
8
  var hljs = require('highlight.js');
@@ -2633,8 +2634,11 @@ const createImgEle = (src) => {
2633
2634
  };
2634
2635
 
2635
2636
  const createSvgEle = (text) => {
2637
+ // we want to purify the SVG to avoid XSS attacks
2638
+ const clean = DOMPurify.sanitize(text, { USE_PROFILES: { svg: true, svgFilters: true } });
2639
+
2636
2640
  const parser = new DOMParser();
2637
- const ele = parser.parseFromString(text, 'image/svg+xml').querySelector('svg');
2641
+ const ele = parser.parseFromString(clean, 'image/svg+xml').querySelector('svg');
2638
2642
  return ele;
2639
2643
  };
2640
2644
 
@@ -2670,7 +2674,7 @@ const componentName$V = getComponentName('icon');
2670
2674
 
2671
2675
  class RawIcon extends createBaseClass({ componentName: componentName$V, baseSelector: 'slot' }) {
2672
2676
  static get observedAttributes() {
2673
- return ['src', 'fill-color'];
2677
+ return ['src'];
2674
2678
  }
2675
2679
 
2676
2680
  #icon;
@@ -2695,36 +2699,23 @@ class RawIcon extends createBaseClass({ componentName: componentName$V, baseSele
2695
2699
  `;
2696
2700
  }
2697
2701
 
2698
- get fillColor() {
2699
- return this.getAttribute('fill-color') === 'true';
2700
- }
2701
-
2702
2702
  get src() {
2703
2703
  return this.getAttribute('src');
2704
2704
  }
2705
2705
 
2706
2706
  // in order to fill an SVG with `currentColor` override all of its `fill` and `path` nodes
2707
2707
  // with the value from the `st-fill` attribute
2708
- updateFillColor() {
2709
- if (this.#icon && this.fillColor) {
2710
- const fillCssVar = (selector) => {
2711
- this.querySelectorAll(selector).forEach((ele) =>
2712
- ele.setAttribute(
2713
- 'fill',
2714
- `var(${IconClass.cssVarList.fill}, ${ele.getAttribute('fill') || "''"})`
2715
- )
2716
- );
2717
- };
2718
-
2719
- fillCssVar('*[fill]');
2720
- fillCssVar('path');
2721
- }
2722
- }
2723
-
2724
- resetIcon() {
2725
- if (!this.#icon) return;
2726
- this.innerHTML = '';
2727
- this.appendChild(this.#icon.cloneNode(true));
2708
+ // eslint-disable-next-line class-methods-use-this
2709
+ updateFillColor(node) {
2710
+ // set fill to root node and all its relevant selectors
2711
+ const elementsToReplace = [node, ...node.querySelectorAll('*[fill]')];
2712
+
2713
+ elementsToReplace.forEach((ele) => {
2714
+ ele.setAttribute(
2715
+ 'fill',
2716
+ `var(${IconClass.cssVarList.fill}, ${ele.getAttribute('fill') || "''"})`
2717
+ );
2718
+ });
2728
2719
  }
2729
2720
 
2730
2721
  attributeChangedCallback(attrName, oldValue, newValue) {
@@ -2734,13 +2725,13 @@ class RawIcon extends createBaseClass({ componentName: componentName$V, baseSele
2734
2725
 
2735
2726
  if (attrName === 'src') {
2736
2727
  createIcon(this.src).then((res) => {
2737
- this.#icon = res;
2738
- this.resetIcon();
2739
- this.updateFillColor();
2728
+ this.innerHTML = '';
2729
+ if (res) {
2730
+ const clonedNode = res.cloneNode(true);
2731
+ this.updateFillColor(clonedNode);
2732
+ this.appendChild(clonedNode);
2733
+ }
2740
2734
  });
2741
- } else if (attrName === 'fill-color') {
2742
- this.resetIcon();
2743
- this.updateFillColor();
2744
2735
  }
2745
2736
  }
2746
2737
  }
@@ -2965,7 +2956,6 @@ const button = {
2965
2956
  [compVars$6.outlineColor]: 'transparent',
2966
2957
 
2967
2958
  [compVars$6.iconSize]: '1.5em',
2968
- [compVars$6.iconColor]: 'currentColor',
2969
2959
 
2970
2960
  size: {
2971
2961
  xs: { [compVars$6.fontSize]: '12px' },
@@ -13214,7 +13204,7 @@ const componentName$3 = getComponentName('list');
13214
13204
 
13215
13205
  class RawList extends createBaseClass({ componentName: componentName$3, baseSelector: '.wrapper' }) {
13216
13206
  static get observedAttributes() {
13217
- return ['variant'];
13207
+ return ['variant', 'readonly'];
13218
13208
  }
13219
13209
 
13220
13210
  constructor() {
@@ -13297,6 +13287,18 @@ class RawList extends createBaseClass({ componentName: componentName$3, baseSele
13297
13287
  observeChildren(this, () => {
13298
13288
  this.#handleEmptyState();
13299
13289
  this.#handleItemsVariant();
13290
+ this.#handleReadOnly();
13291
+ });
13292
+ }
13293
+
13294
+ get isReadOnly() {
13295
+ return this.getAttribute('readonly') === 'true';
13296
+ }
13297
+
13298
+ #handleReadOnly() {
13299
+ this.items.forEach((item) => {
13300
+ if (this.isReadOnly) item.setAttribute('inert', '');
13301
+ else item.removeAttribute('inert');
13300
13302
  });
13301
13303
  }
13302
13304
 
@@ -13307,6 +13309,8 @@ class RawList extends createBaseClass({ componentName: componentName$3, baseSele
13307
13309
 
13308
13310
  if (name === 'variant') {
13309
13311
  this.#handleItemsVariant();
13312
+ } else if (name === 'readonly') {
13313
+ this.#handleReadOnly();
13310
13314
  }
13311
13315
  }
13312
13316
  }
@@ -13520,16 +13524,51 @@ const createDynamicDataMixin =
13520
13524
  super.init?.();
13521
13525
 
13522
13526
  if (rerenderAttrsList.length) {
13523
- observeAttributes(this, () => this.#renderItems(), { includeAttrs: rerenderAttrsList });
13527
+ observeAttributes(
13528
+ this,
13529
+ (attrs) => {
13530
+ if (attrs.includes('data')) this.#handleDataAttr();
13531
+ if (attrs.some((attr) => attr !== 'data')) this.#renderItems();
13532
+ },
13533
+ { includeAttrs: [...rerenderAttrsList, 'data'] }
13534
+ );
13524
13535
  } else {
13525
13536
  this.#renderItems();
13526
13537
  }
13527
13538
  }
13539
+
13540
+ #handleDataAttr() {
13541
+ const dataAttr = this.getAttribute('data');
13542
+
13543
+ if (!dataAttr) return;
13544
+
13545
+ try {
13546
+ this.#data = JSON.parse(dataAttr);
13547
+ } catch (e) {
13548
+ // eslint-disable-next-line no-console
13549
+ console.warn('Invalid JSON data', dataAttr);
13550
+ }
13551
+ }
13552
+
13553
+ attributeChangedCallback(name, oldValue, newValue) {
13554
+ super.attributeChangedCallback?.(name, oldValue, newValue);
13555
+
13556
+ if (newValue === oldValue) return;
13557
+
13558
+ if (name === 'data') {
13559
+ try {
13560
+ this.data = JSON.parse(newValue);
13561
+ } catch (e) {
13562
+ // eslint-disable-next-line no-console
13563
+ console.warn('Invalid JSON data', newValue);
13564
+ }
13565
+ }
13566
+ }
13528
13567
  };
13529
13568
 
13530
13569
  const componentName$2 = getComponentName('apps-list');
13531
13570
 
13532
- const limitAbbreviation = (str, limit = 3) =>
13571
+ const limitAbbreviation = (str, limit = 2) =>
13533
13572
  str
13534
13573
  .trim()
13535
13574
  .split(' ')
@@ -13538,12 +13577,11 @@ const limitAbbreviation = (str, limit = 3) =>
13538
13577
  .join('');
13539
13578
 
13540
13579
  const itemRenderer = ({ name, icon, url }, _, ref) => `
13541
- <a href="${url}" target="_blank" title="${url}">
13580
+ <a ${url ? `href="${url}" title="${url}"` : ''} target="_blank">
13542
13581
  <descope-list-item>
13543
13582
  <descope-avatar
13544
- img="${icon}"
13545
- display-name="${name}"
13546
- abbr=${limitAbbreviation(name)}
13583
+ ${icon ? `img="${icon}"` : ''}
13584
+ ${name ? `display-name="${name}" abbr=${limitAbbreviation(name)}` : ''}
13547
13585
  size=${ref.size}
13548
13586
  ></descope-avatar>
13549
13587
  <descope-text
@@ -13589,7 +13627,7 @@ const AppsListClass = compose(
13589
13627
  createProxy({
13590
13628
  slots: ['empty-state'],
13591
13629
  wrappedEleName: 'descope-list',
13592
- excludeAttrsSync: ['tabindex', 'class'],
13630
+ excludeAttrsSync: ['tabindex', 'class', 'empty'],
13593
13631
  componentName: componentName$2,
13594
13632
  style: () => `
13595
13633
  :host {