@react-navigation/native 8.0.0-alpha.0 → 8.0.0-alpha.10

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.
Files changed (128) hide show
  1. package/ReactNavigation.podspec +20 -0
  2. package/android/build.gradle +147 -0
  3. package/android/src/main/AndroidManifest.xml +2 -0
  4. package/android/src/main/java/org/reactnavigation/MaterialSymbolModule.kt +100 -0
  5. package/android/src/main/java/org/reactnavigation/MaterialSymbolTypeface.kt +77 -0
  6. package/android/src/main/java/org/reactnavigation/MaterialSymbolView.kt +95 -0
  7. package/android/src/main/java/org/reactnavigation/MaterialSymbolViewManager.kt +49 -0
  8. package/android/src/main/java/org/reactnavigation/ReactNavigationPackage.kt +34 -0
  9. package/assets/fonts/MaterialSymbolsOutlined.codepoints +4102 -0
  10. package/assets/fonts/MaterialSymbolsOutlined_100.ttf +0 -0
  11. package/assets/fonts/MaterialSymbolsOutlined_200.ttf +0 -0
  12. package/assets/fonts/MaterialSymbolsOutlined_300.ttf +0 -0
  13. package/assets/fonts/MaterialSymbolsOutlined_400.ttf +0 -0
  14. package/assets/fonts/MaterialSymbolsOutlined_500.ttf +0 -0
  15. package/assets/fonts/MaterialSymbolsOutlined_600.ttf +0 -0
  16. package/assets/fonts/MaterialSymbolsOutlined_700.ttf +0 -0
  17. package/assets/fonts/MaterialSymbolsRounded.codepoints +4102 -0
  18. package/assets/fonts/MaterialSymbolsRounded_100.ttf +0 -0
  19. package/assets/fonts/MaterialSymbolsRounded_200.ttf +0 -0
  20. package/assets/fonts/MaterialSymbolsRounded_300.ttf +0 -0
  21. package/assets/fonts/MaterialSymbolsRounded_400.ttf +0 -0
  22. package/assets/fonts/MaterialSymbolsRounded_500.ttf +0 -0
  23. package/assets/fonts/MaterialSymbolsRounded_600.ttf +0 -0
  24. package/assets/fonts/MaterialSymbolsRounded_700.ttf +0 -0
  25. package/assets/fonts/MaterialSymbolsSharp.codepoints +4102 -0
  26. package/assets/fonts/MaterialSymbolsSharp_100.ttf +0 -0
  27. package/assets/fonts/MaterialSymbolsSharp_200.ttf +0 -0
  28. package/assets/fonts/MaterialSymbolsSharp_300.ttf +0 -0
  29. package/assets/fonts/MaterialSymbolsSharp_400.ttf +0 -0
  30. package/assets/fonts/MaterialSymbolsSharp_500.ttf +0 -0
  31. package/assets/fonts/MaterialSymbolsSharp_600.ttf +0 -0
  32. package/assets/fonts/MaterialSymbolsSharp_700.ttf +0 -0
  33. package/ios/ReactNavigationSFSymbolView.h +14 -0
  34. package/ios/ReactNavigationSFSymbolView.mm +79 -0
  35. package/ios/ReactNavigationSFSymbolView.swift +300 -0
  36. package/lib/module/NavigationContainer.js +7 -2
  37. package/lib/module/NavigationContainer.js.map +1 -1
  38. package/lib/module/createStaticNavigation.js +3 -6
  39. package/lib/module/createStaticNavigation.js.map +1 -1
  40. package/lib/module/index.js +4 -1
  41. package/lib/module/index.js.map +1 -1
  42. package/lib/module/native/MaterialSymbol.android.js +58 -0
  43. package/lib/module/native/MaterialSymbol.android.js.map +1 -0
  44. package/lib/module/native/MaterialSymbol.js +9 -0
  45. package/lib/module/native/MaterialSymbol.js.map +1 -0
  46. package/lib/module/native/MaterialSymbolData.js +2 -0
  47. package/lib/module/native/MaterialSymbolData.js.map +1 -0
  48. package/lib/module/native/MaterialSymbolViewNativeComponent.ts +23 -0
  49. package/lib/module/native/NativeMaterialSymbolModule.js +7 -0
  50. package/lib/module/native/NativeMaterialSymbolModule.js.map +1 -0
  51. package/lib/module/native/SFSymbol.ios.js +46 -0
  52. package/lib/module/native/SFSymbol.ios.js.map +1 -0
  53. package/lib/module/native/SFSymbol.js +6 -0
  54. package/lib/module/native/SFSymbol.js.map +1 -0
  55. package/lib/module/native/SFSymbolViewNativeComponent.ts +32 -0
  56. package/lib/module/native/constants.js +14 -0
  57. package/lib/module/native/constants.js.map +1 -0
  58. package/lib/module/native/types.js +4 -0
  59. package/lib/module/native/types.js.map +1 -0
  60. package/lib/module/theming/{DefaultTheme.js → LightTheme.js} +2 -2
  61. package/lib/module/theming/LightTheme.js.map +1 -0
  62. package/lib/module/theming/MaterialTheme.android.js +29 -0
  63. package/lib/module/theming/MaterialTheme.android.js.map +1 -0
  64. package/lib/module/theming/MaterialTheme.js +18 -0
  65. package/lib/module/theming/MaterialTheme.js.map +1 -0
  66. package/lib/module/useLinkBuilder.js +24 -5
  67. package/lib/module/useLinkBuilder.js.map +1 -1
  68. package/lib/module/useLinkTo.js +2 -4
  69. package/lib/module/useLinkTo.js.map +1 -1
  70. package/lib/module/useLinking.native.js +20 -3
  71. package/lib/module/useLinking.native.js.map +1 -1
  72. package/lib/typescript/src/NavigationContainer.d.ts +6 -1
  73. package/lib/typescript/src/NavigationContainer.d.ts.map +1 -1
  74. package/lib/typescript/src/createStaticNavigation.d.ts +3 -3
  75. package/lib/typescript/src/createStaticNavigation.d.ts.map +1 -1
  76. package/lib/typescript/src/index.d.ts +4 -1
  77. package/lib/typescript/src/index.d.ts.map +1 -1
  78. package/lib/typescript/src/native/MaterialSymbol.android.d.ts +8 -0
  79. package/lib/typescript/src/native/MaterialSymbol.android.d.ts.map +1 -0
  80. package/lib/typescript/src/native/MaterialSymbol.d.ts +8 -0
  81. package/lib/typescript/src/native/MaterialSymbol.d.ts.map +1 -0
  82. package/lib/typescript/src/native/MaterialSymbolData.d.ts +2 -0
  83. package/lib/typescript/src/native/MaterialSymbolData.d.ts.map +1 -0
  84. package/lib/typescript/src/native/MaterialSymbolViewNativeComponent.d.ts +11 -0
  85. package/lib/typescript/src/native/MaterialSymbolViewNativeComponent.d.ts.map +1 -0
  86. package/lib/typescript/src/native/NativeMaterialSymbolModule.d.ts +7 -0
  87. package/lib/typescript/src/native/NativeMaterialSymbolModule.d.ts.map +1 -0
  88. package/lib/typescript/src/native/SFSymbol.d.ts +5 -0
  89. package/lib/typescript/src/native/SFSymbol.d.ts.map +1 -0
  90. package/lib/typescript/src/native/SFSymbol.ios.d.ts +5 -0
  91. package/lib/typescript/src/native/SFSymbol.ios.d.ts.map +1 -0
  92. package/lib/typescript/src/native/SFSymbolViewNativeComponent.d.ts +23 -0
  93. package/lib/typescript/src/native/SFSymbolViewNativeComponent.d.ts.map +1 -0
  94. package/lib/typescript/src/native/constants.d.ts +12 -0
  95. package/lib/typescript/src/native/constants.d.ts.map +1 -0
  96. package/lib/typescript/src/native/types.d.ts +181 -0
  97. package/lib/typescript/src/native/types.d.ts.map +1 -0
  98. package/lib/typescript/src/theming/{DefaultTheme.d.ts → LightTheme.d.ts} +2 -2
  99. package/lib/typescript/src/theming/LightTheme.d.ts.map +1 -0
  100. package/lib/typescript/src/theming/MaterialTheme.android.d.ts +127 -0
  101. package/lib/typescript/src/theming/MaterialTheme.android.d.ts.map +1 -0
  102. package/lib/typescript/src/theming/MaterialTheme.d.ts +114 -0
  103. package/lib/typescript/src/theming/MaterialTheme.d.ts.map +1 -0
  104. package/lib/typescript/src/useLinkBuilder.d.ts +104 -6
  105. package/lib/typescript/src/useLinkBuilder.d.ts.map +1 -1
  106. package/lib/typescript/src/useLinking.native.d.ts.map +1 -1
  107. package/package.json +39 -4
  108. package/src/NavigationContainer.tsx +20 -3
  109. package/src/createStaticNavigation.tsx +8 -12
  110. package/src/index.tsx +7 -1
  111. package/src/native/MaterialSymbol.android.tsx +83 -0
  112. package/src/native/MaterialSymbol.tsx +17 -0
  113. package/src/native/MaterialSymbolData.tsx +4106 -0
  114. package/src/native/MaterialSymbolViewNativeComponent.ts +23 -0
  115. package/src/native/NativeMaterialSymbolModule.ts +19 -0
  116. package/src/native/SFSymbol.ios.tsx +53 -0
  117. package/src/native/SFSymbol.tsx +9 -0
  118. package/src/native/SFSymbolViewNativeComponent.ts +32 -0
  119. package/src/native/constants.tsx +11 -0
  120. package/src/native/types.tsx +218 -0
  121. package/src/theming/{DefaultTheme.tsx → LightTheme.tsx} +1 -1
  122. package/src/theming/MaterialTheme.android.tsx +30 -0
  123. package/src/theming/MaterialTheme.tsx +19 -0
  124. package/src/useLinkBuilder.tsx +26 -6
  125. package/src/useLinkTo.tsx +2 -2
  126. package/src/useLinking.native.tsx +38 -15
  127. package/lib/module/theming/DefaultTheme.js.map +0 -1
  128. package/lib/typescript/src/theming/DefaultTheme.d.ts.map +0 -1
