UNPKG

@kobalte/core

Version:

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

277 lines (268 loc) 7.32 kB
import { MenuCheckboxItem, MenuContent, MenuGroup, MenuGroupLabel, MenuIcon, MenuItem, MenuItemDescription, MenuItemIndicator, MenuItemLabel, MenuPortal, MenuRadioGroup, MenuRadioItem, MenuRoot, MenuSub, MenuSubContent, MenuSubTrigger, useMenuContext, useMenuRootContext } from "./LEK3K6R3.jsx"; import { SeparatorRoot } from "./T4C3DMHT.jsx"; import { PopperArrow } from "./2CTBMVJ4.jsx"; import { useLocale } from "./LR7LBJN3.jsx"; import { createDisclosureState } from "./E53DB7BS.jsx"; import { Polymorphic } from "./FLVHQV4A.jsx"; import { __export } from "./5WXHJDCZ.jsx"; // src/context-menu/index.tsx var context_menu_exports = {}; __export(context_menu_exports, { Arrow: () => PopperArrow, CheckboxItem: () => MenuCheckboxItem, Content: () => ContextMenuContent, ContextMenu: () => ContextMenu, Group: () => MenuGroup, GroupLabel: () => MenuGroupLabel, Icon: () => MenuIcon, Item: () => MenuItem, ItemDescription: () => MenuItemDescription, ItemIndicator: () => MenuItemIndicator, ItemLabel: () => MenuItemLabel, Portal: () => MenuPortal, RadioGroup: () => MenuRadioGroup, RadioItem: () => MenuRadioItem, Root: () => ContextMenuRoot, Separator: () => SeparatorRoot, Sub: () => MenuSub, SubContent: () => MenuSubContent, SubTrigger: () => MenuSubTrigger, Trigger: () => ContextMenuTrigger, useContextMenuContext: () => useContextMenuContext }); // src/context-menu/context-menu-content.tsx import { splitProps } from "solid-js"; function ContextMenuContent(props) { const rootContext = useMenuRootContext(); const [local, others] = splitProps(props, [ "onCloseAutoFocus", "onInteractOutside" ]); let hasInteractedOutside = false; const onCloseAutoFocus = (e) => { local.onCloseAutoFocus?.(e); if (!e.defaultPrevented && hasInteractedOutside) { e.preventDefault(); } hasInteractedOutside = false; }; const onInteractOutside = (e) => { local.onInteractOutside?.(e); if (!e.defaultPrevented && !rootContext.isModal()) { hasInteractedOutside = true; } }; return <MenuContent onCloseAutoFocus={onCloseAutoFocus} onInteractOutside={onInteractOutside} {...others} />; } // src/context-menu/context-menu-root.tsx import { mergeDefaultProps } from "@kobalte/utils"; import { createSignal, createUniqueId, splitProps as splitProps2 } from "solid-js"; // src/context-menu/context-menu-context.tsx import { createContext, useContext } from "solid-js"; var ContextMenuContext = createContext(); function useOptionalContextMenuContext() { return useContext(ContextMenuContext); } function useContextMenuContext() { const context = useOptionalContextMenuContext(); if (context === void 0) { throw new Error( "[kobalte]: `useContextMenuContext` must be used within a `ContextMenu` component" ); } return context; } // src/context-menu/context-menu-root.tsx function ContextMenuRoot(props) { const defaultId = `contextmenu-${createUniqueId()}`; const { direction } = useLocale(); const mergedProps = mergeDefaultProps( { id: defaultId, placement: direction() === "rtl" ? "left-start" : "right-start", gutter: 2, shift: 2 }, props ); const [local, others] = splitProps2(mergedProps, ["onOpenChange"]); const [anchorRect, setAnchorRect] = createSignal({ x: 0, y: 0 }); const disclosureState = createDisclosureState({ defaultOpen: false, onOpenChange: (isOpen) => local.onOpenChange?.(isOpen) }); const context = { setAnchorRect }; return <ContextMenuContext.Provider value={context}><MenuRoot open={disclosureState.isOpen()} onOpenChange={disclosureState.setIsOpen} getAnchorRect={anchorRect} {...others} /></ContextMenuContext.Provider>; } // src/context-menu/context-menu-trigger.tsx import { callHandler, mergeDefaultProps as mergeDefaultProps2, mergeRefs } from "@kobalte/utils"; import { onCleanup, splitProps as splitProps3 } from "solid-js"; import { isServer } from "solid-js/web"; import { combineStyle } from "@solid-primitives/props"; function ContextMenuTrigger(props) { const rootContext = useMenuRootContext(); const menuContext = useMenuContext(); const context = useContextMenuContext(); const mergedProps = mergeDefaultProps2( { id: rootContext.generateId("trigger") }, props ); const [local, others] = splitProps3(mergedProps, [ "ref", "style", "disabled", "onContextMenu", "onPointerDown", "onPointerMove", "onPointerCancel", "onPointerUp" ]); let longPressTimoutId = 0; const clearLongPressTimeout = () => { if (isServer) { return; } window.clearTimeout(longPressTimoutId); }; onCleanup(() => { clearLongPressTimeout(); }); const onContextMenu = (e) => { if (local.disabled) { callHandler(e, local.onContextMenu); return; } clearLongPressTimeout(); e.preventDefault(); e.stopPropagation(); context.setAnchorRect({ x: e.clientX, y: e.clientY }); if (menuContext.isOpen()) { menuContext.focusContent(); } else { menuContext.open(true); } }; const isTouchOrPen = (e) => e.pointerType === "touch" || e.pointerType === "pen"; const onPointerDown = (e) => { callHandler(e, local.onPointerDown); if (!local.disabled && isTouchOrPen(e)) { clearLongPressTimeout(); context.setAnchorRect({ x: e.clientX, y: e.clientY }); longPressTimoutId = window.setTimeout(() => menuContext.open(false), 700); } }; const onPointerMove = (e) => { callHandler(e, local.onPointerMove); if (!local.disabled && isTouchOrPen(e)) { clearLongPressTimeout(); } }; const onPointerCancel = (e) => { callHandler(e, local.onPointerCancel); if (!local.disabled && isTouchOrPen(e)) { clearLongPressTimeout(); } }; const onPointerUp = (e) => { callHandler(e, local.onPointerUp); if (!local.disabled && isTouchOrPen(e)) { clearLongPressTimeout(); } }; return <Polymorphic as="div" ref={mergeRefs(menuContext.setTriggerRef, local.ref)} style={combineStyle( { // prevent iOS context menu from appearing "-webkit-touch-callout": "none" }, local.style )} data-disabled={local.disabled ? "" : void 0} onContextMenu={onContextMenu} onPointerDown={onPointerDown} onPointerMove={onPointerMove} onPointerCancel={onPointerCancel} onPointerUp={onPointerUp} {...menuContext.dataset()} {...others} />; } // src/context-menu/index.tsx var ContextMenu = Object.assign(ContextMenuRoot, { Arrow: PopperArrow, CheckboxItem: MenuCheckboxItem, Content: ContextMenuContent, Group: MenuGroup, GroupLabel: MenuGroupLabel, Icon: MenuIcon, Item: MenuItem, ItemDescription: MenuItemDescription, ItemIndicator: MenuItemIndicator, ItemLabel: MenuItemLabel, Portal: MenuPortal, RadioGroup: MenuRadioGroup, RadioItem: MenuRadioItem, Separator: SeparatorRoot, Sub: MenuSub, SubContent: MenuSubContent, SubTrigger: MenuSubTrigger, Trigger: ContextMenuTrigger }); export { ContextMenuContent, useContextMenuContext, ContextMenuRoot, ContextMenuTrigger, ContextMenu, context_menu_exports };