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