{"version":3,"sources":["SearchModal.tsx"],"sourcesContent":["import { useSearch } from \"./useSearch.ts\"\nimport React, {\n    useEffect,\n    useState,\n    useMemo,\n    forwardRef,\n    useRef,\n    useDeferredValue,\n    useLayoutEffect,\n    useCallback,\n    useImperativeHandle,\n} from \"react\"\nimport { Browser } from \"./browser.ts\"\nimport {\n    motion,\n    Transition,\n    clamp,\n    MotionStyle,\n    useAnimate,\n} from \"framer-motion\"\nimport type { CSSProperties } from \"react\"\nimport type { SearchStatus, SearchItem } from \"./types.ts\"\nimport { SearchIcon, ClearIcon, SpinnerIcon } from \"./Icons.tsx\"\nimport {\n    clampText,\n    getFontFamily,\n    localStorageDebugFlag,\n    animationKeyFromLayout,\n    stripLocaleSlugFromPath,\n} from \"./utils.ts\"\nimport { useCallbackOnMouseMove, Point } from \"./useCallbackOnMouseMove.ts\"\nimport { scrollIntoView } from \"./scrollIntoView.ts\"\nimport type {\n    ResponsiveImage,\n    EntryPointProps,\n    WindowAnimation,\n} from \"../Search.tsx\"\nimport {\n    useLocaleInfo,\n    // @ts-expect-error Internal API\n    useRouter,\n    // @ts-expect-error Internal API\n    inferInitialRouteFromPath,\n} from \"framer\"\n\nconst MAX_DESCRIPTION_LENGTH = 120\nconst MODAL_MAX_HEIGHT = 496\nconst VERTICAL_SPACING_MULTIPLIER = 0.6\n\ninterface ClearButtonProps {\n    theme: SearchTheme\n    type: SearchInputClearButtonType\n    text: string\n    onClick: () => void\n}\n\nfunction ClearButton({ theme, type, onClick, text }: ClearButtonProps) {\n    const shouldDisplayIcon = type === SearchInputClearButtonType.Icon\n\n    const iconOrText = shouldDisplayIcon ? (\n        <ClearIcon\n            style={{\n                color: theme.inputIconColor,\n                width: theme.inputIconSize,\n                height: theme.inputIconSize,\n            }}\n        />\n    ) : (\n        text\n    )\n\n    return (\n        <div\n            style={{\n                flexShrink: 0,\n                fontSize:\n                    theme && theme.titleFont && theme.titleFont.fontSize\n                        ? theme.titleFont.fontSize\n                        : 15,\n            }}\n        >\n            <button\n                className=\"__framer-search-clear-button\"\n                onClick={onClick}\n                style={{\n                    fontFamily: \"inherit\",\n                    border: \"none\",\n                    background: \"none\",\n                    cursor: \"pointer\",\n                    display: \"flex\",\n                    textTransform: \"uppercase\",\n                    color: theme.inputIconColor,\n                    fontSize: \"0.75em\",\n                    padding: 0,\n                }}\n            >\n                {iconOrText}\n            </button>\n        </div>\n    )\n}\n\ninterface DividerProps {\n    theme: SearchTheme\n    type: SearchInputDividerType\n}\n\nfunction Divider({ theme, type }: DividerProps) {\n    const styles: React.CSSProperties = {\n        background: theme.foregroundColor,\n        height: 1,\n        flexShrink: 0,\n        opacity: 0.05,\n    }\n\n    if (type === SearchInputDividerType.Contained && theme) {\n        styles.marginLeft = theme.horizontalSpacing\n        styles.marginRight = theme.horizontalSpacing\n    }\n\n    return <div style={styles} />\n}\n\ninterface InputProps {\n    value?: string\n    status: SearchStatus\n    placeholder: string\n    theme: SearchTheme\n    autofocus?: boolean\n    iconType?: SearchIconType\n    clearButtonType?: SearchInputClearButtonType\n    clearButtonText: string\n    onChange: (value: string) => void\n}\n\nexport const Input = forwardRef<HTMLInputElement, InputProps>(\n    function Input(props, ref) {\n        const {\n            value = \"\",\n            status,\n            autofocus,\n            theme,\n            placeholder,\n            iconType,\n            clearButtonType,\n            onChange,\n        } = props\n        const [inputValue, setInputValue] = useState(value)\n        const [isFocused, setIsFocused] = useState(false)\n        const inputRef = useRef<HTMLInputElement>()\n        useImperativeHandle(ref, () => inputRef.current)\n\n        React.useLayoutEffect(() => {\n            // Runs on unmount, fixes a bug in Safari that scrolls to the bottom\n            // of the page when the input unmounts.\n            return () => {\n                const inputElement = inputRef.current\n                if (!inputElement || inputElement !== document.activeElement)\n                    return\n                inputElement.blur()\n            }\n        }, [])\n\n        const handleInputClick = () => {\n            if (inputRef.current) {\n                inputRef.current.focus()\n            }\n        }\n\n        const handleClearClick = () => {\n            setInputValue(\"\")\n        }\n\n        useEffect(() => {\n            onChange(inputValue)\n        }, [inputValue])\n\n        const hasInputText = inputValue.length > 0\n        const showClearButton =\n            inputValue.length > 0 &&\n            clearButtonType &&\n            clearButtonType !== SearchInputClearButtonType.None\n\n        const verticalSpacing = Math.floor(\n            theme ? theme.horizontalSpacing * VERTICAL_SPACING_MULTIPLIER : 0\n        )\n\n        const searchIcon =\n            iconType === SearchIconType.Custom && theme.inputIconImage ? (\n                <img\n                    alt=\"icon alongside the Site Search input\"\n                    src={theme.inputIconImage.src}\n                    width={theme.inputIconSize}\n                    height={theme.inputIconSize}\n                    decoding=\"async\"\n                />\n            ) : (\n                <SearchIcon\n                    color={theme.inputIconColor}\n                    width={theme.inputIconSize}\n                    height={theme.inputIconSize}\n                />\n            )\n\n        return (\n            <div\n                role=\"search\"\n                style={{\n                    ...inputContainerStyle,\n                    fontFamily: getFontFamily(theme),\n                    paddingLeft: theme && theme.horizontalSpacing,\n                    paddingRight: theme && theme.horizontalSpacing,\n                    gap: 12,\n                    paddingTop: verticalSpacing,\n                    paddingBottom: verticalSpacing,\n                    touchAction: \"none\",\n                }}\n                onClick={handleInputClick}\n            >\n                <div style={{ flexShrink: 0, display: \"flex\" }}>\n                    {status === \"loading\" && inputValue ? (\n                        <SpinnerIcon\n                            color={theme.inputIconColor}\n                            backgroundColor={theme.backgroundColor}\n                            style={{\n                                height: theme && theme.inputIconSize,\n                                width: theme && theme.inputIconSize,\n                            }}\n                        />\n                    ) : (\n                        searchIcon\n                    )}\n                </div>\n                <input\n                    ref={inputRef}\n                    spellCheck={false}\n                    autoFocus={autofocus}\n                    style={{\n                        ...inputStyle,\n                        WebkitTapHighlightColor: \"rgba(0,0,0,0)\",\n                        color: theme.foregroundColor,\n                        lineHeight: \"2em\",\n                        verticalAlign: \"baseline\",\n                        ...theme.titleFont,\n                        ...theme.inputFont,\n                        fontSize: theme.inputFontSize,\n                        // @ts-ignore\n                        \"--framer-search-placeholder-color\":\n                            theme.placeholderColor,\n                    }}\n                    onFocus={() => {\n                        const scrollOffset = document.documentElement.scrollTop\n                        document.documentElement.scrollTop = scrollOffset\n                    }}\n                    placeholder={placeholder}\n                    value={inputValue}\n                    onChange={() => setInputValue(inputRef.current.value)}\n                />\n                {showClearButton && (\n                    <ClearButton\n                        theme={theme}\n                        type={props.clearButtonType}\n                        text={props.clearButtonText}\n                        onClick={handleClearClick}\n                    />\n                )}\n            </div>\n        )\n    }\n)\n\nconst inputContainerStyle: CSSProperties = {\n    display: \"inline-flex\",\n    alignItems: \"center\",\n    flexShrink: 0,\n}\n\nconst inputStyle: CSSProperties = {\n    outline: \"none\",\n    border: \"none\",\n    background: \"transparent\",\n    fontWeight: 500,\n    height: \"2em\",\n    padding: 0,\n    width: \"100%\",\n}\n\ninterface ResultRowProps {\n    index: number\n    result: SearchItem\n    prevMousePositionRef: React.RefObject<Point>\n    type?: SearchResultItemType\n    subtitleType?: SearchResultSubtitleType\n    selected: boolean\n    theme: SearchTheme\n    localeSlug: string | undefined\n    onMouseMove: (event: React.MouseEvent, index: number) => void\n    onPointerDown: (event: React.PointerEvent, index: number) => void\n    onNavigateTo: (url: string) => void\n    style?: CSSProperties\n}\n\nexport const ResultRow = React.memo(\n    React.forwardRef<HTMLAnchorElement, ResultRowProps>(\n        function ResultRow(props, ref) {\n            const {\n                index,\n                result,\n                prevMousePositionRef,\n                type = SearchResultItemType.Contained,\n                subtitleType = SearchResultSubtitleType.Path,\n                selected = false,\n                theme,\n                localeSlug,\n                style,\n                onMouseMove,\n                onPointerDown,\n                onNavigateTo,\n            } = props\n\n            const { url, title, score } = result\n\n            const urlPath = useMemo(() => {\n                return stripLocaleSlugFromPath(url, localeSlug)\n            }, [url, localeSlug])\n\n            const handleMouseMove = useCallbackOnMouseMove(\n                (event) => onMouseMove(event, index),\n                prevMousePositionRef\n            )\n\n            const isContained = type === SearchResultItemType.Contained\n            const borderRadius = isContained\n                ? clamp(0, Infinity, theme.borderRadius - theme.spacing)\n                : 0\n\n            const subtitleText =\n                subtitleType === SearchResultSubtitleType.Path\n                    ? urlPath\n                    : clampText(result.description, MAX_DESCRIPTION_LENGTH)\n\n            const handleClick = (event: React.MouseEvent) => {\n                event.preventDefault()\n                onNavigateTo(result.url)\n            }\n\n            const focusTrap = (event) => {\n                event.preventDefault()\n            }\n\n            return (\n                <a\n                    ref={ref}\n                    style={{ textDecoration: \"none\" }}\n                    href={result.url}\n                    onClick={handleClick}\n                    onMouseMove={handleMouseMove}\n                    onMouseDown={focusTrap}\n                    onPointerDown={(event) => onPointerDown(event, index)}\n                >\n                    <li\n                        style={{\n                            ...resultContainer,\n                            ...style,\n                            paddingTop: isContained ? 12 : 16,\n                            paddingBottom: isContained ? 12 : 16,\n                            color: theme.foregroundColor,\n                            position: \"relative\",\n                            paddingLeft: theme && theme.horizontalSpacing,\n                            paddingRight: theme && theme.horizontalSpacing,\n                        }}\n                        key={result.url}\n                    >\n                        <div\n                            style={{\n                                backgroundColor: theme.foregroundColor,\n                                position: \"absolute\",\n                                opacity: selected ? 0.06 : 0,\n                                borderRadius,\n                                left: theme && isContained ? theme.spacing : 0,\n                                right: theme && isContained ? theme.spacing : 0,\n                                top: 0,\n                                bottom: 0,\n                            }}\n                        />\n                        <div\n                            style={{\n                                display: \"flex\",\n                                flexDirection: \"column\",\n                                overflow: \"hidden\",\n                                gap: 4,\n                            }}\n                        >\n                            <h3\n                                style={{\n                                    ...resultTitle,\n                                    ...theme.titleFont,\n                                    lineHeight: \"1.4em\",\n                                }}\n                            >\n                                {title}\n                            </h3>\n                            <p\n                                style={{\n                                    margin: 0,\n                                    color: theme.subtitleColor,\n                                    ...theme.subtitleFont,\n                                    whiteSpace: \"nowrap\",\n                                    overflow: \"hidden\",\n                                    textOverflow: \"ellipsis\",\n                                    lineHeight: \"1.4em\",\n                                }}\n                            >\n                                {localStorageDebugFlag ? score : \"\"}{\" \"}\n                                {subtitleText}\n                            </p>\n                        </div>\n                    </li>\n                </a>\n            )\n        }\n    )\n)\n\n/**\n * Flexible gap used inside a flexbox layout to push down the quick menu\n * by 20% of the screen height, but also allow it to collapse to zero if\n * there is not enough vertical room.\n */\nfunction QuickMenuSpacer({ onClick }: { onClick: () => void }) {\n    return (\n        <div style={{ width: \"100%\", flexBasis: \"20vh\" }} onClick={onClick} />\n    )\n}\n\ninterface LayoutContainerProps {\n    layoutType: SearchLayoutType\n    modalOptions: EntryPointProps[\"modalOptions\"]\n    theme: SearchTheme\n    onKeyDown: (event: React.KeyboardEvent) => void\n    onDismiss: () => void\n    children: React.ReactNode\n}\n\nconst layoutContainerStyle: React.CSSProperties = {\n    display: \"flex\",\n    flexDirection: \"column\",\n    alignItems: \"center\",\n    justifyContent: \"flex-start\",\n    gap: 15,\n    overflow: \"visible\",\n}\n\nfunction LayoutContainer({\n    layoutType,\n    theme,\n    onKeyDown,\n    onDismiss,\n    children,\n    modalOptions,\n}: LayoutContainerProps) {\n    const layoutStyles = getLayoutBaseStyles(layoutType, theme)\n\n    const style: React.CSSProperties = {\n        ...layoutContainerStyle,\n        ...layoutStyles,\n        willChange: \"transform\",\n        marginTop:\n            layoutType === SearchLayoutType.FixedTop ? theme.offsetTop : 0,\n        height: layoutType === SearchLayoutType.Sidebar ? \"100%\" : \"auto\",\n        maxHeight: layoutType === SearchLayoutType.QuickMenu ? \"100%\" : \"none\",\n        justifyContent:\n            layoutType === SearchLayoutType.Sidebar ? \"flex-end\" : \"flex-start\",\n        flexDirection:\n            layoutType === SearchLayoutType.Sidebar\n                ? \"column-reverse\"\n                : \"column\",\n    }\n\n    const innerStyle: MotionStyle = {\n        ...layoutContainerStyle,\n        ...layoutStyles,\n        height: layoutType === SearchLayoutType.Sidebar ? \"100%\" : \"auto\",\n        maxHeight: layoutType === SearchLayoutType.QuickMenu ? \"100%\" : \"none\",\n        gap:\n            layoutType === SearchLayoutType.Sidebar\n                ? 0\n                : theme.gapBetweenStatusAndSearch,\n        backgroundColor:\n            layoutType === SearchLayoutType.Sidebar\n                ? theme.backgroundColor\n                : \"transparent\",\n        justifyContent:\n            layoutType === SearchLayoutType.Sidebar ? \"flex-end\" : \"flex-start\",\n        flexDirection:\n            layoutType === SearchLayoutType.Sidebar\n                ? \"column-reverse\"\n                : \"column\",\n        originX: 0.5,\n        originY: 0.5,\n    }\n\n    function getContainerAnimation() {\n        switch (layoutType) {\n            case SearchLayoutType.FixedTop: {\n                const key = animationKeyFromLayout(SearchLayoutType.FixedTop)\n                const prop = modalOptions ? modalOptions[key] : undefined\n\n                if (prop) {\n                    return prop\n                } else {\n                    return {\n                        y: -10,\n                        opacity: 0.2,\n                        transition: { duration: Browser.isTouch() ? 0 : 0.15 },\n                    }\n                }\n                break\n            }\n            case SearchLayoutType.QuickMenu: {\n                const key = animationKeyFromLayout(SearchLayoutType.QuickMenu)\n                const prop = modalOptions ? modalOptions[key] : undefined\n\n                if (prop) {\n                    return prop\n                } else {\n                    return {\n                        scale: 0.95,\n                        opacity: 0,\n                        y: 0,\n                        x: 0,\n                        rotate: 0,\n                        transition: {\n                            type: \"spring\",\n                            stiffness: 600,\n                            damping: 40,\n                        },\n                    }\n                }\n                break\n            }\n            case SearchLayoutType.Sidebar: {\n                const key = animationKeyFromLayout(SearchLayoutType.Sidebar)\n                const prop = modalOptions ? modalOptions[key] : undefined\n\n                if (prop) {\n                    return prop\n                } else {\n                    return {\n                        x: -10,\n                        opacity: 0,\n                        transition: { duration: 0.15 },\n                    }\n                }\n                break\n            }\n        }\n    }\n\n    const containerAnimation = getContainerAnimation()\n\n    return (\n        <div\n            style={style}\n            onKeyDown={onKeyDown}\n            onClick={(event) => event.stopPropagation()}\n        >\n            {layoutType === SearchLayoutType.QuickMenu && (\n                <QuickMenuSpacer onClick={onDismiss} />\n            )}\n            <motion.div\n                initial={containerAnimation}\n                animate={{\n                    opacity: 1,\n                    scale: 1,\n                    x: 0,\n                    y: 0,\n                    rotate: 0,\n                }}\n                transition={\n                    containerAnimation\n                        ? containerAnimation.transition\n                        : undefined\n                }\n                exit={{ opacity: 0, transition: { duration: 0 } }}\n                style={innerStyle}\n            >\n                {children}\n            </motion.div>\n        </div>\n    )\n}\n\ninterface ModalContainerProps {\n    layoutType: SearchLayoutType\n    theme: SearchTheme\n    children: React.ReactNode\n    heightIsStatic: boolean\n    heightTransition: Transition\n    heightDeps: React.DependencyList\n}\n\nfunction ModalContainer({\n    layoutType,\n    theme,\n    children,\n    heightIsStatic,\n    heightTransition,\n    heightDeps,\n}: ModalContainerProps) {\n    const style: React.CSSProperties = {\n        // This `willChange` is required to avoid weird rendering issues where\n        // parts of the search window won't redraw, which we observed in Safari 16.4.\n        willChange: \"transform\",\n        backgroundColor: theme.backgroundColor,\n        color: theme.foregroundColor,\n        borderRadius:\n            layoutType === SearchLayoutType.QuickMenu ? theme.borderRadius : 0,\n        width: \"100%\",\n        display: \"flex\",\n        flexDirection: \"column\",\n        overflow: \"hidden\",\n        boxShadow:\n            layoutType !== SearchLayoutType.Sidebar ? theme.shadow : undefined,\n        maxHeight:\n            layoutType === SearchLayoutType.QuickMenu\n                ? // Never let the modal exceed 100vh - top & bottom padding\n                  `min(${MODAL_MAX_HEIGHT}px, calc(100vh - 30px))`\n                : undefined,\n    }\n\n    // Opt-in Height Animations for the Search Quick Actions menu.\n    // These are disabled by default, but can be enabled via props.\n    const [scope, animate] = useAnimate()\n    useLayoutEffect(() => {\n        if (layoutType !== SearchLayoutType.QuickMenu || heightIsStatic) return\n        const prevHeight = scope.current.offsetHeight\n        scope.current.style.height = \"auto\"\n        const height = scope.current.offsetHeight\n        scope.current.style.height = prevHeight + \"px\"\n\n        animate(\n            scope.current,\n            { height: [prevHeight, height] },\n            heightTransition\n        )\n    }, heightDeps)\n\n    return (\n        <div\n            ref={scope}\n            role=\"dialog\"\n            className={\n                layoutType === SearchLayoutType.FixedTop\n                    ? \"__framer-max-height-80dvh\"\n                    : undefined\n            }\n            style={style}\n        >\n            {children}\n        </div>\n    )\n}\n\ninterface ScrollViewProps {\n    theme: SearchTheme\n    children: React.ReactNode\n}\n\nconst ScrollView = React.forwardRef<HTMLDivElement, ScrollViewProps>(\n    function ScrollView(\n        { theme, children },\n        ref: React.MutableRefObject<HTMLDivElement>\n    ) {\n        const isTouch = Browser.isTouch()\n        const [canScroll, setCanScroll] = React.useState(true)\n\n        React.useEffect(() => {\n            if (!isTouch) return\n\n            const element = ref.current\n            if (!element) return\n            setCanScroll(element.scrollHeight > element.clientHeight)\n        })\n\n        return (\n            <div\n                ref={ref}\n                style={{\n                    width: `calc(100% + ${theme.scrollBarWidth}px)`,\n                    overflowY: \"scroll\",\n                    overflowX: \"hidden\",\n                    overscrollBehavior: \"contain\",\n                    touchAction: canScroll ? undefined : \"none\",\n\n                    // Make the list appear slightly under the divider\n                    // so that the divider is still visible when the first\n                    // item is selected.\n                    marginTop: -1,\n                }}\n            >\n                {children}\n            </div>\n        )\n    }\n)\n\ninterface StatusMessageProps {\n    status: SearchStatus\n    layoutType: SearchLayoutType\n    theme: SearchTheme\n}\n\nconst statusStyle: React.CSSProperties = {\n    backgroundColor: \"#B5B5B5\",\n    color: \"#FFF\",\n    boxShadow: \"0px 20px 40px 0px rgba(0, 0, 0, 0.25)\",\n    fontFamily: \"inherit\",\n    textAlign: \"center\",\n    fontSize: 13,\n    padding: \"8px 0\",\n}\n\nfunction StatusMessage({ status, layoutType, theme }: StatusMessageProps) {\n    const verticalSpacing = Math.floor(\n        theme ? theme.horizontalSpacing * VERTICAL_SPACING_MULTIPLIER : 0\n    )\n\n    const style: React.CSSProperties = {\n        ...statusStyle,\n        userSelect: \"none\",\n        fontFamily: getFontFamily(theme),\n        paddingLeft: theme && theme.horizontalSpacing,\n        paddingRight: theme && theme.horizontalSpacing,\n        fontWeight: 500,\n        lineHeight: `calc(${theme.inputFontSize} * 2)`,\n        paddingTop: verticalSpacing,\n        paddingBottom: verticalSpacing,\n        ...theme.titleFont,\n        zIndex: theme.zIndex + 1,\n        maxWidth:\n            layoutType === SearchLayoutType.FixedTop ? \"none\" : theme.width,\n        width:\n            layoutType === SearchLayoutType.FixedTop\n                ? `calc(100% - ${verticalSpacing * 2}px`\n                : \"100%\",\n        boxShadow:\n            layoutType !== SearchLayoutType.Sidebar && statusStyle.boxShadow,\n        borderRadius:\n            layoutType !== SearchLayoutType.Sidebar && theme.borderRadius,\n    }\n\n    // Show less text on fixed text to look nicer on mobile\n    const previewInfoText =\n        layoutType === SearchLayoutType.FixedTop\n            ? \"Preview Mode\"\n            : \"Preview Mode. Publish your Site to Search.\"\n\n    if (status === \"no-meta-tag-found\") {\n        return <div style={style}>{previewInfoText}</div>\n    }\n\n    if (status === \"pending-index-generation\") {\n        return <div style={style}>Site is being indexed</div>\n    }\n\n    return null\n}\n\nconst resultTitle: CSSProperties = {\n    textOverflow: \"ellipsis\",\n    maxWidth: \"100%\",\n    overflow: \"hidden\",\n    fontWeight: 500,\n    whiteSpace: \"nowrap\",\n    flex: 1,\n    margin: 0,\n}\n\nconst resultContainer: CSSProperties = {\n    padding: \"16px 20px\",\n    listStyle: \"none\",\n    fontWeight: 500,\n}\n\nconst sidebarStyles: React.CSSProperties = {\n    left: 0,\n    width: 500,\n}\n\nconst fixedTopStyles: React.CSSProperties = {\n    top: 0,\n    width: \"100%\",\n}\n\nconst quickMenuStyles: React.CSSProperties = {\n    width: 500,\n}\n\nfunction getLayoutBaseStyles(\n    layoutOption: SearchLayoutType,\n    theme: SearchTheme\n): React.CSSProperties {\n    switch (layoutOption) {\n        case SearchLayoutType.Sidebar:\n            return { ...sidebarStyles, width: theme.width }\n        case SearchLayoutType.FixedTop:\n            return fixedTopStyles\n        case SearchLayoutType.QuickMenu:\n            return {\n                ...quickMenuStyles,\n                width: theme.width,\n            }\n    }\n}\n\n// function getMaxHeightClass(\n//     layoutOption: SearchLayoutType,\n//     theme: SearchTheme\n// ): string {\n//     switch (layoutOption) {\n//         case SearchLayoutType.Sidebar:\n//             return \"none\"\n//         case SearchLayoutType.FixedTop:\n//             return \"80dvh\"\n//         case SearchLayoutType.QuickMenu:\n//             return \"510px\"\n//     }\n// }\n\nexport enum SearchInputClearButtonType {\n    Icon = \"icon\",\n    Text = \"text\",\n    None = \"none\",\n}\n\nexport enum SearchInputDividerType {\n    None = \"none\",\n    FullWidth = \"fullWidth\",\n    Contained = \"contained\",\n}\n\nexport enum SearchResultTitleType {\n    H1 = \"h1\",\n    Title = \"title\",\n}\n\nexport enum SearchResultSubtitleType {\n    Description = \"description\",\n    Path = \"path\",\n}\n\nexport enum SearchResultItemType {\n    FullWidth = \"fullWidth\",\n    Contained = \"contained\",\n}\n\nexport enum SearchLayoutType {\n    Sidebar = \"Sidebar\",\n    FixedTop = \"FixedTop\",\n    QuickMenu = \"QuickMenu\",\n}\n\nexport enum SearchEntryType {\n    Icon = \"icon\",\n    Text = \"text\",\n}\n\nexport enum SearchIconType {\n    Default = \"default\",\n    Custom = \"custom\",\n}\n\nexport interface SearchTheme {\n    scrollBarWidth: number\n    gapBetweenStatusAndSearch: number\n    gapBetweenResults: number\n    shadow: string\n    subtitleColor: string\n    titleFont: React.CSSProperties\n    subtitleFont: React.CSSProperties\n    backgroundColor: string\n    foregroundColor: string\n    offsetTop: number\n    width: number\n    spacing: number\n    margin: number\n    borderRadius: number\n    horizontalSpacing: number\n    entryIconColor: string\n    entryIconSize: number\n    entryIconImage: ResponsiveImage\n    inputFontSize: string | number\n    inputFont: React.CSSProperties\n    inputIconSize: number\n    placeholderColor: string\n    inputIconColor: string\n    zIndex: number\n    inputIconImage: ResponsiveImage\n    overlayTransition: Transition\n}\n\nexport interface SearchProps {\n    urlScope: string\n    layoutType: SearchLayoutType\n    theme: SearchTheme\n    modalOptions: EntryPointProps[\"modalOptions\"]\n    inputOptions: EntryPointProps[\"inputOptions\"]\n    resultOptions: EntryPointProps[\"resultOptions\"]\n    backdropOptions: { backgroundColor: string; zIndex: number }\n    onDismiss: () => void\n}\n\ninterface Selected {\n    index: number\n    scroll: boolean\n}\n\n/**\n * @framerSupportedLayoutWidth fixed\n * @framerSupportedLayoutHeight fixed\n */\nexport function SearchModal(props: SearchProps) {\n    const {\n        layoutType,\n        theme,\n        urlScope,\n        inputOptions,\n        backdropOptions,\n        modalOptions,\n        resultOptions,\n        onDismiss,\n    } = props\n\n    const { activeLocale } = useLocaleInfo()\n    const localeId = activeLocale?.id\n    const localeSlug = activeLocale?.slug\n\n    const input = useRef<HTMLInputElement>()\n    const selectedResultRow = useRef<HTMLAnchorElement>()\n    const scrollView = useRef<HTMLDivElement>()\n    const [selected, setSelected] = useState<Selected>({\n        index: 0,\n        scroll: true,\n    })\n    const prevMousePositionRef = useRef<Point>(null)\n\n    const [isKeyboardNavigationDisabled, setIsKeyboardNavigationDisabled] =\n        useState(Browser.isTouch)\n    const [query, setQuery] = useState(\"\")\n    const deferredQuery = useDeferredValue(query)\n\n    const { results, status } = useSearch(deferredQuery, {\n        minimumScore: 0,\n        urlScope,\n        titleType: resultOptions.titleType,\n    })\n\n    const selectedResult = results[selected.index]\n    const verticalSpacing = Math.floor(\n        theme ? theme.horizontalSpacing * VERTICAL_SPACING_MULTIPLIER : 0\n    )\n\n    useEffect(() => {\n        // Reset the selection to the top if the query changes.\n        setSelected({ index: 0, scroll: true })\n    }, [deferredQuery])\n\n    const handleResultRowPointerDown = useCallback(\n        (event: React.PointerEvent, index: number) => {\n            if (event.pointerType !== \"touch\") return\n\n            setIsKeyboardNavigationDisabled(true)\n            setSelected({ index, scroll: false })\n        },\n        []\n    )\n\n    const handleResultRowMouseMove = useCallback(\n        (event: React.MouseEvent, index: number) => {\n            setSelected((previousSelected) => {\n                if (previousSelected.index === index) {\n                    return previousSelected\n                }\n\n                return { index, scroll: false }\n            })\n        },\n        []\n    )\n\n    const router = useRouter()\n\n    const navigateTo = useCallback(\n        async (url: string) => {\n            if (status === \"no-meta-tag-found\") {\n                return\n            }\n\n            try {\n                // Ideally, we would directly expose `routeId` in the search index so that\n                // we don't need to infer it from the URL.\n                const { routeId, pathVariables } = inferInitialRouteFromPath(\n                    router.routes,\n                    url\n                )\n                const route = router.getRoute?.(routeId)\n\n                onDismiss()\n                await route?.page?.preload?.()\n\n                router.navigate?.(routeId, null, pathVariables, false)\n            } catch (error) {\n                window.location.href = url\n            }\n        },\n        [status]\n    )\n\n    const handleKeyDown = (event: React.KeyboardEvent) => {\n        const maxIndex = results.length - 1\n\n        switch (event.code) {\n            case \"ArrowUp\":\n                event.preventDefault()\n\n                if (isKeyboardNavigationDisabled) {\n                    setIsKeyboardNavigationDisabled(false)\n                    break\n                }\n\n                setSelected((previousSelected) => ({\n                    index: clamp(0, maxIndex, previousSelected.index - 1),\n                    scroll: true,\n                }))\n                break\n            case \"ArrowDown\":\n                event.preventDefault()\n\n                if (isKeyboardNavigationDisabled) {\n                    setIsKeyboardNavigationDisabled(false)\n                    break\n                }\n\n                setSelected((previousSelected) => ({\n                    index: clamp(0, maxIndex, previousSelected.index + 1),\n                    scroll: true,\n                }))\n                break\n            case \"Escape\":\n                break\n            case \"Enter\":\n                if (selectedResult) {\n                    navigateTo(selectedResult.url)\n                }\n                break\n            default:\n                event.stopPropagation()\n        }\n    }\n\n    const showNoResults =\n        results.length === 0 && deferredQuery.length > 1 && status !== \"loading\"\n\n    const showDivider = Boolean(\n        ((deferredQuery.length > 0 && results.length > 0) || showNoResults) &&\n            status !== \"loading\" &&\n            props.inputOptions &&\n            props.inputOptions.dividerType !== SearchInputDividerType.None\n    )\n\n    const isItemContained = Boolean(\n        props.resultOptions &&\n            props.resultOptions.itemType === SearchResultItemType.Contained\n    )\n\n    const spacing = isItemContained ? theme.spacing : 10\n    const listPaddingTop =\n        showDivider && isItemContained\n            ? spacing + theme.gapBetweenResults * 2\n            : 0\n\n    useEffect(() => {\n        if (!selected.scroll) return\n\n        const element = selectedResultRow.current\n        if (!element) return\n\n        scrollIntoView(element, scrollView.current, {\n            offsetTop: showDivider && isItemContained ? listPaddingTop : 0,\n            offsetBottom: isItemContained ? spacing : 0,\n        })\n\n        // `showDivider` and `isItemContained` are not dependencies because\n        // they will be the latest values when `selected` changes. And including\n        // them will cause unnecessary scrolling into view.\n    }, [selected])\n\n    return (\n        <LayoutContainer\n            layoutType={layoutType}\n            modalOptions={modalOptions}\n            theme={theme}\n            onKeyDown={handleKeyDown}\n            onDismiss={onDismiss}\n        >\n            <ModalContainer\n                layoutType={layoutType}\n                theme={theme}\n                heightIsStatic={modalOptions.heightIsStatic}\n                heightTransition={modalOptions.heightTransition}\n                heightDeps={[results.length, showNoResults]}\n            >\n                <Input\n                    autofocus\n                    ref={input}\n                    onChange={setQuery}\n                    value={query}\n                    theme={theme}\n                    status={status}\n                    iconType={inputOptions.iconOptions.iconType}\n                    placeholder={\n                        inputOptions.placeholderOptions.placeholderText\n                    }\n                    clearButtonType={\n                        inputOptions ? inputOptions.clearButtonType : undefined\n                    }\n                    clearButtonText={inputOptions.clearButtonText}\n                />\n                {showDivider && (\n                    <Divider theme={theme} type={inputOptions.dividerType} />\n                )}\n                <ScrollView ref={scrollView} theme={theme}>\n                    <ul\n                        aria-live=\"polite\"\n                        style={{\n                            display: \"flex\",\n                            flexDirection: \"column\",\n                            width: `calc(100% - ${theme.scrollBarWidth}px)`,\n                            padding: 0,\n                            paddingTop: listPaddingTop,\n                            paddingBottom:\n                                results.length && isItemContained ? spacing : 0,\n                            gap: theme.gapBetweenResults,\n                            margin: 0,\n                        }}\n                    >\n                        {results.map((result, index) => {\n                            const isSelected = index === selected.index\n\n                            return (\n                                <ResultRow\n                                    ref={isSelected ? selectedResultRow : null}\n                                    key={result.url}\n                                    index={index}\n                                    result={result}\n                                    prevMousePositionRef={prevMousePositionRef}\n                                    selected={\n                                        !isKeyboardNavigationDisabled &&\n                                        isSelected\n                                    }\n                                    type={props.resultOptions.itemType}\n                                    subtitleType={\n                                        props.resultOptions.subtitleOptions\n                                            .subtitleType\n                                    }\n                                    theme={theme}\n                                    localeSlug={localeSlug}\n                                    onMouseMove={handleResultRowMouseMove}\n                                    onPointerDown={handleResultRowPointerDown}\n                                    onNavigateTo={navigateTo}\n                                />\n                            )\n                        })}\n                        {showNoResults && (\n                            <li\n                                style={{\n                                    paddingTop:\n                                        verticalSpacing - listPaddingTop,\n                                    paddingBottom: verticalSpacing,\n                                    lineHeight: \"2em\",\n                                    paddingLeft:\n                                        theme && theme.horizontalSpacing,\n                                    paddingRight:\n                                        theme && theme.horizontalSpacing,\n                                    height: SearchLayoutType.Sidebar\n                                        ? \"100%\"\n                                        : \"auto\",\n                                }}\n                            >\n                                <h3\n                                    style={{\n                                        ...resultTitle,\n                                        textAlign: \"center\",\n                                        lineHeight: `calc(${theme.inputFontSize} * 2)`,\n                                        color: theme.subtitleColor,\n                                        ...theme.titleFont,\n                                    }}\n                                >\n                                    No results\n                                </h3>\n                            </li>\n                        )}\n                    </ul>\n                </ScrollView>\n            </ModalContainer>\n            <StatusMessage\n                status={status}\n                layoutType={layoutType}\n                theme={theme}\n            />\n        </LayoutContainer>\n    )\n}\n"],"names":[],"mappings":"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"}