@faststore/components 2.0.85-alpha.0 → 2.0.88-alpha.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/dist/assets/MagnifyingGlass.d.ts +3 -2
- package/dist/assets/MagnifyingGlass.js +3 -4
- package/dist/assets/MagnifyingGlass.js.map +1 -1
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/index.js +1 -0
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/useSearch.d.ts +7 -0
- package/dist/hooks/useSearch.js +10 -0
- package/dist/hooks/useSearch.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/molecules/SearchAutoComplete/SearchAutoComplete.d.ts +1 -1
- package/dist/molecules/SearchAutoComplete/SearchAutoComplete.js +5 -1
- package/dist/molecules/SearchAutoComplete/SearchAutoComplete.js.map +1 -1
- package/dist/molecules/SearchDropdown/SearchDropdown.d.ts +14 -0
- package/dist/molecules/SearchDropdown/SearchDropdown.js +14 -0
- package/dist/molecules/SearchDropdown/SearchDropdown.js.map +1 -0
- package/dist/molecules/SearchDropdown/index.d.ts +2 -0
- package/dist/molecules/SearchDropdown/index.js +2 -0
- package/dist/molecules/SearchDropdown/index.js.map +1 -0
- package/dist/molecules/SearchHistory/SearchHistory.d.ts +1 -1
- package/dist/molecules/SearchHistory/SearchHistory.js +5 -1
- package/dist/molecules/SearchHistory/SearchHistory.js.map +1 -1
- package/dist/molecules/SearchInputField/SearchInputField.d.ts +36 -0
- package/dist/molecules/SearchInputField/SearchInputField.js +21 -0
- package/dist/molecules/SearchInputField/SearchInputField.js.map +1 -0
- package/dist/molecules/SearchInputField/index.d.ts +2 -0
- package/dist/molecules/SearchInputField/index.js +2 -0
- package/dist/molecules/SearchInputField/index.js.map +1 -0
- package/dist/molecules/SearchProducts/SearchProductItemContent.d.ts +2 -2
- package/dist/molecules/SearchProducts/SearchProducts.d.ts +1 -1
- package/dist/molecules/SearchProducts/SearchProducts.js +5 -1
- package/dist/molecules/SearchProducts/SearchProducts.js.map +1 -1
- package/dist/molecules/SearchProvider/SearchProvider.d.ts +29 -0
- package/dist/molecules/SearchProvider/SearchProvider.js +8 -0
- package/dist/molecules/SearchProvider/SearchProvider.js.map +1 -0
- package/dist/molecules/SearchProvider/index.d.ts +2 -0
- package/dist/molecules/SearchProvider/index.js +2 -0
- package/dist/molecules/SearchProvider/index.js.map +1 -0
- package/dist/molecules/SearchTop/SearchTop.d.ts +0 -8
- package/dist/molecules/SearchTop/SearchTop.js +8 -4
- package/dist/molecules/SearchTop/SearchTop.js.map +1 -1
- package/dist/molecules/SkuSelector/SkuSelector.d.ts +78 -0
- package/dist/molecules/SkuSelector/SkuSelector.js +31 -0
- package/dist/molecules/SkuSelector/SkuSelector.js.map +1 -0
- package/dist/molecules/SkuSelector/index.d.ts +2 -0
- package/dist/molecules/SkuSelector/index.js +2 -0
- package/dist/molecules/SkuSelector/index.js.map +1 -0
- package/dist/molecules/SkuSelector/useDefineVariant.d.ts +3 -0
- package/dist/molecules/SkuSelector/useDefineVariant.js +27 -0
- package/dist/molecules/SkuSelector/useDefineVariant.js.map +1 -0
- package/dist/molecules/SkuSelector/useSkuSlug.d.ts +6 -0
- package/dist/molecules/SkuSelector/useSkuSlug.js +23 -0
- package/dist/molecules/SkuSelector/useSkuSlug.js.map +1 -0
- package/dist/organisms/SearchInput/SearchInput.d.ts +26 -0
- package/dist/organisms/SearchInput/SearchInput.js +8 -0
- package/dist/organisms/SearchInput/SearchInput.js.map +1 -0
- package/dist/organisms/SearchInput/index.d.ts +2 -0
- package/dist/organisms/SearchInput/index.js +2 -0
- package/dist/organisms/SearchInput/index.js.map +1 -0
- package/package.json +2 -2
- package/src/assets/MagnifyingGlass.tsx +12 -29
- package/src/hooks/index.ts +1 -0
- package/src/hooks/useSearch.ts +12 -0
- package/src/index.ts +20 -0
- package/src/molecules/SearchAutoComplete/SearchAutoComplete.tsx +8 -1
- package/src/molecules/SearchDropdown/SearchDropdown.tsx +45 -0
- package/src/molecules/SearchDropdown/index.ts +2 -0
- package/src/molecules/SearchHistory/SearchHistory.tsx +8 -1
- package/src/molecules/SearchInputField/SearchInputField.tsx +100 -0
- package/src/molecules/SearchInputField/index.ts +5 -0
- package/src/molecules/SearchProducts/SearchProductItemContent.tsx +1 -1
- package/src/molecules/SearchProducts/SearchProducts.tsx +6 -1
- package/src/molecules/SearchProvider/SearchProvider.tsx +49 -0
- package/src/molecules/SearchProvider/index.ts +2 -0
- package/src/molecules/SearchTop/SearchTop.tsx +12 -21
- package/src/molecules/SkuSelector/SkuSelector.tsx +181 -0
- package/src/molecules/SkuSelector/index.tsx +2 -0
- package/src/molecules/SkuSelector/useDefineVariant.ts +36 -0
- package/src/molecules/SkuSelector/useSkuSlug.ts +49 -0
- package/src/organisms/SearchInput/SearchInput.tsx +55 -0
- package/src/organisms/SearchInput/index.ts +2 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
const getImageName = (src) => {
|
|
3
|
+
const sourcePath = new URL(src).pathname;
|
|
4
|
+
const imageName = sourcePath.split('/').at(-1);
|
|
5
|
+
return imageName;
|
|
6
|
+
};
|
|
7
|
+
export const useDefineVariant = (options, variant) => useMemo(() => {
|
|
8
|
+
if (variant)
|
|
9
|
+
return variant;
|
|
10
|
+
const allOptionsHaveHexColor = options.every((option) => option.hexColor);
|
|
11
|
+
if (allOptionsHaveHexColor) {
|
|
12
|
+
return 'color';
|
|
13
|
+
}
|
|
14
|
+
const firstImageName = options[0]?.src && getImageName(options[0].src);
|
|
15
|
+
const areSourcesEqualsOrNull = options.every((option) => {
|
|
16
|
+
if (!option.src) {
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
const optionImageName = getImageName(option.src);
|
|
20
|
+
return optionImageName === firstImageName;
|
|
21
|
+
});
|
|
22
|
+
if (!areSourcesEqualsOrNull) {
|
|
23
|
+
return 'image';
|
|
24
|
+
}
|
|
25
|
+
return 'label';
|
|
26
|
+
}, [options, variant]);
|
|
27
|
+
//# sourceMappingURL=useDefineVariant.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useDefineVariant.js","sourceRoot":"","sources":["../../../src/molecules/SkuSelector/useDefineVariant.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAA;AAK/B,MAAM,YAAY,GAAG,CAAC,GAAW,EAAE,EAAE;IACnC,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAA;IACxC,MAAM,SAAS,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAA;IAC9C,OAAO,SAAS,CAAA;AAClB,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,OAAoB,EAAE,OAAiB,EAAW,EAAE,CACnF,OAAO,CAAC,GAAG,EAAE;IACX,IAAG,OAAO;QAAE,OAAO,OAAO,CAAA;IAE1B,MAAM,sBAAsB,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;IACzE,IAAI,sBAAsB,EAAE;QAC1B,OAAO,OAAO,CAAA;KACf;IAED,MAAM,cAAc,GAAG,OAAO,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;IAEtE,MAAM,sBAAsB,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE,EAAE;QACtD,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE;YACf,OAAO,IAAI,CAAA;SACZ;QACD,MAAM,eAAe,GAAG,YAAY,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;QAChD,OAAO,eAAe,KAAK,cAAc,CAAA;IAC3C,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,sBAAsB,EAAE;QAC3B,OAAO,OAAO,CAAA;KACf;IAED,OAAO,OAAO,CAAA;AAChB,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAA"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { SkuOption } from './SkuSelector';
|
|
2
|
+
export declare const useSkuSlug: (activeVariations: Record<string, string>, slugsMap: Record<string, string>, skuPropertyName: string, getItemHrefProp?: ((option: SkuOption) => string) | undefined) => {
|
|
3
|
+
getItemHref: (option: SkuOption) => string | {
|
|
4
|
+
getItemHrefProp: (option: SkuOption) => string;
|
|
5
|
+
};
|
|
6
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { useCallback } from 'react';
|
|
2
|
+
function getSkuSlug(slugsMap, selectedVariations, dominantVariation) {
|
|
3
|
+
const slugsMapKey = Object.entries(selectedVariations).flat().join('-');
|
|
4
|
+
if (slugsMapKey in slugsMap) {
|
|
5
|
+
return slugsMap[slugsMapKey];
|
|
6
|
+
}
|
|
7
|
+
const possibleVariants = Object.keys(slugsMap);
|
|
8
|
+
const firstVariationForDominantValue = possibleVariants.find((slug) => slug.includes(`${dominantVariation}-${selectedVariations[dominantVariation]}`));
|
|
9
|
+
return slugsMap[firstVariationForDominantValue ?? possibleVariants[0]];
|
|
10
|
+
}
|
|
11
|
+
export const useSkuSlug = (activeVariations, slugsMap, skuPropertyName, getItemHrefProp) => {
|
|
12
|
+
const getItemHref = useCallback((option) => {
|
|
13
|
+
if (getItemHrefProp)
|
|
14
|
+
return { getItemHrefProp };
|
|
15
|
+
const currentItemHref = `/${getSkuSlug(slugsMap, {
|
|
16
|
+
...activeVariations,
|
|
17
|
+
[skuPropertyName]: option.value,
|
|
18
|
+
}, skuPropertyName)}/p`;
|
|
19
|
+
return currentItemHref;
|
|
20
|
+
}, [activeVariations, getItemHrefProp, slugsMap, skuPropertyName]);
|
|
21
|
+
return { getItemHref };
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=useSkuSlug.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useSkuSlug.js","sourceRoot":"","sources":["../../../src/molecules/SkuSelector/useSkuSlug.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAA;AAGnC,SAAS,UAAU,CACjB,QAAgC,EAChC,kBAA0C,EAC1C,iBAAyB;IAEzB,MAAM,WAAW,GAAG,MAAM,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IAEvE,IAAI,WAAW,IAAI,QAAQ,EAAE;QAC3B,OAAO,QAAQ,CAAC,WAAW,CAAC,CAAA;KAC7B;IAED,MAAM,gBAAgB,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;IAE9C,MAAM,8BAA8B,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CACpE,IAAI,CAAC,QAAQ,CACX,GAAG,iBAAiB,IAAI,kBAAkB,CAAC,iBAAiB,CAAC,EAAE,CAChE,CACF,CAAA;IAED,OAAO,QAAQ,CAAC,8BAA8B,IAAI,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAA;AACxE,CAAC;AAED,MAAM,CAAC,MAAM,UAAU,GAAG,CACxB,gBAAwC,EACxC,QAAgC,EAChC,eAAuB,EACvB,eAA+C,EAC/C,EAAE;IACF,MAAM,WAAW,GAAG,WAAW,CAC7B,CAAC,MAAiB,EAAE,EAAE;QACpB,IAAG,eAAe;YAAE,OAAO,EAAE,eAAe,EAAE,CAAA;QAE9C,MAAM,eAAe,GAAG,IAAI,UAAU,CACpC,QAAQ,EACR;YACE,GAAG,gBAAgB;YACnB,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC,KAAK;SAChC,EACD,eAAe,CAChB,IAAI,CAAA;QACL,OAAO,eAAe,CAAA;IACxB,CAAC,EACD,CAAC,gBAAgB,EAAE,eAAe,EAAE,QAAQ,EAAE,eAAe,CAAC,CAC/D,CAAA;IACD,OAAO,EAAE,WAAW,EAAE,CAAA;AACxB,CAAC,CAAA"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { HTMLAttributes } from 'react';
|
|
3
|
+
import { SearchProviderContextValue } from '../../molecules/SearchProvider';
|
|
4
|
+
export type SearchInputProps = {
|
|
5
|
+
/**
|
|
6
|
+
* ID to find this component in testing tools (e.g.: cypress,
|
|
7
|
+
* testing-library, and jest).
|
|
8
|
+
*/
|
|
9
|
+
testId?: string;
|
|
10
|
+
/**
|
|
11
|
+
* The current status of the Search Dropdown.
|
|
12
|
+
*/
|
|
13
|
+
visibleDropdown: boolean;
|
|
14
|
+
} & HTMLAttributes<HTMLDivElement> & SearchProviderContextValue;
|
|
15
|
+
declare const SearchInput: React.ForwardRefExoticComponent<{
|
|
16
|
+
/**
|
|
17
|
+
* ID to find this component in testing tools (e.g.: cypress,
|
|
18
|
+
* testing-library, and jest).
|
|
19
|
+
*/
|
|
20
|
+
testId?: string | undefined;
|
|
21
|
+
/**
|
|
22
|
+
* The current status of the Search Dropdown.
|
|
23
|
+
*/
|
|
24
|
+
visibleDropdown: boolean;
|
|
25
|
+
} & React.HTMLAttributes<HTMLDivElement> & SearchProviderContextValue & React.RefAttributes<HTMLDivElement>>;
|
|
26
|
+
export default SearchInput;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import React, { forwardRef } from 'react';
|
|
2
|
+
import SearchProvider from '../../molecules/SearchProvider';
|
|
3
|
+
const SearchInput = forwardRef(function SearchInput({ children, visibleDropdown = false, testId = 'fs-search-input', isLoading, products, term, terms, onSearchSelection, ...otherProps }, ref) {
|
|
4
|
+
return (React.createElement("div", { ref: ref, "data-fs-search-input": true, "data-fs-search-input-dropdown-visible": visibleDropdown, "data-testid": testId, ...otherProps },
|
|
5
|
+
React.createElement(SearchProvider, { onSearchSelection: onSearchSelection, isLoading: isLoading, term: term, products: products, terms: terms }, children)));
|
|
6
|
+
});
|
|
7
|
+
export default SearchInput;
|
|
8
|
+
//# sourceMappingURL=SearchInput.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SearchInput.js","sourceRoot":"","sources":["../../../src/organisms/SearchInput/SearchInput.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,UAAU,EAAE,MAAM,OAAO,CAAA;AAEzC,OAAO,cAA8C,MAAM,gCAAgC,CAAA;AAe3F,MAAM,WAAW,GAAG,UAAU,CAC5B,SAAS,WAAW,CAClB,EACE,QAAQ,EACR,eAAe,GAAG,KAAK,EACvB,MAAM,GAAG,iBAAiB,EAC1B,SAAS,EACT,QAAQ,EACR,IAAI,EACJ,KAAK,EACL,iBAAiB,EACjB,GAAG,UAAU,EACd,EACD,GAAG;IAEH,OAAO,CACL,6BACE,GAAG,EAAE,GAAG,yEAE+B,eAAe,iBACzC,MAAM,KACf,UAAU;QAEd,oBAAC,cAAc,IACb,iBAAiB,EAAE,iBAAiB,EACpC,SAAS,EAAE,SAAS,EACpB,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE,QAAQ,EAClB,KAAK,EAAE,KAAK,IAEX,QAAQ,CACM,CACb,CACP,CAAA;AACH,CAAC,CACF,CAAA;AAED,eAAe,WAAW,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/organisms/SearchInput/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@faststore/components",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.88-alpha.0",
|
|
4
4
|
"module": "dist/index.js",
|
|
5
5
|
"typings": "dist/index.d.ts",
|
|
6
6
|
"author": "Emerson Laurentino @emersonlaurentino",
|
|
@@ -30,5 +30,5 @@
|
|
|
30
30
|
"node": "16.18.0",
|
|
31
31
|
"yarn": "1.19.1"
|
|
32
32
|
},
|
|
33
|
-
"gitHead": "
|
|
33
|
+
"gitHead": "a9aa7a6572c08e0bd26e384bb66464e633f1ad84"
|
|
34
34
|
}
|
|
@@ -1,38 +1,21 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
|
-
import
|
|
2
|
+
import { IconProps } from './IconProps'
|
|
3
3
|
|
|
4
4
|
// Icon from Phosphor Icons
|
|
5
|
-
const MagnifyingGlass
|
|
5
|
+
const MagnifyingGlass = ({ size = 24 }: IconProps) => (
|
|
6
6
|
<svg
|
|
7
7
|
xmlns="http://www.w3.org/2000/svg"
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
width={size}
|
|
9
|
+
height={size}
|
|
10
|
+
viewBox="0 0 24 24"
|
|
11
|
+
fill="none"
|
|
12
|
+
stroke="currentColor"
|
|
13
|
+
strokeWidth="2"
|
|
14
|
+
strokeLinecap="round"
|
|
15
|
+
strokeLinejoin="round"
|
|
13
16
|
>
|
|
14
|
-
<
|
|
15
|
-
<
|
|
16
|
-
cx="116"
|
|
17
|
-
cy="116"
|
|
18
|
-
r="84"
|
|
19
|
-
fill="none"
|
|
20
|
-
stroke="currentColor"
|
|
21
|
-
strokeLinecap="round"
|
|
22
|
-
strokeLinejoin="round"
|
|
23
|
-
strokeWidth="16"
|
|
24
|
-
></circle>
|
|
25
|
-
<line
|
|
26
|
-
x1="175.4"
|
|
27
|
-
y1="175.4"
|
|
28
|
-
x2="224"
|
|
29
|
-
y2="224"
|
|
30
|
-
fill="none"
|
|
31
|
-
stroke="currentColor"
|
|
32
|
-
strokeLinecap="round"
|
|
33
|
-
strokeLinejoin="round"
|
|
34
|
-
strokeWidth="16"
|
|
35
|
-
></line>
|
|
17
|
+
<circle cx="11" cy="11" r="8" />
|
|
18
|
+
<line x1="21" y1="21" x2="16.65" y2="16.65" />
|
|
36
19
|
</svg>
|
|
37
20
|
)
|
|
38
21
|
|
package/src/hooks/index.ts
CHANGED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { SearchContext } from "../molecules/SearchProvider/SearchProvider"
|
|
2
|
+
import { useContext } from "react"
|
|
3
|
+
|
|
4
|
+
export const useSearch = () => {
|
|
5
|
+
const context = useContext(SearchContext)
|
|
6
|
+
|
|
7
|
+
if (!context) {
|
|
8
|
+
return { inContext: false as const }
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
return { inContext: true as const, values: context }
|
|
12
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -116,6 +116,17 @@ export { default as RadioGroup, RadioOption } from './molecules/RadioGroup'
|
|
|
116
116
|
export type { RadioGroupProps, RadioOptionProps } from './molecules/RadioGroup'
|
|
117
117
|
export { default as Rating } from './molecules/Rating'
|
|
118
118
|
export type { RatingProps } from './molecules/Rating'
|
|
119
|
+
|
|
120
|
+
export { default as SearchProvider } from './molecules/SearchProvider'
|
|
121
|
+
export type {
|
|
122
|
+
SearchProviderContextValue,
|
|
123
|
+
} from './molecules/SearchProvider'
|
|
124
|
+
|
|
125
|
+
export { default as SearchInputField } from './molecules/SearchInputField'
|
|
126
|
+
export type {
|
|
127
|
+
SearchInputFieldProps,
|
|
128
|
+
SearchInputFieldRef,
|
|
129
|
+
} from './molecules/SearchInputField'
|
|
119
130
|
export {
|
|
120
131
|
default as SearchAutoComplete,
|
|
121
132
|
SearchAutoCompleteTerm,
|
|
@@ -124,6 +135,10 @@ export type {
|
|
|
124
135
|
SearchAutoCompleteProps,
|
|
125
136
|
SearchAutoCompleteTermProps,
|
|
126
137
|
} from './molecules/SearchAutoComplete'
|
|
138
|
+
export {
|
|
139
|
+
default as SearchDropdown,
|
|
140
|
+
SearchDropdownProps,
|
|
141
|
+
} from './molecules/SearchDropdown'
|
|
127
142
|
export {
|
|
128
143
|
default as SearchHistory,
|
|
129
144
|
SearchHistoryTerm,
|
|
@@ -148,6 +163,8 @@ export { default as SearchTop, SearchTopTerm } from './molecules/SearchTop'
|
|
|
148
163
|
export type { SearchTopProps, SearchTopTermProps } from './molecules/SearchTop'
|
|
149
164
|
export { default as SelectField } from './molecules/SelectField'
|
|
150
165
|
export type { SelectFieldProps } from './molecules/SelectField'
|
|
166
|
+
export { default as SkuSelector } from './molecules/SkuSelector'
|
|
167
|
+
export type { SkuSelectorProps, SkuOption } from './molecules/SkuSelector'
|
|
151
168
|
export {
|
|
152
169
|
Table,
|
|
153
170
|
TableBody,
|
|
@@ -188,6 +205,9 @@ export type { PaymentMethodsProps } from './organisms/PaymentMethods'
|
|
|
188
205
|
export { default as PriceRange } from './organisms/PriceRange'
|
|
189
206
|
export type { PriceRangeProps } from './organisms/PriceRange'
|
|
190
207
|
|
|
208
|
+
export { default as SearchInput } from './organisms/SearchInput'
|
|
209
|
+
export type { SearchInputProps } from './organisms/SearchInput'
|
|
210
|
+
|
|
191
211
|
export { default as SlideOver, SlideOverHeader } from './organisms/SlideOver'
|
|
192
212
|
export type {
|
|
193
213
|
SlideOverProps,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { HTMLAttributes } from 'react'
|
|
2
|
-
import { List } from '../..'
|
|
2
|
+
import { List, useSearch } from '../..'
|
|
3
3
|
|
|
4
4
|
export interface SearchAutoCompleteProps
|
|
5
5
|
extends HTMLAttributes<HTMLDivElement> {
|
|
@@ -14,6 +14,13 @@ const SearchAutoComplete = ({
|
|
|
14
14
|
children,
|
|
15
15
|
...otherProps
|
|
16
16
|
}: SearchAutoCompleteProps) => {
|
|
17
|
+
|
|
18
|
+
const { inContext, values } = useSearch()
|
|
19
|
+
|
|
20
|
+
if (inContext && (values.terms.length <= 0 || values.term.length <= 0)) {
|
|
21
|
+
return null
|
|
22
|
+
}
|
|
23
|
+
|
|
17
24
|
return (
|
|
18
25
|
<section data-testid={testId} data-fs-search-auto-complete {...otherProps}>
|
|
19
26
|
<List as="ol">{children}</List>
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { HTMLAttributes, ReactNode, PropsWithChildren } from 'react'
|
|
2
|
+
import React, { forwardRef } from 'react'
|
|
3
|
+
import { useSearch } from '../../hooks'
|
|
4
|
+
|
|
5
|
+
export interface SearchDropdownProps extends HTMLAttributes<HTMLDivElement> {
|
|
6
|
+
/**
|
|
7
|
+
* ID to find this component in testing tools (e.g.: cypress,
|
|
8
|
+
* testing-library, and jest).
|
|
9
|
+
*/
|
|
10
|
+
testId?: string
|
|
11
|
+
children?: ReactNode
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const SearchLoading = () => {
|
|
15
|
+
const { inContext, values } = useSearch()
|
|
16
|
+
|
|
17
|
+
return (
|
|
18
|
+
<>
|
|
19
|
+
{ (inContext && values.isLoading) && <p data-fs-search-dropdown-loading-text>Loading...</p> }
|
|
20
|
+
</>
|
|
21
|
+
)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const SearchDropdown = forwardRef<
|
|
25
|
+
HTMLDivElement,
|
|
26
|
+
PropsWithChildren<SearchDropdownProps>
|
|
27
|
+
>(function SearchDropdown(
|
|
28
|
+
{
|
|
29
|
+
testId = 'fs-search-dropdown',
|
|
30
|
+
children,
|
|
31
|
+
...otherProps
|
|
32
|
+
},
|
|
33
|
+
ref
|
|
34
|
+
) {
|
|
35
|
+
return (
|
|
36
|
+
<div ref={ref} data-fs-search-dropdown data-testid={testId} {...otherProps}>
|
|
37
|
+
<section>
|
|
38
|
+
<SearchLoading/>
|
|
39
|
+
{children}
|
|
40
|
+
</section>
|
|
41
|
+
</div>
|
|
42
|
+
)
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
export default SearchDropdown
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { HTMLAttributes } from 'react'
|
|
2
|
-
import { List, Button } from '../..'
|
|
2
|
+
import { List, Button, useSearch } from '../..'
|
|
3
3
|
|
|
4
4
|
export interface SearchHistoryProps extends HTMLAttributes<HTMLDivElement> {
|
|
5
5
|
/**
|
|
@@ -28,6 +28,13 @@ const SearchHistory = ({
|
|
|
28
28
|
children,
|
|
29
29
|
...otherProps
|
|
30
30
|
}: SearchHistoryProps) => {
|
|
31
|
+
|
|
32
|
+
const { inContext, values } = useSearch()
|
|
33
|
+
|
|
34
|
+
if (inContext && (values.term.length !== 0 || values.isLoading)) {
|
|
35
|
+
return null
|
|
36
|
+
}
|
|
37
|
+
|
|
31
38
|
return (
|
|
32
39
|
<section data-testid={testId} data-fs-search-history {...otherProps}>
|
|
33
40
|
<header data-fs-search-history-header>
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
AriaAttributes,
|
|
3
|
+
FormEvent,
|
|
4
|
+
InputHTMLAttributes,
|
|
5
|
+
ReactNode,
|
|
6
|
+
} from 'react'
|
|
7
|
+
import React, { forwardRef, useImperativeHandle, useRef } from 'react'
|
|
8
|
+
|
|
9
|
+
import { IconButton, Input, MagnifyingGlass } from '../..'
|
|
10
|
+
|
|
11
|
+
type InputProps = Omit<InputHTMLAttributes<HTMLInputElement>, 'onSubmit'>
|
|
12
|
+
|
|
13
|
+
type ButtonProps = {
|
|
14
|
+
onClick?: () => void
|
|
15
|
+
testId?: string
|
|
16
|
+
}
|
|
17
|
+
export interface SearchInputFieldProps extends InputProps {
|
|
18
|
+
/**
|
|
19
|
+
* ID to find this component in testing tools (e.g.: cypress, testing library, and jest).
|
|
20
|
+
*/
|
|
21
|
+
testId?: string
|
|
22
|
+
/**
|
|
23
|
+
* Props for the submit button inside the input.
|
|
24
|
+
*/
|
|
25
|
+
buttonProps?: ButtonProps
|
|
26
|
+
/**
|
|
27
|
+
* A React component that will be rendered as an icon (submit button).
|
|
28
|
+
* @default <MagnifyingGlass />
|
|
29
|
+
*/
|
|
30
|
+
buttonIcon?: ReactNode
|
|
31
|
+
/**
|
|
32
|
+
* Custom aria-label for input and button.
|
|
33
|
+
*/
|
|
34
|
+
'aria-label'?: AriaAttributes['aria-label']
|
|
35
|
+
/**
|
|
36
|
+
* Callback function when submitted.
|
|
37
|
+
*/
|
|
38
|
+
onSubmit: (value: string) => void
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface SearchInputFieldRef {
|
|
42
|
+
inputRef?: HTMLInputElement | null
|
|
43
|
+
formRef?: HTMLFormElement | null
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const SearchInputField = forwardRef<
|
|
47
|
+
SearchInputFieldRef | null,
|
|
48
|
+
SearchInputFieldProps
|
|
49
|
+
>(function SearchInputField(
|
|
50
|
+
{
|
|
51
|
+
onSubmit,
|
|
52
|
+
buttonIcon,
|
|
53
|
+
'aria-label': ariaLabel = 'search',
|
|
54
|
+
testId = 'fs-search-input',
|
|
55
|
+
buttonProps,
|
|
56
|
+
...otherProps
|
|
57
|
+
},
|
|
58
|
+
ref
|
|
59
|
+
) {
|
|
60
|
+
const inputRef = useRef<HTMLInputElement>(null)
|
|
61
|
+
const formRef = useRef<HTMLFormElement>(null)
|
|
62
|
+
|
|
63
|
+
const handleSubmit = (event: FormEvent) => {
|
|
64
|
+
event.preventDefault()
|
|
65
|
+
|
|
66
|
+
if (inputRef.current?.value !== '') {
|
|
67
|
+
onSubmit(inputRef.current!.value)
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
useImperativeHandle(ref, () => ({
|
|
72
|
+
inputRef: inputRef.current,
|
|
73
|
+
formRef: formRef.current,
|
|
74
|
+
}))
|
|
75
|
+
|
|
76
|
+
return (
|
|
77
|
+
<form
|
|
78
|
+
ref={formRef}
|
|
79
|
+
data-fs-search-input-field
|
|
80
|
+
data-testid={testId}
|
|
81
|
+
onSubmit={handleSubmit}
|
|
82
|
+
role="search"
|
|
83
|
+
>
|
|
84
|
+
<Input
|
|
85
|
+
ref={inputRef}
|
|
86
|
+
aria-label={ariaLabel}
|
|
87
|
+
data-fs-search-input-field-input
|
|
88
|
+
{...otherProps}
|
|
89
|
+
/>
|
|
90
|
+
<IconButton
|
|
91
|
+
type="submit"
|
|
92
|
+
aria-label="Submit Search"
|
|
93
|
+
icon={buttonIcon ?? <MagnifyingGlass />}
|
|
94
|
+
{...buttonProps}
|
|
95
|
+
/>
|
|
96
|
+
</form>
|
|
97
|
+
)
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
export default SearchInputField
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { HTMLAttributes } from 'react'
|
|
2
|
-
import { List } from '../..'
|
|
2
|
+
import { List, useSearch } from '../..'
|
|
3
3
|
|
|
4
4
|
export interface SearchProductsProps extends HTMLAttributes<HTMLDivElement> {
|
|
5
5
|
/**
|
|
@@ -18,6 +18,11 @@ const SearchProductsProps = ({
|
|
|
18
18
|
children,
|
|
19
19
|
...otherProps
|
|
20
20
|
}: SearchProductsProps) => {
|
|
21
|
+
const { inContext, values } = useSearch()
|
|
22
|
+
|
|
23
|
+
if (inContext && (values.products.length <= 0)) {
|
|
24
|
+
return null
|
|
25
|
+
}
|
|
21
26
|
return (
|
|
22
27
|
<section data-testid={testId} data-fs-search-products {...otherProps}>
|
|
23
28
|
<header data-fs-search-products-header>
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import type { PropsWithChildren } from 'react'
|
|
3
|
+
import { createContext } from 'react'
|
|
4
|
+
|
|
5
|
+
export interface SearchProviderContextValue {
|
|
6
|
+
/**
|
|
7
|
+
* Term to be researched.
|
|
8
|
+
*/
|
|
9
|
+
term: string
|
|
10
|
+
/**
|
|
11
|
+
* Enables a loading state.
|
|
12
|
+
*/
|
|
13
|
+
isLoading: boolean
|
|
14
|
+
/**
|
|
15
|
+
* List of Suggestion terms.
|
|
16
|
+
*/
|
|
17
|
+
terms: Array<{ value: string }>
|
|
18
|
+
/**
|
|
19
|
+
* List of Suggested products.
|
|
20
|
+
*/
|
|
21
|
+
products: {}[]
|
|
22
|
+
/**
|
|
23
|
+
* Callback function when a search term is selected.
|
|
24
|
+
*/
|
|
25
|
+
onSearchSelection?: (term: string, path: string) => void
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export const SearchContext = createContext<SearchProviderContextValue | null>(
|
|
29
|
+
null
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
function SearchProvider({
|
|
33
|
+
onSearchSelection,
|
|
34
|
+
children,
|
|
35
|
+
term,
|
|
36
|
+
terms,
|
|
37
|
+
products,
|
|
38
|
+
isLoading,
|
|
39
|
+
}: PropsWithChildren<SearchProviderContextValue>) {
|
|
40
|
+
return (
|
|
41
|
+
<SearchContext.Provider
|
|
42
|
+
value={{ onSearchSelection, term, terms, products, isLoading }}
|
|
43
|
+
>
|
|
44
|
+
{children}
|
|
45
|
+
</SearchContext.Provider>
|
|
46
|
+
)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export default SearchProvider
|
|
@@ -2,7 +2,7 @@ import React from 'react'
|
|
|
2
2
|
import { forwardRef } from 'react'
|
|
3
3
|
import type { HTMLAttributes } from 'react'
|
|
4
4
|
|
|
5
|
-
import { List } from '../../'
|
|
5
|
+
import { List, useSearch } from '../../'
|
|
6
6
|
|
|
7
7
|
export interface SearchTopProps extends HTMLAttributes<HTMLDivElement> {
|
|
8
8
|
/**
|
|
@@ -13,39 +13,30 @@ export interface SearchTopProps extends HTMLAttributes<HTMLDivElement> {
|
|
|
13
13
|
* Title attribute for the <section> tag rendered by this component.
|
|
14
14
|
*/
|
|
15
15
|
title: string
|
|
16
|
-
/**
|
|
17
|
-
* Defines the the message displayed while loading.
|
|
18
|
-
*/
|
|
19
|
-
loadingMessage?: string
|
|
20
|
-
/**
|
|
21
|
-
* Enables a loading state.
|
|
22
|
-
*/
|
|
23
|
-
isLoading?: boolean
|
|
24
16
|
}
|
|
25
17
|
|
|
26
18
|
const SearchTop = forwardRef<HTMLDivElement, SearchTopProps>(function SearchTop(
|
|
27
19
|
{
|
|
28
20
|
testId = 'fs-top-search',
|
|
29
21
|
title = 'Top Search',
|
|
30
|
-
loadingMessage = 'Loading...',
|
|
31
|
-
isLoading,
|
|
32
22
|
children,
|
|
33
23
|
...otherProps
|
|
34
24
|
},
|
|
35
25
|
ref
|
|
36
26
|
) {
|
|
27
|
+
|
|
28
|
+
const { inContext, values } = useSearch()
|
|
29
|
+
|
|
30
|
+
if (inContext && (values.term.length !== 0 || values.isLoading)) {
|
|
31
|
+
return null
|
|
32
|
+
}
|
|
33
|
+
|
|
37
34
|
return (
|
|
38
35
|
<section ref={ref} data-testid={testId} data-fs-search-top {...otherProps}>
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
<header data-fs-search-top-header>
|
|
44
|
-
<p data-fs-search-top-title>{title}</p>
|
|
45
|
-
</header>
|
|
46
|
-
<List as="ol">{children}</List>
|
|
47
|
-
</>
|
|
48
|
-
)}
|
|
36
|
+
<header data-fs-search-top-header>
|
|
37
|
+
<p data-fs-search-top-title>{title}</p>
|
|
38
|
+
</header>
|
|
39
|
+
<List as="ol">{children}</List>
|
|
49
40
|
</section>
|
|
50
41
|
)
|
|
51
42
|
})
|