├── .codesandbox └── ci.json ├── .github ├── CONTRIBUTING.md ├── ISSUE_TEMPLATE │ ├── bug.yml │ ├── config.yml │ └── feature.yml ├── labels-config.yml └── workflows │ ├── labels.yml │ ├── performance.yml │ ├── react-integration.yml │ └── tests.yml ├── .gitignore ├── .watchmanconfig ├── LICENSE ├── README.md ├── configs ├── .eslintignore ├── .eslintrc ├── .flowconfig ├── .prettierignore ├── babel.config.js ├── husky │ └── pre-commit ├── jest-setupFiles.dom.js ├── jest.config.js └── jest.config.node.js ├── flow-typed └── npm │ ├── create-react-class_v15.x.x.js │ ├── prop-types_v15.x.x.js │ └── styleq.js ├── package-lock.json ├── package.json ├── packages ├── babel-plugin-react-native-web │ ├── LICENSE │ ├── README.md │ ├── index.js │ ├── package.json │ └── src │ │ ├── __tests__ │ │ ├── __snapshots__ │ │ │ └── index-test.js.snap │ │ └── index-test.js │ │ ├── index.js │ │ └── moduleMap.js ├── benchmarks │ ├── LICENSE │ ├── README.md │ ├── index.html │ ├── package.json │ ├── src │ │ ├── app │ │ │ ├── App.js │ │ │ ├── Benchmark │ │ │ │ ├── index.js │ │ │ │ ├── math.js │ │ │ │ ├── timing.js │ │ │ │ └── types.js │ │ │ ├── Button.js │ │ │ ├── Icons.js │ │ │ ├── Layout.js │ │ │ ├── ReportCard.js │ │ │ ├── Text.js │ │ │ └── theme.js │ │ ├── cases │ │ │ ├── SierpinskiTriangle.js │ │ │ └── Tree.js │ │ ├── impl.js │ │ ├── implementations │ │ │ ├── css-modules │ │ │ │ ├── Box.js │ │ │ │ ├── Dot.js │ │ │ │ ├── Provider.js │ │ │ │ ├── View.js │ │ │ │ ├── box-styles.css │ │ │ │ ├── dot-styles.css │ │ │ │ ├── index.js │ │ │ │ └── view-styles.css │ │ │ ├── inline-styles │ │ │ │ ├── Box.js │ │ │ │ ├── Dot.js │ │ │ │ ├── Provider.js │ │ │ │ ├── View.js │ │ │ │ └── index.js │ │ │ ├── react-native-web │ │ │ │ ├── Box.js │ │ │ │ ├── Dot.js │ │ │ │ ├── Provider.js │ │ │ │ └── index.js │ │ │ ├── styleq │ │ │ │ ├── Box.js │ │ │ │ ├── Dot.js │ │ │ │ ├── Provider.js │ │ │ │ ├── View.js │ │ │ │ └── index.js │ │ │ └── stylesheet │ │ │ │ ├── Box.js │ │ │ │ ├── Dot.js │ │ │ │ ├── Provider.js │ │ │ │ ├── View.js │ │ │ │ └── index.js │ │ └── index.js │ └── webpack.config.js ├── dom-event-testing-library │ ├── LICENSE │ ├── README.md │ ├── index.js │ ├── package.json │ └── src │ │ ├── __tests__ │ │ ├── __snapshots__ │ │ │ └── index-test.js.snap │ │ └── index-test.js │ │ ├── constants.js │ │ ├── createEvent.js │ │ ├── domEnvironment.js │ │ ├── domEventSequences.js │ │ ├── domEvents.js │ │ ├── index.js │ │ ├── testHelpers.js │ │ └── touchStore.js ├── react-native-web-docs │ ├── .eleventy.js │ ├── LICENSE │ ├── README.md │ ├── package.json │ └── src │ │ ├── data │ │ └── site.js │ │ ├── includes │ │ ├── assets │ │ │ ├── inline.css │ │ │ ├── inline.js │ │ │ └── svg │ │ │ │ ├── 404.svg │ │ │ │ ├── close.svg │ │ │ │ ├── documents.svg │ │ │ │ ├── github.svg │ │ │ │ └── logo.svg │ │ ├── fragments │ │ │ ├── footer.html │ │ │ ├── macros.html │ │ │ └── nav.html │ │ └── layouts │ │ │ ├── 404.html │ │ │ ├── home.html │ │ │ ├── page.html │ │ │ └── shell.html │ │ ├── pages │ │ ├── 404.md │ │ ├── docs │ │ │ ├── apis │ │ │ │ ├── _.md │ │ │ │ ├── animated.md │ │ │ │ ├── app-registry.md │ │ │ │ ├── app-state.md │ │ │ │ ├── appearance.md │ │ │ │ ├── clipboard.md │ │ │ │ ├── dimensions.md │ │ │ │ ├── linking.md │ │ │ │ ├── pan-responder.md │ │ │ │ ├── pixel-ratio.md │ │ │ │ ├── platform.md │ │ │ │ ├── style-sheet.md │ │ │ │ └── vibration.md │ │ │ ├── appendix │ │ │ │ ├── _.md │ │ │ │ ├── about-project.md │ │ │ │ └── unstable-apis.md │ │ │ ├── components │ │ │ │ ├── _.md │ │ │ │ ├── activity-indicator.md │ │ │ │ ├── checkbox.md │ │ │ │ ├── image-background.md │ │ │ │ ├── image.md │ │ │ │ ├── lists.md │ │ │ │ ├── modal.md │ │ │ │ ├── picker.md │ │ │ │ ├── pressable.md │ │ │ │ ├── progress-bar.md │ │ │ │ ├── scroll-view.md │ │ │ │ ├── switch.md │ │ │ │ ├── text-input.md │ │ │ │ ├── text.md │ │ │ │ └── view.md │ │ │ ├── concepts │ │ │ │ ├── _.md │ │ │ │ ├── accessibility.md │ │ │ │ ├── interactions.md │ │ │ │ ├── localization.md │ │ │ │ ├── rendering.md │ │ │ │ └── styling.md │ │ │ ├── getting-started │ │ │ │ ├── _.md │ │ │ │ ├── browser-compatibility.md │ │ │ │ ├── help.md │ │ │ │ ├── installation.md │ │ │ │ ├── introduction.md │ │ │ │ ├── multi-platform.md │ │ │ │ ├── react-native-compatibility.md │ │ │ │ ├── setup.md │ │ │ │ └── typescript-support.md │ │ │ └── hooks │ │ │ │ ├── _.md │ │ │ │ ├── use-color-scheme.md │ │ │ │ ├── use-locale-context.md │ │ │ │ └── use-window-dimensions.md │ │ ├── home.md │ │ └── pages.json │ │ └── static │ │ └── logo.svg ├── react-native-web-examples │ ├── .babelrc │ ├── LICENSE │ ├── README.md │ ├── next.config.js │ ├── package.json │ ├── pages │ │ ├── _document.js │ │ ├── activity-indicator │ │ │ └── index.js │ │ ├── animated │ │ │ └── index.js │ │ ├── app-registry │ │ │ └── index.js │ │ ├── app-state │ │ │ └── index.js │ │ ├── checkbox │ │ │ └── index.js │ │ ├── clipboard │ │ │ └── index.js │ │ ├── dimensions │ │ │ └── index.js │ │ ├── flatlist │ │ │ └── index.js │ │ ├── image-background │ │ │ └── index.js │ │ ├── image │ │ │ └── index.js │ │ ├── index.js │ │ ├── linking │ │ │ └── index.js │ │ ├── lists │ │ │ └── index.js │ │ ├── localization │ │ │ └── index.js │ │ ├── modal │ │ │ └── index.js │ │ ├── pan-responder │ │ │ └── index.js │ │ ├── pressable │ │ │ └── index.js │ │ ├── progress-bar │ │ │ └── index.js │ │ ├── scroll-view │ │ │ └── index.js │ │ ├── section-list │ │ │ └── index.js │ │ ├── switch │ │ │ └── index.js │ │ ├── text-input │ │ │ └── index.js │ │ ├── text │ │ │ └── index.js │ │ └── view │ │ │ └── index.js │ ├── public │ │ ├── image │ │ │ ├── back.svg │ │ │ ├── hawk.png │ │ │ ├── ladybug.jpg │ │ │ ├── placeholder.svg │ │ │ └── smallflower.jpg │ │ └── lists │ │ │ ├── bandaged.png │ │ │ ├── call.png │ │ │ ├── dislike.png │ │ │ ├── fist.png │ │ │ ├── flowers.png │ │ │ ├── heart.png │ │ │ ├── like.png │ │ │ ├── liking.png │ │ │ ├── party.png │ │ │ ├── poke.png │ │ │ ├── superlike.png │ │ │ └── victory.png │ ├── sandbox.config.json │ └── shared │ │ ├── button.js │ │ └── example.js └── react-native-web │ ├── LICENSE │ ├── README.md │ ├── package.json │ └── src │ ├── exports │ ├── AccessibilityInfo │ │ └── index.js │ ├── ActivityIndicator │ │ ├── __tests__ │ │ │ ├── __snapshots__ │ │ │ │ └── index-test.js.snap │ │ │ └── index-test.js │ │ └── index.js │ ├── Alert │ │ └── index.js │ ├── Animated │ │ ├── __tests__ │ │ │ └── index-test.js │ │ └── index.js │ ├── AppRegistry │ │ ├── AppContainer.js │ │ ├── __tests__ │ │ │ ├── __snapshots__ │ │ │ │ └── index-test.js.snap │ │ │ ├── index-test.js │ │ │ └── index-test.node.js │ │ ├── index.js │ │ └── renderApplication.js │ ├── AppState │ │ ├── __tests__ │ │ │ └── index-test.js │ │ └── index.js │ ├── Appearance │ │ └── index.js │ ├── BackHandler │ │ └── index.js │ ├── Button │ │ └── index.js │ ├── CheckBox │ │ ├── __tests__ │ │ │ ├── __snapshots__ │ │ │ │ └── index-test.js.snap │ │ │ └── index-test.js │ │ └── index.js │ ├── Clipboard │ │ └── index.js │ ├── DeviceEventEmitter │ │ └── index.js │ ├── Dimensions │ │ ├── __tests__ │ │ │ └── index-test.js │ │ └── index.js │ ├── Easing │ │ └── index.js │ ├── FlatList │ │ └── index.js │ ├── I18nManager │ │ └── index.js │ ├── Image │ │ ├── __tests__ │ │ │ ├── __snapshots__ │ │ │ │ └── index-test.js.snap │ │ │ └── index-test.js │ │ ├── index.js │ │ └── types.js │ ├── ImageBackground │ │ ├── __tests__ │ │ │ └── index-test.js │ │ └── index.js │ ├── InputAccessoryView │ │ └── index.js │ ├── InteractionManager │ │ ├── TaskQueue.js │ │ ├── __tests__ │ │ │ ├── TaskQueue-test.js │ │ │ └── index-test.js │ │ └── index.js │ ├── Keyboard │ │ └── index.js │ ├── KeyboardAvoidingView │ │ └── index.js │ ├── LayoutAnimation │ │ └── index.js │ ├── Linking │ │ ├── __tests__ │ │ │ └── index-test.js │ │ └── index.js │ ├── LogBox │ │ └── index.js │ ├── Modal │ │ ├── ModalAnimation.js │ │ ├── ModalContent.js │ │ ├── ModalFocusTrap.js │ │ ├── ModalPortal.js │ │ ├── __tests__ │ │ │ ├── __snapshots__ │ │ │ │ └── index-test.js.snap │ │ │ └── index-test.js │ │ └── index.js │ ├── NativeEventEmitter │ │ └── index.js │ ├── NativeModules │ │ └── index.js │ ├── PanResponder │ │ ├── Alternative.js │ │ └── index.js │ ├── Picker │ │ ├── PickerItem.js │ │ ├── __tests__ │ │ │ ├── __snapshots__ │ │ │ │ └── index-test.js.snap │ │ │ └── index-test.js │ │ └── index.js │ ├── PixelRatio │ │ └── index.js │ ├── Platform │ │ ├── __tests__ │ │ │ └── index-test.js │ │ └── index.js │ ├── Pressable │ │ ├── __tests__ │ │ │ ├── __snapshots__ │ │ │ │ └── index-test.js.snap │ │ │ └── index-test.js │ │ └── index.js │ ├── ProgressBar │ │ ├── __tests__ │ │ │ └── index-test.js │ │ └── index.js │ ├── RefreshControl │ │ └── index.js │ ├── SafeAreaView │ │ └── index.js │ ├── ScrollView │ │ ├── ScrollViewBase.js │ │ ├── __tests__ │ │ │ ├── __snapshots__ │ │ │ │ └── index-test.js.snap │ │ │ └── index-test.js │ │ └── index.js │ ├── SectionList │ │ └── index.js │ ├── Share │ │ └── index.js │ ├── StatusBar │ │ └── index.js │ ├── StyleSheet │ │ ├── __tests__ │ │ │ ├── compiler-createReactDOMStyle-test.js │ │ │ ├── compiler-test.js │ │ │ ├── dom-createOrderedCSSStyleSheet-test.js │ │ │ ├── dom-test.js │ │ │ ├── dom-test.node.js │ │ │ ├── index-test.js │ │ │ ├── preprocess-test.js │ │ │ └── validate-test.js │ │ ├── compiler │ │ │ ├── createReactDOMStyle.js │ │ │ ├── hash.js │ │ │ ├── hyphenateStyleName.js │ │ │ ├── index.js │ │ │ ├── normalizeColor.js │ │ │ ├── normalizeValueWithProperty.js │ │ │ ├── resolveShadowValue.js │ │ │ └── unitlessNumbers.js │ │ ├── dom │ │ │ ├── createCSSStyleSheet.js │ │ │ ├── createOrderedCSSStyleSheet.js │ │ │ └── index.js │ │ ├── index.js │ │ ├── preprocess.js │ │ └── validate.js │ ├── Switch │ │ ├── __tests__ │ │ │ ├── __snapshots__ │ │ │ │ └── index-test.js.snap │ │ │ └── index-test.js │ │ └── index.js │ ├── Text │ │ ├── TextAncestorContext.js │ │ ├── __tests__ │ │ │ ├── __snapshots__ │ │ │ │ └── index-test.js.snap │ │ │ └── index-test.js │ │ ├── index.js │ │ └── types.js │ ├── TextInput │ │ ├── __tests__ │ │ │ └── index-test.js │ │ ├── index.js │ │ └── types.js │ ├── Touchable │ │ ├── BoundingDimensions.js │ │ ├── Position.js │ │ ├── ensurePositiveDelayProps.js │ │ └── index.js │ ├── TouchableHighlight │ │ └── index.js │ ├── TouchableNativeFeedback │ │ └── index.js │ ├── TouchableOpacity │ │ └── index.js │ ├── TouchableWithoutFeedback │ │ ├── __tests__ │ │ │ └── index-test.js │ │ └── index.js │ ├── UIManager │ │ ├── __tests__ │ │ │ └── index-test.js │ │ └── index.js │ ├── Vibration │ │ └── index.js │ ├── View │ │ ├── __tests__ │ │ │ ├── __snapshots__ │ │ │ │ └── index-test.js.snap │ │ │ └── index-test.js │ │ ├── index.js │ │ └── types.js │ ├── VirtualizedList │ │ └── index.js │ ├── YellowBox │ │ └── index.js │ ├── createElement │ │ ├── __tests__ │ │ │ ├── __snapshots__ │ │ │ │ └── index-test.js.snap │ │ │ └── index-test.js │ │ └── index.js │ ├── findNodeHandle │ │ └── index.js │ ├── processColor │ │ ├── __tests__ │ │ │ └── index-test.js │ │ └── index.js │ ├── render │ │ └── index.js │ ├── unmountComponentAtNode │ │ └── index.js │ ├── useColorScheme │ │ └── index.js │ ├── useLocaleContext │ │ └── index.js │ └── useWindowDimensions │ │ └── index.js │ ├── index.js │ ├── modules │ ├── AccessibilityUtil │ │ ├── __tests__ │ │ │ ├── propsToAccessibilityComponent-test.js │ │ │ └── propsToAriaRole-test.js │ │ ├── index.js │ │ ├── isDisabled.js │ │ ├── propsToAccessibilityComponent.js │ │ └── propsToAriaRole.js │ ├── AssetRegistry │ │ └── index.js │ ├── ImageLoader │ │ └── index.js │ ├── TextInputState │ │ └── index.js │ ├── UnimplementedView │ │ └── index.js │ ├── addEventListener │ │ ├── __tests__ │ │ │ ├── index-test.js │ │ │ └── index-test.node.js │ │ └── index.js │ ├── canUseDom │ │ └── index.js │ ├── createDOMProps │ │ ├── __tests__ │ │ │ └── index-test.js │ │ └── index.js │ ├── dismissKeyboard │ │ └── index.js │ ├── forwardedProps │ │ └── index.js │ ├── getBoundingClientRect │ │ └── index.js │ ├── isSelectionValid │ │ └── index.js │ ├── isWebColor │ │ └── index.js │ ├── mergeRefs │ │ ├── __tests__ │ │ │ └── index-test.js │ │ └── index.js │ ├── modality │ │ ├── __tests__ │ │ │ └── index-test.js │ │ └── index.js │ ├── multiplyStyleLengthValue │ │ ├── __tests__ │ │ │ └── index-test.js │ │ └── index.js │ ├── normalizeColor │ │ └── index.js │ ├── pick │ │ └── index.js │ ├── prefixStyles │ │ ├── index.js │ │ └── static.js │ ├── requestIdleCallback │ │ └── index.js │ ├── setValueForStyles │ │ ├── dangerousStyleValue.js │ │ └── index.js │ ├── unitlessNumbers │ │ └── index.js │ ├── useElementLayout │ │ └── index.js │ ├── useEvent │ │ ├── __tests__ │ │ │ └── index-test.js │ │ └── index.js │ ├── useHover │ │ ├── __tests__ │ │ │ └── index-test.js │ │ └── index.js │ ├── useLayoutEffect │ │ └── index.js │ ├── useLocale │ │ ├── index.js │ │ └── isLocaleRTL.js │ ├── useMergeRefs │ │ ├── __tests__ │ │ │ └── index-test.js │ │ └── index.js │ ├── usePlatformMethods │ │ └── index.js │ ├── usePressEvents │ │ ├── PressResponder.js │ │ └── index.js │ ├── useResponderEvents │ │ ├── README.md │ │ ├── ResponderEventTypes.js │ │ ├── ResponderSystem.js │ │ ├── ResponderTouchHistoryStore.js │ │ ├── __tests__ │ │ │ └── index-test.js │ │ ├── createResponderEvent.js │ │ ├── index.js │ │ └── utils.js │ ├── useStable │ │ ├── __tests__ │ │ │ └── index-test.js │ │ └── index.js │ └── warnOnce │ │ └── index.js │ ├── types │ ├── index.js │ └── styles.js │ └── vendor │ ├── hash │ └── index.js │ └── react-native │ ├── Animated │ ├── Animated.js │ ├── AnimatedEvent.js │ ├── AnimatedImplementation.js │ ├── AnimatedMock.js │ ├── AnimatedPlatformConfig.js │ ├── Easing.js │ ├── NativeAnimatedHelper.js │ ├── NativeAnimatedModule.js │ ├── NativeAnimatedTurboModule.js │ ├── SpringConfig.js │ ├── animations │ │ ├── Animation.js │ │ ├── DecayAnimation.js │ │ ├── SpringAnimation.js │ │ └── TimingAnimation.js │ ├── bezier.js │ ├── components │ │ ├── AnimatedFlatList.js │ │ ├── AnimatedImage.js │ │ ├── AnimatedScrollView.js │ │ ├── AnimatedSectionList.js │ │ ├── AnimatedText.js │ │ └── AnimatedView.js │ ├── createAnimatedComponent.js │ ├── nodes │ │ ├── AnimatedAddition.js │ │ ├── AnimatedColor.js │ │ ├── AnimatedDiffClamp.js │ │ ├── AnimatedDivision.js │ │ ├── AnimatedInterpolation.js │ │ ├── AnimatedModulo.js │ │ ├── AnimatedMultiplication.js │ │ ├── AnimatedNode.js │ │ ├── AnimatedProps.js │ │ ├── AnimatedStyle.js │ │ ├── AnimatedSubtraction.js │ │ ├── AnimatedTracking.js │ │ ├── AnimatedTransform.js │ │ ├── AnimatedValue.js │ │ ├── AnimatedValueXY.js │ │ └── AnimatedWithChildren.js │ └── useAnimatedProps.js │ ├── Batchinator │ └── index.js │ ├── EventEmitter │ ├── NativeEventEmitter.js │ └── RCTDeviceEventEmitter.js │ ├── FillRateHelper │ └── index.js │ ├── FlatList │ └── index.js │ ├── JSEventLoopWatchdog │ └── index.js │ ├── LayoutAnimation │ └── index.js │ ├── PanResponder │ └── index.js │ ├── PooledClass │ └── index.js │ ├── ReactNative │ └── ReactNativeFeatureFlags.js │ ├── SHA │ ├── SectionList │ └── index.js │ ├── StaticContainer │ └── index.js │ ├── StaticRenderer │ └── index.js │ ├── TouchHistoryMath │ └── index.js │ ├── TurboModule │ ├── RCTExport.js │ └── TurboModuleRegistry.js │ ├── Types │ └── CoreEventTypes.js │ ├── Utilities │ ├── Platform.js │ ├── clamp.js │ ├── setAndForwardRef.js │ ├── useMergeRefs.js │ └── useRefEffect.js │ ├── ViewabilityHelper │ └── index.js │ ├── VirtualizeUtils │ └── index.js │ ├── VirtualizedList │ ├── CellRenderMask.js │ ├── ChildListCollection.js │ ├── StateSafePureComponent.js │ ├── VirtualizedListCellRenderer.js │ ├── VirtualizedListContext.js │ ├── VirtualizedListProps.js │ └── index.js │ ├── VirtualizedSectionList │ └── index.js │ ├── deepDiffer │ └── index.js │ ├── infoLog │ └── index.js │ └── vendor │ └── emitter │ └── EventEmitter.js └── scripts ├── createBabelReactNativeWebModuleMap.js ├── createInlineStylePrefixerData.js └── releaseReactNativeWebPackages.js /.codesandbox/ci.json: -------------------------------------------------------------------------------- 1 | { 2 | "packages": ["packages/react-native-web", "packages/babel-plugin-react-native-web"], 3 | "buildCommand": "build", 4 | "sandboxes": ["/packages/react-native-web-examples/"], 5 | "node": "16" 6 | } 7 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature.yml: -------------------------------------------------------------------------------- 1 | name: Feature request 2 | description: If you have a suggestion… 3 | labels: ["enhancement"] 4 | body: 5 | - type: markdown 6 | attributes: 7 | value: | 8 | Thank you for suggesting a feature! 9 | - type: checkboxes 10 | attributes: 11 | label: Is there an existing request? 12 | description: Please search open and closed issues to see if this request has already been made. 13 | options: 14 | - label: I have searched for this request 15 | required: true 16 | - type: textarea 17 | attributes: 18 | label: Describe the feature request 19 | description: Please provide a concise description of the request, potential solutions, and additional context. 20 | validations: 21 | required: true 22 | -------------------------------------------------------------------------------- /.github/labels-config.yml: -------------------------------------------------------------------------------- 1 | # Configuration for Label Actions - https://github.com/marketplace/actions/label-actions 2 | 3 | "needs: issue template": 4 | comment: > 5 | :warning: This issue is missing required fields. To avoid this issue being closed, please provide the required information as described in the ISSUE TEMPLATE. 6 | 7 | "resolution: no response": 8 | comment: > 9 | This issue is being closed because the requested information has not been provided. 10 | close: true 11 | -------------------------------------------------------------------------------- /.github/workflows/labels.yml: -------------------------------------------------------------------------------- 1 | name: labels 2 | 3 | on: 4 | issues: 5 | types: [labeled, unlabeled] 6 | pull_request: 7 | types: [labeled, unlabeled] 8 | 9 | permissions: 10 | contents: read 11 | issues: write 12 | pull-requests: write 13 | 14 | jobs: 15 | label-actions: 16 | runs-on: ubuntu-latest 17 | steps: 18 | - uses: actions/checkout@v3 19 | - uses: dessant/label-actions@v3 20 | with: 21 | config-path: .github/labels-config.yml 22 | github-token: ${{ github.token }} 23 | -------------------------------------------------------------------------------- /.github/workflows/performance.yml: -------------------------------------------------------------------------------- 1 | name: performance 2 | 3 | on: [pull_request] 4 | 5 | jobs: 6 | compressed-size: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/checkout@v3 10 | - uses: necolas/compressed-size-action@master 11 | with: 12 | build-script: "compile" 13 | exclude: "./packages/react-native-web/dist/cjs/{index.js,**/*.js}" 14 | pattern: "./packages/react-native-web/dist/{index.js,**/*.js}" 15 | repo-token: "${{ secrets.GITHUB_TOKEN }}" 16 | -------------------------------------------------------------------------------- /.github/workflows/react-integration.yml: -------------------------------------------------------------------------------- 1 | name: react@next integration 2 | 3 | on: 4 | schedule: 5 | # Run every Monday at 12:00 (see https://crontab.guru) 6 | - cron: '0 12 * * 1' 7 | 8 | jobs: 9 | react-next: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v3 13 | - uses: actions/setup-node@v3 14 | with: 15 | node-version: 16 16 | - run: npm install 17 | # Update react-native-web to use react@next 18 | - run: npm install --force react@next react-dom@next -w react-native-web 19 | # Run the unit tests 20 | - run: npm run unit 21 | -------------------------------------------------------------------------------- /.github/workflows/tests.yml: -------------------------------------------------------------------------------- 1 | name: tests 2 | 3 | on: 4 | push: 5 | branches: 6 | - "master" 7 | pull_request: 8 | types: [opened, synchronize, reopened] 9 | 10 | jobs: 11 | format: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v3 15 | - uses: actions/setup-node@v3 16 | with: 17 | node-version: 16 18 | - run: npm install 19 | - run: npm run format 20 | 21 | type-check: 22 | runs-on: ubuntu-latest 23 | steps: 24 | - uses: actions/checkout@v3 25 | - uses: actions/setup-node@v3 26 | with: 27 | node-version: 16 28 | - run: npm install 29 | - run: npm run flow 30 | 31 | lint: 32 | runs-on: ubuntu-latest 33 | steps: 34 | - uses: actions/checkout@v3 35 | - uses: actions/setup-node@v3 36 | with: 37 | node-version: 16 38 | - run: npm install 39 | - run: npm run lint 40 | 41 | unit-test: 42 | runs-on: ubuntu-latest 43 | steps: 44 | - uses: actions/checkout@v3 45 | - uses: actions/setup-node@v3 46 | with: 47 | node-version: 16 48 | - run: npm install 49 | - run: npm run unit 50 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .next 2 | build 3 | coverage 4 | dist 5 | node_modules 6 | -------------------------------------------------------------------------------- /.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Nicolas Gallagher. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /configs/.eslintignore: -------------------------------------------------------------------------------- 1 | coverage 2 | dist 3 | flow-typed 4 | node_modules 5 | packages/**/vendor/* 6 | packages/**/.next 7 | -------------------------------------------------------------------------------- /configs/.flowconfig: -------------------------------------------------------------------------------- 1 | [version] 2 | 0.148.0 3 | 4 | [ignore] 5 | /.*/__tests__/.* 6 | /packages/.*/dist/.* 7 | /packages/react-native-web-docs/.* 8 | /packages/react-native-web-examples/.* 9 | 10 | [include] 11 | 12 | [declarations] 13 | .*/node_modules/.* 14 | 15 | [libs] 16 | 17 | [options] 18 | indexed_access=true 19 | munge_underscores=true 20 | -------------------------------------------------------------------------------- /configs/.prettierignore: -------------------------------------------------------------------------------- 1 | ../coverage 2 | ../**/dist 3 | ../flow-typed 4 | ../node_modules 5 | ../packages/**/vendor/* 6 | ../packages/**/.next 7 | -------------------------------------------------------------------------------- /configs/babel.config.js: -------------------------------------------------------------------------------- 1 | const createConfig = ({ modules }) => { 2 | const plugins = [ 3 | '@babel/plugin-transform-flow-strip-types', 4 | ['@babel/plugin-proposal-class-properties', { loose: true }], 5 | ['@babel/plugin-proposal-object-rest-spread', { useBuiltIns: true }], 6 | '@babel/plugin-proposal-nullish-coalescing-operator', 7 | [ 8 | '@babel/plugin-transform-runtime', 9 | { 10 | version: '7.18.6' 11 | } 12 | ] 13 | ].concat(modules ? ['babel-plugin-add-module-exports'] : []); 14 | 15 | return { 16 | assumptions: { 17 | iterableIsArray: true 18 | }, 19 | comments: true, 20 | presets: [ 21 | [ 22 | '@babel/preset-env', 23 | { 24 | loose: true, 25 | modules, 26 | exclude: ['transform-typeof-symbol'], 27 | targets: { 28 | browsers: [ 29 | 'chrome 49', 30 | // https://www.mozilla.org/en-US/firefox/all/#product-desktop-esr 31 | 'firefox 91', 32 | 'ios_saf 10', 33 | 'safari 10', 34 | // https://docs.microsoft.com/en-us/DeployEdge/microsoft-edge-support-lifecycle 35 | 'edge 94', 36 | 'opera 36' 37 | ] 38 | } 39 | } 40 | ], 41 | '@babel/preset-react', 42 | '@babel/preset-flow' 43 | ], 44 | plugins: plugins 45 | }; 46 | }; 47 | 48 | module.exports = function (api) { 49 | if (api) { 50 | api.cache(true); 51 | } 52 | 53 | return process.env.BABEL_ENV === 'commonjs' || process.env.NODE_ENV === 'test' 54 | ? createConfig({ modules: 'commonjs' }) 55 | : createConfig({ modules: false }); 56 | }; 57 | -------------------------------------------------------------------------------- /configs/husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | . "$(dirname -- "$0")/_/husky.sh" 3 | 4 | npx --no lint-staged 5 | -------------------------------------------------------------------------------- /configs/jest-setupFiles.dom.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Nicolas Gallagher. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | // JSDOM doesn't implement ResizeObserver 9 | class ResizeObserver { 10 | disconnect() {} 11 | observe() {} 12 | unobserve() {} 13 | } 14 | window.ResizeObserver = ResizeObserver; 15 | 16 | // JSDOM doesn't provide values for 'clientWidth' etc 17 | Object.defineProperty(window.document.documentElement, 'clientHeight', { 18 | get: function () { 19 | return this._jsdomClientWidth || window.innerHeight; 20 | } 21 | }); 22 | Object.defineProperty(window.document.documentElement, 'clientWidth', { 23 | get: function () { 24 | return this._jsdomClientWidth || window.innerWidth; 25 | } 26 | }); 27 | -------------------------------------------------------------------------------- /configs/jest.config.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const babelConfig = require('./babel.config.js'); 4 | 5 | module.exports = { 6 | coveragePathIgnorePatterns: [ 7 | '/node_modules/', 8 | '/packages/react-native-web/src/vendor/' 9 | ], 10 | fakeTimers: { 11 | enableGlobally: true 12 | }, 13 | modulePathIgnorePatterns: [ 14 | '/packages/benchmarks/', 15 | '/packages/react-native-web-docs/', 16 | '/packages/react-native-web-examples/', 17 | '/packages/react-native-web/dist/' 18 | ], 19 | rootDir: process.cwd(), 20 | roots: ['/packages'], 21 | setupFiles: [require.resolve('./jest-setupFiles.dom.js')], 22 | snapshotFormat: { 23 | printBasicPrototype: false 24 | }, 25 | testEnvironment: 'jsdom', 26 | testMatch: ['**/__tests__/**/?(*-)+(spec|test).[jt]s?(x)'], 27 | transform: { 28 | '\\.[jt]sx?$': ['babel-jest', babelConfig()] 29 | } 30 | }; 31 | -------------------------------------------------------------------------------- /configs/jest.config.node.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const babelConfig = require('./babel.config.js'); 4 | 5 | module.exports = { 6 | coveragePathIgnorePatterns: [ 7 | '/node_modules/', 8 | '/packages/react-native-web/src/vendor/' 9 | ], 10 | fakeTimers: { 11 | enableGlobally: true 12 | }, 13 | modulePathIgnorePatterns: [ 14 | '/packages/benchmarks/', 15 | '/packages/react-native-web-docs/', 16 | '/packages/react-native-web-examples/', 17 | '/packages/react-native-web/dist/' 18 | ], 19 | rootDir: process.cwd(), 20 | roots: ['/packages'], 21 | snapshotFormat: { 22 | printBasicPrototype: false 23 | }, 24 | testEnvironment: 'node', 25 | testMatch: ['**/__tests__/**/?(*-)+(spec|test).node.[jt]s?(x)'], 26 | transform: { 27 | '\\.[jt]sx?$': ['babel-jest', babelConfig()] 28 | } 29 | }; 30 | -------------------------------------------------------------------------------- /flow-typed/npm/create-react-class_v15.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 59a949eac1b23f4800e93fe3c647f055 2 | // flow-typed version: c6154227d1/create-react-class_v15.x.x/flow_>=v0.104.x 3 | 4 | declare module "create-react-class" { 5 | declare module.exports: React$CreateClass; 6 | } 7 | -------------------------------------------------------------------------------- /flow-typed/npm/prop-types_v15.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: c93a723cbeb4d2f95d6a472157f6052f 2 | // flow-typed version: 61b795e5b6/prop-types_v15.x.x/flow_>=v0.104.x 3 | 4 | type $npm$propTypes$ReactPropsCheckType = ( 5 | props: any, 6 | propName: string, 7 | componentName: string, 8 | href?: string 9 | ) => ?Error; 10 | 11 | // Copied from: https://github.com/facebook/flow/blob/0938da8d7293d0077fbe95c3a3e0eebadb57b012/lib/react.js#L433-L449 12 | declare module 'prop-types' { 13 | declare var array: React$PropType$Primitive>; 14 | declare var bool: React$PropType$Primitive; 15 | declare var func: React$PropType$Primitive<(...a: Array) => mixed>; 16 | declare var number: React$PropType$Primitive; 17 | declare var object: React$PropType$Primitive<{ +[string]: mixed, ... }>; 18 | declare var string: React$PropType$Primitive; 19 | declare var symbol: React$PropType$Primitive; 20 | declare var any: React$PropType$Primitive; 21 | declare var arrayOf: React$PropType$ArrayOf; 22 | declare var element: React$PropType$Primitive; 23 | declare var elementType: React$PropType$Primitive; 24 | declare var instanceOf: React$PropType$InstanceOf; 25 | declare var node: React$PropType$Primitive; 26 | declare var objectOf: React$PropType$ObjectOf; 27 | declare var oneOf: React$PropType$OneOf; 28 | declare var oneOfType: React$PropType$OneOfType; 29 | declare var shape: React$PropType$Shape; 30 | 31 | declare function checkPropTypes( 32 | propTypes: { [key: $Keys]: $npm$propTypes$ReactPropsCheckType, ... }, 33 | values: V, 34 | location: string, 35 | componentName: string, 36 | getStack: ?() => ?string 37 | ): void; 38 | } 39 | -------------------------------------------------------------------------------- /flow-typed/npm/styleq.js: -------------------------------------------------------------------------------- 1 | type CompiledStyle = { 2 | $$css: boolean, 3 | [key: string]: string, 4 | }; 5 | 6 | type InlineStyle = { 7 | [key: string]: mixed, 8 | }; 9 | 10 | type EitherStyle = CompiledStyle | InlineStyle; 11 | 12 | type StylesArray<+T> = T | $ReadOnlyArray>; 13 | type Styles = StylesArray; 14 | type Style<+T = EitherStyle> = StylesArray; 15 | 16 | type StyleqOptions = { 17 | disableCache?: boolean, 18 | disableMix?: boolean, 19 | transform?: (EitherStyle) => EitherStyle, 20 | }; 21 | 22 | type StyleqResult = [string, InlineStyle | null]; 23 | type Styleq = (styles: Styles) => StyleqResult; 24 | 25 | type IStyleq = { 26 | (...styles: $ReadOnlyArray): StyleqResult, 27 | factory: (options?: StyleqOptions) => Styleq, 28 | }; 29 | 30 | declare module "styleq" { 31 | declare module.exports: { 32 | styleq: IStyleq 33 | }; 34 | } 35 | 36 | declare module "styleq/transform-localize-style" { 37 | declare module.exports: { 38 | localizeStyle: (style: EitherStyle, isRTL: boolean) => EitherStyle 39 | }; 40 | } 41 | -------------------------------------------------------------------------------- /packages/babel-plugin-react-native-web/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Nicolas Gallagher. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/babel-plugin-react-native-web/README.md: -------------------------------------------------------------------------------- 1 | # babel-plugin-react-native-web 2 | 3 | [![npm version][package-badge]][package-url] [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://reactjs.org/docs/how-to-contribute.html#your-first-pull-request) 4 | 5 | A Babel plugin that will alias `react-native` to `react-native-web` and exclude 6 | any modules not required by your app (keeping bundle size down). 7 | 8 | ## Installation 9 | 10 | ``` 11 | npm install --save-dev babel-plugin-react-native-web 12 | ``` 13 | 14 | ## Usage 15 | 16 | **.babelrc** 17 | 18 | ``` 19 | { 20 | "plugins": [ 21 | ["react-native-web", { commonjs: true }] 22 | ] 23 | } 24 | ``` 25 | 26 | You should configure the plugin to match the module format used by your 27 | bundler. Most modern bundlers will use a package's ES modules by default (i.e., 28 | if `package.json` has a `module` field). But if you need the plugin to rewrite 29 | import paths to point to CommonJS modules, you must set the `commonjs` option 30 | to `true`. 31 | 32 | ## Example 33 | 34 | NOTE: `react-native-web` internal paths are _not stable_ and you must not rely 35 | on them. Always use the Babel plugin to optimize your build. What follows is an 36 | example of the rewrite performed by the plugin. 37 | 38 | **Before** 39 | 40 | ```js 41 | import { StyleSheet, View } from 'react-native'; 42 | ``` 43 | 44 | **After** 45 | 46 | ```js 47 | import StyleSheet from 'react-native-web/dist/exports/StyleSheet'; 48 | import View from 'react-native-web/dist/exports/View'; 49 | ``` 50 | 51 | [package-badge]: https://img.shields.io/npm/v/babel-plugin-react-native-web.svg?style=flat 52 | [package-url]: https://www.npmjs.com/package/babel-plugin-react-native-web 53 | -------------------------------------------------------------------------------- /packages/babel-plugin-react-native-web/index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./src'); 2 | -------------------------------------------------------------------------------- /packages/babel-plugin-react-native-web/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "publishConfig": { 3 | "registry": "https://registry.npmjs.org/" 4 | }, 5 | "name": "babel-plugin-react-native-web", 6 | "version": "0.20.0", 7 | "description": "Babel plugin for React Native for Web", 8 | "main": "index.js", 9 | "devDependencies": { 10 | "babel-plugin-tester": "^10.1.0" 11 | }, 12 | "author": "Nicolas Gallagher", 13 | "license": "MIT", 14 | "repository": { 15 | "type": "git", 16 | "url": "git://github.com/necolas/react-native-web.git" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /packages/babel-plugin-react-native-web/src/moduleMap.js: -------------------------------------------------------------------------------- 1 | // THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. 2 | module.exports = { 3 | AccessibilityInfo: true, 4 | ActivityIndicator: true, 5 | Alert: true, 6 | Animated: true, 7 | AppRegistry: true, 8 | AppState: true, 9 | Appearance: true, 10 | BackHandler: true, 11 | Button: true, 12 | CheckBox: true, 13 | Clipboard: true, 14 | DeviceEventEmitter: true, 15 | Dimensions: true, 16 | Easing: true, 17 | FlatList: true, 18 | I18nManager: true, 19 | Image: true, 20 | ImageBackground: true, 21 | InputAccessoryView: true, 22 | InteractionManager: true, 23 | Keyboard: true, 24 | KeyboardAvoidingView: true, 25 | LayoutAnimation: true, 26 | Linking: true, 27 | LogBox: true, 28 | Modal: true, 29 | NativeEventEmitter: true, 30 | NativeModules: true, 31 | PanResponder: true, 32 | Picker: true, 33 | PixelRatio: true, 34 | Platform: true, 35 | Pressable: true, 36 | ProgressBar: true, 37 | RefreshControl: true, 38 | SafeAreaView: true, 39 | ScrollView: true, 40 | SectionList: true, 41 | Share: true, 42 | StatusBar: true, 43 | StyleSheet: true, 44 | Switch: true, 45 | Text: true, 46 | TextInput: true, 47 | Touchable: true, 48 | TouchableHighlight: true, 49 | TouchableNativeFeedback: true, 50 | TouchableOpacity: true, 51 | TouchableWithoutFeedback: true, 52 | UIManager: true, 53 | Vibration: true, 54 | View: true, 55 | VirtualizedList: true, 56 | YellowBox: true, 57 | createElement: true, 58 | findNodeHandle: true, 59 | processColor: true, 60 | render: true, 61 | unmountComponentAtNode: true, 62 | useColorScheme: true, 63 | useLocaleContext: true, 64 | useWindowDimensions: true 65 | }; 66 | -------------------------------------------------------------------------------- /packages/benchmarks/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Nicolas Gallagher. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/benchmarks/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Performance tests 6 | 7 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /packages/benchmarks/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "name": "benchmarks", 4 | "version": "0.0.0", 5 | "scripts": { 6 | "clean": "del-cli ./dist", 7 | "build": "NODE_ENV=production npm run dev", 8 | "dev": "npm run clean && mkdir -p dist && cp -f index.html dist/index.html && webpack --config ./webpack.config.js" 9 | }, 10 | "dependencies": { 11 | "classnames": "^2.3.1", 12 | "d3-scale-chromatic": "^3.0.0", 13 | "prop-types": "^15.6.0", 14 | "react": ">=17.0.2", 15 | "react-dom": ">=17.0.2", 16 | "react-native-web": "0.18.10" 17 | }, 18 | "devDependencies": { 19 | "babel-loader": "^8.2.5", 20 | "babel-plugin-react-native-web": "0.18.10", 21 | "css-loader": "^6.7.1", 22 | "style-loader": "^3.3.1", 23 | "url-loader": "^4.1.1", 24 | "webpack": "^5.76.0", 25 | "webpack-bundle-analyzer": "^4.5.0", 26 | "webpack-cli": "^4.10.0" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /packages/benchmarks/src/app/Benchmark/math.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | type ValuesType = Array; 3 | 4 | export const getStdDev = (values: ValuesType): number => { 5 | const avg = getMean(values); 6 | 7 | const squareDiffs = values.map((value: number) => { 8 | const diff = value - avg; 9 | return diff * diff; 10 | }); 11 | 12 | return Math.sqrt(getMean(squareDiffs)); 13 | }; 14 | 15 | export const getMean = (values: ValuesType): number => { 16 | const sum = values.reduce((sum: number, value: number) => sum + value, 0); 17 | return sum / values.length; 18 | }; 19 | 20 | export const getMedian = (values: ValuesType): number => { 21 | if (values.length === 1) { 22 | return values[0]; 23 | } 24 | 25 | const numbers = values.sort((a: number, b: number) => a - b); 26 | return ( 27 | (numbers[(numbers.length - 1) >> 1] + numbers[numbers.length >> 1]) / 2 28 | ); 29 | }; 30 | -------------------------------------------------------------------------------- /packages/benchmarks/src/app/Benchmark/timing.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | // Returns a high resolution time (if possible) in milliseconds 4 | export function now(): number { 5 | if (window && window.performance) { 6 | return window.performance.now(); 7 | } else { 8 | return Date.now(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/benchmarks/src/app/Benchmark/types.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @flow 3 | */ 4 | export type BenchResultsType = { 5 | startTime: number, 6 | endTime: number, 7 | runTime: number, 8 | sampleCount: number, 9 | samples: Array, 10 | max: number, 11 | min: number, 12 | median: number, 13 | mean: number, 14 | stdDev: number 15 | }; 16 | 17 | export type SampleTimingType = { 18 | scriptingStart: number, 19 | scriptingEnd?: number, 20 | layoutStart?: number, 21 | layoutEnd?: number 22 | }; 23 | 24 | export type FullSampleTimingType = { 25 | start: number, 26 | end: number, 27 | scriptingStart: number, 28 | scriptingEnd: number, 29 | layoutStart?: number, 30 | layoutEnd?: number 31 | }; 32 | -------------------------------------------------------------------------------- /packages/benchmarks/src/app/Button.js: -------------------------------------------------------------------------------- 1 | import { StyleSheet, TouchableHighlight, Text } from 'react-native'; 2 | import React, { Component } from 'react'; 3 | 4 | export default class Button extends Component<*> { 5 | static displayName = '@app/Button'; 6 | 7 | render() { 8 | const { 9 | accessibilityLabel, 10 | color, 11 | disabled, 12 | onPress, 13 | style, 14 | textStyle, 15 | testID, 16 | title 17 | } = this.props; 18 | 19 | return ( 20 | 33 | 34 | {title} 35 | 36 | 37 | ); 38 | } 39 | } 40 | 41 | const styles = StyleSheet.create({ 42 | button: { 43 | backgroundColor: '#2196F3', 44 | borderRadius: 0, 45 | justifyContent: 'center' 46 | }, 47 | text: { 48 | color: '#fff', 49 | fontSize: 20, 50 | fontWeight: '500', 51 | padding: 8, 52 | textAlign: 'center', 53 | textTransform: 'uppercase' 54 | }, 55 | buttonDisabled: { 56 | backgroundColor: '#dfdfdf' 57 | }, 58 | textDisabled: { 59 | color: '#a1a1a1' 60 | } 61 | }); 62 | -------------------------------------------------------------------------------- /packages/benchmarks/src/app/Text.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { StyleSheet, Text } from 'react-native'; 3 | import { bool } from 'prop-types'; 4 | import { colors } from './theme'; 5 | 6 | class AppText extends React.Component { 7 | static displayName = '@app/Text'; 8 | 9 | static contextTypes = { 10 | isInAParentText: bool 11 | }; 12 | 13 | render() { 14 | const { style, ...rest } = this.props; 15 | const { isInAParentText } = this.context; 16 | return ( 17 | 18 | ); 19 | } 20 | } 21 | 22 | const styles = StyleSheet.create({ 23 | baseText: { 24 | color: colors.textBlack, 25 | fontSize: '1rem', 26 | lineHeight: '1.3125em' 27 | } 28 | }); 29 | 30 | export default AppText; 31 | -------------------------------------------------------------------------------- /packages/benchmarks/src/cases/Tree.js: -------------------------------------------------------------------------------- 1 | import { BenchmarkType } from '../app/Benchmark'; 2 | import React, { Component } from 'react'; 3 | 4 | class Tree extends Component { 5 | static displayName = 'Tree'; 6 | 7 | static benchmarkType = BenchmarkType.MOUNT; 8 | 9 | render() { 10 | const { breadth, components, depth, id, wrap } = this.props; 11 | const { Box } = components; 12 | 13 | let result = ( 14 | 15 | {depth === 0 && } 16 | {depth !== 0 && 17 | Array.from({ length: breadth }).map((el, i) => ( 18 | 26 | ))} 27 | 28 | ); 29 | for (let i = 0; i < wrap; i++) { 30 | result = {result}; 31 | } 32 | return result; 33 | } 34 | } 35 | 36 | export default Tree; 37 | -------------------------------------------------------------------------------- /packages/benchmarks/src/impl.js: -------------------------------------------------------------------------------- 1 | /* @noflow */ 2 | 3 | import { type Component } from 'react'; 4 | import packageJson from '../package.json'; 5 | 6 | const context = require.context('./implementations/', true, /index\.js$/); 7 | const { dependencies } = packageJson; 8 | 9 | type ComponentsType = { 10 | Box: Component, 11 | Dot: Component, 12 | Provider: Component, 13 | View: Component 14 | }; 15 | 16 | type ImplementationType = { 17 | components: ComponentsType, 18 | name: string, 19 | version: string 20 | }; 21 | 22 | const toImplementations = (context: Object): Array => 23 | context.keys().map((path) => { 24 | const components = context(path).default; 25 | const name = path.split('/')[1]; 26 | const version = dependencies[name] || ''; 27 | return { components, name, version }; 28 | }); 29 | 30 | const toObject = (impls: Array): Object => 31 | impls.reduce((acc, impl) => { 32 | acc[impl.name] = impl; 33 | return acc; 34 | }, {}); 35 | 36 | const map = toObject(toImplementations(context)); 37 | 38 | export default map; 39 | -------------------------------------------------------------------------------- /packages/benchmarks/src/implementations/css-modules/Box.js: -------------------------------------------------------------------------------- 1 | import classnames from 'classnames'; 2 | import React from 'react'; 3 | import View from './View'; 4 | import styles from './box-styles.css'; 5 | 6 | const Box = ({ 7 | color, 8 | fixed = false, 9 | layout = 'column', 10 | outer = false, 11 | ...other 12 | }) => ( 13 | 21 | ); 22 | 23 | export default Box; 24 | -------------------------------------------------------------------------------- /packages/benchmarks/src/implementations/css-modules/Dot.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styles from './dot-styles.css'; 3 | 4 | const Dot = ({ size, x, y, children, color }) => ( 5 |
16 | {children} 17 |
18 | ); 19 | 20 | export default Dot; 21 | -------------------------------------------------------------------------------- /packages/benchmarks/src/implementations/css-modules/Provider.js: -------------------------------------------------------------------------------- 1 | import View from './View'; 2 | export default View; 3 | -------------------------------------------------------------------------------- /packages/benchmarks/src/implementations/css-modules/View.js: -------------------------------------------------------------------------------- 1 | import classnames from 'classnames'; 2 | import React from 'react'; 3 | import styles from './view-styles.css'; 4 | 5 | class View extends React.Component { 6 | render() { 7 | const props = this.props; 8 | return ( 9 |
10 | ); 11 | } 12 | } 13 | 14 | export default View; 15 | -------------------------------------------------------------------------------- /packages/benchmarks/src/implementations/css-modules/box-styles.css: -------------------------------------------------------------------------------- 1 | .outer { 2 | align-self: flex-start; 3 | padding: 4px; 4 | } 5 | 6 | .row { 7 | flex-direction: row; 8 | } 9 | 10 | .color0 { 11 | background-color: #14171A; 12 | } 13 | 14 | .color1 { 15 | background-color: #AAB8C2; 16 | } 17 | 18 | .color2 { 19 | background-color: #E6ECF0; 20 | } 21 | 22 | .color3 { 23 | background-color: #FFAD1F; 24 | } 25 | 26 | .color4 { 27 | background-color: #F45D22; 28 | } 29 | 30 | .color5 { 31 | background-color: #E0245E; 32 | } 33 | 34 | .fixed { 35 | width: 6px; 36 | height: 6px; 37 | } 38 | -------------------------------------------------------------------------------- /packages/benchmarks/src/implementations/css-modules/dot-styles.css: -------------------------------------------------------------------------------- 1 | .root { 2 | position: absolute; 3 | cursor: pointer; 4 | width: 0; 5 | height: 0; 6 | border-color: transparent; 7 | border-style: solid; 8 | border-top-width: 0; 9 | transform: translate(50%, 50%); 10 | } 11 | -------------------------------------------------------------------------------- /packages/benchmarks/src/implementations/css-modules/index.js: -------------------------------------------------------------------------------- 1 | import Box from './Box'; 2 | import Dot from './Dot'; 3 | import Provider from './Provider'; 4 | import View from './View'; 5 | 6 | export default { 7 | Box, 8 | Dot, 9 | Provider, 10 | View 11 | }; 12 | -------------------------------------------------------------------------------- /packages/benchmarks/src/implementations/css-modules/view-styles.css: -------------------------------------------------------------------------------- 1 | .initial { 2 | align-items: stretch; 3 | background-color: transparent; 4 | border-width: 0; 5 | border-style: solid; 6 | box-sizing: border-box; 7 | display: flex; 8 | flex-basis: auto; 9 | flex-direction: column; 10 | flex-shrink: 0; 11 | list-style: none; 12 | margin: 0; 13 | min-height: 0; 14 | min-width: 0; 15 | padding: 0; 16 | position: relative; 17 | z-index: 0; 18 | } 19 | -------------------------------------------------------------------------------- /packages/benchmarks/src/implementations/inline-styles/Box.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import View from './View'; 3 | 4 | const Box = ({ 5 | color, 6 | fixed = false, 7 | layout = 'column', 8 | outer = false, 9 | ...other 10 | }) => ( 11 | 20 | ); 21 | 22 | const styles = { 23 | outer: { 24 | alignSelf: 'flex-start', 25 | padding: 4 26 | }, 27 | row: { 28 | flexDirection: 'row' 29 | }, 30 | color0: { 31 | backgroundColor: '#14171A' 32 | }, 33 | color1: { 34 | backgroundColor: '#AAB8C2' 35 | }, 36 | color2: { 37 | backgroundColor: '#E6ECF0' 38 | }, 39 | color3: { 40 | backgroundColor: '#FFAD1F' 41 | }, 42 | color4: { 43 | backgroundColor: '#F45D22' 44 | }, 45 | color5: { 46 | backgroundColor: '#E0245E' 47 | }, 48 | fixed: { 49 | width: 6, 50 | height: 6 51 | } 52 | }; 53 | 54 | export default Box; 55 | -------------------------------------------------------------------------------- /packages/benchmarks/src/implementations/inline-styles/Dot.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const Dot = ({ size, x, y, children, color }) => ( 4 |
14 | {children} 15 |
16 | ); 17 | 18 | const styles = { 19 | root: { 20 | position: 'absolute', 21 | cursor: 'pointer', 22 | width: 0, 23 | height: 0, 24 | borderColor: 'transparent', 25 | borderStyle: 'solid', 26 | borderTopWidth: 0, 27 | transform: 'translate(50%, 50%)' 28 | } 29 | }; 30 | 31 | export default Dot; 32 | -------------------------------------------------------------------------------- /packages/benchmarks/src/implementations/inline-styles/Provider.js: -------------------------------------------------------------------------------- 1 | import View from './View'; 2 | export default View; 3 | -------------------------------------------------------------------------------- /packages/benchmarks/src/implementations/inline-styles/View.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const compose = (s1, s2) => { 4 | if (s1 && s2) { 5 | return { ...s1, ...s2 }; 6 | } else { 7 | return s1 || s2; 8 | } 9 | }; 10 | 11 | class View extends React.Component { 12 | render() { 13 | const { style, ...other } = this.props; 14 | return
; 15 | } 16 | } 17 | 18 | const viewStyle = { 19 | alignItems: 'stretch', 20 | backgroundColor: 'transparent', 21 | border: '0 solid black', 22 | boxSizing: 'border-box', 23 | display: 'flex', 24 | flexBasis: 'auto', 25 | flexDirection: 'column', 26 | flexShrink: 0, 27 | listStyle: 'none', 28 | margin: 0, 29 | minHeight: 0, 30 | minWidth: 0, 31 | padding: 0, 32 | position: 'relative', 33 | zIndex: 0 34 | }; 35 | 36 | export default View; 37 | -------------------------------------------------------------------------------- /packages/benchmarks/src/implementations/inline-styles/index.js: -------------------------------------------------------------------------------- 1 | import Box from './Box'; 2 | import Dot from './Dot'; 3 | import Provider from './Provider'; 4 | import View from './View'; 5 | 6 | export default { 7 | Box, 8 | Dot, 9 | Provider, 10 | View 11 | }; 12 | -------------------------------------------------------------------------------- /packages/benchmarks/src/implementations/react-native-web/Box.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { StyleSheet, View } from 'react-native'; 3 | 4 | const Box = ({ 5 | color, 6 | fixed = false, 7 | layout = 'column', 8 | outer = false, 9 | ...other 10 | }) => ( 11 | 20 | ); 21 | 22 | const styles = StyleSheet.create({ 23 | outer: { 24 | alignSelf: 'flex-start', 25 | padding: 4 26 | }, 27 | row: { 28 | flexDirection: 'row' 29 | }, 30 | color0: { 31 | backgroundColor: '#14171A' 32 | }, 33 | color1: { 34 | backgroundColor: '#AAB8C2' 35 | }, 36 | color2: { 37 | backgroundColor: '#E6ECF0' 38 | }, 39 | color3: { 40 | backgroundColor: '#FFAD1F' 41 | }, 42 | color4: { 43 | backgroundColor: '#F45D22' 44 | }, 45 | color5: { 46 | backgroundColor: '#E0245E' 47 | }, 48 | fixed: { 49 | width: 6, 50 | height: 6 51 | } 52 | }); 53 | 54 | export default Box; 55 | -------------------------------------------------------------------------------- /packages/benchmarks/src/implementations/react-native-web/Dot.js: -------------------------------------------------------------------------------- 1 | import { 2 | unstable_createElement as createElement, 3 | StyleSheet 4 | } from 'react-native'; 5 | 6 | const Dot = ({ size, x, y, children, color }) => 7 | createElement('div', { 8 | children, 9 | style: [ 10 | styles.root, 11 | { 12 | borderBottomColor: color, 13 | borderRightWidth: size / 2, 14 | borderBottomWidth: size / 2, 15 | borderLeftWidth: size / 2, 16 | marginLeft: x, 17 | marginTop: y 18 | } 19 | ] 20 | }); 21 | 22 | const styles = StyleSheet.create({ 23 | root: { 24 | position: 'absolute', 25 | cursor: 'pointer', 26 | width: 0, 27 | height: 0, 28 | borderColor: 'transparent', 29 | borderStyle: 'solid', 30 | borderTopWidth: 0, 31 | transform: [{ translateX: '50%' }, { translateY: '50%' }] 32 | } 33 | }); 34 | 35 | export default Dot; 36 | -------------------------------------------------------------------------------- /packages/benchmarks/src/implementations/react-native-web/Provider.js: -------------------------------------------------------------------------------- 1 | import { View } from 'react-native'; 2 | export default View; 3 | -------------------------------------------------------------------------------- /packages/benchmarks/src/implementations/react-native-web/index.js: -------------------------------------------------------------------------------- 1 | import Box from './Box'; 2 | import Dot from './Dot'; 3 | import Provider from './Provider'; 4 | import { View } from 'react-native'; 5 | 6 | export default { 7 | Box, 8 | Dot, 9 | Provider, 10 | View 11 | }; 12 | -------------------------------------------------------------------------------- /packages/benchmarks/src/implementations/styleq/Box.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import View from './View'; 3 | 4 | const Box = ({ 5 | color, 6 | fixed = false, 7 | layout = 'column', 8 | outer = false, 9 | ...other 10 | }) => ( 11 | 20 | ); 21 | 22 | const styles = { 23 | outer: { 24 | $$css: true, 25 | alignSelf: 'r-k200y', 26 | padding: 'r-tuq35u' 27 | }, 28 | row: { 29 | $$css: true, 30 | flexDirection: 'r-18u37iz' 31 | }, 32 | color0: { 33 | $$css: true, 34 | backgroundColor: 'r-1810x6o' 35 | }, 36 | color1: { 37 | $$css: true, 38 | backgroundColor: 'r-dkge59' 39 | }, 40 | color2: { 41 | $$css: true, 42 | backgroundColor: 'r-18z3xeu' 43 | }, 44 | color3: { 45 | $$css: true, 46 | backgroundColor: 'r-1vkxrha' 47 | }, 48 | color4: { 49 | $$css: true, 50 | backgroundColor: 'r-1dgebii' 51 | }, 52 | color5: { 53 | $$css: true, 54 | backgroundColor: 'r-e84r5y' 55 | }, 56 | fixed: { 57 | $$css: true, 58 | width: 'r-8hc5te', 59 | height: 'r-1xbve24' 60 | } 61 | }; 62 | 63 | export default Box; 64 | -------------------------------------------------------------------------------- /packages/benchmarks/src/implementations/styleq/Dot.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { styleq } from 'styleq'; 3 | 4 | const Dot = ({ size, x, y, children, color }) => { 5 | const [className, inlineStyle] = styleq([ 6 | styles.root, 7 | { 8 | borderBottomColor: color, 9 | borderRightWidth: size / 2, 10 | borderBottomWidth: size / 2, 11 | borderLeftWidth: size / 2, 12 | marginLeft: x, 13 | marginTop: y 14 | } 15 | ]); 16 | 17 | return
; 18 | }; 19 | 20 | const styles = { 21 | root: { 22 | $$css: true, 23 | 'css-1co75s2': 'css-1co75s2' 24 | } 25 | }; 26 | 27 | export default Dot; 28 | -------------------------------------------------------------------------------- /packages/benchmarks/src/implementations/styleq/Provider.js: -------------------------------------------------------------------------------- 1 | import View from './View'; 2 | export default View; 3 | -------------------------------------------------------------------------------- /packages/benchmarks/src/implementations/styleq/View.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { styleq } from 'styleq'; 3 | 4 | const q = styleq.factory({ disableCache: false }); 5 | 6 | function View(props) { 7 | const [className, inlineStyle] = q([styles.root, props.style]); 8 | return
; 9 | } 10 | 11 | const styles = { 12 | root: { 13 | $$css: true, 14 | 'css-g5y9jx': 'css-g5y9jx' 15 | } 16 | }; 17 | 18 | export default View; 19 | -------------------------------------------------------------------------------- /packages/benchmarks/src/implementations/styleq/index.js: -------------------------------------------------------------------------------- 1 | import Box from './Box'; 2 | import Dot from './Dot'; 3 | import Provider from './Provider'; 4 | import View from './View'; 5 | 6 | export default { 7 | Box, 8 | Dot, 9 | Provider, 10 | View 11 | }; 12 | -------------------------------------------------------------------------------- /packages/benchmarks/src/implementations/stylesheet/Box.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import View from './View'; 3 | import { StyleSheet } from 'react-native-web'; 4 | 5 | const Box = ({ 6 | color, 7 | fixed = false, 8 | layout = 'column', 9 | outer = false, 10 | ...other 11 | }) => ( 12 | 21 | ); 22 | 23 | const styles = StyleSheet.create({ 24 | outer: { 25 | alignSelf: 'flex-start', 26 | padding: 4 27 | }, 28 | row: { 29 | flexDirection: 'row' 30 | }, 31 | color0: { 32 | backgroundColor: '#14171A' 33 | }, 34 | color1: { 35 | backgroundColor: '#AAB8C2' 36 | }, 37 | color2: { 38 | backgroundColor: '#E6ECF0' 39 | }, 40 | color3: { 41 | backgroundColor: '#FFAD1F' 42 | }, 43 | color4: { 44 | backgroundColor: '#F45D22' 45 | }, 46 | color5: { 47 | backgroundColor: '#E0245E' 48 | }, 49 | fixed: { 50 | width: 6, 51 | height: 6 52 | } 53 | }); 54 | 55 | export default Box; 56 | -------------------------------------------------------------------------------- /packages/benchmarks/src/implementations/stylesheet/Dot.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { StyleSheet } from 'react-native-web'; 3 | 4 | const Dot = ({ size, x, y, children, color }) => { 5 | const [className, inlineStyle] = StyleSheet([ 6 | styles.root$raw, 7 | { 8 | borderBottomColor: color, 9 | borderRightWidth: size / 2, 10 | borderBottomWidth: size / 2, 11 | borderLeftWidth: size / 2, 12 | marginLeft: x, 13 | marginTop: y 14 | } 15 | ]); 16 | 17 | return
; 18 | }; 19 | 20 | const styles = StyleSheet.create({ 21 | root$raw: { 22 | position: 'absolute', 23 | cursor: 'pointer', 24 | width: 0, 25 | height: 0, 26 | borderColor: 'transparent', 27 | borderStyle: 'solid', 28 | borderTopWidth: 0, 29 | transform: 'translateX(50%) translateY(50%)' 30 | } 31 | }); 32 | 33 | export default Dot; 34 | -------------------------------------------------------------------------------- /packages/benchmarks/src/implementations/stylesheet/Provider.js: -------------------------------------------------------------------------------- 1 | import View from './View'; 2 | export default View; 3 | -------------------------------------------------------------------------------- /packages/benchmarks/src/implementations/stylesheet/View.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { StyleSheet } from 'react-native-web'; 3 | 4 | function View(props) { 5 | const [className, inlineStyle] = StyleSheet([styles.root$raw, props.style]); 6 | return
; 7 | } 8 | 9 | const styles = StyleSheet.create({ 10 | root$raw: { 11 | alignItems: 'stretch', 12 | backgroundColor: 'transparent', 13 | border: '0 solid black', 14 | boxSizing: 'border-box', 15 | display: 'flex', 16 | flexBasis: 'auto', 17 | flexDirection: 'column', 18 | flexShrink: 0, 19 | listStyle: 'none', 20 | margin: 0, 21 | minHeight: 0, 22 | minWidth: 0, 23 | padding: 0, 24 | position: 'relative', 25 | zIndex: 0 26 | } 27 | }); 28 | 29 | export default View; 30 | -------------------------------------------------------------------------------- /packages/benchmarks/src/implementations/stylesheet/index.js: -------------------------------------------------------------------------------- 1 | import Box from './Box'; 2 | import Dot from './Dot'; 3 | import Provider from './Provider'; 4 | import View from './View'; 5 | 6 | export default { 7 | Box, 8 | Dot, 9 | Provider, 10 | View 11 | }; 12 | -------------------------------------------------------------------------------- /packages/benchmarks/webpack.config.js: -------------------------------------------------------------------------------- 1 | const BundleAnalyzerPlugin = 2 | require('webpack-bundle-analyzer').BundleAnalyzerPlugin; 3 | const path = require('path'); 4 | 5 | const appDirectory = path.resolve(__dirname); 6 | 7 | module.exports = { 8 | mode: 'production', 9 | context: __dirname, 10 | entry: './src/index', 11 | output: { 12 | path: path.resolve(appDirectory, 'dist'), 13 | filename: 'bundle.js' 14 | }, 15 | optimization: { 16 | minimize: process.env.NODE_ENV === 'production' 17 | }, 18 | module: { 19 | rules: [ 20 | { 21 | test: /\.css$/, 22 | use: [ 23 | 'style-loader', 24 | { 25 | loader: 'css-loader', 26 | options: { 27 | modules: { 28 | localIdentName: '[hash:base64:8]' 29 | } 30 | } 31 | } 32 | ] 33 | }, 34 | { 35 | test: /\.js$/, 36 | include: [path.resolve(appDirectory, 'src')], 37 | use: { 38 | loader: 'babel-loader', 39 | options: { 40 | cacheDirectory: false, 41 | extends: path.resolve(appDirectory, '../../configs/babel.config') 42 | } 43 | } 44 | } 45 | ] 46 | }, 47 | plugins: [ 48 | new BundleAnalyzerPlugin({ 49 | analyzerMode: 'static', 50 | openAnalyzer: false 51 | }) 52 | ], 53 | resolve: { 54 | alias: { 55 | 'react-native': 'react-native-web' 56 | } 57 | } 58 | }; 59 | -------------------------------------------------------------------------------- /packages/dom-event-testing-library/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Nicolas Gallagher. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/dom-event-testing-library/index.js: -------------------------------------------------------------------------------- 1 | export * from './src/index'; 2 | -------------------------------------------------------------------------------- /packages/dom-event-testing-library/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "name": "dom-event-testing-library", 4 | "version": "0.0.0", 5 | "main": "index.js", 6 | "description": "Browser event sequences for unit tests", 7 | "author": "Nicolas Gallagher", 8 | "license": "MIT", 9 | "homepage": "https://github.com/necolas/react-native-web/tree/master/packages/dom-event-testing-library" 10 | } 11 | -------------------------------------------------------------------------------- /packages/dom-event-testing-library/src/__tests__/__snapshots__/index-test.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`describeWithPointerEvent: MouseEvent/TouchEvent provides boolean to tests 1`] = `false`; 4 | 5 | exports[`describeWithPointerEvent: MouseEvent/TouchEvent testWithPointerType: mouse 1`] = `"mouse"`; 6 | 7 | exports[`describeWithPointerEvent: MouseEvent/TouchEvent testWithPointerType: touch 1`] = `"touch"`; 8 | 9 | exports[`describeWithPointerEvent: PointerEvent provides boolean to tests 1`] = `true`; 10 | 11 | exports[`describeWithPointerEvent: PointerEvent testWithPointerType: mouse 1`] = `"mouse"`; 12 | 13 | exports[`describeWithPointerEvent: PointerEvent testWithPointerType: pen 1`] = `"pen"`; 14 | 15 | exports[`describeWithPointerEvent: PointerEvent testWithPointerType: touch 1`] = `"touch"`; 16 | -------------------------------------------------------------------------------- /packages/dom-event-testing-library/src/constants.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Nicolas Gallagher. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | 'use strict'; 9 | 10 | export const defaultPointerId = 1; 11 | export const defaultPointerSize = 23; 12 | export const defaultBrowserChromeSize = 50; 13 | 14 | /** 15 | * Button property 16 | * This property only guarantees to indicate which buttons are pressed during events caused by pressing or 17 | * releasing one or multiple buttons. As such, it is not reliable for events such as 'mouseenter', 'mouseleave', 18 | * 'mouseover', 'mouseout' or 'mousemove'. Furthermore, the semantics differ for PointerEvent, where the value 19 | * for 'pointermove' will always be -1. 20 | */ 21 | 22 | export const buttonType = { 23 | // no change since last event 24 | none: -1, 25 | // left-mouse 26 | // touch contact 27 | // pen contact 28 | primary: 0, 29 | // right-mouse 30 | // pen barrel button 31 | secondary: 2, 32 | // middle mouse 33 | auxiliary: 1, 34 | // back mouse 35 | back: 3, 36 | // forward mouse 37 | forward: 4, 38 | // pen eraser 39 | eraser: 5 40 | }; 41 | 42 | /** 43 | * Buttons bitmask 44 | */ 45 | 46 | export const buttonsType = { 47 | none: 0, 48 | // left-mouse 49 | // touch contact 50 | // pen contact 51 | primary: 1, 52 | // right-mouse 53 | // pen barrel button 54 | secondary: 2, 55 | // middle mouse 56 | auxiliary: 4, 57 | // back mouse 58 | back: 8, 59 | // forward mouse 60 | forward: 16, 61 | // pen eraser 62 | eraser: 32 63 | }; 64 | -------------------------------------------------------------------------------- /packages/dom-event-testing-library/src/testHelpers.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Nicolas Gallagher. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | 'use strict'; 9 | 10 | import { hasPointerEvent, setPointerEvent } from './domEnvironment'; 11 | 12 | export function describeWithPointerEvent(message, describeFn) { 13 | const pointerEvent = 'PointerEvent'; 14 | const fallback = 'MouseEvent/TouchEvent'; 15 | describe.each` 16 | value | name 17 | ${true} | ${pointerEvent} 18 | ${false} | ${fallback} 19 | `(`${message}: $name`, (entry) => { 20 | const hasPointerEvents = entry.value; 21 | setPointerEvent(hasPointerEvents); 22 | describeFn(hasPointerEvents); 23 | }); 24 | } 25 | 26 | export function testWithPointerType(message, testFn) { 27 | const table = hasPointerEvent() 28 | ? ['mouse', 'touch', 'pen'] 29 | : ['mouse', 'touch']; 30 | test.each(table)(`${message}: %s`, (pointerType) => { 31 | testFn(pointerType); 32 | }); 33 | } 34 | -------------------------------------------------------------------------------- /packages/react-native-web-docs/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Nicolas Gallagher. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/react-native-web-docs/README.md: -------------------------------------------------------------------------------- 1 | # React Native for Web documentation 2 | 3 | Markdown pages and a static site generator. 4 | -------------------------------------------------------------------------------- /packages/react-native-web-docs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "name": "react-native-web-docs", 4 | "version": "0.20.0", 5 | "description": "Documentation website for React Native for Web", 6 | "scripts": { 7 | "dev": "eleventy --serve", 8 | "build": "ELEVENTY_PRODUCTION=true eleventy", 9 | "debug": "DEBUG=* eleventy" 10 | }, 11 | "homepage": "https://github.com/necolas/react-native-web", 12 | "devDependencies": { 13 | "@11ty/eleventy": "^1.0.1", 14 | "@11ty/eleventy-navigation": "^0.3.3", 15 | "@11ty/eleventy-plugin-syntaxhighlight": "^4.1.0", 16 | "csso": "^5.0.3", 17 | "eleventy-plugin-svg-contents": "^0.7.0", 18 | "eleventy-plugin-toc": "^1.1.5", 19 | "html-minifier": "^4.0.0", 20 | "markdown-it": "^13.0.1", 21 | "markdown-it-anchor": "^8.6.4", 22 | "markdown-it-attrs": "^4.1.4", 23 | "markdown-it-container": "^3.0.0", 24 | "markdown-it-emoji": "^2.0.2", 25 | "markdown-it-footnote": "^3.0.3", 26 | "markdown-it-for-inline": "^0.1.1", 27 | "markdown-it-task-lists": "^2.1.1", 28 | "uglify-es": "^3.3.9" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /packages/react-native-web-docs/src/data/site.js: -------------------------------------------------------------------------------- 1 | const packageJson = require('../../package.json'); 2 | 3 | module.exports = { 4 | name: 'React Native for Web', 5 | description: '', 6 | footer: 'Copyright © Nicolas Gallagher and Meta Platforms, Inc.', 7 | url: 'https://necolas.github.io/react-native-web', 8 | githubUrl: 'https://github.com/necolas/react-native-web', 9 | githubBranch: 'master', 10 | packageName: 'react-native-web', 11 | packageUrl: 'https://www.npmjs.com/package/react-native-web', 12 | packageVersion: packageJson.version, 13 | 14 | enableEditButton: true, 15 | enableGithubLink: true 16 | }; 17 | -------------------------------------------------------------------------------- /packages/react-native-web-docs/src/includes/assets/svg/close.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/react-native-web-docs/src/includes/assets/svg/documents.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /packages/react-native-web-docs/src/includes/assets/svg/github.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /packages/react-native-web-docs/src/includes/fragments/footer.html: -------------------------------------------------------------------------------- 1 |
2 | {% if site.enableGithubLink == 1 %} 3 | 4 | {{ '/src/includes/assets/svg/github.svg' | svgContents("w-full") | safe }} 5 | 6 | {% endif %} 7 | 8 |
9 | {{ site.name }} – 10 | {% if site.footer %} 11 | {{ site.footer | safe }} 12 | {% endif %} 13 |
14 |
15 | -------------------------------------------------------------------------------- /packages/react-native-web-docs/src/includes/layouts/404.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: layouts/shell.html 3 | section: page 4 | --- 5 | 6 |
7 |

{{ title }}

8 |
9 | {{ '/src/includes/assets/svg/404.svg' | svgContents("w-full") | safe }} 10 |
11 |
12 | -------------------------------------------------------------------------------- /packages/react-native-web-docs/src/includes/layouts/shell.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | {%- set htmltitle -%} 7 | {%- if page.fileSlug === 'home' -%} 8 | {{- renderData.title or title -}} 9 | {%- else -%} 10 | {{- renderData.title or title }} // {{ site.name -}} 11 | {%- endif -%} 12 | {%- endset -%} 13 | {{ htmltitle }} 14 | 15 | 16 | 17 | {% set cssinline %} 18 | {% include "assets/inline.css" %} 19 | {% endset %} 20 | 21 | 22 | 23 | {% set jsinline %} 24 | {% include "assets/inline.js" %} 25 | {% endset %} 26 | 27 | 28 | 29 | 30 |
31 |
32 | {{ layoutContent | safe }} 33 |
34 |
35 | -------------------------------------------------------------------------------- /packages/react-native-web-docs/src/pages/404.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 404 3 | permalink: /404.html 4 | layout: layouts/404.html 5 | --- 6 | -------------------------------------------------------------------------------- /packages/react-native-web-docs/src/pages/docs/apis/_.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: APIs 3 | date: Last Modified 4 | permalink: false 5 | eleventyNavigation: 6 | key: APIs 7 | title: APIs 8 | order: 30 9 | --- 10 | -------------------------------------------------------------------------------- /packages/react-native-web-docs/src/pages/docs/apis/animated.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Animated 3 | date: Last Modified 4 | permalink: /docs/animated/index.html 5 | eleventyNavigation: 6 | key: Animated 7 | parent: APIs 8 | --- 9 | 10 | :::lead 11 | Animated focuses on declarative relationships between inputs and outputs, configurable transforms in between, and start/stop methods to control time-based animation execution. 12 | ::: 13 | 14 | This API is the same JavaScript implementation as found in React Native. Please refer to the React Native documentation below: 15 | 16 | * [Animated](https://reactnative.dev/docs/animated) 17 | 18 | :::callout 19 | **Warning!** The React Native animation API is not optimized for the web. You may prefer to use external modules that are designed for multi-platform animations and provide better performance, e.g., [React Spring](https://www.react-spring.io/). 20 | ::: 21 | -------------------------------------------------------------------------------- /packages/react-native-web-docs/src/pages/docs/apis/app-state.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: AppState 3 | date: Last Modified 4 | permalink: /docs/app-state/index.html 5 | eleventyNavigation: 6 | key: AppState 7 | parent: APIs 8 | --- 9 | 10 | {% import "fragments/macros.html" as macro with context %} 11 | 12 | :::lead 13 | AppState can tell you if the app is in the foreground or background, and notify you when the state changes. 14 | ::: 15 | 16 | States: active (the app is running in the foreground), background (the app is running in the background, i.e., the user has not focused the app's tab). 17 | 18 | 19 | ```js 20 | import { AppState } from 'react-native'; 21 | ``` 22 | 23 | --- 24 | 25 | ## API 26 | 27 | ### Static properties 28 | 29 | {% call macro.prop('isAvailable', 'boolean') %} 30 | Whether the browser environment supports `AppState`. 31 | {% endcall %} 32 | 33 | {% call macro.prop('currentState', '?("active" | "background")') %} 34 | Returns the current state of the app. 35 | {% endcall %} 36 | 37 | ### Static methods 38 | 39 | {% call macro.prop('addEventListener', '(type: ?string, listener: (boolean) => void) => ?EmitterSubscription') %} 40 | Add a listener to `AppState` changes. Listen to the `"change"` event type. The handler is called with the app state value. 41 | {% endcall %} 42 | 43 | --- 44 | 45 | ## Examples 46 | 47 | {{ macro.codesandbox('app-state') }} 48 | -------------------------------------------------------------------------------- /packages/react-native-web-docs/src/pages/docs/apis/appearance.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Appearance 3 | date: Last Modified 4 | permalink: /docs/appearance/index.html 5 | eleventyNavigation: 6 | key: Appearance 7 | parent: APIs 8 | --- 9 | 10 | {% import "fragments/macros.html" as macro with context %} 11 | 12 | :::lead 13 | The Appearance module exposes information about the user's appearance preferences, such as their preferred color scheme (light or dark). 14 | ::: 15 | 16 | ```js 17 | import { Appearance } from 'react-native'; 18 | ``` 19 | 20 | --- 21 | 22 | ## API 23 | 24 | ### Static methods 25 | 26 | {% call macro.prop('addChangeListener', '(listener) => { remove: () => void }') %} 27 | Add an event handler that is called with `{colorScheme: "dark" | "light"}` when appearance preferences change. Returns a `remove` method used to remove the change listener. 28 | {% endcall %} 29 | 30 | {% call macro.prop('getColorScheme', '() => ("dark" | "light")') %} 31 | You can use the Appearance module to determine if the user prefers a dark color scheme. Although the color scheme is available immediately, this may change (e.g. scheduled color scheme change at sunrise or sunset). Any rendering logic or styles that depend on the user preferred color scheme should try to call this function on every render, rather than caching the value. 32 | {% endcall %} 33 | -------------------------------------------------------------------------------- /packages/react-native-web-docs/src/pages/docs/apis/clipboard.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Clipboard 3 | date: Last Modified 4 | permalink: /docs/clipboard/index.html 5 | eleventyNavigation: 6 | key: Clipboard 7 | parent: APIs 8 | --- 9 | 10 | {% import "fragments/macros.html" as macro with context %} 11 | 12 | :::lead 13 | Clipboard gives you an interface for setting to the clipboard. (Getting clipboard content is not currently supported on web.) 14 | ::: 15 | 16 | ```js 17 | import { Clipboard } from 'react-native'; 18 | ``` 19 | 20 | --- 21 | 22 | ## API 23 | 24 | ### Static methods 25 | 26 | {% call macro.prop('isAvailable', '() => boolean') %} 27 | Determines whether the browser environment supports Clipboard at all. 28 | {% endcall %} 29 | 30 | {% call macro.prop('setString', '() => boolean') %} 31 | Copies a string to the clipboard. On web, some browsers may not support copying to the clipboard, therefore, this function returns a boolean to indicate if the copy was successful. 32 | {% endcall %} 33 | 34 | {% call macro.prop('getString', '() => Promise<"">') %} 35 | Not properly supported on Web. Returns a Promise of an empty string. 36 | {% endcall %} 37 | 38 | --- 39 | 40 | ## Examples 41 | 42 | {{ macro.codesandbox('clipboard') }} 43 | -------------------------------------------------------------------------------- /packages/react-native-web-docs/src/pages/docs/apis/linking.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Linking 3 | date: Last Modified 4 | permalink: /docs/linking/index.html 5 | eleventyNavigation: 6 | key: Linking 7 | parent: APIs 8 | --- 9 | 10 | {% import "fragments/macros.html" as macro with context %} 11 | 12 | :::lead 13 | Linking gives you a general interface for securely opening external URLs from JavaScript. 14 | ::: 15 | 16 | ```js 17 | import { Linking } from 'react-native'; 18 | ``` 19 | 20 | --- 21 | 22 | ## API 23 | 24 | ### Static methods 25 | 26 | {% call macro.prop('canOpenURL', '(url) => Promise') %} 27 | Returns a `Promise` that resolves to a boolean indicating whether the app can open the URL. 28 | {% endcall %} 29 | 30 | {% call macro.prop('getInitialURL', '() => Promise') %} 31 | Returns a `Promise` that resolves to the string of the URL that initially loaded the app. 32 | {% endcall %} 33 | 34 | {% call macro.prop('openURL', '(url, target) => Promise<>') %} 35 | Try to open the given url in a secure fashion. The provided target (including `undefined`) will be passed as the window target, or "_blank" if no target included. The method returns a Promise object. If the url opens, the promise is resolved. If not, the promise is rejected. 36 | {% endcall %} 37 | 38 | --- 39 | 40 | ## Examples 41 | 42 | {{ macro.codesandbox('linking') }} 43 | -------------------------------------------------------------------------------- /packages/react-native-web-docs/src/pages/docs/apis/pan-responder.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: PanResponder 3 | date: Last Modified 4 | permalink: /docs/pan-responder/index.html 5 | eleventyNavigation: 6 | key: PanResponder 7 | parent: APIs 8 | --- 9 | 10 | {% import "fragments/macros.html" as macro with context %} 11 | 12 | :::lead 13 | PanResponder reconciles several pointers into a single gesture. It makes single-pointer gestures resilient to extra touches, and can be used to recognize basic multi-touch gestures. 14 | ::: 15 | 16 | :::callout 17 | **Note:** Using the `PanResponder` on components that contain text may cause native text selection events to interrupt the pan gesture. This can be avoided by setting `userSelect: 'none'` on the text elements while the gesture is active. 18 | ::: 19 | 20 | Please refer to the React Native documentation below: 21 | 22 | * [PanResponder](https://reactnative.dev/docs/panresponder) 23 | 24 | --- 25 | 26 | ## Examples 27 | 28 | {{ macro.codesandbox('pan-responder') }} 29 | -------------------------------------------------------------------------------- /packages/react-native-web-docs/src/pages/docs/apis/pixel-ratio.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: PixelRatio 3 | date: Last Modified 4 | permalink: /docs/pixel-ratio/index.html 5 | eleventyNavigation: 6 | key: PixelRatio 7 | parent: APIs 8 | --- 9 | 10 | {% import "fragments/macros.html" as macro with context %} 11 | 12 | :::lead 13 | `PixelRatio` class gives access to the device pixel density. 14 | ::: 15 | 16 | ```js 17 | import { PixelRatio } from 'react-native'; 18 | ``` 19 | 20 | --- 21 | 22 | ## API 23 | 24 | ### Static methods 25 | 26 | {% call macro.prop('get', '() => number') %} 27 | Returns the device pixel density as a number. 28 | {% endcall %} 29 | 30 | {% call macro.prop('getFontScale', '() => number') %} 31 | On web this returns the device pixel ratio as a number. 32 | {% endcall %} 33 | 34 | {% call macro.prop('getPixelSizeForLayoutSize', '(number) => number') %} 35 | Converts a layout size (dp) to pixel size (px). Guaranteed to return an integer number. 36 | {% endcall %} 37 | 38 | {% call macro.prop('roundToNearestPixel', '(number) => number') %} 39 | Rounds a layout size (dp) to the nearest layout size that corresponds to an integer number of pixels. For example, on a device with a PixelRatio of 3, `PixelRatio.roundToNearestPixel(8.4) = 8.33`, which corresponds to exactly (8.33 * 3) = 25 pixels. 40 | {% endcall %} 41 | -------------------------------------------------------------------------------- /packages/react-native-web-docs/src/pages/docs/apis/platform.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Platform 3 | date: Last Modified 4 | permalink: /docs/platform/index.html 5 | eleventyNavigation: 6 | key: Platform 7 | parent: APIs 8 | --- 9 | 10 | {% import "fragments/macros.html" as macro with context %} 11 | 12 | :::lead 13 | Detect what is the platform in which the app is running. 14 | ::: 15 | 16 | This piece of functionality can be useful when only small parts of a component are platform specific. 17 | 18 | ```js 19 | import { Platform } from 'react-native'; 20 | ``` 21 | 22 | --- 23 | 24 | ## API 25 | 26 | ### Static properties 27 | 28 | {% call macro.prop('OS', '"web"') %} 29 | This value will be `"web"` when running in a Web browser. 30 | {% endcall %} 31 | 32 | ### Static methods 33 | 34 | {% call macro.prop('select', '(config) => any') %} 35 | Takes an object containing `Platform.OS` values as keys and returns the value for the platform you are currently running on. 36 | {% endcall %} 37 | -------------------------------------------------------------------------------- /packages/react-native-web-docs/src/pages/docs/apis/vibration.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Vibration 3 | date: Last Modified 4 | permalink: /docs/vibration/index.html 5 | eleventyNavigation: 6 | key: Vibration 7 | parent: APIs 8 | --- 9 | 10 | {% import "fragments/macros.html" as macro with context %} 11 | 12 | :::lead 13 | Vibration is described as a pattern of on-off pulses, which may be of varying lengths. 14 | ::: 15 | 16 | The vibration pattern may consist of either a single integer, describing the number of milliseconds to vibrate, or an array of integers describing a pattern of vibrations and pauses. Vibration is controlled with a single method: `Vibration.vibrate()`. 17 | 18 | ```js 19 | import { Vibration } from 'react-native'; 20 | ``` 21 | 22 | --- 23 | 24 | ## API 25 | 26 | ### Static methods 27 | 28 | {% call macro.prop('cancel', '() => void') %} 29 | Stop the vibration 30 | {% endcall %} 31 | 32 | {% call macro.prop('vibrate', '(number | Array) => void') %} 33 | Start the vibration pattern 34 | {% endcall %} 35 | -------------------------------------------------------------------------------- /packages/react-native-web-docs/src/pages/docs/appendix/_.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Appendix 3 | date: Last Modified 4 | permalink: false 5 | eleventyNavigation: 6 | key: Appendix 7 | title: Appendix 8 | order: 90 9 | --- 10 | -------------------------------------------------------------------------------- /packages/react-native-web-docs/src/pages/docs/components/_.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Components 3 | date: Last Modified 4 | permalink: false 5 | eleventyNavigation: 6 | key: Components 7 | title: Components 8 | order: 20 9 | --- 10 | -------------------------------------------------------------------------------- /packages/react-native-web-docs/src/pages/docs/components/activity-indicator.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: ActivityIndicator 3 | date: Last Modified 4 | permalink: /docs/activity-indicator/index.html 5 | eleventyNavigation: 6 | key: ActivityIndicator 7 | parent: Components 8 | --- 9 | 10 | {% import "fragments/macros.html" as macro with context %} 11 | 12 | :::lead 13 | Displays a customizable activity indicator. 14 | ::: 15 | 16 | ```jsx 17 | import { ActivityIndicator } from 'react-native'; 18 | 19 | ; 20 | ``` 21 | 22 | --- 23 | 24 | ## API 25 | 26 | ### Props 27 | 28 | {% call macro.prop('...ViewProps', '?ViewProps') %} 29 | All the props supported by [View]({{ '/docs/view' | url }}). 30 | {% endcall %} 31 | 32 | {% call macro.prop('animating', '?boolean') %} 33 | Default `true`. Set whether the activity indicator is animating. 34 | {% endcall %} 35 | 36 | {% call macro.prop('color', '?string') %} 37 | Default `"#1976D2"`. Set the color of the activity indicator. 38 | {% endcall %} 39 | 40 | {% call macro.prop('hidesWhenStopped', '?boolean') %} 41 | Default `true`. Set whether the activity indicator is hidden when not animating. 42 | {% endcall %} 43 | 44 | {% call macro.prop('size', '?("small" | "large" | number)') %} 45 | Default `"small"`. Set the size of the activity indicator. 46 | {% endcall %} 47 | 48 | --- 49 | 50 | ## Examples 51 | 52 | {{ macro.codesandbox('activity-indicator') }} 53 | -------------------------------------------------------------------------------- /packages/react-native-web-docs/src/pages/docs/components/image-background.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: ImageBackground 3 | date: Last Modified 4 | permalink: /docs/image-background/index.html 5 | eleventyNavigation: 6 | key: ImageBackground 7 | parent: Components 8 | --- 9 | 10 | {% import "fragments/macros.html" as macro with context %} 11 | 12 | :::lead 13 | An image component with support for child content. 14 | ::: 15 | 16 | ```jsx 17 | import { ImageBackground } from 'react-native'; 18 | 19 | {children}; 20 | ``` 21 | 22 | --- 23 | 24 | ## API 25 | 26 | ### Props 27 | 28 | {% call macro.prop('...ImageProps', '?ImageProps') %} 29 | All the props supported by [Image]({{ '/docs/image' | url }}). 30 | {% endcall %} 31 | 32 | {% call macro.prop('children', '?any') %} 33 | Content to display over the image. 34 | {% endcall %} 35 | 36 | {% call macro.prop('imageStyle', '?Style') %} 37 | Styles to forward to the image component. 38 | {% endcall %} 39 | 40 | ## Examples 41 | 42 | {{ macro.codesandbox('image-background') }} 43 | -------------------------------------------------------------------------------- /packages/react-native-web-docs/src/pages/docs/components/lists.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Lists 3 | date: Last Modified 4 | permalink: /docs/lists/index.html 5 | eleventyNavigation: 6 | key: Lists 7 | parent: Components 8 | --- 9 | 10 | {% import "fragments/macros.html" as macro with context %} 11 | 12 | :::lead 13 | Basic support for FlatList, SectionList, and VirtualizedList. 14 | ::: 15 | 16 | These components are the same JavaScript implementations as those found in React Native. Please refer to the React Native documentation below: 17 | 18 | * [FlatList](https://reactnative.dev/docs/flatlist) 19 | * [SectionList](https://reactnative.dev/docs/sectionlist) 20 | * [VirtualizedList](https://reactnative.dev/docs/virtualizedlist) 21 | 22 | :::callout 23 | **Warning!** The React Native list components are not optimized for the web. You may prefer to use external modules that are designed for multi-platform lists and provide better performance, e.g., [RecyclerListView](https://github.com/Flipkart/recyclerlistview). 24 | ::: 25 | 26 | --- 27 | 28 | ## Examples 29 | 30 | {{ macro.codesandbox('lists') }} 31 | -------------------------------------------------------------------------------- /packages/react-native-web-docs/src/pages/docs/components/progress-bar.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: ProgressBar 3 | date: Last Modified 4 | permalink: /docs/progress-bar/index.html 5 | eleventyNavigation: 6 | key: ProgressBar 7 | parent: Components 8 | --- 9 | 10 | {% import "fragments/macros.html" as macro with context %} 11 | 12 | :::lead 13 | Display an activity progress bar. 14 | ::: 15 | 16 | ```jsx 17 | import { ProgressBar } from 'react-native'; 18 | 19 | ; 20 | ``` 21 | 22 | --- 23 | 24 | ## API 25 | 26 | ### Props 27 | 28 | {% call macro.prop('...ViewProps', '?ViewProps') %} 29 | All the props supported by [View]({{ '/docs/view' | url }}). 30 | {% endcall %} 31 | 32 | {% call macro.prop('color', '?string = "#1976D2"') %} 33 | Set the background color of the button. 34 | {% endcall %} 35 | 36 | {% call macro.prop('indeterminate', '?boolean = false') %} 37 | Whether the progress bar will show indeterminate progress. 38 | {% endcall %} 39 | 40 | {% call macro.prop('progress', '?number = 0') %} 41 | The progress value between `0` and `1`. 42 | {% endcall %} 43 | 44 | {% call macro.prop('trackColor', '?string = "transparent"') %} 45 | Customize the color of the track bar. 46 | {% endcall %} 47 | 48 | --- 49 | 50 | ## Examples 51 | 52 | Custom sizes can be created using style properties. 53 | 54 | {{ macro.codesandbox('progress-bar') }} 55 | -------------------------------------------------------------------------------- /packages/react-native-web-docs/src/pages/docs/concepts/_.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Main concepts 3 | date: Last Modified 4 | permalink: false 5 | eleventyNavigation: 6 | key: Concepts 7 | title: Main concepts 8 | order: 10 9 | --- 10 | -------------------------------------------------------------------------------- /packages/react-native-web-docs/src/pages/docs/getting-started/_.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Getting started 3 | date: Last Modified 4 | permalink: false 5 | eleventyNavigation: 6 | key: Start 7 | title: Getting started 8 | order: 0 9 | --- 10 | -------------------------------------------------------------------------------- /packages/react-native-web-docs/src/pages/docs/getting-started/help.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Help 3 | date: Last Modified 4 | permalink: /docs/help/index.html 5 | description: 6 | eleventyNavigation: 7 | key: Help 8 | parent: Start 9 | order: 7 10 | --- 11 | 12 | :::lead 13 | Questions? Looking for help? These are the best places to look first. 14 | ::: 15 | 16 | ## Discussions 17 | 18 | [{{ site.name }} Discussions on GitHub]({{ site.githubUrl }}/discussions) is the place for general questions, discussions, and ideas. 19 | 20 | ## Issues 21 | 22 | [{{ site.name }} Issues on GitHub]({{ site.githubUrl }}/issues) is the place for reporting and resolving issues with {{ site.name }}. 23 | -------------------------------------------------------------------------------- /packages/react-native-web-docs/src/pages/docs/getting-started/installation.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Installation 3 | date: Last Modified 4 | permalink: /docs/installation/index.html 5 | eleventyNavigation: 6 | key: Installation 7 | parent: Start 8 | order: 1 9 | --- 10 | 11 | :::lead 12 | An overview of how to install and use {{ site.name }}. 13 | ::: 14 | 15 | React Native for Web can be used for multi-platform and web-only applications. It can be incrementally adopted by existing React Web apps and integrated with existing React Native apps. Preact is also supported. 16 | 17 | ```shell 18 | npm install react-dom {{ site.packageName }} 19 | ``` 20 | 21 | The Babel plugin is recommended for build-time optimizations. 22 | 23 | ```shell 24 | npm install --save-dev babel-plugin-react-native-web 25 | ``` 26 | 27 | --- 28 | 29 | ## Quickstart 30 | 31 | ### Expo 32 | 33 | [Expo](https://expo.dev) is a framework and a platform for universal React applications. [Expo for Web](https://docs.expo.dev/workflow/web/) uses React Native for Web, provides dozens of additional cross-platform APIs, includes web build optimizations, and is compatible with the broader React Native ecosystem. See the Expo docs for more information. 34 | 35 | ### Create React App 36 | 37 | [Create React App](https://github.com/facebook/create-react-app) is a basic way to setup a simple, web-only React app with built-in support for aliasing `react-native-web` to `react-native`. However, it's generally recommended that you use Expo. 38 | 39 | ```shell 40 | npx create-react-app my-app 41 | cd my-app 42 | npm install react-native-web 43 | npm start 44 | ``` 45 | -------------------------------------------------------------------------------- /packages/react-native-web-docs/src/pages/docs/hooks/_.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Hooks 3 | date: Last Modified 4 | permalink: false 5 | eleventyNavigation: 6 | key: Hooks 7 | title: Hooks 8 | order: 40 9 | --- 10 | -------------------------------------------------------------------------------- /packages/react-native-web-docs/src/pages/docs/hooks/use-color-scheme.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: useColorScheme 3 | date: Last Modified 4 | permalink: /docs/use-color-scheme/index.html 5 | eleventyNavigation: 6 | key: useColorScheme 7 | parent: Hooks 8 | --- 9 | 10 | {% import "fragments/macros.html" as macro with context %} 11 | 12 | :::lead 13 | Respond to color scheme updates from the `Appearance` module. 14 | ::: 15 | 16 | The return value indicates the current user preferred color scheme. The value may be updated later, either through direct user action (e.g., theme selection in device settings) or on a schedule (e.g., light and dark themes that follow the day/night cycle). 17 | 18 | ```js 19 | import { useColorScheme } from 'react-native'; 20 | const colorScheme = useColorScheme(); 21 | ``` 22 | 23 | --- 24 | 25 | ## API 26 | 27 | ### Return value 28 | 29 | `useColorScheme` returns the color scheme value. 30 | 31 | {% call macro.prop('colorScheme', '"dark" | "light" | null') %} 32 | A string representing the color scheme. 33 | {% endcall %} 34 | -------------------------------------------------------------------------------- /packages/react-native-web-docs/src/pages/docs/hooks/use-locale-context.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: useLocaleContext 3 | date: Last Modified 4 | permalink: /docs/use-locale-context/index.html 5 | eleventyNavigation: 6 | key: useLocaleContext 7 | parent: Hooks 8 | --- 9 | 10 | {% import "fragments/macros.html" as macro with context %} 11 | 12 | :::lead 13 | Respond to locale and writing direction changes from ancestors. 14 | ::: 15 | 16 | The return value matches the current locale and writing direction of the ancestral tree. The value will be updated for descendants when setting the `dir` or `lang` prop on an element. 17 | 18 | ```js 19 | import { useLocaleContext } from 'react-native'; 20 | const { direction, locale } = useLocaleContext(); 21 | ``` 22 | 23 | --- 24 | 25 | ## API 26 | 27 | ### Return value 28 | 29 | `useLocaleContext` returns the locale context. 30 | 31 | {% call macro.prop('direction', '"ltr" | "rtl"') %} 32 | A string representing the writing direction context. 33 | {% endcall %} 34 | 35 | {% call macro.prop('locale', '?string') %} 36 | The locale context. Locale is `null` if a new direction context is set without an associated locale. 37 | {% endcall %} 38 | -------------------------------------------------------------------------------- /packages/react-native-web-docs/src/pages/docs/hooks/use-window-dimensions.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: useWindowDimensions 3 | date: Last Modified 4 | permalink: /docs/use-window-dimensions/index.html 5 | eleventyNavigation: 6 | key: useWindowDimensions 7 | parent: Hooks 8 | --- 9 | 10 | {% import "fragments/macros.html" as macro with context %} 11 | 12 | :::lead 13 | Respond to window size changes from the `Dimensions` module. 14 | ::: 15 | 16 | `useWindowDimensions` automatically updates `width` and `height` values when viewport size changes. 17 | 18 | ```js 19 | import { useWindowDimensions } from 'react-native'; 20 | const { height, scale, width } = useWindowDimensions(); 21 | ``` 22 | 23 | --- 24 | 25 | ## API 26 | 27 | ### Return value 28 | 29 | `useWindowDimensions` returns the `window` dimension object. 30 | 31 | {% call macro.prop('height', 'number') %} 32 | The height in pixels of the app viewport. 33 | {% endcall %} 34 | 35 | {% call macro.prop('scale', 'number') %} 36 | The pixel ratio of the device your app is running on. 37 | {% endcall %} 38 | 39 | {% call macro.prop('width', 'number') %} 40 | The width in pixels of the app viewport. 41 | {% endcall %} 42 | -------------------------------------------------------------------------------- /packages/react-native-web-docs/src/pages/home.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: React Native for Web 3 | date: Last Modified 4 | permalink: / 5 | layout: layouts/home.html 6 | --- 7 | -------------------------------------------------------------------------------- /packages/react-native-web-docs/src/pages/pages.json: -------------------------------------------------------------------------------- 1 | { 2 | "layout": "layouts/page.html" 3 | } 4 | -------------------------------------------------------------------------------- /packages/react-native-web-examples/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "next/babel", 4 | "@babel/preset-flow" 5 | ], 6 | "plugins": [ 7 | [ "react-native-web", { "commonjs": true } ] 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /packages/react-native-web-examples/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Nicolas Gallagher. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/react-native-web-examples/README.md: -------------------------------------------------------------------------------- 1 | # React Native for Web examples 2 | 3 | Next.js pages and React Native components. Provides interactive examples for the documentation website. 4 | -------------------------------------------------------------------------------- /packages/react-native-web-examples/next.config.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | 4 | const pages = fs 5 | .readdirSync(path.resolve(__dirname, 'pages'), { withFileTypes: true }) 6 | .filter((dirent) => dirent.isDirectory()) 7 | .map((dirent) => dirent.name); 8 | 9 | module.exports = { 10 | env: { pages }, 11 | webpack: (config, options) => { 12 | config.resolve.alias['react-native'] = 'react-native-web'; 13 | return config; 14 | } 15 | }; 16 | -------------------------------------------------------------------------------- /packages/react-native-web-examples/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "name": "react-native-web-examples", 4 | "version": "0.20.0", 5 | "scripts": { 6 | "build": "next build", 7 | "dev": "next", 8 | "start": "next start" 9 | }, 10 | "dependencies": { 11 | "babel-plugin-react-native-web": "0.20.0", 12 | "next": "^12.2.0", 13 | "react": "^18.0.0", 14 | "react-dom": "^18.0.0", 15 | "react-native-web": "0.20.0" 16 | }, 17 | "devDependencies": { 18 | "@babel/core": "^7.18.6", 19 | "@babel/preset-flow": "^7.18.6" 20 | }, 21 | "license": "MIT" 22 | } 23 | -------------------------------------------------------------------------------- /packages/react-native-web-examples/pages/_document.js: -------------------------------------------------------------------------------- 1 | import Document, { Html, Head, Main, NextScript } from 'next/document'; 2 | import { AppRegistry } from 'react-native'; 3 | 4 | export default class MyDocument extends Document { 5 | static async getInitialProps(ctx) { 6 | const { renderPage } = ctx; 7 | AppRegistry.registerComponent('rn', () => Main); 8 | const { getStyleElement } = AppRegistry.getApplication('rn'); 9 | const page = await renderPage(); 10 | const styles = getStyleElement(); 11 | return { ...page, styles }; 12 | } 13 | 14 | render() { 15 | return ( 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | ); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /packages/react-native-web-examples/pages/animated/index.js: -------------------------------------------------------------------------------- 1 | import React, { useRef } from 'react'; 2 | import { Animated, Pressable, StyleSheet, Text, View } from 'react-native'; 3 | import Example from '../../shared/example'; 4 | 5 | export default function AnimatedPage() { 6 | const anim = useRef(new Animated.Value(0)); 7 | 8 | const animateBox = () => { 9 | Animated.timing(anim.current, { 10 | toValue: 1, 11 | duration: 1000, 12 | useNativeDriver: false 13 | }).start(); 14 | }; 15 | 16 | const transform = anim.current.interpolate({ 17 | inputRange: [0, 1], 18 | outputRange: ['rotate(0deg)', 'rotate(45deg)'] 19 | }); 20 | 21 | return ( 22 | 23 | 24 | 25 | [ 28 | styles.button, 29 | { opacity: pressed ? 0.4 : 1 } 30 | ]} 31 | > 32 | Animate Box 33 | 34 | 35 | 36 | ); 37 | } 38 | 39 | const styles = StyleSheet.create({ 40 | container: { 41 | flex: 1, 42 | justifyContent: 'center', 43 | alignItems: 'center' 44 | }, 45 | animatedBox: { 46 | width: 100, 47 | height: 100, 48 | backgroundColor: 'red', 49 | alignSelf: 'center' 50 | }, 51 | button: { 52 | padding: 16, 53 | paddingVertical: 8, 54 | backgroundColor: 'blue', 55 | borderRadius: 8, 56 | marginTop: 24 57 | }, 58 | buttonText: { color: 'white' } 59 | }); 60 | -------------------------------------------------------------------------------- /packages/react-native-web-examples/pages/app-registry/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { AppRegistry, Text, StyleSheet } from 'react-native'; 3 | import Example from '../../shared/example'; 4 | 5 | function App() { 6 | return Should be red and bold; 7 | } 8 | 9 | const styles = StyleSheet.create({ 10 | text: { 11 | color: 'red', 12 | fontWeight: 'bold' 13 | } 14 | }); 15 | 16 | AppRegistry.registerComponent('App', () => App); 17 | 18 | export default function AppStatePage() { 19 | const iframeRef = React.useRef(null); 20 | const shadowRef = React.useRef(null); 21 | 22 | React.useEffect(() => { 23 | const iframeElement = iframeRef.current; 24 | const iframeBody = iframeElement.contentWindow.document.body; 25 | const iframeRootTag = document.createElement('div'); 26 | iframeRootTag.id = 'iframe-root'; 27 | iframeBody.appendChild(iframeRootTag); 28 | const app1 = AppRegistry.runApplication('App', { rootTag: iframeRootTag }); 29 | 30 | const shadowElement = shadowRef.current; 31 | const shadowRoot = shadowElement.attachShadow({ mode: 'open' }); 32 | const shadowRootTag = document.createElement('div'); 33 | shadowRootTag.id = 'shadow-root'; 34 | shadowRoot.appendChild(shadowRootTag); 35 | const app2 = AppRegistry.runApplication('App', { rootTag: shadowRootTag }); 36 | 37 | return () => { 38 | app1.unmount(); 39 | app2.unmount(); 40 | }; 41 | }, []); 42 | 43 | return ( 44 | 45 | Styles in iframe 46 |