@apple-pie/slice-native 0.1.6 → 0.1.7
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 +138 -261
- package/SliceNative.podspec +24 -0
- package/dist/cjs/components.js +4 -0
- package/dist/cjs/hooks.js +2 -0
- package/dist/cjs/index.js +9 -0
- package/dist/cjs/src/components/SliceBackgroundBlur/SliceBackgroundBlur.js +11 -0
- package/dist/cjs/src/components/SliceButton/SliceButton.js +50 -23
- package/dist/cjs/src/components/SliceLiquidGlassView/SliceLiquidGlassView.js +12 -0
- package/dist/cjs/src/components/SliceTextInput/SliceTextInput.js +39 -9
- package/dist/cjs/src/hooks/useDeviceCapabilities/useDeviceCapabilities.js +19 -0
- package/dist/cjs/src/utils/sizes/sizes.js +40 -0
- package/dist/cjs/utils.js +3 -0
- package/dist/esm/components.mjs +2 -0
- package/dist/esm/hooks.mjs +1 -0
- package/dist/esm/index.mjs +4 -0
- package/dist/esm/src/components/SliceBackgroundBlur/SliceBackgroundBlur.mjs +9 -0
- package/dist/esm/src/components/SliceButton/SliceButton.mjs +50 -23
- package/dist/esm/src/components/SliceLiquidGlassView/SliceLiquidGlassView.mjs +10 -0
- package/dist/esm/src/components/SliceTextInput/SliceTextInput.mjs +39 -9
- package/dist/esm/src/hooks/useDeviceCapabilities/useDeviceCapabilities.mjs +17 -0
- package/dist/esm/src/utils/sizes/sizes.mjs +37 -0
- package/dist/esm/utils.mjs +1 -0
- package/dist/react-native/native/src/components/SliceBackgroundBlur/SliceBackgroundBlur.js +6 -0
- package/dist/react-native/native/src/components/SliceBackgroundBlur/SliceBackgroundBlur.native.js +6 -0
- package/dist/react-native/native/src/components/SliceBackgroundBlur/_types.js +1 -0
- package/dist/react-native/native/src/components/SliceBackgroundBlur/index.js +1 -0
- package/dist/react-native/native/src/components/SliceButton/SliceButton.js +141 -0
- package/dist/react-native/native/src/components/SliceButton/_types.js +1 -0
- package/dist/react-native/native/src/components/SliceButton/index.js +1 -0
- package/dist/react-native/native/src/components/SliceIcon/SliceIcon.js +15 -0
- package/dist/react-native/native/src/components/SliceIcon/_types.js +1 -0
- package/dist/react-native/native/src/components/SliceIcon/iconRegistry.js +663 -0
- package/dist/react-native/native/src/components/SliceIcon/icons.js +140 -0
- package/dist/react-native/native/src/components/SliceIcon/index.js +2 -0
- package/dist/react-native/native/src/components/SliceLiquidGlassView/SliceLiquidGlassView.ios.js +6 -0
- package/dist/react-native/native/src/components/SliceLiquidGlassView/SliceLiquidGlassView.js +7 -0
- package/dist/react-native/native/src/components/SliceLiquidGlassView/_types.js +1 -0
- package/dist/react-native/native/src/components/SliceLiquidGlassView/index.js +1 -0
- package/dist/react-native/native/src/components/SliceText/SliceText.js +16 -0
- package/dist/react-native/native/src/components/SliceText/_types.js +1 -0
- package/dist/react-native/native/src/components/SliceText/index.js +1 -0
- package/dist/react-native/native/src/components/SliceTextInput/SliceTextInput.js +111 -0
- package/dist/react-native/native/src/components/SliceTextInput/_types.js +1 -0
- package/dist/react-native/native/src/components/SliceTextInput/index.js +1 -0
- package/dist/react-native/native/src/components/index.js +6 -0
- package/dist/react-native/native/src/hooks/index.js +2 -0
- package/dist/react-native/native/src/hooks/useCreateThemedStyles/index.js +1 -0
- package/dist/react-native/native/src/hooks/useCreateThemedStyles/useCreateThemedStyles.js +8 -0
- package/dist/react-native/native/src/hooks/useDeviceCapabilities/_types.js +1 -0
- package/dist/react-native/native/src/hooks/useDeviceCapabilities/index.js +1 -0
- package/dist/react-native/native/src/hooks/useDeviceCapabilities/useDeviceCapabilities.js +14 -0
- package/dist/react-native/native/src/hooks/useDeviceCapabilities/useDeviceCapabilities.native.js +23 -0
- package/dist/react-native/native/src/index.js +6 -0
- package/dist/react-native/native/src/providers/SliceThemeProvider.js +30 -0
- package/dist/react-native/native/src/providers/index.js +1 -0
- package/dist/react-native/native/src/specs/BackgroundBlurNativeComponent.ts +16 -0
- package/dist/react-native/native/src/specs/LiquidGlassNativeComponent.ts +18 -0
- package/dist/react-native/native/src/specs/NativeDeviceCapabilities.ts +13 -0
- package/dist/react-native/native/src/theme/index.js +69 -0
- package/dist/react-native/native/src/theme/motion.js +43 -0
- package/dist/react-native/native/src/types/index.js +1 -0
- package/dist/react-native/native/src/types/sharedTypes.js +1 -0
- package/dist/react-native/native/src/utils/index.js +2 -0
- package/dist/react-native/native/src/utils/sizes/index.js +1 -0
- package/dist/react-native/native/src/utils/sizes/sizes.js +35 -0
- package/dist/react-native/native/src/utils/typography/index.js +1 -0
- package/dist/react-native/native/src/utils/typography/typography.js +13 -0
- package/dist/react-native/src/theme/colors/colors.js +385 -0
- package/dist/react-native/src/theme/colors/types.js +1 -0
- package/dist/react-native/src/theme/corners/corners.js +10 -0
- package/dist/react-native/src/theme/corners/types.js +1 -0
- package/dist/react-native/src/theme/elevations/_types.js +1 -0
- package/dist/react-native/src/theme/elevations/elevations.js +13 -0
- package/dist/react-native/src/theme/motion/_types.js +1 -0
- package/dist/react-native/src/theme/motion/motion.js +11 -0
- package/dist/react-native/src/theme/spacing/_types.js +1 -0
- package/dist/react-native/src/theme/spacing/spacing.js +10 -0
- package/dist/react-native/src/theme/type/type.js +371 -0
- package/dist/react-native/src/theme/type/types.js +1 -0
- package/dist/types/native/src/components/SliceBackgroundBlur/SliceBackgroundBlur.d.ts +3 -0
- package/dist/types/native/src/components/SliceBackgroundBlur/SliceBackgroundBlur.native.d.ts +2 -0
- package/dist/types/native/src/components/SliceBackgroundBlur/_types.d.ts +24 -0
- package/dist/types/native/src/components/SliceBackgroundBlur/index.d.ts +2 -0
- package/dist/types/native/src/components/SliceButton/_types.d.ts +33 -2
- package/dist/types/native/src/components/SliceLiquidGlassView/SliceLiquidGlassView.d.ts +3 -0
- package/dist/types/native/src/components/SliceLiquidGlassView/SliceLiquidGlassView.ios.d.ts +2 -0
- package/dist/types/native/src/components/SliceLiquidGlassView/_types.d.ts +17 -0
- package/dist/types/native/src/components/SliceLiquidGlassView/index.d.ts +2 -0
- package/dist/types/native/src/components/SliceTextInput/_types.d.ts +23 -1
- package/dist/types/native/src/components/index.d.ts +4 -0
- package/dist/types/native/src/hooks/index.d.ts +2 -0
- package/dist/types/native/src/hooks/useDeviceCapabilities/_types.d.ts +17 -0
- package/dist/types/native/src/hooks/useDeviceCapabilities/index.d.ts +2 -0
- package/dist/types/native/src/hooks/useDeviceCapabilities/useDeviceCapabilities.d.ts +3 -0
- package/dist/types/native/src/hooks/useDeviceCapabilities/useDeviceCapabilities.native.d.ts +7 -0
- package/dist/types/native/src/index.d.ts +12 -0
- package/dist/types/native/src/specs/BackgroundBlurNativeComponent.d.ts +9 -0
- package/dist/types/native/src/specs/LiquidGlassNativeComponent.d.ts +9 -0
- package/dist/types/native/src/specs/NativeDeviceCapabilities.d.ts +11 -0
- package/dist/types/native/src/types/index.d.ts +1 -0
- package/dist/types/native/src/types/sharedTypes.d.ts +14 -0
- package/dist/types/native/src/utils/index.d.ts +1 -0
- package/dist/types/native/src/utils/sizes/index.d.ts +1 -0
- package/dist/types/native/src/utils/sizes/sizes.d.ts +7 -0
- package/package.json +30 -13
- package/platform/android/build.gradle +22 -0
- package/platform/android/src/main/AndroidManifest.xml +1 -0
- package/platform/android/src/main/java/com/slice/SliceBackgroundBlurManager.java +28 -0
- package/platform/android/src/main/java/com/slice/SliceBackgroundBlurView.java +98 -0
- package/platform/android/src/main/java/com/slice/SliceDeviceCapabilitiesModule.java +25 -0
- package/platform/android/src/main/java/com/slice/SlicePackage.java +25 -0
- package/platform/ios/BackgroundBlurSurface.swift +89 -0
- package/platform/ios/LiquidGlassSurface.swift +82 -0
- package/platform/ios/RCTBackgroundBlurView.h +3 -0
- package/platform/ios/RCTBackgroundBlurView.mm +42 -0
- package/platform/ios/RCTLiquidGlassView.h +8 -0
- package/platform/ios/RCTLiquidGlassView.mm +73 -0
- package/platform/ios/SliceDeviceCapabilities.h +4 -0
- package/platform/ios/SliceDeviceCapabilities.mm +35 -0
- package/react-native.config.js +1 -0
- package/src/specs/BackgroundBlurNativeComponent.ts +16 -0
- package/src/specs/LiquidGlassNativeComponent.ts +18 -0
- package/src/specs/NativeDeviceCapabilities.ts +13 -0
- package/dist/types/native/index.d.ts +0 -8
|
@@ -5,7 +5,10 @@ var react = require('react');
|
|
|
5
5
|
var reactNative = require('react-native');
|
|
6
6
|
var Reanimated = require('react-native-reanimated');
|
|
7
7
|
var SliceThemeProvider = require('../../providers/SliceThemeProvider.js');
|
|
8
|
+
var useDeviceCapabilities = require('../../hooks/useDeviceCapabilities/useDeviceCapabilities.js');
|
|
9
|
+
var sizes = require('../../utils/sizes/sizes.js');
|
|
8
10
|
var SliceIcon = require('../SliceIcon/SliceIcon.js');
|
|
11
|
+
var SliceLiquidGlassView = require('../SliceLiquidGlassView/SliceLiquidGlassView.js');
|
|
9
12
|
var SliceText = require('../SliceText/SliceText.js');
|
|
10
13
|
|
|
11
14
|
/**
|
|
@@ -13,10 +16,12 @@ var SliceText = require('../SliceText/SliceText.js');
|
|
|
13
16
|
*/
|
|
14
17
|
function SliceButton(props) {
|
|
15
18
|
const { colors, name } = SliceThemeProvider.useSliceTheme();
|
|
19
|
+
const { supportsLiquidGlass } = useDeviceCapabilities.useDeviceCapabilities();
|
|
16
20
|
const isLightTheme = name.includes('light');
|
|
17
|
-
const { children, onPress, disabled = false, icon, iconPosition = 'left', iconSize = 24, animatedStyle, variant = 'primary', layout, presence, accessibilityState, ...pressableProps } = props;
|
|
21
|
+
const { children, onPress, disabled = false, icon, iconPosition = 'left', iconSize = 24, size = 'm', animatedStyle, variant = 'primary', layout, presence, accessibilityState, liquidGlassBackground, borderRadius = 'pill', borderWidth, borderColor = colors['core-outline-secondary'], backgroundColor, ...pressableProps } = props;
|
|
22
|
+
const { fallbackColor, glassTintColor, glassStyle } = liquidGlassBackground ?? {};
|
|
23
|
+
const applyLiquidGlass = Boolean(liquidGlassBackground) && supportsLiquidGlass;
|
|
18
24
|
const hasLabel = children !== undefined && children !== null && children !== false && children !== '';
|
|
19
|
-
// adjust padding for the visual discrepancy because of the intrinsic padding of each icon
|
|
20
25
|
const pressableStyle = react.useMemo(() => {
|
|
21
26
|
if (!hasLabel)
|
|
22
27
|
return reactNative.StyleSheet.compose(styles.pressable, styles.pressableNoLabel);
|
|
@@ -26,15 +31,13 @@ function SliceButton(props) {
|
|
|
26
31
|
return reactNative.StyleSheet.compose(styles.pressable, styles.pressableIconRight);
|
|
27
32
|
return styles.pressable;
|
|
28
33
|
}, [icon, iconPosition, hasLabel]);
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
return
|
|
34
|
-
}, [
|
|
35
|
-
// memoize the color styles to apply to the button/label based on variant and disabled state
|
|
34
|
+
const bgColor = react.useMemo(() => {
|
|
35
|
+
if (applyLiquidGlass)
|
|
36
|
+
return 'transparent';
|
|
37
|
+
const baseBGColor = variant === 'primary' ? colors['core-button-primary'] : colors['core-surface-primary'];
|
|
38
|
+
return backgroundColor ?? fallbackColor ?? baseBGColor;
|
|
39
|
+
}, [applyLiquidGlass, backgroundColor, fallbackColor, colors, variant]);
|
|
36
40
|
const colorStyles = react.useMemo(() => {
|
|
37
|
-
const bgColor = variant === 'primary' ? colors['core-button-primary'] : colors['core-surface-primary'];
|
|
38
41
|
const disabledBGColor = disabled ? colors['core-surface-secondary'] : undefined;
|
|
39
42
|
const color = colors['core-text-primary'];
|
|
40
43
|
const disabledColor = disabled ? colors['core-text-disabled'] : undefined;
|
|
@@ -45,7 +48,7 @@ function SliceButton(props) {
|
|
|
45
48
|
: colors['core-link-primary'];
|
|
46
49
|
return reactNative.StyleSheet.create({
|
|
47
50
|
backgroundColor: {
|
|
48
|
-
backgroundColor: disabledBGColor ?? bgColor,
|
|
51
|
+
backgroundColor: applyLiquidGlass ? 'transparent' : (disabledBGColor ?? bgColor),
|
|
49
52
|
},
|
|
50
53
|
textColor: {
|
|
51
54
|
color: disabledColor ?? color,
|
|
@@ -57,16 +60,17 @@ function SliceButton(props) {
|
|
|
57
60
|
color: iconColor,
|
|
58
61
|
},
|
|
59
62
|
});
|
|
60
|
-
}, [
|
|
61
|
-
//
|
|
63
|
+
}, [applyLiquidGlass, disabled, colors, isLightTheme, bgColor]);
|
|
64
|
+
// Preserve variant defaults while allowing an explicit zero-width border.
|
|
62
65
|
const borderStyles = react.useMemo(() => {
|
|
66
|
+
const width = borderWidth ?? (variant === 'primary' ? 0 : 1);
|
|
63
67
|
return reactNative.StyleSheet.create({
|
|
64
68
|
border: {
|
|
65
|
-
borderWidth:
|
|
66
|
-
borderColor
|
|
69
|
+
borderWidth: Number.isFinite(width) ? Math.max(0, width) : 0,
|
|
70
|
+
borderColor,
|
|
67
71
|
},
|
|
68
72
|
});
|
|
69
|
-
}, [variant,
|
|
73
|
+
}, [variant, borderColor, borderWidth]);
|
|
70
74
|
// disable touch events when button is disabled
|
|
71
75
|
const pointerEvents = react.useMemo(() => {
|
|
72
76
|
return reactNative.StyleSheet.create({
|
|
@@ -75,24 +79,47 @@ function SliceButton(props) {
|
|
|
75
79
|
},
|
|
76
80
|
});
|
|
77
81
|
}, [disabled]);
|
|
78
|
-
|
|
82
|
+
// set the button size
|
|
83
|
+
const buttonSize = react.useMemo(() => {
|
|
84
|
+
return reactNative.StyleSheet.create({
|
|
85
|
+
size: {
|
|
86
|
+
minHeight: sizes.sizeToNumber(size),
|
|
87
|
+
width: hasLabel ? 'auto' : sizes.sizeToNumber(size),
|
|
88
|
+
},
|
|
89
|
+
});
|
|
90
|
+
}, [size, hasLabel]);
|
|
91
|
+
// set the button border radius
|
|
92
|
+
const cornerRadius = react.useMemo(() => {
|
|
93
|
+
return reactNative.StyleSheet.create({
|
|
94
|
+
borderRadius: {
|
|
95
|
+
borderRadius: sizes.borderRadiusToNumber(borderRadius),
|
|
96
|
+
},
|
|
97
|
+
});
|
|
98
|
+
}, [borderRadius]);
|
|
99
|
+
return (jsxRuntime.jsx(Reanimated.View, { layout: layout, children: jsxRuntime.jsx(Reanimated.View, { entering: presence?.entering, exiting: presence?.exiting, children: jsxRuntime.jsxs(Reanimated.View, { style: [
|
|
100
|
+
styles.wrapper,
|
|
101
|
+
pointerEvents.pointer,
|
|
102
|
+
colorStyles.backgroundColor,
|
|
103
|
+
buttonSize.size,
|
|
104
|
+
borderStyles.border,
|
|
105
|
+
cornerRadius.borderRadius,
|
|
106
|
+
animatedStyle,
|
|
107
|
+
], children: [applyLiquidGlass && (jsxRuntime.jsx(SliceLiquidGlassView.SliceLiquidGlassView, { cornerRadius: sizes.borderRadiusToNumber(borderRadius), fallbackColor: fallbackColor, glassTintColor: glassTintColor, glassStyle: glassStyle, style: styles.background })), jsxRuntime.jsxs(reactNative.Pressable, { ...pressableProps, accessibilityRole: pressableProps.accessibilityRole ?? 'button', accessibilityState: { ...accessibilityState, disabled }, disabled: disabled, style: pressableStyle, onPress: disabled ? undefined : onPress, android_ripple: pressableProps.android_ripple ?? colorStyles.ripple, children: [icon && iconPosition === 'left' && (jsxRuntime.jsx(SliceIcon.SliceIcon, { name: icon, size: iconSize, strokeColor: colorStyles.icon.color, pointerEvents: "none", accessible: false })), hasLabel && (jsxRuntime.jsx(SliceText.StyledText, { textStyle: 'body-xl-bold', style: colorStyles.textColor, singleLine: true, numberOfLines: 1, ellipsizeMode: 'tail', children: children })), icon && iconPosition === 'right' && (jsxRuntime.jsx(SliceIcon.SliceIcon, { name: icon, size: iconSize, strokeColor: colorStyles.icon.color, pointerEvents: "none", accessible: false }))] })] }) }) }));
|
|
79
108
|
}
|
|
80
109
|
/**
|
|
81
110
|
* Base Styles
|
|
82
111
|
*/
|
|
83
112
|
const styles = reactNative.StyleSheet.create({
|
|
84
113
|
wrapper: {
|
|
85
|
-
|
|
114
|
+
position: 'relative',
|
|
86
115
|
overflow: 'hidden',
|
|
87
116
|
justifyContent: 'center',
|
|
88
117
|
alignItems: 'center',
|
|
89
|
-
height: 48,
|
|
90
118
|
width: 'auto',
|
|
91
119
|
},
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
height: 48,
|
|
120
|
+
background: {
|
|
121
|
+
position: 'absolute',
|
|
122
|
+
inset: 0,
|
|
96
123
|
},
|
|
97
124
|
pressable: {
|
|
98
125
|
flex: 1,
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
4
|
+
var react = require('react');
|
|
5
|
+
var reactNative = require('react-native');
|
|
6
|
+
|
|
7
|
+
/** Android/web fallback. Metro selects SliceLiquidGlassView.ios on iOS. */
|
|
8
|
+
const SliceLiquidGlassView = react.forwardRef(function SliceLiquidGlassView({ glassStyle: _glassStyle, glassTintColor: _glassTintColor, interactive: _interactive, cornerRadius = 24, fallbackColor = 'rgba(128, 128, 128, 0.18)', style, ...props }, ref) {
|
|
9
|
+
return (jsxRuntime.jsx(reactNative.View, { ...props, ref: ref, style: [{ backgroundColor: fallbackColor }, style, { borderRadius: cornerRadius, overflow: 'hidden' }] }));
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
exports.SliceLiquidGlassView = SliceLiquidGlassView;
|
|
@@ -5,12 +5,15 @@ var react = require('react');
|
|
|
5
5
|
var reactNative = require('react-native');
|
|
6
6
|
var Reanimated = require('react-native-reanimated');
|
|
7
7
|
var useCreateThemedStyles = require('../../hooks/useCreateThemedStyles/useCreateThemedStyles.js');
|
|
8
|
+
var SliceThemeProvider = require('../../providers/SliceThemeProvider.js');
|
|
8
9
|
var typography = require('../../utils/typography/typography.js');
|
|
10
|
+
var sizes = require('../../utils/sizes/sizes.js');
|
|
9
11
|
var SliceIcon = require('../SliceIcon/SliceIcon.js');
|
|
10
12
|
|
|
11
13
|
function SliceTextInput(props) {
|
|
12
14
|
const themedStyles = useCreateThemedStyles.useCreateThemedStyles(styles);
|
|
13
|
-
const {
|
|
15
|
+
const { colors } = SliceThemeProvider.useSliceTheme();
|
|
16
|
+
const { didFocus, layout, icon, focused, blurClears = false, iconColor, iconSize = 24, placeholderTextColor = themedStyles.placeHolder.color, hideIconOnFocus = true, style, onFocus, onBlur, onChangeText, accessibilityState, borderRadius = 'pill', borderWidth = 1, borderColor = colors['core-outline-secondary'], backgroundColor, size = 'm', ...rest } = props;
|
|
14
17
|
const inputRef = react.useRef(null);
|
|
15
18
|
const [isFocused, setIsFocused] = react.useState(false);
|
|
16
19
|
// Only drive native focus when the caller explicitly supplies a preference.
|
|
@@ -37,7 +40,40 @@ function SliceTextInput(props) {
|
|
|
37
40
|
padding: { paddingRight: 18, paddingLeft: showIcon ? 0 : 18 },
|
|
38
41
|
});
|
|
39
42
|
}, [showIcon]);
|
|
40
|
-
|
|
43
|
+
const inputSize = react.useMemo(() => {
|
|
44
|
+
return reactNative.StyleSheet.create({
|
|
45
|
+
size: {
|
|
46
|
+
minHeight: sizes.sizeToNumber(size),
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
}, [size]);
|
|
50
|
+
const borderStyles = react.useMemo(() => {
|
|
51
|
+
return reactNative.StyleSheet.create({
|
|
52
|
+
border: {
|
|
53
|
+
borderWidth: Number.isFinite(borderWidth) ? Math.max(0, borderWidth) : 0,
|
|
54
|
+
borderColor,
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
}, [borderColor, borderWidth]);
|
|
58
|
+
const cornerRadius = react.useMemo(() => {
|
|
59
|
+
return reactNative.StyleSheet.create({
|
|
60
|
+
borderRadius: {
|
|
61
|
+
borderRadius: sizes.borderRadiusToNumber(borderRadius),
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
}, [borderRadius]);
|
|
65
|
+
const bgColor = react.useMemo(() => {
|
|
66
|
+
return reactNative.StyleSheet.create({
|
|
67
|
+
backgroundColor: { backgroundColor: backgroundColor ?? colors['core-surface-primary'] },
|
|
68
|
+
});
|
|
69
|
+
}, [backgroundColor, colors]);
|
|
70
|
+
return (jsxRuntime.jsxs(Reanimated.View, { style: [
|
|
71
|
+
themedStyles.inputWrapper,
|
|
72
|
+
inputSize.size,
|
|
73
|
+
cornerRadius.borderRadius,
|
|
74
|
+
borderStyles.border,
|
|
75
|
+
bgColor.backgroundColor,
|
|
76
|
+
], layout: layout, children: [showIcon && (jsxRuntime.jsx(reactNative.View, { style: [themedStyles.icon, { height: iconSize, width: iconSize }], children: jsxRuntime.jsx(SliceIcon.SliceIcon, { name: icon, strokeColor: iconColorComputed, size: iconSize, accessible: false, pointerEvents: "none" }) })), jsxRuntime.jsx(reactNative.TextInput, { ...rest, ref: inputRef, style: [themedStyles.inputFieldView, padding.padding, style], accessibilityState: {
|
|
41
77
|
...accessibilityState,
|
|
42
78
|
disabled: rest.editable === false || accessibilityState?.disabled,
|
|
43
79
|
}, onChangeText: onChangeText, placeholderTextColor: placeholderTextColor, onFocus: (event) => {
|
|
@@ -65,11 +101,6 @@ const styles = (theme) => reactNative.StyleSheet.create({
|
|
|
65
101
|
alignItems: 'center',
|
|
66
102
|
justifyContent: 'flex-start',
|
|
67
103
|
gap: 8,
|
|
68
|
-
borderWidth: 1,
|
|
69
|
-
borderColor: theme.colors['core-outline-secondary'],
|
|
70
|
-
borderRadius: 100,
|
|
71
|
-
minHeight: 48,
|
|
72
|
-
backgroundColor: theme.colors['core-surface-primary'],
|
|
73
104
|
zIndex: 2,
|
|
74
105
|
},
|
|
75
106
|
inputFieldView: {
|
|
@@ -77,10 +108,9 @@ const styles = (theme) => reactNative.StyleSheet.create({
|
|
|
77
108
|
color: theme.colors['core-text-primary'],
|
|
78
109
|
flex: 1,
|
|
79
110
|
zIndex: 2,
|
|
80
|
-
minHeight: 48,
|
|
81
111
|
},
|
|
82
112
|
placeHolder: {
|
|
83
|
-
color: theme.colors['core-text-
|
|
113
|
+
color: theme.colors['core-text-tertiary'],
|
|
84
114
|
},
|
|
85
115
|
});
|
|
86
116
|
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var react = require('react');
|
|
4
|
+
var reactNative = require('react-native');
|
|
5
|
+
|
|
6
|
+
/** Unsupported-platform fallback. Metro selects the native hook on iOS/Android. */
|
|
7
|
+
function useDeviceCapabilities() {
|
|
8
|
+
return react.useMemo(() => ({
|
|
9
|
+
platform: reactNative.Platform.OS,
|
|
10
|
+
iosVersion: null,
|
|
11
|
+
androidSdkVersion: null,
|
|
12
|
+
deviceName: null,
|
|
13
|
+
deviceModel: null,
|
|
14
|
+
supportsLiquidGlass: false,
|
|
15
|
+
supportsNativeBlur: false,
|
|
16
|
+
}), []);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
exports.useDeviceCapabilities = useDeviceCapabilities;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Internal utility converting size props to an absolute number
|
|
5
|
+
*/
|
|
6
|
+
function sizeToNumber(size) {
|
|
7
|
+
if (!size)
|
|
8
|
+
return 48;
|
|
9
|
+
if (typeof size === 'number')
|
|
10
|
+
return size;
|
|
11
|
+
switch (size) {
|
|
12
|
+
case 's': {
|
|
13
|
+
return 40;
|
|
14
|
+
}
|
|
15
|
+
case 'm': {
|
|
16
|
+
return 48;
|
|
17
|
+
}
|
|
18
|
+
case 'l': {
|
|
19
|
+
return 56;
|
|
20
|
+
}
|
|
21
|
+
default:
|
|
22
|
+
return 48;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/** Resolve radius presets; invalid or negative values produce square corners. */
|
|
26
|
+
function borderRadiusToNumber(borderRadius) {
|
|
27
|
+
if (typeof borderRadius === 'number')
|
|
28
|
+
return Number.isFinite(borderRadius) ? Math.max(0, borderRadius) : 0;
|
|
29
|
+
switch (borderRadius) {
|
|
30
|
+
case 'pill':
|
|
31
|
+
return 1000;
|
|
32
|
+
case 'rectangular':
|
|
33
|
+
return 4;
|
|
34
|
+
default:
|
|
35
|
+
return 0;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
exports.borderRadiusToNumber = borderRadiusToNumber;
|
|
40
|
+
exports.sizeToNumber = sizeToNumber;
|
package/dist/cjs/utils.js
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var typography = require('./src/utils/typography/typography.js');
|
|
4
|
+
var sizes = require('./src/utils/sizes/sizes.js');
|
|
4
5
|
|
|
5
6
|
|
|
6
7
|
|
|
7
8
|
exports.lineHeightTextStyle = typography.lineHeightTextStyle;
|
|
9
|
+
exports.borderRadiusToNumber = sizes.borderRadiusToNumber;
|
|
10
|
+
exports.sizeToNumber = sizes.sizeToNumber;
|
package/dist/esm/components.mjs
CHANGED
|
@@ -3,3 +3,5 @@ export { SliceIcons } from './src/components/SliceIcon/icons.mjs';
|
|
|
3
3
|
export { StyledText } from './src/components/SliceText/SliceText.mjs';
|
|
4
4
|
export { SliceButton } from './src/components/SliceButton/SliceButton.mjs';
|
|
5
5
|
export { SliceTextInput } from './src/components/SliceTextInput/SliceTextInput.mjs';
|
|
6
|
+
export { SliceLiquidGlassView } from './src/components/SliceLiquidGlassView/SliceLiquidGlassView.mjs';
|
|
7
|
+
export { SliceBackgroundBlur } from './src/components/SliceBackgroundBlur/SliceBackgroundBlur.mjs';
|
package/dist/esm/hooks.mjs
CHANGED
package/dist/esm/index.mjs
CHANGED
|
@@ -3,7 +3,11 @@ export { SliceIcons } from './src/components/SliceIcon/icons.mjs';
|
|
|
3
3
|
export { StyledText } from './src/components/SliceText/SliceText.mjs';
|
|
4
4
|
export { SliceButton } from './src/components/SliceButton/SliceButton.mjs';
|
|
5
5
|
export { SliceTextInput } from './src/components/SliceTextInput/SliceTextInput.mjs';
|
|
6
|
+
export { SliceLiquidGlassView } from './src/components/SliceLiquidGlassView/SliceLiquidGlassView.mjs';
|
|
7
|
+
export { SliceBackgroundBlur } from './src/components/SliceBackgroundBlur/SliceBackgroundBlur.mjs';
|
|
6
8
|
export { createTypography, darkTheme, lightTheme } from './theme.mjs';
|
|
7
9
|
export { SliceThemeProvider, useSliceContext, useSliceTheme } from './src/providers/SliceThemeProvider.mjs';
|
|
8
10
|
export { useCreateThemedStyles } from './src/hooks/useCreateThemedStyles/useCreateThemedStyles.mjs';
|
|
11
|
+
export { useDeviceCapabilities } from './src/hooks/useDeviceCapabilities/useDeviceCapabilities.mjs';
|
|
9
12
|
export { lineHeightTextStyle } from './src/utils/typography/typography.mjs';
|
|
13
|
+
export { borderRadiusToNumber, sizeToNumber } from './src/utils/sizes/sizes.mjs';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { View, StyleSheet } from 'react-native';
|
|
3
|
+
|
|
4
|
+
/** Web/other-platform fallback. Metro selects the native implementation on iOS/Android. */
|
|
5
|
+
function SliceBackgroundBlur({ style, fallbackColor = 'rgba(128, 128, 128, 0.18)', }) {
|
|
6
|
+
return jsx(View, { pointerEvents: "none", style: [StyleSheet.absoluteFill, style, { backgroundColor: fallbackColor }] });
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export { SliceBackgroundBlur };
|
|
@@ -3,7 +3,10 @@ import { useMemo } from 'react';
|
|
|
3
3
|
import { StyleSheet, Pressable } from 'react-native';
|
|
4
4
|
import Reanimated from 'react-native-reanimated';
|
|
5
5
|
import { useSliceTheme } from '../../providers/SliceThemeProvider.mjs';
|
|
6
|
+
import { useDeviceCapabilities } from '../../hooks/useDeviceCapabilities/useDeviceCapabilities.mjs';
|
|
7
|
+
import { sizeToNumber, borderRadiusToNumber } from '../../utils/sizes/sizes.mjs';
|
|
6
8
|
import { SliceIcon } from '../SliceIcon/SliceIcon.mjs';
|
|
9
|
+
import { SliceLiquidGlassView } from '../SliceLiquidGlassView/SliceLiquidGlassView.mjs';
|
|
7
10
|
import { StyledText } from '../SliceText/SliceText.mjs';
|
|
8
11
|
|
|
9
12
|
/**
|
|
@@ -11,10 +14,12 @@ import { StyledText } from '../SliceText/SliceText.mjs';
|
|
|
11
14
|
*/
|
|
12
15
|
function SliceButton(props) {
|
|
13
16
|
const { colors, name } = useSliceTheme();
|
|
17
|
+
const { supportsLiquidGlass } = useDeviceCapabilities();
|
|
14
18
|
const isLightTheme = name.includes('light');
|
|
15
|
-
const { children, onPress, disabled = false, icon, iconPosition = 'left', iconSize = 24, animatedStyle, variant = 'primary', layout, presence, accessibilityState, ...pressableProps } = props;
|
|
19
|
+
const { children, onPress, disabled = false, icon, iconPosition = 'left', iconSize = 24, size = 'm', animatedStyle, variant = 'primary', layout, presence, accessibilityState, liquidGlassBackground, borderRadius = 'pill', borderWidth, borderColor = colors['core-outline-secondary'], backgroundColor, ...pressableProps } = props;
|
|
20
|
+
const { fallbackColor, glassTintColor, glassStyle } = liquidGlassBackground ?? {};
|
|
21
|
+
const applyLiquidGlass = Boolean(liquidGlassBackground) && supportsLiquidGlass;
|
|
16
22
|
const hasLabel = children !== undefined && children !== null && children !== false && children !== '';
|
|
17
|
-
// adjust padding for the visual discrepancy because of the intrinsic padding of each icon
|
|
18
23
|
const pressableStyle = useMemo(() => {
|
|
19
24
|
if (!hasLabel)
|
|
20
25
|
return StyleSheet.compose(styles.pressable, styles.pressableNoLabel);
|
|
@@ -24,15 +29,13 @@ function SliceButton(props) {
|
|
|
24
29
|
return StyleSheet.compose(styles.pressable, styles.pressableIconRight);
|
|
25
30
|
return styles.pressable;
|
|
26
31
|
}, [icon, iconPosition, hasLabel]);
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
return
|
|
32
|
-
}, [
|
|
33
|
-
// memoize the color styles to apply to the button/label based on variant and disabled state
|
|
32
|
+
const bgColor = useMemo(() => {
|
|
33
|
+
if (applyLiquidGlass)
|
|
34
|
+
return 'transparent';
|
|
35
|
+
const baseBGColor = variant === 'primary' ? colors['core-button-primary'] : colors['core-surface-primary'];
|
|
36
|
+
return backgroundColor ?? fallbackColor ?? baseBGColor;
|
|
37
|
+
}, [applyLiquidGlass, backgroundColor, fallbackColor, colors, variant]);
|
|
34
38
|
const colorStyles = useMemo(() => {
|
|
35
|
-
const bgColor = variant === 'primary' ? colors['core-button-primary'] : colors['core-surface-primary'];
|
|
36
39
|
const disabledBGColor = disabled ? colors['core-surface-secondary'] : undefined;
|
|
37
40
|
const color = colors['core-text-primary'];
|
|
38
41
|
const disabledColor = disabled ? colors['core-text-disabled'] : undefined;
|
|
@@ -43,7 +46,7 @@ function SliceButton(props) {
|
|
|
43
46
|
: colors['core-link-primary'];
|
|
44
47
|
return StyleSheet.create({
|
|
45
48
|
backgroundColor: {
|
|
46
|
-
backgroundColor: disabledBGColor ?? bgColor,
|
|
49
|
+
backgroundColor: applyLiquidGlass ? 'transparent' : (disabledBGColor ?? bgColor),
|
|
47
50
|
},
|
|
48
51
|
textColor: {
|
|
49
52
|
color: disabledColor ?? color,
|
|
@@ -55,16 +58,17 @@ function SliceButton(props) {
|
|
|
55
58
|
color: iconColor,
|
|
56
59
|
},
|
|
57
60
|
});
|
|
58
|
-
}, [
|
|
59
|
-
//
|
|
61
|
+
}, [applyLiquidGlass, disabled, colors, isLightTheme, bgColor]);
|
|
62
|
+
// Preserve variant defaults while allowing an explicit zero-width border.
|
|
60
63
|
const borderStyles = useMemo(() => {
|
|
64
|
+
const width = borderWidth ?? (variant === 'primary' ? 0 : 1);
|
|
61
65
|
return StyleSheet.create({
|
|
62
66
|
border: {
|
|
63
|
-
borderWidth:
|
|
64
|
-
borderColor
|
|
67
|
+
borderWidth: Number.isFinite(width) ? Math.max(0, width) : 0,
|
|
68
|
+
borderColor,
|
|
65
69
|
},
|
|
66
70
|
});
|
|
67
|
-
}, [variant,
|
|
71
|
+
}, [variant, borderColor, borderWidth]);
|
|
68
72
|
// disable touch events when button is disabled
|
|
69
73
|
const pointerEvents = useMemo(() => {
|
|
70
74
|
return StyleSheet.create({
|
|
@@ -73,24 +77,47 @@ function SliceButton(props) {
|
|
|
73
77
|
},
|
|
74
78
|
});
|
|
75
79
|
}, [disabled]);
|
|
76
|
-
|
|
80
|
+
// set the button size
|
|
81
|
+
const buttonSize = useMemo(() => {
|
|
82
|
+
return StyleSheet.create({
|
|
83
|
+
size: {
|
|
84
|
+
minHeight: sizeToNumber(size),
|
|
85
|
+
width: hasLabel ? 'auto' : sizeToNumber(size),
|
|
86
|
+
},
|
|
87
|
+
});
|
|
88
|
+
}, [size, hasLabel]);
|
|
89
|
+
// set the button border radius
|
|
90
|
+
const cornerRadius = useMemo(() => {
|
|
91
|
+
return StyleSheet.create({
|
|
92
|
+
borderRadius: {
|
|
93
|
+
borderRadius: borderRadiusToNumber(borderRadius),
|
|
94
|
+
},
|
|
95
|
+
});
|
|
96
|
+
}, [borderRadius]);
|
|
97
|
+
return (jsx(Reanimated.View, { layout: layout, children: jsx(Reanimated.View, { entering: presence?.entering, exiting: presence?.exiting, children: jsxs(Reanimated.View, { style: [
|
|
98
|
+
styles.wrapper,
|
|
99
|
+
pointerEvents.pointer,
|
|
100
|
+
colorStyles.backgroundColor,
|
|
101
|
+
buttonSize.size,
|
|
102
|
+
borderStyles.border,
|
|
103
|
+
cornerRadius.borderRadius,
|
|
104
|
+
animatedStyle,
|
|
105
|
+
], children: [applyLiquidGlass && (jsx(SliceLiquidGlassView, { cornerRadius: borderRadiusToNumber(borderRadius), fallbackColor: fallbackColor, glassTintColor: glassTintColor, glassStyle: glassStyle, style: styles.background })), jsxs(Pressable, { ...pressableProps, accessibilityRole: pressableProps.accessibilityRole ?? 'button', accessibilityState: { ...accessibilityState, disabled }, disabled: disabled, style: pressableStyle, onPress: disabled ? undefined : onPress, android_ripple: pressableProps.android_ripple ?? colorStyles.ripple, children: [icon && iconPosition === 'left' && (jsx(SliceIcon, { name: icon, size: iconSize, strokeColor: colorStyles.icon.color, pointerEvents: "none", accessible: false })), hasLabel && (jsx(StyledText, { textStyle: 'body-xl-bold', style: colorStyles.textColor, singleLine: true, numberOfLines: 1, ellipsizeMode: 'tail', children: children })), icon && iconPosition === 'right' && (jsx(SliceIcon, { name: icon, size: iconSize, strokeColor: colorStyles.icon.color, pointerEvents: "none", accessible: false }))] })] }) }) }));
|
|
77
106
|
}
|
|
78
107
|
/**
|
|
79
108
|
* Base Styles
|
|
80
109
|
*/
|
|
81
110
|
const styles = StyleSheet.create({
|
|
82
111
|
wrapper: {
|
|
83
|
-
|
|
112
|
+
position: 'relative',
|
|
84
113
|
overflow: 'hidden',
|
|
85
114
|
justifyContent: 'center',
|
|
86
115
|
alignItems: 'center',
|
|
87
|
-
height: 48,
|
|
88
116
|
width: 'auto',
|
|
89
117
|
},
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
height: 48,
|
|
118
|
+
background: {
|
|
119
|
+
position: 'absolute',
|
|
120
|
+
inset: 0,
|
|
94
121
|
},
|
|
95
122
|
pressable: {
|
|
96
123
|
flex: 1,
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { forwardRef } from 'react';
|
|
3
|
+
import { View } from 'react-native';
|
|
4
|
+
|
|
5
|
+
/** Android/web fallback. Metro selects SliceLiquidGlassView.ios on iOS. */
|
|
6
|
+
const SliceLiquidGlassView = forwardRef(function SliceLiquidGlassView({ glassStyle: _glassStyle, glassTintColor: _glassTintColor, interactive: _interactive, cornerRadius = 24, fallbackColor = 'rgba(128, 128, 128, 0.18)', style, ...props }, ref) {
|
|
7
|
+
return (jsx(View, { ...props, ref: ref, style: [{ backgroundColor: fallbackColor }, style, { borderRadius: cornerRadius, overflow: 'hidden' }] }));
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
export { SliceLiquidGlassView };
|
|
@@ -3,12 +3,15 @@ import { useRef, useState, useEffect, useMemo } from 'react';
|
|
|
3
3
|
import { StyleSheet, View, TextInput } from 'react-native';
|
|
4
4
|
import Reanimated from 'react-native-reanimated';
|
|
5
5
|
import { useCreateThemedStyles } from '../../hooks/useCreateThemedStyles/useCreateThemedStyles.mjs';
|
|
6
|
+
import { useSliceTheme } from '../../providers/SliceThemeProvider.mjs';
|
|
6
7
|
import { lineHeightTextStyle } from '../../utils/typography/typography.mjs';
|
|
8
|
+
import { sizeToNumber, borderRadiusToNumber } from '../../utils/sizes/sizes.mjs';
|
|
7
9
|
import { SliceIcon } from '../SliceIcon/SliceIcon.mjs';
|
|
8
10
|
|
|
9
11
|
function SliceTextInput(props) {
|
|
10
12
|
const themedStyles = useCreateThemedStyles(styles);
|
|
11
|
-
const {
|
|
13
|
+
const { colors } = useSliceTheme();
|
|
14
|
+
const { didFocus, layout, icon, focused, blurClears = false, iconColor, iconSize = 24, placeholderTextColor = themedStyles.placeHolder.color, hideIconOnFocus = true, style, onFocus, onBlur, onChangeText, accessibilityState, borderRadius = 'pill', borderWidth = 1, borderColor = colors['core-outline-secondary'], backgroundColor, size = 'm', ...rest } = props;
|
|
12
15
|
const inputRef = useRef(null);
|
|
13
16
|
const [isFocused, setIsFocused] = useState(false);
|
|
14
17
|
// Only drive native focus when the caller explicitly supplies a preference.
|
|
@@ -35,7 +38,40 @@ function SliceTextInput(props) {
|
|
|
35
38
|
padding: { paddingRight: 18, paddingLeft: showIcon ? 0 : 18 },
|
|
36
39
|
});
|
|
37
40
|
}, [showIcon]);
|
|
38
|
-
|
|
41
|
+
const inputSize = useMemo(() => {
|
|
42
|
+
return StyleSheet.create({
|
|
43
|
+
size: {
|
|
44
|
+
minHeight: sizeToNumber(size),
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
}, [size]);
|
|
48
|
+
const borderStyles = useMemo(() => {
|
|
49
|
+
return StyleSheet.create({
|
|
50
|
+
border: {
|
|
51
|
+
borderWidth: Number.isFinite(borderWidth) ? Math.max(0, borderWidth) : 0,
|
|
52
|
+
borderColor,
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
}, [borderColor, borderWidth]);
|
|
56
|
+
const cornerRadius = useMemo(() => {
|
|
57
|
+
return StyleSheet.create({
|
|
58
|
+
borderRadius: {
|
|
59
|
+
borderRadius: borderRadiusToNumber(borderRadius),
|
|
60
|
+
},
|
|
61
|
+
});
|
|
62
|
+
}, [borderRadius]);
|
|
63
|
+
const bgColor = useMemo(() => {
|
|
64
|
+
return StyleSheet.create({
|
|
65
|
+
backgroundColor: { backgroundColor: backgroundColor ?? colors['core-surface-primary'] },
|
|
66
|
+
});
|
|
67
|
+
}, [backgroundColor, colors]);
|
|
68
|
+
return (jsxs(Reanimated.View, { style: [
|
|
69
|
+
themedStyles.inputWrapper,
|
|
70
|
+
inputSize.size,
|
|
71
|
+
cornerRadius.borderRadius,
|
|
72
|
+
borderStyles.border,
|
|
73
|
+
bgColor.backgroundColor,
|
|
74
|
+
], layout: layout, children: [showIcon && (jsx(View, { style: [themedStyles.icon, { height: iconSize, width: iconSize }], children: jsx(SliceIcon, { name: icon, strokeColor: iconColorComputed, size: iconSize, accessible: false, pointerEvents: "none" }) })), jsx(TextInput, { ...rest, ref: inputRef, style: [themedStyles.inputFieldView, padding.padding, style], accessibilityState: {
|
|
39
75
|
...accessibilityState,
|
|
40
76
|
disabled: rest.editable === false || accessibilityState?.disabled,
|
|
41
77
|
}, onChangeText: onChangeText, placeholderTextColor: placeholderTextColor, onFocus: (event) => {
|
|
@@ -63,11 +99,6 @@ const styles = (theme) => StyleSheet.create({
|
|
|
63
99
|
alignItems: 'center',
|
|
64
100
|
justifyContent: 'flex-start',
|
|
65
101
|
gap: 8,
|
|
66
|
-
borderWidth: 1,
|
|
67
|
-
borderColor: theme.colors['core-outline-secondary'],
|
|
68
|
-
borderRadius: 100,
|
|
69
|
-
minHeight: 48,
|
|
70
|
-
backgroundColor: theme.colors['core-surface-primary'],
|
|
71
102
|
zIndex: 2,
|
|
72
103
|
},
|
|
73
104
|
inputFieldView: {
|
|
@@ -75,10 +106,9 @@ const styles = (theme) => StyleSheet.create({
|
|
|
75
106
|
color: theme.colors['core-text-primary'],
|
|
76
107
|
flex: 1,
|
|
77
108
|
zIndex: 2,
|
|
78
|
-
minHeight: 48,
|
|
79
109
|
},
|
|
80
110
|
placeHolder: {
|
|
81
|
-
color: theme.colors['core-text-
|
|
111
|
+
color: theme.colors['core-text-tertiary'],
|
|
82
112
|
},
|
|
83
113
|
});
|
|
84
114
|
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
import { Platform } from 'react-native';
|
|
3
|
+
|
|
4
|
+
/** Unsupported-platform fallback. Metro selects the native hook on iOS/Android. */
|
|
5
|
+
function useDeviceCapabilities() {
|
|
6
|
+
return useMemo(() => ({
|
|
7
|
+
platform: Platform.OS,
|
|
8
|
+
iosVersion: null,
|
|
9
|
+
androidSdkVersion: null,
|
|
10
|
+
deviceName: null,
|
|
11
|
+
deviceModel: null,
|
|
12
|
+
supportsLiquidGlass: false,
|
|
13
|
+
supportsNativeBlur: false,
|
|
14
|
+
}), []);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export { useDeviceCapabilities };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Internal utility converting size props to an absolute number
|
|
3
|
+
*/
|
|
4
|
+
function sizeToNumber(size) {
|
|
5
|
+
if (!size)
|
|
6
|
+
return 48;
|
|
7
|
+
if (typeof size === 'number')
|
|
8
|
+
return size;
|
|
9
|
+
switch (size) {
|
|
10
|
+
case 's': {
|
|
11
|
+
return 40;
|
|
12
|
+
}
|
|
13
|
+
case 'm': {
|
|
14
|
+
return 48;
|
|
15
|
+
}
|
|
16
|
+
case 'l': {
|
|
17
|
+
return 56;
|
|
18
|
+
}
|
|
19
|
+
default:
|
|
20
|
+
return 48;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
/** Resolve radius presets; invalid or negative values produce square corners. */
|
|
24
|
+
function borderRadiusToNumber(borderRadius) {
|
|
25
|
+
if (typeof borderRadius === 'number')
|
|
26
|
+
return Number.isFinite(borderRadius) ? Math.max(0, borderRadius) : 0;
|
|
27
|
+
switch (borderRadius) {
|
|
28
|
+
case 'pill':
|
|
29
|
+
return 1000;
|
|
30
|
+
case 'rectangular':
|
|
31
|
+
return 4;
|
|
32
|
+
default:
|
|
33
|
+
return 0;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export { borderRadiusToNumber, sizeToNumber };
|
package/dist/esm/utils.mjs
CHANGED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { StyleSheet, View } from 'react-native';
|
|
3
|
+
/** Web/other-platform fallback. Metro selects the native implementation on iOS/Android. */
|
|
4
|
+
export function SliceBackgroundBlur({ style, fallbackColor = 'rgba(128, 128, 128, 0.18)', }) {
|
|
5
|
+
return _jsx(View, { pointerEvents: "none", style: [StyleSheet.absoluteFill, style, { backgroundColor: fallbackColor }] });
|
|
6
|
+
}
|