@retray-dev/ui-kit 10.2.0 → 12.1.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/COMPONENTS.md +287 -37
- package/README.md +11 -2
- package/dist/Accordion.mjs +2 -2
- package/dist/AlertBanner.mjs +2 -2
- package/dist/AppHeader.mjs +3 -3
- package/dist/Avatar.mjs +2 -2
- package/dist/Badge.mjs +2 -2
- package/dist/Button.mjs +2 -2
- package/dist/Card.mjs +2 -2
- package/dist/CategoryStrip.mjs +2 -2
- package/dist/Checkbox.mjs +2 -2
- package/dist/Chip.mjs +2 -2
- package/dist/ConfirmDialog.d.mts +1 -6
- package/dist/ConfirmDialog.d.ts +1 -6
- package/dist/ConfirmDialog.js +29 -23
- package/dist/ConfirmDialog.mjs +3 -3
- package/dist/CurrencyDisplay.mjs +2 -2
- package/dist/CurrencyInput.d.mts +3 -8
- package/dist/CurrencyInput.d.ts +3 -8
- package/dist/CurrencyInput.js +3 -1
- package/dist/CurrencyInput.mjs +3 -3
- package/dist/DetailRow.mjs +2 -2
- package/dist/EmptyState.mjs +3 -3
- package/dist/ErrorBoundary.mjs +2 -2
- package/dist/Form.mjs +2 -2
- package/dist/IconButton.mjs +2 -2
- package/dist/IconPicker.js +675 -248
- package/dist/IconPicker.mjs +3 -2
- package/dist/ImageUpload.mjs +3 -3
- package/dist/ImageViewer.mjs +4 -4
- package/dist/Input.mjs +2 -2
- package/dist/LabelValue.mjs +2 -2
- package/dist/ListGroup.mjs +2 -2
- package/dist/ListItem.d.mts +7 -7
- package/dist/ListItem.d.ts +7 -7
- package/dist/ListItem.js +12 -7
- package/dist/ListItem.mjs +2 -2
- package/dist/MediaCard.mjs +2 -2
- package/dist/MenuGroup.mjs +2 -2
- package/dist/MenuItem.mjs +2 -2
- package/dist/MonthPicker.mjs +2 -2
- package/dist/NumberStepper.mjs +2 -2
- package/dist/PagerDots.mjs +2 -2
- package/dist/Pressable.d.mts +15 -7
- package/dist/Pressable.d.ts +15 -7
- package/dist/Pressable.js +7 -3
- package/dist/Pressable.mjs +1 -1
- package/dist/PricingCard.mjs +4 -4
- package/dist/Progress.mjs +2 -2
- package/dist/RadioGroup.mjs +2 -2
- package/dist/RetrayProvider.mjs +3 -3
- package/dist/Select.mjs +2 -2
- package/dist/SelectableGrid.mjs +2 -2
- package/dist/Separator.mjs +2 -2
- package/dist/Sheet.d.mts +4 -46
- package/dist/Sheet.d.ts +4 -46
- package/dist/Sheet.js +46 -114
- package/dist/Sheet.mjs +2 -3
- package/dist/SheetSelect.mjs +2 -2
- package/dist/Skeleton.mjs +2 -2
- package/dist/Slider.mjs +2 -2
- package/dist/Spinner.mjs +2 -2
- package/dist/Stats.d.mts +30 -0
- package/dist/Stats.d.ts +30 -0
- package/dist/Stats.js +429 -0
- package/dist/Stats.mjs +9 -0
- package/dist/Switch.mjs +2 -2
- package/dist/TabBar.mjs +2 -2
- package/dist/Tabs.mjs +2 -2
- package/dist/Text.d.mts +3 -1
- package/dist/Text.d.ts +3 -1
- package/dist/Text.js +3 -3
- package/dist/Text.mjs +2 -2
- package/dist/Textarea.mjs +2 -2
- package/dist/Toast.mjs +2 -2
- package/dist/Toggle.mjs +2 -2
- package/dist/{chunk-YJ7I257J.mjs → chunk-265G6A46.mjs} +1 -1
- package/dist/{chunk-ELXBDILQ.mjs → chunk-2A2LEFZG.mjs} +2 -2
- package/dist/{chunk-ID72TK46.mjs → chunk-2CBQKU7H.mjs} +1 -1
- package/dist/{chunk-OB4JUQ3O.mjs → chunk-2I2AYECM.mjs} +1 -1
- package/dist/{chunk-WJLKJMKR.mjs → chunk-357YO24D.mjs} +4 -4
- package/dist/{chunk-GQYFLP3D.mjs → chunk-3GEYJ7I5.mjs} +1 -1
- package/dist/{chunk-AV4EMIRH.mjs → chunk-3N2M3WZL.mjs} +1 -1
- package/dist/{chunk-VF2ATYN3.mjs → chunk-3UYAZ7I4.mjs} +1 -1
- package/dist/{chunk-JMOZEC77.mjs → chunk-4WFMPFZB.mjs} +1 -1
- package/dist/chunk-5OLNXP3S.mjs +144 -0
- package/dist/{chunk-6SECQ2ZF.mjs → chunk-7HSILTC4.mjs} +2 -2
- package/dist/{chunk-IRRY3CRZ.mjs → chunk-AKM4EPOT.mjs} +1 -1
- package/dist/{chunk-IX3NYLYQ.mjs → chunk-AQEVCEXV.mjs} +1 -1
- package/dist/{chunk-WBOOUHSS.mjs → chunk-BCWEHE34.mjs} +1 -1
- package/dist/{chunk-AJ7ZDNBT.mjs → chunk-BOVUP27T.mjs} +1 -1
- package/dist/{chunk-BRKYVJVV.mjs → chunk-BQZE3HAW.mjs} +1 -1
- package/dist/{chunk-Z6SFHN6T.mjs → chunk-D3Y2T42P.mjs} +1 -1
- package/dist/{chunk-T2KCAHOS.mjs → chunk-DF6DU42P.mjs} +1 -1
- package/dist/{chunk-TB6SD2FT.mjs → chunk-DI7CBDL6.mjs} +1 -1
- package/dist/{chunk-HTHGSXFG.mjs → chunk-DOGIPOF5.mjs} +1 -1
- package/dist/{chunk-MBMXYJJV.mjs → chunk-E7NEHHXV.mjs} +7 -3
- package/dist/{chunk-MX6HRKMI.mjs → chunk-EFLFRAHD.mjs} +1 -1
- package/dist/{chunk-SOYNZDVY.mjs → chunk-EMUWGDWC.mjs} +6 -1
- package/dist/{chunk-AJRVDP2H.mjs → chunk-F4V6XLP4.mjs} +3 -3
- package/dist/{chunk-DYT7BG5I.mjs → chunk-FA2KMTH5.mjs} +1 -1
- package/dist/{chunk-Y2NS74WS.mjs → chunk-FFTYLPSB.mjs} +46 -98
- package/dist/{chunk-VKID2D2I.mjs → chunk-FUVYSVGR.mjs} +13 -8
- package/dist/{chunk-7LWRKMF5.mjs → chunk-FVTVCJAH.mjs} +1 -1
- package/dist/{chunk-TZDGAP5N.mjs → chunk-GK4VRMNE.mjs} +2 -2
- package/dist/{chunk-6Q64UFIA.mjs → chunk-HJ46DTJE.mjs} +1 -1
- package/dist/{chunk-WF2XDFRK.mjs → chunk-HLMPMUK2.mjs} +1 -1
- package/dist/{chunk-GD6KXMG5.mjs → chunk-I4V5XZPS.mjs} +1 -1
- package/dist/{chunk-TBNZHU6C.mjs → chunk-ISY26JQJ.mjs} +2 -2
- package/dist/{chunk-X4G6APW6.mjs → chunk-J6Q2YJEV.mjs} +1 -1
- package/dist/{chunk-WYEUNUTP.mjs → chunk-JCZQOY4O.mjs} +31 -24
- package/dist/{chunk-U2XJFYED.mjs → chunk-JNVAIDLK.mjs} +1 -1
- package/dist/{chunk-SOA2Z4RB.mjs → chunk-JULSIZDM.mjs} +1 -1
- package/dist/chunk-KHYX4IOM.mjs +1114 -0
- package/dist/{chunk-RYZC432S.mjs → chunk-LRM4AVYY.mjs} +1 -1
- package/dist/{chunk-6L4G6PBT.mjs → chunk-MYZ2EDYU.mjs} +1 -1
- package/dist/{chunk-BUMAMSTZ.mjs → chunk-N4ZPVCJH.mjs} +1 -1
- package/dist/{chunk-Z4VHZ7B5.mjs → chunk-NXI4YDZ2.mjs} +1 -1
- package/dist/{chunk-ZZ2R6KZ3.mjs → chunk-OULVKTWL.mjs} +1 -1
- package/dist/{chunk-FCSSQK3L.mjs → chunk-P64WHW4A.mjs} +1 -1
- package/dist/{chunk-KOO4WITD.mjs → chunk-P73V2EKS.mjs} +1 -1
- package/dist/{chunk-SXLKNTA4.mjs → chunk-PGERH3P7.mjs} +1 -1
- package/dist/{chunk-2UYENBLV.mjs → chunk-QSFV2P7O.mjs} +1 -1
- package/dist/{chunk-JT7HKXRB.mjs → chunk-S3KJCPEJ.mjs} +1 -1
- package/dist/{chunk-BEMIQXXU.mjs → chunk-V6NFJXKO.mjs} +1 -1
- package/dist/{chunk-A3A6KNQN.mjs → chunk-WOEWGSTU.mjs} +1 -1
- package/dist/{chunk-NMU5FMQJ.mjs → chunk-X26S5EVZ.mjs} +4 -2
- package/dist/{chunk-YFZ3ELX5.mjs → chunk-XBAGGKLW.mjs} +2 -2
- package/dist/{chunk-S2R7UVOE.mjs → chunk-ZHMSAYLT.mjs} +1 -1
- package/dist/fonts.d.mts +1 -7
- package/dist/fonts.d.ts +1 -7
- package/dist/fonts.js +0 -2
- package/dist/fonts.mjs +1 -2
- package/dist/index.d.mts +4 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +1184 -708
- package/dist/index.mjs +53 -52
- package/package.json +3 -3
- package/src/components/ConfirmDialog/ConfirmDialog.tsx +39 -30
- package/src/components/CurrencyInput/CurrencyInput.tsx +4 -7
- package/src/components/IconPicker/IconPicker.tsx +124 -112
- package/src/components/ListItem/ListItem.tsx +43 -28
- package/src/components/Pressable/Pressable.tsx +20 -8
- package/src/components/Sheet/Sheet.tsx +64 -172
- package/src/components/Stats/Stats.tsx +226 -0
- package/src/components/Stats/index.ts +2 -0
- package/src/components/Text/Text.tsx +4 -2
- package/src/fonts.ts +0 -7
- package/src/index.ts +4 -0
- package/src/theme/colorUtils.ts +9 -0
- package/src/utils/curatedIcons.ts +698 -135
- package/src/utils/fontGuard.ts +2 -1
- package/dist/chunk-53Z3NYGE.mjs +0 -742
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
import React, { useState, useCallback } from 'react'
|
|
2
|
+
import { View, Text, StyleSheet, ViewStyle, LayoutChangeEvent } from 'react-native'
|
|
3
|
+
import { impactLight } from '../../utils/haptics'
|
|
4
|
+
import { useTheme } from '../../theme'
|
|
5
|
+
import { s, vs, ms, mvs } from '../../utils/scaling'
|
|
6
|
+
import { RADIUS } from '../../tokens'
|
|
7
|
+
import { renderIcon } from '../../utils/icons'
|
|
8
|
+
import { PressableCard } from '../../utils/pressable'
|
|
9
|
+
|
|
10
|
+
export type StatsVariant = 'elevated' | 'outlined' | 'filled'
|
|
11
|
+
|
|
12
|
+
export interface StatsProps {
|
|
13
|
+
value: string
|
|
14
|
+
label: string
|
|
15
|
+
description?: string
|
|
16
|
+
icon?: React.ReactNode
|
|
17
|
+
iconName?: string
|
|
18
|
+
iconColor?: string
|
|
19
|
+
variant?: StatsVariant
|
|
20
|
+
onPress?: () => void
|
|
21
|
+
style?: ViewStyle
|
|
22
|
+
accessibilityLabel?: string
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface StatsGroupProps {
|
|
26
|
+
children: React.ReactNode
|
|
27
|
+
gap?: number
|
|
28
|
+
style?: ViewStyle
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const COMPACT_THRESHOLD = s(150)
|
|
32
|
+
|
|
33
|
+
function StatsComponent({
|
|
34
|
+
value,
|
|
35
|
+
label,
|
|
36
|
+
description,
|
|
37
|
+
icon,
|
|
38
|
+
iconName,
|
|
39
|
+
iconColor,
|
|
40
|
+
variant = 'elevated',
|
|
41
|
+
onPress,
|
|
42
|
+
style,
|
|
43
|
+
accessibilityLabel,
|
|
44
|
+
}: StatsProps) {
|
|
45
|
+
const { colors } = useTheme()
|
|
46
|
+
const [containerWidth, setContainerWidth] = useState(0)
|
|
47
|
+
|
|
48
|
+
const handleLayout = useCallback((e: LayoutChangeEvent) => {
|
|
49
|
+
const w = e.nativeEvent.layout.width
|
|
50
|
+
if (w > 0 && w !== containerWidth) {
|
|
51
|
+
setContainerWidth(w)
|
|
52
|
+
}
|
|
53
|
+
}, [containerWidth])
|
|
54
|
+
|
|
55
|
+
const handlePress = () => {
|
|
56
|
+
if (!onPress) return
|
|
57
|
+
impactLight()
|
|
58
|
+
onPress()
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const isCompact = containerWidth > 0 && containerWidth < COMPACT_THRESHOLD && !!(icon ?? iconName)
|
|
62
|
+
|
|
63
|
+
const variantStyle: ViewStyle = {
|
|
64
|
+
elevated: {
|
|
65
|
+
backgroundColor: colors.card,
|
|
66
|
+
borderWidth: 0,
|
|
67
|
+
shadowColor: '#000',
|
|
68
|
+
shadowOffset: { width: 0, height: 4 },
|
|
69
|
+
shadowOpacity: 0.09,
|
|
70
|
+
shadowRadius: 14,
|
|
71
|
+
elevation: 4,
|
|
72
|
+
},
|
|
73
|
+
outlined: {
|
|
74
|
+
backgroundColor: colors.card,
|
|
75
|
+
borderColor: colors.border,
|
|
76
|
+
shadowOpacity: 0,
|
|
77
|
+
elevation: 0,
|
|
78
|
+
},
|
|
79
|
+
filled: {
|
|
80
|
+
backgroundColor: colors.surfaceStrong,
|
|
81
|
+
borderColor: colors.border,
|
|
82
|
+
shadowOpacity: 0,
|
|
83
|
+
elevation: 0,
|
|
84
|
+
},
|
|
85
|
+
}[variant]
|
|
86
|
+
|
|
87
|
+
const iconColorResolved = iconColor ?? colors.primary
|
|
88
|
+
|
|
89
|
+
const resolvedIcon = iconName ? renderIcon(iconName, ms(22), iconColorResolved) : icon
|
|
90
|
+
|
|
91
|
+
const iconElement = resolvedIcon ? (
|
|
92
|
+
<View style={styles.iconWrapper}>{resolvedIcon}</View>
|
|
93
|
+
) : null
|
|
94
|
+
|
|
95
|
+
const valueElement = (
|
|
96
|
+
<Text style={[styles.value, { color: colors.foreground }]} allowFontScaling={true}>
|
|
97
|
+
{value}
|
|
98
|
+
</Text>
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
const cardContent = (
|
|
102
|
+
<View style={[styles.card, variantStyle, style]} onLayout={handleLayout}>
|
|
103
|
+
{isCompact ? (
|
|
104
|
+
<>
|
|
105
|
+
{iconElement}
|
|
106
|
+
<View style={styles.compactValue}>{valueElement}</View>
|
|
107
|
+
<Text style={[styles.label, { color: colors.foregroundSubtle }]} allowFontScaling={true}>
|
|
108
|
+
{label}
|
|
109
|
+
</Text>
|
|
110
|
+
{description ? (
|
|
111
|
+
<Text style={[styles.description, { color: colors.foregroundMuted }]} allowFontScaling={true}>
|
|
112
|
+
{description}
|
|
113
|
+
</Text>
|
|
114
|
+
) : null}
|
|
115
|
+
</>
|
|
116
|
+
) : (
|
|
117
|
+
<>
|
|
118
|
+
<View style={styles.valueRow}>
|
|
119
|
+
{iconElement}
|
|
120
|
+
{valueElement}
|
|
121
|
+
</View>
|
|
122
|
+
<Text style={[styles.label, { color: colors.foregroundSubtle }]} allowFontScaling={true}>
|
|
123
|
+
{label}
|
|
124
|
+
</Text>
|
|
125
|
+
{description ? (
|
|
126
|
+
<Text style={[styles.description, { color: colors.foregroundMuted }]} allowFontScaling={true}>
|
|
127
|
+
{description}
|
|
128
|
+
</Text>
|
|
129
|
+
) : null}
|
|
130
|
+
</>
|
|
131
|
+
)}
|
|
132
|
+
</View>
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
if (onPress) {
|
|
136
|
+
return (
|
|
137
|
+
<PressableCard
|
|
138
|
+
onPress={handlePress}
|
|
139
|
+
rippleColor="transparent"
|
|
140
|
+
touchSoundDisabled
|
|
141
|
+
activateOnHover
|
|
142
|
+
accessibilityRole="button"
|
|
143
|
+
accessibilityLabel={accessibilityLabel}
|
|
144
|
+
>
|
|
145
|
+
{cardContent}
|
|
146
|
+
</PressableCard>
|
|
147
|
+
)
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
return cardContent
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function StatsGroup({ children, gap = s(12), style }: StatsGroupProps) {
|
|
154
|
+
return (
|
|
155
|
+
<View style={[styles.group, { gap }, style]}>
|
|
156
|
+
{React.Children.map(children, (child) => {
|
|
157
|
+
if (!React.isValidElement(child)) return child
|
|
158
|
+
const childStyle = (child.props as { style?: ViewStyle }).style
|
|
159
|
+
const mergedStyle = childStyle
|
|
160
|
+
? [childStyle, { alignSelf: 'stretch' as const }]
|
|
161
|
+
: [{ alignSelf: 'stretch' as const }]
|
|
162
|
+
return (
|
|
163
|
+
<View style={styles.groupItem}>
|
|
164
|
+
{React.cloneElement(
|
|
165
|
+
child as React.ReactElement<{ style?: ViewStyle }>,
|
|
166
|
+
{ style: mergedStyle as unknown as ViewStyle },
|
|
167
|
+
)}
|
|
168
|
+
</View>
|
|
169
|
+
)
|
|
170
|
+
})}
|
|
171
|
+
</View>
|
|
172
|
+
)
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export const Stats = Object.assign(React.memo(StatsComponent), { Group: StatsGroup })
|
|
176
|
+
|
|
177
|
+
const styles = StyleSheet.create({
|
|
178
|
+
card: {
|
|
179
|
+
borderRadius: RADIUS.md,
|
|
180
|
+
borderWidth: 1,
|
|
181
|
+
padding: s(16),
|
|
182
|
+
alignSelf: 'flex-start',
|
|
183
|
+
alignItems: 'center',
|
|
184
|
+
justifyContent: 'center',
|
|
185
|
+
},
|
|
186
|
+
valueRow: {
|
|
187
|
+
flexDirection: 'row',
|
|
188
|
+
alignItems: 'center',
|
|
189
|
+
justifyContent: 'center',
|
|
190
|
+
gap: s(8),
|
|
191
|
+
},
|
|
192
|
+
iconWrapper: {
|
|
193
|
+
alignItems: 'center',
|
|
194
|
+
justifyContent: 'center',
|
|
195
|
+
},
|
|
196
|
+
compactValue: {
|
|
197
|
+
marginTop: vs(8),
|
|
198
|
+
},
|
|
199
|
+
value: {
|
|
200
|
+
fontFamily: 'Sohne-Bold',
|
|
201
|
+
fontSize: ms(28),
|
|
202
|
+
lineHeight: mvs(32),
|
|
203
|
+
textAlign: 'center',
|
|
204
|
+
},
|
|
205
|
+
label: {
|
|
206
|
+
fontFamily: 'Sohne-Regular',
|
|
207
|
+
fontSize: ms(13),
|
|
208
|
+
lineHeight: mvs(18),
|
|
209
|
+
marginTop: vs(8),
|
|
210
|
+
textAlign: 'center',
|
|
211
|
+
},
|
|
212
|
+
description: {
|
|
213
|
+
fontFamily: 'Sohne-Regular',
|
|
214
|
+
fontSize: ms(12),
|
|
215
|
+
lineHeight: mvs(16),
|
|
216
|
+
marginTop: vs(4),
|
|
217
|
+
textAlign: 'center',
|
|
218
|
+
},
|
|
219
|
+
group: {
|
|
220
|
+
flexDirection: 'row',
|
|
221
|
+
width: '100%',
|
|
222
|
+
},
|
|
223
|
+
groupItem: {
|
|
224
|
+
flex: 1,
|
|
225
|
+
},
|
|
226
|
+
})
|
|
@@ -26,6 +26,8 @@ export type TextVariant =
|
|
|
26
26
|
export interface TextProps extends RNTextProps {
|
|
27
27
|
variant?: TextVariant
|
|
28
28
|
color?: string
|
|
29
|
+
/** Force uppercase text transformation. Useful for labels, headers, and buttons. */
|
|
30
|
+
uppercase?: boolean
|
|
29
31
|
}
|
|
30
32
|
|
|
31
33
|
// Apply scaling to font/line-height values while preserving all other token props
|
|
@@ -68,7 +70,7 @@ const defaultColorVariant: Partial<Record<TextVariant, 'foreground' | 'foregroun
|
|
|
68
70
|
'button-sm': 'foreground',
|
|
69
71
|
}
|
|
70
72
|
|
|
71
|
-
function TextBase({ variant = 'body-md', color, style, children, ...props }: TextProps) {
|
|
73
|
+
function TextBase({ variant = 'body-md', color, style, uppercase, children, ...props }: TextProps) {
|
|
72
74
|
warnIfFontsMissing()
|
|
73
75
|
const { colors } = useTheme()
|
|
74
76
|
|
|
@@ -77,7 +79,7 @@ function TextBase({ variant = 'body-md', color, style, children, ...props }: Tex
|
|
|
77
79
|
|
|
78
80
|
return (
|
|
79
81
|
<RNText
|
|
80
|
-
style={[variantStyles[variant], { color: resolvedColor }, style]}
|
|
82
|
+
style={[variantStyles[variant], { color: resolvedColor }, uppercase && { textTransform: 'uppercase' }, style]}
|
|
81
83
|
allowFontScaling={true}
|
|
82
84
|
{...props}
|
|
83
85
|
>
|
package/src/fonts.ts
CHANGED
|
@@ -63,10 +63,3 @@ export const SohneFontNames = [
|
|
|
63
63
|
|
|
64
64
|
/** Type for any valid Sohne font family name */
|
|
65
65
|
export type SohneFontName = (typeof SohneFontNames)[number]
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* @deprecated SohneFonts export removed in v10.0.0.
|
|
69
|
-
* Metro cannot resolve require() calls from node_modules reliably.
|
|
70
|
-
* Copy the static SohneFonts boilerplate from CONSUMER.md into your App.tsx instead.
|
|
71
|
-
*/
|
|
72
|
-
export const SohneFonts = undefined
|
package/src/index.ts
CHANGED
|
@@ -57,6 +57,7 @@ export * from './components/SheetSelect'
|
|
|
57
57
|
export * from './components/ImageUpload'
|
|
58
58
|
export * from './components/IconPicker'
|
|
59
59
|
export * from './components/NumberStepper'
|
|
60
|
+
export * from './components/Stats'
|
|
60
61
|
// HolographicCard is intentionally NOT re-exported here — it depends on the
|
|
61
62
|
// optional peer @shopify/react-native-skia, so it must stay out of the main
|
|
62
63
|
// barrel's module graph. Deep-import it: '@retray-dev/ui-kit/HolographicCard'.
|
|
@@ -64,6 +65,9 @@ export * from './components/NumberStepper'
|
|
|
64
65
|
// Icon utility
|
|
65
66
|
export { Icon, renderIcon, configureIconFamilies, getValidIconNames } from './utils/icons'
|
|
66
67
|
|
|
68
|
+
// Color utilities
|
|
69
|
+
export { withAlpha } from './theme/colorUtils'
|
|
70
|
+
|
|
67
71
|
// Typography utilities
|
|
68
72
|
export { getResponsiveFontSize } from './utils/typography'
|
|
69
73
|
export type { IconProps, IconFamily } from './utils/icons'
|
package/src/theme/colorUtils.ts
CHANGED
|
@@ -78,3 +78,12 @@ export function isDark(hex: string): boolean {
|
|
|
78
78
|
const L = 0.2126 * toLinear(rgb.r) + 0.7152 * toLinear(rgb.g) + 0.0722 * toLinear(rgb.b)
|
|
79
79
|
return L < 0.5
|
|
80
80
|
}
|
|
81
|
+
|
|
82
|
+
// Convert a hex color to rgba with the given alpha.
|
|
83
|
+
// Returns an rgba() string suitable for use with semi-transparent backgrounds,
|
|
84
|
+
// borders, and overlays.
|
|
85
|
+
export function withAlpha(hex: string, alpha: number): string {
|
|
86
|
+
const rgb = hexToRgb(hex)
|
|
87
|
+
if (!rgb) return hex
|
|
88
|
+
return `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${alpha})`
|
|
89
|
+
}
|