migrate reagent part 3 (#19165)

This commit is contained in:
flexsurfer 2024-03-13 16:46:44 +01:00 committed by GitHub
parent 98cdf00276
commit e26d3a856d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 315 additions and 343 deletions

View File

@ -1,7 +1,6 @@
(ns quo.components.colors.color-picker.component-spec (ns quo.components.colors.color-picker.component-spec
(:require (:require
[quo.components.colors.color-picker.view :as color-picker] [quo.components.colors.color-picker.view :as color-picker]
[reagent.core :as reagent]
[test-helpers.component :as h])) [test-helpers.component :as h]))
(h/describe "color-picker" (h/describe "color-picker"
@ -12,7 +11,7 @@
(-> (h/expect event) (-> (h/expect event)
(.toHaveBeenCalled)))) (.toHaveBeenCalled))))
(h/test "color picker color changed" (h/test "color picker color changed"
(let [selected (reagent/atom nil)] (let [selected (atom nil)]
(h/render [color-picker/view {:on-change #(reset! selected %)}]) (h/render [color-picker/view {:on-change #(reset! selected %)}])
(h/fire-event :press (get (h/get-all-by-label-text :color-picker-item) 0)) (h/fire-event :press (get (h/get-all-by-label-text :color-picker-item) 0))
(-> (h/expect @selected) (-> (h/expect @selected)

View File

@ -6,8 +6,7 @@
[quo.foundations.colors :as colors] [quo.foundations.colors :as colors]
[quo.theme :as quo.theme] [quo.theme :as quo.theme]
[react-native.core :as rn] [react-native.core :as rn]
[react-native.reanimated :as reanimated] [react-native.reanimated :as reanimated]))
[reagent.core :as reagent]))
(def header-height 56) (def header-height 56)
@ -57,7 +56,7 @@
:justify-content :center :justify-content :center
:align-items :flex-end}) :align-items :flex-end})
(defn title-style (defn get-title-style
[{:keys [left right]} title-align] [{:keys [left right]} title-align]
(merge (merge
absolute-fill absolute-fill
@ -133,76 +132,77 @@
:size :large} :size :large}
title])]) title])])
(defn- header-internal (defn header
[{:keys [left-width right-width]}] [{:keys [left-accessories left-component border-bottom left-width right-width
(let [layout (reagent/atom {:left {:width (or left-width 8) right-accessories right-component insets get-layout
:height header-height} title subtitle title-component style title-align
:right {:width (or right-width 8) background]
:height header-height} :or {title-align :center
:title {:width 0 border-bottom false}}]
:height header-height}}) (let [theme (quo.theme/use-theme-value)
handle-layout (fn [el get-layout] [layout set-layout] (rn/use-state {:left {:width (or left-width 8)
(fn [evt] :height header-height}
(let [width (oget evt "nativeEvent" "layout" "width") :right {:width (or right-width 8)
height (oget evt "nativeEvent" "layout" "height")] :height header-height}
(when get-layout :title {:width 0
(get-layout el :height header-height}})
{:width width handle-layout (rn/use-callback
:height height})) (fn [el get-layout]
(swap! layout assoc (fn [evt]
el (let [width (oget evt "nativeEvent" "layout" "width")
{:width width height (oget evt "nativeEvent" "layout" "height")]
:height height}))))] (when get-layout
(fn (get-layout el
[{:keys [left-accessories left-component border-bottom {:width width
right-accessories right-component insets get-layout :height height}))
title subtitle title-component style title-align (set-layout
background theme] (assoc layout
:or {title-align :center el
border-bottom false}}] {:width width
(let [status-bar-height (get insets :top 0) :height height})))))
height (+ header-height status-bar-height)] [layout])
[reanimated/view status-bar-height (get insets :top 0)
{:style (header-wrapper-style {:height height height (+ header-height status-bar-height)
:background background title-style (rn/use-memo (fn [] (get-title-style layout title-align))
:border-bottom border-bottom [layout title-align])]
:theme theme})} [reanimated/view
[rn/view {:style (header-wrapper-style {:height height
{:pointer-events :box-none :background background
:height status-bar-height}] :border-bottom border-bottom
[rn/view :theme theme})}
{:style (merge {:height header-height} [rn/view
style) {:pointer-events :box-none
:pointer-events :box-none} :height status-bar-height}]
[rn/view [rn/view
{:style absolute-fill {:style (merge {:height header-height}
:pointer-events :box-none} style)
[rn/view :pointer-events :box-none}
{:style content [rn/view
:pointer-events :box-none} {:style absolute-fill
[rn/view :pointer-events :box-none}
{:style left-style [rn/view
:on-layout (handle-layout :left get-layout) {:style content
:pointer-events :box-none} :pointer-events :box-none}
[header-actions [rn/view
{:accessories left-accessories {:style left-style
:component left-component}]] :on-layout (handle-layout :left get-layout)
:pointer-events :box-none}
[rn/view [header-actions
{:style (title-style @layout title-align) {:accessories left-accessories
:on-layout (handle-layout :title get-layout) :component left-component}]]
:pointer-events :box-none} [rn/view
[header-title {:style title-style
{:title title :on-layout (handle-layout :title get-layout)
:subtitle subtitle :pointer-events :box-none}
:title-align title-align [header-title
:component title-component}]] {:title title
[rn/view :subtitle subtitle
{:style right-style :title-align title-align
:on-layout (handle-layout :right get-layout) :component title-component}]]
:pointer-events :box-none} [rn/view
[header-actions {:style right-style
{:accessories right-accessories :on-layout (handle-layout :right get-layout)
:component right-component}]]]]]])))) :pointer-events :box-none}
[header-actions
(def header (quo.theme/with-theme header-internal)) {:accessories right-accessories
:component right-component}]]]]]]))

