import { TOOLTIP_DELAY_MS as s, TOOLTIP_KIND_MODIFIERS as c, TOOLTIP_STICKY_VALUES as p, TOOLTIP_DIRECTIONS as f } from "./tooltip-constants.js";
import { POPOVER_APPEND_TO_VALUES as m } from "../popover/popover-constants.js";
import { returnFirstEl as r, flushPromises as w, warnIfUnmounted as y, hasSlotContent as E, getUniqueString as S } from "../../common/utils/index.js";
import { getPopperOptions as a, createTippy as v, getAnchor as g } from "../popover/tippy-utils.js";
import { createElementBlock as h, openBlock as l, createCommentVNode as A, createElementVNode as T, withKeys as P, renderSlot as d, normalizeClass as L, createTextVNode as O, toDisplayString as b } from "vue";
import { _ as x } from "../../_plugin-vue_export-helper-CHgC5LLL.js";
const I = {
  compatConfig: { MODE: 3 },
  name: "DtTooltip",
  props: {
    /**
     * The id of the tooltip
     */
    id: {
      type: String,
      default() {
        return S();
      }
    },
    /**
     * If the popover does not fit in the direction described by "placement",
     * it will attempt to change its direction to the "fallbackPlacements"
     * if defined, otherwise it will automatically position to a new location
     * as it sees best fit. See
     * <a
     *   class="d-link"
     *   href="https://popper.js.org/docs/v2/modifiers/flip/#fallbackplacements"
     *   target="_blank"
     * >
     *   Popper.js docs
     * </a>
     * */
    fallbackPlacements: {
      type: Array,
      default: () => ["auto"]
    },
    /**
     * If true, applies inverted styles to the tooltip
     * @values true, false
     */
    inverted: {
      type: Boolean,
      default: !1
    },
    /**
     *  Displaces the tooltip from its reference element
     *  by the specified number of pixels. See
     *  <a
     *    class="d-link"
     *    href="https://atomiks.github.io/tippyjs/v6/all-props/#offset"
     *    target="_blank"
     *  >
     *    Tippy.js docs
     *  </a>
     */
    offset: {
      type: Array,
      default: () => [0, 12]
    },
    /**
     * The direction the popover displays relative to the anchor. See
     * <a
     *   class="d-link"
     *   href="https://atomiks.github.io/tippyjs/v6/all-props/#placement"
     *   target="_blank"
     * >
     *   Tippy.js docs
     * </a>
     * @values top, top-start, top-end,
     * right, right-start, right-end,
     * left, left-start, left-end,
     * bottom, bottom-start, bottom-end,
     * auto, auto-start, auto-end
     */
    placement: {
      type: String,
      default: "top",
      validator(e) {
        return f.includes(e);
      }
    },
    /**
     * If the tooltip sticks to the anchor. This is usually not needed, but can be needed
     * if the reference element's position is animating, or to automatically update the popover
     * position in those cases the DOM layout changes the reference element's position.
     * `true` enables it, `reference` only checks the "reference" rect for changes and `popper` only
     * checks the "popper" rect for changes. See
     * <a
     *   class="d-link"
     *   href="https://atomiks.github.io/tippyjs/v6/all-props/#sticky"
     *   target="_blank"
     * >
     *   Tippy.js docs
     * </a>
     * @values true, false, reference, popper
     */
    sticky: {
      type: [Boolean, String],
      default: !0,
      validator: (e) => p.includes(e)
    },
    /**
     * Sets the element to which the tooltip is going to append to.
     * 'body' will append to the nearest body (supports shadow DOM).
     * This prop is not reactive, must be set on initial render.
     * @values 'body', 'parent', HTMLElement,
     */
    appendTo: {
      type: [HTMLElement, String],
      default: "body",
      validator: (e) => m.includes(e) || e instanceof HTMLElement
    },
    /**
     * Additional css classes for the tooltip content element.
     * Can accept all of: String, Object, and Array, i.e. has the
     * same api as Vue's built-in handling of the class attribute.
     */
    contentClass: {
      type: [String, Object, Array],
      default: ""
    },
    /**
     * A provided message for the tooltip content
     */
    message: {
      type: String,
      default: ""
    },
    /**
     * Controls whether hover/focus causes the tooltip to appear.
     * Cannot be combined with the show prop. show value will be ignored.
     * by default this is true, if you override with false, the tooltip will never show up.
     */
    enabled: {
      type: Boolean,
      default: !0
    },
    /**
     * Controls whether the tooltip is shown. Leaving this null will have the tooltip trigger on mouseover by default.
     * If you set this value, the default mouseover behavior will be disabled and you can control it as you need.
     * Supports .sync modifier
     * @values null, true, false
     */
    show: {
      type: Boolean,
      default: null
    },
    /**
     * Whether the tooltip should have a transition effect (fade).
     */
    transition: {
      type: Boolean,
      default: !0
    },
    /**
     * Whether the tooltip will have a delay when being focused or moused over.
     * @values true, false
     */
    delay: {
      type: Boolean,
      default: !0
    },
    /**
     * Set a custom theme on the tooltip. See https://atomiks.github.io/tippyjs/v6/themes/
     */
    theme: {
      type: String,
      default: null
    },
    /**
     * External anchor id to use in those cases the anchor can't be provided via the slot.
     * For instance, using the combobox's input as the anchor for the popover.
     */
    externalAnchor: {
      type: String,
      default: null
    }
  },
  emits: [
    /**
     * Emitted when tooltip is shown or hidden
     *
     * @event shown
     * @type {Boolean}
     */
    "shown",
    /**
     * Sync show value
     *
     * @event update:show
     */
    "update:show"
  ],
  data() {
    return {
      TOOLTIP_KIND_MODIFIERS: c,
      hasSlotContent: E,
      tip: null,
      inTimer: null,
      // Internal state for whether the tooltip is shown. Changing the prop
      // will update this.
      internalShow: !1,
      // this is where the placement currently is, this can be different than
      // the placement prop when there is not enough available room for the tip
      // to display and it uses a fallback placement.
      currentPlacement: this.placement
    };
  },
  computed: {
    tippyProps() {
      return {
        offset: this.offset,
        delay: this.delay ? s : !1,
        placement: this.placement,
        sticky: this.sticky,
        theme: this.inverted ? "inverted" : this.theme,
        animation: this.transition ? "fade" : !1,
        // onShown only triggers when transition is truthy
        onShown: (e) => this.onShow(e, "onShown"),
        // onShown will always be called, but it will be called before the animation is complete
        onShow: (e) => this.onShow(e, "onShow"),
        onHidden: this.onHide,
        popperOptions: a({
          fallbackPlacements: this.fallbackPlacements,
          hasHideModifierEnabled: !0
        })
      };
    },
    anchor() {
      return this.externalAnchor ? document.body.querySelector(this.externalAnchor) : g(this.$refs.anchor);
    }
  },
  watch: {
    tippyProps: {
      handler: "setProps",
      deep: !0
    },
    show: {
      handler: function(e) {
        e !== null && this.enabled && (this.internalShow = e);
      },
      immediate: !0
    },
    internalShow(e) {
      !this.tip || !this.anchor || (e ? (this.setProps(), this.tip.show()) : this.tip.hide());
    },
    sticky(e) {
      this.tip.setProps({
        sticky: e
      });
    }
  },
  async mounted() {
    !this.enabled && this.show != null && (console.warn("Tooltip: You cannot use both the enabled and show props at the same time."), console.warn("The show prop will be ignored.")), this.tip = v(this.anchor, this.initOptions()), this.externalAnchor && (await w(), this.addExternalAnchorEventListeners()), y(r(this.$el), this.$options.name);
  },
  beforeUnmount() {
    var e, t;
    this.externalAnchor && this.removeExternalAnchorEventListeners(), (e = this.anchor) != null && e._tippy && ((t = this.tip) == null || t.destroy());
  },
  methods: {
    calculateAnchorZindex() {
      return r(this.$el).getRootNode().querySelector(
        `.d-modal[aria-hidden="false"],
          .d-modal--transparent[aria-hidden="false"],
          .d-modal:not([aria-hidden]),
          .d-modal--transparent:not([aria-hidden])`
      ) || // Special case because we don't have any dialtone drawer component yet. Render at 651 when
      // anchor of popover is within a drawer.
      r(this.$el).closest(".d-zi-drawer") ? 651 : 400;
    },
    hasVisibleFocus() {
      return this.anchor.matches(":focus-visible");
    },
    onEnterAnchor(e) {
      this.enabled && (this.delay && this.inTimer === null ? this.inTimer = setTimeout(() => {
        this.triggerShow(e);
      }, s) : this.triggerShow(e));
    },
    triggerShow(e) {
      e.type === "focusin" ? this.show === null && this.hasVisibleFocus() && (this.internalShow = !0) : this.show === null && (this.internalShow = !0);
    },
    onLeaveAnchor(e) {
      e.type === "keydown" && e.code !== "Escape" || (clearTimeout(this.inTimer), this.inTimer = null, this.triggerHide());
    },
    triggerHide() {
      this.show === null && (this.internalShow = !1);
    },
    onChangePlacement(e) {
      this.currentPlacement = e;
    },
    onHide() {
      var e;
      (e = this.tip) == null || e.unmount(), this.$emit("shown", !1), this.show !== null && this.$emit("update:show", !1);
    },
    onShow(e, t) {
      if (!this.tooltipHasContent(e))
        return !1;
      this.transition && t === "onShow" || (this.$emit("shown", !0), this.show !== null && this.$emit("update:show", !0));
    },
    setProps() {
      var e, t;
      !this.tip || !this.tip.setProps || !this.anchor || this.tip && this.tip.setProps && this.tip.setProps({
        ...this.tippyProps,
        // these need to be set here rather than in tippyProps because they are non-reactive
        appendTo: this.appendTo === "body" ? (t = (e = this.anchor) == null ? void 0 : e.getRootNode()) == null ? void 0 : t.querySelector("body") : this.appendTo,
        zIndex: this.calculateAnchorZindex()
      });
    },
    onMount() {
      this.setProps();
    },
    tooltipHasContent(e) {
      return e.props.content.textContent.trim().length !== 0;
    },
    // set initial options here. If any of the options need to dynamically change, they should be put in
    // tippyProps instead.
    initOptions() {
      return {
        content: this.$refs.content,
        arrow: '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="7"><path d="M 14.5,7 8,0 1.5,7 Z"/></svg>',
        // transition duration - same as our custom fade delay in dialtone-globals.less
        duration: 180,
        interactive: !1,
        trigger: "manual",
        hideOnClick: !1,
        // disable tooltip from displaying on touch devices
        touch: !1,
        onMount: this.onMount,
        showOnCreate: this.internalShow,
        popperOptions: a({
          hasHideModifierEnabled: !0
        })
      };
    },
    addExternalAnchorEventListeners() {
      ["focusin", "mouseenter"].forEach((e) => {
        var t;
        (t = this.anchor) == null || t.addEventListener(e, (n) => this.onEnterAnchor(n));
      }), ["focusout", "mouseleave", "keydown"].forEach((e) => {
        var t;
        (t = this.anchor) == null || t.addEventListener(e, (n) => this.onLeaveAnchor(n));
      });
    },
    removeExternalAnchorEventListeners() {
      ["focusin", "mouseenter"].forEach((e) => {
        var t;
        (t = this.anchor) == null || t.removeEventListener(e, (n) => this.onEnterAnchor(n));
      }), ["focusout", "mouseleave", "keydown"].forEach((e) => {
        var t;
        (t = this.anchor) == null || t.removeEventListener(e, (n) => this.onLeaveAnchor(n));
      });
    }
  }
}, k = { "data-qa": "dt-tooltip-container" }, C = ["id"];
function M(e, t, n, _, u, o) {
  return l(), h("div", k, [
    n.externalAnchor ? A("", !0) : (l(), h("span", {
      key: 0,
      ref: "anchor",
      "data-qa": "dt-tooltip-anchor",
      onFocusin: t[0] || (t[0] = (...i) => o.onEnterAnchor && o.onEnterAnchor(...i)),
      onFocusout: t[1] || (t[1] = (...i) => o.onLeaveAnchor && o.onLeaveAnchor(...i)),
      onMouseenter: t[2] || (t[2] = (...i) => o.onEnterAnchor && o.onEnterAnchor(...i)),
      onMouseleave: t[3] || (t[3] = (...i) => o.onLeaveAnchor && o.onLeaveAnchor(...i)),
      onKeydown: t[4] || (t[4] = P((...i) => o.onLeaveAnchor && o.onLeaveAnchor(...i), ["esc"]))
    }, [
      d(e.$slots, "anchor")
    ], 544)),
    T("div", {
      id: n.id,
      ref: "content",
      "data-qa": "dt-tooltip",
      class: L([
        "d-tooltip",
        {
          [u.TOOLTIP_KIND_MODIFIERS.inverted]: n.inverted
        },
        n.contentClass
      ])
    }, [
      d(e.$slots, "default", {}, () => [
        O(b(n.message), 1)
      ])
    ], 10, C)
  ]);
}
const F = /* @__PURE__ */ x(I, [["render", M]]);
export {
  F as default
};
//# sourceMappingURL=tooltip.js.map
