fix(steps): allow extensions to introduce new non-default slots

This commit is contained in:
Max Larionov 2019-06-03 12:59:51 +02:00 committed by Mikhail Bashkirov
parent 72516ac2c5
commit 37d0db502f
4 changed files with 36 additions and 13 deletions

View file

@ -97,9 +97,8 @@ export class LionStep extends LionLitElement {
`; `;
} }
connectedCallback() { firstUpdated() {
// eslint-disable-next-line wc/guard-super-call super.firstUpdated();
super.connectedCallback();
this.controller = this.parentNode; this.controller = this.parentNode;
if (this.initialStep === true) { if (this.initialStep === true) {
this.enter(true); this.enter(true);
@ -107,9 +106,9 @@ export class LionStep extends LionLitElement {
} }
getControllerIndex() { getControllerIndex() {
const controllerChildren = this.controller.children; const { steps } = this.controller;
for (let i = 0; i < controllerChildren.length; i += 1) { for (let i = 0; i < steps.length; i += 1) {
if (controllerChildren[i] === this) { if (steps[i] === this) {
return i; return i;
} }
} }

View file

@ -63,7 +63,7 @@ export class LionSteps extends ObserverMixin(LionLitElement) {
firstUpdated() { firstUpdated() {
super.firstUpdated(); super.firstUpdated();
this._max = this.children.length - 1; this._max = this.steps.length - 1;
} }
next() { next() {
@ -74,12 +74,17 @@ export class LionSteps extends ObserverMixin(LionLitElement) {
this._goTo(this.current - 1, this.current); this._goTo(this.current - 1, this.current);
} }
get steps() {
const defaultSlot = this.shadowRoot.querySelector('slot:not([name])');
return defaultSlot.assignedNodes().filter(node => node.nodeType === Node.ELEMENT_NODE);
}
_goTo(newCurrent, oldCurrent) { _goTo(newCurrent, oldCurrent) {
if (newCurrent < 0 || newCurrent > this._max) { if (newCurrent < 0 || newCurrent > this._max) {
throw new Error(`There is no step at index ${newCurrent}.`); throw new Error(`There is no step at index ${newCurrent}.`);
} }
const nextStep = this.children[newCurrent]; const nextStep = this.steps[newCurrent];
const back = newCurrent < oldCurrent; const back = newCurrent < oldCurrent;
if (nextStep.passesCondition(this.data)) { if (nextStep.passesCondition(this.data)) {
@ -99,8 +104,8 @@ export class LionSteps extends ObserverMixin(LionLitElement) {
} }
_changeStep(newCurrent, oldCurrent) { _changeStep(newCurrent, oldCurrent) {
const oldStepElement = this.children[oldCurrent]; const oldStepElement = this.steps[oldCurrent];
const newStepElement = this.children[newCurrent]; const newStepElement = this.steps[newCurrent];
const fromStep = { number: oldCurrent, element: oldStepElement }; const fromStep = { number: oldCurrent, element: oldStepElement };
const toStep = { number: newCurrent, element: newStepElement }; const toStep = { number: newCurrent, element: newStepElement };

View file

@ -1,4 +1,4 @@
import { expect, fixture, html, oneEvent } from '@open-wc/testing'; import { expect, fixture, fixtureSync, html, oneEvent } from '@open-wc/testing';
import '../lion-step.js'; import '../lion-step.js';
@ -36,20 +36,24 @@ describe('lion-step', () => {
}); });
it('allows to define it as the initial-step', async () => { it('allows to define it as the initial-step', async () => {
const el = await fixture(html` const el = fixtureSync(html`
<fake-lion-steps> <fake-lion-steps>
<lion-step initial-step>Step 1</lion-step> <lion-step initial-step>Step 1</lion-step>
</fake-lion-steps> </fake-lion-steps>
`); `);
el.steps = [el.children[0]];
await el.updateComplete;
expect(el.current).to.equal(0); expect(el.current).to.equal(0);
expect(el.children[0].status).to.equal('entered'); expect(el.children[0].status).to.equal('entered');
const el2 = await fixture(html` const el2 = fixtureSync(html`
<fake-lion-steps> <fake-lion-steps>
<lion-step>Step 1</lion-step> <lion-step>Step 1</lion-step>
<lion-step initial-step>Step 2</lion-step> <lion-step initial-step>Step 2</lion-step>
</fake-lion-steps> </fake-lion-steps>
`); `);
el2.steps = [el2.children[0], el2.children[1]];
await el2.updateComplete;
expect(el2.current).to.equal(1); expect(el2.current).to.equal(1);
expect(el2.children[0].status).to.equal('untouched'); expect(el2.children[0].status).to.equal('untouched');
expect(el2.children[1].status).to.equal('entered'); expect(el2.children[1].status).to.equal('entered');

View file

@ -27,6 +27,21 @@ async function checkWorkflow(steps, expected) {
} }
describe('lion-steps', () => { describe('lion-steps', () => {
it('has "steps" getter that returns default slot elements', async () => {
const el = await fixture(html`
<lion-steps>
<lion-step>Step 1</lion-step>
<lion-step initial-step>Step 2</lion-step>
<other-step-element>Step 3</other-step-element>
<steps-extension-element slot="new-slot">e.g. steps indicator</steps-extension-element>
</lion-steps>
`);
expect(el.steps.length).to.equal(3);
expect(el.steps[0].tagName).to.equal('LION-STEP');
expect(el.steps[1].tagName).to.equal('LION-STEP');
expect(el.steps[2].tagName).to.equal('OTHER-STEP-ELEMENT');
});
describe('initialization', () => { describe('initialization', () => {
it('activates step with an "initial-step" attribute', async () => { it('activates step with an "initial-step" attribute', async () => {
const el = await fixture(html` const el = await fixture(html`