@onekeyfe/react-native-perp-depth-bar 3.0.39

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (168) hide show
  1. package/LICENSE +21 -0
  2. package/PerpDepthBar.podspec +29 -0
  3. package/README.md +31 -0
  4. package/android/CMakeLists.txt +24 -0
  5. package/android/build.gradle +128 -0
  6. package/android/src/main/AndroidManifest.xml +2 -0
  7. package/android/src/main/cpp/cpp-adapter.cpp +6 -0
  8. package/android/src/main/java/com/margelo/nitro/perpdepthbar/HybridPerpDepthBars.kt +164 -0
  9. package/android/src/main/java/com/margelo/nitro/perpdepthbar/HybridPerpSideRatio.kt +139 -0
  10. package/android/src/main/java/com/margelo/nitro/perpdepthbar/PerpColorParser.kt +56 -0
  11. package/android/src/main/java/com/margelo/nitro/perpdepthbar/PerpDepthBarPackage.kt +33 -0
  12. package/ios/HybridPerpDepthBars.swift +148 -0
  13. package/ios/HybridPerpSideRatio.swift +118 -0
  14. package/ios/PerpColorParser.swift +92 -0
  15. package/lib/module/PerpDepthBars.nitro.js +4 -0
  16. package/lib/module/PerpDepthBars.nitro.js.map +1 -0
  17. package/lib/module/PerpSideRatio.nitro.js +4 -0
  18. package/lib/module/PerpSideRatio.nitro.js.map +1 -0
  19. package/lib/module/index.js +8 -0
  20. package/lib/module/index.js.map +1 -0
  21. package/lib/module/package.json +1 -0
  22. package/lib/nitrogen/generated/android/c++/JHybridPerpDepthBarsSpec.cpp +130 -0
  23. package/lib/nitrogen/generated/android/c++/JHybridPerpDepthBarsSpec.hpp +80 -0
  24. package/lib/nitrogen/generated/android/c++/JHybridPerpSideRatioSpec.cpp +119 -0
  25. package/lib/nitrogen/generated/android/c++/JHybridPerpSideRatioSpec.hpp +80 -0
  26. package/lib/nitrogen/generated/android/c++/views/JHybridPerpDepthBarsStateUpdater.cpp +84 -0
  27. package/lib/nitrogen/generated/android/c++/views/JHybridPerpDepthBarsStateUpdater.hpp +49 -0
  28. package/lib/nitrogen/generated/android/c++/views/JHybridPerpSideRatioStateUpdater.cpp +84 -0
  29. package/lib/nitrogen/generated/android/c++/views/JHybridPerpSideRatioStateUpdater.hpp +49 -0
  30. package/lib/nitrogen/generated/android/kotlin/com/margelo/nitro/perpdepthbar/HybridPerpDepthBarsSpec.kt +101 -0
  31. package/lib/nitrogen/generated/android/kotlin/com/margelo/nitro/perpdepthbar/HybridPerpSideRatioSpec.kt +101 -0
  32. package/lib/nitrogen/generated/android/kotlin/com/margelo/nitro/perpdepthbar/perpdepthbarOnLoad.kt +35 -0
  33. package/lib/nitrogen/generated/android/kotlin/com/margelo/nitro/perpdepthbar/views/HybridPerpDepthBarsManager.kt +50 -0
  34. package/lib/nitrogen/generated/android/kotlin/com/margelo/nitro/perpdepthbar/views/HybridPerpDepthBarsStateUpdater.kt +23 -0
  35. package/lib/nitrogen/generated/android/kotlin/com/margelo/nitro/perpdepthbar/views/HybridPerpSideRatioManager.kt +50 -0
  36. package/lib/nitrogen/generated/android/kotlin/com/margelo/nitro/perpdepthbar/views/HybridPerpSideRatioStateUpdater.kt +23 -0
  37. package/lib/nitrogen/generated/android/perpdepthbar+autolinking.cmake +87 -0
  38. package/lib/nitrogen/generated/android/perpdepthbar+autolinking.gradle +27 -0
  39. package/lib/nitrogen/generated/android/perpdepthbarOnLoad.cpp +58 -0
  40. package/lib/nitrogen/generated/android/perpdepthbarOnLoad.hpp +25 -0
  41. package/lib/nitrogen/generated/ios/PerpDepthBar+autolinking.rb +60 -0
  42. package/lib/nitrogen/generated/ios/PerpDepthBar-Swift-Cxx-Bridge.cpp +50 -0
  43. package/lib/nitrogen/generated/ios/PerpDepthBar-Swift-Cxx-Bridge.hpp +69 -0
  44. package/lib/nitrogen/generated/ios/PerpDepthBar-Swift-Cxx-Umbrella.hpp +48 -0
  45. package/lib/nitrogen/generated/ios/PerpDepthBarAutolinking.mm +41 -0
  46. package/lib/nitrogen/generated/ios/PerpDepthBarAutolinking.swift +40 -0
  47. package/lib/nitrogen/generated/ios/c++/HybridPerpDepthBarsSpecSwift.cpp +11 -0
  48. package/lib/nitrogen/generated/ios/c++/HybridPerpDepthBarsSpecSwift.hpp +120 -0
  49. package/lib/nitrogen/generated/ios/c++/HybridPerpSideRatioSpecSwift.cpp +11 -0
  50. package/lib/nitrogen/generated/ios/c++/HybridPerpSideRatioSpecSwift.hpp +118 -0
  51. package/lib/nitrogen/generated/ios/c++/views/HybridPerpDepthBarsComponent.mm +131 -0
  52. package/lib/nitrogen/generated/ios/c++/views/HybridPerpSideRatioComponent.mm +131 -0
  53. package/lib/nitrogen/generated/ios/swift/HybridPerpDepthBarsSpec.swift +63 -0
  54. package/lib/nitrogen/generated/ios/swift/HybridPerpDepthBarsSpec_cxx.swift +223 -0
  55. package/lib/nitrogen/generated/ios/swift/HybridPerpSideRatioSpec.swift +63 -0
  56. package/lib/nitrogen/generated/ios/swift/HybridPerpSideRatioSpec_cxx.swift +217 -0
  57. package/lib/nitrogen/generated/shared/c++/HybridPerpDepthBarsSpec.cpp +36 -0
  58. package/lib/nitrogen/generated/shared/c++/HybridPerpDepthBarsSpec.hpp +78 -0
  59. package/lib/nitrogen/generated/shared/c++/HybridPerpSideRatioSpec.cpp +36 -0
  60. package/lib/nitrogen/generated/shared/c++/HybridPerpSideRatioSpec.hpp +77 -0
  61. package/lib/nitrogen/generated/shared/c++/views/HybridPerpDepthBarsComponent.cpp +171 -0
  62. package/lib/nitrogen/generated/shared/c++/views/HybridPerpDepthBarsComponent.hpp +116 -0
  63. package/lib/nitrogen/generated/shared/c++/views/HybridPerpSideRatioComponent.cpp +171 -0
  64. package/lib/nitrogen/generated/shared/c++/views/HybridPerpSideRatioComponent.hpp +115 -0
  65. package/lib/nitrogen/generated/shared/json/PerpDepthBarsConfig.json +17 -0
  66. package/lib/nitrogen/generated/shared/json/PerpSideRatioConfig.json +17 -0
  67. package/lib/nitrogen/nitrogen/generated/android/c++/JHybridPerpDepthBarsSpec.cpp +130 -0
  68. package/lib/nitrogen/nitrogen/generated/android/c++/JHybridPerpDepthBarsSpec.hpp +80 -0
  69. package/lib/nitrogen/nitrogen/generated/android/c++/JHybridPerpSideRatioSpec.cpp +119 -0
  70. package/lib/nitrogen/nitrogen/generated/android/c++/JHybridPerpSideRatioSpec.hpp +80 -0
  71. package/lib/nitrogen/nitrogen/generated/android/c++/views/JHybridPerpDepthBarsStateUpdater.cpp +84 -0
  72. package/lib/nitrogen/nitrogen/generated/android/c++/views/JHybridPerpDepthBarsStateUpdater.hpp +49 -0
  73. package/lib/nitrogen/nitrogen/generated/android/c++/views/JHybridPerpSideRatioStateUpdater.cpp +84 -0
  74. package/lib/nitrogen/nitrogen/generated/android/c++/views/JHybridPerpSideRatioStateUpdater.hpp +49 -0
  75. package/lib/nitrogen/nitrogen/generated/android/kotlin/com/margelo/nitro/perpdepthbar/HybridPerpDepthBarsSpec.kt +101 -0
  76. package/lib/nitrogen/nitrogen/generated/android/kotlin/com/margelo/nitro/perpdepthbar/HybridPerpSideRatioSpec.kt +101 -0
  77. package/lib/nitrogen/nitrogen/generated/android/kotlin/com/margelo/nitro/perpdepthbar/perpdepthbarOnLoad.kt +35 -0
  78. package/lib/nitrogen/nitrogen/generated/android/kotlin/com/margelo/nitro/perpdepthbar/views/HybridPerpDepthBarsManager.kt +50 -0
  79. package/lib/nitrogen/nitrogen/generated/android/kotlin/com/margelo/nitro/perpdepthbar/views/HybridPerpDepthBarsStateUpdater.kt +23 -0
  80. package/lib/nitrogen/nitrogen/generated/android/kotlin/com/margelo/nitro/perpdepthbar/views/HybridPerpSideRatioManager.kt +50 -0
  81. package/lib/nitrogen/nitrogen/generated/android/kotlin/com/margelo/nitro/perpdepthbar/views/HybridPerpSideRatioStateUpdater.kt +23 -0
  82. package/lib/nitrogen/nitrogen/generated/android/perpdepthbar+autolinking.cmake +87 -0
  83. package/lib/nitrogen/nitrogen/generated/android/perpdepthbar+autolinking.gradle +27 -0
  84. package/lib/nitrogen/nitrogen/generated/android/perpdepthbarOnLoad.cpp +58 -0
  85. package/lib/nitrogen/nitrogen/generated/android/perpdepthbarOnLoad.hpp +25 -0
  86. package/lib/nitrogen/nitrogen/generated/ios/PerpDepthBar+autolinking.rb +60 -0
  87. package/lib/nitrogen/nitrogen/generated/ios/PerpDepthBar-Swift-Cxx-Bridge.cpp +50 -0
  88. package/lib/nitrogen/nitrogen/generated/ios/PerpDepthBar-Swift-Cxx-Bridge.hpp +69 -0
  89. package/lib/nitrogen/nitrogen/generated/ios/PerpDepthBar-Swift-Cxx-Umbrella.hpp +48 -0
  90. package/lib/nitrogen/nitrogen/generated/ios/PerpDepthBarAutolinking.mm +41 -0
  91. package/lib/nitrogen/nitrogen/generated/ios/PerpDepthBarAutolinking.swift +40 -0
  92. package/lib/nitrogen/nitrogen/generated/ios/c++/HybridPerpDepthBarsSpecSwift.cpp +11 -0
  93. package/lib/nitrogen/nitrogen/generated/ios/c++/HybridPerpDepthBarsSpecSwift.hpp +120 -0
  94. package/lib/nitrogen/nitrogen/generated/ios/c++/HybridPerpSideRatioSpecSwift.cpp +11 -0
  95. package/lib/nitrogen/nitrogen/generated/ios/c++/HybridPerpSideRatioSpecSwift.hpp +118 -0
  96. package/lib/nitrogen/nitrogen/generated/ios/c++/views/HybridPerpDepthBarsComponent.mm +131 -0
  97. package/lib/nitrogen/nitrogen/generated/ios/c++/views/HybridPerpSideRatioComponent.mm +131 -0
  98. package/lib/nitrogen/nitrogen/generated/ios/swift/HybridPerpDepthBarsSpec.swift +63 -0
  99. package/lib/nitrogen/nitrogen/generated/ios/swift/HybridPerpDepthBarsSpec_cxx.swift +223 -0
  100. package/lib/nitrogen/nitrogen/generated/ios/swift/HybridPerpSideRatioSpec.swift +63 -0
  101. package/lib/nitrogen/nitrogen/generated/ios/swift/HybridPerpSideRatioSpec_cxx.swift +217 -0
  102. package/lib/nitrogen/nitrogen/generated/shared/c++/HybridPerpDepthBarsSpec.cpp +36 -0
  103. package/lib/nitrogen/nitrogen/generated/shared/c++/HybridPerpDepthBarsSpec.hpp +78 -0
  104. package/lib/nitrogen/nitrogen/generated/shared/c++/HybridPerpSideRatioSpec.cpp +36 -0
  105. package/lib/nitrogen/nitrogen/generated/shared/c++/HybridPerpSideRatioSpec.hpp +77 -0
  106. package/lib/nitrogen/nitrogen/generated/shared/c++/views/HybridPerpDepthBarsComponent.cpp +171 -0
  107. package/lib/nitrogen/nitrogen/generated/shared/c++/views/HybridPerpDepthBarsComponent.hpp +116 -0
  108. package/lib/nitrogen/nitrogen/generated/shared/c++/views/HybridPerpSideRatioComponent.cpp +171 -0
  109. package/lib/nitrogen/nitrogen/generated/shared/c++/views/HybridPerpSideRatioComponent.hpp +115 -0
  110. package/lib/nitrogen/nitrogen/generated/shared/json/PerpDepthBarsConfig.json +17 -0
  111. package/lib/nitrogen/nitrogen/generated/shared/json/PerpSideRatioConfig.json +17 -0
  112. package/lib/typescript/package.json +1 -0
  113. package/lib/typescript/src/PerpDepthBars.nitro.d.ts +37 -0
  114. package/lib/typescript/src/PerpDepthBars.nitro.d.ts.map +1 -0
  115. package/lib/typescript/src/PerpSideRatio.nitro.d.ts +29 -0
  116. package/lib/typescript/src/PerpSideRatio.nitro.d.ts.map +1 -0
  117. package/lib/typescript/src/index.d.ts +6 -0
  118. package/lib/typescript/src/index.d.ts.map +1 -0
  119. package/nitro.json +21 -0
  120. package/nitrogen/generated/android/c++/JHybridPerpDepthBarsSpec.cpp +130 -0
  121. package/nitrogen/generated/android/c++/JHybridPerpDepthBarsSpec.hpp +80 -0
  122. package/nitrogen/generated/android/c++/JHybridPerpSideRatioSpec.cpp +119 -0
  123. package/nitrogen/generated/android/c++/JHybridPerpSideRatioSpec.hpp +80 -0
  124. package/nitrogen/generated/android/c++/views/JHybridPerpDepthBarsStateUpdater.cpp +84 -0
  125. package/nitrogen/generated/android/c++/views/JHybridPerpDepthBarsStateUpdater.hpp +49 -0
  126. package/nitrogen/generated/android/c++/views/JHybridPerpSideRatioStateUpdater.cpp +84 -0
  127. package/nitrogen/generated/android/c++/views/JHybridPerpSideRatioStateUpdater.hpp +49 -0
  128. package/nitrogen/generated/android/kotlin/com/margelo/nitro/perpdepthbar/HybridPerpDepthBarsSpec.kt +101 -0
  129. package/nitrogen/generated/android/kotlin/com/margelo/nitro/perpdepthbar/HybridPerpSideRatioSpec.kt +101 -0
  130. package/nitrogen/generated/android/kotlin/com/margelo/nitro/perpdepthbar/perpdepthbarOnLoad.kt +35 -0
  131. package/nitrogen/generated/android/kotlin/com/margelo/nitro/perpdepthbar/views/HybridPerpDepthBarsManager.kt +50 -0
  132. package/nitrogen/generated/android/kotlin/com/margelo/nitro/perpdepthbar/views/HybridPerpDepthBarsStateUpdater.kt +23 -0
  133. package/nitrogen/generated/android/kotlin/com/margelo/nitro/perpdepthbar/views/HybridPerpSideRatioManager.kt +50 -0
  134. package/nitrogen/generated/android/kotlin/com/margelo/nitro/perpdepthbar/views/HybridPerpSideRatioStateUpdater.kt +23 -0
  135. package/nitrogen/generated/android/perpdepthbar+autolinking.cmake +87 -0
  136. package/nitrogen/generated/android/perpdepthbar+autolinking.gradle +27 -0
  137. package/nitrogen/generated/android/perpdepthbarOnLoad.cpp +58 -0
  138. package/nitrogen/generated/android/perpdepthbarOnLoad.hpp +25 -0
  139. package/nitrogen/generated/ios/PerpDepthBar+autolinking.rb +60 -0
  140. package/nitrogen/generated/ios/PerpDepthBar-Swift-Cxx-Bridge.cpp +50 -0
  141. package/nitrogen/generated/ios/PerpDepthBar-Swift-Cxx-Bridge.hpp +69 -0
  142. package/nitrogen/generated/ios/PerpDepthBar-Swift-Cxx-Umbrella.hpp +48 -0
  143. package/nitrogen/generated/ios/PerpDepthBarAutolinking.mm +41 -0
  144. package/nitrogen/generated/ios/PerpDepthBarAutolinking.swift +40 -0
  145. package/nitrogen/generated/ios/c++/HybridPerpDepthBarsSpecSwift.cpp +11 -0
  146. package/nitrogen/generated/ios/c++/HybridPerpDepthBarsSpecSwift.hpp +120 -0
  147. package/nitrogen/generated/ios/c++/HybridPerpSideRatioSpecSwift.cpp +11 -0
  148. package/nitrogen/generated/ios/c++/HybridPerpSideRatioSpecSwift.hpp +118 -0
  149. package/nitrogen/generated/ios/c++/views/HybridPerpDepthBarsComponent.mm +131 -0
  150. package/nitrogen/generated/ios/c++/views/HybridPerpSideRatioComponent.mm +131 -0
  151. package/nitrogen/generated/ios/swift/HybridPerpDepthBarsSpec.swift +63 -0
  152. package/nitrogen/generated/ios/swift/HybridPerpDepthBarsSpec_cxx.swift +223 -0
  153. package/nitrogen/generated/ios/swift/HybridPerpSideRatioSpec.swift +63 -0
  154. package/nitrogen/generated/ios/swift/HybridPerpSideRatioSpec_cxx.swift +217 -0
  155. package/nitrogen/generated/shared/c++/HybridPerpDepthBarsSpec.cpp +36 -0
  156. package/nitrogen/generated/shared/c++/HybridPerpDepthBarsSpec.hpp +78 -0
  157. package/nitrogen/generated/shared/c++/HybridPerpSideRatioSpec.cpp +36 -0
  158. package/nitrogen/generated/shared/c++/HybridPerpSideRatioSpec.hpp +77 -0
  159. package/nitrogen/generated/shared/c++/views/HybridPerpDepthBarsComponent.cpp +171 -0
  160. package/nitrogen/generated/shared/c++/views/HybridPerpDepthBarsComponent.hpp +116 -0
  161. package/nitrogen/generated/shared/c++/views/HybridPerpSideRatioComponent.cpp +171 -0
  162. package/nitrogen/generated/shared/c++/views/HybridPerpSideRatioComponent.hpp +115 -0
  163. package/nitrogen/generated/shared/json/PerpDepthBarsConfig.json +17 -0
  164. package/nitrogen/generated/shared/json/PerpSideRatioConfig.json +17 -0
  165. package/package.json +170 -0
  166. package/src/PerpDepthBars.nitro.ts +42 -0
  167. package/src/PerpSideRatio.nitro.ts +34 -0
  168. package/src/index.tsx +30 -0
