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.
Files changed (36) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/lib/module/components/button/Button.js +21 -13
  3. package/lib/module/components/button/Button.js.map +1 -1
  4. package/lib/module/components/button/index.js.map +1 -1
  5. package/lib/module/components/divider/Divider.js +127 -0
  6. package/lib/module/components/divider/Divider.js.map +1 -0
  7. package/lib/module/components/divider/index.js +4 -0
  8. package/lib/module/components/divider/index.js.map +1 -0
  9. package/lib/module/components/index.js +2 -0
  10. package/lib/module/components/index.js.map +1 -1
  11. package/lib/module/components/pressable/index.js +4 -0
  12. package/lib/module/components/pressable/index.js.map +1 -0
  13. package/lib/module/components/pressable/variants/PressableScale/index.js +110 -0
  14. package/lib/module/components/pressable/variants/PressableScale/index.js.map +1 -0
  15. package/lib/typescript/src/components/button/Button.d.ts +7 -0
  16. package/lib/typescript/src/components/button/Button.d.ts.map +1 -1
  17. package/lib/typescript/src/components/button/index.d.ts +1 -1
  18. package/lib/typescript/src/components/button/index.d.ts.map +1 -1
  19. package/lib/typescript/src/components/divider/Divider.d.ts +49 -0
  20. package/lib/typescript/src/components/divider/Divider.d.ts.map +1 -0
  21. package/lib/typescript/src/components/divider/index.d.ts +3 -0
  22. package/lib/typescript/src/components/divider/index.d.ts.map +1 -0
  23. package/lib/typescript/src/components/index.d.ts +2 -0
  24. package/lib/typescript/src/components/index.d.ts.map +1 -1
  25. package/lib/typescript/src/components/pressable/index.d.ts +3 -0
  26. package/lib/typescript/src/components/pressable/index.d.ts.map +1 -0
  27. package/lib/typescript/src/components/pressable/variants/PressableScale/index.d.ts +47 -0
  28. package/lib/typescript/src/components/pressable/variants/PressableScale/index.d.ts.map +1 -0
  29. package/package.json +1 -1
  30. package/src/components/button/Button.tsx +32 -13
  31. package/src/components/button/index.ts +1 -0
  32. package/src/components/divider/Divider.tsx +164 -0
  33. package/src/components/divider/index.ts +7 -0
  34. package/src/components/index.ts +2 -0
  35. package/src/components/pressable/index.ts +5 -0
  36. 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
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
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(Pressable, {
199
+ children: /*#__PURE__*/_jsxs(PressableScale, {
186
200
  ref: ref,
187
201
  onPress: blocked ? undefined : onPress,
188
- disabled: blocked,
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: state => [styles.base, {
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","Provider","value","Pressable","disabled","accessibilityRole","accessibilityState","busy","state","base","backgroundColor","borderColor","pressed","opacity","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
+ {"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":";;AAOA,SAASA,MAAM,EAAEC,gBAAgB","ignoreList":[]}
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,4 @@
1
+ "use strict";
2
+
3
+ export { Divider } from "./Divider.js";
4
+ //# sourceMappingURL=index.js.map
@@ -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,4 @@
1
+ "use strict";
2
+
3
+ export { PressableScale } from "./variants/PressableScale/index.js";
4
+ //# sourceMappingURL=index.js.map
@@ -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,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAMnD,OAAO,KAAK,EAAE,UAAU,EAAmB,aAAa,EAA2B,MAAM,cAAc,CAAC;AAOxG,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;AAEvE,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;;;;;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,yLAyDd,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
+ {"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,3 @@
1
+ export type { DividerLabelAlign, DividerOrientation, DividerProps, DividerThickness, } from "./Divider.js";
2
+ export { Divider } from "./Divider.js";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -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,3 @@
1
+ export type { PressableScaleAnimationConfig, PressableScaleProps, } from "./variants/PressableScale/index.js";
2
+ export { PressableScale } from "./variants/PressableScale/index.js";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -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,6 @@
1
1
  {
2
2
  "name": "react-native-terra-ui",
3
- "version": "0.10.1",
3
+ "version": "0.10.2",
4
4
  "description": "Themeable React Native UI components built on react-native-unistyles",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",
@@ -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
- <Pressable
235
+ <PressableScale
212
236
  ref={ref}
213
237
  onPress={blocked ? undefined : onPress}
214
- disabled={blocked}
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={(state) => [
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
- </Pressable>
248
+ </PressableScale>
230
249
  </ButtonContext.Provider>
231
250
  );
232
251
  });
@@ -1,4 +1,5 @@
1
1
  export type {
2
+ ButtonAnimation,
2
3
  ButtonIconProps,
3
4
  ButtonProps,
4
5
  ButtonRadius,
@@ -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
+ }));
@@ -0,0 +1,7 @@
1
+ export type {
2
+ DividerLabelAlign,
3
+ DividerOrientation,
4
+ DividerProps,
5
+ DividerThickness,
6
+ } from "./Divider";
7
+ export { Divider } from "./Divider";
@@ -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,5 @@
1
+ export type {
2
+ PressableScaleAnimationConfig,
3
+ PressableScaleProps,
4
+ } from "./variants/PressableScale";
5
+ export { PressableScale } from "./variants/PressableScale";
@@ -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: {} }));