react-native-platform-components 0.6.0 → 0.7.0
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 +211 -44
- package/android/src/main/java/com/platformcomponents/PCContextMenuView.kt +2 -2
- package/android/src/main/java/com/platformcomponents/PCSegmentedControlView.kt +241 -0
- package/android/src/main/java/com/platformcomponents/PCSegmentedControlViewManager.kt +105 -0
- package/android/src/main/java/com/platformcomponents/PCSelectionMenuView.kt +4 -0
- package/android/src/main/java/com/platformcomponents/PlatformComponentsPackage.kt +1 -0
- package/app.plugin.cjs +4 -0
- package/expo-module.config.json +4 -0
- package/ios/PCContextMenu.swift +65 -22
- package/ios/PCDatePickerView.swift +28 -11
- package/ios/PCSegmentedControl.h +10 -0
- package/ios/PCSegmentedControl.mm +194 -0
- package/ios/PCSegmentedControl.swift +200 -0
- package/lib/commonjs/ContextMenu.js +118 -0
- package/lib/commonjs/ContextMenu.js.map +1 -0
- package/lib/commonjs/ContextMenuNativeComponent.ts +141 -0
- package/lib/commonjs/DatePicker.js +86 -0
- package/lib/commonjs/DatePicker.js.map +1 -0
- package/lib/commonjs/DatePickerNativeComponent.ts +69 -0
- package/lib/commonjs/SegmentedControl.js +93 -0
- package/lib/commonjs/SegmentedControl.js.map +1 -0
- package/lib/commonjs/SegmentedControlNativeComponent.ts +79 -0
- package/lib/commonjs/SelectionMenu.js +73 -0
- package/lib/commonjs/SelectionMenu.js.map +1 -0
- package/lib/commonjs/SelectionMenuNativeComponent.ts +97 -0
- package/lib/commonjs/index.js +61 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/package.json +1 -0
- package/lib/commonjs/sharedTypes.js +6 -0
- package/lib/commonjs/sharedTypes.js.map +1 -0
- package/lib/module/SegmentedControl.js +87 -0
- package/lib/module/SegmentedControl.js.map +1 -0
- package/lib/module/SegmentedControlNativeComponent.ts +79 -0
- package/lib/module/index.js +1 -0
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/commonjs/package.json +1 -0
- package/lib/typescript/commonjs/src/ContextMenu.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/ContextMenuNativeComponent.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/DatePicker.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/DatePickerNativeComponent.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/SegmentedControl.d.ts +62 -0
- package/lib/typescript/commonjs/src/SegmentedControl.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/SegmentedControlNativeComponent.d.ts +63 -0
- package/lib/typescript/commonjs/src/SegmentedControlNativeComponent.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/SelectionMenu.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/SelectionMenuNativeComponent.d.ts.map +1 -0
- package/lib/typescript/{src → commonjs/src}/index.d.ts +1 -0
- package/lib/typescript/commonjs/src/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/sharedTypes.d.ts.map +1 -0
- package/lib/typescript/module/src/ContextMenu.d.ts +79 -0
- package/lib/typescript/module/src/ContextMenu.d.ts.map +1 -0
- package/lib/typescript/module/src/ContextMenuNativeComponent.d.ts +122 -0
- package/lib/typescript/module/src/ContextMenuNativeComponent.d.ts.map +1 -0
- package/lib/typescript/module/src/DatePicker.d.ts +40 -0
- package/lib/typescript/module/src/DatePicker.d.ts.map +1 -0
- package/lib/typescript/module/src/DatePickerNativeComponent.d.ts +54 -0
- package/lib/typescript/module/src/DatePickerNativeComponent.d.ts.map +1 -0
- package/lib/typescript/module/src/SegmentedControl.d.ts +62 -0
- package/lib/typescript/module/src/SegmentedControl.d.ts.map +1 -0
- package/lib/typescript/module/src/SegmentedControlNativeComponent.d.ts +63 -0
- package/lib/typescript/module/src/SegmentedControlNativeComponent.d.ts.map +1 -0
- package/lib/typescript/module/src/SelectionMenu.d.ts +47 -0
- package/lib/typescript/module/src/SelectionMenu.d.ts.map +1 -0
- package/lib/typescript/module/src/SelectionMenuNativeComponent.d.ts +78 -0
- package/lib/typescript/module/src/SelectionMenuNativeComponent.d.ts.map +1 -0
- package/lib/typescript/module/src/index.d.ts +6 -0
- package/lib/typescript/module/src/index.d.ts.map +1 -0
- package/lib/typescript/module/src/sharedTypes.d.ts +12 -0
- package/lib/typescript/module/src/sharedTypes.d.ts.map +1 -0
- package/package.json +32 -12
- package/plugin/build/index.cjs +26 -0
- package/plugin/build/index.d.ts +22 -0
- package/plugin/build/index.d.ts.map +1 -0
- package/plugin/tsconfig.json +16 -0
- package/react-native.config.js +1 -0
- package/shared/PCSegmentedControlComponentDescriptors-custom.h +22 -0
- package/shared/PCSegmentedControlShadowNode-custom.cpp +54 -0
- package/shared/PCSegmentedControlShadowNode-custom.h +56 -0
- package/shared/PCSegmentedControlState-custom.h +62 -0
- package/shared/react/renderer/components/PlatformComponentsViewSpec/ComponentDescriptors.h +1 -0
- package/src/SegmentedControl.tsx +178 -0
- package/src/SegmentedControlNativeComponent.ts +79 -0
- package/src/index.tsx +1 -0
- package/lib/typescript/src/ContextMenu.d.ts.map +0 -1
- package/lib/typescript/src/ContextMenuNativeComponent.d.ts.map +0 -1
- package/lib/typescript/src/DatePicker.d.ts.map +0 -1
- package/lib/typescript/src/DatePickerNativeComponent.d.ts.map +0 -1
- package/lib/typescript/src/SelectionMenu.d.ts.map +0 -1
- package/lib/typescript/src/SelectionMenuNativeComponent.d.ts.map +0 -1
- package/lib/typescript/src/index.d.ts.map +0 -1
- package/lib/typescript/src/sharedTypes.d.ts.map +0 -1
- /package/lib/typescript/{src → commonjs/src}/ContextMenu.d.ts +0 -0
- /package/lib/typescript/{src → commonjs/src}/ContextMenuNativeComponent.d.ts +0 -0
- /package/lib/typescript/{src → commonjs/src}/DatePicker.d.ts +0 -0
- /package/lib/typescript/{src → commonjs/src}/DatePickerNativeComponent.d.ts +0 -0
- /package/lib/typescript/{src → commonjs/src}/SelectionMenu.d.ts +0 -0
- /package/lib/typescript/{src → commonjs/src}/SelectionMenuNativeComponent.d.ts +0 -0
- /package/lib/typescript/{src → commonjs/src}/sharedTypes.d.ts +0 -0
- /package/lib/typescript/{package.json → module/package.json} +0 -0
package/package.json
CHANGED
|
@@ -1,16 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-platform-components",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
5
|
-
"main": "./lib/
|
|
6
|
-
"
|
|
3
|
+
"version": "0.7.0",
|
|
4
|
+
"description": "Native UI components for React Native: DatePicker, ContextMenu, SelectionMenu, SegmentedControl.",
|
|
5
|
+
"main": "./lib/commonjs/index.js",
|
|
6
|
+
"module": "./lib/module/index.js",
|
|
7
|
+
"types": "./lib/typescript/commonjs/src/index.d.ts",
|
|
7
8
|
"exports": {
|
|
8
9
|
".": {
|
|
9
10
|
"source": "./src/index.tsx",
|
|
10
|
-
"
|
|
11
|
-
|
|
11
|
+
"import": {
|
|
12
|
+
"types": "./lib/typescript/module/src/index.d.ts",
|
|
13
|
+
"default": "./lib/module/index.js"
|
|
14
|
+
},
|
|
15
|
+
"require": {
|
|
16
|
+
"types": "./lib/typescript/commonjs/src/index.d.ts",
|
|
17
|
+
"default": "./lib/commonjs/index.js"
|
|
18
|
+
}
|
|
12
19
|
},
|
|
13
|
-
"./package.json": "./package.json"
|
|
20
|
+
"./package.json": "./package.json",
|
|
21
|
+
"./app.plugin": "./app.plugin.cjs"
|
|
14
22
|
},
|
|
15
23
|
"files": [
|
|
16
24
|
"src",
|
|
@@ -19,14 +27,18 @@
|
|
|
19
27
|
"android",
|
|
20
28
|
"ios",
|
|
21
29
|
"cpp",
|
|
30
|
+
"plugin",
|
|
22
31
|
"*.podspec",
|
|
23
32
|
"react-native.config.js",
|
|
33
|
+
"app.plugin.cjs",
|
|
34
|
+
"expo-module.config.json",
|
|
24
35
|
"!ios/build",
|
|
25
36
|
"!android/build",
|
|
26
37
|
"!android/gradle",
|
|
27
38
|
"!android/gradlew",
|
|
28
39
|
"!android/gradlew.bat",
|
|
29
40
|
"!android/local.properties",
|
|
41
|
+
"!plugin/src",
|
|
30
42
|
"!**/__tests__",
|
|
31
43
|
"!**/__fixtures__",
|
|
32
44
|
"!**/__mocks__",
|
|
@@ -34,11 +46,13 @@
|
|
|
34
46
|
],
|
|
35
47
|
"scripts": {
|
|
36
48
|
"example": "yarn workspace react-native-platform-components-example",
|
|
37
|
-
"
|
|
38
|
-
"
|
|
49
|
+
"example-expo": "yarn workspace react-native-platform-components-example-expo",
|
|
50
|
+
"clean": "del-cli android/build example/android/build example/android/app/build example/ios/build lib plugin/build",
|
|
51
|
+
"prepare": "bob build && yarn build:plugin",
|
|
39
52
|
"typecheck": "tsc",
|
|
40
53
|
"lint": "eslint \"**/*.{js,ts,tsx}\"",
|
|
41
54
|
"build": "tsc --noEmit",
|
|
55
|
+
"build:plugin": "tsc -p plugin/tsconfig.json && mv plugin/build/index.js plugin/build/index.cjs",
|
|
42
56
|
"release": "release-it",
|
|
43
57
|
"test": "jest",
|
|
44
58
|
"upgrade:check": "yarn dlx npm-check-updates",
|
|
@@ -58,7 +72,8 @@
|
|
|
58
72
|
"context-menu",
|
|
59
73
|
"dropdown",
|
|
60
74
|
"native",
|
|
61
|
-
"material-design"
|
|
75
|
+
"material-design",
|
|
76
|
+
"expo"
|
|
62
77
|
],
|
|
63
78
|
"repository": {
|
|
64
79
|
"type": "git",
|
|
@@ -78,6 +93,7 @@
|
|
|
78
93
|
"@eslint/compat": "^2.0.1",
|
|
79
94
|
"@eslint/eslintrc": "^3.3.3",
|
|
80
95
|
"@eslint/js": "^9.39.2",
|
|
96
|
+
"@expo/config-plugins": "^54.0.4",
|
|
81
97
|
"@react-native-community/cli": "20.1.0",
|
|
82
98
|
"@react-native/babel-preset": "0.83.1",
|
|
83
99
|
"@react-native/eslint-config": "^0.83.1",
|
|
@@ -85,6 +101,7 @@
|
|
|
85
101
|
"@types/jest": "^30.0.0",
|
|
86
102
|
"@types/react": "^19.2.9",
|
|
87
103
|
"@types/react-test-renderer": "^19.1.0",
|
|
104
|
+
"babel-preset-expo": "^54.0.10",
|
|
88
105
|
"commitlint": "^20.3.1",
|
|
89
106
|
"del-cli": "^7.0.0",
|
|
90
107
|
"eslint": "^9.39.2",
|
|
@@ -106,13 +123,15 @@
|
|
|
106
123
|
"react-native": "*"
|
|
107
124
|
},
|
|
108
125
|
"workspaces": [
|
|
109
|
-
"example"
|
|
126
|
+
"example",
|
|
127
|
+
"example-expo"
|
|
110
128
|
],
|
|
111
129
|
"packageManager": "yarn@4.11.0",
|
|
112
130
|
"react-native-builder-bob": {
|
|
113
131
|
"source": "src",
|
|
114
132
|
"output": "lib",
|
|
115
133
|
"targets": [
|
|
134
|
+
"commonjs",
|
|
116
135
|
[
|
|
117
136
|
"module",
|
|
118
137
|
{
|
|
@@ -138,7 +157,8 @@
|
|
|
138
157
|
"componentProvider": {
|
|
139
158
|
"PCSelectionMenu": "PCSelectionMenu",
|
|
140
159
|
"PCDatePicker": "PCDatePicker",
|
|
141
|
-
"PCContextMenu": "PCContextMenu"
|
|
160
|
+
"PCContextMenu": "PCContextMenu",
|
|
161
|
+
"PCSegmentedControl": "PCSegmentedControl"
|
|
142
162
|
}
|
|
143
163
|
}
|
|
144
164
|
},
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
/**
|
|
4
|
+
* Expo config plugin for react-native-platform-components.
|
|
5
|
+
*
|
|
6
|
+
* This library requires no manual native configuration on either iOS or Android.
|
|
7
|
+
* The native modules are automatically linked via Expo prebuild and React Native's
|
|
8
|
+
* autolinking system.
|
|
9
|
+
*
|
|
10
|
+
* iOS:
|
|
11
|
+
* - Pod linkage works automatically via the standard podspec
|
|
12
|
+
* - No Info.plist, entitlements, or AppDelegate changes required
|
|
13
|
+
*
|
|
14
|
+
* Android:
|
|
15
|
+
* - Gradle linkage works automatically via autolinking
|
|
16
|
+
* - No AndroidManifest.xml, theme, or permission changes required
|
|
17
|
+
*
|
|
18
|
+
* This plugin is provided for discoverability and to enable future configuration
|
|
19
|
+
* options if needed. Running prebuild multiple times is idempotent.
|
|
20
|
+
*/
|
|
21
|
+
const withPlatformComponents = (config) => {
|
|
22
|
+
// No-op plugin: react-native-platform-components requires no native configuration
|
|
23
|
+
// beyond standard autolinking which Expo prebuild handles automatically.
|
|
24
|
+
return config;
|
|
25
|
+
};
|
|
26
|
+
exports.default = withPlatformComponents;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { ConfigPlugin } from '@expo/config-plugins';
|
|
2
|
+
/**
|
|
3
|
+
* Expo config plugin for react-native-platform-components.
|
|
4
|
+
*
|
|
5
|
+
* This library requires no manual native configuration on either iOS or Android.
|
|
6
|
+
* The native modules are automatically linked via Expo prebuild and React Native's
|
|
7
|
+
* autolinking system.
|
|
8
|
+
*
|
|
9
|
+
* iOS:
|
|
10
|
+
* - Pod linkage works automatically via the standard podspec
|
|
11
|
+
* - No Info.plist, entitlements, or AppDelegate changes required
|
|
12
|
+
*
|
|
13
|
+
* Android:
|
|
14
|
+
* - Gradle linkage works automatically via autolinking
|
|
15
|
+
* - No AndroidManifest.xml, theme, or permission changes required
|
|
16
|
+
*
|
|
17
|
+
* This plugin is provided for discoverability and to enable future configuration
|
|
18
|
+
* options if needed. Running prebuild multiple times is idempotent.
|
|
19
|
+
*/
|
|
20
|
+
declare const withPlatformComponents: ConfigPlugin;
|
|
21
|
+
export default withPlatformComponents;
|
|
22
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEzD;;;;;;;;;;;;;;;;;GAiBG;AAEH,QAAA,MAAM,sBAAsB,EAAE,YAI7B,CAAC;AAEF,eAAe,sBAAsB,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"module": "CommonJS",
|
|
5
|
+
"moduleResolution": "node",
|
|
6
|
+
"strict": true,
|
|
7
|
+
"esModuleInterop": true,
|
|
8
|
+
"skipLibCheck": true,
|
|
9
|
+
"declaration": true,
|
|
10
|
+
"declarationMap": true,
|
|
11
|
+
"outDir": "build",
|
|
12
|
+
"rootDir": "src"
|
|
13
|
+
},
|
|
14
|
+
"include": ["src/**/*"],
|
|
15
|
+
"exclude": ["node_modules"]
|
|
16
|
+
}
|
package/react-native.config.js
CHANGED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <react/renderer/core/ConcreteComponentDescriptor.h>
|
|
4
|
+
|
|
5
|
+
// Forward declaration to avoid circular includes
|
|
6
|
+
namespace facebook::react {
|
|
7
|
+
class MeasuringPCSegmentedControlShadowNode;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// Include the actual shadow node definition
|
|
11
|
+
#include "PCSegmentedControlShadowNode-custom.h"
|
|
12
|
+
|
|
13
|
+
namespace facebook::react {
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Custom component descriptor that uses our measuring shadow node
|
|
17
|
+
* instead of the generated one.
|
|
18
|
+
*/
|
|
19
|
+
using MeasuringPCSegmentedControlComponentDescriptor =
|
|
20
|
+
ConcreteComponentDescriptor<MeasuringPCSegmentedControlShadowNode>;
|
|
21
|
+
|
|
22
|
+
} // namespace facebook::react
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
#include "PCSegmentedControlShadowNode-custom.h"
|
|
2
|
+
|
|
3
|
+
#include <react/renderer/core/LayoutConstraints.h>
|
|
4
|
+
#include <algorithm>
|
|
5
|
+
|
|
6
|
+
namespace facebook::react {
|
|
7
|
+
|
|
8
|
+
Size MeasuringPCSegmentedControlShadowNode::measureContent(
|
|
9
|
+
const LayoutContext& /*layoutContext*/,
|
|
10
|
+
const LayoutConstraints& layoutConstraints) const {
|
|
11
|
+
|
|
12
|
+
// Get frame size from native state - native measures the actual control
|
|
13
|
+
const auto& stateData = this->getStateData();
|
|
14
|
+
Float measuredW = stateData.frameSize.width;
|
|
15
|
+
Float measuredH = stateData.frameSize.height;
|
|
16
|
+
|
|
17
|
+
// Platform-specific fallback heights
|
|
18
|
+
const Float fallbackHeight =
|
|
19
|
+
#ifdef __ANDROID__
|
|
20
|
+
static_cast<Float>(kFallbackHeightAndroid);
|
|
21
|
+
#else
|
|
22
|
+
static_cast<Float>(kFallbackHeightIOS);
|
|
23
|
+
#endif
|
|
24
|
+
|
|
25
|
+
// If height is 0, use fallback (state not yet set by native)
|
|
26
|
+
const bool usingFallback = (measuredH <= 0);
|
|
27
|
+
if (usingFallback) {
|
|
28
|
+
measuredH = fallbackHeight;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// If width is 0, use available width from constraints
|
|
32
|
+
const Float kHuge = static_cast<Float>(1.0e9);
|
|
33
|
+
if (measuredW <= 0) {
|
|
34
|
+
const Float maxW = layoutConstraints.maximumSize.width;
|
|
35
|
+
measuredW = (maxW > 0 && maxW < kHuge) ? maxW : 300;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Respect layout constraints, but if using fallback height,
|
|
39
|
+
// don't let maximum constraint override our fallback
|
|
40
|
+
measuredW = std::max<Float>(measuredW, layoutConstraints.minimumSize.width);
|
|
41
|
+
if (layoutConstraints.maximumSize.width > 0 && layoutConstraints.maximumSize.width < kHuge) {
|
|
42
|
+
measuredW = std::min<Float>(measuredW, layoutConstraints.maximumSize.width);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
measuredH = std::max<Float>(measuredH, layoutConstraints.minimumSize.height);
|
|
46
|
+
// Only clamp to max height if we have real measured data (not fallback)
|
|
47
|
+
if (!usingFallback && layoutConstraints.maximumSize.height > 0 && layoutConstraints.maximumSize.height < kHuge) {
|
|
48
|
+
measuredH = std::min<Float>(measuredH, layoutConstraints.maximumSize.height);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return Size{measuredW, measuredH};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
} // namespace facebook::react
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
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
|
|
7
|
+
#include <react/renderer/components/PlatformComponentsViewSpec/EventEmitters.h>
|
|
8
|
+
#include <react/renderer/components/PlatformComponentsViewSpec/Props.h>
|
|
9
|
+
|
|
10
|
+
#include "PCSegmentedControlState-custom.h"
|
|
11
|
+
|
|
12
|
+
namespace facebook::react {
|
|
13
|
+
|
|
14
|
+
extern const char PCSegmentedControlComponentName[];
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Custom ShadowNode for SegmentedControl that supports Yoga measurement.
|
|
18
|
+
*
|
|
19
|
+
* Key behavior:
|
|
20
|
+
* - Native side measures the actual segmented control 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
|
|
23
|
+
*/
|
|
24
|
+
class MeasuringPCSegmentedControlShadowNode final : public ConcreteViewShadowNode<
|
|
25
|
+
PCSegmentedControlComponentName,
|
|
26
|
+
PCSegmentedControlProps,
|
|
27
|
+
PCSegmentedControlEventEmitter,
|
|
28
|
+
PCSegmentedControlStateFrameSize> {
|
|
29
|
+
public:
|
|
30
|
+
using ConcreteViewShadowNode::ConcreteViewShadowNode;
|
|
31
|
+
|
|
32
|
+
// Fallback heights used when native hasn't reported measurements yet
|
|
33
|
+
// iOS UISegmentedControl default height
|
|
34
|
+
static constexpr float kFallbackHeightIOS = 32.0f;
|
|
35
|
+
|
|
36
|
+
// Android MaterialButtonToggleGroup height
|
|
37
|
+
static constexpr float kFallbackHeightAndroid = 48.0f;
|
|
38
|
+
|
|
39
|
+
static ShadowNodeTraits BaseTraits() {
|
|
40
|
+
auto traits = ConcreteViewShadowNode::BaseTraits();
|
|
41
|
+
traits.set(ShadowNodeTraits::Trait::LeafYogaNode);
|
|
42
|
+
traits.set(ShadowNodeTraits::Trait::MeasurableYogaNode);
|
|
43
|
+
return traits;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Called by Yoga when it needs the intrinsic size of the component.
|
|
48
|
+
* Returns the size provided by native through state, with fallback to
|
|
49
|
+
* platform-specific defaults if state hasn't been set.
|
|
50
|
+
*/
|
|
51
|
+
Size measureContent(
|
|
52
|
+
const LayoutContext& layoutContext,
|
|
53
|
+
const LayoutConstraints& layoutConstraints) const override;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
} // namespace facebook::react
|
|
@@ -0,0 +1,62 @@
|
|
|
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 SegmentedControl that holds the measured frame size from native.
|
|
16
|
+
* This allows the native side to measure the actual segmented control and communicate
|
|
17
|
+
* the size to the shadow node for proper Yoga layout.
|
|
18
|
+
*/
|
|
19
|
+
struct PCSegmentedControlStateFrameSize {
|
|
20
|
+
using Shared = std::shared_ptr<const PCSegmentedControlStateFrameSize>;
|
|
21
|
+
|
|
22
|
+
Size frameSize{}; // {width, height} in points
|
|
23
|
+
|
|
24
|
+
PCSegmentedControlStateFrameSize() = default;
|
|
25
|
+
|
|
26
|
+
explicit PCSegmentedControlStateFrameSize(Size size) : frameSize(size) {}
|
|
27
|
+
|
|
28
|
+
bool operator==(const PCSegmentedControlStateFrameSize& other) const {
|
|
29
|
+
return frameSize.width == other.frameSize.width &&
|
|
30
|
+
frameSize.height == other.frameSize.height;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
bool operator!=(const PCSegmentedControlStateFrameSize& other) const {
|
|
34
|
+
return !(*this == other);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
#ifdef RN_SERIALIZABLE_STATE
|
|
38
|
+
// Required for Android state serialization
|
|
39
|
+
PCSegmentedControlStateFrameSize(
|
|
40
|
+
const PCSegmentedControlStateFrameSize& previousState,
|
|
41
|
+
folly::dynamic data)
|
|
42
|
+
: frameSize(previousState.frameSize) {
|
|
43
|
+
// Parse frame size from dynamic data if provided
|
|
44
|
+
if (data.isObject()) {
|
|
45
|
+
if (data.count("width") && data.count("height")) {
|
|
46
|
+
frameSize.width = static_cast<Float>(data["width"].asDouble());
|
|
47
|
+
frameSize.height = static_cast<Float>(data["height"].asDouble());
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
folly::dynamic getDynamic() const {
|
|
53
|
+
return folly::dynamic::object("width", frameSize.width)("height", frameSize.height);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
MapBuffer getMapBuffer() const {
|
|
57
|
+
return MapBufferBuilder::EMPTY();
|
|
58
|
+
}
|
|
59
|
+
#endif
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
} // namespace facebook::react
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
// SegmentedControl.tsx
|
|
2
|
+
import React, { useCallback, useMemo } from 'react';
|
|
3
|
+
import {
|
|
4
|
+
Platform,
|
|
5
|
+
StyleSheet,
|
|
6
|
+
type StyleProp,
|
|
7
|
+
type ViewProps,
|
|
8
|
+
type ViewStyle,
|
|
9
|
+
} from 'react-native';
|
|
10
|
+
|
|
11
|
+
import NativeSegmentedControl, {
|
|
12
|
+
type SegmentedControlSelectEvent,
|
|
13
|
+
} from './SegmentedControlNativeComponent';
|
|
14
|
+
|
|
15
|
+
// Android: Minimum height to ensure visibility.
|
|
16
|
+
// Fabric's shadow node measurement isn't being called on initial render,
|
|
17
|
+
// so we apply a minHeight that matches Material design touch target guidelines.
|
|
18
|
+
const ANDROID_MIN_HEIGHT = 48;
|
|
19
|
+
|
|
20
|
+
export interface SegmentedControlSegmentProps {
|
|
21
|
+
/** Display label for the segment */
|
|
22
|
+
label: string;
|
|
23
|
+
|
|
24
|
+
/** Unique value identifier for the segment */
|
|
25
|
+
value: string;
|
|
26
|
+
|
|
27
|
+
/** Whether this specific segment is disabled */
|
|
28
|
+
disabled?: boolean;
|
|
29
|
+
|
|
30
|
+
/** Optional SF Symbol name (iOS) or drawable resource name (Android) */
|
|
31
|
+
icon?: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface SegmentedControlProps extends ViewProps {
|
|
35
|
+
/** Array of segments to display */
|
|
36
|
+
segments: readonly SegmentedControlSegmentProps[];
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Currently selected segment value.
|
|
40
|
+
* Use `null` for no selection.
|
|
41
|
+
*/
|
|
42
|
+
selectedValue: string | null;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Called when the user selects a segment.
|
|
46
|
+
* @param value - The selected segment's value
|
|
47
|
+
* @param index - The selected segment's index
|
|
48
|
+
*/
|
|
49
|
+
onSelect?: (value: string, index: number) => void;
|
|
50
|
+
|
|
51
|
+
/** Whether the entire control is disabled */
|
|
52
|
+
disabled?: boolean;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* iOS-specific configuration
|
|
56
|
+
*/
|
|
57
|
+
ios?: {
|
|
58
|
+
/**
|
|
59
|
+
* Momentary mode: segment springs back after touch (no persistent selection)
|
|
60
|
+
* Default: false
|
|
61
|
+
*/
|
|
62
|
+
momentary?: boolean;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Whether segment widths are proportional to content
|
|
66
|
+
* Default: false (equal widths)
|
|
67
|
+
*/
|
|
68
|
+
apportionsSegmentWidthsByContent?: boolean;
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Selected segment tint color (hex string, e.g., "#007AFF")
|
|
72
|
+
*/
|
|
73
|
+
selectedSegmentTintColor?: string;
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Android-specific configuration
|
|
78
|
+
*/
|
|
79
|
+
android?: {
|
|
80
|
+
/**
|
|
81
|
+
* Whether one segment must always be selected.
|
|
82
|
+
* Default: false
|
|
83
|
+
*/
|
|
84
|
+
selectionRequired?: boolean;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
/** Test identifier */
|
|
88
|
+
testID?: string;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function normalizeSelectedValue(selected: string | null): string {
|
|
92
|
+
return selected ?? '';
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export function SegmentedControl(
|
|
96
|
+
props: SegmentedControlProps
|
|
97
|
+
): React.ReactElement {
|
|
98
|
+
const {
|
|
99
|
+
style,
|
|
100
|
+
segments,
|
|
101
|
+
selectedValue,
|
|
102
|
+
disabled,
|
|
103
|
+
onSelect,
|
|
104
|
+
ios,
|
|
105
|
+
android,
|
|
106
|
+
...viewProps
|
|
107
|
+
} = props;
|
|
108
|
+
|
|
109
|
+
// Normalize segments for native
|
|
110
|
+
const nativeSegments = useMemo(() => {
|
|
111
|
+
return segments.map((seg) => ({
|
|
112
|
+
label: seg.label,
|
|
113
|
+
value: seg.value,
|
|
114
|
+
disabled: seg.disabled ? 'disabled' : 'enabled',
|
|
115
|
+
icon: seg.icon ?? '',
|
|
116
|
+
}));
|
|
117
|
+
}, [segments]);
|
|
118
|
+
|
|
119
|
+
const selectedData = useMemo(
|
|
120
|
+
() => normalizeSelectedValue(selectedValue),
|
|
121
|
+
[selectedValue]
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
const handleSelect = useCallback(
|
|
125
|
+
(e: { nativeEvent: SegmentedControlSelectEvent }) => {
|
|
126
|
+
const { index, value } = e.nativeEvent;
|
|
127
|
+
onSelect?.(value, index);
|
|
128
|
+
},
|
|
129
|
+
[onSelect]
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
// Normalize iOS props to native string format
|
|
133
|
+
const nativeIos = useMemo(() => {
|
|
134
|
+
if (!ios) return undefined;
|
|
135
|
+
return {
|
|
136
|
+
momentary: ios.momentary ? 'true' : 'false',
|
|
137
|
+
apportionsSegmentWidthsByContent: ios.apportionsSegmentWidthsByContent
|
|
138
|
+
? 'true'
|
|
139
|
+
: 'false',
|
|
140
|
+
selectedSegmentTintColor: ios.selectedSegmentTintColor ?? '',
|
|
141
|
+
};
|
|
142
|
+
}, [ios]);
|
|
143
|
+
|
|
144
|
+
// Normalize Android props
|
|
145
|
+
const nativeAndroid = useMemo(() => {
|
|
146
|
+
if (!android) return undefined;
|
|
147
|
+
return {
|
|
148
|
+
selectionRequired: android.selectionRequired ? 'true' : 'false',
|
|
149
|
+
};
|
|
150
|
+
}, [android]);
|
|
151
|
+
|
|
152
|
+
// Merge user style with Android minHeight default
|
|
153
|
+
const mergedStyle = useMemo((): StyleProp<ViewStyle> => {
|
|
154
|
+
if (Platform.OS === 'android') {
|
|
155
|
+
return [styles.androidDefault, style];
|
|
156
|
+
}
|
|
157
|
+
return style;
|
|
158
|
+
}, [style]);
|
|
159
|
+
|
|
160
|
+
return (
|
|
161
|
+
<NativeSegmentedControl
|
|
162
|
+
style={mergedStyle}
|
|
163
|
+
segments={nativeSegments}
|
|
164
|
+
selectedValue={selectedData}
|
|
165
|
+
interactivity={disabled ? 'disabled' : 'enabled'}
|
|
166
|
+
onSelect={onSelect ? handleSelect : undefined}
|
|
167
|
+
ios={nativeIos}
|
|
168
|
+
android={nativeAndroid}
|
|
169
|
+
{...viewProps}
|
|
170
|
+
/>
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const styles = StyleSheet.create({
|
|
175
|
+
androidDefault: {
|
|
176
|
+
minHeight: ANDROID_MIN_HEIGHT,
|
|
177
|
+
},
|
|
178
|
+
});
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
// SegmentedControlNativeComponent.ts
|
|
2
|
+
import type { CodegenTypes, ViewProps } from 'react-native';
|
|
3
|
+
import { codegenNativeComponent } from 'react-native';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* A single segment in the control.
|
|
7
|
+
*/
|
|
8
|
+
export type SegmentedControlSegment = Readonly<{
|
|
9
|
+
label: string;
|
|
10
|
+
value: string;
|
|
11
|
+
disabled: string; // 'enabled' | 'disabled'
|
|
12
|
+
icon: string; // SF Symbol (iOS) or drawable name (Android), empty = none
|
|
13
|
+
}>;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Event emitted when the user selects a segment.
|
|
17
|
+
*/
|
|
18
|
+
export type SegmentedControlSelectEvent = Readonly<{
|
|
19
|
+
/** Selected segment index */
|
|
20
|
+
index: CodegenTypes.Int32;
|
|
21
|
+
|
|
22
|
+
/** Selected segment value */
|
|
23
|
+
value: string;
|
|
24
|
+
}>;
|
|
25
|
+
|
|
26
|
+
/** Interactivity state (no booleans). */
|
|
27
|
+
export type SegmentedControlInteractivity = 'enabled' | 'disabled';
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* iOS-specific configuration.
|
|
31
|
+
*/
|
|
32
|
+
export type IOSProps = Readonly<{
|
|
33
|
+
/** Momentary mode: segment springs back after touch */
|
|
34
|
+
momentary?: string; // 'true' | 'false'
|
|
35
|
+
|
|
36
|
+
/** Whether segment widths are proportional to content */
|
|
37
|
+
apportionsSegmentWidthsByContent?: string; // 'true' | 'false'
|
|
38
|
+
|
|
39
|
+
/** Selected segment tint color (hex string) */
|
|
40
|
+
selectedSegmentTintColor?: string;
|
|
41
|
+
}>;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Android-specific configuration.
|
|
45
|
+
*/
|
|
46
|
+
export type AndroidProps = Readonly<{
|
|
47
|
+
/** Whether one segment must always be selected */
|
|
48
|
+
selectionRequired?: string; // 'true' | 'false'
|
|
49
|
+
}>;
|
|
50
|
+
|
|
51
|
+
export interface SegmentedControlProps extends ViewProps {
|
|
52
|
+
/**
|
|
53
|
+
* Segments to display.
|
|
54
|
+
*/
|
|
55
|
+
segments: ReadonlyArray<SegmentedControlSegment>;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Controlled selection by `value`.
|
|
59
|
+
* Empty string means "no selection".
|
|
60
|
+
*/
|
|
61
|
+
selectedValue?: CodegenTypes.WithDefault<string, ''>;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Enabled / disabled state.
|
|
65
|
+
*/
|
|
66
|
+
interactivity?: string; // SegmentedControlInteractivity
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Fired when the user selects a segment.
|
|
70
|
+
*/
|
|
71
|
+
onSelect?: CodegenTypes.BubblingEventHandler<SegmentedControlSelectEvent>;
|
|
72
|
+
|
|
73
|
+
ios?: IOSProps;
|
|
74
|
+
android?: AndroidProps;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export default codegenNativeComponent<SegmentedControlProps>(
|
|
78
|
+
'PCSegmentedControl'
|
|
79
|
+
);
|
package/src/index.tsx
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ContextMenu.d.ts","sourceRoot":"","sources":["../../../src/ContextMenu.tsx"],"names":[],"mappings":"AACA,OAAO,KAA+B,MAAM,OAAO,CAAC;AACpD,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAQ9C;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC1C,sDAAsD;IACtD,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,kDAAkD;IAClD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,mCAAmC;IACnC,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,8CAA8C;IAC9C,EAAE,EAAE,MAAM,CAAC;IACX,oBAAoB;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,gCAAgC;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iEAAiE;IACjE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0DAA0D;IAC1D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,wBAAwB;IACxB,UAAU,CAAC,EAAE,2BAA2B,CAAC;IACzC,sBAAsB;IACtB,KAAK,CAAC,EAAE,KAAK,GAAG,IAAI,GAAG,OAAO,CAAC;IAC/B,iCAAiC;IACjC,UAAU,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAC;CAC3C;AAED,MAAM,WAAW,gBAAiB,SAAQ,SAAS;IACjD,0CAA0C;IAC1C,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,mBAAmB;IACnB,OAAO,EAAE,SAAS,iBAAiB,EAAE,CAAC;IAEtC,qBAAqB;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;;;OAIG;IACH,OAAO,CAAC,EAAE,WAAW,GAAG,KAAK,CAAC;IAE9B;;;OAGG;IACH,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IAEhE,iCAAiC;IACjC,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IAExB,kCAAkC;IAClC,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IAEzB,0BAA0B;IAC1B,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAE1B,yBAAyB;IACzB,GAAG,CAAC,EAAE;QACJ,wCAAwC;QACxC,aAAa,CAAC,EAAE,OAAO,CAAC;KACzB,CAAC;IAEF,6BAA6B;IAC7B,OAAO,CAAC,EAAE;QACR,yCAAyC;QACzC,cAAc,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;QAClC;;;;WAIG;QACH,OAAO,CAAC,EAAE,OAAO,CAAC;KACnB,CAAC;IAEF,sBAAsB;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AA8CD,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,KAAK,CAAC,YAAY,CAkEvE"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ContextMenuNativeComponent.d.ts","sourceRoot":"","sources":["../../../src/ContextMenuNativeComponent.ts"],"names":[],"mappings":"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"}
|