emoji-picker-react 4.22.0 → 4.22.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/dist/emoji-picker-react.cjs.development.js +73 -16
- 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 +73 -16
- package/dist/emoji-picker-react.esm.js.map +1 -1
- package/dist/hooks/useActiveCategoryScrollDetection.d.ts +8 -1
- package/llms.txt +7 -0
- package/package.json +1 -1
- package/src/components/context/PickerConfigContext.tsx +5 -1
- package/src/components/context/PickerDataContext.tsx +12 -7
- package/src/components/navigation/CategoryNavigation.tsx +8 -1
- package/src/config/compareConfig.ts +72 -0
- package/src/hooks/useActiveCategoryScrollDetection.ts +9 -1
|
@@ -179,7 +179,54 @@ function compareConfig(prev, next) {
|
|
|
179
179
|
var _prev$customEmojis, _next$customEmojis;
|
|
180
180
|
var prevCustomEmojis = (_prev$customEmojis = prev.customEmojis) != null ? _prev$customEmojis : [];
|
|
181
181
|
var nextCustomEmojis = (_next$customEmojis = next.customEmojis) != null ? _next$customEmojis : [];
|
|
182
|
-
return prev.open === next.open && prev.emojiVersion === next.emojiVersion && prev.reactionsDefaultOpen === next.reactionsDefaultOpen && prev.searchPlaceHolder === next.searchPlaceHolder && prev.searchPlaceholder === next.searchPlaceholder && prev.searchClearButtonLabel === next.searchClearButtonLabel && prev.defaultSkinTone === next.defaultSkinTone && prev.skinTonesDisabled === next.skinTonesDisabled && prev.autoFocusSearch === next.autoFocusSearch && prev.emojiStyle === next.emojiStyle && prev.theme === next.theme && prev.suggestedEmojisMode === next.suggestedEmojisMode && prev.lazyLoadEmojis === next.lazyLoadEmojis && prev.className === next.className && prev.height === next.height && prev.width === next.width && prev.style === next.style && prev.searchDisabled === next.searchDisabled && prev.skinTonePickerLocation === next.skinTonePickerLocation && prevCustomEmojis.length === nextCustomEmojis.length && prev.emojiData === next.emojiData;
|
|
182
|
+
return prev.open === next.open && prev.emojiVersion === next.emojiVersion && prev.reactionsDefaultOpen === next.reactionsDefaultOpen && prev.searchPlaceHolder === next.searchPlaceHolder && prev.searchPlaceholder === next.searchPlaceholder && prev.searchClearButtonLabel === next.searchClearButtonLabel && prev.defaultSkinTone === next.defaultSkinTone && prev.skinTonesDisabled === next.skinTonesDisabled && prev.autoFocusSearch === next.autoFocusSearch && prev.emojiStyle === next.emojiStyle && prev.theme === next.theme && prev.suggestedEmojisMode === next.suggestedEmojisMode && prev.lazyLoadEmojis === next.lazyLoadEmojis && prev.className === next.className && prev.height === next.height && prev.width === next.width && prev.style === next.style && prev.searchDisabled === next.searchDisabled && prev.skinTonePickerLocation === next.skinTonePickerLocation && prevCustomEmojis.length === nextCustomEmojis.length && customEmojisEqual(prevCustomEmojis, nextCustomEmojis) && categoriesEqual(prev.categories, next.categories) && prev.emojiData === next.emojiData;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Structural content equality for custom emojis. Length alone misses
|
|
186
|
+
* regroups and swaps, which would leave merged categories, search, and
|
|
187
|
+
* sections stale. Fields are compared element-wise (never serialized
|
|
188
|
+
* with delimiters) so user-controlled values cannot collide.
|
|
189
|
+
*/
|
|
190
|
+
function customEmojisEqual(prev, next) {
|
|
191
|
+
if (prev.length !== next.length) {
|
|
192
|
+
return false;
|
|
193
|
+
}
|
|
194
|
+
return prev.every(function (emoji, index) {
|
|
195
|
+
var _emoji$group, _other$group;
|
|
196
|
+
var other = next[index];
|
|
197
|
+
return emoji.id === other.id && ((_emoji$group = emoji.group) != null ? _emoji$group : '') === ((_other$group = other.group) != null ? _other$group : '') && emoji.imgUrl === other.imgUrl && emoji.names.length === other.names.length && emoji.names.every(function (name, nameIndex) {
|
|
198
|
+
return name === other.names[nameIndex];
|
|
199
|
+
});
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Structural content equality for the categories input. Order, labels,
|
|
204
|
+
* group selection, and icon identity all flow into the merged
|
|
205
|
+
* configuration. Icons compare by reference: swapping one icon element
|
|
206
|
+
* for another must rebuild, while a stable reference stays cheap.
|
|
207
|
+
*/
|
|
208
|
+
function categoriesEqual(prev, next) {
|
|
209
|
+
var prevEntries = prev != null ? prev : [];
|
|
210
|
+
var nextEntries = next != null ? next : [];
|
|
211
|
+
if (prevEntries.length !== nextEntries.length) {
|
|
212
|
+
return false;
|
|
213
|
+
}
|
|
214
|
+
return prevEntries.every(function (entry, index) {
|
|
215
|
+
return categoryEntriesEqual(entry, nextEntries[index]);
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* One categories entry compared structurally. Icons compare by reference:
|
|
220
|
+
* swapping one icon element for another rebuilds, a stable reference stays
|
|
221
|
+
* cheap. Delimited serialization is avoided so user-controlled values
|
|
222
|
+
* cannot collide.
|
|
223
|
+
*/
|
|
224
|
+
function categoryEntriesEqual(entry, other) {
|
|
225
|
+
var _entry$group, _other$group2;
|
|
226
|
+
if (typeof entry === 'string' || typeof other === 'string') {
|
|
227
|
+
return entry === other;
|
|
228
|
+
}
|
|
229
|
+
return entry.category === other.category && entry.name === other.name && ((_entry$group = entry.group) != null ? _entry$group : '') === ((_other$group2 = other.group) != null ? _other$group2 : '') && entry.icon === other.icon;
|
|
183
230
|
}
|
|
184
231
|
|
|
185
232
|
var DEFAULT_REACTIONS = ['1f44d', '2764-fe0f', '1f603', '1f622', '1f64f', '1f44e', '1f621'];
|
|
@@ -557,7 +604,6 @@ function PickerConfigProvider(_ref) {
|
|
|
557
604
|
}, children);
|
|
558
605
|
}
|
|
559
606
|
function useSetConfig(config) {
|
|
560
|
-
var _config$customEmojis;
|
|
561
607
|
var _React$useState = React.useState(function () {
|
|
562
608
|
return mergeConfig(config);
|
|
563
609
|
}),
|
|
@@ -570,7 +616,11 @@ function useSetConfig(config) {
|
|
|
570
616
|
setMergedConfig(mergeConfig(config));
|
|
571
617
|
// not gonna...
|
|
572
618
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
573
|
-
}, [
|
|
619
|
+
}, [
|
|
620
|
+
// New references rebuild merged categories and data even at equal
|
|
621
|
+
// length; compareConfig above still gates no-op updates so inline
|
|
622
|
+
// literals don't loop.
|
|
623
|
+
config.categories, config.customEmojis, config.open, config.emojiVersion, config.reactionsDefaultOpen, config.searchPlaceHolder, config.searchPlaceholder, config.searchClearButtonLabel, config.defaultSkinTone, config.skinTonesDisabled, config.autoFocusSearch, config.emojiStyle, config.theme, config.suggestedEmojisMode, config.lazyLoadEmojis, config.className, config.height, config.width, config.searchDisabled, config.skinTonePickerLocation, config.allowExpandReactions, config.emojiData]);
|
|
574
624
|
return mergedConfig;
|
|
575
625
|
}
|
|
576
626
|
function usePickerConfig() {
|
|
@@ -26927,9 +26977,9 @@ function useIsMounted() {
|
|
|
26927
26977
|
var PickerDataContext = /*#__PURE__*/React__default.createContext({
|
|
26928
26978
|
emojiData: {},
|
|
26929
26979
|
allEmojis: [],
|
|
26930
|
-
allEmojisByUnified:
|
|
26931
|
-
searchIndex:
|
|
26932
|
-
customGroups:
|
|
26980
|
+
allEmojisByUnified: /*#__PURE__*/Object.create(null),
|
|
26981
|
+
searchIndex: /*#__PURE__*/Object.create(null),
|
|
26982
|
+
customGroups: /*#__PURE__*/Object.create(null),
|
|
26933
26983
|
emojiByUnified: emojiByUnified,
|
|
26934
26984
|
activeVariationFromUnified: function activeVariationFromUnified() {
|
|
26935
26985
|
return null;
|
|
@@ -26944,7 +26994,10 @@ function PickerDataProvider(_ref) {
|
|
|
26944
26994
|
var emojiData = genericEmojiData || defaultEmojiData;
|
|
26945
26995
|
// Clone to avoid mutation of shared source
|
|
26946
26996
|
var newData = JSON.parse(JSON.stringify(emojiData));
|
|
26947
|
-
|
|
26997
|
+
// Group names and emoji ids are user-controlled strings: use
|
|
26998
|
+
// null-prototype dictionaries so names like `__proto__` behave as
|
|
26999
|
+
// ordinary data instead of resolving Object.prototype members.
|
|
27000
|
+
var customGroups = Object.create(null);
|
|
26948
27001
|
if (customEmojis && customEmojis.length > 0) {
|
|
26949
27002
|
for (var _iterator = _createForOfIteratorHelperLoose(customEmojis), _step; !(_step = _iterator()).done;) {
|
|
26950
27003
|
var _customGroups$emoji$g;
|
|
@@ -26961,8 +27014,8 @@ function PickerDataProvider(_ref) {
|
|
|
26961
27014
|
}
|
|
26962
27015
|
var emojis = newData.emojis || {};
|
|
26963
27016
|
var allEmojis = Object.values(emojis).concat(Object.values(customGroups)).flat();
|
|
26964
|
-
var allEmojisByUnified =
|
|
26965
|
-
var searchIndex =
|
|
27017
|
+
var allEmojisByUnified = Object.create(null);
|
|
27018
|
+
var searchIndex = Object.create(null);
|
|
26966
27019
|
allEmojis.forEach(function (emoji) {
|
|
26967
27020
|
var unified = emoji[EmojiProperties.unified];
|
|
26968
27021
|
allEmojisByUnified[unified] = emoji;
|
|
@@ -26977,7 +27030,7 @@ function PickerDataProvider(_ref) {
|
|
|
26977
27030
|
var joinedNameString = (emoji[EmojiProperties.name] || []).join('').toLowerCase().split('');
|
|
26978
27031
|
joinedNameString.forEach(function (_char) {
|
|
26979
27032
|
var _searchIndex$_char;
|
|
26980
|
-
searchIndex[_char] = (_searchIndex$_char = searchIndex[_char]) != null ? _searchIndex$_char :
|
|
27033
|
+
searchIndex[_char] = (_searchIndex$_char = searchIndex[_char]) != null ? _searchIndex$_char : Object.create(null);
|
|
26981
27034
|
searchIndex[_char][unified] = emoji;
|
|
26982
27035
|
});
|
|
26983
27036
|
});
|
|
@@ -30507,7 +30560,8 @@ function categoryNameFromDom($category) {
|
|
|
30507
30560
|
|
|
30508
30561
|
function useActiveCategoryScrollDetection(_ref) {
|
|
30509
30562
|
var setActiveCategory = _ref.setActiveCategory,
|
|
30510
|
-
setVisibleCategories = _ref.setVisibleCategories
|
|
30563
|
+
setVisibleCategories = _ref.setVisibleCategories,
|
|
30564
|
+
categories = _ref.categories;
|
|
30511
30565
|
var BodyRef = useBodyRef();
|
|
30512
30566
|
React.useEffect(function () {
|
|
30513
30567
|
var visibleCategories = new Map();
|
|
@@ -30559,7 +30613,7 @@ function useActiveCategoryScrollDetection(_ref) {
|
|
|
30559
30613
|
return function () {
|
|
30560
30614
|
observer.disconnect();
|
|
30561
30615
|
};
|
|
30562
|
-
}, [BodyRef, setActiveCategory, setVisibleCategories]);
|
|
30616
|
+
}, [BodyRef, categories, setActiveCategory, setVisibleCategories]);
|
|
30563
30617
|
}
|
|
30564
30618
|
|
|
30565
30619
|
function useScrollCategoryIntoView() {
|
|
@@ -30945,10 +30999,6 @@ function CategoryNavigation() {
|
|
|
30945
30999
|
var _useVisibleCategories = useVisibleCategoriesState(),
|
|
30946
31000
|
setVisibleCategories = _useVisibleCategories[1];
|
|
30947
31001
|
var scrollCategoryIntoView = useScrollCategoryIntoView();
|
|
30948
|
-
useActiveCategoryScrollDetection({
|
|
30949
|
-
setActiveCategory: setActiveCategory,
|
|
30950
|
-
setVisibleCategories: setVisibleCategories
|
|
30951
|
-
});
|
|
30952
31002
|
var isSearchMode = useIsSearchMode();
|
|
30953
31003
|
var categoriesConfig = useCategoriesConfig();
|
|
30954
31004
|
var categoryIcons = useCategoryIconsConfig();
|
|
@@ -30957,6 +31007,13 @@ function CategoryNavigation() {
|
|
|
30957
31007
|
var _usePickerDataContext = usePickerDataContext(),
|
|
30958
31008
|
customGroups = _usePickerDataContext.customGroups,
|
|
30959
31009
|
emojiData = _usePickerDataContext.emojiData;
|
|
31010
|
+
// The observer re-subscribes when the merged categories reference
|
|
31011
|
+
// changes (sections added/removed); the reference is stable otherwise.
|
|
31012
|
+
useActiveCategoryScrollDetection({
|
|
31013
|
+
setActiveCategory: setActiveCategory,
|
|
31014
|
+
setVisibleCategories: setVisibleCategories,
|
|
31015
|
+
categories: categoriesConfig
|
|
31016
|
+
});
|
|
30960
31017
|
var visibleCategories = categoriesConfig.filter(function (categoryConfig) {
|
|
30961
31018
|
if (isCustomCategory(categoryConfig) && hideCustomCategory) {
|
|
30962
31019
|
return false;
|