@lion/ui 0.0.12 → 0.0.14
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/components/accordion/src/LionAccordion.js +22 -9
- package/components/accordion/test/lion-accordion.test.js +29 -32
- package/components/icon/src/LionIcon.js +11 -4
- package/components/input-tel/translations/bg.js +3 -1
- package/components/input-tel/translations/cs.js +3 -1
- package/components/input-tel/translations/de.js +3 -1
- package/components/input-tel/translations/en.js +3 -1
- package/components/input-tel/translations/es.js +3 -1
- package/components/input-tel/translations/fr.js +3 -1
- package/components/input-tel/translations/hu.js +3 -1
- package/components/input-tel/translations/it.js +3 -1
- package/components/input-tel/translations/nl.js +3 -1
- package/components/input-tel/translations/pl.js +3 -1
- package/components/input-tel/translations/ro.js +3 -1
- package/components/input-tel/translations/ru.js +3 -1
- package/components/input-tel/translations/sk.js +3 -1
- package/components/input-tel/translations/uk.js +3 -1
- package/components/input-tel/translations/zh.js +3 -1
- package/components/input-tel-dropdown/src/LionInputTelDropdown.js +5 -5
- package/components/listbox/src/ListboxMixin.js +0 -4
- package/components/listbox/types/ListboxMixinTypes.ts +1 -4
- package/components/localize/src/LocalizeMixin.js +4 -3
- package/components/overlays/src/OverlayController.js +14 -25
- package/components/overlays/src/utils/adopt-styles.js +136 -0
- package/components/overlays/test/OverlayController.test.js +8 -55
- package/components/overlays/test/local-positioning.test.js +1 -1
- package/components/overlays/test/utils-tests/adopt-styles.test.js +177 -0
- package/components/overlays/test-helpers/createShadowHost.js +16 -0
- package/components/overlays/{test/utils-tests/local-positioning-helpers.js → test-helpers/normalizeTransformStyle.js} +0 -0
- package/components/select-rich/src/LionSelectRich.js +12 -6
- package/components/select-rich/test/lion-select-rich.test.js +25 -1
- package/custom-elements.json +418 -113
- package/dist-types/components/accordion/src/LionAccordion.d.ts.map +1 -1
- package/dist-types/components/icon/src/LionIcon.d.ts.map +1 -1
- package/dist-types/components/input-tel/translations/bg-BG.d.ts +3 -1
- package/dist-types/components/input-tel/translations/bg.d.ts +3 -1
- package/dist-types/components/input-tel/translations/cs-CZ.d.ts +3 -1
- package/dist-types/components/input-tel/translations/cs.d.ts +3 -1
- package/dist-types/components/input-tel/translations/de-DE.d.ts +3 -1
- package/dist-types/components/input-tel/translations/de.d.ts +3 -1
- package/dist-types/components/input-tel/translations/en-AU.d.ts +3 -1
- package/dist-types/components/input-tel/translations/en-GB.d.ts +3 -1
- package/dist-types/components/input-tel/translations/en-US.d.ts +3 -1
- package/dist-types/components/input-tel/translations/en.d.ts +3 -1
- package/dist-types/components/input-tel/translations/es-ES.d.ts +3 -1
- package/dist-types/components/input-tel/translations/es.d.ts +3 -1
- package/dist-types/components/input-tel/translations/fr-BE.d.ts +3 -1
- package/dist-types/components/input-tel/translations/fr-FR.d.ts +3 -1
- package/dist-types/components/input-tel/translations/fr.d.ts +3 -1
- package/dist-types/components/input-tel/translations/hu-HU.d.ts +3 -1
- package/dist-types/components/input-tel/translations/hu.d.ts +3 -1
- package/dist-types/components/input-tel/translations/it-IT.d.ts +3 -1
- package/dist-types/components/input-tel/translations/it.d.ts +3 -1
- package/dist-types/components/input-tel/translations/nl-BE.d.ts +3 -1
- package/dist-types/components/input-tel/translations/nl-NL.d.ts +3 -1
- package/dist-types/components/input-tel/translations/nl.d.ts +3 -1
- package/dist-types/components/input-tel/translations/pl-PL.d.ts +3 -1
- package/dist-types/components/input-tel/translations/pl.d.ts +3 -1
- package/dist-types/components/input-tel/translations/ro-RO.d.ts +3 -1
- package/dist-types/components/input-tel/translations/ro.d.ts +3 -1
- package/dist-types/components/input-tel/translations/ru-RU.d.ts +3 -1
- package/dist-types/components/input-tel/translations/ru.d.ts +3 -1
- package/dist-types/components/input-tel/translations/sk-SK.d.ts +3 -1
- package/dist-types/components/input-tel/translations/sk.d.ts +3 -1
- package/dist-types/components/input-tel/translations/uk-UA.d.ts +3 -1
- package/dist-types/components/input-tel/translations/uk.d.ts +3 -1
- package/dist-types/components/input-tel/translations/zh.d.ts +3 -1
- package/dist-types/components/listbox/src/ListboxMixin.d.ts.map +1 -1
- package/dist-types/components/listbox/types/ListboxMixinTypes.d.ts +1 -2
- package/dist-types/components/listbox/types/ListboxMixinTypes.d.ts.map +1 -1
- package/dist-types/components/localize/src/LocalizeMixin.d.ts +1 -0
- package/dist-types/components/localize/src/LocalizeMixin.d.ts.map +1 -1
- package/dist-types/components/overlays/src/OverlayController.d.ts +5 -1
- package/dist-types/components/overlays/src/OverlayController.d.ts.map +1 -1
- package/dist-types/components/overlays/src/utils/adopt-styles.d.ts +24 -0
- package/dist-types/components/overlays/src/utils/adopt-styles.d.ts.map +1 -0
- package/dist-types/components/overlays/test/OverlayController.test.d.ts.map +1 -1
- package/dist-types/components/overlays/test/utils-tests/adopt-styles.test.d.ts +2 -0
- package/dist-types/components/overlays/test/utils-tests/adopt-styles.test.d.ts.map +1 -0
- package/dist-types/components/overlays/test-helpers/createShadowHost.d.ts +8 -0
- package/dist-types/components/overlays/test-helpers/createShadowHost.d.ts.map +1 -0
- package/dist-types/components/overlays/{test/utils-tests/local-positioning-helpers.d.ts → test-helpers/normalizeTransformStyle.d.ts} +1 -1
- package/dist-types/components/overlays/test-helpers/normalizeTransformStyle.d.ts.map +1 -0
- package/dist-types/components/select-rich/src/LionSelectRich.d.ts +8 -8
- package/dist-types/components/select-rich/src/LionSelectRich.d.ts.map +1 -1
- package/dist-types/tsconfig.tsbuildinfo +1 -1
- package/docs/components/button/use-cases.md +2 -0
- package/docs/components/checkbox-group/overview.md +2 -2
- package/docs/components/collapsible/overview.md +1 -1
- package/docs/components/combobox/overview.md +1 -1
- package/docs/components/combobox/src/demo-selection-display.js +1 -1
- package/docs/components/combobox/use-cases.md +1 -1
- package/docs/components/dialog/overview.md +1 -1
- package/docs/components/dialog/src/demoStyle.js +18 -0
- package/docs/components/fieldset/overview.md +5 -5
- package/docs/components/form/overview.md +3 -3
- package/docs/components/icon/use-cases.md +1 -1
- package/docs/components/input/overview.md +1 -1
- package/docs/components/input-amount/overview.md +3 -3
- package/docs/components/input-date/overview.md +3 -3
- package/docs/components/input-datepicker/overview.md +5 -5
- package/docs/components/input-email/overview.md +2 -2
- package/docs/components/input-iban/overview.md +2 -2
- package/docs/components/input-range/overview.md +2 -2
- package/docs/components/input-stepper/overview.md +1 -1
- package/docs/components/input-tel/overview.md +1 -1
- package/docs/components/input-tel/use-cases.md +6 -6
- package/docs/components/input-tel-dropdown/overview.md +1 -1
- package/docs/components/radio-group/overview.md +3 -3
- package/docs/components/select-rich/use-cases.md +30 -24
- package/docs/components/tabs/examples.md +1 -1
- package/docs/fundamentals/index.md +4 -4
- package/docs/fundamentals/node-tools/providence-analytics/LocalConfiguration.md +1 -1
- package/docs/fundamentals/node-tools/providence-analytics/QueryResult.md +1 -1
- package/docs/fundamentals/node-tools/providence-analytics/analyzer.md +1 -1
- package/docs/fundamentals/node-tools/providence-analytics/dashboard.md +1 -1
- package/docs/fundamentals/node-tools/providence-analytics/overview.md +3 -3
- package/docs/fundamentals/node-tools/publish-docs/overview.md +3 -3
- package/docs/fundamentals/node-tools/rocket-preset-extend-lion-docs/overview.md +2 -2
- package/docs/fundamentals/systems/core/overview.md +1 -1
- package/docs/fundamentals/systems/form/formatting-and-parsing.md +4 -4
- package/docs/fundamentals/systems/form/model-value.md +1 -1
- package/docs/fundamentals/systems/form/overview.md +28 -28
- package/docs/fundamentals/systems/form/validate.md +1 -1
- package/docs/fundamentals/systems/localize/overview.md +4 -4
- package/docs/fundamentals/systems/overlays/assets/demo-el-using-overlaymixin.mjs +0 -16
- package/docs/fundamentals/systems/overlays/configuration.md +13 -25
- package/docs/fundamentals/systems/overlays/overview.md +5 -5
- package/docs/fundamentals/systems/overlays/use-cases.md +5 -5
- package/docs/fundamentals/tools/helpers/overview.md +1 -1
- package/docs/fundamentals/tools/singleton-manager/.gitignore +1 -0
- package/docs/fundamentals/tools/singleton-manager/example-complex/demo-app.js +93 -0
- package/docs/fundamentals/tools/singleton-manager/example-complex/node_modules/overlays/index.js +30 -0
- package/docs/fundamentals/tools/singleton-manager/example-complex/node_modules/overlays/instance.js +4 -0
- package/docs/fundamentals/tools/singleton-manager/example-complex/node_modules/page-a/page-a.js +35 -0
- package/docs/fundamentals/tools/singleton-manager/example-complex/node_modules/page-b/node_modules/overlays/index.js +30 -0
- package/docs/fundamentals/tools/singleton-manager/example-complex/node_modules/page-b/node_modules/overlays/instance.js +4 -0
- package/docs/fundamentals/tools/singleton-manager/example-complex/node_modules/page-b/page-b.js +49 -0
- package/docs/fundamentals/tools/singleton-manager/example-complex/overlayCompatibility.js +70 -0
- package/docs/fundamentals/tools/singleton-manager/example-fail/demo-app.js +91 -0
- package/docs/fundamentals/tools/singleton-manager/example-fail/node_modules/overlays/index.js +30 -0
- package/docs/fundamentals/tools/singleton-manager/example-fail/node_modules/overlays/instance.js +3 -0
- package/docs/fundamentals/tools/singleton-manager/example-fail/node_modules/page-a/page-a.js +34 -0
- package/docs/fundamentals/tools/singleton-manager/example-fail/node_modules/page-b/node_modules/overlays/index.js +30 -0
- package/docs/fundamentals/tools/singleton-manager/example-fail/node_modules/page-b/node_modules/overlays/instance.js +3 -0
- package/docs/fundamentals/tools/singleton-manager/example-fail/node_modules/page-b/page-b.js +34 -0
- package/docs/fundamentals/tools/singleton-manager/example-success/demo-app.js +93 -0
- package/docs/fundamentals/tools/singleton-manager/example-success/node_modules/overlays/index.js +30 -0
- package/docs/fundamentals/tools/singleton-manager/example-success/node_modules/overlays/instance.js +4 -0
- package/docs/fundamentals/tools/singleton-manager/example-success/node_modules/page-a/page-a.js +34 -0
- package/docs/fundamentals/tools/singleton-manager/example-success/node_modules/page-b/node_modules/overlays/index.js +30 -0
- package/docs/fundamentals/tools/singleton-manager/example-success/node_modules/page-b/node_modules/overlays/instance.js +4 -0
- package/docs/fundamentals/tools/singleton-manager/example-success/node_modules/page-b/page-b.js +34 -0
- package/docs/fundamentals/tools/singleton-manager/example-success/overlayCompatibility.js +23 -0
- package/docs/fundamentals/tools/singleton-manager/overview.md +4 -4
- package/docs/guides/how-to/create-a-custom-field.md +5 -5
- package/docs/guides/how-to/extend-a-native-input.md +2 -2
- package/docs/guides/index.md +8 -8
- package/docs/guides/principles/index.md +5 -5
- package/docs/guides/principles/styling.md +1 -1
- package/package.json +2 -2
- package/dist-types/components/overlays/test/utils-tests/local-positioning-helpers.d.ts.map +0 -1
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
// See: https://github.com/ing-bank/lion/issues/1880
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @typedef {import('lit').CSSResult|CSSStyleSheet} AdoptableStyle
|
|
5
|
+
* @typedef {(renderRoot:DocumentOrShadowRoot, style: AdoptableStyle, opts?: {teardown?: boolean}) => void} AdoptStyleFn
|
|
6
|
+
* @typedef {(renderRoot:DocumentOrShadowRoot, styles: AdoptableStyle[], opts?: {teardown?: boolean}) => void} AdoptStylesFn
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
// Shared protected object that can be spied/mocked in tests
|
|
10
|
+
export const _adoptStyleUtils = {
|
|
11
|
+
// Mocking Document.prototype.adoptedStyleSheets seemed impossible
|
|
12
|
+
supportsAdoptingStyleSheets:
|
|
13
|
+
window.ShadowRoot &&
|
|
14
|
+
// @ts-ignore
|
|
15
|
+
(window.ShadyCSS === undefined || window.ShadyCSS.nativeShadow) &&
|
|
16
|
+
'adoptedStyleSheets' in Document.prototype &&
|
|
17
|
+
'replace' in CSSStyleSheet.prototype,
|
|
18
|
+
/** @type {AdoptStyleFn} */
|
|
19
|
+
// @ts-ignore
|
|
20
|
+
adoptStyle: undefined,
|
|
21
|
+
/** @type {AdoptStylesFn} */
|
|
22
|
+
// @ts-ignore
|
|
23
|
+
adoptStyles: undefined,
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const styleCache = new Map();
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* @param {CSSStyleSheet} cssStyleSheet
|
|
30
|
+
*/
|
|
31
|
+
export function serializeConstructableStylesheet(cssStyleSheet) {
|
|
32
|
+
return Array.from(cssStyleSheet.cssRules)
|
|
33
|
+
.map(r => r.cssText)
|
|
34
|
+
.join('');
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @param {DocumentOrShadowRoot} renderRoot
|
|
39
|
+
* @param {AdoptableStyle} style
|
|
40
|
+
* @param {{teardown?: boolean}} opts
|
|
41
|
+
*/
|
|
42
|
+
function adoptStyleWhenAdoptedStylesheetsNotSupported(
|
|
43
|
+
renderRoot,
|
|
44
|
+
style,
|
|
45
|
+
{ teardown = false } = {},
|
|
46
|
+
) {
|
|
47
|
+
const adoptRoot = /** @type {ShadowRoot|Document['body']} */ (
|
|
48
|
+
renderRoot === document ? document.body : renderRoot
|
|
49
|
+
);
|
|
50
|
+
// @ts-ignore
|
|
51
|
+
const styleText = style.cssText || serializeConstructableStylesheet(style);
|
|
52
|
+
|
|
53
|
+
if (!teardown) {
|
|
54
|
+
const styleEl = document.createElement('style');
|
|
55
|
+
// keep notation, so it's not renamed in minification/build
|
|
56
|
+
// eslint-disable-next-line dot-notation
|
|
57
|
+
const nonce = window['litNonce'];
|
|
58
|
+
if (nonce !== undefined) {
|
|
59
|
+
styleEl.setAttribute('nonce', nonce);
|
|
60
|
+
}
|
|
61
|
+
styleEl.textContent = styleText;
|
|
62
|
+
adoptRoot.appendChild(styleEl);
|
|
63
|
+
} else {
|
|
64
|
+
const foundStyleEls = Array.from(adoptRoot.querySelectorAll('style'));
|
|
65
|
+
|
|
66
|
+
for (const foundStyleEl of foundStyleEls) {
|
|
67
|
+
if (foundStyleEl.textContent === styleText) {
|
|
68
|
+
foundStyleEl.remove();
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* @param {DocumentOrShadowRoot} renderRoot
|
|
77
|
+
* @param {AdoptableStyle} style
|
|
78
|
+
* @param {{teardown?: boolean}} opts
|
|
79
|
+
*/
|
|
80
|
+
function handleCache(renderRoot, style, { teardown = false } = {}) {
|
|
81
|
+
let haltFurtherExecution = false;
|
|
82
|
+
if (!styleCache.has(renderRoot)) {
|
|
83
|
+
styleCache.set(renderRoot, []);
|
|
84
|
+
}
|
|
85
|
+
const addedStylesForRoot = styleCache.get(renderRoot);
|
|
86
|
+
const foundStyle = addedStylesForRoot.find(
|
|
87
|
+
(/** @type {import("lit").CSSResultOrNative} */ addedStyle) => style === addedStyle,
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
if (foundStyle && teardown) {
|
|
91
|
+
addedStylesForRoot.splice(addedStylesForRoot.indexOf(style), 1);
|
|
92
|
+
} else if (!foundStyle && !teardown) {
|
|
93
|
+
addedStylesForRoot.push(style);
|
|
94
|
+
} else if ((foundStyle && !teardown) || (!foundStyle && teardown)) {
|
|
95
|
+
// Already removed or added. We're done
|
|
96
|
+
haltFurtherExecution = true;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return { haltFurtherExecution };
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/** @type {AdoptStyleFn} */
|
|
103
|
+
export function adoptStyle(renderRoot, style, { teardown = false } = {}) {
|
|
104
|
+
const { haltFurtherExecution } = handleCache(renderRoot, style, { teardown });
|
|
105
|
+
if (haltFurtherExecution) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (!_adoptStyleUtils.supportsAdoptingStyleSheets) {
|
|
110
|
+
adoptStyleWhenAdoptedStylesheetsNotSupported(renderRoot, style, { teardown });
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const sheet = style instanceof CSSStyleSheet ? style : style.styleSheet;
|
|
115
|
+
if (!sheet) {
|
|
116
|
+
throw new Error(`Please provide a CSSResultOrNative style`);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (!teardown) {
|
|
120
|
+
// @ts-ignore
|
|
121
|
+
// eslint-disable-next-line no-param-reassign
|
|
122
|
+
renderRoot.adoptedStyleSheets.push(sheet);
|
|
123
|
+
} else if (renderRoot.adoptedStyleSheets.includes(sheet)) {
|
|
124
|
+
renderRoot.adoptedStyleSheets.splice(renderRoot.adoptedStyleSheets.indexOf(sheet), 1);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/** @type {AdoptStylesFn} */
|
|
129
|
+
export function adoptStyles(renderRoot, styles, { teardown = false } = {}) {
|
|
130
|
+
for (const style of styles) {
|
|
131
|
+
_adoptStyleUtils.adoptStyle(renderRoot, style, { teardown });
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
_adoptStyleUtils.adoptStyle = adoptStyle;
|
|
136
|
+
_adoptStyleUtils.adoptStyles = adoptStyles;
|
|
@@ -11,9 +11,10 @@ import {
|
|
|
11
11
|
import sinon from 'sinon';
|
|
12
12
|
import { OverlayController, overlays } from '@lion/ui/overlays.js';
|
|
13
13
|
import { mimicClick } from '@lion/ui/overlays-test-helpers.js';
|
|
14
|
-
import { overlayShadowDomStyle } from '../src/overlayShadowDomStyle.js';
|
|
15
14
|
import { keyCodes } from '../src/utils/key-codes.js';
|
|
16
15
|
import { simulateTab } from '../src/utils/simulate-tab.js';
|
|
16
|
+
import { _adoptStyleUtils } from '../src/utils/adopt-styles.js';
|
|
17
|
+
import { createShadowHost } from '../test-helpers/createShadowHost.js';
|
|
17
18
|
|
|
18
19
|
/**
|
|
19
20
|
* @typedef {import('../types/OverlayConfig.js').OverlayConfig} OverlayConfig
|
|
@@ -22,20 +23,6 @@ import { simulateTab } from '../src/utils/simulate-tab.js';
|
|
|
22
23
|
|
|
23
24
|
const wrappingDialogNodeStyle = 'display: none; z-index: 9999;';
|
|
24
25
|
|
|
25
|
-
/**
|
|
26
|
-
* Returns element that adopts stylesheet
|
|
27
|
-
* @param {Element} shadowOrBodyEl
|
|
28
|
-
* @returns {ShadowRoot}
|
|
29
|
-
*/
|
|
30
|
-
function getRootNodeOrBodyElThatAdoptsStylesheet(shadowOrBodyEl) {
|
|
31
|
-
const rootNode = /** @type {* & DocumentOrShadowRoot} */ (shadowOrBodyEl.getRootNode());
|
|
32
|
-
if (rootNode === document) {
|
|
33
|
-
// @ts-ignore
|
|
34
|
-
return document.body;
|
|
35
|
-
}
|
|
36
|
-
return rootNode;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
26
|
/**
|
|
40
27
|
* Make sure that all browsers serialize html in a similar way
|
|
41
28
|
* (Firefox tends to output empty style attrs)
|
|
@@ -97,51 +84,17 @@ describe('OverlayController', () => {
|
|
|
97
84
|
});
|
|
98
85
|
|
|
99
86
|
describe('Stylesheets', () => {
|
|
100
|
-
it('
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
});
|
|
104
|
-
// @ts-ignore
|
|
105
|
-
if (document.body.adoptedStyleSheets) {
|
|
106
|
-
// @ts-ignore
|
|
107
|
-
expect(document.body.adoptedStyleSheets).to.include(overlayShadowDomStyle.styleSheet);
|
|
108
|
-
}
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
it('adds a stylesheet to the shadowRoot when contentWrappeNode is located there', async () => {
|
|
87
|
+
it('calls adoptStyles', async () => {
|
|
88
|
+
const spy = sinon.spy(_adoptStyleUtils, 'adoptStyle');
|
|
89
|
+
const { shadowHost, cleanupShadowHost } = createShadowHost();
|
|
112
90
|
const contentNode = /** @type {HTMLElement} */ (await fixture('<div>contentful</div>'));
|
|
113
|
-
const shadowHost = document.createElement('div');
|
|
114
|
-
shadowHost.attachShadow({ mode: 'open' });
|
|
115
|
-
/** @type {ShadowRoot} */ (shadowHost.shadowRoot).innerHTML = `<slot></slot>`;
|
|
116
91
|
shadowHost.appendChild(contentNode);
|
|
117
|
-
|
|
118
|
-
const ctrl = new OverlayController({
|
|
92
|
+
new OverlayController({
|
|
119
93
|
...withLocalTestConfig(),
|
|
120
94
|
contentNode,
|
|
121
95
|
});
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
expect(rootNodeOrBody).to.not.equal(document.body);
|
|
125
|
-
|
|
126
|
-
if (rootNodeOrBody.adoptedStyleSheets) {
|
|
127
|
-
expect(rootNodeOrBody.adoptedStyleSheets).to.include(overlayShadowDomStyle.styleSheet);
|
|
128
|
-
}
|
|
129
|
-
document.body.removeChild(shadowHost);
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
it('does not add same stylesheet twice', async () => {
|
|
133
|
-
// @ts-ignore
|
|
134
|
-
if (!document.body.adoptedStyleSheets) {
|
|
135
|
-
return;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
new OverlayController({ ...withLocalTestConfig() });
|
|
139
|
-
// @ts-ignore
|
|
140
|
-
const amountOfStylesheetsAfterOneInit = document.body.adoptedStyleSheets.length;
|
|
141
|
-
|
|
142
|
-
new OverlayController({ ...withLocalTestConfig() });
|
|
143
|
-
// @ts-ignore
|
|
144
|
-
expect(document.body.adoptedStyleSheets.length).to.equal(amountOfStylesheetsAfterOneInit);
|
|
96
|
+
expect(spy).to.have.been.called;
|
|
97
|
+
cleanupShadowHost();
|
|
145
98
|
});
|
|
146
99
|
});
|
|
147
100
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { expect, fixture, fixtureSync } from '@open-wc/testing';
|
|
3
3
|
import { html } from 'lit/static-html.js';
|
|
4
4
|
import { OverlayController } from '@lion/ui/overlays.js';
|
|
5
|
-
import { normalizeTransformStyle } from '
|
|
5
|
+
import { normalizeTransformStyle } from '../test-helpers/normalizeTransformStyle.js';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* @typedef {import('../types/OverlayConfig.js').OverlayConfig} OverlayConfig
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import { expect } from '@open-wc/testing';
|
|
2
|
+
import { css } from 'lit';
|
|
3
|
+
import sinon from 'sinon';
|
|
4
|
+
import {
|
|
5
|
+
adoptStyle,
|
|
6
|
+
adoptStyles,
|
|
7
|
+
serializeConstructableStylesheet,
|
|
8
|
+
_adoptStyleUtils,
|
|
9
|
+
} from '../../src/utils/adopt-styles.js';
|
|
10
|
+
import { createShadowHost } from '../../test-helpers/createShadowHost.js';
|
|
11
|
+
|
|
12
|
+
function mockNoSupportAdoptedStylesheets() {
|
|
13
|
+
_adoptStyleUtils.supportsAdoptingStyleSheets = false;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function restoreMockNoSupportAdoptedStylesheets() {
|
|
17
|
+
_adoptStyleUtils.supportsAdoptingStyleSheets = true;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
describe('adoptStyle()', () => {
|
|
21
|
+
it('adds a stylesheet from a CSSResult to the shadowRoot', async () => {
|
|
22
|
+
const { shadowHost, cleanupShadowHost } = createShadowHost();
|
|
23
|
+
const myCssResult = css``;
|
|
24
|
+
const root = /** @type {ShadowRoot} */ (shadowHost.shadowRoot);
|
|
25
|
+
|
|
26
|
+
adoptStyle(root, myCssResult);
|
|
27
|
+
expect(root.adoptedStyleSheets).to.include(myCssResult.styleSheet);
|
|
28
|
+
|
|
29
|
+
cleanupShadowHost();
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('adds a stylesheet from a CSSStyleSheet to the shadowRoot', async () => {
|
|
33
|
+
const { shadowHost, cleanupShadowHost } = createShadowHost();
|
|
34
|
+
const myCSSStyleSheet = new CSSStyleSheet();
|
|
35
|
+
const root = /** @type {ShadowRoot} */ (shadowHost.shadowRoot);
|
|
36
|
+
|
|
37
|
+
adoptStyle(root, myCSSStyleSheet);
|
|
38
|
+
expect(root.adoptedStyleSheets).to.include(myCSSStyleSheet);
|
|
39
|
+
|
|
40
|
+
cleanupShadowHost();
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('does not add same stylesheet twice', async () => {
|
|
44
|
+
const { shadowHost, cleanupShadowHost } = createShadowHost();
|
|
45
|
+
const myCssResult = css``;
|
|
46
|
+
const root = /** @type {ShadowRoot} */ (shadowHost.shadowRoot);
|
|
47
|
+
|
|
48
|
+
adoptStyle(root, myCssResult);
|
|
49
|
+
const amountOfStylesheetsAfterOneInit = root.adoptedStyleSheets.length;
|
|
50
|
+
adoptStyle(root, myCssResult);
|
|
51
|
+
expect(root.adoptedStyleSheets.length).to.equal(amountOfStylesheetsAfterOneInit);
|
|
52
|
+
|
|
53
|
+
cleanupShadowHost();
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it('works as well when document is the root', async () => {
|
|
57
|
+
const myCssResult = css``;
|
|
58
|
+
const root = document;
|
|
59
|
+
|
|
60
|
+
adoptStyle(root, myCssResult);
|
|
61
|
+
expect(root.adoptedStyleSheets).to.include(myCssResult.styleSheet);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
describe('Teardown', () => {
|
|
65
|
+
it('removes stylesheets from the shadowRoot', async () => {
|
|
66
|
+
const { shadowHost, cleanupShadowHost } = createShadowHost();
|
|
67
|
+
const myCssResult = css``;
|
|
68
|
+
const root = /** @type {ShadowRoot} */ (shadowHost.shadowRoot);
|
|
69
|
+
|
|
70
|
+
adoptStyle(root, myCssResult);
|
|
71
|
+
expect(root.adoptedStyleSheets).to.include(myCssResult.styleSheet);
|
|
72
|
+
adoptStyle(root, myCssResult, { teardown: true });
|
|
73
|
+
expect(root.adoptedStyleSheets).to.not.include(myCssResult.styleSheet);
|
|
74
|
+
|
|
75
|
+
const myCSSStyleSheet = new CSSStyleSheet();
|
|
76
|
+
adoptStyle(root, myCSSStyleSheet);
|
|
77
|
+
expect(root.adoptedStyleSheets).to.include(myCSSStyleSheet);
|
|
78
|
+
adoptStyle(root, myCSSStyleSheet, { teardown: true });
|
|
79
|
+
expect(root.adoptedStyleSheets).to.not.include(myCSSStyleSheet);
|
|
80
|
+
|
|
81
|
+
cleanupShadowHost();
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
describe('Fallback when adoptedStyleSheets are not supported', () => {
|
|
86
|
+
beforeEach(() => {
|
|
87
|
+
mockNoSupportAdoptedStylesheets();
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
afterEach(() => {
|
|
91
|
+
restoreMockNoSupportAdoptedStylesheets();
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it('adds a "traditional" stylesheet to the shadowRoot', async () => {
|
|
95
|
+
const { shadowHost, cleanupShadowHost } = createShadowHost();
|
|
96
|
+
const myCssResult = css`
|
|
97
|
+
.check {
|
|
98
|
+
color: blue;
|
|
99
|
+
}
|
|
100
|
+
`;
|
|
101
|
+
const root = /** @type {ShadowRoot} */ (shadowHost.shadowRoot);
|
|
102
|
+
|
|
103
|
+
adoptStyle(root, myCssResult);
|
|
104
|
+
const sheets = Array.from(root.querySelectorAll('style'));
|
|
105
|
+
const lastAddedSheet = sheets[sheets.length - 1];
|
|
106
|
+
expect(lastAddedSheet.textContent).to.equal(myCssResult.cssText);
|
|
107
|
+
|
|
108
|
+
cleanupShadowHost();
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it('adds a "traditional" stylesheet to the body', async () => {
|
|
112
|
+
mockNoSupportAdoptedStylesheets();
|
|
113
|
+
|
|
114
|
+
const myCssResult = css`
|
|
115
|
+
.check {
|
|
116
|
+
color: blue;
|
|
117
|
+
}
|
|
118
|
+
`;
|
|
119
|
+
const root = document;
|
|
120
|
+
adoptStyle(root, myCssResult);
|
|
121
|
+
|
|
122
|
+
const sheets = Array.from(document.body.querySelectorAll('style'));
|
|
123
|
+
const lastAddedSheet = sheets[sheets.length - 1];
|
|
124
|
+
expect(lastAddedSheet.textContent).to.equal(myCssResult.cssText);
|
|
125
|
+
restoreMockNoSupportAdoptedStylesheets();
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
describe('Teardown', () => {
|
|
129
|
+
it('removes a "traditional" stylesheet from the shadowRoot', async () => {
|
|
130
|
+
const { shadowHost, cleanupShadowHost } = createShadowHost();
|
|
131
|
+
const myCssResult = css`
|
|
132
|
+
.check {
|
|
133
|
+
color: blue;
|
|
134
|
+
}
|
|
135
|
+
`;
|
|
136
|
+
const root = /** @type {ShadowRoot} */ (shadowHost.shadowRoot);
|
|
137
|
+
|
|
138
|
+
adoptStyle(root, myCssResult);
|
|
139
|
+
const sheets1 = Array.from(root.querySelectorAll('style'));
|
|
140
|
+
const lastAddedSheet1 = sheets1[sheets1.length - 1];
|
|
141
|
+
expect(lastAddedSheet1.textContent).to.equal(myCssResult.cssText);
|
|
142
|
+
adoptStyle(root, myCssResult, { teardown: true });
|
|
143
|
+
const sheets2 = Array.from(root.querySelectorAll('style'));
|
|
144
|
+
const lastAddedSheet2 = sheets2[sheets2.length - 1];
|
|
145
|
+
expect(lastAddedSheet2?.textContent).to.not.equal(myCssResult.cssText);
|
|
146
|
+
|
|
147
|
+
const myCSSStyleSheet = new CSSStyleSheet();
|
|
148
|
+
myCSSStyleSheet.insertRule('.check { color: blue; }');
|
|
149
|
+
|
|
150
|
+
adoptStyle(root, myCSSStyleSheet);
|
|
151
|
+
const sheets3 = Array.from(root.querySelectorAll('style'));
|
|
152
|
+
const lastAddedSheet3 = sheets3[sheets3.length - 1];
|
|
153
|
+
expect(lastAddedSheet3.textContent).to.equal(
|
|
154
|
+
serializeConstructableStylesheet(myCSSStyleSheet),
|
|
155
|
+
);
|
|
156
|
+
adoptStyle(root, myCSSStyleSheet, { teardown: true });
|
|
157
|
+
const sheets4 = Array.from(root.querySelectorAll('style'));
|
|
158
|
+
const lastAddedSheet4 = sheets4[sheets4.length - 1];
|
|
159
|
+
expect(lastAddedSheet4?.textContent).to.not.equal(myCSSStyleSheet);
|
|
160
|
+
|
|
161
|
+
cleanupShadowHost();
|
|
162
|
+
});
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
describe('adoptStyles()', () => {
|
|
168
|
+
it('calls "adoptStyle" for all entries in CSSResult|CSSStylesheet[]', async () => {
|
|
169
|
+
const spy = sinon.spy(_adoptStyleUtils, 'adoptStyle');
|
|
170
|
+
|
|
171
|
+
const myCssResult = css``;
|
|
172
|
+
const myCSSStyleSheet = new CSSStyleSheet();
|
|
173
|
+
|
|
174
|
+
adoptStyles(document, [myCssResult, myCSSStyleSheet]);
|
|
175
|
+
expect(spy).to.have.been.calledTwice;
|
|
176
|
+
});
|
|
177
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Useful in tests when no need for wc
|
|
3
|
+
*/
|
|
4
|
+
export function createShadowHost() {
|
|
5
|
+
const shadowHost = document.createElement('div');
|
|
6
|
+
shadowHost.attachShadow({ mode: 'open' });
|
|
7
|
+
/** @type {ShadowRoot} */ (shadowHost.shadowRoot).innerHTML = `<slot></slot>`;
|
|
8
|
+
document.body.appendChild(shadowHost);
|
|
9
|
+
|
|
10
|
+
return {
|
|
11
|
+
shadowHost,
|
|
12
|
+
cleanupShadowHost: () => {
|
|
13
|
+
document.body.removeChild(shadowHost);
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
}
|
|
File without changes
|
|
@@ -67,14 +67,11 @@ export class LionSelectRich extends SlotMixin(ScopedElementsMixin(OverlayMixin(L
|
|
|
67
67
|
`;
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
+
/** @type {SlotsMap} */
|
|
70
71
|
get slots() {
|
|
71
72
|
return {
|
|
72
73
|
...super.slots,
|
|
73
|
-
invoker: () =>
|
|
74
|
-
const invokerEl = this.createScopedElement('lion-select-invoker');
|
|
75
|
-
invokerEl.setAttribute('data-tag-name', 'lion-select-invoker');
|
|
76
|
-
return invokerEl;
|
|
77
|
-
},
|
|
74
|
+
invoker: () => html`<lion-select-invoker></lion-select-invoker>`,
|
|
78
75
|
};
|
|
79
76
|
}
|
|
80
77
|
|
|
@@ -88,6 +85,15 @@ export class LionSelectRich extends SlotMixin(ScopedElementsMixin(OverlayMixin(L
|
|
|
88
85
|
);
|
|
89
86
|
}
|
|
90
87
|
|
|
88
|
+
/**
|
|
89
|
+
* @protected
|
|
90
|
+
* @configure FocusMixin
|
|
91
|
+
*/
|
|
92
|
+
// @ts-ignore
|
|
93
|
+
get _focusableNode() {
|
|
94
|
+
return this._invokerNode;
|
|
95
|
+
}
|
|
96
|
+
|
|
91
97
|
/**
|
|
92
98
|
* @configure ListboxMixin
|
|
93
99
|
* @protected
|
|
@@ -262,7 +268,7 @@ export class LionSelectRich extends SlotMixin(ScopedElementsMixin(OverlayMixin(L
|
|
|
262
268
|
|
|
263
269
|
/** @protected */
|
|
264
270
|
_onFormElementsChanged() {
|
|
265
|
-
this.singleOption = this.formElements.length === 1;
|
|
271
|
+
this.singleOption = this.formElements.length === 1 && !this.hasNoDefaultSelected;
|
|
266
272
|
this._invokerNode.singleOption = this.singleOption;
|
|
267
273
|
}
|
|
268
274
|
|
|
@@ -49,10 +49,21 @@ describe('lion-select-rich', () => {
|
|
|
49
49
|
expect(document.activeElement === document.body).to.be.true;
|
|
50
50
|
const { _labelNode, _invokerNode } = getSelectRichMembers(el);
|
|
51
51
|
_labelNode.click();
|
|
52
|
-
|
|
53
52
|
expect(document.activeElement === _invokerNode).to.be.true;
|
|
54
53
|
});
|
|
55
54
|
|
|
55
|
+
it('has an attribute focused when focused', async () => {
|
|
56
|
+
const el = await fixture(html` <lion-select-rich label="foo"> </lion-select-rich> `);
|
|
57
|
+
|
|
58
|
+
el.focus();
|
|
59
|
+
await el.updateComplete;
|
|
60
|
+
expect(el.hasAttribute('focused')).to.be.true;
|
|
61
|
+
|
|
62
|
+
el.blur();
|
|
63
|
+
await el.updateComplete;
|
|
64
|
+
expect(el.hasAttribute('focused')).to.be.false;
|
|
65
|
+
});
|
|
66
|
+
|
|
56
67
|
it('checks the first enabled option', async () => {
|
|
57
68
|
const el = await fixture(html`
|
|
58
69
|
<lion-select-rich>
|
|
@@ -400,6 +411,19 @@ describe('lion-select-rich', () => {
|
|
|
400
411
|
expect(el.singleOption).to.be.false;
|
|
401
412
|
expect(_invokerNode.singleOption).to.be.false;
|
|
402
413
|
});
|
|
414
|
+
|
|
415
|
+
it('should have singleOption only if one option and no hasNoDefaultSelected', async () => {
|
|
416
|
+
const el = await fixture(html`
|
|
417
|
+
<lion-select-rich has-no-default-selected>
|
|
418
|
+
<lion-option .choiceValue=${10}>Item 1</lion-option>
|
|
419
|
+
</lion-select-rich>
|
|
420
|
+
`);
|
|
421
|
+
|
|
422
|
+
const { _invokerNode } = getSelectRichMembers(el);
|
|
423
|
+
|
|
424
|
+
expect(el.singleOption).to.be.false;
|
|
425
|
+
expect(_invokerNode.singleOption).to.be.false;
|
|
426
|
+
});
|
|
403
427
|
});
|
|
404
428
|
|
|
405
429
|
describe('interaction-mode', () => {
|