Skip to content

Commit ef31e51

Browse files
authored
Add react-native-macos-init for adding macOS apps to existing react-native init projects. (#291)
* Got npx command line working. * Generating project folder. * Added macOS template files. * Lint fixes * Remove temp workarounds. * Make react-native.config.js mac and windows compatible. * Restore parity of macOS components with iOS because the `react-native init` sample app depends on them: e.g. StatusBar. * Updated NewAppScreen language for macOS. * Added `--prerelease` switch to allow installing pre-rerelease versions without prompting as this will be needed in CI. Made tweaks to templates and fixed template schemes to rename to project name.
1 parent feed0ac commit ef31e51

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+6275
-71
lines changed

.eslintignore

+2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
Libraries/vendor/**/*
66
Libraries/Renderer/*
77
packages/*/node_modules
8+
packages/*/lib
9+
packages/*/lib-commonjs
810
pr-inactivity-bookmarklet.js
911
question-bookmarklet.js
1012
flow/

.gitignore

+2-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@ package-lock.json
6868

6969
/coverage
7070
/third-party
71-
/packages/
71+
/packages/*
72+
!/packages/react-native-macos-init/
7273

7374
# Root dir shouldn't have Xcode project
7475
/*.xcodeproj

Libraries/Components/Picker/PickerIOS.ios.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import type {SyntheticEvent} from '../../Types/CoreEventTypes';
2424
import type {ColorValue} from '../../StyleSheet/StyleSheetTypes';
2525
import type {ViewProps} from '../View/ViewPropTypes';
2626
import type {TextStyleProp} from '../../StyleSheet/StyleSheet';
27-
import type {NativeOrDynamicColorType} from '../../Color/NativeOrDynamicColorType'; // ]TODO(macOS ISS#2323203)
27+
import type {NativeOrDynamicColorType} from '../../Color/NativeOrDynamicColorType'; // TODO(macOS ISS#2323203)
2828

2929
type PickerIOSChangeEvent = SyntheticEvent<
3030
$ReadOnly<{|

Libraries/Components/Picker/PickerIOS.macos.js

+153-1
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,156 @@
1212

1313
// TODO(macOS ISS#2323203)
1414

15-
module.exports = require('../UnimplementedViews/UnimplementedView');
15+
'use strict';
16+
17+
const React = require('react');
18+
const ReactNative = require('../../Renderer/shims/ReactNative');
19+
const StyleSheet = require('../../StyleSheet/StyleSheet');
20+
const View = require('../View/View');
21+
const processColor = require('../../StyleSheet/processColor');
22+
const RCTPickerNativeComponent = require('./RCTPickerNativeComponent');
23+
24+
import type {SyntheticEvent} from '../../Types/CoreEventTypes';
25+
import type {ColorValue} from '../../StyleSheet/StyleSheetTypes';
26+
import type {ViewProps} from '../View/ViewPropTypes';
27+
import type {TextStyleProp} from '../../StyleSheet/StyleSheet';
28+
import type {NativeOrDynamicColorType} from '../../Color/NativeOrDynamicColorType'; // TODO(macOS ISS#2323203)
29+
30+
type PickerIOSChangeEvent = SyntheticEvent<
31+
$ReadOnly<{|
32+
newValue: number | string,
33+
newIndex: number,
34+
|}>,
35+
>;
36+
37+
type RCTPickerIOSItemType = $ReadOnly<{|
38+
label: ?Label,
39+
value: ?(number | string),
40+
textColor: ?(number | NativeOrDynamicColorType), // TODO(macOS ISS#2323203)
41+
|}>;
42+
43+
type RCTPickerIOSType = Class<
44+
ReactNative.NativeComponent<
45+
$ReadOnly<{|
46+
items: $ReadOnlyArray<RCTPickerIOSItemType>,
47+
onChange: (event: PickerIOSChangeEvent) => void,
48+
onResponderTerminationRequest: () => boolean,
49+
onStartShouldSetResponder: () => boolean,
50+
selectedIndex: number,
51+
style?: ?TextStyleProp,
52+
testID?: ?string,
53+
|}>,
54+
>,
55+
>;
56+
57+
type Label = Stringish | number;
58+
59+
type Props = $ReadOnly<{|
60+
...ViewProps,
61+
children: React.ChildrenArray<React.Element<typeof PickerIOSItem>>,
62+
itemStyle?: ?TextStyleProp,
63+
onChange?: ?(event: PickerIOSChangeEvent) => mixed,
64+
onValueChange?: ?(itemValue: string | number, itemIndex: number) => mixed,
65+
selectedValue: ?(number | string),
66+
|}>;
67+
68+
type State = {|
69+
selectedIndex: number,
70+
items: $ReadOnlyArray<RCTPickerIOSItemType>,
71+
|};
72+
73+
type ItemProps = $ReadOnly<{|
74+
label: ?Label,
75+
value?: ?(number | string),
76+
color?: ?ColorValue,
77+
|}>;
78+
79+
const PickerIOSItem = (props: ItemProps) => {
80+
return null;
81+
};
82+
83+
class PickerIOS extends React.Component<Props, State> {
84+
_picker: ?React.ElementRef<RCTPickerIOSType> = null;
85+
86+
state = {
87+
selectedIndex: 0,
88+
items: [],
89+
};
90+
91+
static Item = PickerIOSItem;
92+
93+
static getDerivedStateFromProps(props: Props): State {
94+
let selectedIndex = 0;
95+
const items = [];
96+
React.Children.toArray(props.children)
97+
.filter(child => child !== null)
98+
.forEach(function(child, index) {
99+
if (child.props.value === props.selectedValue) {
100+
selectedIndex = index;
101+
}
102+
items.push({
103+
value: child.props.value,
104+
label: child.props.label,
105+
textColor: processColor(child.props.color),
106+
});
107+
});
108+
return {selectedIndex, items};
109+
}
110+
111+
render() {
112+
return (
113+
<View style={this.props.style}>
114+
<RCTPickerNativeComponent
115+
ref={picker => {
116+
this._picker = picker;
117+
}}
118+
testID={this.props.testID}
119+
style={[styles.pickerIOS, this.props.itemStyle]}
120+
items={this.state.items}
121+
selectedIndex={this.state.selectedIndex}
122+
onChange={this._onChange}
123+
onStartShouldSetResponder={() => true}
124+
onResponderTerminationRequest={() => false}
125+
/>
126+
</View>
127+
);
128+
}
129+
130+
_onChange = event => {
131+
if (this.props.onChange) {
132+
this.props.onChange(event);
133+
}
134+
if (this.props.onValueChange) {
135+
this.props.onValueChange(
136+
event.nativeEvent.newValue,
137+
event.nativeEvent.newIndex,
138+
);
139+
}
140+
141+
// The picker is a controlled component. This means we expect the
142+
// on*Change handlers to be in charge of updating our
143+
// `selectedValue` prop. That way they can also
144+
// disallow/undo/mutate the selection of certain values. In other
145+
// words, the embedder of this component should be the source of
146+
// truth, not the native component.
147+
if (
148+
this._picker &&
149+
this.state.selectedIndex !== event.nativeEvent.newIndex
150+
) {
151+
this._picker.setNativeProps({
152+
selectedIndex: this.state.selectedIndex,
153+
});
154+
}
155+
};
156+
}
157+
158+
const styles = StyleSheet.create({
159+
pickerIOS: {
160+
// The picker will conform to whatever width is given, but we do
161+
// have to set the component's height explicitly on the
162+
// surrounding view to ensure it gets rendered.
163+
height: 216,
164+
},
165+
});
166+
167+
module.exports = PickerIOS;

Libraries/Components/ProgressViewIOS/ProgressViewIOS.macos.js

+9-18
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,14 @@
1212

1313
'use strict';
1414

15-
var React = require('React');
16-
var StyleSheet = require('StyleSheet');
15+
const React = require('react');
16+
const StyleSheet = require('../../StyleSheet/StyleSheet');
1717

18-
var requireNativeComponent = require('requireNativeComponent');
18+
const RCTProgressViewNativeComponent = require('./RCTProgressViewNativeComponent');
1919

20-
import type {NativeComponent} from 'ReactNative';
21-
import type {ImageSource} from 'ImageSource';
22-
import type {ColorValue} from 'StyleSheetTypes';
23-
import type {ViewProps} from 'ViewPropTypes';
20+
import type {ImageSource} from '../../Image/ImageSource';
21+
import type {ColorValue} from '../../StyleSheet/StyleSheetTypes';
22+
import type {ViewProps} from '../View/ViewPropTypes';
2423

2524
type Props = $ReadOnly<{|
2625
...ViewProps,
@@ -56,20 +55,14 @@ type Props = $ReadOnly<{|
5655
trackImage?: ?ImageSource,
5756
|}>;
5857

59-
type NativeProgressViewIOS = Class<NativeComponent<Props>>;
60-
61-
const RCTProgressView = ((requireNativeComponent(
62-
'RCTProgressView',
63-
): any): NativeProgressViewIOS);
64-
6558
/**
6659
* Use `ProgressViewIOS` to render a UIProgressView on iOS.
6760
*/
6861
const ProgressViewIOS = (
6962
props: Props,
70-
forwardedRef?: ?React.Ref<typeof RCTProgressView>,
63+
forwardedRef?: ?React.Ref<typeof RCTProgressViewNativeComponent>,
7164
) => (
72-
<RCTProgressView
65+
<RCTProgressViewNativeComponent
7366
{...props}
7467
style={[styles.progressView, props.style]}
7568
ref={forwardedRef}
@@ -82,11 +75,9 @@ const styles = StyleSheet.create({
8275
},
8376
});
8477

85-
// $FlowFixMe - TODO T29156721 `React.forwardRef` is not defined in Flow, yet.
8678
const ProgressViewIOSWithRef = React.forwardRef(ProgressViewIOS);
8779

8880
/* $FlowFixMe(>=0.89.0 site=react_native_ios_fb) This comment suppresses an
8981
* error found when Flow v0.89 was deployed. To see the error, delete this
9082
* comment and run Flow. */
91-
// $FlowFixMe
92-
module.exports = (ProgressViewIOSWithRef: NativeProgressViewIOS);
83+
module.exports = (ProgressViewIOSWithRef: typeof RCTProgressViewNativeComponent);

Libraries/NewAppScreen/components/DebugInstructions.js

+7
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,13 @@ const DebugInstructions = Platform.select({
2525
Native debug menu.
2626
</Text>
2727
),
28+
// [TODO(macOS ISS#2323203)
29+
macos: () => (
30+
<Text>
31+
Secondary click in this window to open the React Native debug menu.
32+
</Text>
33+
),
34+
// ]TODO(macOS ISS#2323203)
2835
default: () => (
2936
<Text>
3037
Press <Text style={styles.highlight}>menu button</Text> or{' '}

Libraries/NewAppScreen/components/ReloadInstructions.js

+8
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,14 @@ const ReloadInstructions = Platform.select({
2424
reload your app's code.
2525
</Text>
2626
),
27+
// [TODO(macOS ISS#2323203)
28+
macos: () => (
29+
<Text>
30+
Secondary click in this window and choose{' '}
31+
<Text style={styles.highlight}>Reload</Text> to reload your app's code.
32+
</Text>
33+
),
34+
// ]TODO(macOS ISS#2323203)
2735
default: () => (
2836
<Text>
2937
Double tap <Text style={styles.highlight}>R</Text> on your keyboard to

Libraries/react-native/react-native-implementation.macos.js

+8-12
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,9 @@ const warnOnce = require('warnOnce');
1616
// Export React, plus some native additions.
1717
module.exports = {
1818
// Components
19-
/*
2019
get AccessibilityInfo() {
2120
return require('AccessibilityInfo');
22-
},*/
21+
},
2322
get ActivityIndicator() {
2423
return require('ActivityIndicator');
2524
},
@@ -57,8 +56,7 @@ module.exports = {
5756
/*
5857
get ImageEditor() {
5958
return require('ImageEditor');
60-
},
61-
*/
59+
},*/
6260
get ImageStore() {
6361
warnOnce(
6462
'imagestore-deprecation',
@@ -76,15 +74,14 @@ module.exports = {
7674
get KeyboardAvoidingView() {
7775
return require('KeyboardAvoidingView');
7876
},
79-
get ListView() {
77+
get ListView() {
8078
warnOnce(
8179
'listview-deprecation',
8280
'ListView is deprecated and will be removed in a future release. ' +
8381
'See https://fb.me/nolistview for more information',
8482
);
8583
return require('ListView');
86-
},
87-
/*
84+
},*/
8885
get MaskedViewIOS() {
8986
warnOnce(
9087
'maskedviewios-moved',
@@ -94,6 +91,7 @@ module.exports = {
9491
);
9592
return require('MaskedViewIOS');
9693
},
94+
/*
9795
get Modal() {
9896
return require('Modal');
9997
},*/
@@ -103,13 +101,12 @@ module.exports = {
103101
get PickerIOS() {
104102
return require('../Components/Picker/PickerIOS');
105103
},
106-
/*
107104
get ProgressBarAndroid() {
108105
return require('ProgressBarAndroid');
109106
},
110107
get ProgressViewIOS() {
111108
return require('ProgressViewIOS');
112-
},*/
109+
},
113110
get SafeAreaView() {
114111
return require('SafeAreaView');
115112
},
@@ -119,11 +116,9 @@ module.exports = {
119116
get SectionList() {
120117
return require('SectionList');
121118
},
122-
/*
123119
get SegmentedControlIOS() {
124120
return require('SegmentedControlIOS');
125121
},
126-
*/
127122
get Slider() {
128123
warnOnce(
129124
'slider-moved',
@@ -139,10 +134,11 @@ module.exports = {
139134
/*
140135
get RefreshControl() {
141136
return require('RefreshControl');
142-
},
137+
},*/
143138
get StatusBar() {
144139
return require('StatusBar');
145140
},
141+
/*
146142
get SwipeableFlatList() {
147143
return require('SwipeableFlatList');
148144
},*/

RNTester/RNTester.xcodeproj/project.pbxproj

+4
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,8 @@
135135
2DE7E8061FB2A4F3009E225D /* libRCTWebSocket-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2DD323D51DA2DD8B000FE1B8 /* libRCTWebSocket-tvOS.a */; };
136136
2DE7E8071FB2A4F3009E225D /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2DD323D91DA2DD8B000FE1B8 /* libReact.a */; };
137137
3578590A1B28D2CF00341EDB /* libRCTLinking.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 357859011B28D2C500341EDB /* libRCTLinking.a */; };
138+
383C517F243447EC00CCBC30 /* UpdatePropertiesExampleView.m in Sources */ = {isa = PBXBuildFile; fileRef = 272E6B3C1BEA849E001FCF37 /* UpdatePropertiesExampleView.m */; };
139+
383C51A624344A4600CCBC30 /* FlexibleSizeExampleView.m in Sources */ = {isa = PBXBuildFile; fileRef = 27F441E81BEBE5030039B79C /* FlexibleSizeExampleView.m */; };
138140
38C500E222D3CF2E00BCD999 /* RCTConvert_UIColorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 38C500E122D3CF2E00BCD999 /* RCTConvert_UIColorTests.m */; };
139141
39AA31A41DC1DFDC000F7EBB /* RCTUnicodeDecodeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 39AA31A31DC1DFDC000F7EBB /* RCTUnicodeDecodeTests.m */; };
140142
3D05746D1DE6008900184BB4 /* libRCTPushNotification-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3D05746C1DE6008900184BB4 /* libRCTPushNotification-tvOS.a */; };
@@ -3130,6 +3132,8 @@
31303132
18FC77901EF4770B002B3F17 /* ViewController.m in Sources */,
31313133
18FC778D1EF4770B002B3F17 /* main.m in Sources */,
31323134
18FC778A1EF4770B002B3F17 /* AppDelegate.m in Sources */,
3135+
383C51A624344A4600CCBC30 /* FlexibleSizeExampleView.m in Sources */,
3136+
383C517F243447EC00CCBC30 /* UpdatePropertiesExampleView.m in Sources */,
31333137
);
31343138
runOnlyForDeploymentPostprocessing = 0;
31353139
};

RNTester/RNTester/NativeExampleViews/FlexibleSizeExampleView.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
*
77
*/
88

9-
#import <UIKit/UIKit.h>
9+
#import <React/RCTUIKit.h> // TODO(macOS ISS#2323203)
1010

1111
#import <React/RCTView.h>
1212

0 commit comments

Comments
 (0)