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.
@@ -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
- }, [(_config$customEmojis = config.customEmojis) == null ? void 0 : _config$customEmojis.length, 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]);
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
- var customGroups = {};
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;