chore: add ArrowMixin improvements, add Datepicker local/global switch

This commit is contained in:
Thomas Allmer 2020-11-02 08:55:49 +01:00
parent c242204709
commit 9c3224b4ff
7 changed files with 167 additions and 72 deletions

View file

@ -0,0 +1,8 @@
---
'@lion/input-datepicker': minor
'@lion/overlays': minor
---
- ArrowMixin needs to extend styles and not overwrite them
- ArrowMixin add an `_arrowNodeTemplate` which can be used to only override the arrow content
- InputDatepicker switch between bottomsheet style (on mobile) popover (on desktop/table with screensize bigger then 600px)

45
package-lock.json generated
View file

@ -23,9 +23,9 @@
"@types/chai-dom": "^0.0.8",
"@web/dev-server": "^0.0.13",
"@web/dev-server-legacy": "^0.1.4",
"@web/test-runner": "^0.9.0",
"@web/test-runner": "^0.9.7",
"@web/test-runner-browserstack": "^0.2.0",
"@web/test-runner-playwright": "^0.6.3",
"@web/test-runner-playwright": "^0.6.4",
"@webcomponents/webcomponentsjs": "^2.4.4",
"babel-eslint": "^8.2.6",
"babel-polyfill": "^6.26.0",
@ -4799,9 +4799,9 @@
"dev": true
},
"node_modules/@types/puppeteer": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/@types/puppeteer/-/puppeteer-3.0.2.tgz",
"integrity": "sha512-JRuHPSbHZBadOxxFwpyZPeRlpPTTeMbQneMdpFd8LXdyNfFSiX950CGewdm69g/ipzEAXAmMyFF1WOWJOL/nKw==",
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/@types/puppeteer/-/puppeteer-3.0.4.tgz",
"integrity": "sha512-wmkBg1Wn/wwgGDl9IrxwY9nJ/Hfv/YHFAqy6Dch9KYDSjA0lif8PA7j3Ls1iOfKWEMRIbHkpWIPoiw4r9Vq+3A==",
"dev": true,
"dependencies": {
"@types/node": "*"
@ -5302,16 +5302,17 @@
}
},
"node_modules/@web/test-runner": {
"version": "0.9.6",
"resolved": "https://registry.npmjs.org/@web/test-runner/-/test-runner-0.9.6.tgz",
"integrity": "sha512-ThtPMj2MPe6k6xyg5CZKmtzH0G1CN8NlBrS6+YpHtg7jKneXsFeg8RcinY0Maq4sKRdeYCfwUKqSdGNeqrChlg==",
"version": "0.9.7",
"resolved": "https://registry.npmjs.org/@web/test-runner/-/test-runner-0.9.7.tgz",
"integrity": "sha512-A894e2sgI3aZ7voDMo0o/0ms7oS7NPOb9zui7tMGZt4RUWc4uWduolHd7znAVCTXSJwmlGw8Aa1gWwf4IzAvaQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@rollup/plugin-node-resolve": "^8.1.0",
"@web/config-loader": "^0.1.2",
"@web/dev-server-rollup": "^0.2.9",
"@web/test-runner-chrome": "^0.7.2",
"@web/test-runner-cli": "^0.6.8",
"@web/test-runner-cli": "^0.6.9",
"@web/test-runner-commands": "^0.2.1",
"@web/test-runner-core": "^0.8.7",
"@web/test-runner-mocha": "^0.5.1",
@ -5361,9 +5362,9 @@
}
},
"node_modules/@web/test-runner-cli": {
"version": "0.6.8",
"resolved": "https://registry.npmjs.org/@web/test-runner-cli/-/test-runner-cli-0.6.8.tgz",
"integrity": "sha512-lZhViVaB3/wDfoUPsw9meucUsSonpBnVBy/b3Sqtmfu6bsvOxVEIl5VVRBKIhN94JSQPNUDRWPUVDeV1tljddg==",
"version": "0.6.9",
"resolved": "https://registry.npmjs.org/@web/test-runner-cli/-/test-runner-cli-0.6.9.tgz",
"integrity": "sha512-OgjGb0KEs8ZwlUymsAonMiwpZ1qOSQh4dwqfEqbvbu6LyHbjM6Sm9DLThHCibBIYGzxzdHMwgsgWJJCZFAdaKA==",
"dev": true,
"dependencies": {
"@babel/code-frame": "^7.10.4",
@ -29623,9 +29624,9 @@
"dev": true
},
"@types/puppeteer": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/@types/puppeteer/-/puppeteer-3.0.2.tgz",
"integrity": "sha512-JRuHPSbHZBadOxxFwpyZPeRlpPTTeMbQneMdpFd8LXdyNfFSiX950CGewdm69g/ipzEAXAmMyFF1WOWJOL/nKw==",
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/@types/puppeteer/-/puppeteer-3.0.4.tgz",
"integrity": "sha512-wmkBg1Wn/wwgGDl9IrxwY9nJ/Hfv/YHFAqy6Dch9KYDSjA0lif8PA7j3Ls1iOfKWEMRIbHkpWIPoiw4r9Vq+3A==",
"dev": true,
"requires": {
"@types/node": "*"
@ -30072,16 +30073,16 @@
}
},
"@web/test-runner": {
"version": "0.9.6",
"resolved": "https://registry.npmjs.org/@web/test-runner/-/test-runner-0.9.6.tgz",
"integrity": "sha512-ThtPMj2MPe6k6xyg5CZKmtzH0G1CN8NlBrS6+YpHtg7jKneXsFeg8RcinY0Maq4sKRdeYCfwUKqSdGNeqrChlg==",
"version": "0.9.7",
"resolved": "https://registry.npmjs.org/@web/test-runner/-/test-runner-0.9.7.tgz",
"integrity": "sha512-A894e2sgI3aZ7voDMo0o/0ms7oS7NPOb9zui7tMGZt4RUWc4uWduolHd7znAVCTXSJwmlGw8Aa1gWwf4IzAvaQ==",
"dev": true,
"requires": {
"@rollup/plugin-node-resolve": "^8.1.0",
"@web/config-loader": "^0.1.2",
"@web/dev-server-rollup": "^0.2.9",
"@web/test-runner-chrome": "^0.7.2",
"@web/test-runner-cli": "^0.6.8",
"@web/test-runner-cli": "^0.6.9",
"@web/test-runner-commands": "^0.2.1",
"@web/test-runner-core": "^0.8.7",
"@web/test-runner-mocha": "^0.5.1",
@ -30144,9 +30145,9 @@
}
},
"@web/test-runner-cli": {
"version": "0.6.8",
"resolved": "https://registry.npmjs.org/@web/test-runner-cli/-/test-runner-cli-0.6.8.tgz",
"integrity": "sha512-lZhViVaB3/wDfoUPsw9meucUsSonpBnVBy/b3Sqtmfu6bsvOxVEIl5VVRBKIhN94JSQPNUDRWPUVDeV1tljddg==",
"version": "0.6.9",
"resolved": "https://registry.npmjs.org/@web/test-runner-cli/-/test-runner-cli-0.6.9.tgz",
"integrity": "sha512-OgjGb0KEs8ZwlUymsAonMiwpZ1qOSQh4dwqfEqbvbu6LyHbjM6Sm9DLThHCibBIYGzxzdHMwgsgWJJCZFAdaKA==",
"dev": true,
"requires": {
"@babel/code-frame": "^7.10.4",

View file

@ -48,9 +48,9 @@
"@types/chai-dom": "^0.0.8",
"@web/dev-server": "^0.0.13",
"@web/dev-server-legacy": "^0.1.4",
"@web/test-runner": "^0.9.0",
"@web/test-runner": "^0.9.7",
"@web/test-runner-browserstack": "^0.2.0",
"@web/test-runner-playwright": "^0.6.3",
"@web/test-runner-playwright": "^0.6.4",
"@webcomponents/webcomponentsjs": "^2.4.4",
"babel-eslint": "^8.2.6",
"babel-polyfill": "^6.26.0",

View file

@ -1,14 +1,21 @@
import { LionCalendar } from '@lion/calendar/src/LionCalendar';
import { html, ifDefined, ScopedElementsMixin } from '@lion/core';
import { LionInputDate } from '@lion/input-date';
import { OverlayMixin, withModalDialogConfig } from '@lion/overlays';
import {
OverlayMixin,
withBottomSheetConfig,
withModalDialogConfig,
ArrowMixin,
} from '@lion/overlays';
import { LionCalendarOverlayFrame } from './LionCalendarOverlayFrame.js';
/**
* @customElement lion-input-datepicker
*/
// @ts-expect-error https://github.com/microsoft/TypeScript/issues/40110
export class LionInputDatepicker extends ScopedElementsMixin(OverlayMixin(LionInputDate)) {
export class LionInputDatepicker extends ScopedElementsMixin(
ArrowMixin(OverlayMixin(LionInputDate)),
) {
static get scopedElements() {
return {
...super.scopedElements,
@ -226,10 +233,13 @@ export class LionInputDatepicker extends ScopedElementsMixin(OverlayMixin(LionIn
// When not opened (usually on init), it does not need to be rendered.
// This would make first paint quicker
return html`
<div id="overlay-content-node-wrapper">
<lion-calendar-overlay-frame class="calendar__overlay-frame">
<span slot="heading">${this.calendarHeading}</span>
${this._calendarTemplate()}
</lion-calendar-overlay-frame>
${this._arrowNodeTemplate()}
</div>
`;
}
@ -280,6 +290,15 @@ export class LionInputDatepicker extends ScopedElementsMixin(OverlayMixin(LionIn
`;
}
_setupOverlayCtrl() {
super._setupOverlayCtrl();
this.__datepickerBeforeShow = () => {
this._overlayCtrl.updateConfig(this._defineOverlayConfig());
};
this._overlayCtrl.addEventListener('before-show', this.__datepickerBeforeShow);
}
/**
* @override Configures OverlayMixin
* @desc overrides default configuration options for this component
@ -287,11 +306,21 @@ export class LionInputDatepicker extends ScopedElementsMixin(OverlayMixin(LionIn
*/
// eslint-disable-next-line class-methods-use-this
_defineOverlayConfig() {
if (window.innerWidth >= 600) {
this.hasArrow = true;
return {
...withModalDialogConfig(),
hidesOnOutsideClick: true,
...super._defineOverlayConfig(),
popperConfig: {
...super._defineOverlayConfig().popperConfig,
placement: 'bottom',
},
};
}
this.hasArrow = false;
return withBottomSheetConfig();
}
async __openCalendarOverlay() {
await this._overlayCtrl.show();

View file

@ -4,6 +4,7 @@ import { html, LitElement } from '@lion/core';
import { IsDateDisabled, MaxDate, MinDate, MinMaxDate } from '@lion/form-core';
import { aTimeout, defineCE, expect, fixture as _fixture, nextFrame } from '@open-wc/testing';
import sinon from 'sinon';
import { setViewport } from '@web/test-runner-commands';
import '../lion-input-datepicker.js';
import { LionInputDatepicker } from '../src/LionInputDatepicker.js';
import { DatepickerInputObject } from '../test-helpers.js';
@ -515,7 +516,55 @@ describe('<lion-input-datepicker>', () => {
await myElObj.openCalendar();
myElObj.overlayEl.hidden = true;
await el.updateComplete;
expect(myElObj.overlayEl).not.to.be.displayed;
expect(getComputedStyle(myElObj.overlayEl).display).to.equal('none', 'Display is not none');
});
});
describe('responsive', async () => {
it('opens as bottom sheet on mobile', async () => {
await setViewport({ width: 360, height: 640 });
const el = await fixture(html`<lion-input-datepicker></lion-input-datepicker>`);
const myElObj = new DatepickerInputObject(el);
await myElObj.openCalendar();
expect(el.hasArrow).to.be.false;
expect(
el?.shadowRoot?.contains(myElObj.overlayController.contentNode),
'Datepicker does not get rendered as bottom sheet',
).to.be.false;
});
it('opens as popover on desktop', async () => {
await setViewport({ width: 1200, height: 640 });
const el = await fixture(html`<lion-input-datepicker></lion-input-datepicker>`);
const myElObj = new DatepickerInputObject(el);
await myElObj.openCalendar();
expect(el.hasArrow).to.be.true;
expect(
el?.shadowRoot?.contains(myElObj.overlayController.contentNode),
'Datepicker does not get rendered as a popover',
).to.be.true;
});
// TODO: fix a bug in overlays which does not move global nodes back to the local dom
it.skip('can switch between bottom sheet and popover', async () => {
const el = await fixture(html`<lion-input-datepicker></lion-input-datepicker>`);
await el.updateComplete;
const myElObj = new DatepickerInputObject(el);
await setViewport({ width: 360, height: 640 });
await myElObj.openCalendar();
expect(
el?.shadowRoot?.contains(myElObj.overlayController.contentNode),
'Datepicker does not get rendered as bottom sheet',
).to.be.false;
await myElObj.closeCalendar();
await setViewport({ width: 1200, height: 640 });
await myElObj.openCalendar();
expect(
el?.shadowRoot?.contains(myElObj.overlayController.contentNode),
'Datepicker does not get rendered as a popover',
).to.be.true;
});
});
});

View file

@ -22,7 +22,9 @@ export const ArrowMixinImplementation = superclass =>
}
static get styles() {
return css`
return [
super.styles ? super.styles : [],
css`
:host {
--tooltip-arrow-width: 12px;
--tooltip-arrow-height: 8px;
@ -63,7 +65,8 @@ export const ArrowMixinImplementation = superclass =>
);
transform: rotate(90deg);
}
`;
`,
];
}
constructor() {
@ -77,11 +80,15 @@ export const ArrowMixinImplementation = superclass =>
<slot name="invoker"></slot>
<div id="overlay-content-node-wrapper">
<slot name="content"></slot>
<div class="arrow" x-arrow>${this._arrowTemplate()}</div>
${this._arrowNodeTemplate()}
</div>
`;
}
_arrowNodeTemplate() {
return html`<div class="arrow" x-arrow>${this._arrowTemplate()}</div>`;
}
// eslint-disable-next-line class-methods-use-this
_arrowTemplate() {
return html`

View file

@ -19,6 +19,7 @@ export declare class ArrowHost {
render(): TemplateResult;
_arrowTemplate(): TemplateResult;
_arrowNodeTemplate(): TemplateResult;
_defineOverlayConfig(): OverlayConfig;
__setupRepositionCompletePromise(): void;
get _arrowNode(): Element | null;