@tamer4lynx/tamer-icons 0.0.1

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 (39) hide show
  1. package/README.md +44 -0
  2. package/android/build.gradle.kts +28 -0
  3. package/android/src/main/assets/fonts/MaterialIcons-Regular.ttf +0 -0
  4. package/android/src/main/assets/fonts/MaterialSymbolsOutlined.ttf +0 -0
  5. package/android/src/main/assets/fonts/fa-solid-900.ttf +0 -0
  6. package/android/src/main/assets/fonts/material-codepoints.txt +4206 -0
  7. package/android/src/main/kotlin/com/nanofuxion/tamericons/IconCodepoints.kt +60 -0
  8. package/android/src/main/kotlin/com/nanofuxion/tamericons/IconDrawable.kt +92 -0
  9. package/android/src/main/kotlin/com/nanofuxion/tamericons/IconElement.kt +162 -0
  10. package/dist/fontawesome-codepoints.d.ts +2 -0
  11. package/dist/fontawesome-codepoints.d.ts.map +1 -0
  12. package/dist/fontawesome-codepoints.js +20 -0
  13. package/dist/fonts.css +13 -0
  14. package/dist/fonts.d.ts +7 -0
  15. package/dist/fonts.d.ts.map +1 -0
  16. package/dist/fonts.js +6 -0
  17. package/dist/index.d.ts +19 -0
  18. package/dist/index.d.ts.map +1 -0
  19. package/dist/index.js +16 -0
  20. package/dist/material-codepoints.d.ts +2 -0
  21. package/dist/material-codepoints.d.ts.map +1 -0
  22. package/dist/material-codepoints.js +56 -0
  23. package/dist/plugin.d.ts +3 -0
  24. package/dist/plugin.d.ts.map +1 -0
  25. package/dist/plugin.js +43 -0
  26. package/dist/tamer.config.d.ts +5 -0
  27. package/dist/tamer.config.d.ts.map +1 -0
  28. package/dist/tamer.config.js +4 -0
  29. package/fonts/MaterialIcons-Regular.ttf +0 -0
  30. package/fonts/MaterialSymbolsOutlined.ttf +0 -0
  31. package/fonts/fa-solid-900.ttf +0 -0
  32. package/ios/tamericons/tamericons/Classes/TamerIconElement.h +10 -0
  33. package/ios/tamericons/tamericons/Classes/TamerIconElement.m +307 -0
  34. package/ios/tamericons/tamericons/Resources/MaterialSymbolsOutlined.ttf +0 -0
  35. package/ios/tamericons/tamericons/Resources/fa-solid-900.ttf +0 -0
  36. package/ios/tamericons/tamericons/Resources/material-codepoints.txt +4206 -0
  37. package/ios/tamericons/tamericons.podspec +26 -0
  38. package/lynx.ext.json +17 -0
  39. package/package.json +48 -0
