@descope/web-components-ui 3.16.3 → 3.17.0

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
@@ -16769,6 +16769,10 @@ var deleteIcon = "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTgi
16769
16769
 
16770
16770
  var editIcon = "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTgiIGhlaWdodD0iMTgiIHZpZXdCb3g9IjAgMCAxNSAxNSIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8cGF0aCBkPSJNMTAuMDAwMiAwLjk5MjE0OUMxMC4wMDAyIDEuMDE2MTUgMTAuMDAwMiAxLjAxNjE1IDEwLjAwMDIgMS4wMTYxNUw4LjIyNDE5IDMuMDA4MTVIMi45OTIxOUMyLjQ2NDE5IDMuMDA4MTUgMi4wMDgxOSAzLjQ0MDE1IDIuMDA4MTkgMy45OTIxNVYxMi4wMDgyQzIuMDA4MTkgMTIuNTM2MiAyLjQ0MDE5IDEyLjk5MjIgMi45OTIxOSAxMi45OTIySDUuNTM2MTlDNS44NDgxOSAxMy4wNDAyIDYuMTYwMTkgMTMuMDQwMiA2LjQ3MjE5IDEyLjk5MjJIMTEuMDA4MkMxMS41MzYyIDEyLjk5MjIgMTEuOTkyMiAxMi41NjAyIDExLjk5MjIgMTIuMDA4MlY3Ljc4NDE2TDEzLjkzNjIgNS42MjQxNUwxNC4wMDgyIDUuNjcyMTVWMTEuOTg0MkMxNC4wMDgyIDEzLjY2NDIgMTIuNjY0MiAxNS4wMDgyIDExLjAwODIgMTUuMDA4MkgzLjAxNjE5QzEuMzM2MTkgMTUuMDA4MiAtMC4wMDc4MTI1IDEzLjY2NDIgLTAuMDA3ODEyNSAxMS45ODQyVjMuOTkyMTVDLTAuMDA3ODEyNSAyLjMzNjE1IDEuMzM2MTkgMC45OTIxNDkgMy4wMTYxOSAwLjk5MjE0OUgxMC4wMDAyWk0xMS4yNzIyIDIuNjI0MTVMMTIuNjE2MiA0LjExMjE1TDcuNzIwMTkgOS42ODAxNkM3LjUwNDE5IDkuOTIwMTYgNi44MzIxOSAxMC4yMzIyIDUuNjgwMTkgMTAuNjE2MkM1LjY1NjE5IDEwLjY0MDIgNS42MDgxOSAxMC42NDAyIDUuNTYwMTkgMTAuNjE2MkM1LjQ2NDE5IDEwLjU5MjIgNS4zOTIxOSAxMC40NzIyIDUuNDQwMTkgMTAuMzc2MkM1Ljc1MjE5IDkuMjQ4MTYgNi4wNDAxOSA4LjU1MjE2IDYuMjU2MTkgOC4zMTIxNkwxMS4yNzIyIDIuNjI0MTVaTTExLjkyMDIgMS44NTYxNUwxMy4yODgyIDAuMzIwMTQ5QzEzLjY0ODIgLTAuMDg3ODUxNiAxNC4yNzIyIC0wLjExMTg1MiAxNC42ODAyIDAuMjcyMTQ5QzE1LjA4ODIgMC42MzIxNDkgMTUuMTEyMiAxLjI4MDE1IDE0Ljc1MjIgMS42ODgxNUwxMy4yNjQyIDMuMzY4MTVMMTEuOTIwMiAxLjg1NjE1WiIgZmlsbD0iY3VycmVudGNvbG9yIi8+Cjwvc3ZnPgo=";
16771
16771
 
16772
+ var copyIcon = "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTgiIGhlaWdodD0iMTgiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8cGF0aCBkPSJNMTYgMUg0Yy0xLjEgMC0yIC45LTIgMnYxNGgyVjNoMTJWMXptMyA0SDhjLTEuMSAwLTIgLjktMiAydjE0YzAgMS4xLjkgMiAyIDJoMTFjMS4xIDAgMi0uOSAyLTJWN2MwLTEuMS0uOS0yLTItMnptMCAxNkg4VjdoMTF2MTR6IiBmaWxsPSJjdXJyZW50Y29sb3IiLz4KPC9zdmc+Cg==";
16773
+
16774
+ var checkIcon = "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTgiIGhlaWdodD0iMTgiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8cGF0aCBkPSJNOSAxNi4xNyA0LjgzIDEybC0xLjQyIDEuNDFMOSAxOSAyMSA3bC0xLjQxLTEuNDF6IiBmaWxsPSJjdXJyZW50Y29sb3IiLz4KPC9zdmc+Cg==";
16775
+
16772
16776
  const componentName$G = getComponentName('user-attribute');
