@hzblj/kara-components 0.6.0 → 0.8.0
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 +91 -0
- package/README.md +31 -3
- package/lib/module/atoms/activity-indicator/activity-indicator.android.js +42 -0
- package/lib/module/atoms/activity-indicator/activity-indicator.android.js.map +1 -0
- package/lib/module/atoms/activity-indicator/activity-indicator.ios.js +19 -0
- package/lib/module/atoms/activity-indicator/activity-indicator.ios.js.map +1 -0
- package/lib/module/atoms/activity-indicator/activity-indicator.types.js +4 -0
- package/lib/module/atoms/activity-indicator/activity-indicator.types.js.map +1 -0
- package/lib/module/atoms/activity-indicator/index.js +2 -1
- package/lib/module/atoms/activity-indicator/index.js.map +1 -1
- package/lib/module/atoms/avatar/avatar.js +2 -4
- package/lib/module/atoms/avatar/avatar.js.map +1 -1
- package/lib/module/atoms/blur-view/blur-view.android.js +100 -0
- package/lib/module/atoms/blur-view/blur-view.android.js.map +1 -0
- package/lib/module/atoms/blur-view/blur-view.ios.js +43 -0
- package/lib/module/atoms/blur-view/blur-view.ios.js.map +1 -0
- package/lib/module/atoms/blur-view/blur-view.types.js +4 -0
- package/lib/module/atoms/blur-view/blur-view.types.js.map +1 -0
- package/lib/module/atoms/blur-view/index.js +5 -0
- package/lib/module/atoms/blur-view/index.js.map +1 -0
- package/lib/module/atoms/checkbox/checkbox.android.js +7 -3
- package/lib/module/atoms/checkbox/checkbox.android.js.map +1 -1
- package/lib/module/atoms/date-picker/date-picker.ios.js +32 -11
- package/lib/module/atoms/date-picker/date-picker.ios.js.map +1 -1
- package/lib/module/atoms/glass-view/glass-view.android.js +36 -5
- package/lib/module/atoms/glass-view/glass-view.android.js.map +1 -1
- package/lib/module/atoms/image/image.js +13 -6
- package/lib/module/atoms/image/image.js.map +1 -1
- package/lib/module/atoms/image/image.types.js +4 -0
- package/lib/module/atoms/image/image.types.js.map +1 -0
- package/lib/module/atoms/image/index.js +1 -0
- package/lib/module/atoms/image/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/island/island.android.js +6 -2
- package/lib/module/atoms/island/island.android.js.map +1 -1
- package/lib/module/atoms/island/island.ios.js +5 -2
- package/lib/module/atoms/island/island.ios.js.map +1 -1
- package/lib/module/atoms/pressable/pressable.js +38 -6
- package/lib/module/atoms/pressable/pressable.js.map +1 -1
- package/lib/module/atoms/rn-flat-list/rn-flat-list.js +10 -9
- package/lib/module/atoms/rn-flat-list/rn-flat-list.js.map +1 -1
- package/lib/module/atoms/rn-section-list/rn-section-list.js +5 -8
- package/lib/module/atoms/rn-section-list/rn-section-list.js.map +1 -1
- package/lib/module/atoms/rn-text/rn-text.js +5 -2
- package/lib/module/atoms/rn-text/rn-text.js.map +1 -1
- package/lib/module/atoms/segmented-control/index.js +1 -1
- package/lib/module/atoms/segmented-control/index.js.map +1 -1
- package/lib/module/atoms/segmented-control/segmented-control.android.js +74 -0
- package/lib/module/atoms/segmented-control/segmented-control.android.js.map +1 -0
- package/lib/module/atoms/segmented-control/segmented-control.ios.js +44 -0
- package/lib/module/atoms/segmented-control/segmented-control.ios.js.map +1 -0
- package/lib/module/atoms/skeleton/skeleton.js +5 -5
- package/lib/module/atoms/skeleton/skeleton.js.map +1 -1
- package/lib/module/atoms/switch/switch.android.js +4 -1
- package/lib/module/atoms/switch/switch.android.js.map +1 -1
- package/lib/module/atoms/text/text.android.js +5 -2
- package/lib/module/atoms/text/text.android.js.map +1 -1
- package/lib/module/atoms/text/text.ios.js +14 -3
- package/lib/module/atoms/text/text.ios.js.map +1 -1
- package/lib/module/molecules/collapsible/collapsible.android.js +37 -7
- package/lib/module/molecules/collapsible/collapsible.android.js.map +1 -1
- package/lib/module/molecules/navigation-bar/navigation-bar.android.js +2 -8
- package/lib/module/molecules/navigation-bar/navigation-bar.android.js.map +1 -1
- package/lib/module/molecules/pager/pager.android.js +5 -4
- package/lib/module/molecules/pager/pager.android.js.map +1 -1
- package/lib/module/molecules/scroll-edge-container/scroll-edge-container.android.js +114 -11
- package/lib/module/molecules/scroll-edge-container/scroll-edge-container.android.js.map +1 -1
- package/lib/module/molecules/search-bar/search-bar.js +15 -2
- package/lib/module/molecules/search-bar/search-bar.js.map +1 -1
- package/lib/module/molecules/stepper/stepper.ios.js +45 -8
- package/lib/module/molecules/stepper/stepper.ios.js.map +1 -1
- package/lib/module/molecules/tooltip/tooltip.android.js +16 -5
- package/lib/module/molecules/tooltip/tooltip.android.js.map +1 -1
- package/lib/module/organisms/action-sheet/action-sheet.android.js +41 -20
- package/lib/module/organisms/action-sheet/action-sheet.android.js.map +1 -1
- package/lib/module/organisms/action-sheet/action-sheet.ios.js +24 -8
- package/lib/module/organisms/action-sheet/action-sheet.ios.js.map +1 -1
- package/lib/module/organisms/alert/alert.ios.js +15 -2
- package/lib/module/organisms/alert/alert.ios.js.map +1 -1
- package/lib/module/organisms/form/form.android.js +22 -9
- package/lib/module/organisms/form/form.android.js.map +1 -1
- package/lib/module/organisms/swipe-actions/swipe-actions.android.js +125 -11
- package/lib/module/organisms/swipe-actions/swipe-actions.android.js.map +1 -1
- package/lib/module/organisms/swipe-actions/swipe-actions.ios.js +46 -18
- package/lib/module/organisms/swipe-actions/swipe-actions.ios.js.map +1 -1
- package/lib/module/ripple-clip.js +9 -1
- package/lib/module/ripple-clip.js.map +1 -1
- package/lib/module/templates/screen/screen.android.js +31 -10
- package/lib/module/templates/screen/screen.android.js.map +1 -1
- package/lib/typescript/atoms/activity-indicator/activity-indicator.d.ts +1 -3
- package/lib/typescript/atoms/activity-indicator/activity-indicator.ios.d.ts +3 -0
- package/lib/typescript/atoms/activity-indicator/activity-indicator.types.d.ts +17 -0
- package/lib/typescript/atoms/activity-indicator/index.d.ts +1 -0
- package/lib/typescript/atoms/avatar/avatar.types.d.ts +5 -0
- package/lib/typescript/atoms/badge/badge.types.d.ts +3 -0
- package/lib/typescript/atoms/blur-view/blur-view.d.ts +1 -0
- package/lib/typescript/atoms/blur-view/blur-view.ios.d.ts +3 -0
- package/lib/typescript/atoms/blur-view/blur-view.types.d.ts +31 -0
- package/lib/typescript/atoms/blur-view/index.d.ts +2 -0
- package/lib/typescript/atoms/box/a-box.d.ts +1 -1
- package/lib/typescript/atoms/button/button.types.d.ts +12 -0
- package/lib/typescript/atoms/card/card.types.d.ts +6 -0
- package/lib/typescript/atoms/checkbox/checkbox.types.d.ts +5 -0
- package/lib/typescript/atoms/chip/chip.types.d.ts +5 -0
- package/lib/typescript/atoms/color-picker/color-picker.types.d.ts +4 -0
- package/lib/typescript/atoms/date-picker/date-picker.ios.d.ts +6 -1
- package/lib/typescript/atoms/date-picker/date-picker.types.d.ts +14 -0
- package/lib/typescript/atoms/divider/divider.types.d.ts +3 -0
- package/lib/typescript/atoms/fab/fab.types.d.ts +7 -0
- package/lib/typescript/atoms/glass-view/glass-view.types.d.ts +13 -5
- package/lib/typescript/atoms/h-stack/h-stack.types.d.ts +6 -0
- package/lib/typescript/atoms/icon/icon.types.d.ts +8 -0
- package/lib/typescript/atoms/icon-button/icon-button.types.d.ts +5 -0
- package/lib/typescript/atoms/image/image.d.ts +12 -4
- package/lib/typescript/atoms/image/image.types.d.ts +4 -0
- package/lib/typescript/atoms/image/index.d.ts +1 -0
- package/lib/typescript/atoms/index.d.ts +1 -1
- package/lib/typescript/atoms/island/island.types.d.ts +10 -2
- package/lib/typescript/atoms/list/list.types.d.ts +2 -0
- package/lib/typescript/atoms/picker/picker.types.d.ts +12 -0
- package/lib/typescript/atoms/pressable/pressable.types.d.ts +10 -0
- package/lib/typescript/atoms/progress/progress.types.d.ts +6 -0
- package/lib/typescript/atoms/rn-flat-list/rn-flat-list.d.ts +5 -8
- package/lib/typescript/atoms/rn-flat-list/rn-flat-list.types.d.ts +3 -1
- package/lib/typescript/atoms/rn-scroll-view/rn-scroll-view.types.d.ts +4 -0
- package/lib/typescript/atoms/rn-section-list/rn-section-list.d.ts +2 -8
- package/lib/typescript/atoms/rn-section-list/rn-section-list.types.d.ts +3 -1
- package/lib/typescript/atoms/rn-text/rn-text.types.d.ts +10 -1
- package/lib/typescript/atoms/rn-view/rn-view.types.d.ts +2 -0
- package/lib/typescript/atoms/scroll-view/scroll-view.types.d.ts +4 -0
- package/lib/typescript/atoms/segmented-control/segmented-control.d.ts +1 -6
- package/lib/typescript/atoms/segmented-control/segmented-control.ios.d.ts +7 -0
- package/lib/typescript/atoms/segmented-control/segmented-control.types.d.ts +13 -0
- package/lib/typescript/atoms/skeleton/skeleton.types.d.ts +11 -2
- package/lib/typescript/atoms/slider/slider.types.d.ts +7 -0
- package/lib/typescript/atoms/spacer/spacer.types.d.ts +3 -0
- package/lib/typescript/atoms/surface/surface.types.d.ts +7 -0
- package/lib/typescript/atoms/switch/switch.types.d.ts +8 -0
- package/lib/typescript/atoms/text/text.types.d.ts +18 -1
- package/lib/typescript/atoms/text-field/text-field.types.d.ts +12 -0
- package/lib/typescript/atoms/v-stack/v-stack.types.d.ts +9 -0
- package/lib/typescript/atoms/z-stack/z-stack.types.d.ts +8 -0
- package/lib/typescript/molecules/collapsible/collapsible.types.d.ts +8 -0
- package/lib/typescript/molecules/empty-state/empty-state.types.d.ts +5 -0
- package/lib/typescript/molecules/label/label.types.d.ts +6 -0
- package/lib/typescript/molecules/labeled-content/labeled-content.types.d.ts +6 -0
- package/lib/typescript/molecules/link/link.types.d.ts +6 -0
- package/lib/typescript/molecules/list-item/list-item.types.d.ts +9 -0
- package/lib/typescript/molecules/navigation-bar/navigation-bar.types.d.ts +8 -0
- package/lib/typescript/molecules/pager/pager.types.d.ts +2 -0
- package/lib/typescript/molecules/radio-group/radio-group.types.d.ts +10 -0
- package/lib/typescript/molecules/rn-list-item/rn-list-item.types.d.ts +1 -1
- package/lib/typescript/molecules/rn-tooltip/rn-tooltip.types.d.ts +11 -0
- package/lib/typescript/molecules/scroll-edge-container/scroll-edge-container.types.d.ts +7 -2
- package/lib/typescript/molecules/search-bar/search-bar.types.d.ts +8 -0
- package/lib/typescript/molecules/stepper/stepper.ios.d.ts +5 -0
- package/lib/typescript/molecules/stepper/stepper.types.d.ts +10 -0
- package/lib/typescript/molecules/tooltip/tooltip.types.d.ts +12 -0
- package/lib/typescript/organisms/action-sheet/action-sheet.types.d.ts +8 -0
- package/lib/typescript/organisms/alert/alert.types.d.ts +11 -0
- package/lib/typescript/organisms/context-menu/context-menu.types.d.ts +4 -0
- package/lib/typescript/organisms/fab-menu/fab-menu.types.d.ts +2 -0
- package/lib/typescript/organisms/form/form.types.d.ts +6 -0
- package/lib/typescript/organisms/menu/menu.types.d.ts +17 -0
- package/lib/typescript/organisms/sheet/sheet.types.d.ts +19 -0
- package/lib/typescript/organisms/snackbar/snackbar.types.d.ts +8 -0
- package/lib/typescript/organisms/swipe-actions/swipe-actions.types.d.ts +36 -13
- package/lib/typescript/templates/screen/screen.types.d.ts +9 -0
- package/package.json +5 -7
- package/src/atoms/activity-indicator/activity-indicator.android.tsx +32 -0
- package/src/atoms/activity-indicator/activity-indicator.ios.tsx +15 -0
- package/src/atoms/activity-indicator/activity-indicator.types.ts +20 -0
- package/src/atoms/activity-indicator/index.ts +1 -0
- package/src/atoms/avatar/avatar.tsx +1 -1
- package/src/atoms/avatar/avatar.types.ts +5 -0
- package/src/atoms/badge/badge.types.ts +3 -0
- package/src/atoms/blur-view/blur-view.android.tsx +68 -0
- package/src/atoms/blur-view/blur-view.ios.tsx +37 -0
- package/src/atoms/blur-view/blur-view.types.ts +34 -0
- package/src/atoms/blur-view/index.ts +2 -0
- package/src/atoms/button/button.types.ts +12 -0
- package/src/atoms/card/card.types.ts +6 -0
- package/src/atoms/checkbox/checkbox.android.tsx +7 -3
- package/src/atoms/checkbox/checkbox.types.ts +5 -0
- package/src/atoms/chip/chip.types.ts +5 -0
- package/src/atoms/color-picker/color-picker.types.ts +4 -0
- package/src/atoms/date-picker/date-picker.ios.tsx +33 -13
- package/src/atoms/date-picker/date-picker.types.ts +14 -0
- package/src/atoms/divider/divider.types.ts +3 -0
- package/src/atoms/fab/fab.types.ts +7 -0
- package/src/atoms/glass-view/glass-view.android.tsx +41 -3
- package/src/atoms/glass-view/glass-view.types.ts +13 -5
- package/src/atoms/h-stack/h-stack.types.ts +6 -0
- package/src/atoms/icon/icon.types.ts +8 -0
- package/src/atoms/icon-button/icon-button.types.ts +5 -0
- package/src/atoms/image/image.tsx +11 -12
- package/src/atoms/image/image.types.ts +6 -0
- package/src/atoms/image/index.ts +1 -0
- package/src/atoms/index.ts +1 -1
- package/src/atoms/island/island.android.tsx +10 -2
- package/src/atoms/island/island.ios.tsx +4 -2
- package/src/atoms/island/island.types.ts +10 -2
- package/src/atoms/list/list.types.ts +2 -0
- package/src/atoms/picker/picker.types.ts +12 -0
- package/src/atoms/pressable/pressable.tsx +46 -6
- package/src/atoms/pressable/pressable.types.ts +10 -0
- package/src/atoms/progress/progress.types.ts +6 -0
- package/src/atoms/rn-flat-list/rn-flat-list.tsx +8 -8
- package/src/atoms/rn-flat-list/rn-flat-list.types.ts +3 -1
- package/src/atoms/rn-scroll-view/rn-scroll-view.types.ts +4 -0
- package/src/atoms/rn-section-list/rn-section-list.tsx +5 -8
- package/src/atoms/rn-section-list/rn-section-list.types.ts +3 -1
- package/src/atoms/rn-text/rn-text.tsx +6 -3
- package/src/atoms/rn-text/rn-text.types.ts +15 -5
- package/src/atoms/rn-view/rn-view.types.ts +2 -0
- package/src/atoms/scroll-view/scroll-view.types.ts +4 -0
- package/src/atoms/segmented-control/segmented-control.android.tsx +79 -0
- package/src/atoms/segmented-control/segmented-control.ios.tsx +47 -0
- package/src/atoms/segmented-control/segmented-control.types.ts +13 -0
- package/src/atoms/skeleton/skeleton.tsx +4 -4
- package/src/atoms/skeleton/skeleton.types.ts +11 -2
- package/src/atoms/slider/slider.types.ts +7 -0
- package/src/atoms/spacer/spacer.types.ts +3 -0
- package/src/atoms/surface/surface.types.ts +7 -0
- package/src/atoms/switch/switch.android.tsx +4 -1
- package/src/atoms/switch/switch.types.ts +8 -0
- package/src/atoms/text/text.android.tsx +7 -1
- package/src/atoms/text/text.ios.tsx +14 -3
- package/src/atoms/text/text.types.ts +18 -1
- package/src/atoms/text-field/text-field.types.ts +12 -0
- package/src/atoms/v-stack/v-stack.types.ts +9 -0
- package/src/atoms/z-stack/z-stack.types.ts +8 -0
- package/src/molecules/collapsible/collapsible.android.tsx +47 -7
- package/src/molecules/collapsible/collapsible.types.ts +8 -0
- package/src/molecules/empty-state/empty-state.types.ts +5 -0
- package/src/molecules/label/label.types.ts +6 -0
- package/src/molecules/labeled-content/labeled-content.types.ts +6 -0
- package/src/molecules/link/link.types.ts +6 -0
- package/src/molecules/list-item/list-item.types.ts +9 -0
- package/src/molecules/navigation-bar/navigation-bar.android.tsx +1 -6
- package/src/molecules/navigation-bar/navigation-bar.types.ts +8 -0
- package/src/molecules/pager/pager.android.tsx +4 -1
- package/src/molecules/pager/pager.types.ts +2 -0
- package/src/molecules/radio-group/radio-group.types.ts +10 -0
- package/src/molecules/rn-list-item/rn-list-item.types.ts +1 -1
- package/src/molecules/rn-tooltip/rn-tooltip.types.ts +11 -0
- package/src/molecules/scroll-edge-container/scroll-edge-container.android.tsx +103 -10
- package/src/molecules/scroll-edge-container/scroll-edge-container.types.ts +7 -2
- package/src/molecules/search-bar/search-bar.tsx +9 -2
- package/src/molecules/search-bar/search-bar.types.ts +8 -0
- package/src/molecules/stepper/stepper.ios.tsx +37 -1
- package/src/molecules/stepper/stepper.types.ts +10 -0
- package/src/molecules/tooltip/tooltip.android.tsx +17 -9
- package/src/molecules/tooltip/tooltip.types.ts +12 -0
- package/src/organisms/action-sheet/action-sheet.android.tsx +37 -19
- package/src/organisms/action-sheet/action-sheet.ios.tsx +22 -9
- package/src/organisms/action-sheet/action-sheet.types.ts +8 -0
- package/src/organisms/alert/alert.ios.tsx +11 -1
- package/src/organisms/alert/alert.types.ts +11 -0
- package/src/organisms/context-menu/context-menu.types.ts +4 -0
- package/src/organisms/fab-menu/fab-menu.types.ts +2 -0
- package/src/organisms/form/form.android.tsx +15 -7
- package/src/organisms/form/form.types.ts +6 -0
- package/src/organisms/menu/menu.types.ts +17 -0
- package/src/organisms/sheet/sheet.types.ts +19 -0
- package/src/organisms/snackbar/snackbar.types.ts +8 -0
- package/src/organisms/swipe-actions/swipe-actions.android.tsx +129 -9
- package/src/organisms/swipe-actions/swipe-actions.ios.tsx +45 -11
- package/src/organisms/swipe-actions/swipe-actions.types.ts +37 -14
- package/src/ripple-clip.ts +10 -1
- package/src/templates/screen/screen.android.tsx +33 -12
- package/src/templates/screen/screen.types.ts +9 -0
- package/lib/module/atoms/activity-indicator/activity-indicator.js +0 -14
- package/lib/module/atoms/activity-indicator/activity-indicator.js.map +0 -1
- package/lib/module/atoms/flash-list/flash-list.js +0 -31
- package/lib/module/atoms/flash-list/flash-list.js.map +0 -1
- package/lib/module/atoms/flash-list/flash-list.types.js +0 -4
- package/lib/module/atoms/flash-list/flash-list.types.js.map +0 -1
- package/lib/module/atoms/flash-list/index.js +0 -5
- package/lib/module/atoms/flash-list/index.js.map +0 -1
- package/lib/module/atoms/segmented-control/segmented-control.js +0 -40
- package/lib/module/atoms/segmented-control/segmented-control.js.map +0 -1
- package/lib/typescript/atoms/flash-list/flash-list.d.ts +0 -8
- package/lib/typescript/atoms/flash-list/flash-list.types.d.ts +0 -18
- package/lib/typescript/atoms/flash-list/index.d.ts +0 -2
- package/src/atoms/activity-indicator/activity-indicator.tsx +0 -9
- package/src/atoms/flash-list/flash-list.tsx +0 -28
- package/src/atoms/flash-list/flash-list.types.ts +0 -20
- package/src/atoms/flash-list/index.ts +0 -2
- package/src/atoms/segmented-control/segmented-control.tsx +0 -47
|
@@ -1,18 +1,52 @@
|
|
|
1
|
-
import {SwipeActions as SwiftUISwipeActions} from '@expo/ui/swift-ui'
|
|
1
|
+
import {Button, Image, Label, SwipeActions as SwiftUISwipeActions} from '@expo/ui/swift-ui'
|
|
2
|
+
import {tint} from '@expo/ui/swift-ui/modifiers'
|
|
3
|
+
import {iconResourceName} from '@hzblj/kara-native'
|
|
4
|
+
import {useAppTheme} from '@hzblj/kara-theme'
|
|
2
5
|
|
|
3
6
|
import {useHostGuard} from '../../host-context'
|
|
4
|
-
import type {
|
|
7
|
+
import type {SwipeAction, SwipeActionsComponent, SwipeActionsProps} from './swipe-actions.types'
|
|
5
8
|
|
|
6
|
-
|
|
7
|
-
|
|
9
|
+
type ActionsProps = {actions: SwipeAction[]; allowsFullSwipe: boolean; edge: 'leading' | 'trailing'}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* The edge's buttons, a `Label` each — iOS 26 draws its icon on a round button with the title under it; earlier
|
|
13
|
+
* versions, in a row of the usual height, the icon alone. No `destructive` role: SwiftUI would animate the row out by itself, and whether it goes is
|
|
14
|
+
* the list's data to say.
|
|
15
|
+
*/
|
|
16
|
+
const Actions = ({actions, allowsFullSwipe, edge}: ActionsProps) => {
|
|
17
|
+
const theme = useAppTheme()
|
|
8
18
|
|
|
9
|
-
return
|
|
19
|
+
return (
|
|
20
|
+
<SwiftUISwipeActions.Actions allowsFullSwipe={allowsFullSwipe} edge={edge}>
|
|
21
|
+
{actions.map(action => (
|
|
22
|
+
<Button
|
|
23
|
+
key={action.label}
|
|
24
|
+
modifiers={[
|
|
25
|
+
tint(theme.color(action.tint ?? (action.destructive ? 'fill.destructive.primary' : 'fill.accent.primary'))),
|
|
26
|
+
]}
|
|
27
|
+
onPress={action.onPress}
|
|
28
|
+
>
|
|
29
|
+
<Label icon={<Image assetName={iconResourceName(action.icon)} />} title={action.label} />
|
|
30
|
+
</Button>
|
|
31
|
+
))}
|
|
32
|
+
</SwiftUISwipeActions.Actions>
|
|
33
|
+
)
|
|
10
34
|
}
|
|
11
35
|
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
36
|
+
export const SwipeActions: SwipeActionsComponent = ({
|
|
37
|
+
allowsFullSwipe = true,
|
|
38
|
+
children,
|
|
39
|
+
leading = [],
|
|
40
|
+
testID,
|
|
41
|
+
trailing = [],
|
|
42
|
+
}: SwipeActionsProps) => {
|
|
43
|
+
useHostGuard('SwipeActions')
|
|
17
44
|
|
|
18
|
-
|
|
45
|
+
return (
|
|
46
|
+
<SwiftUISwipeActions testID={testID}>
|
|
47
|
+
{children}
|
|
48
|
+
{leading.length > 0 ? <Actions actions={leading} allowsFullSwipe={allowsFullSwipe} edge="leading" /> : null}
|
|
49
|
+
{trailing.length > 0 ? <Actions actions={trailing} allowsFullSwipe={allowsFullSwipe} edge="trailing" /> : null}
|
|
50
|
+
</SwiftUISwipeActions>
|
|
51
|
+
)
|
|
52
|
+
}
|
|
@@ -1,24 +1,47 @@
|
|
|
1
|
+
import type {ColorToken} from '@hzblj/kara-theme'
|
|
1
2
|
import type {ReactNode} from 'react'
|
|
2
3
|
|
|
3
|
-
|
|
4
|
+
import type {IconName} from '../../atoms/icon'
|
|
5
|
+
|
|
6
|
+
/** One button a swiped row uncovers. */
|
|
7
|
+
export type SwipeAction = {
|
|
8
|
+
/** Fills the button with `fill.destructive.primary` unless `tint` says otherwise. */
|
|
9
|
+
destructive?: boolean
|
|
10
|
+
/** One of the app's icons, on the button — a round one on iOS 26, as in Mail, a filled stadium on Android. */
|
|
11
|
+
icon: IconName
|
|
12
|
+
/**
|
|
13
|
+
* The action's name, written under the button — before iOS 26 a row of the usual height shows the icon alone and
|
|
14
|
+
* keeps the label for VoiceOver. Actions are keyed by it, so keep labels unique within one row.
|
|
15
|
+
*/
|
|
16
|
+
label: string
|
|
17
|
+
/** Called when the button is pressed. The row closes by itself. */
|
|
18
|
+
onPress: () => void
|
|
19
|
+
/**
|
|
20
|
+
* The button's fill — `fill.destructive.primary` for a destructive action, `fill.accent.primary` otherwise. The icon
|
|
21
|
+
* on it is white, so pick a fill that holds white in both appearances.
|
|
22
|
+
*/
|
|
23
|
+
tint?: ColorToken
|
|
24
|
+
}
|
|
4
25
|
|
|
5
26
|
/**
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
27
|
+
* A list row with buttons behind it, uncovered by a swipe — SwiftUI's `swipeActions` on iOS, and on Android, where
|
|
28
|
+
* Compose has none, kara's own: the row slides on an anchored drag and the buttons show in the strip it leaves. One
|
|
29
|
+
* row is open at a time on both; a tap on an open row closes it. A native organism — it belongs inside a `List`.
|
|
9
30
|
*/
|
|
10
31
|
export type SwipeActionsProps = {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
export type SwipeActionsGroupProps = {
|
|
16
|
-
/** Whether swiping all the way performs the first action in the group. */
|
|
32
|
+
/**
|
|
33
|
+
* iOS: a swipe all the way across performs the edge's first action, as in Mail. Android has no full swipe. `true`
|
|
34
|
+
* by default, as in SwiftUI.
|
|
35
|
+
*/
|
|
17
36
|
allowsFullSwipe?: boolean
|
|
37
|
+
/** The row. */
|
|
18
38
|
children: ReactNode
|
|
19
|
-
edge
|
|
39
|
+
/** The buttons at the leading edge, uncovered by a swipe toward the trailing one. The first sits outermost. */
|
|
40
|
+
leading?: SwipeAction[]
|
|
41
|
+
/** Test identifier. iOS: on the row. Android: the row is a Compose node, reach it by its content. */
|
|
42
|
+
testID?: string
|
|
43
|
+
/** The buttons at the trailing edge, uncovered by a swipe toward the leading one. The first sits outermost. */
|
|
44
|
+
trailing?: SwipeAction[]
|
|
20
45
|
}
|
|
21
46
|
|
|
22
|
-
export type SwipeActionsComponent = (
|
|
23
|
-
Actions: (props: SwipeActionsGroupProps) => ReactNode
|
|
24
|
-
}
|
|
47
|
+
export type SwipeActionsComponent = (props: SwipeActionsProps) => ReactNode
|
package/src/ripple-clip.ts
CHANGED
|
@@ -23,6 +23,9 @@ const CONTENT_KEYS = new Set<string>([
|
|
|
23
23
|
|
|
24
24
|
const FILL: ViewStyle = {flexGrow: 1}
|
|
25
25
|
|
|
26
|
+
/** What gives the outer view a height of its own, rather than its content's. */
|
|
27
|
+
const SIZING_KEYS = ['aspectRatio', 'flex', 'flexBasis', 'flexGrow', 'height', 'minHeight'] as const
|
|
28
|
+
|
|
26
29
|
/**
|
|
27
30
|
* Splits a resolved style for a pressable with an Android ripple. The ripple is drawn as the pressable's foreground,
|
|
28
31
|
* which its own `overflow: hidden` does not clip — so it would spill past rounded corners. A parent clips its
|
|
@@ -43,5 +46,11 @@ export const splitForRipple = (style: ViewStyle | undefined): {inner: ViewStyle[
|
|
|
43
46
|
}
|
|
44
47
|
}
|
|
45
48
|
|
|
46
|
-
|
|
49
|
+
// Only a sized outer view needs the pressable stretched to it. Sized by its content it must not be: Yoga grows a
|
|
50
|
+
// `flexGrow` child of a fit-content parent to the most it may take — inside a row centred on its cross axis, the
|
|
51
|
+
// pressable would stretch to the row's full height and leave its content at the top.
|
|
52
|
+
const sized =
|
|
53
|
+
SIZING_KEYS.some(key => flat[key] !== undefined) || (flat.top !== undefined && flat.bottom !== undefined)
|
|
54
|
+
|
|
55
|
+
return {inner: sized ? [FILL, inner as ViewStyle] : [inner as ViewStyle], outer: outer as ViewStyle}
|
|
47
56
|
}
|
|
@@ -1,24 +1,45 @@
|
|
|
1
1
|
import {Column, Host} from '@expo/ui/jetpack-compose'
|
|
2
|
+
import {padding} from '@expo/ui/jetpack-compose/modifiers'
|
|
2
3
|
import {useSxModifiers} from '@hzblj/kara-sx'
|
|
3
4
|
import {useAppTheme} from '@hzblj/kara-theme'
|
|
4
|
-
import {
|
|
5
|
+
import {useCallback, useMemo, useRef, useState} from 'react'
|
|
6
|
+
import {StatusBar, StyleSheet, View} from 'react-native'
|
|
5
7
|
import {HostBoundary} from '../../host-context'
|
|
6
8
|
import type {ScreenComponent, ScreenProps} from './screen.types'
|
|
7
9
|
|
|
10
|
+
/**
|
|
11
|
+
* The content keeps clear of as much of the status bar as the screen covers — all of it when nothing sits above the
|
|
12
|
+
* screen, none under a navigation bar — the way a SwiftUI host keeps to the safe area. Compose would draw under it:
|
|
13
|
+
* the app is edge to edge, and `Host` pads for nothing. The background still runs to the edge.
|
|
14
|
+
*/
|
|
8
15
|
export const Screen: ScreenComponent = ({bg = 'surface.base', children, ignoreKeyboardInset, testID}: ScreenProps) => {
|
|
9
16
|
const theme = useAppTheme()
|
|
10
|
-
const
|
|
17
|
+
const frame = useRef<View>(null)
|
|
18
|
+
const [statusBarOverlap, setStatusBarOverlap] = useState(0)
|
|
19
|
+
const sx = useSxModifiers({bg, tall: true, wide: true})
|
|
20
|
+
const modifiers = useMemo(
|
|
21
|
+
() => (statusBarOverlap > 0 ? [...sx, padding(0, statusBarOverlap, 0, 0)] : sx),
|
|
22
|
+
[statusBarOverlap, sx]
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
const onLayout = useCallback(() => {
|
|
26
|
+
frame.current?.measureInWindow((_x, y) => {
|
|
27
|
+
setStatusBarOverlap(Math.max(0, Math.round((StatusBar.currentHeight ?? 0) - y)))
|
|
28
|
+
})
|
|
29
|
+
}, [])
|
|
11
30
|
|
|
12
31
|
return (
|
|
13
|
-
<
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
<
|
|
21
|
-
|
|
22
|
-
|
|
32
|
+
<View onLayout={onLayout} ref={frame} style={StyleSheet.absoluteFill} testID={testID}>
|
|
33
|
+
<Host
|
|
34
|
+
colorScheme={theme.dark ? 'dark' : 'light'}
|
|
35
|
+
ignoreSafeAreaKeyboardInsets={ignoreKeyboardInset}
|
|
36
|
+
seedColor={theme.materialSeed}
|
|
37
|
+
style={StyleSheet.absoluteFill}
|
|
38
|
+
>
|
|
39
|
+
<Column modifiers={modifiers}>
|
|
40
|
+
<HostBoundary>{children}</HostBoundary>
|
|
41
|
+
</Column>
|
|
42
|
+
</Host>
|
|
43
|
+
</View>
|
|
23
44
|
)
|
|
24
45
|
}
|
|
@@ -1,10 +1,19 @@
|
|
|
1
1
|
import type {Sx} from '@hzblj/kara-sx'
|
|
2
2
|
import type {ReactNode} from 'react'
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* The full-bleed native host a screen starts with — a SwiftUI or Compose `Host` filling its parent, so native atoms
|
|
6
|
+
* render anywhere inside it. The background runs to the edges; the content keeps clear of the status bar where the
|
|
7
|
+
* screen covers it (no navigation bar above), on Android as SwiftUI's safe area does on iOS.
|
|
8
|
+
*/
|
|
4
9
|
export type ScreenProps = {
|
|
10
|
+
/** The screen's colour. `surface.base` by default. */
|
|
5
11
|
bg?: Sx['bg']
|
|
12
|
+
/** Laid out in a column that fills the screen. */
|
|
6
13
|
children?: ReactNode
|
|
14
|
+
/** Keeps the content where it is when the keyboard opens, instead of avoiding it. Android reads it once, on mount. */
|
|
7
15
|
ignoreKeyboardInset?: boolean
|
|
16
|
+
/** Test identifier — on the host view on iOS, on the view around it on Android. */
|
|
8
17
|
testID?: string
|
|
9
18
|
}
|
|
10
19
|
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
import { useAppTheme } from '@hzblj/kara-theme';
|
|
4
|
-
import { ActivityIndicator as RNActivityIndicator } from 'react-native';
|
|
5
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
6
|
-
export const ActivityIndicator = props => {
|
|
7
|
-
const theme = useAppTheme();
|
|
8
|
-
return /*#__PURE__*/_jsx(RNActivityIndicator, {
|
|
9
|
-
color: theme.color('fill.accent.primary'),
|
|
10
|
-
size: "small",
|
|
11
|
-
...props
|
|
12
|
-
});
|
|
13
|
-
};
|
|
14
|
-
//# sourceMappingURL=activity-indicator.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":["useAppTheme","ActivityIndicator","RNActivityIndicator","jsx","_jsx","props","theme","color","size"],"sourceRoot":"../../../../src","sources":["atoms/activity-indicator/activity-indicator.tsx"],"mappings":";;AAAA,SAAQA,WAAW,QAAO,mBAAmB;AAE7C,SAAqCC,iBAAiB,IAAIC,mBAAmB,QAAO,cAAc;AAAA,SAAAC,GAAA,IAAAC,IAAA;AAElG,OAAO,MAAMH,iBAA6C,GAAGI,KAAK,IAAI;EACpE,MAAMC,KAAK,GAAGN,WAAW,CAAC,CAAC;EAE3B,oBAAOI,IAAA,CAACF,mBAAmB;IAACK,KAAK,EAAED,KAAK,CAACC,KAAK,CAAC,qBAAqB,CAAE;IAACC,IAAI,EAAC,OAAO;IAAA,GAAKH;EAAK,CAAG,CAAC;AACnG,CAAC","ignoreList":[]}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
import { useSplitSx, useSx } from '@hzblj/kara-sx';
|
|
4
|
-
import { FlashList as ShopifyFlashList } from '@shopify/flash-list';
|
|
5
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
6
|
-
/** Stands in for an absent `content`, because a hook cannot be called conditionally. */
|
|
7
|
-
const NO_SX = {};
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* The default list in this codebase: recycles its rows, so it holds a long list at a steady cost.
|
|
11
|
-
*
|
|
12
|
-
* `RnFlatList` and `RnSectionList` are the alternatives, and only for rows that host native views —
|
|
13
|
-
* see either one for why recycling and absolute positioning cannot carry an `@expo/ui` host.
|
|
14
|
-
*/
|
|
15
|
-
export const FlashList = ({
|
|
16
|
-
content,
|
|
17
|
-
data,
|
|
18
|
-
renderItem,
|
|
19
|
-
...props
|
|
20
|
-
}) => {
|
|
21
|
-
const [style, rest] = useSplitSx(props);
|
|
22
|
-
const contentStyle = useSx(content ?? NO_SX);
|
|
23
|
-
return /*#__PURE__*/_jsx(ShopifyFlashList, {
|
|
24
|
-
data: data,
|
|
25
|
-
renderItem: renderItem,
|
|
26
|
-
...rest,
|
|
27
|
-
contentContainerStyle: content === undefined ? undefined : contentStyle,
|
|
28
|
-
style: style
|
|
29
|
-
});
|
|
30
|
-
};
|
|
31
|
-
//# sourceMappingURL=flash-list.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":["useSplitSx","useSx","FlashList","ShopifyFlashList","jsx","_jsx","NO_SX","content","data","renderItem","props","style","rest","contentStyle","contentContainerStyle","undefined"],"sourceRoot":"../../../../src","sources":["atoms/flash-list/flash-list.tsx"],"mappings":";;AAAA,SAAQA,UAAU,EAAEC,KAAK,QAAO,gBAAgB;AAChD,SAAQC,SAAS,IAAIC,gBAAgB,QAAO,qBAAqB;AAAA,SAAAC,GAAA,IAAAC,IAAA;AAIjE;AACA,MAAMC,KAAK,GAAG,CAAC,CAAC;;AAEhB;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMJ,SAAS,GAAGA,CAAS;EAACK,OAAO;EAAEC,IAAI;EAAEC,UAAU;EAAE,GAAGC;AAA4B,CAAC,KAAK;EACjG,MAAM,CAACC,KAAK,EAAEC,IAAI,CAAC,GAAGZ,UAAU,CAACU,KAAgC,CAAC;EAClE,MAAMG,YAAY,GAAGZ,KAAK,CAACM,OAAO,IAAID,KAAK,CAAC;EAE5C,oBACED,IAAA,CAACF,gBAAgB;IACfK,IAAI,EAAEA,IAAK;IACXC,UAAU,EAAEA,UAAW;IAAA,GACnBG,IAAI;IACRE,qBAAqB,EAAEP,OAAO,KAAKQ,SAAS,GAAGA,SAAS,GAAGF,YAAa;IACxEF,KAAK,EAAEA;EAAM,CACd,CAAC;AAEN,CAAC","ignoreList":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":[],"sourceRoot":"../../../../src","sources":["atoms/flash-list/flash-list.types.ts"],"mappings":"","ignoreList":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":[],"sourceRoot":"../../../../src","sources":["atoms/flash-list/index.ts"],"mappings":";;AAAA,cAAc,iBAAc;AAC5B,cAAc,uBAAoB","ignoreList":[]}
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
import { SegmentedControl as NativeSegmentedControl } from '@expo/ui/community/segmented-control';
|
|
4
|
-
import { useAppTheme } from '@hzblj/kara-theme';
|
|
5
|
-
import { useCallback } from 'react';
|
|
6
|
-
import { Platform } from 'react-native';
|
|
7
|
-
import { haptics } from "../../haptics/index.js";
|
|
8
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
9
|
-
/**
|
|
10
|
-
* `UISegmentedControl` on iOS, Material's single-choice segmented buttons on Android. A new segment plays `selection`
|
|
11
|
-
* on Android, whose buttons play nothing of their own; iOS 26's control already gives its own feedback.
|
|
12
|
-
*/
|
|
13
|
-
export const SegmentedControl = ({
|
|
14
|
-
disabled = false,
|
|
15
|
-
onChange,
|
|
16
|
-
selectedIndex,
|
|
17
|
-
testID,
|
|
18
|
-
values
|
|
19
|
-
}) => {
|
|
20
|
-
const theme = useAppTheme();
|
|
21
|
-
const onNativeChange = useCallback(event => {
|
|
22
|
-
const index = event.nativeEvent.selectedSegmentIndex;
|
|
23
|
-
|
|
24
|
-
// Material reports a tap on the segment that is already selected too.
|
|
25
|
-
if (Platform.OS === 'android' && index !== selectedIndex) {
|
|
26
|
-
haptics.selection();
|
|
27
|
-
}
|
|
28
|
-
onChange?.(index, event.nativeEvent.value);
|
|
29
|
-
}, [onChange, selectedIndex]);
|
|
30
|
-
return /*#__PURE__*/_jsx(NativeSegmentedControl, {
|
|
31
|
-
appearance: theme.dark ? 'dark' : 'light',
|
|
32
|
-
enabled: !disabled,
|
|
33
|
-
onChange: onNativeChange,
|
|
34
|
-
selectedIndex: selectedIndex,
|
|
35
|
-
testID: testID,
|
|
36
|
-
tintColor: theme.colorString('surface.primary'),
|
|
37
|
-
values: values
|
|
38
|
-
});
|
|
39
|
-
};
|
|
40
|
-
//# sourceMappingURL=segmented-control.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":["SegmentedControl","NativeSegmentedControl","useAppTheme","useCallback","Platform","haptics","jsx","_jsx","disabled","onChange","selectedIndex","testID","values","theme","onNativeChange","event","index","nativeEvent","selectedSegmentIndex","OS","selection","value","appearance","dark","enabled","tintColor","colorString"],"sourceRoot":"../../../../src","sources":["atoms/segmented-control/segmented-control.tsx"],"mappings":";;AAAA,SAAQA,gBAAgB,IAAIC,sBAAsB,QAAO,sCAAsC;AAC/F,SAAQC,WAAW,QAAO,mBAAmB;AAC7C,SAAQC,WAAW,QAAO,OAAO;AACjC,SAAQC,QAAQ,QAAO,cAAc;AAErC,SAAQC,OAAO,QAAO,wBAAe;AAAA,SAAAC,GAAA,IAAAC,IAAA;AAGrC;AACA;AACA;AACA;AACA,OAAO,MAAMP,gBAA2C,GAAGA,CAAC;EAC1DQ,QAAQ,GAAG,KAAK;EAChBC,QAAQ;EACRC,aAAa;EACbC,MAAM;EACNC;AACqB,CAAC,KAAK;EAC3B,MAAMC,KAAK,GAAGX,WAAW,CAAC,CAAC;EAE3B,MAAMY,cAAc,GAAGX,WAAW,CAC/BY,KAAmE,IAAK;IACvE,MAAMC,KAAK,GAAGD,KAAK,CAACE,WAAW,CAACC,oBAAoB;;IAEpD;IACA,IAAId,QAAQ,CAACe,EAAE,KAAK,SAAS,IAAIH,KAAK,KAAKN,aAAa,EAAE;MACxDL,OAAO,CAACe,SAAS,CAAC,CAAC;IACrB;IAEAX,QAAQ,GAAGO,KAAK,EAAED,KAAK,CAACE,WAAW,CAACI,KAAK,CAAC;EAC5C,CAAC,EACD,CAACZ,QAAQ,EAAEC,aAAa,CAC1B,CAAC;EAED,oBACEH,IAAA,CAACN,sBAAsB;IACrBqB,UAAU,EAAET,KAAK,CAACU,IAAI,GAAG,MAAM,GAAG,OAAQ;IAC1CC,OAAO,EAAE,CAAChB,QAAS;IACnBC,QAAQ,EAAEK,cAAe;IACzBJ,aAAa,EAAEA,aAAc;IAC7BC,MAAM,EAAEA,MAAO;IACfc,SAAS,EAAEZ,KAAK,CAACa,WAAW,CAAC,iBAAiB,CAAE;IAChDd,MAAM,EAAEA;EAAO,CAChB,CAAC;AAEN,CAAC","ignoreList":[]}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import type { FlashListProps } from './flash-list.types';
|
|
2
|
-
/**
|
|
3
|
-
* The default list in this codebase: recycles its rows, so it holds a long list at a steady cost.
|
|
4
|
-
*
|
|
5
|
-
* `RnFlatList` and `RnSectionList` are the alternatives, and only for rows that host native views —
|
|
6
|
-
* see either one for why recycling and absolute positioning cannot carry an `@expo/ui` host.
|
|
7
|
-
*/
|
|
8
|
-
export declare const FlashList: <TItem>({ content, data, renderItem, ...props }: FlashListProps<TItem>) => import("react").JSX.Element;
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import type { ResponsiveViewSx } from '@hzblj/kara-sx';
|
|
2
|
-
import type { FlashListRef, FlashListProps as ShopifyFlashListProps } from '@shopify/flash-list';
|
|
3
|
-
import type { Ref } from 'react';
|
|
4
|
-
/**
|
|
5
|
-
* Top-level `sx` styles the viewport; `content` styles the scrolling content container — the same split
|
|
6
|
-
* as `RnScrollView` and the React Native lists.
|
|
7
|
-
*
|
|
8
|
-
* Padding belongs in `content` here and nowhere else. FlashList measures its rows against its own
|
|
9
|
-
* `style`, and padding there throws that measurement off; its docs put it as "margin is okay but padding
|
|
10
|
-
* is not". `content` has no such limit, because it lands on the scroll view's content container.
|
|
11
|
-
*
|
|
12
|
-
* `ref` is declared because this is a wrapper rather than the re-export it used to be — React 19 passes
|
|
13
|
-
* it as a plain prop, and a `FlashListRef` is how a caller reaches `scrollToIndex` and friends.
|
|
14
|
-
*/
|
|
15
|
-
export type FlashListProps<TItem> = ResponsiveViewSx & Omit<ShopifyFlashListProps<TItem>, 'contentContainerStyle' | 'style'> & {
|
|
16
|
-
content?: ResponsiveViewSx;
|
|
17
|
-
ref?: Ref<FlashListRef<TItem>>;
|
|
18
|
-
};
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import {useAppTheme} from '@hzblj/kara-theme'
|
|
2
|
-
import type {FC} from 'react'
|
|
3
|
-
import {type ActivityIndicatorProps, ActivityIndicator as RNActivityIndicator} from 'react-native'
|
|
4
|
-
|
|
5
|
-
export const ActivityIndicator: FC<ActivityIndicatorProps> = props => {
|
|
6
|
-
const theme = useAppTheme()
|
|
7
|
-
|
|
8
|
-
return <RNActivityIndicator color={theme.color('fill.accent.primary')} size="small" {...props} />
|
|
9
|
-
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import {useSplitSx, useSx} from '@hzblj/kara-sx'
|
|
2
|
-
import {FlashList as ShopifyFlashList} from '@shopify/flash-list'
|
|
3
|
-
|
|
4
|
-
import type {FlashListProps} from './flash-list.types'
|
|
5
|
-
|
|
6
|
-
/** Stands in for an absent `content`, because a hook cannot be called conditionally. */
|
|
7
|
-
const NO_SX = {}
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* The default list in this codebase: recycles its rows, so it holds a long list at a steady cost.
|
|
11
|
-
*
|
|
12
|
-
* `RnFlatList` and `RnSectionList` are the alternatives, and only for rows that host native views —
|
|
13
|
-
* see either one for why recycling and absolute positioning cannot carry an `@expo/ui` host.
|
|
14
|
-
*/
|
|
15
|
-
export const FlashList = <TItem,>({content, data, renderItem, ...props}: FlashListProps<TItem>) => {
|
|
16
|
-
const [style, rest] = useSplitSx(props as Record<string, unknown>)
|
|
17
|
-
const contentStyle = useSx(content ?? NO_SX)
|
|
18
|
-
|
|
19
|
-
return (
|
|
20
|
-
<ShopifyFlashList
|
|
21
|
-
data={data}
|
|
22
|
-
renderItem={renderItem}
|
|
23
|
-
{...rest}
|
|
24
|
-
contentContainerStyle={content === undefined ? undefined : contentStyle}
|
|
25
|
-
style={style}
|
|
26
|
-
/>
|
|
27
|
-
)
|
|
28
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import type {ResponsiveViewSx} from '@hzblj/kara-sx'
|
|
2
|
-
import type {FlashListRef, FlashListProps as ShopifyFlashListProps} from '@shopify/flash-list'
|
|
3
|
-
import type {Ref} from 'react'
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Top-level `sx` styles the viewport; `content` styles the scrolling content container — the same split
|
|
7
|
-
* as `RnScrollView` and the React Native lists.
|
|
8
|
-
*
|
|
9
|
-
* Padding belongs in `content` here and nowhere else. FlashList measures its rows against its own
|
|
10
|
-
* `style`, and padding there throws that measurement off; its docs put it as "margin is okay but padding
|
|
11
|
-
* is not". `content` has no such limit, because it lands on the scroll view's content container.
|
|
12
|
-
*
|
|
13
|
-
* `ref` is declared because this is a wrapper rather than the re-export it used to be — React 19 passes
|
|
14
|
-
* it as a plain prop, and a `FlashListRef` is how a caller reaches `scrollToIndex` and friends.
|
|
15
|
-
*/
|
|
16
|
-
export type FlashListProps<TItem> = ResponsiveViewSx &
|
|
17
|
-
Omit<ShopifyFlashListProps<TItem>, 'contentContainerStyle' | 'style'> & {
|
|
18
|
-
content?: ResponsiveViewSx
|
|
19
|
-
ref?: Ref<FlashListRef<TItem>>
|
|
20
|
-
}
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import {SegmentedControl as NativeSegmentedControl} from '@expo/ui/community/segmented-control'
|
|
2
|
-
import {useAppTheme} from '@hzblj/kara-theme'
|
|
3
|
-
import {useCallback} from 'react'
|
|
4
|
-
import {Platform} from 'react-native'
|
|
5
|
-
|
|
6
|
-
import {haptics} from '../../haptics'
|
|
7
|
-
import type {SegmentedControlComponent, SegmentedControlProps} from './segmented-control.types'
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* `UISegmentedControl` on iOS, Material's single-choice segmented buttons on Android. A new segment plays `selection`
|
|
11
|
-
* on Android, whose buttons play nothing of their own; iOS 26's control already gives its own feedback.
|
|
12
|
-
*/
|
|
13
|
-
export const SegmentedControl: SegmentedControlComponent = ({
|
|
14
|
-
disabled = false,
|
|
15
|
-
onChange,
|
|
16
|
-
selectedIndex,
|
|
17
|
-
testID,
|
|
18
|
-
values,
|
|
19
|
-
}: SegmentedControlProps) => {
|
|
20
|
-
const theme = useAppTheme()
|
|
21
|
-
|
|
22
|
-
const onNativeChange = useCallback(
|
|
23
|
-
(event: {nativeEvent: {selectedSegmentIndex: number; value: string}}) => {
|
|
24
|
-
const index = event.nativeEvent.selectedSegmentIndex
|
|
25
|
-
|
|
26
|
-
// Material reports a tap on the segment that is already selected too.
|
|
27
|
-
if (Platform.OS === 'android' && index !== selectedIndex) {
|
|
28
|
-
haptics.selection()
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
onChange?.(index, event.nativeEvent.value)
|
|
32
|
-
},
|
|
33
|
-
[onChange, selectedIndex]
|
|
34
|
-
)
|
|
35
|
-
|
|
36
|
-
return (
|
|
37
|
-
<NativeSegmentedControl
|
|
38
|
-
appearance={theme.dark ? 'dark' : 'light'}
|
|
39
|
-
enabled={!disabled}
|
|
40
|
-
onChange={onNativeChange}
|
|
41
|
-
selectedIndex={selectedIndex}
|
|
42
|
-
testID={testID}
|
|
43
|
-
tintColor={theme.colorString('surface.primary')}
|
|
44
|
-
values={values}
|
|
45
|
-
/>
|
|
46
|
-
)
|
|
47
|
-
}
|