@descope/web-components-ui 1.0.363 → 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,
@@ -3071,18 +3146,9 @@ class PasscodeInternal extends BaseInputClass$7 {
3071
3146
  }
3072
3147
 
3073
3148
  initInputs() {
3074
- let currentInput;
3075
-
3076
3149
  this.inputs.forEach((input) => {
3077
3150
  input.shadowRoot.appendChild(createInputMaskStyle());
3078
3151
 
3079
- input.addEventListener('change', (e) => {
3080
- if (currentInput !== e.target) {
3081
- this.parseInputValue(input, input.value);
3082
- this.dispatchEvent(new Event('input', { bubbles: true, composed: true }));
3083
- }
3084
- });
3085
-
3086
3152
  const handleParseInput = (val) => {
3087
3153
  this.parseInputValue(input, val);
3088
3154
  toggleMaskVisibility(input);
@@ -3098,16 +3164,7 @@ class PasscodeInternal extends BaseInputClass$7 {
3098
3164
  toggleMaskVisibility(input, input.value[0]);
3099
3165
  }
3100
3166
 
3101
- // when using iPhone's code autofill we get only `change` events.
3102
- // In other scenarios we get `input` AND `change` events.
3103
- // In order to be parse the digits properly in iPhone, we need to listen to `change` event
3104
- // and validate it was not preceeded by an `input` event.
3105
- // To do so, we're keeping a reference to the input element in `input` events,
3106
- // and only if there the reference is null, then we're assuming no `input` event was preceeding,
3107
- // and we're parsing the digits.
3108
- currentInput = e.target;
3109
3167
  setTimeout(() => {
3110
- currentInput = null;
3111
3168
  if (e?.inputType === 'deleteContentBackward') {
3112
3169
  focusElement(this.getPrevInput(input));
3113
3170
  }
@@ -12291,6 +12348,9 @@ const button = {
12291
12348
  [compVars$5.outlineStyle]: 'solid',
12292
12349
  [compVars$5.outlineColor]: 'transparent',
12293
12350
 
12351
+ [compVars$5.iconSize]: '1.5em',
12352
+ [compVars$5.iconColor]: 'currentColor',
12353
+
12294
12354
  size: {
12295
12355
  xs: { [compVars$5.fontSize]: '12px' },
12296
12356
  sm: { [compVars$5.fontSize]: '14px' },