feat(overlays): improve API for overriding controller config in mixin

This commit is contained in:
Joren Broekema 2019-11-26 14:54:33 +01:00 committed by Thomas Allmer
parent 6b2b91f1b3
commit 45f557183d
16 changed files with 173 additions and 87 deletions

View file

@ -40,7 +40,7 @@ The accessibility column indicates whether the functionality is accessible in it
| [icon](./packages/icon) | [![icon](https://img.shields.io/npm/v/@lion/icon.svg)](https://www.npmjs.com/package/@lion/icon) | Display our svg icons | [#173][i173], [#172][i172] | | [icon](./packages/icon) | [![icon](https://img.shields.io/npm/v/@lion/icon.svg)](https://www.npmjs.com/package/@lion/icon) | Display our svg icons | [#173][i173], [#172][i172] |
| [steps](./packages/steps) | [![steps](https://img.shields.io/npm/v/@lion/steps.svg)](https://www.npmjs.com/package/@lion/steps) | Multi Step System | n/a | | [steps](./packages/steps) | [![steps](https://img.shields.io/npm/v/@lion/steps.svg)](https://www.npmjs.com/package/@lion/steps) | Multi Step System | n/a |
| [tabs](./packages/tabs) | [![tBS](https://img.shields.io/npm/v/@lion/tabs.svg)](https://www.npmjs.com/package/@lion/tabs) | Move between a small number of equally important views | n/a | | [tabs](./packages/tabs) | [![tBS](https://img.shields.io/npm/v/@lion/tabs.svg)](https://www.npmjs.com/package/@lion/tabs) | Move between a small number of equally important views | n/a |
| **-- Forms --** | | | | **-- Forms --** | | | |
| [form](./packages/form) | [![form](https://img.shields.io/npm/v/@lion/form.svg)](https://www.npmjs.com/package/@lion/form) | Wrapper for multiple form elements | ✔️ | | [form](./packages/form) | [![form](https://img.shields.io/npm/v/@lion/form.svg)](https://www.npmjs.com/package/@lion/form) | Wrapper for multiple form elements | ✔️ |
| [field](./packages/field) | [![field](https://img.shields.io/npm/v/@lion/field.svg)](https://www.npmjs.com/package/@lion/field) | Base Class for all inputs | [#190][i190] | | [field](./packages/field) | [![field](https://img.shields.io/npm/v/@lion/field.svg)](https://www.npmjs.com/package/@lion/field) | Base Class for all inputs | [#190][i190] |
| [fieldset](./packages/fieldset) | [![fieldset](https://img.shields.io/npm/v/@lion/fieldset.svg)](https://www.npmjs.com/package/@lion/fieldset) | Group for form inputs | ✔️ | | [fieldset](./packages/fieldset) | [![fieldset](https://img.shields.io/npm/v/@lion/fieldset.svg)](https://www.npmjs.com/package/@lion/fieldset) | Group for form inputs | ✔️ |
@ -48,7 +48,7 @@ The accessibility column indicates whether the functionality is accessible in it
| [checkbox](./packages/checkbox) | [![checkbox](https://img.shields.io/npm/v/@lion/checkbox.svg)](https://www.npmjs.com/package/@lion/checkbox) | Checkbox form element | ✔️ | | [checkbox](./packages/checkbox) | [![checkbox](https://img.shields.io/npm/v/@lion/checkbox.svg)](https://www.npmjs.com/package/@lion/checkbox) | Checkbox form element | ✔️ |
| [checkbox-group](./packages/checkbox-group) | [![checkbox-group](https://img.shields.io/npm/v/@lion/checkbox-group.svg)](https://www.npmjs.com/package/@lion/checkbox-group) | Group of checkboxes | ✔️ | | [checkbox-group](./packages/checkbox-group) | [![checkbox-group](https://img.shields.io/npm/v/@lion/checkbox-group.svg)](https://www.npmjs.com/package/@lion/checkbox-group) | Group of checkboxes | ✔️ |
| [input](./packages/input) | [![input](https://img.shields.io/npm/v/@lion/input.svg)](https://www.npmjs.com/package/@lion/input) | Input element for strings | ✔️ | | [input](./packages/input) | [![input](https://img.shields.io/npm/v/@lion/input.svg)](https://www.npmjs.com/package/@lion/input) | Input element for strings | ✔️ |
| [input-amount](./packages/input-amount) | [![input-amount](https://img.shields.io/npm/v/@lion/input-amount.svg)](https://www.npmjs.com/package/@lion/input-amount) | Input element for amounts | [#166][i166] | ✔️ | | [input-amount](./packages/input-amount) | [![input-amount](https://img.shields.io/npm/v/@lion/input-amount.svg)](https://www.npmjs.com/package/@lion/input-amount) | Input element for amounts | [#166][i166] |
| [input-date](./packages/input-date) | [![input-date](https://img.shields.io/npm/v/@lion/input-date.svg)](https://www.npmjs.com/package/@lion/input-date) | Input element for dates | ✔️ | | [input-date](./packages/input-date) | [![input-date](https://img.shields.io/npm/v/@lion/input-date.svg)](https://www.npmjs.com/package/@lion/input-date) | Input element for dates | ✔️ |
| [input-datepicker](./packages/input-datepicker) | [![input-datepicker](https://img.shields.io/npm/v/@lion/input-datepicker.svg)](https://www.npmjs.com/package/@lion/input-datepicker) | Input element for dates with a datepicker | ✔️ | | [input-datepicker](./packages/input-datepicker) | [![input-datepicker](https://img.shields.io/npm/v/@lion/input-datepicker.svg)](https://www.npmjs.com/package/@lion/input-datepicker) | Input element for dates with a datepicker | ✔️ |
| [input-email](./packages/input-email) | [![input-email](https://img.shields.io/npm/v/@lion/input-email.svg)](https://www.npmjs.com/package/@lion/input-email) | Input element for e-mails | [#169][i169] | | [input-email](./packages/input-email) | [![input-email](https://img.shields.io/npm/v/@lion/input-email.svg)](https://www.npmjs.com/package/@lion/input-email) | Input element for e-mails | [#169][i169] |
@ -58,9 +58,9 @@ The accessibility column indicates whether the functionality is accessible in it
| [select](./packages/select) | [![select](https://img.shields.io/npm/v/@lion/select.svg)](https://www.npmjs.com/package/@lion/select) | Simple native dropdown element | ✔️ | | [select](./packages/select) | [![select](https://img.shields.io/npm/v/@lion/select.svg)](https://www.npmjs.com/package/@lion/select) | Simple native dropdown element | ✔️ |
| [textarea](./packages/textarea) | [![textarea](https://img.shields.io/npm/v/@lion/textarea.svg)](https://www.npmjs.com/package/@lion/textarea) | Multiline text input | [#165][i165] | | [textarea](./packages/textarea) | [![textarea](https://img.shields.io/npm/v/@lion/textarea.svg)](https://www.npmjs.com/package/@lion/textarea) | Multiline text input | [#165][i165] |
| **-- Overlays --** | | | | | **-- Overlays --** | | | |
| [overlays](./packages/overlays) | [![overlays](https://img.shields.io/npm/v/@lion/overlays.svg)](https://www.npmjs.com/package/@lion/overlays) | Overlays System using lit-html for rendering | ✔️ | | [overlays](./packages/overlays) | [![overlays](https://img.shields.io/npm/v/@lion/overlays.svg)](https://www.npmjs.com/package/@lion/overlays) | Overlay System | ✔️ |
| [popup](./packages/popup) | [![popup](https://img.shields.io/npm/v/@lion/popup.svg)](https://www.npmjs.com/package/@lion/popup) | Popup element | [#175][i175], [#174][i174] | | [dialog](./packages/dialog) | [![dialog](https://img.shields.io/npm/v/@lion/dialog.svg)](https://www.npmjs.com/package/@lion/dialog) | Dialog element | ✔️ |
| [tooltip](./packages/tooltip) | [![tooltip](https://img.shields.io/npm/v/@lion/tooltip.svg)](https://www.npmjs.com/package/@lion/tooltip) | Popup element | [#178][i178], [#177][i177], [#176][i176], [#175][i175], [#174][i174] | | [tooltip](./packages/tooltip) | [![tooltip](https://img.shields.io/npm/v/@lion/tooltip.svg)](https://www.npmjs.com/package/@lion/tooltip) | Tooltip element | [#178][i178], [#177][i177], [#176][i176], [#175][i175], [#174][i174] |
## How to use ## How to use

View file

@ -108,10 +108,16 @@ describe('<lion-calendar>', () => {
`), `),
); );
expect( expect(
elObj.checkForAllDayObjs(o => o.buttonEl.getAttribute('tabindex') === '0', n => n === 5), elObj.checkForAllDayObjs(
o => o.buttonEl.getAttribute('tabindex') === '0',
n => n === 5,
),
).to.be.true; ).to.be.true;
expect( expect(
elObj.checkForAllDayObjs(o => o.buttonEl.getAttribute('tabindex') === '-1', n => n !== 5), elObj.checkForAllDayObjs(
o => o.buttonEl.getAttribute('tabindex') === '-1',
n => n !== 5,
),
).to.be.true; ).to.be.true;
}); });

View file

@ -34,7 +34,7 @@ html`
}}> }}>
This is a dialog This is a dialog
<button <button
@click=${e => e.target.dispatchEvent(new Event('close', { bubbles: true }))} @click=${e => e.target.dispatchEvent(new Event('dialog-close', { bubbles: true }))}
>x</button> >x</button>
<div> <div>
<button slot="invoker"> <button slot="invoker">

View file

@ -1,16 +1,17 @@
import { OverlayController, withModalDialogConfig, OverlayMixin } from '@lion/overlays'; import { withModalDialogConfig, OverlayMixin } from '@lion/overlays';
import { LitElement, html } from '@lion/core'; import { LitElement, html } from '@lion/core';
export class LionDialog extends OverlayMixin(LitElement) { export class LionDialog extends OverlayMixin(LitElement) {
constructor() {
super();
this.closeEventName = 'dialog-close';
}
// eslint-disable-next-line class-methods-use-this // eslint-disable-next-line class-methods-use-this
_defineOverlay({ contentNode, invokerNode }) { _defineOverlayConfig() {
return new OverlayController({ return {
...withModalDialogConfig(), ...withModalDialogConfig(),
elementToFocusAfterHide: invokerNode, };
contentNode,
invokerNode,
...this.config, // lit-property set by user for overrides
});
} }
_setupOpenCloseListeners() { _setupOpenCloseListeners() {
@ -21,12 +22,10 @@ export class LionDialog extends OverlayMixin(LitElement) {
this.opened = !this.opened; this.opened = !this.opened;
}; };
this._overlayCtrl.invokerNode.addEventListener('click', this.__toggle); this._overlayCtrl.invokerNode.addEventListener('click', this.__toggle);
this._overlayCtrl.contentNode.addEventListener('close', this.__close);
} }
_teardownOpenCloseListeners() { _teardownOpenCloseListeners() {
this._overlayCtrl.invokerNode.removeEventListener('click', this.__toggle); this._overlayCtrl.invokerNode.removeEventListener('click', this.__toggle);
this._overlayCtrl.contentNode.removeEventListener('close', this.__close);
} }
render() { render() {

View file

@ -82,7 +82,7 @@ storiesOf('Overlays Specific WC | Dialog', module)
Hello! You can close this notification here: Hello! You can close this notification here:
<lion-button <lion-button
class="close-button" class="close-button"
@click=${e => e.target.dispatchEvent(new Event('close', { bubbles: true }))} @click=${e => e.target.dispatchEvent(new Event('dialog-close', { bubbles: true }))}
></lion-button ></lion-button
> >
</div> </div>
@ -98,7 +98,7 @@ storiesOf('Overlays Specific WC | Dialog', module)
Hello! You can close this notification here: Hello! You can close this notification here:
<lion-button <lion-button
class="close-button" class="close-button"
@click=${e => e.target.dispatchEvent(new Event('close', { bubbles: true }))} @click=${e => e.target.dispatchEvent(new Event('dialog-close', { bubbles: true }))}
></lion-button ></lion-button
> >
</div> </div>
@ -123,7 +123,7 @@ storiesOf('Overlays Specific WC | Dialog', module)
Hello! You can close this notification here: Hello! You can close this notification here:
<lion-button <lion-button
class="close-button" class="close-button"
@click=${e => e.target.dispatchEvent(new Event('close', { bubbles: true }))} @click=${e => e.target.dispatchEvent(new Event('dialog-close', { bubbles: true }))}
></lion-button ></lion-button
> >
</div> </div>

View file

@ -35,7 +35,9 @@ describe('lion-dialog', () => {
<lion-dialog> <lion-dialog>
<div slot="content" class="dialog"> <div slot="content" class="dialog">
Hey there Hey there
<button @click=${e => e.target.dispatchEvent(new Event('close', { bubbles: true }))}> <button
@click=${e => e.target.dispatchEvent(new Event('dialog-close', { bubbles: true }))}
>
x x
</button> </button>
</div> </div>

View file

@ -177,16 +177,28 @@ describe('<lion-fieldset>', () => {
expect(el.modelValue).to.deep.equal({ expect(el.modelValue).to.deep.equal({
lastName: 'Bar', lastName: 'Bar',
newfieldset: { newfieldset: {
'hobbies[]': [{ checked: true, value: 'chess' }, { checked: false, value: 'football' }], 'hobbies[]': [
'gender[]': [{ checked: false, value: 'male' }, { checked: false, value: 'female' }], { checked: true, value: 'chess' },
{ checked: false, value: 'football' },
],
'gender[]': [
{ checked: false, value: 'male' },
{ checked: false, value: 'female' },
],
color: { checked: false, value: 'blue' }, color: { checked: false, value: 'blue' },
}, },
}); });
el.modelValue = { el.modelValue = {
lastName: 2, lastName: 2,
newfieldset: { newfieldset: {
'hobbies[]': [{ checked: true, value: 'chess' }, { checked: false, value: 'baseball' }], 'hobbies[]': [
'gender[]': [{ checked: false, value: 'male' }, { checked: false, value: 'female' }], { checked: true, value: 'chess' },
{ checked: false, value: 'baseball' },
],
'gender[]': [
{ checked: false, value: 'male' },
{ checked: false, value: 'female' },
],
color: { checked: false, value: 'blue' }, color: { checked: false, value: 'blue' },
}, },
}; };
@ -546,7 +558,10 @@ describe('<lion-fieldset>', () => {
expect(fieldset.formElements['hobbies[]'][0].serializedValue).to.equal('Bar-serialized'); expect(fieldset.formElements['hobbies[]'][0].serializedValue).to.equal('Bar-serialized');
expect(fieldset.serializeGroup()).to.deep.equal({ expect(fieldset.serializeGroup()).to.deep.equal({
'hobbies[]': ['Bar-serialized', { checked: false, value: 'rugby' }], 'hobbies[]': ['Bar-serialized', { checked: false, value: 'rugby' }],
'gender[]': [{ checked: false, value: 'male' }, { checked: false, value: 'female' }], 'gender[]': [
{ checked: false, value: 'male' },
{ checked: false, value: 'female' },
],
color: { checked: false, value: 'blue' }, color: { checked: false, value: 'blue' },
}); });
}); });
@ -562,15 +577,27 @@ describe('<lion-fieldset>', () => {
fieldset.formElements.color.modelValue = { checked: false, value: 'blue' }; fieldset.formElements.color.modelValue = { checked: false, value: 'blue' };
expect(fieldset.serializeGroup()).to.deep.equal({ expect(fieldset.serializeGroup()).to.deep.equal({
'hobbies[]': [{ checked: true, value: 'football' }, { checked: false, value: 'rugby' }], 'hobbies[]': [
'gender[]': [{ checked: true, value: 'male' }, { checked: false, value: 'female' }], { checked: true, value: 'football' },
{ checked: false, value: 'rugby' },
],
'gender[]': [
{ checked: true, value: 'male' },
{ checked: false, value: 'female' },
],
color: { checked: false, value: 'blue' }, color: { checked: false, value: 'blue' },
}); });
fieldset.formElements.color.disabled = true; fieldset.formElements.color.disabled = true;
expect(fieldset.serializeGroup()).to.deep.equal({ expect(fieldset.serializeGroup()).to.deep.equal({
'hobbies[]': [{ checked: true, value: 'football' }, { checked: false, value: 'rugby' }], 'hobbies[]': [
'gender[]': [{ checked: true, value: 'male' }, { checked: false, value: 'female' }], { checked: true, value: 'football' },
{ checked: false, value: 'rugby' },
],
'gender[]': [
{ checked: true, value: 'male' },
{ checked: false, value: 'female' },
],
}); });
}); });
@ -594,8 +621,14 @@ describe('<lion-fieldset>', () => {
expect(fieldset.serializeGroup()).to.deep.equal({ expect(fieldset.serializeGroup()).to.deep.equal({
comment: 'Foo', comment: 'Foo',
newfieldset: { newfieldset: {
'hobbies[]': [{ checked: false, value: 'chess' }, { checked: false, value: 'rugby' }], 'hobbies[]': [
'gender[]': [{ checked: false, value: 'male' }, { checked: false, value: 'female' }], { checked: false, value: 'chess' },
{ checked: false, value: 'rugby' },
],
'gender[]': [
{ checked: false, value: 'male' },
{ checked: false, value: 'female' },
],
color: { checked: false, value: 'blue' }, color: { checked: false, value: 'blue' },
}, },
}); });
@ -622,8 +655,14 @@ describe('<lion-fieldset>', () => {
expect(fieldset.serializeGroup()).to.deep.equal({ expect(fieldset.serializeGroup()).to.deep.equal({
comment: 'Foo', comment: 'Foo',
newfieldset: { newfieldset: {
'hobbies[]': [{ checked: false, value: 'chess' }, { checked: false, value: 'rugby' }], 'hobbies[]': [
'gender[]': [{ checked: false, value: 'male' }, { checked: false, value: 'female' }], { checked: false, value: 'chess' },
{ checked: false, value: 'rugby' },
],
'gender[]': [
{ checked: false, value: 'male' },
{ checked: false, value: 'female' },
],
}, },
}); });
@ -631,8 +670,14 @@ describe('<lion-fieldset>', () => {
expect(fieldset.serializeGroup()).to.deep.equal({ expect(fieldset.serializeGroup()).to.deep.equal({
comment: 'Foo', comment: 'Foo',
newfieldset: { newfieldset: {
'hobbies[]': [{ checked: false, value: 'chess' }, { checked: false, value: 'rugby' }], 'hobbies[]': [
'gender[]': [{ checked: false, value: 'male' }, { checked: false, value: 'female' }], { checked: false, value: 'chess' },
{ checked: false, value: 'rugby' },
],
'gender[]': [
{ checked: false, value: 'male' },
{ checked: false, value: 'female' },
],
color: { checked: false, value: 'blue' }, color: { checked: false, value: 'blue' },
}, },
}); });
@ -647,8 +692,14 @@ describe('<lion-fieldset>', () => {
fieldset.formElements['gender[]'][1].modelValue = { checked: false, value: 'female' }; fieldset.formElements['gender[]'][1].modelValue = { checked: false, value: 'female' };
fieldset.formElements.color.modelValue = { checked: false, value: 'blue' }; fieldset.formElements.color.modelValue = { checked: false, value: 'blue' };
expect(fieldset.serializeGroup()).to.deep.equal({ expect(fieldset.serializeGroup()).to.deep.equal({
'hobbies[]': [{ checked: false, value: 'chess' }, { checked: false, value: 'rugby' }], 'hobbies[]': [
'gender[]': [{ checked: false, value: 'male' }, { checked: false, value: 'female' }], { checked: false, value: 'chess' },
{ checked: false, value: 'rugby' },
],
'gender[]': [
{ checked: false, value: 'male' },
{ checked: false, value: 'female' },
],
color: { checked: false, value: 'blue' }, color: { checked: false, value: 'blue' },
}); });
}); });

View file

@ -1,6 +1,6 @@
import { html, ifDefined, render } from '@lion/core'; import { html, ifDefined, render } from '@lion/core';
import { LionInputDate } from '@lion/input-date'; import { LionInputDate } from '@lion/input-date';
import { OverlayController, withModalDialogConfig, OverlayMixin } from '@lion/overlays'; import { withModalDialogConfig, OverlayMixin } from '@lion/overlays';
import '@lion/calendar/lion-calendar.js'; import '@lion/calendar/lion-calendar.js';
import './lion-calendar-overlay-frame.js'; import './lion-calendar-overlay-frame.js';
@ -255,17 +255,14 @@ export class LionInputDatepicker extends OverlayMixin(LionInputDate) {
/** /**
* @override Configures OverlayMixin * @override Configures OverlayMixin
* @desc returns an instance of a (dynamic) overlay controller * @desc overrides default configuration options for this component
* @returns {OverlayController} * @returns {Object}
*/ */
// eslint-disable-next-line class-methods-use-this // eslint-disable-next-line class-methods-use-this
_defineOverlay({ contentNode, invokerNode }) { _defineOverlayConfig() {
const ctrl = new OverlayController({ return {
...withModalDialogConfig(), ...withModalDialogConfig(),
contentNode, };
invokerNode,
});
return ctrl;
} }
async __openCalendarOverlay() { async __openCalendarOverlay() {

View file

@ -53,7 +53,7 @@ const template = html`
<button slot="invoker">Click me!</button> <button slot="invoker">Click me!</button>
<div slot="content"> <div slot="content">
<div>Hello, World!</div> <div>Hello, World!</div>
<button @click=${e => e.target.dispatchEvent(new Event('close', { bubbles: true }))}> <button @click=${e => e.target.dispatchEvent(new Event('dialog-close', { bubbles: true }))}>
Close Close
</button> </button>
</div> </div>

View file

@ -152,7 +152,7 @@ export class OverlayController {
// TODO: Instead, prefetch it or use a preloader-manager to load it during idle time // TODO: Instead, prefetch it or use a preloader-manager to load it during idle time
this.constructor.popperModule = preloadPopper(); this.constructor.popperModule = preloadPopper();
} }
this.__mergePopperConfigs(this.config.popperConfig || {}); this.__mergePopperConfigs(cfgToAdd.popperConfig || {});
} }
this._handleFeatures({ phase: 'init' }); this._handleFeatures({ phase: 'init' });
} }

View file

@ -1,4 +1,5 @@
import { render, dedupeMixin } from '@lion/core'; import { render, dedupeMixin } from '@lion/core';
import { OverlayController } from './OverlayController.js';
/** /**
* @type {Function()} * @type {Function()}
@ -18,12 +19,16 @@ export const OverlayMixin = dedupeMixin(
config: { config: {
type: Object, type: Object,
}, },
closeEventName: {
type: String,
},
}; };
} }
constructor() { constructor() {
super(); super();
this.config = {}; this.config = {};
this.closeEventName = 'overlay-close';
} }
get opened() { get opened() {
@ -59,10 +64,29 @@ export const OverlayMixin = dedupeMixin(
/** /**
* @overridable method `_defineOverlay` * @overridable method `_defineOverlay`
* @desc returns an instance of a (dynamic) overlay controller * @desc returns an instance of a (dynamic) overlay controller
* In case overriding _defineOverlayConfig is not enough
* @returns {OverlayController} * @returns {OverlayController}
*/ */
// eslint-disable-next-line // eslint-disable-next-line
_defineOverlay({ contentNode, invokerNode }) {} _defineOverlay({ contentNode, invokerNode }) {
return new OverlayController({
contentNode,
invokerNode,
...this._defineOverlayConfig(),
...this.config,
});
}
/**
* @overridable method `_defineOverlay`
* @desc returns an object with default configuration options for your overlay component.
* This is generally speaking easier to override than _defineOverlay method entirely.
* @returns {OverlayController}
*/
// eslint-disable-next-line
_defineOverlayConfig() {
return {};
}
/** /**
* @overridable * @overridable
@ -84,6 +108,14 @@ export const OverlayMixin = dedupeMixin(
super.connectedCallback(); super.connectedCallback();
} }
this._createOverlay(); this._createOverlay();
// Default close event catcher on the contentNode which is useful if people want to close
// their overlay but the content is not in the global root node (nowhere near the overlay component)
this.__close = () => {
this.opened = false;
};
this._overlayCtrl.contentNode.addEventListener(this.closeEventName, this.__close);
this._setupOpenCloseListeners(); this._setupOpenCloseListeners();
this.__syncOpened(); this.__syncOpened();
this.__syncPopper(); this.__syncPopper();
@ -91,10 +123,8 @@ export const OverlayMixin = dedupeMixin(
firstUpdated(c) { firstUpdated(c) {
super.firstUpdated(c); super.firstUpdated(c);
if (this._overlayCtrl.config.placementMode === 'local') {
this._createOutletForLocalOverlay(); this._createOutletForLocalOverlay();
} }
}
updated(c) { updated(c) {
super.updated(c); super.updated(c);
@ -107,6 +137,7 @@ export const OverlayMixin = dedupeMixin(
if (super.disconnectedCallback) { if (super.disconnectedCallback) {
super.disconnectedCallback(); super.disconnectedCallback();
} }
this._overlayCtrl.contentNode.removeEventListener(this.closeEventName, this.__close);
this._teardownOpenCloseListeners(); this._teardownOpenCloseListeners();
} }
@ -114,7 +145,8 @@ export const OverlayMixin = dedupeMixin(
return Array.from(this.children).find(child => child.slot === 'invoker'); return Array.from(this.children).find(child => child.slot === 'invoker');
} }
// FIXME: This should be refactored to Array.from(this.children).find(child => child.slot === 'content') // FIXME: This should be refactored to
// Array.from(this.children).find(child => child.slot === 'content')
// When this issue is fixed https://github.com/ing-bank/lion/issues/382 // When this issue is fixed https://github.com/ing-bank/lion/issues/382
get _overlayContentNode() { get _overlayContentNode() {
const contentNode = this.querySelector('[slot=content]'); const contentNode = this.querySelector('[slot=content]');
@ -184,7 +216,7 @@ export const OverlayMixin = dedupeMixin(
__syncPopper() { __syncPopper() {
if (this._overlayCtrl) { if (this._overlayCtrl) {
// TODO: Use updateConfig directly.. but first check if this sync is even still needed! Maybe we can remove it. // TODO: Use updateConfig directly.. But maybe we can remove this entirely.
this._overlayCtrl.updatePopperConfig(this.config.popperConfig); this._overlayCtrl.updatePopperConfig(this.config.popperConfig);
} }
} }

View file

@ -7,7 +7,6 @@ import {
withDropdownConfig, withDropdownConfig,
withModalDialogConfig, withModalDialogConfig,
OverlayMixin, OverlayMixin,
OverlayController,
} from '../index.js'; } from '../index.js';
function renderOffline(litHtmlTemplate) { function renderOffline(litHtmlTemplate) {
@ -96,14 +95,16 @@ const overlayDemoStyle = css`
customElements.define( customElements.define(
'lion-demo-overlay', 'lion-demo-overlay',
class extends OverlayMixin(LitElement) { class extends OverlayMixin(LitElement) {
constructor() {
super();
this.closeEventName = 'demo-overlay-close';
}
// eslint-disable-next-line class-methods-use-this // eslint-disable-next-line class-methods-use-this
_defineOverlay({ contentNode, invokerNode }) { _defineOverlayConfig() {
return new OverlayController({ return {
placementMode: 'global', // have to set a default placementMode: 'global', // have to set a default
contentNode, };
invokerNode,
...this.config,
});
} }
_setupOpenCloseListeners() { _setupOpenCloseListeners() {
@ -114,12 +115,10 @@ customElements.define(
this.opened = !this.opened; this.opened = !this.opened;
}; };
this._overlayCtrl.invokerNode.addEventListener('click', this.__toggle); this._overlayCtrl.invokerNode.addEventListener('click', this.__toggle);
this._overlayCtrl.contentNode.addEventListener('close', this.__close);
} }
_teardownOpenCloseListeners() { _teardownOpenCloseListeners() {
this._overlayCtrl.invokerNode.removeEventListener('click', this.__toggle); this._overlayCtrl.invokerNode.removeEventListener('click', this.__toggle);
this._overlayCtrl.contentNode.removeEventListener('close', this.__close);
} }
render() { render() {
@ -161,7 +160,8 @@ storiesOf('Overlay System | Overlay as a WC', module)
Hello! You can close this notification here: Hello! You can close this notification here:
<lion-button <lion-button
class="close-button" class="close-button"
@click=${e => e.target.dispatchEvent(new Event('close', { bubbles: true }))} @click=${e =>
e.target.dispatchEvent(new Event('demo-overlay-close', { bubbles: true }))}
></lion-button ></lion-button
> >
</div> </div>
@ -179,7 +179,8 @@ storiesOf('Overlay System | Overlay as a WC', module)
Hello! You can close this notification here: Hello! You can close this notification here:
<lion-button <lion-button
class="close-button" class="close-button"
@click=${e => e.target.dispatchEvent(new Event('close', { bubbles: true }))} @click=${e =>
e.target.dispatchEvent(new Event('demo-overlay-close', { bubbles: true }))}
></lion-button ></lion-button
> >
</div> </div>
@ -211,7 +212,8 @@ storiesOf('Overlay System | Overlay as a WC', module)
Hello! You can close this notification here: Hello! You can close this notification here:
<lion-button <lion-button
class="close-button" class="close-button"
@click=${e => e.target.dispatchEvent(new Event('close', { bubbles: true }))} @click=${e =>
e.target.dispatchEvent(new Event('demo-overlay-close', { bubbles: true }))}
></lion-button ></lion-button
> >
</div> </div>
@ -275,7 +277,8 @@ storiesOf('Overlay System | Overlay as a WC', module)
Hello! You can close this notification here: Hello! You can close this notification here:
<lion-button <lion-button
class="close-button" class="close-button"
@click=${e => e.target.dispatchEvent(new Event('close', { bubbles: true }))} @click=${e =>
e.target.dispatchEvent(new Event('demo-overlay-close', { bubbles: true }))}
></lion-button ></lion-button
> >
</div> </div>
@ -410,7 +413,7 @@ storiesOf('Overlay System | Overlay as a WC', module)
Hello! You can close this notification here: Hello! You can close this notification here:
<lion-button <lion-button
class="close-button" class="close-button"
@click=${e => e.target.dispatchEvent(new Event('close', { bubbles: true }))} @click=${e => e.target.dispatchEvent(new Event('demo-overlay-close', { bubbles: true }))}
></lion-button ></lion-button
> >
</div> </div>

View file

@ -1,5 +1,5 @@
import { html, css, LitElement, SlotMixin } from '@lion/core'; import { html, css, LitElement, SlotMixin } from '@lion/core';
import { OverlayController, withDropdownConfig, OverlayMixin } from '@lion/overlays'; import { withDropdownConfig, OverlayMixin } from '@lion/overlays';
import { FormControlMixin, InteractionStateMixin, FormRegistrarMixin } from '@lion/field'; import { FormControlMixin, InteractionStateMixin, FormRegistrarMixin } from '@lion/field';
import { ValidateMixin } from '@lion/validate'; import { ValidateMixin } from '@lion/validate';
import './differentKeyNamesShimIE.js'; import './differentKeyNamesShimIE.js';
@ -601,12 +601,10 @@ export class LionSelectRich extends OverlayMixin(
} }
// eslint-disable-next-line class-methods-use-this // eslint-disable-next-line class-methods-use-this
_defineOverlay({ invokerNode, contentNode } = {}) { _defineOverlayConfig() {
return new OverlayController({ return {
...withDropdownConfig(), ...withDropdownConfig(),
contentNode, };
invokerNode,
});
} }
__setupOverlay() { __setupOverlay() {

View file

@ -17,7 +17,7 @@ e invoker element is focused.
### Installation ### Installation
```sh ```sh
npm i --save @lion/popup npm i --save @lion/tooltip
``` ```
```js ```js
@ -28,7 +28,7 @@ import '@lion/tooltip/lion-tooltip.js';
```html ```html
<lion-tooltip> <lion-tooltip>
<div slot="content" class="tooltip">This is a popup<div> <div slot="content" class="tooltip">This is a tooltip<div>
<a slot="invoker" href="https://www.google.com/"> <a slot="invoker" href="https://www.google.com/">
Popup on link Popup on link
</a> </a>

View file

@ -33,8 +33,7 @@
], ],
"dependencies": { "dependencies": {
"@lion/core": "^0.3.0", "@lion/core": "^0.3.0",
"@lion/overlays": "^0.6.4", "@lion/overlays": "^0.6.4"
"@lion/popup": "^0.3.20"
}, },
"devDependencies": { "devDependencies": {
"@lion/button": "^0.3.43", "@lion/button": "^0.3.43",

View file

@ -1,21 +1,20 @@
import { OverlayMixin, OverlayController } from '@lion/overlays'; import { OverlayMixin } from '@lion/overlays';
import { LitElement, html } from '@lion/core'; import { LitElement, html } from '@lion/core';
export class LionTooltip extends OverlayMixin(LitElement) { export class LionTooltip extends OverlayMixin(LitElement) {
constructor() { constructor() {
super(); super();
this.closeEventName = 'tooltip-close';
this.mouseActive = false; this.mouseActive = false;
this.keyActive = false; this.keyActive = false;
} }
_defineOverlay({ contentNode, invokerNode }) { // eslint-disable-next-line class-methods-use-this
return new OverlayController({ _defineOverlayConfig() {
return {
placementMode: 'local', // have to set a default placementMode: 'local', // have to set a default
elementToFocusAfterHide: null, elementToFocusAfterHide: null,
contentNode, };
invokerNode,
...this.config,
});
} }
_setupOpenCloseListeners() { _setupOpenCloseListeners() {