@@ -0,0 +1,20 @@
1
+ require "json"
2
+
3
+ package = JSON.parse(File.read(File.join(__dir__, "package.json")))
4
+
5
+ Pod::Spec.new do |s|
6
+ s.name = "ReactNavigation"
7
+ s.version = package["version"]
8
+ s.summary = package["description"]
9
+ s.homepage = package["homepage"]
10
+ s.license = package["license"]
11
+ s.authors = "Satyajit Sahoo <satyajit.happy@gmail.com> (https://github.com/satya164/), Michał Osadnik <micosa97@gmail.com> (https://github.com/osdnk/)"
12
+
13
+ s.platforms = { :ios => min_ios_version_supported }
14
+ s.source = { :git => "https://github.com/react-navigation/react-navigation.git", :tag => "#{s.version}" }
15
+
16
+ s.source_files = "ios/**/*.{h,m,mm,swift,cpp}"
17
+ s.private_header_files = "ios/**/*.h"
18
+
19
+ install_modules_dependencies(s)
20
+ end
@@ -0,0 +1,147 @@
1
+ import groovy.json.JsonSlurper
2
+
3
+ buildscript {
4
+ ext.ReactNavigation = [
5
+ kotlinVersion: "2.0.21",
6
+ minSdkVersion: 24,
7
+ compileSdkVersion: 36,
8
+ targetSdkVersion: 36
9
+ ]
10
+
11
+ ext.getExtOrDefault = { prop ->
12
+ if (rootProject.ext.has(prop)) {
13
+ return rootProject.ext.get(prop)
14
+ }
15
+
16
+ return ReactNavigation[prop]
17
+ }
18
+
19
+ repositories {
20
+ google()
21
+ mavenCentral()
22
+ }
23
+
24
+ dependencies {
25
+ classpath "com.android.tools.build:gradle:8.7.2"
26
+ // noinspection DifferentKotlinGradleVersion
27
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${getExtOrDefault('kotlinVersion')}"
28
+ }
29
+ }
30
+
31
+
32
+ apply plugin: "com.android.library"
33
+ apply plugin: "kotlin-android"
34
+
35
+ apply plugin: "com.facebook.react"
36
+
37
+ android {
38
+ namespace "org.reactnavigation"
39
+
40
+ compileSdkVersion getExtOrDefault("compileSdkVersion")
41
+
42
+ defaultConfig {
43
+ minSdkVersion getExtOrDefault("minSdkVersion")
44
+ targetSdkVersion getExtOrDefault("targetSdkVersion")
45
+ }
46
+
47
+ buildTypes {
48
+ release {
49
+ minifyEnabled false
50
+ }
51
+ }
52
+
53
+ lint {
54
+ disable "GradleCompatible"
55
+ }
56
+
57
+ compileOptions {
58
+ sourceCompatibility JavaVersion.VERSION_1_8
59
+ targetCompatibility JavaVersion.VERSION_1_8
60
+ }
61
+ }
62
+
63
+ tasks.register('copyMaterialFonts', Copy) {
64
+ def packageJsonFile = file(rootDir.path + "/../package.json")
65
+ def fontsConfig = null
66
+
67
+ if (packageJsonFile.exists()) {
68
+ def packageJson = new JsonSlurper().parse(packageJsonFile)
69
+
70
+ fontsConfig = packageJson["react-navigation"]?.get("material-symbols")?.get("fonts")
71
+ }
72
+
73
+ fontsConfig = fontsConfig != null ? fontsConfig : [[variant: "outlined", weights: [400]]]
74
+
75
+ def assetsFontsDir = file("../assets/fonts")
76
+ def availableFonts = assetsFontsDir.listFiles()
77
+ ?.findAll { it.name.startsWith("MaterialSymbols") && it.name.endsWith(".ttf") }
78
+ ?.collect { it.name.replaceFirst(/^MaterialSymbols/, '').replaceFirst(/\.ttf$/, '') } ?: []
79
+
80
+ def validVariants = availableFonts.collect { it.split('_')[0].toLowerCase() }.unique().sort()
81
+ def validWeights = availableFonts.collect { it.split('_')[1] as int }.unique().sort()
82
+
83
+ def errors = [] as Set
84
+
85
+ fontsConfig.each { font ->
86
+ if (font.variant && !validVariants.contains(font.variant.toLowerCase())) {
87
+ errors << "Invalid font variant: ${font.variant}"
88
+ }
89
+
90
+ font.weights.each { weight ->
91
+ if (!validWeights.contains(weight)) {
92
+ errors << "Invalid font weight: ${weight}"
93
+ }
94
+ }
95
+ }
96
+
97
+ if (errors) {
98
+ throw new GradleException(
99
+ errors.join("\n") + "\n\nAvailable variants: ${validVariants.join(", ")}.\nAvailable weights: ${validWeights.join(", ")}."
100
+ )
101
+ }
102
+
103
+ def fontFiles = fontsConfig.collectMany { font ->
104
+ def variant = font.variant?.capitalize() ?: ""
105
+
106
+ font.weights.collect { weight -> "MaterialSymbols${variant}_${weight}.ttf" }
107
+ }
108
+
109
+ if (fontFiles) {
110
+ from(assetsFontsDir) { include fontFiles }
111
+ }
112
+
113
+ into layout.buildDirectory.dir("intermediates/react-navigation/fonts")
114
+
115
+ doFirst {
116
+ if (destinationDir.exists()) {
117
+ def extraFiles = destinationDir.listFiles()?.findAll { file -> !fontFiles.contains(file.name) }
118
+
119
+ extraFiles?.each { file -> file.delete() }
120
+ }
121
+ }
122
+
123
+ doLast {
124
+ def digest = java.security.MessageDigest.getInstance("MD5")
125
+
126
+ fontFiles.sort().each { name ->
127
+ def fontFile = new File(assetsFontsDir, name)
128
+
129
+ if (fontFile.exists()) {
130
+ digest.update(fontFile.bytes)
131
+ }
132
+ }
133
+
134
+ def hash = digest.digest().encodeHex().toString().take(8)
135
+ def hashFile = new File(destinationDir, "MaterialSymbols.hash")
136
+
137
+ hashFile.text = hash
138
+ }
139
+ }
140
+
141
+ android.sourceSets.main.assets.srcDirs += layout.buildDirectory.dir("intermediates/react-navigation")
142
+
143
+ preBuild.dependsOn(copyMaterialFonts)
144
+
145
+ dependencies {
146
+ implementation "com.facebook.react:react-android"
147
+ }
@@ -0,0 +1,2 @@
1
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android">
2
+ </manifest>
@@ -0,0 +1,100 @@
1
+ package org.reactnavigation
2
+
3
+ import android.graphics.Bitmap
4
+ import android.graphics.Canvas
5
+ import android.graphics.Paint
6
+ import androidx.core.graphics.createBitmap
7
+ import androidx.core.net.toUri
8
+ import com.facebook.fbreact.specs.NativeMaterialSymbolModuleSpec
9
+ import com.facebook.react.bridge.ColorPropConverter
10
+ import com.facebook.react.bridge.ReactApplicationContext
11
+ import com.facebook.react.bridge.ReadableMap
12
+ import kotlinx.coroutines.CoroutineScope
13
+ import kotlinx.coroutines.Dispatchers
14
+ import kotlinx.coroutines.SupervisorJob
15
+ import kotlinx.coroutines.launch
16
+ import java.io.File
17
+ import java.io.FileOutputStream
18
+ import kotlin.math.roundToInt
19
+
20
+ class MaterialSymbolModule(reactContext: ReactApplicationContext) :
21
+ NativeMaterialSymbolModuleSpec(reactContext) {
22
+
23
+ companion object {
24
+ const val NAME = NativeMaterialSymbolModuleSpec.NAME
25
+
26
+ private val scope = CoroutineScope(Dispatchers.IO + SupervisorJob())
27
+ }
28
+
29
+ private val fontHash: String by lazy {
30
+ reactApplicationContext.assets.open("fonts/MaterialSymbols.hash").bufferedReader().readText()
31
+ .trim()
32
+ }
33
+
34
+ override fun getImageSource(
35
+ name: String, variant: String?, weight: Double?, size: Double, color: ReadableMap
36
+ ): String {
37
+ val colorValue = color.getDynamic("value").let {
38
+ when (it.type) {
39
+ com.facebook.react.bridge.ReadableType.Number -> it.asDouble()
40
+ com.facebook.react.bridge.ReadableType.Map -> it.asMap()
41
+ else -> null
42
+ }
43
+ }
44
+
45
+ val resolvedColor = ColorPropConverter.getColor(colorValue, reactApplicationContext)
46
+ ?: throw IllegalArgumentException("Could not resolve color")
47
+
48
+ val density = reactApplicationContext.resources.displayMetrics.density
49
+ val scaledSize = (size * density).roundToInt().coerceAtLeast(1)
50
+
51
+ val (resolvedTypeface, typefaceSuffix) = MaterialSymbolTypeface.get(
52
+ reactApplicationContext, variant, weight?.toInt()
53
+ )
54
+
55
+ val cacheDir = File(
56
+ reactApplicationContext.cacheDir,
57
+ "react_navigation/material_symbols/$typefaceSuffix/$fontHash"
58
+ )
59
+
60
+ val cacheKey = "${name.hashCode()}_${scaledSize}_$resolvedColor"
61
+ val cacheFile = File(cacheDir, "$cacheKey.png")
62
+
63
+ if (cacheFile.exists()) {
64
+ return cacheFile.toUri().toString()
65
+ }
66
+
67
+ scope.launch {
68
+ cacheDir.parentFile?.listFiles { it.isDirectory && it.name != fontHash }
69
+ ?.forEach { it.deleteRecursively() }
70
+ }
71
+
72
+ cacheDir.mkdirs()
73
+
74
+ val paint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
75
+ typeface = resolvedTypeface
76
+ textSize = scaledSize.toFloat()
77
+ textAlign = Paint.Align.CENTER
78
+
79
+ this.color = resolvedColor
80
+ }
81
+
82
+ val fontMetrics = paint.fontMetrics
83
+ val bitmap = createBitmap(scaledSize, scaledSize)
84
+
85
+ try {
86
+ val canvas = Canvas(bitmap)
87
+ val y = (scaledSize - (fontMetrics.descent - fontMetrics.ascent)) / 2f - fontMetrics.ascent
88
+
89
+ canvas.drawText(name, scaledSize / 2f, y, paint)
90
+
91
+ FileOutputStream(cacheFile).use {
92
+ bitmap.compress(Bitmap.CompressFormat.PNG, 100, it)
93
+ }
94
+ } finally {
95
+ bitmap.recycle()
96
+ }
97
+
98
+ return cacheFile.toUri().toString()
99
+ }
100
+ }
@@ -0,0 +1,77 @@
1
+ package org.reactnavigation
2
+
3
+ import android.content.Context
4
+ import android.graphics.Typeface
5
+
6
+ data class MaterialSymbolTypefaceResult(val typeface: Typeface, val suffix: String)
7
+
8
+ object MaterialSymbolTypeface {
9
+ private val typefaces = mutableMapOf<String, Typeface>()
10
+ private var defaultSuffix: String? = null
11
+
12
+ fun get(context: Context, variant: String?, weight: Int?): MaterialSymbolTypefaceResult {
13
+ val suffix = if (variant != null && weight != null) {
14
+ val resolvedVariant = when (variant) {
15
+ "rounded" -> "Rounded"
16
+ "sharp" -> "Sharp"
17
+ else -> "Outlined"
18
+ }
19
+
20
+ "${resolvedVariant}_$weight"
21
+ } else {
22
+ getDefaultSuffix(context)
23
+ }
24
+
25
+ val typeface = typefaces.getOrPut(suffix) {
26
+ val path = "fonts/MaterialSymbols${suffix}.ttf"
27
+
28
+ try {
29
+ Typeface.createFromAsset(context.assets, path)
30
+ } catch (e: Exception) {
31
+ throw RuntimeException("$path not found.", e)
32
+ }
33
+ }
34
+
35
+ return MaterialSymbolTypefaceResult(typeface, suffix)
36
+ }
37
+
38
+ private fun getDefaultSuffix(context: Context): String {
39
+ defaultSuffix?.let { return it }
40
+
41
+ val fonts = context.assets.list("fonts")
42
+ ?.filter { it.startsWith("MaterialSymbols") && it.endsWith(".ttf") } ?: emptyList()
43
+
44
+ if (fonts.isEmpty()) {
45
+ throw RuntimeException("No MaterialSymbols font found in assets.")
46
+ }
47
+
48
+ if (fonts.size > 1) {
49
+ val outlinedFonts = fonts.filter { it.startsWith("MaterialSymbolsOutlined") }
50
+ val outlinedFont = when {
51
+ outlinedFonts.isEmpty() -> null
52
+ outlinedFonts.size == 1 -> outlinedFonts[0]
53
+ else -> outlinedFonts.firstOrNull {
54
+ it.removePrefix("MaterialSymbols").removeSuffix(".ttf") == "Outlined_400"
55
+ }
56
+ }
57
+
58
+ if (outlinedFont == null) {
59
+ throw RuntimeException(
60
+ "Multiple MaterialSymbols fonts found in assets: ${fonts.joinToString()}. " + "Please specify a variant and weight explicitly."
61
+ )
62
+ }
63
+
64
+ val outlinedSuffix = outlinedFont.removePrefix("MaterialSymbols").removeSuffix(".ttf")
65
+
66
+ defaultSuffix = outlinedSuffix
67
+
68
+ return outlinedSuffix
69
+ }
70
+
71
+ val suffix = fonts[0].removePrefix("MaterialSymbols").removeSuffix(".ttf")
72
+
73
+ defaultSuffix = suffix
74
+
75
+ return suffix
76
+ }
77
+ }
@@ -0,0 +1,95 @@
1
+ package org.reactnavigation
2
+
3
+ import android.content.Context
4
+ import android.graphics.Canvas
5
+ import android.graphics.Paint
6
+ import android.util.AttributeSet
7
+
8
+ class MaterialSymbolView @JvmOverloads constructor(
9
+ context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
10
+ ) : androidx.appcompat.widget.AppCompatTextView(context, attrs, defStyleAttr) {
11
+
12
+ private var variant: String? = null
13
+ private var weight: Int? = null
14
+
15
+ init {
16
+ setColor(null)
17
+ updateTypeface()
18
+ }
19
+
20
+ override fun onDraw(canvas: Canvas) {
21
+ val text = text?.toString() ?: return
22
+
23
+ paint.color = currentTextColor
24
+ paint.textAlign = Paint.Align.CENTER
25
+
26
+ val fontMetrics = paint.fontMetrics
27
+ val x = width / 2f
28
+ val y = (height - (fontMetrics.descent - fontMetrics.ascent)) / 2f - fontMetrics.ascent
29
+
30
+ canvas.drawText(text, x, y, paint)
31
+ }
32
+
33
+ fun setName(name: String?) {
34
+ text = name
35
+
36
+ invalidate()
37
+ }
38
+
39
+ fun setVariant(variant: String?) {
40
+ if (this.variant == variant) {
41
+ return
42
+ }
43
+
44
+ this.variant = variant
45
+
46
+ updateTypeface()
47
+ }
48
+
49
+ fun setWeight(weight: Int?) {
50
+ if (this.weight == weight) {
51
+ return
52
+ }
53
+
54
+ this.weight = weight
55
+
56
+ updateTypeface()
57
+ }
58
+
59
+ private fun updateTypeface() {
60
+ setTypeface(
61
+ MaterialSymbolTypeface.get(
62
+ context,
63
+ variant?.ifEmpty { null },
64
+ weight.takeIf { it != 0 }).typeface
65
+ )
66
+
67
+ invalidate()
68
+ }
69
+
70
+ fun setColor(color: Int?) {
71
+ if (color == null) {
72
+ val typedValue = android.util.TypedValue()
73
+
74
+ context.theme.resolveAttribute(
75
+ android.R.attr.colorForeground, typedValue, true
76
+ )
77
+
78
+ val resolvedColor = if (typedValue.resourceId != 0) {
79
+ context.getColor(typedValue.resourceId)
80
+ } else {
81
+ typedValue.data
82
+ }
83
+
84
+ setTextColor(resolvedColor)
85
+ } else {
86
+ setTextColor(color)
87
+ }
88
+
89
+ invalidate()
90
+ }
91
+
92
+ fun setSize(size: Float) {
93
+ textSize = size
94
+ }
95
+ }
@@ -0,0 +1,49 @@
1
+ package org.reactnavigation
2
+
3
+ import com.facebook.react.module.annotations.ReactModule
4
+ import com.facebook.react.uimanager.SimpleViewManager
5
+ import com.facebook.react.uimanager.ThemedReactContext
6
+ import com.facebook.react.uimanager.annotations.ReactProp
7
+ import com.facebook.react.viewmanagers.ReactNavigationMaterialSymbolViewManagerInterface
8
+
9
+ @ReactModule(name = MaterialSymbolViewManager.NAME)
10
+ class MaterialSymbolViewManager : SimpleViewManager<MaterialSymbolView>(),
11
+ ReactNavigationMaterialSymbolViewManagerInterface<MaterialSymbolView> {
12
+
13
+ override fun getName(): String {
14
+ return NAME
15
+ }
16
+
17
+ override fun createViewInstance(context: ThemedReactContext): MaterialSymbolView {
18
+ return MaterialSymbolView(context)
19
+ }
20
+
21
+ @ReactProp(name = "name")
22
+ override fun setName(view: MaterialSymbolView, name: String?) {
23
+ view.setName(name)
24
+ }
25
+
26
+ @ReactProp(name = "variant")
27
+ override fun setVariant(view: MaterialSymbolView, variant: String?) {
28
+ view.setVariant(variant)
29
+ }
30
+
31
+ @ReactProp(name = "weight")
32
+ override fun setWeight(view: MaterialSymbolView, weight: Int?) {
33
+ view.setWeight(weight)
34
+ }
35
+
36
+ @ReactProp(name = "size")
37
+ override fun setSize(view: MaterialSymbolView, size: Float) {
38
+ view.setSize(size)
39
+ }
40
+
41
+ @ReactProp(name = "color", customType = "Color")
42
+ override fun setColor(view: MaterialSymbolView, color: Int?) {
43
+ view.setColor(color)
44
+ }
45
+
46
+ companion object {
47
+ const val NAME = "ReactNavigationMaterialSymbolView"
48
+ }
49
+ }
@@ -0,0 +1,34 @@
1
+ package org.reactnavigation
2
+
3
+ import com.facebook.react.BaseReactPackage
4
+ import com.facebook.react.bridge.NativeModule
5
+ import com.facebook.react.bridge.ReactApplicationContext
6
+ import com.facebook.react.module.model.ReactModuleInfo
7
+ import com.facebook.react.module.model.ReactModuleInfoProvider
8
+ import com.facebook.react.uimanager.ViewManager
9
+
10
+ class ReactNavigationPackage : BaseReactPackage() {
11
+ override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
12
+ return listOf(MaterialSymbolViewManager())
13
+ }
14
+
15
+ override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? {
16
+ return when (name) {
17
+ MaterialSymbolModule.NAME -> MaterialSymbolModule(reactContext)
18
+ else -> null
19
+ }
20
+ }
21
+
22
+ override fun getReactModuleInfoProvider() = ReactModuleInfoProvider {
23
+ mapOf(
24
+ MaterialSymbolModule.NAME to ReactModuleInfo(
25
+ name = MaterialSymbolModule.NAME,
26
+ className = MaterialSymbolModule.NAME,
27
+ canOverrideExistingModule = false,
28
+ needsEagerInit = false,
29
+ isCxxModule = false,
30
+ isTurboModule = true
31
+ )
32
+ )
33
+ }
34
+ }