achery-ui 0.9.2 → 0.10.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +173 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +198 -0
- package/dist/index.css.map +1 -1
- package/dist/index.d.cts +106 -1
- package/dist/index.d.ts +106 -1
- package/dist/index.js +171 -12
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/native/components/Badge.tsx +6 -2
- package/src/native/components/Button.tsx +18 -11
- package/src/native/components/Input.tsx +42 -1
- package/src/native/components/ScreenNav.tsx +111 -0
- package/src/native/components/SegmentedControl.tsx +81 -0
- package/src/native/components/Skeleton.tsx +1 -1
- package/src/native/components/StatusDot.tsx +53 -0
- package/src/native/components/Tabs.tsx +2 -2
- package/src/native/components/index.ts +11 -2
- package/src/native/index.ts +6 -2
package/package.json
CHANGED
|
@@ -4,11 +4,13 @@ import { useTheme } from '../theme/ThemeContext'
|
|
|
4
4
|
|
|
5
5
|
export type BadgeTone = 'neutral' | 'saved' | 'drafting' | 'stopped' | 'archived'
|
|
6
6
|
export type BadgeVariant = 'outline' | 'solid'
|
|
7
|
+
export type BadgeSize = 'sm' | 'md' | 'lg'
|
|
7
8
|
|
|
8
9
|
export interface BadgeProps {
|
|
9
10
|
tone?: BadgeTone
|
|
10
11
|
variant?: BadgeVariant
|
|
11
12
|
dot?: boolean
|
|
13
|
+
size?: BadgeSize
|
|
12
14
|
children: string
|
|
13
15
|
style?: ViewStyle
|
|
14
16
|
}
|
|
@@ -24,7 +26,9 @@ function toneColors(tone: BadgeTone, variant: BadgeVariant, isDark: boolean) {
|
|
|
24
26
|
return map[tone]
|
|
25
27
|
}
|
|
26
28
|
|
|
27
|
-
|
|
29
|
+
const badgeFontSize: Record<BadgeSize, number> = { sm: 10, md: 11, lg: 12 }
|
|
30
|
+
|
|
31
|
+
export function Badge({ tone = 'neutral', variant = 'outline', dot = false, size = 'md', children, style }: BadgeProps) {
|
|
28
32
|
const { tokens, dark } = useTheme()
|
|
29
33
|
const colors = toneColors(tone, variant, dark)
|
|
30
34
|
|
|
@@ -51,7 +55,7 @@ export function Badge({ tone = 'neutral', variant = 'outline', dot = false, chil
|
|
|
51
55
|
{dot && (
|
|
52
56
|
<View style={{ width: 6, height: 6, borderRadius: 3, backgroundColor: colors.fg }} />
|
|
53
57
|
)}
|
|
54
|
-
<Text style={{ color: fg, fontSize:
|
|
58
|
+
<Text style={{ color: fg, fontSize: badgeFontSize[size], fontWeight: fontWeights.semibold.toString() as any, letterSpacing: 0.5 }}>
|
|
55
59
|
{children}
|
|
56
60
|
</Text>
|
|
57
61
|
</View>
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type ReactNode } from 'react'
|
|
1
2
|
import { TouchableOpacity, View, Text, StyleSheet, type ViewStyle } from 'react-native'
|
|
2
3
|
import { spacing, fontWeights } from 'achery-ui/tokens'
|
|
3
4
|
import { useTheme } from '../theme/ThemeContext'
|
|
@@ -9,7 +10,7 @@ export type ButtonSize = 'sm' | 'md' | 'lg'
|
|
|
9
10
|
export interface ButtonProps {
|
|
10
11
|
variant?: ButtonVariant
|
|
11
12
|
size?: ButtonSize
|
|
12
|
-
children:
|
|
13
|
+
children: ReactNode
|
|
13
14
|
onPress?: () => void
|
|
14
15
|
disabled?: boolean
|
|
15
16
|
style?: ViewStyle
|
|
@@ -37,6 +38,14 @@ function makeColors(variant: ButtonVariant, tokens: SemanticTokens) {
|
|
|
37
38
|
export function Button({ variant = 'secondary', size = 'md', children, onPress, disabled, style }: ButtonProps) {
|
|
38
39
|
const { tokens } = useTheme()
|
|
39
40
|
const colors = makeColors(variant, tokens)
|
|
41
|
+
const textStyle = {
|
|
42
|
+
color: disabled ? tokens.fgMute : colors.label,
|
|
43
|
+
fontSize: fontSize[size],
|
|
44
|
+
fontWeight: fontWeights.semibold.toString() as any,
|
|
45
|
+
letterSpacing: 0.01 * fontSize[size],
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const isString = typeof children === 'string'
|
|
40
49
|
|
|
41
50
|
return (
|
|
42
51
|
<TouchableOpacity
|
|
@@ -52,20 +61,18 @@ export function Button({ variant = 'secondary', size = 'md', children, onPress,
|
|
|
52
61
|
paddingHorizontal: paddingH[size],
|
|
53
62
|
alignSelf: 'flex-start',
|
|
54
63
|
opacity: disabled ? 0.5 : 1,
|
|
64
|
+
flexDirection: 'row',
|
|
65
|
+
alignItems: 'center',
|
|
66
|
+
gap: spacing.sp2,
|
|
55
67
|
},
|
|
56
68
|
style,
|
|
57
69
|
]}
|
|
58
70
|
>
|
|
59
|
-
|
|
60
|
-
style={{
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
letterSpacing: 0.01 * fontSize[size],
|
|
65
|
-
}}
|
|
66
|
-
>
|
|
67
|
-
{children}
|
|
68
|
-
</Text>
|
|
71
|
+
{isString ? (
|
|
72
|
+
<Text style={textStyle}>{children}</Text>
|
|
73
|
+
) : (
|
|
74
|
+
children
|
|
75
|
+
)}
|
|
69
76
|
</TouchableOpacity>
|
|
70
77
|
)
|
|
71
78
|
}
|
|
@@ -32,7 +32,6 @@ export function Field({ label, hint, error, children, style }: FieldProps) {
|
|
|
32
32
|
|
|
33
33
|
export interface InputProps extends TextInputProps {
|
|
34
34
|
error?: boolean
|
|
35
|
-
style?: ViewStyle
|
|
36
35
|
}
|
|
37
36
|
|
|
38
37
|
export function Input({ error, style, ...props }: InputProps) {
|
|
@@ -56,3 +55,45 @@ export function Input({ error, style, ...props }: InputProps) {
|
|
|
56
55
|
/>
|
|
57
56
|
)
|
|
58
57
|
}
|
|
58
|
+
|
|
59
|
+
export interface TextareaProps extends TextInputProps {
|
|
60
|
+
error?: boolean
|
|
61
|
+
/** Approximate number of visible lines. @default 4 */
|
|
62
|
+
rows?: number
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Multi-line text input. Passes `multiline` and `textAlignVertical="top"` to
|
|
67
|
+
* the underlying `TextInput`. Wrap in {@link Field} for a label.
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* ```tsx
|
|
71
|
+
* <Field label="Notes">
|
|
72
|
+
* <Textarea rows={5} placeholder="Notes, checklists, anything…" />
|
|
73
|
+
* </Field>
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
export function Textarea({ error, rows = 4, style, ...props }: TextareaProps) {
|
|
77
|
+
const { tokens } = useTheme()
|
|
78
|
+
return (
|
|
79
|
+
<TextInput
|
|
80
|
+
multiline
|
|
81
|
+
textAlignVertical="top"
|
|
82
|
+
style={[
|
|
83
|
+
{
|
|
84
|
+
backgroundColor: tokens.bg,
|
|
85
|
+
borderWidth: 1.5,
|
|
86
|
+
borderColor: error ? tokens.danger : tokens.border,
|
|
87
|
+
paddingVertical: spacing.sp3,
|
|
88
|
+
paddingHorizontal: spacing.sp5,
|
|
89
|
+
color: tokens.fg,
|
|
90
|
+
fontSize: 14,
|
|
91
|
+
minHeight: rows * 24,
|
|
92
|
+
},
|
|
93
|
+
style,
|
|
94
|
+
]}
|
|
95
|
+
placeholderTextColor={tokens.fgMute}
|
|
96
|
+
{...props}
|
|
97
|
+
/>
|
|
98
|
+
)
|
|
99
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { View, Text, TouchableOpacity } from 'react-native'
|
|
2
|
+
import { useTheme } from '../theme/ThemeContext'
|
|
3
|
+
import { spacing, fontWeights } from 'achery-ui/tokens'
|
|
4
|
+
|
|
5
|
+
export interface ScreenNavProps {
|
|
6
|
+
/** Called when the leading cancel/back button is tapped. */
|
|
7
|
+
onBack: () => void
|
|
8
|
+
/** Label text for the leading button. @default 'cancel' */
|
|
9
|
+
backLabel?: string
|
|
10
|
+
/** Screen title shown centred in the nav bar. */
|
|
11
|
+
title: string
|
|
12
|
+
/** Called when the trailing action button is tapped. */
|
|
13
|
+
onAction?: () => void
|
|
14
|
+
/** Label for the trailing action button. Required when `onAction` is provided. */
|
|
15
|
+
actionLabel?: string
|
|
16
|
+
/** Disables the trailing action button. */
|
|
17
|
+
actionDisabled?: boolean
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Navigation bar for modal push screens (Expo Router `Stack`). Renders a
|
|
22
|
+
* leading cancel/back button, a centred title, and an optional trailing action
|
|
23
|
+
* button. Includes safe-area top padding for iOS.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```tsx
|
|
27
|
+
* <ScreenNav
|
|
28
|
+
* onBack={() => router.back()}
|
|
29
|
+
* title="New task"
|
|
30
|
+
* onAction={handleSave}
|
|
31
|
+
* actionLabel="Save"
|
|
32
|
+
* actionDisabled={isPending}
|
|
33
|
+
* />
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export const ScreenNav = ({
|
|
37
|
+
onBack,
|
|
38
|
+
backLabel = 'cancel',
|
|
39
|
+
title,
|
|
40
|
+
onAction,
|
|
41
|
+
actionLabel,
|
|
42
|
+
actionDisabled = false,
|
|
43
|
+
}: ScreenNavProps) => {
|
|
44
|
+
const { tokens } = useTheme()
|
|
45
|
+
|
|
46
|
+
return (
|
|
47
|
+
<View
|
|
48
|
+
style={{
|
|
49
|
+
flexDirection: 'row',
|
|
50
|
+
alignItems: 'center',
|
|
51
|
+
justifyContent: 'space-between',
|
|
52
|
+
paddingHorizontal: spacing.sp4,
|
|
53
|
+
paddingTop: 56,
|
|
54
|
+
paddingBottom: spacing.sp3,
|
|
55
|
+
backgroundColor: tokens.surface,
|
|
56
|
+
borderBottomWidth: 1,
|
|
57
|
+
borderBottomColor: tokens.border,
|
|
58
|
+
}}
|
|
59
|
+
>
|
|
60
|
+
<TouchableOpacity
|
|
61
|
+
onPress={onBack}
|
|
62
|
+
hitSlop={{ top: 12, bottom: 12, left: 12, right: 12 }}
|
|
63
|
+
style={{ minWidth: 48 }}
|
|
64
|
+
>
|
|
65
|
+
<Text
|
|
66
|
+
style={{
|
|
67
|
+
color: tokens.fg3,
|
|
68
|
+
fontSize: 12,
|
|
69
|
+
fontWeight: fontWeights.semibold.toString() as any,
|
|
70
|
+
letterSpacing: 0.3,
|
|
71
|
+
}}
|
|
72
|
+
>
|
|
73
|
+
{backLabel}
|
|
74
|
+
</Text>
|
|
75
|
+
</TouchableOpacity>
|
|
76
|
+
|
|
77
|
+
<Text
|
|
78
|
+
style={{
|
|
79
|
+
color: tokens.fgMute,
|
|
80
|
+
fontSize: 11,
|
|
81
|
+
fontWeight: fontWeights.semibold.toString() as any,
|
|
82
|
+
letterSpacing: 1.5,
|
|
83
|
+
textTransform: 'uppercase',
|
|
84
|
+
}}
|
|
85
|
+
>
|
|
86
|
+
{title}
|
|
87
|
+
</Text>
|
|
88
|
+
|
|
89
|
+
{onAction && actionLabel ? (
|
|
90
|
+
<TouchableOpacity
|
|
91
|
+
onPress={actionDisabled ? undefined : onAction}
|
|
92
|
+
disabled={actionDisabled}
|
|
93
|
+
hitSlop={{ top: 12, bottom: 12, left: 12, right: 12 }}
|
|
94
|
+
style={{ minWidth: 48, alignItems: 'flex-end' }}
|
|
95
|
+
>
|
|
96
|
+
<Text
|
|
97
|
+
style={{
|
|
98
|
+
color: actionDisabled ? tokens.fgMute : tokens.accent,
|
|
99
|
+
fontSize: 12,
|
|
100
|
+
fontWeight: fontWeights.bold.toString() as any,
|
|
101
|
+
}}
|
|
102
|
+
>
|
|
103
|
+
{actionLabel}
|
|
104
|
+
</Text>
|
|
105
|
+
</TouchableOpacity>
|
|
106
|
+
) : (
|
|
107
|
+
<View style={{ minWidth: 48 }} />
|
|
108
|
+
)}
|
|
109
|
+
</View>
|
|
110
|
+
)
|
|
111
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { View, TouchableOpacity, Text } from 'react-native'
|
|
2
|
+
import type { ReactNode } from 'react'
|
|
3
|
+
import { useTheme } from '../theme/ThemeContext'
|
|
4
|
+
import { spacing, fontWeights } from 'achery-ui/tokens'
|
|
5
|
+
|
|
6
|
+
/** A single option within a native {@link SegmentedControl}. */
|
|
7
|
+
export interface NativeSegmentOption<T extends string = string> {
|
|
8
|
+
value: T
|
|
9
|
+
label: ReactNode
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface SegmentedControlProps<T extends string = string> {
|
|
13
|
+
options: NativeSegmentOption<T>[]
|
|
14
|
+
value: T
|
|
15
|
+
onChange: (value: T) => void
|
|
16
|
+
disabled?: boolean
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Inline button group where exactly one option is active.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```tsx
|
|
24
|
+
* <SegmentedControl
|
|
25
|
+
* options={[{ value: 'hard', label: 'Hard' }, { value: 'soft', label: 'Soft' }]}
|
|
26
|
+
* value={depType}
|
|
27
|
+
* onChange={setDepType}
|
|
28
|
+
* />
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export const SegmentedControl = <T extends string>({
|
|
32
|
+
options,
|
|
33
|
+
value,
|
|
34
|
+
onChange,
|
|
35
|
+
disabled = false,
|
|
36
|
+
}: SegmentedControlProps<T>) => {
|
|
37
|
+
const { tokens } = useTheme()
|
|
38
|
+
|
|
39
|
+
return (
|
|
40
|
+
<View style={{ flexDirection: 'row', borderWidth: 1, borderColor: tokens.border }}>
|
|
41
|
+
{options.map((opt, i) => {
|
|
42
|
+
const isActive = opt.value === value
|
|
43
|
+
const isLast = i === options.length - 1
|
|
44
|
+
return (
|
|
45
|
+
<TouchableOpacity
|
|
46
|
+
key={opt.value}
|
|
47
|
+
onPress={() => !disabled && onChange(opt.value)}
|
|
48
|
+
activeOpacity={0.7}
|
|
49
|
+
style={{
|
|
50
|
+
flex: 1,
|
|
51
|
+
alignItems: 'center',
|
|
52
|
+
justifyContent: 'center',
|
|
53
|
+
paddingVertical: spacing.sp2,
|
|
54
|
+
paddingHorizontal: spacing.sp3,
|
|
55
|
+
backgroundColor: isActive ? tokens.fg : tokens.surface,
|
|
56
|
+
borderRightWidth: isLast ? 0 : 1,
|
|
57
|
+
borderRightColor: tokens.border,
|
|
58
|
+
opacity: disabled ? 0.4 : 1,
|
|
59
|
+
}}
|
|
60
|
+
>
|
|
61
|
+
{typeof opt.label === 'string' ? (
|
|
62
|
+
<Text
|
|
63
|
+
style={{
|
|
64
|
+
color: isActive ? tokens.bg : tokens.fg3,
|
|
65
|
+
fontSize: 10,
|
|
66
|
+
fontWeight: fontWeights.semibold.toString() as any,
|
|
67
|
+
letterSpacing: 0.8,
|
|
68
|
+
textTransform: 'uppercase',
|
|
69
|
+
}}
|
|
70
|
+
>
|
|
71
|
+
{opt.label}
|
|
72
|
+
</Text>
|
|
73
|
+
) : (
|
|
74
|
+
opt.label
|
|
75
|
+
)}
|
|
76
|
+
</TouchableOpacity>
|
|
77
|
+
)
|
|
78
|
+
})}
|
|
79
|
+
</View>
|
|
80
|
+
)
|
|
81
|
+
}
|
|
@@ -60,7 +60,7 @@ export const Skeleton = ({ lines = 3, width, block = false, height = 80, style }
|
|
|
60
60
|
{Array.from({ length: lines }).map((_, i) => (
|
|
61
61
|
<Animated.View
|
|
62
62
|
key={i}
|
|
63
|
-
style={[baseStyle, { height: LINE_HEIGHT, width: lineWidths[i] ?? '100%' }, { opacity }]}
|
|
63
|
+
style={[baseStyle, { height: LINE_HEIGHT, width: (lineWidths[i] ?? '100%') as any }, { opacity }]}
|
|
64
64
|
/>
|
|
65
65
|
))}
|
|
66
66
|
</View>
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { View } from 'react-native'
|
|
2
|
+
import type { BadgeTone } from './Badge'
|
|
3
|
+
import { useTheme } from '../theme/ThemeContext'
|
|
4
|
+
import { palette } from 'achery-ui/tokens'
|
|
5
|
+
|
|
6
|
+
export interface StatusDotProps {
|
|
7
|
+
/** Semantic tone — maps to the same colours as {@link Badge}. */
|
|
8
|
+
tone?: BadgeTone
|
|
9
|
+
/**
|
|
10
|
+
* Diameter in dp.
|
|
11
|
+
* @default 8
|
|
12
|
+
*/
|
|
13
|
+
size?: number
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const TONE_COLOR: Record<BadgeTone, (isDark: boolean) => string> = {
|
|
17
|
+
neutral: (isDark) => isDark ? palette.cream : palette.ink,
|
|
18
|
+
saved: () => palette.success,
|
|
19
|
+
drafting: () => palette.ochre,
|
|
20
|
+
stopped: () => palette.rust,
|
|
21
|
+
archived: (isDark) => isDark ? palette.silver : palette.silverDeep,
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Small filled dot conveying semantic status via the same tone palette as
|
|
26
|
+
* {@link Badge}. Use where a full badge label would be too heavy.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```tsx
|
|
30
|
+
* <View style={{ flexDirection: 'row', alignItems: 'center', gap: 6 }}>
|
|
31
|
+
* <StatusDot tone="drafting" />
|
|
32
|
+
* <Text>In progress</Text>
|
|
33
|
+
* </View>
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export const StatusDot = ({ tone = 'neutral', size = 8 }: StatusDotProps) => {
|
|
37
|
+
const { dark } = useTheme()
|
|
38
|
+
const color = TONE_COLOR[tone](dark)
|
|
39
|
+
const isNeutral = tone === 'neutral'
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<View
|
|
43
|
+
style={{
|
|
44
|
+
width: size,
|
|
45
|
+
height: size,
|
|
46
|
+
borderRadius: size / 2,
|
|
47
|
+
backgroundColor: isNeutral ? 'transparent' : color,
|
|
48
|
+
borderWidth: isNeutral ? 1.5 : 0,
|
|
49
|
+
borderColor: color,
|
|
50
|
+
}}
|
|
51
|
+
/>
|
|
52
|
+
)
|
|
53
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { useState } from 'react'
|
|
1
|
+
import { useState, type ReactNode } from 'react'
|
|
2
2
|
import { ScrollView, TouchableOpacity, View, Text } from 'react-native'
|
|
3
|
-
import type { ViewStyle
|
|
3
|
+
import type { ViewStyle } from 'react-native'
|
|
4
4
|
import { spacing, fontWeights } from 'achery-ui/tokens'
|
|
5
5
|
import { useTheme } from '../theme/ThemeContext'
|
|
6
6
|
|
|
@@ -10,8 +10,8 @@ export type { CardProps, CardVariant, CardPadding } from './Card'
|
|
|
10
10
|
export { Badge } from './Badge'
|
|
11
11
|
export type { BadgeProps, BadgeTone, BadgeVariant } from './Badge'
|
|
12
12
|
|
|
13
|
-
export { Field, Input } from './Input'
|
|
14
|
-
export type { FieldProps, InputProps } from './Input'
|
|
13
|
+
export { Field, Input, Textarea } from './Input'
|
|
14
|
+
export type { FieldProps, InputProps, TextareaProps } from './Input'
|
|
15
15
|
|
|
16
16
|
export { MaterialCard, MaterialEyebrow } from './MaterialCard'
|
|
17
17
|
export type { NativeMaterialCardProps, MaterialIntensity } from './MaterialCard'
|
|
@@ -39,3 +39,12 @@ export type { TabsProps, TabItem } from './Tabs'
|
|
|
39
39
|
|
|
40
40
|
export { ToastProvider, useToast } from './Toast'
|
|
41
41
|
export type { ToastProviderProps, ToastData, ToastOptions } from './Toast'
|
|
42
|
+
|
|
43
|
+
export { StatusDot } from './StatusDot'
|
|
44
|
+
export type { StatusDotProps } from './StatusDot'
|
|
45
|
+
|
|
46
|
+
export { SegmentedControl } from './SegmentedControl'
|
|
47
|
+
export type { SegmentedControlProps, NativeSegmentOption } from './SegmentedControl'
|
|
48
|
+
|
|
49
|
+
export { ScreenNav } from './ScreenNav'
|
|
50
|
+
export type { ScreenNavProps } from './ScreenNav'
|
package/src/native/index.ts
CHANGED
|
@@ -2,17 +2,18 @@ export { NativeThemeProvider, useTheme } from './theme/ThemeContext'
|
|
|
2
2
|
export type { NativeThemeProviderProps, NativeThemeContextValue } from './theme/ThemeContext'
|
|
3
3
|
|
|
4
4
|
export {
|
|
5
|
-
Text, Button, Card, Badge, Field, Input, MaterialCard, MaterialEyebrow,
|
|
5
|
+
Text, Button, Card, Badge, Field, Input, Textarea, MaterialCard, MaterialEyebrow,
|
|
6
6
|
Glyph, GlyphPicker,
|
|
7
7
|
Skeleton, ProgressBar, Checkbox, Toggle, Tabs,
|
|
8
8
|
ToastProvider, useToast,
|
|
9
|
+
StatusDot, SegmentedControl, ScreenNav,
|
|
9
10
|
} from './components/index'
|
|
10
11
|
export type {
|
|
11
12
|
TextProps,
|
|
12
13
|
ButtonProps, ButtonVariant, ButtonSize,
|
|
13
14
|
CardProps, CardVariant, CardPadding,
|
|
14
15
|
BadgeProps, BadgeTone, BadgeVariant,
|
|
15
|
-
FieldProps, InputProps,
|
|
16
|
+
FieldProps, InputProps, TextareaProps,
|
|
16
17
|
NativeMaterialCardProps, MaterialIntensity,
|
|
17
18
|
NativeGlyphProps,
|
|
18
19
|
GlyphPickerProps,
|
|
@@ -22,6 +23,9 @@ export type {
|
|
|
22
23
|
ToggleProps,
|
|
23
24
|
TabsProps, TabItem,
|
|
24
25
|
ToastProviderProps, ToastData, ToastOptions,
|
|
26
|
+
StatusDotProps,
|
|
27
|
+
SegmentedControlProps, NativeSegmentOption,
|
|
28
|
+
ScreenNavProps,
|
|
25
29
|
} from './components/index'
|
|
26
30
|
|
|
27
31
|
// Glyph utilities — pure TS, work on native
|