@hzblj/kara-components 0.1.0 → 0.2.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/CHANGELOG.md +36 -0
- package/lib/module/atoms/badge/badge.android.js +8 -2
- package/lib/module/atoms/badge/badge.android.js.map +1 -1
- package/lib/module/atoms/button/button-tokens.js +39 -0
- package/lib/module/atoms/button/button-tokens.js.map +1 -1
- package/lib/module/atoms/button/button.android.js +40 -12
- package/lib/module/atoms/button/button.android.js.map +1 -1
- package/lib/module/atoms/button/button.ios.js +5 -2
- package/lib/module/atoms/button/button.ios.js.map +1 -1
- package/lib/module/atoms/checkbox/checkbox.android.js +17 -2
- package/lib/module/atoms/checkbox/checkbox.android.js.map +1 -1
- package/lib/module/atoms/date-picker/date-picker.android.js +72 -0
- package/lib/module/atoms/date-picker/date-picker.android.js.map +1 -0
- package/lib/module/atoms/date-picker/{date-picker.js → date-picker.ios.js} +4 -7
- package/lib/module/atoms/date-picker/date-picker.ios.js.map +1 -0
- package/lib/module/atoms/date-picker/index.js +1 -1
- package/lib/module/atoms/date-picker/index.js.map +1 -1
- package/lib/module/atoms/fab/fab.android.js +5 -3
- package/lib/module/atoms/fab/fab.android.js.map +1 -1
- package/lib/module/atoms/glass-view/glass-fallback.js +5 -2
- package/lib/module/atoms/glass-view/glass-fallback.js.map +1 -1
- package/lib/module/atoms/icon/icon.android.js +10 -12
- package/lib/module/atoms/icon/icon.android.js.map +1 -1
- package/lib/module/atoms/icon/icon.ios.js +15 -3
- package/lib/module/atoms/icon/icon.ios.js.map +1 -1
- package/lib/module/atoms/icon/index.js +0 -1
- package/lib/module/atoms/icon/index.js.map +1 -1
- package/lib/module/atoms/index.js +1 -1
- package/lib/module/atoms/index.js.map +1 -1
- package/lib/module/atoms/list/list.android.js +8 -2
- package/lib/module/atoms/list/list.android.js.map +1 -1
- package/lib/module/atoms/picker/index.js +1 -1
- package/lib/module/atoms/picker/index.js.map +1 -1
- package/lib/module/atoms/picker/picker.android.js +87 -0
- package/lib/module/atoms/picker/picker.android.js.map +1 -0
- package/lib/module/atoms/picker/{picker.js → picker.ios.js} +1 -1
- package/lib/module/atoms/picker/picker.ios.js.map +1 -0
- package/lib/module/atoms/rn-icon/index.js +5 -0
- package/lib/module/atoms/rn-icon/index.js.map +1 -0
- package/lib/module/atoms/rn-icon/rn-icon.android.js +29 -0
- package/lib/module/atoms/rn-icon/rn-icon.android.js.map +1 -0
- package/lib/module/atoms/rn-icon/rn-icon.ios.js +29 -0
- package/lib/module/atoms/rn-icon/rn-icon.ios.js.map +1 -0
- package/lib/module/atoms/rn-icon/rn-icon.types.js +4 -0
- package/lib/module/atoms/rn-icon/rn-icon.types.js.map +1 -0
- package/lib/module/atoms/surface/surface.android.js +33 -5
- package/lib/module/atoms/surface/surface.android.js.map +1 -1
- package/lib/module/atoms/switch/switch.android.js +14 -1
- package/lib/module/atoms/switch/switch.android.js.map +1 -1
- package/lib/module/glyph/glyph-button.android.js +25 -0
- package/lib/module/glyph/glyph-button.android.js.map +1 -0
- package/lib/module/glyph/glyph-button.ios.js +33 -0
- package/lib/module/glyph/glyph-button.ios.js.map +1 -0
- package/lib/module/glyph/glyph-button.types.js +4 -0
- package/lib/module/glyph/glyph-button.types.js.map +1 -0
- package/lib/module/glyph/glyph.android.js +20 -0
- package/lib/module/glyph/glyph.android.js.map +1 -0
- package/lib/module/glyph/glyph.ios.js +24 -0
- package/lib/module/glyph/glyph.ios.js.map +1 -0
- package/lib/module/glyph/glyph.types.js +4 -0
- package/lib/module/glyph/glyph.types.js.map +1 -0
- package/lib/module/glyph/index.js +8 -0
- package/lib/module/glyph/index.js.map +1 -0
- package/lib/module/glyph/rn-glyph.android.js +25 -0
- package/lib/module/glyph/rn-glyph.android.js.map +1 -0
- package/lib/module/glyph/rn-glyph.ios.js +26 -0
- package/lib/module/glyph/rn-glyph.ios.js.map +1 -0
- package/lib/module/molecules/collapsible/collapsible.android.js +2 -2
- package/lib/module/molecules/collapsible/collapsible.android.js.map +1 -1
- package/lib/module/molecules/labeled-content/labeled-content.js +2 -1
- package/lib/module/molecules/labeled-content/labeled-content.js.map +1 -1
- package/lib/module/molecules/list-item/list-item.js +2 -1
- package/lib/module/molecules/list-item/list-item.js.map +1 -1
- package/lib/module/molecules/navigation-bar/navigation-bar.android.js +8 -4
- package/lib/module/molecules/navigation-bar/navigation-bar.android.js.map +1 -1
- package/lib/module/molecules/radio-group/radio-group.android.js +5 -0
- package/lib/module/molecules/radio-group/radio-group.android.js.map +1 -1
- package/lib/module/molecules/radio-group/radio-group.ios.js +2 -2
- package/lib/module/molecules/radio-group/radio-group.ios.js.map +1 -1
- package/lib/module/molecules/search-bar/search-bar.js +10 -23
- package/lib/module/molecules/search-bar/search-bar.js.map +1 -1
- package/lib/module/molecules/stepper/stepper.android.js +7 -5
- package/lib/module/molecules/stepper/stepper.android.js.map +1 -1
- package/lib/module/organisms/alert/alert.android.js +42 -13
- package/lib/module/organisms/alert/alert.android.js.map +1 -1
- package/lib/module/organisms/context-menu/context-menu.android.js +82 -31
- package/lib/module/organisms/context-menu/context-menu.android.js.map +1 -1
- package/lib/module/organisms/context-menu/context-menu.ios.js +37 -16
- package/lib/module/organisms/context-menu/context-menu.ios.js.map +1 -1
- package/lib/module/organisms/fab-menu/fab-menu.android.js +6 -2
- package/lib/module/organisms/fab-menu/fab-menu.android.js.map +1 -1
- package/lib/module/organisms/fab-menu/fab-menu.ios.js +15 -6
- package/lib/module/organisms/fab-menu/fab-menu.ios.js.map +1 -1
- package/lib/module/organisms/form/form.android.js +1 -0
- package/lib/module/organisms/form/form.android.js.map +1 -1
- package/lib/module/organisms/index.js +0 -1
- package/lib/module/organisms/index.js.map +1 -1
- package/lib/module/organisms/menu/menu.android.js +51 -33
- package/lib/module/organisms/menu/menu.android.js.map +1 -1
- package/lib/typescript/atoms/button/button-tokens.d.ts +6 -1
- package/lib/typescript/atoms/date-picker/date-picker.d.ts +1 -2
- package/lib/typescript/atoms/date-picker/date-picker.ios.d.ts +3 -0
- package/lib/typescript/atoms/glass-view/glass-fallback.d.ts +4 -1
- package/lib/typescript/atoms/glass-view/glass-view.types.d.ts +1 -1
- package/lib/typescript/atoms/icon/icon.ios.d.ts +4 -0
- package/lib/typescript/atoms/icon/icon.types.d.ts +18 -1
- package/lib/typescript/atoms/icon/index.d.ts +0 -1
- package/lib/typescript/atoms/index.d.ts +1 -1
- package/lib/typescript/atoms/list/list.types.d.ts +9 -0
- package/lib/typescript/atoms/picker/picker.d.ts +1 -2
- package/lib/typescript/atoms/picker/picker.ios.d.ts +2 -0
- package/lib/typescript/atoms/rn-icon/index.d.ts +2 -0
- package/lib/typescript/atoms/rn-icon/rn-icon.d.ts +1 -0
- package/lib/typescript/atoms/rn-icon/rn-icon.ios.d.ts +3 -0
- package/lib/typescript/atoms/rn-icon/rn-icon.types.d.ts +5 -0
- package/lib/typescript/glyph/glyph-button.d.ts +1 -0
- package/lib/typescript/glyph/glyph-button.ios.d.ts +2 -0
- package/lib/typescript/glyph/glyph-button.types.d.ts +10 -0
- package/lib/typescript/glyph/glyph.d.ts +1 -0
- package/lib/typescript/glyph/glyph.ios.d.ts +3 -0
- package/lib/typescript/glyph/glyph.types.d.ts +13 -0
- package/lib/typescript/glyph/index.d.ts +5 -0
- package/lib/typescript/glyph/rn-glyph.d.ts +1 -0
- package/lib/typescript/glyph/rn-glyph.ios.d.ts +3 -0
- package/lib/typescript/molecules/scroll-edge-container/scroll-edge-container.types.d.ts +3 -0
- package/lib/typescript/organisms/context-menu/context-menu.types.d.ts +28 -2
- package/lib/typescript/organisms/fab-menu/fab-menu.types.d.ts +1 -1
- package/lib/typescript/organisms/form/form.types.d.ts +5 -0
- package/lib/typescript/organisms/index.d.ts +0 -1
- package/package.json +4 -6
- package/src/atoms/badge/badge.android.tsx +5 -2
- package/src/atoms/button/button-tokens.ts +49 -0
- package/src/atoms/button/button.android.tsx +46 -12
- package/src/atoms/button/button.ios.tsx +5 -2
- package/src/atoms/checkbox/checkbox.android.tsx +21 -4
- package/src/atoms/date-picker/date-picker.android.tsx +74 -0
- package/src/atoms/date-picker/date-picker.ios.tsx +27 -0
- package/src/atoms/fab/fab.android.tsx +4 -1
- package/src/atoms/glass-view/glass-fallback.tsx +5 -2
- package/src/atoms/glass-view/glass-view.types.ts +1 -1
- package/src/atoms/icon/icon.android.tsx +11 -7
- package/src/atoms/icon/icon.ios.tsx +25 -5
- package/src/atoms/icon/icon.types.ts +18 -24
- package/src/atoms/icon/index.ts +0 -1
- package/src/atoms/index.ts +1 -1
- package/src/atoms/list/list.android.tsx +12 -1
- package/src/atoms/list/list.types.ts +9 -0
- package/src/atoms/picker/picker.android.tsx +88 -0
- package/src/atoms/rn-icon/index.ts +2 -0
- package/src/atoms/rn-icon/rn-icon.android.tsx +28 -0
- package/src/atoms/rn-icon/rn-icon.ios.tsx +28 -0
- package/src/atoms/rn-icon/rn-icon.types.ts +8 -0
- package/src/atoms/surface/surface.android.tsx +28 -4
- package/src/atoms/switch/switch.android.tsx +24 -3
- package/src/glyph/glyph-button.android.tsx +25 -0
- package/src/glyph/glyph-button.ios.tsx +37 -0
- package/src/glyph/glyph-button.types.ts +12 -0
- package/src/glyph/glyph.android.tsx +12 -0
- package/src/glyph/glyph.ios.tsx +15 -0
- package/src/glyph/glyph.types.ts +15 -0
- package/src/glyph/index.ts +5 -0
- package/src/glyph/rn-glyph.android.tsx +14 -0
- package/src/glyph/rn-glyph.ios.tsx +16 -0
- package/src/molecules/collapsible/collapsible.android.tsx +2 -2
- package/src/molecules/labeled-content/labeled-content.tsx +2 -1
- package/src/molecules/list-item/list-item.tsx +2 -1
- package/src/molecules/navigation-bar/navigation-bar.android.tsx +11 -4
- package/src/molecules/radio-group/radio-group.android.tsx +11 -2
- package/src/molecules/radio-group/radio-group.ios.tsx +2 -2
- package/src/molecules/scroll-edge-container/scroll-edge-container.types.ts +3 -0
- package/src/molecules/search-bar/search-bar.tsx +4 -9
- package/src/molecules/stepper/stepper.android.tsx +3 -3
- package/src/organisms/alert/alert.android.tsx +44 -7
- package/src/organisms/context-menu/context-menu.android.tsx +71 -37
- package/src/organisms/context-menu/context-menu.ios.tsx +40 -18
- package/src/organisms/context-menu/context-menu.types.ts +29 -3
- package/src/organisms/fab-menu/fab-menu.android.tsx +3 -2
- package/src/organisms/fab-menu/fab-menu.ios.tsx +13 -12
- package/src/organisms/fab-menu/fab-menu.types.ts +1 -1
- package/src/organisms/form/form.android.tsx +1 -1
- package/src/organisms/form/form.types.ts +5 -0
- package/src/organisms/index.ts +0 -1
- package/src/organisms/menu/menu.android.tsx +36 -30
- package/lib/module/atoms/countdown/countdown-frame.js +0 -115
- package/lib/module/atoms/countdown/countdown-frame.js.map +0 -1
- package/lib/module/atoms/countdown/countdown-units.js +0 -25
- package/lib/module/atoms/countdown/countdown-units.js.map +0 -1
- package/lib/module/atoms/countdown/countdown.android.js +0 -53
- package/lib/module/atoms/countdown/countdown.android.js.map +0 -1
- package/lib/module/atoms/countdown/countdown.ios.js +0 -50
- package/lib/module/atoms/countdown/countdown.ios.js.map +0 -1
- package/lib/module/atoms/countdown/countdown.types.js +0 -4
- package/lib/module/atoms/countdown/countdown.types.js.map +0 -1
- package/lib/module/atoms/countdown/index.js +0 -5
- package/lib/module/atoms/countdown/index.js.map +0 -1
- package/lib/module/atoms/date-picker/date-picker.js.map +0 -1
- package/lib/module/atoms/icon/icon-names.js +0 -53
- package/lib/module/atoms/icon/icon-names.js.map +0 -1
- package/lib/module/atoms/picker/picker.js.map +0 -1
- package/lib/module/organisms/rn-context-menu/index.js +0 -5
- package/lib/module/organisms/rn-context-menu/index.js.map +0 -1
- package/lib/module/organisms/rn-context-menu/rn-context-menu.android.js +0 -101
- package/lib/module/organisms/rn-context-menu/rn-context-menu.android.js.map +0 -1
- package/lib/module/organisms/rn-context-menu/rn-context-menu.ios.js +0 -44
- package/lib/module/organisms/rn-context-menu/rn-context-menu.ios.js.map +0 -1
- package/lib/module/organisms/rn-context-menu/rn-context-menu.types.js +0 -4
- package/lib/module/organisms/rn-context-menu/rn-context-menu.types.js.map +0 -1
- package/lib/typescript/atoms/countdown/countdown-frame.d.ts +0 -17
- package/lib/typescript/atoms/countdown/countdown-units.d.ts +0 -5
- package/lib/typescript/atoms/countdown/countdown.d.ts +0 -1
- package/lib/typescript/atoms/countdown/countdown.ios.d.ts +0 -2
- package/lib/typescript/atoms/countdown/countdown.types.d.ts +0 -21
- package/lib/typescript/atoms/countdown/index.d.ts +0 -2
- package/lib/typescript/atoms/icon/icon-names.d.ts +0 -50
- package/lib/typescript/organisms/rn-context-menu/index.d.ts +0 -2
- package/lib/typescript/organisms/rn-context-menu/rn-context-menu.d.ts +0 -1
- package/lib/typescript/organisms/rn-context-menu/rn-context-menu.ios.d.ts +0 -2
- package/lib/typescript/organisms/rn-context-menu/rn-context-menu.types.d.ts +0 -33
- package/src/atoms/countdown/countdown-frame.tsx +0 -123
- package/src/atoms/countdown/countdown-units.ts +0 -37
- package/src/atoms/countdown/countdown.android.tsx +0 -49
- package/src/atoms/countdown/countdown.ios.tsx +0 -46
- package/src/atoms/countdown/countdown.types.ts +0 -24
- package/src/atoms/countdown/index.ts +0 -2
- package/src/atoms/date-picker/date-picker.tsx +0 -26
- package/src/atoms/icon/icon-names.ts +0 -53
- package/src/organisms/rn-context-menu/index.ts +0 -2
- package/src/organisms/rn-context-menu/rn-context-menu.android.tsx +0 -90
- package/src/organisms/rn-context-menu/rn-context-menu.ios.tsx +0 -47
- package/src/organisms/rn-context-menu/rn-context-menu.types.ts +0 -36
- /package/src/atoms/picker/{picker.tsx → picker.ios.tsx} +0 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Text as ComposeText,
|
|
3
|
+
DropdownMenuItem,
|
|
4
|
+
ExposedDropdownMenu,
|
|
5
|
+
ExposedDropdownMenuBox,
|
|
6
|
+
Host,
|
|
7
|
+
OutlinedTextField,
|
|
8
|
+
useNativeState,
|
|
9
|
+
} from '@expo/ui/jetpack-compose'
|
|
10
|
+
import {fillMaxWidth, menuAnchor, testID as testIdModifier} from '@expo/ui/jetpack-compose/modifiers'
|
|
11
|
+
import {useAppTheme} from '@hzblj/kara-theme'
|
|
12
|
+
import {useEffect, useMemo, useState} from 'react'
|
|
13
|
+
|
|
14
|
+
import {Glyph} from '../../glyph'
|
|
15
|
+
import {HostBoundary} from '../../host-context'
|
|
16
|
+
import type {PickerComponent, PickerProps} from './picker.types'
|
|
17
|
+
|
|
18
|
+
const MATCH_HEIGHT_ONLY = {horizontal: false, vertical: true}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Material's exposed dropdown: a read-only outlined field the width of its container, opening a menu of the options
|
|
22
|
+
* under it. Its own host, themed like an `Island`, so it drops into React Native layout like the iOS picker does.
|
|
23
|
+
*/
|
|
24
|
+
export const Picker: PickerComponent = ({disabled = false, onValueChange, options, testID, value}: PickerProps) => {
|
|
25
|
+
const theme = useAppTheme()
|
|
26
|
+
const [expanded, setExpanded] = useState(false)
|
|
27
|
+
const selectedLabel = options.find(option => option.value === value)?.label ?? ''
|
|
28
|
+
const label = useNativeState(selectedLabel)
|
|
29
|
+
const fieldModifiers = useMemo(() => {
|
|
30
|
+
const list = [fillMaxWidth(), menuAnchor('primaryNotEditable', !disabled)]
|
|
31
|
+
|
|
32
|
+
return testID ? [...list, testIdModifier(testID)] : list
|
|
33
|
+
}, [disabled, testID])
|
|
34
|
+
|
|
35
|
+
// `useNativeState` takes only its initial value; a new selection is pushed to the field.
|
|
36
|
+
useEffect(() => {
|
|
37
|
+
label.set(selectedLabel)
|
|
38
|
+
}, [label, selectedLabel])
|
|
39
|
+
|
|
40
|
+
return (
|
|
41
|
+
<Host colorScheme={theme.dark ? 'dark' : 'light'} matchContents={MATCH_HEIGHT_ONLY} seedColor={theme.materialSeed}>
|
|
42
|
+
<HostBoundary>
|
|
43
|
+
<ExposedDropdownMenuBox expanded={expanded} onExpandedChange={disabled ? undefined : setExpanded}>
|
|
44
|
+
<OutlinedTextField
|
|
45
|
+
enabled={!disabled}
|
|
46
|
+
modifiers={fieldModifiers}
|
|
47
|
+
readOnly
|
|
48
|
+
singleLine
|
|
49
|
+
textStyle={{
|
|
50
|
+
color: theme.colorString('content.primary'),
|
|
51
|
+
fontFamily: theme.typography.body.fontFamily,
|
|
52
|
+
fontWeight: theme.typography.body.fontWeight,
|
|
53
|
+
}}
|
|
54
|
+
value={label}
|
|
55
|
+
>
|
|
56
|
+
<OutlinedTextField.TrailingIcon>
|
|
57
|
+
<Glyph color="content.secondary" name="chevronDown" size="s20" />
|
|
58
|
+
</OutlinedTextField.TrailingIcon>
|
|
59
|
+
</OutlinedTextField>
|
|
60
|
+
<ExposedDropdownMenu
|
|
61
|
+
containerColor={theme.color('surface.primary')}
|
|
62
|
+
expanded={expanded}
|
|
63
|
+
onDismissRequest={() => setExpanded(false)}
|
|
64
|
+
>
|
|
65
|
+
{options.map(option => (
|
|
66
|
+
<DropdownMenuItem
|
|
67
|
+
key={option.value}
|
|
68
|
+
onClick={() => {
|
|
69
|
+
setExpanded(false)
|
|
70
|
+
onValueChange?.(option.value)
|
|
71
|
+
}}
|
|
72
|
+
>
|
|
73
|
+
<DropdownMenuItem.Text>
|
|
74
|
+
<ComposeText
|
|
75
|
+
color={theme.colorString(option.value === value ? 'content.accent' : 'content.primary')}
|
|
76
|
+
style={theme.typography.body}
|
|
77
|
+
>
|
|
78
|
+
{option.label}
|
|
79
|
+
</ComposeText>
|
|
80
|
+
</DropdownMenuItem.Text>
|
|
81
|
+
</DropdownMenuItem>
|
|
82
|
+
))}
|
|
83
|
+
</ExposedDropdownMenu>
|
|
84
|
+
</ExposedDropdownMenuBox>
|
|
85
|
+
</HostBoundary>
|
|
86
|
+
</Host>
|
|
87
|
+
)
|
|
88
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import {iconResourceName} from '@hzblj/kara-native'
|
|
2
|
+
import {IconView} from '@hzblj/kara-native/jetpack-compose'
|
|
3
|
+
import {spacing, useAppTheme} from '@hzblj/kara-theme'
|
|
4
|
+
import {useMemo} from 'react'
|
|
5
|
+
|
|
6
|
+
import type {RnIconComponent, RnIconProps} from './rn-icon.types'
|
|
7
|
+
|
|
8
|
+
/** An `ImageView` over the app's vector drawable — what a list row wants, rather than a Compose host per row. */
|
|
9
|
+
export const RnIcon: RnIconComponent = ({
|
|
10
|
+
accessibilityLabel,
|
|
11
|
+
color = 'content.primary',
|
|
12
|
+
name,
|
|
13
|
+
size = 's24',
|
|
14
|
+
testID,
|
|
15
|
+
}: RnIconProps) => {
|
|
16
|
+
const theme = useAppTheme()
|
|
17
|
+
const style = useMemo(() => ({height: spacing[size], width: spacing[size]}), [size])
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<IconView
|
|
21
|
+
accessibilityLabel={accessibilityLabel}
|
|
22
|
+
iconColor={theme.color(color)}
|
|
23
|
+
resourceName={iconResourceName(name)}
|
|
24
|
+
style={style}
|
|
25
|
+
testID={testID}
|
|
26
|
+
/>
|
|
27
|
+
)
|
|
28
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import {iconResourceName} from '@hzblj/kara-native'
|
|
2
|
+
import {IconView} from '@hzblj/kara-native/swift-ui'
|
|
3
|
+
import {spacing, useAppTheme} from '@hzblj/kara-theme'
|
|
4
|
+
import {useMemo} from 'react'
|
|
5
|
+
|
|
6
|
+
import type {RnIconComponent, RnIconProps} from './rn-icon.types'
|
|
7
|
+
|
|
8
|
+
/** A `UIImageView` over the app's asset-catalog icon — what a list row wants, rather than a SwiftUI host per row. */
|
|
9
|
+
export const RnIcon: RnIconComponent = ({
|
|
10
|
+
accessibilityLabel,
|
|
11
|
+
color = 'content.primary',
|
|
12
|
+
name,
|
|
13
|
+
size = 's24',
|
|
14
|
+
testID,
|
|
15
|
+
}: RnIconProps) => {
|
|
16
|
+
const theme = useAppTheme()
|
|
17
|
+
const style = useMemo(() => ({height: spacing[size], width: spacing[size]}), [size])
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<IconView
|
|
21
|
+
accessibilityLabel={accessibilityLabel}
|
|
22
|
+
assetName={iconResourceName(name)}
|
|
23
|
+
iconColor={theme.color(color)}
|
|
24
|
+
style={style}
|
|
25
|
+
testID={testID}
|
|
26
|
+
/>
|
|
27
|
+
)
|
|
28
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type {ReactNode} from 'react'
|
|
2
|
+
|
|
3
|
+
import type {IconProps} from '../icon'
|
|
4
|
+
|
|
5
|
+
/** The same contract as `Icon`, for the React Native tier — anywhere, no `Screen` or `Island` needed. */
|
|
6
|
+
export type RnIconProps = IconProps
|
|
7
|
+
|
|
8
|
+
export type RnIconComponent = (props: RnIconProps) => ReactNode
|
|
@@ -1,16 +1,40 @@
|
|
|
1
|
-
import {Surface as ComposeSurface, Shape} from '@expo/ui/jetpack-compose'
|
|
1
|
+
import {Column, Surface as ComposeSurface, Shape} from '@expo/ui/jetpack-compose'
|
|
2
|
+
import {testID as testIdModifier} from '@expo/ui/jetpack-compose/modifiers'
|
|
2
3
|
import {useSxModifiers} from '@hzblj/kara-sx'
|
|
3
4
|
import {radii, useAppTheme} from '@hzblj/kara-theme'
|
|
5
|
+
import {useMemo} from 'react'
|
|
4
6
|
import {useHostGuard} from '../../host-context'
|
|
5
7
|
import type {SurfaceComponent, SurfaceProps} from './surface.types'
|
|
6
8
|
|
|
7
9
|
const cornerRadii = (radius: number) => ({bottomEnd: radius, bottomStart: radius, topEnd: radius, topStart: radius})
|
|
8
10
|
|
|
9
|
-
|
|
11
|
+
/**
|
|
12
|
+
* Material's `Surface`, with the padding on a `Column` inside it. Compose applies a `Surface`'s own modifiers before it
|
|
13
|
+
* draws the shape, so padding there would inset the background instead of the content — and a bare `Surface` stacks
|
|
14
|
+
* its children on top of each other rather than in a column.
|
|
15
|
+
*/
|
|
16
|
+
export const Surface: SurfaceComponent = ({
|
|
17
|
+
children,
|
|
18
|
+
glass = false,
|
|
19
|
+
p = 's16',
|
|
20
|
+
pb,
|
|
21
|
+
pl,
|
|
22
|
+
pr,
|
|
23
|
+
pt,
|
|
24
|
+
px,
|
|
25
|
+
py,
|
|
26
|
+
testID,
|
|
27
|
+
...sx
|
|
28
|
+
}: SurfaceProps) => {
|
|
10
29
|
useHostGuard('Surface')
|
|
11
30
|
|
|
12
31
|
const theme = useAppTheme()
|
|
13
|
-
const
|
|
32
|
+
const sxModifiers = useSxModifiers({...sx, bg: undefined})
|
|
33
|
+
const modifiers = useMemo(
|
|
34
|
+
() => (testID ? [...sxModifiers, testIdModifier(testID)] : sxModifiers),
|
|
35
|
+
[sxModifiers, testID]
|
|
36
|
+
)
|
|
37
|
+
const contentModifiers = useSxModifiers({p, pb, pl, pr, pt, px, py, wide: sx.wide})
|
|
14
38
|
|
|
15
39
|
return (
|
|
16
40
|
<ComposeSurface
|
|
@@ -20,7 +44,7 @@ export const Surface: SurfaceComponent = ({children, glass = false, testID, ...s
|
|
|
20
44
|
shape={Shape.RoundedCorner({cornerRadii: cornerRadii(radii[sx.borderRadius ?? 'large'])})}
|
|
21
45
|
tonalElevation={glass ? 3 : 0}
|
|
22
46
|
>
|
|
23
|
-
{children}
|
|
47
|
+
<Column modifiers={contentModifiers}>{children}</Column>
|
|
24
48
|
</ComposeSurface>
|
|
25
49
|
)
|
|
26
50
|
}
|
|
@@ -1,21 +1,42 @@
|
|
|
1
1
|
import {Switch as ComposeSwitch, Row, Text} from '@expo/ui/jetpack-compose'
|
|
2
|
+
import {clickable, fillMaxWidth} from '@expo/ui/jetpack-compose/modifiers'
|
|
2
3
|
import {useAppTheme} from '@hzblj/kara-theme'
|
|
4
|
+
import {useMemo} from 'react'
|
|
3
5
|
|
|
4
6
|
import {useHostGuard} from '../../host-context'
|
|
5
7
|
import type {SwitchComponent, SwitchProps} from './switch.types'
|
|
6
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Material's switch, tinted with the accent like SwiftUI's toggle. With a label it is a full-width row — label at the
|
|
11
|
+
* start, switch at the end — and the whole row toggles, the way a Material settings row does.
|
|
12
|
+
*/
|
|
7
13
|
export const Switch: SwitchComponent = ({disabled = false, label, onValueChange, value}: SwitchProps) => {
|
|
8
14
|
useHostGuard('Switch')
|
|
9
15
|
const theme = useAppTheme()
|
|
10
|
-
const
|
|
16
|
+
const rowModifiers = useMemo(
|
|
17
|
+
() => (disabled || !onValueChange ? [fillMaxWidth()] : [fillMaxWidth(), clickable(() => onValueChange(!value))]),
|
|
18
|
+
[disabled, onValueChange, value]
|
|
19
|
+
)
|
|
20
|
+
const control = (
|
|
21
|
+
<ComposeSwitch
|
|
22
|
+
colors={{
|
|
23
|
+
checkedBorderColor: theme.color('fill.accent.primary'),
|
|
24
|
+
checkedThumbColor: theme.color('content.on.bg'),
|
|
25
|
+
checkedTrackColor: theme.color('fill.accent.primary'),
|
|
26
|
+
}}
|
|
27
|
+
enabled={!disabled}
|
|
28
|
+
onCheckedChange={onValueChange}
|
|
29
|
+
value={value}
|
|
30
|
+
/>
|
|
31
|
+
)
|
|
11
32
|
|
|
12
33
|
if (!label) {
|
|
13
34
|
return control
|
|
14
35
|
}
|
|
15
36
|
|
|
16
37
|
return (
|
|
17
|
-
<Row horizontalArrangement="spaceBetween" verticalAlignment="center">
|
|
18
|
-
<Text color={theme.colorString('content.primary')} style={theme.typography.body}>
|
|
38
|
+
<Row horizontalArrangement="spaceBetween" modifiers={rowModifiers} verticalAlignment="center">
|
|
39
|
+
<Text color={theme.colorString(disabled ? 'content.tertiary' : 'content.primary')} style={theme.typography.body}>
|
|
19
40
|
{label}
|
|
20
41
|
</Text>
|
|
21
42
|
{control}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import {IconButton as ComposeIconButton} from '@expo/ui/jetpack-compose'
|
|
2
|
+
import {GLYPHS} from '@hzblj/kara-native'
|
|
3
|
+
import {DrawableIcon} from '@hzblj/kara-native/jetpack-compose'
|
|
4
|
+
import {useAppTheme} from '@hzblj/kara-theme'
|
|
5
|
+
|
|
6
|
+
import type {GlyphButtonComponent, GlyphButtonProps} from './glyph-button.types'
|
|
7
|
+
|
|
8
|
+
export const GlyphButton: GlyphButtonComponent = ({
|
|
9
|
+
accessibilityLabel,
|
|
10
|
+
disabled = false,
|
|
11
|
+
name,
|
|
12
|
+
onPress,
|
|
13
|
+
}: GlyphButtonProps) => {
|
|
14
|
+
const theme = useAppTheme()
|
|
15
|
+
|
|
16
|
+
return (
|
|
17
|
+
<ComposeIconButton enabled={!disabled} onClick={onPress}>
|
|
18
|
+
<DrawableIcon
|
|
19
|
+
accessibilityLabel={accessibilityLabel}
|
|
20
|
+
iconColor={theme.color(disabled ? 'btn.content.disabled' : 'content.primary')}
|
|
21
|
+
resourceName={GLYPHS[name].android}
|
|
22
|
+
/>
|
|
23
|
+
</ComposeIconButton>
|
|
24
|
+
)
|
|
25
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import {Button} from '@expo/ui/swift-ui'
|
|
2
|
+
import {
|
|
3
|
+
buttonStyle,
|
|
4
|
+
disabled as disabledModifier,
|
|
5
|
+
accessibilityLabel as labelModifier,
|
|
6
|
+
} from '@expo/ui/swift-ui/modifiers'
|
|
7
|
+
import {useMemo} from 'react'
|
|
8
|
+
|
|
9
|
+
import {Glyph} from './glyph'
|
|
10
|
+
import type {GlyphButtonComponent, GlyphButtonProps} from './glyph-button.types'
|
|
11
|
+
|
|
12
|
+
export const GlyphButton: GlyphButtonComponent = ({
|
|
13
|
+
accessibilityLabel,
|
|
14
|
+
disabled = false,
|
|
15
|
+
name,
|
|
16
|
+
onPress,
|
|
17
|
+
}: GlyphButtonProps) => {
|
|
18
|
+
const modifiers = useMemo(() => {
|
|
19
|
+
const list = [buttonStyle('plain')]
|
|
20
|
+
|
|
21
|
+
if (disabled) {
|
|
22
|
+
list.push(disabledModifier(true))
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (accessibilityLabel) {
|
|
26
|
+
list.push(labelModifier(accessibilityLabel))
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return list
|
|
30
|
+
}, [accessibilityLabel, disabled])
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
<Button modifiers={modifiers} onPress={onPress}>
|
|
34
|
+
<Glyph color={disabled ? 'btn.content.disabled' : 'content.primary'} name={name} />
|
|
35
|
+
</Button>
|
|
36
|
+
)
|
|
37
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type {GlyphName} from '@hzblj/kara-native'
|
|
2
|
+
import type {ReactNode} from 'react'
|
|
3
|
+
|
|
4
|
+
/** An icon button over one of kara's glyphs — for the controls its own components build (a stepper, a bar). */
|
|
5
|
+
export type GlyphButtonProps = {
|
|
6
|
+
accessibilityLabel?: string
|
|
7
|
+
disabled?: boolean
|
|
8
|
+
name: GlyphName
|
|
9
|
+
onPress?: () => void
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export type GlyphButtonComponent = (props: GlyphButtonProps) => ReactNode
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import {GLYPHS} from '@hzblj/kara-native'
|
|
2
|
+
import {DrawableIcon} from '@hzblj/kara-native/jetpack-compose'
|
|
3
|
+
import {spacing, useAppTheme} from '@hzblj/kara-theme'
|
|
4
|
+
|
|
5
|
+
import type {GlyphComponent, GlyphProps} from './glyph.types'
|
|
6
|
+
|
|
7
|
+
/** The Material Symbol `@hzblj/kara-native` ships as a drawable — inside a Compose host. */
|
|
8
|
+
export const Glyph: GlyphComponent = ({color = 'content.primary', name, size = 's24'}: GlyphProps) => {
|
|
9
|
+
const theme = useAppTheme()
|
|
10
|
+
|
|
11
|
+
return <DrawableIcon iconColor={theme.color(color)} iconSize={spacing[size]} resourceName={GLYPHS[name].android} />
|
|
12
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import {Image} from '@expo/ui/swift-ui'
|
|
2
|
+
import {accessibilityHidden} from '@expo/ui/swift-ui/modifiers'
|
|
3
|
+
import {GLYPHS} from '@hzblj/kara-native'
|
|
4
|
+
import {spacing, useAppTheme} from '@hzblj/kara-theme'
|
|
5
|
+
|
|
6
|
+
import type {GlyphComponent, GlyphProps} from './glyph.types'
|
|
7
|
+
|
|
8
|
+
const DECORATIVE = [accessibilityHidden(true)]
|
|
9
|
+
|
|
10
|
+
/** The SF Symbol the system already has — inside a SwiftUI host. */
|
|
11
|
+
export const Glyph: GlyphComponent = ({color = 'content.primary', name, size = 's24'}: GlyphProps) => {
|
|
12
|
+
const theme = useAppTheme()
|
|
13
|
+
|
|
14
|
+
return <Image color={theme.color(color)} modifiers={DECORATIVE} size={spacing[size]} systemName={GLYPHS[name].ios} />
|
|
15
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type {GlyphName} from '@hzblj/kara-native'
|
|
2
|
+
import type {ColorToken, SpaceSize} from '@hzblj/kara-theme'
|
|
3
|
+
import type {ReactNode} from 'react'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* One of the few glyphs kara's own components draw — a search field's magnifier, a row's chevron. Internal: apps draw
|
|
7
|
+
* their own icons with `Icon` / `RnIcon`.
|
|
8
|
+
*/
|
|
9
|
+
export type GlyphProps = {
|
|
10
|
+
color?: ColorToken
|
|
11
|
+
name: GlyphName
|
|
12
|
+
size?: SpaceSize
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export type GlyphComponent = (props: GlyphProps) => ReactNode
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import {GLYPHS} from '@hzblj/kara-native'
|
|
2
|
+
import {IconView} from '@hzblj/kara-native/jetpack-compose'
|
|
3
|
+
import {spacing, useAppTheme} from '@hzblj/kara-theme'
|
|
4
|
+
import {useMemo} from 'react'
|
|
5
|
+
|
|
6
|
+
import type {GlyphComponent, GlyphProps} from './glyph.types'
|
|
7
|
+
|
|
8
|
+
/** The Material Symbol drawable in an `ImageView` — the React Native tier. */
|
|
9
|
+
export const RnGlyph: GlyphComponent = ({color = 'content.primary', name, size = 's24'}: GlyphProps) => {
|
|
10
|
+
const theme = useAppTheme()
|
|
11
|
+
const style = useMemo(() => ({height: spacing[size], width: spacing[size]}), [size])
|
|
12
|
+
|
|
13
|
+
return <IconView iconColor={theme.color(color)} resourceName={GLYPHS[name].android} style={style} />
|
|
14
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import {GLYPHS} from '@hzblj/kara-native'
|
|
2
|
+
import {IconView} from '@hzblj/kara-native/swift-ui'
|
|
3
|
+
import {spacing, useAppTheme} from '@hzblj/kara-theme'
|
|
4
|
+
import {useMemo} from 'react'
|
|
5
|
+
|
|
6
|
+
import type {GlyphComponent, GlyphProps} from './glyph.types'
|
|
7
|
+
|
|
8
|
+
/** The SF Symbol in a `UIImageView`, drawn at the size `Glyph` gives it inside a host — the React Native tier. */
|
|
9
|
+
export const RnGlyph: GlyphComponent = ({color = 'content.primary', name, size = 's24'}: GlyphProps) => {
|
|
10
|
+
const theme = useAppTheme()
|
|
11
|
+
const style = useMemo(() => ({height: spacing[size], width: spacing[size]}), [size])
|
|
12
|
+
|
|
13
|
+
return (
|
|
14
|
+
<IconView iconColor={theme.color(color)} style={style} symbolSize={spacing[size]} systemName={GLYPHS[name].ios} />
|
|
15
|
+
)
|
|
16
|
+
}
|
|
@@ -2,7 +2,7 @@ import {AnimatedVisibility, Column, Text as ComposeText, Row} from '@expo/ui/jet
|
|
|
2
2
|
import {clickable} from '@expo/ui/jetpack-compose/modifiers'
|
|
3
3
|
import {useAppTheme} from '@hzblj/kara-theme'
|
|
4
4
|
import {useMemo} from 'react'
|
|
5
|
-
import {
|
|
5
|
+
import {Glyph} from '../../glyph'
|
|
6
6
|
import {useHostGuard} from '../../host-context'
|
|
7
7
|
import type {CollapsibleComponent, CollapsibleProps} from './collapsible.types'
|
|
8
8
|
|
|
@@ -17,7 +17,7 @@ export const Collapsible: CollapsibleComponent = ({children, expanded, label, on
|
|
|
17
17
|
<ComposeText color={theme.colorString('content.primary')} style={theme.typography.body}>
|
|
18
18
|
{label}
|
|
19
19
|
</ComposeText>
|
|
20
|
-
<
|
|
20
|
+
<Glyph name={expanded ? 'chevronDown' : 'chevronRight'} size="s20" />
|
|
21
21
|
</Row>
|
|
22
22
|
<AnimatedVisibility visible={expanded}>{children}</AnimatedVisibility>
|
|
23
23
|
</Column>
|
|
@@ -2,6 +2,7 @@ import {HStack} from '../../atoms/h-stack'
|
|
|
2
2
|
import {Icon} from '../../atoms/icon'
|
|
3
3
|
import {Spacer} from '../../atoms/spacer'
|
|
4
4
|
import {Text} from '../../atoms/text'
|
|
5
|
+
import {Glyph} from '../../glyph'
|
|
5
6
|
import type {LabeledContentComponent, LabeledContentProps} from './labeled-content.types'
|
|
6
7
|
|
|
7
8
|
const TrailingValue = ({value}: {value: string}) => (
|
|
@@ -23,6 +24,6 @@ export const LabeledContent: LabeledContentComponent = ({
|
|
|
23
24
|
<Text variant="body">{label}</Text>
|
|
24
25
|
<Spacer />
|
|
25
26
|
{children ?? (value === undefined ? null : <TrailingValue value={value} />)}
|
|
26
|
-
{onPress ? <
|
|
27
|
+
{onPress ? <Glyph color="content.quaternary" name="chevronRight" size="s16" /> : null}
|
|
27
28
|
</HStack>
|
|
28
29
|
)
|
|
@@ -3,6 +3,7 @@ import {Icon} from '../../atoms/icon'
|
|
|
3
3
|
import {Spacer} from '../../atoms/spacer'
|
|
4
4
|
import {Text} from '../../atoms/text'
|
|
5
5
|
import {VStack} from '../../atoms/v-stack'
|
|
6
|
+
import {Glyph} from '../../glyph'
|
|
6
7
|
import type {ListItemComponent, ListItemProps} from './list-item.types'
|
|
7
8
|
|
|
8
9
|
export const ListItem: ListItemComponent = ({icon, onPress, subtitle, testID, title}: ListItemProps) => (
|
|
@@ -17,6 +18,6 @@ export const ListItem: ListItemComponent = ({icon, onPress, subtitle, testID, ti
|
|
|
17
18
|
) : null}
|
|
18
19
|
</VStack>
|
|
19
20
|
<Spacer />
|
|
20
|
-
{onPress ? <
|
|
21
|
+
{onPress ? <Glyph color="content.quaternary" name="chevronRight" size="s16" /> : null}
|
|
21
22
|
</HStack>
|
|
22
23
|
)
|
|
@@ -1,21 +1,28 @@
|
|
|
1
1
|
import {HStack} from '../../atoms/h-stack'
|
|
2
|
-
import {IconButton} from '../../atoms/icon-button'
|
|
3
2
|
import {Island} from '../../atoms/island'
|
|
4
3
|
import {Spacer} from '../../atoms/spacer'
|
|
5
4
|
import {Text} from '../../atoms/text'
|
|
5
|
+
import {GlyphButton} from '../../glyph'
|
|
6
6
|
import type {NavigationBarComponent, NavigationBarProps} from './navigation-bar.types'
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Material's top bar shape — navigation icon, start-aligned title, action at the end — built from the atoms in its own
|
|
10
10
|
* island. Compose's icon buttons take no accessibility identifier, so `backTestID`/`closeTestID` are iOS-only.
|
|
11
11
|
*/
|
|
12
|
-
export const NavigationBar: NavigationBarComponent = ({
|
|
12
|
+
export const NavigationBar: NavigationBarComponent = ({
|
|
13
|
+
backLabel = 'Back',
|
|
14
|
+
closeLabel = 'Close',
|
|
15
|
+
onBack,
|
|
16
|
+
onClose,
|
|
17
|
+
testID,
|
|
18
|
+
title,
|
|
19
|
+
}: NavigationBarProps) => (
|
|
13
20
|
<Island testID={testID}>
|
|
14
21
|
<HStack align="center" px="s4" spacing="s4" wide>
|
|
15
|
-
{onBack ? <
|
|
22
|
+
{onBack ? <GlyphButton accessibilityLabel={backLabel} name="back" onPress={onBack} /> : null}
|
|
16
23
|
{title ? <Text variant="body">{title}</Text> : null}
|
|
17
24
|
<Spacer />
|
|
18
|
-
{onClose ? <
|
|
25
|
+
{onClose ? <GlyphButton accessibilityLabel={closeLabel} name="close" onPress={onClose} /> : null}
|
|
19
26
|
</HStack>
|
|
20
27
|
</Island>
|
|
21
28
|
)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {Text as ComposeText, RadioButton, Row} from '@expo/ui/jetpack-compose'
|
|
2
|
+
import {clickable, fillMaxWidth} from '@expo/ui/jetpack-compose/modifiers'
|
|
2
3
|
import {useAppTheme} from '@hzblj/kara-theme'
|
|
3
4
|
import {VStack} from '../../atoms/v-stack'
|
|
4
5
|
import {useHostGuard} from '../../host-context'
|
|
@@ -12,8 +13,16 @@ export const RadioGroup: RadioGroupComponent = ({onValueChange, options, value}:
|
|
|
12
13
|
return (
|
|
13
14
|
<VStack spacing="s4" wide>
|
|
14
15
|
{options.map(option => (
|
|
15
|
-
<Row
|
|
16
|
-
|
|
16
|
+
<Row
|
|
17
|
+
key={option.value}
|
|
18
|
+
modifiers={[fillMaxWidth(), clickable(() => onValueChange?.(option.value))]}
|
|
19
|
+
verticalAlignment="center"
|
|
20
|
+
>
|
|
21
|
+
<RadioButton
|
|
22
|
+
colors={{selectedColor: theme.color('fill.accent.primary')}}
|
|
23
|
+
onClick={() => onValueChange?.(option.value)}
|
|
24
|
+
selected={option.value === value}
|
|
25
|
+
/>
|
|
17
26
|
<ComposeText color={theme.colorString('content.primary')} style={theme.typography.body}>
|
|
18
27
|
{option.label}
|
|
19
28
|
</ComposeText>
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {HStack} from '../../atoms/h-stack'
|
|
2
|
-
import {Icon} from '../../atoms/icon'
|
|
3
2
|
import {Spacer} from '../../atoms/spacer'
|
|
4
3
|
import {Text} from '../../atoms/text'
|
|
5
4
|
import {VStack} from '../../atoms/v-stack'
|
|
5
|
+
import {Glyph} from '../../glyph'
|
|
6
6
|
import {useHostGuard} from '../../host-context'
|
|
7
7
|
import type {RadioGroupComponent, RadioGroupProps} from './radio-group.types'
|
|
8
8
|
|
|
@@ -15,7 +15,7 @@ export const RadioGroup: RadioGroupComponent = ({onValueChange, options, value}:
|
|
|
15
15
|
<HStack align="center" key={option.value} onPress={() => onValueChange?.(option.value)} py="s8" wide>
|
|
16
16
|
<Text>{option.label}</Text>
|
|
17
17
|
<Spacer />
|
|
18
|
-
{option.value === value ? <
|
|
18
|
+
{option.value === value ? <Glyph color="content.accent" name="check" size="s20" /> : null}
|
|
19
19
|
</HStack>
|
|
20
20
|
))}
|
|
21
21
|
</VStack>
|
|
@@ -7,6 +7,9 @@ export type {ScrollEdgeEffect, ScrollEdgeScrollableProps} from '@hzblj/kara-nati
|
|
|
7
7
|
/**
|
|
8
8
|
* Bars over one React Native scroll view, with the iOS 26 scroll edge effect under them — the system's progressive
|
|
9
9
|
* blur where content scrolls past a bar. The React Native tier: it needs no host.
|
|
10
|
+
*
|
|
11
|
+
* A screen-level container: wrap the screen's scroll view with it. Mounted inside a cell of a virtualized list on iOS
|
|
12
|
+
* it draws only its bottom bar — the hosted scroll view and the top bar stay blank.
|
|
10
13
|
*/
|
|
11
14
|
export type ScrollEdgeContainerProps = ResponsiveViewSx & {
|
|
12
15
|
/**
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {useAppTheme} from '@hzblj/kara-theme'
|
|
2
2
|
import {TextInput} from 'react-native'
|
|
3
3
|
|
|
4
4
|
import {Box} from '../../atoms/box'
|
|
5
|
-
import {Icon} from '../../atoms/icon'
|
|
6
|
-
import {Island} from '../../atoms/island'
|
|
7
5
|
import {Pressable} from '../../atoms/pressable'
|
|
6
|
+
import {RnGlyph} from '../../glyph'
|
|
8
7
|
import type {SearchBarComponent, SearchBarProps} from './search-bar.types'
|
|
9
8
|
|
|
10
9
|
export const SearchBar: SearchBarComponent = ({
|
|
@@ -27,9 +26,7 @@ export const SearchBar: SearchBarComponent = ({
|
|
|
27
26
|
testID={testID}
|
|
28
27
|
wide
|
|
29
28
|
>
|
|
30
|
-
<
|
|
31
|
-
<Icon color="content.tertiary" name="search" size="s20" />
|
|
32
|
-
</Island>
|
|
29
|
+
<RnGlyph color="content.tertiary" name="search" size="s20" />
|
|
33
30
|
<TextInput
|
|
34
31
|
onChangeText={onChangeText}
|
|
35
32
|
placeholder={placeholder}
|
|
@@ -39,9 +36,7 @@ export const SearchBar: SearchBarComponent = ({
|
|
|
39
36
|
/>
|
|
40
37
|
{value.length > 0 ? (
|
|
41
38
|
<Pressable onPress={() => onChangeText?.('')}>
|
|
42
|
-
<
|
|
43
|
-
<Icon color="content.tertiary" name="close" size="s20" />
|
|
44
|
-
</Island>
|
|
39
|
+
<RnGlyph color="content.tertiary" name="close" size="s20" />
|
|
45
40
|
</Pressable>
|
|
46
41
|
) : null}
|
|
47
42
|
</Box>
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {useCallback} from 'react'
|
|
2
2
|
import {HStack} from '../../atoms/h-stack'
|
|
3
|
-
import {IconButton} from '../../atoms/icon-button'
|
|
4
3
|
import {Spacer} from '../../atoms/spacer'
|
|
5
4
|
import {Text} from '../../atoms/text'
|
|
5
|
+
import {GlyphButton} from '../../glyph'
|
|
6
6
|
import {useHostGuard} from '../../host-context'
|
|
7
7
|
import type {StepperComponent, StepperProps} from './stepper.types'
|
|
8
8
|
|
|
@@ -23,9 +23,9 @@ export const Stepper: StepperComponent = ({
|
|
|
23
23
|
<HStack align="center" spacing="s8" wide>
|
|
24
24
|
<Text>{label}</Text>
|
|
25
25
|
<Spacer />
|
|
26
|
-
<
|
|
26
|
+
<GlyphButton accessibilityLabel="Decrement" disabled={value <= min} name="minus" onPress={onDecrement} />
|
|
27
27
|
<Text variant="labelMedium">{String(value)}</Text>
|
|
28
|
-
<
|
|
28
|
+
<GlyphButton accessibilityLabel="Increment" disabled={value >= max} name="plus" onPress={onIncrement} />
|
|
29
29
|
</HStack>
|
|
30
30
|
)
|
|
31
31
|
}
|