@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/cjs/index.cjs.js +160 -13
- package/dist/cjs/index.cjs.js.map +1 -1
- package/dist/index.esm.js +164 -17
- package/dist/index.esm.js.map +1 -1
- package/dist/umd/DescopeDev.js +1 -1
- package/dist/umd/DescopeDev.js.map +1 -1
- package/dist/umd/descope-code-snippet-index-js.js +1 -1
- package/dist/umd/descope-code-snippet-index-js.js.map +1 -1
- package/dist/umd/descope-grid-index-js.js +1 -1
- package/dist/umd/descope-grid-index-js.js.map +1 -1
- package/dist/umd/index.js +1 -1
- package/dist/umd/index.js.map +1 -1
- package/package.json +31 -31
- package/src/components/descope-code-snippet/CodeSnippetClass.js +108 -4
- package/src/components/descope-code-snippet/check-icon.svg +3 -0
- package/src/components/descope-code-snippet/copy-icon.svg +4 -0
- package/src/components/descope-code-snippet/index.js +1 -0
- package/src/components/descope-grid/GridClass.js +21 -2
- package/src/components/descope-grid/helpers.js +22 -7
- package/src/theme/components/codeSnippet.js +7 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@descope/web-components-ui",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.6",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "dist/cjs/index.cjs.js",
|
|
6
6
|
"module": "dist/index.esm.js",
|
|
@@ -51,10 +51,10 @@
|
|
|
51
51
|
"webpack-cli": "^7.0.0",
|
|
52
52
|
"webpack-dev-server": "^5.0.0",
|
|
53
53
|
"webpack-subresource-integrity": "5.2.0-rc.1",
|
|
54
|
-
"rollup-replace-plugin": "3.1.
|
|
55
|
-
"
|
|
56
|
-
"webpack-
|
|
57
|
-
"
|
|
54
|
+
"rollup-replace-plugin": "3.1.6",
|
|
55
|
+
"webpack-extract-font-loader": "3.1.6",
|
|
56
|
+
"webpack-replace-plugin": "3.1.6",
|
|
57
|
+
"test-drivers": "3.1.6"
|
|
58
58
|
},
|
|
59
59
|
"dependencies": {
|
|
60
60
|
"@vaadin/checkbox": "24.3.4",
|
|
@@ -78,32 +78,32 @@
|
|
|
78
78
|
"libphonenumber-js": "^1.11.12",
|
|
79
79
|
"lodash.debounce": "4.0.8",
|
|
80
80
|
"lodash.merge": "4.6.2",
|
|
81
|
-
"@descope-ui/
|
|
82
|
-
"@descope-ui/descope-
|
|
83
|
-
"@descope-ui/descope-
|
|
84
|
-
"@descope-ui/descope-
|
|
85
|
-
"@descope-ui/descope-country-subdivision-city-field": "3.1.
|
|
86
|
-
"@descope-ui/descope-
|
|
87
|
-
"@descope-ui/descope-button": "3.1.
|
|
88
|
-
"@descope-ui/
|
|
89
|
-
"@descope-ui/descope-
|
|
90
|
-
"@descope-ui/descope-
|
|
91
|
-
"@descope-ui/descope-
|
|
92
|
-
"@descope-ui/descope-
|
|
93
|
-
"@descope-ui/descope-
|
|
94
|
-
"@descope-ui/descope-
|
|
95
|
-
"@descope-ui/descope-list": "3.1.
|
|
96
|
-
"@descope-ui/descope-outbound-app-button": "3.1.
|
|
97
|
-
"@descope-ui/descope-outbound-apps": "3.1.
|
|
98
|
-
"@descope-ui/descope-
|
|
99
|
-
"@descope-ui/descope-
|
|
100
|
-
"@descope-ui/descope-
|
|
101
|
-
"@descope-ui/descope-timer": "3.1.
|
|
102
|
-
"@descope-ui/descope-timer-button": "3.1.
|
|
103
|
-
"@descope-ui/descope-
|
|
104
|
-
"@descope-ui/descope-
|
|
105
|
-
"@descope-ui/descope-
|
|
106
|
-
"@descope-ui/descope-
|
|
81
|
+
"@descope-ui/common": "3.1.6",
|
|
82
|
+
"@descope-ui/descope-address-field": "3.1.6",
|
|
83
|
+
"@descope-ui/descope-apps-list": "3.1.6",
|
|
84
|
+
"@descope-ui/descope-autocomplete-field": "3.1.6",
|
|
85
|
+
"@descope-ui/descope-country-subdivision-city-field": "3.1.6",
|
|
86
|
+
"@descope-ui/descope-avatar": "3.1.6",
|
|
87
|
+
"@descope-ui/descope-button": "3.1.6",
|
|
88
|
+
"@descope-ui/descope-collapsible-container": "3.1.6",
|
|
89
|
+
"@descope-ui/descope-combo-box": "3.1.6",
|
|
90
|
+
"@descope-ui/descope-enriched-text": "3.1.6",
|
|
91
|
+
"@descope-ui/descope-icon": "3.1.6",
|
|
92
|
+
"@descope-ui/descope-image": "3.1.6",
|
|
93
|
+
"@descope-ui/descope-link": "3.1.6",
|
|
94
|
+
"@descope-ui/descope-list": "3.1.6",
|
|
95
|
+
"@descope-ui/descope-list-item": "3.1.6",
|
|
96
|
+
"@descope-ui/descope-outbound-app-button": "3.1.6",
|
|
97
|
+
"@descope-ui/descope-outbound-apps": "3.1.6",
|
|
98
|
+
"@descope-ui/descope-password-strength": "3.1.6",
|
|
99
|
+
"@descope-ui/descope-ponyhot": "3.1.6",
|
|
100
|
+
"@descope-ui/descope-badge": "3.1.6",
|
|
101
|
+
"@descope-ui/descope-timer": "3.1.6",
|
|
102
|
+
"@descope-ui/descope-timer-button": "3.1.6",
|
|
103
|
+
"@descope-ui/descope-tooltip": "3.1.6",
|
|
104
|
+
"@descope-ui/descope-trusted-devices": "3.1.6",
|
|
105
|
+
"@descope-ui/descope-recovery-codes": "3.1.6",
|
|
106
|
+
"@descope-ui/descope-text": "3.1.6"
|
|
107
107
|
},
|
|
108
108
|
"overrides": {
|
|
109
109
|
"@vaadin/avatar": "24.3.4",
|
|
@@ -5,19 +5,23 @@ import { compose } from '../../helpers';
|
|
|
5
5
|
import { getComponentName, observeChildren } from '../../helpers/componentHelpers';
|
|
6
6
|
import { createBaseClass } from '../../baseClasses/createBaseClass';
|
|
7
7
|
import { decode, tpl } from './helpers';
|
|
8
|
+
import copyIconSrc from './copy-icon.svg';
|
|
9
|
+
import checkIconSrc from './check-icon.svg';
|
|
8
10
|
|
|
9
11
|
export const componentName = getComponentName('code-snippet');
|
|
10
12
|
|
|
11
|
-
class CodeSnippet extends createBaseClass({ componentName, baseSelector: ':host >
|
|
13
|
+
class CodeSnippet extends createBaseClass({ componentName, baseSelector: ':host > .wrapper' }) {
|
|
12
14
|
static get observedAttributes() {
|
|
13
|
-
return ['lang', 'inline'];
|
|
15
|
+
return ['lang', 'inline', 'copy-button'];
|
|
14
16
|
}
|
|
15
17
|
|
|
16
18
|
constructor() {
|
|
17
19
|
super();
|
|
18
20
|
|
|
19
21
|
this.attachShadow({ mode: 'open' }).innerHTML = `
|
|
20
|
-
|
|
22
|
+
<div class="wrapper">
|
|
23
|
+
<code class="hljs"></code>
|
|
24
|
+
</div>
|
|
21
25
|
`;
|
|
22
26
|
|
|
23
27
|
injectStyle(
|
|
@@ -26,6 +30,10 @@ class CodeSnippet extends createBaseClass({ componentName, baseSelector: ':host
|
|
|
26
30
|
display: inline-block;
|
|
27
31
|
width: 100%;
|
|
28
32
|
}
|
|
33
|
+
.wrapper {
|
|
34
|
+
position: relative;
|
|
35
|
+
width: 100%;
|
|
36
|
+
}
|
|
29
37
|
code {
|
|
30
38
|
display: block;
|
|
31
39
|
width: 100%;
|
|
@@ -36,6 +44,38 @@ class CodeSnippet extends createBaseClass({ componentName, baseSelector: ':host
|
|
|
36
44
|
pre {
|
|
37
45
|
margin: 0;
|
|
38
46
|
}
|
|
47
|
+
.copy-btn {
|
|
48
|
+
position: absolute;
|
|
49
|
+
top: 8px;
|
|
50
|
+
right: 8px;
|
|
51
|
+
display: flex;
|
|
52
|
+
align-items: center;
|
|
53
|
+
justify-content: center;
|
|
54
|
+
padding: 0;
|
|
55
|
+
border-style: solid;
|
|
56
|
+
cursor: pointer;
|
|
57
|
+
opacity: 0;
|
|
58
|
+
transition: opacity 150ms ease, background 150ms ease;
|
|
59
|
+
}
|
|
60
|
+
.wrapper:hover .copy-btn,
|
|
61
|
+
.copy-btn:focus-visible {
|
|
62
|
+
opacity: 1;
|
|
63
|
+
}
|
|
64
|
+
.copy-btn descope-icon {
|
|
65
|
+
width: 16px;
|
|
66
|
+
height: 16px;
|
|
67
|
+
pointer-events: none;
|
|
68
|
+
flex-shrink: 0;
|
|
69
|
+
}
|
|
70
|
+
.copy-btn .check-icon {
|
|
71
|
+
display: none;
|
|
72
|
+
}
|
|
73
|
+
.copy-btn.copied .check-icon {
|
|
74
|
+
display: block;
|
|
75
|
+
}
|
|
76
|
+
.copy-btn.copied descope-icon:not(.check-icon) {
|
|
77
|
+
display: none;
|
|
78
|
+
}
|
|
39
79
|
`,
|
|
40
80
|
this
|
|
41
81
|
);
|
|
@@ -47,11 +87,15 @@ class CodeSnippet extends createBaseClass({ componentName, baseSelector: ':host
|
|
|
47
87
|
this.lang = this.getAttribute('lang');
|
|
48
88
|
this.isInline = this.getAttribute('inline') === 'true';
|
|
49
89
|
|
|
90
|
+
if (this.getAttribute('copy-button') === 'true') {
|
|
91
|
+
this.#initCopyButton();
|
|
92
|
+
}
|
|
93
|
+
|
|
50
94
|
observeChildren(this, this.#renderSnippet.bind(this));
|
|
51
95
|
}
|
|
52
96
|
|
|
53
97
|
get contentNode() {
|
|
54
|
-
return this.shadowRoot.querySelector(
|
|
98
|
+
return this.shadowRoot.querySelector('code');
|
|
55
99
|
}
|
|
56
100
|
|
|
57
101
|
attributeChangedCallback(attrName, oldValue, newValue) {
|
|
@@ -66,10 +110,58 @@ class CodeSnippet extends createBaseClass({ componentName, baseSelector: ':host
|
|
|
66
110
|
this.lang = newValue;
|
|
67
111
|
}
|
|
68
112
|
|
|
113
|
+
if (attrName === 'copy-button') {
|
|
114
|
+
if (newValue === 'true') {
|
|
115
|
+
this.#initCopyButton();
|
|
116
|
+
} else {
|
|
117
|
+
this.#destroyCopyButton();
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
69
121
|
this.#renderSnippet();
|
|
70
122
|
}
|
|
71
123
|
}
|
|
72
124
|
|
|
125
|
+
// ── Copy button ────────────────────────────────────────────────────────────
|
|
126
|
+
|
|
127
|
+
#initCopyButton() {
|
|
128
|
+
if (this.shadowRoot.querySelector('.copy-btn')) return;
|
|
129
|
+
|
|
130
|
+
const btn = document.createElement('button');
|
|
131
|
+
btn.className = 'copy-btn';
|
|
132
|
+
btn.type = 'button';
|
|
133
|
+
btn.setAttribute('aria-label', 'Copy code');
|
|
134
|
+
const copyIcon = document.createElement('descope-icon');
|
|
135
|
+
copyIcon.setAttribute('src', copyIconSrc);
|
|
136
|
+
|
|
137
|
+
const checkIcon = document.createElement('descope-icon');
|
|
138
|
+
checkIcon.setAttribute('src', checkIconSrc);
|
|
139
|
+
checkIcon.classList.add('check-icon');
|
|
140
|
+
|
|
141
|
+
btn.appendChild(copyIcon);
|
|
142
|
+
btn.appendChild(checkIcon);
|
|
143
|
+
btn.addEventListener('click', () => this.#handleCopyClick());
|
|
144
|
+
|
|
145
|
+
this.shadowRoot.querySelector('.wrapper').appendChild(btn);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
#destroyCopyButton() {
|
|
149
|
+
this.shadowRoot.querySelector('.copy-btn')?.remove();
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
#handleCopyClick() {
|
|
153
|
+
const btn = this.shadowRoot.querySelector('.copy-btn');
|
|
154
|
+
navigator.clipboard
|
|
155
|
+
.writeText(decode(this.textContent))
|
|
156
|
+
.then(() => {
|
|
157
|
+
btn.classList.add('copied');
|
|
158
|
+
setTimeout(() => btn.classList.remove('copied'), 2000);
|
|
159
|
+
})
|
|
160
|
+
.catch(() => {});
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// ── Snippet rendering ──────────────────────────────────────────────────────
|
|
164
|
+
|
|
73
165
|
#renderSnippet() {
|
|
74
166
|
const sanitized = decode(this.textContent);
|
|
75
167
|
const language = this.lang;
|
|
@@ -85,6 +177,8 @@ class CodeSnippet extends createBaseClass({ componentName, baseSelector: ':host
|
|
|
85
177
|
}
|
|
86
178
|
}
|
|
87
179
|
|
|
180
|
+
const copyBtn = { selector: () => '.copy-btn' };
|
|
181
|
+
|
|
88
182
|
const {
|
|
89
183
|
root,
|
|
90
184
|
docTag,
|
|
@@ -236,6 +330,16 @@ export const CodeSnippetClass = compose(
|
|
|
236
330
|
propertyTextColor: { ...property, property: 'color' },
|
|
237
331
|
punctuationTextColor: { ...punctuation, property: 'color' },
|
|
238
332
|
tagTextColor: { ...tag, property: 'color' },
|
|
333
|
+
copyButtonSize: [
|
|
334
|
+
{ ...copyBtn, property: 'width' },
|
|
335
|
+
{ ...copyBtn, property: 'height' },
|
|
336
|
+
],
|
|
337
|
+
copyButtonBorderRadius: { ...copyBtn, property: 'border-radius' },
|
|
338
|
+
copyButtonBorderWidth: { ...copyBtn, property: 'border-width' },
|
|
339
|
+
copyButtonBorderColor: { ...copyBtn, property: 'border-color' },
|
|
340
|
+
copyButtonBgColor: { ...copyBtn, property: 'background-color' },
|
|
341
|
+
copyButtonHoverBgColor: { selector: () => '.copy-btn:hover', property: 'background-color' },
|
|
342
|
+
copyButtonColor: { ...copyBtn, property: 'color' },
|
|
239
343
|
},
|
|
240
344
|
}),
|
|
241
345
|
draggableMixin,
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
2
|
+
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
|
|
3
|
+
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
|
|
4
|
+
</svg>
|
|
@@ -32,6 +32,18 @@ const GridMixin = (superclass) =>
|
|
|
32
32
|
};
|
|
33
33
|
|
|
34
34
|
this.baseElement.rowDetailsRenderer = this.#rowDetailsRenderer.bind(this);
|
|
35
|
+
|
|
36
|
+
// Stop wheel events from propagating to vaadin-grid when scrolling
|
|
37
|
+
// inside code snippets, so touchpad horizontal scroll works
|
|
38
|
+
this.baseElement.addEventListener(
|
|
39
|
+
'wheel',
|
|
40
|
+
(e) => {
|
|
41
|
+
if (e.target.closest('descope-code-snippet')) {
|
|
42
|
+
e.stopPropagation();
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
true
|
|
46
|
+
);
|
|
35
47
|
}
|
|
36
48
|
|
|
37
49
|
// this renders the details panel content
|
|
@@ -342,6 +354,14 @@ export const GridClass = compose(
|
|
|
342
354
|
grid-column: 1 / -1;
|
|
343
355
|
order: 2;
|
|
344
356
|
}
|
|
357
|
+
vaadin-grid details.row-details__item {
|
|
358
|
+
padding: 0;
|
|
359
|
+
}
|
|
360
|
+
vaadin-grid details.row-details__item > summary.row-details__label {
|
|
361
|
+
cursor: pointer;
|
|
362
|
+
list-style: revert;
|
|
363
|
+
display: revert;
|
|
364
|
+
}
|
|
345
365
|
vaadin-grid .row-details__value.text {
|
|
346
366
|
overflow: hidden;
|
|
347
367
|
text-overflow: ellipsis;
|
|
@@ -349,8 +369,7 @@ export const GridClass = compose(
|
|
|
349
369
|
}
|
|
350
370
|
vaadin-grid .row-details__value.code {
|
|
351
371
|
margin-top: 5px;
|
|
352
|
-
|
|
353
|
-
overflow: scroll;
|
|
372
|
+
overflow-x: auto;
|
|
354
373
|
font-size: 0.85em;
|
|
355
374
|
}
|
|
356
375
|
vaadin-grid vaadin-icon.toggle-details-button {
|
|
@@ -29,7 +29,7 @@ export const getValueType = (value) => {
|
|
|
29
29
|
};
|
|
30
30
|
|
|
31
31
|
export const renderCodeSnippet = (value, lang) =>
|
|
32
|
-
`<descope-code-snippet lang="${lang}" class="row-details__value code">${escapeXML(value)}</descope-code-snippet>`;
|
|
32
|
+
`<descope-code-snippet copy-button="true" lang="${lang}" class="row-details__value code">${escapeXML(value)}</descope-code-snippet>`;
|
|
33
33
|
|
|
34
34
|
export const renderText = (text) =>
|
|
35
35
|
`<div class="row-details__value text" title="${text}">${escapeXML(text)}</div>`;
|
|
@@ -57,16 +57,31 @@ const defaultRowDetailsValueRenderer = (value) => {
|
|
|
57
57
|
return renderText(value);
|
|
58
58
|
};
|
|
59
59
|
|
|
60
|
+
const isCodeSnippetValue = (value) => {
|
|
61
|
+
const type = getValueType(value);
|
|
62
|
+
return (
|
|
63
|
+
type === 'object' ||
|
|
64
|
+
type === 'xml' ||
|
|
65
|
+
(type === 'array' && value.some((v) => getValueType(v) === 'object'))
|
|
66
|
+
);
|
|
67
|
+
};
|
|
68
|
+
|
|
60
69
|
export const defaultRowDetailsRenderer = (item, itemLabelsMapping) => `
|
|
61
70
|
<div class="row-details">
|
|
62
71
|
${Object.entries(item)
|
|
63
|
-
.map(
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
72
|
+
.map(([key, value]) => {
|
|
73
|
+
const label = itemLabelsMapping[key] || toTitle(key);
|
|
74
|
+
if (isCodeSnippetValue(value)) {
|
|
75
|
+
return `<details class="row-details__item">
|
|
76
|
+
<summary class="row-details__label">${label}</summary>
|
|
77
|
+
${defaultRowDetailsValueRenderer(value)}
|
|
78
|
+
</details>`;
|
|
79
|
+
}
|
|
80
|
+
return `<div class="row-details__item">
|
|
81
|
+
<div class="row-details__label">${label}</div>
|
|
67
82
|
${defaultRowDetailsValueRenderer(value)}
|
|
68
|
-
</div
|
|
69
|
-
)
|
|
83
|
+
</div>`;
|
|
84
|
+
})
|
|
70
85
|
.join('\n')}
|
|
71
86
|
</div>
|
|
72
87
|
`;
|
|
@@ -39,6 +39,13 @@ const dark = {
|
|
|
39
39
|
};
|
|
40
40
|
|
|
41
41
|
const CodeSnippet = {
|
|
42
|
+
[vars.copyButtonSize]: '32px',
|
|
43
|
+
[vars.copyButtonBorderRadius]: globalRefs.radius.xs,
|
|
44
|
+
[vars.copyButtonBorderWidth]: globalRefs.border.xs,
|
|
45
|
+
[vars.copyButtonBorderColor]: globalRefs.colors.surface.light,
|
|
46
|
+
[vars.copyButtonBgColor]: globalRefs.colors.surface.highlight,
|
|
47
|
+
[vars.copyButtonHoverBgColor]: globalRefs.colors.surface.light,
|
|
48
|
+
[vars.copyButtonColor]: globalRefs.colors.surface.contrast,
|
|
42
49
|
[vars.rootBgColor]: globalRefs.colors.surface.main,
|
|
43
50
|
[vars.rootTextColor]: globalRefs.colors.surface.contrast,
|
|
44
51
|
[vars.docTagTextColor]: light.color2,
|