View File

@ -5,8 +5,7 @@
[quo.components.markdown.text :as text] [quo.components.markdown.text :as text]
[quo.foundations.colors :as colors] [quo.foundations.colors :as colors]
[quo.theme :as theme] [quo.theme :as theme]
[react-native.core :as rn] [react-native.core :as rn]))
[reagent.core :as reagent]))
;;; helpers ;;; helpers
(def themes (def themes
@ -137,24 +136,25 @@
style style
on-press on-press
warning-label]}] warning-label]}]
(let [body-height (reagent/atom nil)] (let [[body-height set-body-height] (rn/use-state nil)
(fn [] on-layout (rn/use-callback #(set-body-height
[rn/view (oget % "nativeEvent.layout.height")))]
{:on-layout #(reset! body-height (oget % "nativeEvent.layout.height")) [rn/view
:overflow :hidden {:on-layout on-layout
:flex 1} :overflow :hidden
[hborder {:type :top}] :flex 1}
[hborder {:type :bottom}] [hborder {:type :top}]
[rn/view [hborder {:type :bottom}]
(merge {:width "100%" [rn/view
:background-color (get-color :background) (merge {:width "100%"
:flex-direction :row :background-color (get-color :background)
:padding 20 :flex-direction :row
:padding-left 31 :padding 20
:margin-vertical 4} :padding-left 31
style) :margin-vertical 4}
style)
[timeline] [timeline]
[body timestamp-far timestamp-near on-info-button-pressed on-press warning-label]] [body timestamp-far timestamp-near on-info-button-pressed on-press warning-label]]
[vborder :left body-height] [vborder :left body-height]
[vborder :right body-height]]))) [vborder :right body-height]]))

View File

