@onekeyfe/react-native-segment-slider 6.7.0-alpha.396 → 6.7.0-alpha.398
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.
- package/README.md +2 -0
- package/android/src/main/java/com/margelo/nitro/segmentslider/HybridSegmentSlider.kt +10 -8
- package/ios/HybridSegmentSlider.swift +11 -7
- package/lib/typescript/src/SegmentSlider.nitro.d.ts +5 -4
- package/lib/typescript/src/SegmentSlider.nitro.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/SegmentSlider.nitro.ts +9 -5
package/README.md
CHANGED
|
@@ -13,18 +13,20 @@ import com.facebook.react.uimanager.ThemedReactContext
|
|
|
13
13
|
/**
|
|
14
14
|
* Native segmented slider. Draws the track, fill bar, segment marks, thumb and
|
|
15
15
|
* value bubble in [View.onDraw] and handles the drag in [View.onTouchEvent], so
|
|
16
|
-
* a drag never crosses the JS bridge per frame.
|
|
17
|
-
*
|
|
16
|
+
* a drag never crosses the JS bridge per frame. Follows the web variant's
|
|
17
|
+
* semantics, with extra endpoint space for the enlarged drag thumb.
|
|
18
18
|
*/
|
|
19
19
|
@DoNotStrip
|
|
20
20
|
class HybridSegmentSlider(val context: ThemedReactContext) : HybridSegmentSliderSpec() {
|
|
21
21
|
|
|
22
22
|
private val density = context.resources.displayMetrics.density
|
|
23
23
|
|
|
24
|
-
// Geometry (dp)
|
|
24
|
+
// Geometry (dp).
|
|
25
25
|
private val thumbSizePx = 16f * density
|
|
26
|
+
private val activeThumbScale = 1.15f
|
|
26
27
|
private val markSizePx = 10f * density
|
|
27
|
-
|
|
28
|
+
// Keep the enlarged thumb and node halo inside the horizontal view bounds.
|
|
29
|
+
private val insetPx = 12f * density
|
|
28
30
|
private val haloRingPx = 4f * density // translucent halo width beyond each mark
|
|
29
31
|
|
|
30
32
|
// Paints.
|
|
@@ -95,7 +97,7 @@ class HybridSegmentSlider(val context: ThemedReactContext) : HybridSegmentSlider
|
|
|
95
97
|
touchStartX = event.x
|
|
96
98
|
lastTouchX = event.x
|
|
97
99
|
onSlideStart?.invoke()
|
|
98
|
-
animateThumbScale(
|
|
100
|
+
animateThumbScale(activeThumbScale)
|
|
99
101
|
// Tap-snap mode: defer the value commit until we know this is a tap or
|
|
100
102
|
// a drag, so a tap never jumps to the raw touch point first.
|
|
101
103
|
if (!snapTapsActive) commitDragValue(valueFromX(event.x))
|
|
@@ -255,7 +257,7 @@ class HybridSegmentSlider(val context: ThemedReactContext) : HybridSegmentSlider
|
|
|
255
257
|
}
|
|
256
258
|
|
|
257
259
|
// MARK: - Geometry helpers
|
|
258
|
-
private val trackWidth: Float get() = (view.width -
|
|
260
|
+
private val trackWidth: Float get() = (view.width - insetPx * 2f).coerceAtLeast(0f)
|
|
259
261
|
private val rangeSafe: Double get() = (max - min).let { if (it == 0.0) 1.0 else it }
|
|
260
262
|
private val markCount: Int get() = if (segments >= 1) segments.toInt() + 1 else 0
|
|
261
263
|
|
|
@@ -418,12 +420,12 @@ class HybridSegmentSlider(val context: ThemedReactContext) : HybridSegmentSlider
|
|
|
418
420
|
val padH = 8f * density
|
|
419
421
|
val bw = textW + padH * 2
|
|
420
422
|
val bh = 20f * density
|
|
421
|
-
val left = thumbX - bw / 2f
|
|
423
|
+
val left = (thumbX - bw / 2f).coerceIn(0f, (w - bw).coerceAtLeast(0f))
|
|
422
424
|
val top = trackTop - 8f * density - bh
|
|
423
425
|
rect.set(left, top, left + bw, top + bh)
|
|
424
426
|
canvas.drawRoundRect(rect, 4f * density, 4f * density, bubblePaint)
|
|
425
427
|
val baseline = top + bh / 2f - (bubbleTextPaint.descent() + bubbleTextPaint.ascent()) / 2f
|
|
426
|
-
canvas.drawText(text,
|
|
428
|
+
canvas.drawText(text, left + bw / 2f, baseline, bubbleTextPaint)
|
|
427
429
|
}
|
|
428
430
|
}
|
|
429
431
|
|
|
@@ -3,15 +3,17 @@ import UIKit
|
|
|
3
3
|
|
|
4
4
|
/// Native segmented slider. Renders the track, fill bar, segment marks, thumb
|
|
5
5
|
/// and value bubble as CALayers and handles the drag gesture itself, so a drag
|
|
6
|
-
/// never crosses the JS bridge per frame.
|
|
7
|
-
///
|
|
6
|
+
/// never crosses the JS bridge per frame. Follows the web variant's semantics,
|
|
7
|
+
/// with extra endpoint space for the enlarged iOS drag thumb.
|
|
8
8
|
final class HybridSegmentSlider: HybridSegmentSliderSpec {
|
|
9
9
|
|
|
10
|
-
// MARK: - Geometry (points)
|
|
10
|
+
// MARK: - Geometry (points)
|
|
11
11
|
private let thumbSize: CGFloat = 16
|
|
12
|
+
private let activeThumbScale: CGFloat = 1.15
|
|
12
13
|
private let markSize: CGFloat = 10
|
|
13
14
|
private let haloRing: CGFloat = 4 // translucent halo width beyond each mark
|
|
14
|
-
|
|
15
|
+
// Include the enlarged thumb radius and room for its shadow at either end.
|
|
16
|
+
private var inset: CGFloat { ceil(thumbSize * activeThumbScale / 2) + 2 }
|
|
15
17
|
|
|
16
18
|
// MARK: - HybridView
|
|
17
19
|
var view: UIView = SegmentSliderUIView()
|
|
@@ -173,7 +175,7 @@ final class HybridSegmentSlider: HybridSegmentSliderSpec {
|
|
|
173
175
|
}
|
|
174
176
|
|
|
175
177
|
// MARK: - Geometry helpers
|
|
176
|
-
private var trackWidth: CGFloat { Swift.max(view.bounds.width -
|
|
178
|
+
private var trackWidth: CGFloat { Swift.max(view.bounds.width - inset * 2, 0) }
|
|
177
179
|
private var trackLeft: CGFloat { inset }
|
|
178
180
|
private var range: Double { let r = max - min; return r == 0 ? 1 : r }
|
|
179
181
|
private var markCount: Int { segments >= 1 ? Int(segments) + 1 : 0 }
|
|
@@ -317,7 +319,9 @@ final class HybridSegmentSlider: HybridSegmentSliderSpec {
|
|
|
317
319
|
let bw = ceil(textW) + padH * 2
|
|
318
320
|
let bh: CGFloat = 20
|
|
319
321
|
let by = trackTop - 8 - bh
|
|
320
|
-
|
|
322
|
+
// Keep endpoint bubbles inside horizontally clipping ancestors.
|
|
323
|
+
let bx = Swift.max(bounds.minX, Swift.min(thumbX - bw / 2, bounds.maxX - bw))
|
|
324
|
+
bubbleLayer.frame = CGRect(x: bx, y: by, width: bw, height: bh)
|
|
321
325
|
bubbleTextLayer.frame = CGRect(x: 0, y: 2, width: bw, height: 16)
|
|
322
326
|
}
|
|
323
327
|
|
|
@@ -385,7 +389,7 @@ final class HybridSegmentSlider: HybridSegmentSliderSpec {
|
|
|
385
389
|
touchStartTime = CACurrentMediaTime()
|
|
386
390
|
haptic.prepare()
|
|
387
391
|
onSlideStart?()
|
|
388
|
-
animateThumbScale(
|
|
392
|
+
animateThumbScale(activeThumbScale)
|
|
389
393
|
setBubbleVisible(true)
|
|
390
394
|
// Tap-snap mode: defer any value change until we know this is a tap or a
|
|
391
395
|
// drag, so a tap never jumps to the raw touch point first.
|
|
@@ -8,12 +8,13 @@ import type { HybridView, HybridViewMethods, HybridViewProps } from 'react-nativ
|
|
|
8
8
|
* (`packages/components/src/composite/SegmentSlider/index.tsx`) which avoids
|
|
9
9
|
* React state per frame by mutating the DOM imperatively.
|
|
10
10
|
*
|
|
11
|
-
* Geometry contract (points)
|
|
11
|
+
* Geometry contract (points):
|
|
12
12
|
* THUMB_SIZE = 16, MARK_SIZE = 10, hit/container height = 24
|
|
13
|
-
*
|
|
13
|
+
* END_INSET = 12 on iOS and Android (room for the enlarged thumb and halo)
|
|
14
|
+
* usable track width W' = max(W - 2 * END_INSET, 0)
|
|
14
15
|
* pct = (clamp(value,min,max) - min) / (max - min)
|
|
15
|
-
* thumb x =
|
|
16
|
-
* mark i x =
|
|
16
|
+
* thumb x = END_INSET + pct * W'
|
|
17
|
+
* mark i x = END_INSET + (i / segments) * W' (i in 0..segments)
|
|
17
18
|
*
|
|
18
19
|
* Colors are resolved from the Tamagui theme in the JS wrapper and passed in as
|
|
19
20
|
* hex / rgba() strings so the native side never depends on the theme system.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SegmentSlider.nitro.d.ts","sourceRoot":"","sources":["../../../src/SegmentSlider.nitro.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,EACV,iBAAiB,EACjB,eAAe,EAChB,MAAM,4BAA4B,CAAC;AAEpC
|
|
1
|
+
{"version":3,"file":"SegmentSlider.nitro.d.ts","sourceRoot":"","sources":["../../../src/SegmentSlider.nitro.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,EACV,iBAAiB,EACjB,eAAe,EAChB,MAAM,4BAA4B,CAAC;AAEpC;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,WAAW,kBAAmB,SAAQ,eAAe;IACzD;;;;;;;;OAQG;IACH,YAAY,EAAE,MAAM,CAAC;IACrB,4CAA4C;IAC5C,GAAG,EAAE,MAAM,CAAC;IACZ,qBAAqB;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,4EAA4E;IAC5E,QAAQ,EAAE,MAAM,CAAC;IACjB,8CAA8C;IAC9C,YAAY,EAAE,MAAM,CAAC;IACrB,0DAA0D;IAC1D,QAAQ,EAAE,OAAO,CAAC;IAClB,6EAA6E;IAC7E,UAAU,EAAE,OAAO,CAAC;IACpB,4EAA4E;IAC5E,YAAY,EAAE,OAAO,CAAC;IACtB;;;;;OAKG;IACH,gBAAgB,EAAE,OAAO,CAAC;IAG1B,mDAAmD;IACnD,SAAS,EAAE,MAAM,CAAC;IAClB,iDAAiD;IACjD,UAAU,EAAE,MAAM,CAAC;IACnB,uCAAuC;IACvC,UAAU,EAAE,MAAM,CAAC;IACnB,mDAAmD;IACnD,gBAAgB,EAAE,MAAM,CAAC;IACzB,6DAA6D;IAC7D,eAAe,EAAE,MAAM,CAAC;IACxB,+CAA+C;IAC/C,iBAAiB,EAAE,MAAM,CAAC;IAC1B,uDAAuD;IACvD,eAAe,EAAE,MAAM,CAAC;IACxB,qDAAqD;IACrD,WAAW,EAAE,MAAM,CAAC;IACpB,wCAAwC;IACxC,eAAe,EAAE,MAAM,CAAC;IAExB,oEAAoE;IACpE,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,yCAAyC;IACzC,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,uCAAuC;IACvC,eAAe,CAAC,EAAE,MAAM,IAAI,CAAC;CAC9B;AAED,MAAM,WAAW,oBAAqB,SAAQ,iBAAiB;IAC7D;;;;;;OAMG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED,MAAM,MAAM,aAAa,GAAG,UAAU,CACpC,kBAAkB,EAClB,oBAAoB,CACrB,CAAC"}
|
package/package.json
CHANGED
|
@@ -13,12 +13,13 @@ import type {
|
|
|
13
13
|
* (`packages/components/src/composite/SegmentSlider/index.tsx`) which avoids
|
|
14
14
|
* React state per frame by mutating the DOM imperatively.
|
|
15
15
|
*
|
|
16
|
-
* Geometry contract (points)
|
|
16
|
+
* Geometry contract (points):
|
|
17
17
|
* THUMB_SIZE = 16, MARK_SIZE = 10, hit/container height = 24
|
|
18
|
-
*
|
|
18
|
+
* END_INSET = 12 on iOS and Android (room for the enlarged thumb and halo)
|
|
19
|
+
* usable track width W' = max(W - 2 * END_INSET, 0)
|
|
19
20
|
* pct = (clamp(value,min,max) - min) / (max - min)
|
|
20
|
-
* thumb x =
|
|
21
|
-
* mark i x =
|
|
21
|
+
* thumb x = END_INSET + pct * W'
|
|
22
|
+
* mark i x = END_INSET + (i / segments) * W' (i in 0..segments)
|
|
22
23
|
*
|
|
23
24
|
* Colors are resolved from the Tamagui theme in the JS wrapper and passed in as
|
|
24
25
|
* hex / rgba() strings so the native side never depends on the theme system.
|
|
@@ -95,4 +96,7 @@ export interface SegmentSliderMethods extends HybridViewMethods {
|
|
|
95
96
|
setValue(value: number): void;
|
|
96
97
|
}
|
|
97
98
|
|
|
98
|
-
export type SegmentSlider = HybridView<
|
|
99
|
+
export type SegmentSlider = HybridView<
|
|
100
|
+
SegmentSliderProps,
|
|
101
|
+
SegmentSliderMethods
|
|
102
|
+
>;
|