UNPKG

reka-ui

Version:

Vue port for Radix UI Primitives.

130 lines (127 loc) 5.09 kB
import { isNullish } from "../shared/nullish.js"; import { useForwardExpose } from "../shared/useForwardExpose.js"; import { Primitive } from "../Primitive/Primitive.js"; import { useFocusOutside, usePointerDownOutside } from "./utils.js"; import { computed, createBlock, defineComponent, nextTick, normalizeStyle, openBlock, reactive, renderSlot, unref, watchEffect, withCtx } from "vue"; import { onKeyStroke } from "@vueuse/core"; //#region src/DismissableLayer/DismissableLayer.vue?vue&type=script&setup=true&lang.ts const context = reactive({ layersRoot: /* @__PURE__ */ new Set(), layersWithOutsidePointerEventsDisabled: /* @__PURE__ */ new Set(), originalBodyPointerEvents: void 0, branches: /* @__PURE__ */ new Set() }); var DismissableLayer_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({ __name: "DismissableLayer", props: { disableOutsidePointerEvents: { type: Boolean, required: false, default: false }, asChild: { type: Boolean, required: false }, as: { type: null, required: false } }, emits: [ "escapeKeyDown", "pointerDownOutside", "focusOutside", "interactOutside", "dismiss" ], setup(__props, { emit: __emit }) { const props = __props; const emits = __emit; const { forwardRef, currentElement: layerElement } = useForwardExpose(); const ownerDocument = computed(() => layerElement.value?.ownerDocument ?? globalThis.document); const layers = computed(() => context.layersRoot); const index = computed(() => { return layerElement.value ? Array.from(layers.value).indexOf(layerElement.value) : -1; }); const isBodyPointerEventsDisabled = computed(() => { return context.layersWithOutsidePointerEventsDisabled.size > 0; }); const isPointerEventsEnabled = computed(() => { const localLayers = Array.from(layers.value); const [highestLayerWithOutsidePointerEventsDisabled] = [...context.layersWithOutsidePointerEventsDisabled].slice(-1); const highestLayerWithOutsidePointerEventsDisabledIndex = localLayers.indexOf(highestLayerWithOutsidePointerEventsDisabled); return index.value >= highestLayerWithOutsidePointerEventsDisabledIndex; }); const pointerDownOutside = usePointerDownOutside(async (event) => { const isPointerDownOnBranch = [...context.branches].some((branch) => branch?.contains(event.target)); if (!isPointerEventsEnabled.value || isPointerDownOnBranch) return; emits("pointerDownOutside", event); emits("interactOutside", event); await nextTick(); if (!event.defaultPrevented) emits("dismiss"); }, layerElement); const focusOutside = useFocusOutside((event) => { const isFocusInBranch = [...context.branches].some((branch) => branch?.contains(event.target)); if (isFocusInBranch) return; emits("focusOutside", event); emits("interactOutside", event); if (!event.defaultPrevented) emits("dismiss"); }, layerElement); onKeyStroke("Escape", (event) => { const isHighestLayer = index.value === layers.value.size - 1; if (!isHighestLayer) return; emits("escapeKeyDown", event); if (!event.defaultPrevented) emits("dismiss"); }); watchEffect((cleanupFn) => { if (!layerElement.value) return; if (props.disableOutsidePointerEvents) { if (context.layersWithOutsidePointerEventsDisabled.size === 0) { context.originalBodyPointerEvents = ownerDocument.value.body.style.pointerEvents; ownerDocument.value.body.style.pointerEvents = "none"; } context.layersWithOutsidePointerEventsDisabled.add(layerElement.value); } layers.value.add(layerElement.value); cleanupFn(() => { if (props.disableOutsidePointerEvents && context.layersWithOutsidePointerEventsDisabled.size === 1 && !isNullish(context.originalBodyPointerEvents)) ownerDocument.value.body.style.pointerEvents = context.originalBodyPointerEvents; }); }); watchEffect((cleanupFn) => { cleanupFn(() => { if (!layerElement.value) return; layers.value.delete(layerElement.value); context.layersWithOutsidePointerEventsDisabled.delete(layerElement.value); }); }); return (_ctx, _cache) => { return openBlock(), createBlock(unref(Primitive), { ref: unref(forwardRef), "as-child": _ctx.asChild, as: _ctx.as, "data-dismissable-layer": "", style: normalizeStyle({ pointerEvents: isBodyPointerEventsDisabled.value ? isPointerEventsEnabled.value ? "auto" : "none" : void 0 }), onFocusCapture: unref(focusOutside).onFocusCapture, onBlurCapture: unref(focusOutside).onBlurCapture, onPointerdownCapture: unref(pointerDownOutside).onPointerDownCapture }, { default: withCtx(() => [renderSlot(_ctx.$slots, "default")]), _: 3 }, 8, [ "as-child", "as", "style", "onFocusCapture", "onBlurCapture", "onPointerdownCapture" ]); }; } }); //#endregion //#region src/DismissableLayer/DismissableLayer.vue var DismissableLayer_default = DismissableLayer_vue_vue_type_script_setup_true_lang_default; //#endregion export { DismissableLayer_default, context }; //# sourceMappingURL=DismissableLayer.js.map