@descope/web-components-ui 1.0.364 → 1.0.365

Sign up to get free protection for your applications and to get access to all the features.
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' },