emoji-picker-react 4.21.1 → 4.22.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/components/context/PickerDataContext.d.ts +2 -1
- package/dist/config/categoryConfig.d.ts +19 -1
- package/dist/config/customEmojiConfig.d.ts +8 -0
- package/dist/emoji-picker-react.cjs.development.js +132 -28
- package/dist/emoji-picker-react.cjs.development.js.map +1 -1
- package/dist/emoji-picker-react.cjs.production.min.js +1 -1
- package/dist/emoji-picker-react.cjs.production.min.js.map +1 -1
- package/dist/emoji-picker-react.esm.js +132 -28
- package/dist/emoji-picker-react.esm.js.map +1 -1
- package/dist/types/exposedTypes.d.ts +6 -0
- package/llms.txt +31 -1
- package/package.json +1 -1
- package/src/components/body/EmojiCategory.tsx +2 -3
- package/src/components/body/EmojiList.tsx +16 -7
- package/src/components/body/MeasureEmoji.tsx +10 -4
- package/src/components/context/PickerDataContext.tsx +28 -5
- package/src/components/navigation/CategoryNavigation.tsx +26 -9
- package/src/config/categoryConfig.ts +97 -5
- package/src/config/config.ts +1 -0
- package/src/config/customEmojiConfig.ts +8 -0
- package/src/hooks/useScrollCategoryIntoView.ts +2 -1
- package/src/types/exposedTypes.ts +6 -0
|
@@ -321,6 +321,34 @@ var SuggestedRecent = {
|
|
|
321
321
|
name: 'Recently Used',
|
|
322
322
|
category: Categories.SUGGESTED
|
|
323
323
|
};
|
|
324
|
+
/**
|
|
325
|
+
* Stable identity for a category entry. Custom groups are namespaced so
|
|
326
|
+
* duplicate `{ category: CUSTOM }` configs no longer collide in React
|
|
327
|
+
* keys, scroll targets, and active-tab detection.
|
|
328
|
+
*/
|
|
329
|
+
function categoryIdFromCategoryConfig(categoryConfig) {
|
|
330
|
+
var category = categoryFromCategoryConfig(categoryConfig);
|
|
331
|
+
if (isCustomGroupConfig(categoryConfig)) {
|
|
332
|
+
return category + ":" + categoryConfig.group;
|
|
333
|
+
}
|
|
334
|
+
return category;
|
|
335
|
+
}
|
|
336
|
+
function isCustomGroupConfig(categoryConfig) {
|
|
337
|
+
if (categoryConfig.category !== Categories.CUSTOM) {
|
|
338
|
+
return false;
|
|
339
|
+
}
|
|
340
|
+
var group = categoryConfig.group;
|
|
341
|
+
return typeof group === 'string' && group.length > 0;
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* The `CustomEmoji` group rendered by a category entry, if any.
|
|
345
|
+
*/
|
|
346
|
+
function customGroupFromCategoryConfig(categoryConfig) {
|
|
347
|
+
if (isCustomGroupConfig(categoryConfig)) {
|
|
348
|
+
return categoryConfig.group;
|
|
349
|
+
}
|
|
350
|
+
return undefined;
|
|
351
|
+
}
|
|
324
352
|
var configByCategory = (_configByCategory = {}, _configByCategory[Categories.SUGGESTED] = {
|
|
325
353
|
category: Categories.SUGGESTED,
|
|
326
354
|
name: 'Frequently Used'
|
|
@@ -363,14 +391,17 @@ function categoryFromCategoryConfig(category) {
|
|
|
363
391
|
function categoryNameFromCategoryConfig(category) {
|
|
364
392
|
return category.name;
|
|
365
393
|
}
|
|
366
|
-
function mergeCategoriesConfig(userCategoriesConfig, modifiers, emojiData) {
|
|
367
|
-
var _userCategoriesConfig;
|
|
394
|
+
function mergeCategoriesConfig(userCategoriesConfig, modifiers, emojiData, customEmojis) {
|
|
395
|
+
var _userCategoriesConfig, _userCategoriesConfig2;
|
|
368
396
|
if (userCategoriesConfig === void 0) {
|
|
369
397
|
userCategoriesConfig = [];
|
|
370
398
|
}
|
|
371
399
|
if (modifiers === void 0) {
|
|
372
400
|
modifiers = {};
|
|
373
401
|
}
|
|
402
|
+
if (customEmojis === void 0) {
|
|
403
|
+
customEmojis = [];
|
|
404
|
+
}
|
|
374
405
|
var extra = function () {
|
|
375
406
|
// 1. Start with localized categories from emojiData
|
|
376
407
|
var fromData = emojiData != null && emojiData.categories ? Object.fromEntries(Object.entries(emojiData.categories).filter(function (_ref) {
|
|
@@ -389,15 +420,50 @@ function mergeCategoriesConfig(userCategoriesConfig, modifiers, emojiData) {
|
|
|
389
420
|
return fromData;
|
|
390
421
|
}();
|
|
391
422
|
var base = baseCategoriesConfig(extra);
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
423
|
+
var explicit = (_userCategoriesConfig = userCategoriesConfig) != null && _userCategoriesConfig.length ? userCategoriesConfig.map(mapUserEntry) : base;
|
|
424
|
+
// Groups without a `categories` entry get an appended section so their
|
|
425
|
+
// emojis always render somewhere — unless the user opted out of customs
|
|
426
|
+
// entirely by listing `categories` without CUSTOM. `categories` remains
|
|
427
|
+
// the override for order, display name, and icon.
|
|
428
|
+
// https://github.com/ealush/emoji-picker-react/issues/510
|
|
429
|
+
var customInPlay = !((_userCategoriesConfig2 = userCategoriesConfig) != null && _userCategoriesConfig2.length) || userCategoriesConfig.some(function (entry) {
|
|
430
|
+
return entry === Categories.CUSTOM || typeof entry !== 'string' && entry.category === Categories.CUSTOM;
|
|
431
|
+
});
|
|
432
|
+
var listedGroups = new Set(explicit.map(function (entry) {
|
|
433
|
+
return customGroupFromCategoryConfig(entry);
|
|
434
|
+
}).filter(function (group) {
|
|
435
|
+
return !!group;
|
|
436
|
+
}));
|
|
437
|
+
var appended = !customInPlay ? [] : Array.from(new Set(customEmojis.map(function (emoji) {
|
|
438
|
+
return emoji.group;
|
|
439
|
+
}).filter(function (group) {
|
|
440
|
+
return !!group;
|
|
441
|
+
}))).filter(function (group) {
|
|
442
|
+
return !listedGroups.has(group);
|
|
443
|
+
}).map(function (group) {
|
|
444
|
+
return {
|
|
445
|
+
category: Categories.CUSTOM,
|
|
446
|
+
name: group,
|
|
447
|
+
group: group
|
|
448
|
+
};
|
|
449
|
+
});
|
|
450
|
+
// Collapse duplicate entries (same identity twice renders the same
|
|
451
|
+
// section twice under one React key); first occurrence wins.
|
|
452
|
+
var seen = new Set();
|
|
453
|
+
return explicit.concat(appended).filter(function (entry) {
|
|
454
|
+
var id = categoryIdFromCategoryConfig(entry);
|
|
455
|
+
if (seen.has(id)) {
|
|
456
|
+
return false;
|
|
457
|
+
}
|
|
458
|
+
seen.add(id);
|
|
459
|
+
return true;
|
|
460
|
+
});
|
|
461
|
+
function mapUserEntry(category) {
|
|
396
462
|
if (typeof category === 'string') {
|
|
397
463
|
return getBaseConfigByCategory(category, extra[category]);
|
|
398
464
|
}
|
|
399
465
|
return _extends({}, getBaseConfigByCategory(category.category, extra[category.category]), category);
|
|
400
|
-
}
|
|
466
|
+
}
|
|
401
467
|
}
|
|
402
468
|
function getBaseConfigByCategory(category, modifier) {
|
|
403
469
|
if (modifier === void 0) {
|
|
@@ -428,7 +494,7 @@ function mergeConfig(userConfig) {
|
|
|
428
494
|
var config = Object.assign(base, userConfig);
|
|
429
495
|
var categories = mergeCategoriesConfig(userConfig.categories, {
|
|
430
496
|
suggestionMode: config.suggestedEmojisMode
|
|
431
|
-
}, userConfig.emojiData);
|
|
497
|
+
}, userConfig.emojiData, userConfig.customEmojis);
|
|
432
498
|
config.hiddenEmojis.forEach(function (emoji) {
|
|
433
499
|
config.unicodeToHide.add(emoji);
|
|
434
500
|
});
|
|
@@ -26862,6 +26928,7 @@ var PickerDataContext = /*#__PURE__*/React__default.createContext({
|
|
|
26862
26928
|
allEmojis: [],
|
|
26863
26929
|
allEmojisByUnified: {},
|
|
26864
26930
|
searchIndex: {},
|
|
26931
|
+
customGroups: {},
|
|
26865
26932
|
emojiByUnified: emojiByUnified,
|
|
26866
26933
|
activeVariationFromUnified: function activeVariationFromUnified() {
|
|
26867
26934
|
return null;
|
|
@@ -26876,11 +26943,23 @@ function PickerDataProvider(_ref) {
|
|
|
26876
26943
|
var emojiData = genericEmojiData || defaultEmojiData;
|
|
26877
26944
|
// Clone to avoid mutation of shared source
|
|
26878
26945
|
var newData = JSON.parse(JSON.stringify(emojiData));
|
|
26946
|
+
var customGroups = {};
|
|
26879
26947
|
if (customEmojis && customEmojis.length > 0) {
|
|
26880
|
-
|
|
26948
|
+
for (var _iterator = _createForOfIteratorHelperLoose(customEmojis), _step; !(_step = _iterator()).done;) {
|
|
26949
|
+
var _customGroups$emoji$g;
|
|
26950
|
+
var emoji = _step.value;
|
|
26951
|
+
if (!emoji.group) {
|
|
26952
|
+
continue;
|
|
26953
|
+
}
|
|
26954
|
+
customGroups[emoji.group] = (_customGroups$emoji$g = customGroups[emoji.group]) != null ? _customGroups$emoji$g : [];
|
|
26955
|
+
customGroups[emoji.group].push(customToRegularEmoji(emoji));
|
|
26956
|
+
}
|
|
26957
|
+
newData.emojis[Categories.CUSTOM] = customEmojis.filter(function (emoji) {
|
|
26958
|
+
return !emoji.group;
|
|
26959
|
+
}).map(customToRegularEmoji);
|
|
26881
26960
|
}
|
|
26882
26961
|
var emojis = newData.emojis || {};
|
|
26883
|
-
var allEmojis = Object.values(emojis).flat();
|
|
26962
|
+
var allEmojis = Object.values(emojis).concat(Object.values(customGroups)).flat();
|
|
26884
26963
|
var allEmojisByUnified = {};
|
|
26885
26964
|
var searchIndex = {};
|
|
26886
26965
|
allEmojis.forEach(function (emoji) {
|
|
@@ -26905,7 +26984,8 @@ function PickerDataProvider(_ref) {
|
|
|
26905
26984
|
emojiData: newData,
|
|
26906
26985
|
allEmojis: allEmojis,
|
|
26907
26986
|
allEmojisByUnified: allEmojisByUnified,
|
|
26908
|
-
searchIndex: searchIndex
|
|
26987
|
+
searchIndex: searchIndex,
|
|
26988
|
+
customGroups: customGroups
|
|
26909
26989
|
};
|
|
26910
26990
|
}, [genericEmojiData, customEmojis]);
|
|
26911
26991
|
var emojiByUnified = React__default.useCallback(function (unified) {
|
|
@@ -26927,7 +27007,8 @@ function usePickerDataContext() {
|
|
|
26927
27007
|
function useGetEmojisByCategory() {
|
|
26928
27008
|
var _usePickerDataContext = usePickerDataContext(),
|
|
26929
27009
|
emojiData = _usePickerDataContext.emojiData,
|
|
26930
|
-
emojiByUnified = _usePickerDataContext.emojiByUnified
|
|
27010
|
+
emojiByUnified = _usePickerDataContext.emojiByUnified,
|
|
27011
|
+
customGroups = _usePickerDataContext.customGroups;
|
|
26931
27012
|
var suggestedEmojisModeConfig = useSuggestedEmojisModeConfig();
|
|
26932
27013
|
var _useUpdateSuggested = useUpdateSuggested(),
|
|
26933
27014
|
suggestedUpdated = _useUpdateSuggested[0];
|
|
@@ -26948,11 +27029,15 @@ function useGetEmojisByCategory() {
|
|
|
26948
27029
|
}).filter(Boolean);
|
|
26949
27030
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
26950
27031
|
}, [isMounted, suggestedUpdated, suggestedEmojisModeConfig, emojiByUnified]);
|
|
26951
|
-
return function getEmojisByCategory(category) {
|
|
27032
|
+
return function getEmojisByCategory(category, group) {
|
|
26952
27033
|
var _emojiData$emojis$cat, _emojiData$emojis;
|
|
26953
27034
|
if (category === Categories.SUGGESTED) {
|
|
26954
27035
|
return suggested;
|
|
26955
27036
|
}
|
|
27037
|
+
if (category === Categories.CUSTOM && group) {
|
|
27038
|
+
var _customGroups$group;
|
|
27039
|
+
return (_customGroups$group = customGroups[group]) != null ? _customGroups$group : [];
|
|
27040
|
+
}
|
|
26956
27041
|
return (_emojiData$emojis$cat = (_emojiData$emojis = emojiData.emojis) == null ? void 0 : _emojiData$emojis[category]) != null ? _emojiData$emojis$cat : [];
|
|
26957
27042
|
};
|
|
26958
27043
|
}
|
|
@@ -29586,11 +29671,10 @@ function EmojiCategory(_ref) {
|
|
|
29586
29671
|
hiddenOnSearch = _ref.hiddenOnSearch,
|
|
29587
29672
|
height = _ref.height,
|
|
29588
29673
|
emojisPerRow = _ref.emojisPerRow;
|
|
29589
|
-
var category = categoryFromCategoryConfig(categoryConfig);
|
|
29590
29674
|
var categoryName = categoryNameFromCategoryConfig(categoryConfig);
|
|
29591
29675
|
return createElement("li", {
|
|
29592
29676
|
className: cx(styles$7.category, hidden && commonStyles.hidden, hiddenOnSearch && commonInteractionStyles.hiddenOnSearch),
|
|
29593
|
-
"data-name":
|
|
29677
|
+
"data-name": categoryIdFromCategoryConfig(categoryConfig),
|
|
29594
29678
|
role: "rowgroup",
|
|
29595
29679
|
"aria-label": categoryName
|
|
29596
29680
|
}, createElement("h2", {
|
|
@@ -29665,7 +29749,7 @@ function MeasureEmoji() {
|
|
|
29665
29749
|
return null;
|
|
29666
29750
|
}
|
|
29667
29751
|
var firstCategory = categories[0];
|
|
29668
|
-
var dummyEmoji = getEmojisByCategory(categoryFromCategoryConfig(firstCategory))[0];
|
|
29752
|
+
var dummyEmoji = firstCategory ? getEmojisByCategory(categoryFromCategoryConfig(firstCategory), customGroupFromCategoryConfig(firstCategory))[0] : undefined;
|
|
29669
29753
|
var unified = dummyEmoji ? emojiUnified(dummyEmoji, activeSkinTone) : '';
|
|
29670
29754
|
if (!dummyEmoji) {
|
|
29671
29755
|
return null;
|
|
@@ -29719,22 +29803,24 @@ function EmojiList(_ref) {
|
|
|
29719
29803
|
role: "grid"
|
|
29720
29804
|
}, createElement(MeasureEmoji, null), categories.map(function (categoryConfig, index) {
|
|
29721
29805
|
var category = categoryFromCategoryConfig(categoryConfig);
|
|
29806
|
+
var categoryId = categoryIdFromCategoryConfig(categoryConfig);
|
|
29807
|
+
var group = customGroupFromCategoryConfig(categoryConfig);
|
|
29722
29808
|
var currentOffset = topOffset;
|
|
29723
|
-
var categoryHeight = categoryHeights[
|
|
29809
|
+
var categoryHeight = categoryHeights[categoryId];
|
|
29724
29810
|
if (categoryHeight) {
|
|
29725
29811
|
topOffset += categoryHeight + labelHeight;
|
|
29726
29812
|
}
|
|
29727
29813
|
return createElement(RenderCategory, {
|
|
29728
|
-
key:
|
|
29729
|
-
categoryEmojis: getEmojisByCategory(category),
|
|
29814
|
+
key: categoryId,
|
|
29815
|
+
categoryEmojis: getEmojisByCategory(category, group),
|
|
29730
29816
|
categoryConfig: categoryConfig,
|
|
29731
29817
|
topOffset: currentOffset,
|
|
29732
29818
|
isFirstCategory: index === 0,
|
|
29733
29819
|
onHeightReady: function onHeightReady(height) {
|
|
29734
|
-
if (categoryHeights[
|
|
29820
|
+
if (categoryHeights[categoryId] !== height) {
|
|
29735
29821
|
setCategoryHeights(function (prev) {
|
|
29736
29822
|
var _extends2;
|
|
29737
|
-
return _extends({}, prev, (_extends2 = {}, _extends2[
|
|
29823
|
+
return _extends({}, prev, (_extends2 = {}, _extends2[categoryId] = height, _extends2));
|
|
29738
29824
|
});
|
|
29739
29825
|
}
|
|
29740
29826
|
},
|
|
@@ -29758,7 +29844,7 @@ function RenderCategory(_ref2) {
|
|
|
29758
29844
|
// the deadlock; the observer takes over from there.
|
|
29759
29845
|
// https://github.com/ealush/emoji-picker-react/issues/469
|
|
29760
29846
|
// https://github.com/ealush/emoji-picker-react/issues/475
|
|
29761
|
-
var isCategoryVisible = isFirstCategory || visibleCategories.includes(categoryConfig
|
|
29847
|
+
var isCategoryVisible = isFirstCategory || visibleCategories.includes(categoryIdFromCategoryConfig(categoryConfig));
|
|
29762
29848
|
var _useEmojiVirtualizati = useEmojiVirtualization({
|
|
29763
29849
|
categoryEmojis: categoryEmojis,
|
|
29764
29850
|
topOffset: topOffset,
|
|
@@ -30483,7 +30569,8 @@ function useScrollCategoryIntoView() {
|
|
|
30483
30569
|
if (!BodyRef.current) {
|
|
30484
30570
|
return;
|
|
30485
30571
|
}
|
|
30486
|
-
|
|
30572
|
+
// Group names are user-controlled; escape for the attribute selector.
|
|
30573
|
+
var $category = (_BodyRef$current = BodyRef.current) == null ? void 0 : _BodyRef$current.querySelector("[data-name=\"" + CSS.escape(category) + "\"]");
|
|
30487
30574
|
if (!$category) {
|
|
30488
30575
|
return;
|
|
30489
30576
|
}
|
|
@@ -30866,8 +30953,24 @@ function CategoryNavigation() {
|
|
|
30866
30953
|
var categoryIcons = useCategoryIconsConfig();
|
|
30867
30954
|
var CategoryNavigationRef = useCategoryNavigationRef();
|
|
30868
30955
|
var hideCustomCategory = useShouldHideCustomEmojis();
|
|
30956
|
+
var _usePickerDataContext = usePickerDataContext(),
|
|
30957
|
+
customGroups = _usePickerDataContext.customGroups,
|
|
30958
|
+
emojiData = _usePickerDataContext.emojiData;
|
|
30869
30959
|
var visibleCategories = categoriesConfig.filter(function (categoryConfig) {
|
|
30870
|
-
|
|
30960
|
+
if (isCustomCategory(categoryConfig) && hideCustomCategory) {
|
|
30961
|
+
return false;
|
|
30962
|
+
}
|
|
30963
|
+
// Tabs navigating to an empty (hidden) section are dead weight.
|
|
30964
|
+
var group = customGroupFromCategoryConfig(categoryConfig);
|
|
30965
|
+
if (group) {
|
|
30966
|
+
var _customGroups$group$l, _customGroups$group;
|
|
30967
|
+
return ((_customGroups$group$l = (_customGroups$group = customGroups[group]) == null ? void 0 : _customGroups$group.length) != null ? _customGroups$group$l : 0) > 0;
|
|
30968
|
+
}
|
|
30969
|
+
if (isCustomCategory(categoryConfig)) {
|
|
30970
|
+
var _emojiData$emojis$Cat, _emojiData$emojis, _emojiData$emojis$Cat2;
|
|
30971
|
+
return ((_emojiData$emojis$Cat = (_emojiData$emojis = emojiData.emojis) == null ? void 0 : (_emojiData$emojis$Cat2 = _emojiData$emojis[Categories.CUSTOM]) == null ? void 0 : _emojiData$emojis$Cat2.length) != null ? _emojiData$emojis$Cat : 0) > 0;
|
|
30972
|
+
}
|
|
30973
|
+
return true;
|
|
30871
30974
|
});
|
|
30872
30975
|
// A single tab navigates nowhere — hide the bar to reclaim its space.
|
|
30873
30976
|
// https://github.com/ealush/emoji-picker-react/issues/396
|
|
@@ -30882,19 +30985,20 @@ function CategoryNavigation() {
|
|
|
30882
30985
|
ref: CategoryNavigationRef
|
|
30883
30986
|
}, visibleCategories.map(function (categoryConfig) {
|
|
30884
30987
|
var category = categoryFromCategoryConfig(categoryConfig);
|
|
30885
|
-
var
|
|
30988
|
+
var categoryId = categoryIdFromCategoryConfig(categoryConfig);
|
|
30989
|
+
var isActiveCategory = categoryId === activeCategory;
|
|
30886
30990
|
var allowNavigation = !isSearchMode && !isActiveCategory;
|
|
30887
30991
|
return createElement(CategoryButton, {
|
|
30888
|
-
key:
|
|
30992
|
+
key: categoryId,
|
|
30889
30993
|
category: category,
|
|
30890
30994
|
isActiveCategory: isActiveCategory,
|
|
30891
30995
|
allowNavigation: allowNavigation,
|
|
30892
30996
|
categoryConfig: categoryConfig,
|
|
30893
30997
|
customIcon: categoryIcons[category],
|
|
30894
30998
|
onClick: function onClick() {
|
|
30895
|
-
scrollCategoryIntoView(
|
|
30999
|
+
scrollCategoryIntoView(categoryId);
|
|
30896
31000
|
setTimeout(function () {
|
|
30897
|
-
setActiveCategory(
|
|
31001
|
+
setActiveCategory(categoryId);
|
|
30898
31002
|
}, 10);
|
|
30899
31003
|
}
|
|
30900
31004
|
});
|