UNPKG

@kobalte/core

Version:

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

161 lines (156 loc) 4.19 kB
import { createInteractOutside } from "./MGQGUY64.jsx"; import { createEscapeKeyDown } from "./IGYOA2ZZ.jsx"; import { layerStack } from "./3NI6FTA2.jsx"; import { Polymorphic } from "./FLVHQV4A.jsx"; // src/dismissable-layer/dismissable-layer.tsx import { contains, getDocument, mergeRefs } from "@kobalte/utils"; import { createEffect, on, onCleanup, onMount, splitProps } from "solid-js"; // src/dismissable-layer/dismissable-layer-context.tsx import { createContext, 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 <DismissableLayerContext.Provider value={context}><Polymorphic as="div" ref={mergeRefs((el) => ref = el, local.ref)} {...others} /></DismissableLayerContext.Provider>; } export { DismissableLayer };