@descope/web-components-ui 1.0.370 → 1.0.372

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. package/dist/cjs/index.cjs.js +410 -41
  2. package/dist/cjs/index.cjs.js.map +1 -1
  3. package/dist/index.esm.js +413 -42
  4. package/dist/index.esm.js.map +1 -1
  5. package/dist/umd/4392.js +1 -1
  6. package/dist/umd/4978.js +1 -1
  7. package/dist/umd/DescopeDev.js +1 -1
  8. package/dist/umd/button-selection-group-fields-descope-button-multi-selection-group-index-js.js +1 -1
  9. package/dist/umd/button-selection-group-fields-descope-button-selection-group-index-js.js +1 -1
  10. package/dist/umd/button-selection-group-fields-descope-button-selection-group-item-index-js.js +1 -1
  11. package/dist/umd/descope-button-index-js.js +2 -2
  12. package/dist/umd/descope-email-field-index-js.js +2 -2
  13. package/dist/umd/descope-icon-index-js.js +1 -1
  14. package/dist/umd/descope-new-password-descope-new-password-internal-index-js.js +1 -1
  15. package/dist/umd/descope-new-password-index-js.js +1 -1
  16. package/dist/umd/descope-number-field-index-js.js +1 -1
  17. package/dist/umd/descope-passcode-index-js.js +1 -1
  18. package/dist/umd/descope-password-index-js.js +1 -1
  19. package/dist/umd/descope-radio-group-index-js.js +1 -1
  20. package/dist/umd/descope-text-field-index-js.js +1 -1
  21. package/dist/umd/descope-upload-file-index-js.js +1 -1
  22. package/dist/umd/descope-user-attribute-index-js.js +1 -1
  23. package/dist/umd/descope-user-auth-method-index-js.js +1 -1
  24. package/dist/umd/mapping-fields-descope-mappings-field-index-js.js +1 -1
  25. package/package.json +1 -1
  26. package/src/components/descope-email-field/EmailFieldClass.js +12 -0
  27. package/src/components/descope-icon/IconClass.js +17 -30
  28. package/src/components/descope-new-password/NewPasswordClass.js +35 -0
  29. package/src/components/descope-new-password/descope-new-password-internal/NewPasswordInternal.js +3 -1
  30. package/src/components/descope-password/PasswordClass.js +59 -1
  31. package/src/components/descope-text-field/textFieldMappings.js +37 -6
  32. package/src/mixins/externalInputHelpers.js +86 -0
  33. package/src/mixins/externalInputMixin.js +165 -0
  34. package/src/mixins/index.js +1 -0
  35. package/src/mixins/proxyInputMixin.js +5 -2
  36. package/src/theme/components/button.js +0 -1
package/dist/index.esm.js CHANGED
@@ -1008,7 +1008,7 @@ const proxyInputMixin =
1008
1008
  ({
1009
1009
  proxyProps = [],
1010
1010
  // useProxyTargets flag allows to forwardProps to other targets, other than
1011
- // `this.inputElement`.
1011
+ // `this.inputElement`. It's to be used within `external-input` components,
1012
1012
  // if needed
1013
1013
  useProxyTargets = false,
1014
1014
  // allows us to set the event that should trigger validation
@@ -1147,7 +1147,10 @@ const proxyInputMixin =
1147
1147
 
1148
1148
  // sync properties
1149
1149
  proxyProps.forEach((prop) => {
1150
- const proxyTargets = useProxyTargets ? [this.baseElement].filter(Boolean) : [];
1150
+ const externalInput = this.querySelector('input[slot="external-input"]') || null;
1151
+ const proxyTargets = useProxyTargets
1152
+ ? [this.baseElement, externalInput].filter(Boolean)
1153
+ : [];
1151
1154
  forwardProps(this, [this.inputElement, ...proxyTargets], prop);
1152
1155
  });
1153
1156
 
@@ -1397,6 +1400,252 @@ const inputEventsDispatchingMixin = (superclass) =>
1397
1400
  }
1398
1401
  };
1399
1402
 
