@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
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
// Generated by native/scripts/generate-icons.mjs from src/components/Icon. Do not edit directly.
|
|
2
|
+
export const SliceIcons = {
|
|
3
|
+
arrows: {
|
|
4
|
+
arrowLeft: 'arrow left',
|
|
5
|
+
arrowRight: 'arrow right',
|
|
6
|
+
arrowUp: 'arrow up',
|
|
7
|
+
arrowDown: 'arrow down',
|
|
8
|
+
chevronDown: 'chevron down',
|
|
9
|
+
chevronUp: 'chevron up',
|
|
10
|
+
navigateRight: 'navigate right',
|
|
11
|
+
navigateLeft: 'navigate left',
|
|
12
|
+
share: 'share',
|
|
13
|
+
},
|
|
14
|
+
selection: {
|
|
15
|
+
check: 'check',
|
|
16
|
+
checkCircle: 'check circle',
|
|
17
|
+
checkbox: 'checkbox',
|
|
18
|
+
checkboxChecked: 'checkbox checked',
|
|
19
|
+
checkboxPartial: 'checkbox partial',
|
|
20
|
+
circle: 'circle',
|
|
21
|
+
circleFill: 'circle fill',
|
|
22
|
+
plus: 'plus',
|
|
23
|
+
plusCircle: 'plus circle',
|
|
24
|
+
},
|
|
25
|
+
Messaging: {
|
|
26
|
+
chat: 'chat',
|
|
27
|
+
mail: 'mail',
|
|
28
|
+
notification: 'notification',
|
|
29
|
+
inbox: 'inbox',
|
|
30
|
+
like: 'like',
|
|
31
|
+
unlike: 'unlike',
|
|
32
|
+
at: '@',
|
|
33
|
+
},
|
|
34
|
+
media: {
|
|
35
|
+
camera: 'camera',
|
|
36
|
+
focus: 'focus',
|
|
37
|
+
mic: 'mic',
|
|
38
|
+
micMuted: 'mic muted',
|
|
39
|
+
video: 'video',
|
|
40
|
+
videoOff: 'video off',
|
|
41
|
+
download: 'download',
|
|
42
|
+
upload: 'upload',
|
|
43
|
+
speaker: 'speaker',
|
|
44
|
+
speakerMuted: 'speaker muted',
|
|
45
|
+
speakerHigh: 'speaker high',
|
|
46
|
+
speakerLow: 'speaker low',
|
|
47
|
+
play: 'play',
|
|
48
|
+
playCircle: 'play circle',
|
|
49
|
+
pause: 'pause',
|
|
50
|
+
pauseCircle: 'pause circle',
|
|
51
|
+
},
|
|
52
|
+
files: {
|
|
53
|
+
document: 'document',
|
|
54
|
+
documentEditor: 'document editor',
|
|
55
|
+
textDocument: 'text document',
|
|
56
|
+
},
|
|
57
|
+
people: {
|
|
58
|
+
people: 'people',
|
|
59
|
+
person: 'person',
|
|
60
|
+
talk: 'talk',
|
|
61
|
+
},
|
|
62
|
+
business: {
|
|
63
|
+
briefcase: 'briefcase',
|
|
64
|
+
dollar: 'dollar',
|
|
65
|
+
invoice: 'invoice',
|
|
66
|
+
payment: 'payment',
|
|
67
|
+
wallet: 'wallet',
|
|
68
|
+
laptop: 'laptop',
|
|
69
|
+
},
|
|
70
|
+
charts: {
|
|
71
|
+
barChart: 'bar chart',
|
|
72
|
+
chart: 'chart',
|
|
73
|
+
chartArrow: 'chart arrow',
|
|
74
|
+
},
|
|
75
|
+
status: {
|
|
76
|
+
alert: 'alert',
|
|
77
|
+
exclamation: 'exclamation',
|
|
78
|
+
help: 'help',
|
|
79
|
+
info: 'info',
|
|
80
|
+
issue: 'issue',
|
|
81
|
+
lightBulb: 'light bulb',
|
|
82
|
+
target: 'target',
|
|
83
|
+
openCircle: 'open circle',
|
|
84
|
+
},
|
|
85
|
+
brands: {
|
|
86
|
+
apple: 'apple',
|
|
87
|
+
google: 'google',
|
|
88
|
+
googleMono: 'google mono',
|
|
89
|
+
linkedin: 'linkedin',
|
|
90
|
+
github: 'github',
|
|
91
|
+
npm: 'npm',
|
|
92
|
+
openAI: 'openAI',
|
|
93
|
+
android: 'android',
|
|
94
|
+
},
|
|
95
|
+
edit: {
|
|
96
|
+
edit: 'edit',
|
|
97
|
+
trashBin: 'trash bin',
|
|
98
|
+
copy: 'copy',
|
|
99
|
+
filter: 'filter',
|
|
100
|
+
highlight: 'highlight',
|
|
101
|
+
undo: 'undo',
|
|
102
|
+
concise: 'concise',
|
|
103
|
+
expanded: 'expanded',
|
|
104
|
+
moderate: 'moderate',
|
|
105
|
+
recent: 'recent',
|
|
106
|
+
},
|
|
107
|
+
typography: {
|
|
108
|
+
fontLarger: 'font larger',
|
|
109
|
+
fontSmaller: 'font smaller',
|
|
110
|
+
characterBeam: 'character beam',
|
|
111
|
+
},
|
|
112
|
+
weather: {
|
|
113
|
+
sun: 'sun',
|
|
114
|
+
moonFull: 'moon full',
|
|
115
|
+
},
|
|
116
|
+
ai: {
|
|
117
|
+
sparkle: 'sparkle',
|
|
118
|
+
wand: 'wand',
|
|
119
|
+
},
|
|
120
|
+
ui: {
|
|
121
|
+
attach: 'attach',
|
|
122
|
+
blank: 'blank',
|
|
123
|
+
book: 'book',
|
|
124
|
+
globeLocation: 'globe location',
|
|
125
|
+
heart: 'heart',
|
|
126
|
+
stop: 'stop',
|
|
127
|
+
search: 'search',
|
|
128
|
+
settings: 'settings',
|
|
129
|
+
view: 'view',
|
|
130
|
+
refresh: 'refresh',
|
|
131
|
+
home: 'home',
|
|
132
|
+
menu: 'menu',
|
|
133
|
+
more: 'more',
|
|
134
|
+
sidebar: 'sidebar',
|
|
135
|
+
sidebarSplit: 'sidebar split',
|
|
136
|
+
keyboard: 'keyboard',
|
|
137
|
+
x: 'x',
|
|
138
|
+
fullscreen: 'fullscreen',
|
|
139
|
+
},
|
|
140
|
+
};
|
package/dist/react-native/native/src/components/SliceLiquidGlassView/SliceLiquidGlassView.ios.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef } from 'react';
|
|
3
|
+
import NativeLiquidGlassView from '../../specs/LiquidGlassNativeComponent';
|
|
4
|
+
export const SliceLiquidGlassView = forwardRef(function SliceLiquidGlassView({ glassStyle = 'regular', interactive = false, cornerRadius = 24, fallbackColor: _fallbackColor, style, ...props }, ref) {
|
|
5
|
+
return (_jsx(NativeLiquidGlassView, { ...props, ref: ref, glassStyle: glassStyle, interactive: interactive, cornerRadius: cornerRadius, style: [style, { borderRadius: cornerRadius }] }));
|
|
6
|
+
});
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef } from 'react';
|
|
3
|
+
import { View } from 'react-native';
|
|
4
|
+
/** Android/web fallback. Metro selects SliceLiquidGlassView.ios on iOS. */
|
|
5
|
+
export const SliceLiquidGlassView = forwardRef(function SliceLiquidGlassView({ glassStyle: _glassStyle, glassTintColor: _glassTintColor, interactive: _interactive, cornerRadius = 24, fallbackColor = 'rgba(128, 128, 128, 0.18)', style, ...props }, ref) {
|
|
6
|
+
return (_jsx(View, { ...props, ref: ref, style: [{ backgroundColor: fallbackColor }, style, { borderRadius: cornerRadius, overflow: 'hidden' }] }));
|
|
7
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { SliceLiquidGlassView } from './SliceLiquidGlassView';
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Text } from 'react-native';
|
|
3
|
+
import { useSliceTheme } from '../../providers/SliceThemeProvider';
|
|
4
|
+
/**
|
|
5
|
+
* Utility wrapper around text component for easier styling of text using slice theme
|
|
6
|
+
*/
|
|
7
|
+
export function StyledText(props) {
|
|
8
|
+
const { textStyle, textColor, style, singleLine, children, ...rest } = props;
|
|
9
|
+
const { type, colors } = useSliceTheme();
|
|
10
|
+
const textStyles = textStyle ? type[textStyle] : undefined;
|
|
11
|
+
const color = { color: textColor ? colors[textColor] : colors['core-text-primary'] };
|
|
12
|
+
const fontSize = textStyles?.fontSize ?? 16;
|
|
13
|
+
const height = typeof singleLine === 'number' ? singleLine : 1.2;
|
|
14
|
+
const lineHeight = { lineHeight: singleLine ? height * fontSize : textStyles?.lineHeight };
|
|
15
|
+
return (_jsx(Text, { ...rest, numberOfLines: singleLine ? 1 : rest.numberOfLines, style: [textStyles, color, lineHeight, style], children: children }));
|
|
16
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { StyledText } from './SliceText';
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useMemo, useRef, useState } from 'react';
|
|
3
|
+
import { StyleSheet, TextInput, View } from 'react-native';
|
|
4
|
+
import Reanimated from 'react-native-reanimated';
|
|
5
|
+
import { useCreateThemedStyles } from '../../hooks';
|
|
6
|
+
import { useSliceTheme } from '../../providers';
|
|
7
|
+
import { borderRadiusToNumber, lineHeightTextStyle, sizeToNumber } from '../../utils';
|
|
8
|
+
import { SliceIcon } from '../SliceIcon';
|
|
9
|
+
export function SliceTextInput(props) {
|
|
10
|
+
const themedStyles = useCreateThemedStyles(styles);
|
|
11
|
+
const { colors } = useSliceTheme();
|
|
12
|
+
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;
|
|
13
|
+
const inputRef = useRef(null);
|
|
14
|
+
const [isFocused, setIsFocused] = useState(false);
|
|
15
|
+
// Only drive native focus when the caller explicitly supplies a preference.
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
if (focused === undefined || !inputRef.current)
|
|
18
|
+
return;
|
|
19
|
+
if (focused && !inputRef.current.isFocused())
|
|
20
|
+
inputRef.current.focus();
|
|
21
|
+
else if (!focused && inputRef.current.isFocused())
|
|
22
|
+
inputRef.current.blur();
|
|
23
|
+
}, [focused]);
|
|
24
|
+
const iconColorComputed = useMemo(() => {
|
|
25
|
+
if (iconColor)
|
|
26
|
+
return iconColor;
|
|
27
|
+
return isFocused ? themedStyles.icon.color : placeholderTextColor;
|
|
28
|
+
}, [themedStyles, isFocused, iconColor, placeholderTextColor]);
|
|
29
|
+
const showIcon = useMemo(() => {
|
|
30
|
+
if (!icon)
|
|
31
|
+
return false;
|
|
32
|
+
return !(isFocused && hideIconOnFocus);
|
|
33
|
+
}, [isFocused, hideIconOnFocus, icon]);
|
|
34
|
+
const padding = useMemo(() => {
|
|
35
|
+
return StyleSheet.create({
|
|
36
|
+
padding: { paddingRight: 18, paddingLeft: showIcon ? 0 : 18 },
|
|
37
|
+
});
|
|
38
|
+
}, [showIcon]);
|
|
39
|
+
const inputSize = useMemo(() => {
|
|
40
|
+
return StyleSheet.create({
|
|
41
|
+
size: {
|
|
42
|
+
minHeight: sizeToNumber(size),
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
}, [size]);
|
|
46
|
+
const borderStyles = useMemo(() => {
|
|
47
|
+
return StyleSheet.create({
|
|
48
|
+
border: {
|
|
49
|
+
borderWidth: Number.isFinite(borderWidth) ? Math.max(0, borderWidth) : 0,
|
|
50
|
+
borderColor,
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
}, [borderColor, borderWidth]);
|
|
54
|
+
const cornerRadius = useMemo(() => {
|
|
55
|
+
return StyleSheet.create({
|
|
56
|
+
borderRadius: {
|
|
57
|
+
borderRadius: borderRadiusToNumber(borderRadius),
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
}, [borderRadius]);
|
|
61
|
+
const bgColor = useMemo(() => {
|
|
62
|
+
return StyleSheet.create({
|
|
63
|
+
backgroundColor: { backgroundColor: backgroundColor ?? colors['core-surface-primary'] },
|
|
64
|
+
});
|
|
65
|
+
}, [backgroundColor, colors]);
|
|
66
|
+
return (_jsxs(Reanimated.View, { style: [
|
|
67
|
+
themedStyles.inputWrapper,
|
|
68
|
+
inputSize.size,
|
|
69
|
+
cornerRadius.borderRadius,
|
|
70
|
+
borderStyles.border,
|
|
71
|
+
bgColor.backgroundColor,
|
|
72
|
+
], 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: {
|
|
73
|
+
...accessibilityState,
|
|
74
|
+
disabled: rest.editable === false || accessibilityState?.disabled,
|
|
75
|
+
}, onChangeText: onChangeText, placeholderTextColor: placeholderTextColor, onFocus: (event) => {
|
|
76
|
+
setIsFocused(true);
|
|
77
|
+
didFocus?.(true);
|
|
78
|
+
onFocus?.(event);
|
|
79
|
+
}, onBlur: (event) => {
|
|
80
|
+
setIsFocused(false);
|
|
81
|
+
if (blurClears) {
|
|
82
|
+
inputRef.current?.clear();
|
|
83
|
+
onChangeText?.('');
|
|
84
|
+
}
|
|
85
|
+
didFocus?.(false);
|
|
86
|
+
onBlur?.(event);
|
|
87
|
+
} })] }));
|
|
88
|
+
}
|
|
89
|
+
const styles = (theme) => StyleSheet.create({
|
|
90
|
+
icon: {
|
|
91
|
+
marginLeft: 16,
|
|
92
|
+
color: theme.name === 'lightMode' ? theme.colors['core-icon-primary'] : theme.colors['core-link-primary'],
|
|
93
|
+
},
|
|
94
|
+
inputWrapper: {
|
|
95
|
+
flex: 1,
|
|
96
|
+
flexDirection: 'row',
|
|
97
|
+
alignItems: 'center',
|
|
98
|
+
justifyContent: 'flex-start',
|
|
99
|
+
gap: 8,
|
|
100
|
+
zIndex: 2,
|
|
101
|
+
},
|
|
102
|
+
inputFieldView: {
|
|
103
|
+
...lineHeightTextStyle(theme.type['body-xl-bold']),
|
|
104
|
+
color: theme.colors['core-text-primary'],
|
|
105
|
+
flex: 1,
|
|
106
|
+
zIndex: 2,
|
|
107
|
+
},
|
|
108
|
+
placeHolder: {
|
|
109
|
+
color: theme.colors['core-text-tertiary'],
|
|
110
|
+
},
|
|
111
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { SliceTextInput } from './SliceTextInput';
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { SliceIcon, SliceIcons } from './SliceIcon';
|
|
2
|
+
export { StyledText } from './SliceText';
|
|
3
|
+
export { SliceButton } from './SliceButton';
|
|
4
|
+
export { SliceTextInput } from './SliceTextInput';
|
|
5
|
+
export { SliceLiquidGlassView } from './SliceLiquidGlassView';
|
|
6
|
+
export { SliceBackgroundBlur } from './SliceBackgroundBlur';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { useCreateThemedStyles } from './useCreateThemedStyles';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
import { useSliceTheme } from '../../providers/SliceThemeProvider';
|
|
3
|
+
/** Resolve native styles using the current provider theme. Keep the factory stable
|
|
4
|
+
* (outside the component, or with useCallback) to reuse styles across renders. */
|
|
5
|
+
export function useCreateThemedStyles(styles) {
|
|
6
|
+
const sliceTheme = useSliceTheme();
|
|
7
|
+
return useMemo(() => styles(sliceTheme), [sliceTheme, styles]);
|
|
8
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { useDeviceCapabilities } from './useDeviceCapabilities';
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
import { Platform } from 'react-native';
|
|
3
|
+
/** Unsupported-platform fallback. Metro selects the native hook on iOS/Android. */
|
|
4
|
+
export function useDeviceCapabilities() {
|
|
5
|
+
return useMemo(() => ({
|
|
6
|
+
platform: Platform.OS,
|
|
7
|
+
iosVersion: null,
|
|
8
|
+
androidSdkVersion: null,
|
|
9
|
+
deviceName: null,
|
|
10
|
+
deviceModel: null,
|
|
11
|
+
supportsLiquidGlass: false,
|
|
12
|
+
supportsNativeBlur: false,
|
|
13
|
+
}), []);
|
|
14
|
+
}
|
package/dist/react-native/native/src/hooks/useDeviceCapabilities/useDeviceCapabilities.native.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
import { Platform } from 'react-native';
|
|
3
|
+
import NativeDeviceCapabilities from '../../specs/NativeDeviceCapabilities';
|
|
4
|
+
/**
|
|
5
|
+
* Reports native API availability. Both values are false on unsupported platforms
|
|
6
|
+
* or when the package's native module is absent. Accessibility preferences and
|
|
7
|
+
* per-view hardware acceleration can still cause components to use their fallback.
|
|
8
|
+
*/
|
|
9
|
+
export function useDeviceCapabilities() {
|
|
10
|
+
return useMemo(() => {
|
|
11
|
+
const platform = Platform.OS;
|
|
12
|
+
const native = platform === 'ios' || platform === 'android' ? NativeDeviceCapabilities?.getConstants() : null;
|
|
13
|
+
return {
|
|
14
|
+
platform,
|
|
15
|
+
iosVersion: platform === 'ios' ? String(Platform.Version) : null,
|
|
16
|
+
androidSdkVersion: platform === 'android' ? Platform.Version : null,
|
|
17
|
+
deviceName: native?.deviceName ?? null,
|
|
18
|
+
deviceModel: native?.deviceModel ?? null,
|
|
19
|
+
supportsLiquidGlass: native?.supportsLiquidGlass ?? false,
|
|
20
|
+
supportsNativeBlur: native?.supportsNativeBlur ?? false,
|
|
21
|
+
};
|
|
22
|
+
}, []);
|
|
23
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { SliceIcon, SliceIcons, StyledText, SliceButton, SliceTextInput, SliceLiquidGlassView } from './components';
|
|
2
|
+
export { lightTheme, darkTheme, createTypography } from './theme';
|
|
3
|
+
export { SliceThemeProvider, useSliceTheme, useSliceContext } from './providers';
|
|
4
|
+
export { useCreateThemedStyles, useDeviceCapabilities } from './hooks';
|
|
5
|
+
export { lineHeightTextStyle, sizeToNumber, borderRadiusToNumber } from './utils';
|
|
6
|
+
export { SliceBackgroundBlur } from './components/SliceBackgroundBlur';
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { createContext, useContext, useMemo } from 'react';
|
|
3
|
+
import { useColorScheme } from 'react-native';
|
|
4
|
+
import { darkTheme, lightTheme } from '../theme';
|
|
5
|
+
const ThemeContext = createContext(undefined);
|
|
6
|
+
export function SliceThemeProvider({ preference = 'system', onPreferenceChange = undefined, children, }) {
|
|
7
|
+
const deviceMode = useColorScheme();
|
|
8
|
+
const mode = preference === 'system' ? (deviceMode === 'dark' ? 'dark' : 'light') : preference;
|
|
9
|
+
const value = useMemo(() => ({
|
|
10
|
+
theme: mode === 'dark' ? darkTheme : lightTheme,
|
|
11
|
+
mode,
|
|
12
|
+
preference,
|
|
13
|
+
setPreference: onPreferenceChange,
|
|
14
|
+
}), [mode, preference, onPreferenceChange]);
|
|
15
|
+
return _jsx(ThemeContext.Provider, { value: value, children: children });
|
|
16
|
+
}
|
|
17
|
+
export function useSliceContext() {
|
|
18
|
+
const context = useContext(ThemeContext);
|
|
19
|
+
if (!context) {
|
|
20
|
+
throw new Error('useSliceContext must be used within SliceThemeProvider');
|
|
21
|
+
}
|
|
22
|
+
return context;
|
|
23
|
+
}
|
|
24
|
+
export function useSliceTheme() {
|
|
25
|
+
const context = useContext(ThemeContext);
|
|
26
|
+
if (!context) {
|
|
27
|
+
throw new Error('useSliceTheme must be used within SliceThemeProvider');
|
|
28
|
+
}
|
|
29
|
+
return context.theme;
|
|
30
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { SliceThemeProvider, useSliceTheme, useSliceContext } from './SliceThemeProvider';
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type CodegenTypes,
|
|
3
|
+
type ColorValue,
|
|
4
|
+
type HostComponent,
|
|
5
|
+
type ViewProps,
|
|
6
|
+
codegenNativeComponent,
|
|
7
|
+
} from 'react-native';
|
|
8
|
+
|
|
9
|
+
export interface NativeProps extends ViewProps {
|
|
10
|
+
blurIntensity?: CodegenTypes.WithDefault<CodegenTypes.Double, 12>;
|
|
11
|
+
fadeStop?: CodegenTypes.WithDefault<CodegenTypes.Double, 0>;
|
|
12
|
+
direction?: CodegenTypes.WithDefault<'down' | 'up' | 'left' | 'right', 'down'>;
|
|
13
|
+
fallbackColor?: ColorValue;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export default codegenNativeComponent<NativeProps>('SliceBackgroundBlur') as HostComponent<NativeProps>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type CodegenTypes,
|
|
3
|
+
type ColorValue,
|
|
4
|
+
type HostComponent,
|
|
5
|
+
type ViewProps,
|
|
6
|
+
codegenNativeComponent,
|
|
7
|
+
} from 'react-native';
|
|
8
|
+
|
|
9
|
+
export interface NativeProps extends ViewProps {
|
|
10
|
+
glassStyle?: CodegenTypes.WithDefault<'regular' | 'clear', 'regular'>;
|
|
11
|
+
glassTintColor?: ColorValue;
|
|
12
|
+
interactive?: CodegenTypes.WithDefault<boolean, false>;
|
|
13
|
+
cornerRadius?: CodegenTypes.WithDefault<CodegenTypes.Double, 24>;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export default codegenNativeComponent<NativeProps>('SliceLiquidGlassView', {
|
|
17
|
+
excludedPlatforms: ['android'],
|
|
18
|
+
}) as HostComponent<NativeProps>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { TurboModule } from 'react-native';
|
|
2
|
+
import { TurboModuleRegistry } from 'react-native';
|
|
3
|
+
|
|
4
|
+
export interface Spec extends TurboModule {
|
|
5
|
+
readonly getConstants: () => {
|
|
6
|
+
supportsLiquidGlass: boolean;
|
|
7
|
+
supportsNativeBlur: boolean;
|
|
8
|
+
deviceName: string;
|
|
9
|
+
deviceModel: string;
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export default TurboModuleRegistry.get<Spec>('SliceDeviceCapabilities');
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { dark, light, coreColors as webCore } from '../../../src/theme/colors/colors';
|
|
2
|
+
import { corners } from '../../../src/theme/corners/corners';
|
|
3
|
+
// Import token modules directly: web barrel exports can initialize browser stores.
|
|
4
|
+
import { elevations } from '../../../src/theme/elevations/elevations';
|
|
5
|
+
import { motion as webMotion } from '../../../src/theme/motion/motion';
|
|
6
|
+
import { spacing } from '../../../src/theme/spacing/spacing';
|
|
7
|
+
import { type as webType } from '../../../src/theme/type/type';
|
|
8
|
+
import { easing } from './motion';
|
|
9
|
+
export { corners, spacing, elevations };
|
|
10
|
+
const { 'surface-shadow-soft-light': _sl, 'surface-shadow-soft-dark': _sd, 'surface-shadow-strong-light': _hl, 'surface-shadow-strong-dark': _hd, ...palette } = webCore;
|
|
11
|
+
export const coreColors = palette;
|
|
12
|
+
/** Uses a 16dp base for the web rem scale. Load this font in the consuming app. */
|
|
13
|
+
export function createTypography(fontFamily = 'Funnel Sans') {
|
|
14
|
+
return Object.fromEntries(Object.entries(webType).map(([key, css]) => {
|
|
15
|
+
const read = (property) => {
|
|
16
|
+
const value = css.match(new RegExp(`(?:^|;)\\s*${property}:\\s*([^;]+)`))?.[1];
|
|
17
|
+
if (!value)
|
|
18
|
+
throw new Error(`Missing typography property: ${property}`);
|
|
19
|
+
return Number.parseFloat(value);
|
|
20
|
+
};
|
|
21
|
+
const fontSize = read('font-size') * 16;
|
|
22
|
+
return [
|
|
23
|
+
key,
|
|
24
|
+
{
|
|
25
|
+
fontFamily,
|
|
26
|
+
fontSize,
|
|
27
|
+
fontWeight: read('font-weight'),
|
|
28
|
+
lineHeight: (fontSize * read('line-height')) / 100,
|
|
29
|
+
letterSpacing: fontSize * read('letter-spacing'),
|
|
30
|
+
textDecorationLine: 'none',
|
|
31
|
+
},
|
|
32
|
+
];
|
|
33
|
+
}));
|
|
34
|
+
}
|
|
35
|
+
export const type = createTypography();
|
|
36
|
+
export const motion = {
|
|
37
|
+
'motion-magnet': easing(webMotion['motion-magnet']),
|
|
38
|
+
'motion-water': easing(webMotion['motion-water']),
|
|
39
|
+
'motion-spring': easing(webMotion['motion-spring']),
|
|
40
|
+
'motion-magnet-duration': Number.parseFloat(webMotion['motion-magnet-duration']) * 1000,
|
|
41
|
+
'motion-water-duration': Number.parseFloat(webMotion['motion-water-duration']) * 1000,
|
|
42
|
+
'motion-spring-duration': Number.parseFloat(webMotion['motion-spring-duration']) * 1000,
|
|
43
|
+
};
|
|
44
|
+
function shadow(value) {
|
|
45
|
+
const match = value.match(/^([\d.]+)px ([\d.]+)px ([\d.]+)px (.+)$/);
|
|
46
|
+
if (!match)
|
|
47
|
+
throw new Error(`Unsupported Slice shadow: ${value}`);
|
|
48
|
+
return {
|
|
49
|
+
boxShadow: [
|
|
50
|
+
{ offsetX: Number(match[1]), offsetY: Number(match[2]), blurRadius: Number(match[3]), color: match[4] },
|
|
51
|
+
],
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
function createTheme(name, palette) {
|
|
55
|
+
const { 'surface-shadow-soft': soft, 'surface-shadow-strong': strong, ...colors } = palette;
|
|
56
|
+
return {
|
|
57
|
+
name,
|
|
58
|
+
coreColors,
|
|
59
|
+
colors,
|
|
60
|
+
corners,
|
|
61
|
+
spacing,
|
|
62
|
+
elevations,
|
|
63
|
+
type,
|
|
64
|
+
motion,
|
|
65
|
+
shadows: { 'surface-shadow-soft': shadow(soft), 'surface-shadow-strong': shadow(strong) },
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
export const lightTheme = createTheme('lightMode', light);
|
|
69
|
+
export const darkTheme = createTheme('darkMode', dark);
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/** Convert Slice's explicit CSS curves without importing the React Native runtime. */
|
|
2
|
+
export function easing(css) {
|
|
3
|
+
if (css.startsWith('cubic-bezier(')) {
|
|
4
|
+
const [x1, y1, x2, y2] = css.slice(13, -1).split(',').map(Number);
|
|
5
|
+
const sample = (t, a, b) => 3 * (1 - t) ** 2 * t * a + 3 * (1 - t) * t ** 2 * b + t ** 3;
|
|
6
|
+
return (progress) => {
|
|
7
|
+
if (progress <= 0)
|
|
8
|
+
return 0;
|
|
9
|
+
if (progress >= 1)
|
|
10
|
+
return 1;
|
|
11
|
+
let low = 0;
|
|
12
|
+
let high = 1;
|
|
13
|
+
for (let i = 0; i < 30; i++) {
|
|
14
|
+
const middle = (low + high) / 2;
|
|
15
|
+
if (sample(middle, x1, x2) < progress)
|
|
16
|
+
low = middle;
|
|
17
|
+
else
|
|
18
|
+
high = middle;
|
|
19
|
+
}
|
|
20
|
+
return sample((low + high) / 2, y1, y2);
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
if (!css.startsWith('linear('))
|
|
24
|
+
throw new Error(`Unsupported Slice easing: ${css}`);
|
|
25
|
+
const points = css
|
|
26
|
+
.slice(7, -1)
|
|
27
|
+
.split(',')
|
|
28
|
+
.map((entry, index, entries) => {
|
|
29
|
+
const [value, percent] = entry.trim().split(/\s+/).map(Number.parseFloat);
|
|
30
|
+
return { value, position: percent === undefined ? index / (entries.length - 1) : percent / 100 };
|
|
31
|
+
});
|
|
32
|
+
return (progress) => {
|
|
33
|
+
if (progress <= 0)
|
|
34
|
+
return points[0].value;
|
|
35
|
+
for (let i = 1; i < points.length; i++) {
|
|
36
|
+
const left = points[i - 1];
|
|
37
|
+
const right = points[i];
|
|
38
|
+
if (progress <= right.position)
|
|
39
|
+
return (left.value + ((right.value - left.value) * (progress - left.position)) / (right.position - left.position));
|
|
40
|
+
}
|
|
41
|
+
return points[points.length - 1].value;
|
|
42
|
+
};
|
|
43
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { sizeToNumber, borderRadiusToNumber } from './sizes';
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Internal utility converting size props to an absolute number
|
|
3
|
+
*/
|
|
4
|
+
export 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
|
+
export 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
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { lineHeightTextStyle } from './typography';
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Simple utility to take text style and returns a defined line height factor
|
|
3
|
+
* Since there is no relative/percent in native, looks for the fontsize and
|
|
4
|
+
* derives an absolute line height from the font size
|
|
5
|
+
*/
|
|
6
|
+
export function lineHeightTextStyle(styles, lineHeightFactor = 1.2) {
|
|
7
|
+
if (!Number.isFinite(lineHeightFactor) || lineHeightFactor < 0 || lineHeightFactor > 2) {
|
|
8
|
+
throw new Error('lineHeightFactor must be a number between 0 and 2');
|
|
9
|
+
}
|
|
10
|
+
const fontSize = styles.fontSize ?? 16;
|
|
11
|
+
const lineHeight = lineHeightFactor * fontSize;
|
|
12
|
+
return { ...styles, lineHeight };
|
|
13
|
+
}
|