195 lines
4.6 KiB
JavaScript
195 lines
4.6 KiB
JavaScript
/*! DSFR v1.11.2 | SPDX-License-Identifier: MIT | License-Filename: LICENSE.md | restricted use (see terms and conditions) */
|
|
|
|
const config = {
|
|
prefix: 'fr',
|
|
namespace: 'dsfr',
|
|
organisation: '@gouvfr',
|
|
version: '1.11.2'
|
|
};
|
|
|
|
const api = window[config.namespace];
|
|
|
|
const TooltipSelector = {
|
|
TOOLTIP: api.internals.ns.selector('tooltip'),
|
|
SHOWN: api.internals.ns.selector('tooltip--shown'),
|
|
BUTTON: api.internals.ns.selector('btn--tooltip')
|
|
};
|
|
|
|
const TooltipReferentState = {
|
|
FOCUS: 1 << 0,
|
|
HOVER: 1 << 1
|
|
};
|
|
|
|
class TooltipReferent extends api.core.PlacementReferent {
|
|
constructor () {
|
|
super();
|
|
this._state = 0;
|
|
}
|
|
|
|
static get instanceClassName () {
|
|
return 'TooltipReferent';
|
|
}
|
|
|
|
init () {
|
|
super.init();
|
|
this.listen('focusin', this.focusIn.bind(this));
|
|
this.listen('focusout', this.focusOut.bind(this));
|
|
if (!this.matches(TooltipSelector.BUTTON)) {
|
|
const mouseover = this.mouseover.bind(this);
|
|
this.listen('mouseover', mouseover);
|
|
this.placement.listen('mouseover', mouseover);
|
|
const mouseout = this.mouseout.bind(this);
|
|
this.listen('mouseout', mouseout);
|
|
this.placement.listen('mouseout', mouseout);
|
|
}
|
|
this.addEmission(api.core.RootEmission.KEYDOWN, this._keydown.bind(this));
|
|
this.listen('click', this._click.bind(this));
|
|
this.addEmission(api.core.RootEmission.CLICK, this._clickOut.bind(this));
|
|
}
|
|
|
|
_click () {
|
|
this.focus();
|
|
}
|
|
|
|
_clickOut (target) {
|
|
if (!this.node.contains(target)) this.blur();
|
|
}
|
|
|
|
_keydown (keyCode) {
|
|
switch (keyCode) {
|
|
case api.core.KeyCodes.ESCAPE:
|
|
this.blur();
|
|
this.close();
|
|
break;
|
|
}
|
|
}
|
|
|
|
close () {
|
|
this.state = 0;
|
|
}
|
|
|
|
get state () {
|
|
return this._state;
|
|
}
|
|
|
|
set state (value) {
|
|
if (this._state === value) return;
|
|
this.isShown = value > 0;
|
|
this._state = value;
|
|
}
|
|
|
|
focusIn () {
|
|
this.state |= TooltipReferentState.FOCUS;
|
|
}
|
|
|
|
focusOut () {
|
|
this.state &= ~TooltipReferentState.FOCUS;
|
|
}
|
|
|
|
mouseover () {
|
|
this.state |= TooltipReferentState.HOVER;
|
|
}
|
|
|
|
mouseout () {
|
|
this.state &= ~TooltipReferentState.HOVER;
|
|
}
|
|
}
|
|
|
|
const ns = name => `${config.prefix}-${name}`;
|
|
|
|
ns.selector = (name, notation) => {
|
|
if (notation === undefined) notation = '.';
|
|
return `${notation}${ns(name)}`;
|
|
};
|
|
|
|
ns.attr = (name) => `data-${ns(name)}`;
|
|
|
|
ns.attr.selector = (name, value) => {
|
|
let result = ns.attr(name);
|
|
if (value !== undefined) result += `="${value}"`;
|
|
return `[${result}]`;
|
|
};
|
|
|
|
ns.event = (type) => `${config.namespace}.${type}`;
|
|
|
|
ns.emission = (domain, type) => `emission:${domain}.${type}`;
|
|
|
|
const TooltipEvent = {
|
|
SHOW: ns.event('show'),
|
|
HIDE: ns.event('hide')
|
|
};
|
|
|
|
const TooltipState = {
|
|
HIDDEN: 'hidden',
|
|
SHOWN: 'shown',
|
|
HIDING: 'hiding'
|
|
};
|
|
|
|
class Tooltip extends api.core.Placement {
|
|
constructor () {
|
|
super(api.core.PlacementMode.AUTO, [api.core.PlacementPosition.TOP, api.core.PlacementPosition.BOTTOM], [api.core.PlacementAlign.CENTER, api.core.PlacementAlign.START, api.core.PlacementAlign.END]);
|
|
this.modifier = '';
|
|
this._state = TooltipState.HIDDEN;
|
|
}
|
|
|
|
static get instanceClassName () {
|
|
return 'Tooltip';
|
|
}
|
|
|
|
init () {
|
|
super.init();
|
|
this.register(`[aria-describedby="${this.id}"]`, TooltipReferent);
|
|
this.listen('transitionend', this.transitionEnd.bind(this));
|
|
}
|
|
|
|
transitionEnd () {
|
|
if (this._state === TooltipState.HIDING) {
|
|
this._state = TooltipState.HIDDEN;
|
|
this.isShown = false;
|
|
}
|
|
}
|
|
|
|
get isShown () {
|
|
return super.isShown;
|
|
}
|
|
|
|
set isShown (value) {
|
|
if (!this.isEnabled) return;
|
|
switch (true) {
|
|
case value:
|
|
this._state = TooltipState.SHOWN;
|
|
this.addClass(TooltipSelector.SHOWN);
|
|
this.dispatch(TooltipEvent.SHOW);
|
|
super.isShown = true;
|
|
break;
|
|
|
|
case this.isShown && !value && this._state === TooltipState.SHOWN:
|
|
this._state = TooltipState.HIDING;
|
|
this.removeClass(TooltipSelector.SHOWN);
|
|
break;
|
|
|
|
case this.isShown && !value && this._state === TooltipState.HIDDEN:
|
|
this.dispatch(TooltipEvent.HIDE);
|
|
super.isShown = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
render () {
|
|
super.render();
|
|
let x = this.referentRect.center - this.rect.center;
|
|
const limit = this.rect.width * 0.5 - 8;
|
|
if (x < -limit) x = -limit;
|
|
if (x > limit) x = limit;
|
|
this.setProperty('--arrow-x', `${x.toFixed(2)}px`);
|
|
}
|
|
}
|
|
|
|
api.tooltip = {
|
|
Tooltip: Tooltip,
|
|
TooltipSelector: TooltipSelector,
|
|
TooltipEvent: TooltipEvent
|
|
};
|
|
|
|
api.internals.register(api.tooltip.TooltipSelector.TOOLTIP, api.tooltip.Tooltip);
|
|
//# sourceMappingURL=tooltip.module.js.map
|