mirror of
https://github.com/status-im/status-react.git
synced 2025-02-28 18:40:54 +00:00
refactor: reformat all clojure code with zprint (#14589)
Co-authored-by: refactor-only <auto@status.im>
This commit is contained in:
parent
39e29cfb5a
commit
0a8993bbf1
@ -1,22 +1,25 @@
|
||||
(ns i18n.i18n
|
||||
(:require
|
||||
["i18n-js" :as i18n]
|
||||
[clojure.string :as string]
|
||||
[status-im.goog.i18n :as goog.i18n]))
|
||||
(:require ["i18n-js" :as i18n]
|
||||
[clojure.string :as string]
|
||||
[status-im.goog.i18n :as goog.i18n]))
|
||||
|
||||
(defn init [default-device-language translations-by-locale]
|
||||
(defn init
|
||||
[default-device-language translations-by-locale]
|
||||
(set! (.-fallbacks i18n) true)
|
||||
(set! (.-defaultSeparator i18n) "/")
|
||||
(set! (.-locale i18n) default-device-language)
|
||||
(set! (.-translations i18n) translations-by-locale))
|
||||
|
||||
(defn get-translations []
|
||||
(defn get-translations
|
||||
[]
|
||||
(.-translations i18n))
|
||||
|
||||
(defn set-language [lang]
|
||||
(defn set-language
|
||||
[lang]
|
||||
(set! (.-locale i18n) lang))
|
||||
|
||||
;;:zh, :zh-hans-xx, :zh-hant-xx have been added until this bug will be fixed https://github.com/fnando/i18n-js/issues/460
|
||||
;;:zh, :zh-hans-xx, :zh-hant-xx have been added until this bug will be fixed
|
||||
;;https://github.com/fnando/i18n-js/issues/460
|
||||
|
||||
(def delimeters
|
||||
"This function is a hack: mobile Safari doesn't support toLocaleString(), so we need to pass
|
||||
@ -29,7 +32,8 @@
|
||||
{:delimiter ""
|
||||
:separator (subs n 4 5)})))
|
||||
|
||||
(defn label-number [number]
|
||||
(defn label-number
|
||||
[number]
|
||||
(when number
|
||||
(let [{:keys [delimiter separator]} delimeters]
|
||||
(.toNumber i18n
|
||||
@ -41,7 +45,8 @@
|
||||
|
||||
(def default-option-value "<no value>")
|
||||
|
||||
(defn label-options [options]
|
||||
(defn label-options
|
||||
[options]
|
||||
;; i18n ignores nil value, leading to misleading messages
|
||||
(into {} (for [[k v] options] [k (or v default-option-value)])))
|
||||
|
||||
@ -55,7 +60,8 @@
|
||||
|
||||
(def label (memoize label-fn))
|
||||
|
||||
(defn label-pluralize [count path & options]
|
||||
(defn label-pluralize
|
||||
[count path & options]
|
||||
(if (exists? (.t i18n))
|
||||
(.p i18n count (name path) (clj->js options))
|
||||
(name path)))
|
||||
|
@ -4,11 +4,13 @@
|
||||
(:require [status-im.utils.test :as utils.test])
|
||||
(:require [status-im.chat.default-chats :refer (default-chats)]))
|
||||
|
||||
;; to generate a js Proxy at js/__STATUS_MOBILE_JS_IDENTITY_PROXY__ that accept any (.xxx) call and return itself
|
||||
;; to generate a js Proxy at js/__STATUS_MOBILE_JS_IDENTITY_PROXY__ that accept any (.xxx) call and
|
||||
;; return itself
|
||||
;; For the convenience to mock eg.
|
||||
;; (-> reanimated/slide-out-up-animation .springify (.damping 20) (.stiffness 300))
|
||||
;; (-> reanimated/slide-out-up-animation (.damping 20) .springify (.stiffness 300))
|
||||
(js/eval "
|
||||
(js/eval
|
||||
"
|
||||
var globalThis
|
||||
if (typeof window === \"undefined\") {
|
||||
globalThis = global
|
||||
@ -18,24 +20,24 @@ if (typeof window === \"undefined\") {
|
||||
globalThis.__STATUS_MOBILE_JS_IDENTITY_PROXY__ = new Proxy({}, {get() { return () => globalThis.__STATUS_MOBILE_JS_IDENTITY_PROXY__}})
|
||||
")
|
||||
|
||||
(def action-button #js {:default #js {:Item #js {}}})
|
||||
(def config #js {:default #js {}})
|
||||
(def camera #js {:RNCamera #js {:Constants #js {}}})
|
||||
(def dialogs #js {})
|
||||
(def dismiss-keyboard #js {})
|
||||
(def emoji-picker #js {:default #js {}})
|
||||
(def fs #js {})
|
||||
(def i18n #js {:locale "en"})
|
||||
(def image-crop-picker #js {})
|
||||
(def image-resizer #js {})
|
||||
(def qr-code #js {})
|
||||
(def svg #js {})
|
||||
(def action-button #js {:default #js {:Item #js {}}})
|
||||
(def config #js {:default #js {}})
|
||||
(def camera #js {:RNCamera #js {:Constants #js {}}})
|
||||
(def dialogs #js {})
|
||||
(def dismiss-keyboard #js {})
|
||||
(def emoji-picker #js {:default #js {}})
|
||||
(def fs #js {})
|
||||
(def i18n #js {:locale "en"})
|
||||
(def image-crop-picker #js {})
|
||||
(def image-resizer #js {})
|
||||
(def qr-code #js {})
|
||||
(def svg #js {})
|
||||
|
||||
(def react-native
|
||||
(clj->js {:NativeModules {:RNGestureHandlerModule {:Direction (fn [])}
|
||||
:PushNotifications {}
|
||||
:Status utils.test/status
|
||||
:ReanimatedModule {:configureProps (fn [])}}
|
||||
(clj->js {:NativeModules {:RNGestureHandlerModule {:Direction (fn [])}
|
||||
:PushNotifications {}
|
||||
:Status utils.test/status
|
||||
:ReanimatedModule {:configureProps (fn [])}}
|
||||
|
||||
:View {}
|
||||
:RefreshControl {}
|
||||
@ -78,9 +80,10 @@ globalThis.__STATUS_MOBILE_JS_IDENTITY_PROXY__ = new Proxy({}, {get() { return (
|
||||
:Platform {:select (fn [])}
|
||||
:I18nManager {:isRTL ""}
|
||||
:NativeEventEmitter (fn [])
|
||||
:LayoutAnimation {:Presets #js {:easeInEaseOut nil
|
||||
:linear nil
|
||||
:spring nil}
|
||||
:LayoutAnimation {:Presets #js
|
||||
{:easeInEaseOut nil
|
||||
:linear nil
|
||||
:spring nil}
|
||||
:Types #js {}
|
||||
:Properties #{}
|
||||
:create (fn [])
|
||||
@ -91,168 +94,199 @@ globalThis.__STATUS_MOBILE_JS_IDENTITY_PROXY__ = new Proxy({}, {get() { return (
|
||||
|
||||
(set! js/ReactNative react-native)
|
||||
|
||||
(def reanimated-bottom-sheet #js {:default #js {}})
|
||||
(def reanimated-bottom-sheet #js {:default #js {}})
|
||||
|
||||
(def icons #js {:default #js {}})
|
||||
(def webview #js {:WebView #js {}})
|
||||
(def status-keycard #js {:default #js {:nfcIsSupported (fn [] #js {:then identity})
|
||||
:nfcIsEnabled (fn [] #js {:then identity})}})
|
||||
(def icons #js {:default #js {}})
|
||||
(def webview #js {:WebView #js {}})
|
||||
(def status-keycard
|
||||
#js
|
||||
{:default #js
|
||||
{:nfcIsSupported (fn [] #js {:then identity})
|
||||
:nfcIsEnabled (fn [] #js {:then identity})}})
|
||||
|
||||
(def snoopy #js {:default #js {}})
|
||||
(def snoopy-filter #js {:default #js {}})
|
||||
(def snoopy-bars #js {:default #js {}})
|
||||
(def snoopy-buffer #js {:default #js {}})
|
||||
(def fetch #js {})
|
||||
(def snoopy #js {:default #js {}})
|
||||
(def snoopy-filter #js {:default #js {}})
|
||||
(def snoopy-bars #js {:default #js {}})
|
||||
(def snoopy-buffer #js {:default #js {}})
|
||||
(def fetch #js {})
|
||||
|
||||
(def async-storage-atom (atom {}))
|
||||
(def async-storage #js {:default #js {:setItem #(js/Promise.resolve)
|
||||
:multiGet #(js/Promise.resolve)
|
||||
:getItem #(js/Promise.resolve)}})
|
||||
(def async-storage
|
||||
#js
|
||||
{:default #js
|
||||
{:setItem #(js/Promise.resolve)
|
||||
:multiGet #(js/Promise.resolve)
|
||||
:getItem #(js/Promise.resolve)}})
|
||||
|
||||
(def background-timer (clj->js {:default {:setTimeout js/setTimeout
|
||||
:setInterval js/setInterval
|
||||
:clearTimeout js/clearTimeout
|
||||
:clearInterval js/clearInterval}}))
|
||||
(def background-timer
|
||||
(clj->js {:default {:setTimeout js/setTimeout
|
||||
:setInterval js/setInterval
|
||||
:clearTimeout js/clearTimeout
|
||||
:clearInterval js/clearInterval}}))
|
||||
|
||||
(def keychain #js {:setGenericPassword (constantly (.resolve js/Promise true))
|
||||
:setInternetCredentials #(js/Promise.resolve)
|
||||
:resetInternetCredentials #(js/Promise.resolve)
|
||||
"ACCESSIBLE" {}
|
||||
"ACCESS_CONTROL" {}})
|
||||
(def keychain
|
||||
#js
|
||||
{:setGenericPassword (constantly (.resolve js/Promise true))
|
||||
:setInternetCredentials #(js/Promise.resolve)
|
||||
:resetInternetCredentials #(js/Promise.resolve)
|
||||
"ACCESSIBLE" {}
|
||||
"ACCESS_CONTROL" {}})
|
||||
|
||||
(def react-native-mail #js {:mail #js {}})
|
||||
(def react-native-screens #js {})
|
||||
(def react-native-shake #js {})
|
||||
(def react-native-screens #js {})
|
||||
(def react-native-shake #js {})
|
||||
(def react-native-share #js {:default {}})
|
||||
(def react-native-svg #js {:SvgUri #js {:render identity}
|
||||
:SvgXml #js {:render identity}
|
||||
:default #js {:render identity}
|
||||
:Path #js {:render identity}})
|
||||
(def react-native-svg
|
||||
#js
|
||||
{:SvgUri #js {:render identity}
|
||||
:SvgXml #js {:render identity}
|
||||
:default #js {:render identity}
|
||||
:Path #js {:render identity}})
|
||||
(def react-native-webview #js {:default {}})
|
||||
(def react-native-audio-toolkit #js {:MediaStates {}})
|
||||
(def net-info #js {})
|
||||
(def touchid #js {})
|
||||
(def net-info #js {})
|
||||
(def touchid #js {})
|
||||
(def react-native-image-viewing #js {:default {}})
|
||||
(def safe-area-context (clj->js {:SafeAreaProvider {:_reactNativeIphoneXHelper {:getStatusBarHeight (fn [])}}
|
||||
:SafeAreaInsetsContext {:Consumer (fn [])}
|
||||
:SafeAreaView {}}))
|
||||
(def safe-area-context
|
||||
(clj->js {:SafeAreaProvider {:_reactNativeIphoneXHelper {:getStatusBarHeight (fn [])}}
|
||||
:SafeAreaInsetsContext {:Consumer (fn [])}
|
||||
:SafeAreaView {}}))
|
||||
|
||||
(def back-handler #js {:addEventListener identity
|
||||
:removeEventListener identity})
|
||||
(def react #js {:useCallback nil
|
||||
:useEffect nil
|
||||
:useRef nil
|
||||
:createRef nil
|
||||
:Fragment identity})
|
||||
(def react-navigation-native #js {:NavigationContainer #js {}
|
||||
:useFocusEffect identity
|
||||
:CommonActions #js {}
|
||||
:StackActions #js {}})
|
||||
(def back-handler
|
||||
#js
|
||||
{:addEventListener identity
|
||||
:removeEventListener identity})
|
||||
(def react
|
||||
#js
|
||||
{:useCallback nil
|
||||
:useEffect nil
|
||||
:useRef nil
|
||||
:createRef nil
|
||||
:Fragment identity})
|
||||
(def react-navigation-native
|
||||
#js
|
||||
{:NavigationContainer #js {}
|
||||
:useFocusEffect identity
|
||||
:CommonActions #js {}
|
||||
:StackActions #js {}})
|
||||
|
||||
(def react-native-navigation #js {:Navigation #js {:constants (fn [] #js {:then identity})
|
||||
:setDefaultOptions identity
|
||||
:setRoot identity
|
||||
:dismissOverlay #(js/Promise.resolve)
|
||||
:showOverlay identity
|
||||
:setLazyComponentRegistrator identity
|
||||
:pop identity
|
||||
:push identity
|
||||
:mergeOptions identity
|
||||
:popToRoot identity
|
||||
:showModal identity
|
||||
:dismissModal identity
|
||||
:registerComponent identity
|
||||
:events
|
||||
(fn []
|
||||
#js {:registerModalDismissedListener identity
|
||||
:registerAppLaunchedListener identity
|
||||
:registerBottomTabSelectedListener identity
|
||||
:registerComponentDidDisappearListener identity
|
||||
:registerComponentDidAppearListener identity
|
||||
:registerNavigationButtonPressedListener identity})}})
|
||||
(def react-native-navigation
|
||||
#js
|
||||
{:Navigation #js
|
||||
{:constants (fn [] #js {:then identity})
|
||||
:setDefaultOptions identity
|
||||
:setRoot identity
|
||||
:dismissOverlay #(js/Promise.resolve)
|
||||
:showOverlay identity
|
||||
:setLazyComponentRegistrator identity
|
||||
:pop identity
|
||||
:push identity
|
||||
:mergeOptions identity
|
||||
:popToRoot identity
|
||||
:showModal identity
|
||||
:dismissModal identity
|
||||
:registerComponent identity
|
||||
:events
|
||||
(fn []
|
||||
#js
|
||||
{:registerModalDismissedListener identity
|
||||
:registerAppLaunchedListener identity
|
||||
:registerBottomTabSelectedListener identity
|
||||
:registerComponentDidDisappearListener identity
|
||||
:registerComponentDidAppearListener identity
|
||||
:registerNavigationButtonPressedListener identity})}})
|
||||
|
||||
(def react-navigation-stack #js {:createStackNavigator identity
|
||||
:TransitionPresets #js {:ModalPresentationIOS #js {}}})
|
||||
(def react-navigation-stack
|
||||
#js
|
||||
{:createStackNavigator identity
|
||||
:TransitionPresets #js {:ModalPresentationIOS #js {}}})
|
||||
(def react-navigation-bottom-tabs #js {:createBottomTabNavigator identity})
|
||||
|
||||
(def react-native-haptic-feedback #js {:default #js {:trigger nil}})
|
||||
|
||||
(def react-native-reanimated #js {:default #js {:createAnimatedComponent identity
|
||||
:eq nil
|
||||
:greaterOrEq nil
|
||||
:greaterThan nil
|
||||
:lessThan nil
|
||||
:lessOrEq nil
|
||||
:add nil
|
||||
:diff nil
|
||||
:divide nil
|
||||
:sub nil
|
||||
:multiply nil
|
||||
:abs nil
|
||||
:min nil
|
||||
:max nil
|
||||
:neq nil
|
||||
:and nil
|
||||
:or nil
|
||||
:not nil
|
||||
:set nil
|
||||
:startClock nil
|
||||
:stopClock nil
|
||||
:Value nil
|
||||
:Clock nil
|
||||
:debug nil
|
||||
:log nil
|
||||
:event nil
|
||||
:cond nil
|
||||
:block nil
|
||||
:interpolateNode nil
|
||||
:call nil
|
||||
:timing nil
|
||||
:onChange nil
|
||||
:View #js {}
|
||||
:Image #js {}
|
||||
:ScrollView #js {}
|
||||
:Text #js {}
|
||||
:Extrapolate #js {:CLAMP nil}
|
||||
:Code #js {}}
|
||||
:EasingNode #js {:bezier identity
|
||||
:linear identity}
|
||||
:clockRunning nil
|
||||
:useSharedValue (fn [])
|
||||
:useAnimatedStyle (fn [])
|
||||
:withTiming (fn [])
|
||||
:withDelay (fn [])
|
||||
:Easing #js {:bezier identity}
|
||||
:Keyframe (fn [])
|
||||
:SlideOutUp js/__STATUS_MOBILE_JS_IDENTITY_PROXY__
|
||||
:SlideInUp js/__STATUS_MOBILE_JS_IDENTITY_PROXY__
|
||||
:LinearTransition js/__STATUS_MOBILE_JS_IDENTITY_PROXY__})
|
||||
(def react-native-gesture-handler #js {:default #js {}
|
||||
:State #js {:BEGAN nil
|
||||
:ACTIVE nil
|
||||
:CANCELLED nil
|
||||
:END nil
|
||||
:FAILED nil
|
||||
:UNDETERMINED nil}
|
||||
:PureNativeButton #js {}
|
||||
:TapGestureHandler #js {}
|
||||
:PanGestureHandler #js {}
|
||||
:TouchableHighlight #js {}
|
||||
:LongPressGestureHandler #js {}
|
||||
:TouchableWithoutFeedback #js {}
|
||||
:NativeViewGestureHandler #js {}
|
||||
:FlatList #js {}
|
||||
:ScrollView #js {}
|
||||
:TouchableOpacity #js {}
|
||||
:GestureDetector #js {}
|
||||
:Gesture #js {:Pan nil}
|
||||
:createNativeWrapper identity})
|
||||
(def react-native-reanimated
|
||||
#js
|
||||
{:default #js
|
||||
{:createAnimatedComponent identity
|
||||
:eq nil
|
||||
:greaterOrEq nil
|
||||
:greaterThan nil
|
||||
:lessThan nil
|
||||
:lessOrEq nil
|
||||
:add nil
|
||||
:diff nil
|
||||
:divide nil
|
||||
:sub nil
|
||||
:multiply nil
|
||||
:abs nil
|
||||
:min nil
|
||||
:max nil
|
||||
:neq nil
|
||||
:and nil
|
||||
:or nil
|
||||
:not nil
|
||||
:set nil
|
||||
:startClock nil
|
||||
:stopClock nil
|
||||
:Value nil
|
||||
:Clock nil
|
||||
:debug nil
|
||||
:log nil
|
||||
:event nil
|
||||
:cond nil
|
||||
:block nil
|
||||
:interpolateNode nil
|
||||
:call nil
|
||||
:timing nil
|
||||
:onChange nil
|
||||
:View #js {}
|
||||
:Image #js {}
|
||||
:ScrollView #js {}
|
||||
:Text #js {}
|
||||
:Extrapolate #js {:CLAMP nil}
|
||||
:Code #js {}}
|
||||
:EasingNode #js
|
||||
{:bezier identity
|
||||
:linear identity}
|
||||
:clockRunning nil
|
||||
:useSharedValue (fn [])
|
||||
:useAnimatedStyle (fn [])
|
||||
:withTiming (fn [])
|
||||
:withDelay (fn [])
|
||||
:Easing #js {:bezier identity}
|
||||
:Keyframe (fn [])
|
||||
:SlideOutUp js/__STATUS_MOBILE_JS_IDENTITY_PROXY__
|
||||
:SlideInUp js/__STATUS_MOBILE_JS_IDENTITY_PROXY__
|
||||
:LinearTransition js/__STATUS_MOBILE_JS_IDENTITY_PROXY__})
|
||||
(def react-native-gesture-handler
|
||||
#js
|
||||
{:default #js {}
|
||||
:State #js
|
||||
{:BEGAN nil
|
||||
:ACTIVE nil
|
||||
:CANCELLED nil
|
||||
:END nil
|
||||
:FAILED nil
|
||||
:UNDETERMINED nil}
|
||||
:PureNativeButton #js {}
|
||||
:TapGestureHandler #js {}
|
||||
:PanGestureHandler #js {}
|
||||
:TouchableHighlight #js {}
|
||||
:LongPressGestureHandler #js {}
|
||||
:TouchableWithoutFeedback #js {}
|
||||
:NativeViewGestureHandler #js {}
|
||||
:FlatList #js {}
|
||||
:ScrollView #js {}
|
||||
:TouchableOpacity #js {}
|
||||
:GestureDetector #js {}
|
||||
:Gesture #js {:Pan nil}
|
||||
:createNativeWrapper identity})
|
||||
|
||||
(def react-native-redash #js {:clamp nil})
|
||||
|
||||
(def react-native-languages
|
||||
(clj->js {:default {:language "en",
|
||||
:addEventListener (fn []),
|
||||
(clj->js {:default {:language "en"
|
||||
:addEventListener (fn [])
|
||||
:removeEventListener (fn [])}}))
|
||||
|
||||
(def react-native-device-info
|
||||
@ -262,8 +296,9 @@ globalThis.__STATUS_MOBILE_JS_IDENTITY_PROXY__ = new Proxy({}, {get() { return (
|
||||
#js {:CameraKitCamera #js {}})
|
||||
|
||||
(def react-native-push-notification
|
||||
#js {:localNotification identity
|
||||
:requestPermission identity})
|
||||
#js
|
||||
{:localNotification identity
|
||||
:requestPermission identity})
|
||||
|
||||
(def react-native-gradien #js {:default #js {}})
|
||||
|
||||
@ -291,12 +326,16 @@ globalThis.__STATUS_MOBILE_JS_IDENTITY_PROXY__ = new Proxy({}, {get() { return (
|
||||
(def react-native-camera-roll
|
||||
(clj->js {:default #js {}}))
|
||||
|
||||
(def wallet-connect-client #js {:default #js {}
|
||||
:CLIENT_EVENTS #js {:session #js {:request nil
|
||||
:created nil
|
||||
:deleted nil
|
||||
:proposal nil
|
||||
:updated nil}}})
|
||||
(def wallet-connect-client
|
||||
#js
|
||||
{:default #js {}
|
||||
:CLIENT_EVENTS #js
|
||||
{:session #js
|
||||
{:request nil
|
||||
:created nil
|
||||
:deleted nil
|
||||
:proposal nil
|
||||
:updated nil}}})
|
||||
|
||||
(def worklet-factory
|
||||
#js {:applyAnimationsToStyle (fn [])})
|
||||
@ -306,70 +345,71 @@ globalThis.__STATUS_MOBILE_JS_IDENTITY_PROXY__ = new Proxy({}, {get() { return (
|
||||
(def record-audio-worklets #js {})
|
||||
|
||||
;; Update i18n_resources.cljs
|
||||
(defn mock [module]
|
||||
(defn mock
|
||||
[module]
|
||||
(case module
|
||||
"react-native-languages" react-native-languages
|
||||
"react-native-background-timer" background-timer
|
||||
"react-native-image-crop-picker" image-crop-picker
|
||||
"react-native-gesture-handler" react-native-gesture-handler
|
||||
"react-native-safe-area-context" safe-area-context
|
||||
"react-native-config" config
|
||||
"react-native-iphone-x-helper" (clj->js {:getStatusBarHeight (fn [])
|
||||
:getBottomSpace (fn [])})
|
||||
"react-native-screens" (clj->js {})
|
||||
"react-native-reanimated" react-native-reanimated
|
||||
"react-native-redash/lib/module/v1" react-native-redash
|
||||
"react-native-fetch-polyfill" fetch
|
||||
"react-native-status-keycard" status-keycard
|
||||
"react-native-keychain" keychain
|
||||
"react-native-touch-id" touchid
|
||||
"@react-native-community/netinfo" net-info
|
||||
"react-native-dialogs" dialogs
|
||||
"react-native" react-native
|
||||
"react-native-fs" fs
|
||||
"react-native-mail" react-native-mail
|
||||
"react-native-image-resizer" image-resizer
|
||||
"react-native-haptic-feedback" react-native-haptic-feedback
|
||||
"react-native-device-info" react-native-device-info
|
||||
"react-native-push-notification" react-native-push-notification
|
||||
"react-native-linear-gradient" react-native-gradien
|
||||
"@react-native-community/masked-view" masked-view
|
||||
"react-native-blob-util" react-native-blob-util
|
||||
"react-native-navigation" react-native-navigation
|
||||
"react-native-languages" react-native-languages
|
||||
"react-native-background-timer" background-timer
|
||||
"react-native-image-crop-picker" image-crop-picker
|
||||
"react-native-gesture-handler" react-native-gesture-handler
|
||||
"react-native-safe-area-context" safe-area-context
|
||||
"react-native-config" config
|
||||
"react-native-iphone-x-helper" (clj->js {:getStatusBarHeight (fn [])
|
||||
:getBottomSpace (fn [])})
|
||||
"react-native-screens" (clj->js {})
|
||||
"react-native-reanimated" react-native-reanimated
|
||||
"react-native-redash/lib/module/v1" react-native-redash
|
||||
"react-native-fetch-polyfill" fetch
|
||||
"react-native-status-keycard" status-keycard
|
||||
"react-native-keychain" keychain
|
||||
"react-native-touch-id" touchid
|
||||
"@react-native-community/netinfo" net-info
|
||||
"react-native-dialogs" dialogs
|
||||
"react-native" react-native
|
||||
"react-native-fs" fs
|
||||
"react-native-mail" react-native-mail
|
||||
"react-native-image-resizer" image-resizer
|
||||
"react-native-haptic-feedback" react-native-haptic-feedback
|
||||
"react-native-device-info" react-native-device-info
|
||||
"react-native-push-notification" react-native-push-notification
|
||||
"react-native-linear-gradient" react-native-gradien
|
||||
"@react-native-community/masked-view" masked-view
|
||||
"react-native-blob-util" react-native-blob-util
|
||||
"react-native-navigation" react-native-navigation
|
||||
"@react-native-community/push-notification-ios" push-notification-ios
|
||||
"@react-native-community/blur" react-native-blur
|
||||
"@react-native-community/cameraroll" react-native-camera-roll
|
||||
"react-native-camera-kit" react-native-camera-kit
|
||||
"react-native-permissions" react-native-permissions
|
||||
"rn-emoji-keyboard" rn-emoji-keyboard
|
||||
"react-native-hole-view" react-native-hole-view
|
||||
"react-native-draggable-flatlist" react-native-draggable-flatlist
|
||||
"react-native-webview" react-native-webview
|
||||
"@react-native-community/audio-toolkit" react-native-audio-toolkit
|
||||
"react-native-image-viewing" react-native-image-viewing
|
||||
"react-native-share" react-native-share
|
||||
"@react-native-async-storage/async-storage" async-storage
|
||||
"react-native-svg" react-native-svg
|
||||
"../src/js/worklet_factory.js" worklet-factory
|
||||
"../src/js/shell_worklets.js" shell-worklets
|
||||
"../src/js/record_audio_worklets.js" record-audio-worklets
|
||||
"./fleets.js" default-fleets
|
||||
"./chats.js" default-chats
|
||||
"@walletconnect/client" wallet-connect-client
|
||||
"../translations/ar.json" (js/JSON.parse (slurp "./translations/ar.json"))
|
||||
"../translations/de.json" (js/JSON.parse (slurp "./translations/de.json"))
|
||||
"../translations/en.json" (js/JSON.parse (slurp "./translations/en.json"))
|
||||
"../translations/es.json" (js/JSON.parse (slurp "./translations/es.json"))
|
||||
"../translations/es_419.json" (js/JSON.parse (slurp "./translations/es_419.json"))
|
||||
"../translations/fil.json" (js/JSON.parse (slurp "./translations/fil.json"))
|
||||
"../translations/fr.json" (js/JSON.parse (slurp "./translations/fr.json"))
|
||||
"../translations/id.json" (js/JSON.parse (slurp "./translations/id.json"))
|
||||
"../translations/it.json" (js/JSON.parse (slurp "./translations/it.json"))
|
||||
"../translations/ko.json" (js/JSON.parse (slurp "./translations/ko.json"))
|
||||
"../translations/pt_BR.json" (js/JSON.parse (slurp "./translations/pt_BR.json"))
|
||||
"../translations/ru.json" (js/JSON.parse (slurp "./translations/ru.json"))
|
||||
"../translations/tr.json" (js/JSON.parse (slurp "./translations/tr.json"))
|
||||
"../translations/zh.json" (js/JSON.parse (slurp "./translations/zh.json"))
|
||||
"../translations/zh_hant.json" (js/JSON.parse (slurp "./translations/zh_hant.json"))
|
||||
"../translations/zh_TW.json" (js/JSON.parse (slurp "./translations/zh_TW.json"))
|
||||
"@react-native-community/blur" react-native-blur
|
||||
"@react-native-community/cameraroll" react-native-camera-roll
|
||||
"react-native-camera-kit" react-native-camera-kit
|
||||
"react-native-permissions" react-native-permissions
|
||||
"rn-emoji-keyboard" rn-emoji-keyboard
|
||||
"react-native-hole-view" react-native-hole-view
|
||||
"react-native-draggable-flatlist" react-native-draggable-flatlist
|
||||
"react-native-webview" react-native-webview
|
||||
"@react-native-community/audio-toolkit" react-native-audio-toolkit
|
||||
"react-native-image-viewing" react-native-image-viewing
|
||||
"react-native-share" react-native-share
|
||||
"@react-native-async-storage/async-storage" async-storage
|
||||
"react-native-svg" react-native-svg
|
||||
"../src/js/worklet_factory.js" worklet-factory
|
||||
"../src/js/shell_worklets.js" shell-worklets
|
||||
"../src/js/record_audio_worklets.js" record-audio-worklets
|
||||
"./fleets.js" default-fleets
|
||||
"./chats.js" default-chats
|
||||
"@walletconnect/client" wallet-connect-client
|
||||
"../translations/ar.json" (js/JSON.parse (slurp "./translations/ar.json"))
|
||||
"../translations/de.json" (js/JSON.parse (slurp "./translations/de.json"))
|
||||
"../translations/en.json" (js/JSON.parse (slurp "./translations/en.json"))
|
||||
"../translations/es.json" (js/JSON.parse (slurp "./translations/es.json"))
|
||||
"../translations/es_419.json" (js/JSON.parse (slurp "./translations/es_419.json"))
|
||||
"../translations/fil.json" (js/JSON.parse (slurp "./translations/fil.json"))
|
||||
"../translations/fr.json" (js/JSON.parse (slurp "./translations/fr.json"))
|
||||
"../translations/id.json" (js/JSON.parse (slurp "./translations/id.json"))
|
||||
"../translations/it.json" (js/JSON.parse (slurp "./translations/it.json"))
|
||||
"../translations/ko.json" (js/JSON.parse (slurp "./translations/ko.json"))
|
||||
"../translations/pt_BR.json" (js/JSON.parse (slurp "./translations/pt_BR.json"))
|
||||
"../translations/ru.json" (js/JSON.parse (slurp "./translations/ru.json"))
|
||||
"../translations/tr.json" (js/JSON.parse (slurp "./translations/tr.json"))
|
||||
"../translations/zh.json" (js/JSON.parse (slurp "./translations/zh.json"))
|
||||
"../translations/zh_hant.json" (js/JSON.parse (slurp "./translations/zh_hant.json"))
|
||||
"../translations/zh_TW.json" (js/JSON.parse (slurp "./translations/zh_TW.json"))
|
||||
nil))
|
||||
|
@ -1,12 +1,12 @@
|
||||
(ns quo.animated
|
||||
(:refer-clojure :exclude [abs set delay divide])
|
||||
(:require [reagent.core :as reagent]
|
||||
[quo.react-native :as rn]
|
||||
[quo.gesture-handler :as gh]
|
||||
[oops.core :refer [oget ocall]]
|
||||
["react-native-reanimated" :default animated :refer (clockRunning EasingNode)]
|
||||
(:require ["react-native-reanimated" :default animated :refer (clockRunning EasingNode)]
|
||||
["react-native-redash/lib/module/v1" :as redash]
|
||||
quo.react)
|
||||
[oops.core :refer [ocall oget]]
|
||||
[quo.gesture-handler :as gh]
|
||||
quo.react
|
||||
[quo.react-native :as rn]
|
||||
[reagent.core :as reagent])
|
||||
(:require-macros [quo.react :refer [maybe-js-deps]]))
|
||||
|
||||
(def create-animated-component (comp reagent/adapt-react-class (.-createAnimatedComponent animated)))
|
||||
@ -15,9 +15,10 @@
|
||||
(def text (reagent/adapt-react-class (.-Text animated)))
|
||||
(def scroll-view (reagent/adapt-react-class (.-ScrollView animated)))
|
||||
(def code (reagent/adapt-react-class (.-Code animated)))
|
||||
(def animated-flat-list (create-animated-component gh/flat-list-raw))
|
||||
(def animated-flat-list (create-animated-component gh/flat-list-raw))
|
||||
|
||||
(defn flat-list [props]
|
||||
(defn flat-list
|
||||
[props]
|
||||
[animated-flat-list (rn/base-list-props props)])
|
||||
|
||||
(def useCode (.-useCode animated))
|
||||
@ -58,37 +59,42 @@
|
||||
(def bezier (.-bezier ^js EasingNode))
|
||||
(def linear (.-linear ^js EasingNode))
|
||||
|
||||
(def easings {:linear linear
|
||||
:ease-in (bezier 0.42 0 1 1)
|
||||
:ease-out (bezier 0 0 0.58 1)
|
||||
:ease-in-out (bezier 0.42 0 0.58 1)
|
||||
:cubic (bezier 0.55 0.055 0.675 0.19)
|
||||
:keyboard (bezier 0.17 0.59 0.4 0.77)})
|
||||
(def easings
|
||||
{:linear linear
|
||||
:ease-in (bezier 0.42 0 1 1)
|
||||
:ease-out (bezier 0 0 0.58 1)
|
||||
:ease-in-out (bezier 0.42 0 0.58 1)
|
||||
:cubic (bezier 0.55 0.055 0.675 0.19)
|
||||
:keyboard (bezier 0.17 0.59 0.4 0.77)})
|
||||
|
||||
(def springs {:lazy {:damping 50
|
||||
:mass 0.3
|
||||
:stiffness 120
|
||||
:overshootClamping true
|
||||
:bouncyFactor 1}
|
||||
:jump {:damping 13
|
||||
:mass 0.5
|
||||
:stiffness 170
|
||||
:overshootClamping false
|
||||
:bouncyFactor 1
|
||||
:restSpeedThreshold 0.001
|
||||
:restDisplacementThreshold 0.001}})
|
||||
(def springs
|
||||
{:lazy {:damping 50
|
||||
:mass 0.3
|
||||
:stiffness 120
|
||||
:overshootClamping true
|
||||
:bouncyFactor 1}
|
||||
:jump {:damping 13
|
||||
:mass 0.5
|
||||
:stiffness 170
|
||||
:overshootClamping false
|
||||
:bouncyFactor 1
|
||||
:restSpeedThreshold 0.001
|
||||
:restDisplacementThreshold 0.001}})
|
||||
|
||||
(defn set-value [anim val]
|
||||
(defn set-value
|
||||
[anim val]
|
||||
(ocall anim "setValue" val))
|
||||
|
||||
(def Value (oget animated "Value"))
|
||||
|
||||
(defn value [x]
|
||||
(defn value
|
||||
[x]
|
||||
(new Value x))
|
||||
|
||||
(def Clock (oget animated "Clock"))
|
||||
|
||||
(defn clock []
|
||||
(defn clock
|
||||
[]
|
||||
(new Clock))
|
||||
|
||||
(def debug (oget animated "debug"))
|
||||
@ -100,8 +106,10 @@
|
||||
([config options]
|
||||
(ocall animated "event" (clj->js config) (clj->js options))))
|
||||
|
||||
(defn on-change [state node]
|
||||
(ocall animated "onChange"
|
||||
(defn on-change
|
||||
[state node]
|
||||
(ocall animated
|
||||
"onChange"
|
||||
state
|
||||
(if (vector? node)
|
||||
(clj->js node)
|
||||
@ -124,24 +132,31 @@
|
||||
(clj->js else-node)
|
||||
else-node))))
|
||||
|
||||
(defn block [opts]
|
||||
(defn block
|
||||
[opts]
|
||||
(.block ^js animated (to-array opts)))
|
||||
|
||||
(defn interpolate [anim-value config]
|
||||
(defn interpolate
|
||||
[anim-value config]
|
||||
(.interpolateNode ^js animated anim-value (clj->js config)))
|
||||
|
||||
(defn call* [args callback]
|
||||
(defn call*
|
||||
[args callback]
|
||||
(.call ^js animated (to-array args) callback))
|
||||
|
||||
(defn timing [clock-value opts config]
|
||||
(defn timing
|
||||
[clock-value opts config]
|
||||
(.timing ^js animated
|
||||
clock-value
|
||||
(clj->js opts)
|
||||
(clj->js config)))
|
||||
|
||||
(defn spring [clock-value opts config]
|
||||
(.spring ^js animated clock-value
|
||||
(clj->js opts) (clj->js config)))
|
||||
(defn spring
|
||||
[clock-value opts config]
|
||||
(.spring ^js animated
|
||||
clock-value
|
||||
(clj->js opts)
|
||||
(clj->js config)))
|
||||
|
||||
(def extrapolate {:clamp (oget animated "Extrapolate" "CLAMP")})
|
||||
|
||||
@ -150,37 +165,48 @@
|
||||
(def clamp (oget redash "clamp"))
|
||||
(def diff-clamp (.-diffClamp ^js redash))
|
||||
|
||||
(defn with-spring [config]
|
||||
(defn with-spring
|
||||
[config]
|
||||
(ocall redash "withSpring" (clj->js config)))
|
||||
|
||||
(defn with-decay [config]
|
||||
(defn with-decay
|
||||
[config]
|
||||
(.withDecay ^js redash (clj->js config)))
|
||||
|
||||
(defn with-offset [config]
|
||||
(defn with-offset
|
||||
[config]
|
||||
(.withOffset ^js redash (clj->js config)))
|
||||
|
||||
(defn with-spring-transition [val config]
|
||||
(defn with-spring-transition
|
||||
[val config]
|
||||
(.withSpringTransition ^js redash val (clj->js config)))
|
||||
|
||||
(defn with-timing-transition [val config]
|
||||
(defn with-timing-transition
|
||||
[val config]
|
||||
(.withTimingTransition ^js redash val (clj->js config)))
|
||||
|
||||
(defn use-spring-transition [val config]
|
||||
(defn use-spring-transition
|
||||
[val config]
|
||||
(.useSpringTransition ^js redash val (clj->js config)))
|
||||
|
||||
(defn use-timing-transition [val config]
|
||||
(defn use-timing-transition
|
||||
[val config]
|
||||
(.useTimingTransition ^js redash val (clj->js config)))
|
||||
|
||||
(defn re-timing [config]
|
||||
(defn re-timing
|
||||
[config]
|
||||
(.timing ^js redash (clj->js config)))
|
||||
|
||||
(defn re-spring [config]
|
||||
(defn re-spring
|
||||
[config]
|
||||
(.spring ^js redash (clj->js config)))
|
||||
|
||||
(defn on-scroll [opts]
|
||||
(defn on-scroll
|
||||
[opts]
|
||||
(ocall redash "onScrollEvent" (clj->js opts)))
|
||||
|
||||
(defn on-gesture [opts]
|
||||
(defn on-gesture
|
||||
[opts]
|
||||
(let [gesture-event (event #js [#js {:nativeEvent (clj->js opts)}])]
|
||||
{:onHandlerStateChange gesture-event
|
||||
:onGestureEvent gesture-event}))
|
||||
@ -191,19 +217,22 @@
|
||||
|
||||
(def delay (.-delay ^js redash))
|
||||
|
||||
(defn loop* [opts]
|
||||
(defn loop*
|
||||
[opts]
|
||||
(ocall redash "loop" (clj->js opts)))
|
||||
|
||||
(def use-value (.-useValue ^js redash))
|
||||
|
||||
(def use-clock (.-useClock ^js redash))
|
||||
|
||||
(defn use-gesture [opts]
|
||||
(defn use-gesture
|
||||
[opts]
|
||||
(let [gesture (.useGestureHandler ^js redash (clj->js opts))]
|
||||
{:onHandlerStateChange (.-onHandlerStateChange ^js gesture)
|
||||
:onGestureEvent (.-onGestureEvent ^js gesture)}))
|
||||
|
||||
(defn snap-point [value velocity snap-points]
|
||||
(defn snap-point
|
||||
[value velocity snap-points]
|
||||
(.snapPoint ^js redash value velocity (to-array snap-points)))
|
||||
|
||||
(defn cancelable-loop
|
||||
@ -256,12 +285,13 @@
|
||||
(set position (add offset val))])
|
||||
(cond* (and* (eq state (:end gh/states))
|
||||
(not* animation-over))
|
||||
[(set position (re-timing
|
||||
{:clock c
|
||||
:easing easing
|
||||
:duration duration
|
||||
:from position
|
||||
:to to}))
|
||||
[(set position
|
||||
(re-timing
|
||||
{:clock c
|
||||
:easing easing
|
||||
:duration duration
|
||||
:from position
|
||||
:to to}))
|
||||
(cond* (not* (clock-running c))
|
||||
finish-animation)])
|
||||
position])))
|
||||
|
@ -1,9 +1,9 @@
|
||||
(ns quo.components.animated.pressable
|
||||
(:require [quo.animated :as animated]
|
||||
(:require [cljs-bean.core :as bean]
|
||||
[quo.animated :as animated]
|
||||
[quo.gesture-handler :as gesture-handler]
|
||||
[quo.react :as react]
|
||||
[reagent.core :as reagent]
|
||||
[cljs-bean.core :as bean]
|
||||
[quo.gesture-handler :as gesture-handler]))
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
(def long-press-duration 500)
|
||||
(def scale-down-small 0.95)
|
||||
@ -54,7 +54,8 @@
|
||||
:right 0
|
||||
:position :absolute})
|
||||
|
||||
(defn pressable-hooks [props]
|
||||
(defn pressable-hooks
|
||||
[props]
|
||||
(let [{background-color :bgColor
|
||||
border-radius :borderRadius
|
||||
border-color :borderColor
|
||||
@ -69,23 +70,24 @@
|
||||
:or {border-radius 0
|
||||
type "primary"}}
|
||||
(bean/bean props)
|
||||
long-press-ref (react/create-ref)
|
||||
state (animated/use-value (:undetermined gesture-handler/states))
|
||||
active (animated/eq state (:began gesture-handler/states))
|
||||
gesture-handler (animated/use-gesture {:state state})
|
||||
animation (react/use-memo
|
||||
(fn []
|
||||
(animated/with-timing-transition active
|
||||
{:duration (animated/cond* active time-in time-out)
|
||||
:easing (:ease-in animated/easings)}))
|
||||
[])
|
||||
long-press-ref (react/create-ref)
|
||||
state (animated/use-value (:undetermined gesture-handler/states))
|
||||
active (animated/eq state (:began gesture-handler/states))
|
||||
gesture-handler (animated/use-gesture {:state state})
|
||||
animation (react/use-memo
|
||||
(fn []
|
||||
(animated/with-timing-transition active
|
||||
{:duration (animated/cond* active time-in time-out)
|
||||
:easing (:ease-in animated/easings)}))
|
||||
[])
|
||||
{:keys [background
|
||||
foreground]} (react/use-memo
|
||||
(fn []
|
||||
(type->animation {:type (keyword type)
|
||||
:animation animation}))
|
||||
[type])
|
||||
handle-press (fn [] (when on-press (on-press)))
|
||||
foreground]}
|
||||
(react/use-memo
|
||||
(fn []
|
||||
(type->animation {:type (keyword type)
|
||||
:animation animation}))
|
||||
[type])
|
||||
handle-press (fn [] (when on-press (on-press)))
|
||||
long-gesture-handler (react/callback
|
||||
(fn [^js evt]
|
||||
(let [gesture-state (-> evt .-nativeEvent .-state)]
|
||||
@ -111,8 +113,9 @@
|
||||
:min-duration-ms long-press-duration
|
||||
:max-dist 22
|
||||
:ref long-press-ref}
|
||||
[animated/view {:accessible true
|
||||
:accessibility-label accessibility-label}
|
||||
[animated/view
|
||||
{:accessible true
|
||||
:accessibility-label accessibility-label}
|
||||
[gesture-handler/tap-gesture-handler
|
||||
(merge gesture-handler
|
||||
{:shouldCancelWhenOutside true
|
||||
@ -120,12 +123,13 @@
|
||||
:enabled (boolean (and (or on-press on-long-press on-press-start)
|
||||
(not disabled)))})
|
||||
[animated/view
|
||||
[animated/view {:style (merge absolute-fill
|
||||
background
|
||||
{:background-color background-color
|
||||
:border-radius border-radius
|
||||
:border-color border-color
|
||||
:border-width border-width})}]
|
||||
[animated/view
|
||||
{:style (merge absolute-fill
|
||||
background
|
||||
{:background-color background-color
|
||||
:border-radius border-radius
|
||||
:border-color border-color
|
||||
:border-width border-width})}]
|
||||
(into [animated/view {:style foreground}]
|
||||
(react/get-children children))]]]])))
|
||||
|
||||
|
@ -7,7 +7,8 @@
|
||||
[quo.platform :as platform]
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
(defn header-wrapper-style [{:keys [value offset]}]
|
||||
(defn header-wrapper-style
|
||||
[{:keys [value offset]}]
|
||||
(merge
|
||||
{:background-color (:ui-background @colors/theme)}
|
||||
(when (and offset platform/android?)
|
||||
@ -27,66 +28,78 @@
|
||||
:shadow-color (:shadow-01 @colors/theme)
|
||||
:shadow-offset {:width 0 :height 4}})))
|
||||
|
||||
(defn title-style [layout]
|
||||
{:flex 1
|
||||
(defn title-style
|
||||
[layout]
|
||||
{:flex 1
|
||||
:justify-content :center
|
||||
:padding-right (get-in layout [:right :width])})
|
||||
:padding-right (get-in layout [:right :width])})
|
||||
|
||||
(defn header-container []
|
||||
(defn header-container
|
||||
[]
|
||||
(let [y (animated/value 0)
|
||||
animation-value (animated/value 0)
|
||||
animation (animated/with-timing-transition
|
||||
animation-value
|
||||
{:duration 250
|
||||
:easing (:ease-in animated/easings)})
|
||||
animation-value
|
||||
{:duration 250
|
||||
:easing (:ease-in animated/easings)})
|
||||
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 refresh-control refreshing-sub refreshing-counter] :as props} children]
|
||||
[animated/view {:flex 1
|
||||
:pointer-events :box-none}
|
||||
[animated/code {:key (str @offset)
|
||||
:exec (animated/cond*
|
||||
(animated/and* (animated/greater-or-eq y @offset)
|
||||
(animated/greater-or-eq y 1))
|
||||
(animated/set animation-value 1)
|
||||
(animated/set animation-value 0))}]
|
||||
[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))
|
||||
:border-bottom false
|
||||
:title-component [animated/view {:style (title-style @layout)}
|
||||
[extended-header {:value y
|
||||
:animation animation
|
||||
:minimized true
|
||||
:offset @offset}]]
|
||||
:title-align :left}
|
||||
(dissoc props :extended-header))]]
|
||||
(into [animated/scroll-view {:on-scroll on-scroll
|
||||
:refreshControl (when refresh-control
|
||||
(refresh-control
|
||||
(and @refreshing-sub
|
||||
@refreshing-counter)))
|
||||
:style {:z-index 1}
|
||||
:scrollEventThrottle 16}
|
||||
[animated/view
|
||||
{:flex 1
|
||||
:pointer-events :box-none}
|
||||
[animated/code
|
||||
{:key (str @offset)
|
||||
:exec (animated/cond*
|
||||
(animated/and* (animated/greater-or-eq y @offset)
|
||||
(animated/greater-or-eq y 1))
|
||||
(animated/set animation-value 1)
|
||||
(animated/set animation-value 0))}]
|
||||
[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))
|
||||
:border-bottom false
|
||||
:title-component [animated/view {:style (title-style @layout)}
|
||||
[extended-header
|
||||
{:value y
|
||||
:animation animation
|
||||
:minimized true
|
||||
:offset @offset}]]
|
||||
:title-align :left}
|
||||
(dissoc props :extended-header))]]
|
||||
(into [animated/scroll-view
|
||||
{:on-scroll on-scroll
|
||||
:refreshControl (when refresh-control
|
||||
(refresh-control
|
||||
(and @refreshing-sub
|
||||
@refreshing-counter)))
|
||||
:style {:z-index 1}
|
||||
:scrollEventThrottle 16}
|
||||
[animated/view {:pointer-events :box-none}
|
||||
[animated/view {:pointer-events :box-none
|
||||
:on-layout on-layout}
|
||||
[extended-header {:value y
|
||||
:animation animation
|
||||
:offset @offset}]]]]
|
||||
[animated/view
|
||||
{:pointer-events :box-none
|
||||
:on-layout on-layout}
|
||||
[extended-header
|
||||
{:value y
|
||||
:animation animation
|
||||
:offset @offset}]]]]
|
||||
children)])))
|
||||
|
||||
(defn header [{:keys [use-insets] :as props} & 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))
|
||||
[header-container
|
||||
(-> props
|
||||
(dissoc :use-insets)
|
||||
(assoc :insets insets))
|
||||
children])]
|
||||
[header-container props children]))
|
||||
|
@ -15,13 +15,14 @@
|
||||
:flex 1
|
||||
:justify-content :flex-end})
|
||||
|
||||
(defn backdrop []
|
||||
{:flex 1
|
||||
:position :absolute
|
||||
:left 0
|
||||
:top 0
|
||||
:right 0
|
||||
:bottom 0})
|
||||
(defn backdrop
|
||||
[]
|
||||
{:flex 1
|
||||
:position :absolute
|
||||
:left 0
|
||||
:top 0
|
||||
:right 0
|
||||
:bottom 0})
|
||||
|
||||
(defn content-container
|
||||
[window-height]
|
||||
|
@ -1,25 +1,27 @@
|
||||
(ns quo.components.bottom-sheet.view
|
||||
(:require [reagent.core :as reagent]
|
||||
(:require [cljs-bean.core :as bean]
|
||||
[quo.animated :as animated]
|
||||
[quo.react-native :as rn]
|
||||
[quo.react :as react]
|
||||
[quo.platform :as platform]
|
||||
[cljs-bean.core :as bean]
|
||||
[quo.components.safe-area :as safe-area]
|
||||
[quo.components.bottom-sheet.style :as styles]
|
||||
[quo.components.safe-area :as safe-area]
|
||||
[quo.design-system.colors :as colors]
|
||||
[quo.gesture-handler :as gesture-handler]
|
||||
[quo.design-system.colors :as colors]))
|
||||
[quo.platform :as platform]
|
||||
[quo.react :as react]
|
||||
[quo.react-native :as rn]
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
(def opacity-coeff 0.8)
|
||||
(def close-duration 150)
|
||||
(def spring-config {:damping 15
|
||||
:mass 0.7
|
||||
:stiffness 150
|
||||
:overshootClamping false
|
||||
:restSpeedThreshold 0.1
|
||||
:restDisplacementThreshold 0.1})
|
||||
(def spring-config
|
||||
{:damping 15
|
||||
:mass 0.7
|
||||
:stiffness 150
|
||||
:overshootClamping false
|
||||
:restSpeedThreshold 0.1
|
||||
:restDisplacementThreshold 0.1})
|
||||
|
||||
(defn bottom-sheet-hooks [props]
|
||||
(defn bottom-sheet-hooks
|
||||
[props]
|
||||
(let [{on-cancel :onCancel
|
||||
disable-drag? :disableDrag?
|
||||
show-handle? :showHandle?
|
||||
@ -31,77 +33,83 @@
|
||||
backdrop-dismiss? true
|
||||
back-button-cancel true}}
|
||||
(bean/bean props)
|
||||
body-ref (react/create-ref)
|
||||
body-ref (react/create-ref)
|
||||
master-ref (react/create-ref)
|
||||
|
||||
height (react/state 0)
|
||||
{window-height :height} (rn/use-window-dimensions)
|
||||
height (react/state 0)
|
||||
{window-height :height} (rn/use-window-dimensions)
|
||||
{:keys [keyboard-shown
|
||||
keyboard-height]} (rn/use-keyboard)
|
||||
keyboard-height-android-delta (if (and platform/android? keyboard-shown) (+ keyboard-height 20) 0)
|
||||
safe-area (safe-area/use-safe-area)
|
||||
window-height (- window-height (if platform/android?
|
||||
(+ 50 keyboard-height-android-delta) ;; TODO : remove 50 when react-native-navigation v8 will be implemented https://github.com/wix/react-native-navigation/issues/7225
|
||||
0))
|
||||
min-height (+ (* styles/vertical-padding 2) (:bottom safe-area))
|
||||
max-height (- window-height (:top safe-area))
|
||||
visible (react/state false)
|
||||
keyboard-height]}
|
||||
(rn/use-keyboard)
|
||||
keyboard-height-android-delta
|
||||
(if (and platform/android? keyboard-shown) (+ keyboard-height 20) 0)
|
||||
safe-area (safe-area/use-safe-area)
|
||||
window-height (- window-height
|
||||
(if platform/android?
|
||||
(+ 50 keyboard-height-android-delta) ;; TODO : remove 50 when
|
||||
;; react-native-navigation v8 will be
|
||||
;; implemented
|
||||
;; https://github.com/wix/react-native-navigation/issues/7225
|
||||
0))
|
||||
min-height (+ (* styles/vertical-padding 2) (:bottom safe-area))
|
||||
max-height (- window-height (:top safe-area))
|
||||
visible (react/state false)
|
||||
|
||||
master-translation-y (animated/use-value 0)
|
||||
master-velocity-y (animated/use-value (:undetermined gesture-handler/states))
|
||||
master-state (animated/use-value (:undetermined gesture-handler/states))
|
||||
tap-state (animated/use-value 0)
|
||||
manual-open (animated/use-value 0)
|
||||
manual-close (animated/use-value 0)
|
||||
offset (animated/use-value 0)
|
||||
drag-over (animated/use-value 1)
|
||||
clock (animated/use-clock)
|
||||
tap-gesture-handler (animated/use-gesture {:state tap-state})
|
||||
on-master-event (animated/use-gesture
|
||||
{:translationY master-translation-y
|
||||
:state master-state
|
||||
:velocityY master-velocity-y})
|
||||
on-body-event on-master-event
|
||||
sheet-height (min max-height
|
||||
(+ styles/border-radius @height))
|
||||
master-velocity-y (animated/use-value (:undetermined gesture-handler/states))
|
||||
master-state (animated/use-value (:undetermined gesture-handler/states))
|
||||
tap-state (animated/use-value 0)
|
||||
manual-open (animated/use-value 0)
|
||||
manual-close (animated/use-value 0)
|
||||
offset (animated/use-value 0)
|
||||
drag-over (animated/use-value 1)
|
||||
clock (animated/use-clock)
|
||||
tap-gesture-handler (animated/use-gesture {:state tap-state})
|
||||
on-master-event (animated/use-gesture
|
||||
{:translationY master-translation-y
|
||||
:state master-state
|
||||
:velocityY master-velocity-y})
|
||||
on-body-event on-master-event
|
||||
sheet-height (min max-height
|
||||
(+ styles/border-radius @height))
|
||||
|
||||
open-snap-point (animated/use-value 0)
|
||||
open-snap-point (animated/use-value 0)
|
||||
close-snap-point 0
|
||||
on-close (fn []
|
||||
(when @visible
|
||||
(reset! visible false)
|
||||
(reset! height 0)
|
||||
(when on-cancel
|
||||
(on-cancel))))
|
||||
close-sheet (fn []
|
||||
(animated/set-value manual-close 1))
|
||||
on-snap (fn [pos]
|
||||
(when (= close-snap-point (aget pos 0))
|
||||
(on-close)))
|
||||
interrupted (animated/and* (animated/eq master-state (:began gesture-handler/states))
|
||||
(animated/clock-running clock))
|
||||
translate-y (react/use-memo
|
||||
(fn []
|
||||
(animated/with-easing
|
||||
{:value (animated/cond* (animated/less-or-eq master-translation-y 0)
|
||||
(animated/divide master-translation-y 2)
|
||||
master-translation-y)
|
||||
:velocity master-velocity-y
|
||||
:offset offset
|
||||
:state master-state
|
||||
:animation-over drag-over
|
||||
:snap-points [open-snap-point close-snap-point]}))
|
||||
[])
|
||||
opacity (react/use-memo
|
||||
(fn []
|
||||
(animated/cond*
|
||||
open-snap-point
|
||||
(animated/interpolate
|
||||
translate-y
|
||||
{:inputRange [(animated/multiply open-snap-point opacity-coeff) 0]
|
||||
:outputRange [1 0]
|
||||
:extrapolate (:clamp animated/extrapolate)})))
|
||||
[])]
|
||||
on-close (fn []
|
||||
(when @visible
|
||||
(reset! visible false)
|
||||
(reset! height 0)
|
||||
(when on-cancel
|
||||
(on-cancel))))
|
||||
close-sheet (fn []
|
||||
(animated/set-value manual-close 1))
|
||||
on-snap (fn [pos]
|
||||
(when (= close-snap-point (aget pos 0))
|
||||
(on-close)))
|
||||
interrupted (animated/and* (animated/eq master-state (:began gesture-handler/states))
|
||||
(animated/clock-running clock))
|
||||
translate-y (react/use-memo
|
||||
(fn []
|
||||
(animated/with-easing
|
||||
{:value (animated/cond* (animated/less-or-eq master-translation-y 0)
|
||||
(animated/divide master-translation-y 2)
|
||||
master-translation-y)
|
||||
:velocity master-velocity-y
|
||||
:offset offset
|
||||
:state master-state
|
||||
:animation-over drag-over
|
||||
:snap-points [open-snap-point close-snap-point]}))
|
||||
[])
|
||||
opacity (react/use-memo
|
||||
(fn []
|
||||
(animated/cond*
|
||||
open-snap-point
|
||||
(animated/interpolate
|
||||
translate-y
|
||||
{:inputRange [(animated/multiply open-snap-point opacity-coeff) 0]
|
||||
:outputRange [1 0]
|
||||
:extrapolate (:clamp animated/extrapolate)})))
|
||||
[])]
|
||||
(animated/code!
|
||||
(fn []
|
||||
(animated/cond* (animated/and* (animated/eq master-state (:end gesture-handler/states))
|
||||
@ -177,39 +185,48 @@
|
||||
(close-sheet)))
|
||||
[visible?])
|
||||
(reagent/as-element
|
||||
[rn/view {:style styles/container
|
||||
:pointer-events :box-none}
|
||||
[gesture-handler/tap-gesture-handler (merge {:enabled backdrop-dismiss?}
|
||||
tap-gesture-handler)
|
||||
[animated/view {:style (merge (styles/backdrop)
|
||||
(when platform/ios?
|
||||
{:opacity opacity
|
||||
:background-color (:backdrop @colors/theme)}))}]]
|
||||
[animated/view {:style (merge (styles/content-container window-height)
|
||||
{:transform [{:translateY (if (= sheet-height max-height)
|
||||
(animated/add translate-y keyboard-height-android-delta)
|
||||
translate-y)}
|
||||
{:translateY (* window-height 2)}]})}
|
||||
[gesture-handler/pan-gesture-handler (merge on-master-event
|
||||
{:ref master-ref
|
||||
:wait-for body-ref
|
||||
:enabled (not disable-drag?)})
|
||||
[animated/view {:style styles/content-header}
|
||||
[rn/view
|
||||
{:style styles/container
|
||||
:pointer-events :box-none}
|
||||
[gesture-handler/tap-gesture-handler
|
||||
(merge {:enabled backdrop-dismiss?}
|
||||
tap-gesture-handler)
|
||||
[animated/view
|
||||
{:style (merge (styles/backdrop)
|
||||
(when platform/ios?
|
||||
{:opacity opacity
|
||||
:background-color (:backdrop @colors/theme)}))}]]
|
||||
[animated/view
|
||||
{:style (merge (styles/content-container window-height)
|
||||
{:transform [{:translateY (if (= sheet-height max-height)
|
||||
(animated/add translate-y
|
||||
keyboard-height-android-delta)
|
||||
translate-y)}
|
||||
{:translateY (* window-height 2)}]})}
|
||||
[gesture-handler/pan-gesture-handler
|
||||
(merge on-master-event
|
||||
{:ref master-ref
|
||||
:wait-for body-ref
|
||||
:enabled (not disable-drag?)})
|
||||
[animated/view {:style styles/content-header}
|
||||
(when show-handle?
|
||||
[rn/view {:style styles/handle}])]]
|
||||
[gesture-handler/pan-gesture-handler (merge on-body-event
|
||||
{:ref body-ref
|
||||
:wait-for master-ref
|
||||
:enabled (and (not disable-drag?)
|
||||
(not= sheet-height max-height))})
|
||||
[animated/view {:height sheet-height
|
||||
:flex 1}
|
||||
[animated/view {:style {:padding-top styles/vertical-padding
|
||||
:padding-bottom (+ styles/vertical-padding
|
||||
(if (and platform/ios? keyboard-shown)
|
||||
keyboard-height
|
||||
(:bottom safe-area)))}
|
||||
:on-layout #(reset! height (.-nativeEvent.layout.height ^js %))}
|
||||
[gesture-handler/pan-gesture-handler
|
||||
(merge on-body-event
|
||||
{:ref body-ref
|
||||
:wait-for master-ref
|
||||
:enabled (and (not disable-drag?)
|
||||
(not= sheet-height max-height))})
|
||||
[animated/view
|
||||
{:height sheet-height
|
||||
:flex 1}
|
||||
[animated/view
|
||||
{:style {:padding-top styles/vertical-padding
|
||||
:padding-bottom (+ styles/vertical-padding
|
||||
(if (and platform/ios? keyboard-shown)
|
||||
keyboard-height
|
||||
(:bottom safe-area)))}
|
||||
:on-layout #(reset! height (.-nativeEvent.layout.height ^js %))}
|
||||
(into [:<>]
|
||||
(react/get-children children))]]]]])))
|
||||
|
||||
|
@ -1,14 +1,14 @@
|
||||
(ns quo.components.button.view
|
||||
(:require [quo.components.animated.pressable :as animation]
|
||||
[quo.react-native :as rn]
|
||||
[quo.haptic :as haptic]
|
||||
[quo.components.text :as text] ;; FIXME:
|
||||
[quo.design-system.colors :as colors]
|
||||
[quo.design-system.spacing :as spacing]
|
||||
[quo.components.text :as text]
|
||||
;; FIXME:
|
||||
[quo.haptic :as haptic]
|
||||
[quo.react-native :as rn]
|
||||
[status-im.ui.components.icons.icons :as icons]))
|
||||
|
||||
(defn style-container [type]
|
||||
(defn style-container
|
||||
[type]
|
||||
(merge {:height 44
|
||||
:align-items :center
|
||||
:justify-content :center
|
||||
@ -19,14 +19,16 @@
|
||||
:icon {}
|
||||
nil)))
|
||||
|
||||
(defn content-style [type]
|
||||
(defn content-style
|
||||
[type]
|
||||
(case type
|
||||
:primary (:base spacing/padding-horizontal)
|
||||
:secondary (:x-tiny spacing/padding-horizontal)
|
||||
:icon (:tiny spacing/padding-horizontal)
|
||||
nil))
|
||||
|
||||
(defn themes [theme]
|
||||
(defn themes
|
||||
[theme]
|
||||
(case theme
|
||||
:main {:icon-color (:icon-04 @colors/theme)
|
||||
:background-color (:interactive-02 @colors/theme)
|
||||
@ -54,44 +56,46 @@
|
||||
:text-color (:text-01 @colors/theme)
|
||||
:border-color (:ui-01 @colors/theme)}))
|
||||
|
||||
(defn button [{:keys [on-press disabled type theme before after
|
||||
haptic-feedback haptic-type on-long-press on-press-start
|
||||
accessibility-label loading border-radius style test-ID]
|
||||
:or {theme :main
|
||||
type :primary
|
||||
haptic-feedback true
|
||||
border-radius 8
|
||||
haptic-type :selection}}
|
||||
children]
|
||||
(let [theme' (cond
|
||||
disabled :disabled
|
||||
:else theme)
|
||||
(defn button
|
||||
[{:keys [on-press disabled type theme before after
|
||||
haptic-feedback haptic-type on-long-press on-press-start
|
||||
accessibility-label loading border-radius style test-ID]
|
||||
:or {theme :main
|
||||
type :primary
|
||||
haptic-feedback true
|
||||
border-radius 8
|
||||
haptic-type :selection}}
|
||||
children]
|
||||
(let [theme' (cond
|
||||
disabled :disabled
|
||||
:else theme)
|
||||
{:keys [icon-color background-color text-color border-color]}
|
||||
(themes theme')
|
||||
|
||||
optional-haptic (fn []
|
||||
(when haptic-feedback
|
||||
(haptic/trigger haptic-type)))]
|
||||
[animation/pressable (merge {:bg-color background-color
|
||||
:border-radius border-radius
|
||||
:type type
|
||||
:disabled disabled
|
||||
:accessibility-label accessibility-label}
|
||||
(when border-color
|
||||
{:border-color border-color
|
||||
:border-width 1})
|
||||
(when on-press
|
||||
{:on-press (fn []
|
||||
(optional-haptic)
|
||||
(on-press))})
|
||||
(when on-long-press
|
||||
{:on-long-press (fn []
|
||||
(optional-haptic)
|
||||
(on-long-press))})
|
||||
(when on-press-start
|
||||
{:on-press-start (fn []
|
||||
(optional-haptic)
|
||||
(on-press-start))}))
|
||||
optional-haptic (fn []
|
||||
(when haptic-feedback
|
||||
(haptic/trigger haptic-type)))]
|
||||
[animation/pressable
|
||||
(merge {:bg-color background-color
|
||||
:border-radius border-radius
|
||||
:type type
|
||||
:disabled disabled
|
||||
:accessibility-label accessibility-label}
|
||||
(when border-color
|
||||
{:border-color border-color
|
||||
:border-width 1})
|
||||
(when on-press
|
||||
{:on-press (fn []
|
||||
(optional-haptic)
|
||||
(on-press))})
|
||||
(when on-long-press
|
||||
{:on-long-press (fn []
|
||||
(optional-haptic)
|
||||
(on-long-press))})
|
||||
(when on-press-start
|
||||
{:on-press-start (fn []
|
||||
(optional-haptic)
|
||||
(on-press-start))}))
|
||||
[rn/view {:test-ID test-ID :style (merge (style-container type) style)}
|
||||
(when before
|
||||
[rn/view
|
||||
@ -99,17 +103,19 @@
|
||||
(when loading
|
||||
[rn/view {:style {:position :absolute}}
|
||||
[rn/activity-indicator]])
|
||||
[rn/view {:style (merge (content-style type)
|
||||
(when loading
|
||||
{:opacity 0}))}
|
||||
[rn/view
|
||||
{:style (merge (content-style type)
|
||||
(when loading
|
||||
{:opacity 0}))}
|
||||
(cond
|
||||
(= type :icon)
|
||||
[icons/icon children {:color icon-color}]
|
||||
|
||||
(string? children)
|
||||
[text/text {:weight :medium
|
||||
:number-of-lines 1
|
||||
:style {:color text-color}}
|
||||
[text/text
|
||||
{:weight :medium
|
||||
:number-of-lines 1
|
||||
:style {:color text-color}}
|
||||
children]
|
||||
|
||||
(vector? children)
|
||||
|
@ -2,7 +2,8 @@
|
||||
(:require [quo.animated :as animated]
|
||||
[quo.design-system.colors :as colors]))
|
||||
|
||||
(defn switch-style [state disabled]
|
||||
(defn switch-style
|
||||
[state disabled]
|
||||
{:width 52
|
||||
:height 28
|
||||
:border-radius 14
|
||||
@ -13,7 +14,8 @@
|
||||
(:interactive-04 @colors/theme)
|
||||
(:interactive-01 @colors/theme)))})
|
||||
|
||||
(defn switch-bullet-style [state hold]
|
||||
(defn switch-bullet-style
|
||||
[state hold]
|
||||
{:width 20
|
||||
:height 20
|
||||
:border-radius 10
|
||||
@ -26,7 +28,8 @@
|
||||
:shadow-color (:shadow-01 @colors/theme)
|
||||
:shadow-offset {:width 0 :height 4}})
|
||||
|
||||
(defn radio-style [state disabled]
|
||||
(defn radio-style
|
||||
[state disabled]
|
||||
{:width 20
|
||||
:height 20
|
||||
:border-radius 10
|
||||
@ -37,7 +40,8 @@
|
||||
(:interactive-04 @colors/theme)
|
||||
(:interactive-01 @colors/theme)))})
|
||||
|
||||
(defn radio-bullet-style [state hold]
|
||||
(defn radio-bullet-style
|
||||
[state hold]
|
||||
{:width 12
|
||||
:height 12
|
||||
:border-radius 6
|
||||
@ -50,7 +54,8 @@
|
||||
:shadow-color (:shadow-01 @colors/theme)
|
||||
:shadow-offset {:width 0 :height 4}})
|
||||
|
||||
(defn animated-checkbox-style [state disabled]
|
||||
(defn animated-checkbox-style
|
||||
[state disabled]
|
||||
{:width 18
|
||||
:height 18
|
||||
:border-radius 4
|
||||
@ -62,7 +67,8 @@
|
||||
(:interactive-04 @colors/theme)
|
||||
(:interactive-01 @colors/theme)))})
|
||||
|
||||
(defn checkbox-style [value disabled]
|
||||
(defn checkbox-style
|
||||
[value disabled]
|
||||
{:width 18
|
||||
:height 18
|
||||
:border-radius 4
|
||||
@ -74,9 +80,11 @@
|
||||
(:interactive-01 @colors/theme))
|
||||
(:ui-01 @colors/theme))})
|
||||
|
||||
(defn animated-check-icon-style [state hold]
|
||||
{:opacity (animated/mix hold 1 0.6)
|
||||
:transform [{:scale (animated/mix state 0.0001 1)}]})
|
||||
(defn animated-check-icon-style
|
||||
[state hold]
|
||||
{:opacity (animated/mix hold 1 0.6)
|
||||
:transform [{:scale (animated/mix state 0.0001 1)}]})
|
||||
|
||||
(defn check-icon-style [value]
|
||||
(defn check-icon-style
|
||||
[value]
|
||||
{:opacity (if value 1 0)})
|
||||
|
@ -1,34 +1,37 @@
|
||||
(ns quo.components.controls.view
|
||||
(:require [reagent.core :as reagent]
|
||||
[cljs-bean.core :as bean]
|
||||
(:require [cljs-bean.core :as bean]
|
||||
[quo.animated :as animated]
|
||||
[quo.components.controls.styles :as styles]
|
||||
[quo.design-system.colors :as colors]
|
||||
[quo.gesture-handler :as gh]
|
||||
[quo.react :as react]
|
||||
[quo.react-native :as rn]
|
||||
[quo.animated :as animated]
|
||||
[quo.gesture-handler :as gh]
|
||||
[quo.design-system.colors :as colors]
|
||||
[quo.components.controls.styles :as styles]
|
||||
[reagent.core :as reagent]
|
||||
[status-im.ui.components.icons.icons :as icons]))
|
||||
|
||||
(defn control-builder [component]
|
||||
(defn control-builder
|
||||
[component]
|
||||
(fn [props]
|
||||
(let [{:keys [value onChange disabled]}
|
||||
(bean/bean props)
|
||||
state (animated/use-value 0)
|
||||
tap-state (animated/use-value (:undetermined gh/states))
|
||||
tap-handler (animated/on-gesture {:state tap-state})
|
||||
hold (react/use-memo
|
||||
(fn []
|
||||
(animated/with-timing-transition
|
||||
(animated/eq tap-state (:began gh/states))
|
||||
{}))
|
||||
[])
|
||||
transition (react/use-memo
|
||||
(fn []
|
||||
(animated/with-spring-transition state (:lazy animated/springs)))
|
||||
[])
|
||||
press-end (fn []
|
||||
(when (and (not disabled) onChange)
|
||||
(onChange (not value))))]
|
||||
state (animated/use-value 0)
|
||||
tap-state (animated/use-value (:undetermined gh/states))
|
||||
tap-handler (animated/on-gesture {:state tap-state})
|
||||
hold (react/use-memo
|
||||
(fn []
|
||||
(animated/with-timing-transition
|
||||
(animated/eq tap-state (:began gh/states))
|
||||
{}))
|
||||
[])
|
||||
transition (react/use-memo
|
||||
(fn []
|
||||
(animated/with-spring-transition state
|
||||
(:lazy
|
||||
animated/springs)))
|
||||
[])
|
||||
press-end (fn []
|
||||
(when (and (not disabled) onChange)
|
||||
(onChange (not value))))]
|
||||
(animated/code!
|
||||
(fn []
|
||||
(animated/cond* (animated/eq tap-state (:end gh/states))
|
||||
@ -41,38 +44,47 @@
|
||||
(animated/set state (if (true? value) 1 0)))
|
||||
[value])
|
||||
(reagent/as-element
|
||||
[gh/tap-gesture-handler (merge tap-handler
|
||||
{:shouldCancelWhenOutside true
|
||||
:enabled (boolean (and onChange (not disabled)))})
|
||||
[gh/tap-gesture-handler
|
||||
(merge tap-handler
|
||||
{:shouldCancelWhenOutside true
|
||||
:enabled (boolean (and onChange (not disabled)))})
|
||||
[animated/view
|
||||
[component {:transition transition
|
||||
:hold hold
|
||||
:disabled disabled}]]]))))
|
||||
[component
|
||||
{:transition transition
|
||||
:hold hold
|
||||
:disabled disabled}]]]))))
|
||||
|
||||
(defn switch-view [{:keys [transition hold disabled value]}]
|
||||
[animated/view {:style (styles/switch-style transition disabled)
|
||||
:accessibility-label (str "switch-" (if value "on" "off"))
|
||||
:accessibility-role :switch}
|
||||
(defn switch-view
|
||||
[{:keys [transition hold disabled value]}]
|
||||
[animated/view
|
||||
{:style (styles/switch-style transition disabled)
|
||||
:accessibility-label (str "switch-" (if value "on" "off"))
|
||||
:accessibility-role :switch}
|
||||
[animated/view {:style (styles/switch-bullet-style transition hold)}]])
|
||||
|
||||
(defn radio-view [{:keys [transition hold disabled value]}]
|
||||
[animated/view {:style (styles/radio-style transition disabled)
|
||||
:accessibility-label (str "radio-" (if value "on" "off"))
|
||||
:accessibility-role :radio}
|
||||
(defn radio-view
|
||||
[{:keys [transition hold disabled value]}]
|
||||
[animated/view
|
||||
{:style (styles/radio-style transition disabled)
|
||||
:accessibility-label (str "radio-" (if value "on" "off"))
|
||||
:accessibility-role :radio}
|
||||
[animated/view {:style (styles/radio-bullet-style transition hold)}]])
|
||||
|
||||
(defn checkbox-view [props]
|
||||
(defn checkbox-view
|
||||
[props]
|
||||
(let [{:keys [value onChange disabled]} (bean/bean props)]
|
||||
(reagent/as-element
|
||||
[rn/touchable-without-feedback
|
||||
{:on-press (when (and onChange (not disabled)) onChange)}
|
||||
[rn/view {:style (styles/checkbox-style value disabled)
|
||||
:accessibility-label (str "checkbox-" (if value "on" "off"))
|
||||
:accessibility-role :checkbox}
|
||||
[rn/view
|
||||
{:style (styles/checkbox-style value disabled)
|
||||
:accessibility-label (str "checkbox-" (if value "on" "off"))
|
||||
:accessibility-role :checkbox}
|
||||
[rn/view {:style (styles/check-icon-style value)}
|
||||
[icons/tiny-icon :tiny-icons/tiny-check {:color colors/white}]]]])))
|
||||
|
||||
(defn animated-checkbox-view [{:keys [transition hold disabled value]}]
|
||||
(defn animated-checkbox-view
|
||||
[{:keys [transition hold disabled value]}]
|
||||
[animated/view
|
||||
{:style (styles/animated-checkbox-style transition disabled)
|
||||
:accessibility-label (str "checkbox-" (if value "on" "off"))
|
||||
|
@ -10,7 +10,8 @@
|
||||
|
||||
(def header-height 56)
|
||||
|
||||
(defn header-wrapper-style [{:keys [height border-bottom background]}]
|
||||
(defn header-wrapper-style
|
||||
[{:keys [height border-bottom background]}]
|
||||
(merge
|
||||
(:x-tiny spacing/padding-horizontal)
|
||||
{:background-color (:ui-background @colors/theme)
|
||||
@ -21,32 +22,37 @@
|
||||
{:border-bottom-width 1
|
||||
:border-bottom-color (:ui-01 @colors/theme)})))
|
||||
|
||||
(def absolute-fill {:position :absolute
|
||||
:top 0
|
||||
:bottom 0
|
||||
:left 0
|
||||
:right 0})
|
||||
(def absolute-fill
|
||||
{:position :absolute
|
||||
:top 0
|
||||
:bottom 0
|
||||
:left 0
|
||||
:right 0})
|
||||
|
||||
(def content {:flex 1
|
||||
:flex-direction :row
|
||||
:align-items :center
|
||||
:justify-content :center})
|
||||
(def content
|
||||
{:flex 1
|
||||
:flex-direction :row
|
||||
:align-items :center
|
||||
:justify-content :center})
|
||||
|
||||
(def left {:position :absolute
|
||||
:left 0
|
||||
:top 0
|
||||
:bottom 0
|
||||
:justify-content :center
|
||||
:align-items :flex-start})
|
||||
(def left
|
||||
{:position :absolute
|
||||
:left 0
|
||||
:top 0
|
||||
:bottom 0
|
||||
:justify-content :center
|
||||
:align-items :flex-start})
|
||||
|
||||
(def right {:position :absolute
|
||||
:right 0
|
||||
:top 0
|
||||
:bottom 0
|
||||
:justify-content :center
|
||||
:align-items :flex-end})
|
||||
(def right
|
||||
{:position :absolute
|
||||
:right 0
|
||||
:top 0
|
||||
:bottom 0
|
||||
:justify-content :center
|
||||
:align-items :flex-end})
|
||||
|
||||
(defn title-style [{:keys [left right]} title-align]
|
||||
(defn title-style
|
||||
[{:keys [left right]} title-align]
|
||||
(merge
|
||||
absolute-fill
|
||||
(case title-align
|
||||
@ -59,66 +65,75 @@
|
||||
|
||||
(def header-actions-style
|
||||
(merge
|
||||
{:flex 1
|
||||
:flex-direction :row
|
||||
:align-items :center
|
||||
:justify-content :center}
|
||||
{:flex 1
|
||||
:flex-direction :row
|
||||
:align-items :center
|
||||
:justify-content :center}
|
||||
(:x-tiny spacing/padding-horizontal)))
|
||||
|
||||
(def header-action-placeholder
|
||||
{:width (:base spacing/spacing)})
|
||||
|
||||
(def element {:align-items :center
|
||||
:justify-content :center
|
||||
:flex 1})
|
||||
(def element
|
||||
{:align-items :center
|
||||
:justify-content :center
|
||||
:flex 1})
|
||||
|
||||
(defn header-action [{:keys [icon label on-press disabled accessibility-label]}]
|
||||
[button/button (merge {:on-press on-press
|
||||
:disabled disabled}
|
||||
(cond
|
||||
icon {:type :icon
|
||||
:theme :icon}
|
||||
label {:type :secondary})
|
||||
(when accessibility-label
|
||||
{:accessibility-label accessibility-label}))
|
||||
(defn header-action
|
||||
[{:keys [icon label on-press disabled accessibility-label]}]
|
||||
[button/button
|
||||
(merge {:on-press on-press
|
||||
:disabled disabled}
|
||||
(cond
|
||||
icon {:type :icon
|
||||
:theme :icon}
|
||||
label {:type :secondary})
|
||||
(when accessibility-label
|
||||
{:accessibility-label accessibility-label}))
|
||||
(cond
|
||||
icon icon
|
||||
label label)])
|
||||
|
||||
(defn header-actions [{:keys [accessories component]}]
|
||||
(defn header-actions
|
||||
[{:keys [accessories component]}]
|
||||
[rn/view {:style element}
|
||||
(cond
|
||||
(seq accessories)
|
||||
(into [rn/view {:style header-actions-style}]
|
||||
(map header-action accessories))
|
||||
|
||||
component component
|
||||
component component
|
||||
|
||||
:else
|
||||
[rn/view {:style header-action-placeholder}])])
|
||||
|
||||
(defn header-title [{:keys [title subtitle component title-align]}]
|
||||
(defn header-title
|
||||
[{:keys [title subtitle component title-align]}]
|
||||
[:<>
|
||||
(cond
|
||||
component component
|
||||
component component
|
||||
|
||||
(and title subtitle)
|
||||
[:<>
|
||||
[text/text {:weight :medium
|
||||
:number-of-lines 1}
|
||||
[text/text
|
||||
{:weight :medium
|
||||
:number-of-lines 1}
|
||||
title]
|
||||
[text/text {:weight :regular
|
||||
:color :secondary
|
||||
:number-of-lines 1}
|
||||
[text/text
|
||||
{:weight :regular
|
||||
:color :secondary
|
||||
:number-of-lines 1}
|
||||
subtitle]]
|
||||
|
||||
title [text/text {:weight :bold
|
||||
:number-of-lines 0
|
||||
:align title-align
|
||||
:size :large}
|
||||
title])])
|
||||
title [text/text
|
||||
{:weight :bold
|
||||
:number-of-lines 0
|
||||
:align title-align
|
||||
:size :large}
|
||||
title])])
|
||||
|
||||
(defn header [{:keys [left-width right-width]}]
|
||||
(defn header
|
||||
[{:keys [left-width right-width]}]
|
||||
(let [layout (reagent/atom {:left {:width (or left-width 8)
|
||||
:height header-height}
|
||||
:right {:width (or right-width 8)
|
||||
@ -130,46 +145,61 @@
|
||||
(let [width (oget evt "nativeEvent" "layout" "width")
|
||||
height (oget evt "nativeEvent" "layout" "height")]
|
||||
(when get-layout
|
||||
(get-layout el {:width width
|
||||
:height height}))
|
||||
(swap! layout assoc el {:width width
|
||||
:height height}))))]
|
||||
(fn [{:keys [left-accessories left-component border-bottom
|
||||
right-accessories right-component insets get-layout
|
||||
title subtitle title-component style title-align
|
||||
background]
|
||||
:or {title-align :center
|
||||
border-bottom true}}]
|
||||
(get-layout el
|
||||
{:width width
|
||||
:height height}))
|
||||
(swap! layout assoc
|
||||
el
|
||||
{:width width
|
||||
:height height}))))]
|
||||
(fn
|
||||
[{:keys [left-accessories left-component border-bottom
|
||||
right-accessories right-component insets get-layout
|
||||
title subtitle title-component style title-align
|
||||
background]
|
||||
:or {title-align :center
|
||||
border-bottom true}}]
|
||||
(let [status-bar-height (get insets :top 0)
|
||||
height (+ header-height status-bar-height)]
|
||||
[animated/view {:style (header-wrapper-style {:height height
|
||||
:background background
|
||||
:border-bottom border-bottom})}
|
||||
[rn/view {:pointer-events :box-none
|
||||
:height status-bar-height}]
|
||||
[rn/view {:style (merge {:height header-height}
|
||||
style)
|
||||
:pointer-events :box-none}
|
||||
[rn/view {:style absolute-fill
|
||||
:pointer-events :box-none}
|
||||
[rn/view {:style content
|
||||
:pointer-events :box-none}
|
||||
[rn/view {:style left
|
||||
:on-layout (handle-layout :left get-layout)
|
||||
:pointer-events :box-none}
|
||||
[header-actions {:accessories left-accessories
|
||||
:component left-component}]]
|
||||
[animated/view
|
||||
{:style (header-wrapper-style {:height height
|
||||
:background background
|
||||
:border-bottom border-bottom})}
|
||||
[rn/view
|
||||
{:pointer-events :box-none
|
||||
:height status-bar-height}]
|
||||
[rn/view
|
||||
{:style (merge {:height header-height}
|
||||
style)
|
||||
:pointer-events :box-none}
|
||||
[rn/view
|
||||
{:style absolute-fill
|
||||
:pointer-events :box-none}
|
||||
[rn/view
|
||||
{:style content
|
||||
:pointer-events :box-none}
|
||||
[rn/view
|
||||
{:style left
|
||||
:on-layout (handle-layout :left get-layout)
|
||||
:pointer-events :box-none}
|
||||
[header-actions
|
||||
{:accessories left-accessories
|
||||
:component left-component}]]
|
||||
|
||||
[rn/view {:style (title-style @layout title-align)
|
||||
:on-layout (handle-layout :title get-layout)
|
||||
:pointer-events :box-none}
|
||||
[header-title {:title title
|
||||
:subtitle subtitle
|
||||
:title-align title-align
|
||||
:component title-component}]]
|
||||
[rn/view
|
||||
{:style (title-style @layout title-align)
|
||||
:on-layout (handle-layout :title get-layout)
|
||||
:pointer-events :box-none}
|
||||
[header-title
|
||||
{:title title
|
||||
:subtitle subtitle
|
||||
:title-align title-align
|
||||
:component title-component}]]
|
||||
|
||||
[rn/view {:style right
|
||||
:on-layout (handle-layout :right get-layout)
|
||||
:pointer-events :box-none}
|
||||
[header-actions {:accessories right-accessories
|
||||
:component right-component}]]]]]]))))
|
||||
[rn/view
|
||||
{:style right
|
||||
:on-layout (handle-layout :right get-layout)
|
||||
:pointer-events :box-none}
|
||||
[header-actions
|
||||
{:accessories right-accessories
|
||||
:component right-component}]]]]]]))))
|
||||
|
@ -1,14 +1,17 @@
|
||||
(ns quo.components.list.footer
|
||||
(:require [quo.react-native :as rn]
|
||||
(:require [quo.components.text :as text]
|
||||
[quo.design-system.spacing :as spacing]
|
||||
[quo.components.text :as text]
|
||||
[quo.react-native :as rn]
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
(defn footer []
|
||||
(let [this (reagent/current-component)
|
||||
(defn footer
|
||||
[]
|
||||
(let [this (reagent/current-component)
|
||||
{:keys [color]
|
||||
:or {color :secondary}} (reagent/props this)]
|
||||
[rn/view {:style (merge (:base spacing/padding-horizontal)
|
||||
(:small spacing/padding-vertical))}
|
||||
:or {color :secondary}}
|
||||
(reagent/props this)]
|
||||
[rn/view
|
||||
{:style (merge (:base spacing/padding-horizontal)
|
||||
(:small spacing/padding-vertical))}
|
||||
(into [text/text {:color color}]
|
||||
(reagent/children this))]))
|
||||
|
@ -1,15 +1,19 @@
|
||||
(ns quo.components.list.header
|
||||
(:require [reagent.core :as reagent]
|
||||
[quo.react-native :as rn]
|
||||
(:require [quo.components.text :as text]
|
||||
[quo.design-system.spacing :as spacing]
|
||||
[quo.components.text :as text]))
|
||||
[quo.react-native :as rn]
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
(defn header []
|
||||
(let [this (reagent/current-component)
|
||||
(defn header
|
||||
[]
|
||||
(let [this (reagent/current-component)
|
||||
{:keys [color]
|
||||
:or {color :secondary}} (reagent/props this)]
|
||||
[rn/view {:style (merge (:base spacing/padding-horizontal)
|
||||
(:x-tiny spacing/padding-vertical))}
|
||||
(into [text/text {:color color
|
||||
:style {:margin-top 10}}]
|
||||
:or {color :secondary}}
|
||||
(reagent/props this)]
|
||||
[rn/view
|
||||
{:style (merge (:base spacing/padding-horizontal)
|
||||
(:x-tiny spacing/padding-vertical))}
|
||||
(into [text/text
|
||||
{:color color
|
||||
:style {:margin-top 10}}]
|
||||
(reagent/children this))]))
|
||||
|
@ -1,16 +1,18 @@
|
||||
(ns quo.components.list.index
|
||||
(:require [quo.react-native :as rn]
|
||||
[quo.components.text :as text]
|
||||
[quo.design-system.colors :as colors]))
|
||||
(:require [quo.components.text :as text]
|
||||
[quo.design-system.colors :as colors]
|
||||
[quo.react-native :as rn]))
|
||||
|
||||
(defn index [{:keys [title]}]
|
||||
(defn index
|
||||
[{:keys [title]}]
|
||||
[rn/view {:style {:padding-right 16}}
|
||||
[rn/view {:style {:border-top-width 1
|
||||
:border-bottom-width 1
|
||||
:border-right-width 1
|
||||
:border-color (colors/get-color :border-01)
|
||||
:padding-vertical 3
|
||||
:padding-horizontal 16
|
||||
:border-top-right-radius 16
|
||||
:border-bottom-right-radius 16}}
|
||||
[rn/view
|
||||
{:style {:border-top-width 1
|
||||
:border-bottom-width 1
|
||||
:border-right-width 1
|
||||
:border-color (colors/get-color :border-01)
|
||||
:padding-vertical 3
|
||||
:padding-horizontal 16
|
||||
:border-top-right-radius 16
|
||||
:border-bottom-right-radius 16}}
|
||||
[text/text title]]])
|
||||
|
@ -1,28 +1,29 @@
|
||||
(ns quo.components.list.item
|
||||
(:require [quo.react-native :as rn]
|
||||
[quo.platform :as platform]
|
||||
[quo.haptic :as haptic]
|
||||
[quo.gesture-handler :as gh]
|
||||
[quo.design-system.spacing :as spacing]
|
||||
[quo.design-system.colors :as colors]
|
||||
[quo.components.text :as text]
|
||||
(:require [quo.components.animated.pressable :as animated]
|
||||
[quo.components.controls.view :as controls]
|
||||
[quo.components.text :as text]
|
||||
[quo.components.tooltip :as tooltip]
|
||||
[status-im.ui.components.icons.icons :as icons]
|
||||
[quo.components.animated.pressable :as animated]))
|
||||
[quo.design-system.colors :as colors]
|
||||
[quo.design-system.spacing :as spacing]
|
||||
[quo.gesture-handler :as gh]
|
||||
[quo.haptic :as haptic]
|
||||
[quo.platform :as platform]
|
||||
[quo.react-native :as rn]
|
||||
[status-im.ui.components.icons.icons :as icons]))
|
||||
|
||||
(defn themes [theme]
|
||||
(defn themes
|
||||
[theme]
|
||||
(case theme
|
||||
:main {:icon-color (:icon-04 @colors/theme)
|
||||
:icon-bg-color (:interactive-02 @colors/theme)
|
||||
:active-background (:interactive-02 @colors/theme)
|
||||
:passive-background (:ui-background @colors/theme)
|
||||
:text-color (:text-01 @colors/theme)}
|
||||
:accent {:icon-color (:icon-04 @colors/theme)
|
||||
:icon-bg-color (:interactive-02 @colors/theme)
|
||||
:active-background (:interactive-02 @colors/theme)
|
||||
:passive-background (:ui-background @colors/theme)
|
||||
:text-color (:text-04 @colors/theme)}
|
||||
:main {:icon-color (:icon-04 @colors/theme)
|
||||
:icon-bg-color (:interactive-02 @colors/theme)
|
||||
:active-background (:interactive-02 @colors/theme)
|
||||
:passive-background (:ui-background @colors/theme)
|
||||
:text-color (:text-01 @colors/theme)}
|
||||
:accent {:icon-color (:icon-04 @colors/theme)
|
||||
:icon-bg-color (:interactive-02 @colors/theme)
|
||||
:active-background (:interactive-02 @colors/theme)
|
||||
:passive-background (:ui-background @colors/theme)
|
||||
:text-color (:text-04 @colors/theme)}
|
||||
:negative {:icon-color (:negative-01 @colors/theme)
|
||||
:icon-bg-color (:negative-02 @colors/theme)
|
||||
:active-background (:negative-02 @colors/theme)
|
||||
@ -39,28 +40,34 @@
|
||||
:passive-background (:ui-background @colors/theme)
|
||||
:text-color (:text-02 @colors/theme)}))
|
||||
|
||||
(defn size->icon-size [size]
|
||||
(defn size->icon-size
|
||||
[size]
|
||||
(case size
|
||||
:small 36
|
||||
40))
|
||||
|
||||
(defn size->container-size [size]
|
||||
(defn size->container-size
|
||||
[size]
|
||||
(case size
|
||||
:small 52
|
||||
64))
|
||||
|
||||
(defn size->single-title-size [size]
|
||||
(defn size->single-title-size
|
||||
[size]
|
||||
(case size
|
||||
:small :base
|
||||
:large))
|
||||
|
||||
(defn container [{:keys [size container-style]} & children]
|
||||
(into [rn/view {:style (merge (:tiny spacing/padding-horizontal)
|
||||
{:min-height (size->container-size size)
|
||||
:padding-vertical 8
|
||||
:flex-direction :row
|
||||
:align-items :center
|
||||
:justify-content :space-between} container-style)}]
|
||||
(defn container
|
||||
[{:keys [size container-style]} & children]
|
||||
(into [rn/view
|
||||
{:style (merge (:tiny spacing/padding-horizontal)
|
||||
{:min-height (size->container-size size)
|
||||
:padding-vertical 8
|
||||
:flex-direction :row
|
||||
:align-items :center
|
||||
:justify-content :space-between}
|
||||
container-style)}]
|
||||
children))
|
||||
|
||||
(defn icon-column
|
||||
@ -72,103 +79,118 @@
|
||||
(vector? icon)
|
||||
icon
|
||||
(keyword? icon)
|
||||
[rn/view {:style {:width icon-size
|
||||
:height icon-size
|
||||
:align-items :center
|
||||
:justify-content :center
|
||||
:border-radius (/ icon-size 2)
|
||||
:background-color icon-bg-color}}
|
||||
[rn/view
|
||||
{:style {:width icon-size
|
||||
:height icon-size
|
||||
:align-items :center
|
||||
:justify-content :center
|
||||
:border-radius (/ icon-size 2)
|
||||
:background-color icon-bg-color}}
|
||||
[icons/icon icon {:color icon-color}]])])))
|
||||
|
||||
(defn title-column
|
||||
[{:keys [title text-color subtitle subtitle-max-lines subtitle-secondary
|
||||
title-accessibility-label size text-size title-text-weight
|
||||
right-side-present?]}]
|
||||
[rn/view {:style (merge (:tiny spacing/padding-horizontal)
|
||||
;; make left-side title grow if nothing is present on right-side
|
||||
(when-not right-side-present?
|
||||
{:flex 1
|
||||
:justify-content :center}))}
|
||||
[rn/view
|
||||
{:style (merge (:tiny spacing/padding-horizontal)
|
||||
;; make left-side title grow if nothing is present on right-side
|
||||
(when-not right-side-present?
|
||||
{:flex 1
|
||||
:justify-content :center}))}
|
||||
(cond
|
||||
|
||||
(and title subtitle)
|
||||
[:<>
|
||||
;; FIXME(Ferossgp): ReactNative 63 will support view inside text on andrid, remove thess if when migrating
|
||||
;; FIXME(Ferossgp): ReactNative 63 will support view inside text on andrid, remove thess if when
|
||||
;; migrating
|
||||
(if (string? title)
|
||||
[text/text {:weight (or title-text-weight :medium)
|
||||
:style {:color text-color}
|
||||
:accessibility-label title-accessibility-label
|
||||
:ellipsize-mode :tail
|
||||
:number-of-lines 1
|
||||
:size text-size}
|
||||
[text/text
|
||||
{:weight (or title-text-weight :medium)
|
||||
:style {:color text-color}
|
||||
:accessibility-label title-accessibility-label
|
||||
:ellipsize-mode :tail
|
||||
:number-of-lines 1
|
||||
:size text-size}
|
||||
title]
|
||||
title)
|
||||
(if (string? subtitle-secondary)
|
||||
[rn/view {:flex-direction :row}
|
||||
[text/text {:style {:max-width "56.5%"}
|
||||
:weight :regular
|
||||
:color :secondary
|
||||
:ellipsize-mode :tail
|
||||
:number-of-lines subtitle-max-lines
|
||||
:size text-size}
|
||||
[text/text
|
||||
{:style {:max-width "56.5%"}
|
||||
:weight :regular
|
||||
:color :secondary
|
||||
:ellipsize-mode :tail
|
||||
:number-of-lines subtitle-max-lines
|
||||
:size text-size}
|
||||
subtitle]
|
||||
[text/text {:style {:width "7%" :text-align :center}
|
||||
:weight :regular
|
||||
:color :secondary
|
||||
:ellipsize-mode :middle
|
||||
:number-of-lines subtitle-max-lines
|
||||
:size text-size}
|
||||
[text/text
|
||||
{:style {:width "7%" :text-align :center}
|
||||
:weight :regular
|
||||
:color :secondary
|
||||
:ellipsize-mode :middle
|
||||
:number-of-lines subtitle-max-lines
|
||||
:size text-size}
|
||||
"•"]
|
||||
[text/text {:style {:max-width "36.5%"}
|
||||
:weight :regular
|
||||
:color :secondary
|
||||
:ellipsize-mode :middle
|
||||
:number-of-lines subtitle-max-lines
|
||||
:size text-size}
|
||||
[text/text
|
||||
{:style {:max-width "36.5%"}
|
||||
:weight :regular
|
||||
:color :secondary
|
||||
:ellipsize-mode :middle
|
||||
:number-of-lines subtitle-max-lines
|
||||
:size text-size}
|
||||
subtitle-secondary]]
|
||||
(if (string? subtitle)
|
||||
[text/text {:weight :regular
|
||||
:color :secondary
|
||||
:ellipsize-mode :tail
|
||||
:number-of-lines subtitle-max-lines
|
||||
:size text-size}
|
||||
[text/text
|
||||
{:weight :regular
|
||||
:color :secondary
|
||||
:ellipsize-mode :tail
|
||||
:number-of-lines subtitle-max-lines
|
||||
:size text-size}
|
||||
subtitle]
|
||||
subtitle))]
|
||||
|
||||
title
|
||||
(if (string? title)
|
||||
[text/text {:weight (or title-text-weight :regular)
|
||||
:number-of-lines 1
|
||||
:style {:color text-color}
|
||||
:title-accessibility-label title-accessibility-label
|
||||
:ellipsize-mode :tail
|
||||
:size (or text-size (size->single-title-size size))}
|
||||
[text/text
|
||||
{:weight (or title-text-weight :regular)
|
||||
:number-of-lines 1
|
||||
:style {:color text-color}
|
||||
:title-accessibility-label title-accessibility-label
|
||||
:ellipsize-mode :tail
|
||||
:size (or text-size (size->single-title-size size))}
|
||||
title]
|
||||
title))])
|
||||
|
||||
(defn left-side [props]
|
||||
[rn/view {:style {:flex-direction :row
|
||||
;; Occupy only content width, never grow, but shrink if need be
|
||||
:flex-grow 0
|
||||
:flex-shrink 1
|
||||
:padding-right 16
|
||||
:align-items (or (:left-side-alignment props) :center)}}
|
||||
(defn left-side
|
||||
[props]
|
||||
[rn/view
|
||||
{:style {:flex-direction :row
|
||||
;; Occupy only content width, never grow, but shrink if need be
|
||||
:flex-grow 0
|
||||
:flex-shrink 1
|
||||
:padding-right 16
|
||||
:align-items (or (:left-side-alignment props) :center)}}
|
||||
[icon-column props]
|
||||
[title-column props]])
|
||||
|
||||
(defn right-side [{:keys [chevron active disabled accessory accessory-text accessory-style animated-accessory?]}]
|
||||
(defn right-side
|
||||
[{:keys [chevron active disabled accessory accessory-text accessory-style animated-accessory?]}]
|
||||
(when (or chevron accessory)
|
||||
[rn/view {:style (merge {:align-items :center
|
||||
:justify-content :flex-end
|
||||
:flex-direction :row
|
||||
;; Grow to occupy full space, shrink when need be, but always maitaining 16px left gutter
|
||||
:flex-grow 1
|
||||
:flex-shrink 0
|
||||
:margin-left 16
|
||||
;; When the left-side leaves no room for right-side, the rendered element is pushed out. A flex-basis ensures that there is some room reserved.
|
||||
;; The number 80px was determined by trial and error.
|
||||
:flex-basis 80}
|
||||
accessory-style)}
|
||||
[rn/view
|
||||
{:style (merge {:align-items :center
|
||||
:justify-content :flex-end
|
||||
:flex-direction :row
|
||||
;; Grow to occupy full space, shrink when need be, but always maitaining 16px left
|
||||
;; gutter
|
||||
:flex-grow 1
|
||||
:flex-shrink 0
|
||||
:margin-left 16
|
||||
;; When the left-side leaves no room for right-side, the rendered element is pushed
|
||||
;; out. A flex-basis ensures that there is some room reserved.
|
||||
;; The number 80px was determined by trial and error.
|
||||
:flex-basis 80}
|
||||
accessory-style)}
|
||||
[rn/view {:style (:tiny spacing/padding-horizontal)}
|
||||
(case accessory
|
||||
:radio [controls/radio {:value active :disabled disabled}]
|
||||
@ -177,25 +199,28 @@
|
||||
controls/checkbox)
|
||||
{:value active :disabled disabled}]
|
||||
:switch [controls/switch {:value active :disabled disabled}]
|
||||
:text [text/text {:color :secondary
|
||||
:ellipsize-mode :middle
|
||||
:number-of-lines 1}
|
||||
:text [text/text
|
||||
{:color :secondary
|
||||
:ellipsize-mode :middle
|
||||
:number-of-lines 1}
|
||||
accessory-text]
|
||||
accessory)]
|
||||
(when (and chevron platform/ios?)
|
||||
[rn/view {:style {:padding-right (:tiny spacing/spacing)}}
|
||||
[icons/icon :main-icons/next {:container-style {:opacity 0.4
|
||||
:align-items :center
|
||||
:justify-content :center}
|
||||
:resize-mode :center
|
||||
:color (:icon-02 @colors/theme)}]])]))
|
||||
[icons/icon :main-icons/next
|
||||
{:container-style {:opacity 0.4
|
||||
:align-items :center
|
||||
:justify-content :center}
|
||||
:resize-mode :center
|
||||
:color (:icon-02 @colors/theme)}]])]))
|
||||
|
||||
(defn list-item
|
||||
[{:keys [theme accessory disabled subtitle-max-lines icon icon-container-style
|
||||
left-side-alignment icon-color icon-bg-color
|
||||
title subtitle subtitle-secondary active on-press on-long-press chevron size text-size
|
||||
accessory-text accessibility-label title-accessibility-label accessory-style
|
||||
haptic-feedback haptic-type error animated animated-accessory? title-text-weight container-style
|
||||
haptic-feedback haptic-type error animated animated-accessory? title-text-weight
|
||||
container-style
|
||||
active-background-enabled background-color]
|
||||
:or {subtitle-max-lines 1
|
||||
theme :main
|
||||
@ -203,26 +228,29 @@
|
||||
animated platform/ios?
|
||||
active-background-enabled true
|
||||
haptic-type :selection}}]
|
||||
(let [theme (if disabled :disabled theme)
|
||||
(let [theme (if disabled :disabled theme)
|
||||
{:keys [text-color active-background passive-background]}
|
||||
(themes theme)
|
||||
icon-color (or icon-color (:icon-color (themes theme)))
|
||||
icon-bg-color (or icon-bg-color (:icon-bg-color (themes theme)))
|
||||
optional-haptic (fn []
|
||||
(when haptic-feedback
|
||||
(haptic/trigger haptic-type)))
|
||||
component (cond
|
||||
(and (not on-press)
|
||||
(not on-long-press))
|
||||
rn/view
|
||||
animated animated/pressable
|
||||
:else gh/touchable-highlight)]
|
||||
[rn/view {:background-color (cond (not= background-color nil)
|
||||
background-color
|
||||
(and (= accessory :radio) active)
|
||||
active-background
|
||||
:else
|
||||
passive-background)}
|
||||
icon-color (or icon-color
|
||||
(:icon-color (themes theme)))
|
||||
icon-bg-color (or icon-bg-color
|
||||
(:icon-bg-color (themes theme)))
|
||||
optional-haptic (fn []
|
||||
(when haptic-feedback
|
||||
(haptic/trigger haptic-type)))
|
||||
component (cond
|
||||
(and (not on-press)
|
||||
(not on-long-press))
|
||||
rn/view
|
||||
animated animated/pressable
|
||||
:else gh/touchable-highlight)]
|
||||
[rn/view
|
||||
{:background-color (cond (not= background-color nil)
|
||||
background-color
|
||||
(and (= accessory :radio) active)
|
||||
active-background
|
||||
:else
|
||||
passive-background)}
|
||||
[component
|
||||
(merge {:type :list-item
|
||||
:disabled disabled
|
||||
@ -237,35 +265,39 @@
|
||||
(optional-haptic)
|
||||
(on-long-press))}))
|
||||
[container {:size size :container-style container-style}
|
||||
[left-side {:icon-color icon-color
|
||||
:text-color (if on-press
|
||||
text-color
|
||||
(:text-color (themes :main)))
|
||||
:left-side-alignment left-side-alignment
|
||||
:icon-bg-color icon-bg-color
|
||||
:title-accessibility-label title-accessibility-label
|
||||
:icon icon
|
||||
:icon-container-style icon-container-style
|
||||
:title title
|
||||
:title-text-weight title-text-weight
|
||||
:size size
|
||||
:text-size text-size
|
||||
:subtitle subtitle
|
||||
:subtitle-max-lines subtitle-max-lines
|
||||
:subtitle-secondary subtitle-secondary
|
||||
:right-side-present? (or accessory chevron)}]
|
||||
[right-side {:chevron chevron
|
||||
:active active
|
||||
:disabled disabled
|
||||
:on-press on-press
|
||||
:accessory-text accessory-text
|
||||
:animated-accessory? animated-accessory?
|
||||
:accessory-style accessory-style
|
||||
:accessory accessory}]]]
|
||||
[left-side
|
||||
{:icon-color icon-color
|
||||
:text-color (if on-press
|
||||
text-color
|
||||
(:text-color (themes :main)))
|
||||
:left-side-alignment left-side-alignment
|
||||
:icon-bg-color icon-bg-color
|
||||
:title-accessibility-label title-accessibility-label
|
||||
:icon icon
|
||||
:icon-container-style icon-container-style
|
||||
:title title
|
||||
:title-text-weight title-text-weight
|
||||
:size size
|
||||
:text-size text-size
|
||||
:subtitle subtitle
|
||||
:subtitle-max-lines subtitle-max-lines
|
||||
:subtitle-secondary subtitle-secondary
|
||||
:right-side-present? (or accessory chevron)}]
|
||||
[right-side
|
||||
{:chevron chevron
|
||||
:active active
|
||||
:disabled disabled
|
||||
:on-press on-press
|
||||
:accessory-text accessory-text
|
||||
:animated-accessory? animated-accessory?
|
||||
:accessory-style accessory-style
|
||||
:accessory accessory}]]]
|
||||
(when error
|
||||
[tooltip/tooltip (merge {:bottom-value 0}
|
||||
(when accessibility-label
|
||||
{:accessibility-label (str (name accessibility-label) "-error")}))
|
||||
[text/text {:color :negative
|
||||
:size :small}
|
||||
[tooltip/tooltip
|
||||
(merge {:bottom-value 0}
|
||||
(when accessibility-label
|
||||
{:accessibility-label (str (name accessibility-label) "-error")}))
|
||||
[text/text
|
||||
{:color :negative
|
||||
:size :small}
|
||||
error]])]))
|
||||
|
@ -1,19 +1,21 @@
|
||||
(ns quo.components.safe-area
|
||||
(:require ["react-native-safe-area-context" :as safe-area-context
|
||||
:refer (SafeAreaView SafeAreaProvider SafeAreaInsetsContext useSafeAreaInsets)]
|
||||
(:require ["react-native-safe-area-context" :as safe-area-context :refer
|
||||
(SafeAreaView SafeAreaProvider SafeAreaInsetsContext useSafeAreaInsets)]
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
(def provider (reagent/adapt-react-class SafeAreaProvider))
|
||||
(def ^:private consumer-raw (reagent/adapt-react-class (.-Consumer ^js SafeAreaInsetsContext)))
|
||||
(def view (reagent/adapt-react-class SafeAreaView))
|
||||
|
||||
(defn consumer [component]
|
||||
(defn consumer
|
||||
[component]
|
||||
[consumer-raw
|
||||
(fn [insets]
|
||||
(reagent/as-element
|
||||
[component (js->clj insets :keywordize-keys true)]))])
|
||||
|
||||
(defn use-safe-area []
|
||||
(defn use-safe-area
|
||||
[]
|
||||
(let [insets (useSafeAreaInsets)]
|
||||
{:top (.-top ^js insets)
|
||||
:bottom (.-bottom ^js insets)
|
||||
|
@ -1,8 +1,9 @@
|
||||
(ns quo.components.separator
|
||||
(:require [quo.react-native :as react]
|
||||
[quo.design-system.colors :as colors]))
|
||||
(:require [quo.design-system.colors :as colors]
|
||||
[quo.react-native :as react]))
|
||||
|
||||
(defn separator [{:keys [color style]}]
|
||||
(defn separator
|
||||
[{:keys [color style]}]
|
||||
[react/view
|
||||
{:style
|
||||
(merge
|
||||
|
@ -5,7 +5,8 @@
|
||||
[quo.react-native :as rn]
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
(defn text-style [{:keys [size align weight monospace color style]}]
|
||||
(defn text-style
|
||||
[{:keys [size align weight monospace color style]}]
|
||||
;; NOTE(Ferossgo): or in destructoring will keep nil as a value
|
||||
(merge (if monospace
|
||||
;; TODO(Ferossgp): Add all weights for monospace
|
||||
@ -38,12 +39,15 @@
|
||||
{:text-align (or align :auto)}
|
||||
style))
|
||||
|
||||
(defn text []
|
||||
(defn text
|
||||
[]
|
||||
(let [this (reagent/current-component)
|
||||
props (reagent/props this)
|
||||
component (if (:animated? props) animated/text rn/text)]
|
||||
(into [component (merge {:style (text-style props)}
|
||||
(dissoc props
|
||||
:style :size :weight :color
|
||||
:align :animated?))]
|
||||
(into [component
|
||||
(merge {:style (text-style props)}
|
||||
(dissoc props
|
||||
:style :size
|
||||
:weight :color
|
||||
:align :animated?))]
|
||||
(reagent/children this))))
|
||||
|
@ -1,16 +1,15 @@
|
||||
(ns quo.components.text-input
|
||||
(:require [clojure.spec.alpha :as s]
|
||||
[reagent.core :as reagent]
|
||||
[oops.core :refer [ocall]]
|
||||
[quo.react-native :as rn]
|
||||
;; TODO(Ferossgp): Move icon component to lib
|
||||
[status-im.ui.components.icons.icons :as icons]
|
||||
[quo.components.text :as text]
|
||||
[quo.components.tooltip :as tooltip]
|
||||
[quo.platform :as platform]
|
||||
[quo.design-system.typography :as typography]
|
||||
[quo.design-system.spacing :as spacing]
|
||||
[quo.design-system.colors :as colors]
|
||||
[quo.components.text :as text]))
|
||||
[quo.design-system.spacing :as spacing]
|
||||
[quo.design-system.typography :as typography]
|
||||
[quo.platform :as platform]
|
||||
[quo.react-native :as rn] ;; TODO(Ferossgp): Move icon component to lib
|
||||
[reagent.core :as reagent]
|
||||
[status-im.ui.components.icons.icons :as icons]))
|
||||
|
||||
;; NOTE(Ferossgp): Refactor with hooks when available
|
||||
;; We track all currently mounted text input refs
|
||||
@ -22,19 +21,26 @@
|
||||
(s/def ::multiline boolean?)
|
||||
(s/def ::secure-text-entry boolean?)
|
||||
(s/def ::show-cancel boolean?)
|
||||
(s/def ::label (s/nilable (s/or :string string? :component vector?)))
|
||||
(s/def ::label
|
||||
(s/nilable (s/or :string string?
|
||||
:component vector?)))
|
||||
(s/def ::cancel-label (s/nilable string?))
|
||||
(s/def ::default-value (s/nilable string?))
|
||||
(s/def ::placeholder (s/nilable string?))
|
||||
(s/def ::keyboard-type (s/nilable (s/or :string string? :keyword keyword?))) ; TODO: make set
|
||||
(s/def ::accessibility-label (s/nilable (s/or :string string? :keyword keyword?)))
|
||||
(s/def ::keyboard-type
|
||||
(s/nilable (s/or :string string?
|
||||
:keyword keyword?))) ; TODO: make set
|
||||
(s/def ::accessibility-label
|
||||
(s/nilable (s/or :string string?
|
||||
:keyword keyword?)))
|
||||
(s/def ::on-focus fn?)
|
||||
(s/def ::on-blur fn?)
|
||||
(s/def ::on-press fn?)
|
||||
|
||||
(s/def ::accessory (s/keys :opt-un [::on-press
|
||||
::icon
|
||||
::component]))
|
||||
(s/def ::accessory
|
||||
(s/keys :opt-un [::on-press
|
||||
::icon
|
||||
::component]))
|
||||
(s/def ::after (s/nilable ::accessory))
|
||||
(s/def ::before (s/nilable ::accessory))
|
||||
|
||||
@ -42,25 +48,27 @@
|
||||
(s/def ::input-style ::style)
|
||||
(s/def ::container-style ::style)
|
||||
|
||||
(s/def ::text-input (s/keys :opt-un
|
||||
[::label
|
||||
::multiline
|
||||
::error
|
||||
::style
|
||||
::input-style
|
||||
::keyboard-type
|
||||
::before
|
||||
::after
|
||||
::cancel-label
|
||||
::on-focus
|
||||
::on-blur
|
||||
::container-style
|
||||
::show-cancel
|
||||
::accessibility-label
|
||||
::bottom-value
|
||||
::secure-text-entry]))
|
||||
(s/def ::text-input
|
||||
(s/keys :opt-un
|
||||
[::label
|
||||
::multiline
|
||||
::error
|
||||
::style
|
||||
::input-style
|
||||
::keyboard-type
|
||||
::before
|
||||
::after
|
||||
::cancel-label
|
||||
::on-focus
|
||||
::on-blur
|
||||
::container-style
|
||||
::show-cancel
|
||||
::accessibility-label
|
||||
::bottom-value
|
||||
::secure-text-entry]))
|
||||
|
||||
(defn check-spec [spec prop]
|
||||
(defn check-spec
|
||||
[spec prop]
|
||||
(if (s/valid? spec prop)
|
||||
true
|
||||
(do
|
||||
@ -70,14 +78,17 @@
|
||||
(def height 44) ; 22 line-height + 11*2 vertical padding
|
||||
(def multiline-height 88) ; 3 * 22 three line-height + 11* vertical padding
|
||||
|
||||
(defn label-style []
|
||||
(defn label-style
|
||||
[]
|
||||
{:margin-bottom (:tiny spacing/spacing)})
|
||||
|
||||
(defn text-input-row-style []
|
||||
(defn text-input-row-style
|
||||
[]
|
||||
{:flex-direction :row
|
||||
:align-items :center})
|
||||
|
||||
(defn text-input-view-style [style]
|
||||
(defn text-input-view-style
|
||||
[style]
|
||||
(merge {:border-radius 8
|
||||
:flex-direction :row
|
||||
:flex 1
|
||||
@ -85,7 +96,8 @@
|
||||
:background-color (:ui-01 @colors/theme)}
|
||||
style))
|
||||
|
||||
(defn text-input-style [multiline input-style monospace before after]
|
||||
(defn text-input-style
|
||||
[multiline input-style monospace before after]
|
||||
(merge (if monospace
|
||||
typography/monospace
|
||||
typography/font-regular)
|
||||
@ -107,66 +119,76 @@
|
||||
:height multiline-height})
|
||||
input-style))
|
||||
|
||||
(defn cancel-style []
|
||||
(defn cancel-style
|
||||
[]
|
||||
{:margin-left (:tiny spacing/spacing)
|
||||
:padding-left (:tiny spacing/spacing)
|
||||
:justify-content :center
|
||||
:align-self :stretch})
|
||||
|
||||
(defn accessory-style []
|
||||
(defn accessory-style
|
||||
[]
|
||||
(merge (:base spacing/padding-horizontal)
|
||||
{:flex 1
|
||||
:justify-content :center}))
|
||||
|
||||
(defn accessory-element [{:keys [icon component icon-opts style accessibility-label on-press]}]
|
||||
(defn accessory-element
|
||||
[{:keys [icon component icon-opts style accessibility-label on-press]}]
|
||||
(let [el (if on-press
|
||||
rn/touchable-opacity
|
||||
rn/view)]
|
||||
[el (merge {:style {:align-self :stretch}}
|
||||
(when on-press
|
||||
{:on-press on-press}))
|
||||
[rn/view (merge {:style (merge (accessory-style)
|
||||
style)}
|
||||
(when accessibility-label
|
||||
{:accessibility-label accessibility-label}))
|
||||
[el
|
||||
(merge {:style {:align-self :stretch}}
|
||||
(when on-press
|
||||
{:on-press on-press}))
|
||||
[rn/view
|
||||
(merge {:style (merge (accessory-style)
|
||||
style)}
|
||||
(when accessibility-label
|
||||
{:accessibility-label accessibility-label}))
|
||||
(cond
|
||||
icon
|
||||
[icons/icon icon (merge {:color (:icon-01 @colors/theme)}
|
||||
icon-opts)]
|
||||
[icons/icon icon
|
||||
(merge {:color (:icon-01 @colors/theme)}
|
||||
icon-opts)]
|
||||
component
|
||||
component
|
||||
|
||||
:else
|
||||
nil)]]))
|
||||
|
||||
(defn text-input-raw []
|
||||
(defn text-input-raw
|
||||
[]
|
||||
(let [focused (reagent/atom nil)
|
||||
visible (reagent/atom false)
|
||||
ref (atom nil)
|
||||
blur (fn []
|
||||
(some-> @ref (ocall "blur")))]
|
||||
(fn [{:keys [label multiline error style input-style keyboard-type before after
|
||||
cancel-label on-focus on-blur show-cancel accessibility-label
|
||||
bottom-value secure-text-entry container-style get-ref on-cancel
|
||||
monospace auto-complete-type auto-correct]
|
||||
:or {cancel-label "Cancel"}
|
||||
:as props}]
|
||||
(some-> @ref
|
||||
(ocall "blur")))]
|
||||
(fn
|
||||
[{:keys [label multiline error style input-style keyboard-type before after
|
||||
cancel-label on-focus on-blur show-cancel accessibility-label
|
||||
bottom-value secure-text-entry container-style get-ref on-cancel
|
||||
monospace auto-complete-type auto-correct]
|
||||
:or {cancel-label "Cancel"}
|
||||
:as props}]
|
||||
{:pre [(check-spec ::text-input props)]}
|
||||
(let [show-cancel (if (nil? show-cancel)
|
||||
;; Enabled by default on iOs and disabled on Android
|
||||
platform/ios?
|
||||
show-cancel)
|
||||
after (cond
|
||||
(and secure-text-entry @visible)
|
||||
{:icon :main-icons/hide
|
||||
:on-press #(reset! visible false)}
|
||||
(let [show-cancel (if (nil? show-cancel)
|
||||
;; Enabled by default on iOs and disabled on Android
|
||||
platform/ios?
|
||||
show-cancel)
|
||||
after (cond
|
||||
(and secure-text-entry @visible)
|
||||
{:icon :main-icons/hide
|
||||
:on-press #(reset! visible false)}
|
||||
|
||||
(and secure-text-entry (not @visible))
|
||||
{:icon :main-icons/show
|
||||
:on-press #(reset! visible true)}
|
||||
(and secure-text-entry (not @visible))
|
||||
{:icon :main-icons/show
|
||||
:on-press #(reset! visible true)}
|
||||
|
||||
:else after)
|
||||
secure (boolean (and secure-text-entry (not @visible))) ; must be a boolean to work on iOS
|
||||
:else after)
|
||||
secure (boolean (and secure-text-entry (not @visible))) ; must be a boolean to work on
|
||||
; iOS
|
||||
auto-complete (cond
|
||||
(= keyboard-type :visible-password)
|
||||
:off
|
||||
@ -176,7 +198,9 @@
|
||||
|
||||
:else
|
||||
auto-complete-type)
|
||||
auto-correct (and (not= keyboard-type :visible-password) (not secure-text-entry) auto-correct)
|
||||
auto-correct (and (not= keyboard-type :visible-password)
|
||||
(not secure-text-entry)
|
||||
auto-correct)
|
||||
on-cancel (fn []
|
||||
(when on-cancel
|
||||
(on-cancel))
|
||||
@ -185,8 +209,10 @@
|
||||
(and platform/ios? (= keyboard-type :visible-password))
|
||||
:default
|
||||
|
||||
; the correct approach on Android would be keep secure-text-entry on set keyboard type
|
||||
; to visible-password. But until https://github.com/facebook/react-native/issues/27946
|
||||
; the correct approach on Android would be keep secure-text-entry on set
|
||||
; keyboard type
|
||||
; to visible-password. But until
|
||||
; https://github.com/facebook/react-native/issues/27946
|
||||
; is solved that's the second best way.
|
||||
(and platform/android? secure-text-entry)
|
||||
:default
|
||||
@ -198,59 +224,71 @@
|
||||
[text/text {:style (label-style)}
|
||||
label])
|
||||
[rn/view {:style (text-input-row-style)}
|
||||
[rn/view {:style (text-input-view-style style)
|
||||
:important-for-accessibility (if secure-text-entry
|
||||
:no-hide-descendants
|
||||
:auto)}
|
||||
[rn/view
|
||||
{:style (text-input-view-style style)
|
||||
:important-for-accessibility (if secure-text-entry
|
||||
:no-hide-descendants
|
||||
:auto)}
|
||||
(when before
|
||||
[accessory-element before])
|
||||
[rn/text-input
|
||||
(merge {:style (text-input-style multiline input-style monospace before after)
|
||||
:ref (fn [r]
|
||||
(reset! ref r)
|
||||
(when get-ref (get-ref r)))
|
||||
:placeholder-text-color (:text-02 @colors/theme)
|
||||
:underline-color-android :transparent
|
||||
:auto-capitalize :none
|
||||
:secure-text-entry secure
|
||||
:auto-correct auto-correct
|
||||
:auto-complete-type auto-complete
|
||||
:on-focus (fn [evt]
|
||||
(when on-focus (on-focus evt))
|
||||
(when show-cancel
|
||||
(rn/configure-next (:ease-in-ease-out rn/layout-animation-presets)))
|
||||
(reset! focused true))
|
||||
:on-blur (fn [evt]
|
||||
(when on-blur (on-blur evt))
|
||||
(when show-cancel
|
||||
(rn/configure-next (:ease-in-ease-out rn/layout-animation-presets)))
|
||||
(reset! focused false))
|
||||
:keyboard-type keyboard-type}
|
||||
(when (and platform/ios? (not after))
|
||||
{:clear-button-mode :while-editing})
|
||||
(dissoc props
|
||||
:style :keyboard-type :on-focus :on-blur
|
||||
:secure-text-entry :ref :get-ref :auto-correct :auto-complete-type))]
|
||||
(merge
|
||||
{:style (text-input-style multiline input-style monospace before after)
|
||||
:ref (fn [r]
|
||||
(reset! ref r)
|
||||
(when get-ref (get-ref r)))
|
||||
:placeholder-text-color (:text-02 @colors/theme)
|
||||
:underline-color-android :transparent
|
||||
:auto-capitalize :none
|
||||
:secure-text-entry secure
|
||||
:auto-correct auto-correct
|
||||
:auto-complete-type auto-complete
|
||||
:on-focus (fn [evt]
|
||||
(when on-focus (on-focus evt))
|
||||
(when show-cancel
|
||||
(rn/configure-next (:ease-in-ease-out
|
||||
rn/layout-animation-presets)))
|
||||
(reset! focused true))
|
||||
:on-blur (fn [evt]
|
||||
(when on-blur (on-blur evt))
|
||||
(when show-cancel
|
||||
(rn/configure-next (:ease-in-ease-out
|
||||
rn/layout-animation-presets)))
|
||||
(reset! focused false))
|
||||
:keyboard-type keyboard-type}
|
||||
(when (and platform/ios? (not after))
|
||||
{:clear-button-mode :while-editing})
|
||||
(dissoc props
|
||||
:style
|
||||
:keyboard-type :on-focus
|
||||
:on-blur
|
||||
:secure-text-entry
|
||||
:ref :get-ref
|
||||
:auto-correct :auto-complete-type))]
|
||||
(when after
|
||||
[accessory-element after])]
|
||||
(when (and show-cancel
|
||||
(not multiline)
|
||||
@focused)
|
||||
[rn/touchable-opacity {:style (cancel-style)
|
||||
:on-press on-cancel}
|
||||
[rn/touchable-opacity
|
||||
{:style (cancel-style)
|
||||
:on-press on-cancel}
|
||||
[text/text {:color :link} cancel-label]])
|
||||
(when error
|
||||
[tooltip/tooltip (merge {:bottom-value (if bottom-value bottom-value 0)}
|
||||
(when accessibility-label
|
||||
{:accessibility-label (str (name accessibility-label) "-error")}))
|
||||
[text/text {:color :negative
|
||||
:align :center
|
||||
:size :small}
|
||||
[tooltip/tooltip
|
||||
(merge {:bottom-value (if bottom-value bottom-value 0)}
|
||||
(when accessibility-label
|
||||
{:accessibility-label (str (name accessibility-label) "-error")}))
|
||||
[text/text
|
||||
{:color :negative
|
||||
:align :center
|
||||
:size :small}
|
||||
error]])]]))))
|
||||
|
||||
;; TODO(Ferossgp): Refactor me when hooks available
|
||||
(defn text-input [{:keys [preserve-input?]
|
||||
:as props}]
|
||||
(defn text-input
|
||||
[{:keys [preserve-input?]
|
||||
:as props}]
|
||||
(if preserve-input?
|
||||
[text-input-raw props]
|
||||
(let [id (random-uuid)]
|
||||
@ -261,10 +299,11 @@
|
||||
:reagent-render
|
||||
(fn [{:keys [get-ref default-value]
|
||||
:as props}]
|
||||
[text-input-raw (merge props
|
||||
{:get-ref (fn [r]
|
||||
;; Store input and its defaultValue
|
||||
;; one we receive a non-nil ref
|
||||
(when r
|
||||
(swap! text-input-refs assoc id {:ref r :value default-value}))
|
||||
(when get-ref (get-ref r)))})])}))))
|
||||
[text-input-raw
|
||||
(merge props
|
||||
{:get-ref (fn [r]
|
||||
;; Store input and its defaultValue
|
||||
;; one we receive a non-nil ref
|
||||
(when r
|
||||
(swap! text-input-refs assoc id {:ref r :value default-value}))
|
||||
(when get-ref (get-ref r)))})])}))))
|
||||
|
@ -1,17 +1,17 @@
|
||||
(ns quo.components.tooltip
|
||||
(:require [reagent.core :as reagent]
|
||||
[oops.core :refer [oget]]
|
||||
(:require [oops.core :refer [oget]]
|
||||
[quo.animated :as animated]
|
||||
[quo.react-native :as rn]
|
||||
[quo.design-system.colors :as colors]
|
||||
[quo.design-system.spacing :as spacing]
|
||||
[quo.platform :as platform]
|
||||
;; FIXME(Ferossgp): Dependecy on status
|
||||
[quo.platform :as platform] ;; FIXME(Ferossgp): Dependecy on status
|
||||
[quo.react-native :as rn]
|
||||
[reagent.core :as reagent]
|
||||
[status-im.ui.components.icons.icons :as icons]))
|
||||
|
||||
(def ^:private initial-height 22)
|
||||
|
||||
(defn tooltip-style [{:keys [bottom-value animation]}]
|
||||
(defn tooltip-style
|
||||
[{:keys [bottom-value animation]}]
|
||||
(merge
|
||||
(:base spacing/padding-horizontal)
|
||||
{:position :absolute
|
||||
@ -22,7 +22,8 @@
|
||||
:opacity animation
|
||||
:transform [{:translateY (animated/mix animation 10 0)}]}))
|
||||
|
||||
(defn container-style []
|
||||
(defn container-style
|
||||
[]
|
||||
{:z-index 2
|
||||
:align-items :center
|
||||
:shadow-radius 16
|
||||
@ -30,43 +31,50 @@
|
||||
:shadow-color (:shadow-01 @colors/theme)
|
||||
:shadow-offset {:width 0 :height 4}})
|
||||
|
||||
(defn content-style []
|
||||
(defn content-style
|
||||
[]
|
||||
(merge (:base spacing/padding-horizontal)
|
||||
{:padding-vertical 6
|
||||
:elevation 2
|
||||
:background-color (:ui-background @colors/theme)
|
||||
:border-radius 8}))
|
||||
|
||||
(defn tooltip []
|
||||
(defn tooltip
|
||||
[]
|
||||
(let [layout (reagent/atom {:height initial-height})
|
||||
animation-v (animated/value 0)
|
||||
animation (animated/with-timing-transition
|
||||
animation-v
|
||||
{:easing (:ease-in animated/easings)})
|
||||
animation-v
|
||||
{:easing (:ease-in animated/easings)})
|
||||
on-layout (fn [evt]
|
||||
(let [width (oget evt "nativeEvent" "layout" "width")
|
||||
height (oget evt "nativeEvent" "layout" "height")]
|
||||
(reset! layout {:width width
|
||||
:height height})))]
|
||||
(fn [{:keys [bottom-value accessibility-label]} & children]
|
||||
(fn [{:keys [bottom-value accessibility-label]} & children]
|
||||
[:<>
|
||||
[animated/code {:exec (animated/cond* (animated/not* animation-v)
|
||||
(animated/set animation-v 1))}]
|
||||
[animated/view {:style (tooltip-style {:bottom-value (- (get @layout :height)
|
||||
bottom-value)
|
||||
:animation animation})
|
||||
:pointer-events :box-none}
|
||||
[animated/view {:style (container-style)
|
||||
:pointer-events :box-none}
|
||||
(into [rn/view {:style (content-style)
|
||||
:pointer-events :box-none
|
||||
:accessibility-label accessibility-label
|
||||
:on-layout on-layout}]
|
||||
[animated/code
|
||||
{:exec (animated/cond* (animated/not* animation-v)
|
||||
(animated/set animation-v 1))}]
|
||||
[animated/view
|
||||
{:style (tooltip-style {:bottom-value (- (get @layout :height)
|
||||
bottom-value)
|
||||
:animation animation})
|
||||
:pointer-events :box-none}
|
||||
[animated/view
|
||||
{:style (container-style)
|
||||
:pointer-events :box-none}
|
||||
(into [rn/view
|
||||
{:style (content-style)
|
||||
:pointer-events :box-none
|
||||
:accessibility-label accessibility-label
|
||||
:on-layout on-layout}]
|
||||
children)
|
||||
|
||||
(when platform/ios?
|
||||
;; NOTE(Ferossgp): Android does not show elevation for tooltip making it lost on white bg
|
||||
[icons/icon :icons/tooltip-tip {:width 18
|
||||
:height 8
|
||||
:container-style {:elevation 3}
|
||||
:color (:ui-background @colors/theme)}])]]])))
|
||||
[icons/icon :icons/tooltip-tip
|
||||
{:width 18
|
||||
:height 8
|
||||
:container-style {:elevation 3}
|
||||
:color (:ui-background @colors/theme)}])]]])))
|
||||
|
@ -1,18 +1,18 @@
|
||||
(ns quo.core
|
||||
(:require [quo.components.animated-header :as animated-header]
|
||||
[quo.components.bottom-sheet.view :as bottom-sheet]
|
||||
[quo.components.button.view :as button]
|
||||
[quo.components.controls.view :as controls]
|
||||
[quo.components.header :as header]
|
||||
[quo.components.list.footer :as list-footer]
|
||||
[quo.components.list.header :as list-header]
|
||||
[quo.components.list.index :as list-index]
|
||||
[quo.components.list.item :as list-item]
|
||||
[quo.components.safe-area :as safe-area]
|
||||
[quo.components.separator :as separator]
|
||||
[quo.components.text :as text]
|
||||
[quo.components.text-input :as text-input]
|
||||
[quo.components.tooltip :as tooltip]
|
||||
[quo.components.text :as text]
|
||||
[quo.components.button.view :as button]
|
||||
[quo.components.list.header :as list-header]
|
||||
[quo.components.list.footer :as list-footer]
|
||||
[quo.components.list.item :as list-item]
|
||||
[quo.components.list.index :as list-index]
|
||||
[quo.components.controls.view :as controls]
|
||||
[quo.components.bottom-sheet.view :as bottom-sheet]
|
||||
[quo.components.separator :as separator]
|
||||
[quo.design-system.colors :as colors]))
|
||||
|
||||
(def text text/text)
|
||||
|
@ -1,6 +1,6 @@
|
||||
(ns quo.design-system.colors
|
||||
(:require [reagent.core :as reagent]
|
||||
[clojure.string :as string]))
|
||||
(:require [clojure.string :as string]
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
;; Colors mapping from figma to code, note that theme is more extended and
|
||||
;; one can follow the comments from the light theme to choose what to use in a component.
|
||||
@ -19,14 +19,17 @@
|
||||
|
||||
(def light-theme
|
||||
{:positive-01 "rgba(68,208,88,1)" ; Primary Positive, text, icons color
|
||||
:positive-02 "rgba(78,188,96,0.1)" ; Secondary Positive, Supporting color for success illustrations
|
||||
:positive-02 "rgba(78,188,96,0.1)" ; Secondary Positive, Supporting color for success
|
||||
; illustrations
|
||||
:positive-03 "rgba(78,188,96,1)" ; Lighter Positive, Supporting color for success illustrations
|
||||
:negative-01 "rgba(255,45,85,1)" ; Primary Negative, text, icons color
|
||||
:negative-02 "rgba(255,45,85,0.1))" ; Secondary Negative, Supporting color for errors illustrations
|
||||
:negative-02 "rgba(255,45,85,0.1))" ; Secondary Negative, Supporting color for errors
|
||||
; illustrations
|
||||
:warning-01 "rgba(255, 202, 15, 1)"
|
||||
:warning-02 "rgba(255, 202, 15, 0.1)"
|
||||
:interactive-01 "rgba(67,96,223,1)" ; Accent color, buttons, own message, actions,active state
|
||||
:interactive-02 "rgba(236,239,252,1)" ; Light Accent, buttons background, actions background, messages
|
||||
:interactive-02 "rgba(236,239,252,1)" ; Light Accent, buttons background, actions background,
|
||||
; messages
|
||||
:interactive-03 "rgba(255,255,255,0.1)" ; Background for interactive above accent
|
||||
:interactive-04 "rgba(147,155,161,1)" ; Disabled state
|
||||
:ui-background "rgba(255,255,255,1)" ; Default view background
|
||||
@ -85,12 +88,14 @@
|
||||
|
||||
(def theme (reagent/atom light-theme))
|
||||
|
||||
(defn get-color [color]
|
||||
(defn get-color
|
||||
[color]
|
||||
(get @theme color))
|
||||
|
||||
;; LEGACY COLORS
|
||||
|
||||
(defn alpha [value opacity]
|
||||
(defn alpha
|
||||
[value opacity]
|
||||
(if (string/starts-with? value "#")
|
||||
(let [hex (string/replace value #"#" "")
|
||||
r (js/parseInt (subs hex 0 2) 16)
|
||||
@ -100,13 +105,15 @@
|
||||
(let [rgb (string/split value #",")]
|
||||
(str (string/join "," (butlast rgb)) "," opacity ")"))))
|
||||
|
||||
(def old-colors-mapping-light {:mentioned-background "#def6fc"
|
||||
:mentioned-border "#b8ecf9"
|
||||
:pin-background "#FFEECC"})
|
||||
(def old-colors-mapping-light
|
||||
{:mentioned-background "#def6fc"
|
||||
:mentioned-border "#b8ecf9"
|
||||
:pin-background "#FFEECC"})
|
||||
|
||||
(def old-colors-mapping-dark {:mentioned-background "#2a4046"
|
||||
:mentioned-border "#2a4046"
|
||||
:pin-background "#34232B"})
|
||||
(def old-colors-mapping-dark
|
||||
{:mentioned-background "#2a4046"
|
||||
:mentioned-border "#2a4046"
|
||||
:pin-background "#34232B"})
|
||||
|
||||
(def old-colors-mapping-themes {:dark old-colors-mapping-dark :light old-colors-mapping-light})
|
||||
|
||||
@ -127,7 +134,8 @@
|
||||
;; BLACK
|
||||
(def black (:text-01 light-theme)) ;; Used as the default text color
|
||||
(def black-persist (:ui-background dark-theme)) ;; this doesn't with theme
|
||||
(def black-transparent (:ui-02 light-theme)) ;; Used as background color for rounded button on dark background and as background color for containers like "Backup recovery phrase"
|
||||
(def black-transparent (:ui-02 light-theme)) ;; Used as background color for rounded button on dark background and as background
|
||||
;; color for containers like "Backup recovery phrase"
|
||||
(def black-transparent-20 (:backdrop light-theme)) ; accounts divider
|
||||
(def black-transparent-40 (:backdrop light-theme))
|
||||
(def black-transparent-40-persist (:backdrop light-theme))
|
||||
@ -136,7 +144,8 @@
|
||||
(def black-transparent-86 (:ui-03 light-theme))
|
||||
|
||||
;; DARK GREY
|
||||
(def gray (:text-02 light-theme)) ;; Dark grey, used as a background for a light foreground and as section header and secondary text color
|
||||
(def gray (:text-02 light-theme)) ;; Dark grey, used as a background for a light foreground and as
|
||||
;; section header and secondary text color
|
||||
(def gray-transparent-10 (alpha gray 0.1))
|
||||
(def gray-transparent-40 (alpha gray 0.4))
|
||||
;; LIGHT GREY
|
||||
@ -164,20 +173,22 @@
|
||||
(def purple "#887af9")
|
||||
(def orange "#FE8F59")
|
||||
|
||||
(def chat-colors ["#fa6565"
|
||||
"#7cda00"
|
||||
purple
|
||||
"#51d0f0"
|
||||
orange
|
||||
"#d37ef4"])
|
||||
(def chat-colors
|
||||
["#fa6565"
|
||||
"#7cda00"
|
||||
purple
|
||||
"#51d0f0"
|
||||
orange
|
||||
"#d37ef4"])
|
||||
|
||||
(def account-colors ["#9B832F"
|
||||
"#D37EF4"
|
||||
"#1D806F"
|
||||
"#FA6565"
|
||||
"#7CDA00"
|
||||
purple
|
||||
"#8B3131"])
|
||||
(def account-colors
|
||||
["#9B832F"
|
||||
"#D37EF4"
|
||||
"#1D806F"
|
||||
"#FA6565"
|
||||
"#7CDA00"
|
||||
purple
|
||||
"#8B3131"])
|
||||
|
||||
(def mention-incoming "#0DA4C9")
|
||||
(def mention-outgoing "#9EE8FA")
|
||||
@ -191,10 +202,12 @@
|
||||
|
||||
(def theme-type (reagent/atom :light))
|
||||
|
||||
(defn dark? []
|
||||
(defn dark?
|
||||
[]
|
||||
(= :dark @theme-type))
|
||||
|
||||
(defn set-legacy-theme-type [type]
|
||||
(defn set-legacy-theme-type
|
||||
[type]
|
||||
(when-not (= type @theme-type)
|
||||
(let [old-colors-mapping-colors (get old-colors-mapping-themes type)]
|
||||
(set! white (:ui-background @theme))
|
||||
|
@ -1,19 +1,22 @@
|
||||
(ns quo.design-system.spacing)
|
||||
|
||||
(def spacing {:x-tiny 4
|
||||
:tiny 8
|
||||
:small 12
|
||||
:base 16
|
||||
:large 24
|
||||
:x-large 32
|
||||
:xx-large 48})
|
||||
(def spacing
|
||||
{:x-tiny 4
|
||||
:tiny 8
|
||||
:small 12
|
||||
:base 16
|
||||
:large 24
|
||||
:x-large 32
|
||||
:xx-large 48})
|
||||
|
||||
(def padding-horizontal (reduce-kv (fn [m k v]
|
||||
(assoc m k {:padding-horizontal v}))
|
||||
{}
|
||||
spacing))
|
||||
(def padding-horizontal
|
||||
(reduce-kv (fn [m k v]
|
||||
(assoc m k {:padding-horizontal v}))
|
||||
{}
|
||||
spacing))
|
||||
|
||||
(def padding-vertical (reduce-kv (fn [m k v]
|
||||
(assoc m k {:padding-vertical v}))
|
||||
{}
|
||||
spacing))
|
||||
(def padding-vertical
|
||||
(reduce-kv (fn [m k v]
|
||||
(assoc m k {:padding-vertical v}))
|
||||
{}
|
||||
spacing))
|
||||
|
@ -1,25 +1,32 @@
|
||||
(ns quo.design-system.typography)
|
||||
|
||||
(def tiny {:font-size 10
|
||||
:line-height 14})
|
||||
(def tiny
|
||||
{:font-size 10
|
||||
:line-height 14})
|
||||
|
||||
(def x-small {:font-size 12
|
||||
:line-height 16})
|
||||
(def x-small
|
||||
{:font-size 12
|
||||
:line-height 16})
|
||||
|
||||
(def small {:font-size 13
|
||||
:line-height 18})
|
||||
(def small
|
||||
{:font-size 13
|
||||
:line-height 18})
|
||||
|
||||
(def base {:font-size 15
|
||||
:line-height 22})
|
||||
(def base
|
||||
{:font-size 15
|
||||
:line-height 22})
|
||||
|
||||
(def large {:font-size 17
|
||||
:line-height 24})
|
||||
(def large
|
||||
{:font-size 17
|
||||
:line-height 24})
|
||||
|
||||
(def x-large {:font-size 22
|
||||
:line-height 30})
|
||||
(def x-large
|
||||
{:font-size 22
|
||||
:line-height 30})
|
||||
|
||||
(def xx-large {:font-size 28
|
||||
:line-height 38})
|
||||
(def xx-large
|
||||
{:font-size 28
|
||||
:line-height 38})
|
||||
|
||||
(def font-regular {:font-family "Inter-Regular"}) ; 400
|
||||
|
||||
|
@ -1,12 +1,17 @@
|
||||
(ns quo.gesture-handler
|
||||
(:require [oops.core :refer [oget]]
|
||||
[reagent.core :as reagent]
|
||||
(:require ["react-native-gesture-handler" :refer
|
||||
(TapGestureHandler PanGestureHandler
|
||||
LongPressGestureHandler
|
||||
TouchableWithoutFeedback
|
||||
TouchableOpacity
|
||||
TouchableHighlight
|
||||
State
|
||||
NativeViewGestureHandler
|
||||
FlatList
|
||||
ScrollView)]
|
||||
[oops.core :refer [oget]]
|
||||
[quo.design-system.colors :as colors]
|
||||
["react-native-gesture-handler"
|
||||
:refer (TapGestureHandler PanGestureHandler LongPressGestureHandler
|
||||
TouchableWithoutFeedback TouchableOpacity
|
||||
TouchableHighlight State NativeViewGestureHandler
|
||||
FlatList ScrollView)]))
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
(def flat-list-raw FlatList)
|
||||
|
||||
@ -30,9 +35,11 @@
|
||||
|
||||
(def touchable-highlight-class (reagent/adapt-react-class TouchableHighlight))
|
||||
|
||||
(defn touchable-highlight [props & children]
|
||||
(into [touchable-highlight-class (merge {:underlay-color (:interactive-02 @colors/theme)}
|
||||
props)]
|
||||
(defn touchable-highlight
|
||||
[props & children]
|
||||
(into [touchable-highlight-class
|
||||
(merge {:underlay-color (:interactive-02 @colors/theme)}
|
||||
props)]
|
||||
children))
|
||||
|
||||
(def touchable-opacity
|
||||
@ -40,9 +47,10 @@
|
||||
|
||||
(def native-view-gesture-handler (reagent/adapt-react-class NativeViewGestureHandler))
|
||||
|
||||
(def states {:began (oget State "BEGAN")
|
||||
:active (oget State "ACTIVE")
|
||||
:cancelled (oget State "CANCELLED")
|
||||
:end (oget State "END")
|
||||
:failed (oget State "FAILED")
|
||||
:undetermined (oget State "UNDETERMINED")})
|
||||
(def states
|
||||
{:began (oget State "BEGAN")
|
||||
:active (oget State "ACTIVE")
|
||||
:cancelled (oget State "CANCELLED")
|
||||
:end (oget State "END")
|
||||
:failed (oget State "FAILED")
|
||||
:undetermined (oget State "UNDETERMINED")})
|
||||
|
@ -9,16 +9,17 @@
|
||||
:notification-success "notificationSuccess"
|
||||
:notification-warning "notificationWarning"
|
||||
:notification-error "notificationError"
|
||||
:clock-tick "clockTick" ; (Android only)
|
||||
:context-click "contextClick" ; (Android only)
|
||||
:keyboard-press "keyboardPress" ; (Android only)
|
||||
:keyboard-release "keyboardRelease" ; (Android only)
|
||||
:keyboard-tap "keyboardTap" ; (Android only)
|
||||
:long-press "longPress" ; (Android only)
|
||||
:text-handle-move "textHandleMove" ; (Android only)
|
||||
:virtual-key "virtualKey" ; (Android only)
|
||||
:virtual-key-release "virtualKeyRelease" ; (Android only)
|
||||
})
|
||||
:clock-tick "clockTick" ; (Android only)
|
||||
:context-click "contextClick" ; (Android only)
|
||||
:keyboard-press "keyboardPress" ; (Android only)
|
||||
:keyboard-release "keyboardRelease" ; (Android only)
|
||||
:keyboard-tap "keyboardTap" ; (Android only)
|
||||
:long-press "longPress" ; (Android only)
|
||||
:text-handle-move "textHandleMove" ; (Android only)
|
||||
:virtual-key "virtualKey" ; (Android only)
|
||||
:virtual-key-release "virtualKeyRelease" ; (Android only)
|
||||
})
|
||||
|
||||
(defn trigger [method]
|
||||
(defn trigger
|
||||
[method]
|
||||
(.trigger ^js react-native-haptic-feedback (get haptic-methods method)))
|
||||
|
@ -1,27 +1,29 @@
|
||||
(ns quo.previews.bottom-sheet
|
||||
(:require [reagent.core :as reagent]
|
||||
[quo.core :as quo]
|
||||
[quo.react-native :as rn]
|
||||
(:require [quo.core :as quo]
|
||||
[quo.design-system.colors :as colors]
|
||||
[quo.previews.preview :as preview]))
|
||||
[quo.previews.preview :as preview]
|
||||
[quo.react-native :as rn]
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
(def descriptor [{:label "Show handle:"
|
||||
:key :show-handle?
|
||||
:type :boolean}
|
||||
{:label "Backdrop dismiss:"
|
||||
:key :backdrop-dismiss?
|
||||
:type :boolean}
|
||||
{:label "Disable drag:"
|
||||
:key :disable-drag?
|
||||
:type :boolean}
|
||||
{:label "Android back cancel:"
|
||||
:key :back-button-cancel
|
||||
:type :boolean}
|
||||
{:label "Scrollable:"
|
||||
:key :scrollable
|
||||
:type :boolean}])
|
||||
(def descriptor
|
||||
[{:label "Show handle:"
|
||||
:key :show-handle?
|
||||
:type :boolean}
|
||||
{:label "Backdrop dismiss:"
|
||||
:key :backdrop-dismiss?
|
||||
:type :boolean}
|
||||
{:label "Disable drag:"
|
||||
:key :disable-drag?
|
||||
:type :boolean}
|
||||
{:label "Android back cancel:"
|
||||
:key :back-button-cancel
|
||||
:type :boolean}
|
||||
{:label "Scrollable:"
|
||||
:key :scrollable
|
||||
:type :boolean}])
|
||||
|
||||
(defn cool-preview []
|
||||
(defn cool-preview
|
||||
[]
|
||||
(let [state (reagent/atom {:show-handle? true
|
||||
:backdrop-dismiss? true
|
||||
:disable-drag? false
|
||||
@ -29,38 +31,47 @@
|
||||
visible (reagent/atom false)
|
||||
scrollable (reagent/cursor state [:scrollable])]
|
||||
(fn []
|
||||
[rn/view {:margin-bottom 50
|
||||
:padding 16}
|
||||
[rn/view
|
||||
{:margin-bottom 50
|
||||
:padding 16}
|
||||
[preview/customizer state descriptor]
|
||||
[:<>
|
||||
[rn/view {:style {:align-items :center
|
||||
:padding 16}}
|
||||
[rn/view
|
||||
{:style {:align-items :center
|
||||
:padding 16}}
|
||||
[rn/touchable-opacity {:on-press #(reset! visible true)}
|
||||
[rn/view {:style {:padding-horizontal 16
|
||||
:padding-vertical 8
|
||||
:border-radius 4
|
||||
:background-color (:interactive-01 @colors/theme)}}
|
||||
[rn/view
|
||||
{:style {:padding-horizontal 16
|
||||
:padding-vertical 8
|
||||
:border-radius 4
|
||||
:background-color (:interactive-01 @colors/theme)}}
|
||||
[quo/text {:color :secondary-inverse}
|
||||
(str "Open sheet: " @visible)]]]]
|
||||
|
||||
[quo/bottom-sheet (merge @state
|
||||
{:visible? @visible
|
||||
:on-cancel #(reset! visible false)})
|
||||
[rn/view {:style {:height (if @scrollable 1200 400)
|
||||
:justify-content :center
|
||||
:align-items :center}}
|
||||
[quo/bottom-sheet
|
||||
(merge @state
|
||||
{:visible? @visible
|
||||
:on-cancel #(reset! visible false)})
|
||||
[rn/view
|
||||
{:style {:height (if @scrollable 1200 400)
|
||||
:justify-content :center
|
||||
:align-items :center}}
|
||||
[rn/touchable-opacity {:on-press #(reset! visible false)}
|
||||
[quo/text {:color :link} "Close"]]
|
||||
[rn/touchable-opacity {:on-press #(swap! scrollable not)
|
||||
:style {:padding-vertical 16}}
|
||||
[rn/touchable-opacity
|
||||
{:on-press #(swap! scrollable not)
|
||||
:style {:padding-vertical 16}}
|
||||
[quo/text {:color :link} "Toggle size"]]
|
||||
[quo/text "Hello world!"]]]]])))
|
||||
|
||||
(defn preview []
|
||||
(defn preview
|
||||
[]
|
||||
(fn []
|
||||
[rn/view {:background-color (:ui-background @colors/theme)
|
||||
:flex 1}
|
||||
[rn/flat-list {:flex 1
|
||||
:keyboardShouldPersistTaps :always
|
||||
:header [cool-preview]
|
||||
:key-fn str}]]))
|
||||
[rn/view
|
||||
{:background-color (:ui-background @colors/theme)
|
||||
:flex 1}
|
||||
[rn/flat-list
|
||||
{:flex 1
|
||||
:keyboardShouldPersistTaps :always
|
||||
:header [cool-preview]
|
||||
:key-fn str}]]))
|
||||
|
@ -1,44 +1,46 @@
|
||||
(ns quo.previews.button
|
||||
(:require [reagent.core :as reagent]
|
||||
[quo.core :as quo]
|
||||
[quo.react-native :as rn]
|
||||
(:require [quo.core :as quo]
|
||||
[quo.design-system.colors :as colors]
|
||||
[quo.previews.preview :as preview]))
|
||||
[quo.previews.preview :as preview]
|
||||
[quo.react-native :as rn]
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
(def descriptor [{:label "Type:"
|
||||
:key :type
|
||||
:type :select
|
||||
:options [{:key :primary
|
||||
:value "Primary"}
|
||||
{:key :secondary
|
||||
:value "Secondary"}
|
||||
{:key :icon
|
||||
:value "Icon"}]}
|
||||
{:label "Theme:"
|
||||
:key :theme
|
||||
:type :select
|
||||
:options [{:key :main
|
||||
:value "Main"}
|
||||
{:key :negative
|
||||
:value "Negative"}
|
||||
{:key :positive
|
||||
:value "Positive"}
|
||||
{:key :accent
|
||||
:value "Accent"}]}
|
||||
{:label "After icon:"
|
||||
:key :after
|
||||
:type :boolean}
|
||||
{:label "Before icon:"
|
||||
:key :before
|
||||
:type :boolean}
|
||||
{:label "Disabled:"
|
||||
:key :disabled
|
||||
:type :boolean}
|
||||
{:label "Label"
|
||||
:key :label
|
||||
:type :text}])
|
||||
(def descriptor
|
||||
[{:label "Type:"
|
||||
:key :type
|
||||
:type :select
|
||||
:options [{:key :primary
|
||||
:value "Primary"}
|
||||
{:key :secondary
|
||||
:value "Secondary"}
|
||||
{:key :icon
|
||||
:value "Icon"}]}
|
||||
{:label "Theme:"
|
||||
:key :theme
|
||||
:type :select
|
||||
:options [{:key :main
|
||||
:value "Main"}
|
||||
{:key :negative
|
||||
:value "Negative"}
|
||||
{:key :positive
|
||||
:value "Positive"}
|
||||
{:key :accent
|
||||
:value "Accent"}]}
|
||||
{:label "After icon:"
|
||||
:key :after
|
||||
:type :boolean}
|
||||
{:label "Before icon:"
|
||||
:key :before
|
||||
:type :boolean}
|
||||
{:label "Disabled:"
|
||||
:key :disabled
|
||||
:type :boolean}
|
||||
{:label "Label"
|
||||
:key :label
|
||||
:type :text}])
|
||||
|
||||
(defn cool-preview []
|
||||
(defn cool-preview
|
||||
[]
|
||||
(let [state (reagent/atom {:label "Press Me"
|
||||
:type :primary
|
||||
:theme :main
|
||||
@ -48,28 +50,36 @@
|
||||
before (reagent/cursor state [:before])
|
||||
after (reagent/cursor state [:after])]
|
||||
(fn []
|
||||
[rn/view {:margin-bottom 50
|
||||
:padding 16}
|
||||
[rn/view
|
||||
{:margin-bottom 50
|
||||
:padding 16}
|
||||
[rn/view {:flex 1}
|
||||
[preview/customizer state descriptor]]
|
||||
[rn/view {:padding-vertical 16
|
||||
:flex-direction :row
|
||||
:justify-content :center}
|
||||
[quo/button (merge (dissoc @state
|
||||
:theme :before :after)
|
||||
{:on-press #(println "Hello world!")}
|
||||
(when @theme
|
||||
{:theme @theme})
|
||||
(when @before
|
||||
{:before :main-icons/back})
|
||||
(when @after
|
||||
{:after :main-icons/next}))
|
||||
[rn/view
|
||||
{:padding-vertical 16
|
||||
:flex-direction :row
|
||||
:justify-content :center}
|
||||
[quo/button
|
||||
(merge (dissoc @state
|
||||
:theme
|
||||
:before
|
||||
:after)
|
||||
{:on-press #(println "Hello world!")}
|
||||
(when @theme
|
||||
{:theme @theme})
|
||||
(when @before
|
||||
{:before :main-icons/back})
|
||||
(when @after
|
||||
{:after :main-icons/next}))
|
||||
@label]]])))
|
||||
|
||||
(defn preview-button []
|
||||
[rn/view {:background-color (:ui-background @colors/theme)
|
||||
:flex 1}
|
||||
[rn/flat-list {:flex 1
|
||||
:keyboardShouldPersistTaps :always
|
||||
:header [cool-preview]
|
||||
:key-fn str}]])
|
||||
(defn preview-button
|
||||
[]
|
||||
[rn/view
|
||||
{:background-color (:ui-background @colors/theme)
|
||||
:flex 1}
|
||||
[rn/flat-list
|
||||
{:flex 1
|
||||
:keyboardShouldPersistTaps :always
|
||||
:header [cool-preview]
|
||||
:key-fn str}]])
|
||||
|
@ -1,44 +1,55 @@
|
||||
(ns quo.previews.controls
|
||||
(:require [reagent.core :as reagent]
|
||||
[quo.core :as quo]
|
||||
(:require [quo.core :as quo]
|
||||
[quo.design-system.colors :as colors]
|
||||
[quo.react-native :as rn]
|
||||
[quo.design-system.colors :as colors]))
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
(defn preview []
|
||||
(defn preview
|
||||
[]
|
||||
(let [switch-state (reagent/atom true)
|
||||
radio-state (reagent/atom true)
|
||||
checkbox-state (reagent/atom true)]
|
||||
(fn []
|
||||
[rn/view {:background-color (:ui-background @colors/theme)
|
||||
:flex 1}
|
||||
[rn/view {:padding 20
|
||||
:flex-direction :row
|
||||
:align-items :center
|
||||
:justify-content :space-between}
|
||||
[rn/touchable-opacity {:style {:margin-vertical 10
|
||||
:padding 10}
|
||||
:on-press #(swap! switch-state not)}
|
||||
[rn/view
|
||||
{:background-color (:ui-background @colors/theme)
|
||||
:flex 1}
|
||||
[rn/view
|
||||
{:padding 20
|
||||
:flex-direction :row
|
||||
:align-items :center
|
||||
:justify-content :space-between}
|
||||
[rn/touchable-opacity
|
||||
{:style {:margin-vertical 10
|
||||
:padding 10}
|
||||
:on-press #(swap! switch-state not)}
|
||||
[quo/text (str "Switch state: " @switch-state)]]
|
||||
[quo/switch {:value @switch-state
|
||||
:on-change #(reset! switch-state %)}]]
|
||||
[quo/switch
|
||||
{:value @switch-state
|
||||
:on-change #(reset! switch-state %)}]]
|
||||
|
||||
[rn/view {:padding 20
|
||||
:flex-direction :row
|
||||
:align-items :center
|
||||
:justify-content :space-between}
|
||||
[rn/touchable-opacity {:style {:margin-vertical 10
|
||||
:padding 10}
|
||||
:on-press #(swap! radio-state not)}
|
||||
[rn/view
|
||||
{:padding 20
|
||||
:flex-direction :row
|
||||
:align-items :center
|
||||
:justify-content :space-between}
|
||||
[rn/touchable-opacity
|
||||
{:style {:margin-vertical 10
|
||||
:padding 10}
|
||||
:on-press #(swap! radio-state not)}
|
||||
[quo/text (str "Radio state: " @radio-state)]]
|
||||
[quo/radio {:value @radio-state
|
||||
:on-change #(reset! radio-state %)}]]
|
||||
[rn/view {:padding 20
|
||||
:flex-direction :row
|
||||
:align-items :center
|
||||
:justify-content :space-between}
|
||||
[rn/touchable-opacity {:style {:margin-vertical 10
|
||||
:padding 10}
|
||||
:on-press #(swap! checkbox-state not)}
|
||||
[quo/radio
|
||||
{:value @radio-state
|
||||
:on-change #(reset! radio-state %)}]]
|
||||
[rn/view
|
||||
{:padding 20
|
||||
:flex-direction :row
|
||||
:align-items :center
|
||||
:justify-content :space-between}
|
||||
[rn/touchable-opacity
|
||||
{:style {:margin-vertical 10
|
||||
:padding 10}
|
||||
:on-press #(swap! checkbox-state not)}
|
||||
[quo/text (str "Checkbox state: " @checkbox-state)]]
|
||||
[quo/checkbox {:value @checkbox-state
|
||||
:on-change #(reset! checkbox-state %)}]]])))
|
||||
[quo/checkbox
|
||||
{:value @checkbox-state
|
||||
:on-change #(reset! checkbox-state %)}]]])))
|
||||
|
@ -1,44 +1,51 @@
|
||||
(ns quo.previews.header
|
||||
(:require [quo.core :as quo]
|
||||
[quo.react-native :as rn]
|
||||
[quo.design-system.colors :as colors])
|
||||
[quo.design-system.colors :as colors]
|
||||
[quo.react-native :as rn])
|
||||
(:require-macros [quo.previews.preview :as preview]))
|
||||
|
||||
(def accessories [nil
|
||||
[{:icon :main-icons/close
|
||||
:on-press identity}]
|
||||
[{:icon :main-icons/close
|
||||
:on-press identity}
|
||||
{:icon :main-icons/add
|
||||
:on-press identity}]
|
||||
[{:icon :main-icons/add
|
||||
:on-press identity}
|
||||
{:label "Text"
|
||||
:on-press identity}]
|
||||
[{:label "Text"
|
||||
:on-press identity}]])
|
||||
(def accessories
|
||||
[nil
|
||||
[{:icon :main-icons/close
|
||||
:on-press identity}]
|
||||
[{:icon :main-icons/close
|
||||
:on-press identity}
|
||||
{:icon :main-icons/add
|
||||
:on-press identity}]
|
||||
[{:icon :main-icons/add
|
||||
:on-press identity}
|
||||
{:label "Text"
|
||||
:on-press identity}]
|
||||
[{:label "Text"
|
||||
:on-press identity}]])
|
||||
|
||||
(def all-props (preview/list-comp [left-accessories accessories
|
||||
right-accessories accessories
|
||||
title [nil "This is a title" "This is a very long super title"]
|
||||
subtitle [nil "This is a subtitle"]
|
||||
title-align [:left :center]]
|
||||
{:left-accessories left-accessories
|
||||
:right-accessories right-accessories
|
||||
:title title
|
||||
:subtitle subtitle
|
||||
:title-align title-align}))
|
||||
(def all-props
|
||||
(preview/list-comp [left-accessories accessories
|
||||
right-accessories accessories
|
||||
title [nil "This is a title" "This is a very long super title"]
|
||||
subtitle [nil "This is a subtitle"]
|
||||
title-align [:left :center]]
|
||||
{:left-accessories left-accessories
|
||||
:right-accessories right-accessories
|
||||
:title title
|
||||
:subtitle subtitle
|
||||
:title-align title-align}))
|
||||
|
||||
(defn render-item [props]
|
||||
[rn/view {:border-bottom-color "#EEF2F5"
|
||||
:border-bottom-width 2}
|
||||
(defn render-item
|
||||
[props]
|
||||
[rn/view
|
||||
{:border-bottom-color "#EEF2F5"
|
||||
:border-bottom-width 2}
|
||||
[quo/header props]])
|
||||
|
||||
(defn preview-header []
|
||||
[rn/view {:background-color (:ui-background @colors/theme)
|
||||
:flex 1}
|
||||
[rn/flat-list {:flex 1
|
||||
:keyboardShouldPersistTaps :always
|
||||
:data all-props
|
||||
:render-fn render-item
|
||||
:key-fn str}]])
|
||||
(defn preview-header
|
||||
[]
|
||||
[rn/view
|
||||
{:background-color (:ui-background @colors/theme)
|
||||
:flex 1}
|
||||
[rn/flat-list
|
||||
{:flex 1
|
||||
:keyboardShouldPersistTaps :always
|
||||
:data all-props
|
||||
:render-fn render-item
|
||||
:key-fn str}]])
|
||||
|
@ -3,9 +3,11 @@
|
||||
[quo.react-native :as rn]
|
||||
[status-im.ui.components.icons.icons :as icons]))
|
||||
|
||||
(defn preview []
|
||||
[rn/scroll-view {:background-color (:ui-background @colors/theme)
|
||||
:flex 1}
|
||||
(defn preview
|
||||
[]
|
||||
[rn/scroll-view
|
||||
{:background-color (:ui-background @colors/theme)
|
||||
:flex 1}
|
||||
(for [i (keys icons/icons)]
|
||||
[rn/view {:flex-direction :row}
|
||||
[icons/icon (keyword i)]
|
||||
|
@ -1,87 +1,94 @@
|
||||
(ns quo.previews.lists
|
||||
(:require [reagent.core :as reagent]
|
||||
[quo.core :as quo]
|
||||
[quo.react-native :as rn]
|
||||
(:require [quo.core :as quo]
|
||||
[quo.design-system.colors :as colors]
|
||||
[quo.previews.preview :as preview]))
|
||||
[quo.previews.preview :as preview]
|
||||
[quo.react-native :as rn]
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
(def all-props (preview/list-comp [] {}))
|
||||
|
||||
(defn avatar []
|
||||
[rn/view {:border-radius 20
|
||||
:width 40
|
||||
:height 40
|
||||
:justify-content :center
|
||||
:align-items :center
|
||||
:background-color :red}
|
||||
[quo/text {:weight :bold
|
||||
:size :large}
|
||||
(defn avatar
|
||||
[]
|
||||
[rn/view
|
||||
{:border-radius 20
|
||||
:width 40
|
||||
:height 40
|
||||
:justify-content :center
|
||||
:align-items :center
|
||||
:background-color :red}
|
||||
[quo/text
|
||||
{:weight :bold
|
||||
:size :large}
|
||||
"T"]])
|
||||
|
||||
(defn icon-element [type]
|
||||
(defn icon-element
|
||||
[type]
|
||||
(case type
|
||||
:icon :main-icons/add-contact
|
||||
:component [avatar]
|
||||
nil))
|
||||
|
||||
(def descriptor [{:label "Accessory:"
|
||||
:key :accessory
|
||||
:type :select
|
||||
:options [{:key :radio
|
||||
:value "Radio"}
|
||||
{:key :checkbox
|
||||
:value "Checkbox"}
|
||||
{:key :switch
|
||||
:value "Switch"}
|
||||
{:key :text
|
||||
:value "Text"}
|
||||
{:key :default
|
||||
:value "Default"}]}
|
||||
{:label "Size:"
|
||||
:key :size
|
||||
:type :select
|
||||
:options [{:key :small
|
||||
:value "Small"}
|
||||
{:key :default
|
||||
:value "Default"}]}
|
||||
{:label "Icon:"
|
||||
:key :icon
|
||||
:type :select
|
||||
:options [{:key :icon
|
||||
:value "Icon"}
|
||||
{:key :component
|
||||
:value "Component"}]}
|
||||
{:label "Theme:"
|
||||
:key :theme
|
||||
:type :select
|
||||
:options [{:key :main
|
||||
:value "Main"}
|
||||
{:key :accent
|
||||
:value "Accent"}
|
||||
{:key :negative
|
||||
:value "Negative"}
|
||||
{:key :positive
|
||||
:value "Positive"}]}
|
||||
{:label "Selectable"
|
||||
:key :selectable
|
||||
:type :boolean}
|
||||
{:label "Chevron"
|
||||
:key :chevron
|
||||
:type :boolean}
|
||||
{:label "Disabled:"
|
||||
:key :disabled
|
||||
:type :boolean}
|
||||
{:label "Title"
|
||||
:key :title
|
||||
:type :text}
|
||||
{:label "Subtitle"
|
||||
:key :subtitle
|
||||
:type :text}])
|
||||
(def descriptor
|
||||
[{:label "Accessory:"
|
||||
:key :accessory
|
||||
:type :select
|
||||
:options [{:key :radio
|
||||
:value "Radio"}
|
||||
{:key :checkbox
|
||||
:value "Checkbox"}
|
||||
{:key :switch
|
||||
:value "Switch"}
|
||||
{:key :text
|
||||
:value "Text"}
|
||||
{:key :default
|
||||
:value "Default"}]}
|
||||
{:label "Size:"
|
||||
:key :size
|
||||
:type :select
|
||||
:options [{:key :small
|
||||
:value "Small"}
|
||||
{:key :default
|
||||
:value "Default"}]}
|
||||
{:label "Icon:"
|
||||
:key :icon
|
||||
:type :select
|
||||
:options [{:key :icon
|
||||
:value "Icon"}
|
||||
{:key :component
|
||||
:value "Component"}]}
|
||||
{:label "Theme:"
|
||||
:key :theme
|
||||
:type :select
|
||||
:options [{:key :main
|
||||
:value "Main"}
|
||||
{:key :accent
|
||||
:value "Accent"}
|
||||
{:key :negative
|
||||
:value "Negative"}
|
||||
{:key :positive
|
||||
:value "Positive"}]}
|
||||
{:label "Selectable"
|
||||
:key :selectable
|
||||
:type :boolean}
|
||||
{:label "Chevron"
|
||||
:key :chevron
|
||||
:type :boolean}
|
||||
{:label "Disabled:"
|
||||
:key :disabled
|
||||
:type :boolean}
|
||||
{:label "Title"
|
||||
:key :title
|
||||
:type :text}
|
||||
{:label "Subtitle"
|
||||
:key :subtitle
|
||||
:type :text}])
|
||||
|
||||
(defn render-item [_]
|
||||
[rn/view {:style {:padding-vertical 24}}])
|
||||
(defn render-item
|
||||
[_]
|
||||
[rn/view {:style {:padding-vertical 24}}])
|
||||
|
||||
(defn cool-preview []
|
||||
(defn cool-preview
|
||||
[]
|
||||
(let [state (reagent/atom {:title "Title"
|
||||
:active false})
|
||||
icon (reagent/cursor state [:icon])
|
||||
@ -92,19 +99,23 @@
|
||||
[rn/view {:padding-horizontal 16}
|
||||
[preview/customizer state descriptor]]
|
||||
[rn/view {:padding-vertical 16}
|
||||
[quo/list-item (merge (dissoc @state :active :selectable)
|
||||
(when @selectable
|
||||
{:active @active
|
||||
:on-press #(swap! active not)})
|
||||
{:accessory-text "Accessory"
|
||||
:icon (icon-element @icon)})]]])))
|
||||
[quo/list-item
|
||||
(merge (dissoc @state :active :selectable)
|
||||
(when @selectable
|
||||
{:active @active
|
||||
:on-press #(swap! active not)})
|
||||
{:accessory-text "Accessory"
|
||||
:icon (icon-element @icon)})]]])))
|
||||
|
||||
(defn preview []
|
||||
[rn/view {:background-color (:ui-background @colors/theme)
|
||||
:flex 1}
|
||||
[rn/flat-list {:flex 1
|
||||
:keyboardShouldPersistTaps :always
|
||||
:header [cool-preview]
|
||||
:data all-props
|
||||
:render-fn render-item
|
||||
:key-fn str}]])
|
||||
(defn preview
|
||||
[]
|
||||
[rn/view
|
||||
{:background-color (:ui-background @colors/theme)
|
||||
:flex 1}
|
||||
[rn/flat-list
|
||||
{:flex 1
|
||||
:keyboardShouldPersistTaps :always
|
||||
:header [cool-preview]
|
||||
:data all-props
|
||||
:render-fn render-item
|
||||
:key-fn str}]])
|
||||
|
@ -1,75 +1,83 @@
|
||||
(ns quo.previews.main
|
||||
(:require [quo.previews.header :as header]
|
||||
(:require [quo.core :as quo]
|
||||
[quo.design-system.colors :as colors]
|
||||
[quo.previews.bottom-sheet :as bottom-sheet]
|
||||
[quo.previews.button :as button]
|
||||
[quo.previews.controls :as controls]
|
||||
[quo.previews.header :as header]
|
||||
[quo.previews.icons :as icons]
|
||||
[quo.previews.lists :as lists]
|
||||
[quo.previews.text :as text]
|
||||
[quo.previews.text-input :as text-input]
|
||||
[quo.previews.tooltip :as tooltip]
|
||||
[quo.previews.button :as button]
|
||||
[quo.previews.lists :as lists]
|
||||
[quo.previews.bottom-sheet :as bottom-sheet]
|
||||
[quo.previews.controls :as controls]
|
||||
[quo.react-native :as rn]
|
||||
[quo.core :as quo]
|
||||
[quo.design-system.colors :as colors]
|
||||
[quo.theme :as theme]
|
||||
[quo.previews.icons :as icons]
|
||||
[re-frame.core :as re-frame]))
|
||||
|
||||
(def screens [{:name :texts
|
||||
:insets {:top false}
|
||||
:component text/preview-text}
|
||||
{:name :tooltip
|
||||
:insets {:top false}
|
||||
:component tooltip/preview-tooltip}
|
||||
{:name :text-input
|
||||
:insets {:top false}
|
||||
:component text-input/preview-text}
|
||||
{:name :headers
|
||||
:insets {:top false}
|
||||
:component header/preview-header}
|
||||
{:name :button
|
||||
:insets {:top false}
|
||||
:component button/preview-button}
|
||||
{:name :lists
|
||||
:instes {:top false}
|
||||
:component lists/preview}
|
||||
{:name :bottom-sheet
|
||||
:insets {:top false}
|
||||
:component bottom-sheet/preview}
|
||||
{:name :controls
|
||||
:insets {:top false}
|
||||
:component controls/preview}
|
||||
{:name :icons
|
||||
:insets {:top false}
|
||||
:component icons/preview}])
|
||||
(def screens
|
||||
[{:name :texts
|
||||
:insets {:top false}
|
||||
:component text/preview-text}
|
||||
{:name :tooltip
|
||||
:insets {:top false}
|
||||
:component tooltip/preview-tooltip}
|
||||
{:name :text-input
|
||||
:insets {:top false}
|
||||
:component text-input/preview-text}
|
||||
{:name :headers
|
||||
:insets {:top false}
|
||||
:component header/preview-header}
|
||||
{:name :button
|
||||
:insets {:top false}
|
||||
:component button/preview-button}
|
||||
{:name :lists
|
||||
:instes {:top false}
|
||||
:component lists/preview}
|
||||
{:name :bottom-sheet
|
||||
:insets {:top false}
|
||||
:component bottom-sheet/preview}
|
||||
{:name :controls
|
||||
:insets {:top false}
|
||||
:component controls/preview}
|
||||
{:name :icons
|
||||
:insets {:top false}
|
||||
:component icons/preview}])
|
||||
|
||||
(defn theme-switcher []
|
||||
[rn/view {:style {:flex-direction :row
|
||||
:margin-vertical 8
|
||||
:border-radius 4
|
||||
:background-color (:ui-01 @colors/theme)
|
||||
:border-width 1
|
||||
:border-color (:ui-02 @colors/theme)}}
|
||||
[rn/touchable-opacity {:style {:padding 8
|
||||
:flex 1
|
||||
:justify-content :center
|
||||
:align-items :center}
|
||||
:on-press #(theme/set-theme :light)}
|
||||
(defn theme-switcher
|
||||
[]
|
||||
[rn/view
|
||||
{:style {:flex-direction :row
|
||||
:margin-vertical 8
|
||||
:border-radius 4
|
||||
:background-color (:ui-01 @colors/theme)
|
||||
:border-width 1
|
||||
:border-color (:ui-02 @colors/theme)}}
|
||||
[rn/touchable-opacity
|
||||
{:style {:padding 8
|
||||
:flex 1
|
||||
:justify-content :center
|
||||
:align-items :center}
|
||||
:on-press #(theme/set-theme :light)}
|
||||
[quo/text "Set light theme"]]
|
||||
[rn/view {:width 1
|
||||
:margin-vertical 4
|
||||
:background-color (:ui-02 @colors/theme)}]
|
||||
[rn/touchable-opacity {:style {:padding 8
|
||||
:flex 1
|
||||
:justify-content :center
|
||||
:align-items :center}
|
||||
:on-press #(theme/set-theme :dark)}
|
||||
[rn/view
|
||||
{:width 1
|
||||
:margin-vertical 4
|
||||
:background-color (:ui-02 @colors/theme)}]
|
||||
[rn/touchable-opacity
|
||||
{:style {:padding 8
|
||||
:flex 1
|
||||
:justify-content :center
|
||||
:align-items :center}
|
||||
:on-press #(theme/set-theme :dark)}
|
||||
[quo/text "Set dark theme"]]])
|
||||
|
||||
(defn main-screen []
|
||||
[rn/scroll-view {:flex 1
|
||||
:padding-vertical 8
|
||||
:padding-horizontal 16
|
||||
:background-color (:ui-background @colors/theme)}
|
||||
(defn main-screen
|
||||
[]
|
||||
[rn/scroll-view
|
||||
{:flex 1
|
||||
:padding-vertical 8
|
||||
:padding-horizontal 16
|
||||
:background-color (:ui-background @colors/theme)}
|
||||
[theme-switcher]
|
||||
[rn/view
|
||||
(for [{:keys [name]} screens]
|
||||
@ -78,6 +86,7 @@
|
||||
[rn/view {:style {:padding-vertical 8}}
|
||||
[quo/text (str "Preview " name)]]])]])
|
||||
|
||||
(def main-screens [{:name :quo-preview
|
||||
:insets {:top false}
|
||||
:component main-screen}])
|
||||
(def main-screens
|
||||
[{:name :quo-preview
|
||||
:insets {:top false}
|
||||
:component main-screen}])
|
||||
|
@ -1,15 +1,17 @@
|
||||
(ns quo.previews.preview)
|
||||
|
||||
(defn descriptor->values [{:keys [key options type]}]
|
||||
(defn descriptor->values
|
||||
[{:keys [key options type]}]
|
||||
{key (case type
|
||||
:boolean [false true]
|
||||
:text [nil "Just simple text"] ; NOTE(Ferossgp): add example with long text?
|
||||
:select (mapv :key options))})
|
||||
|
||||
(defmacro list-comp [[binding seq-expr & bindings] body-expr]
|
||||
(defmacro list-comp
|
||||
[[binding seq-expr & bindings] body-expr]
|
||||
(cond (not binding)
|
||||
`(list ~body-expr)
|
||||
|
||||
:else
|
||||
`(mapcat (fn [~binding] (list-comp ~bindings ~body-expr))
|
||||
~seq-expr)))
|
||||
~seq-expr)))
|
||||
|
@ -1,23 +1,26 @@
|
||||
(ns quo.previews.preview
|
||||
(:require [reagent.core :as reagent]
|
||||
(:require [quo.core :as quo]
|
||||
[quo.design-system.colors :as colors]
|
||||
[quo.react-native :as rn]
|
||||
[quo.core :as quo]
|
||||
[quo.design-system.colors :as colors])
|
||||
[reagent.core :as reagent])
|
||||
(:require-macros quo.previews.preview))
|
||||
|
||||
(def container {:flex-direction :row
|
||||
:padding-vertical 8
|
||||
:flex 1
|
||||
:align-items :center})
|
||||
(def container
|
||||
{:flex-direction :row
|
||||
:padding-vertical 8
|
||||
:flex 1
|
||||
:align-items :center})
|
||||
|
||||
(defn touchable-style []
|
||||
(defn touchable-style
|
||||
[]
|
||||
{:flex 1
|
||||
:align-items :center
|
||||
:justify-content :center
|
||||
:padding-horizontal 16
|
||||
:height 44})
|
||||
|
||||
(defn select-style []
|
||||
(defn select-style
|
||||
[]
|
||||
{:flex 1
|
||||
:flex-direction :row
|
||||
:align-items :center
|
||||
@ -28,7 +31,8 @@
|
||||
:border-width 1
|
||||
:border-color (:ui-02 @colors/theme)})
|
||||
|
||||
(defn select-option-style [selected]
|
||||
(defn select-option-style
|
||||
[selected]
|
||||
(merge (select-style)
|
||||
{:margin-vertical 8
|
||||
:justify-content :center}
|
||||
@ -36,23 +40,27 @@
|
||||
{:background-color (:interactive-02 @colors/theme)}
|
||||
{:background-color (:ui-01 @colors/theme)})))
|
||||
|
||||
(def label-style {:flex 0.4
|
||||
:padding-right 8})
|
||||
(def label-style
|
||||
{:flex 0.4
|
||||
:padding-right 8})
|
||||
|
||||
(defn label-view [state label]
|
||||
(defn label-view
|
||||
[state label]
|
||||
[rn/view {:style label-style}
|
||||
[quo/text
|
||||
(when-let [label-color (:preview-label-color @state)]
|
||||
{:style {:color label-color}})
|
||||
label]])
|
||||
|
||||
(defn modal-container []
|
||||
(defn modal-container
|
||||
[]
|
||||
{:flex 1
|
||||
:justify-content :center
|
||||
:padding-horizontal 24
|
||||
:background-color "rgba(0,0,0,0.4)"})
|
||||
|
||||
(defn modal-view []
|
||||
(defn modal-view
|
||||
[]
|
||||
{:padding-horizontal 16
|
||||
:padding-vertical 8
|
||||
:border-radius 8
|
||||
@ -64,21 +72,25 @@
|
||||
(let [state* (reagent/cursor state [key])]
|
||||
[rn/view {:style container}
|
||||
[label-view state label]
|
||||
[rn/view {:style {:flex-direction :row
|
||||
:flex 0.6
|
||||
:border-radius 4
|
||||
:background-color (:ui-01 @colors/theme)
|
||||
:border-width 1
|
||||
:border-color (:ui-02 @colors/theme)}}
|
||||
[rn/touchable-opacity {:style (touchable-style)
|
||||
:on-press #(reset! state* true)}
|
||||
[quo/text {:color (if @state* :link :secondary)}
|
||||
[rn/view
|
||||
{:style {:flex-direction :row
|
||||
:flex 0.6
|
||||
:border-radius 4
|
||||
:background-color (:ui-01 @colors/theme)
|
||||
:border-width 1
|
||||
:border-color (:ui-02 @colors/theme)}}
|
||||
[rn/touchable-opacity
|
||||
{:style (touchable-style)
|
||||
:on-press #(reset! state* true)}
|
||||
[quo/text {:color (if @state* :link :secondary)}
|
||||
"True"]]
|
||||
[rn/view {:width 1
|
||||
:margin-vertical 4
|
||||
:background-color (:ui-02 @colors/theme)}]
|
||||
[rn/touchable-opacity {:style (touchable-style)
|
||||
:on-press #(reset! state* false)}
|
||||
[rn/view
|
||||
{:width 1
|
||||
:margin-vertical 4
|
||||
:background-color (:ui-02 @colors/theme)}]
|
||||
[rn/touchable-opacity
|
||||
{:style (touchable-style)
|
||||
:on-press #(reset! state* false)}
|
||||
[quo/text {:color (if (not @state*) :link :secondary)}
|
||||
"False"]]]]))
|
||||
|
||||
@ -88,20 +100,22 @@
|
||||
[rn/view {:style container}
|
||||
[label-view state label]
|
||||
[rn/view {:style {:flex 0.6}}
|
||||
[quo/text-input {:value @state*
|
||||
:show-cancel false
|
||||
:style {:border-radius 4
|
||||
:border-width 1
|
||||
:border-color (:ui-02 @colors/theme)}
|
||||
:on-change-text #(do
|
||||
(reset! state* %)
|
||||
(reagent/flush))}]]]))
|
||||
[quo/text-input
|
||||
{:value @state*
|
||||
:show-cancel false
|
||||
:style {:border-radius 4
|
||||
:border-width 1
|
||||
:border-color (:ui-02 @colors/theme)}
|
||||
:on-change-text #(do
|
||||
(reset! state* %)
|
||||
(reagent/flush))}]]]))
|
||||
|
||||
(defn value-for-key
|
||||
[id v]
|
||||
(:value (first (filter #(= (:key %) id) v))))
|
||||
|
||||
(defn customizer-select []
|
||||
(defn customizer-select
|
||||
[]
|
||||
(let [open (reagent/atom nil)]
|
||||
(fn [{:keys [label key state options]}]
|
||||
(let [state* (reagent/cursor state [key])
|
||||
@ -109,54 +123,63 @@
|
||||
[rn/view {:style container}
|
||||
[label-view state label]
|
||||
[rn/view {:style {:flex 0.6}}
|
||||
[rn/modal {:visible @open
|
||||
:on-request-close #(reset! open false)
|
||||
:statusBarTranslucent true
|
||||
:transparent true
|
||||
:animation :slide}
|
||||
[rn/modal
|
||||
{:visible @open
|
||||
:on-request-close #(reset! open false)
|
||||
:statusBarTranslucent true
|
||||
:transparent true
|
||||
:animation :slide}
|
||||
[rn/view {:style (modal-container)}
|
||||
[rn/view {:style (modal-view)}
|
||||
[rn/scroll-view
|
||||
(doall
|
||||
(for [{:keys [key value]} options]
|
||||
^{:key key}
|
||||
[rn/touchable-opacity {:style (select-option-style (= @state* key))
|
||||
:on-press #(do
|
||||
(reset! open false)
|
||||
(reset! state* key))}
|
||||
[rn/touchable-opacity
|
||||
{:style (select-option-style (= @state* key))
|
||||
:on-press #(do
|
||||
(reset! open false)
|
||||
(reset! state* key))}
|
||||
[quo/text {:color (if (= @state* key) :link :secondary)}
|
||||
value]]))
|
||||
[rn/view {:flex-direction :row}
|
||||
[rn/touchable-opacity {:style (select-option-style false)
|
||||
:on-press #(do
|
||||
(reset! state* nil)
|
||||
(reset! open false))}
|
||||
[rn/touchable-opacity
|
||||
{:style (select-option-style false)
|
||||
:on-press #(do
|
||||
(reset! state* nil)
|
||||
(reset! open false))}
|
||||
[quo/text "Clear"]]
|
||||
[rn/view {:width 16}]
|
||||
[rn/touchable-opacity {:style (select-option-style false)
|
||||
:on-press #(reset! open false)}
|
||||
[rn/touchable-opacity
|
||||
{:style (select-option-style false)
|
||||
:on-press #(reset! open false)}
|
||||
[quo/text "Close"]]]]]]]
|
||||
|
||||
[rn/touchable-opacity {:style (select-style)
|
||||
:on-press #(reset! open true)}
|
||||
[rn/touchable-opacity
|
||||
{:style (select-style)
|
||||
:on-press #(reset! open true)}
|
||||
(if selected
|
||||
[quo/text {:color :link} selected]
|
||||
[quo/text "Select option"])
|
||||
[rn/view {:position :absolute
|
||||
:right 16
|
||||
:top 0
|
||||
:bottom 0
|
||||
:justify-content :center}
|
||||
[rn/view
|
||||
{:position :absolute
|
||||
:right 16
|
||||
:top 0
|
||||
:bottom 0
|
||||
:justify-content :center}
|
||||
[quo/text "↓"]]]]]))))
|
||||
|
||||
(defn customizer [state descriptors]
|
||||
[rn/view {:style {:flex 1}
|
||||
:padding-horizontal 16}
|
||||
(defn customizer
|
||||
[state descriptors]
|
||||
[rn/view
|
||||
{:style {:flex 1}
|
||||
:padding-horizontal 16}
|
||||
(doall
|
||||
(for [{:keys [key type]
|
||||
:as desc} descriptors
|
||||
:let [descriptor (merge desc
|
||||
{:state state})]]
|
||||
:as desc}
|
||||
descriptors
|
||||
:let [descriptor (merge desc
|
||||
{:state state})]]
|
||||
^{:key key}
|
||||
[:<>
|
||||
(case type
|
||||
|
@ -1,89 +1,99 @@
|
||||
(ns quo.previews.text
|
||||
(:require [reagent.core :as reagent]
|
||||
(:require [quo.animated :as animated]
|
||||
[quo.core :as quo]
|
||||
[quo.animated :as animated]
|
||||
[quo.react-native :as rn]
|
||||
[quo.design-system.colors :as colors]
|
||||
[quo.previews.preview :as preview]))
|
||||
[quo.previews.preview :as preview]
|
||||
[quo.react-native :as rn]
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
(def all-props (preview/list-comp [size [:tiny :small :base :large :x-large :xx-large]
|
||||
weight [:regular :medium :semi-bold :bold :monospace]]
|
||||
{:weight weight
|
||||
:size size}))
|
||||
(def all-props
|
||||
(preview/list-comp [size [:tiny :small :base :large :x-large :xx-large]
|
||||
weight [:regular :medium :semi-bold :bold :monospace]]
|
||||
{:weight weight
|
||||
:size size}))
|
||||
|
||||
(def descriptor [{:label "Size:"
|
||||
:key :size
|
||||
:type :select
|
||||
:options [{:key :tiny
|
||||
:value "Tiny"}
|
||||
{:key :small
|
||||
:value "Small"}
|
||||
{:key :base
|
||||
:value "Base"}
|
||||
{:key :large
|
||||
:value "Large"}
|
||||
{:key :x-large
|
||||
:value "X-Large"}
|
||||
{:key :xx-large
|
||||
:value "XX-Large"}]}
|
||||
{:label "Weight:"
|
||||
:key :weight
|
||||
:type :select
|
||||
:options [{:key :regular
|
||||
:value "Regular"}
|
||||
{:key :medium
|
||||
:value "Medium"}
|
||||
{:key :semi-bold
|
||||
:value "Semi-bold"}
|
||||
{:key :bold
|
||||
:value "Bold"}
|
||||
{:key :monospace
|
||||
:value "Monospace"}]}
|
||||
{:label "Color:"
|
||||
:key :color
|
||||
:type :select
|
||||
:options [{:key :main
|
||||
:value "main"}
|
||||
{:key :secondary
|
||||
:value "secondary"}
|
||||
{:key :secondary-inverse
|
||||
:value "secondary-inverse"}
|
||||
{:key :link
|
||||
:value "link"}
|
||||
{:key :negative
|
||||
:value "negative"}
|
||||
{:key :positive
|
||||
:value "positive"}]}
|
||||
{:label "Animated:"
|
||||
:key :animated?
|
||||
:type :boolean}])
|
||||
(def descriptor
|
||||
[{:label "Size:"
|
||||
:key :size
|
||||
:type :select
|
||||
:options [{:key :tiny
|
||||
:value "Tiny"}
|
||||
{:key :small
|
||||
:value "Small"}
|
||||
{:key :base
|
||||
:value "Base"}
|
||||
{:key :large
|
||||
:value "Large"}
|
||||
{:key :x-large
|
||||
:value "X-Large"}
|
||||
{:key :xx-large
|
||||
:value "XX-Large"}]}
|
||||
{:label "Weight:"
|
||||
:key :weight
|
||||
:type :select
|
||||
:options [{:key :regular
|
||||
:value "Regular"}
|
||||
{:key :medium
|
||||
:value "Medium"}
|
||||
{:key :semi-bold
|
||||
:value "Semi-bold"}
|
||||
{:key :bold
|
||||
:value "Bold"}
|
||||
{:key :monospace
|
||||
:value "Monospace"}]}
|
||||
{:label "Color:"
|
||||
:key :color
|
||||
:type :select
|
||||
:options [{:key :main
|
||||
:value "main"}
|
||||
{:key :secondary
|
||||
:value "secondary"}
|
||||
{:key :secondary-inverse
|
||||
:value "secondary-inverse"}
|
||||
{:key :link
|
||||
:value "link"}
|
||||
{:key :negative
|
||||
:value "negative"}
|
||||
{:key :positive
|
||||
:value "positive"}]}
|
||||
{:label "Animated:"
|
||||
:key :animated?
|
||||
:type :boolean}])
|
||||
|
||||
(defn render-item [props]
|
||||
[rn/view {:style {:padding-vertical 24
|
||||
:padding-horizontal 16}}
|
||||
(defn render-item
|
||||
[props]
|
||||
[rn/view
|
||||
{:style {:padding-vertical 24
|
||||
:padding-horizontal 16}}
|
||||
[quo/text props
|
||||
(str "Text size " props " number 0 1x2")]])
|
||||
|
||||
(defn cool-preview []
|
||||
(defn cool-preview
|
||||
[]
|
||||
(let [state (reagent/atom {})
|
||||
animation (animated/value 0)]
|
||||
animation (animated/value 0)]
|
||||
(fn []
|
||||
[rn/view {:margin-bottom 50
|
||||
:padding 16}
|
||||
[rn/view
|
||||
{:margin-bottom 50
|
||||
:padding 16}
|
||||
[animated/code {:exec (animated/set animation (animated/loop* {:duration 1000}))}]
|
||||
[preview/customizer state descriptor]
|
||||
[rn/view {:padding-vertical 16}
|
||||
[quo/text (merge @state
|
||||
(when (:animated? @state)
|
||||
{:opacity animation}))
|
||||
[quo/text
|
||||
(merge @state
|
||||
(when (:animated? @state)
|
||||
{:opacity animation}))
|
||||
"This is a demo text 1 2 0 2x2 0x0"]]])))
|
||||
|
||||
(defn preview-text []
|
||||
[rn/view {:background-color (:ui-background @colors/theme)
|
||||
:flex 1}
|
||||
[rn/flat-list {:flex 1
|
||||
:keyboardShouldPersistTaps :always
|
||||
:header [cool-preview]
|
||||
:data all-props
|
||||
:render-fn render-item
|
||||
:key-fn str}]])
|
||||
(defn preview-text
|
||||
[]
|
||||
[rn/view
|
||||
{:background-color (:ui-background @colors/theme)
|
||||
:flex 1}
|
||||
[rn/flat-list
|
||||
{:flex 1
|
||||
:keyboardShouldPersistTaps :always
|
||||
:header [cool-preview]
|
||||
:data all-props
|
||||
:render-fn render-item
|
||||
:key-fn str}]])
|
||||
|
@ -1,57 +1,62 @@
|
||||
(ns quo.previews.text-input
|
||||
(:require [reagent.core :as reagent]
|
||||
[quo.core :as quo]
|
||||
[quo.react-native :as rn]
|
||||
(:require [quo.core :as quo]
|
||||
[quo.design-system.colors :as colors]
|
||||
[quo.previews.preview :as preview]))
|
||||
[quo.previews.preview :as preview]
|
||||
[quo.react-native :as rn]
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
(def all-props (preview/list-comp [multiline [false true]
|
||||
label [nil "Input label"]
|
||||
default-value [nil "Test initial value"]
|
||||
placeholder [nil "Placeholder value"]
|
||||
before [nil {:icon :main-icons/search}]
|
||||
after [nil {:icon :main-icons/close}]
|
||||
error [nil "Something went wrong!"]
|
||||
secure [false true]
|
||||
show-cancel [false true]]
|
||||
{:label label
|
||||
:default-value default-value
|
||||
:placeholder placeholder
|
||||
:multiline multiline
|
||||
:before before
|
||||
:after after
|
||||
:error error
|
||||
:show-cancel show-cancel
|
||||
:secure-text-entry secure}))
|
||||
(def all-props
|
||||
(preview/list-comp [multiline [false true]
|
||||
label [nil "Input label"]
|
||||
default-value [nil "Test initial value"]
|
||||
placeholder [nil "Placeholder value"]
|
||||
before [nil {:icon :main-icons/search}]
|
||||
after [nil {:icon :main-icons/close}]
|
||||
error [nil "Something went wrong!"]
|
||||
secure [false true]
|
||||
show-cancel [false true]]
|
||||
{:label label
|
||||
:default-value default-value
|
||||
:placeholder placeholder
|
||||
:multiline multiline
|
||||
:before before
|
||||
:after after
|
||||
:error error
|
||||
:show-cancel show-cancel
|
||||
:secure-text-entry secure}))
|
||||
|
||||
(def descriptor [{:label "Multiline:"
|
||||
:key :multiline
|
||||
:type :boolean}
|
||||
{:label "Show cancel:"
|
||||
:key :show-cancel
|
||||
:type :boolean}
|
||||
{:label "Secure:"
|
||||
:key :secure-text-entry
|
||||
:type :boolean}
|
||||
{:label "After icon:"
|
||||
:key :after
|
||||
:type :boolean}
|
||||
{:label "Before icon:"
|
||||
:key :before
|
||||
:type :boolean}
|
||||
{:label "Show error:"
|
||||
:key :error
|
||||
:type :boolean}
|
||||
{:label "Label"
|
||||
:key :label
|
||||
:type :text}])
|
||||
(def descriptor
|
||||
[{:label "Multiline:"
|
||||
:key :multiline
|
||||
:type :boolean}
|
||||
{:label "Show cancel:"
|
||||
:key :show-cancel
|
||||
:type :boolean}
|
||||
{:label "Secure:"
|
||||
:key :secure-text-entry
|
||||
:type :boolean}
|
||||
{:label "After icon:"
|
||||
:key :after
|
||||
:type :boolean}
|
||||
{:label "Before icon:"
|
||||
:key :before
|
||||
:type :boolean}
|
||||
{:label "Show error:"
|
||||
:key :error
|
||||
:type :boolean}
|
||||
{:label "Label"
|
||||
:key :label
|
||||
:type :text}])
|
||||
|
||||
(defn render-item [props]
|
||||
[rn/view {:style {:padding-horizontal 16
|
||||
:padding-vertical 24}}
|
||||
(defn render-item
|
||||
[props]
|
||||
[rn/view
|
||||
{:style {:padding-horizontal 16
|
||||
:padding-vertical 24}}
|
||||
[quo/text-input props]])
|
||||
|
||||
(defn cool-preview []
|
||||
(defn cool-preview
|
||||
[]
|
||||
(let [state (reagent/atom {:secure false
|
||||
:show-cancel false
|
||||
:multiline false
|
||||
@ -60,22 +65,27 @@
|
||||
after (reagent/cursor state [:after])
|
||||
error (reagent/cursor state [:error])]
|
||||
(fn []
|
||||
[rn/view {:margin-bottom 50
|
||||
:padding 16}
|
||||
[rn/view
|
||||
{:margin-bottom 50
|
||||
:padding 16}
|
||||
[preview/customizer state descriptor]
|
||||
[quo/text-input (merge @state
|
||||
{:default-value nil
|
||||
:placeholder "I'm a cool placeholder"
|
||||
:before (when @before {:icon :main-icons/search})
|
||||
:after (when @after {:icon :main-icons/close})
|
||||
:error (when @error "Something went wrong!")})]])))
|
||||
[quo/text-input
|
||||
(merge @state
|
||||
{:default-value nil
|
||||
:placeholder "I'm a cool placeholder"
|
||||
:before (when @before {:icon :main-icons/search})
|
||||
:after (when @after {:icon :main-icons/close})
|
||||
:error (when @error "Something went wrong!")})]])))
|
||||
|
||||
(defn preview-text []
|
||||
[rn/view {:background-color (:ui-background @colors/theme)
|
||||
:flex 1}
|
||||
[rn/flat-list {:flex 1
|
||||
:keyboardShouldPersistTaps :always
|
||||
:header [cool-preview]
|
||||
:data all-props
|
||||
:render-fn render-item
|
||||
:key-fn str}]])
|
||||
(defn preview-text
|
||||
[]
|
||||
[rn/view
|
||||
{:background-color (:ui-background @colors/theme)
|
||||
:flex 1}
|
||||
[rn/flat-list
|
||||
{:flex 1
|
||||
:keyboardShouldPersistTaps :always
|
||||
:header [cool-preview]
|
||||
:data all-props
|
||||
:render-fn render-item
|
||||
:key-fn str}]])
|
||||
|
@ -1,30 +1,38 @@
|
||||
(ns quo.previews.tooltip
|
||||
(:require [quo.core :as quo]
|
||||
[quo.react-native :as rn]
|
||||
[quo.design-system.colors :as colors])
|
||||
[quo.design-system.colors :as colors]
|
||||
[quo.react-native :as rn])
|
||||
(:require-macros [quo.previews.preview :as preview]))
|
||||
|
||||
(def all-props (preview/list-comp
|
||||
[child [[quo/text {:size :small} "Simple text"]
|
||||
[quo/text {:color :negative
|
||||
:size :small}
|
||||
"Error text"]
|
||||
[rn/view {:width 100 :height 20 :background-color :red}]
|
||||
[quo/text "Just text, but long. Officia autem est repellendus ad quia exercitationem veniam."]]]
|
||||
child))
|
||||
(def all-props
|
||||
(preview/list-comp
|
||||
[child [[quo/text {:size :small} "Simple text"]
|
||||
[quo/text
|
||||
{:color :negative
|
||||
:size :small}
|
||||
"Error text"]
|
||||
[rn/view {:width 100 :height 20 :background-color :red}]
|
||||
[quo/text
|
||||
"Just text, but long. Officia autem est repellendus ad quia exercitationem veniam."]]]
|
||||
child))
|
||||
|
||||
(defn render-item [children]
|
||||
(defn render-item
|
||||
[children]
|
||||
[rn/view {:margin-vertical 50}
|
||||
[rn/view {:height 20
|
||||
:background-color "rgba(0,0,0,0.1)"}]
|
||||
[rn/view
|
||||
{:height 20
|
||||
:background-color "rgba(0,0,0,0.1)"}]
|
||||
[quo/tooltip {}
|
||||
children]])
|
||||
|
||||
(defn preview-tooltip []
|
||||
[rn/view {:background-color (:ui-background @colors/theme)
|
||||
:flex 1}
|
||||
[rn/flat-list {:flex 1
|
||||
:keyboardShouldPersistTaps :always
|
||||
:data all-props
|
||||
:render-fn render-item
|
||||
:key-fn str}]])
|
||||
(defn preview-tooltip
|
||||
[]
|
||||
[rn/view
|
||||
{:background-color (:ui-background @colors/theme)
|
||||
:flex 1}
|
||||
[rn/flat-list
|
||||
{:flex 1
|
||||
:keyboardShouldPersistTaps :always
|
||||
:data all-props
|
||||
:render-fn render-item
|
||||
:key-fn str}]])
|
||||
|
@ -1,9 +1,11 @@
|
||||
(ns quo.react)
|
||||
|
||||
(defmacro maybe-js-deps [deps]
|
||||
(defmacro maybe-js-deps
|
||||
[deps]
|
||||
`(if ~deps (into-array ~deps) js/undefined))
|
||||
|
||||
(defmacro with-deps-check [[prev-deps] f deps]
|
||||
(defmacro with-deps-check
|
||||
[[prev-deps] f deps]
|
||||
`(let [~prev-deps (quo.react/ref ~deps)]
|
||||
(when (not= @~prev-deps ~deps)
|
||||
(reset! ~prev-deps ~deps))
|
||||
|
@ -2,12 +2,12 @@
|
||||
(:refer-clojure :exclude [ref])
|
||||
(:require ["react" :as react]
|
||||
[oops.core :refer [oget oset!]])
|
||||
(:require-macros [quo.react :refer [with-deps-check
|
||||
maybe-js-deps]]))
|
||||
(:require-macros [quo.react :refer [with-deps-check maybe-js-deps]]))
|
||||
|
||||
(def create-ref react/createRef)
|
||||
|
||||
(defn current-ref [ref]
|
||||
(defn current-ref
|
||||
[ref]
|
||||
(oget ref "current"))
|
||||
|
||||
;; Inspired from UIX, Rum and Rumext
|
||||
@ -16,33 +16,35 @@
|
||||
(oset! ref "current" val)
|
||||
val)
|
||||
|
||||
(defn set-native-props [^js ref ^js props]
|
||||
(defn set-native-props
|
||||
[^js ref ^js props]
|
||||
(when-let [curr-ref ^js (current-ref ref)]
|
||||
(.setNativeProps curr-ref props)))
|
||||
|
||||
(deftype StateHook [value set-value]
|
||||
cljs.core/IHash
|
||||
(-hash [o] (goog/getUid o))
|
||||
(-hash [o] (goog/getUid o))
|
||||
|
||||
cljs.core/IDeref
|
||||
(-deref [_o]
|
||||
value)
|
||||
(-deref [_o]
|
||||
value)
|
||||
|
||||
cljs.core/IReset
|
||||
(-reset! [_o new-value]
|
||||
(set-value new-value))
|
||||
(-reset! [_o new-value]
|
||||
(set-value new-value))
|
||||
|
||||
cljs.core/ISwap
|
||||
(-swap! [_o f]
|
||||
(set-value f))
|
||||
(-swap! [_o f a]
|
||||
(set-value #(f % a)))
|
||||
(-swap! [_o f a b]
|
||||
(set-value #(f % a b)))
|
||||
(-swap! [_o f a b xs]
|
||||
(set-value #(apply f % a b xs))))
|
||||
(-swap! [_o f]
|
||||
(set-value f))
|
||||
(-swap! [_o f a]
|
||||
(set-value #(f % a)))
|
||||
(-swap! [_o f a b]
|
||||
(set-value #(f % a b)))
|
||||
(-swap! [_o f a b xs]
|
||||
(set-value #(apply f % a b xs))))
|
||||
|
||||
(defn state [value]
|
||||
(defn state
|
||||
[value]
|
||||
(let [[value set-value] (react/useState value)
|
||||
sh (react/useMemo #(StateHook. value set-value) #js [])]
|
||||
(react/useMemo (fn []
|
||||
@ -51,31 +53,33 @@
|
||||
sh)
|
||||
#js [value set-value])))
|
||||
|
||||
(defn use-ref [val]
|
||||
(defn use-ref
|
||||
[val]
|
||||
(let [ref (react/useRef val)]
|
||||
(reify
|
||||
cljs.core/IHash
|
||||
(-hash [_] (goog/getUid ref))
|
||||
cljs.core/IHash
|
||||
(-hash [_] (goog/getUid ref))
|
||||
|
||||
cljs.core/IDeref
|
||||
(-deref [_]
|
||||
(current-ref ref))
|
||||
cljs.core/IDeref
|
||||
(-deref [_]
|
||||
(current-ref ref))
|
||||
|
||||
cljs.core/IReset
|
||||
(-reset! [_ new-value]
|
||||
(set-ref-val! ref new-value))
|
||||
cljs.core/IReset
|
||||
(-reset! [_ new-value]
|
||||
(set-ref-val! ref new-value))
|
||||
|
||||
cljs.core/ISwap
|
||||
(-swap! [_ f]
|
||||
(-reset! ref (f (current-ref ref))))
|
||||
(-swap! [_ f a]
|
||||
(-reset! ref (f (current-ref ref) a)))
|
||||
(-swap! [_ f a b]
|
||||
(-reset! ref (f (current-ref ref) a b)))
|
||||
(-swap! [_ f a b xs]
|
||||
(-reset! ref (apply f (current-ref ref) a b xs))))))
|
||||
cljs.core/ISwap
|
||||
(-swap! [_ f]
|
||||
(-reset! ref (f (current-ref ref))))
|
||||
(-swap! [_ f a]
|
||||
(-reset! ref (f (current-ref ref) a)))
|
||||
(-swap! [_ f a b]
|
||||
(-reset! ref (f (current-ref ref) a b)))
|
||||
(-swap! [_ f a b xs]
|
||||
(-reset! ref (apply f (current-ref ref) a b xs))))))
|
||||
|
||||
(defn ref [value]
|
||||
(defn ref
|
||||
[value]
|
||||
(let [vref (use-ref value)]
|
||||
(react/useMemo (fn [] vref) #js [])))
|
||||
|
||||
@ -125,7 +129,8 @@
|
||||
|
||||
(def memo react/memo)
|
||||
|
||||
(defn get-children [^js children]
|
||||
(defn get-children
|
||||
[^js children]
|
||||
(->> children
|
||||
(react/Children.toArray)
|
||||
(into [])))
|
||||
|
@ -1,13 +1,13 @@
|
||||
(ns quo.react-native
|
||||
(:require [reagent.core :as reagent]
|
||||
(:require ["@react-native-community/hooks" :as hooks]
|
||||
["react-native" :as rn]
|
||||
["react-native-draggable-flatlist" :default DraggableFlatList]
|
||||
["react-native-hole-view" :refer (RNHoleView)]
|
||||
["react-native-navigation" :refer (Navigation)]
|
||||
["rn-emoji-keyboard" :refer (EmojiKeyboard)]
|
||||
[cljs-bean.core :as bean]
|
||||
[quo.platform :as platform]
|
||||
["react-native" :as rn]
|
||||
["@react-native-community/hooks" :as hooks]
|
||||
["react-native-navigation" :refer (Navigation)]
|
||||
["react-native-hole-view" :refer (RNHoleView)]
|
||||
["rn-emoji-keyboard" :refer (EmojiKeyboard)]
|
||||
["react-native-draggable-flatlist" :default DraggableFlatList]))
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
(def hole-view (reagent/adapt-react-class RNHoleView))
|
||||
|
||||
@ -25,7 +25,9 @@
|
||||
(def image (reagent/adapt-react-class (.-Image rn)))
|
||||
(def text (reagent/adapt-react-class (.-Text ^js rn)))
|
||||
|
||||
(defn resolve-asset-source [uri] (js->clj (.resolveAssetSource ^js (.-Image ^js rn) uri) :keywordize-keys true))
|
||||
(defn resolve-asset-source
|
||||
[uri]
|
||||
(js->clj (.resolveAssetSource ^js (.-Image ^js rn) uri) :keywordize-keys true))
|
||||
|
||||
(def scroll-view (reagent/adapt-react-class (.-ScrollView ^js rn)))
|
||||
(def modal (reagent/adapt-react-class (.-Modal ^js rn)))
|
||||
@ -42,11 +44,12 @@
|
||||
|
||||
(.then (.constants Navigation)
|
||||
(fn [^js consts]
|
||||
(reset! navigation-const {:top-bar-height (.-topBarHeight consts)
|
||||
(reset! navigation-const {:top-bar-height (.-topBarHeight consts)
|
||||
:bottom-tabs-height (.-bottomTabsHeight consts)
|
||||
:status-bar-height (.-statusBarHeight consts)})))
|
||||
:status-bar-height (.-statusBarHeight consts)})))
|
||||
|
||||
(defn keyboard-avoiding-view []
|
||||
(defn keyboard-avoiding-view
|
||||
[]
|
||||
(let [this (reagent/current-component)
|
||||
props (reagent/props this)]
|
||||
(into [keyboard-avoiding-view-class
|
||||
@ -66,7 +69,8 @@
|
||||
|
||||
(def pan-responder (.-PanResponder ^js rn))
|
||||
|
||||
(defn create-pan-responder [opts]
|
||||
(defn create-pan-responder
|
||||
[opts]
|
||||
(.create ^js pan-responder (clj->js opts)))
|
||||
|
||||
(def animated (.-Animated rn))
|
||||
@ -79,82 +83,99 @@
|
||||
(def animated-view
|
||||
(reagent/adapt-react-class (.-View ^js animated)))
|
||||
|
||||
(def ui-manager (.-UIManager ^js rn))
|
||||
(def ui-manager (.-UIManager ^js rn))
|
||||
|
||||
(def layout-animation (.-LayoutAnimation ^js rn))
|
||||
(def configure-next (.-configureNext ^js layout-animation))
|
||||
(def create-animation (.-create ^js layout-animation))
|
||||
|
||||
(def layout-animation-presets {:ease-in-ease-out (-> ^js layout-animation .-Presets .-easeInEaseOut)
|
||||
:linear (-> ^js layout-animation .-Presets .-linear)
|
||||
:spring (-> ^js layout-animation .-Presets .-spring)})
|
||||
(def layout-animation-presets
|
||||
{:ease-in-ease-out (-> ^js layout-animation .-Presets .-easeInEaseOut)
|
||||
:linear (-> ^js layout-animation .-Presets .-linear)
|
||||
:spring (-> ^js layout-animation .-Presets .-spring)})
|
||||
|
||||
(def layout-animation-types {:spring (-> ^js layout-animation .-Types .-spring)
|
||||
:linear (-> ^js layout-animation .-Types .-linear)
|
||||
:ease-in-ease-out (-> ^js layout-animation .-Types .-easeInEaseOut)
|
||||
:ease-in (-> ^js layout-animation .-Types .-easeIn)
|
||||
:ease-out (-> ^js layout-animation .-Types .-easeOut)})
|
||||
(def layout-animation-types
|
||||
{:spring (-> ^js layout-animation .-Types .-spring)
|
||||
:linear (-> ^js layout-animation .-Types .-linear)
|
||||
:ease-in-ease-out (-> ^js layout-animation .-Types .-easeInEaseOut)
|
||||
:ease-in (-> ^js layout-animation .-Types .-easeIn)
|
||||
:ease-out (-> ^js layout-animation .-Types .-easeOut)})
|
||||
|
||||
(def layout-animation-properties {:opacity (-> ^js layout-animation .-Properties .-opacity)
|
||||
:scale-x (-> ^js layout-animation .-Properties .-scaleX)
|
||||
:scale-y (-> ^js layout-animation .-Properties .-scaleY)
|
||||
:scale-xy (-> ^js layout-animation .-Properties .-scaleXY)})
|
||||
(def layout-animation-properties
|
||||
{:opacity (-> ^js layout-animation .-Properties .-opacity)
|
||||
:scale-x (-> ^js layout-animation .-Properties .-scaleX)
|
||||
:scale-y (-> ^js layout-animation .-Properties .-scaleY)
|
||||
:scale-xy (-> ^js layout-animation .-Properties .-scaleXY)})
|
||||
|
||||
(def custom-animations {:ease-opacity-200 #js {:duration 200
|
||||
:create #js {:type (:ease-in-ease-out layout-animation-types)
|
||||
:property (:opacity layout-animation-properties)}
|
||||
:update #js {:type (:ease-in-ease-out layout-animation-types)
|
||||
:property (:opacity layout-animation-properties)}
|
||||
:delete #js {:type (:ease-in-ease-out layout-animation-types)
|
||||
:property (:opacity layout-animation-properties)}}})
|
||||
(def custom-animations
|
||||
{:ease-opacity-200 #js
|
||||
{:duration 200
|
||||
:create #js
|
||||
{:type (:ease-in-ease-out layout-animation-types)
|
||||
:property (:opacity layout-animation-properties)}
|
||||
:update #js
|
||||
{:type (:ease-in-ease-out layout-animation-types)
|
||||
:property (:opacity layout-animation-properties)}
|
||||
:delete #js
|
||||
{:type (:ease-in-ease-out layout-animation-types)
|
||||
:property (:opacity layout-animation-properties)}}})
|
||||
|
||||
(defonce enable-layout-animations
|
||||
(when platform/android?
|
||||
(.setLayoutAnimationEnabledExperimental ^js ui-manager true)))
|
||||
(when platform/android?
|
||||
(.setLayoutAnimationEnabledExperimental ^js ui-manager true)))
|
||||
|
||||
(def activity-indicator (reagent/adapt-react-class (.-ActivityIndicator ^js rn)))
|
||||
|
||||
;; Flat-list
|
||||
(def ^:private rn-flat-list (reagent/adapt-react-class (.-FlatList ^js rn)))
|
||||
|
||||
(defn- wrap-render-fn [f render-data]
|
||||
(defn- wrap-render-fn
|
||||
[f render-data]
|
||||
(fn [data]
|
||||
(reagent/as-element [f (.-item ^js data) (.-index ^js data)
|
||||
(.-separators ^js data) render-data
|
||||
(.-isActive ^js data) (.-drag ^js data)])))
|
||||
|
||||
(defn- wrap-on-drag-end-fn [f]
|
||||
(defn- wrap-on-drag-end-fn
|
||||
[f]
|
||||
(fn [data]
|
||||
(f (.-from ^js data) (.-to ^js data) (.-data ^js data))))
|
||||
|
||||
(defn- wrap-key-fn [f]
|
||||
(defn- wrap-key-fn
|
||||
[f]
|
||||
(fn [data index]
|
||||
{:post [(some? %)]}
|
||||
(f data index)))
|
||||
|
||||
(defn base-list-props
|
||||
[{:keys [key-fn render-fn empty-component header footer separator data render-data on-drag-end-fn] :as props}]
|
||||
(merge {:data (to-array data)}
|
||||
(when key-fn {:keyExtractor (wrap-key-fn key-fn)})
|
||||
(when render-fn {:renderItem (wrap-render-fn render-fn render-data)})
|
||||
(when separator {:ItemSeparatorComponent (fn [] (reagent/as-element separator))})
|
||||
(when empty-component {:ListEmptyComponent (fn [] (reagent/as-element empty-component))})
|
||||
(when header {:ListHeaderComponent (reagent/as-element header)})
|
||||
(when footer {:ListFooterComponent (reagent/as-element footer)})
|
||||
(when on-drag-end-fn {:onDragEnd (wrap-on-drag-end-fn on-drag-end-fn)})
|
||||
(dissoc props :data :header :footer :empty-component :separator :render-fn :key-fn :on-drag-end-fn)))
|
||||
[{:keys [key-fn render-fn empty-component header footer separator data render-data on-drag-end-fn]
|
||||
:as props}]
|
||||
(merge
|
||||
{:data (to-array data)}
|
||||
(when key-fn {:keyExtractor (wrap-key-fn key-fn)})
|
||||
(when render-fn {:renderItem (wrap-render-fn render-fn render-data)})
|
||||
(when separator {:ItemSeparatorComponent (fn [] (reagent/as-element separator))})
|
||||
(when empty-component {:ListEmptyComponent (fn [] (reagent/as-element empty-component))})
|
||||
(when header {:ListHeaderComponent (reagent/as-element header)})
|
||||
(when footer {:ListFooterComponent (reagent/as-element footer)})
|
||||
(when on-drag-end-fn {:onDragEnd (wrap-on-drag-end-fn on-drag-end-fn)})
|
||||
(dissoc props :data :header :footer :empty-component :separator :render-fn :key-fn :on-drag-end-fn)))
|
||||
|
||||
(defn flat-list [props]
|
||||
(defn flat-list
|
||||
[props]
|
||||
[rn-flat-list (base-list-props props)])
|
||||
|
||||
(defn draggable-flat-list [props]
|
||||
(defn draggable-flat-list
|
||||
[props]
|
||||
[rn-draggable-flatlist (base-list-props props)])
|
||||
|
||||
(defn animated-flat-list [props]
|
||||
(defn animated-flat-list
|
||||
[props]
|
||||
[animated-flat-list-class (base-list-props props)])
|
||||
;; Hooks
|
||||
|
||||
(defn use-window-dimensions []
|
||||
(defn use-window-dimensions
|
||||
[]
|
||||
(let [window (rn/useWindowDimensions)]
|
||||
{:font-scale (.-fontScale window)
|
||||
:height (.-height ^js window)
|
||||
@ -163,12 +184,14 @@
|
||||
|
||||
(def use-back-handler (.-useBackHandler hooks))
|
||||
|
||||
(defn use-keyboard []
|
||||
(defn use-keyboard
|
||||
[]
|
||||
(let [kb (.useKeyboard hooks)]
|
||||
{:keyboard-shown (.-keyboardShown ^js kb)
|
||||
:keyboard-height (.-keyboardHeight ^js kb)}))
|
||||
|
||||
(defn use-layout []
|
||||
(defn use-layout
|
||||
[]
|
||||
(let [{:keys [onLayout x y height width]} (bean/bean (.useLayout hooks))]
|
||||
{:on-layout onLayout
|
||||
:x x
|
||||
|
@ -4,13 +4,16 @@
|
||||
|
||||
(def theme (reagent/atom nil))
|
||||
|
||||
(defn dark? []
|
||||
(defn dark?
|
||||
[]
|
||||
(= :dark @theme))
|
||||
|
||||
(defn get-theme []
|
||||
(defn get-theme
|
||||
[]
|
||||
@theme)
|
||||
|
||||
(defn set-theme [value]
|
||||
(defn set-theme
|
||||
[value]
|
||||
(reset! theme value)
|
||||
(reset! colors/theme (case value
|
||||
:dark colors/dark-theme
|
||||
|
@ -1,14 +1,15 @@
|
||||
(ns quo2.components.avatars.account-avatar
|
||||
(:require [react-native.core :as rn]
|
||||
(:require [quo2.components.icon :as icons]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[quo2.components.icon :as icons]
|
||||
[quo2.theme :as theme]))
|
||||
[quo2.theme :as theme]
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(def icon-color-value
|
||||
{:dark (get-in colors/customization [:dark :purple])
|
||||
:light (get-in colors/customization [:light :purple])})
|
||||
|
||||
(defn get-border-radius [size]
|
||||
(defn get-border-radius
|
||||
[size]
|
||||
(case size
|
||||
80 16
|
||||
48 12
|
||||
@ -16,7 +17,8 @@
|
||||
24 8
|
||||
20 6))
|
||||
|
||||
(defn get-inner-icon-sizes [size]
|
||||
(defn get-inner-icon-sizes
|
||||
[size]
|
||||
(case size
|
||||
80 36
|
||||
48 24
|
||||
@ -28,17 +30,18 @@
|
||||
[{:keys [size icon]
|
||||
:or {size 80
|
||||
icon :main-icons/placeholder}}]
|
||||
(let [icon-color (if (theme/dark?)
|
||||
(:dark icon-color-value)
|
||||
(:light icon-color-value))
|
||||
(let [icon-color (if (theme/dark?)
|
||||
(:dark icon-color-value)
|
||||
(:light icon-color-value))
|
||||
avatar-border-radius (get-border-radius size)
|
||||
inner-icon-size (get-inner-icon-sizes size)]
|
||||
[rn/view {:style {:width size
|
||||
:background-color icon-color
|
||||
:height size
|
||||
:border-radius avatar-border-radius
|
||||
:justify-content :center
|
||||
:align-items :center}}
|
||||
inner-icon-size (get-inner-icon-sizes size)]
|
||||
[rn/view
|
||||
{:style {:width size
|
||||
:background-color icon-color
|
||||
:height size
|
||||
:border-radius avatar-border-radius
|
||||
:justify-content :center
|
||||
:align-items :center}}
|
||||
[icons/icon icon
|
||||
{:no-color true
|
||||
:size inner-icon-size}]]))
|
||||
|
@ -1,41 +1,47 @@
|
||||
(ns quo2.components.avatars.channel-avatar
|
||||
(:require [quo2.foundations.colors :as colors]
|
||||
[react-native.core :as rn]
|
||||
[quo2.components.icon :as icons]
|
||||
(:require [quo2.components.icon :as icons]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.theme :as theme]))
|
||||
[quo2.foundations.colors :as colors]
|
||||
[quo2.theme :as theme]
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(defn channel-avatar [{:keys [big? locked? emoji-background-color emoji]}]
|
||||
(defn channel-avatar
|
||||
[{:keys [big? locked? emoji-background-color emoji]}]
|
||||
(let [lock-exists? (some? locked?)
|
||||
dark? (theme/dark?)]
|
||||
[rn/view {:style {:width (if big? 32 24)
|
||||
:height (if big? 32 24)
|
||||
:border-radius (if big? 32 24)
|
||||
:justify-content :center
|
||||
:align-items :center
|
||||
:background-color emoji-background-color}}
|
||||
[rn/view {:style {:display :flex
|
||||
:justify-content :center
|
||||
:align-items :center}}
|
||||
[text/text {:size (if big?
|
||||
:paragraph-1
|
||||
:label)} emoji]
|
||||
[rn/view
|
||||
{:style {:width (if big? 32 24)
|
||||
:height (if big? 32 24)
|
||||
:border-radius (if big? 32 24)
|
||||
:justify-content :center
|
||||
:align-items :center
|
||||
:background-color emoji-background-color}}
|
||||
[rn/view
|
||||
{:style {:display :flex
|
||||
:justify-content :center
|
||||
:align-items :center}}
|
||||
[text/text
|
||||
{:size (if big?
|
||||
:paragraph-1
|
||||
:label)} emoji]
|
||||
(when lock-exists?
|
||||
[rn/view {:style {:position :absolute
|
||||
:left (if big?
|
||||
14
|
||||
8)
|
||||
:top (if big?
|
||||
15
|
||||
8)
|
||||
:background-color (if dark?
|
||||
colors/neutral-90
|
||||
colors/white)
|
||||
:border-radius 15
|
||||
:padding 2}}
|
||||
[icons/icon (if locked?
|
||||
:main-icons/locked
|
||||
:main-icons/unlocked)
|
||||
[rn/view
|
||||
{:style {:position :absolute
|
||||
:left (if big?
|
||||
14
|
||||
8)
|
||||
:top (if big?
|
||||
15
|
||||
8)
|
||||
:background-color (if dark?
|
||||
colors/neutral-90
|
||||
colors/white)
|
||||
:border-radius 15
|
||||
:padding 2}}
|
||||
[icons/icon
|
||||
(if locked?
|
||||
:main-icons/locked
|
||||
:main-icons/unlocked)
|
||||
{:color (if dark?
|
||||
colors/neutral-40
|
||||
colors/neutral-50)
|
||||
|
@ -1,6 +1,6 @@
|
||||
(ns quo2.components.avatars.group-avatar
|
||||
(:require [quo2.foundations.colors :as colors]
|
||||
[quo2.components.icon :as icon]
|
||||
(:require [quo2.components.icon :as icon]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(def sizes
|
||||
@ -11,16 +11,20 @@
|
||||
:medium 32
|
||||
:large 48}})
|
||||
|
||||
;; TODO: this implementation does not support group display picture (can only display default group icon).
|
||||
(defn group-avatar [_]
|
||||
;; TODO: this implementation does not support group display picture (can only display default group
|
||||
;; icon).
|
||||
(defn group-avatar
|
||||
[_]
|
||||
(fn [{:keys [color size]}]
|
||||
(let [container-size (get-in sizes [:container size])
|
||||
icon-size (get-in sizes [:icon size])]
|
||||
[rn/view {:width container-size
|
||||
:height container-size
|
||||
:align-items :center
|
||||
:justify-content :center
|
||||
:border-radius (/ container-size 2)
|
||||
:background-color (colors/custom-color-by-theme color 50 60)}
|
||||
[icon/icon :i/group {:size icon-size
|
||||
:color colors/white-opa-70}]])))
|
||||
[rn/view
|
||||
{:width container-size
|
||||
:height container-size
|
||||
:align-items :center
|
||||
:justify-content :center
|
||||
:border-radius (/ container-size 2)
|
||||
:background-color (colors/custom-color-by-theme color 50 60)}
|
||||
[icon/icon :i/group
|
||||
{:size icon-size
|
||||
:color colors/white-opa-70}]])))
|
||||
|
@ -1,7 +1,7 @@
|
||||
(ns quo2.components.avatars.icon-avatar
|
||||
(:require [react-native.core :as rn]
|
||||
(:require [quo2.components.icon :as icons]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[quo2.components.icon :as icons]))
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(def sizes
|
||||
{:big 48
|
||||
@ -12,17 +12,19 @@
|
||||
[{:keys [size icon color opacity]
|
||||
:or {opacity 20}}]
|
||||
(let [component-size (size sizes)
|
||||
circle-color (colors/custom-color color 50 opacity)
|
||||
icon-color (colors/custom-color-by-theme color 50 60)
|
||||
icon-size (case size
|
||||
:big 20
|
||||
:medium 16
|
||||
:small 12)]
|
||||
[rn/view {:style {:width component-size
|
||||
:height component-size
|
||||
:border-radius component-size
|
||||
:background-color circle-color
|
||||
:justify-content :center
|
||||
:align-items :center}}
|
||||
[icons/icon icon {:size icon-size
|
||||
:color icon-color}]]))
|
||||
circle-color (colors/custom-color color 50 opacity)
|
||||
icon-color (colors/custom-color-by-theme color 50 60)
|
||||
icon-size (case size
|
||||
:big 20
|
||||
:medium 16
|
||||
:small 12)]
|
||||
[rn/view
|
||||
{:style {:width component-size
|
||||
:height component-size
|
||||
:border-radius component-size
|
||||
:background-color circle-color
|
||||
:justify-content :center
|
||||
:align-items :center}}
|
||||
[icons/icon icon
|
||||
{:size icon-size
|
||||
:color icon-color}]]))
|
||||
|
@ -1,91 +1,96 @@
|
||||
(ns quo2.components.avatars.user-avatar
|
||||
(:require [react-native.core :as rn]
|
||||
[react-native.fast-image :as fast-image]
|
||||
(:require [clojure.string :refer [blank? split upper-case]]
|
||||
[quo2.components.icon :as icons]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[quo2.components.icon :as icons]
|
||||
[quo2.theme :refer [dark?]]
|
||||
[clojure.string :refer [upper-case split blank?]]))
|
||||
[react-native.core :as rn]
|
||||
[react-native.fast-image :as fast-image]))
|
||||
|
||||
(def sizes {:big {:outer 80
|
||||
:inner 72
|
||||
:status-indicator 20
|
||||
:status-indicator-border 4
|
||||
:font-size :heading-1}
|
||||
:medium {:outer 48
|
||||
:inner 44
|
||||
:status-indicator 12
|
||||
:status-indicator-border 2
|
||||
:font-size :paragraph-1}
|
||||
:small {:outer 32
|
||||
:inner 28
|
||||
:status-indicator 12
|
||||
:status-indicator-border 2
|
||||
:font-size :paragraph-2}
|
||||
:xs {:outer 24
|
||||
:inner 24
|
||||
:status-indicator 0
|
||||
:status-indicator-border 0
|
||||
:font-size :paragraph-2}
|
||||
:xxs {:outer 20
|
||||
:inner 20
|
||||
:status-indicator 0
|
||||
:status-indicator-border 0
|
||||
:font-size :label}
|
||||
:xxxs {:outer 16
|
||||
:inner 16
|
||||
:status-indicator 0
|
||||
:status-indicator-border 0
|
||||
:font-size :label}})
|
||||
(def sizes
|
||||
{:big {:outer 80
|
||||
:inner 72
|
||||
:status-indicator 20
|
||||
:status-indicator-border 4
|
||||
:font-size :heading-1}
|
||||
:medium {:outer 48
|
||||
:inner 44
|
||||
:status-indicator 12
|
||||
:status-indicator-border 2
|
||||
:font-size :paragraph-1}
|
||||
:small {:outer 32
|
||||
:inner 28
|
||||
:status-indicator 12
|
||||
:status-indicator-border 2
|
||||
:font-size :paragraph-2}
|
||||
:xs {:outer 24
|
||||
:inner 24
|
||||
:status-indicator 0
|
||||
:status-indicator-border 0
|
||||
:font-size :paragraph-2}
|
||||
:xxs {:outer 20
|
||||
:inner 20
|
||||
:status-indicator 0
|
||||
:status-indicator-border 0
|
||||
:font-size :label}
|
||||
:xxxs {:outer 16
|
||||
:inner 16
|
||||
:status-indicator 0
|
||||
:status-indicator-border 0
|
||||
:font-size :label}})
|
||||
|
||||
(defn dot-indicator
|
||||
[size status-indicator? online? ring? dark?]
|
||||
(when status-indicator?
|
||||
(let [dimensions (get-in sizes [size :status-indicator])
|
||||
(let [dimensions (get-in sizes [size :status-indicator])
|
||||
border-width (get-in sizes [size :status-indicator-border])
|
||||
right (case size
|
||||
:big 2
|
||||
:medium 0
|
||||
:small -2
|
||||
0)
|
||||
bottom (case size
|
||||
:big (if ring?
|
||||
-1
|
||||
2)
|
||||
:medium (if ring?
|
||||
0
|
||||
-2)
|
||||
:small (if ring?
|
||||
-2
|
||||
-2)
|
||||
0)]
|
||||
[rn/view {:style {:background-color (if online?
|
||||
colors/success-50
|
||||
colors/neutral-40)
|
||||
:width dimensions
|
||||
:height dimensions
|
||||
:border-width border-width
|
||||
:border-radius dimensions
|
||||
:border-color (if dark?
|
||||
colors/neutral-100
|
||||
colors/white)
|
||||
:position :absolute
|
||||
:bottom bottom
|
||||
:right right}}])))
|
||||
right (case size
|
||||
:big 2
|
||||
:medium 0
|
||||
:small -2
|
||||
0)
|
||||
bottom (case size
|
||||
:big (if ring?
|
||||
-1
|
||||
2)
|
||||
:medium (if ring?
|
||||
0
|
||||
-2)
|
||||
:small (if ring?
|
||||
-2
|
||||
-2)
|
||||
0)]
|
||||
[rn/view
|
||||
{:style {:background-color (if online?
|
||||
colors/success-50
|
||||
colors/neutral-40)
|
||||
:width dimensions
|
||||
:height dimensions
|
||||
:border-width border-width
|
||||
:border-radius dimensions
|
||||
:border-color (if dark?
|
||||
colors/neutral-100
|
||||
colors/white)
|
||||
:position :absolute
|
||||
:bottom bottom
|
||||
:right right}}])))
|
||||
|
||||
(defn container-styling [inner-dimensions outer-dimensions]
|
||||
{:width inner-dimensions
|
||||
:position :absolute
|
||||
:top (/ (- outer-dimensions inner-dimensions) 2)
|
||||
:left (/ (- outer-dimensions inner-dimensions) 2)
|
||||
:height inner-dimensions
|
||||
(defn container-styling
|
||||
[inner-dimensions outer-dimensions]
|
||||
{:width inner-dimensions
|
||||
:position :absolute
|
||||
:top (/ (- outer-dimensions inner-dimensions) 2)
|
||||
:left (/ (- outer-dimensions inner-dimensions) 2)
|
||||
:height inner-dimensions
|
||||
:border-radius inner-dimensions})
|
||||
|
||||
(defn container [inner-dimensions outer-dimensions & children]
|
||||
[rn/view {:style (merge {:background-color (colors/custom-color-by-theme :turquoise 50 60)
|
||||
:justify-content :center
|
||||
:align-items :center}
|
||||
(container-styling inner-dimensions outer-dimensions))}
|
||||
(defn container
|
||||
[inner-dimensions outer-dimensions & children]
|
||||
[rn/view
|
||||
{:style (merge {:background-color (colors/custom-color-by-theme :turquoise 50 60)
|
||||
:justify-content :center
|
||||
:align-items :center}
|
||||
(container-styling inner-dimensions outer-dimensions))}
|
||||
children])
|
||||
|
||||
(def small-sizes #{:xs :xxs :xxxs})
|
||||
@ -112,9 +117,11 @@
|
||||
identicon? (contains? identicon-sizes size)
|
||||
small? (contains? small-sizes size)
|
||||
outer-dimensions (get-in sizes [size :outer])
|
||||
inner-dimensions (get-in sizes [size (if ring?
|
||||
:inner
|
||||
:outer)])
|
||||
inner-dimensions (get-in sizes
|
||||
[size
|
||||
(if ring?
|
||||
:inner
|
||||
:outer)])
|
||||
font-size (get-in sizes [size :font-size])
|
||||
icon-text (if-not (or (blank? first-initial-letter)
|
||||
(blank? initials))
|
||||
@ -122,22 +129,26 @@
|
||||
first-initial-letter
|
||||
initials)
|
||||
"")]
|
||||
[rn/view {:accessibility-label :user-avatar
|
||||
:style {:width outer-dimensions
|
||||
:height outer-dimensions
|
||||
:border-radius outer-dimensions}}
|
||||
[rn/view
|
||||
{:accessibility-label :user-avatar
|
||||
:style {:width outer-dimensions
|
||||
:height outer-dimensions
|
||||
:border-radius outer-dimensions}}
|
||||
(when (and ring? identicon?)
|
||||
[icons/icon :i/identicon-ring {:size outer-dimensions
|
||||
:no-color true}])
|
||||
[icons/icon :i/identicon-ring
|
||||
{:size outer-dimensions
|
||||
:no-color true}])
|
||||
(if profile-picture
|
||||
;; display image
|
||||
[fast-image/fast-image {:source {:uri profile-picture}
|
||||
:style (container-styling inner-dimensions outer-dimensions)}]
|
||||
[fast-image/fast-image
|
||||
{:source {:uri profile-picture}
|
||||
:style (container-styling inner-dimensions outer-dimensions)}]
|
||||
;; else display initials
|
||||
[container inner-dimensions outer-dimensions
|
||||
^{:key :icon-text}
|
||||
[text/text {:weight :semi-bold
|
||||
:size font-size
|
||||
:style {:color colors/white-opa-70}}
|
||||
[text/text
|
||||
{:weight :semi-bold
|
||||
:size font-size
|
||||
:style {:color colors/white-opa-70}}
|
||||
(upper-case icon-text)]])
|
||||
[dot-indicator size status-indicator? online? ring? (dark?)]]))
|
||||
|
@ -1,31 +1,35 @@
|
||||
(ns quo2.components.avatars.wallet-user-avatar
|
||||
(:require [react-native.core :as rn]
|
||||
[quo2.foundations.colors :as colors]
|
||||
(:require [clojure.string :as string]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[clojure.string :as string]))
|
||||
[quo2.foundations.colors :as colors]
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(def circle-sizes {:small 20
|
||||
:medium 32
|
||||
:large 48
|
||||
:x-large 80})
|
||||
(def circle-sizes
|
||||
{:small 20
|
||||
:medium 32
|
||||
:large 48
|
||||
:x-large 80})
|
||||
|
||||
(def font-sizes {:small :label
|
||||
:medium :paragraph-2
|
||||
:large :paragraph-1
|
||||
:x-large :heading-1})
|
||||
(def font-sizes
|
||||
{:small :label
|
||||
:medium :paragraph-2
|
||||
:large :paragraph-1
|
||||
:x-large :heading-1})
|
||||
|
||||
(def font-weights {:small :medium
|
||||
:medium :semi-bold
|
||||
:large :semi-bold
|
||||
:x-large :medium})
|
||||
(def font-weights
|
||||
{:small :medium
|
||||
:medium :semi-bold
|
||||
:large :semi-bold
|
||||
:x-large :medium})
|
||||
|
||||
(defn wallet-user-avatar
|
||||
"params, first name, last name, color, size
|
||||
and if it's dark or not!"
|
||||
[{:keys [f-name l-name color size] :or {f-name "John"
|
||||
l-name "Doe"
|
||||
color :red
|
||||
size :x-large}}]
|
||||
[{:keys [f-name l-name color size]
|
||||
:or {f-name "John"
|
||||
l-name "Doe"
|
||||
color :red
|
||||
size :x-large}}]
|
||||
(let [circle-size (size circle-sizes)
|
||||
small? (= size :small)
|
||||
f-name-initial (-> f-name
|
||||
@ -36,16 +40,18 @@
|
||||
(subs 0 1))
|
||||
circle-color (colors/custom-color color 50 20)
|
||||
text-color (colors/custom-color-by-theme color 50 60)]
|
||||
[rn/view {:style {:width circle-size
|
||||
:height circle-size
|
||||
:border-radius circle-size
|
||||
:text-align :center
|
||||
:justify-content :center
|
||||
:align-items :center
|
||||
:background-color circle-color}}
|
||||
[text/text {:size (size font-sizes)
|
||||
:weight (size font-weights)
|
||||
:style {:color text-color}}
|
||||
[rn/view
|
||||
{:style {:width circle-size
|
||||
:height circle-size
|
||||
:border-radius circle-size
|
||||
:text-align :center
|
||||
:justify-content :center
|
||||
:align-items :center
|
||||
:background-color circle-color}}
|
||||
[text/text
|
||||
{:size (size font-sizes)
|
||||
:weight (size font-weights)
|
||||
:style {:color text-color}}
|
||||
(if small?
|
||||
(str f-name-initial)
|
||||
(str f-name-initial l-name-initial))]]))
|
||||
|
@ -1,142 +1,143 @@
|
||||
(ns quo2.components.buttons.button
|
||||
(:require [react-native.core :as rn]
|
||||
[quo2.foundations.colors :as colors]
|
||||
(:require [quo2.components.icon :as quo2.icons]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[quo2.theme :as theme]
|
||||
[reagent.core :as reagent]
|
||||
[quo2.components.icon :as quo2.icons]))
|
||||
[react-native.core :as rn]
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
(def themes
|
||||
{:light {:primary {:icon-color colors/white
|
||||
:label-color colors/white
|
||||
:background-color {:default colors/primary-50
|
||||
:pressed colors/primary-60
|
||||
:disabled colors/primary-50}}
|
||||
:secondary {:icon-color colors/primary-50
|
||||
:label-color colors/primary-50
|
||||
:background-color {:default colors/primary-50-opa-20
|
||||
:pressed colors/primary-50-opa-40
|
||||
:disabled colors/primary-50-opa-20}}
|
||||
:grey {:icon-color colors/neutral-100
|
||||
:icon-secondary-color colors/neutral-50
|
||||
:label-color colors/neutral-100
|
||||
:background-color {:default colors/neutral-10
|
||||
:pressed colors/neutral-20
|
||||
:disabled colors/neutral-10}}
|
||||
:dark-grey {:icon-color colors/neutral-100
|
||||
:icon-secondary-color colors/neutral-50
|
||||
:label-color colors/neutral-100
|
||||
:background-color {:default colors/neutral-20
|
||||
:pressed colors/neutral-30
|
||||
:disabled colors/neutral-20}}
|
||||
:outline {:icon-color colors/neutral-50
|
||||
:icon-secondary-color colors/neutral-50
|
||||
:label-color colors/neutral-100
|
||||
:border-color {:default colors/neutral-20
|
||||
:pressed colors/neutral-40
|
||||
:disabled colors/neutral-20}}
|
||||
:ghost {:icon-color colors/neutral-50
|
||||
:icon-secondary-color colors/neutral-50
|
||||
:label-color colors/neutral-100
|
||||
:background-color {:pressed colors/neutral-10}}
|
||||
:danger {:icon-color colors/white
|
||||
:label-color colors/white
|
||||
:background-color {:default colors/danger-50
|
||||
:pressed colors/danger-60
|
||||
:disabled colors/danger-50}}
|
||||
:positive {:icon-color colors/white
|
||||
:label-color colors/white
|
||||
:background-color {:default colors/success-50
|
||||
:pressed colors/success-60
|
||||
:disabled colors/success-50-opa-30}}
|
||||
:photo-bg {:icon-color colors/neutral-100
|
||||
:icon-secondary-color colors/neutral-80-opa-40
|
||||
:label-color colors/neutral-100
|
||||
:background-color {:default colors/white-opa-40
|
||||
:pressed colors/white-opa-50
|
||||
:disabled colors/white-opa-40}}
|
||||
:blur-bg {:icon-color colors/neutral-100
|
||||
:icon-secondary-color colors/neutral-80-opa-40
|
||||
:label-color colors/neutral-100
|
||||
:background-color {:default colors/neutral-80-opa-5
|
||||
:pressed colors/neutral-80-opa-10
|
||||
:disabled colors/neutral-80-opa-5}}
|
||||
:blur-bg-outline {:icon-color colors/neutral-100
|
||||
:icon-secondary-color colors/neutral-80-opa-40
|
||||
:label-color colors/neutral-100
|
||||
:border-color {:default colors/neutral-80-opa-10
|
||||
:pressed colors/neutral-80-opa-20
|
||||
:disabled colors/neutral-80-opa-10}}
|
||||
:shell {:icon-color colors/white
|
||||
:label-color colors/white
|
||||
:background-color {:default colors/neutral-95
|
||||
:pressed colors/neutral-95
|
||||
:disabled colors/neutral-95}}}
|
||||
:dark {:primary {:icon-color colors/white
|
||||
:label-color colors/white
|
||||
:background-color {:default colors/primary-60
|
||||
:pressed colors/primary-50
|
||||
:disabled colors/primary-60}}
|
||||
:secondary {:icon-color colors/primary-50
|
||||
:label-color colors/primary-50
|
||||
:background-color {:default colors/primary-50-opa-20
|
||||
:pressed colors/primary-50-opa-30
|
||||
:disabled colors/primary-50-opa-20}}
|
||||
:grey {:icon-color colors/white
|
||||
:icon-secondary-color colors/neutral-40
|
||||
:label-color colors/white
|
||||
:background-color {:default colors/neutral-80
|
||||
:pressed colors/neutral-60
|
||||
:disabled colors/neutral-80}}
|
||||
:dark-grey {:icon-color colors/white
|
||||
:icon-secondary-color colors/neutral-40
|
||||
:label-color colors/white
|
||||
:background-color {:default colors/neutral-70
|
||||
:pressed colors/neutral-60
|
||||
:disabled colors/neutral-70}}
|
||||
:outline {:icon-color colors/neutral-40
|
||||
:icon-secondary-color colors/neutral-40
|
||||
:label-color colors/white
|
||||
:border-color {:default colors/neutral-70
|
||||
:pressed colors/neutral-60
|
||||
:disabled colors/neutral-70}}
|
||||
:ghost {:icon-color colors/neutral-40
|
||||
:icon-secondary-color colors/neutral-40
|
||||
:label-color colors/white
|
||||
:background-color {:pressed colors/neutral-80}}
|
||||
:danger {:icon-color colors/white
|
||||
:label-color colors/white
|
||||
:background-color {:default colors/danger-60
|
||||
:pressed colors/danger-50
|
||||
:disabled colors/danger-60}}
|
||||
:positive {:icon-color colors/white
|
||||
:label-color colors/white
|
||||
:background-color {:default colors/success-60
|
||||
:pressed colors/success-50
|
||||
:disabled colors/success-60-opa-30}}
|
||||
:photo-bg {:icon-color colors/white
|
||||
:icon-secondary-color colors/neutral-30
|
||||
:label-color colors/white
|
||||
:background-color {:default colors/neutral-80-opa-40
|
||||
:pressed colors/neutral-80-opa-50
|
||||
:disabled colors/neutral-80-opa-40}}
|
||||
:blur-bg {:icon-color colors/white
|
||||
:icon-secondary-color colors/white-opa-40
|
||||
:label-color colors/white
|
||||
:background-color {:default colors/white-opa-5
|
||||
:pressed colors/white-opa-10
|
||||
:disabled colors/white-opa-5}}
|
||||
:blur-bg-outline {:icon-color colors/white
|
||||
:icon-secondary-color colors/white-opa-40
|
||||
:label-color colors/white
|
||||
:border-color {:default colors/white-opa-10
|
||||
:pressed colors/white-opa-20
|
||||
:disabled colors/white-opa-5}}
|
||||
:shell {:icon-color colors/white
|
||||
:label-color colors/white
|
||||
:background-color {:default colors/neutral-95}}}})
|
||||
{:light {:primary {:icon-color colors/white
|
||||
:label-color colors/white
|
||||
:background-color {:default colors/primary-50
|
||||
:pressed colors/primary-60
|
||||
:disabled colors/primary-50}}
|
||||
:secondary {:icon-color colors/primary-50
|
||||
:label-color colors/primary-50
|
||||
:background-color {:default colors/primary-50-opa-20
|
||||
:pressed colors/primary-50-opa-40
|
||||
:disabled colors/primary-50-opa-20}}
|
||||
:grey {:icon-color colors/neutral-100
|
||||
:icon-secondary-color colors/neutral-50
|
||||
:label-color colors/neutral-100
|
||||
:background-color {:default colors/neutral-10
|
||||
:pressed colors/neutral-20
|
||||
:disabled colors/neutral-10}}
|
||||
:dark-grey {:icon-color colors/neutral-100
|
||||
:icon-secondary-color colors/neutral-50
|
||||
:label-color colors/neutral-100
|
||||
:background-color {:default colors/neutral-20
|
||||
:pressed colors/neutral-30
|
||||
:disabled colors/neutral-20}}
|
||||
:outline {:icon-color colors/neutral-50
|
||||
:icon-secondary-color colors/neutral-50
|
||||
:label-color colors/neutral-100
|
||||
:border-color {:default colors/neutral-20
|
||||
:pressed colors/neutral-40
|
||||
:disabled colors/neutral-20}}
|
||||
:ghost {:icon-color colors/neutral-50
|
||||
:icon-secondary-color colors/neutral-50
|
||||
:label-color colors/neutral-100
|
||||
:background-color {:pressed colors/neutral-10}}
|
||||
:danger {:icon-color colors/white
|
||||
:label-color colors/white
|
||||
:background-color {:default colors/danger-50
|
||||
:pressed colors/danger-60
|
||||
:disabled colors/danger-50}}
|
||||
:positive {:icon-color colors/white
|
||||
:label-color colors/white
|
||||
:background-color {:default colors/success-50
|
||||
:pressed colors/success-60
|
||||
:disabled colors/success-50-opa-30}}
|
||||
:photo-bg {:icon-color colors/neutral-100
|
||||
:icon-secondary-color colors/neutral-80-opa-40
|
||||
:label-color colors/neutral-100
|
||||
:background-color {:default colors/white-opa-40
|
||||
:pressed colors/white-opa-50
|
||||
:disabled colors/white-opa-40}}
|
||||
:blur-bg {:icon-color colors/neutral-100
|
||||
:icon-secondary-color colors/neutral-80-opa-40
|
||||
:label-color colors/neutral-100
|
||||
:background-color {:default colors/neutral-80-opa-5
|
||||
:pressed colors/neutral-80-opa-10
|
||||
:disabled colors/neutral-80-opa-5}}
|
||||
:blur-bg-outline {:icon-color colors/neutral-100
|
||||
:icon-secondary-color colors/neutral-80-opa-40
|
||||
:label-color colors/neutral-100
|
||||
:border-color {:default colors/neutral-80-opa-10
|
||||
:pressed colors/neutral-80-opa-20
|
||||
:disabled colors/neutral-80-opa-10}}
|
||||
:shell {:icon-color colors/white
|
||||
:label-color colors/white
|
||||
:background-color {:default colors/neutral-95
|
||||
:pressed colors/neutral-95
|
||||
:disabled colors/neutral-95}}}
|
||||
:dark {:primary {:icon-color colors/white
|
||||
:label-color colors/white
|
||||
:background-color {:default colors/primary-60
|
||||
:pressed colors/primary-50
|
||||
:disabled colors/primary-60}}
|
||||
:secondary {:icon-color colors/primary-50
|
||||
:label-color colors/primary-50
|
||||
:background-color {:default colors/primary-50-opa-20
|
||||
:pressed colors/primary-50-opa-30
|
||||
:disabled colors/primary-50-opa-20}}
|
||||
:grey {:icon-color colors/white
|
||||
:icon-secondary-color colors/neutral-40
|
||||
:label-color colors/white
|
||||
:background-color {:default colors/neutral-80
|
||||
:pressed colors/neutral-60
|
||||
:disabled colors/neutral-80}}
|
||||
:dark-grey {:icon-color colors/white
|
||||
:icon-secondary-color colors/neutral-40
|
||||
:label-color colors/white
|
||||
:background-color {:default colors/neutral-70
|
||||
:pressed colors/neutral-60
|
||||
:disabled colors/neutral-70}}
|
||||
:outline {:icon-color colors/neutral-40
|
||||
:icon-secondary-color colors/neutral-40
|
||||
:label-color colors/white
|
||||
:border-color {:default colors/neutral-70
|
||||
:pressed colors/neutral-60
|
||||
:disabled colors/neutral-70}}
|
||||
:ghost {:icon-color colors/neutral-40
|
||||
:icon-secondary-color colors/neutral-40
|
||||
:label-color colors/white
|
||||
:background-color {:pressed colors/neutral-80}}
|
||||
:danger {:icon-color colors/white
|
||||
:label-color colors/white
|
||||
:background-color {:default colors/danger-60
|
||||
:pressed colors/danger-50
|
||||
:disabled colors/danger-60}}
|
||||
:positive {:icon-color colors/white
|
||||
:label-color colors/white
|
||||
:background-color {:default colors/success-60
|
||||
:pressed colors/success-50
|
||||
:disabled colors/success-60-opa-30}}
|
||||
:photo-bg {:icon-color colors/white
|
||||
:icon-secondary-color colors/neutral-30
|
||||
:label-color colors/white
|
||||
:background-color {:default colors/neutral-80-opa-40
|
||||
:pressed colors/neutral-80-opa-50
|
||||
:disabled colors/neutral-80-opa-40}}
|
||||
:blur-bg {:icon-color colors/white
|
||||
:icon-secondary-color colors/white-opa-40
|
||||
:label-color colors/white
|
||||
:background-color {:default colors/white-opa-5
|
||||
:pressed colors/white-opa-10
|
||||
:disabled colors/white-opa-5}}
|
||||
:blur-bg-outline {:icon-color colors/white
|
||||
:icon-secondary-color colors/white-opa-40
|
||||
:label-color colors/white
|
||||
:border-color {:default colors/white-opa-10
|
||||
:pressed colors/white-opa-20
|
||||
:disabled colors/white-opa-5}}
|
||||
:shell {:icon-color colors/white
|
||||
:label-color colors/white
|
||||
:background-color {:default colors/neutral-95}}}})
|
||||
|
||||
(defn shape-style-container [type icon size]
|
||||
(defn shape-style-container
|
||||
[type icon size]
|
||||
{:border-radius (if (and icon (#{:primary :secondary :danger} type))
|
||||
24
|
||||
(case size
|
||||
@ -145,22 +146,43 @@
|
||||
32 10
|
||||
24 8))})
|
||||
|
||||
(defn style-container [type size disabled background-color border-color icon above width before after]
|
||||
(defn style-container
|
||||
[type size disabled background-color border-color icon above width before after]
|
||||
(merge {:height size
|
||||
:align-items :center
|
||||
:justify-content :center
|
||||
:flex-direction (if above :column :row)
|
||||
:background-color background-color
|
||||
:padding-horizontal (when-not (or icon before after)
|
||||
(case size 56 16 40 16 32 12 24 8))
|
||||
(case size
|
||||
56 16
|
||||
40 16
|
||||
32 12
|
||||
24 8))
|
||||
:padding-left (when-not (or icon before)
|
||||
(case size 56 16 40 16 32 12 24 8))
|
||||
(case size
|
||||
56 16
|
||||
40 16
|
||||
32 12
|
||||
24 8))
|
||||
:padding-right (when-not (or icon after)
|
||||
(case size 56 16 40 16 32 12 24 8))
|
||||
(case size
|
||||
56 16
|
||||
40 16
|
||||
32 12
|
||||
24 8))
|
||||
:padding-top (when-not (or icon before after)
|
||||
(case size 56 0 40 9 32 5 24 3))
|
||||
(case size
|
||||
56 0
|
||||
40 9
|
||||
32 5
|
||||
24 3))
|
||||
:padding-bottom (when-not (or icon before after)
|
||||
(case size 56 0 40 9 32 5 24 4))}
|
||||
(case size
|
||||
56 0
|
||||
40 9
|
||||
32 5
|
||||
24 4))}
|
||||
(shape-style-container type icon size)
|
||||
(when width
|
||||
{:width width})
|
||||
@ -172,7 +194,8 @@
|
||||
(when disabled
|
||||
{:opacity 0.3})))
|
||||
|
||||
(defn community-themed? [type community-color]
|
||||
(defn community-themed?
|
||||
[type community-color]
|
||||
(and (= type :community) (string? community-color)))
|
||||
|
||||
(defn button
|
||||
@ -192,85 +215,97 @@
|
||||
[button {:icon true} :main-icons/close-circle]"
|
||||
[_ _]
|
||||
(let [pressed (reagent/atom false)]
|
||||
(fn [{:keys [on-press disabled type size community-color community-text-color before after above width
|
||||
override-theme override-background-color
|
||||
on-long-press accessibility-label icon icon-no-color style test-ID]
|
||||
:or {type :primary
|
||||
size 40}}
|
||||
children]
|
||||
(fn
|
||||
[{:keys [on-press disabled type size community-color community-text-color before after above
|
||||
width
|
||||
override-theme override-background-color
|
||||
on-long-press accessibility-label icon icon-no-color style test-ID]
|
||||
:or {type :primary
|
||||
size 40}}
|
||||
children]
|
||||
(let [{:keys [icon-color icon-secondary-color background-color label-color border-color]}
|
||||
(get-in themes [(or
|
||||
override-theme
|
||||
(theme/get-theme)) type])
|
||||
state (cond disabled :disabled @pressed :pressed :else :default)
|
||||
icon-size (when (= 24 size) 12)
|
||||
(get-in themes
|
||||
[(or
|
||||
override-theme
|
||||
(theme/get-theme)) type])
|
||||
state (cond disabled :disabled
|
||||
@pressed :pressed
|
||||
:else :default)
|
||||
icon-size (when (= 24 size) 12)
|
||||
icon-secondary-color (or icon-secondary-color icon-color)]
|
||||
[rn/touchable-without-feedback (merge {:test-ID test-ID
|
||||
:disabled disabled
|
||||
:accessibility-label accessibility-label}
|
||||
(when on-press
|
||||
{:on-press (fn []
|
||||
(on-press))})
|
||||
(when on-long-press
|
||||
{:on-long-press (fn []
|
||||
(on-long-press))})
|
||||
{:on-press-in (fn []
|
||||
(reset! pressed true))}
|
||||
{:on-press-out (fn []
|
||||
(reset! pressed nil))})
|
||||
[rn/touchable-without-feedback
|
||||
(merge {:test-ID test-ID
|
||||
:disabled disabled
|
||||
:accessibility-label accessibility-label}
|
||||
(when on-press
|
||||
{:on-press (fn []
|
||||
(on-press))})
|
||||
(when on-long-press
|
||||
{:on-long-press (fn []
|
||||
(on-long-press))})
|
||||
{:on-press-in (fn []
|
||||
(reset! pressed true))}
|
||||
{:on-press-out (fn []
|
||||
(reset! pressed nil))})
|
||||
|
||||
[rn/view {:style (merge
|
||||
(shape-style-container type icon size)
|
||||
{:background-color
|
||||
(if (= state :pressed)
|
||||
(colors/theme-colors colors/neutral-100 colors/white)
|
||||
:transparent)}
|
||||
style)}
|
||||
[rn/view {:style (merge
|
||||
(style-container
|
||||
type
|
||||
size
|
||||
disabled
|
||||
(or override-background-color (get background-color state))
|
||||
(get border-color state)
|
||||
icon
|
||||
above
|
||||
width
|
||||
before
|
||||
after)
|
||||
(when
|
||||
(community-themed? type community-color)
|
||||
(merge
|
||||
{:background-color community-color}
|
||||
(when (= state :pressed) {:opacity 0.9}))))}
|
||||
[rn/view
|
||||
{:style (merge
|
||||
(shape-style-container type icon size)
|
||||
{:background-color
|
||||
(if (= state :pressed)
|
||||
(colors/theme-colors colors/neutral-100 colors/white)
|
||||
:transparent)}
|
||||
style)}
|
||||
[rn/view
|
||||
{:style (merge
|
||||
(style-container
|
||||
type
|
||||
size
|
||||
disabled
|
||||
(or override-background-color (get background-color state))
|
||||
(get border-color state)
|
||||
icon
|
||||
above
|
||||
width
|
||||
before
|
||||
after)
|
||||
(when
|
||||
(community-themed? type community-color)
|
||||
(merge
|
||||
{:background-color community-color}
|
||||
(when (= state :pressed) {:opacity 0.9}))))}
|
||||
(when above
|
||||
[rn/view
|
||||
[quo2.icons/icon above {:container-style {:margin-bottom 2}
|
||||
:color icon-secondary-color
|
||||
:size icon-size}]])
|
||||
[quo2.icons/icon above
|
||||
{:container-style {:margin-bottom 2}
|
||||
:color icon-secondary-color
|
||||
:size icon-size}]])
|
||||
(when before
|
||||
[rn/view
|
||||
[quo2.icons/icon before {:container-style {:margin-left (if (= size 40) 12 8)
|
||||
:margin-right 4}
|
||||
:color icon-secondary-color
|
||||
:size icon-size}]])
|
||||
[quo2.icons/icon before
|
||||
{:container-style {:margin-left (if (= size 40) 12 8)
|
||||
:margin-right 4}
|
||||
:color icon-secondary-color
|
||||
:size icon-size}]])
|
||||
[rn/view
|
||||
(cond
|
||||
(or icon icon-no-color)
|
||||
[quo2.icons/icon children {:color icon-color
|
||||
:no-color icon-no-color
|
||||
:size icon-size}]
|
||||
[quo2.icons/icon children
|
||||
{:color icon-color
|
||||
:no-color icon-no-color
|
||||
:size icon-size}]
|
||||
|
||||
(string? children)
|
||||
[text/text {:size (when (#{56 24} size) :paragraph-2)
|
||||
:weight :medium
|
||||
:number-of-lines 1
|
||||
:style {:color (if
|
||||
(and
|
||||
(community-themed? type community-color)
|
||||
(string? community-text-color))
|
||||
community-text-color
|
||||
label-color)}}
|
||||
[text/text
|
||||
{:size (when (#{56 24} size) :paragraph-2)
|
||||
:weight :medium
|
||||
:number-of-lines 1
|
||||
:style {:color (if
|
||||
(and
|
||||
(community-themed? type community-color)
|
||||
(string? community-text-color))
|
||||
community-text-color
|
||||
label-color)}}
|
||||
|
||||
children]
|
||||
|
||||
@ -278,7 +313,8 @@
|
||||
children)]
|
||||
(when after
|
||||
[rn/view
|
||||
[quo2.icons/icon after {:container-style {:margin-left 4
|
||||
:margin-right (if (= size 40) 12 8)}
|
||||
:color icon-secondary-color
|
||||
:size icon-size}]])]]]))))
|
||||
[quo2.icons/icon after
|
||||
{:container-style {:margin-left 4
|
||||
:margin-right (if (= size 40) 12 8)}
|
||||
:color icon-secondary-color
|
||||
:size icon-size}]])]]]))))
|
||||
|
@ -1,11 +1,12 @@
|
||||
(ns quo2.components.buttons.dynamic-button
|
||||
(:require [react-native.core :as rn]
|
||||
[reagent.core :as reagent]
|
||||
[quo2.components.icon :as icon]
|
||||
(:require [quo2.components.icon :as icon]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[quo2.components.markdown.text :as text]))
|
||||
[react-native.core :as rn]
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
(defn- get-button-color [type pressed? customization-color]
|
||||
(defn- get-button-color
|
||||
[type pressed? customization-color]
|
||||
(if (#{:jump-to :mention} type)
|
||||
(if pressed?
|
||||
(colors/custom-color-by-theme customization-color 60 50)
|
||||
@ -14,12 +15,14 @@
|
||||
(colors/theme-colors colors/neutral-80-opa-80 colors/white-opa-80)
|
||||
(colors/theme-colors colors/neutral-80-opa-70 colors/white-opa-70))))
|
||||
|
||||
(defn- get-icon-and-text-color [type]
|
||||
(defn- get-icon-and-text-color
|
||||
[type]
|
||||
(if (#{:jump-to :mention} type)
|
||||
colors/white
|
||||
(colors/theme-colors colors/white colors/neutral-100)))
|
||||
|
||||
(defn- icon-view [type]
|
||||
(defn- icon-view
|
||||
[type]
|
||||
[icon/icon
|
||||
(case type
|
||||
:jump-to :i/jump-to
|
||||
@ -67,32 +70,34 @@
|
||||
:active-opacity 1
|
||||
:style {:padding 5}
|
||||
:accessibility-label type}
|
||||
[rn/view {:style (merge
|
||||
{:flex-direction :row
|
||||
:height 24
|
||||
:border-radius 12
|
||||
:background-color (get-button-color type @pressed? (or customization-color :primary))}
|
||||
style)}
|
||||
[rn/view
|
||||
{:style (merge
|
||||
{:flex-direction :row
|
||||
:height 24
|
||||
:border-radius 12
|
||||
:background-color (get-button-color type @pressed? (or customization-color :primary))}
|
||||
style)}
|
||||
(when (#{:mention :search :search-with-label :bottom} type)
|
||||
[icon-view type])
|
||||
(when (#{:jump-to :mention :notification-down :notification-up :search-with-label} type)
|
||||
[text/text {:weight :medium
|
||||
:size :paragraph-2
|
||||
:style {:color (get-icon-and-text-color type)
|
||||
:margin-top 2.5
|
||||
:margin-bottom 3.5
|
||||
:margin-left (case type
|
||||
:jump-to 8
|
||||
:mention 0
|
||||
:notification-down 8
|
||||
:notification-up 8
|
||||
:search-with-label 0)
|
||||
:margin-right (case type
|
||||
:jump-to 0
|
||||
:mention 8
|
||||
:notification-down 0
|
||||
:notification-up 0
|
||||
:search-with-label 8)}}
|
||||
[text/text
|
||||
{:weight :medium
|
||||
:size :paragraph-2
|
||||
:style {:color (get-icon-and-text-color type)
|
||||
:margin-top 2.5
|
||||
:margin-bottom 3.5
|
||||
:margin-left (case type
|
||||
:jump-to 8
|
||||
:mention 0
|
||||
:notification-down 8
|
||||
:notification-up 8
|
||||
:search-with-label 0)
|
||||
:margin-right (case type
|
||||
:jump-to 0
|
||||
:mention 8
|
||||
:notification-down 0
|
||||
:notification-up 0
|
||||
:search-with-label 8)}}
|
||||
(case type
|
||||
:jump-to label
|
||||
:search-with-label label
|
||||
|
@ -3,35 +3,36 @@
|
||||
[cljs-bean.core :as bean]
|
||||
[clojure.string :as string]
|
||||
[oops.core :as oops]
|
||||
[react-native.core :as rn]
|
||||
[quo2.theme :as theme]
|
||||
[quo2.components.buttons.button :as button]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[reagent.core :as reagent]
|
||||
[quo2.theme :as theme]
|
||||
[react-native.core :as rn]
|
||||
[react-native.linear-gradient :as linear-gradient]
|
||||
[react-native.masked-view :as masked-view]
|
||||
[react-native.syntax-highlighter :as highlighter]))
|
||||
[react-native.syntax-highlighter :as highlighter]
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
;; Example themes:
|
||||
;; https://github.com/react-syntax-highlighter/react-syntax-highlighter/tree/master/src/styles/hljs
|
||||
(def ^:private themes
|
||||
{:light {:hljs-comment {:color colors/neutral-40},
|
||||
:hljs-title {:color (colors/custom-color :blue 50)},
|
||||
:hljs-keyword {:color (colors/custom-color :green 50)},
|
||||
:hljs-string {:color (colors/custom-color :turquoise 50)},
|
||||
{:light {:hljs-comment {:color colors/neutral-40}
|
||||
:hljs-title {:color (colors/custom-color :blue 50)}
|
||||
:hljs-keyword {:color (colors/custom-color :green 50)}
|
||||
:hljs-string {:color (colors/custom-color :turquoise 50)}
|
||||
:hljs-literal {:color (colors/custom-color :turquoise 50)}
|
||||
:hljs-number {:color (colors/custom-color :turquoise 50)}
|
||||
:line-number {:color colors/neutral-40}}
|
||||
:dark {:hljs-comment {:color colors/neutral-60},
|
||||
:hljs-title {:color (colors/custom-color :blue 60)},
|
||||
:hljs-keyword {:color (colors/custom-color :green 60)},
|
||||
:hljs-string {:color (colors/custom-color :turquoise 60)},
|
||||
:dark {:hljs-comment {:color colors/neutral-60}
|
||||
:hljs-title {:color (colors/custom-color :blue 60)}
|
||||
:hljs-keyword {:color (colors/custom-color :green 60)}
|
||||
:hljs-string {:color (colors/custom-color :turquoise 60)}
|
||||
:hljs-literal {:color (colors/custom-color :turquoise 60)}
|
||||
:hljs-number {:color (colors/custom-color :turquoise 60)}
|
||||
:line-number {:color colors/neutral-40}}})
|
||||
|
||||
(defn- text-style [class-names]
|
||||
(defn- text-style
|
||||
[class-names]
|
||||
(->> class-names
|
||||
(map keyword)
|
||||
(reduce #(merge %1 (get-in themes [(theme/get-theme) %2]))
|
||||
@ -43,35 +44,41 @@
|
||||
;; layout.
|
||||
:line-height 18})))
|
||||
|
||||
(defn- render-nodes [nodes]
|
||||
(defn- render-nodes
|
||||
[nodes]
|
||||
(map (fn [{:keys [children value] :as node}]
|
||||
;; Node can have :children or a :value.
|
||||
(if children
|
||||
(into [text/text {:weight :code
|
||||
:size :paragraph-2
|
||||
:style (text-style (get-in node [:properties :className]))}]
|
||||
(into [text/text
|
||||
{:weight :code
|
||||
:size :paragraph-2
|
||||
:style (text-style (get-in node [:properties :className]))}]
|
||||
(render-nodes children))
|
||||
;; Remove newlines as we already render each line separately.
|
||||
(-> value string/trim-newline)))
|
||||
nodes))
|
||||
|
||||
(defn- code-block [{:keys [rows line-number-width]}]
|
||||
(defn- code-block
|
||||
[{:keys [rows line-number-width]}]
|
||||
[into [:<>]
|
||||
(->> rows
|
||||
(render-nodes)
|
||||
;; Line numbers
|
||||
(map-indexed (fn [idx row]
|
||||
(conj [rn/view {:style {:flex-direction :row}}
|
||||
[rn/view {:style {:width line-number-width
|
||||
;; 8+12 margin
|
||||
:margin-right 20}}
|
||||
[text/text {:weight :code
|
||||
:size :paragraph-2
|
||||
:style (text-style ["line-number"])}
|
||||
[rn/view
|
||||
{:style {:width line-number-width
|
||||
;; 8+12 margin
|
||||
:margin-right 20}}
|
||||
[text/text
|
||||
{:weight :code
|
||||
:size :paragraph-2
|
||||
:style (text-style ["line-number"])}
|
||||
(inc idx)]]]
|
||||
row))))])
|
||||
|
||||
(defn- native-renderer []
|
||||
(defn- native-renderer
|
||||
[]
|
||||
(let [text-height (reagent/atom nil)]
|
||||
(fn [{:keys [rows max-lines on-copy-press]}]
|
||||
(let [background-color (colors/theme-colors
|
||||
@ -89,67 +96,81 @@
|
||||
max-line-digits (-> rows count (min max-rows) str count)
|
||||
;; ~ 9 is char width, 18 is width used in Figma.
|
||||
line-number-width (* font-scale (max 18 (* 9 max-line-digits)))
|
||||
max-text-height (some-> max-lines (* font-scale 18)) ;; 18 is font's line height.
|
||||
max-text-height (some-> max-lines
|
||||
(* font-scale 18)) ;; 18 is font's line height.
|
||||
truncated? (and max-text-height (< max-text-height @text-height))
|
||||
maybe-mask-wrapper (if truncated?
|
||||
[masked-view/masked-view
|
||||
{:mask-element
|
||||
(reagent/as-element
|
||||
[linear-gradient/linear-gradient {:colors ["black" "transparent"]
|
||||
:locations [0.75 1]
|
||||
:style {:flex 1}}])}]
|
||||
[linear-gradient/linear-gradient
|
||||
{:colors ["black" "transparent"]
|
||||
:locations [0.75 1]
|
||||
:style {:flex 1}}])}]
|
||||
[:<>])]
|
||||
|
||||
[rn/view {:style {:overflow :hidden
|
||||
:padding 8
|
||||
:background-color background-color
|
||||
:border-color border-color
|
||||
:border-width 1
|
||||
:border-radius 8
|
||||
;; Hide on intial render to avoid flicker when mask-wrapper is shown.
|
||||
:opacity (if @text-height 1 0)}}
|
||||
[rn/view
|
||||
{:style {:overflow :hidden
|
||||
:padding 8
|
||||
:background-color background-color
|
||||
:border-color border-color
|
||||
:border-width 1
|
||||
:border-radius 8
|
||||
;; Hide on intial render to avoid flicker when mask-wrapper is shown.
|
||||
:opacity (if @text-height 1 0)}}
|
||||
;; Line number container
|
||||
[rn/view {:style {:position :absolute
|
||||
:bottom 0
|
||||
:top 0
|
||||
:left 0
|
||||
:width (+ line-number-width 8 8)
|
||||
:background-color background-color-left
|
||||
:border-right-color border-color
|
||||
:border-right-width 1}}]
|
||||
(conj maybe-mask-wrapper [rn/view {:max-height max-text-height}
|
||||
[rn/view {:on-layout (fn [evt]
|
||||
(let [height (oops/oget evt "nativeEvent.layout.height")]
|
||||
(reset! text-height height)))}
|
||||
[code-block {:rows (take max-rows rows)
|
||||
:line-number-width line-number-width}]]])
|
||||
[rn/view
|
||||
{:style {:position :absolute
|
||||
:bottom 0
|
||||
:top 0
|
||||
:left 0
|
||||
:width (+ line-number-width 8 8)
|
||||
:background-color background-color-left
|
||||
:border-right-color border-color
|
||||
:border-right-width 1}}]
|
||||
(conj maybe-mask-wrapper
|
||||
[rn/view {:max-height max-text-height}
|
||||
[rn/view
|
||||
{:on-layout (fn [evt]
|
||||
(let [height (oops/oget evt "nativeEvent.layout.height")]
|
||||
(reset! text-height height)))}
|
||||
[code-block
|
||||
{:rows (take max-rows rows)
|
||||
:line-number-width line-number-width}]]])
|
||||
|
||||
;; Copy button
|
||||
[rn/view {:style {:position :absolute
|
||||
:bottom 8
|
||||
:right 8}}
|
||||
[button/button {:icon true
|
||||
:type :grey
|
||||
:size 24
|
||||
:on-press on-copy-press}
|
||||
[rn/view
|
||||
{:style {:position :absolute
|
||||
:bottom 8
|
||||
:right 8}}
|
||||
[button/button
|
||||
{:icon true
|
||||
:type :grey
|
||||
:size 24
|
||||
:on-press on-copy-press}
|
||||
:main-icons/copy]]]))))
|
||||
|
||||
(defn- wrap-renderer-fn [f {:keys [max-lines on-copy-press]}]
|
||||
(defn- wrap-renderer-fn
|
||||
[f {:keys [max-lines on-copy-press]}]
|
||||
(fn [^js props]
|
||||
(reagent/as-element [:f> f {:rows (.-rows props)
|
||||
:max-lines max-lines
|
||||
:on-copy-press on-copy-press}])))
|
||||
(reagent/as-element [:f> f
|
||||
{:rows (.-rows props)
|
||||
:max-lines max-lines
|
||||
:on-copy-press on-copy-press}])))
|
||||
|
||||
(defn snippet [{:keys [language max-lines on-copy-press]} children]
|
||||
[highlighter/highlighter {:language language
|
||||
:renderer (wrap-renderer-fn
|
||||
native-renderer {:max-lines max-lines
|
||||
:on-copy-press #(when on-copy-press
|
||||
(on-copy-press children))})
|
||||
;; Default props to adapt Highlighter for react-native.
|
||||
:CodeTag react-native/View
|
||||
:PreTag react-native/View
|
||||
:show-line-numbers false
|
||||
:style #js {}
|
||||
:custom-style #js {:backgroundColor nil}}
|
||||
(defn snippet
|
||||
[{:keys [language max-lines on-copy-press]} children]
|
||||
[highlighter/highlighter
|
||||
{:language language
|
||||
:renderer (wrap-renderer-fn
|
||||
native-renderer
|
||||
{:max-lines max-lines
|
||||
:on-copy-press #(when on-copy-press
|
||||
(on-copy-press children))})
|
||||
;; Default props to adapt Highlighter for react-native.
|
||||
:CodeTag react-native/View
|
||||
:PreTag react-native/View
|
||||
:show-line-numbers false
|
||||
:style #js {}
|
||||
:custom-style #js {:backgroundColor nil}}
|
||||
children])
|
||||
|
@ -1,18 +1,18 @@
|
||||
(ns quo2.components.community.community-card-view
|
||||
(:require
|
||||
[quo2.components.community.community-view :as community-view]
|
||||
[quo2.components.community.style :as style]
|
||||
[react-native.core :as rn]))
|
||||
(:require [quo2.components.community.community-view :as community-view]
|
||||
[quo2.components.community.style :as style]
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(defn community-card-view-item
|
||||
[{:keys [name description locked
|
||||
status tokens cover tags width]} on-press]
|
||||
[rn/touchable-opacity {:on-press on-press}
|
||||
[rn/view {:style (style/community-card 20)}
|
||||
[rn/view {:style {:width width
|
||||
:height 230
|
||||
:border-radius 20}
|
||||
:on-press on-press}
|
||||
[rn/view
|
||||
{:style {:width width
|
||||
:height 230
|
||||
:border-radius 20}
|
||||
:on-press on-press}
|
||||
[rn/view
|
||||
{:flex 1}
|
||||
[rn/view (style/community-cover-container 40)
|
||||
@ -27,9 +27,10 @@
|
||||
;[communities.icon/community-icon-redesign community 48]]
|
||||
(when (= status :gated)
|
||||
[rn/view (style/permission-tag-styles)
|
||||
[community-view/permission-tag-container {:locked locked
|
||||
:status status
|
||||
:tokens tokens}]])
|
||||
[community-view/permission-tag-container
|
||||
{:locked locked
|
||||
:status status
|
||||
:tokens tokens}]])
|
||||
[community-view/community-title
|
||||
{:title name
|
||||
:description description}]
|
||||
|
@ -1,112 +1,131 @@
|
||||
(ns quo2.components.community.community-list-view
|
||||
(:require
|
||||
[quo2.components.community.community-view :as community-view]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[quo2.components.counter.counter :as counter]
|
||||
[quo2.components.icon :as icons]
|
||||
[quo2.components.community.style :as style]
|
||||
[react-native.fast-image :as fast-image]
|
||||
[react-native.core :as rn]))
|
||||
(:require [quo2.components.community.community-view :as community-view]
|
||||
[quo2.components.community.style :as style]
|
||||
[quo2.components.counter.counter :as counter]
|
||||
[quo2.components.icon :as icons]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[react-native.core :as rn]
|
||||
[react-native.fast-image :as fast-image]))
|
||||
|
||||
(defn community-icon-view [community-icon]
|
||||
[rn/view {:width 32
|
||||
:height 32}
|
||||
[fast-image/fast-image {:source {:uri community-icon}
|
||||
:style {:height 32
|
||||
:border-radius 16
|
||||
:width 32}}]])
|
||||
(defn community-icon-view
|
||||
[community-icon]
|
||||
[rn/view
|
||||
{:width 32
|
||||
:height 32}
|
||||
[fast-image/fast-image
|
||||
{:source {:uri community-icon}
|
||||
:style {:height 32
|
||||
:border-radius 16
|
||||
:width 32}}]])
|
||||
|
||||
(defn notification-view [{:keys [muted?
|
||||
unread-messages?
|
||||
unread-mentions-count]}]
|
||||
(defn notification-view
|
||||
[{:keys [muted?
|
||||
unread-messages?
|
||||
unread-mentions-count]}]
|
||||
(cond
|
||||
muted?
|
||||
[icons/icon :i/muted {:container-style {:align-items :center
|
||||
:justify-content :center}
|
||||
:resize-mode :center
|
||||
:size 20
|
||||
:color (colors/theme-colors
|
||||
colors/neutral-40
|
||||
colors/neutral-50)}]
|
||||
[icons/icon :i/muted
|
||||
{:container-style {:align-items :center
|
||||
:justify-content :center}
|
||||
:resize-mode :center
|
||||
:size 20
|
||||
:color (colors/theme-colors
|
||||
colors/neutral-40
|
||||
colors/neutral-50)}]
|
||||
(pos? unread-mentions-count)
|
||||
[counter/counter {:type :default} unread-mentions-count]
|
||||
|
||||
unread-messages?
|
||||
[rn/view {:style {:width 8
|
||||
:height 8
|
||||
:border-radius 4
|
||||
:background-color (colors/theme-colors
|
||||
colors/neutral-40
|
||||
colors/neutral-60)}}]))
|
||||
[rn/view
|
||||
{:style {:width 8
|
||||
:height 8
|
||||
:border-radius 4
|
||||
:background-color (colors/theme-colors
|
||||
colors/neutral-40
|
||||
colors/neutral-60)}}]))
|
||||
|
||||
(defn communities-list-view-item [props {:keys [name
|
||||
locked?
|
||||
status
|
||||
muted?
|
||||
unread-messages?
|
||||
unread-mentions-count
|
||||
community-icon
|
||||
tokens
|
||||
background-color]}]
|
||||
[rn/view {:style (merge (style/community-card 16)
|
||||
{:margin-bottom 12
|
||||
:margin-horizontal 20})}
|
||||
[rn/touchable-highlight (merge {:style {:height 56
|
||||
:border-radius 16}}
|
||||
props)
|
||||
(defn communities-list-view-item
|
||||
[props
|
||||
{:keys [name
|
||||
locked?
|
||||
status
|
||||
muted?
|
||||
unread-messages?
|
||||
unread-mentions-count
|
||||
community-icon
|
||||
tokens
|
||||
background-color]}]
|
||||
[rn/view
|
||||
{:style (merge (style/community-card 16)
|
||||
{:margin-bottom 12
|
||||
:margin-horizontal 20})}
|
||||
[rn/touchable-highlight
|
||||
(merge {:style {:height 56
|
||||
:border-radius 16}}
|
||||
props)
|
||||
[rn/view {:flex 1}
|
||||
[rn/view {:flex-direction :row
|
||||
:border-radius 16
|
||||
:padding-horizontal 12
|
||||
:align-items :center
|
||||
:padding-vertical 8
|
||||
:background-color background-color}
|
||||
[rn/view
|
||||
{:flex-direction :row
|
||||
:border-radius 16
|
||||
:padding-horizontal 12
|
||||
:align-items :center
|
||||
:padding-vertical 8
|
||||
:background-color background-color}
|
||||
[rn/view]
|
||||
(when community-icon
|
||||
[community-icon-view community-icon])
|
||||
[rn/view {:flex 1
|
||||
:margin-horizontal 12}
|
||||
[text/text {:weight :semi-bold
|
||||
:size :paragraph-1
|
||||
:accessibility-label :community-name-text
|
||||
:number-of-lines 1
|
||||
:ellipsize-mode :tail
|
||||
:style {:color (when muted?
|
||||
(colors/theme-colors
|
||||
colors/neutral-40
|
||||
colors/neutral-60))}}
|
||||
[rn/view
|
||||
{:flex 1
|
||||
:margin-horizontal 12}
|
||||
[text/text
|
||||
{:weight :semi-bold
|
||||
:size :paragraph-1
|
||||
:accessibility-label :community-name-text
|
||||
:number-of-lines 1
|
||||
:ellipsize-mode :tail
|
||||
:style {:color (when muted?
|
||||
(colors/theme-colors
|
||||
colors/neutral-40
|
||||
colors/neutral-60))}}
|
||||
name]
|
||||
[community-view/community-stats-column :list-view]]
|
||||
(if (= status :gated)
|
||||
[community-view/permission-tag-container {:locked? locked?
|
||||
:tokens tokens}]
|
||||
[notification-view {:muted? muted?
|
||||
:unread-mentions-count unread-mentions-count
|
||||
:unread-messages? unread-messages?}])]]]])
|
||||
[community-view/permission-tag-container
|
||||
{:locked? locked?
|
||||
:tokens tokens}]
|
||||
[notification-view
|
||||
{:muted? muted?
|
||||
:unread-mentions-count unread-mentions-count
|
||||
:unread-messages? unread-messages?}])]]]])
|
||||
|
||||
(defn communities-membership-list-item [props {:keys [name
|
||||
muted?
|
||||
unread-messages?
|
||||
unread-mentions-count
|
||||
status
|
||||
community-icon
|
||||
tokens
|
||||
locked?]}]
|
||||
(defn communities-membership-list-item
|
||||
[props
|
||||
{:keys [name
|
||||
muted?
|
||||
unread-messages?
|
||||
unread-mentions-count
|
||||
status
|
||||
community-icon
|
||||
tokens
|
||||
locked?]}]
|
||||
[rn/view {:margin-bottom 20}
|
||||
[rn/touchable-highlight (merge {:underlay-color colors/primary-50-opa-5
|
||||
:style {:border-radius 12}}
|
||||
props)
|
||||
[rn/touchable-highlight
|
||||
(merge {:underlay-color colors/primary-50-opa-5
|
||||
:style {:border-radius 12}}
|
||||
props)
|
||||
[rn/view {:flex 1}
|
||||
[rn/view {:flex-direction :row
|
||||
:border-radius 16
|
||||
:align-items :center}
|
||||
[rn/view
|
||||
{:flex-direction :row
|
||||
:border-radius 16
|
||||
:align-items :center}
|
||||
|
||||
(when community-icon
|
||||
[community-icon-view community-icon])
|
||||
[rn/view {:flex 1
|
||||
:margin-left 12
|
||||
:justify-content :center}
|
||||
[rn/view
|
||||
{:flex 1
|
||||
:margin-left 12
|
||||
:justify-content :center}
|
||||
[text/text
|
||||
{:accessibility-label :chat-name-text
|
||||
:number-of-lines 1
|
||||
@ -115,11 +134,14 @@
|
||||
:size :paragraph-1}
|
||||
name]]
|
||||
|
||||
[rn/view {:justify-content :center
|
||||
:margin-right 16}
|
||||
[rn/view
|
||||
{:justify-content :center
|
||||
:margin-right 16}
|
||||
(if (= status :gated)
|
||||
[community-view/permission-tag-container {:locked? locked?
|
||||
:tokens tokens}]
|
||||
[notification-view {:muted? muted?
|
||||
:unread-mentions-count unread-mentions-count
|
||||
:unread-messages? unread-messages?}])]]]]])
|
||||
[community-view/permission-tag-container
|
||||
{:locked? locked?
|
||||
:tokens tokens}]
|
||||
[notification-view
|
||||
{:muted? muted?
|
||||
:unread-mentions-count unread-mentions-count
|
||||
:unread-messages? unread-messages?}])]]]]])
|
||||
|
@ -1,38 +1,46 @@
|
||||
(ns quo2.components.community.community-view
|
||||
(:require
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.components.icon :as icons]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[quo2.components.tags.permission-tag :as permission]
|
||||
[quo2.components.tags.tag :as tag]
|
||||
[quo2.components.community.style :as style]
|
||||
[react-native.core :as rn]))
|
||||
(:require [quo2.components.community.style :as style]
|
||||
[quo2.components.icon :as icons]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.components.tags.permission-tag :as permission]
|
||||
[quo2.components.tags.tag :as tag]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(defn community-stats [{:keys [icon members-count icon-color]}]
|
||||
(defn community-stats
|
||||
[{:keys [icon members-count icon-color]}]
|
||||
[rn/view (style/stats-count-container)
|
||||
[rn/view {:margin-right 4}
|
||||
[icons/icon icon {:container-style {:align-items :center
|
||||
:justify-content :center}
|
||||
:resize-mode :center
|
||||
:size 16
|
||||
:color icon-color}]]
|
||||
[text/text {:weight :regular
|
||||
:size :paragraph-1}
|
||||
[icons/icon icon
|
||||
{:container-style {:align-items :center
|
||||
:justify-content :center}
|
||||
:resize-mode :center
|
||||
:size 16
|
||||
:color icon-color}]]
|
||||
[text/text
|
||||
{:weight :regular
|
||||
:size :paragraph-1}
|
||||
members-count]])
|
||||
|
||||
(defn community-stats-column [type]
|
||||
(defn community-stats-column
|
||||
[type]
|
||||
(let [icon-color (colors/theme-colors colors/neutral-50 colors/neutral-40)]
|
||||
[rn/view (if (= type :card-view)
|
||||
(style/card-stats-container)
|
||||
(style/list-stats-container))
|
||||
[community-stats {:icon :i/group
|
||||
:members-count "629.2K" ;;TODO here should be formatted value, use money/format-members from outside this component
|
||||
:icon-color icon-color}]
|
||||
[community-stats {:icon :i/lightning
|
||||
:members-count "112.1K"
|
||||
:icon-color icon-color}]]))
|
||||
[rn/view
|
||||
(if (= type :card-view)
|
||||
(style/card-stats-container)
|
||||
(style/list-stats-container))
|
||||
[community-stats
|
||||
{:icon :i/group
|
||||
:members-count "629.2K" ;;TODO here should be formatted value, use money/format-members from
|
||||
;;outside this component
|
||||
:icon-color icon-color}]
|
||||
[community-stats
|
||||
{:icon :i/lightning
|
||||
:members-count "112.1K"
|
||||
:icon-color icon-color}]]))
|
||||
|
||||
(defn community-tags [tags]
|
||||
(defn community-tags
|
||||
[tags]
|
||||
[rn/view (style/community-tags-container)
|
||||
(for [{:keys [id tag-label resource]} tags]
|
||||
^{:key id}
|
||||
@ -45,7 +53,8 @@
|
||||
:labelled true
|
||||
:resource resource}]])])
|
||||
|
||||
(defn community-title [{:keys [title description size] :or {size :small}}]
|
||||
(defn community-title
|
||||
[{:keys [title description size] :or {size :small}}]
|
||||
[rn/view (style/community-title-description-container (if (= size :large) 56 32))
|
||||
(when title
|
||||
[text/text
|
||||
@ -65,12 +74,14 @@
|
||||
:style {:margin-top (if (= size :large) 8 2)}}
|
||||
description])])
|
||||
|
||||
(defn permission-tag-container [{:keys [locked? tokens on-press]}]
|
||||
[permission/tag {:background-color (colors/theme-colors
|
||||
colors/neutral-10
|
||||
colors/neutral-80)
|
||||
:locked? locked?
|
||||
:tokens tokens
|
||||
(defn permission-tag-container
|
||||
[{:keys [locked? tokens on-press]}]
|
||||
[permission/tag
|
||||
{:background-color (colors/theme-colors
|
||||
colors/neutral-10
|
||||
colors/neutral-80)
|
||||
:locked? locked?
|
||||
:tokens tokens
|
||||
|
||||
:size 24
|
||||
:on-press on-press}])
|
||||
:size 24
|
||||
:on-press on-press}])
|
||||
|
@ -1,94 +1,107 @@
|
||||
(ns quo2.components.community.discover-card
|
||||
(:require [quo2.components.markdown.text :as text]
|
||||
(:require [quo2.components.community.style :as style]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[quo2.components.community.style :as style]
|
||||
[react-native.core :as rn]))
|
||||
|
||||
;; Discover card placeholders images.
|
||||
;; TODO replaced when real data is available
|
||||
(def images
|
||||
{:images [{:id 1 :column-images [{:id 1 :image ""}]}
|
||||
{:images [{:id 1 :column-images [{:id 1 :image ""}]}
|
||||
{:id 2 :column-images [{}]}]})
|
||||
|
||||
(defn card-title-and-description [title description]
|
||||
(defn card-title-and-description
|
||||
[title description]
|
||||
[rn/view
|
||||
{:flex 1
|
||||
:padding-top 8
|
||||
:padding-bottom 8
|
||||
:border-radius 12}
|
||||
[rn/view {:flex 1
|
||||
:padding-horizontal 12}
|
||||
[text/text {:accessibility-label :community-name-text
|
||||
:ellipsize-mode :tail
|
||||
:number-of-lines 1
|
||||
:weight :semi-bold
|
||||
:size :paragraph-1}
|
||||
{:flex 1
|
||||
:padding-top 8
|
||||
:padding-bottom 8
|
||||
:border-radius 12}
|
||||
[rn/view
|
||||
{:flex 1
|
||||
:padding-horizontal 12}
|
||||
[text/text
|
||||
{:accessibility-label :community-name-text
|
||||
:ellipsize-mode :tail
|
||||
:number-of-lines 1
|
||||
:weight :semi-bold
|
||||
:size :paragraph-1}
|
||||
title]
|
||||
[text/text {:accessibility-label :community-name-text
|
||||
:ellipsize-mode :tail
|
||||
:number-of-lines 1
|
||||
:color (colors/theme-colors
|
||||
colors/neutral-50
|
||||
colors/neutral-40)
|
||||
:weight :regular
|
||||
:size :paragraph-2}
|
||||
[text/text
|
||||
{:accessibility-label :community-name-text
|
||||
:ellipsize-mode :tail
|
||||
:number-of-lines 1
|
||||
:color (colors/theme-colors
|
||||
colors/neutral-50
|
||||
colors/neutral-40)
|
||||
:weight :regular
|
||||
:size :paragraph-2}
|
||||
description]]])
|
||||
|
||||
(defn placeholder-list-images [{:keys [images width height border-radius]}]
|
||||
(defn placeholder-list-images
|
||||
[{:keys [images width height border-radius]}]
|
||||
[rn/view
|
||||
[rn/view {:justify-content :center}
|
||||
[rn/view {:justify-content :center}
|
||||
(for [{:keys [id]} images]
|
||||
^{:key id}
|
||||
[rn/view {:border-radius border-radius
|
||||
:margin-top 4
|
||||
:margin-right 4
|
||||
:width width
|
||||
:height height
|
||||
:background-color colors/neutral-10}])]])
|
||||
[rn/view
|
||||
{:border-radius border-radius
|
||||
:margin-top 4
|
||||
:margin-right 4
|
||||
:width width
|
||||
:height height
|
||||
:background-color colors/neutral-10}])]])
|
||||
|
||||
(defn placeholder-row-images [{:keys [first-image last-image images width height
|
||||
border-radius]}]
|
||||
(defn placeholder-row-images
|
||||
[{:keys [first-image last-image images width height
|
||||
border-radius]}]
|
||||
[rn/view
|
||||
(when first-image
|
||||
[rn/view {:border-bottom-right-radius 6
|
||||
:border-bottom-left-radius 6
|
||||
:margin-right 4
|
||||
:width width
|
||||
:height height
|
||||
:background-color colors/neutral-10}])
|
||||
[rn/view
|
||||
{:border-bottom-right-radius 6
|
||||
:border-bottom-left-radius 6
|
||||
:margin-right 4
|
||||
:width width
|
||||
:height height
|
||||
:background-color colors/neutral-10}])
|
||||
(when images
|
||||
[placeholder-list-images {:images images
|
||||
:width 32
|
||||
:height 32
|
||||
:border-radius 6}])
|
||||
[placeholder-list-images
|
||||
{:images images
|
||||
:width 32
|
||||
:height 32
|
||||
:border-radius 6}])
|
||||
(when last-image
|
||||
[rn/view {:border-top-left-radius border-radius
|
||||
:border-top-right-radius 6
|
||||
:margin-top 4
|
||||
:width width
|
||||
:height height
|
||||
:background-color colors/neutral-10}])])
|
||||
[rn/view
|
||||
{:border-top-left-radius border-radius
|
||||
:border-top-right-radius 6
|
||||
:margin-top 4
|
||||
:width width
|
||||
:height height
|
||||
:background-color colors/neutral-10}])])
|
||||
|
||||
(defn discover-card [{:keys [title description on-press accessibility-label]}]
|
||||
(let [on-joined-images (get images :images)]
|
||||
(defn discover-card
|
||||
[{:keys [title description on-press accessibility-label]}]
|
||||
(let [on-joined-images (get images :images)]
|
||||
[rn/touchable-without-feedback
|
||||
{:on-press on-press
|
||||
:accessibility-label accessibility-label}
|
||||
[rn/view (merge (style/community-card 16)
|
||||
{:background-color (colors/theme-colors
|
||||
colors/white
|
||||
colors/neutral-90)}
|
||||
{:flex-direction :row
|
||||
:margin-horizontal 20
|
||||
:height 56
|
||||
:padding-right 12})
|
||||
[rn/view
|
||||
(merge (style/community-card 16)
|
||||
{:background-color (colors/theme-colors
|
||||
colors/white
|
||||
colors/neutral-90)}
|
||||
{:flex-direction :row
|
||||
:margin-horizontal 20
|
||||
:height 56
|
||||
:padding-right 12})
|
||||
[card-title-and-description title description]
|
||||
(for [{:keys [id column-images]} on-joined-images]
|
||||
^{:key id}
|
||||
[placeholder-row-images {:images (when (= id 1)
|
||||
column-images)
|
||||
:width 32
|
||||
:height (if (= id 1) 8 26)
|
||||
:border-radius 6
|
||||
:first-image "" ; TODO replace with real data
|
||||
:last-image ""}])]])) ; TODO replace with real data
|
||||
[placeholder-row-images
|
||||
{:images (when (= id 1)
|
||||
column-images)
|
||||
:width 32
|
||||
:height (if (= id 1) 8 26)
|
||||
:border-radius 6
|
||||
:first-image "" ; TODO replace with real data
|
||||
:last-image ""}])]])) ; TODO replace with real data
|
||||
|
@ -8,57 +8,66 @@
|
||||
:height 52
|
||||
:padding-left 18})
|
||||
|
||||
(defn community-card [radius]
|
||||
{:shadow-offset {:width 0
|
||||
(defn community-card
|
||||
[radius]
|
||||
{:shadow-offset {:width 0
|
||||
:height 2}
|
||||
:shadow-radius radius
|
||||
:shadow-opacity 1
|
||||
:shadow-color colors/shadow
|
||||
:border-radius radius
|
||||
:justify-content :space-between
|
||||
:elevation 2
|
||||
:background-color (colors/theme-colors
|
||||
colors/white
|
||||
colors/neutral-90)})
|
||||
|
||||
(defn stats-count-container []
|
||||
{:flex-direction :row
|
||||
:align-items :center
|
||||
:margin-right 16})
|
||||
|
||||
(defn card-stats-container []
|
||||
{:flex-direction :row})
|
||||
|
||||
(defn list-stats-container []
|
||||
{:flex-direction :row
|
||||
:align-items :center})
|
||||
|
||||
(defn community-tags-container []
|
||||
{:flex-direction :row})
|
||||
|
||||
(defn card-stats-position []
|
||||
{:position :absolute
|
||||
:top 116
|
||||
:right 12
|
||||
:left 12})
|
||||
|
||||
(defn community-tags-position []
|
||||
{:position :absolute
|
||||
:top 154
|
||||
:right 12
|
||||
:left 12})
|
||||
|
||||
(defn card-view-content-container [padding-horizontal]
|
||||
{:flex 1
|
||||
:height 20
|
||||
:padding-left padding-horizontal
|
||||
:padding-right padding-horizontal
|
||||
:border-radius 16
|
||||
:shadow-radius radius
|
||||
:shadow-opacity 1
|
||||
:shadow-color colors/shadow
|
||||
:border-radius radius
|
||||
:justify-content :space-between
|
||||
:elevation 2
|
||||
:background-color (colors/theme-colors
|
||||
colors/white
|
||||
colors/neutral-90)})
|
||||
|
||||
(defn card-view-chat-icon [icon-size]
|
||||
(defn stats-count-container
|
||||
[]
|
||||
{:flex-direction :row
|
||||
:align-items :center
|
||||
:margin-right 16})
|
||||
|
||||
(defn card-stats-container
|
||||
[]
|
||||
{:flex-direction :row})
|
||||
|
||||
(defn list-stats-container
|
||||
[]
|
||||
{:flex-direction :row
|
||||
:align-items :center})
|
||||
|
||||
(defn community-tags-container
|
||||
[]
|
||||
{:flex-direction :row})
|
||||
|
||||
(defn card-stats-position
|
||||
[]
|
||||
{:position :absolute
|
||||
:top 116
|
||||
:right 12
|
||||
:left 12})
|
||||
|
||||
(defn community-tags-position
|
||||
[]
|
||||
{:position :absolute
|
||||
:top 154
|
||||
:right 12
|
||||
:left 12})
|
||||
|
||||
(defn card-view-content-container
|
||||
[padding-horizontal]
|
||||
{:flex 1
|
||||
:height 20
|
||||
:padding-left padding-horizontal
|
||||
:padding-right padding-horizontal
|
||||
:border-radius 16
|
||||
:background-color (colors/theme-colors
|
||||
colors/white
|
||||
colors/neutral-90)})
|
||||
|
||||
(defn card-view-chat-icon
|
||||
[icon-size]
|
||||
{:border-radius 48
|
||||
:position :absolute
|
||||
:top (- (/ icon-size 2))
|
||||
@ -68,29 +77,34 @@
|
||||
colors/white
|
||||
colors/neutral-90)})
|
||||
|
||||
(defn list-view-content-container []
|
||||
{:flex-direction :row
|
||||
:border-radius 16
|
||||
:align-items :center
|
||||
(defn list-view-content-container
|
||||
[]
|
||||
{:flex-direction :row
|
||||
:border-radius 16
|
||||
:align-items :center
|
||||
:background-color (colors/theme-colors
|
||||
colors/white
|
||||
colors/neutral-90)})
|
||||
|
||||
(defn list-view-chat-icon []
|
||||
{:border-radius 32
|
||||
:padding 12})
|
||||
(defn list-view-chat-icon
|
||||
[]
|
||||
{:border-radius 32
|
||||
:padding 12})
|
||||
|
||||
(defn community-title-description-container [margin-top]
|
||||
(defn community-title-description-container
|
||||
[margin-top]
|
||||
{:margin-top margin-top})
|
||||
|
||||
(defn community-cover-container [height]
|
||||
(defn community-cover-container
|
||||
[height]
|
||||
{:flex-direction :row
|
||||
:height height
|
||||
:border-top-right-radius 20
|
||||
:border-top-left-radius 20
|
||||
:background-color colors/primary-50-opa-20})
|
||||
|
||||
(defn permission-tag-styles []
|
||||
{:position :absolute
|
||||
:top 8
|
||||
:right 8})
|
||||
(defn permission-tag-styles
|
||||
[]
|
||||
{:position :absolute
|
||||
:top 8
|
||||
:right 8})
|
@ -13,75 +13,83 @@
|
||||
(def ^:private token-tag-horizontal-spacing 7)
|
||||
(def token-tag-vertical-spacing 5)
|
||||
|
||||
(def styles {:container {:flex 1
|
||||
:padding-horizontal 20}
|
||||
:header-container {:flex-direction :row
|
||||
:align-items :center}
|
||||
:header-spacing-community {:margin-bottom 16}
|
||||
:header-spacing-channel {:margin-bottom 24}
|
||||
:header-avatar {:margin-right 8}
|
||||
:header-community-avatar-image {:width 32 :height 32}
|
||||
:header-title-container {:flex 1
|
||||
:flex-direction :row
|
||||
:align-items :center}
|
||||
:header-title-lock {:margin-left 6}
|
||||
:header-info-button {:margin-left 8}
|
||||
:token-requirement-text-spacing {:margin-vertical 8}
|
||||
:token-requirement-list-spacing {:padding-vertical (- 8 token-tag-vertical-spacing)}
|
||||
:token-row {:flex-direction :row
|
||||
:flex-wrap :wrap
|
||||
:align-items :center}
|
||||
:token-row-container {:flex-direction :row
|
||||
:align-items :center
|
||||
:margin-horizontal (- token-tag-horizontal-spacing)}
|
||||
:token-row-container-no-shift {:margin-left 0}
|
||||
:token-row-or-text {:margin-right 3}
|
||||
:token-tag-spacing {:margin-horizontal token-tag-horizontal-spacing
|
||||
:margin-vertical token-tag-vertical-spacing}
|
||||
:divider {:height 1
|
||||
:margin-horizontal -20
|
||||
:margin-top (- 12 token-tag-vertical-spacing)
|
||||
:margin-bottom 8}
|
||||
:membership-request-denied {:margin-top 13}
|
||||
:enter-button {:margin-top 16}
|
||||
:info-text {:margin-top 12
|
||||
:text-align :center
|
||||
:padding-horizontal 20}})
|
||||
(def styles
|
||||
{:container {:flex 1
|
||||
:padding-horizontal 20}
|
||||
:header-container {:flex-direction :row
|
||||
:align-items :center}
|
||||
:header-spacing-community {:margin-bottom 16}
|
||||
:header-spacing-channel {:margin-bottom 24}
|
||||
:header-avatar {:margin-right 8}
|
||||
:header-community-avatar-image {:width 32 :height 32}
|
||||
:header-title-container {:flex 1
|
||||
:flex-direction :row
|
||||
:align-items :center}
|
||||
:header-title-lock {:margin-left 6}
|
||||
:header-info-button {:margin-left 8}
|
||||
:token-requirement-text-spacing {:margin-vertical 8}
|
||||
:token-requirement-list-spacing {:padding-vertical (- 8 token-tag-vertical-spacing)}
|
||||
:token-row {:flex-direction :row
|
||||
:flex-wrap :wrap
|
||||
:align-items :center}
|
||||
:token-row-container {:flex-direction :row
|
||||
:align-items :center
|
||||
:margin-horizontal (- token-tag-horizontal-spacing)}
|
||||
:token-row-container-no-shift {:margin-left 0}
|
||||
:token-row-or-text {:margin-right 3}
|
||||
:token-tag-spacing {:margin-horizontal token-tag-horizontal-spacing
|
||||
:margin-vertical token-tag-vertical-spacing}
|
||||
:divider {:height 1
|
||||
:margin-horizontal -20
|
||||
:margin-top (- 12 token-tag-vertical-spacing)
|
||||
:margin-bottom 8}
|
||||
:membership-request-denied {:margin-top 13}
|
||||
:enter-button {:margin-top 16}
|
||||
:info-text {:margin-top 12
|
||||
:text-align :center
|
||||
:padding-horizontal 20}})
|
||||
|
||||
(defn multiple-token-requirements? [token-requirement-lists]
|
||||
(defn multiple-token-requirements?
|
||||
[token-requirement-lists]
|
||||
(when (vector? (first token-requirement-lists))
|
||||
(> (count token-requirement-lists) 1)))
|
||||
|
||||
(defn is-token-requirement-met? [token-requirement-list]
|
||||
(defn is-token-requirement-met?
|
||||
[token-requirement-list]
|
||||
(and (seq token-requirement-list)
|
||||
(every?
|
||||
(fn [token]
|
||||
(get token :is-sufficient?))
|
||||
token-requirement-list)))
|
||||
|
||||
(defn are-multiple-token-requirements-met? [token-requirement-lists]
|
||||
(defn are-multiple-token-requirements-met?
|
||||
[token-requirement-lists]
|
||||
(if (multiple-token-requirements? token-requirement-lists)
|
||||
(some is-token-requirement-met? token-requirement-lists)
|
||||
(is-token-requirement-met? token-requirement-lists)))
|
||||
|
||||
(defn token-requirement-list-row [tokens community-color]
|
||||
[rn/view {:style (merge
|
||||
(get styles :token-row)
|
||||
(get styles :token-requirement-list-spacing))}
|
||||
(defn token-requirement-list-row
|
||||
[tokens community-color]
|
||||
[rn/view
|
||||
{:style (merge
|
||||
(get styles :token-row)
|
||||
(get styles :token-requirement-list-spacing))}
|
||||
(map-indexed (fn [token-index token]
|
||||
(let [{:keys [token-img-src token amount is-sufficient? is-purchasable?]} token]
|
||||
^{:key token-index}
|
||||
[rn/view {:style (get styles :token-tag-spacing)}
|
||||
[token-tag/token-tag {:token token
|
||||
:value amount
|
||||
:size 24
|
||||
:border-color community-color
|
||||
:is-required is-sufficient?
|
||||
:is-purchasable is-purchasable?
|
||||
:token-img-src token-img-src}]]))
|
||||
[token-tag/token-tag
|
||||
{:token token
|
||||
:value amount
|
||||
:size 24
|
||||
:border-color community-color
|
||||
:is-required is-sufficient?
|
||||
:is-purchasable is-purchasable?
|
||||
:token-img-src token-img-src}]]))
|
||||
tokens)])
|
||||
|
||||
(defn token-requirement-list [props community-color]
|
||||
(defn token-requirement-list
|
||||
[props community-color]
|
||||
(let [{:keys [gate token-requirements-changed? required-tokens-lost?]} props
|
||||
[gate-type token-requirement-lists] gate
|
||||
multiple-token-requirements? (multiple-token-requirements? token-requirement-lists)
|
||||
@ -89,15 +97,17 @@
|
||||
you-must-hold-label (if (= gate-type :join)
|
||||
(cond
|
||||
token-requirements-changed? :t/you-must-now-hold
|
||||
required-tokens-lost? :t/you-must-always-hold
|
||||
:else :t/you-must-hold)
|
||||
required-tokens-lost? :t/you-must-always-hold
|
||||
:else :t/you-must-hold)
|
||||
:t/you-must-hold)
|
||||
message-label (cond
|
||||
(= gate-type :join)
|
||||
(cond
|
||||
token-requirements-changed? :t/community-join-requirements-changed
|
||||
required-tokens-lost? :t/community-join-requirements-tokens-lost
|
||||
:else (if is-sufficient? :t/community-join-requirements-met :t/community-join-requirements-not-met))
|
||||
required-tokens-lost? :t/community-join-requirements-tokens-lost
|
||||
:else (if is-sufficient?
|
||||
:t/community-join-requirements-met
|
||||
:t/community-join-requirements-not-met))
|
||||
(= gate-type :read)
|
||||
(if is-sufficient?
|
||||
:t/community-channel-read-requirements-met
|
||||
@ -108,12 +118,14 @@
|
||||
:t/community-channel-write-requirements-not-met))]
|
||||
[rn/view
|
||||
[rn/view {:style (get styles :token-requirement-text-spacing)}
|
||||
[text/text {:weight :medium
|
||||
:number-of-lines 1}
|
||||
[text/text
|
||||
{:weight :medium
|
||||
:number-of-lines 1}
|
||||
(i18n/label
|
||||
message-label)]
|
||||
[text/text {:size :paragraph-2
|
||||
:number-of-lines 1}
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
:number-of-lines 1}
|
||||
(i18n/label
|
||||
you-must-hold-label)]]
|
||||
|
||||
@ -121,22 +133,26 @@
|
||||
(map-indexed
|
||||
(fn [token-requirement-index tokens]
|
||||
^{:key token-requirement-index}
|
||||
[rn/view {:style (merge
|
||||
(get styles :token-row-container)
|
||||
(when-not (= token-requirement-index 0)
|
||||
(get styles :token-row-container-no-shift)))}
|
||||
[rn/view
|
||||
{:style (merge
|
||||
(get styles :token-row-container)
|
||||
(when-not (= token-requirement-index 0)
|
||||
(get styles :token-row-container-no-shift)))}
|
||||
(when-not (= token-requirement-index 0)
|
||||
[text/text {:style (get styles :token-row-or-text)
|
||||
:size :paragraph-2} "or"])
|
||||
[text/text
|
||||
{:style (get styles :token-row-or-text)
|
||||
:size :paragraph-2} "or"])
|
||||
[token-requirement-list-row tokens community-color]])
|
||||
token-requirement-lists)
|
||||
[rn/view {:style (get styles :token-row-container)}
|
||||
[token-requirement-list-row token-requirement-lists community-color]])]))
|
||||
|
||||
(defn is-community-locked? [community]
|
||||
(defn is-community-locked?
|
||||
[community]
|
||||
(not (are-multiple-token-requirements-met? (get-in community [:gates :join]))))
|
||||
|
||||
(defn is-channel-locked? [channel]
|
||||
(defn is-channel-locked?
|
||||
[channel]
|
||||
(not (are-multiple-token-requirements-met?
|
||||
(or (get-in channel [:gates :read])
|
||||
(get-in channel [:gates :write])))))
|
||||
@ -174,82 +190,98 @@
|
||||
membership-request-denied?
|
||||
token-requirements-changed?
|
||||
required-tokens-lost?
|
||||
gates]} (if (= type :community) community channel)
|
||||
gates]}
|
||||
(if (= type :community) community channel)
|
||||
locked? (if
|
||||
(= type :community)
|
||||
(= type :community)
|
||||
(is-community-locked? community)
|
||||
(is-channel-locked? channel))]
|
||||
|
||||
[rn/view {:style (merge (get styles :container) {:background-color (colors/theme-colors colors/white colors/neutral-90)})}
|
||||
[rn/view {:style (merge
|
||||
(get styles :header-container)
|
||||
(if
|
||||
(= type :community)
|
||||
(get styles :header-spacing-community)
|
||||
(get styles :header-spacing-channel)))}
|
||||
[rn/view
|
||||
{:style (merge (get styles :container)
|
||||
{:background-color (colors/theme-colors colors/white colors/neutral-90)})}
|
||||
[rn/view
|
||||
{:style (merge
|
||||
(get styles :header-container)
|
||||
(if
|
||||
(= type :community)
|
||||
(get styles :header-spacing-community)
|
||||
(get styles :header-spacing-channel)))}
|
||||
|
||||
[rn/view {:style (get styles :header-avatar)}
|
||||
(if (= type :community)
|
||||
[fast-image/fast-image {:source community-avatar-img-src
|
||||
:style (get styles :header-community-avatar-image)}]
|
||||
[fast-image/fast-image
|
||||
{:source community-avatar-img-src
|
||||
:style (get styles :header-community-avatar-image)}]
|
||||
|
||||
[channel-avatar/channel-avatar {:big? true
|
||||
:locked? locked?
|
||||
:emoji emoji
|
||||
:emoji-background-color emoji-background-color}])]
|
||||
[channel-avatar/channel-avatar
|
||||
{:big? true
|
||||
:locked? locked?
|
||||
:emoji emoji
|
||||
:emoji-background-color emoji-background-color}])]
|
||||
|
||||
[rn/view {:style (get styles :header-title-container)}
|
||||
[text/text {:weight :semi-bold
|
||||
:number-of-lines 1
|
||||
:size :heading-1
|
||||
:style (get styles :header-text)} (if (= type :community) name (str "# " name))]
|
||||
[text/text
|
||||
{:weight :semi-bold
|
||||
:number-of-lines 1
|
||||
:size :heading-1
|
||||
:style (get styles :header-text)} (if (= type :community) name (str "# " name))]
|
||||
|
||||
(when (= type :community)
|
||||
[icon/icon (if locked?
|
||||
:main-icons2/locked
|
||||
:main-icons2/unlocked)
|
||||
[icon/icon
|
||||
(if locked?
|
||||
:main-icons2/locked
|
||||
:main-icons2/unlocked)
|
||||
{:container-style (get styles :header-title-lock)
|
||||
:color (colors/theme-colors
|
||||
colors/neutral-50
|
||||
colors/neutral-40)}])]
|
||||
|
||||
[button/button {:type :outline
|
||||
:size 32
|
||||
:icon true
|
||||
:style (get styles :header-info-button)} :main-icons2/info]]
|
||||
[button/button
|
||||
{:type :outline
|
||||
:size 32
|
||||
:icon true
|
||||
:style (get styles :header-info-button)} :main-icons2/info]]
|
||||
|
||||
(map-indexed (fn [gate-index gate]
|
||||
^{:key gate-index}
|
||||
[:<>
|
||||
(when-not (= gate-index 0)
|
||||
[rn/view {:style (merge
|
||||
(get styles :divider)
|
||||
{:background-color (colors/theme-colors
|
||||
colors/neutral-10
|
||||
colors/neutral-80)})}])
|
||||
[token-requirement-list {:gate gate :token-requirements-changed? token-requirements-changed? :required-tokens-lost? required-tokens-lost?} community-color]])
|
||||
[rn/view
|
||||
{:style (merge
|
||||
(get styles :divider)
|
||||
{:background-color (colors/theme-colors
|
||||
colors/neutral-10
|
||||
colors/neutral-80)})}])
|
||||
[token-requirement-list
|
||||
{:gate gate
|
||||
:token-requirements-changed? token-requirements-changed?
|
||||
:required-tokens-lost? required-tokens-lost?} community-color]])
|
||||
gates)
|
||||
|
||||
(when (= type :channel)
|
||||
(if membership-request-denied?
|
||||
[information-box/information-box {:type :error
|
||||
:icon :main-icons2/untrustworthy
|
||||
:no-icon-color? true
|
||||
:style (get styles :membership-request-denied)}
|
||||
[information-box/information-box
|
||||
{:type :error
|
||||
:icon :main-icons2/untrustworthy
|
||||
:no-icon-color? true
|
||||
:style (get styles :membership-request-denied)}
|
||||
(i18n/label
|
||||
:t/membership-request-denied)]
|
||||
|
||||
[:<>
|
||||
[button/button {:type :community
|
||||
:community-color community-color
|
||||
:community-text-color community-text-color
|
||||
:style (get styles :enter-button)
|
||||
:disabled locked?
|
||||
:on-press on-enter-channel}
|
||||
(str "# " (i18n/label
|
||||
:t/enter-channel))]
|
||||
[button/button
|
||||
{:type :community
|
||||
:community-color community-color
|
||||
:community-text-color community-text-color
|
||||
:style (get styles :enter-button)
|
||||
:disabled locked?
|
||||
:on-press on-enter-channel}
|
||||
(str "# "
|
||||
(i18n/label
|
||||
:t/enter-channel))]
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
{:size :paragraph-2
|
||||
:style (merge
|
||||
(get styles :info-text)
|
||||
{:color (colors/theme-colors
|
||||
|
@ -7,28 +7,28 @@
|
||||
([]
|
||||
(render-counter {} nil))
|
||||
([opts value]
|
||||
(rtl/render (reagent/as-element [counter/counter opts value]))))
|
||||
(rtl/render (reagent/as-element [counter/counter opts value]))))
|
||||
|
||||
(js/global.test "default render of counter component"
|
||||
(fn []
|
||||
(render-counter)
|
||||
(-> (js/expect (rtl/screen.getByTestId "counter-component"))
|
||||
(-> (js/expect (rtl/screen.getByTestId "counter-component"))
|
||||
(.toBeTruthy))))
|
||||
|
||||
(js/global.test "renders counter with a string value"
|
||||
(fn []
|
||||
(render-counter {} "1")
|
||||
(-> (js/expect (rtl/screen.getByText "1"))
|
||||
(-> (js/expect (rtl/screen.getByText "1"))
|
||||
(.toBeTruthy))))
|
||||
|
||||
(js/global.test "renders counter with an integer value"
|
||||
(fn []
|
||||
(render-counter {} 1)
|
||||
(-> (js/expect (rtl/screen.getByText "1"))
|
||||
(-> (js/expect (rtl/screen.getByText "1"))
|
||||
(.toBeTruthy))))
|
||||
|
||||
(js/global.test "renders counter with value 99+ when the value is greater than 99"
|
||||
(fn []
|
||||
(render-counter {} "100")
|
||||
(-> (js/expect (rtl/screen.getByText "99+"))
|
||||
(-> (js/expect (rtl/screen.getByText "99+"))
|
||||
(.toBeTruthy))))
|
@ -1,20 +1,21 @@
|
||||
(ns quo2.components.counter.counter
|
||||
(:require [quo2.theme :as theme]
|
||||
[react-native.core :as rn]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.foundations.colors :as colors]))
|
||||
(:require [quo2.components.markdown.text :as text]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[quo2.theme :as theme]
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(def themes
|
||||
{:light {:default colors/primary-50
|
||||
:secondary colors/neutral-80-opa-5
|
||||
:grey colors/neutral-10
|
||||
:outline colors/neutral-20}
|
||||
:dark {:default colors/primary-60
|
||||
:secondary colors/white-opa-5
|
||||
:grey colors/neutral-70
|
||||
:outline colors/neutral-70}})
|
||||
{:light {:default colors/primary-50
|
||||
:secondary colors/neutral-80-opa-5
|
||||
:grey colors/neutral-10
|
||||
:outline colors/neutral-20}
|
||||
:dark {:default colors/primary-60
|
||||
:secondary colors/white-opa-5
|
||||
:grey colors/neutral-70
|
||||
:outline colors/neutral-70}})
|
||||
|
||||
(defn get-color [key]
|
||||
(defn get-color
|
||||
[key]
|
||||
(get-in themes [(theme/get-theme) key]))
|
||||
|
||||
(defn counter
|
||||
@ -35,30 +36,32 @@
|
||||
"99+"
|
||||
(str value))
|
||||
width (case (count label)
|
||||
1 16
|
||||
2 20
|
||||
1 16
|
||||
2 20
|
||||
28)]
|
||||
[rn/view {:test-ID :counter-component
|
||||
:accessible true
|
||||
:accessibility-label accessibility-label
|
||||
:style (cond-> (merge
|
||||
{:align-items :center
|
||||
:justify-content :center
|
||||
:border-radius 6
|
||||
:width width
|
||||
:height 16}
|
||||
style)
|
||||
(= type :outline)
|
||||
(merge {:border-width 1
|
||||
:border-color (get-color type)})
|
||||
[rn/view
|
||||
{:test-ID :counter-component
|
||||
:accessible true
|
||||
:accessibility-label accessibility-label
|
||||
:style (cond-> (merge
|
||||
{:align-items :center
|
||||
:justify-content :center
|
||||
:border-radius 6
|
||||
:width width
|
||||
:height 16}
|
||||
style)
|
||||
(= type :outline)
|
||||
(merge {:border-width 1
|
||||
:border-color (get-color type)})
|
||||
|
||||
(not= type :outline)
|
||||
(assoc :background-color
|
||||
(or override-bg-color
|
||||
(get-color type)))
|
||||
(not= type :outline)
|
||||
(assoc :background-color
|
||||
(or override-bg-color
|
||||
(get-color type)))
|
||||
|
||||
(> value 99)
|
||||
(assoc :padding-left 0.5))}
|
||||
[text/text {:weight :medium
|
||||
:size :label
|
||||
:style {:color text-color}} label]]))
|
||||
(> value 99)
|
||||
(assoc :padding-left 0.5))}
|
||||
[text/text
|
||||
{:weight :medium
|
||||
:size :label
|
||||
:style {:color text-color}} label]]))
|
||||
|
@ -1,18 +1,21 @@
|
||||
(ns quo2.components.dividers.date
|
||||
(:require [react-native.core :as rn]
|
||||
(:require [quo2.components.markdown.text :as text]
|
||||
[quo2.components.separator :as separator]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.foundations.colors :as colors]))
|
||||
[quo2.foundations.colors :as colors]
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(defn date [value]
|
||||
[rn/view {:margin-vertical 16
|
||||
:padding-right 8
|
||||
:padding-left 62}
|
||||
[text/text {:weight :medium
|
||||
:accessibility-label :divider-date-text
|
||||
:size :label
|
||||
:style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40)
|
||||
:text-transform :capitalize
|
||||
:margin-bottom 4}}
|
||||
(defn date
|
||||
[value]
|
||||
[rn/view
|
||||
{:margin-vertical 16
|
||||
:padding-right 8
|
||||
:padding-left 62}
|
||||
[text/text
|
||||
{:weight :medium
|
||||
:accessibility-label :divider-date-text
|
||||
:size :label
|
||||
:style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40)
|
||||
:text-transform :capitalize
|
||||
:margin-bottom 4}}
|
||||
value]
|
||||
[separator/separator]])
|
||||
|
@ -1,8 +1,8 @@
|
||||
(ns quo2.components.dividers.divider-label
|
||||
(:require [react-native.core :as rn]
|
||||
(:require [quo2.components.icon :as icons]
|
||||
[quo2.components.markdown.text :as markdown.text]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[quo2.components.icon :as icons]))
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(def chevron-icon-container-width 20)
|
||||
|
||||
@ -15,17 +15,20 @@
|
||||
increase-padding-top? -> boolean
|
||||
blur? -> boolean"
|
||||
[{:keys [label chevron-position counter-value increase-padding-top? blur?]}]
|
||||
(let [dark? (colors/dark?)
|
||||
border-and-counter-bg-color (if dark? (if blur? colors/white-opa-5 colors/neutral-70) colors/neutral-10)
|
||||
padding-top (if increase-padding-top? 16 8)
|
||||
text-and-icon-color (if dark? colors/neutral-40 colors/neutral-50)
|
||||
counter-text-color (if dark? colors/white colors/neutral-100)]
|
||||
[rn/view {:style {:border-top-width 1
|
||||
:border-top-color border-and-counter-bg-color
|
||||
:padding-top padding-top
|
||||
:padding-horizontal 16
|
||||
:align-items :center
|
||||
:flex-direction :row}}
|
||||
(let [dark? (colors/dark?)
|
||||
border-and-counter-bg-color (if dark?
|
||||
(if blur? colors/white-opa-5 colors/neutral-70)
|
||||
colors/neutral-10)
|
||||
padding-top (if increase-padding-top? 16 8)
|
||||
text-and-icon-color (if dark? colors/neutral-40 colors/neutral-50)
|
||||
counter-text-color (if dark? colors/white colors/neutral-100)]
|
||||
[rn/view
|
||||
{:style {:border-top-width 1
|
||||
:border-top-color border-and-counter-bg-color
|
||||
:padding-top padding-top
|
||||
:padding-horizontal 16
|
||||
:align-items :center
|
||||
:flex-direction :row}}
|
||||
(when (= chevron-position :left)
|
||||
[rn/view {:style {:margin-right 4}}
|
||||
[icons/icon
|
||||
@ -33,27 +36,30 @@
|
||||
{:color text-and-icon-color
|
||||
:width chevron-icon-container-width
|
||||
:height chevron-icon-container-height}]])
|
||||
[markdown.text/text {:size :paragraph-2
|
||||
:weight :medium
|
||||
:style {:color text-and-icon-color
|
||||
:flex 1}}
|
||||
[markdown.text/text
|
||||
{:size :paragraph-2
|
||||
:weight :medium
|
||||
:style {:color text-and-icon-color
|
||||
:flex 1}}
|
||||
label]
|
||||
(when (= chevron-position :right)
|
||||
[icons/icon
|
||||
:main-icons/chevron-down
|
||||
{:color text-and-icon-color
|
||||
{:color text-and-icon-color
|
||||
:size chevron-icon-container-width}])
|
||||
(when (pos? counter-value)
|
||||
[rn/view {:style {:border-radius 6
|
||||
:height 16
|
||||
:width (case (count counter-value)
|
||||
1 16
|
||||
2 20
|
||||
28)
|
||||
:background-color border-and-counter-bg-color
|
||||
:align-items :center
|
||||
:justify-content :center}}
|
||||
[markdown.text/text {:size :label
|
||||
:weight :medium
|
||||
:style {:color counter-text-color}}
|
||||
[rn/view
|
||||
{:style {:border-radius 6
|
||||
:height 16
|
||||
:width (case (count counter-value)
|
||||
1 16
|
||||
2 20
|
||||
28)
|
||||
:background-color border-and-counter-bg-color
|
||||
:align-items :center
|
||||
:justify-content :center}}
|
||||
[markdown.text/text
|
||||
{:size :label
|
||||
:weight :medium
|
||||
:style {:color counter-text-color}}
|
||||
counter-value]])]))
|
||||
|
@ -1,7 +1,7 @@
|
||||
(ns quo2.components.dividers.new-messages
|
||||
(:require [react-native.core :as rn]
|
||||
[quo2.components.markdown.text :as text]
|
||||
(:require [quo2.components.markdown.text :as text]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[react-native.core :as rn]
|
||||
[react-native.linear-gradient :as linear-gradient]))
|
||||
|
||||
(defn new-messages
|
||||
@ -9,11 +9,14 @@
|
||||
[{:keys [label color] :or {color :primary}}]
|
||||
(let [bg-color (colors/custom-color-by-theme color 50 60 5 5)
|
||||
text-color (colors/custom-color-by-theme color 50 60)]
|
||||
[linear-gradient/linear-gradient {:colors [bg-color "rgba(0,0,0,0)"]
|
||||
:start {:x 0 :y 0} :end {:x 0 :y 1}}
|
||||
[rn/view {:style {:padding-left 60
|
||||
:padding-vertical 12
|
||||
:padding-right 24}}
|
||||
[linear-gradient/linear-gradient
|
||||
{:colors [bg-color "rgba(0,0,0,0)"]
|
||||
:start {:x 0 :y 0}
|
||||
:end {:x 0 :y 1}}
|
||||
[rn/view
|
||||
{:style {:padding-left 60
|
||||
:padding-vertical 12
|
||||
:padding-right 24}}
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
:weight :medium
|
||||
|
@ -5,21 +5,21 @@
|
||||
|
||||
(defn render-action-drawer
|
||||
([options]
|
||||
(rtl/render (reagent/as-element [action-drawer/action-drawer options]))))
|
||||
(rtl/render (reagent/as-element [action-drawer/action-drawer options]))))
|
||||
|
||||
(js/global.test "action-drawer renders with elements label displaying"
|
||||
(fn []
|
||||
(render-action-drawer [[{:icon :i/friend
|
||||
:label "a sample label"}]])
|
||||
(-> (js/expect (rtl/screen.getByText "a sample label"))
|
||||
(render-action-drawer [[{:icon :i/friend
|
||||
:label "a sample label"}]])
|
||||
(-> (js/expect (rtl/screen.getByText "a sample label"))
|
||||
(.toBeTruthy))))
|
||||
|
||||
(js/global.test "action-drawer renders with elements sub-label displaying"
|
||||
(fn []
|
||||
(render-action-drawer [[{:icon :i/friend
|
||||
:label "a sample label"
|
||||
(render-action-drawer [[{:icon :i/friend
|
||||
:label "a sample label"
|
||||
:sub-label "a sample sub label"}]])
|
||||
(-> (js/expect (rtl/screen.getByText "a sample sub label"))
|
||||
(-> (js/expect (rtl/screen.getByText "a sample sub label"))
|
||||
(.toBeTruthy))))
|
||||
|
||||
(js/global.test "action-drawer on click action works on element"
|
||||
@ -29,14 +29,14 @@
|
||||
:label "a sample label"
|
||||
:on-press event}]])
|
||||
(rtl/fireEvent.press (rtl/screen.getByText "a sample label"))
|
||||
(-> (js/expect event)
|
||||
(-> (js/expect event)
|
||||
(.toHaveBeenCalled)))))
|
||||
|
||||
(js/global.test "action-drawer renders two icons when set"
|
||||
(fn []
|
||||
(render-action-drawer [[{:icon :i/friend
|
||||
:label "a sample label"
|
||||
:right-icon :i/friend
|
||||
(render-action-drawer [[{:icon :i/friend
|
||||
:label "a sample label"
|
||||
:right-icon :i/friend
|
||||
:accessibility-label :first-element}]])
|
||||
(-> (js/expect (rtl/screen.getByLabelText "right-icon-for-action"))
|
||||
(.toBeTruthy))
|
||||
@ -45,19 +45,19 @@
|
||||
|
||||
(js/global.test "action-drawer does not render a divider when the add-divider? prop is false"
|
||||
(fn []
|
||||
(render-action-drawer [[{:icon :i/friend
|
||||
:label "a sample label"
|
||||
:add-divider? false
|
||||
(render-action-drawer [[{:icon :i/friend
|
||||
:label "a sample label"
|
||||
:add-divider? false
|
||||
:accessibility-label :first-element}]])
|
||||
(-> (js/expect (rtl/screen.getAllByLabelText "divider"))
|
||||
(-> (js/expect (rtl/screen.getAllByLabelText "divider"))
|
||||
(.not)
|
||||
(.toBeTruthy))))
|
||||
|
||||
(js/global.test "action-drawer renders a divider when the add-divider? prop is true"
|
||||
(fn []
|
||||
(render-action-drawer [[{:icon :i/friend
|
||||
:label "a sample label"
|
||||
:add-divider? true
|
||||
(render-action-drawer [[{:icon :i/friend
|
||||
:label "a sample label"
|
||||
:add-divider? true
|
||||
:accessibility-label :first-element}]])
|
||||
(-> (js/expect (rtl/screen.getAllByLabelText "divider"))
|
||||
(-> (js/expect (rtl/screen.getAllByLabelText "divider"))
|
||||
(.toBeTruthy))))
|
@ -1,54 +1,62 @@
|
||||
(ns quo2.components.drawers.action-drawers
|
||||
(:require [react-native.core :as rn]
|
||||
(:require [quo2.components.icon :as icon]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.components.icon :as icon]
|
||||
[quo2.foundations.colors :as colors]))
|
||||
[quo2.foundations.colors :as colors]
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(defn- get-icon-color [danger?]
|
||||
(defn- get-icon-color
|
||||
[danger?]
|
||||
(if danger?
|
||||
colors/danger-50
|
||||
(colors/theme-colors colors/neutral-50 colors/neutral-40)))
|
||||
|
||||
(def divider
|
||||
[rn/view {:style {:border-top-width 1
|
||||
:border-top-color (colors/theme-colors
|
||||
colors/neutral-10 colors/neutral-90)
|
||||
:margin-top 8
|
||||
:margin-bottom 7
|
||||
:align-items :center
|
||||
:flex-direction :row}
|
||||
:accessible true
|
||||
:accessibility-label :divider}])
|
||||
[rn/view
|
||||
{:style {:border-top-width 1
|
||||
:border-top-color (colors/theme-colors
|
||||
colors/neutral-10
|
||||
colors/neutral-90)
|
||||
:margin-top 8
|
||||
:margin-bottom 7
|
||||
:align-items :center
|
||||
:flex-direction :row}
|
||||
:accessible true
|
||||
:accessibility-label :divider}])
|
||||
|
||||
(defn action [{:keys [icon
|
||||
label
|
||||
sub-label
|
||||
right-icon
|
||||
danger?
|
||||
on-press
|
||||
add-divider?
|
||||
accessibility-label] :as action-props}]
|
||||
(defn action
|
||||
[{:keys [icon
|
||||
label
|
||||
sub-label
|
||||
right-icon
|
||||
danger?
|
||||
on-press
|
||||
add-divider?
|
||||
accessibility-label]
|
||||
:as action-props}]
|
||||
(when action-props
|
||||
[:<> {:key label}
|
||||
(when add-divider? divider)
|
||||
[rn/touchable-highlight {:accessibility-label accessibility-label
|
||||
:style {:border-radius 12
|
||||
:height (if sub-label 58 50)
|
||||
:margin-horizontal 8}
|
||||
:underlay-color (colors/theme-colors colors/neutral-5 colors/neutral-90)
|
||||
:on-press on-press}
|
||||
[rn/view {:style
|
||||
{:height (if sub-label 58 50)
|
||||
:margin-horizontal 12
|
||||
:flex-direction :row}}
|
||||
[rn/view {:accessibility-label :left-icon-for-action
|
||||
:accessible true
|
||||
:style
|
||||
{:height 20
|
||||
:margin-top :auto
|
||||
:margin-bottom :auto
|
||||
:margin-right 12
|
||||
:width 20}}
|
||||
[rn/touchable-highlight
|
||||
{:accessibility-label accessibility-label
|
||||
:style {:border-radius 12
|
||||
:height (if sub-label 58 50)
|
||||
:margin-horizontal 8}
|
||||
:underlay-color (colors/theme-colors colors/neutral-5 colors/neutral-90)
|
||||
:on-press on-press}
|
||||
[rn/view
|
||||
{:style
|
||||
{:height (if sub-label 58 50)
|
||||
:margin-horizontal 12
|
||||
:flex-direction :row}}
|
||||
[rn/view
|
||||
{:accessibility-label :left-icon-for-action
|
||||
:accessible true
|
||||
:style
|
||||
{:height 20
|
||||
:margin-top :auto
|
||||
:margin-bottom :auto
|
||||
:margin-right 12
|
||||
:width 20}}
|
||||
[icon/icon icon
|
||||
{:color (get-icon-color danger?)
|
||||
:size 20}]]
|
||||
@ -70,18 +78,20 @@
|
||||
(colors/theme-colors colors/neutral-50 colors/neutral-40)}}
|
||||
sub-label])]
|
||||
(when right-icon
|
||||
[rn/view {:style
|
||||
{:height 20
|
||||
:margin-top :auto
|
||||
:margin-bottom :auto
|
||||
:width 20}
|
||||
:accessible true
|
||||
:accessibility-label :right-icon-for-action}
|
||||
[rn/view
|
||||
{:style
|
||||
{:height 20
|
||||
:margin-top :auto
|
||||
:margin-bottom :auto
|
||||
:width 20}
|
||||
:accessible true
|
||||
:accessibility-label :right-icon-for-action}
|
||||
[icon/icon right-icon
|
||||
{:color (get-icon-color danger?)
|
||||
:size 20}]])]]]))
|
||||
|
||||
(defn action-drawer [sections]
|
||||
(defn action-drawer
|
||||
[sections]
|
||||
[:<>
|
||||
(doall
|
||||
(for [actions sections]
|
||||
|
@ -1,97 +1,108 @@
|
||||
(ns quo2.components.dropdowns.dropdown
|
||||
(:require [react-native.core :as rn]
|
||||
[quo2.components.icon :as icons]
|
||||
(:require [quo2.components.icon :as icons]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[react-native.core :as rn]
|
||||
[react-native.reanimated :as reanimated]
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
(defn apply-anim [dd-height val]
|
||||
(defn apply-anim
|
||||
[dd-height val]
|
||||
(reanimated/animate-shared-value-with-delay dd-height
|
||||
val
|
||||
300
|
||||
:easing1
|
||||
0))
|
||||
|
||||
(def sizes {:big {:icon-size 20
|
||||
:font {:font-size :paragraph-1}
|
||||
:height 40
|
||||
:padding {:padding-with-icon {:padding-vertical 9
|
||||
:padding-horizontal 12}
|
||||
:padding-with-no-icon {:padding-vertical 9
|
||||
:padding-left 12
|
||||
:padding-right 8}}}
|
||||
:medium {:icon-size 20
|
||||
:font {:font-size :paragraph-1}
|
||||
:height 32
|
||||
:padding {:padding-with-icon {:padding-vertical 5
|
||||
:padding-horizontal 8}
|
||||
:padding-with-no-icon {:padding-vertical 5
|
||||
:padding-left 12
|
||||
:padding-right 8}}}
|
||||
:small {:icon-size 15
|
||||
:font {:font-size :paragraph-2}
|
||||
:height 24
|
||||
:padding {:padding-with-icon {:padding-vertical 3
|
||||
:padding-horizontal 6}
|
||||
:padding-with-no-icon {:padding-vertical 3
|
||||
:padding-horizontal 6}}}})
|
||||
(def sizes
|
||||
{:big {:icon-size 20
|
||||
:font {:font-size :paragraph-1}
|
||||
:height 40
|
||||
:padding {:padding-with-icon {:padding-vertical 9
|
||||
:padding-horizontal 12}
|
||||
:padding-with-no-icon {:padding-vertical 9
|
||||
:padding-left 12
|
||||
:padding-right 8}}}
|
||||
:medium {:icon-size 20
|
||||
:font {:font-size :paragraph-1}
|
||||
:height 32
|
||||
:padding {:padding-with-icon {:padding-vertical 5
|
||||
:padding-horizontal 8}
|
||||
:padding-with-no-icon {:padding-vertical 5
|
||||
:padding-left 12
|
||||
:padding-right 8}}}
|
||||
:small {:icon-size 15
|
||||
:font {:font-size :paragraph-2}
|
||||
:height 24
|
||||
:padding {:padding-with-icon {:padding-vertical 3
|
||||
:padding-horizontal 6}
|
||||
:padding-with-no-icon {:padding-vertical 3
|
||||
:padding-horizontal 6}}}})
|
||||
(defn color-by-10
|
||||
[color]
|
||||
(colors/alpha color 0.6))
|
||||
|
||||
(defn dropdown-comp [{:keys [icon open? dd-height size disabled? dd-color use-border? border-color]}]
|
||||
(defn dropdown-comp
|
||||
[{:keys [icon open? dd-height size disabled? dd-color use-border? border-color]}]
|
||||
(let [dark? (colors/dark?)
|
||||
{:keys [width height width-with-icon padding font icon-size]} (size sizes)
|
||||
{:keys [padding-with-icon padding-with-no-icon]} padding
|
||||
font-size (:font-size font)
|
||||
spacing (case size
|
||||
:big 4
|
||||
:big 4
|
||||
:medium 2
|
||||
:small 2)]
|
||||
[rn/touchable-opacity (cond-> {:on-press (fn []
|
||||
(if (swap! open? not)
|
||||
(apply-anim dd-height 120)
|
||||
(apply-anim dd-height 0)))
|
||||
:style (cond-> (merge
|
||||
(if icon
|
||||
padding-with-icon
|
||||
padding-with-no-icon)
|
||||
{:width (if icon
|
||||
width-with-icon
|
||||
width)
|
||||
:height height
|
||||
:border-radius (case size
|
||||
:big 12
|
||||
:medium 10
|
||||
:small 8)
|
||||
:flex-direction :row
|
||||
:align-items :center
|
||||
:background-color (if @open?
|
||||
dd-color
|
||||
(color-by-10 dd-color))})
|
||||
use-border? (assoc :border-width 1
|
||||
:border-color (if @open? border-color (color-by-10 border-color))))}
|
||||
disabled? (assoc-in [:style :opacity] 0.3)
|
||||
disabled? (assoc :disabled true))
|
||||
:small 2)]
|
||||
[rn/touchable-opacity
|
||||
(cond->
|
||||
{:on-press (fn []
|
||||
(if (swap! open? not)
|
||||
(apply-anim dd-height 120)
|
||||
(apply-anim dd-height 0)))
|
||||
:style (cond->
|
||||
(merge
|
||||
(if icon
|
||||
padding-with-icon
|
||||
padding-with-no-icon)
|
||||
{:width (if icon
|
||||
width-with-icon
|
||||
width)
|
||||
:height height
|
||||
:border-radius (case size
|
||||
:big 12
|
||||
:medium 10
|
||||
:small 8)
|
||||
:flex-direction :row
|
||||
:align-items :center
|
||||
:background-color (if @open?
|
||||
dd-color
|
||||
(color-by-10 dd-color))})
|
||||
use-border? (assoc :border-width 1
|
||||
:border-color (if @open?
|
||||
border-color
|
||||
(color-by-10 border-color))))}
|
||||
disabled? (assoc-in [:style :opacity] 0.3)
|
||||
disabled? (assoc :disabled true))
|
||||
(when icon
|
||||
[icons/icon icon {:no-color true
|
||||
:size 20
|
||||
:container-style {:margin-right spacing
|
||||
:margin-top 1
|
||||
:width icon-size
|
||||
:height icon-size}}])
|
||||
[text/text {:size font-size
|
||||
:weight :medium
|
||||
:font :font-medium
|
||||
:color :main} "Dropdown"]
|
||||
[icons/icon (if @open?
|
||||
(if dark?
|
||||
:main-icons/pullup-dark
|
||||
:main-icons/pullup)
|
||||
(if dark?
|
||||
:main-icons/dropdown-dark
|
||||
:main-icons/dropdown))
|
||||
[icons/icon icon
|
||||
{:no-color true
|
||||
:size 20
|
||||
:container-style {:margin-right spacing
|
||||
:margin-top 1
|
||||
:width icon-size
|
||||
:height icon-size}}])
|
||||
[text/text
|
||||
{:size font-size
|
||||
:weight :medium
|
||||
:font :font-medium
|
||||
:color :main} "Dropdown"]
|
||||
[icons/icon
|
||||
(if @open?
|
||||
(if dark?
|
||||
:main-icons/pullup-dark
|
||||
:main-icons/pullup)
|
||||
(if dark?
|
||||
:main-icons/dropdown-dark
|
||||
:main-icons/dropdown))
|
||||
{:size 20
|
||||
:no-color true
|
||||
:container-style {:width (+ icon-size 3)
|
||||
@ -105,9 +116,10 @@
|
||||
(defn items-comp
|
||||
[{:keys [items on-select]}]
|
||||
(let [items-count (count items)]
|
||||
[rn/scroll-view {:style {:height "100%"}
|
||||
:horizontal false
|
||||
:nestedScrollEnabled true}
|
||||
[rn/scroll-view
|
||||
{:style {:height "100%"}
|
||||
:horizontal false
|
||||
:nestedScrollEnabled true}
|
||||
(doall
|
||||
(map-indexed (fn [index item]
|
||||
[rn/touchable-opacity
|
||||
@ -121,27 +133,32 @@
|
||||
colors/white)
|
||||
:text-align :center}
|
||||
:on-press #(on-select item)}
|
||||
[text/text {:style {:text-align :center}} item]]) items))]))
|
||||
[text/text {:style {:text-align :center}} item]])
|
||||
items))]))
|
||||
|
||||
(defn dropdown [{:keys [items icon text default-item on-select size disabled? border-color use-border? dd-color]}]
|
||||
(defn dropdown
|
||||
[{:keys [items icon text default-item on-select size disabled? border-color use-border? dd-color]}]
|
||||
[:f>
|
||||
(fn []
|
||||
(let [open? (reagent/atom false)
|
||||
dd-height (reanimated/use-shared-value 0)]
|
||||
[rn/view {:style {:flex-grow 1}}
|
||||
[dropdown-comp {:items items
|
||||
:icon icon
|
||||
:disabled? disabled?
|
||||
:size size
|
||||
:dd-color dd-color
|
||||
:text text
|
||||
:border-color (colors/custom-color-by-theme border-color 50 60)
|
||||
:use-border? use-border?
|
||||
:default-item default-item
|
||||
:open? open?
|
||||
:dd-height dd-height}]
|
||||
[reanimated/view {:style (reanimated/apply-animations-to-style
|
||||
{:height dd-height}
|
||||
{:height dd-height})}
|
||||
[items-comp {:items items
|
||||
:on-select on-select}]]]))])
|
||||
[dropdown-comp
|
||||
{:items items
|
||||
:icon icon
|
||||
:disabled? disabled?
|
||||
:size size
|
||||
:dd-color dd-color
|
||||
:text text
|
||||
:border-color (colors/custom-color-by-theme border-color 50 60)
|
||||
:use-border? use-border?
|
||||
:default-item default-item
|
||||
:open? open?
|
||||
:dd-height dd-height}]
|
||||
[reanimated/view
|
||||
{:style (reanimated/apply-animations-to-style
|
||||
{:height dd-height}
|
||||
{:height dd-height})}
|
||||
[items-comp
|
||||
{:items items
|
||||
:on-select on-select}]]]))])
|
||||
|
@ -1,15 +1,16 @@
|
||||
(ns quo2.components.header
|
||||
(:require [oops.core :refer [oget]]
|
||||
[react-native.reanimated :as reanimated]
|
||||
[quo2.components.buttons.button :as button]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[react-native.core :as rn]
|
||||
[react-native.reanimated :as reanimated]
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
(def header-height 56)
|
||||
|
||||
(defn header-wrapper-style [{:keys [height border-bottom background]}]
|
||||
(defn header-wrapper-style
|
||||
[{:keys [height border-bottom background]}]
|
||||
(merge
|
||||
{:background-color (colors/theme-colors
|
||||
colors/neutral-5
|
||||
@ -23,32 +24,37 @@
|
||||
colors/neutral-5
|
||||
colors/neutral-95)})))
|
||||
|
||||
(def absolute-fill {:position :absolute
|
||||
:top 0
|
||||
:bottom 0
|
||||
:left 0
|
||||
:right 0})
|
||||
(def absolute-fill
|
||||
{:position :absolute
|
||||
:top 0
|
||||
:bottom 0
|
||||
:left 0
|
||||
:right 0})
|
||||
|
||||
(def content {:flex 1
|
||||
:flex-direction :row
|
||||
:align-items :center
|
||||
:justify-content :center})
|
||||
(def content
|
||||
{:flex 1
|
||||
:flex-direction :row
|
||||
:align-items :center
|
||||
:justify-content :center})
|
||||
|
||||
(def left {:position :absolute
|
||||
:left 0
|
||||
:top 0
|
||||
:bottom 0
|
||||
:justify-content :center
|
||||
:align-items :flex-start})
|
||||
(def left
|
||||
{:position :absolute
|
||||
:left 0
|
||||
:top 0
|
||||
:bottom 0
|
||||
:justify-content :center
|
||||
:align-items :flex-start})
|
||||
|
||||
(def right {:position :absolute
|
||||
:right 0
|
||||
:top 0
|
||||
:bottom 0
|
||||
:justify-content :center
|
||||
:align-items :flex-end})
|
||||
(def right
|
||||
{:position :absolute
|
||||
:right 0
|
||||
:top 0
|
||||
:bottom 0
|
||||
:justify-content :center
|
||||
:align-items :flex-end})
|
||||
|
||||
(defn title-style [{:keys [left right]} title-align]
|
||||
(defn title-style
|
||||
[{:keys [left right]} title-align]
|
||||
(merge
|
||||
absolute-fill
|
||||
(case title-align
|
||||
@ -69,57 +75,66 @@
|
||||
(def header-action-placeholder
|
||||
{:width 16})
|
||||
|
||||
(def element {:align-items :center
|
||||
:justify-content :center
|
||||
:flex 1})
|
||||
(def element
|
||||
{:align-items :center
|
||||
:justify-content :center
|
||||
:flex 1})
|
||||
|
||||
(defn header-action [{:keys [icon label on-press disabled accessibility-label]}]
|
||||
[button/button (merge {:on-press on-press
|
||||
:disabled disabled}
|
||||
(cond
|
||||
icon {:type :icon
|
||||
:theme :icon}
|
||||
label {:type :secondary})
|
||||
(when accessibility-label
|
||||
{:accessibility-label accessibility-label}))
|
||||
(defn header-action
|
||||
[{:keys [icon label on-press disabled accessibility-label]}]
|
||||
[button/button
|
||||
(merge {:on-press on-press
|
||||
:disabled disabled}
|
||||
(cond
|
||||
icon {:type :icon
|
||||
:theme :icon}
|
||||
label {:type :secondary})
|
||||
(when accessibility-label
|
||||
{:accessibility-label accessibility-label}))
|
||||
(cond
|
||||
icon icon
|
||||
label label)])
|
||||
|
||||
(defn header-actions [{:keys [accessories component]}]
|
||||
(defn header-actions
|
||||
[{:keys [accessories component]}]
|
||||
[rn/view {:style element}
|
||||
(cond
|
||||
(seq accessories)
|
||||
(into [rn/view {:style header-actions-style}]
|
||||
(map header-action accessories))
|
||||
|
||||
component component
|
||||
component component
|
||||
|
||||
:else
|
||||
[rn/view {:style header-action-placeholder}])])
|
||||
|
||||
(defn header-title [{:keys [title subtitle component title-align]}]
|
||||
(defn header-title
|
||||
[{:keys [title subtitle component title-align]}]
|
||||
[:<>
|
||||
(cond
|
||||
component component
|
||||
component component
|
||||
|
||||
(and title subtitle)
|
||||
[:<>
|
||||
[text/text {:weight :medium
|
||||
:number-of-lines 1}
|
||||
[text/text
|
||||
{:weight :medium
|
||||
:number-of-lines 1}
|
||||
title]
|
||||
[text/text {:weight :regular
|
||||
:color :secondary
|
||||
:number-of-lines 1}
|
||||
[text/text
|
||||
{:weight :regular
|
||||
:color :secondary
|
||||
:number-of-lines 1}
|
||||
subtitle]]
|
||||
|
||||
title [text/text {:weight :bold
|
||||
:number-of-lines 0
|
||||
:align title-align
|
||||
:size :large}
|
||||
title])])
|
||||
title [text/text
|
||||
{:weight :bold
|
||||
:number-of-lines 0
|
||||
:align title-align
|
||||
:size :large}
|
||||
title])])
|
||||
|
||||
(defn header [{:keys [left-width right-width]}]
|
||||
(defn header
|
||||
[{:keys [left-width right-width]}]
|
||||
(let [layout (reagent/atom {:left {:width (or left-width 8)
|
||||
:height header-height}
|
||||
:right {:width (or right-width 8)
|
||||
@ -131,46 +146,61 @@
|
||||
(let [width (oget evt "nativeEvent" "layout" "width")
|
||||
height (oget evt "nativeEvent" "layout" "height")]
|
||||
(when get-layout
|
||||
(get-layout el {:width width
|
||||
:height height}))
|
||||
(swap! layout assoc el {:width width
|
||||
:height height}))))]
|
||||
(fn [{:keys [left-accessories left-component border-bottom
|
||||
right-accessories right-component insets get-layout
|
||||
title subtitle title-component style title-align
|
||||
background]
|
||||
:or {title-align :center
|
||||
border-bottom false}}]
|
||||
(get-layout el
|
||||
{:width width
|
||||
:height height}))
|
||||
(swap! layout assoc
|
||||
el
|
||||
{:width width
|
||||
:height height}))))]
|
||||
(fn
|
||||
[{:keys [left-accessories left-component border-bottom
|
||||
right-accessories right-component insets get-layout
|
||||
title subtitle title-component style title-align
|
||||
background]
|
||||
:or {title-align :center
|
||||
border-bottom false}}]
|
||||
(let [status-bar-height (get insets :top 0)
|
||||
height (+ header-height status-bar-height)]
|
||||
[reanimated/view {:style (header-wrapper-style {:height height
|
||||
:background background
|
||||
:border-bottom border-bottom})}
|
||||
[rn/view {:pointer-events :box-none
|
||||
:height status-bar-height}]
|
||||
[rn/view {:style (merge {:height header-height}
|
||||
style)
|
||||
:pointer-events :box-none}
|
||||
[rn/view {:style absolute-fill
|
||||
:pointer-events :box-none}
|
||||
[rn/view {:style content
|
||||
:pointer-events :box-none}
|
||||
[rn/view {:style left
|
||||
:on-layout (handle-layout :left get-layout)
|
||||
:pointer-events :box-none}
|
||||
[header-actions {:accessories left-accessories
|
||||
:component left-component}]]
|
||||
[reanimated/view
|
||||
{:style (header-wrapper-style {:height height
|
||||
:background background
|
||||
:border-bottom border-bottom})}
|
||||
[rn/view
|
||||
{:pointer-events :box-none
|
||||
:height status-bar-height}]
|
||||
[rn/view
|
||||
{:style (merge {:height header-height}
|
||||
style)
|
||||
:pointer-events :box-none}
|
||||
[rn/view
|
||||
{:style absolute-fill
|
||||
:pointer-events :box-none}
|
||||
[rn/view
|
||||
{:style content
|
||||
:pointer-events :box-none}
|
||||
[rn/view
|
||||
{:style left
|
||||
:on-layout (handle-layout :left get-layout)
|
||||
:pointer-events :box-none}
|
||||
[header-actions
|
||||
{:accessories left-accessories
|
||||
:component left-component}]]
|
||||
|
||||
[rn/view {:style (title-style @layout title-align)
|
||||
:on-layout (handle-layout :title get-layout)
|
||||
:pointer-events :box-none}
|
||||
[header-title {:title title
|
||||
:subtitle subtitle
|
||||
:title-align title-align
|
||||
:component title-component}]]
|
||||
[rn/view
|
||||
{:style (title-style @layout title-align)
|
||||
:on-layout (handle-layout :title get-layout)
|
||||
:pointer-events :box-none}
|
||||
[header-title
|
||||
{:title title
|
||||
:subtitle subtitle
|
||||
:title-align title-align
|
||||
:component title-component}]]
|
||||
|
||||
[rn/view {:style right
|
||||
:on-layout (handle-layout :right get-layout)
|
||||
:pointer-events :box-none}
|
||||
[header-actions {:accessories right-accessories
|
||||
:component right-component}]]]]]]))))
|
||||
[rn/view
|
||||
{:style right
|
||||
:on-layout (handle-layout :right get-layout)
|
||||
:pointer-events :box-none}
|
||||
[header-actions
|
||||
{:accessories right-accessories
|
||||
:component right-component}]]]]]]))))
|
||||
|
@ -1,15 +1,15 @@
|
||||
(ns quo2.components.icon
|
||||
(:require
|
||||
[clojure.string :as string]
|
||||
[react-native.core :as rn]
|
||||
[quo2.components.icons.icons :as icons]
|
||||
[quo2.foundations.colors :as colors]))
|
||||
(:require [clojure.string :as string]
|
||||
[quo2.components.icons.icons :as icons]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(defn memo-icon-fn
|
||||
([icon-name] (memo-icon-fn icon-name nil))
|
||||
([icon-name {:keys [color container-style size
|
||||
accessibility-label no-color]
|
||||
:or {accessibility-label :icon}}]
|
||||
([icon-name
|
||||
{:keys [color container-style size
|
||||
accessibility-label no-color]
|
||||
:or {accessibility-label :icon}}]
|
||||
(let [size (or size 20)]
|
||||
^{:key icon-name}
|
||||
[rn/image
|
||||
|
@ -4,12 +4,14 @@
|
||||
|
||||
(def icon-path "./resources/images/icons2/")
|
||||
|
||||
(defn combine-path [path el]
|
||||
(defn combine-path
|
||||
[path el]
|
||||
(if (System/getenv "COMPONENT_TEST")
|
||||
(str "." path el "@2x.png")
|
||||
(str "." path el ".png")))
|
||||
|
||||
(defn require-icon [size path]
|
||||
(defn require-icon
|
||||
[size path]
|
||||
(fn [el]
|
||||
(let [s (combine-path path el)
|
||||
k (-> el
|
||||
@ -19,18 +21,21 @@
|
||||
(str size))]
|
||||
[k `(js/require ~s)])))
|
||||
|
||||
(defn get-files [path]
|
||||
(defn get-files
|
||||
[path]
|
||||
(->> (io/file path)
|
||||
file-seq
|
||||
(filter #(string/ends-with? % "png"))
|
||||
(map #(first (string/split (.getName %) #"@")))
|
||||
distinct))
|
||||
|
||||
(defn get-icons [size]
|
||||
(defn get-icons
|
||||
[size]
|
||||
(let [path (str icon-path size "x" size "/")]
|
||||
(into {} (map (require-icon size path) (get-files path)))))
|
||||
|
||||
(defmacro resolve-icons []
|
||||
(defmacro resolve-icons
|
||||
[]
|
||||
(merge
|
||||
(get-icons 12)
|
||||
(get-icons 16)
|
||||
|
@ -4,7 +4,8 @@
|
||||
|
||||
(def icons (icons/resolve-icons))
|
||||
|
||||
(defn icon-source [icon]
|
||||
(defn icon-source
|
||||
[icon]
|
||||
(if-let [icon (get icons (name icon))]
|
||||
icon
|
||||
(do
|
||||
|
@ -1,19 +1,20 @@
|
||||
(ns quo2.components.info.info-message
|
||||
(:require [quo2.theme :as theme]
|
||||
[react-native.core :as rn]
|
||||
(:require [quo2.components.icon :as quo2.icons]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[quo2.components.icon :as quo2.icons]))
|
||||
[quo2.theme :as theme]
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(def themes
|
||||
{:light {:default colors/neutral-40
|
||||
:success colors/success-50
|
||||
:error colors/danger-50}
|
||||
:dark {:default colors/neutral-60
|
||||
:success colors/success-60
|
||||
:error colors/danger-60}})
|
||||
{:light {:default colors/neutral-40
|
||||
:success colors/success-50
|
||||
:error colors/danger-50}
|
||||
:dark {:default colors/neutral-60
|
||||
:success colors/success-60
|
||||
:error colors/danger-60}})
|
||||
|
||||
(defn get-color [key]
|
||||
(defn get-color
|
||||
[key]
|
||||
(get-in themes [(theme/get-theme) key]))
|
||||
|
||||
(defn info-message
|
||||
@ -26,17 +27,20 @@
|
||||
:icon-color colors/white ;; icon color override
|
||||
:no-icon-color? false ;; disable tint color for icon"
|
||||
[{:keys [type size icon text-color icon-color no-icon-color?]} message]
|
||||
(let [weight (if (= size :default) :regular :medium)
|
||||
size (if (= size :default) :paragraph-2 :label)
|
||||
text-color (or text-color (get-color type))
|
||||
icon-color (or icon-color text-color)]
|
||||
[rn/view {:style {:flex-direction :row
|
||||
:flex 1}}
|
||||
[quo2.icons/icon icon {:color icon-color
|
||||
:no-color no-icon-color?
|
||||
:size 12
|
||||
:container-style {:margin-top 3}}]
|
||||
[text/text {:size size
|
||||
:weight weight
|
||||
:style {:color text-color
|
||||
:margin-horizontal 8}} message]]))
|
||||
(let [weight (if (= size :default) :regular :medium)
|
||||
size (if (= size :default) :paragraph-2 :label)
|
||||
text-color (or text-color (get-color type))
|
||||
icon-color (or icon-color text-color)]
|
||||
[rn/view
|
||||
{:style {:flex-direction :row
|
||||
:flex 1}}
|
||||
[quo2.icons/icon icon
|
||||
{:color icon-color
|
||||
:no-color no-icon-color?
|
||||
:size 12
|
||||
:container-style {:margin-top 3}}]
|
||||
[text/text
|
||||
{:size size
|
||||
:weight weight
|
||||
:style {:color text-color
|
||||
:margin-horizontal 8}} message]]))
|
||||
|
@ -1,44 +1,46 @@
|
||||
(ns quo2.components.info.information-box
|
||||
(:require [quo2.theme :as theme]
|
||||
[react-native.core :as rn]
|
||||
[clojure.string :as string]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[quo2.components.icon :as quo2.icons]
|
||||
(:require [clojure.string :as string]
|
||||
[quo2.components.buttons.button :as quo2.button]
|
||||
[quo2.components.info.info-message :as info-message]))
|
||||
[quo2.components.icon :as quo2.icons]
|
||||
[quo2.components.info.info-message :as info-message]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[quo2.theme :as theme]
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(def themes
|
||||
{:light {:default {:bg colors/white
|
||||
:border colors/neutral-20
|
||||
:icon colors/neutral-50
|
||||
:text colors/neutral-100}
|
||||
:informative {:bg colors/primary-50-opa-5
|
||||
:border colors/primary-50-opa-10
|
||||
:icon colors/primary-50
|
||||
:text colors/neutral-100}
|
||||
:error {:bg colors/danger-50-opa-5
|
||||
:border colors/danger-50-opa-10
|
||||
:icon colors/danger-50
|
||||
:text colors/danger-50}
|
||||
{:light {:default {:bg colors/white
|
||||
:border colors/neutral-20
|
||||
:icon colors/neutral-50
|
||||
:text colors/neutral-100}
|
||||
:informative {:bg colors/primary-50-opa-5
|
||||
:border colors/primary-50-opa-10
|
||||
:icon colors/primary-50
|
||||
:text colors/neutral-100}
|
||||
:error {:bg colors/danger-50-opa-5
|
||||
:border colors/danger-50-opa-10
|
||||
:icon colors/danger-50
|
||||
:text colors/danger-50}
|
||||
:close-button colors/neutral-100}
|
||||
:dark {:default {:bg colors/neutral-90
|
||||
:border colors/neutral-70
|
||||
:icon colors/neutral-40
|
||||
:text colors/white}
|
||||
:informative {:bg colors/primary-50-opa-5
|
||||
:border colors/primary-50-opa-10
|
||||
:icon colors/white
|
||||
:text colors/white}
|
||||
:error {:bg colors/danger-50-opa-5
|
||||
:border colors/danger-50-opa-10
|
||||
:icon colors/danger-50
|
||||
:text colors/danger-50}
|
||||
:dark {:default {:bg colors/neutral-90
|
||||
:border colors/neutral-70
|
||||
:icon colors/neutral-40
|
||||
:text colors/white}
|
||||
:informative {:bg colors/primary-50-opa-5
|
||||
:border colors/primary-50-opa-10
|
||||
:icon colors/white
|
||||
:text colors/white}
|
||||
:error {:bg colors/danger-50-opa-5
|
||||
:border colors/danger-50-opa-10
|
||||
:icon colors/danger-50
|
||||
:text colors/danger-50}
|
||||
:close-button colors/white}})
|
||||
|
||||
(defn get-color [key]
|
||||
(defn get-color
|
||||
[key]
|
||||
(get-in themes [(theme/get-theme) key]))
|
||||
|
||||
(defn get-color-by-type [type key]
|
||||
(defn get-color-by-type
|
||||
[type key]
|
||||
(get-in themes [(theme/get-theme) type key]))
|
||||
|
||||
(defn information-box
|
||||
@ -54,40 +56,47 @@
|
||||
:button-label \"PressMe\" ;; add action button with label
|
||||
:on-button-press action ;; (required for information box with button-label)
|
||||
:on-close on-close ;; (optional on-close call)"
|
||||
[{:keys [type closable? closed? id icon style button-label on-button-press on-close no-icon-color?]} message]
|
||||
[{:keys [type closable? closed? id icon style button-label on-button-press on-close no-icon-color?]}
|
||||
message]
|
||||
(let [background-color (get-color-by-type type :bg)
|
||||
border-color (get-color-by-type type :border)
|
||||
icon-color (get-color-by-type type :icon)
|
||||
text-color (get-color-by-type type :text)
|
||||
include-button? (not (string/blank? button-label))]
|
||||
(when-not closed?
|
||||
[rn/view {:accessibility-label (or id :information-box)
|
||||
:style (merge {:background-color background-color
|
||||
:border-color border-color
|
||||
:border-width 1
|
||||
:border-radius 12
|
||||
:padding-top (if include-button? 10 11)
|
||||
:padding-bottom (if include-button? 12 11)
|
||||
:padding-horizontal 16} style)}
|
||||
[rn/view {:style {:flex-direction :row
|
||||
:align-self :flex-start}}
|
||||
[info-message/info-message {:size :default
|
||||
:icon icon
|
||||
:text-color text-color
|
||||
:icon-color icon-color
|
||||
:no-icon-color? no-icon-color?} message]
|
||||
[rn/view
|
||||
{:accessibility-label (or id :information-box)
|
||||
:style (merge {:background-color background-color
|
||||
:border-color border-color
|
||||
:border-width 1
|
||||
:border-radius 12
|
||||
:padding-top (if include-button? 10 11)
|
||||
:padding-bottom (if include-button? 12 11)
|
||||
:padding-horizontal 16}
|
||||
style)}
|
||||
[rn/view
|
||||
{:style {:flex-direction :row
|
||||
:align-self :flex-start}}
|
||||
[info-message/info-message
|
||||
{:size :default
|
||||
:icon icon
|
||||
:text-color text-color
|
||||
:icon-color icon-color
|
||||
:no-icon-color? no-icon-color?} message]
|
||||
(when closable?
|
||||
[rn/touchable-opacity
|
||||
{:on-press on-close
|
||||
:accessibility-label (str (or id "information-box") "-close-button")}
|
||||
[quo2.icons/icon :i/close {:size 12
|
||||
:color (get-color :close-button)
|
||||
:container-style {:margin-top 4
|
||||
:margin-left 8}}]])]
|
||||
[quo2.icons/icon :i/close
|
||||
{:size 12
|
||||
:color (get-color :close-button)
|
||||
:container-style {:margin-top 4
|
||||
:margin-left 8}}]])]
|
||||
(when include-button?
|
||||
[quo2.button/button {:type :primary
|
||||
:size 24
|
||||
:on-press on-button-press
|
||||
:style {:margin-left 20
|
||||
:margin-top 8
|
||||
:align-self :flex-start}} button-label])])))
|
||||
[quo2.button/button
|
||||
{:type :primary
|
||||
:size 24
|
||||
:on-press on-button-press
|
||||
:style {:margin-left 20
|
||||
:margin-top 8
|
||||
:align-self :flex-start}} button-label])])))
|
||||
|
@ -7,25 +7,28 @@
|
||||
[quo2.theme :as theme]
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(defn list-item [{:keys [name locked? mentions-count unread-messages?
|
||||
muted? is-active-channel? emoji channel-color on-press]
|
||||
:or {channel-color colors/primary-50}}]
|
||||
(defn list-item
|
||||
[{:keys [name locked? mentions-count unread-messages?
|
||||
muted? is-active-channel? emoji channel-color on-press]
|
||||
:or {channel-color colors/primary-50}}]
|
||||
[rn/touchable-opacity {:on-press on-press}
|
||||
[rn/view {:style (merge {:height 48
|
||||
:display :flex
|
||||
:border-radius 12
|
||||
:flex-direction :row
|
||||
:justify-content :space-between
|
||||
:align-items :center
|
||||
:width "100%"
|
||||
:padding-left 12
|
||||
:padding-right 12}
|
||||
(when is-active-channel?
|
||||
{:background-color (colors/theme-alpha channel-color 0.05 0.05)}))}
|
||||
[rn/view {:display :flex
|
||||
:flex-direction :row
|
||||
:justify-content :flex-start
|
||||
:align-items :center}
|
||||
[rn/view
|
||||
{:style (merge {:height 48
|
||||
:display :flex
|
||||
:border-radius 12
|
||||
:flex-direction :row
|
||||
:justify-content :space-between
|
||||
:align-items :center
|
||||
:width "100%"
|
||||
:padding-left 12
|
||||
:padding-right 12}
|
||||
(when is-active-channel?
|
||||
{:background-color (colors/theme-alpha channel-color 0.05 0.05)}))}
|
||||
[rn/view
|
||||
{:display :flex
|
||||
:flex-direction :row
|
||||
:justify-content :flex-start
|
||||
:align-items :center}
|
||||
[channel-avatar/channel-avatar
|
||||
{:big? true
|
||||
:locked? locked?
|
||||
@ -35,7 +38,8 @@
|
||||
{:style (merge {:margin-left 12}
|
||||
(when (and (not locked?) muted?)
|
||||
{:color (if (theme/dark?) colors/neutral-60 colors/neutral-40)}))
|
||||
:weight :medium :size :paragraph-1} (str "# " name)]]
|
||||
:weight :medium
|
||||
:size :paragraph-1} (str "# " name)]]
|
||||
[rn/view {:style {:height 20}}
|
||||
(when (and (not locked?)
|
||||
muted?)
|
||||
@ -45,8 +49,9 @@
|
||||
(when (and (not locked?)
|
||||
(not muted?)
|
||||
(pos? (int mentions-count)))
|
||||
[rn/view {:style {:margin-right 2
|
||||
:margin-top 2}}
|
||||
[rn/view
|
||||
{:style {:margin-right 2
|
||||
:margin-top 2}}
|
||||
[quo2.counter/counter {:override-bg-color channel-color} mentions-count]])
|
||||
(when (and (not locked?)
|
||||
(not muted?)
|
||||
|
@ -1,17 +1,18 @@
|
||||
(ns quo2.components.list-items.menu-item
|
||||
(:require [react-native.core :as rn]
|
||||
[quo2.foundations.colors :as colors :refer [theme-colors]]
|
||||
(:require [quo2.components.icon :as icons]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.components.icon :as icons]))
|
||||
[quo2.foundations.colors :as colors :refer [theme-colors]]
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(defn themes [type]
|
||||
(defn themes
|
||||
[type]
|
||||
(case type
|
||||
:main {:icon-color (theme-colors colors/neutral-50 colors/neutral-10)
|
||||
:background (theme-colors colors/white colors/neutral-90)
|
||||
:text-color (theme-colors colors/neutral-100 colors/white)}
|
||||
:danger {:icon-color (theme-colors colors/danger-50 colors/danger-60)
|
||||
:background (theme-colors colors/white colors/neutral-90)
|
||||
:text-color (theme-colors colors/danger-50 colors/danger-60)}))
|
||||
:main {:icon-color (theme-colors colors/neutral-50 colors/neutral-10)
|
||||
:background (theme-colors colors/white colors/neutral-90)
|
||||
:text-color (theme-colors colors/neutral-100 colors/white)}
|
||||
:danger {:icon-color (theme-colors colors/danger-50 colors/danger-60)
|
||||
:background (theme-colors colors/white colors/neutral-90)
|
||||
:text-color (theme-colors colors/danger-50 colors/danger-60)}))
|
||||
|
||||
(defn menu-item
|
||||
[{:keys [type title accessibility-label icon on-press]
|
||||
@ -19,25 +20,28 @@
|
||||
(let [{:keys [icon-color text-color background]} (themes type)]
|
||||
[rn/touchable-opacity
|
||||
(merge {:accessibility-label accessibility-label
|
||||
:style {:background-color background
|
||||
:height 48
|
||||
:flex-direction :row
|
||||
:align-items :center}}
|
||||
:style {:background-color background
|
||||
:height 48
|
||||
:flex-direction :row
|
||||
:align-items :center}}
|
||||
(when on-press
|
||||
{:on-press on-press}))
|
||||
[rn/view {:style {:flex-direction :row
|
||||
:flex-grow 0
|
||||
:flex-shrink 1
|
||||
:padding-horizontal 20}}
|
||||
[rn/view {:style {:width 20
|
||||
:height 20
|
||||
:align-items :center
|
||||
:justify-content :center
|
||||
:margin-right 12}}
|
||||
[rn/view
|
||||
{:style {:flex-direction :row
|
||||
:flex-grow 0
|
||||
:flex-shrink 1
|
||||
:padding-horizontal 20}}
|
||||
[rn/view
|
||||
{:style {:width 20
|
||||
:height 20
|
||||
:align-items :center
|
||||
:justify-content :center
|
||||
:margin-right 12}}
|
||||
[icons/icon icon {:color icon-color}]]
|
||||
[text/text {:weight :medium
|
||||
:style {:color text-color}
|
||||
:ellipsize-mode :tail
|
||||
:number-of-lines 1
|
||||
:size :paragraph-1}
|
||||
[text/text
|
||||
{:weight :medium
|
||||
:style {:color text-color}
|
||||
:ellipsize-mode :tail
|
||||
:number-of-lines 1
|
||||
:size :paragraph-1}
|
||||
title]]]))
|
||||
|
@ -1,97 +1,112 @@
|
||||
(ns quo2.components.list-items.preview-list
|
||||
(:require [react-native.core :as rn]
|
||||
[react-native.hole-view :as hole-view]
|
||||
[react-native.fast-image :as fast-image]
|
||||
[quo2.foundations.colors :as colors]
|
||||
(:require [quo2.components.avatars.user-avatar :as user-avatar]
|
||||
[quo2.components.icon :as quo2.icons]
|
||||
[quo2.components.avatars.user-avatar :as user-avatar]
|
||||
[quo2.components.markdown.text :as quo2.text]))
|
||||
[quo2.components.markdown.text :as quo2.text]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[react-native.core :as rn]
|
||||
[react-native.fast-image :as fast-image]
|
||||
[react-native.hole-view :as hole-view]))
|
||||
|
||||
(def params {32 {:border-radius {:circular 16 :rounded 10}
|
||||
:hole-radius {:circular 18 :rounded 12}
|
||||
:margin-left -8
|
||||
:hole-size 36
|
||||
:hole-x 22
|
||||
:hole-y -2}
|
||||
24 {:border-radius {:circular 12 :rounded 8}
|
||||
:hole-radius {:circular 13 :rounded 9}
|
||||
:margin-left -4
|
||||
:hole-size 26
|
||||
:hole-x 19
|
||||
:hole-y -1}
|
||||
16 {:border-radius {:circular 8 :rounded 8}
|
||||
:hole-radius {:circular 9 :rounded 9}
|
||||
:margin-left -4
|
||||
:hole-size 18
|
||||
:hole-x 11
|
||||
:hole-y -1}})
|
||||
(def params
|
||||
{32 {:border-radius {:circular 16 :rounded 10}
|
||||
:hole-radius {:circular 18 :rounded 12}
|
||||
:margin-left -8
|
||||
:hole-size 36
|
||||
:hole-x 22
|
||||
:hole-y -2}
|
||||
24 {:border-radius {:circular 12 :rounded 8}
|
||||
:hole-radius {:circular 13 :rounded 9}
|
||||
:margin-left -4
|
||||
:hole-size 26
|
||||
:hole-x 19
|
||||
:hole-y -1}
|
||||
16 {:border-radius {:circular 8 :rounded 8}
|
||||
:hole-radius {:circular 9 :rounded 9}
|
||||
:margin-left -4
|
||||
:hole-size 18
|
||||
:hole-x 11
|
||||
:hole-y -1}})
|
||||
|
||||
;; TODO - Add avatar components for other types once implemented
|
||||
(defn avatar [item type size border-radius]
|
||||
(defn avatar
|
||||
[item type size border-radius]
|
||||
(case type
|
||||
:user [user-avatar/user-avatar
|
||||
(merge {:ring? false
|
||||
:status-indicator? false
|
||||
:size (case size 32 :small 24 :xs 16 :xxxs)}
|
||||
item)]
|
||||
(:photo :collectible) [fast-image/fast-image {:source (:source item)
|
||||
:style {:width size
|
||||
:height size
|
||||
:border-radius border-radius}}]))
|
||||
:user [user-avatar/user-avatar
|
||||
(merge {:ring? false
|
||||
:status-indicator? false
|
||||
:size (case size
|
||||
32 :small
|
||||
24 :xs
|
||||
16 :xxxs)}
|
||||
item)]
|
||||
(:photo :collectible) [fast-image/fast-image
|
||||
{:source (:source item)
|
||||
:style {:width size
|
||||
:height size
|
||||
:border-radius border-radius}}]))
|
||||
|
||||
(defn list-item [index type size item list-size margin-left
|
||||
hole-size hole-radius hole-x hole-y border-radius]
|
||||
(defn list-item
|
||||
[index type size item list-size margin-left
|
||||
hole-size hole-radius hole-x hole-y border-radius]
|
||||
(let [last-item? (= index (- list-size 1))]
|
||||
[hole-view/hole-view {:style {:margin-left (if (= index 0) 0 margin-left)}
|
||||
:holes (if last-item? []
|
||||
[{:x hole-x
|
||||
:y hole-y
|
||||
:width hole-size
|
||||
:height hole-size
|
||||
:borderRadius hole-radius}])}
|
||||
[hole-view/hole-view
|
||||
{:style {:margin-left (if (= index 0) 0 margin-left)}
|
||||
:holes (if last-item?
|
||||
[]
|
||||
[{:x hole-x
|
||||
:y hole-y
|
||||
:width hole-size
|
||||
:height hole-size
|
||||
:borderRadius hole-radius}])}
|
||||
[avatar item type size border-radius]]))
|
||||
|
||||
(defn get-overflow-color [transparent? transparent-color light-color dark-color override-theme]
|
||||
(defn get-overflow-color
|
||||
[transparent? transparent-color light-color dark-color override-theme]
|
||||
(if transparent?
|
||||
transparent-color
|
||||
(colors/theme-colors light-color dark-color override-theme)))
|
||||
|
||||
(defn overflow-label [label size transparent? border-radius margin-left override-theme more-than-99-label]
|
||||
[rn/view {:style {:width size
|
||||
:height size
|
||||
:margin-left margin-left
|
||||
:border-radius border-radius
|
||||
:justify-content :center
|
||||
:align-items :center
|
||||
:background-color (get-overflow-color
|
||||
transparent?
|
||||
colors/white-opa-10
|
||||
colors/neutral-20
|
||||
colors/neutral-70
|
||||
override-theme)}}
|
||||
(defn overflow-label
|
||||
[label size transparent? border-radius margin-left override-theme more-than-99-label]
|
||||
[rn/view
|
||||
{:style {:width size
|
||||
:height size
|
||||
:margin-left margin-left
|
||||
:border-radius border-radius
|
||||
:justify-content :center
|
||||
:align-items :center
|
||||
:background-color (get-overflow-color
|
||||
transparent?
|
||||
colors/white-opa-10
|
||||
colors/neutral-20
|
||||
colors/neutral-70
|
||||
override-theme)}}
|
||||
(if (= size 16)
|
||||
[quo2.icons/icon :i/more {:size 12
|
||||
:color (get-overflow-color
|
||||
transparent?
|
||||
colors/white-opa-70
|
||||
colors/neutral-50
|
||||
colors/neutral-40
|
||||
override-theme)}]
|
||||
[quo2.text/text {:size (if (= size 32) :paragraph-2 :label)
|
||||
:weight :medium
|
||||
:style {:color (get-overflow-color
|
||||
transparent?
|
||||
colors/white-opa-70
|
||||
colors/neutral-60
|
||||
colors/neutral-40
|
||||
override-theme)
|
||||
:margin-left -2}}
|
||||
[quo2.icons/icon :i/more
|
||||
{:size 12
|
||||
:color (get-overflow-color
|
||||
transparent?
|
||||
colors/white-opa-70
|
||||
colors/neutral-50
|
||||
colors/neutral-40
|
||||
override-theme)}]
|
||||
[quo2.text/text
|
||||
{:size (if (= size 32) :paragraph-2 :label)
|
||||
:weight :medium
|
||||
:style {:color (get-overflow-color
|
||||
transparent?
|
||||
colors/white-opa-70
|
||||
colors/neutral-60
|
||||
colors/neutral-40
|
||||
override-theme)
|
||||
:margin-left -2}}
|
||||
;; If overflow label is below 100, show label as +label (ex. +30), else just show 99+
|
||||
(if (< label 100)
|
||||
(str "+" label)
|
||||
more-than-99-label)])])
|
||||
|
||||
(defn border-type [type]
|
||||
(defn border-type
|
||||
[type]
|
||||
(case type
|
||||
(:account :collectible :photo) :rounded
|
||||
:circular))
|
||||
@ -120,4 +135,5 @@
|
||||
[list-item index type size (get items-arr index) list-size
|
||||
margin-left hole-size hole-radius hole-x hole-y border-radius])
|
||||
(when (> list-size 4)
|
||||
[overflow-label (- list-size 3) size transparent? border-radius margin-left override-theme more-than-99-label])]))
|
||||
[overflow-label (- list-size 3) size transparent? border-radius margin-left override-theme
|
||||
more-than-99-label])]))
|
||||
|
@ -1,25 +1,27 @@
|
||||
(ns quo2.components.loaders.skeleton
|
||||
(:require [react-native.core :as rn]
|
||||
(:require [quo2.foundations.colors :as colors]
|
||||
[react-native.core :as rn]
|
||||
[react-native.masked-view :as masked-view]
|
||||
[reagent.core :as reagent]
|
||||
[react-native.reanimated :as reanimated]
|
||||
[quo2.foundations.colors :as colors]))
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
(def message-skeleton-height 54)
|
||||
|
||||
(def avatar-skeleton-size 32)
|
||||
|
||||
(def message-content-width [{:author 80
|
||||
:message 249}
|
||||
{:author 124
|
||||
:message 156}
|
||||
{:author 96
|
||||
:message 212}
|
||||
{:author 112
|
||||
:message 144}])
|
||||
(def message-content-width
|
||||
[{:author 80
|
||||
:message 249}
|
||||
{:author 124
|
||||
:message 156}
|
||||
{:author 96
|
||||
:message 212}
|
||||
{:author 112
|
||||
:message 144}])
|
||||
|
||||
;; Standlone message skeleton
|
||||
(defn message-skeleton []
|
||||
(defn message-skeleton
|
||||
[]
|
||||
[:f>
|
||||
(fn []
|
||||
(let [color (colors/theme-colors colors/neutral-5 colors/neutral-70)
|
||||
@ -31,47 +33,56 @@
|
||||
translate-x (reanimated/use-shared-value (- window-width))
|
||||
animated-gradient-style (reanimated/apply-animations-to-style
|
||||
{:transform [{:translateX translate-x}]}
|
||||
{:width window-width
|
||||
:height "100%"})]
|
||||
{:width window-width
|
||||
:height "100%"})]
|
||||
(reanimated/animate-shared-value-with-repeat translate-x window-width 1000 :linear (- 1) false)
|
||||
[masked-view/masked-view
|
||||
{:style {:height message-skeleton-height}
|
||||
{:style {:height message-skeleton-height}
|
||||
:maskElement (reagent/as-element
|
||||
[rn/view {:style {:height message-skeleton-height
|
||||
:flex-direction :row
|
||||
:padding-vertical 11
|
||||
:background-color :transparent
|
||||
:padding-left 21}}
|
||||
[rn/view {:style {:height avatar-skeleton-size
|
||||
:width avatar-skeleton-size
|
||||
:border-radius (/ avatar-skeleton-size 2)
|
||||
:background-color color
|
||||
:overflow :hidden}}]
|
||||
[rn/view {:style {:padding-left 8
|
||||
:background-color :transparent}}
|
||||
[rn/view {:style {:height 8
|
||||
:width author-width
|
||||
:border-radius 6
|
||||
:background-color color
|
||||
:margin-bottom 8
|
||||
:overflow :hidden}}]
|
||||
[rn/view {:style {:height 16
|
||||
:width message-width
|
||||
:border-radius 6
|
||||
:overflow :hidden
|
||||
:background-color color}}]]])}
|
||||
[rn/view {:style {:flex 1
|
||||
:background-color color}}
|
||||
[reanimated/linear-gradient {:colors [color color loading-color color color]
|
||||
:start {:x 0 :y 0}
|
||||
:end {:x 1 :y 0}
|
||||
:style animated-gradient-style}]]]))])
|
||||
[rn/view
|
||||
{:style {:height message-skeleton-height
|
||||
:flex-direction :row
|
||||
:padding-vertical 11
|
||||
:background-color :transparent
|
||||
:padding-left 21}}
|
||||
[rn/view
|
||||
{:style {:height avatar-skeleton-size
|
||||
:width avatar-skeleton-size
|
||||
:border-radius (/ avatar-skeleton-size 2)
|
||||
:background-color color
|
||||
:overflow :hidden}}]
|
||||
[rn/view
|
||||
{:style {:padding-left 8
|
||||
:background-color :transparent}}
|
||||
[rn/view
|
||||
{:style {:height 8
|
||||
:width author-width
|
||||
:border-radius 6
|
||||
:background-color color
|
||||
:margin-bottom 8
|
||||
:overflow :hidden}}]
|
||||
[rn/view
|
||||
{:style {:height 16
|
||||
:width message-width
|
||||
:border-radius 6
|
||||
:overflow :hidden
|
||||
:background-color color}}]]])}
|
||||
[rn/view
|
||||
{:style {:flex 1
|
||||
:background-color color}}
|
||||
[reanimated/linear-gradient
|
||||
{:colors [color color loading-color color color]
|
||||
:start {:x 0 :y 0}
|
||||
:end {:x 1 :y 0}
|
||||
:style animated-gradient-style}]]]))])
|
||||
|
||||
(defn skeleton [parent-height]
|
||||
(defn skeleton
|
||||
[parent-height]
|
||||
(let [number-of-skeletons (int (Math/floor (/ parent-height message-skeleton-height)))]
|
||||
[rn/view {:style {:background-color (colors/theme-colors
|
||||
colors/white
|
||||
colors/neutral-90)
|
||||
:flex 1}}
|
||||
[rn/view
|
||||
{:style {:background-color (colors/theme-colors
|
||||
colors/white
|
||||
colors/neutral-90)
|
||||
:flex 1}}
|
||||
(for [n (range number-of-skeletons)]
|
||||
[message-skeleton {:key n}])]))
|
||||
|
@ -1,11 +1,12 @@
|
||||
(ns quo2.components.markdown.text
|
||||
(:require [react-native.core :as rn]
|
||||
[quo2.theme :as theme]
|
||||
[quo2.foundations.colors :as colors]
|
||||
(:require [quo2.foundations.colors :as colors]
|
||||
[quo2.foundations.typography :as typography]
|
||||
[quo2.theme :as theme]
|
||||
[react-native.core :as rn]
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
(defn text-style [{:keys [size align weight style]}]
|
||||
(defn text-style
|
||||
[{:keys [size align weight style]}]
|
||||
(merge (case (or weight :regular)
|
||||
:regular typography/font-regular
|
||||
:medium typography/font-medium
|
||||
@ -26,10 +27,12 @@
|
||||
style
|
||||
(assoc style :color (if (= (theme/get-theme) :dark) colors/white colors/neutral-100)))))
|
||||
|
||||
(defn text []
|
||||
(defn text
|
||||
[]
|
||||
(let [this (reagent/current-component)
|
||||
props (reagent/props this)
|
||||
style (text-style props)]
|
||||
(into [rn/text (merge {:style style}
|
||||
(dissoc props :style :size :align :weight :color))]
|
||||
(into [rn/text
|
||||
(merge {:style style}
|
||||
(dissoc props :style :size :align :weight :color))]
|
||||
(reagent/children this))))
|
||||
|
@ -8,10 +8,12 @@
|
||||
:flex-direction :row
|
||||
:align-items :center})
|
||||
|
||||
(defn ens-text []
|
||||
(defn ens-text
|
||||
[]
|
||||
{:color (colors/theme-colors colors/neutral-100 colors/white)})
|
||||
|
||||
(defn nickname-text []
|
||||
(defn nickname-text
|
||||
[]
|
||||
{:color (colors/theme-colors colors/neutral-100 colors/white)})
|
||||
|
||||
(def middle-dot-nickname
|
||||
@ -26,7 +28,8 @@
|
||||
{:color colors/neutral-50
|
||||
:margin-left 4})
|
||||
|
||||
(defn profile-name-text [nickname?]
|
||||
(defn profile-name-text
|
||||
[nickname?]
|
||||
{:color (if nickname?
|
||||
(colors/theme-colors colors/neutral-60 colors/neutral-40)
|
||||
(colors/theme-colors colors/neutral-100 colors/white))})
|
||||
@ -34,6 +37,7 @@
|
||||
(def icon-container
|
||||
{:margin-left 4})
|
||||
|
||||
(defn time-text [ens?]
|
||||
(defn time-text
|
||||
[ens?]
|
||||
{:color colors/neutral-50
|
||||
:margin-left (if ens? 8 4)})
|
@ -1,60 +1,68 @@
|
||||
(ns quo2.components.messages.author.view
|
||||
(:require
|
||||
[quo2.components.messages.author.style :as style]
|
||||
[react-native.core :as rn]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.components.icon :as icons]
|
||||
[status-im.utils.utils :as utils]
|
||||
[clojure.string :as string]))
|
||||
(:require [clojure.string :as string]
|
||||
[quo2.components.icon :as icons]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.components.messages.author.style :as style]
|
||||
[react-native.core :as rn]
|
||||
[status-im.utils.utils :as utils]))
|
||||
|
||||
(def middle-dot "·")
|
||||
|
||||
(defn display-name [{:keys [profile-name nickname ens-name text-style]}]
|
||||
(defn display-name
|
||||
[{:keys [profile-name nickname ens-name text-style]}]
|
||||
(let [ens? (-> ens-name string/blank? not)
|
||||
nickname? (-> nickname string/blank? not)]
|
||||
(if ens?
|
||||
[text/text (merge {:weight :semi-bold
|
||||
:size :paragraph-2
|
||||
:style (style/ens-text)}
|
||||
text-style)
|
||||
[text/text
|
||||
(merge {:weight :semi-bold
|
||||
:size :paragraph-2
|
||||
:style (style/ens-text)}
|
||||
text-style)
|
||||
ens-name]
|
||||
[:<>
|
||||
(if nickname?
|
||||
[text/text (merge {:weight :semi-bold
|
||||
:size :paragraph-2
|
||||
:style (style/nickname-text)}
|
||||
text-style)
|
||||
[text/text
|
||||
(merge {:weight :semi-bold
|
||||
:size :paragraph-2
|
||||
:style (style/nickname-text)}
|
||||
text-style)
|
||||
nickname]
|
||||
[text/text (merge {:weight :semi-bold
|
||||
:size :paragraph-2
|
||||
:style (style/profile-name-text nickname?)}
|
||||
text-style)
|
||||
[text/text
|
||||
(merge {:weight :semi-bold
|
||||
:size :paragraph-2
|
||||
:style (style/profile-name-text nickname?)}
|
||||
text-style)
|
||||
profile-name])])))
|
||||
|
||||
(defn author [{:keys [profile-name nickname chat-key ens-name time-str contact? verified? untrustworthy?]}]
|
||||
(defn author
|
||||
[{:keys [profile-name nickname chat-key ens-name time-str contact? verified? untrustworthy?]}]
|
||||
[:f>
|
||||
(fn []
|
||||
(let [ens? (-> ens-name string/blank? not)
|
||||
(let [ens? (-> ens-name string/blank? not)
|
||||
nickname? (-> nickname string/blank? not)]
|
||||
[rn/view {:style style/container}
|
||||
(if ens?
|
||||
[text/text {:weight :semi-bold
|
||||
:size :paragraph-2
|
||||
:style (style/ens-text)}
|
||||
[text/text
|
||||
{:weight :semi-bold
|
||||
:size :paragraph-2
|
||||
:style (style/ens-text)}
|
||||
ens-name]
|
||||
[:<>
|
||||
(when nickname?
|
||||
[:<>
|
||||
[text/text {:weight :semi-bold
|
||||
:size :paragraph-2
|
||||
:style (style/nickname-text)}
|
||||
[text/text
|
||||
{:weight :semi-bold
|
||||
:size :paragraph-2
|
||||
:style (style/nickname-text)}
|
||||
nickname]
|
||||
[text/text {:size :paragraph-2
|
||||
:style style/middle-dot-nickname}
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
:style style/middle-dot-nickname}
|
||||
middle-dot]])
|
||||
[text/text {:weight (if nickname? :medium :semi-bold)
|
||||
:size :paragraph-2
|
||||
:style (style/profile-name-text nickname?)}
|
||||
[text/text
|
||||
{:weight (if nickname? :medium :semi-bold)
|
||||
:size :paragraph-2
|
||||
:style (style/profile-name-text nickname?)}
|
||||
profile-name]])
|
||||
(when contact?
|
||||
[icons/icon :main-icons2/contact
|
||||
@ -73,16 +81,19 @@
|
||||
:no-color true
|
||||
:container-style style/icon-container}])
|
||||
(when-not ens?
|
||||
[text/text {:monospace true
|
||||
:size :paragraph-2
|
||||
:style style/chat-key-text}
|
||||
[text/text
|
||||
{:monospace true
|
||||
:size :paragraph-2
|
||||
:style style/chat-key-text}
|
||||
(utils/get-shortened-address chat-key)])
|
||||
(when-not ens?
|
||||
[text/text {:monospace true
|
||||
:size :paragraph-2
|
||||
:style style/middle-dot-chat-key}
|
||||
[text/text
|
||||
{:monospace true
|
||||
:size :paragraph-2
|
||||
:style style/middle-dot-chat-key}
|
||||
middle-dot])
|
||||
[text/text {:monospace true
|
||||
:size :paragraph-2
|
||||
:style (style/time-text ens?)}
|
||||
[text/text
|
||||
{:monospace true
|
||||
:size :paragraph-2
|
||||
:style (style/time-text ens?)}
|
||||
time-str]]))])
|
||||
|
@ -1,12 +1,11 @@
|
||||
(ns quo2.components.messages.gap
|
||||
(:require
|
||||
[oops.core :refer [oget]]
|
||||
[react-native.core :as rn]
|
||||
[quo2.theme :as theme]
|
||||
[quo2.components.icon :as icon]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[reagent.core :as reagent]))
|
||||
(:require [oops.core :refer [oget]]
|
||||
[quo2.components.icon :as icon]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[quo2.theme :as theme]
|
||||
[react-native.core :as rn]
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
;;; helpers
|
||||
(def themes
|
||||
@ -17,7 +16,8 @@
|
||||
:time colors/neutral-40
|
||||
:background colors/neutral-95}})
|
||||
|
||||
(defn get-color [key]
|
||||
(defn get-color
|
||||
[key]
|
||||
(get-in themes [(theme/get-theme) key]))
|
||||
|
||||
(def ui-images
|
||||
@ -27,45 +27,51 @@
|
||||
:dark {:horizontal (js/require "../resources/images/ui/message-gap-hborder-dark.png")
|
||||
:circles (js/require "../resources/images/ui/message-gap-circle-bg-dark.png")}})
|
||||
|
||||
(defn get-image [key]
|
||||
(defn get-image
|
||||
[key]
|
||||
(get-in ui-images [(theme/get-theme) key]))
|
||||
|
||||
;;; components
|
||||
;;;; borders
|
||||
(defn hborder [{:keys [type style]}]
|
||||
[rn/image {:source (get-image :horizontal)
|
||||
:resize-mode :repeat
|
||||
:style (merge {:position :absolute
|
||||
:left 0
|
||||
:padding-horizontal 4
|
||||
:overflow :hidden
|
||||
:width "110%"
|
||||
:height 8
|
||||
:margin-left -4}
|
||||
(if (= type :top)
|
||||
{:top 0}
|
||||
{:transform [{:rotateZ "180deg"}]
|
||||
:bottom 0})
|
||||
style)}])
|
||||
(defn hborder
|
||||
[{:keys [type style]}]
|
||||
[rn/image
|
||||
{:source (get-image :horizontal)
|
||||
:resize-mode :repeat
|
||||
:style (merge {:position :absolute
|
||||
:left 0
|
||||
:padding-horizontal 4
|
||||
:overflow :hidden
|
||||
:width "110%"
|
||||
:height 8
|
||||
:margin-left -4}
|
||||
(if (= type :top)
|
||||
{:top 0}
|
||||
{:transform [{:rotateZ "180deg"}]
|
||||
:bottom 0})
|
||||
style)}])
|
||||
|
||||
(defn vborder [type body-height]
|
||||
(defn vborder
|
||||
[type body-height]
|
||||
(let [height @body-height
|
||||
img (get-image :vertical)]
|
||||
(when (and img height)
|
||||
[rn/image {:source img
|
||||
:resize-mode :repeat
|
||||
:style (merge
|
||||
{:position :absolute
|
||||
:top 4
|
||||
:height (- height 8)
|
||||
:width 4}
|
||||
(if (= type :left)
|
||||
{:left 0}
|
||||
{:transform [{:rotate "180deg"}]
|
||||
:right 0}))}])))
|
||||
[rn/image
|
||||
{:source img
|
||||
:resize-mode :repeat
|
||||
:style (merge
|
||||
{:position :absolute
|
||||
:top 4
|
||||
:height (- height 8)
|
||||
:width 4}
|
||||
(if (= type :left)
|
||||
{:left 0}
|
||||
{:transform [{:rotate "180deg"}]
|
||||
:right 0}))}])))
|
||||
|
||||
;;;; others
|
||||
(defn circle []
|
||||
(defn circle
|
||||
[]
|
||||
[rn/view
|
||||
{:width 9
|
||||
:height 9
|
||||
@ -75,34 +81,40 @@
|
||||
:border-color (get-color :icon)
|
||||
:border-radius 50}])
|
||||
|
||||
(defn timestamp [str]
|
||||
[text/text {:size :label
|
||||
:style {:text-transform :none
|
||||
:color (get-color :time)}} str])
|
||||
(defn timestamp
|
||||
[str]
|
||||
[text/text
|
||||
{:size :label
|
||||
:style {:text-transform :none
|
||||
:color (get-color :time)}} str])
|
||||
|
||||
(defn info-button [on-press]
|
||||
(defn info-button
|
||||
[on-press]
|
||||
[rn/touchable-without-feedback
|
||||
{:on-press on-press}
|
||||
[icon/icon "message-gap-info" {:size 12 :no-color true :container-style {:padding 4}}]])
|
||||
|
||||
;;;; timeline/body
|
||||
(defn timeline []
|
||||
[rn/view {:flex 0
|
||||
:margin-right 20
|
||||
:align-items :center
|
||||
:width 9
|
||||
:justify-content :space-between}
|
||||
(defn timeline
|
||||
[]
|
||||
[rn/view
|
||||
{:flex 0
|
||||
:margin-right 20
|
||||
:align-items :center
|
||||
:width 9
|
||||
:justify-content :space-between}
|
||||
[circle]
|
||||
[rn/image {:style {:flex 1} :source (get-image :circles) :resize-mode :repeat}]
|
||||
[circle]])
|
||||
|
||||
(defn body [timestamp-far timestamp-near on-info-button-pressed on-press warning-label]
|
||||
(defn body
|
||||
[timestamp-far timestamp-near on-info-button-pressed on-press warning-label]
|
||||
[rn/view {:flex 1}
|
||||
[rn/view
|
||||
{:flex-direction :row
|
||||
:align-items :center
|
||||
:justify-content :space-between
|
||||
:margin-right 2}
|
||||
{:flex-direction :row
|
||||
:align-items :center
|
||||
:justify-content :space-between
|
||||
:margin-right 2}
|
||||
[timestamp timestamp-far]
|
||||
(when on-info-button-pressed [info-button on-info-button-pressed])]
|
||||
|
||||
@ -131,13 +143,14 @@
|
||||
:flex 1}
|
||||
[hborder {:type :top}]
|
||||
[hborder {:type :bottom}]
|
||||
[rn/view (merge {:width "100%"
|
||||
:background-color (get-color :background)
|
||||
:flex-direction :row
|
||||
:padding 20
|
||||
:padding-left 31
|
||||
:margin-vertical 4}
|
||||
style)
|
||||
[rn/view
|
||||
(merge {:width "100%"
|
||||
:background-color (get-color :background)
|
||||
:flex-direction :row
|
||||
:padding 20
|
||||
:padding-left 31
|
||||
:margin-vertical 4}
|
||||
style)
|
||||
|
||||
[timeline]
|
||||
[body timestamp-far timestamp-near on-info-button-pressed on-press warning-label]]
|
||||
|
@ -8,9 +8,10 @@
|
||||
[react-native.reanimated :as reanimated]
|
||||
[utils.string :as utils]))
|
||||
|
||||
(def themes-landed {:pinned colors/primary-50-opa-5
|
||||
:added colors/primary-50-opa-5
|
||||
:deleted colors/danger-50-opa-5})
|
||||
(def themes-landed
|
||||
{:pinned colors/primary-50-opa-5
|
||||
:added colors/primary-50-opa-5
|
||||
:deleted colors/danger-50-opa-5})
|
||||
|
||||
(def themes
|
||||
{:light {:text colors/neutral-100
|
||||
@ -24,115 +25,149 @@
|
||||
:pressed colors/neutral-80
|
||||
:landed themes-landed}}})
|
||||
|
||||
(defn get-color [& keys]
|
||||
(defn get-color
|
||||
[& keys]
|
||||
(reduce (fn [acc k] (get acc k (reduced acc)))
|
||||
((theme/get-theme) themes) (vec keys)))
|
||||
((theme/get-theme) themes)
|
||||
(vec keys)))
|
||||
|
||||
(defn sm-timestamp [timestamp-str]
|
||||
(defn sm-timestamp
|
||||
[timestamp-str]
|
||||
[rn/view {:margin-left 6}
|
||||
[text/text {:size :label
|
||||
:style {:color (get-color :time)
|
||||
:text-transform :none}}
|
||||
[text/text
|
||||
{:size :label
|
||||
:style {:color (get-color :time)
|
||||
:text-transform :none}}
|
||||
timestamp-str]])
|
||||
|
||||
(defn sm-icon [{:keys [icon color opacity]}]
|
||||
[rn/view {:align-items :center
|
||||
:margin-right 8}
|
||||
[icon-avatar/icon-avatar {:size :medium
|
||||
:icon icon
|
||||
:color color
|
||||
:opacity opacity}]])
|
||||
(defn sm-icon
|
||||
[{:keys [icon color opacity]}]
|
||||
[rn/view
|
||||
{:align-items :center
|
||||
:margin-right 8}
|
||||
[icon-avatar/icon-avatar
|
||||
{:size :medium
|
||||
:icon icon
|
||||
:color color
|
||||
:opacity opacity}]])
|
||||
|
||||
(defn sm-user-avatar [image]
|
||||
(defn sm-user-avatar
|
||||
[image]
|
||||
[rn/view {:margin-right 4}
|
||||
[user-avatar/user-avatar {:status-indicator? false
|
||||
:online? false
|
||||
:size :xxxs
|
||||
:profile-picture image
|
||||
:ring? false}]])
|
||||
[user-avatar/user-avatar
|
||||
{:status-indicator? false
|
||||
:online? false
|
||||
:size :xxxs
|
||||
:profile-picture image
|
||||
:ring? false}]])
|
||||
|
||||
(defmulti sm-render :type)
|
||||
|
||||
(defmethod sm-render :deleted [{:keys [label timestamp-str labels]}]
|
||||
[rn/view {:align-items :center
|
||||
:justify-content :space-between
|
||||
:flex 1
|
||||
:flex-direction :row}
|
||||
[rn/view {:align-items :center
|
||||
:flex-direction :row}
|
||||
[sm-icon {:icon :main-icons/delete
|
||||
:color :danger
|
||||
:opacity 5}]
|
||||
[text/text {:size :paragraph-2
|
||||
:style {:color (get-color :text)
|
||||
:margin-right 5}}
|
||||
(defmethod sm-render :deleted
|
||||
[{:keys [label timestamp-str labels]}]
|
||||
[rn/view
|
||||
{:align-items :center
|
||||
:justify-content :space-between
|
||||
:flex 1
|
||||
:flex-direction :row}
|
||||
[rn/view
|
||||
{:align-items :center
|
||||
:flex-direction :row}
|
||||
[sm-icon
|
||||
{:icon :main-icons/delete
|
||||
:color :danger
|
||||
:opacity 5}]
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
:style {:color (get-color :text)
|
||||
:margin-right 5}}
|
||||
(or (get labels label) label (:message-deleted labels))]
|
||||
[sm-timestamp timestamp-str]]])
|
||||
|
||||
(defmethod sm-render :added [{:keys [state mentions timestamp-str labels]}]
|
||||
[rn/view {:align-items :center
|
||||
:flex-direction :row}
|
||||
[sm-icon {:icon :main-icons/add-user
|
||||
:color :primary
|
||||
:opacity (if (= state :landed) 0 5)}]
|
||||
(defmethod sm-render :added
|
||||
[{:keys [state mentions timestamp-str labels]}]
|
||||
[rn/view
|
||||
{:align-items :center
|
||||
:flex-direction :row}
|
||||
[sm-icon
|
||||
{:icon :main-icons/add-user
|
||||
:color :primary
|
||||
:opacity (if (= state :landed) 0 5)}]
|
||||
[sm-user-avatar (:image (first mentions))]
|
||||
[text/text {:weight :semi-bold
|
||||
:size :paragraph-2}
|
||||
[text/text
|
||||
{:weight :semi-bold
|
||||
:size :paragraph-2}
|
||||
(:name (first mentions))]
|
||||
[text/text {:size :paragraph-2
|
||||
:style {:color (get-color :text)
|
||||
:margin-left 3
|
||||
:margin-right 3}}
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
:style {:color (get-color :text)
|
||||
:margin-left 3
|
||||
:margin-right 3}}
|
||||
(:added labels)]
|
||||
[sm-user-avatar (:image (second mentions))]
|
||||
[text/text {:weight :semi-bold
|
||||
:size :paragraph-2}
|
||||
[text/text
|
||||
{:weight :semi-bold
|
||||
:size :paragraph-2}
|
||||
(:name (second mentions))]
|
||||
[sm-timestamp timestamp-str]])
|
||||
|
||||
(defmethod sm-render :pinned [{:keys [state pinned-by content timestamp-str labels]}]
|
||||
[rn/view {:flex-direction :row
|
||||
:flex 1
|
||||
:align-items :center}
|
||||
[sm-icon {:icon :main-icons/pin
|
||||
:color :primary
|
||||
:opacity (if (= state :landed) 0 5)}]
|
||||
[rn/view {:flex-direction :column
|
||||
:flex 1}
|
||||
[rn/view {:align-items :baseline
|
||||
:flex-direction :row}
|
||||
[text/text {:size :paragraph-2
|
||||
:weight :semi-bold
|
||||
:style {:color (get-color :text)}}
|
||||
(defmethod sm-render :pinned
|
||||
[{:keys [state pinned-by content timestamp-str labels]}]
|
||||
[rn/view
|
||||
{:flex-direction :row
|
||||
:flex 1
|
||||
:align-items :center}
|
||||
[sm-icon
|
||||
{:icon :main-icons/pin
|
||||
:color :primary
|
||||
:opacity (if (= state :landed) 0 5)}]
|
||||
[rn/view
|
||||
{:flex-direction :column
|
||||
:flex 1}
|
||||
[rn/view
|
||||
{:align-items :baseline
|
||||
:flex-direction :row}
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
:weight :semi-bold
|
||||
:style {:color (get-color :text)}}
|
||||
(utils/truncate-str pinned-by 18)]
|
||||
[rn/view {:margin-left 4
|
||||
:margin-right 2}
|
||||
[text/text {:size :paragraph-2
|
||||
:style {:color (get-color :text)}}
|
||||
[rn/view
|
||||
{:margin-left 4
|
||||
:margin-right 2}
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
:style {:color (get-color :text)}}
|
||||
(:pinned-a-message labels)]]
|
||||
[sm-timestamp timestamp-str]]
|
||||
[rn/view {:flex-direction :row}
|
||||
[rn/view {:flex-direction :row
|
||||
:margin-right 4}
|
||||
[rn/view
|
||||
{:flex-direction :row
|
||||
:margin-right 4}
|
||||
[sm-user-avatar (:image (:mentions content))]
|
||||
[text/text {:weight :semi-bold
|
||||
:size :label}
|
||||
[text/text
|
||||
{:weight :semi-bold
|
||||
:size :label}
|
||||
(:name (:mentions content))]]
|
||||
(when (seq (:text content))
|
||||
[rn/view {:margin-right 20
|
||||
:flex-direction :row
|
||||
:flex 1}
|
||||
[text/text {:size :label
|
||||
:style {:color (get-color :text)}
|
||||
:number-of-lines 1
|
||||
:ellipsize-mode :tail}
|
||||
[rn/view
|
||||
{:margin-right 20
|
||||
:flex-direction :row
|
||||
:flex 1}
|
||||
[text/text
|
||||
{:size :label
|
||||
:style {:color (get-color :text)}
|
||||
:number-of-lines 1
|
||||
:ellipsize-mode :tail}
|
||||
(:text content)]])
|
||||
[rn/view {:justify-content :flex-end
|
||||
:flex-direction :row
|
||||
:min-width 10}
|
||||
[rn/view
|
||||
{:justify-content :flex-end
|
||||
:flex-direction :row
|
||||
:min-width 10}
|
||||
(when (seq (:info content))
|
||||
[text/text {:size :label
|
||||
:style {:color (get-color :time)}}
|
||||
[text/text
|
||||
{:size :label
|
||||
:style {:color (get-color :time)}}
|
||||
(utils/truncate-str (:info content) 24)])]]]])
|
||||
|
||||
(defn system-message
|
||||
@ -143,11 +178,16 @@
|
||||
(get-color :bg (if animate-landing? :landed :default) type))]
|
||||
(when animate-landing?
|
||||
(reanimated/animate-shared-value-with-delay
|
||||
sv-color (get-color :bg :default type) 0 :linear 1000))
|
||||
sv-color
|
||||
(get-color :bg :default type)
|
||||
0
|
||||
:linear
|
||||
1000))
|
||||
[reanimated/touchable-opacity
|
||||
{:on-press #(when-not non-pressable?
|
||||
(reanimated/set-shared-value
|
||||
sv-color (get-color :bg :pressed type)))
|
||||
sv-color
|
||||
(get-color :bg :pressed type)))
|
||||
:style (reanimated/apply-animations-to-style
|
||||
{:background-color sv-color}
|
||||
(merge
|
||||
|
@ -1,12 +1,13 @@
|
||||
(ns quo2.components.navigation.bottom-nav-tab
|
||||
(:require [react-native.core :as rn]
|
||||
[react-native.reanimated :as reanimated]
|
||||
[react-native.hole-view :as hole-view]
|
||||
[quo2.foundations.colors :as colors]
|
||||
(:require [quo2.components.counter.counter :as counter]
|
||||
[quo2.components.icons.icons :as icons]
|
||||
[quo2.components.counter.counter :as counter]))
|
||||
[quo2.foundations.colors :as colors]
|
||||
[react-native.core :as rn]
|
||||
[react-native.hole-view :as hole-view]
|
||||
[react-native.reanimated :as reanimated]))
|
||||
|
||||
(defn toggle-background-color [background-color press-out? pass-through?]
|
||||
(defn toggle-background-color
|
||||
[background-color press-out? pass-through?]
|
||||
(reanimated/set-shared-value
|
||||
background-color
|
||||
(cond
|
||||
@ -36,44 +37,47 @@
|
||||
background-color (reanimated/use-shared-value "transparent")
|
||||
background-animated-style (reanimated/apply-animations-to-style
|
||||
{:background-color background-color}
|
||||
{:width 90
|
||||
:height 40
|
||||
:border-radius 10})]
|
||||
{:width 90
|
||||
:height 40
|
||||
:border-radius 10})]
|
||||
[rn/touchable-without-feedback
|
||||
{:test-ID test-ID
|
||||
{:test-ID test-ID
|
||||
:on-press on-press
|
||||
:on-press-in #(toggle-background-color background-color false pass-through?)
|
||||
:on-press-out #(toggle-background-color background-color true pass-through?)
|
||||
:accessibility-label accessibility-label}
|
||||
[reanimated/view {:style background-animated-style}
|
||||
[hole-view/hole-view {:style {:padding-left 33
|
||||
:padding-top 8}
|
||||
:key new-notifications? ;; Key is required to force removal of holes
|
||||
:holes (cond
|
||||
(not new-notifications?) ;; No new notifications, remove holes
|
||||
[]
|
||||
[hole-view/hole-view
|
||||
{:style {:padding-left 33
|
||||
:padding-top 8}
|
||||
:key new-notifications? ;; Key is required to force removal of holes
|
||||
:holes (cond
|
||||
(not new-notifications?) ;; No new notifications, remove holes
|
||||
[]
|
||||
|
||||
(= notification-indicator :unread-dot)
|
||||
[{:x 50 :y 5 :width 10 :height 10 :borderRadius 5}]
|
||||
(= notification-indicator :unread-dot)
|
||||
[{:x 50 :y 5 :width 10 :height 10 :borderRadius 5}]
|
||||
|
||||
:else
|
||||
[{:x 47 :y 1 :width 18 :height 18 :borderRadius 7}])}
|
||||
:else
|
||||
[{:x 47 :y 1 :width 18 :height 18 :borderRadius 7}])}
|
||||
[reanimated/image
|
||||
{:style icon-animated-style
|
||||
{:style icon-animated-style
|
||||
:source (icons/icon-source (keyword (str icon 24)))}]]
|
||||
(when new-notifications?
|
||||
(if (= notification-indicator :counter)
|
||||
[counter/counter {:outline false
|
||||
:override-text-color colors/white
|
||||
:override-bg-color colors/primary-50
|
||||
:style {:position :absolute
|
||||
:left 48
|
||||
:top 2}}
|
||||
[counter/counter
|
||||
{:outline false
|
||||
:override-text-color colors/white
|
||||
:override-bg-color colors/primary-50
|
||||
:style {:position :absolute
|
||||
:left 48
|
||||
:top 2}}
|
||||
counter-label]
|
||||
[rn/view {:style {:width 8
|
||||
:height 8
|
||||
:border-radius 4
|
||||
:top 6
|
||||
:left 51
|
||||
:position :absolute
|
||||
:background-color colors/primary-50}}]))]]))])
|
||||
[rn/view
|
||||
{:style {:width 8
|
||||
:height 8
|
||||
:border-radius 4
|
||||
:top 6
|
||||
:left 51
|
||||
:position :absolute
|
||||
:background-color colors/primary-50}}]))]]))])
|
||||
|
@ -1,9 +1,10 @@
|
||||
(ns quo2.components.navigation.floating-shell-button
|
||||
(:require [react-native.core :as rn]
|
||||
[react-native.reanimated :as reanimated]
|
||||
[quo2.components.buttons.dynamic-button :as dynamic-button]))
|
||||
(:require [quo2.components.buttons.dynamic-button :as dynamic-button]
|
||||
[react-native.core :as rn]
|
||||
[react-native.reanimated :as reanimated]))
|
||||
|
||||
(defn dynamic-button-view [type dynamic-buttons style]
|
||||
(defn dynamic-button-view
|
||||
[type dynamic-buttons style]
|
||||
(when-let [{:keys [count on-press customization-color label]} (get dynamic-buttons type)]
|
||||
[dynamic-button/dynamic-button
|
||||
{:type type
|
||||
@ -25,23 +26,27 @@
|
||||
(fn []
|
||||
(let [original-style (merge {:flex-direction :row
|
||||
:margin-horizontal 12
|
||||
:pointer-events :box-none} style)
|
||||
:pointer-events :box-none}
|
||||
style)
|
||||
animated-style (reanimated/apply-animations-to-style
|
||||
(if opacity-anim
|
||||
{:opacity opacity-anim} {})
|
||||
{:opacity opacity-anim}
|
||||
{})
|
||||
original-style)]
|
||||
[reanimated/view {:style animated-style}
|
||||
;; Left Section
|
||||
[rn/view {:style {:flex 1}}
|
||||
[dynamic-button-view :search dynamic-buttons {:position :absolute
|
||||
:right 8}]]
|
||||
[dynamic-button-view :search dynamic-buttons
|
||||
{:position :absolute
|
||||
:right 8}]]
|
||||
;; Mid Section (jump-to)
|
||||
[dynamic-button-view :jump-to dynamic-buttons nil]
|
||||
;; Right Section
|
||||
;; Right Section
|
||||
[rn/view {:style {:flex 1}}
|
||||
[rn/view {:style {:position :absolute
|
||||
:flex-direction :row
|
||||
:right 0}}
|
||||
[rn/view
|
||||
{:style {:position :absolute
|
||||
:flex-direction :row
|
||||
:right 0}}
|
||||
[dynamic-button-view :mention dynamic-buttons {:margin-left 8}]
|
||||
[dynamic-button-view :notification-down dynamic-buttons {:margin-left 8}]
|
||||
[dynamic-button-view :notification-up dynamic-buttons {:margin-left 8}]
|
||||
|
@ -1,11 +1,11 @@
|
||||
(ns quo2.components.navigation.page-nav
|
||||
(:require [react-native.core :as rn]
|
||||
[quo2.foundations.colors :as colors]
|
||||
(:require [clojure.string :as string]
|
||||
[quo2.components.avatars.user-avatar :as user-avatar]
|
||||
[quo2.components.buttons.button :as button]
|
||||
[quo2.components.icon :as icons]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[clojure.string :as string]
|
||||
[quo2.components.buttons.button :as button]
|
||||
[quo2.components.avatars.user-avatar :as user-avatar]))
|
||||
[quo2.foundations.colors :as colors]
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(def ^:private centrify-style
|
||||
{:display :flex
|
||||
@ -16,7 +16,8 @@
|
||||
|
||||
(defn- big? [size] (= size :big))
|
||||
|
||||
(defn- icon-props [color size]
|
||||
(defn- icon-props
|
||||
[color size]
|
||||
(merge {:size 20
|
||||
:container-style {:width (if (big? size)
|
||||
20
|
||||
@ -28,22 +29,25 @@
|
||||
{:color color}
|
||||
{:no-color true})))
|
||||
|
||||
(defn left-section-view [{:keys [on-press icon accessibility-label type] :or {type :grey}}
|
||||
put-middle-section-on-left?]
|
||||
(defn left-section-view
|
||||
[{:keys [on-press icon accessibility-label type] :or {type :grey}}
|
||||
put-middle-section-on-left?]
|
||||
[rn/view {:style (when put-middle-section-on-left? {:margin-right 5})}
|
||||
[button/button {:on-press on-press
|
||||
:icon true
|
||||
:type type
|
||||
:size 32
|
||||
:accessibility-label accessibility-label}
|
||||
[button/button
|
||||
{:on-press on-press
|
||||
:icon true
|
||||
:type type
|
||||
:size 32
|
||||
:accessibility-label accessibility-label}
|
||||
icon]])
|
||||
|
||||
(defn- mid-section-comp
|
||||
[{:keys [description-img description-user-icon horizontal-description?
|
||||
text-secondary-color align-mid? text-color icon main-text type description]}]
|
||||
[rn/view {:style (assoc centrify-style
|
||||
:flex-direction :row
|
||||
:margin-horizontal 2)}
|
||||
[rn/view
|
||||
{:style (assoc centrify-style
|
||||
:flex-direction :row
|
||||
:margin-horizontal 2)}
|
||||
(when (or (and (not horizontal-description?)
|
||||
align-mid?
|
||||
(not= :text-with-description type))
|
||||
@ -52,85 +56,98 @@
|
||||
(if description-img
|
||||
[rn/view {:margin-right 8}
|
||||
[description-img]]
|
||||
[rn/image {:source {:uri description-user-icon}
|
||||
:style {:width 32
|
||||
:height 32
|
||||
:border-radius 32
|
||||
:margin-right 8}}]))
|
||||
[rn/view {:style {:flex-direction (if horizontal-description?
|
||||
:row
|
||||
:column)}}
|
||||
[text/text {:size :paragraph-1
|
||||
:weight :semi-bold
|
||||
:style {:color text-color
|
||||
:line-height 21}}
|
||||
[rn/image
|
||||
{:source {:uri description-user-icon}
|
||||
:style {:width 32
|
||||
:height 32
|
||||
:border-radius 32
|
||||
:margin-right 8}}]))
|
||||
[rn/view
|
||||
{:style {:flex-direction (if horizontal-description?
|
||||
:row
|
||||
:column)}}
|
||||
[text/text
|
||||
{:size :paragraph-1
|
||||
:weight :semi-bold
|
||||
:style {:color text-color
|
||||
:line-height 21}}
|
||||
main-text]
|
||||
(when description
|
||||
[text/text {:size :paragraph-2
|
||||
:weight :medium
|
||||
:style (cond-> {:padding-right 4
|
||||
:color text-secondary-color
|
||||
:line-height 18}
|
||||
horizontal-description? (assoc :margin-left 4 :margin-top 2))}
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
:weight :medium
|
||||
:style (cond-> {:padding-right 4
|
||||
:color text-secondary-color
|
||||
:line-height 18}
|
||||
horizontal-description? (assoc :margin-left 4 :margin-top 2))}
|
||||
description])]])
|
||||
|
||||
(defn- mid-section-view
|
||||
[{:keys [horizontal-description? one-icon-align-left? type left-align?
|
||||
main-text right-icon main-text-icon-color left-icon on-press avatar] :as props}]
|
||||
(let [text-color (if (colors/dark?) colors/neutral-5 colors/neutral-95)
|
||||
main-text right-icon main-text-icon-color left-icon on-press avatar]
|
||||
:as props}]
|
||||
(let [text-color (if (colors/dark?) colors/neutral-5 colors/neutral-95)
|
||||
text-secondary-color (if (colors/dark?) colors/neutral-40 colors/neutral-50)
|
||||
component-instance [mid-section-comp (assoc props :text-secondary-color text-secondary-color)]]
|
||||
component-instance [mid-section-comp (assoc props :text-secondary-color text-secondary-color)]]
|
||||
[rn/touchable-opacity {:on-press on-press}
|
||||
[rn/view {:style (merge
|
||||
(if left-align?
|
||||
align-left
|
||||
centrify-style)
|
||||
{:flex 1
|
||||
:margin-left 4
|
||||
:text-align-vertical :center})}
|
||||
[rn/view
|
||||
{:style (merge
|
||||
(if left-align?
|
||||
align-left
|
||||
centrify-style)
|
||||
{:flex 1
|
||||
:margin-left 4
|
||||
:text-align-vertical :center})}
|
||||
(case type
|
||||
:text-only [text/text {:size :paragraph-1
|
||||
:weight :semi-bold
|
||||
:style {:color text-color}}
|
||||
main-text]
|
||||
:user-avatar [rn/view {:style (assoc centrify-style :flex-direction :row)}
|
||||
[user-avatar/user-avatar avatar]
|
||||
[text/text {:size :paragraph-1
|
||||
:text-only [text/text
|
||||
{:size :paragraph-1
|
||||
:weight :semi-bold
|
||||
:style {:color text-color}}
|
||||
main-text]
|
||||
:user-avatar [rn/view {:style (assoc centrify-style :flex-direction :row)}
|
||||
[user-avatar/user-avatar avatar]
|
||||
[text/text
|
||||
{:size :paragraph-1
|
||||
:weight :semi-bold
|
||||
:style {:padding-horizontal 4
|
||||
:color text-color}}
|
||||
main-text]]
|
||||
:text-with-two-icons [rn/view {:style (assoc centrify-style :flex-direction :row)}
|
||||
[icons/icon left-icon
|
||||
(icon-props main-text-icon-color :big)]
|
||||
[text/text {:size :paragraph-1
|
||||
:weight :semi-bold
|
||||
:style {:padding-horizontal 4
|
||||
:color text-color}}
|
||||
main-text]
|
||||
[icons/icon right-icon
|
||||
(icon-props main-text-icon-color :big)]]
|
||||
:text-with-one-icon [rn/view {:style {:flex-direction :row}}
|
||||
(if one-icon-align-left?
|
||||
[rn/view {:style {:flex-direction :row
|
||||
:align-items :center}}
|
||||
(when horizontal-description?
|
||||
[icons/icon left-icon
|
||||
(icon-props main-text-icon-color :big)])
|
||||
component-instance]
|
||||
[rn/view {:style {:flex-direction :row
|
||||
:align-items :center}}
|
||||
component-instance
|
||||
(when horizontal-description?
|
||||
[icons/icon left-icon
|
||||
(icon-props main-text-icon-color :big)])])]
|
||||
main-text]]
|
||||
:text-with-two-icons [rn/view {:style (assoc centrify-style :flex-direction :row)}
|
||||
[icons/icon left-icon
|
||||
(icon-props main-text-icon-color :big)]
|
||||
[text/text
|
||||
{:size :paragraph-1
|
||||
:weight :semi-bold
|
||||
:style {:padding-horizontal 4
|
||||
:color text-color}}
|
||||
main-text]
|
||||
[icons/icon right-icon
|
||||
(icon-props main-text-icon-color :big)]]
|
||||
:text-with-one-icon [rn/view {:style {:flex-direction :row}}
|
||||
(if one-icon-align-left?
|
||||
[rn/view
|
||||
{:style {:flex-direction :row
|
||||
:align-items :center}}
|
||||
(when horizontal-description?
|
||||
[icons/icon left-icon
|
||||
(icon-props main-text-icon-color :big)])
|
||||
component-instance]
|
||||
[rn/view
|
||||
{:style {:flex-direction :row
|
||||
:align-items :center}}
|
||||
component-instance
|
||||
(when horizontal-description?
|
||||
[icons/icon left-icon
|
||||
(icon-props main-text-icon-color :big)])])]
|
||||
:text-with-description component-instance)]]))
|
||||
|
||||
(defn- right-section-view [right-section-buttons]
|
||||
[rn/view {:style (assoc centrify-style
|
||||
:flex-direction :row
|
||||
:flex 1
|
||||
:justify-content :flex-end)}
|
||||
(defn- right-section-view
|
||||
[right-section-buttons]
|
||||
[rn/view
|
||||
{:style (assoc centrify-style
|
||||
:flex-direction :row
|
||||
:flex 1
|
||||
:justify-content :flex-end)}
|
||||
(let [last-icon-index (-> right-section-buttons count dec)]
|
||||
(map-indexed (fn [index {:keys [icon on-press type] :or {type :grey}}]
|
||||
^{:key index}
|
||||
@ -194,27 +211,30 @@
|
||||
:icon (:icon mid-section)
|
||||
:left-icon (:left-icon mid-section)
|
||||
:avatar (:avatar mid-section)}]
|
||||
[rn/view {:style (cond-> {:display :flex
|
||||
:flex-direction :row
|
||||
;; iPhone 11 Pro's height in Figma divided by Component height 56/1125
|
||||
:align-items :center
|
||||
:padding-horizontal 20
|
||||
:height 56
|
||||
:justify-content :space-between}
|
||||
page-nav-background-uri (assoc :background-color page-nav-color)
|
||||
page-nav-color (assoc :background page-nav-background-uri))}
|
||||
[rn/view {:style {:flex 1
|
||||
:flex-direction :row
|
||||
:align-items :center}}
|
||||
[rn/view
|
||||
{:style (cond-> {:display :flex
|
||||
:flex-direction :row
|
||||
;; iPhone 11 Pro's height in Figma divided by Component height 56/1125
|
||||
:align-items :center
|
||||
:padding-horizontal 20
|
||||
:height 56
|
||||
:justify-content :space-between}
|
||||
page-nav-background-uri (assoc :background-color page-nav-color)
|
||||
page-nav-color (assoc :background page-nav-background-uri))}
|
||||
[rn/view
|
||||
{:style {:flex 1
|
||||
:flex-direction :row
|
||||
:align-items :center}}
|
||||
[left-section-view left-section put-middle-section-on-left?]
|
||||
(when put-middle-section-on-left?
|
||||
[mid-section-view (assoc mid-section-props
|
||||
:left-align? true
|
||||
:description (:description mid-section)
|
||||
:description-color (:description-color mid-section)
|
||||
:description-icon (:description-icon mid-section)
|
||||
:align-mid? align-mid?
|
||||
:description-user-icon (:description-user-icon mid-section))])]
|
||||
[mid-section-view
|
||||
(assoc mid-section-props
|
||||
:left-align? true
|
||||
:description (:description mid-section)
|
||||
:description-color (:description-color mid-section)
|
||||
:description-icon (:description-icon mid-section)
|
||||
:align-mid? align-mid?
|
||||
:description-user-icon (:description-user-icon mid-section))])]
|
||||
(when-not put-middle-section-on-left?
|
||||
[mid-section-view mid-section-props])
|
||||
[right-section-view right-section-buttons]]))
|
||||
|
@ -43,7 +43,8 @@
|
||||
:align-items :flex-start
|
||||
:flex 1})
|
||||
|
||||
(defn title [replying?]
|
||||
(defn title
|
||||
[replying?]
|
||||
{:color colors/white
|
||||
:flex-shrink 1
|
||||
:max-width (when-not replying? "60%")})
|
||||
|
@ -4,9 +4,9 @@
|
||||
[quo2.components.buttons.button :as button]
|
||||
[quo2.components.icon :as icon]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.components.notifications.activity-log.style :as style]
|
||||
[quo2.components.tags.status-tags :as status-tags]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[quo2.components.notifications.activity-log.style :as style]
|
||||
[react-native.core :as rn]
|
||||
[reagent.core :as reagent]
|
||||
[status-im.i18n.i18n :as i18n]))
|
||||
@ -21,17 +21,20 @@
|
||||
(defn- activity-reply-text-input
|
||||
[reply-input on-update-reply]
|
||||
[rn/view
|
||||
[rn/view {:style {:margin-top 16
|
||||
:margin-bottom 8
|
||||
:flex-direction :row}}
|
||||
[text/text {:weight :medium
|
||||
:style {:flex-grow 1
|
||||
:color colors/neutral-40}}
|
||||
[rn/view
|
||||
{:style {:margin-top 16
|
||||
:margin-bottom 8
|
||||
:flex-direction :row}}
|
||||
[text/text
|
||||
{:weight :medium
|
||||
:style {:flex-grow 1
|
||||
:color colors/neutral-40}}
|
||||
(i18n/label :t/your-answer)]
|
||||
[text/text {:style {:flex-shrink 1
|
||||
:color (if (valid-reply? @reply-input)
|
||||
colors/neutral-40
|
||||
colors/danger-60)}}
|
||||
[text/text
|
||||
{:style {:flex-shrink 1
|
||||
:color (if (valid-reply? @reply-input)
|
||||
colors/neutral-40
|
||||
colors/danger-60)}}
|
||||
(str (count @reply-input) "/" max-reply-length)]]
|
||||
[rn/view
|
||||
;; TODO(@ilmotta): Replace with quo2 component when available.
|
||||
@ -58,33 +61,39 @@
|
||||
(let [first-line-offset (if replying? 4 0)
|
||||
gap-between-lines 4]
|
||||
(into [rn/view {:style (assoc style/context-container :margin-top first-line-offset)}]
|
||||
(mapcat (fn [detail]
|
||||
^{:key (hash detail)}
|
||||
(if (string? detail)
|
||||
(map (fn [s]
|
||||
[rn/view {:style {:margin-right 4
|
||||
:margin-top 0}}
|
||||
[text/text {:size :paragraph-2
|
||||
:style {:color colors/white}}
|
||||
s]])
|
||||
(string/split detail #"\s+"))
|
||||
[[rn/view {:margin-right 4
|
||||
:margin-top gap-between-lines}
|
||||
detail]]))
|
||||
context))))
|
||||
(mapcat
|
||||
(fn [detail]
|
||||
^{:key (hash detail)}
|
||||
(if (string? detail)
|
||||
(map (fn [s]
|
||||
[rn/view
|
||||
{:style {:margin-right 4
|
||||
:margin-top 0}}
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
:style {:color colors/white}}
|
||||
s]])
|
||||
(string/split detail #"\s+"))
|
||||
[[rn/view
|
||||
{:margin-right 4
|
||||
:margin-top gap-between-lines}
|
||||
detail]]))
|
||||
context))))
|
||||
|
||||
(defn- activity-message
|
||||
[{:keys [title body]}]
|
||||
[rn/view {:style style/message-container}
|
||||
(when title
|
||||
[text/text {:size :paragraph-2
|
||||
:accessibility-label :activity-message-title
|
||||
:style style/message-title}
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
:accessibility-label :activity-message-title
|
||||
:style style/message-title}
|
||||
title])
|
||||
(if (string? body)
|
||||
[text/text {:style style/message-body
|
||||
:accessibility-label :activity-message-body
|
||||
:size :paragraph-1}
|
||||
[text/text
|
||||
{:style style/message-body
|
||||
:accessibility-label :activity-message-body
|
||||
:size :paragraph-1}
|
||||
body]
|
||||
body)])
|
||||
|
||||
@ -97,44 +106,51 @@
|
||||
:flex-basis 0})]
|
||||
[rn/view style/buttons-container
|
||||
(when button-1
|
||||
[button/button (-> button-1
|
||||
(assoc :size size)
|
||||
(update :style merge common-style {:margin-right 8}))
|
||||
[button/button
|
||||
(-> button-1
|
||||
(assoc :size size)
|
||||
(update :style merge common-style {:margin-right 8}))
|
||||
(:label button-1)])
|
||||
(when button-2
|
||||
[button/button (-> button-2
|
||||
(assoc :size size)
|
||||
(assoc :disabled (and replying? (not (valid-reply? @reply-input))))
|
||||
(update :style merge common-style))
|
||||
[button/button
|
||||
(-> button-2
|
||||
(assoc :size size)
|
||||
(assoc :disabled (and replying? (not (valid-reply? @reply-input))))
|
||||
(update :style merge common-style))
|
||||
(:label button-2)])]))
|
||||
|
||||
(defn- activity-status
|
||||
[status]
|
||||
[rn/view {:style style/status
|
||||
:accessibility-label :activity-status}
|
||||
[status-tags/status-tag {:size :small
|
||||
:label (:label status)
|
||||
:status status}]])
|
||||
[rn/view
|
||||
{:style style/status
|
||||
:accessibility-label :activity-status}
|
||||
[status-tags/status-tag
|
||||
{:size :small
|
||||
:label (:label status)
|
||||
:status status}]])
|
||||
|
||||
(defn- activity-title
|
||||
[title replying?]
|
||||
[text/text {:weight :semi-bold
|
||||
:accessibility-label :activity-title
|
||||
:style (style/title replying?)
|
||||
:size (if replying? :heading-2 :paragraph-1)}
|
||||
[text/text
|
||||
{:weight :semi-bold
|
||||
:accessibility-label :activity-title
|
||||
:style (style/title replying?)
|
||||
:size (if replying? :heading-2 :paragraph-1)}
|
||||
title])
|
||||
|
||||
(defn- activity-timestamp
|
||||
[timestamp]
|
||||
[text/text {:size :label
|
||||
:accessibility-label :activity-timestamp
|
||||
:style style/timestamp}
|
||||
[text/text
|
||||
{:size :label
|
||||
:accessibility-label :activity-timestamp
|
||||
:style style/timestamp}
|
||||
timestamp])
|
||||
|
||||
(defn- activity-unread-dot
|
||||
[]
|
||||
[rn/view {:accessibility-label :activity-unread-indicator
|
||||
:style style/unread-dot-container}
|
||||
[rn/view
|
||||
{:accessibility-label :activity-unread-indicator
|
||||
:style style/unread-dot-container}
|
||||
[rn/view {:style style/unread-dot}]])
|
||||
|
||||
(defn- footer
|
||||
@ -159,12 +175,14 @@
|
||||
replying?
|
||||
unread?]
|
||||
:as props}]
|
||||
[rn/view {:accessibility-label :activity
|
||||
:style style/container}
|
||||
[rn/view
|
||||
{:accessibility-label :activity
|
||||
:style style/container}
|
||||
(when-not replying?
|
||||
[activity-icon icon])
|
||||
[rn/view {:style {:padding-left (when-not replying? 8)
|
||||
:flex 1}}
|
||||
[rn/view
|
||||
{:style {:padding-left (when-not replying? 8)
|
||||
:flex 1}}
|
||||
[rn/view
|
||||
[rn/view {:style style/top-section-container}
|
||||
[activity-title title replying?]
|
||||
|
@ -1,11 +1,10 @@
|
||||
(ns quo2.components.notifications.count-down-circle
|
||||
(:require
|
||||
[goog.string :as gstring]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[quo2.theme :as theme]
|
||||
[react-native.core :as rn]
|
||||
[react-native.svg :as svg]
|
||||
[reagent.core :as reagent]))
|
||||
(:require [goog.string :as gstring]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[quo2.theme :as theme]
|
||||
[react-native.core :as rn]
|
||||
[react-native.svg :as svg]
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
(defn- get-path-props
|
||||
[size stroke-width rotation]
|
||||
|
@ -1,17 +1,21 @@
|
||||
(ns quo2.components.notifications.info-count
|
||||
(:require [react-native.core :as rn]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[quo2.foundations.typography :as typography]))
|
||||
(:require [quo2.foundations.colors :as colors]
|
||||
[quo2.foundations.typography :as typography]
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(defn info-count [count style]
|
||||
(defn info-count
|
||||
[count style]
|
||||
(when (> count 0)
|
||||
[rn/view {:style (merge {:width 16
|
||||
:height 16
|
||||
:position :absolute
|
||||
:right 22
|
||||
:border-radius 6
|
||||
:justify-content :center
|
||||
:align-items :center
|
||||
:background-color (colors/theme-colors colors/primary-50 colors/primary-60)}
|
||||
style)}
|
||||
[rn/text {:style (merge typography/font-medium typography/label {:color colors/white :text-align :center})} count]]))
|
||||
[rn/view
|
||||
{:style (merge {:width 16
|
||||
:height 16
|
||||
:position :absolute
|
||||
:right 22
|
||||
:border-radius 6
|
||||
:justify-content :center
|
||||
:align-items :center
|
||||
:background-color (colors/theme-colors colors/primary-50 colors/primary-60)}
|
||||
style)}
|
||||
[rn/text
|
||||
{:style (merge typography/font-medium typography/label {:color colors/white :text-align :center})}
|
||||
count]]))
|
||||
|
@ -1,12 +1,14 @@
|
||||
(ns quo2.components.notifications.notification-dot
|
||||
(:require [react-native.core :as rn]
|
||||
[quo2.foundations.colors :as colors]))
|
||||
(:require [quo2.foundations.colors :as colors]
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(defn notification-dot [style]
|
||||
[rn/view {:style (merge {:background-color (colors/theme-colors colors/primary-50 colors/primary-60)
|
||||
:width 8
|
||||
:height 8
|
||||
:border-radius 4
|
||||
:position :absolute
|
||||
:z-index 1}
|
||||
style)}])
|
||||
(defn notification-dot
|
||||
[style]
|
||||
[rn/view
|
||||
{:style (merge {:background-color (colors/theme-colors colors/primary-50 colors/primary-60)
|
||||
:width 8
|
||||
:height 8
|
||||
:border-radius 4
|
||||
:position :absolute
|
||||
:z-index 1}
|
||||
style)}])
|
||||
|
@ -1,12 +1,11 @@
|
||||
(ns quo2.components.notifications.toast
|
||||
(:require
|
||||
[i18n.i18n :as i18n]
|
||||
[quo2.components.icon :as icon]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.components.notifications.count-down-circle :as count-down-circle]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[quo2.theme :as theme]
|
||||
[react-native.core :as rn]))
|
||||
(:require [i18n.i18n :as i18n]
|
||||
[quo2.components.icon :as icon]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.components.notifications.count-down-circle :as count-down-circle]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[quo2.theme :as theme]
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(def ^:private themes
|
||||
{:container {:light {:background-color colors/white-opa-70}
|
||||
|
@ -1,33 +1,33 @@
|
||||
(ns quo2.components.reactions.reaction
|
||||
(:require [quo2.components.markdown.text :as quo2.text]
|
||||
[react-native.core :as rn]
|
||||
[quo2.theme :as theme]
|
||||
(:require [quo2.components.icon :as icons]
|
||||
[quo2.components.markdown.text :as quo2.text]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[quo2.components.icon :as icons]))
|
||||
[quo2.theme :as theme]
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(def reaction-styling
|
||||
{:flex-direction :row
|
||||
:justify-content :center
|
||||
:align-items :center
|
||||
{:flex-direction :row
|
||||
:justify-content :center
|
||||
:align-items :center
|
||||
:padding-horizontal 8
|
||||
:border-radius 8
|
||||
:height 24})
|
||||
:border-radius 8
|
||||
:height 24})
|
||||
|
||||
(defn open-reactions-menu
|
||||
[{:keys [on-press]}]
|
||||
(let [dark? (theme/dark?)]
|
||||
[rn/touchable-opacity
|
||||
{:on-press on-press
|
||||
{:on-press on-press
|
||||
:accessibility-label :emoji-reaction-add
|
||||
:style (merge reaction-styling
|
||||
{:padding-horizontal 9
|
||||
:border-width 1
|
||||
:margin-top 5
|
||||
:border-color (if dark?
|
||||
colors/neutral-70
|
||||
colors/neutral-30)})}
|
||||
:style (merge reaction-styling
|
||||
{:padding-horizontal 9
|
||||
:border-width 1
|
||||
:margin-top 5
|
||||
:border-color (if dark?
|
||||
colors/neutral-70
|
||||
colors/neutral-30)})}
|
||||
[icons/icon :i/add
|
||||
{:size 20
|
||||
{:size 20
|
||||
:color (if dark?
|
||||
colors/white
|
||||
colors/neutral-100)}]]))
|
||||
@ -35,37 +35,41 @@
|
||||
(defn reaction
|
||||
"Add your emoji as a param here"
|
||||
[{:keys [emoji clicks neutral? on-press accessibility-label]}]
|
||||
(let [dark? (theme/dark?)
|
||||
text-color (if dark? colors/white
|
||||
colors/neutral-100)
|
||||
numeric-value (int clicks)
|
||||
(let [dark? (theme/dark?)
|
||||
text-color (if dark?
|
||||
colors/white
|
||||
colors/neutral-100)
|
||||
numeric-value (int clicks)
|
||||
clicks-positive? (pos? numeric-value)]
|
||||
[rn/touchable-opacity
|
||||
{:on-press on-press
|
||||
:accessibility-label accessibility-label
|
||||
:style (merge reaction-styling
|
||||
(cond-> {:background-color
|
||||
(if dark?
|
||||
(if neutral?
|
||||
colors/neutral-70
|
||||
:transparent)
|
||||
(if neutral?
|
||||
colors/neutral-30
|
||||
:transparent))}
|
||||
(cond->
|
||||
{:background-color
|
||||
(if dark?
|
||||
(if neutral?
|
||||
colors/neutral-70
|
||||
:transparent)
|
||||
(if neutral?
|
||||
colors/neutral-30
|
||||
:transparent))}
|
||||
(and dark? (not neutral?))
|
||||
(assoc :border-color colors/neutral-70
|
||||
:border-width 1)
|
||||
(and (not dark?) (not neutral?))
|
||||
(assoc :border-color colors/neutral-30
|
||||
:border-width 1)))}
|
||||
[icons/icon emoji {:no-color true
|
||||
:size 16}]
|
||||
[quo2.text/text {:size :paragraph-2
|
||||
:weight :semi-bold
|
||||
:color text-color
|
||||
:flex-direction :row
|
||||
:align-items :center
|
||||
:justify-content :center}
|
||||
[icons/icon emoji
|
||||
{:no-color true
|
||||
:size 16}]
|
||||
[quo2.text/text
|
||||
{:size :paragraph-2
|
||||
:weight :semi-bold
|
||||
:color text-color
|
||||
:flex-direction :row
|
||||
:align-items :center
|
||||
:justify-content :center}
|
||||
(if clicks-positive?
|
||||
(str " " numeric-value)
|
||||
"")]]))
|
||||
|
@ -2,7 +2,8 @@
|
||||
(:require [quo2.foundations.colors :as colors]
|
||||
[react-native.reanimated :as reanimated]))
|
||||
|
||||
(defn animated-circle [scale opacity color]
|
||||
(defn animated-circle
|
||||
[scale opacity color]
|
||||
(reanimated/apply-animations-to-style
|
||||
{:transform [{:scale scale}]
|
||||
:opacity opacity}
|
||||
@ -16,11 +17,12 @@
|
||||
:align-items :center
|
||||
:z-index 0}))
|
||||
|
||||
(defn record-button-big-container [translate-x translate-y opacity]
|
||||
(defn record-button-big-container
|
||||
[translate-x translate-y opacity]
|
||||
(reanimated/apply-animations-to-style
|
||||
{:transform [{:translateY translate-y}
|
||||
{:translateX translate-x}]
|
||||
:opacity opacity}
|
||||
:opacity opacity}
|
||||
{:position :absolute
|
||||
:bottom 0
|
||||
:right 0
|
||||
@ -30,7 +32,8 @@
|
||||
:justify-content :center
|
||||
:z-index 0}))
|
||||
|
||||
(defn record-button-big-body [button-color]
|
||||
(defn record-button-big-body
|
||||
[button-color]
|
||||
{:width 56
|
||||
:height 56
|
||||
:border-radius 28
|
||||
@ -39,7 +42,8 @@
|
||||
:background-color button-color
|
||||
:overflow :hidden})
|
||||
|
||||
(defn record-button-big-red-overlay [red-overlay-opacity]
|
||||
(defn record-button-big-red-overlay
|
||||
[red-overlay-opacity]
|
||||
(reanimated/apply-animations-to-style
|
||||
{:opacity red-overlay-opacity}
|
||||
{:position :absolute
|
||||
@ -49,7 +53,8 @@
|
||||
:bottom 0
|
||||
:background-color colors/danger-50}))
|
||||
|
||||
(defn record-button-big-gray-overlay [gray-overlay-opacity]
|
||||
(defn record-button-big-gray-overlay
|
||||
[gray-overlay-opacity]
|
||||
(reanimated/apply-animations-to-style
|
||||
{:opacity gray-overlay-opacity}
|
||||
{:position :absolute
|
||||
@ -59,7 +64,8 @@
|
||||
:bottom 0
|
||||
:background-color (colors/theme-colors colors/neutral-80-opa-5-opaque colors/neutral-80)}))
|
||||
|
||||
(defn record-button-big-icon-container [icon-opacity]
|
||||
(defn record-button-big-icon-container
|
||||
[icon-opacity]
|
||||
(reanimated/apply-animations-to-style
|
||||
{:opacity icon-opacity}
|
||||
{}))
|
||||
@ -70,7 +76,8 @@
|
||||
:border-radius 4
|
||||
:background-color colors/white})
|
||||
|
||||
(defn send-button-container [opacity]
|
||||
(defn send-button-container
|
||||
[opacity]
|
||||
(reanimated/apply-animations-to-style
|
||||
{:opacity opacity}
|
||||
{:justify-content :center
|
||||
@ -81,7 +88,8 @@
|
||||
:top 0
|
||||
:right 20}))
|
||||
|
||||
(defn send-button-connector [opacity width height border-radius-first-half border-radius-second-half]
|
||||
(defn send-button-connector
|
||||
[opacity width height border-radius-first-half border-radius-second-half]
|
||||
(reanimated/apply-animations-to-style
|
||||
{:opacity opacity
|
||||
:width width
|
||||
@ -96,7 +104,8 @@
|
||||
:background-color colors/primary-50
|
||||
:z-index 0}))
|
||||
|
||||
(defn send-button [translate-y opacity]
|
||||
(defn send-button
|
||||
[translate-y opacity]
|
||||
(reanimated/apply-animations-to-style
|
||||
{:transform [{:translateY translate-y}]
|
||||
:opacity opacity}
|
||||
@ -114,7 +123,8 @@
|
||||
(def send-icon-container
|
||||
{:z-index 10})
|
||||
|
||||
(defn lock-button-container [opacity]
|
||||
(defn lock-button-container
|
||||
[opacity]
|
||||
(reanimated/apply-animations-to-style
|
||||
{:opacity opacity}
|
||||
{:transform [{:rotate "45deg"}]
|
||||
@ -126,7 +136,8 @@
|
||||
:top 20
|
||||
:left 20}))
|
||||
|
||||
(defn lock-button-connector [opacity width height border-radius-first-half border-radius-second-half]
|
||||
(defn lock-button-connector
|
||||
[opacity width height border-radius-first-half border-radius-second-half]
|
||||
(reanimated/apply-animations-to-style
|
||||
{:opacity opacity
|
||||
:width width
|
||||
@ -141,7 +152,8 @@
|
||||
:background-color (colors/theme-colors colors/neutral-80-opa-5-opaque colors/neutral-80)
|
||||
:overflow :hidden}))
|
||||
|
||||
(defn lock-button [translate-x-y opacity]
|
||||
(defn lock-button
|
||||
[translate-x-y opacity]
|
||||
(reanimated/apply-animations-to-style
|
||||
{:transform [{:translateX translate-x-y}
|
||||
{:translateY translate-x-y}]
|
||||
@ -158,7 +170,8 @@
|
||||
:overflow :hidden
|
||||
:z-index 12}))
|
||||
|
||||
(defn delete-button-container [opacity]
|
||||
(defn delete-button-container
|
||||
[opacity]
|
||||
(reanimated/apply-animations-to-style
|
||||
{:opacity opacity}
|
||||
{:justify-content :center
|
||||
@ -169,7 +182,8 @@
|
||||
:bottom 20
|
||||
:left 0}))
|
||||
|
||||
(defn delete-button-connector [opacity width height border-radius-first-half border-radius-second-half]
|
||||
(defn delete-button-connector
|
||||
[opacity width height border-radius-first-half border-radius-second-half]
|
||||
(reanimated/apply-animations-to-style
|
||||
{:opacity opacity
|
||||
:width width
|
||||
@ -184,7 +198,8 @@
|
||||
:background-color colors/danger-50
|
||||
:z-index 0}))
|
||||
|
||||
(defn delete-button [translate-x opacity]
|
||||
(defn delete-button
|
||||
[translate-x opacity]
|
||||
(reanimated/apply-animations-to-style
|
||||
{:transform [{:translateX translate-x}]
|
||||
:opacity opacity}
|
||||
@ -199,9 +214,10 @@
|
||||
:left 0
|
||||
:z-index 11}))
|
||||
|
||||
(defn record-button-container [opacity]
|
||||
(defn record-button-container
|
||||
[opacity]
|
||||
(reanimated/apply-animations-to-style
|
||||
{:opacity opacity}
|
||||
{:opacity opacity}
|
||||
{:margin-bottom 32
|
||||
:margin-right 32}))
|
||||
|
||||
|
@ -1,15 +1,15 @@
|
||||
(ns quo2.components.record-audio.record-audio.view
|
||||
(:require [quo.react :refer [memo effect!]]
|
||||
[react-native.core :as rn]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[quo2.components.icon :as icons]
|
||||
(:require [cljs-bean.core :as bean]
|
||||
[oops.core :as oops]
|
||||
[quo.react :refer [effect! memo]]
|
||||
[quo2.components.buttons.button :as button]
|
||||
[quo2.components.icon :as icons]
|
||||
[quo2.components.record-audio.record-audio.style :as style]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[react-native.core :as rn]
|
||||
[react-native.reanimated :as reanimated]
|
||||
[reagent.core :as reagent]
|
||||
[cljs-bean.core :as bean]
|
||||
[quo2.components.record-audio.record-audio.style :as style]
|
||||
[status-im.utils.utils :as utils]
|
||||
[oops.core :as oops]))
|
||||
[status-im.utils.utils :as utils]))
|
||||
|
||||
(def ^:private scale-to-each 1.8)
|
||||
(def ^:private scale-to-total 2.6)
|
||||
@ -39,26 +39,30 @@
|
||||
:x 68
|
||||
:y 68})
|
||||
|
||||
(defn- delete-button-area [active?]
|
||||
(defn- delete-button-area
|
||||
[active?]
|
||||
{:width (if active? 72 82)
|
||||
:height 56
|
||||
:x (if active? -16 -32)
|
||||
:y (if active? 64 70)})
|
||||
|
||||
(defn- lock-button-area [active?]
|
||||
(defn- lock-button-area
|
||||
[active?]
|
||||
{:width (if active? 72 100)
|
||||
:height (if active? 72 102)
|
||||
:x -32
|
||||
:y -32})
|
||||
|
||||
(defn- send-button-area [active?]
|
||||
(defn- send-button-area
|
||||
[active?]
|
||||
{:width 56
|
||||
:height (if active? 72 92)
|
||||
:x 68
|
||||
:y (if active? -16 -32)})
|
||||
|
||||
(defn- touch-inside-area? [{:keys [location-x location-y ignore-min-y? ignore-max-y? ignore-min-x? ignore-max-x?]}
|
||||
{:keys [width height x y]}]
|
||||
(defn- touch-inside-area?
|
||||
[{:keys [location-x location-y ignore-min-y? ignore-max-y? ignore-min-x? ignore-max-x?]}
|
||||
{:keys [width height x y]}]
|
||||
(let [max-x (+ x width)
|
||||
max-y (+ y height)]
|
||||
(and
|
||||
@ -71,12 +75,16 @@
|
||||
|
||||
(def record-audio-worklets (js/require "../src/js/record_audio_worklets.js"))
|
||||
|
||||
(defn- ring-scale [scale substract]
|
||||
(defn- ring-scale
|
||||
[scale substract]
|
||||
(.ringScale ^js record-audio-worklets
|
||||
scale
|
||||
substract))
|
||||
|
||||
(defn- record-button-big [recording? ready-to-send? ready-to-lock? ready-to-delete? record-button-is-animating? record-button-at-initial-position? locked? reviewing-audio? recording-timer recording-length-ms clear-timeout touch-active?]
|
||||
(defn- record-button-big
|
||||
[recording? ready-to-send? ready-to-lock? ready-to-delete? record-button-is-animating?
|
||||
record-button-at-initial-position? locked? reviewing-audio? recording-timer recording-length-ms
|
||||
clear-timeout touch-active?]
|
||||
[:f>
|
||||
(fn []
|
||||
(let [scale (reanimated/use-shared-value 1)
|
||||
@ -85,13 +93,16 @@
|
||||
animations (map
|
||||
(fn [index]
|
||||
(let [ring-scale (ring-scale scale (* scale-padding index))]
|
||||
{:scale ring-scale
|
||||
:opacity (reanimated/interpolate ring-scale [1 scale-to-each] [opacity-from 0])}))
|
||||
{:scale ring-scale
|
||||
:opacity (reanimated/interpolate ring-scale
|
||||
[1 scale-to-each]
|
||||
[opacity-from 0])}))
|
||||
(range 0 5))
|
||||
rings-color (cond
|
||||
@ready-to-lock? (colors/theme-colors colors/neutral-80-opa-5-opaque colors/neutral-80)
|
||||
@ready-to-lock? (colors/theme-colors colors/neutral-80-opa-5-opaque
|
||||
colors/neutral-80)
|
||||
@ready-to-delete? colors/danger-50
|
||||
:else colors/primary-50)
|
||||
:else colors/primary-50)
|
||||
translate-y (reanimated/use-shared-value 0)
|
||||
translate-x (reanimated/use-shared-value 0)
|
||||
button-color colors/primary-50
|
||||
@ -115,12 +126,25 @@
|
||||
(reset! recording-length-ms 0))))
|
||||
start-animation (fn []
|
||||
(reanimated/set-shared-value opacity 1)
|
||||
(reanimated/animate-shared-value-with-timing scale 2.6 signal-anim-duration :linear)
|
||||
;; TODO: Research if we can implement this with withSequence method from Reanimated 2
|
||||
;; GitHub issue [#14561]: https://github.com/status-im/status-mobile/issues/14561
|
||||
(reset! clear-timeout (utils/set-timeout #(do (reanimated/set-shared-value scale scale-to-each)
|
||||
(reanimated/animate-shared-value-with-delay-repeat scale scale-to-total signal-anim-duration-2 :linear 0 -1))
|
||||
signal-anim-duration)))
|
||||
(reanimated/animate-shared-value-with-timing scale
|
||||
2.6
|
||||
signal-anim-duration
|
||||
:linear)
|
||||
;; TODO: Research if we can implement this with withSequence method
|
||||
;; from Reanimated 2
|
||||
;; GitHub issue [#14561]:
|
||||
;; https://github.com/status-im/status-mobile/issues/14561
|
||||
(reset! clear-timeout
|
||||
(utils/set-timeout
|
||||
#(do (reanimated/set-shared-value scale scale-to-each)
|
||||
(reanimated/animate-shared-value-with-delay-repeat
|
||||
scale
|
||||
scale-to-total
|
||||
signal-anim-duration-2
|
||||
:linear
|
||||
0
|
||||
-1))
|
||||
signal-anim-duration)))
|
||||
stop-animation (fn []
|
||||
(reanimated/set-shared-value opacity 0)
|
||||
(reanimated/cancel-animation scale)
|
||||
@ -129,48 +153,105 @@
|
||||
start-y-animation (fn []
|
||||
(reset! record-button-at-initial-position? false)
|
||||
(reset! record-button-is-animating? true)
|
||||
(reanimated/animate-shared-value-with-timing translate-y -64 250 :easing1)
|
||||
(reanimated/animate-shared-value-with-delay icon-opacity 0 33.33 :linear 76.66)
|
||||
(reanimated/animate-shared-value-with-timing translate-y
|
||||
-64
|
||||
250
|
||||
:easing1)
|
||||
(reanimated/animate-shared-value-with-delay icon-opacity
|
||||
0 33.33
|
||||
:linear 76.66)
|
||||
(utils/set-timeout (fn []
|
||||
(reset! record-button-is-animating? false)
|
||||
(when-not @touch-active? (complete-animation)))
|
||||
250))
|
||||
reset-y-animation (fn []
|
||||
(reanimated/animate-shared-value-with-timing translate-y 0 300 :easing1)
|
||||
(reanimated/animate-shared-value-with-timing icon-opacity 1 500 :linear)
|
||||
(utils/set-timeout (fn [] (reset! record-button-at-initial-position? true)) 500))
|
||||
(reanimated/animate-shared-value-with-timing translate-y
|
||||
0
|
||||
300
|
||||
:easing1)
|
||||
(reanimated/animate-shared-value-with-timing icon-opacity
|
||||
1
|
||||
500
|
||||
:linear)
|
||||
(utils/set-timeout (fn []
|
||||
(reset! record-button-at-initial-position? true))
|
||||
500))
|
||||
start-x-animation (fn []
|
||||
(reset! record-button-at-initial-position? false)
|
||||
(reset! record-button-is-animating? true)
|
||||
(reanimated/animate-shared-value-with-timing translate-x -64 250 :easing1)
|
||||
(reanimated/animate-shared-value-with-delay icon-opacity 0 33.33 :linear 76.66)
|
||||
(reanimated/animate-shared-value-with-timing red-overlay-opacity 1 33.33 :linear)
|
||||
(reanimated/animate-shared-value-with-timing translate-x
|
||||
-64
|
||||
250
|
||||
:easing1)
|
||||
(reanimated/animate-shared-value-with-delay icon-opacity
|
||||
0 33.33
|
||||
:linear 76.66)
|
||||
(reanimated/animate-shared-value-with-timing red-overlay-opacity
|
||||
1
|
||||
33.33
|
||||
:linear)
|
||||
(utils/set-timeout (fn []
|
||||
(reset! record-button-is-animating? false)
|
||||
(when-not @touch-active? (complete-animation)))
|
||||
250))
|
||||
reset-x-animation (fn []
|
||||
(reanimated/animate-shared-value-with-timing translate-x 0 300 :easing1)
|
||||
(reanimated/animate-shared-value-with-timing icon-opacity 1 500 :linear)
|
||||
(reanimated/animate-shared-value-with-timing red-overlay-opacity 0 100 :linear)
|
||||
(utils/set-timeout (fn [] (reset! record-button-at-initial-position? true)) 500))
|
||||
(reanimated/animate-shared-value-with-timing translate-x
|
||||
0
|
||||
300
|
||||
:easing1)
|
||||
(reanimated/animate-shared-value-with-timing icon-opacity
|
||||
1
|
||||
500
|
||||
:linear)
|
||||
(reanimated/animate-shared-value-with-timing red-overlay-opacity
|
||||
0
|
||||
100
|
||||
:linear)
|
||||
(utils/set-timeout (fn []
|
||||
(reset! record-button-at-initial-position? true))
|
||||
500))
|
||||
start-x-y-animation (fn []
|
||||
(reset! record-button-at-initial-position? false)
|
||||
(reset! record-button-is-animating? true)
|
||||
(reanimated/animate-shared-value-with-timing translate-y -44 200 :easing1)
|
||||
(reanimated/animate-shared-value-with-timing translate-x -44 200 :easing1)
|
||||
(reanimated/animate-shared-value-with-delay icon-opacity 0 33.33 :linear 33.33)
|
||||
(reanimated/animate-shared-value-with-timing gray-overlay-opacity 1 33.33 :linear)
|
||||
(reanimated/animate-shared-value-with-timing translate-y
|
||||
-44
|
||||
200
|
||||
:easing1)
|
||||
(reanimated/animate-shared-value-with-timing translate-x
|
||||
-44
|
||||
200
|
||||
:easing1)
|
||||
(reanimated/animate-shared-value-with-delay icon-opacity
|
||||
0 33.33
|
||||
:linear 33.33)
|
||||
(reanimated/animate-shared-value-with-timing gray-overlay-opacity
|
||||
1
|
||||
33.33
|
||||
:linear)
|
||||
(utils/set-timeout (fn []
|
||||
(reset! record-button-is-animating? false)
|
||||
(when-not @touch-active? (complete-animation)))
|
||||
200))
|
||||
reset-x-y-animation (fn []
|
||||
(reanimated/animate-shared-value-with-timing translate-y 0 300 :easing1)
|
||||
(reanimated/animate-shared-value-with-timing translate-x 0 300 :easing1)
|
||||
(reanimated/animate-shared-value-with-timing icon-opacity 1 500 :linear)
|
||||
(reanimated/animate-shared-value-with-timing gray-overlay-opacity 0 800 :linear)
|
||||
(utils/set-timeout (fn [] (reset! record-button-at-initial-position? true)) 800))]
|
||||
(reanimated/animate-shared-value-with-timing translate-y
|
||||
0
|
||||
300
|
||||
:easing1)
|
||||
(reanimated/animate-shared-value-with-timing translate-x
|
||||
0
|
||||
300
|
||||
:easing1)
|
||||
(reanimated/animate-shared-value-with-timing icon-opacity
|
||||
1
|
||||
500
|
||||
:linear)
|
||||
(reanimated/animate-shared-value-with-timing gray-overlay-opacity
|
||||
0
|
||||
800
|
||||
:linear)
|
||||
(utils/set-timeout (fn []
|
||||
(reset! record-button-at-initial-position? true))
|
||||
800))]
|
||||
(effect! #(cond
|
||||
@recording?
|
||||
(start-animation)
|
||||
@ -189,15 +270,17 @@
|
||||
(start-x-animation)
|
||||
(reset-x-animation))
|
||||
[@ready-to-delete?])
|
||||
[reanimated/view {:style (style/record-button-big-container translate-x translate-y opacity)
|
||||
:pointer-events :none}
|
||||
[reanimated/view
|
||||
{:style (style/record-button-big-container translate-x translate-y opacity)
|
||||
:pointer-events :none}
|
||||
[:<>
|
||||
(map-indexed
|
||||
(fn [id animation]
|
||||
^{:key id}
|
||||
[animated-ring {:scale (:scale animation)
|
||||
:opacity (:opacity animation)
|
||||
:color rings-color}])
|
||||
[animated-ring
|
||||
{:scale (:scale animation)
|
||||
:opacity (:opacity animation)
|
||||
:color rings-color}])
|
||||
animations)]
|
||||
[rn/view {:style (style/record-button-big-body button-color)}
|
||||
[reanimated/view {:style (style/record-button-big-red-overlay red-overlay-opacity)}]
|
||||
@ -207,7 +290,8 @@
|
||||
[rn/view {:style style/stop-icon}]
|
||||
[icons/icon :i/audio {:color icon-color}])]]]))])
|
||||
|
||||
(defn- send-button [recording? ready-to-send? reviewing-audio?]
|
||||
(defn- send-button
|
||||
[recording? ready-to-send? reviewing-audio?]
|
||||
[:f>
|
||||
(fn []
|
||||
(let [opacity (reanimated/use-shared-value 0)
|
||||
@ -218,33 +302,70 @@
|
||||
border-radius-first-half (reanimated/use-shared-value 16)
|
||||
border-radius-second-half (reanimated/use-shared-value 8)
|
||||
start-y-animation (fn []
|
||||
(reanimated/animate-shared-value-with-delay translate-y 12 50 :linear 133.33)
|
||||
(reanimated/animate-shared-value-with-delay connector-opacity 1 0 :easing1 93.33)
|
||||
(reanimated/animate-shared-value-with-delay width 56 83.33 :easing1 80)
|
||||
(reanimated/animate-shared-value-with-delay height 56 83.33 :easing1 80)
|
||||
(reanimated/animate-shared-value-with-delay border-radius-first-half 28 83.33 :easing1 80)
|
||||
(reanimated/animate-shared-value-with-delay border-radius-second-half 28 83.33 :easing1 80))
|
||||
(reanimated/animate-shared-value-with-delay translate-y
|
||||
12 50
|
||||
:linear 133.33)
|
||||
(reanimated/animate-shared-value-with-delay connector-opacity
|
||||
1 0
|
||||
:easing1 93.33)
|
||||
(reanimated/animate-shared-value-with-delay width
|
||||
56 83.33
|
||||
:easing1 80)
|
||||
(reanimated/animate-shared-value-with-delay height
|
||||
56 83.33
|
||||
:easing1 80)
|
||||
(reanimated/animate-shared-value-with-delay
|
||||
border-radius-first-half
|
||||
28 83.33
|
||||
:easing1 80)
|
||||
(reanimated/animate-shared-value-with-delay
|
||||
border-radius-second-half
|
||||
28 83.33
|
||||
:easing1 80))
|
||||
reset-y-animation (fn []
|
||||
(reanimated/animate-shared-value-with-timing translate-y 0 100 :linear)
|
||||
(reanimated/animate-shared-value-with-timing translate-y
|
||||
0
|
||||
100
|
||||
:linear)
|
||||
(reanimated/set-shared-value connector-opacity 0)
|
||||
(reanimated/set-shared-value width 12)
|
||||
(reanimated/set-shared-value height 24)
|
||||
(reanimated/set-shared-value border-radius-first-half 16)
|
||||
(reanimated/set-shared-value border-radius-second-half 8))
|
||||
fade-in-animation (fn []
|
||||
(reanimated/animate-shared-value-with-timing translate-y 0 200 :linear)
|
||||
(reanimated/animate-shared-value-with-timing opacity 1 200 :linear))
|
||||
(reanimated/animate-shared-value-with-timing translate-y
|
||||
0
|
||||
200
|
||||
:linear)
|
||||
(reanimated/animate-shared-value-with-timing opacity
|
||||
1
|
||||
200
|
||||
:linear))
|
||||
fade-out-animation (fn []
|
||||
(reanimated/animate-shared-value-with-timing translate-y (if @reviewing-audio? 76 20) 200 :linear)
|
||||
(when-not @reviewing-audio? (reanimated/animate-shared-value-with-timing opacity 0 200 :linear))
|
||||
(reanimated/animate-shared-value-with-timing translate-y
|
||||
(if @reviewing-audio?
|
||||
76
|
||||
20)
|
||||
200
|
||||
:linear)
|
||||
(when-not @reviewing-audio?
|
||||
(reanimated/animate-shared-value-with-timing opacity
|
||||
0
|
||||
200
|
||||
:linear))
|
||||
(reanimated/set-shared-value connector-opacity 0)
|
||||
(reanimated/set-shared-value width 24)
|
||||
(reanimated/set-shared-value height 12)
|
||||
(reanimated/set-shared-value border-radius-first-half 8)
|
||||
(reanimated/set-shared-value border-radius-second-half 16))
|
||||
fade-out-reset-animation (fn []
|
||||
(reanimated/animate-shared-value-with-timing opacity 0 200 :linear)
|
||||
(reanimated/animate-shared-value-with-delay translate-y 20 0 :linear 200)
|
||||
(reanimated/animate-shared-value-with-timing opacity
|
||||
0
|
||||
200
|
||||
:linear)
|
||||
(reanimated/animate-shared-value-with-delay translate-y
|
||||
20 0
|
||||
:linear 200)
|
||||
(reanimated/set-shared-value connector-opacity 0)
|
||||
(reanimated/set-shared-value width 24)
|
||||
(reanimated/set-shared-value height 12)
|
||||
@ -260,18 +381,26 @@
|
||||
(effect! #(cond
|
||||
@ready-to-send?
|
||||
(start-y-animation)
|
||||
@recording? (reset-y-animation))
|
||||
@recording? (reset-y-animation))
|
||||
[@ready-to-send?])
|
||||
[:<>
|
||||
[reanimated/view {:style (style/send-button-container opacity)}
|
||||
[reanimated/view {:style (style/send-button-connector connector-opacity width height border-radius-first-half border-radius-second-half)}]]
|
||||
[reanimated/view {:style (style/send-button translate-y opacity)
|
||||
:pointer-events :none}
|
||||
[icons/icon :i/arrow-up {:color colors/white
|
||||
:size 20
|
||||
:container-style style/send-icon-container}]]]))])
|
||||
[reanimated/view
|
||||
{:style (style/send-button-connector connector-opacity
|
||||
width
|
||||
height
|
||||
border-radius-first-half
|
||||
border-radius-second-half)}]]
|
||||
[reanimated/view
|
||||
{:style (style/send-button translate-y opacity)
|
||||
:pointer-events :none}
|
||||
[icons/icon :i/arrow-up
|
||||
{:color colors/white
|
||||
:size 20
|
||||
:container-style style/send-icon-container}]]]))])
|
||||
|
||||
(defn- lock-button [recording? ready-to-lock? locked?]
|
||||
(defn- lock-button
|
||||
[recording? ready-to-lock? locked?]
|
||||
[:f>
|
||||
(fn []
|
||||
(let [translate-x-y (reanimated/use-shared-value 20)
|
||||
@ -282,25 +411,54 @@
|
||||
border-radius-first-half (reanimated/use-shared-value 8)
|
||||
border-radius-second-half (reanimated/use-shared-value 8)
|
||||
start-x-y-animation (fn []
|
||||
(reanimated/animate-shared-value-with-delay translate-x-y 8 50 :linear 116.66)
|
||||
(reanimated/animate-shared-value-with-delay connector-opacity 1 0 :easing1 80)
|
||||
(reanimated/animate-shared-value-with-delay width 56 83.33 :easing1 63.33)
|
||||
(reanimated/animate-shared-value-with-delay height 56 83.33 :easing1 63.33)
|
||||
(reanimated/animate-shared-value-with-delay border-radius-first-half 28 83.33 :easing1 63.33)
|
||||
(reanimated/animate-shared-value-with-delay border-radius-second-half 28 83.33 :easing1 63.33))
|
||||
(reanimated/animate-shared-value-with-delay translate-x-y
|
||||
8 50
|
||||
:linear 116.66)
|
||||
(reanimated/animate-shared-value-with-delay connector-opacity
|
||||
1 0
|
||||
:easing1 80)
|
||||
(reanimated/animate-shared-value-with-delay width
|
||||
56 83.33
|
||||
:easing1 63.33)
|
||||
(reanimated/animate-shared-value-with-delay height
|
||||
56 83.33
|
||||
:easing1 63.33)
|
||||
(reanimated/animate-shared-value-with-delay
|
||||
border-radius-first-half
|
||||
28 83.33
|
||||
:easing1 63.33)
|
||||
(reanimated/animate-shared-value-with-delay
|
||||
border-radius-second-half
|
||||
28 83.33
|
||||
:easing1 63.33))
|
||||
reset-x-y-animation (fn []
|
||||
(reanimated/animate-shared-value-with-timing translate-x-y 0 100 :linear)
|
||||
(reanimated/animate-shared-value-with-timing translate-x-y
|
||||
0
|
||||
100
|
||||
:linear)
|
||||
(reanimated/set-shared-value connector-opacity 0)
|
||||
(reanimated/set-shared-value width 24)
|
||||
(reanimated/set-shared-value height 12)
|
||||
(reanimated/set-shared-value border-radius-first-half 8)
|
||||
(reanimated/set-shared-value border-radius-second-half 16))
|
||||
fade-in-animation (fn []
|
||||
(reanimated/animate-shared-value-with-timing translate-x-y 0 220 :linear)
|
||||
(reanimated/animate-shared-value-with-timing opacity 1 220 :linear))
|
||||
(reanimated/animate-shared-value-with-timing translate-x-y
|
||||
0
|
||||
220
|
||||
:linear)
|
||||
(reanimated/animate-shared-value-with-timing opacity
|
||||
1
|
||||
220
|
||||
:linear))
|
||||
fade-out-animation (fn []
|
||||
(reanimated/animate-shared-value-with-timing translate-x-y 20 200 :linear)
|
||||
(reanimated/animate-shared-value-with-timing opacity 0 200 :linear)
|
||||
(reanimated/animate-shared-value-with-timing translate-x-y
|
||||
20
|
||||
200
|
||||
:linear)
|
||||
(reanimated/animate-shared-value-with-timing opacity
|
||||
0
|
||||
200
|
||||
:linear)
|
||||
(reanimated/set-shared-value connector-opacity 0)
|
||||
(reanimated/set-shared-value width 24)
|
||||
(reanimated/set-shared-value height 12)
|
||||
@ -322,14 +480,21 @@
|
||||
[@locked?])
|
||||
[:<>
|
||||
[reanimated/view {:style (style/lock-button-container opacity)}
|
||||
[reanimated/view {:style (style/lock-button-connector connector-opacity width height border-radius-first-half border-radius-second-half)}]]
|
||||
[reanimated/view {:style (style/lock-button translate-x-y opacity)
|
||||
:pointer-events :none}
|
||||
[reanimated/view
|
||||
{:style (style/lock-button-connector connector-opacity
|
||||
width
|
||||
height
|
||||
border-radius-first-half
|
||||
border-radius-second-half)}]]
|
||||
[reanimated/view
|
||||
{:style (style/lock-button translate-x-y opacity)
|
||||
:pointer-events :none}
|
||||
[icons/icon (if @ready-to-lock? :i/locked :i/unlocked)
|
||||
{:color (colors/theme-colors colors/black colors/white)
|
||||
:size 20}]]]))])
|
||||
|
||||
(defn- delete-button [recording? ready-to-delete?]
|
||||
(defn- delete-button
|
||||
[recording? ready-to-delete?]
|
||||
[:f>
|
||||
(fn []
|
||||
(let [opacity (reanimated/use-shared-value 0)
|
||||
@ -340,25 +505,54 @@
|
||||
border-radius-first-half (reanimated/use-shared-value 8)
|
||||
border-radius-second-half (reanimated/use-shared-value 8)
|
||||
start-x-animation (fn []
|
||||
(reanimated/animate-shared-value-with-delay translate-x 12 50 :linear 133.33)
|
||||
(reanimated/animate-shared-value-with-delay connector-opacity 1 0 :easing1 93.33)
|
||||
(reanimated/animate-shared-value-with-delay width 56 83.33 :easing1 80)
|
||||
(reanimated/animate-shared-value-with-delay height 56 83.33 :easing1 80)
|
||||
(reanimated/animate-shared-value-with-delay border-radius-first-half 28 83.33 :easing1 80)
|
||||
(reanimated/animate-shared-value-with-delay border-radius-second-half 28 83.33 :easing1 80))
|
||||
(reanimated/animate-shared-value-with-delay translate-x
|
||||
12 50
|
||||
:linear 133.33)
|
||||
(reanimated/animate-shared-value-with-delay connector-opacity
|
||||
1 0
|
||||
:easing1 93.33)
|
||||
(reanimated/animate-shared-value-with-delay width
|
||||
56 83.33
|
||||
:easing1 80)
|
||||
(reanimated/animate-shared-value-with-delay height
|
||||
56 83.33
|
||||
:easing1 80)
|
||||
(reanimated/animate-shared-value-with-delay
|
||||
border-radius-first-half
|
||||
28 83.33
|
||||
:easing1 80)
|
||||
(reanimated/animate-shared-value-with-delay
|
||||
border-radius-second-half
|
||||
28 83.33
|
||||
:easing1 80))
|
||||
reset-x-animation (fn []
|
||||
(reanimated/animate-shared-value-with-timing translate-x 0 100 :linear)
|
||||
(reanimated/animate-shared-value-with-timing translate-x
|
||||
0
|
||||
100
|
||||
:linear)
|
||||
(reanimated/set-shared-value connector-opacity 0)
|
||||
(reanimated/set-shared-value width 24)
|
||||
(reanimated/set-shared-value height 12)
|
||||
(reanimated/set-shared-value border-radius-first-half 8)
|
||||
(reanimated/set-shared-value border-radius-second-half 16))
|
||||
fade-in-animation (fn []
|
||||
(reanimated/animate-shared-value-with-timing translate-x 0 200 :linear)
|
||||
(reanimated/animate-shared-value-with-timing opacity 1 200 :linear))
|
||||
(reanimated/animate-shared-value-with-timing translate-x
|
||||
0
|
||||
200
|
||||
:linear)
|
||||
(reanimated/animate-shared-value-with-timing opacity
|
||||
1
|
||||
200
|
||||
:linear))
|
||||
fade-out-animation (fn []
|
||||
(reanimated/animate-shared-value-with-timing translate-x 20 200 :linear)
|
||||
(reanimated/animate-shared-value-with-timing opacity 0 200 :linear)
|
||||
(reanimated/animate-shared-value-with-timing translate-x
|
||||
20
|
||||
200
|
||||
:linear)
|
||||
(reanimated/animate-shared-value-with-timing opacity
|
||||
0
|
||||
200
|
||||
:linear)
|
||||
(reanimated/set-shared-value connector-opacity 0)
|
||||
(reanimated/set-shared-value width 24)
|
||||
(reanimated/set-shared-value height 12)
|
||||
@ -376,13 +570,21 @@
|
||||
[@ready-to-delete?])
|
||||
[:<>
|
||||
[reanimated/view {:style (style/delete-button-container opacity)}
|
||||
[reanimated/view {:style (style/delete-button-connector connector-opacity width height border-radius-first-half border-radius-second-half)}]]
|
||||
[reanimated/view {:style (style/delete-button translate-x opacity)
|
||||
:pointer-events :none}
|
||||
[icons/icon :i/delete {:color colors/white
|
||||
:size 20}]]]))])
|
||||
[reanimated/view
|
||||
{:style (style/delete-button-connector connector-opacity
|
||||
width
|
||||
height
|
||||
border-radius-first-half
|
||||
border-radius-second-half)}]]
|
||||
[reanimated/view
|
||||
{:style (style/delete-button translate-x opacity)
|
||||
:pointer-events :none}
|
||||
[icons/icon :i/delete
|
||||
{:color colors/white
|
||||
:size 20}]]]))])
|
||||
|
||||
(defn- record-button [recording? reviewing-audio?]
|
||||
(defn- record-button
|
||||
[recording? reviewing-audio?]
|
||||
[:f>
|
||||
(fn []
|
||||
(let [opacity (reanimated/use-shared-value 1)
|
||||
@ -393,13 +595,15 @@
|
||||
(show-animation))
|
||||
[@recording? @reviewing-audio?])
|
||||
[reanimated/view {:style (style/record-button-container opacity)}
|
||||
[button/button {:type :outline
|
||||
:size 32
|
||||
:width 32
|
||||
:accessibility-label :mic-button}
|
||||
[button/button
|
||||
{:type :outline
|
||||
:size 32
|
||||
:width 32
|
||||
:accessibility-label :mic-button}
|
||||
[icons/icon :i/audio {:color (colors/theme-colors colors/neutral-100 colors/white)}]]]))])
|
||||
|
||||
(defn input-view []
|
||||
(defn input-view
|
||||
[]
|
||||
[:f>
|
||||
(fn []
|
||||
(let [recording? (reagent/atom false)
|
||||
@ -414,126 +618,136 @@
|
||||
touch-active? (atom false)
|
||||
recording-timer (atom nil)
|
||||
recording-length-ms (atom 0)
|
||||
on-start-should-set-responder (fn [^js e]
|
||||
(when-not @locked?
|
||||
(let [pressed-record-button? (touch-inside-area?
|
||||
{:location-x (oops/oget e "nativeEvent.locationX")
|
||||
:location-y (oops/oget e "nativeEvent.locationY")
|
||||
:ignore-min-y? false
|
||||
:ignore-max-y? false
|
||||
:ignore-min-x? false
|
||||
:ignore-max-x? false}
|
||||
record-button-area)]
|
||||
(when-not @reviewing-audio?
|
||||
(reset! recording? pressed-record-button?)
|
||||
(when pressed-record-button?
|
||||
;; TODO: By now we just track recording length, we need to add actual audio recording logic
|
||||
;; GitHub issue [#14558]: https://github.com/status-im/status-mobile/issues/14558
|
||||
(reset! recording-timer (utils/set-interval #(reset! recording-length-ms (+ @recording-length-ms 500)) 500))))
|
||||
(reset! touch-active? true)))
|
||||
true)
|
||||
on-responder-move (fn [^js e]
|
||||
(when-not @locked?
|
||||
(let [location-x (oops/oget e "nativeEvent.locationX")
|
||||
location-y (oops/oget e "nativeEvent.locationY")
|
||||
page-x (oops/oget e "nativeEvent.pageX")
|
||||
page-y (oops/oget e "nativeEvent.pageY")
|
||||
moved-to-send-button? (touch-inside-area?
|
||||
{:location-x location-x
|
||||
:location-y location-y
|
||||
:ignore-min-y? true
|
||||
:ignore-max-y? false
|
||||
:ignore-min-x? false
|
||||
:ignore-max-x? true}
|
||||
(send-button-area @ready-to-send?))
|
||||
moved-to-delete-button? (touch-inside-area?
|
||||
{:location-x location-x
|
||||
:location-y location-y
|
||||
:ignore-min-y? false
|
||||
:ignore-max-y? true
|
||||
:ignore-min-x? true
|
||||
:ignore-max-x? false}
|
||||
(delete-button-area @ready-to-delete?))
|
||||
moved-to-lock-button? (touch-inside-area?
|
||||
{:location-x location-x
|
||||
:location-y location-y
|
||||
:ignore-min-y? false
|
||||
:ignore-max-y? false
|
||||
:ignore-min-x? false
|
||||
:ignore-max-x? false}
|
||||
(lock-button-area @ready-to-lock?))
|
||||
moved-to-record-button? (and
|
||||
(touch-inside-area?
|
||||
{:location-x location-x
|
||||
:location-y location-y
|
||||
:ignore-min-y? false
|
||||
:ignore-max-y? false
|
||||
:ignore-min-x? false
|
||||
:ignore-max-x? false}
|
||||
record-button-area-big)
|
||||
(not= location-x page-x)
|
||||
(not= location-y page-y))]
|
||||
(cond
|
||||
(and
|
||||
(or
|
||||
(and moved-to-record-button? @ready-to-lock?)
|
||||
(and (not @locked?) moved-to-lock-button? @record-button-at-initial-position?))
|
||||
(not @ready-to-delete?)
|
||||
(not @ready-to-send?)
|
||||
@recording?) (reset! ready-to-lock? moved-to-lock-button?)
|
||||
(and
|
||||
(or
|
||||
(and moved-to-record-button? @ready-to-delete?)
|
||||
(and moved-to-delete-button? @record-button-at-initial-position?))
|
||||
(not @ready-to-lock?)
|
||||
(not @ready-to-send?)
|
||||
@recording?) (reset! ready-to-delete? moved-to-delete-button?)
|
||||
(and
|
||||
(or
|
||||
(and moved-to-record-button? @ready-to-send?)
|
||||
(and moved-to-send-button? @record-button-at-initial-position?))
|
||||
(not @ready-to-lock?)
|
||||
(not @ready-to-delete?)
|
||||
@recording?) (reset! ready-to-send? moved-to-send-button?)))))
|
||||
on-responder-release (fn [^js e]
|
||||
(let [on-record-button? (touch-inside-area?
|
||||
{:location-x (oops/oget e "nativeEvent.locationX")
|
||||
:location-y (oops/oget e "nativeEvent.locationY")
|
||||
:ignore-min-y? false
|
||||
:ignore-max-y? false
|
||||
:ignore-min-x? false
|
||||
:ignore-max-x? false}
|
||||
(if @reviewing-audio? record-button-area record-button-area-big))]
|
||||
(cond
|
||||
(and @reviewing-audio? on-record-button?)
|
||||
(reset! reviewing-audio? false)
|
||||
(and @ready-to-lock? (not @record-button-is-animating?))
|
||||
(do
|
||||
(reset! locked? true)
|
||||
(reset! ready-to-lock? false))
|
||||
(and (not @reviewing-audio?) on-record-button?)
|
||||
(do
|
||||
(when (>= @recording-length-ms 500) (reset! reviewing-audio? true))
|
||||
(reset! locked? false)
|
||||
(reset! recording? false)
|
||||
(reset! ready-to-lock? false)
|
||||
(utils/clear-interval @recording-timer)
|
||||
(reset! recording-length-ms 0))
|
||||
(and (not @locked?) (not @reviewing-audio?) (not @record-button-is-animating?))
|
||||
(do
|
||||
(reset! recording? false)
|
||||
(reset! ready-to-send? false)
|
||||
(reset! ready-to-delete? false)
|
||||
(reset! ready-to-lock? false)
|
||||
(utils/clear-interval @recording-timer)
|
||||
(reset! recording-length-ms 0))))
|
||||
(reset! touch-active? false))]
|
||||
on-start-should-set-responder
|
||||
(fn [^js e]
|
||||
(when-not @locked?
|
||||
(let [pressed-record-button? (touch-inside-area?
|
||||
{:location-x (oops/oget e "nativeEvent.locationX")
|
||||
:location-y (oops/oget e "nativeEvent.locationY")
|
||||
:ignore-min-y? false
|
||||
:ignore-max-y? false
|
||||
:ignore-min-x? false
|
||||
:ignore-max-x? false}
|
||||
record-button-area)]
|
||||
(when-not @reviewing-audio?
|
||||
(reset! recording? pressed-record-button?)
|
||||
(when pressed-record-button?
|
||||
;; TODO: By now we just track recording length, we need to add actual audio
|
||||
;; recording logic
|
||||
;; GitHub issue [#14558]: https://github.com/status-im/status-mobile/issues/14558
|
||||
(reset! recording-timer (utils/set-interval #(reset! recording-length-ms
|
||||
(+ @recording-length-ms 500))
|
||||
500))))
|
||||
(reset! touch-active? true)))
|
||||
true)
|
||||
on-responder-move
|
||||
(fn [^js e]
|
||||
(when-not @locked?
|
||||
(let [location-x (oops/oget e "nativeEvent.locationX")
|
||||
location-y (oops/oget e "nativeEvent.locationY")
|
||||
page-x (oops/oget e "nativeEvent.pageX")
|
||||
page-y (oops/oget e "nativeEvent.pageY")
|
||||
moved-to-send-button? (touch-inside-area?
|
||||
{:location-x location-x
|
||||
:location-y location-y
|
||||
:ignore-min-y? true
|
||||
:ignore-max-y? false
|
||||
:ignore-min-x? false
|
||||
:ignore-max-x? true}
|
||||
(send-button-area @ready-to-send?))
|
||||
moved-to-delete-button? (touch-inside-area?
|
||||
{:location-x location-x
|
||||
:location-y location-y
|
||||
:ignore-min-y? false
|
||||
:ignore-max-y? true
|
||||
:ignore-min-x? true
|
||||
:ignore-max-x? false}
|
||||
(delete-button-area @ready-to-delete?))
|
||||
moved-to-lock-button? (touch-inside-area?
|
||||
{:location-x location-x
|
||||
:location-y location-y
|
||||
:ignore-min-y? false
|
||||
:ignore-max-y? false
|
||||
:ignore-min-x? false
|
||||
:ignore-max-x? false}
|
||||
(lock-button-area @ready-to-lock?))
|
||||
moved-to-record-button? (and
|
||||
(touch-inside-area?
|
||||
{:location-x location-x
|
||||
:location-y location-y
|
||||
:ignore-min-y? false
|
||||
:ignore-max-y? false
|
||||
:ignore-min-x? false
|
||||
:ignore-max-x? false}
|
||||
record-button-area-big)
|
||||
(not= location-x page-x)
|
||||
(not= location-y page-y))]
|
||||
(cond
|
||||
(and
|
||||
(or
|
||||
(and moved-to-record-button? @ready-to-lock?)
|
||||
(and (not @locked?) moved-to-lock-button? @record-button-at-initial-position?))
|
||||
(not @ready-to-delete?)
|
||||
(not @ready-to-send?)
|
||||
@recording?)
|
||||
(reset! ready-to-lock? moved-to-lock-button?)
|
||||
(and
|
||||
(or
|
||||
(and moved-to-record-button? @ready-to-delete?)
|
||||
(and moved-to-delete-button? @record-button-at-initial-position?))
|
||||
(not @ready-to-lock?)
|
||||
(not @ready-to-send?)
|
||||
@recording?)
|
||||
(reset! ready-to-delete? moved-to-delete-button?)
|
||||
(and
|
||||
(or
|
||||
(and moved-to-record-button? @ready-to-send?)
|
||||
(and moved-to-send-button? @record-button-at-initial-position?))
|
||||
(not @ready-to-lock?)
|
||||
(not @ready-to-delete?)
|
||||
@recording?)
|
||||
(reset! ready-to-send? moved-to-send-button?)))))
|
||||
on-responder-release
|
||||
(fn [^js e]
|
||||
(let [on-record-button? (touch-inside-area?
|
||||
{:location-x (oops/oget e "nativeEvent.locationX")
|
||||
:location-y (oops/oget e "nativeEvent.locationY")
|
||||
:ignore-min-y? false
|
||||
:ignore-max-y? false
|
||||
:ignore-min-x? false
|
||||
:ignore-max-x? false}
|
||||
(if @reviewing-audio? record-button-area record-button-area-big))]
|
||||
(cond
|
||||
(and @reviewing-audio? on-record-button?)
|
||||
(reset! reviewing-audio? false)
|
||||
(and @ready-to-lock? (not @record-button-is-animating?))
|
||||
(do
|
||||
(reset! locked? true)
|
||||
(reset! ready-to-lock? false))
|
||||
(and (not @reviewing-audio?) on-record-button?)
|
||||
(do
|
||||
(when (>= @recording-length-ms 500) (reset! reviewing-audio? true))
|
||||
(reset! locked? false)
|
||||
(reset! recording? false)
|
||||
(reset! ready-to-lock? false)
|
||||
(utils/clear-interval @recording-timer)
|
||||
(reset! recording-length-ms 0))
|
||||
(and (not @locked?) (not @reviewing-audio?) (not @record-button-is-animating?))
|
||||
(do
|
||||
(reset! recording? false)
|
||||
(reset! ready-to-send? false)
|
||||
(reset! ready-to-delete? false)
|
||||
(reset! ready-to-lock? false)
|
||||
(utils/clear-interval @recording-timer)
|
||||
(reset! recording-length-ms 0))))
|
||||
(reset! touch-active? false))]
|
||||
(fn []
|
||||
[rn/view {:style style/input-container
|
||||
:pointer-events :box-only
|
||||
:on-start-should-set-responder on-start-should-set-responder
|
||||
:on-responder-move on-responder-move
|
||||
:on-responder-release on-responder-release}
|
||||
[rn/view
|
||||
{:style style/input-container
|
||||
:pointer-events :box-only
|
||||
:on-start-should-set-responder on-start-should-set-responder
|
||||
:on-responder-move on-responder-move
|
||||
:on-responder-release on-responder-release}
|
||||
[delete-button recording? ready-to-delete?]
|
||||
[lock-button recording? ready-to-lock? locked?]
|
||||
[send-button recording? ready-to-send? reviewing-audio?]
|
||||
|
@ -7,30 +7,30 @@
|
||||
([]
|
||||
(render-toggle {}))
|
||||
([opts]
|
||||
(rtl/render (reagent/as-element [selectors/toggle opts]))))
|
||||
(rtl/render (reagent/as-element [selectors/toggle opts]))))
|
||||
|
||||
(defn render-checkbox
|
||||
([]
|
||||
(render-checkbox {}))
|
||||
([opts]
|
||||
(rtl/render (reagent/as-element [selectors/checkbox opts]))))
|
||||
(rtl/render (reagent/as-element [selectors/checkbox opts]))))
|
||||
|
||||
(defn render-checkbox-prefill
|
||||
([]
|
||||
(render-checkbox-prefill {}))
|
||||
([opts]
|
||||
(rtl/render (reagent/as-element [selectors/checkbox-prefill opts]))))
|
||||
(rtl/render (reagent/as-element [selectors/checkbox-prefill opts]))))
|
||||
|
||||
(defn render-radio
|
||||
([]
|
||||
(render-radio {}))
|
||||
([opts]
|
||||
(rtl/render (reagent/as-element [selectors/radio opts]))))
|
||||
(rtl/render (reagent/as-element [selectors/radio opts]))))
|
||||
|
||||
(js/global.test "default render of toggle component"
|
||||
(fn []
|
||||
(render-toggle)
|
||||
(-> (js/expect (rtl/screen.getByTestId "toggle-component"))
|
||||
(-> (js/expect (rtl/screen.getByTestId "toggle-component"))
|
||||
(.toBeTruthy))))
|
||||
|
||||
(js/global.test "toggle component on change is working"
|
||||
@ -44,7 +44,7 @@
|
||||
(js/global.test "default render of radio component"
|
||||
(fn []
|
||||
(render-radio)
|
||||
(-> (js/expect (rtl/screen.getByTestId "radio-component"))
|
||||
(-> (js/expect (rtl/screen.getByTestId "radio-component"))
|
||||
(.toBeTruthy))))
|
||||
|
||||
(js/global.test "radio component on change is working"
|
||||
@ -58,7 +58,7 @@
|
||||
(js/global.test "default render of checkbox component"
|
||||
(fn []
|
||||
(render-checkbox)
|
||||
(-> (js/expect (rtl/screen.getByTestId "checkbox-component"))
|
||||
(-> (js/expect (rtl/screen.getByTestId "checkbox-component"))
|
||||
(.toBeTruthy))))
|
||||
|
||||
(js/global.test "checkbox component on change is working"
|
||||
@ -72,7 +72,7 @@
|
||||
(js/global.test "default render of checkbox-prefill component"
|
||||
(fn []
|
||||
(render-checkbox-prefill)
|
||||
(-> (js/expect (rtl/screen.getByTestId "checkbox-prefill-component"))
|
||||
(-> (js/expect (rtl/screen.getByTestId "checkbox-prefill-component"))
|
||||
(.toBeTruthy))))
|
||||
|
||||
(js/global.test "checkbox-prefill component on change is working"
|
||||
|
@ -1,31 +1,32 @@
|
||||
(ns quo2.components.selectors.disclaimer
|
||||
(:require [react-native.core :as rn]
|
||||
(:require [quo2.components.markdown.text :as text]
|
||||
[quo2.components.selectors.selectors :as selectors]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.components.selectors.selectors :as selectors]))
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(defn disclaimer [{:keys [on-change accessibility-label container-style]} label]
|
||||
(defn disclaimer
|
||||
[{:keys [on-change accessibility-label container-style]} label]
|
||||
[rn/view
|
||||
{:style
|
||||
(merge
|
||||
container-style
|
||||
{:flex 1
|
||||
:flex-direction :row
|
||||
{:flex 1
|
||||
:flex-direction :row
|
||||
:background-color (colors/theme-colors
|
||||
colors/neutral-5
|
||||
colors/neutral-80-opa-40)
|
||||
:padding 11
|
||||
:align-self :stretch
|
||||
:border-radius 12
|
||||
:border-width 1
|
||||
:border-color (colors/theme-colors
|
||||
colors/neutral-20
|
||||
colors/neutral-70)})}
|
||||
:padding 11
|
||||
:align-self :stretch
|
||||
:border-radius 12
|
||||
:border-width 1
|
||||
:border-color (colors/theme-colors
|
||||
colors/neutral-20
|
||||
colors/neutral-70)})}
|
||||
[selectors/checkbox
|
||||
{:on-change on-change}]
|
||||
[text/text
|
||||
{:accessibility-label accessibility-label
|
||||
:size :paragraph-2
|
||||
:style {:margin-left 8}}
|
||||
:style {:margin-left 8}}
|
||||
label]])
|
||||
|
||||
|
@ -1,14 +1,19 @@
|
||||
(ns quo2.components.selectors.selectors
|
||||
(:require [react-native.core :as rn]
|
||||
(:require [quo2.components.icon :as icons]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[reagent.core :as reagent]
|
||||
[quo2.components.icon :as icons]))
|
||||
[react-native.core :as rn]
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
(defn- get-color [checked? disabled? blurred-background?]
|
||||
(defn- get-color
|
||||
[checked? disabled? blurred-background?]
|
||||
(cond
|
||||
checked?
|
||||
(colors/custom-color-by-theme
|
||||
:primary 50 60 (when disabled? 30) (when disabled? 30))
|
||||
:primary
|
||||
50
|
||||
60
|
||||
(when disabled? 30)
|
||||
(when disabled? 30))
|
||||
blurred-background?
|
||||
(colors/theme-colors
|
||||
(colors/alpha colors/neutral-80 (if disabled? 0.05 0.1))
|
||||
@ -18,138 +23,152 @@
|
||||
(colors/alpha colors/neutral-20 (if disabled? 0.4 1))
|
||||
(colors/alpha colors/neutral-70 (if disabled? 0.3 1)))))
|
||||
|
||||
(defn- handle-press [disabled? on-change checked?]
|
||||
(defn- handle-press
|
||||
[disabled? on-change checked?]
|
||||
(when (not disabled?)
|
||||
(fn []
|
||||
(swap! checked? not)
|
||||
(when on-change (on-change @checked?)))))
|
||||
|
||||
(defn checkbox-prefill [{:keys [default-checked?]}]
|
||||
(defn checkbox-prefill
|
||||
[{:keys [default-checked?]}]
|
||||
(let [checked? (reagent/atom (or default-checked? false))]
|
||||
(fn [{:keys [on-change disabled? blurred-background? container-style]}]
|
||||
[rn/touchable-without-feedback
|
||||
{:on-press (handle-press disabled? on-change checked?)}
|
||||
[rn/view
|
||||
{:style (merge
|
||||
container-style
|
||||
{:height 21
|
||||
:width 21
|
||||
:border-radius 6
|
||||
:background-color (if blurred-background?
|
||||
(colors/theme-colors
|
||||
(colors/alpha colors/neutral-80 (if disabled? 0.05 0.1))
|
||||
(colors/alpha colors/white (if disabled? 0.05 0.1)))
|
||||
(colors/theme-colors
|
||||
(colors/alpha colors/neutral-20 (if disabled? 0.3 1))
|
||||
(colors/alpha colors/neutral-70 (if disabled? 0.3 1))))})
|
||||
{:style (merge
|
||||
container-style
|
||||
{:height 21
|
||||
:width 21
|
||||
:border-radius 6
|
||||
:background-color (if blurred-background?
|
||||
(colors/theme-colors
|
||||
(colors/alpha colors/neutral-80
|
||||
(if disabled? 0.05 0.1))
|
||||
(colors/alpha colors/white (if disabled? 0.05 0.1)))
|
||||
(colors/theme-colors
|
||||
(colors/alpha colors/neutral-20
|
||||
(if disabled? 0.3 1))
|
||||
(colors/alpha colors/neutral-70
|
||||
(if disabled? 0.3 1))))})
|
||||
:accessibility-label (str "checkbox-" (if @checked? "on" "off"))
|
||||
:accessibility-role :checkbox
|
||||
:testID "checkbox-prefill-component"}
|
||||
:testID "checkbox-prefill-component"}
|
||||
(when @checked?
|
||||
[rn/view {:style
|
||||
{:height 20
|
||||
:width 20}}
|
||||
[rn/view
|
||||
{:style
|
||||
{:height 20
|
||||
:width 20}}
|
||||
[icons/icon :i/check-small
|
||||
{:size 20
|
||||
{:size 20
|
||||
:color (colors/theme-colors
|
||||
(colors/alpha colors/neutral-100 (if disabled? 0.3 1))
|
||||
(colors/alpha colors/white (if disabled? 0.3 1)))}]])]])))
|
||||
|
||||
(defn checkbox [{:keys [default-checked?]}]
|
||||
(defn checkbox
|
||||
[{:keys [default-checked?]}]
|
||||
(let [checked? (reagent/atom (or default-checked? false))]
|
||||
(fn [{:keys [on-change disabled? blurred-background? container-style]}]
|
||||
[rn/touchable-without-feedback
|
||||
{:on-press (handle-press disabled? on-change checked?)}
|
||||
[rn/view
|
||||
{:style (merge
|
||||
container-style
|
||||
{:height 20
|
||||
:width 20})}
|
||||
{:style (merge
|
||||
container-style
|
||||
{:height 20
|
||||
:width 20})}
|
||||
[rn/view
|
||||
{:style {:flex 1
|
||||
:border-radius 6
|
||||
:border-width (if @checked? 0 1)
|
||||
:background-color (cond
|
||||
@checked?
|
||||
(get-color @checked? disabled? blurred-background?)
|
||||
blurred-background?
|
||||
(colors/theme-colors
|
||||
colors/white-opa-5
|
||||
colors/white-opa-10)
|
||||
:else
|
||||
(colors/theme-colors
|
||||
colors/white
|
||||
colors/neutral-80-opa-40))
|
||||
:border-color (if @checked? :none
|
||||
(get-color @checked? disabled? blurred-background?))}
|
||||
{:style {:flex 1
|
||||
:border-radius 6
|
||||
:border-width (if @checked? 0 1)
|
||||
:background-color (cond
|
||||
@checked?
|
||||
(get-color @checked? disabled? blurred-background?)
|
||||
blurred-background?
|
||||
(colors/theme-colors
|
||||
colors/white-opa-5
|
||||
colors/white-opa-10)
|
||||
:else
|
||||
(colors/theme-colors
|
||||
colors/white
|
||||
colors/neutral-80-opa-40))
|
||||
:border-color (if @checked?
|
||||
:none
|
||||
(get-color @checked? disabled? blurred-background?))}
|
||||
:accessibility-label (str "checkbox-" (if @checked? "on" "off"))
|
||||
:accessibility-role :checkbox
|
||||
:testID "checkbox-component"}
|
||||
:testID "checkbox-component"}
|
||||
(when @checked?
|
||||
[rn/view {:style
|
||||
{:height 20
|
||||
:width 20}}
|
||||
[rn/view
|
||||
{:style
|
||||
{:height 20
|
||||
:width 20}}
|
||||
[icons/icon :i/check-small
|
||||
{:size 20
|
||||
{:size 20
|
||||
:color colors/white}]])]]])))
|
||||
|
||||
(defn radio [{:keys [default-checked?]}]
|
||||
(defn radio
|
||||
[{:keys [default-checked?]}]
|
||||
(let [checked? (reagent/atom (or default-checked? false))]
|
||||
(fn [{:keys [on-change disabled? blurred-background? container-style]}]
|
||||
[rn/touchable-without-feedback
|
||||
{:on-press (handle-press disabled? on-change checked?)}
|
||||
[rn/view
|
||||
{:style (merge
|
||||
container-style
|
||||
{:height 20
|
||||
:width 20
|
||||
:border-radius 20
|
||||
:border-width 1
|
||||
:border-color (get-color @checked? disabled? blurred-background?)
|
||||
:background-color (when-not blurred-background?
|
||||
(colors/theme-colors colors/white
|
||||
(colors/alpha colors/neutral-80 0.4)))})
|
||||
{:style (merge
|
||||
container-style
|
||||
{:height 20
|
||||
:width 20
|
||||
:border-radius 20
|
||||
:border-width 1
|
||||
:border-color (get-color @checked? disabled? blurred-background?)
|
||||
:background-color (when-not blurred-background?
|
||||
(colors/theme-colors colors/white
|
||||
(colors/alpha colors/neutral-80
|
||||
0.4)))})
|
||||
:accessibility-label (str "radio-" (if @checked? "on" "off"))
|
||||
:accessibility-role :checkbox
|
||||
:testID "radio-component"}
|
||||
:testID "radio-component"}
|
||||
|
||||
[rn/view {:style
|
||||
{:margin-left :auto
|
||||
:height 14
|
||||
:width 14
|
||||
:background-color (when @checked? (get-color @checked? disabled? blurred-background?))
|
||||
:border-radius 20
|
||||
:margin-right :auto
|
||||
:margin-top :auto
|
||||
:margin-bottom :auto}}]]])))
|
||||
[rn/view
|
||||
{:style
|
||||
{:margin-left :auto
|
||||
:height 14
|
||||
:width 14
|
||||
:background-color (when @checked? (get-color @checked? disabled? blurred-background?))
|
||||
:border-radius 20
|
||||
:margin-right :auto
|
||||
:margin-top :auto
|
||||
:margin-bottom :auto}}]]])))
|
||||
|
||||
(defn toggle [{:keys [default-checked?]}]
|
||||
(defn toggle
|
||||
[{:keys [default-checked?]}]
|
||||
(let [checked? (reagent/atom (or default-checked? false))]
|
||||
(fn [{:keys [on-change disabled? blurred-background? container-style]}]
|
||||
[rn/touchable-without-feedback
|
||||
{:on-press (handle-press disabled? on-change checked?)}
|
||||
[rn/view
|
||||
{:style (merge
|
||||
container-style
|
||||
{:height 20
|
||||
:width 30
|
||||
:border-radius 20
|
||||
:background-color (get-color @checked? disabled? blurred-background?)})
|
||||
{:style (merge
|
||||
container-style
|
||||
{:height 20
|
||||
:width 30
|
||||
:border-radius 20
|
||||
:background-color (get-color @checked? disabled? blurred-background?)})
|
||||
:accessibility-label (str "toggle-" (if @checked? "on" "off"))
|
||||
:accessibility-role :checkbox
|
||||
:testID "toggle-component"}
|
||||
[rn/view {:style
|
||||
{:margin-left (if @checked? 12 2)
|
||||
:height 16
|
||||
:width 16
|
||||
:background-color (if blurred-background?
|
||||
(colors/theme-colors
|
||||
(colors/alpha colors/white (if disabled? 0.4 1))
|
||||
(colors/alpha colors/white (if disabled? 0.3 1)))
|
||||
(colors/theme-colors
|
||||
(colors/alpha colors/white 1)
|
||||
(colors/alpha colors/white (if disabled? 0.4 1))))
|
||||
:border-radius 20
|
||||
:margin-right :auto
|
||||
:margin-top :auto
|
||||
:margin-bottom :auto}}]]])))
|
||||
:testID "toggle-component"}
|
||||
[rn/view
|
||||
{:style
|
||||
{:margin-left (if @checked? 12 2)
|
||||
:height 16
|
||||
:width 16
|
||||
:background-color (if blurred-background?
|
||||
(colors/theme-colors
|
||||
(colors/alpha colors/white (if disabled? 0.4 1))
|
||||
(colors/alpha colors/white (if disabled? 0.3 1)))
|
||||
(colors/theme-colors
|
||||
(colors/alpha colors/white 1)
|
||||
(colors/alpha colors/white (if disabled? 0.4 1))))
|
||||
:border-radius 20
|
||||
:margin-right :auto
|
||||
:margin-top :auto
|
||||
:margin-bottom :auto}}]]])))
|
||||
|
@ -1,8 +1,9 @@
|
||||
(ns quo2.components.separator
|
||||
(:require [react-native.core :as rn]
|
||||
[quo2.foundations.colors :as quo2.colors]))
|
||||
(:require [quo2.foundations.colors :as quo2.colors]
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(defn separator [{:keys [style]}]
|
||||
(defn separator
|
||||
[{:keys [style]}]
|
||||
[rn/view
|
||||
{:style
|
||||
(merge
|
||||
|
@ -1,10 +1,10 @@
|
||||
(ns quo2.components.settings.privacy-option
|
||||
(:require [react-native.core :as rn]
|
||||
[quo2.components.icon :as icons]
|
||||
(:require [quo2.components.icon :as icons]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.components.selectors.selectors :as selectors]
|
||||
[quo2.components.settings.style :as style]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.foundations.colors :as colors]))
|
||||
[quo2.foundations.colors :as colors]
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(defn- bullet
|
||||
[]
|
||||
@ -27,8 +27,9 @@
|
||||
[rn/view {:style style/card-footer-label-container}
|
||||
[text/text {:size :paragraph-2} label]]
|
||||
[rn/view {:style style/card-footer-toggle-container}
|
||||
[selectors/toggle {:disabled? (not active?)
|
||||
:on-change on-toggle}]]]])
|
||||
[selectors/toggle
|
||||
{:disabled? (not active?)
|
||||
:on-change on-toggle}]]]])
|
||||
|
||||
(defn- selection-indicator
|
||||
[active?]
|
||||
@ -38,8 +39,9 @@
|
||||
(defn- card-header
|
||||
[{:keys [icon label active?]}]
|
||||
[rn/view {:style style/card-header-container}
|
||||
[icons/icon icon {:size 20
|
||||
:color (colors/theme-colors colors/neutral-50 colors/neutral-40)}]
|
||||
[icons/icon icon
|
||||
{:size 20
|
||||
:color (colors/theme-colors colors/neutral-50 colors/neutral-40)}]
|
||||
[rn/view {:style style/card-header-label-container}
|
||||
[text/text {:weight :semi-bold} label]]
|
||||
[selection-indicator active?]])
|
||||
@ -53,11 +55,13 @@
|
||||
:accessibility-label :privacy-option-card
|
||||
:testID :privacy-option-card}
|
||||
[rn/view (style/privacy-option-card active?)
|
||||
[card-header {:active? active?
|
||||
:icon icon
|
||||
:label header}]
|
||||
[card-header
|
||||
{:active? active?
|
||||
:icon icon
|
||||
:label header}]
|
||||
[unordered-list (when-not footer {:margin-bottom 8}) list-items]
|
||||
(when footer
|
||||
[card-footer {:active? active?
|
||||
:label footer
|
||||
:on-toggle on-toggle}])]])
|
||||
[card-footer
|
||||
{:active? active?
|
||||
:label footer
|
||||
:on-toggle on-toggle}])]])
|
||||
|
@ -1,46 +1,47 @@
|
||||
(ns quo2.components.tabs.account-selector
|
||||
(:require
|
||||
[quo2.theme :as theme]
|
||||
[react-native.core :as rn]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[quo2.components.markdown.text :as quo2]))
|
||||
(:require [quo2.components.markdown.text :as quo2]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[quo2.theme :as theme]
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(def themes
|
||||
{:light {:default {:bg colors/neutral-10
|
||||
:account-text colors/neutral-100
|
||||
:label-text colors/neutral-50}
|
||||
:transparent {:bg colors/neutral-80-opa-5
|
||||
:account-text colors/neutral-100
|
||||
:label-text colors/neutral-80-opa-40}}
|
||||
{:light {:default {:bg colors/neutral-10
|
||||
:account-text colors/neutral-100
|
||||
:label-text colors/neutral-50}
|
||||
:transparent {:bg colors/neutral-80-opa-5
|
||||
:account-text colors/neutral-100
|
||||
:label-text colors/neutral-80-opa-40}}
|
||||
|
||||
:dark {:default {:bg colors/neutral-80-opa-80
|
||||
:account-text colors/white
|
||||
:label-text colors/neutral-40}
|
||||
:transparent {:bg colors/white-opa-5
|
||||
:account-text colors/white
|
||||
:label-text colors/neutral-40}}})
|
||||
:dark {:default {:bg colors/neutral-80-opa-80
|
||||
:account-text colors/white
|
||||
:label-text colors/neutral-40}
|
||||
:transparent {:bg colors/white-opa-5
|
||||
:account-text colors/white
|
||||
:label-text colors/neutral-40}}})
|
||||
|
||||
(defn account-container-row [background-color]
|
||||
{:padding-vertical 4
|
||||
:flex-direction :row
|
||||
:align-items :center
|
||||
:background-color background-color
|
||||
:border-radius 12})
|
||||
(defn account-container-row
|
||||
[background-color]
|
||||
{:padding-vertical 4
|
||||
:flex-direction :row
|
||||
:align-items :center
|
||||
:background-color background-color
|
||||
:border-radius 12})
|
||||
|
||||
(def account-emoji
|
||||
{:height 16
|
||||
:width 16})
|
||||
{:height 16
|
||||
:width 16})
|
||||
|
||||
(def account-emoji-container
|
||||
{:background-color (colors/custom-color :purple 50)
|
||||
:padding 8
|
||||
:justify-content :center
|
||||
:align-items :center
|
||||
:border-radius 10
|
||||
:margin-left 4
|
||||
:margin-right 8})
|
||||
{:background-color (colors/custom-color :purple 50)
|
||||
:padding 8
|
||||
:justify-content :center
|
||||
:align-items :center
|
||||
:border-radius 10
|
||||
:margin-left 4
|
||||
:margin-right 8})
|
||||
|
||||
(defn get-color-by-type [type key]
|
||||
(defn get-color-by-type
|
||||
[type key]
|
||||
(get-in themes [(theme/get-theme) type key]))
|
||||
|
||||
(defn account-selector
|
||||
@ -57,16 +58,19 @@
|
||||
account-text-color (get-color-by-type (if transparent? :transparent :default) :account-text)
|
||||
label-text-color (get-color-by-type (if transparent? :transparent :default) :label-text)]
|
||||
[rn/view {:style style}
|
||||
(when show-label? [quo2/text {:weight :medium
|
||||
:size :paragraph-2
|
||||
:style {:color label-text-color
|
||||
:margin-bottom 8}}
|
||||
label-text])
|
||||
(when show-label?
|
||||
[quo2/text
|
||||
{:weight :medium
|
||||
:size :paragraph-2
|
||||
:style {:color label-text-color
|
||||
:margin-bottom 8}}
|
||||
label-text])
|
||||
[rn/view {:style (account-container-row background-color)}
|
||||
[rn/view {:style account-emoji-container}
|
||||
[quo2/text account-emoji]]
|
||||
[quo2/text {:weight :medium
|
||||
:size :paragraph-1
|
||||
:style {:color account-text-color}}
|
||||
[quo2/text
|
||||
{:weight :medium
|
||||
:size :paragraph-1
|
||||
:style {:color account-text-color}}
|
||||
account-text]]]))
|
||||
|
||||
|
@ -1,29 +1,33 @@
|
||||
(ns quo2.components.tabs.segmented-tab
|
||||
(:require [reagent.core :as reagent]
|
||||
[react-native.core :as rn]
|
||||
[quo2.components.tabs.tab :as tab]
|
||||
(:require [quo2.components.tabs.tab :as tab]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[quo2.theme :as theme]))
|
||||
[quo2.theme :as theme]
|
||||
[react-native.core :as rn]
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
(def themes {:light {:background-color colors/neutral-20}
|
||||
:dark {:background-color colors/neutral-80}})
|
||||
(def themes
|
||||
{:light {:background-color colors/neutral-20}
|
||||
:dark {:background-color colors/neutral-80}})
|
||||
|
||||
(defn segmented-control [{:keys [default-active on-change]}]
|
||||
(defn segmented-control
|
||||
[{:keys [default-active on-change]}]
|
||||
(let [active-tab-id (reagent/atom default-active)]
|
||||
(fn [{:keys [data size]}]
|
||||
(let [active-id @active-tab-id]
|
||||
[rn/view {:flex-direction :row
|
||||
:background-color (get-in themes [(theme/get-theme) :background-color])
|
||||
:border-radius (case size
|
||||
32 10
|
||||
28 8
|
||||
24 8
|
||||
20 6)
|
||||
:padding 2}
|
||||
[rn/view
|
||||
{:flex-direction :row
|
||||
:background-color (get-in themes [(theme/get-theme) :background-color])
|
||||
:border-radius (case size
|
||||
32 10
|
||||
28 8
|
||||
24 8
|
||||
20 6)
|
||||
:padding 2}
|
||||
(for [[indx {:keys [label id]}] (map-indexed vector data)]
|
||||
^{:key id}
|
||||
[rn/view {:margin-left (if (= 0 indx) 0 2)
|
||||
:flex 1}
|
||||
[rn/view
|
||||
{:margin-left (if (= 0 indx) 0 2)
|
||||
:flex 1}
|
||||
[tab/tab
|
||||
{:id id
|
||||
:segmented true
|
||||
|
@ -1,49 +1,52 @@
|
||||
(ns quo2.components.tabs.tab
|
||||
(:require [quo2.foundations.colors :as colors]
|
||||
[react-native.core :as rn]
|
||||
[quo2.theme :as theme]
|
||||
(:require [quo2.components.icon :as icons]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.components.icon :as icons]))
|
||||
[quo2.foundations.colors :as colors]
|
||||
[quo2.theme :as theme]
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(def themes {:light {:default {:background-color colors/neutral-20
|
||||
:icon-color colors/neutral-50
|
||||
:label {:style {:color colors/neutral-100}}}
|
||||
:active {:background-color colors/neutral-50
|
||||
:icon-color colors/white
|
||||
:label {:style {:color colors/white}}}
|
||||
:disabled {:background-color colors/neutral-20
|
||||
:icon-color colors/neutral-50
|
||||
:label {:style {:color colors/neutral-100}}}}
|
||||
:dark {:default {:background-color colors/neutral-80
|
||||
:icon-color colors/neutral-40
|
||||
:label {:style {:color colors/white}}}
|
||||
:active {:background-color colors/neutral-60
|
||||
:icon-color colors/white
|
||||
:label {:style {:color colors/white}}}
|
||||
:disabled {:background-color colors/neutral-80
|
||||
:icon-color colors/neutral-40
|
||||
:label {:style {:color colors/white}}}}})
|
||||
(def themes
|
||||
{:light {:default {:background-color colors/neutral-20
|
||||
:icon-color colors/neutral-50
|
||||
:label {:style {:color colors/neutral-100}}}
|
||||
:active {:background-color colors/neutral-50
|
||||
:icon-color colors/white
|
||||
:label {:style {:color colors/white}}}
|
||||
:disabled {:background-color colors/neutral-20
|
||||
:icon-color colors/neutral-50
|
||||
:label {:style {:color colors/neutral-100}}}}
|
||||
:dark {:default {:background-color colors/neutral-80
|
||||
:icon-color colors/neutral-40
|
||||
:label {:style {:color colors/white}}}
|
||||
:active {:background-color colors/neutral-60
|
||||
:icon-color colors/white
|
||||
:label {:style {:color colors/white}}}
|
||||
:disabled {:background-color colors/neutral-80
|
||||
:icon-color colors/neutral-40
|
||||
:label {:style {:color colors/white}}}}})
|
||||
|
||||
(def themes-for-blur-background {:light {:default {:background-color colors/neutral-80-opa-5
|
||||
:icon-color colors/neutral-80-opa-40
|
||||
:label {:style {:color colors/neutral-100}}}
|
||||
:active {:background-color colors/neutral-80-opa-60
|
||||
:icon-color colors/white
|
||||
:label {:style {:color colors/white}}}
|
||||
:disabled {:background-color colors/neutral-80-opa-5
|
||||
:icon-color colors/neutral-80-opa-40
|
||||
:label {:style {:color colors/neutral-100}}}}
|
||||
:dark {:default {:background-color colors/white-opa-5
|
||||
:icon-color colors/white
|
||||
:label {:style {:color colors/white}}}
|
||||
:active {:background-color colors/white-opa-20
|
||||
:icon-color colors/white
|
||||
:label {:style {:color colors/white}}}
|
||||
:disabled {:background-color colors/white-opa-5
|
||||
:icon-color colors/neutral-40
|
||||
:label {:style {:color colors/white}}}}})
|
||||
(def themes-for-blur-background
|
||||
{:light {:default {:background-color colors/neutral-80-opa-5
|
||||
:icon-color colors/neutral-80-opa-40
|
||||
:label {:style {:color colors/neutral-100}}}
|
||||
:active {:background-color colors/neutral-80-opa-60
|
||||
:icon-color colors/white
|
||||
:label {:style {:color colors/white}}}
|
||||
:disabled {:background-color colors/neutral-80-opa-5
|
||||
:icon-color colors/neutral-80-opa-40
|
||||
:label {:style {:color colors/neutral-100}}}}
|
||||
:dark {:default {:background-color colors/white-opa-5
|
||||
:icon-color colors/white
|
||||
:label {:style {:color colors/white}}}
|
||||
:active {:background-color colors/white-opa-20
|
||||
:icon-color colors/white
|
||||
:label {:style {:color colors/white}}}
|
||||
:disabled {:background-color colors/white-opa-5
|
||||
:icon-color colors/neutral-40
|
||||
:label {:style {:color colors/white}}}}})
|
||||
|
||||
(defn style-container [size disabled background-color]
|
||||
(defn style-container
|
||||
[size disabled background-color]
|
||||
(merge {:height size
|
||||
:align-items :center
|
||||
:justify-content :center
|
||||
@ -54,7 +57,11 @@
|
||||
24 8
|
||||
20 6)
|
||||
:background-color background-color
|
||||
:padding-horizontal (case size 32 12 28 12 24 8 20 8)}
|
||||
:padding-horizontal (case size
|
||||
32 12
|
||||
28 12
|
||||
24 8
|
||||
20 8)}
|
||||
(when disabled
|
||||
{:opacity 0.3})))
|
||||
|
||||
@ -70,14 +77,18 @@
|
||||
(fn [{:keys [id on-press disabled size before active accessibility-label blur? override-theme]
|
||||
:or {size 32}}
|
||||
children]
|
||||
(let [state (cond disabled :disabled active :active :else :default)
|
||||
(let [state (cond disabled :disabled
|
||||
active :active
|
||||
:else :default)
|
||||
{:keys [icon-color background-color label]}
|
||||
(get-in (if blur? themes-for-blur-background themes) [(or override-theme (theme/get-theme)) state])]
|
||||
[rn/touchable-without-feedback (merge {:disabled disabled
|
||||
:accessibility-label accessibility-label}
|
||||
(when on-press
|
||||
{:on-press (fn []
|
||||
(on-press id))}))
|
||||
(get-in (if blur? themes-for-blur-background themes)
|
||||
[(or override-theme (theme/get-theme)) state])]
|
||||
[rn/touchable-without-feedback
|
||||
(merge {:disabled disabled
|
||||
:accessibility-label accessibility-label}
|
||||
(when on-press
|
||||
{:on-press (fn []
|
||||
(on-press id))}))
|
||||
[rn/view {:style (style-container size disabled background-color)}
|
||||
(when before
|
||||
[rn/view
|
||||
@ -85,10 +96,14 @@
|
||||
[rn/view
|
||||
(cond
|
||||
(string? children)
|
||||
[text/text (merge {:size (case size 24 :paragraph-2 20 :label nil)
|
||||
:weight :medium
|
||||
:number-of-lines 1}
|
||||
label)
|
||||
[text/text
|
||||
(merge {:size (case size
|
||||
24 :paragraph-2
|
||||
20 :label
|
||||
nil)
|
||||
:weight :medium
|
||||
:number-of-lines 1}
|
||||
label)
|
||||
children]
|
||||
(vector? children)
|
||||
children)]]])))
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user