@descope/web-components-ui 3.1.5 → 3.1.6

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
@@ -14305,6 +14305,10 @@ const componentName$J = getComponentName('grid-item-details-column');
14305
14305
 
14306
14306
  customElements.define(componentName$J, GridItemDetailsColumnClass);
14307
14307
 
14308
+ customElements.define(componentName$1e, ImageClass);
14309
+
14310
+ customElements.define(componentName$1d, IconClass);
14311
+
14308
14312
  const decode = (input) => {
14309
14313
  const txt = document.createElement('textarea');
14310
14314
  txt.innerHTML = input;
@@ -14313,18 +14317,24 @@ const decode = (input) => {
14313
14317
 
14314
14318
  const tpl = (input, inline) => (inline ? input : `<pre>${input}</pre>`);
14315
14319
 
14320
+ var copyIconSrc = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiPgogIDxyZWN0IHg9IjkiIHk9IjkiIHdpZHRoPSIxMyIgaGVpZ2h0PSIxMyIgcng9IjIiIHJ5PSIyIj48L3JlY3Q+CiAgPHBhdGggZD0iTTUgMTVINGEyIDIgMCAwIDEtMi0yVjRhMiAyIDAgMCAxIDItMmg5YTIgMiAwIDAgMSAyIDJ2MSI+PC9wYXRoPgo8L3N2Zz4K";
14321
+
14322
+ var checkIconSrc = "data:image/svg+xml;base64,PHN2ZyBjbGFzcz0iY2hlY2staWNvbiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIj4KICA8cG9seWxpbmUgcG9pbnRzPSIyMCA2IDkgMTcgNCAxMiI+PC9wb2x5bGluZT4KPC9zdmc+Cg==";
14323
+
14316
14324
  const componentName$I = getComponentName('code-snippet');
14317
14325
 
14318
- let CodeSnippet$1 = class CodeSnippet extends createBaseClass({ componentName: componentName$I, baseSelector: ':host > code' }) {
14326
+ let CodeSnippet$1 = class CodeSnippet extends createBaseClass({ componentName: componentName$I, baseSelector: ':host > .wrapper' }) {
14319
14327
  static get observedAttributes() {
14320
- return ['lang', 'inline'];
14328
+ return ['lang', 'inline', 'copy-button'];
14321
14329
  }
14322
14330
 
14323
14331
  constructor() {
14324
14332
  super();
14325
14333
 
14326
14334
  this.attachShadow({ mode: 'open' }).innerHTML = `
14327
- <code class="hljs"></code>
14335
+ <div class="wrapper">
14336
+ <code class="hljs"></code>
14337
+ </div>
14328
14338
  `;
14329
14339
 
14330
14340
  injectStyle(
@@ -14333,6 +14343,10 @@ let CodeSnippet$1 = class CodeSnippet extends createBaseClass({ componentName: c
14333
14343
  display: inline-block;
14334
14344
  width: 100%;
14335
14345
  }
14346
+ .wrapper {
14347
+ position: relative;
14348
+ width: 100%;
14349
+ }
14336
14350
  code {
14337
14351
  display: block;
14338
14352
  width: 100%;
@@ -14343,6 +14357,38 @@ let CodeSnippet$1 = class CodeSnippet extends createBaseClass({ componentName: c
14343
14357
  pre {
14344
14358
  margin: 0;
14345
14359
  }
14360
+ .copy-btn {
14361
+ position: absolute;
14362
+ top: 8px;
14363
+ right: 8px;
14364
+ display: flex;
14365
+ align-items: center;
14366
+ justify-content: center;
14367
+ padding: 0;
14368
+ border-style: solid;
14369
+ cursor: pointer;
14370
+ opacity: 0;
14371
+ transition: opacity 150ms ease, background 150ms ease;
14372
+ }
14373
+ .wrapper:hover .copy-btn,
14374
+ .copy-btn:focus-visible {
14375
+ opacity: 1;
14376
+ }
14377
+ .copy-btn descope-icon {
14378
+ width: 16px;
14379
+ height: 16px;
14380
+ pointer-events: none;
14381
+ flex-shrink: 0;
14382
+ }
14383
+ .copy-btn .check-icon {
14384
+ display: none;
14385
+ }
14386
+ .copy-btn.copied .check-icon {
14387
+ display: block;
14388
+ }
14389
+ .copy-btn.copied descope-icon:not(.check-icon) {
14390
+ display: none;
14391
+ }
14346
14392
  `,
14347
14393
  this
14348
14394
  );
@@ -14354,11 +14400,15 @@ let CodeSnippet$1 = class CodeSnippet extends createBaseClass({ componentName: c
14354
14400
  this.lang = this.getAttribute('lang');
14355
14401
  this.isInline = this.getAttribute('inline') === 'true';
14356
14402
 
14403
+ if (this.getAttribute('copy-button') === 'true') {
14404
+ this.#initCopyButton();
14405
+ }
14406
+
14357
14407
  observeChildren(this, this.#renderSnippet.bind(this));
14358
14408
  }
14359
14409
 
14360
14410
  get contentNode() {
14361
- return this.shadowRoot.querySelector(this.baseSelector);
14411
+ return this.shadowRoot.querySelector('code');
14362
14412
  }
14363
14413
 
14364
14414
  attributeChangedCallback(attrName, oldValue, newValue) {
@@ -14373,10 +14423,58 @@ let CodeSnippet$1 = class CodeSnippet extends createBaseClass({ componentName: c
14373
14423
  this.lang = newValue;
14374
14424
  }
14375
14425
 
14426
+ if (attrName === 'copy-button') {
14427
+ if (newValue === 'true') {
14428
+ this.#initCopyButton();
14429
+ } else {
14430
+ this.#destroyCopyButton();
14431
+ }
14432
+ }
14433
+
14376
14434
  this.#renderSnippet();
14377
14435
  }
14378
14436
  }
14379
14437
 
14438
+ // ── Copy button ────────────────────────────────────────────────────────────
14439
+
14440
+ #initCopyButton() {
14441
+ if (this.shadowRoot.querySelector('.copy-btn')) return;
14442
+
14443
+ const btn = document.createElement('button');
14444
+ btn.className = 'copy-btn';
14445
+ btn.type = 'button';
14446
+ btn.setAttribute('aria-label', 'Copy code');
14447
+ const copyIcon = document.createElement('descope-icon');
14448
+ copyIcon.setAttribute('src', copyIconSrc);
14449
+
14450
+ const checkIcon = document.createElement('descope-icon');
14451
+ checkIcon.setAttribute('src', checkIconSrc);
14452
+ checkIcon.classList.add('check-icon');
14453
+
14454
+ btn.appendChild(copyIcon);
14455
+ btn.appendChild(checkIcon);
14456
+ btn.addEventListener('click', () => this.#handleCopyClick());
14457
+
14458
+ this.shadowRoot.querySelector('.wrapper').appendChild(btn);
14459
+ }
14460
+
14461
+ #destroyCopyButton() {
14462
+ this.shadowRoot.querySelector('.copy-btn')?.remove();
14463
+ }
14464
+
14465
+ #handleCopyClick() {
14466
+ const btn = this.shadowRoot.querySelector('.copy-btn');
14467
+ navigator.clipboard
14468
+ .writeText(decode(this.textContent))
14469
+ .then(() => {
14470
+ btn.classList.add('copied');
14471
+ setTimeout(() => btn.classList.remove('copied'), 2000);
14472
+ })
14473
+ .catch(() => {});
14474
+ }
14475
+
14476
+ // ── Snippet rendering ──────────────────────────────────────────────────────
14477
+
14380
14478
  #renderSnippet() {
14381
14479
  const sanitized = decode(this.textContent);
14382
14480
  const language = this.lang;
@@ -14392,6 +14490,8 @@ let CodeSnippet$1 = class CodeSnippet extends createBaseClass({ componentName: c
14392
14490
  }
14393
14491
  };
14394
14492
 
14493
+ const copyBtn = { selector: () => '.copy-btn' };
14494
+
14395
14495
  const {
14396
14496
  root,
14397
14497
  docTag,
@@ -14543,6 +14643,16 @@ const CodeSnippetClass = compose(
14543
14643
  propertyTextColor: { ...property, property: 'color' },
14544
14644
  punctuationTextColor: { ...punctuation, property: 'color' },
14545
14645
  tagTextColor: { ...tag, property: 'color' },
14646
+ copyButtonSize: [
14647
+ { ...copyBtn, property: 'width' },
14648
+ { ...copyBtn, property: 'height' },
14649
+ ],
14650
+ copyButtonBorderRadius: { ...copyBtn, property: 'border-radius' },
14651
+ copyButtonBorderWidth: { ...copyBtn, property: 'border-width' },
14652
+ copyButtonBorderColor: { ...copyBtn, property: 'border-color' },
14653
+ copyButtonBgColor: { ...copyBtn, property: 'background-color' },
14654
+ copyButtonHoverBgColor: { selector: () => '.copy-btn:hover', property: 'background-color' },
14655
+ copyButtonColor: { ...copyBtn, property: 'color' },
14546
14656
  },
14547
14657
  }),
14548
14658
  draggableMixin,
@@ -14580,7 +14690,7 @@ const getValueType = (value) => {
14580
14690
  };
14581
14691
 
14582
14692
  const renderCodeSnippet = (value, lang) =>
14583
- `<descope-code-snippet lang="${lang}" class="row-details__value code">${escapeXML(value)}</descope-code-snippet>`;
14693
+ `<descope-code-snippet copy-button="true" lang="${lang}" class="row-details__value code">${escapeXML(value)}</descope-code-snippet>`;
14584
14694
 
14585
14695
  const renderText = (text) =>
14586
14696
  `<div class="row-details__value text" title="${text}">${escapeXML(text)}</div>`;
@@ -14608,16 +14718,31 @@ const defaultRowDetailsValueRenderer = (value) => {
14608
14718
  return renderText(value);
14609
14719
  };
14610
14720
 
14721
+ const isCodeSnippetValue = (value) => {
14722
+ const type = getValueType(value);
14723
+ return (
14724
+ type === 'object' ||
14725
+ type === 'xml' ||
14726
+ (type === 'array' && value.some((v) => getValueType(v) === 'object'))
14727
+ );
14728
+ };
14729
+
14611
14730
  const defaultRowDetailsRenderer = (item, itemLabelsMapping) => `
14612
14731
  <div class="row-details">
14613
14732
  ${Object.entries(item)
14614
- .map(
14615
- ([key, value]) =>
14616
- `<div class="row-details__item" >
14617
- <div class="row-details__label">${itemLabelsMapping[key] || toTitle(key)}</div>
14733
+ .map(([key, value]) => {
14734
+ const label = itemLabelsMapping[key] || toTitle(key);
14735
+ if (isCodeSnippetValue(value)) {
14736
+ return `<details class="row-details__item">
14737
+ <summary class="row-details__label">${label}</summary>
14618
14738
  ${defaultRowDetailsValueRenderer(value)}
14619
- </div>`
14620
- )
14739
+ </details>`;
14740
+ }
14741
+ return `<div class="row-details__item">
14742
+ <div class="row-details__label">${label}</div>
14743
+ ${defaultRowDetailsValueRenderer(value)}
14744
+ </div>`;
14745
+ })
14621
14746
  .join('\n')}
14622
14747
  </div>
14623
14748
  `;
@@ -14645,6 +14770,18 @@ const GridMixin = (superclass) =>
14645
14770
  };
14646
14771
 
14647
14772
  this.baseElement.rowDetailsRenderer = this.#rowDetailsRenderer.bind(this);
14773
+
14774
+ // Stop wheel events from propagating to vaadin-grid when scrolling
14775
+ // inside code snippets, so touchpad horizontal scroll works
14776
+ this.baseElement.addEventListener(
14777
+ 'wheel',
14778
+ (e) => {
14779
+ if (e.target.closest('descope-code-snippet')) {
14780
+ e.stopPropagation();
14781
+ }
14782
+ },
14783
+ true
14784
+ );
14648
14785
  }
14649
14786
 
14650
14787
  // this renders the details panel content
@@ -14955,6 +15092,14 @@ const GridClass = compose(
14955
15092
  grid-column: 1 / -1;
14956
15093
  order: 2;
14957
15094
  }
15095
+ vaadin-grid details.row-details__item {
15096
+ padding: 0;
15097
+ }
15098
+ vaadin-grid details.row-details__item > summary.row-details__label {
15099
+ cursor: pointer;
15100
+ list-style: revert;
15101
+ display: revert;
15102
+ }
14958
15103
  vaadin-grid .row-details__value.text {
14959
15104
  overflow: hidden;
14960
15105
  text-overflow: ellipsis;
@@ -14962,8 +15107,7 @@ const GridClass = compose(
14962
15107
  }
14963
15108
  vaadin-grid .row-details__value.code {
14964
15109
  margin-top: 5px;
14965
- max-height: 120px;
14966
- overflow: scroll;
15110
+ overflow-x: auto;
14967
15111
  font-size: 0.85em;
14968
15112
  }
14969
15113
  vaadin-grid vaadin-icon.toggle-details-button {
@@ -16956,10 +17100,6 @@ const UserAttributeClass = compose(
16956
17100
 
16957
17101
  customElements.define(componentName$z, BadgeClass);
16958
17102
 
16959
- customElements.define(componentName$1e, ImageClass);
16960
-
16961
- customElements.define(componentName$1d, IconClass);
16962
-
16963
17103
  customElements.define(componentName$y, UserAttributeClass);
16964
17104
 
16965
17105
  var greenVIcon = "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTggMEMzLjYgMCAwIDMuNiAwIDhDMCAxMi40IDMuNiAxNiA4IDE2QzEyLjQgMTYgMTYgMTIuNCAxNiA4QzE2IDMuNiAxMi40IDAgOCAwWk03LjEgMTEuN0wyLjkgNy42TDQuMyA2LjJMNyA4LjlMMTIgNEwxMy40IDUuNEw3LjEgMTEuN1oiIGZpbGw9IiM0Q0FGNTAiLz4KPC9zdmc+Cg==";
@@ -26676,6 +26816,13 @@ const dark = {
26676
26816
  };
26677
26817
 
26678
26818
  const CodeSnippet = {
26819
+ [vars$c.copyButtonSize]: '32px',
26820
+ [vars$c.copyButtonBorderRadius]: globalRefs$6.radius.xs,
26821
+ [vars$c.copyButtonBorderWidth]: globalRefs$6.border.xs,
26822
+ [vars$c.copyButtonBorderColor]: globalRefs$6.colors.surface.light,
26823
+ [vars$c.copyButtonBgColor]: globalRefs$6.colors.surface.highlight,
26824
+ [vars$c.copyButtonHoverBgColor]: globalRefs$6.colors.surface.light,
26825
+ [vars$c.copyButtonColor]: globalRefs$6.colors.surface.contrast,
26679
26826
  [vars$c.rootBgColor]: globalRefs$6.colors.surface.main,
26680
26827
  [vars$c.rootTextColor]: globalRefs$6.colors.surface.contrast,
26681
26828
  [vars$c.docTagTextColor]: light.color2,