@onlynative/components 0.1.0 → 0.1.1-alpha.1
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/dist/appbar/index.js +133 -62
- package/dist/button/index.js +125 -33
- package/dist/card/index.js +88 -20
- package/dist/checkbox/index.js +88 -17
- package/dist/chip/index.js +122 -30
- package/dist/icon-button/index.js +107 -36
- package/dist/index.js +335 -251
- package/dist/list/index.js +71 -24
- package/dist/radio/index.js +43 -14
- package/dist/switch/index.js +90 -19
- package/dist/text-field/index.js +82 -26
- package/package.json +4 -23
- package/src/appbar/AppBar.tsx +0 -302
- package/src/appbar/index.ts +0 -2
- package/src/appbar/styles.ts +0 -92
- package/src/appbar/types.ts +0 -67
- package/src/button/Button.tsx +0 -133
- package/src/button/index.ts +0 -2
- package/src/button/styles.ts +0 -287
- package/src/button/types.ts +0 -42
- package/src/card/Card.tsx +0 -69
- package/src/card/index.ts +0 -2
- package/src/card/styles.ts +0 -150
- package/src/card/types.ts +0 -27
- package/src/checkbox/Checkbox.tsx +0 -113
- package/src/checkbox/index.ts +0 -2
- package/src/checkbox/styles.ts +0 -155
- package/src/checkbox/types.ts +0 -20
- package/src/chip/Chip.tsx +0 -188
- package/src/chip/index.ts +0 -2
- package/src/chip/styles.ts +0 -239
- package/src/chip/types.ts +0 -58
- package/src/icon-button/IconButton.tsx +0 -362
- package/src/icon-button/index.ts +0 -6
- package/src/icon-button/styles.ts +0 -259
- package/src/icon-button/types.ts +0 -55
- package/src/index.ts +0 -54
- package/src/keyboard-avoiding-wrapper/KeyboardAvoidingWrapper.tsx +0 -69
- package/src/keyboard-avoiding-wrapper/index.ts +0 -2
- package/src/keyboard-avoiding-wrapper/styles.ts +0 -10
- package/src/keyboard-avoiding-wrapper/types.ts +0 -37
- package/src/layout/Box.tsx +0 -99
- package/src/layout/Column.tsx +0 -16
- package/src/layout/Grid.tsx +0 -49
- package/src/layout/Layout.tsx +0 -81
- package/src/layout/Row.tsx +0 -22
- package/src/layout/index.ts +0 -13
- package/src/layout/resolveSpacing.ts +0 -11
- package/src/layout/types.ts +0 -82
- package/src/list/List.tsx +0 -17
- package/src/list/ListDivider.tsx +0 -20
- package/src/list/ListItem.tsx +0 -128
- package/src/list/index.ts +0 -9
- package/src/list/styles.ts +0 -132
- package/src/list/types.ts +0 -54
- package/src/radio/Radio.tsx +0 -103
- package/src/radio/index.ts +0 -2
- package/src/radio/styles.ts +0 -139
- package/src/radio/types.ts +0 -20
- package/src/switch/Switch.tsx +0 -121
- package/src/switch/index.ts +0 -2
- package/src/switch/styles.ts +0 -172
- package/src/switch/types.ts +0 -32
- package/src/text-field/TextField.tsx +0 -301
- package/src/text-field/index.ts +0 -2
- package/src/text-field/styles.ts +0 -239
- package/src/text-field/types.ts +0 -49
- package/src/typography/Typography.tsx +0 -79
- package/src/typography/index.ts +0 -3
- package/src/typography/types.ts +0 -17
package/src/layout/Layout.tsx
DELETED
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
import { useMemo } from 'react'
|
|
2
|
-
import type { PropsWithChildren } from 'react'
|
|
3
|
-
import type { StyleProp, ViewStyle } from 'react-native'
|
|
4
|
-
import { StyleSheet } from 'react-native'
|
|
5
|
-
import { SafeAreaView } from 'react-native-safe-area-context'
|
|
6
|
-
import type { Edge } from 'react-native-safe-area-context'
|
|
7
|
-
import { useTheme } from '@onlynative/core'
|
|
8
|
-
|
|
9
|
-
export interface LayoutProps extends PropsWithChildren {
|
|
10
|
-
/**
|
|
11
|
-
* When `true`, removes all safe area insets for full-screen layout.
|
|
12
|
-
* @default false
|
|
13
|
-
*/
|
|
14
|
-
immersive?: boolean
|
|
15
|
-
/** Explicit set of safe-area edges to apply. Overrides `immersive` when provided. */
|
|
16
|
-
edges?: Edge[]
|
|
17
|
-
/** Additional styles applied to the SafeAreaView container. */
|
|
18
|
-
style?: StyleProp<ViewStyle>
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const defaultEdges: Edge[] = ['bottom']
|
|
22
|
-
|
|
23
|
-
function resolveEdges(immersive?: boolean, edges?: Edge[]): Edge[] {
|
|
24
|
-
if (edges) {
|
|
25
|
-
return edges
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
if (immersive) {
|
|
29
|
-
return []
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
return defaultEdges
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const styles = StyleSheet.create({
|
|
36
|
-
root: {
|
|
37
|
-
flex: 1,
|
|
38
|
-
},
|
|
39
|
-
})
|
|
40
|
-
|
|
41
|
-
function removeBackgroundColor(style?: StyleProp<ViewStyle>) {
|
|
42
|
-
if (!style) {
|
|
43
|
-
return undefined
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
const flattenedStyle = StyleSheet.flatten(style)
|
|
47
|
-
|
|
48
|
-
if (!flattenedStyle || flattenedStyle.backgroundColor === undefined) {
|
|
49
|
-
return style
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const styleWithoutBackground = { ...flattenedStyle }
|
|
53
|
-
delete styleWithoutBackground.backgroundColor
|
|
54
|
-
|
|
55
|
-
return styleWithoutBackground
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export function Layout({ immersive, edges, children, style }: LayoutProps) {
|
|
59
|
-
const theme = useTheme()
|
|
60
|
-
const themeBackgroundStyle = useMemo(
|
|
61
|
-
() => ({ backgroundColor: theme.colors.background }),
|
|
62
|
-
[theme.colors.background],
|
|
63
|
-
)
|
|
64
|
-
const styleWithoutBackground = useMemo(
|
|
65
|
-
() => removeBackgroundColor(style),
|
|
66
|
-
[style],
|
|
67
|
-
)
|
|
68
|
-
const safeAreaEdges = useMemo(
|
|
69
|
-
() => resolveEdges(immersive, edges),
|
|
70
|
-
[immersive, edges],
|
|
71
|
-
)
|
|
72
|
-
|
|
73
|
-
return (
|
|
74
|
-
<SafeAreaView
|
|
75
|
-
style={[styles.root, themeBackgroundStyle, styleWithoutBackground]}
|
|
76
|
-
edges={safeAreaEdges}
|
|
77
|
-
>
|
|
78
|
-
{children}
|
|
79
|
-
</SafeAreaView>
|
|
80
|
-
)
|
|
81
|
-
}
|
package/src/layout/Row.tsx
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { useMemo } from 'react'
|
|
2
|
-
import type { ViewStyle } from 'react-native'
|
|
3
|
-
|
|
4
|
-
import { Box } from './Box'
|
|
5
|
-
import type { RowProps } from './types'
|
|
6
|
-
|
|
7
|
-
export function Row({
|
|
8
|
-
wrap = false,
|
|
9
|
-
inverted = false,
|
|
10
|
-
style,
|
|
11
|
-
...boxProps
|
|
12
|
-
}: RowProps) {
|
|
13
|
-
const directionStyle = useMemo<ViewStyle>(
|
|
14
|
-
() => ({
|
|
15
|
-
flexDirection: inverted ? 'row-reverse' : 'row',
|
|
16
|
-
...(wrap && { flexWrap: 'wrap' }),
|
|
17
|
-
}),
|
|
18
|
-
[wrap, inverted],
|
|
19
|
-
)
|
|
20
|
-
|
|
21
|
-
return <Box {...boxProps} style={[directionStyle, style]} />
|
|
22
|
-
}
|
package/src/layout/index.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
export { Layout } from './Layout'
|
|
2
|
-
export type { LayoutProps } from './Layout'
|
|
3
|
-
export { Box } from './Box'
|
|
4
|
-
export { Column } from './Column'
|
|
5
|
-
export { Grid } from './Grid'
|
|
6
|
-
export { Row } from './Row'
|
|
7
|
-
export type {
|
|
8
|
-
BoxProps,
|
|
9
|
-
ColumnProps,
|
|
10
|
-
GridProps,
|
|
11
|
-
RowProps,
|
|
12
|
-
SpacingValue,
|
|
13
|
-
} from './types'
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import type { MaterialTheme } from '@onlynative/core'
|
|
2
|
-
import type { SpacingValue } from './types'
|
|
3
|
-
|
|
4
|
-
export function resolveSpacing(
|
|
5
|
-
spacing: MaterialTheme['spacing'],
|
|
6
|
-
value: SpacingValue | undefined,
|
|
7
|
-
): number | undefined {
|
|
8
|
-
if (value === undefined) return undefined
|
|
9
|
-
if (typeof value === 'number') return value
|
|
10
|
-
return spacing[value]
|
|
11
|
-
}
|
package/src/layout/types.ts
DELETED
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
import type { FlexAlignType, ViewProps } from 'react-native'
|
|
2
|
-
import type { MaterialTheme } from '@onlynative/core'
|
|
3
|
-
|
|
4
|
-
/** A theme spacing token name or a raw numeric value in dp. */
|
|
5
|
-
export type SpacingValue = keyof MaterialTheme['spacing'] | number
|
|
6
|
-
|
|
7
|
-
export interface BoxProps extends ViewProps {
|
|
8
|
-
/** Padding on all sides */
|
|
9
|
-
p?: SpacingValue
|
|
10
|
-
/** Horizontal padding (paddingStart + paddingEnd) */
|
|
11
|
-
px?: SpacingValue
|
|
12
|
-
/** Vertical padding (paddingTop + paddingBottom) */
|
|
13
|
-
py?: SpacingValue
|
|
14
|
-
/** Padding top */
|
|
15
|
-
pt?: SpacingValue
|
|
16
|
-
/** Padding bottom */
|
|
17
|
-
pb?: SpacingValue
|
|
18
|
-
/** Padding start (left in LTR, right in RTL) */
|
|
19
|
-
ps?: SpacingValue
|
|
20
|
-
/** Padding end (right in LTR, left in RTL) */
|
|
21
|
-
pe?: SpacingValue
|
|
22
|
-
/** Margin on all sides */
|
|
23
|
-
m?: SpacingValue
|
|
24
|
-
/** Horizontal margin (marginStart + marginEnd) */
|
|
25
|
-
mx?: SpacingValue
|
|
26
|
-
/** Vertical margin (marginTop + marginBottom) */
|
|
27
|
-
my?: SpacingValue
|
|
28
|
-
/** Margin top */
|
|
29
|
-
mt?: SpacingValue
|
|
30
|
-
/** Margin bottom */
|
|
31
|
-
mb?: SpacingValue
|
|
32
|
-
/** Margin start */
|
|
33
|
-
ms?: SpacingValue
|
|
34
|
-
/** Margin end */
|
|
35
|
-
me?: SpacingValue
|
|
36
|
-
/** Gap between children */
|
|
37
|
-
gap?: SpacingValue
|
|
38
|
-
/** Row gap between children */
|
|
39
|
-
rowGap?: SpacingValue
|
|
40
|
-
/** Column gap between children */
|
|
41
|
-
columnGap?: SpacingValue
|
|
42
|
-
/** Flex value */
|
|
43
|
-
flex?: number
|
|
44
|
-
/** Align items along the cross axis */
|
|
45
|
-
align?: FlexAlignType
|
|
46
|
-
/** Justify content along the main axis */
|
|
47
|
-
justify?:
|
|
48
|
-
| 'flex-start'
|
|
49
|
-
| 'flex-end'
|
|
50
|
-
| 'center'
|
|
51
|
-
| 'space-between'
|
|
52
|
-
| 'space-around'
|
|
53
|
-
| 'space-evenly'
|
|
54
|
-
/** Background color */
|
|
55
|
-
bg?: string
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export interface RowProps extends BoxProps {
|
|
59
|
-
/**
|
|
60
|
-
* Whether children should wrap to the next line when they overflow.
|
|
61
|
-
* @default false
|
|
62
|
-
*/
|
|
63
|
-
wrap?: boolean
|
|
64
|
-
/**
|
|
65
|
-
* Reverses the layout direction (`row-reverse`).
|
|
66
|
-
* @default false
|
|
67
|
-
*/
|
|
68
|
-
inverted?: boolean
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
export interface ColumnProps extends BoxProps {
|
|
72
|
-
/**
|
|
73
|
-
* Reverses the layout direction (`column-reverse`).
|
|
74
|
-
* @default false
|
|
75
|
-
*/
|
|
76
|
-
inverted?: boolean
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
export interface GridProps extends RowProps {
|
|
80
|
-
/** Number of equal-width columns. */
|
|
81
|
-
columns: number
|
|
82
|
-
}
|
package/src/list/List.tsx
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { useMemo } from 'react'
|
|
2
|
-
import { View } from 'react-native'
|
|
3
|
-
import { useTheme } from '@onlynative/core'
|
|
4
|
-
|
|
5
|
-
import { createListStyles } from './styles'
|
|
6
|
-
import type { ListProps } from './types'
|
|
7
|
-
|
|
8
|
-
export function List({ children, style, ...props }: ListProps) {
|
|
9
|
-
const theme = useTheme()
|
|
10
|
-
const styles = useMemo(() => createListStyles(theme), [theme])
|
|
11
|
-
|
|
12
|
-
return (
|
|
13
|
-
<View {...props} style={[styles.container, style]}>
|
|
14
|
-
{children}
|
|
15
|
-
</View>
|
|
16
|
-
)
|
|
17
|
-
}
|
package/src/list/ListDivider.tsx
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { useMemo } from 'react'
|
|
2
|
-
import { View } from 'react-native'
|
|
3
|
-
import { useTheme } from '@onlynative/core'
|
|
4
|
-
|
|
5
|
-
import { createDividerStyles } from './styles'
|
|
6
|
-
import type { ListDividerProps } from './types'
|
|
7
|
-
|
|
8
|
-
export function ListDivider({
|
|
9
|
-
inset = false,
|
|
10
|
-
style,
|
|
11
|
-
...props
|
|
12
|
-
}: ListDividerProps) {
|
|
13
|
-
const theme = useTheme()
|
|
14
|
-
const styles = useMemo(
|
|
15
|
-
() => createDividerStyles(theme, inset),
|
|
16
|
-
[theme, inset],
|
|
17
|
-
)
|
|
18
|
-
|
|
19
|
-
return <View {...props} style={[styles.divider, style]} />
|
|
20
|
-
}
|
package/src/list/ListItem.tsx
DELETED
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
import { useMemo } from 'react'
|
|
2
|
-
import { Platform, Pressable, Text, View } from 'react-native'
|
|
3
|
-
import type { StyleProp, ViewStyle } from 'react-native'
|
|
4
|
-
import { useTheme } from '@onlynative/core'
|
|
5
|
-
|
|
6
|
-
import { createListItemStyles } from './styles'
|
|
7
|
-
import type { ListItemLines, ListItemProps } from './types'
|
|
8
|
-
|
|
9
|
-
interface PressableState {
|
|
10
|
-
pressed: boolean
|
|
11
|
-
hovered?: boolean
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
function getLines(
|
|
15
|
-
supportingText?: string,
|
|
16
|
-
overlineText?: string,
|
|
17
|
-
supportingTextNumberOfLines?: number,
|
|
18
|
-
): ListItemLines {
|
|
19
|
-
if (
|
|
20
|
-
(supportingText && overlineText) ||
|
|
21
|
-
(supportingText && supportingTextNumberOfLines && supportingTextNumberOfLines > 1)
|
|
22
|
-
) {
|
|
23
|
-
return 3
|
|
24
|
-
}
|
|
25
|
-
if (supportingText || overlineText) return 2
|
|
26
|
-
return 1
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export function ListItem({
|
|
30
|
-
headlineText,
|
|
31
|
-
supportingText,
|
|
32
|
-
overlineText,
|
|
33
|
-
trailingSupportingText,
|
|
34
|
-
leadingContent,
|
|
35
|
-
trailingContent,
|
|
36
|
-
onPress,
|
|
37
|
-
disabled = false,
|
|
38
|
-
containerColor,
|
|
39
|
-
supportingTextNumberOfLines = 1,
|
|
40
|
-
style,
|
|
41
|
-
...props
|
|
42
|
-
}: ListItemProps) {
|
|
43
|
-
const isDisabled = Boolean(disabled)
|
|
44
|
-
const isInteractive = onPress !== undefined
|
|
45
|
-
const theme = useTheme()
|
|
46
|
-
const lines = getLines(supportingText, overlineText, supportingTextNumberOfLines)
|
|
47
|
-
const styles = useMemo(
|
|
48
|
-
() => createListItemStyles(theme, lines, containerColor),
|
|
49
|
-
[theme, lines, containerColor],
|
|
50
|
-
)
|
|
51
|
-
|
|
52
|
-
const content = (
|
|
53
|
-
<>
|
|
54
|
-
{leadingContent != null && (
|
|
55
|
-
<View style={styles.leadingContent}>{leadingContent}</View>
|
|
56
|
-
)}
|
|
57
|
-
<View style={styles.textBlock}>
|
|
58
|
-
{overlineText != null && (
|
|
59
|
-
<Text style={styles.overlineText} numberOfLines={1}>
|
|
60
|
-
{overlineText}
|
|
61
|
-
</Text>
|
|
62
|
-
)}
|
|
63
|
-
<Text style={styles.headlineText} numberOfLines={1}>
|
|
64
|
-
{headlineText}
|
|
65
|
-
</Text>
|
|
66
|
-
{supportingText != null && (
|
|
67
|
-
<Text
|
|
68
|
-
style={styles.supportingText}
|
|
69
|
-
numberOfLines={supportingTextNumberOfLines}
|
|
70
|
-
>
|
|
71
|
-
{supportingText}
|
|
72
|
-
</Text>
|
|
73
|
-
)}
|
|
74
|
-
</View>
|
|
75
|
-
{(trailingContent != null || trailingSupportingText != null) && (
|
|
76
|
-
<View style={styles.trailingBlock}>
|
|
77
|
-
{trailingSupportingText != null && (
|
|
78
|
-
<Text style={styles.trailingSupportingText} numberOfLines={1}>
|
|
79
|
-
{trailingSupportingText}
|
|
80
|
-
</Text>
|
|
81
|
-
)}
|
|
82
|
-
{trailingContent}
|
|
83
|
-
</View>
|
|
84
|
-
)}
|
|
85
|
-
</>
|
|
86
|
-
)
|
|
87
|
-
|
|
88
|
-
if (!isInteractive) {
|
|
89
|
-
return (
|
|
90
|
-
<View {...props} style={[styles.container, style]}>
|
|
91
|
-
{content}
|
|
92
|
-
</View>
|
|
93
|
-
)
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
const resolvedStyle = (state: PressableState): StyleProp<ViewStyle> => [
|
|
97
|
-
styles.container,
|
|
98
|
-
styles.interactiveContainer,
|
|
99
|
-
state.hovered && !state.pressed && !isDisabled
|
|
100
|
-
? styles.hoveredContainer
|
|
101
|
-
: undefined,
|
|
102
|
-
state.pressed && !isDisabled ? styles.pressedContainer : undefined,
|
|
103
|
-
isDisabled ? styles.disabledContainer : undefined,
|
|
104
|
-
typeof style === 'function'
|
|
105
|
-
? (style as (state: PressableState) => ViewStyle)(state)
|
|
106
|
-
: style,
|
|
107
|
-
]
|
|
108
|
-
|
|
109
|
-
return (
|
|
110
|
-
<Pressable
|
|
111
|
-
{...props}
|
|
112
|
-
role="button"
|
|
113
|
-
accessibilityState={{ disabled: isDisabled }}
|
|
114
|
-
hitSlop={Platform.OS === 'web' ? undefined : 4}
|
|
115
|
-
disabled={isDisabled}
|
|
116
|
-
onPress={onPress}
|
|
117
|
-
style={resolvedStyle}
|
|
118
|
-
>
|
|
119
|
-
{isDisabled ? (
|
|
120
|
-
<View style={styles.disabledContentWrapper}>
|
|
121
|
-
{content}
|
|
122
|
-
</View>
|
|
123
|
-
) : (
|
|
124
|
-
content
|
|
125
|
-
)}
|
|
126
|
-
</Pressable>
|
|
127
|
-
)
|
|
128
|
-
}
|
package/src/list/index.ts
DELETED
package/src/list/styles.ts
DELETED
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
import { StyleSheet } from 'react-native'
|
|
2
|
-
import type { MaterialTheme } from '@onlynative/core'
|
|
3
|
-
|
|
4
|
-
import type { ListItemLines } from './types'
|
|
5
|
-
import { alphaColor, blendColor } from '@onlynative/utils'
|
|
6
|
-
|
|
7
|
-
const ITEM_PADDING_VERTICAL = 12
|
|
8
|
-
const INSET_START = 56
|
|
9
|
-
|
|
10
|
-
const MIN_HEIGHT: Record<ListItemLines, number> = {
|
|
11
|
-
1: 56,
|
|
12
|
-
2: 72,
|
|
13
|
-
3: 88,
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export function createListStyles(theme: MaterialTheme) {
|
|
17
|
-
return StyleSheet.create({
|
|
18
|
-
container: {
|
|
19
|
-
paddingVertical: theme.spacing.sm,
|
|
20
|
-
},
|
|
21
|
-
})
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
interface ItemColors {
|
|
25
|
-
backgroundColor: string
|
|
26
|
-
hoveredBackgroundColor: string
|
|
27
|
-
pressedBackgroundColor: string
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
function getItemColors(theme: MaterialTheme, containerColor?: string): ItemColors {
|
|
31
|
-
const base = containerColor ?? 'transparent'
|
|
32
|
-
|
|
33
|
-
if (containerColor) {
|
|
34
|
-
return {
|
|
35
|
-
backgroundColor: containerColor,
|
|
36
|
-
hoveredBackgroundColor: blendColor(
|
|
37
|
-
containerColor,
|
|
38
|
-
theme.colors.onSurface,
|
|
39
|
-
theme.stateLayer.hoveredOpacity,
|
|
40
|
-
),
|
|
41
|
-
pressedBackgroundColor: blendColor(
|
|
42
|
-
containerColor,
|
|
43
|
-
theme.colors.onSurface,
|
|
44
|
-
theme.stateLayer.pressedOpacity,
|
|
45
|
-
),
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
return {
|
|
50
|
-
backgroundColor: base,
|
|
51
|
-
hoveredBackgroundColor: alphaColor(
|
|
52
|
-
theme.colors.onSurface,
|
|
53
|
-
theme.stateLayer.hoveredOpacity,
|
|
54
|
-
),
|
|
55
|
-
pressedBackgroundColor: alphaColor(
|
|
56
|
-
theme.colors.onSurface,
|
|
57
|
-
theme.stateLayer.pressedOpacity,
|
|
58
|
-
),
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
export function createListItemStyles(
|
|
63
|
-
theme: MaterialTheme,
|
|
64
|
-
lines: ListItemLines,
|
|
65
|
-
containerColor?: string,
|
|
66
|
-
) {
|
|
67
|
-
const colors = getItemColors(theme, containerColor)
|
|
68
|
-
|
|
69
|
-
return StyleSheet.create({
|
|
70
|
-
container: {
|
|
71
|
-
flexDirection: 'row',
|
|
72
|
-
alignItems: lines === 3 ? 'flex-start' : 'center',
|
|
73
|
-
minHeight: MIN_HEIGHT[lines],
|
|
74
|
-
paddingHorizontal: theme.spacing.md,
|
|
75
|
-
paddingVertical: ITEM_PADDING_VERTICAL,
|
|
76
|
-
backgroundColor: colors.backgroundColor,
|
|
77
|
-
},
|
|
78
|
-
interactiveContainer: {
|
|
79
|
-
cursor: 'pointer',
|
|
80
|
-
},
|
|
81
|
-
hoveredContainer: {
|
|
82
|
-
backgroundColor: colors.hoveredBackgroundColor,
|
|
83
|
-
},
|
|
84
|
-
pressedContainer: {
|
|
85
|
-
backgroundColor: colors.pressedBackgroundColor,
|
|
86
|
-
},
|
|
87
|
-
disabledContainer: {
|
|
88
|
-
cursor: 'auto',
|
|
89
|
-
},
|
|
90
|
-
disabledContentWrapper: {
|
|
91
|
-
flexDirection: 'row',
|
|
92
|
-
flex: 1,
|
|
93
|
-
opacity: theme.stateLayer.disabledOpacity,
|
|
94
|
-
},
|
|
95
|
-
leadingContent: {
|
|
96
|
-
marginEnd: theme.spacing.md,
|
|
97
|
-
},
|
|
98
|
-
textBlock: {
|
|
99
|
-
flex: 1,
|
|
100
|
-
},
|
|
101
|
-
overlineText: {
|
|
102
|
-
...theme.typography.labelSmall,
|
|
103
|
-
color: theme.colors.onSurfaceVariant,
|
|
104
|
-
},
|
|
105
|
-
headlineText: {
|
|
106
|
-
...theme.typography.bodyLarge,
|
|
107
|
-
color: theme.colors.onSurface,
|
|
108
|
-
},
|
|
109
|
-
supportingText: {
|
|
110
|
-
...theme.typography.bodyMedium,
|
|
111
|
-
color: theme.colors.onSurfaceVariant,
|
|
112
|
-
},
|
|
113
|
-
trailingBlock: {
|
|
114
|
-
marginStart: theme.spacing.md,
|
|
115
|
-
alignItems: 'flex-end',
|
|
116
|
-
},
|
|
117
|
-
trailingSupportingText: {
|
|
118
|
-
...theme.typography.labelSmall,
|
|
119
|
-
color: theme.colors.onSurfaceVariant,
|
|
120
|
-
},
|
|
121
|
-
})
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
export function createDividerStyles(theme: MaterialTheme, inset: boolean) {
|
|
125
|
-
return StyleSheet.create({
|
|
126
|
-
divider: {
|
|
127
|
-
height: 1,
|
|
128
|
-
backgroundColor: theme.colors.outlineVariant,
|
|
129
|
-
...(inset ? { marginStart: INSET_START } : undefined),
|
|
130
|
-
},
|
|
131
|
-
})
|
|
132
|
-
}
|
package/src/list/types.ts
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import type { ReactNode } from 'react'
|
|
2
|
-
import type { StyleProp, ViewProps, ViewStyle } from 'react-native'
|
|
3
|
-
|
|
4
|
-
export interface ListProps extends ViewProps {
|
|
5
|
-
/** Content rendered inside the list container. */
|
|
6
|
-
children: ReactNode
|
|
7
|
-
style?: StyleProp<ViewStyle>
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
/** Number of text lines the item displays, used to determine minimum height. */
|
|
11
|
-
export type ListItemLines = 1 | 2 | 3
|
|
12
|
-
|
|
13
|
-
export interface ListItemProps extends ViewProps {
|
|
14
|
-
/** Primary text displayed on the list item. */
|
|
15
|
-
headlineText: string
|
|
16
|
-
/** Secondary text displayed below the headline. */
|
|
17
|
-
supportingText?: string
|
|
18
|
-
/** Text displayed above the headline (e.g. category label). */
|
|
19
|
-
overlineText?: string
|
|
20
|
-
/** Short text displayed at the trailing edge (e.g. "100+", timestamp). */
|
|
21
|
-
trailingSupportingText?: string
|
|
22
|
-
/** Content rendered before the text block (icon, avatar, image, checkbox). */
|
|
23
|
-
leadingContent?: ReactNode
|
|
24
|
-
/** Content rendered after the text block (icon, switch, checkbox). */
|
|
25
|
-
trailingContent?: ReactNode
|
|
26
|
-
/** When provided, the item becomes interactive (Pressable). Omit to render as a plain View. */
|
|
27
|
-
onPress?: () => void
|
|
28
|
-
/**
|
|
29
|
-
* Disables the press interaction and reduces opacity. Only effective when `onPress` is provided.
|
|
30
|
-
* @default false
|
|
31
|
-
*/
|
|
32
|
-
disabled?: boolean
|
|
33
|
-
/**
|
|
34
|
-
* Override the container (background) color.
|
|
35
|
-
* State-layer colors (hover, press) are derived automatically.
|
|
36
|
-
*/
|
|
37
|
-
containerColor?: string
|
|
38
|
-
/**
|
|
39
|
-
* Maximum number of lines for supportingText before truncating.
|
|
40
|
-
* @default 1
|
|
41
|
-
*/
|
|
42
|
-
supportingTextNumberOfLines?: number
|
|
43
|
-
style?: StyleProp<ViewStyle>
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export interface ListDividerProps extends ViewProps {
|
|
47
|
-
/**
|
|
48
|
-
* When true, adds a leading inset so the divider aligns with text
|
|
49
|
-
* that follows a leading icon (56dp from the start edge).
|
|
50
|
-
* @default false
|
|
51
|
-
*/
|
|
52
|
-
inset?: boolean
|
|
53
|
-
style?: StyleProp<ViewStyle>
|
|
54
|
-
}
|
package/src/radio/Radio.tsx
DELETED
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
import { useMemo } from 'react'
|
|
2
|
-
import { Platform, Pressable, View } from 'react-native'
|
|
3
|
-
import type { StyleProp, ViewStyle } from 'react-native'
|
|
4
|
-
import { useTheme } from '@onlynative/core'
|
|
5
|
-
|
|
6
|
-
import { createStyles } from './styles'
|
|
7
|
-
import type { RadioProps } from './types'
|
|
8
|
-
|
|
9
|
-
interface PressableState {
|
|
10
|
-
pressed: boolean
|
|
11
|
-
hovered?: boolean
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
function resolveStyle(
|
|
15
|
-
containerStyle: StyleProp<ViewStyle>,
|
|
16
|
-
hoveredContainerStyle: StyleProp<ViewStyle>,
|
|
17
|
-
pressedContainerStyle: StyleProp<ViewStyle>,
|
|
18
|
-
disabledContainerStyle: StyleProp<ViewStyle>,
|
|
19
|
-
disabled: boolean,
|
|
20
|
-
style: RadioProps['style'],
|
|
21
|
-
): (state: PressableState) => StyleProp<ViewStyle> {
|
|
22
|
-
if (typeof style === 'function') {
|
|
23
|
-
return (state) => [
|
|
24
|
-
containerStyle,
|
|
25
|
-
state.hovered && !state.pressed && !disabled
|
|
26
|
-
? hoveredContainerStyle
|
|
27
|
-
: undefined,
|
|
28
|
-
state.pressed && !disabled ? pressedContainerStyle : undefined,
|
|
29
|
-
disabled ? disabledContainerStyle : undefined,
|
|
30
|
-
style(state),
|
|
31
|
-
]
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
return (state) => [
|
|
35
|
-
containerStyle,
|
|
36
|
-
state.hovered && !state.pressed && !disabled
|
|
37
|
-
? hoveredContainerStyle
|
|
38
|
-
: undefined,
|
|
39
|
-
state.pressed && !disabled ? pressedContainerStyle : undefined,
|
|
40
|
-
disabled ? disabledContainerStyle : undefined,
|
|
41
|
-
style,
|
|
42
|
-
]
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export function Radio({
|
|
46
|
-
style,
|
|
47
|
-
value = false,
|
|
48
|
-
onValueChange,
|
|
49
|
-
containerColor,
|
|
50
|
-
contentColor,
|
|
51
|
-
disabled = false,
|
|
52
|
-
...props
|
|
53
|
-
}: RadioProps) {
|
|
54
|
-
const isDisabled = Boolean(disabled)
|
|
55
|
-
const isSelected = Boolean(value)
|
|
56
|
-
|
|
57
|
-
const theme = useTheme()
|
|
58
|
-
const styles = useMemo(
|
|
59
|
-
() => createStyles(theme, isSelected, containerColor, contentColor),
|
|
60
|
-
[theme, isSelected, containerColor, contentColor],
|
|
61
|
-
)
|
|
62
|
-
|
|
63
|
-
const handlePress = () => {
|
|
64
|
-
if (!isDisabled) {
|
|
65
|
-
onValueChange?.(!isSelected)
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
return (
|
|
70
|
-
<Pressable
|
|
71
|
-
{...props}
|
|
72
|
-
accessibilityRole="radio"
|
|
73
|
-
accessibilityState={{
|
|
74
|
-
disabled: isDisabled,
|
|
75
|
-
checked: isSelected,
|
|
76
|
-
}}
|
|
77
|
-
hitSlop={Platform.OS === 'web' ? undefined : 4}
|
|
78
|
-
disabled={isDisabled}
|
|
79
|
-
onPress={handlePress}
|
|
80
|
-
style={resolveStyle(
|
|
81
|
-
styles.container,
|
|
82
|
-
styles.hoveredContainer,
|
|
83
|
-
styles.pressedContainer,
|
|
84
|
-
styles.disabledContainer,
|
|
85
|
-
isDisabled,
|
|
86
|
-
style,
|
|
87
|
-
)}
|
|
88
|
-
>
|
|
89
|
-
<View
|
|
90
|
-
style={[styles.outer, isDisabled ? styles.disabledOuter : undefined]}
|
|
91
|
-
>
|
|
92
|
-
{isSelected ? (
|
|
93
|
-
<View
|
|
94
|
-
style={[
|
|
95
|
-
styles.inner,
|
|
96
|
-
isDisabled ? styles.disabledInner : undefined,
|
|
97
|
-
]}
|
|
98
|
-
/>
|
|
99
|
-
) : null}
|
|
100
|
-
</View>
|
|
101
|
-
</Pressable>
|
|
102
|
-
)
|
|
103
|
-
}
|
package/src/radio/index.ts
DELETED