@ -4,50 +4,48 @@
[quo.components.markdown.text :as text] [quo.components.markdown.text :as text]
[quo.components.numbered-keyboard.keyboard-key.style :as style] [quo.components.numbered-keyboard.keyboard-key.style :as style]
[quo.theme :as quo.theme] [quo.theme :as quo.theme]
[react-native.core :as rn] [react-native.core :as rn]))
[reagent.core :as reagent]))
(defn- label->accessibility-label (defn- label->accessibility-label
[label] [label]
(let [label-name (if (keyword? label) (name label) label)] (let [label-name (if (keyword? label) (name label) label)]
(keyword (str "keyboard-key-" label-name)))) (keyword (str "keyboard-key-" label-name))))
(defn- view-internal (defn view
[] [{:keys [disabled? blur? on-press on-long-press type]} label]
(let [pressed? (reagent/atom false)] (let [theme (quo.theme/use-theme-value)
(fn [{:keys [disabled? theme blur? on-press on-long-press type]} label] [pressed? set-pressed?] (rn/use-state false)
(let [label-color (style/get-label-color disabled? theme blur?) on-press (rn/use-callback #(when on-press (on-press label)) [label])
background-color (style/toggle-background-color @pressed? blur? theme)] on-long-press (rn/use-callback #(when (fn? on-long-press) (on-long-press label))
[rn/pressable [label])
{:accessibility-label (label->accessibility-label label) on-press-in (rn/use-callback #(set-pressed? true))
:disabled (or disabled? (not label)) on-press-out (rn/use-callback #(set-pressed? false))
:on-press (fn [] label-color (style/get-label-color disabled? theme blur?)
(when on-press background-color (style/toggle-background-color pressed? blur? theme)]
(on-press label))) [rn/pressable
:on-long-press (fn [] {:accessibility-label (label->accessibility-label label)
(when (fn? on-long-press) :disabled (or disabled? (not label))
(on-long-press label))) :on-press on-press
:allow-multiple-presses? true :on-long-press on-long-press
:on-press-in #(reset! pressed? true) :allow-multiple-presses? true
:on-press-out #(reset! pressed? false) :on-press-in on-press-in
:hit-slop {:top 8 :bottom 8 :left 25 :right 25} :on-press-out on-press-out
:style (style/container background-color)} :hit-slop {:top 8 :bottom 8 :left 25 :right 25}
(case type :style (style/container background-color)}
:key [icons/icon (case type
label :key [icons/icon
{:color label-color label
:accessibility-label :icon-label}] {:color label-color
:digit [text/text :accessibility-label :icon-label}]
{:accessibility-label :text-label :digit [text/text
:weight :regular {:accessibility-label :text-label
:size :heading-1 :weight :regular
:style {:color label-color}} :size :heading-1
label] :style {:color label-color}}
:derivation-path [icons/icon label]
:i/derivation-path :derivation-path [icons/icon
{:color label-color :i/derivation-path
:size 32 {:color label-color
:accessibility-label :derivation-path-label}] :size 32
nil)])))) :accessibility-label :derivation-path-label}]
nil)]))
(def view (quo.theme/with-theme view-internal))

View File

@ -3,48 +3,33 @@
[quo.components.avatars.user-avatar.view :as user-avatar] [quo.components.avatars.user-avatar.view :as user-avatar]
[quo.components.markdown.text :as text] [quo.components.markdown.text :as text]
[quo.components.profile.select-profile.style :as style] [quo.components.profile.select-profile.style :as style]
[react-native.core :as rn] [react-native.core :as rn]))
[reagent.core :as reagent]))
(defn- on-change-handler
[selected? on-change]
(swap! selected? not)
(when on-change (on-change @selected?)))
(defn view (defn view
"Options "Options
- `default-selected?` The default selected state. Use when the component is not controlled.
- `selected?` Selected state. Use when the component is controlled. - `selected?` Selected state. Use when the component is controlled.
- `name` Full name - `name` Full name
- `profile-picture` Profile picture - `profile-picture` Profile picture
- `customization-color` Customization color - `customization-color` Customization color
- `(on-change selected?)` On change event handler - `(on-change selected?)` On change event handler
" "
[{:keys [default-selected?]}] [{:keys [selected? profile-picture name customization-color on-change]
(let [internal-selected? (reagent/atom (or default-selected? false))] :or {customization-color :turquoise}}]
(fn [{:keys [selected? [rn/touchable-opacity
profile-picture {:style (style/container customization-color selected?)
name :on-press #(when on-change (on-change (not selected?)))
customization-color :accessibility-label :select-profile}
on-change] [rn/view {:style style/header}
:or {customization-color :turquoise}}] [user-avatar/user-avatar
(when (and (not (nil? selected?)) (not= @internal-selected? selected?)) {:full-name name
(reset! internal-selected? selected?)) :status-indicator? false
[rn/touchable-opacity :size :medium
{:style (style/container customization-color @internal-selected?) :profile-picture profile-picture}]
:on-press #(on-change-handler internal-selected? on-change) [rn/view {:style (style/select-radio selected?)}
:active-opacity 1 (when selected?
:accessibility-label :select-profile} [rn/view {:style style/select-radio-inner}])]]
[rn/view {:style style/header} [text/text
[user-avatar/user-avatar {:size :heading-2
{:full-name name :weight :semi-bold
:status-indicator? false :style style/profile-name}
:size :medium name]])
:profile-picture profile-picture}]
[rn/view {:style (style/select-radio @internal-selected?)}
(when @internal-selected? [rn/view {:style style/select-radio-inner}])]]
[text/text
{:size :heading-2
:weight :semi-bold
:style style/profile-name}
name]])))

