docs: add search to workflows reference (#11054)
* docs: add search to workflows reference * fix error
This commit is contained in:
@@ -1,21 +1,25 @@
|
||||
"use client"
|
||||
|
||||
import React, { useCallback, useMemo } from "react"
|
||||
import React, { useCallback, useEffect, useMemo, useState } from "react"
|
||||
import {
|
||||
Card,
|
||||
CardList,
|
||||
getLocalSearch,
|
||||
H2,
|
||||
H3,
|
||||
H4,
|
||||
Hr,
|
||||
isSidebarItemLink,
|
||||
LocalSearch,
|
||||
MarkdownContent,
|
||||
SearchInput,
|
||||
useIsBrowser,
|
||||
useSidebar,
|
||||
} from "../.."
|
||||
import { InteractiveSidebarItem, SidebarItem, SidebarItemLink } from "types"
|
||||
import slugify from "slugify"
|
||||
import { MDXComponents } from "../.."
|
||||
import { ChevronDoubleRight } from "@medusajs/icons"
|
||||
import { ChevronDoubleRight, ExclamationCircle } from "@medusajs/icons"
|
||||
|
||||
type HeadingComponent = (
|
||||
props: React.HTMLAttributes<HTMLHeadingElement>
|
||||
@@ -32,6 +36,11 @@ export type UseChildDocsProps = {
|
||||
childLevel?: number
|
||||
itemsPerRow?: number
|
||||
defaultItemsPerRow?: number
|
||||
search?: {
|
||||
enable: boolean
|
||||
storageKey?: string
|
||||
placeholder?: string
|
||||
}
|
||||
}
|
||||
|
||||
export const useChildDocs = ({
|
||||
@@ -45,8 +54,18 @@ export const useChildDocs = ({
|
||||
childLevel = 1,
|
||||
itemsPerRow,
|
||||
defaultItemsPerRow,
|
||||
search: {
|
||||
enable: enableSearch = false,
|
||||
storageKey = "child-docs",
|
||||
...searchProps
|
||||
} = { enable: false },
|
||||
}: UseChildDocsProps) => {
|
||||
const { currentItems, activeItem } = useSidebar()
|
||||
const { isBrowser } = useIsBrowser()
|
||||
const [searchQuery, setSearchQuery] = useState("")
|
||||
const [localSearch, setLocalSearch] = useState<
|
||||
LocalSearch<SidebarItemLink> | undefined
|
||||
>()
|
||||
const TitleHeaderComponent = useCallback(
|
||||
(level: number): HeadingComponent => {
|
||||
switch (level) {
|
||||
@@ -92,16 +111,11 @@ export const useChildDocs = ({
|
||||
}
|
||||
}
|
||||
|
||||
const filterItems = (items: SidebarItem[]): SidebarItem[] => {
|
||||
return items
|
||||
.filter(filterCondition)
|
||||
const filterItems = (items: SidebarItem[]): InteractiveSidebarItem[] => {
|
||||
return (items.filter(filterCondition) as InteractiveSidebarItem[])
|
||||
.map((item) => Object.assign({}, item))
|
||||
.map((item) => {
|
||||
if (
|
||||
item.type !== "separator" &&
|
||||
item.children &&
|
||||
filterType === "hide"
|
||||
) {
|
||||
if (item.children && filterType === "hide") {
|
||||
item.children = filterItems(item.children)
|
||||
}
|
||||
|
||||
@@ -109,25 +123,6 @@ export const useChildDocs = ({
|
||||
})
|
||||
}
|
||||
|
||||
const filteredItems = useMemo(() => {
|
||||
const targetItems =
|
||||
type === "sidebar"
|
||||
? currentItems
|
||||
? Object.assign({}, currentItems)
|
||||
: undefined
|
||||
: {
|
||||
default: [...(activeItem?.children || [])],
|
||||
}
|
||||
if (filterType === "all" || !targetItems) {
|
||||
return targetItems
|
||||
}
|
||||
|
||||
return {
|
||||
...targetItems,
|
||||
default: filterItems(targetItems.default),
|
||||
}
|
||||
}, [currentItems, type, activeItem, filterItems])
|
||||
|
||||
const filterNonInteractiveItems = (
|
||||
items: SidebarItem[] | undefined
|
||||
): InteractiveSidebarItem[] => {
|
||||
@@ -164,11 +159,115 @@ export const useChildDocs = ({
|
||||
return childrenResult
|
||||
}
|
||||
|
||||
const getTopLevelElms = (items?: SidebarItem[]) => {
|
||||
const filteredItems = useMemo(() => {
|
||||
let targetItems =
|
||||
type === "sidebar"
|
||||
? currentItems
|
||||
? Object.assign({}, currentItems)
|
||||
: undefined
|
||||
: {
|
||||
default: [...(activeItem?.children || [])],
|
||||
}
|
||||
if (filterType !== "all" && targetItems) {
|
||||
targetItems = {
|
||||
...targetItems,
|
||||
default: filterItems(targetItems.default),
|
||||
}
|
||||
}
|
||||
|
||||
return targetItems
|
||||
? {
|
||||
...targetItems,
|
||||
default: filterNonInteractiveItems(targetItems?.default),
|
||||
}
|
||||
: undefined
|
||||
}, [currentItems, type, activeItem, filterType])
|
||||
|
||||
const searchableItems = useMemo(() => {
|
||||
const searchableItems: SidebarItemLink[] = []
|
||||
if (!enableSearch) {
|
||||
return searchableItems
|
||||
}
|
||||
if (onlyTopLevel) {
|
||||
filteredItems?.default?.forEach((item) => {
|
||||
if (isSidebarItemLink(item)) {
|
||||
searchableItems.push(item)
|
||||
} else {
|
||||
const firstChild = item.children?.find((child) =>
|
||||
isSidebarItemLink(child)
|
||||
)
|
||||
if (firstChild) {
|
||||
searchableItems.push(firstChild as SidebarItemLink)
|
||||
}
|
||||
}
|
||||
})
|
||||
} else {
|
||||
filteredItems?.default?.forEach((item) => {
|
||||
const childItems: SidebarItemLink[] =
|
||||
(getChildrenForLevel(item)?.filter((childItem) => {
|
||||
return isSidebarItemLink(childItem)
|
||||
}) as SidebarItemLink[]) || []
|
||||
searchableItems.push(...childItems)
|
||||
})
|
||||
}
|
||||
|
||||
return searchableItems
|
||||
}, [filteredItems, onlyTopLevel, enableSearch])
|
||||
|
||||
useEffect(() => {
|
||||
if (!enableSearch && localSearch) {
|
||||
setLocalSearch(undefined)
|
||||
return
|
||||
}
|
||||
if (!enableSearch || !searchableItems?.length || localSearch) {
|
||||
return
|
||||
}
|
||||
|
||||
setLocalSearch(
|
||||
getLocalSearch<SidebarItemLink>({
|
||||
docs: searchableItems,
|
||||
searchableFields: ["title", "description"],
|
||||
options: {
|
||||
storeFields: ["title", "description", "path", "type"],
|
||||
searchOptions: {
|
||||
boost: { title: 2 },
|
||||
prefix: true,
|
||||
fuzzy: 0.2,
|
||||
},
|
||||
idField: "path",
|
||||
},
|
||||
})
|
||||
)
|
||||
}, [searchableItems, enableSearch, localSearch])
|
||||
|
||||
const searchResult = useMemo(() => {
|
||||
return localSearch?.search(searchQuery) || []
|
||||
}, [localSearch, searchQuery])
|
||||
|
||||
useEffect(() => {
|
||||
if (!isBrowser || !enableSearch) {
|
||||
return
|
||||
}
|
||||
|
||||
const storedQuery = localStorage.getItem(`${storageKey}-query`)
|
||||
if (storedQuery) {
|
||||
setSearchQuery(storedQuery)
|
||||
}
|
||||
}, [isBrowser, storageKey, enableSearch])
|
||||
|
||||
useEffect(() => {
|
||||
if (!isBrowser || !enableSearch) {
|
||||
return
|
||||
}
|
||||
|
||||
localStorage.setItem(`${storageKey}-query`, searchQuery)
|
||||
}, [isBrowser, searchQuery, storageKey, enableSearch])
|
||||
|
||||
const getTopLevelElms = (items?: InteractiveSidebarItem[]) => {
|
||||
return (
|
||||
<CardList
|
||||
items={
|
||||
filterNonInteractiveItems(items).map((childItem) => {
|
||||
items?.map((childItem) => {
|
||||
const href = isSidebarItemLink(childItem)
|
||||
? childItem.path
|
||||
: childItem.children?.length
|
||||
@@ -193,11 +292,10 @@ export const useChildDocs = ({
|
||||
}
|
||||
|
||||
const getAllLevelsElms = (
|
||||
items?: SidebarItem[],
|
||||
items?: InteractiveSidebarItem[],
|
||||
headerLevel = titleLevel
|
||||
) => {
|
||||
const filteredItems = filterNonInteractiveItems(items)
|
||||
return filteredItems.map((item, key) => {
|
||||
return items?.map((item, key) => {
|
||||
const itemChildren = getChildrenForLevel(item)
|
||||
const HeadingComponent = itemChildren?.length
|
||||
? TitleHeaderComponent(headerLevel)
|
||||
@@ -243,7 +341,7 @@ export const useChildDocs = ({
|
||||
defaultItemsPerRow={defaultItemsPerRow}
|
||||
/>
|
||||
)}
|
||||
{key !== filteredItems.length - 1 && headerLevel === 2 && <Hr />}
|
||||
{key !== items.length - 1 && headerLevel === 2 && <Hr />}
|
||||
</>
|
||||
)}
|
||||
{!HeadingComponent && isSidebarItemLink(item) && (
|
||||
@@ -259,12 +357,64 @@ export const useChildDocs = ({
|
||||
})
|
||||
}
|
||||
|
||||
const getElms = (items?: SidebarItem[]) => {
|
||||
return onlyTopLevel ? getTopLevelElms(items) : getAllLevelsElms(items)
|
||||
const getSearchResultElms = () => {
|
||||
const Heading = TitleHeaderComponent(titleLevel)
|
||||
return (
|
||||
<>
|
||||
<Heading>Search Results</Heading>
|
||||
{searchResult.length > 0 && (
|
||||
<CardList
|
||||
items={searchResult.map((item) => ({
|
||||
title: item.title,
|
||||
href: item.path,
|
||||
text: item.description,
|
||||
rightIcon: item.type === "ref" ? ChevronDoubleRight : undefined,
|
||||
highlightText: item.terms,
|
||||
}))}
|
||||
itemsPerRow={itemsPerRow}
|
||||
defaultItemsPerRow={defaultItemsPerRow}
|
||||
className="my-docs_2"
|
||||
/>
|
||||
)}
|
||||
{!searchResult.length && (
|
||||
<div className="flex flex-col justify-center items-center gap-docs_0.75">
|
||||
<ExclamationCircle className="text-medusa-fg-subtle" />
|
||||
<span className="text-compact-small-plus text-medusa-fg-subtle text-center">
|
||||
No results found matching your query.
|
||||
</span>
|
||||
<span className="text-compact-small text-medusa-fg-muted text-center">
|
||||
Try searching with another term or clearing the search.
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
const getElms = () => {
|
||||
return (
|
||||
<>
|
||||
{enableSearch && (
|
||||
<SearchInput
|
||||
value={searchQuery || ""}
|
||||
onChange={setSearchQuery}
|
||||
{...searchProps}
|
||||
/>
|
||||
)}
|
||||
{searchQuery && getSearchResultElms()}
|
||||
{!searchQuery && (
|
||||
<>
|
||||
{onlyTopLevel
|
||||
? getTopLevelElms(filteredItems?.default)
|
||||
: getAllLevelsElms(filteredItems?.default)}
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
return {
|
||||
items: filteredItems,
|
||||
component: getElms(filteredItems?.default),
|
||||
component: getElms(),
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user