emoji-picker-react 4.6.14 → 4.7.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.
Files changed (51) hide show
  1. package/README.md +37 -12
  2. package/dist/components/Reactions/BtnPlus.d.ts +2 -0
  3. package/dist/components/Reactions/DEFAULT_REACTIONS.d.ts +1 -0
  4. package/dist/components/Reactions/Reactions.d.ts +2 -0
  5. package/dist/components/context/ElementRefContext.d.ts +1 -0
  6. package/dist/components/context/PickerContext.d.ts +1 -0
  7. package/dist/components/emoji/ClickableEmojiButton.d.ts +2 -1
  8. package/dist/components/emoji/Emoji.d.ts +2 -1
  9. package/dist/components/header/Search/BtnClearSearch.d.ts +2 -0
  10. package/dist/components/header/Search/IcnSearch.d.ts +2 -0
  11. package/dist/components/header/SkinTonePicker/BtnSkinToneVariation.d.ts +11 -0
  12. package/dist/components/navigation/CategoryButton.d.ts +11 -0
  13. package/dist/config/config.d.ts +2 -0
  14. package/dist/config/useConfig.d.ts +2 -0
  15. package/dist/emoji-picker-react.cjs.development.js +1265 -963
  16. package/dist/emoji-picker-react.cjs.development.js.map +1 -1
  17. package/dist/emoji-picker-react.cjs.production.min.js +1 -1
  18. package/dist/emoji-picker-react.cjs.production.min.js.map +1 -1
  19. package/dist/emoji-picker-react.esm.js +1266 -964
  20. package/dist/emoji-picker-react.esm.js.map +1 -1
  21. package/package.json +5 -2
  22. package/src/EmojiPickerReact.tsx +28 -3
  23. package/src/Stylesheet/stylesheet.tsx +14 -2
  24. package/src/components/Reactions/BtnPlus.tsx +78 -0
  25. package/src/components/Reactions/DEFAULT_REACTIONS.ts +9 -0
  26. package/src/components/Reactions/Reactions.tsx +62 -0
  27. package/src/components/Reactions/svg/plus.svg +17 -0
  28. package/src/components/body/Body.tsx +8 -2
  29. package/src/components/body/EmojiVariationPicker.tsx +6 -7
  30. package/src/components/context/ElementRefContext.tsx +10 -2
  31. package/src/components/context/PickerContext.tsx +16 -3
  32. package/src/components/emoji/ClickableEmojiButton.tsx +13 -3
  33. package/src/components/emoji/Emoji.tsx +4 -1
  34. package/src/components/footer/Preview.tsx +11 -8
  35. package/src/components/header/Header.tsx +6 -2
  36. package/src/components/header/Search/BtnClearSearch.tsx +91 -0
  37. package/src/components/header/{CssSearch.tsx → Search/CssSearch.tsx} +2 -2
  38. package/src/components/header/Search/IcnSearch.tsx +39 -0
  39. package/src/components/header/{Search.tsx → Search/Search.tsx} +14 -49
  40. package/src/components/header/SkinTonePicker/BtnSkinToneVariation.tsx +80 -0
  41. package/src/components/header/{SkinTonePicker.tsx → SkinTonePicker/SkinTonePicker.tsx} +25 -67
  42. package/src/components/main/PickerMain.tsx +27 -2
  43. package/src/components/navigation/CategoryButton.tsx +141 -0
  44. package/src/components/navigation/CategoryNavigation.tsx +10 -129
  45. package/src/config/config.ts +7 -2
  46. package/src/config/useConfig.ts +16 -3
  47. /package/dist/components/header/{CssSearch.d.ts → Search/CssSearch.d.ts} +0 -0
  48. /package/dist/components/header/{Search.d.ts → Search/Search.d.ts} +0 -0
  49. /package/dist/components/header/{SkinTonePicker.d.ts → SkinTonePicker/SkinTonePicker.d.ts} +0 -0
  50. /package/src/components/header/{svg → Search/svg}/magnifier.svg +0 -0
  51. /package/src/components/header/{svg → Search/svg}/times.svg +0 -0
@@ -1,7 +1,7 @@
1
1
  import * as React from 'react';
2
2
 
