@envive-ai/react-toolkit 0.1.0 → 0.1.1
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/LICENSE +2 -0
- package/package.json +10 -7
- package/src/atoms/search/types.ts +5 -0
- package/src/components/common/ButtonBase/ButtonBase.tsx +70 -0
- package/src/components/common/ButtonBase/types.ts +27 -0
- package/src/components/common/Headline/Headline.tsx +81 -0
- package/src/components/common/ImageWithFallback/ImageWithFallback.tsx +66 -0
- package/src/components/common/ProductCard/ProductCard.tsx +305 -0
- package/src/components/common/ProductCard/ProductCardSkeleton.tsx +83 -0
- package/src/components/common/ProductCard/productCardVariants.ts +63 -0
- package/src/components/common/ProductCard/types.ts +49 -0
- package/src/components/common/ProductGrid/ProductGrid.tsx +73 -0
- package/src/components/common/ProductGrid/productGridVariants.ts +31 -0
- package/src/components/common/SparkleAnimation/SparkleAnimation.tsx +105 -0
- package/src/components/common/SparkleAnimation/types.ts +6 -0
- package/src/components/common/Spinner/Spinner.tsx +30 -0
- package/src/components/common/SuggestionButton/SuggestionButton.tsx +258 -0
- package/src/components/common/SuggestionButton/types.ts +14 -0
- package/src/components/common/Text/Text.tsx +58 -0
- package/src/components/common/Text/textVariantClasses.ts +106 -0
- package/src/components/common/Text/types.ts +23 -0
- package/src/components/common/TextInput/TextInput.tsx +34 -0
- package/src/components/models/colorsConfig.ts +28 -0
- package/src/components/search/FilterScrollbar/AppliedFiltersScrollbar.tsx +70 -0
- package/src/components/search/FilterScrollbar/DynamicFiltersScrollbar.tsx +52 -0
- package/src/components/search/SearchFilter/SearchFilter.tsx +84 -0
- package/src/components/search/SearchFilter/SearchFilterHeader.tsx +42 -0
- package/src/components/search/SearchFilter/SearchFilterItem.tsx +42 -0
- package/src/components/search/SearchFilter/types.ts +48 -0
- package/src/components/search/SearchInput/SearchInput.tsx +135 -0
- package/src/components/search/SearchInput/searchInputVariants.ts +27 -0
- package/src/components/search/SearchInputAutocomplete/SearchAutocomplete.tsx +62 -0
- package/src/components/search/SearchInputForm/SearchInputForm.tsx +66 -0
- package/src/components/search/SearchResultsFilterSidebar/SearchResultsFilter.tsx +82 -0
- package/src/components/search/SearchResultsFilterSidebar/searchFilterSidebarVariants.ts +45 -0
- package/{dist/packages/components/src/components/search/SearchResultsFilterSidebar/types.d.ts → src/components/search/SearchResultsFilterSidebar/types.ts} +1 -1
- package/src/components/search/SearchResultsStates/NoSearchResultsFound.tsx +41 -0
- package/src/components/search/SearchResultsStates/SearchResultsGrid.tsx +105 -0
- package/src/components/search/SearchResultsStates/SearchResultsLoadingGrid.tsx +50 -0
- package/src/components/search/types.ts +5 -0
- package/{dist/packages/components/src/components/test/types.d.ts → src/components/test/types.ts} +1 -1
- package/src/config/chatElementDisplayLocation.ts +22 -0
- package/{dist/packages/components/src/index.js → src/index.ts} +10 -0
- package/src/logging/logger.ts +21 -0
- package/src/types/external.ts +24 -0
- package/{dist/packages/components/src/util/camelCase.d.ts → src/util/camelCase.ts} +33 -11
- package/src/util/camelCasedPropertiesDeep.ts +81 -0
- package/src/util/formatPrice.ts +14 -0
- package/src/util/internal.ts +95 -0
- package/{dist/packages/components/src/util/primitive.d.ts → src/util/primitive.ts} +2 -0
- package/src/util/splitWords.ts +72 -0
- package/{dist/packages/components/src/util/trim.d.ts → src/util/trim.ts} +5 -1
- package/dist/packages/components/src/atoms/search/types.d.ts +0 -5
- package/dist/packages/components/src/atoms/search/types.js +0 -1
- package/dist/packages/components/src/components/common/ButtonBase/ButtonBase.d.ts +0 -2
- package/dist/packages/components/src/components/common/ButtonBase/ButtonBase.js +0 -41
- package/dist/packages/components/src/components/common/ButtonBase/types.d.ts +0 -24
- package/dist/packages/components/src/components/common/ButtonBase/types.js +0 -6
- package/dist/packages/components/src/components/common/Headline/Headline.d.ts +0 -10
- package/dist/packages/components/src/components/common/Headline/Headline.js +0 -34
- package/dist/packages/components/src/components/common/ImageWithFallback/ImageWithFallback.d.ts +0 -12
- package/dist/packages/components/src/components/common/ImageWithFallback/ImageWithFallback.js +0 -26
- package/dist/packages/components/src/components/common/ProductCard/ProductCard.d.ts +0 -39
- package/dist/packages/components/src/components/common/ProductCard/ProductCard.js +0 -83
- package/dist/packages/components/src/components/common/ProductCard/ProductCardSkeleton.d.ts +0 -9
- package/dist/packages/components/src/components/common/ProductCard/ProductCardSkeleton.js +0 -15
- package/dist/packages/components/src/components/common/ProductCard/productCardVariants.d.ts +0 -8
- package/dist/packages/components/src/components/common/ProductCard/productCardVariants.js +0 -50
- package/dist/packages/components/src/components/common/ProductCard/types.d.ts +0 -39
- package/dist/packages/components/src/components/common/ProductCard/types.js +0 -10
- package/dist/packages/components/src/components/common/ProductGrid/ProductGrid.d.ts +0 -14
- package/dist/packages/components/src/components/common/ProductGrid/ProductGrid.js +0 -13
- package/dist/packages/components/src/components/common/ProductGrid/productGridVariants.d.ts +0 -10
- package/dist/packages/components/src/components/common/ProductGrid/productGridVariants.js +0 -16
- package/dist/packages/components/src/components/common/SparkleAnimation/SparkleAnimation.d.ts +0 -7
- package/dist/packages/components/src/components/common/SparkleAnimation/SparkleAnimation.js +0 -40
- package/dist/packages/components/src/components/common/SparkleAnimation/types.d.ts +0 -6
- package/dist/packages/components/src/components/common/SparkleAnimation/types.js +0 -7
- package/dist/packages/components/src/components/common/Spinner/Spinner.d.ts +0 -5
- package/dist/packages/components/src/components/common/Spinner/Spinner.js +0 -16
- package/dist/packages/components/src/components/common/SuggestionButton/SuggestionButton.d.ts +0 -18
- package/dist/packages/components/src/components/common/SuggestionButton/SuggestionButton.js +0 -210
- package/dist/packages/components/src/components/common/SuggestionButton/types.d.ts +0 -1
- package/dist/packages/components/src/components/common/SuggestionButton/types.js +0 -1
- package/dist/packages/components/src/components/common/Text/Text.d.ts +0 -12
- package/dist/packages/components/src/components/common/Text/Text.js +0 -26
- package/dist/packages/components/src/components/common/Text/textVariantClasses.d.ts +0 -171
- package/dist/packages/components/src/components/common/Text/textVariantClasses.js +0 -103
- package/dist/packages/components/src/components/common/Text/types.d.ts +0 -16
- package/dist/packages/components/src/components/common/Text/types.js +0 -6
- package/dist/packages/components/src/components/common/TextInput/TextInput.d.ts +0 -8
- package/dist/packages/components/src/components/common/TextInput/TextInput.js +0 -25
- package/dist/packages/components/src/components/models/colorsConfig.d.ts +0 -26
- package/dist/packages/components/src/components/models/colorsConfig.js +0 -23
- package/dist/packages/components/src/components/search/FilterScrollbar/AppliedFiltersScrollbar.d.ts +0 -11
- package/dist/packages/components/src/components/search/FilterScrollbar/AppliedFiltersScrollbar.js +0 -18
- package/dist/packages/components/src/components/search/FilterScrollbar/DynamicFiltersScrollbar.d.ts +0 -15
- package/dist/packages/components/src/components/search/FilterScrollbar/DynamicFiltersScrollbar.js +0 -15
- package/dist/packages/components/src/components/search/SearchFilter/SearchFilter.d.ts +0 -2
- package/dist/packages/components/src/components/search/SearchFilter/SearchFilter.js +0 -24
- package/dist/packages/components/src/components/search/SearchFilter/SearchFilterHeader.d.ts +0 -2
- package/dist/packages/components/src/components/search/SearchFilter/SearchFilterHeader.js +0 -9
- package/dist/packages/components/src/components/search/SearchFilter/SearchFilterItem.d.ts +0 -2
- package/dist/packages/components/src/components/search/SearchFilter/SearchFilterItem.js +0 -13
- package/dist/packages/components/src/components/search/SearchFilter/types.d.ts +0 -42
- package/dist/packages/components/src/components/search/SearchFilter/types.js +0 -1
- package/dist/packages/components/src/components/search/SearchInput/SearchInput.d.ts +0 -16
- package/dist/packages/components/src/components/search/SearchInput/SearchInput.js +0 -38
- package/dist/packages/components/src/components/search/SearchInput/searchInputVariants.d.ts +0 -13
- package/dist/packages/components/src/components/search/SearchInput/searchInputVariants.js +0 -12
- package/dist/packages/components/src/components/search/SearchInputAutocomplete/SearchAutocomplete.d.ts +0 -10
- package/dist/packages/components/src/components/search/SearchInputAutocomplete/SearchAutocomplete.js +0 -14
- package/dist/packages/components/src/components/search/SearchInputForm/SearchInputForm.d.ts +0 -16
- package/dist/packages/components/src/components/search/SearchInputForm/SearchInputForm.js +0 -13
- package/dist/packages/components/src/components/search/SearchInputForm/types.js +0 -1
- package/dist/packages/components/src/components/search/SearchResultsFilterSidebar/SearchResultsFilter.d.ts +0 -14
- package/dist/packages/components/src/components/search/SearchResultsFilterSidebar/SearchResultsFilter.js +0 -15
- package/dist/packages/components/src/components/search/SearchResultsFilterSidebar/searchFilterSidebarVariants.d.ts +0 -16
- package/dist/packages/components/src/components/search/SearchResultsFilterSidebar/searchFilterSidebarVariants.js +0 -29
- package/dist/packages/components/src/components/search/SearchResultsFilterSidebar/types.js +0 -1
- package/dist/packages/components/src/components/search/SearchResultsStates/NoSearchResultsFound.d.ts +0 -8
- package/dist/packages/components/src/components/search/SearchResultsStates/NoSearchResultsFound.js +0 -10
- package/dist/packages/components/src/components/search/SearchResultsStates/SearchResultsGrid.d.ts +0 -24
- package/dist/packages/components/src/components/search/SearchResultsStates/SearchResultsGrid.js +0 -19
- package/dist/packages/components/src/components/search/SearchResultsStates/SearchResultsLoadingGrid.d.ts +0 -6
- package/dist/packages/components/src/components/search/SearchResultsStates/SearchResultsLoadingGrid.js +0 -10
- package/dist/packages/components/src/components/search/types.d.ts +0 -5
- package/dist/packages/components/src/components/search/types.js +0 -6
- package/dist/packages/components/src/components/test/types.js +0 -1
- package/dist/packages/components/src/config/chatElementDisplayLocation.d.ts +0 -21
- package/dist/packages/components/src/config/chatElementDisplayLocation.js +0 -23
- package/dist/packages/components/src/index.d.ts +0 -45
- package/dist/packages/components/src/logging/logger.d.ts +0 -7
- package/dist/packages/components/src/logging/logger.js +0 -16
- package/dist/packages/components/src/types/external.d.ts +0 -21
- package/dist/packages/components/src/types/external.js +0 -5
- package/dist/packages/components/src/util/camelCase.js +0 -2
- package/dist/packages/components/src/util/camelCasedPropertiesDeep.d.ts +0 -53
- package/dist/packages/components/src/util/camelCasedPropertiesDeep.js +0 -1
- package/dist/packages/components/src/util/formatPrice.d.ts +0 -1
- package/dist/packages/components/src/util/formatPrice.js +0 -11
- package/dist/packages/components/src/util/internal.d.ts +0 -27
- package/dist/packages/components/src/util/internal.js +0 -4
- package/dist/packages/components/src/util/primitive.js +0 -2
- package/dist/packages/components/src/util/splitWords.d.ts +0 -55
- package/dist/packages/components/src/util/splitWords.js +0 -2
- package/dist/packages/components/src/util/trim.js +0 -2
- package/dist/packages/components/src/util/unknownArray.js +0 -1
- package/dist/tsconfig.tsbuildinfo +0 -1
- /package/{dist/packages/components/src/components/search/SearchInputForm/types.d.ts → src/components/search/SearchInputForm/types.ts} +0 -0
- /package/{dist/packages/components/src/util/unknownArray.d.ts → src/util/unknownArray.ts} +0 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import classNames from 'classnames';
|
|
2
|
+
import { type TextType, type TextVariant } from './types';
|
|
3
|
+
import { TextVariantMap } from './textVariantClasses';
|
|
4
|
+
|
|
5
|
+
type TextProps = {
|
|
6
|
+
children: React.ReactNode;
|
|
7
|
+
noOfLines?: number;
|
|
8
|
+
className?: string;
|
|
9
|
+
style?: React.CSSProperties;
|
|
10
|
+
variant?: TextVariant;
|
|
11
|
+
type?: TextType;
|
|
12
|
+
testId?: string;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export const Text = ({
|
|
16
|
+
children,
|
|
17
|
+
className,
|
|
18
|
+
style,
|
|
19
|
+
noOfLines,
|
|
20
|
+
testId,
|
|
21
|
+
type = 'span',
|
|
22
|
+
variant = 'body3',
|
|
23
|
+
}: TextProps) => {
|
|
24
|
+
const variantClassNames = variant ? TextVariantMap[variant] : {};
|
|
25
|
+
const textClassNames = classNames(className, variantClassNames, {
|
|
26
|
+
'spiffy-tw-font-["Inter Variable,sans-serif"]': true,
|
|
27
|
+
'spiffy-tw-line-clamp-1': noOfLines === 1,
|
|
28
|
+
'spiffy-tw-line-clamp-2': noOfLines === 2,
|
|
29
|
+
'spiffy-tw-line-clamp-3': noOfLines === 3,
|
|
30
|
+
'spiffy-tw-line-clamp-4': noOfLines === 4,
|
|
31
|
+
'spiffy-tw-line-clamp-5': noOfLines === 5,
|
|
32
|
+
'spiffy-tw-line-clamp-6': noOfLines === 6,
|
|
33
|
+
'spiffy-tw-line-clamp-7': noOfLines === 7,
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
switch (type) {
|
|
37
|
+
case 'p':
|
|
38
|
+
return (
|
|
39
|
+
<p data-testid={testId} className={textClassNames} style={style}>
|
|
40
|
+
{children}
|
|
41
|
+
</p>
|
|
42
|
+
);
|
|
43
|
+
case 'span':
|
|
44
|
+
return (
|
|
45
|
+
<span data-testid={testId} className={textClassNames} style={style}>
|
|
46
|
+
{children}
|
|
47
|
+
</span>
|
|
48
|
+
);
|
|
49
|
+
case 'sub':
|
|
50
|
+
return (
|
|
51
|
+
<sub data-testid={testId} className={textClassNames} style={style}>
|
|
52
|
+
{children}
|
|
53
|
+
</sub>
|
|
54
|
+
);
|
|
55
|
+
default:
|
|
56
|
+
throw new Error(`Invalid text type: ${type}`);
|
|
57
|
+
}
|
|
58
|
+
};
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
// TODO: add the rest of the variants as needed
|
|
2
|
+
export const HeadlineVariantMap = {
|
|
3
|
+
t1: {
|
|
4
|
+
'spiffy-headline': true,
|
|
5
|
+
'spiffy-headline-1': true,
|
|
6
|
+
'spiffy-tw-text-[32px]': true,
|
|
7
|
+
'spiffy-tw-font-medium': true,
|
|
8
|
+
'spiffy-tw-leading-[124%]': true,
|
|
9
|
+
},
|
|
10
|
+
t2: {
|
|
11
|
+
'spiffy-headline': true,
|
|
12
|
+
'spiffy-headline-1': true,
|
|
13
|
+
'spiffy-tw-text-[16px]': true,
|
|
14
|
+
'spiffy-tw-font-medium': true,
|
|
15
|
+
'spiffy-tw-leading-[124%]': true,
|
|
16
|
+
},
|
|
17
|
+
t3: {
|
|
18
|
+
'spiffy-headline': true,
|
|
19
|
+
'spiffy-headline-1': true,
|
|
20
|
+
'spiffy-tw-text-[24px]': true,
|
|
21
|
+
'spiffy-tw-leading-[120%]': true,
|
|
22
|
+
},
|
|
23
|
+
h1: {
|
|
24
|
+
'spiffy-headline': true,
|
|
25
|
+
'spiffy-headline-1': true,
|
|
26
|
+
'spiffy-tw-text-[20px]': true,
|
|
27
|
+
'spiffy-tw-font-normal': true,
|
|
28
|
+
'spiffy-tw-leading-[120%]': true,
|
|
29
|
+
},
|
|
30
|
+
h2: {
|
|
31
|
+
'spiffy-headline': true,
|
|
32
|
+
'spiffy-headline-2': true,
|
|
33
|
+
'spiffy-tw-text-[16px]': true,
|
|
34
|
+
'spiffy-tw-font-normal': true,
|
|
35
|
+
'spiffy-tw-leading-[124%]': true,
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
h3: {
|
|
39
|
+
'spiffy-headline': true,
|
|
40
|
+
'spiffy-headline-3': true,
|
|
41
|
+
'spiffy-tw-text-[15px]': true,
|
|
42
|
+
'spiffy-tw-font-medium': true,
|
|
43
|
+
'spiffy-tw-leading-[124%]': true,
|
|
44
|
+
},
|
|
45
|
+
h4: {
|
|
46
|
+
'spiffy-headline': true,
|
|
47
|
+
'spiffy-headline-4': true,
|
|
48
|
+
'spiffy-tw-text-[14px]': true,
|
|
49
|
+
'spiffy-tw-font-medium': true,
|
|
50
|
+
'spiffy-tw-leading-[124%]': true,
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
// TODO: add the rest of the variants as needed
|
|
55
|
+
export const TextVariantMap = {
|
|
56
|
+
body1: {
|
|
57
|
+
'spiffy-body-text': true,
|
|
58
|
+
'spiffy-body-1': true,
|
|
59
|
+
'spiffy-tw-text-[20px]': true,
|
|
60
|
+
'spiffy-tw-font-normal': true,
|
|
61
|
+
'spiffy-tw-line-height-[120%]': true,
|
|
62
|
+
},
|
|
63
|
+
body2: {
|
|
64
|
+
'spiffy-body-text': true,
|
|
65
|
+
'spiffy-body-2': true,
|
|
66
|
+
'spiffy-tw-text-[16px]': true,
|
|
67
|
+
'spiffy-tw-font-normal': true,
|
|
68
|
+
'spiffy-tw-line-height-[148%]': true,
|
|
69
|
+
},
|
|
70
|
+
body3: {
|
|
71
|
+
'spiffy-body-text': true,
|
|
72
|
+
'spiffy-body-3': true,
|
|
73
|
+
'spiffy-tw-text-sm': true,
|
|
74
|
+
'spiffy-tw-font-normal': true,
|
|
75
|
+
'spiffy-tw-leading-[140%]': true,
|
|
76
|
+
},
|
|
77
|
+
body4: {
|
|
78
|
+
'spiffy-body-text': true,
|
|
79
|
+
'spiffy-body-4': true,
|
|
80
|
+
'spiffy-tw-text-xs': true,
|
|
81
|
+
'spiffy-tw-font-medium': true,
|
|
82
|
+
'spiffy-tw-leading-[130%]': true,
|
|
83
|
+
},
|
|
84
|
+
body5: {
|
|
85
|
+
'spiffy-body-text': true,
|
|
86
|
+
'spiffy-body-5': true,
|
|
87
|
+
'spiffy-tw-text-[10px]': true,
|
|
88
|
+
'spiffy-tw-font-normal': true,
|
|
89
|
+
},
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
export const TextStyleVariantMap = {
|
|
93
|
+
...TextVariantMap,
|
|
94
|
+
...HeadlineVariantMap,
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
export const getVariantPlaceholderClassNames = (classes: Record<string, boolean>) => {
|
|
98
|
+
return Object.keys(classes).reduce((acc, key) => {
|
|
99
|
+
if(key.includes('spiffy-tw')){
|
|
100
|
+
acc[`placeholder:${key}`] = classes[key];
|
|
101
|
+
} else {
|
|
102
|
+
acc[`${key}-placeholder`] = classes[key];
|
|
103
|
+
}
|
|
104
|
+
return acc;
|
|
105
|
+
}, {} as Record<string, boolean>);
|
|
106
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export enum ExpandableTextOverrides {
|
|
2
|
+
EXPANDABLE_TEXT_CONTAINER = 'spiffy-expandable-text-container',
|
|
3
|
+
EXPANDABLE_TEXT = 'spiffy-expandable-text',
|
|
4
|
+
EXPANDABLE_BUTTON = 'spiffy-expandable-button',
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
// This is an incomplete list of text variants
|
|
8
|
+
// TODO: add the rest of the variants as needed
|
|
9
|
+
export type TextVariant = 'body1' | 'body2' | 'body3' | 'body4' | 'body5';
|
|
10
|
+
export type TextType = 'p' | 'span' | 'sub';
|
|
11
|
+
|
|
12
|
+
export type HeadlineProps = {
|
|
13
|
+
children: React.ReactNode;
|
|
14
|
+
className?: string;
|
|
15
|
+
style?: React.CSSProperties;
|
|
16
|
+
variant?: HeadlineVariant;
|
|
17
|
+
testId?: string;
|
|
18
|
+
id?: string;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
// This is an incomplete list of text variants
|
|
22
|
+
// TODO: add the rest of the variants as needed
|
|
23
|
+
export type HeadlineVariant = 't1' | 't2' | 't3' | 'h1' | 'h2' | 'h3' | 'h4';
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// Disabling this prevents an otherwise simple wrapper around input
|
|
2
|
+
// from becoming needlessly verbose while maintaining flexibility.
|
|
3
|
+
// Keeping it enabled requires listing every possible prop.
|
|
4
|
+
import React from 'react';
|
|
5
|
+
import classNames from 'classnames';
|
|
6
|
+
import { getVariantPlaceholderClassNames, TextStyleVariantMap } from '../Text/textVariantClasses';
|
|
7
|
+
|
|
8
|
+
export interface TextInputProps extends React.InputHTMLAttributes<HTMLInputElement> {
|
|
9
|
+
borderRadius: 'sm' | 'md' | 'lg' | 'xl';
|
|
10
|
+
borderColorClass?: string;
|
|
11
|
+
placeholderVariant?: keyof typeof TextStyleVariantMap;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const TextInput = React.forwardRef<HTMLInputElement, TextInputProps>(
|
|
15
|
+
({ className, borderRadius, borderColorClass, placeholderVariant, ...rest }, ref) => {
|
|
16
|
+
const variantClassNames = placeholderVariant ? TextStyleVariantMap[placeholderVariant] : {};
|
|
17
|
+
const placeholderVariantClassNames = getVariantPlaceholderClassNames(variantClassNames);
|
|
18
|
+
const inputClasses = classNames([
|
|
19
|
+
{
|
|
20
|
+
'spiffy-text-input': true,
|
|
21
|
+
'spiffy-tw-outline-none': true,
|
|
22
|
+
'spiffy-tw-rounded-[64px]': borderRadius === 'xl',
|
|
23
|
+
'spiffy-tw-rounded-[20px]': borderRadius === 'lg',
|
|
24
|
+
'spiffy-tw-rounded-[8px]': borderRadius === 'md',
|
|
25
|
+
'spiffy-tw-rounded-[0px]': borderRadius === 'sm',
|
|
26
|
+
...placeholderVariantClassNames,
|
|
27
|
+
},
|
|
28
|
+
borderColorClass,
|
|
29
|
+
className,
|
|
30
|
+
]);
|
|
31
|
+
|
|
32
|
+
return <input ref={ref} {...rest} className={inputClasses} />;
|
|
33
|
+
},
|
|
34
|
+
);
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
enum ColorNames {
|
|
2
|
+
TextPrimary = 'text-primary',
|
|
3
|
+
TextSecondary = 'text-secondary',
|
|
4
|
+
TextAccent = 'text-accent',
|
|
5
|
+
TextLink = 'text-link',
|
|
6
|
+
TextLight = 'text-light',
|
|
7
|
+
BackgroundPrimary = 'background-primary',
|
|
8
|
+
BackgroundSecondary = 'background-secondary',
|
|
9
|
+
BackgroundSecondaryDark = 'background-secondary-dark',
|
|
10
|
+
BackgroundTertiary = 'background-tertiary',
|
|
11
|
+
BackgroundDark = 'background-dark',
|
|
12
|
+
BackgroundLight = 'background-light',
|
|
13
|
+
BackgroundSaturated = 'background-saturated',
|
|
14
|
+
BorderLight = 'border-light',
|
|
15
|
+
BorderMedium = 'border-medium',
|
|
16
|
+
BorderDark = 'border-dark',
|
|
17
|
+
BorderOutline = 'border-outline',
|
|
18
|
+
AccentPrimary = 'accent-primary',
|
|
19
|
+
AccentSecondary = 'accent-secondary',
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
type ColorMapping = {
|
|
23
|
+
[key in ColorNames]: string;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const colorVar = (color: ColorNames): string => `var(--spiffy-colors-${color})`;
|
|
27
|
+
export { ColorNames, colorVar };
|
|
28
|
+
export type { ColorMapping };
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import classNames from 'classnames';
|
|
2
|
+
import ScrollContainer from 'react-indiana-drag-scroll';
|
|
3
|
+
import { Text } from 'src/components/common/Text/Text';
|
|
4
|
+
import type { SelectedFilterOption } from 'src/atoms/search/types';
|
|
5
|
+
|
|
6
|
+
interface AppliedFiltersScrollbarProps {
|
|
7
|
+
selectedFilterOptions: SelectedFilterOption[];
|
|
8
|
+
filterBarClassNames: string;
|
|
9
|
+
filterDefaultClasses: string;
|
|
10
|
+
filterHoverClasses: string;
|
|
11
|
+
appliedFilterBackgroundClasses: string;
|
|
12
|
+
onRemoveFilter: (filter: SelectedFilterOption) => void;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const AppliedFiltersScrollbar = ({
|
|
16
|
+
selectedFilterOptions,
|
|
17
|
+
filterBarClassNames,
|
|
18
|
+
filterDefaultClasses,
|
|
19
|
+
filterHoverClasses,
|
|
20
|
+
appliedFilterBackgroundClasses,
|
|
21
|
+
onRemoveFilter,
|
|
22
|
+
}: AppliedFiltersScrollbarProps) => {
|
|
23
|
+
if (selectedFilterOptions.length === 0) {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Extract border and text classes from filterDefaultClasses, excluding background because everything is shared between filters except for the applied filters background
|
|
28
|
+
const filterDefaultWithoutBg = filterDefaultClasses
|
|
29
|
+
.replace(/spiffy-tw-bg-\[--spiffy-colors-[^\]]+\]/g, '')
|
|
30
|
+
.trim();
|
|
31
|
+
const buttonClasses = classNames(
|
|
32
|
+
' spiffy-tw-flex spiffy-tw-items-center spiffy-tw-rounded-full spiffy-tw-px-[8px] spiffy-tw-py-[4px] spiffy-tw-whitespace-nowrap',
|
|
33
|
+
filterHoverClasses,
|
|
34
|
+
filterDefaultWithoutBg,
|
|
35
|
+
appliedFilterBackgroundClasses,
|
|
36
|
+
);
|
|
37
|
+
const iconColor = 'currentColor'; // match with text color
|
|
38
|
+
|
|
39
|
+
return (
|
|
40
|
+
<ScrollContainer className={filterBarClassNames} hideScrollbars>
|
|
41
|
+
{selectedFilterOptions.map((filter) => {
|
|
42
|
+
return (
|
|
43
|
+
<button
|
|
44
|
+
key={filter.id}
|
|
45
|
+
className={buttonClasses}
|
|
46
|
+
type="button"
|
|
47
|
+
onClick={() => onRemoveFilter(filter)}
|
|
48
|
+
aria-label={`Remove filter: ${filter.displayName}`}
|
|
49
|
+
>
|
|
50
|
+
<div className="spiffy-tw-flex spiffy-tw-items-center spiffy-tw-gap-[8px]">
|
|
51
|
+
<Text variant="body3">{filter.displayName}</Text>
|
|
52
|
+
<svg
|
|
53
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
54
|
+
width="10"
|
|
55
|
+
height="10"
|
|
56
|
+
viewBox="0 0 10 10"
|
|
57
|
+
fill="none"
|
|
58
|
+
>
|
|
59
|
+
<path
|
|
60
|
+
d="M4.59766 4.29297L8.48535 0.405273L9.19238 1.1123L5.30469 5L9.19238 8.8877L8.48535 9.59473L4.59766 5.70703L0.707031 9.59766L0 8.89062L3.89062 5L0 1.10938L0.707031 0.402344L4.59766 4.29297Z"
|
|
61
|
+
fill={iconColor}
|
|
62
|
+
/>
|
|
63
|
+
</svg>
|
|
64
|
+
</div>
|
|
65
|
+
</button>
|
|
66
|
+
);
|
|
67
|
+
})}
|
|
68
|
+
</ScrollContainer>
|
|
69
|
+
);
|
|
70
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import classNames from 'classnames';
|
|
2
|
+
import ScrollContainer from 'react-indiana-drag-scroll';
|
|
3
|
+
import { Text } from 'src/components/common/Text/Text';
|
|
4
|
+
|
|
5
|
+
interface DynamicFiltersScrollbarProps {
|
|
6
|
+
availableDynamicFilters: { name: string; displayName: string }[];
|
|
7
|
+
filterBarClassNames: string;
|
|
8
|
+
filterDefaultClasses: string;
|
|
9
|
+
filterHoverClasses: string;
|
|
10
|
+
onToggleDynamicFilter: ({
|
|
11
|
+
filter,
|
|
12
|
+
dynamicFilterDisplayName,
|
|
13
|
+
}: {
|
|
14
|
+
filter: string;
|
|
15
|
+
dynamicFilterDisplayName: string;
|
|
16
|
+
}) => void;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const DynamicFiltersScrollbar = ({
|
|
20
|
+
availableDynamicFilters,
|
|
21
|
+
filterBarClassNames,
|
|
22
|
+
filterDefaultClasses,
|
|
23
|
+
filterHoverClasses,
|
|
24
|
+
onToggleDynamicFilter,
|
|
25
|
+
}: DynamicFiltersScrollbarProps) => {
|
|
26
|
+
return (
|
|
27
|
+
<ScrollContainer className={filterBarClassNames} hideScrollbars>
|
|
28
|
+
{availableDynamicFilters.map(({ name, displayName }) => {
|
|
29
|
+
const buttonClasses = classNames(
|
|
30
|
+
'spiffy-tw-px-[12px] spiffy-tw-py-2 spiffy-tw-rounded-full spiffy-tw-border spiffy-tw-whitespace-nowrap ',
|
|
31
|
+
filterHoverClasses,
|
|
32
|
+
filterDefaultClasses,
|
|
33
|
+
);
|
|
34
|
+
return (
|
|
35
|
+
<button
|
|
36
|
+
key={name}
|
|
37
|
+
type="button"
|
|
38
|
+
className={buttonClasses}
|
|
39
|
+
onClick={() => {
|
|
40
|
+
onToggleDynamicFilter({
|
|
41
|
+
filter: name,
|
|
42
|
+
dynamicFilterDisplayName: displayName,
|
|
43
|
+
});
|
|
44
|
+
}}
|
|
45
|
+
>
|
|
46
|
+
<Text variant="body3">{displayName}</Text>
|
|
47
|
+
</button>
|
|
48
|
+
);
|
|
49
|
+
})}
|
|
50
|
+
</ScrollContainer>
|
|
51
|
+
);
|
|
52
|
+
};
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import classNames from 'classnames';
|
|
2
|
+
import { SearchFilterItem } from './SearchFilterItem';
|
|
3
|
+
import type { SearchFilterProps } from './types';
|
|
4
|
+
import { Text } from 'src/components/common/Text/Text';
|
|
5
|
+
import { ButtonBase } from 'src/components/common/ButtonBase/ButtonBase';
|
|
6
|
+
|
|
7
|
+
export const SearchFilter = ({
|
|
8
|
+
isOpen,
|
|
9
|
+
setIsOpen,
|
|
10
|
+
filters,
|
|
11
|
+
// productCount,
|
|
12
|
+
selectFilterItem,
|
|
13
|
+
clearAllFilters,
|
|
14
|
+
// applyFiltersUnchangedClasses,
|
|
15
|
+
// applyFiltersChangedClasses,
|
|
16
|
+
filterButtonText,
|
|
17
|
+
radioButtonFillColor,
|
|
18
|
+
radioButtonHoverColor,
|
|
19
|
+
radioButtonUncheckedBorderColor,
|
|
20
|
+
// filterCloseIconVariant,
|
|
21
|
+
headerContent,
|
|
22
|
+
}: SearchFilterProps) => {
|
|
23
|
+
const modalClasses = classNames(
|
|
24
|
+
'spiffy-tw-fixed spiffy-tw-inset-0 spiffy-tw-z-50 spiffy-tw-flex spiffy-tw-transform spiffy-tw-transition-all',
|
|
25
|
+
{
|
|
26
|
+
'spiffy-tw-translate-x-full': !isOpen,
|
|
27
|
+
'spiffy-tw-translate-x-0': isOpen,
|
|
28
|
+
},
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
const overlayClasses = classNames(
|
|
32
|
+
'spiffy-tw-absolute spiffy-tw-inset-0 spiffy-tw-bg-black spiffy-tw-bg-opacity-50',
|
|
33
|
+
{
|
|
34
|
+
'spiffy-tw-opacity-0': !isOpen,
|
|
35
|
+
'spiffy-tw-opacity-100': isOpen,
|
|
36
|
+
},
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
const sidebarClasses = classNames(
|
|
40
|
+
'spiffy-tw-relative spiffy-tw-ml-auto spiffy-tw-flex spiffy-tw-h-full spiffy-tw-w-full spiffy-tw-max-w-xs spiffy-tw-flex-col spiffy-tw-overflow-y-auto spiffy-tw-bg-[--spiffy-colors-background-light] spiffy-tw-py-4 spiffy-tw-shadow-xl',
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
<div className={modalClasses}>
|
|
45
|
+
<div className={overlayClasses} onClick={() => setIsOpen(false)} />
|
|
46
|
+
<div className={sidebarClasses}>
|
|
47
|
+
{headerContent}
|
|
48
|
+
<div className="spiffy-tw-flex-1 spiffy-tw-px-4 spiffy-tw-py-6">
|
|
49
|
+
{filters.map((filter) => (
|
|
50
|
+
<div key={filter.id} className="spiffy-tw-mb-6">
|
|
51
|
+
<Text variant="body2" className="spiffy-tw-font-medium spiffy-tw-mb-3">
|
|
52
|
+
{filter.displayName}
|
|
53
|
+
</Text>
|
|
54
|
+
<ul>
|
|
55
|
+
{filter.items.map((item) => (
|
|
56
|
+
<SearchFilterItem
|
|
57
|
+
key={item.id}
|
|
58
|
+
filterItem={item}
|
|
59
|
+
onSelectFilterItem={selectFilterItem}
|
|
60
|
+
radioButtonFillColor={radioButtonFillColor}
|
|
61
|
+
radioButtonHoverColor={radioButtonHoverColor}
|
|
62
|
+
radioButtonUncheckedBorderColor={radioButtonUncheckedBorderColor}
|
|
63
|
+
/>
|
|
64
|
+
))}
|
|
65
|
+
</ul>
|
|
66
|
+
</div>
|
|
67
|
+
))}
|
|
68
|
+
</div>
|
|
69
|
+
<div className="spiffy-tw-border-t spiffy-tw-border-[--spiffy-colors-border-light] spiffy-tw-px-4 spiffy-tw-py-3">
|
|
70
|
+
<ButtonBase
|
|
71
|
+
onClick={clearAllFilters}
|
|
72
|
+
text="Clear All"
|
|
73
|
+
buttonClass="spiffy-tw-w-full spiffy-tw-mb-2"
|
|
74
|
+
/>
|
|
75
|
+
<ButtonBase
|
|
76
|
+
onClick={() => setIsOpen(false)}
|
|
77
|
+
text={filterButtonText}
|
|
78
|
+
buttonClass="spiffy-tw-w-full"
|
|
79
|
+
/>
|
|
80
|
+
</div>
|
|
81
|
+
</div>
|
|
82
|
+
</div>
|
|
83
|
+
);
|
|
84
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import classNames from 'classnames';
|
|
2
|
+
import { Text } from 'src/components/common/Text/Text';
|
|
3
|
+
import type { SearchFilterHeaderProps } from './types';
|
|
4
|
+
|
|
5
|
+
export const SearchFilterHeader = ({
|
|
6
|
+
closeModal,
|
|
7
|
+
productCount,
|
|
8
|
+
headerClassName,
|
|
9
|
+
filterCloseIconVariant,
|
|
10
|
+
}: SearchFilterHeaderProps) => {
|
|
11
|
+
const closeIconColor =
|
|
12
|
+
filterCloseIconVariant === 'dark'
|
|
13
|
+
? 'var(--spiffy-colors-text-primary)'
|
|
14
|
+
: 'var(--spiffy-colors-text-light)';
|
|
15
|
+
|
|
16
|
+
return (
|
|
17
|
+
<div
|
|
18
|
+
className={classNames(
|
|
19
|
+
'spiffy-tw-flex spiffy-tw-items-center spiffy-tw-justify-between spiffy-tw-px-4 spiffy-tw-py-3',
|
|
20
|
+
headerClassName,
|
|
21
|
+
)}
|
|
22
|
+
>
|
|
23
|
+
<Text variant="body2" className="spiffy-tw-font-medium">
|
|
24
|
+
Filters ({productCount})
|
|
25
|
+
</Text>
|
|
26
|
+
<button onClick={closeModal} className="spiffy-tw-p-2">
|
|
27
|
+
<svg
|
|
28
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
29
|
+
width="14"
|
|
30
|
+
height="14"
|
|
31
|
+
viewBox="0 0 14 14"
|
|
32
|
+
fill="none"
|
|
33
|
+
>
|
|
34
|
+
<path
|
|
35
|
+
d="M13.7071 1.70711C14.0976 1.31658 14.0976 0.683417 13.7071 0.292893C13.3166 -0.0976311 12.6834 -0.0976311 12.2929 0.292893L7 5.58579L1.70711 0.292893C1.31658 -0.0976311 0.683417 -0.0976311 0.292893 0.292893C-0.0976311 0.683417 -0.0976311 1.31658 0.292893 1.70711L5.58579 7L0.292893 12.2929C-0.0976311 12.6834 -0.0976311 13.3166 0.292893 13.7071C0.683417 14.0976 1.31658 14.0976 1.70711 13.7071L7 8.41421L12.2929 13.7071C12.6834 14.0976 13.3166 14.0976 13.7071 13.7071C14.0976 13.3166 14.0976 12.6834 13.7071 12.2929L8.41421 7L13.7071 1.70711Z"
|
|
36
|
+
fill={closeIconColor}
|
|
37
|
+
/>
|
|
38
|
+
</svg>
|
|
39
|
+
</button>
|
|
40
|
+
</div>
|
|
41
|
+
);
|
|
42
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import classNames from 'classnames';
|
|
2
|
+
import { Text } from 'src/components/common/Text/Text';
|
|
3
|
+
import type { SearchFilterItemProps } from './types';
|
|
4
|
+
|
|
5
|
+
export const SearchFilterItem = ({
|
|
6
|
+
filterItem,
|
|
7
|
+
onSelectFilterItem,
|
|
8
|
+
radioButtonFillColor,
|
|
9
|
+
radioButtonHoverColor,
|
|
10
|
+
radioButtonUncheckedBorderColor,
|
|
11
|
+
}: SearchFilterItemProps) => {
|
|
12
|
+
const { displayName, isSelected } = filterItem;
|
|
13
|
+
|
|
14
|
+
const radioClasses = classNames(
|
|
15
|
+
'spiffy-tw-w-4 spiffy-tw-h-4 spiffy-tw-rounded-full spiffy-tw-border-2',
|
|
16
|
+
'spiffy-tw-flex spiffy-tw-items-center spiffy-tw-justify-center',
|
|
17
|
+
radioButtonUncheckedBorderColor,
|
|
18
|
+
radioButtonHoverColor,
|
|
19
|
+
{
|
|
20
|
+
[radioButtonFillColor]: isSelected,
|
|
21
|
+
},
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<li
|
|
26
|
+
className="spiffy-tw-flex spiffy-tw-items-center spiffy-tw-justify-between spiffy-tw-py-2 spiffy-tw-cursor-pointer"
|
|
27
|
+
onClick={() => onSelectFilterItem(filterItem)}
|
|
28
|
+
>
|
|
29
|
+
<Text variant="body3">{displayName}</Text>
|
|
30
|
+
<div className={radioClasses}>
|
|
31
|
+
{isSelected && (
|
|
32
|
+
<div
|
|
33
|
+
className={classNames('spiffy-tw-w-2 spiffy-tw-h-2 spiffy-tw-rounded-full', {
|
|
34
|
+
'spiffy-tw-bg-white': radioButtonFillColor.includes('spiffy-tw-bg-'),
|
|
35
|
+
'spiffy-tw-bg-black': radioButtonFillColor.includes('spiffy-tw-bg-white'),
|
|
36
|
+
})}
|
|
37
|
+
/>
|
|
38
|
+
)}
|
|
39
|
+
</div>
|
|
40
|
+
</li>
|
|
41
|
+
);
|
|
42
|
+
};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
|
|
3
|
+
export type SearchFilterItem = {
|
|
4
|
+
id: string;
|
|
5
|
+
displayName: string;
|
|
6
|
+
value: string;
|
|
7
|
+
isSelected: boolean;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export type SearchFilter = {
|
|
11
|
+
id: string;
|
|
12
|
+
displayName: string;
|
|
13
|
+
items: SearchFilterItem[];
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export type SelectFilterItem = (filterItem: SearchFilterItem) => void;
|
|
17
|
+
|
|
18
|
+
export interface SearchFilterItemProps {
|
|
19
|
+
filterItem: SearchFilterItem;
|
|
20
|
+
onSelectFilterItem: SelectFilterItem;
|
|
21
|
+
radioButtonFillColor: string;
|
|
22
|
+
radioButtonHoverColor: string;
|
|
23
|
+
radioButtonUncheckedBorderColor: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface SearchFilterHeaderProps {
|
|
27
|
+
closeModal: () => void;
|
|
28
|
+
productCount: number;
|
|
29
|
+
headerClassName: string;
|
|
30
|
+
filterCloseIconVariant: 'dark' | 'light' | 'tertiary';
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface SearchFilterProps {
|
|
34
|
+
isOpen: boolean;
|
|
35
|
+
setIsOpen: (isOpen: boolean) => void;
|
|
36
|
+
filters: SearchFilter[];
|
|
37
|
+
productCount: number;
|
|
38
|
+
selectFilterItem: SelectFilterItem;
|
|
39
|
+
clearAllFilters: () => void;
|
|
40
|
+
applyFiltersUnchangedClasses: string;
|
|
41
|
+
applyFiltersChangedClasses: string;
|
|
42
|
+
filterButtonText: string;
|
|
43
|
+
radioButtonFillColor: string;
|
|
44
|
+
radioButtonHoverColor: string;
|
|
45
|
+
radioButtonUncheckedBorderColor: string;
|
|
46
|
+
filterCloseIconVariant: 'dark' | 'light' | 'tertiary';
|
|
47
|
+
headerContent: ReactNode;
|
|
48
|
+
}
|