@descope/web-components-ui 1.0.371 → 1.0.372

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
@@ -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;
@@ -2601,6 +2850,10 @@ const {
2601
2850
  disabledPlaceholder,
2602
2851
  inputDisabled,
2603
2852
  inputIcon,
2853
+ externalInput,
2854
+ externalInputDisabled,
2855
+ externalPlaceholder,
2856
+ externalDisabledPlaceholder,
2604
2857
  } = {
2605
2858
  host: { selector: () => ':host' },
2606
2859
  label: { selector: '::part(label)' },
@@ -2617,6 +2870,10 @@ const {
2617
2870
  helperText: { selector: '::part(helper-text)' },
2618
2871
  errorMessage: { selector: '::part(error-message)' },
2619
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)' },
2620
2877
  };
2621
2878
 
2622
2879
  var textFieldMappings = {
@@ -2649,8 +2906,12 @@ var textFieldMappings = {
2649
2906
  inputValueTextColor: [
2650
2907
  { ...inputField$6, property: 'color' },
2651
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' },
2652
2914
  ],
2653
- inputCaretTextColor: [{ ...input, property: 'color' }],
2654
2915
 
2655
2916
  labelRequiredIndicator: { ...requiredIndicator$9, property: 'content' },
2656
2917
 
@@ -2663,6 +2924,8 @@ var textFieldMappings = {
2663
2924
  inputHorizontalPadding: [
2664
2925
  { ...input, property: 'padding-left' },
2665
2926
  { ...input, property: 'padding-right' },
2927
+ { ...externalInput, property: 'padding-left' },
2928
+ { ...externalInput, property: 'padding-right' },
2666
2929
  ],
2667
2930
 
2668
2931
  inputOutlineColor: { ...inputField$6, property: 'outline-color' },
@@ -2670,12 +2933,17 @@ var textFieldMappings = {
2670
2933
  inputOutlineWidth: { ...inputField$6, property: 'outline-width' },
2671
2934
  inputOutlineOffset: { ...inputField$6, property: 'outline-offset' },
2672
2935
 
2673
- inputTextAlign: [{ ...input, property: 'text-align' }],
2936
+ inputTextAlign: [
2937
+ { ...input, property: 'text-align' },
2938
+ { ...externalInput, property: 'text-align' },
2939
+ ],
2674
2940
 
2675
2941
  inputPlaceholderColor: [
2676
2942
  { selector: () => ':host input:placeholder-shown', property: 'color' },
2943
+ { ...externalPlaceholder, property: 'color' },
2677
2944
  { ...placeholder$3, property: 'color' },
2678
2945
  { ...disabledPlaceholder, property: '-webkit-text-fill-color' },
2946
+ { ...externalDisabledPlaceholder, property: '-webkit-text-fill-color' },
2679
2947
  ],
2680
2948
 
2681
2949
  labelPosition: { ...label$9, property: 'position' },
@@ -2687,10 +2955,22 @@ var textFieldMappings = {
2687
2955
  inputTransformY: { ...label$9, property: 'transform' },
2688
2956
  inputTransition: { ...label$9, property: 'transition' },
2689
2957
  marginInlineStart: { ...label$9, property: 'margin-inline-start' },
2690
- placeholderOpacity: [{ selector: '> input:placeholder-shown', property: 'opacity' }],
2691
- inputVerticalAlignment: [{ ...inputField$6, property: 'align-items' }],
2692
- valueInputHeight: [{ ...input, property: 'height' }],
2693
- 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
+ ],
2694
2974
 
2695
2975
  inputIconOffset: [
2696
2976
  { ...inputIcon, property: 'margin-right' },
@@ -2716,6 +2996,8 @@ const customMixin$c = (superclass) =>
2716
2996
  if (!this.getAttribute('autocomplete')) {
2717
2997
  this.setAttribute('autocomplete', defaultAutocomplete);
2718
2998
  }
2999
+
3000
+ this.createExternalInput();
2719
3001
  }
2720
3002
  };
2721
3003
 
@@ -2724,6 +3006,11 @@ const EmailFieldClass = compose(
2724
3006
  mappings: textFieldMappings,
2725
3007
  }),
2726
3008
  draggableMixin,
3009
+ externalInputMixin({
3010
+ inputType: 'text',
3011
+ autocompleteType: 'username',
3012
+ includeAttrs: ['disabled', 'readonly', 'pattern'],
3013
+ }),
2727
3014
  composedProxyInputMixin({ proxyProps: ['value', 'selectionStart'], useProxyTargets: true }),
2728
3015
  componentNameValidationMixin,
2729
3016
  customMixin$c
@@ -2755,6 +3042,10 @@ const EmailFieldClass = compose(
2755
3042
  :host ::slotted(*) {
2756
3043
  -webkit-mask-image: none;
2757
3044
  }
3045
+
3046
+ vaadin-email-field[external-input="true"] > input:not(:placeholder-shown) {
3047
+ opacity: 0;
3048
+ }
2758
3049
  `,
2759
3050
  excludeAttrsSync: ['tabindex'],
2760
3051
  componentName: componentName$Q,
@@ -3593,6 +3884,15 @@ const customMixin$9 = (superclass) =>
3593
3884
  this.origSetPasswordVisible = this.baseElement._setPasswordVisible;
3594
3885
  this.origSetFocused = this.baseElement._setFocused;
3595
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
+ }
3596
3896
  }
3597
3897
 
3598
3898
  get caretPosition() {
@@ -3607,6 +3907,7 @@ const customMixin$9 = (superclass) =>
3607
3907
  setTimeout(() => {
3608
3908
  origTogglePasswordVisibility();
3609
3909
  this.inputElement.setSelectionRange(this.caretPosition, this.caretPosition);
3910
+ return false;
3610
3911
  });
3611
3912
  };
3612
3913
  }
@@ -3633,6 +3934,44 @@ const customMixin$9 = (superclass) =>
3633
3934
  attributeChangedCallback(attrName, oldValue, newValue) {
3634
3935
  super.attributeChangedCallback?.(attrName, oldValue, newValue);
3635
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
+ }
3636
3975
  };
3637
3976
 
3638
3977
  const {
@@ -3727,7 +4066,12 @@ const PasswordClass = compose(
3727
4066
  },
3728
4067
  }),
3729
4068
  draggableMixin,
3730
- 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 }),
3731
4075
  componentNameValidationMixin,
3732
4076
  passwordDraggableMixin,
3733
4077
  customMixin$9
@@ -3791,6 +4135,10 @@ const PasswordClass = compose(
3791
4135
  ::part(reveal-button) {
3792
4136
  align-self: center;
3793
4137
  }
4138
+
4139
+ vaadin-password-field[external-input="true"] > input:not(:placeholder-shown) {
4140
+ opacity: 0;
4141
+ }
3794
4142
  `,
3795
4143
  excludeAttrsSync: ['tabindex'],
3796
4144
  componentName: componentName$H,
@@ -6918,11 +7266,14 @@ const customMixin$6 = (superclass) =>
6918
7266
 
6919
7267
  const template = document.createElement('template');
6920
7268
 
7269
+ const externalInputAttr = this.getAttribute('external-input');
7270
+
6921
7271
  template.innerHTML = `
6922
7272
  <${componentName$y}
6923
7273
  name="new-password"
6924
7274
  tabindex="-1"
6925
7275
  slot="input"
7276
+ external-input="${externalInputAttr}"
6926
7277
  >
6927
7278
  </${componentName$y}>
6928
7279
  `;
@@ -6931,6 +7282,10 @@ const customMixin$6 = (superclass) =>
6931
7282
 
6932
7283
  this.inputElement = this.shadowRoot.querySelector(componentName$y);
6933
7284
 
7285
+ if (this.getAttribute('external-input') === 'true') {
7286
+ this.initExternalInput();
7287
+ }
7288
+
6934
7289
  forwardAttrs(this, this.inputElement, {
6935
7290
  includeAttrs: [
6936
7291
  'password-label',
@@ -6955,6 +7310,34 @@ const customMixin$6 = (superclass) =>
6955
7310
  ],
6956
7311
  });
6957
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
+ }
6958
7341
  };
6959
7342
 
6960
7343
  const {
@@ -7181,24 +7564,26 @@ class NewPasswordInternal extends BaseInputClass$4 {
7181
7564
  this.passwordInput.focus();
7182
7565
  }
7183
7566
  });
7184
-
7185
7567
  super.init?.();
7186
7568
  this.renderInputs(this.hasConfirm, this.hasValidation);
7187
7569
  }
7188
7570
 
7189
7571
  renderInputs() {
7572
+ const hasExternalInput = this.getAttribute('external-input') === 'true';
7190
7573
  const template = `
7191
7574
  <div>
7192
7575
  <descope-password
7193
7576
  autocomplete="new-password"
7194
7577
  manual-visibility-toggle="true"
7195
7578
  data-id="password"
7579
+ external-input="${hasExternalInput}"
7196
7580
  ></descope-password>
7197
7581
  <descope-policy-validation></descope-policy-validation>
7198
7582
  </div>
7199
7583
  <descope-password
7200
7584
  autocomplete="new-password"
7201
7585
  manual-visibility-toggle="true"
7586
+ external-input="${hasExternalInput}"
7202
7587
  data-id="confirm"
7203
7588
  ></descope-password>
7204
7589
  `;