@descope/web-components-ui 1.0.368 → 1.0.370

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.
@@ -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');
@@ -2622,7 +2623,9 @@ const getFileExtension = (path) => {
2622
2623
  return match ? match[1] : null;
2623
2624
  };
2624
2625
 
2625
- const isSvg = (src) => getFileExtension(src) === 'svg' || src.indexOf('image/svg+xml') > -1;
2626
+ const base64Prefix = 'data:image/svg+xml;base64,';
2627
+
2628
+ const isBase64Svg = (src) => src.startsWith(base64Prefix);
2626
2629
 
2627
2630
  const createImgEle = (src) => {
2628
2631
  const ele = document.createElement('img');
@@ -2631,20 +2634,28 @@ const createImgEle = (src) => {
2631
2634
  };
2632
2635
 
2633
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
+
2634
2640
  const parser = new DOMParser();
2635
- const ele = parser.parseFromString(text, 'image/svg+xml').querySelector('svg');
2641
+ const ele = parser.parseFromString(clean, 'image/svg+xml').querySelector('svg');
2636
2642
  return ele;
2637
2643
  };
2638
2644
 
2639
2645
  const createIcon = async (src) => {
2640
2646
  try {
2641
2647
  let ele;
2642
-
2643
- if (isSvg(src)) {
2648
+ if (isBase64Svg(src)) {
2649
+ // handle base64 source
2650
+ const svgXml = atob(src.slice(base64Prefix.length));
2651
+ ele = createSvgEle(svgXml);
2652
+ } else if (getFileExtension(src) === 'svg') {
2653
+ // handle urls
2644
2654
  const fetchedSrc = await fetch(src);
2645
2655
  const text = await fetchedSrc.text();
2646
2656
  ele = createSvgEle(text);
2647
2657
  } else {
2658
+ // handle binary
2648
2659
  ele = createImgEle(src);
2649
2660
  }
2650
2661
 
@@ -13207,7 +13218,7 @@ const componentName$3 = getComponentName('list');
13207
13218
 
13208
13219
  class RawList extends createBaseClass({ componentName: componentName$3, baseSelector: '.wrapper' }) {
13209
13220
  static get observedAttributes() {
13210
- return ['variant'];
13221
+ return ['variant', 'readonly'];
13211
13222
  }
13212
13223
 
13213
13224
  constructor() {
@@ -13290,6 +13301,18 @@ class RawList extends createBaseClass({ componentName: componentName$3, baseSele
13290
13301
  observeChildren(this, () => {
13291
13302
  this.#handleEmptyState();
13292
13303
  this.#handleItemsVariant();
13304
+ this.#handleReadOnly();
13305
+ });
13306
+ }
13307
+
13308
+ get isReadOnly() {
13309
+ return this.getAttribute('readonly') === 'true';
13310
+ }
13311
+
13312
+ #handleReadOnly() {
13313
+ this.items.forEach((item) => {
13314
+ if (this.isReadOnly) item.setAttribute('inert', '');
13315
+ else item.removeAttribute('inert');
13293
13316
  });
13294
13317
  }
13295
13318
 
@@ -13300,6 +13323,8 @@ class RawList extends createBaseClass({ componentName: componentName$3, baseSele
13300
13323
 
13301
13324
  if (name === 'variant') {
13302
13325
  this.#handleItemsVariant();
13326
+ } else if (name === 'readonly') {
13327
+ this.#handleReadOnly();
13303
13328
  }
13304
13329
  }
13305
13330
  }
@@ -13513,16 +13538,51 @@ const createDynamicDataMixin =
13513
13538
  super.init?.();
13514
13539
 
13515
13540
  if (rerenderAttrsList.length) {
13516
- observeAttributes(this, () => this.#renderItems(), { includeAttrs: rerenderAttrsList });
13541
+ observeAttributes(
13542
+ this,
13543
+ (attrs) => {
13544
+ if (attrs.includes('data')) this.#handleDataAttr();
13545
+ if (attrs.some((attr) => attr !== 'data')) this.#renderItems();
13546
+ },
13547
+ { includeAttrs: [...rerenderAttrsList, 'data'] }
13548
+ );
13517
13549
  } else {
13518
13550
  this.#renderItems();
13519
13551
  }
13520
13552
  }
13553
+
13554
+ #handleDataAttr() {
13555
+ const dataAttr = this.getAttribute('data');
13556
+
13557
+ if (!dataAttr) return;
13558
+
13559
+ try {
13560
+ this.#data = JSON.parse(dataAttr);
13561
+ } catch (e) {
13562
+ // eslint-disable-next-line no-console
13563
+ console.warn('Invalid JSON data', dataAttr);
13564
+ }
13565
+ }
13566
+
13567
+ attributeChangedCallback(name, oldValue, newValue) {
13568
+ super.attributeChangedCallback?.(name, oldValue, newValue);
13569
+
13570
+ if (newValue === oldValue) return;
13571
+
13572
+ if (name === 'data') {
13573
+ try {
13574
+ this.data = JSON.parse(newValue);
13575
+ } catch (e) {
13576
+ // eslint-disable-next-line no-console
13577
+ console.warn('Invalid JSON data', newValue);
13578
+ }
13579
+ }
13580
+ }
13521
13581
  };
13522
13582
 
13523
13583
  const componentName$2 = getComponentName('apps-list');
13524
13584
 
13525
- const limitAbbreviation = (str, limit = 3) =>
13585
+ const limitAbbreviation = (str, limit = 2) =>
13526
13586
  str
13527
13587
  .trim()
13528
13588
  .split(' ')
@@ -13531,12 +13591,11 @@ const limitAbbreviation = (str, limit = 3) =>
13531
13591
  .join('');
13532
13592
 
13533
13593
  const itemRenderer = ({ name, icon, url }, _, ref) => `
13534
- <a href="${url}" target="_blank" title="${url}">
13594
+ <a ${url ? `href="${url}" title="${url}"` : ''} target="_blank">
13535
13595
  <descope-list-item>
13536
13596
  <descope-avatar
13537
- img="${icon}"
13538
- display-name="${name}"
13539
- abbr=${limitAbbreviation(name)}
13597
+ ${icon ? `img="${icon}"` : ''}
13598
+ ${name ? `display-name="${name}" abbr=${limitAbbreviation(name)}` : ''}
13540
13599
  size=${ref.size}
13541
13600
  ></descope-avatar>
13542
13601
  <descope-text
@@ -13582,7 +13641,7 @@ const AppsListClass = compose(
13582
13641
  createProxy({
13583
13642
  slots: ['empty-state'],
13584
13643
  wrappedEleName: 'descope-list',
13585
- excludeAttrsSync: ['tabindex', 'class'],
13644
+ excludeAttrsSync: ['tabindex', 'class', 'empty'],
13586
13645
  componentName: componentName$2,
13587
13646
  style: () => `
13588
13647
  :host {