@@ -0,0 +1,148 @@
1
+ import Foundation
2
+ import UIKit
3
+
4
+ /// Renders an entire column of order-book depth bars for one side (asks/bids).
5
+ /// Each row is a CALayer whose horizontal `scaleX` fill is animated on the UI
6
+ /// thread, replacing N reanimated `DepthBar` instances.
7
+ final class HybridPerpDepthBars: HybridPerpDepthBarsSpec {
8
+
9
+ // MARK: - HybridView
10
+ var view: UIView = PerpLayoutView()
11
+
12
+ // MARK: - Per-row fill layers
13
+ private var barLayers: [CALayer] = []
14
+
15
+ // MARK: - State for animation decisions
16
+ private var lastPercents: [Double] = []
17
+ private var lastEpoch: Double = .nan
18
+ private var hasLaidOut = false
19
+
20
+ // MARK: - Props (required props -> non-optional in generated spec)
21
+ var percents: [Double] = [] { didSet { scheduleLayout() } }
22
+ var rowHeight: Double = 0 { didSet { scheduleLayout() } }
23
+ var rowMarginTop: Double = 0 { didSet { scheduleLayout() } }
24
+ var barInset: Double = 0 { didSet { scheduleLayout() } }
25
+ var origin: String = "left" { didSet { scheduleLayout() } }
26
+ var reducedMotion: Bool = false { didSet { scheduleLayout() } }
27
+ var epoch: Double = 0 { didSet { scheduleLayout() } }
28
+
29
+ var color: String = "" {
30
+ didSet {
31
+ cachedColor = PerpColorParser.parse(color).cgColor
32
+ applyColorToLayers()
33
+ }
34
+ }
35
+ private var cachedColor: CGColor = UIColor.clear.cgColor
36
+
37
+ // MARK: - Init
38
+ override init() {
39
+ super.init()
40
+ view.isUserInteractionEnabled = false // taps handled by RN overlay
41
+ view.clipsToBounds = true
42
+ if let layoutView = view as? PerpLayoutView {
43
+ layoutView.onLayout = { [weak self] in self?.performLayout() }
44
+ }
45
+ }
46
+
47
+ private func scheduleLayout() {
48
+ view.setNeedsLayout()
49
+ }
50
+
51
+ // MARK: - Layout + animation
52
+ private func performLayout() {
53
+ let bounds = view.bounds
54
+ guard bounds.width > 0 else { return }
55
+
56
+ let count = percents.count
57
+ syncLayerCount(count)
58
+
59
+ // Decide whether this update should animate or snap.
60
+ let epochChanged = epoch != lastEpoch
61
+ let countChanged = lastPercents.count != count
62
+ let snap = !hasLaidOut || reducedMotion || epochChanged || countChanged
63
+
64
+ let rowW = bounds.width
65
+ let h = CGFloat(rowHeight)
66
+ let inset = CGFloat(barInset)
67
+ let barH = max(h - inset * 2, 0)
68
+ let isRight = origin == "right"
69
+ let anchorX: CGFloat = isRight ? 1 : 0
70
+
71
+ CATransaction.begin()
72
+ CATransaction.setDisableActions(true) // suppress implicit anims for geometry
73
+
74
+ for i in 0..<count {
75
+ let layer = barLayers[i]
76
+ let rowTop = CGFloat(rowMarginTop) + CGFloat(i) * (h + CGFloat(rowMarginTop))
77
+ let rowCenterY = rowTop + h / 2
78
+
79
+ layer.anchorPoint = CGPoint(x: anchorX, y: 0.5)
80
+ layer.bounds = CGRect(x: 0, y: 0, width: rowW, height: barH)
81
+ layer.position = CGPoint(x: isRight ? rowW : 0, y: rowCenterY)
82
+ layer.backgroundColor = cachedColor
83
+
84
+ let target = clampScale(percents[i])
85
+ let changed = i >= lastPercents.count || lastPercents[i] != percents[i]
86
+
87
+ if snap || !changed {
88
+ layer.removeAnimation(forKey: "fill")
89
+ layer.transform = CATransform3DMakeScale(target, 1, 1)
90
+ } else {
91
+ animateScaleX(layer: layer, to: target)
92
+ }
93
+ }
94
+
95
+ CATransaction.commit()
96
+
97
+ lastPercents = percents
98
+ lastEpoch = epoch
99
+ hasLaidOut = true
100
+ }
101
+
102
+ private func animateScaleX(layer: CALayer, to target: CGFloat) {
103
+ // Continue from the on-screen (presentation) value to avoid snap-back when
104
+ // a new animation starts every tick (~10Hz).
105
+ let current: CGFloat
106
+ if let pres = layer.presentation() {
107
+ current = pres.value(forKeyPath: "transform.scale.x") as? CGFloat
108
+ ?? (layer.value(forKeyPath: "transform.scale.x") as? CGFloat ?? target)
109
+ } else {
110
+ current = layer.value(forKeyPath: "transform.scale.x") as? CGFloat ?? target
111
+ }
112
+
113
+ layer.transform = CATransform3DMakeScale(target, 1, 1) // model = final
114
+
115
+ let anim = CABasicAnimation(keyPath: "transform.scale.x")
116
+ anim.fromValue = current
117
+ anim.toValue = target
118
+ anim.duration = PerpTiming.depthBarDurationMs / 1000.0
119
+ anim.timingFunction = PerpTiming.easeOutCubic()
120
+ anim.isRemovedOnCompletion = true
121
+ layer.add(anim, forKey: "fill")
122
+ }
123
+
124
+ private func syncLayerCount(_ count: Int) {
125
+ if barLayers.count < count {
126
+ for _ in barLayers.count..<count {
127
+ let l = CALayer()
128
+ l.backgroundColor = cachedColor
129
+ view.layer.addSublayer(l)
130
+ barLayers.append(l)
131
+ }
132
+ } else if barLayers.count > count {
133
+ for l in barLayers[count...] { l.removeFromSuperlayer() }
134
+ barLayers.removeLast(barLayers.count - count)
135
+ }
136
+ }
137
+
138
+ private func applyColorToLayers() {
139
+ CATransaction.begin()
140
+ CATransaction.setDisableActions(true)
141
+ for l in barLayers { l.backgroundColor = cachedColor }
142
+ CATransaction.commit()
143
+ }
144
+
145
+ private func clampScale(_ percent: Double) -> CGFloat {
146
+ CGFloat(max(0, min(100, percent)) / 100.0)
147
+ }
148
+ }
@@ -0,0 +1,118 @@
1
+ import Foundation
2
+ import UIKit
3
+
4
+ /// Two horizontal segments whose widths animate to the bid/ask ratio.
5
+ final class HybridPerpSideRatio: HybridPerpSideRatioSpec {
6
+
7
+ // MARK: - HybridView
8
+ var view: UIView = PerpLayoutView()
9
+
10
+ private let bidLayer = CALayer()
11
+ private let askLayer = CALayer()
12
+ private var hasLaidOut = false
13
+
14
+ // MARK: - Props
15
+ var bidPercentage: Double = 50 { didSet { scheduleLayout() } }
16
+ var askPercentage: Double = 50 { didSet { scheduleLayout() } }
17
+ var segmentHeight: Double = 4 { didSet { scheduleLayout() } }
18
+ var cornerRadius: Double = 999 { didSet { scheduleLayout() } }
19
+ var gap: Double = 2 { didSet { scheduleLayout() } }
20
+ var reducedMotion: Bool = false { didSet { scheduleLayout() } }
21
+
22
+ var longColor: String = "" {
23
+ didSet {
24
+ bidLayer.backgroundColor = PerpColorParser.parse(longColor).cgColor
25
+ }
26
+ }
27
+ var shortColor: String = "" {
28
+ didSet {
29
+ askLayer.backgroundColor = PerpColorParser.parse(shortColor).cgColor
30
+ }
31
+ }
32
+
33
+ override init() {
34
+ super.init()
35
+ view.isUserInteractionEnabled = false
36
+ view.clipsToBounds = true
37
+ bidLayer.maskedCorners = [.layerMinXMinYCorner, .layerMinXMaxYCorner]
38
+ askLayer.maskedCorners = [.layerMaxXMinYCorner, .layerMaxXMaxYCorner]
39
+ view.layer.addSublayer(bidLayer)
40
+ view.layer.addSublayer(askLayer)
41
+ if let layoutView = view as? PerpLayoutView {
42
+ layoutView.onLayout = { [weak self] in self?.performLayout() }
43
+ }
44
+ }
45
+
46
+ private func scheduleLayout() {
47
+ view.setNeedsLayout()
48
+ }
49
+
50
+ private func performLayout() {
51
+ let bounds = view.bounds
52
+ guard bounds.width > 0 else { return }
53
+
54
+ let h = CGFloat(segmentHeight)
55
+ let y = (bounds.height - h) / 2
56
+ let g = CGFloat(gap)
57
+ let available = max(bounds.width - g, 0)
58
+
59
+ let bid = max(bidPercentage, 1)
60
+ let ask = max(askPercentage, 1)
61
+ let total = bid + ask
62
+ let bidW = available * CGFloat(bid / total)
63
+ let askW = available - bidW
64
+ let radius = CGFloat(cornerRadius)
65
+
66
+ let bidFrame = CGRect(x: 0, y: y, width: bidW, height: h)
67
+ let askFrame = CGRect(x: bidW + g, y: y, width: askW, height: h)
68
+
69
+ let snap = !hasLaidOut || reducedMotion
70
+
71
+ CATransaction.begin()
72
+ CATransaction.setDisableActions(true)
73
+ bidLayer.cornerRadius = min(radius, h / 2)
74
+ askLayer.cornerRadius = min(radius, h / 2)
75
+ CATransaction.commit()
76
+
77
+ if snap {
78
+ CATransaction.begin()
79
+ CATransaction.setDisableActions(true)
80
+ bidLayer.frame = bidFrame
81
+ askLayer.frame = askFrame
82
+ CATransaction.commit()
83
+ } else {
84
+ animateFrame(layer: bidLayer, to: bidFrame)
85
+ animateFrame(layer: askLayer, to: askFrame)
86
+ }
87
+ hasLaidOut = true
88
+ }
89
+
90
+ private func animateFrame(layer: CALayer, to frame: CGRect) {
91
+ let duration = PerpTiming.sideRatioDurationMs / 1000.0
92
+ let timing = PerpTiming.easeOutCubic()
93
+
94
+ let fromBounds = layer.presentation()?.bounds ?? layer.bounds
95
+ let fromPos = layer.presentation()?.position ?? layer.position
96
+
97
+ let newBounds = CGRect(x: 0, y: 0, width: frame.width, height: frame.height)
98
+ let newPos = CGPoint(x: frame.midX, y: frame.midY)
99
+
100
+ layer.bounds = newBounds
101
+ layer.position = newPos
102
+
103
+ let boundsAnim = CABasicAnimation(keyPath: "bounds")
104
+ boundsAnim.fromValue = NSValue(cgRect: fromBounds)
105
+ boundsAnim.toValue = NSValue(cgRect: newBounds)
106
+ boundsAnim.duration = duration
107
+ boundsAnim.timingFunction = timing
108
+
109
+ let posAnim = CABasicAnimation(keyPath: "position")
110
+ posAnim.fromValue = NSValue(cgPoint: fromPos)
111
+ posAnim.toValue = NSValue(cgPoint: newPos)
112
+ posAnim.duration = duration
113
+ posAnim.timingFunction = timing
114
+
115
+ layer.add(boundsAnim, forKey: "ratioBounds")
116
+ layer.add(posAnim, forKey: "ratioPos")
117
+ }
118
+ }
@@ -0,0 +1,92 @@
1
+ import Foundation
2
+ import UIKit
3
+
4
+ /// Parses a color string coming from JS. Supports:
5
+ /// - `#rgb`, `#rrggbb`, `#rrggbbaa`
6
+ /// - `rgb(r, g, b)` / `rgba(r, g, b, a)` where a is 0..1
7
+ /// Falls back to `fallback` on parse failure.
8
+ enum PerpColorParser {
9
+ static func parse(_ value: String?, fallback: UIColor = .clear) -> UIColor {
10
+ guard let raw = value?.trimmingCharacters(in: .whitespacesAndNewlines),
11
+ !raw.isEmpty else {
12
+ return fallback
13
+ }
14
+
15
+ if raw.hasPrefix("#") {
16
+ return parseHex(raw) ?? fallback
17
+ }
18
+ if raw.lowercased().hasPrefix("rgb") {
19
+ return parseRGB(raw) ?? fallback
20
+ }
21
+ return fallback
22
+ }
23
+
24
+ private static func parseHex(_ hex: String) -> UIColor? {
25
+ var s = hex
26
+ s.removeFirst() // '#'
27
+
28
+ // Expand shorthand #rgb -> #rrggbb
29
+ if s.count == 3 {
30
+ s = s.map { "\($0)\($0)" }.joined()
31
+ }
32
+
33
+ guard s.count == 6 || s.count == 8 else { return nil }
34
+ var int: UInt64 = 0
35
+ guard Scanner(string: s).scanHexInt64(&int) else { return nil }
36
+
37
+ let r, g, b, a: CGFloat
38
+ if s.count == 8 {
39
+ r = CGFloat((int >> 24) & 0xFF) / 255.0
40
+ g = CGFloat((int >> 16) & 0xFF) / 255.0
41
+ b = CGFloat((int >> 8) & 0xFF) / 255.0
42
+ a = CGFloat(int & 0xFF) / 255.0
43
+ } else {
44
+ r = CGFloat((int >> 16) & 0xFF) / 255.0
45
+ g = CGFloat((int >> 8) & 0xFF) / 255.0
46
+ b = CGFloat(int & 0xFF) / 255.0
47
+ a = 1.0
48
+ }
49
+ return UIColor(red: r, green: g, blue: b, alpha: a)
50
+ }
51
+
52
+ private static func parseRGB(_ value: String) -> UIColor? {
53
+ guard let open = value.firstIndex(of: "("),
54
+ let close = value.firstIndex(of: ")") else { return nil }
55
+ let inner = value[value.index(after: open)..<close]
56
+ let parts = inner.split(separator: ",").map {
57
+ $0.trimmingCharacters(in: .whitespaces)
58
+ }
59
+ guard parts.count >= 3,
60
+ let r = Double(parts[0]),
61
+ let g = Double(parts[1]),
62
+ let b = Double(parts[2]) else { return nil }
63
+ let a = parts.count >= 4 ? (Double(parts[3]) ?? 1.0) : 1.0
64
+ return UIColor(
65
+ red: CGFloat(r) / 255.0,
66
+ green: CGFloat(g) / 255.0,
67
+ blue: CGFloat(b) / 255.0,
68
+ alpha: CGFloat(a)
69
+ )
70
+ }
71
+ }
72
+
73
+ /// Matches the JS `cubic-bezier(0.33, 1, 0.68, 1)` (Easing.out(cubic)) curve.
74
+ enum PerpTiming {
75
+ static let depthBarDurationMs: Double = 260
76
+ static let sideRatioDurationMs: Double = 300
77
+
78
+ static func easeOutCubic() -> CAMediaTimingFunction {
79
+ CAMediaTimingFunction(controlPoints: 0.33, 1, 0.68, 1)
80
+ }
81
+ }
82
+
83
+ /// UIView subclass that forwards `layoutSubviews` to a callback so a Nitro
84
+ /// HybridView can re-lay-out its CALayers when bounds change.
85
+ final class PerpLayoutView: UIView {
86
+ var onLayout: (() -> Void)?
87
+
88
+ override func layoutSubviews() {
89
+ super.layoutSubviews()
90
+ onLayout?()
91
+ }
92
+ }
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+
3
+ export {};
4
+ //# sourceMappingURL=PerpDepthBars.nitro.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":[],"sourceRoot":"../../src","sources":["PerpDepthBars.nitro.ts"],"mappings":"","ignoreList":[]}
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+
3
+ export {};
4
+ //# sourceMappingURL=PerpSideRatio.nitro.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":[],"sourceRoot":"../../src","sources":["PerpSideRatio.nitro.ts"],"mappings":"","ignoreList":[]}
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+
3
+ import { getHostComponent } from 'react-native-nitro-modules';
4
+ const PerpDepthBarsConfig = require('../nitrogen/generated/shared/json/PerpDepthBarsConfig.json');
5
+ const PerpSideRatioConfig = require('../nitrogen/generated/shared/json/PerpSideRatioConfig.json');
6
+ export const PerpDepthBarsView = getHostComponent('PerpDepthBars', () => PerpDepthBarsConfig);
7
+ export const PerpSideRatioView = getHostComponent('PerpSideRatio', () => PerpSideRatioConfig);
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["getHostComponent","PerpDepthBarsConfig","require","PerpSideRatioConfig","PerpDepthBarsView","PerpSideRatioView"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA,SAASA,gBAAgB,QAAQ,4BAA4B;AAW7D,MAAMC,mBAAmB,GAAGC,OAAO,CAAC,4DAA4D,CAAC;AACjG,MAAMC,mBAAmB,GAAGD,OAAO,CAAC,4DAA4D,CAAC;AASjG,OAAO,MAAME,iBAAiB,GAAGJ,gBAAgB,CAG/C,eAAe,EAAE,MAAMC,mBAAmB,CAAC;AAE7C,OAAO,MAAMI,iBAAiB,GAAGL,gBAAgB,CAG/C,eAAe,EAAE,MAAMG,mBAAmB,CAAC","ignoreList":[]}
@@ -0,0 +1 @@
1
+ {"type":"module"}
@@ -0,0 +1,130 @@
1
+ ///
2
+ /// JHybridPerpDepthBarsSpec.cpp
3
+ /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4
+ /// https://github.com/mrousavy/nitro
5
+ /// Copyright © 2026 Marc Rousavy @ Margelo
6
+ ///
7
+
8
+ #include "JHybridPerpDepthBarsSpec.hpp"
9
+
10
+
11
+
12
+ #include <vector>
13
+ #include <string>
14
+
15
+ namespace margelo::nitro::perpdepthbar {
16
+
17
+ jni::local_ref<JHybridPerpDepthBarsSpec::jhybriddata> JHybridPerpDepthBarsSpec::initHybrid(jni::alias_ref<jhybridobject> jThis) {
18
+ return makeCxxInstance(jThis);
19
+ }
20
+
21
+ void JHybridPerpDepthBarsSpec::registerNatives() {
22
+ registerHybrid({
23
+ makeNativeMethod("initHybrid", JHybridPerpDepthBarsSpec::initHybrid),
24
+ });
25
+ }
26
+
27
+ size_t JHybridPerpDepthBarsSpec::getExternalMemorySize() noexcept {
28
+ static const auto method = javaClassStatic()->getMethod<jlong()>("getMemorySize");
29
+ return method(_javaPart);
30
+ }
31
+
32
+ void JHybridPerpDepthBarsSpec::dispose() noexcept {
33
+ static const auto method = javaClassStatic()->getMethod<void()>("dispose");
34
+ method(_javaPart);
35
+ }
36
+
37
+ std::string JHybridPerpDepthBarsSpec::toString() {
38
+ static const auto method = javaClassStatic()->getMethod<jni::JString()>("toString");
39
+ auto javaString = method(_javaPart);
40
+ return javaString->toStdString();
41
+ }
42
+
43
+ // Properties
44
+ std::vector<double> JHybridPerpDepthBarsSpec::getPercents() {
45
+ static const auto method = javaClassStatic()->getMethod<jni::local_ref<jni::JArrayDouble>()>("getPercents");
46
+ auto __result = method(_javaPart);
47
+ return [&]() {
48
+ size_t __size = __result->size();
49
+ std::vector<double> __vector(__size);
50
+ __result->getRegion(0, __size, __vector.data());
51
+ return __vector;
52
+ }();
53
+ }
54
+ void JHybridPerpDepthBarsSpec::setPercents(const std::vector<double>& percents) {
55
+ static const auto method = javaClassStatic()->getMethod<void(jni::alias_ref<jni::JArrayDouble> /* percents */)>("setPercents");
56
+ method(_javaPart, [&]() {
57
+ size_t __size = percents.size();
58
+ jni::local_ref<jni::JArrayDouble> __array = jni::JArrayDouble::newArray(__size);
59
+ __array->setRegion(0, __size, percents.data());
60
+ return __array;
61
+ }());
62
+ }
63
+ double JHybridPerpDepthBarsSpec::getRowHeight() {
64
+ static const auto method = javaClassStatic()->getMethod<double()>("getRowHeight");
65
+ auto __result = method(_javaPart);
66
+ return __result;
67
+ }
68
+ void JHybridPerpDepthBarsSpec::setRowHeight(double rowHeight) {
69
+ static const auto method = javaClassStatic()->getMethod<void(double /* rowHeight */)>("setRowHeight");
70
+ method(_javaPart, rowHeight);
71
+ }
72
+ double JHybridPerpDepthBarsSpec::getRowMarginTop() {
73
+ static const auto method = javaClassStatic()->getMethod<double()>("getRowMarginTop");
74
+ auto __result = method(_javaPart);
75
+ return __result;
76
+ }
77
+ void JHybridPerpDepthBarsSpec::setRowMarginTop(double rowMarginTop) {
78
+ static const auto method = javaClassStatic()->getMethod<void(double /* rowMarginTop */)>("setRowMarginTop");
79
+ method(_javaPart, rowMarginTop);
80
+ }
81
+ double JHybridPerpDepthBarsSpec::getBarInset() {
82
+ static const auto method = javaClassStatic()->getMethod<double()>("getBarInset");
83
+ auto __result = method(_javaPart);
84
+ return __result;
85
+ }
86
+ void JHybridPerpDepthBarsSpec::setBarInset(double barInset) {
87
+ static const auto method = javaClassStatic()->getMethod<void(double /* barInset */)>("setBarInset");
88
+ method(_javaPart, barInset);
89
+ }
90
+ std::string JHybridPerpDepthBarsSpec::getColor() {
91
+ static const auto method = javaClassStatic()->getMethod<jni::local_ref<jni::JString>()>("getColor");
92
+ auto __result = method(_javaPart);
93
+ return __result->toStdString();
94
+ }
95
+ void JHybridPerpDepthBarsSpec::setColor(const std::string& color) {
96
+ static const auto method = javaClassStatic()->getMethod<void(jni::alias_ref<jni::JString> /* color */)>("setColor");
97
+ method(_javaPart, jni::make_jstring(color));
98
+ }
99
+ std::string JHybridPerpDepthBarsSpec::getOrigin() {
100
+ static const auto method = javaClassStatic()->getMethod<jni::local_ref<jni::JString>()>("getOrigin");
101
+ auto __result = method(_javaPart);
102
+ return __result->toStdString();
103
+ }
104
+ void JHybridPerpDepthBarsSpec::setOrigin(const std::string& origin) {
105
+ static const auto method = javaClassStatic()->getMethod<void(jni::alias_ref<jni::JString> /* origin */)>("setOrigin");
106
+ method(_javaPart, jni::make_jstring(origin));
107
+ }
108
+ bool JHybridPerpDepthBarsSpec::getReducedMotion() {
109
+ static const auto method = javaClassStatic()->getMethod<jboolean()>("getReducedMotion");
110
+ auto __result = method(_javaPart);
111
+ return static_cast<bool>(__result);
112
+ }
113
+ void JHybridPerpDepthBarsSpec::setReducedMotion(bool reducedMotion) {
114
+ static const auto method = javaClassStatic()->getMethod<void(jboolean /* reducedMotion */)>("setReducedMotion");
115
+ method(_javaPart, reducedMotion);
116
+ }
117
+ double JHybridPerpDepthBarsSpec::getEpoch() {
118
+ static const auto method = javaClassStatic()->getMethod<double()>("getEpoch");
119
+ auto __result = method(_javaPart);
120
+ return __result;
121
+ }
122
+ void JHybridPerpDepthBarsSpec::setEpoch(double epoch) {
123
+ static const auto method = javaClassStatic()->getMethod<void(double /* epoch */)>("setEpoch");
124
+ method(_javaPart, epoch);
125
+ }
126
+
127
+ // Methods
128
+
129
+
130
+ } // namespace margelo::nitro::perpdepthbar
@@ -0,0 +1,80 @@
1
+ ///
2
+ /// HybridPerpDepthBarsSpec.hpp
3
+ /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4
+ /// https://github.com/mrousavy/nitro
5
+ /// Copyright © 2026 Marc Rousavy @ Margelo
6
+ ///
7
+
8
+ #pragma once
9
+
10
+ #include <NitroModules/JHybridObject.hpp>
11
+ #include <fbjni/fbjni.h>
12
+ #include "HybridPerpDepthBarsSpec.hpp"
13
+
14
+
15
+
16
+
17
+ namespace margelo::nitro::perpdepthbar {
18
+
19
+ using namespace facebook;
20
+
21
+ class JHybridPerpDepthBarsSpec: public jni::HybridClass<JHybridPerpDepthBarsSpec, JHybridObject>,
22
+ public virtual HybridPerpDepthBarsSpec {
23
+ public:
24
+ static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/perpdepthbar/HybridPerpDepthBarsSpec;";
25
+ static jni::local_ref<jhybriddata> initHybrid(jni::alias_ref<jhybridobject> jThis);
26
+ static void registerNatives();
27
+
28
+ protected:
29
+ // C++ constructor (called from Java via `initHybrid()`)
30
+ explicit JHybridPerpDepthBarsSpec(jni::alias_ref<jhybridobject> jThis) :
31
+ HybridObject(HybridPerpDepthBarsSpec::TAG),
32
+ HybridBase(jThis),
33
+ _javaPart(jni::make_global(jThis)) {}
34
+
35
+ public:
36
+ ~JHybridPerpDepthBarsSpec() override {
37
+ // Hermes GC can destroy JS objects on a non-JNI Thread.
38
+ jni::ThreadScope::WithClassLoader([&] { _javaPart.reset(); });
39
+ }
40
+
41
+ public:
42
+ size_t getExternalMemorySize() noexcept override;
43
+ void dispose() noexcept override;
44
+ std::string toString() override;
45
+
46
+ public:
47
+ inline const jni::global_ref<JHybridPerpDepthBarsSpec::javaobject>& getJavaPart() const noexcept {
48
+ return _javaPart;
49
+ }
50
+
51
+ public:
52
+ // Properties
53
+ std::vector<double> getPercents() override;
54
+ void setPercents(const std::vector<double>& percents) override;
55
+ double getRowHeight() override;
56
+ void setRowHeight(double rowHeight) override;
57
+ double getRowMarginTop() override;
58
+ void setRowMarginTop(double rowMarginTop) override;
59
+ double getBarInset() override;
60
+ void setBarInset(double barInset) override;
61
+ std::string getColor() override;
62
+ void setColor(const std::string& color) override;
63
+ std::string getOrigin() override;
64
+ void setOrigin(const std::string& origin) override;
65
+ bool getReducedMotion() override;
66
+ void setReducedMotion(bool reducedMotion) override;
67
+ double getEpoch() override;
68
+ void setEpoch(double epoch) override;
69
+
70
+ public:
71
+ // Methods
72
+
73
+
74
+ private:
75
+ friend HybridBase;
76
+ using HybridBase::HybridBase;
77
+ jni::global_ref<JHybridPerpDepthBarsSpec::javaobject> _javaPart;
78
+ };
79
+
80
+ } // namespace margelo::nitro::perpdepthbar