react-native-platform-components 0.8.5 → 0.8.7
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/android/src/main/java/com/platformcomponents/PCSelectionMenuView.kt +32 -8
- package/ios/PCDatePickerView.swift +1 -1
- package/ios/PCLiquidGlass.mm +2 -1
- package/ios/PCSelectionMenu.mm +8 -4
- package/ios/PCSelectionMenu.swift +86 -115
- package/lib/commonjs/SelectionMenu.js +6 -1
- package/lib/commonjs/SelectionMenu.js.map +1 -1
- package/lib/module/SelectionMenu.js +6 -1
- package/lib/module/SelectionMenu.js.map +1 -1
- package/lib/typescript/commonjs/src/SelectionMenu.d.ts.map +1 -1
- package/lib/typescript/module/src/SelectionMenu.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/SelectionMenu.tsx +9 -1
|
@@ -178,16 +178,23 @@ class PCSelectionMenuView(context: Context) : FrameLayout(context), ReactScrollV
|
|
|
178
178
|
val inlineWidget: View? = inlineLayout ?: inlineSpinner
|
|
179
179
|
if (inlineWidget == null) return
|
|
180
180
|
|
|
181
|
-
|
|
182
|
-
|
|
181
|
+
val density = resources.displayMetrics.density
|
|
182
|
+
|
|
183
|
+
// Use AT_MOST with a large upper bound rather than UNSPECIFIED.
|
|
184
|
+
// TextInputLayout (and other composite views) can return incorrect
|
|
185
|
+
// intrinsic widths with UNSPECIFIED because their children don't
|
|
186
|
+
// handle that mode reliably. AT_MOST mirrors normal layout behavior.
|
|
187
|
+
val maxPx = (10000 * density).toInt()
|
|
188
|
+
val widthSpec = MeasureSpec.makeMeasureSpec(maxPx, MeasureSpec.AT_MOST)
|
|
183
189
|
val heightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)
|
|
184
190
|
inlineWidget.measure(widthSpec, heightSpec)
|
|
191
|
+
val intrinsicWidthPx = inlineWidget.measuredWidth
|
|
192
|
+
val intrinsicHeightPx = inlineWidget.measuredHeight
|
|
185
193
|
|
|
186
|
-
val widthDp = PixelUtil.toDIPFromPixel(
|
|
187
|
-
val
|
|
188
|
-
val rawHeightDp = PixelUtil.toDIPFromPixel(rawHeightPx.toFloat())
|
|
194
|
+
val widthDp = PixelUtil.toDIPFromPixel(intrinsicWidthPx.toFloat())
|
|
195
|
+
val rawHeightDp = PixelUtil.toDIPFromPixel(intrinsicHeightPx.toFloat())
|
|
189
196
|
|
|
190
|
-
Log.d(TAG, "updateFrameSizeState: widget=${inlineWidget.javaClass.simpleName},
|
|
197
|
+
Log.d(TAG, "updateFrameSizeState: widget=${inlineWidget.javaClass.simpleName}, intrinsicWidthPx=$intrinsicWidthPx, widthDp=$widthDp, intrinsicHeightPx=$intrinsicHeightPx, rawHeightDp=$rawHeightDp, minimumHeight=$minimumHeight, density=$density")
|
|
191
198
|
|
|
192
199
|
// Only update if changed
|
|
193
200
|
if (widthDp != lastReportedWidth || rawHeightDp != lastReportedHeight) {
|
|
@@ -242,6 +249,11 @@ class PCSelectionMenuView(context: Context) : FrameLayout(context), ReactScrollV
|
|
|
242
249
|
placeholder = value
|
|
243
250
|
inlineLayout?.hint = placeholder
|
|
244
251
|
// Spinner doesn't support placeholder
|
|
252
|
+
|
|
253
|
+
// Re-measure after placeholder change
|
|
254
|
+
if (anchorMode == "inline") {
|
|
255
|
+
post { updateFrameSizeState() }
|
|
256
|
+
}
|
|
245
257
|
}
|
|
246
258
|
|
|
247
259
|
fun applyAnchorMode(value: String?) {
|
|
@@ -311,6 +323,8 @@ class PCSelectionMenuView(context: Context) : FrameLayout(context), ReactScrollV
|
|
|
311
323
|
headlessDismissProgrammatic = false
|
|
312
324
|
headlessDismissAfterSelect = false
|
|
313
325
|
hasRequestedLayoutUpdate = false
|
|
326
|
+
lastReportedWidth = 0f
|
|
327
|
+
lastReportedHeight = 0f
|
|
314
328
|
|
|
315
329
|
// Headless should be invisible but anchorable.
|
|
316
330
|
alpha = if (anchorMode == "headless") 0.01f else 1f
|
|
@@ -344,7 +358,7 @@ class PCSelectionMenuView(context: Context) : FrameLayout(context), ReactScrollV
|
|
|
344
358
|
// Must set box background mode BEFORE setting endIconMode to avoid IllegalStateException
|
|
345
359
|
val til = TextInputLayout(context).apply {
|
|
346
360
|
layoutParams = FrameLayout.LayoutParams(
|
|
347
|
-
FrameLayout.LayoutParams.
|
|
361
|
+
FrameLayout.LayoutParams.WRAP_CONTENT,
|
|
348
362
|
FrameLayout.LayoutParams.WRAP_CONTENT
|
|
349
363
|
)
|
|
350
364
|
// Set box background mode first - required for END_ICON_DROPDOWN_MENU
|
|
@@ -463,7 +477,7 @@ class PCSelectionMenuView(context: Context) : FrameLayout(context), ReactScrollV
|
|
|
463
477
|
|
|
464
478
|
sp.apply {
|
|
465
479
|
layoutParams = FrameLayout.LayoutParams(
|
|
466
|
-
FrameLayout.LayoutParams.
|
|
480
|
+
FrameLayout.LayoutParams.WRAP_CONTENT,
|
|
467
481
|
FrameLayout.LayoutParams.WRAP_CONTENT
|
|
468
482
|
)
|
|
469
483
|
visibility = View.VISIBLE
|
|
@@ -529,6 +543,11 @@ class PCSelectionMenuView(context: Context) : FrameLayout(context), ReactScrollV
|
|
|
529
543
|
}
|
|
530
544
|
|
|
531
545
|
refreshHeadlessMenu()
|
|
546
|
+
|
|
547
|
+
// Re-measure after adapter change so Fabric state reflects new content width
|
|
548
|
+
if (anchorMode == "inline") {
|
|
549
|
+
post { updateFrameSizeState() }
|
|
550
|
+
}
|
|
532
551
|
}
|
|
533
552
|
|
|
534
553
|
private fun refreshSelections() {
|
|
@@ -555,6 +574,11 @@ class PCSelectionMenuView(context: Context) : FrameLayout(context), ReactScrollV
|
|
|
555
574
|
|
|
556
575
|
// Update headless menu checked state
|
|
557
576
|
refreshHeadlessMenu()
|
|
577
|
+
|
|
578
|
+
// Re-measure after selection change so Fabric state reflects new text width
|
|
579
|
+
if (anchorMode == "inline") {
|
|
580
|
+
post { updateFrameSizeState() }
|
|
581
|
+
}
|
|
558
582
|
}
|
|
559
583
|
|
|
560
584
|
// ---- Inline dropdown overlay ----
|
package/ios/PCLiquidGlass.mm
CHANGED
|
@@ -29,7 +29,8 @@ using namespace facebook::react;
|
|
|
29
29
|
- (instancetype)initWithFrame:(CGRect)frame {
|
|
30
30
|
if (self = [super initWithFrame:frame]) {
|
|
31
31
|
_view = [[PCLiquidGlassView alloc] initWithEffect:nil];
|
|
32
|
-
|
|
32
|
+
_view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
|
33
|
+
[self addSubview:_view];
|
|
33
34
|
|
|
34
35
|
// Set up press callback
|
|
35
36
|
__weak __typeof(self) weakSelf = self;
|
package/ios/PCSelectionMenu.mm
CHANGED
|
@@ -63,6 +63,11 @@ static inline bool OptionsEqual(
|
|
|
63
63
|
__typeof(self) strongSelf = weakSelf;
|
|
64
64
|
if (!strongSelf) return;
|
|
65
65
|
|
|
66
|
+
// The Swift view has already updated its content (selectedData + sync()).
|
|
67
|
+
// Trigger measurement now so Yoga gets the new size before the React
|
|
68
|
+
// round-trip, preventing a frame of clipped text.
|
|
69
|
+
[strongSelf updateMeasurements];
|
|
70
|
+
|
|
66
71
|
auto eventEmitter =
|
|
67
72
|
std::static_pointer_cast<const PCSelectionMenuEventEmitter>(
|
|
68
73
|
strongSelf->_eventEmitter);
|
|
@@ -201,10 +206,9 @@ static inline bool OptionsEqual(
|
|
|
201
206
|
if (_state == nullptr)
|
|
202
207
|
return;
|
|
203
208
|
|
|
204
|
-
//
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
CGSize size = [_view sizeForLayoutWithConstrainedTo:CGSizeMake(w, 0)];
|
|
209
|
+
// Measure unconstrained so the view reports its true intrinsic size.
|
|
210
|
+
// Yoga's measureContent() will clamp to parent layout constraints.
|
|
211
|
+
CGSize size = [_view sizeForLayoutWithConstrainedTo:CGSizeMake(CGFLOAT_MAX, 0)];
|
|
208
212
|
|
|
209
213
|
PCSelectionMenuStateFrameSize next;
|
|
210
214
|
next.frameSize = {(Float)size.width, (Float)size.height};
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import os.log
|
|
2
|
-
import SwiftUI
|
|
3
2
|
import UIKit
|
|
4
3
|
|
|
5
4
|
private let logger = Logger(subsystem: "com.platformcomponents", category: "SelectionMenu")
|
|
@@ -11,54 +10,6 @@ struct PCSelectionMenuOption {
|
|
|
11
10
|
let data: String
|
|
12
11
|
}
|
|
13
12
|
|
|
14
|
-
final class PCSelectionMenuModel: ObservableObject {
|
|
15
|
-
@Published var options: [PCSelectionMenuOption] = []
|
|
16
|
-
@Published var selectedData: String = "" // sentinel = no selection
|
|
17
|
-
@Published var placeholder: String = "Select"
|
|
18
|
-
@Published var interactivity: String = "enabled" // "enabled" | "disabled"
|
|
19
|
-
|
|
20
|
-
var isDisabled: Bool { interactivity == "disabled" }
|
|
21
|
-
|
|
22
|
-
var displayTitle: String {
|
|
23
|
-
if let opt = options.first(where: { $0.data == selectedData }), !selectedData.isEmpty {
|
|
24
|
-
return opt.label
|
|
25
|
-
}
|
|
26
|
-
return placeholder
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
var hasOptions: Bool { !options.isEmpty }
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
private struct PCSelectionMenuInlinePickerView: View {
|
|
33
|
-
@ObservedObject var model: PCSelectionMenuModel
|
|
34
|
-
let onSelectIndex: (Int) -> Void
|
|
35
|
-
|
|
36
|
-
var body: some View {
|
|
37
|
-
Menu {
|
|
38
|
-
ForEach(Array(model.options.enumerated()), id: \.offset) { i, opt in
|
|
39
|
-
Button(opt.label) { onSelectIndex(i) }
|
|
40
|
-
}
|
|
41
|
-
} label: {
|
|
42
|
-
HStack(spacing: 8) {
|
|
43
|
-
Text(model.displayTitle)
|
|
44
|
-
.font(.body)
|
|
45
|
-
.lineLimit(1)
|
|
46
|
-
.truncationMode(.tail)
|
|
47
|
-
|
|
48
|
-
Spacer(minLength: 0)
|
|
49
|
-
|
|
50
|
-
Image(systemName: "chevron.up.chevron.down")
|
|
51
|
-
.imageScale(.small)
|
|
52
|
-
.opacity(0.7)
|
|
53
|
-
}
|
|
54
|
-
.frame(maxWidth: .infinity, alignment: .leading)
|
|
55
|
-
.contentShape(Rectangle())
|
|
56
|
-
.padding(.vertical, 10)
|
|
57
|
-
}
|
|
58
|
-
.disabled(model.isDisabled || !model.hasOptions)
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
13
|
@objcMembers
|
|
63
14
|
public final class PCSelectionMenuView: UIControl {
|
|
64
15
|
// MARK: - Props (set from ObjC++)
|
|
@@ -93,10 +44,12 @@ public final class PCSelectionMenuView: UIControl {
|
|
|
93
44
|
public var onSelect: ((Int, String, String) -> Void)? // (index,label,data)
|
|
94
45
|
public var onRequestClose: (() -> Void)?
|
|
95
46
|
|
|
96
|
-
// MARK: - Internal
|
|
47
|
+
// MARK: - Internal (inline UIKit views)
|
|
48
|
+
|
|
49
|
+
private var menuButton: UIButton?
|
|
50
|
+
|
|
51
|
+
// MARK: - Internal (headless)
|
|
97
52
|
|
|
98
|
-
private let model = PCSelectionMenuModel()
|
|
99
|
-
private var hostingController: UIHostingController<AnyView>?
|
|
100
53
|
private var headlessMenuView: UIView?
|
|
101
54
|
private var headlessMenuVC: UIViewController?
|
|
102
55
|
private var headlessPresentationToken: Int = 0
|
|
@@ -110,6 +63,14 @@ public final class PCSelectionMenuView: UIControl {
|
|
|
110
63
|
}
|
|
111
64
|
}
|
|
112
65
|
|
|
66
|
+
private var displayTitle: String {
|
|
67
|
+
let opts = parsedOptions
|
|
68
|
+
if !selectedData.isEmpty, let opt = opts.first(where: { $0.data == selectedData }) {
|
|
69
|
+
return opt.label
|
|
70
|
+
}
|
|
71
|
+
return placeholder ?? "Select"
|
|
72
|
+
}
|
|
73
|
+
|
|
113
74
|
// MARK: - Init
|
|
114
75
|
|
|
115
76
|
public override init(frame: CGRect) {
|
|
@@ -155,45 +116,75 @@ public final class PCSelectionMenuView: UIControl {
|
|
|
155
116
|
}
|
|
156
117
|
|
|
157
118
|
private func sync() {
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
model.placeholder = placeholder ?? "Select"
|
|
161
|
-
model.interactivity = interactivity
|
|
119
|
+
// Update the button title
|
|
120
|
+
menuButton?.setTitle(displayTitle, for: .normal)
|
|
162
121
|
|
|
163
|
-
|
|
122
|
+
// Rebuild the UIMenu with current options
|
|
123
|
+
if anchorMode == "inline" {
|
|
124
|
+
rebuildMenu()
|
|
125
|
+
}
|
|
164
126
|
|
|
165
127
|
invalidateIntrinsicContentSize()
|
|
166
128
|
setNeedsLayout()
|
|
167
129
|
}
|
|
168
130
|
|
|
169
|
-
|
|
170
|
-
return AnyView(PCSelectionMenuInlinePickerView(
|
|
171
|
-
model: model,
|
|
172
|
-
onSelectIndex: { [weak self] idx in
|
|
173
|
-
guard let self else { return }
|
|
174
|
-
let opts = self.parsedOptions
|
|
175
|
-
guard idx >= 0, idx < opts.count else { return }
|
|
176
|
-
let opt = opts[idx]
|
|
177
|
-
self.selectedData = opt.data
|
|
178
|
-
self.onSelect?(idx, opt.label, opt.data)
|
|
179
|
-
}
|
|
180
|
-
))
|
|
181
|
-
}
|
|
131
|
+
// MARK: - Inline (UIKit-based)
|
|
182
132
|
|
|
183
133
|
private func installInlineIfNeeded() {
|
|
184
|
-
guard
|
|
185
|
-
|
|
134
|
+
guard menuButton == nil else { return }
|
|
135
|
+
|
|
136
|
+
var config = UIButton.Configuration.plain()
|
|
137
|
+
config.baseForegroundColor = .tintColor
|
|
138
|
+
config.image = UIImage(systemName: "chevron.up.chevron.down")
|
|
139
|
+
config.preferredSymbolConfigurationForImage = UIImage.SymbolConfiguration(scale: .small)
|
|
140
|
+
config.imagePlacement = .trailing
|
|
141
|
+
config.imagePadding = 8
|
|
142
|
+
config.contentInsets = NSDirectionalEdgeInsets(top: 10, leading: 0, bottom: 10, trailing: 0)
|
|
143
|
+
|
|
144
|
+
let button = UIButton(configuration: config)
|
|
145
|
+
button.showsMenuAsPrimaryAction = true
|
|
146
|
+
button.changesSelectionAsPrimaryAction = false
|
|
147
|
+
|
|
148
|
+
addSubview(button)
|
|
149
|
+
menuButton = button
|
|
150
|
+
|
|
151
|
+
rebuildMenu()
|
|
152
|
+
setNeedsLayout()
|
|
186
153
|
}
|
|
187
154
|
|
|
188
155
|
private func uninstallInlineIfNeeded() {
|
|
189
|
-
guard let
|
|
190
|
-
|
|
156
|
+
guard let button = menuButton else { return }
|
|
157
|
+
button.removeFromSuperview()
|
|
158
|
+
menuButton = nil
|
|
159
|
+
}
|
|
191
160
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
161
|
+
private func rebuildMenu() {
|
|
162
|
+
let opts = parsedOptions
|
|
163
|
+
let disabled = (interactivity == "disabled") || opts.isEmpty
|
|
164
|
+
let actions = opts.enumerated().map { (idx, opt) in
|
|
165
|
+
UIAction(title: opt.label) { [weak self] _ in
|
|
166
|
+
guard let self else { return }
|
|
167
|
+
self.selectedData = opt.data
|
|
168
|
+
self.onSelect?(idx, opt.label, opt.data)
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
menuButton?.menu = disabled ? nil : UIMenu(children: actions)
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
override public func layoutSubviews() {
|
|
175
|
+
super.layoutSubviews()
|
|
176
|
+
guard let button = menuButton else { return }
|
|
177
|
+
let fitted = button.intrinsicContentSize
|
|
178
|
+
button.frame = CGRect(
|
|
179
|
+
x: 0,
|
|
180
|
+
y: (bounds.height - fitted.height) / 2,
|
|
181
|
+
width: fitted.width,
|
|
182
|
+
height: fitted.height
|
|
183
|
+
)
|
|
195
184
|
}
|
|
196
185
|
|
|
186
|
+
// MARK: - Headless
|
|
187
|
+
|
|
197
188
|
private func installHeadlessIfNeeded() {
|
|
198
189
|
guard headlessMenuView == nil else { return }
|
|
199
190
|
|
|
@@ -220,27 +211,6 @@ public final class PCSelectionMenuView: UIControl {
|
|
|
220
211
|
view.removeFromSuperview()
|
|
221
212
|
}
|
|
222
213
|
|
|
223
|
-
private func installHostingController() {
|
|
224
|
-
let host = UIHostingController(rootView: makeRootView())
|
|
225
|
-
host.view.translatesAutoresizingMaskIntoConstraints = false
|
|
226
|
-
host.view.backgroundColor = .clear
|
|
227
|
-
|
|
228
|
-
addSubview(host.view)
|
|
229
|
-
NSLayoutConstraint.activate([
|
|
230
|
-
host.view.topAnchor.constraint(equalTo: topAnchor),
|
|
231
|
-
host.view.bottomAnchor.constraint(equalTo: bottomAnchor),
|
|
232
|
-
host.view.leadingAnchor.constraint(equalTo: leadingAnchor),
|
|
233
|
-
host.view.trailingAnchor.constraint(equalTo: trailingAnchor),
|
|
234
|
-
])
|
|
235
|
-
|
|
236
|
-
if let parent = nearestViewController() {
|
|
237
|
-
parent.addChild(host)
|
|
238
|
-
host.didMove(toParent: parent)
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
hostingController = host
|
|
242
|
-
}
|
|
243
|
-
|
|
244
214
|
private func nearestViewController() -> UIViewController? {
|
|
245
215
|
var r: UIResponder? = self
|
|
246
216
|
while let next = r?.next {
|
|
@@ -351,24 +321,26 @@ public final class PCSelectionMenuView: UIControl {
|
|
|
351
321
|
public override func sizeThatFits(_ size: CGSize) -> CGSize {
|
|
352
322
|
if anchorMode != "inline" { return CGSize(width: size.width, height: 1) }
|
|
353
323
|
|
|
354
|
-
guard let
|
|
355
|
-
return CGSize(width:
|
|
324
|
+
guard let button = menuButton else {
|
|
325
|
+
return CGSize(width: 0, height: PCConstants.minTouchTargetHeight)
|
|
356
326
|
}
|
|
357
327
|
|
|
358
|
-
let
|
|
359
|
-
|
|
360
|
-
|
|
328
|
+
let fitted = button.intrinsicContentSize
|
|
329
|
+
return CGSize(
|
|
330
|
+
width: fitted.width,
|
|
331
|
+
height: max(PCConstants.minTouchTargetHeight, fitted.height)
|
|
332
|
+
)
|
|
361
333
|
}
|
|
362
334
|
|
|
363
335
|
public override var intrinsicContentSize: CGSize {
|
|
364
336
|
if anchorMode != "inline" {
|
|
365
337
|
return CGSize(width: UIView.noIntrinsicMetric, height: 1)
|
|
366
338
|
}
|
|
367
|
-
let
|
|
368
|
-
|
|
369
|
-
|
|
339
|
+
let fitted = sizeThatFits(CGSize(width: CGFloat.greatestFiniteMagnitude, height: .greatestFiniteMagnitude))
|
|
340
|
+
return CGSize(
|
|
341
|
+
width: fitted.width,
|
|
342
|
+
height: max(PCConstants.minTouchTargetHeight, fitted.height)
|
|
370
343
|
)
|
|
371
|
-
return CGSize(width: UIView.noIntrinsicMetric, height: h)
|
|
372
344
|
}
|
|
373
345
|
|
|
374
346
|
/// Called by the measuring pipeline to get the size for Yoga layout.
|
|
@@ -376,16 +348,15 @@ public final class PCSelectionMenuView: UIControl {
|
|
|
376
348
|
@objc public func sizeForLayout(withConstrainedTo constrainedSize: CGSize) -> CGSize {
|
|
377
349
|
guard anchorMode == "inline" else { return .zero }
|
|
378
350
|
|
|
379
|
-
guard let
|
|
380
|
-
return CGSize(width:
|
|
351
|
+
guard let button = menuButton else {
|
|
352
|
+
return CGSize(width: 0, height: PCConstants.minTouchTargetHeight)
|
|
381
353
|
}
|
|
382
354
|
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
return CGSize(width: constrainedSize.width, height: max(PCConstants.minTouchTargetHeight, fitted.height))
|
|
355
|
+
let fitted = button.intrinsicContentSize
|
|
356
|
+
return CGSize(
|
|
357
|
+
width: fitted.width,
|
|
358
|
+
height: max(PCConstants.minTouchTargetHeight, fitted.height)
|
|
359
|
+
)
|
|
389
360
|
}
|
|
390
361
|
}
|
|
391
362
|
|
|
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.SelectionMenu = SelectionMenu;
|
|
7
7
|
var _react = _interopRequireWildcard(require("react"));
|
|
8
|
+
var _reactNative = require("react-native");
|
|
8
9
|
var _SelectionMenuNativeComponent = _interopRequireDefault(require("./SelectionMenuNativeComponent"));
|
|
9
10
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
10
11
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
@@ -55,6 +56,10 @@ function SelectionMenu(props) {
|
|
|
55
56
|
material: android.material
|
|
56
57
|
};
|
|
57
58
|
}, [android]);
|
|
59
|
+
|
|
60
|
+
// On Android, force a fresh native view when structural props change so the
|
|
61
|
+
// widget gets a clean measurement cycle (TextInputLayout caches aggressively).
|
|
62
|
+
const remountKey = _reactNative.Platform.OS === 'android' ? `${presentation}-${android?.material ?? 'system'}` : undefined;
|
|
58
63
|
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_SelectionMenuNativeComponent.default, {
|
|
59
64
|
style: style,
|
|
60
65
|
options: options,
|
|
@@ -68,6 +73,6 @@ function SelectionMenu(props) {
|
|
|
68
73
|
ios: ios,
|
|
69
74
|
android: nativeAndroid,
|
|
70
75
|
...viewProps
|
|
71
|
-
});
|
|
76
|
+
}, remountKey);
|
|
72
77
|
}
|
|
73
78
|
//# sourceMappingURL=SelectionMenu.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_react","_interopRequireWildcard","require","_SelectionMenuNativeComponent","_interopRequireDefault","_jsxRuntime","e","__esModule","default","t","WeakMap","r","n","o","i","f","__proto__","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","normalizeSelectedData","selected","normalizeNativeVisible","presentation","visible","undefined","SelectionMenu","props","style","options","disabled","placeholder","onSelect","onRequestClose","ios","android","viewProps","selectedData","useMemo","nativeVisible","handleSelect","useCallback","index","label","data","nativeEvent","handleRequestClose","nativeAndroid","material","jsx","interactivity","anchorMode"],"sourceRoot":"../../src","sources":["SelectionMenu.tsx"],"mappings":";;;;;;AACA,IAAAA,MAAA,GAAAC,uBAAA,CAAAC,OAAA;
|
|
1
|
+
{"version":3,"names":["_react","_interopRequireWildcard","require","_reactNative","_SelectionMenuNativeComponent","_interopRequireDefault","_jsxRuntime","e","__esModule","default","t","WeakMap","r","n","o","i","f","__proto__","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","normalizeSelectedData","selected","normalizeNativeVisible","presentation","visible","undefined","SelectionMenu","props","style","options","disabled","placeholder","onSelect","onRequestClose","ios","android","viewProps","selectedData","useMemo","nativeVisible","handleSelect","useCallback","index","label","data","nativeEvent","handleRequestClose","nativeAndroid","material","remountKey","Platform","OS","jsx","interactivity","anchorMode"],"sourceRoot":"../../src","sources":["SelectionMenu.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
// SelectionMenu.tsx
|
|
4
4
|
import React, { useCallback, useMemo } from 'react';
|
|
5
|
+
import { Platform } from 'react-native';
|
|
5
6
|
import NativeSelectionMenu from './SelectionMenuNativeComponent';
|
|
6
7
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
7
8
|
function normalizeSelectedData(selected) {
|
|
@@ -48,6 +49,10 @@ export function SelectionMenu(props) {
|
|
|
48
49
|
material: android.material
|
|
49
50
|
};
|
|
50
51
|
}, [android]);
|
|
52
|
+
|
|
53
|
+
// On Android, force a fresh native view when structural props change so the
|
|
54
|
+
// widget gets a clean measurement cycle (TextInputLayout caches aggressively).
|
|
55
|
+
const remountKey = Platform.OS === 'android' ? `${presentation}-${android?.material ?? 'system'}` : undefined;
|
|
51
56
|
return /*#__PURE__*/_jsx(NativeSelectionMenu, {
|
|
52
57
|
style: style,
|
|
53
58
|
options: options,
|
|
@@ -61,6 +66,6 @@ export function SelectionMenu(props) {
|
|
|
61
66
|
ios: ios,
|
|
62
67
|
android: nativeAndroid,
|
|
63
68
|
...viewProps
|
|
64
|
-
});
|
|
69
|
+
}, remountKey);
|
|
65
70
|
}
|
|
66
71
|
//# sourceMappingURL=SelectionMenu.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["React","useCallback","useMemo","NativeSelectionMenu","jsx","_jsx","normalizeSelectedData","selected","normalizeNativeVisible","presentation","visible","undefined","SelectionMenu","props","style","options","disabled","placeholder","onSelect","onRequestClose","ios","android","viewProps","selectedData","nativeVisible","handleSelect","e","index","label","data","nativeEvent","handleRequestClose","nativeAndroid","material","interactivity","anchorMode"],"sourceRoot":"../../src","sources":["SelectionMenu.tsx"],"mappings":";;AAAA;AACA,OAAOA,KAAK,IAAIC,WAAW,EAAEC,OAAO,QAAQ,OAAO;
|
|
1
|
+
{"version":3,"names":["React","useCallback","useMemo","Platform","NativeSelectionMenu","jsx","_jsx","normalizeSelectedData","selected","normalizeNativeVisible","presentation","visible","undefined","SelectionMenu","props","style","options","disabled","placeholder","onSelect","onRequestClose","ios","android","viewProps","selectedData","nativeVisible","handleSelect","e","index","label","data","nativeEvent","handleRequestClose","nativeAndroid","material","remountKey","OS","interactivity","anchorMode"],"sourceRoot":"../../src","sources":["SelectionMenu.tsx"],"mappings":";;AAAA;AACA,OAAOA,KAAK,IAAIC,WAAW,EAAEC,OAAO,QAAQ,OAAO;AACnD,SAASC,QAAQ,QAAwB,cAAc;AAEvD,OAAOC,mBAAmB,MAGnB,gCAAgC;AAAC,SAAAC,GAAA,IAAAC,IAAA;AAyDxC,SAASC,qBAAqBA,CAACC,QAAuB,EAAU;EAC9D,OAAOA,QAAQ,IAAI,EAAE;AACvB;AAEA,SAASC,sBAAsBA,CAC7BC,YAAsC,EACtCC,OAA4B,EACG;EAC/B;EACA,IAAID,YAAY,KAAK,UAAU,EAAE,OAAOE,SAAS;EACjD,OAAOD,OAAO,GAAG,MAAM,GAAG,QAAQ;AACpC;AAEA,OAAO,SAASE,aAAaA,CAACC,KAAyB,EAAsB;EAC3E,MAAM;IACJC,KAAK;IACLC,OAAO;IACPR,QAAQ;IACRS,QAAQ;IACRC,WAAW;IACXR,YAAY,GAAG,OAAO;IACtBC,OAAO;IACPQ,QAAQ;IACRC,cAAc;IACdC,GAAG;IACHC,OAAO;IACP,GAAGC;EACL,CAAC,GAAGT,KAAK;EAET,MAAMU,YAAY,GAAGtB,OAAO,CAC1B,MAAMK,qBAAqB,CAACC,QAAQ,CAAC,EACrC,CAACA,QAAQ,CACX,CAAC;EAED,MAAMiB,aAAa,GAAGvB,OAAO,CAC3B,MAAMO,sBAAsB,CAACC,YAAY,EAAEC,OAAO,CAAC,EACnD,CAACD,YAAY,EAAEC,OAAO,CACxB,CAAC;EAED,MAAMe,YAAY,GAAGzB,WAAW,CAC7B0B,CAA4C,IAAK;IAChD,MAAM;MAAEC,KAAK;MAAEC,KAAK;MAAEC;IAAK,CAAC,GAAGH,CAAC,CAACI,WAAW;IAC5CZ,QAAQ,GAAGW,IAAI,EAAED,KAAK,EAAED,KAAK,CAAC;EAChC,CAAC,EACD,CAACT,QAAQ,CACX,CAAC;EAED,MAAMa,kBAAkB,GAAG/B,WAAW,CAAC,MAAM;IAC3CmB,cAAc,GAAG,CAAC;EACpB,CAAC,EAAE,CAACA,cAAc,CAAC,CAAC;;EAEpB;EACA,MAAMa,aAAa,GAAG/B,OAAO,CAAC,MAAM;IAClC,IAAI,CAACoB,OAAO,EAAE,OAAOV,SAAS;IAC9B,OAAO;MAAEsB,QAAQ,EAAEZ,OAAO,CAACY;IAAS,CAAC;EACvC,CAAC,EAAE,CAACZ,OAAO,CAAC,CAAC;;EAEb;EACA;EACA,MAAMa,UAAU,GACdhC,QAAQ,CAACiC,EAAE,KAAK,SAAS,GACrB,GAAG1B,YAAY,IAAIY,OAAO,EAAEY,QAAQ,IAAI,QAAQ,EAAE,GAClDtB,SAAS;EAEf,oBACEN,IAAA,CAACF,mBAAmB;IAElBW,KAAK,EAAEA,KAAM;IACbC,OAAO,EAAEA,OAAQ;IACjBQ,YAAY,EAAEA,YAAa;IAC3Ba,aAAa,EAAEpB,QAAQ,GAAG,UAAU,GAAG,SAAU;IACjDC,WAAW,EAAEA,WAAY;IACzBoB,UAAU,EAAE5B,YAAY,KAAK,UAAU,GAAG,QAAQ,GAAG,UAAW;IAChEC,OAAO,EAAEc,aAAc;IACvBN,QAAQ,EAAEA,QAAQ,GAAGO,YAAY,GAAGd,SAAU;IAC9CQ,cAAc,EAAEA,cAAc,GAAGY,kBAAkB,GAAGpB,SAAU;IAChES,GAAG,EAAEA,GAAI;IACTC,OAAO,EAAEW,aAAc;IAAA,GACnBV;EAAS,GAZRY,UAaN,CAAC;AAEN","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SelectionMenu.d.ts","sourceRoot":"","sources":["../../../../src/SelectionMenu.tsx"],"names":[],"mappings":"AACA,OAAO,KAA+B,MAAM,OAAO,CAAC;AACpD,OAAO,
|
|
1
|
+
{"version":3,"file":"SelectionMenu.d.ts","sourceRoot":"","sources":["../../../../src/SelectionMenu.tsx"],"names":[],"mappings":"AACA,OAAO,KAA+B,MAAM,OAAO,CAAC;AACpD,OAAO,EAAY,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAExD,OAA4B,EAC1B,KAAK,mBAAmB,EAEzB,MAAM,gCAAgC,CAAC;AAExC,YAAY,EAAE,mBAAmB,EAAE,CAAC;AAEpC,OAAO,KAAK,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAEvE,MAAM,WAAW,kBAAmB,SAAQ,SAAS;IACnD,yCAAyC;IACzC,OAAO,EAAE,SAAS,mBAAmB,EAAE,CAAC;IAExC;;;OAGG;IACH,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IAExB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;;OAIG;IACH,YAAY,CAAC,EAAE,YAAY,CAAC;IAE5B;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;;OAGG;IACH,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAEhE;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAE5B;;OAEG;IACH,GAAG,CAAC,EAAE,EAAE,CAAC;IAET,OAAO,CAAC,EAAE;QACR,6CAA6C;QAC7C,QAAQ,CAAC,EAAE,mBAAmB,CAAC;KAChC,CAAC;IAEF,sBAAsB;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAeD,wBAAgB,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,KAAK,CAAC,YAAY,CAoE3E"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SelectionMenu.d.ts","sourceRoot":"","sources":["../../../../src/SelectionMenu.tsx"],"names":[],"mappings":"AACA,OAAO,KAA+B,MAAM,OAAO,CAAC;AACpD,OAAO,
|
|
1
|
+
{"version":3,"file":"SelectionMenu.d.ts","sourceRoot":"","sources":["../../../../src/SelectionMenu.tsx"],"names":[],"mappings":"AACA,OAAO,KAA+B,MAAM,OAAO,CAAC;AACpD,OAAO,EAAY,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAExD,OAA4B,EAC1B,KAAK,mBAAmB,EAEzB,MAAM,gCAAgC,CAAC;AAExC,YAAY,EAAE,mBAAmB,EAAE,CAAC;AAEpC,OAAO,KAAK,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAEvE,MAAM,WAAW,kBAAmB,SAAQ,SAAS;IACnD,yCAAyC;IACzC,OAAO,EAAE,SAAS,mBAAmB,EAAE,CAAC;IAExC;;;OAGG;IACH,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IAExB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;;OAIG;IACH,YAAY,CAAC,EAAE,YAAY,CAAC;IAE5B;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;;OAGG;IACH,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAEhE;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAE5B;;OAEG;IACH,GAAG,CAAC,EAAE,EAAE,CAAC;IAET,OAAO,CAAC,EAAE;QACR,6CAA6C;QAC7C,QAAQ,CAAC,EAAE,mBAAmB,CAAC;KAChC,CAAC;IAEF,sBAAsB;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAeD,wBAAgB,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,KAAK,CAAC,YAAY,CAoE3E"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-platform-components",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.7",
|
|
4
4
|
"description": "Native UI components for React Native: DatePicker, ContextMenu, SelectionMenu, SegmentedControl, LiquidGlass.",
|
|
5
5
|
"main": "./lib/commonjs/index.js",
|
|
6
6
|
"module": "./lib/module/index.js",
|
package/src/SelectionMenu.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// SelectionMenu.tsx
|
|
2
2
|
import React, { useCallback, useMemo } from 'react';
|
|
3
|
-
import { type ViewProps } from 'react-native';
|
|
3
|
+
import { Platform, type ViewProps } from 'react-native';
|
|
4
4
|
|
|
5
5
|
import NativeSelectionMenu, {
|
|
6
6
|
type SelectionMenuOption,
|
|
@@ -119,8 +119,16 @@ export function SelectionMenu(props: SelectionMenuProps): React.ReactElement {
|
|
|
119
119
|
return { material: android.material };
|
|
120
120
|
}, [android]);
|
|
121
121
|
|
|
122
|
+
// On Android, force a fresh native view when structural props change so the
|
|
123
|
+
// widget gets a clean measurement cycle (TextInputLayout caches aggressively).
|
|
124
|
+
const remountKey =
|
|
125
|
+
Platform.OS === 'android'
|
|
126
|
+
? `${presentation}-${android?.material ?? 'system'}`
|
|
127
|
+
: undefined;
|
|
128
|
+
|
|
122
129
|
return (
|
|
123
130
|
<NativeSelectionMenu
|
|
131
|
+
key={remountKey}
|
|
124
132
|
style={style}
|
|
125
133
|
options={options}
|
|
126
134
|
selectedData={selectedData}
|