@descope/web-components-ui 1.0.300 → 1.0.302
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 +287 -207
- package/dist/cjs/index.cjs.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.esm.js +221 -141
- package/dist/index.esm.js.map +1 -1
- package/dist/umd/1612.js +1 -1
- package/dist/umd/1621.js +2 -2
- package/dist/umd/3951.js +1 -1
- package/dist/umd/4024.js +1 -1
- package/dist/umd/4052.js +1 -1
- package/dist/umd/4746.js +1 -1
- package/dist/umd/4978.js +1 -1
- package/dist/umd/5806.js +1 -1
- package/dist/umd/6770.js +1 -1
- package/dist/umd/7056.js +1 -1
- package/dist/umd/7531.js +1 -1
- package/dist/umd/7911.js +1 -1
- package/dist/umd/9092.js +2 -2
- package/dist/umd/9314.js +1 -1
- package/dist/umd/9423.js +2 -2
- package/dist/umd/9562.js +1 -1
- package/dist/umd/9927.js +1 -0
- package/dist/umd/DescopeDev.js +1 -1
- package/dist/umd/descope-button-index-js.js +1 -1
- package/dist/umd/descope-divider-index-js.js +1 -1
- package/dist/umd/descope-email-field-index-js.js +1 -1
- package/dist/umd/descope-enriched-text-index-js.js +1 -0
- package/dist/umd/descope-grid-descope-grid-custom-column-index-js.js +1 -1
- package/dist/umd/descope-grid-descope-grid-text-column-index-js.js +1 -1
- package/dist/umd/descope-link-index-js.js +1 -1
- package/dist/umd/descope-text-index-js.js +1 -0
- package/dist/umd/descope-user-attribute-index-js.js +1 -1
- package/dist/umd/descope-user-auth-method-index-js.js +1 -1
- package/dist/umd/index.js +1 -1
- package/dist/umd/mapping-fields-descope-mappings-field-index-js.js +1 -1
- package/dist/umd/mapping-fields-descope-saml-group-mappings-index-js.js +1 -1
- package/package.json +3 -3
- package/src/components/descope-divider/DividerClass.js +1 -1
- package/src/components/descope-divider/index.js +1 -1
- package/src/components/descope-enriched-text/EnrichedTextClass.js +162 -0
- package/src/components/descope-enriched-text/consts.js +74 -0
- package/src/components/descope-link/LinkClass.js +1 -1
- package/src/components/descope-link/index.js +1 -1
- package/src/components/descope-text/TextClass.js +62 -0
- package/src/components/descope-user-attribute/UserAttributeClass.js +1 -1
- package/src/components/descope-user-attribute/index.js +1 -1
- package/src/components/descope-user-auth-method/UserAuthMethodClass.js +1 -1
- package/src/components/descope-user-auth-method/index.js +1 -1
- package/src/components/mapping-fields/descope-mappings-field/MappingsFieldClass.js +1 -1
- package/src/components/mapping-fields/descope-mappings-field/index.js +1 -1
- package/src/helpers/componentHelpers.js +2 -2
- package/src/index.cjs.js +2 -2
- package/src/index.d.ts +2 -2
- package/src/index.js +2 -2
- package/src/theme/components/enrichedText.js +4 -1
- package/src/theme/components/text.js +1 -1
- package/dist/umd/4569.js +0 -1
- package/dist/umd/text-components-descope-enriched-text-index-js.js +0 -1
- package/dist/umd/text-components-descope-text-index-js.js +0 -1
- package/src/components/text-components/createBaseTextClass.js +0 -26
- package/src/components/text-components/descope-enriched-text/EnrichedTextClass.js +0 -106
- package/src/components/text-components/descope-enriched-text/helpers.js +0 -41
- package/src/components/text-components/descope-text/TextClass.js +0 -34
- package/src/components/text-components/hideWhenEmptyMixin.js +0 -17
- /package/src/components/{text-components/descope-enriched-text → descope-enriched-text}/index.js +0 -0
- /package/src/components/{text-components/descope-text → descope-text}/index.js +0 -0
package/dist/index.d.ts
CHANGED
@@ -24,8 +24,8 @@ export { NotpImageClass } from './components/descope-notp-image';
|
|
24
24
|
export { NumberFieldClass } from './components/descope-number-field';
|
25
25
|
export { PasscodeClass } from './components/descope-passcode';
|
26
26
|
export { PasswordClass } from './components/descope-password';
|
27
|
-
export { TextClass } from './components/
|
28
|
-
export { EnrichedTextClass } from './components/
|
27
|
+
export { TextClass } from './components/descope-text';
|
28
|
+
export { EnrichedTextClass } from './components/descope-enriched-text';
|
29
29
|
export { TextAreaClass } from './components/descope-text-area';
|
30
30
|
export { TextFieldClass } from './components/descope-text-field';
|
31
31
|
export { ImageClass } from './components/descope-image';
|
package/dist/index.esm.js
CHANGED
@@ -5,7 +5,7 @@ import '@vaadin/text-field';
|
|
5
5
|
import '@vaadin/email-field';
|
6
6
|
import '@vaadin/number-field';
|
7
7
|
import '@vaadin/password-field';
|
8
|
-
import
|
8
|
+
import { Remarkable } from 'remarkable';
|
9
9
|
import '@vaadin/text-area';
|
10
10
|
import '@vaadin/combo-box';
|
11
11
|
import '@vaadin/grid';
|
@@ -112,13 +112,13 @@ const observeChildren = (ele, callback) => {
|
|
112
112
|
|
113
113
|
const observer = new MutationObserver((mutationsList) => {
|
114
114
|
mutationsList.forEach((mutation) => {
|
115
|
-
if (mutation.type === 'childList') {
|
115
|
+
if (mutation.type === 'childList' || mutation.type === 'characterData') {
|
116
116
|
callback(mutation);
|
117
117
|
}
|
118
118
|
});
|
119
119
|
});
|
120
120
|
|
121
|
-
observer.observe(ele, { childList: true });
|
121
|
+
observer.observe(ele, { childList: true, characterData: true, subtree: true });
|
122
122
|
};
|
123
123
|
|
124
124
|
const createSyncAttrsCb =
|
@@ -2214,50 +2214,39 @@ const ContainerClass = compose(
|
|
2214
2214
|
|
2215
2215
|
customElements.define(componentName$M, ContainerClass);
|
2216
2216
|
|
2217
|
-
const
|
2218
|
-
class HideWhenEmptyMixinClass extends superclass {
|
2219
|
-
get hideWhenEmpty() {
|
2220
|
-
return this.getAttribute('hide-when-empty') === 'true';
|
2221
|
-
}
|
2222
|
-
|
2223
|
-
init() {
|
2224
|
-
super.init();
|
2225
|
-
|
2226
|
-
observeChildren(this, () => {
|
2227
|
-
const hasChildren = !!this.childNodes.length;
|
2228
|
-
this.style.display = !hasChildren && this.hideWhenEmpty ? 'none' : '';
|
2229
|
-
});
|
2230
|
-
}
|
2231
|
-
};
|
2232
|
-
|
2233
|
-
const createBaseTextClass = (componentName) => {
|
2234
|
-
class BaseText extends createBaseClass({ componentName, baseSelector: ':host > slot' }) {
|
2235
|
-
constructor() {
|
2236
|
-
super();
|
2217
|
+
const componentName$L = getComponentName('text');
|
2237
2218
|
|
2238
|
-
|
2239
|
-
|
2240
|
-
|
2241
|
-
display: inline-block;
|
2242
|
-
}
|
2243
|
-
:host > slot {
|
2244
|
-
width: 100%;
|
2245
|
-
display: inline-block;
|
2246
|
-
}
|
2247
|
-
</style>
|
2248
|
-
<slot part="text-wrapper"></slot>
|
2249
|
-
`;
|
2219
|
+
class RawText extends createBaseClass({ componentName: componentName$L, baseSelector: ':host > slot' }) {
|
2220
|
+
constructor() {
|
2221
|
+
super();
|
2250
2222
|
|
2251
|
-
|
2252
|
-
|
2223
|
+
this.attachShadow({ mode: 'open' }).innerHTML = `
|
2224
|
+
<style>
|
2225
|
+
:host {
|
2226
|
+
display: inline-block;
|
2227
|
+
}
|
2228
|
+
:host > slot {
|
2229
|
+
width: 100%;
|
2230
|
+
display: inline-block;
|
2231
|
+
}
|
2232
|
+
</style>
|
2233
|
+
<slot part="text-wrapper"></slot>
|
2234
|
+
`;
|
2253
2235
|
}
|
2254
2236
|
|
2255
|
-
|
2256
|
-
|
2237
|
+
get hideWhenEmpty() {
|
2238
|
+
return this.getAttribute('hide-when-empty') === 'true';
|
2239
|
+
}
|
2257
2240
|
|
2258
|
-
|
2241
|
+
init() {
|
2242
|
+
super.init();
|
2259
2243
|
|
2260
|
-
|
2244
|
+
observeChildren(this, () => {
|
2245
|
+
const hasChildren = !!this.childNodes.length;
|
2246
|
+
this.style.display = !hasChildren && this.hideWhenEmpty ? 'none' : '';
|
2247
|
+
});
|
2248
|
+
}
|
2249
|
+
}
|
2261
2250
|
|
2262
2251
|
const TextClass = compose(
|
2263
2252
|
createStyleMixin({
|
@@ -2280,9 +2269,8 @@ const TextClass = compose(
|
|
2280
2269
|
},
|
2281
2270
|
}),
|
2282
2271
|
draggableMixin,
|
2283
|
-
componentNameValidationMixin
|
2284
|
-
|
2285
|
-
)(BaseTextClass);
|
2272
|
+
componentNameValidationMixin
|
2273
|
+
)(RawText);
|
2286
2274
|
|
2287
2275
|
const componentName$K = getComponentName('divider');
|
2288
2276
|
class RawDivider extends createBaseClass({ componentName: componentName$K, baseSelector: ':host > div' }) {
|
@@ -3343,115 +3331,217 @@ const PasswordClass = compose(
|
|
3343
3331
|
|
3344
3332
|
customElements.define(componentName$A, PasswordClass);
|
3345
3333
|
|
3346
|
-
const
|
3347
|
-
|
3334
|
+
const ruleSet = {
|
3335
|
+
custom: ['image'],
|
3336
|
+
core: [
|
3337
|
+
'block',
|
3338
|
+
'inline',
|
3339
|
+
'abbr', // Parse abbreviation definitions, i.e. `*[abbr]: description`
|
3340
|
+
'abbr2', // Enclose abbreviations in <abbr> tags
|
3341
|
+
'references',
|
3342
|
+
'footnote_tail',
|
3343
|
+
'replacements', // Simple typographical replacements
|
3344
|
+
'smartquotes', // Convert straight quotation marks to typographic ones
|
3345
|
+
],
|
3346
|
+
inline: [
|
3347
|
+
'text',
|
3348
|
+
'newline', // Proceess '\n'
|
3349
|
+
'backticks', // Parse backticks
|
3350
|
+
'del', // Process ~~deleted text~~
|
3351
|
+
'emphasis', // Process *this* and _that_
|
3352
|
+
'sub', // Process ~subscript~
|
3353
|
+
'sup', // Process ^superscript^
|
3354
|
+
'links', // Process [links](<to> "stuff")
|
3355
|
+
'escape', // Proceess escaped chars and hardbreaks
|
3356
|
+
'ins', // Process ++inserted text++
|
3357
|
+
'mark', // Process ==highlighted text==
|
3358
|
+
'footnote_inline', // Process inline footnotes (^[...])
|
3359
|
+
'footnote_ref', // Process footnote references ([^...])
|
3360
|
+
'autolink', // Process autolinks '<protocol:...>'
|
3361
|
+
'htmltag', // Process html tags
|
3362
|
+
'entity', // Process html entity - {, ¯, ", ...
|
3363
|
+
],
|
3364
|
+
block: [
|
3365
|
+
'code', // Code block (4 spaces padded)
|
3366
|
+
'fences', // fences (``` lang, ~~~ lang)
|
3367
|
+
'blockquote', // Block quotes
|
3368
|
+
'list',
|
3369
|
+
'heading', // heading (#, ##, ...)
|
3370
|
+
'paragraph',
|
3371
|
+
'hr', // Horizontal rule
|
3372
|
+
'footnote', // Process footnote reference list
|
3373
|
+
'lheading', // lheading (---, ===)
|
3374
|
+
'htmlblock', // HTML block
|
3375
|
+
'table', // GFM table, non-standard
|
3376
|
+
'deflist', // Definition lists
|
3377
|
+
],
|
3348
3378
|
};
|
3349
3379
|
|
3350
|
-
const
|
3380
|
+
const textRuleSet = {
|
3381
|
+
core: ['block', 'inline'],
|
3382
|
+
inline: [
|
3383
|
+
'text',
|
3384
|
+
'newline', // Proceess '\n'
|
3385
|
+
'backticks', // Parse backticks
|
3386
|
+
'del', // Process ~~deleted text~~
|
3387
|
+
'emphasis', // Process *this* and _that_
|
3388
|
+
'sub', // Process ~subscript~
|
3389
|
+
'sup', // Process ^superscript^
|
3390
|
+
'links', // Process [links](<to> "stuff")
|
3391
|
+
'escape', // Proceess escaped chars and hardbreaks
|
3392
|
+
'ins', // Process ++inserted text++
|
3393
|
+
'footnote_inline', // Process inline footnotes (^[...])
|
3394
|
+
'footnote_ref', // Process footnote references ([^...])
|
3395
|
+
'autolink', // Process autolinks '<protocol:...>'
|
3396
|
+
],
|
3397
|
+
block: [
|
3398
|
+
'code', // Code block (4 spaces padded)
|
3399
|
+
'fences', // fences (``` lang, ~~~ lang)
|
3400
|
+
'blockquote', // Block quotes
|
3401
|
+
'list',
|
3402
|
+
'heading', // heading (#, ##, ...)
|
3403
|
+
'paragraph',
|
3404
|
+
'footnote', // Process footnote reference list
|
3405
|
+
'htmlblock', // HTML block
|
3406
|
+
],
|
3407
|
+
};
|
3351
3408
|
|
3352
|
-
const
|
3409
|
+
const componentName$z = getComponentName('enriched-text');
|
3353
3410
|
|
3354
|
-
|
3355
|
-
|
3356
|
-
const tag = getTokenTag(token);
|
3411
|
+
let EnrichedText$2 = class EnrichedText extends createBaseClass({ componentName: componentName$z, baseSelector: ':host > div' }) {
|
3412
|
+
#origImageRenderer;
|
3357
3413
|
|
3358
|
-
|
3359
|
-
|
3360
|
-
return {
|
3361
|
-
...token,
|
3362
|
-
tag,
|
3363
|
-
};
|
3364
|
-
}
|
3414
|
+
constructor() {
|
3415
|
+
super();
|
3365
3416
|
|
3366
|
-
|
3367
|
-
|
3368
|
-
|
3369
|
-
|
3370
|
-
|
3371
|
-
|
3372
|
-
|
3417
|
+
this.attachShadow({ mode: 'open' }).innerHTML = `
|
3418
|
+
<style>
|
3419
|
+
:host {
|
3420
|
+
display: inline-block;
|
3421
|
+
}
|
3422
|
+
:host > slot {
|
3423
|
+
width: 100%;
|
3424
|
+
display: inline-block;
|
3425
|
+
}
|
3426
|
+
*, *:last-child {
|
3427
|
+
margin: 0;
|
3428
|
+
}
|
3429
|
+
h1,
|
3430
|
+
h2,
|
3431
|
+
h3,
|
3432
|
+
h4,
|
3433
|
+
h5,
|
3434
|
+
h6,
|
3435
|
+
p {
|
3436
|
+
margin-bottom: 1em;
|
3437
|
+
}
|
3438
|
+
a {
|
3439
|
+
text-decoration: none;
|
3440
|
+
cursor: pointer;
|
3441
|
+
}
|
3442
|
+
a:hover {
|
3443
|
+
text-decoration: underline;
|
3444
|
+
}
|
3445
|
+
blockquote {
|
3446
|
+
padding: 0 2em;
|
3447
|
+
}
|
3448
|
+
</style>
|
3449
|
+
<slot part="text-wrapper" style="display:none"></slot>
|
3450
|
+
<div class="content"></div>
|
3451
|
+
`;
|
3373
3452
|
|
3374
|
-
|
3375
|
-
...token,
|
3376
|
-
tag,
|
3377
|
-
};
|
3378
|
-
});
|
3453
|
+
this.textSlot = this.shadowRoot.querySelector('slot');
|
3379
3454
|
|
3380
|
-
|
3381
|
-
const selection = document.getSelection().toString();
|
3382
|
-
const clipdata = e.clipboardData || window.clipboardData;
|
3383
|
-
clipdata.setData('text/plain', selection);
|
3384
|
-
clipdata.setData('text/html', selection);
|
3385
|
-
e.preventDefault();
|
3386
|
-
};
|
3455
|
+
this.#initProcessor();
|
3387
3456
|
|
3388
|
-
|
3457
|
+
observeChildren(this, this.#parseChildren.bind(this));
|
3458
|
+
}
|
3459
|
+
|
3460
|
+
static get observedAttributes() {
|
3461
|
+
return ['readonly'];
|
3462
|
+
}
|
3389
3463
|
|
3390
|
-
|
3464
|
+
attributeChangedCallback(attrName, oldValue, newValue) {
|
3465
|
+
super.attributeChangedCallback?.(attrName, oldValue, newValue);
|
3391
3466
|
|
3392
|
-
|
3393
|
-
|
3394
|
-
|
3395
|
-
|
3467
|
+
if (newValue !== oldValue) {
|
3468
|
+
if (attrName === 'readonly') {
|
3469
|
+
this.onReadOnlyChange(newValue === 'true');
|
3470
|
+
}
|
3396
3471
|
}
|
3472
|
+
}
|
3397
3473
|
|
3398
|
-
|
3399
|
-
|
3474
|
+
#disableAllRules() {
|
3475
|
+
if (!this.processor) {
|
3476
|
+
return;
|
3400
3477
|
}
|
3401
3478
|
|
3402
|
-
|
3403
|
-
|
3404
|
-
|
3479
|
+
ruleSet?.core && this.processor.core.ruler.disable(ruleSet.core);
|
3480
|
+
ruleSet?.inline && this.processor.inline.ruler.disable(ruleSet.inline);
|
3481
|
+
ruleSet?.block && this.processor.block.ruler.disable(ruleSet.block);
|
3405
3482
|
|
3406
|
-
|
3407
|
-
|
3408
|
-
|
3409
|
-
|
3483
|
+
this.processor.renderer.rules.image = () => {
|
3484
|
+
return '';
|
3485
|
+
};
|
3486
|
+
}
|
3487
|
+
|
3488
|
+
#enableCustomRules() {
|
3489
|
+
if (!this.processor) {
|
3490
|
+
return;
|
3410
3491
|
}
|
3411
3492
|
|
3412
|
-
|
3413
|
-
super.attributeChangedCallback?.(attrName, oldValue, newValue);
|
3493
|
+
const customRuleSet = textRuleSet;
|
3414
3494
|
|
3415
|
-
|
3416
|
-
|
3417
|
-
|
3418
|
-
this.#parseChildren();
|
3419
|
-
}
|
3420
|
-
}
|
3495
|
+
customRuleSet?.core && this.processor?.core.ruler.enable(customRuleSet?.core);
|
3496
|
+
customRuleSet?.inline && this.processor?.inline.ruler.enable(customRuleSet?.inline);
|
3497
|
+
customRuleSet?.block && this.processor?.block.ruler.enable(customRuleSet?.block);
|
3421
3498
|
|
3422
|
-
|
3423
|
-
|
3424
|
-
}
|
3499
|
+
if (customRuleSet?.custom?.includes('image')) {
|
3500
|
+
this.processor.renderer.rules.image = this.#origImageRenderer;
|
3425
3501
|
}
|
3502
|
+
}
|
3426
3503
|
|
3427
|
-
|
3428
|
-
|
3429
|
-
|
3504
|
+
#updateProcessorRules() {
|
3505
|
+
this.#disableAllRules();
|
3506
|
+
this.#enableCustomRules();
|
3507
|
+
}
|
3430
3508
|
|
3431
|
-
|
3432
|
-
|
3509
|
+
#initProcessor() {
|
3510
|
+
this.processor = new Remarkable();
|
3511
|
+
this.#origImageRenderer = this.processor.renderer.rules.image;
|
3512
|
+
this.#updateProcessorRules();
|
3513
|
+
}
|
3433
3514
|
|
3434
|
-
|
3435
|
-
|
3436
|
-
|
3437
|
-
breaks: this.lineBreak,
|
3438
|
-
});
|
3515
|
+
get contentNode() {
|
3516
|
+
return this.shadowRoot.querySelector('.content');
|
3517
|
+
}
|
3439
3518
|
|
3440
|
-
|
3441
|
-
|
3442
|
-
|
3443
|
-
// eslint-disable-next-line no-use-before-define
|
3444
|
-
span.innerHTML = `${getStyleReset()}${result}`;
|
3445
|
-
span.addEventListener('copy', onClipboardCopy);
|
3446
|
-
node.parentNode.replaceChild(span, node);
|
3447
|
-
}
|
3448
|
-
}
|
3519
|
+
#parseChildren() {
|
3520
|
+
if (!this.processor) {
|
3521
|
+
return;
|
3449
3522
|
}
|
3450
3523
|
|
3451
|
-
|
3452
|
-
|
3524
|
+
let html = this.textContent;
|
3525
|
+
|
3526
|
+
try {
|
3527
|
+
const tokens = this.processor.parse(this.textContent);
|
3528
|
+
html = this.processor.renderer.render(tokens, { breaks: true });
|
3529
|
+
} catch (e) {
|
3530
|
+
// eslint-disable-next-line no-console
|
3531
|
+
console.warn('Not parsing invalid markdown token');
|
3453
3532
|
}
|
3454
|
-
|
3533
|
+
|
3534
|
+
this.contentNode.innerHTML = html;
|
3535
|
+
}
|
3536
|
+
|
3537
|
+
onReadOnlyChange(isReadOnly) {
|
3538
|
+
if (isReadOnly) {
|
3539
|
+
this.setAttribute('inert', isReadOnly);
|
3540
|
+
} else {
|
3541
|
+
this.removeAttribute('inert');
|
3542
|
+
}
|
3543
|
+
}
|
3544
|
+
};
|
3455
3545
|
|
3456
3546
|
const EnrichedTextClass = compose(
|
3457
3547
|
createStyleMixin({
|
@@ -3463,26 +3553,14 @@ const EnrichedTextClass = compose(
|
|
3463
3553
|
fontWeight: {},
|
3464
3554
|
textColor: { property: 'color' },
|
3465
3555
|
textLineHeight: { property: 'line-height' },
|
3466
|
-
marginReset: { selector: '*', property: 'margin' },
|
3467
3556
|
textAlign: {},
|
3557
|
+
linkColor: { selector: 'a', property: 'color' },
|
3468
3558
|
},
|
3469
3559
|
}),
|
3560
|
+
createStyleMixin({ componentNameOverride: getComponentName('link') }),
|
3470
3561
|
draggableMixin,
|
3471
|
-
componentNameValidationMixin
|
3472
|
-
|
3473
|
-
hideWhenEmptyMixin
|
3474
|
-
)(BaseEnrichedTextClass);
|
3475
|
-
|
3476
|
-
function getStyleReset() {
|
3477
|
-
return `
|
3478
|
-
<style>
|
3479
|
-
.enriched-text > * { margin:0 }
|
3480
|
-
.enriched-text > *:not(:only-child):not(:last-child) {
|
3481
|
-
margin-bottom: var(${EnrichedTextClass.cssVarList.textLineHeight})
|
3482
|
-
}
|
3483
|
-
</style>
|
3484
|
-
`;
|
3485
|
-
}
|
3562
|
+
componentNameValidationMixin
|
3563
|
+
)(EnrichedText$2);
|
3486
3564
|
|
3487
3565
|
customElements.define(componentName$z, EnrichedTextClass);
|
3488
3566
|
|
@@ -11562,6 +11640,8 @@ const EnrichedText = {
|
|
11562
11640
|
[vars$q.textAlign]: 'left',
|
11563
11641
|
[vars$q.textColor]: globalRefs$i.colors.surface.dark,
|
11564
11642
|
|
11643
|
+
[vars$q.linkColor]: `var(${LinkClass.cssVarList.textColor})`,
|
11644
|
+
|
11565
11645
|
mode: {
|
11566
11646
|
primary: {
|
11567
11647
|
[vars$q.textColor]: globalRefs$i.colors.surface.contrast,
|