@lion/ui 0.14.1 → 0.14.3
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/dialog/test/lion-dialog.test.js +114 -1
- package/components/overlays/src/OverlayMixin.js +12 -5
- package/components/overlays/test/OverlayController.test.js +2 -0
- package/components/overlays/test-suites/OverlayMixin.suite.js +4 -1
- package/components/select-rich/src/LionSelectRich.js +4 -2
- package/components/select-rich/test/lion-select-rich.test.js +376 -1
- package/custom-elements.json +30 -30
- package/dist-types/components/dialog/test/lion-dialog.test.d.ts.map +1 -1
- package/dist-types/components/overlays/src/OverlayMixin.d.ts.map +1 -1
- package/dist-types/components/overlays/test-suites/OverlayMixin.suite.d.ts.map +1 -1
- package/dist-types/components/select-rich/src/LionSelectRich.d.ts.map +1 -1
- package/dist-types/components/select-rich/test/lion-select-rich.test.d.ts.map +1 -1
- package/dist-types/tsconfig.tsbuildinfo +1 -1
- 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/use-cases.md +1 -1
- package/docs/components/dialog/overview.md +1 -1
- package/docs/components/fieldset/overview.md +5 -5
- package/docs/components/form/overview.md +3 -3
- package/docs/components/form/use-cases.md +2 -2
- 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-file/overview.md +1 -1
- 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/listbox/use-cases.md +1 -1
- package/docs/components/radio-group/overview.md +3 -3
- package/docs/components/select/use-cases.md +1 -1
- package/docs/components/select-rich/use-cases.md +16 -2
- package/docs/components/tabs/examples.md +1 -1
- package/docs/fundamentals/index.md +4 -4
- 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/rationales/accessibility.md +1 -1
- package/docs/fundamentals/systems/core/SlotMixin.md +1 -1
- 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 +2 -2
- package/docs/fundamentals/systems/localize/overview.md +4 -4
- package/docs/fundamentals/systems/overlays/configuration.md +2 -2
- package/docs/fundamentals/systems/overlays/overview.md +5 -5
- package/docs/fundamentals/systems/overlays/use-cases.md +2 -2
- package/docs/fundamentals/tools/helpers/overview.md +1 -1
- 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/create-a-form.md +4 -4
- 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 +1 -1
|
@@ -1,9 +1,20 @@
|
|
|
1
1
|
/* eslint-disable lit-a11y/no-autofocus */
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
expect,
|
|
4
|
+
fixture as _fixture,
|
|
5
|
+
html,
|
|
6
|
+
unsafeStatic,
|
|
7
|
+
aTimeout,
|
|
8
|
+
defineCE,
|
|
9
|
+
waitUntil,
|
|
10
|
+
} from '@open-wc/testing';
|
|
11
|
+
import { cache } from 'lit/directives/cache.js';
|
|
12
|
+
import { LitElement, nothing } from 'lit';
|
|
3
13
|
import { runOverlayMixinSuite } from '../../overlays/test-suites/OverlayMixin.suite.js';
|
|
4
14
|
import { isActiveElement } from '../../core/test-helpers/isActiveElement.js';
|
|
5
15
|
import '../test-helpers/test-router.js';
|
|
6
16
|
import '@lion/ui/define/lion-dialog.js';
|
|
17
|
+
import '@lion/ui/define/lion-tabs.js';
|
|
7
18
|
|
|
8
19
|
/**
|
|
9
20
|
* @typedef {import('../src/LionDialog.js').LionDialog} LionDialog
|
|
@@ -296,5 +307,107 @@ describe('lion-dialog', () => {
|
|
|
296
307
|
await dialogAfterRouteChange._overlayCtrl._showComplete;
|
|
297
308
|
expect(dialogAfterRouteChange.opened).to.be.true;
|
|
298
309
|
});
|
|
310
|
+
|
|
311
|
+
it('should close the popup dialog after rendered from cache', async () => {
|
|
312
|
+
/**
|
|
313
|
+
*
|
|
314
|
+
* @param {Event} e
|
|
315
|
+
* @returns
|
|
316
|
+
*/
|
|
317
|
+
const closeButtonHandler = e =>
|
|
318
|
+
e.target?.dispatchEvent(new Event('close-overlay', { bubbles: true }));
|
|
319
|
+
const dialog = html` <lion-dialog>
|
|
320
|
+
<button slot="invoker" class="invoker-button">Click me to open dialog</button>
|
|
321
|
+
<div slot="content" class="demo-dialog-content">
|
|
322
|
+
Hello! You can close this dialog here:
|
|
323
|
+
<button class="close-button" @click="${closeButtonHandler}">⨯</button>
|
|
324
|
+
</div>
|
|
325
|
+
</lion-dialog>`;
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* Note, inactive tab content is **destroyed** on every tab switch.
|
|
329
|
+
*/
|
|
330
|
+
class Wrapper extends LitElement {
|
|
331
|
+
static properties = {
|
|
332
|
+
...super.properties,
|
|
333
|
+
activeTabIndex: { type: Number },
|
|
334
|
+
};
|
|
335
|
+
|
|
336
|
+
constructor() {
|
|
337
|
+
super();
|
|
338
|
+
this.activeTabIndex = 0;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* @param {number} index
|
|
343
|
+
*/
|
|
344
|
+
changeActiveTabIndex(index) {
|
|
345
|
+
this.activeTabIndex = index;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
render() {
|
|
349
|
+
const changeActiveTabIndexRef = this.changeActiveTabIndex.bind(this);
|
|
350
|
+
return html`
|
|
351
|
+
<lion-tabs>
|
|
352
|
+
<button slot="tab" class="first-button" @click=${() => changeActiveTabIndexRef(0)}>
|
|
353
|
+
First
|
|
354
|
+
</button>
|
|
355
|
+
<p slot="panel">${cache(this.activeTabIndex === 0 ? dialog : nothing)}</p>
|
|
356
|
+
<button slot="tab" class="second-button" @click=${() => changeActiveTabIndexRef(1)}>
|
|
357
|
+
Second
|
|
358
|
+
</button>
|
|
359
|
+
<p slot="panel">Info page with lots of information about us.</p>
|
|
360
|
+
</lion-tabs>
|
|
361
|
+
`;
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
const wrapperFixture = /** @type {(arg: TemplateResult) => Promise<Wrapper>} */ (_fixture);
|
|
366
|
+
const tagString = defineCE(Wrapper);
|
|
367
|
+
const wrapperTag = unsafeStatic(tagString);
|
|
368
|
+
const wrapperElement = /** @type {Wrapper} */ (
|
|
369
|
+
await wrapperFixture(html`<${wrapperTag}></${wrapperTag}>`)
|
|
370
|
+
);
|
|
371
|
+
await wrapperElement.updateComplete;
|
|
372
|
+
const wrapperElementShadowRoot = wrapperElement.shadowRoot;
|
|
373
|
+
/**
|
|
374
|
+
* @returns { HTMLElement | null | undefined }
|
|
375
|
+
*/
|
|
376
|
+
const getFirstButton = () => wrapperElementShadowRoot?.querySelector('.first-button');
|
|
377
|
+
/**
|
|
378
|
+
* @returns { HTMLElement | null | undefined }
|
|
379
|
+
*/
|
|
380
|
+
const getSecondButton = () => wrapperElementShadowRoot?.querySelector('.second-button');
|
|
381
|
+
/**
|
|
382
|
+
* @returns { HTMLElement | null | undefined }
|
|
383
|
+
*/
|
|
384
|
+
const getInvokerButton = () => wrapperElementShadowRoot?.querySelector('.invoker-button');
|
|
385
|
+
/**
|
|
386
|
+
* @returns { HTMLElement | null | undefined }
|
|
387
|
+
*/
|
|
388
|
+
const getCloseButton = () => wrapperElementShadowRoot?.querySelector('.close-button');
|
|
389
|
+
/**
|
|
390
|
+
* @returns { Element | null | undefined }
|
|
391
|
+
*/
|
|
392
|
+
const getDialog = () =>
|
|
393
|
+
wrapperElementShadowRoot?.querySelector('lion-dialog')?.shadowRoot?.querySelector('dialog');
|
|
394
|
+
// @ts-ignore
|
|
395
|
+
const isDialogVisible = () => getDialog()?.checkVisibility() === true;
|
|
396
|
+
const isDialogRendered = () =>
|
|
397
|
+
!!wrapperElement.shadowRoot?.querySelector('lion-dialog')?.shadowRoot?.childNodes.length;
|
|
398
|
+
getInvokerButton()?.click();
|
|
399
|
+
await waitUntil(isDialogVisible);
|
|
400
|
+
getCloseButton()?.click();
|
|
401
|
+
await waitUntil(() => !isDialogVisible());
|
|
402
|
+
getSecondButton()?.click();
|
|
403
|
+
await waitUntil(() => !isDialogRendered());
|
|
404
|
+
getFirstButton()?.click();
|
|
405
|
+
await waitUntil(isDialogRendered);
|
|
406
|
+
getInvokerButton()?.click();
|
|
407
|
+
await waitUntil(isDialogVisible);
|
|
408
|
+
getCloseButton()?.click();
|
|
409
|
+
await waitUntil(() => !isDialogVisible());
|
|
410
|
+
expect(isDialogVisible()).to.equal(false);
|
|
411
|
+
});
|
|
299
412
|
});
|
|
300
413
|
});
|
|
@@ -246,16 +246,23 @@ export const OverlayMixinImplementation = superclass =>
|
|
|
246
246
|
|
|
247
247
|
/** @protected */
|
|
248
248
|
_setupOverlayCtrl() {
|
|
249
|
-
if (this
|
|
250
|
-
|
|
251
|
-
/** @type {OverlayController} */
|
|
252
|
-
this._overlayCtrl = this._defineOverlay({
|
|
249
|
+
if (this.#hasSetup) return;
|
|
250
|
+
const config = {
|
|
253
251
|
contentNode: this._overlayContentNode,
|
|
254
252
|
contentWrapperNode: this._overlayContentWrapperNode,
|
|
255
253
|
invokerNode: this._overlayInvokerNode,
|
|
256
254
|
referenceNode: this._overlayReferenceNode,
|
|
257
255
|
backdropNode: this._overlayBackdropNode,
|
|
258
|
-
}
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
if (this._overlayCtrl) {
|
|
259
|
+
// when `lit` `cache` attaches node to the DOM, register the controller back in the OverlaysManager
|
|
260
|
+
this._overlayCtrl.updateConfig(config);
|
|
261
|
+
} else {
|
|
262
|
+
/** @type {OverlayController} */
|
|
263
|
+
this._overlayCtrl = this._defineOverlay(config);
|
|
264
|
+
}
|
|
265
|
+
|
|
259
266
|
this.__syncToOverlayController();
|
|
260
267
|
this.__setupSyncFromOverlayController();
|
|
261
268
|
this._setupOpenCloseListeners();
|
|
@@ -153,6 +153,8 @@ async function createNestedEscControllers(parentContent) {
|
|
|
153
153
|
|
|
154
154
|
afterEach(() => {
|
|
155
155
|
overlays.teardown();
|
|
156
|
+
// clean document.body from the DOM nodes left by previous tests
|
|
157
|
+
document.body.innerHTML = '';
|
|
156
158
|
});
|
|
157
159
|
|
|
158
160
|
describe('OverlayController', () => {
|
|
@@ -533,8 +533,11 @@ export function runOverlayMixinSuite({ tagString, tag, suffix = '' }) {
|
|
|
533
533
|
|
|
534
534
|
el.switched = false;
|
|
535
535
|
await el.updateComplete;
|
|
536
|
-
|
|
537
536
|
expect(setupSpy.callCount).to.equal(1);
|
|
537
|
+
|
|
538
|
+
const elCtrl = /** @type {OverlayEl} */ (el.overlayEl)?._overlayCtrl;
|
|
539
|
+
const isCtrlRegisteredAtOverlaysManager = elCtrl.manager.list.some(ctrl => elCtrl === ctrl);
|
|
540
|
+
expect(isCtrlRegisteredAtOverlaysManager).to.equal(true);
|
|
538
541
|
});
|
|
539
542
|
|
|
540
543
|
it('correctly removes event listeners when disconnected from dom', async () => {
|
|
@@ -146,8 +146,10 @@ export class LionSelectRich extends SlotMixin(ScopedElementsMixin(OverlayMixin(L
|
|
|
146
146
|
|
|
147
147
|
connectedCallback() {
|
|
148
148
|
super.connectedCallback();
|
|
149
|
-
this.
|
|
150
|
-
this.
|
|
149
|
+
this.registrationComplete.then(() => {
|
|
150
|
+
this._invokerNode.selectedElement =
|
|
151
|
+
this.formElements[/** @type {number} */ (this.checkedIndex)];
|
|
152
|
+
});
|
|
151
153
|
|
|
152
154
|
this._invokerNode.hostElement = this;
|
|
153
155
|
|
|
@@ -6,7 +6,8 @@ import { LionOption } from '@lion/ui/listbox.js';
|
|
|
6
6
|
import '@lion/ui/define/lion-select-rich.js';
|
|
7
7
|
import '@lion/ui/define/lion-listbox.js';
|
|
8
8
|
import '@lion/ui/define/lion-option.js';
|
|
9
|
-
import
|
|
9
|
+
import '@lion/ui/define/lion-tabs.js';
|
|
10
|
+
import { LitElement, nothing } from 'lit';
|
|
10
11
|
import sinon from 'sinon';
|
|
11
12
|
import {
|
|
12
13
|
fixture as _fixture,
|
|
@@ -16,7 +17,9 @@ import {
|
|
|
16
17
|
defineCE,
|
|
17
18
|
expect,
|
|
18
19
|
html,
|
|
20
|
+
waitUntil,
|
|
19
21
|
} from '@open-wc/testing';
|
|
22
|
+
import { cache } from 'lit/directives/cache.js';
|
|
20
23
|
|
|
21
24
|
import { isActiveElement } from '../../core/test-helpers/isActiveElement.js';
|
|
22
25
|
|
|
@@ -724,6 +727,378 @@ describe('lion-select-rich', () => {
|
|
|
724
727
|
});
|
|
725
728
|
});
|
|
726
729
|
|
|
730
|
+
describe('Render from `lit` `cache`', () => {
|
|
731
|
+
describe('when `lion-option` is set by `.choiceValue` property with and no `checked` attribute', () => {
|
|
732
|
+
it('should display the second option', async () => {
|
|
733
|
+
const colours = [
|
|
734
|
+
{
|
|
735
|
+
label: 'Red',
|
|
736
|
+
value: 'red',
|
|
737
|
+
},
|
|
738
|
+
{
|
|
739
|
+
label: 'Blue',
|
|
740
|
+
value: 'blue',
|
|
741
|
+
},
|
|
742
|
+
];
|
|
743
|
+
|
|
744
|
+
/**
|
|
745
|
+
* Note, inactive tab content is **destroyed** on every tab switch.
|
|
746
|
+
*/
|
|
747
|
+
class Wrapper extends LitElement {
|
|
748
|
+
static properties = {
|
|
749
|
+
...super.properties,
|
|
750
|
+
activeTabIndex: { type: Number },
|
|
751
|
+
};
|
|
752
|
+
|
|
753
|
+
constructor() {
|
|
754
|
+
super();
|
|
755
|
+
this.activeTabIndex = 0;
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
/**
|
|
759
|
+
* @param {number} index
|
|
760
|
+
*/
|
|
761
|
+
changeActiveTabIndex(index) {
|
|
762
|
+
this.activeTabIndex = index;
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
render() {
|
|
766
|
+
const changeActiveTabIndexRef = this.changeActiveTabIndex.bind(this);
|
|
767
|
+
return html`
|
|
768
|
+
<lion-tabs>
|
|
769
|
+
<button slot="tab" class="first-button" @click=${() => changeActiveTabIndexRef(0)}>
|
|
770
|
+
Info
|
|
771
|
+
</button>
|
|
772
|
+
<p slot="panel">
|
|
773
|
+
${cache(
|
|
774
|
+
this.activeTabIndex === 0
|
|
775
|
+
? html`<lion-select-rich name="favoriteColor" label="Favorite color">
|
|
776
|
+
${colours.map(
|
|
777
|
+
colour =>
|
|
778
|
+
html`<lion-option .choiceValue="${colour.value}"
|
|
779
|
+
>${colour.label}</lion-option
|
|
780
|
+
>`,
|
|
781
|
+
)}
|
|
782
|
+
</lion-select-rich>`
|
|
783
|
+
: nothing,
|
|
784
|
+
)}
|
|
785
|
+
</p>
|
|
786
|
+
<button slot="tab" class="second-button" @click=${() => changeActiveTabIndexRef(1)}>
|
|
787
|
+
Work
|
|
788
|
+
</button>
|
|
789
|
+
<p slot="panel">Info page with lots of information about us.</p>
|
|
790
|
+
</lion-tabs>
|
|
791
|
+
`;
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
const wrapperFixture = /** @type {(arg: TemplateResult) => Promise<Wrapper>} */ (_fixture);
|
|
796
|
+
const tagString = defineCE(Wrapper);
|
|
797
|
+
const wrapperTag = unsafeStatic(tagString);
|
|
798
|
+
const wrapperElement = /** @type {Wrapper} */ (
|
|
799
|
+
await wrapperFixture(html`<${wrapperTag}></${wrapperTag}>`)
|
|
800
|
+
);
|
|
801
|
+
await wrapperElement.updateComplete;
|
|
802
|
+
const wrapperElementShadowRoot = wrapperElement.shadowRoot;
|
|
803
|
+
/**
|
|
804
|
+
* @returns { HTMLElement | null | undefined }
|
|
805
|
+
*/
|
|
806
|
+
const getFirstButton = () => wrapperElementShadowRoot?.querySelector('.first-button');
|
|
807
|
+
/**
|
|
808
|
+
* @returns { HTMLElement | null | undefined }
|
|
809
|
+
*/
|
|
810
|
+
const getSecondButton = () => wrapperElementShadowRoot?.querySelector('.second-button');
|
|
811
|
+
/**
|
|
812
|
+
* @returns { HTMLElement | null | undefined }
|
|
813
|
+
*/
|
|
814
|
+
const getInvoker = () => wrapperElementShadowRoot?.querySelector('lion-select-invoker');
|
|
815
|
+
/**
|
|
816
|
+
* @returns { boolean }
|
|
817
|
+
*/
|
|
818
|
+
const isSelectRichRendered = () => !!getInvoker()?.shadowRoot?.childNodes.length;
|
|
819
|
+
/**
|
|
820
|
+
* @returns { string | undefined }
|
|
821
|
+
*/
|
|
822
|
+
const getSelectedColourLabel = () =>
|
|
823
|
+
getInvoker()?.shadowRoot?.querySelector('#content-wrapper')?.textContent?.trim();
|
|
824
|
+
const getDialog = () =>
|
|
825
|
+
wrapperElementShadowRoot
|
|
826
|
+
?.querySelector('lion-select-rich')
|
|
827
|
+
?.shadowRoot?.querySelector('dialog');
|
|
828
|
+
const isDialogVisible = () =>
|
|
829
|
+
// @ts-ignore
|
|
830
|
+
getDialog()?.checkVisibility() === true &&
|
|
831
|
+
getDialog()?.querySelector('#overlay-content-node-wrapper[data-popper-placement]');
|
|
832
|
+
await waitUntil(isSelectRichRendered);
|
|
833
|
+
getInvoker()?.click();
|
|
834
|
+
await waitUntil(isDialogVisible);
|
|
835
|
+
const optionBlue = /** @type { HTMLElement | undefined } */ (
|
|
836
|
+
wrapperElementShadowRoot?.querySelectorAll('lion-option')
|
|
837
|
+
)?.[1];
|
|
838
|
+
optionBlue?.click();
|
|
839
|
+
await waitUntil(() => !isDialogVisible());
|
|
840
|
+
const selectedColourLabelBeforeTabSwitch = getSelectedColourLabel();
|
|
841
|
+
expect(selectedColourLabelBeforeTabSwitch).to.equal('Blue');
|
|
842
|
+
getSecondButton()?.click();
|
|
843
|
+
await waitUntil(() => !isSelectRichRendered());
|
|
844
|
+
getFirstButton()?.click();
|
|
845
|
+
await waitUntil(isSelectRichRendered);
|
|
846
|
+
const selectedColourAfterTabSwitch = getSelectedColourLabel();
|
|
847
|
+
expect(selectedColourAfterTabSwitch).to.equal('Blue');
|
|
848
|
+
});
|
|
849
|
+
});
|
|
850
|
+
describe('when `lion-option` is set by `.choiceValue` property and `checked` attribute', () => {
|
|
851
|
+
it('should display the second option', async () => {
|
|
852
|
+
const colours = [
|
|
853
|
+
{
|
|
854
|
+
label: 'Red',
|
|
855
|
+
value: 'red',
|
|
856
|
+
checked: true,
|
|
857
|
+
},
|
|
858
|
+
{
|
|
859
|
+
label: 'Blue',
|
|
860
|
+
value: 'blue',
|
|
861
|
+
checked: false,
|
|
862
|
+
},
|
|
863
|
+
];
|
|
864
|
+
|
|
865
|
+
/**
|
|
866
|
+
* Note, inactive tab content is **destroyed** on every tab switch.
|
|
867
|
+
*/
|
|
868
|
+
class Wrapper extends LitElement {
|
|
869
|
+
static properties = {
|
|
870
|
+
...super.properties,
|
|
871
|
+
activeTabIndex: { type: Number },
|
|
872
|
+
};
|
|
873
|
+
|
|
874
|
+
constructor() {
|
|
875
|
+
super();
|
|
876
|
+
this.activeTabIndex = 0;
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
/**
|
|
880
|
+
* @param {number} index
|
|
881
|
+
*/
|
|
882
|
+
changeActiveTabIndex(index) {
|
|
883
|
+
this.activeTabIndex = index;
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
render() {
|
|
887
|
+
const changeActiveTabIndexRef = this.changeActiveTabIndex.bind(this);
|
|
888
|
+
return html`
|
|
889
|
+
<lion-tabs>
|
|
890
|
+
<button slot="tab" class="first-button" @click=${() => changeActiveTabIndexRef(0)}>
|
|
891
|
+
Info
|
|
892
|
+
</button>
|
|
893
|
+
<p slot="panel">
|
|
894
|
+
${cache(
|
|
895
|
+
this.activeTabIndex === 0
|
|
896
|
+
? html`<lion-select-rich name="favoriteColor" label="Favorite color">
|
|
897
|
+
${colours.map(
|
|
898
|
+
colour =>
|
|
899
|
+
html`<lion-option
|
|
900
|
+
.choiceValue="${colour.value}"
|
|
901
|
+
checked="${colour.checked || nothing}"
|
|
902
|
+
>${colour.label}</lion-option
|
|
903
|
+
>`,
|
|
904
|
+
)}
|
|
905
|
+
</lion-select-rich>`
|
|
906
|
+
: nothing,
|
|
907
|
+
)}
|
|
908
|
+
</p>
|
|
909
|
+
<button slot="tab" class="second-button" @click=${() => changeActiveTabIndexRef(1)}>
|
|
910
|
+
Work
|
|
911
|
+
</button>
|
|
912
|
+
<p slot="panel">Info page with lots of information about us.</p>
|
|
913
|
+
</lion-tabs>
|
|
914
|
+
`;
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
const wrapperFixture = /** @type {(arg: TemplateResult) => Promise<Wrapper>} */ (_fixture);
|
|
919
|
+
const tagString = defineCE(Wrapper);
|
|
920
|
+
const wrapperTag = unsafeStatic(tagString);
|
|
921
|
+
const wrapperElement = /** @type {Wrapper} */ (
|
|
922
|
+
await wrapperFixture(html`<${wrapperTag}></${wrapperTag}>`)
|
|
923
|
+
);
|
|
924
|
+
await wrapperElement.updateComplete;
|
|
925
|
+
const wrapperElementShadowRoot = wrapperElement.shadowRoot;
|
|
926
|
+
/**
|
|
927
|
+
* @returns { HTMLElement | null | undefined }
|
|
928
|
+
*/
|
|
929
|
+
const getFirstButton = () => wrapperElementShadowRoot?.querySelector('.first-button');
|
|
930
|
+
/**
|
|
931
|
+
* @returns { HTMLElement | null | undefined }
|
|
932
|
+
*/
|
|
933
|
+
const getSecondButton = () => wrapperElementShadowRoot?.querySelector('.second-button');
|
|
934
|
+
/**
|
|
935
|
+
* @returns { HTMLElement | null | undefined }
|
|
936
|
+
*/
|
|
937
|
+
const getInvoker = () => wrapperElementShadowRoot?.querySelector('lion-select-invoker');
|
|
938
|
+
/**
|
|
939
|
+
* @returns { boolean }
|
|
940
|
+
*/
|
|
941
|
+
const isSelectRichRendered = () => !!getInvoker()?.shadowRoot?.childNodes.length;
|
|
942
|
+
/**
|
|
943
|
+
* @returns { string | undefined }
|
|
944
|
+
*/
|
|
945
|
+
const getSelectedColourLabel = () =>
|
|
946
|
+
getInvoker()?.shadowRoot?.querySelector('#content-wrapper')?.textContent?.trim();
|
|
947
|
+
const getDialog = () =>
|
|
948
|
+
wrapperElementShadowRoot
|
|
949
|
+
?.querySelector('lion-select-rich')
|
|
950
|
+
?.shadowRoot?.querySelector('dialog');
|
|
951
|
+
const isDialogVisible = () =>
|
|
952
|
+
// @ts-ignore
|
|
953
|
+
getDialog()?.checkVisibility() === true &&
|
|
954
|
+
getDialog()?.querySelector('#overlay-content-node-wrapper[data-popper-placement]');
|
|
955
|
+
await waitUntil(isSelectRichRendered);
|
|
956
|
+
getInvoker()?.click();
|
|
957
|
+
await waitUntil(isDialogVisible);
|
|
958
|
+
const optionBlue = /** @type { HTMLElement | undefined } */ (
|
|
959
|
+
wrapperElementShadowRoot?.querySelectorAll('lion-option')
|
|
960
|
+
)?.[1];
|
|
961
|
+
optionBlue?.click();
|
|
962
|
+
await waitUntil(() => !isDialogVisible());
|
|
963
|
+
const selectedColourLabelBeforeTabSwitch = getSelectedColourLabel();
|
|
964
|
+
expect(selectedColourLabelBeforeTabSwitch).to.equal('Blue');
|
|
965
|
+
getSecondButton()?.click();
|
|
966
|
+
await waitUntil(() => !isSelectRichRendered());
|
|
967
|
+
getFirstButton()?.click();
|
|
968
|
+
await waitUntil(isSelectRichRendered);
|
|
969
|
+
const selectedColourAfterTabSwitch = getSelectedColourLabel();
|
|
970
|
+
expect(selectedColourAfterTabSwitch).to.equal('Blue');
|
|
971
|
+
});
|
|
972
|
+
});
|
|
973
|
+
describe('when `lion-option` is set by `.modelValue` property', () => {
|
|
974
|
+
it('should display the second option', async () => {
|
|
975
|
+
const colours = [
|
|
976
|
+
{
|
|
977
|
+
label: 'Red',
|
|
978
|
+
value: 'red',
|
|
979
|
+
checked: true,
|
|
980
|
+
},
|
|
981
|
+
{
|
|
982
|
+
label: 'Blue',
|
|
983
|
+
value: 'blue',
|
|
984
|
+
checked: false,
|
|
985
|
+
},
|
|
986
|
+
];
|
|
987
|
+
|
|
988
|
+
/**
|
|
989
|
+
* Note, inactive tab content is **destroyed** on every tab switch.
|
|
990
|
+
*/
|
|
991
|
+
class Wrapper extends LitElement {
|
|
992
|
+
static properties = {
|
|
993
|
+
...super.properties,
|
|
994
|
+
activeTabIndex: { type: Number },
|
|
995
|
+
};
|
|
996
|
+
|
|
997
|
+
constructor() {
|
|
998
|
+
super();
|
|
999
|
+
this.activeTabIndex = 0;
|
|
1000
|
+
}
|
|
1001
|
+
|
|
1002
|
+
/**
|
|
1003
|
+
* @param {number} index
|
|
1004
|
+
*/
|
|
1005
|
+
changeActiveTabIndex(index) {
|
|
1006
|
+
this.activeTabIndex = index;
|
|
1007
|
+
}
|
|
1008
|
+
|
|
1009
|
+
render() {
|
|
1010
|
+
const changeActiveTabIndexRef = this.changeActiveTabIndex.bind(this);
|
|
1011
|
+
return html`
|
|
1012
|
+
<lion-tabs>
|
|
1013
|
+
<button slot="tab" class="first-button" @click=${() => changeActiveTabIndexRef(0)}>
|
|
1014
|
+
Info
|
|
1015
|
+
</button>
|
|
1016
|
+
<p slot="panel">
|
|
1017
|
+
${cache(
|
|
1018
|
+
this.activeTabIndex === 0
|
|
1019
|
+
? html`<lion-select-rich name="favoriteColor" label="Favorite color">
|
|
1020
|
+
${colours.map(
|
|
1021
|
+
colour =>
|
|
1022
|
+
html`<lion-option
|
|
1023
|
+
@model-value-changed=${(/** @type {Event} */ ev) => {
|
|
1024
|
+
const lionOption = /** @type {LionOption} */ (ev.target);
|
|
1025
|
+
// eslint-disable-next-line no-param-reassign
|
|
1026
|
+
colour.checked = lionOption.modelValue.checked;
|
|
1027
|
+
}}
|
|
1028
|
+
.modelValue=${{ value: colour.value, checked: colour.checked }}
|
|
1029
|
+
>${colour.label}</lion-option
|
|
1030
|
+
>`,
|
|
1031
|
+
)}
|
|
1032
|
+
</lion-select-rich>`
|
|
1033
|
+
: nothing,
|
|
1034
|
+
)}
|
|
1035
|
+
</p>
|
|
1036
|
+
<button slot="tab" class="second-button" @click=${() => changeActiveTabIndexRef(1)}>
|
|
1037
|
+
Work
|
|
1038
|
+
</button>
|
|
1039
|
+
<p slot="panel">Info page with lots of information about us.</p>
|
|
1040
|
+
</lion-tabs>
|
|
1041
|
+
`;
|
|
1042
|
+
}
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
const wrapperFixture = /** @type {(arg: TemplateResult) => Promise<Wrapper>} */ (_fixture);
|
|
1046
|
+
const tagString = defineCE(Wrapper);
|
|
1047
|
+
const wrapperTag = unsafeStatic(tagString);
|
|
1048
|
+
const wrapperElement = /** @type {Wrapper} */ (
|
|
1049
|
+
await wrapperFixture(html`<${wrapperTag}></${wrapperTag}>`)
|
|
1050
|
+
);
|
|
1051
|
+
await wrapperElement.updateComplete;
|
|
1052
|
+
const wrapperElementShadowRoot = wrapperElement.shadowRoot;
|
|
1053
|
+
/**
|
|
1054
|
+
* @returns { HTMLElement | null | undefined }
|
|
1055
|
+
*/
|
|
1056
|
+
const getFirstButton = () => wrapperElementShadowRoot?.querySelector('.first-button');
|
|
1057
|
+
/**
|
|
1058
|
+
* @returns { HTMLElement | null | undefined }
|
|
1059
|
+
*/
|
|
1060
|
+
const getSecondButton = () => wrapperElementShadowRoot?.querySelector('.second-button');
|
|
1061
|
+
/**
|
|
1062
|
+
* @returns { HTMLElement | null | undefined }
|
|
1063
|
+
*/
|
|
1064
|
+
const getInvoker = () => wrapperElementShadowRoot?.querySelector('lion-select-invoker');
|
|
1065
|
+
/**
|
|
1066
|
+
* @returns { boolean }
|
|
1067
|
+
*/
|
|
1068
|
+
const isSelectRichRendered = () => !!getInvoker()?.shadowRoot?.childNodes.length;
|
|
1069
|
+
/**
|
|
1070
|
+
* @returns { string | undefined }
|
|
1071
|
+
*/
|
|
1072
|
+
const getSelectedColourLabel = () =>
|
|
1073
|
+
getInvoker()?.shadowRoot?.querySelector('#content-wrapper')?.textContent?.trim();
|
|
1074
|
+
const getDialog = () =>
|
|
1075
|
+
wrapperElementShadowRoot
|
|
1076
|
+
?.querySelector('lion-select-rich')
|
|
1077
|
+
?.shadowRoot?.querySelector('dialog');
|
|
1078
|
+
const isDialogVisible = () =>
|
|
1079
|
+
// @ts-ignore
|
|
1080
|
+
getDialog()?.checkVisibility() === true &&
|
|
1081
|
+
getDialog()?.querySelector('#overlay-content-node-wrapper[data-popper-placement]');
|
|
1082
|
+
await waitUntil(isSelectRichRendered);
|
|
1083
|
+
getInvoker()?.click();
|
|
1084
|
+
await waitUntil(isDialogVisible);
|
|
1085
|
+
const optionBlue = /** @type { HTMLElement | undefined } */ (
|
|
1086
|
+
wrapperElementShadowRoot?.querySelectorAll('lion-option')
|
|
1087
|
+
)?.[1];
|
|
1088
|
+
optionBlue?.click();
|
|
1089
|
+
await waitUntil(() => !isDialogVisible());
|
|
1090
|
+
const selectedColourLabelBeforeTabSwitch = getSelectedColourLabel();
|
|
1091
|
+
expect(selectedColourLabelBeforeTabSwitch).to.equal('Blue');
|
|
1092
|
+
getSecondButton()?.click();
|
|
1093
|
+
await waitUntil(() => !isSelectRichRendered());
|
|
1094
|
+
getFirstButton()?.click();
|
|
1095
|
+
await waitUntil(isSelectRichRendered);
|
|
1096
|
+
const selectedColourAfterTabSwitch = getSelectedColourLabel();
|
|
1097
|
+
expect(selectedColourAfterTabSwitch).to.equal('Blue');
|
|
1098
|
+
});
|
|
1099
|
+
});
|
|
1100
|
+
});
|
|
1101
|
+
|
|
727
1102
|
describe('Teardown', () => {
|
|
728
1103
|
it('correctly removes event listeners when disconnected from dom', async () => {
|
|
729
1104
|
const el = await fixture(html`
|
package/custom-elements.json
CHANGED
|
@@ -2145,6 +2145,36 @@
|
|
|
2145
2145
|
}
|
|
2146
2146
|
]
|
|
2147
2147
|
},
|
|
2148
|
+
{
|
|
2149
|
+
"kind": "javascript-module",
|
|
2150
|
+
"path": "exports/define-helpers/sb-action-logger.js",
|
|
2151
|
+
"declarations": [],
|
|
2152
|
+
"exports": [
|
|
2153
|
+
{
|
|
2154
|
+
"kind": "custom-element-definition",
|
|
2155
|
+
"name": "sb-action-logger",
|
|
2156
|
+
"declaration": {
|
|
2157
|
+
"name": "SbActionLogger",
|
|
2158
|
+
"module": "/exports/helpers.js"
|
|
2159
|
+
}
|
|
2160
|
+
}
|
|
2161
|
+
]
|
|
2162
|
+
},
|
|
2163
|
+
{
|
|
2164
|
+
"kind": "javascript-module",
|
|
2165
|
+
"path": "exports/define-helpers/sb-locale-switcher.js",
|
|
2166
|
+
"declarations": [],
|
|
2167
|
+
"exports": [
|
|
2168
|
+
{
|
|
2169
|
+
"kind": "custom-element-definition",
|
|
2170
|
+
"name": "sb-locale-switcher",
|
|
2171
|
+
"declaration": {
|
|
2172
|
+
"name": "SbLocaleSwitcher",
|
|
2173
|
+
"module": "/exports/helpers.js"
|
|
2174
|
+
}
|
|
2175
|
+
}
|
|
2176
|
+
]
|
|
2177
|
+
},
|
|
2148
2178
|
{
|
|
2149
2179
|
"kind": "javascript-module",
|
|
2150
2180
|
"path": "exports/define/lion-accordion.js",
|
|
@@ -2850,36 +2880,6 @@
|
|
|
2850
2880
|
}
|
|
2851
2881
|
]
|
|
2852
2882
|
},
|
|
2853
|
-
{
|
|
2854
|
-
"kind": "javascript-module",
|
|
2855
|
-
"path": "exports/define-helpers/sb-action-logger.js",
|
|
2856
|
-
"declarations": [],
|
|
2857
|
-
"exports": [
|
|
2858
|
-
{
|
|
2859
|
-
"kind": "custom-element-definition",
|
|
2860
|
-
"name": "sb-action-logger",
|
|
2861
|
-
"declaration": {
|
|
2862
|
-
"name": "SbActionLogger",
|
|
2863
|
-
"module": "/exports/helpers.js"
|
|
2864
|
-
}
|
|
2865
|
-
}
|
|
2866
|
-
]
|
|
2867
|
-
},
|
|
2868
|
-
{
|
|
2869
|
-
"kind": "javascript-module",
|
|
2870
|
-
"path": "exports/define-helpers/sb-locale-switcher.js",
|
|
2871
|
-
"declarations": [],
|
|
2872
|
-
"exports": [
|
|
2873
|
-
{
|
|
2874
|
-
"kind": "custom-element-definition",
|
|
2875
|
-
"name": "sb-locale-switcher",
|
|
2876
|
-
"declaration": {
|
|
2877
|
-
"name": "SbLocaleSwitcher",
|
|
2878
|
-
"module": "/exports/helpers.js"
|
|
2879
|
-
}
|
|
2880
|
-
}
|
|
2881
|
-
]
|
|
2882
|
-
},
|
|
2883
2883
|
{
|
|
2884
2884
|
"kind": "javascript-module",
|
|
2885
2885
|
"path": "components/accordion/src/LionAccordion.js",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lion-dialog.test.d.ts","sourceRoot":"","sources":["../../../../components/dialog/test/lion-dialog.test.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"lion-dialog.test.d.ts","sourceRoot":"","sources":["../../../../components/dialog/test/lion-dialog.test.js"],"names":[],"mappings":"yBAmBa,OAAO,sBAAsB,EAAE,UAAU;6BACzC,OAAO,KAAK,EAAE,cAAc"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OverlayMixin.d.ts","sourceRoot":"","sources":["../../../../components/overlays/src/OverlayMixin.js"],"names":[],"mappings":"AAIA;;;;GAIG;AAEH;;;;;;;GAOG;AACH,yCAHU,YAAY,
|
|
1
|
+
{"version":3,"file":"OverlayMixin.d.ts","sourceRoot":"","sources":["../../../../components/overlays/src/OverlayMixin.js"],"names":[],"mappings":"AAIA;;;;GAIG;AAEH;;;;;;;GAOG;AACH,yCAHU,YAAY,CAqZlB;2BA7ZS,OAAO,+BAA+B,EAAE,YAAY;AA8ZjE,gGAAoE;4BAhavD,OAAO,2BAA2B,EAAE,aAAa;kCACjD,OAAO,+BAA+B,EAAE,mBAAmB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OverlayMixin.suite.d.ts","sourceRoot":"","sources":["../../../../components/overlays/test-suites/OverlayMixin.suite.js"],"names":[],"mappings":"AAwDA;;GAEG;AACH,iEAFW;IAAC,SAAS,EAAC,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAC,MAAM,CAAA;CAAC,
|
|
1
|
+
{"version":3,"file":"OverlayMixin.suite.d.ts","sourceRoot":"","sources":["../../../../components/overlays/test-suites/OverlayMixin.suite.js"],"names":[],"mappings":"AAwDA;;GAEG;AACH,iEAFW;IAAC,SAAS,EAAC,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAC,MAAM,CAAA;CAAC,QA+mBzD;kCArpBY,OAAO,+BAA+B,EAAE,mBAAmB;wBAC3D,UAAU,GAAG,WAAW,GAAG;IAAC,YAAY,EAAC,iBAAiB,CAAA;CAAC;2BAC3D,OAAO,+BAA+B,EAAE,YAAY;0BACpD,OAAO,+BAA+B,EAAE,WAAW;4BACnD,OAAO,2BAA2B,EAAE,aAAa"}
|