docs,api-ref: added search filters (#4830)

* initial implementation of search modal

* added hit and search suggestions

* added support for multiple indices

* updated sample env

* added close when click outside dropdown

* test for mobile

* added mobile design

* added shortcut

* dark mode fixes

* added search to docs

* added plugins filter

* added React import

* moved filters to configurations

* handled error on page load

* change suggestion text

* removed hits limit

* handle select all

* open link in current tab

* change highlight colors

* added support for shortcuts + auto focus

* change header and footer

* redesigned search ui
This commit is contained in:
Shahed Nasser
2023-08-24 18:36:06 +03:00
committed by GitHub
parent f4bf9ee169
commit f07dc0384f
109 changed files with 4555 additions and 1648 deletions

View File

@@ -0,0 +1,70 @@
import { useCallback, useEffect } from "react"
import { usePageLoading } from "../providers/page-loading"
type useKeyboardShortcutOptions = {
metakey?: boolean
shortcutKeys: string[]
action: (e: KeyboardEvent) => void
checkEditing?: boolean
preventDefault?: boolean
}
const useKeyboardShortcut = ({
metakey = true,
shortcutKeys,
action,
checkEditing = true,
preventDefault = true,
}: useKeyboardShortcutOptions) => {
const { isLoading } = usePageLoading()
function isEditingContent(event: KeyboardEvent) {
const element = event.target as HTMLElement
const tagName = element.tagName
return (
element.isContentEditable ||
tagName === "INPUT" ||
tagName === "SELECT" ||
tagName === "TEXTAREA"
)
}
const checkKeysPressed = useCallback(
(pressedKey: string) => {
const lowerPressedKey = pressedKey.toLowerCase()
return shortcutKeys.some(
(value) => lowerPressedKey === value.toLowerCase()
)
},
[shortcutKeys]
)
const sidebarShortcut = useCallback(
(e: KeyboardEvent) => {
if (isLoading) {
return
}
if (
(!metakey || e.metaKey || e.ctrlKey) &&
checkKeysPressed(e.key) &&
(!checkEditing || !isEditingContent(e))
) {
if (preventDefault) {
e.preventDefault()
}
action(e)
}
},
[isLoading, metakey, checkKeysPressed, checkEditing, action, preventDefault]
)
useEffect(() => {
window.addEventListener("keydown", sidebarShortcut)
return () => {
window.removeEventListener("keydown", sidebarShortcut)
}
}, [sidebarShortcut])
}
export default useKeyboardShortcut

View File

@@ -0,0 +1,93 @@
import { useCallback, useMemo } from "react"
export type OptionType = {
value: string
label: string
index?: string
isAllOption?: boolean
}
export type SelectOptions = {
value: string | string[]
multiple?: boolean
options: OptionType[]
setSelected?: (value: string | string[]) => void
addSelected?: (value: string) => void
removeSelected?: (value: string) => void
handleAddAll?: (isAllSelected: boolean) => void
}
const useSelect = ({
value,
options,
multiple = false,
setSelected,
addSelected,
removeSelected,
handleAddAll,
}: SelectOptions) => {
const isValueSelected = useCallback(
(val: string) => {
return (
(typeof value === "string" && val === value) ||
(Array.isArray(value) && value.includes(val))
)
},
[value]
)
// checks if there are multiple selected values
const hasSelectedValues = useMemo(() => {
return multiple && Array.isArray(value) && value.length > 0
}, [value, multiple])
// checks if there are any selected values,
// whether multiple or one
const hasSelectedValue = useMemo(() => {
return hasSelectedValues || (typeof value === "string" && value.length)
}, [hasSelectedValues, value])
const selectedValues: OptionType[] = useMemo(() => {
if (typeof value === "string") {
const selectedValue = options.find((option) => option.value === value)
return selectedValue ? [selectedValue] : []
} else if (Array.isArray(value)) {
return options.filter((option) => value.includes(option.value))
}
return []
}, [options, value])
const isAllSelected = useMemo(() => {
return Array.isArray(value) && value.length === options.length
}, [options, value])
const handleChange = (selectedValue: string, wasSelected: boolean) => {
if (multiple) {
wasSelected
? removeSelected?.(selectedValue)
: addSelected?.(selectedValue)
} else {
setSelected?.(selectedValue)
}
}
const handleSelectAll = () => {
if (handleAddAll) {
handleAddAll(isAllSelected)
} else {
setSelected?.(options.map((option) => option.value))
}
}
return {
isValueSelected,
hasSelectedValue,
hasSelectedValues,
selectedValues,
isAllSelected,
handleChange,
handleSelectAll,
}
}
export default useSelect