@compsych/mobile-ui 1.0.15 → 1.0.17
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@compsych/mobile-ui",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.17",
|
|
4
4
|
"description": "ComPsych React Native Design System — 19 mobile UI components with self-contained design tokens",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"types": "src/index.ts",
|
|
@@ -32,11 +32,17 @@
|
|
|
32
32
|
"peerDependencies": {
|
|
33
33
|
"@expo/vector-icons": ">=15.0.0",
|
|
34
34
|
"expo-font": ">=13.0.0",
|
|
35
|
+
"expo-linear-gradient": ">=13.0.0",
|
|
35
36
|
"lucide-react-native": ">=0.400.0",
|
|
36
37
|
"react": ">=18.0.0",
|
|
37
38
|
"react-native": ">=0.73.0",
|
|
38
39
|
"react-native-svg": ">=15.0.0"
|
|
39
40
|
},
|
|
41
|
+
"peerDependenciesMeta": {
|
|
42
|
+
"expo-linear-gradient": {
|
|
43
|
+
"optional": true
|
|
44
|
+
}
|
|
45
|
+
},
|
|
40
46
|
"devDependencies": {
|
|
41
47
|
"@babel/core": "^7.25.2",
|
|
42
48
|
"@babel/plugin-transform-flow-strip-types": "^7.27.1",
|
|
@@ -52,6 +58,7 @@
|
|
|
52
58
|
"babel-jest": "^29.7.0",
|
|
53
59
|
"eslint": "^9.39.4",
|
|
54
60
|
"eslint-plugin-unused-imports": "^4.4.1",
|
|
61
|
+
"expo-linear-gradient": "^56.0.4",
|
|
55
62
|
"husky": "^9.1.7",
|
|
56
63
|
"jest": "^29.7.0",
|
|
57
64
|
"jest-expo": "^55.0.17",
|
|
@@ -1,13 +1,15 @@
|
|
|
1
|
-
import React, { useMemo, useRef, useState } from 'react';
|
|
1
|
+
import React, { useCallback, useMemo, useRef, useState } from 'react';
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
4
|
Image,
|
|
5
5
|
ImageSourcePropType,
|
|
6
|
+
NativeSyntheticEvent,
|
|
6
7
|
Pressable,
|
|
7
8
|
ScrollView,
|
|
8
9
|
StyleProp,
|
|
9
10
|
StyleSheet,
|
|
10
11
|
TextInput,
|
|
12
|
+
TextInputContentSizeChangeEventData,
|
|
11
13
|
View,
|
|
12
14
|
ViewStyle,
|
|
13
15
|
} from 'react-native';
|
|
@@ -47,6 +49,18 @@ export function ChatInput({
|
|
|
47
49
|
const { colorRoles: cr, dimensions: dim, iconography: ico } = useTheme();
|
|
48
50
|
const [isFocused, setIsFocused] = useState(false);
|
|
49
51
|
const inputRef = useRef<TextInput>(null);
|
|
52
|
+
const [inputHeight, setInputHeight] = useState(24);
|
|
53
|
+
|
|
54
|
+
const handleContentSizeChange = useCallback(
|
|
55
|
+
(e: NativeSyntheticEvent<TextInputContentSizeChangeEventData>) => {
|
|
56
|
+
const newHeight = Math.max(
|
|
57
|
+
24,
|
|
58
|
+
Math.min(120, e.nativeEvent.contentSize.height),
|
|
59
|
+
);
|
|
60
|
+
setInputHeight(newHeight);
|
|
61
|
+
},
|
|
62
|
+
[],
|
|
63
|
+
);
|
|
50
64
|
|
|
51
65
|
const hasText = value.trim().length > 0;
|
|
52
66
|
const hasAttachments = !!attachments && attachments.length > 0;
|
|
@@ -182,12 +196,15 @@ export function ChatInput({
|
|
|
182
196
|
multiline
|
|
183
197
|
onFocus={() => setIsFocused(true)}
|
|
184
198
|
onBlur={() => setIsFocused(false)}
|
|
199
|
+
onContentSizeChange={handleContentSizeChange}
|
|
200
|
+
scrollEnabled={inputHeight >= 120}
|
|
185
201
|
style={[
|
|
186
202
|
styles.textInput,
|
|
187
203
|
{
|
|
188
204
|
color: cr.surface.surface.sysOnSurface,
|
|
189
205
|
fontSize: 16,
|
|
190
206
|
lineHeight: 24,
|
|
207
|
+
height: inputHeight,
|
|
191
208
|
},
|
|
192
209
|
]}
|
|
193
210
|
accessibilityLabel={placeholder}
|
|
@@ -237,7 +254,6 @@ const styles = StyleSheet.create({
|
|
|
237
254
|
includeFontPadding: false,
|
|
238
255
|
padding: 0,
|
|
239
256
|
margin: 0,
|
|
240
|
-
maxHeight: 120,
|
|
241
257
|
},
|
|
242
258
|
attachStrip: {
|
|
243
259
|
flexShrink: 0,
|
|
@@ -10,6 +10,8 @@ import {
|
|
|
10
10
|
ViewStyle,
|
|
11
11
|
} from 'react-native';
|
|
12
12
|
|
|
13
|
+
import { LinearGradient } from 'expo-linear-gradient';
|
|
14
|
+
|
|
13
15
|
import { type IconName, SIZE_MAP, resolveIcon } from '../../icons';
|
|
14
16
|
import { useTheme } from '../../theme';
|
|
15
17
|
import { BodyText } from '../BodyText';
|
|
@@ -37,6 +39,12 @@ export interface ServiceCardProps {
|
|
|
37
39
|
accessibilityLabel?: string;
|
|
38
40
|
fullWidth?: boolean;
|
|
39
41
|
style?: StyleProp<ViewStyle>;
|
|
42
|
+
/** Gradient colors for the "doubled" variant inner card (e.g. ['#a855f7', '#6366f1']). Falls back to the solid token color when omitted. */
|
|
43
|
+
gradient?: readonly [string, string, ...string[]];
|
|
44
|
+
/** Start point of the gradient in 0–1 coordinate space. Defaults to { x: 0, y: 0 } (top). */
|
|
45
|
+
gradientStart?: { x: number; y: number };
|
|
46
|
+
/** End point of the gradient in 0–1 coordinate space. Defaults to { x: 0, y: 1 } (bottom). */
|
|
47
|
+
gradientEnd?: { x: number; y: number };
|
|
40
48
|
}
|
|
41
49
|
|
|
42
50
|
const ELEVATION = {
|
|
@@ -64,6 +72,9 @@ export function ServiceCard({
|
|
|
64
72
|
accessibilityLabel,
|
|
65
73
|
fullWidth = false,
|
|
66
74
|
style,
|
|
75
|
+
gradient,
|
|
76
|
+
gradientStart,
|
|
77
|
+
gradientEnd,
|
|
67
78
|
}: ServiceCardProps) {
|
|
68
79
|
const { colorRoles: cr, dimensions: dim } = useTheme();
|
|
69
80
|
|
|
@@ -225,19 +236,18 @@ export function ServiceCard({
|
|
|
225
236
|
let inner: React.ReactNode;
|
|
226
237
|
|
|
227
238
|
if (variant === 'doubled') {
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
>
|
|
239
|
+
const doubledInnerStyle: StyleProp<ViewStyle> = [
|
|
240
|
+
styles.colRoot,
|
|
241
|
+
{
|
|
242
|
+
borderRadius: s.borderRadius,
|
|
243
|
+
paddingHorizontal: s.paddingH,
|
|
244
|
+
paddingVertical: s.paddingV,
|
|
245
|
+
gap: dim.spacing.padding.sysPadding24,
|
|
246
|
+
},
|
|
247
|
+
];
|
|
248
|
+
|
|
249
|
+
const doubledInnerContent = (
|
|
250
|
+
<>
|
|
241
251
|
{renderedIcon && (
|
|
242
252
|
<View
|
|
243
253
|
style={[
|
|
@@ -253,6 +263,21 @@ export function ServiceCard({
|
|
|
253
263
|
)}
|
|
254
264
|
{textBlock}
|
|
255
265
|
{children}
|
|
266
|
+
</>
|
|
267
|
+
);
|
|
268
|
+
|
|
269
|
+
inner = gradient ? (
|
|
270
|
+
<LinearGradient
|
|
271
|
+
colors={gradient}
|
|
272
|
+
start={gradientStart ?? { x: 0, y: 0 }}
|
|
273
|
+
end={gradientEnd ?? { x: 0, y: 1 }}
|
|
274
|
+
style={doubledInnerStyle}
|
|
275
|
+
>
|
|
276
|
+
{doubledInnerContent}
|
|
277
|
+
</LinearGradient>
|
|
278
|
+
) : (
|
|
279
|
+
<View style={[doubledInnerStyle, { backgroundColor: v.innerBg }]}>
|
|
280
|
+
{doubledInnerContent}
|
|
256
281
|
</View>
|
|
257
282
|
);
|
|
258
283
|
} else if (variant === 'image') {
|