@frank-auth/react
Version:
Flexible and customizable React UI components for Frank Authentication
1 lines • 26.9 kB
Source Map (JSON)
{"version":3,"file":"tooltip.cjs","sources":["../../../../../src/components/ui/tooltip/tooltip.tsx"],"sourcesContent":["import { useTheme } from \"@/theme/context\";\nimport type { StyledProps } from \"@/theme/styled\";\nimport { css, keyframes } from \"@emotion/react\";\nimport styled from \"@emotion/styled\";\nimport React, { useState, useRef, useEffect, useCallback } from \"react\";\nimport { createPortal } from \"react-dom\";\n\nexport interface TooltipProps extends React.HTMLAttributes<HTMLDivElement> {\n\t/** Tooltip open state */\n\tisOpen?: boolean;\n\t/** Default open state */\n\tdefaultOpen?: boolean;\n\t/** Open state change handler */\n\tonOpenChange?: (open: boolean) => void;\n\t/** Tooltip placement */\n\tplacement?:\n\t\t| \"top\"\n\t\t| \"top-start\"\n\t\t| \"top-end\"\n\t\t| \"bottom\"\n\t\t| \"bottom-start\"\n\t\t| \"bottom-end\"\n\t\t| \"left\"\n\t\t| \"left-start\"\n\t\t| \"left-end\"\n\t\t| \"right\"\n\t\t| \"right-start\"\n\t\t| \"right-end\";\n\t/** Show delay in milliseconds */\n\tdelay?: number;\n\t/** Hide delay in milliseconds */\n\tcloseDelay?: number;\n\t/** Show arrow */\n\tshowArrow?: boolean;\n\t/** Offset from trigger */\n\toffset?: number;\n\t/** Cross axis offset */\n\tcrossOffset?: number;\n\t/** Disable tooltip */\n\tisDisabled?: boolean;\n\t/** Custom class name */\n\tclassName?: string;\n\t/** Custom styles */\n\tcss?: any;\n\t/** Portal container */\n\tportalContainer?: Element;\n\t/** Trigger element */\n\tchildren?: React.ReactNode;\n}\n\nexport interface TooltipTriggerProps\n\textends React.HTMLAttributes<HTMLDivElement> {\n\tchildren: React.ReactNode;\n\tclassName?: string;\n\tcss?: any;\n\t/** Accessibility label for the trigger */\n\t\"aria-label\"?: string;\n}\n\nexport interface TooltipContentProps\n\textends React.HTMLAttributes<HTMLDivElement> {\n\tchildren: React.ReactNode;\n\tclassName?: string;\n\tcss?: any;\n}\n\ntype StyledTooltipProps = StyledProps<TooltipProps>;\n\n// Validation arrays for prop values\nconst VALID_PLACEMENTS = [\n\t\"top\",\n\t\"top-start\",\n\t\"top-end\",\n\t\"bottom\",\n\t\"bottom-start\",\n\t\"bottom-end\",\n\t\"left\",\n\t\"left-start\",\n\t\"left-end\",\n\t\"right\",\n\t\"right-start\",\n\t\"right-end\",\n] as const;\n\n// Helper function to validate placement\nconst validatePlacement = (placement: any): TooltipProps[\"placement\"] => {\n\treturn VALID_PLACEMENTS.includes(placement) ? placement : \"top\";\n};\n\n// Animation keyframes\nconst tooltipFadeIn = keyframes`\n from {\n opacity: 0;\n transform: scale(0.9);\n }\n to {\n opacity: 1;\n transform: scale(1);\n }\n`;\n\nconst tooltipFadeOut = keyframes`\n from {\n opacity: 1;\n transform: scale(1);\n }\n to {\n opacity: 0;\n transform: scale(0.9);\n }\n`;\n\nconst getTooltipPlacementStyles = (\n\tplacement: TooltipProps[\"placement\"],\n\ttriggerRect: DOMRect | null,\n\toffset: number,\n\tcrossOffset: number,\n) => {\n\tif (!triggerRect) return {};\n\n\tconst validatedPlacement = validatePlacement(placement);\n\tconst styles: React.CSSProperties = {\n\t\tposition: \"absolute\",\n\t\tzIndex: 1600, // Higher than popover\n\t};\n\n\t// Add viewport boundary checking\n\tconst viewportPadding = 8;\n\tconst maxWidth = Math.min(320, window.innerWidth - viewportPadding * 2);\n\n\tswitch (validatedPlacement) {\n\t\tcase \"top\":\n\t\t\tstyles.bottom = `${window.innerHeight - triggerRect.top + offset}px`;\n\t\t\tstyles.left = `${triggerRect.left + triggerRect.width / 2}px`;\n\t\t\tstyles.transform = `translateX(-50%) translateX(${crossOffset}px)`;\n\t\t\tstyles.maxWidth = `${maxWidth}px`;\n\t\t\tbreak;\n\t\tcase \"top-start\":\n\t\t\tstyles.bottom = `${window.innerHeight - triggerRect.top + offset}px`;\n\t\t\tstyles.left = `${Math.max(viewportPadding, triggerRect.left + crossOffset)}px`;\n\t\t\tstyles.maxWidth = `${maxWidth}px`;\n\t\t\tbreak;\n\t\tcase \"top-end\":\n\t\t\tstyles.bottom = `${window.innerHeight - triggerRect.top + offset}px`;\n\t\t\tstyles.right = `${Math.max(viewportPadding, window.innerWidth - triggerRect.right - crossOffset)}px`;\n\t\t\tstyles.maxWidth = `${maxWidth}px`;\n\t\t\tbreak;\n\t\tcase \"bottom\":\n\t\t\tstyles.top = `${triggerRect.bottom + offset}px`;\n\t\t\tstyles.left = `${triggerRect.left + triggerRect.width / 2}px`;\n\t\t\tstyles.transform = `translateX(-50%) translateX(${crossOffset}px)`;\n\t\t\tstyles.maxWidth = `${maxWidth}px`;\n\t\t\tbreak;\n\t\tcase \"bottom-start\":\n\t\t\tstyles.top = `${triggerRect.bottom + offset}px`;\n\t\t\tstyles.left = `${Math.max(viewportPadding, triggerRect.left + crossOffset)}px`;\n\t\t\tstyles.maxWidth = `${maxWidth}px`;\n\t\t\tbreak;\n\t\tcase \"bottom-end\":\n\t\t\tstyles.top = `${triggerRect.bottom + offset}px`;\n\t\t\tstyles.right = `${Math.max(viewportPadding, window.innerWidth - triggerRect.right - crossOffset)}px`;\n\t\t\tstyles.maxWidth = `${maxWidth}px`;\n\t\t\tbreak;\n\t\tcase \"left\":\n\t\t\tstyles.right = `${window.innerWidth - triggerRect.left + offset}px`;\n\t\t\tstyles.top = `${triggerRect.top + triggerRect.height / 2}px`;\n\t\t\tstyles.transform = `translateY(-50%) translateY(${crossOffset}px)`;\n\t\t\tstyles.maxWidth = `${maxWidth}px`;\n\t\t\tbreak;\n\t\tcase \"left-start\":\n\t\t\tstyles.right = `${window.innerWidth - triggerRect.left + offset}px`;\n\t\t\tstyles.top = `${Math.max(viewportPadding, triggerRect.top + crossOffset)}px`;\n\t\t\tstyles.maxWidth = `${maxWidth}px`;\n\t\t\tbreak;\n\t\tcase \"left-end\":\n\t\t\tstyles.right = `${window.innerWidth - triggerRect.left + offset}px`;\n\t\t\tstyles.bottom = `${Math.max(viewportPadding, window.innerHeight - triggerRect.bottom - crossOffset)}px`;\n\t\t\tstyles.maxWidth = `${maxWidth}px`;\n\t\t\tbreak;\n\t\tcase \"right\":\n\t\t\tstyles.left = `${triggerRect.right + offset}px`;\n\t\t\tstyles.top = `${triggerRect.top + triggerRect.height / 2}px`;\n\t\t\tstyles.transform = `translateY(-50%) translateY(${crossOffset}px)`;\n\t\t\tstyles.maxWidth = `${maxWidth}px`;\n\t\t\tbreak;\n\t\tcase \"right-start\":\n\t\t\tstyles.left = `${triggerRect.right + offset}px`;\n\t\t\tstyles.top = `${Math.max(viewportPadding, triggerRect.top + crossOffset)}px`;\n\t\t\tstyles.maxWidth = `${maxWidth}px`;\n\t\t\tbreak;\n\t\tcase \"right-end\":\n\t\t\tstyles.left = `${triggerRect.right + offset}px`;\n\t\t\tstyles.bottom = `${Math.max(viewportPadding, window.innerHeight - triggerRect.bottom - crossOffset)}px`;\n\t\t\tstyles.maxWidth = `${maxWidth}px`;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\t// Default to top\n\t\t\tstyles.bottom = `${window.innerHeight - triggerRect.top + offset}px`;\n\t\t\tstyles.left = `${triggerRect.left + triggerRect.width / 2}px`;\n\t\t\tstyles.transform = `translateX(-50%) translateX(${crossOffset}px)`;\n\t\t\tstyles.maxWidth = `${maxWidth}px`;\n\t}\n\n\treturn styles;\n};\n\nconst getTooltipArrowStyles = (placement: TooltipProps[\"placement\"]) => {\n\tconst validatedPlacement = validatePlacement(placement);\n\tconst arrowSize = 6;\n\n\tswitch (validatedPlacement) {\n\t\tcase \"top\":\n\t\tcase \"top-start\":\n\t\tcase \"top-end\":\n\t\t\treturn css`\n &::after {\n content: '';\n position: absolute;\n top: 100%;\n left: ${validatedPlacement === \"top\" ? \"50%\" : validatedPlacement === \"top-start\" ? \"12px\" : \"auto\"};\n right: ${validatedPlacement === \"top-end\" ? \"12px\" : \"auto\"};\n transform: ${validatedPlacement === \"top\" ? \"translateX(-50%)\" : \"none\"};\n width: 0;\n height: 0;\n border-left: ${arrowSize}px solid transparent;\n border-right: ${arrowSize}px solid transparent;\n border-top: ${arrowSize}px solid currentColor;\n }\n `;\n\t\tcase \"bottom\":\n\t\tcase \"bottom-start\":\n\t\tcase \"bottom-end\":\n\t\t\treturn css`\n &::after {\n content: '';\n position: absolute;\n bottom: 100%;\n left: ${validatedPlacement === \"bottom\" ? \"50%\" : validatedPlacement === \"bottom-start\" ? \"12px\" : \"auto\"};\n right: ${validatedPlacement === \"bottom-end\" ? \"12px\" : \"auto\"};\n transform: ${validatedPlacement === \"bottom\" ? \"translateX(-50%)\" : \"none\"};\n width: 0;\n height: 0;\n border-left: ${arrowSize}px solid transparent;\n border-right: ${arrowSize}px solid transparent;\n border-bottom: ${arrowSize}px solid currentColor;\n }\n `;\n\t\tcase \"left\":\n\t\tcase \"left-start\":\n\t\tcase \"left-end\":\n\t\t\treturn css`\n &::after {\n content: '';\n position: absolute;\n left: 100%;\n top: ${validatedPlacement === \"left\" ? \"50%\" : validatedPlacement === \"left-start\" ? \"12px\" : \"auto\"};\n bottom: ${validatedPlacement === \"left-end\" ? \"12px\" : \"auto\"};\n transform: ${validatedPlacement === \"left\" ? \"translateY(-50%)\" : \"none\"};\n width: 0;\n height: 0;\n border-top: ${arrowSize}px solid transparent;\n border-bottom: ${arrowSize}px solid transparent;\n border-left: ${arrowSize}px solid currentColor;\n }\n `;\n\t\tcase \"right\":\n\t\tcase \"right-start\":\n\t\tcase \"right-end\":\n\t\t\treturn css`\n &::after {\n content: '';\n position: absolute;\n right: 100%;\n top: ${validatedPlacement === \"right\" ? \"50%\" : validatedPlacement === \"right-start\" ? \"12px\" : \"auto\"};\n bottom: ${validatedPlacement === \"right-end\" ? \"12px\" : \"auto\"};\n transform: ${validatedPlacement === \"right\" ? \"translateY(-50%)\" : \"none\"};\n width: 0;\n height: 0;\n border-top: ${arrowSize}px solid transparent;\n border-bottom: ${arrowSize}px solid transparent;\n border-right: ${arrowSize}px solid currentColor;\n }\n `;\n\t\tdefault:\n\t\t\treturn css``;\n\t}\n};\n\nconst TooltipContent = styled.div<\n\tStyledTooltipProps & {\n\t\tisClosing?: boolean;\n\t\tplacement?: TooltipProps[\"placement\"];\n\t\tshowArrow?: boolean;\n\t}\n>`\n background-color: ${(props) => props.theme.colors.neutral[800]};\n color: ${(props) => props.theme.colors.neutral[50]};\n border-radius: ${(props) => props.theme.borderRadius.md};\n padding: ${(props) => props.theme.spacing[2]} ${(props) => props.theme.spacing[3]};\n font-size: ${(props) => props.theme.fontSizes.sm};\n line-height: ${(props) => props.theme.lineHeights.tight};\n max-width: 320px;\n word-wrap: break-word;\n box-shadow: ${(props) => props.theme.shadows.md};\n animation: ${(props) => (props.isClosing ? tooltipFadeOut : tooltipFadeIn)} \n ${(props) => props.theme.transitions.fast};\n\n /* Arrow styles */\n ${(props) => props.showArrow && getTooltipArrowStyles(props.placement)}\n\n /* Ensure arrow uses the same color as background */\n &::after {\n color: ${(props) => props.theme.colors.neutral[800]};\n }\n\n /* Custom CSS prop */\n ${(props) => props.css}\n`;\n\nconst TooltipTrigger = styled.div<StyledProps<TooltipTriggerProps>>`\n display: inline-block;\n\n /* Custom CSS prop */\n ${(props) => props.css}\n`;\n\n// Context for tooltip state\nconst TooltipContext = React.createContext<{\n\tisOpen: boolean;\n\tonOpenChange: (open: boolean) => void;\n\ttriggerRef: React.RefObject<HTMLDivElement>;\n\tplacement: TooltipProps[\"placement\"];\n\tshowArrow: boolean;\n\toffset: number;\n\tcrossOffset: number;\n\tdelay: number;\n\tcloseDelay: number;\n\tisDisabled: boolean;\n} | null>(null);\n\nexport const Tooltip: React.FC<TooltipProps> & {\n\tTrigger: React.FC<TooltipTriggerProps>;\n\tContent: React.FC<TooltipContentProps>;\n} = ({\n\tchildren,\n\tisOpen: controlledOpen,\n\tdefaultOpen = false,\n\tonOpenChange,\n\tplacement = \"top\",\n\tdelay = 700,\n\tcloseDelay = 300,\n\tshowArrow = true,\n\toffset = 8,\n\tcrossOffset = 0,\n\tisDisabled = false,\n\tclassName,\n\tcss,\n\tportalContainer,\n\t...props\n}) => {\n\tconst [internalOpen, setInternalOpen] = useState(defaultOpen);\n\tconst triggerRef = useRef<HTMLDivElement>(null);\n\tconst isControlled = controlledOpen !== undefined;\n\tconst isOpen = isControlled ? controlledOpen : internalOpen;\n\n\tconst validatedPlacement = validatePlacement(placement);\n\tconst validatedDelay = typeof delay === \"number\" && delay >= 0 ? delay : 700;\n\tconst validatedCloseDelay =\n\t\ttypeof closeDelay === \"number\" && closeDelay >= 0 ? closeDelay : 300;\n\n\tconst handleOpenChange = useCallback(\n\t\t(open: boolean) => {\n\t\t\tif (isDisabled) return;\n\n\t\t\tif (!isControlled) {\n\t\t\t\tsetInternalOpen(open);\n\t\t\t}\n\t\t\tonOpenChange?.(open);\n\t\t},\n\t\t[isControlled, onOpenChange, isDisabled],\n\t);\n\n\t// Close on escape\n\tuseEffect(() => {\n\t\tif (!isOpen || isDisabled) return;\n\n\t\tconst handleEscape = (event: KeyboardEvent) => {\n\t\t\tif (event.key === \"Escape\") {\n\t\t\t\thandleOpenChange(false);\n\t\t\t}\n\t\t};\n\n\t\tdocument.addEventListener(\"keydown\", handleEscape);\n\t\treturn () => document.removeEventListener(\"keydown\", handleEscape);\n\t}, [isOpen, handleOpenChange, isDisabled]);\n\n\tconst contextValue = {\n\t\tisOpen,\n\t\tonOpenChange: handleOpenChange,\n\t\ttriggerRef,\n\t\tplacement: validatedPlacement,\n\t\tshowArrow,\n\t\toffset,\n\t\tcrossOffset,\n\t\tdelay: validatedDelay,\n\t\tcloseDelay: validatedCloseDelay,\n\t\tisDisabled,\n\t};\n\n\treturn (\n\t\t<TooltipContext.Provider value={contextValue}>\n\t\t\t<div className={className} {...props}>\n\t\t\t\t{children}\n\t\t\t</div>\n\t\t</TooltipContext.Provider>\n\t);\n};\n\nconst TooltipTriggerComponent: React.FC<TooltipTriggerProps> = ({\n\tchildren,\n\tclassName,\n\tcss,\n\t\"aria-label\": ariaLabel,\n\t...props\n}) => {\n\tconst { theme } = useTheme();\n\tconst context = React.useContext(TooltipContext);\n\tif (!context) {\n\t\tthrow new Error(\"TooltipTrigger must be used within a Tooltip\");\n\t}\n\n\tconst { isOpen, onOpenChange, triggerRef, delay, closeDelay, isDisabled } =\n\t\tcontext;\n\tconst showTimeoutRef = useRef<NodeJS.Timeout>();\n\tconst hideTimeoutRef = useRef<NodeJS.Timeout>();\n\n\tconst clearTimeouts = () => {\n\t\tif (showTimeoutRef.current) {\n\t\t\tclearTimeout(showTimeoutRef.current);\n\t\t}\n\t\tif (hideTimeoutRef.current) {\n\t\t\tclearTimeout(hideTimeoutRef.current);\n\t\t}\n\t};\n\n\tconst handleMouseEnter = () => {\n\t\tif (isDisabled) return;\n\n\t\tclearTimeouts();\n\t\tshowTimeoutRef.current = setTimeout(() => {\n\t\t\tonOpenChange(true);\n\t\t}, delay);\n\t};\n\n\tconst handleMouseLeave = () => {\n\t\tif (isDisabled) return;\n\n\t\tclearTimeouts();\n\t\thideTimeoutRef.current = setTimeout(() => {\n\t\t\tonOpenChange(false);\n\t\t}, closeDelay);\n\t};\n\n\tconst handleFocus = () => {\n\t\tif (isDisabled) return;\n\n\t\tclearTimeouts();\n\t\tonOpenChange(true);\n\t};\n\n\tconst handleBlur = () => {\n\t\tif (isDisabled) return;\n\n\t\tclearTimeouts();\n\t\tonOpenChange(false);\n\t};\n\n\t// Cleanup timeouts on unmount\n\tuseEffect(() => {\n\t\treturn () => clearTimeouts();\n\t}, []);\n\n\treturn (\n\t\t<TooltipTrigger\n\t\t\tref={triggerRef}\n\t\t\ttheme={theme}\n\t\t\tclassName={className}\n\t\t\tcss={css}\n\t\t\tonMouseEnter={handleMouseEnter}\n\t\t\tonMouseLeave={handleMouseLeave}\n\t\t\tonFocus={handleFocus}\n\t\t\tonBlur={handleBlur}\n\t\t\taria-describedby={isOpen ? \"tooltip-content\" : undefined}\n\t\t\taria-label={ariaLabel}\n\t\t\t{...props}\n\t\t>\n\t\t\t{children}\n\t\t</TooltipTrigger>\n\t);\n};\n\nconst TooltipContentComponent: React.FC<TooltipContentProps> = ({\n\tchildren,\n\tclassName,\n\tcss,\n\t...props\n}) => {\n\tconst { theme } = useTheme();\n\tconst context = React.useContext(TooltipContext);\n\tif (!context) {\n\t\tthrow new Error(\"TooltipContent must be used within a Tooltip\");\n\t}\n\n\tconst {\n\t\tisOpen,\n\t\ttriggerRef,\n\t\tplacement,\n\t\tshowArrow,\n\t\toffset,\n\t\tcrossOffset,\n\t\tisDisabled,\n\t} = context;\n\tconst [triggerRect, setTriggerRect] = useState<DOMRect | null>(null);\n\tconst [isClosing, setIsClosing] = useState(false);\n\n\t// Update trigger rect when tooltip opens\n\tuseEffect(() => {\n\t\tif (isOpen && triggerRef.current && !isDisabled) {\n\t\t\tconst updateRect = () => {\n\t\t\t\tsetTriggerRect(triggerRef.current!.getBoundingClientRect());\n\t\t\t};\n\n\t\t\tupdateRect();\n\n\t\t\t// Update on scroll/resize\n\t\t\twindow.addEventListener(\"scroll\", updateRect, true);\n\t\t\twindow.addEventListener(\"resize\", updateRect);\n\n\t\t\treturn () => {\n\t\t\t\twindow.removeEventListener(\"scroll\", updateRect, true);\n\t\t\t\twindow.removeEventListener(\"resize\", updateRect);\n\t\t\t};\n\t\t}\n\t}, [isOpen, triggerRef, isDisabled]);\n\n\t// Handle closing animation\n\tuseEffect(() => {\n\t\tif (!isOpen && triggerRect) {\n\t\t\tsetIsClosing(true);\n\t\t\tconst timer = setTimeout(() => {\n\t\t\t\tsetIsClosing(false);\n\t\t\t\tsetTriggerRect(null);\n\t\t\t}, 150); // Match animation duration\n\t\t\treturn () => clearTimeout(timer);\n\t\t}\n\t}, [isOpen, triggerRect]);\n\n\tif ((!isOpen && !isClosing) || isDisabled) return null;\n\n\tconst positionStyles = getTooltipPlacementStyles(\n\t\tplacement,\n\t\ttriggerRect,\n\t\toffset,\n\t\tcrossOffset,\n\t);\n\n\tconst container = document.body;\n\n\tconst content = (\n\t\t<TooltipContent\n\t\t\tid=\"tooltip-content\"\n\t\t\ttheme={theme}\n\t\t\tdata-tooltip-content\n\t\t\tclassName={className}\n\t\t\tcss={css}\n\t\t\tplacement={placement}\n\t\t\tshowArrow={showArrow}\n\t\t\tisClosing={isClosing}\n\t\t\tstyle={positionStyles}\n\t\t\trole=\"tooltip\"\n\t\t\t{...props}\n\t\t>\n\t\t\t{children}\n\t\t</TooltipContent>\n\t);\n\n\treturn createPortal(content, container);\n};\n\nTooltip.Trigger = TooltipTriggerComponent;\nTooltip.Content = TooltipContentComponent;\n\nTooltip.displayName = \"Tooltip\";\nTooltipTriggerComponent.displayName = \"TooltipTrigger\";\nTooltipContentComponent.displayName = \"TooltipContent\";\n"],"names":["VALID_PLACEMENTS","validatePlacement","placement","tooltipFadeIn","keyframes","tooltipFadeOut","getTooltipPlacementStyles","triggerRect","offset","crossOffset","validatedPlacement","styles","viewportPadding","maxWidth","getTooltipArrowStyles","arrowSize","css","TooltipContent","styled","props","TooltipTrigger","TooltipContext","React","Tooltip","children","controlledOpen","defaultOpen","onOpenChange","delay","closeDelay","showArrow","isDisabled","className","portalContainer","internalOpen","setInternalOpen","useState","triggerRef","useRef","isControlled","isOpen","validatedDelay","validatedCloseDelay","handleOpenChange","useCallback","open","useEffect","handleEscape","event","contextValue","jsx","TooltipTriggerComponent","ariaLabel","theme","useTheme","context","showTimeoutRef","hideTimeoutRef","clearTimeouts","handleMouseEnter","handleMouseLeave","handleFocus","handleBlur","TooltipContentComponent","setTriggerRect","isClosing","setIsClosing","updateRect","timer","positionStyles","container","content","createPortal"],"mappings":"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"}