emoji-picker-react 4.6.0 → 4.6.1-rc.2

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/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "4.6.0",
2
+ "version": "4.6.1-rc.2",
3
3
  "license": "MIT",
4
4
  "main": "dist/index.js",
5
5
  "typings": "dist/index.d.ts",
@@ -96,5 +96,8 @@
96
96
  "tsdx": "^0.14.1",
97
97
  "tslib": "^2.4.0",
98
98
  "typescript": "^4.7.4"
99
+ },
100
+ "dependencies": {
101
+ "flairup": "0.0.4"
99
102
  }
100
103
  }
@@ -24,27 +24,3 @@ export enum ClassNames {
24
24
  export function asSelectors(...classNames: ClassNames[]): string {
25
25
  return classNames.map(c => `.${c}`).join('');
26
26
  }
27
-
28
- export function clsx(...args: any[]): string {
29
- const classes = args.reduce((classes, arg) => {
30
- if (typeof arg === 'string') {
31
- classes.push(arg);
32
- }
33
-
34
- if (Array.isArray(arg)) {
35
- classes.push(clsx(...arg));
36
- }
37
-
38
- if (typeof arg === 'object') {
39
- Object.entries(arg).forEach(([key, value]) => {
40
- if (value) {
41
- classes.push(key);
42
- }
43
- });
44
- }
45
-
46
- return classes;
47
- }, []);
48
-
49
- return classes.filter(Boolean).join(' ');
50
- }
@@ -0,0 +1,3 @@
1
+ import { createSheet } from 'flairup';
2
+
3
+ export const stylesheet = createSheet('epr');
@@ -1,7 +1,7 @@
1
+ import { cx } from 'flairup';
1
2
  import * as React from 'react';
2
3
 
3
4
  import './Flex.css';
4
- import { clsx } from '../../DomUtils/classNames';
5
5
 
6
6
  export enum FlexDirection {
7
7
  ROW = 'FlexRow',
@@ -22,7 +22,7 @@ export default function Flex({
22
22
  direction = FlexDirection.ROW
23
23
  }: Props) {
24
24
  return (
25
- <div style={{ ...style }} className={clsx('Flex', className, direction)}>
25
+ <div style={{ ...style }} className={cx('Flex', className, direction)}>
26
26
  {children}
27
27
  </div>
28
28
  );
@@ -1,6 +1,6 @@
1
+ import { cx } from 'flairup';
1
2
  import * as React from 'react';
2
3
 
3
- import { clsx } from '../../DomUtils/classNames';
4
4
 
5
5
  type Props = Readonly<{
6
6
  className?: string;
@@ -8,5 +8,5 @@ type Props = Readonly<{
8
8
  }>;
9
9
 
10
10
  export default function Space({ className, style = {} }: Props) {
11
- return <div style={{ flex: 1, ...style }} className={clsx(className)} />;
11
+ return <div style={{ flex: 1, ...style }} className={cx(className)} />;
12
12
  }
@@ -1,7 +1,6 @@
1
+ import { cx } from 'flairup';
1
2
  import * as React from 'react';
2
3
 
3
- import { clsx } from '../../DomUtils/classNames';
4
-
5
4
  interface Props
6
5
  extends React.DetailedHTMLProps<
7
6
  React.ButtonHTMLAttributes<HTMLButtonElement>,
@@ -12,11 +11,7 @@ interface Props
12
11
 
13
12
  export function Button(props: Props) {
14
13
  return (
15
- <button
16
- type="button"
17
- {...props}
18
- className={clsx('epr-btn', props.className)}
19
- >
14
+ <button type="button" {...props} className={cx('epr-btn', props.className)}>
20
15
  {props.children}
21
16
  </button>
22
17
  );
@@ -1,6 +1,8 @@
1
+ import { cx } from 'flairup';
1
2
  import * as React from 'react';
2
3
 
3
4
  import { ClassNames } from '../../DomUtils/classNames';
5
+ import { stylesheet } from '../../Stylesheet/stylesheet';
4
6
  import { useOnMouseMove } from '../../hooks/useDisallowMouseMove';
5
7
  import { useMouseDownHandlers } from '../../hooks/useMouseDownHandlers';
6
8
  import { useOnScroll } from '../../hooks/useOnScroll';
@@ -9,8 +11,6 @@ import { useBodyRef } from '../context/ElementRefContext';
9
11
  import { EmojiList } from './EmojiList';
10
12
  import { EmojiVariationPicker } from './EmojiVariationPicker';
11
13
 
12
- import './Body.css';
13
-
14
14
  export function Body() {
15
15
  const BodyRef = useBodyRef();
16
16
  useOnScroll(BodyRef);
@@ -18,9 +18,19 @@ export function Body() {
18
18
  useOnMouseMove();
19
19
 
20
20
  return (
21
- <div className={ClassNames.scrollBody} ref={BodyRef}>
21
+ <div className={cx(styles.body)} ref={BodyRef}>
22
22
  <EmojiVariationPicker />
23
23
  <EmojiList />
24
24
  </div>
25
25
  );
26
26
  }
27
+
28
+ const styles = stylesheet.create({
29
+ body: {
30
+ '.': ClassNames.scrollBody,
31
+ flex: 1,
32
+ overflowY: 'scroll',
33
+ overflowX: 'hidden',
34
+ position: 'relative'
35
+ }
36
+ });
@@ -1,11 +1,13 @@
1
+ import { cx } from 'flairup';
1
2
  import * as React from 'react';
2
3
 
3
- import { ClassNames, clsx } from '../../DomUtils/classNames';
4
+ import { ClassNames } from '../../DomUtils/classNames';
4
5
  import {
5
6
  CategoryConfig,
6
7
  categoryFromCategoryConfig,
7
8
  categoryNameFromCategoryConfig
8
9
  } from '../../config/categoryConfig';
10
+
9
11
  import './EmojiCategory.css';
10
12
 
11
13
  type Props = Readonly<{
@@ -26,7 +28,7 @@ export function EmojiCategory({
26
28
 
27
29
  return (
28
30
  <li
29
- className={clsx(ClassNames.category, {
31
+ className={cx(ClassNames.category, {
30
32
  [ClassNames.hidden]: hidden,
31
33
  [ClassNames.hiddenOnSearch]: hiddenOnSearch
32
34
  })}
@@ -1,7 +1,8 @@
1
+ import { cx } from 'flairup';
1
2
  import * as React from 'react';
2
3
  import { useEffect } from 'react';
3
4
 
4
- import { ClassNames, clsx } from '../../DomUtils/classNames';
5
+ import { ClassNames } from '../../DomUtils/classNames';
5
6
  import { focusFirstVisibleEmoji } from '../../DomUtils/keyboardNavigation';
6
7
  import {
7
8
  buttonFromTarget,
@@ -26,6 +27,7 @@ import {
26
27
  } from '../context/ElementRefContext';
27
28
  import { useEmojiVariationPickerState } from '../context/PickerContext';
28
29
  import { ClickableEmoji } from '../emoji/Emoji';
30
+
29
31
  import './EmojiVariationPicker.css';
30
32
 
31
33
  enum Direction {
@@ -74,7 +76,7 @@ export function EmojiVariationPicker() {
74
76
  return (
75
77
  <div
76
78
  ref={VariationPickerRef}
77
- className={clsx(ClassNames.variationPicker, {
79
+ className={cx(ClassNames.variationPicker, {
78
80
  visible,
79
81
  'pointing-up': getMenuDirection() === Direction.Down
80
82
  })}
@@ -1,7 +1,9 @@
1
+ import { cx } from 'flairup';
1
2
  import * as React from 'react';
2
3
 
3
- import { ClassNames, clsx } from '../../DomUtils/classNames';
4
+ import { ClassNames } from '../../DomUtils/classNames';
4
5
  import { Button } from '../atoms/Button';
6
+
5
7
  import './Emoji.css';
6
8
 
7
9
  type ClickableEmojiButtonProps = Readonly<{
@@ -25,7 +27,7 @@ export function ClickableEmojiButton({
25
27
  }: ClickableEmojiButtonProps) {
26
28
  return (
27
29
  <Button
28
- className={clsx(ClassNames.emoji, {
30
+ className={cx(ClassNames.emoji, {
29
31
  [ClassNames.hidden]: hidden,
30
32
  [ClassNames.hiddenOnSearch]: hiddenOnSearch,
31
33
  [ClassNames.visible]: !hidden && !hiddenOnSearch,
@@ -1,6 +1,7 @@
1
+ import { cx } from 'flairup';
1
2
  import * as React from 'react';
2
3
 
3
- import { ClassNames, clsx } from '../../DomUtils/classNames';
4
+ import { ClassNames } from '../../DomUtils/classNames';
4
5
  import { EmojiStyle } from '../../types/exposedTypes';
5
6
 
6
7
  export function EmojiImg({
@@ -21,7 +22,7 @@ export function EmojiImg({
21
22
  <img
22
23
  src={imgUrl}
23
24
  alt={emojiName}
24
- className={clsx(ClassNames.external, 'epr-emoji-img')}
25
+ className={cx(ClassNames.external, 'epr-emoji-img')}
25
26
  loading={lazyLoad ? 'lazy' : 'eager'}
26
27
  onError={onError}
27
28
  style={style}
@@ -1,6 +1,7 @@
1
+ import { cx } from 'flairup';
1
2
  import * as React from 'react';
2
3
 
3
- import { ClassNames, clsx } from '../../DomUtils/classNames';
4
+ import { ClassNames } from '../../DomUtils/classNames';
4
5
  import { parseNativeEmoji } from '../../dataUtils/parseNativeEmoji';
5
6
 
6
7
  export function NativeEmoji({
@@ -12,7 +13,7 @@ export function NativeEmoji({
12
13
  }) {
13
14
  return (
14
15
  <span
15
- className={clsx(ClassNames.external, 'epr-emoji-native')}
16
+ className={cx(ClassNames.external, 'epr-emoji-native')}
16
17
  data-unified={unified}
17
18
  style={style}
18
19
  >
@@ -1,7 +1,7 @@
1
+ import { cx } from 'flairup';
1
2
  import * as React from 'react';
2
3
  import { useState } from 'react';
3
4
 
4
- import { clsx } from '../../DomUtils/classNames';
5
5
  import {
6
6
  useAutoFocusSearchConfig,
7
7
  useSearchDisabledConfig,
@@ -72,7 +72,7 @@ export function Search() {
72
72
  {searchTerm ? (
73
73
  <div
74
74
  role="status"
75
- className={clsx(
75
+ className={cx(
76
76
  'epr-status-search-results',
77
77
  'epr-status-visually-hidden'
78
78
  )}
@@ -85,8 +85,10 @@ export function Search() {
85
85
  ) : null}
86
86
  <div className="epr-icn-search" />
87
87
  <Button
88
- className={clsx('epr-btn-clear-search', 'epr-visible-on-search-only')}
88
+ className={cx('epr-btn-clear-search', 'epr-visible-on-search-only')}
89
89
  onClick={clearSearch}
90
+ aria-label="Clear"
91
+ title="Clear"
90
92
  >
91
93
  <div className="epr-icn-clear-search" />
92
94
  </Button>
@@ -1,6 +1,6 @@
1
1
  import * as React from 'react';
2
2
 
3
- import { ClassNames, clsx } from '../../DomUtils/classNames';
3
+ import { ClassNames } from '../../DomUtils/classNames';
4
4
  import { useSkinTonesDisabledConfig } from '../../config/useConfig';
5
5
  import skinToneVariations, {
6
6
  skinTonesNamed
@@ -16,7 +16,9 @@ import {
16
16
  useActiveSkinToneState,
17
17
  useSkinToneFanOpenState
18
18
  } from '../context/PickerContext';
19
+
19
20
  import './SkinTonePicker.css';
21
+ import { cx } from 'flairup';
20
22
 
21
23
  const ITEM_SIZE = 28;
22
24
 
@@ -56,7 +58,7 @@ export function SkinTonePicker({
56
58
 
57
59
  return (
58
60
  <Relative
59
- className={clsx('epr-skin-tones', direction, {
61
+ className={cx('epr-skin-tones', direction, {
60
62
  [ClassNames.open]: isOpen
61
63
  })}
62
64
  style={
@@ -71,7 +73,7 @@ export function SkinTonePicker({
71
73
  return (
72
74
  <Button
73
75
  style={{
74
- transform: clsx(
76
+ transform: cx(
75
77
  vertical
76
78
  ? `translateY(-${i * (isOpen ? ITEM_SIZE : 0)}px)`
77
79
  : `translateX(-${i * (isOpen ? ITEM_SIZE : 0)}px)`,
@@ -88,7 +90,7 @@ export function SkinTonePicker({
88
90
  closeAllOpenToggles();
89
91
  }}
90
92
  key={skinToneVariation}
91
- className={clsx(`epr-tone-${skinToneVariation}`, 'epr-tone', {
93
+ className={cx(`epr-tone-${skinToneVariation}`, 'epr-tone', {
92
94
  [ClassNames.active]: active
93
95
  })}
94
96
  tabIndex={isOpen ? 0 : -1}
@@ -1,13 +1,19 @@
1
+ import { cx } from 'flairup';
1
2
  import * as React from 'react';
2
3
 
3
- import { ClassNames, clsx } from '../../DomUtils/classNames';
4
- import { useClassNameConfig, useStyleConfig, useThemeConfig } from '../../config/useConfig';
4
+ import { ClassNames } from '../../DomUtils/classNames';
5
+ import {
6
+ useClassNameConfig,
7
+ useStyleConfig,
8
+ useThemeConfig
9
+ } from '../../config/useConfig';
5
10
  import useIsSearchMode from '../../hooks/useIsSearchMode';
6
11
  import { useKeyboardNavigation } from '../../hooks/useKeyboardNavigation';
7
12
  import { useOnFocus } from '../../hooks/useOnFocus';
8
13
  import { Theme } from '../../types/exposedTypes';
9
14
  import { usePickerMainRef } from '../context/ElementRefContext';
10
15
  import { PickerContextProvider } from '../context/PickerContext';
16
+
11
17
  import './PickerMain.css';
12
18
 
13
19
  type Props = Readonly<{
@@ -40,11 +46,16 @@ function PickerRootElement({ children }: RootProps) {
40
46
 
41
47
  return (
42
48
  <aside
43
- className={clsx(ClassNames.emojiPicker, 'epr-main', {
44
- [ClassNames.searchActive]: searchModeActive,
45
- [ClassNames.darkTheme]: theme === Theme.DARK,
46
- [ClassNames.autoTheme]: theme === Theme.AUTO
47
- }, className)}
49
+ className={cx(
50
+ ClassNames.emojiPicker,
51
+ 'epr-main',
52
+ {
53
+ [ClassNames.searchActive]: searchModeActive,
54
+ [ClassNames.darkTheme]: theme === Theme.DARK,
55
+ [ClassNames.autoTheme]: theme === Theme.AUTO
56
+ },
57
+ className
58
+ )}
48
59
  ref={PickerMainRef}
49
60
  style={style}
50
61
  >
@@ -1,8 +1,9 @@
1
+ import { cx } from 'flairup';
1
2
  import * as React from 'react';
2
3
  import { useState } from 'react';
3
4
  import './CategoryNavigation.css';
4
5
 
5
- import { ClassNames, clsx } from '../../DomUtils/classNames';
6
+ import { ClassNames } from '../../DomUtils/classNames';
6
7
  import {
7
8
  categoryFromCategoryConfig,
8
9
  categoryNameFromCategoryConfig
@@ -27,13 +28,13 @@ export function CategoryNavigation() {
27
28
  const hideCustomCategory = useShouldHideCustomEmojis();
28
29
 
29
30
  return (
30
- <div
31
- className='epr-category-nav'
32
- role='tablist'
33
- aria-label='Category navigation'
34
- id='epr-category-nav-id'
35
- ref={CategoryNavigationRef}
36
- >
31
+ <div
32
+ className="epr-category-nav"
33
+ role="tablist"
34
+ aria-label="Category navigation"
35
+ id="epr-category-nav-id"
36
+ ref={CategoryNavigationRef}
37
+ >
37
38
  {categoriesConfig.map(categoryConfig => {
38
39
  const category = categoryFromCategoryConfig(categoryConfig);
39
40
  const isActiveCategory = category === activeCategory;
@@ -44,8 +45,8 @@ export function CategoryNavigation() {
44
45
 
45
46
  return (
46
47
  <Button
47
- tabIndex={(isSearchMode || isActiveCategory) ? -1 : 0}
48
- className={clsx('epr-cat-btn', `epr-icn-${category}`, {
48
+ tabIndex={isSearchMode || isActiveCategory ? -1 : 0}
49
+ className={cx('epr-cat-btn', `epr-icn-${category}`, {
49
50
  [ClassNames.active]: isActiveCategory
50
51
  })}
51
52
  key={category}
@@ -55,8 +56,8 @@ export function CategoryNavigation() {
55
56
  }}
56
57
  aria-label={categoryNameFromCategoryConfig(categoryConfig)}
57
58
  aria-selected={isActiveCategory}
58
- role='tab'
59
- aria-controls='epr-category-nav-id'
59
+ role="tab"
60
+ aria-controls="epr-category-nav-id"
60
61
  />
61
62
  );
62
63
  })}
@@ -1,18 +1,18 @@
1
1
  import { scrollTo } from '../DomUtils/scrollTo';
2
2
  import {
3
3
  usePickerMainRef,
4
- useSearchInputRef,
4
+ useSearchInputRef
5
5
  } from '../components/context/ElementRefContext';
6
6
  import {
7
7
  FilterState,
8
8
  useFilterRef,
9
- useSearchTermState,
9
+ useSearchTermState
10
10
  } from '../components/context/PickerContext';
11
+ import { useSearchResultsConfig } from '../config/useConfig';
11
12
  import { DataEmoji } from '../dataUtils/DataTypes';
12
13
  import { emojiNames } from '../dataUtils/emojiSelectors';
13
14
 
14
15
  import { useFocusSearchInput } from './useFocus';
15
- import { useSearchResultsConfig } from '../config/useConfig';
16
16
 
17
17
  function useSetFilterRef() {
18
18
  const filterRef = useFilterRef();
@@ -64,13 +64,16 @@ export function useFilter() {
64
64
  const applySearch = useApplySearch();
65
65
 
66
66
  const [searchTerm] = useSearchTermState();
67
- const statusSearchResults = getStatusSearchResults(filterRef.current, searchTerm);
67
+ const statusSearchResults = getStatusSearchResults(
68
+ filterRef.current,
69
+ searchTerm
70
+ );
68
71
 
69
72
  return {
70
73
  onChange,
71
74
  searchTerm,
72
75
  SearchInputRef,
73
- statusSearchResults,
76
+ statusSearchResults
74
77
  };
75
78
 
76
79
  function onChange(inputValue: string) {
@@ -90,9 +93,9 @@ export function useFilter() {
90
93
  return applySearch(nextValue);
91
94
  }
92
95
 
93
- setFilterRef((current) =>
96
+ setFilterRef(current =>
94
97
  Object.assign(current, {
95
- [nextValue]: filterEmojiObjectByKeyword(longestMatch, nextValue),
98
+ [nextValue]: filterEmojiObjectByKeyword(longestMatch, nextValue)
96
99
  })
97
100
  );
98
101
  applySearch(nextValue);
@@ -132,14 +135,14 @@ function filterEmojiObjectByKeyword(
132
135
  }
133
136
 
134
137
  function hasMatch(emoji: DataEmoji, keyword: string): boolean {
135
- return emojiNames(emoji).some((name) => name.includes(keyword));
138
+ return emojiNames(emoji).some(name => name.includes(keyword));
136
139
  }
137
140
 
138
141
  export function useIsEmojiFiltered(): (unified: string) => boolean {
139
142
  const { current: filter } = useFilterRef();
140
143
  const [searchTerm] = useSearchTermState();
141
144
 
142
- return (unified) => isEmojiFilteredBySearchTerm(unified, filter, searchTerm);
145
+ return unified => isEmojiFilteredBySearchTerm(unified, filter, searchTerm);
143
146
  }
144
147
 
145
148
  function isEmojiFilteredBySearchTerm(
@@ -170,7 +173,7 @@ function findLongestMatch(
170
173
 
171
174
  const longestMatchingKey = Object.keys(dict)
172
175
  .sort((a, b) => b.length - a.length)
173
- .find((key) => keyword.includes(key));
176
+ .find(key => keyword.includes(key));
174
177
 
175
178
  if (longestMatchingKey) {
176
179
  return dict[longestMatchingKey];
@@ -187,9 +190,14 @@ export function getNormalizedSearchTerm(str: string): string {
187
190
  return str.trim().toLowerCase();
188
191
  }
189
192
 
190
- function getStatusSearchResults(filterState: FilterState, searchTerm: string): string {
193
+ function getStatusSearchResults(
194
+ filterState: FilterState,
195
+ searchTerm: string
196
+ ): string {
191
197
  if (!filterState?.[searchTerm]) return '';
192
198
 
193
- const searchResultsCount = Object.entries(filterState?.[searchTerm])?.length || 0;
199
+ const searchResultsCount =
200
+ Object.entries(filterState?.[searchTerm])?.length || 0;
201
+ // eslint-disable-next-line react-hooks/rules-of-hooks
194
202
  return useSearchResultsConfig(searchResultsCount);
195
203
  }
@@ -24,6 +24,7 @@ import {
24
24
  useSkinTonePickerRef
25
25
  } from '../components/context/ElementRefContext';
26
26
  import { useSkinToneFanOpenState } from '../components/context/PickerContext';
27
+ import { useSearchDisabledConfig } from '../config/useConfig';
27
28
 
28
29
  import {
29
30
  useCloseAllOpenToggles,
@@ -42,7 +43,6 @@ import {
42
43
  useIsSkinToneInPreview,
43
44
  useIsSkinToneInSearch
44
45
  } from './useShouldShowSkinTonePicker';
45
- import { useSearchDisabledConfig } from '../config/useConfig';
46
46
 
47
47
  enum KeyboardEvents {
48
48
  ArrowDown = 'ArrowDown',
@@ -1,6 +0,0 @@
1
- .EmojiPickerReact .epr-body {
2
- position: relative;
3
- flex: 1;
4
- overflow-y: scroll;
5
- overflow-x: hidden;
6
- }