react-native-terra-ui 0.13.7 → 0.13.9
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 +18 -0
- package/lib/module/components/header/parts/HeaderBar.js +3 -1
- package/lib/module/components/header/parts/HeaderBar.js.map +1 -1
- package/lib/module/components/header/parts/HeaderGradientOverlay.js +1 -2
- package/lib/module/components/header/parts/HeaderGradientOverlay.js.map +1 -1
- package/lib/module/components/header/parts/HeaderSurface.js +9 -4
- package/lib/module/components/header/parts/HeaderSurface.js.map +1 -1
- package/lib/module/components/header/variants/LargeTitleHeader/index.js +1 -0
- package/lib/module/components/header/variants/LargeTitleHeader/index.js.map +1 -1
- package/lib/module/components/header/variants/TitleHeader/index.js +1 -0
- package/lib/module/components/header/variants/TitleHeader/index.js.map +1 -1
- package/lib/module/components/input/hooks/use-focus-state.js +25 -0
- package/lib/module/components/input/hooks/use-focus-state.js.map +1 -0
- package/lib/module/components/input/parts/InputField.js +53 -31
- package/lib/module/components/input/parts/InputField.js.map +1 -1
- package/lib/module/components/input/variants/SearchInput/SearchCancelButton.js +93 -0
- package/lib/module/components/input/variants/SearchInput/SearchCancelButton.js.map +1 -0
- package/lib/module/components/input/variants/SearchInput/SearchClearButton.js +52 -0
- package/lib/module/components/input/variants/SearchInput/SearchClearButton.js.map +1 -0
- package/lib/module/components/input/variants/SearchInput/index.js +85 -30
- package/lib/module/components/input/variants/SearchInput/index.js.map +1 -1
- package/lib/module/components/input/variants/SearchInput/utils.js +9 -0
- package/lib/module/components/input/variants/SearchInput/utils.js.map +1 -0
- package/lib/module/components/screen/ScreenList.js +5 -1
- package/lib/module/components/screen/ScreenList.js.map +1 -1
- package/lib/module/components/screen/ScreenScrollView.js +5 -1
- package/lib/module/components/screen/ScreenScrollView.js.map +1 -1
- package/lib/module/theme/tokens/light.js +1 -1
- package/lib/typescript/src/components/header/parts/HeaderBar.d.ts +3 -1
- package/lib/typescript/src/components/header/parts/HeaderBar.d.ts.map +1 -1
- package/lib/typescript/src/components/header/parts/HeaderGradientOverlay.d.ts +3 -3
- package/lib/typescript/src/components/header/parts/HeaderGradientOverlay.d.ts.map +1 -1
- package/lib/typescript/src/components/header/parts/HeaderSurface.d.ts +12 -3
- package/lib/typescript/src/components/header/parts/HeaderSurface.d.ts.map +1 -1
- package/lib/typescript/src/components/header/variants/LargeTitleHeader/index.d.ts.map +1 -1
- package/lib/typescript/src/components/header/variants/TitleHeader/index.d.ts.map +1 -1
- package/lib/typescript/src/components/input/hooks/use-focus-state.d.ts +15 -0
- package/lib/typescript/src/components/input/hooks/use-focus-state.d.ts.map +1 -0
- package/lib/typescript/src/components/input/parts/InputField.d.ts +3 -1
- package/lib/typescript/src/components/input/parts/InputField.d.ts.map +1 -1
- package/lib/typescript/src/components/input/types.d.ts +11 -1
- package/lib/typescript/src/components/input/types.d.ts.map +1 -1
- package/lib/typescript/src/components/input/variants/SearchInput/SearchCancelButton.d.ts +19 -0
- package/lib/typescript/src/components/input/variants/SearchInput/SearchCancelButton.d.ts.map +1 -0
- package/lib/typescript/src/components/input/variants/SearchInput/SearchClearButton.d.ts +13 -0
- package/lib/typescript/src/components/input/variants/SearchInput/SearchClearButton.d.ts.map +1 -0
- package/lib/typescript/src/components/input/variants/SearchInput/index.d.ts +15 -1
- package/lib/typescript/src/components/input/variants/SearchInput/index.d.ts.map +1 -1
- package/lib/typescript/src/components/input/variants/SearchInput/utils.d.ts +4 -0
- package/lib/typescript/src/components/input/variants/SearchInput/utils.d.ts.map +1 -0
- package/lib/typescript/src/components/screen/ScreenList.d.ts.map +1 -1
- package/lib/typescript/src/components/screen/ScreenScrollView.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/header/parts/HeaderBar.tsx +4 -1
- package/src/components/header/parts/HeaderGradientOverlay.tsx +3 -4
- package/src/components/header/parts/HeaderSurface.tsx +14 -8
- package/src/components/header/variants/LargeTitleHeader/index.tsx +1 -0
- package/src/components/header/variants/TitleHeader/index.tsx +1 -0
- package/src/components/input/hooks/use-focus-state.ts +32 -0
- package/src/components/input/parts/InputField.tsx +45 -31
- package/src/components/input/types.ts +11 -1
- package/src/components/input/variants/SearchInput/SearchCancelButton.tsx +109 -0
- package/src/components/input/variants/SearchInput/SearchClearButton.tsx +58 -0
- package/src/components/input/variants/SearchInput/index.tsx +92 -24
- package/src/components/input/variants/SearchInput/utils.ts +4 -0
- package/src/components/screen/ScreenList.tsx +3 -0
- package/src/components/screen/ScreenScrollView.tsx +3 -0
- package/src/theme/tokens/light.ts +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ScreenList.d.ts","sourceRoot":"","sources":["../../../../../src/components/screen/ScreenList.tsx"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"ScreenList.d.ts","sourceRoot":"","sources":["../../../../../src/components/screen/ScreenList.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ScreenScrollView.d.ts","sourceRoot":"","sources":["../../../../../src/components/screen/ScreenScrollView.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA2C,KAAK,SAAS,EAAe,MAAM,OAAO,CAAC;AAC7F,OAAO,EAGL,KAAK,eAAe,EACpB,KAAK,SAAS,EAEd,KAAK,SAAS,EACf,MAAM,cAAc,CAAC;AAatB,OAAO,KAAK,EAAwB,qBAAqB,EAAE,MAAM,YAAS,CAAC;AAG3E,qFAAqF;AACrF,MAAM,WAAW,qBAAsB,SAAQ,IAAI,CAAC,eAAe,EAAE,YAAY,CAAC,EAAE,qBAAqB;IACvG,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,iEAAiE;IACjE,YAAY,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACpC,uFAAuF;IACvF,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,gBAAgB,
|
|
1
|
+
{"version":3,"file":"ScreenScrollView.d.ts","sourceRoot":"","sources":["../../../../../src/components/screen/ScreenScrollView.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA2C,KAAK,SAAS,EAAe,MAAM,OAAO,CAAC;AAC7F,OAAO,EAGL,KAAK,eAAe,EACpB,KAAK,SAAS,EAEd,KAAK,SAAS,EACf,MAAM,cAAc,CAAC;AAatB,OAAO,KAAK,EAAwB,qBAAqB,EAAE,MAAM,YAAS,CAAC;AAG3E,qFAAqF;AACrF,MAAM,WAAW,qBAAsB,SAAQ,IAAI,CAAC,eAAe,EAAE,YAAY,CAAC,EAAE,qBAAqB;IACvG,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,iEAAiE;IACjE,YAAY,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACpC,uFAAuF;IACvF,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,gBAAgB,8MA8F5B,CAAC"}
|
package/package.json
CHANGED
|
@@ -25,6 +25,8 @@ interface HeaderBarProps extends HeaderDismissProps {
|
|
|
25
25
|
titleAlignment: "center" | "left";
|
|
26
26
|
color: string;
|
|
27
27
|
surfaceStyle?: HeaderSurfaceProps["animatedStyle"];
|
|
28
|
+
/** An accessory sits under the bar, so the bar's surface stays solid. */
|
|
29
|
+
hasAccessory?: boolean;
|
|
28
30
|
titleStyle?: ComponentProps<typeof Animated.View>["style"];
|
|
29
31
|
}
|
|
30
32
|
|
|
@@ -39,6 +41,7 @@ export function HeaderBar({
|
|
|
39
41
|
titleAlignment,
|
|
40
42
|
color,
|
|
41
43
|
surfaceStyle,
|
|
44
|
+
hasAccessory = false,
|
|
42
45
|
titleStyle,
|
|
43
46
|
dismissAction = "none",
|
|
44
47
|
navigation,
|
|
@@ -75,7 +78,7 @@ export function HeaderBar({
|
|
|
75
78
|
*/
|
|
76
79
|
<ScrollToTopGuard>
|
|
77
80
|
<View style={[styles.bar, styles.windowInsets(windowInsets.left, windowInsets.right)]}>
|
|
78
|
-
<HeaderSurface color={color} animatedStyle={surfaceStyle} />
|
|
81
|
+
<HeaderSurface color={color} animatedStyle={surfaceStyle} hasAccessoryBelow={hasAccessory} />
|
|
79
82
|
<HeaderWindowInsets onInsetsChange={setWindowInsets} />
|
|
80
83
|
{hasLeading && (
|
|
81
84
|
<Toolbar onLayout={onLeadingLayout}>
|
|
@@ -10,9 +10,9 @@ import Svg, { Defs, Rect, Stop, LinearGradient as SvgLinearGradient } from "reac
|
|
|
10
10
|
export const HEADER_FADE_END_OPACITY = 0.9;
|
|
11
11
|
|
|
12
12
|
export interface HeaderGradientOverlayProps {
|
|
13
|
-
/** Fill color, ramped from opaque to
|
|
13
|
+
/** Fill color, ramped from opaque to `endOpacity`. */
|
|
14
14
|
color: string;
|
|
15
|
-
|
|
15
|
+
/** Opacity at the bottom edge. Defaults to {@link HEADER_FADE_END_OPACITY}; `1` is a solid fill. */
|
|
16
16
|
endOpacity?: number;
|
|
17
17
|
}
|
|
18
18
|
|
|
@@ -25,7 +25,6 @@ export interface HeaderGradientOverlayProps {
|
|
|
25
25
|
*/
|
|
26
26
|
export function HeaderGradientOverlay({
|
|
27
27
|
color,
|
|
28
|
-
startOpacity = 1,
|
|
29
28
|
endOpacity = HEADER_FADE_END_OPACITY,
|
|
30
29
|
}: HeaderGradientOverlayProps) {
|
|
31
30
|
const gradientId = useId();
|
|
@@ -34,7 +33,7 @@ export function HeaderGradientOverlay({
|
|
|
34
33
|
<Svg height="100%" width="100%">
|
|
35
34
|
<Defs>
|
|
36
35
|
<SvgLinearGradient id={gradientId} x1="0" y1="0" x2="0" y2="1">
|
|
37
|
-
<Stop offset={0} stopColor={color} stopOpacity={
|
|
36
|
+
<Stop offset={0} stopColor={color} stopOpacity={1} />
|
|
38
37
|
<Stop offset={1} stopColor={color} stopOpacity={endOpacity} />
|
|
39
38
|
</SvgLinearGradient>
|
|
40
39
|
</Defs>
|
|
@@ -10,24 +10,30 @@ export interface HeaderSurfaceProps {
|
|
|
10
10
|
color: string;
|
|
11
11
|
/** Opacity style for variants that fade the whole surface in as they collapse. */
|
|
12
12
|
animatedStyle?: HeaderOpacityStyle;
|
|
13
|
-
/**
|
|
13
|
+
/** This surface is an accessory's: it carries the fade, from solid to the end opacity. */
|
|
14
14
|
accessory?: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* An accessory sits under this bar. The bar then stays solid, since the
|
|
17
|
+
* header's bottom edge, where the fade belongs, is the accessory's.
|
|
18
|
+
*/
|
|
19
|
+
hasAccessoryBelow?: boolean;
|
|
15
20
|
}
|
|
16
21
|
|
|
17
22
|
/**
|
|
18
|
-
* Header background
|
|
23
|
+
* Header background. One fade per header, at its bottom edge: the bar's when it
|
|
24
|
+
* stands alone, the accessory's when there is one, with the bar solid above it.
|
|
25
|
+
* Content scrolling under a pinned accessory then meets a header as opaque as
|
|
26
|
+
* any other, rather than one that thinned twice, once at each part's edge, and
|
|
27
|
+
* let saturated rows show through around a search field.
|
|
19
28
|
*
|
|
20
29
|
* The ramp spans the surface itself: it is sized by the caller and stays inside
|
|
21
30
|
* those bounds, so a taller surface stretches the fade rather than adding to it.
|
|
22
31
|
*/
|
|
23
|
-
export function HeaderSurface({ color, animatedStyle, accessory }: HeaderSurfaceProps) {
|
|
32
|
+
export function HeaderSurface({ color, animatedStyle, accessory, hasAccessoryBelow }: HeaderSurfaceProps) {
|
|
33
|
+
const fades = accessory || !hasAccessoryBelow;
|
|
24
34
|
return (
|
|
25
35
|
<Animated.View style={[styles.surface, animatedStyle]} pointerEvents="none">
|
|
26
|
-
<HeaderGradientOverlay
|
|
27
|
-
color={color}
|
|
28
|
-
startOpacity={accessory ? HEADER_FADE_END_OPACITY : 1}
|
|
29
|
-
endOpacity={accessory ? 0.85 : HEADER_FADE_END_OPACITY}
|
|
30
|
-
/>
|
|
36
|
+
<HeaderGradientOverlay color={color} endOpacity={fades ? HEADER_FADE_END_OPACITY : 1} />
|
|
31
37
|
</Animated.View>
|
|
32
38
|
);
|
|
33
39
|
}
|
|
@@ -92,6 +92,7 @@ export function LargeTitleHeader({
|
|
|
92
92
|
titleAlignment={titleAlignment}
|
|
93
93
|
color={color}
|
|
94
94
|
surfaceStyle={layout.surfaceStyle}
|
|
95
|
+
hasAccessory={accessory != null}
|
|
95
96
|
titleStyle={layout.compactTitleStyle}
|
|
96
97
|
leading={leadingActions !== undefined ? leadingActions : LeftToolbar}
|
|
97
98
|
trailing={trailingActions !== undefined ? trailingActions : RightToolbar}
|
|
@@ -93,6 +93,7 @@ export function TitleHeader({
|
|
|
93
93
|
subtitle={subtitle}
|
|
94
94
|
titleAlignment={titleAlignment}
|
|
95
95
|
color={color}
|
|
96
|
+
hasAccessory={accessory != null}
|
|
96
97
|
leading={leadingActions !== undefined ? leadingActions : LeftToolbar}
|
|
97
98
|
trailing={trailingActions !== undefined ? trailingActions : RightToolbar}
|
|
98
99
|
/>
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { useCallback, useState } from "react";
|
|
2
|
+
import type { TextInputProps } from "react-native";
|
|
3
|
+
|
|
4
|
+
type FocusHandler = NonNullable<TextInputProps["onFocus"]>;
|
|
5
|
+
type BlurHandler = NonNullable<TextInputProps["onBlur"]>;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Track whether a `TextInput` is focused while still forwarding the caller's
|
|
9
|
+
* own `onFocus` / `onBlur`. Shared by the field (for its focus ring) and by
|
|
10
|
+
* variants that show extra controls while focused.
|
|
11
|
+
*/
|
|
12
|
+
export function useFocusState(onFocus?: FocusHandler, onBlur?: BlurHandler) {
|
|
13
|
+
const [isFocused, setIsFocused] = useState(false);
|
|
14
|
+
|
|
15
|
+
const handleFocus = useCallback<FocusHandler>(
|
|
16
|
+
(event) => {
|
|
17
|
+
setIsFocused(true);
|
|
18
|
+
onFocus?.(event);
|
|
19
|
+
},
|
|
20
|
+
[onFocus]
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
const handleBlur = useCallback<BlurHandler>(
|
|
24
|
+
(event) => {
|
|
25
|
+
setIsFocused(false);
|
|
26
|
+
onBlur?.(event);
|
|
27
|
+
},
|
|
28
|
+
[onBlur]
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
return { isFocused, handleFocus, handleBlur };
|
|
32
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type ComponentRef, forwardRef
|
|
1
|
+
import { type ComponentRef, forwardRef } from "react";
|
|
2
2
|
import { TextInput, View } from "react-native";
|
|
3
3
|
|
|
4
4
|
import { StyleSheet, useUnistyles } from "react-native-unistyles";
|
|
@@ -6,8 +6,12 @@ import { StyleSheet, useUnistyles } from "react-native-unistyles";
|
|
|
6
6
|
import type { ColorToken, RadiusKey } from "#theme/types";
|
|
7
7
|
import { resolveThemeColor } from "#utils/resolve-theme-color";
|
|
8
8
|
import { FONT_WEIGHT_VALUE, SYSTEM_FONT } from "#utils/typography";
|
|
9
|
+
import { useFocusState } from "../hooks/use-focus-state";
|
|
9
10
|
import type { InputBaseProps, InputSize } from "../types";
|
|
10
11
|
|
|
12
|
+
/** Container height per size, in dp. Sibling controls sized to match read from here. */
|
|
13
|
+
export const FIELD_HEIGHT: Record<InputSize, number> = { sm: 36, md: 44, lg: 52 };
|
|
14
|
+
|
|
11
15
|
/** Typographic role of the text, per size. */
|
|
12
16
|
const TEXT_VARIANT: Record<InputSize, "subheadline" | "callout" | "body"> = {
|
|
13
17
|
sm: "subheadline",
|
|
@@ -25,6 +29,9 @@ export const InputField = forwardRef<ComponentRef<typeof TextInput>, InputBasePr
|
|
|
25
29
|
size = "md",
|
|
26
30
|
isDisabled = false,
|
|
27
31
|
isInvalid = false,
|
|
32
|
+
focusBorderColor,
|
|
33
|
+
focusBorderWidth,
|
|
34
|
+
hasFocusGlow = false,
|
|
28
35
|
leading,
|
|
29
36
|
trailing,
|
|
30
37
|
background = "surface.sunken",
|
|
@@ -36,32 +43,24 @@ export const InputField = forwardRef<ComponentRef<typeof TextInput>, InputBasePr
|
|
|
36
43
|
},
|
|
37
44
|
ref
|
|
38
45
|
) {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
// as a prop rather than as a style.
|
|
42
|
-
const [isFocused, setIsFocused] = useState(false);
|
|
43
|
-
const { theme } = useUnistyles();
|
|
44
|
-
|
|
45
|
-
const handleFocus = useCallback<NonNullable<InputBaseProps["onFocus"]>>(
|
|
46
|
-
(event) => {
|
|
47
|
-
setIsFocused(true);
|
|
48
|
-
onFocus?.(event);
|
|
49
|
-
},
|
|
50
|
-
[onFocus]
|
|
51
|
-
);
|
|
46
|
+
const { isFocused, handleFocus, handleBlur } = useFocusState(onFocus, onBlur);
|
|
47
|
+
const showsFocus = isFocused && !isDisabled;
|
|
52
48
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
onBlur?.(event);
|
|
57
|
-
},
|
|
58
|
-
[onBlur]
|
|
59
|
-
);
|
|
49
|
+
// The placeholder colour has to leave the stylesheet because `TextInput` takes
|
|
50
|
+
// it as a prop rather than as a style.
|
|
51
|
+
const { theme } = useUnistyles();
|
|
60
52
|
|
|
61
|
-
styles.useVariants({ size, disabled: isDisabled, invalid: isInvalid
|
|
53
|
+
styles.useVariants({ size, disabled: isDisabled, invalid: isInvalid });
|
|
62
54
|
|
|
63
55
|
return (
|
|
64
|
-
<View
|
|
56
|
+
<View
|
|
57
|
+
style={[
|
|
58
|
+
styles.container,
|
|
59
|
+
styles.fill(background, radius),
|
|
60
|
+
showsFocus && styles.focus(focusBorderColor, focusBorderWidth, hasFocusGlow, isInvalid),
|
|
61
|
+
style,
|
|
62
|
+
]}
|
|
63
|
+
>
|
|
65
64
|
{leading}
|
|
66
65
|
<TextInput
|
|
67
66
|
ref={ref}
|
|
@@ -97,13 +96,9 @@ const styles = StyleSheet.create((theme) => {
|
|
|
97
96
|
borderColor: theme.color["border.subtle"],
|
|
98
97
|
variants: {
|
|
99
98
|
size: {
|
|
100
|
-
sm: { height:
|
|
101
|
-
md: { height:
|
|
102
|
-
lg: { height:
|
|
103
|
-
},
|
|
104
|
-
focused: {
|
|
105
|
-
true: { borderColor: theme.color["accent.border"] },
|
|
106
|
-
false: {},
|
|
99
|
+
sm: { height: FIELD_HEIGHT.sm, paddingHorizontal: theme.spacing["3"], gap: 6 },
|
|
100
|
+
md: { height: FIELD_HEIGHT.md, paddingHorizontal: theme.spacing["3"], gap: 6 },
|
|
101
|
+
lg: { height: FIELD_HEIGHT.lg, paddingHorizontal: theme.spacing["4"], gap: 6 },
|
|
107
102
|
},
|
|
108
103
|
invalid: {
|
|
109
104
|
true: { borderColor: theme.color["danger.text"] },
|
|
@@ -115,6 +110,26 @@ const styles = StyleSheet.create((theme) => {
|
|
|
115
110
|
},
|
|
116
111
|
},
|
|
117
112
|
},
|
|
113
|
+
// Only the keys that apply are set, so an unset option leaves the resting
|
|
114
|
+
// border alone rather than overriding it with `undefined`. An invalid field
|
|
115
|
+
// keeps its danger border and skips the glow, so the error stays the loudest
|
|
116
|
+
// signal; only the width still follows focus.
|
|
117
|
+
focus: (
|
|
118
|
+
color: ColorToken | undefined,
|
|
119
|
+
width: number | undefined,
|
|
120
|
+
hasGlow: boolean,
|
|
121
|
+
isInvalid: boolean
|
|
122
|
+
) => {
|
|
123
|
+
const focusColor = resolveThemeColor(color ?? "border.default", theme);
|
|
124
|
+
return {
|
|
125
|
+
...(width !== undefined && { borderWidth: width }),
|
|
126
|
+
...(color && !isInvalid && { borderColor: focusColor }),
|
|
127
|
+
...(hasGlow &&
|
|
128
|
+
!isInvalid && {
|
|
129
|
+
boxShadow: [{ offsetX: 0, offsetY: 0, blurRadius: 4, spreadDistance: 1, color: focusColor }],
|
|
130
|
+
}),
|
|
131
|
+
};
|
|
132
|
+
},
|
|
118
133
|
// `background` is an open `ColorToken` and `radius` an eight-step scale, so
|
|
119
134
|
// both resolve in a dynamic function rather than enumerating as variants.
|
|
120
135
|
fill: (background: ColorToken, radius: RadiusKey) => ({
|
|
@@ -137,7 +152,6 @@ const styles = StyleSheet.create((theme) => {
|
|
|
137
152
|
md: { fontSize: theme.typography.variants[TEXT_VARIANT.md].fontSize },
|
|
138
153
|
lg: { fontSize: theme.typography.variants[TEXT_VARIANT.lg].fontSize },
|
|
139
154
|
},
|
|
140
|
-
focused: { true: {}, false: {} },
|
|
141
155
|
invalid: { true: {}, false: {} },
|
|
142
156
|
disabled: { true: {}, false: {} },
|
|
143
157
|
},
|
|
@@ -24,8 +24,18 @@ export interface InputBaseProps extends Omit<TextInputProps, "style" | "editable
|
|
|
24
24
|
trailing?: ReactNode;
|
|
25
25
|
/** Fill token. Defaults to `'surface.sunken'`. */
|
|
26
26
|
background?: ColorToken;
|
|
27
|
-
/** Corner radius. Defaults to `'
|
|
27
|
+
/** Corner radius. Defaults to `'lg'`; `Input.Search` uses `'full'`. */
|
|
28
28
|
radius?: RadiusKey;
|
|
29
|
+
/** Border colour while focused. Defaults to `undefined` — the resting border stays. */
|
|
30
|
+
focusBorderColor?: ColorToken;
|
|
31
|
+
/** Border width while focused, in dp. Defaults to `undefined` — the resting hairline stays. */
|
|
32
|
+
focusBorderWidth?: number;
|
|
33
|
+
/**
|
|
34
|
+
* Surround the field with a soft glow while focused, tinted by
|
|
35
|
+
* `focusBorderColor` or `border.default` when that is unset. Defaults to
|
|
36
|
+
* `false`; `Input.Search` turns it on.
|
|
37
|
+
*/
|
|
38
|
+
hasFocusGlow?: boolean;
|
|
29
39
|
/** Merged over the container's own style. */
|
|
30
40
|
style?: StyleProp<ViewStyle>;
|
|
31
41
|
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { useEffect } from "react";
|
|
2
|
+
|
|
3
|
+
import Animated, {
|
|
4
|
+
Easing,
|
|
5
|
+
interpolate,
|
|
6
|
+
useAnimatedStyle,
|
|
7
|
+
useSharedValue,
|
|
8
|
+
withTiming,
|
|
9
|
+
} from "react-native-reanimated";
|
|
10
|
+
import { StyleSheet, useUnistyles } from "react-native-unistyles";
|
|
11
|
+
|
|
12
|
+
import type { ColorToken } from "#theme/types";
|
|
13
|
+
import { resolveThemeColor } from "#utils/resolve-theme-color";
|
|
14
|
+
import { Icon } from "../../../icon";
|
|
15
|
+
import { PressableOpacity } from "../../../pressable";
|
|
16
|
+
import { FIELD_HEIGHT } from "../../parts/InputField";
|
|
17
|
+
import type { InputSize } from "../../types";
|
|
18
|
+
import { ICON_SIZE } from "./utils";
|
|
19
|
+
|
|
20
|
+
/** How long the button takes to slide in and the field to make room, in ms. */
|
|
21
|
+
const TRANSITION_MS = 250;
|
|
22
|
+
|
|
23
|
+
/** Scale the button grows from, so it pops in rather than only fading. */
|
|
24
|
+
const START_SCALE = 0.6;
|
|
25
|
+
|
|
26
|
+
/** The x runs a touch larger than the field's glyphs; it has a circle to itself. */
|
|
27
|
+
const GLYPH_EXTRA = 2;
|
|
28
|
+
|
|
29
|
+
interface SearchCancelButtonProps {
|
|
30
|
+
/** Slides the button in when `true` and out when `false`. */
|
|
31
|
+
isVisible: boolean;
|
|
32
|
+
size: InputSize;
|
|
33
|
+
/** Fill token, matched to the field it sits beside. */
|
|
34
|
+
background: ColorToken;
|
|
35
|
+
accessibilityLabel: string;
|
|
36
|
+
onPress: () => void;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* A round button the height of the field, in a slot that opens and closes
|
|
41
|
+
* beside it. The slot stays mounted so it can animate out; while collapsed it
|
|
42
|
+
* is hidden from touch and from screen readers.
|
|
43
|
+
*/
|
|
44
|
+
export function SearchCancelButton({
|
|
45
|
+
isVisible,
|
|
46
|
+
size,
|
|
47
|
+
background,
|
|
48
|
+
accessibilityLabel,
|
|
49
|
+
onPress,
|
|
50
|
+
}: SearchCancelButtonProps) {
|
|
51
|
+
// One progress value drives the slot's width, so the field (flex: 1) gives
|
|
52
|
+
// up its room frame by frame instead of jumping when the button appears.
|
|
53
|
+
const { theme } = useUnistyles();
|
|
54
|
+
const progress = useSharedValue(0);
|
|
55
|
+
const diameter = FIELD_HEIGHT[size];
|
|
56
|
+
// The gap lives inside the slot, so it opens with the button and the field
|
|
57
|
+
// sits flush to the edge when the button is gone.
|
|
58
|
+
const slotWidth = diameter + theme.spacing["2"];
|
|
59
|
+
|
|
60
|
+
useEffect(() => {
|
|
61
|
+
progress.value = withTiming(isVisible ? 1 : 0, {
|
|
62
|
+
duration: TRANSITION_MS,
|
|
63
|
+
easing: Easing.bezier(0.25, 0.1, 0.25, 1),
|
|
64
|
+
});
|
|
65
|
+
}, [isVisible, progress]);
|
|
66
|
+
|
|
67
|
+
const slotStyle = useAnimatedStyle(() => ({
|
|
68
|
+
width: progress.value * slotWidth,
|
|
69
|
+
opacity: progress.value,
|
|
70
|
+
transform: [{ scale: interpolate(progress.value, [0, 1], [START_SCALE, 1]) }],
|
|
71
|
+
}));
|
|
72
|
+
|
|
73
|
+
return (
|
|
74
|
+
<Animated.View
|
|
75
|
+
style={[styles.slot(isVisible), slotStyle]}
|
|
76
|
+
accessibilityElementsHidden={!isVisible}
|
|
77
|
+
importantForAccessibility={isVisible ? "auto" : "no-hide-descendants"}
|
|
78
|
+
>
|
|
79
|
+
<PressableOpacity
|
|
80
|
+
accessibilityLabel={accessibilityLabel}
|
|
81
|
+
accessibilityRole="button"
|
|
82
|
+
onPress={onPress}
|
|
83
|
+
style={styles.button(diameter, background)}
|
|
84
|
+
>
|
|
85
|
+
<Icon name="terra.x" size={ICON_SIZE[size] + GLYPH_EXTRA} color="text.primary" />
|
|
86
|
+
</PressableOpacity>
|
|
87
|
+
</Animated.View>
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const styles = StyleSheet.create((theme) => ({
|
|
92
|
+
slot: (isVisible: boolean) => ({
|
|
93
|
+
flexDirection: "row",
|
|
94
|
+
justifyContent: "flex-end",
|
|
95
|
+
overflow: "hidden",
|
|
96
|
+
pointerEvents: isVisible ? "auto" : "none",
|
|
97
|
+
}),
|
|
98
|
+
// A circle the height of the field, filled and edged to match it.
|
|
99
|
+
button: (diameter: number, background: ColorToken) => ({
|
|
100
|
+
width: diameter,
|
|
101
|
+
height: diameter,
|
|
102
|
+
borderRadius: diameter / 2,
|
|
103
|
+
alignItems: "center",
|
|
104
|
+
justifyContent: "center",
|
|
105
|
+
backgroundColor: resolveThemeColor(background, theme),
|
|
106
|
+
borderWidth: StyleSheet.hairlineWidth,
|
|
107
|
+
borderColor: theme.color["border.subtle"],
|
|
108
|
+
}),
|
|
109
|
+
}));
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { Pressable } from "react-native";
|
|
2
|
+
|
|
3
|
+
import { StyleSheet } from "react-native-unistyles";
|
|
4
|
+
|
|
5
|
+
import { Icon } from "../../../icon";
|
|
6
|
+
import type { InputSize } from "../../types";
|
|
7
|
+
import { ICON_SIZE } from "./utils";
|
|
8
|
+
|
|
9
|
+
/** Touch expansion around the button, in dp — it is smaller than a cell. */
|
|
10
|
+
const HIT_SLOP = 8;
|
|
11
|
+
|
|
12
|
+
/** The x as a share of its disc, so it reads inside the circle. */
|
|
13
|
+
const GLYPH_RATIO = 0.6;
|
|
14
|
+
|
|
15
|
+
/** Heavier than the icon default so the small glyph stays legible on the disc. */
|
|
16
|
+
const GLYPH_STROKE_WIDTH = 3.3;
|
|
17
|
+
|
|
18
|
+
interface SearchClearButtonProps {
|
|
19
|
+
size: InputSize;
|
|
20
|
+
accessibilityLabel: string;
|
|
21
|
+
onPress: () => void;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* A solid disc with an x, like iOS's `xmark.circle.fill`. Sized to the field's
|
|
26
|
+
* glyphs so it sits in the trailing slot without changing the row height.
|
|
27
|
+
*/
|
|
28
|
+
export function SearchClearButton({ size, accessibilityLabel, onPress }: SearchClearButtonProps) {
|
|
29
|
+
const diameter = ICON_SIZE[size];
|
|
30
|
+
|
|
31
|
+
return (
|
|
32
|
+
<Pressable
|
|
33
|
+
accessibilityLabel={accessibilityLabel}
|
|
34
|
+
accessibilityRole="button"
|
|
35
|
+
hitSlop={HIT_SLOP}
|
|
36
|
+
onPress={onPress}
|
|
37
|
+
style={styles.disc(diameter)}
|
|
38
|
+
>
|
|
39
|
+
<Icon
|
|
40
|
+
name="terra.x"
|
|
41
|
+
size={Math.round(diameter * GLYPH_RATIO)}
|
|
42
|
+
color="text.inverse"
|
|
43
|
+
strokeWidth={GLYPH_STROKE_WIDTH}
|
|
44
|
+
/>
|
|
45
|
+
</Pressable>
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const styles = StyleSheet.create((theme) => ({
|
|
50
|
+
disc: (diameter: number) => ({
|
|
51
|
+
width: diameter,
|
|
52
|
+
height: diameter,
|
|
53
|
+
borderRadius: diameter / 2,
|
|
54
|
+
alignItems: "center",
|
|
55
|
+
justifyContent: "center",
|
|
56
|
+
backgroundColor: theme.color["text.tertiary"],
|
|
57
|
+
}),
|
|
58
|
+
}));
|