react-native-terra-ui 0.10.1 → 0.10.2
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/CHANGELOG.md +7 -0
- package/lib/module/components/button/Button.js +21 -13
- package/lib/module/components/button/Button.js.map +1 -1
- package/lib/module/components/button/index.js.map +1 -1
- package/lib/module/components/divider/Divider.js +127 -0
- package/lib/module/components/divider/Divider.js.map +1 -0
- package/lib/module/components/divider/index.js +4 -0
- package/lib/module/components/divider/index.js.map +1 -0
- package/lib/module/components/index.js +2 -0
- package/lib/module/components/index.js.map +1 -1
- package/lib/module/components/pressable/index.js +4 -0
- package/lib/module/components/pressable/index.js.map +1 -0
- package/lib/module/components/pressable/variants/PressableScale/index.js +110 -0
- package/lib/module/components/pressable/variants/PressableScale/index.js.map +1 -0
- package/lib/typescript/src/components/button/Button.d.ts +7 -0
- package/lib/typescript/src/components/button/Button.d.ts.map +1 -1
- package/lib/typescript/src/components/button/index.d.ts +1 -1
- package/lib/typescript/src/components/button/index.d.ts.map +1 -1
- package/lib/typescript/src/components/divider/Divider.d.ts +49 -0
- package/lib/typescript/src/components/divider/Divider.d.ts.map +1 -0
- package/lib/typescript/src/components/divider/index.d.ts +3 -0
- package/lib/typescript/src/components/divider/index.d.ts.map +1 -0
- package/lib/typescript/src/components/index.d.ts +2 -0
- package/lib/typescript/src/components/index.d.ts.map +1 -1
- package/lib/typescript/src/components/pressable/index.d.ts +3 -0
- package/lib/typescript/src/components/pressable/index.d.ts.map +1 -0
- package/lib/typescript/src/components/pressable/variants/PressableScale/index.d.ts +47 -0
- package/lib/typescript/src/components/pressable/variants/PressableScale/index.d.ts.map +1 -0
- package/package.json +1 -1
- package/src/components/button/Button.tsx +32 -13
- package/src/components/button/index.ts +1 -0
- package/src/components/divider/Divider.tsx +164 -0
- package/src/components/divider/index.ts +7 -0
- package/src/components/index.ts +2 -0
- package/src/components/pressable/index.ts +5 -0
- package/src/components/pressable/variants/PressableScale/index.tsx +166 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.10.2](https://github.com/earthlin9/react-native-terra-ui/compare/v0.10.1...v0.10.2) (2026-09-11)
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
|
|
7
|
+
* **ui:** [button] add PressableScale and a Button animation prop ([#22](https://github.com/earthlin9/react-native-terra-ui/issues/22)) ([ff91d4f](https://github.com/earthlin9/react-native-terra-ui/commit/ff91d4f9f1d68ea68c779b647f2320dab49516fe))
|
|
8
|
+
* **ui:** [divider] add Divider ([#23](https://github.com/earthlin9/react-native-terra-ui/issues/23)) ([132c83b](https://github.com/earthlin9/react-native-terra-ui/commit/132c83bcb134bdfb552f4f0070805ab7efdf7e45))
|
|
9
|
+
|
|
3
10
|
## [0.10.1](https://github.com/earthlin9/react-native-terra-ui/compare/v0.10.0...v0.10.1) (2026-09-10)
|
|
4
11
|
|
|
5
12
|
### Bug Fixes
|
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
import { Pressable } from "react-native-unistyles/components/native/Pressable";
|
|
4
3
|
import { Children, createContext, forwardRef, useContext } from "react";
|
|
5
4
|
import { StyleSheet, useUnistyles } from "react-native-unistyles";
|
|
6
5
|
import { getDefaultRadius } from "../../theme/registry.js";
|
|
7
6
|
import { readableOn } from "../../utils/color-utils.js";
|
|
8
7
|
import { resolveThemeColor } from "../../utils/resolve-theme-color.js";
|
|
9
8
|
import { Icon } from "../icon/index.js";
|
|
9
|
+
import { PressableScale } from "../pressable/index.js";
|
|
10
10
|
import { Spinner } from "../spinner/index.js";
|
|
11
11
|
import { Text } from "../text/index.js";
|
|
12
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
13
|
+
/** Matches pressto's `minScale` default — enough to feel, not enough to distract. */
|
|
14
|
+
const PRESSED_SCALE = 0.96;
|
|
12
15
|
|
|
13
16
|
// ─── Context (lets icons/labels read the resolved foreground + size) ───────────
|
|
14
|
-
|
|
17
|
+
|
|
15
18
|
const ButtonContext = /*#__PURE__*/createContext({
|
|
16
19
|
color: "",
|
|
17
20
|
size: "md"
|
|
@@ -147,6 +150,7 @@ const ButtonRoot = /*#__PURE__*/forwardRef(function Button({
|
|
|
147
150
|
isIconOnly = false,
|
|
148
151
|
fullWidth = true,
|
|
149
152
|
compact = false,
|
|
153
|
+
animation = "scale",
|
|
150
154
|
background,
|
|
151
155
|
children,
|
|
152
156
|
onPress,
|
|
@@ -177,30 +181,34 @@ const ButtonRoot = /*#__PURE__*/forwardRef(function Button({
|
|
|
177
181
|
style: externalStyle,
|
|
178
182
|
...pressableRest
|
|
179
183
|
} = rest;
|
|
184
|
+
const ownStyles = [styles.base, {
|
|
185
|
+
backgroundColor: bg,
|
|
186
|
+
borderColor: border,
|
|
187
|
+
borderWidth
|
|
188
|
+
}, compact ? styles.compact : null, isDisabled ? {
|
|
189
|
+
opacity: theme.opacity.disabled
|
|
190
|
+
} : null];
|
|
191
|
+
// Only the function form forces a re-render per touch, so keep the array form
|
|
192
|
+
// whenever the caller's style doesn't need the pressed state.
|
|
193
|
+
const style = typeof externalStyle === "function" ? state => [...ownStyles, externalStyle(state)] : [...ownStyles, externalStyle];
|
|
180
194
|
return /*#__PURE__*/_jsx(ButtonContext.Provider, {
|
|
181
195
|
value: {
|
|
182
196
|
color: fg,
|
|
183
197
|
size
|
|
184
198
|
},
|
|
185
|
-
children: /*#__PURE__*/_jsxs(
|
|
199
|
+
children: /*#__PURE__*/_jsxs(PressableScale, {
|
|
186
200
|
ref: ref,
|
|
187
201
|
onPress: blocked ? undefined : onPress,
|
|
188
|
-
|
|
202
|
+
isDisabled: blocked,
|
|
203
|
+
minScale: animation === "scale" ? PRESSED_SCALE : 1,
|
|
204
|
+
pressedOpacity: animation === "opacity" ? theme.opacity.pressed : undefined,
|
|
189
205
|
accessibilityRole: "button",
|
|
190
206
|
accessibilityState: {
|
|
191
207
|
disabled: blocked,
|
|
192
208
|
busy: isLoading
|
|
193
209
|
},
|
|
194
210
|
...pressableRest,
|
|
195
|
-
style:
|
|
196
|
-
backgroundColor: bg,
|
|
197
|
-
borderColor: border,
|
|
198
|
-
borderWidth
|
|
199
|
-
}, compact ? styles.compact : null, state.pressed && !blocked ? {
|
|
200
|
-
opacity: theme.opacity.pressed
|
|
201
|
-
} : null, isDisabled ? {
|
|
202
|
-
opacity: theme.opacity.disabled
|
|
203
|
-
} : null, typeof externalStyle === "function" ? externalStyle(state) : externalStyle],
|
|
211
|
+
style: style,
|
|
204
212
|
children: [isLoading && /*#__PURE__*/_jsx(Spinner, {
|
|
205
213
|
size: "sm",
|
|
206
214
|
color: fg
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["Children","createContext","forwardRef","useContext","StyleSheet","useUnistyles","getDefaultRadius","readableOn","resolveThemeColor","Icon","Spinner","Text","jsx","_jsx","jsxs","_jsxs","ButtonContext","color","size","useButtonContext","getColors","variant","theme","c","get","key","bg","border","borderWidth","fg","LABEL_TYPOGRAPHY","sm","weight","md","lg","ButtonLabel","children","typography","style","ICON_SIZE","ButtonIcon","name","sizeProp","colorProp","strokeWidth","renderChildren","map","child","trim","length","ButtonRoot","Button","radius","isDisabled","isLoading","isIconOnly","fullWidth","compact","background","onPress","rest","ref","_styles","styles","useVariants","iconOnly","variantBg","variantFg","resolvedBackground","undefined","blocked","externalStyle","pressableRest","
|
|
1
|
+
{"version":3,"names":["Children","createContext","forwardRef","useContext","StyleSheet","useUnistyles","getDefaultRadius","readableOn","resolveThemeColor","Icon","PressableScale","Spinner","Text","jsx","_jsx","jsxs","_jsxs","PRESSED_SCALE","ButtonContext","color","size","useButtonContext","getColors","variant","theme","c","get","key","bg","border","borderWidth","fg","LABEL_TYPOGRAPHY","sm","weight","md","lg","ButtonLabel","children","typography","style","ICON_SIZE","ButtonIcon","name","sizeProp","colorProp","strokeWidth","renderChildren","map","child","trim","length","ButtonRoot","Button","radius","isDisabled","isLoading","isIconOnly","fullWidth","compact","animation","background","onPress","rest","ref","_styles","styles","useVariants","iconOnly","variantBg","variantFg","resolvedBackground","undefined","blocked","externalStyle","pressableRest","ownStyles","base","backgroundColor","borderColor","opacity","disabled","state","Provider","value","minScale","pressedOpacity","pressed","accessibilityRole","accessibilityState","busy","Label","create","flexDirection","alignItems","justifyContent","alignSelf","variants","height","paddingHorizontal","gap","none","borderRadius","xl","full","true","false","aspectRatio","uni__dependencies","paddingVertical"],"sourceRoot":"../../../../src","sources":["components/button/Button.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["Button","useButtonContext"],"sourceRoot":"../../../../src","sources":["components/button/index.ts"],"mappings":";;
|
|
1
|
+
{"version":3,"names":["Button","useButtonContext"],"sourceRoot":"../../../../src","sources":["components/button/index.ts"],"mappings":";;AAQA,SAASA,MAAM,EAAEC,gBAAgB","ignoreList":[]}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { View } from "react-native-unistyles/components/native/View";
|
|
4
|
+
import { Children, forwardRef } from "react";
|
|
5
|
+
import { StyleSheet as RNStyleSheet } from "react-native";
|
|
6
|
+
import { StyleSheet, useUnistyles } from "react-native-unistyles";
|
|
7
|
+
import { resolveThemeColor } from "../../utils/resolve-theme-color.js";
|
|
8
|
+
import { Text } from "../text/index.js";
|
|
9
|
+
|
|
10
|
+
/** `number | 'hairline'`, mirroring `Box`'s `borderWidth`. */
|
|
11
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
12
|
+
function resolveThickness(thickness) {
|
|
13
|
+
return thickness === "hairline" ? RNStyleSheet.hairlineWidth : thickness;
|
|
14
|
+
}
|
|
15
|
+
function renderLabel(children) {
|
|
16
|
+
return Children.map(children, child => {
|
|
17
|
+
if (typeof child === "string") {
|
|
18
|
+
return child.trim().length > 0 ? /*#__PURE__*/_jsx(Text, {
|
|
19
|
+
variant: "label-sm",
|
|
20
|
+
color: "text.secondary",
|
|
21
|
+
children: child
|
|
22
|
+
}) : null;
|
|
23
|
+
}
|
|
24
|
+
if (typeof child === "number") {
|
|
25
|
+
return /*#__PURE__*/_jsx(Text, {
|
|
26
|
+
variant: "label-sm",
|
|
27
|
+
color: "text.secondary",
|
|
28
|
+
children: child
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
return child;
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* A rule that separates content.
|
|
37
|
+
*
|
|
38
|
+
* Decorative by default — screen readers skip it, because the separation it
|
|
39
|
+
* expresses is already carried by the content either side. A labelled divider
|
|
40
|
+
* keeps its label readable.
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* <Divider />
|
|
44
|
+
* <Divider spacing="4" />
|
|
45
|
+
* <Divider orientation="vertical" />
|
|
46
|
+
* <Divider>OR</Divider>
|
|
47
|
+
*/
|
|
48
|
+
export const Divider = /*#__PURE__*/forwardRef(function Divider({
|
|
49
|
+
orientation = "horizontal",
|
|
50
|
+
color = "border.default",
|
|
51
|
+
thickness = "hairline",
|
|
52
|
+
spacing,
|
|
53
|
+
labelAlign = "center",
|
|
54
|
+
children,
|
|
55
|
+
style,
|
|
56
|
+
...rest
|
|
57
|
+
}, ref) {
|
|
58
|
+
const {
|
|
59
|
+
theme
|
|
60
|
+
} = useUnistyles();
|
|
61
|
+
const isVertical = orientation === "vertical";
|
|
62
|
+
// A vertical rule has no room to run either side of a label, so children are
|
|
63
|
+
// dropped rather than silently laid out in a direction they were not written for.
|
|
64
|
+
const label = isVertical ? null : renderLabel(children);
|
|
65
|
+
const hasLabel = Children.count(label) > 0;
|
|
66
|
+
const lineColor = resolveThemeColor(color, theme);
|
|
67
|
+
const weight = resolveThickness(thickness);
|
|
68
|
+
const margin = spacing !== undefined ? theme.spacing[spacing] : undefined;
|
|
69
|
+
const line = {
|
|
70
|
+
backgroundColor: lineColor,
|
|
71
|
+
...(isVertical ? {
|
|
72
|
+
width: weight
|
|
73
|
+
} : {
|
|
74
|
+
height: weight
|
|
75
|
+
})
|
|
76
|
+
};
|
|
77
|
+
if (!hasLabel) {
|
|
78
|
+
return /*#__PURE__*/_jsx(View, {
|
|
79
|
+
ref: ref,
|
|
80
|
+
accessibilityElementsHidden: true,
|
|
81
|
+
importantForAccessibility: "no-hide-descendants",
|
|
82
|
+
"aria-hidden": true,
|
|
83
|
+
...rest,
|
|
84
|
+
style: [styles.rule, line, margin !== undefined ? isVertical ? {
|
|
85
|
+
marginHorizontal: margin
|
|
86
|
+
} : {
|
|
87
|
+
marginVertical: margin
|
|
88
|
+
} : null, style]
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// The label stays readable, so the wrapper is not hidden from accessibility —
|
|
93
|
+
// only the two rule segments are, and each is a bare decorative View.
|
|
94
|
+
return /*#__PURE__*/_jsxs(View, {
|
|
95
|
+
ref: ref,
|
|
96
|
+
...rest,
|
|
97
|
+
style: [styles.labelledRoot, margin !== undefined ? {
|
|
98
|
+
marginVertical: margin
|
|
99
|
+
} : null, style],
|
|
100
|
+
children: [labelAlign !== "start" && /*#__PURE__*/_jsx(View, {
|
|
101
|
+
style: [styles.labelledSegment, line]
|
|
102
|
+
}), label, labelAlign !== "end" && /*#__PURE__*/_jsx(View, {
|
|
103
|
+
style: [styles.labelledSegment, line]
|
|
104
|
+
})]
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
// ─── Styles ───────────────────────────────────────────────────────────────────
|
|
109
|
+
|
|
110
|
+
const styles = StyleSheet.create(theme => ({
|
|
111
|
+
// Stretches across its parent's cross axis: full width in a column, full
|
|
112
|
+
// height in a row. The `line` style supplies the other dimension.
|
|
113
|
+
rule: {
|
|
114
|
+
alignSelf: "stretch"
|
|
115
|
+
},
|
|
116
|
+
labelledRoot: {
|
|
117
|
+
alignSelf: "stretch",
|
|
118
|
+
flexDirection: "row",
|
|
119
|
+
alignItems: "center",
|
|
120
|
+
gap: theme.spacing["3"],
|
|
121
|
+
uni__dependencies: [0]
|
|
122
|
+
},
|
|
123
|
+
labelledSegment: {
|
|
124
|
+
flex: 1
|
|
125
|
+
}
|
|
126
|
+
}));
|
|
127
|
+
//# sourceMappingURL=Divider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["Children","forwardRef","StyleSheet","RNStyleSheet","useUnistyles","resolveThemeColor","Text","jsx","_jsx","jsxs","_jsxs","resolveThickness","thickness","hairlineWidth","renderLabel","children","map","child","trim","length","variant","color","Divider","orientation","spacing","labelAlign","style","rest","ref","theme","isVertical","label","hasLabel","count","lineColor","weight","margin","undefined","line","backgroundColor","width","height","View","accessibilityElementsHidden","importantForAccessibility","styles","rule","marginHorizontal","marginVertical","labelledRoot","labelledSegment","create","alignSelf","flexDirection","alignItems","gap","uni__dependencies","flex"],"sourceRoot":"../../../../src","sources":["components/divider/Divider.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["Divider"],"sourceRoot":"../../../../src","sources":["components/divider/index.ts"],"mappings":";;AAMA,SAASA,OAAO","ignoreList":[]}
|
|
@@ -4,12 +4,14 @@ export * from "./avatar/index.js";
|
|
|
4
4
|
export * from "./box/index.js";
|
|
5
5
|
export * from "./button/index.js";
|
|
6
6
|
export * from "./chip/index.js";
|
|
7
|
+
export * from "./divider/index.js";
|
|
7
8
|
export * from "./empty-state/index.js";
|
|
8
9
|
export * from "./header/index.js";
|
|
9
10
|
export * from "./icon/index.js";
|
|
10
11
|
export * from "./image/index.js";
|
|
11
12
|
export * from "./page-indicator/index.js";
|
|
12
13
|
export * from "./portal/index.js";
|
|
14
|
+
export * from "./pressable/index.js";
|
|
13
15
|
export * from "./screen/index.js";
|
|
14
16
|
export * from "./slot/index.js";
|
|
15
17
|
export * from "./spinner/index.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sourceRoot":"../../../src","sources":["components/index.ts"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":[],"sourceRoot":"../../../src","sources":["components/index.ts"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","ignoreList":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["PressableScale"],"sourceRoot":"../../../../src","sources":["components/pressable/index.ts"],"mappings":";;AAIA,SAASA,cAAc","ignoreList":[]}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { Pressable } from "react-native-unistyles/components/native/Pressable";
|
|
4
|
+
import { forwardRef, useCallback, useEffect, useState } from "react";
|
|
5
|
+
import Animated, { Easing, interpolate, useAnimatedStyle, useSharedValue, withSpring, withTiming } from "react-native-reanimated";
|
|
6
|
+
import { StyleSheet } from "react-native-unistyles";
|
|
7
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
8
|
+
const AnimatedPressable = Animated.createAnimatedComponent(Pressable);
|
|
9
|
+
|
|
10
|
+
/** A 250ms ease that reads as instant on press-in but never snaps back on release. */
|
|
11
|
+
const DEFAULT_TIMING = {
|
|
12
|
+
duration: 250,
|
|
13
|
+
easing: Easing.bezier(0.25, 0.1, 0.25, 1)
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* A `Pressable` that animates a scale (and optionally an opacity) between its
|
|
17
|
+
* resting and pressed states, driven by a single shared `progress` value on the
|
|
18
|
+
* UI thread.
|
|
19
|
+
*
|
|
20
|
+
* Use it anywhere a press deserves physical feedback — cards, list rows, custom
|
|
21
|
+
* controls. `Button` renders one internally via its `animation` prop.
|
|
22
|
+
*/
|
|
23
|
+
export const PressableScale = /*#__PURE__*/forwardRef(function PressableScale({
|
|
24
|
+
baseScale = 1,
|
|
25
|
+
minScale = 0.96,
|
|
26
|
+
pressedOpacity,
|
|
27
|
+
animationConfig,
|
|
28
|
+
isDisabled = false,
|
|
29
|
+
style,
|
|
30
|
+
onPressIn,
|
|
31
|
+
onPressOut,
|
|
32
|
+
...rest
|
|
33
|
+
}, ref) {
|
|
34
|
+
const progress = useSharedValue(0);
|
|
35
|
+
|
|
36
|
+
// Only the function form of `style` needs a re-render to resolve; tracking
|
|
37
|
+
// `pressed` unconditionally would re-render every consumer on every touch.
|
|
38
|
+
const isStyleFunction = typeof style === "function";
|
|
39
|
+
const [pressed, setPressed] = useState(false);
|
|
40
|
+
const animateTo = useCallback(to => {
|
|
41
|
+
if (animationConfig?.type === "spring") {
|
|
42
|
+
progress.value = withSpring(to, animationConfig.config);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
progress.value = withTiming(to, {
|
|
46
|
+
...DEFAULT_TIMING,
|
|
47
|
+
...animationConfig?.config
|
|
48
|
+
});
|
|
49
|
+
}, [animationConfig, progress]);
|
|
50
|
+
const handlePressIn = useCallback(event => {
|
|
51
|
+
animateTo(1);
|
|
52
|
+
if (isStyleFunction) setPressed(true);
|
|
53
|
+
onPressIn?.(event);
|
|
54
|
+
}, [animateTo, isStyleFunction, onPressIn]);
|
|
55
|
+
const handlePressOut = useCallback(event => {
|
|
56
|
+
animateTo(0);
|
|
57
|
+
if (isStyleFunction) setPressed(false);
|
|
58
|
+
onPressOut?.(event);
|
|
59
|
+
}, [animateTo, isStyleFunction, onPressOut]);
|
|
60
|
+
|
|
61
|
+
// A press that disables its own pressable — `onPress` flipping a button into
|
|
62
|
+
// a loading state — never gets an `onPressOut`, so release it here instead
|
|
63
|
+
// of leaving it stuck at the pressed scale.
|
|
64
|
+
useEffect(() => {
|
|
65
|
+
if (!isDisabled) return;
|
|
66
|
+
animateTo(0);
|
|
67
|
+
setPressed(false);
|
|
68
|
+
}, [isDisabled, animateTo]);
|
|
69
|
+
const animatedStyle = useAnimatedStyle(() => {
|
|
70
|
+
const scale = interpolate(progress.value, [0, 1], [baseScale, minScale]);
|
|
71
|
+
if (pressedOpacity === undefined) {
|
|
72
|
+
return {
|
|
73
|
+
transform: [{
|
|
74
|
+
scale
|
|
75
|
+
}]
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
return {
|
|
79
|
+
transform: [{
|
|
80
|
+
scale
|
|
81
|
+
}],
|
|
82
|
+
opacity: interpolate(progress.value, [0, 1], [1, pressedOpacity])
|
|
83
|
+
};
|
|
84
|
+
});
|
|
85
|
+
const pressableState = {
|
|
86
|
+
pressed
|
|
87
|
+
};
|
|
88
|
+
return /*#__PURE__*/_jsx(AnimatedPressable, {
|
|
89
|
+
ref: ref,
|
|
90
|
+
disabled: isDisabled,
|
|
91
|
+
...rest,
|
|
92
|
+
onPressIn: handlePressIn,
|
|
93
|
+
onPressOut: handlePressOut
|
|
94
|
+
// The animated style goes first so anything the caller sets — a disabled
|
|
95
|
+
// opacity, say — still wins.
|
|
96
|
+
,
|
|
97
|
+
style: [styles.root, animatedStyle, isStyleFunction ? style(pressableState) : style]
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
// ─── Styles ───────────────────────────────────────────────────────────────────
|
|
102
|
+
//
|
|
103
|
+
// PressableScale has no style of its own — this stylesheet exists so the
|
|
104
|
+
// Unistyles Babel plugin swaps the `Pressable` imported above for its
|
|
105
|
+
// Unistyles-aware counterpart. Without it a themed style handed in through
|
|
106
|
+
// `style` freezes at whichever theme was active when it was created.
|
|
107
|
+
const styles = StyleSheet.create(() => ({
|
|
108
|
+
root: {}
|
|
109
|
+
}));
|
|
110
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["forwardRef","useCallback","useEffect","useState","Animated","Easing","interpolate","useAnimatedStyle","useSharedValue","withSpring","withTiming","StyleSheet","jsx","_jsx","AnimatedPressable","createAnimatedComponent","Pressable","DEFAULT_TIMING","duration","easing","bezier","PressableScale","baseScale","minScale","pressedOpacity","animationConfig","isDisabled","style","onPressIn","onPressOut","rest","ref","progress","isStyleFunction","pressed","setPressed","animateTo","to","type","value","config","handlePressIn","event","handlePressOut","animatedStyle","scale","undefined","transform","opacity","pressableState","disabled","styles","root","create"],"sourceRoot":"../../../../../../src","sources":["components/pressable/variants/PressableScale/index.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -4,6 +4,7 @@ import type { ColorToken, TerraIconName } from "../../theme/types";
|
|
|
4
4
|
export type ButtonVariant = "primary" | "secondary" | "outline" | "ghost" | "danger";
|
|
5
5
|
export type ButtonSize = "sm" | "md" | "lg";
|
|
6
6
|
export type ButtonRadius = "none" | "sm" | "md" | "lg" | "xl" | "full";
|
|
7
|
+
export type ButtonAnimation = "scale" | "opacity" | "none";
|
|
7
8
|
export interface ButtonProps extends Omit<PressableProps, "style" | "children" | "disabled"> {
|
|
8
9
|
variant?: ButtonVariant;
|
|
9
10
|
size?: ButtonSize;
|
|
@@ -19,6 +20,12 @@ export interface ButtonProps extends Omit<PressableProps, "style" | "children" |
|
|
|
19
20
|
fullWidth?: boolean;
|
|
20
21
|
/** Remove the button's built-in horizontal padding. */
|
|
21
22
|
compact?: boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Press feedback. `'scale'` shrinks the button to 0.96, `'opacity'` dims it
|
|
25
|
+
* to `opacity.pressed`, `'none'` leaves it static. The two are mutually
|
|
26
|
+
* exclusive. Defaults to `'scale'`.
|
|
27
|
+
*/
|
|
28
|
+
animation?: ButtonAnimation;
|
|
22
29
|
/**
|
|
23
30
|
* Overrides the variant's resolved background color (theme token or raw
|
|
24
31
|
* CSS color). The label/icon/spinner foreground automatically switches to
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Button.d.ts","sourceRoot":"","sources":["../../../../../src/components/button/Button.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA0D,KAAK,SAAS,EAAc,MAAM,OAAO,CAAC;AAC3G,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"Button.d.ts","sourceRoot":"","sources":["../../../../../src/components/button/Button.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA0D,KAAK,SAAS,EAAc,MAAM,OAAO,CAAC;AAC3G,OAAO,KAAK,EAAa,cAAc,EAA8B,MAAM,cAAc,CAAC;AAK1F,OAAO,KAAK,EAAE,UAAU,EAAmB,aAAa,EAA2B,MAAM,cAAc,CAAC;AAQxG,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,GAAG,OAAO,GAAG,QAAQ,CAAC;AACrF,MAAM,MAAM,UAAU,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAC5C,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,MAAM,CAAC;AACvE,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;AAK3D,MAAM,WAAW,WAAY,SAAQ,IAAI,CAAC,cAAc,EAAE,OAAO,GAAG,UAAU,GAAG,UAAU,CAAC;IAC1F,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,4DAA4D;IAC5D,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,uDAAuD;IACvD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;OAIG;IACH,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B;;;;;OAKG;IACH,UAAU,CAAC,EAAE,UAAU,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IACxC,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAID,UAAU,kBAAkB;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,UAAU,CAAC;CAClB;AAOD,eAAO,MAAM,gBAAgB,QAAO,kBAA+C,CAAC;AAmEpF,QAAA,MAAM,WAAW,GAAI,cAAc;IAAE,QAAQ,EAAE,SAAS,CAAA;CAAE,gCAQzD,CAAC;AAUF,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,aAAa,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,QAAA,MAAM,UAAU,GAAI,yDAAyD,eAAe,gCAW3F,CAAC;AAgBF,QAAA,MAAM,UAAU,yLAkEd,CAAC;AAEH,KAAK,eAAe,GAAG,OAAO,UAAU,GAAG;IACzC,IAAI,EAAE,OAAO,UAAU,CAAC;IACxB,KAAK,EAAE,OAAO,WAAW,CAAC;CAC3B,CAAC;AAEF,eAAO,MAAM,MAAM,EAAiB,eAAe,CAAC"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export type { ButtonIconProps, ButtonProps, ButtonRadius, ButtonSize, ButtonVariant, } from "./Button.js";
|
|
1
|
+
export type { ButtonAnimation, ButtonIconProps, ButtonProps, ButtonRadius, ButtonSize, ButtonVariant, } from "./Button.js";
|
|
2
2
|
export { Button, useButtonContext } from "./Button.js";
|
|
3
3
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/button/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,eAAe,EACf,WAAW,EACX,YAAY,EACZ,UAAU,EACV,aAAa,GACd,MAAM,aAAU,CAAC;AAClB,OAAO,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,aAAU,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/button/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,eAAe,EACf,eAAe,EACf,WAAW,EACX,YAAY,EACZ,UAAU,EACV,aAAa,GACd,MAAM,aAAU,CAAC;AAClB,OAAO,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,aAAU,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
import { type ViewProps } from "react-native";
|
|
3
|
+
import type { ColorToken, SpacingKey } from "../../theme/types";
|
|
4
|
+
export type DividerOrientation = "horizontal" | "vertical";
|
|
5
|
+
export type DividerLabelAlign = "start" | "center" | "end";
|
|
6
|
+
/** `number | 'hairline'`, mirroring `Box`'s `borderWidth`. */
|
|
7
|
+
export type DividerThickness = number | "hairline";
|
|
8
|
+
export interface DividerProps extends ViewProps {
|
|
9
|
+
/** Rule direction. Defaults to `'horizontal'`. */
|
|
10
|
+
orientation?: DividerOrientation;
|
|
11
|
+
/** Rule color. Defaults to `'border.default'`. */
|
|
12
|
+
color?: ColorToken;
|
|
13
|
+
/**
|
|
14
|
+
* Rule weight. `'hairline'` is the thinnest line the display can draw —
|
|
15
|
+
* a true 1px rule at any density. Defaults to `'hairline'`.
|
|
16
|
+
*/
|
|
17
|
+
thickness?: DividerThickness;
|
|
18
|
+
/**
|
|
19
|
+
* Symmetric margin on the cross axis — above and below a horizontal rule,
|
|
20
|
+
* either side of a vertical one. Defaults to `undefined` (no margin).
|
|
21
|
+
*/
|
|
22
|
+
spacing?: SpacingKey;
|
|
23
|
+
/**
|
|
24
|
+
* Where the label sits along the rule. Ignored without `children`.
|
|
25
|
+
* Defaults to `'center'`.
|
|
26
|
+
*/
|
|
27
|
+
labelAlign?: DividerLabelAlign;
|
|
28
|
+
/**
|
|
29
|
+
* An optional label, drawn with the rule running either side of it. Strings
|
|
30
|
+
* and numbers are wrapped in `Text` automatically. Horizontal only — a
|
|
31
|
+
* vertical divider ignores children.
|
|
32
|
+
*/
|
|
33
|
+
children?: ReactNode;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* A rule that separates content.
|
|
37
|
+
*
|
|
38
|
+
* Decorative by default — screen readers skip it, because the separation it
|
|
39
|
+
* expresses is already carried by the content either side. A labelled divider
|
|
40
|
+
* keeps its label readable.
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* <Divider />
|
|
44
|
+
* <Divider spacing="4" />
|
|
45
|
+
* <Divider orientation="vertical" />
|
|
46
|
+
* <Divider>OR</Divider>
|
|
47
|
+
*/
|
|
48
|
+
export declare const Divider: import("react").ForwardRefExoticComponent<DividerProps & import("react").RefAttributes<import("react-native/types_generated/src/private/webapis/dom/nodes/ReactNativeElement").default>>;
|
|
49
|
+
//# sourceMappingURL=Divider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Divider.d.ts","sourceRoot":"","sources":["../../../../../src/components/divider/Divider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA2C,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAChF,OAAO,EAAoC,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAIhF,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAI3D,MAAM,MAAM,kBAAkB,GAAG,YAAY,GAAG,UAAU,CAAC;AAC3D,MAAM,MAAM,iBAAiB,GAAG,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAC;AAE3D,8DAA8D;AAC9D,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,UAAU,CAAC;AAEnD,MAAM,WAAW,YAAa,SAAQ,SAAS;IAC7C,kDAAkD;IAClD,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,kDAAkD;IAClD,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB;;;OAGG;IACH,SAAS,CAAC,EAAE,gBAAgB,CAAC;IAC7B;;;OAGG;IACH,OAAO,CAAC,EAAE,UAAU,CAAC;IACrB;;;OAGG;IACH,UAAU,CAAC,EAAE,iBAAiB,CAAC;IAC/B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AA0BD;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,OAAO,0LAgElB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/divider/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,iBAAiB,EACjB,kBAAkB,EAClB,YAAY,EACZ,gBAAgB,GACjB,MAAM,cAAW,CAAC;AACnB,OAAO,EAAE,OAAO,EAAE,MAAM,cAAW,CAAC"}
|
|
@@ -2,12 +2,14 @@ export * from "./avatar/index.js";
|
|
|
2
2
|
export * from "./box/index.js";
|
|
3
3
|
export * from "./button/index.js";
|
|
4
4
|
export * from "./chip/index.js";
|
|
5
|
+
export * from "./divider/index.js";
|
|
5
6
|
export * from "./empty-state/index.js";
|
|
6
7
|
export * from "./header/index.js";
|
|
7
8
|
export * from "./icon/index.js";
|
|
8
9
|
export * from "./image/index.js";
|
|
9
10
|
export * from "./page-indicator/index.js";
|
|
10
11
|
export * from "./portal/index.js";
|
|
12
|
+
export * from "./pressable/index.js";
|
|
11
13
|
export * from "./screen/index.js";
|
|
12
14
|
export * from "./slot/index.js";
|
|
13
15
|
export * from "./spinner/index.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAU,CAAC;AACzB,cAAc,gBAAO,CAAC;AACtB,cAAc,mBAAU,CAAC;AACzB,cAAc,iBAAQ,CAAC;AACvB,cAAc,wBAAe,CAAC;AAC9B,cAAc,mBAAU,CAAC;AACzB,cAAc,iBAAQ,CAAC;AACvB,cAAc,kBAAS,CAAC;AACxB,cAAc,2BAAkB,CAAC;AACjC,cAAc,mBAAU,CAAC;AACzB,cAAc,mBAAU,CAAC;AACzB,cAAc,iBAAQ,CAAC;AACvB,cAAc,oBAAW,CAAC;AAC1B,cAAc,oBAAW,CAAC;AAC1B,cAAc,iBAAQ,CAAC;AACvB,cAAc,kBAAS,CAAC;AACxB,cAAc,oBAAW,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAU,CAAC;AACzB,cAAc,gBAAO,CAAC;AACtB,cAAc,mBAAU,CAAC;AACzB,cAAc,iBAAQ,CAAC;AACvB,cAAc,oBAAW,CAAC;AAC1B,cAAc,wBAAe,CAAC;AAC9B,cAAc,mBAAU,CAAC;AACzB,cAAc,iBAAQ,CAAC;AACvB,cAAc,kBAAS,CAAC;AACxB,cAAc,2BAAkB,CAAC;AACjC,cAAc,mBAAU,CAAC;AACzB,cAAc,sBAAa,CAAC;AAC5B,cAAc,mBAAU,CAAC;AACzB,cAAc,iBAAQ,CAAC;AACvB,cAAc,oBAAW,CAAC;AAC1B,cAAc,oBAAW,CAAC;AAC1B,cAAc,iBAAQ,CAAC;AACvB,cAAc,kBAAS,CAAC;AACxB,cAAc,oBAAW,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/pressable/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,6BAA6B,EAC7B,mBAAmB,GACpB,MAAM,oCAA2B,CAAC;AACnC,OAAO,EAAE,cAAc,EAAE,MAAM,oCAA2B,CAAC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { PressableProps, PressableStateCallbackType, StyleProp, ViewStyle } from "react-native";
|
|
2
|
+
import { type WithSpringConfig, type WithTimingConfig } from "react-native-reanimated";
|
|
3
|
+
export type PressableScaleAnimationConfig = {
|
|
4
|
+
type: "timing";
|
|
5
|
+
config?: WithTimingConfig;
|
|
6
|
+
} | {
|
|
7
|
+
type: "spring";
|
|
8
|
+
config?: WithSpringConfig;
|
|
9
|
+
};
|
|
10
|
+
export interface PressableScaleProps extends Omit<PressableProps, "style" | "disabled"> {
|
|
11
|
+
/** Scale held at rest. Defaults to `1`. */
|
|
12
|
+
baseScale?: number;
|
|
13
|
+
/**
|
|
14
|
+
* Scale held while pressed. Values below `baseScale` shrink, above it grow.
|
|
15
|
+
* Defaults to `0.96`.
|
|
16
|
+
*/
|
|
17
|
+
minScale?: number;
|
|
18
|
+
/**
|
|
19
|
+
* Opacity held while pressed, animated on the same curve as the scale.
|
|
20
|
+
* Defaults to `undefined` — opacity is left untouched so `style` keeps
|
|
21
|
+
* ownership of it.
|
|
22
|
+
*/
|
|
23
|
+
pressedOpacity?: number;
|
|
24
|
+
/**
|
|
25
|
+
* Drives the press animation. Defaults to `{ type: 'timing' }` with a 250ms
|
|
26
|
+
* ease; pass `{ type: 'spring' }` for a springy release.
|
|
27
|
+
*/
|
|
28
|
+
animationConfig?: PressableScaleAnimationConfig;
|
|
29
|
+
/** Blocks presses and holds the resting scale. Defaults to `false`. */
|
|
30
|
+
isDisabled?: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Styles for the pressable itself. The function form receives `pressed`
|
|
33
|
+
* only — `hovered` and `focused` are not tracked, because the animated
|
|
34
|
+
* style has to be merged outside of `Pressable`'s own callback.
|
|
35
|
+
*/
|
|
36
|
+
style?: StyleProp<ViewStyle> | ((state: PressableStateCallbackType) => StyleProp<ViewStyle>);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* A `Pressable` that animates a scale (and optionally an opacity) between its
|
|
40
|
+
* resting and pressed states, driven by a single shared `progress` value on the
|
|
41
|
+
* UI thread.
|
|
42
|
+
*
|
|
43
|
+
* Use it anywhere a press deserves physical feedback — cards, list rows, custom
|
|
44
|
+
* controls. `Button` renders one internally via its `animation` prop.
|
|
45
|
+
*/
|
|
46
|
+
export declare const PressableScale: import("react").ForwardRefExoticComponent<PressableScaleProps & import("react").RefAttributes<import("react-native/types_generated/src/private/webapis/dom/nodes/ReactNativeElement").default>>;
|
|
47
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../../src/components/pressable/variants/PressableScale/index.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAEV,cAAc,EACd,0BAA0B,EAC1B,SAAS,EACT,SAAS,EACV,MAAM,cAAc,CAAC;AAGtB,OAAiB,EAKf,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EAGtB,MAAM,yBAAyB,CAAC;AAWjC,MAAM,MAAM,6BAA6B,GACrC;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,CAAC,EAAE,gBAAgB,CAAA;CAAE,GAC7C;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,CAAC,EAAE,gBAAgB,CAAA;CAAE,CAAC;AAElD,MAAM,WAAW,mBAAoB,SAAQ,IAAI,CAAC,cAAc,EAAE,OAAO,GAAG,UAAU,CAAC;IACrF,2CAA2C;IAC3C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,eAAe,CAAC,EAAE,6BAA6B,CAAC;IAChD,uEAAuE;IACvE,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;OAIG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,0BAA0B,KAAK,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC;CAC9F;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,cAAc,iMAsF1B,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { Children, type ComponentRef, createContext, forwardRef, type ReactNode, useContext } from "react";
|
|
2
|
-
import type { PressableProps } from "react-native";
|
|
3
|
-
import { Pressable } from "react-native";
|
|
2
|
+
import type { Pressable, PressableProps, PressableStateCallbackType } from "react-native";
|
|
4
3
|
|
|
5
4
|
import { StyleSheet, useUnistyles } from "react-native-unistyles";
|
|
6
5
|
|
|
@@ -9,12 +8,17 @@ import type { ColorToken, FontWeightToken, TerraIconName, TerraTheme, TextVarian
|
|
|
9
8
|
import { readableOn } from "#utils/color-utils";
|
|
10
9
|
import { resolveThemeColor } from "#utils/resolve-theme-color";
|
|
11
10
|
import { Icon } from "../icon";
|
|
11
|
+
import { PressableScale } from "../pressable";
|
|
12
12
|
import { Spinner } from "../spinner";
|
|
13
13
|
import { Text } from "../text";
|
|
14
14
|
|
|
15
15
|
export type ButtonVariant = "primary" | "secondary" | "outline" | "ghost" | "danger";
|
|
16
16
|
export type ButtonSize = "sm" | "md" | "lg";
|
|
17
17
|
export type ButtonRadius = "none" | "sm" | "md" | "lg" | "xl" | "full";
|
|
18
|
+
export type ButtonAnimation = "scale" | "opacity" | "none";
|
|
19
|
+
|
|
20
|
+
/** Matches pressto's `minScale` default — enough to feel, not enough to distract. */
|
|
21
|
+
const PRESSED_SCALE = 0.96;
|
|
18
22
|
|
|
19
23
|
export interface ButtonProps extends Omit<PressableProps, "style" | "children" | "disabled"> {
|
|
20
24
|
variant?: ButtonVariant;
|
|
@@ -31,6 +35,12 @@ export interface ButtonProps extends Omit<PressableProps, "style" | "children" |
|
|
|
31
35
|
fullWidth?: boolean;
|
|
32
36
|
/** Remove the button's built-in horizontal padding. */
|
|
33
37
|
compact?: boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Press feedback. `'scale'` shrinks the button to 0.96, `'opacity'` dims it
|
|
40
|
+
* to `opacity.pressed`, `'none'` leaves it static. The two are mutually
|
|
41
|
+
* exclusive. Defaults to `'scale'`.
|
|
42
|
+
*/
|
|
43
|
+
animation?: ButtonAnimation;
|
|
34
44
|
/**
|
|
35
45
|
* Overrides the variant's resolved background color (theme token or raw
|
|
36
46
|
* CSS color). The label/icon/spinner foreground automatically switches to
|
|
@@ -182,6 +192,7 @@ const ButtonRoot = forwardRef<ComponentRef<typeof Pressable>, ButtonProps>(funct
|
|
|
182
192
|
isIconOnly = false,
|
|
183
193
|
fullWidth = true,
|
|
184
194
|
compact = false,
|
|
195
|
+
animation = "scale",
|
|
185
196
|
background,
|
|
186
197
|
children,
|
|
187
198
|
onPress,
|
|
@@ -206,27 +217,35 @@ const ButtonRoot = forwardRef<ComponentRef<typeof Pressable>, ButtonProps>(funct
|
|
|
206
217
|
style?: PressableProps["style"];
|
|
207
218
|
};
|
|
208
219
|
|
|
220
|
+
const ownStyles = [
|
|
221
|
+
styles.base,
|
|
222
|
+
{ backgroundColor: bg, borderColor: border, borderWidth },
|
|
223
|
+
compact ? styles.compact : null,
|
|
224
|
+
isDisabled ? { opacity: theme.opacity.disabled } : null,
|
|
225
|
+
];
|
|
226
|
+
// Only the function form forces a re-render per touch, so keep the array form
|
|
227
|
+
// whenever the caller's style doesn't need the pressed state.
|
|
228
|
+
const style =
|
|
229
|
+
typeof externalStyle === "function"
|
|
230
|
+
? (state: PressableStateCallbackType) => [...ownStyles, externalStyle(state)]
|
|
231
|
+
: [...ownStyles, externalStyle];
|
|
232
|
+
|
|
209
233
|
return (
|
|
210
234
|
<ButtonContext.Provider value={{ color: fg, size }}>
|
|
211
|
-
<
|
|
235
|
+
<PressableScale
|
|
212
236
|
ref={ref}
|
|
213
237
|
onPress={blocked ? undefined : onPress}
|
|
214
|
-
|
|
238
|
+
isDisabled={blocked}
|
|
239
|
+
minScale={animation === "scale" ? PRESSED_SCALE : 1}
|
|
240
|
+
pressedOpacity={animation === "opacity" ? theme.opacity.pressed : undefined}
|
|
215
241
|
accessibilityRole="button"
|
|
216
242
|
accessibilityState={{ disabled: blocked, busy: isLoading }}
|
|
217
243
|
{...pressableRest}
|
|
218
|
-
style={
|
|
219
|
-
styles.base,
|
|
220
|
-
{ backgroundColor: bg, borderColor: border, borderWidth },
|
|
221
|
-
compact ? styles.compact : null,
|
|
222
|
-
state.pressed && !blocked ? { opacity: theme.opacity.pressed } : null,
|
|
223
|
-
isDisabled ? { opacity: theme.opacity.disabled } : null,
|
|
224
|
-
typeof externalStyle === "function" ? externalStyle(state) : externalStyle,
|
|
225
|
-
]}
|
|
244
|
+
style={style}
|
|
226
245
|
>
|
|
227
246
|
{isLoading && <Spinner size="sm" color={fg} />}
|
|
228
247
|
{renderChildren(children)}
|
|
229
|
-
</
|
|
248
|
+
</PressableScale>
|
|
230
249
|
</ButtonContext.Provider>
|
|
231
250
|
);
|
|
232
251
|
});
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { Children, type ComponentRef, forwardRef, type ReactNode } from "react";
|
|
2
|
+
import { StyleSheet as RNStyleSheet, View, type ViewProps } from "react-native";
|
|
3
|
+
|
|
4
|
+
import { StyleSheet, useUnistyles } from "react-native-unistyles";
|
|
5
|
+
|
|
6
|
+
import type { ColorToken, SpacingKey } from "#theme/types";
|
|
7
|
+
import { resolveThemeColor } from "#utils/resolve-theme-color";
|
|
8
|
+
import { Text } from "../text";
|
|
9
|
+
|
|
10
|
+
export type DividerOrientation = "horizontal" | "vertical";
|
|
11
|
+
export type DividerLabelAlign = "start" | "center" | "end";
|
|
12
|
+
|
|
13
|
+
/** `number | 'hairline'`, mirroring `Box`'s `borderWidth`. */
|
|
14
|
+
export type DividerThickness = number | "hairline";
|
|
15
|
+
|
|
16
|
+
export interface DividerProps extends ViewProps {
|
|
17
|
+
/** Rule direction. Defaults to `'horizontal'`. */
|
|
18
|
+
orientation?: DividerOrientation;
|
|
19
|
+
/** Rule color. Defaults to `'border.default'`. */
|
|
20
|
+
color?: ColorToken;
|
|
21
|
+
/**
|
|
22
|
+
* Rule weight. `'hairline'` is the thinnest line the display can draw —
|
|
23
|
+
* a true 1px rule at any density. Defaults to `'hairline'`.
|
|
24
|
+
*/
|
|
25
|
+
thickness?: DividerThickness;
|
|
26
|
+
/**
|
|
27
|
+
* Symmetric margin on the cross axis — above and below a horizontal rule,
|
|
28
|
+
* either side of a vertical one. Defaults to `undefined` (no margin).
|
|
29
|
+
*/
|
|
30
|
+
spacing?: SpacingKey;
|
|
31
|
+
/**
|
|
32
|
+
* Where the label sits along the rule. Ignored without `children`.
|
|
33
|
+
* Defaults to `'center'`.
|
|
34
|
+
*/
|
|
35
|
+
labelAlign?: DividerLabelAlign;
|
|
36
|
+
/**
|
|
37
|
+
* An optional label, drawn with the rule running either side of it. Strings
|
|
38
|
+
* and numbers are wrapped in `Text` automatically. Horizontal only — a
|
|
39
|
+
* vertical divider ignores children.
|
|
40
|
+
*/
|
|
41
|
+
children?: ReactNode;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function resolveThickness(thickness: DividerThickness): number {
|
|
45
|
+
return thickness === "hairline" ? RNStyleSheet.hairlineWidth : thickness;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function renderLabel(children: ReactNode): ReactNode {
|
|
49
|
+
return Children.map(children, (child) => {
|
|
50
|
+
if (typeof child === "string") {
|
|
51
|
+
return child.trim().length > 0 ? (
|
|
52
|
+
<Text variant="label-sm" color="text.secondary">
|
|
53
|
+
{child}
|
|
54
|
+
</Text>
|
|
55
|
+
) : null;
|
|
56
|
+
}
|
|
57
|
+
if (typeof child === "number") {
|
|
58
|
+
return (
|
|
59
|
+
<Text variant="label-sm" color="text.secondary">
|
|
60
|
+
{child}
|
|
61
|
+
</Text>
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
return child;
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* A rule that separates content.
|
|
70
|
+
*
|
|
71
|
+
* Decorative by default — screen readers skip it, because the separation it
|
|
72
|
+
* expresses is already carried by the content either side. A labelled divider
|
|
73
|
+
* keeps its label readable.
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* <Divider />
|
|
77
|
+
* <Divider spacing="4" />
|
|
78
|
+
* <Divider orientation="vertical" />
|
|
79
|
+
* <Divider>OR</Divider>
|
|
80
|
+
*/
|
|
81
|
+
export const Divider = forwardRef<ComponentRef<typeof View>, DividerProps>(function Divider(
|
|
82
|
+
{
|
|
83
|
+
orientation = "horizontal",
|
|
84
|
+
color = "border.default",
|
|
85
|
+
thickness = "hairline",
|
|
86
|
+
spacing,
|
|
87
|
+
labelAlign = "center",
|
|
88
|
+
children,
|
|
89
|
+
style,
|
|
90
|
+
...rest
|
|
91
|
+
},
|
|
92
|
+
ref
|
|
93
|
+
) {
|
|
94
|
+
const { theme } = useUnistyles();
|
|
95
|
+
const isVertical = orientation === "vertical";
|
|
96
|
+
// A vertical rule has no room to run either side of a label, so children are
|
|
97
|
+
// dropped rather than silently laid out in a direction they were not written for.
|
|
98
|
+
const label = isVertical ? null : renderLabel(children);
|
|
99
|
+
const hasLabel = Children.count(label) > 0;
|
|
100
|
+
|
|
101
|
+
const lineColor = resolveThemeColor(color, theme);
|
|
102
|
+
const weight = resolveThickness(thickness);
|
|
103
|
+
const margin = spacing !== undefined ? theme.spacing[spacing] : undefined;
|
|
104
|
+
|
|
105
|
+
const line = {
|
|
106
|
+
backgroundColor: lineColor,
|
|
107
|
+
...(isVertical ? { width: weight } : { height: weight }),
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
if (!hasLabel) {
|
|
111
|
+
return (
|
|
112
|
+
<View
|
|
113
|
+
ref={ref}
|
|
114
|
+
accessibilityElementsHidden
|
|
115
|
+
importantForAccessibility="no-hide-descendants"
|
|
116
|
+
aria-hidden
|
|
117
|
+
{...rest}
|
|
118
|
+
style={[
|
|
119
|
+
styles.rule,
|
|
120
|
+
line,
|
|
121
|
+
margin !== undefined
|
|
122
|
+
? isVertical
|
|
123
|
+
? { marginHorizontal: margin }
|
|
124
|
+
: { marginVertical: margin }
|
|
125
|
+
: null,
|
|
126
|
+
style,
|
|
127
|
+
]}
|
|
128
|
+
/>
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// The label stays readable, so the wrapper is not hidden from accessibility —
|
|
133
|
+
// only the two rule segments are, and each is a bare decorative View.
|
|
134
|
+
return (
|
|
135
|
+
<View
|
|
136
|
+
ref={ref}
|
|
137
|
+
{...rest}
|
|
138
|
+
style={[styles.labelledRoot, margin !== undefined ? { marginVertical: margin } : null, style]}
|
|
139
|
+
>
|
|
140
|
+
{labelAlign !== "start" && <View style={[styles.labelledSegment, line]} />}
|
|
141
|
+
{label}
|
|
142
|
+
{labelAlign !== "end" && <View style={[styles.labelledSegment, line]} />}
|
|
143
|
+
</View>
|
|
144
|
+
);
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
// ─── Styles ───────────────────────────────────────────────────────────────────
|
|
148
|
+
|
|
149
|
+
const styles = StyleSheet.create((theme) => ({
|
|
150
|
+
// Stretches across its parent's cross axis: full width in a column, full
|
|
151
|
+
// height in a row. The `line` style supplies the other dimension.
|
|
152
|
+
rule: {
|
|
153
|
+
alignSelf: "stretch",
|
|
154
|
+
},
|
|
155
|
+
labelledRoot: {
|
|
156
|
+
alignSelf: "stretch",
|
|
157
|
+
flexDirection: "row",
|
|
158
|
+
alignItems: "center",
|
|
159
|
+
gap: theme.spacing["3"],
|
|
160
|
+
},
|
|
161
|
+
labelledSegment: {
|
|
162
|
+
flex: 1,
|
|
163
|
+
},
|
|
164
|
+
}));
|
package/src/components/index.ts
CHANGED
|
@@ -2,12 +2,14 @@ export * from "./avatar";
|
|
|
2
2
|
export * from "./box";
|
|
3
3
|
export * from "./button";
|
|
4
4
|
export * from "./chip";
|
|
5
|
+
export * from "./divider";
|
|
5
6
|
export * from "./empty-state";
|
|
6
7
|
export * from "./header";
|
|
7
8
|
export * from "./icon";
|
|
8
9
|
export * from "./image";
|
|
9
10
|
export * from "./page-indicator";
|
|
10
11
|
export * from "./portal";
|
|
12
|
+
export * from "./pressable";
|
|
11
13
|
export * from "./screen";
|
|
12
14
|
export * from "./slot";
|
|
13
15
|
export * from "./spinner";
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { type ComponentRef, forwardRef, useCallback, useEffect, useState } from "react";
|
|
2
|
+
import type {
|
|
3
|
+
GestureResponderEvent,
|
|
4
|
+
PressableProps,
|
|
5
|
+
PressableStateCallbackType,
|
|
6
|
+
StyleProp,
|
|
7
|
+
ViewStyle,
|
|
8
|
+
} from "react-native";
|
|
9
|
+
import { Pressable } from "react-native";
|
|
10
|
+
|
|
11
|
+
import Animated, {
|
|
12
|
+
Easing,
|
|
13
|
+
interpolate,
|
|
14
|
+
useAnimatedStyle,
|
|
15
|
+
useSharedValue,
|
|
16
|
+
type WithSpringConfig,
|
|
17
|
+
type WithTimingConfig,
|
|
18
|
+
withSpring,
|
|
19
|
+
withTiming,
|
|
20
|
+
} from "react-native-reanimated";
|
|
21
|
+
import { StyleSheet } from "react-native-unistyles";
|
|
22
|
+
|
|
23
|
+
const AnimatedPressable = Animated.createAnimatedComponent(Pressable);
|
|
24
|
+
|
|
25
|
+
/** A 250ms ease that reads as instant on press-in but never snaps back on release. */
|
|
26
|
+
const DEFAULT_TIMING: WithTimingConfig = {
|
|
27
|
+
duration: 250,
|
|
28
|
+
easing: Easing.bezier(0.25, 0.1, 0.25, 1),
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export type PressableScaleAnimationConfig =
|
|
32
|
+
| { type: "timing"; config?: WithTimingConfig }
|
|
33
|
+
| { type: "spring"; config?: WithSpringConfig };
|
|
34
|
+
|
|
35
|
+
export interface PressableScaleProps extends Omit<PressableProps, "style" | "disabled"> {
|
|
36
|
+
/** Scale held at rest. Defaults to `1`. */
|
|
37
|
+
baseScale?: number;
|
|
38
|
+
/**
|
|
39
|
+
* Scale held while pressed. Values below `baseScale` shrink, above it grow.
|
|
40
|
+
* Defaults to `0.96`.
|
|
41
|
+
*/
|
|
42
|
+
minScale?: number;
|
|
43
|
+
/**
|
|
44
|
+
* Opacity held while pressed, animated on the same curve as the scale.
|
|
45
|
+
* Defaults to `undefined` — opacity is left untouched so `style` keeps
|
|
46
|
+
* ownership of it.
|
|
47
|
+
*/
|
|
48
|
+
pressedOpacity?: number;
|
|
49
|
+
/**
|
|
50
|
+
* Drives the press animation. Defaults to `{ type: 'timing' }` with a 250ms
|
|
51
|
+
* ease; pass `{ type: 'spring' }` for a springy release.
|
|
52
|
+
*/
|
|
53
|
+
animationConfig?: PressableScaleAnimationConfig;
|
|
54
|
+
/** Blocks presses and holds the resting scale. Defaults to `false`. */
|
|
55
|
+
isDisabled?: boolean;
|
|
56
|
+
/**
|
|
57
|
+
* Styles for the pressable itself. The function form receives `pressed`
|
|
58
|
+
* only — `hovered` and `focused` are not tracked, because the animated
|
|
59
|
+
* style has to be merged outside of `Pressable`'s own callback.
|
|
60
|
+
*/
|
|
61
|
+
style?: StyleProp<ViewStyle> | ((state: PressableStateCallbackType) => StyleProp<ViewStyle>);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* A `Pressable` that animates a scale (and optionally an opacity) between its
|
|
66
|
+
* resting and pressed states, driven by a single shared `progress` value on the
|
|
67
|
+
* UI thread.
|
|
68
|
+
*
|
|
69
|
+
* Use it anywhere a press deserves physical feedback — cards, list rows, custom
|
|
70
|
+
* controls. `Button` renders one internally via its `animation` prop.
|
|
71
|
+
*/
|
|
72
|
+
export const PressableScale = forwardRef<ComponentRef<typeof Pressable>, PressableScaleProps>(
|
|
73
|
+
function PressableScale(
|
|
74
|
+
{
|
|
75
|
+
baseScale = 1,
|
|
76
|
+
minScale = 0.96,
|
|
77
|
+
pressedOpacity,
|
|
78
|
+
animationConfig,
|
|
79
|
+
isDisabled = false,
|
|
80
|
+
style,
|
|
81
|
+
onPressIn,
|
|
82
|
+
onPressOut,
|
|
83
|
+
...rest
|
|
84
|
+
},
|
|
85
|
+
ref
|
|
86
|
+
) {
|
|
87
|
+
const progress = useSharedValue(0);
|
|
88
|
+
|
|
89
|
+
// Only the function form of `style` needs a re-render to resolve; tracking
|
|
90
|
+
// `pressed` unconditionally would re-render every consumer on every touch.
|
|
91
|
+
const isStyleFunction = typeof style === "function";
|
|
92
|
+
const [pressed, setPressed] = useState(false);
|
|
93
|
+
|
|
94
|
+
const animateTo = useCallback(
|
|
95
|
+
(to: number) => {
|
|
96
|
+
if (animationConfig?.type === "spring") {
|
|
97
|
+
progress.value = withSpring(to, animationConfig.config);
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
progress.value = withTiming(to, { ...DEFAULT_TIMING, ...animationConfig?.config });
|
|
101
|
+
},
|
|
102
|
+
[animationConfig, progress]
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
const handlePressIn = useCallback(
|
|
106
|
+
(event: GestureResponderEvent) => {
|
|
107
|
+
animateTo(1);
|
|
108
|
+
if (isStyleFunction) setPressed(true);
|
|
109
|
+
onPressIn?.(event);
|
|
110
|
+
},
|
|
111
|
+
[animateTo, isStyleFunction, onPressIn]
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
const handlePressOut = useCallback(
|
|
115
|
+
(event: GestureResponderEvent) => {
|
|
116
|
+
animateTo(0);
|
|
117
|
+
if (isStyleFunction) setPressed(false);
|
|
118
|
+
onPressOut?.(event);
|
|
119
|
+
},
|
|
120
|
+
[animateTo, isStyleFunction, onPressOut]
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
// A press that disables its own pressable — `onPress` flipping a button into
|
|
124
|
+
// a loading state — never gets an `onPressOut`, so release it here instead
|
|
125
|
+
// of leaving it stuck at the pressed scale.
|
|
126
|
+
useEffect(() => {
|
|
127
|
+
if (!isDisabled) return;
|
|
128
|
+
animateTo(0);
|
|
129
|
+
setPressed(false);
|
|
130
|
+
}, [isDisabled, animateTo]);
|
|
131
|
+
|
|
132
|
+
const animatedStyle = useAnimatedStyle(() => {
|
|
133
|
+
const scale = interpolate(progress.value, [0, 1], [baseScale, minScale]);
|
|
134
|
+
if (pressedOpacity === undefined) {
|
|
135
|
+
return { transform: [{ scale }] };
|
|
136
|
+
}
|
|
137
|
+
return {
|
|
138
|
+
transform: [{ scale }],
|
|
139
|
+
opacity: interpolate(progress.value, [0, 1], [1, pressedOpacity]),
|
|
140
|
+
};
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
const pressableState: PressableStateCallbackType = { pressed };
|
|
144
|
+
|
|
145
|
+
return (
|
|
146
|
+
<AnimatedPressable
|
|
147
|
+
ref={ref}
|
|
148
|
+
disabled={isDisabled}
|
|
149
|
+
{...rest}
|
|
150
|
+
onPressIn={handlePressIn}
|
|
151
|
+
onPressOut={handlePressOut}
|
|
152
|
+
// The animated style goes first so anything the caller sets — a disabled
|
|
153
|
+
// opacity, say — still wins.
|
|
154
|
+
style={[styles.root, animatedStyle, isStyleFunction ? style(pressableState) : style]}
|
|
155
|
+
/>
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
);
|
|
159
|
+
|
|
160
|
+
// ─── Styles ───────────────────────────────────────────────────────────────────
|
|
161
|
+
//
|
|
162
|
+
// PressableScale has no style of its own — this stylesheet exists so the
|
|
163
|
+
// Unistyles Babel plugin swaps the `Pressable` imported above for its
|
|
164
|
+
// Unistyles-aware counterpart. Without it a themed style handed in through
|
|
165
|
+
// `style` freezes at whichever theme was active when it was created.
|
|
166
|
+
const styles = StyleSheet.create(() => ({ root: {} }));
|