expo-native-sheet-emojis 1.8.1 → 2.0.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/README.md +8 -6
- package/android/build.gradle +2 -1
- package/android/src/main/java/expo/community/modules/emojisheet/EmojiGridAdapter.kt +15 -0
- package/android/src/main/java/expo/community/modules/emojisheet/EmojiSheetContentView.kt +6 -0
- package/android/src/main/java/expo/community/modules/emojisheet/EmojiSheetModule.kt +4 -1
- package/android/src/main/java/expo/community/modules/emojisheet/EmojiSheetUIView.kt +84 -82
- package/ios/EmojiGridView.swift +4 -2
- package/ios/EmojiSheetContentView.swift +10 -2
- package/ios/EmojiSheetModule.podspec +1 -1
- package/ios/EmojiSheetModule.swift +9 -1
- package/ios/EmojiSheetUIView.swift +110 -54
- package/lib/commonjs/EmojiSheetModule.js +12 -1
- package/lib/commonjs/EmojiSheetModule.js.map +1 -1
- package/lib/commonjs/EmojiSheetView.js +4 -2
- package/lib/commonjs/EmojiSheetView.js.map +1 -1
- package/lib/module/EmojiSheetModule.js +12 -1
- package/lib/module/EmojiSheetModule.js.map +1 -1
- package/lib/module/EmojiSheetView.js +4 -2
- package/lib/module/EmojiSheetView.js.map +1 -1
- package/lib/typescript/EmojiSheetModule.d.ts.map +1 -1
- package/lib/typescript/EmojiSheetModule.types.d.ts +12 -1
- package/lib/typescript/EmojiSheetModule.types.d.ts.map +1 -1
- package/lib/typescript/EmojiSheetView.d.ts +1 -1
- package/lib/typescript/EmojiSheetView.d.ts.map +1 -1
- package/package.json +1 -1
- package/plugin/build/withEmojiSheet.js +38 -22
- package/src/EmojiSheetModule.ts +15 -2
- package/src/EmojiSheetModule.types.ts +7 -4
- package/src/EmojiSheetView.tsx +3 -1
package/README.md
CHANGED
|
@@ -72,7 +72,7 @@ function MyComponent() {
|
|
|
72
72
|
style={{ flex: 1 }}
|
|
73
73
|
theme="light"
|
|
74
74
|
layoutDirection="auto"
|
|
75
|
-
onEmojiSelected={(emoji) => console.log(emoji)}
|
|
75
|
+
onEmojiSelected={(emoji, name, id) => console.log(emoji, name, id)}
|
|
76
76
|
columns={7}
|
|
77
77
|
showSearch={true}
|
|
78
78
|
/>
|
|
@@ -278,7 +278,7 @@ Presents the emoji picker as a native bottom sheet. Returns a promise that resol
|
|
|
278
278
|
**Returns:** `Promise<EmojiSheetResult>`
|
|
279
279
|
|
|
280
280
|
The result is a discriminated union:
|
|
281
|
-
- `{ emoji: string }` when an emoji is selected
|
|
281
|
+
- `{ emoji: string; name: string; id: string }` when an emoji is selected
|
|
282
282
|
- `{ cancelled: true }` when the sheet is dismissed without selection
|
|
283
283
|
|
|
284
284
|
### EmojiSheetModule.dismiss()
|
|
@@ -307,8 +307,9 @@ A declarative React component that renders the emoji picker inline.
|
|
|
307
307
|
|
|
308
308
|
| Prop | Type | Default | Description |
|
|
309
309
|
|-|-|-|-|
|
|
310
|
-
| onEmojiSelected | `(emoji: string) => void` | required | Called when an emoji is tapped |
|
|
310
|
+
| onEmojiSelected | `(emoji: string, name: string, id: string) => void` | required | Called when an emoji is tapped |
|
|
311
311
|
| onDismiss | `() => void` | -- | Called when the picker is dismissed (View API only, not Embedded view) |
|
|
312
|
+
| onOpen | `() => void` | -- | Called when the picker becomes visible |
|
|
312
313
|
| theme | `EmojiSheetTheme \| 'dark' \| 'light' \| 'system'` | `'light'` | Theme configuration |
|
|
313
314
|
| translations | `EmojiSheetTranslations` | -- | Localized strings |
|
|
314
315
|
| layoutDirection | `'auto' \| 'ltr' \| 'rtl'` | `'auto'` | UI layout direction. `'auto'` follows the device locale; use `'ltr'` or `'rtl'` to force a direction. |
|
|
@@ -372,6 +373,7 @@ All theme fields with their purpose:
|
|
|
372
373
|
| gestureEnabled | `boolean` | `true` | Allow swipe-to-dismiss gesture |
|
|
373
374
|
| backdropOpacity | `number` | `0.22` | Opacity of the backdrop behind the sheet |
|
|
374
375
|
| excludeEmojis | `string[]` | `[]` | Emoji IDs to hide from the picker |
|
|
376
|
+
| onOpen | `() => void` | -- | Called when the sheet becomes visible |
|
|
375
377
|
|
|
376
378
|
### EmojiSheetResult
|
|
377
379
|
|
|
@@ -379,8 +381,8 @@ A discriminated union type:
|
|
|
379
381
|
|
|
380
382
|
```typescript
|
|
381
383
|
type EmojiSheetResult =
|
|
382
|
-
| { emoji: string; cancelled?: never }
|
|
383
|
-
| { cancelled: true; emoji?: never };
|
|
384
|
+
| { emoji: string; name: string; id: string; cancelled?: never }
|
|
385
|
+
| { cancelled: true; emoji?: never; name?: never; id?: never };
|
|
384
386
|
```
|
|
385
387
|
|
|
386
388
|
## Category Bar Position
|
|
@@ -431,7 +433,7 @@ await EmojiSheetModule.present({
|
|
|
431
433
|
|
|
432
434
|
## LLM / AI Agent Reference
|
|
433
435
|
|
|
434
|
-
If you're an AI agent or using an LLM to integrate this module, see [llms.txt](llms.txt) for a concise, structured reference with all types, APIs, and usage patterns.
|
|
436
|
+
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.
|
|
435
437
|
|
|
436
438
|
## Contributing
|
|
437
439
|
|
package/android/build.gradle
CHANGED
|
@@ -43,9 +43,10 @@ android {
|
|
|
43
43
|
|
|
44
44
|
dependencies {
|
|
45
45
|
implementation "androidx.recyclerview:recyclerview:1.3.2"
|
|
46
|
-
implementation "androidx.appcompat:appcompat:1.
|
|
46
|
+
implementation "androidx.appcompat:appcompat:1.7.0"
|
|
47
47
|
implementation "com.google.android.material:material:1.12.0"
|
|
48
48
|
implementation "androidx.emoji2:emoji2:1.6.0"
|
|
49
49
|
implementation "androidx.emoji2:emoji2-views-helper:1.6.0"
|
|
50
|
+
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.10.2"
|
|
50
51
|
}
|
|
51
52
|
}
|
|
@@ -9,6 +9,9 @@ import android.view.ViewGroup
|
|
|
9
9
|
import android.widget.FrameLayout
|
|
10
10
|
import android.widget.TextView
|
|
11
11
|
import androidx.appcompat.widget.AppCompatTextView
|
|
12
|
+
import androidx.core.view.AccessibilityDelegateCompat
|
|
13
|
+
import androidx.core.view.ViewCompat
|
|
14
|
+
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat
|
|
12
15
|
import androidx.recyclerview.widget.RecyclerView
|
|
13
16
|
|
|
14
17
|
class EmojiGridAdapter(
|
|
@@ -113,6 +116,10 @@ class EmojiGridAdapter(
|
|
|
113
116
|
}
|
|
114
117
|
is ListItem.Emoji -> {
|
|
115
118
|
val h = holder as EmojiVH
|
|
119
|
+
// Cancel any in-flight animation from a previous binding to prevent stale end-actions on recycled views
|
|
120
|
+
h.container.animate().cancel()
|
|
121
|
+
h.container.scaleX = 1f
|
|
122
|
+
h.container.scaleY = 1f
|
|
116
123
|
h.textView.text = item.emoji
|
|
117
124
|
h.container.contentDescription = item.name
|
|
118
125
|
h.textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, emojiTextSize)
|
|
@@ -124,6 +131,7 @@ class EmojiGridAdapter(
|
|
|
124
131
|
view.performHapticFeedback(android.view.HapticFeedbackConstants.KEYBOARD_TAP)
|
|
125
132
|
}
|
|
126
133
|
if (enableAnimations) {
|
|
134
|
+
view.animate().cancel()
|
|
127
135
|
view.animate().scaleX(0.85f).scaleY(0.85f).setDuration(80).withEndAction {
|
|
128
136
|
view.animate().scaleX(1f).scaleY(1f).setDuration(80).start()
|
|
129
137
|
}.start()
|
|
@@ -135,9 +143,16 @@ class EmojiGridAdapter(
|
|
|
135
143
|
onEmojiLongPress(h.container, item.emoji, item.id)
|
|
136
144
|
true
|
|
137
145
|
}
|
|
146
|
+
ViewCompat.setAccessibilityDelegate(h.container, object : AccessibilityDelegateCompat() {
|
|
147
|
+
override fun onInitializeAccessibilityNodeInfo(host: View, info: AccessibilityNodeInfoCompat) {
|
|
148
|
+
super.onInitializeAccessibilityNodeInfo(host, info)
|
|
149
|
+
info.hintText = "Hold to select skin tone"
|
|
150
|
+
}
|
|
151
|
+
})
|
|
138
152
|
} else {
|
|
139
153
|
h.container.setOnLongClickListener(null)
|
|
140
154
|
h.container.isLongClickable = false
|
|
155
|
+
ViewCompat.setAccessibilityDelegate(h.container, null)
|
|
141
156
|
}
|
|
142
157
|
}
|
|
143
158
|
}
|
|
@@ -14,6 +14,7 @@ class EmojiSheetContentView(
|
|
|
14
14
|
|
|
15
15
|
private val onEmojiSelected by EventDispatcher()
|
|
16
16
|
private val onDismiss by EventDispatcher()
|
|
17
|
+
private val onOpen by EventDispatcher()
|
|
17
18
|
private val pickerView = EmojiSheetUIView(context)
|
|
18
19
|
|
|
19
20
|
init {
|
|
@@ -25,6 +26,11 @@ class EmojiSheetContentView(
|
|
|
25
26
|
pickerView.loadDataAsync()
|
|
26
27
|
}
|
|
27
28
|
|
|
29
|
+
override fun onAttachedToWindow() {
|
|
30
|
+
super.onAttachedToWindow()
|
|
31
|
+
onOpen(mapOf<String, Any>())
|
|
32
|
+
}
|
|
33
|
+
|
|
28
34
|
fun applyConfiguration() {
|
|
29
35
|
pickerView.applyConfiguration()
|
|
30
36
|
}
|
|
@@ -29,6 +29,8 @@ class EmojiSheetModule : Module() {
|
|
|
29
29
|
ModuleDefinition {
|
|
30
30
|
Name("EmojiSheet")
|
|
31
31
|
|
|
32
|
+
Events("onSheetOpened")
|
|
33
|
+
|
|
32
34
|
OnCreate {
|
|
33
35
|
val ctx = appContext.reactContext ?: return@OnCreate
|
|
34
36
|
EmojiSheetUIView.warmCache(ctx)
|
|
@@ -115,7 +117,7 @@ class EmojiSheetModule : Module() {
|
|
|
115
117
|
Prop("excludeEmojis") { view: EmojiSheetContentView, ids: List<String>? ->
|
|
116
118
|
view.updateExcludeEmojis(ids ?: emptyList())
|
|
117
119
|
}
|
|
118
|
-
Events("onEmojiSelected", "onDismiss")
|
|
120
|
+
Events("onEmojiSelected", "onDismiss", "onOpen")
|
|
119
121
|
}
|
|
120
122
|
}
|
|
121
123
|
|
|
@@ -308,6 +310,7 @@ class EmojiSheetModule : Module() {
|
|
|
308
310
|
(parent as? View)?.setBackgroundColor(Color.TRANSPARENT)
|
|
309
311
|
}
|
|
310
312
|
pickerView.loadDataAsync()
|
|
313
|
+
sendEvent("onSheetOpened", android.os.Bundle())
|
|
311
314
|
}
|
|
312
315
|
|
|
313
316
|
bottomSheet.window?.let { window ->
|
|
@@ -12,11 +12,19 @@ import android.widget.LinearLayout
|
|
|
12
12
|
import android.widget.TextView
|
|
13
13
|
import androidx.recyclerview.widget.GridLayoutManager
|
|
14
14
|
import androidx.recyclerview.widget.RecyclerView
|
|
15
|
+
import kotlinx.coroutines.CoroutineScope
|
|
16
|
+
import kotlinx.coroutines.Dispatchers
|
|
17
|
+
import kotlinx.coroutines.Job
|
|
18
|
+
import kotlinx.coroutines.SupervisorJob
|
|
19
|
+
import kotlinx.coroutines.cancel
|
|
20
|
+
import kotlinx.coroutines.currentCoroutineContext
|
|
21
|
+
import kotlinx.coroutines.ensureActive
|
|
22
|
+
import kotlinx.coroutines.launch
|
|
23
|
+
import kotlinx.coroutines.sync.Mutex
|
|
24
|
+
import kotlinx.coroutines.sync.withLock
|
|
25
|
+
import kotlinx.coroutines.withContext
|
|
15
26
|
import java.text.Normalizer
|
|
16
27
|
import java.util.Locale
|
|
17
|
-
import java.util.concurrent.ExecutorService
|
|
18
|
-
import java.util.concurrent.Executors
|
|
19
|
-
import java.util.concurrent.Future
|
|
20
28
|
|
|
21
29
|
class EmojiSheetUIView(context: Context) : LinearLayout(context) {
|
|
22
30
|
|
|
@@ -26,23 +34,34 @@ class EmojiSheetUIView(context: Context) : LinearLayout(context) {
|
|
|
26
34
|
private const val FREQ_DAY_SUFFIX = "_day"
|
|
27
35
|
private const val FREQ_TIME_SUFFIX = "_time"
|
|
28
36
|
private val COMBINING_MARKS_REGEX = "\\p{Mn}+".toRegex()
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
// and loadDataAsync() from parsing the same data twice.
|
|
32
|
-
private val cacheLock = Any()
|
|
37
|
+
private val cacheScope = CoroutineScope(SupervisorJob() + Dispatchers.Default)
|
|
38
|
+
private val cacheMutex = Mutex()
|
|
33
39
|
@Volatile
|
|
34
40
|
private var cachedData: Pair<List<EmojiCategory>, Map<String, List<String>>>? = null
|
|
35
41
|
|
|
36
42
|
fun warmCache(context: Context) {
|
|
37
43
|
if (cachedData != null) return
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
44
|
+
val appContext = context.applicationContext
|
|
45
|
+
cacheScope.launch {
|
|
46
|
+
loadCachedData(appContext)
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
private suspend fun loadCachedData(context: Context): Pair<List<EmojiCategory>, Map<String, List<String>>> {
|
|
51
|
+
cachedData?.let { return it }
|
|
52
|
+
|
|
53
|
+
return cacheMutex.withLock {
|
|
54
|
+
cachedData?.let { return it }
|
|
55
|
+
|
|
56
|
+
try {
|
|
41
57
|
val categories = EmojiData.loadCategories(context)
|
|
42
58
|
val keywords = loadAllKeywords(context)
|
|
43
|
-
|
|
59
|
+
Pair(categories, keywords).also { cachedData = it }
|
|
60
|
+
} catch (e: Exception) {
|
|
61
|
+
android.util.Log.e("EmojiSheet", "Failed to load emoji data", e)
|
|
62
|
+
throw e
|
|
44
63
|
}
|
|
45
|
-
}
|
|
64
|
+
}
|
|
46
65
|
}
|
|
47
66
|
|
|
48
67
|
private fun loadAllKeywords(context: Context): Map<String, List<String>> {
|
|
@@ -120,6 +139,9 @@ class EmojiSheetUIView(context: Context) : LinearLayout(context) {
|
|
|
120
139
|
private var velocityTracker: VelocityTracker? = null
|
|
121
140
|
private var topPullStartY: Float? = null
|
|
122
141
|
private val topPullActivationThresholdPx = 24f * context.resources.displayMetrics.density
|
|
142
|
+
private val viewScope = CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate)
|
|
143
|
+
private var loadJob: Job? = null
|
|
144
|
+
private var searchJob: Job? = null
|
|
123
145
|
|
|
124
146
|
init {
|
|
125
147
|
orientation = VERTICAL
|
|
@@ -415,34 +437,20 @@ class EmojiSheetUIView(context: Context) : LinearLayout(context) {
|
|
|
415
437
|
set(value) { field = value; if (value != null) emptyStateLabel.text = value }
|
|
416
438
|
|
|
417
439
|
fun loadDataAsync() {
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
440
|
+
loadJob?.cancel()
|
|
441
|
+
val appContext = context.applicationContext
|
|
442
|
+
loadJob = viewScope.launch {
|
|
443
|
+
val data = withContext(Dispatchers.Default) {
|
|
444
|
+
loadCachedData(appContext)
|
|
445
|
+
}
|
|
446
|
+
val categories = data.first
|
|
447
|
+
val keywords = data.second
|
|
448
|
+
allCategories = categories
|
|
449
|
+
localizedKeywords = keywords
|
|
422
450
|
allCategoryKeys = buildCategoryKeys()
|
|
423
451
|
rebuildCategoryStrip()
|
|
424
452
|
buildAndSetItems()
|
|
425
|
-
return
|
|
426
453
|
}
|
|
427
|
-
|
|
428
|
-
Thread {
|
|
429
|
-
val data = synchronized(cacheLock) {
|
|
430
|
-
cachedData ?: run {
|
|
431
|
-
val categories = EmojiData.loadCategories(context)
|
|
432
|
-
val keywords = loadLocalizedKeywords()
|
|
433
|
-
Pair(categories, keywords).also { cachedData = it }
|
|
434
|
-
}
|
|
435
|
-
}
|
|
436
|
-
val categories = data.first
|
|
437
|
-
val keywords = data.second
|
|
438
|
-
post {
|
|
439
|
-
allCategories = categories
|
|
440
|
-
localizedKeywords = keywords
|
|
441
|
-
allCategoryKeys = buildCategoryKeys()
|
|
442
|
-
rebuildCategoryStrip()
|
|
443
|
-
buildAndSetItems()
|
|
444
|
-
}
|
|
445
|
-
}.start()
|
|
446
454
|
}
|
|
447
455
|
|
|
448
456
|
fun updateTheme(theme: String) {
|
|
@@ -594,17 +602,14 @@ class EmojiSheetUIView(context: Context) : LinearLayout(context) {
|
|
|
594
602
|
}
|
|
595
603
|
}
|
|
596
604
|
|
|
597
|
-
// Search runs on a
|
|
598
|
-
//
|
|
599
|
-
// new keystrokes cancel the previous task via Future.cancel(true)
|
|
600
|
-
// and the generation counter provides a secondary guard against stale results.
|
|
605
|
+
// Search runs on a cancellable coroutine job. The generation counter remains
|
|
606
|
+
// as a small secondary guard so stale results cannot apply after a newer query.
|
|
601
607
|
private var searchGeneration = 0
|
|
602
|
-
private val searchExecutor: ExecutorService = Executors.newSingleThreadExecutor()
|
|
603
|
-
private var searchFuture: Future<*>? = null
|
|
604
608
|
|
|
605
609
|
private fun onSearch(query: String) {
|
|
606
610
|
val trimmedQuery = query.trim()
|
|
607
611
|
currentSearchQuery = trimmedQuery
|
|
612
|
+
searchJob?.cancel()
|
|
608
613
|
if (trimmedQuery.isEmpty()) {
|
|
609
614
|
searchGeneration += 1
|
|
610
615
|
isSearchActive = false
|
|
@@ -625,46 +630,49 @@ class EmojiSheetUIView(context: Context) : LinearLayout(context) {
|
|
|
625
630
|
val categories = allCategories
|
|
626
631
|
val keywords = localizedKeywords
|
|
627
632
|
|
|
628
|
-
// Cancel previous search task
|
|
629
|
-
searchFuture?.cancel(true)
|
|
630
633
|
val exclude = excludeEmojis
|
|
631
|
-
|
|
632
|
-
val
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
val
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
634
|
+
searchJob = viewScope.launch {
|
|
635
|
+
val matchedItems = withContext(Dispatchers.Default) {
|
|
636
|
+
val normalizedQueryVariants = normalizedSearchVariants(trimmedQuery)
|
|
637
|
+
val scored = mutableListOf<Pair<EmojiGridAdapter.ListItem.Emoji, Int>>()
|
|
638
|
+
|
|
639
|
+
for (cat in categories) {
|
|
640
|
+
currentCoroutineContext().ensureActive()
|
|
641
|
+
for (emoji in cat.data) {
|
|
642
|
+
currentCoroutineContext().ensureActive()
|
|
643
|
+
if (emoji.id in exclude) continue
|
|
644
|
+
val score = relevanceScore(emoji, normalizedQueryVariants, keywords)
|
|
645
|
+
if (score > 0) {
|
|
646
|
+
val resolved = resolveSkinTone(emoji.emoji, emoji.id, emoji.toneEnabled)
|
|
647
|
+
scored.add(Pair(EmojiGridAdapter.ListItem.Emoji(
|
|
648
|
+
emoji = resolved,
|
|
649
|
+
name = emoji.name,
|
|
650
|
+
toneEnabled = emoji.toneEnabled,
|
|
651
|
+
keywords = emoji.keywords,
|
|
652
|
+
id = emoji.id
|
|
653
|
+
), score))
|
|
654
|
+
}
|
|
646
655
|
}
|
|
647
656
|
}
|
|
657
|
+
|
|
658
|
+
scored.sortByDescending { it.second }
|
|
659
|
+
scored.map { it.first }
|
|
648
660
|
}
|
|
649
661
|
|
|
650
|
-
|
|
651
|
-
scored.sortByDescending { it.second }
|
|
662
|
+
if (generation != searchGeneration) return@launch
|
|
652
663
|
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
val results = mutableListOf<EmojiGridAdapter.ListItem>()
|
|
657
|
-
val sectionPositions = mutableListOf<Int>()
|
|
664
|
+
val results = mutableListOf<EmojiGridAdapter.ListItem>()
|
|
665
|
+
val sectionPositions = mutableListOf<Int>()
|
|
666
|
+
if (matchedItems.isNotEmpty()) {
|
|
658
667
|
sectionPositions.add(0)
|
|
659
668
|
results.add(EmojiGridAdapter.ListItem.Header("Search Results", "search"))
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
val hasResults = results.size > 1
|
|
663
|
-
emptyStateLabel.visibility = if (hasResults) View.GONE else View.VISIBLE
|
|
664
|
-
recyclerView.visibility = if (hasResults) View.VISIBLE else View.GONE
|
|
665
|
-
gridAdapter.setItems(results, sectionPositions)
|
|
666
|
-
recyclerView.scrollToPosition(0)
|
|
669
|
+
results.addAll(matchedItems)
|
|
667
670
|
}
|
|
671
|
+
|
|
672
|
+
emptyStateLabel.visibility = if (matchedItems.isNotEmpty()) View.GONE else View.VISIBLE
|
|
673
|
+
recyclerView.visibility = if (matchedItems.isNotEmpty()) View.VISIBLE else View.GONE
|
|
674
|
+
gridAdapter.setItems(results, sectionPositions)
|
|
675
|
+
recyclerView.scrollToPosition(0)
|
|
668
676
|
}
|
|
669
677
|
}
|
|
670
678
|
|
|
@@ -709,13 +717,6 @@ class EmojiSheetUIView(context: Context) : LinearLayout(context) {
|
|
|
709
717
|
}
|
|
710
718
|
return null
|
|
711
719
|
}
|
|
712
|
-
|
|
713
|
-
// --- Localized Search ---
|
|
714
|
-
|
|
715
|
-
private fun loadLocalizedKeywords(): Map<String, List<String>> {
|
|
716
|
-
return loadAllKeywords(context)
|
|
717
|
-
}
|
|
718
|
-
|
|
719
720
|
// --- Frequently Used ---
|
|
720
721
|
|
|
721
722
|
private fun getFreqPrefs(): SharedPreferences =
|
|
@@ -858,7 +859,8 @@ class EmojiSheetUIView(context: Context) : LinearLayout(context) {
|
|
|
858
859
|
|
|
859
860
|
override fun onDetachedFromWindow() {
|
|
860
861
|
super.onDetachedFromWindow()
|
|
861
|
-
|
|
862
|
-
|
|
862
|
+
loadJob?.cancel()
|
|
863
|
+
searchJob?.cancel()
|
|
864
|
+
viewScope.cancel()
|
|
863
865
|
}
|
|
864
866
|
}
|
package/ios/EmojiGridView.swift
CHANGED
|
@@ -213,6 +213,7 @@ class EmojiGridView: UIView, UICollectionViewDataSource, UICollectionViewDelegat
|
|
|
213
213
|
cell.isAccessibilityElement = true
|
|
214
214
|
cell.accessibilityLabel = item.name
|
|
215
215
|
cell.accessibilityTraits = .button
|
|
216
|
+
cell.accessibilityHint = (enableSkinTones && item.toneEnabled) ? "Hold to select skin tone" : nil
|
|
216
217
|
|
|
217
218
|
// Add long press for tone-enabled emojis
|
|
218
219
|
if enableSkinTones && item.toneEnabled {
|
|
@@ -251,11 +252,12 @@ class EmojiGridView: UIView, UICollectionViewDataSource, UICollectionViewDelegat
|
|
|
251
252
|
selectionFeedback.selectionChanged()
|
|
252
253
|
}
|
|
253
254
|
if enableAnimations, let cell = collectionView.cellForItem(at: indexPath) {
|
|
255
|
+
let path = indexPath
|
|
254
256
|
UIView.animate(withDuration: 0.08, delay: 0, options: [.allowUserInteraction]) {
|
|
255
257
|
cell.transform = CGAffineTransform(scaleX: 0.85, y: 0.85)
|
|
256
|
-
} completion: { _ in
|
|
258
|
+
} completion: { [weak collectionView] _ in
|
|
257
259
|
UIView.animate(withDuration: 0.08) {
|
|
258
|
-
|
|
260
|
+
collectionView?.cellForItem(at: path)?.transform = .identity
|
|
259
261
|
}
|
|
260
262
|
}
|
|
261
263
|
}
|
|
@@ -3,7 +3,7 @@ import UIKit
|
|
|
3
3
|
|
|
4
4
|
// MARK: - Data Models
|
|
5
5
|
|
|
6
|
-
struct EmojiItem {
|
|
6
|
+
struct EmojiItem: Sendable {
|
|
7
7
|
let emoji: String
|
|
8
8
|
let name: String
|
|
9
9
|
let version: String
|
|
@@ -12,7 +12,7 @@ struct EmojiItem {
|
|
|
12
12
|
let id: String
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
struct EmojiSection {
|
|
15
|
+
struct EmojiSection: Sendable {
|
|
16
16
|
let title: String
|
|
17
17
|
var data: [EmojiItem]
|
|
18
18
|
}
|
|
@@ -22,6 +22,7 @@ struct EmojiSection {
|
|
|
22
22
|
class EmojiSheetContentView: ExpoView, EmojiSheetUIViewDelegate {
|
|
23
23
|
let onEmojiSelected = EventDispatcher()
|
|
24
24
|
let onDismiss = EventDispatcher()
|
|
25
|
+
let onOpen = EventDispatcher()
|
|
25
26
|
private let pickerView = EmojiSheetUIView()
|
|
26
27
|
|
|
27
28
|
required init(appContext: AppContext? = nil) {
|
|
@@ -42,6 +43,13 @@ class EmojiSheetContentView: ExpoView, EmojiSheetUIViewDelegate {
|
|
|
42
43
|
fatalError("init(coder:) has not been implemented")
|
|
43
44
|
}
|
|
44
45
|
|
|
46
|
+
override func didMoveToWindow() {
|
|
47
|
+
super.didMoveToWindow()
|
|
48
|
+
if window != nil {
|
|
49
|
+
onOpen([:])
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
45
53
|
func updateTheme(_ theme: String) {
|
|
46
54
|
pickerView.updateTheme(theme)
|
|
47
55
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Pod::Spec.new do |s|
|
|
2
2
|
s.name = 'EmojiSheetModule'
|
|
3
|
-
s.version = '
|
|
3
|
+
s.version = '2.0.0'
|
|
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 = ''
|
|
@@ -9,6 +9,8 @@ public class EmojiSheetModule: Module {
|
|
|
9
9
|
public func definition() -> ModuleDefinition {
|
|
10
10
|
Name("EmojiSheet")
|
|
11
11
|
|
|
12
|
+
Events("onSheetOpened")
|
|
13
|
+
|
|
12
14
|
OnCreate {
|
|
13
15
|
EmojiSheetUIView.warmCache()
|
|
14
16
|
}
|
|
@@ -87,7 +89,7 @@ public class EmojiSheetModule: Module {
|
|
|
87
89
|
Prop("excludeEmojis") { (view, ids: [String]?) in
|
|
88
90
|
view.updateExcludeEmojis(ids ?? [])
|
|
89
91
|
}
|
|
90
|
-
Events("onEmojiSelected", "onDismiss")
|
|
92
|
+
Events("onEmojiSelected", "onDismiss", "onOpen")
|
|
91
93
|
}
|
|
92
94
|
}
|
|
93
95
|
|
|
@@ -209,6 +211,9 @@ public class EmojiSheetModule: Module {
|
|
|
209
211
|
sheetVC.mediumDetentRatio = CGFloat(snapPoints.first ?? 0.5)
|
|
210
212
|
sheetVC.gestureEnabled = gestureEnabled
|
|
211
213
|
sheetVC.embedPickerView(pickerView)
|
|
214
|
+
sheetVC.onAppear = { [weak self] in
|
|
215
|
+
self?.sendEvent("onSheetOpened", [:])
|
|
216
|
+
}
|
|
212
217
|
sheetVC.onDismiss = { [weak self] in
|
|
213
218
|
if let promise = self?.currentPromise {
|
|
214
219
|
promise.resolve(["cancelled": true])
|
|
@@ -312,6 +317,7 @@ private final class SheetViewController: UIViewController, UIGestureRecognizerDe
|
|
|
312
317
|
case large
|
|
313
318
|
}
|
|
314
319
|
|
|
320
|
+
var onAppear: (() -> Void)?
|
|
315
321
|
var onDismiss: (() -> Void)?
|
|
316
322
|
var mediumDetentRatio: CGFloat = 0.5
|
|
317
323
|
var gestureEnabled: Bool = true
|
|
@@ -373,6 +379,8 @@ private final class SheetViewController: UIViewController, UIGestureRecognizerDe
|
|
|
373
379
|
) {
|
|
374
380
|
self.backdropView.alpha = Layout.backdropAlpha
|
|
375
381
|
self.sheetContainerView.transform = self.transform(for: self.currentDetent)
|
|
382
|
+
} completion: { [weak self] _ in
|
|
383
|
+
self?.onAppear?()
|
|
376
384
|
}
|
|
377
385
|
}
|
|
378
386
|
|
|
@@ -12,6 +12,69 @@ private enum FrequentlyUsedKeys {
|
|
|
12
12
|
static let timestamp = "timestamp"
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
+
private struct EmojiDataSnapshot: Sendable {
|
|
16
|
+
let sections: [EmojiSection]
|
|
17
|
+
let keywords: [String: [String]]
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
private actor EmojiDataCacheStorage {
|
|
21
|
+
private var cachedSnapshot: EmojiDataSnapshot?
|
|
22
|
+
|
|
23
|
+
func cached() -> EmojiDataSnapshot? { cachedSnapshot }
|
|
24
|
+
|
|
25
|
+
@discardableResult
|
|
26
|
+
func store(_ snapshot: EmojiDataSnapshot) -> EmojiDataSnapshot {
|
|
27
|
+
if let existing = cachedSnapshot { return existing }
|
|
28
|
+
cachedSnapshot = snapshot
|
|
29
|
+
return snapshot
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
private final class EmojiDataCache {
|
|
34
|
+
static let shared = EmojiDataCache()
|
|
35
|
+
|
|
36
|
+
private let storage = EmojiDataCacheStorage()
|
|
37
|
+
private let stateLock = NSLock()
|
|
38
|
+
private var hasCachedDataSnapshot = false
|
|
39
|
+
|
|
40
|
+
private init() {}
|
|
41
|
+
|
|
42
|
+
var hasCachedData: Bool {
|
|
43
|
+
stateLock.withLock { hasCachedDataSnapshot }
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
func warm(loader: @escaping @Sendable () -> EmojiDataSnapshot) {
|
|
47
|
+
guard !hasCachedData else { return }
|
|
48
|
+
Task.detached(priority: .utility) {
|
|
49
|
+
_ = await self.load(loader: loader)
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
func load(loader: @escaping @Sendable () -> EmojiDataSnapshot) async -> EmojiDataSnapshot {
|
|
54
|
+
if let snapshot = await storage.cached() {
|
|
55
|
+
stateLock.withLock { hasCachedDataSnapshot = true }
|
|
56
|
+
return snapshot
|
|
57
|
+
}
|
|
58
|
+
// Compute outside the actor on a non-cooperative thread to avoid blocking the Swift concurrency thread pool
|
|
59
|
+
let snapshot: EmojiDataSnapshot = await withCheckedContinuation { continuation in
|
|
60
|
+
DispatchQueue.global(qos: .utility).async {
|
|
61
|
+
continuation.resume(returning: loader())
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
let result = await storage.store(snapshot)
|
|
65
|
+
stateLock.withLock { hasCachedDataSnapshot = true }
|
|
66
|
+
return result
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
private extension NSLock {
|
|
71
|
+
func withLock<T>(_ body: () -> T) -> T {
|
|
72
|
+
lock()
|
|
73
|
+
defer { unlock() }
|
|
74
|
+
return body()
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
15
78
|
// MARK: - EmojiSheetUIView
|
|
16
79
|
|
|
17
80
|
class EmojiSheetUIView: UIView,
|
|
@@ -80,9 +143,10 @@ class EmojiSheetUIView: UIView,
|
|
|
80
143
|
private var frequentlyUsedSection: EmojiSection?
|
|
81
144
|
private var localizedKeywords: [String: [String]] = [:]
|
|
82
145
|
private var currentSearchText: String?
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
//
|
|
146
|
+
private var loadTask: Task<Void, Never>?
|
|
147
|
+
private var searchTask: Task<Void, Never>?
|
|
148
|
+
// Search work is cancellable. The generation counter remains as a lightweight
|
|
149
|
+
// secondary guard so stale results never apply after a newer query wins.
|
|
86
150
|
private var searchGeneration: Int = 0
|
|
87
151
|
|
|
88
152
|
private let searchBar = EmojiSearchBar()
|
|
@@ -130,6 +194,11 @@ class EmojiSheetUIView: UIView,
|
|
|
130
194
|
fatalError("init(coder:) has not been implemented")
|
|
131
195
|
}
|
|
132
196
|
|
|
197
|
+
deinit {
|
|
198
|
+
loadTask?.cancel()
|
|
199
|
+
searchTask?.cancel()
|
|
200
|
+
}
|
|
201
|
+
|
|
133
202
|
// MARK: - Setup
|
|
134
203
|
|
|
135
204
|
private func setupViews() {
|
|
@@ -332,25 +401,19 @@ class EmojiSheetUIView: UIView,
|
|
|
332
401
|
|
|
333
402
|
// MARK: - Data Loading (cached across instances)
|
|
334
403
|
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
// and loadDataAsync() from racing on the same static vars.
|
|
338
|
-
private static let cacheQueue = DispatchQueue(label: "EmojiSheetCache")
|
|
339
|
-
private static var cachedSections: [EmojiSection]?
|
|
340
|
-
private static var cachedKeywords: [String: [String]]?
|
|
341
|
-
static var hasCachedData: Bool { cacheQueue.sync { cachedSections != nil && cachedKeywords != nil } }
|
|
404
|
+
private static let dataCache = EmojiDataCache.shared
|
|
405
|
+
static var hasCachedData: Bool { dataCache.hasCachedData }
|
|
342
406
|
|
|
343
407
|
static func warmCache() {
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
cachedKeywords = keywords
|
|
408
|
+
dataCache.warm {
|
|
409
|
+
EmojiDataSnapshot(
|
|
410
|
+
sections: parseEmojiJSON(),
|
|
411
|
+
keywords: loadAllKeywords()
|
|
412
|
+
)
|
|
350
413
|
}
|
|
351
414
|
}
|
|
352
415
|
|
|
353
|
-
private static func loadAllKeywords() -> [String: [String]] {
|
|
416
|
+
nonisolated private static func loadAllKeywords() -> [String: [String]] {
|
|
354
417
|
let bundle = Bundle(for: EmojiSheetUIView.self)
|
|
355
418
|
var merged: [String: [String]] = [:]
|
|
356
419
|
|
|
@@ -383,7 +446,7 @@ class EmojiSheetUIView: UIView,
|
|
|
383
446
|
return merged
|
|
384
447
|
}
|
|
385
448
|
|
|
386
|
-
private static func mergeKeywords(from url: URL, into merged: inout [String: [String]]) {
|
|
449
|
+
nonisolated private static func mergeKeywords(from url: URL, into merged: inout [String: [String]]) {
|
|
387
450
|
guard let data = try? Data(contentsOf: url),
|
|
388
451
|
let dict = try? JSONSerialization.jsonObject(with: data) as? [String: [String]]
|
|
389
452
|
else { return }
|
|
@@ -398,23 +461,20 @@ class EmojiSheetUIView: UIView,
|
|
|
398
461
|
}
|
|
399
462
|
|
|
400
463
|
func loadDataAsync() {
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
464
|
+
loadTask?.cancel()
|
|
465
|
+
loadTask = Task { [weak self] in
|
|
466
|
+
let snapshot = await Self.dataCache.load {
|
|
467
|
+
EmojiDataSnapshot(
|
|
468
|
+
sections: Self.parseEmojiJSON(),
|
|
469
|
+
keywords: Self.loadAllKeywords()
|
|
470
|
+
)
|
|
471
|
+
}
|
|
408
472
|
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
Self.cachedKeywords = keywords
|
|
415
|
-
DispatchQueue.main.async {
|
|
416
|
-
self.allSections = sections
|
|
417
|
-
self.localizedKeywords = keywords
|
|
473
|
+
guard !Task.isCancelled else { return }
|
|
474
|
+
await MainActor.run {
|
|
475
|
+
guard let self, !Task.isCancelled else { return }
|
|
476
|
+
self.allSections = snapshot.sections
|
|
477
|
+
self.localizedKeywords = snapshot.keywords
|
|
418
478
|
self.rebuildSections(searchText: nil)
|
|
419
479
|
}
|
|
420
480
|
}
|
|
@@ -422,7 +482,7 @@ class EmojiSheetUIView: UIView,
|
|
|
422
482
|
|
|
423
483
|
// iOS version → max Unicode emoji version. Source: https://emojipedia.org/apple
|
|
424
484
|
// Cases MUST remain ordered most-specific first (Swift evaluates top-to-bottom).
|
|
425
|
-
private static func maxSupportedEmojiVersion() -> Double {
|
|
485
|
+
nonisolated private static func maxSupportedEmojiVersion() -> Double {
|
|
426
486
|
let osVersion = ProcessInfo.processInfo.operatingSystemVersion
|
|
427
487
|
switch (osVersion.majorVersion, osVersion.minorVersion) {
|
|
428
488
|
case (18, 4...): return 16.0
|
|
@@ -437,7 +497,7 @@ class EmojiSheetUIView: UIView,
|
|
|
437
497
|
}
|
|
438
498
|
}
|
|
439
499
|
|
|
440
|
-
private static func parseEmojiJSON() -> [EmojiSection] {
|
|
500
|
+
nonisolated private static func parseEmojiJSON() -> [EmojiSection] {
|
|
441
501
|
let bundle = Bundle(for: EmojiSheetUIView.self)
|
|
442
502
|
guard let url = bundle.url(forResource: "emojis", withExtension: "json"),
|
|
443
503
|
let data = try? Data(contentsOf: url),
|
|
@@ -471,10 +531,6 @@ class EmojiSheetUIView: UIView,
|
|
|
471
531
|
}
|
|
472
532
|
}
|
|
473
533
|
|
|
474
|
-
private func loadLocalizedKeywords() -> [String: [String]] {
|
|
475
|
-
return Self.loadAllKeywords()
|
|
476
|
-
}
|
|
477
|
-
|
|
478
534
|
private var filteredAllSections: [EmojiSection] {
|
|
479
535
|
guard !excludeEmojis.isEmpty else { return allSections }
|
|
480
536
|
return allSections.map { section in
|
|
@@ -494,6 +550,7 @@ class EmojiSheetUIView: UIView,
|
|
|
494
550
|
|
|
495
551
|
private func rebuildSections(searchText: String?) {
|
|
496
552
|
currentSearchText = searchText
|
|
553
|
+
searchTask?.cancel()
|
|
497
554
|
|
|
498
555
|
guard let search = searchText, !search.isEmpty else {
|
|
499
556
|
searchGeneration += 1
|
|
@@ -524,15 +581,15 @@ class EmojiSheetUIView: UIView,
|
|
|
524
581
|
let sections = filteredAllSections
|
|
525
582
|
let keywords = localizedKeywords
|
|
526
583
|
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
let searchVariants = self.normalizedSearchVariants(search)
|
|
584
|
+
searchTask = Task(priority: .userInitiated) { [weak self, sections, keywords, search, generation] in
|
|
585
|
+
let searchVariants = Self.normalizedSearchVariants(search)
|
|
530
586
|
var scored: [(item: EmojiItem, score: Int)] = []
|
|
531
587
|
|
|
532
588
|
for section in sections {
|
|
533
|
-
|
|
589
|
+
if Task.isCancelled { return }
|
|
534
590
|
for item in section.data {
|
|
535
|
-
|
|
591
|
+
if Task.isCancelled { return }
|
|
592
|
+
let score = Self.relevanceScore(
|
|
536
593
|
item: item,
|
|
537
594
|
searchVariants: searchVariants,
|
|
538
595
|
localizedKeywords: keywords
|
|
@@ -543,13 +600,12 @@ class EmojiSheetUIView: UIView,
|
|
|
543
600
|
}
|
|
544
601
|
}
|
|
545
602
|
|
|
546
|
-
// Sort by relevance score descending, then by original order for ties
|
|
547
603
|
scored.sort { $0.score > $1.score }
|
|
548
604
|
let matchedItems = scored.map { $0.item }
|
|
549
605
|
|
|
550
|
-
guard
|
|
551
|
-
|
|
552
|
-
guard let self, generation == self.searchGeneration else { return }
|
|
606
|
+
guard !Task.isCancelled else { return }
|
|
607
|
+
await MainActor.run {
|
|
608
|
+
guard let self, !Task.isCancelled, generation == self.searchGeneration else { return }
|
|
553
609
|
var resultSections: [EmojiSection] = []
|
|
554
610
|
if !matchedItems.isEmpty {
|
|
555
611
|
resultSections.append(EmojiSection(title: "search_results", data: matchedItems))
|
|
@@ -563,7 +619,7 @@ class EmojiSheetUIView: UIView,
|
|
|
563
619
|
}
|
|
564
620
|
}
|
|
565
621
|
|
|
566
|
-
private static func localizedKeywordsForEmoji(_ emoji: String, in dict: [String: [String]]) -> [String] {
|
|
622
|
+
nonisolated private static func localizedKeywordsForEmoji(_ emoji: String, in dict: [String: [String]]) -> [String] {
|
|
567
623
|
if let kw = dict[emoji] { return kw }
|
|
568
624
|
let stripped = String(emoji.unicodeScalars.filter { $0.value != 0xFE0E && $0.value != 0xFE0F })
|
|
569
625
|
if stripped != emoji, let kw = dict[stripped] { return kw }
|
|
@@ -574,7 +630,7 @@ class EmojiSheetUIView: UIView,
|
|
|
574
630
|
// 100 = exact name match, 90 = name starts with, 80 = exact keyword,
|
|
575
631
|
// 70 = keyword starts with, 50 = name contains, 30 = keyword contains,
|
|
576
632
|
// 10 = localized keyword contains. Returns 0 for no match.
|
|
577
|
-
private func relevanceScore(
|
|
633
|
+
nonisolated private static func relevanceScore(
|
|
578
634
|
item: EmojiItem,
|
|
579
635
|
searchVariants: [String],
|
|
580
636
|
localizedKeywords: [String: [String]]
|
|
@@ -630,7 +686,7 @@ class EmojiSheetUIView: UIView,
|
|
|
630
686
|
return true
|
|
631
687
|
}
|
|
632
688
|
|
|
633
|
-
return normalizedSearchVariants(originalText)
|
|
689
|
+
return Self.normalizedSearchVariants(originalText)
|
|
634
690
|
.contains { candidateVariant in
|
|
635
691
|
candidateVariant != normalizedText &&
|
|
636
692
|
searchVariants.contains(where: { candidateVariant.contains($0) })
|
|
@@ -677,7 +733,7 @@ class EmojiSheetUIView: UIView,
|
|
|
677
733
|
UserDefaults.standard.set(dict, forKey: Self.frequentlyUsedKey)
|
|
678
734
|
}
|
|
679
735
|
|
|
680
|
-
private func normalizeSearchText(_ text: String) -> String {
|
|
736
|
+
nonisolated private static func normalizeSearchText(_ text: String) -> String {
|
|
681
737
|
text
|
|
682
738
|
.precomposedStringWithCompatibilityMapping
|
|
683
739
|
.folding(
|
|
@@ -688,7 +744,7 @@ class EmojiSheetUIView: UIView,
|
|
|
688
744
|
.lowercased(with: .current)
|
|
689
745
|
}
|
|
690
746
|
|
|
691
|
-
private func normalizedSearchVariants(_ text: String) -> [String] {
|
|
747
|
+
nonisolated private static func normalizedSearchVariants(_ text: String) -> [String] {
|
|
692
748
|
let normalized = normalizeSearchText(text)
|
|
693
749
|
let transliterated = text.applyingTransform(.toLatin, reverse: false)
|
|
694
750
|
.map(normalizeSearchText)
|
|
@@ -59,7 +59,18 @@ function flattenOptions(options) {
|
|
|
59
59
|
const NativeEmojiSheet = (0, _expo.requireNativeModule)('EmojiSheet');
|
|
60
60
|
var _default = exports.default = {
|
|
61
61
|
present(options = {}) {
|
|
62
|
-
|
|
62
|
+
let subscription = null;
|
|
63
|
+
if (options.onOpen) {
|
|
64
|
+
subscription = NativeEmojiSheet.addListener('onSheetOpened', () => {
|
|
65
|
+
options.onOpen();
|
|
66
|
+
subscription?.remove();
|
|
67
|
+
subscription = null;
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
return NativeEmojiSheet.present(flattenOptions(options)).finally(() => {
|
|
71
|
+
subscription?.remove();
|
|
72
|
+
subscription = null;
|
|
73
|
+
});
|
|
63
74
|
},
|
|
64
75
|
dismiss() {
|
|
65
76
|
return NativeEmojiSheet.dismiss();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_expo","require","flattenOptions","options","flat","theme","backgroundColor","searchBarBackgroundColor","textColor","textSecondaryColor","accentColor","dividerColor","searchTextColor","placeholderTextColor","selectionColor","categoryIconColor","categoryActiveIconColor","categoryActiveBackgroundColor","handleColor","categoryBarBackgroundColor","translations","searchPlaceholder","noResultsText","categoryNames","layoutDirection","snapPoints","categoryBarPosition","columns","emojiSize","recentLimit","showSearch","showRecents","enableSkinTones","enableHaptics","enableAnimations","gestureEnabled","backdropOpacity","excludeEmojis","NativeEmojiSheet","requireNativeModule","_default","exports","default","present","dismiss","clearRecents","clearSkinTonePreferences"],"sourceRoot":"../../src","sources":["EmojiSheetModule.ts"],"mappings":";;;;;;AAAA,IAAAA,KAAA,GAAAC,OAAA;AAKA,SAASC,cAAcA,CAACC,OAAiC,EAAiB;EACxE,MAAMC,IAAmB,GAAG,CAAC,CAAC;;EAE9B;EACA,IAAID,OAAO,CAACE,KAAK,EAAE;IACjB,IAAI,OAAOF,OAAO,CAACE,KAAK,KAAK,QAAQ,EAAE;MACrCD,IAAI,CAACC,KAAK,GAAGF,OAAO,CAACE,KAAK;IAC5B,CAAC,MAAM;MACL,MAAMA,KAAK,GAAGF,OAAO,CAACE,KAAwB;MAC9CD,IAAI,CAACC,KAAK,GAAG,QAAQ;MACrBD,IAAI,CAACE,eAAe,GAAGD,KAAK,CAACC,eAAe;MAC5CF,IAAI,CAACG,wBAAwB,GAAGF,KAAK,CAACE,wBAAwB;MAC9DH,IAAI,CAACI,SAAS,GAAGH,KAAK,CAACG,SAAS;MAChCJ,IAAI,CAACK,kBAAkB,GAAGJ,KAAK,CAACI,kBAAkB;MAClDL,IAAI,CAACM,WAAW,GAAGL,KAAK,CAACK,WAAW;MACpCN,IAAI,CAACO,YAAY,GAAGN,KAAK,CAACM,YAAY;MACtC,IAAIN,KAAK,CAACO,eAAe,EAAER,IAAI,CAACQ,eAAe,GAAGP,KAAK,CAACO,eAAe;MACvE,IAAIP,KAAK,CAACQ,oBAAoB,EAAET,IAAI,CAACS,oBAAoB,GAAGR,KAAK,CAACQ,oBAAoB;MACtF,IAAIR,KAAK,CAACS,cAAc,EAAEV,IAAI,CAACU,cAAc,GAAGT,KAAK,CAACS,cAAc;MACpE,IAAIT,KAAK,CAACU,iBAAiB,EAAEX,IAAI,CAACW,iBAAiB,GAAGV,KAAK,CAACU,iBAAiB;MAC7E,IAAIV,KAAK,CAACW,uBAAuB,EAAEZ,IAAI,CAACY,uBAAuB,GAAGX,KAAK,CAACW,uBAAuB;MAC/F,IAAIX,KAAK,CAACY,6BAA6B,EAAEb,IAAI,CAACa,6BAA6B,GAAGZ,KAAK,CAACY,6BAA6B;MACjH,IAAIZ,KAAK,CAACa,WAAW,EAAEd,IAAI,CAACc,WAAW,GAAGb,KAAK,CAACa,WAAW;MAC3D,IAAIb,KAAK,CAACc,0BAA0B,EAAEf,IAAI,CAACe,0BAA0B,GAAGd,KAAK,CAACc,0BAA0B;IAC1G;EACF;;EAEA;EACA,IAAIhB,OAAO,CAACiB,YAAY,EAAE;IACxB,IAAIjB,OAAO,CAACiB,YAAY,CAACC,iBAAiB,EAAEjB,IAAI,CAACiB,iBAAiB,GAAGlB,OAAO,CAACiB,YAAY,CAACC,iBAAiB;IAC3G,IAAIlB,OAAO,CAACiB,YAAY,CAACE,aAAa,EAAElB,IAAI,CAACkB,aAAa,GAAGnB,OAAO,CAACiB,YAAY,CAACE,aAAa;IAC/F,IAAInB,OAAO,CAACiB,YAAY,CAACG,aAAa,EAAEnB,IAAI,CAACmB,aAAa,GAAGpB,OAAO,CAACiB,YAAY,CAACG,aAAa;EACjG;;EAEA;EACA,IAAIpB,OAAO,CAACqB,eAAe,EAAEpB,IAAI,CAACoB,eAAe,GAAGrB,OAAO,CAACqB,eAAe;EAC3E,IAAIrB,OAAO,CAACsB,UAAU,EAAErB,IAAI,CAACqB,UAAU,GAAGtB,OAAO,CAACsB,UAAU;EAC5D,IAAItB,OAAO,CAACuB,mBAAmB,EAAEtB,IAAI,CAACsB,mBAAmB,GAAGvB,OAAO,CAACuB,mBAAmB;EACvF,IAAIvB,OAAO,CAACwB,OAAO,IAAI,IAAI,EAAEvB,IAAI,CAACuB,OAAO,GAAGxB,OAAO,CAACwB,OAAO;EAC3D,IAAIxB,OAAO,CAACyB,SAAS,IAAI,IAAI,EAAExB,IAAI,CAACwB,SAAS,GAAGzB,OAAO,CAACyB,SAAS;EACjE,IAAIzB,OAAO,CAAC0B,WAAW,IAAI,IAAI,EAAEzB,IAAI,CAACyB,WAAW,GAAG1B,OAAO,CAAC0B,WAAW;EACvE,IAAI1B,OAAO,CAAC2B,UAAU,IAAI,IAAI,EAAE1B,IAAI,CAAC0B,UAAU,GAAG3B,OAAO,CAAC2B,UAAU;EACpE,IAAI3B,OAAO,CAAC4B,WAAW,IAAI,IAAI,EAAE3B,IAAI,CAAC2B,WAAW,GAAG5B,OAAO,CAAC4B,WAAW;EACvE,IAAI5B,OAAO,CAAC6B,eAAe,IAAI,IAAI,EAAE5B,IAAI,CAAC4B,eAAe,GAAG7B,OAAO,CAAC6B,eAAe;EACnF,IAAI7B,OAAO,CAAC8B,aAAa,IAAI,IAAI,EAAE7B,IAAI,CAAC6B,aAAa,GAAG9B,OAAO,CAAC8B,aAAa;EAC7E,IAAI9B,OAAO,CAAC+B,gBAAgB,IAAI,IAAI,EAAE9B,IAAI,CAAC8B,gBAAgB,GAAG/B,OAAO,CAAC+B,gBAAgB;EACtF,IAAI/B,OAAO,CAACgC,cAAc,IAAI,IAAI,EAAE/B,IAAI,CAAC+B,cAAc,GAAGhC,OAAO,CAACgC,cAAc;EAChF,IAAIhC,OAAO,CAACiC,eAAe,IAAI,IAAI,EAAEhC,IAAI,CAACgC,eAAe,GAAGjC,OAAO,CAACiC,eAAe;EACnF,IAAIjC,OAAO,CAACkC,aAAa,EAAEjC,IAAI,CAACiC,aAAa,GAAGlC,OAAO,CAACkC,aAAa;EAErE,OAAOjC,IAAI;AACb;AASA,MAAMkC,gBAAgB,GAAG,IAAAC,yBAAmB,EAAuB,YAAY,CAAC;AAAC,IAAAC,QAAA,GAAAC,OAAA,CAAAC,OAAA,GAIlE;EACbC,OAAOA,CAACxC,OAAiC,GAAG,CAAC,CAAC,EAA6B;IACzE,
|
|
1
|
+
{"version":3,"names":["_expo","require","flattenOptions","options","flat","theme","backgroundColor","searchBarBackgroundColor","textColor","textSecondaryColor","accentColor","dividerColor","searchTextColor","placeholderTextColor","selectionColor","categoryIconColor","categoryActiveIconColor","categoryActiveBackgroundColor","handleColor","categoryBarBackgroundColor","translations","searchPlaceholder","noResultsText","categoryNames","layoutDirection","snapPoints","categoryBarPosition","columns","emojiSize","recentLimit","showSearch","showRecents","enableSkinTones","enableHaptics","enableAnimations","gestureEnabled","backdropOpacity","excludeEmojis","NativeEmojiSheet","requireNativeModule","_default","exports","default","present","subscription","onOpen","addListener","remove","finally","dismiss","clearRecents","clearSkinTonePreferences"],"sourceRoot":"../../src","sources":["EmojiSheetModule.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -10,6 +10,7 @@ const NativeView = (0, _expo.requireNativeView)('EmojiSheet');
|
|
|
10
10
|
function EmojiSheetView({
|
|
11
11
|
onEmojiSelected,
|
|
12
12
|
onDismiss,
|
|
13
|
+
onOpen,
|
|
13
14
|
theme,
|
|
14
15
|
translations,
|
|
15
16
|
layoutDirection,
|
|
@@ -51,9 +52,10 @@ function EmojiSheetView({
|
|
|
51
52
|
onEmojiSelected: ({
|
|
52
53
|
nativeEvent
|
|
53
54
|
}) => {
|
|
54
|
-
onEmojiSelected(nativeEvent.emoji);
|
|
55
|
+
onEmojiSelected(nativeEvent.emoji, nativeEvent.name, nativeEvent.id);
|
|
55
56
|
},
|
|
56
|
-
onDismiss: onDismiss ? () => onDismiss() : undefined
|
|
57
|
+
onDismiss: onDismiss ? () => onDismiss() : undefined,
|
|
58
|
+
onOpen: onOpen ? () => onOpen() : undefined
|
|
57
59
|
});
|
|
58
60
|
}
|
|
59
61
|
//# sourceMappingURL=EmojiSheetView.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_expo","require","_jsxRuntime","NativeView","requireNativeView","EmojiSheetView","onEmojiSelected","onDismiss","theme","translations","layoutDirection","categoryBarPosition","columns","emojiSize","recentLimit","showSearch","showRecents","enableSkinTones","enableHaptics","enableAnimations","excludeEmojis","rest","resolvedTheme","jsx","searchPlaceholder","noResultsText","categoryNames","nativeEvent","emoji","undefined"],"sourceRoot":"../../src","sources":["EmojiSheetView.tsx"],"mappings":";;;;;;AAAA,IAAAA,KAAA,GAAAC,OAAA;AAAyC,IAAAC,WAAA,GAAAD,OAAA;AAOzC,MAAME,UAA0D,GAC9D,IAAAC,uBAAiB,EAAC,YAAY,CAAC;AAElB,SAASC,cAAcA,CAAC;EACrCC,eAAe;EACfC,SAAS;EACTC,KAAK;EACLC,YAAY;EACZC,eAAe;EACfC,mBAAmB;EACnBC,OAAO;EACPC,SAAS;EACTC,WAAW;EACXC,UAAU;EACVC,WAAW;EACXC,eAAe;EACfC,aAAa;EACbC,gBAAgB;EAChBC,aAAa;EACb,GAAGC;AACgB,CAAC,EAAE;EACtB,MAAMC,aAAa,GAAG,OAAOd,KAAK,KAAK,QAAQ,GAAG,QAAQ,GAAGA,KAAK;;EAElE;EACA;EACA;;EAEA,oBACE,
|
|
1
|
+
{"version":3,"names":["_expo","require","_jsxRuntime","NativeView","requireNativeView","EmojiSheetView","onEmojiSelected","onDismiss","onOpen","theme","translations","layoutDirection","categoryBarPosition","columns","emojiSize","recentLimit","showSearch","showRecents","enableSkinTones","enableHaptics","enableAnimations","excludeEmojis","rest","resolvedTheme","jsx","searchPlaceholder","noResultsText","categoryNames","nativeEvent","emoji","name","id","undefined"],"sourceRoot":"../../src","sources":["EmojiSheetView.tsx"],"mappings":";;;;;;AAAA,IAAAA,KAAA,GAAAC,OAAA;AAAyC,IAAAC,WAAA,GAAAD,OAAA;AAOzC,MAAME,UAA0D,GAC9D,IAAAC,uBAAiB,EAAC,YAAY,CAAC;AAElB,SAASC,cAAcA,CAAC;EACrCC,eAAe;EACfC,SAAS;EACTC,MAAM;EACNC,KAAK;EACLC,YAAY;EACZC,eAAe;EACfC,mBAAmB;EACnBC,OAAO;EACPC,SAAS;EACTC,WAAW;EACXC,UAAU;EACVC,WAAW;EACXC,eAAe;EACfC,aAAa;EACbC,gBAAgB;EAChBC,aAAa;EACb,GAAGC;AACgB,CAAC,EAAE;EACtB,MAAMC,aAAa,GAAG,OAAOd,KAAK,KAAK,QAAQ,GAAG,QAAQ,GAAGA,KAAK;;EAElE;EACA;EACA;;EAEA,oBACE,IAAAP,WAAA,CAAAsB,GAAA,EAACrB,UAAU;IAAA,GACLmB,IAAI;IACRb,KAAK,EAAEc,aAAc;IACrBZ,eAAe,EAAEA,eAAgB;IACjCC,mBAAmB,EAAEA,mBAAoB;IACzCC,OAAO,EAAEA,OAAQ;IACjBC,SAAS,EAAEA,SAAU;IACrBC,WAAW,EAAEA,WAAY;IACzBC,UAAU,EAAEA,UAAW;IACvBC,WAAW,EAAEA,WAAY;IACzBC,eAAe,EAAEA,eAAgB;IACjCC,aAAa,EAAEA,aAAc;IAC7BC,gBAAgB,EAAEA,gBAAiB;IACnCC,aAAa,EAAEA,aAAc;IAC7BI,iBAAiB,EAAEf,YAAY,EAAEe,iBAAkB;IACnDC,aAAa,EAAEhB,YAAY,EAAEgB,aAAc;IAC3CC,aAAa,EAAEjB,YAAY,EAAEiB,aAAc;IAC3CrB,eAAe,EAAEA,CAAC;MAAEsB;IAAY,CAAC,KAAK;MACpCtB,eAAe,CAACsB,WAAW,CAACC,KAAK,EAAED,WAAW,CAACE,IAAI,EAAEF,WAAW,CAACG,EAAE,CAAC;IACtE,CAAE;IACFxB,SAAS,EAAEA,SAAS,GAAG,MAAMA,SAAS,CAAC,CAAC,GAAGyB,SAAU;IACrDxB,MAAM,EAAEA,MAAM,GAAG,MAAMA,MAAM,CAAC,CAAC,GAAGwB;EAAU,CAC7C,CAAC;AAEN","ignoreList":[]}
|
|
@@ -55,7 +55,18 @@ function flattenOptions(options) {
|
|
|
55
55
|
const NativeEmojiSheet = requireNativeModule('EmojiSheet');
|
|
56
56
|
export default {
|
|
57
57
|
present(options = {}) {
|
|
58
|
-
|
|
58
|
+
let subscription = null;
|
|
59
|
+
if (options.onOpen) {
|
|
60
|
+
subscription = NativeEmojiSheet.addListener('onSheetOpened', () => {
|
|
61
|
+
options.onOpen();
|
|
62
|
+
subscription?.remove();
|
|
63
|
+
subscription = null;
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
return NativeEmojiSheet.present(flattenOptions(options)).finally(() => {
|
|
67
|
+
subscription?.remove();
|
|
68
|
+
subscription = null;
|
|
69
|
+
});
|
|
59
70
|
},
|
|
60
71
|
dismiss() {
|
|
61
72
|
return NativeEmojiSheet.dismiss();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["NativeModule","requireNativeModule","flattenOptions","options","flat","theme","backgroundColor","searchBarBackgroundColor","textColor","textSecondaryColor","accentColor","dividerColor","searchTextColor","placeholderTextColor","selectionColor","categoryIconColor","categoryActiveIconColor","categoryActiveBackgroundColor","handleColor","categoryBarBackgroundColor","translations","searchPlaceholder","noResultsText","categoryNames","layoutDirection","snapPoints","categoryBarPosition","columns","emojiSize","recentLimit","showSearch","showRecents","enableSkinTones","enableHaptics","enableAnimations","gestureEnabled","backdropOpacity","excludeEmojis","NativeEmojiSheet","present","dismiss","clearRecents","clearSkinTonePreferences"],"sourceRoot":"../../src","sources":["EmojiSheetModule.ts"],"mappings":"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
|
|
1
|
+
{"version":3,"names":["NativeModule","requireNativeModule","flattenOptions","options","flat","theme","backgroundColor","searchBarBackgroundColor","textColor","textSecondaryColor","accentColor","dividerColor","searchTextColor","placeholderTextColor","selectionColor","categoryIconColor","categoryActiveIconColor","categoryActiveBackgroundColor","handleColor","categoryBarBackgroundColor","translations","searchPlaceholder","noResultsText","categoryNames","layoutDirection","snapPoints","categoryBarPosition","columns","emojiSize","recentLimit","showSearch","showRecents","enableSkinTones","enableHaptics","enableAnimations","gestureEnabled","backdropOpacity","excludeEmojis","NativeEmojiSheet","present","subscription","onOpen","addListener","remove","finally","dismiss","clearRecents","clearSkinTonePreferences"],"sourceRoot":"../../src","sources":["EmojiSheetModule.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -6,6 +6,7 @@ const NativeView = requireNativeView('EmojiSheet');
|
|
|
6
6
|
export default function EmojiSheetView({
|
|
7
7
|
onEmojiSelected,
|
|
8
8
|
onDismiss,
|
|
9
|
+
onOpen,
|
|
9
10
|
theme,
|
|
10
11
|
translations,
|
|
11
12
|
layoutDirection,
|
|
@@ -47,9 +48,10 @@ export default function EmojiSheetView({
|
|
|
47
48
|
onEmojiSelected: ({
|
|
48
49
|
nativeEvent
|
|
49
50
|
}) => {
|
|
50
|
-
onEmojiSelected(nativeEvent.emoji);
|
|
51
|
+
onEmojiSelected(nativeEvent.emoji, nativeEvent.name, nativeEvent.id);
|
|
51
52
|
},
|
|
52
|
-
onDismiss: onDismiss ? () => onDismiss() : undefined
|
|
53
|
+
onDismiss: onDismiss ? () => onDismiss() : undefined,
|
|
54
|
+
onOpen: onOpen ? () => onOpen() : undefined
|
|
53
55
|
});
|
|
54
56
|
}
|
|
55
57
|
//# sourceMappingURL=EmojiSheetView.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["requireNativeView","jsx","_jsx","NativeView","EmojiSheetView","onEmojiSelected","onDismiss","theme","translations","layoutDirection","categoryBarPosition","columns","emojiSize","recentLimit","showSearch","showRecents","enableSkinTones","enableHaptics","enableAnimations","excludeEmojis","rest","resolvedTheme","searchPlaceholder","noResultsText","categoryNames","nativeEvent","emoji","undefined"],"sourceRoot":"../../src","sources":["EmojiSheetView.tsx"],"mappings":";;AAAA,SAASA,iBAAiB,QAAQ,MAAM;AAAC,SAAAC,GAAA,IAAAC,IAAA;AAOzC,MAAMC,UAA0D,GAC9DH,iBAAiB,CAAC,YAAY,CAAC;AAEjC,eAAe,SAASI,cAAcA,CAAC;EACrCC,eAAe;EACfC,SAAS;EACTC,KAAK;EACLC,YAAY;EACZC,eAAe;EACfC,mBAAmB;EACnBC,OAAO;EACPC,SAAS;EACTC,WAAW;EACXC,UAAU;EACVC,WAAW;EACXC,eAAe;EACfC,aAAa;EACbC,gBAAgB;EAChBC,aAAa;EACb,GAAGC;AACgB,CAAC,EAAE;EACtB,MAAMC,aAAa,GAAG,OAAOd,KAAK,KAAK,QAAQ,GAAG,QAAQ,GAAGA,KAAK;;EAElE;EACA;EACA;;EAEA,
|
|
1
|
+
{"version":3,"names":["requireNativeView","jsx","_jsx","NativeView","EmojiSheetView","onEmojiSelected","onDismiss","onOpen","theme","translations","layoutDirection","categoryBarPosition","columns","emojiSize","recentLimit","showSearch","showRecents","enableSkinTones","enableHaptics","enableAnimations","excludeEmojis","rest","resolvedTheme","searchPlaceholder","noResultsText","categoryNames","nativeEvent","emoji","name","id","undefined"],"sourceRoot":"../../src","sources":["EmojiSheetView.tsx"],"mappings":";;AAAA,SAASA,iBAAiB,QAAQ,MAAM;AAAC,SAAAC,GAAA,IAAAC,IAAA;AAOzC,MAAMC,UAA0D,GAC9DH,iBAAiB,CAAC,YAAY,CAAC;AAEjC,eAAe,SAASI,cAAcA,CAAC;EACrCC,eAAe;EACfC,SAAS;EACTC,MAAM;EACNC,KAAK;EACLC,YAAY;EACZC,eAAe;EACfC,mBAAmB;EACnBC,OAAO;EACPC,SAAS;EACTC,WAAW;EACXC,UAAU;EACVC,WAAW;EACXC,eAAe;EACfC,aAAa;EACbC,gBAAgB;EAChBC,aAAa;EACb,GAAGC;AACgB,CAAC,EAAE;EACtB,MAAMC,aAAa,GAAG,OAAOd,KAAK,KAAK,QAAQ,GAAG,QAAQ,GAAGA,KAAK;;EAElE;EACA;EACA;;EAEA,oBACEN,IAAA,CAACC,UAAU;IAAA,GACLkB,IAAI;IACRb,KAAK,EAAEc,aAAc;IACrBZ,eAAe,EAAEA,eAAgB;IACjCC,mBAAmB,EAAEA,mBAAoB;IACzCC,OAAO,EAAEA,OAAQ;IACjBC,SAAS,EAAEA,SAAU;IACrBC,WAAW,EAAEA,WAAY;IACzBC,UAAU,EAAEA,UAAW;IACvBC,WAAW,EAAEA,WAAY;IACzBC,eAAe,EAAEA,eAAgB;IACjCC,aAAa,EAAEA,aAAc;IAC7BC,gBAAgB,EAAEA,gBAAiB;IACnCC,aAAa,EAAEA,aAAc;IAC7BG,iBAAiB,EAAEd,YAAY,EAAEc,iBAAkB;IACnDC,aAAa,EAAEf,YAAY,EAAEe,aAAc;IAC3CC,aAAa,EAAEhB,YAAY,EAAEgB,aAAc;IAC3CpB,eAAe,EAAEA,CAAC;MAAEqB;IAAY,CAAC,KAAK;MACpCrB,eAAe,CAACqB,WAAW,CAACC,KAAK,EAAED,WAAW,CAACE,IAAI,EAAEF,WAAW,CAACG,EAAE,CAAC;IACtE,CAAE;IACFvB,SAAS,EAAEA,SAAS,GAAG,MAAMA,SAAS,CAAC,CAAC,GAAGwB,SAAU;IACrDvB,MAAM,EAAEA,MAAM,GAAG,MAAMA,MAAM,CAAC,CAAC,GAAGuB;EAAU,CAC7C,CAAC;AAEN","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EmojiSheetModule.d.ts","sourceRoot":"","sources":["../../src/EmojiSheetModule.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,wBAAwB,EAAmB,MAAM,0BAA0B,CAAC;AAkE5G,YAAY,EAAE,gBAAgB,EAAE,CAAC;;sBAGd,wBAAwB,GAAQ,OAAO,CAAC,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"EmojiSheetModule.d.ts","sourceRoot":"","sources":["../../src/EmojiSheetModule.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,wBAAwB,EAAmB,MAAM,0BAA0B,CAAC;AAkE5G,YAAY,EAAE,gBAAgB,EAAE,CAAC;;sBAGd,wBAAwB,GAAQ,OAAO,CAAC,gBAAgB,CAAC;eAgB/D,OAAO,CAAC,IAAI,CAAC;oBAGR,OAAO,CAAC,IAAI,CAAC;gCAGD,OAAO,CAAC,IAAI,CAAC;;AAvB3C,wBA0BE"}
|
|
@@ -38,22 +38,30 @@ export type EmojiSheetPresentOptions = {
|
|
|
38
38
|
gestureEnabled?: boolean;
|
|
39
39
|
backdropOpacity?: number;
|
|
40
40
|
excludeEmojis?: string[];
|
|
41
|
+
onOpen?: () => void;
|
|
41
42
|
};
|
|
42
43
|
export type EmojiSheetResult = {
|
|
43
44
|
emoji: string;
|
|
45
|
+
name: string;
|
|
46
|
+
id: string;
|
|
44
47
|
cancelled?: never;
|
|
45
48
|
} | {
|
|
46
49
|
cancelled: true;
|
|
47
50
|
emoji?: never;
|
|
51
|
+
name?: never;
|
|
52
|
+
id?: never;
|
|
48
53
|
};
|
|
49
54
|
export type EmojiSelectionListener = (event: {
|
|
50
55
|
nativeEvent: {
|
|
51
56
|
emoji: string;
|
|
57
|
+
name: string;
|
|
58
|
+
id: string;
|
|
52
59
|
};
|
|
53
60
|
}) => void;
|
|
54
61
|
export type EmojiSheetViewProps = ViewProps & {
|
|
55
|
-
onEmojiSelected: (emoji: string) => void;
|
|
62
|
+
onEmojiSelected: (emoji: string, name: string, id: string) => void;
|
|
56
63
|
onDismiss?: () => void;
|
|
64
|
+
onOpen?: () => void;
|
|
57
65
|
theme?: EmojiSheetTheme | 'dark' | 'light' | 'system';
|
|
58
66
|
translations?: EmojiSheetTranslations;
|
|
59
67
|
layoutDirection?: 'ltr' | 'rtl' | 'auto';
|
|
@@ -73,6 +81,9 @@ export type EmojiSheetNativeViewProps = ViewProps & {
|
|
|
73
81
|
onDismiss?: (event: {
|
|
74
82
|
nativeEvent: {};
|
|
75
83
|
}) => void;
|
|
84
|
+
onOpen?: (event: {
|
|
85
|
+
nativeEvent: {};
|
|
86
|
+
}) => void;
|
|
76
87
|
theme?: string;
|
|
77
88
|
layoutDirection?: 'ltr' | 'rtl' | 'auto';
|
|
78
89
|
categoryBarPosition?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EmojiSheetModule.types.d.ts","sourceRoot":"","sources":["../../src/EmojiSheetModule.types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C,MAAM,MAAM,eAAe,GAAG;IAC5B,eAAe,EAAE,MAAM,CAAC;IACxB,wBAAwB,EAAE,MAAM,CAAC;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,6BAA6B,CAAC,EAAE,MAAM,CAAC;IACvC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,0BAA0B,CAAC,EAAE,MAAM,CAAC;CACrC,CAAC;AAEF,MAAM,MAAM,aAAa,GACrB,iBAAiB,GACjB,iBAAiB,GACjB,aAAa,GACb,gBAAgB,GAChB,YAAY,GACZ,eAAe,GACf,YAAY,GACZ,SAAS,GACT,SAAS,GACT,OAAO,CAAC;AAEZ,MAAM,MAAM,sBAAsB,GAAG;IACnC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC,CAAC;CACxD,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG;IACrC,KAAK,CAAC,EAAE,eAAe,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAC;IACtD,YAAY,CAAC,EAAE,sBAAsB,CAAC;IACtC,eAAe,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,MAAM,CAAC;IACzC,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,mBAAmB,CAAC,EAAE,KAAK,GAAG,QAAQ,CAAC;IACvC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"EmojiSheetModule.types.d.ts","sourceRoot":"","sources":["../../src/EmojiSheetModule.types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { EmojiSheetViewProps } from './EmojiSheetModule.types';
|
|
2
|
-
export default function EmojiSheetView({ onEmojiSelected, onDismiss, theme, translations, layoutDirection, categoryBarPosition, columns, emojiSize, recentLimit, showSearch, showRecents, enableSkinTones, enableHaptics, enableAnimations, excludeEmojis, ...rest }: EmojiSheetViewProps): import("react/jsx-runtime").JSX.Element;
|
|
2
|
+
export default function EmojiSheetView({ onEmojiSelected, onDismiss, onOpen, theme, translations, layoutDirection, categoryBarPosition, columns, emojiSize, recentLimit, showSearch, showRecents, enableSkinTones, enableHaptics, enableAnimations, excludeEmojis, ...rest }: EmojiSheetViewProps): import("react/jsx-runtime").JSX.Element;
|
|
3
3
|
//# sourceMappingURL=EmojiSheetView.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EmojiSheetView.d.ts","sourceRoot":"","sources":["../../src/EmojiSheetView.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAEV,mBAAmB,EACpB,MAAM,0BAA0B,CAAC;AAKlC,MAAM,CAAC,OAAO,UAAU,cAAc,CAAC,EACrC,eAAe,EACf,SAAS,EACT,KAAK,EACL,YAAY,EACZ,eAAe,EACf,mBAAmB,EACnB,OAAO,EACP,SAAS,EACT,WAAW,EACX,UAAU,EACV,WAAW,EACX,eAAe,EACf,aAAa,EACb,gBAAgB,EAChB,aAAa,EACb,GAAG,IAAI,EACR,EAAE,mBAAmB,
|
|
1
|
+
{"version":3,"file":"EmojiSheetView.d.ts","sourceRoot":"","sources":["../../src/EmojiSheetView.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAEV,mBAAmB,EACpB,MAAM,0BAA0B,CAAC;AAKlC,MAAM,CAAC,OAAO,UAAU,cAAc,CAAC,EACrC,eAAe,EACf,SAAS,EACT,MAAM,EACN,KAAK,EACL,YAAY,EACZ,eAAe,EACf,mBAAmB,EACnB,OAAO,EACP,SAAS,EACT,WAAW,EACX,UAAU,EACV,WAAW,EACX,eAAe,EACf,aAAa,EACb,gBAAgB,EAChB,aAAa,EACb,GAAG,IAAI,EACR,EAAE,mBAAmB,2CAgCrB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expo-native-sheet-emojis",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
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",
|
|
@@ -41,42 +41,58 @@ const withEmojiSheet = (config, props) => {
|
|
|
41
41
|
if (searchLocales.length === 0) {
|
|
42
42
|
return config;
|
|
43
43
|
}
|
|
44
|
-
// iOS:
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
44
|
+
// iOS: Add locale files directly to the Xcode project's Copy Bundle Resources phase.
|
|
45
|
+
// This avoids the pod-install-time limitation of s.resources glob evaluation —
|
|
46
|
+
// files are added to the .xcodeproj by prebuild and survive without re-running pod install.
|
|
47
|
+
config = (0, config_plugins_1.withXcodeProject)(config, (config) => {
|
|
48
|
+
const project = config.modResults;
|
|
49
|
+
const projectRoot = config.modRequest.projectRoot;
|
|
50
|
+
const packageTranslationsDir = path.resolve(projectRoot, 'node_modules', 'expo-native-sheet-emojis', 'translations');
|
|
51
|
+
if (!fs.existsSync(packageTranslationsDir)) {
|
|
52
|
+
console.warn('[expo-native-sheet-emojis] translations/ directory not found in package.');
|
|
49
53
|
return config;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
|
|
54
|
+
}
|
|
55
|
+
const target = project.getFirstTarget();
|
|
56
|
+
if (!target)
|
|
57
|
+
return config;
|
|
58
|
+
// addResourceFile crashes when no PBXGroup named 'Resources' exists (common in
|
|
59
|
+
// Expo-generated projects). ensureGroupRecursively creates it if absent — this is
|
|
60
|
+
// exactly how expo-asset's own config plugin handles the same situation.
|
|
61
|
+
config_plugins_1.IOSConfig.XcodeUtils.ensureGroupRecursively(project, 'Resources');
|
|
62
|
+
for (const locale of searchLocales) {
|
|
63
|
+
const absolutePath = path.join(packageTranslationsDir, `${locale}.json`);
|
|
64
|
+
if (!fs.existsSync(absolutePath)) {
|
|
65
|
+
console.warn(`[expo-native-sheet-emojis] Translation file not found for locale: ${locale}`);
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
// Path relative to ios/ where the .xcodeproj lives.
|
|
69
|
+
// Xcode copies this file into the app bundle at build time.
|
|
70
|
+
const relativePath = `../node_modules/expo-native-sheet-emojis/translations/${locale}.json`;
|
|
71
|
+
project.addResourceFile(relativePath, { target: target.uuid });
|
|
72
|
+
}
|
|
73
|
+
return config;
|
|
74
|
+
});
|
|
75
|
+
// Android: Copy locale files to the module's assets directory.
|
|
76
|
+
// Note: the module's Gradle copyTranslations task copies all locales at build time for
|
|
77
|
+
// bare React Native projects. For Expo managed workflow this plugin runs first and
|
|
78
|
+
// the Gradle task supplements with any remaining locales.
|
|
53
79
|
config = (0, config_plugins_1.withDangerousMod)(config, [
|
|
54
80
|
'android',
|
|
55
81
|
(config) => {
|
|
56
|
-
|
|
82
|
+
copyAndroidLocaleFiles(config, searchLocales);
|
|
57
83
|
return config;
|
|
58
84
|
},
|
|
59
85
|
]);
|
|
60
86
|
return config;
|
|
61
87
|
};
|
|
62
|
-
function
|
|
88
|
+
function copyAndroidLocaleFiles(config, locales) {
|
|
63
89
|
const projectRoot = config.modRequest.projectRoot;
|
|
64
|
-
// Find the translations directory in the npm package
|
|
65
90
|
const packageTranslationsDir = path.resolve(projectRoot, 'node_modules', 'expo-native-sheet-emojis', 'translations');
|
|
66
91
|
if (!fs.existsSync(packageTranslationsDir)) {
|
|
67
|
-
console.warn('[expo-native-sheet-emojis] translations/ directory not found in package.
|
|
92
|
+
console.warn('[expo-native-sheet-emojis] translations/ directory not found in package.');
|
|
68
93
|
return;
|
|
69
94
|
}
|
|
70
|
-
|
|
71
|
-
if (platform === 'ios') {
|
|
72
|
-
// For iOS, copy into the module's bundle resources
|
|
73
|
-
// The podspec includes translations/*.json, so we copy to the pod's source
|
|
74
|
-
targetDir = path.resolve(projectRoot, 'node_modules', 'expo-native-sheet-emojis', 'ios', 'translations');
|
|
75
|
-
}
|
|
76
|
-
else {
|
|
77
|
-
// For Android, copy into the module's assets
|
|
78
|
-
targetDir = path.resolve(projectRoot, 'node_modules', 'expo-native-sheet-emojis', 'android', 'src', 'main', 'assets', 'translations');
|
|
79
|
-
}
|
|
95
|
+
const targetDir = path.resolve(projectRoot, 'node_modules', 'expo-native-sheet-emojis', 'android', 'src', 'main', 'assets', 'translations');
|
|
80
96
|
fs.mkdirSync(targetDir, { recursive: true });
|
|
81
97
|
for (const locale of locales) {
|
|
82
98
|
const sourceFile = path.join(packageTranslationsDir, `${locale}.json`);
|
package/src/EmojiSheetModule.ts
CHANGED
|
@@ -56,7 +56,7 @@ function flattenOptions(options: EmojiSheetPresentOptions): NativeOptions {
|
|
|
56
56
|
return flat;
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
declare class EmojiSheetModuleType extends NativeModule {
|
|
59
|
+
declare class EmojiSheetModuleType extends NativeModule<{ onSheetOpened: () => void }> {
|
|
60
60
|
present(options: NativeOptions): Promise<EmojiSheetResult>;
|
|
61
61
|
dismiss(): Promise<void>;
|
|
62
62
|
clearRecents(): Promise<void>;
|
|
@@ -69,7 +69,20 @@ export type { EmojiSheetResult };
|
|
|
69
69
|
|
|
70
70
|
export default {
|
|
71
71
|
present(options: EmojiSheetPresentOptions = {}): Promise<EmojiSheetResult> {
|
|
72
|
-
|
|
72
|
+
let subscription: ReturnType<typeof NativeEmojiSheet.addListener> | null = null;
|
|
73
|
+
|
|
74
|
+
if (options.onOpen) {
|
|
75
|
+
subscription = NativeEmojiSheet.addListener('onSheetOpened', () => {
|
|
76
|
+
options.onOpen!();
|
|
77
|
+
subscription?.remove();
|
|
78
|
+
subscription = null;
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return NativeEmojiSheet.present(flattenOptions(options)).finally(() => {
|
|
83
|
+
subscription?.remove();
|
|
84
|
+
subscription = null;
|
|
85
|
+
});
|
|
73
86
|
},
|
|
74
87
|
dismiss(): Promise<void> {
|
|
75
88
|
return NativeEmojiSheet.dismiss();
|
|
@@ -52,17 +52,19 @@ export type EmojiSheetPresentOptions = {
|
|
|
52
52
|
gestureEnabled?: boolean;
|
|
53
53
|
backdropOpacity?: number;
|
|
54
54
|
excludeEmojis?: string[];
|
|
55
|
+
onOpen?: () => void;
|
|
55
56
|
};
|
|
56
57
|
|
|
57
58
|
export type EmojiSheetResult =
|
|
58
|
-
| { emoji: string; cancelled?: never }
|
|
59
|
-
| { cancelled: true; emoji?: never };
|
|
59
|
+
| { emoji: string; name: string; id: string; cancelled?: never }
|
|
60
|
+
| { cancelled: true; emoji?: never; name?: never; id?: never };
|
|
60
61
|
|
|
61
|
-
export type EmojiSelectionListener = (event: { nativeEvent: { emoji: string } }) => void;
|
|
62
|
+
export type EmojiSelectionListener = (event: { nativeEvent: { emoji: string; name: string; id: string } }) => void;
|
|
62
63
|
|
|
63
64
|
export type EmojiSheetViewProps = ViewProps & {
|
|
64
|
-
onEmojiSelected: (emoji: string) => void;
|
|
65
|
+
onEmojiSelected: (emoji: string, name: string, id: string) => void;
|
|
65
66
|
onDismiss?: () => void;
|
|
67
|
+
onOpen?: () => void;
|
|
66
68
|
theme?: EmojiSheetTheme | 'dark' | 'light' | 'system';
|
|
67
69
|
translations?: EmojiSheetTranslations;
|
|
68
70
|
layoutDirection?: 'ltr' | 'rtl' | 'auto';
|
|
@@ -81,6 +83,7 @@ export type EmojiSheetViewProps = ViewProps & {
|
|
|
81
83
|
export type EmojiSheetNativeViewProps = ViewProps & {
|
|
82
84
|
onEmojiSelected: EmojiSelectionListener;
|
|
83
85
|
onDismiss?: (event: { nativeEvent: {} }) => void;
|
|
86
|
+
onOpen?: (event: { nativeEvent: {} }) => void;
|
|
84
87
|
theme?: string;
|
|
85
88
|
layoutDirection?: 'ltr' | 'rtl' | 'auto';
|
|
86
89
|
categoryBarPosition?: string;
|
package/src/EmojiSheetView.tsx
CHANGED
|
@@ -11,6 +11,7 @@ const NativeView: React.ComponentType<EmojiSheetNativeViewProps> =
|
|
|
11
11
|
export default function EmojiSheetView({
|
|
12
12
|
onEmojiSelected,
|
|
13
13
|
onDismiss,
|
|
14
|
+
onOpen,
|
|
14
15
|
theme,
|
|
15
16
|
translations,
|
|
16
17
|
layoutDirection,
|
|
@@ -51,9 +52,10 @@ export default function EmojiSheetView({
|
|
|
51
52
|
noResultsText={translations?.noResultsText}
|
|
52
53
|
categoryNames={translations?.categoryNames}
|
|
53
54
|
onEmojiSelected={({ nativeEvent }) => {
|
|
54
|
-
onEmojiSelected(nativeEvent.emoji);
|
|
55
|
+
onEmojiSelected(nativeEvent.emoji, nativeEvent.name, nativeEvent.id);
|
|
55
56
|
}}
|
|
56
57
|
onDismiss={onDismiss ? () => onDismiss() : undefined}
|
|
58
|
+
onOpen={onOpen ? () => onOpen() : undefined}
|
|
57
59
|
/>
|
|
58
60
|
);
|
|
59
61
|
}
|