import { css, html, dedupeMixin } from '@lion/core'; /** * @typedef {import('../types/OverlayConfig').OverlayConfig} OverlayConfig * @typedef {import('../types/ArrowMixinTypes').ArrowMixin} ArrowMixin * */ /** * @type {ArrowMixin} */ export const ArrowMixinImplementation = superclass => class ArrowMixin extends superclass { static get properties() { return { hasArrow: { type: Boolean, reflect: true, attribute: 'has-arrow', }, }; } static get styles() { return [ super.styles ? super.styles : [], css` :host { --tooltip-arrow-width: 12px; --tooltip-arrow-height: 8px; } .arrow { display: none; position: absolute; width: var(--tooltip-arrow-width); height: var(--tooltip-arrow-height); } :host([has-arrow]) .arrow { display: block; } .arrow svg { display: block; } [x-placement^='bottom'] .arrow { top: calc(-1 * var(--tooltip-arrow-height)); transform: rotate(180deg); } [x-placement^='left'] .arrow { right: calc( -1 * (var(--tooltip-arrow-height) + (var(--tooltip-arrow-width) - var(--tooltip-arrow-height)) / 2) ); transform: rotate(270deg); } [x-placement^='right'] .arrow { left: calc( -1 * (var(--tooltip-arrow-height) + (var(--tooltip-arrow-width) - var(--tooltip-arrow-height)) / 2) ); transform: rotate(90deg); } `, ]; } constructor() { super(); this.hasArrow = true; this.__setupRepositionCompletePromise(); } render() { return html`
${this._arrowNodeTemplate()}
`; } _arrowNodeTemplate() { return html`
${this._arrowTemplate()}
`; } // eslint-disable-next-line class-methods-use-this _arrowTemplate() { return html` `; } /** * @overridable method `_defineOverlay` * @desc Overrides arrow and keepTogether modifier to be enabled, * and adds onCreate and onUpdate hooks to sync from popper state * @returns {OverlayConfig} */ // eslint-disable-next-line _defineOverlayConfig() { if (!this.hasArrow) { return super._defineOverlayConfig(); } return { ...super._defineOverlayConfig(), popperConfig: { ...super._defineOverlayConfig()?.popperConfig, placement: 'top', modifiers: { ...super._defineOverlayConfig()?.popperConfig?.modifiers, keepTogether: { ...super._defineOverlayConfig()?.popperConfig?.modifiers?.keepTogether, enabled: true, }, arrow: { ...super._defineOverlayConfig()?.popperConfig?.modifiers?.arrow, enabled: true, }, }, /** @param {import("popper.js").default.Data} data */ onCreate: data => { this.__syncFromPopperState(data); }, /** @param {import("popper.js").default.Data} data */ onUpdate: data => { this.__syncFromPopperState(data); }, }, }; } __setupRepositionCompletePromise() { this.repositionComplete = new Promise(resolve => { this.__repositionCompleteResolver = resolve; }); } get _arrowNode() { return /** @type {ShadowRoot} */ (this.shadowRoot).querySelector('[x-arrow]'); } /** * @param {import("popper.js").default.Data} data */ __syncFromPopperState(data) { if (!data) { return; } if ( this._arrowNode && data.placement !== /** @type {Element & {placement:string}} */ (this._arrowNode).placement ) { /** @type {function} */ (this.__repositionCompleteResolver)(data.placement); this.__setupRepositionCompletePromise(); } } }; export const ArrowMixin = dedupeMixin(ArrowMixinImplementation);