react-native-platform-components 0.5.3 → 0.5.4
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 +6 -1
- package/android/build.gradle +3 -1
- package/android/src/main/java/com/platformcomponents/PCConstants.kt +3 -0
- package/android/src/main/java/com/platformcomponents/PCDatePickerView.kt +53 -1
- package/android/src/main/java/com/platformcomponents/PCDatePickerViewManager.kt +14 -0
- package/android/src/main/java/com/platformcomponents/PCSelectionMenuView.kt +169 -10
- package/android/src/main/java/com/platformcomponents/PCSelectionMenuViewManager.kt +14 -0
- package/android/src/main/jni/CMakeLists.txt +47 -0
- package/android/src/main/jni/OnLoad.cpp +33 -0
- package/ios/PCDatePickerView.swift +19 -2
- package/ios/PCSelectionMenu.mm +42 -0
- package/ios/PCSelectionMenu.swift +17 -0
- package/lib/module/SelectionMenu.js +1 -8
- package/lib/module/SelectionMenu.js.map +1 -1
- package/lib/typescript/src/SelectionMenu.d.ts.map +1 -1
- package/package.json +1 -1
- package/react-native.config.js +13 -0
- package/shared/PCDatePickerComponentDescriptors-custom.h +14 -43
- package/shared/PCDatePickerShadowNode-custom.cpp +35 -0
- package/shared/PCDatePickerShadowNode-custom.h +40 -18
- package/shared/PCDatePickerState-custom.h +53 -1
- package/shared/PCSelectionMenuComponentDescriptors-custom.h +15 -18
- package/shared/PCSelectionMenuShadowNode-custom.cpp +42 -21
- package/shared/PCSelectionMenuShadowNode-custom.h +23 -10
- package/shared/PCSelectionMenuState-custom.h +65 -0
- package/shared/README.md +179 -0
- package/shared/react/renderer/components/PlatformComponentsViewSpec/ComponentDescriptors.h +9 -0
- package/src/SelectionMenu.tsx +2 -12
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
// SelectionMenu.tsx
|
|
4
4
|
import React, { useCallback, useMemo } from 'react';
|
|
5
|
-
import { Platform, StyleSheet } from 'react-native';
|
|
6
5
|
import NativeSelectionMenu from './SelectionMenuNativeComponent';
|
|
7
6
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
8
7
|
function normalizeSelectedData(selected) {
|
|
@@ -49,9 +48,8 @@ export function SelectionMenu(props) {
|
|
|
49
48
|
material: android.material
|
|
50
49
|
};
|
|
51
50
|
}, [android]);
|
|
52
|
-
const isAndroidM3Inline = android?.material && inlineMode && android.material === 'm3' && Platform.OS === 'android';
|
|
53
51
|
return /*#__PURE__*/_jsx(NativeSelectionMenu, {
|
|
54
|
-
style:
|
|
52
|
+
style: style,
|
|
55
53
|
options: options,
|
|
56
54
|
selectedData: selectedData,
|
|
57
55
|
interactivity: disabled ? 'disabled' : 'enabled',
|
|
@@ -65,9 +63,4 @@ export function SelectionMenu(props) {
|
|
|
65
63
|
...viewProps
|
|
66
64
|
});
|
|
67
65
|
}
|
|
68
|
-
const styles = StyleSheet.create({
|
|
69
|
-
androidInline: {
|
|
70
|
-
minHeight: 60
|
|
71
|
-
}
|
|
72
|
-
});
|
|
73
66
|
//# sourceMappingURL=SelectionMenu.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["React","useCallback","useMemo","
|
|
1
|
+
{"version":3,"names":["React","useCallback","useMemo","NativeSelectionMenu","jsx","_jsx","normalizeSelectedData","selected","normalizeNativeVisible","inlineMode","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;AAGnD,OAAOC,mBAAmB,MAGnB,gCAAgC;AAAC,SAAAC,GAAA,IAAAC,IAAA;AAsDxC,SAASC,qBAAqBA,CAACC,QAAuB,EAAU;EAC9D,OAAOA,QAAQ,IAAI,EAAE;AACvB;AAEA,SAASC,sBAAsBA,CAC7BC,UAA+B,EAC/BC,OAA4B,EACG;EAC/B;EACA,IAAID,UAAU,EAAE,OAAOE,SAAS;EAChC,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,UAAU;IACVC,OAAO;IACPQ,QAAQ;IACRC,cAAc;IACdC,GAAG;IACHC,OAAO;IACP,GAAGC;EACL,CAAC,GAAGT,KAAK;EAET,MAAMU,YAAY,GAAGrB,OAAO,CAC1B,MAAMI,qBAAqB,CAACC,QAAQ,CAAC,EACrC,CAACA,QAAQ,CACX,CAAC;EAED,MAAMiB,aAAa,GAAGtB,OAAO,CAC3B,MAAMM,sBAAsB,CAACC,UAAU,EAAEC,OAAO,CAAC,EACjD,CAACD,UAAU,EAAEC,OAAO,CACtB,CAAC;EAED,MAAMe,YAAY,GAAGxB,WAAW,CAC7ByB,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,GAAG9B,WAAW,CAAC,MAAM;IAC3CkB,cAAc,GAAG,CAAC;EACpB,CAAC,EAAE,CAACA,cAAc,CAAC,CAAC;;EAEpB;EACA,MAAMa,aAAa,GAAG9B,OAAO,CAAC,MAAM;IAClC,IAAI,CAACmB,OAAO,EAAE,OAAOV,SAAS;IAC9B,OAAO;MAAEsB,QAAQ,EAAEZ,OAAO,CAACY;IAAS,CAAC;EACvC,CAAC,EAAE,CAACZ,OAAO,CAAC,CAAC;EAEb,oBACEhB,IAAA,CAACF,mBAAmB;IAClBW,KAAK,EAAEA,KAAM;IACbC,OAAO,EAAEA,OAAQ;IACjBQ,YAAY,EAAEA,YAAa;IAC3BW,aAAa,EAAElB,QAAQ,GAAG,UAAU,GAAG,SAAU;IACjDC,WAAW,EAAEA,WAAY;IACzBkB,UAAU,EAAE1B,UAAU,GAAG,QAAQ,GAAG,UAAW;IAC/CC,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,CACd,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,EAAE,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C,OAA4B,EAC1B,KAAK,mBAAmB,EAEzB,MAAM,gCAAgC,CAAC;AAExC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAEzD,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;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;;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,CA4D3E"}
|
package/package.json
CHANGED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
dependency: {
|
|
3
|
+
platforms: {
|
|
4
|
+
android: {
|
|
5
|
+
componentDescriptors: [
|
|
6
|
+
'MeasuringPCSelectionMenuComponentDescriptor',
|
|
7
|
+
'MeasuringPCDatePickerComponentDescriptor',
|
|
8
|
+
],
|
|
9
|
+
cmakeListsPath: 'src/main/jni/CMakeLists.txt',
|
|
10
|
+
},
|
|
11
|
+
},
|
|
12
|
+
},
|
|
13
|
+
};
|
|
@@ -1,52 +1,23 @@
|
|
|
1
1
|
#pragma once
|
|
2
2
|
|
|
3
|
-
#include "PCDatePickerShadowNode-custom.h"
|
|
4
|
-
|
|
5
3
|
#include <react/renderer/core/ConcreteComponentDescriptor.h>
|
|
6
|
-
#include <react/renderer/mounting/ShadowView.h>
|
|
7
|
-
#include <react/renderer/core/ShadowNode.h>
|
|
8
|
-
#include <react/renderer/core/ShadowNodeTraits.h>
|
|
9
|
-
#include <react/renderer/core/ShadowNodeFragment.h>
|
|
10
|
-
#include <react/renderer/core/ShadowNodeFamily.h>
|
|
11
|
-
#include <react/renderer/components/view/YogaLayoutableShadowNode.h>
|
|
12
|
-
|
|
13
|
-
namespace facebook::react
|
|
14
|
-
{
|
|
15
4
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
using ConcreteComponentDescriptor::ConcreteComponentDescriptor;
|
|
5
|
+
// Forward declaration to avoid circular includes
|
|
6
|
+
namespace facebook::react {
|
|
7
|
+
class MeasuringPCDatePickerShadowNode;
|
|
8
|
+
}
|
|
21
9
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
auto &pickerShadowNode =
|
|
25
|
-
static_cast<MeasuringPCDatePickerShadowNode &>(shadowNode);
|
|
26
|
-
auto &layoutableShadowNode =
|
|
27
|
-
static_cast<YogaLayoutableShadowNode &>(pickerShadowNode);
|
|
28
|
-
|
|
29
|
-
auto state =
|
|
30
|
-
std::static_pointer_cast<
|
|
31
|
-
const MeasuringPCDatePickerShadowNode::ConcreteState
|
|
32
|
-
>(shadowNode.getState());
|
|
33
|
-
|
|
34
|
-
if (state)
|
|
35
|
-
{
|
|
36
|
-
auto stateData = state->getData();
|
|
37
|
-
auto frameSize = stateData.frameSize;
|
|
10
|
+
// Include the actual shadow node definition
|
|
11
|
+
#include "PCDatePickerShadowNode-custom.h"
|
|
38
12
|
|
|
39
|
-
|
|
40
|
-
{
|
|
41
|
-
layoutableShadowNode.setSize(Size{
|
|
42
|
-
frameSize.width,
|
|
43
|
-
frameSize.height,
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
}
|
|
13
|
+
namespace facebook::react {
|
|
47
14
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
15
|
+
/**
|
|
16
|
+
* Custom component descriptor that uses our measuring shadow node
|
|
17
|
+
* instead of the generated one. No custom adopt() needed since
|
|
18
|
+
* measurement is handled via measureContent().
|
|
19
|
+
*/
|
|
20
|
+
using MeasuringPCDatePickerComponentDescriptor =
|
|
21
|
+
ConcreteComponentDescriptor<MeasuringPCDatePickerShadowNode>;
|
|
51
22
|
|
|
52
23
|
} // namespace facebook::react
|
|
@@ -1 +1,36 @@
|
|
|
1
1
|
#include "PCDatePickerShadowNode-custom.h"
|
|
2
|
+
|
|
3
|
+
#include <react/renderer/core/LayoutConstraints.h>
|
|
4
|
+
#include <react/renderer/core/ConcreteShadowNode.h>
|
|
5
|
+
#include <algorithm>
|
|
6
|
+
|
|
7
|
+
namespace facebook::react {
|
|
8
|
+
|
|
9
|
+
Size MeasuringPCDatePickerShadowNode::measureContent(
|
|
10
|
+
const LayoutContext& /*layoutContext*/,
|
|
11
|
+
const LayoutConstraints& layoutConstraints) const {
|
|
12
|
+
|
|
13
|
+
// Get frame size from native state - native measures the actual picker
|
|
14
|
+
const auto& stateData = this->getStateData();
|
|
15
|
+
Float measuredW = stateData.frameSize.width;
|
|
16
|
+
Float measuredH = stateData.frameSize.height;
|
|
17
|
+
|
|
18
|
+
// If width is 0, use available width from constraints
|
|
19
|
+
const Float kHuge = static_cast<Float>(1.0e9);
|
|
20
|
+
if (measuredW <= 0) {
|
|
21
|
+
const Float maxW = layoutConstraints.maximumSize.width;
|
|
22
|
+
measuredW = (maxW > 0 && maxW < kHuge) ? maxW : 0;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Respect layout constraints
|
|
26
|
+
measuredW = std::max<Float>(measuredW, layoutConstraints.minimumSize.width);
|
|
27
|
+
measuredW = std::min<Float>(measuredW, layoutConstraints.maximumSize.width);
|
|
28
|
+
|
|
29
|
+
measuredH = std::max<Float>(measuredH, layoutConstraints.minimumSize.height);
|
|
30
|
+
measuredH = std::min<Float>(measuredH, layoutConstraints.maximumSize.height);
|
|
31
|
+
|
|
32
|
+
Size result{measuredW, measuredH};
|
|
33
|
+
return layoutConstraints.clamp(result);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
} // namespace facebook::react
|
|
@@ -1,27 +1,49 @@
|
|
|
1
1
|
#pragma once
|
|
2
2
|
|
|
3
|
-
#include <react/renderer/components/
|
|
3
|
+
#include <react/renderer/components/view/ConcreteViewShadowNode.h>
|
|
4
|
+
|
|
5
|
+
// Only include what we need for the shadow node definition
|
|
6
|
+
// Do NOT include ComponentDescriptors.h here to avoid circular dependency
|
|
4
7
|
#include <react/renderer/components/PlatformComponentsViewSpec/EventEmitters.h>
|
|
5
8
|
#include <react/renderer/components/PlatformComponentsViewSpec/Props.h>
|
|
6
9
|
|
|
7
|
-
#include <react/renderer/components/view/ConcreteViewShadowNode.h>
|
|
8
|
-
#include <react/renderer/core/ConcreteState.h>
|
|
9
|
-
#include <react/renderer/core/ShadowNodeTraits.h>
|
|
10
|
-
#include <react/renderer/mounting/ShadowView.h>
|
|
11
|
-
|
|
12
10
|
#include "PCDatePickerState-custom.h"
|
|
13
11
|
|
|
14
|
-
namespace facebook::react
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
12
|
+
namespace facebook::react {
|
|
13
|
+
|
|
14
|
+
extern const char PCDatePickerComponentName[];
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Custom ShadowNode for DatePicker that supports Yoga measurement.
|
|
18
|
+
*
|
|
19
|
+
* Key behavior:
|
|
20
|
+
* - Native side measures the actual picker and updates state with frameSize
|
|
21
|
+
* - measureContent() returns the size from state for proper Yoga layout
|
|
22
|
+
* - No hardcoded dimensions - uses actual measured values from native
|
|
23
|
+
*/
|
|
24
|
+
class MeasuringPCDatePickerShadowNode final
|
|
25
|
+
: public ConcreteViewShadowNode<
|
|
26
|
+
PCDatePickerComponentName,
|
|
27
|
+
PCDatePickerProps,
|
|
28
|
+
PCDatePickerEventEmitter,
|
|
29
|
+
PCDatePickerStateFrameSize> {
|
|
30
|
+
public:
|
|
31
|
+
using ConcreteViewShadowNode::ConcreteViewShadowNode;
|
|
32
|
+
|
|
33
|
+
static ShadowNodeTraits BaseTraits() {
|
|
34
|
+
auto traits = ConcreteViewShadowNode::BaseTraits();
|
|
35
|
+
traits.set(ShadowNodeTraits::Trait::LeafYogaNode);
|
|
36
|
+
traits.set(ShadowNodeTraits::Trait::MeasurableYogaNode);
|
|
37
|
+
return traits;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Called by Yoga when it needs the intrinsic size of the component.
|
|
42
|
+
* Returns the size provided by native through state - no hardcoding.
|
|
43
|
+
*/
|
|
44
|
+
Size measureContent(
|
|
45
|
+
const LayoutContext& layoutContext,
|
|
46
|
+
const LayoutConstraints& layoutConstraints) const override;
|
|
47
|
+
};
|
|
26
48
|
|
|
27
49
|
} // namespace facebook::react
|
|
@@ -1,13 +1,65 @@
|
|
|
1
1
|
#pragma once
|
|
2
2
|
|
|
3
3
|
#include <react/renderer/core/LayoutPrimitives.h>
|
|
4
|
+
#include <memory>
|
|
5
|
+
|
|
6
|
+
#ifdef RN_SERIALIZABLE_STATE
|
|
7
|
+
#include <folly/dynamic.h>
|
|
8
|
+
#include <react/renderer/mapbuffer/MapBuffer.h>
|
|
9
|
+
#include <react/renderer/mapbuffer/MapBufferBuilder.h>
|
|
10
|
+
#endif
|
|
4
11
|
|
|
5
12
|
namespace facebook::react {
|
|
6
13
|
|
|
7
|
-
|
|
14
|
+
/**
|
|
15
|
+
* Custom state for DatePicker that holds the measured frame size from native.
|
|
16
|
+
* This allows the native side to measure the actual picker and communicate
|
|
17
|
+
* the size to the shadow node for proper Yoga layout.
|
|
18
|
+
*
|
|
19
|
+
* Note: Does NOT inherit from StateData (which is final). Custom state types
|
|
20
|
+
* are standalone structs that satisfy the ConcreteState template requirements.
|
|
21
|
+
*/
|
|
22
|
+
struct PCDatePickerStateFrameSize {
|
|
8
23
|
using Shared = std::shared_ptr<const PCDatePickerStateFrameSize>;
|
|
9
24
|
|
|
10
25
|
Size frameSize{}; // {width, height} in points
|
|
26
|
+
|
|
27
|
+
PCDatePickerStateFrameSize() = default;
|
|
28
|
+
|
|
29
|
+
explicit PCDatePickerStateFrameSize(Size size) : frameSize(size) {}
|
|
30
|
+
|
|
31
|
+
bool operator==(const PCDatePickerStateFrameSize& other) const {
|
|
32
|
+
return frameSize.width == other.frameSize.width &&
|
|
33
|
+
frameSize.height == other.frameSize.height;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
bool operator!=(const PCDatePickerStateFrameSize& other) const {
|
|
37
|
+
return !(*this == other);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
#ifdef RN_SERIALIZABLE_STATE
|
|
41
|
+
// Required for Android state serialization
|
|
42
|
+
PCDatePickerStateFrameSize(
|
|
43
|
+
const PCDatePickerStateFrameSize& previousState,
|
|
44
|
+
folly::dynamic data)
|
|
45
|
+
: frameSize(previousState.frameSize) {
|
|
46
|
+
// Parse frame size from dynamic data if provided
|
|
47
|
+
if (data.isObject()) {
|
|
48
|
+
if (data.count("width") && data.count("height")) {
|
|
49
|
+
frameSize.width = static_cast<Float>(data["width"].asDouble());
|
|
50
|
+
frameSize.height = static_cast<Float>(data["height"].asDouble());
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
folly::dynamic getDynamic() const {
|
|
56
|
+
return folly::dynamic::object("width", frameSize.width)("height", frameSize.height);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
MapBuffer getMapBuffer() const {
|
|
60
|
+
return MapBufferBuilder::EMPTY();
|
|
61
|
+
}
|
|
62
|
+
#endif
|
|
11
63
|
};
|
|
12
64
|
|
|
13
65
|
} // namespace facebook::react
|
|
@@ -1,25 +1,22 @@
|
|
|
1
1
|
#pragma once
|
|
2
2
|
|
|
3
|
-
#include "PCSelectionMenuShadowNode-custom.h"
|
|
4
|
-
|
|
5
3
|
#include <react/renderer/core/ConcreteComponentDescriptor.h>
|
|
6
|
-
#include <react/renderer/mounting/ShadowView.h>
|
|
7
|
-
#include <react/renderer/core/ShadowNode.h>
|
|
8
|
-
#include <react/renderer/core/ShadowNodeTraits.h>
|
|
9
|
-
#include <react/renderer/core/ShadowNodeFragment.h>
|
|
10
|
-
#include <react/renderer/core/ShadowNodeFamily.h>
|
|
11
|
-
#include <react/renderer/components/view/YogaLayoutableShadowNode.h>
|
|
12
4
|
|
|
13
|
-
|
|
14
|
-
{
|
|
15
|
-
|
|
5
|
+
// Forward declaration to avoid circular includes
|
|
6
|
+
namespace facebook::react {
|
|
7
|
+
class MeasuringPCSelectionMenuShadowNode;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// Include the actual shadow node definition
|
|
11
|
+
#include "PCSelectionMenuShadowNode-custom.h"
|
|
12
|
+
|
|
13
|
+
namespace facebook::react {
|
|
16
14
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
};*/
|
|
15
|
+
/**
|
|
16
|
+
* Custom component descriptor that uses our measuring shadow node
|
|
17
|
+
* instead of the generated one.
|
|
18
|
+
*/
|
|
19
|
+
using MeasuringPCSelectionMenuComponentDescriptor =
|
|
20
|
+
ConcreteComponentDescriptor<MeasuringPCSelectionMenuShadowNode>;
|
|
24
21
|
|
|
25
22
|
} // namespace facebook::react
|
|
@@ -1,36 +1,57 @@
|
|
|
1
|
-
#include <react/renderer/core/LayoutConstraints.h>
|
|
2
1
|
#include "PCSelectionMenuShadowNode-custom.h"
|
|
3
2
|
|
|
3
|
+
#include <react/renderer/core/LayoutConstraints.h>
|
|
4
4
|
#include <algorithm>
|
|
5
5
|
|
|
6
6
|
namespace facebook::react {
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const Float kHuge = static_cast<Float>(1.0e9);
|
|
8
|
+
Size MeasuringPCSelectionMenuShadowNode::measureContent(
|
|
9
|
+
const LayoutContext& /*layoutContext*/,
|
|
10
|
+
const LayoutConstraints& layoutConstraints) const {
|
|
13
11
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
const auto& props = *std::static_pointer_cast<const PCSelectionMenuProps>(getProps());
|
|
18
|
-
const bool inlineMode = props.anchorMode == "inline";
|
|
12
|
+
const auto& props = *std::static_pointer_cast<const PCSelectionMenuProps>(getProps());
|
|
13
|
+
const bool inlineMode = props.anchorMode == "inline";
|
|
19
14
|
|
|
20
|
-
|
|
15
|
+
// Headless mode: zero size
|
|
16
|
+
if (!inlineMode) {
|
|
17
|
+
return layoutConstraints.clamp(Size{0, 0});
|
|
18
|
+
}
|
|
21
19
|
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
// Get frame size from native state - native measures the actual picker
|
|
21
|
+
const auto& stateData = this->getStateData();
|
|
22
|
+
Float measuredW = stateData.frameSize.width;
|
|
23
|
+
Float measuredH = stateData.frameSize.height;
|
|
24
|
+
|
|
25
|
+
// If height is 0, use fallback values (state not yet set by native)
|
|
26
|
+
if (measuredH <= 0) {
|
|
27
|
+
#ifdef __ANDROID__
|
|
28
|
+
const std::string& material = props.android.material;
|
|
29
|
+
if (material == "m3") {
|
|
30
|
+
measuredH = static_cast<Float>(kFallbackHeightAndroidM3);
|
|
24
31
|
} else {
|
|
25
|
-
measuredH =
|
|
32
|
+
measuredH = static_cast<Float>(kFallbackHeightAndroid);
|
|
26
33
|
}
|
|
34
|
+
#else
|
|
35
|
+
measuredH = static_cast<Float>(kFallbackHeightIOS);
|
|
36
|
+
#endif
|
|
37
|
+
}
|
|
27
38
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
return layoutConstraints.clamp(result);
|
|
39
|
+
// If width is 0, use available width from constraints
|
|
40
|
+
const Float kHuge = static_cast<Float>(1.0e9);
|
|
41
|
+
if (measuredW <= 0) {
|
|
42
|
+
const Float maxW = layoutConstraints.maximumSize.width;
|
|
43
|
+
measuredW = (maxW > 0 && maxW < kHuge) ? maxW : 0;
|
|
34
44
|
}
|
|
35
45
|
|
|
46
|
+
// Respect layout constraints
|
|
47
|
+
measuredW = std::max<Float>(measuredW, layoutConstraints.minimumSize.width);
|
|
48
|
+
measuredW = std::min<Float>(measuredW, layoutConstraints.maximumSize.width);
|
|
49
|
+
|
|
50
|
+
measuredH = std::max<Float>(measuredH, layoutConstraints.minimumSize.height);
|
|
51
|
+
measuredH = std::min<Float>(measuredH, layoutConstraints.maximumSize.height);
|
|
52
|
+
|
|
53
|
+
Size result{measuredW, measuredH};
|
|
54
|
+
return layoutConstraints.clamp(result);
|
|
55
|
+
}
|
|
56
|
+
|
|
36
57
|
} // namespace facebook::react
|
|
@@ -2,31 +2,43 @@
|
|
|
2
2
|
|
|
3
3
|
#include <react/renderer/components/view/ConcreteViewShadowNode.h>
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
#
|
|
5
|
+
// Only include what we need for the shadow node definition
|
|
6
|
+
// Do NOT include ComponentDescriptors.h here to avoid circular dependency
|
|
7
|
+
#include <react/renderer/components/PlatformComponentsViewSpec/EventEmitters.h>
|
|
8
|
+
#include <react/renderer/components/PlatformComponentsViewSpec/Props.h>
|
|
9
|
+
|
|
10
|
+
#include "PCSelectionMenuState-custom.h"
|
|
8
11
|
|
|
9
12
|
namespace facebook::react {
|
|
10
13
|
|
|
11
14
|
extern const char PCSelectionMenuComponentName[];
|
|
12
15
|
|
|
13
16
|
/**
|
|
14
|
-
* ShadowNode for SelectionMenu.
|
|
17
|
+
* Custom ShadowNode for SelectionMenu that supports Yoga measurement.
|
|
15
18
|
*
|
|
16
19
|
* Key behavior:
|
|
17
|
-
* -
|
|
18
|
-
*
|
|
20
|
+
* - Native side measures the actual picker and updates state with frameSize
|
|
21
|
+
* - measureContent() returns the size from state for proper Yoga layout
|
|
22
|
+
* - Falls back to platform-specific defaults if state hasn't been set yet
|
|
19
23
|
*/
|
|
20
24
|
class MeasuringPCSelectionMenuShadowNode final : public ConcreteViewShadowNode<
|
|
21
25
|
PCSelectionMenuComponentName,
|
|
22
26
|
PCSelectionMenuProps,
|
|
23
27
|
PCSelectionMenuEventEmitter,
|
|
24
|
-
|
|
28
|
+
PCSelectionMenuStateFrameSize> {
|
|
25
29
|
public:
|
|
26
30
|
using ConcreteViewShadowNode::ConcreteViewShadowNode;
|
|
27
31
|
|
|
28
|
-
|
|
29
|
-
|
|
32
|
+
// Fallback heights used when native hasn't reported measurements yet
|
|
33
|
+
// iOS standard row height
|
|
34
|
+
static constexpr float kFallbackHeightIOS = 44.0f;
|
|
35
|
+
|
|
36
|
+
// Android System Spinner height
|
|
37
|
+
static constexpr float kFallbackHeightAndroid = 56.0f;
|
|
38
|
+
|
|
39
|
+
// Android M3 TextInputLayout with floating label height
|
|
40
|
+
static constexpr float kFallbackHeightAndroidM3 = 72.0f;
|
|
41
|
+
|
|
30
42
|
static ShadowNodeTraits BaseTraits() {
|
|
31
43
|
auto traits = ConcreteViewShadowNode::BaseTraits();
|
|
32
44
|
traits.set(ShadowNodeTraits::Trait::LeafYogaNode);
|
|
@@ -36,7 +48,8 @@ class MeasuringPCSelectionMenuShadowNode final : public ConcreteViewShadowNode<
|
|
|
36
48
|
|
|
37
49
|
/**
|
|
38
50
|
* Called by Yoga when it needs the intrinsic size of the component.
|
|
39
|
-
*
|
|
51
|
+
* Returns the size provided by native through state, with fallback to
|
|
52
|
+
* platform-specific defaults if state hasn't been set.
|
|
40
53
|
*/
|
|
41
54
|
Size measureContent(
|
|
42
55
|
const LayoutContext& layoutContext,
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <react/renderer/core/LayoutPrimitives.h>
|
|
4
|
+
#include <memory>
|
|
5
|
+
|
|
6
|
+
#ifdef RN_SERIALIZABLE_STATE
|
|
7
|
+
#include <folly/dynamic.h>
|
|
8
|
+
#include <react/renderer/mapbuffer/MapBuffer.h>
|
|
9
|
+
#include <react/renderer/mapbuffer/MapBufferBuilder.h>
|
|
10
|
+
#endif
|
|
11
|
+
|
|
12
|
+
namespace facebook::react {
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Custom state for SelectionMenu that holds the measured frame size from native.
|
|
16
|
+
* This allows the native side to measure the actual picker and communicate
|
|
17
|
+
* the size to the shadow node for proper Yoga layout.
|
|
18
|
+
*
|
|
19
|
+
* Note: Does NOT inherit from StateData (which is final). Custom state types
|
|
20
|
+
* are standalone structs that satisfy the ConcreteState template requirements.
|
|
21
|
+
*/
|
|
22
|
+
struct PCSelectionMenuStateFrameSize {
|
|
23
|
+
using Shared = std::shared_ptr<const PCSelectionMenuStateFrameSize>;
|
|
24
|
+
|
|
25
|
+
Size frameSize{}; // {width, height} in points
|
|
26
|
+
|
|
27
|
+
PCSelectionMenuStateFrameSize() = default;
|
|
28
|
+
|
|
29
|
+
explicit PCSelectionMenuStateFrameSize(Size size) : frameSize(size) {}
|
|
30
|
+
|
|
31
|
+
bool operator==(const PCSelectionMenuStateFrameSize& other) const {
|
|
32
|
+
return frameSize.width == other.frameSize.width &&
|
|
33
|
+
frameSize.height == other.frameSize.height;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
bool operator!=(const PCSelectionMenuStateFrameSize& other) const {
|
|
37
|
+
return !(*this == other);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
#ifdef RN_SERIALIZABLE_STATE
|
|
41
|
+
// Required for Android state serialization
|
|
42
|
+
PCSelectionMenuStateFrameSize(
|
|
43
|
+
const PCSelectionMenuStateFrameSize& previousState,
|
|
44
|
+
folly::dynamic data)
|
|
45
|
+
: frameSize(previousState.frameSize) {
|
|
46
|
+
// Parse frame size from dynamic data if provided
|
|
47
|
+
if (data.isObject()) {
|
|
48
|
+
if (data.count("width") && data.count("height")) {
|
|
49
|
+
frameSize.width = static_cast<Float>(data["width"].asDouble());
|
|
50
|
+
frameSize.height = static_cast<Float>(data["height"].asDouble());
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
folly::dynamic getDynamic() const {
|
|
56
|
+
return folly::dynamic::object("width", frameSize.width)("height", frameSize.height);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
MapBuffer getMapBuffer() const {
|
|
60
|
+
return MapBufferBuilder::EMPTY();
|
|
61
|
+
}
|
|
62
|
+
#endif
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
} // namespace facebook::react
|