@@ -0,0 +1,60 @@
1
+ package com.nanofuxion.tamericons
2
+
3
+ import java.io.BufferedReader
4
+ import java.io.InputStreamReader
5
+
6
+ object IconCodepoints {
7
+
8
+ val FONTAWESOME: Map<String, Char> = mapOf(
9
+ "search" to '\uf002',
10
+ "home" to '\uf015',
11
+ "bars" to '\uf0c9',
12
+ "arrow-left" to '\uf060',
13
+ "xmark" to '\uf00d',
14
+ "close" to '\uf00d',
15
+ "plus" to '\uf067',
16
+ "minus" to '\uf068',
17
+ "cog" to '\uf013',
18
+ "user" to '\uf007',
19
+ "heart" to '\uf004',
20
+ "share" to '\uf064',
21
+ "trash" to '\uf1f8',
22
+ "pen" to '\uf304',
23
+ "check" to '\uf00c',
24
+ "info" to '\uf129',
25
+ "exclamation-triangle" to '\uf071',
26
+ "circle-xmark" to '\uf057',
27
+ )
28
+
29
+ @Volatile
30
+ private var materialCache: Map<String, Int>? = null
31
+
32
+ fun getMaterial(assets: android.content.res.AssetManager): Map<String, Int> {
33
+ return materialCache ?: synchronized(this) {
34
+ materialCache ?: loadMaterialFromAssets(assets).also { materialCache = it }
35
+ }
36
+ }
37
+
38
+ private fun loadMaterialFromAssets(assets: android.content.res.AssetManager): Map<String, Int> {
39
+ return try {
40
+ assets.open("fonts/material-codepoints.txt").use { stream ->
41
+ BufferedReader(InputStreamReader(stream)).use { reader ->
42
+ buildMap {
43
+ reader.lineSequence().forEach { line ->
44
+ val space = line.indexOf(' ')
45
+ if (space > 0) {
46
+ val name = line.substring(0, space)
47
+ val hex = line.substring(space + 1).trim()
48
+ if (hex.all { it in '0'..'9' || it in 'a'..'f' || it in 'A'..'F' }) {
49
+ put(name, hex.toInt(16))
50
+ }
51
+ }
52
+ }
53
+ }
54
+ }
55
+ }
56
+ } catch (e: Exception) {
57
+ emptyMap()
58
+ }
59
+ }
60
+ }
@@ -0,0 +1,92 @@
1
+ package com.nanofuxion.tamericons
2
+
3
+ import android.content.res.ColorStateList
4
+ import android.graphics.Canvas
5
+ import android.graphics.Paint
6
+ import android.graphics.Path
7
+ import android.graphics.RectF
8
+ import android.graphics.drawable.Drawable
9
+ import android.graphics.Typeface
10
+
11
+ /**
12
+ * Drawable that renders a single icon font character, scaled and centered in bounds.
13
+ * Color handling follows Android-Iconics: color is stored in a ColorStateList and
14
+ * applied to the paint in draw() so the icon color is not overridden by framework tint.
15
+ */
16
+ class IconDrawable(
17
+ private val typeface: Typeface,
18
+ private val codepoint: Int,
19
+ color: Int,
20
+ private val sizePx: Int
21
+ ) : Drawable() {
22
+
23
+ private var colorList: ColorStateList = ColorStateList.valueOf(color)
24
+
25
+ private val paint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
26
+ style = Paint.Style.FILL
27
+ textAlign = Paint.Align.LEFT
28
+ this.typeface = this@IconDrawable.typeface
29
+ }
30
+
31
+ private val path = Path()
32
+ private val pathBounds = RectF()
33
+
34
+ private val charSequence: CharSequence
35
+ get() = if (codepoint <= 0xFFFF) Character.toString(codepoint.toChar())
36
+ else String(Character.toChars(codepoint))
37
+
38
+ init {
39
+ setBounds(0, 0, sizePx, sizePx)
40
+ }
41
+
42
+ fun setColor(value: Int) {
43
+ if (colorList.defaultColor != value) {
44
+ colorList = ColorStateList.valueOf(value)
45
+ invalidateSelf()
46
+ }
47
+ }
48
+
49
+ override fun draw(canvas: Canvas) {
50
+ if (codepoint == 0) return
51
+ paint.color = colorList.getColorForState(state, colorList.defaultColor)
52
+ paint.colorFilter = null
53
+ val b = bounds
54
+ if (b.width() <= 0 || b.height() <= 0) return
55
+
56
+ val seq = charSequence
57
+ path.reset()
58
+ var textSize = b.height().toFloat()
59
+ paint.textSize = textSize
60
+ paint.getTextPath(seq.toString(), 0, seq.length, 0f, 0f, path)
61
+ path.computeBounds(pathBounds, true)
62
+
63
+ val pathW = pathBounds.width().coerceAtLeast(1f)
64
+ val pathH = pathBounds.height().coerceAtLeast(1f)
65
+ val scaleW = b.width() / pathW
66
+ val scaleH = b.height() / pathH
67
+ val scale = minOf(scaleW, scaleH).coerceAtMost(1f)
68
+ textSize *= scale
69
+ paint.textSize = textSize
70
+ path.reset()
71
+ paint.getTextPath(seq.toString(), 0, seq.length, 0f, 0f, path)
72
+ path.computeBounds(pathBounds, true)
73
+
74
+ val offsetX = b.left + (b.width() - pathBounds.width()) / 2 - pathBounds.left
75
+ val offsetY = b.top + (b.height() - pathBounds.height()) / 2 - pathBounds.top
76
+ path.offset(offsetX, offsetY)
77
+ canvas.drawPath(path, paint)
78
+ }
79
+
80
+ override fun setAlpha(alpha: Int) {
81
+ paint.alpha = alpha
82
+ }
83
+
84
+ override fun setColorFilter(colorFilter: android.graphics.ColorFilter?) {
85
+ }
86
+
87
+ @Deprecated("Deprecated in Java")
88
+ override fun getOpacity(): Int = android.graphics.PixelFormat.TRANSLUCENT
89
+
90
+ override fun getIntrinsicWidth(): Int = sizePx
91
+ override fun getIntrinsicHeight(): Int = sizePx
92
+ }
@@ -0,0 +1,162 @@
1
+ package com.nanofuxion.tamericons
2
+
3
+ import android.content.Context
4
+ import android.graphics.Color
5
+ import android.graphics.Typeface
6
+ import android.util.Log
7
+ import android.util.TypedValue
8
+ import android.view.ViewGroup
9
+ import android.widget.FrameLayout
10
+ import android.widget.ImageView
11
+ import com.lynx.react.bridge.Dynamic
12
+ import com.lynx.react.bridge.ReadableType
13
+ import com.lynx.tasm.behavior.LynxContext
14
+ import com.lynx.tasm.behavior.LynxProp
15
+ import com.lynx.tasm.behavior.ui.LynxUI
16
+
17
+ class IconElement(context: LynxContext) : LynxUI<FrameLayout>(context) {
18
+
19
+ private var iconSet = "material"
20
+ private var iconName = ""
21
+ private var iconColor = Color.BLACK
22
+ private var iconSizeSp = 24f
23
+
24
+ private lateinit var imageView: ImageView
25
+
26
+ override fun createView(context: Context): FrameLayout {
27
+ Log.d("TamerIcon", "createView called")
28
+ val container = FrameLayout(context).apply {
29
+ clipChildren = false
30
+ clipToPadding = false
31
+ }
32
+ imageView = ImageView(context).apply {
33
+ scaleType = ImageView.ScaleType.CENTER_INSIDE
34
+ setColorFilter(null)
35
+ if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
36
+ imageTintList = null
37
+ }
38
+ }
39
+ container.addView(imageView, FrameLayout.LayoutParams(
40
+ ViewGroup.LayoutParams.MATCH_PARENT,
41
+ ViewGroup.LayoutParams.MATCH_PARENT
42
+ ))
43
+ return container
44
+ }
45
+
46
+ private fun getTypeface(): Typeface? {
47
+ return try {
48
+ val assetPath = when (iconSet) {
49
+ "fontawesome", "fa" -> "fonts/fa-solid-900.ttf"
50
+ else -> "fonts/MaterialSymbolsOutlined.ttf"
51
+ }
52
+ Typeface.createFromAsset(lynxContext.context.assets, assetPath)
53
+ } catch (e: Exception) {
54
+ null
55
+ }
56
+ }
57
+
58
+ private fun resolveCodepoint(): Int {
59
+ return when (iconSet) {
60
+ "fontawesome", "fa" -> {
61
+ val key = iconName.removePrefix("fa-").replace("_", "-")
62
+ (IconCodepoints.FONTAWESOME[key] ?: IconCodepoints.FONTAWESOME[iconName])?.code ?: 0
63
+ }
64
+ else -> {
65
+ val map = IconCodepoints.getMaterial(lynxContext.context.assets)
66
+ map[iconName]
67
+ ?: map[iconName.replace("_", "-")]
68
+ ?: map[iconName.replace("-", "_")]
69
+ ?: 0
70
+ }
71
+ }
72
+ }
73
+
74
+ private fun applyIcon() {
75
+ if (!::imageView.isInitialized) return
76
+ val typeface = getTypeface()
77
+ if (typeface == null) {
78
+ Log.w("TamerIcon", "typeface null for set=$iconSet icon=$iconName")
79
+ return
80
+ }
81
+ val codepoint = resolveCodepoint()
82
+ if (codepoint == 0) {
83
+ Log.w("TamerIcon", "codepoint=0 for icon=$iconName set=$iconSet")
84
+ }
85
+ val sizePx = TypedValue.applyDimension(
86
+ TypedValue.COMPLEX_UNIT_SP,
87
+ iconSizeSp,
88
+ imageView.context.resources.displayMetrics
89
+ ).toInt().coerceAtLeast(1)
90
+ val drawable = IconDrawable(typeface, codepoint, iconColor, sizePx)
91
+ imageView.setImageDrawable(drawable)
92
+ imageView.clearColorFilter()
93
+ }
94
+
95
+ @LynxProp(name = "icon")
96
+ fun setIcon(value: String) {
97
+ iconName = value
98
+ applyIcon()
99
+ }
100
+
101
+ @LynxProp(name = "set")
102
+ fun setIconSet(value: String) {
103
+ iconSet = value.lowercase()
104
+ applyIcon()
105
+ }
106
+
107
+ @LynxProp(name = "iconColor")
108
+ fun setIconColor(value: Dynamic) {
109
+ applyColorFromDynamic(value)
110
+ }
111
+
112
+ private fun applyColorFromDynamic(value: Dynamic) {
113
+ if (value.type == ReadableType.Null) return
114
+ iconColor = when (value.type) {
115
+ ReadableType.Number -> (value.asDouble().toLong() and 0xFFFFFFFFL).toInt()
116
+ ReadableType.String -> parseColorString(value.asString())
117
+ else -> return
118
+ }
119
+ if (::imageView.isInitialized) {
120
+ (imageView.drawable as? IconDrawable)?.setColor(iconColor)
121
+ ?: applyIcon()
122
+ }
123
+ }
124
+
125
+ private fun expandHex(hex: String): String =
126
+ if (hex.length == 3) hex.map { "$it$it" }.joinToString("") else hex
127
+
128
+ private fun parseColorString(value: String): Int = try {
129
+ when {
130
+ value.startsWith("#") -> Color.parseColor("#${expandHex(value.removePrefix("#"))}")
131
+ value.startsWith("rgb") -> parseRgb(value)
132
+ else -> Color.parseColor(value)
133
+ }
134
+ } catch (_: Exception) {
135
+ Color.BLACK
136
+ }
137
+
138
+ @LynxProp(name = "size")
139
+ fun setSize(value: Double) {
140
+ iconSizeSp = value.toFloat()
141
+ applyIcon()
142
+ }
143
+
144
+ private fun parseRgb(value: String): Int {
145
+ val parts = value.replace(Regex("[^0-9,.]"), "").split(",")
146
+ val nums = parts.map { it.toFloatOrNull() ?: 0f }
147
+ return when (nums.size) {
148
+ 3 -> Color.rgb(nums[0].toInt(), nums[1].toInt(), nums[2].toInt())
149
+ 4 -> Color.argb((nums[3] * 255).toInt(), nums[0].toInt(), nums[1].toInt(), nums[2].toInt())
150
+ else -> Color.BLACK
151
+ }
152
+ }
153
+
154
+ override fun onLayoutUpdated() {
155
+ super.onLayoutUpdated()
156
+ val paddingTop = mPaddingTop + mBorderTopWidth
157
+ val paddingBottom = mPaddingBottom + mBorderBottomWidth
158
+ val paddingLeft = mPaddingLeft + mBorderLeftWidth
159
+ val paddingRight = mPaddingRight + mBorderRightWidth
160
+ mView.setPadding(paddingLeft, paddingTop, paddingRight, paddingBottom)
161
+ }
162
+ }
@@ -0,0 +1,2 @@
1
+ export declare const FONTAWESOME_CODEPOINTS: Record<string, string>;
2
+ //# sourceMappingURL=fontawesome-codepoints.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fontawesome-codepoints.d.ts","sourceRoot":"","sources":["../src/fontawesome-codepoints.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,sBAAsB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAmBzD,CAAA"}
@@ -0,0 +1,20 @@
1
+ export const FONTAWESOME_CODEPOINTS = {
2
+ search: '\uf002',
3
+ home: '\uf015',
4
+ bars: '\uf0c9',
5
+ 'arrow-left': '\uf060',
6
+ xmark: '\uf00d',
7
+ close: '\uf00d',
8
+ plus: '\uf067',
9
+ minus: '\uf068',
10
+ cog: '\uf013',
11
+ user: '\uf007',
12
+ heart: '\uf004',
13
+ share: '\uf064',
14
+ trash: '\uf1f8',
15
+ pen: '\uf304',
16
+ check: '\uf00c',
17
+ info: '\uf129',
18
+ 'exclamation-triangle': '\uf071',
19
+ 'circle-xmark': '\uf057',
20
+ };
package/dist/fonts.css ADDED
@@ -0,0 +1,13 @@
1
+ @font-face {
2
+ font-family: 'Material Symbols Outlined';
3
+ src: url('../fonts/MaterialSymbolsOutlined.ttf') format('truetype');
4
+ font-weight: 100 700;
5
+ font-style: normal;
6
+ }
7
+
8
+ @font-face {
9
+ font-family: 'Font Awesome 6 Free';
10
+ src: url('../fonts/fa-solid-900.ttf') format('truetype');
11
+ font-weight: 900;
12
+ font-style: normal;
13
+ }
@@ -0,0 +1,7 @@
1
+ export declare const MATERIAL_SYMBOLS_URL = "https://github.com/google/material-design-icons/raw/refs/heads/master/variablefont/MaterialSymbolsOutlined%5BFILL%2CGRAD%2Copsz%2Cwght%5D.ttf";
2
+ export declare const MATERIAL_SYMBOLS_FAMILY = "Material Symbols Outlined";
3
+ export declare const MATERIAL_ICONS_URL = "https://github.com/google/material-design-icons/raw/refs/heads/master/variablefont/MaterialSymbolsOutlined%5BFILL%2CGRAD%2Copsz%2Cwght%5D.ttf";
4
+ export declare const MATERIAL_ICONS_FAMILY = "Material Symbols Outlined";
5
+ export declare const FONTAWESOME_SOLID_URL = "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/webfonts/fa-solid-900.ttf";
6
+ export declare const FONTAWESOME_SOLID_FAMILY = "Font Awesome 6 Free";
7
+ //# sourceMappingURL=fonts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fonts.d.ts","sourceRoot":"","sources":["../src/fonts.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,oBAAoB,kJACgH,CAAA;AACjJ,eAAO,MAAM,uBAAuB,8BAA8B,CAAA;AAElE,eAAO,MAAM,kBAAkB,kJAAuB,CAAA;AACtD,eAAO,MAAM,qBAAqB,8BAA0B,CAAA;AAE5D,eAAO,MAAM,qBAAqB,wFACqD,CAAA;AACvF,eAAO,MAAM,wBAAwB,wBAAwB,CAAA"}
package/dist/fonts.js ADDED
@@ -0,0 +1,6 @@
1
+ export const MATERIAL_SYMBOLS_URL = 'https://github.com/google/material-design-icons/raw/refs/heads/master/variablefont/MaterialSymbolsOutlined%5BFILL%2CGRAD%2Copsz%2Cwght%5D.ttf';
2
+ export const MATERIAL_SYMBOLS_FAMILY = 'Material Symbols Outlined';
3
+ export const MATERIAL_ICONS_URL = MATERIAL_SYMBOLS_URL;
4
+ export const MATERIAL_ICONS_FAMILY = MATERIAL_SYMBOLS_FAMILY;
5
+ export const FONTAWESOME_SOLID_URL = 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/webfonts/fa-solid-900.ttf';
6
+ export const FONTAWESOME_SOLID_FAMILY = 'Font Awesome 6 Free';
@@ -0,0 +1,19 @@
1
+ import type { ViewProps } from '@lynx-js/types';
2
+ export { MATERIAL_ICONS_URL, FONTAWESOME_SOLID_URL } from './fonts';
3
+ export { MATERIAL_CODEPOINTS } from './material-codepoints';
4
+ export interface TfontProps {
5
+ src: string;
6
+ family: string;
7
+ weight?: number;
8
+ style?: ViewProps['style'];
9
+ }
10
+ export type IconSet = 'material' | 'fontawesome' | 'fa';
11
+ export interface IconProps extends ViewProps {
12
+ name: string;
13
+ set?: IconSet;
14
+ size?: number;
15
+ color?: string;
16
+ }
17
+ export declare function Tfont(props: TfontProps): null;
18
+ export declare function Icon(props: IconProps): any;
19
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAE/C,OAAO,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAA;AACnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAA;AAE3D,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAA;IACX,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,KAAK,CAAC,EAAE,SAAS,CAAC,OAAO,CAAC,CAAA;CAC3B;AAED,MAAM,MAAM,OAAO,GAAG,UAAU,GAAG,aAAa,GAAG,IAAI,CAAA;AAEvD,MAAM,WAAW,SAAU,SAAQ,SAAS;IAC1C,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,OAAO,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAID,wBAAgB,KAAK,CAAC,KAAK,EAAE,UAAU,QAGtC;AAED,wBAAgB,IAAI,CAAC,KAAK,EAAE,SAAS,OAgBpC"}
package/dist/index.js ADDED
@@ -0,0 +1,16 @@
1
+ import { jsx as _jsx } from "@lynx-js/react/jsx-runtime";
2
+ export { MATERIAL_ICONS_URL, FONTAWESOME_SOLID_URL } from './fonts';
3
+ export { MATERIAL_CODEPOINTS } from './material-codepoints';
4
+ const px = (value) => `${Math.round(value)}px`;
5
+ export function Tfont(props) {
6
+ void props;
7
+ return null;
8
+ }
9
+ export function Icon(props) {
10
+ const { name, set = 'material', size = 24, color, style, ...rest } = props;
11
+ return (_jsx("icon", { icon: name, set: set, size: size, iconColor: color, style: {
12
+ width: px(size),
13
+ height: px(size),
14
+ ...style,
15
+ }, ...rest }));
16
+ }
@@ -0,0 +1,2 @@
1
+ export declare const MATERIAL_CODEPOINTS: Record<string, string>;
2
+ //# sourceMappingURL=material-codepoints.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"material-codepoints.d.ts","sourceRoot":"","sources":["../src/material-codepoints.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAuDtD,CAAA"}
@@ -0,0 +1,56 @@
1
+ export const MATERIAL_CODEPOINTS = {
2
+ // Navigation
3
+ home: '\ue9b2',
4
+ menu: '\ue5d2',
5
+ arrow_back: '\ue5c4',
6
+ arrow_back_ios: '\ue5e0',
7
+ arrow_forward: '\ue5c8',
8
+ chevron_left: '\ue5cb',
9
+ chevron_right: '\ue5cc',
10
+ expand_less: '\ue5ce',
11
+ expand_more: '\ue5cf',
12
+ close: '\ue5cd',
13
+ more_vert: '\ue5d4',
14
+ more_horiz: '\ue5d3',
15
+ // Actions
16
+ add: '\ue145',
17
+ check: '\ue5ca',
18
+ delete: '\ue92e',
19
+ edit: '\uf097',
20
+ search: '\ue8b6',
21
+ share: '\ue80d',
22
+ send: '\ue163',
23
+ download: '\uf090',
24
+ upload: '\uf09b',
25
+ refresh: '\ue5d5',
26
+ // Status / Info
27
+ info: '\ue88e',
28
+ warning: '\uf083',
29
+ error: '\uf8b6',
30
+ help: '\ue887',
31
+ // Social / Profile
32
+ person: '\uf0d3',
33
+ people: '\uea21',
34
+ favorite: '\ue87e',
35
+ star: '\uf8d7',
36
+ // Content
37
+ settings: '\ue8b8',
38
+ notifications: '\ue7f4',
39
+ link: '\ue250',
40
+ history: '\ue8b3',
41
+ // Network / Connectivity
42
+ wifi: '\ue63e',
43
+ wifi_find: '\ueb31',
44
+ bluetooth: '\ue1a7',
45
+ // Misc
46
+ lock: '\ue897',
47
+ lock_open: '\ue898',
48
+ visibility: '\ue8f4',
49
+ visibility_off: '\ue8f5',
50
+ calendar_today: '\ue935',
51
+ schedule: '\ue8b5',
52
+ location_on: '\ue0c8',
53
+ phone: '\ue0cd',
54
+ email: '\ue0be',
55
+ camera: '\ue3af',
56
+ };
@@ -0,0 +1,3 @@
1
+ import type { RsbuildPlugin } from '@rsbuild/core';
2
+ export declare function pluginTamerIcons(): RsbuildPlugin;
3
+ //# sourceMappingURL=plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAqClD,wBAAgB,gBAAgB,IAAI,aAAa,CAUhD"}
package/dist/plugin.js ADDED
@@ -0,0 +1,43 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import { fileURLToPath } from 'url';
4
+ import { MATERIAL_ICONS_URL, FONTAWESOME_SOLID_URL } from './fonts';
5
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
6
+ async function fetchToBuffer(url) {
7
+ const res = await fetch(url);
8
+ if (!res.ok)
9
+ throw new Error(`Failed to fetch ${url}: ${res.status}`);
10
+ const arr = await res.arrayBuffer();
11
+ return Buffer.from(arr);
12
+ }
13
+ async function ensureFonts(pkgDir) {
14
+ const fontsDir = path.join(pkgDir, 'fonts');
15
+ fs.mkdirSync(fontsDir, { recursive: true });
16
+ const materialPath = path.join(fontsDir, 'MaterialSymbolsOutlined.ttf');
17
+ const faPath = path.join(fontsDir, 'fa-solid-900.ttf');
18
+ const cacheDir = path.join(pkgDir, '.cache', 'tamer-icons');
19
+ fs.mkdirSync(cacheDir, { recursive: true });
20
+ const materialCache = path.join(cacheDir, 'MaterialSymbolsOutlined.ttf');
21
+ const faCache = path.join(cacheDir, 'fa-solid-900.ttf');
22
+ if (!fs.existsSync(materialCache)) {
23
+ const buf = await fetchToBuffer(MATERIAL_ICONS_URL);
24
+ fs.writeFileSync(materialCache, buf);
25
+ }
26
+ fs.copyFileSync(materialCache, materialPath);
27
+ if (!fs.existsSync(faCache)) {
28
+ const buf = await fetchToBuffer(FONTAWESOME_SOLID_URL);
29
+ fs.writeFileSync(faCache, buf);
30
+ }
31
+ fs.copyFileSync(faCache, faPath);
32
+ }
33
+ export function pluginTamerIcons() {
34
+ return {
35
+ name: 'tamer-icons',
36
+ async setup(api) {
37
+ const pkgDir = path.resolve(__dirname, '..');
38
+ if (fs.existsSync(path.join(pkgDir, 'package.json'))) {
39
+ await ensureFonts(pkgDir);
40
+ }
41
+ },
42
+ };
43
+ }
@@ -0,0 +1,5 @@
1
+ declare const _default: {
2
+ pluginTamerIcons: import("@rsbuild/core").RsbuildPlugin;
3
+ };
4
+ export default _default;
5
+ //# sourceMappingURL=tamer.config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tamer.config.d.ts","sourceRoot":"","sources":["../src/tamer.config.ts"],"names":[],"mappings":";;;AAEA,wBAEC"}
@@ -0,0 +1,4 @@
1
+ import { pluginTamerIcons } from './plugin';
2
+ export default {
3
+ pluginTamerIcons: pluginTamerIcons(),
4
+ };
Binary file
Binary file
@@ -0,0 +1,10 @@
1
+ #import <Lynx/LynxUI.h>
2
+ #import <UIKit/UIKit.h>
3
+
4
+ NS_ASSUME_NONNULL_BEGIN
5
+
6
+ @interface TamerIconElement : LynxUI<UIView *>
7
+ + (void)registerFonts;
8
+ @end
9
+
10
+ NS_ASSUME_NONNULL_END