@descope/web-components-ui 1.0.363 → 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,
@@ -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' },