Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support showEmoji predicate #282

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version": "4.3.0",
"version": "4.4.0-rc.1",
"license": "MIT",
"main": "dist/index.js",
"typings": "dist/index.d.ts",
Expand Down
3 changes: 3 additions & 0 deletions src/config/config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { GetEmojiUrl } from '../components/emoji/Emoji';
import { DataEmoji } from '../dataUtils/DataTypes';
import { emojiUrlByUnified } from '../dataUtils/emojiSelectors';
import {
EmojiClickData,
Expand Down Expand Up @@ -58,6 +59,7 @@ export function basePickerConfig(): PickerConfigInternal {
...basePreviewConfig
},
searchPlaceHolder: 'Search',
showEmoji: undefined,
skinTonesDisabled: false,
suggestedEmojisMode: SuggestionMode.FREQUENT,
theme: Theme.LIGHT,
Expand All @@ -81,6 +83,7 @@ export type PickerConfigInternal = {
height: PickerDimensions;
width: PickerDimensions;
getEmojiUrl: GetEmojiUrl;
showEmoji: undefined | ((emoji: DataEmoji) => boolean);
};

export type PreviewConfig = {
Expand Down
8 changes: 8 additions & 0 deletions src/config/useConfig.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { isSystemDarkTheme } from '../DomUtils/isDarkTheme';
import { usePickerConfig } from '../components/context/PickerConfigContext';
import { DataEmoji } from '../dataUtils/DataTypes';
import {
EmojiClickData,
EmojiStyle,
Expand Down Expand Up @@ -95,6 +96,13 @@ export function useGetEmojiUrlConfig(): (
return getEmojiUrl;
}

export function useShowEmojiConfig():
| undefined
| ((emoji: DataEmoji) => boolean) {
const { showEmoji } = usePickerConfig();
return showEmoji;
}

function getDimension(dimensionConfig: PickerDimensions): PickerDimensions {
return typeof dimensionConfig === 'number'
? `${dimensionConfig}px`
Expand Down
21 changes: 17 additions & 4 deletions src/hooks/useDisallowedEmojis.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,41 @@
import { useRef, useMemo } from 'react';

import { useEmojiVersionConfig } from '../config/useConfig';
import { useEmojiVersionConfig, useShowEmojiConfig } from '../config/useConfig';
import { DataEmoji } from '../dataUtils/DataTypes';
import { addedIn, allEmojis, emojiUnified } from '../dataUtils/emojiSelectors';
import isFunction from '../predicates/isFunction';

export function useDisallowedEmojis() {
const DisallowedEmojisRef = useRef<Record<string, boolean>>({});
const emojiVersionConfig = useEmojiVersionConfig();
const shouldShowEmoji = useShowEmojiConfig();

return useMemo(() => {
const emojiVersion = parseFloat(`${emojiVersionConfig}`);

if (!emojiVersionConfig || Number.isNaN(emojiVersion)) {
if (
(!emojiVersionConfig || Number.isNaN(emojiVersion)) &&
!shouldShowEmoji
) {
return DisallowedEmojisRef.current;
}

return allEmojis.reduce((disallowedEmojis, emoji) => {
if (isFunction(shouldShowEmoji) && !shouldShowEmoji(emoji)) {
disallowEmoji();
}

if (addedInNewerVersion(emoji, emojiVersion)) {
disallowedEmojis[emojiUnified(emoji)] = true;
disallowEmoji();
}

return disallowedEmojis;

function disallowEmoji() {
disallowedEmojis[emojiUnified(emoji)] = true;
}
}, DisallowedEmojisRef.current);
}, [emojiVersionConfig]);
}, [emojiVersionConfig, shouldShowEmoji]);
}

function addedInNewerVersion(
Expand Down
19 changes: 10 additions & 9 deletions src/hooks/useFilter.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import { scrollTo } from '../DomUtils/scrollTo';
import {
usePickerMainRef,
useSearchInputRef,
useSearchInputRef
} from '../components/context/ElementRefContext';
import {
FilterState,
useFilterRef,
useSearchTermState,
useSearchTermState
} from '../components/context/PickerContext';
import { DataEmoji } from '../dataUtils/DataTypes';
import { emojiNames } from '../dataUtils/emojiSelectors';
import isFunction from '../predicates/isFunction';

import { useFocusSearchInput } from './useFocus';

Expand All @@ -19,7 +20,7 @@ function useSetFilterRef() {
return function setFilter(
setter: FilterState | ((current: FilterState) => FilterState)
): void {
if (typeof setter === 'function') {
if (isFunction(setter)) {
return setFilter(setter(filterRef.current));
}

Expand Down Expand Up @@ -67,7 +68,7 @@ export function useFilter() {
return {
onChange,
searchTerm,
SearchInputRef,
SearchInputRef
};

function onChange(inputValue: string) {
Expand All @@ -87,9 +88,9 @@ export function useFilter() {
return applySearch(nextValue);
}

setFilterRef((current) =>
setFilterRef(current =>
Object.assign(current, {
[nextValue]: filterEmojiObjectByKeyword(longestMatch, nextValue),
[nextValue]: filterEmojiObjectByKeyword(longestMatch, nextValue)
})
);
applySearch(nextValue);
Expand Down Expand Up @@ -129,14 +130,14 @@ function filterEmojiObjectByKeyword(
}

function hasMatch(emoji: DataEmoji, keyword: string): boolean {
return emojiNames(emoji).some((name) => name.includes(keyword));
return emojiNames(emoji).some(name => name.includes(keyword));
}

export function useIsEmojiFiltered(): (unified: string) => boolean {
const { current: filter } = useFilterRef();
const [searchTerm] = useSearchTermState();

return (unified) => isEmojiFilteredBySearchTerm(unified, filter, searchTerm);
return unified => isEmojiFilteredBySearchTerm(unified, filter, searchTerm);
}

function isEmojiFilteredBySearchTerm(
Expand Down Expand Up @@ -167,7 +168,7 @@ function findLongestMatch(

const longestMatchingKey = Object.keys(dict)
.sort((a, b) => b.length - a.length)
.find((key) => keyword.includes(key));
.find(key => keyword.includes(key));

if (longestMatchingKey) {
return dict[longestMatchingKey];
Expand Down
5 changes: 5 additions & 0 deletions src/predicates/isFunction.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export default function isFunction(
value: any
): value is (...args: any[]) => any {
return typeof value === 'function';
}
8 changes: 8 additions & 0 deletions stories/picker.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import EmojiPicker, {
Theme
} from '../src';
import { Categories } from '../src/config/categoryConfig';
import { DataEmoji } from '../src/dataUtils/DataTypes';
import { SuggestionMode } from '../src/types/exposedTypes';

const meta: Meta = {
Expand Down Expand Up @@ -77,6 +78,13 @@ export const CustomSearchPlaceholder = (args: Props) => (
export const SkinTonesDisabled = (args: Props) => (
<Template {...args} skinTonesDisabled />
);

export const ShowEmoji = (args: Props) => (
<Template
{...args}
showEmoji={(emoji: DataEmoji) => emoji.n.join('').includes('clown')}
/>
);
export const AlternativeDefaultSkinTone = (args: Props) => (
<Template {...args} defaultSkinTone={SkinTones.MEDIUM} />
);
Expand Down