1403
+ // since on load we can only sample the color of the placeholder,
1404
+ // we need to temporarily populate the input in order to sample the value color
1405
+ const getValueColor = (ele, computedStyle) => {
1406
+ // eslint-disable-next-line no-param-reassign
1407
+ ele.value = '_';
1408
+
1409
+ const valueColor = computedStyle.getPropertyValue('color');
1410
+
1411
+ // eslint-disable-next-line no-param-reassign
1412
+ ele.value = '';
1413
+
1414
+ return valueColor;
1415
+ };
1416
+
1417
+ const createExternalInputSlot = (slotName, targetSlotName) => {
1418
+ const slotEle = document.createElement('slot');
1419
+
1420
+ slotEle.setAttribute('name', slotName);
1421
+ slotEle.setAttribute('slot', targetSlotName);
1422
+
1423
+ return slotEle;
1424
+ };
1425
+
1426
+ const createExternalInputEle = (targetSlotName, type, autocompleteType) => {
1427
+ const inputEle = document.createElement('input');
1428
+
1429
+ inputEle.setAttribute('slot', targetSlotName);
1430
+ inputEle.setAttribute('type', type);
1431
+ inputEle.setAttribute('data-hidden-input', 'true');
1432
+ inputEle.setAttribute('autocomplete', autocompleteType);
1433
+
1434
+ return inputEle;
1435
+ };
1436
+
1437
+ // We apply the original input's style to the external-input.
1438
+ // Eventually, the user should interact directly with the external input.
1439
+ // We keep the original input
1440
+ const applyExternalInputStyles = (sourceInputEle, targetInputEle, labelType) => {
1441
+ // We set a timeout here to avoid "Double Print" cases,
1442
+ // caused by sampling the computed style before it's ready.
1443
+ setTimeout(() => {
1444
+ const computedStyle = getComputedStyle(sourceInputEle);
1445
+ // Get minimal set of computed theme properties to set on external input
1446
+ const height = computedStyle.getPropertyValue('height');
1447
+ const paddingLeft = computedStyle.getPropertyValue('padding-left');
1448
+ const paddingRight = computedStyle.getPropertyValue('padding-right');
1449
+ const fontSize = computedStyle.getPropertyValue('font-size');
1450
+ const fontFamily = computedStyle.getPropertyValue('font-family');
1451
+ const letterSpacing = computedStyle.getPropertyValue('letter-spacing');
1452
+ const caretColor = computedStyle.getPropertyValue('caret-color');
1453
+
1454
+ const valueColor = getValueColor(sourceInputEle, computedStyle);
1455
+
1456
+ const commonThemeStyles = [
1457
+ ['all', 'unset'],
1458
+ ['position', 'absolute'],
1459
+ ['background-color', 'transparent'],
1460
+ ['height', height],
1461
+ ['left', paddingLeft],
1462
+ ['right', paddingRight],
1463
+ ['font-size', fontSize],
1464
+ ['font-family', fontFamily],
1465
+ ['letter-spacing', letterSpacing],
1466
+ ['caret-color', caretColor], // this is for seeing caret when focusing on external input
1467
+ ['color', valueColor],
1468
+ ];
1469
+
1470
+ commonThemeStyles.forEach(([key, val]) =>
1471
+ targetInputEle.style.setProperty(key, val, 'important')
1472
+ );
1473
+
1474
+ // Handle floating label theme properties
1475
+ if (labelType === 'floating') {
1476
+ const marginBottom = computedStyle.getPropertyValue('margin-bottom');
1477
+ targetInputEle.style.setProperty('margin-bottom', marginBottom, 'important');
1478
+ }
1479
+
1480
+ // sample and apply width only after original input is ready and fully rendered
1481
+ const width = computedStyle.getPropertyValue('width');
1482
+ targetInputEle.style.setProperty(
1483
+ 'width',
1484
+ `calc(${width} - ${paddingLeft} - ${paddingRight}`,
1485
+ 'important'
1486
+ );
1487
+ }, 0);
1488
+ };
1489
+
1490
+ const externalInputMixin =
1491
+ ({ inputType, autocompleteType, includeAttrs = [], noBlurDispatch = false }) =>
1492
+ (superclass) =>
1493
+ class ExternalInputMixinClass extends superclass {
1494
+ #timers = [];
1495
+
1496
+ get isExternalInput() {
1497
+ return this.getAttribute('external-input') === 'true';
1498
+ }
1499
+
1500
+ createExternalInput() {
1501
+ if (!this.isExternalInput) {
1502
+ return null;
1503
+ }
1504
+
1505
+ // use original input element as reference
1506
+ const origInput = this.baseElement.querySelector('input');
1507
+
1508
+ // to avoid focus loop between external-input and origInput
1509
+ // we set origInput's tabindex to -1
1510
+ // otherwise, shift-tab will never leave the component focus
1511
+ origInput.setAttribute('tabindex', '-1');
1512
+
1513
+ // create external slot
1514
+ const externalInputSlot = createExternalInputSlot('external-input', 'suffix');
1515
+
1516
+ // append external slot to base element
1517
+ this.baseElement.appendChild(externalInputSlot);
1518
+
1519
+ this.externalInput = createExternalInputEle(
1520
+ 'external-input',
1521
+ inputType,
1522
+ this.getAutocompleteType()
1523
+ );
1524
+
1525
+ // apply original input's styles to external input
1526
+ setTimeout(() => {
1527
+ applyExternalInputStyles(origInput, this.externalInput, this.getAttribute('label-type'));
1528
+ });
1529
+
1530
+ // 1Password catches the internal input, so we forward the value to the external input
1531
+ this.forwardInputValue(origInput, this.externalInput);
1532
+
1533
+ syncAttrs(origInput, this.externalInput, {
1534
+ includeAttrs,
1535
+ });
1536
+
1537
+ // We disable Vaadin's original `_setFocused` function, and use handleFocusEvents
1538
+ // and handleBlurEvents functions
1539
+ this.baseElement
1540
+ .querySelector('input')
1541
+ .addEventListener('focusout', (e) => e.stopImmediatePropagation(), true);
1542
+
1543
+ // In order to manage focus/blur events when moving between parts of the component
1544
+ // we're managing the event dispatching by ourselves, with the following strategy:
1545
+ // - If one of the component parts is focused - it means that the component is still focused - so we stop the blur events.
1546
+ // - When none of the component parts is focused, we dispatch blur event.
1547
+ this.handleFocusEvents();
1548
+ this.handleBlurEvents();
1549
+
1550
+ // sync input value
1551
+ this.handlelInputEvents(this.externalInput);
1552
+
1553
+ // append external input to component's DOM
1554
+ this.appendChild(this.externalInput);
1555
+
1556
+ return this.externalInput;
1557
+ }
1558
+
1559
+ clearBlurTimers() {
1560
+ this.#timers.forEach((timer) => clearTimeout(timer));
1561
+ this.#timers.length = 0;
1562
+ }
1563
+
1564
+ dispatchBlur() {
1565
+ return setTimeout(() => {
1566
+ this.dispatchEvent(new Event('blur', { bubbles: true, composed: true }));
1567
+ this.removeAttribute('focused');
1568
+ });
1569
+ }
1570
+
1571
+ handleFocusEvents() {
1572
+ // on baseElement `focus` we forward the focus to the external input.
1573
+ // also, in order to avoid any blur within the component, we clear the blur timers.
1574
+ this.baseElement.addEventListener('focus', () => {
1575
+ this.externalInput.focus();
1576
+ this.clearBlurTimers();
1577
+ });
1578
+
1579
+ // on `focus` of the external input, we manually set the `focused` attribute
1580
+ this.externalInput.addEventListener('focus', () => {
1581
+ this.clearBlurTimers();
1582
+ setTimeout(() => this.baseElement.setAttribute('focused', 'true'));
1583
+ });
1584
+ }
1585
+
1586
+ handleBlurEvents() {
1587
+ this.baseElement.addEventListener(
1588
+ 'blur',
1589
+ (e) => {
1590
+ e.stopImmediatePropagation();
1591
+ // some components do not require this synthetic blur dispatch (e.g. Password)
1592
+ // so we allow them to override this dispatch
1593
+ if (noBlurDispatch) return;
1594
+ this.#timers.push(this.dispatchBlur());
1595
+ },
1596
+ true
1597
+ );
1598
+
1599
+ this.externalInput.addEventListener(
1600
+ 'blur',
1601
+ (e) => {
1602
+ e.stopImmediatePropagation();
1603
+ this.#timers.push(this.dispatchBlur());
1604
+ },
1605
+ true
1606
+ );
1607
+ }
1608
+
1609
+ handlelInputEvents(externalInput) {
1610
+ // sync value of insible input back to original input
1611
+ externalInput.addEventListener('input', (e) => {
1612
+ this.value = e.target.value;
1613
+ });
1614
+
1615
+ // handle has-value attr
1616
+ externalInput.addEventListener('input', (e) => {
1617
+ if (!e.target.value) {
1618
+ this.removeAttribute('has-value');
1619
+ } else {
1620
+ this.setAttribute('has-value', 'true');
1621
+ }
1622
+ });
1623
+ }
1624
+
1625
+ getAutocompleteType() {
1626
+ return this.getAttribute('autocomplete') || autocompleteType;
1627
+ }
1628
+
1629
+ forwardInputValue(source, target) {
1630
+ // set internal sync events
1631
+ const valueDescriptor = Object.getOwnPropertyDescriptor(
1632
+ this.inputElement.constructor.prototype,
1633
+ 'value'
1634
+ );
1635
+
1636
+ Object.defineProperty(source, 'value', {
1637
+ ...valueDescriptor,
1638
+
1639
+ set(v) {
1640
+ valueDescriptor.set.call(this, v);
1641
+ // eslint-disable-next-line no-param-reassign
1642
+ target.value = v;
1643
+ },
1644
+ configurable: true,
1645
+ });
1646
+ }
1647
+ };
1648
+
1400
1649
  const getFileExtension = (path) => {
1401
1650
  const match = path.match(/\.([0-9a-z]+)(?:[\\?#]|$)/i);
1402
1651
  return match ? match[1] : null;
@@ -1453,7 +1702,7 @@ const componentName$_ = getComponentName('icon');
1453
1702
 
1454
1703
  class RawIcon extends createBaseClass({ componentName: componentName$_, baseSelector: 'slot' }) {
1455
1704
  static get observedAttributes() {
1456
- return ['src', 'fill-color'];
1705
+ return ['src'];
1457
1706
  }
1458
1707
 
1459
1708
  #icon;
@@ -1478,36 +1727,23 @@ class RawIcon extends createBaseClass({ componentName: componentName$_, baseSele
1478
1727
  `;
1479
1728
  }
1480
1729
 
1481
- get fillColor() {
1482
- return this.getAttribute('fill-color') === 'true';
1483
- }
1484
-
1485
1730
  get src() {
1486
1731
  return this.getAttribute('src');
1487
1732
  }
1488
1733
 
1489
1734
  // in order to fill an SVG with `currentColor` override all of its `fill` and `path` nodes
1490
1735
  // with the value from the `st-fill` attribute
1491
- updateFillColor() {
1492
- if (this.#icon && this.fillColor) {
1493
- const fillCssVar = (selector) => {
1494
- this.querySelectorAll(selector).forEach((ele) =>
1495
- ele.setAttribute(
1496
- 'fill',
1497
- `var(${IconClass.cssVarList.fill}, ${ele.getAttribute('fill') || "''"})`
1498
- )
1499
- );
1500
- };
1501
-
1502
- fillCssVar('*[fill]');
1503
- fillCssVar('path');
1504
- }
1505
- }
1506
-
1507
- resetIcon() {
1508
- if (!this.#icon) return;
1509
- this.innerHTML = '';
1510
- this.appendChild(this.#icon.cloneNode(true));
1736
+ // eslint-disable-next-line class-methods-use-this
1737
+ updateFillColor(node) {
1738
+ // set fill to root node and all its relevant selectors
1739
+ const elementsToReplace = [node, ...node.querySelectorAll('*[fill]')];
1740
+
1741
+ elementsToReplace.forEach((ele) => {
1742
+ ele.setAttribute(
1743
+ 'fill',
1744
+ `var(${IconClass.cssVarList.fill}, ${ele.getAttribute('fill') || "''"})`
1745
+ );
1746
+ });
1511
1747
  }
1512
1748
 
1513
1749
  attributeChangedCallback(attrName, oldValue, newValue) {
@@ -1517,13 +1753,13 @@ class RawIcon extends createBaseClass({ componentName: componentName$_, baseSele
1517
1753
 
1518
1754
  if (attrName === 'src') {
1519
1755
  createIcon(this.src).then((res) => {
1520
- this.#icon = res;
1521
- this.resetIcon();
1522
- this.updateFillColor();
1756
+ this.innerHTML = '';
1757
+ if (res) {
1758
+ const clonedNode = res.cloneNode(true);
1759
+ this.updateFillColor(clonedNode);
1760
+ this.appendChild(clonedNode);
1761
+ }
1523
1762
  });
1524
- } else if (attrName === 'fill-color') {
1525
- this.resetIcon();
1526
- this.updateFillColor();
1527
1763
  }
1528
1764
  }
1529
1765
  }
@@ -2614,6 +2850,10 @@ const {
2614
2850
  disabledPlaceholder,
2615
2851
  inputDisabled,
2616
2852
  inputIcon,
2853
+ externalInput,
2854
+ externalInputDisabled,
2855
+ externalPlaceholder,
2856
+ externalDisabledPlaceholder,
2617
2857
  } = {
2618
2858
  host: { selector: () => ':host' },
2619
2859
  label: { selector: '::part(label)' },
@@ -2630,6 +2870,10 @@ const {
2630
2870
  helperText: { selector: '::part(helper-text)' },
2631
2871
  errorMessage: { selector: '::part(error-message)' },
2632
2872
  inputIcon: { selector: 'vaadin-icon' },
2873
+ externalInput: { selector: () => '::slotted(input)' },
2874
+ externalInputDisabled: { selector: () => '::slotted(input:disabled)' },
2875
+ externalPlaceholder: { selector: () => '::slotted(input:placeholder-shown)' },
2876
+ externalDisabledPlaceholder: { selector: () => '::slotted(input:disabled::placeholder)' },
2633
2877
  };
2634
2878
 
2635
2879
  var textFieldMappings = {
@@ -2662,8 +2906,12 @@ var textFieldMappings = {
2662
2906
  inputValueTextColor: [
2663
2907
  { ...inputField$6, property: 'color' },
2664
2908
  { ...inputDisabled, property: '-webkit-text-fill-color' },
2909
+ { ...externalInputDisabled, property: '-webkit-text-fill-color' },
2910
+ ],
2911
+ inputCaretTextColor: [
2912
+ { ...input, property: 'caret-color' },
2913
+ { ...externalInput, property: 'caret-color' },
2665
2914
  ],
2666
- inputCaretTextColor: [{ ...input, property: 'color' }],
2667
2915
 
2668
2916
  labelRequiredIndicator: { ...requiredIndicator$9, property: 'content' },
2669
2917
 
@@ -2676,6 +2924,8 @@ var textFieldMappings = {
2676
2924
  inputHorizontalPadding: [
2677
2925
  { ...input, property: 'padding-left' },
2678
2926
  { ...input, property: 'padding-right' },
2927
+ { ...externalInput, property: 'padding-left' },
2928
+ { ...externalInput, property: 'padding-right' },
2679
2929
  ],
2680
2930
 
2681
2931
  inputOutlineColor: { ...inputField$6, property: 'outline-color' },
@@ -2683,12 +2933,17 @@ var textFieldMappings = {
2683
2933
  inputOutlineWidth: { ...inputField$6, property: 'outline-width' },
2684
2934
  inputOutlineOffset: { ...inputField$6, property: 'outline-offset' },
2685
2935
 
2686
- inputTextAlign: [{ ...input, property: 'text-align' }],
2936
+ inputTextAlign: [
2937
+ { ...input, property: 'text-align' },
2938
+ { ...externalInput, property: 'text-align' },
2939
+ ],
2687
2940
 
2688
2941
  inputPlaceholderColor: [
2689
2942
  { selector: () => ':host input:placeholder-shown', property: 'color' },
2943
+ { ...externalPlaceholder, property: 'color' },
2690
2944
  { ...placeholder$3, property: 'color' },
2691
2945
  { ...disabledPlaceholder, property: '-webkit-text-fill-color' },
2946
+ { ...externalDisabledPlaceholder, property: '-webkit-text-fill-color' },
2692
2947
  ],
2693
2948
 
2694
2949
  labelPosition: { ...label$9, property: 'position' },
@@ -2700,10 +2955,22 @@ var textFieldMappings = {
2700
2955
  inputTransformY: { ...label$9, property: 'transform' },
2701
2956
  inputTransition: { ...label$9, property: 'transition' },
2702
2957
  marginInlineStart: { ...label$9, property: 'margin-inline-start' },
2703
- placeholderOpacity: [{ selector: '> input:placeholder-shown', property: 'opacity' }],
2704
- inputVerticalAlignment: [{ ...inputField$6, property: 'align-items' }],
2705
- valueInputHeight: [{ ...input, property: 'height' }],
2706
- valueInputMarginBottom: [{ ...input, property: 'margin-bottom' }],
2958
+ placeholderOpacity: [
2959
+ { selector: '> input:placeholder-shown', property: 'opacity' },
2960
+ { ...externalPlaceholder, property: 'opacity' },
2961
+ ],
2962
+ inputVerticalAlignment: [
2963
+ { ...inputField$6, property: 'align-items' },
2964
+ { ...externalInput, property: 'align-items' },
2965
+ ],
2966
+ valueInputHeight: [
2967
+ { ...input, property: 'height' },
2968
+ { ...externalInput, property: 'height' },
2969
+ ],
2970
+ valueInputMarginBottom: [
2971
+ { ...input, property: 'margin-bottom' },
2972
+ { ...externalInput, property: 'margin-bottom' },
2973
+ ],
2707
2974
 
2708
2975
  inputIconOffset: [
2709
2976
  { ...inputIcon, property: 'margin-right' },
@@ -2729,6 +2996,8 @@ const customMixin$c = (superclass) =>
2729
2996
  if (!this.getAttribute('autocomplete')) {
2730
2997
  this.setAttribute('autocomplete', defaultAutocomplete);
2731
2998
  }
2999
+
3000
+ this.createExternalInput();
2732
3001
  }
2733
3002
  };
2734
3003
 
@@ -2737,6 +3006,11 @@ const EmailFieldClass = compose(
2737
3006
  mappings: textFieldMappings,
2738
3007
  }),
2739
3008
  draggableMixin,
3009
+ externalInputMixin({
3010
+ inputType: 'text',
3011
+ autocompleteType: 'username',
3012
+ includeAttrs: ['disabled', 'readonly', 'pattern'],
3013
+ }),
2740
3014
  composedProxyInputMixin({ proxyProps: ['value', 'selectionStart'], useProxyTargets: true }),
2741
3015
  componentNameValidationMixin,
2742
3016
  customMixin$c
@@ -2768,6 +3042,10 @@ const EmailFieldClass = compose(
2768
3042
  :host ::slotted(*) {
2769
3043
  -webkit-mask-image: none;
2770
3044
  }
3045
+
3046
+ vaadin-email-field[external-input="true"] > input:not(:placeholder-shown) {
3047
+ opacity: 0;
3048
+ }
2771
3049
  `,
2772
3050
  excludeAttrsSync: ['tabindex'],
2773
3051
  componentName: componentName$Q,
@@ -3606,6 +3884,15 @@ const customMixin$9 = (superclass) =>
3606
3884
  this.origSetPasswordVisible = this.baseElement._setPasswordVisible;
3607
3885
  this.origSetFocused = this.baseElement._setFocused;
3608
3886
  this.baseElement._setFocused = this.setFocus.bind(this);
3887
+
3888
+ this.initExternalInput();
3889
+ }
3890
+
3891
+ initExternalInput() {
3892
+ const externalInput = this.createExternalInput();
3893
+ if (externalInput) {
3894
+ this.handlePasswordVisibility(externalInput);
3895
+ }
3609
3896
  }
3610
3897
 
3611
3898
  get caretPosition() {
@@ -3620,6 +3907,7 @@ const customMixin$9 = (superclass) =>
3620
3907
  setTimeout(() => {
3621
3908
  origTogglePasswordVisibility();
3622
3909
  this.inputElement.setSelectionRange(this.caretPosition, this.caretPosition);
3910
+ return false;
3623
3911
  });
3624
3912
  };
3625
3913
  }
@@ -3646,6 +3934,44 @@ const customMixin$9 = (superclass) =>
3646
3934
  attributeChangedCallback(attrName, oldValue, newValue) {
3647
3935
  super.attributeChangedCallback?.(attrName, oldValue, newValue);
3648
3936
  }
3937
+
3938
+ // override vaadin's password visibility toggle.
3939
+ // we need this override in order to to resolve the external input `focus` race condition,
3940
+ // which is caused due to the focus sync between the two inputs.
3941
+ handlePasswordVisibility(externalInput) {
3942
+ // disable vaadin's `__boundRevealButtonMouseDown` mouse-down event lisetener
3943
+ const origBoundRevealButtonMouseDown = this.baseElement.__boundRevealButtonMouseDown;
3944
+ this.baseElement
3945
+ .querySelector('vaadin-password-field-button')
3946
+ .removeEventListener('mousedown', origBoundRevealButtonMouseDown);
3947
+
3948
+ // disable vaadin's `_passwordVisibleChanged` observer
3949
+ this.baseElement._passwordVisibleChanged = () => {};
3950
+
3951
+ // override vaadin's `_togglePasswordVisibility`
3952
+ this.baseElement._togglePasswordVisibility = () => {
3953
+ const currVisibility = externalInput.getAttribute('type');
3954
+ if (currVisibility === 'password') {
3955
+ this.showPasswordVisibility(externalInput);
3956
+ } else {
3957
+ this.hidePasswordVisibility(externalInput);
3958
+ }
3959
+ };
3960
+ }
3961
+
3962
+ showPasswordVisibility(input) {
3963
+ // handle input element's type
3964
+ input.setAttribute('type', 'text');
3965
+ // handle vaadin's `password-visible` attribute
3966
+ this.setAttribute('password-visible', 'true');
3967
+ }
3968
+
3969
+ hidePasswordVisibility(input) {
3970
+ // handle input element's type
3971
+ input.setAttribute('type', 'password');
3972
+ // handle vaadin's `password-visible` attribute
3973
+ this.setAttribute('password-visible', 'false');
3974
+ }
3649
3975
  };
3650
3976
 
3651
3977
  const {
@@ -3740,7 +4066,12 @@ const PasswordClass = compose(
3740
4066
  },
3741
4067
  }),
3742
4068
  draggableMixin,
3743
- composedProxyInputMixin({ proxyProps: ['value', 'selectionStart'] }),
4069
+ externalInputMixin({
4070
+ inputType: 'password',
4071
+ includeAttrs: ['disabled', 'readonly', 'pattern', 'type', 'autocomplete'],
4072
+ noBlurDispatch: true,
4073
+ }),
4074
+ composedProxyInputMixin({ proxyProps: ['value', 'selectionStart'], useProxyTargets: true }),
3744
4075
  componentNameValidationMixin,
3745
4076
  passwordDraggableMixin,
3746
4077
  customMixin$9
@@ -3804,6 +4135,10 @@ const PasswordClass = compose(
3804
4135
  ::part(reveal-button) {
3805
4136
  align-self: center;
3806
4137
  }
4138
+
4139
+ vaadin-password-field[external-input="true"] > input:not(:placeholder-shown) {
4140
+ opacity: 0;
4141
+ }
3807
4142
  `,
3808
4143
  excludeAttrsSync: ['tabindex'],
3809
4144
  componentName: componentName$H,
@@ -6931,11 +7266,14 @@ const customMixin$6 = (superclass) =>
6931
7266
 
6932
7267
  const template = document.createElement('template');
6933
7268
 
7269
+ const externalInputAttr = this.getAttribute('external-input');
7270
+
6934
7271
  template.innerHTML = `
6935
7272
  <${componentName$y}
6936
7273
  name="new-password"
6937
7274
  tabindex="-1"
6938
7275
  slot="input"
7276
+ external-input="${externalInputAttr}"
6939
7277
  >
6940
7278
  </${componentName$y}>
6941
7279
  `;
@@ -6944,6 +7282,10 @@ const customMixin$6 = (superclass) =>
6944
7282
 
6945
7283
  this.inputElement = this.shadowRoot.querySelector(componentName$y);
6946
7284
 
7285
+ if (this.getAttribute('external-input') === 'true') {
7286
+ this.initExternalInput();
7287
+ }
7288
+
6947
7289
  forwardAttrs(this, this.inputElement, {
6948
7290
  includeAttrs: [
6949
7291
  'password-label',
@@ -6968,6 +7310,34 @@ const customMixin$6 = (superclass) =>
6968
7310
  ],
6969
7311
  });
6970
7312
  }
7313
+
7314
+ createSlottedExternalInput(node, slotName) {
7315
+ const externalInput = node.querySelector('input');
7316
+ const slotEle = document.createElement('slot');
7317
+
7318
+ const targetSlot = externalInput.getAttribute('slot');
7319
+
7320
+ slotEle.setAttribute('name', slotName);
7321
+ slotEle.setAttribute('slot', targetSlot);
7322
+
7323
+ node.appendChild(slotEle);
7324
+
7325
+ // move external input
7326
+ externalInput.setAttribute('slot', slotName);
7327
+ externalInput.setAttribute('data-hidden-input', 'true');
7328
+
7329
+ this.appendChild(externalInput);
7330
+ }
7331
+
7332
+ initExternalInput() {
7333
+ // get descope input components
7334
+ this.passwordInput = this.inputElement.querySelector('[data-id="password"]');
7335
+ this.confirmInput = this.inputElement.querySelector('[data-id="confirm"]');
7336
+
7337
+ // create slots for external password input
7338
+ this.createSlottedExternalInput(this.passwordInput, 'external-password-input');
7339
+ this.createSlottedExternalInput(this.confirmInput, 'external-confirm-input');
7340
+ }
6971
7341
  };
6972
7342
 
6973
7343
  const {
@@ -7194,24 +7564,26 @@ class NewPasswordInternal extends BaseInputClass$4 {
7194
7564
  this.passwordInput.focus();
7195
7565
  }
7196
7566
  });
7197
-
7198
7567
  super.init?.();
7199
7568
  this.renderInputs(this.hasConfirm, this.hasValidation);
7200
7569
  }
7201
7570
 
7202
7571
  renderInputs() {
7572
+ const hasExternalInput = this.getAttribute('external-input') === 'true';
7203
7573
  const template = `
7204
7574
  <div>
7205
7575
  <descope-password
7206
7576
  autocomplete="new-password"
7207
7577
  manual-visibility-toggle="true"
7208
7578
  data-id="password"
7579
+ external-input="${hasExternalInput}"
7209
7580
  ></descope-password>
7210
7581
  <descope-policy-validation></descope-policy-validation>
7211
7582
  </div>
7212
7583
  <descope-password
7213
7584
  autocomplete="new-password"
7214
7585
  manual-visibility-toggle="true"
7586
+ external-input="${hasExternalInput}"
7215
7587
  data-id="confirm"
7216
7588
  ></descope-password>
7217
7589
  `;
@@ -12791,7 +13163,6 @@ const button = {
12791
13163
  [compVars$6.outlineColor]: 'transparent',
12792
13164
 
12793
13165
  [compVars$6.iconSize]: '1.5em',
12794
- [compVars$6.iconColor]: 'currentColor',
12795
13166
 
12796
13167
  size: {
12797
13168
  xs: { [compVars$6.fontSize]: '12px' },