View File

@ -1,7 +1,6 @@
(ns quo.components.profile.showcase-nav.component-spec (ns quo.components.profile.showcase-nav.component-spec
(:require (:require
[quo.components.profile.showcase-nav.view :as view] [quo.components.profile.showcase-nav.view :as view]
[reagent.core :as reagent]
[test-helpers.component :as h])) [test-helpers.component :as h]))
(def nav-data (def nav-data
@ -35,7 +34,7 @@
(.toHaveBeenCalled)))) (.toHaveBeenCalled))))
(h/test "active id updated" (h/test "active id updated"
(let [active-id (reagent/atom :recent)] (let [active-id (atom :recent)]
(h/render [view/view (h/render [view/view
{:data nav-data {:data nav-data
:on-press #(reset! active-id %)}]) :on-press #(reset! active-id %)}])

View File

@ -7,17 +7,23 @@
[quo.foundations.colors :as colors] [quo.foundations.colors :as colors]
[quo.theme :as quo.theme] [quo.theme :as quo.theme]
[react-native.core :as rn] [react-native.core :as rn]
[react-native.draggable-flatlist :as draggable-flatlist] [react-native.draggable-flatlist :as draggable-flatlist]))
[reagent.core :as reagent]))
(defn on-drag-end-fn (defn key-fn [item index] (str (:title item) index))
[data atom-data]
(reset! atom-data data)
(reagent/flush))
(defn- reorder-category-internal (defn reorder-category
[{:keys [label data blur? theme container-style]}] [{:keys [label data blur? container-style]}]
(reagent/with-let [atom-data (reagent/atom data)] (let [theme (quo.theme/use-theme-value)
[atom-data set-atom-data] (rn/use-state data)
render-fn (rn/use-callback
(fn [item _ _ _ _ drag]
[reorder-item/reorder-item item types/item
{:blur? blur? :drag drag}])
[blur?])
on-drag-end-fn (rn/use-callback (fn [_ _ data] (set-atom-data data)))
separator (rn/use-memo (fn [] [rn/view
{:style (style/reorder-separator blur? theme)}])
[blur? theme])]
[rn/view {:style (merge (style/container label) container-style)} [rn/view {:style (merge (style/container label) container-style)}
[text/text [text/text
{:weight :medium {:weight :medium
@ -25,14 +31,9 @@
:style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)}} :style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)}}
label] label]
[draggable-flatlist/draggable-flatlist [draggable-flatlist/draggable-flatlist
{:data @atom-data {:data atom-data
:key-fn (fn [item index] (str (:title item) index)) :key-fn key-fn
:style style/reorder-items :style style/reorder-items
:render-fn (fn [item _ _ _ _ drag] [reorder-item/reorder-item item types/item :render-fn render-fn
{:blur? blur? :drag drag}]) :on-drag-end-fn on-drag-end-fn
:on-drag-end-fn (fn [_ _ data] :separator separator}]]))
(on-drag-end-fn data atom-data))
:separator [rn/view
{:style (style/reorder-separator blur? theme)}]}]]))
(def reorder-category (quo.theme/with-theme reorder-category-internal))

View File

@ -16,7 +16,6 @@
[quo.foundations.colors :as colors] [quo.foundations.colors :as colors]
[quo.theme] [quo.theme]
[react-native.core :as rn] [react-native.core :as rn]
[reagent.core :as reagent]
[schema.core :as schema] [schema.core :as schema]
[utils.i18n :as i18n])) [utils.i18n :as i18n]))
@ -190,20 +189,20 @@
(defn- view-internal (defn- view-internal
[props] [props]
(reagent/with-let [component-width (reagent/atom nil) (let [[component-width
container-component [rn/view {:background-color style/overlay-color}]] set-component-width] (rn/use-state nil)
on-layout (rn/use-callback #(set-component-width
(oops/oget % "nativeEvent.layout.width")))
props (-> props
(assoc :component-width component-width)
(clojure.set/rename-keys {:type :share-qr-type}))]
[quo.theme/provider {:theme :dark} [quo.theme/provider {:theme :dark}
[rn/view [rn/view
{:accessibility-label :share-qr-code {:accessibility-label :share-qr-code
:style style/outer-container :style style/outer-container
:on-layout #(reset! component-width (oops/oget % "nativeEvent.layout.width"))} :on-layout on-layout}
(conj container-component [rn/view {:style {:background-color style/overlay-color}}
(when @component-width (when component-width
[share-qr-code [share-qr-code props])]]]))
(-> props
(assoc :component-width @component-width)
(clojure.set/rename-keys {:type :share-qr-type}))]))]]))
(def view (def view (schema/instrument #'view-internal component-schema/?schema))
(quo.theme/with-theme
(schema/instrument #'view-internal component-schema/?schema)))

View File

@ -3,8 +3,7 @@
[quo.components.tabs.tab.view :as tab] [quo.components.tabs.tab.view :as tab]
[quo.foundations.colors :as colors] [quo.foundations.colors :as colors]
[quo.theme :as quo.theme] [quo.theme :as quo.theme]
[react-native.core :as rn] [react-native.core :as rn]))
[reagent.core :as reagent]))
(def themes-for-blur (def themes-for-blur
{:light {:background-color colors/neutral-80-opa-5} {:light {:background-color colors/neutral-80-opa-5}
@ -14,41 +13,41 @@
{:light {:background-color colors/neutral-10} {:light {:background-color colors/neutral-10}
:dark {:background-color colors/neutral-90}}) :dark {:background-color colors/neutral-90}})
(defn- segmented-control-internal (defn segmented-control
[{:keys [default-active on-change]}] [{:keys [data size blur? container-style item-container-style
(let [active-tab-id (reagent/atom default-active)] active-item-container-style default-active on-change]}]
(fn [{:keys [data size theme blur? container-style item-container-style (let [theme (quo.theme/use-theme-value)
active-item-container-style]}] [active-tab-id
(let [active-id @active-tab-id] set-active-tab-id] (rn/use-state default-active)
[rn/view on-press (rn/use-callback
(merge (fn [tab-id]
{:flex-direction :row (set-active-tab-id tab-id)
:background-color (get-in (if blur? themes-for-blur themes) (when on-change (on-change tab-id)))
[theme :background-color]) [on-change])]
:border-radius (case size [rn/view
32 10 (merge
28 10 {:flex-direction :row
24 8 :background-color (get-in (if blur? themes-for-blur themes)
20 6) [theme :background-color])
:padding 2} :border-radius (case size
container-style) 32 10
(for [[indx {:keys [label id]}] (map-indexed vector data)] 28 10
^{:key id} 24 8
[rn/view 20 6)
{:margin-left (if (= 0 indx) 0 2) :padding 2}
:flex 1} container-style)
[tab/view (for [[indx {:keys [label id]}] (map-indexed vector data)]
{:id id ^{:key id}
:active-item-container-style active-item-container-style [rn/view
:item-container-style item-container-style {:margin-left (if (= 0 indx) 0 2)
:segmented? true :flex 1}
:size size [tab/view
:blur? blur? {:id id
:active (= id active-id) :active-item-container-style active-item-container-style
:on-press (fn [tab-id] :item-container-style item-container-style
(reset! active-tab-id tab-id) :segmented? true
(when on-change :size size
(on-change tab-id)))} :blur? blur?
label]])])))) :active (= id active-tab-id)
:on-press on-press}
(def segmented-control (quo.theme/with-theme segmented-control-internal)) label]])]))

View File

@ -41,7 +41,7 @@
(into [:<>] children))) (into [:<>] children)))
(defn- on-scroll-handler (defn- on-scroll-handler
[{:keys [on-scroll fading fade-end-percentage fade-end?]} ^js e] [{:keys [on-scroll fading set-fading fade-end-percentage fade-end?]} ^js e]
(when fade-end? (when fade-end?
(let [offset-x (oget e "nativeEvent.contentOffset.x") (let [offset-x (oget e "nativeEvent.contentOffset.x")
content-width (oget e "nativeEvent.contentSize.width") content-width (oget e "nativeEvent.contentSize.width")
@ -52,11 +52,8 @@
:layout-width layout-width :layout-width layout-width
:max-fade-percentage fade-end-percentage})] :max-fade-percentage fade-end-percentage})]
;; Avoid unnecessary re-rendering. ;; Avoid unnecessary re-rendering.
(when (not= new-percentage (when (not= new-percentage (get fading :fade-end-percentage))
(get @fading :fade-end-percentage)) (set-fading (assoc fading :fade-end-percentage new-percentage)))))
(swap! fading assoc
:fade-end-percentage
new-percentage))))
(when on-scroll (when on-scroll
(on-scroll e))) (on-scroll e)))
@ -64,6 +61,7 @@
[{:keys [id label notification-dot? accessibility-label]} [{:keys [id label notification-dot? accessibility-label]}
index _ index _
{:keys [active-tab-id {:keys [active-tab-id
set-active-tab-id
blur? blur?
customization-color customization-color
flat-list-ref flat-list-ref
@ -85,9 +83,9 @@
:accessibility-label accessibility-label :accessibility-label accessibility-label
:size size :size size
:blur? blur? :blur? blur?
:active (= id @active-tab-id) :active (= id active-tab-id)
:on-press (fn [id] :on-press (fn [id]
(reset! active-tab-id id) (set-active-tab-id id)
(when (and scroll-on-press? @flat-list-ref) (when (and scroll-on-press? @flat-list-ref)
(.scrollToIndex ^js @flat-list-ref (.scrollToIndex ^js @flat-list-ref
#js #js
@ -118,87 +116,81 @@
- `scroll-on-press?` When non-nil, clicking on a tag centers it the middle - `scroll-on-press?` When non-nil, clicking on a tag centers it the middle
(with animation enabled). (with animation enabled).
" "
[{:keys [default-active fade-end-percentage] [{:keys [default-active data fade-end-percentage fade-end? on-change on-scroll scroll-on-press?
:or {fade-end-percentage 0.8}}] scrollable? style container-style size blur? in-scroll-view? customization-color]
(let [active-tab-id (reagent/atom default-active) :or {fade-end-percentage 0.8
fading (reagent/atom {:fade-end-percentage fade-end-percentage}) fade-end? false
flat-list-ref (atom nil)] scrollable? false
(fn scroll-on-press? false
[{:keys [data size default-tab-size}
fade-end-percentage :as props}]
fade-end? (let [[active-tab-id
on-change set-active-tab-id] (rn/use-state default-active)
on-scroll [fading set-fading] (rn/use-state {:fade-end-percentage fade-end-percentage})
scroll-on-press? flat-list-ref (rn/use-ref-atom nil)
scrollable? clean-props (dissoc props
style :default-active
container-style :fade-end-percentage
size :fade-end?
blur? :on-change
in-scroll-view? :scroll-on-press?
customization-color] :size)
:or {fade-end-percentage fade-end-percentage on-scroll (rn/use-callback
fade-end? false (partial on-scroll-handler
scrollable? false {:fade-end-percentage fade-end-percentage
scroll-on-press? false :fade-end? fade-end?
size default-tab-size} :fading fading
:as props}] :set-fading set-fading
(if scrollable? :on-scroll on-scroll})
[rn/view {:style {:margin-top (- (dec unread-count-offset))}} [fade-end? fading])]
[masked-view-wrapper (if scrollable?
{:fade-end-percentage (get @fading :fade-end-percentage) :fade-end? fade-end?} [rn/view {:style {:margin-top (- (dec unread-count-offset))}}
[(if in-scroll-view? [masked-view-wrapper
gesture/flat-list {:fade-end-percentage (get fading :fade-end-percentage) :fade-end? fade-end?}
rn/flat-list) [(if in-scroll-view?
(merge gesture/flat-list
(dissoc props rn/flat-list)
:default-active (merge
:fade-end-percentage clean-props
:fade-end? (when scroll-on-press?
:on-change {:initial-scroll-index (utils.collection/first-index #(= active-tab-id (:id %)) data)})
:scroll-on-press? {:ref #(reset! flat-list-ref %)
:size) :style style
(when scroll-on-press? ;; The padding-top workaround is needed because on Android
{:initial-scroll-index (utils.collection/first-index #(= @active-tab-id (:id %)) data)}) ;; {:overflow :visible} doesn't work on components inheriting
{:ref #(reset! flat-list-ref %) ;; from ScrollView (e.g. FlatList). There are open issues, here's
:style style ;; just one about this topic:
;; The padding-top workaround is needed because on Android ;; https://github.com/facebook/react-native/issues/31218
;; {:overflow :visible} doesn't work on components inheriting :content-container-style
;; from ScrollView (e.g. FlatList). There are open issues, here's (assoc container-style :padding-top (dec unread-count-offset))
;; just one about this topic: :horizontal true
;; https://github.com/facebook/react-native/issues/31218 :scroll-event-throttle 64
:content-container-style :shows-horizontal-scroll-indicator false
(assoc container-style :padding-top (dec unread-count-offset)) :data data
:horizontal true :key-fn (comp str :id)
:scroll-event-throttle 64 :on-scroll-to-index-failed identity
:shows-horizontal-scroll-indicator false :on-scroll on-scroll
:data data :render-fn tab-view
:key-fn (comp str :id) :render-data {:active-tab-id active-tab-id
:on-scroll-to-index-failed identity :set-active-tab-id set-active-tab-id
:on-scroll (partial on-scroll-handler :blur? blur?
{:fade-end-percentage fade-end-percentage :customization-color customization-color
:fade-end? fade-end? :flat-list-ref flat-list-ref
:fading fading :number-of-items (count data)
:on-scroll on-scroll}) :on-change on-change
:render-fn tab-view :scroll-on-press? scroll-on-press?
:render-data {:active-tab-id active-tab-id :size size
:blur? blur? :style style}})]]]
:customization-color customization-color [rn/view (merge style {:flex-direction :row})
:flat-list-ref flat-list-ref (map-indexed (fn [index item]
:number-of-items (count data) ^{:key (:id item)}
:on-change on-change [tab-view item index nil
:scroll-on-press? scroll-on-press? {:active-tab-id active-tab-id
:size size :set-active-tab-id set-active-tab-id
:style style}})]]] :blur? blur?
[rn/view (merge style {:flex-direction :row}) :customization-color customization-color
(map-indexed (fn [index item] :number-of-items (count data)
^{:key (:id item)} :on-change on-change
[tab-view item index nil :size size
{:active-tab-id active-tab-id :style style}])
:blur? blur? data)])))
:customization-color customization-color
:number-of-items (count data)
:on-change on-change
:size size
:style style}])
data)]))))