Add text input and tooltip components
Add tooltip component Add text input component rename Signed-off-by: Gheorghe Pinzaru <feross95@gmail.com>
@ -1,6 +1,7 @@
|
|||||||
{:lint-as {status-im.utils.views/defview clojure.core/defn
|
{:lint-as {status-im.utils.views/defview clojure.core/defn
|
||||||
status-im.utils.views/letsubs clojure.core/let
|
status-im.utils.views/letsubs clojure.core/let
|
||||||
status-im.utils.fx/defn clj-kondo.lint-as/def-catch-all
|
status-im.utils.fx/defn clj-kondo.lint-as/def-catch-all
|
||||||
|
quo.previews.preview/list-comp clojure.core/for
|
||||||
status-im.utils.styles/def clojure.core/def
|
status-im.utils.styles/def clojure.core/def
|
||||||
status-im.utils.styles/defn clojure.core/defn}
|
status-im.utils.styles/defn clojure.core/defn}
|
||||||
:linters {:invalid-arity {:skip-args [status-im.utils.fx/defn]}
|
:linters {:invalid-arity {:skip-args [status-im.utils.fx/defn]}
|
||||||
|
BIN
android/app/src/main/res/drawable-mdpi/hide.png
Normal file
After Width: | Height: | Size: 352 B |
BIN
android/app/src/main/res/drawable-mdpi/show.png
Normal file
After Width: | Height: | Size: 326 B |
BIN
android/app/src/main/res/drawable-mdpi/tooltip_tip.png
Normal file
After Width: | Height: | Size: 184 B |
BIN
android/app/src/main/res/drawable-xhdpi/hide.png
Normal file
After Width: | Height: | Size: 616 B |
BIN
android/app/src/main/res/drawable-xhdpi/show.png
Normal file
After Width: | Height: | Size: 586 B |
BIN
android/app/src/main/res/drawable-xhdpi/tooltip_tip.png
Normal file
After Width: | Height: | Size: 245 B |
BIN
android/app/src/main/res/drawable-xxhdpi/hide.png
Normal file
After Width: | Height: | Size: 913 B |
BIN
android/app/src/main/res/drawable-xxhdpi/show.png
Normal file
After Width: | Height: | Size: 840 B |
BIN
android/app/src/main/res/drawable-xxhdpi/tooltip_tip.png
Normal file
After Width: | Height: | Size: 364 B |
@ -14,6 +14,7 @@
|
|||||||
25DC9C9DC25846BD8D084888 /* libc++.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 8B9A886A2CB448B1ABA0EB62 /* libc++.tbd */; };
|
25DC9C9DC25846BD8D084888 /* libc++.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 8B9A886A2CB448B1ABA0EB62 /* libc++.tbd */; };
|
||||||
3870E1E692E24133A80B07DE /* Inter-SemiBold.otf in Resources */ = {isa = PBXBuildFile; fileRef = 693A62DB37BC4CD5A30E5C96 /* Inter-SemiBold.otf */; };
|
3870E1E692E24133A80B07DE /* Inter-SemiBold.otf in Resources */ = {isa = PBXBuildFile; fileRef = 693A62DB37BC4CD5A30E5C96 /* Inter-SemiBold.otf */; };
|
||||||
393D26E3080B443A998F4A2F /* Inter-Italic.otf in Resources */ = {isa = PBXBuildFile; fileRef = B07176ACDAA1422E8F0A3D6B /* Inter-Italic.otf */; };
|
393D26E3080B443A998F4A2F /* Inter-Italic.otf in Resources */ = {isa = PBXBuildFile; fileRef = B07176ACDAA1422E8F0A3D6B /* Inter-Italic.otf */; };
|
||||||
|
3ABC7AF8245FF85900612C45 /* InterStatus-Regular.otf in Resources */ = {isa = PBXBuildFile; fileRef = 9C76AF5A418D4D65A4CAD1D9 /* InterStatus-Regular.otf */; };
|
||||||
57C854A7993C47A3B1AECD32 /* Inter-MediumItalic.otf in Resources */ = {isa = PBXBuildFile; fileRef = C6B1215047604CD59A4C74D6 /* Inter-MediumItalic.otf */; };
|
57C854A7993C47A3B1AECD32 /* Inter-MediumItalic.otf in Resources */ = {isa = PBXBuildFile; fileRef = C6B1215047604CD59A4C74D6 /* Inter-MediumItalic.otf */; };
|
||||||
70ADBB5ECF934DCF8A0E4919 /* Inter-Regular.otf in Resources */ = {isa = PBXBuildFile; fileRef = 1426DF592BA248FC81D955CB /* Inter-Regular.otf */; };
|
70ADBB5ECF934DCF8A0E4919 /* Inter-Regular.otf in Resources */ = {isa = PBXBuildFile; fileRef = 1426DF592BA248FC81D955CB /* Inter-Regular.otf */; };
|
||||||
74B758FC20D7C00B003343C3 /* launch-image-universal.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 74B758FB20D7C00B003343C3 /* launch-image-universal.storyboard */; };
|
74B758FC20D7C00B003343C3 /* launch-image-universal.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 74B758FB20D7C00B003343C3 /* launch-image-universal.storyboard */; };
|
||||||
@ -90,7 +91,6 @@
|
|||||||
13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = StatusIm/main.m; sourceTree = "<group>"; };
|
13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = StatusIm/main.m; sourceTree = "<group>"; };
|
||||||
1426DF592BA248FC81D955CB /* Inter-Regular.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Inter-Regular.otf"; path = "../resources/fonts/Inter-Regular.otf"; sourceTree = "<group>"; };
|
1426DF592BA248FC81D955CB /* Inter-Regular.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Inter-Regular.otf"; path = "../resources/fonts/Inter-Regular.otf"; sourceTree = "<group>"; };
|
||||||
38A44830EC5708E89387F641 /* Pods-StatusIm.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-StatusIm.release.xcconfig"; path = "Pods/Target Support Files/Pods-StatusIm/Pods-StatusIm.release.xcconfig"; sourceTree = "<group>"; };
|
38A44830EC5708E89387F641 /* Pods-StatusIm.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-StatusIm.release.xcconfig"; path = "Pods/Target Support Files/Pods-StatusIm/Pods-StatusIm.release.xcconfig"; sourceTree = "<group>"; };
|
||||||
3A0B103024581B74004B0F23 /* InterStatus-Regular.otf */ = {isa = PBXFileReference; lastKnownFileType = file; name = "InterStatus-Regular.otf"; path = "../resources/fonts/InterStatus-Regular.otf"; sourceTree = "<group>"; };
|
|
||||||
439B6B4B407A4E2AACAFE5BE /* RCTStatus.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RCTStatus.xcodeproj; path = "../modules/react-native-status/ios/RCTStatus/RCTStatus.xcodeproj"; sourceTree = "<group>"; };
|
439B6B4B407A4E2AACAFE5BE /* RCTStatus.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RCTStatus.xcodeproj; path = "../modules/react-native-status/ios/RCTStatus/RCTStatus.xcodeproj"; sourceTree = "<group>"; };
|
||||||
4C16DE0B1F89508700AA10DB /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
|
4C16DE0B1F89508700AA10DB /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
|
||||||
4E586E1B0E544F64AA9F5BD1 /* libz.tbd */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; };
|
4E586E1B0E544F64AA9F5BD1 /* libz.tbd */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; };
|
||||||
@ -98,6 +98,7 @@
|
|||||||
74B758FB20D7C00B003343C3 /* launch-image-universal.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = "launch-image-universal.storyboard"; sourceTree = "<group>"; };
|
74B758FB20D7C00B003343C3 /* launch-image-universal.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = "launch-image-universal.storyboard"; sourceTree = "<group>"; };
|
||||||
8B9A886A2CB448B1ABA0EB62 /* libc++.tbd */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = "libc++.tbd"; path = "usr/lib/libc++.tbd"; sourceTree = SDKROOT; };
|
8B9A886A2CB448B1ABA0EB62 /* libc++.tbd */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = "libc++.tbd"; path = "usr/lib/libc++.tbd"; sourceTree = SDKROOT; };
|
||||||
922C4CA61F4D5F8B0033C753 /* StatusIm.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = StatusIm.entitlements; path = StatusIm/StatusIm.entitlements; sourceTree = "<group>"; };
|
922C4CA61F4D5F8B0033C753 /* StatusIm.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = StatusIm.entitlements; path = StatusIm/StatusIm.entitlements; sourceTree = "<group>"; };
|
||||||
|
9C76AF5A418D4D65A4CAD1D9 /* InterStatus-Regular.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "InterStatus-Regular.otf"; path = "../resources/fonts/InterStatus-Regular.otf"; sourceTree = "<group>"; };
|
||||||
9EC0135C1E06FB1900155B5C /* RCTWKWebView.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTWKWebView.xcodeproj; path = "../node_modules/react-native-wkwebview-reborn/ios/RCTWKWebView.xcodeproj"; sourceTree = "<group>"; };
|
9EC0135C1E06FB1900155B5C /* RCTWKWebView.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTWKWebView.xcodeproj; path = "../node_modules/react-native-wkwebview-reborn/ios/RCTWKWebView.xcodeproj"; sourceTree = "<group>"; };
|
||||||
9EF083381F3B538A00876A8F /* ReactNativeConfig.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = ReactNativeConfig.xcodeproj; path = "../node_modules/react-native-config/ios/ReactNativeConfig.xcodeproj"; sourceTree = "<group>"; };
|
9EF083381F3B538A00876A8F /* ReactNativeConfig.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = ReactNativeConfig.xcodeproj; path = "../node_modules/react-native-config/ios/ReactNativeConfig.xcodeproj"; sourceTree = "<group>"; };
|
||||||
A4F2BBE8D4DD4140A6CCAC39 /* Inter-SemiBoldItalic.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Inter-SemiBoldItalic.otf"; path = "../resources/fonts/Inter-SemiBoldItalic.otf"; sourceTree = "<group>"; };
|
A4F2BBE8D4DD4140A6CCAC39 /* Inter-SemiBoldItalic.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Inter-SemiBoldItalic.otf"; path = "../resources/fonts/Inter-SemiBoldItalic.otf"; sourceTree = "<group>"; };
|
||||||
@ -181,12 +182,12 @@
|
|||||||
CD4A2C27D6D5473184DC1F7E /* Inter-Bold.otf */,
|
CD4A2C27D6D5473184DC1F7E /* Inter-Bold.otf */,
|
||||||
B321D25F4493470980039457 /* Inter-BoldItalic.otf */,
|
B321D25F4493470980039457 /* Inter-BoldItalic.otf */,
|
||||||
B07176ACDAA1422E8F0A3D6B /* Inter-Italic.otf */,
|
B07176ACDAA1422E8F0A3D6B /* Inter-Italic.otf */,
|
||||||
3A0B103024581B74004B0F23 /* InterStatus-Regular.otf */,
|
|
||||||
B2A38FC3D3954DE7B2B171F8 /* Inter-Medium.otf */,
|
B2A38FC3D3954DE7B2B171F8 /* Inter-Medium.otf */,
|
||||||
C6B1215047604CD59A4C74D6 /* Inter-MediumItalic.otf */,
|
C6B1215047604CD59A4C74D6 /* Inter-MediumItalic.otf */,
|
||||||
1426DF592BA248FC81D955CB /* Inter-Regular.otf */,
|
1426DF592BA248FC81D955CB /* Inter-Regular.otf */,
|
||||||
693A62DB37BC4CD5A30E5C96 /* Inter-SemiBold.otf */,
|
693A62DB37BC4CD5A30E5C96 /* Inter-SemiBold.otf */,
|
||||||
A4F2BBE8D4DD4140A6CCAC39 /* Inter-SemiBoldItalic.otf */,
|
A4F2BBE8D4DD4140A6CCAC39 /* Inter-SemiBoldItalic.otf */,
|
||||||
|
9C76AF5A418D4D65A4CAD1D9 /* InterStatus-Regular.otf */,
|
||||||
);
|
);
|
||||||
name = Resources;
|
name = Resources;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -429,6 +430,7 @@
|
|||||||
B2F2D1BC1D9D531B00B7B453 /* Images.xcassets in Resources */,
|
B2F2D1BC1D9D531B00B7B453 /* Images.xcassets in Resources */,
|
||||||
D84616FB563A48EBB1678699 /* Inter-Bold.otf in Resources */,
|
D84616FB563A48EBB1678699 /* Inter-Bold.otf in Resources */,
|
||||||
D99C50E5E18942A39C8DDF61 /* Inter-BoldItalic.otf in Resources */,
|
D99C50E5E18942A39C8DDF61 /* Inter-BoldItalic.otf in Resources */,
|
||||||
|
3ABC7AF8245FF85900612C45 /* InterStatus-Regular.otf in Resources */,
|
||||||
393D26E3080B443A998F4A2F /* Inter-Italic.otf in Resources */,
|
393D26E3080B443A998F4A2F /* Inter-Italic.otf in Resources */,
|
||||||
D1786306E0184916B11F4C37 /* Inter-Medium.otf in Resources */,
|
D1786306E0184916B11F4C37 /* Inter-Medium.otf in Resources */,
|
||||||
57C854A7993C47A3B1AECD32 /* Inter-MediumItalic.otf in Resources */,
|
57C854A7993C47A3B1AECD32 /* Inter-MediumItalic.otf in Resources */,
|
||||||
|
23
ios/StatusIm/Images.xcassets/hide.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "Hide.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "Hide@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "Hide@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
BIN
ios/StatusIm/Images.xcassets/hide.imageset/Hide.png
vendored
Normal file
After Width: | Height: | Size: 352 B |
BIN
ios/StatusIm/Images.xcassets/hide.imageset/Hide@2x.png
vendored
Normal file
After Width: | Height: | Size: 616 B |
BIN
ios/StatusIm/Images.xcassets/hide.imageset/Hide@3x.png
vendored
Normal file
After Width: | Height: | Size: 913 B |
23
ios/StatusIm/Images.xcassets/show.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "Show.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "Show@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "Show@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
BIN
ios/StatusIm/Images.xcassets/show.imageset/Show.png
vendored
Normal file
After Width: | Height: | Size: 326 B |
BIN
ios/StatusIm/Images.xcassets/show.imageset/Show@2x.png
vendored
Normal file
After Width: | Height: | Size: 586 B |
BIN
ios/StatusIm/Images.xcassets/show.imageset/Show@3x.png
vendored
Normal file
After Width: | Height: | Size: 840 B |
23
ios/StatusIm/Images.xcassets/tooltip-tip.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "Tip.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "Tip@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "Tip@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
BIN
ios/StatusIm/Images.xcassets/tooltip-tip.imageset/Tip.png
vendored
Normal file
After Width: | Height: | Size: 184 B |
BIN
ios/StatusIm/Images.xcassets/tooltip-tip.imageset/Tip@2x.png
vendored
Normal file
After Width: | Height: | Size: 245 B |
BIN
ios/StatusIm/Images.xcassets/tooltip-tip.imageset/Tip@3x.png
vendored
Normal file
After Width: | Height: | Size: 364 B |
@ -103,6 +103,7 @@
|
|||||||
<string>Inter-SemiBoldItalic.otf</string>
|
<string>Inter-SemiBoldItalic.otf</string>
|
||||||
<string>Inter-Thin-BETA.otf</string>
|
<string>Inter-Thin-BETA.otf</string>
|
||||||
<string>Inter-ThinItalic-BETA.otf</string>
|
<string>Inter-ThinItalic-BETA.otf</string>
|
||||||
|
<string>InterStatus-Regular.otf</string>
|
||||||
</array>
|
</array>
|
||||||
<key>UIBackgroundModes</key>
|
<key>UIBackgroundModes</key>
|
||||||
<array>
|
<array>
|
||||||
|
@ -28,9 +28,13 @@
|
|||||||
(def set (oget animated "set"))
|
(def set (oget animated "set"))
|
||||||
(def start-clock (oget animated "startClock"))
|
(def start-clock (oget animated "startClock"))
|
||||||
(def stop-clock (oget animated "stopClock"))
|
(def stop-clock (oget animated "stopClock"))
|
||||||
|
(def clock-running clockRunning)
|
||||||
(def bezier (.-bezier ^js Easing))
|
(def bezier (.-bezier ^js Easing))
|
||||||
(def linear (.-linear ^js Easing))
|
(def linear (.-linear ^js Easing))
|
||||||
|
|
||||||
|
(def easings {:ease-in (bezier 0.42 0 1 1)
|
||||||
|
:ease-out (bezier 0 0 0.58 1)})
|
||||||
|
|
||||||
(defn set-value [anim val]
|
(defn set-value [anim val]
|
||||||
(ocall anim "setValue" val))
|
(ocall anim "setValue" val))
|
||||||
|
|
||||||
@ -111,3 +115,9 @@
|
|||||||
|
|
||||||
(defn on-scroll [opts]
|
(defn on-scroll [opts]
|
||||||
(ocall redash "onScrollEvent" (clj->js opts)))
|
(ocall redash "onScrollEvent" (clj->js opts)))
|
||||||
|
|
||||||
|
(defn b-interpolate [anim-value a b]
|
||||||
|
(ocall redash "bInterpolate" anim-value a b))
|
||||||
|
|
||||||
|
(defn loop* [opts]
|
||||||
|
(ocall redash "loop" (clj->js opts)))
|
||||||
|
@ -86,7 +86,7 @@
|
|||||||
(when accessibility-label
|
(when accessibility-label
|
||||||
{:accessibility-label accessibility-label}))
|
{:accessibility-label accessibility-label}))
|
||||||
(cond
|
(cond
|
||||||
icon [icons/icon icon]
|
icon [icons/icon icon {:color (:icon-01 @colors/theme)}]
|
||||||
label [text/text {:color :link} label])]])
|
label [text/text {:color :link} label])]])
|
||||||
|
|
||||||
(defn header-actions [{:keys [accessories component]}]
|
(defn header-actions [{:keys [accessories component]}]
|
||||||
@ -102,12 +102,12 @@
|
|||||||
[rn/view {:style header-action-placeholder}])])
|
[rn/view {:style header-action-placeholder}])])
|
||||||
|
|
||||||
(defn header-title [{:keys [title subtitle component title-align]}]
|
(defn header-title [{:keys [title subtitle component title-align]}]
|
||||||
[react/fragment
|
[:<>
|
||||||
(cond
|
(cond
|
||||||
component component
|
component component
|
||||||
|
|
||||||
(and title subtitle)
|
(and title subtitle)
|
||||||
[react/fragment
|
[:<>
|
||||||
[text/text {:weight :medium
|
[text/text {:weight :medium
|
||||||
:number-of-lines 1}
|
:number-of-lines 1}
|
||||||
title]
|
title]
|
||||||
|
@ -5,19 +5,16 @@
|
|||||||
[quo.react-native :as rn]
|
[quo.react-native :as rn]
|
||||||
[reagent.core :as reagent]))
|
[reagent.core :as reagent]))
|
||||||
|
|
||||||
(defn text-style [{:keys [size align weight color style]
|
(defn text-style [{:keys [size align weight color style]}]
|
||||||
:or {size :base
|
;; NOTE(Ferossgo): or in destructoring will keep nil as a value
|
||||||
weight :regular
|
(merge (case (or weight :regular)
|
||||||
align :auto
|
|
||||||
color :main}}]
|
|
||||||
(merge (case weight
|
|
||||||
:regular typography/font-regular
|
:regular typography/font-regular
|
||||||
:medium typography/font-medium
|
:medium typography/font-medium
|
||||||
:semi-bold typography/font-semi-bold
|
:semi-bold typography/font-semi-bold
|
||||||
:bold typography/font-bold
|
:bold typography/font-bold
|
||||||
:monospace typography/monospace
|
:monospace typography/monospace
|
||||||
:inherit nil)
|
:inherit nil)
|
||||||
(case color
|
(case (or color :main)
|
||||||
:main {:color (:text-01 @colors/theme)}
|
:main {:color (:text-01 @colors/theme)}
|
||||||
:secondary {:color (:text-02 @colors/theme)}
|
:secondary {:color (:text-02 @colors/theme)}
|
||||||
:secondary-inverse {:color (:text-03 @colors/theme)}
|
:secondary-inverse {:color (:text-03 @colors/theme)}
|
||||||
@ -25,7 +22,7 @@
|
|||||||
:positive {:color (:positive-01 @colors/theme)}
|
:positive {:color (:positive-01 @colors/theme)}
|
||||||
:negative {:color (:negative-01 @colors/theme)}
|
:negative {:color (:negative-01 @colors/theme)}
|
||||||
:inherit nil)
|
:inherit nil)
|
||||||
(case size
|
(case (or size :base)
|
||||||
:tiny typography/tiny
|
:tiny typography/tiny
|
||||||
:small typography/small
|
:small typography/small
|
||||||
:base typography/base
|
:base typography/base
|
||||||
@ -33,7 +30,7 @@
|
|||||||
:x-large typography/x-large
|
:x-large typography/x-large
|
||||||
:xx-large typography/xx-large
|
:xx-large typography/xx-large
|
||||||
:inherit nil)
|
:inherit nil)
|
||||||
{:text-align align}
|
{:text-align (or align :auto)}
|
||||||
style))
|
style))
|
||||||
|
|
||||||
(defn text []
|
(defn text []
|
||||||
|
204
src/quo/components/text_input.cljs
Normal file
@ -0,0 +1,204 @@
|
|||||||
|
(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.vector-icons :as icons]
|
||||||
|
;; TODO(Ferossgp): Move tooltip into lib
|
||||||
|
[quo.components.tooltip :as tooltip]
|
||||||
|
[quo.react :as react]
|
||||||
|
[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]))
|
||||||
|
|
||||||
|
(s/def ::multiline boolean?)
|
||||||
|
(s/def ::secure-text-entry boolean?)
|
||||||
|
(s/def ::show-cancel boolean?)
|
||||||
|
(s/def ::label (s/nilable string?))
|
||||||
|
(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/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 :req-un [::icon]
|
||||||
|
:opt-un [::on-press]))
|
||||||
|
(s/def ::after (s/nilable ::accessory))
|
||||||
|
(s/def ::before (s/nilable ::accessory))
|
||||||
|
|
||||||
|
(s/def ::style (s/nilable map?))
|
||||||
|
(s/def ::input-style (s/nilable map?))
|
||||||
|
|
||||||
|
(s/def ::text-input (s/keys :opt-un
|
||||||
|
[::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]))
|
||||||
|
|
||||||
|
(defn check-spec [spec prop]
|
||||||
|
(if (s/valid? spec prop)
|
||||||
|
true
|
||||||
|
(do
|
||||||
|
(s/explain spec prop)
|
||||||
|
false)))
|
||||||
|
|
||||||
|
;; TODO(Ferossgp): Check performance for android layout animations
|
||||||
|
(when (and platform/android?
|
||||||
|
(aget rn/ui-manager "setLayoutAnimationEnabledExperimental"))
|
||||||
|
(ocall rn/ui-manager "setLayoutAnimationEnabledExperimental" true))
|
||||||
|
|
||||||
|
(def height 44) ; 22 line-height + 11*2 vertical padding
|
||||||
|
(def multiline-height 88) ; 3 * 22 three line-height + 11* vertical padding
|
||||||
|
|
||||||
|
(defn container-style [])
|
||||||
|
|
||||||
|
(defn label-style []
|
||||||
|
{:margin-bottom (:tiny spacing/spacing)})
|
||||||
|
|
||||||
|
(defn text-input-row-style []
|
||||||
|
{:flex-direction :row
|
||||||
|
:align-items :center})
|
||||||
|
|
||||||
|
(defn text-input-view-style [style]
|
||||||
|
(merge {:border-radius 8
|
||||||
|
:flex-direction :row
|
||||||
|
:flex 1
|
||||||
|
:align-items :center
|
||||||
|
:background-color (:ui-01 @colors/theme)}
|
||||||
|
style))
|
||||||
|
|
||||||
|
(defn text-input-style [multiline input-style before after]
|
||||||
|
(merge typography/font-regular
|
||||||
|
{:padding-top 11
|
||||||
|
:padding-bottom 11
|
||||||
|
:font-size 15
|
||||||
|
:margin 0
|
||||||
|
:text-align-vertical :center
|
||||||
|
:flex 1
|
||||||
|
:height height}
|
||||||
|
(when-not before
|
||||||
|
{:padding-left (:base spacing/spacing)})
|
||||||
|
(when-not after
|
||||||
|
{:padding-right (:base spacing/spacing)})
|
||||||
|
(when multiline
|
||||||
|
{:text-align-vertical :top
|
||||||
|
:line-height 22
|
||||||
|
:height multiline-height})
|
||||||
|
input-style))
|
||||||
|
|
||||||
|
(defn cancel-style []
|
||||||
|
{:margin-left (:tiny spacing/spacing)
|
||||||
|
:padding-left (:tiny spacing/spacing)
|
||||||
|
:justify-content :center
|
||||||
|
:align-self :stretch})
|
||||||
|
|
||||||
|
(defn accessory-style []
|
||||||
|
(merge (:base spacing/padding-horizontal)
|
||||||
|
{:flex 1
|
||||||
|
:justify-content :center}))
|
||||||
|
|
||||||
|
(defn accessory-element [{:keys [icon 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}))
|
||||||
|
[icons/icon icon (merge {:color (:icon-01 @colors/theme)}
|
||||||
|
icon-opts)]]]))
|
||||||
|
|
||||||
|
(defn text-input []
|
||||||
|
(let [focused (reagent/atom nil)
|
||||||
|
visible (reagent/atom false)
|
||||||
|
ref (react/create-ref)
|
||||||
|
on-cancel (fn []
|
||||||
|
(some-> (react/current-ref 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]
|
||||||
|
:or {cancel-label "Cancel"
|
||||||
|
show-cancel true}
|
||||||
|
:as props}]
|
||||||
|
{:pre [(check-spec ::text-input props)]}
|
||||||
|
(let [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)}
|
||||||
|
|
||||||
|
:else after)
|
||||||
|
secure (and secure-text-entry (not @visible))]
|
||||||
|
[rn/view {:style container-style}
|
||||||
|
(when label
|
||||||
|
[text/text {:style (label-style)}
|
||||||
|
label])
|
||||||
|
[rn/view {:style (text-input-row-style)}
|
||||||
|
[rn/view {:style (text-input-view-style style)}
|
||||||
|
(when before
|
||||||
|
[accessory-element before])
|
||||||
|
[rn/text-input
|
||||||
|
(merge {:style (text-input-style multiline input-style before after)
|
||||||
|
:ref ref
|
||||||
|
:placeholder-text-color (:text-02 @colors/theme)
|
||||||
|
:color (:text-01 @colors/theme)
|
||||||
|
:underline-color-android :transparent
|
||||||
|
:auto-capitalize :none
|
||||||
|
:secure-text-entry secure
|
||||||
|
:on-focus (fn [evt]
|
||||||
|
(when on-focus (on-focus evt))
|
||||||
|
(rn/configure-next (:ease-in-ease-out rn/layout-animation-presets))
|
||||||
|
(reset! focused true))
|
||||||
|
:on-blur (fn [evt]
|
||||||
|
(when on-blur (on-blur evt))
|
||||||
|
(rn/configure-next (:ease-in-ease-out rn/layout-animation-presets))
|
||||||
|
(reset! focused false))}
|
||||||
|
(when (and platform/ios? (not after))
|
||||||
|
{:clear-button-mode :while-editing})
|
||||||
|
(when (and platform/ios?
|
||||||
|
(not= keyboard-type "visible-password"))
|
||||||
|
{:keyboard-type keyboard-type})
|
||||||
|
(dissoc props
|
||||||
|
:style :keyboard-type :on-focus :on-blur
|
||||||
|
:secure-text-entry :ref))]
|
||||||
|
(when after
|
||||||
|
[accessory-element after])]
|
||||||
|
(when (and platform/ios?
|
||||||
|
show-cancel
|
||||||
|
(not multiline)
|
||||||
|
@focused)
|
||||||
|
[rn/touchable-opacity {:style (cancel-style)
|
||||||
|
:on-press on-cancel}
|
||||||
|
[text/text {:color :link} cancel-label]])]
|
||||||
|
(when error
|
||||||
|
[tooltip/tooltip (merge {:bottom-value (cond bottom-value bottom-value
|
||||||
|
label 30 ; 22 line height 8 margin
|
||||||
|
)}
|
||||||
|
(when accessibility-label
|
||||||
|
{:accessibility-label (str (name accessibility-label) "-error")}))
|
||||||
|
[text/text {:color :negative
|
||||||
|
:size :small}
|
||||||
|
error]])]))))
|
65
src/quo/components/tooltip.cljs
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
(ns quo.components.tooltip
|
||||||
|
(:require [reagent.core :as reagent]
|
||||||
|
[oops.core :refer [oget]]
|
||||||
|
[quo.animated :as animated]
|
||||||
|
[quo.react :as react]
|
||||||
|
[quo.react-native :as rn]
|
||||||
|
[quo.design-system.colors :as colors]
|
||||||
|
[quo.design-system.spacing :as spacing]
|
||||||
|
[status-im.ui.components.icons.vector-icons :as vector-icons]))
|
||||||
|
|
||||||
|
(def ^:private initial-height 22)
|
||||||
|
|
||||||
|
(defn tooltip-style [{:keys [bottom-value animation]}]
|
||||||
|
(merge
|
||||||
|
(:base spacing/padding-horizontal)
|
||||||
|
{:position :absolute
|
||||||
|
:align-items :center
|
||||||
|
:left 0
|
||||||
|
:right 0
|
||||||
|
:top (- bottom-value)
|
||||||
|
:opacity animation
|
||||||
|
:transform [{:translateY (animated/b-interpolate animation 10 0)}]}))
|
||||||
|
|
||||||
|
(defn container-style []
|
||||||
|
{:z-index 2
|
||||||
|
:align-items :center
|
||||||
|
:shadow-radius 16
|
||||||
|
:shadow-opacity 1
|
||||||
|
:shadow-color (:shadow-01 @colors/theme)
|
||||||
|
:shadow-offset {:width 0 :height 4}})
|
||||||
|
|
||||||
|
(defn content-style []
|
||||||
|
(merge (:base spacing/padding-horizontal)
|
||||||
|
{:padding-vertical 6
|
||||||
|
:elevation 2
|
||||||
|
:background-color (:ui-background @colors/theme)
|
||||||
|
:border-radius 8}))
|
||||||
|
|
||||||
|
(defn tooltip []
|
||||||
|
(let [layout (reagent/atom {:height initial-height})
|
||||||
|
animation-v (animated/value 0)
|
||||||
|
animation (animated/with-timing
|
||||||
|
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]} & children]
|
||||||
|
[:<>
|
||||||
|
[animated/code {:exec (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)
|
||||||
|
:on-layout on-layout}]
|
||||||
|
children)
|
||||||
|
[vector-icons/icon :icons/tooltip-tip {:width 18
|
||||||
|
:height 8
|
||||||
|
:container-style {:elevation 3}
|
||||||
|
:color (:ui-background @colors/theme)}]]]])))
|
@ -2,12 +2,15 @@
|
|||||||
(:require [quo.components.animated-header :as animated-header]
|
(:require [quo.components.animated-header :as animated-header]
|
||||||
[quo.components.header :as header]
|
[quo.components.header :as header]
|
||||||
[quo.components.safe-area :as safe-area]
|
[quo.components.safe-area :as safe-area]
|
||||||
|
[quo.components.text-input :as text-input]
|
||||||
|
[quo.components.tooltip :as tooltip]
|
||||||
[quo.components.text :as text]))
|
[quo.components.text :as text]))
|
||||||
|
|
||||||
(def text text/text)
|
(def text text/text)
|
||||||
(def header header/header)
|
(def header header/header)
|
||||||
(def animated-header animated-header/header)
|
(def animated-header animated-header/header)
|
||||||
|
(def text-input text-input/text-input)
|
||||||
|
(def tooltip tooltip/tooltip)
|
||||||
(def safe-area-provider safe-area/provider)
|
(def safe-area-provider safe-area/provider)
|
||||||
(def safe-area-consumer safe-area/consumer)
|
(def safe-area-consumer safe-area/consumer)
|
||||||
(def safe-area-view safe-area/view)
|
(def safe-area-view safe-area/view)
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
(ns quo.previews.header
|
(ns quo.previews.header
|
||||||
(:require [quo.core :as quo]
|
(:require [quo.core :as quo]
|
||||||
[quo.react-native :as rn]))
|
[quo.react-native :as rn]
|
||||||
|
[quo.design-system.colors :as colors])
|
||||||
|
(:require-macros [quo.previews.preview :as preview]))
|
||||||
|
|
||||||
(def accessories [nil
|
(def accessories [nil
|
||||||
[{:icon :main-icons/close
|
[{:icon :main-icons/close
|
||||||
@ -16,17 +18,27 @@
|
|||||||
[{:label "Text"
|
[{:label "Text"
|
||||||
:on-press identity}]])
|
:on-press identity}]])
|
||||||
|
|
||||||
(defn preview-header []
|
(def all-props (preview/list-comp [left-accessories accessories
|
||||||
[rn/scroll-view {:flex 1}
|
|
||||||
(for [left-accessories accessories
|
|
||||||
right-accessories accessories
|
right-accessories accessories
|
||||||
title [nil "This is a title" "This is a very long super title"]
|
title [nil "This is a title" "This is a very long super title"]
|
||||||
subtitle [nil "This is a subtitle"]
|
subtitle [nil "This is a subtitle"]
|
||||||
title-align [:left :center]]
|
title-align [:left :center]]
|
||||||
[rn/view {:border-bottom-color "#EEF2F5"
|
{:left-accessories left-accessories
|
||||||
:border-bottom-width 2}
|
|
||||||
[quo/header {:left-accessories left-accessories
|
|
||||||
:right-accessories right-accessories
|
:right-accessories right-accessories
|
||||||
:title title
|
:title title
|
||||||
:subtitle subtitle
|
:subtitle subtitle
|
||||||
:title-align title-align}]])])
|
:title-align title-align}))
|
||||||
|
|
||||||
|
(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}]])
|
||||||
|
@ -2,26 +2,62 @@
|
|||||||
(:require [oops.core :refer [ocall]]
|
(:require [oops.core :refer [ocall]]
|
||||||
[quo.previews.header :as header]
|
[quo.previews.header :as header]
|
||||||
[quo.previews.text :as text]
|
[quo.previews.text :as text]
|
||||||
|
[quo.previews.text-input :as text-input]
|
||||||
|
[quo.previews.tooltip :as tooltip]
|
||||||
[quo.react-native :as rn]
|
[quo.react-native :as rn]
|
||||||
|
[quo.core :as quo]
|
||||||
[reagent.core :as reagent]
|
[reagent.core :as reagent]
|
||||||
|
[quo.design-system.colors :as colors]
|
||||||
|
[quo.theme :as theme]
|
||||||
[status-im.ui.screens.routing.core :as navigation]))
|
[status-im.ui.screens.routing.core :as navigation]))
|
||||||
|
|
||||||
(def screens [{:name :texts
|
(def screens [{:name :texts
|
||||||
:insets {:top false}
|
:insets {:top false}
|
||||||
:component text/preview-text}
|
: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
|
{:name :headers
|
||||||
:insets {:top false}
|
:insets {:top false}
|
||||||
:component header/preview-header}])
|
:component header/preview-header}])
|
||||||
|
|
||||||
|
(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)}
|
||||||
|
[quo/text "Set dark theme"]]])
|
||||||
|
|
||||||
(defn main-screen []
|
(defn main-screen []
|
||||||
[rn/scroll-view {:flex 1
|
[rn/scroll-view {:flex 1
|
||||||
:padding-vertical 8
|
:padding-vertical 8
|
||||||
:padding-horizontal 16}
|
:padding-horizontal 16
|
||||||
|
:background-color (:ui-background @colors/theme)}
|
||||||
|
[theme-switcher]
|
||||||
[rn/view
|
[rn/view
|
||||||
(for [{:keys [name]} screens]
|
(for [{:keys [name]} screens]
|
||||||
[rn/touchable-opacity {:on-press #(navigation/navigate-to name nil)}
|
[rn/touchable-opacity {:on-press #(navigation/navigate-to name nil)}
|
||||||
[rn/view {:style {:padding-vertical 8}}
|
[rn/view {:style {:padding-vertical 8}}
|
||||||
[rn/text (str "Preview " name)]]])]])
|
[quo/text (str "Preview " name)]]])]])
|
||||||
|
|
||||||
(defonce navigation-state (atom nil))
|
(defonce navigation-state (atom nil))
|
||||||
|
|
||||||
|
15
src/quo/previews/preview.clj
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
(ns quo.previews.preview)
|
||||||
|
|
||||||
|
(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]
|
||||||
|
(cond (not binding)
|
||||||
|
`(list ~body-expr)
|
||||||
|
|
||||||
|
:else
|
||||||
|
`(mapcat (fn [~binding] (list-comp ~bindings ~body-expr))
|
||||||
|
~seq-expr)))
|
171
src/quo/previews/preview.cljs
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
(ns quo.previews.preview
|
||||||
|
(:require [reagent.core :as reagent]
|
||||||
|
[quo.react-native :as rn]
|
||||||
|
[quo.core :as quo]
|
||||||
|
[quo.design-system.colors :as colors])
|
||||||
|
(:require-macros quo.previews.preview))
|
||||||
|
|
||||||
|
(def container {:flex-direction :row
|
||||||
|
:padding-vertical 8
|
||||||
|
:align-items :center})
|
||||||
|
|
||||||
|
(defn touchable-style []
|
||||||
|
{:flex 1
|
||||||
|
:align-items :center
|
||||||
|
:justify-content :center
|
||||||
|
:padding-horizontal 16
|
||||||
|
:height 44})
|
||||||
|
|
||||||
|
(defn select-style []
|
||||||
|
{:flex 1
|
||||||
|
:flex-direction :row
|
||||||
|
:align-items :center
|
||||||
|
:padding-horizontal 16
|
||||||
|
:height 44
|
||||||
|
:border-radius 4
|
||||||
|
:background-color (:ui-01 @colors/theme)
|
||||||
|
:border-width 1
|
||||||
|
:border-color (:ui-02 @colors/theme)})
|
||||||
|
|
||||||
|
(defn select-option-style [selected]
|
||||||
|
(merge (select-style)
|
||||||
|
{:margin-vertical 8
|
||||||
|
:justify-content :center}
|
||||||
|
(if selected
|
||||||
|
{:background-color (:interactive-02 @colors/theme)}
|
||||||
|
{:background-color (:ui-01 @colors/theme)})))
|
||||||
|
|
||||||
|
(def label-style {:flex 0.4
|
||||||
|
:padding-right 8})
|
||||||
|
|
||||||
|
(defn modal-container []
|
||||||
|
{:flex 1
|
||||||
|
:justify-content :center
|
||||||
|
:padding-horizontal 24
|
||||||
|
:background-color "rgba(0,0,0,0.4)"})
|
||||||
|
|
||||||
|
(defn modal-view []
|
||||||
|
{:padding-horizontal 16
|
||||||
|
:padding-vertical 8
|
||||||
|
:border-radius 8
|
||||||
|
:flex-direction :column
|
||||||
|
:background-color (:ui-background @colors/theme)})
|
||||||
|
|
||||||
|
(defn customizer-boolean
|
||||||
|
[{:keys [label key state]}]
|
||||||
|
(let [state* (reagent/cursor state [key])]
|
||||||
|
[rn/view {:style container}
|
||||||
|
[rn/view {:style label-style}
|
||||||
|
[quo/text 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)}
|
||||||
|
"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)}
|
||||||
|
[quo/text {:color (if (not @state*) :link :secondary)}
|
||||||
|
"False"]]]]))
|
||||||
|
|
||||||
|
(defn customizer-text
|
||||||
|
[{:keys [label key state]}]
|
||||||
|
(let [state* (reagent/cursor state [key])]
|
||||||
|
[rn/view {:style container}
|
||||||
|
[rn/view {:style label-style}
|
||||||
|
[quo/text 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))}]]]))
|
||||||
|
|
||||||
|
(defn value-for-key
|
||||||
|
[id v]
|
||||||
|
(:value (first (filter #(= (:key %) id) v))))
|
||||||
|
|
||||||
|
(defn customizer-select []
|
||||||
|
(let [open (reagent/atom nil)]
|
||||||
|
(fn [{:keys [label key state options]}]
|
||||||
|
(let [state* (reagent/cursor state [key])
|
||||||
|
selected (value-for-key @state* options)]
|
||||||
|
[rn/view {:style container}
|
||||||
|
[rn/view {:style label-style}
|
||||||
|
[quo/text label]]
|
||||||
|
[rn/view {:style {:flex 0.6}}
|
||||||
|
[rn/modal {:visible @open
|
||||||
|
:on-request-close #(reset! open false)
|
||||||
|
: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))}
|
||||||
|
[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))}
|
||||||
|
[quo/text "Clear"]]
|
||||||
|
[rn/view {:width 16}]
|
||||||
|
[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)}
|
||||||
|
(if selected
|
||||||
|
[quo/text {:color :link} selected]
|
||||||
|
[quo/text "Select option"])
|
||||||
|
[rn/view {:position :absolute
|
||||||
|
:right 16
|
||||||
|
:top 0
|
||||||
|
:bottom 0
|
||||||
|
:justify-content :center}
|
||||||
|
[quo/text "↓"]]]]]))))
|
||||||
|
|
||||||
|
(defn customizer [state descriptors]
|
||||||
|
[rn/view
|
||||||
|
(doall
|
||||||
|
(for [{:keys [key type]
|
||||||
|
:as desc} descriptors
|
||||||
|
:let [descriptor (merge desc
|
||||||
|
{:state state})]]
|
||||||
|
^{:key key}
|
||||||
|
[rn/view
|
||||||
|
(case type
|
||||||
|
:boolean [customizer-boolean descriptor]
|
||||||
|
:text [customizer-text descriptor]
|
||||||
|
:select [customizer-select descriptor])]))])
|
||||||
|
|
||||||
|
(comment
|
||||||
|
[{:label "Show error:"
|
||||||
|
:key :error
|
||||||
|
:type :boolean}
|
||||||
|
{:label "Label:"
|
||||||
|
:key :label
|
||||||
|
:type :text}
|
||||||
|
{:label "Type:"
|
||||||
|
:key :type
|
||||||
|
:type :select
|
||||||
|
:options [{:key :primary :value "Primary"}
|
||||||
|
{:key :secondary :value "Secondary"}]}])
|
@ -1,14 +1,89 @@
|
|||||||
(ns quo.previews.text
|
(ns quo.previews.text
|
||||||
(:require [quo.core :as quo]
|
(:require [reagent.core :as reagent]
|
||||||
[quo.react-native :as rn]))
|
[quo.core :as quo]
|
||||||
|
[quo.animated :as animated]
|
||||||
|
[quo.react-native :as rn]
|
||||||
|
[quo.design-system.colors :as colors]
|
||||||
|
[quo.previews.preview :as preview]))
|
||||||
|
|
||||||
|
(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}])
|
||||||
|
|
||||||
|
(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 []
|
||||||
|
(let [state (reagent/atom {})
|
||||||
|
animation (animated/value 0)]
|
||||||
|
(fn []
|
||||||
|
[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}))
|
||||||
|
"This is a demo text 1 2 0 2x2 0x0"]]])))
|
||||||
|
|
||||||
(defn preview-text []
|
(defn preview-text []
|
||||||
[rn/scroll-view {:flex 1
|
[rn/view {:background-color (:ui-background @colors/theme)
|
||||||
:padding-horizontal 16}
|
:flex 1}
|
||||||
(for [size [:tiny :small :base :large :x-large :xx-large]
|
[rn/flat-list {:flex 1
|
||||||
weight [:regular :medium :semi-bold :bold :monospace]]
|
:keyboardShouldPersistTaps :always
|
||||||
^{:key (str)}
|
:header [cool-preview]
|
||||||
[rn/view {:padding-vertical 16}
|
:data all-props
|
||||||
[quo/text {:weight weight
|
:render-fn render-item
|
||||||
:size size}
|
:key-fn str}]])
|
||||||
(str "Text size " size ", font weight " weight)]])])
|
|
||||||
|
81
src/quo/previews/text_input.cljs
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
(ns quo.previews.text-input
|
||||||
|
(:require [reagent.core :as reagent]
|
||||||
|
[quo.core :as quo]
|
||||||
|
[quo.react-native :as rn]
|
||||||
|
[quo.design-system.colors :as colors]
|
||||||
|
[quo.previews.preview :as preview]))
|
||||||
|
|
||||||
|
(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}])
|
||||||
|
|
||||||
|
(defn render-item [props]
|
||||||
|
[rn/view {:style {:padding-horizontal 16
|
||||||
|
:padding-vertical 24}}
|
||||||
|
[quo/text-input props]])
|
||||||
|
|
||||||
|
(defn cool-preview []
|
||||||
|
(let [state (reagent/atom {:secure false
|
||||||
|
:show-cancel false
|
||||||
|
:multiline false
|
||||||
|
:label "I'm a cool label"})
|
||||||
|
before (reagent/cursor state [:before])
|
||||||
|
after (reagent/cursor state [:after])
|
||||||
|
error (reagent/cursor state [:error])]
|
||||||
|
(fn []
|
||||||
|
[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!")})]])))
|
||||||
|
|
||||||
|
(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}]])
|
30
src/quo/previews/tooltip.cljs
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
(ns quo.previews.tooltip
|
||||||
|
(:require [quo.core :as quo]
|
||||||
|
[quo.react-native :as rn]
|
||||||
|
[quo.design-system.colors :as colors])
|
||||||
|
(: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))
|
||||||
|
|
||||||
|
(defn render-item [children]
|
||||||
|
[rn/view {:margin-vertical 50}
|
||||||
|
[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}]])
|
@ -1,7 +1,8 @@
|
|||||||
(ns quo.react
|
(ns quo.react
|
||||||
(:require [oops.core :refer [oget]]
|
(:require [oops.core :refer [oget]]
|
||||||
[reagent.core :as reagent]
|
|
||||||
["react" :as react]))
|
["react" :as react]))
|
||||||
|
|
||||||
;; NOTE(Ferossgp): Available in new versions of reagent as `:<>`
|
(def create-ref (oget react "createRef"))
|
||||||
(def fragment (reagent/adapt-react-class (oget react "Fragment")))
|
|
||||||
|
(defn current-ref [ref]
|
||||||
|
(oget ref "current"))
|
||||||
|
@ -11,6 +11,45 @@
|
|||||||
(def text (reagent/adapt-react-class (.-Text ^js rn)))
|
(def text (reagent/adapt-react-class (.-Text ^js rn)))
|
||||||
|
|
||||||
(def scroll-view (reagent/adapt-react-class (.-ScrollView ^js rn)))
|
(def scroll-view (reagent/adapt-react-class (.-ScrollView ^js rn)))
|
||||||
|
(def modal (reagent/adapt-react-class (.-Modal ^js rn)))
|
||||||
|
|
||||||
(def touchable-opacity (reagent/adapt-react-class (.-TouchableOpacity ^js rn)))
|
(def touchable-opacity (reagent/adapt-react-class (.-TouchableOpacity ^js rn)))
|
||||||
(def touchable-highlight (reagent/adapt-react-class (.-TouchableHighlight ^js rn)))
|
(def touchable-highlight (reagent/adapt-react-class (.-TouchableHighlight ^js rn)))
|
||||||
|
|
||||||
|
(def text-input (reagent/adapt-react-class (.-TextInput ^js rn)))
|
||||||
|
|
||||||
|
(def ui-manager (.-UIManager ^js rn))
|
||||||
|
|
||||||
|
(def layout-animation (.-LayoutAnimation ^js rn))
|
||||||
|
(def configure-next (.-configureNext ^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 switch (reagent/adapt-react-class (.-Switch ^js rn)))
|
||||||
|
|
||||||
|
;; Flat-list
|
||||||
|
(def ^:private rn-flat-list (reagent/adapt-react-class (.-FlatList ^js rn)))
|
||||||
|
|
||||||
|
(defn- wrap-render-fn [f]
|
||||||
|
(fn [data]
|
||||||
|
(reagent/as-element (f (.-item data) (.-index data) (.-separators data)))))
|
||||||
|
|
||||||
|
(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] :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)})
|
||||||
|
(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)})
|
||||||
|
(dissoc props :data :header :footer :empty-component :separator :render-fn :key-fn)))
|
||||||
|
|
||||||
|
(defn flat-list [props]
|
||||||
|
[rn-flat-list (base-list-props props)])
|
||||||
|
4
src/quo/spec.cljs
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
(ns quo.spec
|
||||||
|
(:require [clojure.spec.alpha :as s]))
|
||||||
|
|
||||||
|
(s/def ::style (s/nilable map?))
|