koval-ui
Version:
React components collection with minimalistic design. Supports theming, layout, and input validation.
1 lines • 7.43 kB
Source Map (JSON)
{"version":3,"file":"Menu.cjs","sources":["../../../../src/lib/Menu/Menu.tsx"],"sourcesContent":["import type {ReactNode} from 'react';\nimport {useCallback, forwardRef, Fragment, useState, useEffect} from 'react';\nimport classNames from 'classnames';\nimport type {Placement} from '@floating-ui/react-dom';\nimport {useFloating, autoUpdate, size, offset, autoPlacement} from '@floating-ui/react-dom';\nimport {useRootTheme, useLocalTheme} from 'css-vars-hook';\n\nimport type {DataAttributes, LibraryProps} from '@/internal/LibraryAPI';\nimport {Portal} from '@/internal/Portal';\nimport {useDismiss} from '@/internal/hooks/useDismiss.ts';\nimport {useFocusTrap} from '@/internal/hooks/useFocusTrap.ts';\nimport {useInternalRef} from '@/internal/hooks/useInternalRef.ts';\n\nimport classes from './Menu.module.css';\nimport {Variants} from './Variants.ts';\n\nexport type Props = DataAttributes &\n LibraryProps & {\n children: ReactNode;\n /** Control visibility of the Menu */\n isOpen?: boolean;\n /**\n * Provide Tooltip content\n * @example\n * <Menu content={<div>Foo<div>} //... />\n */\n content: ReactNode;\n /** Set class name of reference component wrapper */\n referenceClassName?: string;\n /** Provide callback for open/close events */\n onToggle?: (openState: boolean) => void;\n /** Focus on the first element when open and trap focus */\n trapFocus?: boolean;\n /** Align Menu width with a reference element */\n alignWidth?: boolean;\n /** Set design of Menu */\n variant?: keyof typeof Variants;\n /**\n * Define which relative positions Menu can be placed in\n */\n allowedPlacements?: Placement[];\n };\n\nconst allowedPlacementsDefault: Placement[] = [\n 'bottom',\n 'left',\n 'right',\n 'top',\n 'bottom-end',\n 'bottom-start',\n 'left-start',\n 'left-end',\n 'right-start',\n 'right-end',\n 'top-start',\n 'top-end',\n];\n\nexport const Menu = forwardRef<HTMLDivElement, Props>(\n (\n {\n children,\n className,\n isOpen: openProp = false,\n content,\n referenceClassName,\n onToggle = () => {},\n trapFocus = true,\n alignWidth = true,\n variant = Variants.plain,\n allowedPlacements = allowedPlacementsDefault,\n ...nativeProps\n },\n ref\n ) => {\n const menuRef = useInternalRef(ref);\n const [isOpen, setOpen] = useState(openProp);\n useEffect(() => {\n setOpen(openProp);\n }, [openProp, setOpen]);\n useEffect(() => {\n onToggle(isOpen);\n }, [isOpen, onToggle]);\n const {refs, floatingStyles} = useFloating<HTMLDivElement>({\n strategy: 'fixed',\n whileElementsMounted: autoUpdate,\n middleware: [\n alignWidth &&\n size({\n apply({rects, elements}) {\n Object.assign(elements.floating.style, {\n width: `${rects.reference.width}px`,\n });\n },\n }),\n offset(18),\n autoPlacement({allowedPlacements}),\n ],\n });\n const {LocalRoot} = useLocalTheme();\n const {getTheme} = useRootTheme();\n\n const handleDismiss = useCallback(() => {\n setOpen(false);\n }, [setOpen]);\n\n useDismiss(handleDismiss, menuRef, isOpen);\n useFocusTrap(refs.floating.current, isOpen, trapFocus);\n\n return (\n <Fragment>\n <div\n ref={refs.setReference}\n className={classNames(classes.reference, referenceClassName)}>\n {children}\n </div>\n {isOpen && (\n <Portal>\n <div\n ref={refs.setFloating}\n style={floatingStyles}\n className={classes.floating}>\n <LocalRoot className={classes.provider} theme={getTheme()}>\n <div\n {...nativeProps}\n ref={menuRef}\n className={classNames(\n classes.menu,\n {\n [classes.bordered]: variant === Variants.bordered,\n [classes.plain]: variant === Variants.plain,\n },\n className\n )}>\n {content}\n </div>\n </LocalRoot>\n </div>\n </Portal>\n )}\n </Fragment>\n );\n }\n);\n\nMenu.displayName = 'Menu';\n"],"names":["allowedPlacementsDefault","Menu","forwardRef","children","className","openProp","content","referenceClassName","onToggle","trapFocus","alignWidth","variant","Variants","allowedPlacements","nativeProps","ref","menuRef","useInternalRef","isOpen","setOpen","useState","useEffect","refs","floatingStyles","useFloating","autoUpdate","size","rects","elements","offset","autoPlacement","LocalRoot","useLocalTheme","getTheme","useRootTheme","handleDismiss","useCallback","useDismiss","useFocusTrap","Fragment","jsx","classNames","classes","Portal"],"mappings":"kfA2CMA,EAAwC,CAC1C,SACA,OACA,QACA,MACA,aACA,eACA,aACA,WACA,cACA,YACA,YACA,SACJ,EAEaC,EAAOC,EAAA,WAChB,CACI,CACI,SAAAC,EACA,UAAAC,EACA,OAAQC,EAAW,GACnB,QAAAC,EACA,mBAAAC,EACA,SAAAC,EAAW,IAAM,CAAC,EAClB,UAAAC,EAAY,GACZ,WAAAC,EAAa,GACb,QAAAC,EAAUC,EAAS,SAAA,MACnB,kBAAAC,EAAoBb,EACpB,GAAGc,GAEPC,IACC,CACK,MAAAC,EAAUC,iBAAeF,CAAG,EAC5B,CAACG,EAAQC,CAAO,EAAIC,EAAAA,SAASf,CAAQ,EAC3CgB,EAAAA,UAAU,IAAM,CACZF,EAAQd,CAAQ,CAAA,EACjB,CAACA,EAAUc,CAAO,CAAC,EACtBE,EAAAA,UAAU,IAAM,CACZb,EAASU,CAAM,CAAA,EAChB,CAACA,EAAQV,CAAQ,CAAC,EACrB,KAAM,CAAC,KAAAc,EAAM,eAAAC,CAAc,EAAIC,cAA4B,CACvD,SAAU,QACV,qBAAsBC,EAAA,WACtB,WAAY,CACRf,GACIgB,EAAAA,KAAK,CACD,MAAM,CAAC,MAAAC,EAAO,SAAAC,GAAW,CACd,OAAA,OAAOA,EAAS,SAAS,MAAO,CACnC,MAAO,GAAGD,EAAM,UAAU,KAAK,IAAA,CAClC,CAAA,CACL,CACH,EACLE,EAAAA,OAAO,EAAE,EACTC,EAAA,cAAc,CAAC,kBAAAjB,CAAkB,CAAA,CAAA,CACrC,CACH,EACK,CAAC,UAAAkB,CAAS,EAAIC,gBAAc,EAC5B,CAAC,SAAAC,CAAQ,EAAIC,eAAa,EAE1BC,EAAgBC,EAAAA,YAAY,IAAM,CACpCjB,EAAQ,EAAK,CAAA,EACd,CAACA,CAAO,CAAC,EAEDkB,OAAAA,aAAAF,EAAenB,EAASE,CAAM,EACzCoB,EAAAA,aAAahB,EAAK,SAAS,QAASJ,EAAQT,CAAS,SAGhD8B,WACG,CAAA,SAAA,CAAAC,EAAA,IAAC,MAAA,CACG,IAAKlB,EAAK,aACV,UAAWmB,EAAWC,UAAQ,UAAWnC,CAAkB,EAC1D,SAAAJ,CAAA,CACL,EACCe,SACIyB,SACG,CAAA,SAAAH,EAAA,IAAC,MAAA,CACG,IAAKlB,EAAK,YACV,MAAOC,EACP,UAAWmB,EAAQ,QAAA,SACnB,eAACX,EAAU,CAAA,UAAWW,EAAAA,QAAQ,SAAU,MAAOT,IAC3C,SAAAO,EAAA,IAAC,MAAA,CACI,GAAG1B,EACJ,IAAKE,EACL,UAAWyB,EACPC,EAAAA,QAAQ,KACR,CACI,CAACA,UAAQ,QAAQ,EAAG/B,IAAYC,EAAS,SAAA,SACzC,CAAC8B,UAAQ,KAAK,EAAG/B,IAAYC,WAAS,KAC1C,EACAR,CACJ,EACC,SAAAE,CAAA,CAAA,CAET,CAAA,CAAA,CAAA,CAER,CAAA,CAAA,EAER,CAAA,CAGZ,EAEAL,EAAK,YAAc"}