3
- import { ClassNames, asSelectors } from '../../DomUtils/classNames';
4
- import { getNormalizedSearchTerm } from '../../hooks/useFilter';
3
+ import { ClassNames, asSelectors } from '../../../DomUtils/classNames';
4
+ import { getNormalizedSearchTerm } from '../../../hooks/useFilter';
5
5
 
6
6
  const SCOPE = `${asSelectors(ClassNames.emojiPicker)} ${asSelectors(
7
7
  ClassNames.emojiList
@@ -0,0 +1,39 @@
1
+ import { cx } from 'flairup';
2
+ import * as React from 'react';
3
+
4
+ import { stylesheet } from '../../../Stylesheet/stylesheet';
5
+
6
+ import SVGMagnifier from './svg/magnifier.svg';
7
+
8
+ export function IcnSearch() {
9
+ return <div className={cx(styles.icnSearch)} />;
10
+ }
11
+
12
+ const styles = stylesheet.create({
13
+ icnSearch: {
14
+ '.': 'epr-icn-search',
15
+ content: '',
16
+ position: 'absolute',
17
+ top: '50%',
18
+ left: 'var(--epr-search-bar-inner-padding)',
19
+ transform: 'translateY(-50%)',
20
+ width: '20px',
21
+ height: '20px',
22
+ backgroundRepeat: 'no-repeat',
23
+ backgroundPosition: '0 0',
24
+ backgroundSize: '20px',
25
+ backgroundImage: `url(${SVGMagnifier})`
26
+ },
27
+ '.epr-dark-theme': {
28
+ icnSearch: {
29
+ backgroundPositionY: '-20px'
30
+ }
31
+ },
32
+ '.epr-auto-theme': {
33
+ icnSearch: {
34
+ '@media (prefers-color-scheme: dark)': {
35
+ backgroundPositionY: '-20px'
36
+ }
37
+ }
38
+ }
39
+ });
@@ -2,26 +2,23 @@ import { cx } from 'flairup';
2
2
  import * as React from 'react';
3
3
  import { useState } from 'react';
4
4
 
5
- import {
6
- commonInteractionStyles,
7
- stylesheet
8
- } from '../../Stylesheet/stylesheet';
5
+ import { stylesheet } from '../../../Stylesheet/stylesheet';
9
6
  import {
10
7
  useAutoFocusSearchConfig,
11
8
  useSearchDisabledConfig,
12
9
  useSearchPlaceHolderConfig
13
- } from '../../config/useConfig';
14
- import { useCloseAllOpenToggles } from '../../hooks/useCloseAllOpenToggles';
15
- import { useClearSearch, useFilter } from '../../hooks/useFilter';
16
- import { useIsSkinToneInSearch } from '../../hooks/useShouldShowSkinTonePicker';
17
- import Flex from '../Layout/Flex';
18
- import Relative from '../Layout/Relative';
19
- import { Button } from '../atoms/Button';
20
- import { useSearchInputRef } from '../context/ElementRefContext';
10
+ } from '../../../config/useConfig';
11
+ import { useCloseAllOpenToggles } from '../../../hooks/useCloseAllOpenToggles';
12
+ import { useFilter } from '../../../hooks/useFilter';
13
+ import { useIsSkinToneInSearch } from '../../../hooks/useShouldShowSkinTonePicker';
14
+ import Flex from '../../Layout/Flex';
15
+ import Relative from '../../Layout/Relative';
16
+ import { useSearchInputRef } from '../../context/ElementRefContext';
17
+ import { SkinTonePicker } from '../SkinTonePicker/SkinTonePicker';
21
18
 
19
+ import { BtnClearSearch } from './BtnClearSearch';
22
20
  import { CssSearch } from './CssSearch';
23
- import { SkinTonePicker } from './SkinTonePicker';
24
- import SVGMagnifier from './svg/magnifier.svg';
21
+ import { IcnSearch } from './IcnSearch';
25
22
  import SVGTimes from './svg/times.svg';
26
23
 
27
24
  export function SearchContainer() {
@@ -46,7 +43,6 @@ export function Search() {
46
43
  const [inc, setInc] = useState(0);
47
44
  const closeAllOpenToggles = useCloseAllOpenToggles();
48
45
  const SearchInputRef = useSearchInputRef();
49
- const clearSearch = useClearSearch();
50
46
  const placeholder = useSearchPlaceHolderConfig();
51
47
  const autoFocus = useAutoFocusSearchConfig();
52
48
  const { statusSearchResults, searchTerm, onChange } = useFilter();
@@ -85,18 +81,8 @@ export function Search() {
85
81
  {statusSearchResults}
86
82
  </div>
87
83
  ) : null}
88
- <div className={cx(styles.icnSearch)} />
89
- <Button
90
- className={cx(
91
- styles.btnClearSearch,
92
- commonInteractionStyles.visibleOnSearchOnly
93
- )}
94
- onClick={clearSearch}
95
- aria-label="Clear"
96
- title="Clear"
97
- >
98
- <div className={cx(styles.icnClearnSearch)} />
99
- </Button>
84
+ <IcnSearch />
85
+ <BtnClearSearch />
100
86
  </Relative>
101
87
  );
102
88
  }
@@ -139,20 +125,7 @@ const styles = stylesheet.create({
139
125
  color: 'var(--epr-search-input-placeholder-color)'
140
126
  }
141
127
  },
142
- icnSearch: {
143
- '.': 'epr-icn-search',
144
- content: '',
145
- position: 'absolute',
146
- top: '50%',
147
- left: 'var(--epr-search-bar-inner-padding)',
148
- transform: 'translateY(-50%)',
149
- width: '20px',
150
- height: '20px',
151
- backgroundRepeat: 'no-repeat',
152
- backgroundPosition: '0 0',
153
- backgroundSize: '20px',
154
- backgroundImage: `url(${SVGMagnifier})`
155
- },
128
+
156
129
  btnClearSearch: {
157
130
  '.': 'epr-btn-clear-search',
158
131
  position: 'absolute',
@@ -189,9 +162,6 @@ const styles = stylesheet.create({
189
162
  }
190
163
  },
191
164
  '.epr-dark-theme': {
192
- icnSearch: {
193
- backgroundPositionY: '-20px'
194
- },
195
165
  icnClearnSearch: {
196
166
  backgroundPositionY: '-40px'
197
167
  },
@@ -202,11 +172,6 @@ const styles = stylesheet.create({
202
172
  }
203
173
  },
204
174
  '.epr-auto-theme': {
205
- icnSearch: {
206
- '@media (prefers-color-scheme: dark)': {
207
- backgroundPositionY: '-20px'
208
- }
209
- },
210
175
  icnClearnSearch: {
211
176
  '@media (prefers-color-scheme: dark)': {
212
177
  backgroundPositionY: '-40px'
@@ -0,0 +1,80 @@
1
+ import { cx } from 'flairup';
2
+ import * as React from 'react';
3
+
4
+ import { stylesheet } from '../../../Stylesheet/stylesheet';
5
+ import { skinTonesNamed } from '../../../data/skinToneVariations';
6
+ import { SkinTones } from '../../../types/exposedTypes';
7
+ import { Button } from '../../atoms/Button';
8
+
9
+ type Props = {
10
+ isOpen: boolean;
11
+ onClick: () => void;
12
+ isActive: boolean;
13
+ skinToneVariation: SkinTones;
14
+ style?: React.CSSProperties;
15
+ };
16
+
17
+ // eslint-disable-next-line complexity
18
+ export function BtnSkinToneVariation({
19
+ isOpen,
20
+ onClick,
21
+ isActive,
22
+ skinToneVariation,
23
+ style
24
+ }: Props) {
25
+ return (
26
+ <Button
27
+ style={style}
28
+ onClick={onClick}
29
+ className={cx(
30
+ `epr-tone-${skinToneVariation}`,
31
+ styles.tone,
32
+ !isOpen && styles.closedTone,
33
+ isActive && styles.active
34
+ )}
35
+ tabIndex={isOpen ? 0 : -1}
36
+ aria-pressed={isActive}
37
+ aria-label={`Skin tone ${skinTonesNamed[skinToneVariation as SkinTones]}`}
38
+ ></Button>
39
+ );
40
+ }
41
+
42
+ const styles = stylesheet.create({
43
+ closedTone: {
44
+ opacity: '0',
45
+ zIndex: '0'
46
+ },
47
+ active: {
48
+ '.': 'epr-active',
49
+ zIndex: '1',
50
+ opacity: '1'
51
+ },
52
+ tone: {
53
+ '.': 'epr-tone',
54
+ ':hover': {
55
+ boxShadow: '0 0 0 3px var(--epr-active-skin-hover-color)'
56
+ },
57
+ ':focus': {
58
+ boxShadow: '0 0 0 3px var(--epr-focus-bg-color)'
59
+ },
60
+ // @ts-ignore
61
+ '&.epr-tone-neutral': {
62
+ backgroundColor: '#ffd225'
63
+ },
64
+ '&.epr-tone-1f3fb': {
65
+ backgroundColor: '#ffdfbd'
66
+ },
67
+ '&.epr-tone-1f3fc': {
68
+ backgroundColor: '#e9c197'
69
+ },
70
+ '&.epr-tone-1f3fd': {
71
+ backgroundColor: '#c88e62'
72
+ },
73
+ '&.epr-tone-1f3fe': {
74
+ backgroundColor: '#a86637'
75
+ },
76
+ '&.epr-tone-1f3ff': {
77
+ backgroundColor: '#60463a'
78
+ }
79
+ }
80
+ });
@@ -2,23 +2,21 @@
2
2
  import { cx } from 'flairup';
3
3
  import * as React from 'react';
4
4
 
5
- import { ClassNames } from '../../DomUtils/classNames';
6
- import { stylesheet } from '../../Stylesheet/stylesheet';
7
- import { useSkinTonesDisabledConfig } from '../../config/useConfig';
8
- import skinToneVariations, {
9
- skinTonesNamed
10
- } from '../../data/skinToneVariations';
11
- import { useCloseAllOpenToggles } from '../../hooks/useCloseAllOpenToggles';
12
- import { useFocusSearchInput } from '../../hooks/useFocus';
13
- import { SkinTones } from '../../types/exposedTypes';
14
- import Absolute from '../Layout/Absolute';
15
- import Relative from '../Layout/Relative';
16
- import { Button } from '../atoms/Button';
17
- import { useSkinTonePickerRef } from '../context/ElementRefContext';
5
+ import { ClassNames } from '../../../DomUtils/classNames';
6
+ import { stylesheet } from '../../../Stylesheet/stylesheet';
7
+ import { useSkinTonesDisabledConfig } from '../../../config/useConfig';
8
+ import skinToneVariations from '../../../data/skinToneVariations';
9
+ import { useCloseAllOpenToggles } from '../../../hooks/useCloseAllOpenToggles';
10
+ import { useFocusSearchInput } from '../../../hooks/useFocus';
11
+ import Absolute from '../../Layout/Absolute';
12
+ import Relative from '../../Layout/Relative';
13
+ import { useSkinTonePickerRef } from '../../context/ElementRefContext';
18
14
  import {
19
15
  useActiveSkinToneState,
20
16
  useSkinToneFanOpenState
21
- } from '../context/PickerContext';
17
+ } from '../../context/PickerContext';
18
+
19
+ import { BtnSkinToneVariation } from './BtnSkinToneVariation';
22
20
 
23
21
  const ITEM_SIZE = 28;
24
22
 
@@ -61,7 +59,8 @@ export function SkinTonePicker({
61
59
  className={cx(
62
60
  styles.skinTones,
63
61
  vertical && styles.vertical,
64
- isOpen && styles.open
62
+ isOpen && styles.open,
63
+ vertical && isOpen && styles.verticalShadow
65
64
  )}
66
65
  style={
67
66
  vertical
@@ -72,8 +71,12 @@ export function SkinTonePicker({
72
71
  <div className={cx(styles.select)} ref={SkinTonePickerRef}>
73
72
  {skinToneVariations.map((skinToneVariation, i) => {
74
73
  const active = skinToneVariation === activeSkinTone;
74
+
75
75
  return (
76
- <Button
76
+ <BtnSkinToneVariation
77
+ key={skinToneVariation}
78
+ skinToneVariation={skinToneVariation}
79
+ isOpen={isOpen}
77
80
  style={{
78
81
  transform: cx(
79
82
  vertical
@@ -82,6 +85,7 @@ export function SkinTonePicker({
82
85
  isOpen && active && 'scale(1.3)'
83
86
  )
84
87
  }}
88
+ isActive={active}
85
89
  onClick={() => {
86
90
  if (isOpen) {
87
91
  setActiveSkinTone(skinToneVariation);
@@ -91,19 +95,7 @@ export function SkinTonePicker({
91
95
  }
92
96
  closeAllOpenToggles();
93
97
  }}
94
- key={skinToneVariation}
95
- className={cx(
96
- `epr-tone-${skinToneVariation}`,
97
- styles.tone,
98
- !isOpen && styles.closedTone,
99
- active && styles.active
100
- )}
101
- tabIndex={isOpen ? 0 : -1}
102
- aria-pressed={active}
103
- aria-label={`Skin tone ${
104
- skinTonesNamed[skinToneVariation as SkinTones]
105
- }`}
106
- ></Button>
98
+ />
107
99
  );
108
100
  })}
109
101
  </div>
@@ -129,12 +121,15 @@ const styles = stylesheet.create({
129
121
  padding: '10px 0'
130
122
  },
131
123
  vertical: {
132
- padding: '5px',
124
+ padding: '9px',
133
125
  alignItems: 'flex-end',
134
126
  flexDirection: 'column',
135
127
  borderRadius: '6px',
136
128
  border: '1px solid var(--epr-bg-color)'
137
129
  },
130
+ verticalShadow: {
131
+ boxShadow: '0px 0 7px var(--epr-picker-border-color)'
132
+ },
138
133
  open: {
139
134
  // @ts-ignore
140
135
  backdropFilter: 'blur(5px)',
@@ -169,42 +164,5 @@ const styles = stylesheet.create({
169
164
  zIndex: '0',
170
165
  boxShadow: '0 0 0 0px var(--epr-active-skin-hover-color)'
171
166
  }
172
- },
173
- closedTone: {
174
- opacity: '0',
175
- zIndex: '0'
176
- },
177
- active: {
178
- '.': 'epr-active',
179
- zIndex: '1',
180
- opacity: '1'
181
- },
182
- tone: {
183
- '.': 'epr-tone',
184
- ':hover': {
185
- boxShadow: '0 0 0 3px var(--epr-active-skin-hover-color)'
186
- },
187
- ':focus': {
188
- boxShadow: '0 0 0 3px var(--epr-focus-bg-color)'
189
- },
190
- // @ts-ignore
191
- '&.epr-tone-neutral': {
192
- backgroundColor: '#ffd225'
193
- },
194
- '&.epr-tone-1f3fb': {
195
- backgroundColor: '#ffdfbd'
196
- },
197
- '&.epr-tone-1f3fc': {
198
- backgroundColor: '#e9c197'
199
- },
200
- '&.epr-tone-1f3fd': {
201
- backgroundColor: '#c88e62'
202
- },
203
- '&.epr-tone-1f3fe': {
204
- backgroundColor: '#a86637'
205
- },
206
- '&.epr-tone-1f3ff': {
207
- backgroundColor: '#60463a'
208
- },
209
167
  }
210
168
  });
@@ -13,7 +13,10 @@ import { useKeyboardNavigation } from '../../hooks/useKeyboardNavigation';
13
13
  import { useOnFocus } from '../../hooks/useOnFocus';
14
14
  import { Theme } from '../../types/exposedTypes';
15
15
  import { usePickerMainRef } from '../context/ElementRefContext';
16
- import { PickerContextProvider } from '../context/PickerContext';
16
+ import {
17
+ PickerContextProvider,
18
+ useReactionsModeState
19
+ } from '../context/PickerContext';
17
20
 
18
21
  type Props = Readonly<{
19
22
  children: React.ReactNode;
@@ -35,6 +38,7 @@ type RootProps = Readonly<{
35
38
  }>;
36
39
 
37
40
  function PickerRootElement({ children }: RootProps) {
41
+ const [reactionsMode] = useReactionsModeState();
38
42
  const theme = useThemeConfig();
39
43
  const searchModeActive = useIsSearchMode();
40
44
  const PickerMainRef = usePickerMainRef();
@@ -44,6 +48,8 @@ function PickerRootElement({ children }: RootProps) {
44
48
  useKeyboardNavigation();
45
49
  useOnFocus();
46
50
 
51
+ const { width, height, ...styleProps } = style || {};
52
+
47
53
  return (
48
54
  <aside
49
55
  className={cx(
@@ -54,10 +60,14 @@ function PickerRootElement({ children }: RootProps) {
54
60
  {
55
61
  [ClassNames.searchActive]: searchModeActive
56
62
  },
63
+ reactionsMode && styles.reactionsMenu,
57
64
  className
58
65
  )}
59
66
  ref={PickerMainRef}
60
- style={style}
67
+ style={{
68
+ ...styleProps,
69
+ ...(!reactionsMode && { height, width })
70
+ }}
61
71
  >
62
72
  {children}
63
73
  </aside>
@@ -75,6 +85,7 @@ const DarkTheme = {
75
85
  '--epr-category-label-bg-color': 'var(--epr-dark-category-label-bg-color)',
76
86
  '--epr-picker-border-color': 'var(--epr-dark-picker-border-color)',
77
87
  '--epr-bg-color': 'var(--epr-dark-bg-color)',
88
+ '--epr-reactions-bg-color': 'var(--epr-dark-reactions-bg-color)',
78
89
  '--epr-search-input-bg-color-active':
79
90
  'var(--epr-dark-search-input-bg-color-active)',
80
91
  '--epr-emoji-variation-indicator-color':
@@ -97,6 +108,7 @@ const styles = stylesheet.create({
97
108
  borderColor: 'var(--epr-picker-border-color)',
98
109
  backgroundColor: 'var(--epr-bg-color)',
99
110
  overflow: 'hidden',
111
+ transition: 'all 0.3s ease-in-out, background-color 0.1s ease-in-out',
100
112
  // @ts-expect-error - need to work on this
101
113
  '*': {
102
114
  boxSizing: 'border-box',
@@ -112,6 +124,7 @@ const styles = stylesheet.create({
112
124
  '--epr-search-input-bg-color': '#f6f6f6',
113
125
  '--epr-picker-border-color': '#e7e7e7',
114
126
  '--epr-bg-color': '#fff',
127
+ '--epr-reactions-bg-color': '#ffffff90',
115
128
  '--epr-category-icon-active-color': '#6aa8de',
116
129
  '--epr-skin-tone-picker-menu-color': '#ffffff95',
117
130
 
@@ -187,6 +200,7 @@ const styles = stylesheet.create({
187
200
  '--epr-dark-category-label-bg-color': '#222222e6',
188
201
  '--epr-dark-picker-border-color': '#151617',
189
202
  '--epr-dark-bg-color': '#222222',
203
+ '--epr-dark-reactions-bg-color': '#22222290',
190
204
  '--epr-dark-search-input-bg-color-active': 'var(--epr-dark)',
191
205
  '--epr-dark-emoji-variation-indicator-color': '#444',
192
206
  '--epr-dark-category-icon-active-color': '#3271b7',
@@ -202,5 +216,16 @@ const styles = stylesheet.create({
202
216
  darkTheme: {
203
217
  '.': ClassNames.darkTheme,
204
218
  '--': DarkTheme
219
+ },
220
+ reactionsMenu: {
221
+ '.': 'epr-reactions',
222
+ height: '50px',
223
+ display: 'inline-flex',
224
+ backgroundColor: 'var(--epr-reactions-bg-color)',
225
+ // @ts-expect-error - need to work on this
226
+ backdropFilter: 'blur(8px)',
227
+ '--': {
228
+ '--epr-picker-border-radius': '50px'
229
+ }
205
230
  }
206
231
  });
@@ -0,0 +1,141 @@
1
+ import { cx } from 'flairup';
2
+ import * as React from 'react';
3
+
4
+ import { ClassNames } from '../../DomUtils/classNames';
5
+ import {
6
+ commonInteractionStyles,
7
+ stylesheet
8
+ } from '../../Stylesheet/stylesheet';
9
+ import {
10
+ CategoryConfig,
11
+ categoryNameFromCategoryConfig
12
+ } from '../../config/categoryConfig';
13
+ import { Button } from '../atoms/Button';
14
+
15
+ import SVGNavigation from './svg/CategoryNav.svg';
16
+
17
+ type Props = {
18
+ isActiveCategory: boolean;
19
+ category: string;
20
+ allowNavigation: boolean;
21
+ onClick: () => void;
22
+ categoryConfig: CategoryConfig;
23
+ };
24
+
25
+ export function CategoryButton({
26
+ isActiveCategory,
27
+ category,
28
+ allowNavigation,
29
+ categoryConfig,
30
+ onClick
31
+ }: Props) {
32
+ return (
33
+ <Button
34
+ tabIndex={allowNavigation ? 0 : -1}
35
+ className={cx(
36
+ styles.catBtn,
37
+ commonInteractionStyles.categoryBtn,
38
+ `epr-icn-${category}`,
39
+ {
40
+ [ClassNames.active]: isActiveCategory
41
+ }
42
+ )}
43
+ onClick={onClick}
44
+ aria-label={categoryNameFromCategoryConfig(categoryConfig)}
45
+ aria-selected={isActiveCategory}
46
+ role="tab"
47
+ aria-controls="epr-category-nav-id"
48
+ />
49
+ );
50
+ }
51
+
52
+ const DarkActivePositionY = {
53
+ backgroundPositionY: 'calc(var(--epr-category-navigation-button-size) * 3)'
54
+ };
55
+ const DarkPositionY = {
56
+ backgroundPositionY: 'calc(var(--epr-category-navigation-button-size) * 2)'
57
+ };
58
+
59
+ const DarkInactivePosition = {
60
+ ':not(.epr-search-active)': {
61
+ catBtn: {
62
+ ':hover': DarkActivePositionY,
63
+ '&.epr-active': DarkActivePositionY
64
+ }
65
+ }
66
+ };
67
+
68
+ const styles = stylesheet.create({
69
+ catBtn: {
70
+ '.': 'epr-cat-btn',
71
+ display: 'inline-block',
72
+ transition: 'opacity 0.2s ease-in-out',
73
+ position: 'relative',
74
+ height: 'var(--epr-category-navigation-button-size)',
75
+ width: 'var(--epr-category-navigation-button-size)',
76
+ backgroundSize: 'calc(var(--epr-category-navigation-button-size) * 10)',
77
+ outline: 'none',
78
+ backgroundPosition: '0 0',
79
+ backgroundImage: `url(${SVGNavigation})`,
80
+ ':focus:before': {
81
+ content: '',
82
+ position: 'absolute',
83
+ top: '-2px',
84
+ left: '-2px',
85
+ right: '-2px',
86
+ bottom: '-2px',
87
+ border: '2px solid var(--epr-category-icon-active-color)',
88
+ borderRadius: '50%'
89
+ },
90
+ // @ts-ignore
91
+ '&.epr-icn-suggested': {
92
+ backgroundPositionX:
93
+ 'calc(var(--epr-category-navigation-button-size) * -8)'
94
+ },
95
+ '&.epr-icn-custom': {
96
+ backgroundPositionX:
97
+ 'calc(var(--epr-category-navigation-button-size) * -9)'
98
+ },
99
+ '&.epr-icn-activities': {
100
+ backgroundPositionX:
101
+ 'calc(var(--epr-category-navigation-button-size) * -4)'
102
+ },
103
+ '&.epr-icn-animals_nature': {
104
+ backgroundPositionX:
105
+ 'calc(var(--epr-category-navigation-button-size) * -1)'
106
+ },
107
+ '&.epr-icn-flags': {
108
+ backgroundPositionX:
109
+ 'calc(var(--epr-category-navigation-button-size) * -7)'
110
+ },
111
+ '&.epr-icn-food_drink': {
112
+ backgroundPositionX:
113
+ 'calc(var(--epr-category-navigation-button-size) * -2)'
114
+ },
115
+ '&.epr-icn-objects': {
116
+ backgroundPositionX:
117
+ 'calc(var(--epr-category-navigation-button-size) * -5)'
118
+ },
119
+ '&.epr-icn-smileys_people': {
120
+ backgroundPositionX: '0px'
121
+ },
122
+ '&.epr-icn-symbols': {
123
+ backgroundPositionX:
124
+ 'calc(var(--epr-category-navigation-button-size) * -6)'
125
+ },
126
+ '&.epr-icn-travel_places': {
127
+ backgroundPositionX:
128
+ 'calc(var(--epr-category-navigation-button-size) * -3)'
129
+ }
130
+ },
131
+ '.epr-dark-theme': {
132
+ catBtn: DarkPositionY,
133
+ ...DarkInactivePosition
134
+ },
135
+ '.epr-auto-theme': {
136
+ catBtn: {
137
+ '@media (prefers-color-scheme: dark)': DarkPositionY
138
+ },
139
+ ...DarkInactivePosition
140
+ }
141
+ });