mirror of
https://github.com/minibits-cash/minibits_wallet.git
synced 2026-08-10 16:43:19 +00:00
198 lines
5.4 KiB
TypeScript
198 lines
5.4 KiB
TypeScript
import React, { ComponentType } from "react"
|
|
import {
|
|
Pressable,
|
|
PressableProps,
|
|
PressableStateCallbackType,
|
|
StyleProp,
|
|
TextStyle,
|
|
ViewStyle,
|
|
} from "react-native"
|
|
import {moderateScale, scale, verticalScale} from '@gocodingnow/rn-size-matters'
|
|
import { colors, spacing, typography, useThemeColor } from "../theme"
|
|
import { Text, TextProps } from "./Text"
|
|
|
|
type Presets = keyof typeof $viewPresets
|
|
|
|
export interface ButtonAccessoryProps {
|
|
style: StyleProp<any>
|
|
pressableState: PressableStateCallbackType
|
|
}
|
|
|
|
export interface ButtonProps extends PressableProps {
|
|
/**
|
|
* Text which is looked up via i18n.
|
|
*/
|
|
tx?: TextProps["tx"]
|
|
/**
|
|
* The text to display if not using `tx` or nested components.
|
|
*/
|
|
text?: TextProps["text"]
|
|
/**
|
|
* Optional options to pass to i18n. Useful for interpolation
|
|
* as well as explicitly setting locale or translation fallbacks.
|
|
*/
|
|
txOptions?: TextProps["txOptions"]
|
|
/**
|
|
* An optional style override useful for padding & margin.
|
|
*/
|
|
style?: StyleProp<ViewStyle>
|
|
/**
|
|
* An optional style override for the "pressed" state.
|
|
*/
|
|
pressedStyle?: StyleProp<ViewStyle>
|
|
/**
|
|
* An optional style override for the button text.
|
|
*/
|
|
textStyle?: StyleProp<TextStyle>
|
|
/**
|
|
* An optional style override for the button text when in the "pressed" state.
|
|
*/
|
|
pressedTextStyle?: StyleProp<TextStyle>
|
|
/**
|
|
* One of the different types of button presets.
|
|
*/
|
|
preset?: Presets
|
|
/**
|
|
* An optional component to render on the right side of the text.
|
|
* Example: `RightAccessory={(props) => <View {...props} />}`
|
|
*/
|
|
RightAccessory?: ComponentType<ButtonAccessoryProps>
|
|
/**
|
|
* An optional component to render on the left side of the text.
|
|
* Example: `LeftAccessory={(props) => <View {...props} />}`
|
|
*/
|
|
LeftAccessory?: ComponentType<ButtonAccessoryProps>
|
|
/**
|
|
* Children components.
|
|
*/
|
|
children?: React.ReactNode
|
|
}
|
|
|
|
/**
|
|
* A component that allows users to take actions and make choices.
|
|
* Wraps the Text component with a Pressable component.
|
|
*
|
|
* - [Documentation and Examples](https://github.com/infinitered/ignite/blob/master/docs/Components-Button.md)
|
|
*/
|
|
export function Button(props: ButtonProps) {
|
|
const {
|
|
tx,
|
|
text,
|
|
txOptions,
|
|
preset = "default",
|
|
style: $viewStyleOverride,
|
|
pressedStyle: $pressedViewStyleOverride,
|
|
textStyle: $textStyleOverride,
|
|
pressedTextStyle: $pressedTextStyleOverride,
|
|
children,
|
|
RightAccessory,
|
|
LeftAccessory,
|
|
...rest
|
|
} = props
|
|
|
|
const textColor = useThemeColor("text")
|
|
const defaultBg = useThemeColor("button")
|
|
const defaultBgPressed = useThemeColor("buttonPressed")
|
|
const secondaryBg = useThemeColor("buttonSecondary")
|
|
const secondaryBgPressed = useThemeColor("buttonSecondaryPressed")
|
|
const tertiaryBg = useThemeColor("buttonTertiary")
|
|
const tertiaryBgPressed = useThemeColor("buttonTertiaryPressed")
|
|
|
|
const $pressedViewPresets: Record<Presets, StyleProp<ViewStyle>> = {
|
|
default: { backgroundColor: defaultBgPressed },
|
|
secondary: { backgroundColor: secondaryBgPressed },
|
|
tertiary: { backgroundColor: tertiaryBgPressed },
|
|
}
|
|
|
|
function $viewStyle({ pressed }) {
|
|
return [
|
|
$viewPresets[preset],
|
|
{ backgroundColor: defaultBg },
|
|
preset === "secondary" && { backgroundColor: secondaryBg },
|
|
preset === "tertiary" && { backgroundColor: tertiaryBg },
|
|
!!LeftAccessory && (text || tx) && {paddingLeft: spacing.tiny},
|
|
$viewStyleOverride,
|
|
!!pressed && [$pressedViewPresets[preset], $pressedViewStyleOverride],
|
|
]
|
|
}
|
|
function $textStyle({ pressed }) {
|
|
return [
|
|
$textPresets[preset],
|
|
{ color: textColor },
|
|
preset === "default" && { color: 'white' },
|
|
$textStyleOverride,
|
|
!!pressed && [$pressedTextPresets[preset], $pressedTextStyleOverride],
|
|
]
|
|
}
|
|
|
|
return (
|
|
<Pressable style={$viewStyle} accessibilityRole="button" {...rest}>
|
|
{(state) => (
|
|
<>
|
|
{!!LeftAccessory && <LeftAccessory style={$leftAccessoryStyle} pressableState={state} />}
|
|
|
|
<Text tx={tx} text={text} txOptions={txOptions} style={$textStyle(state)}>
|
|
{children}
|
|
</Text>
|
|
|
|
{!!RightAccessory && (
|
|
<RightAccessory style={$rightAccessoryStyle} pressableState={state} />
|
|
)}
|
|
</>
|
|
)}
|
|
</Pressable>
|
|
)
|
|
}
|
|
|
|
|
|
const $baseViewStyle: ViewStyle = {
|
|
minHeight: verticalScale(50),
|
|
borderRadius: spacing.extraSmall,
|
|
justifyContent: "center",
|
|
alignItems: "center",
|
|
flexDirection: "row",
|
|
paddingVertical: spacing.small,
|
|
paddingLeft: spacing.small,
|
|
paddingRight: spacing.small,
|
|
overflow: "hidden",
|
|
}
|
|
|
|
const $baseTextStyle: TextStyle = {
|
|
fontSize: verticalScale(16),
|
|
lineHeight: verticalScale(20),
|
|
fontFamily: typography.primary?.light,
|
|
textAlign: "center",
|
|
flexShrink: 1,
|
|
flexGrow: 0,
|
|
zIndex: 2,
|
|
}
|
|
|
|
const $rightAccessoryStyle: ViewStyle = { zIndex: 1 }
|
|
const $leftAccessoryStyle: ViewStyle = { zIndex: 1 }
|
|
|
|
const $viewPresets = {
|
|
default: [
|
|
$baseViewStyle,
|
|
] as StyleProp<ViewStyle>,
|
|
|
|
secondary: [
|
|
$baseViewStyle,
|
|
] as StyleProp<ViewStyle>,
|
|
|
|
tertiary: [
|
|
$baseViewStyle,
|
|
] as StyleProp<ViewStyle>,
|
|
}
|
|
|
|
const $textPresets: Record<Presets, StyleProp<TextStyle>> = {
|
|
default: $baseTextStyle,
|
|
secondary: $baseTextStyle,
|
|
tertiary: $baseTextStyle,
|
|
}
|
|
|
|
const $pressedTextPresets: Record<Presets, StyleProp<TextStyle>> = {
|
|
default: { opacity: 0.9 },
|
|
secondary: { opacity: 0.9 },
|
|
tertiary: { opacity: 0.9 },
|
|
}
|