@graphcommerce/magento-search 9.0.0-canary.98 → 9.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +36 -951
- package/components/CategorySearchResult/CategorySearchResult.tsx +5 -4
- package/components/CategorySearchResult/CategorySearchResults.tsx +3 -1
- package/components/NoSearchResults/NoSearchResults.tsx +7 -2
- package/components/ProductFiltersPro/ProductFiltersProCategorySectionSearch.tsx +6 -6
- package/components/ProductFiltersPro/ProductFiltersProSearchHeader.tsx +15 -4
- package/components/ProductFiltersPro/ProductFiltersProSearchInput.tsx +2 -5
- package/components/ProductFiltersPro/{ProductFiltersProSearchField.tsx → SearchField.tsx} +10 -7
- package/components/ProductFiltersPro/useSearchPageAndParam.ts +1 -1
- package/components/SearchButton/SearchButton.tsx +4 -3
- package/components/SearchFab/SearchFab.tsx +24 -0
- package/components/SearchForm/SearchForm.tsx +4 -2
- package/components/SearchForm/SearchFormAdornment.tsx +3 -2
- package/components/SearchLink/SearchLink.tsx +6 -5
- package/hooks/useProductList.ts +14 -10
- package/index.ts +3 -1
- package/package.json +13 -11
- package/tsconfig.json +1 -1
- package/utils/productListApplySearchDefaults.ts +8 -3
@@ -1,14 +1,15 @@
|
|
1
|
-
import { Highlight,
|
2
|
-
import {
|
1
|
+
import { Highlight, IconSvg, extendableComponent, iconChevronRight } from '@graphcommerce/next-ui'
|
2
|
+
import type { SxProps, Theme } from '@mui/material'
|
3
|
+
import { Button } from '@mui/material'
|
3
4
|
import React from 'react'
|
4
|
-
import { CategorySearchResultFragment } from './CategorySearchResult.gql'
|
5
|
+
import type { CategorySearchResultFragment } from './CategorySearchResult.gql'
|
5
6
|
|
6
7
|
export type CategorySearchResultProps = Omit<CategorySearchResultFragment, 'uid'> & {
|
7
8
|
search?: string
|
8
9
|
sx?: SxProps<Theme>
|
9
10
|
}
|
10
11
|
|
11
|
-
const name = 'CategorySearchResult'
|
12
|
+
const name = 'CategorySearchResult'
|
12
13
|
const parts = ['root'] as const
|
13
14
|
const { classes } = extendableComponent(name, parts)
|
14
15
|
|
@@ -1,10 +1,12 @@
|
|
1
|
-
import {
|
1
|
+
import type { SxProps, Theme } from '@mui/material'
|
2
|
+
import { Box } from '@mui/material'
|
2
3
|
|
3
4
|
export type CategorySearchResultsProps = {
|
4
5
|
children: React.ReactNode
|
5
6
|
sx?: SxProps<Theme>
|
6
7
|
}
|
7
8
|
|
9
|
+
/** @public */
|
8
10
|
export function CategorySearchResults(props: CategorySearchResultsProps) {
|
9
11
|
const { children, sx = [] } = props
|
10
12
|
return <Box sx={sx}>{children}</Box>
|
@@ -1,13 +1,18 @@
|
|
1
1
|
import { extendableComponent } from '@graphcommerce/next-ui'
|
2
2
|
import { Trans } from '@lingui/react'
|
3
|
-
import {
|
3
|
+
import type { SxProps, Theme } from '@mui/material'
|
4
|
+
import { Box, Typography } from '@mui/material'
|
4
5
|
|
5
6
|
export type NoSearchResultsProps = { sx?: SxProps<Theme> }
|
6
7
|
|
7
|
-
const name = 'NoSearchResults'
|
8
|
+
const name = 'NoSearchResults'
|
8
9
|
const parts = ['root'] as const
|
9
10
|
const { classes } = extendableComponent(name, parts)
|
10
11
|
|
12
|
+
/**
|
13
|
+
* @deprecated
|
14
|
+
* @public
|
15
|
+
*/
|
11
16
|
export function NoSearchResults(props: NoSearchResultsProps) {
|
12
17
|
const { sx = [] } = props
|
13
18
|
|
@@ -1,11 +1,11 @@
|
|
1
1
|
import type {
|
2
|
-
MenuQueryFragment,
|
3
2
|
CategoryTreeItem,
|
3
|
+
MenuQueryFragment,
|
4
4
|
NavigationItemFragment,
|
5
5
|
} from '@graphcommerce/magento-category'
|
6
|
+
import type { ProductFiltersProCategoryAccordionProps } from '@graphcommerce/magento-product'
|
6
7
|
import {
|
7
8
|
ProductFiltersProCategoryAccordion,
|
8
|
-
ProductFiltersProCategoryAccordionProps,
|
9
9
|
useProductFiltersPro,
|
10
10
|
} from '@graphcommerce/magento-product'
|
11
11
|
import { filterNonNullableKeys } from '@graphcommerce/next-ui'
|
@@ -79,7 +79,7 @@ function isParent<U extends TreeItem>(item: U, parent: U): boolean {
|
|
79
79
|
return false
|
80
80
|
}
|
81
81
|
|
82
|
-
type ProductFiltersProCategorySectionSearchProps = Omit<
|
82
|
+
export type ProductFiltersProCategorySectionSearchProps = Omit<
|
83
83
|
ProductFiltersProCategoryAccordionProps,
|
84
84
|
'categoryTree' | 'onChange'
|
85
85
|
> & {
|
@@ -90,7 +90,7 @@ export function ProductFiltersProCategorySectionSearch(
|
|
90
90
|
props: ProductFiltersProCategorySectionSearchProps,
|
91
91
|
) {
|
92
92
|
const { menu } = props
|
93
|
-
const { form, submit, params, aggregations
|
93
|
+
const { form, submit, params, aggregations } = useProductFiltersPro()
|
94
94
|
const currentFilter = params.filters.category_uid?.in
|
95
95
|
|
96
96
|
const categoryTree = useMemo(() => {
|
@@ -148,9 +148,9 @@ export function ProductFiltersProCategorySectionSearch(
|
|
148
148
|
})
|
149
149
|
.slice(1)
|
150
150
|
.filter((c) => c.visible)
|
151
|
-
}, [
|
151
|
+
}, [aggregations, currentFilter, menu?.items])
|
152
152
|
|
153
|
-
if (!categoryTree) return null
|
153
|
+
if (!categoryTree.length) return null
|
154
154
|
|
155
155
|
return (
|
156
156
|
<ProductFiltersProCategoryAccordion
|
@@ -1,9 +1,10 @@
|
|
1
|
-
import { ProductListParams
|
1
|
+
import type { ProductListParams } from '@graphcommerce/magento-product'
|
2
|
+
import { useProductFiltersPro } from '@graphcommerce/magento-product'
|
2
3
|
import { useWatch } from '@graphcommerce/react-hook-form'
|
3
4
|
import { Trans } from '@lingui/macro'
|
4
5
|
import { Box } from '@mui/material'
|
5
6
|
|
6
|
-
type ProductFiltersProSearchHeaderProps = {
|
7
|
+
export type ProductFiltersProSearchHeaderProps = {
|
7
8
|
params: ProductListParams
|
8
9
|
/**
|
9
10
|
* Provide a text when there is no term searched
|
@@ -11,8 +12,7 @@ type ProductFiltersProSearchHeaderProps = {
|
|
11
12
|
children: React.ReactNode
|
12
13
|
}
|
13
14
|
|
14
|
-
export function
|
15
|
-
const { params, children } = props
|
15
|
+
export function useSearchResultRemaining(params: ProductListParams) {
|
16
16
|
const { form } = useProductFiltersPro()
|
17
17
|
const resultSearch = params.search ?? ''
|
18
18
|
const targetSearch = useWatch({ control: form.control, name: 'search' }) ?? ''
|
@@ -21,6 +21,17 @@ export function ProductFiltersProSearchTerm(props: ProductFiltersProSearchHeader
|
|
21
21
|
? targetSearch.slice(resultSearch.length)
|
22
22
|
: ''
|
23
23
|
|
24
|
+
return {
|
25
|
+
resultSearch,
|
26
|
+
targetSearch,
|
27
|
+
remaining,
|
28
|
+
}
|
29
|
+
}
|
30
|
+
|
31
|
+
export function ProductFiltersProSearchTerm(props: ProductFiltersProSearchHeaderProps) {
|
32
|
+
const { params, children } = props
|
33
|
+
|
34
|
+
const { remaining, resultSearch, targetSearch } = useSearchResultRemaining(params)
|
24
35
|
if (!resultSearch && !targetSearch) return children
|
25
36
|
|
26
37
|
const search = (
|
@@ -1,17 +1,14 @@
|
|
1
1
|
import { globalFormContextRef } from '@graphcommerce/magento-product'
|
2
2
|
import { IconSvg, iconClose } from '@graphcommerce/next-ui'
|
3
3
|
import { t } from '@lingui/macro'
|
4
|
-
import {
|
4
|
+
import type {
|
5
5
|
ButtonBaseProps,
|
6
|
-
FormControl,
|
7
6
|
FormControlProps,
|
8
|
-
IconButton,
|
9
7
|
IconButtonProps,
|
10
8
|
InputBaseProps,
|
11
|
-
OutlinedInput,
|
12
9
|
OutlinedInputProps,
|
13
|
-
useForkRef,
|
14
10
|
} from '@mui/material'
|
11
|
+
import { FormControl, IconButton, OutlinedInput, useForkRef } from '@mui/material'
|
15
12
|
import { useRouter } from 'next/router'
|
16
13
|
import { useEffect, useRef } from 'react'
|
17
14
|
import { useSearchPageAndParam } from './useSearchPageAndParam'
|
@@ -1,20 +1,23 @@
|
|
1
|
-
import {
|
2
|
-
import {
|
1
|
+
import { iconSearch, IconSvg, showPageLoadIndicator } from '@graphcommerce/next-ui'
|
2
|
+
import type { FabProps } from '@mui/material'
|
3
|
+
import { Fab } from '@mui/material'
|
3
4
|
import dynamic from 'next/dynamic'
|
4
5
|
import { useMemo, useState } from 'react'
|
5
|
-
import { ProductFiltersProSearchInputProps } from './ProductFiltersProSearchInput'
|
6
|
+
import type { ProductFiltersProSearchInputProps } from './ProductFiltersProSearchInput'
|
6
7
|
import { useSearchPageAndParam } from './useSearchPageAndParam'
|
7
8
|
|
8
|
-
type
|
9
|
+
export type SearchFieldProps = ProductFiltersProSearchInputProps & {
|
9
10
|
fab?: FabProps
|
11
|
+
visible?: boolean
|
12
|
+
searchField?: Record<string, unknown>
|
10
13
|
}
|
11
14
|
|
12
15
|
const ProductFiltersProSearchInputLazy = dynamic(
|
13
16
|
async () => (await import('./ProductFiltersProSearchInput')).ProductFiltersProSearchOutlinedInput,
|
14
17
|
)
|
15
18
|
|
16
|
-
export function
|
17
|
-
const { fab, formControl } = props
|
19
|
+
export function SearchField(props: SearchFieldProps) {
|
20
|
+
const { fab, formControl, visible: incomingVisible } = props
|
18
21
|
|
19
22
|
const [searchPage] = useSearchPageAndParam()
|
20
23
|
const [expanded, setExpanded] = useState(searchPage)
|
@@ -22,7 +25,7 @@ export function ProductFiltersProSearchField(props: ProductFiltersProSearchField
|
|
22
25
|
if (!searchPage) setExpanded(searchPage)
|
23
26
|
}, [searchPage])
|
24
27
|
|
25
|
-
const visible = expanded || searchPage
|
28
|
+
const visible = incomingVisible || expanded || searchPage
|
26
29
|
|
27
30
|
return (
|
28
31
|
<>
|
@@ -5,7 +5,7 @@ export function useSearchPageAndParam() {
|
|
5
5
|
const router = useRouter()
|
6
6
|
|
7
7
|
const path = router.asPath.startsWith('/c/') ? router.asPath.slice(3) : router.asPath.slice(1)
|
8
|
-
const [url
|
8
|
+
const [url] = extractUrlQuery({ url: path.split('#')[0].split('/') })
|
9
9
|
const searchParam = url?.startsWith('search') ? decodeURI(url.split('/')[1] ?? '') : null
|
10
10
|
const searchPage = router.asPath.startsWith('/search')
|
11
11
|
return [searchPage, searchParam] as const
|
@@ -1,12 +1,13 @@
|
|
1
|
-
import {
|
1
|
+
import { IconSvg, extendableComponent, iconSearch, responsiveVal } from '@graphcommerce/next-ui'
|
2
2
|
import { Trans } from '@lingui/react'
|
3
3
|
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
|
4
|
-
import {
|
4
|
+
import type { TextFieldProps } from '@mui/material'
|
5
|
+
import { TextField } from '@mui/material'
|
5
6
|
|
6
7
|
export type SearchButtonProps = TextFieldProps
|
7
8
|
|
8
9
|
type OwnerState = { fullWidth?: boolean }
|
9
|
-
const name = 'SearchButton'
|
10
|
+
const name = 'SearchButton'
|
10
11
|
const parts = ['root', 'inputRoot'] as const
|
11
12
|
const { withState } = extendableComponent<OwnerState, typeof name, typeof parts>(name, parts)
|
12
13
|
|
@@ -0,0 +1,24 @@
|
|
1
|
+
import type { FabProps } from '@graphcommerce/next-ui'
|
2
|
+
import { Fab, iconSearch } from '@graphcommerce/next-ui'
|
3
|
+
import { useRouter } from 'next/router'
|
4
|
+
import type { SetOptional } from 'type-fest'
|
5
|
+
|
6
|
+
export type SearchFabProps = SetOptional<FabProps, 'icon'>
|
7
|
+
|
8
|
+
export function SearchFab(props: SearchFabProps) {
|
9
|
+
const { sx, ...fabProps } = props
|
10
|
+
const router = useRouter()
|
11
|
+
return (
|
12
|
+
<Fab
|
13
|
+
color='inherit'
|
14
|
+
size='medium'
|
15
|
+
sx={sx}
|
16
|
+
icon={iconSearch}
|
17
|
+
onClick={async () => {
|
18
|
+
await router.push('/search')
|
19
|
+
globalThis.document.body.querySelector<HTMLInputElement>('[name="search"]')?.focus()
|
20
|
+
}}
|
21
|
+
{...fabProps}
|
22
|
+
/>
|
23
|
+
)
|
24
|
+
}
|
@@ -1,7 +1,9 @@
|
|
1
|
-
import {
|
1
|
+
import type { TextFieldElementProps } from '@graphcommerce/ecommerce-ui'
|
2
|
+
import { TextFieldElement } from '@graphcommerce/ecommerce-ui'
|
2
3
|
import { extendableComponent } from '@graphcommerce/next-ui'
|
3
4
|
import { FormAutoSubmit, useForm } from '@graphcommerce/react-hook-form'
|
4
|
-
import {
|
5
|
+
import type { SxProps, Theme } from '@mui/material'
|
6
|
+
import { Box } from '@mui/material'
|
5
7
|
import { useRouter } from 'next/router'
|
6
8
|
import { useEffect, useRef } from 'react'
|
7
9
|
import { SearchFormAdornment } from './SearchFormAdornment'
|
@@ -1,5 +1,6 @@
|
|
1
|
-
import { IconSvg,
|
2
|
-
import { Control, FieldPath, FieldValues
|
1
|
+
import { IconSvg, iconClose, iconSearch } from '@graphcommerce/next-ui'
|
2
|
+
import type { Control, FieldPath, FieldValues } from '@graphcommerce/react-hook-form'
|
3
|
+
import { useWatch } from '@graphcommerce/react-hook-form'
|
3
4
|
import { i18n } from '@lingui/core'
|
4
5
|
import { IconButton } from '@mui/material'
|
5
6
|
|
@@ -1,14 +1,15 @@
|
|
1
1
|
import {
|
2
|
-
iconSearch,
|
3
|
-
responsiveVal,
|
4
2
|
IconSvg,
|
5
3
|
extendableComponent,
|
4
|
+
iconSearch,
|
5
|
+
responsiveVal,
|
6
6
|
useFabSize,
|
7
7
|
useIconSvgSize,
|
8
8
|
} from '@graphcommerce/next-ui'
|
9
|
-
import { Breakpoint,
|
9
|
+
import type { Breakpoint, FabProps, LinkProps } from '@mui/material'
|
10
|
+
import { Fab, Link } from '@mui/material'
|
10
11
|
import { useRouter } from 'next/router'
|
11
|
-
import { KeyboardEventHandler, MouseEventHandler } from 'react'
|
12
|
+
import type { KeyboardEventHandler, MouseEventHandler } from 'react'
|
12
13
|
import type { SetRequired } from 'type-fest'
|
13
14
|
|
14
15
|
export type SearchLinkProps = {
|
@@ -16,7 +17,7 @@ export type SearchLinkProps = {
|
|
16
17
|
fab?: FabProps
|
17
18
|
} & SetRequired<Pick<LinkProps<'a'>, 'href' | 'sx' | 'children' | 'onClick'>, 'href'>
|
18
19
|
|
19
|
-
const name = 'SearchLink'
|
20
|
+
const name = 'SearchLink'
|
20
21
|
const parts = ['root', 'text', 'svg'] as const
|
21
22
|
const { classes } = extendableComponent(name, parts)
|
22
23
|
|
package/hooks/useProductList.ts
CHANGED
@@ -1,12 +1,14 @@
|
|
1
|
-
import {
|
2
|
-
import {
|
1
|
+
import { usePrivateQuery, useQuery } from '@graphcommerce/graphql'
|
2
|
+
import type {
|
3
3
|
FilterFormProviderProps,
|
4
|
-
ProductFiltersDocument,
|
5
4
|
ProductFiltersQuery,
|
6
|
-
ProductListDocument,
|
7
5
|
ProductListParams,
|
8
6
|
ProductListQuery,
|
7
|
+
} from '@graphcommerce/magento-product'
|
8
|
+
import {
|
9
9
|
prefetchProductList,
|
10
|
+
ProductFiltersDocument,
|
11
|
+
ProductListDocument,
|
10
12
|
toProductListParams,
|
11
13
|
useRouterFilterParams,
|
12
14
|
} from '@graphcommerce/magento-product'
|
@@ -24,15 +26,17 @@ import {
|
|
24
26
|
* - Creates a prefetch function to preload the product list
|
25
27
|
*/
|
26
28
|
export function useProductList<
|
27
|
-
T extends ProductListQuery &
|
28
|
-
ProductFiltersQuery & {
|
29
|
-
params?: ProductListParams
|
30
|
-
},
|
29
|
+
T extends ProductListQuery & ProductFiltersQuery & { params?: ProductListParams },
|
31
30
|
>(props: T) {
|
32
31
|
const { params, shallow } = useRouterFilterParams(props)
|
33
32
|
const variables = useProductListApplySearchDefaults(params)
|
34
|
-
const result =
|
35
|
-
|
33
|
+
const result = usePrivateQuery(
|
34
|
+
ProductListDocument,
|
35
|
+
{ variables: { ...variables }, skip: !shallow },
|
36
|
+
props,
|
37
|
+
)
|
38
|
+
|
39
|
+
const filters = usePrivateQuery(
|
36
40
|
ProductFiltersDocument,
|
37
41
|
{ variables: searchDefaultsToProductListFilters(variables), skip: !shallow },
|
38
42
|
props,
|
package/index.ts
CHANGED
@@ -1,12 +1,14 @@
|
|
1
1
|
export * from './CategorySearch.gql'
|
2
2
|
export * from './components/CategorySearchResult/CategorySearchResult'
|
3
3
|
export * from './components/CategorySearchResult/CategorySearchResults'
|
4
|
+
export * from './components/CategorySearchResult/CategorySearchResult.gql'
|
4
5
|
export * from './components/NoSearchResults/NoSearchResults'
|
5
6
|
export * from './components/SearchButton/SearchButton'
|
6
7
|
export * from './components/SearchContext/SearchContext'
|
7
8
|
export * from './components/SearchDivider/SearchDivider'
|
8
9
|
export * from './components/SearchForm/SearchForm'
|
9
10
|
export * from './components/SearchLink/SearchLink'
|
11
|
+
export * from './components/SearchFab/SearchFab'
|
10
12
|
export * from './hooks/useProductList'
|
11
13
|
export * from './components/ProductFiltersPro/ProductFiltersProCategorySectionSearch'
|
12
14
|
export * from './components/ProductFiltersPro/ProductFiltersProSearchHeader'
|
@@ -23,4 +25,4 @@ export {
|
|
23
25
|
|
24
26
|
export * from '@graphcommerce/magento-product/components/ProductFiltersPro'
|
25
27
|
export * from './utils/productListApplySearchDefaults'
|
26
|
-
export * from './components/ProductFiltersPro/
|
28
|
+
export * from './components/ProductFiltersPro/SearchField'
|
package/package.json
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
"name": "@graphcommerce/magento-search",
|
3
3
|
"homepage": "https://www.graphcommerce.org/",
|
4
4
|
"repository": "github:graphcommerce-org/graphcommerce",
|
5
|
-
"version": "9.0.0
|
5
|
+
"version": "9.0.0",
|
6
6
|
"sideEffects": false,
|
7
7
|
"prettier": "@graphcommerce/prettier-config-pwa",
|
8
8
|
"eslintConfig": {
|
@@ -12,20 +12,22 @@
|
|
12
12
|
}
|
13
13
|
},
|
14
14
|
"peerDependencies": {
|
15
|
-
"@graphcommerce/ecommerce-ui": "^9.0.0
|
16
|
-
"@graphcommerce/eslint-config-pwa": "^9.0.0
|
17
|
-
"@graphcommerce/
|
18
|
-
"@graphcommerce/
|
19
|
-
"@graphcommerce/
|
20
|
-
"@graphcommerce/magento-
|
21
|
-
"@graphcommerce/
|
22
|
-
"@graphcommerce/
|
23
|
-
"@graphcommerce/
|
24
|
-
"@graphcommerce/
|
15
|
+
"@graphcommerce/ecommerce-ui": "^9.0.0",
|
16
|
+
"@graphcommerce/eslint-config-pwa": "^9.0.0",
|
17
|
+
"@graphcommerce/framer-utils": "^9.0.0",
|
18
|
+
"@graphcommerce/graphql": "^9.0.0",
|
19
|
+
"@graphcommerce/image": "^9.0.0",
|
20
|
+
"@graphcommerce/magento-product": "^9.0.0",
|
21
|
+
"@graphcommerce/magento-store": "^9.0.0",
|
22
|
+
"@graphcommerce/next-ui": "^9.0.0",
|
23
|
+
"@graphcommerce/prettier-config-pwa": "^9.0.0",
|
24
|
+
"@graphcommerce/react-hook-form": "^9.0.0",
|
25
|
+
"@graphcommerce/typescript-config-pwa": "^9.0.0",
|
25
26
|
"@lingui/core": "^4.2.1",
|
26
27
|
"@lingui/macro": "^4.2.1",
|
27
28
|
"@lingui/react": "^4.2.1",
|
28
29
|
"@mui/material": "^5.10.16",
|
30
|
+
"framer-motion": "*",
|
29
31
|
"next": "*",
|
30
32
|
"react": "^18.2.0",
|
31
33
|
"react-dom": "^18.2.0"
|
package/tsconfig.json
CHANGED
@@ -1,6 +1,11 @@
|
|
1
1
|
import { cloneDeep, useQuery } from '@graphcommerce/graphql'
|
2
|
-
import {
|
3
|
-
|
2
|
+
import type {
|
3
|
+
ProductFiltersQueryVariables,
|
4
|
+
ProductListParams,
|
5
|
+
ProductListQueryVariables,
|
6
|
+
} from '@graphcommerce/magento-product'
|
7
|
+
import type { StoreConfigQuery } from '@graphcommerce/magento-store'
|
8
|
+
import { StoreConfigDocument } from '@graphcommerce/magento-store'
|
4
9
|
|
5
10
|
export function useProductListApplySearchDefaults(
|
6
11
|
params: ProductListParams | undefined,
|
@@ -42,7 +47,7 @@ export function productListApplySearchDefaults(
|
|
42
47
|
|
43
48
|
export function searchDefaultsToProductListFilters(
|
44
49
|
variables: ProductListQueryVariables | undefined,
|
45
|
-
):
|
50
|
+
): ProductFiltersQueryVariables {
|
46
51
|
return {
|
47
52
|
...variables,
|
48
53
|
filters: {},
|