@hzblj/kara-components 0.20.1 → 0.21.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 +35 -0
- package/lib/module/atoms/activity-indicator/activity-indicator.android.js +1 -1
- package/lib/module/atoms/activity-indicator/activity-indicator.android.js.map +1 -1
- package/lib/module/atoms/activity-indicator/activity-indicator.ios.js +1 -1
- package/lib/module/atoms/activity-indicator/activity-indicator.ios.js.map +1 -1
- package/lib/module/atoms/badge/badge.android.js +1 -1
- package/lib/module/atoms/badge/badge.android.js.map +1 -1
- package/lib/module/atoms/badge/badge.ios.js +1 -1
- package/lib/module/atoms/badge/badge.ios.js.map +1 -1
- package/lib/module/atoms/blur-view/blur-view.android.js +22 -1
- package/lib/module/atoms/blur-view/blur-view.android.js.map +1 -1
- package/lib/module/atoms/blur-view/blur-view.ios.js +20 -0
- package/lib/module/atoms/blur-view/blur-view.ios.js.map +1 -1
- package/lib/module/atoms/button/button.android.js +1 -1
- package/lib/module/atoms/button/button.android.js.map +1 -1
- package/lib/module/atoms/button/button.ios.js +1 -1
- package/lib/module/atoms/button/button.ios.js.map +1 -1
- package/lib/module/atoms/card/card.android.js +1 -1
- package/lib/module/atoms/card/card.android.js.map +1 -1
- package/lib/module/atoms/card/card.ios.js +1 -1
- package/lib/module/atoms/card/card.ios.js.map +1 -1
- package/lib/module/atoms/checkbox/checkbox.android.js +1 -1
- package/lib/module/atoms/checkbox/checkbox.android.js.map +1 -1
- package/lib/module/atoms/checkbox/checkbox.ios.js +1 -1
- package/lib/module/atoms/checkbox/checkbox.ios.js.map +1 -1
- package/lib/module/atoms/color-picker/color-picker.android.js +1 -1
- package/lib/module/atoms/color-picker/color-picker.android.js.map +1 -1
- package/lib/module/atoms/color-picker/color-picker.ios.js +1 -1
- package/lib/module/atoms/color-picker/color-picker.ios.js.map +1 -1
- package/lib/module/atoms/date-picker/date-picker.android.js +1 -1
- package/lib/module/atoms/date-picker/date-picker.android.js.map +1 -1
- package/lib/module/atoms/date-picker/date-picker.ios.js +1 -1
- package/lib/module/atoms/date-picker/date-picker.ios.js.map +1 -1
- package/lib/module/atoms/divider/divider.android.js +1 -1
- package/lib/module/atoms/divider/divider.android.js.map +1 -1
- package/lib/module/atoms/divider/divider.ios.js +1 -1
- package/lib/module/atoms/divider/divider.ios.js.map +1 -1
- package/lib/module/atoms/fab/fab.android.js +1 -1
- package/lib/module/atoms/fab/fab.android.js.map +1 -1
- package/lib/module/atoms/fab/fab.ios.js +1 -1
- package/lib/module/atoms/fab/fab.ios.js.map +1 -1
- package/lib/module/atoms/glyph/glyph-button.android.js.map +1 -0
- package/lib/module/atoms/glyph/glyph-button.ios.js.map +1 -0
- package/lib/module/atoms/glyph/glyph-button.types.js.map +1 -0
- package/lib/module/atoms/glyph/glyph.android.js.map +1 -0
- package/lib/module/atoms/glyph/glyph.ios.js.map +1 -0
- package/lib/module/atoms/glyph/glyph.types.js.map +1 -0
- package/lib/module/atoms/glyph/index.js.map +1 -0
- package/lib/module/atoms/glyph/rn-glyph.android.js.map +1 -0
- package/lib/module/atoms/glyph/rn-glyph.ios.js.map +1 -0
- package/lib/module/atoms/h-stack/h-stack.android.js +2 -2
- package/lib/module/atoms/h-stack/h-stack.android.js.map +1 -1
- package/lib/module/atoms/h-stack/h-stack.ios.js +2 -2
- package/lib/module/atoms/h-stack/h-stack.ios.js.map +1 -1
- package/lib/module/atoms/icon/icon.android.js +1 -1
- package/lib/module/atoms/icon/icon.android.js.map +1 -1
- package/lib/module/atoms/icon/icon.ios.js +1 -1
- package/lib/module/atoms/icon/icon.ios.js.map +1 -1
- package/lib/module/atoms/icon-button/icon-button.android.js +1 -1
- package/lib/module/atoms/icon-button/icon-button.android.js.map +1 -1
- package/lib/module/atoms/icon-button/icon-button.ios.js +1 -1
- package/lib/module/atoms/icon-button/icon-button.ios.js.map +1 -1
- package/lib/module/atoms/island/island.android.js +3 -1
- package/lib/module/atoms/island/island.android.js.map +1 -1
- package/lib/module/atoms/island/island.ios.js +3 -1
- package/lib/module/atoms/island/island.ios.js.map +1 -1
- package/lib/module/atoms/list/list.android.js +2 -2
- package/lib/module/atoms/list/list.android.js.map +1 -1
- package/lib/module/atoms/list/list.ios.js +1 -1
- package/lib/module/atoms/list/list.ios.js.map +1 -1
- package/lib/module/atoms/picker/picker.android.js +2 -2
- package/lib/module/atoms/picker/picker.android.js.map +1 -1
- package/lib/module/atoms/picker/picker.ios.js +1 -1
- package/lib/module/atoms/picker/picker.ios.js.map +1 -1
- package/lib/module/atoms/pressable/pressable.js +1 -1
- package/lib/module/atoms/pressable/pressable.js.map +1 -1
- package/lib/module/atoms/progress/progress.android.js +1 -1
- package/lib/module/atoms/progress/progress.android.js.map +1 -1
- package/lib/module/atoms/progress/progress.ios.js +1 -1
- package/lib/module/atoms/progress/progress.ios.js.map +1 -1
- package/lib/module/atoms/scroll-view/scroll-view.android.js +2 -2
- package/lib/module/atoms/scroll-view/scroll-view.android.js.map +1 -1
- package/lib/module/atoms/scroll-view/scroll-view.ios.js +1 -1
- package/lib/module/atoms/scroll-view/scroll-view.ios.js.map +1 -1
- package/lib/module/atoms/segmented-control/segmented-control.android.js +1 -1
- package/lib/module/atoms/segmented-control/segmented-control.android.js.map +1 -1
- package/lib/module/atoms/segmented-control/segmented-control.ios.js +1 -1
- package/lib/module/atoms/segmented-control/segmented-control.ios.js.map +1 -1
- package/lib/module/atoms/slider/slider.android.js +1 -1
- package/lib/module/atoms/slider/slider.android.js.map +1 -1
- package/lib/module/atoms/slider/slider.ios.js +1 -1
- package/lib/module/atoms/slider/slider.ios.js.map +1 -1
- package/lib/module/atoms/spacer/spacer.android.js +1 -1
- package/lib/module/atoms/spacer/spacer.android.js.map +1 -1
- package/lib/module/atoms/spacer/spacer.ios.js +1 -1
- package/lib/module/atoms/spacer/spacer.ios.js.map +1 -1
- package/lib/module/atoms/surface/surface.android.js +1 -1
- package/lib/module/atoms/surface/surface.android.js.map +1 -1
- package/lib/module/atoms/surface/surface.ios.js +1 -1
- package/lib/module/atoms/surface/surface.ios.js.map +1 -1
- package/lib/module/atoms/switch/switch.android.js +1 -1
- package/lib/module/atoms/switch/switch.android.js.map +1 -1
- package/lib/module/atoms/switch/switch.ios.js +1 -1
- package/lib/module/atoms/switch/switch.ios.js.map +1 -1
- package/lib/module/atoms/text/text.android.js +1 -1
- package/lib/module/atoms/text/text.android.js.map +1 -1
- package/lib/module/atoms/text/text.ios.js +1 -1
- package/lib/module/atoms/text/text.ios.js.map +1 -1
- package/lib/module/atoms/text-field/text-field.android.js +2 -2
- package/lib/module/atoms/text-field/text-field.android.js.map +1 -1
- package/lib/module/atoms/text-field/text-field.ios.js +1 -1
- package/lib/module/atoms/text-field/text-field.ios.js.map +1 -1
- package/lib/module/atoms/v-stack/v-stack.android.js +2 -2
- package/lib/module/atoms/v-stack/v-stack.android.js.map +1 -1
- package/lib/module/atoms/v-stack/v-stack.ios.js +2 -2
- package/lib/module/atoms/v-stack/v-stack.ios.js.map +1 -1
- package/lib/module/atoms/z-stack/z-stack.android.js +2 -2
- package/lib/module/atoms/z-stack/z-stack.android.js.map +1 -1
- package/lib/module/atoms/z-stack/z-stack.ios.js +2 -2
- package/lib/module/atoms/z-stack/z-stack.ios.js.map +1 -1
- package/lib/module/hooks/host-context.js.map +1 -0
- package/lib/module/hooks/use-refresh-state.js.map +1 -0
- package/lib/module/hooks/use-stack-modifiers.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/collapsible/collapsible.ios.js +1 -1
- package/lib/module/molecules/collapsible/collapsible.ios.js.map +1 -1
- package/lib/module/molecules/labeled-content/labeled-content.js +1 -1
- package/lib/module/molecules/labeled-content/labeled-content.js.map +1 -1
- package/lib/module/molecules/list-item/list-item.js +1 -1
- package/lib/module/molecules/list-item/list-item.js.map +1 -1
- package/lib/module/molecules/navigation-bar/navigation-bar.constants.js +5 -0
- package/lib/module/molecules/navigation-bar/navigation-bar.constants.js.map +1 -0
- package/lib/module/molecules/navigation-bar/navigation-bar.ios.js +31 -4
- package/lib/module/molecules/navigation-bar/navigation-bar.ios.js.map +1 -1
- package/lib/module/molecules/pager/pager.android.js +1 -1
- package/lib/module/molecules/pager/pager.android.js.map +1 -1
- package/lib/module/molecules/pager/pager.ios.js +1 -1
- package/lib/module/molecules/pager/pager.ios.js.map +1 -1
- package/lib/module/molecules/radio-group/radio-group.android.js +1 -1
- 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/rn-list-item/rn-list-item.js +1 -1
- package/lib/module/molecules/rn-list-item/rn-list-item.js.map +1 -1
- package/lib/module/molecules/rn-tooltip/rn-tooltip.android.js +1 -1
- package/lib/module/molecules/rn-tooltip/rn-tooltip.android.js.map +1 -1
- package/lib/module/molecules/search-bar/search-bar.js +1 -1
- package/lib/module/molecules/search-bar/search-bar.js.map +1 -1
- package/lib/module/molecules/stepper/stepper.android.js +2 -2
- package/lib/module/molecules/stepper/stepper.android.js.map +1 -1
- package/lib/module/molecules/stepper/stepper.ios.js +1 -1
- package/lib/module/molecules/stepper/stepper.ios.js.map +1 -1
- package/lib/module/molecules/tooltip/tooltip.android.js +1 -1
- package/lib/module/molecules/tooltip/tooltip.android.js.map +1 -1
- package/lib/module/molecules/tooltip/tooltip.ios.js +1 -1
- package/lib/module/molecules/tooltip/tooltip.ios.js.map +1 -1
- package/lib/module/organisms/action-sheet/action-sheet.android.js +1 -1
- package/lib/module/organisms/action-sheet/action-sheet.android.js.map +1 -1
- package/lib/module/organisms/action-sheet/action-sheet.ios.js +1 -1
- package/lib/module/organisms/action-sheet/action-sheet.ios.js.map +1 -1
- package/lib/module/organisms/alert/alert.android.js +1 -1
- package/lib/module/organisms/alert/alert.android.js.map +1 -1
- package/lib/module/organisms/alert/alert.ios.js +1 -1
- package/lib/module/organisms/alert/alert.ios.js.map +1 -1
- package/lib/module/organisms/context-menu/context-menu.android.js +2 -2
- package/lib/module/organisms/context-menu/context-menu.android.js.map +1 -1
- package/lib/module/organisms/fab-menu/fab-menu.android.js +2 -2
- package/lib/module/organisms/fab-menu/fab-menu.android.js.map +1 -1
- package/lib/module/organisms/fab-menu/fab-menu.ios.js +2 -2
- package/lib/module/organisms/fab-menu/fab-menu.ios.js.map +1 -1
- package/lib/module/organisms/form/form.android.js +1 -1
- package/lib/module/organisms/form/form.android.js.map +1 -1
- package/lib/module/organisms/form/form.ios.js +1 -1
- package/lib/module/organisms/form/form.ios.js.map +1 -1
- package/lib/module/organisms/header/header-color.js +8 -0
- package/lib/module/organisms/header/header-color.js.map +1 -0
- package/lib/module/organisms/header/header-inset.android.js +6 -0
- package/lib/module/organisms/header/header-inset.android.js.map +1 -0
- package/lib/module/organisms/header/header-inset.ios.js +19 -0
- package/lib/module/organisms/header/header-inset.ios.js.map +1 -0
- package/lib/module/organisms/header/header-options.android.js +180 -0
- package/lib/module/organisms/header/header-options.android.js.map +1 -0
- package/lib/module/organisms/header/header-options.ios.js +145 -0
- package/lib/module/organisms/header/header-options.ios.js.map +1 -0
- package/lib/module/organisms/header/header-options.types.js +4 -0
- package/lib/module/organisms/header/header-options.types.js.map +1 -0
- package/lib/module/organisms/header/header-search-accessory.android.js +5 -0
- package/lib/module/organisms/header/header-search-accessory.android.js.map +1 -0
- package/lib/module/organisms/header/header-search-accessory.ios.js +35 -0
- package/lib/module/organisms/header/header-search-accessory.ios.js.map +1 -0
- package/lib/module/organisms/header/header-search-accessory.types.js +4 -0
- package/lib/module/organisms/header/header-search-accessory.types.js.map +1 -0
- package/lib/module/organisms/header/header-search-input.android.js +80 -0
- package/lib/module/organisms/header/header-search-input.android.js.map +1 -0
- package/lib/module/organisms/header/header-search-input.ios.js +8 -0
- package/lib/module/organisms/header/header-search-input.ios.js.map +1 -0
- package/lib/module/organisms/header/header-search-input.types.js +4 -0
- package/lib/module/organisms/header/header-search-input.types.js.map +1 -0
- package/lib/module/organisms/header/header-search-scrim.js +62 -0
- package/lib/module/organisms/header/header-search-scrim.js.map +1 -0
- package/lib/module/organisms/header/header-title.js +230 -0
- package/lib/module/organisms/header/header-title.js.map +1 -0
- package/lib/module/organisms/header/header.types.js +4 -0
- package/lib/module/organisms/header/header.types.js.map +1 -0
- package/lib/module/organisms/header/hero-header-background.android.js +33 -0
- package/lib/module/organisms/header/hero-header-background.android.js.map +1 -0
- package/lib/module/organisms/header/hero-header-background.ios.js +40 -0
- package/lib/module/organisms/header/hero-header-background.ios.js.map +1 -0
- package/lib/module/organisms/header/hero-header-background.types.js +4 -0
- package/lib/module/organisms/header/hero-header-background.types.js.map +1 -0
- package/lib/module/organisms/header/index.js +13 -0
- package/lib/module/organisms/header/index.js.map +1 -0
- package/lib/module/organisms/header/native-subtitle.android.js +5 -0
- package/lib/module/organisms/header/native-subtitle.android.js.map +1 -0
- package/lib/module/organisms/header/native-subtitle.ios.js +22 -0
- package/lib/module/organisms/header/native-subtitle.ios.js.map +1 -0
- package/lib/module/organisms/header/native-subtitle.types.js +4 -0
- package/lib/module/organisms/header/native-subtitle.types.js.map +1 -0
- package/lib/module/organisms/header/sheet-grabber.android.js +5 -0
- package/lib/module/organisms/header/sheet-grabber.android.js.map +1 -0
- package/lib/module/organisms/header/sheet-grabber.ios.js +15 -0
- package/lib/module/organisms/header/sheet-grabber.ios.js.map +1 -0
- package/lib/module/organisms/header/sheet-grabber.types.js +4 -0
- package/lib/module/organisms/header/sheet-grabber.types.js.map +1 -0
- package/lib/module/organisms/header/use-header-bar-inset.android.js +4 -0
- package/lib/module/organisms/header/use-header-bar-inset.android.js.map +1 -0
- package/lib/module/organisms/header/use-header-bar-inset.ios.js +9 -0
- package/lib/module/organisms/header/use-header-bar-inset.ios.js.map +1 -0
- package/lib/module/organisms/header/use-header-bar-inset.types.js +2 -0
- package/lib/module/organisms/header/use-header-bar-inset.types.js.map +1 -0
- package/lib/module/organisms/header/use-header-scroll-to-top.js +51 -0
- package/lib/module/organisms/header/use-header-scroll-to-top.js.map +1 -0
- package/lib/module/organisms/header/use-header-search.js +135 -0
- package/lib/module/organisms/header/use-header-search.js.map +1 -0
- package/lib/module/organisms/header/use-header.js +74 -0
- package/lib/module/organisms/header/use-header.js.map +1 -0
- package/lib/module/organisms/header/use-hero-header.js +189 -0
- package/lib/module/organisms/header/use-hero-header.js.map +1 -0
- package/lib/module/organisms/header/use-stack-screen-options.js +77 -0
- package/lib/module/organisms/header/use-stack-screen-options.js.map +1 -0
- package/lib/module/organisms/menu/menu.android.js +2 -2
- package/lib/module/organisms/menu/menu.android.js.map +1 -1
- package/lib/module/organisms/menu/menu.ios.js +1 -1
- package/lib/module/organisms/menu/menu.ios.js.map +1 -1
- package/lib/module/organisms/sheet/use-sheet-header.js +3 -1
- package/lib/module/organisms/sheet/use-sheet-header.js.map +1 -1
- package/lib/module/organisms/snackbar/snackbar.js +1 -1
- package/lib/module/organisms/snackbar/snackbar.js.map +1 -1
- package/lib/module/organisms/swipe-actions/swipe-actions.android.js +1 -1
- package/lib/module/organisms/swipe-actions/swipe-actions.android.js.map +1 -1
- package/lib/module/organisms/swipe-actions/swipe-actions.ios.js +1 -1
- package/lib/module/organisms/swipe-actions/swipe-actions.ios.js.map +1 -1
- package/lib/module/templates/screen/screen.android.js +3 -3
- package/lib/module/templates/screen/screen.android.js.map +1 -1
- package/lib/module/templates/screen/screen.ios.js +3 -3
- package/lib/module/templates/screen/screen.ios.js.map +1 -1
- package/lib/module/utils/ripple-clip.js.map +1 -0
- package/lib/module/utils/tap-modifiers.js.map +1 -0
- package/lib/typescript/atoms/blur-view/blur-view.types.d.ts +8 -0
- package/lib/typescript/atoms/island/island.types.d.ts +17 -0
- package/lib/typescript/molecules/navigation-bar/navigation-bar.constants.d.ts +2 -0
- package/lib/typescript/molecules/navigation-bar/navigation-bar.types.d.ts +67 -4
- package/lib/typescript/organisms/header/header-color.d.ts +6 -0
- package/lib/typescript/organisms/header/header-inset.d.ts +1 -0
- package/lib/typescript/organisms/header/header-inset.ios.d.ts +2 -0
- package/lib/typescript/organisms/header/header-options.d.ts +1 -0
- package/lib/typescript/organisms/header/header-options.ios.d.ts +2 -0
- package/lib/typescript/organisms/header/header-options.types.d.ts +4 -0
- package/lib/typescript/organisms/header/header-search-accessory.d.ts +1 -0
- package/lib/typescript/organisms/header/header-search-accessory.ios.d.ts +6 -0
- package/lib/typescript/organisms/header/header-search-accessory.types.d.ts +9 -0
- package/lib/typescript/organisms/header/header-search-input.d.ts +1 -0
- package/lib/typescript/organisms/header/header-search-input.ios.d.ts +5 -0
- package/lib/typescript/organisms/header/header-search-input.types.d.ts +17 -0
- package/lib/typescript/organisms/header/header-search-scrim.d.ts +11 -0
- package/lib/typescript/organisms/header/header-title.d.ts +22 -0
- package/lib/typescript/organisms/header/header.types.d.ts +440 -0
- package/lib/typescript/organisms/header/hero-header-background.d.ts +1 -0
- package/lib/typescript/organisms/header/hero-header-background.ios.d.ts +7 -0
- package/lib/typescript/organisms/header/hero-header-background.types.d.ts +9 -0
- package/lib/typescript/organisms/header/index.d.ts +11 -0
- package/lib/typescript/organisms/header/native-subtitle.d.ts +1 -0
- package/lib/typescript/organisms/header/native-subtitle.ios.d.ts +4 -0
- package/lib/typescript/organisms/header/native-subtitle.types.d.ts +6 -0
- package/lib/typescript/organisms/header/sheet-grabber.d.ts +1 -0
- package/lib/typescript/organisms/header/sheet-grabber.ios.d.ts +7 -0
- package/lib/typescript/organisms/header/sheet-grabber.types.d.ts +6 -0
- package/lib/typescript/organisms/header/use-header-bar-inset.d.ts +1 -0
- package/lib/typescript/organisms/header/use-header-bar-inset.ios.d.ts +1 -0
- package/lib/typescript/organisms/header/use-header-bar-inset.types.d.ts +6 -0
- package/lib/typescript/organisms/header/use-header-scroll-to-top.d.ts +8 -0
- package/lib/typescript/organisms/header/use-header-search.d.ts +12 -0
- package/lib/typescript/organisms/header/use-header.d.ts +14 -0
- package/lib/typescript/organisms/header/use-hero-header.d.ts +10 -0
- package/lib/typescript/organisms/header/use-stack-screen-options.d.ts +17 -0
- package/lib/typescript/templates/screen/screen.types.d.ts +6 -2
- package/package.json +24 -5
- package/src/atoms/activity-indicator/activity-indicator.android.tsx +1 -1
- package/src/atoms/activity-indicator/activity-indicator.ios.tsx +1 -1
- package/src/atoms/badge/badge.android.tsx +1 -1
- package/src/atoms/badge/badge.ios.tsx +1 -1
- package/src/atoms/blur-view/blur-view.android.tsx +28 -1
- package/src/atoms/blur-view/blur-view.ios.tsx +25 -0
- package/src/atoms/blur-view/blur-view.types.ts +8 -0
- package/src/atoms/button/button.android.tsx +1 -1
- package/src/atoms/button/button.ios.tsx +1 -1
- package/src/atoms/card/card.android.tsx +1 -1
- package/src/atoms/card/card.ios.tsx +1 -1
- package/src/atoms/checkbox/checkbox.android.tsx +1 -1
- package/src/atoms/checkbox/checkbox.ios.tsx +1 -1
- package/src/atoms/color-picker/color-picker.android.tsx +1 -1
- package/src/atoms/color-picker/color-picker.ios.tsx +1 -1
- package/src/atoms/date-picker/date-picker.android.tsx +1 -1
- package/src/atoms/date-picker/date-picker.ios.tsx +1 -1
- package/src/atoms/divider/divider.android.tsx +1 -1
- package/src/atoms/divider/divider.ios.tsx +1 -1
- package/src/atoms/fab/fab.android.tsx +1 -1
- package/src/atoms/fab/fab.ios.tsx +1 -1
- package/src/atoms/h-stack/h-stack.android.tsx +2 -2
- package/src/atoms/h-stack/h-stack.ios.tsx +2 -2
- package/src/atoms/icon/icon.android.tsx +1 -1
- package/src/atoms/icon/icon.ios.tsx +1 -1
- package/src/atoms/icon-button/icon-button.android.tsx +1 -1
- package/src/atoms/icon-button/icon-button.ios.tsx +1 -1
- package/src/atoms/island/island.android.tsx +3 -1
- package/src/atoms/island/island.ios.tsx +10 -2
- package/src/atoms/island/island.types.ts +18 -0
- package/src/atoms/list/list.android.tsx +2 -2
- package/src/atoms/list/list.ios.tsx +1 -1
- package/src/atoms/picker/picker.android.tsx +2 -3
- package/src/atoms/picker/picker.ios.tsx +1 -1
- package/src/atoms/pressable/pressable.tsx +1 -1
- package/src/atoms/progress/progress.android.tsx +1 -1
- package/src/atoms/progress/progress.ios.tsx +1 -1
- package/src/atoms/scroll-view/scroll-view.android.tsx +2 -2
- package/src/atoms/scroll-view/scroll-view.ios.tsx +1 -1
- package/src/atoms/segmented-control/segmented-control.android.tsx +1 -1
- package/src/atoms/segmented-control/segmented-control.ios.tsx +1 -1
- package/src/atoms/slider/slider.android.tsx +1 -1
- package/src/atoms/slider/slider.ios.tsx +1 -1
- package/src/atoms/spacer/spacer.android.tsx +1 -1
- package/src/atoms/spacer/spacer.ios.tsx +1 -1
- package/src/atoms/surface/surface.android.tsx +1 -1
- package/src/atoms/surface/surface.ios.tsx +1 -1
- package/src/atoms/switch/switch.android.tsx +1 -1
- package/src/atoms/switch/switch.ios.tsx +1 -1
- package/src/atoms/text/text.android.tsx +1 -1
- package/src/atoms/text/text.ios.tsx +1 -1
- package/src/atoms/text-field/text-field.android.tsx +2 -2
- package/src/atoms/text-field/text-field.ios.tsx +1 -1
- package/src/atoms/v-stack/v-stack.android.tsx +2 -2
- package/src/atoms/v-stack/v-stack.ios.tsx +2 -2
- package/src/atoms/z-stack/z-stack.android.tsx +2 -2
- package/src/atoms/z-stack/z-stack.ios.tsx +2 -2
- package/src/molecules/collapsible/collapsible.android.tsx +2 -2
- package/src/molecules/collapsible/collapsible.ios.tsx +1 -1
- package/src/molecules/labeled-content/labeled-content.tsx +1 -1
- package/src/molecules/list-item/list-item.tsx +1 -2
- package/src/molecules/navigation-bar/navigation-bar.constants.ts +2 -0
- package/src/molecules/navigation-bar/navigation-bar.ios.tsx +35 -5
- package/src/molecules/navigation-bar/navigation-bar.types.ts +69 -5
- package/src/molecules/pager/pager.android.tsx +1 -1
- package/src/molecules/pager/pager.ios.tsx +1 -1
- package/src/molecules/radio-group/radio-group.android.tsx +1 -1
- package/src/molecules/radio-group/radio-group.ios.tsx +2 -2
- package/src/molecules/rn-list-item/rn-list-item.tsx +1 -1
- package/src/molecules/rn-tooltip/rn-tooltip.android.tsx +1 -1
- package/src/molecules/search-bar/search-bar.tsx +1 -1
- package/src/molecules/stepper/stepper.android.tsx +2 -2
- package/src/molecules/stepper/stepper.ios.tsx +1 -1
- package/src/molecules/tooltip/tooltip.android.tsx +1 -1
- package/src/molecules/tooltip/tooltip.ios.tsx +1 -1
- package/src/organisms/action-sheet/action-sheet.android.tsx +1 -1
- package/src/organisms/action-sheet/action-sheet.ios.tsx +1 -1
- package/src/organisms/alert/alert.android.tsx +1 -1
- package/src/organisms/alert/alert.ios.tsx +1 -1
- package/src/organisms/context-menu/context-menu.android.tsx +2 -2
- package/src/organisms/fab-menu/fab-menu.android.tsx +2 -2
- package/src/organisms/fab-menu/fab-menu.ios.tsx +2 -3
- package/src/organisms/form/form.android.tsx +1 -1
- package/src/organisms/form/form.ios.tsx +1 -1
- package/src/organisms/header/header-color.ts +7 -0
- package/src/organisms/header/header-inset.android.tsx +3 -0
- package/src/organisms/header/header-inset.ios.tsx +12 -0
- package/src/organisms/header/header-options.android.tsx +168 -0
- package/src/organisms/header/header-options.ios.tsx +138 -0
- package/src/organisms/header/header-options.types.ts +6 -0
- package/src/organisms/header/header-search-accessory.android.tsx +4 -0
- package/src/organisms/header/header-search-accessory.ios.tsx +42 -0
- package/src/organisms/header/header-search-accessory.types.ts +12 -0
- package/src/organisms/header/header-search-input.android.tsx +89 -0
- package/src/organisms/header/header-search-input.ios.tsx +7 -0
- package/src/organisms/header/header-search-input.types.ts +21 -0
- package/src/organisms/header/header-search-scrim.tsx +49 -0
- package/src/organisms/header/header-title.tsx +220 -0
- package/src/organisms/header/header.types.ts +416 -0
- package/src/organisms/header/hero-header-background.android.tsx +22 -0
- package/src/organisms/header/hero-header-background.ios.tsx +26 -0
- package/src/organisms/header/hero-header-background.types.ts +11 -0
- package/src/organisms/header/index.ts +11 -0
- package/src/organisms/header/native-subtitle.android.tsx +5 -0
- package/src/organisms/header/native-subtitle.ios.tsx +22 -0
- package/src/organisms/header/native-subtitle.types.ts +8 -0
- package/src/organisms/header/sheet-grabber.android.tsx +4 -0
- package/src/organisms/header/sheet-grabber.ios.tsx +12 -0
- package/src/organisms/header/sheet-grabber.types.ts +8 -0
- package/src/organisms/header/use-header-bar-inset.android.ts +1 -0
- package/src/organisms/header/use-header-bar-inset.ios.ts +7 -0
- package/src/organisms/header/use-header-bar-inset.types.ts +6 -0
- package/src/organisms/header/use-header-scroll-to-top.ts +48 -0
- package/src/organisms/header/use-header-search.tsx +138 -0
- package/src/organisms/header/use-header.ts +67 -0
- package/src/organisms/header/use-hero-header.tsx +222 -0
- package/src/organisms/header/use-stack-screen-options.ts +66 -0
- package/src/organisms/menu/menu.android.tsx +2 -2
- package/src/organisms/menu/menu.ios.tsx +1 -1
- package/src/organisms/sheet/use-sheet-header.tsx +4 -1
- package/src/organisms/snackbar/snackbar.tsx +1 -1
- package/src/organisms/swipe-actions/swipe-actions.android.tsx +1 -1
- package/src/organisms/swipe-actions/swipe-actions.ios.tsx +1 -1
- package/src/templates/screen/screen.android.tsx +8 -3
- package/src/templates/screen/screen.ios.tsx +8 -3
- package/src/templates/screen/screen.types.ts +7 -2
- package/lib/module/glyph/glyph-button.android.js.map +0 -1
- package/lib/module/glyph/glyph-button.ios.js.map +0 -1
- package/lib/module/glyph/glyph-button.types.js.map +0 -1
- package/lib/module/glyph/glyph.android.js.map +0 -1
- package/lib/module/glyph/glyph.ios.js.map +0 -1
- package/lib/module/glyph/glyph.types.js.map +0 -1
- package/lib/module/glyph/index.js.map +0 -1
- package/lib/module/glyph/rn-glyph.android.js.map +0 -1
- package/lib/module/glyph/rn-glyph.ios.js.map +0 -1
- package/lib/module/host-context.js.map +0 -1
- package/lib/module/ripple-clip.js.map +0 -1
- package/lib/module/tap-modifiers.js.map +0 -1
- package/lib/module/use-refresh-state.js.map +0 -1
- package/lib/module/use-stack-modifiers.js.map +0 -1
- /package/lib/module/{glyph → atoms/glyph}/glyph-button.android.js +0 -0
- /package/lib/module/{glyph → atoms/glyph}/glyph-button.ios.js +0 -0
- /package/lib/module/{glyph → atoms/glyph}/glyph-button.types.js +0 -0
- /package/lib/module/{glyph → atoms/glyph}/glyph.android.js +0 -0
- /package/lib/module/{glyph → atoms/glyph}/glyph.ios.js +0 -0
- /package/lib/module/{glyph → atoms/glyph}/glyph.types.js +0 -0
- /package/lib/module/{glyph → atoms/glyph}/index.js +0 -0
- /package/lib/module/{glyph → atoms/glyph}/rn-glyph.android.js +0 -0
- /package/lib/module/{glyph → atoms/glyph}/rn-glyph.ios.js +0 -0
- /package/lib/module/{host-context.js → hooks/host-context.js} +0 -0
- /package/lib/module/{use-refresh-state.js → hooks/use-refresh-state.js} +0 -0
- /package/lib/module/{use-stack-modifiers.js → hooks/use-stack-modifiers.js} +0 -0
- /package/lib/module/{ripple-clip.js → utils/ripple-clip.js} +0 -0
- /package/lib/module/{tap-modifiers.js → utils/tap-modifiers.js} +0 -0
- /package/lib/typescript/{glyph → atoms/glyph}/glyph-button.d.ts +0 -0
- /package/lib/typescript/{glyph → atoms/glyph}/glyph-button.ios.d.ts +0 -0
- /package/lib/typescript/{glyph → atoms/glyph}/glyph-button.types.d.ts +0 -0
- /package/lib/typescript/{glyph → atoms/glyph}/glyph.d.ts +0 -0
- /package/lib/typescript/{glyph → atoms/glyph}/glyph.ios.d.ts +0 -0
- /package/lib/typescript/{glyph → atoms/glyph}/glyph.types.d.ts +0 -0
- /package/lib/typescript/{glyph → atoms/glyph}/index.d.ts +0 -0
- /package/lib/typescript/{glyph → atoms/glyph}/rn-glyph.d.ts +0 -0
- /package/lib/typescript/{glyph → atoms/glyph}/rn-glyph.ios.d.ts +0 -0
- /package/lib/typescript/{host-context.d.ts → hooks/host-context.d.ts} +0 -0
- /package/lib/typescript/{use-refresh-state.d.ts → hooks/use-refresh-state.d.ts} +0 -0
- /package/lib/typescript/{use-stack-modifiers.d.ts → hooks/use-stack-modifiers.d.ts} +0 -0
- /package/lib/typescript/{ripple-clip.d.ts → utils/ripple-clip.d.ts} +0 -0
- /package/lib/typescript/{tap-modifiers.d.ts → utils/tap-modifiers.d.ts} +0 -0
- /package/src/{glyph → atoms/glyph}/glyph-button.android.tsx +0 -0
- /package/src/{glyph → atoms/glyph}/glyph-button.ios.tsx +0 -0
- /package/src/{glyph → atoms/glyph}/glyph-button.types.ts +0 -0
- /package/src/{glyph → atoms/glyph}/glyph.android.tsx +0 -0
- /package/src/{glyph → atoms/glyph}/glyph.ios.tsx +0 -0
- /package/src/{glyph → atoms/glyph}/glyph.types.ts +0 -0
- /package/src/{glyph → atoms/glyph}/index.ts +0 -0
- /package/src/{glyph → atoms/glyph}/rn-glyph.android.tsx +0 -0
- /package/src/{glyph → atoms/glyph}/rn-glyph.ios.tsx +0 -0
- /package/src/{host-context.tsx → hooks/host-context.tsx} +0 -0
- /package/src/{use-refresh-state.ts → hooks/use-refresh-state.ts} +0 -0
- /package/src/{use-stack-modifiers.ts → hooks/use-stack-modifiers.ts} +0 -0
- /package/src/{ripple-clip.ts → utils/ripple-clip.ts} +0 -0
- /package/src/{tap-modifiers.ts → utils/tap-modifiers.ts} +0 -0
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import {type ReactNode, useCallback, useMemo, useState} from 'react'
|
|
2
|
+
import {type LayoutChangeEvent, Platform, StyleSheet, useWindowDimensions, View} from 'react-native'
|
|
3
|
+
import Animated, {
|
|
4
|
+
Extrapolation,
|
|
5
|
+
interpolate,
|
|
6
|
+
type SharedValue,
|
|
7
|
+
useAnimatedReaction,
|
|
8
|
+
useAnimatedStyle,
|
|
9
|
+
useDerivedValue,
|
|
10
|
+
useSharedValue,
|
|
11
|
+
} from 'react-native-reanimated'
|
|
12
|
+
import {scheduleOnRN} from 'react-native-worklets'
|
|
13
|
+
|
|
14
|
+
import {RnText} from '../../atoms/rn-text'
|
|
15
|
+
import type {HeaderOptions} from './header.types'
|
|
16
|
+
import {hasNativeSubtitle, NativeSubtitle} from './native-subtitle'
|
|
17
|
+
|
|
18
|
+
/** Past half, a revealed title counts as shown: the native title and subtitle switch then. */
|
|
19
|
+
const REVEALED_THRESHOLD = 0.5
|
|
20
|
+
|
|
21
|
+
/** iOS centres a custom title view in what the bar items leave; this much stays for them on a leading title. */
|
|
22
|
+
const LEADING_TITLE_RESERVED_WIDTH = 200
|
|
23
|
+
|
|
24
|
+
const styles = StyleSheet.create({
|
|
25
|
+
largeTitle: {paddingHorizontal: 16, paddingVertical: 8},
|
|
26
|
+
leadingTitleAndroid: {paddingStart: 2, paddingTop: 1},
|
|
27
|
+
leadingTitleIos: {flexShrink: 1, paddingTop: 1},
|
|
28
|
+
shrink: {flexShrink: 1},
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
export const useIsTitleRevealed = (progress?: SharedValue<number>) => {
|
|
32
|
+
const [revealed, setRevealed] = useState(() => progress === undefined || progress.value > REVEALED_THRESHOLD)
|
|
33
|
+
|
|
34
|
+
useAnimatedReaction(
|
|
35
|
+
() => progress === undefined || progress.value > REVEALED_THRESHOLD,
|
|
36
|
+
(isRevealed, wasRevealed) => {
|
|
37
|
+
if (isRevealed !== wasRevealed) {
|
|
38
|
+
scheduleOnRN(setRevealed, isRevealed)
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
return revealed
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const Reveal = ({children, progress}: {children: ReactNode; progress: SharedValue<number>}) => {
|
|
47
|
+
const animatedStyle = useAnimatedStyle(() => ({opacity: progress.value}))
|
|
48
|
+
|
|
49
|
+
return <Animated.View style={[styles.shrink, animatedStyle]}>{children}</Animated.View>
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const BarTitle = ({title}: {title: string}) => (
|
|
53
|
+
<RnText accessibilityRole="header" allowFontScaling={false} numberOfLines={1} variant="headline">
|
|
54
|
+
{title}
|
|
55
|
+
</RnText>
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
const LeadingTitle = ({subtitle, title}: {subtitle: string; title: string}) => {
|
|
59
|
+
const {width} = useWindowDimensions()
|
|
60
|
+
const content = (
|
|
61
|
+
<>
|
|
62
|
+
<RnText accessibilityRole="header" allowFontScaling={false} numberOfLines={1} variant="subheadlineMedium">
|
|
63
|
+
{title}
|
|
64
|
+
</RnText>
|
|
65
|
+
<RnText allowFontScaling={false} color="content.secondary" numberOfLines={1} variant="label">
|
|
66
|
+
{subtitle}
|
|
67
|
+
</RnText>
|
|
68
|
+
</>
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
if (Platform.OS === 'ios') {
|
|
72
|
+
return (
|
|
73
|
+
<View style={[styles.leadingTitleIos, {width}]}>
|
|
74
|
+
<View style={{maxWidth: width - LEADING_TITLE_RESERVED_WIDTH}}>{content}</View>
|
|
75
|
+
</View>
|
|
76
|
+
)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return <View style={[styles.leadingTitleAndroid, {maxWidth: width - LEADING_TITLE_RESERVED_WIDTH}]}>{content}</View>
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const LargeTitle = ({height, title}: {height: SharedValue<number>; title: string}) => {
|
|
83
|
+
const onLayout = useCallback(
|
|
84
|
+
(event: LayoutChangeEvent) => {
|
|
85
|
+
height.value = event.nativeEvent.layout.height
|
|
86
|
+
},
|
|
87
|
+
[height]
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
return (
|
|
91
|
+
<View onLayout={onLayout} style={styles.largeTitle}>
|
|
92
|
+
<RnText accessibilityRole="header" allowFontScaling={false} numberOfLines={1} variant="headingM">
|
|
93
|
+
{title}
|
|
94
|
+
</RnText>
|
|
95
|
+
</View>
|
|
96
|
+
)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const CollapsingTitle = ({
|
|
100
|
+
height,
|
|
101
|
+
scrollY,
|
|
102
|
+
title,
|
|
103
|
+
}: {
|
|
104
|
+
height: SharedValue<number>
|
|
105
|
+
scrollY: SharedValue<number>
|
|
106
|
+
title: string
|
|
107
|
+
}) => {
|
|
108
|
+
const progress = useDerivedValue(() => {
|
|
109
|
+
if (height.value === 0) {
|
|
110
|
+
return 0
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return interpolate(scrollY.value, [height.value / 2, height.value], [0, 1], Extrapolation.CLAMP)
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
return (
|
|
117
|
+
<Reveal progress={progress}>
|
|
118
|
+
<BarTitle title={title} />
|
|
119
|
+
</Reveal>
|
|
120
|
+
)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
type TitleParams = {
|
|
124
|
+
largeTitle?: boolean
|
|
125
|
+
subtitle?: string
|
|
126
|
+
title?: string
|
|
127
|
+
titleHidden: boolean
|
|
128
|
+
titleRevealProgress?: SharedValue<number>
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* The title half of a header: the options that show the title (centred, leading with a subtitle, revealed on scroll or
|
|
133
|
+
* large), plus on Android the large title row and the scroll worklet that collapses it into the bar, as Material's large
|
|
134
|
+
* top app bar does. iOS needs neither: the large title is UIKit's own.
|
|
135
|
+
*/
|
|
136
|
+
export const useHeaderTitle = ({largeTitle, subtitle, title, titleHidden, titleRevealProgress}: TitleParams) => {
|
|
137
|
+
const scrollY = useSharedValue(0)
|
|
138
|
+
const largeTitleHeight = useSharedValue(0)
|
|
139
|
+
const revealed = useIsTitleRevealed(titleRevealProgress)
|
|
140
|
+
const isAndroidLargeTitle = Platform.OS === 'android' && largeTitle === true && !!title
|
|
141
|
+
|
|
142
|
+
const onScroll = useCallback(
|
|
143
|
+
(offsetY: number) => {
|
|
144
|
+
'worklet'
|
|
145
|
+
scrollY.value = offsetY
|
|
146
|
+
},
|
|
147
|
+
[scrollY]
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
const options = useMemo((): HeaderOptions => {
|
|
151
|
+
const titleOptions: HeaderOptions = {}
|
|
152
|
+
|
|
153
|
+
if (largeTitle !== undefined) {
|
|
154
|
+
titleOptions.headerLargeTitleEnabled = Platform.OS === 'ios' && largeTitle
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (title === undefined) {
|
|
158
|
+
return titleOptions
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
titleOptions.title = title
|
|
162
|
+
|
|
163
|
+
if (titleHidden) {
|
|
164
|
+
titleOptions.headerTitle = ''
|
|
165
|
+
return titleOptions
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
if (subtitle !== undefined && hasNativeSubtitle) {
|
|
169
|
+
const shownTitle = revealed ? title : ''
|
|
170
|
+
|
|
171
|
+
// The subtitle styles the screen's navigation item from inside its tree, which `headerBackground` is.
|
|
172
|
+
titleOptions.headerBackground = () => <NativeSubtitle subtitle={subtitle} subtitleHidden={!revealed} />
|
|
173
|
+
titleOptions.headerTitle = shownTitle
|
|
174
|
+
titleOptions.title = shownTitle
|
|
175
|
+
return titleOptions
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if (subtitle !== undefined) {
|
|
179
|
+
const leadingTitle = <LeadingTitle subtitle={subtitle} title={title} />
|
|
180
|
+
|
|
181
|
+
titleOptions.headerTitle = () =>
|
|
182
|
+
titleRevealProgress ? <Reveal progress={titleRevealProgress}>{leadingTitle}</Reveal> : leadingTitle
|
|
183
|
+
return titleOptions
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
if (titleRevealProgress) {
|
|
187
|
+
titleOptions.headerTitle = () => (
|
|
188
|
+
<Reveal progress={titleRevealProgress}>
|
|
189
|
+
<BarTitle title={title} />
|
|
190
|
+
</Reveal>
|
|
191
|
+
)
|
|
192
|
+
return titleOptions
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
if (isAndroidLargeTitle) {
|
|
196
|
+
titleOptions.headerTitle = () => <CollapsingTitle height={largeTitleHeight} scrollY={scrollY} title={title} />
|
|
197
|
+
return titleOptions
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
titleOptions.headerTitle = title
|
|
201
|
+
return titleOptions
|
|
202
|
+
}, [
|
|
203
|
+
isAndroidLargeTitle,
|
|
204
|
+
largeTitle,
|
|
205
|
+
largeTitleHeight,
|
|
206
|
+
revealed,
|
|
207
|
+
scrollY,
|
|
208
|
+
subtitle,
|
|
209
|
+
title,
|
|
210
|
+
titleHidden,
|
|
211
|
+
titleRevealProgress,
|
|
212
|
+
])
|
|
213
|
+
|
|
214
|
+
const largeTitleRow = useMemo(
|
|
215
|
+
() => (isAndroidLargeTitle && title ? <LargeTitle height={largeTitleHeight} title={title} /> : null),
|
|
216
|
+
[isAndroidLargeTitle, largeTitleHeight, title]
|
|
217
|
+
)
|
|
218
|
+
|
|
219
|
+
return {largeTitle: largeTitleRow, onScroll, options, revealed}
|
|
220
|
+
}
|
|
@@ -0,0 +1,416 @@
|
|
|
1
|
+
import type {ColorToken} from '@hzblj/kara-theme'
|
|
2
|
+
import type {ReactElement, ReactNode, RefObject} from 'react'
|
|
3
|
+
import type {ColorValue, ImageSourcePropType} from 'react-native'
|
|
4
|
+
import type {SharedValue} from 'react-native-reanimated'
|
|
5
|
+
import type {SearchBarCommands} from 'react-native-screens'
|
|
6
|
+
import type {SFSymbol} from 'sf-symbols-typescript'
|
|
7
|
+
|
|
8
|
+
import type {IconName} from '../../atoms/icon'
|
|
9
|
+
import type {SearchFieldVoice} from '../../molecules/navigation-bar/navigation-bar.types'
|
|
10
|
+
|
|
11
|
+
type HeaderActionBase = {
|
|
12
|
+
/**
|
|
13
|
+
* iOS 26: neighbouring actions on one side share a glass capsule; this gives the action its own. A close next to
|
|
14
|
+
* other actions usually wants it. Material has no grouped capsules, so Android ignores it.
|
|
15
|
+
*/
|
|
16
|
+
separated?: boolean
|
|
17
|
+
/** iOS: the bar item's `identifier`, which UI tests match; Android: the button's test tag. */
|
|
18
|
+
testID?: string
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* The platform's own back or close: a chevron or a cross (an SF Symbol on iOS, a Material Symbol on Android), named
|
|
23
|
+
* `Back` / `Close` for VoiceOver and TalkBack unless given another label. `icon` puts one of the app's icons in their
|
|
24
|
+
* place.
|
|
25
|
+
*/
|
|
26
|
+
export type HeaderNavigationAction = HeaderActionBase & {
|
|
27
|
+
/** One of the app's icons in place of the platform's glyph. */
|
|
28
|
+
icon?: IconName
|
|
29
|
+
/** What VoiceOver and TalkBack say. `Back` or `Close` by default. */
|
|
30
|
+
label?: string
|
|
31
|
+
/** Called when the action is pressed. */
|
|
32
|
+
onPress: () => void
|
|
33
|
+
type: 'back' | 'close'
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** An action drawn as one of the app's icons. */
|
|
37
|
+
export type HeaderIconAction = HeaderActionBase & {
|
|
38
|
+
/** iOS 26: a badge on the item, a count or a short text. Android ignores it. */
|
|
39
|
+
badge?: number | string
|
|
40
|
+
/** The icon's colour. The header's own tint by default. */
|
|
41
|
+
color?: ColorToken
|
|
42
|
+
/** Dims the action and stops it responding. */
|
|
43
|
+
disabled?: boolean
|
|
44
|
+
/** One of the app's icons. */
|
|
45
|
+
icon: IconName
|
|
46
|
+
/**
|
|
47
|
+
* What VoiceOver and TalkBack say, since an icon has no words of its own, and the row iOS 26 shows when the items no
|
|
48
|
+
* longer fit and collapse into its overflow menu.
|
|
49
|
+
*/
|
|
50
|
+
label: string
|
|
51
|
+
/** Shows a spinner in the action's place while what it started is still running. */
|
|
52
|
+
loading?: boolean
|
|
53
|
+
/** Called when the action is pressed. */
|
|
54
|
+
onPress: () => void
|
|
55
|
+
/** iOS: draws the item in its selected state. Android ignores it. */
|
|
56
|
+
selected?: boolean
|
|
57
|
+
type: 'icon'
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** An action drawn as its label: "Edit", "Done". */
|
|
61
|
+
export type HeaderTextAction = HeaderActionBase & {
|
|
62
|
+
/** Dims the action and stops it responding. */
|
|
63
|
+
disabled?: boolean
|
|
64
|
+
/** The action's text. */
|
|
65
|
+
label: string
|
|
66
|
+
/** Called when the action is pressed. */
|
|
67
|
+
onPress: () => void
|
|
68
|
+
/** iOS: the prominent style, filled on iOS 26. Android ignores it. */
|
|
69
|
+
prominent?: boolean
|
|
70
|
+
type: 'text'
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** One row of a header menu. */
|
|
74
|
+
export type HeaderMenuAction = {
|
|
75
|
+
/** iOS: a checkmark before the row, for a menu that picks one of several. Android ignores it. */
|
|
76
|
+
checked?: boolean
|
|
77
|
+
/** iOS: a second line under the label. Android ignores it. */
|
|
78
|
+
description?: string
|
|
79
|
+
/** Draws the row in the destructive colour. */
|
|
80
|
+
destructive?: boolean
|
|
81
|
+
/** Greys the row out and stops it responding. */
|
|
82
|
+
disabled?: boolean
|
|
83
|
+
/** One of the app's icons, beside the label. */
|
|
84
|
+
icon?: IconName
|
|
85
|
+
/** The row's text. */
|
|
86
|
+
label: string
|
|
87
|
+
/** Called when the row is chosen; the menu closes by itself. */
|
|
88
|
+
onPress: () => void
|
|
89
|
+
type: 'action'
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* A group of rows: on iOS a nested menu, or with `inline` a section of its parent. Android's dropdown has no nesting,
|
|
94
|
+
* so it lists the group's rows in place.
|
|
95
|
+
*/
|
|
96
|
+
export type HeaderSubmenu = {
|
|
97
|
+
/** iOS: one of the app's icons beside the group's label. */
|
|
98
|
+
icon?: IconName
|
|
99
|
+
/** iOS: shows the rows as a section of the parent menu instead of behind a row of their own. */
|
|
100
|
+
inline?: boolean
|
|
101
|
+
/** The group's rows, top to bottom. */
|
|
102
|
+
items: HeaderMenuItem[]
|
|
103
|
+
/** The group's label. */
|
|
104
|
+
label: string
|
|
105
|
+
type: 'submenu'
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export type HeaderMenuItem = HeaderMenuAction | HeaderSubmenu
|
|
109
|
+
|
|
110
|
+
/** An icon that opens a menu: a `UIMenu` from the bar item on iOS, a Material dropdown under it on Android. */
|
|
111
|
+
export type HeaderMenu = HeaderActionBase & {
|
|
112
|
+
/** One of the app's icons on the item. */
|
|
113
|
+
icon: IconName
|
|
114
|
+
/** The menu's rows, top to bottom. */
|
|
115
|
+
items: HeaderMenuItem[]
|
|
116
|
+
/** What VoiceOver and TalkBack say for the item: "More options". */
|
|
117
|
+
label: string
|
|
118
|
+
/** iOS: a title above the rows. Android ignores it. */
|
|
119
|
+
title?: string
|
|
120
|
+
type: 'menu'
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/** Any React Native element in the header, for what the other actions cannot draw: an avatar, a count. */
|
|
124
|
+
export type HeaderCustomAction = {
|
|
125
|
+
/** The element, laid out at its own size. */
|
|
126
|
+
element: ReactElement
|
|
127
|
+
/** Identifies the element among the side's actions. */
|
|
128
|
+
key: string
|
|
129
|
+
/** iOS 26: keeps the element apart from its neighbours' shared glass. Android ignores it. */
|
|
130
|
+
separated?: boolean
|
|
131
|
+
type: 'custom'
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* One action of a screen's header. iOS draws them as the navigation bar's own `UIBarButtonItem`s (the same glass,
|
|
136
|
+
* press and overflow menu as the system's), Android as Material icon and text buttons in the top app bar.
|
|
137
|
+
*/
|
|
138
|
+
export type HeaderAction =
|
|
139
|
+
| HeaderCustomAction
|
|
140
|
+
| HeaderIconAction
|
|
141
|
+
| HeaderMenu
|
|
142
|
+
| HeaderNavigationAction
|
|
143
|
+
| HeaderTextAction
|
|
144
|
+
|
|
145
|
+
export type HeaderParams = {
|
|
146
|
+
/**
|
|
147
|
+
* Hides the stack's own back button. On Android a trailing `close` then takes the navigation icon's place at the
|
|
148
|
+
* start, as Material's full-screen dialogs have it, unless there are leading actions.
|
|
149
|
+
*/
|
|
150
|
+
backHidden?: boolean
|
|
151
|
+
/**
|
|
152
|
+
* A large title that collapses into the bar as the list scrolls. iOS draws UIKit's own; Android, where the native
|
|
153
|
+
* stack has none, puts it into the content as the list's first row (`largeTitle` in the result) and fades the bar's
|
|
154
|
+
* title in once that row has scrolled away, as Material's large top app bar does. Wire `onScroll` for it.
|
|
155
|
+
*/
|
|
156
|
+
largeTitle?: boolean
|
|
157
|
+
/**
|
|
158
|
+
* The leading side's actions, in screen order from the edge. On iOS they follow the back button. Unset leaves the
|
|
159
|
+
* side as the stack's options have it; an empty array clears it.
|
|
160
|
+
*/
|
|
161
|
+
leadingActions?: HeaderAction[]
|
|
162
|
+
/**
|
|
163
|
+
* A search field in the header, from `useHeaderSearch`: UIKit's search bar under the title on iOS. Android has no
|
|
164
|
+
* field in its top app bar, so `useHeaderSearch` gives the screen a row of its own to put under it.
|
|
165
|
+
*/
|
|
166
|
+
search?: HeaderSearchBarOptions
|
|
167
|
+
/**
|
|
168
|
+
* A line under the title, both on the leading side. iOS 26 sets it as the navigation item's own subtitle, which
|
|
169
|
+
* truncates and morphs between screens natively; elsewhere a title and subtitle are drawn in the bar.
|
|
170
|
+
*/
|
|
171
|
+
subtitle?: string
|
|
172
|
+
/** The screen's title, in the bar. */
|
|
173
|
+
title?: string
|
|
174
|
+
/** Keeps the bar without a title, for a screen that draws its own under it. */
|
|
175
|
+
titleHidden?: boolean
|
|
176
|
+
/**
|
|
177
|
+
* Fades the title (and subtitle) in as this goes from 0 to 1, for a detail screen whose title appears once its image
|
|
178
|
+
* has scrolled away. Past half, iOS 26 switches its native title and subtitle on with a cross-dissolve.
|
|
179
|
+
*/
|
|
180
|
+
titleRevealProgress?: SharedValue<number>
|
|
181
|
+
/**
|
|
182
|
+
* The trailing side's actions, in screen order toward the edge: the close usually last. Unset leaves the side as the
|
|
183
|
+
* stack's options have it; an empty array clears it.
|
|
184
|
+
*/
|
|
185
|
+
trailingActions?: HeaderAction[]
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
type NativeHeaderItemIcon = {name: SFSymbol; type: 'sfSymbol'} | {source: ImageSourcePropType; type: 'image'}
|
|
189
|
+
|
|
190
|
+
type NativeHeaderItemShared = {
|
|
191
|
+
accessibilityLabel?: string
|
|
192
|
+
badge?: {value: number | string}
|
|
193
|
+
disabled?: boolean
|
|
194
|
+
icon?: NativeHeaderItemIcon
|
|
195
|
+
identifier?: string
|
|
196
|
+
label: string
|
|
197
|
+
sharesBackground?: boolean
|
|
198
|
+
tintColor?: ColorValue
|
|
199
|
+
variant?: 'done' | 'plain' | 'prominent'
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
export type NativeHeaderMenuElement =
|
|
203
|
+
| {
|
|
204
|
+
description?: string
|
|
205
|
+
destructive?: boolean
|
|
206
|
+
disabled?: boolean
|
|
207
|
+
icon?: NativeHeaderItemIcon
|
|
208
|
+
label: string
|
|
209
|
+
onPress: () => void
|
|
210
|
+
state?: 'mixed' | 'off' | 'on'
|
|
211
|
+
type: 'action'
|
|
212
|
+
}
|
|
213
|
+
| {icon?: NativeHeaderItemIcon; inline?: boolean; items: NativeHeaderMenuElement[]; label: string; type: 'submenu'}
|
|
214
|
+
|
|
215
|
+
/** A native-stack header item, the shape React Navigation's and Expo Router's native stacks both take. */
|
|
216
|
+
export type NativeHeaderItem =
|
|
217
|
+
| (NativeHeaderItemShared & {menu: {items: NativeHeaderMenuElement[]; title?: string}; type: 'menu'})
|
|
218
|
+
| (NativeHeaderItemShared & {onPress: () => void; selected?: boolean; type: 'button'})
|
|
219
|
+
| {element: ReactElement; hidesSharedBackground?: boolean; type: 'custom'}
|
|
220
|
+
| {spacing: number; type: 'spacing'}
|
|
221
|
+
|
|
222
|
+
export type HeaderItemProps = {
|
|
223
|
+
/** Whether the stack can go back from this screen. */
|
|
224
|
+
canGoBack?: boolean
|
|
225
|
+
/** The header's tint. */
|
|
226
|
+
tintColor?: ColorValue
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Native-stack screen options, as React Navigation's native stack and Expo Router's `Stack` both take them: spread them
|
|
231
|
+
* into `options`, or hand them to `navigation.setOptions`.
|
|
232
|
+
*/
|
|
233
|
+
export type HeaderOptions = {
|
|
234
|
+
headerBackground?: () => ReactNode
|
|
235
|
+
headerBackVisible?: boolean
|
|
236
|
+
headerBlurEffect?: 'none' | 'systemChromeMaterial'
|
|
237
|
+
headerLargeTitleEnabled?: boolean
|
|
238
|
+
headerLeft?: (props: HeaderItemProps) => ReactNode
|
|
239
|
+
headerRight?: (props: HeaderItemProps) => ReactNode
|
|
240
|
+
headerSearchBarOptions?: HeaderSearchBarOptions
|
|
241
|
+
headerShown?: boolean
|
|
242
|
+
headerStyle?: {backgroundColor?: string}
|
|
243
|
+
headerTintColor?: string
|
|
244
|
+
headerTitle?: string | (() => ReactNode)
|
|
245
|
+
headerTransparent?: boolean
|
|
246
|
+
scrollEdgeEffects?: {top?: 'automatic' | 'hidden'}
|
|
247
|
+
statusBarStyle?: 'auto' | 'dark' | 'light'
|
|
248
|
+
title?: string
|
|
249
|
+
unstable_headerLeftItems?: (props: HeaderItemProps) => NativeHeaderItem[]
|
|
250
|
+
unstable_headerRightItems?: (props: HeaderItemProps) => NativeHeaderItem[]
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/** What a list under the header needs from it. */
|
|
254
|
+
export type HeaderContent = {
|
|
255
|
+
/**
|
|
256
|
+
* Hand it to the list: `automatic` lets iOS inset the content under its transparent bar, `never` (a hero header)
|
|
257
|
+
* lets the content run under it.
|
|
258
|
+
*/
|
|
259
|
+
contentInsetAdjustmentBehavior: 'automatic' | 'never'
|
|
260
|
+
/** Android, with `largeTitle`: the large title, to render as the list's first row. `null` everywhere else. */
|
|
261
|
+
largeTitle: ReactElement | null
|
|
262
|
+
/** A worklet to call with the list's vertical offset from its scroll handler, for what follows the scroll. */
|
|
263
|
+
onScroll: (offsetY: number) => void
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/** `HeaderContent` plus the options, for a screen that sets them itself (Expo Router's `<Stack.Screen options>`). */
|
|
267
|
+
export type HeaderOptionsResult = HeaderContent & {
|
|
268
|
+
options: HeaderOptions
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/** UIKit's search bar options, as the native stack takes them (`headerSearchBarOptions`). */
|
|
272
|
+
export type HeaderSearchBarOptions = {
|
|
273
|
+
allowToolbarIntegration?: boolean
|
|
274
|
+
autoCapitalize?: 'characters' | 'none' | 'sentences' | 'words'
|
|
275
|
+
hideNavigationBar?: boolean
|
|
276
|
+
hideWhenScrolling?: boolean
|
|
277
|
+
obscureBackground?: boolean
|
|
278
|
+
onBlur?: () => void
|
|
279
|
+
onCancelButtonPress?: () => void
|
|
280
|
+
onChangeText?: (event: {nativeEvent: {text: string}}) => void
|
|
281
|
+
onFocus?: () => void
|
|
282
|
+
placeholder?: string
|
|
283
|
+
placement?: 'automatic' | 'inline' | 'integrated' | 'integratedButton' | 'integratedCentered' | 'stacked'
|
|
284
|
+
ref?: RefObject<SearchBarCommands | null>
|
|
285
|
+
tintColor?: string
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Where the search goes on iOS: `stacked` in a row under the title (title and items kept); `integratedButton` as a
|
|
290
|
+
* search button in the bar's trailing corner that opens the field in the bar, the title and items hidden meanwhile.
|
|
291
|
+
* The integrated field's close is the system's: iOS gives it no other glyph.
|
|
292
|
+
*/
|
|
293
|
+
export type HeaderSearchPlacement = 'integratedButton' | 'stacked'
|
|
294
|
+
|
|
295
|
+
export type HeaderSearchParams = {
|
|
296
|
+
/** iOS: the cancel circle beside a focused stacked field (iOS 26), one of the app's icons; the system cross unset. */
|
|
297
|
+
cancelIcon?: IconName
|
|
298
|
+
/** The field's clear button, one of the app's icons; the platform's unset. */
|
|
299
|
+
clearIcon?: IconName
|
|
300
|
+
/** Off leaves the header without a field, for a screen that searches only sometimes. On by default. */
|
|
301
|
+
enabled?: boolean
|
|
302
|
+
/** Shown while the field is empty. `Search` by default. */
|
|
303
|
+
placeholder?: string
|
|
304
|
+
/** iOS: `stacked` by default. Android always puts its field in a row under the bar. */
|
|
305
|
+
placement?: HeaderSearchPlacement
|
|
306
|
+
/** A microphone in the field: see `SearchFieldVoice`. Write what it hears with `setText`. */
|
|
307
|
+
voice?: SearchFieldVoice
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* A header's search: what to give `useHeader` (`searchBar`, iOS), the row Android puts under its bar (`searchInput`),
|
|
312
|
+
* the scrim that washes the content out while the field is focused and empty (render it last, over the content), and
|
|
313
|
+
* the query to filter by.
|
|
314
|
+
*/
|
|
315
|
+
export type HeaderSearch = {
|
|
316
|
+
/** Empties the field and ends the search. */
|
|
317
|
+
clear: () => void
|
|
318
|
+
/** The field's text. */
|
|
319
|
+
query: string
|
|
320
|
+
/**
|
|
321
|
+
* Over the content while the field is focused and empty; a tap on it ends the search. On iOS it also carries the
|
|
322
|
+
* field's glyphs and voice, which have to sit in the screen's tree. Render it last.
|
|
323
|
+
*/
|
|
324
|
+
scrim: ReactElement | null
|
|
325
|
+
/** Android: the Material search field, a row to put right under the bar. `null` on iOS. */
|
|
326
|
+
searchInput: ReactElement | null
|
|
327
|
+
/** iOS: `search` for `useHeader`. `undefined` on Android. */
|
|
328
|
+
searchBar: HeaderSearchBarOptions | undefined
|
|
329
|
+
/** Puts text into the field and the query, the way dictation fills it in. */
|
|
330
|
+
setText: (text: string) => void
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/** Whether the header over a hero is light (over a dark image) or dark (over a light one). */
|
|
334
|
+
export type HeroHeaderStyle = 'dark' | 'light'
|
|
335
|
+
|
|
336
|
+
export type HeroHeaderParams = Pick<HeaderParams, 'backHidden' | 'leadingActions' | 'subtitle' | 'trailingActions'> & {
|
|
337
|
+
/** The hero's height: the header fades in while the part of it under the bar scrolls away. */
|
|
338
|
+
heroHeight: number
|
|
339
|
+
/**
|
|
340
|
+
* Holds the header in its revealed look while above 0, for a hero that opens with an intro (the bar's background, tint
|
|
341
|
+
* and status bar; the title and the trailing actions follow the scroll alone).
|
|
342
|
+
*/
|
|
343
|
+
introProgress?: SharedValue<number>
|
|
344
|
+
/** The items and status bar over the hero. `light` (over a dark image) by default. */
|
|
345
|
+
overHeroStyle?: HeroHeaderStyle
|
|
346
|
+
/** Trailing actions that join the bar, in front of `trailingActions`, once the title is revealed. */
|
|
347
|
+
revealedTrailingActions?: HeaderAction[]
|
|
348
|
+
/** The screen's title, revealed in the bar once the hero has scrolled away. */
|
|
349
|
+
title: string
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/** A hero header: a transparent bar over a full-bleed image that fades in as the image scrolls away. */
|
|
353
|
+
export type HeroHeader = HeaderContent & {
|
|
354
|
+
/**
|
|
355
|
+
* The bar's background below iOS 26 and on Android, and the status bar over the hero. Render it after the list.
|
|
356
|
+
*/
|
|
357
|
+
background: ReactElement
|
|
358
|
+
/** How far the header has faded in, intro included: 0 over the hero, 1 revealed. */
|
|
359
|
+
progress: SharedValue<number>
|
|
360
|
+
/** The same from the scroll alone, without the intro. */
|
|
361
|
+
scrollProgress: SharedValue<number>
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* What `useHeroHeader` needs of a screen's navigation object, React Navigation's and Expo Router's `useNavigation()`
|
|
366
|
+
* both: setting options, and whether the screen is focused, so its status bar applies to it alone.
|
|
367
|
+
*/
|
|
368
|
+
export type HeroHeaderNavigation = HeaderNavigation & {
|
|
369
|
+
addListener(event: 'blur' | 'focus', callback: () => void): () => void
|
|
370
|
+
isFocused(): boolean
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
/** A native stack's screen options, as React Navigation's native stack and Expo Router's `Stack` both take them. */
|
|
374
|
+
export type StackScreenOptions = {
|
|
375
|
+
contentStyle?: {backgroundColor?: string}
|
|
376
|
+
headerBackButtonDisplayMode?: 'default' | 'generic' | 'minimal'
|
|
377
|
+
headerBlurEffect?: 'none' | 'systemChromeMaterial'
|
|
378
|
+
headerLargeTitleEnabled?: boolean
|
|
379
|
+
headerLargeTitleShadowVisible?: boolean
|
|
380
|
+
headerLargeTitleStyle?: {color?: string; fontFamily?: string; fontSize?: number}
|
|
381
|
+
headerShadowVisible?: boolean
|
|
382
|
+
headerShown?: boolean
|
|
383
|
+
headerStyle?: {backgroundColor?: string}
|
|
384
|
+
headerTintColor?: string
|
|
385
|
+
headerTitleStyle?: {color?: string; fontFamily?: string; fontSize?: number}
|
|
386
|
+
headerTransparent?: boolean
|
|
387
|
+
scrollEdgeEffects?: {top?: 'automatic' | 'hidden'}
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
/** What `useHeader` needs of a screen's navigation object: React Navigation's and Expo Router's `useNavigation()` both. */
|
|
391
|
+
export type HeaderNavigation = {
|
|
392
|
+
setOptions(options: HeaderOptions): void
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
/** Something a list can scroll with: a `ScrollView`, a `FlatList`, a `FlashList` or a `LegendList`. */
|
|
396
|
+
export type HeaderScrollable =
|
|
397
|
+
| {getScrollResponder: () => {scrollTo: (options: {animated?: boolean; y?: number}) => void} | null | undefined}
|
|
398
|
+
| {scrollTo: (options: {animated?: boolean; y?: number}) => void}
|
|
399
|
+
| {scrollToOffset: (params: {animated?: boolean; offset: number}) => void}
|
|
400
|
+
|
|
401
|
+
export type HeaderScrollToTopOptions = {
|
|
402
|
+
/** Whether the screen has a large title, which the top includes on iOS. */
|
|
403
|
+
largeTitle?: boolean
|
|
404
|
+
/** Extra room above the content, for a bar the screen lays out under the header itself. */
|
|
405
|
+
topInset?: number
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
/** What React Navigation's and Expo Router's `useScrollToTop` call when its tab is pressed again. */
|
|
409
|
+
export type HeaderScrollToTopRef = RefObject<{scrollToTop: () => void}>
|
|
410
|
+
|
|
411
|
+
export type HeaderInsetProps = {
|
|
412
|
+
/** The content that starts right under the header. */
|
|
413
|
+
children?: ReactNode
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
export type HeaderInsetComponent = (props: HeaderInsetProps) => ReactNode
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import {useAppTheme} from '@hzblj/kara-theme'
|
|
2
|
+
import {StyleSheet} from 'react-native'
|
|
3
|
+
import Animated, {useAnimatedStyle} from 'react-native-reanimated'
|
|
4
|
+
|
|
5
|
+
import type {HeroHeaderBackgroundComponent, HeroHeaderBackgroundProps} from './hero-header-background.types'
|
|
6
|
+
|
|
7
|
+
const styles = StyleSheet.create({
|
|
8
|
+
bar: {left: 0, position: 'absolute', right: 0, top: 0},
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
/** The top app bar's surface, fading in behind the transparent bar as the hero scrolls away. */
|
|
12
|
+
export const HeroHeaderBackground: HeroHeaderBackgroundComponent = ({height, progress}: HeroHeaderBackgroundProps) => {
|
|
13
|
+
const theme = useAppTheme()
|
|
14
|
+
const animatedStyle = useAnimatedStyle(() => ({opacity: progress.value}))
|
|
15
|
+
|
|
16
|
+
return (
|
|
17
|
+
<Animated.View
|
|
18
|
+
pointerEvents="none"
|
|
19
|
+
style={[styles.bar, {backgroundColor: theme.color('surface.base'), height}, animatedStyle]}
|
|
20
|
+
/>
|
|
21
|
+
)
|
|
22
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import {isScrollEdgeEffectAvailable} from '@hzblj/kara-native'
|
|
2
|
+
import {StyleSheet, View} from 'react-native'
|
|
3
|
+
|
|
4
|
+
import {BlurView} from '../../atoms/blur-view'
|
|
5
|
+
import type {HeroHeaderBackgroundComponent, HeroHeaderBackgroundProps} from './hero-header-background.types'
|
|
6
|
+
|
|
7
|
+
const styles = StyleSheet.create({
|
|
8
|
+
bar: {left: 0, position: 'absolute', right: 0, top: 0},
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* iOS 26 draws the bar's background itself: its scroll edge effect, switched on once the reveal starts. Before it the
|
|
13
|
+
* bar's own blur cannot fade, so the bar's chrome material comes in behind the transparent bar by its intensity, the
|
|
14
|
+
* way UIKit fades a material in, rather than by its opacity.
|
|
15
|
+
*/
|
|
16
|
+
export const HeroHeaderBackground: HeroHeaderBackgroundComponent = ({height, progress}: HeroHeaderBackgroundProps) => {
|
|
17
|
+
if (isScrollEdgeEffectAvailable()) {
|
|
18
|
+
return null
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<View pointerEvents="none" style={[styles.bar, {height}]}>
|
|
23
|
+
<BlurView flex={1} intensity={progress} material="ultraThick" />
|
|
24
|
+
</View>
|
|
25
|
+
)
|
|
26
|
+
}
|