UNPKG

@kobalte/core

Version:

Unstyled components and primitives for building accessible web apps and design systems with SolidJS.

130 lines (126 loc) 4.09 kB
import { createInteractOutside } from './KKN23NY7.js'; import { createEscapeKeyDown } from './QEMPLYZX.js'; import { layerStack } from './ZKYDDHM6.js'; import { Polymorphic } from './6Y7B2NEO.js'; import { createComponent, mergeProps } from 'solid-js/web'; import { getDocument, mergeRefs, contains } from '@kobalte/utils'; import { createContext, splitProps, onMount, createEffect, on, onCleanup, useContext } from 'solid-js'; var DismissableLayerContext = createContext(); function useOptionalDismissableLayerContext() { return useContext(DismissableLayerContext); } // src/dismissable-layer/dismissable-layer.tsx function DismissableLayer(props) { let ref; const parentContext = useOptionalDismissableLayerContext(); const [local, others] = splitProps(props, ["ref", "disableOutsidePointerEvents", "excludedElements", "onEscapeKeyDown", "onPointerDownOutside", "onFocusOutside", "onInteractOutside", "onDismiss", "bypassTopMostLayerCheck"]); const nestedLayers = /* @__PURE__ */ new Set([]); const registerNestedLayer = (element) => { nestedLayers.add(element); const parentUnregister = parentContext?.registerNestedLayer(element); return () => { nestedLayers.delete(element); parentUnregister?.(); }; }; const shouldExcludeElement = (element) => { if (!ref) { return false; } return local.excludedElements?.some((node) => contains(node(), element)) || [...nestedLayers].some((layer) => contains(layer, element)); }; const onPointerDownOutside = (e) => { if (!ref || layerStack.isBelowPointerBlockingLayer(ref)) { return; } if (!local.bypassTopMostLayerCheck && !layerStack.isTopMostLayer(ref)) { return; } local.onPointerDownOutside?.(e); local.onInteractOutside?.(e); if (!e.defaultPrevented) { local.onDismiss?.(); } }; const onFocusOutside = (e) => { local.onFocusOutside?.(e); local.onInteractOutside?.(e); if (!e.defaultPrevented) { local.onDismiss?.(); } }; createInteractOutside({ shouldExcludeElement, onPointerDownOutside, onFocusOutside }, () => ref); createEscapeKeyDown({ ownerDocument: () => getDocument(ref), onEscapeKeyDown: (e) => { if (!ref || !layerStack.isTopMostLayer(ref)) { return; } local.onEscapeKeyDown?.(e); if (!e.defaultPrevented && local.onDismiss) { e.preventDefault(); local.onDismiss(); } } }); onMount(() => { if (!ref) { return; } layerStack.addLayer({ node: ref, isPointerBlocking: local.disableOutsidePointerEvents, dismiss: local.onDismiss }); const unregisterFromParentLayer = parentContext?.registerNestedLayer(ref); layerStack.assignPointerEventToLayers(); layerStack.disableBodyPointerEvents(ref); onCleanup(() => { if (!ref) { return; } layerStack.removeLayer(ref); unregisterFromParentLayer?.(); layerStack.assignPointerEventToLayers(); layerStack.restoreBodyPointerEvents(ref); }); }); createEffect(on([() => ref, () => local.disableOutsidePointerEvents], ([ref2, disableOutsidePointerEvents]) => { if (!ref2) { return; } const layer = layerStack.find(ref2); if (layer && layer.isPointerBlocking !== disableOutsidePointerEvents) { layer.isPointerBlocking = disableOutsidePointerEvents; layerStack.assignPointerEventToLayers(); } if (disableOutsidePointerEvents) { layerStack.disableBodyPointerEvents(ref2); } onCleanup(() => { layerStack.restoreBodyPointerEvents(ref2); }); }, { defer: true })); const context = { registerNestedLayer }; return createComponent(DismissableLayerContext.Provider, { value: context, get children() { return createComponent(Polymorphic, mergeProps({ as: "div", ref(r$) { const _ref$ = mergeRefs((el) => ref = el, local.ref); typeof _ref$ === "function" && _ref$(r$); } }, others)); } }); } export { DismissableLayer };