16773
16777
  class RawUserAttribute extends createBaseClass({
16774
16778
  componentName: componentName$G,
@@ -16784,6 +16788,10 @@ class RawUserAttribute extends createBaseClass({
16784
16788
  <descope-text st-text-align="auto" data-id="value-text" variant="body1" mode="primary" class="value"></descope-text>
16785
16789
  <div class="btn-wrapper">
16786
16790
  <descope-badge mode="default" bordered="true" size="xs"></descope-badge>
16791
+ <descope-button size="sm" data-id="copy-btn" variant="link" mode="primary">
16792
+ <slot name="copy-icon"></slot>
16793
+ <descope-icon class="check-icon" src="${checkIcon}" src-dark="${checkIcon}"></descope-icon>
16794
+ </descope-button>
16787
16795
  <descope-button size="sm" data-id="delete-btn" variant="link" mode="primary">
16788
16796
  <slot name="delete-icon"></slot>
16789
16797
  </descope-button>
@@ -16830,12 +16838,29 @@ class RawUserAttribute extends createBaseClass({
16830
16838
  }
16831
16839
 
16832
16840
  slot[name="edit-icon"],
16833
- slot[name="delete-icon"] {
16841
+ slot[name="delete-icon"],
16842
+ slot[name="copy-icon"] {
16834
16843
  display: inline-flex;
16835
16844
  flex-shrink: 0;
16836
16845
  align-items: center;
16837
16846
  }
16838
16847
 
16848
+ descope-button[data-id="copy-btn"].hidden {
16849
+ display: none;
16850
+ }
16851
+
16852
+ descope-button[data-id="copy-btn"] .check-icon {
16853
+ display: none;
16854
+ }
16855
+
16856
+ descope-button[data-id="copy-btn"].copied slot[name="copy-icon"] {
16857
+ display: none;
16858
+ }
16859
+
16860
+ descope-button[data-id="copy-btn"].copied .check-icon {
16861
+ display: inline-flex;
16862
+ }
16863
+
16839
16864
  .content-wrapper {
16840
16865
  display: flex;
16841
16866
  flex-grow: 1;
@@ -16878,7 +16903,7 @@ class RawUserAttribute extends createBaseClass({
16878
16903
  color: var(${TextClass.cssVarList.textColor});
16879
16904
  }
16880
16905
 
16881
- :host([readonly="true"]) descope-button {
16906
+ :host([readonly="true"]) descope-button:not([data-id="copy-btn"]) {
16882
16907
  visibility: hidden;
16883
16908
  width: 0;
16884
16909
  }
@@ -16886,6 +16911,7 @@ class RawUserAttribute extends createBaseClass({
16886
16911
  this
16887
16912
  );
16888
16913
 
16914
+ this.copyButton = this.shadowRoot.querySelector('descope-button[data-id="copy-btn"]');
16889
16915
  this.deleteButton = this.shadowRoot.querySelector('descope-button[data-id="delete-btn"]');
16890
16916
  this.editButton = this.shadowRoot.querySelector('descope-button[data-id="edit-btn"]');
16891
16917
  this.badge = this.shadowRoot.querySelector('descope-badge');
@@ -16975,6 +17001,14 @@ class RawUserAttribute extends createBaseClass({
16975
17001
  return this.getAttribute('hide-delete') === 'true';
16976
17002
  }
16977
17003
 
17004
+ get isCopyEnabled() {
17005
+ return this.getAttribute('show-copy') === 'true';
17006
+ }
17007
+
17008
+ get copyButtonLabel() {
17009
+ return this.getAttribute('copy-button-label') || '';
17010
+ }
17011
+
16978
17012
  init() {
16979
17013
  this.onLabelChange();
16980
17014
  this.onValueOrPlaceholderChange();
@@ -16983,7 +17017,9 @@ class RawUserAttribute extends createBaseClass({
16983
17017
  this.onBadgeTooltipTextChange();
16984
17018
  this.updateButtonLabel(this.editButton, this.editButtonLabel);
16985
17019
  this.updateButtonLabel(this.deleteButton, this.deleteButtonLabel);
17020
+ this.updateButtonLabel(this.copyButton, this.copyButtonLabel);
16986
17021
  this.handleDeleteButtonVisibility();
17022
+ this.handleCopyButtonState();
16987
17023
 
16988
17024
  this.deleteButton.addEventListener('click', () =>
16989
17025
  this.dispatchEvent(new CustomEvent('delete-clicked', { bubbles: true, composed: true }))
@@ -16993,9 +17029,35 @@ class RawUserAttribute extends createBaseClass({
16993
17029
  this.dispatchEvent(new CustomEvent('edit-clicked', { bubbles: true, composed: true }))
16994
17030
  );
16995
17031
 
17032
+ this.copyButton.addEventListener('click', () => this.#handleCopyClick());
17033
+
16996
17034
  this.setDefaultChildren();
16997
17035
  }
16998
17036
 
17037
+ #handleCopyClick() {
17038
+ // isDraggable is true only inside the page editor (craftjs sets draggable="true"
17039
+ // for drag-and-drop); there the copy action must not run.
17040
+ if (!this.value || this.isDraggable || !navigator.clipboard) return;
17041
+
17042
+ navigator.clipboard
17043
+ .writeText(this.value)
17044
+ .then(() => {
17045
+ this.copyButton.classList.add('copied');
17046
+ setTimeout(() => this.copyButton.classList.remove('copied'), 2000);
17047
+ })
17048
+ .catch(() => {});
17049
+ }
17050
+
17051
+ handleCopyButtonState() {
17052
+ this.copyButton.classList.toggle('hidden', !this.isCopyEnabled);
17053
+
17054
+ if (this.value) {
17055
+ this.copyButton.removeAttribute('disabled');
17056
+ } else {
17057
+ this.copyButton.setAttribute('disabled', 'true');
17058
+ }
17059
+ }
17060
+
16999
17061
  #addIcon(src, slotName) {
17000
17062
  const icon = document.createElement('descope-icon');
17001
17063
  icon.setAttribute('src', src);
@@ -17005,9 +17067,19 @@ class RawUserAttribute extends createBaseClass({
17005
17067
  }
17006
17068
 
17007
17069
  setDefaultChildren() {
17008
- if (this.children.length) return;
17009
- this.#addIcon(deleteIcon, 'delete-icon');
17010
- this.#addIcon(editIcon, 'edit-icon');
17070
+ if (!this.querySelector('[slot="delete-icon"]')) {
17071
+ this.#addIcon(deleteIcon, 'delete-icon');
17072
+ }
17073
+ if (!this.querySelector('[slot="edit-icon"]')) {
17074
+ this.#addIcon(editIcon, 'edit-icon');
17075
+ }
17076
+ this.setDefaultCopyIcon();
17077
+ }
17078
+
17079
+ setDefaultCopyIcon() {
17080
+ if (this.isCopyEnabled && !this.querySelector('[slot="copy-icon"]')) {
17081
+ this.#addIcon(copyIcon, 'copy-icon');
17082
+ }
17011
17083
  }
17012
17084
 
17013
17085
  static get observedAttributes() {
@@ -17020,7 +17092,9 @@ class RawUserAttribute extends createBaseClass({
17020
17092
  'badge-tooltip-text',
17021
17093
  'edit-button-label',
17022
17094
  'delete-button-label',
17095
+ 'copy-button-label',
17023
17096
  'hide-delete',
17097
+ 'show-copy',
17024
17098
  ].concat(super.observedAttributes);
17025
17099
  }
17026
17100
 
@@ -17052,11 +17126,19 @@ class RawUserAttribute extends createBaseClass({
17052
17126
  this.updateButtonLabel(this.editButton, this.editButtonLabel);
17053
17127
  } else if (name === 'delete-button-label') {
17054
17128
  this.updateButtonLabel(this.deleteButton, this.deleteButtonLabel);
17129
+ } else if (name === 'copy-button-label') {
17130
+ this.updateButtonLabel(this.copyButton, this.copyButtonLabel);
17131
+ } else if (name === 'show-copy') {
17132
+ this.setDefaultCopyIcon();
17055
17133
  }
17056
17134
 
17057
17135
  if (name === 'value' || name === 'required' || name === 'hide-delete') {
17058
17136
  this.handleDeleteButtonVisibility();
17059
17137
  }
17138
+
17139
+ if (name === 'value' || name === 'show-copy') {
17140
+ this.handleCopyButtonState();
17141
+ }
17060
17142
  }
17061
17143
  }
17062
17144
 
@@ -17085,7 +17167,12 @@ const UserAttributeClass = compose(
17085
17167
  contentMinWidth: { ...contentWrapper, property: 'min-width' },
17086
17168
  badgeMaxWidth: { ...badge$3, property: 'max-width' },
17087
17169
  itemsGap: [{ property: 'gap' }, { ...contentWrapper, property: 'gap' }],
17088
- iconColor: [{ selector: () => '::slotted(*)', property: IconClass.cssVarList.fill }],
17170
+ iconColor: [
17171
+ { selector: () => '::slotted(*)', property: IconClass.cssVarList.fill },
17172
+ // the copied check-icon lives in the shadow DOM (not slotted), so it
17173
+ // needs its own mapping to follow the same icon color
17174
+ { selector: () => '.check-icon', property: IconClass.cssVarList.fill },
17175
+ ],
17089
17176
  },
17090
17177
  }),
17091
17178
  draggableMixin,
@@ -19179,8 +19266,17 @@ class RawHybridField extends BaseClass$8 {
19179
19266
 
19180
19267
  setActiveInputSelectionStart() {
19181
19268
  setTimeout(() => {
19182
- this.activeInputEle.focus();
19183
- this.activeInputEle.setSelectionRange?.(this.#selectionStart, this.#selectionStart);
19269
+ const ele = this.activeInputEle;
19270
+ ele.focus();
19271
+ // setSelectionRange throws InvalidStateError on input types that do not
19272
+ // support selection (e.g. `email`). The focus handler usually switches
19273
+ // type to `text` first, but that can race with the blur timer or fail
19274
+ // to fire (e.g. background tab). Restoring the caret is best-effort.
19275
+ try {
19276
+ ele.setSelectionRange?.(this.#selectionStart, this.#selectionStart);
19277
+ } catch {
19278
+ /* noop */
19279
+ }
19184
19280
  });
19185
19281
  }
19186
19282