@onlynative/components 0.1.0-alpha.3 → 0.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/dist/appbar/index.js +54 -122
- package/dist/button/index.js +31 -120
- package/dist/card/index.js +20 -89
- package/dist/checkbox/index.js +10 -75
- package/dist/chip/index.js +29 -118
- package/dist/icon-button/index.js +32 -97
- package/dist/index.d.ts +1 -0
- package/dist/index.js +461 -474
- package/dist/keyboard-avoiding-wrapper/index.d.ts +36 -0
- package/dist/keyboard-avoiding-wrapper/index.js +98 -0
- package/dist/list/index.js +5 -50
- package/dist/radio/index.js +8 -35
- package/dist/switch/index.js +12 -77
- package/dist/text-field/index.js +25 -78
- package/package.json +13 -3
- package/src/appbar/AppBar.tsx +1 -1
- package/src/button/Button.tsx +1 -1
- package/src/button/styles.ts +1 -2
- package/src/card/styles.ts +1 -2
- package/src/checkbox/Checkbox.tsx +1 -1
- package/src/checkbox/styles.ts +1 -1
- package/src/chip/Chip.tsx +1 -1
- package/src/chip/styles.ts +1 -2
- package/src/icon-button/IconButton.tsx +5 -2
- package/src/icon-button/styles.ts +1 -1
- package/src/index.ts +3 -0
- package/src/keyboard-avoiding-wrapper/KeyboardAvoidingWrapper.tsx +69 -0
- package/src/keyboard-avoiding-wrapper/index.ts +2 -0
- package/src/keyboard-avoiding-wrapper/styles.ts +10 -0
- package/src/keyboard-avoiding-wrapper/types.ts +37 -0
- package/src/list/styles.ts +1 -1
- package/src/radio/styles.ts +1 -1
- package/src/switch/Switch.tsx +1 -1
- package/src/switch/styles.ts +1 -1
- package/src/text-field/TextField.tsx +1 -1
- package/src/text-field/styles.ts +1 -2
- package/src/typography/Typography.tsx +2 -0
- package/src/test-utils/render-with-theme.tsx +0 -13
- package/src/utils/color.ts +0 -64
- package/src/utils/elevation.ts +0 -33
- package/src/utils/icon.ts +0 -30
- package/src/utils/rtl.ts +0 -19
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onlynative/components",
|
|
3
|
-
"version": "0.1.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"description": "Material Design 3 UI components for React Native — Button, Card, Chip, TextField, and more.",
|
|
5
5
|
"private": false,
|
|
6
6
|
"sideEffects": false,
|
|
@@ -74,6 +74,11 @@
|
|
|
74
74
|
"types": "./dist/list/index.d.ts",
|
|
75
75
|
"react-native": "./src/list/index.ts",
|
|
76
76
|
"default": "./dist/list/index.js"
|
|
77
|
+
},
|
|
78
|
+
"./keyboard-avoiding-wrapper": {
|
|
79
|
+
"types": "./dist/keyboard-avoiding-wrapper/index.d.ts",
|
|
80
|
+
"react-native": "./src/keyboard-avoiding-wrapper/index.ts",
|
|
81
|
+
"default": "./dist/keyboard-avoiding-wrapper/index.js"
|
|
77
82
|
}
|
|
78
83
|
},
|
|
79
84
|
"typesVersions": {
|
|
@@ -113,6 +118,9 @@
|
|
|
113
118
|
],
|
|
114
119
|
"list": [
|
|
115
120
|
"dist/list/index.d.ts"
|
|
121
|
+
],
|
|
122
|
+
"keyboard-avoiding-wrapper": [
|
|
123
|
+
"dist/keyboard-avoiding-wrapper/index.d.ts"
|
|
116
124
|
]
|
|
117
125
|
}
|
|
118
126
|
},
|
|
@@ -140,13 +148,14 @@
|
|
|
140
148
|
"material-you"
|
|
141
149
|
],
|
|
142
150
|
"scripts": {
|
|
143
|
-
"build": "tsup src/index.ts src/typography/index.ts src/layout/index.ts src/button/index.ts src/icon-button/index.ts src/appbar/index.ts src/card/index.ts src/chip/index.ts src/checkbox/index.ts src/radio/index.ts src/switch/index.ts src/text-field/index.ts src/list/index.ts --dts --format cjs --outDir dist --clean",
|
|
151
|
+
"build": "tsup src/index.ts src/typography/index.ts src/layout/index.ts src/button/index.ts src/icon-button/index.ts src/appbar/index.ts src/card/index.ts src/chip/index.ts src/checkbox/index.ts src/radio/index.ts src/switch/index.ts src/text-field/index.ts src/list/index.ts src/keyboard-avoiding-wrapper/index.ts --dts --format cjs --outDir dist --clean",
|
|
144
152
|
"typecheck": "tsc --noEmit",
|
|
145
153
|
"test": "jest --passWithNoTests"
|
|
146
154
|
},
|
|
147
155
|
"peerDependencies": {
|
|
148
156
|
"@expo/vector-icons": ">=14.0.0",
|
|
149
|
-
"@onlynative/core": ">=0.1.0
|
|
157
|
+
"@onlynative/core": ">=0.1.0",
|
|
158
|
+
"@onlynative/utils": ">=0.1.0-alpha.3",
|
|
150
159
|
"react": ">=18.0.0",
|
|
151
160
|
"react-native": ">=0.72.0",
|
|
152
161
|
"react-native-safe-area-context": ">=4.0.0"
|
|
@@ -159,6 +168,7 @@
|
|
|
159
168
|
"devDependencies": {
|
|
160
169
|
"@react-native/babel-preset": "^0.81.5",
|
|
161
170
|
"@onlynative/core": "workspace:*",
|
|
171
|
+
"@onlynative/utils": "workspace:*",
|
|
162
172
|
"@testing-library/react-native": "^13.3.3",
|
|
163
173
|
"@types/jest": "^29.5.14",
|
|
164
174
|
"@types/react": "^19.0.0",
|
package/src/appbar/AppBar.tsx
CHANGED
|
@@ -9,7 +9,7 @@ import { IconButton } from '../icon-button'
|
|
|
9
9
|
import type { IconButtonProps } from '../icon-button'
|
|
10
10
|
import { Typography } from '../typography'
|
|
11
11
|
import type { TypographyVariant } from '../typography'
|
|
12
|
-
import { selectRTL } from '
|
|
12
|
+
import { selectRTL } from '@onlynative/utils'
|
|
13
13
|
import { createStyles } from './styles'
|
|
14
14
|
import type { AppBarProps } from './types'
|
|
15
15
|
|
package/src/button/Button.tsx
CHANGED
|
@@ -5,7 +5,7 @@ import { Text } from 'react-native'
|
|
|
5
5
|
import type { StyleProp, ViewStyle } from 'react-native'
|
|
6
6
|
import { useTheme } from '@onlynative/core'
|
|
7
7
|
|
|
8
|
-
import { getMaterialCommunityIcons } from '
|
|
8
|
+
import { getMaterialCommunityIcons } from '@onlynative/utils'
|
|
9
9
|
import { createStyles } from './styles'
|
|
10
10
|
import type { ButtonProps } from './types'
|
|
11
11
|
|
package/src/button/styles.ts
CHANGED
|
@@ -2,8 +2,7 @@ import { StyleSheet } from 'react-native'
|
|
|
2
2
|
import type { MaterialTheme } from '@onlynative/core'
|
|
3
3
|
|
|
4
4
|
import type { ButtonVariant } from './types'
|
|
5
|
-
import { alphaColor, blendColor } from '
|
|
6
|
-
import { elevationStyle } from '../utils/elevation'
|
|
5
|
+
import { alphaColor, blendColor, elevationStyle } from '@onlynative/utils'
|
|
7
6
|
|
|
8
7
|
interface VariantColors {
|
|
9
8
|
backgroundColor: string
|
package/src/card/styles.ts
CHANGED
|
@@ -2,8 +2,7 @@ import { StyleSheet } from 'react-native'
|
|
|
2
2
|
import type { MaterialTheme } from '@onlynative/core'
|
|
3
3
|
|
|
4
4
|
import type { CardVariant } from './types'
|
|
5
|
-
import { alphaColor, blendColor } from '
|
|
6
|
-
import { elevationStyle } from '../utils/elevation'
|
|
5
|
+
import { alphaColor, blendColor, elevationStyle } from '@onlynative/utils'
|
|
7
6
|
|
|
8
7
|
interface VariantColors {
|
|
9
8
|
backgroundColor: string
|
|
@@ -3,7 +3,7 @@ import { Platform, Pressable, StyleSheet, View } from 'react-native'
|
|
|
3
3
|
import type { StyleProp, ViewStyle } from 'react-native'
|
|
4
4
|
import { useTheme } from '@onlynative/core'
|
|
5
5
|
|
|
6
|
-
import { getMaterialCommunityIcons } from '
|
|
6
|
+
import { getMaterialCommunityIcons } from '@onlynative/utils'
|
|
7
7
|
import { createStyles } from './styles'
|
|
8
8
|
import type { CheckboxProps } from './types'
|
|
9
9
|
|
package/src/checkbox/styles.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { StyleSheet } from 'react-native'
|
|
2
2
|
import type { MaterialTheme } from '@onlynative/core'
|
|
3
3
|
|
|
4
|
-
import { alphaColor, blendColor } from '
|
|
4
|
+
import { alphaColor, blendColor } from '@onlynative/utils'
|
|
5
5
|
|
|
6
6
|
interface BoxColors {
|
|
7
7
|
backgroundColor: string
|
package/src/chip/Chip.tsx
CHANGED
|
@@ -3,7 +3,7 @@ import { Platform, Pressable, StyleSheet, Text, View } from 'react-native'
|
|
|
3
3
|
import type { StyleProp, ViewStyle } from 'react-native'
|
|
4
4
|
import { useTheme } from '@onlynative/core'
|
|
5
5
|
|
|
6
|
-
import { getMaterialCommunityIcons } from '
|
|
6
|
+
import { getMaterialCommunityIcons } from '@onlynative/utils'
|
|
7
7
|
import { createStyles } from './styles'
|
|
8
8
|
import type { ChipProps } from './types'
|
|
9
9
|
|
package/src/chip/styles.ts
CHANGED
|
@@ -2,8 +2,7 @@ import { StyleSheet } from 'react-native'
|
|
|
2
2
|
import type { MaterialTheme } from '@onlynative/core'
|
|
3
3
|
|
|
4
4
|
import type { ChipVariant } from './types'
|
|
5
|
-
import { alphaColor, blendColor } from '
|
|
6
|
-
import { elevationStyle } from '../utils/elevation'
|
|
5
|
+
import { alphaColor, blendColor, elevationStyle } from '@onlynative/utils'
|
|
7
6
|
|
|
8
7
|
interface VariantColors {
|
|
9
8
|
backgroundColor: string
|
|
@@ -3,14 +3,17 @@ import { Pressable } from 'react-native'
|
|
|
3
3
|
import type { StyleProp, ViewStyle } from 'react-native'
|
|
4
4
|
import { useTheme } from '@onlynative/core'
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
alphaColor,
|
|
8
|
+
blendColor,
|
|
9
|
+
getMaterialCommunityIcons,
|
|
10
|
+
} from '@onlynative/utils'
|
|
7
11
|
import { createStyles } from './styles'
|
|
8
12
|
import type {
|
|
9
13
|
IconButtonProps,
|
|
10
14
|
IconButtonSize,
|
|
11
15
|
IconButtonVariant,
|
|
12
16
|
} from './types'
|
|
13
|
-
import { alphaColor, blendColor } from '../utils/color'
|
|
14
17
|
|
|
15
18
|
function getIconColor(
|
|
16
19
|
variant: IconButtonVariant,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { StyleSheet } from 'react-native'
|
|
2
2
|
import type { MaterialTheme } from '@onlynative/core'
|
|
3
|
-
import { alphaColor, blendColor } from '
|
|
3
|
+
import { alphaColor, blendColor } from '@onlynative/utils'
|
|
4
4
|
|
|
5
5
|
export function createStyles(theme: MaterialTheme) {
|
|
6
6
|
const disabledContainerColor = alphaColor(theme.colors.onSurface, 0.12)
|
package/src/index.ts
CHANGED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { useEffect } from 'react'
|
|
2
|
+
import {
|
|
3
|
+
Keyboard,
|
|
4
|
+
KeyboardAvoidingView,
|
|
5
|
+
Platform,
|
|
6
|
+
ScrollView,
|
|
7
|
+
} from 'react-native'
|
|
8
|
+
|
|
9
|
+
import type { KeyboardAvoidingWrapperProps } from './types'
|
|
10
|
+
import { styles } from './styles'
|
|
11
|
+
|
|
12
|
+
const isIOS = Platform.OS === 'ios'
|
|
13
|
+
|
|
14
|
+
export function KeyboardAvoidingWrapper({
|
|
15
|
+
children,
|
|
16
|
+
behavior = 'padding',
|
|
17
|
+
keyboardVerticalOffset = 0,
|
|
18
|
+
enabled = true,
|
|
19
|
+
scrollViewProps,
|
|
20
|
+
onKeyboardShow,
|
|
21
|
+
onKeyboardHide,
|
|
22
|
+
style,
|
|
23
|
+
contentContainerStyle,
|
|
24
|
+
}: KeyboardAvoidingWrapperProps) {
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
const subscriptions: ReturnType<typeof Keyboard.addListener>[] = []
|
|
27
|
+
|
|
28
|
+
if (onKeyboardShow) {
|
|
29
|
+
const showEvent = isIOS
|
|
30
|
+
? 'keyboardWillShow'
|
|
31
|
+
: 'keyboardDidShow'
|
|
32
|
+
subscriptions.push(
|
|
33
|
+
Keyboard.addListener(showEvent, onKeyboardShow),
|
|
34
|
+
)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (onKeyboardHide) {
|
|
38
|
+
const hideEvent = isIOS
|
|
39
|
+
? 'keyboardWillHide'
|
|
40
|
+
: 'keyboardDidHide'
|
|
41
|
+
subscriptions.push(
|
|
42
|
+
Keyboard.addListener(hideEvent, onKeyboardHide),
|
|
43
|
+
)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return () => {
|
|
47
|
+
subscriptions.forEach((sub) => sub.remove())
|
|
48
|
+
}
|
|
49
|
+
}, [onKeyboardShow, onKeyboardHide])
|
|
50
|
+
|
|
51
|
+
return (
|
|
52
|
+
<KeyboardAvoidingView
|
|
53
|
+
style={[styles.root, style]}
|
|
54
|
+
behavior={behavior}
|
|
55
|
+
keyboardVerticalOffset={keyboardVerticalOffset}
|
|
56
|
+
enabled={!isIOS && enabled}
|
|
57
|
+
>
|
|
58
|
+
<ScrollView
|
|
59
|
+
automaticallyAdjustKeyboardInsets={isIOS && enabled}
|
|
60
|
+
keyboardShouldPersistTaps="handled"
|
|
61
|
+
showsVerticalScrollIndicator={false}
|
|
62
|
+
{...scrollViewProps}
|
|
63
|
+
contentContainerStyle={[styles.container, contentContainerStyle]}
|
|
64
|
+
>
|
|
65
|
+
{children}
|
|
66
|
+
</ScrollView>
|
|
67
|
+
</KeyboardAvoidingView>
|
|
68
|
+
)
|
|
69
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { PropsWithChildren } from 'react'
|
|
2
|
+
import type {
|
|
3
|
+
KeyboardAvoidingViewProps,
|
|
4
|
+
KeyboardEvent,
|
|
5
|
+
ScrollViewProps,
|
|
6
|
+
StyleProp,
|
|
7
|
+
ViewStyle,
|
|
8
|
+
} from 'react-native'
|
|
9
|
+
|
|
10
|
+
export interface KeyboardAvoidingWrapperProps extends PropsWithChildren {
|
|
11
|
+
/**
|
|
12
|
+
* Keyboard avoidance strategy.
|
|
13
|
+
* @default 'padding'
|
|
14
|
+
*/
|
|
15
|
+
behavior?: KeyboardAvoidingViewProps['behavior']
|
|
16
|
+
/**
|
|
17
|
+
* Extra offset added to the keyboard height calculation.
|
|
18
|
+
* Useful for accounting for headers or tab bars.
|
|
19
|
+
* @default 0
|
|
20
|
+
*/
|
|
21
|
+
keyboardVerticalOffset?: number
|
|
22
|
+
/**
|
|
23
|
+
* Enable or disable the keyboard avoiding behavior.
|
|
24
|
+
* @default true
|
|
25
|
+
*/
|
|
26
|
+
enabled?: boolean
|
|
27
|
+
/** Props forwarded to the inner `ScrollView`. */
|
|
28
|
+
scrollViewProps?: ScrollViewProps
|
|
29
|
+
/** Called when the keyboard is about to show (iOS) or has shown (Android). */
|
|
30
|
+
onKeyboardShow?: (event: KeyboardEvent) => void
|
|
31
|
+
/** Called when the keyboard is about to hide (iOS) or has hidden (Android). */
|
|
32
|
+
onKeyboardHide?: (event: KeyboardEvent) => void
|
|
33
|
+
/** Style applied to the outer `KeyboardAvoidingView`. */
|
|
34
|
+
style?: StyleProp<ViewStyle>
|
|
35
|
+
/** Style applied to the inner `ScrollView` contentContainerStyle. */
|
|
36
|
+
contentContainerStyle?: StyleProp<ViewStyle>
|
|
37
|
+
}
|
package/src/list/styles.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { StyleSheet } from 'react-native'
|
|
|
2
2
|
import type { MaterialTheme } from '@onlynative/core'
|
|
3
3
|
|
|
4
4
|
import type { ListItemLines } from './types'
|
|
5
|
-
import { alphaColor, blendColor } from '
|
|
5
|
+
import { alphaColor, blendColor } from '@onlynative/utils'
|
|
6
6
|
|
|
7
7
|
const ITEM_PADDING_VERTICAL = 12
|
|
8
8
|
const INSET_START = 56
|
package/src/radio/styles.ts
CHANGED
package/src/switch/Switch.tsx
CHANGED
|
@@ -3,7 +3,7 @@ import { Platform, Pressable, StyleSheet, View } from 'react-native'
|
|
|
3
3
|
import type { StyleProp, ViewStyle } from 'react-native'
|
|
4
4
|
import { useTheme } from '@onlynative/core'
|
|
5
5
|
|
|
6
|
-
import { getMaterialCommunityIcons } from '
|
|
6
|
+
import { getMaterialCommunityIcons } from '@onlynative/utils'
|
|
7
7
|
import { createStyles } from './styles'
|
|
8
8
|
import type { SwitchProps } from './types'
|
|
9
9
|
|
package/src/switch/styles.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { StyleSheet } from 'react-native'
|
|
2
2
|
import type { MaterialTheme } from '@onlynative/core'
|
|
3
3
|
|
|
4
|
-
import { alphaColor, blendColor } from '
|
|
4
|
+
import { alphaColor, blendColor } from '@onlynative/utils'
|
|
5
5
|
|
|
6
6
|
interface TrackColors {
|
|
7
7
|
trackColor: string
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
import type { NativeSyntheticEvent, TargetedEvent } from 'react-native'
|
|
11
11
|
import { useTheme } from '@onlynative/core'
|
|
12
12
|
|
|
13
|
-
import { getMaterialCommunityIcons } from '
|
|
13
|
+
import { getMaterialCommunityIcons } from '@onlynative/utils'
|
|
14
14
|
import { createStyles, labelPositions } from './styles'
|
|
15
15
|
import type { TextFieldProps } from './types'
|
|
16
16
|
|
package/src/text-field/styles.ts
CHANGED
|
@@ -2,8 +2,7 @@ import { StyleSheet } from 'react-native'
|
|
|
2
2
|
import type { MaterialTheme } from '@onlynative/core'
|
|
3
3
|
|
|
4
4
|
import type { TextFieldVariant } from './types'
|
|
5
|
-
import { alphaColor } from '
|
|
6
|
-
import { transformOrigin } from '../utils/rtl'
|
|
5
|
+
import { alphaColor, transformOrigin } from '@onlynative/utils'
|
|
7
6
|
|
|
8
7
|
const CONTAINER_HEIGHT = 56
|
|
9
8
|
const ICON_SIZE = 24
|
|
@@ -51,6 +51,8 @@ export function Typography({
|
|
|
51
51
|
|
|
52
52
|
// When the consumer overrides fontSize via style, auto-adjust lineHeight
|
|
53
53
|
// proportionally so text isn't clipped inside overflow:hidden containers.
|
|
54
|
+
// Skipped when: no style prop (theme lineHeight is already proportional),
|
|
55
|
+
// no fontSize override, or consumer explicitly sets lineHeight.
|
|
54
56
|
const lineHeightFix = useMemo(() => {
|
|
55
57
|
if (!style) return undefined
|
|
56
58
|
const flat = StyleSheet.flatten(style)
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { render, type RenderOptions } from '@testing-library/react-native'
|
|
2
|
-
import type { ReactElement } from 'react'
|
|
3
|
-
import { ThemeProvider } from '@onlynative/core'
|
|
4
|
-
|
|
5
|
-
export function renderWithTheme(
|
|
6
|
-
ui: ReactElement,
|
|
7
|
-
options?: Omit<RenderOptions, 'wrapper'>,
|
|
8
|
-
) {
|
|
9
|
-
return render(ui, {
|
|
10
|
-
wrapper: ({ children }) => <ThemeProvider>{children}</ThemeProvider>,
|
|
11
|
-
...options,
|
|
12
|
-
})
|
|
13
|
-
}
|
package/src/utils/color.ts
DELETED
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
interface RgbChannels {
|
|
2
|
-
r: number
|
|
3
|
-
g: number
|
|
4
|
-
b: number
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
function parseHexColor(color: string): RgbChannels | null {
|
|
8
|
-
const normalized = color.replace('#', '')
|
|
9
|
-
|
|
10
|
-
if (normalized.length !== 6 && normalized.length !== 8) {
|
|
11
|
-
return null
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const r = Number.parseInt(normalized.slice(0, 2), 16)
|
|
15
|
-
const g = Number.parseInt(normalized.slice(2, 4), 16)
|
|
16
|
-
const b = Number.parseInt(normalized.slice(4, 6), 16)
|
|
17
|
-
|
|
18
|
-
if (Number.isNaN(r) || Number.isNaN(g) || Number.isNaN(b)) {
|
|
19
|
-
return null
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
return { r, g, b }
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
function clampAlpha(alpha: number): number {
|
|
26
|
-
return Math.max(0, Math.min(1, alpha))
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export function alphaColor(color: string, alpha: number): string {
|
|
30
|
-
const channels = parseHexColor(color)
|
|
31
|
-
const boundedAlpha = clampAlpha(alpha)
|
|
32
|
-
|
|
33
|
-
if (!channels) {
|
|
34
|
-
return color
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
return `rgba(${channels.r}, ${channels.g}, ${channels.b}, ${boundedAlpha})`
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export function blendColor(
|
|
41
|
-
base: string,
|
|
42
|
-
overlay: string,
|
|
43
|
-
overlayAlpha: number,
|
|
44
|
-
): string {
|
|
45
|
-
const baseChannels = parseHexColor(base)
|
|
46
|
-
const overlayChannels = parseHexColor(overlay)
|
|
47
|
-
const boundedAlpha = clampAlpha(overlayAlpha)
|
|
48
|
-
|
|
49
|
-
if (!baseChannels || !overlayChannels) {
|
|
50
|
-
return alphaColor(overlay, boundedAlpha)
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const r = Math.round(
|
|
54
|
-
(1 - boundedAlpha) * baseChannels.r + boundedAlpha * overlayChannels.r,
|
|
55
|
-
)
|
|
56
|
-
const g = Math.round(
|
|
57
|
-
(1 - boundedAlpha) * baseChannels.g + boundedAlpha * overlayChannels.g,
|
|
58
|
-
)
|
|
59
|
-
const b = Math.round(
|
|
60
|
-
(1 - boundedAlpha) * baseChannels.b + boundedAlpha * overlayChannels.b,
|
|
61
|
-
)
|
|
62
|
-
|
|
63
|
-
return `rgb(${r}, ${g}, ${b})`
|
|
64
|
-
}
|
package/src/utils/elevation.ts
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { Platform } from 'react-native'
|
|
2
|
-
import type { ViewStyle } from 'react-native'
|
|
3
|
-
import type { ElevationLevel } from '@onlynative/core'
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Converts a theme elevation level into platform-appropriate shadow styles.
|
|
7
|
-
* - Native: uses shadow* props + elevation
|
|
8
|
-
* - Web: uses boxShadow string
|
|
9
|
-
*/
|
|
10
|
-
export function elevationStyle(level: ElevationLevel): ViewStyle {
|
|
11
|
-
if (Platform.OS === 'web') {
|
|
12
|
-
const { shadowOffset, shadowOpacity, shadowRadius } = level
|
|
13
|
-
|
|
14
|
-
if (shadowOpacity === 0) {
|
|
15
|
-
return { boxShadow: 'none' } as ViewStyle
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
return {
|
|
19
|
-
boxShadow: `${shadowOffset.width}px ${shadowOffset.height}px ${shadowRadius}px rgba(0, 0, 0, ${shadowOpacity})`,
|
|
20
|
-
} as ViewStyle
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
return {
|
|
24
|
-
shadowColor: level.shadowColor,
|
|
25
|
-
shadowOffset: {
|
|
26
|
-
width: level.shadowOffset.width,
|
|
27
|
-
height: level.shadowOffset.height,
|
|
28
|
-
},
|
|
29
|
-
shadowOpacity: level.shadowOpacity,
|
|
30
|
-
shadowRadius: level.shadowRadius,
|
|
31
|
-
elevation: level.elevation,
|
|
32
|
-
}
|
|
33
|
-
}
|
package/src/utils/icon.ts
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
2
|
-
let _MCIcons: any = null
|
|
3
|
-
let _resolved = false
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Lazily resolves MaterialCommunityIcons from `@expo/vector-icons`.
|
|
7
|
-
*
|
|
8
|
-
* Called at render time (not module load) so that components can be
|
|
9
|
-
* imported without `@expo/vector-icons` installed — the error only
|
|
10
|
-
* fires when an icon is actually rendered.
|
|
11
|
-
*/
|
|
12
|
-
export function getMaterialCommunityIcons() {
|
|
13
|
-
if (!_resolved) {
|
|
14
|
-
_resolved = true
|
|
15
|
-
try {
|
|
16
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
17
|
-
const mod = require('@expo/vector-icons/MaterialCommunityIcons')
|
|
18
|
-
_MCIcons = mod.default || mod
|
|
19
|
-
} catch {
|
|
20
|
-
_MCIcons = null
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
if (!_MCIcons) {
|
|
24
|
-
throw new Error(
|
|
25
|
-
'@expo/vector-icons is required for icon support. ' +
|
|
26
|
-
'Install it with: npx expo install @expo/vector-icons',
|
|
27
|
-
)
|
|
28
|
-
}
|
|
29
|
-
return _MCIcons
|
|
30
|
-
}
|
package/src/utils/rtl.ts
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { I18nManager } from 'react-native'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Returns the appropriate transform origin for animations that scale
|
|
5
|
-
* from a horizontal edge (e.g. label shrink in TextField).
|
|
6
|
-
*/
|
|
7
|
-
export function transformOrigin(
|
|
8
|
-
vertical: 'top' | 'center' | 'bottom' = 'top',
|
|
9
|
-
): string {
|
|
10
|
-
return I18nManager.isRTL ? `right ${vertical}` : `left ${vertical}`
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Picks a value based on layout direction.
|
|
15
|
-
* Useful for selecting mirrored icons or other direction-dependent values.
|
|
16
|
-
*/
|
|
17
|
-
export function selectRTL<T>(ltr: T, rtl: T): T {
|
|
18
|
-
return I18nManager.isRTL ? rtl : ltr
|
|
19
|
-
}
|