status-mobile/src/quo/components/animated_header.cljs

83 lines
3.3 KiB
Plaintext
Raw Normal View History

(ns quo.components.animated-header
(:require [oops.core :refer [oget]]
[quo.animated :as animated]
[quo.components.header :as header]
[quo.components.safe-area :as safe-area]
[quo.design-system.colors :as colors]
[quo.platform :as platform]
[quo.react-native :as rn]
[reagent.core :as reagent]))
(defn header-wrapper-style [{:keys [value offset]}]
(merge
{:background-color :white}
(when (and offset platform/android?)
{:elevation (animated/interpolate
value
{:inputRange [0 offset]
:outputRange [0 4]
:extrapolate (:clamp animated/extrapolate)})})
(when (and offset platform/ios?)
{:shadow-opacity (animated/interpolate
value
{:inputRange [0 offset]
:outputRange [0 1]
:extrapolate (:clamp animated/extrapolate)})
:shadow-radius 16
:z-index 2
:shadow-color (:shadow-01 @colors/theme)
:shadow-offset {:width 0 :height 4}})))
(defn header-opened-style [{:keys [value offset]}]
(merge
{:position :absolute
:top 0
:left 0
:right 0}
(when offset
{:transform [{:translateY
(animated/interpolate
value
{:inputRange [0 offset]
:outputRange [0 (- header/header-height)]
:extrapolateRight (:clamp animated/extrapolate)})}]})))
(defn header-container []
(let [y (animated/value 0)
on-scroll (animated/on-scroll {:y y})
layout (reagent/atom {})
offset (reagent/atom 0)
on-layout (fn [evt]
(reset! offset (oget evt "nativeEvent" "layout" "height")))]
(fn [{:keys [extended-header] :as props} & children]
[animated/view {:flex 1
:pointer-events :box-none}
[animated/view {:pointer-events :box-none
:style (header-wrapper-style {:value y
:offset @offset})}
[header/header (merge {:get-layout (fn [el l] (swap! layout assoc el l))}
(dissoc props :extended-header))]
[rn/view {:pointer-events :box-none}
[animated/view {:style (header-opened-style {:value y
:offset @offset})
:pointer-events :box-none
:on-layout on-layout}
[extended-header {:value y
:layout @layout
:offset @offset}]]]]
(into [animated/scroll-view {:on-scroll on-scroll
:scrollEventThrottle 1}
[rn/view {:pointer-events :box-none
:height @offset}]]
children)])))
(defn header [{:keys [use-insets] :as props} & children]
(if use-insets
[safe-area/consumer
(fn [insets]
[header-container (-> props
(dissoc :use-insets)
(assoc :insets insets))
children])]
[header-container props children]))