@esri/calcite-components
Version:
Web Components for Esri's Calcite Design System.
131 lines (130 loc) • 8.77 kB
JavaScript
/* COPYRIGHT Esri - https://js.arcgis.com/5.1/LICENSE.txt */
import { c as customElement } from "../../chunks/runtime.js";
import { keyed } from "lit/directives/keyed.js";
import { css, html } from "lit";
import { LitElement, createEvent, safeClassMap } from "@arcgis/lumina";
import { createRef, ref } from "lit/directives/ref.js";
import { useDirection } from "@arcgis/lumina/controllers";
import { e as defaultOffsetDistance, r as reposition, c as connectFloatingUI, a as disconnectFloatingUI, h as hideFloatingUI, F as FloatingCSS } from "../../chunks/floating-ui.js";
import { t as toggleOpenClose } from "../../chunks/openCloseComponent.js";
import { F as FloatingArrow } from "../../chunks/FloatingArrow.js";
import { u as useTopLayer } from "../../chunks/useTopLayer.js";
import { u as useReferenceElement, r as referenceElementManager } from "../../chunks/manager.js";
const CSS = {
positionContainer: "position-container",
container: "container"
};
const styles = css`:host{display:contents;--calcite-internal-tooltip-padding-block: var(--calcite-spacing-sm);--calcite-internal-tooltip-padding-inline: var(--calcite-spacing-md)}:host([top-layer-disabled]){--calcite-floating-ui-z-index: var(--calcite-z-index-tooltip)}.position-container{inline-size:max-content;display:none;max-inline-size:100vw;max-block-size:100vh;inset-block-start:0;left:0;z-index:var(--calcite-floating-ui-z-index)}@starting-style{.position-container{opacity:0;inset-block-start:0;left:0}}.position-container{max-inline-size:var(--calcite-tooltip-max-size-x, 20rem);max-block-size:20rem}.position-container[popover]{padding:0;margin:0;border:none;background-color:transparent;overflow:visible;display:none}.position-container:popover-open{display:block}.position-container .calcite-floating-ui-anim{position:relative;transition-duration:var(--calcite-floating-ui-transition);transition-property:inset-block-start,left,opacity,display;transition-behavior:allow-discrete;opacity:0;box-shadow:0 0 16px #00000029;z-index:var(--calcite-z-index);border-radius:.25rem}.position-container[data-placement^=bottom] .calcite-floating-ui-anim{inset-block-start:-5px}.position-container[data-placement^=top] .calcite-floating-ui-anim{inset-block-start:5px}.position-container[data-placement^=left] .calcite-floating-ui-anim{left:5px}.position-container[data-placement^=right] .calcite-floating-ui-anim{left:-5px}.position-container[data-placement] .calcite-floating-ui-anim--active{opacity:1;inset-block-start:0;left:0}@starting-style{.position-container[data-placement] .calcite-floating-ui-anim--active{opacity:0}}.calcite-floating-ui-arrow{pointer-events:none;position:absolute;z-index:calc(var(--calcite-z-index) * -1);fill:var(--calcite-color-foreground-1)}.calcite-floating-ui-arrow__stroke{stroke:var(--calcite-color-border-3)}:host([scale=s]){--calcite-internal-tooltip-padding-block: var(--calcite-spacing-xxs);--calcite-internal-tooltip-padding-inline: var(--calcite-spacing-sm)}:host([scale=s]) .container{font-size:var(--calcite-font-size-relative-xs);line-height:var(--calcite-font-line-height-relative-snug)}:host([scale=l]) .container{font-size:var(--calcite-font-size-relative-base);line-height:var(--calcite-font-line-height-relative-snug)}.container{position:relative;overflow:hidden;font-size:var(--calcite-font-size-relative-sm);line-height:var(--calcite-font-line-height-relative-snug);font-weight:var(--calcite-font-weight-medium);word-wrap:break-word;word-break:break-word;padding-block:var(--calcite-internal-tooltip-padding-block);padding-inline:var(--calcite-internal-tooltip-padding-inline);border-radius:var(--calcite-tooltip-corner-radius, var(--calcite-corner-radius-round));color:var(--calcite-tooltip-text-color, var(--calcite-color-text-1));text-align:start}.position-container .calcite-floating-ui-anim{border-width:1px;border-style:solid;background-color:var(--calcite-tooltip-background-color, var(--calcite-color-foreground-1));border-color:var(--calcite-tooltip-border-color, var(--calcite-color-border-3));border-radius:var(--calcite-tooltip-corner-radius, var(--calcite-corner-radius-round))}.calcite-floating-ui-arrow{fill:var(--calcite-tooltip-background-color, var(--calcite-color-foreground-1))}.calcite-floating-ui-arrow__stroke{stroke:var(--calcite-tooltip-border-color, var(--calcite-color-border-3))}:host([hidden]){display:none}[hidden]{display:none}`;
const manager = referenceElementManager({ hover: true });
class Tooltip extends LitElement {
constructor() {
super(...arguments);
this.direction = useDirection();
this.referenceElementType = "hover";
this.referenceElementController = useReferenceElement({ manager })(this);
this.transitionProp = "opacity";
this.transitionRef = createRef();
this.topLayer = useTopLayer({
disabledOverride: () => this.open && !this.referenceEl,
target: () => this.floatingEl
})(this);
this.floatingLayout = "vertical";
this.closeOnClick = false;
this.offsetDistance = defaultOffsetDistance;
this.offsetSkidding = 0;
this.open = false;
this.overlayPositioning = "absolute";
this.placement = "auto";
this.pointerDisabled = false;
this.scale = "m";
this.topLayerDisabled = false;
this.calciteTooltipBeforeClose = createEvent({ cancelable: false });
this.calciteTooltipBeforeOpen = createEvent({ cancelable: false });
this.calciteTooltipClose = createEvent({ cancelable: false });
this.calciteTooltipOpen = createEvent({ cancelable: false });
}
static {
this.properties = { floatingLayout: [16, {}, { state: true }], referenceEl: [16, {}, { state: true }], closeOnClick: [7, {}, { reflect: true, type: Boolean }], label: 1, offsetDistance: [11, {}, { type: Number, reflect: true }], offsetSkidding: [11, {}, { reflect: true, type: Number }], open: [7, {}, { reflect: true, type: Boolean }], overlayPositioning: [3, {}, { reflect: true }], placement: [3, {}, { reflect: true }], pointerDisabled: [7, {}, { reflect: true, type: Boolean }], referenceElement: 1, scale: [3, {}, { reflect: true }], topLayerDisabled: [7, {}, { reflect: true, type: Boolean }] };
}
static {
this.styles = styles;
}
async reposition(delayed = false) {
const { referenceEl, placement, overlayPositioning, offsetDistance, offsetSkidding, arrowEl, floatingEl } = this;
return reposition(this, {
direction: this.direction,
floatingEl,
referenceEl,
overlayPositioning,
placement,
offsetDistance,
offsetSkidding,
arrowEl,
type: "tooltip"
}, delayed);
}
willUpdate(changes) {
if (changes.has("offsetDistance") && (this.hasUpdated || this.offsetDistance !== defaultOffsetDistance) || changes.has("offsetSkidding") && (this.hasUpdated || this.offsetSkidding !== 0) || changes.has("overlayPositioning") && (this.hasUpdated || this.overlayPositioning !== "absolute") || changes.has("placement") && (this.hasUpdated || this.placement !== "auto")) {
this.reposition(true);
}
if (changes.has("open") && (this.hasUpdated || this.open !== false)) {
this.openHandler();
}
if (changes.has("referenceElement") && !this.referenceElement && this.open) {
this.topLayer.hide();
}
}
updated(changes) {
if (changes.has("referenceEl")) {
connectFloatingUI(this);
}
}
disconnectedCallback() {
super.disconnectedCallback();
disconnectFloatingUI(this);
}
openHandler() {
toggleOpenClose(this);
this.reposition(true);
}
onBeforeOpen() {
this.calciteTooltipBeforeOpen.emit();
this.topLayer.show();
}
onOpen() {
this.calciteTooltipOpen.emit();
}
onBeforeClose() {
this.calciteTooltipBeforeClose.emit();
}
onClose() {
this.calciteTooltipClose.emit();
hideFloatingUI(this);
this.topLayer.hide();
}
setFloatingEl(el) {
this.floatingEl = el;
}
setArrowEl(el) {
this.arrowEl = el;
this.reposition(true);
}
render() {
const { referenceEl, label, open, pointerDisabled, floatingLayout } = this;
const displayed = referenceEl && open;
const hidden = !displayed;
const arrowNode = !pointerDisabled ? keyed("floating-arrow", FloatingArrow({ floatingLayout, ref: this.setArrowEl })) : null;
this.el.inert = hidden;
this.el.ariaLabel = label;
this.el.ariaLive = "polite";
this.el.role = "tooltip";
return html`<div class=${safeClassMap(CSS.positionContainer)} popover=manual ${ref(this.setFloatingEl)}><div class=${safeClassMap({
[FloatingCSS.animation]: true,
[FloatingCSS.animationActive]: displayed
})} ${ref(this.transitionRef)}>${arrowNode}<div class=${safeClassMap(CSS.container)}><slot></slot></div></div></div>`;
}
}
customElement("calcite-tooltip", Tooltip);
export {
Tooltip
};