expo-native-sheet-emojis 2.0.1 → 2.0.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/README.md CHANGED
@@ -6,7 +6,7 @@ A fully native emoji picker bottom sheet for React Native. Built entirely in Swi
6
6
 
7
7
  ## Highlights
8
8
 
9
- - **1900+ emojis** across 9 categories (Unicode Emoji up to v16.0), rendered at 60+ FPS
9
+ - **1900+ emojis** across 9 categories (Unicode Emoji up to v16.0)
10
10
  - **60+ FPS everywhere** -- native UICollectionView (iOS) and RecyclerView (Android) with no JS bridge involvement during scrolling, searching, or animations
11
11
  - Fully native on both platforms -- no JavaScript emoji rendering, no web views, no React re-renders
12
12
  - Search across 21 languages powered by [Unicode CLDR](https://cldr.unicode.org/) -- the industry-standard source for emoji annotations used by iOS, Android, and major platforms. Runs on a background thread to keep the UI thread free
@@ -431,6 +431,41 @@ await EmojiSheetModule.present({
431
431
  | gestureEnabled | `boolean` | `true` | Swipe to dismiss |
432
432
  | backdropOpacity | `number` | `0.22` | Backdrop opacity |
433
433
 
434
+ ## Companion: expo-native-emojis-popup
435
+
436
+ For quick emoji reactions (like message reaction trays), the companion module [expo-native-emojis-popup](https://github.com/efstathiosntonas/expo-native-emojis-popup) provides a fully native emoji reaction popup with long-press drag-to-select, hover labels, and spring animations.
437
+
438
+ Together they form a complete reaction system:
439
+
440
+ 1. User long-presses a message/post -> `expo-native-emojis-popup` shows the quick reaction tray
441
+ 2. User taps the plus button -> your app presents `expo-native-sheet-emojis` for the full emoji catalog
442
+ 3. Selected emoji flows back into your reaction system
443
+
444
+ ```typescript
445
+ import { EmojisPopupModule } from 'expo-native-emojis-popup';
446
+ import { EmojiSheetModule } from 'expo-native-sheet-emojis';
447
+
448
+ const result = await EmojisPopupModule.show({
449
+ anchorId: 'message:42',
450
+ items: [
451
+ { emoji: '❤️', emoji_name: 'Red Heart', id: 'heart' },
452
+ { emoji: '👍', emoji_name: 'Thumbs Up', id: 'thumbsup' },
453
+ { emoji: '😂', emoji_name: 'Face with Tears of Joy', id: 'laugh' },
454
+ ],
455
+ plusEnabled: true,
456
+ });
457
+
458
+ if (result.type === 'plus') {
459
+ // Open the full emoji picker
460
+ const sheetResult = await EmojiSheetModule.present({ theme: 'dark' });
461
+ if (!sheetResult.cancelled) {
462
+ handleReaction(sheetResult.emoji);
463
+ }
464
+ } else if (result.type === 'select') {
465
+ handleReaction(result.id);
466
+ }
467
+ ```
468
+
434
469
  ## LLM / AI Agent Reference
435
470
 
436
471
  If you're an AI agent or using an LLM to integrate this module, see [llms.txt](https://raw.githubusercontent.com/efstathiosntonas/expo-native-sheet-emojis/refs/heads/main/llms.txt) for a concise, structured reference with all types, APIs, and usage patterns.
@@ -111,12 +111,16 @@ class EmojiSkinTonePicker(
111
111
  }
112
112
  }
113
113
 
114
- // Position above anchor
115
- val location = IntArray(2)
116
- anchorView.getLocationOnScreen(location)
117
- val xOff = -(totalWidth / 2) + (anchorView.width / 2)
118
- val yOff = -totalHeight - (4 * density).toInt()
114
+ // Use window-relative coordinates to avoid RTL xOff flip and status bar offset
115
+ val anchorLocation = IntArray(2)
116
+ anchorView.getLocationInWindow(anchorLocation)
117
+ val windowWidth = anchorView.rootView.width
118
+ val edgePadding = (8 * density).toInt()
119
119
 
120
- popup.showAsDropDown(anchorView, xOff, yOff)
120
+ val idealLeft = anchorLocation[0] + anchorView.width / 2 - totalWidth / 2
121
+ val clampedLeft = idealLeft.coerceIn(edgePadding, windowWidth - totalWidth - edgePadding)
122
+ val popupTop = anchorLocation[1] - totalHeight - (4 * density).toInt()
123
+
124
+ popup.showAtLocation(anchorView.rootView, Gravity.NO_GRAVITY, clampedLeft, popupTop)
121
125
  }
122
126
  }
@@ -357,7 +357,8 @@ class EmojiGridView: UIView, UICollectionViewDataSource, UICollectionViewDelegat
357
357
  dismissSkinTonePicker()
358
358
 
359
359
  guard let cell = collectionView.cellForItem(at: indexPath) else { return }
360
- let cellFrameInSelf = collectionView.convert(cell.frame, to: self)
360
+ let targetView = superview ?? self
361
+ let cellFrameInTarget = collectionView.convert(cell.frame, to: targetView)
361
362
 
362
363
  if enableHaptics {
363
364
  impactFeedbackMedium.impactOccurred()
@@ -381,19 +382,19 @@ class EmojiGridView: UIView, UICollectionViewDataSource, UICollectionViewDelegat
381
382
  self.dismissSkinTonePicker()
382
383
  }
383
384
 
384
- addSubview(picker)
385
+ targetView.addSubview(picker)
385
386
  picker.translatesAutoresizingMaskIntoConstraints = false
386
387
 
387
388
  let pickerWidth: CGFloat = 6 * 48 + 16
388
389
  let pickerHeight: CGFloat = 56
389
390
 
390
- var centerX = cellFrameInSelf.midX
391
+ var centerX = cellFrameInTarget.midX
391
392
  let halfWidth = pickerWidth / 2
392
- centerX = max(halfWidth + 4, min(bounds.width - halfWidth - 4, centerX))
393
+ centerX = max(halfWidth + 8, min(targetView.bounds.width - halfWidth - 8, centerX))
393
394
 
394
395
  NSLayoutConstraint.activate([
395
- picker.centerXAnchor.constraint(equalTo: leadingAnchor, constant: centerX),
396
- picker.bottomAnchor.constraint(equalTo: topAnchor, constant: cellFrameInSelf.minY - 4),
396
+ picker.centerXAnchor.constraint(equalTo: targetView.leftAnchor, constant: centerX),
397
+ picker.bottomAnchor.constraint(equalTo: targetView.topAnchor, constant: cellFrameInTarget.minY - 4),
397
398
  picker.widthAnchor.constraint(equalToConstant: pickerWidth),
398
399
  picker.heightAnchor.constraint(equalToConstant: pickerHeight),
399
400
  ])
@@ -1,6 +1,6 @@
1
1
  Pod::Spec.new do |s|
2
2
  s.name = 'EmojiSheetModule'
3
- s.version = '2.0.1'
3
+ s.version = '2.0.2'
4
4
  s.summary = 'Native emoji picker bottom sheet for React Native'
5
5
  s.description = 'A fully native iOS/Android emoji picker presented in a bottom sheet with search, skin tones, and theming support.'
6
6
  s.author = ''
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-native-sheet-emojis",
3
- "version": "2.0.1",
3
+ "version": "2.0.2",
4
4
  "description": "A fully native emoji picker bottom sheet for React Native. Built with Swift and Kotlin for maximum performance. Features search with multilingual keywords, skin tones, frequently used tracking, theming, and configurable layout.",
5
5
  "main": "lib/commonjs/index.js",
6
6
  "module": "lib/module/index.js",
@@ -32,7 +32,7 @@
32
32
  "input"
33
33
  ],
34
34
  "license": "MIT",
35
- "author": "Efstathios Ntonas <efstathiosntonas@gmail.com> (https://github.com/efstathiosntonas)",
35
+ "author": "Efstathios Ntonas",
36
36
  "homepage": "https://github.com/efstathiosntonas/expo-native-sheet-emojis#readme",
37
37
  "bugs": {
38
38
  "url": "https://github.com/efstathiosntonas/expo-native-sheet-emojis/issues"