@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.
package/dist/index.esm.js CHANGED
@@ -1393,11 +1393,57 @@ const inputEventsDispatchingMixin = (superclass) =>
1393
1393
  }
1394
1394
  };
1395
1395
 
1396
+ const getFileExtension = (path) => {
1397
+ const match = path.match(/\.([0-9a-z]+)(?:[\\?#]|$)/i);
1398
+ return match ? match[1] : null;
1399
+ };
1400
+
1401
+ const isSvg = (src) => getFileExtension(src) === 'svg' || src.indexOf('image/svg+xml') > -1;
1402
+
1403
+ const createImgEle = (src) => {
1404
+ const ele = document.createElement('img');
1405
+ ele.setAttribute('src', src);
1406
+ return ele;
1407
+ };
1408
+
1409
+ const createSvgEle = (text) => {
1410
+ const parser = new DOMParser();
1411
+ const ele = parser.parseFromString(text, 'image/svg+xml').querySelector('svg');
1412
+ return ele;
1413
+ };
1414
+
1415
+ const createIcon = async (src) => {
1416
+ try {
1417
+ let ele;
1418
+
1419
+ if (isSvg(src)) {
1420
+ const fetchedSrc = await fetch(src);
1421
+ const text = await fetchedSrc.text();
1422
+ ele = createSvgEle(text);
1423
+ } else {
1424
+ ele = createImgEle(src);
1425
+ }
1426
+
1427
+ ele.style.setProperty('width', '100%');
1428
+ ele.style.setProperty('height', '100%');
1429
+
1430
+ return ele;
1431
+ } catch {
1432
+ return null;
1433
+ }
1434
+ };
1435
+
1396
1436
  /* eslint-disable no-use-before-define */
1397
1437
 
1398
1438
  const componentName$X = getComponentName('icon');
1399
1439
 
1400
1440
  class RawIcon extends createBaseClass({ componentName: componentName$X, baseSelector: 'slot' }) {
1441
+ static get observedAttributes() {
1442
+ return ['src', 'fill-color'];
1443
+ }
1444
+
1445
+ #icon;
1446
+
1401
1447
  constructor() {
1402
1448
  super();
1403
1449
 
@@ -1408,7 +1454,7 @@ class RawIcon extends createBaseClass({ componentName: componentName$X, baseSele
1408
1454
  width: 100%;
1409
1455
  height: 100%;
1410
1456
  display: flex;
1411
- overflow: auto;
1457
+ overflow: hidden;
1412
1458
  }
1413
1459
  :host {
1414
1460
  display: inline-block;
@@ -1418,30 +1464,53 @@ class RawIcon extends createBaseClass({ componentName: componentName$X, baseSele
1418
1464
  `;
1419
1465
  }
1420
1466
 
1421
- get items() {
1422
- return this.shadowRoot.querySelector('slot').assignedNodes();
1467
+ get fillColor() {
1468
+ return this.getAttribute('fill-color') === 'true';
1423
1469
  }
1424
1470
 
1425
- #onChildrenChange() {
1426
- // force hide icon if empty.
1427
- if (this.items?.length > 0) {
1428
- this.shadowRoot.host.style.setProperty('display', 'inline-block');
1429
- } else {
1430
- this.shadowRoot.host.style.setProperty('display', 'none');
1471
+ get src() {
1472
+ return this.getAttribute('src');
1473
+ }
1474
+
1475
+ // in order to fill an SVG with `currentColor` override all of its `fill` and `path` nodes
1476
+ // with the value from the `st-fill` attribute
1477
+ updateFillColor() {
1478
+ if (this.#icon && this.fillColor) {
1479
+ const fillCssVar = (selector) => {
1480
+ this.querySelectorAll(selector).forEach((ele) =>
1481
+ ele.setAttribute(
1482
+ 'fill',
1483
+ `var(${IconClass.cssVarList.fill}, ${ele.getAttribute('fill') || "''"})`
1484
+ )
1485
+ );
1486
+ };
1487
+
1488
+ fillCssVar('*[fill]');
1489
+ fillCssVar('path');
1431
1490
  }
1491
+ }
1432
1492
 
1433
- // set fill for all inner svgs to fill var and a fallback
1434
- const elems = this.querySelectorAll('*[fill]');
1435
- elems.forEach((ele) =>
1436
- ele.setAttribute(
1437
- 'fill',
1438
- `var(${IconClass.cssVarList.fill}, ${ele.getAttribute('fill') || "''"})`
1439
- )
1440
- );
1493
+ resetIcon() {
1494
+ if (!this.#icon) return;
1495
+ this.innerHTML = '';
1496
+ this.appendChild(this.#icon.cloneNode(true));
1441
1497
  }
1442
1498
 
1443
- init() {
1444
- observeChildren(this, this.#onChildrenChange.bind(this));
1499
+ attributeChangedCallback(attrName, oldValue, newValue) {
1500
+ super.attributeChangedCallback?.(attrName, oldValue, newValue);
1501
+
1502
+ if (oldValue === newValue) return;
1503
+
1504
+ if (attrName === 'src') {
1505
+ createIcon(this.src).then((res) => {
1506
+ this.#icon = res;
1507
+ this.resetIcon();
1508
+ this.updateFillColor();
1509
+ });
1510
+ } else if (attrName === 'fill-color') {
1511
+ this.resetIcon();
1512
+ this.updateFillColor();
1513
+ }
1445
1514
  }
1446
1515
  }
1447
1516
 
@@ -1504,9 +1573,10 @@ const iconStyles = `
1504
1573
 
1505
1574
  const editorOverrides = `vaadin-button::part(label) { pointer-events: none; }`;
1506
1575
 
1507
- const { host: host$n, label: label$a } = {
1576
+ const { host: host$n, label: label$a, slottedIcon } = {
1508
1577
  host: { selector: () => ':host' },
1509
1578
  label: { selector: '::part(label)' },
1579
+ slottedIcon: { selector: () => '::slotted(descope-icon)' },
1510
1580
  };
1511
1581
 
1512
1582
  let loadingIndicatorStyles;
@@ -1547,6 +1617,11 @@ const ButtonClass = compose(
1547
1617
  labelTextDecoration: { ...label$a, property: 'text-decoration' },
1548
1618
  labelSpacing: { ...label$a, property: 'gap' },
1549
1619
  textAlign: { ...label$a, property: 'justify-content', fallback: 'center' },
1620
+
1621
+ iconSize: [
1622
+ { ...slottedIcon, property: 'width' },
1623
+ { ...slottedIcon, property: 'height' },
1624
+ ],
1550
1625
  },
1551
1626
  }),
1552
1627
  clickableMixin,
@@ -12273,6 +12348,9 @@ const button = {
12273
12348
  [compVars$5.outlineStyle]: 'solid',
12274
12349
  [compVars$5.outlineColor]: 'transparent',
12275
12350
 
12351
+ [compVars$5.iconSize]: '1.5em',
12352
+ [compVars$5.iconColor]: 'currentColor',
12353
+
12276
12354
  size: {
12277
12355
  xs: { [compVars$5.fontSize]: '12px' },
12278
12356
  sm: { [compVars$5.fontSize]: '14px' },